diff --git a/apps/admin-x-settings/src/MainContent.tsx b/apps/admin-x-settings/src/MainContent.tsx index 09e62d3d49..f1ddeabafa 100644 --- a/apps/admin-x-settings/src/MainContent.tsx +++ b/apps/admin-x-settings/src/MainContent.tsx @@ -6,6 +6,7 @@ import Users from './components/settings/general/Users'; import useRouting from './hooks/useRouting'; import {ReactNode, useEffect} from 'react'; import {canAccessSettings, isEditorUser} from './api/users'; +import {topLevelBackdropClasses} from './admin-x-ds/global/modal/Modal'; import {useGlobalData} from './components/providers/GlobalDataProvider'; const Page: React.FC<{children: ReactNode}> = ({children}) => { @@ -22,7 +23,7 @@ const Page: React.FC<{children: ReactNode}> = ({children}) => { const MainContent: React.FC = () => { const {currentUser} = useGlobalData(); - const {route, updateRoute} = useRouting(); + const {route, updateRoute, loadingModal} = useRouting(); useEffect(() => { if (!canAccessSettings(currentUser) && route !== `users/show/${currentUser.slug}`) { @@ -47,6 +48,8 @@ const MainContent: React.FC = () => { return ( + {loadingModal &&
} + {/* Sidebar */}
diff --git a/apps/admin-x-settings/src/admin-x-ds/global/modal/Modal.tsx b/apps/admin-x-settings/src/admin-x-ds/global/modal/Modal.tsx index 300d7bfc81..45ccdc02de 100644 --- a/apps/admin-x-settings/src/admin-x-ds/global/modal/Modal.tsx +++ b/apps/admin-x-settings/src/admin-x-ds/global/modal/Modal.tsx @@ -41,6 +41,8 @@ export interface ModalProps { formSheet?: boolean; } +export const topLevelBackdropClasses = 'bg-[rgba(98,109,121,0.2)] backdrop-blur-[3px]'; + const Modal: React.FC = ({ size = 'md', testId, @@ -257,7 +259,7 @@ const Modal: React.FC = ({ -
+
diff --git a/apps/admin-x-settings/src/components/providers/RoutingProvider.tsx b/apps/admin-x-settings/src/components/providers/RoutingProvider.tsx index 05edc694a6..55c77b0058 100644 --- a/apps/admin-x-settings/src/components/providers/RoutingProvider.tsx +++ b/apps/admin-x-settings/src/components/providers/RoutingProvider.tsx @@ -18,11 +18,13 @@ export type InternalLink = { export type RoutingContextData = { route: string; updateRoute: (to: string | InternalLink | ExternalLink) => void; + loadingModal: boolean; }; export const RouteContext = createContext({ route: '', - updateRoute: () => {} + updateRoute: () => {}, + loadingModal: false }); export type RoutingModalProps = { @@ -108,13 +110,16 @@ const handleNavigation = () => { if (pathName) { const [path, modal] = Object.entries(modalPaths).find(([modalPath]) => matchRoute(pathName, modalPath)) || []; - if (path && modal) { - modal().then(({default: component}) => NiceModal.show(component, {params: matchRoute(pathName, path)})); - } - - return pathName; + return { + pathName, + modal: (path && modal) ? + modal().then(({default: component}) => { + NiceModal.show(component, {params: matchRoute(pathName, path)}); + }) : + undefined + }; } - return ''; + return {pathName: ''}; }; const matchRoute = (pathname: string, routeDefinition: string) => { @@ -133,7 +138,8 @@ type RouteProviderProps = { }; const RoutingProvider: React.FC = ({externalNavigate, children}) => { - const [route, setRoute] = useState(''); + const [route, setRoute] = useState(undefined); + const [loadingModal, setLoadingModal] = useState(false); useEffect(() => { // Preload all the modals after initial render to avoid a delay when opening them @@ -161,12 +167,16 @@ const RoutingProvider: React.FC = ({externalNavigate, childr useEffect(() => { const handleHashChange = () => { - const matchedRoute = handleNavigation(); - setRoute(matchedRoute); + const {pathName, modal} = handleNavigation(); + setRoute(pathName); + + if (modal) { + setLoadingModal(true); + modal.then(() => setLoadingModal(false)); + } }; - const matchedRoute = handleNavigation(); - setRoute(matchedRoute); + handleHashChange(); window.addEventListener('hashchange', handleHashChange); @@ -175,11 +185,16 @@ const RoutingProvider: React.FC = ({externalNavigate, childr }; }, []); // eslint-disable-line react-hooks/exhaustive-deps + if (route === undefined) { + return null; + } + return ( diff --git a/apps/admin-x-settings/src/components/settings/email/newsletters/NewsletterDetailModal.tsx b/apps/admin-x-settings/src/components/settings/email/newsletters/NewsletterDetailModal.tsx index 5a70f95279..243e44c84d 100644 --- a/apps/admin-x-settings/src/components/settings/email/newsletters/NewsletterDetailModal.tsx +++ b/apps/admin-x-settings/src/components/settings/email/newsletters/NewsletterDetailModal.tsx @@ -321,6 +321,7 @@ const Sidebar: React.FC<{ config={config} hint='Any extra information or legal text' nodes='MINIMAL_NODES' + placeholder=' ' title='Email footer' value={newsletter.footer_content || ''} onChange={html => updateNewsletter({footer_content: html})} diff --git a/apps/admin-x-settings/src/components/settings/membership/Tiers.tsx b/apps/admin-x-settings/src/components/settings/membership/Tiers.tsx index a7be96ea7c..4361d40634 100644 --- a/apps/admin-x-settings/src/components/settings/membership/Tiers.tsx +++ b/apps/admin-x-settings/src/components/settings/membership/Tiers.tsx @@ -35,14 +35,7 @@ const Tiers: React.FC<{ keywords: string[] }> = ({keywords}) => { }; const sortTiers = (t: Tier[]) => { - t.sort((a, b) => { - if ((a.monthly_price as number) < (b.monthly_price as number)) { - return -1; - } else { - return 1; - } - }); - return t; + return [...t].sort((a, b) => (a.monthly_price ?? 0) - (b.monthly_price ?? 0)); }; const tabs = [ diff --git a/apps/admin-x-settings/src/components/settings/membership/tiers/TierDetailModal.tsx b/apps/admin-x-settings/src/components/settings/membership/tiers/TierDetailModal.tsx index cbeae5b80e..16be05fa75 100644 --- a/apps/admin-x-settings/src/components/settings/membership/tiers/TierDetailModal.tsx +++ b/apps/admin-x-settings/src/components/settings/membership/tiers/TierDetailModal.tsx @@ -244,6 +244,11 @@ const TierDetailModalContent: React.FC<{tier?: Tier}> = ({tier}) => { value={benefits.newItem} hideTitle onChange={e => benefits.setNewItem(e.target.value)} + onKeyDown={(e) => { + if (e.key === 'Enter') { + benefits.addItem(); + } + }} />