fix
This commit is contained in:
parent
7ba2c91dc0
commit
55a6b2564c
|
|
@ -9,8 +9,11 @@ import { svLocal } from "./edit/action/sv-local";
|
||||||
import { svdiffRemote } from "./edit/action/svdiff-remote";
|
import { svdiffRemote } from "./edit/action/svdiff-remote";
|
||||||
import { redo, undo } from "./edit/action/undo-redo";
|
import { redo, undo } from "./edit/action/undo-redo";
|
||||||
import { eg } from "./edit/edit-global";
|
import { eg } from "./edit/edit-global";
|
||||||
import { sendWS } from "./edit/send";import { syncHandler } from "./sync/sync-handler";
|
import { sendWS } from "./edit/send";
|
||||||
|
import { syncHandler } from "./sync/sync-handler";
|
||||||
|
import * as Y from "yjs";
|
||||||
|
|
||||||
|
(globalThis as any).Y = Y;
|
||||||
eg.edit = {
|
eg.edit = {
|
||||||
site: {},
|
site: {},
|
||||||
comp: {},
|
comp: {},
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ export const SyncActionDefinition = {
|
||||||
"comp": {
|
"comp": {
|
||||||
"list": "3",
|
"list": "3",
|
||||||
"group": "4",
|
"group": "4",
|
||||||
"doc": "5"
|
"load": "5"
|
||||||
},
|
},
|
||||||
"page": {
|
"page": {
|
||||||
"list": "6",
|
"list": "6",
|
||||||
|
|
@ -20,7 +20,7 @@ export const SyncActionPaths = {
|
||||||
"2": "site.load",
|
"2": "site.load",
|
||||||
"3": "comp.list",
|
"3": "comp.list",
|
||||||
"4": "comp.group",
|
"4": "comp.group",
|
||||||
"5": "comp.doc",
|
"5": "comp.load",
|
||||||
"6": "page.list",
|
"6": "page.list",
|
||||||
"7": "page.load"
|
"7": "page.load"
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { component, page } from "dbgen";
|
import { component, page } from "dbgen";
|
||||||
import { EPage, ESite } from "../../../web/src/render/ed/logic/ed-global";
|
import { EComp, EPage, ESite } from "../../../web/src/render/ed/logic/ed-global";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
WARNING:
|
WARNING:
|
||||||
|
|
@ -20,7 +20,7 @@ export const SyncActions = {
|
||||||
comp: {
|
comp: {
|
||||||
list: () => ({}) as Record<string, Exclude<component, "content_tree">>,
|
list: () => ({}) as Record<string, Exclude<component, "content_tree">>,
|
||||||
group: () => ({}) as Record<string, string[]>,
|
group: () => ({}) as Record<string, string[]>,
|
||||||
doc: (id: string) => ({}) as Uint8Array,
|
load: async (id: string) => ({}) as EComp | void,
|
||||||
},
|
},
|
||||||
page: {
|
page: {
|
||||||
list: (id_site: string) =>
|
list: (id_site: string) =>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
import { syncronize } from "y-pojo";
|
||||||
|
import { docs } from "../entity/docs";
|
||||||
|
import { snapshot } from "../entity/snapshot";
|
||||||
|
import { ActionCtx } from "../type";
|
||||||
|
|
||||||
|
export const comp_load = async function (this: ActionCtx, id: string) {
|
||||||
|
let snap = snapshot.get("comp", id);
|
||||||
|
let ydoc = docs.comp[id];
|
||||||
|
|
||||||
|
if (!snap || !ydoc) {
|
||||||
|
const comp = await db.component.findFirst({ where: { id } });
|
||||||
|
if (comp) {
|
||||||
|
const doc = new Y.Doc();
|
||||||
|
let root = doc.getMap("map");
|
||||||
|
syncronize(root, { id, item: comp.content_tree });
|
||||||
|
|
||||||
|
const um = new Y.UndoManager(root, { ignoreRemoteMapChanges: true });
|
||||||
|
docs.comp[id] = {
|
||||||
|
doc: doc as any,
|
||||||
|
id,
|
||||||
|
um,
|
||||||
|
};
|
||||||
|
|
||||||
|
const bin = Y.encodeStateAsUpdate(doc);
|
||||||
|
snapshot.set({
|
||||||
|
bin,
|
||||||
|
id,
|
||||||
|
type: "comp",
|
||||||
|
name: comp.name,
|
||||||
|
url: "",
|
||||||
|
ts: Date.now(),
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: id,
|
||||||
|
name: comp.name,
|
||||||
|
snapshot: bin,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (snap) {
|
||||||
|
return {
|
||||||
|
id: snap.id,
|
||||||
|
name: snap.name,
|
||||||
|
snapshot: snap.bin,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
export * from "./site_load";
|
export * from "./site_load";
|
||||||
export * from "./site_group";
|
export * from "./site_group";
|
||||||
export * from "./page_load";
|
export * from "./page_load";
|
||||||
|
export * from "./comp_load";
|
||||||
|
|
|
||||||
|
|
@ -8,10 +8,10 @@ export const page_load: SAction["page"]["load"] = async function (
|
||||||
this: ActionCtx,
|
this: ActionCtx,
|
||||||
id: string
|
id: string
|
||||||
) {
|
) {
|
||||||
let ss = snapshot.get("page", id);
|
let snap = snapshot.get("page", id);
|
||||||
let ydoc = docs.page[id];
|
let ydoc = docs.page[id];
|
||||||
|
|
||||||
if (!ss || !ydoc) {
|
if (!snap || !ydoc) {
|
||||||
const page = await db.page.findFirst({ where: { id } });
|
const page = await db.page.findFirst({ where: { id } });
|
||||||
if (page) {
|
if (page) {
|
||||||
const doc = new Y.Doc();
|
const doc = new Y.Doc();
|
||||||
|
|
@ -44,12 +44,12 @@ export const page_load: SAction["page"]["load"] = async function (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ss) {
|
if (snap) {
|
||||||
return {
|
return {
|
||||||
id: ss.id,
|
id: snap.id,
|
||||||
url: ss.url,
|
url: snap.url,
|
||||||
name: ss.name,
|
name: snap.name,
|
||||||
snapshot: ss.bin,
|
snapshot: snap.bin,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ const emptySnapshot = {
|
||||||
bin: new Uint8Array(),
|
bin: new Uint8Array(),
|
||||||
url: "",
|
url: "",
|
||||||
name: "",
|
name: "",
|
||||||
ts: Date.now(),
|
ts: Date.now()
|
||||||
};
|
};
|
||||||
export type DocSnapshot = typeof emptySnapshot;
|
export type DocSnapshot = typeof emptySnapshot;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ export const syncHandler: WebSocketHandler<WSData> = {
|
||||||
if (actionName) {
|
if (actionName) {
|
||||||
const baseAction = (actions as any)[actionName];
|
const baseAction = (actions as any)[actionName];
|
||||||
if (!baseAction) {
|
if (!baseAction) {
|
||||||
console.log(`app/ws/edit/sync/${actionName}.ts not found}`);
|
console.log(`app/ws/edit/sync/${actionName}.ts not found`);
|
||||||
}
|
}
|
||||||
if (baseAction) {
|
if (baseAction) {
|
||||||
const action = baseAction.bind({
|
const action = baseAction.bind({
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,8 @@ import { NodeModel } from "@minoru/react-dnd-treeview";
|
||||||
import { clientStartSync } from "../../../utils/sync/client";
|
import { clientStartSync } from "../../../utils/sync/client";
|
||||||
import { IContent, MContent } from "../../../utils/types/general";
|
import { IContent, MContent } from "../../../utils/types/general";
|
||||||
import { IItem, MItem } from "../../../utils/types/item";
|
import { IItem, MItem } from "../../../utils/types/item";
|
||||||
import { DPage, IRoot } from "../../../utils/types/root";
|
import { DComp, DPage, IRoot } from "../../../utils/types/root";
|
||||||
import { IText, MText } from "../../../utils/types/text";
|
import { IText, MText } from "../../../utils/types/text";
|
||||||
import { NodeMeta } from "../../editor/logic/global";
|
|
||||||
|
|
||||||
const EmptySite = {
|
const EmptySite = {
|
||||||
id: "",
|
id: "",
|
||||||
|
|
@ -16,6 +15,7 @@ const EmptySite = {
|
||||||
};
|
};
|
||||||
export type ESite = typeof EmptySite;
|
export type ESite = typeof EmptySite;
|
||||||
export type EPage = typeof EmptyPage;
|
export type EPage = typeof EmptyPage;
|
||||||
|
export type EComp = typeof EmptyComp;
|
||||||
|
|
||||||
const EmptyPage = {
|
const EmptyPage = {
|
||||||
id: "",
|
id: "",
|
||||||
|
|
@ -24,9 +24,18 @@ const EmptyPage = {
|
||||||
snapshot: null as null | Uint8Array,
|
snapshot: null as null | Uint8Array,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const EmptyComp = {
|
||||||
|
id: "",
|
||||||
|
snapshot: null as null | Uint8Array,
|
||||||
|
};
|
||||||
|
|
||||||
export type EdMeta = {
|
export type EdMeta = {
|
||||||
item: IItem | IText;
|
item: IItem | IText;
|
||||||
mitem?: MItem | MText;
|
mitem?: MItem | MText;
|
||||||
|
parent_comp?: {
|
||||||
|
ref_ids: Record<string, string>;
|
||||||
|
mcomp: MItem;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const EDGlobal = {
|
export const EDGlobal = {
|
||||||
|
|
@ -39,12 +48,19 @@ export const EDGlobal = {
|
||||||
sync: null as unknown as Awaited<ReturnType<typeof clientStartSync>>,
|
sync: null as unknown as Awaited<ReturnType<typeof clientStartSync>>,
|
||||||
site: EmptySite,
|
site: EmptySite,
|
||||||
page: {
|
page: {
|
||||||
current: EmptyPage,
|
cur: EmptyPage,
|
||||||
doc: null as null | DPage,
|
doc: null as null | DPage,
|
||||||
root: null as null | IRoot,
|
root: null as null | IRoot,
|
||||||
entry: [] as string[],
|
entry: [] as string[],
|
||||||
tree: [] as NodeModel<EdMeta>[],
|
tree: [] as NodeModel<EdMeta>[],
|
||||||
meta: {} as Record<string, { item: IContent; mitem?: MContent }>,
|
meta: {} as Record<string, { item: IContent; mitem?: MContent }>,
|
||||||
|
list: {} as Record<string, EPage>,
|
||||||
|
},
|
||||||
|
comp: {
|
||||||
|
cur: EmptyComp,
|
||||||
|
doc: null as null | DComp,
|
||||||
|
item: null as null | IItem,
|
||||||
|
list: {} as Record<string, { cur: EComp; doc: DComp }>,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ export const edRoute = async (p: PG) => {
|
||||||
p.site = site;
|
p.site = site;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p.page.current.id !== params.page_id || !p.page.current.snapshot) {
|
if (p.page.cur.id !== params.page_id || !p.page.cur.snapshot) {
|
||||||
p.status = "loading";
|
p.status = "loading";
|
||||||
const page = await p.sync.page.load(params.page_id);
|
const page = await p.sync.page.load(params.page_id);
|
||||||
|
|
||||||
|
|
@ -26,7 +26,7 @@ export const edRoute = async (p: PG) => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
p.page.current = page;
|
p.page.cur = page;
|
||||||
if (page.snapshot) {
|
if (page.snapshot) {
|
||||||
const doc = new Y.Doc();
|
const doc = new Y.Doc();
|
||||||
Y.applyUpdate(doc, page.snapshot);
|
Y.applyUpdate(doc, page.snapshot);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
|
import { createId } from "@paralleldrive/cuid2";
|
||||||
|
import { MContent } from "../../../../utils/types/general";
|
||||||
import { IItem, MItem } from "../../../../utils/types/item";
|
import { IItem, MItem } from "../../../../utils/types/item";
|
||||||
import { MRoot } from "../../../../utils/types/root";
|
import { DComp } from "../../../../utils/types/root";
|
||||||
import { MSection } from "../../../../utils/types/section";
|
import { MSection } from "../../../../utils/types/section";
|
||||||
import { walk } from "../../../editor/logic/tree-logic";
|
|
||||||
import { EdMeta, PG } from "../ed-global";
|
import { EdMeta, PG } from "../ed-global";
|
||||||
|
|
||||||
export const treeRebuild = async (p: PG) => {
|
export const treeRebuild = async (p: PG) => {
|
||||||
|
|
@ -24,13 +25,7 @@ export const treeRebuild = async (p: PG) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const walkMap = async (
|
const mapItem = (mitem: MContent, item: any) => {
|
||||||
p: PG,
|
|
||||||
arg: { mitem: MItem | MSection; tree_parent_id: string }
|
|
||||||
) => {
|
|
||||||
const { mitem, tree_parent_id } = arg;
|
|
||||||
|
|
||||||
const item = {} as unknown as IItem;
|
|
||||||
mitem.forEach((e, k) => {
|
mitem.forEach((e, k) => {
|
||||||
if (k !== "childs") {
|
if (k !== "childs") {
|
||||||
let val = e;
|
let val = e;
|
||||||
|
|
@ -39,15 +34,104 @@ const walkMap = async (
|
||||||
val = e.toJSON() as any;
|
val = e.toJSON() as any;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(item as any)[k] = val;
|
item[k] = val;
|
||||||
} else {
|
} else {
|
||||||
item[k] = [];
|
item[k] = [];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const walkMap = async (
|
||||||
|
p: PG,
|
||||||
|
arg: {
|
||||||
|
mitem: MItem | MSection;
|
||||||
|
tree_parent_id: string;
|
||||||
|
parent_comp?: EdMeta["parent_comp"];
|
||||||
|
}
|
||||||
|
) => {
|
||||||
|
const { mitem, tree_parent_id, parent_comp } = arg;
|
||||||
|
|
||||||
|
const item = {} as unknown as IItem;
|
||||||
|
mapItem(mitem, item);
|
||||||
|
|
||||||
|
// sesuaikan item instance id dengan parent comp
|
||||||
|
if (parent_comp) {
|
||||||
|
if (!parent_comp["ref_ids"][item.id]) {
|
||||||
|
parent_comp["ref_ids"][item.id] = createId();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parent_comp["ref_ids"][item.id]) {
|
||||||
|
item.id = parent_comp["ref_ids"][item.id];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const metaNotFound = () => {
|
||||||
|
p.page.tree.push({
|
||||||
|
id: item.id,
|
||||||
|
parent: tree_parent_id,
|
||||||
|
text: item.name,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const item_comp = item.component;
|
||||||
|
if (item_comp && item_comp.id) {
|
||||||
|
if (!p.comp.list[item_comp.id]) {
|
||||||
|
let found = false;
|
||||||
|
const cur = await p.sync.comp.load(item_comp.id);
|
||||||
|
if (cur && cur.snapshot) {
|
||||||
|
const doc = new Y.Doc() as DComp;
|
||||||
|
if (cur.snapshot) {
|
||||||
|
Y.applyUpdate(doc as any, cur.snapshot);
|
||||||
|
p.comp.list[item_comp.id] = { cur, doc };
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
metaNotFound();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const ref_comp = p.comp.list[item_comp.id];
|
||||||
|
if (ref_comp) {
|
||||||
|
const mcomp = ref_comp.doc.getMap("map").get("item");
|
||||||
|
if (mcomp) {
|
||||||
|
const ref_ids: Record<string, string> = {};
|
||||||
|
|
||||||
|
if (parent_comp) {
|
||||||
|
let old_id = item.id;
|
||||||
|
mapItem(mcomp, item);
|
||||||
|
ref_ids[item.id] = old_id;
|
||||||
|
item.id = old_id;
|
||||||
|
} else {
|
||||||
|
mapItem(mcomp, item);
|
||||||
|
ref_ids[item.id] = createId();
|
||||||
|
item.id = ref_ids[item.id];
|
||||||
|
}
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
mcomp.get("childs")?.map(async (e) => {
|
||||||
|
await walkMap(p, {
|
||||||
|
mitem: e,
|
||||||
|
tree_parent_id: item.id,
|
||||||
|
parent_comp: { ref_ids, mcomp },
|
||||||
|
});
|
||||||
|
}) || []
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
metaNotFound();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const meta: EdMeta = {
|
const meta: EdMeta = {
|
||||||
item,
|
item,
|
||||||
mitem: mitem as MItem,
|
mitem: mitem as MItem,
|
||||||
|
parent_comp,
|
||||||
};
|
};
|
||||||
|
|
||||||
p.page.meta[item.id] = meta;
|
p.page.meta[item.id] = meta;
|
||||||
|
|
@ -59,10 +143,13 @@ const walkMap = async (
|
||||||
data: meta,
|
data: meta,
|
||||||
});
|
});
|
||||||
|
|
||||||
await Promise.all(
|
const mchilds = mitem.get("childs");
|
||||||
mitem.get("childs")?.map(async (e, k) => {
|
if (mchilds) {
|
||||||
item.childs.push(e.get("id"));
|
await Promise.all(
|
||||||
await walkMap(p, { mitem: e, tree_parent_id: item.id });
|
mchilds.map(async (e, k) => {
|
||||||
}) || []
|
item.childs.push(e.get("id"));
|
||||||
);
|
await walkMap(p, { mitem: e, tree_parent_id: item.id });
|
||||||
|
}) || []
|
||||||
|
);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { TypedArray, TypedDoc, TypedMap } from "yjs-types";
|
import { TypedArray, TypedDoc, TypedMap } from "yjs-types";
|
||||||
import { ISection } from "./section";
|
import { ISection } from "./section";
|
||||||
|
import { MItem } from "./item";
|
||||||
|
|
||||||
export type IRoot = {
|
export type IRoot = {
|
||||||
id: "root";
|
id: "root";
|
||||||
|
|
@ -14,3 +15,4 @@ export type MRoot = TypedMap<{
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
export type DPage = TypedDoc<{ map: TypedMap<{ id: string; root: MRoot }> }>;
|
export type DPage = TypedDoc<{ map: TypedMap<{ id: string; root: MRoot }> }>;
|
||||||
|
export type DComp = TypedDoc<{ map: TypedMap<{ id: string; item: MItem }> }>;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue