Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for admin configuration through props instead of elements #8944

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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;