Add a new Files section powered by WebDAV for browsing, uploading, downloading, renaming, and deleting files and folders. New features: - WebDAV file browser with grid/list views and breadcrumb navigation - File upload (drag-and-drop and button), folder creation, rename, delete - File preview modals for images and other file types - WebDAV proxy API route to handle authentication - Navigation rail entry for Files (auto-hidden when WebDAV is unsupported) Auth improvements: - Fix premature redirects on calendar, contacts, and settings pages by adding explicit auth check on mount before redirecting to login - Persist active settings tab in localStorage Other: - Expose getAuthHeader() and getServerUrl() on JMAPClient - Add WebDAV store with connection testing and capability detection - Add i18n translations for file browser in all 8 locales (de, en, es, fr, it, ja, nl, pt)
59 lines
1.7 KiB
TypeScript
59 lines
1.7 KiB
TypeScript
"use client";
|
|
|
|
import { useState } from "react";
|
|
import { useTranslations } from "next-intl";
|
|
import { Button } from "@/components/ui/button";
|
|
import { Input } from "@/components/ui/input";
|
|
|
|
interface NewFolderDialogProps {
|
|
onConfirm: (name: string) => Promise<void>;
|
|
onCancel: () => void;
|
|
}
|
|
|
|
export function NewFolderDialog({ onConfirm, onCancel }: NewFolderDialogProps) {
|
|
const t = useTranslations("files");
|
|
const [name, setName] = useState("");
|
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
|
|
const handleSubmit = async (e: React.FormEvent) => {
|
|
e.preventDefault();
|
|
const trimmed = name.trim();
|
|
if (!trimmed) return;
|
|
|
|
setIsSubmitting(true);
|
|
try {
|
|
await onConfirm(trimmed);
|
|
} finally {
|
|
setIsSubmitting(false);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50" onClick={onCancel}>
|
|
<div
|
|
className="bg-background border border-border rounded-lg shadow-lg p-6 w-full max-w-sm mx-4"
|
|
onClick={(e) => e.stopPropagation()}
|
|
>
|
|
<h2 className="text-lg font-semibold mb-4">{t("new_folder")}</h2>
|
|
<form onSubmit={handleSubmit}>
|
|
<Input
|
|
autoFocus
|
|
value={name}
|
|
onChange={(e) => setName(e.target.value)}
|
|
placeholder={t("new_folder_name")}
|
|
className="mb-4"
|
|
/>
|
|
<div className="flex justify-end gap-2">
|
|
<Button type="button" variant="outline" onClick={onCancel} disabled={isSubmitting}>
|
|
{t("cancel")}
|
|
</Button>
|
|
<Button type="submit" disabled={!name.trim() || isSubmitting}>
|
|
{t("create")}
|
|
</Button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|