wip fix
This commit is contained in:
parent
ac5117b4ab
commit
3429621f3e
|
|
@ -10,11 +10,12 @@ import { edUndoManager } from "./logic/ed-undo";
|
|||
import { EdPane } from "./panel/main/pane-resize";
|
||||
import { EdPopCode } from "./panel/popup/code/code";
|
||||
import { EdPopCompGroup } from "./panel/popup/comp/comp-group";
|
||||
import { EdPagePop } from "./panel/popup/page/page-popup";
|
||||
import { EdPopPage } from "./panel/popup/page/page-popup";
|
||||
import { EdPopScript } from "./panel/popup/script/pop-script";
|
||||
import { EdPopSite } from "./panel/popup/site/site-popup";
|
||||
import { EdScriptInit } from "./panel/script/monaco/init";
|
||||
import { EdPopApi } from "./panel/popup/api/api-server";
|
||||
import { EdPopComp } from "./panel/popup/comp/comp-popup";
|
||||
|
||||
export const EdBase = () => {
|
||||
const p = useGlobal(EDGlobal, "EDITOR");
|
||||
|
|
@ -53,8 +54,9 @@ export const EdBase = () => {
|
|||
<EdPopScript />
|
||||
<EdPopSite />
|
||||
<EdPopApi />
|
||||
<EdPagePop />
|
||||
<EdPopPage />
|
||||
<EdPopCompGroup />
|
||||
<EdPopComp />
|
||||
<EdScriptInit />
|
||||
</>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ export const EdMid: FC<{}> = () => {
|
|||
<EdPagePicker />
|
||||
</div>
|
||||
|
||||
<div className="flex items-stretch">
|
||||
<div className="flex items-center">
|
||||
<EdCompPicker />
|
||||
</div>
|
||||
<div className="flex items-stretch justify-end"></div>
|
||||
|
|
|
|||
|
|
@ -240,7 +240,9 @@ export const EDGlobal = {
|
|||
domain?: string;
|
||||
responsive?: string;
|
||||
},
|
||||
comp: null as null | ((comp_id: string) => void | Promise<void>),
|
||||
comp: {
|
||||
open: null as null | ((comp_id: string) => void | Promise<void>),
|
||||
},
|
||||
comp_group: null as null | {
|
||||
mouse_event: React.MouseEvent<HTMLElement, MouseEvent>;
|
||||
on_pick?: (group_id: string) => void | Promise<void>;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,10 @@ export const EdCompPicker = () => {
|
|||
|
||||
return (
|
||||
<TopBtn
|
||||
onClick={(e) => {}}
|
||||
onClick={(e) => {
|
||||
p.ui.popup.comp.open = (comp_id) => {};
|
||||
p.render();
|
||||
}}
|
||||
style="slim"
|
||||
>
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -0,0 +1,90 @@
|
|||
import {
|
||||
Tree as DNDTree,
|
||||
DndProvider,
|
||||
TreeMethods,
|
||||
getBackendOptions,
|
||||
} from "@minoru/react-dnd-treeview";
|
||||
import { useEffect } from "react";
|
||||
import { HTML5Backend } from "react-dnd-html5-backend";
|
||||
import { useGlobal, useLocal } from "web-utils";
|
||||
import { Loading } from "../../../../../utils/ui/loading";
|
||||
import { Modal } from "../../../../../utils/ui/modal";
|
||||
import { EDGlobal } from "../../../logic/ed-global";
|
||||
import { compPicker, reloadCompPicker } from "./comp-reload";
|
||||
import { CompItem, edPageTreeRender } from "./comp-tree";
|
||||
|
||||
export const EdPopComp = () => {
|
||||
const p = useGlobal(EDGlobal, "EDITOR");
|
||||
const local = useLocal({
|
||||
tree: null as TreeMethods | null,
|
||||
});
|
||||
const TypedTree = DNDTree<CompItem>;
|
||||
compPicker.render = local.render;
|
||||
|
||||
useEffect(() => {
|
||||
// waitUntil(() => local.tree).then(() => {});
|
||||
}, [p.ui.popup.comp.open, compPicker.site_id]);
|
||||
|
||||
if (!p.ui.popup.comp.open) return null;
|
||||
|
||||
if (p.site.id !== compPicker.site_id) {
|
||||
compPicker.site_id = p.site.id;
|
||||
reloadCompPicker(p);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Modal
|
||||
open
|
||||
onOpenChange={(open) => {
|
||||
if (!open) {
|
||||
p.ui.popup.comp.open = null;
|
||||
p.render();
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div
|
||||
id="comp-picker"
|
||||
ref={(ref) => {
|
||||
if (ref) {
|
||||
compPicker.ref = ref;
|
||||
}
|
||||
}}
|
||||
className={cx("absolute inset-[5%] bg-white flex")}
|
||||
>
|
||||
<div className="relative flex flex-1 items-stretch text-[12px] overflow-auto">
|
||||
{compPicker.status === "loading" && (
|
||||
<Loading note="listing-comp" backdrop={false} />
|
||||
)}
|
||||
|
||||
{compPicker.ref && (
|
||||
<DndProvider
|
||||
backend={HTML5Backend}
|
||||
options={getBackendOptions({
|
||||
html5: {
|
||||
rootElement: compPicker.ref,
|
||||
},
|
||||
})}
|
||||
>
|
||||
<TypedTree
|
||||
ref={(ref) => {
|
||||
if (local.tree !== ref) {
|
||||
local.tree = ref;
|
||||
}
|
||||
}}
|
||||
tree={compPicker.tree}
|
||||
rootId={"comp-root"}
|
||||
onDrop={() => {}}
|
||||
dragPreviewRender={() => <></>}
|
||||
canDrag={() => true}
|
||||
classes={{ root: "flex-1" }}
|
||||
render={edPageTreeRender}
|
||||
/>
|
||||
</DndProvider>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { NodeModel } from "@minoru/react-dnd-treeview";
|
||||
import { PG } from "../../../logic/ed-global";
|
||||
import { CompItem } from "./comp-tree";
|
||||
|
||||
export const compPicker = {
|
||||
site_id: "",
|
||||
ref: null as any,
|
||||
tree: [] as NodeModel<CompItem>[],
|
||||
status: "ready" as "loading" | "ready",
|
||||
render: () => {},
|
||||
};
|
||||
|
||||
export const reloadCompPicker = async (p: PG) => {
|
||||
compPicker.status = "loading";
|
||||
|
||||
compPicker.status = "ready";
|
||||
compPicker.render();
|
||||
};
|
||||
|
|
@ -0,0 +1,284 @@
|
|||
import { NodeModel, NodeRender } from "@minoru/react-dnd-treeview";
|
||||
import { FC } from "react";
|
||||
import { useGlobal, useLocal } from "web-utils";
|
||||
import { EDGlobal } from "../../../logic/ed-global";
|
||||
import { compPicker, reloadCompPicker } from "./comp-reload";
|
||||
|
||||
export type CompItem = {
|
||||
id: string;
|
||||
name: string;
|
||||
type: "page" | "folder";
|
||||
};
|
||||
export const edPageTreeRender: NodeRender<CompItem> = (
|
||||
node: NodeModel<CompItem>,
|
||||
{ depth, isOpen, onToggle }
|
||||
) => {
|
||||
const p = useGlobal(EDGlobal, "EDITOR");
|
||||
const local = useLocal({ renaming: node.id === "", rename_to: "" });
|
||||
const item = node.data;
|
||||
if (!item) return <></>;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cx(
|
||||
"flex border-b py-[2px] items-center hover:bg-blue-50 cursor-pointer relative",
|
||||
css`
|
||||
.btn {
|
||||
opacity: 0;
|
||||
}
|
||||
&:hover .btn {
|
||||
opacity: 1;
|
||||
}
|
||||
`,
|
||||
item.id === p.page.cur.id && `bg-blue-50`
|
||||
)}
|
||||
onClick={() => {
|
||||
if (item.type === "folder") {
|
||||
onToggle();
|
||||
} else if (p.ui.popup.page.open) {
|
||||
p.ui.popup.page.open(item.id);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div className="flex w-[40%] items-center relative ">
|
||||
{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] pl-1",
|
||||
css`
|
||||
width: ${depth * 13}px;
|
||||
`
|
||||
)}
|
||||
></div>
|
||||
{item.type === "folder" && (
|
||||
<>
|
||||
{isOpen && <FolderOpen />}
|
||||
{!isOpen && <FolderClose />}
|
||||
</>
|
||||
)}
|
||||
<div className="flex flex-1 pl-1">
|
||||
{local.renaming ? (
|
||||
<input
|
||||
value={local.rename_to}
|
||||
autoFocus
|
||||
onBlur={async () => {
|
||||
local.renaming = false;
|
||||
item.name = local.rename_to;
|
||||
if (item.id === "") {
|
||||
if (item.name) {
|
||||
db.page_folder.create({
|
||||
data: { name: local.rename_to, id_site: p.site.id },
|
||||
});
|
||||
}
|
||||
await reloadCompPicker(p);
|
||||
} else {
|
||||
db.page_folder.update({
|
||||
where: { id: item.id },
|
||||
data: { name: local.rename_to },
|
||||
});
|
||||
}
|
||||
local.render();
|
||||
}}
|
||||
className="border px-1 bg-white flex-1 outline-none mr-1 border-blue-500 "
|
||||
onChange={(e) => {
|
||||
local.rename_to = e.currentTarget.value;
|
||||
local.render();
|
||||
}}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === "Enter") e.currentTarget.blur();
|
||||
if (e.key === "Escape") {
|
||||
local.rename_to = item.name;
|
||||
local.render();
|
||||
e.currentTarget.blur();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<Name name={item.name} />
|
||||
)}
|
||||
</div>
|
||||
|
||||
{!local.renaming && (
|
||||
<div className="flex pr-2 items-stretch h-[18px] space-x-[2px] text-[10px]">
|
||||
{item.type === "folder" && (
|
||||
<>
|
||||
<div
|
||||
className="btn transition-all bg-white flex items-center border px-1 hover:border-blue-300 hover:bg-blue-100"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
compPicker.tree.push({
|
||||
id: "",
|
||||
parent: item.id,
|
||||
text: "",
|
||||
data: {
|
||||
id: "",
|
||||
name: "",
|
||||
type: "folder",
|
||||
},
|
||||
});
|
||||
p.render();
|
||||
}}
|
||||
>
|
||||
+ Folder
|
||||
</div>
|
||||
<div
|
||||
className="btn transition-all bg-white flex items-center border px-1 hover:border-blue-300 hover:bg-blue-100"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
|
||||
p.ui.popup.page.form = {
|
||||
id_site: p.site.id,
|
||||
id_folder: item.id === "root" ? null : item.id,
|
||||
};
|
||||
p.render();
|
||||
}}
|
||||
>
|
||||
+ Page
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
{item.id !== "root" && (
|
||||
<>
|
||||
<div
|
||||
className="btn transition-all bg-white flex items-center border px-1 hover:border-blue-300 hover:bg-blue-100"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
if (item.type === "folder") {
|
||||
local.rename_to = item.name;
|
||||
local.renaming = true;
|
||||
local.render();
|
||||
} else {
|
||||
p.ui.popup.page.form = item;
|
||||
p.render();
|
||||
}
|
||||
}}
|
||||
>
|
||||
<EditIcon />
|
||||
</div>
|
||||
<div
|
||||
className="btn transition-all bg-white flex items-center border px-1 hover:border-red-300 hover:bg-red-100"
|
||||
onClick={async (e) => {
|
||||
e.stopPropagation();
|
||||
if (confirm("Deletting cannot be undone. Are you sure ?")) {
|
||||
if (item.type === "folder") {
|
||||
await db.page.updateMany({
|
||||
where: { id_folder: node.id as string },
|
||||
data: {
|
||||
id_folder:
|
||||
node.parent === "root"
|
||||
? null
|
||||
: (node.parent as string),
|
||||
},
|
||||
});
|
||||
await db.page_folder.update({
|
||||
where: { id: node.id as string },
|
||||
data: {
|
||||
is_deleted: true,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
await db.page.update({
|
||||
where: { id: node.id as string },
|
||||
data: {
|
||||
is_deleted: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
await reloadCompPicker(p);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<DeleteIcon />
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const Name: FC<{ name: string }> = ({ name }) => {
|
||||
if (name.startsWith("layout::")) {
|
||||
return (
|
||||
<div className="flex items-center">
|
||||
<div className="border border-green-600 text-green-600 mr-1 font-mono text-[8px] px-1 bg-white ">
|
||||
LAYOUT
|
||||
</div>
|
||||
<div>{name.substring("layout::".length)}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return <div>{name}</div>;
|
||||
};
|
||||
|
||||
const DeleteIcon = () => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="12"
|
||||
height="12"
|
||||
fill="none"
|
||||
viewBox="0 0 15 15"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
fillRule="evenodd"
|
||||
d="M5.5 1a.5.5 0 000 1h4a.5.5 0 000-1h-4zM3 3.5a.5.5 0 01.5-.5h8a.5.5 0 010 1H11v8a1 1 0 01-1 1H5a1 1 0 01-1-1V4h-.5a.5.5 0 01-.5-.5zM5 4h5v8H5V4z"
|
||||
clipRule="evenodd"
|
||||
></path>
|
||||
</svg>
|
||||
);
|
||||
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 EditIcon = () => (
|
||||
<svg
|
||||
width="12"
|
||||
height="12"
|
||||
viewBox="0 0 15 15"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M11.8536 1.14645C11.6583 0.951184 11.3417 0.951184 11.1465 1.14645L3.71455 8.57836C3.62459 8.66832 3.55263 8.77461 3.50251 8.89155L2.04044 12.303C1.9599 12.491 2.00189 12.709 2.14646 12.8536C2.29103 12.9981 2.50905 13.0401 2.69697 12.9596L6.10847 11.4975C6.2254 11.4474 6.3317 11.3754 6.42166 11.2855L13.8536 3.85355C14.0488 3.65829 14.0488 3.34171 13.8536 3.14645L11.8536 1.14645ZM4.42166 9.28547L11.5 2.20711L12.7929 3.5L5.71455 10.5784L4.21924 11.2192L3.78081 10.7808L4.42166 9.28547Z"
|
||||
fill="currentColor"
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
></path>
|
||||
</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>
|
||||
);
|
||||
|
|
@ -14,7 +14,7 @@ import { pagePicker, reloadPagePicker } from "./page-reload";
|
|||
import { PageItem, edPageTreeRender } from "./page-tree";
|
||||
import { EdFormPage } from "./page-form";
|
||||
|
||||
export const EdPagePop = () => {
|
||||
export const EdPopPage = () => {
|
||||
const p = useGlobal(EDGlobal, "EDITOR");
|
||||
const local = useLocal({
|
||||
tree: null as TreeMethods | null,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { PG } from "../../../../../logic/ed-global";
|
|||
|
||||
export const edActionAttach = (p: PG, item: IItem) => {
|
||||
const pick = () => {
|
||||
p.ui.popup.comp = (comp_id) => {};
|
||||
p.ui.popup.comp.open = (comp_id) => {};
|
||||
p.render();
|
||||
};
|
||||
pick();
|
||||
|
|
|
|||
Loading…
Reference in New Issue