diff --git a/app/srv/ws/sync/actions.ts b/app/srv/ws/sync/actions.ts index 71461220..f95e02fc 100644 --- a/app/srv/ws/sync/actions.ts +++ b/app/srv/ws/sync/actions.ts @@ -23,7 +23,13 @@ export const SyncActions = { load: async (id: string) => ({}) as ESite | void, }, comp: { - new: async (arg: { group_id: string; item: IItem }) => {}, + new: async (arg: { + group_id: string; + page_id?: string; + comp_id?: string; + item_id: string; + item: IItem; + }) => {}, list: () => ({}) as Record>, group: async (id_site: string) => ({}) as Record, diff --git a/app/srv/ws/sync/actions/comp_new.ts b/app/srv/ws/sync/actions/comp_new.ts index 2bfa925b..8ead049a 100644 --- a/app/srv/ws/sync/actions/comp_new.ts +++ b/app/srv/ws/sync/actions/comp_new.ts @@ -1,9 +1,106 @@ +import { TypedArray } from "yjs-types"; +import { MContent } from "../../../../web/src/utils/types/general"; +import { IItem, MItem } from "../../../../web/src/utils/types/item"; import { SAction } from "../actions"; +import { docs } from "../entity/docs"; import { SyncConnection } from "../type"; +import { syncronize } from "y-pojo"; +import { + FMComponent, + FNComponent, +} from "../../../../web/src/utils/types/meta-fn"; +import { MText } from "../../../../web/src/utils/types/text"; export const comp_new: SAction["comp"]["new"] = async function ( this: SyncConnection, arg ) { - console.log(arg); + const { group_id, item, item_id, page_id, comp_id } = arg; + + const comp = await createComp(item, group_id); + + const walk = (mitem: MItem | MText) => { + if (mitem.get("id") === item_id) { + const map = new Y.Map() as FMComponent; + syncronize( + map as any, + { + id: comp.id, + ref_ids: {}, + props: {}, + } as FNComponent + ); + mitem.set("component", map); + mitem.set("childs", new Y.Array()); + } + + const childs = mitem.get("childs") as TypedArray; + if (childs) walkArray(childs); + }; + const walkArray = (mitems: TypedArray) => { + mitems.forEach((item: MItem) => { + const mcomp = item.get("component"); + if (mcomp && item.get("type") === "item") { + mcomp.get("props")?.forEach((e) => { + if (e.get("meta")?.get("type") === "content-element") { + const content = e.get("content") as MItem; + if (content) { + walk(content); + } + } + }); + } + + walk(item); + }); + }; + if (page_id) { + const doc = docs.page[page_id].doc; + doc.transact(() => { + const root = doc.getMap("map").get("root"); + if (root) { + root.get("childs")?.forEach((e) => { + walk(e); + }); + } + }, "server: comp_new"); + } else if (comp_id) { + const doc = docs.comp[comp_id].doc; + doc.transact(() => { + const root = doc.getMap("map").get("item"); + if (root) { + root.get("childs")?.forEach((e) => { + walk(e); + }); + } + }, "server: comp_new"); + } +}; + +const createComp = async (item: any, group_id: string) => { + const comp = await db.component.create({ + data: { + name: item.name, + content_tree: {}, + component_group: { + connect: { + id: group_id, + }, + }, + }, + }); + + if (comp) { + item.component = { + id: comp.id, + props: {}, + ref_ids: {}, + }; + await db.component.update({ + where: { id: comp.id }, + data: { content_tree: item }, + }); + comp.content_tree = item; + } + return comp; }; diff --git a/app/srv/ws/sync/sync-handler.ts b/app/srv/ws/sync/sync-handler.ts index d0f3f47b..3f2c75aa 100644 --- a/app/srv/ws/sync/sync-handler.ts +++ b/app/srv/ws/sync/sync-handler.ts @@ -52,8 +52,6 @@ export const syncHandler: WebSocketHandler = { await loadDefaultSite(user_id); } - console.log(conf); - conn.conf = new Proxy(conf, { get(_, p) { const conf = user.conf.get(user_id); diff --git a/app/web/src/render/ed/logic/ed-global.ts b/app/web/src/render/ed/logic/ed-global.ts index 070b3bb9..53bb7cd0 100644 --- a/app/web/src/render/ed/logic/ed-global.ts +++ b/app/web/src/render/ed/logic/ed-global.ts @@ -88,6 +88,7 @@ export const EDGlobal = { }, ui: { tree: { + item_loading: [] as string[], search: "", search_mode: { Name: true, diff --git a/app/web/src/render/ed/logic/ed-sync.tsx b/app/web/src/render/ed/logic/ed-sync.tsx index ea41c779..aa9c8c5e 100644 --- a/app/web/src/render/ed/logic/ed-sync.tsx +++ b/app/web/src/render/ed/logic/ed-sync.tsx @@ -22,7 +22,9 @@ export const edInitSync = (p: PG) => { page_id: params.page_id, events: { connected() { - if (w.offline) console.log("connected"); + if (w.offline) { + console.log("reconnected, syncing..."); + } w.offline = false; p.render(); }, diff --git a/app/web/src/render/ed/logic/tree/build.tsx b/app/web/src/render/ed/logic/tree/build.tsx index 8bbd1685..ddfc3311 100644 --- a/app/web/src/render/ed/logic/tree/build.tsx +++ b/app/web/src/render/ed/logic/tree/build.tsx @@ -93,7 +93,7 @@ const walkLoad = async (p: PG, mitem: MItem, loaded: Set) => { const pcomp = p.comp.list[id]; if (pcomp) { - const pitem = pcomp.doc.getMap("map").get("item"); + const pitem = pcomp.doc.getMap("map").get("root"); if (pitem && !loaded.has(id)) { await walkLoad(p, pitem, loaded); } @@ -137,6 +137,12 @@ const walkMap = ( let override_id = ""; const id = mitem.get("id"); + let skip_tree = arg.skip_add_tree; + let skip_tree_child = skip_tree; + if (id && p.ui.tree.item_loading.includes(id)) { + skip_tree_child = true; + } + if (parent_comp && id) { const fcomp = parent_comp.mitem.get("component"); if (fcomp) { @@ -159,7 +165,7 @@ const walkMap = ( const item_comp = item.component; const mitem_comp = mitem.get("component"); const metaNotFound = () => { - if (!arg.skip_add_tree) { + if (!skip_tree) { p.page.tree.push({ id: item.id, parent: parent_item.id, @@ -174,14 +180,17 @@ const walkMap = ( } const ref_comp = p.comp.list[item_comp.id]; + if (ref_comp && mitem_comp) { - const mcomp = ref_comp.doc.getMap("map").get("item"); + const mcomp = ref_comp.doc.getMap("map").get("root"); + if (mcomp) { let ref_ids: Record = item_comp.ref_ids; if (!ref_ids) { mitem_comp.set("ref_ids", new Y.Map() as any); ref_ids = {}; } + mapItem(mcomp, item); const meta: EdMeta = { @@ -191,7 +200,7 @@ const walkMap = ( parent_comp, }; p.page.meta[item.id] = meta; - if (!arg.skip_add_tree) { + if (!skip_tree) { p.page.tree.push({ id: item.id, parent: parent_item.id, @@ -221,6 +230,7 @@ const walkMap = ( parent_item: { id: item.id, mitem: mitem as MItem }, parent_comp: { mitem: mitem as MItem, mcomp }, portal: arg.portal, + skip_add_tree: skip_tree_child, }); } } @@ -263,7 +273,7 @@ const walkMap = ( p.page.meta[item.id] = meta; - if (!arg.skip_add_tree) { + if (!skip_tree) { p.page.tree.push({ id: item.id, parent: parent_item.id, @@ -279,6 +289,7 @@ const walkMap = ( parent_item: { id: item.id, mitem: mitem as MItem }, parent_comp: arg.parent_comp, portal: arg.portal, + skip_add_tree: skip_tree_child, }); } }; diff --git a/app/web/src/render/ed/panel/tree/node/item/action/detach.tsx b/app/web/src/render/ed/panel/tree/node/item/action/detach.tsx index fa2d9c68..a9bc4aa4 100644 --- a/app/web/src/render/ed/panel/tree/node/item/action/detach.tsx +++ b/app/web/src/render/ed/panel/tree/node/item/action/detach.tsx @@ -1,8 +1,35 @@ +import { syncronize } from "y-pojo"; import { IItem } from "../../../../../../../utils/types/item"; import { PG } from "../../../../../logic/ed-global"; +import { treeRebuild } from "../../../../../logic/tree/build"; +import { fillID } from "../../../../../../editor/tools/fill-id"; export const edActionDetach = (p: PG, item: IItem) => { const mitem = p.page.meta[item.id].mitem; if (mitem) { + const compid = mitem.get("component")?.get("id"); + if (compid) { + let comp = p.comp.list[compid].doc + .getMap("map") + .get("root") + ?.toJSON() as IItem; + + if (comp) { + fillID(comp); + comp.id = item.id; + delete comp.component; + mitem.doc?.transact(() => { + mitem.parent.forEach((e, k) => { + if (e == mitem) { + mitem.parent.delete(k); + const nmap = new Y.Map(); + syncronize(nmap, comp); + mitem.parent.insert(k, [nmap]); + } + }); + }); + } + treeRebuild(p); + } } }; diff --git a/app/web/src/render/ed/panel/tree/node/item/action/new-comp.tsx b/app/web/src/render/ed/panel/tree/node/item/action/new-comp.tsx index 8ac8f2d0..e0aab3e8 100644 --- a/app/web/src/render/ed/panel/tree/node/item/action/new-comp.tsx +++ b/app/web/src/render/ed/panel/tree/node/item/action/new-comp.tsx @@ -1,5 +1,6 @@ import { IItem } from "../../../../../../../utils/types/item"; -import { PG } from "../../../../../logic/ed-global"; +import { PG, active } from "../../../../../logic/ed-global"; +import { treeRebuild } from "../../../../../logic/tree/build"; export const edActionNewComp = ( p: PG, @@ -11,7 +12,30 @@ export const edActionNewComp = ( p.ui.popup.comp_group = { mouse_event: e, async on_pick(group_id) { - await p.sync.comp.new({ group_id, item }); + const item = mitem.toJSON() as IItem; + let item_id = active.item_id; + p.ui.tree.item_loading.push(item_id); + await treeRebuild(p); + if (p.comp.cur.id) { + await p.sync.comp.new({ + group_id, + item, + comp_id: p.comp.cur.id, + item_id: active.item_id, + }); + } else { + await p.sync.comp.new({ + group_id, + item, + page_id: p.page.cur.id, + item_id: active.item_id, + }); + } + + p.ui.tree.item_loading = p.ui.tree.item_loading.filter( + (e) => e !== item_id + ); + p.render(); }, }; p.render(); diff --git a/app/web/src/render/ed/panel/tree/node/render.tsx b/app/web/src/render/ed/panel/tree/node/render.tsx index 6f2746aa..3d1b5d0c 100644 --- a/app/web/src/render/ed/panel/tree/node/render.tsx +++ b/app/web/src/render/ed/panel/tree/node/render.tsx @@ -5,6 +5,7 @@ import { EdTreeAction } from "./item/action"; import { EdTreeCtxMenu } from "./item/ctx-menu"; import { EdTreeIndent } from "./item/indent"; import { EdTreeName } from "./item/name"; +import { Loading } from "../../../../../utils/ui/loading"; export const nodeRender: NodeRender = (node, prm) => { const p = useGlobal(EDGlobal, "EDITOR"); @@ -15,6 +16,14 @@ export const nodeRender: NodeRender = (node, prm) => { const item = node.data?.item; const isComponent = item.type === "item" && item.component?.id; + if (p.ui.tree.item_loading.includes(item.id)) { + return ( +
+ +
+ ); + } + return (
; export type DPage = TypedDoc<{ map: TypedMap<{ id: string; root: MRoot }> }>; -export type DComp = TypedDoc<{ map: TypedMap<{ id: string; item: MItem }> }>; +export type DComp = TypedDoc<{ map: TypedMap<{ id: string; root: MItem }> }>;