Skip to main content
Version: 2.x

Migration Guides

This area contains the Migration steps to follow for upgrading your store to new Front-Commerce versions.

info

To update Front-Commerce in your project, use the command below (with the exact version you need):

npm install git+ssh://git@gitlab.blackswift.cloud/front-commerce/front-commerce.git#2.33.0

2.32.0 -> 2.33.0​

No manual migration steps are required for this release.

2.31.0 -> 2.32.0​

No manual migration steps are required for this release.

2.30.0 -> 2.31.0​

No manual migration steps are required for this release.

2.29.0 -> 2.30.0​

Fixed add to wishlist after new registration​

In this version we fixed the add to wishlist state updates after the first registration. Previously it would not display a product in the wishlist until a full page reload is initiated.

To accommodate this fix, we had to add changes to the following files;

If you have overridden these files please ensure to update them with the changes.

Reworked QuickOrder component​

In this version, we've introduced a new feature that enables you to bulk import products from a CSV file and directly add them to your cart.

The quick order page is active by default

The Quick order page is active by default at /quick-order. If you want to opt-out of this feature, you will have to remove the route using the front-commerce-prepare.js::onCreateRoute callback.

To develop this new feature, we've had to update the following files;

Stripe integration now uses IPNs on Magento2 / Magento2 B2B​

In this version we've updated Stripe payment module to use IPNs. To cope with this change, you will need to ensure that:

  • Stripe is configured to use an asyncOrder checkout flow
src/web/theme/pages/Checkout/checkoutFlowOf.js
diff --git a/src/web/theme/pages/Checkout/checkoutFlowOf.js b/src/web/theme/pages/Checkout/checkoutFlowOf.js
index f7bd3222f..b843608da 100644
--- a/src/web/theme/pages/Checkout/checkoutFlowOf.js
+++ b/src/web/theme/pages/Checkout/checkoutFlowOf.js
@@ -11,6 +11,7 @@ const checkoutFlowOf = (method) => {
if (method.startsWith("hipay_")) return "directOrderWithAdditionalAction";

if (method === "payzen_embedded") return "asyncOrder";
+ if (method === "stripe") return "asyncOrder";

return "directOrder";
};
  • In StripeCheckout component, cartId is added to the paymentData object in the checkout state:
src/web/theme/modules/Checkout/Payment/AdditionalPaymentInformation/StripeCheckout/StripeCheckout.js
diff --git a/src/web/theme/modules/Checkout/Payment/AdditionalPaymentInformation/StripeCheckout/StripeCheckout.js b/src/web/theme/modules/Checkout/Payment/AdditionalPaymentInformation/StripeCheckout/StripeCheckout.js
index 5539c0c87..976f89594 100644
--- a/src/web/theme/modules/Checkout/Payment/AdditionalPaymentInformation/StripeCheckout/StripeCheckout.js
+++ b/src/web/theme/modules/Checkout/Payment/AdditionalPaymentInformation/StripeCheckout/StripeCheckout.js
@@ -41,6 +41,7 @@ const withData = compose(
loading: data.loading,
clientSecret:
!data.loading && data.cart?.stripe?.paymentIntent?.clientSecret,
+ cartId: !data.loading && data.cart?.id,
}),
})
),
@@ -101,6 +102,7 @@ const StripeCheckoutComponent = (props) => {
} else if (paymentIntent.status === "requires_capture") {
const paymentData = {
paymentIntentId: paymentIntent.id,
+ cartId: props.cartId,
};
setState({
loading: false,

Fixed multiple triggers of "Order Completed" analytics event​

In this version we've fixed the issue where the "Order Completed" event would be triggered multiple times by refreshing the /checkout/success page (see related commit).

To benefit from this fix, you will need to ensure that the following changes have been applied to your project, in the case you overrode those files:

theme/modules/Checkout/withCheckoutTracking/withCheckoutSuccessTracking.js
diff --git a/src/web/theme/modules/Checkout/withCheckoutTracking/withCheckoutSuccessTracking.js b/src/web/theme/modules/Checkout/
withCheckoutTracking/withCheckoutSuccessTracking.js
index 1f1cc1cd1..8fe9f3d61 100644
--- a/src/web/theme/modules/Checkout/withCheckoutTracking/withCheckoutSuccessTracking.js
+++ b/src/web/theme/modules/Checkout/withCheckoutTracking/withCheckoutSuccessTracking.js
@@ -6,6 +6,10 @@ import trackEvent from "theme/modules/Analytics/trackEvent";
import CheckoutSuccessTrackingQuery from "./CheckoutSuccessTrackingQuery.gql";

const trackCartOrdered = (order) => {
+ const shouldTrack = localStorage.getItem("trackOrderCompleted");
+ if (!shouldTrack) {
+ return;
+ }
try {
const formatItemForAnalytics = ({ sku, name, row_total, qty_ordered }) => ({
sku,
@@ -25,6 +29,7 @@ const trackCartOrdered = (order) => {
discount: order.totals.discount.value.amount,
products: order.items.map(formatItemForAnalytics),
});
+ localStorage.removeItem("trackOrderCompleted");
} catch (e) {
console.error(
"Failed to send successfull order to tracking. Does it have a valid format?"
theme/pages/Checkout/stepsDefinition.js
diff --git a/src/web/theme/pages/Checkout/stepsDefinition.js b/src/web/theme/pages/Checkout/stepsDefinition.js
index d54db0f25..6d40d9ac4 100644
--- a/src/web/theme/pages/Checkout/stepsDefinition.js
+++ b/src/web/theme/pages/Checkout/stepsDefinition.js
@@ -170,17 +170,20 @@ const steps = [
isDisplayable: (checkoutState) => !!checkoutState.paymentMethod,
},
{
- renderStep: (props) => (
- <Redirect
- to={{
- pathname: "/checkout/success",
- state: {
- ...props.checkoutState.placedOrderData,
- checkoutState: props.checkoutState,
- },
- }}
- />
- ),
+ renderStep: (props) => {
+ localStorage.setItem("trackOrderCompleted", "true");
+ return (
+ <Redirect
+ to={{
+ pathname: "/checkout/success",
+ state: {
+ ...props.checkoutState.placedOrderData,
+ checkoutState: props.checkoutState,
+ },
+ }}
+ />
+ );
+ },
isValid: (checkoutState) => false,
isRelevant: () => true,
isDisplayable: (checkoutState) => checkoutState.isPlaced,

New features in 2.30.0​

2.28.0 -> 2.29.0​

No manual migration steps are required for this release.

2.27.0 -> 2.28.0​

No manual migration steps are required for this release.

2.26.0 -> 2.27.0​

Magento1: Reviews​

In this release, we added the ability to see and publish product reviews for Magento1. However, you will need to update your Front-Commerce Magento1 module to version 1.6.0 or above for this feature to work.

New features in 2.27.0​

2.25.0 -> 2.26.0​

Requisition List UID Update​

In version 2.26.0, we have updated the behavior of the requisition list UID to align with the Magento 2 GraphQL API.

The requisition list UID is now a base64-encoded string instead of a decoded string value.

If you are using a Magento version lower than 2.4.5, you must update the requisition list module by running the following command:

composer require magento/module-requisition-list-graph-ql 1.3.3
info

We have added the FRONT_COMMERCE_MAGENTO_UNSAFE_LEGACY_REQUISITION_LIST_ID=true environment variable for backward compatibility. However, please note that this variable will be removed in version 3.0. To ensure future compatibility, we recommend updating the Magento module instead of relying on this environment variable.

Configurable Axios Timeouts​

In this version, we have added the ability to configure the timeouts for the Axios instance used by Front-Commerce. We recommend using the new configuration instead of the timeout file with static values, which has been marked as deprecated for v3.0.

The loaders that previously used these values have been updated to use a configProvider to get the values, which are customizable via the following environment variables:

We hope this documentation helps you configure the timeouts for the Axios instance used by Front-Commerce. If you have any questions or concerns, please don't hesitate to contact us.

Redis invalidation SCAN iterations size configuration (invalidationScanIterationSize)​

We've increased the default iterations size for SCAN commands issued by the Redis caching strategy during cache invalidation with wildcards.

It used to be an arbitrary value of 100, and we increased it to 1000 to have better performances when invalidating cache on databases containing several millions of keys.

We feel it's a better default from our observations. This value is now configurable, so if you want to tweak its value or go back to the previous behavior, please update your caching.js with the invalidationScanIterationSize: 100 value.

New features in 2.26.0​

  • caching: the PerMagentoCustomerTaxZone caching strategy is now also available for Magento 1, to cache prices per tax zone (see documentation)
  • payment: Authorize.net is now supported for Magento1 (OpenMage LTS) projects. To use it, please update the Magento module front-commerce/magento1-module to 1.5.0+

2.24.0 -> 2.25.0​

Updated canonical URL creation method​

Breaking: In this version we have changed the way QueryHelper.filterCanonicalQueryStringParameters compute the canonical URL parameters, in order to better fit SEO-recommended rules (see Google article on this matter).

To opt-in to this behaviour, you can pass a boolean as the second parameter of QueryHelper.filterCanonicalQueryStringParameters to configure whether or not additional filters should be included in the canonical. true (default value) will include additional filters, and false will exclude them. Please note that we removed the sorting, minPrice and maxPrice parameters from the canonical url parameters.

See more in the related commit.

Drop support of Node 14​

In this version we've dropped support for Node 14 (EOL: 2023-04-30). The minimum required version is now Node 16.

You need to check your project dependencies for compatibility with at least Node 16 (you can check npm to find infos about your dependencies) and upgrade them in your package.json file.

info

If you are a Front-Commerce-Cloud customer, when you upgrade to Front-Commerce 2.25+, please contact us to upgrade the Node version used to deploy your project(s).

New default sorting method for ElasticSearch datasource​

In this version we changed the behavior when sorting with ElasticSearch datasource. From now on, if no sorting params are passed to the datasource, it will instead sort by the items' category index.

info

It also affects the sort by "Popular" on Front-Commerce themes.

Please let us know if you encounter any issues regarding this new behavior.

Use facet labels as values​

To opt-in to using facet labels as values, you must add the following following configuration to your config/website:

config/website.js
module.exports = {
...
search: {
dynamicFacetSize: 10,
ignoredAttributeKeys: [],
attributeFacetMinimumDocumentCount: 1,
authorizedCategoriesFacet: [],
categoryFacetMinimumDocumentCount: 1,
useAttributeLabels: true,
},
};

This also introduced the new isUsingIdsForAttributes method for datasources, if you have custom datasources, you must implement this method.

If your datasource already uses labels as values the method should return false, for example:

Multi shipment enhanced display​

info

Only for Magento 2

In this version we've added the list of products shipped in each shipments of an order.

If you've redefined the resolver for Shipment.trackingDetails, you must synchronize your version to apply the same kind of change as in the patch providing the feature so that items is correctly defined in the tracking details.

If you've overridden the OrderShipmentTrackingFragment.gql file, you must inject a new fragment:

src/web/theme/modules/User/Order/OrderShipmentTracking/OrderShipmentTrackingFragment.gql
#import "theme/modules/User/Order/OrderShipmentTrackingProducts/OrderShipmentTrackingProductsFragment.gql"
fragment OrderShipmentTrackingFragment on Shipment {
trackingDetails {
trackingId
name
url
items {
...OrderShipmentTrackingProductsFragment
}
__typename
}
}

If you've overridden the BaseTrackingDetails component, you must add a new component to display the list of items:

src/web/theme/modules/User/Order/OrderShipmentTracking/OrderShipmentTracking.js
import React from "react";
import { FormattedMessage } from "react-intl";
import Link from "theme/components/atoms/Typography/Link";
import { BodyFade } from "theme/components/atoms/Typography/Body";
import OrderShipmentTrackingProducts from "theme/modules/User/Order/OrderShipmentTrackingProducts";

const Tracking = ({ tracking }) => {
const name = tracking.url ? (
<Link to={tracking.url}>{tracking.name}</Link>
) : (
tracking.name
);

return (
<div className="account-orders-details__item">
<div className="account-orders-details__item__title">{name}</div>
<BodyFade>
<FormattedMessage
id="modules.User.Order.OrderShipmentTracking.number"
defaultMessage="Tracking number: {trackingId}"
values={{ trackingId: tracking.trackingId }}
/>
</BodyFade>
<OrderShipmentTrackingProducts items={tracking.items} />
</div>
);
};

export default Tracking;

Magic Button​

To implement the Magic Button related features, we have changed several files from the theme:

If you have an override of template/index.html, you need to apply the following changes:

template/index.html
     <script>
window.__APOLLO_STATE__ = %%__APOLLO_STATE__%%;
</script>
+ <script>
+ window.__CONTRIBUTION_MODE_DATA__ = %%__CONTRIBUTION_MODE_DATA__%%;
+ </script>
<script>
window.__MAINTENANCE__ = %%__MAINTENANCE__%%;
</script>

We strongly advice you to synchronize any override you may have done in your project.

Negotiable Quotes: online payments​

In this release, we've added support for a first online payment method (Stripe) to the negotiable quote checkout.

To achieve this feature, we had to perform a minor but potentially impactful Breaking Change to the negotiable checkout. The payment method selection step now only performs a single mutation instead of two.

The setNegotiableQuotePaymentMethod and placeNegotiableQuoteOrder mutations have been merged into setNegotiableQuotePaymentInformationAndPlaceOrder. Here is the merge request containing the diff, so that you can check whether or not your overrides are affected by this change.

To use this feature you need to:

  • update your Magento2 B2B Front-Commerce module to version 1.2.0+
  • ensure you haven't overriden theme files impacted with this breaking change

Impacted files:

  • theme/modules/Checkout/NegotiableQuotes/Payment/ChoosePayment.js
  • theme/modules/Checkout/NegotiableQuotes/Payment/EnhanceChoosePayment.js
  • theme/modules/Checkout/NegotiableQuotes/Payment/SetNegotiableQuotePaymentMethod.gql
  • theme/modules/Checkout/NegotiableQuotes/PlaceOrder/EnhancePlaceOrder.js
  • theme/modules/Checkout/NegotiableQuotes/PlaceOrder/PlaceNegotiableQuoteOrderMutation.gql
  • theme/modules/Checkout/NegotiableQuotes/PlaceOrder/PlaceOrder.js
  • theme/modules/Checkout/NegotiableQuotes/PlaceOrder/SetNegotiableQuotePaymentInformationAndPlaceOrderMutation.gql
note

We usually try hard to avoid Breaking Changes. In this context, we decided to remain pragmatic as we knew that this relatively new feature wasn't used by many projects. For this reason, we chose the simplest solution instead of adding complexity with deprecated GraphQL mutations and conditional paths in the checkout. Please contact us if you need help with this upgrade.

Image caching​

In this version we've introduced Focal Point support for the <Image> component.

If you use Front-Commerce's media middleware, the cache needs to be fully regenerated.

To do so, you should delete the .front-commerce/cache/images directory and deploy your project.

caution

Regenerate image cache will lead to a high CPU usage, to not disturb the availability of your app, we recommend you do this outside peak visit time on your website.

Performance: remove chunks preloading​

We've

removed the chunks preloading feature

as it led to blocking network requests that could reduce the LCP / FCP

of your app. From our analysis it improves the performance of the application and is a good default.

We invite you to test the impact of this change (i.e: run a Core Web Vitals test on your application and compare the results to confirm this).

If you want to restore the previous behavior, you can set the FRONT_COMMERCE_ENABLE_CHUNKS_PRELOAD=true environment variable.

New features in 2.25.0​

2.23.0 -> 2.24.0​

caution

We've released version 2.24.1 which fixes a critical regression introduced in version 2.24.0. Please ensure that you're upgrading to the latest 2.24.x version.

Apple Pay and Google Pay support with Stripe​

In this version, we have added support for Apple Pay and Google Pay with Stripe. We have also took this as an opportunity to upgrade Stripe related dependencies. If your project uses Stripe, we strongly advice you to test your integration.

note

To enable support for Apple Pay and Google Pay, we have changed the implementation of StripeCheckoutForm to use Stripe's PaymentElement instead of Stripe's CardElement. This results in a slight user interface change. Please update your theme/modules/Checkout/Payment/AdditionalPaymentInformation/StripeCheckout/* overrides if any.

ImageAdapters without multiple sources​

In the version we extended the ImageAdapters feature allow an adapter to change how sources are generated for the srcSet, to allow this, we had to make changes to the makeImagesProps If you have overriden this file, you will need to update it to match the new implementation.

src/web/theme/components/atoms/Image/makeImagesProps.js
import imageAdapters from "./adapters";

const makeImgProps = (baseUrl, src, format, bg, cover, fluid) => {
// [..]

const sourcesExtensions = imageAdapters.getSupportedExtensions(
src,
bg === "transparent"
);
const defaultExtension = imageAdapters.getDefaultExtension(src);

return {
src: makeImgSrc(src, format, sizes[0], bg, extension, cover, baseUrl),
src: makeImgSrc(src, format, sizes[0], bg, defaultFormat, cover, baseUrl),
sources: sourcesExtensions.map((extension) => ({
type: `image/${extension}`,
...(extension ? { type: `image/${extension}` } : {}),
srcSet: makeImageSrcset(
baseUrl,
src,
format,
sizes,
bg,
extension,
cover,
fluid
),
})),
};
};

We also added two optional methods getSupportedExtensions and getDefaultExtension to adapters, see Custom ImageAdapters documentation for more information.

info

This change removed the responsibility of the exported transparentExtensions, extensions and defaultExtension consts from the ImageComponent so we have marked them for deprecation in v3, they are currently re-exporting the methods from the default Front-Commerce image adapter

Search engine interface updated​

If you implemented a very custom search engine datasource, please update it to expose a scopes.queries.matchingQuery scope. You can use a dummy implementation if you don't want to support search query autocompletion. See MR!2072 for an example.

If you use an existing Front-Commerce search engine (Platform native, ElasticSearch, Algolia or Attraqt), you don't have anything to do.

New features in 2.24.0​

2.22.0 -> 2.23.0​

Adobe Commerce RMA​

This version contains improvements to RMA functionality. When updating your project, you must also update the Magento2 Commerce - Module Front Commerce to version 2.1.0+

composer require front-commerce/magento2-commerce-module@2.1.0

Adobe Commerce Negotiable quotes​

In this version, we added support for Negotiable quotes. When updating your project, if you want to be able to use Negotiable quotes, please note that you will need to synchronize your changes with the core ones on the following files:

  • theme/components/atoms/Icon/icons/core-icons.js (1f324c8a)
  • theme/modules/Cart/CartFooter.js (a4ae74ac)
  • theme/modules/User/AccountNavigation/AccountNavigation.js (a4ae74ac)
  • theme/layouts/Header/Navigation/AccountNavigation/AccountSubNavigation.js (a4ae74ac)
  • theme/pages/Account/AccountLayout.js (1f324c8a)
  • theme/_b2b.scss (ddc9b581)

New features in 2.23.0​

2.21.0 -> 2.22.0​

Fix sort params in QueryHelper's getFacetsParams​

We detected a bug related to sort parameters retrieved from the URL (notably on the PLP page), where the GraphQL query would fail if the object passed in this URL parameter did not match the SortInput input defined in the GraphQL schema. We fixed it by picking only the parameters required by the schema in QueryHelper.getFacetsParams().

Breaking change: If you extended SortInput input in the GraphQL schema, you will also need to override this QueryHelper method to reflect those changes, otherwise only the base input fields will be taken into account.

2.20.0 -> 2.21.0​

Algolia facet configurations​

As of this version, the Algolia datasource for Magento2 takes the facet type into account to build queries sent to Algolia. In previous versions, Front-Commerce behaved as if the facet type was set to Conjunctive. So by upgrading to this version, you might experience a change of behavior in the search results. To avoid that, you can set the facet type to Conjunctive under Stores > Configuration > Algolia Search > Instant Search Results Page in the Facets configuration.

Media proxy updated to send a custom user agent​

If you have added a custom media proxy endpoint in your application, we recommend to update the code as follows:

- import proxy from "express-http-proxy";
+ import proxy from "server/core/proxy";

We detected an issue with some remote services that were blocking Front-Commerce due to firewall rules detecting a weird behavior caused by the media proxy: many requests from the same IP address with different User-Agent values was considered as a suspicious activity. It could ultimately lead to a blacklisting.

This behavior has been fixed in this version and backported to all support branches. Front-Commerce will now send a custom User-Agent value to the remote services: Front-Commerce media proxy/<version> (where <version> is the version of Front-Commerce). Please update your codebase as described above to ensure your code is compatible with this new behavior.

2.19.0 -> 2.20.0​

Default shipping and billing address support​

In this release, we updated how the "Use as default billing address" and "Use as default shipping address" checkboxes are displayed in the AddressForm component. It now can be controlled globally using a configuration in the src/config/website.js configuration file.

Please check if you have overridden the AddressForm component (commit) if you're interested in using this feature.

2.18.0 -> 2.19.0​

Replaced mkdirp package with make-dir​

Due to a bug causing issues with our image resizer we have opted to replace the mkdirp package with make-dir in our dependencies, starting from version 2.19.0 we will no longer ship this package in Front-Commerce, so if you are using mkdirp in your own code, you will need to ensure that you have installed it.

npm install mkdirp@^1.0.4

Allow report-only frames for Adyen​

If you were using Adyen as a payment provider you might have allowed all iframes to load, to prevent blocking 3DS2 authorization iframes from credit card providers.

You can now restrict the policy again and use the reportOnlyDirectives feature instead.

Although it will not strengthen the policy, this will allow to log loaded iframes and help investigate risks of unsecure iframes.

my-module/config/website.js
  contentSecurityPolicy: {
directives: {
- frameSrc: ["*"],
+ frameSrc: ["*.adyen.com"],
}
+ reportOnlyDirectives: {
+ frameSrc: true,
+ }
},

Configure the new logger​

A new security logger has been added (for now to collect CSP violations).

Add it to your logging.js configuration to be able to see those logs (see the logging documentation for more details)

my-module/config/logging.js
module.exports = {
...
access: [
{
type: "console",
},
],
security: [
{
...
},
],
};

Adding custom icons​

We have improved the way you can add custom icons to your theme. Before you had to override the theme/components/atoms/Icon/Icon.js file to add your custom icons. Now you can simply extend or override the core icons with your custom icons by adding them to the theme/components/atoms/Icon/icons/app-icons.js file.

theme/components/atoms/Icon/icons/app-icons.js
import { FcHome, FcPhone } from "react-icons/fc";

/** @type {Record<string, import("react-icons").IconType>} */
const componentIcons = {
home: FcHome // this will override the `IoIosHome` icon from the core implementation
phone: FcPhone // this will add a new icon
};

/** @type {string[]} */
const svgIcons = [];

export default {
componentIcons,
svgIcons,
};
important

To apply this change you need to restore the original Icon.js files, you can do this by deleting the override from your custom theme.

Default country from graph​

In this release, we have changed the usage of default_country_id defined in your stores.js configuration.

From 2.19.0, this settings is directly exposed in the GraphQL API directly in Country.isDefault field.

note

This field will use the value returned by Magento2, and default to the one defined in your stores.js otherwise. In order to fully benefit from this change, you will also have to update you Front-Commerce Magento 2 module to version 2.9.0.

On other backends (Magento1, BigCommerce), this field will only expose the value from your stores.js.

Breaking changes: Previously, this setting was used directly in the frontend in web/theme/modules/User/Address/AddressForm/AddressForm.js, and was removed in favor of using the isDefault field in the graph. Please verify if you overwrote any of these files:

  • web/theme/modules/User/Address/AddressForm/AddressForm.js
  • web/theme/modules/User/Address/CountryFieldWithRegion/CountriesWithRegionQuery.gql
  • web/theme/modules/User/Address/CountryFieldWithRegion/withCountriesAndRegions.js

Form/Item inline property depreciation​

To standardize the API of theme/components/molecules/Form/Item between the default theme and the theme chocolatine, the inline property of that component from the default theme has been deprecated to use an appearance property. So if your project is not using the theme chocolatine and theme/components/molecules/Form/Item explicitly receives the inline property, you have to apply changes similar to:

 import FormItem from "theme/components/molecules/Form/Item";

const MyComponent = () => {
return (
- <FormItem inline={true}>
+ <FormItem appearance="inline">
<SomeComponent />
</FormItem>
);
}

or

 import FormItem from "theme/components/molecules/Form/Item";

const MyComponent = () => {
return (
- <FormItem inline={false}>
+ <FormItem>
<SomeComponent />
</FormItem>
);
}

New features in 2.19.0​

2.17.0 -> 2.18.0​

The Prismic module has moved to a new home.​

We have tagged the last version of the Prismic module in the external repository v1 πŸ₯³

Since this version we have moved the Prismic module into the core repository of Front-Commerce, moving forward any new features will be made available and follow the same semantic versioning as the core.

You can use the module by adding the following changes to your .front-commerce.js config file:

.front-commerce.js
module.exports = {
modules: [
"./node_modules/front-commerce/theme-chocolatine",
- "./node_modules/front-commerce-prismic/prismic",
+ "./node_modules/front-commerce/modules/prismic",
"./src",
],
serverModules: [
{ name: "FrontCommerce", path: "server/modules/front-commerce" },
{
name: "Magento2Elasticsearch",
path: "datasource-elasticsearch/server/modules/magento2-elasticsearch",
},
{ name: "Magento2", path: "server/modules/magento2" },
{ name: "Prismic", path: "prismic/server/modules/prismic" },
],
webModules: [
{ name: "FrontCommerce", path: "front-commerce/src/web" },
- {
- name: "Prismic",
- path: "./node_modules/front-commerce-prismic/prismic/web",
- },
],
};

path-to-regexp package added​

We noticed that the path-to-regexp package was missing from our dependencies, it was only useable due to a transitive dependency. We have added it to our dependencies to avoid any future issues.

The previous version of the package was 0.1.7 and we have upgraded it to 6.2.1. Because of others dependencies depending on older version of path-to-regexp, you have to install it in your project in order to satisfy Front-Commerce's requirements by running:

npm install path-to-regexp@^6.2.1

If you don't, you'll experience server side rendering errors like:

TypeError: Object(...) is not a function
at /path/to/your/project/build/server/webpack:/node_modules/front-commerce/src/server/modules/magento2/catalog/products/urlMatchers.js:6:1

If you used this import without installing it in your project, the import methods have changed.

- import pathToRegexp from "path-to-regexp";
+ import { pathToRegexp } from "path-to-regexp";

In addition, given the amount of changes between the version 0.1.7 and 6.2.1, we strongly advice you to check the project documentation and to carefully test any code involving this library.

Magento2 Adyen module update​

In this release, we added support for version 8 of Magento2 Adyen module. If you have a Front-Commerce setup where the module Magento2/Adyen is used, the FRONT_COMMERCE_ADYEN_MAGENTO_MODULE_VERSION environment variable is now required and it must contain the Magento2 module version.

New configurations were added in the Adyen Magento module regarding headless storefronts. Please ensure you've configured the "Headless Integration" as per our docs.

DomainEvent implementations reworked​

The PaymentDetails attribute was removed from the payment DomainEvents. A custom paymentData last attribute now allows your payment methods to provide custom JSON payload to the magento backend.

- new PaymentReceived(orderId, paymentDetails, pspReference)
+ new PaymentReceived(orderId, pspReference, paymentData)

Concerned classes : PaymentAuthenticationStarted, PaymentAuthorized, PaymentCaptured, PaymentCancelled, PaymentReceived and PaymentRefused

FRONT_COMMERCE_WEB_UNSAFE_USE_DEPRECATED_FIELDS support removal​

The support for the undocumented environment variable FRONT_COMMERCE_WEB_UNSAFE_USE_DEPRECATED_FIELDS has been removed in this version. If you were previously defining this variable, you can safely remove it. The main use case for this variable was to change npm run lint behavior so that it triggers a warning instead of an error when a deprecated GraphQL is used. This is now the default behavior.

New Adobe Commerce B2B PHP module​

Some B2B features were previously leveraging features from the Magento2 Commerce module. During this release, we've extracted B2B related features into their own repository.

If you work on an Adobe Commerce B2B project, you must:

  • update front-commerce/magento2-commerce-module to version 2.x (currently 2.0.0)
  • install front-commerce/magento2-b2b-module to its latest version

Here are the commands to achieve this:

composer require front-commerce/magento2-commerce-module:2.0.0

composer config repositories.front-commerce-magento2-b2b git \
git@gitlab.blackswift.cloud:front-commerce/magento2-b2b-module-front-commerce.git
composer require front-commerce/magento2-b2b-module:1.1.0

bin/magento setup:upgrade

2.16.0 -> 2.17.0​

Adyen's Stored payment methods​

In this release, we added support for Adyen's Stored Payment Methods for its Magento module. For more information, see Adyen's Stored Payment Methods documentation.

Payment workflow rework​

We added a new frontend payment workflow for payment means using asynchronous notifications. As most embedded payment methods will be migrated in the future, please ensure you update the following files if you overrode them

theme/modules/Checkout/PlaceOrder/PlaceOrder.js
...
+import AsyncOrderQuery from "./AsyncOrderQuery.gql";

...

EnhancePlaceOrder({
SetPaymentInfoAndPlaceOrderMutation,
SetCheckoutPaymentInformationAndRedirectMutation,
PlaceOrderAndRedirectMutation,
+ AsyncOrderQuery,
}),
branch(
- (props) => props.hasMessage,
+ (props) => props.message || props.errorMessage,
() => ErrorOccured,
(BaseComponent) => BaseComponent
)
theme/modules/Checkout/PlaceOrder/EnhancePlaceOrder.js
...
+import withAsyncOrderAction from "./PaymentFlow/withAsyncOrderAction";


export const supportedPaymentFlowTypes = [
"directOrder",
+ "asyncOrder",
"redirectBeforeOrder",
"redirectAfterOrder",
"directOrderWithAdditionalAction",
"workflowAgnosticCheckout",
];

const EnhancePlaceOrder = ({
SetPaymentInfoAndPlaceOrderMutation,
SetCheckoutPaymentInformationAndRedirectMutation,
PlaceOrderAndRedirectMutation,
+ AsyncOrderQuery,
}) =>
...
withHandlers({
onError:
(props) =>
({ errorMessage }) =>
props.formatErrorMessage(errorMessage),
}),
+ withAsyncOrderAction(AsyncOrderQuery),
makeCommandDispatcher({

DomainEvent rework​

The DomainEvent class was reworked.

If you handled payment events on orders (backend operation) using DomainEvent implementations, these implementations now base on a PurchaseIdentifier instead of a direct orderId (this allows to update order events based on a cartId)

Here is the new usage for those classes

new PaymentCaptured(
- orderId,
+ new PurchaseIdentifier({ orderId }),
paymentDetail
)

Payzen/Lyra on Magento1​

We migrated the Payzen/Lyra embedded payment module for Magento2 to the new asyncOrder payment workflow.

As this is not supported for Magento1, override theme/pages/Checkout/checkoutFlowOf.js to keep using the former workflow.

theme/pages/Checkout/checkoutFlowOf.js

const checkoutFlowOf = (method) => {
...

- if (method === "payzen_embedded") return "asyncOrder";
+ if (method === "payzen_embedded") return "directOrder";

...
};

2.15.0 -> 2.16.0​

Updating Front-Commerce from 2.15.0 to 2.16.0 does not require any manual operation.


2.14.0 -> 2.15.0​

Environment variables: quote values containing # or ``` characters​

As part of our continuous dependencies upgrade process, we've upgraded the dotenv dependency to its latest version. We've updated it from version 8.2.0 (October 2019) to version 16.0.0 (February 2022). Technically, it contains 2 Breaking Changes that we've decided to be pragmatic about. We prioritized having an up-to-date dependency with a minor migration check, over an outdated one for pure SemVer compatibility. Please check that your environment variables are not impacted by these breaking changes:

  1. 15.0.0: # marks the beginning of a comment (UNLESS the value is wrapped in quotes. Please update your .env files to wrap in quotes any values containing #:
  2. 16.0.0: If you had values containing the backtick character, please quote those values with either single or double quotes.
- SECRET_WITH_HASH=something-with-a-#-hash
- SECRET_WITH_BACKTICK=something-with-a-`-backtick
+ SECRET_WITH_HASH="something-with-a-#-hash"
+ SECRET_WITH_BACKTICK="something-with-a-`-backtick"
info

you can change your environment variables right away. Quoted values also work with previous Front-Commerce versions.

In-Stock Alerts​

In this release, we introduced the In-Stock Alert feature. When this feature is enabled on your backend (Magento 1 and 2), it will by default render a new component SubscribeToInStockAlert inside the existing OutOfStock component.

Paginated orders​

In this release we added pagination for orders. In the process, the orders GraphQL field used to retrieve orders has been deprecated and will eventually be removed in FC version 3.0.0. orderList should now be used instead. If you had overridden the Orders (theme/pages/Account/Orders/Orders.js) component, you might want to update it to use the new GraphQL field and add a pagination component.

Node Version Support Change​

We now support Node versions 14, 16 and 17 (Node 17 is supported on a best effort basis). If you are using Node 12 (which reached its end of life), you must update your Node version (we recommend Node 16). To support these latest Node versions, we had to upgrade some dependencies. These upgrades imply changes that could impact your codebase:

  • You need to update to the latest version of your front-commerce-skeleton

  • @apollo/* are only installed as sub-dependencies and therefore should not be used directly. In 2.15.0 you need to replace all uses of @apollo/* in your codebase with react-apollo, or graphql-tag imports where applicable.

    Check if you overrode any file that you need to apply the changes to

    modules/front-commerce-b2b/web/core/permissions/CompanyPermissionsContext.js
    - * @property {import('@apollo/react-hoc').DataValue<{ me: Object }, {}>} data
    + * @property {import('react-apollo').DataValue<{ me: Object }, {}>} data

    modules/front-commerce-b2b/web/theme/modules/Company/CompanyStructure/CompanyStructure/withCompanyStructureMutations.js
    -import { useMutation } from "@apollo/react-hooks";
    -
    -/**
    - * @callback MutationFunction
    - * @param {import('@apollo/react-common/lib/types/types').MutationFunctionOptions} options
    - * @returns {Promise<import('@apollo/react-common/lib/types/types').ExecutionResult>}
    - */
    +import { useMutation } from "react-apollo";
    +
    +/**
    + * @typedef {typeof useMutation} UseMutation
    + * @typedef {ReturnType<useMutation>} UseMutationReturn
    + * @typedef {UseMutationReturn[0]} MutationFunction
    + */

    modules/front-commerce-b2b/web/theme/modules/Company/CompanyUserDeactivate/CompanyUserDeactivate.js
    -import { useMutation } from "@apollo/react-hooks";
    +import { useMutation } from "react-apollo";

    modules/front-commerce-b2b/web/theme/modules/Company/CompanyUserModal/CompanyUserModal.js
    -import { useMutation } from "@apollo/react-hooks";
    +import { useMutation } from "react-apollo";

    modules/front-commerce-b2b/web/theme/modules/RequisitionList/AddToRequisitionList/withAddMultipleItemsToNewRequisitionListMutation.js
    - * @returns {Promise<import('@apollo/react-common/lib/types/types').ExecutionResult>}

    modules/front-commerce-b2b/web/theme/modules/RequisitionList/AddToRequisitionList/withAddMultipleItemsToRequisitionListMutation.js
    +/**
    + * @typedef {typeof useMutation} UseMutation
    + * @typedef {ReturnType<useMutation>} UseMutationReturn
    + * @typedef {UseMutationReturn[0]} MutationFunction
    + * @typedef {ReturnType<MutationFunction>} MutationFunctionReturn
    + */
    /**
    * @typedef {object} AddToRequisitionListFunctionProps
    * @param {string} requisitionListId
    * @param {any[]} selectedItems
    */
    /**
    * @callback AddToRequisitionListFunction
    * @param {AddToRequisitionListFunctionProps} props
    - * @returns {Promise<import('@apollo/react-common/lib/types/types').ExecutionResult>}
    + * @returns {MutationFunctionReturn}
    */

    modules/front-commerce-b2b/web/theme/modules/RequisitionList/AddToRequisitionList/withProductConfigurationModal.js
    - * @returns {Promise<import('@apollo/react-common/lib/types/types').ExecutionResult>}

    modules/front-commerce-b2b/web/theme/modules/RequisitionList/RequisitionListDelete/RequisitionListDelete.js
    -import { useMutation } from "@apollo/react-hooks";
    +import { useMutation } from "react-apollo";

    modules/front-commerce-b2b/web/theme/modules/RequisitionList/RequisitionListItemsGrid/RequisitionListItem/RequisitionListItem.js
    -import { useMutation } from "@apollo/react-hooks";
    +import { useMutation } from "react-apollo";

    modules/front-commerce-b2b/web/theme/modules/RequisitionList/RequisitionListModal/RequisitionListCreateModal/RequisitionListCreateModal.js
    -import { useMutation } from "@apollo/react-hooks";
    +import { useMutation } from "react-apollo";

    modules/front-commerce-b2b/web/theme/modules/RequisitionList/RequisitionListModal/RequisitionListUpdateModal/RequisitionListUpdateModal.js
    -import { useMutation } from "@apollo/react-hooks";
    +import { useMutation } from "react-apollo";

    modules/front-commerce-b2b/web/theme/modules/RequisitionList/RequisitionListToolbar/RequisitionListToolbarAddToCart/RequisitionListToolbarAddToCart.js
    -import { useMutation } from "@apollo/react-hooks";
    +import { useMutation } from "react-apollo";

    modules/front-commerce-b2b/web/theme/pages/Account/CompanyStructure/EnhanceCompanyStructure.js
    -         * @param {import('@apollo/react-hoc/lib/types').OptionProps<any, GraphQLData, any>} param0
    + * @param {import('react-apollo').OptionProps<any, GraphQLData, any>} param0

    modules/front-commerce-b2b/web/theme/pages/Account/RequisitionListDetails/EnhanceRequisitionListDetails.js
    -         * @param {import('@apollo/react-hoc/lib/types').OptionProps<any, GraphQLData, any>} param0
    + * @param {import('react-apollo').OptionProps<any, GraphQLData, any>} param0

    modules/payment-adyen/web/theme/modules/Adyen/PaypalCheckout/EnhancePaypalCheckout.js
    -         * @param {import('@apollo/react-hoc/lib/types').OptionProps<any, GraphQLData, any>} param0
    + * @param {import('react-apollo').OptionProps<any, GraphQLData, any>} param0

    modules/payment-adyen/web/theme/modules/Checkout/PlaceOrder/AdditionalAction/Adyen/Adyen.js
    -import { useQuery } from "@apollo/react-hooks";
    +import { useQuery } from "react-apollo";

    modules/payment-hipay/web/theme/modules/Checkout/PlaceOrder/AdditionalAction/HiPay/HiPayActions.js
    -import { useQuery } from "@apollo/react-hooks";
    +import { useQuery } from "react-apollo";

    src/web/core/apollo/graphqlWithPreload.js
    - * @param {import('@apollo/react-hoc/lib/types').OperationOption & PreloadOperationOptions} options
    + * @param {import('react-apollo').OperationOption & PreloadOperationOptions} options
    ...
    - /** @type {import('@apollo/client').ApolloClient | null} */
    + /** @type {import('apollo-client').ApolloClient | null} */
    ...

    src/web/core/shop/ShopContext.js
    - * @property {import('@apollo/react-hoc').DataValue<{ shop: Shop, loading: boolean, error: import('apollo-client').ApolloError }, {}>} data
    + * @property {import('react-apollo').DataValue<{ shop: Shop, loading: boolean, error: import('apollo-client').ApolloError }, {}>} data

    src/web/theme/modules/SmartForms/Field/Email/useEmailServerValidation.js
    -import { useApolloClient } from "@apollo/react-hooks";
    +import { useApolloClient } from "react-apollo";

    src/web/theme/modules/SmartForms/Field/PhoneNumber/usePhoneNumberValidation.js
    -import { useLazyQuery } from "@apollo/react-hooks";
    +import { useLazyQuery } from "react-apollo";

    src/web/theme/modules/SmartForms/Field/helpers/useLazyQueryAlwaysTriggeredOnComplete.js
    -import { useLazyQuery } from "@apollo/react-hooks";
    +import { useLazyQuery } from "react-apollo";
    +
    +/**
    + * @typedef {typeof useLazyQuery} UseLazyQuery
    + * @typedef {Parameters<UseLazyQuery>} UseLazyQueryParams
    + * @typedef {ReturnType<UseLazyQuery>} UseLazyQueryReturn
    + */
    /**
    * @callback OnCompletedCallback
    * @param {any} data
    */
    /**
    * @typedef {Object} QueryResultsRef
    * @property {OnCompletedCallback} onCompleted
    * @property {boolean} loading
    * @property {import('apollo-client/errors/ApolloError').ApolloError} error
    * @property {any} data
    - * @property {import('@apollo/react-common').OperationVariables} variables
    + * @property {UseLazyQueryReturn[1]["variables"]} variables
    */
    /**
    - * @param {import('graphql').DocumentNode} Query
    - * @param {import('@apollo/react-hooks/lib/types').LazyQueryHookOptions} options
    - * @returns {import('@apollo/react-hooks/lib/types').QueryTuple<any,import('@apollo/react-common').OperationVariables>}
    + * @param {UseLazyQueryParams[0]} Query
    + * @param {UseLazyQueryParams[1]} options
    + * @returns {UseLazyQueryReturn}
    */

    src/web/theme/modules/Wishlist/AddAllWishlistToCartModal/useAddAllWishlistToCartModalInternal.js
    -import { useMutation } from "@apollo/react-hooks";
    +import { useMutation } from "react-apollo";

    src/web/theme/modules/Wishlist/WishlistProvider/WishlistProvider.js
    -import { useLazyQuery, useQuery } from "@apollo/react-hooks";
    +import { useLazyQuery, useQuery } from "react-apollo";

    src/web/theme/pages/Account/DownloadableProduct/EnhanceDownloadableProduct.js
    -         * @param {import('@apollo/react-hoc/lib/types').OptionProps<any, GraphQLData, any>} param0
    + * @param {import('react-apollo').OptionProps<any, GraphQLData, any>} param0

    src/web/theme/pages/Orders/Orders.js
    -import { useLazyQuery } from "@apollo/react-hooks";
    +import { useLazyQuery } from "react-apollo";

    src/web/theme/pages/Product/useProductBySkuLoader.js
    -import { useQuery } from "@apollo/react-hooks";
    +import { useQuery } from "react-apollo";
  • If after the above fixes there is still @apollo/* dependencies and you are not sure how to resolve please contact us for support. You can also check here and here for the changes we did to our codebase.

  • Resolvers for fields that are not in the schema now throw errors. To avoid this remove all unneeded field/Type resolvers that do not have a representation in the GraphQL schema. Check our cleaning commit regarding this issue.

  • makeApolloClientStub now expects resolvers as an argument instead of mocks. This is in tandem with the graphql-tools upgrade notes. Note that we provided an adapter that converts mocks to resolvers so that old tests are not affected. However it is recommended to make the change. To disable the adapter's warning set FRONT_COMMERCE_WEB_PRINT_MAKEAPOLLOCLIENTSTUB_MOCKS_DEPRECATION_WARNING environment variable to "false".

  • The use of SchemaVisitor/SchemaDirectiveVisitor to implement GraphQL directive is deprecated and it is replaced by the use of the new API. We implemented an adapter so that uses of SchemaVisitor/SchemaDirectiveVisitor will not break, however it is recommended to make the change. Please note that the adapter only supports the use of visitFieldDefinition function of the SchemaVisitor/SchemaDirectiveVisitor class. If you have use for other functions and cannot make the change to the new API please contact us for help.

  • When using Node 17 you need to prefix your npm commands by NODE_OPTIONS=--openssl-legacy-provider e.g. NODE_OPTIONS=--openssl-legacy-provider npm start, NODE_OPTIONS=--openssl-legacy-provider npm run build.

  • When using npm >= 7 you need to add --legacy-peer-deps to npm install commands. e.g. npm install --legacy-peer-deps, npm i some_dependency --legacy-peer-deps.

  • Reinstall your dependencies after the update:

rm -rf ./node_modules/
npm install --legacy-peer-deps

New features in 2.15.0​


2.13.0 -> 2.14.0​

New style sheet for B2B​

In this release we updated the RequisitionList configurable options modal. In case you are using the B2B module and have overridden modules/front-commerce-b2b/web/theme/modules/RequisitionList/_RequisitionList.scss please add the following line to it:

@import "~theme/modules/RequisitionList/ProductConfigurationModal/ProductConfigurationModal";

withFlashMessages now exports hooks​

The logic of withFlashMessages is now also exported as a hook useFlashMessages. If you have overridden withFlashMessages please apply the changes in this diff to it.

Added downloadable products support for Magento2​

Minimum required magento 2 module version 2.6.1

Support for shareable downloadable products was added. There is now a new page under the user account /user/downloadable-products that lists all the downloadable products of the current user.

P.S. The withFlashMessage update is required for the downloadable product page.

To add a link to the downloadable products in the account navigation please apply the following diffs to your project:

If you are using the base theme:

If you are using theme chocolatine:

PaymentMethodLabel relocated​

The <PaymentMethodLabel> component was moved from theme/modules/User/Order/OrderMethod/PaymentMethodLabel.js to theme/modules/Checkout/Payment/PaymentMethodLabel.js the old location will still work but will output deprecation messages when used. If you have overridden <PaymentMethodLabel> you should also relocate your override to the same path and update all references to point to it.

As a consequence of relocating <PaymentMethodLabel> we had to rename all the translation keys it uses. As such the following translation keys have been updated

Old KeyNew Key
modules.User.Order.OrderMethod.PaymentMethod.checkmomodules.Checkout.Payment.PaymentMethodLabel.checkmo
modules.User.Order.OrderMethod.PaymentMethod.ogoneFlexcheckoutmodules.Checkout.Payment.PaymentMethodLabel.ogoneFlexcheckout
modules.User.Order.OrderMethod.PaymentMethod.paymentOnAccountmodules.Checkout.Payment.PaymentMethodLabel.paymentOnAccount
modules.User.Order.OrderMethod.PaymentMethod.paypalButtonmodules.Checkout.Payment.PaymentMethodLabel.paypalButton
modules.User.Order.OrderMethod.PaymentMethod.paypalExpressmodules.Checkout.Payment.PaymentMethodLabel.paypalExpress
modules.User.Order.OrderMethod.PaymentMethod.paypalStandardmodules.Checkout.Payment.PaymentMethodLabel.paypalStandard
modules.User.Order.OrderMethod.PaymentMethod.payzenEmbeddedmodules.Checkout.Payment.PaymentMethodLabel.payzenEmbedded
modules.User.Order.OrderMethod.PaymentMethod.stripemodules.Checkout.Payment.PaymentMethodLabel.stripe
modules.User.Order.OrderMethod.PaymentMethod.hipaymodules.Checkout.Payment.PaymentMethodLabel.hipay

All translation keys that start with modules.User.Order.OrderMethod.PaymentMethod now starts with modules.Checkout.Payment.PaymentMethodLabel. You need to update any use of the old keys (if any) in your project to the respective new key.

Update your CSPs​

In this release, we have removed most of the module-related CSPs from Front-Commerce default configuration file. If you are using one or more of the following modules, please do update your CSPs accordingly in your config/website.js configuration:

Removed deprecations in Button component​

The properties that were tagged as deprecated in theme/components/atoms/Button/Button.js before version 2.0 have been removed in this release:

  • appearance should now be used instead of primary, icon, link and warning.
  • state should now be used instead of disabled and pending.

Please update your code to fit the new behavior.

Code clean up​

In this release, we have removed some dead and unused code (see corresponding MR):

  • src/theme/pages/Account/Account.js that despites its name is not used at all and very unlikely to be used by any project
  • some loadable routes from src/web/LoadableRoutes.js there were useless since the addition of file based routing in 2.0.0-rc.0.

If you have trouble about those removals while upgrading, please contact us.

Fixed the Front-Commerce B2B module's company credit display​

In the account menu we displayed the company credit menu even for companies not allowed to pay on account.

If you overrode FirstnameQuery.gql add the following code

modules/front-commerce-b2b/web/theme/pages/Account/FirstnameQuery.gql
query Firstname {
me {
...
company {
name
+ credit {
+ availableCredit {
+ amount
+ }
+ }
}
}
}

If you overrode AccountNavigation.js perform the following changes

theme/modules/User/AccountNavigation/AccountNavigation.js
...

const isCompanyUser = (user) => {
return Boolean(user?.company);
};

+const isCompanyCreditsAllowed = (user) => {
+ return Boolean(user?.company?.credit);
+};

...
- isCompanyUser(user) && {
+ isCompanyCreditsAllowed(user) && {
value: "/user/company/credit",
label: intl.formatMessage(messages.companyCredit),
},
...
- {isCompanyUser(user) && (
+ {isCompanyCreditsAllowed(user) && (
<Route
exact
path={`${basePath}/company/credit`}
children={({ match }) => (
<Link to="/user/company/credit" className={makeClassName(match)}>
{intl.formatMessage(messages.companyCredit)}
<Icon icon="cash" title="" />
</Link>
)}
/>
...

New features in 2.14.0​

note

When a Prismic document has been registered using the registerRoutableType method or the registerPrismicRoute method, A url property is exposed in the Content type object. This property contains the resolved url of the document.


2.12.0 -> 2.13.0​

Upgrade the Magento2 module​

If you are using Magento2, version 2.6.0 of front-commerce/magento2-module is now the minimum required version. To update it to the latest version, from Magento2 root, you can run:

composer update front-commerce/magento2-module
info

You can refer to the Magento2 module changelog for the full details.

Upgrade the Prismic module​

The front-commerce-prismic module is now using the latest version of prismic.

npm install git+ssh://git@gitlab.blackswift.cloud/front-commerce/front-commerce-prismic.git#1.0.0

The most notable breaking changes is the removal of the FRONT_COMMERCE_PRISMIC_URL and the inclusion of the path option for the registerRoutableType method.

info

You can refer to the front-commerce-prismic module changelog for the full details.

FRONT_COMMERCE_PRISMIC_URL has been removed​

The environment variable FRONT_COMMERCE_PRISMIC_URL has been removed. Please use FRONT_COMMERCE_PRISMIC_REPOSITORY_NAME instead.

.env
- FRONT_COMMERCE_PRISMIC_URL=https://my-repo.prismic.io
+ FRONT_COMMERCE_PRISMIC_REPOSITORY_NAME=my-repo

Improved the registerRoutableType method​

  • A new required property has been added for dynamic routes: path
    Examples: /:uid, /:lang/:uid, /:category*/:uid, /:section/:category?/:uid.

    ProTipβ„’

    You can use the online express-route-tester@2.0.0 to test your paths.

  • A new resolvers property to allow the nested routes content relationship resolution.

      PrismicLoader.registerRoutableType({
    typeIdentifier: "album", // document type "album" will resolve to path `/albums/:uid`
    - path: "/album/:uid", // "/album/queen"
    + path: "/:category/:uid", // "/rock-and-roll/queen"
    + resolvers: {
    + category: "category" // identifier of the Content Relationship in the album Custom Type
    + },
    ...
    })
Depth Limit

The Route Resolver is limited to retrieving data from 2 levels deep, please see the Route Resolver example for more information.

@prismicio/client has been updated to v6​

See https://prismic.io/docs/technologies/prismic-client-v6-migration-guide for the complete migration guide

The new predicate object contains the same predicate functions as Predicates with new names to better match the API's predicate names.

- import { Predicates } from "@prismicio/client";
+ import * as prismic from "@prismicio/client";
const query = new ListQuery(10)
- query.addPredicate(prismic.Predicates.gt('my.movie.rating', 3))
+ query.addPredicate(prismic.predicate.numberGreaterThan('my.movie.rating', 3))

The following predicates have been renamed:

  • dayOfMonth β†’ dateDayOfMonth
  • dayOfMonthAfter β†’ dateDayOfMonthAfter
  • dayOfMonthBefore β†’ dateDayOfMonthBefore
  • dayOfWeek β†’ dateDayOfWeek
  • dayOfWeekAfter β†’ dateDayOfWeekAfter
  • dayOfWeekBefore β†’ dateDayOfWeekBefore
  • month β†’ dateMonth
  • monthBefore β†’ dateMonthBefore
  • monthAfter β†’ dateMonthAfter
  • year β†’ dateYear
  • hour β†’ dateHour
  • hourBefore β†’ dateHourBefore
  • hourAfter β†’ dateHourAfter
  • gt β†’ numberGreaterThan
  • lt β†’ numberLessThan
  • inRange β†’ numberInRange
  • near β†’ geopointNear

prismic-dom replaced with @prismicio/helpers​

See https://prismic.io/docs/technologies/prismic-helpers-v2-migration-guide for the complete migration guide

Added FlashMessages to the Order Details​

For the HiPay payment method, FlashMessages may be shown at the order detail level for errors.

If you overrode <OrderDetailsLayout> add the following lines to it

+ import FlashMessages from "theme/modules/FlashMessages";
...
return (
<div
className={classNames("order-details-layout", {
"account-orders-details--no-actions": !showOrderActions,
})}
>
+ <FlashMessages />
...

Login Form Update​

For the external logins feature <AdditionalLoginFormActions> and <FlashMessages> have been added to the <LoginForm>.

If you overrode <LoginForm> please add the following lines to it

...
+import AdditionalLoginFormActions from "theme/modules/User/LoginForm/AdditionalLoginFormActions";
+import FlashMessages from "theme/modules/FlashMessages";
...
{props.errorMessage && <ErrorAlert>{props.errorMessage}</ErrorAlert>}
+ <FlashMessages />
...
</SubmitButton>
+ <AdditionalLoginFormActions />
</FormActions>
...

New icons required​

In this release, these new icons were added google, facebook to the <Icon> component theme/components/atoms/Icon/Icon.js.

If you have overridden the <Icon> component, you need to add the icons as follows to the list of icons to avoid any error messages at page loading:

-import { FaUserCircle } from "react-icons/fa";
+import { FaUserCircle, FaFacebook, FaGoogle } from "react-icons/fa";
const keyToComponent = {
...
organigram: GiOrganigram,
gripper: VscGripper,
+ facebook: FaFacebook,
+ google: FaGoogle,
};

New features in 2.13.0​

These new features may be relevant for your existing application:


2.11.0 -> 2.12.0​

Upgrade the Magento2 module​

If you are using Magento2, version 2.5.0 of front-commerce/magento2-module is now the minimum required version. To update it to the last version, from Magento2 root, you can run:

composer update front-commerce/magento2-module

Homogenize the Map components​

To ensure a more consistent usage we have homogenize the props of the map components and we added a few fixes.

  • The LocationInternalShape has been deprecated in favor of LocationInputShape.
  • The CoordinatesShape now accepts either longitude or lng.
  • Included the onBoundsChanged prop in the Map components
info

For a list of available props for the map and marker components see: Display a map

To support the Slider and Slider Magento2 page builder content types, we have moved the <Carousel /> component from theme chocolatine to the default theme. If you plan to use this component directly or through the page builder Slider, you must add a carousel image format to your src/config/images.js:

src/config/images.js
@@ -6,6 +6,7 @@ module.exports = {
large: { width: 1100, height: 1100, bgColors: [] },
+ carousel: { width: 1280, height: 600, bgColors: [] },
zoomable: { width: 1100, height: 1100, bgColors: [], sizes: [2] },
},
};

swatch image format in base theme​

We backported the swatch image format from theme chocolatine to base theme. This image format is used to display product images of a requisition list. If you are using the base theme and want to use the requisition list feature of the B2B module you have to add the swatch image format to your src/config/images.js as follows:

src/config/images.js
module.exports = {
defaultBgColor: "FFFFFF",
presets: {
...
+ swatch: { width: 26, height: 26, bgColors: [] },
...
},
};

Smarter image resizing mechanism​

In this release, we have improved the image resizing mechanism to be bit smarter. Before this release, a check on the requested file extension was done before trying to resize an image. As of this release, this check has been removed and it's now up to the underlying image processing library to check if this file is a image or not. As a result, out of the box, more image file formats can be processed without any configuration. The extensions setting from config/images.js becomes useless and is now deprecated. You should remove it from your application:

src/config/images.js
    large: { width: 1100, height: 1100, bgColors: [] }
},
- extensions: [".jpg", ".jpeg", ".png"]
};

Added requisition list features to B2B module (only theme chocolatine suported)​

If you are using base theme and wish to use the B2B module you have to override theme/modules/ProductView/Synthesis/AddProductToCart.js from the base theme and provide a way to add to requisition list from the product page (see AddProductToRequisitionList and B2B's AddProductToCart for inspiration). You also need to override theme/modules/AddToCart/_AddToCart.scss if you have not already and just copy the styles from the base theme to it (src/web/theme/modules/AddToCart/_AddToCart.scss).

If you are using theme chocolatine and have overridden theme/modules/ProductView/Synthesis/AddProductToCart.js and want to use the B2B module you need to apply the following change to it:

...
+import AddProductToRequisitionList from "theme/modules/RequisitionList/AddProductToRequisitionList";
...
<AddToCart
appearance={appearance}
selectedOptions={selectedOptions}
selectedCustomOptions={selectedCustomOptions}
selectedBundleOptions={selectedBundleOptions}
onProductAdded={onProductAdded}
product={withComputedPrice(product)}
label={intl.formatMessage(messages.addToCartLabel)}
unavailableLabel={intl.formatMessage(messages.unavailableLabel)}
actions={
- withWishlist !== false && (
+ <>
+ {withWishlist !== false && (
<AddProductToWishlist
sku={product.sku}
selectedOptions={selectedOptions}
selectedCustomOptions={selectedCustomOptions}
selectedBundleOptions={selectedBundleOptions}
size="big"
/>
- )
+ )}
+ <AddProductToRequisitionList
+ product={product}
+ selectedConfigurableOptions={selectedOptions}
+ size="big"
+ />
+ </>
}
/>
...

If you overrode theme/modules/Cart/CartTitle/CartTitle.js you need to apply the following diff to it:

...
+import AddCartToRequisitionList from "../../RequisitionList/AddCartToRequisitionList";
...
<FormActions appearance="center">
+ <AddCartToRequisitionList cart={props.cart} size="big" />
{hasCartError ? (
<Button onDisableClick={() => {}} state="disabled">
<ProceedToCheckout />
</Button>
) : (
<Link to="/checkout" buttonAppearance="primary">
<ProceedToCheckout />
</Link>
)}
</FormActions>
...

Cookies max age configuration​

The cookieMaxAgeInMonths configuration in src/config/website.js represents the consent cookie's maxage in months. It now has a default value of 12 months. Previously if left unconfigured the cookie banner will appear to users every time they visit the site.

The company structure and requisition list links are added to the <AccountNavigation> component. Those links are part of the B2B features so if you need them and overrode the <AccountNavigation> component you need to apply the below diff to your overridden <AccountNavigation>:

"AccountNavigation" diff (click to expand diff)
import React from "react";
...
const messages = defineMessages({
...
+ companyStructureLink: {
+ id: "pages.Account.Navigation.companyStructure",
+ defaultMessage: "Company structure",
+ },
...
+ requisitionListsLink: {
+ id: "pages.Account.Navigation.requisitionLists",
+ defaultMessage: "Your requisition lists",
+ },
...
});
...
export const MobileSelector = injectIntl(
({
intl,
location,
ordersCount,
storeCredit,
wishlist,
+ requisitionList,
user,
returnMerchandiseAuthorization,
}) => {
const companyRoutes = isCompanyUser(user)
? [
...
+ {
+ value: "/user/company/structure",
+ label: intl.formatMessage(messages.companyStructureLink),
+ },
]
: [];
const routes = [
...
+ requisitionList?.isFeatureActive && {
+ value: "/user/requisition-lists",
+ label: intl.formatMessage(messages.requisitionListsLink),
+ },
...
].filter(Boolean);
...
}
);
...
export const DesktopLeftMenu = injectIntl(
({
intl,
basePath,
ordersCount,
storeCredit,
wishlist,
user,
+ requisitionList,
returnMerchandiseAuthorization,
}) => {
return (
<nav className="account-navigation">
...
{isCompanyUser(user) ? (
<>
...
+ <Route
+ exact
+ path={`${basePath}/company/structure`}
+ children={({ match }) => (
+ <Link
+ to="/user/company/structure"
+ className={makeClassName(match)}
+ >
+ {intl.formatMessage(messages.companyStructureLink)}
+ <Icon icon="organigram" title="" />
+ </Link>
+ )}
+ />
</>
) : null}
...
+ {requisitionList?.isFeatureActive && (
+ <Route
+ path={`${basePath}/requisition-lists`}
+ children={({ match }) => (
+ <Link
+ to="/user/requisition-lists"
+ className={makeClassName(match, ordersCount === 0)}
+ >
+ {intl.formatMessage(messages.requisitionListsLink)}
+ <Icon icon="list" title="" />
+ </Link>
+ )}
+ />
+ )}
...
</nav>
);
}
);

New style sheets​

If you overrode theme/components/_components.scss you need to add the following line to it

@import "~theme/components/molecules/LoadingOverlay/LoadingOverlay";
@import "~theme/components/molecules/SelectMenu/SelectMenu";

If you overrode theme/components/_modules.scss you need to add the following line to it to use the <ProductPicker> component (used by the QuickOrder feature)

@import "~theme/modules/ProductPicker/ProductPicker";

If you are using the B2B module and overrode theme/_b2b.scss you need to add the following lines to it

@import "~theme/components/organisms/Tree/Tree";
@import "~theme/modules/Company/CompanyStructure/CompanyStructure";
@import "~theme/modules/RequisitionList/RequisitionList";
@import "~theme/modules/RequisitionList/RequisitionListTable/RequisitionListTable";

If you overrode src/web/theme/components/atoms/Button/_Button.scss apply the following diff to it:

...
+.button--disabled {
+ &:hover,
+ &:focus {
+ background: $white;
+ }
+}
...
.button--disabled {
+ &,
+ &:hover,
+ &:focus,
+ &:active {
+ background: $white;
+ text-decoration: none;
cursor: not-allowed;
border-color: $shade04;
background: $white;
color: $shade04;
&.button--primary {
border-color: $shade04;
background: $shade04;
color: $white;
}
&.button--icon {
background: transparent;
color: $shade04;
}
+ }
}

if you overrode theme/modules/AddToCart/_AddToCart.scss and are using theme chocolatine apply the following diff to it:

...
&__actions {
display: none;
padding: math.div($boxSizeMargin, 2);
@media screen and (min-width: $menuBreakpoint) {
display: block;
}
}
&__actions {
- display: none;
+ display: flex;
padding: math.div($boxSizeMargin, 2);
- @media screen and (min-width: $menuBreakpoint) {
- display: block;
- }
+ > * {
+ margin-left: math.div($boxSizeMargin, 2);
+ }
+ :first-child {
+ margin-left: 0;
+ }
}...

New icons required​

In this release, these new icons were added eye-off, user-circle, organigram and gripper to the <Icon> component theme/components/atoms/Icon/Icon.js.

If you have overridden the <Icon> component, you need to add the icons as follows to the list of icons to avoid any error messages at page loading:

import {
...
+ IoIosEyeOff,
} from "react-icons/io";
+import { FaUserCircle } from "react-icons/fa";
+import { GiOrganigram } from "react-icons/gi";
+import { VscGripper } from "react-icons/vsc";
const keyToComponent = {
...
eye: IoIosEye,
+ "eye-off": IoIosEyeOff,
pencil: IoMdCreate,
...
+ "user-circle": FaUserCircle,
+ organigram: GiOrganigram,
+ gripper: VscGripper,
};

Password field updated with a show/hide feature​

The <Password> input now displays a show/hide icon allowing users to reveal their password. It is enabled by default. You can opt-out this feature using the disableShowPassword prop:

<Password
id="password"
name="password"
required
+ disableShowPassword
/>

This new Password component requires a stylesheet to add in the _components.scss file if you overrode it.

// theme/components/_components.scss
...
@import "~theme/components/atoms/Form/Label/Label";
+@import "~theme/components/atoms/Form/Input/Password/Password";
@import "~theme/components/atoms/Form/Input/Select/Select";
...

If you overrode the _Input.scss file, you may need to indicate the inputs height by adding an input-height class to correct the vertical alignment of the icon.

// theme/components/atoms/Form/Input/_Input.scss
input,
+.input-height,
select {
height: 3.4rem;
}

New <PasswordStrengthHint> component in default forms​

We've included a <PasswordStrengthHint> to provide a better feedback to users about the expected password complexity.

If you don't want to use this feature in your application, please follow the Disable password strength hints guide Please update the files below, to ensure that your application displays user forms consistently:

// theme/components/_components.scss
+@import "~theme/components/atoms/Form/Input/PasswordStrengthHint/PasswordStrengthHint";
+@import "~theme/components/atoms/ProgressStatus/ProgressStatus";
// theme/components/atoms/Form/Input/index.js
+import PasswordStrengthHint from "./PasswordStrengthHint";
export {
...
+ PasswordStrengthHint,
};

You should add the <PasswordStrengthHint> component in every override using the <Password> input. In the default theme, the following components were affected:

  • theme/modules/User/RegisterForm/RegisterForm.js
  • theme/pages/Account/Information/ChangeUserPasswordForm.js
  • theme/pages/PasswordManagment/PasswordReset/PasswordReset.js
  • theme/modules/User/PasswordManagement/PasswordResetForm/PasswordResetForm.js

Here is an example of the changes involved to use this component (usually added after the <Password> field):

+import PasswordStrengthHint from "theme/components/atoms/Form/Input/PasswordStrengthHint/PasswordStrengthHint";
<Password
name="password"
...
/>
+ <PasswordStrengthHint
+ formValuePath="password" // must equal the password name value
+/>

passwordValidation deprecation​

The file theme/components/atoms/Form/Input/Password/passwordValidation.js is now deprecated. If you overrode it, you must also override the password validity configuration in theme/components/atoms/Form/Input/Password/passwordConfig.js (introduced in this release).

See the password field's documentation for more details on the password field validation configuration.

If you overrode some of the following components:

  • theme/modules/User/RegisterForm/RegisterForm.js
  • theme/pages/Account/Information/ChangeUserPasswordForm.js
  • theme/pages/PasswordManagment/PasswordReset/PasswordReset.js
  • theme/modules/User/PasswordManagement/PasswordResetForm/PasswordResetForm.js

You must use the new src/web/theme/components/atoms/Form/Input/Password/passwordFieldValidator.js instead of the deprecated passwordValidation as follow:

-import {
- isPasswordValid,
- errorMessage,
- MIN_PASSWORD_LENGTH,
- MIN_CHAR_CLASSES,
-} from "theme/components/atoms/Form/Input/Password/passwordValidation";
+import {
+ passwordValidationRules,
+ passwordValidationErrors,
+} from "theme/components/atoms/Form/Input/Password/passwordFieldValidator";
...
<Password
name="password"
- validations={{
- magentoPasswordRule: (_, value) => isPasswordValid(value),
- }}
+ validations={passwordValidationRules}
- validationError={intl.formatMessage(errorMessage, {
- minLength: MIN_PASSWORD_LENGTH,
- minClasses: MIN_CHAR_CLASSES,
- })}
+ validationError={passwordValidationErrors}
/>

New Confirmation Modal​

We added a new <ConfirmationModal> in theme/components/organisms/Modal. If you overrode the theme/components/organisms/Modal/index.js file please add the following lines to ensure that the confirmation modal works :

+import ConfirmationModal from "./ConfirmationModal/ConfirmationModal";
-export { CloseModal };
+export { CloseModal, ConfirmationModal };

New features in 2.12.0​

These new features may be relevant for your existing application:

  • Page builder: Slider content type and Slide support
  • the <Password> component now allows the user to reveal the password
  • New component: <PasswordStrengthHint> to show hints of password's strength criterias to the user
  • New component: <ProgressStatus> to show a progressbar with a label
  • New component: <ConfirmationModal> to simplify confirmation modals

2.10.0 -> 2.11.0​

Zoom-in on product images​

In this release, we have added the ability for customers to zoom in on product images in the product page. For that, we have implemented a <Ligthbox /> component that leverages react-image-lightbox library behind the scene.

This feature is enabled by default in both in theme Chocolatine and in the base theme. You MUST decide whether you want it or not and follow the related instructions below:

Disabling the zoom in feature​

This feature is controlled by the enableZoomOnImage property of the product <Gallery /> component in the base theme or the <GalleryWithCarousel /> component in theme Chocolatine. So If you want to disable this feature and one of these components is used in your integration, you can pass false in the enableZoomOnImage property.

note

In the base theme, the <Gallery /> component is rendered by theme/modules/ProductView/ProductView, while in theme Chocolatine, the <GalleryWithCarousel /> is rendered by theme/modules/ProductView/Gallery/Gallery.

Integrating the zoom in feature​

If you want to add that feature to your project you have to define an image format named zoomable. For instance, we have added one in the last version of the Skeleton but the actual format parameters depends on your project constraints.

note

zoomable is the default image format used by the <Lightbox /> component to render the image on which the customer can zoom in. This component accepts an imageFormat property in which you can pass an other image format.

Then, depending on the amount of customization, you might also have to bring changes similar to what we have done in the merge requests for that feature:

In a nutshell, when the feature is enabled, we place a transparent button on top of the product image; if the customer clicks on it, we then render a <Lightbox /> for that image.

MondialRelay shipping in a Magento2 based project​

In this version, we have improved the MondialRelay shipping support with Magento2 so that a customer can only choose a pickup point suitable for the products being ordered. This improvement requires an update of Magentix's module to install at least the version 100.10.7.

New icons required​

In this release, two new icons (warn and users) were added to the <Icon> component.

If you have overridden the <Icon> component, you need to add both icons as follows to the list of icons to avoid any error messages at page loading:

import {
...
+ IoIosWarning,
+ IoIosPeople,
} from "react-icons/io";
const keyToComponent = {
...
+ warn: IoIosWarning,
+ users: IoIosPeople,
};

Dependencies updates​

We recommend to reformat your source code using the latest Prettier version (see below).

Here are some highlights of the main changes in upstream libraries that unlikely may impact your application. We have tested them and haven't found any regression, but we prefer to mention these changes in case you detect a weird issue after upgrading:

  • axios does not append the charset=utf-8 anymore for requests with Content-Type:application/json. See #680, #4016 and #2154 and for details.
  • prettier has been updated from 2.2.1 to 2.4.1 (MR!742). We've reformatted our code with this version, so it may lead to style differences with your overrides. To update your application code, you can run npx prettier -w ./path/to/your/directories and commit the changes.
ProTipβ„’

we've discovered the git ignoreRevsFile option it could be useful in your project too 😎

Unnecessary safeHtml in product overviews​

The product overview component does not need to escape the product name with safeHtml.

If you did override any of the following components, you can safely remove safeHtml calls in them:

  • src/web/theme/modules/ProductView/Overview/Overview.js
  • theme-chocolatine/web/theme/modules/ProductView/ProductItem/Overview/Overview.js
- {<span dangerouslySetInnerHTML={{ __html: safeHtml(name) }} />}
+ {name}

New Magento <WysiwygV2> transforms may conflict with yours​

In order to support Magento Page Builder's default content types, we have added new components to the default MagentoWysiwyg transforms.

See the Page Builder ones and ensure there is no collision with your custom WYSIWYG components. While very unlikely, it could be possible. For instance, if you may have overridden the theme/modules/WysiwygV2/MagentoWysiwyg/MagentoWysiwyg.js to add a custom heading component to the componentsMap.

New features in 2.11.0​

These new features may be relevant for your existing application:


2.9.0 -> 2.10.0​

Magento1 MondialRelay module update​

In this release we have added support for MondialRelay as a shipping method in Magento2 based Front-Commerce implementation. As a result, we have changed the way files are organized on the disk.

In a nutshell, the Front-Commerce module modules/shipping-mondialrelay-magento1 has been renamed to modules/shipping-mondialrelay and this module was defining a GraphQL module that has been renamed from mondialrelay to magento1-mondialrelay. So, if you are upgrading a Magento1 based project using the MondialRelay module, you have to update your .front-commerce.js as documented in the MondialRelay guide page. In addition, if you have custom code importing files from modules/shipping-mondialrelay-magento1, you will also have to update those imports to match the new file layout.

Magento2 Adyen module update​

In this release the Magento2 Adyen Front-Commerce module got a major revamp to make it compatible with the latest Magento2 Adyen plugin (7.2). Several steps are needed to upgrade your project if you are using this payment platform:

  1. the Magento2 Adyen Front-Commerce module has been moved. As a result, you have to update your .front-commerce.js as documented in the Adyen integration page.
  2. the FRONT_COMMERCE_ADYEN_CLIENT_KEY environment variable is now required so you have to configure the environment so that it is defined
  3. we have made some changes and fixes to the Adyen related frontend components. If you have overridden some of those, you have to backport the changes.

Magento1 Payline module update​

In this release, we've implemented automatic configuration for the Payline environment from the related Magento setting. Payline will use the HOMO or PRODUCTION environment based on what is configured in Magento.

If using Payline, you should update the Magento module to version 1.3.0. If you don't, you will see the error below in your logs (and the PRODUCTION environment will be used):

ERROR on reorderForIds, the id payment/payline_common/environment has no associated result

Configurable options HOC refactoring​

We highly recommend to test products configuration on the product and cart pages after this migration. Product configuration, bundle and custom options selectors where homogeneized between these pages to fix some issues.

In this release we have done a refactor of the configurable product options. We have extracted much of the logic from configurable product options from HOCs into functions that can be used even outside of react.

This refactoring homogenized how options were used and allowed us to fix some discrepancies between the product page and cart item update configurators. Internal APIs were updated to cope with this change, and we deprecated some legacy props.

CartItemOptionsUpdater needs product prop​

<CartItemOptionsUpdater> now expects a product prop if you are using it you should now send it the product as a prop like below:

-<CartItemOptionsUpdater {...props} />
+<CartItemOptionsUpdater product={product} {...props} />

ConfigurableOptions needs selectedOptions and deprecates currentOptions​

currentOptions is deprecated in <ConfigurableOptions> (format { optionLabel: valueLabel }). <ConfigurableOptions> now expects selectedOptions (format { optionId: valueId } same as what useSelectedProductWithConfigurableOptions returns)

-<ConfigurableOptions currentOptions={currentOptions} {...props} />
+<ConfigurableOptions selectedOptions={selectedOptions} {...props} />

New style sheet for CartItemOptionsUpdater​

add the following line to theme/modules/_modules.scss

@import "~theme/modules/Cart/CartItem/CartItemOptionsUpdater/CartItemOptionsUpdater";

Import hasCartItemOptions from its own file in theme chocolatine​

We refactored hasCartItemOptions from theme/modules/Cart/CartItem/CartItemOptions/CartItemOptions to theme/modules/Cart/CartItem/CartItemOptions/hasCartItemOptions so if you where using it you need to change where you are importing if like below:

-import { hasCartItemOptions } from "theme/modules/Cart/CartItem/CartItemOptions/CartItemOptions";
+import hasCartItemOptions from "theme/modules/Cart/CartItem/CartItemOptions/hasCartItemOptions";

SmartForms field internal changes​

In this release, we've reworked the internals of SmartForm fields to better support browser autocomplete.

The public API remains unchanged but if you've overridden internal components, please check your overrides against their original. See these Merge Requests: #641 and #645

New features in 2.10.0​

These new features may be relevant for your existing application: