Skip to content
Snippets Groups Projects
Commit 7f50dc6cef5f authored by Arnaud Vergnet's avatar Arnaud Vergnet :sun_with_face:
Browse files

feat(frontend): use native <a> props for file downloads

parent a97a1747f5bb
No related branches found
No related tags found
1 merge request!51feat(frontend): use real name for file downloads
......@@ -3,7 +3,7 @@
import Visibility from "@mui/icons-material/Visibility";
import { ChangeEventHandler, useRef } from "react";
import { CWFile } from "@/types";
import { downloadFile, getFileNameFromURL, openFile } from "@/utils";
import { getFileDownloadUrl, getFileNameFromURL } from "@/utils";
import { ButtonTooltip } from "./ButtonTooltip";
interface FileFieldProps {
......@@ -21,15 +21,6 @@
}: FileFieldProps) {
const ref = useRef<HTMLInputElement>(null);
const onPressOpen = async () => {
let fileToOpen = value?.data as Blob;
// The file is available on the server, fetch it
if (!fileToOpen && value?.downloadUrl) {
fileToOpen = await downloadFile(value.downloadUrl);
}
openFile(fileToOpen);
};
const chooseFile = () => {
ref.current?.click();
};
......@@ -46,6 +37,6 @@
function getFileName() {
if (value?.data) {
return `(${value.data.name})`;
return `${value.data.name}`;
}
if (value?.downloadUrl) {
......@@ -50,6 +41,6 @@
}
if (value?.downloadUrl) {
return `(${getFileNameFromURL(value?.downloadUrl)})`;
return `${getFileNameFromURL(value?.downloadUrl)}`;
}
return "";
}
......@@ -73,7 +64,7 @@
>
{label}
{filePresent
? ` ${getFileName()}: Modifier le fichier`
? ` (${getFileName()}): Modifier le fichier`
: " : Choisir un fichier"}
</Button>
<ButtonTooltip
......@@ -84,7 +75,8 @@
<Button
startIcon={<Visibility />}
disabled={disabled || !filePresent}
onClick={onPressOpen}
href={getFileDownloadUrl(value)}
download={getFileName()}
>
Voir
</Button>
......
......@@ -23,6 +23,5 @@
import { useGetImportProcesses } from "@/hooks/useGetImportProcesses";
import { ErrorScreen } from "./ErrorScreen";
import { LoadingScreen } from "./LoadingScreen";
import { downloadFile, openFile } from "@/utils";
import { ButtonTooltip } from "./ButtonTooltip";
import { useState, useEffect } from "react";
......@@ -27,5 +26,6 @@
import { ButtonTooltip } from "./ButtonTooltip";
import { useState, useEffect } from "react";
import { getFileNameFromURL } from "@/utils";
export interface ImportProcessTableProps {
dataServiceEid?: number;
......@@ -34,15 +34,6 @@
showProjectColumn?: boolean;
}
async function showFile(url?: string) {
if (url) {
const fileToOpen = await downloadFile(url);
openFile(fileToOpen);
} else {
console.error("No file to open");
}
}
const REFRESH_INTERVAL = 5000;
export function ImportProcessTable(props: ImportProcessTableProps) {
......@@ -141,7 +132,8 @@
<IconButton
color="primary"
disabled={!hasLog}
onClick={() => showFile(importProcess.log_url)}
href={importProcess.log_url ?? ""}
download={getFileNameFromURL(importProcess.log_url)}
>
{hasLog ? <Visibility /> : <VisibilityOff />}
</IconButton>
......@@ -190,26 +182,18 @@
"aria-labelledby": "dataset-menu",
}}
>
<MenuItem
onClick={() => {
showFile(importProcess.input_dataset_url);
handleClose();
}}
disabled={importProcess.input_dataset_url == null}
>
Entrée
</MenuItem>
<MenuItem
onClick={() => {
showFile(importProcess.output_dataset_url);
handleClose();
}}
disabled={importProcess.output_dataset_url == null}
>
Sortie
</MenuItem>
<DatasetMenuItem
text="Entrée"
url={importProcess.input_dataset_url}
onClick={handleClose}
/>
<DatasetMenuItem
text="Sortie"
url={importProcess.output_dataset_url}
onClick={handleClose}
/>
</Menu>
</TableCell>
);
}
......@@ -211,8 +195,42 @@
</Menu>
</TableCell>
);
}
function DatasetMenuItem({
text,
url,
onClick,
}: {
text: string;
url?: string;
onClick: () => void;
}) {
if (!url) {
return (
<MenuItem onClick={onClick} disabled={true}>
{text}
</MenuItem>
);
}
// Putting href and download props directly on the MenuItem does not work
return (
<a
href={url}
download={getFileNameFromURL(url)}
style={{
color: "inherit",
textDecoration: "inherit",
}}
>
<MenuItem onClick={onClick} disabled={false}>
{text}
</MenuItem>
</a>
);
}
function ShaclButton({ importProcess }: { importProcess: ImportProcess }) {
if (importProcess.shacl_valid) {
return (
......@@ -236,7 +254,8 @@
<ButtonTooltip title={"Voir le rapport d'erreur SHACL"}>
<IconButton
color="primary"
onClick={() => showFile(importProcess.shacl_report_url)}
href={importProcess.shacl_report_url ?? ""}
download={getFileNameFromURL(importProcess.shacl_report_url)}
>
<Visibility color="warning" />
</IconButton>
......
export function openFile(file?: Blob) {
if (file) {
const url = URL.createObjectURL(file);
window.open(url);
} else {
console.warn("No file available either locally or on the server");
import { CWFile } from "./types";
export function getFileDownloadUrl(file?: CWFile): string {
if (file?.data) {
return URL.createObjectURL(file.data);
}
......@@ -7,3 +6,7 @@
}
if (file?.downloadUrl) {
return file.downloadUrl;
}
return "";
}
......@@ -8,12 +11,8 @@
}
export async function downloadFile(url: string) {
const response = await fetch(url, {
credentials: "include",
});
return await response.blob();
}
export function getFileNameFromURL(url: string): string {
export function getFileNameFromURL(url?: string): string {
if (!url) {
return "";
}
return url.slice(url.lastIndexOf("/") + 1);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment