Can detach file from movement
This commit is contained in:
parent
a5609d2ebd
commit
bce17bc9b4
@ -1,14 +1,20 @@
|
||||
import DeleteIcon from "@mui/icons-material/DeleteOutlined";
|
||||
import DriveFileMoveOutlineIcon from "@mui/icons-material/DriveFileMoveOutline";
|
||||
import { IconButton, Tooltip, Typography } from "@mui/material";
|
||||
import LinkOffIcon from "@mui/icons-material/LinkOff";
|
||||
import MoreVertIcon from "@mui/icons-material/MoreVert";
|
||||
import {
|
||||
DataGrid,
|
||||
GridActionsCellItem,
|
||||
GridColDef,
|
||||
GridRowSelectionModel,
|
||||
} from "@mui/x-data-grid";
|
||||
IconButton,
|
||||
ListItemIcon,
|
||||
ListItemText,
|
||||
Tooltip,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import Menu from "@mui/material/Menu";
|
||||
import MenuItem from "@mui/material/MenuItem";
|
||||
import { DataGrid, GridColDef, GridRowSelectionModel } from "@mui/x-data-grid";
|
||||
import React from "react";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { UploadedFile } from "../api/FileApi";
|
||||
import { Movement, MovementApi } from "../api/MovementsApi";
|
||||
import { useAccounts } from "../hooks/AccountsListProvider";
|
||||
import { useAlert } from "../hooks/context_providers/AlertDialogProvider";
|
||||
@ -20,12 +26,11 @@ import { AccountWidget } from "../widgets/AccountWidget";
|
||||
import { AmountWidget } from "../widgets/AmountWidget";
|
||||
import { AsyncWidget } from "../widgets/AsyncWidget";
|
||||
import { DateWidget } from "../widgets/DateWidget";
|
||||
import { UploadFileButton } from "../widgets/forms/UploadFileButton";
|
||||
import { MoneyMgrWebRouteContainer } from "../widgets/MoneyMgrWebRouteContainer";
|
||||
import { NewMovementWidget } from "../widgets/NewMovementWidget";
|
||||
import { NotFoundRoute } from "./NotFound";
|
||||
import { UploadFileButton } from "../widgets/forms/UploadFileButton";
|
||||
import { UploadedFile } from "../api/FileApi";
|
||||
import { UploadedFileWidget } from "../widgets/UploadedFileWidget";
|
||||
import { NotFoundRoute } from "./NotFound";
|
||||
|
||||
export function AccountRoute(): React.ReactElement {
|
||||
const loadingMessage = useLoadingMessage();
|
||||
@ -80,7 +85,7 @@ export function AccountRoute(): React.ReactElement {
|
||||
<AsyncWidget
|
||||
loadKey={`${account.id}-${loadKey.current}`}
|
||||
load={load}
|
||||
ready={movements}
|
||||
ready={movements !== undefined}
|
||||
errMsg="Failed to load the list of movements!"
|
||||
build={() => (
|
||||
<MovementsTable needReload={reload} movements={movements!} />
|
||||
@ -148,6 +153,25 @@ function MovementsTable(p: {
|
||||
}
|
||||
};
|
||||
|
||||
// Detach movement from account
|
||||
const handleDetachFile = async (movement: Movement) => {
|
||||
try {
|
||||
if (
|
||||
!(await confirm(
|
||||
`Do you really want to detach the file attached to the movement ${movement.label} (${movement.amount}€)? The associated file will be automatically deleted within the day if it is not referenced anywhere else!`,
|
||||
`Detach file from movement`,
|
||||
`Detach file`
|
||||
))
|
||||
)
|
||||
return;
|
||||
|
||||
await setUploadedFile(movement, undefined);
|
||||
} catch (e) {
|
||||
console.error("Failed to detach file from movement!", e);
|
||||
alert(`Failed to detach file from movement! ${e}`);
|
||||
}
|
||||
};
|
||||
|
||||
// Delete movement
|
||||
const handleDeleteClick = async (movement: Movement) => {
|
||||
try {
|
||||
@ -318,28 +342,19 @@ function MovementsTable(p: {
|
||||
{
|
||||
field: "actions",
|
||||
type: "actions",
|
||||
headerName: "Actions",
|
||||
width: 80,
|
||||
headerName: "",
|
||||
width: 55,
|
||||
cellClassName: "actions",
|
||||
editable: false,
|
||||
getActions: (params) => {
|
||||
return [
|
||||
<Tooltip title="Move to another account" key="move">
|
||||
<GridActionsCellItem
|
||||
icon={<DriveFileMoveOutlineIcon />}
|
||||
label="Move to another account"
|
||||
onClick={() => handleMoveClick(params.row)}
|
||||
color="inherit"
|
||||
/>
|
||||
</Tooltip>,
|
||||
<Tooltip title="Delete the movement" key="delete">
|
||||
<GridActionsCellItem
|
||||
icon={<DeleteIcon color="error" />}
|
||||
label="Delete"
|
||||
onClick={() => handleDeleteClick(params.row)}
|
||||
color="inherit"
|
||||
/>
|
||||
</Tooltip>,
|
||||
<MovementActionMenu
|
||||
key="menu"
|
||||
movement={params.row}
|
||||
onDelete={handleDeleteClick}
|
||||
onMove={handleMoveClick}
|
||||
onDetachFile={handleDetachFile}
|
||||
/>,
|
||||
];
|
||||
},
|
||||
},
|
||||
@ -407,3 +422,74 @@ function MovementsTable(p: {
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function MovementActionMenu(p: {
|
||||
movement: Movement;
|
||||
onDetachFile: (m: Movement) => void;
|
||||
onMove: (m: Movement) => void;
|
||||
onDelete: (m: Movement) => void;
|
||||
}): React.ReactElement {
|
||||
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
|
||||
const open = Boolean(anchorEl);
|
||||
const handleClick = (event: React.MouseEvent<HTMLElement>) => {
|
||||
setAnchorEl(event.currentTarget);
|
||||
};
|
||||
const handleClose = () => {
|
||||
setAnchorEl(null);
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<IconButton
|
||||
aria-label="Actions"
|
||||
aria-haspopup="true"
|
||||
onClick={handleClick}
|
||||
>
|
||||
<MoreVertIcon />
|
||||
</IconButton>
|
||||
<Menu anchorEl={anchorEl} open={open} onClose={handleClose}>
|
||||
{/* Detach file */}
|
||||
{p.movement.file_id && (
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
handleClose();
|
||||
p.onDetachFile(p.movement);
|
||||
}}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<LinkOffIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText secondary={"Detach linked file"}>
|
||||
Detach file
|
||||
</ListItemText>
|
||||
</MenuItem>
|
||||
)}
|
||||
{/* Move to another account */}
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
handleClose();
|
||||
p.onMove(p.movement);
|
||||
}}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<DriveFileMoveOutlineIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText secondary={"Move to another account"}>
|
||||
Move
|
||||
</ListItemText>
|
||||
</MenuItem>
|
||||
{/* Delete */}
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
handleClose();
|
||||
p.onDelete(p.movement);
|
||||
}}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<DeleteIcon color="error" />
|
||||
</ListItemIcon>
|
||||
<ListItemText secondary={"Delete the movement"}>Delete</ListItemText>
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user