fix kv
This commit is contained in:
parent
8ec266d47c
commit
d14e07a1fc
|
|
@ -24,6 +24,7 @@ export const Form: FC<FMProps> = (props) => {
|
||||||
reload: async () => {
|
reload: async () => {
|
||||||
formReload(fm);
|
formReload(fm);
|
||||||
},
|
},
|
||||||
|
save_status: "init",
|
||||||
fields: {},
|
fields: {},
|
||||||
events: {
|
events: {
|
||||||
on_change(name: string, new_value: any) {},
|
on_change(name: string, new_value: any) {},
|
||||||
|
|
@ -81,7 +82,9 @@ export const Form: FC<FMProps> = (props) => {
|
||||||
fm.soft_delete.field = null;
|
fm.soft_delete.field = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const ref = useRef({
|
const ref = useRef({
|
||||||
el: null as null | HTMLFormElement,
|
el: null as null | HTMLFormElement,
|
||||||
rob: new ResizeObserver(([e]) => {
|
rob: new ResizeObserver(([e]) => {
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import { useField } from "../utils/use-field";
|
||||||
import { validate } from "../utils/validate";
|
import { validate } from "../utils/validate";
|
||||||
import { FieldInput } from "./FieldInput";
|
import { FieldInput } from "./FieldInput";
|
||||||
import { Label } from "./Label";
|
import { Label } from "./Label";
|
||||||
|
import { hashSum } from "lib/utils/hash-sum";
|
||||||
|
|
||||||
export const Field: FC<FieldProp> = (arg) => {
|
export const Field: FC<FieldProp> = (arg) => {
|
||||||
const showlabel = arg.show_label || "y";
|
const showlabel = arg.show_label || "y";
|
||||||
|
|
@ -19,7 +20,33 @@ export const Field: FC<FieldProp> = (arg) => {
|
||||||
const w = field.width;
|
const w = field.width;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (fm.save_status === "init" || fm.status !== "ready") return;
|
||||||
|
if (local.prev_val === undefined) {
|
||||||
|
if (typeof fm.data[name] === "object") {
|
||||||
|
const sfied = hashSum(fm.data[name]);
|
||||||
|
if (sfied !== local.prev_val) {
|
||||||
|
local.prev_val = sfied;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
local.prev_val = fm.data[name];
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (local.prev_val !== fm.data[name]) {
|
if (local.prev_val !== fm.data[name]) {
|
||||||
|
if (typeof fm.data[name] === "object") {
|
||||||
|
const sfied = hashSum(fm.data[name]);
|
||||||
|
if (sfied !== local.prev_val) {
|
||||||
|
local.prev_val = sfied;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
local.prev_val = fm.data[name];
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(!local.prev_val && fm.data[name]) ||
|
(!local.prev_val && fm.data[name]) ||
|
||||||
(local.prev_val && !fm.data[name])
|
(local.prev_val && !fm.data[name])
|
||||||
|
|
@ -30,6 +57,9 @@ export const Field: FC<FieldProp> = (arg) => {
|
||||||
if (arg.on_change) {
|
if (arg.on_change) {
|
||||||
arg.on_change({ value: fm.data[name], name, fm });
|
arg.on_change({ value: fm.data[name], name, fm });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fm.save_status = "unsaved";
|
||||||
|
|
||||||
if (!fm.events) {
|
if (!fm.events) {
|
||||||
fm.events = {
|
fm.events = {
|
||||||
on_change(name, new_value) {},
|
on_change(name, new_value) {},
|
||||||
|
|
|
||||||
|
|
@ -5,19 +5,30 @@ import { useEffect, useRef } from "react";
|
||||||
export const KeyValue = ({
|
export const KeyValue = ({
|
||||||
value,
|
value,
|
||||||
onChange,
|
onChange,
|
||||||
|
index,
|
||||||
}: {
|
}: {
|
||||||
value: any;
|
value: any;
|
||||||
onChange: (val: any) => void;
|
onChange: (val: any) => void;
|
||||||
|
index?: "preserve" | "auto-sort";
|
||||||
}) => {
|
}) => {
|
||||||
const local = useLocal({
|
const local = useLocal({
|
||||||
entries: Object.entries(value),
|
entries: [] as [string, string][],
|
||||||
new: { idx: -1, key: "", value: "" },
|
new: { idx: -1, key: "", value: "" },
|
||||||
});
|
});
|
||||||
const ref = useRef<HTMLDivElement>(null);
|
const ref = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
let entries: any[] = [];
|
||||||
|
if (index === "preserve") {
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
local.entries = value;
|
||||||
|
} else {
|
||||||
|
local.entries = Object.entries(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (local.entries.length > 0) {
|
if (local.entries.length > 0) {
|
||||||
Object.entries(value).forEach(([k, v], idx) => {
|
entries.forEach(([k, v], idx) => {
|
||||||
const found = local.entries.find((e) => {
|
const found = local.entries.find((e) => {
|
||||||
if (e[0] === k) return true;
|
if (e[0] === k) return true;
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -30,8 +41,9 @@ export const KeyValue = ({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
local.entries = Object.entries(value);
|
local.entries = entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
local.render();
|
local.render();
|
||||||
}, [value]);
|
}, [value]);
|
||||||
|
|
||||||
|
|
@ -87,7 +99,11 @@ export const KeyValue = ({
|
||||||
local.render();
|
local.render();
|
||||||
}}
|
}}
|
||||||
onBlur={() => {
|
onBlur={() => {
|
||||||
|
if (index === "preserve") {
|
||||||
|
onChange([...local.entries]);
|
||||||
|
} else {
|
||||||
onChange(reverseEntries(local.entries));
|
onChange(reverseEntries(local.entries));
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
|
@ -106,7 +122,11 @@ export const KeyValue = ({
|
||||||
local.new.key = "";
|
local.new.key = "";
|
||||||
local.new.value = "";
|
local.new.value = "";
|
||||||
local.render();
|
local.render();
|
||||||
|
if (index === "preserve") {
|
||||||
|
onChange([...local.entries]);
|
||||||
|
} else {
|
||||||
onChange(reverseEntries(local.entries));
|
onChange(reverseEntries(local.entries));
|
||||||
|
}
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
(
|
(
|
||||||
ref?.current?.querySelector(
|
ref?.current?.querySelector(
|
||||||
|
|
@ -186,7 +206,7 @@ const KVRow = ({
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
update(idx, k, e.currentTarget.value || "");
|
update(idx, k, e.currentTarget.value || "");
|
||||||
}}
|
}}
|
||||||
onKeyDown={(e) => {
|
onKeyUp={(e) => {
|
||||||
if (e.key === "Backspace" && !e.currentTarget.value) {
|
if (e.key === "Backspace" && !e.currentTarget.value) {
|
||||||
keyref.current?.focus();
|
keyref.current?.focus();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -217,6 +217,7 @@ export const FieldTypeInput: FC<{
|
||||||
case "key-value":
|
case "key-value":
|
||||||
return (
|
return (
|
||||||
<KeyValue
|
<KeyValue
|
||||||
|
index={field.prop.kv?.index}
|
||||||
value={
|
value={
|
||||||
Object.keys(fm.data[field.name] || {}).length === 0
|
Object.keys(fm.data[field.name] || {}).length === 0
|
||||||
? field.prop.kv?.default
|
? field.prop.kv?.default
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,8 @@ ${
|
||||||
data: v,
|
data: v,
|
||||||
fk: rel.fk,
|
fk: rel.fk,
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
record[k] = v;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
record[k] = v;
|
record[k] = v;
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ export type FieldProp = {
|
||||||
label: string;
|
label: string;
|
||||||
desc?: string;
|
desc?: string;
|
||||||
props?: any;
|
props?: any;
|
||||||
kv?: { default: any };
|
kv?: { default: any; index: "preserve" | "auto-sort" };
|
||||||
upload?: {
|
upload?: {
|
||||||
mode: "single-file" | "multi-file";
|
mode: "single-file" | "multi-file";
|
||||||
accept: string;
|
accept: string;
|
||||||
|
|
@ -137,6 +137,7 @@ export type FMInternal = {
|
||||||
events: {
|
events: {
|
||||||
on_change: (name: string, new_value: any) => void;
|
on_change: (name: string, new_value: any) => void;
|
||||||
};
|
};
|
||||||
|
save_status: "init" | "unsaved" | "saved";
|
||||||
fields: Record<string, FieldLocal>;
|
fields: Record<string, FieldLocal>;
|
||||||
field_def: Record<string, GFCol>;
|
field_def: Record<string, GFCol>;
|
||||||
error: {
|
error: {
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@ export const formInit = (fm: FMLocal, props: FMProps) => {
|
||||||
|
|
||||||
const toastSuccess = (opt: { addNewText: string }) => {
|
const toastSuccess = (opt: { addNewText: string }) => {
|
||||||
const md = fm.deps.md as MDLocal;
|
const md = fm.deps.md as MDLocal;
|
||||||
|
fm.save_status = "saved";
|
||||||
|
|
||||||
if (md) {
|
if (md) {
|
||||||
toast.success(
|
toast.success(
|
||||||
<div
|
<div
|
||||||
|
|
@ -184,6 +186,7 @@ export const formInit = (fm: FMLocal, props: FMProps) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
fm.data = result;
|
fm.data = result;
|
||||||
|
fm.save_status = "saved";
|
||||||
|
|
||||||
if (result === undefined) fm.data = {};
|
if (result === undefined) fm.data = {};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue