import { Checkbox, Grid, Table, TableBody, TableCell, TableFooter, TablePagination, TableRow, Tooltip, } from "@material-ui/core"; import DeleteIcon from "@material-ui/icons/Delete"; import SendIcon from "@material-ui/icons/Send"; import VisibilityIcon from "@material-ui/icons/Visibility"; import { ToggleButton, ToggleButtonGroup } from "@mui/material"; import clsx from "clsx"; import React, { useEffect, useState } from "react"; import { Link } from "react-router-dom"; import EditIcon from "@material-ui/icons/Edit"; import { logger } from "../../../services/monitoring"; import { LocalDateTimeString } from "../../../utils/dates"; import { TYPE_MANIFEST_AFTERSALES, TYPE_MANIFEST_CONFIG, TYPE_MANIFEST_SOFTWARE } from "../../../utils/manifest_types"; import { Permissions, hasRole } from "../../../utils/roles"; import { ManifestsProvider, useManifestsContext } from "../../Contexts/ManifestsContext"; import { useStatusContext } from "../../Contexts/StatusContext"; import { useUserContext } from "../../Contexts/UserContext"; import DropDownButton from "../../Controls/DropDownButton"; import ECUList from "../../Controls/ECUList"; import { RoleWrap } from "../../Controls/RoleWrap"; import SearchField from "../../Controls/SearchField"; import DeleteConfirmation from "../../DeleteConfirmation"; import TableHeaderSortable from "../../Table/HeaderSortable"; import { useLocalStorage } from "../../useLocalStorage"; import useStyles from "../../useStyles"; import { useUpdateManifest } from "../../../hooks"; import GeneralConfirmation from "../../GeneralConfirmation"; const tableColumns = [ { id: "id", label: "ID", }, { id: "name", label: "Name", }, { id: "version", label: "Version", }, { id: "manifest_type", label: "Type", }, { id: "sums", label: "SUMS", }, { id: "type", label: "Update", }, { id: "created_at", label: "Created", }, { id: "updated_at", label: "Updated", }, { id: "", label: "Actions", }, ]; const formatType = (type) => { switch (type) { case "forced": return "Forced"; default: return "Standard"; } }; const formatManifestType = (manifestType) => { switch (manifestType) { case 1: return "Software"; case 2: return "Config"; case 3: return "Magna"; case 4: return "Aftersales"; default: return manifestType; } } const PAGE_SIZE = "MANIFEST_LIST_PAGE_SIZE"; const MainForm = () => { const classes = useStyles(); const [pageSize, setPageSize] = useLocalStorage(PAGE_SIZE, 10); const [pageIndex, setPageIndex] = useState(0); const [orderBy, setOrderBy] = useState("id"); const [order, setOrder] = useState("asc"); const [search, setSearch] = useLocalStorage("DEPLOYMENT_SEARCH", ""); const [active, setActive] = useLocalStorage("DEPLOYMENT_TAB_TOGGLE", "software"); const [showDeleteModal, setShowDeleteModal] = useState(false); const [showArchiveModal, setShowArchiveModal] = useState(false); const [archiveLabel, setArchiveLabel] = useState("Archive"); const { getManifests, manifests, totalManifests } = useManifestsContext(); const { setMessage, setTitle, setSitePath } = useStatusContext(); const { token: { idToken: { jwtToken: token }, }, groups, providers, } = useUserContext(); const { remove, archive, updateManifestIds, setUpdateManifestIds, setMakeActive, } = useUpdateManifest(token); const sortHandler = (event, property) => { if (property === orderBy) { if (order === "asc") { setOrder("desc"); } else { setOrder("asc"); } } else { setOrderBy(property); setOrder("asc"); } }; useEffect(() => { setTitle("Deployments"); setSitePath([]); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); useEffect(() => { (async () => { try { handleActiveChange(null, active); switch (active) { case "all": await getManifests( { limit: pageSize, offset: pageSize * pageIndex, order: `${orderBy} ${order}`, search, }, token ); break; case "aftersales": await getManifests( { limit: pageSize, offset: pageSize * pageIndex, order: `${orderBy} ${order}`, manifest_type: TYPE_MANIFEST_AFTERSALES, search, active: "true", }, token ); break; case "config": await getManifests( { limit: pageSize, offset: pageSize * pageIndex, order: `${orderBy} ${order}`, manifest_type: TYPE_MANIFEST_CONFIG, search, active: "true", }, token ); break; case "software": await getManifests( { limit: pageSize, offset: pageSize * pageIndex, order: `${orderBy} ${order}`, manifest_type: TYPE_MANIFEST_SOFTWARE, search, active: "true", }, token ); break; case "archived": await getManifests( { limit: pageSize, offset: pageSize * pageIndex, order: `${orderBy} ${order}`, manifest_type: TYPE_MANIFEST_SOFTWARE, search, active: "false", }, token ); break; default: break; } } catch (e) { setMessage(e.message); logger.warn(e.stack); } })(); // eslint-disable-next-line react-hooks/exhaustive-deps }, [pageIndex, pageSize, token, orderBy, order, search, active, updateManifestIds]); useEffect(() => { setUpdateManifestIds([]); }, [active, setUpdateManifestIds]); const handleChangePageIndex = (_event, newIndex) => { setPageIndex(newIndex); }; const handleChangePageSize = (event) => { setPageSize(parseInt(event.target.value, 10)); setPageIndex(0); }; const handleSearch = (query) => { setPageIndex(0); setSearch(query); }; const handleActiveChange = (event, newAlignment) => { if (newAlignment !== null) { setActive(newAlignment); setMakeActive(newAlignment === 'archived'); setArchiveLabel(() => { if (newAlignment === "archived") { return "Activate"; } return "Archive"; }); } } const handleSelectAll = () => { setUpdateManifestIds((selected) => selected.length ? [] : manifests.map((manifest) => manifest.id)); }; const handleSelect = (event, manifest) => { setUpdateManifestIds((selected) => { if (event.target.checked) { return [...selected, manifest.id]; } return selected.filter(id => id !== manifest.id); }); }; const setDeletePopup = (row) => { handleSelect({ target: { checked: true } }, row); setShowDeleteModal(true); }; const onArchive = async () => { try { await archive() .then(({ message }) => { setUpdateManifestIds([]); setMessage(message); }); } catch (e) { setMessage(e.message); logger.warn(e.stack); } }; const onDelete = async () => { try { await remove() .then(({ summary }) => { setUpdateManifestIds([]); setMessage(summary); }); } catch (e) { setMessage(e.message); logger.warn(e.stack); } }; const Actions = (row) => { let actions = []; if (hasRole(groups, Permissions.FiskerMagnaRead, providers)) { actions.push({ tip: `Status "${row.name} ${row.version}"`, link: `/package-status/${row.id}`, icon: ( ), }); } if (hasRole(groups, Permissions.FiskerCreate, providers)) { actions.push({ tip: `Update "${row.name} ${row.version}"`, link: `/package-update/${row.id}`, icon: , }); } if (hasRole(groups, Permissions.FiskerUpdateDeploy, providers)) { actions.push({ tip: `Deploy "${row.name} ${row.version}"`, link: `/package-deploy/${row.id}`, icon: , }); } if (hasRole(groups, Permissions.FiskerDelete, providers)) { actions.push({ tip: `Delete "${row.name} ${row.version}"`, id: row.id, icon: , }); } if (actions.length === 0) return ["No actions"]; return actions.map((action) => { if (action.link != null) { return ( {action.icon} ); } else { return ( setDeletePopup(row)}> {action.icon} ); } }); }; return (
Software Archived All setShowArchiveModal(true), disabled: !updateManifestIds.length || active === "all", } ]} /> {manifests.map((row) => { const isSelected = updateManifestIds ? !!updateManifestIds.find((id) => id === row.id) : false; return ( handleSelect(event, row)} /> {row.id} {row.name} {row.ecu_list && ( <>
)}
{row.version} {formatManifestType(row.manifest_type)} {row.sums} {formatType(row.type)} {LocalDateTimeString(row.created)} {LocalDateTimeString(row.updated)} {Actions(row)}
); })}
setShowDeleteModal(false)} deleteFunction={() => onDelete()} /> setShowArchiveModal(false)} actionFunction={() => onArchive()} />
); }; const ManifestsList = () => ( ); export default ManifestsList;