fix
This commit is contained in:
parent
9cde4fb165
commit
ad557ca5c0
|
|
@ -32,6 +32,11 @@ export const Form: FC<FMProps> = (props) => {
|
|||
promises: [],
|
||||
done: [],
|
||||
},
|
||||
submit: {
|
||||
timeout: null as any,
|
||||
promises: [],
|
||||
done: [],
|
||||
},
|
||||
},
|
||||
field_def: {},
|
||||
props: {} as any,
|
||||
|
|
@ -90,11 +95,6 @@ export const Form: FC<FMProps> = (props) => {
|
|||
}
|
||||
const toaster_el = document.getElementsByClassName("prasi-toaster")[0];
|
||||
|
||||
const childs = get(
|
||||
body,
|
||||
"props.meta.item.component.props.body.content.childs"
|
||||
) as any[];
|
||||
|
||||
return (
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
|
|
|
|||
|
|
@ -7,20 +7,47 @@ export const TypeCustom: FC<{ field: FieldLocal; fm: FMLocal }> = ({
|
|||
field,
|
||||
fm,
|
||||
}) => {
|
||||
const local = useLocal({ custom: null as any }, async () => {
|
||||
if (field.custom) {
|
||||
local.custom = await field.custom();
|
||||
local.render();
|
||||
}
|
||||
const local = useLocal({
|
||||
custom: null as any,
|
||||
exec: false,
|
||||
result: null as any,
|
||||
});
|
||||
|
||||
if (!local.custom && field.custom) {
|
||||
console.log("field", field.custom);
|
||||
local.custom = field.custom;
|
||||
}
|
||||
|
||||
if (!local.exec) {
|
||||
local.exec = true;
|
||||
const callback = (value: any, should_render: boolean) => {
|
||||
local.result = value;
|
||||
if (should_render) {
|
||||
local.render();
|
||||
setTimeout(() => {
|
||||
local.exec = false;
|
||||
}, 100);
|
||||
}
|
||||
};
|
||||
if (field.custom) {
|
||||
const res = local.custom();
|
||||
if (res instanceof Promise) {
|
||||
res.then((value) => {
|
||||
callback(value, true);
|
||||
});
|
||||
} else {
|
||||
callback(res, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let el = null as any;
|
||||
if (local.custom) {
|
||||
if (isValidElement(local.custom)) {
|
||||
el = local.custom;
|
||||
if (local.result) {
|
||||
if (isValidElement(local.result)) {
|
||||
el = local.result;
|
||||
} else {
|
||||
if (local.custom.field === "text") {
|
||||
el = <FieldTypeText field={field} fm={fm} prop={local.custom} />;
|
||||
if (local.result.field === "text") {
|
||||
el = <FieldTypeText field={field} fm={fm} prop={local.result} />;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,21 +1,34 @@
|
|||
import { FC } from "react";
|
||||
import { FMLocal, FieldLocal } from "../../typings";
|
||||
import { useLocal } from "@/utils/use-local";
|
||||
import parser from "any-date-parser";
|
||||
|
||||
export type PropTypeText = {
|
||||
type: "text" | "password" | "number";
|
||||
type: "text" | "password" | "number" | "date" | "datetime";
|
||||
};
|
||||
|
||||
const parse = parser.exportAsFunctionAny("en-US");
|
||||
|
||||
export const FieldTypeText: FC<{
|
||||
field: FieldLocal;
|
||||
fm: FMLocal;
|
||||
prop: PropTypeText;
|
||||
}> = ({ field, fm, prop }) => {
|
||||
const input = useLocal({});
|
||||
const value = fm.data[field.name];
|
||||
let value: any = fm.data[field.name];
|
||||
field.input = input;
|
||||
field.prop = prop;
|
||||
|
||||
if (["date", "datetime"].includes(prop.type)) {
|
||||
if (typeof value === "string") {
|
||||
let date = parse(value);
|
||||
if (typeof date === "object" && date instanceof Date) {
|
||||
if (prop.type === "date") value = date.toISOString().substring(0, 10);
|
||||
else if (prop.type === "datetime") value = date.toISOString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<input
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ export type FMInternal = {
|
|||
status: "init" | "resizing" | "loading" | "saving" | "ready";
|
||||
data: any;
|
||||
reload: () => Promise<void>;
|
||||
submit: () => Promise<void>;
|
||||
submit: () => Promise<boolean>;
|
||||
events: {
|
||||
on_change: (name: string, new_value: any) => void;
|
||||
};
|
||||
|
|
@ -82,6 +82,11 @@ export type FMInternal = {
|
|||
promises: Promise<void>[];
|
||||
done: any[];
|
||||
};
|
||||
submit: {
|
||||
promises: Promise<boolean>[];
|
||||
timeout: ReturnType<typeof setTimeout>;
|
||||
done: any[];
|
||||
};
|
||||
};
|
||||
props: Exclude<FMProps, "body" | "PassProp">;
|
||||
size: {
|
||||
|
|
@ -204,6 +209,6 @@ export type CustomField =
|
|||
| { field: "relation"; type: "has-many" | "has-one" };
|
||||
|
||||
export const FieldTypeCustom = `type CustomField =
|
||||
{ field: "text", type: "text" | "password" | "number" }
|
||||
{ field: "text", type: "text" | "password" | "number" | "date" | "datetime" }
|
||||
| { field: "relation", type: "has-many" | "has-one" }
|
||||
`;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { parseGenField } from "@/gen/utils";
|
||||
import get from "lodash.get";
|
||||
import { Loader2 } from "lucide-react";
|
||||
import { AlertTriangle, Check, Loader2 } from "lucide-react";
|
||||
import { toast } from "sonner";
|
||||
import { FMLocal, FMProps } from "../typings";
|
||||
import { editorFormData } from "./ed-data";
|
||||
|
|
@ -89,10 +89,77 @@ export const formInit = (fm: FMLocal, props: FMProps) => {
|
|||
return promise;
|
||||
};
|
||||
|
||||
fm.submit = async () => {
|
||||
if (typeof fm.props.on_submit === "function") {
|
||||
fm.props.on_submit({ fm, form: fm.data, error: fm.error.object });
|
||||
}
|
||||
fm.submit = () => {
|
||||
const promise = new Promise<boolean>(async (done) => {
|
||||
fm.internal.submit.done.push(done);
|
||||
clearTimeout(fm.internal.submit.timeout);
|
||||
fm.internal.submit.timeout = setTimeout(async () => {
|
||||
const done_all = (val: boolean) => {
|
||||
for (const d of fm.internal.submit.done) {
|
||||
d(val);
|
||||
}
|
||||
fm.internal.submit.done = [];
|
||||
fm.render();
|
||||
};
|
||||
|
||||
if (typeof fm.props.on_submit === "function") {
|
||||
if (fm.props.sonar === "on") {
|
||||
toast.loading(
|
||||
<>
|
||||
<Loader2 className="c-h-4 c-w-4 c-animate-spin" />
|
||||
Submitting...
|
||||
</>
|
||||
);
|
||||
}
|
||||
const success = await fm.props.on_submit({
|
||||
fm,
|
||||
form: fm.data,
|
||||
error: fm.error.object,
|
||||
});
|
||||
|
||||
toast.dismiss();
|
||||
done_all(success);
|
||||
if (fm.props.sonar === "on") {
|
||||
setTimeout(() => {
|
||||
toast.dismiss();
|
||||
|
||||
if (!success) {
|
||||
toast.error(
|
||||
<div className="c-flex c-text-red-600 c-items-center">
|
||||
<AlertTriangle className="c-h-4 c-w-4 c-mr-1" />
|
||||
Save Failed, please correct{" "}
|
||||
{Object.keys(fm.error.list).length} errors.
|
||||
</div>,
|
||||
{
|
||||
dismissible: true,
|
||||
className: css`
|
||||
background: #ffecec;
|
||||
border: 2px solid red;
|
||||
`,
|
||||
}
|
||||
);
|
||||
} else {
|
||||
toast.success(
|
||||
<div className="c-flex c-text-green-700 c-items-center">
|
||||
<Check className="c-h-4 c-w-4 c-mr-1 " />
|
||||
Done
|
||||
</div>,
|
||||
{
|
||||
className: css`
|
||||
background: #e4ffed;
|
||||
border: 2px solid green;
|
||||
`,
|
||||
}
|
||||
);
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
fm.internal.submit.promises.push(promise);
|
||||
|
||||
return promise;
|
||||
};
|
||||
if (typeof fm.props.on_init === "function") {
|
||||
fm.props.on_init({ fm, submit: fm.submit, reload: fm.reload });
|
||||
|
|
|
|||
Loading…
Reference in New Issue