vlocity-dc-assets-list/vlocity-dc-assets-list.js

/*************************************************************************
 *
 * VLOCITY, INC. CONFIDENTIAL
 * __________________
 *
 *  [2014] - [2020] Vlocity, Inc.
 *  All Rights Reserved.
 *
 * NOTICE:  All information contained herein is, and remains
 * the property of Vlocity, Inc. and its suppliers,
 * if any. The intellectual and technical concepts contained
 * herein are proprietary to Vlocity, Inc. and its suppliers and may be
 * covered by U.S. and Foreign Patents, patents in process, and are
 * protected by trade secret or copyright law. Dissemination of this
 * information and reproduction, modification or reverse-engineering
 * of this material, is prohibited unless prior written permission
 * is obtained from Vlocity, Inc.
 *
 */
import { LitElement } from "lit-element";
import assetsListTemplate from "./vlocity-dc-assets-list.template";
import { digitalCommerceSDKInstance } from "../vlocity-dc-utils/vlocity-dc-sdk-utils";
import VlocityDCBaseComponent from "../vlocity-dc-base-component/vlocity-dc-base-component";

/**
 * @class VlocityDCAssetsList
 * @extends {LitElement} Extend the LitElement base class
 *
 * @classdesc
 * vlocity-dc-assets-list is the component for displaying all the assets.
 * @property {Array} assets - array containing list of all assets.
 *
 * @example
 * Sample Usage -
 *
 * Include the component in your template by adding vlocity-dc-assets-list custom tag
 *
 * <vlocity-dc-assets-list .assets="${assetsList}"></vlocity-dc-assets-list>
 *
 * | Attribute Name    | Type Expected                                                                   | Required |
 * |-------------------|---------------------------------------------------------------------------------|----------|
 * | assets            | It expects an array which contains a list of all assets                         |   Yes    |
 *
 *  KEY INFO -
 *
 *  events fired : "vlocity-dc-route-navigation"
 *
 *  events registered :
 *
 *  | Event Name                            |        Event source component                                                                      |   Callback Function       | Description                                    |
 *  |---------------------------------------|----------------------------------------------------------------------------------------------------|---------------------------|------------------------------------------------|
 *  | vlocity-dc-toggle-asset               | vlocity-dc-asset-details                                                                           | toggleAssetSelection      | toggle asset selection in the asset list       |
 *
 *  Dependency - vlocity-dc-assets-list is an independent component and has no dependency on parent component.
 *  It is commonly used in the account page to display the list of all assets for the logged in users.
 *
 *
 *                | Parent Component | Expected Children Components |
 *                |------------------|------------------------------|
 *                | none             | vlocity-dc-asset-details     |
 *
 *
 * Sample with slots -
 *
 * <vlocity-dc-assets-list>
 *    <span slot="{slot_name}">
 *      Custom HTML elements goes here
 *    </span>
 * </vlocity-dc-assets-list>
 *
 * List of available slots -
 *
 * | Slot names                  | Dynamic     | Description                   | Impact                                 |
 * |--------------------------   |-------------|------------------------------------------------------------------------|
 * | dc-asset-details            | -           | Wrapper for asset details     | Replaces each asset detail view        |
 * | dc-asset-modify             | -           | Wrapper for modify button     | Replaces modify button                 |
 * | dc-loading-message          | -           | Wrapper for loading message   | Allows adding of loading message       |
 *
 */

export default class VlocityDCAssetsList extends VlocityDCBaseComponent {
  constructor() {
    super(); // always call super() first in the ctor.
    this.root = this;
    this.template = assetsListTemplate;
    this.selectedAssets = [];
    this.loading = false;
    this.catalogCode = "";
    this.digitalCommerceSDK =
      digitalCommerceSDKInstance() &&
      digitalCommerceSDKInstance().digitalCommerce;
    this.digitalCommerceTranslation =
      digitalCommerceSDKInstance() &&
      digitalCommerceSDKInstance().digitalCommerceTranslation;
  }

  /**
   *  Properties that will be available in the template binding
   * @readonly
   * @memberof VlocityDCAssetsList
   * @static
   */
  static get properties() {
    return {
      assets: Array,
      isModifyBtnDisabled: Array,
      isDateModalOpen: Boolean,
      isFutureDate: Boolean,
      selectedDate: Date,
      loading: Boolean
    };
  }
  connectedCallback() {
    super.connectedCallback();
    this.toggleAssetSelectionEventHandler = {
      result: this.toggleAssetSelection.bind(this)
    };
    this.digitalCommerceSDK &&
      this.digitalCommerceSDK.register(
        "vlocity-dc-toggle-asset",
        this.toggleAssetSelectionEventHandler
      );
    this.isModifyBtnDisabled = true;
    this.isFutureDate = false;
    this.selectedDate = null;
  }

  render() {
    return this.template(this);
  }

  /**
   * Event handler for asset toggle selection
   * @memberof VlocityDCAssetsList
   */
  toggleAssetSelection(assetSelectionData) {
    if (assetSelectionData.checked) {
      this.selectedAssets.push(assetSelectionData.assetId);
      this.catalogCode = assetSelectionData.catalogCode;
    } else {
      const index = this.selectedAssets.indexOf(assetSelectionData.assetId);
      this.selectedAssets.splice(index, 1);
    }
    this.isModifyBtnDisabled = this.selectedAssets.length === 0;
  }

  /**
   * Method to move selected assets to basket
   * @memberof VlocityDCAssetsList
   */
  async modifyAssets() {
    const input = this.modifyAssetsGetInput();
    const updatedInput = await this.modifyAssetsPreHook(input);
    this.modifyAssetsPreSDKCalls();
    this.modifyAssetsSDKCall(updatedInput);
  }

  /**
   * This function is used to get assetToBasket input object
   * @memberof VlocityDCAssetsList
   */
  modifyAssetsGetInput() {
    const input =
      this.digitalCommerceSDK &&
      this.digitalCommerceSDK.createAssetToBasketInput();
    const newDate = new Date();
    newDate.setHours(newDate.getHours() + 1);
    input.basketAction = "AssetToBasket";
    input.rootAssetIds = this.selectedAssets.join(",");
    input.catalogCode = this.catalogCode;
    input.requestDateTime = newDate;
    return input;
  }

  /**
   * This function is used to execute any action before assetToBasket SDK call is made.
   *  @memberof VlocityDCAssetsList
   */
  modifyAssetsPreSDKCalls() {
    this.loading = true;
  }

  /**
   * A custom function to be used by customers for customisation, any custom action prior to assetToBasket call can be written here
   *  @param {object} input - Current Input Object.
   *  @memberof VlocityDCAssetsList
   */
  modifyAssetsPreHook(input) {
    return Promise.resolve(input);
  }

  /**
   * This function is used to make SDK call for modifyAssets
   * @param {object} input - Current Input Object.
   * @memberof VlocityDCAssetsList
   */
  modifyAssetsSDKCall(input) {
    this.digitalCommerceSDK &&
      this.digitalCommerceSDK
        .assetToBasket(input)
        .then(atbResponse => {
          this.modifyAssetsProcessResponse(atbResponse);
          this.modifyAssetsPostHook(atbResponse);
        })
        .catch(error => {
          this.modifyAssetsHandleFailure(error);
        });
  }

  /**
   * This function is used to process assetToBasket response
   * @param {object} assets - Assets list from SDK call.
   * @memberof VlocityDCAssetsList
   */
  modifyAssetsProcessResponse(atbResponse) {
    this.loading = false;
    if (atbResponse.cartContextKey) {
      const defaultRouteUrl =
        "/shoppingcart/" + this.catalogCode + "/" + atbResponse.cartContextKey;
      sessionStorage.setItem("cartContextKey", atbResponse.cartContextKey);
      sessionStorage.setItem("rootAssetIds", this.selectedAssets);
      this.digitalCommerceSDK.fire("vlocity-dc-route-navigation", "result", {
        data: {
          catalogCode: this.catalogCode,
          cartContextKey: atbResponse.cartContextKey,
          cartResponse: atbResponse
        },
        defaultRouteUrl: defaultRouteUrl,
        source: "assets"
      });
    }
  }

  /**
   * This function is used to handle assetToBasket failure
   * @param {object} error - Error Object from SDK call.
   * @memberof VlocityDCAssetsList
   */
  modifyAssetsHandleFailure(error) {
    this.loading = false;
    console.error(error);
  }

  /**
   * A custom function to be used by customers for customisation, any custom action after assetToBasket call is successfull can be written here
   *  @param {object} response - SDK Response object.
   *  @memberof VlocityDCAssetsList
   */
  modifyAssetsPostHook() {}

  disconnectedCallback() {
    this.digitalCommerceSDK &&
      this.digitalCommerceSDK.unregister(
        "vlocity-dc-toggle-asset",
        this.toggleAssetSelectionEventHandler
      );
  }
}

customElements.define("vlocity-dc-assets-list", VlocityDCAssetsList);