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