@open-mercato/ui 0.4.2-canary-c02407ff85
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build.mjs +62 -0
- package/dist/backend/AppShell.js +902 -0
- package/dist/backend/AppShell.js.map +7 -0
- package/dist/backend/ConfirmDialog.js +17 -0
- package/dist/backend/ConfirmDialog.js.map +7 -0
- package/dist/backend/ContextHelp.js +31 -0
- package/dist/backend/ContextHelp.js.map +7 -0
- package/dist/backend/CrudForm.js +2028 -0
- package/dist/backend/CrudForm.js.map +7 -0
- package/dist/backend/DataTable.js +1363 -0
- package/dist/backend/DataTable.js.map +7 -0
- package/dist/backend/EmptyState.js +52 -0
- package/dist/backend/EmptyState.js.map +7 -0
- package/dist/backend/FilterBar.js +140 -0
- package/dist/backend/FilterBar.js.map +7 -0
- package/dist/backend/FilterOverlay.js +279 -0
- package/dist/backend/FilterOverlay.js.map +7 -0
- package/dist/backend/FlashMessages.js +66 -0
- package/dist/backend/FlashMessages.js.map +7 -0
- package/dist/backend/JsonBuilder.js +322 -0
- package/dist/backend/JsonBuilder.js.map +7 -0
- package/dist/backend/JsonDisplay.js +203 -0
- package/dist/backend/JsonDisplay.js.map +7 -0
- package/dist/backend/Page.js +27 -0
- package/dist/backend/Page.js.map +7 -0
- package/dist/backend/PerspectiveSidebar.js +282 -0
- package/dist/backend/PerspectiveSidebar.js.map +7 -0
- package/dist/backend/RowActions.js +148 -0
- package/dist/backend/RowActions.js.map +7 -0
- package/dist/backend/TruncatedCell.js +92 -0
- package/dist/backend/TruncatedCell.js.map +7 -0
- package/dist/backend/UserMenu.js +107 -0
- package/dist/backend/UserMenu.js.map +7 -0
- package/dist/backend/ValueIcons.js +34 -0
- package/dist/backend/ValueIcons.js.map +7 -0
- package/dist/backend/custom-fields/FieldDefinitionsEditor.js +1264 -0
- package/dist/backend/custom-fields/FieldDefinitionsEditor.js.map +7 -0
- package/dist/backend/custom-fields/FieldDefinitionsManager.js +332 -0
- package/dist/backend/custom-fields/FieldDefinitionsManager.js.map +7 -0
- package/dist/backend/dashboard/DashboardScreen.js +578 -0
- package/dist/backend/dashboard/DashboardScreen.js.map +7 -0
- package/dist/backend/dashboard/index.js +5 -0
- package/dist/backend/dashboard/index.js.map +7 -0
- package/dist/backend/dashboard/widgetRegistry.js +55 -0
- package/dist/backend/dashboard/widgetRegistry.js.map +7 -0
- package/dist/backend/detail/ActivitiesSection.js +962 -0
- package/dist/backend/detail/ActivitiesSection.js.map +7 -0
- package/dist/backend/detail/AddressEditor.js +413 -0
- package/dist/backend/detail/AddressEditor.js.map +7 -0
- package/dist/backend/detail/AddressTiles.js +437 -0
- package/dist/backend/detail/AddressTiles.js.map +7 -0
- package/dist/backend/detail/AddressesSection.js +264 -0
- package/dist/backend/detail/AddressesSection.js.map +7 -0
- package/dist/backend/detail/AttachmentDeleteDialog.js +41 -0
- package/dist/backend/detail/AttachmentDeleteDialog.js.map +7 -0
- package/dist/backend/detail/AttachmentMetadataDialog.js +517 -0
- package/dist/backend/detail/AttachmentMetadataDialog.js.map +7 -0
- package/dist/backend/detail/AttachmentsSection.js +367 -0
- package/dist/backend/detail/AttachmentsSection.js.map +7 -0
- package/dist/backend/detail/CustomDataSection.js +433 -0
- package/dist/backend/detail/CustomDataSection.js.map +7 -0
- package/dist/backend/detail/DetailFieldsSection.js +75 -0
- package/dist/backend/detail/DetailFieldsSection.js.map +7 -0
- package/dist/backend/detail/ErrorMessage.js +28 -0
- package/dist/backend/detail/ErrorMessage.js.map +7 -0
- package/dist/backend/detail/InlineEditors.js +681 -0
- package/dist/backend/detail/InlineEditors.js.map +7 -0
- package/dist/backend/detail/LoadingMessage.js +14 -0
- package/dist/backend/detail/LoadingMessage.js.map +7 -0
- package/dist/backend/detail/NotesSection.js +1032 -0
- package/dist/backend/detail/NotesSection.js.map +7 -0
- package/dist/backend/detail/TabEmptyState.js +25 -0
- package/dist/backend/detail/TabEmptyState.js.map +7 -0
- package/dist/backend/detail/TagsSection.js +254 -0
- package/dist/backend/detail/TagsSection.js.map +7 -0
- package/dist/backend/detail/addressFormat.js +77 -0
- package/dist/backend/detail/addressFormat.js.map +7 -0
- package/dist/backend/detail/index.js +34 -0
- package/dist/backend/detail/index.js.map +7 -0
- package/dist/backend/fields/registry.generated.js +8 -0
- package/dist/backend/fields/registry.generated.js.map +7 -0
- package/dist/backend/fields/registry.js +29 -0
- package/dist/backend/fields/registry.js.map +7 -0
- package/dist/backend/indexes/PartialIndexBanner.js +58 -0
- package/dist/backend/indexes/PartialIndexBanner.js.map +7 -0
- package/dist/backend/indexes/store.js +62 -0
- package/dist/backend/indexes/store.js.map +7 -0
- package/dist/backend/injection/InjectionSpot.js +179 -0
- package/dist/backend/injection/InjectionSpot.js.map +7 -0
- package/dist/backend/injection/PageInjectionBoundary.js +26 -0
- package/dist/backend/injection/PageInjectionBoundary.js.map +7 -0
- package/dist/backend/injection/helpers.js +26 -0
- package/dist/backend/injection/helpers.js.map +7 -0
- package/dist/backend/injection/widgetRegistry.js +55 -0
- package/dist/backend/injection/widgetRegistry.js.map +7 -0
- package/dist/backend/inputs/ComboboxInput.js +225 -0
- package/dist/backend/inputs/ComboboxInput.js.map +7 -0
- package/dist/backend/inputs/LookupSelect.js +191 -0
- package/dist/backend/inputs/LookupSelect.js.map +7 -0
- package/dist/backend/inputs/PhoneNumberField.js +100 -0
- package/dist/backend/inputs/PhoneNumberField.js.map +7 -0
- package/dist/backend/inputs/SwitchableMarkdownInput.js +92 -0
- package/dist/backend/inputs/SwitchableMarkdownInput.js.map +7 -0
- package/dist/backend/inputs/TagsInput.js +222 -0
- package/dist/backend/inputs/TagsInput.js.map +7 -0
- package/dist/backend/inputs/index.js +6 -0
- package/dist/backend/inputs/index.js.map +7 -0
- package/dist/backend/operations/LastOperationBanner.js +80 -0
- package/dist/backend/operations/LastOperationBanner.js.map +7 -0
- package/dist/backend/operations/store.js +183 -0
- package/dist/backend/operations/store.js.map +7 -0
- package/dist/backend/schedule/ScheduleAgenda.js +107 -0
- package/dist/backend/schedule/ScheduleAgenda.js.map +7 -0
- package/dist/backend/schedule/ScheduleGrid.js +107 -0
- package/dist/backend/schedule/ScheduleGrid.js.map +7 -0
- package/dist/backend/schedule/ScheduleToolbar.js +166 -0
- package/dist/backend/schedule/ScheduleToolbar.js.map +7 -0
- package/dist/backend/schedule/ScheduleView.js +165 -0
- package/dist/backend/schedule/ScheduleView.js.map +7 -0
- package/dist/backend/schedule/index.js +6 -0
- package/dist/backend/schedule/index.js.map +7 -0
- package/dist/backend/schedule/recurrence.js +83 -0
- package/dist/backend/schedule/recurrence.js.map +7 -0
- package/dist/backend/schedule/types.js +1 -0
- package/dist/backend/schedule/types.js.map +7 -0
- package/dist/backend/upgrades/UpgradeActionBanner.js +91 -0
- package/dist/backend/upgrades/UpgradeActionBanner.js.map +7 -0
- package/dist/backend/utils/api.js +127 -0
- package/dist/backend/utils/api.js.map +7 -0
- package/dist/backend/utils/apiCall.js +48 -0
- package/dist/backend/utils/apiCall.js.map +7 -0
- package/dist/backend/utils/crud.js +126 -0
- package/dist/backend/utils/crud.js.map +7 -0
- package/dist/backend/utils/customFieldColumns.js +56 -0
- package/dist/backend/utils/customFieldColumns.js.map +7 -0
- package/dist/backend/utils/customFieldDefs.js +143 -0
- package/dist/backend/utils/customFieldDefs.js.map +7 -0
- package/dist/backend/utils/customFieldFilters.js +126 -0
- package/dist/backend/utils/customFieldFilters.js.map +7 -0
- package/dist/backend/utils/customFieldForms.js +162 -0
- package/dist/backend/utils/customFieldForms.js.map +7 -0
- package/dist/backend/utils/customFieldValues.js +26 -0
- package/dist/backend/utils/customFieldValues.js.map +7 -0
- package/dist/backend/utils/flash.js +16 -0
- package/dist/backend/utils/flash.js.map +7 -0
- package/dist/backend/utils/nav.js +185 -0
- package/dist/backend/utils/nav.js.map +7 -0
- package/dist/backend/utils/serverErrors.js +230 -0
- package/dist/backend/utils/serverErrors.js.map +7 -0
- package/dist/frontend/AuthFooter.js +23 -0
- package/dist/frontend/AuthFooter.js.map +7 -0
- package/dist/frontend/LanguageSwitcher.js +57 -0
- package/dist/frontend/LanguageSwitcher.js.map +7 -0
- package/dist/frontend/Layout.js +14 -0
- package/dist/frontend/Layout.js.map +7 -0
- package/dist/index.js +32 -0
- package/dist/index.js.map +7 -0
- package/dist/primitives/DataLoader.js +67 -0
- package/dist/primitives/DataLoader.js.map +7 -0
- package/dist/primitives/ErrorNotice.js +20 -0
- package/dist/primitives/ErrorNotice.js.map +7 -0
- package/dist/primitives/alert.js +38 -0
- package/dist/primitives/alert.js.map +7 -0
- package/dist/primitives/badge.js +28 -0
- package/dist/primitives/badge.js.map +7 -0
- package/dist/primitives/button.js +44 -0
- package/dist/primitives/button.js.map +7 -0
- package/dist/primitives/card.js +91 -0
- package/dist/primitives/card.js.map +7 -0
- package/dist/primitives/checkbox.js +28 -0
- package/dist/primitives/checkbox.js.map +7 -0
- package/dist/primitives/dialog.js +90 -0
- package/dist/primitives/dialog.js.map +7 -0
- package/dist/primitives/input.js +22 -0
- package/dist/primitives/input.js.map +7 -0
- package/dist/primitives/label.js +21 -0
- package/dist/primitives/label.js.map +7 -0
- package/dist/primitives/separator.js +9 -0
- package/dist/primitives/separator.js.map +7 -0
- package/dist/primitives/spinner.js +24 -0
- package/dist/primitives/spinner.js.map +7 -0
- package/dist/primitives/switch.js +80 -0
- package/dist/primitives/switch.js.map +7 -0
- package/dist/primitives/table.js +29 -0
- package/dist/primitives/table.js.map +7 -0
- package/dist/primitives/tabs.js +87 -0
- package/dist/primitives/tabs.js.map +7 -0
- package/dist/primitives/textarea.js +21 -0
- package/dist/primitives/textarea.js.map +7 -0
- package/dist/primitives/tooltip.js +60 -0
- package/dist/primitives/tooltip.js.map +7 -0
- package/dist/theme/QueryProvider.js +44 -0
- package/dist/theme/QueryProvider.js.map +7 -0
- package/dist/theme/ThemeProvider.js +95 -0
- package/dist/theme/ThemeProvider.js.map +7 -0
- package/dist/theme/ThemeToggle.js +88 -0
- package/dist/theme/ThemeToggle.js.map +7 -0
- package/dist/theme/index.js +10 -0
- package/dist/theme/index.js.map +7 -0
- package/dist/types/react-big-calendar.d.js +1 -0
- package/dist/types/react-big-calendar.d.js.map +7 -0
- package/jest.config.cjs +23 -0
- package/jest.setup.ts +55 -0
- package/package.json +105 -0
- package/src/backend/AppShell.tsx +1096 -0
- package/src/backend/ConfirmDialog.tsx +19 -0
- package/src/backend/ContextHelp.tsx +38 -0
- package/src/backend/CrudForm.tsx +2503 -0
- package/src/backend/DataTable.tsx +1730 -0
- package/src/backend/EmptyState.tsx +65 -0
- package/src/backend/FilterBar.tsx +161 -0
- package/src/backend/FilterOverlay.tsx +328 -0
- package/src/backend/FlashMessages.tsx +82 -0
- package/src/backend/JsonBuilder.tsx +362 -0
- package/src/backend/JsonDisplay.tsx +254 -0
- package/src/backend/Page.tsx +30 -0
- package/src/backend/PerspectiveSidebar.tsx +337 -0
- package/src/backend/RowActions.tsx +151 -0
- package/src/backend/TruncatedCell.tsx +133 -0
- package/src/backend/UserMenu.tsx +118 -0
- package/src/backend/ValueIcons.tsx +48 -0
- package/src/backend/__tests__/AppShell.test.tsx +115 -0
- package/src/backend/__tests__/CrudForm.render.test.tsx +30 -0
- package/src/backend/__tests__/DataTable.render.test.tsx +48 -0
- package/src/backend/__tests__/custom-field-filters.test.ts +72 -0
- package/src/backend/__tests__/custom-field-forms.test.ts +54 -0
- package/src/backend/__tests__/serverErrors.test.ts +83 -0
- package/src/backend/custom-fields/FieldDefinitionsEditor.tsx +1292 -0
- package/src/backend/custom-fields/FieldDefinitionsManager.tsx +381 -0
- package/src/backend/dashboard/DashboardScreen.tsx +684 -0
- package/src/backend/dashboard/__tests__/DashboardScreen.test.tsx +112 -0
- package/src/backend/dashboard/index.ts +1 -0
- package/src/backend/dashboard/widgetRegistry.ts +68 -0
- package/src/backend/detail/ActivitiesSection.tsx +1284 -0
- package/src/backend/detail/AddressEditor.tsx +472 -0
- package/src/backend/detail/AddressTiles.tsx +587 -0
- package/src/backend/detail/AddressesSection.tsx +346 -0
- package/src/backend/detail/AttachmentDeleteDialog.tsx +56 -0
- package/src/backend/detail/AttachmentMetadataDialog.tsx +672 -0
- package/src/backend/detail/AttachmentsSection.tsx +414 -0
- package/src/backend/detail/CustomDataSection.tsx +530 -0
- package/src/backend/detail/DetailFieldsSection.tsx +147 -0
- package/src/backend/detail/ErrorMessage.tsx +32 -0
- package/src/backend/detail/InlineEditors.tsx +877 -0
- package/src/backend/detail/LoadingMessage.tsx +14 -0
- package/src/backend/detail/NotesSection.tsx +1275 -0
- package/src/backend/detail/TabEmptyState.tsx +48 -0
- package/src/backend/detail/TagsSection.tsx +314 -0
- package/src/backend/detail/addressFormat.tsx +121 -0
- package/src/backend/detail/index.ts +44 -0
- package/src/backend/fields/registry.generated.ts +8 -0
- package/src/backend/fields/registry.ts +38 -0
- package/src/backend/indexes/PartialIndexBanner.tsx +68 -0
- package/src/backend/indexes/store.ts +88 -0
- package/src/backend/injection/InjectionSpot.tsx +236 -0
- package/src/backend/injection/PageInjectionBoundary.tsx +31 -0
- package/src/backend/injection/helpers.ts +35 -0
- package/src/backend/injection/widgetRegistry.ts +68 -0
- package/src/backend/inputs/ComboboxInput.tsx +269 -0
- package/src/backend/inputs/LookupSelect.tsx +247 -0
- package/src/backend/inputs/PhoneNumberField.tsx +129 -0
- package/src/backend/inputs/SwitchableMarkdownInput.tsx +128 -0
- package/src/backend/inputs/TagsInput.tsx +259 -0
- package/src/backend/inputs/index.ts +5 -0
- package/src/backend/operations/LastOperationBanner.tsx +85 -0
- package/src/backend/operations/__tests__/LastOperationBanner.test.tsx +99 -0
- package/src/backend/operations/store.ts +230 -0
- package/src/backend/schedule/ScheduleAgenda.tsx +136 -0
- package/src/backend/schedule/ScheduleGrid.tsx +136 -0
- package/src/backend/schedule/ScheduleToolbar.tsx +178 -0
- package/src/backend/schedule/ScheduleView.tsx +198 -0
- package/src/backend/schedule/index.ts +5 -0
- package/src/backend/schedule/recurrence.ts +99 -0
- package/src/backend/schedule/types.ts +26 -0
- package/src/backend/upgrades/UpgradeActionBanner.tsx +128 -0
- package/src/backend/utils/__tests__/apiCall.test.ts +109 -0
- package/src/backend/utils/__tests__/crud.test.ts +87 -0
- package/src/backend/utils/__tests__/customFieldDefs.test.ts +25 -0
- package/src/backend/utils/__tests__/customFieldValues.test.ts +35 -0
- package/src/backend/utils/api.ts +149 -0
- package/src/backend/utils/apiCall.ts +96 -0
- package/src/backend/utils/crud.ts +174 -0
- package/src/backend/utils/customFieldColumns.ts +71 -0
- package/src/backend/utils/customFieldDefs.ts +245 -0
- package/src/backend/utils/customFieldFilters.ts +145 -0
- package/src/backend/utils/customFieldForms.ts +196 -0
- package/src/backend/utils/customFieldValues.ts +41 -0
- package/src/backend/utils/flash.ts +17 -0
- package/src/backend/utils/nav.ts +238 -0
- package/src/backend/utils/serverErrors.ts +302 -0
- package/src/frontend/AuthFooter.tsx +29 -0
- package/src/frontend/LanguageSwitcher.tsx +66 -0
- package/src/frontend/Layout.tsx +13 -0
- package/src/index.ts +32 -0
- package/src/primitives/DataLoader.tsx +92 -0
- package/src/primitives/ErrorNotice.tsx +26 -0
- package/src/primitives/alert.tsx +52 -0
- package/src/primitives/badge.tsx +31 -0
- package/src/primitives/button.tsx +47 -0
- package/src/primitives/card.tsx +92 -0
- package/src/primitives/checkbox.tsx +28 -0
- package/src/primitives/dialog.tsx +110 -0
- package/src/primitives/input.tsx +20 -0
- package/src/primitives/label.tsx +18 -0
- package/src/primitives/separator.tsx +7 -0
- package/src/primitives/spinner.tsx +27 -0
- package/src/primitives/switch.tsx +86 -0
- package/src/primitives/table.tsx +27 -0
- package/src/primitives/tabs.tsx +128 -0
- package/src/primitives/textarea.tsx +20 -0
- package/src/primitives/tooltip.tsx +85 -0
- package/src/theme/QueryProvider.tsx +46 -0
- package/src/theme/ThemeProvider.tsx +120 -0
- package/src/theme/ThemeToggle.tsx +88 -0
- package/src/theme/index.ts +3 -0
- package/src/types/react-big-calendar.d.ts +16 -0
- package/tsconfig.build.json +11 -0
- package/tsconfig.json +9 -0
- package/watch.mjs +6 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/backend/utils/apiCall.ts"],
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport { apiFetch } from './api'\nimport { raiseCrudError, readJsonSafe } from './serverErrors'\n\nexport type ApiCallOptions<TReturn> = {\n parse?: (res: Response) => Promise<TReturn | null>\n fallback?: TReturn | null\n}\n\nexport type ApiCallResult<TReturn> = {\n ok: boolean\n status: number\n result: TReturn | null\n response: Response\n cacheStatus: 'hit' | 'miss' | null\n}\n\nexport async function apiCall<TReturn = Record<string, unknown>>(\n input: RequestInfo | URL,\n init?: RequestInit,\n options?: ApiCallOptions<TReturn>,\n): Promise<ApiCallResult<TReturn>> {\n const response = await apiFetch(input, init)\n const parser = options?.parse\n const fallback = options?.fallback ?? null\n let result: TReturn | null = null\n const rawCacheStatus =\n response.headers?.get?.('x-om-cache') ??\n response.headers?.get?.('x-cache-status') ??\n null\n const cacheStatus = rawCacheStatus === 'hit' || rawCacheStatus === 'miss' ? rawCacheStatus : null\n try {\n const source = typeof (response as Response & { clone?: () => Response }).clone === 'function'\n ? response.clone()\n : response\n if (parser) result = await parser(source)\n else result = await readJsonSafe<TReturn>(source, fallback)\n } catch {\n result = fallback\n }\n return {\n ok: response.ok,\n status: response.status,\n result,\n response,\n cacheStatus,\n }\n}\n\nexport type ApiCallOrThrowOptions<TReturn> = ApiCallOptions<TReturn> & {\n errorMessage?: string\n}\n\nexport async function apiCallOrThrow<TReturn = Record<string, unknown>>(\n input: RequestInfo | URL,\n init?: RequestInit,\n options?: ApiCallOrThrowOptions<TReturn>,\n): Promise<ApiCallResult<TReturn>> {\n const { errorMessage, ...callOptions } = options ?? {}\n const call = await apiCall<TReturn>(input, init, callOptions)\n if (!call.ok) {\n await raiseCrudError(call.response, errorMessage)\n }\n return call\n}\n\nexport type ReadApiResultOrThrowOptions<TReturn> = ApiCallOrThrowOptions<TReturn> & {\n allowNullResult?: boolean\n emptyResultMessage?: string\n}\n\nexport async function readApiResultOrThrow<TReturn = Record<string, unknown>>(\n input: RequestInfo | URL,\n init?: RequestInit,\n options?: ReadApiResultOrThrowOptions<TReturn> & { allowNullResult?: false },\n): Promise<TReturn>\nexport async function readApiResultOrThrow<TReturn = Record<string, unknown>>(\n input: RequestInfo | URL,\n init: RequestInit | undefined,\n options: ReadApiResultOrThrowOptions<TReturn> & { allowNullResult: true },\n): Promise<TReturn | null>\nexport async function readApiResultOrThrow<TReturn = Record<string, unknown>>(\n input: RequestInfo | URL,\n init?: RequestInit,\n options?: ReadApiResultOrThrowOptions<TReturn>,\n): Promise<TReturn | null> {\n const { allowNullResult = false, emptyResultMessage, ...callOptions } = options ?? {}\n const call = await apiCallOrThrow<TReturn>(input, init, callOptions)\n if (call.result == null && !allowNullResult) {\n const fallback =\n emptyResultMessage ?? callOptions.errorMessage ?? `Missing response payload (${call.status})`\n throw new Error(fallback)\n }\n return call.result\n}\n"],
|
|
5
|
+
"mappings": ";AAEA,SAAS,gBAAgB;AACzB,SAAS,gBAAgB,oBAAoB;AAe7C,eAAsB,QACpB,OACA,MACA,SACiC;AACjC,QAAM,WAAW,MAAM,SAAS,OAAO,IAAI;AAC3C,QAAM,SAAS,SAAS;AACxB,QAAM,WAAW,SAAS,YAAY;AACtC,MAAI,SAAyB;AAC7B,QAAM,iBACJ,SAAS,SAAS,MAAM,YAAY,KACpC,SAAS,SAAS,MAAM,gBAAgB,KACxC;AACF,QAAM,cAAc,mBAAmB,SAAS,mBAAmB,SAAS,iBAAiB;AAC7F,MAAI;AACF,UAAM,SAAS,OAAQ,SAAmD,UAAU,aAChF,SAAS,MAAM,IACf;AACJ,QAAI,OAAQ,UAAS,MAAM,OAAO,MAAM;AAAA,QACnC,UAAS,MAAM,aAAsB,QAAQ,QAAQ;AAAA,EAC5D,QAAQ;AACN,aAAS;AAAA,EACX;AACA,SAAO;AAAA,IACL,IAAI,SAAS;AAAA,IACb,QAAQ,SAAS;AAAA,IACjB;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAMA,eAAsB,eACpB,OACA,MACA,SACiC;AACjC,QAAM,EAAE,cAAc,GAAG,YAAY,IAAI,WAAW,CAAC;AACrD,QAAM,OAAO,MAAM,QAAiB,OAAO,MAAM,WAAW;AAC5D,MAAI,CAAC,KAAK,IAAI;AACZ,UAAM,eAAe,KAAK,UAAU,YAAY;AAAA,EAClD;AACA,SAAO;AACT;AAiBA,eAAsB,qBACpB,OACA,MACA,SACyB;AACzB,QAAM,EAAE,kBAAkB,OAAO,oBAAoB,GAAG,YAAY,IAAI,WAAW,CAAC;AACpF,QAAM,OAAO,MAAM,eAAwB,OAAO,MAAM,WAAW;AACnE,MAAI,KAAK,UAAU,QAAQ,CAAC,iBAAiB;AAC3C,UAAM,WACJ,sBAAsB,YAAY,gBAAgB,6BAA6B,KAAK,MAAM;AAC5F,UAAM,IAAI,MAAM,QAAQ;AAAA,EAC1B;AACA,SAAO,KAAK;AACd;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
function toQuery(params) {
|
|
2
|
+
const sp = new URLSearchParams();
|
|
3
|
+
for (const [k, v] of Object.entries(params)) {
|
|
4
|
+
if (v === void 0 || v === null) continue;
|
|
5
|
+
if (Array.isArray(v)) {
|
|
6
|
+
if (v.length === 0) continue;
|
|
7
|
+
sp.set(k, v.join(","));
|
|
8
|
+
} else {
|
|
9
|
+
sp.set(k, String(v));
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
return sp.toString();
|
|
13
|
+
}
|
|
14
|
+
function buildCrudQuery(params) {
|
|
15
|
+
return toQuery(params);
|
|
16
|
+
}
|
|
17
|
+
import { apiCall, readApiResultOrThrow } from "./apiCall.js";
|
|
18
|
+
import { raiseCrudError } from "./serverErrors.js";
|
|
19
|
+
function mergeHeaders(base, extra) {
|
|
20
|
+
if (!base) return extra;
|
|
21
|
+
const hasHeadersCtor = typeof Headers !== "undefined";
|
|
22
|
+
if (hasHeadersCtor && base instanceof Headers) {
|
|
23
|
+
const merged = new Headers(base);
|
|
24
|
+
Object.entries(extra).forEach(([key, value]) => merged.set(key, value));
|
|
25
|
+
return merged;
|
|
26
|
+
}
|
|
27
|
+
if (Array.isArray(base)) {
|
|
28
|
+
return [...base, ...Object.entries(extra)];
|
|
29
|
+
}
|
|
30
|
+
return { ...base, ...extra };
|
|
31
|
+
}
|
|
32
|
+
async function fetchCrudList(apiPath, params, init) {
|
|
33
|
+
const qs = buildCrudQuery(params);
|
|
34
|
+
return readApiResultOrThrow(`/api/${apiPath}?${qs}`, init, {
|
|
35
|
+
errorMessage: "Failed to fetch list"
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
function buildCrudExportUrl(apiPath, params, format) {
|
|
39
|
+
const qs = buildCrudQuery({ ...params, format });
|
|
40
|
+
return `/api/${apiPath}?${qs}`;
|
|
41
|
+
}
|
|
42
|
+
function buildCrudCsvUrl(apiPath, params) {
|
|
43
|
+
return buildCrudExportUrl(apiPath, params, "csv");
|
|
44
|
+
}
|
|
45
|
+
async function createCrud(apiPath, body, init) {
|
|
46
|
+
const { parseResult, fallbackResult, errorMessage, headers, ...rest } = init ?? {};
|
|
47
|
+
const call = await apiCall(
|
|
48
|
+
`/api/${apiPath}`,
|
|
49
|
+
{
|
|
50
|
+
...rest,
|
|
51
|
+
method: "POST",
|
|
52
|
+
headers: mergeHeaders(headers, { "content-type": "application/json" }),
|
|
53
|
+
body: JSON.stringify(body)
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
parse: parseResult,
|
|
57
|
+
fallback: fallbackResult ?? null
|
|
58
|
+
}
|
|
59
|
+
);
|
|
60
|
+
if (!call.ok) await raiseCrudError(call.response, errorMessage ?? "Failed to create");
|
|
61
|
+
return call;
|
|
62
|
+
}
|
|
63
|
+
async function updateCrud(apiPath, body, init) {
|
|
64
|
+
const { parseResult, fallbackResult, errorMessage, headers, ...rest } = init ?? {};
|
|
65
|
+
const call = await apiCall(
|
|
66
|
+
`/api/${apiPath}`,
|
|
67
|
+
{
|
|
68
|
+
...rest,
|
|
69
|
+
method: "PUT",
|
|
70
|
+
headers: mergeHeaders(headers, { "content-type": "application/json" }),
|
|
71
|
+
body: JSON.stringify(body)
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
parse: parseResult,
|
|
75
|
+
fallback: fallbackResult ?? null
|
|
76
|
+
}
|
|
77
|
+
);
|
|
78
|
+
if (!call.ok) await raiseCrudError(call.response, errorMessage ?? "Failed to update");
|
|
79
|
+
return call;
|
|
80
|
+
}
|
|
81
|
+
async function deleteCrud(apiPath, idOrOptions, maybeInit) {
|
|
82
|
+
if (typeof idOrOptions === "string") {
|
|
83
|
+
const { parseResult: parseResult2, fallbackResult: fallbackResult2, errorMessage: errorMessage2, ...rest2 } = maybeInit ?? {};
|
|
84
|
+
const call2 = await apiCall(
|
|
85
|
+
`/api/${apiPath}?id=${encodeURIComponent(idOrOptions)}`,
|
|
86
|
+
{
|
|
87
|
+
...rest2,
|
|
88
|
+
method: "DELETE"
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
parse: parseResult2,
|
|
92
|
+
fallback: fallbackResult2 ?? null
|
|
93
|
+
}
|
|
94
|
+
);
|
|
95
|
+
if (!call2.ok) await raiseCrudError(call2.response, errorMessage2 ?? "Failed to delete");
|
|
96
|
+
return call2;
|
|
97
|
+
}
|
|
98
|
+
const { parseResult, fallbackResult, errorMessage, headers, body, id, ...rest } = idOrOptions;
|
|
99
|
+
const payload = body ?? (id ? { id } : void 0);
|
|
100
|
+
const requestHeaders = payload !== void 0 ? mergeHeaders(headers, { "content-type": "application/json" }) : headers;
|
|
101
|
+
const call = await apiCall(
|
|
102
|
+
`/api/${apiPath}`,
|
|
103
|
+
{
|
|
104
|
+
...rest,
|
|
105
|
+
method: "DELETE",
|
|
106
|
+
headers: requestHeaders,
|
|
107
|
+
body: payload !== void 0 ? JSON.stringify(payload) : void 0
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
parse: parseResult,
|
|
111
|
+
fallback: fallbackResult ?? null
|
|
112
|
+
}
|
|
113
|
+
);
|
|
114
|
+
if (!call.ok) await raiseCrudError(call.response, errorMessage ?? "Failed to delete");
|
|
115
|
+
return call;
|
|
116
|
+
}
|
|
117
|
+
export {
|
|
118
|
+
buildCrudCsvUrl,
|
|
119
|
+
buildCrudExportUrl,
|
|
120
|
+
buildCrudQuery,
|
|
121
|
+
createCrud,
|
|
122
|
+
deleteCrud,
|
|
123
|
+
fetchCrudList,
|
|
124
|
+
updateCrud
|
|
125
|
+
};
|
|
126
|
+
//# sourceMappingURL=crud.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/backend/utils/crud.ts"],
|
|
4
|
+
"sourcesContent": ["export type SortDir = 'asc' | 'desc'\n\nexport type ListResponse<T> = {\n items: T[]\n total: number\n page: number\n pageSize: number\n totalPages: number\n}\n\nexport type CrudExportFormat = 'csv' | 'json' | 'xml' | 'markdown'\n\nfunction toQuery(params: Record<string, any>) {\n const sp = new URLSearchParams()\n for (const [k, v] of Object.entries(params)) {\n if (v === undefined || v === null) continue\n if (Array.isArray(v)) {\n if (v.length === 0) continue\n sp.set(k, v.join(','))\n } else {\n sp.set(k, String(v))\n }\n }\n return sp.toString()\n}\n\nexport function buildCrudQuery(params: Record<string, any>): string {\n return toQuery(params)\n}\n\nimport { apiCall, readApiResultOrThrow, type ApiCallResult } from './apiCall'\nimport { raiseCrudError } from './serverErrors'\n\nfunction mergeHeaders(base: HeadersInit | undefined, extra: Record<string, string>): HeadersInit {\n if (!base) return extra\n const hasHeadersCtor = typeof Headers !== 'undefined'\n if (hasHeadersCtor && base instanceof Headers) {\n const merged = new Headers(base)\n Object.entries(extra).forEach(([key, value]) => merged.set(key, value))\n return merged\n }\n if (Array.isArray(base)) {\n return [...base, ...Object.entries(extra)]\n }\n return { ...(base as Record<string, string>), ...extra }\n}\n\ntype CrudRequestExtras<TReturn> = {\n parseResult?: (res: Response) => Promise<TReturn | null>\n fallbackResult?: TReturn | null\n errorMessage?: string\n}\n\nexport type CrudRequestInit<TReturn> = Omit<RequestInit, 'body' | 'method'> & CrudRequestExtras<TReturn>\ntype CrudDeleteOptions<TReturn> = Omit<RequestInit, 'method' | 'body'> &\n CrudRequestExtras<TReturn> & {\n body?: unknown\n id?: string\n }\n\nexport type CrudResponse<TReturn> = ApiCallResult<TReturn>\n\nexport async function fetchCrudList<T>(apiPath: string, params: Record<string, any>, init?: RequestInit): Promise<ListResponse<T>> {\n const qs = buildCrudQuery(params)\n return readApiResultOrThrow<ListResponse<T>>(`/api/${apiPath}?${qs}`, init, {\n errorMessage: 'Failed to fetch list',\n })\n}\n\nexport function buildCrudExportUrl(apiPath: string, params: Record<string, any>, format: CrudExportFormat): string {\n const qs = buildCrudQuery({ ...params, format })\n return `/api/${apiPath}?${qs}`\n}\n\nexport function buildCrudCsvUrl(apiPath: string, params: Record<string, any>): string {\n return buildCrudExportUrl(apiPath, params, 'csv')\n}\n\nexport async function createCrud<TReturn = Record<string, unknown>>(\n apiPath: string,\n body: any,\n init?: CrudRequestInit<TReturn>,\n): Promise<CrudResponse<TReturn>> {\n const { parseResult, fallbackResult, errorMessage, headers, ...rest } = init ?? {}\n const call = await apiCall<TReturn>(\n `/api/${apiPath}`,\n {\n ...rest,\n method: 'POST',\n headers: mergeHeaders(headers, { 'content-type': 'application/json' }),\n body: JSON.stringify(body),\n },\n {\n parse: parseResult,\n fallback: fallbackResult ?? null,\n },\n )\n if (!call.ok) await raiseCrudError(call.response, errorMessage ?? 'Failed to create')\n return call\n}\n\nexport async function updateCrud<TReturn = Record<string, unknown>>(\n apiPath: string,\n body: any,\n init?: CrudRequestInit<TReturn>,\n): Promise<CrudResponse<TReturn>> {\n const { parseResult, fallbackResult, errorMessage, headers, ...rest } = init ?? {}\n const call = await apiCall<TReturn>(\n `/api/${apiPath}`,\n {\n ...rest,\n method: 'PUT',\n headers: mergeHeaders(headers, { 'content-type': 'application/json' }),\n body: JSON.stringify(body),\n },\n {\n parse: parseResult,\n fallback: fallbackResult ?? null,\n },\n )\n if (!call.ok) await raiseCrudError(call.response, errorMessage ?? 'Failed to update')\n return call\n}\n\nexport async function deleteCrud<TReturn = Record<string, unknown>>(\n apiPath: string,\n id: string,\n init?: CrudRequestInit<TReturn>,\n): Promise<CrudResponse<TReturn>>\nexport async function deleteCrud<TReturn = Record<string, unknown>>(\n apiPath: string,\n options: CrudDeleteOptions<TReturn>,\n): Promise<CrudResponse<TReturn>>\nexport async function deleteCrud<TReturn = Record<string, unknown>>(\n apiPath: string,\n idOrOptions: string | CrudDeleteOptions<TReturn>,\n maybeInit?: CrudRequestInit<TReturn>,\n): Promise<CrudResponse<TReturn>> {\n if (typeof idOrOptions === 'string') {\n const { parseResult, fallbackResult, errorMessage, ...rest } = maybeInit ?? {}\n const call = await apiCall<TReturn>(\n `/api/${apiPath}?id=${encodeURIComponent(idOrOptions)}`,\n {\n ...rest,\n method: 'DELETE',\n },\n {\n parse: parseResult,\n fallback: fallbackResult ?? null,\n },\n )\n if (!call.ok) await raiseCrudError(call.response, errorMessage ?? 'Failed to delete')\n return call\n }\n const { parseResult, fallbackResult, errorMessage, headers, body, id, ...rest } = idOrOptions\n const payload = body ?? (id ? { id } : undefined)\n const requestHeaders =\n payload !== undefined ? mergeHeaders(headers, { 'content-type': 'application/json' }) : headers\n const call = await apiCall<TReturn>(\n `/api/${apiPath}`,\n {\n ...rest,\n method: 'DELETE',\n headers: requestHeaders,\n body: payload !== undefined ? JSON.stringify(payload) : undefined,\n },\n {\n parse: parseResult,\n fallback: fallbackResult ?? null,\n },\n )\n if (!call.ok) await raiseCrudError(call.response, errorMessage ?? 'Failed to delete')\n return call\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["parseResult", "fallbackResult", "errorMessage", "rest", "call"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { isDefVisible } from "./customFieldDefs.js";
|
|
2
|
+
function applyCustomFieldVisibility(columns, defs, mode = "list") {
|
|
3
|
+
const byKey = new Map(defs.map((d) => [d.key, d]));
|
|
4
|
+
const filtered = columns.filter((c) => {
|
|
5
|
+
const key = String(c.accessorKey || "");
|
|
6
|
+
if (!key.startsWith("cf_")) return true;
|
|
7
|
+
const cfKey = key.slice(3);
|
|
8
|
+
const def = byKey.get(cfKey);
|
|
9
|
+
if (!def) return false;
|
|
10
|
+
if (!isDefVisible(def, mode)) return false;
|
|
11
|
+
const currentHeader = c.header;
|
|
12
|
+
const fallbackHeader = typeof currentHeader === "string" && currentHeader.trim().length ? currentHeader : key;
|
|
13
|
+
const label = def.label && def.label.trim().length ? def.label : fallbackHeader;
|
|
14
|
+
if (currentHeader == null || typeof currentHeader === "string") {
|
|
15
|
+
c.header = label;
|
|
16
|
+
}
|
|
17
|
+
const existingMeta = c.meta || {};
|
|
18
|
+
const nextMeta = Object.assign({}, existingMeta, { label });
|
|
19
|
+
c.meta = nextMeta;
|
|
20
|
+
return true;
|
|
21
|
+
});
|
|
22
|
+
const cfEntries = [];
|
|
23
|
+
filtered.forEach((c) => {
|
|
24
|
+
const key = String(c.accessorKey || "");
|
|
25
|
+
if (key.startsWith("cf_")) {
|
|
26
|
+
const cfKey = key.slice(3);
|
|
27
|
+
const def = byKey.get(cfKey);
|
|
28
|
+
cfEntries.push({ col: c, key: cfKey, prio: def?.priority ?? 0 });
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
cfEntries.sort((a, b) => a.prio - b.prio);
|
|
32
|
+
let cfIdx = 0;
|
|
33
|
+
const result = filtered.map((c) => {
|
|
34
|
+
const key = String(c.accessorKey || "");
|
|
35
|
+
if (!key.startsWith("cf_")) return c;
|
|
36
|
+
const next = cfEntries[cfIdx++]?.col ?? c;
|
|
37
|
+
return next;
|
|
38
|
+
});
|
|
39
|
+
const existingCfKeys = new Set(result.map((c) => String(c.accessorKey || "")).filter((k) => k.startsWith("cf_")).map((k) => k.slice(3)));
|
|
40
|
+
const visibleSorted = defs.filter((d) => isDefVisible(d, mode)).sort((a, b) => (a.priority ?? 0) - (b.priority ?? 0));
|
|
41
|
+
const missing = visibleSorted.filter((d) => !existingCfKeys.has(d.key));
|
|
42
|
+
for (const d of missing) {
|
|
43
|
+
const col = {
|
|
44
|
+
accessorKey: `cf_${d.key}`,
|
|
45
|
+
header: d.label || `cf_${d.key}`,
|
|
46
|
+
// Respect responsive priority when provided; default leaves it visible
|
|
47
|
+
meta: { priority: d.priority, label: d.label || `cf_${d.key}` }
|
|
48
|
+
};
|
|
49
|
+
result.push(col);
|
|
50
|
+
}
|
|
51
|
+
return result;
|
|
52
|
+
}
|
|
53
|
+
export {
|
|
54
|
+
applyCustomFieldVisibility
|
|
55
|
+
};
|
|
56
|
+
//# sourceMappingURL=customFieldColumns.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/backend/utils/customFieldColumns.ts"],
|
|
4
|
+
"sourcesContent": ["import type { ColumnDef } from '@tanstack/react-table'\nimport type { CustomFieldDefDto, CustomFieldVisibility } from './customFieldDefs'\nimport { isDefVisible } from './customFieldDefs'\n\n// Filters and annotates columns with custom-field definitions:\n// - Drops cf_* columns when no definition exists or listVisible === false\n// - Uses definition label as header when header is missing\nexport function applyCustomFieldVisibility<T>(columns: ColumnDef<T, any>[], defs: CustomFieldDefDto[], mode: CustomFieldVisibility = 'list'): ColumnDef<T, any>[] {\n const byKey = new Map(defs.map((d) => [d.key, d]))\n // First, filter and annotate headers\n const filtered = columns.filter((c) => {\n const key = String((c as any).accessorKey || '')\n if (!key.startsWith('cf_')) return true\n const cfKey = key.slice(3)\n const def = byKey.get(cfKey)\n if (!def) return false\n if (!isDefVisible(def, mode)) return false\n const currentHeader = (c as any).header\n const fallbackHeader = typeof currentHeader === 'string' && currentHeader.trim().length ? currentHeader : key\n const label = def.label && def.label.trim().length ? def.label : fallbackHeader\n if (currentHeader == null || typeof currentHeader === 'string') {\n (c as any).header = label\n }\n const existingMeta = ((c as any).meta || {}) as Record<string, unknown>\n const nextMeta = Object.assign({}, existingMeta, { label })\n ;(c as any).meta = nextMeta\n return true\n })\n\n // Then, reorder only the cf_* columns by definition priority while preserving\n // the positions of non-cf columns and the count of cf slots.\n const cfEntries: Array<{ col: ColumnDef<T, any>; key: string; prio: number }> = []\n filtered.forEach((c) => {\n const key = String((c as any).accessorKey || '')\n if (key.startsWith('cf_')) {\n const cfKey = key.slice(3)\n const def = byKey.get(cfKey)\n cfEntries.push({ col: c, key: cfKey, prio: def?.priority ?? 0 })\n }\n })\n cfEntries.sort((a, b) => a.prio - b.prio)\n let cfIdx = 0\n const result = filtered.map((c) => {\n const key = String((c as any).accessorKey || '')\n if (!key.startsWith('cf_')) return c\n const next = cfEntries[cfIdx++]?.col ?? c\n return next\n })\n\n // Append any missing cf columns (defs visible but not present in incoming columns)\n const existingCfKeys = new Set<string>(result\n .map((c) => String((c as any).accessorKey || ''))\n .filter((k) => k.startsWith('cf_'))\n .map((k) => k.slice(3)))\n\n const visibleSorted = defs\n .filter((d) => isDefVisible(d, mode))\n .sort((a, b) => (a.priority ?? 0) - (b.priority ?? 0))\n\n const missing = visibleSorted.filter((d) => !existingCfKeys.has(d.key))\n for (const d of missing) {\n const col: ColumnDef<T, any> = {\n accessorKey: `cf_${d.key}` as any,\n header: d.label || `cf_${d.key}`,\n // Respect responsive priority when provided; default leaves it visible\n meta: { priority: (d as any).priority, label: d.label || `cf_${d.key}` } as any,\n }\n result.push(col)\n }\n return result\n}\n"],
|
|
5
|
+
"mappings": "AAEA,SAAS,oBAAoB;AAKtB,SAAS,2BAA8B,SAA8B,MAA2B,OAA8B,QAA6B;AAChK,QAAM,QAAQ,IAAI,IAAI,KAAK,IAAI,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;AAEjD,QAAM,WAAW,QAAQ,OAAO,CAAC,MAAM;AACrC,UAAM,MAAM,OAAQ,EAAU,eAAe,EAAE;AAC/C,QAAI,CAAC,IAAI,WAAW,KAAK,EAAG,QAAO;AACnC,UAAM,QAAQ,IAAI,MAAM,CAAC;AACzB,UAAM,MAAM,MAAM,IAAI,KAAK;AAC3B,QAAI,CAAC,IAAK,QAAO;AACjB,QAAI,CAAC,aAAa,KAAK,IAAI,EAAG,QAAO;AACrC,UAAM,gBAAiB,EAAU;AACjC,UAAM,iBAAiB,OAAO,kBAAkB,YAAY,cAAc,KAAK,EAAE,SAAS,gBAAgB;AAC1G,UAAM,QAAQ,IAAI,SAAS,IAAI,MAAM,KAAK,EAAE,SAAS,IAAI,QAAQ;AACjE,QAAI,iBAAiB,QAAQ,OAAO,kBAAkB,UAAU;AAC9D,MAAC,EAAU,SAAS;AAAA,IACtB;AACA,UAAM,eAAiB,EAAU,QAAQ,CAAC;AAC1C,UAAM,WAAW,OAAO,OAAO,CAAC,GAAG,cAAc,EAAE,MAAM,CAAC;AACzD,IAAC,EAAU,OAAO;AACnB,WAAO;AAAA,EACT,CAAC;AAID,QAAM,YAA0E,CAAC;AACjF,WAAS,QAAQ,CAAC,MAAM;AACtB,UAAM,MAAM,OAAQ,EAAU,eAAe,EAAE;AAC/C,QAAI,IAAI,WAAW,KAAK,GAAG;AACzB,YAAM,QAAQ,IAAI,MAAM,CAAC;AACzB,YAAM,MAAM,MAAM,IAAI,KAAK;AAC3B,gBAAU,KAAK,EAAE,KAAK,GAAG,KAAK,OAAO,MAAM,KAAK,YAAY,EAAE,CAAC;AAAA,IACjE;AAAA,EACF,CAAC;AACD,YAAU,KAAK,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,IAAI;AACxC,MAAI,QAAQ;AACZ,QAAM,SAAS,SAAS,IAAI,CAAC,MAAM;AACjC,UAAM,MAAM,OAAQ,EAAU,eAAe,EAAE;AAC/C,QAAI,CAAC,IAAI,WAAW,KAAK,EAAG,QAAO;AACnC,UAAM,OAAO,UAAU,OAAO,GAAG,OAAO;AACxC,WAAO;AAAA,EACT,CAAC;AAGD,QAAM,iBAAiB,IAAI,IAAY,OACpC,IAAI,CAAC,MAAM,OAAQ,EAAU,eAAe,EAAE,CAAC,EAC/C,OAAO,CAAC,MAAM,EAAE,WAAW,KAAK,CAAC,EACjC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAEzB,QAAM,gBAAgB,KACnB,OAAO,CAAC,MAAM,aAAa,GAAG,IAAI,CAAC,EACnC,KAAK,CAAC,GAAG,OAAO,EAAE,YAAY,MAAM,EAAE,YAAY,EAAE;AAEvD,QAAM,UAAU,cAAc,OAAO,CAAC,MAAM,CAAC,eAAe,IAAI,EAAE,GAAG,CAAC;AACtE,aAAW,KAAK,SAAS;AACvB,UAAM,MAAyB;AAAA,MAC7B,aAAa,MAAM,EAAE,GAAG;AAAA,MACxB,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG;AAAA;AAAA,MAE9B,MAAM,EAAE,UAAW,EAAU,UAAU,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,GAAG;AAAA,IACzE;AACA,WAAO,KAAK,GAAG;AAAA,EACjB;AACA,SAAO;AACT;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { useQuery } from "@tanstack/react-query";
|
|
3
|
+
import { readApiResultOrThrow } from "./apiCall.js";
|
|
4
|
+
function normalizeEntityIds(entityIds) {
|
|
5
|
+
if (entityIds == null) return [];
|
|
6
|
+
const list = Array.isArray(entityIds) ? entityIds : [entityIds];
|
|
7
|
+
const dedup = /* @__PURE__ */ new Set();
|
|
8
|
+
const normalized = [];
|
|
9
|
+
for (const raw of list) {
|
|
10
|
+
const trimmed = String(raw ?? "").trim();
|
|
11
|
+
if (!trimmed || dedup.has(trimmed)) continue;
|
|
12
|
+
dedup.add(trimmed);
|
|
13
|
+
normalized.push(trimmed);
|
|
14
|
+
}
|
|
15
|
+
return normalized;
|
|
16
|
+
}
|
|
17
|
+
function buildDefinitionsQuery(entityIds, options) {
|
|
18
|
+
const params = new URLSearchParams();
|
|
19
|
+
entityIds.forEach((id) => {
|
|
20
|
+
if (id) params.append("entityId", id);
|
|
21
|
+
});
|
|
22
|
+
if (options?.fieldset) params.set("fieldset", options.fieldset);
|
|
23
|
+
return params.toString();
|
|
24
|
+
}
|
|
25
|
+
function normalizeRecord(value) {
|
|
26
|
+
if (!value || typeof value !== "object") return {};
|
|
27
|
+
const out = {};
|
|
28
|
+
for (const [key, raw] of Object.entries(value)) {
|
|
29
|
+
if (!Array.isArray(raw)) continue;
|
|
30
|
+
out[key] = raw;
|
|
31
|
+
}
|
|
32
|
+
return out;
|
|
33
|
+
}
|
|
34
|
+
function preparePayload(data) {
|
|
35
|
+
const items = Array.isArray(data?.items) ? [...data.items] : [];
|
|
36
|
+
items.sort((a, b) => (a.priority ?? 0) - (b.priority ?? 0));
|
|
37
|
+
const fieldsetsByEntity = normalizeRecord(data?.fieldsetsByEntity);
|
|
38
|
+
const entitySettings = data?.entitySettings && typeof data.entitySettings === "object" ? data.entitySettings : {};
|
|
39
|
+
return { items, fieldsetsByEntity, entitySettings };
|
|
40
|
+
}
|
|
41
|
+
async function readDefinitionsViaFetch(entityIds, fetchImpl, options) {
|
|
42
|
+
const query = buildDefinitionsQuery(entityIds, options);
|
|
43
|
+
const res = await fetchImpl(`/api/entities/definitions?${query}`, {
|
|
44
|
+
headers: { "content-type": "application/json" }
|
|
45
|
+
});
|
|
46
|
+
const data = await res.json().catch(() => ({ items: [] }));
|
|
47
|
+
return preparePayload(data);
|
|
48
|
+
}
|
|
49
|
+
async function readDefinitionsViaApi(entityIds, options) {
|
|
50
|
+
const query = buildDefinitionsQuery(entityIds, options);
|
|
51
|
+
const payload = await readApiResultOrThrow(
|
|
52
|
+
`/api/entities/definitions?${query}`,
|
|
53
|
+
{ headers: { "content-type": "application/json" } },
|
|
54
|
+
{
|
|
55
|
+
errorMessage: "Failed to load custom field definitions",
|
|
56
|
+
fallback: { items: [] }
|
|
57
|
+
}
|
|
58
|
+
);
|
|
59
|
+
return preparePayload(payload);
|
|
60
|
+
}
|
|
61
|
+
async function fetchCustomFieldDefinitionsPayload(entityIds, fetchImpl, options) {
|
|
62
|
+
const filtered = normalizeEntityIds(entityIds);
|
|
63
|
+
if (!filtered.length) return { items: [] };
|
|
64
|
+
return fetchImpl ? await readDefinitionsViaFetch(filtered, fetchImpl, options) : await readDefinitionsViaApi(filtered, options);
|
|
65
|
+
}
|
|
66
|
+
async function fetchCustomFieldDefs(entityIds, fetchImpl, options) {
|
|
67
|
+
const payload = await fetchCustomFieldDefinitionsPayload(entityIds, fetchImpl, options);
|
|
68
|
+
return payload.items ?? [];
|
|
69
|
+
}
|
|
70
|
+
function useCustomFieldDefs(entityIds, options = {}) {
|
|
71
|
+
const {
|
|
72
|
+
enabled: enabledOption = true,
|
|
73
|
+
staleTime,
|
|
74
|
+
gcTime,
|
|
75
|
+
keyExtras,
|
|
76
|
+
fetchImpl,
|
|
77
|
+
fieldset
|
|
78
|
+
} = options;
|
|
79
|
+
const normalizedIds = React.useMemo(() => normalizeEntityIds(entityIds), [entityIds]);
|
|
80
|
+
const idsSignature = React.useMemo(() => JSON.stringify(normalizedIds), [normalizedIds]);
|
|
81
|
+
const extrasSignature = React.useMemo(() => JSON.stringify(keyExtras ?? []), [keyExtras]);
|
|
82
|
+
const normalizedFieldset = typeof fieldset === "string" && fieldset.trim().length ? fieldset.trim() : null;
|
|
83
|
+
const queryKey = React.useMemo(
|
|
84
|
+
() => ["customFieldDefs", ...keyExtras ?? [], ...normalizedIds, `fieldset:${normalizedFieldset ?? "default"}`],
|
|
85
|
+
[idsSignature, extrasSignature, normalizedFieldset]
|
|
86
|
+
);
|
|
87
|
+
const enabled = enabledOption && normalizedIds.length > 0;
|
|
88
|
+
return useQuery({
|
|
89
|
+
queryKey,
|
|
90
|
+
queryFn: () => fetchCustomFieldDefs(
|
|
91
|
+
normalizedIds,
|
|
92
|
+
fetchImpl,
|
|
93
|
+
normalizedFieldset ? { fieldset: normalizedFieldset } : void 0
|
|
94
|
+
),
|
|
95
|
+
enabled,
|
|
96
|
+
staleTime: staleTime ?? 5 * 60 * 1e3,
|
|
97
|
+
gcTime: gcTime ?? 30 * 60 * 1e3,
|
|
98
|
+
select: options.select
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
function isDefVisible(def, mode) {
|
|
102
|
+
switch (mode) {
|
|
103
|
+
case "list":
|
|
104
|
+
return def.listVisible !== false;
|
|
105
|
+
case "form":
|
|
106
|
+
return def.formEditable !== false;
|
|
107
|
+
case "filter":
|
|
108
|
+
return !!def.filterable;
|
|
109
|
+
default:
|
|
110
|
+
return true;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
function filterCustomFieldDefs(defs, mode) {
|
|
114
|
+
return defs.filter((d) => isDefVisible(d, mode)).sort((a, b) => (a.priority ?? 0) - (b.priority ?? 0));
|
|
115
|
+
}
|
|
116
|
+
async function invalidateCustomFieldDefs(queryClient, entityIds) {
|
|
117
|
+
const normalizedIds = normalizeEntityIds(entityIds);
|
|
118
|
+
const targetPrefixes = /* @__PURE__ */ new Set(["customFieldDefs", "customFieldForms", "dealFormFields"]);
|
|
119
|
+
if (!normalizedIds.length) {
|
|
120
|
+
await queryClient.invalidateQueries({
|
|
121
|
+
predicate: (query) => Array.isArray(query.queryKey) && typeof query.queryKey[0] === "string" && targetPrefixes.has(query.queryKey[0])
|
|
122
|
+
});
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
await queryClient.invalidateQueries({
|
|
126
|
+
predicate: (query) => {
|
|
127
|
+
if (!Array.isArray(query.queryKey)) return false;
|
|
128
|
+
const [prefix] = query.queryKey;
|
|
129
|
+
if (typeof prefix !== "string" || !targetPrefixes.has(prefix)) return false;
|
|
130
|
+
return normalizedIds.every((id) => query.queryKey.includes(id));
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
export {
|
|
135
|
+
fetchCustomFieldDefinitionsPayload,
|
|
136
|
+
fetchCustomFieldDefs,
|
|
137
|
+
filterCustomFieldDefs,
|
|
138
|
+
invalidateCustomFieldDefs,
|
|
139
|
+
isDefVisible,
|
|
140
|
+
normalizeEntityIds,
|
|
141
|
+
useCustomFieldDefs
|
|
142
|
+
};
|
|
143
|
+
//# sourceMappingURL=customFieldDefs.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/backend/utils/customFieldDefs.ts"],
|
|
4
|
+
"sourcesContent": ["import * as React from 'react'\nimport { useQuery, type UseQueryResult, type QueryClient } from '@tanstack/react-query'\nimport { readApiResultOrThrow } from './apiCall'\nimport type { CustomFieldOptionDto } from '@open-mercato/shared/modules/entities/options'\n\nexport type CustomFieldDefDto = {\n entityId?: string\n key: string\n kind: string\n label?: string\n description?: string\n options?: CustomFieldOptionDto[]\n optionsUrl?: string\n multi?: boolean\n filterable?: boolean\n formEditable?: boolean\n listVisible?: boolean\n editor?: string\n input?: string\n priority?: number\n fieldset?: string\n group?: { code: string; title?: string; hint?: string }\n // attachments-specific config\n maxAttachmentSizeMb?: number\n acceptExtensions?: string[]\n // optional validation rules\n validation?: Array<\n | { rule: 'required'; message: string }\n | { rule: 'date'; message: string }\n | { rule: 'integer'; message: string }\n | { rule: 'float'; message: string }\n | { rule: 'lt' | 'lte' | 'gt' | 'gte'; param: number; message: string }\n | { rule: 'eq' | 'ne'; param: any; message: string }\n | { rule: 'regex'; param: string; message: string }\n >\n dictionaryId?: string\n dictionaryInlineCreate?: boolean\n}\n\nexport type CustomFieldsetGroupDto = {\n code: string\n title?: string\n hint?: string\n}\n\nexport type CustomFieldsetDto = {\n code: string\n label: string\n icon?: string\n description?: string\n groups?: CustomFieldsetGroupDto[]\n}\n\nexport type CustomFieldDefinitionsPayload = {\n items?: CustomFieldDefDto[]\n fieldsetsByEntity?: Record<string, CustomFieldsetDto[]>\n entitySettings?: Record<string, { singleFieldsetPerRecord?: boolean }>\n}\n\nexport function normalizeEntityIds(entityIds: string | string[] | null | undefined): string[] {\n if (entityIds == null) return []\n const list = Array.isArray(entityIds) ? entityIds : [entityIds]\n const dedup = new Set<string>()\n const normalized: string[] = []\n for (const raw of list) {\n const trimmed = String(raw ?? '').trim()\n if (!trimmed || dedup.has(trimmed)) continue\n dedup.add(trimmed)\n normalized.push(trimmed)\n }\n return normalized\n}\n\nexport type CustomFieldDefinitionQueryOptions = {\n fieldset?: string\n}\n\nfunction buildDefinitionsQuery(entityIds: string[], options?: CustomFieldDefinitionQueryOptions): string {\n const params = new URLSearchParams()\n entityIds.forEach((id) => {\n if (id) params.append('entityId', id)\n })\n if (options?.fieldset) params.set('fieldset', options.fieldset)\n return params.toString()\n}\n\ntype CustomFieldDefinitionsResponse = CustomFieldDefinitionsPayload\n\nfunction normalizeRecord<T>(value: unknown): Record<string, T[]> {\n if (!value || typeof value !== 'object') return {}\n const out: Record<string, T[]> = {}\n for (const [key, raw] of Object.entries(value as Record<string, unknown>)) {\n if (!Array.isArray(raw)) continue\n out[key] = raw as T[]\n }\n return out\n}\n\nfunction preparePayload(data: CustomFieldDefinitionsResponse | null | undefined): CustomFieldDefinitionsPayload {\n const items = Array.isArray(data?.items) ? [...data!.items] : []\n items.sort((a, b) => (a.priority ?? 0) - (b.priority ?? 0))\n const fieldsetsByEntity = normalizeRecord<CustomFieldsetDto>(data?.fieldsetsByEntity)\n const entitySettings = (data?.entitySettings && typeof data.entitySettings === 'object'\n ? data.entitySettings\n : {}) as CustomFieldDefinitionsPayload['entitySettings']\n return { items, fieldsetsByEntity, entitySettings }\n}\n\nasync function readDefinitionsViaFetch(\n entityIds: string[],\n fetchImpl: typeof fetch,\n options?: CustomFieldDefinitionQueryOptions,\n): Promise<CustomFieldDefinitionsPayload> {\n const query = buildDefinitionsQuery(entityIds, options)\n const res = await fetchImpl(`/api/entities/definitions?${query}`, {\n headers: { 'content-type': 'application/json' },\n })\n const data = await res.json().catch(() => ({ items: [] }))\n return preparePayload(data)\n}\n\nasync function readDefinitionsViaApi(entityIds: string[], options?: CustomFieldDefinitionQueryOptions): Promise<CustomFieldDefinitionsPayload> {\n const query = buildDefinitionsQuery(entityIds, options)\n const payload = await readApiResultOrThrow<CustomFieldDefinitionsResponse>(\n `/api/entities/definitions?${query}`,\n { headers: { 'content-type': 'application/json' } },\n {\n errorMessage: 'Failed to load custom field definitions',\n fallback: { items: [] },\n },\n )\n return preparePayload(payload)\n}\n\nexport async function fetchCustomFieldDefinitionsPayload(\n entityIds: string | string[],\n fetchImpl?: typeof fetch,\n options?: CustomFieldDefinitionQueryOptions,\n): Promise<CustomFieldDefinitionsPayload> {\n const filtered = normalizeEntityIds(entityIds)\n if (!filtered.length) return { items: [] }\n return fetchImpl\n ? await readDefinitionsViaFetch(filtered, fetchImpl, options)\n : await readDefinitionsViaApi(filtered, options)\n}\n\nexport async function fetchCustomFieldDefs(\n entityIds: string | string[],\n fetchImpl?: typeof fetch,\n options?: CustomFieldDefinitionQueryOptions,\n): Promise<CustomFieldDefDto[]> {\n const payload = await fetchCustomFieldDefinitionsPayload(entityIds, fetchImpl, options)\n return payload.items ?? []\n}\n\nexport type UseCustomFieldDefsOptions<TData = CustomFieldDefDto[]> = {\n enabled?: boolean\n staleTime?: number\n gcTime?: number\n /** @deprecated Custom fetch implementations are no longer needed. */\n fetchImpl?: typeof fetch\n keyExtras?: Array<string | number | boolean | null | undefined>\n fieldset?: string\n select?: (data: CustomFieldDefDto[]) => TData\n}\n\nexport function useCustomFieldDefs<TData = CustomFieldDefDto[]>(\n entityIds: string | string[] | null | undefined,\n options: UseCustomFieldDefsOptions<TData> = {}\n): UseQueryResult<TData> {\n const {\n enabled: enabledOption = true,\n staleTime,\n gcTime,\n keyExtras,\n fetchImpl,\n fieldset,\n } = options\n const normalizedIds = React.useMemo(() => normalizeEntityIds(entityIds), [entityIds])\n const idsSignature = React.useMemo(() => JSON.stringify(normalizedIds), [normalizedIds])\n const extrasSignature = React.useMemo(() => JSON.stringify(keyExtras ?? []), [keyExtras])\n const normalizedFieldset = typeof fieldset === 'string' && fieldset.trim().length ? fieldset.trim() : null\n const queryKey = React.useMemo(\n () => ['customFieldDefs', ...(keyExtras ?? []), ...normalizedIds, `fieldset:${normalizedFieldset ?? 'default'}`],\n [idsSignature, extrasSignature, normalizedFieldset]\n )\n const enabled = enabledOption && normalizedIds.length > 0\n\n return useQuery<CustomFieldDefDto[], Error, TData>({\n queryKey,\n queryFn: () =>\n fetchCustomFieldDefs(\n normalizedIds,\n fetchImpl,\n normalizedFieldset ? { fieldset: normalizedFieldset } : undefined\n ),\n enabled,\n staleTime: staleTime ?? 5 * 60 * 1000,\n gcTime: gcTime ?? 30 * 60 * 1000,\n select: options.select,\n })\n}\n\nexport type CustomFieldVisibility = 'list' | 'form' | 'filter'\n\nexport function isDefVisible(def: CustomFieldDefDto, mode: CustomFieldVisibility): boolean {\n switch (mode) {\n case 'list':\n return def.listVisible !== false\n case 'form':\n return def.formEditable !== false\n case 'filter':\n return !!def.filterable\n default:\n return true\n }\n}\n\nexport function filterCustomFieldDefs(defs: CustomFieldDefDto[], mode: CustomFieldVisibility): CustomFieldDefDto[] {\n return defs\n .filter((d) => isDefVisible(d, mode))\n .sort((a, b) => (a.priority ?? 0) - (b.priority ?? 0))\n}\n\nexport async function invalidateCustomFieldDefs(\n queryClient: QueryClient,\n entityIds?: string | string[] | null,\n): Promise<void> {\n const normalizedIds = normalizeEntityIds(entityIds)\n const targetPrefixes = new Set(['customFieldDefs', 'customFieldForms', 'dealFormFields'])\n if (!normalizedIds.length) {\n await queryClient.invalidateQueries({\n predicate: (query) => Array.isArray(query.queryKey) && typeof query.queryKey[0] === 'string' && targetPrefixes.has(query.queryKey[0] as string),\n })\n return\n }\n await queryClient.invalidateQueries({\n predicate: (query) => {\n if (!Array.isArray(query.queryKey)) return false\n const [prefix] = query.queryKey\n if (typeof prefix !== 'string' || !targetPrefixes.has(prefix)) return false\n return normalizedIds.every((id) => query.queryKey.includes(id))\n },\n })\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { useCustomFieldDefs } from "./customFieldDefs.js";
|
|
3
|
+
import { filterCustomFieldDefs, fetchCustomFieldDefs as loadCustomFieldDefs } from "./customFieldDefs.js";
|
|
4
|
+
import { apiCall } from "./apiCall.js";
|
|
5
|
+
import { CURRENCY_OPTIONS_URL } from "@open-mercato/shared/modules/entities/kinds";
|
|
6
|
+
function buildOptionsUrl(base, query) {
|
|
7
|
+
if (!query) return base;
|
|
8
|
+
try {
|
|
9
|
+
const isAbsolute = /^([a-z][a-z\d+\-.]*:)?\/\//i.test(base);
|
|
10
|
+
const origin = typeof window !== "undefined" ? window.location.origin : "http://localhost";
|
|
11
|
+
const url = isAbsolute ? new URL(base) : new URL(base, origin);
|
|
12
|
+
if (!url.searchParams.has("query")) url.searchParams.append("query", query);
|
|
13
|
+
if (!url.searchParams.has("q")) url.searchParams.append("q", query);
|
|
14
|
+
if (isAbsolute) return url.toString();
|
|
15
|
+
return `${url.pathname}${url.search}`;
|
|
16
|
+
} catch {
|
|
17
|
+
const sep = base.includes("?") ? "&" : "?";
|
|
18
|
+
if (base.includes("query=")) return `${base}${sep}q=${encodeURIComponent(query)}`;
|
|
19
|
+
return `${base}${sep}query=${encodeURIComponent(query)}`;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
async function loadRemoteOptions(url) {
|
|
23
|
+
try {
|
|
24
|
+
const call = await apiCall(url, void 0, { fallback: { items: [] } });
|
|
25
|
+
if (!call.ok) return [];
|
|
26
|
+
const payload = call.result ?? { items: [] };
|
|
27
|
+
const items = Array.isArray(payload?.items) ? payload.items : [];
|
|
28
|
+
return items.map((it) => ({
|
|
29
|
+
value: String(it?.value ?? it),
|
|
30
|
+
label: String(it?.label ?? it?.value ?? it)
|
|
31
|
+
}));
|
|
32
|
+
} catch {
|
|
33
|
+
return [];
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function normalizeOptions(options) {
|
|
37
|
+
if (!Array.isArray(options)) return [];
|
|
38
|
+
return options.map((option) => {
|
|
39
|
+
if (option && typeof option === "object" && "value" in option) {
|
|
40
|
+
const rawValue = option.value;
|
|
41
|
+
const rawLabel = option.label ?? rawValue;
|
|
42
|
+
const value2 = String(rawValue);
|
|
43
|
+
const label = typeof rawLabel === "string" ? rawLabel : String(rawLabel);
|
|
44
|
+
return { value: value2, label };
|
|
45
|
+
}
|
|
46
|
+
const value = String(option);
|
|
47
|
+
return { value, label: value.charAt(0).toUpperCase() + value.slice(1) };
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
function buildFilterDefsFromCustomFields(defs) {
|
|
51
|
+
const f = [];
|
|
52
|
+
const visible = filterCustomFieldDefs(defs, "filter");
|
|
53
|
+
const seenKeys = /* @__PURE__ */ new Set();
|
|
54
|
+
for (const d of visible) {
|
|
55
|
+
const keyLower = String(d.key).toLowerCase();
|
|
56
|
+
if (seenKeys.has(keyLower)) continue;
|
|
57
|
+
seenKeys.add(keyLower);
|
|
58
|
+
const id = `cf_${d.key}`;
|
|
59
|
+
const label = d.label || d.key;
|
|
60
|
+
if (d.kind === "boolean") {
|
|
61
|
+
f.push({ id, label, type: "checkbox" });
|
|
62
|
+
} else if (d.kind === "select" || d.kind === "currency" || d.kind === "relation" || d.kind === "dictionary") {
|
|
63
|
+
const options = normalizeOptions(d.options);
|
|
64
|
+
const base = { id: d.multi ? `${id}In` : id, label, type: "select", multiple: !!d.multi, options };
|
|
65
|
+
const optionsUrl = d.kind === "currency" ? CURRENCY_OPTIONS_URL : d.optionsUrl;
|
|
66
|
+
if (optionsUrl) {
|
|
67
|
+
;
|
|
68
|
+
base.loadOptions = async (query) => {
|
|
69
|
+
const url = buildOptionsUrl(optionsUrl, query);
|
|
70
|
+
return loadRemoteOptions(url);
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
f.push(base);
|
|
74
|
+
} else if (d.kind === "text" && d.multi) {
|
|
75
|
+
const base = {
|
|
76
|
+
id: `${id}In`,
|
|
77
|
+
label,
|
|
78
|
+
type: "tags",
|
|
79
|
+
// If static options provided, pass them for suggestions
|
|
80
|
+
options: normalizeOptions(d.options)
|
|
81
|
+
};
|
|
82
|
+
if (d.optionsUrl) {
|
|
83
|
+
;
|
|
84
|
+
base.loadOptions = async (query) => {
|
|
85
|
+
const url = buildOptionsUrl(d.optionsUrl, query);
|
|
86
|
+
return loadRemoteOptions(url);
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
f.push(base);
|
|
90
|
+
} else {
|
|
91
|
+
f.push({ id, label, type: "text" });
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
const out = [];
|
|
95
|
+
const seen = /* @__PURE__ */ new Set();
|
|
96
|
+
for (const item of f) {
|
|
97
|
+
if (seen.has(item.id)) continue;
|
|
98
|
+
seen.add(item.id);
|
|
99
|
+
out.push(item);
|
|
100
|
+
}
|
|
101
|
+
const order = new Map(visible.map((v, idx) => [v.key, idx]));
|
|
102
|
+
out.sort((a, b) => (order.get(a.id.replace(/^cf_/, "").replace(/In$/, "")) ?? 0) - (order.get(b.id.replace(/^cf_/, "").replace(/In$/, "")) ?? 0));
|
|
103
|
+
return out;
|
|
104
|
+
}
|
|
105
|
+
async function fetchCustomFieldFilterDefs(entityIds, fetchImpl, options) {
|
|
106
|
+
const defs = await loadCustomFieldDefs(
|
|
107
|
+
entityIds,
|
|
108
|
+
fetchImpl,
|
|
109
|
+
options?.fieldset ? { fieldset: options.fieldset } : void 0
|
|
110
|
+
);
|
|
111
|
+
return buildFilterDefsFromCustomFields(defs);
|
|
112
|
+
}
|
|
113
|
+
function useCustomFieldFilterDefs(entityIds, options = {}) {
|
|
114
|
+
const { select, ...rest } = options;
|
|
115
|
+
const selectFn = React.useCallback(
|
|
116
|
+
(defs) => select ? select(defs) : buildFilterDefsFromCustomFields(defs),
|
|
117
|
+
[select]
|
|
118
|
+
);
|
|
119
|
+
return useCustomFieldDefs(entityIds, { ...rest, select: selectFn });
|
|
120
|
+
}
|
|
121
|
+
export {
|
|
122
|
+
buildFilterDefsFromCustomFields,
|
|
123
|
+
fetchCustomFieldFilterDefs,
|
|
124
|
+
useCustomFieldFilterDefs
|
|
125
|
+
};
|
|
126
|
+
//# sourceMappingURL=customFieldFilters.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/backend/utils/customFieldFilters.ts"],
|
|
4
|
+
"sourcesContent": ["import * as React from 'react'\nimport { useCustomFieldDefs, type UseCustomFieldDefsOptions } from './customFieldDefs'\nimport { Filter } from '@open-mercato/shared/lib/query/types'\nimport type { FilterDef } from '../FilterOverlay'\nimport type { CustomFieldDefDto } from './customFieldDefs'\nexport type { CustomFieldDefDto }\nimport { filterCustomFieldDefs, fetchCustomFieldDefs as loadCustomFieldDefs } from './customFieldDefs'\nimport { type UseQueryResult } from '@tanstack/react-query'\nimport { apiCall } from './apiCall'\nimport { CURRENCY_OPTIONS_URL } from '@open-mercato/shared/modules/entities/kinds'\n\nfunction buildOptionsUrl(base: string, query?: string): string {\n if (!query) return base\n try {\n const isAbsolute = /^([a-z][a-z\\d+\\-.]*:)?\\/\\//i.test(base)\n const origin = typeof window !== 'undefined' ? window.location.origin : 'http://localhost'\n const url = isAbsolute ? new URL(base) : new URL(base, origin)\n if (!url.searchParams.has('query')) url.searchParams.append('query', query)\n if (!url.searchParams.has('q')) url.searchParams.append('q', query)\n if (isAbsolute) return url.toString()\n return `${url.pathname}${url.search}`\n } catch {\n const sep = base.includes('?') ? '&' : '?'\n if (base.includes('query=')) return `${base}${sep}q=${encodeURIComponent(query)}`\n return `${base}${sep}query=${encodeURIComponent(query)}`\n }\n}\n\ntype OptionsResponse = { items?: unknown[] }\n\nasync function loadRemoteOptions(url: string): Promise<Array<{ value: string; label: string }>> {\n try {\n const call = await apiCall<OptionsResponse>(url, undefined, { fallback: { items: [] } })\n if (!call.ok) return []\n const payload = call.result ?? { items: [] }\n const items = Array.isArray(payload?.items) ? payload.items : []\n return items.map((it: any) => ({\n value: String(it?.value ?? it),\n label: String(it?.label ?? it?.value ?? it),\n }))\n } catch {\n return []\n }\n}\n\ntype RawOption = string | number | { value?: unknown; label?: unknown }\n\nfunction normalizeOptions(options?: RawOption[]): Array<{ value: string; label: string }> {\n if (!Array.isArray(options)) return []\n return options.map((option) => {\n if (option && typeof option === 'object' && 'value' in option) {\n const rawValue = (option as any).value\n const rawLabel = (option as any).label ?? rawValue\n const value = String(rawValue)\n const label = typeof rawLabel === 'string' ? rawLabel : String(rawLabel)\n return { value, label }\n }\n const value = String(option)\n return { value, label: value.charAt(0).toUpperCase() + value.slice(1) }\n })\n}\n\nexport function buildFilterDefsFromCustomFields(defs: CustomFieldDefDto[]): FilterDef[] {\n const f: FilterDef[] = []\n const visible = filterCustomFieldDefs(defs, 'filter')\n const seenKeys = new Set<string>() // case-insensitive de-dupe by key\n for (const d of visible) {\n const keyLower = String(d.key).toLowerCase()\n if (seenKeys.has(keyLower)) continue\n seenKeys.add(keyLower)\n const id = `cf_${d.key}`\n const label = d.label || d.key\n if (d.kind === 'boolean') {\n f.push({ id, label, type: 'checkbox' })\n } else if (d.kind === 'select' || d.kind === 'currency' || d.kind === 'relation' || d.kind === 'dictionary') {\n const options = normalizeOptions(d.options)\n const base: FilterDef = { id: d.multi ? `${id}In` : id, label, type: 'select', multiple: !!d.multi, options }\n // When optionsUrl is provided, allow async options loading for filters too\n const optionsUrl = d.kind === 'currency' ? CURRENCY_OPTIONS_URL : d.optionsUrl\n if (optionsUrl) {\n ;(base as FilterDef).loadOptions = async (query?: string) => {\n const url = buildOptionsUrl(optionsUrl, query)\n return loadRemoteOptions(url)\n }\n }\n f.push(base)\n } else if (d.kind === 'text' && d.multi) {\n // Multi-text custom field \u2192 use tags input in filters\n const base: FilterDef = {\n id: `${id}In`,\n label,\n type: 'tags',\n // If static options provided, pass them for suggestions\n options: normalizeOptions(d.options),\n } as any\n // Enable async suggestions when optionsUrl provided\n if (d.optionsUrl) {\n ;(base as any).loadOptions = async (query?: string) => {\n const url = buildOptionsUrl(d.optionsUrl!, query)\n return loadRemoteOptions(url)\n }\n }\n f.push(base)\n } else {\n f.push({ id, label, type: 'text' })\n }\n }\n // De-duplicate by id in case of overlaps; keep first occurrence\n const out: FilterDef[] = []\n const seen = new Set<string>()\n for (const item of f) {\n if (seen.has(item.id)) continue\n seen.add(item.id)\n out.push(item)\n }\n // Preserve the original visible order (already sorted by priority) by mapping back\n const order = new Map(visible.map((v, idx) => [v.key, idx]))\n out.sort((a, b) => (order.get(a.id.replace(/^cf_/, '').replace(/In$/, '')) ?? 0) - (order.get(b.id.replace(/^cf_/, '').replace(/In$/, '')) ?? 0))\n return out\n}\n\nexport async function fetchCustomFieldFilterDefs(\n entityIds: string | string[],\n fetchImpl?: typeof fetch,\n options?: { fieldset?: string },\n): Promise<FilterDef[]> {\n const defs: CustomFieldDefDto[] = await loadCustomFieldDefs(\n entityIds,\n fetchImpl,\n options?.fieldset ? { fieldset: options.fieldset } : undefined,\n )\n return buildFilterDefsFromCustomFields(defs)\n}\n\nexport function useCustomFieldFilterDefs(\n entityIds: string | string[] | null | undefined,\n options: UseCustomFieldDefsOptions<FilterDef[]> = {}\n): UseQueryResult<FilterDef[]> {\n const { select, ...rest } = options\n const selectFn = React.useCallback(\n (defs: CustomFieldDefDto[]) => (select ? select(defs) : buildFilterDefsFromCustomFields(defs)),\n [select]\n )\n return useCustomFieldDefs<FilterDef[]>(entityIds, { ...rest, select: selectFn })\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["value"]
|
|
7
|
+
}
|