wip fix filter
This commit is contained in:
parent
13bd7e3858
commit
4433f5fcd1
|
|
@ -0,0 +1,32 @@
|
||||||
|
import capitalize from "lodash.capitalize";
|
||||||
|
import { FC } from "react";
|
||||||
|
import { FilterFieldType, modifiers } from "./utils/types";
|
||||||
|
|
||||||
|
export const FieldModifier: FC<{
|
||||||
|
type: FilterFieldType;
|
||||||
|
modifier: string;
|
||||||
|
onChange: (modifier: string) => void;
|
||||||
|
}> = ({ type, modifier, onChange }) => {
|
||||||
|
if (!modifier && modifiers[type]) {
|
||||||
|
onChange(Object.keys(modifiers[type])[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<select
|
||||||
|
onChange={(e) => {
|
||||||
|
const val = e.currentTarget.value;
|
||||||
|
onChange(val);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{modifiers[type]
|
||||||
|
? Object.entries(modifiers[type]).map(([value, label]) => {
|
||||||
|
return (
|
||||||
|
<option selected={modifier === value} value={value}>
|
||||||
|
{label}
|
||||||
|
</option>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
: null}
|
||||||
|
</select>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -1,159 +0,0 @@
|
||||||
import { useLocal } from "@/utils/use-local";
|
|
||||||
import get from "lodash.get";
|
|
||||||
import { FC, ReactNode, useEffect, useRef } from "react";
|
|
||||||
import { FMLocal } from "../form/Form";
|
|
||||||
import { createPortal, render } from "react-dom";
|
|
||||||
import { Label } from "@/comps/ui/label";
|
|
||||||
import { Input } from "@/comps/ui/input";
|
|
||||||
|
|
||||||
type FilterPosition = 'regular' | 'inline' | 'popup';
|
|
||||||
|
|
||||||
type FilterForm = {
|
|
||||||
gen_fields: GenField[];
|
|
||||||
gen_table: string;
|
|
||||||
name: string;
|
|
||||||
value: any;
|
|
||||||
position: FilterPosition;
|
|
||||||
children?: ReactNode;
|
|
||||||
onClose?: () => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
type GenField = {
|
|
||||||
name: string,
|
|
||||||
is_pk: boolean,
|
|
||||||
type: string,
|
|
||||||
optional: boolean
|
|
||||||
};
|
|
||||||
|
|
||||||
export const MasterFilter: FC<FilterForm> = ({ gen_fields, gen_table, name, value, position, children, onClose }): ReactNode => {
|
|
||||||
const local = useLocal({
|
|
||||||
data: [] as any[],
|
|
||||||
columns: [] as string[],
|
|
||||||
fields: [] as GenField[],
|
|
||||||
tableName: "",
|
|
||||||
isGenerated: false,
|
|
||||||
// fm: {} as FMLocal,
|
|
||||||
argInit: {} as { fm: FMLocal; submit: any; reload: any },
|
|
||||||
argOnLoad: {} as { arg: { fm: FMLocal } },
|
|
||||||
argOnSubmit: {} as {
|
|
||||||
arg: {
|
|
||||||
fm: FMLocal;
|
|
||||||
form: any;
|
|
||||||
error: any;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
useEffect(() => {
|
|
||||||
if (!isEditor) {
|
|
||||||
const w = window as any;
|
|
||||||
if (typeof w["prasi_filter"] !== "object") w["prasi_filter"] = {};
|
|
||||||
if (typeof w["prasi_filter"][name] !== "object")
|
|
||||||
w["prasi_filter"][name] = {};
|
|
||||||
const val = value();
|
|
||||||
w["prasi_filter"][name] = {
|
|
||||||
...w["prasi_filter"][name],
|
|
||||||
...val
|
|
||||||
};
|
|
||||||
w.prasiContext.render();
|
|
||||||
}
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
const renderContent = (): ReactNode => (
|
|
||||||
<div className={`filter-content filter-${position}`}>
|
|
||||||
<h3>Filter</h3>
|
|
||||||
<form>
|
|
||||||
{local.fields.map((field) => (
|
|
||||||
<div>
|
|
||||||
{field.type === 'varchar' && (
|
|
||||||
<div className="grid w-full max-w-sm items-center gap-1.5" >
|
|
||||||
<Label htmlFor={field.name}>{field.name}</Label>
|
|
||||||
<Input id={field.name} type="text" />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{field.type === "number" && (
|
|
||||||
<div className="grid w-full max-w-sm items-center gap-1.5" >
|
|
||||||
<Label htmlFor={field.name}>{field.name}</Label>
|
|
||||||
<Input id={field.name} type="number" />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</form >
|
|
||||||
</div >
|
|
||||||
);
|
|
||||||
|
|
||||||
const generateFilter = () => {
|
|
||||||
local.isGenerated = true;
|
|
||||||
local.tableName = gen_table;
|
|
||||||
gen_fields.forEach((data: any) => {
|
|
||||||
local.fields.push(JSON.parse(data));
|
|
||||||
});
|
|
||||||
local.render();
|
|
||||||
console.log('tableName', local.tableName);
|
|
||||||
console.log('fields', local.fields);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (position === 'popup') {
|
|
||||||
let popup = document.querySelector(".main-content-preview > .portal");
|
|
||||||
if (!popup) {
|
|
||||||
popup = document.createElement("div");
|
|
||||||
popup.classList.add("portal");
|
|
||||||
|
|
||||||
const main = document.querySelector(".main-content-preview");
|
|
||||||
if (main) {
|
|
||||||
main.appendChild(popup);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{createPortal(
|
|
||||||
<div
|
|
||||||
onClick={onClose}
|
|
||||||
className={cx(
|
|
||||||
css`
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
right: 0;
|
|
||||||
left: 0;
|
|
||||||
background: white;
|
|
||||||
z-index: 100;
|
|
||||||
`,
|
|
||||||
"c-flex c-flex-col"
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{renderContent()}
|
|
||||||
</div>,
|
|
||||||
popup
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (local.isGenerated) {
|
|
||||||
return renderContent();
|
|
||||||
} else {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<button
|
|
||||||
onClick={generateFilter}
|
|
||||||
style={{
|
|
||||||
backgroundColor: "#4CAF50",
|
|
||||||
border: "none",
|
|
||||||
color: "white",
|
|
||||||
padding: "15px 32px",
|
|
||||||
textAlign: "center",
|
|
||||||
textDecoration: "none",
|
|
||||||
display: "inline-block",
|
|
||||||
fontSize: "16px",
|
|
||||||
margin: "4px 2px",
|
|
||||||
cursor: "pointer",
|
|
||||||
borderRadius: "10px",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Generate
|
|
||||||
</button>
|
|
||||||
</div >
|
|
||||||
)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
import { FC } from "react";
|
||||||
|
import { BaseForm } from "../form/base/BaseForm";
|
||||||
|
import { FilterLocal } from "./utils/types";
|
||||||
|
import { useLocal } from "lib/utils/use-local";
|
||||||
|
|
||||||
|
export const FilterContent: FC<{
|
||||||
|
mode: string;
|
||||||
|
filter: FilterLocal;
|
||||||
|
PassProp: any;
|
||||||
|
child: any;
|
||||||
|
_item: PrasiItem;
|
||||||
|
}> = ({ mode, filter, PassProp, child, _item }) => {
|
||||||
|
const internal = useLocal({});
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={cx(
|
||||||
|
`c-flex c-flex-1 filter-content filter-${mode}`,
|
||||||
|
css`
|
||||||
|
&.filter-content {
|
||||||
|
border-radius: 4px;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
&.filter-regular {
|
||||||
|
width: 100%;
|
||||||
|
/* Styles specific to sidebar */
|
||||||
|
}
|
||||||
|
|
||||||
|
&.filter-inline {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
/* Styles specific to topbar */
|
||||||
|
}
|
||||||
|
|
||||||
|
&.filter-popup {
|
||||||
|
position: fixed;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
z-index: 1000;
|
||||||
|
/* Styles specific to popup */
|
||||||
|
}
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<BaseForm
|
||||||
|
data={filter.data}
|
||||||
|
on_submit={(form) => {
|
||||||
|
console.log("skrg nyubmit");
|
||||||
|
}}
|
||||||
|
render={internal.render}
|
||||||
|
>
|
||||||
|
{(form) => {
|
||||||
|
filter.form = form;
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{!!(PassProp && child) && (
|
||||||
|
<PassProp filter={filter}>{child}</PassProp>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
</BaseForm>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
import { FC, useEffect } from "react";
|
||||||
|
import { BaseField } from "../form/base/BaseField";
|
||||||
|
import { FilterLocal, filter_window } from "./utils/types";
|
||||||
|
import { FieldTypeText } from "../form/field/type/TypeText";
|
||||||
|
import { FieldModifier } from "./FieldModifier";
|
||||||
|
import { useLocal } from "lib/utils/use-local";
|
||||||
|
|
||||||
|
export const FilterField: FC<{
|
||||||
|
filter: FilterLocal;
|
||||||
|
name?: string;
|
||||||
|
label?: string;
|
||||||
|
type: "text" | "number" | "boolean";
|
||||||
|
}> = ({ filter, name, label, type }) => {
|
||||||
|
const internal = useLocal({ render_timeout: null as any });
|
||||||
|
if (!name) return <>No Name</>;
|
||||||
|
if (!filter.form) return <div>Loading...</div>;
|
||||||
|
|
||||||
|
filter.types[name] = type;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
clearTimeout(internal.render_timeout);
|
||||||
|
internal.render_timeout = setTimeout(() => {
|
||||||
|
filter_window.prasiContext.render();
|
||||||
|
}, 500);
|
||||||
|
}, [filter.form?.data[name]]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<BaseField
|
||||||
|
{...filter.form.fieldProps({
|
||||||
|
name: name || "",
|
||||||
|
label: label || name || "",
|
||||||
|
render: internal.render,
|
||||||
|
prefix: () => (
|
||||||
|
<FieldModifier
|
||||||
|
onChange={(modifier) => {
|
||||||
|
filter.modifiers[name] = modifier;
|
||||||
|
filter.render();
|
||||||
|
filter_window.prasiContext.render();
|
||||||
|
}}
|
||||||
|
modifier={filter.modifiers[name]}
|
||||||
|
type={type}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
{(field) => (
|
||||||
|
<>
|
||||||
|
{type === "text" && (
|
||||||
|
<FieldTypeText
|
||||||
|
{...field}
|
||||||
|
prop={{
|
||||||
|
type: "text",
|
||||||
|
sub_type: "text",
|
||||||
|
prefix: "",
|
||||||
|
suffix: "",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{type === "number" && (
|
||||||
|
<FieldTypeText
|
||||||
|
{...field}
|
||||||
|
prop={{
|
||||||
|
type: "text",
|
||||||
|
sub_type: "number",
|
||||||
|
prefix: "",
|
||||||
|
suffix: "",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</BaseField>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
import { FC, ReactNode } from "react";
|
|
||||||
|
|
||||||
export const Label: FC<{ children: ReactNode; text: string }> = ({
|
|
||||||
children,
|
|
||||||
text,
|
|
||||||
}) => {
|
|
||||||
return (
|
|
||||||
<label className="field c-flex c-w-full c-flex-col c-space-y-1 c-px-2">
|
|
||||||
<div className="label c-text-sm c-flex c-items-center c-mt-3 c-capitalize">
|
|
||||||
{text}
|
|
||||||
</div>
|
|
||||||
<div className="field-inner c-flex c-flex-1 c-flex-col">
|
|
||||||
<div
|
|
||||||
className={cx(
|
|
||||||
"field-outer c-flex c-flex-1 c-flex-row c-rounded c-border c-text-sm c-flex-wrap",
|
|
||||||
css`
|
|
||||||
> * {
|
|
||||||
width: 100%;
|
|
||||||
padding: 5px;
|
|
||||||
}
|
|
||||||
`
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</label>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
@ -0,0 +1,103 @@
|
||||||
|
import { useLocal } from "@/utils/use-local";
|
||||||
|
import { FC, ReactNode, useEffect } from "react";
|
||||||
|
import { createPortal } from "react-dom";
|
||||||
|
import { GenField } from "../form/typings";
|
||||||
|
import { default_filter_local, filter_window } from "./utils/types";
|
||||||
|
import { FilterContent } from "./FilterContent";
|
||||||
|
import { getPathname } from "lib/utils/pathname";
|
||||||
|
|
||||||
|
type FilterMode = "regular" | "inline" | "popup";
|
||||||
|
|
||||||
|
type FilterProps = {
|
||||||
|
gen_fields: GenField[];
|
||||||
|
gen_table: string;
|
||||||
|
name: string;
|
||||||
|
value: any;
|
||||||
|
mode: FilterMode;
|
||||||
|
children?: ReactNode;
|
||||||
|
onClose?: () => void;
|
||||||
|
PassProp: any;
|
||||||
|
child: any;
|
||||||
|
_item: PrasiItem;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const MasterFilter: FC<FilterProps> = ({
|
||||||
|
gen_fields,
|
||||||
|
gen_table,
|
||||||
|
name,
|
||||||
|
value,
|
||||||
|
mode,
|
||||||
|
PassProp,
|
||||||
|
child,
|
||||||
|
onClose,
|
||||||
|
_item,
|
||||||
|
}): ReactNode => {
|
||||||
|
const filter = useLocal({ ...default_filter_local });
|
||||||
|
filter.name = name;
|
||||||
|
|
||||||
|
if (!isEditor) {
|
||||||
|
if (!filter_window.prasi_filter) {
|
||||||
|
filter_window.prasi_filter = {};
|
||||||
|
}
|
||||||
|
const pf = filter_window.prasi_filter;
|
||||||
|
if (pf) {
|
||||||
|
const pathname = getPathname();
|
||||||
|
if (!pf[pathname]) pf[pathname] = {};
|
||||||
|
if (!pf[pathname][name]) pf[pathname][name] = {};
|
||||||
|
pf[pathname][name][_item.id] = filter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode === "popup") {
|
||||||
|
let popup = document.querySelector(".main-content-preview > .portal");
|
||||||
|
if (!popup) {
|
||||||
|
popup = document.createElement("div");
|
||||||
|
popup.classList.add("portal");
|
||||||
|
|
||||||
|
const main = document.querySelector(".main-content-preview");
|
||||||
|
if (main) {
|
||||||
|
main.appendChild(popup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{createPortal(
|
||||||
|
<div
|
||||||
|
onClick={onClose}
|
||||||
|
className={cx(
|
||||||
|
css`
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
left: 0;
|
||||||
|
background: white;
|
||||||
|
z-index: 100;
|
||||||
|
`,
|
||||||
|
"c-flex c-flex-col"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<FilterContent
|
||||||
|
PassProp={PassProp}
|
||||||
|
child={child}
|
||||||
|
mode={mode}
|
||||||
|
_item={_item}
|
||||||
|
filter={filter}
|
||||||
|
/>
|
||||||
|
</div>,
|
||||||
|
popup
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FilterContent
|
||||||
|
PassProp={PassProp}
|
||||||
|
_item={_item}
|
||||||
|
child={child}
|
||||||
|
mode={mode}
|
||||||
|
filter={filter}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
.filter-content {
|
|
||||||
padding: 1rem;
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
border-radius: 4px;
|
|
||||||
background: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.filter-regular {
|
|
||||||
width: 250px;
|
|
||||||
/* Styles specific to sidebar */
|
|
||||||
}
|
|
||||||
|
|
||||||
.filter-inline {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
/* Styles specific to topbar */
|
|
||||||
}
|
|
||||||
|
|
||||||
.filter-popup {
|
|
||||||
position: fixed;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
z-index: 1000;
|
|
||||||
/* Styles specific to popup */
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
import { getPathname } from "lib/utils/pathname";
|
||||||
|
import { filter_window } from "./types";
|
||||||
|
|
||||||
|
export const filterWhere = (filter_name: string) => {
|
||||||
|
const pf = filter_window.prasi_filter?.[getPathname()]?.[filter_name];
|
||||||
|
const where: any = {};
|
||||||
|
const AND: any[] = [];
|
||||||
|
|
||||||
|
if (pf) {
|
||||||
|
for (const [k, filter] of Object.entries(pf)) {
|
||||||
|
for (const [name, value] of Object.entries(filter.data)) {
|
||||||
|
const type = filter.types[name];
|
||||||
|
const modifier = filter.modifiers[name];
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case "text":
|
||||||
|
{
|
||||||
|
if (modifier === "contains")
|
||||||
|
where[name] = {
|
||||||
|
contains: value,
|
||||||
|
mode: "insensitive",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "date": {
|
||||||
|
let is_value_valid = false;
|
||||||
|
// TODO: pastikan value bisa diparse pakai any-date-parser
|
||||||
|
if (is_value_valid) {
|
||||||
|
if (modifier === "between") {
|
||||||
|
AND.push({ [name]: { gt: value } });
|
||||||
|
AND.push({ [name]: { lt: value } });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (AND.length > 0) where.AND = AND;
|
||||||
|
}
|
||||||
|
return where;
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
import { BaseFormLocal } from "../../form/base/types";
|
||||||
|
import { GenField } from "../../form/typings";
|
||||||
|
|
||||||
|
export type FilterFieldType = "text" | "number" | "boolean" | "date";
|
||||||
|
export const default_filter_local = {
|
||||||
|
data: {} as any,
|
||||||
|
columns: [] as string[],
|
||||||
|
fields: [] as GenField[],
|
||||||
|
tableName: "",
|
||||||
|
form: null as null | BaseFormLocal<any>,
|
||||||
|
modifiers: {} as Record<string, string>,
|
||||||
|
types: {} as Record<string, FilterFieldType>,
|
||||||
|
name: "",
|
||||||
|
};
|
||||||
|
|
||||||
|
export const modifiers = {
|
||||||
|
text: { contains: "Contains", ends_with: "Ends With" },
|
||||||
|
boolean: {},
|
||||||
|
number: {},
|
||||||
|
date: {
|
||||||
|
between: "Between",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
export type FilterModifier = typeof modifiers;
|
||||||
|
|
||||||
|
export type FilterLocal = typeof default_filter_local & { render: () => void };
|
||||||
|
|
||||||
|
export const filter_window = window as unknown as {
|
||||||
|
prasi_filter: Record<string, Record<string, Record<string, FilterLocal>>>;
|
||||||
|
prasiContext: {
|
||||||
|
render: () => void;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,116 @@
|
||||||
|
import { ReactNode } from "react";
|
||||||
|
import { FMLocal, FieldLocal, FieldProp } from "../typings";
|
||||||
|
import { Label } from "../field/Label";
|
||||||
|
import { FieldLoading } from "../field/raw/FieldLoading";
|
||||||
|
|
||||||
|
export const BaseField = (prop: {
|
||||||
|
field: FieldLocal;
|
||||||
|
fm: FMLocal;
|
||||||
|
arg: FieldProp;
|
||||||
|
children: (arg: {
|
||||||
|
field: FieldLocal;
|
||||||
|
fm: FMLocal;
|
||||||
|
arg: FieldProp;
|
||||||
|
}) => ReactNode;
|
||||||
|
}) => {
|
||||||
|
const { field, fm, arg } = prop;
|
||||||
|
const w = field.width;
|
||||||
|
const mode = fm.props.label_mode;
|
||||||
|
const prefix =
|
||||||
|
typeof field.prefix === "function"
|
||||||
|
? field.prefix()
|
||||||
|
: typeof field.prefix === "string"
|
||||||
|
? field.prefix
|
||||||
|
: null;
|
||||||
|
const suffix =
|
||||||
|
typeof field.suffix === "function"
|
||||||
|
? field.suffix()
|
||||||
|
: typeof field.suffix === "string"
|
||||||
|
? field.prefix
|
||||||
|
: null;
|
||||||
|
const name = field.name;
|
||||||
|
const errors = fm.error.get(name);
|
||||||
|
let type_field = typeof arg.type === "function" ? arg.type() : arg.type; // tipe field
|
||||||
|
|
||||||
|
return (
|
||||||
|
<label
|
||||||
|
className={cx(
|
||||||
|
"field",
|
||||||
|
"c-flex",
|
||||||
|
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",
|
||||||
|
w === "⅓" && "c-w-1/3",
|
||||||
|
w === "¼" && "c-w-1/4",
|
||||||
|
mode === "horizontal" && "c-flex-row c-items-center",
|
||||||
|
mode === "vertical" && "c-flex-col c-space-y-1"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{mode !== "hidden" && <Label field={field} fm={fm} />}
|
||||||
|
<div className="field-inner c-flex c-flex-1 c-flex-col">
|
||||||
|
<div
|
||||||
|
className={cx(
|
||||||
|
!["toogle", "button", "radio", "checkbox"].includes(arg.sub_type)
|
||||||
|
? "field-outer c-flex c-flex-1 c-flex-row c-rounded c-border c-text-sm c-flex-wrap"
|
||||||
|
: "",
|
||||||
|
fm.status === "loading"
|
||||||
|
? css`
|
||||||
|
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",
|
||||||
|
css`
|
||||||
|
& > .field-inner {
|
||||||
|
min-height: 35px;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{prefix && prefix !== "" ? (
|
||||||
|
<div
|
||||||
|
className="
|
||||||
|
c-px-2 c-bg-gray-200 c-flex c-flex-row c-items-center"
|
||||||
|
>
|
||||||
|
{prefix}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
)}
|
||||||
|
{fm.status === "loading" ? (
|
||||||
|
<FieldLoading />
|
||||||
|
) : (
|
||||||
|
<div
|
||||||
|
className={cx(
|
||||||
|
"field-inner c-flex-1 c-flex c-items-center",
|
||||||
|
field.disabled && "c-pointer-events-none"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{prop.children(prop)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{suffix && suffix !== "" ? (
|
||||||
|
<div
|
||||||
|
className="
|
||||||
|
c-px-2 c-bg-gray-200 c-flex c-flex-row c-items-center"
|
||||||
|
>
|
||||||
|
{suffix}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,111 @@
|
||||||
|
import { ReactNode, useCallback, useEffect, useState } from "react";
|
||||||
|
import { BaseFormLocal, default_base_form_local } from "./types";
|
||||||
|
import { useLocal } from "lib/utils/use-local";
|
||||||
|
import { FieldLocal, FieldProp } from "../typings";
|
||||||
|
|
||||||
|
export type BaseFormProps<T> = {
|
||||||
|
data: T;
|
||||||
|
className?: string;
|
||||||
|
on_submit?: (form: BaseFormLocal<T>) => Promise<any> | any;
|
||||||
|
children: ReactNode | ((form: BaseFormLocal<T>) => ReactNode);
|
||||||
|
render?: () => void;
|
||||||
|
};
|
||||||
|
export const BaseForm = <T extends Record<string, any>>(
|
||||||
|
props: BaseFormProps<T>
|
||||||
|
) => {
|
||||||
|
const { data, children, className, on_submit, render } = props;
|
||||||
|
const form = useLocal({ ...default_base_form_local }) as BaseFormLocal<T>;
|
||||||
|
|
||||||
|
if (render) {
|
||||||
|
form.render = render;
|
||||||
|
}
|
||||||
|
|
||||||
|
form.submit = useCallback(async () => {
|
||||||
|
if (form.status === "ready") {
|
||||||
|
form.status = "submitting";
|
||||||
|
form.render();
|
||||||
|
|
||||||
|
const result = await on_submit?.(form);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
form.status = "ready";
|
||||||
|
form.render();
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}, [on_submit]);
|
||||||
|
|
||||||
|
form.createArg = (arg) => {
|
||||||
|
const prop: FieldProp = { name: arg.name } as any;
|
||||||
|
if (arg.onChange) prop.on_change = arg.onChange;
|
||||||
|
return prop;
|
||||||
|
};
|
||||||
|
|
||||||
|
form.createField = (arg) => {
|
||||||
|
const prop: FieldLocal = {
|
||||||
|
name: arg.name,
|
||||||
|
label: typeof arg.label !== "undefined" ? arg.label : arg.name,
|
||||||
|
render: arg.render || form.render,
|
||||||
|
width: "auto",
|
||||||
|
prefix: arg.prefix,
|
||||||
|
} as any;
|
||||||
|
return prop;
|
||||||
|
};
|
||||||
|
|
||||||
|
form.createFm = () => {
|
||||||
|
return {
|
||||||
|
data: form.data,
|
||||||
|
props: { label_mode: "vertical" },
|
||||||
|
error: {
|
||||||
|
get: () => {
|
||||||
|
return [];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
size: { field: "full" },
|
||||||
|
render: form.render,
|
||||||
|
} as any;
|
||||||
|
};
|
||||||
|
|
||||||
|
form.fieldProps = (arg) => {
|
||||||
|
return {
|
||||||
|
fm: form.createFm(),
|
||||||
|
arg: form.createArg(arg),
|
||||||
|
field: form.createField(arg),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
form.data = data;
|
||||||
|
form.render();
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
|
if (form.status === "init") {
|
||||||
|
form.status = "ready";
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<form
|
||||||
|
onSubmit={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
form.submit();
|
||||||
|
}}
|
||||||
|
className={cx(
|
||||||
|
"form c-flex-1 c-flex-col c-w-full c-h-full c-relative c-overflow-auto",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className={cx(
|
||||||
|
"form-inner c-flex c-flex-1 c-flex-wrap c-items-start c-content-start c-absolute c-inset-0",
|
||||||
|
css`
|
||||||
|
padding-right: 10px;
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{typeof children === "function" ? children(form) : children}
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
import { ReactNode } from "react";
|
||||||
|
import { FMLocal, FieldLocal, FieldProp } from "../typings";
|
||||||
|
|
||||||
|
export const default_base_form_local = {
|
||||||
|
status: "init" as "init" | "submitting" | "ready",
|
||||||
|
data: {} as any,
|
||||||
|
};
|
||||||
|
|
||||||
|
type CreateFieldArg = {
|
||||||
|
name: string;
|
||||||
|
label?: string;
|
||||||
|
prefix?: ReactNode | (() => ReactNode);
|
||||||
|
onChange?: (value: any) => void;
|
||||||
|
render?: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type BaseFormLocal<T> = Omit<typeof default_base_form_local, "data"> & {
|
||||||
|
data: T;
|
||||||
|
createArg: (arg: CreateFieldArg) => FieldProp;
|
||||||
|
createField: (arg: CreateFieldArg) => FieldLocal;
|
||||||
|
createFm: () => FMLocal;
|
||||||
|
fieldProps: (arg: CreateFieldArg) => {
|
||||||
|
fm: FMLocal;
|
||||||
|
field: FieldLocal;
|
||||||
|
arg: FieldProp;
|
||||||
|
};
|
||||||
|
submit: () => Promise<any> | any;
|
||||||
|
render: () => void;
|
||||||
|
};
|
||||||
|
|
@ -55,7 +55,6 @@ export const TypeDropdown: FC<{
|
||||||
} else {
|
} else {
|
||||||
selected = value;
|
selected = value;
|
||||||
}
|
}
|
||||||
console.log({selected})
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{field.status === "loading" ? (
|
{field.status === "loading" ? (
|
||||||
|
|
@ -75,7 +74,6 @@ export const TypeDropdown: FC<{
|
||||||
if (item[input.pk] === val) {
|
if (item[input.pk] === val) {
|
||||||
fm.data[field.name] = val;
|
fm.data[field.name] = val;
|
||||||
fm.render();
|
fm.render();
|
||||||
arg.on_change({value: item})
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,12 @@
|
||||||
import { FC } from "react";
|
import { AutoHeightTextarea } from "@/comps/custom/AutoHeightTextarea";
|
||||||
import { FMLocal, FieldLocal, FieldProp } from "../../typings";
|
|
||||||
import { useLocal } from "@/utils/use-local";
|
import { useLocal } from "@/utils/use-local";
|
||||||
import parser from "any-date-parser";
|
import parser from "any-date-parser";
|
||||||
import { AutoHeightTextarea } from "@/comps/custom/AutoHeightTextarea";
|
|
||||||
import { M } from "src/data/unitShortcuts";
|
|
||||||
import { format } from "date-fns";
|
import { format } from "date-fns";
|
||||||
import get from "lodash.get";
|
import { FC } from "react";
|
||||||
|
import { FMLocal, FieldLocal, FieldProp } from "../../typings";
|
||||||
import { FieldMoney } from "./TypeMoney";
|
import { FieldMoney } from "./TypeMoney";
|
||||||
import { FieldUpload } from "./TypeUpload";
|
|
||||||
import { FieldRichText } from "./TypeRichText";
|
import { FieldRichText } from "./TypeRichText";
|
||||||
|
import { FieldUpload } from "./TypeUpload";
|
||||||
|
|
||||||
export type PropTypeText = {
|
export type PropTypeText = {
|
||||||
type: "text" | "date";
|
type: "text" | "date";
|
||||||
|
|
@ -45,9 +43,11 @@ export const FieldTypeText: FC<{
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
const input = useLocal({});
|
const input = useLocal({});
|
||||||
let display: any = null;
|
let display: any = null;
|
||||||
let value: any = fm.data[field.name];
|
let value: any = fm.data[field.name];
|
||||||
|
|
||||||
// let value: any = "2024-05-14T05:58:01.376Z" // case untuk date time
|
// let value: any = "2024-05-14T05:58:01.376Z" // case untuk date time
|
||||||
field.input = input;
|
field.input = input;
|
||||||
field.prop = prop;
|
field.prop = prop;
|
||||||
|
|
@ -75,6 +75,7 @@ export const FieldTypeText: FC<{
|
||||||
} else if (["number"].includes(type_field)) {
|
} else if (["number"].includes(type_field)) {
|
||||||
value = Number(value) || null;
|
value = Number(value) || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{type_field === "textarea" ? (
|
{type_field === "textarea" ? (
|
||||||
|
|
@ -153,7 +154,6 @@ export const FieldTypeText: FC<{
|
||||||
<input
|
<input
|
||||||
type={type_field}
|
type={type_field}
|
||||||
onChange={(ev) => {
|
onChange={(ev) => {
|
||||||
console.log("onchange");
|
|
||||||
if (["date", "datetime", "datetime-local"].includes(type_field)) {
|
if (["date", "datetime", "datetime-local"].includes(type_field)) {
|
||||||
let result = null;
|
let result = null;
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,16 @@ export type FMProps = {
|
||||||
on_load_deps?: any[];
|
on_load_deps?: any[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type GenField = {
|
||||||
|
name: string,
|
||||||
|
is_pk: boolean,
|
||||||
|
type: string,
|
||||||
|
optional: boolean,
|
||||||
|
} | {
|
||||||
|
checked: GenField[],
|
||||||
|
value: GFCol
|
||||||
|
};
|
||||||
|
|
||||||
type FieldType =
|
type FieldType =
|
||||||
| "-"
|
| "-"
|
||||||
| "relation"
|
| "relation"
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,8 @@ type TableListProp = {
|
||||||
}) => Promise<any[]>;
|
}) => Promise<any[]>;
|
||||||
on_init: (arg?: any) => any;
|
on_init: (arg?: any) => any;
|
||||||
mode: "table" | "list" | "grid" | "auto";
|
mode: "table" | "list" | "grid" | "auto";
|
||||||
_meta: Record<string, any>;
|
// _meta: Record<string, any>;
|
||||||
|
_item: PrasiItem;
|
||||||
gen_fields: string[];
|
gen_fields: string[];
|
||||||
row_click: OnRowClick;
|
row_click: OnRowClick;
|
||||||
selected: SelectedRow;
|
selected: SelectedRow;
|
||||||
|
|
@ -61,7 +62,7 @@ export const TableList: FC<TableListProp> = ({
|
||||||
PassProp,
|
PassProp,
|
||||||
mode,
|
mode,
|
||||||
on_init,
|
on_init,
|
||||||
_meta,
|
_item,
|
||||||
gen_fields,
|
gen_fields,
|
||||||
row_click,
|
row_click,
|
||||||
selected,
|
selected,
|
||||||
|
|
@ -247,7 +248,6 @@ export const TableList: FC<TableListProp> = ({
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
const checked = !!local.selectedRows.find((data) => data.pk === rowId);
|
const checked = !!local.selectedRows.find((data) => data.pk === rowId);
|
||||||
console.log(checked);
|
|
||||||
if (!checked) {
|
if (!checked) {
|
||||||
// jika checkbox tercheck, maka rowData akan diambil jika memiliki id yang sama dengan rowId yang dikirim
|
// jika checkbox tercheck, maka rowData akan diambil jika memiliki id yang sama dengan rowId yang dikirim
|
||||||
const checkedRowData = rowData.filter((row) => row[pk] === rowId);
|
const checkedRowData = rowData.filter((row) => row[pk] === rowId);
|
||||||
|
|
@ -256,14 +256,12 @@ export const TableList: FC<TableListProp> = ({
|
||||||
rows: checkedRowData,
|
rows: checkedRowData,
|
||||||
});
|
});
|
||||||
local.render();
|
local.render();
|
||||||
console.log("selected", local.selectedRows);
|
|
||||||
} else {
|
} else {
|
||||||
// jika tidak, maka akan dihapus
|
// jika tidak, maka akan dihapus
|
||||||
local.selectedRows = local.selectedRows.filter(
|
local.selectedRows = local.selectedRows.filter(
|
||||||
(data) => data.pk !== rowId
|
(data) => data.pk !== rowId
|
||||||
);
|
);
|
||||||
local.render();
|
local.render();
|
||||||
console.log("deselected", local.selectedRows);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -271,9 +269,12 @@ export const TableList: FC<TableListProp> = ({
|
||||||
(e: any) => e.name === sub_name || e.name === mode
|
(e: any) => e.name === sub_name || e.name === mode
|
||||||
);
|
);
|
||||||
if (mode_child) {
|
if (mode_child) {
|
||||||
const meta = _meta[mode_child.id];
|
const tbl = _item.edit.childs[0].edit.childs.find(
|
||||||
if (meta && meta.item.childs) {
|
(e) => get(e, "id") === mode_child.id
|
||||||
childs = meta.item.childs;
|
);
|
||||||
|
const meta = tbl;
|
||||||
|
if (meta && meta.childs) {
|
||||||
|
childs = meta.childs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let columns: ColumnOrColumnGroup<any>[] = [];
|
let columns: ColumnOrColumnGroup<any>[] = [];
|
||||||
|
|
@ -322,37 +323,36 @@ export const TableList: FC<TableListProp> = ({
|
||||||
cellClass: selectCellClassname,
|
cellClass: selectCellClassname,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// for (const child of childs) {
|
for (const child of childs) {
|
||||||
// const key = getProp(child, "name", {});
|
const key = getProp(child, "name", {});
|
||||||
// const name = getProp(child, "title", {});
|
const name = getProp(child, "title", {});
|
||||||
// const width = parseInt(getProp(child, "width", {}));
|
const width = parseInt(getProp(child, "width", {}));
|
||||||
|
|
||||||
// columns.push({
|
columns.push({
|
||||||
// key,
|
key,
|
||||||
// name,
|
name,
|
||||||
// width: width > 0 ? width : undefined,
|
width: width > 0 ? width : undefined,
|
||||||
// resizable: true,
|
resizable: true,
|
||||||
// sortable: true,
|
sortable: true,
|
||||||
// renderCell(props) {
|
renderCell(props) {
|
||||||
// return (
|
return (
|
||||||
// <PassProp
|
<PassProp
|
||||||
// idx={props.rowIdx}
|
idx={props.rowIdx}
|
||||||
// row={props.row}
|
row={props.row}
|
||||||
// col={{
|
col={{
|
||||||
// name: props.column.key,
|
name: props.column.key,
|
||||||
// value: props.row[props.column.key],
|
value: props.row[props.column.key],
|
||||||
// depth: props.row.__depth || 0,
|
depth: props.row.__depth || 0,
|
||||||
// }}
|
}}
|
||||||
// rows={local.data}
|
rows={local.data}
|
||||||
// >
|
>
|
||||||
// {child}
|
{child}
|
||||||
// </PassProp>
|
</PassProp>
|
||||||
// );
|
);
|
||||||
// },
|
},
|
||||||
// });
|
});
|
||||||
// }
|
}
|
||||||
if (mode === "list") {
|
if (mode === "list") {
|
||||||
// ambil satu index saja;
|
|
||||||
if (columns.length > 1) columns = columns.slice(0, 0 + 1);
|
if (columns.length > 1) columns = columns.slice(0, 0 + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -420,12 +420,19 @@ export const TableList: FC<TableListProp> = ({
|
||||||
if (id_parent && local.pk && local.sort.columns.length === 0) {
|
if (id_parent && local.pk && local.sort.columns.length === 0) {
|
||||||
data = sortTree(local.data, id_parent, local.pk.name);
|
data = sortTree(local.data, id_parent, local.pk.name);
|
||||||
}
|
}
|
||||||
|
console.log("render?")
|
||||||
|
// return "123"
|
||||||
if (mode === "table") {
|
if (mode === "table") {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cx(
|
className={cx(
|
||||||
"c-w-full c-h-full c-flex-1 c-relative c-overflow-hidden",
|
"c-w-full c-h-full c-flex-1 c-relative c-overflow-hidden",
|
||||||
dataGridStyle(local)
|
dataGridStyle(local),
|
||||||
|
css`
|
||||||
|
.rdg {
|
||||||
|
display: grid !important;
|
||||||
|
}
|
||||||
|
`
|
||||||
)}
|
)}
|
||||||
ref={(el) => {
|
ref={(el) => {
|
||||||
if (!local.el && el) {
|
if (!local.el && el) {
|
||||||
|
|
@ -485,7 +492,7 @@ export const TableList: FC<TableListProp> = ({
|
||||||
row: props.row,
|
row: props.row,
|
||||||
rows: local.data,
|
rows: local.data,
|
||||||
});
|
});
|
||||||
// return "halo"
|
|
||||||
return (
|
return (
|
||||||
<Row
|
<Row
|
||||||
key={key}
|
key={key}
|
||||||
|
|
@ -651,3 +658,11 @@ function isAtBottom({ currentTarget }: React.UIEvent<HTMLDivElement>): boolean {
|
||||||
currentTarget.scrollHeight - currentTarget.clientHeight
|
currentTarget.scrollHeight - currentTarget.clientHeight
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getProp(child: IItem, name: string, defaultValue?: any) {
|
||||||
|
const fn = new Function(
|
||||||
|
`return ${get(child, `component.props.${name}.valueBuilt`) || `null`}`
|
||||||
|
);
|
||||||
|
|
||||||
|
return fn() || defaultValue;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,6 @@ export const MasterDetail: FC<MDProps> = (arg) => {
|
||||||
if (isEditor) {
|
if (isEditor) {
|
||||||
editorMDInit(md, mdr, arg);
|
editorMDInit(md, mdr, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cx(
|
className={cx(
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,157 @@
|
||||||
|
import { createItem } from "lib/gen/utils";
|
||||||
|
import capitalize from "lodash.capitalize";
|
||||||
|
import { ArrowBigDown } from "lucide-react";
|
||||||
|
export type GFCol = {
|
||||||
|
name: string;
|
||||||
|
type: string;
|
||||||
|
is_pk: boolean;
|
||||||
|
optional: boolean;
|
||||||
|
relation?: {
|
||||||
|
from: { table: string; fields: string[] };
|
||||||
|
to: { table: string; fields: string[] };
|
||||||
|
fields: GFCol[];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
export const newField = (arg: GFCol, opt: { parent_table: string, value: Array<string> }) => {
|
||||||
|
console.log({ arg, opt });
|
||||||
|
let type = "input";
|
||||||
|
if (["int", "string", "text"].includes(arg.type)) {
|
||||||
|
if (["int"].includes(arg.type)) {
|
||||||
|
return createItem({
|
||||||
|
component: {
|
||||||
|
id: "32550d01-42a3-4b15-a04a-2c2d5c3c8e67",
|
||||||
|
props: {
|
||||||
|
name: arg.name,
|
||||||
|
label: formatName(arg.name),
|
||||||
|
type,
|
||||||
|
sub_type: "number",
|
||||||
|
child: {
|
||||||
|
childs: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return createItem({
|
||||||
|
component: {
|
||||||
|
id: "32550d01-42a3-4b15-a04a-2c2d5c3c8e67",
|
||||||
|
props: {
|
||||||
|
name: arg.name,
|
||||||
|
label: formatName(arg.name),
|
||||||
|
type,
|
||||||
|
sub_type: "text",
|
||||||
|
child: {
|
||||||
|
childs: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else if (["timestamptz", "date"].includes(arg.type) && arg.relation) {
|
||||||
|
return createItem({
|
||||||
|
component: {
|
||||||
|
id: "32550d01-42a3-4b15-a04a-2c2d5c3c8e67",
|
||||||
|
props: {
|
||||||
|
name: arg.name,
|
||||||
|
label: formatName(arg.name),
|
||||||
|
type: "date",
|
||||||
|
sub_type: "datetime",
|
||||||
|
child: {
|
||||||
|
childs: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else if (["has-many", "has-one"].includes(arg.type) && arg.relation) {
|
||||||
|
if(["has-one"].includes(arg.type)){
|
||||||
|
return createItem({
|
||||||
|
component: {
|
||||||
|
id: "32550d01-42a3-4b15-a04a-2c2d5c3c8e67",
|
||||||
|
props: {
|
||||||
|
name: arg.name,
|
||||||
|
label: formatName(arg.name),
|
||||||
|
type: "single-option",
|
||||||
|
sub_type: "dropdown",
|
||||||
|
rel__gen_table: arg.name,
|
||||||
|
rel__gen_fields: [`[${opt.value.join(",")}]`],
|
||||||
|
child: {
|
||||||
|
childs: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
// return {
|
||||||
|
// name: "item",
|
||||||
|
// type: "item",
|
||||||
|
// component: {
|
||||||
|
// id: "32550d01-42a3-4b15-a04a-2c2d5c3c8e67",
|
||||||
|
// props: {
|
||||||
|
// name: {
|
||||||
|
// mode: "string",
|
||||||
|
// value: arg.name
|
||||||
|
// },
|
||||||
|
// label: {
|
||||||
|
// mode: "string",
|
||||||
|
// value: formatName(arg.name)
|
||||||
|
// },
|
||||||
|
// type: {
|
||||||
|
// mode: "string",
|
||||||
|
// value: "single-option"
|
||||||
|
// },
|
||||||
|
// sub_type: {
|
||||||
|
// mode: "string",
|
||||||
|
// value: "dropdown"
|
||||||
|
// },
|
||||||
|
// rel__gen_table: {
|
||||||
|
// mode: "string",
|
||||||
|
// value: arg.name
|
||||||
|
// },
|
||||||
|
// rel__gen_fields: {
|
||||||
|
// mode: "raw",
|
||||||
|
// value: `${JSON.stringify(opt.val)}`
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// };
|
||||||
|
}else{
|
||||||
|
return createItem({
|
||||||
|
component: {
|
||||||
|
id: "32550d01-42a3-4b15-a04a-2c2d5c3c8e67",
|
||||||
|
props: {
|
||||||
|
name: arg.name,
|
||||||
|
label: formatName(arg.name),
|
||||||
|
type: "date",
|
||||||
|
sub_type: "datetime",
|
||||||
|
child: {
|
||||||
|
childs: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// type not found,
|
||||||
|
return createItem({
|
||||||
|
component: {
|
||||||
|
id: "32550d01-42a3-4b15-a04a-2c2d5c3c8e67",
|
||||||
|
props: {
|
||||||
|
name: arg.name,
|
||||||
|
label: formatName(arg.name),
|
||||||
|
type,
|
||||||
|
sub_type: "text",
|
||||||
|
child: {
|
||||||
|
childs: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
export const formatName = (name: string) => {
|
||||||
|
return (name || "")
|
||||||
|
.split("_")
|
||||||
|
.filter((e) => e.length > 1)
|
||||||
|
.map((e) => capitalize(e))
|
||||||
|
.join(" ");
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
import { GFCol } from "./fields";
|
||||||
|
|
||||||
|
export const on_load = ({
|
||||||
|
pk,
|
||||||
|
table,
|
||||||
|
select,
|
||||||
|
pks,
|
||||||
|
opt,
|
||||||
|
}: {
|
||||||
|
pk: GFCol;
|
||||||
|
table: string;
|
||||||
|
select: any;
|
||||||
|
pks: Record<string, string>;
|
||||||
|
opt?: {
|
||||||
|
before_load: string;
|
||||||
|
after_load: string;
|
||||||
|
};
|
||||||
|
}) => {
|
||||||
|
const sample: any = {};
|
||||||
|
for (const [k, v] of Object.entries(select) as any) {
|
||||||
|
if (typeof v === "object") {
|
||||||
|
sample[k] = {};
|
||||||
|
|
||||||
|
Object.keys(v.select).map((e) => {
|
||||||
|
sample[k][e] = "sample";
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
sample[k] = "sample";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return `\
|
||||||
|
async (opt) => {
|
||||||
|
if (isEditor) return ${JSON.stringify(sample)};
|
||||||
|
|
||||||
|
let raw_id = params.id;
|
||||||
|
if (typeof md === 'object' && md.selected && md.pk) {
|
||||||
|
const pk = md.pk?.name;
|
||||||
|
if (md.selected[pk]) {
|
||||||
|
raw_id = md.selected[pk];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
${
|
||||||
|
opt?.before_load
|
||||||
|
? opt.before_load
|
||||||
|
: `let id = ${pk.type === "int" ? "parseInt(raw_id)" : "raw_id"};`
|
||||||
|
}
|
||||||
|
|
||||||
|
let item = {};
|
||||||
|
if (id){
|
||||||
|
item = await db.${table}.findFirst({
|
||||||
|
where: {
|
||||||
|
${pk.name}: id,
|
||||||
|
},
|
||||||
|
select: ${JSON.stringify(select, null, 2).split("\n").join("\n ")},
|
||||||
|
});
|
||||||
|
|
||||||
|
${opt?.after_load ? opt?.after_load : ""}
|
||||||
|
|
||||||
|
return item;
|
||||||
|
} else {
|
||||||
|
${opt?.after_load ? opt?.after_load : ""}
|
||||||
|
}
|
||||||
|
}`;
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
import { createItem, parseGenField } from "lib/gen/utils";
|
||||||
|
import get from "lodash.get";
|
||||||
|
import { generateTableList } from "./gen-table-list";
|
||||||
|
import { generateSelect } from "./md-select";
|
||||||
|
import { on_load } from "./tbl-list/on_load";
|
||||||
|
import { on_submit } from "./tbl-list/on_submit";
|
||||||
|
import { newField } from "./form/fields";
|
||||||
|
import { createId } from "@paralleldrive/cuid2";
|
||||||
|
|
||||||
|
export const generateForm = async (
|
||||||
|
modify: (data: any) => void,
|
||||||
|
data: any,
|
||||||
|
item: PrasiItem,
|
||||||
|
commit: boolean
|
||||||
|
) => {
|
||||||
|
const table = JSON.parse(data.gen_table.value);
|
||||||
|
console.log("halo");
|
||||||
|
console.log(table);
|
||||||
|
const raw_fields = JSON.parse(data.gen_fields.value) as (
|
||||||
|
| string
|
||||||
|
| { value: string; checked: string[] }
|
||||||
|
)[];
|
||||||
|
let pk = "";
|
||||||
|
console.log({ raw_fields });
|
||||||
|
let pks: Record<string, string> = {};
|
||||||
|
const fields = parseGenField(raw_fields);
|
||||||
|
// convert ke bahasa prisma untuk select
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
if (pk) {
|
||||||
|
console.log("masuk");
|
||||||
|
if (data["on_load"]) {
|
||||||
|
result.on_load = {
|
||||||
|
mode: "raw",
|
||||||
|
value: on_load({ pk, table, select, pks }),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (data["on_submit"]) {
|
||||||
|
result.on_submit = {
|
||||||
|
mode: "raw",
|
||||||
|
value: on_submit({ pk, table, select, pks }),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
result.body = data["body"];
|
||||||
|
|
||||||
|
console.log({ fields, result });
|
||||||
|
const childs = [];
|
||||||
|
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 });
|
||||||
|
childs.push(field);
|
||||||
|
}
|
||||||
|
if (commit) {
|
||||||
|
const body = item.edit.childs[0] as PrasiItem;
|
||||||
|
item.edit.setProp("body", {
|
||||||
|
mode: "jsx",
|
||||||
|
value: createItem({
|
||||||
|
childs: childs,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
// await item.edit.commit();
|
||||||
|
} else {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,129 @@
|
||||||
|
import capitalize from "lodash.capitalize";
|
||||||
|
import { GFCol, createItem, parseGenField } from "../../../gen/utils";
|
||||||
|
import { generateSelect } from "./md-select";
|
||||||
|
import { on_load } from "./tbl-list/on_load";
|
||||||
|
import { modeTableList } from "./mode-table-list";
|
||||||
|
import get from "lodash.get";
|
||||||
|
import set from "lodash.set";
|
||||||
|
|
||||||
|
export const generateTableList = async (
|
||||||
|
modify: (data: any) => void,
|
||||||
|
data: any,
|
||||||
|
item: PrasiItem,
|
||||||
|
arg: { mode: "table" | "list" | "grid" | "auto"; id_parent?: string },
|
||||||
|
commit: boolean
|
||||||
|
) => {
|
||||||
|
const table = JSON.parse(data.gen_table.value) as string;
|
||||||
|
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);
|
||||||
|
// convert ke bahasa prisma untuk select
|
||||||
|
const res = generateSelect(fields);
|
||||||
|
pk = res.pk;
|
||||||
|
const select = res.select as any;
|
||||||
|
const result: Record<string, PropVal> = {};
|
||||||
|
if (arg.id_parent) {
|
||||||
|
select[arg.id_parent] = true;
|
||||||
|
}
|
||||||
|
if (!pk) {
|
||||||
|
alert("Failed to generate! Primary Key not found. ");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let childs = [] as any;
|
||||||
|
if (pk) {
|
||||||
|
let sub_name = modeTableList(arg.mode);
|
||||||
|
let rows = Array.isArray(get(data, "child.content.childs"))
|
||||||
|
? get(data, "child.content.childs")
|
||||||
|
: Array.isArray(get(data, "child.childs"))
|
||||||
|
? get(data, "child.childs")
|
||||||
|
: [];
|
||||||
|
|
||||||
|
rows = rows.filter((e: PrasiItem) => e.name !== sub_name);
|
||||||
|
childs = childs.concat(rows);
|
||||||
|
|
||||||
|
if (data["on_load"]) {
|
||||||
|
result.on_load = {
|
||||||
|
mode: "raw",
|
||||||
|
value: on_load({ pk, table, select, pks }),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
let first = true;
|
||||||
|
|
||||||
|
const child_sub_name = createItem({
|
||||||
|
name: sub_name,
|
||||||
|
childs: fields
|
||||||
|
.map((e, idx) => {
|
||||||
|
if (idx >= 1 && arg.mode === "list") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (e.is_pk && arg.mode === "table") return;
|
||||||
|
let tree_depth = "";
|
||||||
|
let tree_depth_built = "";
|
||||||
|
if (first) {
|
||||||
|
tree_depth = `tree_depth={col.depth}`;
|
||||||
|
tree_depth_built = `tree_depth:col.depth`;
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
component: {
|
||||||
|
id: "297023a4-d552-464a-971d-f40dcd940b77",
|
||||||
|
props: {
|
||||||
|
name: e.name,
|
||||||
|
title: formatName(e.name),
|
||||||
|
child: createItem({
|
||||||
|
childs: [
|
||||||
|
createItem({
|
||||||
|
name: "cell",
|
||||||
|
padding: {
|
||||||
|
l: 8,
|
||||||
|
b: 0,
|
||||||
|
t: 0,
|
||||||
|
r: 8,
|
||||||
|
},
|
||||||
|
adv: {
|
||||||
|
js: `\
|
||||||
|
<div {...props} className={cx(props.className, "")}>
|
||||||
|
<FormatValue value={col.value} name={col.name} gen_fields={gen_fields} ${tree_depth} />
|
||||||
|
</div>`,
|
||||||
|
jsBuilt: `\
|
||||||
|
render(React.createElement("div", Object.assign({}, props, { className: cx(props.className, "") }),React.createElement(FormatValue, { value: col.value, name: col.name, gen_fields: gen_fields, ${tree_depth_built} })));
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.filter((e) => e) as any,
|
||||||
|
});
|
||||||
|
childs.push(child_sub_name);
|
||||||
|
|
||||||
|
if (commit) {
|
||||||
|
Object.keys(result).map((e) => {
|
||||||
|
item.edit.setProp(e, result[e]);
|
||||||
|
});
|
||||||
|
console.log({ childs });
|
||||||
|
item.edit.setChilds(childs);
|
||||||
|
await item.edit.commit();
|
||||||
|
} else {
|
||||||
|
set(data, "child.value.childs", childs);
|
||||||
|
Object.keys(result).map((e) => {
|
||||||
|
set(data, e, result[e]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatName = (name: string) => {
|
||||||
|
return name
|
||||||
|
.split("_")
|
||||||
|
.filter((e) => e.length > 1)
|
||||||
|
.map((e) => capitalize(e))
|
||||||
|
.join(" ");
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,122 @@
|
||||||
|
import { createItem } from "lib/gen/utils";
|
||||||
|
import get from "lodash.get";
|
||||||
|
import { generateTableList } from "./gen-table-list";
|
||||||
|
|
||||||
|
export const generateMDForm = async (
|
||||||
|
arg: { item: PrasiItem; table: string; fields: any },
|
||||||
|
data: any,
|
||||||
|
commit: boolean
|
||||||
|
) => {
|
||||||
|
const item = arg.item;
|
||||||
|
const tab_master = item.edit.childs[0].edit.childs.find(
|
||||||
|
(e) => get(e, "component.id") === "c68415ca-dac5-44fe-aeb6-936caf8cc491"
|
||||||
|
);
|
||||||
|
const props: Record<string, PropVal> = {
|
||||||
|
gen_table: {
|
||||||
|
mode: "string",
|
||||||
|
value: arg.table,
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
mode: "string",
|
||||||
|
value: arg.table,
|
||||||
|
},
|
||||||
|
generate: {
|
||||||
|
mode: "string",
|
||||||
|
value: "y",
|
||||||
|
},
|
||||||
|
on_load: {
|
||||||
|
mode: "string",
|
||||||
|
value: "",
|
||||||
|
},
|
||||||
|
row_click: {
|
||||||
|
mode: "raw",
|
||||||
|
value: `\
|
||||||
|
({ row, rows, idx, event }: OnRowClick) => {
|
||||||
|
md.selected = row;
|
||||||
|
md.internal.action_should_refresh = true;
|
||||||
|
md.params.apply();
|
||||||
|
md.render();
|
||||||
|
};
|
||||||
|
|
||||||
|
type OnRowClick = {
|
||||||
|
row: any;
|
||||||
|
rows: any[];
|
||||||
|
idx: any;
|
||||||
|
event: React.MouseEvent<HTMLDivElement, MouseEvent>;
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
selected: {
|
||||||
|
mode: "raw",
|
||||||
|
value: `\
|
||||||
|
({ row, rows, idx }: SelectedRow) => {
|
||||||
|
try {
|
||||||
|
if (typeof md === "object") {
|
||||||
|
if (Array.isArray(md.selected)) {
|
||||||
|
if (md.selected.length) {
|
||||||
|
let select = md.selected.find((e) => e === row)
|
||||||
|
if(select) return true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (md.selected === row) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
type SelectedRow = {
|
||||||
|
row: any;
|
||||||
|
rows: any[];
|
||||||
|
idx: any;
|
||||||
|
}`,
|
||||||
|
},
|
||||||
|
gen_fields: {
|
||||||
|
mode: "raw",
|
||||||
|
value: `${JSON.stringify(arg.fields)}`,
|
||||||
|
},
|
||||||
|
child: {
|
||||||
|
mode: "jsx",
|
||||||
|
value: createItem({
|
||||||
|
name: "halo",
|
||||||
|
childs: [],
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const tablelist: any = {
|
||||||
|
type: "item",
|
||||||
|
name: "item",
|
||||||
|
component: {
|
||||||
|
id: "567d5362-2cc8-4ca5-a531-f771a5c866c2",
|
||||||
|
props,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
generateTableList(
|
||||||
|
async (props: any) => {},
|
||||||
|
props,
|
||||||
|
tablelist,
|
||||||
|
{ mode: "table" },
|
||||||
|
false
|
||||||
|
);
|
||||||
|
tab_master?.edit.setChilds([ {
|
||||||
|
type: "item",
|
||||||
|
name: "item",
|
||||||
|
component: {
|
||||||
|
id: "567d5362-2cc8-4ca5-a531-f771a5c866c2",
|
||||||
|
props,
|
||||||
|
},
|
||||||
|
}]);
|
||||||
|
console.log({
|
||||||
|
type: "item",
|
||||||
|
name: "item",
|
||||||
|
component: {
|
||||||
|
id: "567d5362-2cc8-4ca5-a531-f771a5c866c2",
|
||||||
|
props,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
// console.log(tablelist);
|
||||||
|
};
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { createItem } from "lib/gen/utils";
|
import { createItem } from "lib/gen/utils";
|
||||||
import get from "lodash.get";
|
import get from "lodash.get";
|
||||||
import { generateTableList } from "./md-table-list";
|
import { generateTableList } from "./gen-table-list";
|
||||||
|
|
||||||
export const generateList = async (
|
export const generateList = async (
|
||||||
arg: { item: PrasiItem; table: string; fields: any },
|
arg: { item: PrasiItem; table: string; fields: any },
|
||||||
|
|
@ -82,47 +82,32 @@ idx: any;
|
||||||
child: {
|
child: {
|
||||||
mode: "jsx",
|
mode: "jsx",
|
||||||
value: createItem({
|
value: createItem({
|
||||||
name: "halo"
|
name: "halo",
|
||||||
})
|
childs: [],
|
||||||
}
|
}),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
// console.log(true);
|
const tablelist: any = {
|
||||||
console.log({ tab_master });
|
|
||||||
const tablelist = tab_master?.childs[0];
|
|
||||||
// generateTableList(
|
|
||||||
// async (props: any) => {},
|
|
||||||
// props,
|
|
||||||
// tablelist,
|
|
||||||
// { mode: "table" },
|
|
||||||
// false
|
|
||||||
// );
|
|
||||||
// // console.log({modify: async (props: any) => {}, data, item, arg: { mode: "table" }});
|
|
||||||
// const tablelist: PrasiItem= get(item,"edit.childs[0].edit.childs[0].edit.childs[0]");
|
|
||||||
// const data_tbl = get(tablelist, "component.props")
|
|
||||||
// console.log({tablelist, data_tbl})
|
|
||||||
// if(typeof tab_master === "object"){
|
|
||||||
// // const master_child: PrasiItem= tab_master;
|
|
||||||
// // const prop_tablelist = get(tablelist, "component.props")
|
|
||||||
// // console.log({tablelist})
|
|
||||||
// //
|
|
||||||
// }
|
|
||||||
|
|
||||||
// tab_master?.edit.setChilds([
|
|
||||||
// {
|
|
||||||
// type: "item",
|
|
||||||
// name: "item",
|
|
||||||
// component: {
|
|
||||||
// id: "567d5362-2cc8-4ca5-a531-f771a5c866c2",
|
|
||||||
// props,
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// ]);
|
|
||||||
console.log({
|
|
||||||
type: "item",
|
type: "item",
|
||||||
name: "item",
|
name: "item",
|
||||||
component: {
|
component: {
|
||||||
id: "567d5362-2cc8-4ca5-a531-f771a5c866c2",
|
id: "567d5362-2cc8-4ca5-a531-f771a5c866c2",
|
||||||
props,
|
props,
|
||||||
},
|
},
|
||||||
})
|
};
|
||||||
|
generateTableList(
|
||||||
|
async (props: any) => {},
|
||||||
|
props,
|
||||||
|
tablelist,
|
||||||
|
{ mode: "table" },
|
||||||
|
false
|
||||||
|
);
|
||||||
|
tab_master?.edit.setChilds([ {
|
||||||
|
type: "item",
|
||||||
|
name: "item",
|
||||||
|
component: {
|
||||||
|
id: "567d5362-2cc8-4ca5-a531-f771a5c866c2",
|
||||||
|
props,
|
||||||
|
},
|
||||||
|
}]);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,241 +0,0 @@
|
||||||
import capitalize from "lodash.capitalize";
|
|
||||||
import { GFCol, createItem, parseGenField } from "../../../gen/utils";
|
|
||||||
import { generateSelect } from "./md-select";
|
|
||||||
import { on_load } from "./tbl-list/on_load";
|
|
||||||
import { modeTableList } from "./mode-table-list";
|
|
||||||
import get from "lodash.get";
|
|
||||||
import set from "lodash.set";
|
|
||||||
|
|
||||||
export const generateTableList = async (
|
|
||||||
modify: (data: any) => void,
|
|
||||||
data: any,
|
|
||||||
item: PrasiItem,
|
|
||||||
arg: { mode: "table" | "list" | "grid" | "auto"; id_parent?: string },
|
|
||||||
commit: boolean
|
|
||||||
) => {
|
|
||||||
|
|
||||||
item.edit.setChilds([
|
|
||||||
{
|
|
||||||
type: "item",
|
|
||||||
name: "1",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "item",
|
|
||||||
name: "2",
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
await item.edit.commit();
|
|
||||||
// console.log({ data, item, arg });
|
|
||||||
// const table = data.gen_table.value as string;
|
|
||||||
// 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 result = {} as any;
|
|
||||||
// // generate value dari raw_field array string convert ke value selected prisma
|
|
||||||
// const res = generateSelect(fields);
|
|
||||||
// pk = res.pk;
|
|
||||||
// const select = res.select as any;
|
|
||||||
// const result: Record<string, PropVal> = {};
|
|
||||||
// if (arg.id_parent) {
|
|
||||||
// select[arg.id_parent] = true;
|
|
||||||
// }
|
|
||||||
// if (!pk) {
|
|
||||||
// alert("Failed to generate! Primary Key not found. ");
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// let childs = [] as any;
|
|
||||||
// if (pk) {
|
|
||||||
// let sub_name = modeTableList(arg.mode);
|
|
||||||
// let rows = Array.isArray(get(data, "child.content.childs"))
|
|
||||||
// ? get(data, "child.content.childs")
|
|
||||||
// : Array.isArray(get(data, "child.childs"))
|
|
||||||
// ? get(data, "child.childs")
|
|
||||||
// : [];
|
|
||||||
|
|
||||||
// rows = rows.filter((e: PrasiItem) => e.name !== sub_name);
|
|
||||||
// childs = childs.concat(rows);
|
|
||||||
|
|
||||||
// if (data["on_load"]) {
|
|
||||||
// result.on_load = {
|
|
||||||
// mode: "raw",
|
|
||||||
// value: on_load({ pk, table, select, pks }),
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
// let first = true;
|
|
||||||
|
|
||||||
// const child_sub_name = createItem({
|
|
||||||
// name: sub_name,
|
|
||||||
// childs: fields
|
|
||||||
// .map((e, idx) => {
|
|
||||||
// if (idx >= 1 && arg.mode === "list") {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// if (e.is_pk && arg.mode === "table") return;
|
|
||||||
// let tree_depth = "";
|
|
||||||
// let tree_depth_built = "";
|
|
||||||
// if (first) {
|
|
||||||
// tree_depth = `tree_depth={col.depth}`;
|
|
||||||
// tree_depth_built = `tree_depth:col.depth`;
|
|
||||||
// first = false;
|
|
||||||
// }
|
|
||||||
// return {
|
|
||||||
// component: {
|
|
||||||
// id: "297023a4-d552-464a-971d-f40dcd940b77",
|
|
||||||
// props: {
|
|
||||||
// name: e.name,
|
|
||||||
// title: formatName(e.name),
|
|
||||||
// child: createItem({
|
|
||||||
// childs: [
|
|
||||||
// createItem({
|
|
||||||
// name: "cell",
|
|
||||||
// padding: {
|
|
||||||
// l: 8,
|
|
||||||
// b: 0,
|
|
||||||
// t: 0,
|
|
||||||
// r: 8,
|
|
||||||
// },
|
|
||||||
// adv: {
|
|
||||||
// js: `\
|
|
||||||
// <div {...props} className={cx(props.className, "")}>
|
|
||||||
// <FormatValue value={col.value} name={col.name} gen_fields={gen_fields} ${tree_depth} />
|
|
||||||
// </div>`,
|
|
||||||
// jsBuilt: `\
|
|
||||||
// render(React.createElement("div", Object.assign({}, props, { className: cx(props.className, "") }),React.createElement(FormatValue, { value: col.value, name: col.name, gen_fields: gen_fields, ${tree_depth_built} })));
|
|
||||||
// `,
|
|
||||||
// },
|
|
||||||
// }),
|
|
||||||
// ],
|
|
||||||
// }),
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// };
|
|
||||||
// })
|
|
||||||
// .filter((e) => e) as any,
|
|
||||||
// });
|
|
||||||
// childs.push(child_sub_name);
|
|
||||||
|
|
||||||
// // result.child = {
|
|
||||||
// // mode: "jsx",
|
|
||||||
// // value: createItem({ name: "child", childs: [child] }),
|
|
||||||
// // };
|
|
||||||
// // item.edit.setChilds([child]);
|
|
||||||
|
|
||||||
// if (commit) {
|
|
||||||
// Object.keys(result).map((e) => {
|
|
||||||
// item.edit.setProp(e, result[e]);
|
|
||||||
// });
|
|
||||||
// console.log({ childs });
|
|
||||||
// item.edit.setChilds([
|
|
||||||
// {
|
|
||||||
// name: sub_name,
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// name: "123",
|
|
||||||
// },
|
|
||||||
// ]);
|
|
||||||
// await item.edit.commit();
|
|
||||||
// } else {
|
|
||||||
// set(item, "childs", childs);
|
|
||||||
// Object.keys(result).map((e) => {
|
|
||||||
// set(data, e, result[e]);
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
// console.log({ res, item });
|
|
||||||
// console.log({ data });
|
|
||||||
// console.log({ result });
|
|
||||||
// }
|
|
||||||
// return;
|
|
||||||
// if (pk) {
|
|
||||||
// console.log("pk");
|
|
||||||
// const code = {} as any;
|
|
||||||
// if (data["on_load"]) {
|
|
||||||
// result["on_load"] = data["on_load"];
|
|
||||||
// result["on_load"].value = on_load({ pk, table, select, pks });
|
|
||||||
// delete result["on_load"].valueBuilt;
|
|
||||||
// code.on_load = result["on_load"].value;
|
|
||||||
// }
|
|
||||||
// let sub_name = "fields";
|
|
||||||
// switch (arg.mode) {
|
|
||||||
// case "table":
|
|
||||||
// sub_name = "tbl-col";
|
|
||||||
// break;
|
|
||||||
// case "list":
|
|
||||||
// sub_name = "md-list";
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// let first = true;
|
|
||||||
// console.log(sub_name);
|
|
||||||
// const child = {
|
|
||||||
// name: sub_name,
|
|
||||||
// childs: fields
|
|
||||||
// .map((e, idx) => {
|
|
||||||
// if (idx >= 1 && arg.mode === "list") {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// if (e.is_pk && arg.mode === "table") return;
|
|
||||||
// let tree_depth = "";
|
|
||||||
// let tree_depth_built = "";
|
|
||||||
// if (first) {
|
|
||||||
// tree_depth = `tree_depth={col.depth}`;
|
|
||||||
// tree_depth_built = `tree_depth:col.depth`;
|
|
||||||
// first = false;
|
|
||||||
// }
|
|
||||||
// return {
|
|
||||||
// component: {
|
|
||||||
// id: "297023a4-d552-464a-971d-f40dcd940b77",
|
|
||||||
// props: {
|
|
||||||
// name: {
|
|
||||||
// mode: "string",
|
|
||||||
// value: e.name
|
|
||||||
// },
|
|
||||||
// title: {
|
|
||||||
// mode: "string",
|
|
||||||
// value: formatName(e.name)
|
|
||||||
// },
|
|
||||||
// child: createItem({
|
|
||||||
// childs: [
|
|
||||||
// createItem({
|
|
||||||
// name: "cell",
|
|
||||||
// padding: {
|
|
||||||
// l: 8,
|
|
||||||
// b: 0,
|
|
||||||
// t: 0,
|
|
||||||
// r: 8,
|
|
||||||
// },
|
|
||||||
// adv: {
|
|
||||||
// js: `\
|
|
||||||
// <div {...props} className={cx(props.className, "")}>
|
|
||||||
// <FormatValue value={col.value} name={col.name} gen_fields={gen_fields} ${tree_depth} />
|
|
||||||
// </div>`,
|
|
||||||
// jsBuilt: `\
|
|
||||||
// render(React.createElement("div", Object.assign({}, props, { className: cx(props.className, "") }),React.createElement(FormatValue, { value: col.value, name: col.name, gen_fields: gen_fields, ${tree_depth_built} })));
|
|
||||||
// `,
|
|
||||||
// },
|
|
||||||
// }),
|
|
||||||
// ],
|
|
||||||
// }),
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// };
|
|
||||||
// })
|
|
||||||
// .filter((e) => e) as any,
|
|
||||||
// };
|
|
||||||
// data.child.value = child;
|
|
||||||
// result["child"] = data.child
|
|
||||||
// }
|
|
||||||
// modify(result);
|
|
||||||
// console.log({ child: data["child"] });
|
|
||||||
};
|
|
||||||
|
|
||||||
const formatName = (name: string) => {
|
|
||||||
return name
|
|
||||||
.split("_")
|
|
||||||
.filter((e) => e.length > 1)
|
|
||||||
.map((e) => capitalize(e))
|
|
||||||
.join(" ");
|
|
||||||
};
|
|
||||||
|
|
@ -0,0 +1,85 @@
|
||||||
|
import { GFCol } from "lib/gen/utils";
|
||||||
|
|
||||||
|
|
||||||
|
export const on_submit = ({
|
||||||
|
pk,
|
||||||
|
table,
|
||||||
|
select,
|
||||||
|
pks,
|
||||||
|
}: {
|
||||||
|
pk: string;
|
||||||
|
table: string;
|
||||||
|
select: any;
|
||||||
|
pks: Record<string, string>;
|
||||||
|
}) => {
|
||||||
|
const id = pk;
|
||||||
|
|
||||||
|
return `\
|
||||||
|
async ({ form, error }: IForm) => {
|
||||||
|
if (typeof form !== "object") return false;
|
||||||
|
if (typeof error === "object" && Object.keys(error).length > 0) return false;
|
||||||
|
|
||||||
|
let original_actions = [];
|
||||||
|
if (typeof md === "object") {
|
||||||
|
original_actions = md.actions;
|
||||||
|
md.actions = [{ label: <>...</> }];
|
||||||
|
md.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = false;
|
||||||
|
try {
|
||||||
|
const data = { ...form };
|
||||||
|
delete data.${id};
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
const pks = ${JSON.stringify(pks)};
|
||||||
|
for (const [k, v] of Object.entries(pks)) {
|
||||||
|
if (typeof data[k] === 'object') {
|
||||||
|
if (data[k] === null) {
|
||||||
|
data[k] = {
|
||||||
|
disconnect: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (data[k][v]) {
|
||||||
|
data[k] = {
|
||||||
|
connect: {
|
||||||
|
[v]: data[k][v]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (form.${id}) {
|
||||||
|
await db.${table}.update({
|
||||||
|
where: {
|
||||||
|
${id}: form.${id},
|
||||||
|
},
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const res = await db.${table}.create({
|
||||||
|
data,
|
||||||
|
select: { ${id}: true },
|
||||||
|
});
|
||||||
|
if (res) form.${id} = res.${id};
|
||||||
|
}
|
||||||
|
|
||||||
|
result = true;
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof md === "object") {
|
||||||
|
md.actions = original_actions;
|
||||||
|
md.selected = null;
|
||||||
|
md.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
type IForm = { form: any; error: Record<string, string> }`;
|
||||||
|
};
|
||||||
|
|
@ -38,7 +38,18 @@ export const MDMaster: FC<{ md: MDLocal; mdr: MDRef }> = ({ md, mdr }) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{md.props.show_head === "only-master" && <MDHeader md={md} mdr={mdr} />}
|
{md.props.show_head === "only-master" && <MDHeader md={md} mdr={mdr} />}
|
||||||
<PassProp md={md}>{mdr.master}</PassProp>
|
<div
|
||||||
|
className={cx(
|
||||||
|
css`
|
||||||
|
> div {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
"c-flex c-flex-1"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<PassProp md={md}>{mdr.master}</PassProp>
|
||||||
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@ export const editorMDInit = (md: MDLocal, mdr: MDRef, arg: MDProps) => {
|
||||||
md.props.gen_table = gen_table;
|
md.props.gen_table = gen_table;
|
||||||
md.props.on_init = on_init;
|
md.props.on_init = on_init;
|
||||||
|
|
||||||
console.log(get(mdr, "master.edit.childs.0"));
|
|
||||||
if (!mdr.master || (mdr.master && !get(mdr, "master.edit.childs.0.childs.length"))) {
|
if (!mdr.master || (mdr.master && !get(mdr, "master.edit.childs.0.childs.length"))) {
|
||||||
md.breadcrumb = [
|
md.breadcrumb = [
|
||||||
{
|
{
|
||||||
|
|
|
||||||
10
exports.ts
10
exports.ts
|
|
@ -34,13 +34,18 @@ export const ExportExcel = lazify(
|
||||||
|
|
||||||
/** Filter */
|
/** Filter */
|
||||||
export const MasterFilter = lazify(
|
export const MasterFilter = lazify(
|
||||||
async () => (await import("@/comps/filter/Filter")).MasterFilter
|
async () => (await import("@/comps/filter/MasterFilter")).MasterFilter
|
||||||
|
);
|
||||||
|
|
||||||
|
export const FilterField = lazify(
|
||||||
|
async () => (await import("@/comps/filter/FilterField")).FilterField
|
||||||
);
|
);
|
||||||
|
|
||||||
/** Generator */
|
/** Generator */
|
||||||
export { generateMasterDetail } from "lib/comps/md/gen/md-gen";
|
export { generateMasterDetail } from "lib/comps/md/gen/md-gen";
|
||||||
|
|
||||||
/** ETC */
|
/** ETC */
|
||||||
|
export { filterWhere } from "@/comps/filter/utils/filter-where";
|
||||||
export {
|
export {
|
||||||
FMLocal,
|
FMLocal,
|
||||||
FieldTypeCustom,
|
FieldTypeCustom,
|
||||||
|
|
@ -54,7 +59,8 @@ export { TableListType } from "lib/comps/list/utils/typings";
|
||||||
export { Button, FloatButton } from "@/comps/ui/button";
|
export { Button, FloatButton } from "@/comps/ui/button";
|
||||||
export { prasi_gen } from "@/gen/prasi_gen";
|
export { prasi_gen } from "@/gen/prasi_gen";
|
||||||
export { password } from "@/utils/password";
|
export { password } from "@/utils/password";
|
||||||
export {generateTableList} from "@/comps/md/gen/md-table-list"
|
export { generateTableList } from "@/comps/md/gen/gen-table-list";
|
||||||
|
export { generateForm } from "@/comps/md/gen/gen-form";
|
||||||
|
|
||||||
/** Session */
|
/** Session */
|
||||||
export {
|
export {
|
||||||
|
|
|
||||||
|
|
@ -10,11 +10,13 @@ export const parseGenField = (fields: PropOptRaw) => {
|
||||||
if (typeof f === "string") {
|
if (typeof f === "string") {
|
||||||
try {
|
try {
|
||||||
const field = JSON.parse(f);
|
const field = JSON.parse(f);
|
||||||
|
field["value"] = f
|
||||||
result.push(field);
|
result.push(field);
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
} else {
|
} else {
|
||||||
const field = JSON.parse(f.value);
|
const field = JSON.parse(f.value);
|
||||||
field.relation.fields = parseGenField(f.checked);
|
field.relation.fields = parseGenField(f.checked);
|
||||||
|
field["value"] = f
|
||||||
result.push(field);
|
result.push(field);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -46,6 +48,7 @@ export type GFCol = {
|
||||||
to: { table: string; fields: string[] };
|
to: { table: string; fields: string[] };
|
||||||
fields: GFCol[];
|
fields: GFCol[];
|
||||||
};
|
};
|
||||||
|
value: Array<string> | string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const formatName = (name: string) => {
|
export const formatName = (name: string) => {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import { FC } from "react";
|
import { FC } from "react";
|
||||||
|
import { prasi_user } from "./utils/user";
|
||||||
|
|
||||||
const w = window as unknown as {
|
const w = window as unknown as {
|
||||||
prasi_home: Record<string, string>;
|
prasi_home: Record<string, string>;
|
||||||
|
|
@ -7,11 +8,15 @@ const w = window as unknown as {
|
||||||
export type LGProps = {
|
export type LGProps = {
|
||||||
salt: string;
|
salt: string;
|
||||||
url_home: Array<Record<string, string>>;
|
url_home: Array<Record<string, string>>;
|
||||||
body: any
|
body: any;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Login: FC<LGProps> = (props) => {
|
export const Login: FC<LGProps> = (props) => {
|
||||||
w.prasi_home = props.url_home[0];
|
w.prasi_home = props.url_home[0];
|
||||||
console.log(w.prasi_home)
|
try {
|
||||||
|
const home = prasi_user.prasi_home[prasi_user.user.m_role.name];
|
||||||
|
navigate(home);
|
||||||
|
} catch (e: any) {
|
||||||
|
}
|
||||||
return <>{props.body}</>;
|
return <>{props.body}</>;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ export const prasi_user = window as unknown as {
|
||||||
user: {
|
user: {
|
||||||
id: string;
|
id: string;
|
||||||
username: string;
|
username: string;
|
||||||
|
name: string;
|
||||||
|
fullname: string;
|
||||||
m_role: {
|
m_role: {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
|
|
|
||||||
|
|
@ -62,12 +62,12 @@ export const Layout: FC<LYTChild> = (props) => {
|
||||||
fn();
|
fn();
|
||||||
const path = getPathname();
|
const path = getPathname();
|
||||||
const no_layout = props.exception;
|
const no_layout = props.exception;
|
||||||
|
loadSession("/auth/login");
|
||||||
if (Array.isArray(no_layout))
|
if (Array.isArray(no_layout))
|
||||||
if (no_layout.length) {
|
if (no_layout.length) {
|
||||||
if (no_layout.includes(path)) {
|
if (no_layout.includes(path)) {
|
||||||
return <>{props.defaultLayout}</>;
|
return <>{props.defaultLayout}</>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
loadSession("/dev/auth");
|
|
||||||
return <>{props.children}</>;
|
return <>{props.children}</>;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -22,13 +22,13 @@ export const FormatValue: FC<{
|
||||||
return {
|
return {
|
||||||
...JSON.parse(e.value),
|
...JSON.parse(e.value),
|
||||||
checked: e.checked.map((ex: any) => {
|
checked: e.checked.map((ex: any) => {
|
||||||
if(typeof ex === "string"){
|
if (typeof ex === "string") {
|
||||||
return JSON.parse(e.value)
|
return JSON.parse(e.value);
|
||||||
}
|
}
|
||||||
try{
|
try {
|
||||||
return JSON.parse(ex["value"]);
|
return JSON.parse(ex["value"]);
|
||||||
}catch(em){
|
} catch (em) {
|
||||||
return null
|
return null;
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
@ -42,19 +42,20 @@ export const FormatValue: FC<{
|
||||||
if (typeof value === "object" && value) {
|
if (typeof value === "object" && value) {
|
||||||
const rel = fields?.find((e) => e.name === name);
|
const rel = fields?.find((e) => e.name === name);
|
||||||
if (rel && rel.checked) {
|
if (rel && rel.checked) {
|
||||||
const result = rel.checked
|
|
||||||
.filter((e) => !e.is_pk)
|
if (rel.type === "has-one") {
|
||||||
.map((e) => {
|
const result = [];
|
||||||
return value[e.name];
|
for (const [k,v] of Object.entries(value) as any ) {
|
||||||
})
|
if (!k.toLowerCase().includes('id')) result.push(v);
|
||||||
.join(" - ");
|
}
|
||||||
|
return result.join(' - ');
|
||||||
|
}
|
||||||
|
|
||||||
if (Array.isArray(value)) {
|
if (Array.isArray(value)) {
|
||||||
const len = value.length;
|
const len = value.length;
|
||||||
if (len === 0) return ` - `;
|
if (len === 0) return ` - `;
|
||||||
return `${len} item${len > 1 ? "s" : ""}`;
|
return `${len} item${len > 1 ? "s" : ""}`;
|
||||||
}
|
}
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return JSON.stringify(value);
|
return JSON.stringify(value);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
import { GFCol } from "lib/gen/utils";
|
||||||
|
|
||||||
|
export const parseGenFields = (gen_fields: any) => {
|
||||||
|
const fields_map = new Map<string, (GFCol & { checked?: GFCol[] })[]>();
|
||||||
|
if (gen_fields) {
|
||||||
|
const gf = JSON.stringify(gen_fields);
|
||||||
|
if (!fields_map.has(gf)) {
|
||||||
|
fields_map.set(
|
||||||
|
gf,
|
||||||
|
gen_fields.map((e: any) => {
|
||||||
|
if (typeof e === "string") {
|
||||||
|
return JSON.parse(e);
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
...JSON.parse(e.value),
|
||||||
|
checked: e.checked.map((ex: any) => {
|
||||||
|
if (typeof ex === "string") {
|
||||||
|
return JSON.parse(e.value);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return JSON.parse(ex["value"]);
|
||||||
|
} catch (em) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fields_map;
|
||||||
|
};
|
||||||
Loading…
Reference in New Issue