Added a lot of functionality; Fixed a large number of bugs; Removed Bootstrap from the mix and replaced it with SimpleGrid and some choice bits from the bootstrap system; Pricing, Sales, and Product management all now function at basic levels.
This commit is contained in:
@@ -1,33 +1,90 @@
|
||||
|
||||
import './Products.html';
|
||||
|
||||
let QUERY_LIMIT = 20;
|
||||
let PREFIX = "Products.";
|
||||
|
||||
Tracker.autorun(function() {
|
||||
Meteor.subscribe("products");
|
||||
Meteor.subscribe("productTags");
|
||||
Meteor.subscribe("measures");
|
||||
});
|
||||
|
||||
Template.Products.onCreated(function() {
|
||||
Session.set(PREFIX + "displayNewProduct", false);
|
||||
Session.set(PREFIX + "showHidden", false);
|
||||
});
|
||||
Template.Products.helpers({
|
||||
displayNewProduct: function() {
|
||||
return Session.get(PREFIX + "displayNewProduct");
|
||||
},
|
||||
products: function() {
|
||||
let query = Session.get('searchQuery');
|
||||
let dbQuery = {};
|
||||
let skipCount = Session.get(PREFIX + 'skipCount') || 0;
|
||||
let query = Session.get(PREFIX + 'searchQuery');
|
||||
let dbQuery = [];
|
||||
|
||||
if(query) {
|
||||
_.each(_.keys(query), function(key) {
|
||||
if(_.isFunction(query[key])) dbQuery[key] = query[key]();
|
||||
else if(_.isObject(query[key])) dbQuery[key] = query[key];
|
||||
else if(_.isNumber(query[key])) dbQuery[key] = query[key];
|
||||
else dbQuery[key] = {$regex: query[key], $options: 'i'};
|
||||
if(_.isFunction(query[key])) dbQuery.push({[key]: query[key]}); //dbQuery[key] = query[key]();
|
||||
else if(_.isObject(query[key])) dbQuery.push({[key]: query[key]}); //dbQuery[key] = query[key]; //Will look something like: {$in: [xxx,xxx,xxx]}
|
||||
else if(_.isNumber(query[key])) dbQuery.push({[key]: query[key]}); //dbQuery[key] = query[key];
|
||||
else {
|
||||
//dbQuery[key] = {$regex: query[key], $options: 'i'};
|
||||
let searchValue = query[key];
|
||||
let searches = searchValue && searchValue.length > 0 ? searchValue.split(/\s+/) : undefined;
|
||||
|
||||
for(let search of searches) {
|
||||
dbQuery.push({[key]: {$regex: '\\b' + search, $options: 'i'}});
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return Meteor.collections.Products.find(dbQuery, {limit: 20, sort: {name: 1}});
|
||||
if(!Session.get(PREFIX + "showHidden")) {
|
||||
//Ignore any hidden elements by showing those not hidden, or those without the hidden field.
|
||||
dbQuery.push({$or: [{hidden: false}, {hidden: {$exists:false}}]});
|
||||
}
|
||||
|
||||
dbQuery = dbQuery.length > 0 ? {$and: dbQuery} : {};
|
||||
Session.set(PREFIX + 'productCount', Meteor.collections.Products.find(dbQuery).count()); //Always get a full count.
|
||||
return Meteor.collections.Products.find(dbQuery, {limit: QUERY_LIMIT, skip: skipCount, sort: {name: 1}});
|
||||
},
|
||||
disablePrev: function() {
|
||||
return (Session.get(PREFIX + 'skipCount') || 0) == 0;
|
||||
},
|
||||
disableNext: function() {
|
||||
return Session.get(PREFIX + 'productCount') - (Session.get(PREFIX + 'skipCount') || 0) - QUERY_LIMIT <= 0;
|
||||
}
|
||||
});
|
||||
Template.Products.events({
|
||||
'click .prevProducts': function(event, template) {
|
||||
if(!$(event.target).hasClass('disabled'))
|
||||
Session.set(PREFIX + 'skipCount', Math.max(0, (Session.get(PREFIX + 'skipCount') || 0) - QUERY_LIMIT));
|
||||
},
|
||||
'click .nextProducts': function(event, template) {
|
||||
if(!$(event.target).hasClass('disabled'))
|
||||
Session.set(PREFIX + 'skipCount', (Session.get(PREFIX + 'skipCount') || 0) + QUERY_LIMIT);
|
||||
},
|
||||
'click .newProductButton': function(event, template) {
|
||||
if(template.$('.newProductButton').hasClass('active')) {
|
||||
Session.set(PREFIX + 'displayNewProduct', false);
|
||||
}
|
||||
else {
|
||||
Session.set(PREFIX + 'displayNewProduct', true);
|
||||
Session.set(PREFIX + "editedProduct", undefined); //Clear the edited product so that only one editor is open at a time.
|
||||
}
|
||||
template.$('.newProductButton').toggleClass('active');
|
||||
},
|
||||
'change input[name="showHidden"]': function(event, template) {
|
||||
//console.log("changed " + $(event.target).prop('checked'));
|
||||
Session.set(PREFIX + "showHidden", $(event.target).prop('checked'));
|
||||
}
|
||||
});
|
||||
|
||||
Template.ProductSearch.events({
|
||||
"keyup .searchInput": _.throttle(function(event, template) {
|
||||
let searchQuery = Session.get('searchQuery') || {};
|
||||
let searchFields = Session.get('searchFields') || {};
|
||||
let searchQuery = Session.get(PREFIX + 'searchQuery') || {};
|
||||
let searchFields = Session.get(PREFIX + 'searchFields') || {};
|
||||
let searchValue = template.$('.searchInput').val();
|
||||
|
||||
if(searchValue) {
|
||||
@@ -51,13 +108,13 @@ Template.ProductSearch.events({
|
||||
delete searchFields[this.columnName];
|
||||
}
|
||||
|
||||
Session.set('searchQuery', searchQuery);
|
||||
Session.set(PREFIX + 'searchQuery', searchQuery);
|
||||
Session.set(PREFIX + 'searchFields', searchFields);
|
||||
}, 500)
|
||||
});
|
||||
|
||||
Template.ProductSearch.helpers({
|
||||
searchValue: function() {
|
||||
let searchFields = Session.get('searchFields');
|
||||
let searchFields = Session.get(PREFIX + 'searchFields');
|
||||
|
||||
return (searchFields && searchFields[this.columnName]) ? searchFields[this.columnName] : '';
|
||||
}
|
||||
@@ -82,6 +139,9 @@ Template.Product.helpers({
|
||||
|
||||
return result;
|
||||
},
|
||||
aliases: function() {
|
||||
return this.aliases.join(', ');
|
||||
},
|
||||
tags: function() {
|
||||
let result = "";
|
||||
|
||||
@@ -99,5 +159,112 @@ Template.Product.helpers({
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
editing: function() {
|
||||
let editedProduct = Session.get(PREFIX + "editedProduct");
|
||||
|
||||
return editedProduct == this._id;
|
||||
},
|
||||
getRowClass: function() {
|
||||
return this.hidden ? "hidden" : this.deactivated ? "deactivated" : "";
|
||||
}
|
||||
});
|
||||
Template.Product.events({
|
||||
"click .actionEdit": function(event, template) {
|
||||
Session.set(PREFIX + "editedProduct", this._id);
|
||||
Session.set(PREFIX + 'displayNewProduct', false); //Ensure the new product editor is closed.
|
||||
template.$('.newProductButton').removeClass('active');
|
||||
},
|
||||
"click .actionRemove": function(event, template) {
|
||||
Meteor.call('deactivateProduct', this._id, function(error, result) {
|
||||
if(error) sAlert.error(error);
|
||||
else sAlert.success("Product Deactivated");
|
||||
});
|
||||
},
|
||||
'click .actionActivate': function(event, template) {
|
||||
Meteor.call('reactivateProduct', this._id, function(error, result) {
|
||||
if(error) sAlert.error(error);
|
||||
else sAlert.success("Product Reactivated");
|
||||
});
|
||||
},
|
||||
"click .actionShow": function(event, template) {
|
||||
Meteor.call('showProduct', this._id, function(error, result) {
|
||||
if(error) sAlert.error(error);
|
||||
else sAlert.success("Product Visibility Enabled");
|
||||
});
|
||||
},
|
||||
'click .actionHide': function(event, template) {
|
||||
Meteor.call('hideProduct', this._id, function(error, result) {
|
||||
if(error) sAlert.error(error);
|
||||
else sAlert.success("Product Visibility Disabled");
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Template.ProductEditor.onRendered(function() {
|
||||
this.$(".productTagsEditor").select2();
|
||||
this.$(".productAliasesEditor").select2({tags: true, tokenSeparators: [';', '.']});
|
||||
this.$(".productMeasuresEditor").select2();
|
||||
});
|
||||
Template.ProductEditor.helpers({
|
||||
measures: function() {
|
||||
return Meteor.collections.Measures.find({});
|
||||
},
|
||||
measureSelected: function() {
|
||||
let measure = this;
|
||||
let product = Template.parentData();
|
||||
|
||||
return product.measures && product.measures.includes(measure._id) ? "selected" : "";
|
||||
},
|
||||
aliases: function() {
|
||||
return this.aliases;
|
||||
},
|
||||
tags: function() {
|
||||
return Meteor.collections.ProductTags.find({});
|
||||
},
|
||||
tagSelected: function() {
|
||||
let tag = this;
|
||||
let product = Template.parentData();
|
||||
|
||||
return product.tags && product.tags.includes(tag._id) ? "selected" : "";
|
||||
}
|
||||
});
|
||||
Template.ProductEditor.events({
|
||||
"click .editorCancel": function(event, template) {
|
||||
Session.set(PREFIX + "editedProduct", undefined);
|
||||
Session.set(PREFIX + 'displayNewProduct', false);
|
||||
template.$('.newProductButton').removeClass('active');
|
||||
},
|
||||
"click .editorApply": function(event, template) {
|
||||
let name = template.$("input[name='name']").val().trim();
|
||||
let tags = template.$(".productTagsEditor").select2('data');
|
||||
let aliases = template.$(".productAliasesEditor").select2('data');
|
||||
let measures = template.$(".productMeasuresEditor").select2('data');
|
||||
|
||||
tags = tags.map((n)=>n.id);
|
||||
aliases = aliases.map((n)=>n.id);
|
||||
measures = measures.map((n)=>n.id);
|
||||
|
||||
if(Session.get(PREFIX + 'displayNewProduct')) {
|
||||
Meteor.call("createProduct", name, tags, aliases, measures, function(error, result) {
|
||||
if(error) sAlert.error(error);
|
||||
else {
|
||||
sAlert.success("Product created.");
|
||||
Session.set(PREFIX + 'displayNewProduct', false);
|
||||
template.$('.newProductButton').removeClass('active');
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
Meteor.call("updateProduct", this._id, name, tags, aliases, measures, function(error, result) {
|
||||
if(error) sAlert.error(error);
|
||||
else {
|
||||
sAlert.success("Product updated.");
|
||||
Session.set(PREFIX + "editedProduct", undefined);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user