mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-30 00:38:11 +00:00
Refactor file handling to improve URL safety and enhance file viewing capabilities across components
This commit is contained in:
@@ -32,6 +32,7 @@ import { isViewable } from "@edr/ui-common";
|
||||
|
||||
import { SectionCard } from "./SectionCard";
|
||||
import { bookingsService } from "@/services/bookings.service";
|
||||
import { fileViewUrl } from "@/constants/apiConfig";
|
||||
import { useFileViewer } from "@/hooks/useFileViewer";
|
||||
|
||||
export interface ClearanceReviewSectionProps {
|
||||
@@ -240,7 +241,7 @@ export function ClearanceReviewSection({
|
||||
<>
|
||||
{isViewable({
|
||||
name: doc.file.name,
|
||||
url: doc.file.url,
|
||||
url: fileViewUrl(doc.file.id),
|
||||
}) && (
|
||||
<Tooltip label="View">
|
||||
<Box
|
||||
@@ -249,7 +250,7 @@ export function ClearanceReviewSection({
|
||||
onClick={() =>
|
||||
view({
|
||||
name: doc.file!.name,
|
||||
url: doc.file!.url,
|
||||
url: fileViewUrl(doc.file!.id),
|
||||
})
|
||||
}
|
||||
c="edr-green"
|
||||
@@ -267,9 +268,7 @@ export function ClearanceReviewSection({
|
||||
<Tooltip label="Download">
|
||||
<Box
|
||||
component="a"
|
||||
href={doc.file.url}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
href={fileViewUrl(doc.file.id, true)}
|
||||
c="edr-green"
|
||||
style={{ display: "flex" }}
|
||||
>
|
||||
@@ -456,7 +455,10 @@ function DocReviewCard({
|
||||
{meta.label}
|
||||
</Badge>
|
||||
{hasFile &&
|
||||
isViewable({ name: doc.file!.name, url: doc.file!.url }) && (
|
||||
isViewable({
|
||||
name: doc.file!.name,
|
||||
url: fileViewUrl(doc.file!.id),
|
||||
}) && (
|
||||
<Tooltip label="Preview document">
|
||||
<Button
|
||||
size="compact-xs"
|
||||
@@ -464,7 +466,10 @@ function DocReviewCard({
|
||||
radius="md"
|
||||
leftSection={<Eye size={13} />}
|
||||
onClick={() =>
|
||||
onView({ name: doc.file!.name, url: doc.file!.url })
|
||||
onView({
|
||||
name: doc.file!.name,
|
||||
url: fileViewUrl(doc.file!.id),
|
||||
})
|
||||
}
|
||||
>
|
||||
View
|
||||
|
||||
@@ -34,6 +34,7 @@ import { isViewable } from "@edr/ui-common";
|
||||
import { SectionCard } from "@/components/bookings/detail/SectionCard";
|
||||
import { QUERY_KEYS } from "@/constants/QUERY_KEYS";
|
||||
import { contractsService } from "@/services/contracts.service";
|
||||
import { fileViewUrl } from "@/constants/apiConfig";
|
||||
import { useContractClearanceMutations } from "@/hooks/contracts/useContracts";
|
||||
import { useFileViewer } from "@/hooks/useFileViewer";
|
||||
|
||||
@@ -261,7 +262,7 @@ export function ContractClearanceReviewSection({
|
||||
<>
|
||||
{isViewable({
|
||||
name: doc.file.name,
|
||||
url: doc.file.url,
|
||||
url: fileViewUrl(doc.file.id),
|
||||
}) && (
|
||||
<Tooltip label="View">
|
||||
<Box
|
||||
@@ -270,7 +271,7 @@ export function ContractClearanceReviewSection({
|
||||
onClick={() =>
|
||||
view({
|
||||
name: doc.file!.name,
|
||||
url: doc.file!.url,
|
||||
url: fileViewUrl(doc.file!.id),
|
||||
})
|
||||
}
|
||||
c="edr-green"
|
||||
@@ -288,9 +289,7 @@ export function ContractClearanceReviewSection({
|
||||
<Tooltip label="Download">
|
||||
<Box
|
||||
component="a"
|
||||
href={doc.file.url}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
href={fileViewUrl(doc.file.id, true)}
|
||||
c="edr-green"
|
||||
style={{ display: "flex" }}
|
||||
>
|
||||
@@ -548,7 +547,10 @@ function DocReviewCard({
|
||||
{meta.label}
|
||||
</Badge>
|
||||
{hasFile &&
|
||||
isViewable({ name: doc.file!.name, url: doc.file!.url }) && (
|
||||
isViewable({
|
||||
name: doc.file!.name,
|
||||
url: fileViewUrl(doc.file!.id),
|
||||
}) && (
|
||||
<Tooltip label="Preview document">
|
||||
<Button
|
||||
size="compact-xs"
|
||||
@@ -556,7 +558,10 @@ function DocReviewCard({
|
||||
radius="md"
|
||||
leftSection={<Eye size={13} />}
|
||||
onClick={() =>
|
||||
onView({ name: doc.file!.name, url: doc.file!.url })
|
||||
onView({
|
||||
name: doc.file!.name,
|
||||
url: fileViewUrl(doc.file!.id),
|
||||
})
|
||||
}
|
||||
>
|
||||
View
|
||||
|
||||
@@ -1,3 +1,15 @@
|
||||
export const API_BASE_URL = 'https://edrfreightapi.triaplc.com';
|
||||
|
||||
// export const API_BASE_URL = 'http://localhost:3001';
|
||||
|
||||
/**
|
||||
* URL that streams an uploaded file through the API by its UUID. Routes the
|
||||
* bytes through `GET /api/files/:id` (served from MinIO with backend
|
||||
* credentials) instead of a presigned MinIO URL — the latter is not reachable
|
||||
* from the browser and breaks on the minio-js port-443 signature quirk. Serves
|
||||
* inline for preview by default; pass `download` to force a save dialog.
|
||||
*/
|
||||
export function fileViewUrl(fileId: string, download = false): string {
|
||||
const base = `${API_BASE_URL}/api/files/${fileId}`;
|
||||
return download ? `${base}?download=1` : base;
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ import {
|
||||
humanize,
|
||||
} from "@/components/customers";
|
||||
import { KpiStrip, PageContainer, PageHeader } from "@/components/page";
|
||||
import { fileViewUrl } from "@/constants/apiConfig";
|
||||
import { api } from "@/services/api";
|
||||
import type {
|
||||
CompanyProfile,
|
||||
@@ -289,7 +290,7 @@ export default function CustomerDetailPage() {
|
||||
cell: ({ row }) => (
|
||||
<ActionIcon
|
||||
component="a"
|
||||
href={row.original.url ?? "#"}
|
||||
href={fileViewUrl(row.original.id, true)}
|
||||
variant="subtle"
|
||||
color="gray"
|
||||
aria-label="Download"
|
||||
|
||||
Reference in New Issue
Block a user