diff --git a/kfet/static/kfet/js/kfet.api.js b/kfet/static/kfet/js/kfet.api.js index 81f0cfe4..e0bc2c35 100644 --- a/kfet/static/kfet/js/kfet.api.js +++ b/kfet/static/kfet/js/kfet.api.js @@ -572,75 +572,74 @@ class Article extends ModelObject { set price(v) { this._price = floatCheck(v); } } +class TreeNode { + + constructor(type, content) { + this.type = type; + this.content = content; + this.parent = null; + this.children = []; + } +} + /** * Simple {@link Models.ModelObject} list. * @memberof Models */ -class ModelList { +class ModelTree { /** * Nested structure of the list * @abstract * @type {Models.ModelObject[]} */ - static get models() { return []; } + static get models() { return {}; } - /** - * Verbose names for list models - * @abstract - * @type {string[]} - */ - static get names() { - return this.models.map(function(v) { - return v.verbose_name; - }); - } /** * Creates empty instance and populates it with data if given * @param {Object[]} [datalist=[]] */ constructor(datalist) { - this.data = {}; + this._root = new TreeNode({}) ; this.from(datalist || []); } /** * Fetches an object from the instance data, or creates it if * it does not exist yet.
- * Parent objects are created recursively if needed. + * If direction >= 0, parent objects are created recursively. + * If direction <= 0, child objects are created recursively. * @param {number} depth depth on the nested structure of the list * @param {Object} data */ - get_or_create(depth, data) { - var model = this.constructor.models[depth]; - var name = model.verbose_name ; - - var existing = this.data[name].find(function (v){ - return v.id === data['id'] ; - }) ; + get_or_create(data, direction=0) { + var model = this.constructor.models[data.type]; + var existing = this.find(data.type, data.content.id); if (existing) { return existing; } - if (depth == this.constructor.models.length-1) { - var created = new model(data) ; - this.data[name].push(created); - return created ; - } else { - var par_name = this.constructor.models[depth+1] - .verbose_name; + var content = new this.constructor.models[data.type](); + var node = new TreeNode(data.type, content); - var par_data = data[par_name]; - var created = new model(data); - var parnt = this.get_or_create(depth+1, par_data); - created[par_name] = parnt; - - this.data[name].push(created); - return created ; + if (direction <= 0) { + var parent = data.parent ? this.get_or_create(data.parent, -1) : this._root; + node.parent = parent; + parent.children.push(node); } + + if (direction >= 0) { + for (let child_data of data.children) { + var child = this.get_or_create(child_data, 1); + child.parent = node; + node.children.push(child); + } + } + + return node ; } /** @@ -655,7 +654,7 @@ class ModelList { } for (let data of datalist) { - this.get_or_create(0, data); + this.get_or_create(data, 0); } } @@ -728,18 +727,19 @@ class ModelList { * @param {class} model * @param {Object} props Properties to match */ - find(model, props) { - if (this.constructor.models.indexOf(model) == -1) { - return undefined ; - } + find(type, id) { + (function recurse(node) { + if (node.type === type && node.data.id === id) + return node ; - return this.data[model.verbose_name].find(function(v) { - for (let key in props) { - if (v[key] !== props[key]) - return false; + for (let child of node.children) { + var result = recurse(child) ; + if (result) + return result; } - return true; - }); + + return null; + })(this._root;) } }