mirror of
https://github.com/shishantbiswas/bknd.git
synced 2026-03-16 04:27:21 +00:00
fix json field
This commit is contained in:
@@ -64,17 +64,20 @@ export class JsonField<Required extends true | false = false, TypeOverride = obj
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override isValid(value: any): boolean {
|
||||||
|
return this.isSerializable(value);
|
||||||
|
}
|
||||||
|
|
||||||
override getValue(value: any, context: TRenderContext): any {
|
override getValue(value: any, context: TRenderContext): any {
|
||||||
switch (context) {
|
switch (context) {
|
||||||
case "form":
|
|
||||||
if (value === null) return "";
|
|
||||||
return JSON.stringify(value, null, 2);
|
|
||||||
case "table":
|
case "table":
|
||||||
if (value === null) return null;
|
if (value === null) return null;
|
||||||
return JSON.stringify(value);
|
return JSON.stringify(value);
|
||||||
case "submit":
|
case "submit":
|
||||||
if (typeof value === "string" && value.length === 0) {
|
if (!value || (typeof value === "string" && value.length === 0)) {
|
||||||
return null;
|
return null;
|
||||||
|
} else if (typeof value === "object") {
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
return JSON.parse(value);
|
return JSON.parse(value);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Suspense, lazy, useState } from "react";
|
import { Suspense, lazy, useEffect, useState } from "react";
|
||||||
import { twMerge } from "tailwind-merge";
|
import { twMerge } from "tailwind-merge";
|
||||||
import type { CodeEditorProps } from "./CodeEditor";
|
import type { CodeEditorProps } from "./CodeEditor";
|
||||||
import { useDebouncedCallback } from "@mantine/hooks";
|
import { useDebouncedCallback } from "@mantine/hooks";
|
||||||
@@ -7,7 +7,8 @@ const CodeEditor = lazy(() => import("./CodeEditor"));
|
|||||||
export type JsonEditorProps = Omit<CodeEditorProps, "value" | "onChange"> & {
|
export type JsonEditorProps = Omit<CodeEditorProps, "value" | "onChange"> & {
|
||||||
value?: object;
|
value?: object;
|
||||||
onChange?: (value: object) => void;
|
onChange?: (value: object) => void;
|
||||||
emptyAs?: "null" | "undefined";
|
emptyAs?: any;
|
||||||
|
onInvalid?: (error: Error) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function JsonEditor({
|
export function JsonEditor({
|
||||||
@@ -16,29 +17,45 @@ export function JsonEditor({
|
|||||||
value,
|
value,
|
||||||
onChange,
|
onChange,
|
||||||
onBlur,
|
onBlur,
|
||||||
emptyAs = "undefined",
|
emptyAs = undefined,
|
||||||
|
onInvalid,
|
||||||
...props
|
...props
|
||||||
}: JsonEditorProps) {
|
}: JsonEditorProps) {
|
||||||
const [editorValue, setEditorValue] = useState<string | null | undefined>(
|
const [editorValue, setEditorValue] = useState<string | null | undefined>(
|
||||||
JSON.stringify(value, null, 2),
|
value ? JSON.stringify(value, null, 2) : emptyAs,
|
||||||
);
|
);
|
||||||
|
const [error, setError] = useState<boolean>(false);
|
||||||
const handleChange = useDebouncedCallback((given: string) => {
|
const handleChange = useDebouncedCallback((given: string) => {
|
||||||
const value = given === "" ? (emptyAs === "null" ? null : undefined) : given;
|
|
||||||
try {
|
try {
|
||||||
setEditorValue(value);
|
setError(false);
|
||||||
onChange?.(value ? JSON.parse(value) : value);
|
onChange?.(given ? JSON.parse(given) : emptyAs);
|
||||||
} catch (e) {}
|
} catch (e) {
|
||||||
}, 500);
|
onInvalid?.(e as Error);
|
||||||
|
setError(true);
|
||||||
|
}
|
||||||
|
}, 250);
|
||||||
const handleBlur = (e) => {
|
const handleBlur = (e) => {
|
||||||
setEditorValue(JSON.stringify(value, null, 2));
|
try {
|
||||||
|
const formatted = JSON.stringify(value, null, 2);
|
||||||
|
setEditorValue(formatted);
|
||||||
|
} catch (e) {}
|
||||||
|
|
||||||
onBlur?.(e);
|
onBlur?.(e);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!editorValue) {
|
||||||
|
setEditorValue(value ? JSON.stringify(value, null, 2) : emptyAs);
|
||||||
|
}
|
||||||
|
}, [value]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Suspense fallback={null}>
|
<Suspense fallback={null}>
|
||||||
<CodeEditor
|
<CodeEditor
|
||||||
className={twMerge(
|
className={twMerge(
|
||||||
"flex w-full border border-muted",
|
"flex w-full border border-muted",
|
||||||
!editable && "opacity-70",
|
!editable && "opacity-70",
|
||||||
|
error && "border-red-500",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
editable={editable}
|
editable={editable}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import type { FieldApi, ReactFormExtendedApi } from "@tanstack/react-form";
|
|||||||
import type { JSX } from "react";
|
import type { JSX } from "react";
|
||||||
import { useStore } from "@tanstack/react-store";
|
import { useStore } from "@tanstack/react-store";
|
||||||
import { MediaField } from "media/MediaField";
|
import { MediaField } from "media/MediaField";
|
||||||
import { type ComponentProps, Suspense } from "react";
|
import { type ComponentProps, Suspense, useState } from "react";
|
||||||
import { JsonEditor } from "ui/components/code/JsonEditor";
|
import { JsonEditor } from "ui/components/code/JsonEditor";
|
||||||
import * as Formy from "ui/components/form/Formy";
|
import * as Formy from "ui/components/form/Formy";
|
||||||
import { FieldLabel } from "ui/components/form/Formy";
|
import { FieldLabel } from "ui/components/form/Formy";
|
||||||
@@ -287,12 +287,14 @@ function EntityJsonFormField({
|
|||||||
field,
|
field,
|
||||||
...props
|
...props
|
||||||
}: { fieldApi: TFieldApi; field: JsonField }) {
|
}: { fieldApi: TFieldApi; field: JsonField }) {
|
||||||
|
const [error, setError] = useState<any>(null);
|
||||||
const handleUpdate = useEvent((value: any) => {
|
const handleUpdate = useEvent((value: any) => {
|
||||||
|
setError(null);
|
||||||
fieldApi.handleChange(value);
|
fieldApi.handleChange(value);
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Formy.Group>
|
<Formy.Group error={!!error}>
|
||||||
<Formy.FieldLabel htmlFor={fieldApi.name} field={field} />
|
<Formy.FieldLabel htmlFor={fieldApi.name} field={field} />
|
||||||
<Suspense>
|
<Suspense>
|
||||||
<JsonEditor
|
<JsonEditor
|
||||||
@@ -300,6 +302,7 @@ function EntityJsonFormField({
|
|||||||
value={fieldApi.state.value}
|
value={fieldApi.state.value}
|
||||||
onChange={handleUpdate}
|
onChange={handleUpdate}
|
||||||
onBlur={fieldApi.handleBlur}
|
onBlur={fieldApi.handleBlur}
|
||||||
|
onInvalid={setError}
|
||||||
minHeight="100"
|
minHeight="100"
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user