Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .meteor/packages
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,5 @@ reactioncommerce:default-theme # default Reaction theme
# Forced updates on packages
mdg:[email protected]
cosmos:[email protected]

ramusus:reaction-filtration
4 changes: 4 additions & 0 deletions .meteor/versions
2 changes: 2 additions & 0 deletions packages/reaction-collections/package.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Package.onUse(function (api) {
api.use("ongoworks:[email protected]");
api.use("alanning:[email protected]");
api.use("meteorhacks:[email protected]");
api.use("tmeasday:[email protected]");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This package doesn't seem to be very well maintained,(source has deprecated Meteor code) and warns This package is designed primarily for correctness, not performance. That's why it's aimed at counting smaller datasets and keeping the count instantly up to date. Is this the best choice?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree completely, this notice also make me hesitate about using it. I will try to find another way of getting reactive count value.


// ReactionCore declaration
api.addFiles("common/globals.js");
Expand Down Expand Up @@ -74,6 +75,7 @@ Package.onUse(function (api) {
api.imply("vsivsi:job-collection");
api.imply("ongoworks:security");
api.imply("alanning:roles");
api.imply("tmeasday:publish-counts");
api.imply("alanning:roles");
api.imply("meteorhacks:subs-manager");
api.imply("reactioncommerce:reaction-schemas");
Expand Down
57 changes: 54 additions & 3 deletions packages/reaction-collections/server/publications/products.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,32 @@
Meteor.publish("Products", function (productScrollLimit, productFilters) {
check(productScrollLimit, Match.OneOf(null, undefined, Number));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could simplify it like this:

const filters = new SimpleSchema({
  "shops": {type: [String], optional: true},
  "tag": {type: String, optional: true},
  "query": {type: String, optional: true},
  "visibility": {type: Boolean, optional: true},
  "details": {type: Object, optional: true},
  "details.key": {type: String},
  "details.value": {type: String},
  "price": {type: Object, optional: true},
  "price.min": {type: Number},
  "price.max": {type: Number},
  "weight": {type: Object, optional: true},
  "weight.min": {type: Number},
  "weight.max": {type: Number}
})

Meteor.publish("Products", function (productScrollLimit, productFilters) {
  new SimpleSchema({
    productScrollLimit: { type: Number, optional: true },
    productFilters: { type: filters, optional: true }
  }).validator()
...

I think it should work not only in validationMethod. see docs. We don't need try/catch. Need tests

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I already tried this and I learned, that we can not completely substitute check() with SS validator, because check package will throw error "not all arguments of publication are checked with check()".
And I like more verbose schema in my case, because it shows full structure of productFilters argument. Don't mistake ValidatedMethod with publication function. You are offering use the same strategy and imho this is right way, but there is no ValidatedPublication package for now, read here

Try/catch we need, because validate() throws ValidationError and inside publication will fails silently without and log message (for me that is strange). We need throw Meteor error again to stop continue publication with wrong format of arguments

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a feeling that we can't use audit-arguments-check and SS.validator() within one app. here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can in the way I did. audit-arguments-check only need that all publication arguments were checked using check(). After we can validate structure of any argument using SS validate() and throw error if it's wrong

check(productFilters, Match.OneOf(null, undefined, Object));
try {
new SimpleSchema({
"shops": {type: [String], optional: true},
"tag": {type: String, optional: true},
"query": {type: String, optional: true},
"visibility": {type: Boolean, optional: true},
"details": {type: Object, optional: true},
"details.key": {type: String},
"details.value": {type: String},
"price": {type: Object, optional: true},
"price.min": {type: Number},
"price.max": {type: Number},
"weight": {type: Object, optional: true},
"weight.min": {type: Number},
"weight.max": {type: Number}
}).validate(productFilters);
} catch (e) {
ReactionCore.Log.error(e);
throw new Meteor.Error(e);
}

let shopAdmin;
const limit = productScrollLimit || 10;
const shop = ReactionCore.getCurrentShop();
const Products = ReactionCore.Collections.Products;
let sort = {title: 1};
const sort = {title: 1};

if (typeof shop !== "object") {
return this.ready();
Expand All @@ -24,7 +44,6 @@ Meteor.publish("Products", function (productScrollLimit, productFilters) {
if (productFilters) {
// handle multiple shops
if (productFilters.shops) {
check(productFilters.shops, Array);
_.extend(selector, {shopId: {$in: productFilters.shops}});

// check if this user is a shopAdmin
Expand All @@ -37,16 +56,48 @@ Meteor.publish("Products", function (productScrollLimit, productFilters) {

// filter by tag
if (productFilters.tag) {
check(productFilters.tag, String);
_.extend(selector, {hashtags: {$in: [productFilters.tag]}});
}

// filter by query
if (productFilters.query) {
let cond = {$regex: productFilters.query, $options: "i"};
_.extend(selector, {$or: [{title: cond}, {pageTitle: cond}, {description: cond}]});
}

// filter by details
if (productFilters.details) {
_.extend(selector, {metafields: {$elemMatch: {key: {$regex: productFilters.details.key, $options: "i"},
value: {$regex: productFilters.details.value, $options: "i"}}}});
}

// filter by visibility
if (productFilters.visibility !== undefined) {
_.extend(selector, {isVisible: productFilters.visibility});
}

// filter by price
if (productFilters.price) {
_.extend(selector, {variants: {$elemMatch: {price: {$gte: productFilters.price.min,
$lte: productFilters.price.max}}}});
}

// filter by weight
if (productFilters.weight) {
_.extend(selector, {variants: {$elemMatch: {weight: {$gte: productFilters.weight.min,
$lte: productFilters.weight.max}}}});
}
}

// products are always visible to owners
if (!(Roles.userIsInRole(this.userId, ["owner"], shop._id) || shopAdmin)) {
selector.isVisible = true;
}

ReactionCore.Log.debug("Products publication limit", productScrollLimit);
ReactionCore.Log.debug("Products publication selector", EJSON.stringify(selector));

Counts.publish(this, "Products", Products.find(selector), {noReady: true});
return Products.find(selector, {
sort: sort,
limit: limit
Expand Down
25 changes: 24 additions & 1 deletion packages/reaction-i18n/private/data/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@
"socialLabel": "Social",
"socialDescription": "Social Channel configuration",
"stripeLabel": "Stripe",
"stripeDescription": "Stripe payments"
"stripeDescription": "Stripe payments",
"filtrationLabel": "Filtration",
"filtrationDescription": "Products filtration for Reaction"
},
"settings": {
"accountSettingsLabel": "Account Settings",
Expand Down Expand Up @@ -512,6 +514,27 @@
"unknownError": "Unknown error"
}
},
"filtration": {
"filters": {
"titleLabel": "Title",
"titlePlaceholder": "Filter by title",
"priceLabel": "Price",
"weightLabel": "Weight",
"tagLabel": "Tag",
"tagPlaceholder": "Filter by tag",
"detailsLabel": "Details",
"detailNamePlaceholder": "Filter by detail name",
"detailValuePlaceholder": "Filter by detail value",
"visibilityLabel": "Visibility",
"visibilityAny": "Any",
"visibilityNotVisible": "Not visible",
"visibilityVisible": "Visible"
},
"showFilters": "Show Filters",
"settings": "Filters",
"found": "Found",
"products": "products"
},
"error": {
"nameRequired": "Name is required.",
"isRequired": "{{field}} is required.",
Expand Down
25 changes: 24 additions & 1 deletion packages/reaction-i18n/private/data/i18n/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@
"socialLabel": "Социальные сети",
"socialDescription": "Интеграция с соц. сетями",
"stripeLabel": "Stripe",
"stripeDescription": "Платежи через Stripe"
"stripeDescription": "Платежи через Stripe",
"filtrationLabel": "Фильтрация",
"filtrationDescription": "Фильтрация продуктов в Reaction"
},
"settings": {
"accountSettingsLabel": "Настройки учетных записей",
Expand Down Expand Up @@ -525,6 +527,27 @@
"unknownError": "Неизвестная ошибка"
}
},
"filtration": {
"filters": {
"titleLabel": "Название",
"titlePlaceholder": "Введите название",
"priceLabel": "Цена",
"weightLabel": "Вес",
"tagLabel": "Тэг",
"tagPlaceholder": "Введите тег",
"detailsLabel": "Характеристики",
"detailNamePlaceholder": "Название",
"detailValuePlaceholder": "Значение",
"visibilityLabel": "Видимость",
"visibilityAny": "Все",
"visibilityNotVisible": "Невидимые",
"visibilityVisible": "Видимые"
},
"showFilters": "Показать фильтры",
"settings": "Фильтры",
"found": "Найдено",
"products": "продуктов"
},
"error": {
"nameRequired": "Название обязательно.",
"isRequired": "Поле \"{{field}}\" обязательно.",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<template name="productGrid">

<div class="container-main">
<div class="product-grid" data-event-category="grid" data-event-action="generic-click" data-event-label="product grid click">
<ul class="product-grid-list list-unstyled" id="product-grid-list">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,23 @@ function loadMoreProducts() {

Template.productGrid.onCreated(function () {
Session.set("productGrid/selectedProducts", []);

ReactionFiltration.reset();
// Update product subscription
this.autorun(() => {
Meteor.subscribe("Products", Session.get("productScrollLimit"));
const tagId = ReactionRouter.getParam("slug");
if (tagId) {
const tag = ReactionCore.Collections.Tags.findOne({ slug: tagId }) || ReactionCore.Collections.Tags.findOne(tagId);
if (tag) {
ReactionFiltration.update("tag", tag._id);
} else {
// TODO: show notFound template
}
}
Meteor.subscribe("Products", Session.get("productScrollLimit"), Session.get("productFilters"));
});

this.autorun(() => {
let isActionViewOpen = ReactionCore.isActionViewOpen();

const isActionViewOpen = ReactionCore.isActionViewOpen();
if (isActionViewOpen === false) {
Session.set("productGrid/selectedProducts", []);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template name="products">
{{>productGrid tag}}
{{>productGrid}}
</template>

<template name="productListGrid">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,3 @@
Template.products.helpers({
tag: function () {
const id = ReactionRouter.getParam("_tag");
return {
tag: ReactionCore.Collections.Tags.findOne({ slug: id }) || ReactionCore.Collections.Tags.findOne(id)
};
}
});

/**
* products events
*/
Expand Down
1 change: 1 addition & 0 deletions packages/reaction-product-variant/package.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ Package.onUse(function (api) {
// community packages
api.use("reactioncommerce:[email protected]");
api.use("reactioncommerce:[email protected]");
api.use("ramusus:[email protected]");

// register package
api.addFiles("server/register.js", "server");
Expand Down
2 changes: 1 addition & 1 deletion packages/reaction-product-variant/server/register.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ ReactionCore.registerPackage({
route: "/tag/:slug",
name: "tag",
template: "products",
workflow: "coreProductWorkflow"
workflow: "coreWorkflow"
}, {
route: "/products/createProduct",
name: "createProduct",
Expand Down
1 change: 1 addition & 0 deletions packages/reaction-router/common/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ ReactionRouter.initPackageRoutes = (userId) => {
shop.route("/", {
name: "index",
action: function () {
ReactionFiltration.reset();
renderLayout();
}
});
Expand Down
2 changes: 2 additions & 0 deletions packages/reaction-router/package.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ Package.onUse(function (api) {
api.use("blaze-html-templates");
api.use("accounts-base");
api.use("reactioncommerce:[email protected]");
api.use("ramusus:[email protected]");

// flow-router packages
api.use("kadira:[email protected]");
api.use("kadira:[email protected]");
Expand Down
4 changes: 2 additions & 2 deletions packages/reaction-sample-data/private/data/Shops.json
Original file line number Diff line number Diff line change
Expand Up @@ -3081,7 +3081,7 @@
"layoutFooter": "layoutFooter",
"notFound": "notFound",
"dashboardHeader": "",
"dashboardControls": "dashboardControls",
"dashboardControls": "filtrationDashboardControls",
"adminControlsFooter": "adminControlsFooter"
}
}, {
Expand Down Expand Up @@ -6273,7 +6273,7 @@
"layoutHeader": "layoutHeader",
"layoutFooter": "layoutFooter",
"notFound": "notFound",
"dashboardControls": "dashboardControls",
"dashboardControls": "filtrationDashboardControls",
"adminControlsFooter": "adminControlsFooter"
}
}, {
Expand Down