Skip to content

Commit

Permalink
feat: querying menu and block settings
Browse files Browse the repository at this point in the history
  • Loading branch information
nicholasio committed Jul 13, 2024
1 parent 7af7b2d commit 6d2dc90
Show file tree
Hide file tree
Showing 7 changed files with 171 additions and 20 deletions.
105 changes: 105 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 4 additions & 13 deletions packages/core/src/react/provider/useThemeSetting.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,8 @@
'use client';

import { getObjectProperty } from '../../utils';
import { useThemeSettings } from './useThemeSettings';

const get = (obj, path, defaultValue: any = undefined) => {
const travel = (regexp) =>
String.prototype.split
.call(path, regexp)
.filter(Boolean)
.reduce((res, key) => (res !== null && res !== undefined ? res[key] : res), obj);
const result = travel(/[,[\]]+?/) || travel(/[,[\].]+?/);
return result === undefined || result === obj ? defaultValue : result;
};

/**
* Returns a single theme setting normalized
*
Expand All @@ -29,14 +20,14 @@ export function useThemeSetting(
) {
const settings = useThemeSettings();

if (blockName && get(settings, `blocks.${blockName}.${path}`)) {
return get(settings, `blocks.${blockName}.${path}`);
if (blockName && getObjectProperty(settings, `blocks.${blockName}.${path}`)) {
return getObjectProperty(settings, `blocks.${blockName}.${path}`);
}

// if blockName is set but doesn't have the setting and we should not fallback, return the default value only
if (blockName && !fallbackToGlobalSetting) {
return defaultValue;
}

return get(settings, path, defaultValue);
return getObjectProperty(settings, path, defaultValue);
}
9 changes: 9 additions & 0 deletions packages/core/src/utils/getObjectProperty.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export function getObjectProperty(obj, path, defaultValue: any = undefined) {
const travel = (regexp) =>
String.prototype.split
.call(path, regexp)
.filter(Boolean)
.reduce((res, key) => (res !== null && res !== undefined ? res[key] : res), obj);
const result = travel(/[,[\]]+?/) || travel(/[,[\].]+?/);
return result === undefined || result === obj ? defaultValue : result;
}
1 change: 1 addition & 0 deletions packages/core/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ export * from './isInternalLink';
export * from './url';
export * from './log';
export * from './decodeHtmlSpeciaChars';
export * from './getObjectProperty';
44 changes: 39 additions & 5 deletions packages/next/src/rsc/data/queries/queryAppSettings.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,50 @@
import { AppEntity, EndpointParams, HeadlessConfig, fetchAppSettings } from '@headstartwp/core';
import {
AppEntity,
EndpointParams,
HeadlessConfig,
MenuItemEntity,
fetchAppSettings,
getObjectProperty,
} from '@headstartwp/core';
import { handleFetchError } from '../handleFetchError';
import { prepareQuery } from './prepareQuery';
import { NextQueryProps } from './types';
import { AppNextQueryProps } from './types';

type QueryAppSettingsResult = Awaited<ReturnType<typeof fetchAppSettings>> & {
menu?: MenuItemEntity[];
blockSetting?: any;
};

export async function queryAppSettings<
T extends AppEntity = AppEntity,
P extends EndpointParams = EndpointParams,
>(q: NextQueryProps<P>, _config: HeadlessConfig | undefined = undefined) {
const { config, ...query } = prepareQuery<P>(q, _config);
>(
q: AppNextQueryProps<P>,
_config: HeadlessConfig | undefined = undefined,
): Promise<QueryAppSettingsResult> {
const { menu, blockSetting, ...rest } = q;

const { config, ...query } = prepareQuery<P>(rest, _config);

try {
const result = await fetchAppSettings<T, P>(query, config);
const result = (await fetchAppSettings<T, P>(query, config)) as QueryAppSettingsResult;

if (menu && result.data.menus[menu]) {
result.menu = result.data.menus[menu];
}

if (blockSetting && result.data['theme.json']) {
const blockSettingValue = blockSetting?.blockName
? getObjectProperty(
result.data['theme.json'],
`blocks.${blockSetting?.blockName}.${blockSetting.setting}`,
)
: getObjectProperty(result.data['theme.json'], blockSetting.setting);

if (blockSettingValue) {
result.blockSetting = blockSettingValue;
}
}

return result;
} catch (error) {
Expand Down
8 changes: 8 additions & 0 deletions packages/next/src/rsc/data/queries/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,11 @@ export type NextQueryProps<P> = {
[k: string]: unknown;
};
} & Omit<QueryProps<P>, 'path'>;

export type AppNextQueryProps<P> = NextQueryProps<P> & {
menu?: string;
blockSetting?: {
blockName?: string;
setting: string;
};
};
7 changes: 5 additions & 2 deletions projects/wp-nextjs-app/src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { Metadata } from 'next';
import { Inter } from 'next/font/google';
import './globals.css';
import { PreviewIndicator } from '@headstartwp/next/app';
import { PreviewIndicator, queryAppSettings } from '@headstartwp/next/app';

const inter = Inter({ subsets: ['latin'] });

Expand All @@ -10,14 +10,17 @@ export const metadata: Metadata = {
description: 'Generated by create next app',
};

const RootLayout = ({
const RootLayout = async ({
children,
}: Readonly<{
children: React.ReactNode;
}>) => {
const { menu } = await queryAppSettings({ menu: 'primary' });

return (
<html lang="en">
<body className={inter.className}>
{menu ? JSON.stringify(menu) : null}
{children}
<PreviewIndicator className="form-container" />
</body>
Expand Down

0 comments on commit 6d2dc90

Please sign in to comment.