This commit is contained in:
rizky 2024-08-19 18:18:17 -07:00
parent 5fff3856f0
commit 73ae85841b
12 changed files with 232 additions and 169 deletions

View File

@ -114,6 +114,8 @@ export const Detail: FC<{
if (typeof values !== "object" || values === null) return null;
const entries = Object.entries(values);
console.log(entries)
return (
<div
className={cx(

View File

@ -296,13 +296,13 @@ export const ImgThumb = ({
url,
w,
h,
fit
fit,
}: {
className?: string;
url: string;
w: number;
h: number;
fit?: 'cover' | 'contain',
fit?: "cover" | "contain" | "inside" | "fill" | "outside";
}) => {
const local = useLocal({ error: false });
return (
@ -311,7 +311,7 @@ export const ImgThumb = ({
"img-thumb",
className,
css`
width: ${w}px;
width: ${w}px;
height: ${h}px;
background-image: linear-gradient(45deg, #ccc 25%, transparent 25%),
linear-gradient(135deg, #ccc 25%, transparent 25%),
@ -329,7 +329,9 @@ export const ImgThumb = ({
local.render();
}}
src={siteurl(
`/_img/${url.substring("_file/".length)}?w=${w}&h=${h}&fit=${fit || 'cover'}`
`/_img/${url.substring("_file/".length)}?w=${w}&h=${h}&fit=${
fit || "cover"
}`
)}
/>
)}

View File

@ -1,3 +1,4 @@
import { kvToJSON } from "lib/utils/kv-to-json";
import { useLocal } from "lib/utils/use-local";
import { useEffect, useRef } from "react";
@ -7,7 +8,7 @@ export const KeyValue = ({
index,
}: {
value: any;
onChange: (val: any) => void;
onChange?: (val: any) => void;
index?: "preserve" | "auto-sort";
}) => {
const local = useLocal({
@ -48,18 +49,9 @@ export const KeyValue = ({
if (typeof value !== "object") return null;
const reverseEntries = (input: [string, unknown][]) => {
return input
.filter(([k, v]) => {
return true; // some irrelevant conditions here
})
.reduce((accum: any, [k, v]) => {
accum[k] = v;
return accum;
}, {});
};
console.log(value);
return (
<div className="c-flex c-relative c-flex-1" ref={ref}>
<div className="c-flex c-relative c-flex-1 key-value" ref={ref}>
<table
onClick={(e) => {
e.stopPropagation();
@ -67,6 +59,10 @@ export const KeyValue = ({
}}
className={cx(
"c-flex-1",
!onChange &&
css`
border: 1px solid #ececeb;
`,
css`
input {
width: 100%;
@ -88,54 +84,60 @@ export const KeyValue = ({
key={idx}
item={item}
idx={idx}
update={(idx, k, v) => {
local.entries[idx] = [k, v];
update={
onChange
? (idx, k, v) => {
local.entries[idx] = [k, v];
if (k === "" && v === "") {
local.entries.splice(idx, 1);
}
if (k === "" && v === "") {
local.entries.splice(idx, 1);
}
local.render();
}}
local.render();
}
: undefined
}
onBlur={() => {
if (index === "preserve") {
onChange([...local.entries]);
onChange?.([...local.entries]);
} else {
onChange(reverseEntries(local.entries));
onChange?.(kvToJSON(local.entries));
}
}}
/>
))}
<KVRow
item={[local.new.key, local.new.value]}
idx={local.entries.length}
update={(idx, k, v) => {
local.new.key = k;
local.new.value = v;
local.render();
}}
onBlur={(field, val) => {
if (field === "key" && val) {
const idx = local.entries.length;
local.entries[idx] = [local.new.key, local.new.value];
local.new.key = "";
local.new.value = "";
{onChange && (
<KVRow
item={[local.new.key, local.new.value]}
idx={local.entries.length}
update={(idx, k, v) => {
local.new.key = k;
local.new.value = v;
local.render();
if (index === "preserve") {
onChange([...local.entries]);
} else {
onChange(reverseEntries(local.entries));
}}
onBlur={(field, val) => {
if (field === "key" && val) {
const idx = local.entries.length;
local.entries[idx] = [local.new.key, local.new.value];
local.new.key = "";
local.new.value = "";
local.render();
if (index === "preserve") {
onChange?.([...local.entries]);
} else {
onChange?.(kvToJSON(local.entries));
}
setTimeout(() => {
(
ref?.current?.querySelector(
`.kv-row-${idx} .kv-value input`
) as HTMLInputElement
)?.focus();
}, 10);
}
setTimeout(() => {
(
ref?.current?.querySelector(
`.kv-row-${idx} .kv-value input`
) as HTMLInputElement
)?.focus();
}, 10);
}
}}
/>
}}
/>
)}
</tbody>
</table>
</div>
@ -150,7 +152,7 @@ const KVRow = ({
}: {
item: [string, unknown];
idx: number;
update: (idx: number, key: string, value: string) => void;
update?: (idx: number, key: string, value: string) => void;
onBlur?: (field: "key" | "value", val: string) => void;
}) => {
const [k, v] = item as any;
@ -172,22 +174,26 @@ const KVRow = ({
`
)}
>
<input
type="text"
spellCheck={false}
value={k}
onChange={(e) => {
update(idx, e.currentTarget.value, v || "");
}}
onBlur={
onBlur
? (e) => {
onBlur("key", e.currentTarget.value);
}
: undefined
}
ref={keyref}
></input>
{update ? (
<input
type="text"
spellCheck={false}
value={k}
onChange={(e) => {
update(idx, e.currentTarget.value, v || "");
}}
onBlur={
onBlur
? (e) => {
onBlur("key", e.currentTarget.value);
}
: undefined
}
ref={keyref}
></input>
) : (
k
)}
</td>
<td
className={cx(
@ -198,27 +204,31 @@ const KVRow = ({
`
)}
>
<input
type="text"
spellCheck={false}
value={v || ""}
onChange={(e) => {
update(idx, k, e.currentTarget.value || "");
}}
onKeyUp={(e) => {
if (e.key === "Backspace" && !e.currentTarget.value) {
keyref.current?.focus();
{update ? (
<input
type="text"
spellCheck={false}
value={v || ""}
onChange={(e) => {
update(idx, k, e.currentTarget.value || "");
}}
onKeyUp={(e) => {
if (e.key === "Backspace" && !e.currentTarget.value) {
keyref.current?.focus();
}
}}
onBlur={
onBlur
? (e) => {
onBlur("value", e.currentTarget.value);
}
: undefined
}
}}
onBlur={
onBlur
? (e) => {
onBlur("value", e.currentTarget.value);
}
: undefined
}
ref={valref}
></input>
ref={valref}
></input>
) : (
v
)}
</td>
</tr>
);

View File

@ -129,7 +129,7 @@ const formatCurrency = (value: any) => {
return (isNegative ? "-" : "") + rupiah;
}
};
export const formatMoney = (res: number) => {
export const formatMoney = (res: any) => {
const formattedAmount = new Intl.NumberFormat("id-ID", {
minimumFractionDigits: 0,
}).format(res);

View File

@ -81,7 +81,7 @@ export const TLSlider: FC<{
})}
</div>
) : (
<div className="c-flex c-items-center c-justify-center c-flex-1 w-full h-full c-flex-col ">
<div className="c-flex c-items-center c-justify-center c-flex-1 w-full h-full c-flex-col c-py-10 ">
<Sticker size={35} strokeWidth={1} />
<div className="c-pt-1 c-text-center">
No&nbsp;Data

View File

@ -39,6 +39,7 @@ import { sortTree } from "./utils/sort-tree";
import { TLList } from "./TLList";
import { OnRowClick } from "./utils/type";
import { TLSlider } from "./TLSlider";
import { getPathname } from "lib/exports";
let EMPTY_SET = new Set() as ReadonlySet<any>;
@ -253,6 +254,7 @@ export const TableList: FC<TableListProp> = ({
skip: local.paging.skip,
},
};
if (id_parent) {
load_args.paging = {};
}
@ -261,7 +263,8 @@ export const TableList: FC<TableListProp> = ({
if (
id_parent ||
!local.paging ||
(local.paging && !local.paging.take)
(local.paging && !local.paging.take) ||
local.paging.skip === 0
) {
local.data = data;
} else {

View File

@ -95,18 +95,23 @@ export const ScrollArea = lazify(
async () => (await import("@/comps/ui/scroll-area")).ScrollArea
);
export const KeyValue = lazify(
async () => (await import("@/comps/form/field/type/KeyValue")).KeyValue
);
export { fetchLinkParams } from "@/comps/form/field/type/TypeLink";
export { FieldLoading } from "@/comps/ui/field-loading";
export { FieldLoading, Spinner } from "@/comps/ui/field-loading";
export { lang } from "lib/lang";
export { prasi_gen } from "./gen/prasi_gen";
export { guessLabel } from "./utils/guess-label";
import __get from "lodash.get";
import { sum } from "./utils/sum";
export { kvToJSON } from "./utils/kv-to-json";
export { overrideNav } from "./utils/override-nav";
export const _sum = sum;
export const _get = __get;
/** Generator */
export { generateFilter as genereteFilter } from "@/comps/filter/gen/gen-filter";
export { generateRelation } from "@/comps/form/gen/gen-rel";
@ -126,14 +131,14 @@ export {
fieldType,
FieldTypeCustom,
FMLocal,
formType
formType,
} from "@/comps/form/typings";
export { TableListType } from "@/comps/list/utils/typings";
export { generateTableList as generateTableList } from "@/comps/md/gen/gen-table-list";
export { generateSelect } from "@/comps/md/gen/md-select";
export { MasterDetailType } from "@/comps/md/utils/typings";
export { Button, FloatButton } from "@/comps/ui/button";
export { baseurl } from "@/utils/baseurl";
export { baseurl, imgThumb } from "@/utils/baseurl";
export { FormatValue } from "@/utils/format-value";
export { GetValue } from "@/utils/get-value";
export { password } from "@/utils/password";
@ -146,7 +151,7 @@ export { logout } from "@/preset/login/utils/logout";
export {
registerSession,
RG,
UserSession
UserSession,
} from "@/preset/login/utils/register";
export { Card } from "@/comps/custom/Card";

View File

@ -5,6 +5,7 @@ import { getPathname } from "lib/utils/pathname";
import { useLocal } from "lib/utils/use-local";
import { FC, ReactNode, useLayoutEffect } from "react";
import { loadSession } from "../login/utils/load";
import { overrideNav } from "lib/utils/override-nav";
const w = window as any;
const initResponsive = function () {
@ -69,75 +70,7 @@ export const Layout: FC<LYTChild> = (props) => {
const path = getPathname();
const no_layout = props.exception;
if (!w.prasi_menu && !isEditor) {
w.prasi_menu = { nav_override: true, nav: w.navigate, pm: null };
w.navigate = (async (_href, params) => {
if (!_href) {
console.error("Failed to navigate, empty url");
return;
}
if (_href.startsWith("/")) {
const url = new URL(location.href);
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) => {
return {
label: e.label,
url: e.url || getPathname({ hash: true }),
};
}) || [];
const values: LinkParam = {
name: params.name,
url: getPathname({ hash: true }),
prefix,
hash: "",
create: params.create,
update: params.update,
where: params.where,
};
const vhash = hashSum(values);
values.hash = vhash;
await api._kv("set", vhash, values);
const lnk = location.hash
.split("#")
.find((e) => e.startsWith("lnk="));
let prev_link = "";
if (lnk) {
prev_link = lnk.split("=").pop() || "";
if (prev_link) prev_link = prev_link + "+";
}
_href = `${_href}#lnk=${prev_link + vhash}`;
}
if (preloaded(pathname)) {
w.prasi_menu.nav(_href);
} else if (w.prasi_menu.pm?.on_load) {
let done = { exec: () => {} };
local.loading = true;
local.render();
w.prasi_menu.pm?.on_load((exec: any) => {
done.exec = exec;
});
await preload(pathname);
setTimeout(() => {
w.prasi_menu.nav(_href);
done.exec();
}, 500);
} else {
await preload(pathname);
w.prasi_menu.nav(_href);
}
}
}) as typeof navigate;
}
overrideNav({ local });
if (
!isEditor &&

View File

@ -6,3 +6,21 @@ export const baseurl = (url: string) => {
}
return url;
};
export const imgThumb = ({
url,
w,
h,
fit,
}: {
url: string;
w: number;
h: number;
fit?: "cover" | "contain" | "inside" | "fill" | "outside";
}) => {
return siteurl(
`/_img/${url.substring("_file/".length)}?w=${w}&h=${h}&fit=${
fit || "cover"
}`
);
};

View File

@ -1,3 +1,4 @@
const w = window as any;
if (typeof isEditor === "undefined") {
if (
@ -5,7 +6,7 @@ if (typeof isEditor === "undefined") {
location.pathname.startsWith("/ed")
) {
w.isEditor = true;
} else {
} else {
w.isEditor = false;
}
}

10
utils/kv-to-json.ts Executable file
View File

@ -0,0 +1,10 @@
export const kvToJSON = (input: [string, unknown][]) => {
return input
.filter(([k, v]) => {
return true; // some irrelevant conditions here
})
.reduce((accum: any, [k, v]) => {
accum[k] = v;
return accum;
}, {}) as Record<string, any>;
};

79
utils/override-nav.ts Executable file
View File

@ -0,0 +1,79 @@
import { LinkParam } from "lib/comps/form/field/type/TypeLink";
import { hashSum } from "lib/utils/hash-sum";
import { getPathname } from "lib/utils/pathname";
const w = window as any;
export const overrideNav = (arg?: { local?: any }) => {
if (!w.prasi_menu && !isEditor) {
w.prasi_menu = { nav_override: true, nav: w.navigate, pm: null };
w.navigate = (async (_href, params) => {
if (!_href) {
console.error("Failed to navigate, empty url");
return;
}
if (_href.startsWith("/")) {
const url = new URL(location.href);
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) => {
return {
label: e.label,
url: e.url || getPathname({ hash: true }),
};
}) || [];
const values: LinkParam = {
name: params.name,
url: getPathname({ hash: true }),
prefix,
hash: "",
create: params.create,
update: params.update,
where: params.where,
};
const vhash = hashSum(values);
values.hash = vhash;
await api._kv("set", vhash, values);
const lnk = location.hash
.split("#")
.find((e) => e.startsWith("lnk="));
let prev_link = "";
if (lnk) {
prev_link = lnk.split("=").pop() || "";
if (prev_link) prev_link = prev_link + "+";
}
_href = `${_href}#lnk=${prev_link + vhash}`;
}
if (preloaded(pathname)) {
w.prasi_menu.nav(_href);
} else if (w.prasi_menu.pm?.on_load) {
let done = { exec: () => {} };
if (arg?.local) {
arg.local.loading = true;
arg.local.render();
}
w.prasi_menu.pm?.on_load((exec: any) => {
done.exec = exec;
});
await preload(pathname);
setTimeout(() => {
w.prasi_menu.nav(_href);
done.exec();
}, 500);
} else {
await preload(pathname);
w.prasi_menu.nav(_href);
}
}
}) as typeof navigate;
}
};