17
common/resources/client/core/bootstrap-data/bootstrap-data-context.ts
Executable file
17
common/resources/client/core/bootstrap-data/bootstrap-data-context.ts
Executable file
@@ -0,0 +1,17 @@
|
||||
import {BootstrapData} from './bootstrap-data';
|
||||
import {createContext, useContext} from 'react';
|
||||
|
||||
export interface BoostrapDataContextValue<T = BootstrapData> {
|
||||
data: T;
|
||||
setBootstrapData: (data: string | T) => void;
|
||||
mergeBootstrapData: (data: Partial<T>) => void;
|
||||
invalidateBootstrapData: () => void;
|
||||
}
|
||||
|
||||
export const BoostrapDataContext = createContext<BoostrapDataContextValue>(
|
||||
null!
|
||||
);
|
||||
|
||||
export function useBootstrapData() {
|
||||
return useContext(BoostrapDataContext);
|
||||
}
|
||||
33
common/resources/client/core/bootstrap-data/bootstrap-data-provider.tsx
Executable file
33
common/resources/client/core/bootstrap-data/bootstrap-data-provider.tsx
Executable file
@@ -0,0 +1,33 @@
|
||||
import React, {useMemo} from 'react';
|
||||
import {
|
||||
invalidateBootstrapData,
|
||||
mergeBootstrapData,
|
||||
setBootstrapData,
|
||||
useBackendBootstrapData,
|
||||
} from './use-backend-bootstrap-data';
|
||||
import {
|
||||
BoostrapDataContext,
|
||||
BoostrapDataContextValue,
|
||||
} from './bootstrap-data-context';
|
||||
|
||||
interface BootstrapDataProviderProps {
|
||||
children: any;
|
||||
}
|
||||
export function BootstrapDataProvider({children}: BootstrapDataProviderProps) {
|
||||
const {data} = useBackendBootstrapData();
|
||||
|
||||
const value: BoostrapDataContextValue = useMemo(() => {
|
||||
return {
|
||||
data: data,
|
||||
setBootstrapData: setBootstrapData,
|
||||
mergeBootstrapData: mergeBootstrapData,
|
||||
invalidateBootstrapData: invalidateBootstrapData,
|
||||
};
|
||||
}, [data]);
|
||||
|
||||
return (
|
||||
<BoostrapDataContext.Provider value={value}>
|
||||
{children}
|
||||
</BoostrapDataContext.Provider>
|
||||
);
|
||||
}
|
||||
20
common/resources/client/core/bootstrap-data/bootstrap-data.ts
Executable file
20
common/resources/client/core/bootstrap-data/bootstrap-data.ts
Executable file
@@ -0,0 +1,20 @@
|
||||
import {CssTheme} from '../../ui/themes/css-theme';
|
||||
import {Settings} from '../settings/settings';
|
||||
import {User} from '../../auth/user';
|
||||
import {Role} from '../../auth/role';
|
||||
import {Localization} from '../../i18n/localization';
|
||||
import {MetaTag} from '../../seo/meta-tag';
|
||||
|
||||
export interface BootstrapData {
|
||||
themes: {all: CssTheme[]; selectedThemeId?: number | string | null};
|
||||
sentry_release: string;
|
||||
is_mobile_device: boolean;
|
||||
csrf_token: string;
|
||||
settings: Settings;
|
||||
user: User | null;
|
||||
guest_role: Role | null;
|
||||
i18n: Localization;
|
||||
default_meta_tags: MetaTag[];
|
||||
show_cookie_notice: boolean;
|
||||
rendered_ssr?: boolean;
|
||||
}
|
||||
57
common/resources/client/core/bootstrap-data/use-backend-bootstrap-data.ts
Executable file
57
common/resources/client/core/bootstrap-data/use-backend-bootstrap-data.ts
Executable file
@@ -0,0 +1,57 @@
|
||||
import {apiClient, queryClient} from '../../http/query-client';
|
||||
import {BootstrapData} from './bootstrap-data';
|
||||
import {keepPreviousData, useQuery} from '@tanstack/react-query';
|
||||
|
||||
const queryKey = ['bootstrapData'];
|
||||
|
||||
export function getBootstrapData(): BootstrapData {
|
||||
return queryClient.getQueryData(queryKey)!;
|
||||
}
|
||||
|
||||
export function invalidateBootstrapData() {
|
||||
queryClient.invalidateQueries({queryKey});
|
||||
}
|
||||
|
||||
export function setBootstrapData(data: string | BootstrapData) {
|
||||
queryClient.setQueryData<BootstrapData>(
|
||||
queryKey,
|
||||
typeof data === 'string' ? decodeBootstrapData(data) : data,
|
||||
);
|
||||
}
|
||||
|
||||
export function mergeBootstrapData(partialData: Partial<BootstrapData>) {
|
||||
setBootstrapData({
|
||||
...getBootstrapData(),
|
||||
...partialData,
|
||||
});
|
||||
}
|
||||
|
||||
// set bootstrap data that was provided with initial request from backend
|
||||
const initialBootstrapData = (
|
||||
typeof window !== 'undefined' && window.bootstrapData
|
||||
? decodeBootstrapData(window.bootstrapData)
|
||||
: undefined
|
||||
) as BootstrapData;
|
||||
|
||||
// make sure initial data is available right away when accessing it via "getBootstrapData()"
|
||||
queryClient.setQueryData(queryKey, initialBootstrapData);
|
||||
|
||||
export function useBackendBootstrapData() {
|
||||
return useQuery({
|
||||
queryKey: queryKey,
|
||||
queryFn: () => fetchBootstrapData(),
|
||||
staleTime: Infinity,
|
||||
placeholderData: keepPreviousData,
|
||||
initialData: initialBootstrapData,
|
||||
});
|
||||
}
|
||||
|
||||
const fetchBootstrapData = async (): Promise<BootstrapData> => {
|
||||
return apiClient.get('bootstrap-data').then(response => {
|
||||
return decodeBootstrapData(response.data.data);
|
||||
});
|
||||
};
|
||||
|
||||
function decodeBootstrapData(data: string | BootstrapData): BootstrapData {
|
||||
return typeof data === 'string' ? JSON.parse(data) : data;
|
||||
}
|
||||
Reference in New Issue
Block a user