diff --git a/kfet/static/kfet/js/kfet.api.js b/kfet/static/kfet/js/kfet.api.js
index 8fccf247..78289fa3 100644
--- a/kfet/static/kfet/js/kfet.api.js
+++ b/kfet/static/kfet/js/kfet.api.js
@@ -450,22 +450,28 @@ class ArticleCategory extends ModelObject {
/**
* Properties associated to a category
- * @default ['id', 'name']
+ * @default ['id', 'name', 'has_addcost', 'article']
* @see {@link Models.ModelObject.props|ModelObject.props}
*/
static get props() {
- return ['id', 'name', 'has_addcost'];
+ return ['id', 'name', 'has_addcost', 'articles'];
}
/**
* Default values for ArticleCategory model instances.
- * @default { 'id': 0, 'name': '' }
+ * @default { 'id': 0, 'name': '', 'has_addcost': true, 'articles': [] }
* @see {@link Models.ModelObject.default_data|ModelObject.default_data}
*/
static get default_data() {
- return {'id': 0, 'name': '', 'has_addcost': true};
+ return {'id': 0, 'name': '', 'has_addcost': true, 'articles': []};
}
+ /**
+ * Verbose name for ArticleCategory model
+ * @default 'category'
+ */
+ static get verbose_name() { return 'category'; }
+
/**
* @default {@link Formatters.ArticleCategoryFormatter}
*/
@@ -490,7 +496,7 @@ class ArticleCategory extends ModelObject {
class Article extends ModelObject {
/**
* Properties associated to an article
- * @default ['id', 'name']
+ * @default ['id', 'name', 'price', 'stock', 'category']
* @see {@link Models.ModelObject.props|ModelObject.props}
*/
static get props() {
@@ -510,6 +516,12 @@ class Article extends ModelObject {
};
}
+ /**
+ * Verbose name for Article model
+ * @default 'article'
+ */
+ static get verbose_name() { return 'article'; }
+
/**
* @default {@link Formatters.ArticleFormatter}
*/
@@ -535,22 +547,6 @@ class Article extends ModelObject {
}
}
-
-/**
- * Node for ModelForest object
- * @memberof Models
- */
-class TreeNode {
-
- constructor(type, content) {
- this.modelname = type;
- this.content = content;
- this.parent = null;
- this.children = [];
- }
-}
-
-
/**
* Simple {@link Models.ModelObject} forest.
* @memberof Models
@@ -558,24 +554,11 @@ class TreeNode {
class ModelForest {
/**
- * Dictionary associating types to classes
+ * Abstract structure of the forest
* @abstract
* @type {Object}
*/
- static get models() { return {}; }
-
- /**
- * Comparison function for nodes
- * @abstract
- * @param {class} model Model to use for comparison
- * @param {Models.TreeNode} a
- * @param {Models.TreeNode} b
- * @see {@link Models.ModelObject.compare|ModelObject.compare}
- */
- static compare(model, a, b) {
- return model.compare(a.content, b.content);
- }
-
+ static get structure() { return {}; }
/**
* Creates empty instance and populates it with data if given
@@ -585,6 +568,19 @@ class ModelForest {
this.from(datalist || []);
}
+ /**
+ * Shortcut functions to get parent and children of a given node
+ */
+ get_parent(node) {
+ var parent_name = this.constructor.structure[node.constructor.verbose_name].parent;
+ return node[parent_name];
+ }
+
+ get_children(node) {
+ var child_name = this.constructor.structure[node.constructor.verbose_name].children;
+ return node[child_name];
+ }
+
/**
* Fetches an object from the instance data, or creates it if
* it does not exist yet.
@@ -594,34 +590,38 @@ class ModelForest {
* @param {number} direction
*/
get_or_create(data, direction) {
- var model = this.constructor.models[data.modelname];
+ var struct_data = this.constructor.structure[data.modelname];
+ var model = struct_data.model;
- var existing = this.find_node(data.modelname, data.content.id);
+ var existing = this.find(data.modelname, data.content.id);
if (existing) {
return existing;
}
- var content = new this.constructor.models[data.modelname](data.content);
- var node = new TreeNode(data.modelname, content);
-
- if (data.child_sort)
- node.child_sort = data.child_sort
+ var node = new model(data.content);
if (direction <= 0) {
- if (data.parent) {
- var parent = this.get_or_create(data.parent, -1);
- node.parent = parent;
- parent.children.push(node);
+ var parent_name = struct_data.parent;
+ var parent_data = data.parent;
+ var parent_struct = this.constructor.structure[parent_name];
+ if (parent_data) {
+ var parent_node = this.get_or_create(parent_data, -1);
+ node[parent_name] = parent_node;
+ parent_node[parent_struct.children].push(node);
} else {
this.roots.push(node);
}
}
- if (direction >= 0 && data.children) {
- for (let child_data of data.children) {
- var child = this.get_or_create(child_data, 1);
- child.parent = node;
- node.children.push(child);
+ if (direction >= 0) {
+ var child_name = struct_data.children;
+ var child_struct = this.constructor.structure[child_name];
+ if (data.children && data.children.length) {
+ for (let child_data of data.children) {
+ var child = this.get_or_create(child_data, 1);
+ child[child_struct.parent] = node;
+ node[child_name].push(child);
+ }
}
}
@@ -654,33 +654,43 @@ class ModelForest {
* @param {Object} [options] Options for element render method
*/
render_element(node, templates, options) {
- var template = templates[node.modelname];
+ var modelname = node.constructor.verbose_name;
+ var struct_data = this.constructor.structure[modelname];
+
+ var template = templates[modelname];
var options = options || {} ;
var $container = $('