wip component

This commit is contained in:
Rizky 2023-12-27 08:22:44 +07:00
parent 57044a6a08
commit 346c1d2ed4
11 changed files with 222 additions and 223 deletions

View File

@ -1,5 +1,4 @@
import { EPage } from "../../../../web/src/nova/ed/logic/ed-global"; import { EPage } from "../../../../web/src/nova/ed/logic/ed-global";
import { assignMitem } from "../../../../web/src/nova/ed/logic/tree/assign-mitem";
import { initLoadComp } from "../../../../web/src/nova/vi/meta/comp/init-comp-load"; import { initLoadComp } from "../../../../web/src/nova/vi/meta/comp/init-comp-load";
import { genMeta } from "../../../../web/src/nova/vi/meta/meta"; import { genMeta } from "../../../../web/src/nova/vi/meta/meta";
import { simplifyMeta } from "../../../../web/src/nova/vi/meta/simplify"; import { simplifyMeta } from "../../../../web/src/nova/vi/meta/simplify";
@ -9,6 +8,8 @@ import { DPage } from "../../../../web/src/utils/types/root";
import { SAction } from "../actions"; import { SAction } from "../actions";
import { loadComponent, userSyncComponent } from "../editor/load-component"; import { loadComponent, userSyncComponent } from "../editor/load-component";
import { parseJs } from "../editor/parser/parse-js"; import { parseJs } from "../editor/parser/parse-js";
import { prepareComponentForPage } from "../editor/prep-comp-page";
import { prepContentTree } from "../editor/prep-page";
import { activity } from "../entity/activity"; import { activity } from "../entity/activity";
import { conns } from "../entity/conn"; import { conns } from "../entity/conn";
import { docs } from "../entity/docs"; import { docs } from "../entity/docs";
@ -85,7 +86,8 @@ export const page_load: SAction["page"]["load"] = async function (
const doc = new Y.Doc(); const doc = new Y.Doc();
let root = doc.getMap("map"); let root = doc.getMap("map");
syncronize(root, { id, root: page.content_tree }); const proot = await prepContentTree(page.id, page.content_tree, this);
syncronize(root, { id, root: proot });
const um = await createUndoManager(root); const um = await createUndoManager(root);
docs.page[id] = { docs.page[id] = {
@ -116,14 +118,12 @@ export const page_load: SAction["page"]["load"] = async function (
page_id: page.id, page_id: page.id,
}); });
const meta = await scanMeta(docs.page[id].doc, this);
return { return {
id: id, id: id,
url: page.url, url: page.url,
name: page.name, name: page.name,
snapshot: await gzipAsync(bin), snapshot: await gzipAsync(bin),
...meta, comps: await prepareComponentForPage(id),
}; };
} }
} else if (snap && !ydoc) { } else if (snap && !ydoc) {
@ -151,14 +151,12 @@ export const page_load: SAction["page"]["load"] = async function (
page_id: snap.id, page_id: snap.id,
}); });
const meta = await scanMeta(docs.page[id].doc, this);
return { return {
id: id, id: id,
url: snap.url, url: snap.url,
name: snap.name, name: snap.name,
snapshot: await gzipAsync(snap.bin), snapshot: await gzipAsync(snap.bin),
...meta, comps: await prepareComponentForPage(id),
}; };
} else if (snap && ydoc) { } else if (snap && ydoc) {
await setActivityPage(snap.id_site, id); await setActivityPage(snap.id_site, id);
@ -171,117 +169,116 @@ export const page_load: SAction["page"]["load"] = async function (
page_id: snap.id, page_id: snap.id,
}); });
const meta = await scanMeta(ydoc.doc, this);
return { return {
id: snap.id, id: snap.id,
url: snap.url, url: snap.url,
name: snap.name, name: snap.name,
snapshot: await gzipAsync(snap.bin), snapshot: await gzipAsync(snap.bin),
...meta, comps: await prepareComponentForPage(id),
}; };
} }
}; };
const scanMeta = async (doc: DPage, sync: SyncConnection) => { // const scanMeta = async (doc: DPage, sync: SyncConnection) => {
const meta: GenMetaP["meta"] = {}; // const meta: GenMetaP["meta"] = {};
const mcomps: GenMetaP["comps"] = {}; // const mcomps: GenMetaP["comps"] = {};
const msnap: Record<string, CompSnapshot> = {}; // const msnap: Record<string, CompSnapshot> = {};
const loading = {} as Record<string, Promise<void>>; // const loading = {} as Record<string, Promise<void>>;
const mchilds = doc.getMap("map").get("root")?.get("childs"); // const mchilds = doc.getMap("map").get("root")?.get("childs");
const entry: string[] = []; // const entry: string[] = [];
if (mchilds) { // if (mchilds) {
const childs = mchilds.map((m) => m); // const childs = mchilds.map((m) => m);
for (const mchild of childs) { // for (const mchild of childs) {
await initLoadComp( // await initLoadComp(
{ comps: mcomps, meta }, // { comps: mcomps, meta },
mchild.toJSON(), // mchild.toJSON(),
async (comp_ids) => { // async (comp_ids) => {
for (const id of comp_ids) { // for (const id of comp_ids) {
if (!docs.comp[id]) { // if (!docs.comp[id]) {
if (typeof loading[id] === "undefined") { // if (typeof loading[id] === "undefined") {
loading[id] = new Promise<void>(async (resolve) => { // loading[id] = new Promise<void>(async (resolve) => {
await loadComponent(id, sync); // await loadComponent(id, sync);
resolve(); // resolve();
}); // });
} // }
await loading[id]; // await loading[id];
} else { // } else {
userSyncComponent(sync, id); // userSyncComponent(sync, id);
} // }
const snap = snapshot.get("comp", id); // const snap = snapshot.get("comp", id);
if (snap) { // if (snap) {
msnap[id] = snap; // msnap[id] = snap;
} // }
if (docs.comp[id]) { // if (docs.comp[id]) {
const mitem = docs.comp[id].doc.getMap("map").get("root"); // const mitem = docs.comp[id].doc.getMap("map").get("root");
const comp = mitem?.toJSON() as IItem; // const comp = mitem?.toJSON() as IItem;
const smeta: Record<string, IMeta> = {}; // const smeta: Record<string, IMeta> = {};
genMeta( // genMeta(
{ // {
comps: {}, // comps: {},
meta: smeta, // meta: smeta,
on: { // on: {
visit(meta) { // visit(meta) {
if (typeof meta.item.adv?.js === "string") { // if (typeof meta.item.adv?.js === "string") {
meta.scope.def = parseJs(meta.item.adv?.js); // meta.scope.def = parseJs(meta.item.adv?.js);
} // }
}, // },
}, // },
}, // },
{ item: comp, ignore_first_component: true } // { item: comp, ignore_first_component: true }
); // );
mcomps[id] = { comp, smeta: simplifyMeta(smeta) }; // mcomps[id] = { comp, smeta: simplifyMeta(smeta) };
} // }
} // }
} // }
); // );
} // }
const transact = { // const save = {
instances_check: {} as Record<string, true | IMeta>, // instances_check: {} as Record<string, true | IMeta>,
}; // };
for (const mitem of childs) { // for (const mitem of childs) {
const item = mitem.toJSON() as IItem; // const item = mitem.toJSON() as IItem;
entry.push(item.id); // entry.push(item.id);
genMeta( // genMeta(
{ // {
comps: mcomps, // comps: mcomps,
meta, // meta,
on: { // on: {
visit_component(item) { // visit_component(item) {
if (!item.component?.instances) { // if (!item.component?.instances) {
transact.instances_check[item.id] = true; // save.instances_check[item.id] = true;
} // }
}, // },
visit(m) { // visit(m) {
if (!m.parent?.comp_id) { // if (!m.parent?.comp_id) {
if (typeof m.item.adv?.js === "string") { // if (typeof m.item.adv?.js === "string") {
m.scope.def = parseJs(m.item.adv?.js); // m.scope.def = parseJs(m.item.adv?.js);
} // }
} // }
if (m.item.component?.id) { // if (m.item.component?.id) {
if (transact.instances_check[m.item.id]) { // if (save.instances_check[m.item.id]) {
transact.instances_check[m.item.id] = m; // save.instances_check[m.item.id] = m;
} // }
} // }
}, // },
}, // },
}, // },
{ item } // { item }
); // );
} // }
} // }
const comps: EPage["comps"] = {}; // const comps: EPage["comps"] = {};
for (const [id, snap] of Object.entries(msnap)) { // for (const [id, snap] of Object.entries(msnap)) {
const meta = mcomps[id].smeta; // const meta = mcomps[id].smeta;
comps[id] = { id, meta, snapshot: await gzipAsync(snap.bin) }; // comps[id] = { id, meta, snapshot: await gzipAsync(snap.bin) };
} // }
return { meta: simplifyMeta(meta), comps, entry }; // return { meta: simplifyMeta(meta), comps, entry };
}; // };

View File

@ -0,0 +1,5 @@
import { EComp } from "../../../../web/src/nova/ed/logic/ed-global";
export const prepareComponentForPage = async (page_id: string) => {
return {} as Record<string, EComp>;
};

View File

@ -0,0 +1,83 @@
import { initLoadComp } from "../../../../web/src/nova/vi/meta/comp/init-comp-load";
import { genMeta } from "../../../../web/src/nova/vi/meta/meta";
import { GenMetaP } from "../../../../web/src/nova/vi/utils/types";
import { IItem } from "../../../../web/src/utils/types/item";
import { IRoot } from "../../../../web/src/utils/types/root";
import { docs } from "../entity/docs";
import { SyncConnection } from "../type";
import { loadComponent, userSyncComponent } from "./load-component";
import { parseJs } from "./parser/parse-js";
export const prepContentTree = async (
page_id: string,
ctree: any,
sync: SyncConnection
) => {
const root = ctree as IRoot;
root.id_page = page_id;
root.component_ids = await loadCompForPage(ctree, sync);
const comps: GenMetaP["comps"] = {};
for (const id of root.component_ids) {
const comp = docs.comp[id].doc.getMap("map").get("root")?.toJSON() as IItem;
if (comp) comps[id] = comp;
}
const meta = {};
genMeta(
{
comps,
meta,
on: {
visit_component(item) {
if (item.component) {
if (!item.component.instances) {
item.component.instances = {};
}
}
},
visit(meta) {
if (meta.item.adv?.js) {
meta.item.script = parseJs(meta.item.adv.js);
}
},
},
mode: "page",
},
{ item: root as unknown as IItem }
);
return ctree;
};
const loadCompForPage = async (ctree: IRoot, sync: SyncConnection) => {
const meta: GenMetaP["meta"] = {};
const mcomps: GenMetaP["comps"] = {};
const result = new Set<string>();
const loading = {} as Record<string, Promise<void>>;
for (const mchild of ctree.childs) {
await initLoadComp(
{ comps: mcomps, meta, mode: "page" },
mchild as unknown as IItem,
async (comp_ids) => {
for (const id of comp_ids) {
if (!docs.comp[id]) {
if (typeof loading[id] === "undefined") {
loading[id] = new Promise<void>(async (resolve) => {
await loadComponent(id, sync);
resolve();
});
}
await loading[id];
} else {
userSyncComponent(sync, id);
}
result.add(id);
}
}
);
}
return [...result];
};

View File

@ -53,8 +53,6 @@ const EmptyPage = {
name: "", name: "",
url: "", url: "",
snapshot: null as null | Uint8Array, snapshot: null as null | Uint8Array,
entry: [] as string[],
meta: {} as Record<string, ISimpleMeta>,
comps: {} as Record<string, EComp>, comps: {} as Record<string, EComp>,
}; };

View File

@ -8,42 +8,30 @@ import { simplifyItemChild } from "./simplify";
export const genComp = (p: GenMetaP, arg: GenMetaArg) => { export const genComp = (p: GenMetaP, arg: GenMetaArg) => {
const { item } = arg; const { item } = arg;
if (item.type === "item" && item.component?.id && arg.parent?.item.id) { if (item.type === "item" && item.component?.id && arg.parent?.item.id) {
let pcomp = p.comps[item.component.id]; let item_comp = p.comps[item.component.id];
if (p.on?.visit_component) { if (p.on?.visit_component) {
p.on.visit_component(item); p.on.visit_component(item);
} }
if (!pcomp) { if (!item_comp) {
return; return;
} }
if (pcomp) { if (item_comp) {
let instance = {}; let instances: undefined | typeof item.component.instances = undefined;
let instances: IMeta["instances"] = undefined; if (p.mode === "page") {
if (item.component.instances) {
instances = item.component.instances; instances = item.component.instances;
instance = instances[item.id] || {};
instances[item.id] = instance;
} else { } else {
const parent_instance = getParentInstance(p, arg, item.id); instances = arg.parent?.root_instances;
instance = parent_instance || {};
instances = !parent_instance ? { [item.id]: instance } : undefined;
} }
instantiate({ if (instances) {
item, const instance = instances[item.id];
comp: pcomp.comp, instantiate({
ids: instance, item,
}); comp: item_comp,
ids: instance,
if (item.component) { });
item.component.loaded = true;
}
let smeta = p.comps[item.component.id].smeta;
if (smeta) {
smeta = applySMeta(smeta, instance);
} }
const meta: IMeta = { const meta: IMeta = {
@ -53,16 +41,8 @@ export const genComp = (p: GenMetaP, arg: GenMetaArg) => {
comp_id: arg.parent?.comp?.component?.id, comp_id: arg.parent?.comp?.component?.id,
instance_id: arg.parent?.instance_id, instance_id: arg.parent?.instance_id,
}, },
instances,
scope: {},
}; };
if (!meta.parent?.comp_id) {
if (p.smeta?.[item.id]) {
meta.scope.def = p.smeta[item.id].scope;
}
}
if (item.id) { if (item.id) {
if (p.set_meta !== false) { if (p.set_meta !== false) {
p.meta[item.id] = meta; p.meta[item.id] = meta;
@ -71,14 +51,14 @@ export const genComp = (p: GenMetaP, arg: GenMetaArg) => {
walkProp({ walkProp({
item, item,
pcomp, item_comp: item_comp,
each(name, prop) { each(name, prop) {
const comp_id = item.component?.id; const comp_id = item.component?.id;
if (prop.meta?.type === "content-element" && comp_id) { if (prop.meta?.type === "content-element" && comp_id) {
if (prop.content) { if (prop.content) {
genMeta( genMeta(
{ ...p, smeta }, { ...p },
{ {
item: prop.content, item: prop.content,
is_root: false, is_root: false,
@ -90,7 +70,8 @@ export const genComp = (p: GenMetaP, arg: GenMetaArg) => {
parent: { parent: {
item: meta.item, item: meta.item,
instance_id: item.id, instance_id: item.id,
comp: pcomp.comp, comp: item_comp,
root_instances: instances,
}, },
} }
); );
@ -99,14 +80,6 @@ export const genComp = (p: GenMetaP, arg: GenMetaArg) => {
}, },
}); });
if (p.on) {
if (p.on.item_exists && p.meta[item.id]) {
p.on.item_exists({ old: p.meta[item.id], new: meta });
} else if (p.on.item_new && !p.meta[item.id]) {
p.on.item_new({ new: meta });
}
}
if (p.on?.visit) { if (p.on?.visit) {
p.on.visit(meta); p.on.visit(meta);
} }
@ -115,14 +88,14 @@ export const genComp = (p: GenMetaP, arg: GenMetaArg) => {
if (child.name.startsWith("jsx:")) continue; if (child.name.startsWith("jsx:")) continue;
genMeta( genMeta(
{ ...p, smeta }, { ...p, mode: "comp" },
{ {
item: child, item: child,
is_root: false, is_root: false,
parent: { parent: {
item, item,
instance_id: item.id, instance_id: item.id,
comp: pcomp.comp, root_instances: instances,
}, },
} }
); );
@ -130,38 +103,3 @@ export const genComp = (p: GenMetaP, arg: GenMetaArg) => {
} }
} }
}; };
const getParentInstance = (p: GenMetaP, arg: GenMetaArg, id: string) => {
if (arg.parent?.instance_id && p.meta[arg.parent?.instance_id]) {
const parent_instance = p.meta[arg.parent?.instance_id];
if (parent_instance.instances) {
if (!parent_instance.instances[id]) {
parent_instance.instances[id] = {};
}
return parent_instance.instances[id];
}
}
};
const applySMeta = (
smeta: Record<string, ISimpleMeta>,
ids: Record<string, string>
) => {
const nmeta: typeof smeta = {};
for (const [k, v] of Object.entries(smeta)) {
const id = ids[k];
if (id) {
nmeta[id] = deepClone(v);
nmeta[id].id = id;
const parent = nmeta[id].parent;
if (parent) {
if (parent.instance_id) parent.instance_id = ids[parent.instance_id];
if (parent.id) parent.id = ids[id];
}
}
}
return nmeta;
};

View File

@ -4,10 +4,10 @@ import { FNCompDef } from "../../../../utils/types/meta-fn";
export const walkProp = (arg: { export const walkProp = (arg: {
item: IItem; item: IItem;
pcomp: { comp: IItem }; item_comp: IItem;
each: (name: string, prop: FNCompDef) => void; each: (name: string, prop: FNCompDef) => void;
}) => { }) => {
for (const [k, v] of Object.entries(arg.pcomp.comp.component?.props || {})) { for (const [k, v] of Object.entries(arg.item_comp.component?.props || {})) {
let prop = deepClone(v); let prop = deepClone(v);
const props = arg.item.component?.props; const props = arg.item.component?.props;
if (props && props[k]) { if (props && props[k]) {

View File

@ -13,13 +13,6 @@ export const genMeta = (p: GenMetaP, arg: GenMetaArg) => {
} }
} }
let scope: IMeta["scope"] = {};
if (p.smeta) {
if (p.smeta[item.id] && p.smeta[item.id].scope) {
scope.def = p.smeta[item.id].scope;
}
}
const meta: IMeta = { const meta: IMeta = {
item: simplifyItemChild(item), item: simplifyItemChild(item),
jsx_prop: arg.jsx_prop, jsx_prop: arg.jsx_prop,
@ -28,20 +21,12 @@ export const genMeta = (p: GenMetaP, arg: GenMetaArg) => {
instance_id: arg.parent?.instance_id, instance_id: arg.parent?.instance_id,
comp_id: arg.parent?.comp?.component?.id, comp_id: arg.parent?.comp?.component?.id,
}, },
scope,
}; };
if (p.on?.visit) { if (p.on?.visit) {
p.on.visit(meta); p.on.visit(meta);
} }
if (p.on) {
if (p.on.item_exists && p.meta[item.id]) {
p.on.item_exists({ old: p.meta[item.id], new: meta });
} else if (p.on.item_new && !p.meta[item.id]) {
p.on.item_new({ new: meta });
}
}
if (item.id) { if (item.id) {
if (p.set_meta !== false) { if (p.set_meta !== false) {
p.meta[meta.item.id] = meta; p.meta[meta.item.id] = meta;
@ -57,6 +42,7 @@ export const genMeta = (p: GenMetaP, arg: GenMetaArg) => {
item: meta.item, item: meta.item,
instance_id: arg.parent?.instance_id, instance_id: arg.parent?.instance_id,
comp: arg.parent?.comp, comp: arg.parent?.comp,
root_instances: arg.parent?.root_instances,
}, },
}); });
} }

View File

@ -7,16 +7,14 @@ import { createViPassProp } from "../render/script/passprop";
export type GenMetaP = { export type GenMetaP = {
meta: Record<string, IMeta>; meta: Record<string, IMeta>;
comps: Record<string, { comp: IItem; smeta: Record<string, ISimpleMeta> }>; comps: Record<string, IItem>;
on?: { on?: {
visit_component?: (item: IItem) => void; visit_component?: (item: IItem) => void;
visit?: (meta: IMeta) => void; visit?: (meta: IMeta) => void;
item_exists?: (arg: { old: IMeta; new: IMeta }) => void;
item_new?: (arg: { new: IMeta }) => void;
}; };
smeta?: Record<string, ISimpleMeta>;
set_meta?: boolean; set_meta?: boolean;
note?: string; note?: string;
mode: "page" | "comp";
}; };
export type GenMetaArg = { export type GenMetaArg = {
@ -28,6 +26,7 @@ export type GenMetaArg = {
item: IItem; item: IItem;
instance_id?: string; instance_id?: string;
comp?: IItem; comp?: IItem;
root_instances?: Record<string, Record<string, string>>;
}; };
}; };
@ -42,7 +41,6 @@ export type ISimpleMeta = {
instance_id?: string; instance_id?: string;
comp_id?: string; comp_id?: string;
}; };
scope: IMeta["scope"]["def"];
}; };
export type IMeta = { export type IMeta = {
@ -67,8 +65,5 @@ export type IMeta = {
PassProp: ReturnType<typeof createViPassProp>; PassProp: ReturnType<typeof createViPassProp>;
} }
>; >;
scope: {
def?: ReturnType<typeof parseJs>;
};
render?: () => void; render?: () => void;
}; };

View File

@ -1,18 +1,16 @@
import { TypedArray, TypedMap } from "yjs-types"; import { TypedArray, TypedMap } from "yjs-types";
import { parseJs } from "../../../../srv/ws/sync/editor/parser/parse-js";
import { BasicItem, MBasicItem, MetaItem } from "./meta"; import { BasicItem, MBasicItem, MetaItem } from "./meta";
import { import { FNAdv, FNComponent, FNLayout, FNLinkTag } from "./meta-fn";
FNAdv,
FNComponent,
FNLayout,
FNLinkTag
} from "./meta-fn";
import { MSection } from "./section"; import { MSection } from "./section";
import { IText, MText } from "./text"; import { IText, MText } from "./text";
export type IItem = { export type IItem = {
layout?: FNLayout; layout?: FNLayout;
linktag?: FNLinkTag; linktag?: FNLinkTag;
mobile?: IItem; mobile?: IItem;
adv?: FNAdv; adv?: FNAdv;
script?: ReturnType<typeof parseJs>;
type: "item"; type: "item";
component?: FNComponent; component?: FNComponent;
childs: (IItem | IText)[]; childs: (IItem | IText)[];

View File

@ -19,10 +19,7 @@ export type FNAdv = {
export type FMAdv = TypedMap<FNAdv>; export type FMAdv = TypedMap<FNAdv>;
export type FNComponent = { export type FNComponent = {
id: string; id: string;
name?: string;
loaded?: boolean;
props: Record<string, FNCompDef>; props: Record<string, FNCompDef>;
ref_ids?: Record<string, string>;
instances?: Record<string, Record<string, string>>; instances?: Record<string, Record<string, string>>;
}; };

View File

@ -5,8 +5,10 @@ import * as Y from "yjs";
export type IRoot = { export type IRoot = {
id: "root"; id: "root";
type: "root"; type: "root";
id_page: string; id_page?: string;
childs: ISection[]; childs: ISection[];
component_ids?: string[];
entry_ids?: string[];
}; };
export type MRoot = TypedMap<{ export type MRoot = TypedMap<{
id: "root"; id: "root";