diff --git a/www/src/components/editor/CommissioningPackageDeletionDialog.tsx b/www/src/components/editor/CommissioningPackageDeletionDialog.tsx new file mode 100644 index 00000000..fc43978f --- /dev/null +++ b/www/src/components/editor/CommissioningPackageDeletionDialog.tsx @@ -0,0 +1,87 @@ +import { Button, Checkbox, Dialog, Table } from "@equinor/eds-core-react"; +import React, { useEffect, useState } from "react"; +import { useCommissioningPackageContext } from "../../hooks/useCommissioningPackageContext.tsx"; + +interface DeleteDialogProps { + isOpen: boolean; + onClose: () => void; +} + +const DeleteCommissioningPackageDialog: React.FC = ({ isOpen, onClose }) => { + const context = useCommissioningPackageContext(); + const [selectedPackages, setSelectedPackages] = useState>(new Set()); + + const handleCheckboxChange = (packageId: string) => { + setSelectedPackages((prevSelected) => { + const newSelected = new Set(prevSelected); + if (newSelected.has(packageId)) { + newSelected.delete(packageId); + } else { + newSelected.add(packageId); + } + return newSelected; + }); + }; + + const handleDelete = () => { + selectedPackages.forEach((packageId) => { + context?.deleteCommissioningPackage(packageId); + }); + onClose(); + setSelectedPackages(new Set()); + + if (context?.commissioningPackages.length === 0) { + context?.createInitialPackage(); + } + }; + + useEffect(() => { + if (isOpen && context?.activePackage) { + setSelectedPackages(new Set([context.activePackage.id])); + } + }, [isOpen, context?.activePackage]); + + return ( + + + Delete Commissioning Packages + + + Choose which commissioning packages to delete: + + + {context?.commissioningPackages.map((commpckg) => ( + + +
+
+ handleCheckboxChange(commpckg.id)} + /> +
+
+
+ ))} +
+
+
+ + + + +
+ ); +}; + +export default DeleteCommissioningPackageDialog; \ No newline at end of file diff --git a/www/src/components/editor/EditorSidebar.tsx b/www/src/components/editor/EditorSidebar.tsx index d6b089ed..cc36db01 100644 --- a/www/src/components/editor/EditorSidebar.tsx +++ b/www/src/components/editor/EditorSidebar.tsx @@ -1,11 +1,12 @@ import { SideBar, SidebarLinkProps } from "@equinor/eds-core-react"; -import { add, boundaries, category, texture } from "@equinor/eds-icons"; +import { add, boundaries, category, texture, delete_to_trash } from "@equinor/eds-icons"; import styled from "styled-components"; import { useContext, useState } from "react"; import Tools from "../../enums/Tools.ts"; import { useCommissioningPackageContext } from "../../hooks/useCommissioningPackageContext.tsx"; import ToolContext from "../../context/ToolContext.ts"; import CommissioningPackageCreationDialog from "./CommissioningPackageCreationDialog.tsx"; +import CommissioningPackageDeletionDialog from "./CommissioningPackageDeletionDialog.tsx"; const StyledSideBar = styled.div` height: 100%; @@ -15,6 +16,7 @@ export default function EditorSidebar() { const context = useCommissioningPackageContext(); const { activeTool, setActiveTool } = useContext(ToolContext); const [isCreationOpen, setIsCreationOpen] = useState(false); + const [isDeleteOpen, setIsDeleteOpen] = useState(false); const menuItemsInitial: SidebarLinkProps[] = [ { @@ -33,13 +35,25 @@ export default function EditorSidebar() { }, active: activeTool === Tools.INSIDEBOUNDARY, }, + { + label: "Delete commissioning packages", + icon: delete_to_trash, + onClick: () => { + setIsDeleteOpen(true); + }, + }, ]; + return ( <> + setIsDeleteOpen(false)} + /> diff --git a/www/src/context/CommissioningPackageContext.tsx b/www/src/context/CommissioningPackageContext.tsx index 1cdf76cf..b55f0677 100644 --- a/www/src/context/CommissioningPackageContext.tsx +++ b/www/src/context/CommissioningPackageContext.tsx @@ -1,6 +1,7 @@ import React, { createContext, useEffect, useState } from "react"; import CommissioningPackage from "../types/CommissioningPackage.ts"; import HighlightColors from "../enums/HighlightColors.ts"; +import { deletePackageFromTripleStore } from "../utils/Triplestore.ts"; export interface CommissioningPackageContextProps { activePackage: CommissioningPackage; @@ -9,26 +10,28 @@ export interface CommissioningPackageContextProps { setCommissioningPackages: React.Dispatch< React.SetStateAction >; + deleteCommissioningPackage: (packageId: string) => void; + createInitialPackage: () => CommissioningPackage; } const CommissioningPackageContext = createContext< CommissioningPackageContextProps | undefined >(undefined); +export const createInitialPackage = (): CommissioningPackage => ({ + id: "asset:Package1", + name: "Initial Package", + color: HighlightColors.LASER_LEMON, + boundaryIds: [], + internalIds: [], + nodeIds: [], +}); + export const CommissioningPackageContextProvider: React.FC<{ children: React.ReactNode; }> = ({ children }) => { - const [activePackage, setActivePackage] = useState({ - id: "asset:Package1", - name: "Initial Package", - color: HighlightColors.LASER_LEMON, - boundaryIds: [], - internalIds: [], - nodeIds: [], - }); - const [commissioningPackages, setCommissioningPackages] = useState< - CommissioningPackage[] - >([]); + const [activePackage, setActivePackage] = useState(createInitialPackage()); + const [commissioningPackages, setCommissioningPackages] = useState([]); useEffect(() => { if (activePackage && commissioningPackages.length === 0) { @@ -36,6 +39,42 @@ export const CommissioningPackageContextProvider: React.FC<{ } }, [activePackage, commissioningPackages]); + const deleteCommissioningPackage = async (packageId: string) => { + await deletePackageFromTripleStore(packageId); + + if (commissioningPackages.length === 1) { + const initialPackage = createInitialPackage(); + setCommissioningPackages([initialPackage]); + setActivePackage(initialPackage); + } else { + setCommissioningPackages((prevPackages) => { + const updatedPackages = prevPackages.filter((pkg) => pkg.id !== packageId); + if (activePackage.id === packageId) { + setActivePackage(updatedPackages[0]); + } + return updatedPackages; + }); + } + + setCommissioningPackages((prevPackages) => + prevPackages.map((pkg) => ({ + ...pkg, + boundaryIds: pkg.boundaryIds.filter((id) => id !== packageId), + internalIds: pkg.internalIds.filter((id) => id !== packageId), + nodeIds: pkg.nodeIds.filter((id) => id !== packageId), + })) + ); + + if (activePackage.id === packageId) { + setActivePackage((prevPackage) => ({ + ...prevPackage, + boundaryIds: [], + internalIds: [], + nodeIds: [], + })); + } + }; + return ( {children} diff --git a/www/src/utils/Triplestore.ts b/www/src/utils/Triplestore.ts index ef83542b..ed8210c8 100644 --- a/www/src/utils/Triplestore.ts +++ b/www/src/utils/Triplestore.ts @@ -30,6 +30,13 @@ export async function cleanTripleStore() { await queryTripleStore(deleteInternal, Method.Post); } +export async function deletePackageFromTripleStore(packageId: string) { + const deleteBoundary = "DELETE WHERE { ?boundary comp:isBoundaryOf " + packageId + " . }"; + const deleteInternal = "DELETE WHERE { ?internal comp:isInPackage " + packageId + " . }"; + await queryTripleStore(deleteBoundary, Method.Post); + await queryTripleStore(deleteInternal, Method.Post); +} + export async function getNodeIdsInCommissioningPackage(packageIri: string) { const query = "SELECT ?node WHERE{?node comp:isInPackage " + packageIri + " .}";