Support opening PDFs in a new tab

This commit is contained in:
2024-11-30 10:43:33 +01:00
parent 26bcfc684a
commit 2e3f90de19

View File

@@ -1,8 +1,8 @@
import type { Attachment, Piece } from "backend/database"; import type { Attachment, Piece } from "backend/database";
import { AttachmentId, PieceId } from "common"; import { PieceId } from "common";
import { ACCEPTED_EXTENSIONS } from "common/MediaType"; import { ACCEPTED_EXTENSIONS } from "common/MediaType";
import { ELYSIA_FORM_DATA } from "elysia"; import { ELYSIA_FORM_DATA } from "elysia";
import { FormEventHandler, useId, useReducer, useRef, useState } from "react"; import { FormEventHandler, MouseEvent, useCallback, useId, useReducer, useRef, useState } from "react";
import { Link, useParams } from "react-router-dom"; import { Link, useParams } from "react-router-dom";
import { client } from "../client"; import { client } from "../client";
import { FileReducer } from "../FileReducer"; import { FileReducer } from "../FileReducer";
@@ -125,11 +125,36 @@ namespace Attachments {
} }
function Attachments(props: Attachments.Props) { function Attachments(props: Attachments.Props) {
return (
<table className="grow">
<thead>
<tr>
<th className="p-1 border">Nazwa pliku</th>
<th className="p-1 border">Typ</th>
<th className="p-1 border">Dodano</th>
<th className="p-1 border">Zmodyfikowano</th>
<th className="p-1 border">Pobierz</th>
</tr>
</thead>
<tbody>
{props.attachments.map((attachment) => <AttachmentRow key={attachment.attachmentId} attachment={attachment} />)}
</tbody>
</table>
);
}
const download = (attachmentId: AttachmentId) => async () => { namespace AttachmentRow {
export interface Props {
readonly attachment: Attachment;
}
}
function AttachmentRow(props: AttachmentRow.Props) {
const download = useCallback(async () => {
const { error, data: _data } = await client const { error, data: _data } = await client
.piece({ pieceId: props.pieceId }) .piece({ pieceId: props.attachment.pieceId })
.attachment({ attachmentId }) .attachment({ attachmentId: props.attachment.attachmentId })
.get(); .get();
if (error !== null) { if (error !== null) {
@@ -144,52 +169,64 @@ function Attachments(props: Attachments.Props) {
a.download = data.filename; a.download = data.filename;
a.click(); a.click();
URL.revokeObjectURL(url); URL.revokeObjectURL(url);
}; }, [props.attachment.attachmentId, props.attachment.pieceId]);
const open = useCallback(async () => {
const { error, data: _data } = await client
.piece({ pieceId: props.attachment.pieceId })
.attachment({ attachmentId: props.attachment.attachmentId })
.get();
if (error !== null) {
console.error(error.value);
return;
}
const data = _data as unknown as typeof _data[ELYSIA_FORM_DATA];
const url = URL.createObjectURL(data.data);
window.open(url, "_target");
URL.revokeObjectURL(url);
}, [props.attachment.attachmentId, props.attachment.pieceId, props.attachment.mediaType]);
const onOpen = useCallback((event: MouseEvent<HTMLAnchorElement>) => {
if (props.attachment.mediaType !== "application/pdf") {
return;
}
event.preventDefault();
open();
}, [props.attachment.mediaType, open]);
return ( return (
<table className="grow"> <tr>
<thead> <td className="p-1 border">
<tr> {props.attachment.mediaType === "application/vnd.recordare.musicxml"
<th className="p-1 border">Nazwa pliku</th> || props.attachment.mediaType === "application/vnd.recordare.musicxml+xml"
<th className="p-1 border">Typ</th> || props.attachment.mediaType === "application/pdf" ? (
<th className="p-1 border">Dodano</th> <Link className="underline" to={`attachment/${props.attachment.attachmentId}`} onClick={onOpen}>
<th className="p-1 border">Zmodyfikowano</th> {props.attachment.filename}
<th className="p-1 border">Pobierz</th> </Link>
</tr> ) : (
</thead> props.attachment.filename
<tbody> )}
{props.attachments.map((attachment) => ( </td>
<tr key={attachment.attachmentId}> <td className="p-1 border">{props.attachment.mediaType}</td>
<td className="p-1 border"> <td className="p-1 border text-center font-mono text-sm">
{attachment.mediaType === "application/vnd.recordare.musicxml" {props.attachment.createdAt}
|| attachment.mediaType === "application/vnd.recordare.musicxml+xml" ? ( {props.attachment.createdBy !== null && <><br />przez {props.attachment.createdBy}</>}
<Link className="underline" to={`attachment/${attachment.attachmentId}`}> </td>
{attachment.filename} <td className="p-1 border text-center font-mono text-sm">
</Link> {props.attachment.modifiedAt === null && props.attachment.modifiedBy === null ? "\u2014"
) : ( : props.attachment.modifiedAt !== null && props.attachment.modifiedBy === null ? props.attachment.modifiedAt
attachment.filename : props.attachment.modifiedAt === null ? `przez ${props.attachment.createdBy}`
)} : <>{props.attachment.createdAt}<br />przez {props.attachment.createdBy}</>}
</td> </td>
<td className="p-1 border">{attachment.mediaType}</td> <td className="p-1 border text-center">
<td className="p-1 border text-center font-mono text-sm"> <Button type="button" onClick={download}>
{attachment.createdAt} Pobierz
{attachment.createdBy !== null && <><br />przez {attachment.createdBy}</>} </Button>
</td> </td>
<td className="p-1 border text-center font-mono text-sm"> </tr>
{attachment.modifiedAt === null && attachment.modifiedBy === null ? "\u2014"
: attachment.modifiedAt !== null && attachment.modifiedBy === null ? attachment.modifiedAt
: attachment.modifiedAt === null ? `przez ${attachment.createdBy}`
: <>{attachment.createdAt}<br />przez {attachment.createdBy}</>}
</td>
<td className="p-1 border text-center">
<Button type="button" onClick={download(attachment.attachmentId)}>
Pobierz
</Button>
</td>
</tr>
))}
</tbody>
</table>
); );
} }