From 2f14d723b29ba6f23549225933841ab08e502964 Mon Sep 17 00:00:00 2001 From: "Alex A. Naanou" Date: Sun, 18 Feb 2018 15:02:45 +0300 Subject: [PATCH] reworked localStorage/sessionStorage store backend, still not content with the HL API... Signed-off-by: Alex A. Naanou --- ui (gen4)/features/config.js | 7 +- ui (gen4)/features/core.js | 9 ++ ui (gen4)/features/store.js | 225 ++++++++++++++++------------------- ui (gen4)/package-lock.json | 8 +- ui (gen4)/package.json | 2 +- 5 files changed, 117 insertions(+), 134 deletions(-) diff --git a/ui (gen4)/features/config.js b/ui (gen4)/features/config.js index 42ceedb0..531e4fd7 100755 --- a/ui (gen4)/features/config.js +++ b/ui (gen4)/features/config.js @@ -113,8 +113,8 @@ module.ConfigStore = core.ImageGridFeatures.Feature({ // XXX need to update rather than rewrite things... ['prepareStoreToSave', function(res){ - //var ls_path = '/${ROOT_PATH}/config' - var ls_path = 'config' + var ls_path = '${INSTANCE}/config' + //var ls_path = 'config' // localStorage... // NOTE: we do not need to clone anything here as this @@ -135,8 +135,7 @@ module.ConfigStore = core.ImageGridFeatures.Feature({ ['storeDataLoaded', function(data){ var base = this.__base_config = this.__base_config || this.config - //var ls_path = '/${ROOT_PATH}/config' - var ls_path = 'config' + var ls_path = '${INSTANCE}/config' // XXX sort out load priority/logic... // - one or the other or both? diff --git a/ui (gen4)/features/core.js b/ui (gen4)/features/core.js index a45e7c3a..62395cf9 100755 --- a/ui (gen4)/features/core.js +++ b/ui (gen4)/features/core.js @@ -670,6 +670,8 @@ var CacheActions = actions.Actions({ NOTE: both "modes" of doing a pre-cache run in the main thread, the difference is that the "async" version lets JS run frames between processing sync chunks... + NOTE: this will not drop the existing cache, to do this run + .clearCache() first or run .reCache(..). `, function(t){ if(this.config.cache){ @@ -719,6 +721,13 @@ var CacheActions = actions.Actions({ delete this.__cache } }], + + // XXX do we need this... + reCache: ['System/Re-cache', + function(t){ + this + .clearCache() + .preCache(t) }], }) var Cache = diff --git a/ui (gen4)/features/store.js b/ui (gen4)/features/store.js index b17257e4..52eb710d 100755 --- a/ui (gen4)/features/store.js +++ b/ui (gen4)/features/store.js @@ -84,7 +84,7 @@ var StoreActions = actions.Actions({ })], - // XXX do we need to parse date here??? + // base API... parseStoreQuery: ['- Store/', core.doc` @@ -145,7 +145,6 @@ var StoreActions = actions.Actions({ } }], - // base API... prepareStoreToSave: ['- Store/', core.doc` @@ -328,140 +327,116 @@ module.Store = core.ImageGridFeatures.Feature({ // NOTE: the doc is reused for both localStorage and sessionStorage with // appropriate automated changes... -// XXX Q: do we save to ROOT_PATH by default??? var __storageHandler_doc = core.doc`Handle localStorage store data... + + Write data to key... + .localStorageDataHandler(key, data) + + Get data from key... + .localStorageDataHandler(key) + -> value + + Remove key... + .localStorageDataHandler(key, null) + .localStorageDataHandler([key, ..], null) + - Get localStorage data... + + Get stored keys... + .localStorageDataHandler('?') + -> keys + .localStorageDataHandler() + .localStorageDataHandler('??') + -> data + + .localStorageDataHandler([key, ..], '??') -> data - Save data set to localStorage... + Expand data to store... .localStorageDataHandler(data) - -> this - - Save data to key in localStorage... - .localStorageDataHandler(data, key) - -> this - - Delete all data from localStorage... + + Remove all data... .localStorageDataHandler(null) - -> this - - - NOTE: load resolves to the same keys as were passed to load, while - localStorage stores the expanded keys... - '/$\{ROOT_PATH}/path' - --(store)--> this.config['store-root-key'] +'/path' - --(load)--> '/$\{ROOT_PATH}/path' - - - Root keys of data partially support path syntax: - '/key' or '../key' - stored in localStorage[key] - './key' or 'key' - stored as-is in localStorage[this.config['store-root-key']] - - - Path variables: - $\{ROOT_PATH} - resolves to .config['store-root-key'] - NOTE: './key' and $\{ROOT_PATH}/key are - not the same, the former will be stored in: - localStorage[this.config['store-root-key']][key] - while the later is stored in: - localStorage[this.config['store-root-key/' + key] - XXX not yet sure this is the right way to go... - - HOTE: other path syntax is ignored and the key will be saved as-is. + + + NOTE: when handling key expansion the unexpanded key should be used + to access data, e.g. if writing '\${INSTANCE}/xyz' the same string + is returned via .localStorageDataHandler('??') and should be used + to get the value, i.e. + .localStorageDataHandler('\${INSTANCE}/xyz') ` -function makeStorageHandler(storage, alias){ - var func = function(data, key){ - alias = alias || storage +function makeStorageHandler(storage){ + var func = function(a, b){ storage = typeof(storage) == typeof('str') ? window[storage] : storage - var root_pattern = /^(\.\.)?[\\\/]/ - var root = this.config['store-root-key'] - + var instance = this.config['store-instance-key'] var resolvePath = function(p){ return p - .replace('${ROOT_PATH}', root) - .replace(root_pattern, '') } - - // clear... - if(data === null){ - // remove specific key... - if(key){ - var data = func.call(this) - data[key] = undefined - func.call(this, data) - - // clear all... - } else { - var d = storage[root] - d = d != undefined ? JSON.parse(d) : {} - ;(d.__root_paths__ || []) - .forEach(function(p){ - var key = resolvePath(p) - delete storage[key] }) - delete storage[root] - } - - // set... - // NOTE: this will update existing data set... - // NOTE: attrs explicitly set to undefined are removed... - } else if(data){ - if(key){ - data = { [key]: data } - } - - // update existing data... - var old = func.call(this) - Object.keys(data).forEach(function(k){ - if(data[k] === undefined){ - delete old[k] - delete data[k] - } - }) - data = Object.assign(old, data) - - var root_data = {} - var root_paths = [] - - // handle root paths... - Object.keys(data) - .forEach(function(p){ - if(root_pattern.test(p)){ - var key = resolvePath(p) - root_paths.push(p) - root_data[key] = JSON.stringify(data[p]) - delete data[p] - } - }) - data.__root_paths__ = root_paths - - storage[root] = JSON.stringify(data) - - // store root stuff... - Object.assign(storage, root_data) - - // get... - } else { - var d = storage[root] - d = d != undefined ? JSON.parse(d) : {} - - // load root paths... - ;(d.__root_paths__ || []) - .forEach(function(p){ - var key = resolvePath(p) - var o = storage[key] - o = o != undefined ? JSON.parse(o) : o - - d[p] = o - }) - delete d.__root_paths__ - - return d + .replace('${INSTANCE}', instance) } + + // XXX should this be all keys by default??? + var keys = Object.keys(storage) + + var dict_key = '${INSTANCE}/__dict__' + var k = resolvePath(dict_key) + var dict = JSON.parse(storage[k] || '{}') + dict[k] = dict_key + + // get list of keys... + if(a == '?'){ + return keys + .map(function(key){ return dict[key] || key }) + + // get store contents... + } else if(a == '??' + || arguments.length == 0 + || (a instanceof Array && (b == '??' || arguments.length == 1))){ + var res = {} + var keys = a instanceof Array ? a : keys + keys.forEach(function(key){ + res[dict[key] || key] = JSON.parse(storage[key]) }) + return res + + // remove all keys... + } else if(a === null || (a instanceof Array && b === null)){ + ;(a || keys) + .forEach(function(key){ + delete storage[key] }) + dict = {} + + // expand data to store... + } else if(typeof(a) != typeof('str')){ + Object.keys(a).forEach(function(key){ + var k = resolvePath(key) + k != key + && (dict[k] = key) + storage[k] = JSON.stringify(a[key]) }) + + // remove key... + } else if(b === null){ + var k = resolvePath(a) + delete dict[k] + delete storage[k] + + // get key... + } else if(b === undefined){ + var k = resolvePath(a) + return k in storage ? + JSON.parse(storage[k]) + : actions.UNDEFINED + + // write key... + } else { + var k = resolvePath(a) + k != a + && (dict[k] = a) + storage[k] = JSON.stringify(b) + } + + storage[resolvePath('${INSTANCE}/__dict__')] = JSON.stringify(dict) } if(typeof(storage) == typeof('str')){ @@ -478,16 +453,16 @@ function makeStorageHandler(storage, alias){ // load the store... (???) var StoreLocalStorageActions = actions.Actions({ config: { - 'store-root-key': 'ImageGrid.Viewer.main', + 'store-instance-key': 'ImageGrid.Viewer.main', }, // NOTE: for docs see __storageHandler_doc... localStorageDataHandler: ['- Store/', {handle_data_store: 'storage',}, - makeStorageHandler('localStorage', 'storage')], + makeStorageHandler('localStorage')], sessionStorageDataHandler: ['- Store/', {handle_data_store: 'session',}, - makeStorageHandler('sessionStorage', 'session')], + makeStorageHandler('sessionStorage')], }) var StoreLocalStorage = diff --git a/ui (gen4)/package-lock.json b/ui (gen4)/package-lock.json index 00b0900c..f8b1babc 100755 --- a/ui (gen4)/package-lock.json +++ b/ui (gen4)/package-lock.json @@ -1058,9 +1058,9 @@ "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" }, "ig-actions": { - "version": "3.16.0", - "resolved": "https://registry.npmjs.org/ig-actions/-/ig-actions-3.16.0.tgz", - "integrity": "sha512-4ibmH2vMNYxzac63ibCS5vwSr6C+NO+IJLwft9eEorAxyi74es+QRgyPPyZVqHOB9GouUZM9kWQVDxcZYrGp+w==", + "version": "3.18.0", + "resolved": "https://registry.npmjs.org/ig-actions/-/ig-actions-3.18.0.tgz", + "integrity": "sha512-wiN7pjt5CfklD/XNiehJnxrAn6/K7/dorUAYG0zTItYTCtp3iqyPCDtFiAF/PAFMbWjbiQxA2w8oIrZNV1QECQ==", "requires": { "ig-object": "1.0.2" } @@ -1070,7 +1070,7 @@ "resolved": "https://registry.npmjs.org/ig-features/-/ig-features-3.3.4.tgz", "integrity": "sha512-nJmMDfY6JiyQ2mQj31oMOmw/HOY4zbN6yyPEFu61ySXU/f3+CC/GZjdaYFemVbnZThC7hcxYfmj62eSjt7oT+Q==", "requires": { - "ig-actions": "3.16.0", + "ig-actions": "3.18.0", "ig-object": "1.0.2" } }, diff --git a/ui (gen4)/package.json b/ui (gen4)/package.json index ab1ce801..0ec46817 100755 --- a/ui (gen4)/package.json +++ b/ui (gen4)/package.json @@ -26,7 +26,7 @@ "fs-walk": "^0.0.1", "glob": "^4.0.6", "guarantee-events": "^1.0.0", - "ig-actions": "^3.16.0", + "ig-actions": "^3.18.0", "ig-features": "^3.3.4", "ig-object": "^1.0.2", "moment": "^2.20.1",