feat(webui): add bounded file quick access
This commit is contained in:
@@ -578,6 +578,8 @@ manifest = ModuleManifest(
|
||||
required_any=("files:file:read",),
|
||||
order=10,
|
||||
modes=("browse", "select", "upload"),
|
||||
returned_reference_kinds=("files.file-version",),
|
||||
help_context_id="files.quick_access.files",
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -684,8 +686,10 @@ manifest = ModuleManifest(
|
||||
summary="Use managed files in the Records and documents area and keep a compact file surface beside current work.",
|
||||
body=(
|
||||
"Files contributes its authorized workspace to Records and documents. When Quick Access is enabled, the owner-rendered "
|
||||
"file-space summary appears in Files on the right rail and links back to the complete workspace. View and rail settings "
|
||||
"do not bypass file ownership, shares, connector policy, integrity gates, or purpose-aware access."
|
||||
"recent-file selector appears in Files on the right rail and can return one exact file-version reference to the current task. "
|
||||
"Opening the selector causes Files to re-run its own authorization; completion and cancellation are explicit, and the full Files "
|
||||
"workspace remains available as a deep-link fallback. View and rail settings may recommend or focus this tool, but do not bypass "
|
||||
"file ownership, shares, connector policy, integrity gates, or purpose-aware access."
|
||||
),
|
||||
layer="configured",
|
||||
documentation_types=("user", "admin"),
|
||||
@@ -711,8 +715,11 @@ manifest = ModuleManifest(
|
||||
"summary": "Verwaltete Dateien im Produktbereich Akten und Dokumente und optional neben der aktuellen Arbeit verwenden.",
|
||||
"body": (
|
||||
"Files ordnet seinen berechtigten Arbeitsbereich Akten und Dokumente zu. Ist der Schnellzugriff aktiviert, erscheint "
|
||||
"die vom Modul gerenderte Übersicht der Dateibereiche rechts neben der aktuellen Seite. Ansichts- und Leistenkonfiguration "
|
||||
"umgehen weder Eigentum, Freigaben, Connector-Richtlinien, Integritätsprüfungen noch zweckgebundenen Zugriff."
|
||||
"die vom Modul gerenderte Auswahl zuletzt berechtigter Dateien rechts neben der aktuellen Seite und kann einen exakten "
|
||||
"Dateiversionsverweis an die aktuelle Aufgabe zurückgeben. Files prüft die Berechtigung beim Öffnen erneut; Abschluss und "
|
||||
"Abbruch sind ausdrücklich, und der vollständige Files-Arbeitsbereich bleibt als Ausweichziel erreichbar. Ansichts- und "
|
||||
"Leistenkonfiguration dürfen das Werkzeug empfehlen oder fokussieren, umgehen aber weder Eigentum, Freigaben, Connector-"
|
||||
"Richtlinien, Integritätsprüfungen noch zweckgebundenen Zugriff."
|
||||
),
|
||||
}
|
||||
},
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
import { FileText, X } from "lucide-react";
|
||||
import { useCallback } from "react";
|
||||
import {
|
||||
Button,
|
||||
DismissibleAlert,
|
||||
LoadingFrame,
|
||||
SelectionList,
|
||||
SelectionListItem,
|
||||
SelectionListItemContent,
|
||||
useDashboardWidgetData,
|
||||
type QuickAccessToolRenderContext
|
||||
} from "@govoplan/core-webui";
|
||||
import { listFiles } from "../../api/files";
|
||||
|
||||
type Props = Pick<
|
||||
QuickAccessToolRenderContext,
|
||||
"settings" | "launchContext" | "complete" | "cancel"
|
||||
>;
|
||||
|
||||
/**
|
||||
* Bounded file selection. listFiles remains the owner-side authorization
|
||||
* check; the host receives only a versioned reference after explicit choice.
|
||||
*/
|
||||
export default function FileQuickAccess({
|
||||
settings,
|
||||
launchContext,
|
||||
complete,
|
||||
cancel
|
||||
}: Props) {
|
||||
const load = useCallback(
|
||||
async () => (await listFiles(settings, { page_size: 7 })).files,
|
||||
[settings]
|
||||
);
|
||||
const { data: files, loading, error } = useDashboardWidgetData(load, 0);
|
||||
|
||||
return (
|
||||
<LoadingFrame loading={loading} label="Loading recent files">
|
||||
{launchContext.activeObject ? (
|
||||
<p className="muted small-note">
|
||||
Select a file for {launchContext.activeObject.label}. Files checks
|
||||
your current access again before showing this list.
|
||||
</p>
|
||||
) : null}
|
||||
{error ? <DismissibleAlert tone="warning" resetKey={error}>{error}</DismissibleAlert> : null}
|
||||
<SelectionList variant="navigation" label="Recent authorized files">
|
||||
{(files ?? []).map((file) => (
|
||||
<SelectionListItem
|
||||
key={file.version_id}
|
||||
selected={false}
|
||||
onClick={() => complete({
|
||||
contractVersion: "1",
|
||||
outcome: "completed",
|
||||
action: "selected",
|
||||
reference: {
|
||||
ownerModule: "files",
|
||||
kind: "file-version",
|
||||
objectId: file.version_id,
|
||||
tenantId: file.tenant_id,
|
||||
label: file.filename,
|
||||
version: file.version_id,
|
||||
path: `/files?fileId=${encodeURIComponent(file.id)}&versionId=${encodeURIComponent(file.version_id)}`
|
||||
}
|
||||
})}
|
||||
>
|
||||
<SelectionListItemContent
|
||||
leading={<FileText size={16} aria-hidden="true" />}
|
||||
title={file.filename}
|
||||
description={file.display_path}
|
||||
/>
|
||||
</SelectionListItem>
|
||||
))}
|
||||
</SelectionList>
|
||||
{!loading && !error && !(files ?? []).length ? (
|
||||
<p className="muted">No authorized files are available.</p>
|
||||
) : null}
|
||||
<div className="button-row compact-actions">
|
||||
<Button onClick={() => cancel("user")}><X size={15} aria-hidden="true" /> Cancel selection</Button>
|
||||
</div>
|
||||
</LoadingFrame>
|
||||
);
|
||||
}
|
||||
+2
-8
@@ -12,6 +12,7 @@ import { FolderTree } from "./features/files/components/FileManagerComponents";
|
||||
import FileConnectorSettingsPanel from "./features/files/FileConnectorSettingsPanel";
|
||||
import ManagedFileChooser from "./features/files/components/ManagedFileChooser";
|
||||
import FileSpacesWidget from "./features/files/FileSpacesWidget";
|
||||
import FileQuickAccess from "./features/files/FileQuickAccess";
|
||||
import { listFileSpaces, listFiles, listFilesDelta, listFolders, resolveFilePatterns, shareFilesWithTarget } from "./api/files";
|
||||
import { generatedTranslations } from "./i18n/generatedTranslations";
|
||||
import "./styles/file-manager.css";
|
||||
@@ -72,14 +73,7 @@ const fileQuickAccessTools: QuickAccessToolsUiCapability = {
|
||||
tools: [
|
||||
{
|
||||
id: "files.recent",
|
||||
render: ({ settings }) => createElement(FileSpacesWidget, {
|
||||
settings,
|
||||
refreshKey: 0,
|
||||
configuration: {
|
||||
maxItems: 7,
|
||||
includeConnectors: true
|
||||
}
|
||||
})
|
||||
render: (context) => createElement(FileQuickAccess, context)
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user