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";
|
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);
|
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) {
|
controller($scope, modelManager) {
|
||||||
|
|
||||||
$scope.formattedPermissions = $scope.permissions.map(function(permission){
|
$scope.permissionsString = function() {
|
||||||
if(permission.name === "stream-items") {
|
var finalString = "";
|
||||||
var types = permission.content_types.map(function(type){
|
let permissionsCount = $scope.permissions.length;
|
||||||
var desc = modelManager.humanReadableDisplayForContentType(type);
|
|
||||||
if(desc) {
|
|
||||||
return desc + "s";
|
|
||||||
} else {
|
|
||||||
return "items of type " + type;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
var typesString = "";
|
|
||||||
var separator = ", ";
|
|
||||||
|
|
||||||
for(var i = 0;i < types.length;i++) {
|
let addSeparator = (index, length) => {
|
||||||
var type = types[i];
|
if(index > 0) {
|
||||||
if(i == 0) {
|
if(index == length - 1) {
|
||||||
// first element
|
if(length == 2) {
|
||||||
typesString = typesString + type;
|
return " and ";
|
||||||
} else if(i == types.length - 1) {
|
} else {
|
||||||
// last element
|
return ", and "
|
||||||
if(types.length > 2) {
|
|
||||||
typesString += separator + "and " + type;
|
|
||||||
} else if(types.length == 2) {
|
|
||||||
typesString = typesString + " and " + type;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
typesString += separator + type;
|
return ", ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return typesString;
|
return "";
|
||||||
} 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];
|
|
||||||
}
|
}
|
||||||
})
|
|
||||||
|
$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
|
get-context-client-data
|
||||||
install-local-component
|
install-local-component
|
||||||
toggle-activate-component
|
toggle-activate-component
|
||||||
|
request-permissions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if(message.action === "stream-items") {
|
if(message.action === "stream-items") {
|
||||||
@@ -252,6 +253,8 @@ class ComponentManager {
|
|||||||
} else if(message.action === "toggle-activate-component") {
|
} else if(message.action === "toggle-activate-component") {
|
||||||
let componentToToggle = this.modelManager.findItem(message.data.uuid);
|
let componentToToggle = this.modelManager.findItem(message.data.uuid);
|
||||||
this.handleToggleComponentMessage(component, componentToToggle, message);
|
this.handleToggleComponentMessage(component, componentToToggle, message);
|
||||||
|
} else if(message.action === "request-permissions") {
|
||||||
|
this.handleRequestPermissionsMessage(component, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify observers
|
// 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) {
|
handleSetComponentDataMessage(component, message) {
|
||||||
// A component setting its own data does not require special permissions
|
// A component setting its own data does not require special permissions
|
||||||
this.runWithPermissions(component, [], () => {
|
this.runWithPermissions(component, [], () => {
|
||||||
@@ -459,7 +468,6 @@ class ComponentManager {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
handleToggleComponentMessage(sourceComponent, targetComponent, message) {
|
handleToggleComponentMessage(sourceComponent, targetComponent, message) {
|
||||||
if(targetComponent.area == "modal") {
|
if(targetComponent.area == "modal") {
|
||||||
this.openModalComponent(targetComponent);
|
this.openModalComponent(targetComponent);
|
||||||
@@ -504,7 +512,7 @@ class ComponentManager {
|
|||||||
matching = acquiredPermissions.find((candidate) => {
|
matching = acquiredPermissions.find((candidate) => {
|
||||||
return Array.isArray(candidate.content_types)
|
return Array.isArray(candidate.content_types)
|
||||||
&& Array.isArray(required.content_types)
|
&& Array.isArray(required.content_types)
|
||||||
&& candidate.content_types.containsSubset(required.content_types);
|
&& candidate.content_types.containsPrimitiveSubset(required.content_types);
|
||||||
});
|
});
|
||||||
|
|
||||||
if(!matching) {
|
if(!matching) {
|
||||||
@@ -514,8 +522,6 @@ class ComponentManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// var acquiredMatchesRequested = angular.toJson(component.permissions.sort()) === angular.toJson(requestedPermissions.sort());
|
|
||||||
|
|
||||||
if(!acquiredMatchesRequired) {
|
if(!acquiredMatchesRequired) {
|
||||||
this.promptForPermissions(component, requiredPermissions, function(approved){
|
this.promptForPermissions(component, requiredPermissions, function(approved){
|
||||||
if(approved) {
|
if(approved) {
|
||||||
@@ -528,9 +534,6 @@ class ComponentManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
promptForPermissions(component, permissions, callback) {
|
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);
|
var scope = this.$rootScope.$new(true);
|
||||||
scope.component = component;
|
scope.component = component;
|
||||||
scope.permissions = permissions;
|
scope.permissions = permissions;
|
||||||
@@ -547,28 +550,47 @@ class ComponentManager {
|
|||||||
this.syncManager.sync();
|
this.syncManager.sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
for(var existing of this.permissionDialogs) {
|
this.permissionDialogs = this.permissionDialogs.filter((pendingDialog) => {
|
||||||
if(existing.component === component && existing.actionBlock) {
|
// Remove self
|
||||||
existing.actionBlock(approved);
|
if(pendingDialog == scope) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
if(approved && pendingDialog.component == component) {
|
||||||
|
// remove pending dialogs that are encapsulated by already approved permissions, and run its function
|
||||||
this.permissionDialogs = this.permissionDialogs.filter(function(dialog){
|
if(pendingDialog.permissions == permissions || permissions.containsObjectSubset(pendingDialog.permissions)) {
|
||||||
return dialog.component !== component;
|
pendingDialog.actionBlock && pendingDialog.actionBlock(approved);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if(this.permissionDialogs.length > 0) {
|
||||||
|
this.presentDialog(this.permissionDialogs[0]);
|
||||||
|
}
|
||||||
|
|
||||||
}.bind(this);
|
}.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);
|
this.permissionDialogs.push(scope);
|
||||||
|
|
||||||
if(!existingDialog) {
|
if(!existingDialog) {
|
||||||
var el = this.$compile( "<permissions-modal component='component' permissions='permissions' callback='callback' class='modal'></permissions-modal>" )(scope);
|
this.presentDialog(scope);
|
||||||
angular.element(document.body).append(el);
|
|
||||||
} else {
|
} else {
|
||||||
console.log("Existing dialog, not presenting.");
|
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) {
|
openModalComponent(component) {
|
||||||
var scope = this.$rootScope.$new(true);
|
var scope = this.$rootScope.$new(true);
|
||||||
scope.component = component;
|
scope.component = component;
|
||||||
|
|||||||
@@ -12,8 +12,7 @@
|
|||||||
%h3
|
%h3
|
||||||
%strong {{component.name}}
|
%strong {{component.name}}
|
||||||
would like to interact with your
|
would like to interact with your
|
||||||
%span{"ng-repeat" => "permission in formattedPermissions"}
|
{{permissionsString()}}
|
||||||
{{permission}}.
|
|
||||||
|
|
||||||
.panel-row
|
.panel-row
|
||||||
%p
|
%p
|
||||||
|
|||||||
Reference in New Issue
Block a user