Files
Stirling-PDF/frontend/src/core/components/shared/BulkUploadToServerModal.tsx
T
James BruntonandGitHub 8ab060a4be Prettier 2: Electric Boogaloo (#6113)
# Description of Changes
When I added Prettier formatting in #6052, my aim was to use just the
default settings in Prettier. Turns out, Prettier looks _really hard_
for any config files if it's not explicitly given one, which means that
if a developer has some sort of Prettier config file lying around on
their system, Prettier might find it and use it. Also, Prettier changes
its defaults based on stuff in `.editorconfig` without any good way of
disabling that behaviour explicitly in its config file.

To solve both of these issues, I've introduced a `.prettierrc` file
which sets Prettier's defaults explicitly, and then reformatted all our
code _again_ in Prettier's actual default settings. This should achieve
the aim of #6052 and remove the possibility for it breaking on different
dev computers.
2026-04-17 09:50:16 +00:00

161 lines
4.7 KiB
TypeScript

import React, { useCallback, useEffect, useMemo, useState } from "react";
import { Modal, Stack, Text, Button, Group, Alert } from "@mantine/core";
import CloudUploadIcon from "@mui/icons-material/CloudUpload";
import { useTranslation } from "react-i18next";
import { alert } from "@app/components/toast";
import { Z_INDEX_OVER_FILE_MANAGER_MODAL } from "@app/styles/zIndex";
import type { StirlingFileStub } from "@app/types/fileContext";
import { uploadHistoryChains } from "@app/services/serverStorageUpload";
import { fileStorage } from "@app/services/fileStorage";
import { useFileActions } from "@app/contexts/FileContext";
import type { FileId } from "@app/types/file";
interface BulkUploadToServerModalProps {
opened: boolean;
onClose: () => void;
files: StirlingFileStub[];
onUploaded?: () => Promise<void> | void;
}
const BulkUploadToServerModal: React.FC<BulkUploadToServerModalProps> = ({
opened,
onClose,
files,
onUploaded,
}) => {
const { t } = useTranslation();
const { actions } = useFileActions();
const [isUploading, setIsUploading] = useState(false);
const [errorMessage, setErrorMessage] = useState<string | null>(null);
const fileNames = useMemo(() => files.map((file) => file.name), [files]);
const displayNames = useMemo(() => fileNames.slice(0, 3), [fileNames]);
useEffect(() => {
if (!opened) {
setIsUploading(false);
setErrorMessage(null);
}
}, [opened]);
const handleUpload = useCallback(async () => {
setIsUploading(true);
setErrorMessage(null);
try {
const rootIds = Array.from(
new Set(
files.map((file) => (file.originalFileId || file.id) as FileId),
),
);
const remoteIds = Array.from(
new Set(
files.map((file) => file.remoteStorageId).filter(Boolean) as number[],
),
);
const existingRemoteId =
remoteIds.length === 1 ? remoteIds[0] : undefined;
const { remoteId, updatedAt, chain } = await uploadHistoryChains(
rootIds,
existingRemoteId,
);
for (const stub of chain) {
actions.updateStirlingFileStub(stub.id, {
remoteStorageId: remoteId,
remoteStorageUpdatedAt: updatedAt,
remoteOwnedByCurrentUser: true,
remoteSharedViaLink: false,
});
await fileStorage.updateFileMetadata(stub.id, {
remoteStorageId: remoteId,
remoteStorageUpdatedAt: updatedAt,
remoteOwnedByCurrentUser: true,
remoteSharedViaLink: false,
});
}
alert({
alertType: "success",
title: t("storageUpload.success", "Uploaded to server"),
expandable: false,
durationMs: 3000,
});
if (onUploaded) {
await onUploaded();
}
onClose();
} catch (error) {
console.error("Failed to upload files to server:", error);
setErrorMessage(
t(
"storageUpload.failure",
"Upload failed. Please check your login and storage settings.",
),
);
} finally {
setIsUploading(false);
}
}, [actions, files, onClose, onUploaded, t]);
return (
<Modal
opened={opened}
onClose={onClose}
centered
title={t("storageUpload.bulkTitle", "Upload selected files")}
zIndex={Z_INDEX_OVER_FILE_MANAGER_MODAL}
>
<Stack gap="sm">
<Text size="sm">
{t(
"storageUpload.bulkDescription",
"This uploads the selected files to your server storage.",
)}
</Text>
<Text size="sm" c="dimmed">
{t("storageUpload.fileCount", "{{count}} files selected", {
count: files.length,
})}
</Text>
{displayNames.length > 0 && (
<Text size="xs" c="dimmed">
{displayNames.join(", ")}
{fileNames.length > displayNames.length
? t("storageUpload.more", " +{{count}} more", {
count: fileNames.length - displayNames.length,
})
: ""}
</Text>
)}
{errorMessage && (
<Alert
color="red"
title={t("storageUpload.errorTitle", "Upload failed")}
>
{errorMessage}
</Alert>
)}
<Group justify="flex-end" gap="sm">
<Button variant="default" onClick={onClose} disabled={isUploading}>
{t("cancel", "Cancel")}
</Button>
<Button
leftSection={<CloudUploadIcon style={{ fontSize: 18 }} />}
onClick={handleUpload}
loading={isUploading}
>
{t("storageUpload.uploadButton", "Upload to Server")}
</Button>
</Group>
</Stack>
</Modal>
);
};
export default BulkUploadToServerModal;