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))
|
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
|
/// Download an uploaded file
|
||||||
pub async fn download(req: HttpRequest, file_extractor: FileIdExtractor) -> HttpResult {
|
pub async fn download(req: HttpRequest, file_extractor: FileIdExtractor) -> HttpResult {
|
||||||
serve_file(req, file_extractor.as_ref()).await
|
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", web::post().to(files_controller::upload))
|
||||||
.route(
|
.route(
|
||||||
"/api/file/{file_id}",
|
"/api/file/{file_id}",
|
||||||
|
web::get().to(files_controller::get_info),
|
||||||
|
)
|
||||||
|
.route(
|
||||||
|
"/api/file/{file_id}/download",
|
||||||
web::get().to(files_controller::download),
|
web::get().to(files_controller::download),
|
||||||
)
|
)
|
||||||
.route(
|
.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",
|
"@mui/x-date-pickers": "^8.0.0-beta.3",
|
||||||
"date-and-time": "^3.6.0",
|
"date-and-time": "^3.6.0",
|
||||||
"dayjs": "^1.11.13",
|
"dayjs": "^1.11.13",
|
||||||
|
"filesize": "^10.1.6",
|
||||||
"qrcode.react": "^4.2.0",
|
"qrcode.react": "^4.2.0",
|
||||||
"react": "^19.1.0",
|
"react": "^19.1.0",
|
||||||
"react-dom": "^19.1.0",
|
"react-dom": "^19.1.0",
|
||||||
@ -3148,6 +3149,15 @@
|
|||||||
"node": ">=16.0.0"
|
"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": {
|
"node_modules/fill-range": {
|
||||||
"version": "7.1.1",
|
"version": "7.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
"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",
|
"@mui/x-date-pickers": "^8.0.0-beta.3",
|
||||||
"date-and-time": "^3.6.0",
|
"date-and-time": "^3.6.0",
|
||||||
"dayjs": "^1.11.13",
|
"dayjs": "^1.11.13",
|
||||||
|
"filesize": "^10.1.6",
|
||||||
"qrcode.react": "^4.2.0",
|
"qrcode.react": "^4.2.0",
|
||||||
"react": "^19.1.0",
|
"react": "^19.1.0",
|
||||||
"react-dom": "^19.1.0",
|
"react-dom": "^19.1.0",
|
||||||
|
@ -25,4 +25,16 @@ export class FileApi {
|
|||||||
})
|
})
|
||||||
).data;
|
).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 { NotFoundRoute } from "./NotFound";
|
||||||
import { UploadFileButton } from "../widgets/forms/UploadFileButton";
|
import { UploadFileButton } from "../widgets/forms/UploadFileButton";
|
||||||
import { UploadedFile } from "../api/FileApi";
|
import { UploadedFile } from "../api/FileApi";
|
||||||
|
import { UploadedFileWidget } from "../widgets/UploadedFileWidget";
|
||||||
|
|
||||||
export function AccountRoute(): React.ReactElement {
|
export function AccountRoute(): React.ReactElement {
|
||||||
const loadingMessage = useLoadingMessage();
|
const loadingMessage = useLoadingMessage();
|
||||||
@ -281,7 +282,7 @@ function MovementsTable(p: {
|
|||||||
{
|
{
|
||||||
field: "label",
|
field: "label",
|
||||||
headerName: "Label",
|
headerName: "Label",
|
||||||
flex: 1,
|
flex: 3,
|
||||||
editable: true,
|
editable: true,
|
||||||
type: "string",
|
type: "string",
|
||||||
},
|
},
|
||||||
@ -301,7 +302,7 @@ function MovementsTable(p: {
|
|||||||
field: "file",
|
field: "file",
|
||||||
headerName: "File",
|
headerName: "File",
|
||||||
editable: false,
|
editable: false,
|
||||||
width: 150,
|
flex: 1,
|
||||||
renderCell: (params) => {
|
renderCell: (params) => {
|
||||||
if (!params.row.file_id)
|
if (!params.row.file_id)
|
||||||
return (
|
return (
|
||||||
@ -311,7 +312,7 @@ function MovementsTable(p: {
|
|||||||
onUploaded={(f) => setUploadedFile(params.row, f)}
|
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