File

libs/nx/src/generators/journey-src/lib/create-pages/single-page/single-page.ts

Index

Properties

Properties

module
Type string
package
Type string
import {
  BannerBlockConfiguration,
  BuildingBlockConfiguration,
  OverarchingDetailsBlockConfiguration,
  PageConfiguration,
  SectionConfiguration
} from '@allianz/taly-core/schemas';
import { JourneyTargetType, getAllBuildingBlocksInPage } from '@allianz/taly-sdk';
import { Tree, formatFiles, generateFiles, joinPathFragments } from '@nx/devkit';
import * as strings from '@nx/devkit/src/utils/string-utils';
import ejs from 'ejs';
import fs from 'fs';
import pick from 'lodash/pick';
import uniqWith from 'lodash/uniqWith';
import { Experiments } from '../../experimental/experimental';
import { createPageDataAssignment } from './create-page-data-assignment';
import { createPageDataOverridesString } from './create-page-data-overrides';
import * as exampleState from './example-state';
import { BuildingBlockWithExampleMap } from './example-state';
import {
  SectionRuntimeDefinition,
  isPanel,
  mergeBlocksAndPanelsIntoSections
} from './merge-blocks-and-panels-into-sections';
import { getNotificationsConfigForTemplate } from './notifications/notifications';
import { renderMarkdownAsHtml } from './render-markdown-as-html';
import { SinglePageOptions } from './single-page-options';

export async function singlePage(tree: Tree, options: SinglePageOptions) {
  const { page } = options;

  let pageTitle = '';
  let subline = '';
  if (typeof page.title === 'string') {
    pageTitle = page.title;
  } else if (typeof page.title === 'object' && !page.title?.showAsStage) {
    pageTitle = page.title.headline;
    subline = page.title?.subline || '';
  }

  const name = page.id;
  const processedSections = mergeBlocksAndPanelsIntoSections(page, options.expert);
  const allBlocks = getAllBuildingBlocksInPage(page);
  /**
   * TODO: Guarantee, that there is no conflict with static imports in the template itself (TS AST task).
   */
  const buildingBlockImports = collectBuildingBlockImports(allBlocks);
  let exampleMap = new Map();
  let exampleAssignments;

  if (options.showDebugPanel) {
    exampleMap = exampleState.collectFromBuildingBlocks(allBlocks);
    exampleAssignments = exampleState.renderAllVariableDeclarations(exampleMap);
  }

  const hasStage = typeof page.title === 'object' && page.title?.showAsStage;

  const hasSectionHeadline =
    processedSections.filter((processedSection: SectionRuntimeDefinition) => processedSection.title)
      .length > 0;
  const hasHeadline = Boolean(pageTitle) || hasSectionHeadline;

  const bannerBlock = page.bannerBlock;

  const hasSidebarBlocks = processedSections.some((processedSection) =>
    processedSection.sectionItems.some(
      (sectionItem) => (sectionItem as BuildingBlockConfiguration).sidebar
    )
  );

  const hasCompactBb = hasCompactBuildingBlock(processedSections);

  const pageDataAssignment = createPageDataAssignment(page);

  const pageDataOverrides: string = createPageDataOverridesString(page.id, allBlocks);

  const hasSectionWithDividerLine = page.sections?.some((section) => section.dividerLineBelow);

  const smallPrintParagraphs =
    page.smallPrint?.map((smallPrintParagraph) => renderMarkdownAsHtml(smallPrintParagraph)) ?? [];

  const hasNotifications = Boolean(page.notifications?.length);
  const notifications = getNotificationsConfigForTemplate(page.notifications);

  const singleBbWithBg = hasSingleBuildingBlockWithBackground(page, options.navigationSections);
  generateFiles(tree, joinPathFragments(__dirname, 'files'), options.destinationDirectory, {
    name: name,
    dasherizedName: strings.dasherize(name),
    title: pageTitle,
    subtitle: subline,
    hasHeadline,
    hasSectionHeadline,
    hasStage,
    pageID: page.id,
    isFirstPage: options.isFirstPage,
    isPanel,
    processedSections,
    bannerBlock,
    buildingBlockImports,
    hasSidebarBlocks,
    smallPrintParagraphs,
    notifications,
    hasNotifications,
    // eslint-disable-next-line @typescript-eslint/no-use-before-define
    renderBuildingBlock: renderBuildingBlockFactory(
      exampleMap,
      options.showDebugPanel ?? false,
      options.showroom && options.target === JourneyTargetType.App
    ),
    exampleAssignments,
    ...strings,
    showDebugPanel: options.showDebugPanel ?? false,
    pageDataAssignment: pageDataAssignment,
    provideMetaServiceInComponent: options.provideMetaServiceInComponent ?? false,
    expert: options.expert ?? false,
    hasCompactBb,
    hasSectionWithDividerLine,
    pageDataOverrides,
    showroom: options.showroom,
    isStandalone: options.target === JourneyTargetType.App,
    singleBbWithBg,
    overarchingDetails: options.page.overarchingDetailsBlock,
    useNewVerticalSpacing: options.experimental?.includes(Experiments.VerticalSpacing) ?? false
  });

  await formatFiles(tree);
}

/**
 * Render a Building Block. Pulled out of the actual template and rendered
 * instead by code by using the underlying `template` method to prevent duplication
 * in the template as we have two places to output Building Blocks.
 */

const renderBuildingBlockFactory =
  (
    exampleStateItems: BuildingBlockWithExampleMap,
    showDebugPanel: boolean,
    respectDebugToolsService: boolean
  ) =>
  (block: BuildingBlockConfiguration) => {
    const exampleStateIdentifier = exampleState.createIdentifier(block.id);
    const value = exampleStateItems.has(block.id) ? exampleStateIdentifier : null;

    const properties = {
      id: block.id,
      aclTag: block.aclTag ?? block.id,
      selector: block.selector,
      sidebar: block.sidebar,
      templateReferenceID: `bb${strings.classify(block.id)}`,
      exampleStateIdentifier: value,
      showDebugPanel,
      respectDebugToolsService
    };

    const content = fs
      .readFileSync(joinPathFragments(__dirname, 'partials/building-block'))
      .toString();
    const renderedContent = ejs.render(content, properties, {});

    return renderedContent;
  };

interface BuildingBlockImport {
  module: string;
  package: string;
}

function collectBuildingBlockImports(
  blocks: (
    | BuildingBlockConfiguration
    | OverarchingDetailsBlockConfiguration
    | BannerBlockConfiguration
  )[]
): BuildingBlockImport[] {
  const moduleAndPackage = blocks.map((item) => pick(item, ['package', 'module']));
  const uniqBlockImports = uniqWith(moduleAndPackage, function (a, b) {
    return a.package === b.package && a.module === b.module;
  });

  return uniqBlockImports;
}

export function hasSingleBuildingBlockWithBackground(
  page: PageConfiguration,
  navigationSections: SectionConfiguration[]
) {
  if (
    page.bannerBlock?.id ||
    page.overarchingDetailsBlock?.id ||
    page.notifications?.length ||
    page.title ||
    page.blocks?.length !== 1
  ) {
    return false;
  }

  const hasNavigation = navigationSections.length && !page.pageData?.navigation?.hidden;
  if (hasNavigation) {
    return false;
  }

  const backgroundColor = (page.blocks[0] as BuildingBlockConfiguration)?.buildingBlockStyle
    ?.backgroundColor;
  return Boolean(backgroundColor && backgroundColor !== 'transparent');
}

function hasCompactBuildingBlock(allSections: SectionRuntimeDefinition[]) {
  return allSections.some((section) => section.compact);
}

results matching ""

    No results matching ""