diff --git a/comps/custom/Detail.tsx b/comps/custom/Detail.tsx index cc41759..8e550de 100755 --- a/comps/custom/Detail.tsx +++ b/comps/custom/Detail.tsx @@ -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 (
{ 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" + }` )} /> )} diff --git a/comps/form/field/type/KeyValue.tsx b/comps/form/field/type/KeyValue.tsx index 34125f1..e5da000 100755 --- a/comps/form/field/type/KeyValue.tsx +++ b/comps/form/field/type/KeyValue.tsx @@ -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 ( -
+
{ 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)); } }} /> ))} - { - 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 && ( + { + 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); - } - }} - /> + }} + /> + )}
@@ -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 = ({ ` )} > - { - update(idx, e.currentTarget.value, v || ""); - }} - onBlur={ - onBlur - ? (e) => { - onBlur("key", e.currentTarget.value); - } - : undefined - } - ref={keyref} - > + {update ? ( + { + update(idx, e.currentTarget.value, v || ""); + }} + onBlur={ + onBlur + ? (e) => { + onBlur("key", e.currentTarget.value); + } + : undefined + } + ref={keyref} + > + ) : ( + k + )} - { - update(idx, k, e.currentTarget.value || ""); - }} - onKeyUp={(e) => { - if (e.key === "Backspace" && !e.currentTarget.value) { - keyref.current?.focus(); + {update ? ( + { + 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} - > + ref={valref} + > + ) : ( + v + )} ); diff --git a/comps/form/field/type/TypeMoney.tsx b/comps/form/field/type/TypeMoney.tsx index ba9b1eb..597e69e 100755 --- a/comps/form/field/type/TypeMoney.tsx +++ b/comps/form/field/type/TypeMoney.tsx @@ -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); diff --git a/comps/list/TLSlider.tsx b/comps/list/TLSlider.tsx index 2eeed3f..a122bad 100755 --- a/comps/list/TLSlider.tsx +++ b/comps/list/TLSlider.tsx @@ -81,7 +81,7 @@ export const TLSlider: FC<{ })}
) : ( -
+
No Data diff --git a/comps/list/TableList.tsx b/comps/list/TableList.tsx index 5d912bc..bffe9fc 100755 --- a/comps/list/TableList.tsx +++ b/comps/list/TableList.tsx @@ -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; @@ -253,6 +254,7 @@ export const TableList: FC = ({ skip: local.paging.skip, }, }; + if (id_parent) { load_args.paging = {}; } @@ -261,7 +263,8 @@ export const TableList: FC = ({ if ( id_parent || !local.paging || - (local.paging && !local.paging.take) + (local.paging && !local.paging.take) || + local.paging.skip === 0 ) { local.data = data; } else { diff --git a/exports.tsx b/exports.tsx index e84d3f0..5237448 100755 --- a/exports.tsx +++ b/exports.tsx @@ -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"; diff --git a/preset/menu/Layout.tsx b/preset/menu/Layout.tsx index bab8bf1..60f691e 100755 --- a/preset/menu/Layout.tsx +++ b/preset/menu/Layout.tsx @@ -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 = (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 && diff --git a/utils/baseurl.ts b/utils/baseurl.ts index 039133c..178a835 100755 --- a/utils/baseurl.ts +++ b/utils/baseurl.ts @@ -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" + }` + ); +}; diff --git a/utils/init.ts b/utils/init.ts index de1db81..c62d4a6 100755 --- a/utils/init.ts +++ b/utils/init.ts @@ -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; } } diff --git a/utils/kv-to-json.ts b/utils/kv-to-json.ts new file mode 100755 index 0000000..a51aced --- /dev/null +++ b/utils/kv-to-json.ts @@ -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; +}; diff --git a/utils/override-nav.ts b/utils/override-nav.ts new file mode 100755 index 0000000..b384b2a --- /dev/null +++ b/utils/override-nav.ts @@ -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; + } +};