Display info of uploaded files
This commit is contained in:
@ -39,6 +39,11 @@ pub async fn upload(auth: AuthExtractor, file: FileExtractor) -> HttpResult {
|
||||
Ok(HttpResponse::Ok().json(file))
|
||||
}
|
||||
|
||||
/// Get information about a file
|
||||
pub async fn get_info(file_extractor: FileIdExtractor) -> HttpResult {
|
||||
Ok(HttpResponse::Ok().json(file_extractor.as_ref()))
|
||||
}
|
||||
|
||||
/// Download an uploaded file
|
||||
pub async fn download(req: HttpRequest, file_extractor: FileIdExtractor) -> HttpResult {
|
||||
serve_file(req, file_extractor.as_ref()).await
|
||||
|
@ -123,6 +123,10 @@ async fn main() -> std::io::Result<()> {
|
||||
.route("/api/file", web::post().to(files_controller::upload))
|
||||
.route(
|
||||
"/api/file/{file_id}",
|
||||
web::get().to(files_controller::get_info),
|
||||
)
|
||||
.route(
|
||||
"/api/file/{file_id}/download",
|
||||
web::get().to(files_controller::download),
|
||||
)
|
||||
.route(
|
||||
|
10
moneymgr_web/package-lock.json
generated
10
moneymgr_web/package-lock.json
generated
@ -20,6 +20,7 @@
|
||||
"@mui/x-date-pickers": "^8.0.0-beta.3",
|
||||
"date-and-time": "^3.6.0",
|
||||
"dayjs": "^1.11.13",
|
||||
"filesize": "^10.1.6",
|
||||
"qrcode.react": "^4.2.0",
|
||||
"react": "^19.1.0",
|
||||
"react-dom": "^19.1.0",
|
||||
@ -3148,6 +3149,15 @@
|
||||
"node": ">=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/filesize": {
|
||||
"version": "10.1.6",
|
||||
"resolved": "https://registry.npmjs.org/filesize/-/filesize-10.1.6.tgz",
|
||||
"integrity": "sha512-sJslQKU2uM33qH5nqewAwVB2QgR6w1aMNsYUp3aN5rMRyXEwJGmZvaWzeJFNTOXWlHQyBFCWrdj3fV/fsTOX8w==",
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">= 10.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fill-range": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
||||
|
@ -22,6 +22,7 @@
|
||||
"@mui/x-date-pickers": "^8.0.0-beta.3",
|
||||
"date-and-time": "^3.6.0",
|
||||
"dayjs": "^1.11.13",
|
||||
"filesize": "^10.1.6",
|
||||
"qrcode.react": "^4.2.0",
|
||||
"react": "^19.1.0",
|
||||
"react-dom": "^19.1.0",
|
||||
|
@ -25,4 +25,16 @@ export class FileApi {
|
||||
})
|
||||
).data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a file information
|
||||
*/
|
||||
static async GetFile(id: number): Promise<UploadedFile> {
|
||||
return (
|
||||
await APIClient.exec({
|
||||
method: "GET",
|
||||
uri: `/file/${id}`,
|
||||
})
|
||||
).data;
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ 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";
|
||||
|
||||
export function AccountRoute(): React.ReactElement {
|
||||
const loadingMessage = useLoadingMessage();
|
||||
@ -281,7 +282,7 @@ function MovementsTable(p: {
|
||||
{
|
||||
field: "label",
|
||||
headerName: "Label",
|
||||
flex: 1,
|
||||
flex: 3,
|
||||
editable: true,
|
||||
type: "string",
|
||||
},
|
||||
@ -301,7 +302,7 @@ function MovementsTable(p: {
|
||||
field: "file",
|
||||
headerName: "File",
|
||||
editable: false,
|
||||
width: 150,
|
||||
flex: 1,
|
||||
renderCell: (params) => {
|
||||
if (!params.row.file_id)
|
||||
return (
|
||||
@ -311,7 +312,7 @@ function MovementsTable(p: {
|
||||
onUploaded={(f) => setUploadedFile(params.row, f)}
|
||||
/>
|
||||
);
|
||||
else return <>got file</>;
|
||||
else return <UploadedFileWidget file_id={params.row.file_id} />;
|
||||
},
|
||||
},
|
||||
{
|
||||
|
42
moneymgr_web/src/widgets/UploadedFileWidget.tsx
Normal file
42
moneymgr_web/src/widgets/UploadedFileWidget.tsx
Normal file
@ -0,0 +1,42 @@
|
||||
import ImageIcon from "@mui/icons-material/Image";
|
||||
import PictureAsPdfIcon from "@mui/icons-material/PictureAsPdf";
|
||||
import { Button } from "@mui/material";
|
||||
import { filesize } from "filesize";
|
||||
import React from "react";
|
||||
import { FileApi, UploadedFile } from "../api/FileApi";
|
||||
import { AsyncWidget } from "./AsyncWidget";
|
||||
|
||||
export function UploadedFileWidget(p: { file_id: number }): React.ReactElement {
|
||||
const [file, setFile] = React.useState<UploadedFile | null>(null);
|
||||
|
||||
const load = async () => {
|
||||
setFile(await FileApi.GetFile(p.file_id));
|
||||
};
|
||||
|
||||
return (
|
||||
<AsyncWidget
|
||||
errMsg="Failed"
|
||||
build={() => <UploadedFileWidgetInner file={file!} />}
|
||||
loadKey={p.file_id}
|
||||
load={load}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function UploadedFileWidgetInner(p: {
|
||||
file: UploadedFile;
|
||||
}): React.ReactElement {
|
||||
return (
|
||||
<Button
|
||||
startIcon={
|
||||
p.file.mime_type === "application/pdf" ? (
|
||||
<PictureAsPdfIcon />
|
||||
) : (
|
||||
<ImageIcon />
|
||||
)
|
||||
}
|
||||
>
|
||||
{p.file.file_name} ({filesize(p.file.file_size)})
|
||||
</Button>
|
||||
);
|
||||
}
|
Reference in New Issue
Block a user