From 012db596e801f4a0e4d11a7a1a16bcda0fb6b889 Mon Sep 17 00:00:00 2001
From: Lang <7system7@gmail.com>
Date: Mon, 13 Jan 2025 21:51:17 +0100
Subject: [PATCH] add list and show to the Person entity
---
src/App.tsx | 19 +--
src/admin-components/admin-dashboard.tsx | 24 ++--
src/admin-components/admin-menu.tsx | 1 +
src/admin-components/index.ts | 1 +
src/admin-components/resources/index.ts | 1 +
.../person/components/array-field.tsx | 31 +++++
.../resources/person/components/index.ts | 1 +
.../resources/person/index.ts | 3 +
.../resources/person/list.tsx | 103 ++++++++++++++++
.../resources/person/show.tsx | 114 ++++++++++++++++++
src/{ => admin-core}/authProvider.ts | 7 +-
src/admin-core/data-provider-extension.ts | 15 +--
src/admin-core/dataProvider.ts | 31 +++++
src/admin-core/hooks/useQueryEngine.ts | 72 ++++++-----
src/admin-core/index.ts | 2 +
src/dataProvider.ts | 7 --
16 files changed, 357 insertions(+), 75 deletions(-)
create mode 100644 src/admin-components/resources/index.ts
create mode 100644 src/admin-components/resources/person/components/array-field.tsx
create mode 100644 src/admin-components/resources/person/components/index.ts
create mode 100644 src/admin-components/resources/person/index.ts
create mode 100644 src/admin-components/resources/person/list.tsx
create mode 100644 src/admin-components/resources/person/show.tsx
rename src/{ => admin-core}/authProvider.ts (89%)
create mode 100644 src/admin-core/dataProvider.ts
delete mode 100644 src/dataProvider.ts
diff --git a/src/App.tsx b/src/App.tsx
index cfb5a44..10019fe 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,14 +1,7 @@
-import {
- Admin,
- EditGuesser,
- ListGuesser,
- Resource,
- ShowGuesser,
-} from "react-admin";
+import { Admin, Resource } from "react-admin";
import { Layout } from "./Layout";
-import { dataProvider } from "./dataProvider";
-import { authProvider } from "./authProvider";
-import { AdminDashboard } from '@admin';
+import { AdminDashboard, PersonList, PersonShow } from "@admin";
+import { authProvider, dataProvider } from "@core";
export const App = () => (
(
>
);
diff --git a/src/admin-components/admin-dashboard.tsx b/src/admin-components/admin-dashboard.tsx
index 13f98c0..4d4601c 100644
--- a/src/admin-components/admin-dashboard.tsx
+++ b/src/admin-components/admin-dashboard.tsx
@@ -1,20 +1,18 @@
-import { Card, CardContent } from "@mui/material";
-import { Title, useDataProvider } from "react-admin";
-import { useQuery } from "@tanstack/react-query";
+import { Card, CardContent, Typography } from "@mui/material";
+import { Title } from "react-admin";
export const AdminDashboard = () => {
- const dataProvider = useDataProvider();
- const { data } = useQuery({
- queryKey: ["dashboard"],
- queryFn: () => dataProvider.person(),
- });
-
- console.log(data);
-
return (
-
+
- Lorem ipsum sic dolor amet...
+
+
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eveniet
+ impedit, temporibus? Amet dolor fuga hic libero molestiae nemo
+ perferendis quas quis repellendus voluptas? Aliquid doloremque, est
+ labore odit optio similique.
+
+
);
};
diff --git a/src/admin-components/admin-menu.tsx b/src/admin-components/admin-menu.tsx
index c5d91d0..d229bff 100644
--- a/src/admin-components/admin-menu.tsx
+++ b/src/admin-components/admin-menu.tsx
@@ -3,5 +3,6 @@ import { Menu } from "react-admin";
export const AdminMenu = () => (
);
diff --git a/src/admin-components/index.ts b/src/admin-components/index.ts
index 21bcece..fd665ba 100644
--- a/src/admin-components/index.ts
+++ b/src/admin-components/index.ts
@@ -1,2 +1,3 @@
export { AdminMenu } from './admin-menu';
export { AdminDashboard } from './admin-dashboard';
+export * from './resources';
diff --git a/src/admin-components/resources/index.ts b/src/admin-components/resources/index.ts
new file mode 100644
index 0000000..6e3bd67
--- /dev/null
+++ b/src/admin-components/resources/index.ts
@@ -0,0 +1 @@
+export * from './person';
diff --git a/src/admin-components/resources/person/components/array-field.tsx b/src/admin-components/resources/person/components/array-field.tsx
new file mode 100644
index 0000000..7885319
--- /dev/null
+++ b/src/admin-components/resources/person/components/array-field.tsx
@@ -0,0 +1,31 @@
+import React, { FC } from 'react';
+import { isObject } from "lodash";
+import { useRecordContext } from 'react-admin';
+import { Chip, Stack } from '@mui/material';
+
+interface FieldProps {
+ source: string;
+}
+
+export const ArrayField: FC = ({ source }) => {
+ const record = useRecordContext();
+ const objects = record?.[source];
+
+ if (!objects) return "";
+
+ return (
+
+ {objects.map((currentObject: string, key: number) => {
+ if (isObject(currentObject)) {
+ return (
+
+ );
+ }
+
+ return (
+
+ );
+ })}
+
+ );
+};
diff --git a/src/admin-components/resources/person/components/index.ts b/src/admin-components/resources/person/components/index.ts
new file mode 100644
index 0000000..214238c
--- /dev/null
+++ b/src/admin-components/resources/person/components/index.ts
@@ -0,0 +1 @@
+export { ArrayField } from "./array-field.tsx";
diff --git a/src/admin-components/resources/person/index.ts b/src/admin-components/resources/person/index.ts
new file mode 100644
index 0000000..747170b
--- /dev/null
+++ b/src/admin-components/resources/person/index.ts
@@ -0,0 +1,3 @@
+export { PersonList } from './list.tsx';
+export { PersonShow } from './show.tsx';
+export * from './components';
diff --git a/src/admin-components/resources/person/list.tsx b/src/admin-components/resources/person/list.tsx
new file mode 100644
index 0000000..5f76792
--- /dev/null
+++ b/src/admin-components/resources/person/list.tsx
@@ -0,0 +1,103 @@
+import React, { Fragment, useEffect, useState } from "react";
+import {
+ BooleanField,
+ Datagrid,
+ isEmpty,
+ ListContextProvider,
+ ListToolbar,
+ Pagination,
+ TextField,
+ Title,
+ TopToolbar,
+ useDataProvider,
+ WrapperField,
+} from "react-admin";
+import { useQuery } from "@tanstack/react-query";
+import { ArrayField } from "./components";
+import { TextField as MuiTextField } from "@mui/material";
+
+export const PersonList = () => {
+ const [page, setPage] = useState(1);
+ const [perPage, setPerPage] = useState(25);
+ const [firstName, setFirstName] = useState("");
+ const dataProvider = useDataProvider();
+ const { data, isPending, refetch } = useQuery({
+ queryKey: ["personList", page, perPage, firstName],
+ queryFn: () => {
+ const httpParams = new URLSearchParams({
+ page: `${page - 1}`,
+ size: `${perPage}`,
+ ...(isEmpty(firstName)
+ ? {}
+ : { filters: `firstName::like_ignore_case::${firstName}` }),
+ });
+
+ return dataProvider.personList(httpParams);
+ },
+ });
+
+ useEffect(() => {
+ (async () => {
+ await refetch();
+ })();
+ }, [page, perPage]);
+
+ return (
+
+
+
+
+
+ }
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+const FilterName = ({ setFirstName }) => {
+ return (
+ ) => {
+ setFirstName(event.target.value);
+ }}
+ />
+ );
+};
diff --git a/src/admin-components/resources/person/show.tsx b/src/admin-components/resources/person/show.tsx
new file mode 100644
index 0000000..56c6343
--- /dev/null
+++ b/src/admin-components/resources/person/show.tsx
@@ -0,0 +1,114 @@
+import React from "react";
+import {
+ BooleanField,
+ DateField,
+ Labeled,
+ Show,
+ SimpleShowLayout,
+ TextField,
+} from "react-admin";
+import {
+ Box,
+ Card,
+ CardContent,
+ CardHeader,
+ Stack,
+ Typography,
+} from "@mui/material";
+import { ArrayField } from "@admin";
+
+export const PersonShow = () => {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Company
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
diff --git a/src/authProvider.ts b/src/admin-core/authProvider.ts
similarity index 89%
rename from src/authProvider.ts
rename to src/admin-core/authProvider.ts
index 6988dce..cbaad34 100644
--- a/src/authProvider.ts
+++ b/src/admin-core/authProvider.ts
@@ -10,6 +10,7 @@ export const authProvider: AuthProvider = {
response = await fetch(
new Request("http://localhost:8080/atsp-idp/token", {
method: "POST",
+ credentials: "include",
body: new URLSearchParams({
grant_type: "authorization_code",
code: "code",
@@ -36,9 +37,9 @@ export const authProvider: AuthProvider = {
);
}
- const { refresh_token } = await response.json();
- localStorage.setItem("token", refresh_token);
- localStorage.setItem("user", refresh_token);
+ const { access_token } = await response.json();
+ localStorage.setItem("user", access_token);
+ localStorage.setItem("token", access_token);
return Promise.resolve();
},
diff --git a/src/admin-core/data-provider-extension.ts b/src/admin-core/data-provider-extension.ts
index 7e2209c..9b4fe62 100644
--- a/src/admin-core/data-provider-extension.ts
+++ b/src/admin-core/data-provider-extension.ts
@@ -1,19 +1,10 @@
-import { useQueryEngine } from "@core";
+import { useQueryEngine } from './hooks';
export const dataProviderExtension = () => {
const { fetchCommon } = useQueryEngine();
+ const url = import.meta.env.VITE_SIMPLE_REST_URL;
return {
- person: () =>
- fetchCommon(
- "http://localhost:8081/core/api/admin/person",
- {
- headers: new Headers({
- Accept: "application/json",
- 'X-XSRF-TOKEN': 'c3aKjTfLsPSdmiMtTaj933RbsQMR6IWmf9C5ZImMh9pCmDGkEETougKpiZew-UcZe4XJ5xE4nDpwirWLR-SOXbm94-Im-QLB',
- 'Cookie': 'LAST_LOGIN_LOCATION=http://localhost:3000; SESSION=652f7c23-fe94-4727-a980-59052e75aab2; XSRF-TOKEN=c2b75b9c-cd46-48ec-9ab0-847901d8da3e',
- }),
- },
- ),
+ personList: (params: URLSearchParams) => fetchCommon(`${url}/person?${params}`),
};
};
diff --git a/src/admin-core/dataProvider.ts b/src/admin-core/dataProvider.ts
new file mode 100644
index 0000000..e89abe4
--- /dev/null
+++ b/src/admin-core/dataProvider.ts
@@ -0,0 +1,31 @@
+import { fetchUtils, withLifecycleCallbacks } from 'react-admin';
+import simpleRestProvider from "ra-data-simple-rest";
+import { dataProviderExtension } from "@core";
+
+const fetchJson = (url, options = {}) => {
+ if (!options.headers) {
+ options.headers = new Headers({ Accept: "application/json" });
+ }
+ options.credentials = "include";
+ options.headers.set(
+ "Authorization",
+ `Bearer ${localStorage.getItem("user")}`,
+ );
+ options.headers.set("X-XSRF-TOKEN", localStorage.getItem("user"));
+ return fetchUtils.fetchJson(url, options);
+};
+
+export const dataProvider = withLifecycleCallbacks(
+ {
+ ...simpleRestProvider(import.meta.env.VITE_SIMPLE_REST_URL, fetchJson),
+ ...dataProviderExtension(),
+ },
+ [
+ {
+ resource: "person",
+ afterRead: async (data: object) => {
+ return data.original;
+ },
+ },
+ ],
+);
diff --git a/src/admin-core/hooks/useQueryEngine.ts b/src/admin-core/hooks/useQueryEngine.ts
index c1d1197..752b6c8 100644
--- a/src/admin-core/hooks/useQueryEngine.ts
+++ b/src/admin-core/hooks/useQueryEngine.ts
@@ -1,16 +1,16 @@
export const useQueryEngine = () => {
const defaultHeaders = {
- Accept: 'application/ld+json',
- 'Content-Type': 'application/ld+json',
+ Accept: "application/json",
+ "Content-Type": "application/json",
};
- const response = async (request) => {
+ const response = async (request: Request) => {
let response;
try {
response = await fetch(request);
} catch (e) {
- throw new Error('Network error');
+ throw new Error("Network error");
}
if (200 > response?.status || 300 <= response?.status) {
@@ -20,58 +20,76 @@ export const useQueryEngine = () => {
return response.json();
};
- return ({
+ const decodeJwt = (token: string) => {
+ try {
+ return JSON.parse(window.atob(token.split(".")[1]));
+ } catch (e) {
+ return null;
+ }
+ };
+
+ return {
defaultHeaders,
- fetchCommon: async (url, options = {}) => {
+ fetchCommon: async (url: string, options: object = {}) => {
+ const token = decodeJwt(localStorage.getItem("user"));
+
+ document.cookie = `XSRF-TOKEN=${token.sub}; SESSION=${token.jti}`;
+
return await response(
new Request(url, {
- ...(options?.method ? { method: options.method } : { method: 'GET' }),
+ credentials: "include",
+ ...(options?.method ? { method: options.method } : { method: "GET" }),
...(options.replaceHeaders
- ? { headers: options.replaceHeaders }
+ ? { headers: new Headers(options.replaceHeaders) }
: {
- headers: {
- ...defaultHeaders,
- Authorization: `Bearer ${localStorage.getItem('user')}`,
- ...(options?.headers ? { ...options.headers } : {}),
- },
- }),
+ headers: new Headers({
+ ...defaultHeaders,
+ Authorization: `Bearer ${localStorage.getItem("user")}`,
+ "X-XSRF-TOKEN": localStorage.getItem("user"),
+ ...(options?.headers ? { ...options.headers } : {}),
+ }),
+ }),
...(options?.body ? { body: options.body } : {}),
}),
);
},
- fetchMultipart: async (url, options) => {
+ fetchMultipart: async (url: string, options: object = {}) => {
return await response(
new Request(url, {
- method: 'POST',
+ method: "POST",
headers: {
- Accept: 'application/ld+json',
+ Accept: "application/json",
/**
* DO NOT SPECIFY THIS - Because the boundary data in it
* @see https://stackoverflow.com/a/71392989/3111514
*/
// 'Content-Type': 'multipart/form-data',
- Authorization: `Bearer ${localStorage.getItem('user')}`,
+ Authorization: `Bearer ${localStorage.getItem("user")}`,
},
...options,
}),
);
},
- fetchPlain: async (url, options = {}, withAuth = false) => {
+ fetchPlain: async (url: string, options: object = {}, withAuth = false) => {
return await response(
new Request(url, {
- ...(options?.method ? { method: options.method } : { method: 'GET' }),
+ ...(options?.method ? { method: options.method } : { method: "GET" }),
...(options.replaceHeaders
? { headers: options.replaceHeaders }
: {
- headers: {
- 'Content-Type': 'application/json',
- ...(options?.headers ? { headers: options.headers } : {}),
- ...(withAuth ? { Authorization: `Bearer ${localStorage.getItem('user')}` } : {}),
- },
- }),
+ headers: {
+ "Content-Type": "application/json",
+ ...(options?.headers ? { headers: options.headers } : {}),
+ ...(withAuth
+ ? {
+ Authorization: `Bearer ${localStorage.getItem("user")}`,
+ }
+ : {}),
+ },
+ }),
...(options?.body ? { body: options.body } : {}),
}),
);
},
- });
+ };
};
diff --git a/src/admin-core/index.ts b/src/admin-core/index.ts
index 64c0369..bbdbaa9 100644
--- a/src/admin-core/index.ts
+++ b/src/admin-core/index.ts
@@ -1,2 +1,4 @@
export { dataProviderExtension } from './data-provider-extension';
+export { dataProvider } from './dataProvider.ts';
+export { authProvider } from './authProvider.ts';
export * from './hooks';
diff --git a/src/dataProvider.ts b/src/dataProvider.ts
deleted file mode 100644
index 122178f..0000000
--- a/src/dataProvider.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import simpleRestProvider from "ra-data-simple-rest";
-import { dataProviderExtension } from "@core";
-
-export const dataProvider = {
- ...simpleRestProvider(import.meta.env.VITE_SIMPLE_REST_URL),
- ...dataProviderExtension(),
-};