mirror of
https://github.com/Unleash/unleash.git
synced 2025-02-09 00:18:00 +01:00
feat: application graph (#6279)
Basic graph, that works with mock data. Next steps, work on backend and try to put more content and **styling to nodes**. ![image](https://github.com/Unleash/unleash/assets/964450/545d6527-ecd8-4010-a0fe-8001bc8c1456)
This commit is contained in:
parent
f46d420b10
commit
f3c01545f2
@ -1,5 +1,5 @@
|
|||||||
/* eslint react/no-multi-comp:off */
|
/* eslint react/no-multi-comp:off */
|
||||||
import React, { useContext, useState } from 'react';
|
import React, { lazy, useContext, useState } from 'react';
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
Avatar,
|
Avatar,
|
||||||
@ -68,6 +68,8 @@ const StyledTab = styled(Tab)(({ theme }) => ({
|
|||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const ApplicationOverview = lazy(() => import('./ApplicationOverview'));
|
||||||
|
|
||||||
export const Application = () => {
|
export const Application = () => {
|
||||||
const useOldApplicationScreen = !useUiFlag('sdkReporting');
|
const useOldApplicationScreen = !useUiFlag('sdkReporting');
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@ -230,7 +232,7 @@ export const Application = () => {
|
|||||||
/>
|
/>
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path='instances' element={<ConnectedInstances />} />
|
<Route path='instances' element={<ConnectedInstances />} />
|
||||||
<Route path='*' element={<p>This is a placeholder</p>} />
|
<Route path='*' element={<ApplicationOverview />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
</PageContent>
|
</PageContent>
|
||||||
</>
|
</>
|
||||||
|
@ -14,7 +14,7 @@ import {
|
|||||||
import { Link as LinkIcon } from '@mui/icons-material';
|
import { Link as LinkIcon } from '@mui/icons-material';
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
import { UPDATE_APPLICATION } from 'component/providers/AccessProvider/permissions';
|
import { UPDATE_APPLICATION } from 'component/providers/AccessProvider/permissions';
|
||||||
import { ApplicationView } from '../ApplicationView/ApplicationView';
|
import { ApplicationOverview } from '../ApplicationOverview';
|
||||||
import { ApplicationUpdate } from '../ApplicationUpdate/ApplicationUpdate';
|
import { ApplicationUpdate } from '../ApplicationUpdate/ApplicationUpdate';
|
||||||
import { Dialogue } from 'component/common/Dialogue/Dialogue';
|
import { Dialogue } from 'component/common/Dialogue/Dialogue';
|
||||||
import { PageContent } from 'component/common/PageContent/PageContent';
|
import { PageContent } from 'component/common/PageContent/PageContent';
|
||||||
@ -76,7 +76,7 @@ export const ApplicationEdit = () => {
|
|||||||
const tabData = [
|
const tabData = [
|
||||||
{
|
{
|
||||||
label: 'Application overview',
|
label: 'Application overview',
|
||||||
component: <ApplicationView />,
|
component: <ApplicationEdit />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Edit application',
|
label: 'Edit application',
|
||||||
|
84
frontend/src/component/application/ApplicationOverview.tsx
Normal file
84
frontend/src/component/application/ApplicationOverview.tsx
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
import { usePageTitle } from 'hooks/usePageTitle';
|
||||||
|
import { Mermaid } from 'component/common/Mermaid/Mermaid';
|
||||||
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
|
import { Alert, styled } from '@mui/material';
|
||||||
|
import { useThemeMode } from 'hooks/useThemeMode';
|
||||||
|
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
|
const StyledMermaid = styled(Mermaid)(({ theme }) => ({
|
||||||
|
'#mermaid .node rect': {
|
||||||
|
fill: theme.palette.secondary.light,
|
||||||
|
stroke: theme.palette.secondary.border,
|
||||||
|
},
|
||||||
|
'#mermaid .application-container': {
|
||||||
|
// display: 'flex',
|
||||||
|
// padding: theme.spacing(4,3,3,3),
|
||||||
|
// flexDirection: 'column',
|
||||||
|
// alignItems: 'center',
|
||||||
|
// gap: theme.spacing(3),
|
||||||
|
backgroundColor: theme.palette.secondary.light,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const ApplicationOverview = () => {
|
||||||
|
usePageTitle('Applications - Overview');
|
||||||
|
const applicationName = useRequiredPathParam('name');
|
||||||
|
const { themeMode } = useThemeMode();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
const app = {
|
||||||
|
projects: ['default', 'dx'],
|
||||||
|
featureCount: 12,
|
||||||
|
environments: [
|
||||||
|
{
|
||||||
|
name: 'production',
|
||||||
|
instanceCount: 34,
|
||||||
|
sdks: ['unleash-client-node:5.4.0'],
|
||||||
|
lastSeen: '2021-10-01T12:00:00Z',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'development',
|
||||||
|
instanceCount: 16,
|
||||||
|
sdks: ['unleash-client-java:5.4.0'],
|
||||||
|
lastSeen: '2021-10-01T12:00:00Z',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const applicationNode = `
|
||||||
|
${applicationName}[<span>${applicationName}</span>]
|
||||||
|
`;
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
window.navigateToInstances = (environment: string) => {
|
||||||
|
navigate(
|
||||||
|
`/applications/${applicationName}/instances?environment=${environment}`,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const graph = `
|
||||||
|
graph TD
|
||||||
|
subgraph _[ ]
|
||||||
|
direction BT
|
||||||
|
${applicationNode}
|
||||||
|
${app.environments
|
||||||
|
.map(
|
||||||
|
({ name }, i) =>
|
||||||
|
`${name}("${name}") --- ${applicationName}
|
||||||
|
click ${name} navigateToInstances`,
|
||||||
|
)
|
||||||
|
.join('\n')}
|
||||||
|
end
|
||||||
|
`;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={1 === 2 + 1}
|
||||||
|
show={<Alert severity='warning'>No data available.</Alert>}
|
||||||
|
elseShow={<StyledMermaid>{graph}</StyledMermaid>}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ApplicationOverview;
|
@ -30,6 +30,7 @@ const StyledMermaid = styled('div')(({ theme }) => ({
|
|||||||
mermaid.initialize({
|
mermaid.initialize({
|
||||||
startOnLoad: false,
|
startOnLoad: false,
|
||||||
theme: 'default',
|
theme: 'default',
|
||||||
|
securityLevel: 'loose',
|
||||||
themeCSS: `
|
themeCSS: `
|
||||||
.clusters #_ rect {
|
.clusters #_ rect {
|
||||||
fill: transparent;
|
fill: transparent;
|
||||||
@ -46,9 +47,10 @@ export const Mermaid = ({ children, ...props }: IMermaidProps) => {
|
|||||||
const mermaidRef = useRef<HTMLDivElement>(null);
|
const mermaidRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
mermaid.render('mermaid', children, (svgCode) => {
|
mermaid.render('mermaid', children, (svgCode, bindFunctions) => {
|
||||||
if (mermaidRef.current) {
|
if (mermaidRef.current) {
|
||||||
mermaidRef.current.innerHTML = svgCode;
|
mermaidRef.current.innerHTML = svgCode;
|
||||||
|
bindFunctions?.(mermaidRef.current);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, [children]);
|
}, [children]);
|
||||||
|
Loading…
Reference in New Issue
Block a user