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:
79
src/components/Issues/Info/Details/index.jsx
Normal file
79
src/components/Issues/Info/Details/index.jsx
Normal 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;
|
||||
21
src/components/Issues/Info/DetailsTab.jsx
Normal file
21
src/components/Issues/Info/DetailsTab.jsx
Normal 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;
|
||||
104
src/components/Issues/Info/index.jsx
Normal file
104
src/components/Issues/Info/index.jsx
Normal 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;
|
||||
Reference in New Issue
Block a user