96 lines
3.7 KiB
TypeScript
96 lines
3.7 KiB
TypeScript
import ExitSettingsButton from './components/exit-settings-button';
|
|
import Settings from './components/settings';
|
|
import Sidebar from './components/sidebar';
|
|
import Users from './components/settings/general/users';
|
|
import {Heading, confirmIfDirty, topLevelBackdropClasses, useGlobalDirtyState} from '@tryghost/admin-x-design-system';
|
|
import {type ReactNode, useEffect} from 'react';
|
|
import {canAccessSettings, isEditorUser} from '@tryghost/admin-x-framework/api/users';
|
|
import {toast} from 'react-hot-toast';
|
|
import {useGlobalData} from './components/providers/global-data-provider';
|
|
import {useRouting} from '@tryghost/admin-x-framework/routing';
|
|
|
|
const EMPTY_KEYWORDS: string[] = [];
|
|
|
|
const Page: React.FC<{children: ReactNode}> = ({children}) => {
|
|
return <>
|
|
<div className='fixed top-2 right-0 z-50 m-8 flex justify-end bg-transparent tablet:fixed tablet:top-0' id="done-button-container">
|
|
<ExitSettingsButton />
|
|
</div>
|
|
<div className="fixed top-0 left-0 flex size-full dark:bg-grey-975" id="admin-x-settings-content">
|
|
{children}
|
|
</div>
|
|
</>;
|
|
};
|
|
|
|
const MainContent: React.FC = () => {
|
|
const {currentUser} = useGlobalData();
|
|
const {loadingModal} = useRouting();
|
|
const {isDirty} = useGlobalDirtyState();
|
|
|
|
const navigateAway = (escLocation: string) => {
|
|
window.location.hash = escLocation;
|
|
};
|
|
|
|
useEffect(() => {
|
|
const handleKeyDown = (event: KeyboardEvent) => {
|
|
if (event.key === 'Escape') {
|
|
// Don't navigate away if a modal is open - let the modal handle ESC
|
|
const modalBackdrop = document.getElementById('modal-backdrop');
|
|
if (modalBackdrop) {
|
|
return;
|
|
}
|
|
|
|
confirmIfDirty(isDirty, () => {
|
|
navigateAway('/');
|
|
});
|
|
}
|
|
};
|
|
|
|
window.addEventListener('keydown', handleKeyDown);
|
|
|
|
return () => {
|
|
window.removeEventListener('keydown', handleKeyDown);
|
|
};
|
|
}, [isDirty]);
|
|
|
|
useEffect(() => {
|
|
// resets any toasts that may have been left open on initial load
|
|
toast.remove();
|
|
}, []);
|
|
|
|
// Contributors/Authors only see their profile modal (rendered via routing)
|
|
// Don't render the main settings content for them
|
|
if (!canAccessSettings(currentUser)) {
|
|
return null;
|
|
}
|
|
|
|
if (isEditorUser(currentUser)) {
|
|
return (
|
|
<Page>
|
|
<div className='flex-1 overflow-y-auto bg-white dark:bg-grey-975' id="admin-x-settings-scroller">
|
|
<div className='mx-auto max-w-5xl px-[5vmin] tablet:mt-16 xl:mt-10'>
|
|
<Heading className='mb-[5vmin]'>Settings</Heading>
|
|
<Users highlight={false} keywords={EMPTY_KEYWORDS} />
|
|
</div>
|
|
</div>
|
|
</Page>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<Page>
|
|
{loadingModal && <div className={`fixed inset-0 z-40 h-[calc(100vh-55px)] w-[100vw] tablet:h-[100vh] ${topLevelBackdropClasses}`} />}
|
|
<div className="fixed inset-x-0 top-0 z-[35] max-w-[calc(100%-16px)] flex-1 basis-[320px] bg-white p-8 tablet:relative tablet:inset-x-auto tablet:top-auto tablet:h-full tablet:overflow-y-scroll tablet:bg-grey-50 tablet:py-0 dark:bg-grey-975 dark:tablet:bg-[#101114]" id="admin-x-settings-sidebar-scroller">
|
|
<div className="relative w-full">
|
|
<Sidebar />
|
|
</div>
|
|
</div>
|
|
<div className="relative h-full flex-1 overflow-y-scroll bg-white pt-12 tablet:basis-[800px] dark:bg-grey-975 dark:tablet:bg-black" id="admin-x-settings-scroller">
|
|
<Settings />
|
|
</div>
|
|
</Page>
|
|
);
|
|
};
|
|
|
|
export default MainContent;
|