From 015aaef7297997048a2909e377b1ffd4f1e83af0 Mon Sep 17 00:00:00 2001 From: Arthur de Moulins Date: Wed, 13 Dec 2023 20:52:17 +0100 Subject: [PATCH] WIP --- dashboard/client/.prettierrc.js | 2 +- dashboard/client/config-compiler.js | 37 +++++++++++- dashboard/client/index.tpl.html | 40 +++++++------ dashboard/client/package.json | 6 +- dashboard/client/src/ClientApp.tsx | 32 ++++++++++ dashboard/client/src/Root.tsx | 61 ++++++++++++++++++- dashboard/client/src/Service.tsx | 91 +++++++++++++++++++++++++++++ dashboard/client/src/config.ts | 26 ++++++++- dashboard/client/src/index.tsx | 62 +++++++++++++++++++- pnpm-lock.yaml | 17 ++++++ 10 files changed, 349 insertions(+), 25 deletions(-) create mode 100644 dashboard/client/src/ClientApp.tsx create mode 100644 dashboard/client/src/Service.tsx diff --git a/dashboard/client/.prettierrc.js b/dashboard/client/.prettierrc.js index 1087cf3a3..13ed8bbea 100644 --- a/dashboard/client/.prettierrc.js +++ b/dashboard/client/.prettierrc.js @@ -1,3 +1,3 @@ module.exports = { - ...require('../.prettierrc'), + ...require('../../.prettierrc'), }; diff --git a/dashboard/client/config-compiler.js b/dashboard/client/config-compiler.js index 4e1f3fa5b..a1e39b57b 100644 --- a/dashboard/client/config-compiler.js +++ b/dashboard/client/config-compiler.js @@ -1,6 +1,41 @@ (function (config, env) { + const whiteList = [ + 'DATABOX_API_URL', + 'DATABOX_CLIENT_URL', + 'DEV_MODE', + 'DISPLAY_SERVICES_MENU', + 'DOCKER_TAG', + 'ELASTICHQ_URL', + 'EXPOSE_API_URL', + 'EXPOSE_CLIENT_URL', + 'KEYCLOAK_URL', + 'MAILHOG_URL', + 'MATOMO_URL', + 'NOTIFY_API_URL', + 'PGADMIN_URL', + 'PHPMYADMIN_URL', + 'RABBITMQ_CONSOLE_URL', + 'REPORT_API_URL', + 'SAML_URL', + 'SAML2_URL', + 'STACK_NAME', + 'TRAEFIK_CONSOLE_URL', + 'UPLOADER_API_URL', + 'UPLOADER_CLIENT_URL', + 'ZIPPY_URL', + ]; + + const e = {}; + + Object.entries(env).forEach(([key, value]) => { + if (whiteList.includes(key)) { + e[key] = value; + } + }) + + return { locales: config.available_locales, - env, + env: e, }; }); diff --git a/dashboard/client/index.tpl.html b/dashboard/client/index.tpl.html index bada4d06f..f28d40056 100644 --- a/dashboard/client/index.tpl.html +++ b/dashboard/client/index.tpl.html @@ -1,10 +1,10 @@ - - + + Phrasea Dashboard __TPL_CONFIG__ - - - -
- - - + You can add webfonts, meta tags, or analytics to this file. + The build step will place the bundled scripts into the tag. + + To begin the development, run `npm start` or `yarn start`. + To create a production bundle, use `npm run build` or `yarn build`. +--> + diff --git a/dashboard/client/package.json b/dashboard/client/package.json index c02d642c6..80dde20b4 100644 --- a/dashboard/client/package.json +++ b/dashboard/client/package.json @@ -12,10 +12,12 @@ }, "dependencies": { "@alchemy/theme-editor": "workspace:*", + "@mui/material": "^5.15.0", + "@mui/icons-material": "^5.15.0", "react": "^18.2.0", "react-dom": "^18.2.0", - "vite-plugin-svgr": "^4.2.0", - "@mui/material": "^5.15.0" + "react-google-font-loader": "^1.1.0", + "vite-plugin-svgr": "^4.2.0" }, "devDependencies": { "@types/node": "^18.8.5", diff --git a/dashboard/client/src/ClientApp.tsx b/dashboard/client/src/ClientApp.tsx new file mode 100644 index 000000000..0ce2f71ad --- /dev/null +++ b/dashboard/client/src/ClientApp.tsx @@ -0,0 +1,32 @@ +import Service, {ServiceBaseProps} from "./Service.tsx"; +import AdminPanelSettingsIcon from '@mui/icons-material/AdminPanelSettings'; +import ApiIcon from '@mui/icons-material/Api'; + +type Props = { + apiUrl: string; + clientUrl: string; +} & ServiceBaseProps; + +export default function ClientApp({ + apiUrl, + clientUrl, + ...props +}: Props) { + + return , + href: `${apiUrl}/admin`, + title: `Admin of ${props.title}` + }, + { + icon: , + href: apiUrl, + title: `API documentation of ${props.title}` + }, + ]} + {...props} + /> +} diff --git a/dashboard/client/src/Root.tsx b/dashboard/client/src/Root.tsx index e75f2fa97..9a510be7f 100644 --- a/dashboard/client/src/Root.tsx +++ b/dashboard/client/src/Root.tsx @@ -1,6 +1,65 @@ +import {Container, Grid} from "@mui/material"; +import Service from "./Service"; +import ClientApp from "./ClientApp.tsx"; +import config from "./config.ts"; + type Props = {}; export default function Root({}: Props) { + const { + DATABOX_API_URL, + EXPOSE_API_URL, + UPLOADER_API_URL, + NOTIFY_API_URL, + KEYCLOAK_URL, + DATABOX_CLIENT_URL, + EXPOSE_CLIENT_URL, + UPLOADER_CLIENT_URL, + } = config.env; + + console.log('config.env', config.env); - return <>Dashboard! + return + + + {DATABOX_API_URL && } + {EXPOSE_API_URL && } + {UPLOADER_API_URL && } + {NOTIFY_API_URL && } + + } diff --git a/dashboard/client/src/Service.tsx b/dashboard/client/src/Service.tsx new file mode 100644 index 000000000..8721df822 --- /dev/null +++ b/dashboard/client/src/Service.tsx @@ -0,0 +1,91 @@ +import {Button, Card, CardActions, CardContent, CardMedia, Grid, IconButton, Typography,} from '@mui/material'; +import {JSX, PropsWithChildren, ReactNode} from "react"; + +type BaseProps = { + title: string; + mainUrl?: string; + description?: ReactNode; + logo?: string; +}; + +type AppLink = { + icon: ReactNode; + title: string; + href: string; +} + +type Props = { + links?: AppLink[]; +} & BaseProps; + +export type {BaseProps as ServiceBaseProps}; + +export default function Service({ + title, + logo, + description, + mainUrl, + links = [], +}: Props) { + return + + + ({ + height: 140, + backgroundSize: 'contain', + backgroundColor: theme.palette.background.default, + })} + image={logo} + title="green iguana" + /> + + + + + {title} + + + {description && + {description} + } + + + {links.map(({href, icon, title}, i) => + {icon} + )} + + + +} + +function Link({href, children}: PropsWithChildren<{ + href: string | undefined; +}>) { + if (href) { + return + {children} + + } + + return children as JSX.Element; +} diff --git a/dashboard/client/src/config.ts b/dashboard/client/src/config.ts index de65dee48..8be4f8b82 100644 --- a/dashboard/client/src/config.ts +++ b/dashboard/client/src/config.ts @@ -3,7 +3,31 @@ declare global { interface Window { config: { locales: string[]; - env: Record; + env: { + DATABOX_API_URL: string; + DATABOX_CLIENT_URL: string; + DEV_MODE: string; + DISPLAY_SERVICES_MENU: string; + DOCKER_TAG: string; + ELASTICHQ_URL: string; + EXPOSE_API_URL: string; + EXPOSE_CLIENT_URL: string; + KEYCLOAK_URL: string; + MAILHOG_URL: string; + MATOMO_URL: string; + NOTIFY_API_URL: string; + PGADMIN_URL: string; + PHPMYADMIN_URL: string; + RABBITMQ_CONSOLE_URL: string; + REPORT_API_URL: string; + SAML_URL: string; + SAML2_URL: string; + STACK_NAME: string; + TRAEFIK_CONSOLE_URL: string; + UPLOADER_API_URL: string; + UPLOADER_CLIENT_URL: string; + ZIPPY_URL: string; + }; }; } } diff --git a/dashboard/client/src/index.tsx b/dashboard/client/src/index.tsx index e7cc266e3..512bd8058 100644 --- a/dashboard/client/src/index.tsx +++ b/dashboard/client/src/index.tsx @@ -1,9 +1,69 @@ import ReactDOM from 'react-dom/client'; import Root from './Root.tsx'; import React from 'react'; +import {CssBaseline, GlobalStyles, ThemeOptions} from "@mui/material"; +import {ThemeEditorProvider} from '@alchemy/theme-editor'; + +const theme: ThemeOptions = { + typography: { + fontFamily: '\'Montserrat\', sans-serif', + h1: { + fontSize: 24, + fontWeight: 600, + }, + h2: { + fontSize: 19, + fontWeight: 600, + }, + h5: { + fontSize: 19, + }, + }, + palette: { + primary: { + main: '#003249', + contrastText: '#e7eaea', + }, + secondary: { + main: '#007EA7', + }, + common: { + white: '#e7eaea', + }, + background: { + default: '#85dbff', + } + }, +} + +const scrollbarWidth = 3; ReactDOM.createRoot(document.getElementById('root')!).render( - + + + ({ + '*': { + '*::-webkit-scrollbar': { + width: scrollbarWidth, + }, + '*::-webkit-scrollbar-track': { + borderRadius: 10, + }, + '*::-webkit-scrollbar-thumb': { + borderRadius: scrollbarWidth, + backgroundColor: theme.palette.primary.main, + }, + }, + 'body': { + backgroundColor: theme.palette.common.white, + }, + })} + /> + + ); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4363f8f76..f14656588 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -20,6 +20,9 @@ importers: '@alchemy/theme-editor': specifier: workspace:* version: link:../../lib/js/theme-editor + '@mui/icons-material': + specifier: ^5.15.0 + version: 5.15.0(@mui/material@5.15.0)(@types/react@18.2.39)(react@18.2.0) '@mui/material': specifier: ^5.15.0 version: 5.15.0(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.39)(react-dom@18.2.0)(react@18.2.0) @@ -29,6 +32,9 @@ importers: react-dom: specifier: ^18.2.0 version: 18.2.0(react@18.2.0) + react-google-font-loader: + specifier: ^1.1.0 + version: 1.1.0(react-dom@18.2.0)(react@18.2.0) vite-plugin-svgr: specifier: ^4.2.0 version: 4.2.0(typescript@5.3.2)(vite@5.0.7) @@ -17666,6 +17672,17 @@ packages: react: 18.2.0 dev: false + /react-google-font-loader@1.1.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-mnPYxBdhYEldTtREYPKllbmMvCGkTbpdmNjR6iTM3eTNWcg17OrfXjq9HRDZe+1+mhnUnI/AOcpvG0LIQPcLIw==} + peerDependencies: + react: ^16.6.3 + react-dom: ^16.6.3 + dependencies: + prop-types: 15.8.1 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /react-grid-gallery@0.5.6(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-x+JYmt8iHVzcoeji7hG33IQdzJ4LmcOpgg0zS/mAPf7FsGtSgo/UpfhUPWduhDBglMTG1xbbw/z/kiZb7J9Pcg==} peerDependencies: