diff --git a/Sources/AssemblyVersionAuto.cs b/Sources/AssemblyVersionAuto.cs
index 23743d8f..020d349f 100644
--- a/Sources/AssemblyVersionAuto.cs
+++ b/Sources/AssemblyVersionAuto.cs
@@ -3,6 +3,6 @@
[assembly: AssemblyCopyright("Copyright ? 2020 Episerver")]
-[assembly: AssemblyVersion("13.22.0.0")]
-[assembly: AssemblyInformationalVersion("13.22.0")]
-[assembly: AssemblyFileVersion("13.22.0.4155")]
+[assembly: AssemblyVersion("13.26.0.0")]
+[assembly: AssemblyInformationalVersion("13.26.0")]
+[assembly: AssemblyFileVersion("13.26.0.4223")]
diff --git a/Sources/EPiServer.Reference.Commerce.Manager/EPiServer.Reference.Commerce.Manager.csproj b/Sources/EPiServer.Reference.Commerce.Manager/EPiServer.Reference.Commerce.Manager.csproj
index 1e30d27b..22bab25f 100644
--- a/Sources/EPiServer.Reference.Commerce.Manager/EPiServer.Reference.Commerce.Manager.csproj
+++ b/Sources/EPiServer.Reference.Commerce.Manager/EPiServer.Reference.Commerce.Manager.csproj
@@ -407,101 +407,101 @@
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\EPiServer.Business.Commerce.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\EPiServer.Business.Commerce.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\EPiServer.Commerce.Reporting.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\EPiServer.Commerce.Reporting.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\EPiServer.Commerce.Internal.Migration.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\EPiServer.Commerce.Internal.Migration.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.BusinessFoundation.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.BusinessFoundation.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.BusinessFoundation.Data.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.BusinessFoundation.Data.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.Commerce.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.Commerce.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.Commerce.Marketing.Validators.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.Commerce.Marketing.Validators.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.Commerce.Plugins.Payment.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.Commerce.Plugins.Payment.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.Commerce.Plugins.Shipping.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.Commerce.Plugins.Shipping.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.Commerce.Website.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.Commerce.Website.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.Commerce.Workflow.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.Commerce.Workflow.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.DataProvider.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.DataProvider.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.FileUploader.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.FileUploader.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.MetaDataPlus.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.MetaDataPlus.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.Search.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.Search.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.Search.Extensions.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.Search.Extensions.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.Search.LuceneSearchProvider.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.Search.LuceneSearchProvider.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.SqlDataProvider.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.SqlDataProvider.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.WebConsoleLib.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.WebConsoleLib.dll
True
- ..\..\packages\EPiServer.CommerceManager.13.22.0\lib\net461\Mediachase.ConsoleManager.dll
+ ..\..\packages\EPiServer.CommerceManager.13.26.0\lib\net461\Mediachase.ConsoleManager.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\AjaxControlToolkit.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\AjaxControlToolkit.dll
True
- ..\..\packages\EPiServer.CommerceManager.13.22.0\lib\net461\ComponentArt.Web.UI.dll
+ ..\..\packages\EPiServer.CommerceManager.13.26.0\lib\net461\ComponentArt.Web.UI.dll
True
-
+
This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
-
+
diff --git a/Sources/EPiServer.Reference.Commerce.Manager/packages.config b/Sources/EPiServer.Reference.Commerce.Manager/packages.config
index 2c90c045..e0fe5286 100644
--- a/Sources/EPiServer.Reference.Commerce.Manager/packages.config
+++ b/Sources/EPiServer.Reference.Commerce.Manager/packages.config
@@ -45,6 +45,6 @@
-
-
+
+
diff --git a/Sources/EPiServer.Reference.Commerce.Manager/web.config b/Sources/EPiServer.Reference.Commerce.Manager/web.config
index 6576194f..7b1ccddb 100644
--- a/Sources/EPiServer.Reference.Commerce.Manager/web.config
+++ b/Sources/EPiServer.Reference.Commerce.Manager/web.config
@@ -580,79 +580,79 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
diff --git a/Sources/EPiServer.Reference.Commerce.Shared/EPiServer.Reference.Commerce.Shared.csproj b/Sources/EPiServer.Reference.Commerce.Shared/EPiServer.Reference.Commerce.Shared.csproj
index 1c93fcda..354daec9 100644
--- a/Sources/EPiServer.Reference.Commerce.Shared/EPiServer.Reference.Commerce.Shared.csproj
+++ b/Sources/EPiServer.Reference.Commerce.Shared/EPiServer.Reference.Commerce.Shared.csproj
@@ -267,79 +267,79 @@
-->
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\EPiServer.Business.Commerce.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\EPiServer.Business.Commerce.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\EPiServer.Commerce.Internal.Migration.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\EPiServer.Commerce.Internal.Migration.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.BusinessFoundation.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.BusinessFoundation.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.BusinessFoundation.Data.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.BusinessFoundation.Data.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.Commerce.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.Commerce.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.Commerce.Marketing.Validators.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.Commerce.Marketing.Validators.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.Commerce.Plugins.Payment.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.Commerce.Plugins.Payment.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.Commerce.Plugins.Shipping.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.Commerce.Plugins.Shipping.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.Commerce.Website.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.Commerce.Website.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.Commerce.Workflow.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.Commerce.Workflow.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.DataProvider.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.DataProvider.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.FileUploader.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.FileUploader.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.MetaDataPlus.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.MetaDataPlus.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.Search.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.Search.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.Search.Extensions.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.Search.Extensions.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.Search.LuceneSearchProvider.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.Search.LuceneSearchProvider.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.SqlDataProvider.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.SqlDataProvider.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.WebConsoleLib.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.WebConsoleLib.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\AjaxControlToolkit.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\AjaxControlToolkit.dll
True
diff --git a/Sources/EPiServer.Reference.Commerce.Shared/packages.config b/Sources/EPiServer.Reference.Commerce.Shared/packages.config
index 8bc0aa7c..84e02f32 100644
--- a/Sources/EPiServer.Reference.Commerce.Shared/packages.config
+++ b/Sources/EPiServer.Reference.Commerce.Shared/packages.config
@@ -39,5 +39,5 @@
-
+
diff --git a/Sources/EPiServer.Reference.Commerce.Site.Tests/EPiServer.Reference.Commerce.Site.Tests.csproj b/Sources/EPiServer.Reference.Commerce.Site.Tests/EPiServer.Reference.Commerce.Site.Tests.csproj
index 3a0d316b..fbef2854 100644
--- a/Sources/EPiServer.Reference.Commerce.Site.Tests/EPiServer.Reference.Commerce.Site.Tests.csproj
+++ b/Sources/EPiServer.Reference.Commerce.Site.Tests/EPiServer.Reference.Commerce.Site.Tests.csproj
@@ -411,91 +411,91 @@
-->
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\EPiServer.Business.Commerce.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\EPiServer.Business.Commerce.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\EPiServer.Commerce.Reporting.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\EPiServer.Commerce.Reporting.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\EPiServer.Commerce.Internal.Migration.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\EPiServer.Commerce.Internal.Migration.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.BusinessFoundation.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.BusinessFoundation.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.BusinessFoundation.Data.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.BusinessFoundation.Data.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.Commerce.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.Commerce.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.Commerce.Marketing.Validators.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.Commerce.Marketing.Validators.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.Commerce.Plugins.Payment.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.Commerce.Plugins.Payment.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.Commerce.Plugins.Shipping.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.Commerce.Plugins.Shipping.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.Commerce.Website.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.Commerce.Website.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.Commerce.Workflow.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.Commerce.Workflow.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.DataProvider.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.DataProvider.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.FileUploader.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.FileUploader.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.MetaDataPlus.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.MetaDataPlus.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.Search.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.Search.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.Search.Extensions.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.Search.Extensions.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.Search.LuceneSearchProvider.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.Search.LuceneSearchProvider.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.SqlDataProvider.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.SqlDataProvider.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\Mediachase.WebConsoleLib.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\Mediachase.WebConsoleLib.dll
True
- ..\..\packages\EPiServer.Tracking.Commerce.3.2.18\lib\net461\EPiServer.Tracking.Commerce.dll
+ ..\..\packages\EPiServer.Tracking.Commerce.3.2.23\lib\net461\EPiServer.Tracking.Commerce.dll
True
- ..\..\packages\EPiServer.Personalization.Commerce.3.2.18\lib\net461\EPiServer.Personalization.Commerce.dll
+ ..\..\packages\EPiServer.Personalization.Commerce.3.2.23\lib\net461\EPiServer.Personalization.Commerce.dll
True
- ..\..\packages\EPiServer.Commerce.Core.13.22.0\lib\net461\AjaxControlToolkit.dll
+ ..\..\packages\EPiServer.Commerce.Core.13.26.0\lib\net461\AjaxControlToolkit.dll
True
diff --git a/Sources/EPiServer.Reference.Commerce.Site.Tests/packages.config b/Sources/EPiServer.Reference.Commerce.Site.Tests/packages.config
index 6b6c9a26..4d741a0d 100644
--- a/Sources/EPiServer.Reference.Commerce.Site.Tests/packages.config
+++ b/Sources/EPiServer.Reference.Commerce.Site.Tests/packages.config
@@ -60,7 +60,7 @@
-
-
-
+
+
+
diff --git a/Sources/EPiServer.Reference.Commerce.Site/CSRExtensibility/CSRCustomUI.cs b/Sources/EPiServer.Reference.Commerce.Site/CSRExtensibility/CSRCustomUI.cs
new file mode 100644
index 00000000..b4def68b
--- /dev/null
+++ b/Sources/EPiServer.Reference.Commerce.Site/CSRExtensibility/CSRCustomUI.cs
@@ -0,0 +1,15 @@
+using EPiServer.Commerce.UI.CustomerService.Extensibility;
+using EPiServer.ServiceLocation;
+
+namespace EPiServer.Reference.Commerce.Site.CSRExtensibility
+{
+ [ServiceConfiguration(typeof(CSRUIExtensionConfiguration))]
+ public class CSRCustomUI : CSRUIExtensionConfiguration
+ {
+ public CSRCustomUI()
+ {
+ // comment out the line below to make the CSR extended components samples visible
+ //ResourceScripts = new string[] { "/CSRExtensibility/react-app/dist/customized-csr-bundle.min.js" };
+ }
+ }
+}
\ No newline at end of file
diff --git a/Sources/EPiServer.Reference.Commerce.Site/CSRExtensibility/Controllers/DemoApiController.cs b/Sources/EPiServer.Reference.Commerce.Site/CSRExtensibility/Controllers/DemoApiController.cs
new file mode 100644
index 00000000..3ec1fa62
--- /dev/null
+++ b/Sources/EPiServer.Reference.Commerce.Site/CSRExtensibility/Controllers/DemoApiController.cs
@@ -0,0 +1,17 @@
+using EPiServer.Commerce.UI.CustomerService.Extensibility;
+using EPiServer.Commerce.UI.CustomerService.Routing;
+using System.Web.Http;
+
+namespace EPiServer.Reference.Commerce.Site.CSRExtensibility.Controllers
+{
+ [EpiRoutePrefix("csr-demo")]
+ public class DemoApiController: CSRAPIController
+ {
+ [HttpGet]
+ [EpiRoute("getData")]
+ public IHttpActionResult Get()
+ {
+ return Ok("Sample data");
+ }
+ }
+}
\ No newline at end of file
diff --git a/Sources/EPiServer.Reference.Commerce.Site/CSRExtensibility/react-app/.env b/Sources/EPiServer.Reference.Commerce.Site/CSRExtensibility/react-app/.env
new file mode 100644
index 00000000..57727ee9
--- /dev/null
+++ b/Sources/EPiServer.Reference.Commerce.Site/CSRExtensibility/react-app/.env
@@ -0,0 +1 @@
+PORT=4000
\ No newline at end of file
diff --git a/Sources/EPiServer.Reference.Commerce.Site/CSRExtensibility/react-app/.gitignore b/Sources/EPiServer.Reference.Commerce.Site/CSRExtensibility/react-app/.gitignore
new file mode 100644
index 00000000..32d6f947
--- /dev/null
+++ b/Sources/EPiServer.Reference.Commerce.Site/CSRExtensibility/react-app/.gitignore
@@ -0,0 +1,28 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+
+# testing
+/coverage
+
+# production
+/build
+
+# misc
+.DS_Store
+.env.local
+.env.development.local
+.env.test.local
+.env.production.local
+
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+internal-npm-packages/csr-app/node_modules
+
+yarn.lock
+
+/dist/static
\ No newline at end of file
diff --git a/Sources/EPiServer.Reference.Commerce.Site/CSRExtensibility/react-app/README.md b/Sources/EPiServer.Reference.Commerce.Site/CSRExtensibility/react-app/README.md
new file mode 100644
index 00000000..0013a666
--- /dev/null
+++ b/Sources/EPiServer.Reference.Commerce.Site/CSRExtensibility/react-app/README.md
@@ -0,0 +1,110 @@
+## Introduction
+For the CSR Extensibility feature, we created a sample react project, including:
+- @episerver/csr-extension: use this package for declaring extension configuration.
+- @episerver/csr-app : use this package for debugging purpose.
+- scripts: to build the bundle config file and use it for injecting to CSR
+
+## Basic setup
+Below are the basic steps to add a CSR extension module
+- Declare a setting object
+ - We already defined `demo-setting.tsx` with sample configuration. You can change those configurations.
+- Call function `CSRExtension.InitConfiguration` with `setting` object you defined as param.
+ - This function was defined by CSR itself. When you want to make a change to setting object, call function `CSRExtension.InitConfiguration` again.
+- Create a bundle file from `csr-extension.tsx` as entry point by using script `yarn package`
+ - This script will output bundle file at `dist` folder
+- Specify js and css files which will be injected into CSR
+ - By default, Quicksilver take `customized-csr-bundle.min.js` file and inject into current CSR page.
+
+ You can change the injected js, css file at `CSRExtensibility/CSRCustomUI.cs`
+
+ Sample code
+
+ ```c#
+ namespace EPiServer.Reference.Commerce.Site.UIComponents
+ {
+ [ServiceConfiguration(typeof(CSRUIExtensionConfiguration))]
+ public class CSRCustomUI : CSRUIExtensionConfiguration
+ {
+ public CSRCustomUI()
+ {
+ ResourceScripts = new string[] { "/CSRExtensibility/react-app/dist/customized-csr-bundle.min.js" };
+
+ ResourceStyles = new string[]{};
+ }
+ }
+ }
+ ```
+ You can add ResourceStyles and ResourceScripts. We will take those files and inject into CSR.
+
+
+## Available Scripts
+
+### `yarn package` and `yarn package:dev`
+
+This script will bundle `src/configuration/csr-extension.tsx` file and output result to `dist` folder.
+If you want to pack in the development environment, you can use `yarn package:dev`. This will output bundle file without minified, for debugging.
+
+## Define new API controller
+When there is a need to define new API for specific job, you can do by your own or using `HTTPRequest` included in the @episerver/csr-extension package.
+HTTPRequest is an axios instance come with the baseURL config.
+
+- First, create a new Controller where extend CSRAPIController at server side:
+```c#
+[EpiRoutePrefix("csr-demo")]
+public class DemoApiController: CSRAPIController
+{
+ [HttpGet]
+ [EpiRoute("getData")]
+ public IHttpActionResult Get()
+ {
+ return Ok("Sample data");
+ }
+}
+```
+- Then make API request at the front-end side:
+```javascript
+import { HttpRequest } from '@episerver/csr-extension';
+
+HTTPRequest.get('csr-demo/getData').then(resp => {
+ console.log(resp.data);
+});
+
+```
+
+## Development environment
+### How to debug the extension bundle in CSR app
+We had exported CSRApp component include in internal `@episerver/csr-app` package
+Follow these steps to setup debug environment:
+- Declare component and passing `setting` object via props
+- Setup local environment of the Quicksilver site and config proxy at `setupProxy.js` in the `src` folder
+
+Here is the sample code to running CSRApp in the development evironment
+```javascript
+import * as React from 'react';
+import ReactDOM from 'react-dom';
+import { CSRApp } from '@episerver/csr-app';
+import { setting } from './configuration/demo-setting';
+
+import '@episerver/csr-app/bundle.css';
+
+ReactDOM.render(
+
+
+
,
+ document.getElementById('root')
+);
+```
+
+- run `yarn start` to start debugging
+
+## Important Notes
+
+- To use the react hook, please config react as an external library. By default, we already set externals config at `webpack.extension.config.js` file
+```javascript
+externals: {
+ react: 'React'
+},
+```
+We also injected the react library into CSR as a separate library, so that it guarantees the existing CSR and extension share the same react library.
+
+
diff --git a/Sources/EPiServer.Reference.Commerce.Site/CSRExtensibility/react-app/config/env.js b/Sources/EPiServer.Reference.Commerce.Site/CSRExtensibility/react-app/config/env.js
new file mode 100644
index 00000000..09ec03c5
--- /dev/null
+++ b/Sources/EPiServer.Reference.Commerce.Site/CSRExtensibility/react-app/config/env.js
@@ -0,0 +1,101 @@
+'use strict';
+
+const fs = require('fs');
+const path = require('path');
+const paths = require('./paths');
+
+// Make sure that including paths.js after env.js will read .env variables.
+delete require.cache[require.resolve('./paths')];
+
+const NODE_ENV = process.env.NODE_ENV;
+if (!NODE_ENV) {
+ throw new Error(
+ 'The NODE_ENV environment variable is required but was not specified.'
+ );
+}
+
+// https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use
+const dotenvFiles = [
+ `${paths.dotenv}.${NODE_ENV}.local`,
+ `${paths.dotenv}.${NODE_ENV}`,
+ // Don't include `.env.local` for `test` environment
+ // since normally you expect tests to produce the same
+ // results for everyone
+ NODE_ENV !== 'test' && `${paths.dotenv}.local`,
+ paths.dotenv,
+].filter(Boolean);
+
+// Load environment variables from .env* files. Suppress warnings using silent
+// if this file is missing. dotenv will never modify any environment variables
+// that have already been set. Variable expansion is supported in .env files.
+// https://github.com/motdotla/dotenv
+// https://github.com/motdotla/dotenv-expand
+dotenvFiles.forEach(dotenvFile => {
+ if (fs.existsSync(dotenvFile)) {
+ require('dotenv-expand')(
+ require('dotenv').config({
+ path: dotenvFile,
+ })
+ );
+ }
+});
+
+// We support resolving modules according to `NODE_PATH`.
+// This lets you use absolute paths in imports inside large monorepos:
+// https://github.com/facebook/create-react-app/issues/253.
+// It works similar to `NODE_PATH` in Node itself:
+// https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders
+// Note that unlike in Node, only *relative* paths from `NODE_PATH` are honored.
+// Otherwise, we risk importing Node.js core modules into an app instead of webpack shims.
+// https://github.com/facebook/create-react-app/issues/1023#issuecomment-265344421
+// We also resolve them to make sure all tools using them work consistently.
+const appDirectory = fs.realpathSync(process.cwd());
+process.env.NODE_PATH = (process.env.NODE_PATH || '')
+ .split(path.delimiter)
+ .filter(folder => folder && !path.isAbsolute(folder))
+ .map(folder => path.resolve(appDirectory, folder))
+ .join(path.delimiter);
+
+// Grab NODE_ENV and REACT_APP_* environment variables and prepare them to be
+// injected into the application via DefinePlugin in webpack configuration.
+const REACT_APP = /^REACT_APP_/i;
+
+function getClientEnvironment(publicUrl) {
+ const raw = Object.keys(process.env)
+ .filter(key => REACT_APP.test(key))
+ .reduce(
+ (env, key) => {
+ env[key] = process.env[key];
+ return env;
+ },
+ {
+ // Useful for determining whether we’re running in production mode.
+ // Most importantly, it switches React into the correct mode.
+ NODE_ENV: process.env.NODE_ENV || 'development',
+ // Useful for resolving the correct path to static assets in `public`.
+ // For example, .
+ // This should only be used as an escape hatch. Normally you would put
+ // images into the `src` and `import` them in code to get their paths.
+ PUBLIC_URL: publicUrl,
+ // We support configuring the sockjs pathname during development.
+ // These settings let a developer run multiple simultaneous projects.
+ // They are used as the connection `hostname`, `pathname` and `port`
+ // in webpackHotDevClient. They are used as the `sockHost`, `sockPath`
+ // and `sockPort` options in webpack-dev-server.
+ WDS_SOCKET_HOST: process.env.WDS_SOCKET_HOST,
+ WDS_SOCKET_PATH: process.env.WDS_SOCKET_PATH,
+ WDS_SOCKET_PORT: process.env.WDS_SOCKET_PORT,
+ }
+ );
+ // Stringify all values so we can feed into webpack DefinePlugin
+ const stringified = {
+ 'process.env': Object.keys(raw).reduce((env, key) => {
+ env[key] = JSON.stringify(raw[key]);
+ return env;
+ }, {}),
+ };
+
+ return { raw, stringified };
+}
+
+module.exports = getClientEnvironment;
diff --git a/Sources/EPiServer.Reference.Commerce.Site/CSRExtensibility/react-app/config/getHttpsConfig.js b/Sources/EPiServer.Reference.Commerce.Site/CSRExtensibility/react-app/config/getHttpsConfig.js
new file mode 100644
index 00000000..013d493c
--- /dev/null
+++ b/Sources/EPiServer.Reference.Commerce.Site/CSRExtensibility/react-app/config/getHttpsConfig.js
@@ -0,0 +1,66 @@
+'use strict';
+
+const fs = require('fs');
+const path = require('path');
+const crypto = require('crypto');
+const chalk = require('react-dev-utils/chalk');
+const paths = require('./paths');
+
+// Ensure the certificate and key provided are valid and if not
+// throw an easy to debug error
+function validateKeyAndCerts({ cert, key, keyFile, crtFile }) {
+ let encrypted;
+ try {
+ // publicEncrypt will throw an error with an invalid cert
+ encrypted = crypto.publicEncrypt(cert, Buffer.from('test'));
+ } catch (err) {
+ throw new Error(
+ `The certificate "${chalk.yellow(crtFile)}" is invalid.\n${err.message}`
+ );
+ }
+
+ try {
+ // privateDecrypt will throw an error with an invalid key
+ crypto.privateDecrypt(key, encrypted);
+ } catch (err) {
+ throw new Error(
+ `The certificate key "${chalk.yellow(keyFile)}" is invalid.\n${
+ err.message
+ }`
+ );
+ }
+}
+
+// Read file and throw an error if it doesn't exist
+function readEnvFile(file, type) {
+ if (!fs.existsSync(file)) {
+ throw new Error(
+ `You specified ${chalk.cyan(
+ type
+ )} in your env, but the file "${chalk.yellow(file)}" can't be found.`
+ );
+ }
+ return fs.readFileSync(file);
+}
+
+// Get the https config
+// Return cert files if provided in env, otherwise just true or false
+function getHttpsConfig() {
+ const { SSL_CRT_FILE, SSL_KEY_FILE, HTTPS } = process.env;
+ const isHttps = HTTPS === 'true';
+
+ if (isHttps && SSL_CRT_FILE && SSL_KEY_FILE) {
+ const crtFile = path.resolve(paths.appPath, SSL_CRT_FILE);
+ const keyFile = path.resolve(paths.appPath, SSL_KEY_FILE);
+ const config = {
+ cert: readEnvFile(crtFile, 'SSL_CRT_FILE'),
+ key: readEnvFile(keyFile, 'SSL_KEY_FILE'),
+ };
+
+ validateKeyAndCerts({ ...config, keyFile, crtFile });
+ return config;
+ }
+ return isHttps;
+}
+
+module.exports = getHttpsConfig;
diff --git a/Sources/EPiServer.Reference.Commerce.Site/CSRExtensibility/react-app/config/jest/fileTransform.js b/Sources/EPiServer.Reference.Commerce.Site/CSRExtensibility/react-app/config/jest/fileTransform.js
new file mode 100644
index 00000000..aab67618
--- /dev/null
+++ b/Sources/EPiServer.Reference.Commerce.Site/CSRExtensibility/react-app/config/jest/fileTransform.js
@@ -0,0 +1,40 @@
+'use strict';
+
+const path = require('path');
+const camelcase = require('camelcase');
+
+// This is a custom Jest transformer turning file imports into filenames.
+// http://facebook.github.io/jest/docs/en/webpack.html
+
+module.exports = {
+ process(src, filename) {
+ const assetFilename = JSON.stringify(path.basename(filename));
+
+ if (filename.match(/\.svg$/)) {
+ // Based on how SVGR generates a component name:
+ // https://github.com/smooth-code/svgr/blob/01b194cf967347d43d4cbe6b434404731b87cf27/packages/core/src/state.js#L6
+ const pascalCaseFilename = camelcase(path.parse(filename).name, {
+ pascalCase: true,
+ });
+ const componentName = `Svg${pascalCaseFilename}`;
+ return `const React = require('react');
+ module.exports = {
+ __esModule: true,
+ default: ${assetFilename},
+ ReactComponent: React.forwardRef(function ${componentName}(props, ref) {
+ return {
+ $$typeof: Symbol.for('react.element'),
+ type: 'svg',
+ ref: ref,
+ key: null,
+ props: Object.assign({}, props, {
+ children: ${assetFilename}
+ })
+ };
+ }),
+ };`;
+ }
+
+ return `module.exports = ${assetFilename};`;
+ },
+};
diff --git a/Sources/EPiServer.Reference.Commerce.Site/CSRExtensibility/react-app/config/modules.js b/Sources/EPiServer.Reference.Commerce.Site/CSRExtensibility/react-app/config/modules.js
new file mode 100644
index 00000000..c8efd0dd
--- /dev/null
+++ b/Sources/EPiServer.Reference.Commerce.Site/CSRExtensibility/react-app/config/modules.js
@@ -0,0 +1,141 @@
+'use strict';
+
+const fs = require('fs');
+const path = require('path');
+const paths = require('./paths');
+const chalk = require('react-dev-utils/chalk');
+const resolve = require('resolve');
+
+/**
+ * Get additional module paths based on the baseUrl of a compilerOptions object.
+ *
+ * @param {Object} options
+ */
+function getAdditionalModulePaths(options = {}) {
+ const baseUrl = options.baseUrl;
+
+ // We need to explicitly check for null and undefined (and not a falsy value) because
+ // TypeScript treats an empty string as `.`.
+ if (baseUrl == null) {
+ // If there's no baseUrl set we respect NODE_PATH
+ // Note that NODE_PATH is deprecated and will be removed
+ // in the next major release of create-react-app.
+
+ const nodePath = process.env.NODE_PATH || '';
+ return nodePath.split(path.delimiter).filter(Boolean);
+ }
+
+ const baseUrlResolved = path.resolve(paths.appPath, baseUrl);
+
+ // We don't need to do anything if `baseUrl` is set to `node_modules`. This is
+ // the default behavior.
+ if (path.relative(paths.appNodeModules, baseUrlResolved) === '') {
+ return null;
+ }
+
+ // Allow the user set the `baseUrl` to `appSrc`.
+ if (path.relative(paths.appSrc, baseUrlResolved) === '') {
+ return [paths.appSrc];
+ }
+
+ // If the path is equal to the root directory we ignore it here.
+ // We don't want to allow importing from the root directly as source files are
+ // not transpiled outside of `src`. We do allow importing them with the
+ // absolute path (e.g. `src/Components/Button.js`) but we set that up with
+ // an alias.
+ if (path.relative(paths.appPath, baseUrlResolved) === '') {
+ return null;
+ }
+
+ // Otherwise, throw an error.
+ throw new Error(
+ chalk.red.bold(
+ "Your project's `baseUrl` can only be set to `src` or `node_modules`." +
+ ' Create React App does not support other values at this time.'
+ )
+ );
+}
+
+/**
+ * Get webpack aliases based on the baseUrl of a compilerOptions object.
+ *
+ * @param {*} options
+ */
+function getWebpackAliases(options = {}) {
+ const baseUrl = options.baseUrl;
+
+ if (!baseUrl) {
+ return {};
+ }
+
+ const baseUrlResolved = path.resolve(paths.appPath, baseUrl);
+
+ if (path.relative(paths.appPath, baseUrlResolved) === '') {
+ return {
+ src: paths.appSrc,
+ };
+ }
+}
+
+/**
+ * Get jest aliases based on the baseUrl of a compilerOptions object.
+ *
+ * @param {*} options
+ */
+function getJestAliases(options = {}) {
+ const baseUrl = options.baseUrl;
+
+ if (!baseUrl) {
+ return {};
+ }
+
+ const baseUrlResolved = path.resolve(paths.appPath, baseUrl);
+
+ if (path.relative(paths.appPath, baseUrlResolved) === '') {
+ return {
+ '^src/(.*)$': '/src/$1',
+ };
+ }
+}
+
+function getModules() {
+ // Check if TypeScript is setup
+ const hasTsConfig = fs.existsSync(paths.appTsConfig);
+ const hasJsConfig = fs.existsSync(paths.appJsConfig);
+
+ if (hasTsConfig && hasJsConfig) {
+ throw new Error(
+ 'You have both a tsconfig.json and a jsconfig.json. If you are using TypeScript please remove your jsconfig.json file.'
+ );
+ }
+
+ let config;
+
+ // If there's a tsconfig.json we assume it's a
+ // TypeScript project and set up the config
+ // based on tsconfig.json
+ if (hasTsConfig) {
+ const ts = require(resolve.sync('typescript', {
+ basedir: paths.appNodeModules,
+ }));
+ config = ts.readConfigFile(paths.appTsConfig, ts.sys.readFile).config;
+ // Otherwise we'll check if there is jsconfig.json
+ // for non TS projects.
+ } else if (hasJsConfig) {
+ config = require(paths.appJsConfig);
+ }
+
+ config = config || {};
+ const options = config.compilerOptions || {};
+
+ const additionalModulePaths = getAdditionalModulePaths(options);
+
+ return {
+ additionalModulePaths: additionalModulePaths,
+ webpackAliases: getWebpackAliases(options),
+ jestAliases: getJestAliases(options),
+ hasTsConfig,
+ };
+}
+
+module.exports = getModules();
diff --git a/Sources/EPiServer.Reference.Commerce.Site/CSRExtensibility/react-app/config/paths.js b/Sources/EPiServer.Reference.Commerce.Site/CSRExtensibility/react-app/config/paths.js
new file mode 100644
index 00000000..78696f36
--- /dev/null
+++ b/Sources/EPiServer.Reference.Commerce.Site/CSRExtensibility/react-app/config/paths.js
@@ -0,0 +1,72 @@
+'use strict';
+
+const path = require('path');
+const fs = require('fs');
+const getPublicUrlOrPath = require('react-dev-utils/getPublicUrlOrPath');
+
+// Make sure any symlinks in the project folder are resolved:
+// https://github.com/facebook/create-react-app/issues/637
+const appDirectory = fs.realpathSync(process.cwd());
+const resolveApp = relativePath => path.resolve(appDirectory, relativePath);
+
+// We use `PUBLIC_URL` environment variable or "homepage" field to infer
+// "public path" at which the app is served.
+// webpack needs to know it to put the right