From 812bb40b31a64beaa08f9181aec09366dfd1b446 Mon Sep 17 00:00:00 2001 From: Rizky Date: Sat, 25 Nov 2023 13:56:53 +0700 Subject: [PATCH] wip fix --- app/web/src/nova/ed/ed-base.tsx | 2 +- app/web/src/nova/ed/ed-left.tsx | 28 ++++-- .../nova/ed/panel/header/mid/page-picker.tsx | 1 + .../nova/ed/panel/popup/page/page-popup.tsx | 92 ++++++++++++++----- .../nova/ed/panel/popup/page/page-reload.ts | 35 ++++++- .../nova/ed/panel/popup/page/page-tree.tsx | 81 +++++++++++++++- .../nova/ed/panel/popup/site/site-popup.tsx | 12 ++- app/web/src/nova/ed/panel/tree/body.tsx | 8 +- app/web/src/utils/ui/modal.tsx | 1 + 9 files changed, 222 insertions(+), 38 deletions(-) diff --git a/app/web/src/nova/ed/ed-base.tsx b/app/web/src/nova/ed/ed-base.tsx index 4056832e..25c92435 100644 --- a/app/web/src/nova/ed/ed-base.tsx +++ b/app/web/src/nova/ed/ed-base.tsx @@ -27,7 +27,7 @@ export const EdBase = () => { edRoute(p); if (p.status === "loading") { - return ; + return ; } if (p.status === "site-not-found" || p.status === "page-not-found") { return ( diff --git a/app/web/src/nova/ed/ed-left.tsx b/app/web/src/nova/ed/ed-left.tsx index 41e1e4ae..decf2971 100644 --- a/app/web/src/nova/ed/ed-left.tsx +++ b/app/web/src/nova/ed/ed-left.tsx @@ -1,6 +1,7 @@ -import { MultiBackend, getBackendOptions } from "@minoru/react-dnd-treeview"; +import { getBackendOptions } from "@minoru/react-dnd-treeview"; import { DndProvider } from "react-dnd"; -import { useGlobal } from "web-utils"; +import { HTML5Backend } from "react-dnd-html5-backend"; +import { useGlobal, useLocal } from "web-utils"; import { EDGlobal } from "./logic/ed-global"; import { EdApi } from "./panel/header/left/api"; import { EdSiteJS } from "./panel/header/left/js"; @@ -10,6 +11,7 @@ import { EdTreeSearch } from "./panel/tree/search"; export const EdLeft = () => { const p = useGlobal(EDGlobal, "EDITOR"); + const local = useLocal({ tree: null as any }); return (
{
-
+
{ + if (ref) local.tree = ref; + }} + >
- - - + {local.tree && ( + + + + )}
diff --git a/app/web/src/nova/ed/panel/header/mid/page-picker.tsx b/app/web/src/nova/ed/panel/header/mid/page-picker.tsx index e08a2b90..33121e0e 100644 --- a/app/web/src/nova/ed/panel/header/mid/page-picker.tsx +++ b/app/web/src/nova/ed/panel/header/mid/page-picker.tsx @@ -9,6 +9,7 @@ export const EdPagePicker = () => { { p.ui.popup.page.open = (page_id) => { + p.ui.popup.page.open = null; navigate(`/ed/${p.site.id}/${page_id}`); }; p.render(); diff --git a/app/web/src/nova/ed/panel/popup/page/page-popup.tsx b/app/web/src/nova/ed/panel/popup/page/page-popup.tsx index 6950d247..2397c383 100644 --- a/app/web/src/nova/ed/panel/popup/page/page-popup.tsx +++ b/app/web/src/nova/ed/panel/popup/page/page-popup.tsx @@ -1,6 +1,12 @@ -import { Tree as DNDTree, DndProvider, MultiBackend, getBackendOptions } from "@minoru/react-dnd-treeview"; +import { + Tree as DNDTree, + DndProvider, + TreeMethods, + getBackendOptions, +} from "@minoru/react-dnd-treeview"; import { useEffect } from "react"; -import { useGlobal, useLocal } from "web-utils"; +import { HTML5Backend } from "react-dnd-html5-backend"; +import { useGlobal, useLocal, waitUntil } from "web-utils"; import { Loading } from "../../../../../utils/ui/loading"; import { Modal } from "../../../../../utils/ui/modal"; import { EDGlobal } from "../../../logic/ed-global"; @@ -9,25 +15,38 @@ import { PageItem, edPageTreeRender } from "./page-tree"; export const EdPagePop = () => { const p = useGlobal(EDGlobal, "EDITOR"); - const local = useLocal({}); + const local = useLocal({ + tree: null as TreeMethods | null, + }); const TypedTree = DNDTree; pagePicker.render = local.render; useEffect(() => { - p.ui.popup.page.open = () => {}; - - (async () => { - if (pagePicker.status === "ready") { - reloadPagePicker(p); + waitUntil(() => local.tree).then(() => { + if (local.tree) { + const parents: string[] = []; + let cur = pagePicker.tree.find((e) => e.id === p.page.cur.id); + while (cur) { + if (typeof cur.id === "string") { + const parent_id = cur.parent; + parents.push(cur.id); + cur = pagePicker.tree.find((e) => e.id === parent_id); + } + } + local.tree.open(parents); } - })(); - }, [p.site.id]); + }); + }, [p.ui.popup.page.open]); if (!p.ui.popup.page.open) return null; + if (p.site.id !== pagePicker.site_id) { + pagePicker.site_id = p.site.id; + reloadPagePicker(p); + } + return ( <> - {pagePicker.status === "loading" && } { @@ -37,16 +56,47 @@ export const EdPagePop = () => { } }} > -
-
- - {}} - render={edPageTreeRender} - /> - +
{ + if (ref) { + pagePicker.ref = ref; + } + }} + className={cx( + "absolute inset-[5%] bg-white flex", + css` + z-index: 100; + ` + )} + > +
+ {pagePicker.status === "loading" && } + + {pagePicker.ref && ( + + { + if (local.tree !== ref) { + local.tree = ref; + } + }} + tree={pagePicker.tree} + rootId={"page-root"} + onDrop={() => {}} + canDrag={() => true} + classes={{ root: "flex-1" }} + render={edPageTreeRender} + /> + + )}
diff --git a/app/web/src/nova/ed/panel/popup/page/page-reload.ts b/app/web/src/nova/ed/panel/popup/page/page-reload.ts index 6cf8f817..4213b19a 100644 --- a/app/web/src/nova/ed/panel/popup/page/page-reload.ts +++ b/app/web/src/nova/ed/panel/popup/page/page-reload.ts @@ -1,8 +1,10 @@ import { NodeModel } from "@minoru/react-dnd-treeview"; -import { PageItem } from "./page-tree"; import { PG } from "../../../logic/ed-global"; +import { PageItem } from "./page-tree"; export const pagePicker = { + site_id: "", + ref: null as any, tree: [] as NodeModel[], status: "ready" as "loading" | "ready", render: () => {}, @@ -10,7 +12,6 @@ export const pagePicker = { export const reloadPagePicker = async (p: PG) => { pagePicker.status = "loading"; - pagePicker.render(); const pages = await db.page.findMany({ where: { id_site: p.site.id, is_deleted: false }, @@ -29,6 +30,36 @@ export const reloadPagePicker = async (p: PG) => { select: { id: true, is_deleted: false, name: true, parent_id: true }, }); + pagePicker.tree = []; + const tree = pagePicker.tree; + for (const page of pages) { + tree.push({ + id: page.id, + parent: page.id_folder || "page-root", + text: page.name, + data: { + id: page.id, + name: page.name, + type: "page", + url: page.url, + }, + }); + } + + for (const folder of folders) { + tree.push({ + id: folder.id, + parent: folder.parent_id || "page-root", + text: folder.name || "", + droppable: true, + data: { + id: folder.id, + name: folder.name || "", + type: "folder", + }, + }); + } + pagePicker.status = "ready"; pagePicker.render(); }; diff --git a/app/web/src/nova/ed/panel/popup/page/page-tree.tsx b/app/web/src/nova/ed/panel/popup/page/page-tree.tsx index e402f6e7..603d2894 100644 --- a/app/web/src/nova/ed/panel/popup/page/page-tree.tsx +++ b/app/web/src/nova/ed/panel/popup/page/page-tree.tsx @@ -1,6 +1,83 @@ +import { NodeModel, NodeRender } from "@minoru/react-dnd-treeview"; +import { useGlobal } from "web-utils"; +import { EDGlobal } from "../../../logic/ed-global"; + export type PageItem = { id: string; + name: string; + url?: string; + type: "page" | "folder"; }; -export const edPageTreeRender = () => { - return <>; +export const edPageTreeRender: NodeRender = ( + node: NodeModel, + { depth, isOpen, onToggle } +) => { + const p = useGlobal(EDGlobal, "EDITOR"); + const item = node.data; + if (!item) return <>; + return ( +
{ + if (item.type === "folder") { + onToggle(); + } else if (p.ui.popup.page.open) { + p.ui.popup.page.open(item.id); + } + }} + > + {item.id === p.page.cur.id && ( +
+ )} +
+ {item.type === "folder" && ( + <> + {isOpen && } + {!isOpen && } + + )} +
{item.name}
+
{item.url}
+
+ ); }; + +const FolderClose = () => ( + +); + +const FolderOpen = () => ( + +); diff --git a/app/web/src/nova/ed/panel/popup/site/site-popup.tsx b/app/web/src/nova/ed/panel/popup/site/site-popup.tsx index 74306845..003cc7b1 100644 --- a/app/web/src/nova/ed/panel/popup/site/site-popup.tsx +++ b/app/web/src/nova/ed/panel/popup/site/site-popup.tsx @@ -84,7 +84,6 @@ export const EdPopSite = () => { return ( <> - {local.status === "loading" && } { @@ -94,8 +93,17 @@ export const EdPopSite = () => { } }} > -
+
+ {local.status === "loading" && } + {(local.status === "ready" || local.group.length > 0) && ( { useEffect(() => { if (local.tree) { - let parents = []; - if (active.comp_id) { + let parents: string[] = []; + if (active.comp_id && p.comp.list[local.comp_id].scope[active.item_id]) { parents = p.comp.list[local.comp_id].scope[active.item_id].p; - } else { + } else if (p.page.scope[active.item_id]) { parents = p.page.scope[active.item_id].p; } - if (parents.length === 1) { + if (parents.length <= 1) { local.tree.open( tree.filter((e) => e.parent === "root").map((e) => e.id) ); diff --git a/app/web/src/utils/ui/modal.tsx b/app/web/src/utils/ui/modal.tsx index 2001d48b..46f81e86 100644 --- a/app/web/src/utils/ui/modal.tsx +++ b/app/web/src/utils/ui/modal.tsx @@ -163,6 +163,7 @@ export const ModalContent = React.forwardRef< "modal-overlay", "flex items-center justify-center transition-all ", css` + z-index: 100; background: rgba(0, 0, 0, 0.3); display: grid; place-items: center;