fix table list

This commit is contained in:
rizky 2024-08-19 04:44:36 -07:00
parent 66ce2ab145
commit 52105ef69c
8 changed files with 275 additions and 114 deletions

113
comps/list/TLList.tsx Executable file
View File

@ -0,0 +1,113 @@
import { FC } from "react";
import { Skeleton } from "../ui/skeleton";
import { OnRowClick } from "./utils/type";
import { Sticker } from "lucide-react";
export const TLList: FC<{
local: Record<string, any> & {
el: null | HTMLDivElement;
render: () => void;
};
data: any[];
PassProp: any;
row_click: OnRowClick;
mode_child: any;
dataGridStyle: (local: { el: null | HTMLDivElement }) => string;
}> = ({ local, data, dataGridStyle, mode_child, PassProp, row_click }) => {
return (
<div
className={cx(
"c-w-full c-h-full c-flex-1 c-relative c-overflow-hidden",
dataGridStyle(local)
)}
ref={(el) => {
if (!local.el && el) {
local.el = el;
}
}}
>
{local.status !== "ready" ? (
<div className="c-flex c-flex-col c-space-y-2 c-m-4 c-absolute c-left-0 c-top-0">
<Skeleton className={cx("c-w-[200px] c-h-[11px]")} />
<Skeleton className={cx("c-w-[170px] c-h-[11px]")} />
<Skeleton className={cx("c-w-[180px] c-h-[11px]")} />
</div>
) : (
<div
className={cx(
"c-absolute c-inset-0",
!isEditor &&
css`
@keyframes flasher {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0px);
}
}
.list-row {
animation: flasher 0.5s;
}
`
)}
>
<>
{Array.isArray(data) && data.length > 0 ? (
<div
className="w-full h-full overflow-y-auto c-flex-col"
ref={(e) => {
local.grid_ref = e;
}}
onScroll={(e) => local.paging.scroll(e.currentTarget)}
>
{data.map((e, idx) => {
return (
<div
className={cx("list-row c-flex-grow c-flex")}
onClick={(ev) => {
if (!isEditor && typeof row_click === "function") {
row_click({
event: ev,
idx: idx,
row: e,
rows: local.data,
});
}
}}
>
<PassProp idx={idx} row={e} col={{}} rows={local.data}>
{mode_child}
</PassProp>
</div>
);
})}
</div>
) : (
<div className="c-flex c-items-center c-justify-center c-flex-1 w-full h-full c-flex-col ">
<Sticker size={35} strokeWidth={1} />
<div className="c-pt-1 c-text-center">
No&nbsp;Data
<br />
{local.filtering && (
<div
className={css`
color: gray;
font-style: italic;
font-size: 90%;
`}
>
{local.filtering}
</div>
)}
</div>
</div>
)}
</>
</div>
)}
</div>
);
};

107
comps/list/TLSlider.tsx Executable file
View File

@ -0,0 +1,107 @@
import { FC } from "react";
import { Skeleton } from "../ui/skeleton";
import { OnRowClick } from "./utils/type";
import { Sticker } from "lucide-react";
export const TLSlider: FC<{
local: Record<string, any> & {
el: null | HTMLDivElement;
render: () => void;
};
data: any[];
PassProp: any;
row_click: OnRowClick;
mode_child: any;
item_w: string;
dataGridStyle: (local: { el: null | HTMLDivElement }) => string;
}> = ({
local,
data,
dataGridStyle,
item_w,
mode_child,
PassProp,
row_click,
}) => {
return (
<>
{local.status !== "ready" ? (
<div className="c-flex c-flex-col c-space-y-2 c-m-4 c-absolute c-left-0 c-top-0">
<Skeleton className={cx("c-w-[200px] c-h-[11px]")} />
<Skeleton className={cx("c-w-[170px] c-h-[11px]")} />
<Skeleton className={cx("c-w-[180px] c-h-[11px]")} />
</div>
) : (
<>
{Array.isArray(data) && data.length > 0 ? (
<div
className={cx(
"c-overflow-x-auto c-snap-x c-h-full c-w-full c-flex",
css`
padding-right: 50px;
`
)}
ref={(e) => {
local.grid_ref = e;
}}
onScroll={(e) => local.paging.scroll(e.currentTarget)}
>
{data.map((e, idx) => {
return (
<div
className={cx(
"list-item c-snap-start c-flex c-shrink-0",
css`
width: ${item_w}px;
`
)}
onClick={(ev) => {
if (!isEditor && typeof row_click === "function") {
row_click({
event: ev,
idx: idx,
row: e,
rows: local.data,
});
}
}}
>
<PassProp
idx={idx}
item_w={item_w}
is_last={idx == data.length - 1}
row={e}
col={{}}
rows={local.data}
>
{mode_child}
</PassProp>
</div>
);
})}
</div>
) : (
<div className="c-flex c-items-center c-justify-center c-flex-1 w-full h-full c-flex-col ">
<Sticker size={35} strokeWidth={1} />
<div className="c-pt-1 c-text-center">
No&nbsp;Data
<br />
{local.filtering && (
<div
className={css`
color: gray;
font-style: italic;
font-size: 90%;
`}
>
{local.filtering}
</div>
)}
</div>
</div>
)}
</>
)}
</>
);
};

View File

@ -36,19 +36,17 @@ import { MDLocal } from "../md/utils/typings";
import { Skeleton } from "../ui/skeleton";
import { toast } from "../ui/toast";
import { sortTree } from "./utils/sort-tree";
import { TLList } from "./TLList";
import { OnRowClick } from "./utils/type";
import { TLSlider } from "./TLSlider";
type OnRowClick = (arg: {
row: any;
rows: any[];
idx: any;
event: React.MouseEvent<HTMLDivElement>;
}) => void;
let EMPTY_SET = new Set() as ReadonlySet<any>;
type SelectedRow = (arg: { row: any; rows: any[]; idx: any }) => boolean;
type TableListProp = {
child: any;
PassProp: any;
list: { type: string; item_w: string };
name: string;
value?: any[];
on_load?: (arg: {
@ -75,7 +73,6 @@ type TableListProp = {
tbl: any;
child: any;
}) => ReactNode;
softdel_field?: string;
gen_table?: string;
softdel_type?: string;
paging?: boolean;
@ -110,6 +107,7 @@ export const TableList: FC<TableListProp> = ({
row_height: rowHeight,
render_col,
show_header,
list,
value,
paging,
cache_row,
@ -163,6 +161,7 @@ export const TableList: FC<TableListProp> = ({
last_length: 0,
scroll: (currentTarget: HTMLDivElement) => {
if (
isEditor ||
local.data.length < local.paging.take ||
local.data.length === 0 ||
local.status !== "ready" ||
@ -259,7 +258,11 @@ export const TableList: FC<TableListProp> = ({
}
const result = on_load({ ...load_args, mode: "query" });
const callback = (data: any[]) => {
if (!local.paging || (local.paging && !local.paging.take)) {
if (
id_parent ||
!local.paging ||
(local.paging && !local.paging.take)
) {
local.data = data;
} else {
local.data = [...local.data, ...data];
@ -414,6 +417,9 @@ export const TableList: FC<TableListProp> = ({
useEffect(() => {
if (isEditor || value) {
on_init(local);
if (isEditor && local.data.length === 0 && local.status === "ready") {
reload();
}
return;
}
(async () => {
@ -935,107 +941,35 @@ export const TableList: FC<TableListProp> = ({
);
} else if (mode === "list") {
return (
<div
className={cx(
"c-w-full c-h-full c-flex-1 c-relative c-overflow-hidden",
dataGridStyle(local)
)}
ref={(el) => {
if (!local.el && el) {
local.el = el;
}
}}
>
<>
{toaster_el &&
createPortal(
<Toaster position={toast.position} cn={cn} />,
toaster_el
)}
{local.status !== "ready" ? (
<div className="c-flex c-flex-col c-space-y-2 c-m-4 c-absolute c-left-0 c-top-0">
<Skeleton className={cx("c-w-[200px] c-h-[11px]")} />
<Skeleton className={cx("c-w-[170px] c-h-[11px]")} />
<Skeleton className={cx("c-w-[180px] c-h-[11px]")} />
</div>
) : (
<div
className={cx(
"c-absolute c-inset-0",
css`
@keyframes flasher {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0px);
}
}
.list-row {
animation: flasher 0.5s;
}
`
)}
>
<>
{Array.isArray(data) && data.length > 0 ? (
<div
className="w-full h-full overflow-y-auto c-flex-col"
ref={(e) => {
local.grid_ref = e;
}}
onScroll={(e) => local.paging.scroll(e.currentTarget)}
>
{data.map((e, idx) => {
return (
<div
className={cx("list-row c-flex-grow c-flex")}
onClick={(ev) => {
if (!isEditor && typeof row_click === "function") {
row_click({
event: ev,
idx: idx,
row: e,
rows: local.data,
});
}
}}
>
<PassProp idx={idx} row={e} col={{}} rows={local.data}>
{mode_child}
</PassProp>
</div>
);
})}
</div>
) : (
<div className="c-flex c-items-center c-justify-center c-flex-1 w-full h-full c-flex-col ">
<Sticker size={35} strokeWidth={1} />
<div className="c-pt-1 c-text-center">
No&nbsp;Data
<br />
{local.filtering && (
<div
className={css`
color: gray;
font-style: italic;
font-size: 90%;
`}
>
{local.filtering}
</div>
)}
</div>
</div>
)}
</>
</div>
{list.type !== "slider" && list.type !== "grid" && (
<TLList
row_click={row_click}
PassProp={PassProp}
local={local}
mode_child={mode_child}
data={data}
dataGridStyle={dataGridStyle}
/>
)}
</div>
{list.type === "slider" && (
<TLSlider
row_click={row_click}
PassProp={PassProp}
local={local}
mode_child={mode_child}
data={data}
item_w={list.item_w}
dataGridStyle={dataGridStyle}
/>
)}
</>
);
} else {
}
};
const CheckboxList: FC<{

6
comps/list/utils/type.tsx Executable file
View File

@ -0,0 +1,6 @@
export type OnRowClick = (arg: {
row: any;
rows: any[];
idx: any;
event: React.MouseEvent<HTMLDivElement>;
}) => void;

View File

@ -129,11 +129,11 @@ const genList = async (opt: GenOpt) => {
},
adv: {
js: `\
<div {...props} className={cx(props.className, \`s-\${_item?.edit?.parent?.item?.id}\` , "list-field")}>
<div {...props} className={cx(props.className, _item?.edit?.parent?.item?.id && \`s-\${_item?.edit?.parent?.item?.id}\` , "list-field")}>
<FormatValue value={_get(row, name)} name={name} gen_fields={gen__fields} />
</div>`,
jsBuilt: `\
render(React.createElement("div", Object.assign({}, props, { className: cx(props.className, \`s-\${_item?.edit?.parent?.item?.id}\` , "") }),React.createElement(FormatValue, { value: _get(row, name), name: name, gen_fields: gen__fields })));
render(React.createElement("div", Object.assign({}, props, { className: cx(props.className, _item?.edit?.parent?.item?.id && \`s-\${_item?.edit?.parent?.item?.id}\` , "") }),React.createElement(FormatValue, { value: _get(row, name), name: name, gen_fields: gen__fields })));
`,
},
}),
@ -189,11 +189,11 @@ const genTable = async (opt: GenOpt) => {
title: formatName(e.name),
child: createItem({
name: "cell",
"layout": {
"dir": "col",
"align": "left",
"gap": 0,
"wrap": "flex-nowrap"
layout: {
dir: "col",
align: "left",
gap: 0,
wrap: "flex-nowrap",
},
padding: {
l: 8,
@ -203,11 +203,11 @@ const genTable = async (opt: GenOpt) => {
},
adv: {
js: `\
<div {...props} className={cx(props.className, \`s-\${_item?.edit?.parent?.item?.id}\` , "table-col")}>
<div {...props} className={cx(props.className, _item?.edit?.parent?.item?.id && \`s-\${_item?.edit?.parent?.item?.id}\` , "table-col")}>
<FormatValue value={col.value} name={col.name} gen_fields={gen__fields} />
</div>`,
jsBuilt: `\
render(React.createElement("div", Object.assign({}, props, { className: cx(props.className, \`s-\${_item?.edit?.parent?.item?.id}\` , "") }),React.createElement(FormatValue, { value: col.value, name: col.name, gen_fields: gen__fields })));
render(React.createElement("div", Object.assign({}, props, { className: cx(props.className, _item?.edit?.parent?.item?.id && \`s-\${_item?.edit?.parent?.item?.id}\` , "") }),React.createElement(FormatValue, { value: col.value, name: col.name, gen_fields: gen__fields })));
`,
},
}),

View File

@ -40,7 +40,7 @@ async (arg: TableOnLoad) => {
if (isEditor)
return [${JSON.stringify(sample)}];
let where = arg.where;
let where = arg.where as Prisma.${table}WhereInput;
if (arg.mode === "count") {
return await db.${table}.count({
where: {

View File

@ -81,6 +81,7 @@ export const Layout: FC<LYTChild> = (props) => {
const newurl = new URL(`${url.protocol}//${url.host}${_href}`);
const pathname = newurl.pathname;
_href = baseurl(_href);
if (params) {
const prefix: LinkParam["prefix"] =
params.breads?.map((e) => {