Skip to content
Snippets Groups Projects
Commit 7bb7838b authored by Simon Künzel's avatar Simon Künzel
Browse files

Add JsonEditor

parent 8122c297
Branches
Tags
No related merge requests found
......@@ -166,7 +166,7 @@ export interface field_description {
has_default_value: boolean;
default_value?: any;
// type: object, datetime
// type: object, datetime, media_process
may_be_null?: boolean;
// type: enum
enums?: string[];
......
......@@ -2,6 +2,7 @@ import React, { useEffect, useRef, useState } from "react";
import type { int } from "@/videoag/api/types";
import { useLanguage } from "@/videoag/localization/LanguageProvider";
import { deepEquals } from "@/videoag/miscellaneous/Util";
export type EditorArgs = {
value?: any;
......@@ -348,3 +349,82 @@ export function ChooserEditor({
</select>
);
}
export function JsonEditor({
value,
updateValue,
disabled,
autoFocus,
hideErrors,
allowUndefined,
undefinedAsNull,
}: EditorArgs & {
allowUndefined?: boolean;
undefinedAsNull?: boolean;
}) {
// We need to store the default value locally to enable smooth editing. If the input is partially invalid, we just
// get nothing and setting that back as the value will cause the whole input to reset
const knownValue = useRef<any>(undefined);
const [stringValue, setStringValue] = useState<string>("");
useEffect(() => {
if (deepEquals(value, knownValue.current)) return;
//Value was changed not by us, update internal state
knownValue.current = value;
let normValue = value;
if (undefinedAsNull && normValue === null) {
normValue = undefined;
}
if (allowUndefined && normValue === undefined) {
setStringValue("");
} else {
setStringValue(JSON.stringify(normValue, null, " "));
}
}, [knownValue, value, allowUndefined, undefinedAsNull]);
const getJsonParseResults = (stringValue: string) => {
let json;
let isValid;
let errorMsg = undefined;
if (stringValue === "" && allowUndefined === true) {
isValid = true;
json = undefinedAsNull ? null : undefined;
} else {
try {
json = JSON.parse(stringValue);
isValid = true;
} catch (e: any) {
json = undefined;
isValid = false;
errorMsg = e.toString();
}
}
return [json, isValid, errorMsg];
};
const update = (val: any, affectNow: boolean) => {
setStringValue(val);
const [json, isValid, errorMsg] = getJsonParseResults(val);
knownValue.current = json;
updateValue(json, isValid, affectNow);
};
const [json, isValid, errorMsg] = getJsonParseResults(stringValue);
return (
<div className="d-inline-grid w-100">
<textarea
className={
"form-control w-100 " + (isValid || hideErrors === true ? "" : "is-invalid")
}
style={{ minHeight: "6em" }}
value={stringValue ?? ""}
onChange={(e) => update(e.target.value, false)}
disabled={disabled}
autoFocus={autoFocus}
/>
{errorMsg && (
<span className="d-inline invalid-feedback">Invalid JSON: {errorMsg}</span>
)}
</div>
);
}
......@@ -8,6 +8,7 @@ import {
IntEditor,
DatetimeEditor,
ChooserEditor,
JsonEditor,
} from "@/videoag/form/TypeEditor";
import { UserIdListEditor } from "./ObjectEditor";
......@@ -73,7 +74,15 @@ export function OMFieldEditor({
</span>
);
// TODO media_process
case "media_process":
return (
<JsonEditor
{...args}
allowUndefined={description.may_be_null}
undefinedAsNull={true}
/>
);
// TODO object
default:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment