wip fix
This commit is contained in:
parent
4559a90ca1
commit
9957e9d626
|
|
@ -93,7 +93,6 @@ export const Field: FC<{
|
||||||
},
|
},
|
||||||
modify: null as any,
|
modify: null as any,
|
||||||
});
|
});
|
||||||
|
|
||||||
const textAreaRef = useRef<any>();
|
const textAreaRef = useRef<any>();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
autosize(textAreaRef.current);
|
autosize(textAreaRef.current);
|
||||||
|
|
|
||||||
|
|
@ -1,30 +1,54 @@
|
||||||
import { useLocal } from "@/utils/use-local";
|
import { useLocal } from "@/utils/use-local";
|
||||||
import get from "lodash.get";
|
import get from "lodash.get";
|
||||||
import { FC, useEffect } from "react";
|
import { FC, useEffect } from "react";
|
||||||
|
import { Tabs, TabsList, TabsTrigger } from "../ui/tabs";
|
||||||
import {
|
import {
|
||||||
MasterDetailConfig,
|
MasterDetailConfig,
|
||||||
MasterDetailLocal,
|
MasterDetailLocal,
|
||||||
MasterDetailProp,
|
MasterDetailProp,
|
||||||
} from "./type";
|
} from "./type";
|
||||||
import { Tab } from "../custom/Tab";
|
import { GFCol } from "@/gen/utils";
|
||||||
import { Tabs, TabsList, TabsTrigger } from "../ui/tabs";
|
import { master_detail_gen_hash, master_detail_params } from "./utils";
|
||||||
|
|
||||||
export const MasterDetail: FC<MasterDetailProp> = (props) => {
|
export const MasterDetail: FC<MasterDetailProp> = (props) => {
|
||||||
const { header, PassProp, master, detail, mode, title, actions } = props;
|
const { header, name, mode, title, actions, gen_fields } = props;
|
||||||
const md = useLocal<MasterDetailLocal & { cache_internal: any }>({
|
const md = useLocal<MasterDetailLocal & { cache_internal: any }>(
|
||||||
mode,
|
{
|
||||||
selected: null,
|
name,
|
||||||
active_tab: "",
|
mode,
|
||||||
ui: {
|
selected: null,
|
||||||
back: false,
|
active_tab: "",
|
||||||
title: title,
|
ui: {
|
||||||
breadcrumb: [],
|
back: false,
|
||||||
default_actions: null as any,
|
title: title,
|
||||||
actions: null as any,
|
breadcrumb: [],
|
||||||
|
default_actions: null as any,
|
||||||
|
actions: null as any,
|
||||||
|
},
|
||||||
|
cache_internal: {},
|
||||||
|
cache: null as any,
|
||||||
|
pk: null as null | GFCol,
|
||||||
},
|
},
|
||||||
cache_internal: {},
|
() => {
|
||||||
cache: null as any,
|
if (!isEditor) {
|
||||||
});
|
const hash = master_detail_params(md);
|
||||||
|
if (hash && hash[name] && md.pk) {
|
||||||
|
if (md.pk.type === "int") {
|
||||||
|
md.selected = { [md.pk.name]: parseInt(hash[name]) };
|
||||||
|
} else {
|
||||||
|
md.selected = { [md.pk.name]: hash[name] };
|
||||||
|
}
|
||||||
|
md.render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (!md.pk && gen_fields) {
|
||||||
|
for (const str of gen_fields) {
|
||||||
|
const f = JSON.parse(str) as GFCol;
|
||||||
|
if (f.is_pk) md.pk = f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!md.ui.actions) {
|
if (!md.ui.actions) {
|
||||||
md.ui.actions = actions(md);
|
md.ui.actions = actions(md);
|
||||||
|
|
@ -72,6 +96,24 @@ const BreadcrumbMode: FC<{
|
||||||
props: MasterDetailProp;
|
props: MasterDetailProp;
|
||||||
md: MasterDetailConfig;
|
md: MasterDetailConfig;
|
||||||
}> = ({ props, md }) => {
|
}> = ({ props, md }) => {
|
||||||
|
const local = useLocal({ init: false }, () => {
|
||||||
|
local.init = true;
|
||||||
|
local.render();
|
||||||
|
});
|
||||||
|
|
||||||
|
if (local.init) {
|
||||||
|
const hash = master_detail_params(md);
|
||||||
|
delete hash.parent_id;
|
||||||
|
|
||||||
|
if (!md.selected) {
|
||||||
|
delete hash[md.name];
|
||||||
|
location.hash = master_detail_gen_hash(hash);
|
||||||
|
} else if (md.pk) {
|
||||||
|
hash[md.name] = md.selected[md.pk.name];
|
||||||
|
location.hash = master_detail_gen_hash(hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={cx("c-flex-1 c-flex-col c-flex")}>
|
<div className={cx("c-flex-1 c-flex-col c-flex")}>
|
||||||
<div
|
<div
|
||||||
|
|
@ -80,6 +122,11 @@ const BreadcrumbMode: FC<{
|
||||||
<props.PassProp md={md}>{props.master}</props.PassProp>
|
<props.PassProp md={md}>{props.master}</props.PassProp>
|
||||||
</div>
|
</div>
|
||||||
{md.selected && <Detail props={props} md={md} />}
|
{md.selected && <Detail props={props} md={md} />}
|
||||||
|
{isEditor && !local.init && (
|
||||||
|
<div className="c-hidden">
|
||||||
|
<Detail props={props} md={md} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { GFCol } from "@/gen/utils";
|
||||||
import { ReactElement, ReactNode } from "react";
|
import { ReactElement, ReactNode } from "react";
|
||||||
|
|
||||||
export type MasterDetailProp = {
|
export type MasterDetailProp = {
|
||||||
|
|
@ -8,6 +9,8 @@ export type MasterDetailProp = {
|
||||||
mode: "breadcrumb" | "vertical" | "horizontal";
|
mode: "breadcrumb" | "vertical" | "horizontal";
|
||||||
title: string;
|
title: string;
|
||||||
actions: (md: any) => MasterDetailAction[];
|
actions: (md: any) => MasterDetailAction[];
|
||||||
|
gen_fields: any;
|
||||||
|
name: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
type MasterDetailAction = {
|
type MasterDetailAction = {
|
||||||
|
|
@ -18,6 +21,7 @@ type MasterDetailAction = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export type MasterDetailLocal = {
|
export type MasterDetailLocal = {
|
||||||
|
name: string;
|
||||||
mode: MasterDetailProp["mode"];
|
mode: MasterDetailProp["mode"];
|
||||||
selected: null | Record<string, any>;
|
selected: null | Record<string, any>;
|
||||||
active_tab: string;
|
active_tab: string;
|
||||||
|
|
@ -29,6 +33,7 @@ export type MasterDetailLocal = {
|
||||||
actions: MasterDetailAction[];
|
actions: MasterDetailAction[];
|
||||||
};
|
};
|
||||||
cache: (name: string, opt?: { reset: boolean }) => any;
|
cache: (name: string, opt?: { reset: boolean }) => any;
|
||||||
|
pk: null | GFCol;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type MasterDetailConfig = MasterDetailLocal & { render: () => void };
|
export type MasterDetailConfig = MasterDetailLocal & { render: () => void };
|
||||||
|
|
@ -54,6 +59,7 @@ export const master_detail_typings = {
|
||||||
actions: ${action_type}[];
|
actions: ${action_type}[];
|
||||||
};
|
};
|
||||||
cache: (name: string, opt?: { reset: boolean }) => any;
|
cache: (name: string, opt?: { reset: boolean }) => any;
|
||||||
|
pk: null | any
|
||||||
}`,
|
}`,
|
||||||
action_type,
|
action_type,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
import { MasterDetailConfig } from "./type";
|
||||||
|
|
||||||
|
export const master_detail_params = (md: MasterDetailConfig) => {
|
||||||
|
let parent_id =
|
||||||
|
md.pk?.type === "int"
|
||||||
|
? parseInt(md.selected?.[md.pk?.name || ""])
|
||||||
|
: md.selected?.[md.pk?.name || ""];
|
||||||
|
|
||||||
|
const hash: any = {};
|
||||||
|
for (const h of location.hash.split("#")) {
|
||||||
|
if (h) {
|
||||||
|
const [tab_name, tab_val] = h.split("=");
|
||||||
|
if (tab_name && tab_val) {
|
||||||
|
hash[tab_name] = tab_val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parent_id) {
|
||||||
|
return { ...hash, parent_id };
|
||||||
|
}
|
||||||
|
return hash;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const master_detail_gen_hash = (
|
||||||
|
obj: Record<string, number | string>
|
||||||
|
) => {
|
||||||
|
let hash = "";
|
||||||
|
for (const [k, v] of Object.entries(obj)) {
|
||||||
|
hash += `#${k}=${v}`;
|
||||||
|
}
|
||||||
|
return hash;
|
||||||
|
};
|
||||||
|
|
@ -20,8 +20,13 @@ export const on_load = ({
|
||||||
async (opt) => {
|
async (opt) => {
|
||||||
if (isEditor) return {};
|
if (isEditor) return {};
|
||||||
|
|
||||||
|
${
|
||||||
|
opt?.before_load
|
||||||
|
? opt.before_load
|
||||||
|
: `
|
||||||
let id = ${pk.type === "int" ? "parseInt(params.id)" : "params.id"};
|
let id = ${pk.type === "int" ? "parseInt(params.id)" : "params.id"};
|
||||||
${opt?.before_load}
|
`
|
||||||
|
}
|
||||||
|
|
||||||
let item = {};
|
let item = {};
|
||||||
if (id){
|
if (id){
|
||||||
|
|
@ -32,16 +37,19 @@ async (opt) => {
|
||||||
select: ${JSON.stringify(select, null, 2).split("\n").join("\n ")},
|
select: ${JSON.stringify(select, null, 2).split("\n").join("\n ")},
|
||||||
});
|
});
|
||||||
|
|
||||||
for (const [k, v] of Object.entries(item)) {
|
if (item){
|
||||||
${Object.entries(pks)
|
for (const [k, v] of Object.entries(item)) {
|
||||||
.map(([k, v]) => {
|
${Object.entries(pks)
|
||||||
return `\
|
.map(([k, v]) => {
|
||||||
if (k === "${k}") {
|
return `\
|
||||||
if (v?.["${v}"]) item[k] = { connect: { ${v}: v?.["${v}"] } } as any;
|
if (k === "${k}") {
|
||||||
else delete item[k];
|
if (v?.["${v}"]) item[k] = { connect: { ${v}: v?.["${v}"] } } as any;
|
||||||
}`;
|
else delete item[k];
|
||||||
})
|
}`;
|
||||||
.join("\n")}
|
})
|
||||||
|
.join("\n")}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
${opt?.after_load}
|
${opt?.after_load}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,15 @@
|
||||||
|
import { GFCol } from "../utils";
|
||||||
|
|
||||||
export const form_before_load = (
|
export const form_before_load = (
|
||||||
table: string,
|
table: string,
|
||||||
pk: string,
|
pk: GFCol,
|
||||||
title: string,
|
title: string,
|
||||||
label: string
|
label: string
|
||||||
) => {
|
) => {
|
||||||
return `
|
return `
|
||||||
|
|
||||||
|
const id = master_detail_params(md).parent_id;
|
||||||
|
|
||||||
const after_load = (item: any) => {
|
const after_load = (item: any) => {
|
||||||
const set_actions = () =>
|
const set_actions = () =>
|
||||||
(md.ui.actions = [
|
(md.ui.actions = [
|
||||||
|
|
@ -16,7 +21,9 @@ export const form_before_load = (
|
||||||
md.ui.actions = [{ label: "Deleting...", type: "ghost" }];
|
md.ui.actions = [{ label: "Deleting...", type: "ghost" }];
|
||||||
md.render();
|
md.render();
|
||||||
|
|
||||||
await db.${table}.delete({ where: { ${pk}: item.${pk} } });
|
await db.${table}.delete({ where: { ${pk.name}: item.${
|
||||||
|
pk.name
|
||||||
|
} } });
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
md.ui.actions = [...md.ui.default_actions];
|
md.ui.actions = [...md.ui.default_actions];
|
||||||
|
|
@ -44,10 +51,12 @@ export const form_before_load = (
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
set_actions();
|
set_actions();
|
||||||
md.ui.breadcrumb = [["${title}", ""]${label ? `, item?.["${label}"]` : ""}];
|
md.ui.breadcrumb = [[md.ui.title, ""]${
|
||||||
|
label ? `, item?.["${label}"]` : ""
|
||||||
|
}];
|
||||||
md.render();
|
md.render();
|
||||||
};
|
};
|
||||||
md.ui.breadcrumb = [["${title}", ""], "..."];
|
md.ui.breadcrumb = [[md.ui.title, ""], "..."];
|
||||||
md.render();
|
md.render();
|
||||||
|
|
||||||
`;
|
`;
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import { gen_columns } from "../gen_table/columns";
|
||||||
import { newField as table_new_field } from "../gen_table/new_field";
|
import { newField as table_new_field } from "../gen_table/new_field";
|
||||||
import { gen_detail } from "./gen_detail";
|
import { gen_detail } from "./gen_detail";
|
||||||
import { form_before_load } from "./form_before_load";
|
import { form_before_load } from "./form_before_load";
|
||||||
|
import { createId } from "@paralleldrive/cuid2";
|
||||||
|
|
||||||
export const gen_md = (modify: (data: any) => void, data: any) => {
|
export const gen_md = (modify: (data: any) => void, data: any) => {
|
||||||
const table = JSON.parse(data.gen_table.value);
|
const table = JSON.parse(data.gen_table.value);
|
||||||
|
|
@ -86,7 +87,7 @@ export const gen_md = (modify: (data: any) => void, data: any) => {
|
||||||
const detail = gen_detail();
|
const detail = gen_detail();
|
||||||
const title = parse(get(data, "title.value"));
|
const title = parse(get(data, "title.value"));
|
||||||
const label = parse(get(data, "gen_label.value"));
|
const label = parse(get(data, "gen_label.value"));
|
||||||
const before_load = form_before_load(table, pk.name, title, label);
|
const before_load = form_before_load(table, pk, title, label);
|
||||||
|
|
||||||
detail.props["on_load"].value = form_on_load({
|
detail.props["on_load"].value = form_on_load({
|
||||||
pk,
|
pk,
|
||||||
|
|
@ -105,9 +106,17 @@ export const gen_md = (modify: (data: any) => void, data: any) => {
|
||||||
const childs = get(detail.props, "body.content.childs");
|
const childs = get(detail.props, "body.content.childs");
|
||||||
if (Array.isArray(childs)) {
|
if (Array.isArray(childs)) {
|
||||||
detail.props.body.content.childs = new_fields.map(form_new_field) as any;
|
detail.props.body.content.childs = new_fields.map(form_new_field) as any;
|
||||||
console.log(detail.props.body.content.childs);
|
|
||||||
}
|
}
|
||||||
result["detail"].content = detail.content;
|
result["detail"].content = {
|
||||||
|
id: createId(),
|
||||||
|
name: "Detail",
|
||||||
|
type: "item",
|
||||||
|
dim: {
|
||||||
|
w: "full",
|
||||||
|
h: "full",
|
||||||
|
},
|
||||||
|
childs: [detail.content],
|
||||||
|
};
|
||||||
}
|
}
|
||||||
modify(result);
|
modify(result);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue