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

[sitecore-jss] [sitecore-jss-nextjs] Pass sc_layoutKind to grapqhl layout request header. #1907

Merged
merged 13 commits into from
Aug 27, 2024
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ Our versioning strategy is as follows:
* Promo component ([#1897](https://github.com/Sitecore/jss/pull/1897))
* PageContent component ([#1905](https://github.com/Sitecore/jss/pull/1905))
* Navigation component ([#1894](https://github.com/Sitecore/jss/pull/1894))
* `[sitecore-jss]``[sitecore-jss-nextjs]` Pass `sc_layoutKind` to grapqhl layout request header. ([#1907](https://github.com/Sitecore/jss/pull/1907))
addy-pathania marked this conversation as resolved.
Show resolved Hide resolved

### 🛠 Breaking Change

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,14 @@ class PreviewModePlugin implements Plugin {

// If we're in Pages preview (editing) Metadata Edit Mode, prefetch the editing data
if (isEditingMetadataPreviewData(context.previewData)) {
const { site, itemId, language, version, variantIds } = context.previewData;
const { site, itemId, language, version, variantIds, layoutKind } = context.previewData;
addy-pathania marked this conversation as resolved.
Show resolved Hide resolved

const data = await graphQLEditingService.fetchEditingData({
siteName: site,
itemId,
language,
version,
layoutKind,
});

if (!data) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ describe('EditingRenderMiddleware', () => {
sc_variant: 'dev',
sc_version: 'latest',
secret: secret,
sc_layoutKind: 'shared',
} as MetadataQueryParams;

it('should handle request', async () => {
Expand All @@ -198,6 +199,7 @@ describe('EditingRenderMiddleware', () => {
version: 'latest',
editMode: 'metadata',
pageState: 'edit',
layoutKind: 'shared',
});

expect(res.redirect).to.have.been.calledOnce;
Expand Down Expand Up @@ -235,6 +237,7 @@ describe('EditingRenderMiddleware', () => {
version: undefined,
editMode: 'metadata',
pageState: 'edit',
layoutKind: 'final',
});
});

Expand Down Expand Up @@ -263,6 +266,7 @@ describe('EditingRenderMiddleware', () => {
version: undefined,
editMode: 'metadata',
pageState: 'edit',
layoutKind: 'final',
});

expect(res.redirect).to.have.been.calledOnce;
Expand Down Expand Up @@ -295,6 +299,7 @@ describe('EditingRenderMiddleware', () => {
version: 'latest',
editMode: 'metadata',
pageState: 'edit',
layoutKind: 'shared',
});

expect(res.redirect).to.have.been.calledOnce;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { NextApiRequest, NextApiResponse } from 'next';
import { STATIC_PROPS_ID, SERVER_PROPS_ID } from 'next/constants';
import { AxiosDataFetcher, debug } from '@sitecore-jss/sitecore-jss';
import { EditMode, LayoutServicePageState } from '@sitecore-jss/sitecore-jss/layout';
import { EditMode, LayoutServicePageState, LayoutKind } from '@sitecore-jss/sitecore-jss/layout';
import { EditingData } from './editing-data';
import { EditingDataService, editingDataService } from './editing-data-service';
import { EDITING_ALLOWED_ORIGINS, QUERY_PARAM_EDITING_SECRET } from './constants';
Expand Down Expand Up @@ -274,6 +274,7 @@ export type MetadataQueryParams = {
mode: Exclude<LayoutServicePageState, 'normal'>;
sc_variant?: string;
sc_version?: string;
sc_layoutKind?: LayoutKind;
};

/**
Expand All @@ -294,6 +295,7 @@ export type EditingMetadataPreviewData = {
pageState: Exclude<LayoutServicePageState, 'Normal'>;
variantIds: string[];
version?: string;
layoutKind?: LayoutKind;
};

/**
Expand Down Expand Up @@ -355,6 +357,7 @@ export class MetadataHandler {
version: query.sc_version,
editMode: EditMode.Metadata,
pageState: query.mode,
layoutKind: query.sc_layoutKind || LayoutKind.Final,
addy-pathania marked this conversation as resolved.
Show resolved Hide resolved
} as EditingMetadataPreviewData,
// Cache the preview data for 3 seconds to ensure the page is rendered with the correct preview data not the cached one
{
Expand Down
41 changes: 27 additions & 14 deletions packages/sitecore-jss/src/editing/graphql-editing-service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
mockEditingServiceDictionaryResponse,
mockEditingServiceResponse,
} from '../test-data/mockEditingServiceResponse';
import { EditMode } from '../layout';
import { EditMode, LayoutKind } from '../layout';
import debug from '../debug';

use(spies);
Expand Down Expand Up @@ -62,7 +62,7 @@ describe('GraphQLEditingService', () => {
});

it('should fetch editing data', async () => {
nock(hostname, { reqheaders: { sc_editMode: 'true' } })
nock(hostname, { reqheaders: { sc_editMode: 'true', sc_layoutKind: 'final' } })
.post(endpointPath, /EditingQuery/gi)
.reply(200, editingData);

Expand Down Expand Up @@ -91,12 +91,18 @@ describe('GraphQLEditingService', () => {
})
).to.be.true;
expect(clientFactorySpy.returnValues[0].request).to.be.called.exactly(1);
expect(clientFactorySpy.returnValues[0].request).to.be.called.with(query, {
language,
version,
itemId,
siteName,
});
expect(clientFactorySpy.returnValues[0].request).to.be.called.with(
query,
{
language,
version,
itemId,
siteName,
},
{
sc_layoutKind: 'final',
}
);

expect(result).to.deep.equal({
layoutData: layoutDataResponse,
Expand Down Expand Up @@ -136,6 +142,7 @@ describe('GraphQLEditingService', () => {
version,
itemId,
siteName,
layoutKind: LayoutKind.Shared,
addy-pathania marked this conversation as resolved.
Show resolved Hide resolved
});

expect(clientFactorySpy.calledOnce).to.be.true;
Expand All @@ -148,12 +155,18 @@ describe('GraphQLEditingService', () => {
})
).to.be.true;
expect(clientFactorySpy.returnValues[0].request).to.be.called.exactly(1);
expect(clientFactorySpy.returnValues[0].request).to.be.called.with(query, {
language,
version,
itemId,
siteName,
});
expect(clientFactorySpy.returnValues[0].request).to.be.called.with(
query,
{
language,
version,
itemId,
siteName,
},
{
sc_layoutKind: 'shared',
}
);

expect(result).to.deep.equal({
layoutData: {
Expand Down
32 changes: 24 additions & 8 deletions packages/sitecore-jss/src/editing/graphql-editing-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import debug from '../debug';
import { PageInfo } from '../graphql';
import { GraphQLClient, GraphQLRequestClientFactory } from '../graphql-request-client';
import { DictionaryPhrases } from '../i18n';
import { EditMode, LayoutServiceData } from '../layout';
import { EditMode, LayoutKind, LayoutServiceData } from '../layout';

/**
* The dictionary query default page size.
Expand Down Expand Up @@ -115,20 +115,30 @@ export class GraphQLEditingService {
* @param {string} variables.itemId - The item id (path) to fetch layout data for.
* @param {string} variables.language - The language to fetch layout data for.
* @param {string} [variables.version] - The version of the item (optional).
* @param {LayoutKind} [variables.layoutKind] - The final or shared layout switcher.
addy-pathania marked this conversation as resolved.
Show resolved Hide resolved
* @returns {Promise} The layout data and dictionary phrases.
*/
async fetchEditingData({
siteName,
itemId,
language,
version,
layoutKind,
addy-pathania marked this conversation as resolved.
Show resolved Hide resolved
}: {
siteName: string;
itemId: string;
language: string;
version?: string;
layoutKind?: LayoutKind;
}) {
debug.editing('fetching editing data for %s %s %s %s', siteName, itemId, language, version);
debug.editing(
'fetching editing data for %s %s %s %s',
siteName,
itemId,
language,
version,
layoutKind
);

if (!siteName) {
throw new RangeError('The site name must be a non-empty string');
Expand All @@ -143,12 +153,18 @@ export class GraphQLEditingService {
let hasNext = true;
let after = '';

const editingData = await this.graphQLClient.request<GraphQLEditingQueryResponse>(query, {
siteName,
itemId,
version,
language,
});
const editingData = await this.graphQLClient.request<GraphQLEditingQueryResponse>(
query,
{
siteName,
itemId,
version,
language,
},
{
sc_layoutKind: layoutKind || LayoutKind.Final,
}
);

if (editingData?.site?.siteInfo?.dictionary) {
dictionaryResults = editingData.site.siteInfo.dictionary.results;
Expand Down
12 changes: 9 additions & 3 deletions packages/sitecore-jss/src/graphql-request-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ export interface GraphQLClient {
* @param {string | DocumentNode} query graphql query
* @param {Object} variables graphql variables
*/
request<T>(query: string | DocumentNode, variables?: { [key: string]: unknown }): Promise<T>;
request<T>(
query: string | DocumentNode,
variables?: { [key: string]: unknown },
requestHeaders?: Record<string, string>
addy-pathania marked this conversation as resolved.
Show resolved Hide resolved
): Promise<T>;
}

/**
Expand Down Expand Up @@ -207,10 +211,12 @@ export class GraphQLRequestClient implements GraphQLClient {
* Execute graphql request
* @param {string | DocumentNode} query graphql query
* @param {Object} variables graphql variables
* @param {Record<string, string>} requestHeaders
*/
async request<T>(
query: string | DocumentNode,
variables?: { [key: string]: unknown }
variables?: { [key: string]: unknown },
requestHeaders?: Record<string, string>
): Promise<T> {
let attempt = 1;

Expand All @@ -224,7 +230,7 @@ export class GraphQLRequestClient implements GraphQLClient {
variables,
addy-pathania marked this conversation as resolved.
Show resolved Hide resolved
});
const startTimestamp = Date.now();
const fetchWithOptionalTimeout = [this.client.request(query, variables)];
const fetchWithOptionalTimeout = [this.client.request(query, variables, requestHeaders)];
if (this.timeout) {
this.abortTimeout = new TimeoutPromise(this.timeout);
fetchWithOptionalTimeout.push(this.abortTimeout.start);
Expand Down
1 change: 1 addition & 0 deletions packages/sitecore-jss/src/layout/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export {
ComponentFields,
ComponentParams,
EditMode,
LayoutKind,
FieldMetadata,
} from './models';

Expand Down
10 changes: 10 additions & 0 deletions packages/sitecore-jss/src/layout/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,16 @@ export enum EditMode {
Metadata = 'metadata',
}

/**
* Represents the layout switcher to pass to CM when rendering to horizon.
addy-pathania marked this conversation as resolved.
Show resolved Hide resolved
* - shared - shared layout
* - final- final layout
addy-pathania marked this conversation as resolved.
Show resolved Hide resolved
*/
export enum LayoutKind {
addy-pathania marked this conversation as resolved.
Show resolved Hide resolved
Final = 'final',
Shared = 'shared',
}

/**
* Shape of context data from the Sitecore Layout Service
*/
Expand Down