UNPKG

alinea

Version:
261 lines (259 loc) 7.71 kB
import { require_dataloader } from "../../chunks/chunk-3TNMMA3W.js"; import { useAtomValue } from "../../chunks/chunk-TOJF2G3X.js"; import { atom } from "../../chunks/chunk-WJ67RR7S.js"; import { PLazy } from "../../chunks/chunk-IKINPSS5.js"; import { __toESM } from "../../chunks/chunk-NZLE2WMY.js"; // src/dashboard/atoms/EntryAtoms.ts var import_dataloader = __toESM(require_dataloader(), 1); import { Config } from "alinea/core/Config"; import { Entry } from "alinea/core/Entry"; import { getRoot, getType } from "alinea/core/Internal"; import { Type } from "alinea/core/Type"; import { entries } from "alinea/core/util/Objects"; import { parents, translations } from "alinea/query"; import { useMemo } from "react"; import { configAtom } from "./DashboardAtoms.js"; import { dbAtom } from "./DbAtoms.js"; import { localeAtom, rootAtom, workspaceAtom } from "./NavigationAtoms.js"; var ROOT_ID = "@alinea/root"; var visibleTypesAtom = atom((get) => { const { schema } = get(configAtom); return entries(schema).filter(([_, type]) => !Type.isHidden(type)).map(([name]) => name); }); async function getHasChildren(graph, workspace, root, parentId, visibleTypes) { return Boolean( await graph.first({ workspace, root, parentId, filter: { _type: { in: visibleTypes } }, status: "preferDraft" }) ); } function childrenOf(graph, locale, workspace, root, parentId, visibleTypes, orderBy) { return PLazy.from(async () => { const children = await graph.find({ select: { id: Entry.id, locale: Entry.locale }, orderBy, workspace, root, parentId, filter: { _type: { in: visibleTypes } }, status: "preferDraft" }); const untranslated = /* @__PURE__ */ new Set(); const translatedChildren = new Set( children.filter((child) => child.locale === locale).map((child) => child.id) ); const orderedChildren = children.filter((child) => { if (translatedChildren.has(child.id)) return child.locale === locale; if (untranslated.has(child.id)) return false; untranslated.add(child.id); return true; }); return [...new Set(orderedChildren.map((child) => child.id))]; }); } async function entryTreeRoot(graph, locale, workspace, rootName, visibleTypes) { const root = graph.config.workspaces[workspace][rootName]; const orderBy = getRoot(root).orderChildrenBy; return { id: ROOT_ID, index: "", type: ROOT_ID, isFolder: true, isRoot: true, entries: [], hasChildren: true, children: childrenOf( graph, locale, workspace, rootName, null, visibleTypes, orderBy ) }; } var loaderAtom = atom((get) => { const graph = get(dbAtom); const locale = get(localeAtom); const visibleTypes = get(visibleTypesAtom); const { schema } = get(configAtom); const root = get(rootAtom); const workspace = get(workspaceAtom); return new import_dataloader.default(async (ids) => { const indexed = /* @__PURE__ */ new Map(); const search = ids.filter((id) => id !== ROOT_ID); const data = { id: Entry.id, type: Entry.type, title: Entry.title, status: Entry.status, locale: Entry.locale, workspace: Entry.workspace, main: Entry.main, root: Entry.root, path: Entry.path, parents: parents({ select: { path: Entry.path, type: Entry.type } }) }; const rows = await graph.find({ groupBy: Entry.id, select: { id: Entry.id, index: Entry.index, type: Entry.type, data, translations: translations({ select: data }) }, id: { in: search }, status: "preferDraft" }); for (const row of rows) { const canDrag = row.data.parents.length > 0 ? !getType(schema[row.data.parents.at(-1).type]).orderChildrenBy : true; const type = schema[row.type]; const typeConfig = getType(type); const orderBy = typeConfig.orderChildrenBy; const children = childrenOf( graph, locale, row.data.workspace, row.data.root, row.id, visibleTypes, orderBy ); const hasChildren = typeConfig.contains ? await getHasChildren( graph, row.data.workspace, row.data.root, row.id, visibleTypes ) : false; const entries2 = [row.data].concat(row.translations); indexed.set(row.id, { id: row.id, type: row.type, index: row.index, entries: entries2, canDrag, hasChildren, children }); } const res = []; for (const id of ids) { if (id === ROOT_ID) { res.push( await entryTreeRoot( graph, locale, workspace.name, root.name, visibleTypes ) ); continue; } const entry = indexed.get(id); if (!entry) { res.push(void 0); continue; } const typeName = entry.entries[0].type; const type = schema[typeName]; const isFolder = Type.isContainer(type); res.push({ ...entry, isFolder }); } return res; }); }); function useEntryTreeProvider() { const loader = useAtomValue(loaderAtom); const db = useAtomValue(dbAtom); return useMemo(() => { return { canDrag(items) { return items.every((item) => { const data = item.getItemData(); return data.canDrag; }); }, canDrop(items, target) { const { item: parent } = target; if (items.length !== 1) return false; const [dropping] = items; const newParent = dropping.getParent() !== parent; const parentData = parent.getItemData(); const droppingData = dropping.getItemData(); if (!droppingData) return false; const childType = db.config.schema[droppingData.type]; if (!parentData) return false; if (parentData.type === ROOT_ID) { const entry = droppingData.entries[0]; const root = db.config.workspaces[entry.workspace][entry.root]; const orderBy2 = getRoot(root).orderChildrenBy; return !newParent ? !orderBy2 : Config.rootContains(db.config, root, childType); } const parentType = db.config.schema[parentData.type]; const orderBy = getType(parentType).orderChildrenBy; return !newParent ? !orderBy : Config.typeContains(db.config, parentType, childType); }, onDrop(items, target) { const { item: parent } = target; if (items.length !== 1) return; const [dropping] = items; const children = parent.getChildren(); const previous = "childIndex" in target ? children[target.childIndex - 1] : null; const after = previous ? previous.getId() : null; const newParent = dropping.getParent() !== parent; const toRoot = parent.getId().startsWith("@alinea") ? dropping.getItemData().entries[0].root : void 0; const toParent = !toRoot && newParent ? parent.getId() : void 0; db.move({ id: dropping.getId(), after, toParent, toRoot }); }, async getItem(id) { const data = await loader.clear(id).load(id); if (!data) throw new Error(`Item ${id} not found`); return data; }, async getChildren(id) { return this.getItem(id).then((item) => item?.children ?? []); } }; }, [loader]); } export { ROOT_ID, useEntryTreeProvider };