diff --git a/Viewer/features/core.js b/Viewer/features/core.js index 6f91ef35..ac46b59a 100755 --- a/Viewer/features/core.js +++ b/Viewer/features/core.js @@ -2855,6 +2855,72 @@ function(title, func){ { __session_task__: true }) } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +// XXX EXPERIMENTAL... +var LinkContext = +module.LinkContext = ImageGridFeatures.Feature({ + title: '', + tag: 'link-context', + depends: [ + 'changes', + ], + + actions: actions.Actions({ + title: null, + // NOTE: we need .__parent to be able to test if we are fully + // detached in .type... + // NOTE: this is maintained by .detachLink(..)... + __parent: null, + parent: null, + + get type(){ + return this.parent ? + 'link' + : (this.__parent + && (this.data !== this.__parent.data + || this.images !== this.__parent.images)) ? + 'link-detached' + : 'link-partial' }, + + __changes: null, + get changes(){ + return this.parent ? + this.parent.changes + : this.__changes }, + set changes(value){ + this.parent ? + (this.parent.changes = value) + : (this.__changes = value)}, + + // NOTE: .detachLink(false) is not intended for direct use as it + // will create a partial link... + detachLink: ['- System/', + doc``, + function(full=true){ + // partial detach... + if(this.type == 'link'){ + // copy over .changes + this.__changes = this.changes === undefined ? + undefined + : JSON.parse(JSON.stringify([this.changes]))[0] + this.__parent = this.parent + delete this.parent } + // full detach... + if(this.type != 'link-detached' && full){ + Object.assign( + this, + this.clone(true)) + // cleanup... + // NOTE: we do not need to cleanup things outside of + // the full detach as this will be done in .links + this.links.current === this + && (delete this.links.current) + this.links.previous === this + && (delete this.links.previous) } }], + }), }) + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // XXX revise logging and logger passing... @@ -2877,6 +2943,11 @@ var TaskActions = actions.Actions({ '__tasks', '__queues', + // NOTE: we link the changes directly to the parent so no need to + // copy them... + 'changes', + + // keep the local features as they are not the same as .parent.features 'features', ], }, @@ -3063,7 +3134,7 @@ var TaskActions = actions.Actions({ // XXX after this is stabilized, do we need session tasks and its complexities??? __links: null, get links(){ - var links = this.__linked = this.__linked || {} + var links = this.__links = this.__links || {} // remove 'current' if it does not match the current index... // XXX revise the test... var c = links.current @@ -3152,9 +3223,6 @@ var TaskActions = actions.Actions({ // link metadata... parent: this, title: title, - // XXX change this when data/images changes... - // ...a prop in the link feature... - type: 'link', // link configuration... logger: that.logger .push(`Linked ${ Object.keys(links).length }`), @@ -3203,6 +3271,14 @@ module.Tasks = ImageGridFeatures.Feature({ // XXX BUG: for some reason calling .abort here does not work... //'sessionTasks.stop'], 'sessionTasks.abort'], + + ['clear.pre', + function(){ + Object.values(this.links || []) + .forEach(function(link){ + // NOTE: we do a partial detach here as .clear(..) will + // detach the data for us... + link.detachLink(false) }) }], ], }) diff --git a/Viewer/features/filesystem.js b/Viewer/features/filesystem.js index 931f659f..62cbe813 100755 --- a/Viewer/features/filesystem.js +++ b/Viewer/features/filesystem.js @@ -779,6 +779,7 @@ var FileSystemLoaderActions = actions.Actions({ }) }], + /* XXX cleanup... // XXX update index for removed images... // - remove non-existing previews from index // - replace non-existing originals with the largest preview (in index) @@ -838,7 +839,59 @@ var FileSystemLoaderActions = actions.Actions({ .then(function(res){ return res.flat() }) }], + //*/ + // XXX EXPERIMENTAL... + // XXX move this to base.js??? + get indexCheckerActions(){ + var that = this + return this.cache('indexCheckerActions', function(cached){ + return cached instanceof Array ? + cached.slice() + : this.actions + .filter(function(action){ + return that.getActionAttr(action, 'checkIndex') }) }) }, + // NOTE: this is not implemented as an overloadable action because it + // would require collection each action's results for post processing + // which in turn would necessitate a second wrapper action that would + // call the first as well as requiring the user not to call the + // overloaded action, and if each of the individual checks can be run + // independently it would require a separate wrapper... + // ...this seems quire a bit more convoluted than the current + // .indexCheckerActions + .checkIndex(..) pair... + // XXX since this by default runs in a .linked context this will update + // the current context state if it was not reloaded but .changes if + // it was set to false will not reflect the changes made by the + // checker actions... + checkIndex: ['File/Check index consistency', + core.doc` + + + Protocol: + - this will call all the actions in .indexCheckerActions + - each of the above actions should comply with: + .() + -> promise + - actions should set .changes appropriately + - the returned promise should yield an array of changes -- empty + array indicates that no changes were made. + + `, + function(options={}){ + var context = + options.linked === false ? + this + : this.link() + return Promise.all( + context.indexCheckerActions + .map(function(action){ + return context[action]() })) + .then(function(res){ + res.flat().length > 0 + && context.saveIndex() + // XXX BUG?: this is not returned by the action for some reason... + return res }) }], + // XXX add a context wrapper a-la .makeIndex(..)... // ...might be a good idea to rename this to .checkIndexPaths(..) // and make the .checkIndex(..) a context aggregate actions like @@ -861,6 +914,7 @@ var FileSystemLoaderActions = actions.Actions({ NOTE: currently this is disabled for merged indexes, need to load and check individually... `, + {checkIndex: true}, core.sessionQueueHandler('checkIndex', function(queue, ...args){ // XXX ignore merged index... @@ -887,25 +941,7 @@ var FileSystemLoaderActions = actions.Actions({ return updated ? gid : [] })], - checkIndex: ['File/Check index consistency', - core.doc``, - function(options={}){ - var context = - options.linked === false ? - this - : this.link() - // XXX we could mark all the index test/recovery actions and - // get them here dynamically... - return Promise.all([ - context.checkIndexPaths(), - // XXX more checks??? - ]).then(function(res){ - // XXX either make res format a protocol requirement or - // revise this... - res.flat().length > 0 - && context.saveIndex() - // XXX this is not returned by the action for some reason... - return res }) }], + // XXX should this take a path argument??? // XXX not yet sure about this... @@ -1062,9 +1098,7 @@ module.FileSystemLoader = core.ImageGridFeatures.Feature({ .markChanged('data') .markChanged('images', imgs.keys()) }, function(){}) }], - // XXX - //['checkIndexPaths', - ['checkIndex', + ['checkIndexPaths', function(res){ var that = this res.then(