- Updated .env.example to include configuration for OnlyOffice Document Server. - Modified the workspace configuration to remove the drive-suite path. - Adjusted TypeScript environment imports for consistency. - Enhanced Next.js configuration to disable canvas in Webpack. - Updated package.json to include new dependencies for OnlyOffice and PDF.js. - Added global styles for OnlyOffice theme integration in the CSS. - Created new layout and page components for the Drive feature, including public sharing and editing functionalities. - Updated metadata handling across various layouts to reflect the new app structure.
134 lines
4.3 KiB
TypeScript
134 lines
4.3 KiB
TypeScript
"use client"
|
|
|
|
import { ArrowDown, ArrowUp, Check } from "lucide-react"
|
|
import {
|
|
DropdownMenu,
|
|
DropdownMenuContent,
|
|
DropdownMenuTrigger,
|
|
} from "@/components/ui/dropdown-menu"
|
|
import {
|
|
DRIVE_SORT_FIELD_LABELS,
|
|
driveSortOrderLabels,
|
|
} from "@/lib/drive/drive-sort"
|
|
import type { DriveFolderPlacement, DriveSortField } from "@/lib/stores/drive-settings-store"
|
|
import { useDriveSettingsStore } from "@/lib/stores/drive-settings-store"
|
|
import { DRIVE_MENU_SURFACE_CLASS } from "@/components/drive/drive-file-context-menu"
|
|
import { cn } from "@/lib/utils"
|
|
|
|
const MENU_SURFACE = cn(
|
|
DRIVE_MENU_SURFACE_CLASS,
|
|
"w-[min(100vw-2rem,20rem)] rounded-xl p-0"
|
|
)
|
|
|
|
function SortSectionTitle({ children }: { children: React.ReactNode }) {
|
|
return (
|
|
<p className="px-4 pt-3 pb-1 text-xs font-medium text-[#5f6368] dark:text-muted-foreground">
|
|
{children}
|
|
</p>
|
|
)
|
|
}
|
|
|
|
function SortMenuOption({
|
|
label,
|
|
selected,
|
|
onSelect,
|
|
}: {
|
|
label: string
|
|
selected: boolean
|
|
onSelect: () => void
|
|
}) {
|
|
return (
|
|
<button
|
|
type="button"
|
|
role="menuitemradio"
|
|
aria-checked={selected}
|
|
onClick={onSelect}
|
|
className={cn(
|
|
"flex w-full cursor-pointer items-center gap-3 px-4 py-2.5 text-left text-sm text-[#202124] transition-colors dark:text-foreground",
|
|
selected ? "bg-[#e8f0fe] dark:bg-primary/15" : "hover:bg-[#f1f3f4] dark:hover:bg-accent/60"
|
|
)}
|
|
>
|
|
<span className="flex h-5 w-5 shrink-0 items-center justify-center">
|
|
{selected ? <Check className="h-4 w-4 text-[#1967d2]" strokeWidth={2.5} /> : null}
|
|
</span>
|
|
{label}
|
|
</button>
|
|
)
|
|
}
|
|
|
|
function SortMenuDivider() {
|
|
return <div className="my-1 border-t border-[#e8eaed] dark:border-border" />
|
|
}
|
|
|
|
const SORT_FIELDS: DriveSortField[] = ["name", "date", "size"]
|
|
|
|
export function DriveSortMenu() {
|
|
const sortField = useDriveSettingsStore((s) => s.sortField)
|
|
const sortDir = useDriveSettingsStore((s) => s.sortDir)
|
|
const folderPlacement = useDriveSettingsStore((s) => s.folderPlacement)
|
|
const setSortField = useDriveSettingsStore((s) => s.setSortField)
|
|
const setSortDir = useDriveSettingsStore((s) => s.setSortDir)
|
|
const setFolderPlacement = useDriveSettingsStore((s) => s.setFolderPlacement)
|
|
|
|
const orderLabels = driveSortOrderLabels(sortField)
|
|
const triggerLabel = DRIVE_SORT_FIELD_LABELS[sortField]
|
|
|
|
return (
|
|
<DropdownMenu>
|
|
<DropdownMenuTrigger asChild>
|
|
<button
|
|
type="button"
|
|
className={cn(
|
|
"inline-flex h-8 cursor-pointer items-center gap-1 rounded-full px-3 text-sm font-medium transition-colors",
|
|
"bg-[#e8f0fe] text-[#1967d2] hover:bg-[#d2e3fc]",
|
|
"dark:bg-primary/15 dark:text-primary dark:hover:bg-primary/25"
|
|
)}
|
|
>
|
|
{triggerLabel}
|
|
{sortDir === "asc" ? (
|
|
<ArrowUp className="h-4 w-4 shrink-0 opacity-80" />
|
|
) : (
|
|
<ArrowDown className="h-4 w-4 shrink-0 opacity-80" />
|
|
)}
|
|
</button>
|
|
</DropdownMenuTrigger>
|
|
<DropdownMenuContent align="end" sideOffset={6} data-drive-menu-surface className={MENU_SURFACE}>
|
|
<SortSectionTitle>Trier par</SortSectionTitle>
|
|
{SORT_FIELDS.map((field) => (
|
|
<SortMenuOption
|
|
key={field}
|
|
label={DRIVE_SORT_FIELD_LABELS[field]}
|
|
selected={sortField === field}
|
|
onSelect={() => setSortField(field)}
|
|
/>
|
|
))}
|
|
<SortMenuDivider />
|
|
<SortSectionTitle>Ordre de tri</SortSectionTitle>
|
|
<SortMenuOption
|
|
label={orderLabels.asc}
|
|
selected={sortDir === "asc"}
|
|
onSelect={() => setSortDir("asc")}
|
|
/>
|
|
<SortMenuOption
|
|
label={orderLabels.desc}
|
|
selected={sortDir === "desc"}
|
|
onSelect={() => setSortDir("desc")}
|
|
/>
|
|
<SortMenuDivider />
|
|
<SortSectionTitle>Dossiers</SortSectionTitle>
|
|
<SortMenuOption
|
|
label="En haut"
|
|
selected={folderPlacement === "top"}
|
|
onSelect={() => setFolderPlacement("top")}
|
|
/>
|
|
<SortMenuOption
|
|
label="Mélangés avec les fichiers"
|
|
selected={folderPlacement === "mixed"}
|
|
onSelect={() => setFolderPlacement("mixed")}
|
|
/>
|
|
<div className="h-2" aria-hidden />
|
|
</DropdownMenuContent>
|
|
</DropdownMenu>
|
|
)
|
|
}
|