* Split permissions for reading documents from updating collection * fix: Admins should have collection read permission, tests * tsc * Add admin option to permission selector * Combine publish and create permissions, update -> createDocuments where appropriate * Plural -> singular * wip * Quick version of collection structure loading, will revisit * Remove documentIds method * stash * fixing tests to account for admin creation * Add self-hosted migration * fix: Allow groups to have admin permission * Prefetch collection documents * fix: Document explorer (move/publish) not working with async documents * fix: Cannot re-parent document to collection by drag and drop * fix: Cannot drag to import into collection item without admin permission * Remove unused isEditor getter
85 lines
2.4 KiB
TypeScript
85 lines
2.4 KiB
TypeScript
import * as React from "react";
|
|
import { NavigationNode, NavigationNodeType } from "@shared/types";
|
|
import Collection from "~/models/Collection";
|
|
import useStores from "~/hooks/useStores";
|
|
|
|
/**
|
|
* React hook that modifies the document structure
|
|
* of all collections present in store. Adds extra attributes
|
|
* like type, depth and parent to each of the nodes in document
|
|
* structure.
|
|
*
|
|
* @return {NavigationNode[]} collectionTrees root collection nodes of modified trees
|
|
*/
|
|
export default function useCollectionTrees(): NavigationNode[] {
|
|
const { collections } = useStores();
|
|
|
|
const getCollectionTree = (collection: Collection): NavigationNode => {
|
|
const addType = (node: NavigationNode): NavigationNode => {
|
|
if (node.children.length > 0) {
|
|
node.children = node.children.map(addType);
|
|
}
|
|
|
|
node.type = node.type ? node.type : NavigationNodeType.Document;
|
|
return node;
|
|
};
|
|
|
|
const addParent = (
|
|
node: NavigationNode,
|
|
parent: NavigationNode | null = null
|
|
): NavigationNode => {
|
|
if (node.children.length > 0) {
|
|
node.children = node.children.map((child) => addParent(child, node));
|
|
}
|
|
|
|
node.parent = parent;
|
|
return node;
|
|
};
|
|
|
|
const addDepth = (node: NavigationNode, depth = 0): NavigationNode => {
|
|
if (node.children.length > 0) {
|
|
node.children = node.children.map((child) =>
|
|
addDepth(child, depth + 1)
|
|
);
|
|
}
|
|
|
|
node.depth = depth;
|
|
return node;
|
|
};
|
|
|
|
const addCollectionId = (
|
|
node: NavigationNode,
|
|
collectionId = collection.id
|
|
): NavigationNode => {
|
|
if (node.children.length > 0) {
|
|
node.children = node.children.map((child) =>
|
|
addCollectionId(child, collectionId)
|
|
);
|
|
}
|
|
|
|
node.collectionId = collectionId;
|
|
return node;
|
|
};
|
|
|
|
const collectionNode: NavigationNode = {
|
|
id: collection.id,
|
|
title: collection.name,
|
|
url: collection.url,
|
|
type: NavigationNodeType.Collection,
|
|
children: collection.documents || [],
|
|
parent: null,
|
|
};
|
|
|
|
return addParent(addCollectionId(addDepth(addType(collectionNode))));
|
|
};
|
|
|
|
const key = collections.orderedData.map((o) => o.documents?.length).join("-");
|
|
const collectionTrees = React.useMemo(
|
|
() => collections.orderedData.map(getCollectionTree),
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
[collections.orderedData, key]
|
|
);
|
|
|
|
return collectionTrees;
|
|
}
|