CEC-2752-Add-Mobile-Issue-Tracker (#250)

* first commit

* removed comments

* remove more comments

* fix build issues

* fix unused vars

* update snapshot

* fix test

* Fix connect ECONNREFUSED 127.0.0.1:80

* Test Magna side menu

* attempt to pass test

* fix test

* remove comments

* fix some code smells

* fix test

* resolve comments

* fix bug

* resolved comments

* resolve comments

* resolve comments

* update snapshot

* resolved comments

Co-authored-by: jwu-fisker <jwu@fiskerinc.com>
This commit is contained in:
das31
2023-01-09 13:17:41 -05:00
committed by GitHub
parent 097d58656a
commit 28135b4829
23 changed files with 3024 additions and 131 deletions

View File

@@ -0,0 +1,79 @@
import { Grid } from "@material-ui/core";
import clsx from "clsx";
import React, { useEffect } from "react";
import { logger } from "../../../../services/monitoring";
import { useStatusContext } from "../../../Contexts/StatusContext";
import { useUserContext } from "../../../Contexts/UserContext";
import {
useIssueContext,
IssueProvider
} from "../../../Contexts/IssueContext";
import useStyles from "../../../useStyles";
const MainForm = ({ id }) => {
const classes = useStyles();
const { setMessage } = useStatusContext();
const { issue, getIssue } = useIssueContext();
const {
token: {
idToken: { jwtToken: token },
},
} = useUserContext();
useEffect(() => {
(async () => {
try {
if (!id || !token) return;
await getIssue(id, token);
} catch (e) {
setMessage(e.message);
logger.warn(e.stack);
}
})();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [token]);
if (issue) {
return (
<div className={clsx(classes.paper, classes.tableSize)}>
<Grid container className={classes.root} spacing={2}>
<Grid item md={12} className={classes.textCenterAlign}>
<p>
<b>ID</b>: {id}
</p>
<p>
<b>VIN</b>: {issue.vin}
</p>
<p>
<b>Title</b>: {issue.title}
</p>
<p>
<b>Description</b>: {issue.description}
</p>
<p>
<b>timestamp</b>: {issue.timestamp}
</p>
{issue.images && issue.images.map((image, index) => (
<img key={image.id} src={`data:image/png;base64, ${image.image}`} alt="Issue images" />
))}
</Grid>
</Grid>
</div>
);
} else {
return <p>Loading...</p>;
}
};
const IssueDetails = (props) => (
<IssueProvider>
<MainForm {...props} />
</IssueProvider>
);
export default IssueDetails;

View File

@@ -0,0 +1,21 @@
import React from "react";
import { useParams } from "react-router";
import clsx from "clsx";
import { Typography } from "@material-ui/core";
import IssueDetails from "./Details";
import useStyles from "../../useStyles";
const IssueDetailsTab = () => {
const { id } = useParams();
const classes = useStyles();
return (
<div className={clsx(classes.paper, classes.tableSize)}>
<Typography variant="h6">Issue Details</Typography>
<IssueDetails id={id} classes={classes} />
</div >
);
};
export default IssueDetailsTab;

View File

@@ -0,0 +1,104 @@
import { Box, Tab, Tabs } from "@material-ui/core";
import clsx from "clsx";
import React, { useEffect, useState } from "react";
import { useParams } from "react-router";
import { useLocation } from "react-router-dom";
import { hasRole } from "../../../utils/roles";
import { useStatusContext } from "../../Contexts/StatusContext";
import { useUserContext } from "../../Contexts/UserContext";
import TabPanel from "../../Controls/TabPanel";
import useStyles from "../../useStyles";
import IssueDetailsTab from "./DetailsTab";
const tabHashes = ["details", "updates", "filters"];
const TabViews = [
{
label: "Details",
component: IssueDetailsTab,
},
];
const filterTabs = (data, groups, providers) => {
return data.reduce((result, item) => {
if (hasRole(groups, item.rolesPerProvider, providers)) {
result.push(item);
}
return result;
}, []);
};
const IssueInfo = () => {
const { id } = useParams();
const classes = useStyles();
const { setTitle, setSitePath } = useStatusContext();
const { hash } = useLocation();
const [tabIndex, setTabIndex] = useState(0);
const [tabs, setTabs] = useState([]);
const { groups, providers } = useUserContext();
useEffect(() => {
const data = filterTabs(TabViews, groups, providers);
setTabs(data);
}, [groups, providers]);
useEffect(() => {
const key = hash.replace("#", "");
const index = tabHashes.findIndex((element) => element === key);
if (index >= 0) setTabIndex(index);
}, [hash]);
useEffect(() => {
const title = `Issue ${id} Details`;
setTitle(title);
setSitePath([
{
label: "Issues",
link: "/issues",
},
{
label: title,
},
]);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [id]);
const handleTabChange = (_event, newIndex) => {
setTabIndex(newIndex);
};
return (
<div className={clsx(classes.paper, classes.tableSize)}>
<Box
className={classes.tableToolbar}
sx={{ borderBottom: 1, borderColor: "divider" }}
>
<Tabs
value={tabIndex}
onChange={handleTabChange}
aria-label="issue tabs"
indicatorColor="secondary">
{tabs.map((item, index) => <Tab key={index} label={item.label} {...tabProps(index)} />)}
</Tabs>
</Box>
{tabs.map((item, index) => (
<TabPanel key={index} value={tabIndex} index={index}>
<item.component id={id} />
</TabPanel>
))}
</div>
);
};
function tabProps(index) {
return {
id: `tab-${index}`,
"aria-controls": `tabpanel-${index}`,
};
}
export default IssueInfo;