Merge branch 'Aufinal/refactor_articles' into Aufinal/refactor_history
This commit is contained in:
commit
11603cee69
5 changed files with 219 additions and 199 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -71,8 +71,10 @@ class Config {
|
|||
* A model subclasses {@link Models.ModelObject}.<br>
|
||||
* A model whose instances can be got from API subclasses
|
||||
* {@link Models.APIModelObject}.<br>
|
||||
* A model to manage ModelObject lists
|
||||
* {@link Models.ModelList}.<br>
|
||||
* A model to manage ModelObject forests
|
||||
* {@link Models.ModelForest}.<br>
|
||||
* A ModelObject that can be fetched through API
|
||||
* {@link Models.APIModelForest}.<br>
|
||||
* These classes should not be used directly.
|
||||
* <br><br>
|
||||
*
|
||||
|
@ -81,7 +83,9 @@ class Config {
|
|||
* {@link Models.Checkout} (partial).
|
||||
* <br>
|
||||
* Models without API support:
|
||||
* {@link Models.Statement}.
|
||||
* {@link Models.Statement},
|
||||
* {@link Models.ArticleCategory},
|
||||
* {@link Models.Article}.
|
||||
*
|
||||
* @namespace Models
|
||||
*/
|
||||
|
@ -107,13 +111,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
|
||||
|
@ -171,15 +168,12 @@ class ModelObject {
|
|||
}
|
||||
|
||||
/**
|
||||
* Compare function between two instances of the model
|
||||
* @abstract
|
||||
* @param {a} Models.ModelObject
|
||||
* @param {b} Models.ModelObject
|
||||
* Returns a string value for the model, to use in comparisons
|
||||
* @see {@link Models.TreeNode.compare|TreeNode.compare}
|
||||
*/
|
||||
static compare(a, b) {
|
||||
return a.id - b.id ;
|
||||
comparevalue() {
|
||||
return this.id.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -493,13 +487,6 @@ class ArticleCategory extends ModelObject {
|
|||
return {'id': 0, 'name': ''};
|
||||
}
|
||||
|
||||
/**
|
||||
* Verbose name for ArticleCategory model.
|
||||
* @default <tt>'article_category'</tt>
|
||||
* @see {@link Models.ModelObject.verbose_name[ModelObject.verbose_name}
|
||||
*/
|
||||
static get verbose_name() { return 'category'; }
|
||||
|
||||
/**
|
||||
* @default {@link Formatters.ArticleCategoryFormatter}
|
||||
*/
|
||||
|
@ -511,8 +498,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 +531,6 @@ class Article extends ModelObject {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Verbose name for Article model
|
||||
* @default <tt>'article'</tt>
|
||||
* @see {@link Models.ModelObject.verbose_name|ModelObject.verbose_name}
|
||||
*/
|
||||
static get verbose_name() { return 'article'; }
|
||||
|
||||
/**
|
||||
* @default {@link Formatters.ArticleFormatter}
|
||||
*/
|
||||
|
@ -562,8 +542,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 this.name;
|
||||
}
|
||||
|
||||
// Take care of 'price' type
|
||||
|
@ -757,136 +737,148 @@ class Operation extends ModelObject {
|
|||
|
||||
|
||||
/**
|
||||
* Simple {@link Models.ModelObject} list.
|
||||
* Node for ModelForest object
|
||||
* @memberof Models
|
||||
*/
|
||||
class ModelList {
|
||||
|
||||
/**
|
||||
* Nested structure of the list
|
||||
* @abstract
|
||||
* @type {Models.ModelObject[]}
|
||||
*/
|
||||
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;
|
||||
});
|
||||
class TreeNode {
|
||||
|
||||
constructor(type, content) {
|
||||
this.type = type;
|
||||
this.content = content;
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Simple {@link Models.ModelObject} forest.
|
||||
* @memberof Models
|
||||
*/
|
||||
class ModelForest {
|
||||
|
||||
/**
|
||||
* Dictionary associating types to classes
|
||||
* @abstract
|
||||
* @type {Object}
|
||||
*/
|
||||
static get models() { return {}; }
|
||||
|
||||
|
||||
/**
|
||||
* Creates empty instance and populates it with data if given
|
||||
* @param {Object[]} [datalist=[]]
|
||||
*/
|
||||
constructor(datalist) {
|
||||
this.data = {};
|
||||
this.from(datalist || []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches an object from the instance data, or creates it if
|
||||
* it does not exist yet.<br>
|
||||
* Parent objects are created recursively if needed.
|
||||
* @param {number} depth depth on the nested structure of the list
|
||||
* If direction >= 0, parent objects are created recursively.
|
||||
* If direction <= 0, child objects are created recursively.
|
||||
* @param {Object} data
|
||||
* @param {number} direction
|
||||
*/
|
||||
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) {
|
||||
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](data.content);
|
||||
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) {
|
||||
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 && 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);
|
||||
}
|
||||
}
|
||||
|
||||
return node ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets then populates the instance with the given data, starting from
|
||||
* the lowest level Models.ModelObject in {@link Models.ModelList#models|models}.<br>
|
||||
* 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(0, data);
|
||||
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);
|
||||
// Allows for more granular template specification
|
||||
var template = templates[elt.type] || templates[name];
|
||||
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 = $('<div></div>');
|
||||
$container.attr('id', node.type+'-'+node.content.id);
|
||||
|
||||
//TODO: less dirty
|
||||
var $container = $('<div></div>');
|
||||
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(TreeNode.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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -896,44 +888,53 @@ class ModelList {
|
|||
* @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(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(model, props) {
|
||||
if (this.constructor.models.indexOf(model) == -1) {
|
||||
return undefined ;
|
||||
find(type, id) {
|
||||
var result = null;
|
||||
function callback(node) {
|
||||
if (node.type === type && node.content.id == id)
|
||||
result = node ;
|
||||
}
|
||||
|
||||
return this.data[model.verbose_name].find(function(v) {
|
||||
for (let key in props) {
|
||||
if (v[key] !== props[key])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
this.traverse(callback);
|
||||
|
||||
return result ;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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.
|
||||
|
@ -944,7 +945,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.
|
||||
|
@ -970,24 +971,26 @@ 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
|
||||
* @default <tt>[Article, ArticleCategory]</tt>
|
||||
* @see {@link Models.ModelList.models|ModelList.models}
|
||||
* @abstract
|
||||
* @default <tt>{'article': Article,
|
||||
'category': ArticleCategory}</tt>
|
||||
*/
|
||||
static get models() {
|
||||
return [Article, ArticleCategory];
|
||||
return {'article': Article,
|
||||
'category': ArticleCategory};
|
||||
}
|
||||
|
||||
/**
|
||||
* Default url to get ArticleList data
|
||||
* @default <tt>django-js-reverse('kfet.kpsul.articles_data')</tt>
|
||||
* @see {@link Models.APIModelList.url_model|APIModelList.url_model}
|
||||
* @see {@link Models.APIModelForest.url_model|APIModelForest.url_model}
|
||||
*/
|
||||
static get url_model() {
|
||||
return Urls['kfet.kpsul.articles_data']();
|
||||
|
|
|
@ -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': '<tr class="category"><td class="name" colspan="3"></td></tr>',
|
||||
'article' : '<tr class="article"><td class="name"></td><td class="price"></td><td class="stock"></td></tr>'}
|
||||
this.templates = {'category': '<div class="category"><span class="name"></span></div>',
|
||||
'article' : '<div class="article"><span class="name"></span><span class="price"></span><span class="stock"></span></div>'}
|
||||
|
||||
this.selected = new Article() ;
|
||||
this.list = new ArticleList() ;
|
||||
|
@ -410,19 +410,19 @@ class ArticleManager {
|
|||
}
|
||||
|
||||
reset_data() {
|
||||
this._$container.find('tr').remove();
|
||||
this._$container.html('');
|
||||
this.list.clear();
|
||||
this.list.fromAPI({}, this.display_list.bind(this), $.noop) ;
|
||||
}
|
||||
|
||||
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']);
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -488,8 +489,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 +522,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 +554,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 +581,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': []};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -131,10 +131,6 @@
|
|||
<input type="hidden" id="article_id" value="">
|
||||
</div>
|
||||
<div id="articles_data">
|
||||
<table>
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row kpsul_middle_left_bottom">
|
||||
|
@ -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();
|
||||
});
|
||||
|
|
|
@ -1479,13 +1479,19 @@ def kpsul_articles_data(request):
|
|||
|
||||
for article in articles:
|
||||
articlelist.append({
|
||||
'id': article.id,
|
||||
'name': article.name,
|
||||
'price': article.price,
|
||||
'stock': article.stock,
|
||||
'category': {
|
||||
'id': article.category.id,
|
||||
'name': article.category.name,
|
||||
'type': 'article',
|
||||
'content': {
|
||||
'id': article.id,
|
||||
'name': article.name,
|
||||
'price': article.price,
|
||||
'stock': article.stock,
|
||||
},
|
||||
'parent': {
|
||||
'type': 'category',
|
||||
'content': {
|
||||
'id': article.category.id,
|
||||
'name': article.category.name,
|
||||
},
|
||||
}
|
||||
})
|
||||
return JsonResponse(articlelist, safe=False)
|
||||
|
|
Loading…
Reference in a new issue