wip fix
This commit is contained in:
parent
fd0b71bc8f
commit
812bb40b31
|
|
@ -27,7 +27,7 @@ export const EdBase = () => {
|
||||||
edRoute(p);
|
edRoute(p);
|
||||||
|
|
||||||
if (p.status === "loading") {
|
if (p.status === "loading") {
|
||||||
return <Loading note={`base-${p.status}-page`} />;
|
return <Loading note={`page-${p.status}`} />;
|
||||||
}
|
}
|
||||||
if (p.status === "site-not-found" || p.status === "page-not-found") {
|
if (p.status === "site-not-found" || p.status === "page-not-found") {
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -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 { 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 { EDGlobal } from "./logic/ed-global";
|
||||||
import { EdApi } from "./panel/header/left/api";
|
import { EdApi } from "./panel/header/left/api";
|
||||||
import { EdSiteJS } from "./panel/header/left/js";
|
import { EdSiteJS } from "./panel/header/left/js";
|
||||||
|
|
@ -10,6 +11,7 @@ import { EdTreeSearch } from "./panel/tree/search";
|
||||||
|
|
||||||
export const EdLeft = () => {
|
export const EdLeft = () => {
|
||||||
const p = useGlobal(EDGlobal, "EDITOR");
|
const p = useGlobal(EDGlobal, "EDITOR");
|
||||||
|
const local = useLocal({ tree: null as any });
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cx(
|
className={cx(
|
||||||
|
|
@ -33,11 +35,25 @@ export const EdLeft = () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<EdTreeSearch />
|
<EdTreeSearch />
|
||||||
<div className="tree-body flex relative flex-1 overflow-y-auto overflow-x-hidden">
|
<div
|
||||||
|
className="tree-body flex relative flex-1 overflow-y-auto overflow-x-hidden"
|
||||||
|
ref={(ref) => {
|
||||||
|
if (ref) local.tree = ref;
|
||||||
|
}}
|
||||||
|
>
|
||||||
<div className="absolute inset-0 flex flex-col">
|
<div className="absolute inset-0 flex flex-col">
|
||||||
<DndProvider backend={MultiBackend} options={getBackendOptions()}>
|
{local.tree && (
|
||||||
<EdTreeBody />
|
<DndProvider
|
||||||
</DndProvider>
|
backend={HTML5Backend}
|
||||||
|
options={getBackendOptions({
|
||||||
|
html5: {
|
||||||
|
rootElement: local.tree,
|
||||||
|
},
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<EdTreeBody />
|
||||||
|
</DndProvider>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ export const EdPagePicker = () => {
|
||||||
<TopBtn
|
<TopBtn
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
p.ui.popup.page.open = (page_id) => {
|
p.ui.popup.page.open = (page_id) => {
|
||||||
|
p.ui.popup.page.open = null;
|
||||||
navigate(`/ed/${p.site.id}/${page_id}`);
|
navigate(`/ed/${p.site.id}/${page_id}`);
|
||||||
};
|
};
|
||||||
p.render();
|
p.render();
|
||||||
|
|
|
||||||
|
|
@ -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 { 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 { Loading } from "../../../../../utils/ui/loading";
|
||||||
import { Modal } from "../../../../../utils/ui/modal";
|
import { Modal } from "../../../../../utils/ui/modal";
|
||||||
import { EDGlobal } from "../../../logic/ed-global";
|
import { EDGlobal } from "../../../logic/ed-global";
|
||||||
|
|
@ -9,25 +15,38 @@ import { PageItem, edPageTreeRender } from "./page-tree";
|
||||||
|
|
||||||
export const EdPagePop = () => {
|
export const EdPagePop = () => {
|
||||||
const p = useGlobal(EDGlobal, "EDITOR");
|
const p = useGlobal(EDGlobal, "EDITOR");
|
||||||
const local = useLocal({});
|
const local = useLocal({
|
||||||
|
tree: null as TreeMethods | null,
|
||||||
|
});
|
||||||
const TypedTree = DNDTree<PageItem>;
|
const TypedTree = DNDTree<PageItem>;
|
||||||
pagePicker.render = local.render;
|
pagePicker.render = local.render;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
p.ui.popup.page.open = () => {};
|
waitUntil(() => local.tree).then(() => {
|
||||||
|
if (local.tree) {
|
||||||
(async () => {
|
const parents: string[] = [];
|
||||||
if (pagePicker.status === "ready") {
|
let cur = pagePicker.tree.find((e) => e.id === p.page.cur.id);
|
||||||
reloadPagePicker(p);
|
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.ui.popup.page.open) return null;
|
||||||
|
|
||||||
|
if (p.site.id !== pagePicker.site_id) {
|
||||||
|
pagePicker.site_id = p.site.id;
|
||||||
|
reloadPagePicker(p);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{pagePicker.status === "loading" && <Loading note="listing-page" />}
|
|
||||||
<Modal
|
<Modal
|
||||||
open
|
open
|
||||||
onOpenChange={(open) => {
|
onOpenChange={(open) => {
|
||||||
|
|
@ -37,16 +56,47 @@ export const EdPagePop = () => {
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="absolute inset-[5%] bg-white flex">
|
<div
|
||||||
<div className="relative flex flex-1">
|
id="page-picker"
|
||||||
<DndProvider backend={MultiBackend} options={getBackendOptions()}>
|
ref={(ref) => {
|
||||||
<TypedTree
|
if (ref) {
|
||||||
tree={pagePicker.tree}
|
pagePicker.ref = ref;
|
||||||
rootId={"root"}
|
}
|
||||||
onDrop={() => {}}
|
}}
|
||||||
render={edPageTreeRender}
|
className={cx(
|
||||||
/>
|
"absolute inset-[5%] bg-white flex",
|
||||||
</DndProvider>
|
css`
|
||||||
|
z-index: 100;
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<div className="relative flex flex-1 items-stretch text-[12px] overflow-auto">
|
||||||
|
{pagePicker.status === "loading" && <Loading note="listing-page" backdrop={false} />}
|
||||||
|
|
||||||
|
{pagePicker.ref && (
|
||||||
|
<DndProvider
|
||||||
|
backend={HTML5Backend}
|
||||||
|
options={getBackendOptions({
|
||||||
|
html5: {
|
||||||
|
rootElement: pagePicker.ref,
|
||||||
|
},
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<TypedTree
|
||||||
|
ref={(ref) => {
|
||||||
|
if (local.tree !== ref) {
|
||||||
|
local.tree = ref;
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
tree={pagePicker.tree}
|
||||||
|
rootId={"page-root"}
|
||||||
|
onDrop={() => {}}
|
||||||
|
canDrag={() => true}
|
||||||
|
classes={{ root: "flex-1" }}
|
||||||
|
render={edPageTreeRender}
|
||||||
|
/>
|
||||||
|
</DndProvider>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
import { NodeModel } from "@minoru/react-dnd-treeview";
|
import { NodeModel } from "@minoru/react-dnd-treeview";
|
||||||
import { PageItem } from "./page-tree";
|
|
||||||
import { PG } from "../../../logic/ed-global";
|
import { PG } from "../../../logic/ed-global";
|
||||||
|
import { PageItem } from "./page-tree";
|
||||||
|
|
||||||
export const pagePicker = {
|
export const pagePicker = {
|
||||||
|
site_id: "",
|
||||||
|
ref: null as any,
|
||||||
tree: [] as NodeModel<PageItem>[],
|
tree: [] as NodeModel<PageItem>[],
|
||||||
status: "ready" as "loading" | "ready",
|
status: "ready" as "loading" | "ready",
|
||||||
render: () => {},
|
render: () => {},
|
||||||
|
|
@ -10,7 +12,6 @@ export const pagePicker = {
|
||||||
|
|
||||||
export const reloadPagePicker = async (p: PG) => {
|
export const reloadPagePicker = async (p: PG) => {
|
||||||
pagePicker.status = "loading";
|
pagePicker.status = "loading";
|
||||||
pagePicker.render();
|
|
||||||
|
|
||||||
const pages = await db.page.findMany({
|
const pages = await db.page.findMany({
|
||||||
where: { id_site: p.site.id, is_deleted: false },
|
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 },
|
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.status = "ready";
|
||||||
pagePicker.render();
|
pagePicker.render();
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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 = {
|
export type PageItem = {
|
||||||
id: string;
|
id: string;
|
||||||
|
name: string;
|
||||||
|
url?: string;
|
||||||
|
type: "page" | "folder";
|
||||||
};
|
};
|
||||||
export const edPageTreeRender = () => {
|
export const edPageTreeRender: NodeRender<PageItem> = (
|
||||||
return <></>;
|
node: NodeModel<PageItem>,
|
||||||
|
{ depth, isOpen, onToggle }
|
||||||
|
) => {
|
||||||
|
const p = useGlobal(EDGlobal, "EDITOR");
|
||||||
|
const item = node.data;
|
||||||
|
if (!item) return <></>;
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="px-1 pl-2 flex border-b py-[2px] items-center hover:bg-blue-50 cursor-pointer relative"
|
||||||
|
onClick={() => {
|
||||||
|
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 && (
|
||||||
|
<div className="absolute left-0 top-0 bottom-0 bg-blue-500 w-1"></div>
|
||||||
|
)}
|
||||||
|
<div
|
||||||
|
className={cx(
|
||||||
|
"h-[13px] ",
|
||||||
|
css`
|
||||||
|
width: ${depth * 13}px;
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
></div>
|
||||||
|
{item.type === "folder" && (
|
||||||
|
<>
|
||||||
|
{isOpen && <FolderOpen />}
|
||||||
|
{!isOpen && <FolderClose />}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
<div className="pl-1 flex-1">{item.name}</div>
|
||||||
|
<div className="pl-1 flex-1">{item.url}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const FolderClose = () => (
|
||||||
|
<svg
|
||||||
|
fill="currentColor"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
strokeWidth={1}
|
||||||
|
width={13}
|
||||||
|
height={13}
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
<path d="M2 6a2 2 0 012-2h5l2 2h5a2 2 0 012 2v6a2 2 0 01-2 2H4a2 2 0 01-2-2V6z" />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
|
||||||
|
const FolderOpen = () => (
|
||||||
|
<svg
|
||||||
|
fill="currentColor"
|
||||||
|
strokeWidth={1}
|
||||||
|
width={13}
|
||||||
|
height={13}
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
clipRule="evenodd"
|
||||||
|
fillRule="evenodd"
|
||||||
|
d="M2 6a2 2 0 012-2h4l2 2h4a2 2 0 012 2v1H8a3 3 0 00-3 3v1.5a1.5 1.5 0 01-3 0V6z"
|
||||||
|
/>
|
||||||
|
<path d="M6 12a2 2 0 012-2h8a2 2 0 012 2v2a2 2 0 01-2 2H2h2a2 2 0 002-2v-2z" />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,6 @@ export const EdPopSite = () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{local.status === "loading" && <Loading note="listing-site" />}
|
|
||||||
<Modal
|
<Modal
|
||||||
open
|
open
|
||||||
onOpenChange={(open) => {
|
onOpenChange={(open) => {
|
||||||
|
|
@ -94,8 +93,17 @@ export const EdPopSite = () => {
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="absolute inset-[5%] bg-white flex">
|
<div
|
||||||
|
className={cx(
|
||||||
|
"absolute inset-[5%] bg-white flex",
|
||||||
|
css`
|
||||||
|
z-index: 100;
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
>
|
||||||
<div className="relative flex flex-1">
|
<div className="relative flex flex-1">
|
||||||
|
{local.status === "loading" && <Loading note="listing-site" backdrop={false} />}
|
||||||
|
|
||||||
{(local.status === "ready" || local.group.length > 0) && (
|
{(local.status === "ready" || local.group.length > 0) && (
|
||||||
<SitePicker
|
<SitePicker
|
||||||
group={local.group}
|
group={local.group}
|
||||||
|
|
|
||||||
|
|
@ -42,13 +42,13 @@ export const EdTreeBody = () => {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (local.tree) {
|
if (local.tree) {
|
||||||
let parents = [];
|
let parents: string[] = [];
|
||||||
if (active.comp_id) {
|
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;
|
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;
|
parents = p.page.scope[active.item_id].p;
|
||||||
}
|
}
|
||||||
if (parents.length === 1) {
|
if (parents.length <= 1) {
|
||||||
local.tree.open(
|
local.tree.open(
|
||||||
tree.filter((e) => e.parent === "root").map((e) => e.id)
|
tree.filter((e) => e.parent === "root").map((e) => e.id)
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -163,6 +163,7 @@ export const ModalContent = React.forwardRef<
|
||||||
"modal-overlay",
|
"modal-overlay",
|
||||||
"flex items-center justify-center transition-all ",
|
"flex items-center justify-center transition-all ",
|
||||||
css`
|
css`
|
||||||
|
z-index: 100;
|
||||||
background: rgba(0, 0, 0, 0.3);
|
background: rgba(0, 0, 0, 0.3);
|
||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue