From 02485afd9ba652ac3dc6697b96354d75bfbc2120 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Fri, 10 Mar 2017 19:59:15 -0300 Subject: [PATCH 01/13] doc and compare function --- kfet/static/kfet/js/kfet.api.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/kfet/static/kfet/js/kfet.api.js b/kfet/static/kfet/js/kfet.api.js index 2a0c398b..81f0cfe4 100644 --- a/kfet/static/kfet/js/kfet.api.js +++ b/kfet/static/kfet/js/kfet.api.js @@ -547,17 +547,25 @@ class Article extends ModelObject { /** * Verbose name for Article model * @default 'article' - * @see {@link Models.ModelObject.compare|ModelObject.compare} + * @see {@link Models.ModelObject.verbose_name|ModelObject.verbose_name} */ static get verbose_name() { return 'article'; } /** - * @default {@link Formatters.ArticleCategoryFormatter} + * @default {@link Formatters.ArticleFormatter} */ formatter() { return ArticleFormatter; } + /** + * Comparison function between Article model instances. + * @see {@link Models.ModelObject.compare|ModelObject.compare} + */ + static compare(a, b) { + return a.name.localeCompare(b.name); + } + // Take care of 'price' type // API currently returns a string object (serialization of Decimal type within Django) get price() { return this._price; } From 0219d998ac97b44a51a04f1bc3e5db9e2a6f98f1 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Wed, 15 Mar 2017 02:45:13 -0300 Subject: [PATCH 02/13] model tree struct draft --- kfet/static/kfet/js/kfet.api.js | 92 ++++++++++++++++----------------- 1 file changed, 46 insertions(+), 46 deletions(-) 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;) } } From 1570d9f49446e6939a786dd27d4471d78004741b Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Wed, 15 Mar 2017 22:10:56 -0300 Subject: [PATCH 03/13] Polish ModelForest class --- kfet/static/kfet/js/kfet.api.js | 177 ++++++++++++++++---------------- 1 file changed, 90 insertions(+), 87 deletions(-) diff --git a/kfet/static/kfet/js/kfet.api.js b/kfet/static/kfet/js/kfet.api.js index e0bc2c35..a655786d 100644 --- a/kfet/static/kfet/js/kfet.api.js +++ b/kfet/static/kfet/js/kfet.api.js @@ -107,13 +107,6 @@ class ModelObject { */ static get default_data() { return {}; } - /** - * Verbose name so refer to this model - * @abstract - * @type {string} - */ - static get verbose_name() { return ""; } - /** * Create new instance from data or default values. * @param {Object} [data={}] - data to store in instance @@ -170,14 +163,24 @@ class ModelObject { return formatter.render(this, $container, options); } + /** + * Returns a string value for the model, to use in comparisons + * @see {@link Models.ModelObject.compare|ModelObject.compare} + */ + comparevalue() { + return this.id.toString(); + } + /** * Compare function between two instances of the model + * by serializing them using comparevalue(). * @abstract * @param {a} Models.ModelObject * @param {b} Models.ModelObject + * @see {@link Models.ModelObject.comparevalue|ModelObject.comparevalue} */ static compare(a, b) { - return a.id - b.id ; + return a.comparevalue().localeCompare(b.comparevalue()); } } @@ -493,13 +496,6 @@ class ArticleCategory extends ModelObject { return {'id': 0, 'name': ''}; } - /** - * Verbose name for ArticleCategory model. - * @default 'article_category' - * @see {@link Models.ModelObject.verbose_name[ModelObject.verbose_name} - */ - static get verbose_name() { return 'category'; } - /** * @default {@link Formatters.ArticleCategoryFormatter} */ @@ -511,8 +507,8 @@ class ArticleCategory extends ModelObject { * Comparison function between ArticleCategory model instances. * @see {@link Models.ModelObject.compare|ModelObject.compare} */ - static compare(a, b) { - return a.name.localeCompare(b.name); + comparevalue() { + return this.name ; } } @@ -544,13 +540,6 @@ class Article extends ModelObject { }; } - /** - * Verbose name for Article model - * @default 'article' - * @see {@link Models.ModelObject.verbose_name|ModelObject.verbose_name} - */ - static get verbose_name() { return 'article'; } - /** * @default {@link Formatters.ArticleFormatter} */ @@ -562,8 +551,8 @@ class Article extends ModelObject { * Comparison function between Article model instances. * @see {@link Models.ModelObject.compare|ModelObject.compare} */ - static compare(a, b) { - return a.name.localeCompare(b.name); + comparevalue() { + return a.name; } // Take care of 'price' type @@ -572,6 +561,11 @@ class Article extends ModelObject { set price(v) { this._price = floatCheck(v); } } + +/** + * Node for ModelForest object + * @memberof Models + */ class TreeNode { constructor(type, content) { @@ -584,15 +578,15 @@ class TreeNode { /** - * Simple {@link Models.ModelObject} list. + * Simple {@link Models.ModelObject} forest. * @memberof Models */ -class ModelTree { +class ModelForest { /** - * Nested structure of the list + * Dictionary associating types to classes * @abstract - * @type {Models.ModelObject[]} + * @type {Object} */ static get models() { return {}; } @@ -602,7 +596,6 @@ class ModelTree { * @param {Object[]} [datalist=[]] */ constructor(datalist) { - this._root = new TreeNode({}) ; this.from(datalist || []); } @@ -611,10 +604,10 @@ class ModelTree { * it does not exist yet.
* 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 + * @param {number} direction */ - get_or_create(data, direction=0) { + get_or_create(data, direction) { var model = this.constructor.models[data.type]; var existing = this.find(data.type, data.content.id); @@ -622,13 +615,17 @@ class ModelTree { return existing; } - var content = new this.constructor.models[data.type](); + var content = new this.constructor.models[data.type](data.content); var node = new TreeNode(data.type, content); if (direction <= 0) { - var parent = data.parent ? this.get_or_create(data.parent, -1) : this._root; - node.parent = parent; - parent.children.push(node); + if (data.parent) { + var parent = this.get_or_create(data.parent, -1); + node.parent = parent; + parent.children.push(node); + } else { + this.roots.push(node); + } } if (direction >= 0) { @@ -643,65 +640,64 @@ class ModelTree { } /** - * Resets then populates the instance with the given data, starting from - * the lowest level Models.ModelObject in {@link Models.ModelList#models|models}.
+ * Resets then populates the instance with the given data. * @param {Object[]} datalist */ from(datalist) { - - for (let key of this.constructor.names) { - this.data[key] = []; - } - + this.roots = []; for (let data of datalist) { this.get_or_create(data, 0); } } /** - * Removes all Models.ModelObject from the list. + * Removes all Models.TreeNode from the tree. */ clear() { this.from([]); } /** - * Renders an element (and all its offspring) and returns the + * Renders a node (and all its offspring) and returns the * corresponding jQuery object. - * @param {Models.ModelObject} elt + * @param {Models.TreeNode} node * @param {Object} templates Templates to render each model * @param {Object} [options] Options for element render method */ - render_element(elt, templates, options) { - var name = elt.constructor.verbose_name; - var depth = this.constructor.names.indexOf(name); - var template = templates[name]; - var options = options || {} ; + render_element(node, templates, options) { + var template = templates[node.type]; + var options = options || {} ; - if (depth == -1) { - return $(); - } else if (depth == 0) { - var $rendered = elt.display($(template), options); - $rendered.attr('data-'+name+'-id', elt.id); - return $rendered; - } else { - var child_model = this.constructor.models[depth-1]; - var children = this.data[child_model.verbose_name] - .filter(v => v[name].id == elt.id) ; - children.sort(child_model.compare); + var $container = $('
'); + $container.attr('id', node.type+'-'+node.content.id); - //TODO: less dirty - var $container = $('
'); - var $elt = elt.display($(template), options); - $elt.attr('data-'+name+'-id', elt.id); - $container.append($elt); + var $rendered = node.content.display($(template), options); + $container.append($rendered); - for (let child of children) { - $container.append(this.render_element(child, templates, options)); - } + //TODO: better sorting control + node.children.sort(ModelObject.compare); - return $container.html(); + for (let child of node.children) { + var $child = this.render_element(child, templates, options); + $container.append($child); } + + return $container; + } + + add_to_container($container, node, templates, options) { + var existing = node.parent ; + var first_missing = node; + + while (existing && !($container.find('#'+existing.type+'-'+existing.id))) { + first_missing = existing ; + existing = existing.parent; + } + + var $to_insert = render_element(first_missing, templates, options); + var $insert_in = existing ? $container.find('#'+existing.type+'-'+existing.id) + : $container ; + $insert_in.prepend($to_insert); } /** @@ -711,9 +707,7 @@ class ModelTree { * @param {Object} [options] Options for element render method */ display($container, templates, options) { - var root_model = this.constructor.models[this.constructor.models.length-1]; - var roots = this.data[root_model.verbose_name]; - roots.sort(root_model.compare); + this.roots.sort(ModelObject.compare); for (let root of roots) { $container.append(this.render_element(root, templates, options)); @@ -728,28 +722,35 @@ class ModelTree { * @param {Object} props Properties to match */ find(type, id) { - (function recurse(node) { + + function recurse(node) { if (node.type === type && node.data.id === id) return node ; for (let child of node.children) { - var result = recurse(child) ; - if (result) + if (result = recurse(node)) return result; } return null; - })(this._root;) + } + + for (let root of this.roots) { + if (result = recurse(root)) + return result; + } + + return null ; } } /** * Describes a model list that can be filled through API. - * @extends Models.ModelList + * @extends Models.ModelForest * @memberof Models */ -class APIModelList extends ModelList { +class APIModelForest extends ModelForest { /** * Request url to fill the model. @@ -760,7 +761,7 @@ class APIModelList extends ModelList { /** * Fills the instance with distant data. It sends a GET HTTP request to - * {@link Models.APIModelList#url_model}. + * {@link Models.APIModelForest#url_model}. * @param {object} [api_options] Additional data appended to the request. * @param {jQueryAjaxSuccess} [on_success] A function to be called if the request succeeds. * @param {jQueryAjaxError} [on_error] A function to be called if the request fails. @@ -786,25 +787,27 @@ class APIModelList extends ModelList { /** * ArticleList model. Can be accessed through API. - * @extends Models.APIModelList + * @extends Models.APIModelForest * @memberof Models */ -class ArticleList extends APIModelList { +class ArticleList extends APIModelForest { /** * Default structure for ArticleList instances * @abstract - * @default [Article, ArticleCategory] + * @default {'article': Article, + 'category': ArticleCategory} */ static get models() { - return [Article, ArticleCategory]; + return {'article': Article, + 'category': ArticleCategory}; } /** * Default url to get ArticlList data * @abstract * @default django-js-reverse('kfet.kpsul.articles_data') - * @see {@link Models.APIModelList.url_model|APIModelList.url_model} + * @see {@link Models.APIModelForest.url_model|APIModelList.url_model} */ static get url_model() { return Urls['kfet.kpsul.articles_data'](); From fe6823fc7bc9f8e96afb916880af33e15c60d27b Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Wed, 15 Mar 2017 22:39:30 -0300 Subject: [PATCH 04/13] Adapt article_data return value to ModelTree standards --- kfet/views.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/kfet/views.py b/kfet/views.py index 4b356d43..93557157 100644 --- a/kfet/views.py +++ b/kfet/views.py @@ -1349,11 +1349,14 @@ def kpsul_articles_data(request): for article in articles: articlelist.append({ - 'id': article.id, - 'name': article.name, - 'price': article.price, - 'stock': article.stock, - 'category': { + 'type': 'article', + 'content': { + 'id': article.id, + 'name': article.name, + 'price': article.price, + 'stock': article.stock, + }, + 'parent': { 'id': article.category.id, 'name': article.category.name, } From 08d1521d8160ede23e6dd702b2d69a4551d6c536 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Wed, 15 Mar 2017 22:40:06 -0300 Subject: [PATCH 05/13] Adapt ArticleManagerto new API --- kfet/static/kfet/js/kpsul.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kfet/static/kfet/js/kpsul.js b/kfet/static/kfet/js/kpsul.js index 238a40a6..9d5515b2 100644 --- a/kfet/static/kfet/js/kpsul.js +++ b/kfet/static/kfet/js/kpsul.js @@ -417,12 +417,12 @@ class ArticleManager { update_data(data) { for (let article_dict of data) { - article = this.list.find(Article, {'id': article_dict['id']}); + article = this.list.find('article', article_dict['id']); // For now, article additions are disregarded if (article) { article.stock = article_dict['stock']; - this._$container.find('#data-article-'+article_dict['id']+' .stock') + this._$container.find('#article-'+article_dict['id']+' .stock') .text(article_dict['stock']); } } From 3d760794391b5565127ab315268412e750a9dc9e Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Thu, 16 Mar 2017 01:20:06 -0300 Subject: [PATCH 06/13] Add correct syntax to category data --- kfet/views.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/kfet/views.py b/kfet/views.py index 93557157..1c6042e4 100644 --- a/kfet/views.py +++ b/kfet/views.py @@ -1357,8 +1357,11 @@ def kpsul_articles_data(request): 'stock': article.stock, }, 'parent': { - 'id': article.category.id, - 'name': article.category.name, + 'type': 'category', + 'content': { + 'id': article.category.id, + 'name': article.category.name, + }, } }) return JsonResponse(articlelist, safe=False) From 770c185bd07934334f6cb823bae6bf071d7b27c4 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Thu, 16 Mar 2017 01:21:18 -0300 Subject: [PATCH 07/13] Modify sort in ModelTree --- kfet/static/kfet/js/kfet.api.js | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/kfet/static/kfet/js/kfet.api.js b/kfet/static/kfet/js/kfet.api.js index a655786d..1339f284 100644 --- a/kfet/static/kfet/js/kfet.api.js +++ b/kfet/static/kfet/js/kfet.api.js @@ -165,24 +165,11 @@ class ModelObject { /** * Returns a string value for the model, to use in comparisons - * @see {@link Models.ModelObject.compare|ModelObject.compare} + * @see {@link Models.TreeNode.compare|TreeNode.compare} */ comparevalue() { return this.id.toString(); } - - /** - * Compare function between two instances of the model - * by serializing them using comparevalue(). - * @abstract - * @param {a} Models.ModelObject - * @param {b} Models.ModelObject - * @see {@link Models.ModelObject.comparevalue|ModelObject.comparevalue} - */ - static compare(a, b) { - return a.comparevalue().localeCompare(b.comparevalue()); - } - } @@ -552,7 +539,7 @@ class Article extends ModelObject { * @see {@link Models.ModelObject.compare|ModelObject.compare} */ comparevalue() { - return a.name; + return this.name; } // Take care of 'price' type @@ -574,6 +561,13 @@ class TreeNode { this.parent = null; this.children = []; } + + static compare(a, b) { + var a_serial = a.content.comparevalue(); + var b_serial = b.content.comparevalue(); + + return a_serial.localeCompare(b_serial) + } } From 2ce96bce1be54ea057283cb5015c71114ea0302e Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Thu, 16 Mar 2017 01:21:50 -0300 Subject: [PATCH 08/13] Add traverse function to ModelTree --- kfet/static/kfet/js/kfet.api.js | 43 ++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/kfet/static/kfet/js/kfet.api.js b/kfet/static/kfet/js/kfet.api.js index 1339f284..409c61a5 100644 --- a/kfet/static/kfet/js/kfet.api.js +++ b/kfet/static/kfet/js/kfet.api.js @@ -622,7 +622,7 @@ class ModelForest { } } - if (direction >= 0) { + if (direction >= 0 && data.children) { for (let child_data of data.children) { var child = this.get_or_create(child_data, 1); child.parent = node; @@ -669,7 +669,7 @@ class ModelForest { $container.append($rendered); //TODO: better sorting control - node.children.sort(ModelObject.compare); + node.children.sort(TreeNode.compare); for (let child of node.children) { var $child = this.render_element(child, templates, options); @@ -701,40 +701,43 @@ class ModelForest { * @param {Object} [options] Options for element render method */ display($container, templates, options) { - this.roots.sort(ModelObject.compare); + this.roots.sort(TreeNode.compare); - for (let root of roots) { + for (let root of this.roots) { $container.append(this.render_element(root, templates, options)); } return $container; } + traverse(callback) { + function recurse(node) { + callback(node) ; + + for (let child of node.children) + callback(child); + } + + for (let root of this.roots) + recurse(root); + } + /** * Find instance in data matching given properties. * @param {class} model * @param {Object} props Properties to match */ find(type, id) { - - function recurse(node) { - if (node.type === type && node.data.id === id) - return node ; - - for (let child of node.children) { - if (result = recurse(node)) - return result; - } - - return null; + var result = null; + function callback(node) { + if (node.type === type && node.content.id == id) + result = node ; } - for (let root of this.roots) { - if (result = recurse(root)) - return result; - } + this.traverse(callback); + + return result ; - return null ; } } From 01295d464d1ffd8073fe475ae57ef0a1e782758e Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Thu, 16 Mar 2017 01:22:46 -0300 Subject: [PATCH 09/13] Adapt ArticleAutocomplete to new format --- kfet/static/kfet/js/kpsul.js | 66 ++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/kfet/static/kfet/js/kpsul.js b/kfet/static/kfet/js/kpsul.js index 9d5515b2..e3621dee 100644 --- a/kfet/static/kfet/js/kpsul.js +++ b/kfet/static/kfet/js/kpsul.js @@ -488,8 +488,6 @@ class ArticleAutocomplete { constructor(article_manager) { this.manager = article_manager; - this.matching = []; - this.active_categories = []; this._$container = article_manager._$container ; this._$input = $('#article_autocomplete'); @@ -523,31 +521,30 @@ class ArticleAutocomplete { update(prefix, backspace) { + this.resetMatch(); var article_list = this.manager.list ; var lower = prefix.toLowerCase() ; var that = this ; - this.matching = article_list.data['article'] - .filter(function(article) { - return article.name.toLowerCase() - .indexOf(lower) === 0 ; + + article_list.traverse(function(node) { + if (node.type === 'article' && + node.content.name.toLowerCase() + .startsWith(lower)) { + that.matching['article'].push(node.content); + if (that.matching['category'].indexOf(node.parent.content) == -1) + that.matching['category'].push(node.parent.content); + } }); - this.active_categories = article_list.data['category'] - .filter(function(category) { - return that.matching.find(function(article) { - return article.category === category ; - }); - }); - - if (this.matching.length == 1) { + if (this.matching['article'].length == 1) { if (!backspace) { - this.manager.validate(this.matching[0]) ; + this.manager.validate(this.matching['article'][0]) ; this.showAll() ; } else { this.manager.unset(); this.updateDisplay(); } - } else if (this.matching.length > 1) { + } else if (this.matching['article'].length > 1) { this.manager.unset(); this.updateDisplay() ; if (!backspace) @@ -556,26 +553,21 @@ class ArticleAutocomplete { } updateDisplay() { - var article_list = this.manager.list ; - for (let article of article_list.data['article']) { - if (this.matching.indexOf(article) > -1) { - this._$container.find('[data-article-id='+article.id+']').show(); - } else { - this._$container.find('[data-article-id='+article.id+']').hide(); - } - } + var that = this; - for (let category of article_list.data['category']) { - if (this.active_categories.indexOf(category) > -1) { - this._$container.find('[data-category-id='+category.id+']').show(); - } else { - this._$container.find('[data-category-id='+category.id+']').hide(); + this.manager.list.traverse(function(node) { + if (that.matching[node.type].indexOf(node.content) != -1) { + that._$container.find('#'+node.type+'-'+node.content.id) + .show(); + } else { + that._$container.find('#'+node.type+'-'+node.content.id) + .hide(); } - } + }); } updatePrefix() { - var lower = this.matching.map(function (article) { + var lower = this.matching['article'].map(function (article) { return article.name.toLowerCase() ; }); @@ -588,8 +580,16 @@ class ArticleAutocomplete { } showAll() { - this.matching = this.manager.list.data['article']; - this.active_categories = this.manager.list.data['category']; + var that = this; + this.resetMatch(); + this.manager.list.traverse(function(node) { + that.matching[node.type].push(node.content); + }); this.updateDisplay(); } + + resetMatch() { + this.matching = {'article' : [], + 'category': []}; + } } From f0a80561edaba1b6ce0ed2a32886fa803853a9fb Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Thu, 16 Mar 2017 22:24:57 -0300 Subject: [PATCH 10/13] Add article display to Config callback --- kfet/templates/kfet/kpsul.html | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/kfet/templates/kfet/kpsul.html b/kfet/templates/kfet/kpsul.html index 43a55dd2..31714bdb 100644 --- a/kfet/templates/kfet/kpsul.html +++ b/kfet/templates/kfet/kpsul.html @@ -131,10 +131,6 @@
- - - -
@@ -833,10 +829,10 @@ $(document).ready(function() { function hardReset(give_tri_focus=true) { coolReset(give_tri_focus); kpsul.checkout_manager.reset(); - kpsul.article_manager.reset_data(); resetPreviousOp(); khistory.reset(); Config.reset(function() { + kpsul.article_manager.reset_data(); displayAddcost(); getHistory(); }); From 1c5ac561a3b019ae4c12d8e0f39490d42e5b4e29 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Thu, 16 Mar 2017 22:26:08 -0300 Subject: [PATCH 11/13] Change article table into divs --- kfet/static/kfet/css/kpsul.css | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/kfet/static/kfet/css/kpsul.css b/kfet/static/kfet/css/kpsul.css index 3d8c63f4..371331c0 100644 --- a/kfet/static/kfet/css/kpsul.css +++ b/kfet/static/kfet/css/kpsul.css @@ -296,30 +296,44 @@ input[type=number]::-webkit-outer-spin-button { #articles_data { overflow:auto; max-height:500px; -} - -#articles_data table { width: 100%; } -#articles_data table tr.article { +#articles_data div.article { height:25px; font-size:14px; } -#articles_data table tr.article>td:first-child { - padding-left:10px; +#articles_data span { + height:25px; + line-height:25px; + display: inline-block; } -#articles_data table tr.category { +#articles_data span.name { + padding-left:10px; + width:78%; +} + +#articles_data span.price { + width:8%; +} + +#articles_data span.stock { + width:14%; +} + + +#articles_data div.category { height:35px; + line-height:35px; background-color:#c8102e; font-size:16px; color:#FFF; font-weight:bold; } -#articles_data table tr.category>td:first-child { +#articles_data div.category>span:first-child { padding-left:20px; } From 91f14deda1c783eb5daccdadcbf6bb90f1bc9b3f Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Thu, 16 Mar 2017 22:26:30 -0300 Subject: [PATCH 12/13] last tweaks and doc --- kfet/static/kfet/js/kfet.api.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/kfet/static/kfet/js/kfet.api.js b/kfet/static/kfet/js/kfet.api.js index 409c61a5..8a3e0951 100644 --- a/kfet/static/kfet/js/kfet.api.js +++ b/kfet/static/kfet/js/kfet.api.js @@ -71,8 +71,10 @@ class Config { * A model subclasses {@link Models.ModelObject}.
* A model whose instances can be got from API subclasses * {@link Models.APIModelObject}.
- * A model to manage ModelObject lists - * {@link Models.ModelList}.
+ * A model to manage ModelObject forests + * {@link Models.ModelForest}.
+ * A ModelObject that can be fetched through API + * {@link Models.APIModelForest}.
* These classes should not be used directly. *

* @@ -81,7 +83,9 @@ class Config { * {@link Models.Checkout} (partial). *
* Models without API support: - * {@link Models.Statement}. + * {@link Models.Statement}, + * {@link Models.ArticleCategory}, + * {@link Models.Article}. * * @namespace Models */ @@ -804,7 +808,7 @@ class ArticleList extends APIModelForest { * Default url to get ArticlList data * @abstract * @default django-js-reverse('kfet.kpsul.articles_data') - * @see {@link Models.APIModelForest.url_model|APIModelList.url_model} + * @see {@link Models.APIModelForest.url_model|APIModelForest.url_model} */ static get url_model() { return Urls['kfet.kpsul.articles_data'](); From 9ab2a11432bfc026f32c03d7639af8175f88f461 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Thu, 16 Mar 2017 22:26:59 -0300 Subject: [PATCH 13/13] Finish adapting ArticleManager and Autocomplete --- kfet/static/kfet/js/kpsul.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/kfet/static/kfet/js/kpsul.js b/kfet/static/kfet/js/kpsul.js index e3621dee..b2b4c5fa 100644 --- a/kfet/static/kfet/js/kpsul.js +++ b/kfet/static/kfet/js/kpsul.js @@ -373,11 +373,11 @@ class ArticleManager { constructor(env) { this._env = env; // Global K-Psul Manager - this._$container = $('#articles_data tbody'); + this._$container = $('#articles_data'); this._$input = $('#article_autocomplete'); this._$nb = $('#article_number'); - this.templates = {'category': '', - 'article' : ''} + this.templates = {'category': '
', + 'article' : '
'} this.selected = new Article() ; this.list = new ArticleList() ; @@ -410,7 +410,7 @@ class ArticleManager { } reset_data() { - this._$container.find('tr').remove(); + this._$container.html(''); this.list.clear(); this.list.fromAPI({}, this.display_list.bind(this), $.noop) ; } @@ -450,10 +450,11 @@ class ArticleManager { }); this._$container.on('click', '.article', function() { - var id = $(this).attr('data-article-id') ; - var article = that.list.find(Article, { 'id': intCheck(id) }); + var id = $(this).parent().attr('id').split('-')[1]; + console.log(id); + var article = that.list.find('article', id); if (article) - that.validate(article); + that.validate(article.content); }); this._$nb.on('keydown', function(e) {