cleanup
This commit is contained in:
@@ -29,7 +29,7 @@ const useDocumentsShell = (): DocumentsShellView => {
|
|||||||
openDetailPanel: shell.openDetailPanel as WorkspaceSurfaceConfig['openDetailPanel'],
|
openDetailPanel: shell.openDetailPanel as WorkspaceSurfaceConfig['openDetailPanel'],
|
||||||
closeDetailPanel: shell.closeDetailPanel as WorkspaceSurfaceConfig['closeDetailPanel'],
|
closeDetailPanel: shell.closeDetailPanel as WorkspaceSurfaceConfig['closeDetailPanel'],
|
||||||
previewWorkspaceDocument: shell.previewWorkspaceDocument,
|
previewWorkspaceDocument: shell.previewWorkspaceDocument,
|
||||||
previewDocumentId: (shell.previewDocumentId as Identifier | null | undefined) ?? null,
|
previewDocumentId: (shell.previewDocumentId as Identifier) ?? null,
|
||||||
closeDocumentPreview: shell.closeDocumentPreview as WorkspaceSurfaceConfig['closeDocumentPreview'],
|
closeDocumentPreview: shell.closeDocumentPreview as WorkspaceSurfaceConfig['closeDocumentPreview'],
|
||||||
ensurePreviewData: shell.ensurePreviewData as WorkspaceSurfaceConfig['ensurePreviewData'],
|
ensurePreviewData: shell.ensurePreviewData as WorkspaceSurfaceConfig['ensurePreviewData'],
|
||||||
ensureAssetUrl: shell.ensureAssetUrl as WorkspaceSurfaceConfig['ensureAssetUrl'],
|
ensureAssetUrl: shell.ensureAssetUrl as WorkspaceSurfaceConfig['ensureAssetUrl'],
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ import useDetailWorkspace from '../../viewer/logic/useDetailWorkspace';
|
|||||||
import useWorkspaceTaxonomies from './useWorkspaceTaxonomies';
|
import useWorkspaceTaxonomies from './useWorkspaceTaxonomies';
|
||||||
import useWorkspaceBreadcrumbs from '../logic/useWorkspaceBreadcrumbs';
|
import useWorkspaceBreadcrumbs from '../logic/useWorkspaceBreadcrumbs';
|
||||||
import useWorkspaceSelectionSync from '../features/selection/useWorkspaceSelectionSync';
|
import useWorkspaceSelectionSync from '../features/selection/useWorkspaceSelectionSync';
|
||||||
import type { DocumentId, FolderId as FolderIdentifier, Identifier } from '../../types/identifiers';
|
import type { DocumentId, FolderNodeId, Identifier } from '../../types/identifiers';
|
||||||
|
|
||||||
const EntryType = Object.freeze({
|
const EntryType = Object.freeze({
|
||||||
document: 'document',
|
document: 'document',
|
||||||
@@ -60,14 +60,13 @@ const EntryType = Object.freeze({
|
|||||||
|
|
||||||
const noop = () => { };
|
const noop = () => { };
|
||||||
|
|
||||||
type FolderId = FolderIdentifier | 'root';
|
|
||||||
|
|
||||||
import type { Document } from '../../types/documents';
|
import type { Document } from '../../types/documents';
|
||||||
|
|
||||||
interface FolderContentsEntry {
|
interface FolderContentsEntry {
|
||||||
folder?: { id?: FolderId; name?: string | null } | null;
|
folder?: { id?: FolderNodeId; name?: string | null } | null;
|
||||||
documents?: Document[];
|
documents?: Document[];
|
||||||
subfolders?: Array<{ id?: FolderId; name?: string | null;[key: string]: unknown }>;
|
subfolders?: Array<{ id?: FolderNodeId; name?: string | null;[key: string]: unknown }>;
|
||||||
__includesDocuments?: boolean;
|
__includesDocuments?: boolean;
|
||||||
__sortField?: string | null;
|
__sortField?: string | null;
|
||||||
__sortDirection?: string | null;
|
__sortDirection?: string | null;
|
||||||
@@ -210,7 +209,7 @@ const useDocumentsWorkspace = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const [draggedDocumentIds, setDraggedDocumentIds] = useState<DocumentId[]>([]);
|
const [draggedDocumentIds, setDraggedDocumentIds] = useState<DocumentId[]>([]);
|
||||||
const [draggedFolderId, setDraggedFolderId] = useState<FolderId | null>(null);
|
const [draggedFolderId, setDraggedFolderId] = useState<FolderNodeId | null>(null);
|
||||||
const [activePreviewId, setActivePreviewId] = useState<DocumentId | null>(routeDocumentId || null);
|
const [activePreviewId, setActivePreviewId] = useState<DocumentId | null>(routeDocumentId || null);
|
||||||
const shellRef = useRef(null);
|
const shellRef = useRef(null);
|
||||||
const assetManagerRef = useRef(null);
|
const assetManagerRef = useRef(null);
|
||||||
@@ -293,7 +292,7 @@ const useDocumentsWorkspace = ({
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
const [folderContents, setFolderContents] = useState<Map<FolderId, FolderContentsEntry>>(
|
const [folderContents, setFolderContents] = useState<Map<FolderNodeId, FolderContentsEntry>>(
|
||||||
() => new Map(),
|
() => new Map(),
|
||||||
);
|
);
|
||||||
const folderContentsRef = useRef(folderContents);
|
const folderContentsRef = useRef(folderContents);
|
||||||
@@ -687,12 +686,12 @@ const useDocumentsWorkspace = ({
|
|||||||
return filtered.length === prev.length ? prev : filtered;
|
return filtered.length === prev.length ? prev : filtered;
|
||||||
});
|
});
|
||||||
|
|
||||||
setFolderContents((prev: Map<FolderId, FolderContentsEntry>) => {
|
setFolderContents((prev: Map<FolderNodeId, FolderContentsEntry>) => {
|
||||||
if (!prev.size) {
|
if (!prev.size) {
|
||||||
return prev;
|
return prev;
|
||||||
}
|
}
|
||||||
let changed = false;
|
let changed = false;
|
||||||
const next = new Map<FolderId, FolderContentsEntry>();
|
const next = new Map<FolderNodeId, FolderContentsEntry>();
|
||||||
prev.forEach((contents, key) => {
|
prev.forEach((contents, key) => {
|
||||||
const docs = Array.isArray(contents?.documents) ? contents.documents : null;
|
const docs = Array.isArray(contents?.documents) ? contents.documents : null;
|
||||||
if (!docs || docs.length === 0) {
|
if (!docs || docs.length === 0) {
|
||||||
|
|||||||
@@ -9,17 +9,15 @@ import {
|
|||||||
createDocumentEntryKey,
|
createDocumentEntryKey,
|
||||||
createFolderEntryKey,
|
createFolderEntryKey,
|
||||||
} from '../../../app/entryKey';
|
} from '../../../app/entryKey';
|
||||||
import type { FolderId as FolderIdentifier, Identifier } from '../../../types/identifiers';
|
import type { FolderId, FolderNodeId, Identifier } from '../../../types/identifiers';
|
||||||
import type { Document } from '../../../types/documents';
|
import type { Document } from '../../../types/documents';
|
||||||
|
|
||||||
type FolderId = FolderIdentifier | 'root';
|
|
||||||
|
|
||||||
interface FolderSummary {
|
interface FolderSummary {
|
||||||
id?: FolderId;
|
id?: FolderNodeId;
|
||||||
name?: string;
|
name?: string;
|
||||||
parent_id?: FolderId | null;
|
parent_id?: FolderNodeId | null;
|
||||||
parentId?: FolderId | null;
|
parentId?: FolderNodeId | null;
|
||||||
children?: FolderId[];
|
children?: FolderNodeId[];
|
||||||
subfolders?: FolderSummary[];
|
subfolders?: FolderSummary[];
|
||||||
has_children?: boolean;
|
has_children?: boolean;
|
||||||
hasChildren?: boolean;
|
hasChildren?: boolean;
|
||||||
@@ -37,8 +35,8 @@ interface FolderContentsEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface FolderTreeNode extends FolderSummary {
|
interface FolderTreeNode extends FolderSummary {
|
||||||
id: FolderId;
|
id: FolderNodeId;
|
||||||
children: FolderId[];
|
children: FolderNodeId[];
|
||||||
expanded?: boolean;
|
expanded?: boolean;
|
||||||
loaded?: boolean;
|
loaded?: boolean;
|
||||||
hasChildren?: boolean;
|
hasChildren?: boolean;
|
||||||
@@ -54,18 +52,18 @@ interface SelectionHelpers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface UseFolderTreeOptions {
|
interface UseFolderTreeOptions {
|
||||||
initialSelectedFolder?: FolderId;
|
initialSelectedFolder?: FolderNodeId;
|
||||||
tenantIdRef: MutableRefObject<Identifier | null>;
|
tenantIdRef: MutableRefObject<Identifier | null>;
|
||||||
documentsSortFieldRef: MutableRefObject<string>;
|
documentsSortFieldRef: MutableRefObject<string>;
|
||||||
documentsSortDirectionRef: MutableRefObject<string>;
|
documentsSortDirectionRef: MutableRefObject<string>;
|
||||||
selectionHelpers: SelectionHelpers;
|
selectionHelpers: SelectionHelpers;
|
||||||
setDocuments: Dispatch<SetStateAction<Document[]>>;
|
setDocuments: Dispatch<SetStateAction<Document[]>>;
|
||||||
setFolderContents: Dispatch<SetStateAction<Map<FolderId, FolderContentsEntry>>>;
|
setFolderContents: Dispatch<SetStateAction<Map<FolderNodeId, FolderContentsEntry>>>;
|
||||||
folderContentsRef: MutableRefObject<Map<FolderId, FolderContentsEntry>>;
|
folderContentsRef: MutableRefObject<Map<FolderNodeId, FolderContentsEntry>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface FolderOption {
|
interface FolderOption {
|
||||||
id: FolderId;
|
id: FolderNodeId;
|
||||||
label: string;
|
label: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,7 +77,7 @@ const useFolderTree = ({
|
|||||||
setFolderContents,
|
setFolderContents,
|
||||||
folderContentsRef,
|
folderContentsRef,
|
||||||
}: UseFolderTreeOptions) => {
|
}: UseFolderTreeOptions) => {
|
||||||
const [folderNodes, setFolderNodes] = useState<Map<FolderId, FolderTreeNode>>(() => {
|
const [folderNodes, setFolderNodes] = useState<Map<FolderNodeId, FolderTreeNode>>(() => {
|
||||||
const rootNode = createRootNode() as FolderTreeNode;
|
const rootNode = createRootNode() as FolderTreeNode;
|
||||||
return new Map([[rootNode.id, rootNode]]);
|
return new Map([[rootNode.id, rootNode]]);
|
||||||
});
|
});
|
||||||
@@ -90,12 +88,12 @@ const useFolderTree = ({
|
|||||||
const data = await getFolderTree();
|
const data = await getFolderTree();
|
||||||
setFolderNodes((prev) => {
|
setFolderNodes((prev) => {
|
||||||
const next = new Map(prev);
|
const next = new Map(prev);
|
||||||
const rootChildren: FolderId[] = [];
|
const rootChildren: FolderNodeId[] = [];
|
||||||
|
|
||||||
data.forEach((item) => {
|
data.forEach((item) => {
|
||||||
const id = item.id as FolderId;
|
const id = item.id as FolderNodeId;
|
||||||
const parentId = (item.parent_id || 'root') as FolderId;
|
const parentId = (item.parent_id || 'root') as FolderNodeId;
|
||||||
const children = (item.children || []).map((c) => c as FolderId);
|
const children = (item.children || []).map((c) => c as FolderNodeId);
|
||||||
|
|
||||||
next.set(id, {
|
next.set(id, {
|
||||||
id,
|
id,
|
||||||
@@ -130,7 +128,7 @@ const useFolderTree = ({
|
|||||||
fetchTree();
|
fetchTree();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const [selectedFolder, setSelectedFolder] = useState<FolderId>(initialSelectedFolder || 'root');
|
const [selectedFolder, setSelectedFolder] = useState<FolderNodeId>(initialSelectedFolder || 'root');
|
||||||
const [currentFolder, setCurrentFolder] = useState<FolderSummary | null>(null);
|
const [currentFolder, setCurrentFolder] = useState<FolderSummary | null>(null);
|
||||||
const [currentSubfolders, setCurrentSubfolders] = useState<FolderSummary[]>([]);
|
const [currentSubfolders, setCurrentSubfolders] = useState<FolderSummary[]>([]);
|
||||||
|
|
||||||
@@ -149,7 +147,7 @@ const useFolderTree = ({
|
|||||||
}, [focusedDocumentId]);
|
}, [focusedDocumentId]);
|
||||||
|
|
||||||
const applySelectedFolder = useCallback(
|
const applySelectedFolder = useCallback(
|
||||||
(folderId: FolderId, contents?: FolderContentsEntry | null) => {
|
(folderId: FolderNodeId, contents?: FolderContentsEntry | null) => {
|
||||||
const subfolders = Array.isArray(contents?.subfolders) ? contents.subfolders : [];
|
const subfolders = Array.isArray(contents?.subfolders) ? contents.subfolders : [];
|
||||||
const docs = Array.isArray(contents?.documents) ? contents.documents : [];
|
const docs = Array.isArray(contents?.documents) ? contents.documents : [];
|
||||||
const folderInfo = contents?.folder ?? null;
|
const folderInfo = contents?.folder ?? null;
|
||||||
@@ -159,7 +157,7 @@ const useFolderTree = ({
|
|||||||
setCurrentFolder(folderInfo);
|
setCurrentFolder(folderInfo);
|
||||||
|
|
||||||
const availableDocKeys = docs
|
const availableDocKeys = docs
|
||||||
.map((doc) => createDocumentEntryKey(doc?.id as Identifier))
|
.map((doc) => createDocumentEntryKey((doc as Document)?.id as Identifier))
|
||||||
.filter(Boolean);
|
.filter(Boolean);
|
||||||
const availableDocKeySet = new Set(availableDocKeys);
|
const availableDocKeySet = new Set(availableDocKeys);
|
||||||
const availableFolderKeys = new Set(
|
const availableFolderKeys = new Set(
|
||||||
@@ -212,13 +210,13 @@ const useFolderTree = ({
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
const expandFolderAncestors = useCallback((targetId: FolderId | null) => {
|
const expandFolderAncestors = useCallback((targetId: FolderNodeId | null) => {
|
||||||
if (!targetId || targetId === 'root') {
|
if (!targetId || targetId === 'root') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setFolderNodes((prev: Map<FolderId, FolderTreeNode>) => {
|
setFolderNodes((prev: Map<FolderNodeId, FolderTreeNode>) => {
|
||||||
const next = new Map<FolderId, FolderTreeNode>(prev);
|
const next = new Map<FolderNodeId, FolderTreeNode>(prev);
|
||||||
const node = next.get(targetId);
|
const node = next.get(targetId);
|
||||||
let currentId = node?.parentId ?? 'root';
|
let currentId = node?.parentId ?? 'root';
|
||||||
let guard = 0;
|
let guard = 0;
|
||||||
@@ -238,7 +236,7 @@ const useFolderTree = ({
|
|||||||
|
|
||||||
const ensureFolderData = useCallback(
|
const ensureFolderData = useCallback(
|
||||||
async (
|
async (
|
||||||
folderId: FolderId,
|
folderId: FolderNodeId,
|
||||||
{
|
{
|
||||||
includeDocuments = true,
|
includeDocuments = true,
|
||||||
prefetchDepth = 0,
|
prefetchDepth = 0,
|
||||||
@@ -289,8 +287,8 @@ const useFolderTree = ({
|
|||||||
const data = await listFolderContents<FolderContentsEntry>(path, params);
|
const data = await listFolderContents<FolderContentsEntry>(path, params);
|
||||||
const childFolders = Array.isArray(data.subfolders) ? data.subfolders : [];
|
const childFolders = Array.isArray(data.subfolders) ? data.subfolders : [];
|
||||||
const childIds = childFolders
|
const childIds = childFolders
|
||||||
.map((child) => (child?.id ?? null) as FolderId | null)
|
.map((child) => (child?.id ?? null) as FolderNodeId | null)
|
||||||
.filter((id): id is FolderId => Boolean(id));
|
.filter((id): id is FolderNodeId => Boolean(id));
|
||||||
|
|
||||||
const enriched = {
|
const enriched = {
|
||||||
...data,
|
...data,
|
||||||
@@ -303,8 +301,8 @@ const useFolderTree = ({
|
|||||||
return enriched;
|
return enriched;
|
||||||
}
|
}
|
||||||
|
|
||||||
setFolderNodes((prev: Map<FolderId, FolderTreeNode>) => {
|
setFolderNodes((prev: Map<FolderNodeId, FolderTreeNode>) => {
|
||||||
const next = new Map<FolderId, FolderTreeNode>(prev);
|
const next = new Map<FolderNodeId, FolderTreeNode>(prev);
|
||||||
const existingNode = next.get(folderId) || {
|
const existingNode = next.get(folderId) || {
|
||||||
id: folderId,
|
id: folderId,
|
||||||
name: folderId === 'root' ? DEFAULT_FOLDER_NAME : data.folder?.name || 'Folder',
|
name: folderId === 'root' ? DEFAULT_FOLDER_NAME : data.folder?.name || 'Folder',
|
||||||
@@ -326,7 +324,7 @@ const useFolderTree = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
childFolders.forEach((child) => {
|
childFolders.forEach((child) => {
|
||||||
const childId = (child?.id ?? null) as FolderId | null;
|
const childId = (child?.id ?? null) as FolderNodeId | null;
|
||||||
if (!childId) {
|
if (!childId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -346,7 +344,7 @@ const useFolderTree = ({
|
|||||||
next.set(childId, {
|
next.set(childId, {
|
||||||
id: childId,
|
id: childId,
|
||||||
name: child.name,
|
name: child.name,
|
||||||
parentId: (child.parent_id ?? 'root') as FolderId,
|
parentId: (child.parent_id ?? 'root') as FolderNodeId,
|
||||||
children: previousChildren,
|
children: previousChildren,
|
||||||
expanded: childNode?.expanded ?? false,
|
expanded: childNode?.expanded ?? false,
|
||||||
loaded: childNode?.loaded ?? false,
|
loaded: childNode?.loaded ?? false,
|
||||||
@@ -369,11 +367,11 @@ const useFolderTree = ({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
setFolderContents((prev: Map<FolderId, FolderContentsEntry>) => {
|
setFolderContents((prev: Map<FolderNodeId, FolderContentsEntry>) => {
|
||||||
if (tenantIdRef.current !== requestTenantId) {
|
if (tenantIdRef.current !== requestTenantId) {
|
||||||
return prev;
|
return prev;
|
||||||
}
|
}
|
||||||
const next = new Map<FolderId, FolderContentsEntry>(prev);
|
const next = new Map<FolderNodeId, FolderContentsEntry>(prev);
|
||||||
if (includeDocuments) {
|
if (includeDocuments) {
|
||||||
next.set(folderId, enriched);
|
next.set(folderId, enriched);
|
||||||
} else {
|
} else {
|
||||||
@@ -408,7 +406,7 @@ const useFolderTree = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const ensureFolderAncestorsLoaded = useCallback(
|
const ensureFolderAncestorsLoaded = useCallback(
|
||||||
async (targetId: FolderId | null) => {
|
async (targetId: FolderNodeId | null) => {
|
||||||
if (!targetId || targetId === 'root') {
|
if (!targetId || targetId === 'root') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -429,7 +427,7 @@ const useFolderTree = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const isInvalidFolderDrop = useCallback(
|
const isInvalidFolderDrop = useCallback(
|
||||||
(sourceId: FolderId | null, targetId: FolderId | null) => {
|
(sourceId: FolderNodeId | null, targetId: FolderNodeId | null) => {
|
||||||
if (!sourceId) return false;
|
if (!sourceId) return false;
|
||||||
if (!targetId || targetId === 'root') {
|
if (!targetId || targetId === 'root') {
|
||||||
return false;
|
return false;
|
||||||
@@ -456,8 +454,8 @@ const useFolderTree = ({
|
|||||||
|
|
||||||
const resetFolderTreeState = useCallback(() => {
|
const resetFolderTreeState = useCallback(() => {
|
||||||
const rootNode = createRootNode() as FolderTreeNode;
|
const rootNode = createRootNode() as FolderTreeNode;
|
||||||
setFolderNodes(new Map<FolderId, FolderTreeNode>([[rootNode.id, rootNode]]));
|
setFolderNodes(new Map<FolderNodeId, FolderTreeNode>([[rootNode.id, rootNode]]));
|
||||||
setFolderContents(new Map<FolderId, FolderContentsEntry>());
|
setFolderContents(new Map<FolderNodeId, FolderContentsEntry>());
|
||||||
setSelectedFolder('root');
|
setSelectedFolder('root');
|
||||||
setCurrentFolder(null);
|
setCurrentFolder(null);
|
||||||
setCurrentSubfolders([]);
|
setCurrentSubfolders([]);
|
||||||
@@ -469,10 +467,10 @@ const useFolderTree = ({
|
|||||||
}, [selectedFolder, currentFolder]);
|
}, [selectedFolder, currentFolder]);
|
||||||
|
|
||||||
const folderOptions: FolderOption[] = useMemo(() => {
|
const folderOptions: FolderOption[] = useMemo(() => {
|
||||||
const cache = new Map<FolderId, string>();
|
const cache = new Map<FolderNodeId, string>();
|
||||||
const computePath = (id: FolderId | null): string => {
|
const computePath = (id: FolderNodeId | null): string => {
|
||||||
if (cache.has(id as FolderId)) {
|
if (cache.has(id as FolderNodeId)) {
|
||||||
return cache.get(id as FolderId) as string;
|
return cache.get(id as FolderNodeId) as string;
|
||||||
}
|
}
|
||||||
if (!id || id === 'root') {
|
if (!id || id === 'root') {
|
||||||
cache.set('root', DEFAULT_FOLDER_NAME);
|
cache.set('root', DEFAULT_FOLDER_NAME);
|
||||||
@@ -506,7 +504,7 @@ const useFolderTree = ({
|
|||||||
}, [folderNodes]);
|
}, [folderNodes]);
|
||||||
|
|
||||||
const folderLabelMap = useMemo(() => {
|
const folderLabelMap = useMemo(() => {
|
||||||
const map = new Map<FolderId, string>();
|
const map = new Map<FolderNodeId, string>();
|
||||||
folderOptions.forEach((option) => {
|
folderOptions.forEach((option) => {
|
||||||
map.set(option.id, option.label);
|
map.set(option.id, option.label);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ export type Identifier = string;
|
|||||||
|
|
||||||
export type DocumentId = Identifier;
|
export type DocumentId = Identifier;
|
||||||
export type FolderId = Identifier;
|
export type FolderId = Identifier;
|
||||||
|
export type FolderNodeId = FolderId | 'root';
|
||||||
export type CapabilitySetId = Identifier;
|
export type CapabilitySetId = Identifier;
|
||||||
export type CapabilityValue = Identifier;
|
export type CapabilityValue = Identifier;
|
||||||
export type TenantId = Identifier;
|
export type TenantId = Identifier;
|
||||||
|
|||||||
Reference in New Issue
Block a user