feat: add WebDAV file browser with auth improvements
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)
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
"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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user