Various components fixes

This commit is contained in:
Mo Bitar
2018-01-27 09:40:48 -06:00
parent c33c45278f
commit 61843b1472
10 changed files with 85 additions and 46 deletions

View File

@@ -497,14 +497,18 @@ angular.module('app')
} }
this.toggleStackComponentForCurrentItem = function(component) { this.toggleStackComponentForCurrentItem = function(component) {
if(component.active) { if(component.hidden) {
// Unhide, associate with current item
component.hidden = false;
if(!component.active) {
componentManager.activateComponent(component);
}
this.associateComponentWithCurrentNote(component);
componentManager.contextItemDidChangeInArea("editor-stack");
} else {
// not hidden, hide
component.hidden = true; component.hidden = true;
this.disassociateComponentWithCurrentNote(component); this.disassociateComponentWithCurrentNote(component);
} else {
// Inactive
componentManager.activateComponent(component);
componentManager.contextItemDidChangeInArea("editor-stack");
this.associateComponentWithCurrentNote(component);
} }
} }

View File

@@ -50,9 +50,17 @@ class Item {
if(json.content) { if(json.content) {
this.mapContentToLocalProperties(this.contentObject); this.mapContentToLocalProperties(this.contentObject);
} else if(json.deleted == true) {
this.handleDeletedContent();
} }
} }
/* Allows the item to handle the case where the item is deleted and the content is null */
handleDeletedContent() {
// Subclasses can override
}
setDirty(dirty) { setDirty(dirty) {
this.dirty = dirty; this.dirty = dirty;

View File

@@ -38,6 +38,10 @@ class Component extends Item {
this.area = content.area; this.area = content.area;
this.permissions = content.permissions; this.permissions = content.permissions;
if(!this.permissions) {
this.permissions = [];
}
this.active = content.active; this.active = content.active;
// custom data that a component can store in itself // custom data that a component can store in itself
@@ -50,6 +54,12 @@ class Component extends Item {
this.associatedItemIds = content.associatedItemIds || []; this.associatedItemIds = content.associatedItemIds || [];
} }
handleDeletedContent() {
super.handleDeletedContent();
this.active = false;
}
structureParams() { structureParams() {
var params = { var params = {
url: this.url, url: this.url,

View File

@@ -193,7 +193,8 @@ class ComponentManager {
} }
sendMessageToComponent(component, message) { sendMessageToComponent(component, message) {
if(component.hidden && message.action !== "component-registered") { let permissibleActionsWhileHidden = ["component-registered", "themes"];
if(component.hidden && !permissibleActionsWhileHidden.includes(message.action)) {
if(this.loggingEnabled) { if(this.loggingEnabled) {
console.log("Component disabled for current item, not sending any messages.", component.name); console.log("Component disabled for current item, not sending any messages.", component.name);
} }
@@ -471,11 +472,15 @@ class ComponentManager {
]; ];
this.runWithPermissions(component, requiredPermissions, () => { this.runWithPermissions(component, requiredPermissions, () => {
var items = message.data.items; var itemsData = message.data.items;
var noun = items.length == 1 ? "item" : "items"; var noun = itemsData.length == 1 ? "item" : "items";
if(confirm(`Are you sure you want to delete ${items.length} ${noun}?`)) { if(confirm(`Are you sure you want to delete ${itemsData.length} ${noun}?`)) {
for(var item of items) { // Filter for any components and deactivate before deleting
var model = this.modelManager.findItem(item.uuid); for(var itemData of itemsData) {
var model = this.modelManager.findItem(itemData.uuid);
if(["SN|Component", "SN|Theme"].includes(model.content_type)) {
this.deactivateComponent(model, true);
}
this.modelManager.setItemToBeDeleted(model); this.modelManager.setItemToBeDeleted(model);
} }
@@ -598,10 +603,14 @@ class ComponentManager {
return false; return false;
} }
if(approved && pendingDialog.component == component) { if(pendingDialog.component == component) {
// remove pending dialogs that are encapsulated by already approved permissions, and run its function // remove pending dialogs that are encapsulated by already approved permissions, and run its function
if(pendingDialog.permissions == permissions || permissions.containsObjectSubset(pendingDialog.permissions)) { if(pendingDialog.permissions == permissions || permissions.containsObjectSubset(pendingDialog.permissions)) {
pendingDialog.actionBlock && pendingDialog.actionBlock(approved); // If approved, run the action block. Otherwise, if canceled, cancel any pending ones as well, since the user was
// explicit in their intentions
if(approved) {
pendingDialog.actionBlock && pendingDialog.actionBlock(approved);
}
return false; return false;
} }
} }
@@ -641,30 +650,6 @@ class ComponentManager {
angular.element(document.body).append(el); angular.element(document.body).append(el);
} }
activateComponent(component) {
var didChange = component.active != true;
component.active = true;
for(var handler of this.handlers) {
if(handler.areas.includes(component.area) || handler.areas.includes("*")) {
handler.activationHandler(component);
}
}
if(didChange) {
component.setDirty(true);
this.syncManager.sync("activateComponent");
}
if(!this.activeComponents.includes(component)) {
this.activeComponents.push(component);
}
if(component.area == "themes") {
this.postThemeToAllComponents();
}
}
registerHandler(handler) { registerHandler(handler) {
this.handlers.push(handler); this.handlers.push(handler);
} }
@@ -699,7 +684,31 @@ class ComponentManager {
this.postThemeToComponent(component); this.postThemeToComponent(component);
} }
deactivateComponent(component) { activateComponent(component, dontSync = false) {
var didChange = component.active != true;
component.active = true;
for(var handler of this.handlers) {
if(handler.areas.includes(component.area) || handler.areas.includes("*")) {
handler.activationHandler(component);
}
}
if(didChange && !dontSync) {
component.setDirty(true);
this.syncManager.sync("activateComponent");
}
if(!this.activeComponents.includes(component)) {
this.activeComponents.push(component);
}
if(component.area == "themes") {
this.postThemeToAllComponents();
}
}
deactivateComponent(component, dontSync = false) {
var didChange = component.active != false; var didChange = component.active != false;
component.active = false; component.active = false;
component.sessionKey = null; component.sessionKey = null;
@@ -710,7 +719,7 @@ class ComponentManager {
} }
} }
if(didChange) { if(didChange && !dontSync) {
component.setDirty(true); component.setDirty(true);
this.syncManager.sync("deactivateComponent"); this.syncManager.sync("deactivateComponent");
} }

View File

@@ -51,12 +51,18 @@ class DesktopManager {
desktop_onComponentInstallationComplete(componentData, error) { desktop_onComponentInstallationComplete(componentData, error) {
console.log("Web|Component Installation/Update Complete", componentData, error); console.log("Web|Component Installation/Update Complete", componentData, error);
// Desktop is only allowed to change these keys:
let permissableKeys = ["package_info", "local_url"];
var component = this.modelManager.findItem(componentData.uuid); var component = this.modelManager.findItem(componentData.uuid);
if(error) { if(error) {
component = this.modelManager.findItem(componentData.uuid);
component.setAppDataItem("installError", error); component.setAppDataItem("installError", error);
} else { } else {
component = this.modelManager.mapResponseItemsToLocalModels([componentData], ModelManager.MappingSourceDesktopInstalled)[0]; for(var key of permissableKeys) {
component[key] = componentData.content[key];
}
this.modelManager.notifySyncObserversOfModels([component], ModelManager.MappingSourceDesktopInstalled);
component.setAppDataItem("installError", null); component.setAppDataItem("installError", null);
} }
component.setDirty(true); component.setDirty(true);

View File

@@ -119,8 +119,6 @@ class ModelManager {
mapResponseItemsToLocalModelsOmittingFields(items, omitFields, source) { mapResponseItemsToLocalModelsOmittingFields(items, omitFields, source) {
var models = [], processedObjects = [], modelsToNotifyObserversOf = []; var models = [], processedObjects = [], modelsToNotifyObserversOf = [];
// console.log("mapResponseItemsToLocalModelsOmittingFields");
// first loop should add and process items // first loop should add and process items
for (var json_obj of items) { for (var json_obj of items) {
if((!json_obj.content_type || !json_obj.content) && !json_obj.deleted && !json_obj.errorDecrypting) { if((!json_obj.content_type || !json_obj.content) && !json_obj.deleted && !json_obj.errorDecrypting) {
@@ -176,6 +174,7 @@ class ModelManager {
return models; return models;
} }
/* Note that this function is public, and can also be called manually (desktopManager uses it) */
notifySyncObserversOfModels(models, source) { notifySyncObserversOfModels(models, source) {
for(var observer of this.itemSyncObservers) { for(var observer of this.itemSyncObservers) {
var allRelevantItems = models.filter(function(item){return item.content_type == observer.type || observer.type == "*"}); var allRelevantItems = models.filter(function(item){return item.content_type == observer.type || observer.type == "*"});

View File

@@ -291,6 +291,7 @@ class SyncManager {
response.retrieved_items = response.retrieved_items.filter((candidate) => {return !allSavedUUIDs.includes(candidate.uuid)}); response.retrieved_items = response.retrieved_items.filter((candidate) => {return !allSavedUUIDs.includes(candidate.uuid)});
// Map retrieved items to local data // Map retrieved items to local data
// Note that deleted items will not be returned
var retrieved var retrieved
= this.handleItemsResponse(response.retrieved_items, null, ModelManager.MappingSourceRemoteRetrieved); = this.handleItemsResponse(response.retrieved_items, null, ModelManager.MappingSourceRemoteRetrieved);

View File

@@ -117,9 +117,9 @@ $heading-height: 75px;
width: 100%; width: 100%;
.component-stack-item { .component-stack-item {
// height: 50px;
width: 100%; width: 100%;
position: relative; position: relative;
&:not(:last-child) { &:not(:last-child) {
border-bottom: 1px solid $bg-color; border-bottom: 1px solid $bg-color;
} }

View File

@@ -53,4 +53,4 @@
%p.medium-padding{"style" => "padding-top: 0 !important;"} There was an error decrypting this item. Ensure you are running the latest version of this app, then sign out and sign back in to try again. %p.medium-padding{"style" => "padding-top: 0 !important;"} There was an error decrypting this item. Ensure you are running the latest version of this app, then sign out and sign back in to try again.
#editor-pane-component-stack #editor-pane-component-stack
%component-view.component-view.component-stack-item{"ng-repeat" => "component in ctrl.componentStack", "ng-if" => "component.active", "ng-show" => "!component.hidden", "manual-dealloc" => "true", "component" => "component"} %component-view.component-view.component-stack-item.border-color{"ng-repeat" => "component in ctrl.componentStack", "ng-if" => "component.active", "ng-show" => "!component.hidden", "manual-dealloc" => "true", "component" => "component"}

View File

@@ -1,6 +1,8 @@
.section.tags#tags-column .section.tags#tags-column
.component-view-container{"ng-if" => "ctrl.component.active"} .component-view-container{"ng-if" => "ctrl.component.active"}
%component-view.component-view{"component" => "ctrl.component"} %component-view.component-view{"component" => "ctrl.component"}
#tags-content.content{"ng-if" => "!(ctrl.component && ctrl.component.active)"} #tags-content.content{"ng-if" => "!(ctrl.component && ctrl.component.active)"}
#tags-title-bar.section-title-bar #tags-title-bar.section-title-bar
.section-title-bar-header .section-title-bar-header