Skip to content

Commit

Permalink
Merge branch 'main' into add-tvd-and-custom-ids
Browse files Browse the repository at this point in the history
  • Loading branch information
MiraGeowerkstatt authored Dec 17, 2024
2 parents 9304498 + f780876 commit 3e371cc
Show file tree
Hide file tree
Showing 14 changed files with 286 additions and 210 deletions.
4 changes: 3 additions & 1 deletion src/client/cypress/e2e/detailPage/boreholeform.cy.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { exportCSVItem, exportJsonItem, saveWithSaveBar } from "../helpers/buttonHelpers";
import { exportCSVItem, exportItem, exportJsonItem, saveWithSaveBar } from "../helpers/buttonHelpers";
import { clickOnRowWithText, showTableAndWaitForData, sortBy } from "../helpers/dataGridHelpers";
import { evaluateInput, evaluateSelect, isDisabled, setInput, setSelect } from "../helpers/formHelpers";
import {
Expand Down Expand Up @@ -248,7 +248,9 @@ describe("Test for the borehole form.", () => {
cy.get("@borehole_id").then(id => {
goToRouteAndAcceptTerms(`/${id}`);
ensureEditingDisabled();
exportItem();
exportJsonItem();
exportItem();
exportCSVItem();
});

Expand Down
13 changes: 11 additions & 2 deletions src/client/cypress/e2e/helpers/buttonHelpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,20 @@ export const deleteItem = parent => {
cy.get(selector).click({ force: true });
};

/**
* Clicks on the Export button.
*/
export const exportItem = () => {
const selector = '[data-cy="export-button"]';
cy.get(selector).should("not.be.disabled");
cy.get(selector).click({ force: true });
};

/**
* Clicks on the JSON-export button.
*/
export const exportJsonItem = () => {
const selector = '[data-cy="exportjson-button"]';
const selector = '[data-cy="json-button"]';
cy.get(selector).should("not.be.disabled");
cy.get(selector).click({ force: true });
};
Expand All @@ -72,7 +81,7 @@ export const exportJsonItem = () => {
* Clicks on the CSV-export button.
*/
export const exportCSVItem = () => {
const selector = '[data-cy="exportcsv-button"]';
const selector = '[data-cy="csv-button"]';
cy.get(selector).should("not.be.disabled");
cy.get(selector).click({ force: true });
};
Expand Down
17 changes: 11 additions & 6 deletions src/client/cypress/e2e/mainPage/export.cy.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { addItem, deleteItem, exportCSVItem, exportJsonItem, saveWithSaveBar } from "../helpers/buttonHelpers";
import { deleteItem, exportCSVItem, exportItem, exportJsonItem } from "../helpers/buttonHelpers";
import { checkAllVisibleRows, checkRowWithText, showTableAndWaitForData } from "../helpers/dataGridHelpers.js";
import { evaluateInput, setInput, setSelect } from "../helpers/formHelpers";
import {
Expand Down Expand Up @@ -58,7 +58,11 @@ describe("Test for exporting boreholes.", () => {
checkRowWithText("AAA_NINTIC");
checkRowWithText("AAA_LOMONE");

deleteDownloadedFile(jsonFileName);
deleteDownloadedFile(csvFileName);
exportItem();
exportJsonItem();
exportItem();
exportCSVItem();
readDownloadedFile(jsonFileName);
readDownloadedFile(csvFileName);
Expand Down Expand Up @@ -187,14 +191,15 @@ describe("Test for exporting boreholes.", () => {
deleteDownloadedFile(jsonFileName);
showTableAndWaitForData();
checkAllVisibleRows();
exportCSVItem();
deleteDownloadedFile(csvFileName);
exportItem();

const moreThan100SelectedPrompt =
"You have selected more than 100 boreholes and a maximum of 100 boreholes can be exported. Do you want to continue?";
handlePrompt(moreThan100SelectedPrompt, "Cancel");
cy.get("@borehole_export_csv").should("not.exist");
exportCSVItem();
exportItem();
handlePrompt(moreThan100SelectedPrompt, "Export 100 boreholes");
exportCSVItem();
cy.wait("@borehole_export_csv").its("response.statusCode").should("eq", 200);
readDownloadedFile(csvFileName);

Expand All @@ -203,7 +208,7 @@ describe("Test for exporting boreholes.", () => {
const lines = fileContent.split("\n");
expect(lines.length).to.equal(102);
});
exportJsonItem();
handlePrompt(moreThan100SelectedPrompt, "Cancel");

deleteDownloadedFile(jsonFileName);
});
});
1 change: 1 addition & 0 deletions src/client/public/locale/de/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@
"maxValue": "Maximalwert",
"member": "Member",
"messageDiscardUnsavedChanges": "Es gibt ungespeicherte Änderungen. Möchten Sie alle Änderungen verwerfen?",
"messageUnsavedChangesAtExport": "Es gibt ungespeicherte Änderungen. Möchten Sie das Bohrloch ohne Speichern exportieren?",
"meter": "Meter",
"minValue": "Minimalwert",
"minute": "Minute",
Expand Down
1 change: 1 addition & 0 deletions src/client/public/locale/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@
"maxValue": "Maximum",
"member": "Member",
"messageDiscardUnsavedChanges": "There are unsaved changes. Do you want to discard all changes?",
"messageUnsavedChangesAtExport": "There are unsaved changes. Do you want to export the borehole without saving?",
"meter": "Meter",
"minValue": "Minimum",
"minute": "minute",
Expand Down
1 change: 1 addition & 0 deletions src/client/public/locale/fr/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@
"maxValue": "Valeur maximale",
"member": "Membre",
"messageDiscardUnsavedChanges": "Il y a des modifications non enregistrées. Voulez-vous annuler toutes les modifications?",
"messageUnsavedChangesAtExport": "Il y a des modifications non enregistrées. Voulez-vous exporter le forage sans enregistrer?",
"meter": "Mètres",
"minValue": "Valeur minimale",
"minute": "minute",
Expand Down
1 change: 1 addition & 0 deletions src/client/public/locale/it/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@
"maxValue": "Valore massimo",
"member": "Membro",
"messageDiscardUnsavedChanges": "Sono presenti modifiche non salvate. Si desidera annullare tutte le modifiche?",
"messageUnsavedChangesAtExport": "Ci sono modifiche non salvate. Si desidera esportare la perforazione senza salvare?",
"meter": "Metri",
"minValue": "Valore minimo",
"minute": "minuto",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { GridRowSelectionModel } from "@mui/x-data-grid";
import { FormValueType } from "../../form/form.ts";
import { FormValueType } from "../form/form.ts";

export interface BulkEditFormProps {
selected: GridRowSelectionModel;
loadBoreholes: () => void;
isOpen: boolean;
}

export type BulkEditFormValue = string | number | boolean | undefined | null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
AccordionDetails,
AccordionSummary,
Box,
Dialog,
DialogActions,
DialogContent,
DialogTitle,
Expand All @@ -15,20 +16,20 @@ import {
Typography,
} from "@mui/material";
import { ChevronDownIcon, RotateCcw } from "lucide-react";
import { patchBoreholes } from "../../../api-lib";
import { ReduxRootState, User } from "../../../api-lib/ReduxStateInterfaces.ts";
import { theme } from "../../../AppTheme.ts";
import WorkgroupSelect from "../../../pages/overview/sidePanelContent/commons/workgroupSelect.tsx";
import { AlertContext } from "../../alert/alertContext.tsx";
import { CancelButton, SaveButton } from "../../buttons/buttons";
import { FormValueType } from "../../form/form.ts";
import { FormBooleanSelect } from "../../form/formBooleanSelect.tsx";
import { FormDomainSelect } from "../../form/formDomainSelect.tsx";
import { FormInput } from "../../form/formInput.tsx";
import { StackFullWidth } from "../../styledComponents.ts";
import { patchBoreholes } from "../../api-lib";
import { ReduxRootState, User } from "../../api-lib/ReduxStateInterfaces.ts";
import { theme } from "../../AppTheme.ts";
import WorkgroupSelect from "../../pages/overview/sidePanelContent/commons/workgroupSelect.tsx";
import { AlertContext } from "../alert/alertContext.tsx";
import { CancelButton, SaveButton } from "../buttons/buttons.tsx";
import { FormValueType } from "../form/form.ts";
import { FormBooleanSelect } from "../form/formBooleanSelect.tsx";
import { FormDomainSelect } from "../form/formDomainSelect.tsx";
import { FormInput } from "../form/formInput.tsx";
import { StackFullWidth } from "../styledComponents.ts";
import { BulkEditFormField, BulkEditFormProps, BulkEditFormValue } from "./BulkEditFormProps.ts";

export const BulkEditForm = ({ selected, loadBoreholes }: BulkEditFormProps) => {
export const BulkEditDialog = ({ isOpen, selected, loadBoreholes }: BulkEditFormProps) => {
const [fieldsToUpdate, setFieldsToUpdate] = useState<Array<[string, BulkEditFormValue]>>([]);
const [workgroupId, setWorkgroupId] = useState<string>("");
const { showAlert } = useContext(AlertContext);
Expand Down Expand Up @@ -200,68 +201,82 @@ export const BulkEditForm = ({ selected, loadBoreholes }: BulkEditFormProps) =>
);

return (
<Stack sx={{ height: "100%" }}>
<DialogTitle>
<Typography variant="h1">{t("bulkEditing")}</Typography>
</DialogTitle>
<DialogContent
sx={{
overflowY: "auto",
flexGrow: 1,
}}>
<Box sx={{ mt: 3 }}>
<FormProvider {...formMethods}>
{bulkEditFormFields.map(field => {
if (field.type != FormValueType.Workgroup || enabledWorkgroups.length > 1) {
return (
<Accordion key={field.fieldName} data-cy={"bulk-edit-accordion"} sx={{ minHeight: theme.spacing(6) }}>
<AccordionSummary
expandIcon={<ChevronDownIcon />}
sx={{
pl: 1,
"& .MuiAccordionSummary-content": {
m: 0,
},
}}>
<Stack direction="row" alignItems="center">
<IconButton
size="small"
data-cy="bulk-edit-reset-button"
sx={{
visibility: fieldsToUpdate.map(f => f[0]).includes(field.api ?? field.fieldName)
? "visible"
: "hidden",
mr: 1,
}}
onClick={e => {
e.stopPropagation();
undoChange(field);
}}>
<RotateCcw fontSize="small" color={theme.palette.primary.main} />
</IconButton>
<Typography variant="h6" sx={{ color: "black" }}>
{t(field.fieldName)}
</Typography>
</Stack>
</AccordionSummary>
<AccordionDetails sx={{ pl: 5, pr: 3, mt: -4 }}>
<StackFullWidth>
<>{renderInput(field)}</>
</StackFullWidth>
</AccordionDetails>
</Accordion>
);
}
})}
</FormProvider>
</Box>
</DialogContent>
<DialogActions>
<Stack direction="row" justifyContent="flex-end" spacing={2}>
<CancelButton onClick={unselectBoreholes} />
<SaveButton variant="contained" disabled={fieldsToUpdate.length === 0} onClick={save} />
</Stack>
</DialogActions>
</Stack>
<Dialog
fullWidth
maxWidth="sm"
open={isOpen}
PaperProps={{
sx: {
overflow: "hidden",
height: "90vh",
},
}}>
<Stack sx={{ height: "100%" }}>
<DialogTitle>
<Typography variant="h1">{t("bulkEditing")}</Typography>
</DialogTitle>
<DialogContent
sx={{
overflowY: "auto",
flexGrow: 1,
}}>
<Box sx={{ mt: 3 }}>
<FormProvider {...formMethods}>
{bulkEditFormFields.map(field => {
if (field.type != FormValueType.Workgroup || enabledWorkgroups.length > 1) {
return (
<Accordion
key={field.fieldName}
data-cy={"bulk-edit-accordion"}
sx={{ minHeight: theme.spacing(6) }}>
<AccordionSummary
expandIcon={<ChevronDownIcon />}
sx={{
pl: 1,
"& .MuiAccordionSummary-content": {
m: 0,
},
}}>
<Stack direction="row" alignItems="center">
<IconButton
size="small"
data-cy="bulk-edit-reset-button"
sx={{
visibility: fieldsToUpdate.map(f => f[0]).includes(field.api ?? field.fieldName)
? "visible"
: "hidden",
mr: 1,
}}
onClick={e => {
e.stopPropagation();
undoChange(field);
}}>
<RotateCcw fontSize="small" color={theme.palette.primary.main} />
</IconButton>
<Typography variant="h6" sx={{ color: "black" }}>
{t(field.fieldName)}
</Typography>
</Stack>
</AccordionSummary>
<AccordionDetails sx={{ pl: 5, pr: 3, mt: -4 }}>
<StackFullWidth>
<>{renderInput(field)}</>
</StackFullWidth>
</AccordionDetails>
</Accordion>
);
}
})}
</FormProvider>
</Box>
</DialogContent>
<DialogActions>
<Stack direction="row" justifyContent="flex-end" spacing={2}>
<CancelButton onClick={unselectBoreholes} />
<SaveButton variant="contained" disabled={fieldsToUpdate.length === 0} onClick={save} />
</Stack>
</DialogActions>
</Stack>
</Dialog>
);
};
50 changes: 50 additions & 0 deletions src/client/src/components/export/exportDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { useTranslation } from "react-i18next";
import { Dialog, DialogActions, DialogContent, DialogTitle, Stack, Typography } from "@mui/material";
import { GridRowSelectionModel } from "@mui/x-data-grid";
import { exportCSVBorehole, getAllBoreholes } from "../../api/borehole.ts";
import { downloadData } from "../../utils.ts";
import { CancelButton, ExportButton } from "../buttons/buttons.tsx";

interface ExportDialogProps {
isExporting: boolean;
setIsExporting: React.Dispatch<React.SetStateAction<boolean>>;
selectionModel: GridRowSelectionModel;
fileName: string;
}
export const ExportDialog = ({ isExporting, setIsExporting, selectionModel, fileName }: ExportDialogProps) => {
const { t } = useTranslation();

const exportJson = async () => {
const paginatedResponse = await getAllBoreholes(selectionModel, 1, selectionModel.length);
const jsonString = JSON.stringify(paginatedResponse.boreholes, null, 2);
downloadData(jsonString, `${fileName}.json`, "application/json");
setIsExporting(false);
};

const exportCsv = async () => {
const csvData = await exportCSVBorehole(selectionModel.slice(0, 100));
downloadData(csvData, `${fileName}.csv`, "text/csv");
setIsExporting(false);
};

return (
<Dialog open={isExporting}>
<Stack sx={{ minWidth: "326px" }}>
<DialogTitle>
<Typography variant="h2">{t("export")}</Typography>
</DialogTitle>
<DialogContent>
<Stack gap={1} sx={{ mt: 3 }}>
<ExportButton label={"JSON"} onClick={exportJson} />
<ExportButton label={"CSV"} onClick={exportCsv} />
</Stack>
</DialogContent>
<DialogActions>
<Stack direction="row" justifyContent="flex-end" spacing={2}>
<CancelButton onClick={() => setIsExporting(false)} />
</Stack>
</DialogActions>
</Stack>
</Dialog>
);
};
Loading

0 comments on commit 3e371cc

Please sign in to comment.