Skip to content

Commit

Permalink
Add Manage tab to Digital Twins page preview (#957)
Browse files Browse the repository at this point in the history
Adds manage tab to digital twins preview page.
The manage tabs enables reconfiguration and deletion
of digital twins.

---------
Co-authored-by: vanessa <[email protected]>
  • Loading branch information
VanessaScherma authored Oct 22, 2024
1 parent bfa34e0 commit 54f6dbe
Show file tree
Hide file tree
Showing 65 changed files with 3,542 additions and 339 deletions.
39 changes: 3 additions & 36 deletions client/DEVELOPER.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,44 +212,11 @@ This token is required to trigger pipelines by using the API.
You can create this token in your GitLab project's CI/CD settings under
the *Pipeline trigger tokens* section.

Once the token configuration is in place, the gitlab code can be developed
Once the token configuration is in place, the gitlab integration can be developed
and tested using the following yarn commands.

```bash
yarn gitlab:compile
yarn gitlab:run
yarn test:preview:int
yarn test:preview:unit
```

These two commands run `src/util/gitlabDriver.ts` code to check the correct
functioning of the gitlab code placed in `src/util` directory.

A piece of code in `src/util/gitlabDriver.ts` checks for correct execution
of a DT in gitlab runner. The token owner must have a hosted runner
in order for this piece of code to be executed successfully.
Otherwise, the following error appears.

```log
....
Execution Result: false
Execution Status: error
Execution Logs: [
{
status: 'error',
error: Error: GitbeakerRequestError: Not Found
at DigitalTwin.<anonymous> (file:///C:/Users/au598657/git/DTaaS/client/dist/gitlabDigitalTwin.js:32:73)
at Generator.throw (<anonymous>)
at rejected (file:///C:/Users/au598657/git/DTaaS/client/dist/gitlabDigitalTwin.js:5:65)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5),
DTName: 'hello-world',
runnerTag: 'dtaas'
}
]
```

## Digital Twins page preview

In the Workbench section, there is a link to preview the **Digital Twins**
page. The GitLab account used as OAuth provider must have a *DTaaS* group,
a project under your username, and a *digital_twins* folder which contains
the Digital Twins. From this interface, you can start or stop execution of
Digital Twins, and once the execution is complete, view the complete logs.
16 changes: 15 additions & 1 deletion client/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,4 +131,18 @@ the following command:
sudo gitlab-runner run
```

It can also be used to reactivate offline runners during subsequent sessions.
It can also be used to reactivate offline runners during subsequent sessions.

## Digital Twins page preview

In the Workbench section, there is a link to preview the **Digital Twins**
page. The GitLab account used as OAuth provider must have a *DTaaS* group,
a project under your username, and a *digital_twins* folder which contains
the Digital Twins.

In the Manage tab, you can read the README.md file of the selected Digital
Twin, reconfigure the content of files included in its GitLab folder or
delete the entire folder.

In the Execute tab, you can start or stop execution of Digital Twins, and
once the execution is complete, view the complete logs.
5 changes: 0 additions & 5 deletions client/config/gitlab.json

This file was deleted.

4 changes: 2 additions & 2 deletions client/config/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ if (typeof window !== 'undefined') {
REACT_APP_WORKBENCHLINK_JUPYTERLAB: '/lab',
REACT_APP_WORKBENCHLINK_JUPYTERNOTEBOOK: '',

REACT_APP_CLIENT_ID: '1be55736756190b3ace4c2c4fb19bde386d1dcc748d20b47ea8cfb5935b8446c',
REACT_APP_AUTH_AUTHORITY: 'https://gitlab.com/',
REACT_APP_CLIENT_ID: '38bf4764fad5ebb2ebbf49b4f57c7720145b61266f13bf4891ff7851dd5c6563',
REACT_APP_AUTH_AUTHORITY: 'https://maestro.cps.digit.au.dk/gitlab',
REACT_APP_REDIRECT_URI: 'http://localhost:4000/Library',
REACT_APP_LOGOUT_REDIRECT_URI: 'http://localhost:4000/',
REACT_APP_GITLAB_SCOPES: 'openid profile read_user read_repository api',
Expand Down
5 changes: 3 additions & 2 deletions client/jest.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
"<rootDir>/src/"
],
"moduleNameMapper": {
"^test/(.*)$": "<rootDir>/test/$1"
"^test/(.*)$": "<rootDir>/test/$1",
"\\.(css|less|scss)$": "<rootDir>/test/preview/__mocks__/styleMock.ts"
}
}
}
13 changes: 10 additions & 3 deletions client/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@into-cps-association/dtaas-web",
"version": "0.5.0",
"version": "0.6.0",
"description": "Web client for Digital Twin as a Service (DTaaS)",
"main": "index.tsx",
"author": "prasadtalasila <[email protected]> (http://prasad.talasila.in/)",
Expand All @@ -24,8 +24,6 @@
"config:test": "npx shx cp config/test.js public/env.js && npx shx cp config/test.js build/env.js",
"develop": "npx react-scripts start",
"format": "prettier --ignore-path ../.gitignore --write \"**/*.{ts,tsx,css,scss}\"",
"gitlab:compile": "npx tsc --project tsconfig.gitlab.json",
"gitlab:run": "node dist/src/preview/util/gitlabDriver.js",
"graph": "npx madge --image src.svg src && npx madge --image test.svg test",
"start": "serve -s build -l 4000",
"stop": "npx kill-port 4000",
Expand All @@ -51,9 +49,13 @@
"@emotion/styled": "^11.11.0",
"@fontsource/roboto": "^5.0.8",
"@gitbeaker/rest": "^40.1.2",
"@monaco-editor/react": "^4.6.0",
"@mui/icons-material": "^5.14.8",
"@mui/material": "^5.14.8",
"@mui/x-tree-view": "^7.19.0",
"@reduxjs/toolkit": "^1.9.7",
"@types/react-syntax-highlighter": "^15.5.13",
"@types/remarkable": "^2.0.8",
"@types/styled-components": "^5.1.32",
"@typescript-eslint/eslint-plugin": "^6.12.0",
"@typescript-eslint/parser": "^6.12.0",
Expand All @@ -66,6 +68,8 @@
"eslint-plugin-jest": "^27.6.0",
"eslint-plugin-jsx-a11y": "^6.8.0",
"eslint-plugin-react": "^7.33.2",
"katex": "^0.16.11",
"markdown-it-katex": "^2.0.3",
"oidc-client-ts": "^2.2.2",
"prop-types": "^15.8.1",
"react": "^18.2.0",
Expand All @@ -76,8 +80,11 @@
"react-redux": "^8.1.3",
"react-router-dom": "^6.20.0",
"react-scripts": "^5.0.1",
"react-syntax-highlighter": "^15.5.0",
"react-tabs": "^6.0.2",
"redux": "^4.2.1",
"remarkable": "^2.0.1",
"remarkable-katex": "^1.2.1",
"resize-observer-polyfill": "^1.5.1",
"serve": "^14.2.1",
"styled-components": "^6.1.1",
Expand Down
7 changes: 5 additions & 2 deletions client/src/page/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,16 @@ function MenuLayout(props: { children: React.ReactNode }) {
);
}

function Layout(props: { children: React.ReactNode }) {
function Layout(props: {
children: React.ReactNode;
sx?: React.CSSProperties;
}) {
return (
<Box sx={{ display: 'flex', minHeight: '100vh' }}>
<MenuLayout>
<Container
maxWidth="lg"
sx={{ mt: 1, mb: 1, flexGrow: 1, display: 'flex' }}
sx={{ mt: 1, mb: 1, flexGrow: 1, ...props.sx }}
className="content"
>
<Grid container spacing={3} sx={{ minHeight: '100%' }}>
Expand Down
1 change: 0 additions & 1 deletion client/src/preview/components/asset/Asset.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
export interface Asset {
name: string;
description?: string;
path: string;
}
28 changes: 22 additions & 6 deletions client/src/preview/components/asset/AssetBoard.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import * as React from 'react';
import { Grid } from '@mui/material';
import { useSelector } from 'react-redux';
import { useSelector, useDispatch } from 'react-redux';
import { RootState } from 'store/store';
import AssetCardExecute from './AssetCard';
import { deleteAsset } from 'preview/store/assets.slice';
import { AssetCardExecute, AssetCardManage } from './AssetCard';
import { Asset } from './Asset';

const outerGridContainerProps = {
Expand All @@ -24,7 +25,8 @@ interface AssetBoardProps {
const AssetGridItem: React.FC<{
asset: Asset;
tab: string;
}> = ({ asset }) => (
onDelete: (path: string) => void;
}> = ({ asset, tab, onDelete }) => (
<Grid
key={asset.path}
item
Expand All @@ -34,21 +36,35 @@ const AssetGridItem: React.FC<{
lg={3}
sx={{ minWidth: 250 }}
>
<AssetCardExecute asset={asset} />
{tab === 'Execute' ? (
<AssetCardExecute asset={asset} />
) : (
<AssetCardManage asset={asset} onDelete={() => onDelete(asset.path)} />
)}
</Grid>
);

const AssetBoard: React.FC<AssetBoardProps> = ({ tab, error }) => {
const assets = useSelector((state: RootState) => state.assets.items);
const dispatch = useDispatch();

const handleDelete = (deletedAssetPath: string) => {
dispatch(deleteAsset(deletedAssetPath));
};

if (error) {
return <em style={{ textAlign: 'center' }}>{error}</em>;
}

return (
<Grid {...outerGridContainerProps}>
{assets.map((asset: Asset) => (
<AssetGridItem key={asset.path} asset={asset} tab={tab} />
{assets.map((asset) => (
<AssetGridItem
key={asset.path}
asset={asset}
tab={tab}
onDelete={handleDelete}
/>
))}
</Grid>
);
Expand Down
78 changes: 77 additions & 1 deletion client/src/preview/components/asset/AssetCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,34 @@ import { useSelector } from 'react-redux';
import { selectDigitalTwinByName } from 'preview/store/digitalTwin.slice';
import { RootState } from 'store/store';
import LogDialog from 'preview/route/digitaltwins/execute/LogDialog';
import DetailsDialog from 'preview/route/digitaltwins/manage/DetailsDialog';
import ReconfigureDialog from 'preview/route/digitaltwins/manage/ReconfigureDialog';
import DeleteDialog from 'preview/route/digitaltwins/manage/DeleteDialog';
import StartStopButton from './StartStopButton';
import LogButton from './LogButton';
import { Asset } from './Asset';
import DetailsButton from './DetailsButton';
import ReconfigureButton from './ReconfigureButton';
import DeleteButton from './DeleteButton';

interface AssetCardProps {
asset: Asset;
buttons?: React.ReactNode;
}

interface AssetCardManageProps {
asset: Asset;
buttons?: React.ReactNode;
onDelete: () => void;
}

interface CardButtonsContainerManageProps {
assetName: string;
setShowDetails: Dispatch<SetStateAction<boolean>>;
setShowReconfigure: Dispatch<SetStateAction<boolean>>;
setShowDelete: Dispatch<SetStateAction<boolean>>;
}

interface CardButtonsContainerExecuteProps {
assetName: string;
setShowLog: Dispatch<SetStateAction<boolean>>;
Expand Down Expand Up @@ -67,6 +86,21 @@ function CardActionAreaContainer(asset: Asset) {
);
}

function CardButtonsContainerManage({
assetName,
setShowDetails,
setShowReconfigure,
setShowDelete,
}: CardButtonsContainerManageProps) {
return (
<CardActions style={{ justifyContent: 'flex-end' }}>
<DetailsButton assetName={assetName} setShowDetails={setShowDetails} />
<ReconfigureButton setShowReconfigure={setShowReconfigure} />
<DeleteButton setShowDelete={setShowDelete} />
</CardActions>
);
}

function CardButtonsContainerExecute({
assetName,
setShowLog,
Expand Down Expand Up @@ -105,6 +139,48 @@ function AssetCard({ asset, buttons }: AssetCardProps) {
);
}

function AssetCardManage({ asset, onDelete }: AssetCardManageProps) {
const [showDetailsLog, setShowDetailsLog] = useState(false);
const [showDeleteLog, setShowDeleteLog] = useState(false);
const [showReconfigure, setShowReconfigure] = useState(false);
const digitalTwin = useSelector(selectDigitalTwinByName(asset.name));

return (
digitalTwin && (
<>
<AssetCard
asset={asset}
buttons={
<CardButtonsContainerManage
assetName={asset.name}
setShowDelete={setShowDeleteLog}
setShowDetails={setShowDetailsLog}
setShowReconfigure={setShowReconfigure}
/>
}
/>
<CustomSnackbar />
<DetailsDialog
showDialog={showDetailsLog}
setShowDialog={setShowDetailsLog}
name={asset.name}
/>
<ReconfigureDialog
showDialog={showReconfigure}
setShowDialog={setShowReconfigure}
name={asset.name}
/>
<DeleteDialog
showDialog={showDeleteLog}
setShowDialog={setShowDeleteLog}
name={asset.name}
onDelete={onDelete}
/>
</>
)
);
}

function AssetCardExecute({ asset }: AssetCardProps) {
useState<AlertColor>('success');
const [showLog, setShowLog] = useState(false);
Expand Down Expand Up @@ -133,4 +209,4 @@ function AssetCardExecute({ asset }: AssetCardProps) {
);
}

export default AssetCardExecute;
export { AssetCardManage, AssetCardExecute };
28 changes: 28 additions & 0 deletions client/src/preview/components/asset/DeleteButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import * as React from 'react';
import { Dispatch, SetStateAction } from 'react';
import { Button } from '@mui/material';

interface DeleteButtonProps {
setShowDelete: Dispatch<React.SetStateAction<boolean>>;
}

const handleToggleDeleteDialog = (
setShowDelete: Dispatch<SetStateAction<boolean>>,
) => {
setShowDelete(true);
};

function DeleteButton({ setShowDelete }: DeleteButtonProps) {
return (
<Button
variant="contained"
size="small"
color="primary"
onClick={() => handleToggleDeleteDialog(setShowDelete)}
>
Delete
</Button>
);
}

export default DeleteButton;
Loading

0 comments on commit 54f6dbe

Please sign in to comment.