Next-generation platform

Modifying application-provided screens

The screens in Sterling Store Engagement are modeled as angular routes. You can customize the application-provided screens as needed for your business.

About this task

A page component is a route-level angular component that is used to define a route in a routing module. These components are suffixed with PageComponent in the class.

The following example illustrates a route definition where ShipmentSummaryPageComponent is a page component.
{
path: 'summary/:shipmentKey',
component: ShipmentSummaryPageComponent
}

Procedure

  1. Identify the single-spa application that contains the screen you want to customize. You can identify the single-spa application by looking at the URL in the address bar of the browser.
    For example, if you are customizing the Shipment summary screen, the URL is https://<hostname>:<port>/isf/store-frontend/shell/shipment/summary/<ShipmentKey>
    All the URLs in Sterling Store Engagement contain /isf/store-frontend/shell in common followed by the screen-specific route path. If the Shipment summary screen, the screen-specific route path is /shipment/summary/<ShipmentKey>. Consider the first fragment of the route path, which is shipment. However, in most of the cases, the first fragment is the application name, with few exceptions. The following table describes the exceptional fragments:
    Table 1. Exceptional fragments
    First fragment Application name
    order orders
    ship-package ship-packages
    return returns
    shipment shipment-list-summary
    customer customer-profile

    In the specified example, the first fragment is shipment, which is part of the exception table and the application name is shipment-list-summary. The source code for the identified application is present in the <store-temp>/packages/features/<application name> folder. For the shipment-list-summary application, the source code is present in the <store-temp>/packages/features/shipment-list-summary folder.

    Consider another example of the list screen in the pack order flow. The URL for the Pack order list screen is http://<host-name>:<port>/isf/store-frontend/shell/pack-order/pack-order-list. The first fragment in the route path is pack-order. Observe that pack-order is not part of the exception table. Therefore, the application name is the same as the first fragment, which is pack-order. The source code is present in the <store-temp>/packages/features/pack-order folder.

  2. Determine the page component within the shipment-list-summary application by considering the angular route path.

    It is now clear that for the route path for shipment summary is shipment/summary/<ShipmentKey>.

    To find the page component, see the routing module within <store-temp>/packages/features/shipment-list-summary and match with the route path.

    If the Shipment summary screen, the route path is matched within <store-temp>/packages/features/shipment-list-summary/src/app/features/shipment-list-summary/shipment-list-summary-routing.module.ts for which the route is as follows:
    {
        path: 'summary/:shipmentKey',
        component: ShipmentSummaryPageComponent
      }
    From the route configuration, you can identify the page component as ShipmentSummaryPageComponent. The routing module file also contains the import statement for the ShipmentSummaryPageComponent page component, which describes where the component is present in the source code.
    import { ShipmentSummaryPageComponent } from './shipment-summary-page/shipment-summary-page.component';

    The ShipmentSummaryPageComponent is present in the <store-temp>/packages/features/shipment-list-summary/src/app/features/shipment-list-summary/shipment-summary-page folder.

  3. Browse to the <store-temp> directory, and run the following command:
    yarn override-route --module-name=<module-name> --override-module-name=<override-module-name> --override-component-folder-name=<component-name> --port=<port>
    For example,
    yarn override-route --override-module-name=shipment-list-summary --module-name=custom-shipment-list-summary  --override-component-folder-name=shipment-summary-page --port=6785
    In this command:
    • --override-module-name refers to the name of the application that contains the application-provided screen. The application name for the Shipment summary screen is shipment-list-summary.
    • --module-name refers to the name of the extension application that must be created and can be any valid name. As a best practice, prefix the custom name to the application name and use it as the module-name. For example, custom-shipment-list-summary.
    • --override-component-folder-name refers to the folder name of the application-provided page component that you want to override.

      In step 2, for the page component you identified the folder name as shipment-summary-page.

    • --port refers to the port number where the new application runs.
    The override-route CLI command completes the following tasks:
    • Creates an angular application with isf as the prefix in the <store-temp>/extensions/features folder. The source code is present in the <store-temp>/extensions/features/<module-name> folder.
    • Installs the single-spa-angular node module in the angular application that is created.
    • Generates the main.single-spa.ts file in the src project folder.
    • Generates a lazy loaded module with <module-name> in the <store-temp>/extensions/features/<module-name>/src/app project folder.
    • Updates the <store-temp>/extensions/features/<module-name>/src/app-routing.module.ts routing module file with the following route definitions:
      • Lazy loaded module with the appropriate route path definition.
      • EmptyRouteComponent for the unmatched routes.
    • Updates the package.json file with start and build scripts of the application.
    • Registers the new application in the <store-temp>/extensions/override-static-assets/root-config/custom/import-map.json file. The import-map.json file registers the JavaScript module to load the specific application.
    • To support localization and internationalization, the command generates the i18n folders in the <store-temp>/extensions/features/<module-name>/src/assets project folder and maintains the language-specific bundle JSON files. An empty en.json bundle JSON file is generated in the <store-temp>/extensions/features/<module-name>/src/assets/<module-name>/i18n project folder. The code is also updated to set up TranslateModule to load the appropriate translation bundle JSON files.
    • Copies the component folder that is specified in the --override-component-folder-name parameter to the <store-temp>/extensions/features/<module-name>/src/app/features/<module-name> folder. The files present in the component folder are used to override the application-provided screen.
    • Automatically imports the dependent angular services and components into the extension application module ts file, store-temp>/extensions/features/<module-name>/src/app/features/<module-name>.module.ts. However, if the providers array is defined in the <module-name>.module.ts file of the source code, the CLI command does not copy the providers array. Manually copy the providers array to the /extensions/features/src/app/features/<module-name>.module.ts and import the dependencies that are copied as part of the providers array.
      For example, if you are extending PickOrderPageComponent from shipment-backroom-pick, the shipment-backroom-pick.module.ts file contains the defined providers array.
      providers: [
          AlertModalService,
          PickOrderDataService,
          ValidatePickOrderGuard,
          PickOrderRTConfig
        ]
      From the shipment-backroom-pick.module.ts file, copy the providers array to the corresponding module.ts file in extensions. Add import statements for each of the entry in providers as illustrated.
      import { AlertModalService } from '@store/core';
      import { PickOrderDataService } from './pick-order-page/pick-order-data.service';
      import { ValidatePickOrderGuard } from './pick-order-page/validate-pick-order.guard';
      import { PickOrderRTConfig } from './pick-order-page/pick-order-rt-config';
      Note: The CLI command copies only the files that are present in the component folder. If the extended component imports files that are outside of the component folder, ensure that you manually copy such files to the appropriate location within the new extension application. Then, import and declare such dependencies in the <store-temp>/extensions/features/<module-name>/src/app/features/<module-name>/<module-name>.module.ts extension module file.
    • Updates the following entry for the custom import-map.json file that is present in the <store-temp>/extensions/override-static-assets/root-config/custom/ folder.
      {
        "imports": {
          "<module-name>": "/<module-name>/main.js"
        }
      }
    Note: If you are extending any route from shipment-backroom-pick or shipment-batch-pick single-spa applications, add an entry in the app.module.ts file of the extended application to have assets included from backroom-pick and batch-pick, respectively. For example,
    class CustomShipmentBackroomPickBundlesModule {
        static bundles: Array<any> = [
          {
            prefix: './assets/shipment-backroom-pick/i18n/',
            suffix: '.json'
          },
          {
            prefix: './assets/backroom-pick/i18n/',
            suffix: '.json'
          },
          {
            prefix: './assets/custom-shipment-backroom-pick/i18n/',
            suffix: '.json'
          }
        ].concat(CommonBundlesModule.bundles);
      };
  4. Update the route definition of the overridden route in the lazy loaded routing module.ts file (<store-temp>/extensions/features/<module-name>/src/app/features/<module-name>/<module-name>-routing.module.ts) and add the import statement for the component.
    For the shipment summary example, you must update <store-temp>/extensions/features/custom-shipment-list-summary/src/app/features/custom-shipment-list-summary/custom-shipment-list-summary-routing.module.ts

    Update the routes array with the route that is determined in step 2.

    The following sample code illustrates the behavior before and after an update:
    • Before update
      import { NgModule } from '@angular/core';
      import { Routes, RouterModule } from '@angular/router';
      
      const routes: Routes = [
      ];
      
      @NgModule({
        imports: [RouterModule.forChild(routes)],
        exports: [RouterModule]
      })
      export class CustomShipmentListSummaryRoutingModule { }
    • After update
      import { NgModule } from '@angular/core';
      import { Routes, RouterModule } from '@angular/router';
      import { ShipmentSummaryPageComponent } from './shipment-summary-page/shipment-summary-page.component';
      
      const routes: Routes = [
        {
          path: 'summary/:shipmentKey',
          component: ShipmentSummaryPageComponent
        }
      ];
      
      @NgModule({
        imports: [RouterModule.forChild(routes)],
        exports: [RouterModule]
      })
      export class CustomShipmentListSummaryRoutingModule { }
  5. Identify the route entry in the feature-routes.json file that is present in the <store-temp>/packages/apps/store-root-app/src/assets/root-config/config/ folder
    For example, identify the route definitions for the shipment-list-summary application in the feature-routes.json file by searching for "name": "shipment-list-summary". The following list of routes are applicable for the shipment-list-summary application.
    {
    "type": "route",
    "path": "shell/shipment",
    "routes": [
    {
    "type": "application",
    "name": "shipment-list-summary"
    }
    ]
    },
    {
    "type": "route",
    "path": "shell/shipment/list",
    "routes": [
    {
    "type": "application",
    "name": "shipment-list-summary"
    }
    ]
    },
    {
    "type": "route",
    "path": "shell/shipment/summary/:shipmentKey",
    "routes": [
    {
    "type": "application",
    "name": "shipment-list-summary"
    }
    ]
    }

    To identify the route definition for the Shipment summary screen, consider the URL http://<hostname>:port/isf/store-frontend/shell/shipment/summary/<ShipmentKey>.

    The relative URL for the shipment summary route is, shell/shipment/summary/<shipmentKey>. For relative URL, find the matching entry from the list by comparing with the path attribute.

    The following code snippet illustrates the matching entry in the feature-routes.json file.
    {
    "type": "route",
    "path": "shell/shipment/summary/:shipmentKey",
    "routes": [
    {
    "type": "application",
    "name": "shipment-list-summary"
    }
    ]
    }
  6. Copy the matching entry from step 5 to the <store-temp>/extensions/override-static-assets/root-config/custom/routes.json file and update the application name with the <module-name> argument that is used in step 3.
    For example,
    {
    "type": "route",
    "path": "shell/shipment/summary/:shipmentKey",
    "routes": [
    {
    "type": "application",
    "name": "custom-shipment-list-summary"
    }
    ]
    }

    As illustrated in the sample snippet, the entry maps the application-provided route with the custom application, and also ensures that the route is loaded from the custom application.

What to do next

  • To locally verify the extended application-provided screen, start the application.

    To start the application, run the following command:

    yarn start-app
  • To verify the changes in the developer toolkit, extract and deploy the customizations. For more information, see Extracting customizations.