import { Admin } from './Admin'; import { CatchResult, IErrorEventHandler, useErrorEventCatcher } from './dev'; import { useI18nProvider } from './i18n'; import { ThemeCustomizationProvider } from './themes'; import { AuthBackground, GenericErrorPage, Layout, LoginPage, MainIcon, MenuConfigProvider, MenuItem, Notification, SmallIcon } from '@/components'; import type { PushNotificationConfig } from '@/hooks/usePushNotifications'; import { AppStateProvider } from '@/components/AppStateProvider'; import { ThemeConfig, ThemeProvider } from '@/components/Layout/ThemeProvider'; import { GoogleOAuthProvider } from '@react-oauth/google'; import React, { useMemo } from 'react'; import { AdminProps, AuthProvider, DataProvider, I18nProvider } from 'react-admin'; import { QueryClient } from 'react-query'; const defaultQueryClient = new QueryClient({ defaultOptions: { queries: { refetchOnWindowFocus: false } } }); /** * Define a basic super cool application based on React Admin, Mantis Theme and our style. */ function ApplicaAdmin({ theme, themeConfig, apiUrl, defaultLocale = 'en', development = false, logoMain, logoIcon, loginPage = } />, menu, name, copy, version = '0.0.0', dataProvider, authProvider, i18nProvider: _i18nProvider, errorHandler, error, enableNotification = false, enableRegistration = false, enablePasswordRecover = false, enableThemeToggler = false, enableLocaleSwitcher = false, oauth = {}, queryClient = defaultQueryClient, background, notificationAPI = 'entities/notification', pushNotifications, ...props }: ApplicaAdminProps): JSX.Element { useErrorEventCatcher({ apiUrl, errorHandler, catcherFn: (error: ErrorEvent | string): CatchResult => { const errorMessage = error?.toString(); const knownErrors = [ // @see https://github.com/marmelab/react-admin/pull/8884 'Invalid prop `file` of type `string` supplied to `FileInputPreview`, expected `object`.', 'Failed prop type: Invalid prop `checked` of type `string` supplied to `ForwardRef(Switch)`, expected `boolean`.', 'Failed prop type: Invalid prop `checked` of type `string` supplied to `ForwardRef(SwitchBase)`, expected `boolean`.', 'Support for defaultProps will be removed from function components in a future major release.', 'validateDOMNesting(...):
cannot appear as a descendant of .', 'Missing translation for key:', 'HttpError: ' ]; const isKnowBug = knownErrors.some((knownError) => errorMessage?.includes(knownError)); const result = new CatchResult({ catch: isKnowBug, display: !isKnowBug, log: !isKnowBug && development === true, error: errorMessage }); return result; } }); const login = useMemo(() => { if (React.isValidElement(loginPage)) { return React.cloneElement(loginPage, { // @ts-ignore name, copy, logo: logoMain, version, background, enableRegistration, enablePasswordRecover, oauth }); } return loginPage; }, [loginPage, name, version, copy, background, logoMain, enableRegistration, enablePasswordRecover, oauth]); const layout = useMemo( () => (props: any) => { const _logoMain = name ? : logoMain; const _logoIcon = name ? : logoIcon; return ( ); }, [ logoMain, logoIcon, name, copy, version, error, notificationAPI, enableNotification, enableThemeToggler, enableLocaleSwitcher, pushNotifications ] ); const i18nProvider = useI18nProvider({ apiUrl: apiUrl, defaultLocale: defaultLocale, allowMissing: development, createMissing: development, customProvider: _i18nProvider }) as I18nProvider; if (i18nProvider === undefined) { return <>; } else if (i18nProvider.error) { return ( ); } const appContent = ( ); if (oauth.google?.clientId) { return {appContent}; } else { return appContent; } } type ApplicaAdminProps = AdminProps & { /** * Optional: Push notification configuration for enabling FCM notifications. * If provided, enables foreground push notification listening and triggers notification panel refresh on new messages. */ pushNotifications?: PushNotificationConfig; /** * Optionally, a custom theme to use in the application. * @remarks This theme is based on Mantis Theme (https://mantisdashboard.io/) * * @see https://marmelab.com/react-admin/Theming.html * @see https://material-ui.com/customization/theming/ */ theme: any; /** * Optionally, a custom theme configuration to use in the application. * Have fun with caution to modify theme configuration variables, if you make a mess Marco Colucci could use the fire extinguisher (I said everything). */ themeConfig: ThemeConfig; /** * The URL of the API to use in the application. * Although a default dataProvider and authProvider are already defined, it is possible that the app * uses the specified apiUrl for further operations (e.g. handling notifications). */ apiUrl: string; /** * The default language to use in the application (default: en). */ defaultLocale: string; /** * If set to true, the application works in development mode. * Development mode is useful for testing and debugging and performs activities that are not * recommended in production (e.g. capturing and forwarding non-localized messages). */ development: boolean; /** * The main logo to display in the sidebar when the menu is expanded laterally. */ logoMain: any; /** * The icon to display in the sidebar when the menu is collapsed laterally. */ logoIcon: any; /** * Configured menu to display in the application. */ menu: MenuItem[]; /** * The name of the application to display in the header. */ name: string; /** * Text to display in the footer. Default: '© Applica Software Guru for'. */ copy: string; /** * Application version to display in the footer. */ version: string; /** * The data provider to use in the application. */ dataProvider: DataProvider; /** * The auth provider to use in the application. */ authProvider: AuthProvider; /** * The i18n provider activation function. * If not specified, the default i18n provider is used. */ i18nProvider?: Promise; /** * Indicates the handler to use for error management. * By default, a PUT /api/ui/error call is made with the error message "error". * You can implement your own handler to manage errors differently. */ errorHandler?: IErrorEventHandler | undefined; /** * Indicates the component to display in case of error. */ error: React.Component; /** * Indicates the name of the REST resource to use for notification management. * The REST resource must be compatible with standard CRUD operations. * @default "entities/notification" * @example * // In this case, notifications will be managed through the "entities/notification" resource * */ notificationAPI: string; /** * Indicates whether notifications should be disabled. * If notifications are enabled, an icon will automatically appear in the top right of the header. * * @example * */ enableNotification: boolean; /** * Indicates whether the registration screen should be disabled. * If enabled, it is necessary to register a page, in the routes, that points to /register * * @example * // Basic page made by Applica * import { RegisterPage } from "@applica-software-guru/react-admin"; * * * */ enableRegistration: boolean; /** * Indicates whether the password recovery screen should be disabled. * If enabled, it is necessary to register a page, in the routes, that points to /recover * * @example * // Basic page made by Applica * import { RecoverPage } from "@applica-software-guru/react-admin"; * * * */ enablePasswordRecover: boolean; /** * The query client instance to use in the application. */ queryClient: QueryClient; /** * Background image to display in login, recover, and register pages. * This image must be a component with absolute positioning. */ background?: React.ReactNode; /** * Indicates whether the theme toggler should be displayed. */ enableThemeToggler: boolean; /** * Indicates whether the locale switcher should be displayed. */ enableLocaleSwitcher: boolean; /** * Indicates which OAuth providers to enable and configurations. */ oauth: { google?: { clientId: string; }; }; }; export { ApplicaAdmin }; export type { ApplicaAdminProps };