Can delete multiple movements
This commit is contained in:
parent
53494210af
commit
a24eb02dc4
@ -9,7 +9,7 @@ import {
|
|||||||
import React, { PropsWithChildren } from "react";
|
import React, { PropsWithChildren } from "react";
|
||||||
|
|
||||||
type ConfirmContext = (
|
type ConfirmContext = (
|
||||||
message: string,
|
message: string | React.ReactElement,
|
||||||
title?: string,
|
title?: string,
|
||||||
confirmButton?: string
|
confirmButton?: string
|
||||||
) => Promise<boolean>;
|
) => Promise<boolean>;
|
||||||
@ -22,7 +22,7 @@ export function ConfirmDialogProvider(
|
|||||||
const [open, setOpen] = React.useState(false);
|
const [open, setOpen] = React.useState(false);
|
||||||
|
|
||||||
const [title, setTitle] = React.useState<string | undefined>(undefined);
|
const [title, setTitle] = React.useState<string | undefined>(undefined);
|
||||||
const [message, setMessage] = React.useState("");
|
const [message, setMessage] = React.useState<string | React.ReactElement>("");
|
||||||
const [confirmButton, setConfirmButton] = React.useState<string | undefined>(
|
const [confirmButton, setConfirmButton] = React.useState<string | undefined>(
|
||||||
undefined
|
undefined
|
||||||
);
|
);
|
||||||
@ -53,13 +53,13 @@ export function ConfirmDialogProvider(
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ConfirmContextK value={hook}>
|
<ConfirmContextK value={hook}>{p.children}</ConfirmContextK>
|
||||||
{p.children}
|
|
||||||
</ConfirmContextK>
|
|
||||||
|
|
||||||
<Dialog
|
<Dialog
|
||||||
open={open}
|
open={open}
|
||||||
onClose={() => { handleClose(false); }}
|
onClose={() => {
|
||||||
|
handleClose(false);
|
||||||
|
}}
|
||||||
aria-labelledby="alert-dialog-title"
|
aria-labelledby="alert-dialog-title"
|
||||||
aria-describedby="alert-dialog-description"
|
aria-describedby="alert-dialog-description"
|
||||||
onKeyUp={keyUp}
|
onKeyUp={keyUp}
|
||||||
@ -71,10 +71,20 @@ export function ConfirmDialogProvider(
|
|||||||
</DialogContentText>
|
</DialogContentText>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
<Button onClick={() => { handleClose(false); }} autoFocus>
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
handleClose(false);
|
||||||
|
}}
|
||||||
|
autoFocus
|
||||||
|
>
|
||||||
Cancel
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
<Button onClick={() => { handleClose(true); }} color="error">
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
handleClose(true);
|
||||||
|
}}
|
||||||
|
color="error"
|
||||||
|
>
|
||||||
{confirmButton ?? "Confirm"}
|
{confirmButton ?? "Confirm"}
|
||||||
</Button>
|
</Button>
|
||||||
</DialogActions>
|
</DialogActions>
|
||||||
|
@ -1,7 +1,12 @@
|
|||||||
import DeleteIcon from "@mui/icons-material/DeleteOutlined";
|
import DeleteIcon from "@mui/icons-material/DeleteOutlined";
|
||||||
import DriveFileMoveOutlineIcon from "@mui/icons-material/DriveFileMoveOutline";
|
import DriveFileMoveOutlineIcon from "@mui/icons-material/DriveFileMoveOutline";
|
||||||
import { Tooltip, Typography } from "@mui/material";
|
import { IconButton, Tooltip, Typography } from "@mui/material";
|
||||||
import { DataGrid, GridActionsCellItem, GridColDef } from "@mui/x-data-grid";
|
import {
|
||||||
|
DataGrid,
|
||||||
|
GridActionsCellItem,
|
||||||
|
GridColDef,
|
||||||
|
GridRowSelectionModel,
|
||||||
|
} from "@mui/x-data-grid";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import { Movement, MovementApi } from "../api/MovementsApi";
|
import { Movement, MovementApi } from "../api/MovementsApi";
|
||||||
@ -93,9 +98,13 @@ function MovementsTable(p: {
|
|||||||
const alert = useAlert();
|
const alert = useAlert();
|
||||||
const confirm = useConfirm();
|
const confirm = useConfirm();
|
||||||
const snackbar = useSnackbar();
|
const snackbar = useSnackbar();
|
||||||
|
const loadingMessage = useLoadingMessage();
|
||||||
|
|
||||||
const chooseAccount = useSelectAccount();
|
const chooseAccount = useSelectAccount();
|
||||||
|
|
||||||
|
const [rowSelectionModel, setRowSelectionModel] =
|
||||||
|
React.useState<GridRowSelectionModel>([]);
|
||||||
|
|
||||||
// Change account of movement
|
// Change account of movement
|
||||||
const handleMoveClick = async (movement: Movement) => {
|
const handleMoveClick = async (movement: Movement) => {
|
||||||
const target = await chooseAccount(
|
const target = await chooseAccount(
|
||||||
@ -143,6 +152,46 @@ function MovementsTable(p: {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Delete multiple movements
|
||||||
|
const deleteMultiple = async () => {
|
||||||
|
try {
|
||||||
|
const movements = p.movements.filter((m) =>
|
||||||
|
rowSelectionModel.includes(m.id)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (
|
||||||
|
!(await confirm(
|
||||||
|
<>
|
||||||
|
Do you really want to delete the following movements:
|
||||||
|
<ul>
|
||||||
|
{movements.map((m) => (
|
||||||
|
<li>
|
||||||
|
{m.label} ({m.amount} €)
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</>
|
||||||
|
))
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (const [num, m] of movements.entries()) {
|
||||||
|
loadingMessage.show(`Deleting movement ${num}/${movements.length}`);
|
||||||
|
|
||||||
|
await MovementApi.Delete(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
snackbar("The movements have been successfully deleted!");
|
||||||
|
|
||||||
|
p.needReload(false);
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Failed to delete multiple movements!", e);
|
||||||
|
alert(`Failed to delete multiple movements! ${e}`);
|
||||||
|
} finally {
|
||||||
|
loadingMessage.hide();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const columns: GridColDef<(typeof p.movements)[number]>[] = [
|
const columns: GridColDef<(typeof p.movements)[number]>[] = [
|
||||||
{
|
{
|
||||||
field: "checked",
|
field: "checked",
|
||||||
@ -221,33 +270,53 @@ function MovementsTable(p: {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DataGrid<Movement>
|
<>
|
||||||
columns={columns}
|
<div>
|
||||||
rows={p.movements}
|
<Tooltip title="Delete all the selected entries">
|
||||||
autoPageSize
|
<IconButton
|
||||||
checkboxSelection
|
disabled={
|
||||||
initialState={{
|
rowSelectionModel.length === 0 ||
|
||||||
sorting: {
|
rowSelectionModel.length === p.movements.length
|
||||||
sortModel: [{ field: "time", sort: "desc" }],
|
}
|
||||||
},
|
onClick={deleteMultiple}
|
||||||
columns: {
|
>
|
||||||
columnVisibilityModel: {
|
<DeleteIcon />
|
||||||
checked: false,
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
<DataGrid<Movement>
|
||||||
|
columns={columns}
|
||||||
|
rows={p.movements}
|
||||||
|
autoPageSize
|
||||||
|
checkboxSelection
|
||||||
|
initialState={{
|
||||||
|
sorting: {
|
||||||
|
sortModel: [{ field: "time", sort: "desc" }],
|
||||||
},
|
},
|
||||||
},
|
columns: {
|
||||||
}}
|
columnVisibilityModel: {
|
||||||
processRowUpdate={async (n) => {
|
checked: false,
|
||||||
try {
|
},
|
||||||
return await MovementApi.Update(n);
|
},
|
||||||
} catch (e) {
|
}}
|
||||||
console.error("Failed to update movement information!", e);
|
onRowSelectionModelChange={(newRowSelectionModel) => {
|
||||||
alert(`Failed to update row! ${e}`);
|
setRowSelectionModel(newRowSelectionModel);
|
||||||
throw e;
|
}}
|
||||||
} finally {
|
rowSelectionModel={rowSelectionModel}
|
||||||
p.needReload(true);
|
processRowUpdate={async (n) => {
|
||||||
}
|
try {
|
||||||
}}
|
return await MovementApi.Update(n);
|
||||||
/>
|
} catch (e) {
|
||||||
|
console.error("Failed to update movement information!", e);
|
||||||
|
alert(`Failed to update row! ${e}`);
|
||||||
|
throw e;
|
||||||
|
} finally {
|
||||||
|
p.needReload(true);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user