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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ Our versioning strategy is as follows:

### 🧹 Chores

## 22.1.1

### 🎉 New Features & Improvements
addy-pathania marked this conversation as resolved.
Show resolved Hide resolved

* `[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

## 22.1.0

### 🐛 Bug Fixes
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 @@ -181,6 +181,7 @@ describe('EditingRenderMiddleware', () => {
sc_variant: 'dev',
sc_version: 'latest',
secret: secret,
sc_layoutKind: 'shared',
} as MetadataQueryParams;

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

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

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

expect(res.redirect).to.have.been.calledOnce;
Expand Down Expand Up @@ -297,6 +301,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
Expand Up @@ -2,6 +2,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 { LayoutKind } from '@sitecore-jss/sitecore-jss/editing';
import {
QUERY_PARAM_EDITING_SECRET,
EDITING_ALLOWED_ORIGINS,
Expand Down Expand Up @@ -277,6 +278,7 @@ export type MetadataQueryParams = {
mode: Exclude<LayoutServicePageState, 'normal'>;
sc_variant?: string;
sc_version?: string;
sc_layoutKind?: LayoutKind;
};

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

/**
Expand Down Expand Up @@ -358,6 +361,7 @@ export class MetadataHandler {
version: query.sc_version,
editMode: EditMode.Metadata,
pageState: query.mode,
layoutKind: query.sc_layoutKind,
} 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
38 changes: 26 additions & 12 deletions packages/sitecore-jss/src/editing/graphql-editing-service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
mockEditingServiceResponse,
} from '../test-data/mockEditingServiceResponse';
import { EditMode } from '../layout';
import { LayoutKind } from './models';
import debug from '../debug';

use(spies);
Expand Down Expand Up @@ -91,12 +92,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 +143,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 +156,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
31 changes: 24 additions & 7 deletions packages/sitecore-jss/src/editing/graphql-editing-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { PageInfo } from '../graphql';
import { GraphQLClient, GraphQLRequestClientFactory } from '../graphql-request-client';
import { DictionaryPhrases } from '../i18n';
import { EditMode, LayoutServiceData } from '../layout';
import { LayoutKind } from './models';

/**
* The dictionary query default page size.
Expand Down Expand Up @@ -115,20 +116,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 = LayoutKind.Final,
}: {
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 +154,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,
addy-pathania marked this conversation as resolved.
Show resolved Hide resolved
}
);

if (editingData?.site?.siteInfo?.dictionary) {
dictionaryResults = editingData.site.siteInfo.dictionary.results;
Expand Down
1 change: 1 addition & 0 deletions packages/sitecore-jss/src/editing/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ export {
EditButtonTypes,
mapButtonToCommand,
} from './edit-frame';
export { LayoutKind } from './models';
9 changes: 9 additions & 0 deletions packages/sitecore-jss/src/editing/models.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* Represents the Editing Layout variant.
* - shared - shared layout
* - final - final layout
*/
export enum LayoutKind {
Final = 'final',
Shared = 'shared',
}
27 changes: 21 additions & 6 deletions packages/sitecore-jss/src/graphql-request-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,29 @@ import { DocumentNode } from 'graphql';
import debuggers, { Debugger } from './debug';
import TimeoutPromise from './utils/timeout-promise';

/**
* Options for configuring a GraphQL request.
*/
interface RequestOptions {
[key: string]: unknown;
addy-pathania marked this conversation as resolved.
Show resolved Hide resolved
headers?: Record<string, string>;
}

/**
* An interface for GraphQL clients for Sitecore APIs
*/
export interface GraphQLClient {
/**
* Execute graphql request
* @param {string | DocumentNode} query graphql query
* @param {Object} variables graphql variables
* @param {Object} [variables] graphql variables
* @param {RequestOptions} [options] options for configuring a GraphQL request.
*/
request<T>(query: string | DocumentNode, variables?: { [key: string]: unknown }): Promise<T>;
request<T>(
query: string | DocumentNode,
variables?: { [key: string]: unknown },
options?: RequestOptions
): Promise<T>;
}

/**
Expand Down Expand Up @@ -206,11 +219,13 @@ export class GraphQLRequestClient implements GraphQLClient {
/**
* Execute graphql request
* @param {string | DocumentNode} query graphql query
* @param {Object} variables graphql variables
* @param {Object} [variables] graphql variables
* @param {RequestOptions} [options] Options for configuring a GraphQL request.
*/
async request<T>(
query: string | DocumentNode,
variables?: { [key: string]: unknown }
variables?: { [key: string]: unknown },
options?: RequestOptions
addy-pathania marked this conversation as resolved.
Show resolved Hide resolved
): Promise<T> {
let attempt = 1;

Expand All @@ -219,12 +234,12 @@ export class GraphQLRequestClient implements GraphQLClient {
// (or nice hooks like we have with Axios), but we should log whatever we have.
this.debug('request: %o', {
url: this.endpoint,
headers: this.headers,
headers: { ...this.headers, ...options?.headers },
query,
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, options?.headers)];
if (this.timeout) {
this.abortTimeout = new TimeoutPromise(this.timeout);
fetchWithOptionalTimeout.push(this.abortTimeout.start);
Expand Down