Permissions formatting, dialog queue
This commit is contained in:
@@ -41,6 +41,12 @@ function isMacApplication() {
|
||||
return window && window.process && window.process.type && window.process.platform == "darwin";
|
||||
}
|
||||
|
||||
Array.prototype.containsSubset = function(array) {
|
||||
/* Use with numbers and strings, not objects */
|
||||
Array.prototype.containsPrimitiveSubset = function(array) {
|
||||
return !array.some(val => this.indexOf(val) === -1);
|
||||
}
|
||||
|
||||
/* Use with numbers and strings, not objects */
|
||||
Array.prototype.containsObjectSubset = function(array) {
|
||||
return !array.some(val => !_.find(this, val));
|
||||
}
|
||||
|
||||
@@ -30,46 +30,68 @@ class PermissionsModal {
|
||||
|
||||
controller($scope, modelManager) {
|
||||
|
||||
$scope.formattedPermissions = $scope.permissions.map(function(permission){
|
||||
if(permission.name === "stream-items") {
|
||||
var types = permission.content_types.map(function(type){
|
||||
var desc = modelManager.humanReadableDisplayForContentType(type);
|
||||
if(desc) {
|
||||
return desc + "s";
|
||||
} else {
|
||||
return "items of type " + type;
|
||||
}
|
||||
})
|
||||
var typesString = "";
|
||||
var separator = ", ";
|
||||
$scope.permissionsString = function() {
|
||||
var finalString = "";
|
||||
let permissionsCount = $scope.permissions.length;
|
||||
|
||||
for(var i = 0;i < types.length;i++) {
|
||||
var type = types[i];
|
||||
if(i == 0) {
|
||||
// first element
|
||||
typesString = typesString + type;
|
||||
} else if(i == types.length - 1) {
|
||||
// last element
|
||||
if(types.length > 2) {
|
||||
typesString += separator + "and " + type;
|
||||
} else if(types.length == 2) {
|
||||
typesString = typesString + " and " + type;
|
||||
let addSeparator = (index, length) => {
|
||||
if(index > 0) {
|
||||
if(index == length - 1) {
|
||||
if(length == 2) {
|
||||
return " and ";
|
||||
} else {
|
||||
return ", and "
|
||||
}
|
||||
} else {
|
||||
typesString += separator + type;
|
||||
return ", ";
|
||||
}
|
||||
}
|
||||
|
||||
return typesString;
|
||||
} else if(permission.name === "stream-context-item") {
|
||||
var mapping = {
|
||||
"editor-stack" : "working note",
|
||||
"note-tags" : "working note",
|
||||
"editor-editor": "working note"
|
||||
}
|
||||
return mapping[$scope.component.area];
|
||||
return "";
|
||||
}
|
||||
})
|
||||
|
||||
$scope.permissions.forEach((permission, index) => {
|
||||
|
||||
if(permission.name === "stream-items") {
|
||||
var types = permission.content_types.map(function(type){
|
||||
var desc = modelManager.humanReadableDisplayForContentType(type);
|
||||
if(desc) {
|
||||
return desc + "s";
|
||||
} else {
|
||||
return "items of type " + type;
|
||||
}
|
||||
})
|
||||
var typesString = "";
|
||||
|
||||
for(var i = 0;i < types.length;i++) {
|
||||
var type = types[i];
|
||||
typesString += addSeparator(i, types.length + permissionsCount - index - 1);
|
||||
typesString += type;
|
||||
}
|
||||
|
||||
finalString += addSeparator(index, permissionsCount);
|
||||
|
||||
finalString += typesString;
|
||||
|
||||
if(types.length >= 2 && index < permissionsCount - 1) {
|
||||
// If you have a list of types, and still an additional root-level permission coming up, add a comma
|
||||
finalString += ", ";
|
||||
}
|
||||
} else if(permission.name === "stream-context-item") {
|
||||
var mapping = {
|
||||
"editor-stack" : "working note",
|
||||
"note-tags" : "working note",
|
||||
"editor-editor": "working note"
|
||||
}
|
||||
|
||||
finalString += addSeparator(index, permissionsCount, true);
|
||||
|
||||
finalString += mapping[$scope.component.area];
|
||||
}
|
||||
})
|
||||
|
||||
return finalString + ".";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -235,6 +235,7 @@ class ComponentManager {
|
||||
get-context-client-data
|
||||
install-local-component
|
||||
toggle-activate-component
|
||||
request-permissions
|
||||
*/
|
||||
|
||||
if(message.action === "stream-items") {
|
||||
@@ -252,6 +253,8 @@ class ComponentManager {
|
||||
} else if(message.action === "toggle-activate-component") {
|
||||
let componentToToggle = this.modelManager.findItem(message.data.uuid);
|
||||
this.handleToggleComponentMessage(component, componentToToggle, message);
|
||||
} else if(message.action === "request-permissions") {
|
||||
this.handleRequestPermissionsMessage(component, message);
|
||||
}
|
||||
|
||||
// Notify observers
|
||||
@@ -450,6 +453,12 @@ class ComponentManager {
|
||||
});
|
||||
}
|
||||
|
||||
handleRequestPermissionsMessage(component, message) {
|
||||
this.runWithPermissions(component, message.data.permissions, () => {
|
||||
this.replyToMessage(component, message, {approved: true});
|
||||
});
|
||||
}
|
||||
|
||||
handleSetComponentDataMessage(component, message) {
|
||||
// A component setting its own data does not require special permissions
|
||||
this.runWithPermissions(component, [], () => {
|
||||
@@ -459,7 +468,6 @@ class ComponentManager {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
handleToggleComponentMessage(sourceComponent, targetComponent, message) {
|
||||
if(targetComponent.area == "modal") {
|
||||
this.openModalComponent(targetComponent);
|
||||
@@ -504,7 +512,7 @@ class ComponentManager {
|
||||
matching = acquiredPermissions.find((candidate) => {
|
||||
return Array.isArray(candidate.content_types)
|
||||
&& Array.isArray(required.content_types)
|
||||
&& candidate.content_types.containsSubset(required.content_types);
|
||||
&& candidate.content_types.containsPrimitiveSubset(required.content_types);
|
||||
});
|
||||
|
||||
if(!matching) {
|
||||
@@ -514,8 +522,6 @@ class ComponentManager {
|
||||
}
|
||||
}
|
||||
|
||||
// var acquiredMatchesRequested = angular.toJson(component.permissions.sort()) === angular.toJson(requestedPermissions.sort());
|
||||
|
||||
if(!acquiredMatchesRequired) {
|
||||
this.promptForPermissions(component, requiredPermissions, function(approved){
|
||||
if(approved) {
|
||||
@@ -528,9 +534,6 @@ class ComponentManager {
|
||||
}
|
||||
|
||||
promptForPermissions(component, permissions, callback) {
|
||||
// since these calls are asyncronous, multiple dialogs may be requested at the same time. We only want to present one and trigger all callbacks based on one modal result
|
||||
var existingDialog = _.find(this.permissionDialogs, {component: component});
|
||||
|
||||
var scope = this.$rootScope.$new(true);
|
||||
scope.component = component;
|
||||
scope.permissions = permissions;
|
||||
@@ -547,28 +550,47 @@ class ComponentManager {
|
||||
this.syncManager.sync();
|
||||
}
|
||||
|
||||
for(var existing of this.permissionDialogs) {
|
||||
if(existing.component === component && existing.actionBlock) {
|
||||
existing.actionBlock(approved);
|
||||
this.permissionDialogs = this.permissionDialogs.filter((pendingDialog) => {
|
||||
// Remove self
|
||||
if(pendingDialog == scope) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
this.permissionDialogs = this.permissionDialogs.filter(function(dialog){
|
||||
return dialog.component !== component;
|
||||
if(approved && pendingDialog.component == component) {
|
||||
// remove pending dialogs that are encapsulated by already approved permissions, and run its function
|
||||
if(pendingDialog.permissions == permissions || permissions.containsObjectSubset(pendingDialog.permissions)) {
|
||||
pendingDialog.actionBlock && pendingDialog.actionBlock(approved);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
})
|
||||
|
||||
if(this.permissionDialogs.length > 0) {
|
||||
this.presentDialog(this.permissionDialogs[0]);
|
||||
}
|
||||
|
||||
}.bind(this);
|
||||
|
||||
// since these calls are asyncronous, multiple dialogs may be requested at the same time. We only want to present one and trigger all callbacks based on one modal result
|
||||
var existingDialog = _.find(this.permissionDialogs, {component: component});
|
||||
|
||||
this.permissionDialogs.push(scope);
|
||||
|
||||
if(!existingDialog) {
|
||||
var el = this.$compile( "<permissions-modal component='component' permissions='permissions' callback='callback' class='modal'></permissions-modal>" )(scope);
|
||||
angular.element(document.body).append(el);
|
||||
this.presentDialog(scope);
|
||||
} else {
|
||||
console.log("Existing dialog, not presenting.");
|
||||
}
|
||||
}
|
||||
|
||||
presentDialog(dialog) {
|
||||
var permissions = dialog.permissions;
|
||||
var component = dialog.component;
|
||||
var callback = dialog.callback;
|
||||
var el = this.$compile( "<permissions-modal component='component' permissions='permissions' callback='callback' class='modal'></permissions-modal>" )(dialog);
|
||||
angular.element(document.body).append(el);
|
||||
}
|
||||
|
||||
openModalComponent(component) {
|
||||
var scope = this.$rootScope.$new(true);
|
||||
scope.component = component;
|
||||
|
||||
@@ -12,8 +12,7 @@
|
||||
%h3
|
||||
%strong {{component.name}}
|
||||
would like to interact with your
|
||||
%span{"ng-repeat" => "permission in formattedPermissions"}
|
||||
{{permission}}.
|
||||
{{permissionsString()}}
|
||||
|
||||
.panel-row
|
||||
%p
|
||||
|
||||
Reference in New Issue
Block a user