Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed bug that caused visibility button to not save a change. #1477

Merged
merged 7 commits into from
Oct 7, 2016
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ class ProductAdmin extends Component {
}

handleToggleVisibility = () => {
if (this.props.onFieldChange) {
this.props.onFieldChange("isVisible", !this.product.isVisible);
if (this.props.onProductFieldSave) {
this.props.onProductFieldSave(this.product._id, "isVisible", !this.product.isVisible);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { Template } from "meteor/templating";
import { Button, EditButton } from "/imports/plugins/core/ui/client/components";
import { PublishContainer } from "/imports/plugins/core/revisions";
import { ProductDetailContainer } from "/imports/plugins/included/product-detail-simple/client/containers";
import { isRevisionControlEnabled } from "/imports/plugins/core/revisions/lib/api";

Template.productDetail.onCreated(function () {
this.state = new ReactiveDict();
Expand Down Expand Up @@ -574,45 +575,50 @@ Template.productDetailDashboardControls.helpers({
*/
Template.productDetailDashboardControls.events({
"click [data-event-action=publishProduct]": function (event, template) {
let errorMsg = "";
const instance = Template.instance();
const self = instance.state.get("product") || {};
if (!self.title) {
errorMsg += `${i18next.t("error.isRequired", { field: i18next.t("productDetailEdit.title") })} `;
template.$(".title-edit-input").focus();
}
const variants = ReactionProduct.getVariants(self._id);
variants.forEach((variant, index) => {
if (!variant.title) {
errorMsg +=
`${i18next.t("error.variantFieldIsRequired", { field: i18next.t("productVariant.title"), number: index + 1 })} `;

if (isRevisionControlEnabled()) {
Meteor.call("products/updateProductField", self._id, "isVisible", !self.isVisible);
} else {
let errorMsg = "";
if (!self.title) {
errorMsg += `${i18next.t("error.isRequired", { field: i18next.t("productDetailEdit.title") })} `;
template.$(".title-edit-input").focus();
}
// if top variant has children, it is not necessary to check its price
if (variant.ancestors.length === 1 && !ReactionProduct.checkChildVariants(variant._id) ||
variant.ancestors.length !== 1) {
if (!variant.price) {
const variants = ReactionProduct.getVariants(self._id);
variants.forEach((variant, index) => {
if (!variant.title) {
errorMsg +=
`${i18next.t("error.variantFieldIsRequired", { field: i18next.t("productVariant.price"), number: index + 1 })} `;
`${i18next.t("error.variantFieldIsRequired", { field: i18next.t("productVariant.title"), number: index + 1 })} `;
}
}
});
if (errorMsg.length > 0) {
Alerts.inline(errorMsg, "warning", {
placement: "productManagement",
i18nKey: "productDetail.errorMsg"
});
} else {
Meteor.call("products/publishProduct", self._id, function (error) {
if (error) {
return Alerts.inline(error.reason, "error", {
placement: "productManagement",
id: self._id,
i18nKey: "productDetail.errorMsg"
});
// if top variant has children, it is not necessary to check its price
if (variant.ancestors.length === 1 && !ReactionProduct.checkChildVariants(variant._id) ||
variant.ancestors.length !== 1) {
if (!variant.price) {
errorMsg +=
`${i18next.t("error.variantFieldIsRequired", { field: i18next.t("productVariant.price"), number: index + 1 })} `;
}
}

return true;
});
if (errorMsg.length > 0) {
Alerts.inline(errorMsg, "warning", {
placement: "productManagement",
i18nKey: "productDetail.errorMsg"
});
} else {
Meteor.call("products/publishProduct", self._id, function (error) {
if (error) {
return Alerts.inline(error.reason, "error", {
placement: "productManagement",
id: self._id,
i18nKey: "productDetail.errorMsg"
});
}

return true;
});
}
}
}
});
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { Reaction } from "/client/api";
import Logger from "/client/modules/logger";
import { ReactionProduct } from "/lib/api";
import { Media } from "/lib/collections";
import { isRevisionControlEnabled } from "/imports/plugins/core/revisions/lib/api";

/**
* productGridItems helpers
Expand Down Expand Up @@ -49,7 +50,11 @@ Template.productGridItems.helpers({
$checkbox.prop("checked", true).trigger("change");
},
onPublishButtonClick() {
ReactionProduct.publishProduct(instance.data);
if (isRevisionControlEnabled()) {
Meteor.call("products/updateProductField", instance.data._id, "isVisible", !instance.data.isVisible);
} else {
ReactionProduct.publishProduct(instance.data);
}
}
};
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import Logger from "/client/modules/logger";
import { ReactionProduct } from "/lib/api";
import { Media, Products } from "/lib/collections";
import { PublishContainer } from "/imports/plugins/core/revisions";
import { isRevisionControlEnabled } from "/imports/plugins/core/revisions/lib/api";
import { applyProductRevision } from "/lib/api/products";

Template.productSettings.onCreated(function () {
this.state = new ReactiveDict();
Expand All @@ -19,18 +21,16 @@ Template.productSettings.onCreated(function () {
const productIds = currentData.products.map((product) => {
return product._id;
});
this.state.set("productIds", productIds);

const products = Products.find({
_id: {
$in: productIds
}
}).map((product) => {
if (product.__revisions && product.__revisions.length) {
return product.__revisions[0].documentData;
}
return product._id;
return applyProductRevision(product);
});

this.state.set("productIds", productIds);
this.state.set("products", products);
}
});
Expand All @@ -46,6 +46,17 @@ Template.productSettings.helpers({
documentIds: productIds
};
},
isVisible() {
const instance = Template.instance();
const products = instance.state.get("products") || [];

// Use the first selected product to determin status of bulk, isVisible button
if (Array.isArray(products) && products.length) {
return products[0].isVisible;
}

return false;
},
hasSelectedProducts() {
return this.products.length > 0;
},
Expand Down Expand Up @@ -138,7 +149,25 @@ Template.productSettingsListItem.inheritsHelpersFrom("productSettingsGridItem");

Template.productSettings.events({
"click [data-event-action=publishProduct]": function () {
ReactionProduct.publishProduct(this.products);
const instance = Template.instance();
const products = instance.state.get("products") || [];

if (isRevisionControlEnabled()) {
for (const product of products) {
// Update the visibility using the first selected product to determine the proper
// visibility toggle. This is to ensure that all selected products will become visible or not visible
// at the same time so it's not confusing.
Meteor.call("products/updateProductField", product._id, "isVisible", !products[0].isVisible);
}
} else {
// The legacy behavior will bulk toggle visibilty of each product seperatly.
//
// Example:
// If you selected 10 products, and 5 were visible and 5 were not visible, and then
// clicked the visibility button, 5 products would switched from not visible to visible, and the other 5
// would be swiched from visible to not visible.
ReactionProduct.publishProduct(products);
}
},
"click [data-event-action=cloneProduct]": function () {
ReactionProduct.cloneProduct(this.products);
Expand Down