-
Notifications
You must be signed in to change notification settings - Fork 56
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Create tab into Digital Twins page preview #1005
base: feature/distributed-demo
Are you sure you want to change the base?
Changes from 10 commits
8d1d846
2db9646
fb72ff4
54985e5
b9a0c62
15654df
b6dff7d
0d06bdb
8289011
e4d9dc6
70e1565
ae4a9a8
28c38a7
86159b1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,96 +1,76 @@ | ||
import * as React from 'react'; | ||
import { useState, useEffect } from 'react'; | ||
import { useEffect } from 'react'; | ||
import { useDispatch } from 'react-redux'; | ||
import { Typography } from '@mui/material'; | ||
import Layout from 'page/Layout'; | ||
import TabComponent from 'components/tab/TabComponent'; | ||
import { TabData } from 'components/tab/subcomponents/TabRender'; | ||
import AssetBoard from 'preview/components/asset/AssetBoard'; | ||
import GitlabInstance from 'preview/util/gitlab'; | ||
import { getAuthority } from 'util/envUtil'; | ||
import { setAssets } from 'preview/store/assets.slice'; | ||
import { Asset } from 'preview/components/asset/Asset'; | ||
import DigitalTwin from 'preview/util/gitlabDigitalTwin'; | ||
import { setDigitalTwin } from 'preview/store/digitalTwin.slice'; | ||
import { addNewFile } from 'preview/store/file.slice'; | ||
import tabs from './DigitalTwinTabDataPreview'; | ||
import CreatePage from './create/CreatePage'; | ||
|
||
export const createDTTab = (error: string | null): TabData[] => | ||
interface DTTabProps { | ||
newDigitalTwinName: string; | ||
setNewDigitalTwinName: React.Dispatch<React.SetStateAction<string>>; | ||
} | ||
|
||
export const createDTTab = ({ | ||
newDigitalTwinName, | ||
setNewDigitalTwinName, | ||
}: DTTabProps): TabData[] => | ||
tabs | ||
.filter((tab) => tab.label === 'Manage' || tab.label === 'Execute') | ||
.filter( | ||
(tab) => | ||
tab.label === 'Manage' || | ||
tab.label === 'Execute' || | ||
tab.label === 'Create', | ||
) | ||
.map((tab) => ({ | ||
label: tab.label, | ||
body: ( | ||
<> | ||
<Typography variant="body1">{tab.body}</Typography> | ||
<AssetBoard tab={tab.label} error={error} /> | ||
</> | ||
), | ||
body: | ||
tab.label === 'Create' ? ( | ||
<> | ||
<Typography variant="body1">{tab.body}</Typography> | ||
<CreatePage | ||
newDigitalTwinName={newDigitalTwinName} | ||
setNewDigitalTwinName={setNewDigitalTwinName} | ||
/> | ||
</> | ||
) : ( | ||
<> | ||
<Typography variant="body1">{tab.body}</Typography> | ||
<AssetBoard tab={tab.label} /> | ||
</> | ||
), | ||
})); | ||
|
||
export const fetchSubfolders = async ( | ||
gitlabInstance: GitlabInstance, | ||
dispatch: ReturnType<typeof useDispatch>, | ||
setError: React.Dispatch<React.SetStateAction<string | null>>, | ||
) => { | ||
try { | ||
await gitlabInstance.init(); | ||
if (gitlabInstance.projectId) { | ||
const subfolders = await gitlabInstance.getDTSubfolders( | ||
gitlabInstance.projectId, | ||
); | ||
dispatch(setAssets(subfolders)); | ||
return subfolders; | ||
} | ||
dispatch(setAssets([])); | ||
return []; | ||
} catch (error) { | ||
setError('An error occurred'); | ||
return []; | ||
} | ||
}; | ||
|
||
export const createDigitalTwinsForAssets = async ( | ||
assets: Asset[], | ||
dispatch: ReturnType<typeof useDispatch>, | ||
) => { | ||
assets.forEach(async (asset) => { | ||
const gitlabInstance = new GitlabInstance( | ||
sessionStorage.getItem('username') || '', | ||
getAuthority(), | ||
sessionStorage.getItem('access_token') || '', | ||
); | ||
await gitlabInstance.init(); | ||
const digitalTwin = new DigitalTwin(asset.name, gitlabInstance); | ||
await digitalTwin.getDescription(); | ||
dispatch(setDigitalTwin({ assetName: asset.name, digitalTwin })); | ||
}); | ||
}; | ||
|
||
export const DTContent = () => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is only creating new DT. Can this intent be made more clear with a restructuring of code? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The purpose of this file has remained unchanged, I have only added the necessary logic for the Create page (the useState There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
const [error, setError] = useState<string | null>(null); | ||
const [newDigitalTwinName, setNewDigitalTwinName] = React.useState(''); | ||
const dispatch = useDispatch(); | ||
const gitlabInstance = new GitlabInstance( | ||
sessionStorage.getItem('username') || '', | ||
getAuthority(), | ||
sessionStorage.getItem('access_token') || '', | ||
); | ||
|
||
useEffect(() => { | ||
fetchSubfolders(gitlabInstance, dispatch, setError).then((assets) => { | ||
if (assets) { | ||
createDigitalTwinsForAssets(assets, dispatch); | ||
} | ||
const defaultFiles = [ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This array and the method to iterate upon this can moved to either to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It has been moved to |
||
{ name: 'description.md', type: 'description' }, | ||
{ name: 'README.md', type: 'description' }, | ||
{ name: '.gitlab-ci.yml', type: 'config' }, | ||
]; | ||
defaultFiles.forEach((file) => { | ||
dispatch(addNewFile(file)); | ||
}); | ||
}, [dispatch]); | ||
|
||
return ( | ||
<Layout> | ||
<Typography variant="body1" style={{ marginBottom: 0 }}> | ||
This page demonstrates integration of DTaaS with gitlab CI/CD workflows. | ||
The feature is experimental and requires certain gitlab setup in order | ||
<Typography variant="body1" sx={{ marginBottom: 0 }}> | ||
This page demonstrates integration of DTaaS with GitLab CI/CD workflows. | ||
The feature is experimental and requires certain GitLab setup in order | ||
for it to work. | ||
</Typography> | ||
<TabComponent assetType={createDTTab(error)} scope={[]} /> | ||
<TabComponent | ||
assetType={createDTTab({ newDigitalTwinName, setNewDigitalTwinName })} | ||
scope={[]} | ||
/> | ||
</Layout> | ||
); | ||
}; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. File handling relates to operations on gitlab repo from frontend. Perhaps separating all the file handling operations into one module, say There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Functions with file-related operations have been moved to |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
import * as React from 'react'; | ||
import { | ||
Dialog, | ||
DialogActions, | ||
DialogContent, | ||
DialogTitle, | ||
TextField, | ||
Button, | ||
} from '@mui/material'; | ||
import { renameFile } from 'preview/store/file.slice'; | ||
import { useDispatch } from 'react-redux'; | ||
import { Dispatch, SetStateAction, useEffect, useState } from 'react'; | ||
|
||
interface ChangeFileNameDialogProps { | ||
open: boolean; | ||
onClose: () => void; | ||
fileName: string; | ||
setFileName: Dispatch<SetStateAction<string>>; | ||
setFileType: Dispatch<SetStateAction<string>>; | ||
} | ||
|
||
const ChangeFileNameDialog: React.FC<ChangeFileNameDialogProps> = ({ | ||
open, | ||
onClose, | ||
fileName, | ||
setFileName, | ||
setFileType, | ||
}) => { | ||
const [modifiedFileName, setModifiedFileName] = useState(fileName); | ||
|
||
const dispatch = useDispatch(); | ||
|
||
useEffect(() => { | ||
setModifiedFileName(fileName); | ||
}, [fileName]); | ||
|
||
const handleChangeFileName = () => { | ||
dispatch(renameFile({ oldName: fileName, newName: modifiedFileName })); | ||
setFileName(modifiedFileName); | ||
|
||
const extension = modifiedFileName.split('.').pop(); | ||
setFileType(extension || ''); | ||
|
||
onClose(); | ||
}; | ||
|
||
return ( | ||
<Dialog open={open} onClose={onClose}> | ||
<DialogTitle>Change the file name</DialogTitle> | ||
<DialogContent> | ||
<TextField | ||
autoFocus | ||
margin="dense" | ||
label="New File Name" | ||
fullWidth | ||
variant="outlined" | ||
value={modifiedFileName} | ||
onChange={(e) => setModifiedFileName(e.target.value)} | ||
/> | ||
</DialogContent> | ||
<DialogActions> | ||
<Button onClick={onClose} color="primary"> | ||
Cancel | ||
</Button> | ||
<Button onClick={handleChangeFileName} color="secondary"> | ||
Change | ||
</Button> | ||
</DialogActions> | ||
</Dialog> | ||
); | ||
}; | ||
|
||
export default ChangeFileNameDialog; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
import * as React from 'react'; | ||
import { Dispatch, SetStateAction } from 'react'; | ||
import { Dialog, DialogActions, DialogContent, Button } from '@mui/material'; | ||
import { removeAllCreationFiles, addNewFile } from 'preview/store/file.slice'; | ||
import { useDispatch, useSelector } from 'react-redux'; | ||
import { RootState } from 'store/store'; | ||
|
||
interface ConfirmDeleteDialogProps { | ||
open: boolean; | ||
onClose: () => void; | ||
setFileName: Dispatch<SetStateAction<string>>; | ||
setFileContent: Dispatch<SetStateAction<string>>; | ||
setFileType: Dispatch<SetStateAction<string>>; | ||
setNewDigitalTwinName: Dispatch<SetStateAction<string>>; | ||
} | ||
|
||
const ConfirmDeleteDialog: React.FC<ConfirmDeleteDialogProps> = ({ | ||
open, | ||
onClose, | ||
setFileName, | ||
setFileContent, | ||
setFileType, | ||
setNewDigitalTwinName, | ||
}) => { | ||
const dispatch = useDispatch(); | ||
|
||
const files = useSelector((state: RootState) => state.files); | ||
|
||
const handleConfirmCancel = () => { | ||
setFileName(''); | ||
setFileContent(''); | ||
setFileType(''); | ||
setNewDigitalTwinName(''); | ||
dispatch(removeAllCreationFiles()); | ||
|
||
const defaultFiles = [ | ||
VanessaScherma marked this conversation as resolved.
Show resolved
Hide resolved
|
||
{ name: 'description.md', type: 'description' }, | ||
{ name: 'README.md', type: 'description' }, | ||
{ name: '.gitlab-ci.yml', type: 'config' }, | ||
]; | ||
|
||
defaultFiles.forEach((file) => { | ||
const fileExists = files.some( | ||
(f) => f.name === file.name && f.isNew === true, | ||
); | ||
if (!fileExists) { | ||
dispatch(addNewFile(file)); | ||
} | ||
}); | ||
|
||
onClose(); | ||
}; | ||
|
||
return ( | ||
<Dialog open={open} onClose={onClose}> | ||
<DialogContent> | ||
Are you sure you want to delete the inserted files and their content? | ||
</DialogContent> | ||
<DialogActions> | ||
<Button onClick={onClose}>Cancel</Button> | ||
<Button onClick={handleConfirmCancel}>Yes</Button> | ||
</DialogActions> | ||
</Dialog> | ||
); | ||
}; | ||
|
||
export default ConfirmDeleteDialog; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code has been moved from
DigitalTwinsPreview.tsx
to here. The non-react part of code belongs to some file inpreview/util
module.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It has been moved to
init.ts
inpreview/util.