Skip to content

Commit

Permalink
Add support for admin configuration through props instead of elements
Browse files Browse the repository at this point in the history
  • Loading branch information
djhi committed May 25, 2023
1 parent 5dabdd5 commit f5b15aa
Show file tree
Hide file tree
Showing 25 changed files with 925 additions and 43 deletions.
50 changes: 50 additions & 0 deletions examples/with-config/README.md
@@ -0,0 +1,50 @@
# with-config

## Installation

Install the application dependencies by running:

```sh
npm install
# or
yarn install
```

## Development

Start the application in development mode by running:

```sh
npm run dev
# or
yarn dev
```

## Production

Build the application in production mode by running:

```sh
npm run build
# or
yarn build
```

## DataProvider

The included data provider use [FakeREST](https://github.com/marmelab/fakerest) to simulate a backend.
You'll find a `data.json` file in the `src` directory that includes some fake data for testing purposes.

It includes two resources, posts and comments.
Posts have the following properties: `id`, `title` and `content`.
Comments have the following properties: `id`, `post_id` and `content`.

## Authentication

The included auth provider should only be used for development and test purposes.
You'll find a `users.json` file in the `src` directory that includes the users you can use.

You can sign in to the application with the following usernames and password:
- janedoe / password
- johndoe / password

125 changes: 125 additions & 0 deletions examples/with-config/index.html
@@ -0,0 +1,125 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="minimum-scale=1, initial-scale=1, width=device-width, shrink-to-fit=no"
/>
<meta name="theme-color" content="#000000" />
<link rel="manifest" href="./manifest.json" />
<link rel="shortcut icon" href="./favicon.ico" />
<title>with-config</title>
<style>
body {
margin: 0;
padding: 0;
font-family: sans-serif;
}

.loader-container {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: #fafafa;
}

/* CSS Spinner from https://projects.lukehaas.me/css-loaders/ */

.loader,
.loader:before,
.loader:after {
border-radius: 50%;
}

.loader {
color: #283593;
font-size: 11px;
text-indent: -99999em;
margin: 55px auto;
position: relative;
width: 10em;
height: 10em;
box-shadow: inset 0 0 0 1em;
-webkit-transform: translateZ(0);
-ms-transform: translateZ(0);
transform: translateZ(0);
}

.loader:before,
.loader:after {
position: absolute;
content: '';
}

.loader:before {
width: 5.2em;
height: 10.2em;
background: #fafafa;
border-radius: 10.2em 0 0 10.2em;
top: -0.1em;
left: -0.1em;
-webkit-transform-origin: 5.2em 5.1em;
transform-origin: 5.2em 5.1em;
-webkit-animation: load2 2s infinite ease 1.5s;
animation: load2 2s infinite ease 1.5s;
}

.loader:after {
width: 5.2em;
height: 10.2em;
background: #fafafa;
border-radius: 0 10.2em 10.2em 0;
top: -0.1em;
left: 5.1em;
-webkit-transform-origin: 0px 5.1em;
transform-origin: 0px 5.1em;
-webkit-animation: load2 2s infinite ease;
animation: load2 2s infinite ease;
}

@-webkit-keyframes load2 {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}

@keyframes load2 {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
</style>
<link rel="preconnect" href="https://fonts.gstatic.com" />
<link
href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap"
rel="stylesheet"
/>
</head>

<body>
<noscript> You need to enable JavaScript to run this app. </noscript>
<div id="root">
<div class="loader-container">
<div class="loader">Loading...</div>
</div>
</div>
</body>
<script type="module" src="/src/index.tsx"></script>
</html>
24 changes: 24 additions & 0 deletions examples/with-config/package.json
@@ -0,0 +1,24 @@
{
"name": "with-config",
"private": true,
"scripts": {
"dev": "vite",
"build": "vite build",
"serve": "vite preview",
"type-check": "tsc --noEmit"
},
"dependencies": {
"ra-data-fakerest": "^4.9.2",
"react": "^18.2.0",
"react-admin": "^4.9.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@types/node": "^18.16.1",
"@types/react": "^18.0.22",
"@types/react-dom": "^18.0.7",
"@vitejs/plugin-react": "^2.2.0",
"typescript": "^4.6.4",
"vite": "^3.2.0"
}
}
Binary file added examples/with-config/public/favicon.ico
Binary file not shown.
15 changes: 15 additions & 0 deletions examples/with-config/public/manifest.json
@@ -0,0 +1,15 @@
{
"short_name": "with-config",
"name": "{{name}}",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
}
],
"start_url": "./index.html",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}
58 changes: 58 additions & 0 deletions examples/with-config/src/App.tsx
@@ -0,0 +1,58 @@
import {
Admin,
ListGuesser,
EditGuesser,
ShowGuesser,
CardContentInner,
Button,
} from 'react-admin';
import { Link } from 'react-router-dom';
import { dataProvider } from './dataProvider';
import { authProvider } from './authProvider';

export const App = () => (
<Admin
dataProvider={dataProvider}
authProvider={authProvider}
resources={(permissions: any) => ({
posts: {
edit: EditGuesser,
list: ListGuesser,
routes: [
{
path: 'all/*',
element: <ListGuesser />,
},
{
path: '*',
element: (
<CardContentInner>
Posts Dashboard
<br />
<Button
component={Link}
to="all"
label="All posts"
/>
</CardContentInner>
),
},
],
},
comments: {
list: ListGuesser,
edit: EditGuesser,
show: ShowGuesser,
},
})}
customRoutes={(permissions: any) => [
{ path: 'custom', element: <div>Custom route</div> },
]}
customRoutesWithoutLayout={[
{
path: 'custom-no-layout',
element: <div>Custom route no layout</div>,
},
]}
/>
);
8 changes: 8 additions & 0 deletions examples/with-config/src/README.md
@@ -0,0 +1,8 @@
## Authentication

The included auth provider should only be used for development and test purposes.
You'll find a `users.json` file in the `src` directory that includes the users you can use.

You can sign in to the application with the following usernames and password:
- janedoe / password
- johndoe / password
41 changes: 41 additions & 0 deletions examples/with-config/src/authProvider.ts
@@ -0,0 +1,41 @@
import { AuthProvider, HttpError } from 'react-admin';
import data from './users.json';

/**
* This authProvider is only for test purposes. Don't use it in production.
*/
export const authProvider: AuthProvider = {
login: ({ username, password }) => {
const user = data.users.find(
u => u.username === username && u.password === password
);

if (user) {
let { password, ...userToPersist } = user;
localStorage.setItem('user', JSON.stringify(userToPersist));
return Promise.resolve();
}

return Promise.reject(
new HttpError('Unauthorized', 401, {
message: 'Invalid username or password',
})
);
},
logout: () => {
localStorage.removeItem('user');
return Promise.resolve();
},
checkError: () => Promise.resolve(),
checkAuth: () =>
localStorage.getItem('user') ? Promise.resolve() : Promise.reject(),
getPermissions: () => Promise.resolve(['admin']),
getIdentity: () => {
const persistedUser = localStorage.getItem('user');
const user = persistedUser ? JSON.parse(persistedUser) : null;

return Promise.resolve(user);
},
};

export default authProvider;

0 comments on commit f5b15aa

Please sign in to comment.