mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-03-11 02:12:21 -05:00
Updated AdminX search to use centralised configuration (#17106)
refs https://github.com/TryGhost/Team/issues/3349
This commit is contained in:
parent
fdef6a30ab
commit
0d8eb203bf
26 changed files with 129 additions and 87 deletions
|
@ -2,16 +2,16 @@ import ButtonGroup from '../global/ButtonGroup';
|
|||
import React from 'react';
|
||||
import SettingGroupHeader from './SettingGroupHeader';
|
||||
import clsx from 'clsx';
|
||||
import useSearchable from '../../hooks/useSearchable';
|
||||
import {ButtonProps} from '../global/Button';
|
||||
import {SaveState} from '../../hooks/useForm';
|
||||
import {useSearch} from '../../components/providers/ServiceProvider';
|
||||
|
||||
interface SettingGroupProps {
|
||||
navid?:string;
|
||||
testId?: string;
|
||||
title?: string;
|
||||
description?: React.ReactNode;
|
||||
searchKeywords?: string[];
|
||||
keywords?: string[];
|
||||
isEditing?: boolean;
|
||||
saveState?: SaveState;
|
||||
customHeader?: React.ReactNode;
|
||||
|
@ -39,7 +39,7 @@ const SettingGroup: React.FC<SettingGroupProps> = ({
|
|||
testId,
|
||||
title,
|
||||
description,
|
||||
searchKeywords,
|
||||
keywords = [],
|
||||
isEditing,
|
||||
saveState,
|
||||
customHeader,
|
||||
|
@ -53,7 +53,7 @@ const SettingGroup: React.FC<SettingGroupProps> = ({
|
|||
onSave,
|
||||
onCancel
|
||||
}) => {
|
||||
const {isVisible} = useSearchable({keywords: searchKeywords && [title || '', ...searchKeywords]});
|
||||
const {checkVisible} = useSearch();
|
||||
|
||||
const handleEdit = () => {
|
||||
onEditingChange?.(true);
|
||||
|
@ -126,7 +126,7 @@ const SettingGroup: React.FC<SettingGroupProps> = ({
|
|||
}
|
||||
|
||||
return (
|
||||
<div className={clsx('relative flex flex-col gap-6 rounded', !isVisible && 'hidden', border && 'border p-5 md:p-7', styles)} data-testid={testId}>
|
||||
<div className={clsx('relative flex flex-col gap-6 rounded', border && 'border p-5 md:p-7', !checkVisible(keywords) && 'hidden', styles)} data-testid={testId}>
|
||||
<div className='absolute top-[-60px]' id={navid && navid}></div>
|
||||
{customHeader ? customHeader :
|
||||
<SettingGroupHeader description={description} title={title!}>
|
||||
|
|
|
@ -17,11 +17,11 @@ type Story = StoryObj<typeof meta>;
|
|||
export const Default: Story = {
|
||||
args: {
|
||||
title: 'Section header',
|
||||
children:
|
||||
children:
|
||||
<>
|
||||
<SettingGroup {...SettingGroupStories.SingleColumn.args} />
|
||||
<SettingGroup {...SettingGroupStories.Editing.args} />
|
||||
<SettingGroup {...SettingGroupStories.Unsaved.args} />
|
||||
</>
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,14 +1,18 @@
|
|||
import React from 'react';
|
||||
import SettingSectionHeader from './SettingSectionHeader';
|
||||
import {useSearch} from '../../components/providers/ServiceProvider';
|
||||
|
||||
interface Props {
|
||||
title?: string;
|
||||
keywords?: string[];
|
||||
children?: React.ReactNode;
|
||||
}
|
||||
|
||||
const SettingSection: React.FC<Props> = ({title, children}) => {
|
||||
const SettingSection: React.FC<Props> = ({title, keywords = [], children}) => {
|
||||
const {checkVisible} = useSearch();
|
||||
|
||||
return (
|
||||
<div className="!visible hidden [&:has(>div>:not(.hidden))]:!block">
|
||||
<div className={checkVisible(keywords) ? '' : 'hidden'}>
|
||||
{title && <SettingSectionHeader sticky={true} title={title} />}
|
||||
{children &&
|
||||
<div className="mb-[100px] flex flex-col gap-9">
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import React, {createContext, useContext, useMemo} from 'react';
|
||||
import setupGhostApi from '../../utils/api';
|
||||
import useSearchService, {SearchService} from '../../utils/search';
|
||||
import {OfficialTheme} from '../../models/themes';
|
||||
|
||||
export interface FileService {
|
||||
|
@ -9,7 +10,7 @@ interface ServicesContextProps {
|
|||
api: ReturnType<typeof setupGhostApi>;
|
||||
fileService: FileService|null;
|
||||
officialThemes: OfficialTheme[];
|
||||
search: {filter: string, setFilter: (value: string) => void}
|
||||
search: SearchService
|
||||
}
|
||||
|
||||
interface ServicesProviderProps {
|
||||
|
@ -22,7 +23,7 @@ const ServicesContext = createContext<ServicesContextProps>({
|
|||
api: setupGhostApi({ghostVersion: ''}),
|
||||
fileService: null,
|
||||
officialThemes: [],
|
||||
search: {filter: '', setFilter: () => {}}
|
||||
search: {filter: '', setFilter: () => {}, checkVisible: () => true}
|
||||
});
|
||||
|
||||
const ServicesProvider: React.FC<ServicesProviderProps> = ({children, ghostVersion, officialThemes}) => {
|
||||
|
@ -33,15 +34,14 @@ const ServicesProvider: React.FC<ServicesProviderProps> = ({children, ghostVersi
|
|||
return response.images[0].url;
|
||||
}
|
||||
}), [apiService]);
|
||||
|
||||
const [filter, setFilter] = React.useState('');
|
||||
const search = useSearchService();
|
||||
|
||||
return (
|
||||
<ServicesContext.Provider value={{
|
||||
api: apiService,
|
||||
fileService,
|
||||
officialThemes,
|
||||
search: {filter, setFilter}
|
||||
search
|
||||
}}>
|
||||
{children}
|
||||
</ServicesContext.Provider>
|
||||
|
|
|
@ -60,7 +60,7 @@ function getDefaultRecipientValue({
|
|||
return defaultEmailRecipients;
|
||||
}
|
||||
|
||||
const DefaultRecipients: React.FC = () => {
|
||||
const DefaultRecipients: React.FC<{ keywords: string[] }> = ({keywords}) => {
|
||||
const {
|
||||
localSettings,
|
||||
isEditing,
|
||||
|
@ -198,9 +198,9 @@ const DefaultRecipients: React.FC = () => {
|
|||
<SettingGroup
|
||||
description='When you publish new content, who do you usually want to send it to?'
|
||||
isEditing={isEditing}
|
||||
keywords={keywords}
|
||||
navid='default-recipients'
|
||||
saveState={saveState}
|
||||
searchKeywords={['newsletter', 'recipients', 'email']}
|
||||
testId='default-recipients'
|
||||
title='Default recipients'
|
||||
onCancel={handleCancel}
|
||||
|
|
|
@ -3,13 +3,18 @@ import MailGun from './Mailgun';
|
|||
import React from 'react';
|
||||
import SettingSection from '../../../admin-x-ds/settings/SettingSection';
|
||||
|
||||
const searchKeywords = {
|
||||
defaultRecipients: ['newsletter', 'default recipients', 'email'],
|
||||
mailgun: ['mailgun', 'email']
|
||||
};
|
||||
|
||||
const EmailSettings: React.FC = () => {
|
||||
return (
|
||||
<SettingSection title='Email newsletters'>
|
||||
<DefaultRecipients />
|
||||
<MailGun />
|
||||
<SettingSection keywords={Object.values(searchKeywords).flat()} title='Email newsletters'>
|
||||
<DefaultRecipients keywords={searchKeywords.defaultRecipients} />
|
||||
<MailGun keywords={searchKeywords.mailgun} />
|
||||
</SettingSection>
|
||||
);
|
||||
};
|
||||
|
||||
export default EmailSettings;
|
||||
export default EmailSettings;
|
||||
|
|
|
@ -13,7 +13,7 @@ const MAILGUN_REGIONS = [
|
|||
{label: '🇪🇺 EU', value: 'https://api.eu.mailgun.net/v3'}
|
||||
];
|
||||
|
||||
const MailGun: React.FC = () => {
|
||||
const MailGun: React.FC<{ keywords: string[] }> = ({keywords}) => {
|
||||
const {
|
||||
localSettings,
|
||||
isEditing,
|
||||
|
@ -99,9 +99,9 @@ const MailGun: React.FC = () => {
|
|||
<SettingGroup
|
||||
description={groupDescription}
|
||||
isEditing={isEditing}
|
||||
keywords={keywords}
|
||||
navid='mailgun'
|
||||
saveState={saveState}
|
||||
searchKeywords={['mailgun', 'email']}
|
||||
testId='mailgun'
|
||||
title='Mailgun'
|
||||
onCancel={handleCancel}
|
||||
|
|
|
@ -9,7 +9,7 @@ import {ReactComponent as FacebookLogo} from '../../../admin-x-ds/assets/images/
|
|||
import {FileService, ServicesContext} from '../../providers/ServiceProvider';
|
||||
import {getSettingValues} from '../../../utils/helpers';
|
||||
|
||||
const Facebook: React.FC = () => {
|
||||
const Facebook: React.FC<{ keywords: string[] }> = ({keywords}) => {
|
||||
const {
|
||||
localSettings,
|
||||
isEditing,
|
||||
|
@ -100,9 +100,9 @@ const Facebook: React.FC = () => {
|
|||
<SettingGroup
|
||||
description='Customize structured data of your site'
|
||||
isEditing={isEditing}
|
||||
keywords={keywords}
|
||||
navid='facebook'
|
||||
saveState={saveState}
|
||||
searchKeywords={['facebook card', 'structured data', 'rich cards']}
|
||||
testId='facebook'
|
||||
title='Facebook card'
|
||||
onCancel={handleCancel}
|
||||
|
|
|
@ -11,22 +11,32 @@ import TitleAndDescription from './TitleAndDescription';
|
|||
import Twitter from './Twitter';
|
||||
import Users from './Users';
|
||||
|
||||
const searchKeywords = {
|
||||
titleAndDescription: ['title and description', 'site title', 'site description'],
|
||||
timeZone: ['time', 'date', 'site timezone', 'time zone'],
|
||||
publicationLanguage: ['publication language', 'locale'],
|
||||
metadata: ['metadata', 'title', 'description', 'search', 'engine', 'google'],
|
||||
twitter: ['twitter card', 'structured data', 'rich cards'],
|
||||
facebook: ['facebook card', 'structured data', 'rich cards'],
|
||||
socialAccounts: ['social accounts', 'facebook', 'twitter', 'structured data', 'rich cards'],
|
||||
lockSite: ['private', 'password', 'lock site'],
|
||||
users: ['users and permissions', 'roles', 'staff']
|
||||
};
|
||||
|
||||
const GeneralSettings: React.FC = () => {
|
||||
return (
|
||||
<>
|
||||
<SettingSection title="General">
|
||||
<TitleAndDescription />
|
||||
<TimeZone />
|
||||
<PublicationLanguage />
|
||||
<Metadata />
|
||||
<Twitter />
|
||||
<Facebook />
|
||||
<SocialAccounts />
|
||||
<LockSite />
|
||||
<Users />
|
||||
</SettingSection>
|
||||
</>
|
||||
<SettingSection keywords={Object.values(searchKeywords).flat()} title="General">
|
||||
<TitleAndDescription keywords={searchKeywords.titleAndDescription} />
|
||||
<TimeZone keywords={searchKeywords.timeZone} />
|
||||
<PublicationLanguage keywords={searchKeywords.publicationLanguage} />
|
||||
<Metadata keywords={searchKeywords.metadata} />
|
||||
<Twitter keywords={searchKeywords.twitter} />
|
||||
<Facebook keywords={searchKeywords.facebook} />
|
||||
<SocialAccounts keywords={searchKeywords.socialAccounts} />
|
||||
<LockSite keywords={searchKeywords.lockSite} />
|
||||
<Users keywords={searchKeywords.users} />
|
||||
</SettingSection>
|
||||
);
|
||||
};
|
||||
|
||||
export default GeneralSettings;
|
||||
export default GeneralSettings;
|
||||
|
|
|
@ -8,7 +8,7 @@ import Toggle from '../../../admin-x-ds/global/form/Toggle';
|
|||
import useSettingGroup from '../../../hooks/useSettingGroup';
|
||||
import {getSettingValues} from '../../../utils/helpers';
|
||||
|
||||
const LockSite: React.FC = () => {
|
||||
const LockSite: React.FC<{ keywords: string[] }> = ({keywords}) => {
|
||||
const {
|
||||
localSettings,
|
||||
isEditing,
|
||||
|
@ -81,9 +81,9 @@ const LockSite: React.FC = () => {
|
|||
<SettingGroup
|
||||
description='Enable protection with a simple shared password.'
|
||||
isEditing={isEditing}
|
||||
keywords={keywords}
|
||||
navid='locksite'
|
||||
saveState={saveState}
|
||||
searchKeywords={['private', 'password', 'lock']}
|
||||
testId='locksite'
|
||||
title='Make site private'
|
||||
onCancel={handleCancel}
|
||||
|
|
|
@ -55,7 +55,7 @@ const SearchEnginePreview: React.FC<SearchEnginePreviewProps> = ({
|
|||
);
|
||||
};
|
||||
|
||||
const Metadata: React.FC = () => {
|
||||
const Metadata: React.FC<{ keywords: string[] }> = ({keywords}) => {
|
||||
const {
|
||||
localSettings,
|
||||
isEditing,
|
||||
|
@ -102,9 +102,9 @@ const Metadata: React.FC = () => {
|
|||
<SettingGroup
|
||||
description='Extra content for search engines'
|
||||
isEditing={isEditing}
|
||||
keywords={keywords}
|
||||
navid='metadata'
|
||||
saveState={saveState}
|
||||
searchKeywords={['meta', 'title', 'description', 'search', 'engine', 'google']}
|
||||
testId='metadata'
|
||||
title='Metadata'
|
||||
onCancel={handleCancel}
|
||||
|
|
|
@ -5,7 +5,7 @@ import TextField from '../../../admin-x-ds/global/form/TextField';
|
|||
import useSettingGroup from '../../../hooks/useSettingGroup';
|
||||
import {getSettingValues} from '../../../utils/helpers';
|
||||
|
||||
const PublicationLanguage: React.FC = () => {
|
||||
const PublicationLanguage: React.FC<{ keywords: string[] }> = ({keywords}) => {
|
||||
const {
|
||||
localSettings,
|
||||
isEditing,
|
||||
|
@ -57,9 +57,9 @@ const PublicationLanguage: React.FC = () => {
|
|||
<SettingGroup
|
||||
description="Set the language/locale which is used on your site"
|
||||
isEditing={isEditing}
|
||||
keywords={keywords}
|
||||
navid='publication-language'
|
||||
saveState={saveState}
|
||||
searchKeywords={['language', 'locale']}
|
||||
testId='publication-language'
|
||||
title="Publication Language"
|
||||
onCancel={handleCancel}
|
||||
|
|
|
@ -59,7 +59,7 @@ function validateTwitterUrl(newUrl: string) {
|
|||
}
|
||||
}
|
||||
|
||||
const SocialAccounts: React.FC = () => {
|
||||
const SocialAccounts: React.FC<{ keywords: string[] }> = ({keywords}) => {
|
||||
const {
|
||||
localSettings,
|
||||
isEditing,
|
||||
|
@ -158,9 +158,9 @@ const SocialAccounts: React.FC = () => {
|
|||
<SettingGroup
|
||||
description='Link your social accounts for full structured data and rich card support'
|
||||
isEditing={isEditing}
|
||||
keywords={keywords}
|
||||
navid='social-accounts'
|
||||
saveState={saveState}
|
||||
searchKeywords={['social', 'accounts', 'facebook', 'twitter', 'structured data', 'rich cards']}
|
||||
testId='social-accounts'
|
||||
title='Social accounts'
|
||||
onCancel={handleCancel}
|
||||
|
|
|
@ -34,7 +34,7 @@ const Hint: React.FC<HintProps> = ({timezone}) => {
|
|||
);
|
||||
};
|
||||
|
||||
const TimeZone: React.FC = () => {
|
||||
const TimeZone: React.FC<{ keywords: string[] }> = ({keywords}) => {
|
||||
const {
|
||||
localSettings,
|
||||
isEditing,
|
||||
|
@ -85,9 +85,9 @@ const TimeZone: React.FC = () => {
|
|||
<SettingGroup
|
||||
description='Set the time and date of your publication, used for all published posts'
|
||||
isEditing={isEditing}
|
||||
keywords={keywords}
|
||||
navid='timezone'
|
||||
saveState={saveState}
|
||||
searchKeywords={['time', 'date', 'timezone', 'time zone']}
|
||||
testId='timezone'
|
||||
title='Site timezone'
|
||||
onCancel={handleCancel}
|
||||
|
|
|
@ -6,7 +6,7 @@ import TextField from '../../../admin-x-ds/global/form/TextField';
|
|||
import useSettingGroup from '../../../hooks/useSettingGroup';
|
||||
import {getSettingValues} from '../../../utils/helpers';
|
||||
|
||||
const TitleAndDescription: React.FC = () => {
|
||||
const TitleAndDescription: React.FC<{ keywords: string[] }> = ({keywords}) => {
|
||||
const {
|
||||
localSettings,
|
||||
isEditing,
|
||||
|
@ -69,9 +69,9 @@ const TitleAndDescription: React.FC = () => {
|
|||
<SettingGroup
|
||||
description='The details used to identify your publication around the web'
|
||||
isEditing={isEditing}
|
||||
keywords={keywords}
|
||||
navid='title-and-description'
|
||||
saveState={saveState}
|
||||
searchKeywords={['site title', 'site description']}
|
||||
testId='title-and-description'
|
||||
title='Title & description'
|
||||
onCancel={handleCancel}
|
||||
|
|
|
@ -9,7 +9,7 @@ import {FileService, ServicesContext} from '../../providers/ServiceProvider';
|
|||
import {ReactComponent as TwitterLogo} from '../../../admin-x-ds/assets/images/twitter-logo.svg';
|
||||
import {getSettingValues} from '../../../utils/helpers';
|
||||
|
||||
const Twitter: React.FC = () => {
|
||||
const Twitter: React.FC<{ keywords: string[] }> = ({keywords}) => {
|
||||
const {
|
||||
localSettings,
|
||||
isEditing,
|
||||
|
@ -102,9 +102,9 @@ const Twitter: React.FC = () => {
|
|||
<SettingGroup
|
||||
description='Customize structured data of your site'
|
||||
isEditing={isEditing}
|
||||
keywords={keywords}
|
||||
navid='twitter'
|
||||
saveState={saveState}
|
||||
searchKeywords={['twitter card', 'structured data', 'rich cards']}
|
||||
testId='twitter'
|
||||
title='Twitter card'
|
||||
onCancel={handleCancel}
|
||||
|
|
|
@ -180,7 +180,7 @@ const InvitesUserList: React.FC<InviteListProps> = ({users}) => {
|
|||
);
|
||||
};
|
||||
|
||||
const Users: React.FC = () => {
|
||||
const Users: React.FC<{ keywords: string[] }> = ({keywords}) => {
|
||||
const {
|
||||
ownerUser,
|
||||
adminUsers,
|
||||
|
@ -234,8 +234,8 @@ const Users: React.FC = () => {
|
|||
return (
|
||||
<SettingGroup
|
||||
customButtons={buttons}
|
||||
keywords={keywords}
|
||||
navid='users'
|
||||
searchKeywords={['users', 'permissions', 'roles', 'staff']}
|
||||
testId='users'
|
||||
title='Users and permissions'
|
||||
>
|
||||
|
|
|
@ -28,7 +28,7 @@ const COMMENTS_ENABLED_OPTIONS = [
|
|||
{value: 'off', label: 'Nobody'}
|
||||
];
|
||||
|
||||
const Access: React.FC = () => {
|
||||
const Access: React.FC<{ keywords: string[] }> = ({keywords}) => {
|
||||
const {
|
||||
localSettings,
|
||||
isEditing,
|
||||
|
@ -143,9 +143,9 @@ const Access: React.FC = () => {
|
|||
<SettingGroup
|
||||
description='Set up default access options for subscription and posts'
|
||||
isEditing={isEditing}
|
||||
keywords={keywords}
|
||||
navid='access'
|
||||
saveState={saveState}
|
||||
searchKeywords={['access', 'subscription', 'post']}
|
||||
testId='access'
|
||||
title='Access'
|
||||
onCancel={handleCancel}
|
||||
|
|
|
@ -6,7 +6,7 @@ import Toggle from '../../../admin-x-ds/global/form/Toggle';
|
|||
import useSettingGroup from '../../../hooks/useSettingGroup';
|
||||
import {getSettingValues} from '../../../utils/helpers';
|
||||
|
||||
const Analytics: React.FC = () => {
|
||||
const Analytics: React.FC<{ keywords: string[] }> = ({keywords}) => {
|
||||
const {
|
||||
localSettings,
|
||||
isEditing,
|
||||
|
@ -76,9 +76,9 @@ const Analytics: React.FC = () => {
|
|||
description='Decide what data you collect from your members'
|
||||
hideEditButton={true}
|
||||
isEditing={isEditing}
|
||||
keywords={keywords}
|
||||
navid='analytics'
|
||||
saveState={saveState}
|
||||
searchKeywords={['analytics', 'tracking', 'privacy']}
|
||||
testId='analytics'
|
||||
title='Analytics'
|
||||
onCancel={handleCancel}
|
||||
|
|
|
@ -3,13 +3,18 @@ import Analytics from './Analytics';
|
|||
import React from 'react';
|
||||
import SettingSection from '../../../admin-x-ds/settings/SettingSection';
|
||||
|
||||
const searchKeywords = {
|
||||
access: ['access', 'subscription', 'post'],
|
||||
analytics: ['analytics', 'tracking', 'privacy']
|
||||
};
|
||||
|
||||
const MembershipSettings: React.FC = () => {
|
||||
return (
|
||||
<SettingSection title='Membership'>
|
||||
<Access />
|
||||
<Analytics />
|
||||
<SettingSection keywords={Object.values(searchKeywords).flat()} title='Membership'>
|
||||
<Access keywords={searchKeywords.access} />
|
||||
<Analytics keywords={searchKeywords.analytics} />
|
||||
</SettingSection>
|
||||
);
|
||||
};
|
||||
|
||||
export default MembershipSettings;
|
||||
export default MembershipSettings;
|
||||
|
|
|
@ -4,7 +4,7 @@ import NiceModal from '@ebay/nice-modal-react';
|
|||
import React from 'react';
|
||||
import SettingGroup from '../../../admin-x-ds/settings/SettingGroup';
|
||||
|
||||
const DesignSetting: React.FC = () => {
|
||||
const DesignSetting: React.FC<{ keywords: string[] }> = ({keywords}) => {
|
||||
const openPreviewModal = () => {
|
||||
NiceModal.show(DesignModal);
|
||||
};
|
||||
|
@ -13,8 +13,8 @@ const DesignSetting: React.FC = () => {
|
|||
<SettingGroup
|
||||
customButtons={<Button color='green' label='Customize' link onClick={openPreviewModal}/>}
|
||||
description="Customize the look and feel of your site"
|
||||
keywords={keywords}
|
||||
navid='branding-and-design'
|
||||
searchKeywords={['design', 'branding', 'logo', 'cover', 'colors', 'fonts', 'background']}
|
||||
testId='design'
|
||||
title="Branding and design"
|
||||
/>
|
||||
|
|
|
@ -4,7 +4,7 @@ import NiceModal from '@ebay/nice-modal-react';
|
|||
import React from 'react';
|
||||
import SettingGroup from '../../../admin-x-ds/settings/SettingGroup';
|
||||
|
||||
const Navigation: React.FC = () => {
|
||||
const Navigation: React.FC<{ keywords: string[] }> = ({keywords}) => {
|
||||
const openPreviewModal = () => {
|
||||
NiceModal.show(NavigationModal);
|
||||
};
|
||||
|
@ -13,8 +13,8 @@ const Navigation: React.FC = () => {
|
|||
<SettingGroup
|
||||
customButtons={<Button color='green' label='Customize' link onClick={openPreviewModal}/>}
|
||||
description="Set up primary and secondary menus"
|
||||
keywords={keywords}
|
||||
navid='navigation'
|
||||
searchKeywords={['navigation', 'menus', 'primary', 'secondary', 'links']}
|
||||
testId='navigation'
|
||||
title="Navigation"
|
||||
/>
|
||||
|
|
|
@ -4,13 +4,19 @@ import React from 'react';
|
|||
import SettingSection from '../../../admin-x-ds/settings/SettingSection';
|
||||
import Theme from './Theme';
|
||||
|
||||
const searchKeywords = {
|
||||
theme: ['themes', 'design', 'appearance', 'style'],
|
||||
design: ['design', 'branding', 'logo', 'cover', 'colors', 'fonts', 'background'],
|
||||
navigation: ['navigation', 'menus', 'primary', 'secondary', 'links']
|
||||
};
|
||||
|
||||
const SiteSettings: React.FC = () => {
|
||||
return (
|
||||
<>
|
||||
<SettingSection title="Site">
|
||||
<Theme />
|
||||
<DesignSetting />
|
||||
<Navigation />
|
||||
<SettingSection keywords={Object.values(searchKeywords).flat()} title="Site">
|
||||
<Theme keywords={searchKeywords.theme} />
|
||||
<DesignSetting keywords={searchKeywords.design} />
|
||||
<Navigation keywords={searchKeywords.navigation} />
|
||||
</SettingSection>
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -4,15 +4,15 @@ import NiceModal from '@ebay/nice-modal-react';
|
|||
import React from 'react';
|
||||
import SettingGroup from '../../../admin-x-ds/settings/SettingGroup';
|
||||
|
||||
const Theme: React.FC = () => {
|
||||
const Theme: React.FC<{ keywords: string[] }> = ({keywords}) => {
|
||||
return (
|
||||
<SettingGroup
|
||||
customButtons={<Button color='green' label='Manage themes' link onClick={() => {
|
||||
NiceModal.show(ChangeThemeModal);
|
||||
}}/>}
|
||||
description="Change or upload themes"
|
||||
keywords={keywords}
|
||||
navid='theme'
|
||||
searchKeywords={['themes', 'design', 'appearance', 'style']}
|
||||
testId='theme'
|
||||
title="Theme"
|
||||
/>
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
import {useSearch} from '../components/providers/ServiceProvider';
|
||||
|
||||
const useSearchable = ({keywords}: { keywords: string[] | undefined }) => {
|
||||
const {filter} = useSearch();
|
||||
|
||||
if (!filter || !keywords) {
|
||||
return {isVisible: true};
|
||||
}
|
||||
|
||||
const isVisible = keywords.some(keyword => keyword.toLowerCase().includes(filter.toLowerCase()));
|
||||
|
||||
return {isVisible};
|
||||
};
|
||||
|
||||
export default useSearchable;
|
27
apps/admin-x-settings/src/utils/search.ts
Normal file
27
apps/admin-x-settings/src/utils/search.ts
Normal file
|
@ -0,0 +1,27 @@
|
|||
import {useState} from 'react';
|
||||
|
||||
export interface SearchService {
|
||||
filter: string;
|
||||
setFilter: (value: string) => void;
|
||||
checkVisible: (keywords: string[]) => boolean;
|
||||
}
|
||||
|
||||
const useSearchService = () => {
|
||||
const [filter, setFilter] = useState('');
|
||||
|
||||
const checkVisible = (keywords: string[]) => {
|
||||
if (!keywords.length) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return keywords.some(keyword => keyword.toLowerCase().includes(filter.toLowerCase()));
|
||||
};
|
||||
|
||||
return {
|
||||
filter,
|
||||
setFilter,
|
||||
checkVisible
|
||||
};
|
||||
};
|
||||
|
||||
export default useSearchService;
|
Loading…
Add table
Reference in a new issue