From 1ad73e9ee4a0eb7d7a8b25faf2b781e8801efb76 Mon Sep 17 00:00:00 2001
From: Lang <7system7@gmail.com>
Date: Tue, 21 Jan 2025 22:05:10 +0100
Subject: [PATCH] add custom layout - & theme provider - & i18provider and so
on
---
public/img/ats-logo-desktop.svg | 26 +++++++
src/App.tsx | 5 +-
src/Layout.tsx | 68 ++++++++++++++--
src/admin-components/admin-dashboard.tsx | 2 +-
src/admin-components/admin-menu.tsx | 16 +++-
.../person/components/array-field.tsx | 18 +++--
.../resources/person/edit.tsx | 7 +-
.../resources/person/list.tsx | 77 ++++++++++---------
.../resources/person/show.tsx | 4 +-
src/admin-core/authProvider.ts | 7 +-
src/admin-core/components/admin-appbar.tsx | 43 +++++++++++
src/admin-core/components/admin-menu-item.tsx | 53 +++++++++++++
.../components/admin-menu-label.tsx | 56 ++++++++++++++
src/admin-core/components/admin-sidebar.tsx | 45 +++++++++++
src/admin-core/components/index.ts | 4 +
src/admin-core/hooks/useQueryEngine.ts | 8 +-
src/admin-core/i18nProvider.ts | 14 ++++
src/admin-core/index.ts | 8 +-
src/admin-core/messages/en-messages.ts | 13 ++++
src/admin-core/messages/index.ts | 1 +
src/admin-core/theme.ts | 16 ++++
tsconfig.json | 12 ++-
22 files changed, 433 insertions(+), 70 deletions(-)
create mode 100644 public/img/ats-logo-desktop.svg
create mode 100644 src/admin-core/components/admin-appbar.tsx
create mode 100644 src/admin-core/components/admin-menu-item.tsx
create mode 100644 src/admin-core/components/admin-menu-label.tsx
create mode 100644 src/admin-core/components/admin-sidebar.tsx
create mode 100644 src/admin-core/components/index.ts
create mode 100644 src/admin-core/i18nProvider.ts
create mode 100644 src/admin-core/messages/en-messages.ts
create mode 100644 src/admin-core/messages/index.ts
create mode 100644 src/admin-core/theme.ts
diff --git a/public/img/ats-logo-desktop.svg b/public/img/ats-logo-desktop.svg
new file mode 100644
index 0000000..625b02c
--- /dev/null
+++ b/public/img/ats-logo-desktop.svg
@@ -0,0 +1,26 @@
+
diff --git a/src/App.tsx b/src/App.tsx
index a3fb757..0e8c7c8 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,7 +1,7 @@
import { Admin, Resource } from "react-admin";
import { Layout } from "./Layout";
import { AdminDashboard, PersonList, PersonShow, PersonEdit } from '@admin';
-import { authProvider, dataProvider } from "@core";
+import { authProvider, dataProvider, i18nProvider, darkTheme, lightTheme } from "@core";
export const App = () => (
(
dashboard={AdminDashboard}
dataProvider={dataProvider}
authProvider={authProvider}
+ i18nProvider={i18nProvider}
+ theme={lightTheme}
+ darkTheme={darkTheme}
>
(
-
- {children}
-
-
-);
+export const Layout = ({ children }: { children: ReactNode }) => {
+ const [open] = useSidebarState();
+
+ return (
+
+ "dark" === theme.palette.mode ? '#313131' : '#fafafb',
+ position: "relative",
+ display: "flex",
+ flexDirection: "column",
+ minHeight: "100vw",
+ zIndex: 1,
+ }}
+ >
+
+
+
+ "dark" === theme.palette.mode ? blueGrey[900] : "white",
+ position: "relative",
+ }}
+ direction="column"
+ >
+
+
+ {open &&
}
+
+
+
+
+
+
+ {children}
+
+
+
+
+
+ );
+};
diff --git a/src/admin-components/admin-dashboard.tsx b/src/admin-components/admin-dashboard.tsx
index 4d4601c..5a0d81d 100644
--- a/src/admin-components/admin-dashboard.tsx
+++ b/src/admin-components/admin-dashboard.tsx
@@ -3,7 +3,7 @@ import { Title } from "react-admin";
export const AdminDashboard = () => {
return (
-
+
diff --git a/src/admin-components/admin-menu.tsx b/src/admin-components/admin-menu.tsx
index d229bff..b15751a 100644
--- a/src/admin-components/admin-menu.tsx
+++ b/src/admin-components/admin-menu.tsx
@@ -1,8 +1,20 @@
import { Menu } from "react-admin";
+import { DashboardTwoTone, Person4TwoTone } from '@mui/icons-material';
+import { AdminMenuItem, AdminMenuLabel } from "@core";
export const AdminMenu = () => (
);
diff --git a/src/admin-components/resources/person/components/array-field.tsx b/src/admin-components/resources/person/components/array-field.tsx
index 7885319..1b3422d 100644
--- a/src/admin-components/resources/person/components/array-field.tsx
+++ b/src/admin-components/resources/person/components/array-field.tsx
@@ -1,12 +1,16 @@
-import React, { FC } from 'react';
+import { FC } from "react";
import { isObject } from "lodash";
-import { useRecordContext } from 'react-admin';
-import { Chip, Stack } from '@mui/material';
+import { useRecordContext } from "react-admin";
+import { Chip, Stack } from "@mui/material";
interface FieldProps {
source: string;
}
+interface People {
+ name: string;
+}
+
export const ArrayField: FC = ({ source }) => {
const record = useRecordContext();
const objects = record?.[source];
@@ -15,10 +19,14 @@ export const ArrayField: FC = ({ source }) => {
return (
- {objects.map((currentObject: string, key: number) => {
+ {objects.map((currentObject: People | string, key: number) => {
if (isObject(currentObject)) {
return (
-
+
);
}
diff --git a/src/admin-components/resources/person/edit.tsx b/src/admin-components/resources/person/edit.tsx
index 2d80f6d..e862b55 100644
--- a/src/admin-components/resources/person/edit.tsx
+++ b/src/admin-components/resources/person/edit.tsx
@@ -1,12 +1,11 @@
-import React from "react";
import {
- BooleanField, BooleanInput,
+ BooleanInput,
DateInput,
Edit,
Labeled,
SimpleForm,
TextInput,
-} from 'react-admin';
+} from "react-admin";
import { Box, Card, CardContent, CardHeader, Stack } from "@mui/material";
export const PersonEdit = () => {
@@ -33,7 +32,7 @@ export const PersonEdit = () => {
-
+
{
@@ -45,41 +46,43 @@ export const PersonList = () => {
}
/>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
);
};
diff --git a/src/admin-components/resources/person/show.tsx b/src/admin-components/resources/person/show.tsx
index 56c6343..06af1c1 100644
--- a/src/admin-components/resources/person/show.tsx
+++ b/src/admin-components/resources/person/show.tsx
@@ -21,7 +21,7 @@ export const PersonShow = () => {
return (
-
+
{
-
+
{
diff --git a/src/admin-core/components/admin-appbar.tsx b/src/admin-core/components/admin-appbar.tsx
new file mode 100644
index 0000000..71286ca
--- /dev/null
+++ b/src/admin-core/components/admin-appbar.tsx
@@ -0,0 +1,43 @@
+/**
+ * This file is part of the SplendidBear Websites' projects.
+ *
+ * Copyright (c) 2023 @ www.splendidbear.org
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+import { Fragment } from "react";
+import {
+ AppBar,
+ LoadingIndicator,
+ TitlePortal,
+ ToggleThemeButton,
+} from "react-admin";
+import { blueGrey, grey } from "@mui/material/colors";
+
+export const AdminAppbar = () => (
+
+ "dark" === theme.palette.mode ? blueGrey[800] : grey[200],
+ position: "relative",
+ minHeight: 50,
+ borderRadius: 0,
+ "& > .MuiToolbar-root": {
+ borderRadius: 0,
+ },
+ boxShadow: "none",
+ color: (theme) =>
+ "dark" === theme.palette.mode ? "white" : blueGrey[600],
+ }}
+ toolbar={
+
+
+
+
+ }
+ >
+
+
+);
diff --git a/src/admin-core/components/admin-menu-item.tsx b/src/admin-core/components/admin-menu-item.tsx
new file mode 100644
index 0000000..1b2b66b
--- /dev/null
+++ b/src/admin-core/components/admin-menu-item.tsx
@@ -0,0 +1,53 @@
+/**
+ * This file is part of the SplendidBear Websites' projects.
+ *
+ * Copyright (c) 2024 @ www.splendidbear.org
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+import { FC, JSX, useMemo } from "react";
+import { isObject } from "lodash";
+import { Tooltip } from "@mui/material";
+import { Menu, useSidebarState, useTranslate } from "react-admin";
+
+interface AdminMenuItemProps {
+ to: string;
+ leftIcon: JSX.Element;
+ primaryText: string;
+ primaryTextTooltip: string;
+}
+
+export const AdminMenuItem: FC = ({
+ to,
+ leftIcon,
+ primaryText,
+ primaryTextTooltip = "n/a",
+ ...rest
+}) => {
+ const t = useTranslate();
+ const [open] = useSidebarState();
+ const isTextObject = useMemo(() => isObject(primaryText), [primaryText]);
+
+ if (!open) {
+ return (
+
+
+
+ );
+ }
+
+ return (
+
+ );
+};
diff --git a/src/admin-core/components/admin-menu-label.tsx b/src/admin-core/components/admin-menu-label.tsx
new file mode 100644
index 0000000..32d358e
--- /dev/null
+++ b/src/admin-core/components/admin-menu-label.tsx
@@ -0,0 +1,56 @@
+/**
+ * This file is part of the SplendidBear Websites' projects.
+ *
+ * Copyright (c) 2025 @ www.splendidbear.org
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+import { FC, Fragment, JSX, useState } from "react";
+import { motion } from "framer-motion";
+import { Collapse, Divider, Stack } from "@mui/material";
+import { ChevronLeft } from "@mui/icons-material";
+import { grey } from "@mui/material/colors";
+import { useSidebarState, useTranslate } from "react-admin";
+
+interface AdminMenuLabelProps {
+ label: string;
+ children: JSX.Element[];
+ id: string;
+ isDefaultOpen: boolean;
+}
+
+export const AdminMenuLabel: FC = ({
+ label,
+ children,
+ isDefaultOpen = false,
+}) => {
+ const t = useTranslate();
+ const [open] = useSidebarState();
+ const [isMenuOpened, setIsMenuOpened] = useState(isDefaultOpen);
+
+ return (
+
+ setIsMenuOpened(!isMenuOpened)}
+ >
+ {open && t(label)}
+
+
+
+
+ {children}
+
+ );
+};
diff --git a/src/admin-core/components/admin-sidebar.tsx b/src/admin-core/components/admin-sidebar.tsx
new file mode 100644
index 0000000..1762bdf
--- /dev/null
+++ b/src/admin-core/components/admin-sidebar.tsx
@@ -0,0 +1,45 @@
+import type { ReactNode } from "react";
+import PropTypes from "prop-types";
+import { Box } from "@mui/material";
+import { useLocale, useSidebarState } from "react-admin";
+import { blueGrey } from "@mui/material/colors";
+
+export const AdminSidebar = ({ children }: { children: ReactNode }) => {
+ const [open] = useSidebarState();
+ /** force redraw on locale change */
+ useLocale();
+
+ return (
+ .MuiPaper-root": {
+ bgcolor: blueGrey[900],
+ width: open ? "250px" : "50px",
+ },
+ "& .MuiMenuItem-root": {
+ padding: open ? "6px 16px" : 0,
+ ...(open
+ ? {}
+ : {
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "center",
+ width: "100%",
+ "&.RaMenuItemLink-active": {
+ borderRadius: 0,
+ },
+ }),
+ },
+ "& .MuiChip-label": {
+ color: "white",
+ },
+ }}
+ >
+ {children}
+
+ );
+};
+
+AdminSidebar.propTypes = {
+ children: PropTypes.node.isRequired,
+};
diff --git a/src/admin-core/components/index.ts b/src/admin-core/components/index.ts
new file mode 100644
index 0000000..99a0a9a
--- /dev/null
+++ b/src/admin-core/components/index.ts
@@ -0,0 +1,4 @@
+export { AdminSidebar } from './admin-sidebar';
+export { AdminAppbar } from './admin-appbar';
+export { AdminMenuItem } from './admin-menu-item';
+export { AdminMenuLabel } from './admin-menu-label';
diff --git a/src/admin-core/hooks/useQueryEngine.ts b/src/admin-core/hooks/useQueryEngine.ts
index f47915f..1b00121 100644
--- a/src/admin-core/hooks/useQueryEngine.ts
+++ b/src/admin-core/hooks/useQueryEngine.ts
@@ -4,10 +4,8 @@ export const useQueryEngine = () => {
"Content-Type": "application/json",
Origin: "http://localhost:3000",
Referer: "http://localhost:3000",
- "Access-Control-Allow-Origin": "http://localhost:3000",
- "Access-Control-Allow-Headers":
+ "Access-Control-Request-Headers":
"Origin, X-Requested-With, Content-Type, Accept, X-XSRF-TOKEN, Authorization, Cookie",
- "Access-Control-Allow-Credentials": true,
};
const response = async (request: Request) => {
@@ -53,7 +51,9 @@ export const useQueryEngine = () => {
...defaultHeaders,
Authorization: `Bearer ${localStorage.getItem("user")}`,
"X-XSRF-TOKEN": localStorage.getItem("user"),
- "Access-Control-Request-Method": options?.method ? options.method : "GET",
+ "Access-Control-Request-Method": options?.method
+ ? options.method
+ : "GET",
...(options?.headers ? { ...options.headers } : {}),
}),
}),
diff --git a/src/admin-core/i18nProvider.ts b/src/admin-core/i18nProvider.ts
new file mode 100644
index 0000000..a10e22d
--- /dev/null
+++ b/src/admin-core/i18nProvider.ts
@@ -0,0 +1,14 @@
+import polyglotI18nProvider from "ra-i18n-polyglot";
+import fr from "ra-language-french";
+import { enMessages } from './messages';
+
+const translations = { en: enMessages, fr };
+
+export const i18nProvider = polyglotI18nProvider(
+ (locale: string) => translations[locale],
+ "en", // default locale
+ [
+ { locale: "en", name: "English" },
+ { locale: "fr", name: "Français" },
+ ],
+);
diff --git a/src/admin-core/index.ts b/src/admin-core/index.ts
index bbdbaa9..41888cd 100644
--- a/src/admin-core/index.ts
+++ b/src/admin-core/index.ts
@@ -1,4 +1,8 @@
export { dataProviderExtension } from './data-provider-extension';
-export { dataProvider } from './dataProvider.ts';
-export { authProvider } from './authProvider.ts';
+export { dataProvider } from './dataProvider';
+export { authProvider } from './authProvider';
+export { lightTheme, darkTheme } from './theme';
+export { i18nProvider } from './i18nProvider';
export * from './hooks';
+export * from './components';
+export * from './messages';
diff --git a/src/admin-core/messages/en-messages.ts b/src/admin-core/messages/en-messages.ts
new file mode 100644
index 0000000..52604d6
--- /dev/null
+++ b/src/admin-core/messages/en-messages.ts
@@ -0,0 +1,13 @@
+import en from "ra-language-english";
+import { deepmerge } from "@mui/utils";
+
+export const enMessages = deepmerge(en, {
+ ra: {
+ menu: {
+ main: {
+ userManagement: "User management",
+ },
+ people: "Users",
+ },
+ },
+});
diff --git a/src/admin-core/messages/index.ts b/src/admin-core/messages/index.ts
new file mode 100644
index 0000000..b1baf63
--- /dev/null
+++ b/src/admin-core/messages/index.ts
@@ -0,0 +1 @@
+export { enMessages } from './en-messages';
diff --git a/src/admin-core/theme.ts b/src/admin-core/theme.ts
new file mode 100644
index 0000000..4cfbc95
--- /dev/null
+++ b/src/admin-core/theme.ts
@@ -0,0 +1,16 @@
+import { defaultTheme, RaThemeOptions } from "react-admin";
+import { deepmerge } from "@mui/utils";
+
+export const lightTheme: RaThemeOptions = deepmerge(defaultTheme, {
+ components: {
+ '& .Apex-Sidebar': {
+
+ }
+ },
+});
+
+export const darkTheme: RaThemeOptions = deepmerge(lightTheme, {
+ palette: {
+ mode: "dark",
+ },
+});
diff --git a/tsconfig.json b/tsconfig.json
index ea9d0cd..f54711e 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -7,5 +7,15 @@
{
"path": "./tsconfig.node.json"
}
- ]
+ ],
+ "compilerOptions": {
+ "paths": {
+ "@admin*": [
+ "./src/admin-components/*"
+ ],
+ "@core*": [
+ "./src/admin-core/*"
+ ],
+ }
+ }
}