mirror of
https://github.com/flynx/ImageGrid.git
synced 2025-10-29 10:20:08 +00:00
adding queries to store API (in progress)...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
80d7fbd4ad
commit
ff1e1627cc
@ -115,30 +115,37 @@ module.ConfigStore = core.ImageGridFeatures.Feature({
|
|||||||
// localStorage...
|
// localStorage...
|
||||||
// NOTE: we do not need to clone anything here as this
|
// NOTE: we do not need to clone anything here as this
|
||||||
// will be done by the localStorage handler...
|
// will be done by the localStorage handler...
|
||||||
res.store.localStorage.config = this.config
|
if(res.data.localStorage){
|
||||||
|
res.data.localStorage.config = this.config
|
||||||
// XXX sync fs store...
|
|
||||||
// XXX get better tag...
|
|
||||||
if(res.store.fsJSONSync){
|
|
||||||
// XXX should this include path???
|
|
||||||
res.store.fsJSONSync[this.config['config-fs-filename'] || '.ImageGrid.json'] = this.config
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(res.data.fsJSONSync){
|
||||||
|
// XXX should this include path???
|
||||||
|
res.data.fsJSONSync[this.config['config-fs-filename'] || '.ImageGrid.json'] = this.config
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
['prepareIndexForLoad',
|
||||||
|
function(){
|
||||||
}],
|
}],
|
||||||
// NOTE: this is sync for sync stores...
|
// NOTE: this is sync for sync stores...
|
||||||
['storeDataLoaded',
|
['storeDataLoaded',
|
||||||
function(store){
|
function(data){
|
||||||
if((store.localStorage || {}).config){
|
|
||||||
var base = this.__base_config = this.__base_config || this.config
|
var base = this.__base_config = this.__base_config || this.config
|
||||||
var config = store.localStorage.config || {}
|
|
||||||
|
// XXX sort out load priority/logic...
|
||||||
|
// - one or the other or both?
|
||||||
|
// - what order?
|
||||||
|
|
||||||
|
if((data.localStorage || {}).config){
|
||||||
|
var config = data.localStorage.config || {}
|
||||||
config.__proto__ = base
|
config.__proto__ = base
|
||||||
this.config = config
|
this.config = config
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX sync fs store...
|
if((data.fsJSONSync || {}).config){
|
||||||
// XXX get better tag...
|
var config = data.fsJSONSync.config || {}
|
||||||
// XXX where do we write???
|
config.__proto__ = base
|
||||||
if((store.fsJSONSync || {}).config){
|
this.config = config
|
||||||
// XXX
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// auto-start auto-save...
|
// auto-start auto-save...
|
||||||
|
|||||||
@ -49,8 +49,8 @@ var StoreActions = actions.Actions({
|
|||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// XXX this is almost the same as .collection_handlers...
|
// XXX this is almost the same as .collection_handlers...
|
||||||
get store_handlers(){
|
get stores(){
|
||||||
return this.cache('store_handlers', function(d){
|
return this.cache('stores', function(d){
|
||||||
var res = {}
|
var res = {}
|
||||||
|
|
||||||
this.actions.forEach(function(action){
|
this.actions.forEach(function(action){
|
||||||
@ -64,6 +64,8 @@ var StoreActions = actions.Actions({
|
|||||||
|
|
||||||
return res
|
return res
|
||||||
}) },
|
}) },
|
||||||
|
// XXX need store client list (???)
|
||||||
|
//get store_clients(){ return [] },
|
||||||
|
|
||||||
// events...
|
// events...
|
||||||
storeDataLoaded: ['- Store/',
|
storeDataLoaded: ['- Store/',
|
||||||
@ -80,11 +82,74 @@ var StoreActions = actions.Actions({
|
|||||||
return data
|
return data
|
||||||
})],
|
})],
|
||||||
|
|
||||||
|
|
||||||
|
// XXX do we need to parse date here???
|
||||||
|
parseStoreQuery: ['- Store/',
|
||||||
|
core.doc`
|
||||||
|
|
||||||
|
Query syntax:
|
||||||
|
<event>:<store>:<key>
|
||||||
|
<store>:<key>
|
||||||
|
<store>
|
||||||
|
<key>
|
||||||
|
|
||||||
|
Format:
|
||||||
|
{
|
||||||
|
query: <input-query>,
|
||||||
|
date: <timestamp>,
|
||||||
|
event: 'manual' | <event>,
|
||||||
|
store: '*' | <store> | [<store>, ...]
|
||||||
|
key: '*' | <key> | [<key>, ...]
|
||||||
|
}
|
||||||
|
|
||||||
|
`,
|
||||||
|
function(query, date){
|
||||||
|
var defaults = {
|
||||||
|
date: date || Date.timeStamp(),
|
||||||
|
event: 'manual',
|
||||||
|
store: '*',
|
||||||
|
key: '*',
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse string...
|
||||||
|
if(typeof(query) == typeof('str')){
|
||||||
|
var res = {}
|
||||||
|
res.query = query
|
||||||
|
|
||||||
|
query = query.split(/:/g)
|
||||||
|
|
||||||
|
res.event = query.length > 2 ?
|
||||||
|
query.shift()
|
||||||
|
: defaults.event
|
||||||
|
res.store = (this.stores[query[0]] || query.length > 1) ?
|
||||||
|
query.shift().split(/\|/g)
|
||||||
|
: defaults.store
|
||||||
|
res.key = query.length > 0 ?
|
||||||
|
query.pop().split(/\|/g)
|
||||||
|
: defaults.key
|
||||||
|
res.date = date || defaults.date
|
||||||
|
|
||||||
|
return res
|
||||||
|
|
||||||
|
// get the defaults...
|
||||||
|
} else if(query == null){
|
||||||
|
return defaults
|
||||||
|
|
||||||
|
// pass on the input...
|
||||||
|
} else {
|
||||||
|
if(date){
|
||||||
|
query.date = date
|
||||||
|
}
|
||||||
|
return query
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
|
||||||
// base API...
|
// base API...
|
||||||
// XXX we need to be able to save/load specific part of the data...
|
// XXX we need to be able to save/load specific part of the data...
|
||||||
// ...i.e. query by store and/or key...
|
// ...i.e. query by store and/or key...
|
||||||
// the syntax could be:
|
// the syntax could be:
|
||||||
// <store>:<path>
|
// <store>:<path>
|
||||||
|
// <store>:<event>:<path>
|
||||||
//
|
//
|
||||||
// Example:
|
// Example:
|
||||||
// 'localstorage:config' - save config to localStorage
|
// 'localstorage:config' - save config to localStorage
|
||||||
@ -96,10 +161,6 @@ var StoreActions = actions.Actions({
|
|||||||
prepareStoreToSave: ['- Store/',
|
prepareStoreToSave: ['- Store/',
|
||||||
core.doc`
|
core.doc`
|
||||||
|
|
||||||
Modes:
|
|
||||||
'fast' - fast timer
|
|
||||||
'full' - full store
|
|
||||||
|
|
||||||
Format:
|
Format:
|
||||||
{
|
{
|
||||||
// metadata...
|
// metadata...
|
||||||
@ -107,8 +168,8 @@ var StoreActions = actions.Actions({
|
|||||||
data: <timestamp>,
|
data: <timestamp>,
|
||||||
|
|
||||||
// the actual data...
|
// the actual data...
|
||||||
store: {
|
data: {
|
||||||
<store-type>: {
|
<data-type>: {
|
||||||
<data-key>: <data>,
|
<data-key>: <data>,
|
||||||
...
|
...
|
||||||
},
|
},
|
||||||
@ -116,60 +177,100 @@ var StoreActions = actions.Actions({
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
function(mode, date){
|
function(query, data){
|
||||||
var store = {}
|
var defaults = this.parseStoreQuery()
|
||||||
// populate the store...
|
query = this.parseStoreQuery(query)
|
||||||
Object.keys(this.store_handlers)
|
var stores = query.store || defaults.store
|
||||||
.forEach(function(key){ store[key] = {} })
|
|
||||||
return {
|
|
||||||
mode: mode || 'full',
|
|
||||||
date: date || Date.timeStamp(),
|
|
||||||
|
|
||||||
store: store,
|
// populate the store...
|
||||||
|
data = data || {}
|
||||||
|
Object.keys(this.stores)
|
||||||
|
// only populate the requested handlers...
|
||||||
|
.filter(function(store){
|
||||||
|
return (stores == '*'
|
||||||
|
|| stores == 'all')
|
||||||
|
|| stores == store
|
||||||
|
|| stores.indexOf(store) >= 0 })
|
||||||
|
.forEach(function(key){ data[key] = {} })
|
||||||
|
|
||||||
|
return {
|
||||||
|
date: query.date || Date.timeStamp(),
|
||||||
|
|
||||||
|
event: query.event || defaults.event,
|
||||||
|
key: query.key || defaults.key,
|
||||||
|
|
||||||
|
data: data,
|
||||||
}
|
}
|
||||||
}],
|
}],
|
||||||
|
// XXX use query???
|
||||||
prepareStoreToLoad: ['- Store/',
|
prepareStoreToLoad: ['- Store/',
|
||||||
core.doc`
|
core.doc`
|
||||||
|
|
||||||
NOTE: this can be called multiple times, once per each store.
|
NOTE: this can be called multiple times, once per each store.
|
||||||
NOTE: only one store data set is included per call.`,
|
NOTE: only one store data set is included per call.`,
|
||||||
function(data){ return data || {} }],
|
function(data){ return data || {} }],
|
||||||
|
// XXX this is different from .prepareIndexForWrite(..) in that there
|
||||||
|
// is no default data set...
|
||||||
// XXX async???
|
// XXX async???
|
||||||
// XXX we need to be able to save/load specific part of the data...
|
|
||||||
// ...i.e. query by store and/or key...
|
|
||||||
// the syntax could be:
|
|
||||||
// <store>:<path>
|
|
||||||
//
|
|
||||||
// Example:
|
|
||||||
// 'localstorage:config' - save config to localStorage
|
|
||||||
// 'localstorage:*' - save all to localstorage
|
|
||||||
// '*:config' - save config to all supported stores
|
|
||||||
// '*:*' - save everything
|
|
||||||
//
|
|
||||||
// ...this must be supported by .prepareStoreToSave(..)
|
|
||||||
// XXX API
|
|
||||||
// .storeData(mode) - store all with mode...
|
|
||||||
// .storeData(mode, data) - store data with mode...
|
|
||||||
// .storeData(selector) - store only matching
|
|
||||||
// .storeData(selector, data) - store data to selector...
|
|
||||||
// XXX do we need mode here???
|
|
||||||
saveData: ['- Store/',
|
saveData: ['- Store/',
|
||||||
function(mode, date){
|
// XXX signature not final...
|
||||||
var handlers = this.store_handlers
|
function(query, data){
|
||||||
var data = this.prepareStoreToSave(mode, date)
|
var handlers = this.stores
|
||||||
|
|
||||||
Object.keys(data.store).forEach(function(store){
|
// save the given data...
|
||||||
|
// NOTE: we are not calling .prepareStoreToSave(..) here, thus
|
||||||
|
// we need not care about .key, .date, and other stuff...
|
||||||
|
if(data){
|
||||||
|
var defaults = this.parseStoreQuery()
|
||||||
|
query = this.parseStoreQuery(query)
|
||||||
|
|
||||||
|
if(query.store == defaults.store || query.key == defaults.key){
|
||||||
|
console.error('saveData: at least "store" and "key" '
|
||||||
|
+'must be explicitly set in query...')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var d = {
|
||||||
|
data: {}
|
||||||
|
}
|
||||||
|
var stores = query.store == '*' ? handlers : query.store
|
||||||
|
stores = stores instanceof Array ? stores : [stores]
|
||||||
|
stores.forEach(function(s){
|
||||||
|
d.data[s] = {
|
||||||
|
[query.key]: data,
|
||||||
|
} })
|
||||||
|
|
||||||
|
data = d
|
||||||
|
|
||||||
|
// build the data...
|
||||||
|
} else {
|
||||||
|
data = this.prepareStoreToSave(query)
|
||||||
|
}
|
||||||
|
|
||||||
|
// iterate and handle stores...
|
||||||
|
Object.keys(data.data).forEach(function(store){
|
||||||
var handler = handlers[store]
|
var handler = handlers[store]
|
||||||
handler
|
handler
|
||||||
&& this[handler].call(this, data.store[store])
|
&& this[handler].call(this, data.data[store])
|
||||||
}.bind(this))
|
}.bind(this))
|
||||||
}],
|
}],
|
||||||
|
// XXX add query support... (???)
|
||||||
|
// ...we can't support keys other than '*' until we register
|
||||||
|
// store keys...
|
||||||
loadData: ['- Store/',
|
loadData: ['- Store/',
|
||||||
function(){
|
function(query){
|
||||||
var handlers = this.store_handlers
|
var handlers = this.stores
|
||||||
|
|
||||||
|
var defaults = this.parseStoreQuery()
|
||||||
|
query = this.parseStoreQuery(query)
|
||||||
|
|
||||||
|
query.store = query.store == defaults.store ? Object.keys(handlers) : query.store
|
||||||
|
query.store = query.store instanceof Array ? query.store : [query.store]
|
||||||
|
|
||||||
|
// XXX need to filter loading by query.key...
|
||||||
var data = {}
|
var data = {}
|
||||||
return Promise
|
return Promise
|
||||||
.all(Object.keys(handlers)
|
.all(query.store
|
||||||
.map(function(s){
|
.map(function(s){
|
||||||
var res = this[handlers[s]]()
|
var res = this[handlers[s]]()
|
||||||
return res instanceof Promise ?
|
return res instanceof Promise ?
|
||||||
@ -188,7 +289,7 @@ var StoreActions = actions.Actions({
|
|||||||
// XXX do we need to do a partial clear???
|
// XXX do we need to do a partial clear???
|
||||||
clearData: ['- Store/',
|
clearData: ['- Store/',
|
||||||
function(target){
|
function(target){
|
||||||
var handlers = this.store_handlers
|
var handlers = this.stores
|
||||||
|
|
||||||
Object.keys(handlers).forEach(function(store){
|
Object.keys(handlers).forEach(function(store){
|
||||||
var handler = handlers[store]
|
var handler = handlers[store]
|
||||||
@ -236,6 +337,53 @@ module.Store = core.ImageGridFeatures.Feature({
|
|||||||
|
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
|
|
||||||
|
// NOTE: the doc is reused for both localStorage and sessionStorage with
|
||||||
|
// appropriate automated changes...
|
||||||
|
var __storageHandler_doc =
|
||||||
|
core.doc`Handle localStorage store data...
|
||||||
|
|
||||||
|
Get localStorage data...
|
||||||
|
.localStorageDataHandler()
|
||||||
|
-> data
|
||||||
|
|
||||||
|
Save data set to localStorage...
|
||||||
|
.localStorageDataHandler(data)
|
||||||
|
-> this
|
||||||
|
|
||||||
|
Save data to key in localStorage...
|
||||||
|
.localStorageDataHandler(data, key)
|
||||||
|
-> this
|
||||||
|
|
||||||
|
Delete all data from localStorage...
|
||||||
|
.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.
|
||||||
|
`
|
||||||
function makeStorageHandler(storage){
|
function makeStorageHandler(storage){
|
||||||
var func = function(data, key){
|
var func = function(data, key){
|
||||||
storage = typeof(storage) == typeof('str') ? window[storage] : storage
|
storage = typeof(storage) == typeof('str') ? window[storage] : storage
|
||||||
@ -279,7 +427,6 @@ function makeStorageHandler(storage){
|
|||||||
})
|
})
|
||||||
data.__root_paths__ = root_paths
|
data.__root_paths__ = root_paths
|
||||||
|
|
||||||
|
|
||||||
storage[root] = JSON.stringify(data)
|
storage[root] = JSON.stringify(data)
|
||||||
|
|
||||||
// store root stuff...
|
// store root stuff...
|
||||||
@ -306,50 +453,7 @@ function makeStorageHandler(storage){
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(typeof(storage) == typeof('str')){
|
if(typeof(storage) == typeof('str')){
|
||||||
func.long_doc = core.doc`Handle ${storage} store data...
|
func.long_doc = __storageHandler_doc.replace(/localStorage/g, storage)
|
||||||
|
|
||||||
Get ${storage} data...
|
|
||||||
.${storage}DataHandler()
|
|
||||||
-> data
|
|
||||||
|
|
||||||
Save data set to ${storage}...
|
|
||||||
.${storage}DataHandler(data)
|
|
||||||
-> this
|
|
||||||
|
|
||||||
Save data to key in ${storage}...
|
|
||||||
.${storage}DataHandler(data, key)
|
|
||||||
-> this
|
|
||||||
|
|
||||||
Delete all data from ${storage}...
|
|
||||||
.${storage}DataHandler(null)
|
|
||||||
-> this
|
|
||||||
|
|
||||||
|
|
||||||
NOTE: load resolves to the same keys as were passed to load, while
|
|
||||||
${storage} 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 ${storage}[key]
|
|
||||||
'./key' or 'key'
|
|
||||||
stored as-is in ${storage}[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:
|
|
||||||
${storage}[this.config['store-root-key']][key]
|
|
||||||
while the later is stored in:
|
|
||||||
${storage}[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.
|
|
||||||
`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return func
|
return func
|
||||||
@ -365,7 +469,7 @@ var StoreLocalStorageActions = actions.Actions({
|
|||||||
'store-root-key': 'ImageGrid.Viewer.main',
|
'store-root-key': 'ImageGrid.Viewer.main',
|
||||||
},
|
},
|
||||||
|
|
||||||
// NOTE: for docs see makeStorageHandler(..)
|
// NOTE: for docs see __storageHandler_doc...
|
||||||
localStorageDataHandler: ['- Store/',
|
localStorageDataHandler: ['- Store/',
|
||||||
{handle_data_store: 'localStorage',},
|
{handle_data_store: 'localStorage',},
|
||||||
makeStorageHandler('localStorage')],
|
makeStorageHandler('localStorage')],
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user