diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3d71a0a88f..25f8a47f76 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -35,7 +35,7 @@ Our versioning strategy is as follows:
### 🛠Breaking Change
-* Editing Integration Support: ([#1776](https://github.com/Sitecore/jss/pull/1776))([#1792](https://github.com/Sitecore/jss/pull/1792))([#1773](https://github.com/Sitecore/jss/pull/1773))([#1797](https://github.com/Sitecore/jss/pull/1797))([#1800](https://github.com/Sitecore/jss/pull/1800))([#1803](https://github.com/Sitecore/jss/pull/1803))([#1806](https://github.com/Sitecore/jss/pull/1806))([#1809](https://github.com/Sitecore/jss/pull/1809))([#1814](https://github.com/Sitecore/jss/pull/1814))([#1816](https://github.com/Sitecore/jss/pull/1816))([#1819](https://github.com/Sitecore/jss/pull/1819))([#1828](https://github.com/Sitecore/jss/pull/1828))([#1835](https://github.com/Sitecore/jss/pull/1835))([#1849](https://github.com/Sitecore/jss/pull/1849))([#1831](https://github.com/Sitecore/jss/pull/1831))([#1854](https://github.com/Sitecore/jss/pull/1854))
+* Editing Integration Support: ([#1776](https://github.com/Sitecore/jss/pull/1776))([#1792](https://github.com/Sitecore/jss/pull/1792))([#1773](https://github.com/Sitecore/jss/pull/1773))([#1797](https://github.com/Sitecore/jss/pull/1797))([#1800](https://github.com/Sitecore/jss/pull/1800))([#1803](https://github.com/Sitecore/jss/pull/1803))([#1806](https://github.com/Sitecore/jss/pull/1806))([#1809](https://github.com/Sitecore/jss/pull/1809))([#1814](https://github.com/Sitecore/jss/pull/1814))([#1816](https://github.com/Sitecore/jss/pull/1816))([#1819](https://github.com/Sitecore/jss/pull/1819))([#1828](https://github.com/Sitecore/jss/pull/1828))([#1835](https://github.com/Sitecore/jss/pull/1835))([#1849](https://github.com/Sitecore/jss/pull/1849))([#1831](https://github.com/Sitecore/jss/pull/1831))([#1853](https://github.com/Sitecore/jss/pull/1853))([#1854](https://github.com/Sitecore/jss/pull/1854))
* `[sitecore-jss-react]` Introduces `PlaceholderMetadata` component which supports the hydration of chromes on Pages by rendering the components and placeholders with required metadata.
* `[sitecore-jss]` Chromes are hydrated based on the basis of new `editMode` property derived from LayoutData, which is defined as an enum consisting of `metadata` and `chromes`.
* `ComponentConsumerProps` is removed. You might need to reuse `WithSitecoreContextProps` type.
@@ -47,6 +47,7 @@ Our versioning strategy is as follows:
* `[sitecore-jss]` Introduced `GraphQLEditingService` class to fetch editing data in Metadata Edit Mode.
* `[templates/nextjs-xmcloud]` Introduced _/lib/graphql-editing-service_ to fetch editing data in Metadata Edit Mode.
* `[templates/nextjs-xmcloud]` Added a new _page-props-factory/plugins/preview-mode_ plugin to handle both Chromes and Metadata Edit Mode.
+ * `[sitecore-jss]` layout-personalizer will mark components hidden by personalization by setting 'Hidden Rendering' component name in Metadata edit mode
* `[sitecore-jss]` Introduced _/editing_ submodule that contains all editing related functionality. Editing utils are now available in _/editing_ submodule. Editing utils exported from _/utils_ marked as deprecated. ([#1806](https://github.com/Sitecore/jss/pull/1806))
* `[sitecore-jss-nextjs]` EditingRenderMiddleware `resolvePageUrl` function now accepts an object `(args: { serverUrl?: string; itemPath: string }) => string` instead of multiple parameters `(serverUrl: string, itemPath: string) => string`. `serverUrl` is now optional and omitted when Metadata Edit Mode is used.
* `[templates/nextjs]` `[sitecore-jss-nextjs]` `[sitecore-jss]` Remove Partial rendering implementation as it will not be used by Pages in its current implementation - includes removing of EditingComponentPlaceholder component, few constants associated with it and RenderingType enum ([#1821](https://github.com/Sitecore/jss/pull/1821))
diff --git a/packages/sitecore-jss-angular/src/components/hidden-rendering.component.ts b/packages/sitecore-jss-angular/src/components/hidden-rendering.component.ts
index a332aa1836..facecfa9d1 100644
--- a/packages/sitecore-jss-angular/src/components/hidden-rendering.component.ts
+++ b/packages/sitecore-jss-angular/src/components/hidden-rendering.component.ts
@@ -8,5 +8,3 @@ export class HiddenRenderingComponent {
return 'background-image: linear-gradient(45deg, #ffffff 25%, #dcdcdc 25%, #dcdcdc 50%, #ffffff 50%, #ffffff 75%, #dcdcdc 75%, #dcdcdc 100%); background-size: 3px 3px; display: block; height: 100px;';
}
}
-
-export const HIDDEN_RENDERING_NAME = 'Hidden Rendering';
diff --git a/packages/sitecore-jss-angular/src/components/placeholder.component.ts b/packages/sitecore-jss-angular/src/components/placeholder.component.ts
index 1683afac3d..b34c614164 100644
--- a/packages/sitecore-jss-angular/src/components/placeholder.component.ts
+++ b/packages/sitecore-jss-angular/src/components/placeholder.component.ts
@@ -39,7 +39,7 @@ import {
PLACEHOLDER_HIDDEN_RENDERING_COMPONENT,
PLACEHOLDER_MISSING_COMPONENT_COMPONENT,
} from '../services/placeholder.token';
-import { HIDDEN_RENDERING_NAME } from './hidden-rendering.component';
+import { constants } from '@sitecore-jss/sitecore-jss';
import { PlaceholderLoadingDirective } from './placeholder-loading.directive';
import { RenderEachDirective } from './render-each.directive';
import { RenderEmptyDirective } from './render-empty.directive';
@@ -286,7 +286,8 @@ export class PlaceholderComponent implements OnInit, OnChanges, DoCheck, OnDestr
private _renderEmbeddedComponent(rendering: ComponentFactoryResult, data: Data, index: number) {
if (
- (rendering.componentDefinition as ComponentRendering).componentName === HIDDEN_RENDERING_NAME
+ (rendering.componentDefinition as ComponentRendering).componentName ===
+ constants.HIDDEN_RENDERING_NAME
) {
rendering.componentImplementation = this.hiddenRenderingComponent;
}
diff --git a/packages/sitecore-jss-react/src/components/HiddenRendering.tsx b/packages/sitecore-jss-react/src/components/HiddenRendering.tsx
index e9f914db75..66e5632f8f 100644
--- a/packages/sitecore-jss-react/src/components/HiddenRendering.tsx
+++ b/packages/sitecore-jss-react/src/components/HiddenRendering.tsx
@@ -8,5 +8,3 @@ const styles = {
};
export const HiddenRendering = () =>
;
-
-export const HIDDEN_RENDERING_NAME = 'Hidden Rendering';
diff --git a/packages/sitecore-jss-react/src/components/Placeholder.test.tsx b/packages/sitecore-jss-react/src/components/Placeholder.test.tsx
index ebc2b5eabf..485e4fc384 100644
--- a/packages/sitecore-jss-react/src/components/Placeholder.test.tsx
+++ b/packages/sitecore-jss-react/src/components/Placeholder.test.tsx
@@ -2,7 +2,7 @@
/* eslint-disable no-unused-expressions */
/* eslint-disable react/prop-types */
/* eslint-disable @typescript-eslint/no-explicit-any */
-import { ComponentRendering, EditMode, RouteData } from '@sitecore-jss/sitecore-jss/layout';
+import { ComponentRendering, RouteData } from '@sitecore-jss/sitecore-jss/layout';
import { expect } from 'chai';
import { mount, shallow } from 'enzyme';
import PropTypes from 'prop-types';
diff --git a/packages/sitecore-jss-react/src/components/PlaceholderCommon.tsx b/packages/sitecore-jss-react/src/components/PlaceholderCommon.tsx
index 749c334450..cff5643817 100644
--- a/packages/sitecore-jss-react/src/components/PlaceholderCommon.tsx
+++ b/packages/sitecore-jss-react/src/components/PlaceholderCommon.tsx
@@ -10,8 +10,9 @@ import {
HtmlElementRendering,
EditMode,
} from '@sitecore-jss/sitecore-jss/layout';
+import { constants } from '@sitecore-jss/sitecore-jss';
import { convertAttributesToReactProps } from '../utils';
-import { HiddenRendering, HIDDEN_RENDERING_NAME } from './HiddenRendering';
+import { HiddenRendering } from './HiddenRendering';
import { FEaaSComponent, FEAAS_COMPONENT_RENDERING_NAME } from './FEaaSComponent';
import { FEaaSWrapper, FEAAS_WRAPPER_RENDERING_NAME } from './FEaaSWrapper';
import { BYOCComponent, BYOC_COMPONENT_RENDERING_NAME } from './BYOCComponent';
@@ -243,7 +244,7 @@ export class PlaceholderCommon extends React.Compone
let component;
- if (componentRendering.componentName === HIDDEN_RENDERING_NAME) {
+ if (componentRendering.componentName === constants.HIDDEN_RENDERING_NAME) {
component = hiddenRenderingComponent ?? HiddenRendering;
isEmpty = true;
} else if (!componentRendering.componentName) {
diff --git a/packages/sitecore-jss-vue/src/components/HiddenRendering.ts b/packages/sitecore-jss-vue/src/components/HiddenRendering.ts
index f13cc33d3b..1f0c7ce9b9 100644
--- a/packages/sitecore-jss-vue/src/components/HiddenRendering.ts
+++ b/packages/sitecore-jss-vue/src/components/HiddenRendering.ts
@@ -12,5 +12,3 @@ export const HiddenRendering = defineComponent({
});
},
});
-
-export const HIDDEN_RENDERING_NAME = 'Hidden Rendering';
diff --git a/packages/sitecore-jss-vue/src/components/PlaceholderCommon.ts b/packages/sitecore-jss-vue/src/components/PlaceholderCommon.ts
index 67910dcc64..201d294842 100644
--- a/packages/sitecore-jss-vue/src/components/PlaceholderCommon.ts
+++ b/packages/sitecore-jss-vue/src/components/PlaceholderCommon.ts
@@ -7,9 +7,10 @@ import {
RouteData,
} from '@sitecore-jss/sitecore-jss/layout';
import { resetEditorChromes } from '@sitecore-jss/sitecore-jss/editing';
+import { constants } from '@sitecore-jss/sitecore-jss';
import { Component, h, VNode, DefineComponent, ref, onMounted } from 'vue';
import { MissingComponent } from './MissingComponent';
-import { HiddenRendering, HIDDEN_RENDERING_NAME } from './HiddenRendering';
+import { HiddenRendering } from './HiddenRendering';
import { ComponentFactory } from './sharedTypes';
export interface PlaceholderProps {
@@ -116,7 +117,7 @@ export function getVNodesForRenderingData(
let component: any;
- if (rendering.componentName === HIDDEN_RENDERING_NAME) {
+ if (rendering.componentName === constants.HIDDEN_RENDERING_NAME) {
component = hiddenRenderingComponent || HiddenRendering;
} else {
component = getComponentForRendering(rendering, componentFactory);
diff --git a/packages/sitecore-jss/src/constants.ts b/packages/sitecore-jss/src/constants.ts
index 7fd8f42154..7a974f39c7 100644
--- a/packages/sitecore-jss/src/constants.ts
+++ b/packages/sitecore-jss/src/constants.ts
@@ -19,3 +19,5 @@ export const JSS_MODE = {
export const siteNameError = 'The siteName cannot be empty';
export const SITECORE_EDGE_URL_DEFAULT = 'https://edge-platform.sitecorecloud.io';
+
+export const HIDDEN_RENDERING_NAME = 'Hidden Rendering';
diff --git a/packages/sitecore-jss/src/graphql-request-client.test.ts b/packages/sitecore-jss/src/graphql-request-client.test.ts
index 767629682d..82a858fdad 100644
--- a/packages/sitecore-jss/src/graphql-request-client.test.ts
+++ b/packages/sitecore-jss/src/graphql-request-client.test.ts
@@ -345,7 +345,7 @@ describe('GraphQLRequestClient', () => {
}
});
- describe('Retrayable status codes', () => {
+ describe('Retryable status codes', () => {
const retryableStatusCodeThrowError = async (statusCode: number) => {
nock('http://jssnextweb')
.post('/graphql')
diff --git a/packages/sitecore-jss/src/personalize/layout-personalizer.test.ts b/packages/sitecore-jss/src/personalize/layout-personalizer.test.ts
index fc6db5ee01..397017d565 100644
--- a/packages/sitecore-jss/src/personalize/layout-personalizer.test.ts
+++ b/packages/sitecore-jss/src/personalize/layout-personalizer.test.ts
@@ -16,6 +16,7 @@ import {
mountain_bike_audience,
city_bike_audience,
} from '../test-data/personalizeData';
+import { HIDDEN_RENDERING_NAME } from '../constants';
const { personalizeLayout, personalizePlaceholder, personalizeComponent } = personalize;
@@ -340,7 +341,7 @@ describe('layout-personalizer', () => {
).to.deep.equal({});
});
- it('should return null when variantVariant is hidden', () => {
+ it('should return null when variant is hidden', () => {
const variant = 'mountain_bike_audience';
const personalizedComponentResult = personalizeComponent(
(variantIsHidden as unknown) as ComponentRenderingWithExperiences,
@@ -349,7 +350,7 @@ describe('layout-personalizer', () => {
expect(personalizedComponentResult).to.equal(null);
});
- it('should return null when variantVariant and componentName is undefined', () => {
+ it('should return null when variant and componentName is undefined', () => {
const variant = 'test';
const personalizedComponentResult = personalizeComponent(
(withoutComponentName as unknown) as ComponentRenderingWithExperiences,
@@ -359,6 +360,26 @@ describe('layout-personalizer', () => {
});
});
+ it('should return HIDDEN_RENDERING variant in metadata edit mode when non-default variant is hidden', () => {
+ const variant = 'mountain_bike_audience';
+ const personalizedComponentResult = personalizeComponent(
+ (variantIsHidden as unknown) as ComponentRenderingWithExperiences,
+ [variant],
+ true
+ );
+ expect(personalizedComponentResult?.componentName).to.equal(HIDDEN_RENDERING_NAME);
+ });
+
+ it('should return HIDDEN_RENDERING variant in metadata edit mode when default variant is hidden', () => {
+ const variant = 'will-not-match';
+ const personalizedComponentResult = personalizeComponent(
+ (withoutComponentName as unknown) as ComponentRenderingWithExperiences,
+ [variant],
+ true
+ );
+ expect(personalizedComponentResult?.componentName).to.equal(HIDDEN_RENDERING_NAME);
+ });
+
describe('with multiple variant Ids', () => {
const testComponent = structuredClone(component);
diff --git a/packages/sitecore-jss/src/personalize/layout-personalizer.ts b/packages/sitecore-jss/src/personalize/layout-personalizer.ts
index b370813446..9f1d7138bb 100644
--- a/packages/sitecore-jss/src/personalize/layout-personalizer.ts
+++ b/packages/sitecore-jss/src/personalize/layout-personalizer.ts
@@ -1,10 +1,17 @@
+import { HIDDEN_RENDERING_NAME } from '../constants';
import {
LayoutServiceData,
ComponentRendering,
HtmlElementRendering,
PlaceholdersData,
+ EditMode,
} from './../layout/models';
+const hiddenRenderingVariant = {
+ componentName: HIDDEN_RENDERING_NAME,
+ experiences: {},
+};
+
export type ComponentRenderingWithExperiences = ComponentRendering & {
experiences: { [name: string]: ComponentRenderingWithExperiences };
};
@@ -26,12 +33,15 @@ export function personalizeLayout(
if (Object.keys(placeholders ?? {}).length === 0) {
return;
}
+ const metadataEditing =
+ layout.sitecore.context.pageEditing && layout.sitecore.context.editMode === EditMode.Metadata;
if (placeholders) {
Object.keys(placeholders).forEach((placeholder) => {
- placeholders[placeholder] = personalizePlaceholder(placeholders[placeholder], [
- variantId,
- ...(componentVariantIds || []),
- ]);
+ placeholders[placeholder] = personalizePlaceholder(
+ placeholders[placeholder],
+ [variantId, ...(componentVariantIds || [])],
+ metadataEditing
+ );
});
}
return placeholders;
@@ -40,25 +50,33 @@ export function personalizeLayout(
/**
* @param {Array} components components within placeholder
* @param {string[]} variantIds variant ids
+ * @param {boolean} metadataEditing indicates if page is rendered in metadata edit mode
* @returns {Array} components with personalization applied
*/
export function personalizePlaceholder(
components: Array,
- variantIds: string[]
+ variantIds: string[],
+ metadataEditing?: boolean
): Array {
return components
.map((component) => {
const rendering = component as ComponentRendering;
if ((rendering as ComponentRenderingWithExperiences).experiences !== undefined) {
- return personalizeComponent(rendering as ComponentRenderingWithExperiences, variantIds) as
- | ComponentRendering
- | HtmlElementRendering;
+ return personalizeComponent(
+ rendering as ComponentRenderingWithExperiences,
+ variantIds,
+ metadataEditing
+ ) as ComponentRendering | HtmlElementRendering;
} else if (rendering.placeholders) {
const placeholders = rendering.placeholders as PlaceholdersData;
Object.keys(placeholders).forEach((placeholder) => {
- placeholders[placeholder] = personalizePlaceholder(placeholders[placeholder], variantIds);
+ placeholders[placeholder] = personalizePlaceholder(
+ placeholders[placeholder],
+ variantIds,
+ metadataEditing
+ );
});
}
@@ -70,23 +88,35 @@ export function personalizePlaceholder(
/**
* @param {ComponentRenderingWithExperiences} component component with experiences
* @param {string[]} variantIds variant ids
+ * @param {boolean} metadataEditing indicates if page is rendered in metadata edit mode
* @returns {ComponentRendering | null} component with personalization applied or null if hidden
*/
export function personalizeComponent(
component: ComponentRenderingWithExperiences,
- variantIds: string[]
+ variantIds: string[],
+ metadataEditing?: boolean
): ComponentRendering | null {
// Check if we have a page/component experience matching any of the variants (there should be at most 1)
const match = Object.keys(component.experiences).find((variantId) =>
variantIds.includes(variantId)
);
const variant = match && component.experiences[match];
- if (variant === undefined && component.componentName === undefined) {
+
+ // variant and componentName can be undefined or null
+ if (!variant && !component.componentName) {
// DEFAULT IS HIDDEN
- return null;
+ if (metadataEditing) {
+ component = hiddenRenderingVariant;
+ } else {
+ return null;
+ }
} else if (variant && variant.componentName === null && variant.dataSource === null) {
// VARIANT IS HIDDEN
- return null;
+ if (metadataEditing) {
+ component = hiddenRenderingVariant;
+ } else {
+ return null;
+ }
} else if (variant) {
component = variant;
}