291 lines
8.0 KiB
TypeScript
291 lines
8.0 KiB
TypeScript
import { IItem, MItem } from "../../../../utils/types/item";
|
|
import { FNCompDef } from "../../../../utils/types/meta-fn";
|
|
import { IMeta } from "../../utils/types";
|
|
|
|
const w = window as unknown as {
|
|
prasiEdit: Record<string, Record<string, SingleChange[]>>;
|
|
};
|
|
|
|
type SingleChange =
|
|
| { type: "set"; name: string; value: any }
|
|
| ({ type: "prop"; name: string } & PropVal);
|
|
|
|
type PropVal =
|
|
| { mode: "string"; value: string }
|
|
| { mode: "raw"; value: string; valueBuilt?: string }
|
|
| { mode: "jsx"; value: null | (IItem & PrasiEdit) };
|
|
|
|
type ParentArg = {
|
|
item: IItem & PrasiEdit;
|
|
child_type: "jsx" | "child";
|
|
child_idx: number;
|
|
};
|
|
|
|
type PrasiEdit = {
|
|
edit: {
|
|
setValue: <T extends keyof IItem>(name: T, value: IItem[T]) => void;
|
|
setProp: (name: string, value: PropVal | string) => void;
|
|
pending: SingleChange[];
|
|
readonly childs: (IItem & PrasiEdit)[];
|
|
readonly parent: null | ParentArg;
|
|
commit: () => Promise<void>;
|
|
readonly props?: Record<string, PropVal>;
|
|
};
|
|
};
|
|
|
|
export const devItem = (
|
|
metas: Record<string, IMeta>,
|
|
mitem: MItem,
|
|
page_id: string
|
|
) => {
|
|
if (!w.prasiEdit) {
|
|
w.prasiEdit = {};
|
|
}
|
|
let pedit = w.prasiEdit[page_id];
|
|
if (!pedit) {
|
|
w.prasiEdit[page_id] = {};
|
|
pedit = w.prasiEdit[page_id];
|
|
}
|
|
|
|
const initChanges = () => {
|
|
const id = mitem.get("id") || "";
|
|
let changes = pedit[id];
|
|
if (!changes) {
|
|
pedit[id] = [];
|
|
changes = pedit[id];
|
|
}
|
|
return changes;
|
|
};
|
|
|
|
const item = mitem.toJSON() as IItem;
|
|
|
|
return {
|
|
...item,
|
|
edit: {
|
|
get props() {
|
|
if (item.component?.props) {
|
|
const result: Record<string, PropVal> = {};
|
|
for (const [k, v] of Object.entries(item.component.props)) {
|
|
if (v.content) {
|
|
const content = mitem
|
|
.get("component")
|
|
?.get("props")
|
|
?.get(k)
|
|
?.get("content");
|
|
|
|
if (content) {
|
|
result[k] = {
|
|
mode: "jsx",
|
|
value: devItem(metas, content, page_id),
|
|
};
|
|
} else {
|
|
result[k] = {
|
|
mode: "jsx",
|
|
value: null as any,
|
|
};
|
|
}
|
|
} else {
|
|
let vbuilt =
|
|
typeof v.valueBuilt === "string"
|
|
? (v.valueBuilt.trim() as string)
|
|
: "";
|
|
if (vbuilt.endsWith(";\n")) {
|
|
vbuilt = vbuilt.substring(0, vbuilt.length - ";\n".length);
|
|
}
|
|
if (vbuilt && vbuilt === v.value.trim()) {
|
|
result[k] = { mode: "string", value: JSON.parse(v.value) };
|
|
} else {
|
|
result[k] = {
|
|
mode: "raw",
|
|
value: v.value,
|
|
valueBuilt: v.valueBuilt,
|
|
};
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
return undefined;
|
|
},
|
|
get pending() {
|
|
return [];
|
|
},
|
|
async commit() {
|
|
const result = {} as Record<string, any>;
|
|
for (const [item_id, changes] of Object.entries(pedit)) {
|
|
if (mitem) {
|
|
const item = mitem.toJSON();
|
|
const props = item?.component?.props as Record<string, FNCompDef>;
|
|
const src = {} as Record<string, string>;
|
|
for (const c of changes) {
|
|
if (c.type === "prop" && props) {
|
|
if (props[c.name]) {
|
|
if (c.mode === "string") {
|
|
props[c.name].value = JSON.stringify(c.value);
|
|
props[c.name].valueBuilt = JSON.stringify(c.value);
|
|
} else if (c.mode === "raw") {
|
|
props[c.name].value = c.value;
|
|
if (c.valueBuilt) {
|
|
props[c.name].valueBuilt = c.valueBuilt;
|
|
} else {
|
|
src[c.name] = c.value;
|
|
}
|
|
} else if (c.mode === "jsx") {
|
|
if (!props[c.name]) {
|
|
props[c.name] = {
|
|
meta: { type: "content-element" },
|
|
} as any;
|
|
}
|
|
if (c.value) {
|
|
props[c.name].content = formatChilds([c.value])[0];
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
if (c.type === "set" && typeof c.value === "object") {
|
|
for (const [k, v] of Object.entries(c.value) as any) {
|
|
item[k] = v;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
const result = await _api.code_build(src);
|
|
for (const [k, v] of Object.entries(result)) {
|
|
props[k].valueBuilt = v;
|
|
}
|
|
result[item_id] = item;
|
|
}
|
|
}
|
|
|
|
if (mitem) {
|
|
mitem.doc?.transact(() => {
|
|
for (const [k, v] of Object.entries(result)) {
|
|
const m = metas[k];
|
|
if (m.mitem) {
|
|
syncronize(m.mitem as any, v);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
},
|
|
setValue(name, value) {
|
|
const changes = initChanges();
|
|
|
|
let _value: any = value;
|
|
|
|
if (name === "childs") {
|
|
_value = formatChilds(value as any);
|
|
}
|
|
|
|
changes.push({ type: "set", name, value: _value });
|
|
},
|
|
setProp(name, value) {
|
|
const changes = initChanges();
|
|
if (typeof value === "string") {
|
|
changes.push({
|
|
type: "prop",
|
|
mode: "string",
|
|
name,
|
|
value,
|
|
});
|
|
} else {
|
|
if (value.mode === "string") {
|
|
changes.push({
|
|
type: "prop",
|
|
mode: "string",
|
|
name,
|
|
value: value.value,
|
|
});
|
|
} else if (value.mode === "raw") {
|
|
changes.push({
|
|
type: "prop",
|
|
mode: "raw",
|
|
name,
|
|
value: value.value,
|
|
valueBuilt: value.valueBuilt,
|
|
});
|
|
} else if (value.mode === "jsx") {
|
|
changes.push({
|
|
type: "prop",
|
|
mode: "jsx",
|
|
name,
|
|
value: value.value,
|
|
});
|
|
}
|
|
}
|
|
},
|
|
get childs() {
|
|
const item = mitem?.toJSON() as IItem;
|
|
|
|
if (item.component?.id) {
|
|
const child = item.component?.props.child;
|
|
if (child.content) {
|
|
const m = mitem
|
|
.get("component")
|
|
?.get("props")
|
|
?.get("child")
|
|
?.get("content");
|
|
if (m) {
|
|
return [devItem(metas, m, page_id)];
|
|
}
|
|
}
|
|
return [];
|
|
}
|
|
|
|
if (item.childs) {
|
|
return item.childs
|
|
.map((e) => {
|
|
if (e) {
|
|
const m = metas[e.id];
|
|
if (m && m.mitem) return devItem(metas, m.mitem, page_id);
|
|
}
|
|
})
|
|
.filter((e) => e);
|
|
}
|
|
|
|
return [];
|
|
},
|
|
get parent() {
|
|
if (mitem) {
|
|
const parent = mitem.parent.toJSON();
|
|
if (Array.isArray(parent)) {
|
|
const parent_id = (mitem.parent?.parent as any).get("id");
|
|
const parent_meta = metas[parent_id].mitem;
|
|
if (parent_meta) {
|
|
return {
|
|
item: devItem(metas, parent_meta, page_id),
|
|
child_type: "child",
|
|
child_idx: parent.findIndex((e) => e.id === item.id),
|
|
};
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
},
|
|
},
|
|
} as IItem & PrasiEdit;
|
|
};
|
|
|
|
const formatChilds = (childs: (IItem & PrasiEdit)[]) => {
|
|
const result = childs.map((e) => {
|
|
const item: any = { ...e };
|
|
delete item.edit;
|
|
|
|
if (item.component?.props) {
|
|
for (const [k, v] of Object.entries(item.component.props) as any) {
|
|
if (v.content) {
|
|
v.content = formatChilds([v.content]);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (item.childs) {
|
|
item.childs = formatChilds(item.childs);
|
|
}
|
|
|
|
return item;
|
|
});
|
|
return result;
|
|
};
|