File

feature-libs/smartedit/core/services/smart-edit.service.ts

Index

Properties
Methods

Constructor

constructor(cmsService: CmsService, routingService: RoutingService, baseSiteService: BaseSiteService, zone: NgZone, winRef: WindowRef, rendererFactory: RendererFactory2, config: SmartEditConfig, scriptLoader: ScriptLoader)
Parameters :
Name Type Optional
cmsService CmsService No
routingService RoutingService No
baseSiteService BaseSiteService No
zone NgZone No
winRef WindowRef No
rendererFactory RendererFactory2 No
config SmartEditConfig No
scriptLoader ScriptLoader No

Methods

Protected addPageContract
addPageContract(cmsPage: Page)

add CSS classes in a body tag

Parameters :
Name Type Optional
cmsPage Page No
Returns : void
Public addSmartEditContract
addSmartEditContract(element: Element, renderer: Renderer2, properties: any)

add smartedit HTML markup contract

Parameters :
Name Type Optional
element Element No
renderer Renderer2 No
properties any No
Returns : void
Protected goToPreviewPage
goToPreviewPage(cmsPage: Page)

go to the default preview page

Parameters :
Name Type Optional
cmsPage Page No
Returns : void
Protected loadScript
loadScript()

load webApplicationInjector.js

Returns : void
Public processCmsPage
processCmsPage()
Returns : void
Protected renderComponent
renderComponent(componentId: string, componentType?: string, parentId?: string)

re-render CMS components and slots

Parameters :
Name Type Optional
componentId string No
componentType string Yes
parentId string Yes
Returns : boolean
Protected reprocessPage
reprocessPage()
Returns : void

Properties

Private _currentPageId
Type : string | undefined
Private defaultPreviewCategoryCode
Type : string | undefined
Private defaultPreviewProductCode
Type : string | undefined
Private isPreviewPage
Default value : false
import { Injectable, NgZone, Renderer2, RendererFactory2 } from '@angular/core';
import {
  BaseSiteService,
  CmsService,
  Page,
  PageType,
  RoutingService,
  ScriptLoader,
  WindowRef,
} from '@spartacus/core';
import { SmartEditConfig } from '@spartacus/smartedit/root';
import { filter, take } from 'rxjs/operators';

@Injectable({
  providedIn: 'root',
})
export class SmartEditService {
  private isPreviewPage = false;
  private _currentPageId: string | undefined;

  private defaultPreviewProductCode: string | undefined;
  private defaultPreviewCategoryCode: string | undefined;

  constructor(
    protected cmsService: CmsService,
    protected routingService: RoutingService,
    protected baseSiteService: BaseSiteService,
    protected zone: NgZone,
    protected winRef: WindowRef,
    protected rendererFactory: RendererFactory2,
    protected config: SmartEditConfig,
    protected scriptLoader: ScriptLoader
  ) {
    // load webApplicationInjector.js first
    this.loadScript();

    if (winRef.nativeWindow) {
      const window = winRef.nativeWindow as any;
      // rerender components and slots after editing
      window.smartedit = window.smartedit || {};
      window.smartedit.renderComponent = (
        componentId: string,
        componentType: string,
        parentId: string
      ) => {
        return this.renderComponent(componentId, componentType, parentId);
      };

      // reprocess page
      window.smartedit.reprocessPage = this.reprocessPage;
    }
  }

  public processCmsPage(): void {
    this.baseSiteService
      .get()
      .pipe(
        filter((site: any) => Boolean(site)),
        take(1)
      )
      .subscribe((site) => {
        this.defaultPreviewCategoryCode = site.defaultPreviewCategoryCode;
        this.defaultPreviewProductCode = site.defaultPreviewProductCode;

        this.cmsService
          .getCurrentPage()
          .pipe(filter<Page>(Boolean))
          .subscribe((cmsPage) => {
            this._currentPageId = cmsPage.pageId;
            // before adding contract to page, we need redirect to that page
            this.goToPreviewPage(cmsPage);
            this.addPageContract(cmsPage);
          });
      });
  }

  /**
   * load webApplicationInjector.js
   */
  protected loadScript(): void {
    this.scriptLoader.embedScript({
      src: 'assets/webApplicationInjector.js',
      params: undefined,
      attributes: {
        id: 'text/smartedit-injector',
        'data-smartedit-allow-origin': this.config.smartEdit?.allowOrigin,
      },
    });
  }

  /**
   * add CSS classes in a body tag
   */
  protected addPageContract(cmsPage: Page) {
    const renderer = this.rendererFactory.createRenderer('body', null);
    const element = this.winRef.document.body;

    // remove old page contract
    const previousContract: string[] = [];
    Array.from(element.classList).forEach((attr) =>
      previousContract.push(attr)
    );
    previousContract.forEach((attr) => renderer.removeClass(element, attr));

    // add new page contract
    this.addSmartEditContract(element, renderer, cmsPage.properties);
  }

  /**
   * go to the default preview page
   */
  protected goToPreviewPage(cmsPage: Page) {
    // only the first page is the smartedit preview page
    if (!this.isPreviewPage) {
      this.isPreviewPage = true;
      if (
        cmsPage.type === PageType.PRODUCT_PAGE &&
        this.defaultPreviewProductCode
      ) {
        this.routingService.go({
          cxRoute: 'product',
          params: { code: this.defaultPreviewProductCode, name: '' },
        });
      } else if (
        cmsPage.type === PageType.CATEGORY_PAGE &&
        this.defaultPreviewCategoryCode
      ) {
        this.routingService.go({
          cxRoute: 'category',
          params: { code: this.defaultPreviewCategoryCode },
        });
      }
    }
  }

  /**
   * re-render CMS components and slots
   */
  protected renderComponent(
    componentId: string,
    componentType?: string,
    parentId?: string
  ): boolean {
    if (componentId) {
      this.zone.run(() => {
        // without parentId, it is slot
        if (!parentId) {
          if (this._currentPageId) {
            this.cmsService.refreshPageById(this._currentPageId);
          } else {
            this.cmsService.refreshLatestPage();
          }
        } else if (componentType) {
          this.cmsService.refreshComponent(componentId);
        }
      });
    }

    return true;
  }

  protected reprocessPage() {
    // TODO: reprocess page API
  }

  /**
   * add smartedit HTML markup contract
   */
  public addSmartEditContract(
    element: Element,
    renderer: Renderer2,
    properties: any
  ): void {
    if (properties) {
      // check each group of properties, e.g. smartedit
      Object.keys(properties).forEach((group) => {
        const name = 'data-' + group + '-';
        const groupProps = properties[group];

        // check each property in the group
        Object.keys(groupProps).forEach((propName) => {
          const propValue = groupProps[propName];
          if (propName === 'classes') {
            const classes = propValue.split(' ');
            classes.forEach((classItem: string) => {
              renderer.addClass(element, classItem);
            });
          } else {
            renderer.setAttribute(
              element,
              name +
                propName
                  .split(/(?=[A-Z])/)
                  .join('-')
                  .toLowerCase(),
              propValue
            );
          }
        });
      });
    }
  }
}

result-matching ""

    No results matching ""