From 76f9e37dedcb9f3a7ff7967fddfc043f6eea1ee5 Mon Sep 17 00:00:00 2001 From: Pierre HUBERT Date: Mon, 12 May 2025 19:13:14 +0200 Subject: [PATCH] Display the list of inbox entries --- moneymgr_web/src/api/InboxApi.ts | 15 ++++ moneymgr_web/src/routes/InboxRoute.tsx | 109 +++++++++++++++++++++++-- 2 files changed, 118 insertions(+), 6 deletions(-) diff --git a/moneymgr_web/src/api/InboxApi.ts b/moneymgr_web/src/api/InboxApi.ts index e5f491c..9394755 100644 --- a/moneymgr_web/src/api/InboxApi.ts +++ b/moneymgr_web/src/api/InboxApi.ts @@ -54,4 +54,19 @@ export class InboxApi { }) ).data; } + + /** + * Update inbox entry + */ + static async Update( + inbox: InboxEntry & InboxEntryUpdate + ): Promise { + return ( + await APIClient.exec({ + uri: `/inbox/${inbox.id}`, + method: "PUT", + jsonData: inbox, + }) + ).data; + } } diff --git a/moneymgr_web/src/routes/InboxRoute.tsx b/moneymgr_web/src/routes/InboxRoute.tsx index 96dce97..217d1ce 100644 --- a/moneymgr_web/src/routes/InboxRoute.tsx +++ b/moneymgr_web/src/routes/InboxRoute.tsx @@ -1,13 +1,17 @@ import RefreshIcon from "@mui/icons-material/Refresh"; import { Checkbox, FormControlLabel, IconButton, Tooltip } from "@mui/material"; +import { DataGrid, GridColDef, GridRowSelectionModel } from "@mui/x-data-grid"; import React from "react"; import { InboxApi, InboxEntry } from "../api/InboxApi"; import { useAlert } from "../hooks/context_providers/AlertDialogProvider"; import { useLoadingMessage } from "../hooks/context_providers/LoadingMessageProvider"; +import { useUnmatchedInboxEntriesCount } from "../hooks/UnmatchedInboxEntriesCountProvider"; +import { AmountWidget } from "../widgets/AmountWidget"; import { AsyncWidget } from "../widgets/AsyncWidget"; +import { DateWidget } from "../widgets/DateWidget"; import { MoneyMgrWebRouteContainer } from "../widgets/MoneyMgrWebRouteContainer"; import { NewMovementWidget } from "../widgets/NewMovementWidget"; -import { useUnmatchedInboxEntriesCount } from "../hooks/UnmatchedInboxEntriesCountProvider"; +import { UploadedFileWidget } from "../widgets/UploadedFileWidget"; export function InboxRoute(): React.ReactElement { const loadingMessage = useLoadingMessage(); @@ -46,9 +50,8 @@ export function InboxRoute(): React.ReactElement { checked={includeAttached} control={ { - setIncludeAttached(e.target.checked); - reload(false); + onChange={(_e, value) => { + setIncludeAttached(value); }} /> } @@ -65,10 +68,10 @@ export function InboxRoute(): React.ReactElement {
<>todo table} + build={() => } /> reload(false)} />
@@ -76,3 +79,97 @@ export function InboxRoute(): React.ReactElement { ); } + +function InboxTable(p: { + entries: InboxEntry[]; + onReload: (skipEntries: boolean) => void; +}): React.ReactElement { + const [rowSelectionModel, setRowSelectionModel] = + React.useState([]); + + const columns: GridColDef<(typeof p.entries)[number]>[] = [ + { + field: "time", + headerName: "Date", + width: 98 + 80, + editable: true, + type: "dateTime", + valueGetter(_, m) { + return new Date(m.time * 1000); + }, + valueSetter(v, row) { + row.time = Math.floor(v.getTime() / 1000); + return row; + }, + renderCell: (params) => { + return ; + }, + }, + { + field: "label", + headerName: "Label", + flex: 3, + editable: true, + type: "string", + }, + { + field: "amount", + headerName: "Amount", + width: 110, + editable: true, + type: "number", + align: "left", + headerAlign: "left", + renderCell: (params) => { + if (params.row.amount) + return ; + else return Unspecified; + }, + }, + { + field: "file", + headerName: "File", + editable: false, + flex: 3, + renderCell: (params) => { + return ; + }, + }, + ]; + + return ( +
+ + columns={columns} + rows={p.entries} + autoPageSize + checkboxSelection + initialState={{ + sorting: { + sortModel: [{ field: "time", sort: "desc" }], + }, + columns: { + columnVisibilityModel: { + checked: false, + }, + }, + }} + onRowSelectionModelChange={(newRowSelectionModel) => { + setRowSelectionModel(newRowSelectionModel); + }} + rowSelectionModel={rowSelectionModel} + processRowUpdate={async (n) => { + try { + return await InboxApi.Update(n); + } catch (e) { + console.error("Failed to update movement information!", e); + alert(`Failed to update row! ${e}`); + throw e; + } finally { + p.onReload(true); + } + }} + /> +
+ ); +}