Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
4rthem committed Dec 20, 2023
1 parent f70a3b9 commit d336426
Show file tree
Hide file tree
Showing 30 changed files with 492 additions and 522 deletions.
4 changes: 3 additions & 1 deletion .env
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ LETS_ENCRYPT_PROVIDER=
LETS_ENCRYPT_CA_SERVER=https://acme-staging-v02.api.letsencrypt.org/directory

PHRASEA_DOMAIN="${PHRASEA_DOMAIN:-phrasea.local}"
DASHBOARD_URL=https://dashboard.${PHRASEA_DOMAIN}${HTTPS_PORT_PREFIX}
DASHBOARD_CLIENT_URL=https://dashboard.${PHRASEA_DOMAIN}${HTTPS_PORT_PREFIX}
S3_ENDPOINT=https://minio.${PHRASEA_DOMAIN}${HTTPS_PORT_PREFIX}
UPLOADER_API_URL=https://api-uploader.${PHRASEA_DOMAIN}${HTTPS_PORT_PREFIX}
EXPOSE_API_URL=https://api-expose.${PHRASEA_DOMAIN}${HTTPS_PORT_PREFIX}
Expand Down Expand Up @@ -51,6 +51,8 @@ APP_ENV=prod
# Enables some features for debugging applications
DEV_MODE=false

# Dashboard
DASHBOARD_CLIENT_ID=dashboard-app
DISPLAY_SERVICES_MENU=true

# Minio
Expand Down
1 change: 1 addition & 0 deletions configurator/config/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ services:
- databox
- expose
- uploader
- dashboard

# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
Expand Down
39 changes: 39 additions & 0 deletions dashboard/client/config-compiler.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
(function (config, env) {
config = config || {};

const analytics = {};

if (env.MATOMO_URL) {
analytics.matomo = {
baseUrl: env.MATOMO_URL,
siteId: env.MATOMO_SITE_ID,
};
}

const whiteList = [
'DATABOX_API_URL',
'DATABOX_CLIENT_URL',
Expand Down Expand Up @@ -33,8 +44,36 @@
}
});

function castBoolean(value) {
if (typeof value === 'boolean') {
return value;
}

if (typeof value === 'string') {
return ['true', '1', 'on', 'y', 'yes'].includes(
value.toLowerCase()
);
}

return false;
}


return {
locales: config.available_locales,
autoConnectIdP: env.AUTO_CONNECT_IDP,
baseUrl: env.DASHBOARD_CLIENT_URL,
keycloakUrl: env.KEYCLOAK_URL,
realmName: env.KEYCLOAK_REALM_NAME,
clientId: env.CLIENT_ID,
devMode: castBoolean(env.DEV_MODE),
displayServicesMenu: castBoolean(env.DISPLAY_SERVICES_MENU),
dashboardBaseUrl: env.DASHBOARD_CLIENT_URL,
analytics,
appId: env.APP_ID || 'dashboard',
sentryDsn: env.SENTRY_DSN,
sentryEnvironment: env.SENTRY_ENVIRONMENT,
sentryRelease: env.SENTRY_RELEASE,
env: e,
};
});
8 changes: 7 additions & 1 deletion dashboard/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,19 @@
"preview": "vite preview"
},
"dependencies": {
"@alchemy/api": "workspace:*",
"@alchemy/auth": "workspace:*",
"@alchemy/core": "workspace:*",
"@alchemy/react-auth": "workspace:*",
"@alchemy/theme-editor": "workspace:*",
"@alchemy/phrasea-ui": "workspace:*",
"@mui/material": "^5.15.1",
"@mui/icons-material": "^5.15.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-google-font-loader": "^1.1.0",
"vite-plugin-svgr": "^4.2.0"
"vite-plugin-svgr": "^4.2.0",
"react-i18next": "^13.5.0"
},
"devDependencies": {
"@types/node": "^18.8.5",
Expand Down
51 changes: 24 additions & 27 deletions dashboard/client/src/Dashboard.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,4 @@
import {
Alert,
Chip,
Container,
Grid,
Typography,
useMediaQuery,
useTheme,
} from '@mui/material';
import {Alert, Chip, Container, Grid, Typography, useMediaQuery, useTheme,} from '@mui/material';
import Service from './Service';
import ClientApp from './ClientApp.tsx';
import config from './config.ts';
Expand All @@ -17,6 +9,7 @@ import databoxImg from './images/databox.png';
import uploaderImg from './images/uploader.png';
import exposeImg from './images/expose.png';
import notifyImg from './images/notify.png';
import DashboardBar from "./DashboardBar";

type Props = {};

Expand All @@ -26,7 +19,6 @@ export default function Dashboard({}: Props) {
EXPOSE_API_URL,
UPLOADER_API_URL,
NOTIFY_API_URL,
KEYCLOAK_URL,
DATABOX_CLIENT_URL,
EXPOSE_CLIENT_URL,
UPLOADER_CLIENT_URL,
Expand All @@ -35,26 +27,31 @@ export default function Dashboard({}: Props) {
STACK_VERSION,
} = config.env;

console.debug('config.env', config.env);
console.debug('config', config);

const theme = useTheme();
const isLarge = useMediaQuery(theme.breakpoints.up('sm'));

return (
<Container>
{isLarge && (
<Typography
variant={'h1'}
sx={{
'.MuiChip-root': {
ml: 2,
fontWeight: 400,
},
}}
>
{STACK_NAME}
<Chip icon={<SellIcon />} label={STACK_VERSION} />
</Typography>
<DashboardBar>
<Typography
variant={'h1'}
sx={{
'.MuiChip-root': {
ml: 2,
},
}}
>
{STACK_NAME}
<Chip
icon={<SellIcon/>}
label={STACK_VERSION}
color={'info'}
/>
</Typography>
</DashboardBar>
)}

{isLarge && DEV_MODE && (
Expand All @@ -76,14 +73,14 @@ export default function Dashboard({}: Props) {
spacing={2}
>
<Service
mainUrl={KEYCLOAK_URL}
mainUrl={config.keycloakUrl}
title={`Identity Manager`}
description={`Keycloak IAM`}
logo={keycloakImg}
links={[
{
icon: <ApiIcon />,
href: KEYCLOAK_URL,
icon: <ApiIcon/>,
href: config.keycloakUrl,
title: `Keycloak Home`,
},
]}
Expand Down Expand Up @@ -123,7 +120,7 @@ export default function Dashboard({}: Props) {
logo={notifyImg}
links={[
{
icon: <ApiIcon />,
icon: <ApiIcon/>,
href: NOTIFY_API_URL,
title: `API documentation of Notify`,
},
Expand Down
53 changes: 53 additions & 0 deletions dashboard/client/src/DashboardBar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import AppBar from '@mui/material/AppBar';
import Toolbar from '@mui/material/Toolbar';
import {PropsWithChildren} from "react";
import {useKeycloakUrls, useKeycloakUser} from '@alchemy/react-auth';
import config from "./config.ts";
import {keycloakClient} from "./lib/apiClient.ts";
import MenuItem from "@mui/material/MenuItem";
import Box from "@mui/material/Box";
import {UserMenu} from '@alchemy/phrasea-ui';
import {useTranslation} from "react-i18next";

type Props = PropsWithChildren<{}>;

export default function DashboardBar({
children
}: Props) {
const menuHeight = 42;
const {t} = useTranslation();
const {getLoginUrl, getAccountUrl} = useKeycloakUrls({
autoConnectIdP: config.autoConnectIdP,
keycloakClient,
});

const {user, logout} = useKeycloakUser();

return (
<AppBar position="sticky">
<Toolbar>
<div style={{
flexGrow: 1
}}>
{children}
</div>


<Box sx={{flexGrow: 0}}>
{!user ? (
<MenuItem component={'a'} href={getLoginUrl()}>
{t('menu.sign_in', 'Sign in')}
</MenuItem>
) : (
<UserMenu
menuHeight={menuHeight}
username={user?.username}
accountUrl={getAccountUrl()}
onLogout={logout}
/>
)}
</Box>
</Toolbar>
</AppBar>
);
}
26 changes: 26 additions & 0 deletions dashboard/client/src/Root.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import {oauthClient} from './lib/apiClient';
import {AuthenticationProvider, SessionExpireContainer, useAuthorizationCode} from '@alchemy/react-auth';
import Dashboard from "./Dashboard.tsx";

type Props = {};

export default function Root({}: Props) {
useAuthorizationCode({
oauthClient,
navigate: (path, {replace} = {}) => {
if (replace) {
document.location.replace(path);
} else {
document.location.href = path
}
},
successUri: '/'
});

return (
<AuthenticationProvider oauthClient={oauthClient}>
<SessionExpireContainer/>
<Dashboard />
</AuthenticationProvider>
);
}
8 changes: 5 additions & 3 deletions dashboard/client/src/config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import {WindowConfig} from '@alchemy/core';

declare global {
interface Window {
config: {
locales: string[];
env: {
DATABOX_API_URL: string;
DATABOX_CLIENT_URL: string;
Expand All @@ -10,7 +11,6 @@ declare global {
ELASTICHQ_URL: string;
EXPOSE_API_URL: string;
EXPOSE_CLIENT_URL: string;
KEYCLOAK_URL: string;
MAILHOG_URL: string;
MATOMO_URL: string;
NOTIFY_API_URL: string;
Expand All @@ -27,10 +27,12 @@ declare global {
UPLOADER_CLIENT_URL: string;
ZIPPY_URL: string;
};
};
} & WindowConfig;
}
}

const config = window.config;

config.appName = 'dashboard';

export default config;
4 changes: 2 additions & 2 deletions dashboard/client/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import ReactDOM from 'react-dom/client';
import Dashboard from './Dashboard.tsx';
import React from 'react';
import {CssBaseline, GlobalStyles, responsiveFontSizes} from '@mui/material';
import {ThemeEditorProvider} from '@alchemy/theme-editor';
import {scrollbarWidth, theme} from './theme.ts';
import Root from "./Root.tsx";

ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
Expand Down Expand Up @@ -31,7 +31,7 @@ ReactDOM.createRoot(document.getElementById('root')!).render(
},
})}
/>
<Dashboard />
<Root/>
</ThemeEditorProvider>
</React.StrictMode>
);
17 changes: 17 additions & 0 deletions dashboard/client/src/lib/apiClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import {configureClientAuthentication, KeycloakClient} from '@alchemy/auth';
import {createHttpClient} from '@alchemy/api';

import config from '../config';

export const keycloakClient = new KeycloakClient({
clientId: config.clientId,
baseUrl: config.keycloakUrl,
realm: config.realmName,
});
export const oauthClient = keycloakClient.client;

const apiClient = createHttpClient(window.config.baseUrl);

configureClientAuthentication(apiClient, oauthClient);

export default apiClient;
2 changes: 1 addition & 1 deletion dashboard/client/src/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export const theme: ThemeOptions = {
typography: {
fontFamily: "'Montserrat', sans-serif",
h1: {
fontSize: '3rem',
fontSize: '2rem',
fontWeight: 600,
},
h2: {
Expand Down
2 changes: 1 addition & 1 deletion databox/client/config-compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
devMode: castBoolean(env.DEV_MODE),
requestSignatureTtl: env.S3_REQUEST_SIGNATURE_TTL,
displayServicesMenu: castBoolean(env.DISPLAY_SERVICES_MENU),
dashboardBaseUrl: env.DASHBOARD_URL,
dashboardBaseUrl: env.DASHBOARD_CLIENT_URL,
allowedTypes: normalizeTypes(env.ALLOWED_FILE_TYPES),
analytics,
appId: env.APP_ID || 'databox',
Expand Down
1 change: 1 addition & 0 deletions databox/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"@alchemy/theme-editor": "workspace:*",
"@alchemy/visual-workflow": "workspace:*",
"@alchemy/react-hooks": "workspace:*",
"@alchemy/phrasea-ui": "workspace:*",
"@alchemy/navigation": "workspace:*",
"@dnd-kit/core": "^6.0.5",
"@dnd-kit/sortable": "^7.0.1",
Expand Down
Loading

0 comments on commit d336426

Please sign in to comment.