From 83351ca7c2adae6c3dced703cce2ead9f233e72e Mon Sep 17 00:00:00 2001 From: rizky Date: Tue, 26 Mar 2024 14:11:22 -0700 Subject: [PATCH] wip fix --- comps/form/Form.tsx | 46 +- comps/form/Radio/index.tsx | 13 +- comps/form/utils/utils.ts | 1 + comps/list/Table.tsx | 95 +++- comps/mst/MasterDetail.tsx | 190 ++++++-- comps/mst/type.ts | 5 +- comps/mst/utils.ts | 47 +- comps/ui/tabs.tsx | 56 ++- gen/gen_form/gen_form.ts | 16 +- gen/gen_form/on_submit.ts | 4 + gen/gen_md/form_before_load.ts | 11 +- gen/gen_md/gen_detail.ts | 867 +++++++++++++++++---------------- gen/gen_md/gen_header.ts | 9 +- gen/gen_md/gen_master.ts | 151 ++---- gen/gen_md/gen_md.ts | 6 +- gen/gen_table/gen_table.ts | 13 + gen/gen_table/new_field.ts | 5 +- gen/gen_table/on_load.ts | 14 +- 18 files changed, 886 insertions(+), 663 deletions(-) diff --git a/comps/form/Form.tsx b/comps/form/Form.tsx index 49f7fcd..64d2b42 100755 --- a/comps/form/Form.tsx +++ b/comps/form/Form.tsx @@ -1,16 +1,17 @@ import { Form as FForm } from "@/comps/ui/form"; import { Toaster } from "@/comps/ui/sonner"; import { useLocal } from "@/utils/use-local"; -import { FC } from "react"; +import { FC, useEffect } from "react"; import { createPortal } from "react-dom"; import { useForm } from "react-hook-form"; import { toast } from "sonner"; import { FormHook } from "./utils/utils"; import { AlertTriangle, Check, Loader2 } from "lucide-react"; import { cn } from "@/utils"; +import { Skeleton } from "../ui/skeleton"; export const Form: FC<{ - on_init: (arg: { submit: any }) => any; + on_init: (arg: { submit: any; reload: any }) => any; on_load: () => any; on_submit: (arg: { form: any; error: any }) => Promise; body: any; @@ -63,7 +64,7 @@ export const Form: FC<{ toast.loading( <> - Saving ... + Processing ... , { dismissible: true, @@ -112,7 +113,7 @@ export const Form: FC<{ toast.success(
- Data saved + Done
, { className: css` @@ -127,7 +128,19 @@ export const Form: FC<{ if (!local.init) { local.init = true; - on_init({ submit }); + on_init({ + submit, + reload: () => { + local.init = false; + form.unload = () => { + form.hook.clearErrors(); + form.hook.reset(); + delete form.unload; + local.render(); + }; + local.render(); + }, + }); const res = on_load(); const loaded = (values: any) => { setTimeout(() => { @@ -166,8 +179,16 @@ export const Form: FC<{ } const toaster_el = document.getElementsByClassName("prasi-toaster")[0]; + if (form.unload) + return ( +
+ + +
+ ); + return ( - + {toaster_el && createPortal(, toaster_el)}
-
+ ); }; + +const FormInternal = (props: any) => { + useEffect(() => { + return () => { + if (props.form && props.form.unload) { + props.form.unload(); + } + }; + }, []); + return ; +}; diff --git a/comps/form/Radio/index.tsx b/comps/form/Radio/index.tsx index ecabe59..43d77f3 100755 --- a/comps/form/Radio/index.tsx +++ b/comps/form/Radio/index.tsx @@ -92,7 +92,7 @@ export const Radio: FC<{ {!!local.list && local.list .filter((e) => e) - .map((item, index:number) => { + .map((item, index: number) => { if (custom === "y" && form) return ( { if (selection === "single") { - console.log(value, "====single", name); local.mod(name, { value: item.value }); local.render(); } else if (selection === "multi") { - const val = []; - console.log(); - - val.push( ...value, item.value); - - local.mod(name, { value: val }); + local.mod(name, { value: item.value }); local.render(); - console.log(item.value, "value", form.hook.getValues()); - return; - console.log(value, "====multi", name); } else { null; } diff --git a/comps/form/utils/utils.ts b/comps/form/utils/utils.ts index 8c49a6b..4480579 100755 --- a/comps/form/utils/utils.ts +++ b/comps/form/utils/utils.ts @@ -27,4 +27,5 @@ export type FormHook = { cache: any; validation: Record; render: () => void; + unload?: () => void; }; diff --git a/comps/list/Table.tsx b/comps/list/Table.tsx index 1800ee5..e0d5e47 100755 --- a/comps/list/Table.tsx +++ b/comps/list/Table.tsx @@ -1,7 +1,8 @@ import { useLocal } from "@/utils/use-local"; -import { FC, useEffect } from "react"; +import { FC, useEffect, useRef } from "react"; import DataGrid, { ColumnOrColumnGroup, + DataGridHandle, Row, SortColumn, } from "react-data-grid"; @@ -14,13 +15,20 @@ type OnRowClick = { idx: any; event: React.MouseEvent; }; + +type RowSelected = { + row: any; + rows: any[]; + idx: any; +}; export const Table: FC<{ columns: () => Promise[]>; - on_load: () => Promise; + on_load: (opt: { reload: () => Promise }) => Promise; child: any; PassProp: any; row_click: (arg: OnRowClick) => void; -}> = ({ columns, on_load, child, PassProp, row_click }) => { + selected: (arg: RowSelected) => boolean; +}> = ({ columns, on_load, child, PassProp, row_click, selected }) => { const local = useLocal({ loading: false, data: undefined as unknown as any[], @@ -58,7 +66,19 @@ export const Table: FC<{ useEffect(() => { local.loading = true; - on_load().then((data) => { + const arg = { + reload: async () => { + local.loading = true; + local.render(); + + const data = await on_load(arg); + + local.data = data; + local.loading = false; + local.render(); + }, + }; + on_load(arg).then((data) => { local.data = data; local.loading = false; local.render(); @@ -67,6 +87,7 @@ export const Table: FC<{ return ( void; row_click: (arg: OnRowClick) => void; -}> = ({ columns, data, render, row_click }) => { + selected: (arg: RowSelected) => boolean; +}> = ({ columns, data, render, row_click, selected }) => { const local = useLocal({ width: 0, height: 0, @@ -91,7 +113,9 @@ const TableInternal: FC<{ }), el: null as any, sort: [] as SortColumn[], + scrolled: false, }); + const rdg = useRef(null); useEffect(() => { return () => { @@ -100,22 +124,45 @@ const TableInternal: FC<{ }, []); const sort = local.sort; - let sorted = data; - if (sort.length > 0 && data) { - sorted = data.sort((a, b) => { - const va = a[sort[0].columnKey]; - const vb = b[sort[0].columnKey]; - if (typeof va === "string" && typeof vb === "string") { - if (sort[0].direction === "ASC") { - return va.localeCompare(vb); - } else { - return vb.localeCompare(va); - } + // let sorted = data; + // if (sort.length > 0 && data) { + // sorted = data.sort((a, b) => { + // const va = a[sort[0].columnKey]; + // const vb = b[sort[0].columnKey]; + // if (typeof va === "string" && typeof vb === "string") { + // if (sort[0].direction === "ASC") { + // return va.localeCompare(vb); + // } else { + // return vb.localeCompare(va); + // } + // } + // return 0; + // }); + // } + + let selected_idx = -1; + if (data) { + for (let i = 0; i < data.length; i++) { + const row = data[i]; + if ( + typeof selected === "function" + ? selected({ + idx: i, + row: row, + rows: data, + }) + : false + ) { + selected_idx = i; + break; } - return 0; - }); + } } + useEffect(() => { + rdg.current!.scrollToCell({ rowIdx: selected_idx, idx: 0 }); + }, [selected_idx]); + return (
{ @@ -148,6 +199,7 @@ const TableInternal: FC<{ { local.sort = []; if (col) { @@ -173,6 +225,8 @@ const TableInternal: FC<{ ? undefined : { renderRow(key, props) { + const is_selected = selected_idx === props.rowIdx; + return ( ); }, diff --git a/comps/mst/MasterDetail.tsx b/comps/mst/MasterDetail.tsx index 788a6bb..217f5b6 100755 --- a/comps/mst/MasterDetail.tsx +++ b/comps/mst/MasterDetail.tsx @@ -1,17 +1,18 @@ +import { GFCol } from "@/gen/utils"; import { useLocal } from "@/utils/use-local"; import get from "lodash.get"; import { FC, useEffect } from "react"; +import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels"; import { Tabs, TabsList, TabsTrigger } from "../ui/tabs"; import { MasterDetailConfig, MasterDetailLocal, MasterDetailProp, } from "./type"; -import { GFCol } from "@/gen/utils"; import { master_detail_gen_hash, master_detail_params } from "./utils"; export const MasterDetail: FC = (props) => { - const { header, name, mode, title, actions, gen_fields } = props; + const { header, name, mode, title, actions, gen_fields, md_parent } = props; const md = useLocal( { name, @@ -28,25 +29,53 @@ export const MasterDetail: FC = (props) => { cache_internal: {}, cache: null as any, pk: null as null | GFCol, + parent: md_parent, }, () => { - if (!isEditor) { - const hash = master_detail_params(md); + const params = master_detail_params(md); + const hash = params.hash; + + if (params.tabs && params.tabs[md.name]) { + md.active_tab = params.tabs[md.name]; + } + if (md.mode === "breadcrumb") { if (hash && hash[name] && md.pk) { if (md.pk.type === "int") { md.selected = { [md.pk.name]: parseInt(hash[name]) }; } else { md.selected = { [md.pk.name]: hash[name] }; } - md.render(); } } + md.render(); } ); + + const local = useLocal({ init: false }, () => { + local.init = true; + local.render(); + }); + + if (local.init) { + const params = master_detail_params(md); + const hash = params.hash; + delete hash.parent_id; + + if (!md.selected) { + delete hash[md.name]; + master_detail_gen_hash(params); + } else if (md.pk) { + hash[md.name] = md.selected[md.pk.name]; + master_detail_gen_hash(params); + } + } + if (!md.pk && gen_fields) { for (const str of gen_fields) { - const f = JSON.parse(str) as GFCol; - if (f.is_pk) md.pk = f; + try { + const f = JSON.parse(str) as GFCol; + if (f.is_pk) md.pk = f; + } catch (e) {} } } @@ -67,6 +96,11 @@ export const MasterDetail: FC = (props) => { md.ui.title = title; md.render(); }, [title]); + + useEffect(() => { + md.mode = mode; + md.render(); + }, [mode]); } useEffect(() => { @@ -86,8 +120,88 @@ export const MasterDetail: FC = (props) => { "c-flex-1 c-flex-col c-flex c-w-full c-h-full c-overflow-hidden" )} > - {header} - + {md.mode === "breadcrumb" && ( + + )} + {md.mode === "vertical" && ( + + )} + {md.mode === "horizontal" && ( + + )} + {isEditor && ( +
+ {props.detail} +
+ )} +
+ ); +}; + +const VerticalMode: FC<{ + props: MasterDetailProp; + md: MasterDetailConfig; + header: any; +}> = ({ props, md, header }) => { + return ( +
+ + + {props.master} + + <> + + { + if (e < 80) { + localStorage.setItem(`prasi-md-h-${md.name}`, e.toString()); + } + }} + > + {header} + + + + +
+ ); +}; + +const HorizontalMode: FC<{ + props: MasterDetailProp; + md: MasterDetailConfig; + header: any; +}> = ({ props, md, header }) => { + return ( +
+ + + {props.master} + + <> + + { + if (e < 80) { + localStorage.setItem(`prasi-md-h-${md.name}`, e.toString()); + } + }} + > + {header} + + + +
); }; @@ -95,39 +209,23 @@ export const MasterDetail: FC = (props) => { const BreadcrumbMode: FC<{ props: MasterDetailProp; md: MasterDetailConfig; -}> = ({ props, md }) => { - const local = useLocal({ init: false }, () => { - local.init = true; - local.render(); - }); - - if (local.init) { - const hash = master_detail_params(md); - delete hash.parent_id; - - if (!md.selected) { - delete hash[md.name]; - location.hash = master_detail_gen_hash(hash); - } else if (md.pk) { - hash[md.name] = md.selected[md.pk.name]; - location.hash = master_detail_gen_hash(hash); - } - } - + header: any; +}> = ({ props, md, header }) => { return ( -
-
- {props.master} -
- {md.selected && } - {isEditor && !local.init && ( -
- + <> + {header} +
+
+ {props.master}
- )} -
+ {md.selected && } +
+ ); }; @@ -145,7 +243,9 @@ const Detail: FC<{ ); if (idx < 0) { idx = 0; - md.active_tab = childs[idx].name; + if (childs[idx]) { + md.active_tab = childs[idx].name; + } setTimeout(md.render); } const content = childs[idx]; @@ -170,6 +270,7 @@ const Detail: FC<{ "c-flex c-w-full c-rounded-none c-border-b c-border-gray-300 c-justify-start", css` padding: 0 !important; + padding-left: 20px !important; height: auto !important; ` )} @@ -179,6 +280,13 @@ const Detail: FC<{ { + const params = master_detail_params(md); + const hash = params.hash; + delete hash.parent_id; + + params.tabs[md.name] = e.name; + master_detail_gen_hash(params); + md.active_tab = e.name; md.render(); }} diff --git a/comps/mst/type.ts b/comps/mst/type.ts index cdfda30..15ba700 100755 --- a/comps/mst/type.ts +++ b/comps/mst/type.ts @@ -11,6 +11,7 @@ export type MasterDetailProp = { actions: (md: any) => MasterDetailAction[]; gen_fields: any; name: string; + md_parent?: MasterDetailConfig; }; type MasterDetailAction = { @@ -34,6 +35,7 @@ export type MasterDetailLocal = { }; cache: (name: string, opt?: { reset: boolean }) => any; pk: null | GFCol; + parent?: MasterDetailConfig; }; export type MasterDetailConfig = MasterDetailLocal & { render: () => void }; @@ -59,7 +61,8 @@ export const master_detail_typings = { actions: ${action_type}[]; }; cache: (name: string, opt?: { reset: boolean }) => any; - pk: null | any + pk: null | any; + parent?: typeof md; }`, action_type, }; diff --git a/comps/mst/utils.ts b/comps/mst/utils.ts index b00e773..aa43eb4 100755 --- a/comps/mst/utils.ts +++ b/comps/mst/utils.ts @@ -7,27 +7,52 @@ export const master_detail_params = (md: MasterDetailConfig) => { : md.selected?.[md.pk?.name || ""]; const hash: any = {}; - for (const h of location.hash.split("#")) { + const tabs: any = {}; + + let raw_hash = decodeURIComponent(location.hash); + + if (isEditor) { + raw_hash = localStorage.getItem("prasi-md-hash") || ""; + } + + for (const h of raw_hash.split("#")) { if (h) { - const [tab_name, tab_val] = h.split("="); - if (tab_name && tab_val) { - hash[tab_name] = tab_val; + if (h.includes("=")) { + const [tab_name, tab_val] = h.split("="); + if (tab_name && tab_val) { + hash[tab_name] = tab_val; + } + } else if (h.includes("~")) { + const [tab_name, tab_val] = h.split("~"); + if (tab_name && tab_val) { + tabs[tab_name] = tab_val; + } } } } if (parent_id) { - return { ...hash, parent_id }; + return { hash, parent_id, tabs }; } - return hash; + return { hash, tabs }; }; -export const master_detail_gen_hash = ( - obj: Record -) => { +export const master_detail_gen_hash = (obj: { + hash: Record; + tabs: Record; + parent_id?: string; +}) => { let hash = ""; - for (const [k, v] of Object.entries(obj)) { + for (const [k, v] of Object.entries(obj.hash)) { hash += `#${k}=${v}`; } - return hash; + for (const [k, v] of Object.entries(obj.tabs)) { + hash += `#${k}~${v}`; + } + + if (isEditor) { + localStorage.setItem("prasi-md-hash", hash); + } else { + location.hash = hash; + } }; diff --git a/comps/ui/tabs.tsx b/comps/ui/tabs.tsx index 67063d9..96739a9 100755 --- a/comps/ui/tabs.tsx +++ b/comps/ui/tabs.tsx @@ -10,18 +10,22 @@ const TabsList = React.forwardRef< React.ComponentPropsWithoutRef & { overrideClassName?: boolean; } ->(({ className, ...props }, ref) => ( - -)); +>(({ className, ...props }, ref) => { + const overrideClassName = props.overrideClassName; + delete props.overrideClassName; + return ( + + ); +}); TabsList.displayName = TabsPrimitive.List.displayName; const TabsTrigger = React.forwardRef< @@ -29,18 +33,22 @@ const TabsTrigger = React.forwardRef< React.ComponentPropsWithoutRef & { overrideClassName?: boolean; } ->(({ className, ...props }, ref) => ( - -)); +>(({ className, ...props }, ref) => { + const overrideClassName = props.overrideClassName; + delete props.overrideClassName; + return ( + + ); +}); TabsTrigger.displayName = TabsPrimitive.Trigger.displayName; const TabsContent = React.forwardRef< diff --git a/gen/gen_form/gen_form.ts b/gen/gen_form/gen_form.ts index c527057..b65373d 100755 --- a/gen/gen_form/gen_form.ts +++ b/gen/gen_form/gen_form.ts @@ -66,14 +66,16 @@ export const gen_form = (modify: (data: any) => void, data: any) => { return; } if (pk) { - if (mode.includes("on_load")) { - result["on_load"] = data["on_load"]; - result["on_load"].value = on_load({ pk, pks, select, table }); - } + if (mode) { + if (mode.includes("on_load")) { + result["on_load"] = data["on_load"]; + result["on_load"].value = on_load({ pk, pks, select, table }); + } - if (mode.includes("on_submit")) { - result["on_submit"] = data["on_submit"]; - result["on_submit"].value = on_submit({ pk, table, select, pks }); + if (mode.includes("on_submit")) { + result["on_submit"] = data["on_submit"]; + result["on_submit"].value = on_submit({ pk, table, select, pks }); + } } result["body"] = data["body"]; diff --git a/gen/gen_form/on_submit.ts b/gen/gen_form/on_submit.ts index f087bba..a12e19c 100755 --- a/gen/gen_form/on_submit.ts +++ b/gen/gen_form/on_submit.ts @@ -36,6 +36,10 @@ export const on_submit = ({ if (res) form.${id} = res.${id}; } + if (md.mode !== "breadcrumb") { + md.cache("master")?.reload(); + } + return true; }; diff --git a/gen/gen_md/form_before_load.ts b/gen/gen_md/form_before_load.ts index 44983a7..50677f9 100755 --- a/gen/gen_md/form_before_load.ts +++ b/gen/gen_md/form_before_load.ts @@ -7,6 +7,9 @@ export const form_before_load = ( label: string ) => { return ` + const master = md.cache("master") as + | { reload: () => Promise } + | undefined; const id = master_detail_params(md).parent_id; @@ -31,6 +34,9 @@ export const form_before_load = ( md.ui.back = false; md.selected = null; md.render(); + if (md.mode !== "breadcrumb") { + master?.reload(); + } }); } }, @@ -41,10 +47,13 @@ export const form_before_load = ( onClick: async () => { md.ui.actions = [{ label: "Saving...", type: "ghost" }]; md.render(); - await md.cache("form")._submit(); + await md.cache("master")._submit(); setTimeout(() => { set_actions(); md.render(); + if (md.mode !== "breadcrumb") { + master?.reload(); + } }, 500); }, icon: \`\`, diff --git a/gen/gen_md/gen_detail.ts b/gen/gen_md/gen_detail.ts index 2b68a0a..9bf191a 100755 --- a/gen/gen_md/gen_detail.ts +++ b/gen/gen_md/gen_detail.ts @@ -18,32 +18,45 @@ export const gen_detail = () => { w: "full", h: "full", }, + adv: { + css: "", + js: "", + jsBuilt: "render();\n", + }, childs: [ { id: createId(), - adv: { - js: '
\n \n {children}\n \n
', - css: "", - jsBuilt: - 'render(/* @__PURE__ */ React.createElement("div", { ...props }, /* @__PURE__ */ React.createElement(\n Local,\n {\n name: "form",\n value: {\n hook: null\n }\n },\n children\n)));\n', - }, - dim: { - h: "full", - w: "full", - }, - name: "form", + name: "selected", type: "item", + dim: { + w: "full", + h: "full", + }, + adv: { + css: "", + js: `<> + {(md.selected || isEditor) && ( +
+ {children} +
+ )} +`, + jsBuilt: `render(React.createElement(React.Fragment, null, (md.selected || isEditor) && (React.createElement("div", Object.assign({}, props, { className: cx(props.className, "") }), children))));`, + }, childs: [ { id: createId(), adv: { + js: '
\n \n {children}\n \n
', css: "", + jsBuilt: + 'render(/* @__PURE__ */ React.createElement("div", { ...props }, /* @__PURE__ */ React.createElement(\n Local,\n {\n name: "form",\n value: {\n hook: null\n }\n },\n children\n)));\n', }, dim: { h: "full", w: "full", }, - name: "jsx: body", + name: "form", type: "item", childs: [ { @@ -55,435 +68,449 @@ export const gen_detail = () => { h: "full", w: "full", }, - name: "field", + name: "jsx: body", type: "item", - childs: [], - script: { - props: { - name: { - value: '"hello"', + childs: [ + { + id: createId(), + adv: { + css: "", }, - type: { - value: ' "text";\n', + dim: { + h: "full", + w: "full", }, - label: { - value: '"hello"', + name: "field", + type: "item", + childs: [], + script: { + props: { + name: { + value: '"hello"', + }, + type: { + value: ' "text";\n', + }, + label: { + value: '"hello"', + }, + }, }, + component: { + id: "32550d01-42a3-4b15-a04a-2c2d5c3c8e67", + props: { + fill: { + idx: 11, + meta: { + type: "text", + }, + name: "prop_11", + type: "string", + value: "`Haha`", + valueBuilt: "`Haha`", + }, + name: { + idx: 1, + meta: { + type: "text", + }, + name: "prop_1", + type: "string", + value: "`field_name`", + valueBuilt: "`field_name`", + }, + type: { + idx: 3, + meta: { + type: "option", + options: + '[\n "text", "buttons", "date", "datetime"\n]', + optionsBuilt: + ' [\n "text",\n "buttons",\n "date",\n "datetime"\n];\n', + }, + name: "prop_3", + type: "string", + value: '"text"', + valueBuilt: '"text"', + }, + label: { + idx: 1, + meta: { + type: "text", + }, + name: "prop_1", + type: "string", + value: "`Name`", + valueBuilt: "`Name`", + }, + title: { + idx: 7, + meta: { + type: "text", + }, + name: "prop_7", + type: "string", + value: '"hello"', + valueBuilt: ' "hello";\n', + }, + custom: { + idx: 5, + meta: { + type: "option", + options: + '[\n {\n label: "yes",\n value: "y"\n },\n {\n label: "no",\n value: "n"\n },\n]\n', + option_mode: "button", + optionsBuilt: + ' [\n {\n label: "yes",\n value: "y"\n },\n {\n label: "no",\n value: "n"\n }\n];\n', + }, + name: "prop_11", + type: "string", + value: '"y"', + valueBuilt: '"y"', + }, + options: { + idx: 5, + meta: { + type: "text", + }, + name: "prop_5", + type: "string", + value: + 'async () => {\r\n return [\r\n {\r\n value: "sample1",\r\n label: "sample1",\r\n },\r\n ];\r\n}', + valueBuilt: + ' async () => {\n return [\n {\n value: "sample1",\n label: "sample1"\n }\n ];\n};\n', + }, + required: { + idx: 7, + meta: { + type: "option", + options: + '[\n {\n label: "yes",\n value: "y",\n },\n {\n label: "no",\n value: "n",\n },\n] ', + optionsBuilt: + ' [\n {\n label: "yes",\n value: "y"\n },\n {\n label: "no",\n value: "n"\n }\n];\n', + }, + name: "prop_7", + type: "string", + value: '"n"', + valueBuilt: ' "n";\n', + }, + label_alt: { + idx: 2, + meta: { + type: "text", + }, + name: "prop_10", + type: "string", + value: '""', + valueBuilt: ' "";\n', + }, + on_change: { + idx: 11, + meta: { + type: "text", + }, + name: "prop_11", + type: "string", + value: "({ value }) => {}", + valueBuilt: " ({ value }) => {\n};\n", + }, + placeholder: { + idx: 3, + meta: { + type: "text", + }, + name: "prop_11", + type: "string", + value: '""', + visible: + '["text", "number", "password"].includes(type)', + valueBuilt: ' "";\n', + }, + slider_options: { + idx: 9, + meta: { + type: "text", + }, + name: "prop_9", + type: "string", + value: + 'async () => {\n return {\n step: 1,\n min: { value: 0, label: "Start" },\n max: { value: 100, label: "End" },\n };\n}', + visible: "type === 'slider'", + valueBuilt: + ' async () => {\n return {\n step: 1,\n min: { value: 0, label: "Start" },\n max: { value: 100, label: "End" }\n };\n};\n', + }, + suffix: { + idx: 12, + meta: { + type: "text", + }, + name: "prop_11", + type: "string", + value: '("")', + visible: + '["number", "text", "password"].includes(type)', + valueBuilt: ' "";\n', + }, + rel_fields: { + idx: 11, + name: "prop_11", + type: "string", + value: "[]", + valueBuilt: " [];\n", + meta: { + type: "option", + option_mode: "checkbox", + options: + "async () => {\n const result: { label: string; value: string; options?: any[] }[] = [];\n const fields = await db._schema.columns(rel_table);\n for (const [k, v] of Object.entries(fields)) {\n result.push({ value: k, label: k });\n }\n\n const rels = await db._schema.rels(rel_table);\n for (const [k, v] of Object.entries(rels)) {\n let options = [];\n const fields = await db._schema.columns(v.to.table);\n for (const [k, v] of Object.entries(fields)) {\n options.push({ value: k, label: k });\n }\n\n result.push({ value: k, label: k, options });\n }\n\n return result;\n}", + optionsBuilt: + " async () => {\n const result = [];\n const fields = await db._schema.columns(rel_table);\n for (const [k, v] of Object.entries(fields)) {\n result.push({ value: k, label: k });\n }\n const rels = await db._schema.rels(rel_table);\n for (const [k, v] of Object.entries(rels)) {\n let options = [];\n const fields2 = await db._schema.columns(v.to.table);\n for (const [k2, v2] of Object.entries(fields2)) {\n options.push({ value: k2, label: k2 });\n }\n result.push({ value: k, label: k, options });\n }\n return result;\n};\n", + }, + label: "fields", + }, + rel_query: { + idx: 11, + name: "prop_11", + type: "string", + value: "async () => {\n return {};\n}", + valueBuilt: " async () => {\n return {};\n};\n", + meta: { + type: "text", + }, + label: "query", + }, + }, + ref_ids: {}, + instances: { + npj543t5rpwx932a153hsfyl: { + zmit41kbgkbqcsmm8aspp8zy: + "mo4m0rnyey4y6v7tlajod95l", + }, + }, + }, + originalid: createId(), }, - }, - component: { - id: "32550d01-42a3-4b15-a04a-2c2d5c3c8e67", - props: { - fill: { - idx: 11, - meta: { - type: "text", - }, - name: "prop_11", - type: "string", - value: "`Haha`", - valueBuilt: "`Haha`", - }, - name: { - idx: 1, - meta: { - type: "text", - }, - name: "prop_1", - type: "string", - value: "`field_name`", - valueBuilt: "`field_name`", - }, - type: { - idx: 3, - meta: { - type: "option", - options: - '[\n "text", "buttons", "date", "datetime"\n]', - optionsBuilt: - ' [\n "text",\n "buttons",\n "date",\n "datetime"\n];\n', - }, - name: "prop_3", - type: "string", - value: '"text"', - valueBuilt: '"text"', - }, - label: { - idx: 1, - meta: { - type: "text", - }, - name: "prop_1", - type: "string", - value: "`Name`", - valueBuilt: "`Name`", - }, - title: { - idx: 7, - meta: { - type: "text", - }, - name: "prop_7", - type: "string", - value: '"hello"', - valueBuilt: ' "hello";\n', - }, - custom: { - idx: 5, - meta: { - type: "option", - options: - '[\n {\n label: "yes",\n value: "y"\n },\n {\n label: "no",\n value: "n"\n },\n]\n', - option_mode: "button", - optionsBuilt: - ' [\n {\n label: "yes",\n value: "y"\n },\n {\n label: "no",\n value: "n"\n }\n];\n', - }, - name: "prop_11", - type: "string", - value: '"y"', - valueBuilt: '"y"', - }, - options: { - idx: 5, - meta: { - type: "text", - }, - name: "prop_5", - type: "string", - value: - 'async () => {\r\n return [\r\n {\r\n value: "sample1",\r\n label: "sample1",\r\n },\r\n ];\r\n}', - valueBuilt: - ' async () => {\n return [\n {\n value: "sample1",\n label: "sample1"\n }\n ];\n};\n', - }, - required: { - idx: 7, - meta: { - type: "option", - options: - '[\n {\n label: "yes",\n value: "y",\n },\n {\n label: "no",\n value: "n",\n },\n] ', - optionsBuilt: - ' [\n {\n label: "yes",\n value: "y"\n },\n {\n label: "no",\n value: "n"\n }\n];\n', - }, - name: "prop_7", - type: "string", - value: '"n"', - valueBuilt: ' "n";\n', - }, - label_alt: { - idx: 2, - meta: { - type: "text", - }, - name: "prop_10", - type: "string", - value: '""', - valueBuilt: ' "";\n', - }, - on_change: { - idx: 11, - meta: { - type: "text", - }, - name: "prop_11", - type: "string", - value: "({ value }) => {}", - valueBuilt: " ({ value }) => {\n};\n", - }, - placeholder: { - idx: 3, - meta: { - type: "text", - }, - name: "prop_11", - type: "string", - value: '""', - visible: - '["text", "number", "password"].includes(type)', - valueBuilt: ' "";\n', - }, - slider_options: { - idx: 9, - meta: { - type: "text", - }, - name: "prop_9", - type: "string", - value: - 'async () => {\n return {\n step: 1,\n min: { value: 0, label: "Start" },\n max: { value: 100, label: "End" },\n };\n}', - visible: "type === 'slider'", - valueBuilt: - ' async () => {\n return {\n step: 1,\n min: { value: 0, label: "Start" },\n max: { value: 100, label: "End" }\n };\n};\n', - }, - suffix: { - idx: 12, - meta: { - type: "text", - }, - name: "prop_11", - type: "string", - value: '("")', - visible: - '["number", "text", "password"].includes(type)', - valueBuilt: ' "";\n', - }, - rel_fields: { - idx: 11, - name: "prop_11", - type: "string", - value: "[]", - valueBuilt: " [];\n", - meta: { - type: "option", - option_mode: "checkbox", - options: - "async () => {\n const result: { label: string; value: string; options?: any[] }[] = [];\n const fields = await db._schema.columns(rel_table);\n for (const [k, v] of Object.entries(fields)) {\n result.push({ value: k, label: k });\n }\n\n const rels = await db._schema.rels(rel_table);\n for (const [k, v] of Object.entries(rels)) {\n let options = [];\n const fields = await db._schema.columns(v.to.table);\n for (const [k, v] of Object.entries(fields)) {\n options.push({ value: k, label: k });\n }\n\n result.push({ value: k, label: k, options });\n }\n\n return result;\n}", - optionsBuilt: - " async () => {\n const result = [];\n const fields = await db._schema.columns(rel_table);\n for (const [k, v] of Object.entries(fields)) {\n result.push({ value: k, label: k });\n }\n const rels = await db._schema.rels(rel_table);\n for (const [k, v] of Object.entries(rels)) {\n let options = [];\n const fields2 = await db._schema.columns(v.to.table);\n for (const [k2, v2] of Object.entries(fields2)) {\n options.push({ value: k2, label: k2 });\n }\n result.push({ value: k, label: k, options });\n }\n return result;\n};\n", - }, - label: "fields", - }, - rel_query: { - idx: 11, - name: "prop_11", - type: "string", - value: "async () => {\n return {};\n}", - valueBuilt: " async () => {\n return {};\n};\n", - meta: { - type: "text", - }, - label: "query", - }, - }, - ref_ids: {}, - instances: { - npj543t5rpwx932a153hsfyl: { - zmit41kbgkbqcsmm8aspp8zy: "mo4m0rnyey4y6v7tlajod95l", - }, - }, - }, - originalid: createId(), + ], }, - ], - }, - { - id: createId(), - adv: { - js: "", - css: "", - jsBuilt: - "render(/* @__PURE__ */ React.createElement(\n Form,\n {\n on_init,\n on_load,\n form,\n PassProp,\n body,\n props,\n layout,\n on_submit\n }\n));\n", - }, - dim: { - h: "full", - w: "full", - }, - name: "el", - type: "item", - childs: [], - mobile: { - dim: { - h: "fit", - w: "full", - }, - }, - script: {}, - }, - ], - script: { - local: { - end: 85, - name: "form", - start: 53, - value: "{hook: null as any}", - }, - }, - component: { - id: "c4e65c26-4f36-48aa-a5b3-0771feac082e", - props: { - generate: { - idx: 5, - name: "prop_6", - type: "string", - value: '"n"', - valueBuilt: '"n"', - meta: { - options: - '[\n {\n label: "yes",\n value: "y"\n },\n {\n label: "no",\n value: "n"\n },\n] ', - optionsBuilt: - ' [\n {\n label: "yes",\n value: "y"\n },\n {\n label: "no",\n value: "n"\n }\n];\n', - type: "option", - }, - }, - gen_table: { - visible: "generate === 'y'", - idx: 6, - name: "prop_8", - type: "string", - value: '"m_aset"', - valueBuilt: '"m_aset"', - meta: { - options: - 'async () => {\n return (await db._schema.tables()).map((e) => ({\n value: e,\n label: e,\n reload: ["gen_fields"],\n }));\n}', - optionsBuilt: - ' async () => {\n return (await db._schema.tables()).map((e) => ({\n value: e,\n label: e,\n reload: ["gen_fields"]\n }));\n};\n', - type: "option", - option_mode: "dropdown", - }, - label: "table", - }, - gen_fields: { - idx: 7, - name: "prop_10", - type: "string", - value: - '["{\\"name\\":\\"id\\",\\"is_pk\\":true,\\"type\\":\\"int\\",\\"optional\\":false}","{\\"name\\":\\"nama_aset\\",\\"is_pk\\":false,\\"type\\":\\"varchar\\",\\"optional\\":true}","{\\"name\\":\\"nama_aset_keuangan\\",\\"is_pk\\":false,\\"type\\":\\"varchar\\",\\"optional\\":true}","{\\"name\\":\\"nama_aset_komersial\\",\\"is_pk\\":false,\\"type\\":\\"varchar\\",\\"optional\\":true}","{\\"name\\":\\"asset_number\\",\\"is_pk\\":false,\\"type\\":\\"varchar\\",\\"optional\\":true}","{\\"name\\":\\"luas_setifikat\\",\\"is_pk\\":false,\\"type\\":\\"decimal\\",\\"optional\\":true}","{\\"name\\":\\"tanggal_sertifikat\\",\\"is_pk\\":false,\\"type\\":\\"varchar\\",\\"optional\\":true}",{"value":"{\\"name\\":\\"m_cabang\\",\\"is_pk\\":false,\\"type\\":\\"has-one\\",\\"optional\\":true}","checked":["{\\"name\\":\\"id\\",\\"is_pk\\":true,\\"type\\":\\"int\\",\\"optional\\":false}","{\\"name\\":\\"nama_cabang\\",\\"is_pk\\":false,\\"type\\":\\"string\\",\\"optional\\":true}"]},{"value":"{\\"name\\":\\"m_regional\\",\\"is_pk\\":false,\\"type\\":\\"has-one\\",\\"optional\\":true}","checked":["{\\"name\\":\\"id\\",\\"is_pk\\":true,\\"type\\":\\"int\\",\\"optional\\":false}","{\\"name\\":\\"regional\\",\\"is_pk\\":false,\\"type\\":\\"varchar\\",\\"optional\\":false}"]}]', - valueBuilt: - '["{\\"name\\":\\"id\\",\\"is_pk\\":true,\\"type\\":\\"int\\",\\"optional\\":false}","{\\"name\\":\\"nama_aset\\",\\"is_pk\\":false,\\"type\\":\\"varchar\\",\\"optional\\":true}","{\\"name\\":\\"nama_aset_keuangan\\",\\"is_pk\\":false,\\"type\\":\\"varchar\\",\\"optional\\":true}","{\\"name\\":\\"nama_aset_komersial\\",\\"is_pk\\":false,\\"type\\":\\"varchar\\",\\"optional\\":true}","{\\"name\\":\\"asset_number\\",\\"is_pk\\":false,\\"type\\":\\"varchar\\",\\"optional\\":true}","{\\"name\\":\\"luas_setifikat\\",\\"is_pk\\":false,\\"type\\":\\"decimal\\",\\"optional\\":true}","{\\"name\\":\\"tanggal_sertifikat\\",\\"is_pk\\":false,\\"type\\":\\"varchar\\",\\"optional\\":true}",{"value":"{\\"name\\":\\"m_cabang\\",\\"is_pk\\":false,\\"type\\":\\"has-one\\",\\"optional\\":true}","checked":["{\\"name\\":\\"id\\",\\"is_pk\\":true,\\"type\\":\\"int\\",\\"optional\\":false}","{\\"name\\":\\"nama_cabang\\",\\"is_pk\\":false,\\"type\\":\\"string\\",\\"optional\\":true}"]},{"value":"{\\"name\\":\\"m_regional\\",\\"is_pk\\":false,\\"type\\":\\"has-one\\",\\"optional\\":true}","checked":["{\\"name\\":\\"id\\",\\"is_pk\\":true,\\"type\\":\\"int\\",\\"optional\\":false}","{\\"name\\":\\"regional\\",\\"is_pk\\":false,\\"type\\":\\"varchar\\",\\"optional\\":false}"]}]', - meta: { - options: - "async () => {\n const result: { label: string; value: string; options?: any[] }[] = [];\n const fields = await db._schema.columns(gen_table);\n for (const [k, v] of Object.entries(fields)) {\n result.push({\n value: JSON.stringify({\n name: k,\n is_pk: v.is_pk,\n type: v.db_type || v.type,\n optional: v.optional,\n }),\n label: k,\n });\n }\n const rels = await db._schema.rels(gen_table);\n for (const [k, v] of Object.entries(rels)) {\n let options = [];\n const fields = await db._schema.columns(v.to.table);\n for (const [k, v] of Object.entries(fields)) {\n options.push({\n value: JSON.stringify({\n name: k,\n is_pk: v.is_pk,\n type: v.db_type || v.type,\n optional: v.optional,\n }),\n label: k,\n });\n }\n result.push({\n value: JSON.stringify({\n name: k,\n is_pk: false,\n type: v.type,\n optional: true,\n }),\n label: k,\n options,\n });\n }\n\n return result;\n}", - optionsBuilt: - " async () => {\n const result = [];\n const fields = await db._schema.columns(gen_table);\n for (const [k, v] of Object.entries(fields)) {\n result.push({\n value: JSON.stringify({\n name: k,\n is_pk: v.is_pk,\n type: v.db_type || v.type,\n optional: v.optional\n }),\n label: k\n });\n }\n const rels = await db._schema.rels(gen_table);\n for (const [k, v] of Object.entries(rels)) {\n let options = [];\n const fields2 = await db._schema.columns(v.to.table);\n for (const [k2, v2] of Object.entries(fields2)) {\n options.push({\n value: JSON.stringify({\n name: k2,\n is_pk: v2.is_pk,\n type: v2.db_type || v2.type,\n optional: v2.optional\n }),\n label: k2\n });\n }\n result.push({\n value: JSON.stringify({\n name: k,\n is_pk: false,\n type: v.type,\n optional: true\n }),\n label: k,\n options\n });\n }\n return result;\n};\n", - type: "option", - option_mode: "checkbox", - }, - label: "fields", - visible: "generate === 'y'", - }, - gen_btn: { - idx: 9, - name: "prop_10", - type: "string", - value: - '[\n {\n label: "Generate",\n onClick: gen_form,\n },\n]', - valueBuilt: - ' [\n {\n label: "Generate",\n onClick: gen_form\n }\n];\n', - meta: { - type: "button", - }, - label: "_", - visible: "generate === 'y'", - }, - body: { - idx: 4, - meta: { - type: "content-element", - }, - name: "prop_3", - type: "string", - value: '"hello"', - content: { + { id: createId(), adv: { + js: "", css: "", + jsBuilt: + "render(/* @__PURE__ */ React.createElement(\n Form,\n {\n on_init,\n on_load,\n form,\n PassProp,\n body,\n props,\n layout,\n on_submit\n }\n));\n", }, dim: { h: "full", w: "full", }, - name: "body", + name: "el", type: "item", childs: [], - padding: { - l: 10, - b: 10, - t: 10, - r: 10, + mobile: { + dim: { + h: "fit", + w: "full", + }, + }, + script: {}, + }, + ], + script: { + local: { + end: 85, + name: "form", + start: 53, + value: "{hook: null as any}", + }, + }, + component: { + id: "c4e65c26-4f36-48aa-a5b3-0771feac082e", + props: { + generate: { + idx: 5, + name: "prop_6", + type: "string", + value: '"n"', + valueBuilt: '"n"', + meta: { + options: + '[\n {\n label: "yes",\n value: "y"\n },\n {\n label: "no",\n value: "n"\n },\n] ', + optionsBuilt: + ' [\n {\n label: "yes",\n value: "y"\n },\n {\n label: "no",\n value: "n"\n }\n];\n', + type: "option", + }, + }, + gen_table: { + visible: "generate === 'y'", + idx: 6, + name: "prop_8", + type: "string", + value: '"m_aset"', + valueBuilt: '"m_aset"', + meta: { + options: + 'async () => {\n return (await db._schema.tables()).map((e) => ({\n value: e,\n label: e,\n reload: ["gen_fields"],\n }));\n}', + optionsBuilt: + ' async () => {\n return (await db._schema.tables()).map((e) => ({\n value: e,\n label: e,\n reload: ["gen_fields"]\n }));\n};\n', + type: "option", + option_mode: "dropdown", + }, + label: "table", + }, + gen_fields: { + idx: 7, + name: "prop_10", + type: "string", + value: + '["{\\"name\\":\\"id\\",\\"is_pk\\":true,\\"type\\":\\"int\\",\\"optional\\":false}","{\\"name\\":\\"nama_aset\\",\\"is_pk\\":false,\\"type\\":\\"varchar\\",\\"optional\\":true}","{\\"name\\":\\"nama_aset_keuangan\\",\\"is_pk\\":false,\\"type\\":\\"varchar\\",\\"optional\\":true}","{\\"name\\":\\"nama_aset_komersial\\",\\"is_pk\\":false,\\"type\\":\\"varchar\\",\\"optional\\":true}","{\\"name\\":\\"asset_number\\",\\"is_pk\\":false,\\"type\\":\\"varchar\\",\\"optional\\":true}","{\\"name\\":\\"luas_setifikat\\",\\"is_pk\\":false,\\"type\\":\\"decimal\\",\\"optional\\":true}","{\\"name\\":\\"tanggal_sertifikat\\",\\"is_pk\\":false,\\"type\\":\\"varchar\\",\\"optional\\":true}",{"value":"{\\"name\\":\\"m_cabang\\",\\"is_pk\\":false,\\"type\\":\\"has-one\\",\\"optional\\":true}","checked":["{\\"name\\":\\"id\\",\\"is_pk\\":true,\\"type\\":\\"int\\",\\"optional\\":false}","{\\"name\\":\\"nama_cabang\\",\\"is_pk\\":false,\\"type\\":\\"string\\",\\"optional\\":true}"]},{"value":"{\\"name\\":\\"m_regional\\",\\"is_pk\\":false,\\"type\\":\\"has-one\\",\\"optional\\":true}","checked":["{\\"name\\":\\"id\\",\\"is_pk\\":true,\\"type\\":\\"int\\",\\"optional\\":false}","{\\"name\\":\\"regional\\",\\"is_pk\\":false,\\"type\\":\\"varchar\\",\\"optional\\":false}"]}]', + valueBuilt: + '["{\\"name\\":\\"id\\",\\"is_pk\\":true,\\"type\\":\\"int\\",\\"optional\\":false}","{\\"name\\":\\"nama_aset\\",\\"is_pk\\":false,\\"type\\":\\"varchar\\",\\"optional\\":true}","{\\"name\\":\\"nama_aset_keuangan\\",\\"is_pk\\":false,\\"type\\":\\"varchar\\",\\"optional\\":true}","{\\"name\\":\\"nama_aset_komersial\\",\\"is_pk\\":false,\\"type\\":\\"varchar\\",\\"optional\\":true}","{\\"name\\":\\"asset_number\\",\\"is_pk\\":false,\\"type\\":\\"varchar\\",\\"optional\\":true}","{\\"name\\":\\"luas_setifikat\\",\\"is_pk\\":false,\\"type\\":\\"decimal\\",\\"optional\\":true}","{\\"name\\":\\"tanggal_sertifikat\\",\\"is_pk\\":false,\\"type\\":\\"varchar\\",\\"optional\\":true}",{"value":"{\\"name\\":\\"m_cabang\\",\\"is_pk\\":false,\\"type\\":\\"has-one\\",\\"optional\\":true}","checked":["{\\"name\\":\\"id\\",\\"is_pk\\":true,\\"type\\":\\"int\\",\\"optional\\":false}","{\\"name\\":\\"nama_cabang\\",\\"is_pk\\":false,\\"type\\":\\"string\\",\\"optional\\":true}"]},{"value":"{\\"name\\":\\"m_regional\\",\\"is_pk\\":false,\\"type\\":\\"has-one\\",\\"optional\\":true}","checked":["{\\"name\\":\\"id\\",\\"is_pk\\":true,\\"type\\":\\"int\\",\\"optional\\":false}","{\\"name\\":\\"regional\\",\\"is_pk\\":false,\\"type\\":\\"varchar\\",\\"optional\\":false}"]}]', + meta: { + options: + "async () => {\n const result: { label: string; value: string; options?: any[] }[] = [];\n const fields = await db._schema.columns(gen_table);\n for (const [k, v] of Object.entries(fields)) {\n result.push({\n value: JSON.stringify({\n name: k,\n is_pk: v.is_pk,\n type: v.db_type || v.type,\n optional: v.optional,\n }),\n label: k,\n });\n }\n const rels = await db._schema.rels(gen_table);\n for (const [k, v] of Object.entries(rels)) {\n let options = [];\n const fields = await db._schema.columns(v.to.table);\n for (const [k, v] of Object.entries(fields)) {\n options.push({\n value: JSON.stringify({\n name: k,\n is_pk: v.is_pk,\n type: v.db_type || v.type,\n optional: v.optional,\n }),\n label: k,\n });\n }\n result.push({\n value: JSON.stringify({\n name: k,\n is_pk: false,\n type: v.type,\n optional: true,\n }),\n label: k,\n options,\n });\n }\n\n return result;\n}", + optionsBuilt: + " async () => {\n const result = [];\n const fields = await db._schema.columns(gen_table);\n for (const [k, v] of Object.entries(fields)) {\n result.push({\n value: JSON.stringify({\n name: k,\n is_pk: v.is_pk,\n type: v.db_type || v.type,\n optional: v.optional\n }),\n label: k\n });\n }\n const rels = await db._schema.rels(gen_table);\n for (const [k, v] of Object.entries(rels)) {\n let options = [];\n const fields2 = await db._schema.columns(v.to.table);\n for (const [k2, v2] of Object.entries(fields2)) {\n options.push({\n value: JSON.stringify({\n name: k2,\n is_pk: v2.is_pk,\n type: v2.db_type || v2.type,\n optional: v2.optional\n }),\n label: k2\n });\n }\n result.push({\n value: JSON.stringify({\n name: k,\n is_pk: false,\n type: v.type,\n optional: true\n }),\n label: k,\n options\n });\n }\n return result;\n};\n", + type: "option", + option_mode: "checkbox", + }, + label: "fields", + visible: "generate === 'y'", + }, + gen_btn: { + idx: 9, + name: "prop_10", + type: "string", + value: + '[\n {\n label: "Generate",\n onClick: gen_form,\n },\n]', + valueBuilt: + ' [\n {\n label: "Generate",\n onClick: gen_form\n }\n];\n', + meta: { + type: "button", + }, + label: "_", + visible: "generate === 'y'", + }, + body: { + idx: 4, + meta: { + type: "content-element", + }, + name: "prop_3", + type: "string", + value: '"hello"', + content: { + id: createId(), + adv: { + css: "", + }, + dim: { + h: "full", + w: "full", + }, + name: "body", + type: "item", + childs: [], + padding: { + l: 10, + b: 10, + t: 10, + r: 10, + }, + }, + typings: 'const typings = {\n data: "any",\n}', + valueBuilt: ' "hello";\n', + jsxCalledBy: [ + "bca0tc62ycv8tarukqpo1vf8", + "deqnuhatpkpyf5uqjsxcdpe0", + ], + }, + layout: { + idx: 3, + meta: { + type: "option", + options: '["auto", "1-col", "2-col"]', + optionsBuilt: ' ["auto", "1-col", "2-col"];\n', + }, + name: "prop_5", + type: "string", + value: '"auto"', + valueBuilt: ' "auto";\n', + }, + on_init: { + idx: 0, + meta: { + type: "text", + }, + name: "prop_5", + type: "string", + value: `\ +({ submit, reload }: Init) => { + // on init + md.cache("detail").submit = submit; + md.cache("detail").reload = reload; +}; + +type Init = { submit: () => void; reload: () => Promise };`, + }, + on_load: { + idx: 1, + meta: { + type: "text", + }, + name: "prop_1", + type: "string", + value: + 'async (opt) => {\n if (isEditor) return {};\n\n let id = parseInt(md.selected.id);\n\n const after_load = (item: any) => {\n const set_actions = () =>\n (md.ui.actions = [\n {\n label: "Delete",\n type: "destructive",\n onClick: async () => {\n if (confirm("Are you sure ?")) {\n md.ui.actions = [{ label: "Deleting...", type: "ghost" }];\n md.render();\n\n await db.m_aset.delete({ where: { id: item.id } });\n\n setTimeout(() => {\n md.ui.actions = [...md.ui.default_actions];\n md.ui.breadcrumb = [];\n md.ui.back = false;\n md.selected = null;\n md.render();\n });\n }\n },\n icon: ``,\n },\n {\n label: "Save",\n onClick: async () => {\n md.ui.actions = [{ label: "Saving...", type: "ghost" }];\n md.render();\n await md.cache("form")._submit();\n setTimeout(() => {\n set_actions();\n md.render();\n }, 500);\n },\n icon: ``,\n },\n ]);\n set_actions();\n md.ui.breadcrumb = [["Master Aset", ""], item?.nama_aset_komersial];\n md.render();\n };\n\n if (id) {\n md.ui.breadcrumb = [["Master Aset", ""], "..."];\n md.render();\n\n const item = await db.m_aset.findFirst({\n where: {\n id: id,\n },\n select: {\n id: true,\n nama_aset: true,\n nama_aset_keuangan: true,\n nama_aset_komersial: true,\n asset_number: true,\n luas_setifikat: true,\n tanggal_sertifikat: true,\n m_cabang: {\n select: {\n id: true,\n },\n },\n m_regional: {\n select: {\n id: true,\n },\n },\n },\n });\n\n for (const [k, v] of Object.entries(item)) {\n if (k === "m_cabang") {\n if (v?.["id"]) item[k] = { connect: { id: v?.["id"] } } as any;\n else delete item[k];\n }\n if (k === "m_regional") {\n if (v?.["id"]) item[k] = { connect: { id: v?.["id"] } } as any;\n else delete item[k];\n }\n }\n\n after_load(item);\n\n return item;\n } else {\n after_load({});\n }\n}', + }, + on_submit: { + idx: 2, + meta: { + type: "text", + }, + name: "prop_1", + type: "string", + value: + 'async ({ form, error }: IForm) => {\n if (typeof error === "object" && Object.keys(error).length > 0) return {};\n\n const data = { ...form };\n delete data.id;\n\n if (form.id) {\n await db.m_aset.update({\n where: {\n id: form.id,\n },\n data,\n });\n } else {\n const res = await db.m_aset.create({\n data,\n select: { id: true },\n });\n if (res) form.id = res.id;\n }\n\n return true;\n};\n\ntype IForm = { form: any; error: Record }', + }, + gen_mode: { + idx: 8, + name: "prop_10", + type: "string", + value: + '["on_init",{"value":"fields","checked":["clear","add","update"]},"on_submit","on_load"]', + valueBuilt: + '["on_init",{"value":"fields","checked":["clear","add","update"]},"on_submit","on_load"]', + meta: { + options: + '[\n {\n label: "on_init",\n value: "on_init",\n },\n {\n label: "on_load",\n value: "on_load",\n },\n {\n label: "on_submit",\n value: "on_submit",\n },\n\n {\n label: "fields",\n value: "fields",\n options: [\n {\n label: "clear",\n value: "clear",\n },\n {\n label: "add",\n value: "add",\n },\n {\n label: "update",\n value: "update",\n },\n ],\n },\n]', + optionsBuilt: + ' [\n {\n label: "on_init",\n value: "on_init"\n },\n {\n label: "on_load",\n value: "on_load"\n },\n {\n label: "on_submit",\n value: "on_submit"\n },\n {\n label: "fields",\n value: "fields",\n options: [\n {\n label: "clear",\n value: "clear"\n },\n {\n label: "add",\n value: "add"\n },\n {\n label: "update",\n value: "update"\n }\n ]\n }\n];\n', + type: "option", + option_mode: "checkbox", + }, + label: "mode", + visible: "generate === 'y'", + }, + cache: { + idx: 11, + name: "prop_11", + type: "string", + value: '() => {\n return md.cache("form");\n}', + valueBuilt: ' () => {\n return md.cache("form");\n};\n', + meta: { + type: "text", + }, }, }, - typings: 'const typings = {\n data: "any",\n}', - valueBuilt: ' "hello";\n', - jsxCalledBy: [ - "bca0tc62ycv8tarukqpo1vf8", - "deqnuhatpkpyf5uqjsxcdpe0", - ], - }, - layout: { - idx: 3, - meta: { - type: "option", - options: '["auto", "1-col", "2-col"]', - optionsBuilt: ' ["auto", "1-col", "2-col"];\n', - }, - name: "prop_5", - type: "string", - value: '"auto"', - valueBuilt: ' "auto";\n', - }, - on_init: { - idx: 0, - meta: { - type: "text", - }, - name: "prop_5", - type: "string", - value: - '({ submit }: Init) => {\n // on init\n md.cache("form")._submit = submit;\n};\n\ntype Init = { submit: () => void }', - valueBuilt: - ' ({ submit }) => {\n md.cache("form")._submit = submit;\n};\n', - }, - on_load: { - idx: 1, - meta: { - type: "text", - }, - name: "prop_1", - type: "string", - value: - 'async (opt) => {\n if (isEditor) return {};\n\n let id = parseInt(md.selected.id);\n\n const after_load = (item: any) => {\n const set_actions = () =>\n (md.ui.actions = [\n {\n label: "Delete",\n type: "destructive",\n onClick: async () => {\n if (confirm("Are you sure ?")) {\n md.ui.actions = [{ label: "Deleting...", type: "ghost" }];\n md.render();\n\n await db.m_aset.delete({ where: { id: item.id } });\n\n setTimeout(() => {\n md.ui.actions = [...md.ui.default_actions];\n md.ui.breadcrumb = [];\n md.ui.back = false;\n md.selected = null;\n md.render();\n });\n }\n },\n icon: ``,\n },\n {\n label: "Save",\n onClick: async () => {\n md.ui.actions = [{ label: "Saving...", type: "ghost" }];\n md.render();\n await md.cache("form")._submit();\n setTimeout(() => {\n set_actions();\n md.render();\n }, 500);\n },\n icon: ``,\n },\n ]);\n set_actions();\n md.ui.breadcrumb = [["Master Aset", ""], item?.nama_aset_komersial];\n md.render();\n };\n\n if (id) {\n md.ui.breadcrumb = [["Master Aset", ""], "..."];\n md.render();\n\n const item = await db.m_aset.findFirst({\n where: {\n id: id,\n },\n select: {\n id: true,\n nama_aset: true,\n nama_aset_keuangan: true,\n nama_aset_komersial: true,\n asset_number: true,\n luas_setifikat: true,\n tanggal_sertifikat: true,\n m_cabang: {\n select: {\n id: true,\n },\n },\n m_regional: {\n select: {\n id: true,\n },\n },\n },\n });\n\n for (const [k, v] of Object.entries(item)) {\n if (k === "m_cabang") {\n if (v?.["id"]) item[k] = { connect: { id: v?.["id"] } } as any;\n else delete item[k];\n }\n if (k === "m_regional") {\n if (v?.["id"]) item[k] = { connect: { id: v?.["id"] } } as any;\n else delete item[k];\n }\n }\n\n after_load(item);\n\n return item;\n } else {\n after_load({});\n }\n}', - }, - on_submit: { - idx: 2, - meta: { - type: "text", - }, - name: "prop_1", - type: "string", - value: - 'async ({ form, error }: IForm) => {\n if (typeof error === "object" && Object.keys(error).length > 0) return {};\n\n const data = { ...form };\n delete data.id;\n\n if (form.id) {\n await db.m_aset.update({\n where: {\n id: form.id,\n },\n data,\n });\n } else {\n const res = await db.m_aset.create({\n data,\n select: { id: true },\n });\n if (res) form.id = res.id;\n }\n\n return true;\n};\n\ntype IForm = { form: any; error: Record }', - }, - gen_mode: { - idx: 8, - name: "prop_10", - type: "string", - value: - '["on_init",{"value":"fields","checked":["clear","add","update"]},"on_submit","on_load"]', - valueBuilt: - '["on_init",{"value":"fields","checked":["clear","add","update"]},"on_submit","on_load"]', - meta: { - options: - '[\n {\n label: "on_init",\n value: "on_init",\n },\n {\n label: "on_load",\n value: "on_load",\n },\n {\n label: "on_submit",\n value: "on_submit",\n },\n\n {\n label: "fields",\n value: "fields",\n options: [\n {\n label: "clear",\n value: "clear",\n },\n {\n label: "add",\n value: "add",\n },\n {\n label: "update",\n value: "update",\n },\n ],\n },\n]', - optionsBuilt: - ' [\n {\n label: "on_init",\n value: "on_init"\n },\n {\n label: "on_load",\n value: "on_load"\n },\n {\n label: "on_submit",\n value: "on_submit"\n },\n {\n label: "fields",\n value: "fields",\n options: [\n {\n label: "clear",\n value: "clear"\n },\n {\n label: "add",\n value: "add"\n },\n {\n label: "update",\n value: "update"\n }\n ]\n }\n];\n', - type: "option", - option_mode: "checkbox", - }, - label: "mode", - visible: "generate === 'y'", - }, - cache: { - idx: 11, - name: "prop_11", - type: "string", - value: '() => {\n return md.cache("form");\n}', - valueBuilt: ' () => {\n return md.cache("form");\n};\n', - meta: { - type: "text", - }, + ref_ids: {}, + useStyle: false, + instances: {}, }, + originalid: createId(), }, - ref_ids: {}, - useStyle: false, - instances: {}, - }, - originalid: createId(), + ], }, ], - adv: { - css: "", - js: "", - jsBuilt: "render();\n", - }, }, ], adv: { @@ -495,6 +522,6 @@ export const gen_detail = () => { return { content: res.childs[0], - props: res.childs[0].childs[0].component.props, + props: res.childs[0].childs[0].childs[0].component.props, }; }; diff --git a/gen/gen_md/gen_header.ts b/gen/gen_md/gen_header.ts index 5a7f493..5b741ac 100755 --- a/gen/gen_md/gen_header.ts +++ b/gen/gen_md/gen_header.ts @@ -13,7 +13,7 @@ export const gen_header = () => { childs: [ { id: createId(), - name: "breadcrumb", + name: "wrapper", type: "item", dim: { w: "full", @@ -71,9 +71,9 @@ export const gen_header = () => { }, ], adv: { - js: '<>\n {md.ui.back && (\n {\n md.ui.actions = [...md.ui.default_actions];\n md.ui.breadcrumb = [];\n md.ui.back = false;\n md.selected = null;\n md.render();\n }}\n >\n {children}\n
\n )}\n', + js: '<>\n {md.selected && (\n {\n md.ui.actions = [...md.ui.default_actions];\n md.ui.breadcrumb = [];\n md.ui.back = false;\n md.selected = null;\n md.render();\n }}\n >\n {children}\n \n )}\n', jsBuilt: - 'render(/* @__PURE__ */ React.createElement(React.Fragment, null, md.ui.back && /* @__PURE__ */ React.createElement(\n "div",\n {\n ...props,\n className: cx(props.className, ""),\n onClick: () => {\n md.ui.actions = [...md.ui.default_actions];\n md.ui.breadcrumb = [];\n md.ui.back = false;\n md.selected = null;\n md.render();\n }\n },\n children\n)));\n', + 'render(/* @__PURE__ */ React.createElement(React.Fragment, null, md.selected && /* @__PURE__ */ React.createElement(\n "div",\n {\n ...props,\n className: cx(props.className, ""),\n onClick: () => {\n md.ui.actions = [...md.ui.default_actions];\n md.ui.breadcrumb = [];\n md.ui.back = false;\n md.selected = null;\n md.render();\n }\n },\n children\n)));\n', css: "& {\n display: flex;\n cursor: pointer;\n\n // &.mobile {}\n // &.desktop {}\n &:hover {\n background: rgb(237, 246, 255);\n }\n}", }, script: {}, @@ -188,9 +188,6 @@ export const gen_header = () => { }, ], adv: { - js: '<>\n {md.mode === "breadcrumb" && (\n
\n {children}\n
\n )}\n', - jsBuilt: - 'render(/* @__PURE__ */ React.createElement(React.Fragment, null, md.mode === "breadcrumb" && /* @__PURE__ */ React.createElement("div", { ...props, className: cx(props.className, "") }, children)));\n', css: "", }, script: {}, diff --git a/gen/gen_md/gen_master.ts b/gen/gen_md/gen_master.ts index 248b33a..8d9f535 100755 --- a/gen/gen_md/gen_master.ts +++ b/gen/gen_md/gen_master.ts @@ -100,110 +100,7 @@ export const gen_master = () => { }, name: "prop_3", type: "item", - childs: [ - { - id: createId(), - adv: { - js: '<>\n {cell.key === "id" && (\n
\n {cell.value}\n
\n )}\n', - css: "", - jsBuilt: - 'render(\n React.createElement(\n React.Fragment,\n null,\n cell.key === "id" &&\n React.createElement(\n "div",\n Object.assign({}, props, { className: cx(props.className, "") }),\n cell.value\n )\n )\n)', - }, - dim: { - h: "full", - w: "full", - }, - name: "id", - type: "item", - childs: [], - script: {}, - }, - { - id: createId(), - adv: { - js: '<>\n {cell.key === "nama_aset_komersial" && (\n
\n {cell.value}\n
\n )}\n', - css: "", - jsBuilt: - 'render(\n React.createElement(\n React.Fragment,\n null,\n cell.key === "nama_aset_komersial" &&\n React.createElement(\n "div",\n Object.assign({}, props, { className: cx(props.className, "") }),\n cell.value\n )\n )\n)', - }, - dim: { - h: "full", - w: "full", - }, - name: "nama_aset_komersial", - type: "item", - childs: [], - script: {}, - }, - { - id: createId(), - adv: { - js: '<>\n {cell.key === "m_cabang" && (\n
\n {cell.value?.["nama_cabang"]}\n
\n )}\n', - css: "", - jsBuilt: - 'render(\n React.createElement(\n React.Fragment,\n null,\n cell.key === "m_cabang" &&\n React.createElement(\n "div",\n Object.assign({}, props, { className: cx(props.className, "") }),\n cell.value?.["nama_cabang"]\n )\n )\n)', - }, - dim: { - h: "full", - w: "full", - }, - name: "m_cabang", - type: "item", - childs: [], - script: {}, - }, - { - id: createId(), - adv: { - js: '<>\n {cell.key === "m_regional" && (\n
\n {cell.value?.["regional"]}\n
\n )}\n', - css: "", - jsBuilt: - 'render(\n React.createElement(\n React.Fragment,\n null,\n cell.key === "m_regional" &&\n React.createElement(\n "div",\n Object.assign({}, props, { className: cx(props.className, "") }),\n cell.value?.["regional"]\n )\n )\n)', - }, - dim: { - h: "full", - w: "full", - }, - name: "m_regional", - type: "item", - childs: [], - script: {}, - }, - { - id: createId(), - adv: { - js: '<>\n {cell.key === "luas_setifikat" && (\n
\n {cell.value}\n
\n )}\n', - css: "", - jsBuilt: - 'render(\n React.createElement(\n React.Fragment,\n null,\n cell.key === "luas_setifikat" &&\n React.createElement(\n "div",\n Object.assign({}, props, { className: cx(props.className, "") }),\n cell.value\n )\n )\n)', - }, - dim: { - h: "full", - w: "full", - }, - name: "luas_setifikat", - type: "item", - childs: [], - script: {}, - }, - { - id: createId(), - adv: { - js: '<>\n {cell.key === "tanggal_sertifikat" && (\n
\n {cell.value}\n
\n )}\n', - css: "", - jsBuilt: - 'render(\n React.createElement(\n React.Fragment,\n null,\n cell.key === "tanggal_sertifikat" &&\n React.createElement(\n "div",\n Object.assign({}, props, { className: cx(props.className, "") }),\n cell.value\n )\n )\n)', - }, - dim: { - h: "full", - w: "full", - }, - name: "tanggal_sertifikat", - type: "item", - childs: [], - script: {}, - }, - ], + childs: [] as any, hidden: false, }, typings: @@ -217,7 +114,7 @@ export const gen_master = () => { name: "prop_1", type: "string", value: - 'async (): Promise<\n { key: string; name: string; width?: number; frozen?: boolean }[]\n > => {\n return [\n { key: "id", name: "#", width: 60, frozen: true },\n {"key":"nama_aset_komersial","name":"Nama Aset Komersial"},\n {"key":"m_cabang","name":"Cabang"},\n {"key":"m_regional","name":"Regional"},\n {"key":"luas_setifikat","name":"Luas Setifikat"},\n {"key":"tanggal_sertifikat","name":"Tanggal Sertifikat"}\n ];\n }', + 'async (): Promise<\n { key: string; name: string; width?: number; frozen?: boolean }[]\n > => {\n return [\n { key: "id", name: "#", width: 60, frozen: true },\n {"key":"m_cabang","name":"Cabang"},\n {"key":"m_regional","name":"Regional"},\n {"key":"nama_aset_komersial","name":"Nama Aset Komersial"},\n {"key":"asset_number","name":"Asset Number"}\n ];\n }', }, on_load: { idx: 1, @@ -227,7 +124,7 @@ export const gen_master = () => { name: "prop_1", type: "string", value: - "async () => {\n if (isEditor)\n return [\n {\n },\n });\n\n return items;\n}", + 'async (arg: TableOnLoad) => {\n md.cache("master").reload = arg.reload;\n\n if (isEditor)\n return [\n {\n id: "sample",\n m_cabang: { nama_cabang: "sample" },\n m_regional: { regional: "sample" },\n nama_aset_komersial: "sample",\n asset_number: "sample",\n },\n ];\n\n const items = await db.m_aset.findMany({\n select: {\n id: true,\n m_cabang: {\n select: {\n id: true,\n nama_cabang: true,\n },\n },\n m_regional: {\n select: {\n regional: true,\n id: true,\n },\n },\n nama_aset_komersial: true,\n asset_number: true,\n },\n orderBy: {\n id: createId(),\n },\n });\n\n return items;\n};\n\ntype TableOnLoad = {\n reload: () => Promise;\n}', }, generate: { idx: 5, @@ -263,10 +160,32 @@ export const gen_master = () => { idx: 11, name: "prop_11", type: "string", - value: - "({ row, rows, idx, event }: OnRowClick) => {\n md.selected = row;\n md.render();\n};\n\ntype OnRowClick = {\n row: any;\n rows: any[];\n idx: any;\n event: React.MouseEvent;\n}", - valueBuilt: - " ({ row, rows, idx, event }) => {\n md.selected = row;\n md.render();\n};\n", + value: `\ +({ row, rows, idx, event }: OnRowClick) => { + md.selected = row; + md.render(); + const reload = md.cache("detail")?.reload; + if (typeof reload === 'function') { + reload() + } +}; + +type OnRowClick = { + row: any; + rows: any[]; + idx: any; + event: React.MouseEvent; +}`, + valueBuilt: `({ row, rows, idx, event }) => { + var _a; + md.selected = row; + md.render(); + const reload = (_a = md.cache("detail")) === null || _a === void 0 ? void 0 : _a.reload; + if (typeof reload === 'function') { + reload(); + } +}; +`, meta: { type: "text", }, @@ -281,6 +200,18 @@ export const gen_master = () => { type: "button", }, }, + selected: { + idx: 3, + name: "prop_9", + type: "string", + value: + "({ row, rows, idx }: SelectedRow) => {\n return md.selected?.id === row?.id;\n};\n\ntype SelectedRow = {\n row: any;\n rows: any[];\n idx: any;\n}", + valueBuilt: + " ({ row, rows, idx }) => {\n return md.selected?.id === row?.id;\n};\n", + meta: { + type: "text", + }, + }, }, ref_ids: {}, instances: {}, diff --git a/gen/gen_md/gen_md.ts b/gen/gen_md/gen_md.ts index 05aa42e..b089d7a 100755 --- a/gen/gen_md/gen_md.ts +++ b/gen/gen_md/gen_md.ts @@ -28,17 +28,21 @@ export const gen_md = (modify: (data: any) => void, data: any) => { const col = JSON.parse(sel.value) as Col; select[col.name] = {}; const fields: string[] = []; + const subsel: any = {}; + for (let s of sel.checked) { const c = JSON.parse(s) as Col; if (c.is_pk) { pks[col.name] = c.name; fields.push(`::${c.name}`); - select[col.name] = { select: { [c.name]: true } }; col.relation = { table: col.name, pk: sel.name }; } else { fields.push(c.name); } + subsel[c.name] = true; } + select[col.name] = { select: subsel }; + columns.push(col); new_fields.push({ name: col.name, diff --git a/gen/gen_table/gen_table.ts b/gen/gen_table/gen_table.ts index 0dcb06d..46a0563 100755 --- a/gen/gen_table/gen_table.ts +++ b/gen/gen_table/gen_table.ts @@ -56,6 +56,19 @@ export const gen_table = (modify: (data: any) => void, data: any) => { result["child"] = data["child"]; result["child"].content.childs = newField(select, pks); } + if (data["selected"]) { + result["selected"] = data["selected"]; + result["selected"].value = `\ +({ row, rows, idx }: SelectedRow) => { + return md.selected?.id === row?.id; +}; + +type SelectedRow = { + row: any; + rows: any[]; + idx: any; +}`; + } } modify(result); diff --git a/gen/gen_table/new_field.ts b/gen/gen_table/new_field.ts index 500cdfa..54c0cab 100755 --- a/gen/gen_table/new_field.ts +++ b/gen/gen_table/new_field.ts @@ -1,5 +1,4 @@ import { createId } from "@paralleldrive/cuid2"; -import { GFCol } from "../utils"; export const newField = (select: any, pks: Record) => { const result = []; @@ -8,7 +7,7 @@ export const newField = (select: any, pks: Record) => { if (typeof v === "object") { const res = Object.keys(v.select) .filter((e) => e !== pks[k]) - .map((e) => `cell.value?.["${e}"]`) + .map((e) => `cell.value?.["${k}"]?.["${e}"] || ''`) .join('+ " " +'); result.push({ @@ -18,7 +17,7 @@ export const newField = (select: any, pks: Record) => { <> {cell.key === "${k}" && (
- {${res}} + {Array.isArray(cell.value) ? cell.value.length + ' items' : ${res}}
)} `, diff --git a/gen/gen_table/on_load.ts b/gen/gen_table/on_load.ts index bf63fe5..1936257 100755 --- a/gen/gen_table/on_load.ts +++ b/gen/gen_table/on_load.ts @@ -28,7 +28,12 @@ export const on_load = ({ } return `\ -async () => { +async (arg: TableOnLoad) => { + + if (typeof md !== 'undefined') { + md.cache("master").reload = arg.reload; + } + if (isEditor) return [${JSON.stringify(sample)}]; const items = await db.${table}.findMany({ @@ -39,5 +44,10 @@ async () => { }); return items; -}`; +} + +type TableOnLoad = { + reload: () => Promise; +} +`; };