336 lines
8.6 KiB
TypeScript
336 lines
8.6 KiB
TypeScript
import {
|
|
Breadcrumbs,
|
|
Chip,
|
|
IconButton,
|
|
Link,
|
|
LinkProps,
|
|
Skeleton,
|
|
Theme,
|
|
useTheme
|
|
} from "@mui/material";
|
|
import { Replay } from "@mui/icons-material";
|
|
// import Link, { LinkProps } from "@material-ui/core/Link";
|
|
// import { Skeleton } from "@mui/l";
|
|
import { useMobile } from "hooks";
|
|
// import { MatchParams } from "navigation/Routes";
|
|
import React, { ReactNode } from "react";
|
|
import { useLocation } from "react-router";
|
|
import { Link as RouterLink } from "react-router-dom";
|
|
import { or } from "utils/types";
|
|
import { makeStyles } from "@mui/styles";
|
|
import { getThemeType } from "theme/themeType";
|
|
|
|
const useStyles = makeStyles((theme: Theme) => {
|
|
// const isMobile = useMobile()
|
|
return ({
|
|
chip: {
|
|
maxWidth: "150px",
|
|
[theme.breakpoints.up("md")]: {
|
|
maxWidth: "200px"
|
|
},
|
|
color: "inherit",
|
|
textDecoration: "none",
|
|
'&:hover': {
|
|
color: "inherit"
|
|
}
|
|
},
|
|
textOverflow: {
|
|
whiteSpace: "nowrap",
|
|
overflow: "hidden",
|
|
textOverflow: "ellipsis",
|
|
textTransform: "capitalize",
|
|
textDecoration: "none"
|
|
}
|
|
});
|
|
});
|
|
|
|
interface Props {
|
|
deviceName?: string;
|
|
componentName?: string;
|
|
groupName?: string;
|
|
binName?: string;
|
|
reportTarget?: string;
|
|
loading?: boolean;
|
|
reload?: () => void;
|
|
}
|
|
|
|
interface LinkRouterProps extends LinkProps {
|
|
to: string;
|
|
replace?: boolean;
|
|
}
|
|
|
|
const LinkRouter = (props: LinkRouterProps) => <Link {...props} component={RouterLink as any} />;
|
|
|
|
export default function SmartBreadcrumb(props: Props) {
|
|
const theme = useTheme();
|
|
const location = useLocation();
|
|
const isMobile = useMobile();
|
|
const classes = useStyles();
|
|
const { loading, reload } = props;
|
|
|
|
const groupID = (): string => {
|
|
const regexMatch = or(location.pathname.match(/\/groups\/([^/]+)/), [])
|
|
return or(regexMatch[1], "0").toString();
|
|
};
|
|
|
|
const deviceID = (): string => {
|
|
const regexMatch = or(location.pathname.match(/\/devices\/([^/]+)/), [])
|
|
return or(regexMatch[1], "0").toString();
|
|
};
|
|
|
|
const mineKey = (): string => {
|
|
const regexMatch = or(location.pathname.match(/\/mines\/([^/]+)/), [])
|
|
return or(regexMatch[1], "0").toString();
|
|
};
|
|
|
|
const jobsiteKey = (): string => {
|
|
const regexMatch = or(location.pathname.match(/\/jobs\/([^/]+)/), [])
|
|
return or(regexMatch[1], "0").toString();
|
|
};
|
|
|
|
const componentID = (): string => {
|
|
const regexMatch = or(location.pathname.match(/\/components\/([^/]+)/), [])
|
|
return or(regexMatch[1], "0").toString();
|
|
};
|
|
|
|
const reportID = (): string => {
|
|
const regexMatch = or(location.pathname.match(/\/reports\/([^/]+)/), [])
|
|
return or(regexMatch[1], "0").toString();
|
|
};
|
|
|
|
const binID = (): string => {
|
|
const regexMatch = or(location.pathname.match(/\/bins\/([^/]+)/), [])
|
|
return or(regexMatch[1], "0").toString();
|
|
};
|
|
|
|
const reportIDShort = (): string => {
|
|
return reportID().split("-")[0];
|
|
};
|
|
|
|
// Paths
|
|
|
|
const dashboardPath = (): string => {
|
|
return "/";
|
|
};
|
|
|
|
const groupsPath = (): string => {
|
|
return "/groups";
|
|
};
|
|
|
|
const groupPath = (): string => {
|
|
return groupsPath() + "/" + groupID();
|
|
};
|
|
|
|
const devicesPath = (): string => {
|
|
return "/devices";
|
|
};
|
|
|
|
const devicePath = (): string => {
|
|
return devicesPath() + "/" + deviceID();
|
|
};
|
|
|
|
const minesPath = (): string => {
|
|
return "/mines";
|
|
};
|
|
|
|
const minePath = (): string => {
|
|
return minesPath() + "/" + mineKey();
|
|
};
|
|
|
|
const jobsitesPath = (): string => {
|
|
return "/jobsites";
|
|
};
|
|
|
|
const jobsitePath = (): string => {
|
|
return jobsitesPath() + "/" + jobsiteKey();
|
|
};
|
|
|
|
const componentsPath = (): string => {
|
|
return "/components";
|
|
};
|
|
|
|
const componentPath = (): string => {
|
|
return componentsPath() + "/" + componentID();
|
|
};
|
|
|
|
const securityPath = (): string => {
|
|
return "/security";
|
|
};
|
|
|
|
const reportPath = (): string => {
|
|
return securityPath() + "/" + reportID();
|
|
};
|
|
|
|
const groupDevicesPath = (): string => {
|
|
return groupPath() + devicesPath();
|
|
};
|
|
|
|
const groupDevicePath = (): string => {
|
|
return groupPath() + devicePath();
|
|
};
|
|
|
|
const groupComponentsPath = (): string => {
|
|
return groupPath() + componentsPath();
|
|
};
|
|
|
|
const groupComponentPath = (): string => {
|
|
return groupPath() + componentPath();
|
|
};
|
|
|
|
const historyPath = (): string => {
|
|
return "/history";
|
|
};
|
|
|
|
const deviceHistoryPath = (): string => {
|
|
return devicePath() + historyPath();
|
|
};
|
|
|
|
const groupDeviceHistoryPath = (): string => {
|
|
return groupDevicePath() + historyPath();
|
|
};
|
|
|
|
const firmwarePath = (): string => {
|
|
return "/firmware";
|
|
};
|
|
|
|
const usersPath = (): string => {
|
|
return "/users";
|
|
};
|
|
|
|
const binsPath = (): string => {
|
|
return "/bins";
|
|
};
|
|
|
|
const binPath = (): string => {
|
|
return binsPath() + "/" + binID();
|
|
};
|
|
|
|
const getBreadcrumbMap = (): { [key: string]: string } => {
|
|
const { groupName, deviceName, componentName, reportTarget, binName } = props;
|
|
const deviceLabel: string = deviceName ? deviceName : "Device " + deviceID();
|
|
const componentLabel: string = componentName ? componentName : "Component " + componentID();
|
|
const binLabel: string = binName ?? "Bin " + binID();
|
|
const mineLabel: string = "Mine Site";
|
|
const jobsiteLabel: string = "Job Site";
|
|
|
|
return {
|
|
[dashboardPath()]: "Dashboard",
|
|
[groupsPath()]: "Groups",
|
|
[groupPath()]: groupName ? groupName : "Group " + groupID(),
|
|
[devicesPath()]: "Devices",
|
|
[devicePath()]: deviceLabel,
|
|
[minesPath()]: "Mines",
|
|
[minePath()]: mineLabel,
|
|
[jobsitesPath()]: "Job Sites",
|
|
[jobsitePath()]: jobsiteLabel,
|
|
[componentsPath()]: "Components",
|
|
[componentPath()]: componentLabel,
|
|
[securityPath()]: "Security",
|
|
[reportPath()]: "Report " + reportIDShort() + (reportTarget ? " (" + reportTarget + ")" : ""),
|
|
[groupDevicePath()]: deviceLabel,
|
|
[groupComponentPath()]: componentLabel,
|
|
[deviceHistoryPath()]: "History",
|
|
[groupDeviceHistoryPath()]: "History",
|
|
[firmwarePath()]: "Firmware",
|
|
[usersPath()]: "Users",
|
|
[binsPath()]: "Bins",
|
|
[binPath()]: binLabel
|
|
};
|
|
};
|
|
|
|
const breadcrumbBlacklist = (): string[] => {
|
|
return [dashboardPath(), componentsPath(), groupDevicesPath(), groupComponentsPath()];
|
|
};
|
|
|
|
const breadcrumbLinks = (): ReactNode[] => {
|
|
const breadcrumbMap = getBreadcrumbMap();
|
|
|
|
let links: ReactNode[] = [];
|
|
const pathnames = location.pathname.split("/").filter((x: any) => x);
|
|
const blacklist = breadcrumbBlacklist();
|
|
|
|
// console.log(pathnames)
|
|
|
|
if (pathnames.length < 1) {
|
|
return [linkComponent("/", "Dashboard", true)];
|
|
}
|
|
|
|
pathnames.forEach((_value: any, index: any) => {
|
|
const lastPath = index === pathnames.length - 1;
|
|
const to = `/${pathnames.slice(0, index + 1).join("/")}`;
|
|
|
|
let label = breadcrumbMap[to];
|
|
let result = to.split("/").filter(str => str !== "");
|
|
// console.log(result)
|
|
if (!label) {
|
|
if (result.length > 1) {
|
|
if (result[result.length - 1] !== "components") {
|
|
label = breadcrumbMap["/" + result[result.length - 1]];
|
|
console.log(label)
|
|
}
|
|
}
|
|
if (!label && result[result.length - 1] !== "components") {
|
|
label = breadcrumbMap["/" + result[result.length - 2] + "/" + result[result.length - 1]];
|
|
console.log(label)
|
|
}
|
|
}
|
|
|
|
if (!blacklist.includes(to) && label) {
|
|
links.push(linkComponent(to, label, lastPath));
|
|
}
|
|
});
|
|
|
|
// console.log(links)
|
|
|
|
return links;
|
|
};
|
|
|
|
const linkComponent = (to: string, label: string, lastPath: boolean) => {
|
|
return (
|
|
<Chip
|
|
key={to}
|
|
variant={lastPath ? "filled" : "outlined"}
|
|
label={
|
|
<LinkRouter
|
|
color={lastPath ? "textPrimary" : "textSecondary"}
|
|
variant="subtitle1"
|
|
to={to}
|
|
sx={{ '&:hover': { color: getThemeType() === "dark" ? 'white' : "black" } }}
|
|
className={classes.textOverflow}>
|
|
{label}
|
|
</LinkRouter>
|
|
}
|
|
className={classes.chip}
|
|
/>
|
|
);
|
|
};
|
|
|
|
const localReload = () => {
|
|
if (reload) {
|
|
reload();
|
|
} else {
|
|
}
|
|
};
|
|
|
|
if (loading === true) return <Skeleton variant="text" width="100%" />;
|
|
|
|
return (
|
|
<React.Fragment>
|
|
<Breadcrumbs
|
|
maxItems={isMobile ? 1 : 3}
|
|
itemsBeforeCollapse={0}
|
|
aria-label="Location Breadcrumb">
|
|
{breadcrumbLinks()}
|
|
</Breadcrumbs>
|
|
{reload && (
|
|
<IconButton
|
|
color="inherit"
|
|
size="small"
|
|
style={{ marginLeft: theme.spacing(1) }}
|
|
onClick={localReload}>
|
|
<Replay />
|
|
</IconButton>
|
|
)}
|
|
</React.Fragment>
|
|
);
|
|
}
|