fix
This commit is contained in:
parent
32ead5308f
commit
3f56904fd7
|
|
@ -18,6 +18,7 @@ import useOnClickOutside from "../hooks";
|
|||
import { Period, DatepickerType, ColorKeys } from "../types";
|
||||
|
||||
import { Arrow, VerticalDash } from "./utils";
|
||||
import { createPortal } from "react-dom";
|
||||
|
||||
const Datepicker: React.FC<DatepickerType> = ({
|
||||
primaryColor = "blue",
|
||||
|
|
@ -70,8 +71,8 @@ const Datepicker: React.FC<DatepickerType> = ({
|
|||
const [inputRef, setInputRef] = useState(React.createRef<HTMLInputElement>());
|
||||
|
||||
// Custom Hooks use
|
||||
useOnClickOutside(containerRef, () => {
|
||||
const container = containerRef.current;
|
||||
useOnClickOutside(calendarContainerRef, () => {
|
||||
const container = calendarContainerRef.current;
|
||||
if (container) {
|
||||
hideDatepicker();
|
||||
}
|
||||
|
|
@ -341,59 +342,76 @@ const Datepicker: React.FC<DatepickerType> = ({
|
|||
: defaultContainerClassName;
|
||||
}, [containerClassName]);
|
||||
|
||||
const toaster = document.querySelector(".prasi-toaster");
|
||||
const rect = inputRef.current?.getBoundingClientRect();
|
||||
return (
|
||||
<DatepickerContext.Provider value={contextValues}>
|
||||
<div className={containerClassNameOverload} ref={containerRef}>
|
||||
<Input setContextRef={setInputRef} />
|
||||
|
||||
<div
|
||||
className="c-transition-all c-ease-out c-duration-300 c-absolute c-z-10 c-mt-[1px] c-text-sm 2xl:c-text-sm c-translate-y-4 c-opacity-0 c-hidden"
|
||||
ref={calendarContainerRef}
|
||||
>
|
||||
<Arrow ref={arrowRef} />
|
||||
{toaster &&
|
||||
createPortal(
|
||||
<div
|
||||
className={cx(
|
||||
"c-transition-all c-ease-out c-absolute c-z-50 c-duration-300 c-mt-[1px] c-text-sm 2xl:c-text-sm c-translate-y-4 c-hidden c-opacity-0",
|
||||
rect &&
|
||||
css`
|
||||
top: ${rect.top +
|
||||
rect.height +
|
||||
rect.height / 2}px !important;
|
||||
left: ${rect.left -
|
||||
rect.width +
|
||||
rect.width / 2}px !important;
|
||||
`
|
||||
)}
|
||||
ref={calendarContainerRef}
|
||||
>
|
||||
<Arrow ref={arrowRef} />
|
||||
|
||||
<div className=" c-mt-2.5 c-shadow-sm c-border c-border-gray-300 c-px-1 c-py-0.5 c-bg-white dark:c-bg-slate-800 dark:c-text-white dark:c-border-slate-600 c-rounded-lg">
|
||||
<div className="c-flex c-flex-col lg:c-flex-row c-py-2">
|
||||
{showShortcuts && <Shortcuts />}
|
||||
|
||||
<div
|
||||
className={`c-flex c-items-stretch c-flex-col md:c-flex-row c-space-y-4 md:c-space-y-0 md:c-space-x-1.5 ${
|
||||
showShortcuts ? "md:pl-2" : "md:c-pl-1"
|
||||
} c-pr-2 lg:c-pr-1`}
|
||||
>
|
||||
<Calendar
|
||||
date={firstDate}
|
||||
onClickPrevious={previousMonthFirst}
|
||||
onClickNext={nextMonthFirst}
|
||||
changeMonth={changeFirstMonth}
|
||||
changeYear={changeFirstYear}
|
||||
minDate={minDate}
|
||||
maxDate={maxDate}
|
||||
/>
|
||||
|
||||
{useRange && (
|
||||
<>
|
||||
<div className="c-flex c-items-center">
|
||||
<VerticalDash />
|
||||
</div>
|
||||
<div className=" c-mt-2.5 c-shadow-sm c-border c-border-gray-300 c-px-1 c-py-0.5 c-bg-white dark:c-bg-slate-800 dark:c-text-white dark:c-border-slate-600 c-rounded-lg">
|
||||
<div className="c-flex c-flex-col lg:c-flex-row c-py-2">
|
||||
{showShortcuts && <Shortcuts />}
|
||||
|
||||
<div
|
||||
className={`c-flex c-items-stretch c-flex-col md:c-flex-row c-space-y-4 md:c-space-y-0 md:c-space-x-1.5 ${
|
||||
showShortcuts ? "md:pl-2" : "md:c-pl-1"
|
||||
} c-pr-2 lg:c-pr-1`}
|
||||
>
|
||||
<Calendar
|
||||
date={secondDate}
|
||||
onClickPrevious={previousMonthSecond}
|
||||
onClickNext={nextMonthSecond}
|
||||
changeMonth={changeSecondMonth}
|
||||
changeYear={changeSecondYear}
|
||||
date={firstDate}
|
||||
onClickPrevious={previousMonthFirst}
|
||||
onClickNext={nextMonthFirst}
|
||||
changeMonth={changeFirstMonth}
|
||||
changeYear={changeFirstYear}
|
||||
minDate={minDate}
|
||||
maxDate={maxDate}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{showFooter && <Footer />}
|
||||
</div>
|
||||
</div>
|
||||
{useRange && (
|
||||
<>
|
||||
<div className="c-flex c-items-center">
|
||||
<VerticalDash />
|
||||
</div>
|
||||
|
||||
<Calendar
|
||||
date={secondDate}
|
||||
onClickPrevious={previousMonthSecond}
|
||||
onClickNext={nextMonthSecond}
|
||||
changeMonth={changeSecondMonth}
|
||||
changeYear={changeSecondYear}
|
||||
minDate={minDate}
|
||||
maxDate={maxDate}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{showFooter && <Footer />}
|
||||
</div>
|
||||
</div>,
|
||||
toaster
|
||||
)}
|
||||
</div>
|
||||
</DatepickerContext.Provider>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ const Input: React.FC<Props> = (e: Props) => {
|
|||
primaryColor as keyof (typeof RING_COLOR)["second-focus"]
|
||||
];
|
||||
|
||||
const defaultInputClassName = `c-relative c-transition-all c-duration-300 c-pl-2 c-pr-14 c-w-full c-border-gray-300 dark:c-bg-slate-800 dark:c-text-white/80 dark:c-border-slate-600 c-rounded-lg c-tracking-wide c-font-light c-text-sm c-placeholder-gray-400 c-bg-white c-outline-none focus:c-ring-0 disabled:c-opacity-40 disabled:c-cursor-not-allowed ${border} ${ring}`;
|
||||
const defaultInputClassName = `c-relative c-transition-all c-duration-300 c-pl-2 c-pr-14 c-w-full c-border-gray-300 dark:c-bg-slate-800 dark:c-text-white/80 dark:c-border-slate-600 c-rounded-lg c-tracking-wide c-font-light c-text-sm c-placeholder-gray-400 c-bg-transparent c-outline-none focus:c-ring-0 disabled:c-opacity-40 disabled:c-cursor-not-allowed ${border} ${ring}`;
|
||||
|
||||
return typeof inputClassName === "function"
|
||||
? inputClassName(defaultInputClassName)
|
||||
|
|
|
|||
|
|
@ -14,39 +14,39 @@ export function classNames(...classes: (false | null | undefined | string)[]) {
|
|||
export function getTextColorByPrimaryColor(color: string) {
|
||||
switch (color) {
|
||||
case "blue":
|
||||
return "text-blue-500";
|
||||
return "c-text-blue-500";
|
||||
case "orange":
|
||||
return "text-orange-500";
|
||||
return "c-text-orange-500";
|
||||
case "yellow":
|
||||
return "text-yellow-500";
|
||||
return "c-text-yellow-500";
|
||||
case "red":
|
||||
return "text-red-500";
|
||||
return "c-text-red-500";
|
||||
case "purple":
|
||||
return "text-purple-500";
|
||||
return "c-text-purple-500";
|
||||
case "amber":
|
||||
return "text-amber-500";
|
||||
return "c-text-amber-500";
|
||||
case "lime":
|
||||
return "text-lime-500";
|
||||
return "c-text-lime-500";
|
||||
case "green":
|
||||
return "text-green-500";
|
||||
return "c-text-green-500";
|
||||
case "emerald":
|
||||
return "text-emerald-500";
|
||||
return "c-text-emerald-500";
|
||||
case "teal":
|
||||
return "text-teal-500";
|
||||
return "c-text-teal-500";
|
||||
case "cyan":
|
||||
return "text-cyan-500";
|
||||
return "c-text-cyan-500";
|
||||
case "sky":
|
||||
return "text-sky-500";
|
||||
return "c-text-sky-500";
|
||||
case "indigo":
|
||||
return "text-indigo-500";
|
||||
return "c-text-indigo-500";
|
||||
case "violet":
|
||||
return "text-violet-500";
|
||||
return "c-text-violet-500";
|
||||
case "fuchsia":
|
||||
return "text-fuchsia-500";
|
||||
return "c-text-fuchsia-500";
|
||||
case "pink":
|
||||
return "text-pink-500";
|
||||
return "c-text-pink-500";
|
||||
case "rose":
|
||||
return "text-rose-500";
|
||||
return "c-text-rose-500";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
export const generateFilter = (
|
||||
data: any,
|
||||
item: PrasiItem,
|
||||
commit: boolean
|
||||
) => {};
|
||||
|
|
@ -9,6 +9,7 @@ export type BaseFormProps<T> = {
|
|||
on_submit?: (form: BaseFormLocal<T>) => Promise<any> | any;
|
||||
children: ReactNode | ((form: BaseFormLocal<T>) => ReactNode);
|
||||
render?: () => void;
|
||||
is_form?: boolean;
|
||||
};
|
||||
export const BaseForm = <T extends Record<string, any>>(
|
||||
props: BaseFormProps<T>
|
||||
|
|
@ -101,7 +102,29 @@ export const BaseForm = <T extends Record<string, any>>(
|
|||
if (form.status === "init") {
|
||||
form.status = "ready";
|
||||
}
|
||||
|
||||
if (typeof props.is_form === "boolean") {
|
||||
if (!props.is_form) {
|
||||
return (
|
||||
<div
|
||||
className={cx(
|
||||
"form c-flex-1 c-flex-col c-w-full c-h-full c-relative c-overflow-auto c-contents",
|
||||
className
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className={cx(
|
||||
"form-inner c-flex-1 c-flex-wrap c-items-start c-content-start c-absolute c-inset-0 c-contents",
|
||||
css`
|
||||
padding-right: 10px;
|
||||
`
|
||||
)}
|
||||
>
|
||||
{typeof children === "function" ? children(form) : children}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
return (
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
|
|
|
|||
|
|
@ -1,13 +1,17 @@
|
|||
import { useLocal } from "@/utils/use-local";
|
||||
import { FC, useEffect } from "react";
|
||||
import { FieldProp } from "../typings";
|
||||
import { useField } from "../utils/use-field";
|
||||
import { validate } from "../utils/validate";
|
||||
import { FieldInput } from "./FieldInput";
|
||||
import { Label } from "./Label";
|
||||
import { useLocal } from "@/utils/use-local";
|
||||
|
||||
export const Field: FC<FieldProp> = (arg) => {
|
||||
const showlabel = arg.show_label || "y";
|
||||
|
||||
let type: any = typeof arg.type === "function" ? arg.type() : arg.type; // tipe field
|
||||
let sub_type: any = arg.sub_type; // tipe field
|
||||
|
||||
const { fm } = arg;
|
||||
const field = useField(arg);
|
||||
const name = field.name;
|
||||
|
|
@ -27,6 +31,46 @@ export const Field: FC<FieldProp> = (arg) => {
|
|||
const errors = fm.error.get(name);
|
||||
const props = { ...arg.props };
|
||||
delete props.className;
|
||||
if (type === "-" || !type || sub_type === "-" || !sub_type) {
|
||||
return (
|
||||
<>
|
||||
<div className="c-p-4">
|
||||
⚠️ Field {arg.label} is not ready
|
||||
<br />
|
||||
<div
|
||||
className={css`
|
||||
font-size: 12px;
|
||||
font-weight: normal;
|
||||
`}
|
||||
>
|
||||
{arg.msg_error}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
if (
|
||||
(type === "multi-option" && sub_type === "-") ||
|
||||
(type === "multi-option" && sub_type === "table-edit" && (!arg.gen_table || arg.gen_table === ""))
|
||||
) {
|
||||
return (
|
||||
<>
|
||||
<div className="c-p-4">
|
||||
⚠️ Table Edit {arg.label} is not ready
|
||||
<br />
|
||||
<div
|
||||
className={css`
|
||||
font-size: 12px;
|
||||
font-weight: normal;
|
||||
`}
|
||||
>
|
||||
{arg.msg_error}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<label
|
||||
className={cx(
|
||||
|
|
@ -35,8 +79,8 @@ export const Field: FC<FieldProp> = (arg) => {
|
|||
css`
|
||||
padding: 5px 0px 0px 10px;
|
||||
`,
|
||||
|
||||
w === "auto" && fm.size.field === "full" && "c-w-full",
|
||||
w === "auto" && fm.size.field === "half" && "c-w-1/2",
|
||||
w === "full" && "c-w-full",
|
||||
w === "¾" && "c-w-3/4",
|
||||
w === "½" && "c-w-1/2",
|
||||
|
|
@ -47,8 +91,9 @@ export const Field: FC<FieldProp> = (arg) => {
|
|||
)}
|
||||
{...props}
|
||||
>
|
||||
|
||||
{mode !== "hidden" && showlabel === "y" && <Label field={field} fm={fm} />}
|
||||
{mode !== "hidden" && showlabel === "y" && (
|
||||
<Label field={field} fm={fm} />
|
||||
)}
|
||||
<div className="field-inner c-flex c-flex-1 c-flex-col">
|
||||
<FieldInput
|
||||
field={field}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
import get from "lodash.get";
|
||||
import { FC, isValidElement } from "react";
|
||||
import { FieldLoading } from "../../ui/field-loading";
|
||||
import { FMLocal, FieldLocal, FieldProp } from "../typings";
|
||||
import { TableEdit } from "./table-edit/TableEdit";
|
||||
import { FieldTypeInput, PropTypeInput } from "./type/TypeInput";
|
||||
import { MultiOption } from "./type/TypeMultiOption";
|
||||
import { SingleOption } from "./type/TypeSingleOption";
|
||||
|
|
@ -16,20 +18,20 @@ export const FieldInput: FC<{
|
|||
child: any;
|
||||
_item: PrasiItem;
|
||||
arg: FieldProp;
|
||||
}> = ({ field, fm, arg }) => {
|
||||
}> = ({ field, fm, arg, _item, PassProp, child}) => {
|
||||
// return <></>
|
||||
const prefix =
|
||||
typeof field.prefix === "function"
|
||||
? field.prefix()
|
||||
: typeof field.prefix === "string"
|
||||
? field.prefix
|
||||
: null;
|
||||
? field.prefix
|
||||
: null;
|
||||
const suffix =
|
||||
typeof field.suffix === "function"
|
||||
? field.suffix()
|
||||
: typeof field.suffix === "string"
|
||||
? field.prefix
|
||||
: null;
|
||||
? field.prefix
|
||||
: null;
|
||||
const name = field.name;
|
||||
const errors = fm.error.get(name);
|
||||
let type_field: any = typeof arg.type === "function" ? arg.type() : arg.type; // tipe field
|
||||
|
|
@ -46,8 +48,29 @@ export const FieldInput: FC<{
|
|||
}
|
||||
}
|
||||
}
|
||||
if(type_field === "multi-option" && arg.sub_type === "table-edit"){
|
||||
return <>{arg.child}</>
|
||||
if (type_field === "multi-option" && arg.sub_type === "table-edit") {
|
||||
const childsTableEdit = get(
|
||||
_item,
|
||||
"edit.props.child.value.childs"
|
||||
) as unknown as Array<PrasiItem>;
|
||||
const tableEdit = {
|
||||
child: get(_item, "edit.props.child.value") as PrasiItem,
|
||||
bottom: childsTableEdit.find((e) => e.name === "bottom") as PrasiItem,
|
||||
};
|
||||
return (
|
||||
<TableEdit
|
||||
on_init={() => {
|
||||
return fm;
|
||||
}}
|
||||
name={arg.name}
|
||||
child={child}
|
||||
PassProp={PassProp}
|
||||
item={_item}
|
||||
bottom={tableEdit.bottom}
|
||||
body={tableEdit.child}
|
||||
/>
|
||||
);
|
||||
return <>{arg.child}</>;
|
||||
}
|
||||
return (
|
||||
<div
|
||||
|
|
@ -60,13 +83,12 @@ export const FieldInput: FC<{
|
|||
border-color: transparent;
|
||||
`
|
||||
: field.disabled
|
||||
? "c-border-gray-100"
|
||||
: errors.length > 0
|
||||
? field.focused
|
||||
? "c-border-red-600 c-bg-red-50 c-outline c-outline-red-700"
|
||||
: "c-border-red-600 c-bg-red-50"
|
||||
: field.focused &&
|
||||
"c-border-blue-700 c-outline c-outline-blue-700",
|
||||
? "c-border-gray-100"
|
||||
: errors.length > 0
|
||||
? field.focused
|
||||
? "c-border-red-600 c-bg-red-50 c-outline c-outline-red-700"
|
||||
: "c-border-red-600 c-bg-red-50"
|
||||
: field.focused && "c-border-blue-700 c-outline c-outline-blue-700",
|
||||
css`
|
||||
& > .field-inner {
|
||||
min-height: 35px;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { FC, MouseEvent } from "react";
|
||||
import { FMLocal } from "../../typings";
|
||||
import { useLocal } from "lib/utils/use-local";
|
||||
import { BaseForm } from "../../base/BaseForm";
|
||||
import { TableList } from "lib/comps/list/TableList";
|
||||
import { useLocal } from "lib/utils/use-local";
|
||||
import { FC } from "react";
|
||||
import { BaseForm } from "../../base/BaseForm";
|
||||
import { FMLocal } from "../../typings";
|
||||
import get from "lodash.get";
|
||||
|
||||
export const TableEdit: FC<{
|
||||
|
|
@ -15,20 +15,40 @@ export const TableEdit: FC<{
|
|||
body: any;
|
||||
}> = ({ on_init, name, child, PassProp, item, bottom, body }) => {
|
||||
const fm = on_init();
|
||||
const local = useLocal({}, () => {
|
||||
//
|
||||
});
|
||||
const value = fm.data[name] || [];
|
||||
const local = useLocal(
|
||||
{
|
||||
tbl: null as any,
|
||||
},
|
||||
() => {}
|
||||
);
|
||||
const value = isEditor ? [{}] :Array.isArray(fm.data[name]) ? fm.data[name] : [];
|
||||
return (
|
||||
<>
|
||||
<div className="c-w-full c-h-full c-flex c-flex-col">
|
||||
<div className="c-h-[250px] c-w-full">
|
||||
<div
|
||||
className={cx(
|
||||
"c-h-[50px] c-w-full",
|
||||
css`
|
||||
> .rdg {
|
||||
overflow-y: hidden !important;
|
||||
}
|
||||
`
|
||||
)}
|
||||
style={{
|
||||
height: isEditor
|
||||
? 100
|
||||
: value.length === 0
|
||||
? 50
|
||||
: value.length * 50 + 50,
|
||||
}}
|
||||
>
|
||||
<TableList
|
||||
rowHeight={50}
|
||||
feature={["checkbox"]}
|
||||
feature={[]}
|
||||
child={child}
|
||||
PassProp={PassProp}
|
||||
name={""}
|
||||
value={value}
|
||||
on_init={() => {}}
|
||||
mode={"table"}
|
||||
_item={item}
|
||||
|
|
@ -38,24 +58,12 @@ export const TableEdit: FC<{
|
|||
return false;
|
||||
}}
|
||||
filter_name={""}
|
||||
on_load={async (arg: {
|
||||
reload: () => Promise<void>;
|
||||
orderBy?:
|
||||
| Record<
|
||||
string,
|
||||
"desc" | "asc" | Record<string, "desc" | "asc">
|
||||
>
|
||||
| undefined;
|
||||
paging: { take: number; skip: number };
|
||||
mode: "count" | "query";
|
||||
}) => {
|
||||
return value;
|
||||
}}
|
||||
render_col={(arg: any) => {
|
||||
const { props, tbl, child } = arg;
|
||||
const fm_row = { ...fm };
|
||||
fm_row.data = props.row;
|
||||
fm_row.render = fm.render;
|
||||
local.tbl = tbl;
|
||||
return (
|
||||
<PassProp
|
||||
idx={props.rowIdx}
|
||||
|
|
@ -69,8 +77,6 @@ export const TableEdit: FC<{
|
|||
fm={fm_row}
|
||||
ext_fm={{
|
||||
remove: () => {
|
||||
console.log(fm.data)
|
||||
console.log(props.row)
|
||||
if (Array.isArray(fm.data[name])) {
|
||||
fm.data[name] = value.filter(
|
||||
(e: any) => e !== props.row
|
||||
|
|
@ -78,7 +84,6 @@ export const TableEdit: FC<{
|
|||
fm.render();
|
||||
tbl.data = fm.data[name];
|
||||
tbl.render();
|
||||
console.log(fm.data)
|
||||
}
|
||||
},
|
||||
add: () => {
|
||||
|
|
@ -98,6 +103,7 @@ export const TableEdit: FC<{
|
|||
return (
|
||||
<div className="c-contents">
|
||||
<BaseForm
|
||||
is_form={false}
|
||||
data={data}
|
||||
on_submit={(form) => {}}
|
||||
render={fm.render}
|
||||
|
|
@ -111,8 +117,59 @@ export const TableEdit: FC<{
|
|||
}}
|
||||
/>
|
||||
</div>
|
||||
{bottom}
|
||||
<PassProp
|
||||
ext_fm={{
|
||||
add: () => {
|
||||
if (Array.isArray(value)) {
|
||||
value.push({});
|
||||
fm.data[name] = value;
|
||||
fm.render();
|
||||
} else {
|
||||
fm.data[name] = [{}];
|
||||
fm.render();
|
||||
}
|
||||
},
|
||||
}}
|
||||
>
|
||||
{bottom}
|
||||
</PassProp>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const Footer = (
|
||||
fm: FMLocal,
|
||||
name: string,
|
||||
PassProp: any,
|
||||
child: any,
|
||||
value: Array<any>
|
||||
) => {
|
||||
return (
|
||||
<>
|
||||
{/* <div>
|
||||
<PassProp
|
||||
ext_fm={{
|
||||
remove: () => {
|
||||
if (Array.isArray(fm.data[name])) {
|
||||
fm.data[name] = value.filter(
|
||||
(e: any) => e !== props.row
|
||||
);
|
||||
fm.render();
|
||||
tbl.data = fm.data[name];
|
||||
tbl.render();
|
||||
console.log(fm.data)
|
||||
}
|
||||
},
|
||||
add: () => {
|
||||
if (Array.isArray(value)) {
|
||||
value.push({});
|
||||
} else {
|
||||
alert("value bukan array");
|
||||
}
|
||||
},
|
||||
}}></PassProp>
|
||||
</div> */}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -13,12 +13,15 @@ export const TypeDropdown: FC<{
|
|||
loaded: false,
|
||||
options: [],
|
||||
});
|
||||
let value = typeof arg.opt_get_value === "function" ? arg.opt_get_value({
|
||||
fm,
|
||||
name: field.name,
|
||||
options: local.options,
|
||||
type: field.type,
|
||||
}) : fm.data[field.name];;
|
||||
let value =
|
||||
typeof arg.opt_get_value === "function"
|
||||
? arg.opt_get_value({
|
||||
fm,
|
||||
name: field.name,
|
||||
options: local.options,
|
||||
type: field.type,
|
||||
})
|
||||
: fm.data[field.name];
|
||||
useEffect(() => {
|
||||
if (typeof arg.on_load === "function") {
|
||||
const options = arg.on_load({});
|
||||
|
|
@ -48,29 +51,31 @@ export const TypeDropdown: FC<{
|
|||
if (!local.loaded) return <FieldLoading />;
|
||||
if (field.type === "single-option")
|
||||
return (
|
||||
<Typeahead
|
||||
value={value}
|
||||
onSelect={({ search, item }) => {
|
||||
if (item) {
|
||||
arg.opt_set_value({
|
||||
fm,
|
||||
name: field.name,
|
||||
type: field.type,
|
||||
options: local.options,
|
||||
selected: [item.value],
|
||||
});
|
||||
}
|
||||
return item?.value || search;
|
||||
}}
|
||||
allowNew={false}
|
||||
autoPopupWidth={true}
|
||||
focusOpen={true}
|
||||
mode={"single"}
|
||||
placeholder={arg.placeholder}
|
||||
options={() => {
|
||||
return local.options;
|
||||
}}
|
||||
/>
|
||||
<>
|
||||
<Typeahead
|
||||
value={value}
|
||||
onSelect={({ search, item }) => {
|
||||
if (item) {
|
||||
arg.opt_set_value({
|
||||
fm,
|
||||
name: field.name,
|
||||
type: field.type,
|
||||
options: local.options,
|
||||
selected: [item.value],
|
||||
});
|
||||
}
|
||||
return item?.value || search;
|
||||
}}
|
||||
allowNew={false}
|
||||
autoPopupWidth={true}
|
||||
focusOpen={true}
|
||||
mode={"single"}
|
||||
placeholder={arg.placeholder}
|
||||
options={() => {
|
||||
return local.options;
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
||||
return (
|
||||
|
|
@ -80,6 +85,7 @@ export const TypeDropdown: FC<{
|
|||
onSelect={({ search, item }) => {
|
||||
return item?.value || search;
|
||||
}}
|
||||
note="dropdown"
|
||||
onChange={(values) => {
|
||||
arg.opt_set_value({
|
||||
fm,
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ export const FieldTypeInput: FC<{
|
|||
</>
|
||||
) : type_field === "money" ? (
|
||||
<>
|
||||
<FieldMoney field={field} fm={fm} prop={prop} />
|
||||
<FieldMoney field={field} fm={fm} prop={prop} arg={arg} />
|
||||
</>
|
||||
) : type_field === "rich-text" ? (
|
||||
<>
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
import { useLocal } from "@/utils/use-local";
|
||||
import { FC } from "react";
|
||||
import { FMLocal, FieldLocal } from "../../typings";
|
||||
import { FMLocal, FieldLocal, FieldProp } from "../../typings";
|
||||
import { PropTypeInput } from "./TypeInput";
|
||||
export const FieldMoney: FC<{
|
||||
field: FieldLocal;
|
||||
fm: FMLocal;
|
||||
prop: PropTypeInput;
|
||||
}> = ({ field, fm, prop }) => {
|
||||
arg: FieldProp;
|
||||
}> = ({ field, fm, prop, arg }) => {
|
||||
let type_field = prop.sub_type;
|
||||
let value: any = fm.data[field.name];
|
||||
const input = useLocal({
|
||||
|
|
@ -15,13 +16,14 @@ export const FieldMoney: FC<{
|
|||
ref: null as any,
|
||||
});
|
||||
let display: any = null;
|
||||
// console.log({ prop });
|
||||
const money = formatMoney(Number(value) || 0)
|
||||
return (
|
||||
<div className="c-flex-grow c-flex-row c-flex c-w-full c-h-full">
|
||||
<div
|
||||
className={cx(
|
||||
input.display ? "c-hidden" : "",
|
||||
"c-flex-grow c-px-2 c-flex c-flex-row c-items-center"
|
||||
"c-flex-grow c-px-2 c-flex c-flex-row c-items-center",
|
||||
money === "0" ? "c-text-gray-400" : ""
|
||||
)}
|
||||
onClick={() => {
|
||||
if (input.ref) {
|
||||
|
|
@ -31,7 +33,7 @@ export const FieldMoney: FC<{
|
|||
}
|
||||
}}
|
||||
>
|
||||
{formatMoney(Number(value) || 0)}
|
||||
{money === "0" ? arg.placeholder : money}
|
||||
</div>
|
||||
<input
|
||||
ref={(el) => (input.ref = el)}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { get_value } from "./get-value";
|
|||
import { set_value } from "./set-value";
|
||||
import get from "lodash.get";
|
||||
import { gen_rel_many } from "./gen-rel-many";
|
||||
import { genTableEdit } from "./gen-table-edit";
|
||||
export type GFCol = {
|
||||
name: string;
|
||||
type: string;
|
||||
|
|
@ -23,8 +24,10 @@ export type GFCol = {
|
|||
};
|
||||
export const newField = (
|
||||
arg: GFCol,
|
||||
opt: { parent_table: string; value: Array<string> }
|
||||
opt: { parent_table: string; value: Array<string> },
|
||||
show_label: boolean
|
||||
) => {
|
||||
let show = typeof show_label === "boolean" ? show_label : true;
|
||||
let type = "input";
|
||||
if (["int", "string", "text"].includes(arg.type)) {
|
||||
if (["int"].includes(arg.type)) {
|
||||
|
|
@ -32,6 +35,7 @@ export const newField = (
|
|||
component: {
|
||||
id: "32550d01-42a3-4b15-a04a-2c2d5c3c8e67",
|
||||
props: {
|
||||
ext__show_label: show ? "y" : "n",
|
||||
name: arg.name,
|
||||
label: formatName(arg.name),
|
||||
type,
|
||||
|
|
@ -51,6 +55,7 @@ export const newField = (
|
|||
label: formatName(arg.name),
|
||||
type,
|
||||
sub_type: "text",
|
||||
ext__show_label: show ? "y" : "n",
|
||||
child: {
|
||||
childs: [],
|
||||
},
|
||||
|
|
@ -58,7 +63,20 @@ export const newField = (
|
|||
},
|
||||
});
|
||||
}
|
||||
} else if (["timestamptz", "date"].includes(arg.type) && arg.relation) {
|
||||
} else if (["boolean"].includes(arg.type)) {
|
||||
return createItem({
|
||||
component: {
|
||||
id: "32550d01-42a3-4b15-a04a-2c2d5c3c8e67",
|
||||
props: {
|
||||
name: arg.name,
|
||||
label: formatName(arg.name),
|
||||
ext__show_label: show ? "y" : "n",
|
||||
type: "single-option",
|
||||
sub_type: "toogle",
|
||||
},
|
||||
},
|
||||
});
|
||||
} else if (["timestamptz", "date"].includes(arg.type)) {
|
||||
return createItem({
|
||||
component: {
|
||||
id: "32550d01-42a3-4b15-a04a-2c2d5c3c8e67",
|
||||
|
|
@ -66,6 +84,7 @@ export const newField = (
|
|||
name: arg.name,
|
||||
label: formatName(arg.name),
|
||||
type: "date",
|
||||
ext__show_label: show ? "y" : "n",
|
||||
sub_type: "datetime",
|
||||
child: {
|
||||
childs: [],
|
||||
|
|
@ -90,6 +109,7 @@ export const newField = (
|
|||
name: arg.name,
|
||||
label: formatName(arg.name),
|
||||
type: "single-option",
|
||||
ext__show_label: show ? "y" : "n",
|
||||
sub_type: "dropdown",
|
||||
rel__gen_table: arg.name,
|
||||
opt__on_load: [load],
|
||||
|
|
@ -121,27 +141,53 @@ export const newField = (
|
|||
},
|
||||
});
|
||||
} else {
|
||||
const result = gen_rel_many({table_parent: opt.parent_table, arg, rel: fields })
|
||||
console.log({result})
|
||||
return createItem({
|
||||
component: {
|
||||
id: "32550d01-42a3-4b15-a04a-2c2d5c3c8e67",
|
||||
props: {
|
||||
name: arg.name,
|
||||
label: formatName(arg.name),
|
||||
type: "multi-option",
|
||||
sub_type: "checkbox",
|
||||
rel__gen_table: arg.name,
|
||||
opt__on_load: [result.on_load],
|
||||
opt__label: [result.get_label],
|
||||
opt__get_value: [result.get_value],
|
||||
opt__set_value: [result.set_value],
|
||||
child: {
|
||||
childs: [],
|
||||
const result = gen_rel_many({
|
||||
table_parent: opt.parent_table,
|
||||
arg,
|
||||
rel: fields,
|
||||
});
|
||||
if (result.on_load) {
|
||||
return createItem({
|
||||
component: {
|
||||
id: "32550d01-42a3-4b15-a04a-2c2d5c3c8e67",
|
||||
props: {
|
||||
name: arg.name,
|
||||
label: formatName(arg.name),
|
||||
type: "multi-option",
|
||||
sub_type: "checkbox",
|
||||
rel__gen_table: arg.name,
|
||||
opt__on_load: [result.on_load],
|
||||
ext__show_label: show ? "y" : "n",
|
||||
opt__label: [result.get_label],
|
||||
opt__get_value: [result.get_value],
|
||||
opt__set_value: [result.set_value],
|
||||
child: {
|
||||
childs: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
} else {
|
||||
return createItem({
|
||||
component: {
|
||||
id: "32550d01-42a3-4b15-a04a-2c2d5c3c8e67",
|
||||
props: {
|
||||
name: arg.name,
|
||||
ext__show_label: show ? "y" : "n",
|
||||
label: formatName(arg.name),
|
||||
type: "-",
|
||||
ext__width: "full",
|
||||
sub_type: "-",
|
||||
msg_error: `\
|
||||
Select type (multi-option) and sub type (table-edit) ➡️ select table(${arg.name}) and fields ➡️ Click generate
|
||||
`,
|
||||
child: {
|
||||
childs: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// type not found,
|
||||
|
|
@ -150,6 +196,7 @@ export const newField = (
|
|||
id: "32550d01-42a3-4b15-a04a-2c2d5c3c8e67",
|
||||
props: {
|
||||
name: arg.name,
|
||||
ext__show_label: show ? "y" : "n",
|
||||
label: formatName(arg.name),
|
||||
type,
|
||||
sub_type: "text",
|
||||
|
|
|
|||
|
|
@ -46,7 +46,9 @@ export const generateForm = async (
|
|||
try {
|
||||
|
||||
const data = { ...form }; // data form
|
||||
const data_rel = ${JSON.stringify(rel_many)} // list relasi has many
|
||||
const data_rel = ${JSON.stringify(
|
||||
rel_many
|
||||
)} // list relasi has many
|
||||
const data_master = {} as Record<string, any> | any; // variabel untuk data master
|
||||
const data_array = [] as Array<{
|
||||
table: string;
|
||||
|
|
@ -135,42 +137,177 @@ export const generateForm = async (
|
|||
};
|
||||
|
||||
type IForm = { form: any; error: Record<string, string> }
|
||||
`
|
||||
`,
|
||||
};
|
||||
}
|
||||
const childs = [];
|
||||
console.log({fields})
|
||||
for (const item of fields.filter((e) => !e.is_pk)) {
|
||||
let value = [] as Array<string>;
|
||||
if (["has-one", "has-many"].includes(item.type)) {
|
||||
value = get(item, "value.checked") as any;
|
||||
}
|
||||
const field = newField(item, { parent_table: table, value });
|
||||
const field = newField(item, { parent_table: table, value }, true);
|
||||
childs.push(field);
|
||||
}
|
||||
childs.push(
|
||||
createItem({
|
||||
name: "btn-wrapper",
|
||||
layout: { dir: "row", align: "top-left", gap: 0, wrap: "flex-nowrap" },
|
||||
padding: { l: 10, b: 10, t: 10, r: 10 },
|
||||
childs: [
|
||||
createItem({
|
||||
component: {
|
||||
id: "a15d152d-0118-408f-89f1-f6b2dfbd2e05",
|
||||
props: {
|
||||
on_click: [
|
||||
`\
|
||||
() => {
|
||||
fm.submit();
|
||||
}
|
||||
`,
|
||||
],
|
||||
childs.push({
|
||||
id: createId(),
|
||||
dim: { h: "fit", w: "full", hUnit: "px", wUnit: "px" },
|
||||
name: "submit",
|
||||
type: "item",
|
||||
childs: [
|
||||
{
|
||||
id: createId(),
|
||||
dim: { h: "fit", w: "full", hUnit: "px", wUnit: "px" },
|
||||
name: "bottom",
|
||||
type: "item",
|
||||
childs: [
|
||||
{
|
||||
id: createId(),
|
||||
adv: {
|
||||
js: '<Button\n {...props}\n onClick={(e) => {\n console.log(isEditor);\n if (!isEditor) on_click(e);\n }}\n variant={variant !== "primary" ? variant : undefined}\n size={size !== "default" ? size : undefined}\n>\n {label}\n</Button>',
|
||||
css: "& {\n display: flex;\n box-shadow: rgba(50, 50, 93, 0.25) 0px 2px 5px -1px, rgba(0, 0, 0, 0.3) 0px 1px 3px -1px;\n\n &:hover {\n cursor: pointer;\n\n\n\n\n\n // &.mobile {}\n // &.desktop {}\n // &:hover {}\n }\n}",
|
||||
jsBuilt:
|
||||
'render(/* @__PURE__ */ React.createElement(\n Button,\n {\n ...props,\n onClick: (e) => {\n console.log(isEditor);\n if (!isEditor)\n on_click(e);\n },\n variant: variant !== "primary" ? variant : void 0,\n size: size !== "default" ? size : void 0\n },\n label\n));\n',
|
||||
},
|
||||
dim: { h: "full", w: "full" },
|
||||
name: "button",
|
||||
type: "item",
|
||||
childs: [],
|
||||
mobile: { linktag: {} },
|
||||
script: {
|
||||
props: {
|
||||
size: { value: ' "default";\n' },
|
||||
variant: { value: ' "primary";\n' },
|
||||
on_click: {
|
||||
value:
|
||||
" (e) => {\n e.preventDefault();\n e.stopPropagation();\n fm.submit();\n};\n",
|
||||
},
|
||||
},
|
||||
},
|
||||
component: {
|
||||
id: "a15d152d-0118-408f-89f1-f6b2dfbd2e05",
|
||||
props: {
|
||||
size: {
|
||||
idx: 5,
|
||||
meta: {
|
||||
type: "option",
|
||||
options: '["default", "sm", "lg", "icon","nosize"]',
|
||||
optionsBuilt:
|
||||
' ["default", "sm", "lg", "icon", "nosize"];\n',
|
||||
},
|
||||
name: "prop_5",
|
||||
type: "string",
|
||||
value: '"default"',
|
||||
valueBuilt: ' "default";\n',
|
||||
},
|
||||
label: {
|
||||
idx: 1,
|
||||
meta: { type: "content-element" },
|
||||
name: "prop_1",
|
||||
type: "string",
|
||||
value: '"hello"',
|
||||
content: {
|
||||
id: createId(),
|
||||
adv: {
|
||||
js: '<div {...props} className={cx(props.className, "")}>\n {children}\n</div>',
|
||||
css: "",
|
||||
jsBuilt:
|
||||
'render(/* @__PURE__ */ React.createElement("div", { ...props, className: cx(props.className, "") }, children));\n',
|
||||
},
|
||||
dim: { h: "full", w: "full" },
|
||||
name: "label",
|
||||
type: "item",
|
||||
childs: [
|
||||
{
|
||||
id: createId(),
|
||||
name: "Wrapped",
|
||||
type: "item",
|
||||
childs: [
|
||||
{
|
||||
id: createId(),
|
||||
adv: {
|
||||
js: '<div {...props} className={cx(props.className, "")}>\n <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24"><g fill="none" stroke="currentColor" stroke-width="2"><path d="M16 21v-2c0-1.886 0-2.828-.586-3.414C14.828 15 13.886 15 12 15h-1c-1.886 0-2.828 0-3.414.586C7 16.172 7 17.114 7 19v2" /><path stroke-linecap="round" d="M7 8h5" /><path d="M3 9c0-2.828 0-4.243.879-5.121C4.757 3 6.172 3 9 3h7.172c.408 0 .613 0 .796.076c.184.076.329.22.618.51l2.828 2.828c.29.29.434.434.51.618c.076.183.076.388.076.796V15c0 2.828 0 4.243-.879 5.121C19.243 21 17.828 21 15 21H9c-2.828 0-4.243 0-5.121-.879C3 19.243 3 17.828 3 15z" /></g></svg>\n</div>',
|
||||
css: "",
|
||||
jsBuilt:
|
||||
'render(/* @__PURE__ */ React.createElement("div", { ...props, className: cx(props.className, "") }, /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", viewBox: "0 0 24 24" }, /* @__PURE__ */ React.createElement("g", { fill: "none", stroke: "currentColor", "stroke-width": "2" }, /* @__PURE__ */ React.createElement("path", { d: "M16 21v-2c0-1.886 0-2.828-.586-3.414C14.828 15 13.886 15 12 15h-1c-1.886 0-2.828 0-3.414.586C7 16.172 7 17.114 7 19v2" }), /* @__PURE__ */ React.createElement("path", { "stroke-linecap": "round", d: "M7 8h5" }), /* @__PURE__ */ React.createElement("path", { d: "M3 9c0-2.828 0-4.243.879-5.121C4.757 3 6.172 3 9 3h7.172c.408 0 .613 0 .796.076c.184.076.329.22.618.51l2.828 2.828c.29.29.434.434.51.618c.076.183.076.388.076.796V15c0 2.828 0 4.243-.879 5.121C19.243 21 17.828 21 15 21H9c-2.828 0-4.243 0-5.121-.879C3 19.243 3 17.828 3 15z" })))));\n',
|
||||
},
|
||||
dim: { h: "full", w: "full" },
|
||||
html: "aadd",
|
||||
name: "new_text",
|
||||
text: "",
|
||||
type: "text",
|
||||
layout: { dir: "col", gap: 0, align: "center" },
|
||||
script: {},
|
||||
},
|
||||
{
|
||||
id: createId(),
|
||||
adv: {
|
||||
js: '<div {...props} className={cx(props.className, "")}>\n Save\n</div>',
|
||||
css: "",
|
||||
jsBuilt:
|
||||
'render(/* @__PURE__ */ React.createElement("div", { ...props, className: cx(props.className, "") }, "Save"));\n',
|
||||
},
|
||||
dim: { h: "full", w: "full" },
|
||||
name: "new_item",
|
||||
type: "item",
|
||||
childs: [],
|
||||
script: {},
|
||||
},
|
||||
],
|
||||
layout: {
|
||||
dir: "row",
|
||||
gap: 10,
|
||||
wrap: "flex-nowrap",
|
||||
align: "top-left",
|
||||
},
|
||||
},
|
||||
],
|
||||
hidden: false,
|
||||
layout: {
|
||||
dir: "col",
|
||||
gap: 0,
|
||||
wrap: "flex-nowrap",
|
||||
align: "center",
|
||||
},
|
||||
script: {},
|
||||
},
|
||||
valueBuilt: '"hello"',
|
||||
},
|
||||
variant: {
|
||||
idx: 3,
|
||||
meta: {
|
||||
type: "option",
|
||||
options:
|
||||
'["primary", "secondary", "outline", "ghost", "link", "destructive"]',
|
||||
option_mode: "button",
|
||||
optionsBuilt:
|
||||
' ["primary", "secondary", "outline", "ghost", "link", "destructive"];\n',
|
||||
},
|
||||
name: "prop_3",
|
||||
type: "string",
|
||||
value: '"primary"',
|
||||
valueBuilt: ' "primary";\n',
|
||||
},
|
||||
on_click: {
|
||||
idx: 1,
|
||||
meta: { type: "text" },
|
||||
name: "prop_1",
|
||||
type: "string",
|
||||
value:
|
||||
"(e) => {\n e.preventDefault();\n e.stopPropagation();\n fm.submit();\n}",
|
||||
valueBuilt:
|
||||
" (e) => {\n e.preventDefault();\n e.stopPropagation();\n fm.submit();\n};\n",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
],
|
||||
})
|
||||
);
|
||||
// console.log({ childs });
|
||||
],
|
||||
layout: { dir: "col", gap: 0, wrap: "flex-nowrap", align: "center" },
|
||||
},
|
||||
],
|
||||
padding: { b: 10, l: 10, r: 10, t: 10 },
|
||||
});
|
||||
if (commit) {
|
||||
Object.keys(result).map((e) => {
|
||||
item.edit.setProp(e, result[e]);
|
||||
|
|
@ -184,12 +321,12 @@ export const generateForm = async (
|
|||
});
|
||||
await item.edit.commit();
|
||||
} else {
|
||||
console.log({data})
|
||||
console.log({ data });
|
||||
set(data, "body.value.childs", childs);
|
||||
Object.keys(result).map((e) => {
|
||||
set(data, e, result[e]);
|
||||
});
|
||||
return
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
import { generateSelect } from "lib/comps/md/gen/md-select";
|
||||
import { get_rel_many } from "./get_rel_many";
|
||||
import { parseGenField } from "lib/gen/utils";
|
||||
|
||||
export const genRelForm = (rel: any) => {
|
||||
const raw_fields = JSON.parse(rel) as (
|
||||
| string
|
||||
| { value: string; checked: string[] }
|
||||
)[];
|
||||
const fields = parseGenField(raw_fields);
|
||||
const res = generateSelect(fields);
|
||||
const rel_many = get_rel_many(fields);
|
||||
}
|
||||
|
|
@ -8,21 +8,153 @@ export const gen_rel_many = (prop: {
|
|||
rel: any;
|
||||
}) => {
|
||||
const { table_parent, arg, rel } = prop;
|
||||
console.log({ rel });
|
||||
const parent = rel.find((e: any) => e.name === table_parent);
|
||||
const master = rel.find(
|
||||
(e: any) => e.name !== table_parent && e.type === "has-one"
|
||||
);
|
||||
const result = {} as Record<string, any>;
|
||||
// select master
|
||||
const select = generateSelect(master.relation.fields);
|
||||
result.on_load = on_load_rel({
|
||||
pk: select.pk,
|
||||
table: master.name,
|
||||
select: select.select,
|
||||
pks: {},
|
||||
});
|
||||
const pk_master = master.relation.fields.find((e: any) => get(e, "is_pk"))
|
||||
const get_value = `\
|
||||
if (master) {
|
||||
const select = generateSelect(master.relation.fields);
|
||||
result.on_load = on_load_rel({
|
||||
pk: select.pk,
|
||||
table: master.name,
|
||||
select: select.select,
|
||||
pks: {},
|
||||
});
|
||||
const pk_master = master.relation.fields.find((e: any) => get(e, "is_pk"));
|
||||
const get_value = `\
|
||||
(arg: {
|
||||
options: { label: string; value: string; item?: string }[];
|
||||
fm: FMLocal;
|
||||
name: string;
|
||||
type: string;
|
||||
}) => {
|
||||
const { options, fm, name, type } = arg;
|
||||
if (isEditor) {
|
||||
return fm.data[name];
|
||||
}
|
||||
let result = null;
|
||||
result = fm.data[name];
|
||||
switch (type) {
|
||||
case "single-option":
|
||||
try {
|
||||
const data = fm.data[name];
|
||||
if (typeof data === "object") {
|
||||
if (typeof data?.connect?.id === "string") {
|
||||
result = data.connect.id;
|
||||
}else if (typeof data?.id === "string") {
|
||||
result = data.id;
|
||||
}
|
||||
}
|
||||
} catch (ex) { }
|
||||
break;
|
||||
case "multi-option":
|
||||
const selected = [];
|
||||
const data = fm.data[name];
|
||||
if (Array.isArray(data) && data.length) {
|
||||
data.map((e) => {
|
||||
try {
|
||||
if (typeof e === "object") {
|
||||
if (typeof e["${master.name}"].connect?.${pk_master.name} === "string") {
|
||||
selected.push(e["${master.name}"].connect.${pk_master.name});
|
||||
} else if (typeof e["${master.name}"]?.${pk_master.name} === "string") {
|
||||
selected.push(e["${master.name}"].${pk_master.name});
|
||||
}
|
||||
}
|
||||
} catch (ex) { }
|
||||
})
|
||||
}
|
||||
return selected;
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
`;
|
||||
const set_value = `\
|
||||
(arg: {
|
||||
selected: any[];
|
||||
options: { label: string; value: string; item?: string }[];
|
||||
fm: FMLocal;
|
||||
name: string;
|
||||
type: string;
|
||||
}) => {
|
||||
const { selected, options, fm, name, type } = arg;
|
||||
switch (type) {
|
||||
case "single-option":
|
||||
fm.data[name] = {
|
||||
connect: {
|
||||
id: selected[0],
|
||||
},
|
||||
};
|
||||
break;
|
||||
case "multi-option":
|
||||
let parent = {} as any;
|
||||
try {
|
||||
parent = {
|
||||
${arg.relation.from.table}: {
|
||||
connect: {
|
||||
${arg.relation.from.fields[0]}: fm.data.id || null,
|
||||
},
|
||||
},
|
||||
};
|
||||
} catch (e) {}
|
||||
fm.data[name] = selected.map((e) => {
|
||||
return {
|
||||
${master.name}: {
|
||||
connect: {
|
||||
id: e,
|
||||
},
|
||||
},
|
||||
...parent,
|
||||
};
|
||||
});
|
||||
break;
|
||||
default:
|
||||
fm.data[name] = selected.map((e) => e);
|
||||
}
|
||||
fm.render();
|
||||
}
|
||||
`;
|
||||
const cols = [];
|
||||
for (const [k, v] of Object.entries(select.select) as any) {
|
||||
if (k !== select.pk && typeof v !== "object") {
|
||||
cols.push(k);
|
||||
}
|
||||
}
|
||||
const get_label = `\
|
||||
(row: { value: string; label: string; item?: any }) => {
|
||||
const cols = ${JSON.stringify(cols)};
|
||||
|
||||
if (isEditor) {
|
||||
return row.label;
|
||||
}
|
||||
const result = [];
|
||||
if (!!row.item && !Array.isArray(row.item)) {
|
||||
cols.map((e) => {
|
||||
if (row.item[e]) {
|
||||
result.push(row.item[e]);
|
||||
}
|
||||
});
|
||||
return result.join(" - ");
|
||||
}
|
||||
return row.label;
|
||||
}
|
||||
`;
|
||||
|
||||
result.get_label = get_label;
|
||||
result.get_value = get_value;
|
||||
result.set_value = set_value;
|
||||
} else {
|
||||
console.log("tidak punya master");
|
||||
|
||||
result.get_label = `\
|
||||
(row: { value: string; label: string; item?: any }) => {
|
||||
return row.label;
|
||||
}
|
||||
`;
|
||||
result.get_value = `\
|
||||
(arg: {
|
||||
options: { label: string; value: string; item?: string }[];
|
||||
fm: FMLocal;
|
||||
|
|
@ -48,29 +180,11 @@ export const gen_rel_many = (prop: {
|
|||
}
|
||||
} catch (ex) { }
|
||||
break;
|
||||
case "multi-option":
|
||||
const selected = [];
|
||||
const data = fm.data[name];
|
||||
if (Array.isArray(data) && data.length) {
|
||||
data.map((e) => {
|
||||
try {
|
||||
if (typeof e === "object") {
|
||||
if (typeof e["${master.name}"].connect?.${pk_master.name} === "string") {
|
||||
selected.push(e["${master.name}"].connect.${pk_master.name});
|
||||
} else if (typeof e["${master.name}"]?.${pk_master.name} === "string") {
|
||||
selected.push(e["${master.name}"].${pk_master.name});
|
||||
}
|
||||
}
|
||||
} catch (ex) { }
|
||||
})
|
||||
}
|
||||
return selected;
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
`
|
||||
const set_value = `\
|
||||
`;
|
||||
result.set_value = `\
|
||||
(arg: {
|
||||
selected: any[];
|
||||
options: { label: string; value: string; item?: string }[];
|
||||
|
|
@ -78,70 +192,10 @@ export const gen_rel_many = (prop: {
|
|||
name: string;
|
||||
type: string;
|
||||
}) => {
|
||||
const { selected, options, fm, name, type } = arg;
|
||||
switch (type) {
|
||||
case "single-option":
|
||||
fm.data[name] = {
|
||||
connect: {
|
||||
id: selected[0],
|
||||
},
|
||||
};
|
||||
break;
|
||||
case "multi-option":
|
||||
let parent = {} as any;
|
||||
try {
|
||||
parent = {
|
||||
${arg.relation.from.table}: {
|
||||
connect: {
|
||||
${arg.relation.from.fields[0]}: fm.data.id || null,
|
||||
},
|
||||
},
|
||||
};
|
||||
} catch (e) {}
|
||||
fm.data[name] = selected.map((e) => {
|
||||
return {
|
||||
${master.name}: {
|
||||
connect: {
|
||||
id: e,
|
||||
},
|
||||
},
|
||||
...parent,
|
||||
};
|
||||
});
|
||||
break;
|
||||
default:
|
||||
fm.data[name] = selected.map((e) => e);
|
||||
}
|
||||
|
||||
fm.render();
|
||||
}
|
||||
`
|
||||
const cols = [];
|
||||
for (const [k, v] of Object.entries(select.select) as any) {
|
||||
if (k !== select.pk && typeof v !== "object") {
|
||||
cols.push(k);
|
||||
}
|
||||
`;
|
||||
}
|
||||
const get_label = `\
|
||||
(row: { value: string; label: string; item?: any }) => {
|
||||
const cols = ${JSON.stringify(cols)};
|
||||
|
||||
if (isEditor) {
|
||||
return row.label;
|
||||
}
|
||||
const result = [];
|
||||
if (!!row.item && !Array.isArray(row.item)) {
|
||||
cols.map((e) => {
|
||||
if (row.item[e]) {
|
||||
result.push(row.item[e]);
|
||||
}
|
||||
});
|
||||
return result.join(" - ");
|
||||
}
|
||||
return row.label;
|
||||
}
|
||||
`
|
||||
result.get_label = get_label;
|
||||
result.get_value = get_value;
|
||||
result.set_value = set_value;
|
||||
return result;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,10 +1,46 @@
|
|||
export const generateRelation = (
|
||||
import { createItem } from "lib/gen/utils";
|
||||
import { genTableEdit } from "./gen-table-edit";
|
||||
import { createId } from "@paralleldrive/cuid2";
|
||||
|
||||
export const generateRelation = async (
|
||||
data: {
|
||||
rel__gen_table: any;
|
||||
rel__gen_field: any;
|
||||
rel__gen_fields: any;
|
||||
sub_type: any;
|
||||
},
|
||||
item: PrasiItem,
|
||||
commit: boolean
|
||||
) => {
|
||||
console.log(data, item, commit);
|
||||
let sub_type = getValueProp(data.sub_type.value);
|
||||
if (sub_type === "table-edit") {
|
||||
const result = (await genTableEdit(
|
||||
item,
|
||||
{
|
||||
gen__table: data.rel__gen_table,
|
||||
gen__fields: data.rel__gen_fields,
|
||||
},
|
||||
false
|
||||
)) as any;
|
||||
item.edit.setProp("child", {
|
||||
mode: "jsx",
|
||||
value: {
|
||||
id: createId(),
|
||||
name: "item",
|
||||
type: "item",
|
||||
edit: null as any,
|
||||
childs: result,
|
||||
},
|
||||
});
|
||||
await item.edit.commit();
|
||||
}
|
||||
};
|
||||
|
||||
const getValueProp = (data: any) => {
|
||||
let table = "" as string;
|
||||
try {
|
||||
table = eval(data);
|
||||
} catch (e) {
|
||||
table = data;
|
||||
}
|
||||
return table;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,506 @@
|
|||
import { generateSelect } from "lib/comps/md/gen/md-select";
|
||||
import { createItem, parseGenField } from "lib/gen/utils";
|
||||
import get from "lodash.get";
|
||||
import { formatName, newField } from "./fields";
|
||||
import { set } from "lib/utils/set";
|
||||
import { createId } from "@paralleldrive/cuid2";
|
||||
|
||||
export const genTableEdit = async (
|
||||
item: PrasiItem,
|
||||
data: any,
|
||||
commit: boolean
|
||||
) => {
|
||||
let table = "" as string;
|
||||
try {
|
||||
table = eval(data.gen__table.value);
|
||||
} catch (e) {
|
||||
table = data.gen__table.value;
|
||||
}
|
||||
const raw_fields = JSON.parse(data.gen__fields.value) as (
|
||||
| string
|
||||
| { value: string; checked: string[] }
|
||||
)[];
|
||||
let pk = "";
|
||||
let pks: Record<string, string> = {};
|
||||
const fields = parseGenField(raw_fields);
|
||||
const res = generateSelect(fields);
|
||||
pk = res.pk;
|
||||
const select = res.select as any;
|
||||
const result: Record<string, PropVal> = {};
|
||||
if (!pk) {
|
||||
alert("Failed to generate! Primary Key not found. ");
|
||||
return;
|
||||
}
|
||||
const childs = [] as Array<any>;
|
||||
let first = true;
|
||||
fields
|
||||
.map((e, idx) => {
|
||||
if (e.is_pk) return;
|
||||
let value = [] as Array<string>;
|
||||
if (["has-one", "has-many"].includes(e.type)) {
|
||||
value = get(e, "value.checked") as any;
|
||||
}
|
||||
const field = newField(e, { parent_table: table, value }, false);
|
||||
let tree_depth = "";
|
||||
let tree_depth_built = "";
|
||||
if (first) {
|
||||
tree_depth = `tree_depth={col.depth}`;
|
||||
tree_depth_built = `tree_depth:col.depth`;
|
||||
first = false;
|
||||
}
|
||||
childs.push({
|
||||
component: {
|
||||
id: "297023a4-d552-464a-971d-f40dcd940b77",
|
||||
props: {
|
||||
name: e.name,
|
||||
title: formatName(e.name),
|
||||
child: createItem({
|
||||
childs: [field],
|
||||
}),
|
||||
},
|
||||
},
|
||||
});
|
||||
})
|
||||
.filter((e) => e) as any;
|
||||
childs.push({
|
||||
component: {
|
||||
id: "297023a4-d552-464a-971d-f40dcd940b77",
|
||||
props: {
|
||||
name: "option",
|
||||
title: "option",
|
||||
child: {
|
||||
id: createId(),
|
||||
name: "option",
|
||||
type: "item",
|
||||
childs: [
|
||||
{
|
||||
id: createId(),
|
||||
adv: { css: "" },
|
||||
dim: { h: "fit", w: "fit" },
|
||||
name: "info",
|
||||
type: "item",
|
||||
childs: [
|
||||
{
|
||||
id: createId(),
|
||||
adv: {
|
||||
js: '<Button\n {...props}\n onClick={(e) => {\n console.log(isEditor);\n if (!isEditor) on_click(e);\n }}\n variant={variant !== "primary" ? variant : undefined}\n size={size !== "default" ? size : undefined}\n>\n {label}\n</Button>',
|
||||
css: "& {\n display: flex;\n box-shadow: rgba(50, 50, 93, 0.25) 0px 2px 5px -1px, rgba(0, 0, 0, 0.3) 0px 1px 3px -1px;\n\n &:hover {\n cursor: pointer;\n\n\n\n\n\n // &.mobile {}\n // &.desktop {}\n // &:hover {}\n }\n}",
|
||||
jsBuilt:
|
||||
'render(/* @__PURE__ */ React.createElement(\n Button,\n {\n ...props,\n onClick: (e) => {\n console.log(isEditor);\n if (!isEditor)\n on_click(e);\n },\n variant: variant !== "primary" ? variant : void 0,\n size: size !== "default" ? size : void 0\n },\n label\n));\n',
|
||||
},
|
||||
dim: { h: "full", w: "full" },
|
||||
name: "button",
|
||||
type: "item",
|
||||
childs: [],
|
||||
mobile: { linktag: {} },
|
||||
script: {},
|
||||
component: {
|
||||
id: "a15d152d-0118-408f-89f1-f6b2dfbd2e05",
|
||||
props: {
|
||||
size: {
|
||||
type: "string",
|
||||
value: '"default"',
|
||||
valueBuilt: ' "default";\n',
|
||||
},
|
||||
label: {
|
||||
idx: 1,
|
||||
meta: { type: "content-element" },
|
||||
name: "prop_1",
|
||||
type: "string",
|
||||
value: '"hello"',
|
||||
content: {
|
||||
id: createId(),
|
||||
adv: {
|
||||
js: '<div {...props} className={cx(props.className, "")}>\n {children}\n</div>',
|
||||
css: "",
|
||||
jsBuilt:
|
||||
'render(/* @__PURE__ */ React.createElement("div", { ...props, className: cx(props.className, "") }, children));\n',
|
||||
},
|
||||
dim: { h: "full", w: "full" },
|
||||
name: "label",
|
||||
type: "item",
|
||||
childs: [
|
||||
{
|
||||
id: createId(),
|
||||
adv: {
|
||||
js: '<div {...props} className={cx(props.className, "")}>\n <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 16 16"><path fill="currentColor" d="m8.93 6.588l-2.29.287l-.082.38l.45.083c.294.07.352.176.288.469l-.738 3.468c-.194.897.105 1.319.808 1.319c.545 0 1.178-.252 1.465-.598l.088-.416c-.2.176-.492.246-.686.246c-.275 0-.375-.193-.304-.533zM9 4.5a1 1 0 1 1-2 0a1 1 0 0 1 2 0"/></svg>\n</div>',
|
||||
css: "",
|
||||
jsBuilt:
|
||||
'render(/* @__PURE__ */ React.createElement("div", { ...props, className: cx(props.className, "") }, /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", viewBox: "0 0 16 16" }, /* @__PURE__ */ React.createElement("path", { fill: "currentColor", d: "m8.93 6.588l-2.29.287l-.082.38l.45.083c.294.07.352.176.288.469l-.738 3.468c-.194.897.105 1.319.808 1.319c.545 0 1.178-.252 1.465-.598l.088-.416c-.2.176-.492.246-.686.246c-.275 0-.375-.193-.304-.533zM9 4.5a1 1 0 1 1-2 0a1 1 0 0 1 2 0" }))));\n',
|
||||
},
|
||||
dim: { h: "full", w: "full" },
|
||||
html: "submit",
|
||||
name: "new_text",
|
||||
text: "",
|
||||
type: "text",
|
||||
layout: { dir: "col", gap: 0, align: "center" },
|
||||
script: {},
|
||||
},
|
||||
],
|
||||
hidden: false,
|
||||
script: {},
|
||||
},
|
||||
valueBuilt: '"hello"',
|
||||
},
|
||||
variant: {
|
||||
idx: 3,
|
||||
meta: {
|
||||
type: "option",
|
||||
options:
|
||||
'["primary", "secondary", "outline", "ghost", "link", "destructive"]',
|
||||
option_mode: "button",
|
||||
optionsBuilt:
|
||||
' ["primary", "secondary", "outline", "ghost", "link", "destructive"];\n',
|
||||
},
|
||||
name: "prop_3",
|
||||
type: "string",
|
||||
value: '"outline"',
|
||||
valueBuilt: '"outline"',
|
||||
},
|
||||
on_click: {
|
||||
idx: 1,
|
||||
meta: { type: "text" },
|
||||
name: "prop_1",
|
||||
type: "string",
|
||||
value:
|
||||
"(e) => {\n e.preventDefault();\n e.stopPropagation();\n}",
|
||||
valueBuilt:
|
||||
" (e) => {\n e.preventDefault();\n e.stopPropagation();\n};\n",
|
||||
},
|
||||
},
|
||||
ref_ids: {},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: createId(),
|
||||
adv: { css: "" },
|
||||
dim: { h: "fit", w: "fit" },
|
||||
name: "remove",
|
||||
type: "item",
|
||||
childs: [
|
||||
{
|
||||
id: createId(),
|
||||
adv: {
|
||||
js: '<Button\n {...props}\n onClick={(e) => {\n console.log(isEditor);\n if (!isEditor) on_click(e);\n }}\n variant={variant !== "primary" ? variant : undefined}\n size={size !== "default" ? size : undefined}\n>\n {label}\n</Button>',
|
||||
css: "& {\n display: flex;\n box-shadow: rgba(50, 50, 93, 0.25) 0px 2px 5px -1px, rgba(0, 0, 0, 0.3) 0px 1px 3px -1px;\n\n &:hover {\n cursor: pointer;\n\n\n\n\n\n // &.mobile {}\n // &.desktop {}\n // &:hover {}\n }\n}",
|
||||
jsBuilt:
|
||||
'render(/* @__PURE__ */ React.createElement(\n Button,\n {\n ...props,\n onClick: (e) => {\n console.log(isEditor);\n if (!isEditor)\n on_click(e);\n },\n variant: variant !== "primary" ? variant : void 0,\n size: size !== "default" ? size : void 0\n },\n label\n));\n',
|
||||
},
|
||||
dim: { h: "full", w: "full" },
|
||||
name: "button",
|
||||
type: "item",
|
||||
mobile: { linktag: {} },
|
||||
script: {},
|
||||
component: {
|
||||
id: "a15d152d-0118-408f-89f1-f6b2dfbd2e05",
|
||||
props: {
|
||||
size: {
|
||||
idx: 5,
|
||||
meta: {
|
||||
type: "option",
|
||||
options: '["default", "sm", "lg", "icon","nosize"]',
|
||||
optionsBuilt:
|
||||
' ["default", "sm", "lg", "icon", "nosize"];\n',
|
||||
},
|
||||
name: "prop_5",
|
||||
type: "string",
|
||||
value: '"default"',
|
||||
valueBuilt: ' "default";\n',
|
||||
},
|
||||
label: {
|
||||
idx: 1,
|
||||
meta: { type: "content-element" },
|
||||
name: "prop_1",
|
||||
type: "string",
|
||||
value: '"hello"',
|
||||
content: {
|
||||
id: createId(),
|
||||
adv: {
|
||||
js: '<div {...props} className={cx(props.className, "")}>\n {children}\n</div>',
|
||||
css: "",
|
||||
jsBuilt:
|
||||
'render(/* @__PURE__ */ React.createElement("div", { ...props, className: cx(props.className, "") }, children));\n',
|
||||
},
|
||||
dim: { h: "full", w: "full" },
|
||||
name: "label",
|
||||
type: "item",
|
||||
childs: [
|
||||
{
|
||||
id: createId(),
|
||||
adv: {
|
||||
js: '<div {...props} className={cx(props.className, "")}>\n <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 512 512"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32" d="m112 112l20 320c.95 18.49 14.4 32 32 32h184c17.67 0 30.87-13.51 32-32l20-320" /><path fill="currentColor" stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="32" d="M80 112h352" /><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32" d="M192 112V72h0a23.93 23.93 0 0 1 24-24h80a23.93 23.93 0 0 1 24 24h0v40m-64 64v224m-72-224l8 224m136-224l-8 224" /></svg>\n</div>',
|
||||
css: "",
|
||||
jsBuilt:
|
||||
'render(/* @__PURE__ */ React.createElement("div", { ...props, className: cx(props.className, "") }, /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", viewBox: "0 0 512 512" }, /* @__PURE__ */ React.createElement("path", { fill: "none", stroke: "currentColor", "stroke-linecap": "round", "stroke-linejoin": "round", "stroke-width": "32", d: "m112 112l20 320c.95 18.49 14.4 32 32 32h184c17.67 0 30.87-13.51 32-32l20-320" }), /* @__PURE__ */ React.createElement("path", { fill: "currentColor", stroke: "currentColor", "stroke-linecap": "round", "stroke-miterlimit": "10", "stroke-width": "32", d: "M80 112h352" }), /* @__PURE__ */ React.createElement("path", { fill: "none", stroke: "currentColor", "stroke-linecap": "round", "stroke-linejoin": "round", "stroke-width": "32", d: "M192 112V72h0a23.93 23.93 0 0 1 24-24h80a23.93 23.93 0 0 1 24 24h0v40m-64 64v224m-72-224l8 224m136-224l-8 224" }))));\n',
|
||||
},
|
||||
dim: { h: "full", w: "full" },
|
||||
html: "submit",
|
||||
name: "new_text",
|
||||
text: "",
|
||||
type: "text",
|
||||
layout: { dir: "col", gap: 0, align: "center" },
|
||||
script: {},
|
||||
},
|
||||
],
|
||||
hidden: false,
|
||||
script: {},
|
||||
},
|
||||
valueBuilt: '"hello"',
|
||||
},
|
||||
variant: {
|
||||
idx: 3,
|
||||
meta: {
|
||||
type: "option",
|
||||
options:
|
||||
'["primary", "secondary", "outline", "ghost", "link", "destructive"]',
|
||||
option_mode: "button",
|
||||
optionsBuilt:
|
||||
' ["primary", "secondary", "outline", "ghost", "link", "destructive"];\n',
|
||||
},
|
||||
name: "prop_3",
|
||||
type: "string",
|
||||
value: '"destructive"',
|
||||
valueBuilt: '"destructive"',
|
||||
},
|
||||
on_click: {
|
||||
idx: 1,
|
||||
meta: { type: "text" },
|
||||
name: "prop_1",
|
||||
type: "string",
|
||||
value:
|
||||
'(e) => {\n e.preventDefault();\n e.stopPropagation();\n if (typeof ext_fm === "object") {\n ext_fm.remove();\n }\n}',
|
||||
valueBuilt:
|
||||
' (e) => {\n e.preventDefault();\n e.stopPropagation();\n if (typeof ext_fm === "object") {\n ext_fm.remove();\n }\n};\n',
|
||||
},
|
||||
},
|
||||
ref_ids: {},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
layout: {
|
||||
dir: "row",
|
||||
gap: 10,
|
||||
wrap: "flex-nowrap",
|
||||
align: "top-left",
|
||||
},
|
||||
padding: { b: 0, l: 10, r: 10, t: 0 },
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
const child_sub_name = createItem({
|
||||
name: "tbl-col",
|
||||
childs: childs,
|
||||
});
|
||||
if (commit) {
|
||||
item.edit.setProp("bottom", {
|
||||
mode: "jsx",
|
||||
value: {
|
||||
id: createId(),
|
||||
name: "btn-submit",
|
||||
type: "item",
|
||||
edit: null as any,
|
||||
childs: [
|
||||
{
|
||||
id: createId(),
|
||||
name: "button",
|
||||
type: "item",
|
||||
component: {
|
||||
id: "a15d152d-0118-408f-89f1-f6b2dfbd2e05",
|
||||
props: {
|
||||
on_click: {
|
||||
type: "raw",
|
||||
value: `\
|
||||
(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
if (typeof fm === "object") {
|
||||
const value = fm.data[name] || [];
|
||||
if (Array.isArray(value)) {
|
||||
value.push({});
|
||||
fm.render();
|
||||
}else{
|
||||
value = [];
|
||||
fm.render();
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
},
|
||||
},
|
||||
},
|
||||
childs: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
item.edit.setProp("child", {
|
||||
mode: "jsx",
|
||||
value: {
|
||||
id: createId(),
|
||||
name: "item",
|
||||
type: "item",
|
||||
edit: null as any,
|
||||
childs: [child_sub_name],
|
||||
},
|
||||
});
|
||||
await item.edit.commit();
|
||||
} else {
|
||||
const result = [child_sub_name] || [];
|
||||
const option = {
|
||||
id: createId(),
|
||||
name: "bottom",
|
||||
type: "item",
|
||||
childs: [
|
||||
{
|
||||
id: createId(),
|
||||
name: "bottom",
|
||||
type: "item",
|
||||
childs: [
|
||||
{
|
||||
id: createId(),
|
||||
adv: {
|
||||
js: '<Button\n {...props}\n onClick={(e) => {\n console.log(isEditor);\n if (!isEditor) on_click(e);\n }}\n variant={variant !== "primary" ? variant : undefined}\n size={size !== "default" ? size : undefined}\n>\n {label}\n</Button>',
|
||||
css: "& {\n display: flex;\n box-shadow: rgba(50, 50, 93, 0.25) 0px 2px 5px -1px, rgba(0, 0, 0, 0.3) 0px 1px 3px -1px;\n\n &:hover {\n cursor: pointer;\n\n\n\n\n\n // &.mobile {}\n // &.desktop {}\n // &:hover {}\n }\n}",
|
||||
jsBuilt:
|
||||
'render(/* @__PURE__ */ React.createElement(\n Button,\n {\n ...props,\n onClick: (e) => {\n console.log(isEditor);\n if (!isEditor)\n on_click(e);\n },\n variant: variant !== "primary" ? variant : void 0,\n size: size !== "default" ? size : void 0\n },\n label\n));\n',
|
||||
},
|
||||
dim: { h: "full", w: "full" },
|
||||
name: "button",
|
||||
type: "item",
|
||||
childs: [],
|
||||
mobile: { linktag: {} },
|
||||
script: {
|
||||
props: {
|
||||
size: { value: ' "default";\n' },
|
||||
variant: { value: ' "primary";\n' },
|
||||
on_click: {
|
||||
value:
|
||||
' (e) => {\n e.preventDefault();\n e.stopPropagation();\n if (typeof ext_fm === "object") {\n console.log("masuk");\n ext_fm.add();\n }\n};\n',
|
||||
},
|
||||
},
|
||||
},
|
||||
component: {
|
||||
id: "a15d152d-0118-408f-89f1-f6b2dfbd2e05",
|
||||
props: {
|
||||
size: {
|
||||
idx: 5,
|
||||
meta: {
|
||||
type: "option",
|
||||
options: '["default", "sm", "lg", "icon","nosize"]',
|
||||
optionsBuilt:
|
||||
' ["default", "sm", "lg", "icon", "nosize"];\n',
|
||||
},
|
||||
name: "prop_5",
|
||||
type: "string",
|
||||
value: '"default"',
|
||||
valueBuilt: ' "default";\n',
|
||||
},
|
||||
label: {
|
||||
idx: 1,
|
||||
meta: { type: "content-element" },
|
||||
name: "prop_1",
|
||||
type: "string",
|
||||
value: '"hello"',
|
||||
content: {
|
||||
id: createId(),
|
||||
adv: {
|
||||
js: '<div {...props} className={cx(props.className, "")}>\n {children}\n</div>',
|
||||
css: "",
|
||||
jsBuilt:
|
||||
'render(/* @__PURE__ */ React.createElement("div", { ...props, className: cx(props.className, "") }, children));\n',
|
||||
},
|
||||
dim: { h: "full", w: "full" },
|
||||
name: "label",
|
||||
type: "item",
|
||||
childs: [
|
||||
{
|
||||
id: createId(),
|
||||
name: "Wrapped",
|
||||
type: "item",
|
||||
childs: [
|
||||
{
|
||||
id: "vxmz8pt05cm5biygbunoxk4b",
|
||||
adv: {
|
||||
js: '<div {...props} className={cx(props.className, "")}>\n <svg\n xmlns="http://www.w3.org/2000/svg"\n width="20"\n height="20"\n viewBox="0 0 24 24"\n >\n <path\n fill="currentColor"\n d="M11.883 3.007L12 3a1 1 0 0 1 .993.883L13 4v7h7a1 1 0 0 1 .993.883L21 12a1 1 0 0 1-.883.993L20 13h-7v7a1 1 0 0 1-.883.993L12 21a1 1 0 0 1-.993-.883L11 20v-7H4a1 1 0 0 1-.993-.883L3 12a1 1 0 0 1 .883-.993L4 11h7V4a1 1 0 0 1 .883-.993L12 3z"\n />\n </svg>\n</div>',
|
||||
css: "",
|
||||
jsBuilt:
|
||||
'render(/* @__PURE__ */ React.createElement("div", { ...props, className: cx(props.className, "") }, /* @__PURE__ */ React.createElement(\n "svg",\n {\n xmlns: "http://www.w3.org/2000/svg",\n width: "20",\n height: "20",\n viewBox: "0 0 24 24"\n },\n /* @__PURE__ */ React.createElement(\n "path",\n {\n fill: "currentColor",\n d: "M11.883 3.007L12 3a1 1 0 0 1 .993.883L13 4v7h7a1 1 0 0 1 .993.883L21 12a1 1 0 0 1-.883.993L20 13h-7v7a1 1 0 0 1-.883.993L12 21a1 1 0 0 1-.993-.883L11 20v-7H4a1 1 0 0 1-.993-.883L3 12a1 1 0 0 1 .883-.993L4 11h7V4a1 1 0 0 1 .883-.993L12 3z"\n }\n )\n)));\n',
|
||||
},
|
||||
dim: { h: "full", w: "full" },
|
||||
html: "aadd",
|
||||
name: "new_text",
|
||||
text: "",
|
||||
type: "text",
|
||||
layout: { dir: "col", gap: 0, align: "center" },
|
||||
script: {},
|
||||
},
|
||||
{
|
||||
id: createId(),
|
||||
adv: {
|
||||
js: '<div {...props} className={cx(props.className, "")}>\n Add\n</div>',
|
||||
css: "",
|
||||
jsBuilt:
|
||||
'render(/* @__PURE__ */ React.createElement("div", { ...props, className: cx(props.className, "") }, "Add"));\n',
|
||||
},
|
||||
dim: { h: "full", w: "full" },
|
||||
name: "new_item",
|
||||
type: "item",
|
||||
childs: [],
|
||||
script: {},
|
||||
},
|
||||
],
|
||||
layout: {
|
||||
dir: "row",
|
||||
gap: 10,
|
||||
wrap: "flex-nowrap",
|
||||
align: "top-left",
|
||||
},
|
||||
},
|
||||
],
|
||||
hidden: false,
|
||||
script: {},
|
||||
},
|
||||
valueBuilt: '"hello"',
|
||||
},
|
||||
variant: {
|
||||
idx: 3,
|
||||
meta: {
|
||||
type: "option",
|
||||
options:
|
||||
'["primary", "secondary", "outline", "ghost", "link", "destructive"]',
|
||||
option_mode: "button",
|
||||
optionsBuilt:
|
||||
' ["primary", "secondary", "outline", "ghost", "link", "destructive"];\n',
|
||||
},
|
||||
name: "prop_3",
|
||||
type: "string",
|
||||
value: '"primary"',
|
||||
valueBuilt: ' "primary";\n',
|
||||
},
|
||||
on_click: {
|
||||
idx: 1,
|
||||
meta: { type: "text" },
|
||||
name: "prop_1",
|
||||
type: "string",
|
||||
value:
|
||||
'(e) => {\n e.preventDefault();\n e.stopPropagation();\n if (typeof ext_fm === "object") {\n console.log("masuk")\n ext_fm.add();\n // const value = fm.data[name] || [];\n // if (Array.isArray(value)) {\n // value.push({});\n // fm.render();\n // } else {\n // value = [];\n // fm.render();\n // }\n }\n}',
|
||||
valueBuilt:
|
||||
' (e) => {\n e.preventDefault();\n e.stopPropagation();\n if (typeof ext_fm === "object") {\n console.log("masuk");\n ext_fm.add();\n }\n};\n',
|
||||
},
|
||||
},
|
||||
ref_ids: {},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
result.push(option);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
|
@ -86,6 +86,8 @@ export type FieldProp = {
|
|||
sub_type: string;
|
||||
placeholder: string;
|
||||
show_label: boolean;
|
||||
msg_error: string;
|
||||
gen_table: string;
|
||||
};
|
||||
|
||||
export type FMInternal = {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,494 @@
|
|||
@layer rdg {
|
||||
@layer Defaults,
|
||||
FocusSink,
|
||||
CheckboxInput,
|
||||
CheckboxIcon,
|
||||
CheckboxLabel,
|
||||
Cell,
|
||||
HeaderCell,
|
||||
SummaryCell,
|
||||
EditCell,
|
||||
Row,
|
||||
HeaderRow,
|
||||
SummaryRow,
|
||||
GroupedRow,
|
||||
Root;
|
||||
}
|
||||
|
||||
.mlln6zg7-0-0-beta-44 {
|
||||
@layer rdg.MeasuringCell {
|
||||
contain: strict;
|
||||
grid-row: 1;
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.cj343x07-0-0-beta-44 {
|
||||
@layer rdg.Cell {
|
||||
/* max-content does not work with size containment
|
||||
* dynamically switching between different containment styles incurs a heavy relayout penalty
|
||||
* Chromium bug: at odd zoom levels or subpixel positioning,
|
||||
* layout/paint/style containment can make cell borders disappear
|
||||
* https://bugs.chromium.org/p/chromium/issues/detail?id=1326946
|
||||
*/
|
||||
position: relative; /* needed for absolute positioning to work */
|
||||
padding-block: 0;
|
||||
padding-inline: 8px;
|
||||
border-inline-end: 1px solid var(--rdg-border-color);
|
||||
border-block-end: 1px solid var(--rdg-border-color);
|
||||
grid-row-start: var(--rdg-grid-row-start);
|
||||
background-color: inherit;
|
||||
|
||||
white-space: nowrap;
|
||||
overflow: clip;
|
||||
text-overflow: ellipsis;
|
||||
outline: none;
|
||||
|
||||
&[aria-selected="true"] {
|
||||
outline: 2px solid var(--rdg-selection-color);
|
||||
outline-offset: -2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.csofj7r7-0-0-beta-44 {
|
||||
@layer rdg.Cell {
|
||||
position: sticky;
|
||||
/* Should have a higher value than 0 to show up above unfrozen cells */
|
||||
z-index: 1;
|
||||
|
||||
/* Add box-shadow on the last frozen cell */
|
||||
&:nth-last-child(1 of &) {
|
||||
box-shadow: var(--rdg-cell-frozen-box-shadow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.c1bn88vv7-0-0-beta-44 {
|
||||
@layer rdg.CheckboxLabel {
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
margin-inline-end: 1px; /* align checkbox in row group cell */
|
||||
}
|
||||
}
|
||||
|
||||
.c1qt073l7-0-0-beta-44 {
|
||||
@layer rdg.CheckboxInput {
|
||||
all: unset;
|
||||
}
|
||||
}
|
||||
|
||||
.cf71kmq7-0-0-beta-44 {
|
||||
@layer rdg.CheckboxIcon {
|
||||
content: "";
|
||||
inline-size: 20px;
|
||||
block-size: 20px;
|
||||
border: 2px solid var(--rdg-border-color);
|
||||
background-color: var(--rdg-background-color);
|
||||
|
||||
.c1qt073l7-0-0-beta-44:checked + & {
|
||||
background-color: var(--rdg-checkbox-color);
|
||||
outline: 4px solid var(--rdg-background-color);
|
||||
outline-offset: -6px;
|
||||
}
|
||||
|
||||
.c1qt073l7-0-0-beta-44:focus + & {
|
||||
border-color: var(--rdg-checkbox-focus-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.c1lwve4p7-0-0-beta-44 {
|
||||
@layer rdg.CheckboxLabel {
|
||||
cursor: default;
|
||||
|
||||
.cf71kmq7-0-0-beta-44 {
|
||||
border-color: var(--rdg-checkbox-disabled-border-color);
|
||||
background-color: var(--rdg-checkbox-disabled-background-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.g1s9ylgp7-0-0-beta-44 {
|
||||
@layer rdg.GroupCellContent {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
.cz54e4y7-0-0-beta-44 {
|
||||
@layer rdg.GroupCellCaret {
|
||||
margin-inline-start: 4px;
|
||||
stroke: currentColor;
|
||||
stroke-width: 1.5px;
|
||||
fill: transparent;
|
||||
vertical-align: middle;
|
||||
|
||||
> path {
|
||||
transition: d 0.1s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.c1w9bbhr7-0-0-beta-44 {
|
||||
@layer rdg.DragHandle {
|
||||
--rdg-drag-handle-size: 8px;
|
||||
z-index: 0;
|
||||
cursor: move;
|
||||
inline-size: var(--rdg-drag-handle-size);
|
||||
block-size: var(--rdg-drag-handle-size);
|
||||
background-color: var(--rdg-selection-color);
|
||||
place-self: end;
|
||||
|
||||
&:hover {
|
||||
--rdg-drag-handle-size: 16px;
|
||||
border: 2px solid var(--rdg-selection-color);
|
||||
background-color: var(--rdg-background-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.c1creorc7-0-0-beta-44 {
|
||||
@layer rdg.DragHandle {
|
||||
z-index: 1;
|
||||
position: sticky;
|
||||
}
|
||||
}
|
||||
|
||||
.cis5rrm7-0-0-beta-44 {
|
||||
@layer rdg.EditCell {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.h44jtk67-0-0-beta-44 {
|
||||
@layer rdg.SortableHeaderCell {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.hcgkhxz7-0-0-beta-44 {
|
||||
@layer rdg.SortableHeaderCellName {
|
||||
flex-grow: 1;
|
||||
overflow: clip;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
|
||||
.c6l2wv17-0-0-beta-44 {
|
||||
@layer rdg.HeaderCell {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.c1kqdw7y7-0-0-beta-44 {
|
||||
@layer rdg.HeaderCell {
|
||||
touch-action: none;
|
||||
}
|
||||
}
|
||||
|
||||
.r1y6ywlx7-0-0-beta-44 {
|
||||
@layer rdg.HeaderCell {
|
||||
cursor: col-resize;
|
||||
position: absolute;
|
||||
inset-block-start: 0;
|
||||
inset-inline-end: 0;
|
||||
inset-block-end: 0;
|
||||
inline-size: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.c1bezg5o7-0-0-beta-44 {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.c1vc96037-0-0-beta-44 {
|
||||
background-color: var(--rdg-header-draggable-background-color);
|
||||
}
|
||||
|
||||
.r1upfr807-0-0-beta-44 {
|
||||
@layer rdg.Row {
|
||||
display: contents;
|
||||
line-height: var(--rdg-row-height);
|
||||
background-color: var(--rdg-background-color);
|
||||
|
||||
&:hover {
|
||||
background-color: var(--rdg-row-hover-background-color);
|
||||
}
|
||||
|
||||
&[aria-selected="true"] {
|
||||
background-color: var(--rdg-row-selected-background-color);
|
||||
|
||||
&:hover {
|
||||
background-color: var(--rdg-row-selected-hover-background-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.r190mhd37-0-0-beta-44 {
|
||||
@layer rdg.FocusSink {
|
||||
outline: 2px solid var(--rdg-selection-color);
|
||||
outline-offset: -2px;
|
||||
}
|
||||
}
|
||||
|
||||
.r139qu9m7-0-0-beta-44 {
|
||||
@layer rdg.FocusSink {
|
||||
&::before {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
height: 100%;
|
||||
position: sticky;
|
||||
inset-inline-start: 0;
|
||||
border-inline-start: 2px solid var(--rdg-selection-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.h10tskcx7-0-0-beta-44 {
|
||||
@layer rdg.HeaderRow {
|
||||
display: contents;
|
||||
line-height: var(--rdg-header-row-height);
|
||||
background-color: var(--rdg-header-background-color);
|
||||
font-weight: bold;
|
||||
|
||||
& > .cj343x07-0-0-beta-44 {
|
||||
/* Should have a higher value than 1 to show up above regular cells and the focus sink */
|
||||
z-index: 2;
|
||||
position: sticky;
|
||||
}
|
||||
|
||||
& > .csofj7r7-0-0-beta-44 {
|
||||
z-index: 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.c6ra8a37-0-0-beta-44 {
|
||||
@layer rdg.Cell {
|
||||
background-color: #ccccff;
|
||||
}
|
||||
}
|
||||
|
||||
.cq910m07-0-0-beta-44 {
|
||||
@layer rdg.Cell {
|
||||
background-color: #ccccff;
|
||||
|
||||
&.c6ra8a37-0-0-beta-44 {
|
||||
background-color: #9999ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.a3ejtar7-0-0-beta-44 {
|
||||
@layer rdg.SortIcon {
|
||||
fill: currentColor;
|
||||
|
||||
> path {
|
||||
transition: d 0.1s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.rnvodz57-0-0-beta-44 {
|
||||
@layer rdg.Defaults {
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
@layer rdg.Root {
|
||||
--rdg-color: #000;
|
||||
--rdg-border-color: #ddd;
|
||||
--rdg-summary-border-color: #aaa;
|
||||
--rdg-background-color: hsl(0deg 0% 100%);
|
||||
--rdg-header-background-color: hsl(0deg 0% 97.5%);
|
||||
--rdg-header-draggable-background-color: hsl(0deg 0% 90.5%);
|
||||
--rdg-row-hover-background-color: hsl(0deg 0% 96%);
|
||||
--rdg-row-selected-background-color: hsl(207deg 76% 92%);
|
||||
--rdg-row-selected-hover-background-color: hsl(207deg 76% 88%);
|
||||
--rdg-checkbox-color: hsl(207deg 100% 29%);
|
||||
--rdg-checkbox-focus-color: hsl(207deg 100% 69%);
|
||||
--rdg-checkbox-disabled-border-color: #ccc;
|
||||
--rdg-checkbox-disabled-background-color: #ddd;
|
||||
--rdg-selection-color: #66afe9;
|
||||
--rdg-font-size: 14px;
|
||||
--rdg-cell-frozen-box-shadow: calc(2px * var(--rdg-sign)) 0 5px -2px rgba(136, 136, 136, 0.3);
|
||||
|
||||
display: grid;
|
||||
|
||||
/* https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context */
|
||||
/* We set a stacking context so internal elements don't render on top of external elements. */
|
||||
/* size containment is not used as it could break "width: min-content" for example, and the grid would infinitely resize on Chromium browsers */
|
||||
contain: content;
|
||||
content-visibility: auto;
|
||||
block-size: 350px;
|
||||
border: 1px solid var(--rdg-border-color);
|
||||
box-sizing: border-box;
|
||||
overflow: auto;
|
||||
background-color: var(--rdg-background-color);
|
||||
color: var(--rdg-color);
|
||||
font-size: var(--rdg-font-size);
|
||||
|
||||
/* needed on Firefox to fix scrollbars */
|
||||
&::before {
|
||||
content: "";
|
||||
grid-column: 1/-1;
|
||||
grid-row: 1/-1;
|
||||
}
|
||||
|
||||
/* &.rdg-dark {
|
||||
--rdg-color-scheme: dark;
|
||||
--rdg-color: #ddd;
|
||||
--rdg-border-color: #444;
|
||||
--rdg-summary-border-color: #555;
|
||||
--rdg-background-color: hsl(0deg 0% 13%);
|
||||
--rdg-header-background-color: hsl(0deg 0% 10.5%);
|
||||
--rdg-header-draggable-background-color: hsl(0deg 0% 17.5%);
|
||||
--rdg-row-hover-background-color: hsl(0deg 0% 9%);
|
||||
--rdg-row-selected-background-color: hsl(207deg 76% 42%);
|
||||
--rdg-row-selected-hover-background-color: hsl(207deg 76% 38%);
|
||||
--rdg-checkbox-color: hsl(207deg 100% 79%);
|
||||
--rdg-checkbox-focus-color: hsl(207deg 100% 89%);
|
||||
--rdg-checkbox-disabled-border-color: #000;
|
||||
--rdg-checkbox-disabled-background-color: #333;
|
||||
} */
|
||||
|
||||
&.rdg-light {
|
||||
--rdg-color-scheme: light;
|
||||
}
|
||||
/*
|
||||
@media (prefers-color-scheme: dark) {
|
||||
&:not(.rdg-light) {
|
||||
--rdg-color: #ddd;
|
||||
--rdg-border-color: #444;
|
||||
--rdg-summary-border-color: #555;
|
||||
--rdg-background-color: hsl(0deg 0% 13%);
|
||||
--rdg-header-background-color: hsl(0deg 0% 10.5%);
|
||||
--rdg-header-draggable-background-color: hsl(0deg 0% 17.5%);
|
||||
--rdg-row-hover-background-color: hsl(0deg 0% 9%);
|
||||
--rdg-row-selected-background-color: hsl(207deg 76% 42%);
|
||||
--rdg-row-selected-hover-background-color: hsl(207deg 76% 38%);
|
||||
--rdg-checkbox-color: hsl(207deg 100% 79%);
|
||||
--rdg-checkbox-focus-color: hsl(207deg 100% 89%);
|
||||
--rdg-checkbox-disabled-border-color: #000;
|
||||
--rdg-checkbox-disabled-background-color: #333;
|
||||
}
|
||||
} */
|
||||
|
||||
> :nth-last-child(1 of .rdg-top-summary-row) {
|
||||
> .cj343x07-0-0-beta-44 {
|
||||
border-block-end: 2px solid var(--rdg-summary-border-color);
|
||||
}
|
||||
}
|
||||
|
||||
> :nth-child(1 of .rdg-bottom-summary-row) {
|
||||
> .cj343x07-0-0-beta-44 {
|
||||
border-block-start: 2px solid var(--rdg-summary-border-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.vlqv91k7-0-0-beta-44 {
|
||||
@layer rdg.Root {
|
||||
user-select: none;
|
||||
|
||||
& .r1upfr807-0-0-beta-44 {
|
||||
cursor: move;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.f1lsfrzw7-0-0-beta-44 {
|
||||
@layer rdg.FocusSink {
|
||||
grid-column: 1/-1;
|
||||
pointer-events: none;
|
||||
/* Should have a higher value than 1 to show up above regular frozen cells */
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.f1cte0lg7-0-0-beta-44 {
|
||||
@layer rdg.FocusSink {
|
||||
/* Should have a higher value than 3 to show up above header and summary rows */
|
||||
z-index: 3;
|
||||
}
|
||||
}
|
||||
|
||||
.s8wc6fl7-0-0-beta-44 {
|
||||
@layer rdg.SummaryCell {
|
||||
inset-block-start: var(--rdg-summary-row-top);
|
||||
inset-block-end: var(--rdg-summary-row-bottom);
|
||||
}
|
||||
}
|
||||
|
||||
.skuhp557-0-0-beta-44 {
|
||||
@layer rdg.SummaryRow {
|
||||
line-height: var(--rdg-summary-row-height);
|
||||
|
||||
> .cj343x07-0-0-beta-44 {
|
||||
position: sticky;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tf8l5ub7-0-0-beta-44 {
|
||||
@layer rdg.SummaryRow {
|
||||
> .cj343x07-0-0-beta-44 {
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
> .csofj7r7-0-0-beta-44 {
|
||||
z-index: 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.g1yxluv37-0-0-beta-44 {
|
||||
@layer rdg.GroupedRow {
|
||||
&:not([aria-selected="true"]) {
|
||||
background-color: var(--rdg-header-background-color);
|
||||
}
|
||||
|
||||
> .cj343x07-0-0-beta-44:not(:last-child, .csofj7r7-0-0-beta-44),
|
||||
> :nth-last-child(n + 2 of .csofj7r7-0-0-beta-44) {
|
||||
border-inline-end: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.t7vyx3i7-0-0-beta-44 {
|
||||
@layer rdg.TextEditor {
|
||||
appearance: none;
|
||||
|
||||
box-sizing: border-box;
|
||||
inline-size: 100%;
|
||||
block-size: 100%;
|
||||
padding-block: 0;
|
||||
padding-inline: 6px;
|
||||
border: 2px solid #ccc;
|
||||
vertical-align: top;
|
||||
color: var(--rdg-color);
|
||||
background-color: var(--rdg-background-color);
|
||||
|
||||
font-family: inherit;
|
||||
font-size: var(--rdg-font-size);
|
||||
|
||||
&:focus {
|
||||
border-color: var(--rdg-selection-color);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
&::placeholder {
|
||||
color: #999;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -11,7 +11,7 @@ import DataGrid, {
|
|||
SELECT_COLUMN_KEY,
|
||||
SortColumn,
|
||||
} from "react-data-grid";
|
||||
import "react-data-grid/lib/styles.css";
|
||||
import "./TableList.css";
|
||||
import { createPortal } from "react-dom";
|
||||
import { Toaster, toast } from "sonner";
|
||||
import { Skeleton } from "../ui/skeleton";
|
||||
|
|
@ -29,7 +29,8 @@ type TableListProp = {
|
|||
child: any;
|
||||
PassProp: any;
|
||||
name: string;
|
||||
on_load: (arg: {
|
||||
value?: any[];
|
||||
on_load?: (arg: {
|
||||
reload: () => Promise<void>;
|
||||
orderBy?: Record<string, "asc" | "desc" | Record<string, "asc" | "desc">>;
|
||||
paging: { take: number; skip: number };
|
||||
|
|
@ -47,7 +48,7 @@ type TableListProp = {
|
|||
filter_name: string;
|
||||
render_row?: (child: any, data: any) => ReactNode;
|
||||
rowHeight?: number;
|
||||
render_col?: (props: any) => ReactNode
|
||||
render_col?: (props: any) => ReactNode;
|
||||
};
|
||||
const w = window as any;
|
||||
const selectCellClassname = css`
|
||||
|
|
@ -73,7 +74,10 @@ export const TableList: FC<TableListProp> = ({
|
|||
id_parent,
|
||||
feature,
|
||||
filter_name,
|
||||
render_row,rowHeight,render_col
|
||||
render_row,
|
||||
rowHeight,
|
||||
render_col,
|
||||
value
|
||||
}) => {
|
||||
const where = get(w, `prasi_filter.${filter_name}`) ?? "hello";
|
||||
const whereQuery = filterWhere("hello");
|
||||
|
|
@ -121,50 +125,52 @@ export const TableList: FC<TableListProp> = ({
|
|||
sort: {
|
||||
columns: [] as SortColumn[],
|
||||
on_change: (cols: SortColumn[]) => {
|
||||
local.sort.columns = cols;
|
||||
local.paging.skip = 0;
|
||||
if (feature?.find((e) => e === "sorting")) {
|
||||
local.sort.columns = cols;
|
||||
local.paging.skip = 0;
|
||||
|
||||
if (cols.length > 0) {
|
||||
const { columnKey, direction } = cols[0];
|
||||
if (cols.length > 0) {
|
||||
const { columnKey, direction } = cols[0];
|
||||
|
||||
let should_set = true;
|
||||
const gf = JSON.stringify(gen_fields);
|
||||
const fields = fields_map.get(gf);
|
||||
let should_set = true;
|
||||
const gf = JSON.stringify(gen_fields);
|
||||
const fields = fields_map.get(gf);
|
||||
|
||||
if (fields) {
|
||||
const rel = fields?.find((e) => e.name === columnKey);
|
||||
if (rel && rel.checked) {
|
||||
should_set = false;
|
||||
if (fields) {
|
||||
const rel = fields?.find((e) => e.name === columnKey);
|
||||
if (rel && rel.checked) {
|
||||
should_set = false;
|
||||
|
||||
if (rel.type === "has-many") {
|
||||
local.sort.orderBy = {
|
||||
[columnKey]: {
|
||||
_count: direction === "ASC" ? "asc" : "desc",
|
||||
},
|
||||
};
|
||||
} else {
|
||||
const field = rel.checked.find((e) => !e.is_pk);
|
||||
if (field) {
|
||||
if (rel.type === "has-many") {
|
||||
local.sort.orderBy = {
|
||||
[columnKey]: {
|
||||
[field.name]: direction === "ASC" ? "asc" : "desc",
|
||||
_count: direction === "ASC" ? "asc" : "desc",
|
||||
},
|
||||
};
|
||||
} else {
|
||||
const field = rel.checked.find((e) => !e.is_pk);
|
||||
if (field) {
|
||||
local.sort.orderBy = {
|
||||
[columnKey]: {
|
||||
[field.name]: direction === "ASC" ? "asc" : "desc",
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (should_set) {
|
||||
local.sort.orderBy = {
|
||||
[columnKey]: direction === "ASC" ? "asc" : "desc",
|
||||
};
|
||||
if (should_set) {
|
||||
local.sort.orderBy = {
|
||||
[columnKey]: direction === "ASC" ? "asc" : "desc",
|
||||
};
|
||||
}
|
||||
} else {
|
||||
local.sort.orderBy = null;
|
||||
}
|
||||
} else {
|
||||
local.sort.orderBy = null;
|
||||
local.status = "reload";
|
||||
local.render();
|
||||
}
|
||||
local.status = "reload";
|
||||
local.render();
|
||||
},
|
||||
orderBy: null as null | Record<
|
||||
string,
|
||||
|
|
@ -172,6 +178,9 @@ export const TableList: FC<TableListProp> = ({
|
|||
>,
|
||||
},
|
||||
});
|
||||
if(typeof value !== "undefined"){
|
||||
local.data = value;
|
||||
}
|
||||
// code ini digunakan untuk mengambil nama dari pk yang akan digunakan sebagai key untuk id
|
||||
const pk = local.pk?.name || "id";
|
||||
useEffect(() => {
|
||||
|
|
@ -207,7 +216,6 @@ export const TableList: FC<TableListProp> = ({
|
|||
}
|
||||
})();
|
||||
}, [local.status, on_load, local.sort.orderBy]);
|
||||
|
||||
const raw_childs = get(
|
||||
child,
|
||||
"props.meta.item.component.props.child.content.childs"
|
||||
|
|
@ -233,7 +241,7 @@ export const TableList: FC<TableListProp> = ({
|
|||
|
||||
// function untuk menghandle checkbox di header (digunakan untuk check all)
|
||||
const headerCheckboxClick = (e: ChangeEvent<HTMLInputElement>) => {
|
||||
if (e.target.checked) {
|
||||
if (e.target.checked && Array.isArray(rowData)) {
|
||||
// jika checbox checked, maka semua rowData akan dimasukkan ke dalam local selected rows
|
||||
rowData.forEach((data) => {
|
||||
local.selectedRows.push({
|
||||
|
|
@ -270,7 +278,6 @@ export const TableList: FC<TableListProp> = ({
|
|||
local.render();
|
||||
}
|
||||
};
|
||||
|
||||
const mode_child = raw_childs.find(
|
||||
(e: any) => e.name === sub_name || e.name === mode
|
||||
);
|
||||
|
|
@ -288,6 +295,7 @@ export const TableList: FC<TableListProp> = ({
|
|||
try {
|
||||
if (feature?.find((e) => e === "checkbox")) isCheckbox = true;
|
||||
} catch (e) {}
|
||||
|
||||
if (childs.length && isCheckbox) {
|
||||
columns.push({
|
||||
key: SELECT_COLUMN_KEY,
|
||||
|
|
@ -341,7 +349,8 @@ export const TableList: FC<TableListProp> = ({
|
|||
resizable: true,
|
||||
sortable: true,
|
||||
renderCell(props) {
|
||||
if(typeof render_col === "function") return render_col({props,tbl: local, child})
|
||||
if (typeof render_col === "function")
|
||||
return render_col({ props, tbl: local, child });
|
||||
return (
|
||||
<PassProp
|
||||
idx={props.rowIdx}
|
||||
|
|
@ -403,22 +412,23 @@ export const TableList: FC<TableListProp> = ({
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isEditor && local.status !== "ready") {
|
||||
if (local.data.length === 0) {
|
||||
const load_args: any = {
|
||||
async reload() {},
|
||||
where,
|
||||
paging: { take: local.paging.take, skip: local.paging.skip },
|
||||
};
|
||||
|
||||
if (id_parent) load_args.paging = {};
|
||||
if (typeof on_load === "function") {
|
||||
local.data = on_load({ ...load_args, mode: "query" }) as any;
|
||||
if(typeof value === "undefined")
|
||||
if (isEditor && local.status !== "ready") {
|
||||
if (local.data.length === 0) {
|
||||
const load_args: any = {
|
||||
async reload() {},
|
||||
where,
|
||||
paging: { take: local.paging.take, skip: local.paging.skip },
|
||||
};
|
||||
|
||||
if (id_parent) load_args.paging = {};
|
||||
if (typeof on_load === "function") {
|
||||
local.data = on_load({ ...load_args, mode: "query" }) as any;
|
||||
}
|
||||
}
|
||||
local.status = "ready";
|
||||
}
|
||||
local.status = "ready";
|
||||
}
|
||||
|
||||
|
||||
let selected_idx = -1;
|
||||
|
||||
|
|
@ -426,7 +436,6 @@ export const TableList: FC<TableListProp> = ({
|
|||
if (id_parent && local.pk && local.sort.columns.length === 0) {
|
||||
data = sortTree(local.data, id_parent, local.pk.name);
|
||||
}
|
||||
// return "halo dek"
|
||||
if (mode === "table") {
|
||||
return (
|
||||
<div
|
||||
|
|
@ -446,7 +455,6 @@ export const TableList: FC<TableListProp> = ({
|
|||
}
|
||||
}}
|
||||
>
|
||||
123
|
||||
{local.status !== "ready" && (
|
||||
<div className="c-flex c-flex-col c-space-y-2 c-m-4 c-absolute c-left-0 c-top-0">
|
||||
<Skeleton className={cx("c-w-[200px] c-h-[11px]")} />
|
||||
|
|
@ -482,7 +490,7 @@ export const TableList: FC<TableListProp> = ({
|
|||
) : (
|
||||
<>
|
||||
<DataGrid
|
||||
rowHeight={rowHeight || 35}
|
||||
rowHeight={rowHeight || 35}
|
||||
sortColumns={local.sort.columns}
|
||||
onSortColumnsChange={local.sort.on_change}
|
||||
columns={columns}
|
||||
|
|
@ -530,9 +538,7 @@ export const TableList: FC<TableListProp> = ({
|
|||
|
||||
return (
|
||||
<>
|
||||
<div className="c-contents">
|
||||
{child_row}
|
||||
</div>
|
||||
<div className="c-contents">{child_row}</div>
|
||||
</>
|
||||
);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -13,10 +13,12 @@ export const generateTableList = async (
|
|||
arg: { mode: "table" | "list" | "grid" | "auto"; id_parent?: string },
|
||||
commit: boolean
|
||||
) => {
|
||||
console.log({data})
|
||||
console.log(typeof data.gen_table.value)
|
||||
const table = eval(data.gen_table.value) as string;
|
||||
console.log({table})
|
||||
let table = "" as string;
|
||||
try {
|
||||
table = eval(data.gen_table.value);
|
||||
} catch (e) {
|
||||
table = data.gen_table.value;
|
||||
}
|
||||
const raw_fields = JSON.parse(data.gen_fields.value) as (
|
||||
| string
|
||||
| { value: string; checked: string[] }
|
||||
|
|
@ -24,7 +26,6 @@ export const generateTableList = async (
|
|||
let pk = "";
|
||||
let pks: Record<string, string> = {};
|
||||
const fields = parseGenField(raw_fields);
|
||||
console.log({fields})
|
||||
// convert ke bahasa prisma untuk select
|
||||
const res = generateSelect(fields);
|
||||
pk = res.pk;
|
||||
|
|
@ -55,7 +56,6 @@ export const generateTableList = async (
|
|||
value: on_load({ pk, table, select, pks }),
|
||||
};
|
||||
}
|
||||
console.log(result.opt__on_load?.value)
|
||||
let first = true;
|
||||
const child_sub_name = createItem({
|
||||
name: sub_name,
|
||||
|
|
@ -106,16 +106,14 @@ render(React.createElement("div", Object.assign({}, props, { className: cx(props
|
|||
})
|
||||
.filter((e) => e) as any,
|
||||
});
|
||||
childs.push(child_sub_name)
|
||||
// console.log({childs})
|
||||
if (commit) {
|
||||
Object.keys(result).map((e) => {
|
||||
item.edit.setProp(e, result[e]);
|
||||
});
|
||||
item.edit.setChilds(childs);
|
||||
item.edit.setChilds([child_sub_name]);
|
||||
await item.edit.commit();
|
||||
} else {
|
||||
set(data, "child.value.childs", childs);
|
||||
set(data, "child.value.childs", [child_sub_name]);
|
||||
Object.keys(result).map((e) => {
|
||||
set(data, e, result[e]);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ export const generateMDForm = async (
|
|||
label: "List ${formatName(arg.table)}",
|
||||
onClick: () => {
|
||||
md.selected = null;
|
||||
md.tab.active = "master";
|
||||
md.internal.action_should_refresh = true;
|
||||
md.params.apply();
|
||||
md.render();
|
||||
|
|
@ -92,6 +93,14 @@ export const generateMDForm = async (
|
|||
}
|
||||
`
|
||||
})
|
||||
console.log({form: {
|
||||
type: "item",
|
||||
name: "item",
|
||||
component: {
|
||||
id: "c4e65c26-4f36-48aa-a5b3-0771feac082e",
|
||||
props,
|
||||
},
|
||||
}})
|
||||
tab_detail?.edit.setChilds([
|
||||
{
|
||||
type: "item",
|
||||
|
|
|
|||
|
|
@ -119,6 +119,14 @@ idx: any;
|
|||
}
|
||||
`
|
||||
})
|
||||
console.log({
|
||||
type: "item",
|
||||
name: "item",
|
||||
component: {
|
||||
id: "567d5362-2cc8-4ca5-a531-f771a5c866c2",
|
||||
props,
|
||||
},
|
||||
})
|
||||
tab_master?.edit.setChilds([ {
|
||||
type: "item",
|
||||
name: "item",
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ export const MDDetail: FC<{ md: MDLocal; mdr: MDRef }> = ({ md, mdr }) => {
|
|||
if (!detail) {
|
||||
return null;
|
||||
}
|
||||
console.log(md.tab.list);
|
||||
return (
|
||||
<>
|
||||
{md.props.show_head === "only-child" && <MDHeader md={md} mdr={mdr} />}
|
||||
|
|
@ -114,10 +115,11 @@ export const MDRenderTab: FC<{
|
|||
breadcrumb: () => Array<any>;
|
||||
}> = ({ child, on_init, breadcrumb }) => {
|
||||
useEffect(() => {
|
||||
|
||||
let md = on_init();
|
||||
md.breadcrumb.list = breadcrumb();
|
||||
md.breadcrumb.render();
|
||||
}, [])
|
||||
if (!isEditor) {
|
||||
md.breadcrumb.reload();
|
||||
}
|
||||
}, []);
|
||||
return <>{child}</>;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -15,7 +15,9 @@ export const MDRenderMaster: FC<{
|
|||
useEffect(() => {
|
||||
let md = on_init();
|
||||
md.breadcrumb.list = breadcrumb();
|
||||
md.breadcrumb.render();
|
||||
if(!isEditor){
|
||||
md.breadcrumb.reload();
|
||||
}
|
||||
if (md) {
|
||||
let width = 0;
|
||||
let min_width = 0;
|
||||
|
|
|
|||
|
|
@ -25,8 +25,10 @@ export const Typeahead: FC<{
|
|||
focusOpen?: boolean;
|
||||
disabled?: boolean;
|
||||
mode?: "multi" | "single";
|
||||
note?: string;
|
||||
}> = ({
|
||||
value,
|
||||
note,
|
||||
options: options_fn,
|
||||
onSelect,
|
||||
unique,
|
||||
|
|
@ -94,6 +96,9 @@ export const Typeahead: FC<{
|
|||
if (typeof value === "object" && value) {
|
||||
local.value = value;
|
||||
local.render();
|
||||
} else if (typeof value === "string") {
|
||||
local.value = [value];
|
||||
local.render();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
|
|
@ -257,6 +262,7 @@ export const Typeahead: FC<{
|
|||
search: local.search.input,
|
||||
existing: local.options,
|
||||
});
|
||||
|
||||
if (res) {
|
||||
const applyOptions = (
|
||||
result: (string | { value: string; label: string })[]
|
||||
|
|
@ -267,8 +273,10 @@ export const Typeahead: FC<{
|
|||
});
|
||||
local.render();
|
||||
};
|
||||
|
||||
if (res instanceof Promise) {
|
||||
applyOptions(await res);
|
||||
const result = await res;
|
||||
applyOptions(result);
|
||||
} else {
|
||||
applyOptions(res);
|
||||
}
|
||||
|
|
@ -385,7 +393,9 @@ export const Typeahead: FC<{
|
|||
}}
|
||||
>
|
||||
<input
|
||||
placeholder={local.mode === "multi" ? placeholder : ""}
|
||||
placeholder={
|
||||
local.mode === "multi" ? placeholder : valueLabel[0]?.label
|
||||
}
|
||||
type="text"
|
||||
ref={input}
|
||||
value={local.search.input}
|
||||
|
|
@ -482,7 +492,7 @@ export const Typeahead: FC<{
|
|||
}}
|
||||
spellCheck={false}
|
||||
className={cx(
|
||||
"c-flex-1 c-mb-2 c-text-sm c-outline-none",
|
||||
"c-flex-1 c-mb-2 c-text-sm c-outline-none c-bg-transparent",
|
||||
local.mode === "single" ? "c-cursor-pointer" : ""
|
||||
)}
|
||||
onKeyDown={keydown}
|
||||
|
|
@ -493,7 +503,7 @@ export const Typeahead: FC<{
|
|||
<div
|
||||
className={cx(
|
||||
"c-absolute c-pointer-events-none c-z-10 c-inset-0 c-left-auto c-flex c-items-center ",
|
||||
"c-bg-white c-justify-center c-w-6 c-mr-1 c-my-2",
|
||||
" c-justify-center c-w-6 c-mr-1 c-my-2 c-bg-transparent",
|
||||
disabled && "c-hidden"
|
||||
)}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { lazify } from "./utils/lazify";
|
||||
export { FieldLoading } from "./comps/ui/field-loading";
|
||||
import { lazify, lazifyMany } from "./utils/lazify";
|
||||
|
||||
/** Master - Detail - List - Form */
|
||||
export const MasterDetail = lazify(
|
||||
|
|
@ -19,16 +20,18 @@ export const Breadcrumb = lazify(
|
|||
export const TableList = lazify(
|
||||
async () => (await import("@/comps/list/TableList")).TableList
|
||||
);
|
||||
export const Form = lazify(
|
||||
async () => (await import("@/comps/form/Form")).Form
|
||||
);
|
||||
export const TableEdit = lazify(
|
||||
async () => (await import("@/comps/form/field/table-edit/TableEdit")).TableEdit
|
||||
);
|
||||
export const Field = lazify(
|
||||
async () => (await import("@/comps/form/field/Field")).Field
|
||||
async () =>
|
||||
(await import("@/comps/form/field/table-edit/TableEdit")).TableEdit
|
||||
);
|
||||
|
||||
const form = lazifyMany({
|
||||
Form: async () => (await import("@/comps/form/Form")).Form,
|
||||
Field: async () => (await import("@/comps/form/field/Field")).Field,
|
||||
});
|
||||
export const Form = form.Form;
|
||||
export const Field = form.Field;
|
||||
|
||||
/** Export - Import */
|
||||
export const ImportExcel = lazify(
|
||||
async () => (await import("@/comps/list/ImportExcel")).ImportExcel
|
||||
|
|
@ -49,7 +52,10 @@ export const FilterField = lazify(
|
|||
|
||||
/** Generator */
|
||||
export { generateMasterDetail } from "@/comps/md/gen/md-gen";
|
||||
|
||||
export { genTableEdit } from "@/comps/form/gen/gen-table-edit";
|
||||
export { generateFilter as genereteFilter } from "@/comps/filter/gen/gen-filter";
|
||||
export { generateRelation } from "@/comps/form/gen/gen-rel";
|
||||
export { parseGenField } from "@/gen/utils";
|
||||
/** ETC */
|
||||
export { filterModifier } from "@/comps/filter/utils/filter-modifier";
|
||||
export { filterWhere } from "@/comps/filter/utils/filter-where";
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
import { createId } from "@paralleldrive/cuid2";
|
||||
import { gen_relation } from "../gen_relation/gen_relation";
|
||||
import { GFCol, createItem, formatName } from "../utils";
|
||||
|
||||
export const newItem = (component: {
|
||||
id: string;
|
||||
props: Record<string, string>;
|
||||
|
|
|
|||
|
|
@ -142,6 +142,6 @@ export const createItem = (arg: SimplifiedItem): any => {
|
|||
type: "item",
|
||||
component,
|
||||
adv: arg.adv,
|
||||
childs: arg.childs?.map(createItem),
|
||||
childs: arg.childs?.map(createItem) || [],
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { FC } from "react";
|
||||
import { FC, useEffect } from "react";
|
||||
import { prasi_user } from "./utils/user";
|
||||
|
||||
const w = window as unknown as {
|
||||
|
|
@ -13,11 +13,11 @@ export type LGProps = {
|
|||
|
||||
export const Login: FC<LGProps> = (props) => {
|
||||
w.prasi_home = props.url_home[0];
|
||||
console.log("render?");
|
||||
try {
|
||||
const home = prasi_user.prasi_home[prasi_user.user.m_role.name];
|
||||
navigate(home);
|
||||
} catch (e: any) {
|
||||
}
|
||||
useEffect(() => {
|
||||
try {
|
||||
const home = prasi_user.prasi_home[prasi_user.user.m_role.name];
|
||||
navigate(home);
|
||||
} catch (e: any) {}
|
||||
}, []);
|
||||
return <>{props.body}</>;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { getPathname } from "lib/utils/pathname";
|
||||
import { FC, ReactNode, useLayoutEffect, useState } from "react";
|
||||
import { FC, ReactNode, useEffect, useLayoutEffect, useState } from "react";
|
||||
import { loadSession } from "../login/utils/load";
|
||||
|
||||
const w = window as any;
|
||||
|
|
@ -62,7 +62,9 @@ export const Layout: FC<LYTChild> = (props) => {
|
|||
fn();
|
||||
const path = getPathname();
|
||||
const no_layout = props.exception;
|
||||
loadSession("/auth/login");
|
||||
useEffect(() => {
|
||||
loadSession("/auth/login");
|
||||
}, []);
|
||||
if (Array.isArray(no_layout))
|
||||
if (no_layout.length) {
|
||||
if (no_layout.includes(path)) {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
import { FC, lazy } from "react";
|
||||
import { FC, ReactNode, Suspense, lazy } from "react";
|
||||
|
||||
export const lazify = <T extends FC<any>>(
|
||||
fn: () => Promise<T>,
|
||||
note?: string
|
||||
): T => {
|
||||
export const lazify = <T extends FC<any>>(fn: () => Promise<T>): T => {
|
||||
return lazy(async () => {
|
||||
const result = await fn();
|
||||
return {
|
||||
|
|
@ -11,3 +8,31 @@ export const lazify = <T extends FC<any>>(
|
|||
};
|
||||
}) as any;
|
||||
};
|
||||
|
||||
export const lazifyMany = <T extends Record<string, FC<any>>>(fns: {
|
||||
[K in keyof T]: () => Promise<T[K]>;
|
||||
}) => {
|
||||
const cached = {} as any;
|
||||
const result = {} as any;
|
||||
for (const [k, v] of Object.entries(fns)) {
|
||||
const fn = v as any;
|
||||
result[k] = lazy(async () => {
|
||||
if (cached[k]) return { default: cached[k] };
|
||||
|
||||
const result = await fn();
|
||||
cached[k] = result;
|
||||
|
||||
for (const [i, j] of Object.entries(fns)) {
|
||||
if (!cached[i]) {
|
||||
cached[i] = await (j as any)();
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
default: result,
|
||||
};
|
||||
}) as any;
|
||||
}
|
||||
|
||||
return result as T;
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue