Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

When the layout query stop expanding references, traversefield method crashes #1867

Open
minyiediazvelir opened this issue Jul 30, 2024 · 2 comments
Labels
backlog Issue/PR/discussion is reviewed and added to backlog for the further work 🐞 bug

Comments

@minyiediazvelir
Copy link

minyiediazvelir commented Jul 30, 2024

Describe the Bug

When the standard layout query stops expanding references, it returns the guid value of the field which is expected.
But the traverse method doesn't handle this case and it crashes.
Example error Cannot use 'in' operator to search for 'editable' in {77F1D209-AC8C-4945-A5C8-9FCCC93AFE4F} at traverseField (/opt/build/repo/src/acr/node_modules/@sitecore-jss/sitecore-jss-nextjs/node_modules/@sitecore-jss/sitecore-jss/dist/cjs/layout/content-styles.js:42:20)

To Reproduce

Create a sitecore item that has a reference field to another item, then the other item have a field that reference another item and so on do it 4 times.

Expected Behavior

I would expect to ignore it.

Possible Fix

No response

Provide environment information

  • Sitecore Version: XM Cloud
  • JSS Version: 22.0.0
  • Browser Name and version:
  • Operating System and version (desktop or mobile):
  • Link to your project (if available):
@yavorsk
Copy link
Contributor

yavorsk commented Jul 31, 2024

Thanks @minyiediazvelir for submitting this. I am adding this to our backlog for prioritization.

@addy-pathania addy-pathania added the backlog Issue/PR/discussion is reviewed and added to backlog for the further work label Aug 1, 2024
@jflheureux
Copy link
Contributor

We got this issue as well. Sitecore support suggested us to copy the original SDK file and apply the fix to our copy. Then use our copy instead of the SDK version.

Here is our copy of the SDK file src\lib\page-props-factory\content-styles.ts

// CUSTOMIZATION (whole file) - articles with authors erroring in EE because GQL depth exceeded. Implementing Sitecore's workaround customization (Sitecore.Support.JSS-1757)
// Original file URL from the SDK: https://github.com/Sitecore/jss/blob/dev/packages/sitecore-jss/src/layout/content-styles.ts
// Primary difference that makes this work is that traverseField() on line 66 now does an early return if the field is type string.
// This works because the article authors were coming back as a string guid, instead of a full field object.
// Unknown when this issue will be properly fixed. Sitecore said they will consider it for future releases.
import {
  ComponentRendering,
  Field,
  HtmlElementRendering,
  Item,
  LayoutServiceData,
  RouteData,
} from '@sitecore-jss/sitecore-jss/layout';
import { HTMLLink } from '@sitecore-jss/sitecore-jss';

/**
 * Regular expression to check if the content styles are used in the field value
 */
const CLASS_REGEXP = /class=".*(\bck-content\b).*"/g;

type Config = { loadStyles: boolean };

/**
 * Get the content styles link to be loaded from the Sitecore Edge Platform
 * @param {LayoutServiceData} layoutData Layout service data
 * @param {string} sitecoreEdgeContextId Sitecore Edge Context ID
 * @param {string} [sitecoreEdgeUrl] Sitecore Edge Platform URL. Default is https://edge-platform.sitecorecloud.io
 * @returns {HTMLLink | null} content styles link, null if no styles are used in layout
 */
export const getContentStylesheetLink = (
  layoutData: LayoutServiceData,
  sitecoreEdgeContextId: string,
  sitecoreEdgeUrl = 'https://edge-platform.sitecorecloud.io'
): HTMLLink | null => {
  if (!layoutData.sitecore.route) return null;

  const config: Config = { loadStyles: false };

  traverseComponent(layoutData.sitecore.route, config);

  if (!config.loadStyles) return null;

  return {
    href: getContentStylesheetUrl(sitecoreEdgeContextId, sitecoreEdgeUrl),
    rel: 'stylesheet',
  };
};

export const getContentStylesheetUrl = (
  sitecoreEdgeContextId: string,
  sitecoreEdgeUrl = 'https://edge-platform.sitecorecloud.io'
): string =>
  `${sitecoreEdgeUrl}/v1/files/pages/styles/content-styles.css?sitecoreContextId=${sitecoreEdgeContextId}`;

export const traversePlaceholder = (
  components: Array<ComponentRendering | HtmlElementRendering>,
  config: Config
) => {
  if (config.loadStyles) return;

  components.forEach((component) => {
    traverseComponent(component, config);
  });
};

export const traverseField = (field: Field | Item | Item[] | undefined, config: Config) => {
  //Sitecore.Support.JSS-1757
  if (!field || typeof field === 'string' || config.loadStyles) return;

  if ('editable' in field && field.editable) {
    config.loadStyles = CLASS_REGEXP.test(field.editable);
  } else if ('value' in field && typeof field.value === 'string') {
    config.loadStyles = CLASS_REGEXP.test(field.value);
  } else if ('fields' in field) {
    Object.values(field.fields).forEach((field) => {
      traverseField(field, config);
    });
  } else if (Array.isArray(field)) {
    field.forEach((field) => {
      traverseField(field, config);
    });
  }
};

export const traverseComponent = (
  component: RouteData | ComponentRendering | HtmlElementRendering,
  config: Config
) => {
  if (config.loadStyles) return;

  if ('fields' in component && component.fields) {
    Object.values(component.fields).forEach((field) => {
      traverseField(field, config);
    });
  }

  const placeholders = (component as ComponentRendering).placeholders || {};

  Object.keys(placeholders).forEach((placeholder) => {
    traversePlaceholder(placeholders[placeholder], config);
  });
};

And our usage of it in src\lib\page-props-factory\plugins\content-styles.ts:

import { SitecorePageProps } from 'lib/page-props';

// BEGIN CUSTOMIZATION - articles with authors erroring in EE because GQL depth exceeded. Implementing Sitecore's workaround customization (Sitecore.Support.JSS-1757)
// import { getContentStylesheetLink } from '@sitecore-jss/sitecore-jss-nextjs';
import { getContentStylesheetLink } from '../content-styles';
import config from 'temp/config';
// END CUSTOMIZATION
import { Plugin } from '..';

class ContentStylesPlugin implements Plugin {
  order = 2;

  async exec(props: SitecorePageProps) {
    // Get content stylessheet link, empty if styles are not used on the page
    // BEGIN CUSTOMIZATION - articles with authors erroring in EE because GQL depth exceeded. Implementing Sitecore's workaround customization (Sitecore.Support.JSS-1757)
    const contentStyles = getContentStylesheetLink(
      props.layoutData,
      config.sitecoreEdgeContextId,
      config.sitecoreEdgeUrl
    );
    // END CUSTOMIZATION

    contentStyles && props.headLinks.push(contentStyles);

    return props;
  }
}

export const contentStylesPlugin = new ContentStylesPlugin();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backlog Issue/PR/discussion is reviewed and added to backlog for the further work 🐞 bug
Projects
None yet
Development

No branches or pull requests

4 participants