diff --git a/src/client/public/locale/de/common.json b/src/client/public/locale/de/common.json index a4af2d2b6..863bb5aeb 100644 --- a/src/client/public/locale/de/common.json +++ b/src/client/public/locale/de/common.json @@ -376,6 +376,7 @@ "section_name": "Sektionsname", "sections": "Sektionen", "selectAll": "Alle auswählen", + "selectWorkgroupToCreateCopy": "Wählen Sie eine Arbeitsgruppe aus, um eine Kopie zu erstellen.", "selectedCount": "{{count}} ausgewählt", "show": "{{what}} anzeigen", "showAll": "Alle anzeigen", diff --git a/src/client/public/locale/en/common.json b/src/client/public/locale/en/common.json index 84869af63..7c15ed2cf 100644 --- a/src/client/public/locale/en/common.json +++ b/src/client/public/locale/en/common.json @@ -377,6 +377,7 @@ "section_name": "Section name", "sections": "Sections", "selectAll": "Select all", + "selectWorkgroupToCreateCopy": "Select a workgroup to create a copy.", "selectedCount": "{{count}} selected", "show": "Show {{what}}", "showAll": "Show all", diff --git a/src/client/public/locale/fr/common.json b/src/client/public/locale/fr/common.json index 619605fd9..c72a14fe2 100644 --- a/src/client/public/locale/fr/common.json +++ b/src/client/public/locale/fr/common.json @@ -376,6 +376,7 @@ "section_name": "Nom de la section", "sections": "Sections", "selectAll": "Tout sélectionner", + "selectWorkgroupToCreateCopy": "Sélectionnez le groupe de travail pour créer une copie.", "selectedCount": "{{count}} sélectionnés", "show": "Afficher {{what}}", "showAll": "Afficher tout", diff --git a/src/client/public/locale/it/common.json b/src/client/public/locale/it/common.json index 32335de48..65c4e4cc0 100644 --- a/src/client/public/locale/it/common.json +++ b/src/client/public/locale/it/common.json @@ -376,6 +376,7 @@ "section_name": "Nome della sezione", "sections": "Sezioni", "selectAll": "Seleziona tutto", + "selectWorkgroupToCreateCopy": "Seleziona un gruppo di lavoro per creare una copia.", "selectedCount": "{{count}} selezionati", "show": "Mostra {{what}}", "showAll": "Mostra tutti", diff --git a/src/client/src/assets/icons/copy.svg b/src/client/src/assets/icons/copy.svg new file mode 100644 index 000000000..f16cf0e8c --- /dev/null +++ b/src/client/src/assets/icons/copy.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/client/src/components/buttons/buttons.tsx b/src/client/src/components/buttons/buttons.tsx index 21ea91752..6e88326c1 100644 --- a/src/client/src/components/buttons/buttons.tsx +++ b/src/client/src/components/buttons/buttons.tsx @@ -3,7 +3,7 @@ import TranslationText from "../legacyComponents/translationText"; import { Button } from "@mui/material"; import AddIcon from "@mui/icons-material/Add"; import EditIcon from "../../assets/icons/edit.svg?react"; -import CopyIcon from "@mui/icons-material/ContentCopy"; +import CopyIcon from "../../assets/icons/copy.svg?react"; import CloseIcon from "@mui/icons-material/Close"; import SaveIcon from "@mui/icons-material/Save"; import TrashIcon from "../../assets/icons/trash.svg?react"; diff --git a/src/client/src/components/prompt/prompt.tsx b/src/client/src/components/prompt/prompt.tsx index d2ba557de..0ae1b814a 100644 --- a/src/client/src/components/prompt/prompt.tsx +++ b/src/client/src/components/prompt/prompt.tsx @@ -4,14 +4,14 @@ import { PromptContext } from "./promptContext.js"; import { BdmsButton } from "../buttons/buttons.tsx"; export const Prompt = () => { - const { promptIsOpen, message, actions, closePrompt } = useContext(PromptContext); + const { promptIsOpen, message, actions, dialogContent, dialogWidth, closePrompt } = useContext(PromptContext); return ( { }}> {message} + {dialogContent &&
{dialogContent}
}
diff --git a/src/client/src/components/prompt/promptContext.tsx b/src/client/src/components/prompt/promptContext.tsx index 48aa791fb..5a71251bd 100644 --- a/src/client/src/components/prompt/promptContext.tsx +++ b/src/client/src/components/prompt/promptContext.tsx @@ -1,10 +1,12 @@ -import { createContext, FC, useState } from "react"; +import { createContext, FC, ReactNode, useState } from "react"; import { PromptAction, PromptContextInterface, PromptOptions, PromptProviderProps } from "./promptInterface"; export const PromptContext = createContext({ message: "", actions: [], promptIsOpen: false, + dialogContent: null, + dialogWidth: null, showPrompt: () => {}, closePrompt: () => {}, }); @@ -12,10 +14,17 @@ export const PromptContext = createContext({ export const PromptProvider: FC = ({ children }) => { const [prompt, setPrompt] = useState(); - const showPrompt = (message: string, actions: PromptAction[]) => { + const showPrompt = ( + message: string, + actions: PromptAction[], + dialogContent: ReactNode = null, + dialogWidth: string | null = null, + ) => { setPrompt({ message: message, actions: actions, + dialogContent: dialogContent, + dialogWidth: dialogWidth, }); }; @@ -29,6 +38,8 @@ export const PromptProvider: FC = ({ children }) => { promptIsOpen: prompt?.message != null, message: prompt?.message, actions: prompt?.actions, + dialogContent: prompt?.dialogContent, + dialogWidth: prompt?.dialogWidth ?? null, showPrompt, closePrompt, }}> diff --git a/src/client/src/components/prompt/promptInterface.ts b/src/client/src/components/prompt/promptInterface.ts index f17a19e6c..a85cfdf5f 100644 --- a/src/client/src/components/prompt/promptInterface.ts +++ b/src/client/src/components/prompt/promptInterface.ts @@ -15,13 +15,17 @@ export interface PromptAction { export interface PromptContextInterface { message?: string; + dialogContent?: ReactNode; + dialogWidth?: string | null; actions?: PromptAction[]; promptIsOpen: boolean; - showPrompt: (message: string, actions: PromptAction[]) => void; + showPrompt: (message: string, actions: PromptAction[], dialogContent?: ReactNode, dialogWidth?: string) => void; closePrompt: () => void; } export interface PromptOptions { message: string; actions: PromptAction[]; + dialogContent: ReactNode; + dialogWidth: string | null; } diff --git a/src/client/src/pages/detail/form/borehole/geometryImport.jsx b/src/client/src/pages/detail/form/borehole/geometryImport.jsx index af46ec1bd..45f8c99d4 100644 --- a/src/client/src/pages/detail/form/borehole/geometryImport.jsx +++ b/src/client/src/pages/detail/form/borehole/geometryImport.jsx @@ -21,7 +21,7 @@ import { } from "../../../../api/fetchApiV2.js"; import { Controller, FormProvider, useForm, useWatch } from "react-hook-form"; import { FormSelect } from "../../../../components/form/form.js"; -import ContentCopyIcon from "@mui/icons-material/ContentCopy"; +import CopyIcon from "../../../../assets/icons/copy.svg?react"; import { AlertContext } from "../../../../components/alert/alertContext.tsx"; import { StackHalfWidth } from "../../../../components/styledComponents.js"; import { DevTool } from "../../../../../hookformDevtools.ts"; @@ -97,7 +97,7 @@ const GeometryImport = ({ boreholeId }) => { navigator.clipboard.writeText(expectedCSVHeader)}> - + diff --git a/src/client/src/pages/overview/boreholeTable/bottomBar.tsx b/src/client/src/pages/overview/boreholeTable/bottomBar.tsx index f5dfd3587..1820b41bc 100644 --- a/src/client/src/pages/overview/boreholeTable/bottomBar.tsx +++ b/src/client/src/pages/overview/boreholeTable/bottomBar.tsx @@ -1,16 +1,18 @@ -import { useContext } from "react"; +import React, { useContext, useEffect } from "react"; import { Box, Button, Stack, Typography } from "@mui/material"; import ArrowDownIcon from "../../../assets/icons/arrow_down.svg?react"; import ArrowUpIcon from "../../../assets/icons/arrow_up.svg?react"; import TrashIcon from "../../../assets/icons/trash.svg?react"; - +import CopyIcon from "../../../assets/icons/copy.svg?react"; import { BoreholeNumbersPreview } from "./boreholeNumbersPreview.tsx"; import { useTranslation } from "react-i18next"; import { theme } from "../../../AppTheme.ts"; -import { Boreholes } from "../../../api-lib/ReduxStateInterfaces.ts"; +import { Boreholes, ReduxRootState, User } from "../../../api-lib/ReduxStateInterfaces.ts"; import { BulkEditButton, CopyButton, DeleteButton } from "../../../components/buttons/buttons.tsx"; import { GridRowSelectionModel } from "@mui/x-data-grid"; import { PromptContext } from "../../../components/prompt/promptContext.tsx"; +import WorkgroupSelect from "../sidePanelContent/commons/workgroupSelect.tsx"; +import { useSelector } from "react-redux"; interface BottomBarProps { toggleBottomDrawer: (open: boolean) => void; @@ -21,6 +23,8 @@ interface BottomBarProps { search: { filter: string }; onDeleteMultiple: () => void; onCopyBorehole: () => void; + workgroup: number | null; + setWorkgroup: React.Dispatch>; } const BottomBar = ({ @@ -32,15 +36,44 @@ const BottomBar = ({ search, onCopyBorehole, boreholes, + workgroup, + setWorkgroup, }: BottomBarProps) => { const { t } = useTranslation(); const { showPrompt } = useContext(PromptContext); + const user: User = useSelector((state: ReduxRootState) => state.core_user); + const enabledWorkgroups = user.data.workgroups.filter( + w => w.disabled === null && !w.supplier && w.roles.includes("EDIT"), + ); + + function showCopyPromptForSelectedWorkgroup() { + showPrompt( + t("selectWorkgroupToCreateCopy"), + [ + { + label: t("cancel"), + }, + { + label: "copy", + icon: , + variant: "contained", + action: onCopy, + }, + ], + , + "400px", + ); + } + + useEffect(() => { + if (selectionModel.length > 0) showCopyPromptForSelectedWorkgroup(); + }, [workgroup]); function bulkEditSelected() { multipleSelected(selectionModel, search.filter); } - function copySelected() { + function onCopy() { onCopyBorehole(); } @@ -76,7 +109,7 @@ const BottomBar = ({ ) } /> - {selectionModel.length === 1 && } + {selectionModel.length === 1 && showCopyPromptForSelectedWorkgroup()} />} {t("selectedCount", { count: selectionModel.length })} diff --git a/src/client/src/pages/overview/boreholeTable/bottomBarContainer.tsx b/src/client/src/pages/overview/boreholeTable/bottomBarContainer.tsx index 176e2cc83..4d31aa377 100644 --- a/src/client/src/pages/overview/boreholeTable/bottomBarContainer.tsx +++ b/src/client/src/pages/overview/boreholeTable/bottomBarContainer.tsx @@ -1,5 +1,4 @@ import { useCallback, useContext, useEffect, useState } from "react"; -import { useSelector } from "react-redux"; import { useHistory } from "react-router-dom"; import { BoreholeTable } from "./boreholeTable.tsx"; import BottomBar from "./bottomBar.tsx"; @@ -9,6 +8,7 @@ import { Boreholes, ReduxRootState, User } from "../../../api-lib/ReduxStateInte import { FilterContext } from "../sidePanelContent/filter/filterContext.tsx"; import { deleteBoreholes } from "../../../api-lib"; import { copyBorehole } from "../../../api/fetchApiV2"; +import { useSelector } from "react-redux"; interface BottomBarContainerProps { boreholes: Boreholes; @@ -34,6 +34,8 @@ const BottomBarContainer = ({ onHover, rowToHighlight, }: BottomBarContainerProps) => { + const user: User = useSelector((state: ReduxRootState) => state.core_user); + const [workgroupId, setWorkgroupId] = useState(user.data.workgroups[0]?.id); const [isBusy, setIsBusy] = useState(false); const [bottomDrawerOpen, setBottomDrawerOpen] = useState(false); const [paginationModel, setPaginationModel] = useState({ @@ -51,8 +53,6 @@ const BottomBarContainer = ({ const history = useHistory(); - const user: User = useSelector((state: ReduxRootState) => state.core_user); - const reloadBoreholes = useCallback(() => { loadEditingBoreholes( paginationModel.page + 1, // MUI Datagrid pagination starts at 0, whereas server pagination starts at 1 @@ -70,8 +70,7 @@ const BottomBarContainer = ({ const onCopyBorehole = async () => { setIsBusy(true); - const workgroup = user.data.workgroups.filter(w => w.disabled === null && !w.supplier && w.roles.includes("EDIT")); - const newBoreholeId = await copyBorehole(selectionModel, workgroup[0].id); + const newBoreholeId = await copyBorehole(selectionModel, workgroupId); setIsBusy(false); history.push(`/${newBoreholeId}/borehole`); }; @@ -100,6 +99,8 @@ const BottomBarContainer = ({ onDeleteMultiple={onDeleteMultiple} search={search} boreholes={boreholes} + workgroup={workgroupId} + setWorkgroup={setWorkgroupId} />