From afbea10a02ae86838625a7e8227fe2c86538cb80 Mon Sep 17 00:00:00 2001 From: Artur Arseniev Date: Thu, 26 May 2016 00:16:12 +0200 Subject: [PATCH] Refactor StorageManager --- src/editor/model/Editor.js | 84 ++++++++++++++++++++-- src/storage_manager/config/config.js | 3 + src/storage_manager/main.js | 64 +++++++++++++---- src/storage_manager/model/LocalStorage.js | 24 +++++-- src/storage_manager/model/RemoteStorage.js | 26 ++++--- test/specs/storage_manager/main.js | 33 +++++---- test/specs/storage_manager/model/Models.js | 57 +++++++++++---- 7 files changed, 232 insertions(+), 59 deletions(-) diff --git a/src/editor/model/Editor.js b/src/editor/model/Editor.js index c989fd27c..3ee72dde8 100644 --- a/src/editor/model/Editor.js +++ b/src/editor/model/Editor.js @@ -97,6 +97,7 @@ define([ cfg.sm = this; this.cssc = new CssComposer(cfg); + this.CssComposer = this.cssc; this.set('CssComposer', this.cssc); if(this.stm.isAutosave()) @@ -182,7 +183,7 @@ define([ cfg.em = this; this.cmp = new DomComponents(cfg); - + this.Components = this.cmp; if(this.stm.isAutosave()){ var md = this.cmp.getComponent(); this.updateComponents( md, null, { avoidStore : 1 }); @@ -227,9 +228,9 @@ define([ /** * Initialize storage * */ - initStorage: function() - { - this.stm = new StorageManager(this.config.storageManager); + initStorage: function() { + this.stm = new StorageManager(this.config.storageManager); + this.StorageManager = this.stm; this.stm.loadDefaultProviders().setCurrent(this.config.storageType); this.set('StorageManager', this.stm); }, @@ -272,6 +273,7 @@ define([ pfx = cfg.stylePrefix || 'cm-'; cfg.stylePrefix = this.config.stylePrefix + pfx; this.cm = new CodeManager(cfg); + this.CodeManager = this.cm; this.cm.loadDefaultGenerators().loadDefaultViewers(); this.set('CodeManager', this.cm); }, @@ -509,7 +511,79 @@ define([ if(!avSt) this.componentsUpdated(); - } + }, + + /** + * Store data to the current storage + */ + store: function(){ + var sm = this.StorageManager; + var cm = this.CodeManager; + var cmp = this.Components; + var cssc = this.CssComposer; + + if(!sm || !cm || !cmp) + return; + + var wrp = cmp.getComponent(); + var smConfig = sm.getConfig(); + var store = {}; + + if(wrp){ + if(smConfig.storeHtml) + store.html = cm.getCode(wrp, 'html'); + + if(smConfig.storeComponents) + store.components = JSON.stringify(cm.getCode(wrp, 'json')); + } + + if(cssc){ + if(smConfig.storeCss && wrp) + store.css = cm.getCode(wrp, 'css', cssc); + + if(smConfig.storeStyles) + store.styles = JSON.stringify(cssc.getRules()); + } + + sm.store(store); + }, + + /** + * Load data from the current storage + */ + load: function(){ + var sm = this.StorageManager; + var load = []; + + if(!sm) + return; + + var smConfig = sm.getConfig(); + + if(smConfig.storeHtml) + load.push('html'); + + if(smConfig.storeComponents) + load.push('components'); + + if(smConfig.storeCss) + load.push('css'); + + if(smConfig.storeStyles) + load.push('styles'); + + var result = sm.load(load); + + if(result.components){ + try{ + var comps = JSON.parse(result.components); + this.setComponents(comps); + }catch(err){} + }else if(result.html){ + this.setComponents(result.html); + } + + }, }); }); diff --git a/src/storage_manager/config/config.js b/src/storage_manager/config/config.js index 48e3b846a..3ea20bb34 100644 --- a/src/storage_manager/config/config.js +++ b/src/storage_manager/config/config.js @@ -1,6 +1,9 @@ define(function () { return { + // Prefix identifier that will be used inside storing and loading + id: 'gjs-', + // Enable/Disable autosaving autosave: 1, diff --git a/src/storage_manager/main.js b/src/storage_manager/main.js index bf02f8e3c..bcc45ec74 100644 --- a/src/storage_manager/main.js +++ b/src/storage_manager/main.js @@ -20,6 +20,8 @@ * * @module StorageManager * @param {Object} config Configurations + * @param {string} [config.id='gjs-'] The prefix for the fields, useful to differentiate storing/loading + * with multiple editors on the same page. For example, in local storage, the item of HTML will be saved like 'gjs-html' * @param {Boolean} [config.autosave=true] Indicates if autosave mode is enabled, works in conjunction with stepsBeforeSave * @param {number} [config.stepsBeforeSave=1] If autosave enabled, indicates how many steps/changes are necessary * before autosave is triggered @@ -100,11 +102,17 @@ define(function(require) { * @return {this} * @example * storageManager.add('local2', { - * load: function(item){ - * return localStorage.getItem(name); + * load: function(keys){ + * var res = {}; + * for (var i = 0, len = keys.length; i < len; i++){ + * var v = localStorage.getItem(keys[i]); + * if(v) res[keys[i]] = v; + * } + * return res; * }, - * store: function(item, value){ - * localStorage.setItem(item, value); + * store: function(data){ + * for(var key in data) + * localStorage.setItem(key, data[key]); * } * }); * */ @@ -149,24 +157,43 @@ define(function(require) { }, /** - * Store resource in the current storage - * @param {String} name Resource's name - * @param {String} value Resource's value + * Store key-value resources in the current storage + * @param {Object} data Data in key-value format, eg. {item1: value1, item2: value2} * @return {Object|null} + * @example + * storageManager.store({item1: value1, item2: value2}); * */ - store: function(name, value){ + store: function(data){ var st = this.get(this.getCurrent()); - return st ? st.store(name, value) : null; + var dataF = {}; + + for(var key in data) + dataF[c.id + key] = data[key]; + + return st ? st.store(dataF) : null; }, /** - * Load resource from the current storage - * @param {string} name Resource's name - * @return {Object|null} Loaded resource + * Load resource from the current storage by keys + * @param {string|Array} keys Keys to load + * @return {Object|null} Loaded resources + * @example + * var data = storageManager.load(['item1', 'item2']); + * // data -> {item1: value1, item2: value2} + * var data2 = storageManager.load('item1'); + * // data2 -> {item1: value1} * */ - load: function(name){ + load: function(keys){ var st = this.get(this.getCurrent()); - return st ? st.load(name) : null; + var keysF = []; + + if(typeof keys === 'string') + keys = [keys]; + + for (var i = 0, len = keys.length; i < len; i++) + keysF.push(c.id + keys[i]); + + return st ? st.load(keysF) : null; }, /** @@ -180,6 +207,15 @@ define(function(require) { return this; }, + /** + * Get configuration object + * @return {Object} + * @private + * */ + getConfig : function() { + return c; + }, + }; }; diff --git a/src/storage_manager/model/LocalStorage.js b/src/storage_manager/model/LocalStorage.js index d4b44ae09..dd0a51c11 100644 --- a/src/storage_manager/model/LocalStorage.js +++ b/src/storage_manager/model/LocalStorage.js @@ -8,21 +8,33 @@ define(['backbone'], }, /** @inheritdoc */ - store: function(name, value) { + store: function(data) { this.checkStorageEnvironment(); - localStorage.setItem(name, value); + + for(var key in data) + localStorage.setItem(key, data[key]); }, /** @inheritdoc */ - load: function(name){ + load: function(keys){ this.checkStorageEnvironment(); - return localStorage.getItem(name); + var result = {}; + + for (var i = 0, len = keys.length; i < len; i++){ + var value = localStorage.getItem(keys[i]); + if(value) + result[keys[i]] = value; + } + + return result; }, /** @inheritdoc */ - remove: function(name) { + remove: function(keys) { this.checkStorageEnvironment(); - localStorage.removeItem(name); + + for (var i = 0, len = keys.length; i < len; i++) + localStorage.removeItem(keys[i]); }, /** diff --git a/src/storage_manager/model/RemoteStorage.js b/src/storage_manager/model/RemoteStorage.js index e85ed19d5..b25225bb9 100644 --- a/src/storage_manager/model/RemoteStorage.js +++ b/src/storage_manager/model/RemoteStorage.js @@ -14,13 +14,15 @@ define(['backbone'], }, /** @inheritdoc */ - store: function(name, value) { - var fd = new FormData(), + store: function(data) { + var fd = {}, params = this.get('params'); - fd.append(name, value); + + for(var k in data) + fd[k] = data[k]; for(var key in params) - fd.append(key, params[key]); + fd[key] = params[key]; $.ajax({ url: this.get('urlStore'), @@ -34,17 +36,25 @@ define(['backbone'], }, /** @inheritdoc */ - load: function(name){ - var result = null; + load: function(keys){ + var result = {}, + fd = {}, + params = this.get('params'); + + for(var key in params) + fd[key] = params[key]; + + fd.keys = keys; + $.ajax({ url: this.get('urlLoad'), beforeSend: this.get('beforeSend'), complete: this.get('onComplete'), - data: this.get('paramsLoad'), + data: fd, async: false, type: 'GET', }).done(function(d){ - result = d.data ? d.data[name] : d[name]; + result = d; }); return result; }, diff --git a/test/specs/storage_manager/main.js b/test/specs/storage_manager/main.js index 1dd3d1f42..99578612e 100644 --- a/test/specs/storage_manager/main.js +++ b/test/specs/storage_manager/main.js @@ -64,11 +64,11 @@ define([ }); it('Store do not execute if empty', function() { - (obj.store('item','test') === null).should.equal(true); + (obj.store({item:'test'}) === null).should.equal(true); }); it('Load do not execute if empty', function() { - (obj.load('item') === null).should.equal(true); + (obj.load(['item']) === null).should.equal(true); }); it('Load default storages ', function() { @@ -83,11 +83,11 @@ define([ var storeValue; var storageId = 'testStorage'; var storage = { - store: function(n, v){ - storeValue[n] = v; + store: function(data){ + storeValue = data; }, - load: function(n){ - return storeValue[n]; + load: function(keys){ + return storeValue; }, }; @@ -104,14 +104,19 @@ define([ }); it('Store and load data', function() { - obj.store('item','testData'); - storeValue['item'].should.equal('testData'); - obj.load('item').should.equal('testData'); - }); - - it('Load inexistent data', function() { - obj.store('item','testData'); - (obj.load('item2') === undefined).should.equal(true); + var data = { + item: 'testData', + item2: 'testData2', + }; + var data2 = {}; + var id = obj.getConfig().id; + data2[id + 'item'] = 'testData'; + data2[id + 'item2'] = 'testData2'; + + obj.store(data); + var load = obj.load(['item', 'item2']); + storeValue.should.deep.equal(data2); + load.should.deep.equal(data2); }); }); diff --git a/test/specs/storage_manager/model/Models.js b/test/specs/storage_manager/model/Models.js index 855071a28..3b6aa072e 100644 --- a/test/specs/storage_manager/model/Models.js +++ b/test/specs/storage_manager/model/Models.js @@ -10,6 +10,10 @@ define([path + 'LocalStorage', var obj; var itemName = 'testItem'; + var data = { + 'item1': 'value1', + 'item2': 'value2', + }; beforeEach(function () { obj = new LocalStorage(); @@ -19,15 +23,29 @@ define([path + 'LocalStorage', delete obj; }); - it('Store and load item', function() { - obj.store(itemName, 'test'); - obj.load(itemName).should.equal('test'); + it('Store and load items', function() { + obj.store(data); + var result = obj.load(['item1', 'item2']); + result.should.deep.equal(data); }); - it('Remove item', function() { - obj.store(itemName, 'test'); - obj.remove(itemName); - (obj.load(itemName) === null).should.equal(true); + it('Store, update and load items', function() { + obj.store(data); + obj.store({item3: 'value3'}); + obj.store({item2: 'value22'}); + var result = obj.load(['item1', 'item2', 'item3']); + result.should.deep.equal({ + 'item1': 'value1', + 'item2': 'value22', + 'item3': 'value3', + }); + }); + + it('Remove items', function() { + var items = ['item1', 'item2', 'item3']; + obj.store(data); + obj.remove(items); + obj.load(items).should.be.empty; }); }); @@ -40,8 +58,13 @@ define([path + 'LocalStorage', var endpointLoad = 'testLoadEndpoint'; var params = { test: 'testValue' }; var storageOptions; + var data; beforeEach(function () { + data = { + 'item1': 'value1', + 'item2': 'value2', + }; storageOptions = { urlStore: endpointStore, urlLoad: endpointLoad, @@ -57,11 +80,14 @@ define([path + 'LocalStorage', it('Store data', function() { sinon.stub($, "ajax"); - obj.store(itemName, 'test'); - var data = params; - data.itemName = 'test'; + + for(var k in params) + data[k] = params[k]; + + obj.store(data); $.ajax.calledWithMatch({ url: endpointStore, + data: data, }).should.equal(true); }); @@ -69,10 +95,17 @@ define([path + 'LocalStorage', sinon.stub($, "ajax").returns({ done: function(){} }); - obj.load(itemName); - var data = params; + var dt = {}; + var keys = ['item1', 'item2']; + obj.load(keys); + dt.keys = keys; + + for(var k in params) + dt[k] = params[k]; + $.ajax.calledWithMatch({ url: endpointLoad, + data: dt }).should.equal(true); });