diff --git a/__test__/test-website/src/app/related/[...slug]/page.tsx b/__test__/test-website/src/app/related/[...slug]/page.tsx index 5016e79e..ef057737 100644 --- a/__test__/test-website/src/app/related/[...slug]/page.tsx +++ b/__test__/test-website/src/app/related/[...slug]/page.tsx @@ -1,5 +1,4 @@ import { GraphClient } from '@optimizely/cms-sdk'; -import { OptimizelyComponent } from '@optimizely/cms-sdk/react/server'; import React from 'react'; type Props = { @@ -17,21 +16,8 @@ export default async function Page({ params }: Props) { graphUrl: process.env.OPTIMIZELY_GRAPH_URL, }); - const children = [ - ...((await client.getLinksByPath(`/${slug.join('/')}/`)) ?? []), - // NOTE: if you are using "simple address", you should fetch without trailing slash: - ...((await client.getLinksByPath(`/${slug.join('/')}`)) ?? []), - ]; - const ancestors = [ - ...((await client.getLinksByPath(`/${slug.join('/')}/`, { - type: 'PATH', - })) ?? []), - // Same here: - ...((await client.getLinksByPath(`/${slug.join('/')}`, { - type: 'PATH', - })) ?? []), - ]; - // .catch(handleGraphErrors); + const children = (await client.getItems(`/${slug.join('/')}`)) ?? []; + const ancestors = (await client.getPath(`/${slug.join('/')}`)) ?? []; return (
@@ -39,16 +25,16 @@ export default async function Page({ params }: Props) {

Children

Ancestors (breadcrumbs)

    {ancestors?.map((l) => ( -
  1. - {l?.displayName} ({l?.url?.default}) +
  2. + {l?._metadata?.displayName} ({l?._metadata?.url?.default})
  3. ))}
diff --git a/packages/optimizely-cms-sdk/src/graph/filters.ts b/packages/optimizely-cms-sdk/src/graph/filters.ts index b0cd97dd..9a14cf24 100644 --- a/packages/optimizely-cms-sdk/src/graph/filters.ts +++ b/packages/optimizely-cms-sdk/src/graph/filters.ts @@ -93,10 +93,17 @@ export function variationFilter(value: string): ContentInput { }; } +export function localeFilter(locale?: string[]): ContentInput { + return { + locale, + }; +} + /** * Arguments for querying content via the Graph API. */ export type ContentInput = { + locale?: string[]; variation?: GraphVariationInput; where?: ContentWhereInput; }; diff --git a/packages/optimizely-cms-sdk/src/graph/index.ts b/packages/optimizely-cms-sdk/src/graph/index.ts index 1e03c515..538aa60a 100644 --- a/packages/optimizely-cms-sdk/src/graph/index.ts +++ b/packages/optimizely-cms-sdk/src/graph/index.ts @@ -13,6 +13,7 @@ import { pathFilter, previewFilter, GraphVariationInput, + localeFilter, } from './filters.js'; /** Options for Graph */ @@ -35,7 +36,8 @@ export type GraphGetContentOptions = { }; export type GraphGetLinksOptions = { - type?: 'DEFAULT' | 'ITEMS' | 'ASSETS' | 'PATH'; + host?: string; + locales?: string[]; }; export { GraphVariationInput }; @@ -53,15 +55,42 @@ query GetContentMetadata($where: _ContentWhereInput, $variation: VariationInput) } `; -const GET_LINKS_QUERY = ` -query GetLinks($where: _ContentWhereInput, $type: LinkTypes) { - _Content(where: $where) { +const GET_PATH_QUERY = ` +query GetPath($where: _ContentWhereInput, $locale: [Locale]) { + _Content(where: $where, locale: $locale) { item { _id - _link(type: $type) { + _link(type: PATH) { _Page { items { _metadata { + key + sortOrder + displayName + locale + types + url { + hierarchical + default + } + } + } + } + } + } + } +}`; + +const GET_ITEMS_QUERY = ` +query GetPath($where: _ContentWhereInput, $locale: [Locale]) { + _Content(where: $where, locale: $locale) { + item { + _id + _link(type: ITEMS) { + _Page { + items { + _metadata { + key sortOrder displayName locale @@ -86,6 +115,7 @@ type GetLinksResponse = { _Page: { items: Array<{ _metadata?: { + key: string; sortOrder?: number; displayName?: string; locale?: string; @@ -254,41 +284,60 @@ export class GraphClient { return response?._Content?.items; } - async getLinksByPath(path: string, options?: GraphGetLinksOptions) { - const input = { - ...pathFilter(path), - type: options?.type, - }; - const data = (await this.request( - GET_LINKS_QUERY, - input - )) as GetLinksResponse; + /** + * Given the path of a page, return its "path" (i.e. a list of ancestor pages). + * + * @param path The URL of the current page + * @returns A list with the metadata information of all ancestors sorted + * from the top-most to the current + */ + async getPath(path: string, options?: GraphGetLinksOptions) { + const data = (await this.request(GET_PATH_QUERY, { + ...pathFilter(path, options?.host), + ...localeFilter(options?.locales), + })) as GetLinksResponse; // Check if the page itself exist. if (!data._Content.item._id) { return null; } - const links = data?._Content?.item._link._Page.items.map( - (i) => i._metadata - ); + const links = data?._Content?.item._link._Page.items; - if (options?.type === 'PATH') { - // Return sorted by "hierarchical" - return links.toSorted((a, b) => { - const ha = a?.url?.hierarchical ?? ''; - const hb = b?.url?.hierarchical ?? ''; + // Return sorted by "hierarchical" + return links.toSorted((a, b) => { + const ha = a?._metadata?.url?.hierarchical ?? ''; + const hb = b?._metadata?.url?.hierarchical ?? ''; - if (ha > hb) { - return 1; - } - if (ha < hb) { - return -1; - } - return 0; - }); + if (ha > hb) { + return 1; + } + if (ha < hb) { + return -1; + } + return 0; + }); + } + + /** + * Given the path of a page, get its "items" (i.e. the children pages) + * + * @param path The URL of the current page + * @returns A list with the metadata information of all child/descendant pages + */ + async getItems(path: string, options?: GraphGetLinksOptions) { + const data = (await this.request(GET_ITEMS_QUERY, { + ...pathFilter(path, options?.host), + ...localeFilter(options?.locales), + })) as GetLinksResponse; + + // Check if the page itself exist. + if (!data._Content.item._id) { + return null; } + const links = data?._Content?.item._link._Page.items; + return links; } diff --git a/packages/optimizely-cms-sdk/src/index.ts b/packages/optimizely-cms-sdk/src/index.ts index fb98bd8f..43bd3001 100644 --- a/packages/optimizely-cms-sdk/src/index.ts +++ b/packages/optimizely-cms-sdk/src/index.ts @@ -11,6 +11,7 @@ export { export { GraphClient, GraphGetContentOptions, + GraphGetLinksOptions, GraphVariationInput, } from './graph/index.js'; export type { PreviewParams } from './graph/index.js';