From 0ae681830880daef6900f18622abebbf49b0b5b2 Mon Sep 17 00:00:00 2001 From: rizky Date: Tue, 30 Jul 2024 06:39:40 -0700 Subject: [PATCH] form generate without clear --- comps/form/gen/fields.ts | 1 + comps/form/gen/gen-form.ts | 79 ++++++++++++++++-- comps/md/gen/md-form.ts | 6 +- utils/diff-gen.ts | 167 +++++++++++++++++++++++++++++++++++++ 4 files changed, 245 insertions(+), 8 deletions(-) create mode 100755 utils/diff-gen.ts diff --git a/comps/form/gen/fields.ts b/comps/form/gen/fields.ts index b66c920..c2feb30 100755 --- a/comps/form/gen/fields.ts +++ b/comps/form/gen/fields.ts @@ -166,6 +166,7 @@ export const newField = async ( name: field.name, label: formatName(field.name), type: "link", + ext__show_label: show ? "y" : "n", link__params: [ `async (field: any) => { return { diff --git a/comps/form/gen/gen-form.ts b/comps/form/gen/gen-form.ts index 3701f61..e261255 100755 --- a/comps/form/gen/gen-form.ts +++ b/comps/form/gen/gen-form.ts @@ -1,4 +1,10 @@ import { createItem, parseGenField } from "lib/gen/utils"; +import { + copyProps, + mapCompItemTree, + propFromItem, + reduceItemMapping, +} from "lib/utils/diff-gen"; import { set } from "lib/utils/set"; import get from "lodash.get"; import { generateSelect } from "../../md/gen/md-select"; @@ -57,7 +63,6 @@ export const generateForm = async ( break; } } - console.log(is_md); } if (pk) { @@ -109,7 +114,7 @@ export const generateForm = async ( (item.component?.props.body as any)?.content as IItem )?.childs; - let child_body = createItem({ + let new_body = createItem({ name: "item", ...body_prop, childs: [ @@ -139,7 +144,71 @@ export const generateForm = async ( }); if (Array.isArray(existing_childs) && existing_childs.length > 0) { - walkGenForm(child_body, existing_childs as any); + walkGenForm(new_body, existing_childs as any); + } + + const current_body = propFromItem(item)?.body?.value as IItem; + + if (current_body) { + const mapping = mapCompItemTree(new_body, { + shouldAdd({ item }) { + if (item.component?.props?.sub_type?.value === "table-edit") + return "add-skip-children"; + + return "add"; + }, + }); + + reduceItemMapping(current_body, mapping, (old_item, new_item) => { + const pold = propFromItem(old_item); + const pnew = propFromItem(new_item); + + let result = old_item; + if ( + result.component && + result.component?.id === "32550d01-42a3-4b15-a04a-2c2d5c3c8e67" + ) { + if (pold.type.value !== pnew.type.value) { + result = new_item; + } else if (pold.sub_type.value !== pnew.sub_type.value) { + result = new_item; + } + + // if (result === new_item) { + // const new_mapping = mapCompItemTree(new_body); + // console.log(mapping, new_mapping); + // } + + copyProps(old_item, new_item, [ + "placeholder", + "label", + "ext__width", + "ext__on_change", + "ext__description", + "ext__show_label", + "ext__disabled", + "ext__prefix", + "ext__suffxi", + ]); + } + + return result; + }); + + if ( + mapping["32550d01-42a3-4b15-a04a-2c2d5c3c8e67"] && + Object.keys(mapping["32550d01-42a3-4b15-a04a-2c2d5c3c8e67"]).length > 0 + ) { + for (const val of Object.values( + mapping["32550d01-42a3-4b15-a04a-2c2d5c3c8e67"] + )) { + current_body.childs?.[0]?.childs.push(val); + } + } + + if (current_body?.childs?.length > 0) { + new_body = current_body; + } } if (commit) { @@ -148,12 +217,12 @@ export const generateForm = async ( }); item.edit.setProp("body", { mode: "jsx", - value: child_body, + value: new_body, }); await item.edit.commit(); } else { set(data, "body.value", { ...data.body?.value, ...body_prop }); - set(data, "body.value.childs", child_body.childs); + set(data, "body.value.childs", new_body.childs); Object.keys(result).map((e) => { set(data, e, result[e]); }); diff --git a/comps/md/gen/md-form.ts b/comps/md/gen/md-form.ts index 133e63d..a13c45b 100755 --- a/comps/md/gen/md-form.ts +++ b/comps/md/gen/md-form.ts @@ -29,7 +29,7 @@ export const generateMDForm = async ( mode: "raw", value: `({ md: typeof md !== "undefined" ? md : undefined })`, }, - on_load: { + on_load: { mode: "string", value: "", }, @@ -45,7 +45,7 @@ export const generateMDForm = async ( }), }, }; - const tablelist: any = { + const newitem: any = { type: "item", name: "item", component: { @@ -53,7 +53,7 @@ export const generateMDForm = async ( props, }, }; - generateForm(async (props: any) => {}, props, tablelist, false, true); + generateForm(async (props: any) => {}, props, newitem, false, true); tab_detail?.edit.setProp("breadcrumb", { mode: "raw", diff --git a/utils/diff-gen.ts b/utils/diff-gen.ts new file mode 100755 index 0000000..b35d4c9 --- /dev/null +++ b/utils/diff-gen.ts @@ -0,0 +1,167 @@ +export const mapCompItemTree = ( + item: IItem, + opt: { + shouldAdd?: (arg: { + parent_comp?: IItem; + item: IItem; + }) => "add" | "add-skip-children"; + }, + arg?: { + parent_comp?: IItem; + mapping: Record>; + } +) => { + const map = arg?.mapping || {}; + + if (item.component?.id && item.component.props) { + let skip_children = false; + for (const [k, v] of Object.entries(item.component.props)) { + if (k === "name") { + let action = "add"; + + if (opt.shouldAdd) { + action = opt.shouldAdd({ parent_comp: arg?.parent_comp, item }); + } + + if (action === "add" || action === "add-skip-children") { + if (!map[item.component.id]) map[item.component.id] = {}; + map[item.component.id][v.value] = item; + + if (action === "add-skip-children") { + skip_children = true; + } + } + } + } + + if (skip_children) { + for (const [k, v] of Object.entries(item.component.props)) { + if (!!(v as any).content) { + mapCompItemTree((v as any).content, opt, { + parent_comp: item, + mapping: map, + }); + } + } + } + } + + if (item.childs) { + for (const c of item.childs) { + mapCompItemTree(c, opt, { ...arg, mapping: map }); + } + } + return map; +}; + +export const copyProps = (from: IItem, to: IItem, prop_name: string[]) => { + if (from.component && to.component) { + for (const p of prop_name) { + if (from.component.props[p]) { + to.component.props[p] = from.component.props[p]; + } + } + } +}; + +export const reduceItemMapping = ( + item: IItem, + map: ReturnType, + found?: (old_item: IItem, new_item: IItem) => IItem +) => { + if (item.childs) { + for (const [k, c] of Object.entries(item.childs)) { + if ( + c.component?.id && + c.component.props.name && + c.component.props.name.value + ) { + if (map?.[c.component.id]?.[c.component.props.name.value]) { + if (found) { + item.childs[k as any] = found( + c, + map[c.component.id][c.component.props.name.value] + ); + } + + delete map[c.component.id][c.component.props.name.value]; + continue; + } else { + if (c.component?.id && c.component.props) { + for (const [k, v] of Object.entries(c.component.props)) { + if (!!(v as any).content) { + reduceItemMapping((v as any).content, map, found); + } + } + } + } + } + + reduceItemMapping(c, map, found); + } + } +}; + +// export const mergeNewToOld = ( +// new_item: IItem, +// old_item: IItem, +// founds?: { +// name: Record; +// comp: Record>; +// } +// ) => { +// const comp_founds = founds?.comp || {}; +// const name_founds = founds?.name || {}; + +// let _founds = founds || { +// comp: comp_founds, +// name: name_founds, +// }; + +// for (const c of old_item.childs) { +// if (c.component?.id && c.component.props.name) { +// if (!comp_founds[c.component.id]) { +// comp_founds[c.component.id] = {}; +// } +// comp_founds[c.component.id][c.component.props.name.value] = c; +// } else { +// name_founds[c.name] = c; +// } +// } + +// for (const c of new_item.childs) { +// if (c.component?.id && c.component.props.name) { +// if (!comp_founds[c.component.id]?.[c.component.props.name.value]) { +// old_item.childs.push(c); +// } else { +// mergeNewToOld( +// c, +// comp_founds[c.component.id]?.[c.component.props.name.value], +// _founds +// ); +// } +// } else { +// if (!name_founds[c.name]) { +// old_item.childs.push(c); +// } else { +// mergeNewToOld(c, name_founds[c.name], _founds); +// } +// } +// } +// }; + +export const propFromItem = (item: IItem) => { + const result: Record = {}; + if (item.component?.props) { + for (const [k, v] of Object.entries(item.component.props)) { + const prop = v as any; + + if (prop.meta.type === "content-element") { + result[k] = { mode: "jsx", value: prop.content }; + } else { + result[k] = { mode: "raw", value: v.value }; + } + } + } + return result; +};