From 1eb402fea92bd4936206a3be6a537191e2a7bd24 Mon Sep 17 00:00:00 2001 From: Sina Rohde <s.rohde@indiscale.com> Date: Tue, 10 Sep 2024 14:09:13 +0200 Subject: [PATCH] first steps --- pages/fdo/show/[prefix]/sandbox.tsx | 172 ++++++++++++++++++++++++++ src/components/fdos/details.tsx | 121 ++++++++++++++++++ src/components/fdos/table.tsx | 128 +++++++++++++++++++ src/components/linkahead_icon_256.png | Bin 0 -> 11747 bytes 4 files changed, 421 insertions(+) create mode 100644 pages/fdo/show/[prefix]/sandbox.tsx create mode 100644 src/components/fdos/details.tsx create mode 100644 src/components/fdos/table.tsx create mode 100644 src/components/linkahead_icon_256.png diff --git a/pages/fdo/show/[prefix]/sandbox.tsx b/pages/fdo/show/[prefix]/sandbox.tsx new file mode 100644 index 0000000..0b99069 --- /dev/null +++ b/pages/fdo/show/[prefix]/sandbox.tsx @@ -0,0 +1,172 @@ +import React from 'react' +import { ErrorComponent } from '../../../../src/components/ErrorComponent'; +import { GetServerSideProps } from 'next'; +import { serverSideTranslations } from 'next-i18next/serverSideTranslations'; +import { useShow, useTranslate, useParsed, useCustom, useApiUrl } from '@refinedev/core'; +import { Show } from '@refinedev/mui'; +import { CardContent, Typography } from '@mui/material'; +import CircularProgress from '@mui/material/CircularProgress'; +import Box from '@mui/material/Box'; +import Stack from '@mui/material/Stack'; +import Chip from '@mui/material/Chip'; +import Link from '@mui/material/Link'; +import StorageIcon from '@mui/icons-material/Storage'; +import Paper from '@mui/material/Paper'; +import RadioButtonUncheckedIcon from '@mui/icons-material/RadioButtonUnchecked'; +import Divider from '@mui/material/Divider'; +import MenuList from '@mui/material/MenuList'; +import MenuItem from '@mui/material/MenuItem'; +import ListItemText from '@mui/material/ListItemText'; +import ListItemIcon from '@mui/material/ListItemIcon'; +import VerifiedIcon from '@mui/icons-material/Verified'; +import ReportIcon from '@mui/icons-material/Report'; +import Table from '../../../../src/components/fdos/table'; +import { styled } from '@mui/material/styles'; +import Details from '../../../../src/components/fdos/details'; + + +const resolvePid = (pid: string) => `https://hdl.handle.net/${pid}` + +const ShowFDO = () => { + const { params } = useParsed() + const showId = `${params?.prefix}/${params?.suffix}` + const apiUrl = useApiUrl() + const t = useTranslate() + const { data, isLoading, isError, error } = useCustom({ + url: `${apiUrl}/fdo/${showId}`, + method: 'get', + errorNotification: () => false, + queryOptions: { + retry: false + } + }) + + if (isError) { + return <ErrorComponent message={t('fdo.show.handle_not_found', 'Handle not found.')} /> + } + + const handleUrl = resolvePid(showId) + const dataPid = data?.data?.dataPid + const metadataPid = data?.data?.metadataPid + const profilePid = '21.T11969/141bf451b18a79d0fe66' + const Item = styled(Paper)(({ theme }) => ({ + backgroundColor: '#fff', + ...theme.typography.body2, + padding: theme.spacing(1), + textAlign: 'center', + color: theme.palette.text.secondary, + ...theme.applyStyles('dark', { + backgroundColor: '#1A2027', + }), + })); + + return ( + <Show + isLoading={isLoading} + title={<Typography variant="h5">{ showId }{ !isLoading && (data?.data?.isFdo ? <Chip label="FDO" color="success" variant="outlined" /> : <Chip label="Not an FDO" color="error" variant="outlined" />)}</Typography>} + > + { isLoading && <Box sx={{ textAlign: 'center' }}><CircularProgress/></Box>} + + <div> + <Stack + direction="row" + divider={<Divider orientation="vertical" flexItem />} + spacing={2} + > + <Item> + <MenuList> + <MenuItem> + <ListItemIcon> + <RadioButtonUncheckedIcon/> + </ListItemIcon> + <ListItemText> + <Link href={`${handleUrl}?noredirect`}>Handle Record</Link> + </ListItemText> + </MenuItem> + <MenuItem> + <ListItemIcon> + <StorageIcon/> + </ListItemIcon> + <ListItemText> + <Link href={handleUrl}>To Repository</Link> + </ListItemText> + </MenuItem> + { data?.data?.isFdo && (<> + <Divider /> + <MenuItem> + <ListItemIcon> + { dataPid + ? <VerifiedIcon color="success"/> + : <ReportIcon color="error"/> + } + </ListItemIcon> + <ListItemText> + { metadataPid + ? <Link href={resolvePid(dataPid)}>Data</Link> + : 'Data not available.' + } + </ListItemText> + </MenuItem> + <MenuItem> + <ListItemIcon> + { metadataPid + ? <VerifiedIcon color="success"/> + : <ReportIcon color="error"/> + } + </ListItemIcon> + <ListItemText> + { metadataPid + ? <Link href={resolvePid(metadataPid)}>Metadata</Link> + : 'Metadata not available.' + } + </ListItemText> + </MenuItem> + <MenuItem> + <ListItemIcon> + { profilePid + ? <VerifiedIcon color="success"/> + : <ReportIcon color="error"/> + } + </ListItemIcon> + <ListItemText> + { profilePid + ? <Link href={resolvePid(profilePid)}>Profile</Link> + : 'Profile not available.' + } + </ListItemText> + </MenuItem> + </>)} + </MenuList> + + </Item> + <Item> + <h2>FDO Name</h2> + <Details/> + </Item> + <Item sx={{width: '30%' }}> + <h3>Description</h3><br/> + Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + </Item> + </Stack> + </div> + <br/> + <Table/> + + </Show> + + ) +} + +export default ShowFDO + +export const getServerSideProps: GetServerSideProps<{}> = async (context) => { + const translateProps = await serverSideTranslations(context.locale ?? 'en', [ + 'common' + ]) + + return { + props: { + ...translateProps + } + } +} diff --git a/src/components/fdos/details.tsx b/src/components/fdos/details.tsx new file mode 100644 index 0000000..79832b4 --- /dev/null +++ b/src/components/fdos/details.tsx @@ -0,0 +1,121 @@ +import * as React from 'react'; +import List from '@mui/material/List'; +import ListItem from '@mui/material/ListItem'; +import Divider from '@mui/material/Divider'; +import ListItemText from '@mui/material/ListItemText'; +import ListItemAvatar from '@mui/material/ListItemAvatar'; +import Avatar from '@mui/material/Avatar'; +import Typography from '@mui/material/Typography'; + +export default function AlignItemsList() { + return ( + + <List sx={{ width: '100%', maxWidth: 360, bgcolor: 'background.paper' }}> + <ListItem alignItems="flex-start"> + <ListItemAvatar> + <Avatar alt="LinkAhead Logo" src="/linkahead_icon_256.png" /> + </ListItemAvatar> + <ListItemText + primary="Repository: LinkAhead XX" + secondary={ + <React.Fragment> + <Typography + component="span" + variant="body2" + sx={{ color: 'text.primary', display: 'inline' }} + > + Further Information: + </Typography> + {"Lorem ipsum dolor sit amet."} + </React.Fragment> + } + /> + </ListItem> + <Divider variant="inset" component="li" /> + <ListItem alignItems="flex-start"> + + <ListItemText + primary="Dataspace: RWTH" + secondary={ + <React.Fragment> + <Typography + component="span" + variant="body2" + sx={{ color: 'text.primary', display: 'inline' }} + > + Further Information: + </Typography> + {"Lorem ipsum dolor sit amet."} + </React.Fragment> + } + /> + <ListItemAvatar> + <Avatar alt="Text" src="" /> + </ListItemAvatar> + </ListItem> + <Divider variant="inset" component="li" /> + <ListItem alignItems="flex-start"> + <ListItemAvatar> + <Avatar alt="Text" src="" /> + </ListItemAvatar> + <ListItemText + primary="Technology: EDC" + secondary={ + <React.Fragment> + <Typography + component="span" + variant="body2" + sx={{ color: 'text.primary', display: 'inline' }} + > + Further Information: + </Typography> + {"Lorem ipsum dolor sit amet."} + </React.Fragment> + } + /> + </ListItem> + <Divider variant="inset" component="li" /> + <ListItem alignItems="flex-start"> + <ListItemAvatar> + <Avatar alt="Text" src="" /> + </ListItemAvatar> + <ListItemText + primary="Type: CETTS" + secondary={ + <React.Fragment> + <Typography + component="span" + variant="body2" + sx={{ color: 'text.primary', display: 'inline' }} + > + Further Information: + </Typography> + {"Lorem ipsum dolor sit amet."} + </React.Fragment> + } + /> + </ListItem> + <Divider variant="inset" component="li" /> + <ListItem alignItems="flex-start"> + <ListItemAvatar> + <Avatar alt="Text" src="" /> + </ListItemAvatar> + <ListItemText + primary="Display Name: " + secondary={ + <React.Fragment> + <Typography + component="span" + variant="body2" + sx={{ color: 'text.primary', display: 'inline' }} + > + Further Information: + </Typography> + {"Lorem ipsum dolor sit amet."} + </React.Fragment> + } + /> + </ListItem> + </List> + ); +} \ No newline at end of file diff --git a/src/components/fdos/table.tsx b/src/components/fdos/table.tsx new file mode 100644 index 0000000..147fb9f --- /dev/null +++ b/src/components/fdos/table.tsx @@ -0,0 +1,128 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import Collapse from '@mui/material/Collapse'; +import IconButton from '@mui/material/IconButton'; +import Table from '@mui/material/Table'; +import TableBody from '@mui/material/TableBody'; +import TableCell from '@mui/material/TableCell'; +import TableContainer from '@mui/material/TableContainer'; +import TableHead from '@mui/material/TableHead'; +import TableRow from '@mui/material/TableRow'; +import Typography from '@mui/material/Typography'; +import Paper from '@mui/material/Paper'; +import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown'; +import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp'; + +function createData( + name: string, + type: string, + dataspace: string, +) { + return { + name, + type, + dataspace, + details: [ + { + update: '2020-01-05', + customerId: '11091700', + amount: 'ASS', + }, + { + update: '2020-01-02', + customerId: '23987003', + amount: 'LinkAhead', + }, + ], + }; +} + +function Row(props: { row: ReturnType<typeof createData> }) { + const { row } = props; + const [open, setOpen] = React.useState(false); + + return ( + <React.Fragment> + <TableRow sx={{ '& > *': { borderBottom: 'unset' } }}> + <TableCell> + <IconButton + aria-label="expand row" + size="small" + onClick={() => setOpen(!open)} + > + {open ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />} + </IconButton> + </TableCell> + <TableCell component="th" scope="row"> + {row.name} + </TableCell> + <TableCell align="right">{row.type}</TableCell> + <TableCell align="right">{row.dataspace}</TableCell> + </TableRow> + <TableRow> + <TableCell style={{ paddingBottom: 0, paddingTop: 0 }} colSpan={6}> + <Collapse in={open} timeout="auto" unmountOnExit> + <Box sx={{ margin: 1 }}> + <Typography variant="h6" gutterBottom component="div"> + Details + </Typography> + <Table size="small" aria-label="purchases"> + <TableHead> + <TableRow> + <TableCell>UPDATE</TableCell> + <TableCell>CUSTOMER-ID</TableCell> + <TableCell align="right">DATASPACE</TableCell> + </TableRow> + </TableHead> + <TableBody> + {row.details.map((detailsRow) => ( + <TableRow key={detailsRow.update}> + <TableCell component="th" scope="row"> + {detailsRow.update} + </TableCell> + <TableCell>{detailsRow.customerId}</TableCell> + <TableCell component="th" scope="row"> + </TableCell> + <TableCell>{detailsRow.amount}</TableCell> + <TableCell component="th" scope="row"> + </TableCell> + </TableRow> + ))} + </TableBody> + </Table> + </Box> + </Collapse> + </TableCell> + </TableRow> + </React.Fragment> + ); +} +const rows = [ + createData('CETTS-D2-2024-07-08', '159', '6.0'), + createData('CETTS-D2-2024-06-24', '237', '9.0'), + createData('CETTS-XD2-2024-06-03', '262', '16.0'), + createData('CETTS-L2a-2024-05-08', '305', '3.7'), + createData('CETTS-XD3a-2024-03-11', '356', '16.0'), +]; +export default function CollapsibleTable() { + return ( + <TableContainer component={Paper}> + <Table aria-label="collapsible table"> + <TableHead> + <TableRow> + <TableCell /> + <TableCell>Name & Date</TableCell> + <TableCell align="right">Time</TableCell> + <TableCell align="right">Device</TableCell> + <TableCell align="right">Status</TableCell> + </TableRow> + </TableHead> + <TableBody> + {rows.map((row) => ( + <Row key={row.name} row={row} /> + ))} + </TableBody> + </Table> + </TableContainer> + ); +} \ No newline at end of file diff --git a/src/components/linkahead_icon_256.png b/src/components/linkahead_icon_256.png new file mode 100644 index 0000000000000000000000000000000000000000..f67910740fb5e4beb56ae8bb8dcf16414ee3658d GIT binary patch literal 11747 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 literal 0 HcmV?d00001 -- GitLab