Vendor dependencies

This commit is contained in:
2026-08-01 16:11:49 +03:00
parent 7f139a0241
commit 6b5e7f0f8b
29706 changed files with 9575646 additions and 0 deletions
@@ -0,0 +1,11 @@
# GraphQL based Admin Dashboard with Loco and Seaography
In this tutorial, we would develop a GraphQL based admin dashboard with [Seaography](https://github.com/SeaQL/seaography) and Loco.
Read The full tutorial [here](https://www.sea-ql.org/blog/2024-08-08-graphql-admin-dashboard-with-loco-seaography/).
Read our first and second tutorial of the series, [Getting Started with Loco & SeaORM](https://www.sea-ql.org/blog/2024-05-28-getting-started-with-loco-seaorm/), [Adding GraphQL Support to Loco with Seaography](https://www.sea-ql.org/blog/2024-07-01-graphql-support-with-loco-seaography/), if you haven't.
![Screenshot List](Screenshot-List.png)
![Screenshot View](Screenshot-View.png)
Binary file not shown.

After

Width:  |  Height:  |  Size: 821 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 822 KiB

@@ -0,0 +1,21 @@
export default {
"extends": [
"eslint:recommended",
"plugin:react/recommended",
"plugin:react/jsx-runtime",
"plugin:react-hooks/recommended",
"prettier"
],
"parser": "@typescript-eslint/parser",
"plugins": ["@typescript-eslint"],
"env": {
"browser": true,
"es2021": true,
"node": true
},
"settings": {
"react": {
"version": "detect"
}
}
}
@@ -0,0 +1,35 @@
# react-admin
## Installation
Install the application dependencies by running:
```sh
npm install
```
## Development
Start the application in development mode by running:
```sh
npm run dev
```
## Production
Build the application in production mode by running:
```sh
npm run build
```
## 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
@@ -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>react-admin</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>
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,34 @@
{
"private": true,
"scripts": {
"dev": "vite",
"build": "vite build",
"serve": "vite preview",
"type-check": "tsc --noEmit",
"lint": "eslint --fix --ext .js,.jsx,.ts,.tsx ./src",
"format": "prettier --write ./src"
},
"dependencies": {
"axios": "^1.7.2",
"ra-data-json-server": "^5.0.5",
"react": "^18.3.0",
"react-admin": "^5.0.0",
"react-dom": "^18.3.0"
},
"devDependencies": {
"@types/node": "^20.10.7",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@typescript-eslint/eslint-plugin": "^5.60.1",
"@typescript-eslint/parser": "^5.60.1",
"@vitejs/plugin-react": "^4.0.1",
"eslint": "^8.43.0",
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-react": "^7.32.2",
"eslint-plugin-react-hooks": "^4.6.0",
"prettier": "^2.8.8",
"typescript": "^5.1.6",
"vite": "^4.3.9"
},
"name": "react-admin"
}
@@ -0,0 +1 @@
module.exports = {}
Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

@@ -0,0 +1,15 @@
{
"short_name": "react-admin",
"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"
}
@@ -0,0 +1,15 @@
import { Admin } from 'react-admin';
import { Layout } from './Layout';
import { authProvider } from './authProvider';
export const App = () => (
<Admin
layout={Layout}
authProvider={authProvider}
>
</Admin>
);
@@ -0,0 +1,12 @@
import type { ReactNode } from 'react';
import {
Layout as RALayout,
CheckForApplicationUpdate,
} from "react-admin";
export const Layout = ({ children }: { children: ReactNode }) => (
<RALayout>
{children}
<CheckForApplicationUpdate />
</RALayout>
);
@@ -0,0 +1,44 @@
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) {
// eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
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: () => {
return Promise.resolve(undefined);
},
getIdentity: () => {
const persistedUser = localStorage.getItem('user');
const user = persistedUser ? JSON.parse(persistedUser) : null;
return Promise.resolve(user);
},
};
export default authProvider;
@@ -0,0 +1,90 @@
import { DataProvider } from "react-admin";
import axios from 'axios';
const apiUrl = 'http://localhost:3000/api/graphql';
export const dataProvider: DataProvider = {
// Fetch data for post listing
getList: (resource, params) => {
// Paginator status
const { page, perPage } = params.pagination;
// Sorter status
const { field, order } = params.sort;
// POST request to GraphQL endpoint
return axios.post(apiUrl, {
query: `
query {
notes (
orderBy: { ${field}: ${order} },
pagination: { page: { limit: ${perPage}, page: ${page - 1} }}
) {
nodes {
id
title
createdAt
updatedAt
}
paginationInfo {
pages
current
offset
total
}
}
}
`
})
.then((response) => {
// Unwrap the response
const { nodes, paginationInfo } = response.data.data.notes;
// Return the data array and total number of pages
return {
data: nodes,
total: paginationInfo.total,
};
});
},
// Fetch data for a single post
getOne: (resource, params) => {
// POST request to GraphQL endpoint
return axios.post(apiUrl, {
query: `
query {
notes(filters: {id: {eq: ${params.id}}}) {
nodes {
id
title
content
createdAt
updatedAt
}
}
}
`
})
.then((response) => {
// Unwrap the response
const { nodes } = response.data.data.notes;
// Return the one and only data
return {
data: nodes[0],
};
});
},
getMany: (resource, params) => { },
getManyReference: (resource, params) => { },
update: (resource, params) => { },
updateMany: (resource, params) => { },
create: (resource, params) => { },
delete: (resource, params) => { },
deleteMany: (resource, params) => { },
};
@@ -0,0 +1,33 @@
import ReactDOM from 'react-dom/client';
import { Admin, Resource, List, Datagrid, TextField, Show, SimpleShowLayout } from 'react-admin';
import { dataProvider } from './dataProvider';
const PostList = () => (
<List>
<Datagrid bulkActionButtons={false}>
<TextField source="id" />
<TextField source="title" />
<TextField source="createdAt" />
<TextField source="updatedAt" />
</Datagrid>
</List>
);
const PostShow = () => (
<Show>
<SimpleShowLayout>
<TextField source="id" />
<TextField source="title" />
<TextField source="content" />
<TextField source="createdAt" />
<TextField source="updatedAt" />
</SimpleShowLayout>
</Show>
);
ReactDOM.createRoot(document.getElementById('root')!).render(
<Admin dataProvider={dataProvider}>
<Resource name="posts" list={PostList} show={PostShow} />
</Admin>
);
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
/// <reference types="vite/client" />
@@ -0,0 +1,26 @@
{
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
},
"include": [
"src"
]
}
@@ -0,0 +1,14 @@
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
define: {
'process.env': process.env,
},
server: {
host: true,
},
base: './',
});