From d9b20c03a8098735f31a531e44fe2e74f043dcd7 Mon Sep 17 00:00:00 2001 From: Mo Bitar Date: Thu, 9 Nov 2017 20:57:16 -0600 Subject: [PATCH] Component clientData --- .../app/frontend/models/api/item.js | 18 +++++--- .../app/services/componentManager.js | 44 ++++++++++++++++--- 2 files changed, 51 insertions(+), 11 deletions(-) diff --git a/app/assets/javascripts/app/frontend/models/api/item.js b/app/assets/javascripts/app/frontend/models/api/item.js index af65d5aa3..1c3dcff1d 100644 --- a/app/assets/javascripts/app/frontend/models/api/item.js +++ b/app/assets/javascripts/app/frontend/models/api/item.js @@ -151,17 +151,17 @@ class Item { App Data */ - setAppDataItem(key, value) { - var data = this.appData[AppDomain]; + setDomainDataItem(key, value, domain) { + var data = this.appData[domain]; if(!data) { data = {} } data[key] = value; - this.appData[AppDomain] = data; + this.appData[domain] = data; } - getAppDataItem(key) { - var data = this.appData[AppDomain]; + getDomainDataItem(key, domain) { + var data = this.appData[domain]; if(data) { return data[key]; } else { @@ -169,6 +169,14 @@ class Item { } } + setAppDataItem(key, value) { + this.setDomainDataItem(key, value, AppDomain); + } + + getAppDataItem(key) { + return this.getDomainDataItem(key, AppDomain); + } + get pinned() { return this.getAppDataItem("pinned"); } diff --git a/app/assets/javascripts/app/services/componentManager.js b/app/assets/javascripts/app/services/componentManager.js index b1692592d..da97f6231 100644 --- a/app/assets/javascripts/app/services/componentManager.js +++ b/app/assets/javascripts/app/services/componentManager.js @@ -1,5 +1,8 @@ class ComponentManager { + /* This domain will be used to save context item client data */ + let ClientDataDomain = "org.standardnotes.sn.components"; + constructor($rootScope, modelManager, syncManager, themeManager, $timeout, $compile) { this.$compile = $compile; this.$rootScope = $rootScope; @@ -115,9 +118,11 @@ class ComponentManager { } } - jsonForItem(item) { + jsonForItem(item, component) { var params = {uuid: item.uuid, content_type: item.content_type, created_at: item.created_at, updated_at: item.updated_at, deleted: item.deleted}; params.content = item.createContentJSONFromProperties(); + params.clientData = item.getDomainDataItem(component.url, ClientDataDomain); + this.removePrivatePropertiesFromResponseItems([params]); return params; } @@ -125,7 +130,7 @@ class ComponentManager { if(this.loggingEnabled) {console.log("Web|componentManager|sendItemsInReply", component, items, message)}; var response = {items: {}}; var mapped = items.map(function(item) { - return this.jsonForItem(item); + return this.jsonForItem(item, component); }.bind(this)); response.items = mapped; @@ -134,7 +139,7 @@ class ComponentManager { sendContextItemInReply(component, item, originalMessage) { if(this.loggingEnabled) {console.log("Web|componentManager|sendContextItemInReply", component, item, originalMessage)}; - var response = {item: this.jsonForItem(item)}; + var response = {item: this.jsonForItem(item, component)}; this.replyToMessage(component, originalMessage, response); } @@ -180,6 +185,8 @@ class ComponentManager { create-item delete-items set-component-data + save-context-client-data + get-context-client-data */ if(message.action === "stream-items") { @@ -210,17 +217,24 @@ class ComponentManager { } else if(message.action === "create-item") { - var item = this.modelManager.createItem(message.data.item); + var responseItem = message.data.item; + this.removePrivatePropertiesFromResponseItems([responseItem]); + var item = this.modelManager.createItem(responseItem); + if(responseItem.clientData) { + item.setDomainDataItem(component.url, responseItem.clientData, ClientDataDomain); + } this.modelManager.addItem(item); this.modelManager.resolveReferencesForItem(item); item.setDirty(true); this.syncManager.sync(); - this.replyToMessage(component, message, {item: this.jsonForItem(item)}) + this.replyToMessage(component, message, {item: this.jsonForItem(item, component)}) } else if(message.action === "save-items") { var responseItems = message.data.items; + this.removePrivatePropertiesFromResponseItems(responseItems); + /* We map the items here because modelManager is what updatese the UI. If you were to instead get the items directly, this would update them server side via sync, but would never make its way back to the UI. @@ -230,6 +244,9 @@ class ComponentManager { for(var item of localItems) { var responseItem = _.find(responseItems, {uuid: item.uuid}); _.merge(item.content, responseItem.content); + if(responseItem.clientData) { + item.setDomainDataItem(component.url, responseItem.clientData, ClientDataDomain); + } item.setDirty(true); } this.syncManager.sync((response) => { @@ -249,6 +266,21 @@ class ComponentManager { } } + removePrivatePropertiesFromResponseItems(responseItems) { + // Don't allow component to overwrite these properties. + let privateProperties = ["appData"]; + for(var responseItem of responseItems) { + + // Do not pass in actual items here, otherwise that would be destructive. + // Instead, generic JS/JSON objects should be passed. + console.assert(typeof responseItem.setDirty !== 'function'); + + for(var prop of privateProperties) { + delete responseItem[prop]; + } + } + } + handleStreamItemsMessage(component, message) { var requiredPermissions = [ { @@ -506,7 +538,7 @@ class ComponentManager { } component.disassociatedItemIds.push(item.uuid); - + component.setDirty(true); this.syncManager.sync(); }