CEC-3944 Static dashboard (#301)
* CEC-3944 Static dashboard * Unit test
This commit is contained in:
@@ -7,4 +7,5 @@ REACT_APP_MAGNA_GROUP_ID=68273225-9da4-4fa7-aea5-38e16ec471fe
|
|||||||
REACT_APP_OTA_SERVICE_URL=https://gw.cec-euprd.fiskerinc.com/ota_update
|
REACT_APP_OTA_SERVICE_URL=https://gw.cec-euprd.fiskerinc.com/ota_update
|
||||||
REACT_APP_SECURITY_DLL_URL=https://assets.fiskerdps.com/cloud-supplier/fisker_security_32.dll
|
REACT_APP_SECURITY_DLL_URL=https://assets.fiskerdps.com/cloud-supplier/fisker_security_32.dll
|
||||||
REACT_APP_SECURITY_DLL_64_URL=https://assets.fiskerdps.com/cloud-supplier/fisker_security_64.dll
|
REACT_APP_SECURITY_DLL_64_URL=https://assets.fiskerdps.com/cloud-supplier/fisker_security_64.dll
|
||||||
|
REACT_APP_STATIC_DASHBOARDS_URL=https://assets.fiskerdps.com/dashboards
|
||||||
REACT_APP_SUPERSET_URL=https://superset.cec-euprd.fiskerinc.com
|
REACT_APP_SUPERSET_URL=https://superset.cec-euprd.fiskerinc.com
|
||||||
|
|||||||
@@ -7,4 +7,5 @@ REACT_APP_MAGNA_GROUP_ID=68273225-9da4-4fa7-aea5-38e16ec471fe
|
|||||||
REACT_APP_OTA_SERVICE_URL=https://gw.cec-prd.fiskerinc.com/ota_update
|
REACT_APP_OTA_SERVICE_URL=https://gw.cec-prd.fiskerinc.com/ota_update
|
||||||
REACT_APP_SECURITY_DLL_URL=https://assets.fiskerdps.com/cloud-supplier/fisker_security_32.dll
|
REACT_APP_SECURITY_DLL_URL=https://assets.fiskerdps.com/cloud-supplier/fisker_security_32.dll
|
||||||
REACT_APP_SECURITY_DLL_64_URL=https://assets.fiskerdps.com/cloud-supplier/fisker_security_64.dll
|
REACT_APP_SECURITY_DLL_64_URL=https://assets.fiskerdps.com/cloud-supplier/fisker_security_64.dll
|
||||||
|
REACT_APP_STATIC_DASHBOARDS_URL=https://assets.fiskerdps.com/dashboards
|
||||||
REACT_APP_SUPERSET_URL=https://superset.cec-prd.fiskerinc.com
|
REACT_APP_SUPERSET_URL=https://superset.cec-prd.fiskerinc.com
|
||||||
|
|||||||
1
.env.dev
1
.env.dev
@@ -7,4 +7,5 @@ REACT_APP_MAGNA_GROUP_ID=efcc3025-e2d8-4212-8227-805c7be39d2c
|
|||||||
REACT_APP_OTA_SERVICE_URL=https://dev-gw.cloud.fiskerinc.com/ota_update
|
REACT_APP_OTA_SERVICE_URL=https://dev-gw.cloud.fiskerinc.com/ota_update
|
||||||
REACT_APP_SECURITY_DLL_URL=https://assets.fiskerdps.com/cloud-supplier/fisker_security_32.dll
|
REACT_APP_SECURITY_DLL_URL=https://assets.fiskerdps.com/cloud-supplier/fisker_security_32.dll
|
||||||
REACT_APP_SECURITY_DLL_64_URL=https://assets.fiskerdps.com/cloud-supplier/fisker_security_64.dll
|
REACT_APP_SECURITY_DLL_64_URL=https://assets.fiskerdps.com/cloud-supplier/fisker_security_64.dll
|
||||||
|
REACT_APP_STATIC_DASHBOARDS_URL=https://assets.fiskerdps.com/dashboards
|
||||||
REACT_APP_SUPERSET_URL=https://dev-superset-new.cloud.fiskerinc.com
|
REACT_APP_SUPERSET_URL=https://dev-superset-new.cloud.fiskerinc.com
|
||||||
|
|||||||
@@ -7,4 +7,6 @@ REACT_APP_MAGNA_GROUP_ID=efcc3025-e2d8-4212-8227-805c7be39d2c
|
|||||||
REACT_APP_OTA_SERVICE_URL=http://localhost/ota_update
|
REACT_APP_OTA_SERVICE_URL=http://localhost/ota_update
|
||||||
REACT_APP_SECURITY_DLL_URL=https://assets.fiskerdps.com/cloud-supplier/fisker_security_32.dll
|
REACT_APP_SECURITY_DLL_URL=https://assets.fiskerdps.com/cloud-supplier/fisker_security_32.dll
|
||||||
REACT_APP_SECURITY_DLL_64_URL=https://assets.fiskerdps.com/cloud-supplier/fisker_security_64.dll
|
REACT_APP_SECURITY_DLL_64_URL=https://assets.fiskerdps.com/cloud-supplier/fisker_security_64.dll
|
||||||
|
REACT_APP_STATIC_DASHBOARDS_URL=https://assets.fiskerdps.com/dashboards
|
||||||
REACT_APP_SUPERSET_URL=https://dev-superset-new.cloud.fiskerinc.com
|
REACT_APP_SUPERSET_URL=https://dev-superset-new.cloud.fiskerinc.com
|
||||||
|
|
||||||
|
|||||||
1
.env.prd
1
.env.prd
@@ -7,4 +7,5 @@ REACT_APP_MAGNA_GROUP_ID=68273225-9da4-4fa7-aea5-38e16ec471fe
|
|||||||
REACT_APP_OTA_SERVICE_URL=https://gw.cloud.fiskerinc.com/ota_update
|
REACT_APP_OTA_SERVICE_URL=https://gw.cloud.fiskerinc.com/ota_update
|
||||||
REACT_APP_SECURITY_DLL_URL=https://assets.fiskerdps.com/cloud-supplier/fisker_security_32.dll
|
REACT_APP_SECURITY_DLL_URL=https://assets.fiskerdps.com/cloud-supplier/fisker_security_32.dll
|
||||||
REACT_APP_SECURITY_DLL_64_URL=https://assets.fiskerdps.com/cloud-supplier/fisker_security_64.dll
|
REACT_APP_SECURITY_DLL_64_URL=https://assets.fiskerdps.com/cloud-supplier/fisker_security_64.dll
|
||||||
|
REACT_APP_STATIC_DASHBOARDS_URL=https://assets.fiskerdps.com/dashboards
|
||||||
REACT_APP_SUPERSET_URL=https://superset.cloud.fiskerinc.com
|
REACT_APP_SUPERSET_URL=https://superset.cloud.fiskerinc.com
|
||||||
|
|||||||
1
.env.stg
1
.env.stg
@@ -7,4 +7,5 @@ REACT_APP_MAGNA_GROUP_ID=68273225-9da4-4fa7-aea5-38e16ec471fe
|
|||||||
REACT_APP_OTA_SERVICE_URL=https://stg-gw.cloud.fiskerinc.com/ota_update
|
REACT_APP_OTA_SERVICE_URL=https://stg-gw.cloud.fiskerinc.com/ota_update
|
||||||
REACT_APP_SECURITY_DLL_URL=https://assets.fiskerdps.com/cloud-supplier/fisker_security_32.dll
|
REACT_APP_SECURITY_DLL_URL=https://assets.fiskerdps.com/cloud-supplier/fisker_security_32.dll
|
||||||
REACT_APP_SECURITY_DLL_64_URL=https://assets.fiskerdps.com/cloud-supplier/fisker_security_64.dll
|
REACT_APP_SECURITY_DLL_64_URL=https://assets.fiskerdps.com/cloud-supplier/fisker_security_64.dll
|
||||||
|
REACT_APP_STATIC_DASHBOARDS_URL=https://assets.fiskerdps.com/dashboards
|
||||||
REACT_APP_SUPERSET_URL=https://stg-superset.cloud.fiskerinc.com
|
REACT_APP_SUPERSET_URL=https://stg-superset.cloud.fiskerinc.com
|
||||||
|
|||||||
@@ -126,6 +126,10 @@ describe("App", () => {
|
|||||||
await check("/tools/security-dll", "span.MuiButton-label", "Sign In");
|
await check("/tools/security-dll", "span.MuiButton-label", "Sign In");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("Route /dashboards/0 unauthenticated", async () => {
|
||||||
|
await check("/dashboards/0", "span.MuiButton-label", "Sign In");
|
||||||
|
});
|
||||||
|
|
||||||
it("Route /page-not-found unauthenticated", async () => {
|
it("Route /page-not-found unauthenticated", async () => {
|
||||||
await check("/page-not-found", "h1", "Page Not Found");
|
await check("/page-not-found", "h1", "Page Not Found");
|
||||||
});
|
});
|
||||||
@@ -200,4 +204,15 @@ describe("App", () => {
|
|||||||
setToken(TEST_AUTH_OBJECT_MAGNA);
|
setToken(TEST_AUTH_OBJECT_MAGNA);
|
||||||
await sleepAndCheck("/tools/security-dll", "h6", "Security.dll Download");
|
await sleepAndCheck("/tools/security-dll", "h6", "Security.dll Download");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("Route /dashboards/0 authenticated", async () => {
|
||||||
|
setToken(TEST_AUTH_OBJECT_FISKER);
|
||||||
|
await check("/dashboards/0", "h6", "Datascope");
|
||||||
|
});
|
||||||
|
|
||||||
|
// test bad dashboard
|
||||||
|
it("Route /dashboards/1000 authenticated", async () => {
|
||||||
|
setToken(TEST_AUTH_OBJECT_FISKER);
|
||||||
|
await check("/dashboards/1000", "span.error", "Invalid Dashboard");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
28
src/components/DashboardStatic/index.jsx
Normal file
28
src/components/DashboardStatic/index.jsx
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { useParams } from "react-router-dom";
|
||||||
|
|
||||||
|
import { getStaticDashboard } from "../../services/staticDashboards";
|
||||||
|
import { useStatusContext } from "../Contexts/StatusContext";
|
||||||
|
import useStyles from "../useStyles";
|
||||||
|
|
||||||
|
const StaticDashboard = () => {
|
||||||
|
const classes = useStyles();
|
||||||
|
const [dashboard, setDashboard] = useState(null);
|
||||||
|
const { setTitle, setSitePath } = useStatusContext();
|
||||||
|
const { index } = useParams();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const result = getStaticDashboard(parseInt(index));
|
||||||
|
setDashboard(result);
|
||||||
|
setTitle("Datascope");
|
||||||
|
setSitePath([{ label: result.label}]);
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [index]);
|
||||||
|
|
||||||
|
if (!dashboard) return <div>Loading...</div>;
|
||||||
|
if (dashboard.error) return <span className="error">{dashboard.error}</span>;
|
||||||
|
return <iframe className={classes.iframe} src={dashboard.url} title={dashboard.label}/>;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
export default StaticDashboard;
|
||||||
@@ -1,19 +1,19 @@
|
|||||||
import { List } from "@material-ui/core";
|
import { List } from "@material-ui/core";
|
||||||
import AssessmentIcon from "@material-ui/icons/Assessment";
|
import AssessmentIcon from "@material-ui/icons/Assessment";
|
||||||
|
import BugReportIcon from "@material-ui/icons/BugReport";
|
||||||
import BuildIcon from "@material-ui/icons/Build";
|
import BuildIcon from "@material-ui/icons/Build";
|
||||||
import CloudDownloadIcon from "@material-ui/icons/CloudDownload";
|
import CloudDownloadIcon from "@material-ui/icons/CloudDownload";
|
||||||
import CommuteIcon from "@material-ui/icons/Commute";
|
import CommuteIcon from "@material-ui/icons/Commute";
|
||||||
import DirectionsCarIcon from "@material-ui/icons/DirectionsCar";
|
import DirectionsCarIcon from "@material-ui/icons/DirectionsCar";
|
||||||
import BugReportIcon from "@material-ui/icons/BugReport";
|
|
||||||
import HomeIcon from "@material-ui/icons/Home";
|
import HomeIcon from "@material-ui/icons/Home";
|
||||||
import SettingsInputCompositeIcon from "@material-ui/icons/SettingsInputComposite";
|
import SettingsInputCompositeIcon from "@material-ui/icons/SettingsInputComposite";
|
||||||
import { default as React, useEffect, useState } from "react";
|
import { default as React, useEffect, useState } from "react";
|
||||||
|
|
||||||
|
import { getStaticDashboardSubmenu } from "../../services/staticDashboards";
|
||||||
import { hasRole, Permissions } from "../../utils/roles";
|
import { hasRole, Permissions } from "../../utils/roles";
|
||||||
import { useUserContext } from "../Contexts/UserContext";
|
import { useUserContext } from "../Contexts/UserContext";
|
||||||
import SupersetDashboardList from "../SupersetDashboardList/SupersetDashboardList";
|
import SupersetDashboardList from "../SupersetDashboardList/SupersetDashboardList";
|
||||||
import { ExpandableSideMenuItem, MenuItem } from "./MenuItem";
|
import { ExpandableSideMenuItem, MenuItem } from "./MenuItem";
|
||||||
|
|
||||||
const menuData = [
|
const menuData = [
|
||||||
{
|
{
|
||||||
label: "Home",
|
label: "Home",
|
||||||
@@ -51,6 +51,7 @@ const menuData = [
|
|||||||
icon: <AssessmentIcon />,
|
icon: <AssessmentIcon />,
|
||||||
rolesPerProvider: Permissions.FiskerRead,
|
rolesPerProvider: Permissions.FiskerRead,
|
||||||
component: SupersetDashboardList,
|
component: SupersetDashboardList,
|
||||||
|
submenus: getStaticDashboardSubmenu(Permissions.FiskerRead),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Suppliers",
|
label: "Suppliers",
|
||||||
|
|||||||
@@ -188,67 +188,95 @@ exports[`SideMenu Authenticated 1`] = `
|
|||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<span>
|
||||||
<div
|
<li>
|
||||||
aria-disabled="false"
|
|
||||||
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-button"
|
|
||||||
role="button"
|
|
||||||
tabindex="0"
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
class="MuiListItemIcon-root"
|
aria-disabled="false"
|
||||||
|
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-button"
|
||||||
|
role="button"
|
||||||
|
tabindex="0"
|
||||||
>
|
>
|
||||||
<svg
|
<div
|
||||||
aria-hidden="true"
|
class="MuiListItemIcon-root"
|
||||||
class="MuiSvgIcon-root"
|
|
||||||
focusable="false"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
>
|
>
|
||||||
<path
|
<svg
|
||||||
d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM9 17H7v-7h2v7zm4 0h-2V7h2v10zm4 0h-2v-4h2v4z"
|
aria-hidden="true"
|
||||||
/>
|
class="MuiSvgIcon-root"
|
||||||
</svg>
|
focusable="false"
|
||||||
</div>
|
viewBox="0 0 24 24"
|
||||||
<div
|
|
||||||
class="MuiListItemText-root"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
|
|
||||||
>
|
|
||||||
Datascope
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<span
|
|
||||||
class="MuiTouchRipple-root"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<ul
|
|
||||||
style="margin-left: 50px;"
|
|
||||||
>
|
|
||||||
<li>
|
|
||||||
<a
|
|
||||||
aria-disabled="false"
|
|
||||||
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-button"
|
|
||||||
href="/datascope/00000000-0000-0000-0000-000000000000"
|
|
||||||
role="button"
|
|
||||||
tabindex="0"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="MuiListItemText-root"
|
|
||||||
>
|
>
|
||||||
<span
|
<path
|
||||||
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
|
d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM9 17H7v-7h2v7zm4 0h-2V7h2v10zm4 0h-2v-4h2v4z"
|
||||||
>
|
/>
|
||||||
test title
|
</svg>
|
||||||
</span>
|
</div>
|
||||||
</div>
|
<div
|
||||||
|
class="MuiListItemText-root"
|
||||||
|
>
|
||||||
<span
|
<span
|
||||||
class="MuiTouchRipple-root"
|
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
|
||||||
/>
|
>
|
||||||
</a>
|
Datascope
|
||||||
</li>
|
</span>
|
||||||
</ul>
|
</div>
|
||||||
</li>
|
<span
|
||||||
|
class="MuiTouchRipple-root"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<ul
|
||||||
|
style="margin-left: 50px;"
|
||||||
|
>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
aria-disabled="false"
|
||||||
|
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-button"
|
||||||
|
href="/datascope/00000000-0000-0000-0000-000000000000"
|
||||||
|
role="button"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="MuiListItemText-root"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
|
||||||
|
>
|
||||||
|
test title
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
class="MuiTouchRipple-root"
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</span>
|
||||||
|
<ul
|
||||||
|
style="margin-left: 50px;"
|
||||||
|
>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
aria-disabled="false"
|
||||||
|
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-button"
|
||||||
|
href="/dashboards/0"
|
||||||
|
role="button"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="MuiListItemText-root"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
|
||||||
|
>
|
||||||
|
Vehicle Paths
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
class="MuiTouchRipple-root"
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
aria-disabled="false"
|
aria-disabled="false"
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ const SMSSend = React.lazy(() => import("../SMS/Send"));
|
|||||||
const SuppliersList = React.lazy(() => import("../Suppliers/List"));
|
const SuppliersList = React.lazy(() => import("../Suppliers/List"));
|
||||||
const SupplierDetails = React.lazy(() => import("../Suppliers/Details"));
|
const SupplierDetails = React.lazy(() => import("../Suppliers/Details"));
|
||||||
const Datascope = React.lazy(() => import("../Dashboard"));
|
const Datascope = React.lazy(() => import("../Dashboard"));
|
||||||
|
const StaticDashboard = React.lazy(() => import("../DashboardStatic"));
|
||||||
|
|
||||||
const SiteRoutes = () => {
|
const SiteRoutes = () => {
|
||||||
const { token, groups, providers } = useUserContext();
|
const { token, groups, providers } = useUserContext();
|
||||||
return (
|
return (
|
||||||
@@ -54,6 +56,15 @@ const SiteRoutes = () => {
|
|||||||
type={TYPES.GUEST}
|
type={TYPES.GUEST}
|
||||||
token={token}
|
token={token}
|
||||||
/>
|
/>
|
||||||
|
<AuthRoute
|
||||||
|
path="/dashboards/:index"
|
||||||
|
render={() => <StaticDashboard />}
|
||||||
|
type={TYPES.PROTECTED}
|
||||||
|
token={token}
|
||||||
|
groups={groups}
|
||||||
|
rolesPerGroup={Permissions.FiskerRead}
|
||||||
|
providers={providers}
|
||||||
|
/>
|
||||||
<AuthRoute
|
<AuthRoute
|
||||||
path="/filter-add"
|
path="/filter-add"
|
||||||
render={() => <CANFilterCreate />}
|
render={() => <CANFilterCreate />}
|
||||||
|
|||||||
26
src/services/staticDashboards.js
Normal file
26
src/services/staticDashboards.js
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
const STATIC_DASHBOARDS_URL = process.env.REACT_APP_STATIC_DASHBOARDS_URL;
|
||||||
|
|
||||||
|
const INVALID_DASHBOARD = {
|
||||||
|
label: "Invalid Dashboard",
|
||||||
|
error: "Invalid Dashboard"
|
||||||
|
}
|
||||||
|
|
||||||
|
export const StaticDashboardList = [
|
||||||
|
{
|
||||||
|
label: "Vehicle Paths",
|
||||||
|
url: `${STATIC_DASHBOARDS_URL}/paths.html`
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
export const getStaticDashboard = (index) => {
|
||||||
|
if (index < 0 || index >= StaticDashboardList.length) return INVALID_DASHBOARD;
|
||||||
|
return StaticDashboardList[index];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getStaticDashboardSubmenu = (role) => {
|
||||||
|
return StaticDashboardList.map((item, index) => ({
|
||||||
|
label: item.label,
|
||||||
|
to: `/dashboards/${index}`,
|
||||||
|
rolesPerProvider: role,
|
||||||
|
}));
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user