mirror of
https://github.com/flynx/ImageGrid.git
synced 2025-10-29 10:20:08 +00:00
referted back and made a mixed definition implementation...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
7784794e45
commit
fb9570c175
@ -62,6 +62,31 @@ module.Tags = core.ImageGridFeatures.Feature({
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// Persistent tags (tree)
|
||||||
|
//
|
||||||
|
// XXX add save/load tree to fs...
|
||||||
|
// XXX
|
||||||
|
var PersistentTagsActions = actions.Actions({
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
var PersistentTags =
|
||||||
|
module.PersistentTags = core.ImageGridFeatures.Feature({
|
||||||
|
title: '',
|
||||||
|
doc: '',
|
||||||
|
|
||||||
|
tag: 'persistent-tags',
|
||||||
|
depends: [
|
||||||
|
'base',
|
||||||
|
],
|
||||||
|
actions: PersistentTagsActions,
|
||||||
|
|
||||||
|
handlers: [],
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
|
|
||||||
var TagsEditActions =
|
var TagsEditActions =
|
||||||
@ -264,36 +289,17 @@ module.TagsEdit = core.ImageGridFeatures.Feature({
|
|||||||
res.data.tag('marked', json.marked || [])
|
res.data.tag('marked', json.marked || [])
|
||||||
res.data.tag('bookmark', json.bookmarked ? json.bookmarked[0] : [])
|
res.data.tag('bookmark', json.bookmarked ? json.bookmarked[0] : [])
|
||||||
}],
|
}],
|
||||||
|
['load',
|
||||||
|
function(){
|
||||||
|
// XXX for now this is testing only...
|
||||||
|
//this.data.tags.togglePersistent(this.config['tags-persistent'] || [], 'on')
|
||||||
|
//this.data.tags.define(this.config['tags-definitions'] || [])
|
||||||
|
}],
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
|
||||||
// Persistent tags (tree)
|
|
||||||
//
|
|
||||||
// XXX add save/load tree to fs...
|
|
||||||
// XXX
|
|
||||||
var PersistentTagsActions = actions.Actions({
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
var PersistentTags =
|
|
||||||
module.PersistentTags = core.ImageGridFeatures.Feature({
|
|
||||||
title: '',
|
|
||||||
doc: '',
|
|
||||||
|
|
||||||
tag: 'persistent-tags',
|
|
||||||
depends: [
|
|
||||||
'base',
|
|
||||||
],
|
|
||||||
actions: PersistentTagsActions,
|
|
||||||
|
|
||||||
handlers: [],
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
// Tags UI...
|
// Tags UI...
|
||||||
//
|
//
|
||||||
@ -342,7 +348,7 @@ var TagUIActions = actions.Actions({
|
|||||||
// orientation:landscape / orientation:portrait / orientation:square (???)
|
// orientation:landscape / orientation:portrait / orientation:square (???)
|
||||||
// ...these should not be settable by user...
|
// ...these should not be settable by user...
|
||||||
// XXX do a whitepaper (RFC?) on this system when done...
|
// XXX do a whitepaper (RFC?) on this system when done...
|
||||||
'base-tags': [
|
'tags-persistent': [
|
||||||
'count',
|
'count',
|
||||||
'count/one',
|
'count/one',
|
||||||
'count/two',
|
'count/two',
|
||||||
@ -399,6 +405,30 @@ var TagUIActions = actions.Actions({
|
|||||||
'activity/sport/tennis',
|
'activity/sport/tennis',
|
||||||
// ...
|
// ...
|
||||||
],
|
],
|
||||||
|
'tags-definitions': {
|
||||||
|
// abstract...
|
||||||
|
'entity': 'entity:one',
|
||||||
|
'couple': 'entity:two',
|
||||||
|
'entities': 'entity:many',
|
||||||
|
|
||||||
|
// people...
|
||||||
|
'man': 'man:one',
|
||||||
|
'men': 'man:many',
|
||||||
|
'woman': 'woman:one',
|
||||||
|
'women': 'woman:one',
|
||||||
|
'child': 'child:one',
|
||||||
|
'children': 'child:many',
|
||||||
|
'girl': 'girl:one',
|
||||||
|
'girls': 'girl:many',
|
||||||
|
'boy': 'boy:one',
|
||||||
|
'boys': 'boy:many',
|
||||||
|
'baby': 'baby:one',
|
||||||
|
'babies': 'baby:one',
|
||||||
|
|
||||||
|
'person': 'person:man:woman:girl:boy:child:baby:entity',
|
||||||
|
'people': 'person:many',
|
||||||
|
'crowd': 'person:man:woman:girl:boy:child:entity:many',
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// Tag cloud/list...
|
// Tag cloud/list...
|
||||||
|
|||||||
@ -25,6 +25,7 @@
|
|||||||
* XXX should this serialize recursively down???
|
* XXX should this serialize recursively down???
|
||||||
* ...it might be a good idea to decide on a serialization
|
* ...it might be a good idea to decide on a serialization
|
||||||
* protocol and use it throughout...
|
* protocol and use it throughout...
|
||||||
|
* XXX should .tags() return all the used tags + .persistent or .persistentAll ???
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
@ -263,12 +264,40 @@ var BaseTagsPrototype = {
|
|||||||
// Tag definitions...
|
// Tag definitions...
|
||||||
//
|
//
|
||||||
// Format:
|
// Format:
|
||||||
|
// Set([<tag>, ..])
|
||||||
|
//
|
||||||
|
// XXX Q: should definitions be treated as persistent tags???
|
||||||
|
definitions: null,
|
||||||
|
// Format:
|
||||||
// {
|
// {
|
||||||
// <tag>: [<tag>, ..],
|
// <tag>: [<tag>, ..],
|
||||||
// ...
|
// ...
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
definitions: null,
|
__definition_index: null,
|
||||||
|
get definition_index(){
|
||||||
|
var that = this
|
||||||
|
return (this.definitions == null || this.definitions.size == 0) ?
|
||||||
|
{}
|
||||||
|
: (this.__definition_index = this.__definition_index
|
||||||
|
|| [...this.definitions]
|
||||||
|
.reduce(function(res, p){
|
||||||
|
p = that.splitPath(p)
|
||||||
|
res[p.pop()] = that.splitSet(p[0])
|
||||||
|
return res }, {})) },
|
||||||
|
|
||||||
|
|
||||||
|
// Props...
|
||||||
|
//
|
||||||
|
get length(){
|
||||||
|
return this.values().length },
|
||||||
|
// XXX should this include only definition keys, values or both???
|
||||||
|
get persistentAll(){
|
||||||
|
return (this.__persistent || new Set())
|
||||||
|
.unite(this.definitions || []) },
|
||||||
|
//.unite(Object.entries(this.definitions || {})
|
||||||
|
// .flat(1)
|
||||||
|
// .map(function(d){ return d.join ? d.join(':') : d })) },
|
||||||
|
|
||||||
|
|
||||||
// Utils...
|
// Utils...
|
||||||
@ -371,7 +400,7 @@ var BaseTagsPrototype = {
|
|||||||
|
|
||||||
// match two tags...
|
// match two tags...
|
||||||
} else {
|
} else {
|
||||||
var definitions = this.definitions
|
var definitions = this.definition_index
|
||||||
|
|
||||||
var root = /^\s*[\\\/]/.test(a)
|
var root = /^\s*[\\\/]/.test(a)
|
||||||
var base = /[\\\/]\s*$/.test(a)
|
var base = /[\\\/]\s*$/.test(a)
|
||||||
@ -388,9 +417,12 @@ var BaseTagsPrototype = {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Expand definitions...
|
// Expand definitions...
|
||||||
//
|
//
|
||||||
// NOTE: this does not care about infinite recursion...
|
// NOTE: this does not care about infinite recursion...
|
||||||
|
// NOTE: this does the same job as adding .definitions to
|
||||||
|
// .persistent but much much faster...
|
||||||
var expand = function(tags, res){
|
var expand = function(tags, res){
|
||||||
if(!definitions){
|
if(!definitions){
|
||||||
return tags
|
return tags
|
||||||
@ -492,7 +524,7 @@ var BaseTagsPrototype = {
|
|||||||
var paths = function(tag){
|
var paths = function(tag){
|
||||||
return that.directMatch(tag, cmp)
|
return that.directMatch(tag, cmp)
|
||||||
.filter(function(t){
|
.filter(function(t){
|
||||||
return /[\\\/]/.test(t) }) }
|
return that.PATH_SEPARATOR.test(t) }) }
|
||||||
// search the path tree...
|
// search the path tree...
|
||||||
// NOTE: this will stop the search on first hit...
|
// NOTE: this will stop the search on first hit...
|
||||||
var search = function(tag, seen){
|
var search = function(tag, seen){
|
||||||
@ -639,9 +671,6 @@ var BaseTagsPrototype = {
|
|||||||
|
|
||||||
// Introspection and Access API...
|
// Introspection and Access API...
|
||||||
//
|
//
|
||||||
get length(){
|
|
||||||
return this.values().length },
|
|
||||||
|
|
||||||
// Direct tag/value check...
|
// Direct tag/value check...
|
||||||
//
|
//
|
||||||
// NOTE: these are not using for loops so as to enable "fast abort",
|
// NOTE: these are not using for loops so as to enable "fast abort",
|
||||||
@ -681,6 +710,7 @@ var BaseTagsPrototype = {
|
|||||||
//
|
//
|
||||||
// XXX should we rename this to .usedTags(..) and .singleTags(..) to
|
// XXX should we rename this to .usedTags(..) and .singleTags(..) to
|
||||||
// .tags(..) ???
|
// .tags(..) ???
|
||||||
|
// XXX should this use .persistentAll or .persistent ???
|
||||||
tags: function(value, ...tags){
|
tags: function(value, ...tags){
|
||||||
var that = this
|
var that = this
|
||||||
|
|
||||||
@ -706,6 +736,7 @@ var BaseTagsPrototype = {
|
|||||||
// get all tags...
|
// get all tags...
|
||||||
} else {
|
} else {
|
||||||
return Object.keys(this.__index || {})
|
return Object.keys(this.__index || {})
|
||||||
|
//.concat([...(this.persistentAll || [])]
|
||||||
.concat([...(this.persistent || [])]
|
.concat([...(this.persistent || [])]
|
||||||
.map(function(t){
|
.map(function(t){
|
||||||
return that.normalize(t) }))
|
return that.normalize(t) }))
|
||||||
@ -1003,7 +1034,9 @@ var BaseTagsPrototype = {
|
|||||||
} else {
|
} else {
|
||||||
patchSet(this.persistent || [])
|
patchSet(this.persistent || [])
|
||||||
patchObj(this.__index || {})
|
patchObj(this.__index || {})
|
||||||
patchObj(this.definitions || {}, true)
|
//patchObj(this.definitions || {}, true)
|
||||||
|
patchSet(this.definitions || [])
|
||||||
|
delete this.__definition_index
|
||||||
}
|
}
|
||||||
|
|
||||||
return this
|
return this
|
||||||
@ -1048,6 +1081,17 @@ var BaseTagsPrototype = {
|
|||||||
return res
|
return res
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*/ XXX there are two implementations here:
|
||||||
|
// 1) using a map index...
|
||||||
|
// + should be faster...
|
||||||
|
// - re-implements essentially the same mechanism as path
|
||||||
|
// searching but in a different way...
|
||||||
|
// 2) using the existing path mechanic...
|
||||||
|
// + simpler
|
||||||
|
// + less code
|
||||||
|
// - should be slower for lots of deffinitions...
|
||||||
// Get/set/remove tag definitions...
|
// Get/set/remove tag definitions...
|
||||||
//
|
//
|
||||||
// A definition is a single tag that is defined by ("means") a tag set.
|
// A definition is a single tag that is defined by ("means") a tag set.
|
||||||
@ -1136,6 +1180,111 @@ var BaseTagsPrototype = {
|
|||||||
}
|
}
|
||||||
return this
|
return this
|
||||||
},
|
},
|
||||||
|
/*/
|
||||||
|
// Get/set/remove tag definitions...
|
||||||
|
//
|
||||||
|
// A definition is a single tag that is defined by ("means") a tag set.
|
||||||
|
//
|
||||||
|
// Resolve definition (recursive)...
|
||||||
|
// .define(tag)
|
||||||
|
// -> value
|
||||||
|
// -> undefined
|
||||||
|
//
|
||||||
|
// Set definition...
|
||||||
|
// .define(tag, value)
|
||||||
|
// -> this
|
||||||
|
//
|
||||||
|
// Remove definition...
|
||||||
|
// .define(tag, null)
|
||||||
|
// -> this
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Batch call...
|
||||||
|
// .define([[tag, value], ..])
|
||||||
|
// .define({tag: value, ..})
|
||||||
|
// -> this
|
||||||
|
// NOTE: each entry should be .define(...entry) call compatible
|
||||||
|
// though there is little point to call the resolve/get mode
|
||||||
|
// in this manner...
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// This expects and maintains one and only one definition per tag,
|
||||||
|
// thus all stray definitions will be overwritten on any write
|
||||||
|
// operation...
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
// // nested recursive definition...
|
||||||
|
// ts.define('bird', 'bird:one')
|
||||||
|
//
|
||||||
|
// ts.define('birds', 'bird:many')
|
||||||
|
//
|
||||||
|
// // filter a list...
|
||||||
|
// ts.match('bird', ['bird', 'birds', 'animal']) // -> ['bird', 'birds']
|
||||||
|
//
|
||||||
|
// NOTE: definitions are a special case persistent path maintained
|
||||||
|
// in a different location (.definitions), same search rules
|
||||||
|
// apply.
|
||||||
|
//
|
||||||
|
// XXX this can be faster if we index definitions via a map...
|
||||||
|
define: function(tag, value){
|
||||||
|
var that = this
|
||||||
|
var definitions = this.definitions
|
||||||
|
|
||||||
|
// batch...
|
||||||
|
tag = tag instanceof Array ? new Map(tag) : tag
|
||||||
|
if(typeof(tag) != typeof('str')){
|
||||||
|
(tag instanceof Map ?
|
||||||
|
[...tag.entries()]
|
||||||
|
: Object.entries(tag))
|
||||||
|
.forEach(function(e){
|
||||||
|
that.define(...e) })
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
tag = this.normalize(tag)
|
||||||
|
if(/[:\\\/]/.test(tag)){
|
||||||
|
throw new Error(`.alias(..): tag must be a single tag, got: "${tag}`) }
|
||||||
|
|
||||||
|
// get/resolve...
|
||||||
|
if(arguments.length == 1){
|
||||||
|
// NOTE: we expect there to be only one definition...
|
||||||
|
return this.match(tag +'/', [...this.definitions || []])
|
||||||
|
.map(function(d){
|
||||||
|
return that.splitPath(d).shift() })[0]
|
||||||
|
|
||||||
|
// remove...
|
||||||
|
} else if(value == null){
|
||||||
|
// remove all definitions of tag...
|
||||||
|
this.match(tag +'/', [...this.definitions || []])
|
||||||
|
.forEach(function(value){
|
||||||
|
definitions.delete(value +'/'+ tag) })
|
||||||
|
|
||||||
|
// delete empty .definitions
|
||||||
|
definitions
|
||||||
|
&& definitions.size == 0
|
||||||
|
&& (delete this.definitions)
|
||||||
|
|
||||||
|
delete this.__definition_index
|
||||||
|
|
||||||
|
// set...
|
||||||
|
} else {
|
||||||
|
value = this.normalize(value)
|
||||||
|
if(/[\\\/]/.test(tag)){
|
||||||
|
throw new Error(`.alias(..): value must not be a path, got: "${value}`) }
|
||||||
|
|
||||||
|
// clear previous definition...
|
||||||
|
this.define(tag, null)
|
||||||
|
|
||||||
|
this.definitions = (this.definitions || new Set())
|
||||||
|
.add(value +'/'+ tag)
|
||||||
|
}
|
||||||
|
return this
|
||||||
|
},
|
||||||
|
//*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Optimize tags...
|
// Optimize tags...
|
||||||
//
|
//
|
||||||
@ -1502,8 +1651,10 @@ var BaseTagsPrototype = {
|
|||||||
var res = {}
|
var res = {}
|
||||||
|
|
||||||
// definitions...
|
// definitions...
|
||||||
this.definitions && Object.keys(this.definitions).length > 0
|
//this.definitions && Object.keys(this.definitions).length > 0
|
||||||
&& (res.definitions = Object.assign({}, this.definitions))
|
// && (res.definitions = Object.assign({}, this.definitions))
|
||||||
|
this.definitions && this.definitions.size > 0
|
||||||
|
&& (res.definitions = [...this.definitions])
|
||||||
|
|
||||||
// persistent tags...
|
// persistent tags...
|
||||||
this.persistent && this.persistent.size > 0
|
this.persistent && this.persistent.size > 0
|
||||||
@ -1523,7 +1674,8 @@ var BaseTagsPrototype = {
|
|||||||
|
|
||||||
// definitions...
|
// definitions...
|
||||||
json.definitions
|
json.definitions
|
||||||
&& (this.definitions = Object.assign({}, json.definitions))
|
//&& (this.definitions = Object.assign({}, json.definitions))
|
||||||
|
&& (this.definitions = new Set(json.definitions))
|
||||||
|
|
||||||
// persistent tags...
|
// persistent tags...
|
||||||
json.persistent
|
json.persistent
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user