174 lines
4.2 KiB
TypeScript
Executable File
174 lines
4.2 KiB
TypeScript
Executable File
import { useLocal } from "@/utils/use-local";
|
|
import { FC, useEffect, useRef } from "react";
|
|
import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels";
|
|
import { refreshBread } from "./MDBread";
|
|
import { MDHeader } from "./MDHeader";
|
|
import { MDTab, should_show_tab } from "./MDTab";
|
|
import {
|
|
masterDetailApplyParams,
|
|
masterDetailParseHash as masterDetailParseParams,
|
|
} from "./utils/md-hash";
|
|
import { masterDetailInit, masterDetailSelected } from "./utils/md-init";
|
|
import { MDLocal, MDLocalInternal, MDRef } from "./utils/typings";
|
|
|
|
const w = window as unknown as {
|
|
generating_prasi_md: Record<string, true>;
|
|
};
|
|
|
|
export const MasterDetail: FC<{
|
|
child: any;
|
|
PassProp: any;
|
|
name: string;
|
|
mode: "full" | "h-split" | "v-split";
|
|
show_head: "always" | "only-master" | "only-child" | "hidden";
|
|
tab_mode: "h-tab" | "v-tab" | "hidden";
|
|
editor_tab: string;
|
|
gen_fields: any;
|
|
gen_table: string;
|
|
on_init: (md: MDLocal) => void;
|
|
}> = ({
|
|
PassProp,
|
|
child,
|
|
name,
|
|
mode,
|
|
show_head,
|
|
tab_mode,
|
|
editor_tab,
|
|
gen_fields,
|
|
gen_table,
|
|
on_init,
|
|
}) => {
|
|
let isGenerate = false as Boolean;
|
|
try {
|
|
isGenerate = false;
|
|
if (w.generating_prasi_md["master_detail"]) {
|
|
isGenerate = true;
|
|
}
|
|
} catch (ex) {}
|
|
|
|
const _ref = useRef({ PassProp, child });
|
|
const md = useLocal<MDLocalInternal>({
|
|
name,
|
|
actions: [],
|
|
breadcrumb: [],
|
|
selected: null,
|
|
tab: {
|
|
active: "",
|
|
list: [],
|
|
},
|
|
internal: { action_should_refresh: true },
|
|
childs: {},
|
|
props: {
|
|
mode,
|
|
show_head,
|
|
tab_mode,
|
|
editor_tab,
|
|
gen_fields,
|
|
gen_table,
|
|
on_init,
|
|
},
|
|
params: {
|
|
hash: {},
|
|
tabs: {},
|
|
parse: () => {
|
|
masterDetailParseParams(md);
|
|
},
|
|
apply: () => {
|
|
masterDetailApplyParams(md);
|
|
},
|
|
},
|
|
master: { internal: null, render() {} },
|
|
});
|
|
const local = useLocal({ init: false });
|
|
if (isEditor) {
|
|
md.props.mode = mode;
|
|
md.props.show_head = show_head;
|
|
md.props.tab_mode = tab_mode;
|
|
md.props.editor_tab = editor_tab;
|
|
md.props.gen_fields = gen_fields;
|
|
md.props.gen_table = gen_table;
|
|
md.props.on_init = on_init;
|
|
}
|
|
_ref.current.PassProp = PassProp;
|
|
_ref.current.child = child;
|
|
|
|
useEffect(() => {
|
|
local.init = false;
|
|
local.render();
|
|
}, [editor_tab]);
|
|
|
|
refreshBread(md);
|
|
|
|
if (!local.init || isEditor) {
|
|
local.init = true;
|
|
masterDetailInit(md, child, editor_tab);
|
|
masterDetailSelected(md);
|
|
}
|
|
if (isGenerate) return <>Generating ...</>;
|
|
return (
|
|
<div
|
|
className={cx(
|
|
"c-flex-1 c-flex-col c-flex c-w-full c-h-full c-overflow-hidden"
|
|
)}
|
|
>
|
|
{md.props.show_head === "always" && (
|
|
<MDHeader md={md} mdr={_ref.current} />
|
|
)}
|
|
{md.props.mode === "full" && <ModeFull md={md} mdr={_ref.current} />}
|
|
{md.props.mode === "v-split" && <ModeVSplit md={md} mdr={_ref.current} />}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
const ModeFull: FC<{ md: MDLocal; mdr: MDRef }> = ({ md, mdr }) => {
|
|
if (should_show_tab(md)) {
|
|
return <MDTab md={md} mdr={mdr} />;
|
|
}
|
|
return (
|
|
<>
|
|
{!md.selected && <Master md={md} mdr={mdr} />}
|
|
{md.selected && <MDTab md={md} mdr={mdr} />}
|
|
</>
|
|
);
|
|
};
|
|
|
|
const ModeVSplit: FC<{ md: MDLocal; mdr: MDRef }> = ({ md, mdr }) => {
|
|
return (
|
|
<div className={cx("c-flex-1")}>
|
|
<PanelGroup direction="vertical">
|
|
<Panel className="c-border-b">
|
|
<Master md={md} mdr={mdr} />
|
|
</Panel>
|
|
<>
|
|
<PanelResizeHandle />
|
|
<Panel
|
|
className="c-flex c-flex-col c-items-stretch"
|
|
defaultSize={
|
|
parseInt(localStorage.getItem(`prasi-md-h-${md.name}`) || "") ||
|
|
undefined
|
|
}
|
|
onResize={(e) => {
|
|
if (e < 80) {
|
|
localStorage.setItem(`prasi-md-h-${md.name}`, e.toString());
|
|
}
|
|
}}
|
|
>
|
|
<MDTab md={md} mdr={mdr} />
|
|
</Panel>
|
|
</>
|
|
</PanelGroup>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
const Master: FC<{ md: MDLocal; mdr: MDRef }> = ({ md, mdr }) => {
|
|
const PassProp = mdr.PassProp;
|
|
|
|
return (
|
|
<>
|
|
{md.props.show_head === "only-master" && <MDHeader md={md} mdr={mdr} />}
|
|
<PassProp md={md}>{md.master.internal}</PassProp>
|
|
</>
|
|
);
|
|
};
|