@plumile/backoffice-react 0.1.156 → 0.1.158

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.
Files changed (51) hide show
  1. package/lib/esm/auth/authRefreshNotice.css.js +1 -0
  2. package/lib/esm/auth/login/loginPage.css.js +0 -1
  3. package/lib/esm/auth/login/synchronizeAuthStatusQuery.js.map +1 -1
  4. package/lib/esm/components/backoffice/actions/BackofficeEntityActionFormDialog.js.map +1 -1
  5. package/lib/esm/components/backoffice/detail/BackofficeDetailRelationListBlock.js +1 -1
  6. package/lib/esm/components/backoffice/detail/BackofficeDetailRelationListBlock.js.map +1 -1
  7. package/lib/esm/components/backoffice/detail/BackofficeRelationsSummaryGrid.js.map +1 -1
  8. package/lib/esm/components/backoffice/filters/backofficeFilterAction.css.js +1 -0
  9. package/lib/esm/components/backoffice/refs/BackofficeLazyEntityCount.js +31 -0
  10. package/lib/esm/components/backoffice/refs/BackofficeLazyEntityCount.js.map +1 -0
  11. package/lib/esm/components/backoffice/refs/BackofficeRelatedCountLink.js +36 -32
  12. package/lib/esm/components/backoffice/refs/BackofficeRelatedCountLink.js.map +1 -1
  13. package/lib/esm/components/backoffice/refs/backofficeEntityIdRef.css.js +0 -1
  14. package/lib/esm/hooks/useBackofficeAuth.js.map +1 -1
  15. package/lib/esm/i18n/locales/en/backofficeReact.js +0 -1
  16. package/lib/esm/i18n/locales/en/backofficeReact.js.map +1 -1
  17. package/lib/esm/i18n/locales/fr/backofficeReact.js +0 -1
  18. package/lib/esm/i18n/locales/fr/backofficeReact.js.map +1 -1
  19. package/lib/esm/index.js +33 -32
  20. package/lib/esm/node_modules/relay-test-utils/index.js.map +1 -1
  21. package/lib/esm/pages/BackofficeEntityDetailPage.js +200 -214
  22. package/lib/esm/pages/BackofficeEntityDetailPage.js.map +1 -1
  23. package/lib/esm/pages/BackofficeEntityDetailPage.view-helpers.js +0 -1
  24. package/lib/esm/pages/BackofficeEntityDetailPage.view-helpers.js.map +1 -1
  25. package/lib/esm/pages/BackofficeEntityListPage.helpers.js +2 -2
  26. package/lib/esm/pages/BackofficeEntityListPage.helpers.js.map +1 -1
  27. package/lib/esm/pages/BackofficeEntityListPage.js +76 -269
  28. package/lib/esm/pages/BackofficeEntityListPage.js.map +1 -1
  29. package/lib/esm/relay/connectionUtils.js +1 -1
  30. package/lib/esm/relay/connectionUtils.js.map +1 -1
  31. package/lib/esm/subscriptions/useCursorResumableSubscription.js +18 -4
  32. package/lib/esm/subscriptions/useCursorResumableSubscription.js.map +1 -1
  33. package/lib/types/components/backoffice/detail/BackofficeDetailRelationListBlock.d.ts.map +1 -1
  34. package/lib/types/components/backoffice/detail/BackofficeRelationsSummaryGrid.d.ts +1 -1
  35. package/lib/types/components/backoffice/detail/BackofficeRelationsSummaryGrid.d.ts.map +1 -1
  36. package/lib/types/components/backoffice/refs/BackofficeLazyEntityCount.d.ts +8 -0
  37. package/lib/types/components/backoffice/refs/BackofficeLazyEntityCount.d.ts.map +1 -0
  38. package/lib/types/components/backoffice/refs/BackofficeRelatedCountLink.d.ts +1 -1
  39. package/lib/types/components/backoffice/refs/BackofficeRelatedCountLink.d.ts.map +1 -1
  40. package/lib/types/i18n/resources.d.ts +0 -2
  41. package/lib/types/i18n/resources.d.ts.map +1 -1
  42. package/lib/types/index.d.ts +1 -0
  43. package/lib/types/index.d.ts.map +1 -1
  44. package/lib/types/pages/BackofficeEntityDetailPage.d.ts.map +1 -1
  45. package/lib/types/pages/BackofficeEntityDetailPage.view-helpers.d.ts +2 -3
  46. package/lib/types/pages/BackofficeEntityDetailPage.view-helpers.d.ts.map +1 -1
  47. package/lib/types/pages/BackofficeEntityListPage.d.ts.map +1 -1
  48. package/lib/types/pages/BackofficeEntityListPage.helpers.d.ts +1 -6
  49. package/lib/types/pages/BackofficeEntityListPage.helpers.d.ts.map +1 -1
  50. package/lib/types/subscriptions/useCursorResumableSubscription.d.ts.map +1 -1
  51. package/package.json +16 -16
@@ -1,3 +1,4 @@
1
+ /* empty css */
1
2
  /* empty css */
2
3
  //#region src/auth/authRefreshNotice.css.ts
3
4
  var e = "txvbqbqhu txvbqbrff txvbqbry7 txvbqbp5g txvbqb13ik txvbqb1auw txvbqblx6 txvbqb13l3 txvbqbdjn txvbqbtxc txvbqbegv";
@@ -1,4 +1,3 @@
1
- /* empty css */
2
1
  /* empty css */
3
2
  /* empty css */
4
3
  //#region src/auth/login/loginPage.css.ts
@@ -1 +1 @@
1
- {"version":3,"file":"synchronizeAuthStatusQuery.js","names":[],"sources":["../../../../src/auth/login/synchronizeAuthStatusQuery.ts"],"sourcesContent":["import RelayRuntime, {\n type GraphQLTaggedNode,\n type IEnvironment,\n type OperationType,\n} from 'relay-runtime';\n\nconst { fetchQuery } = RelayRuntime;\n\ntype AuthStatusQueryResponse = {\n readonly isLoggedIn?: boolean | null;\n};\n\n/**\n * Forces a fresh auth-status read from network to avoid stale cache guards\n * right after login mutations complete.\n */\nexport async function synchronizeAuthStatusQuery<TQuery extends OperationType>(\n environment: IEnvironment,\n query: GraphQLTaggedNode,\n): Promise<boolean> {\n const response = await fetchQuery<TQuery>(\n environment,\n query,\n {},\n { fetchPolicy: 'network-only' },\n ).toPromise();\n\n const isLoggedIn = (response as AuthStatusQueryResponse | null | undefined)\n ?.isLoggedIn;\n return isLoggedIn === true;\n}\n"],"mappings":";;AAMA,IAAM,EAAE,YAAA,MAAe;AAUvB,eAAsB,EACpB,GACA,GACkB;CAUlB,QAFoB,MAPG,EACrB,GACA,GACA,CAAC,GACD,EAAE,aAAa,eAAe,CAChC,EAAE,UAAU,IAGR,eACkB;AACxB"}
1
+ {"version":3,"file":"synchronizeAuthStatusQuery.js","names":[],"sources":["../../../../src/auth/login/synchronizeAuthStatusQuery.ts"],"sourcesContent":["import RelayRuntime, {\n type GraphQLTaggedNode,\n type IEnvironment,\n type OperationType,\n} from 'relay-runtime';\n\nconst { fetchQuery } = RelayRuntime;\n\ntype AuthStatusQueryResponse = {\n readonly isLoggedIn?: boolean | null;\n};\n\n/**\n * Forces a fresh auth-status read from network to avoid stale cache guards\n * right after login mutations complete.\n */\nexport async function synchronizeAuthStatusQuery<TQuery extends OperationType>(\n environment: IEnvironment,\n query: GraphQLTaggedNode,\n): Promise<boolean> {\n const response = await fetchQuery<TQuery>(\n environment,\n query,\n {},\n { fetchPolicy: 'network-only' },\n ).toPromise();\n\n const isLoggedIn = (response as AuthStatusQueryResponse | null | undefined)\n ?.isLoggedIn;\n return isLoggedIn === true;\n}\n"],"mappings":";;AAMA,IAAM,EAAE,kBAAe;AAUvB,eAAsB,EACpB,GACA,GACkB;CAUlB,QAFoB,MAPG,EACrB,GACA,GACA,CAAC,GACD,EAAE,aAAa,eAAe,CAChC,EAAE,UAAU,IAGR,eACkB;AACxB"}
@@ -1 +1 @@
1
- {"version":3,"file":"BackofficeEntityActionFormDialog.js","names":[],"sources":["../../../../../src/components/backoffice/actions/BackofficeEntityActionFormDialog.tsx"],"sourcesContent":["import {\n type FormEvent,\n type JSX,\n useCallback,\n useContext,\n useEffect,\n useId,\n useMemo,\n useState,\n} from 'react';\nimport type { TFunction } from 'i18next';\nimport { useTranslation } from 'react-i18next';\nimport * as ReactRelay from 'react-relay';\nimport {\n type MutationPayloadBase,\n resolveMutationOutcome,\n} from '../../../relay/mutationResult.js';\nimport { Button } from '@plumile/ui/atomic/atoms/button/Button.js';\nimport { Input } from '@plumile/ui/atomic/atoms/input/Input.js';\nimport { Label } from '@plumile/ui/atomic/atoms/label/Label.js';\nimport { Modal } from '@plumile/ui/atomic/atoms/modal/Modal.js';\nimport { Textarea } from '@plumile/ui/atomic/atoms/textarea/Textarea.js';\nimport { CheckboxField } from '@plumile/ui/atomic/molecules/checkbox_field/CheckboxField.js';\nimport { Form } from '@plumile/ui/atomic/molecules/form/Form.js';\nimport { FormError } from '@plumile/ui/atomic/molecules/form_error/FormError.js';\nimport { FormGroup } from '@plumile/ui/atomic/molecules/form/FormGroup.js';\nimport { HighlightCode } from '@plumile/ui/atomic/molecules/highlight/HighlightCode.js';\nimport { useToast } from '@plumile/ui/atomic/molecules/toast/ToastProvider.js';\nimport { BackofficeFormSection } from '@plumile/ui/backoffice/molecules/backoffice_form_section/BackofficeFormSection.js';\nimport { SimpleSelect } from '@plumile/ui/components/select/SimpleSelect.js';\nimport type {\n BackofficeEntityActionFormFieldSpec,\n BackofficeEntityFormMutationActionSpec,\n I18nLabel,\n} from '@plumile/backoffice-core/types.js';\n\nimport { useBackofficeReactTranslation } from '../../../i18n/useBackofficeReactTranslation.js';\nimport { useBackofficeConfig } from '../../../provider/BackofficeConfigContext.js';\nimport { EntityIdFilterField } from '../filters/EntityIdFilterField.js';\nimport { EntityIdPickerDialog } from '../pickers/EntityIdPickerDialog.js';\nimport {\n resolveToastSpec,\n resolveToastViewActions,\n} from './toastViewAction.js';\n\nconst { commitMutation, useRelayEnvironment } = ReactRelay;\nimport RoutingContext from '@plumile/router/routing/RoutingContext.js';\n\nimport * as styles from './backofficeEntityActionFormDialog.css.js';\n\nexport type BackofficeEntityActionFormDialogProps<Node> = {\n isOpen: boolean;\n action: BackofficeEntityFormMutationActionSpec<Node>;\n node: Node;\n onClose: () => void;\n onSuccess?: () => void;\n};\n\nconst resolveLabel = (label: I18nLabel, tApp: TFunction): string => {\n return label(tApp);\n};\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> => {\n return typeof value === 'object' && value != null && !Array.isArray(value);\n};\n\nconst extractMutationPayload = (\n response: unknown,\n): MutationPayloadBase | null => {\n if (!isPlainObject(response)) {\n return null;\n }\n\n for (const value of Object.values(response)) {\n if (isPlainObject(value) && ('status' in value || 'result' in value)) {\n return value;\n }\n }\n\n return null;\n};\n\nconst buildDefaultValues = (\n fields: readonly BackofficeEntityActionFormFieldSpec[],\n): Record<string, unknown> => {\n const output: Record<string, unknown> = {};\n fields.forEach((field) => {\n if (field.kind === 'boolean') {\n output[field.id] = field.defaultValue ?? false;\n return;\n }\n if (field.kind === 'multiEnum') {\n output[field.id] = field.defaultValue ?? [];\n return;\n }\n if (field.defaultValue != null) {\n output[field.id] = field.defaultValue;\n return;\n }\n output[field.id] = '';\n });\n return output;\n};\n\nconst normalizeInitialValue = (\n field: BackofficeEntityActionFormFieldSpec,\n value: unknown,\n): unknown => {\n if (field.kind === 'number') {\n if (typeof value === 'number') {\n return String(value);\n }\n if (typeof value === 'string') {\n return value;\n }\n return '';\n }\n if (field.kind === 'multiEnum') {\n if (Array.isArray(value)) {\n return value.filter((entry): entry is string => {\n return typeof entry === 'string' && entry.trim() !== '';\n });\n }\n return [];\n }\n if (field.kind === 'boolean') {\n return value === true;\n }\n if (typeof value === 'string') {\n return value;\n }\n return value ?? '';\n};\n\nconst buildInitialValues = <Node,>(\n action: BackofficeEntityFormMutationActionSpec<Node>,\n node: Node,\n): Record<string, unknown> => {\n const defaults = buildDefaultValues(action.fields);\n if (action.getInitialValues == null) {\n return defaults;\n }\n const overrides = action.getInitialValues(node);\n const next: Record<string, unknown> = { ...defaults };\n action.fields.forEach((field) => {\n if (!(field.id in overrides)) {\n return;\n }\n next[field.id] = normalizeInitialValue(field, overrides[field.id]);\n });\n return next;\n};\n\nexport const BackofficeEntityActionFormDialog = <Node,>({\n isOpen,\n action,\n node,\n onClose,\n onSuccess,\n}: BackofficeEntityActionFormDialogProps<Node>): JSX.Element | null => {\n const { t: tApp } = useTranslation();\n const { t } = useBackofficeReactTranslation();\n const { entities } = useBackofficeConfig();\n const routing = useContext(RoutingContext);\n const environment = useRelayEnvironment();\n const toast = useToast();\n const formId = useId();\n\n const [values, setValues] = useState<Record<string, unknown>>({});\n const [formError, setFormError] = useState<string | null>(null);\n const [fieldErrors, setFieldErrors] = useState<Record<string, string>>({});\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [resultValue, setResultValue] = useState<string | null>(null);\n const [resultResponse, setResultResponse] = useState<unknown>(null);\n const [activeEntityPicker, setActiveEntityPicker] = useState<{\n fieldId: string;\n entity: string;\n label: string;\n } | null>(null);\n\n useEffect(() => {\n if (!isOpen) {\n return;\n }\n setValues(buildInitialValues(action, node));\n setFormError(null);\n setFieldErrors({});\n setResultValue(null);\n setResultResponse(null);\n }, [action, isOpen, node]);\n\n const handleClose = useCallback(() => {\n if (isSubmitting) {\n return;\n }\n onClose();\n }, [isSubmitting, onClose]);\n\n const setFieldValue = useCallback((fieldId: string, value: unknown) => {\n setValues((current) => {\n return { ...current, [fieldId]: value };\n });\n setFieldErrors((current) => {\n if (current[fieldId] == null) {\n return current;\n }\n const { [fieldId]: removedValue, ...next } = current;\n return next;\n });\n }, []);\n\n const title = resolveLabel(action.label, tApp);\n\n const resolveRequiredError = useCallback(\n (fieldLabel: string): string => {\n return t('actions.form.errors.required', {\n label: fieldLabel,\n });\n },\n [t],\n );\n\n const resolveInvalidNumberError = useCallback(\n (fieldLabel: string): string => {\n return t('actions.form.errors.invalidNumber', {\n label: fieldLabel,\n });\n },\n [t],\n );\n\n const resolveInvalidJsonError = useCallback(\n (fieldLabel: string): string => {\n return t('actions.form.errors.invalidJson', {\n label: fieldLabel,\n });\n },\n [t],\n );\n\n const resolveInvalidJsonObjectError = useCallback(\n (fieldLabel: string): string => {\n return t('actions.form.errors.invalidJsonObject', {\n label: fieldLabel,\n });\n },\n [t],\n );\n\n const resolveInvalidJsonArrayError = useCallback(\n (fieldLabel: string): string => {\n return t('actions.form.errors.invalidJsonArray', {\n label: fieldLabel,\n });\n },\n [t],\n );\n\n const buildPayload = useCallback(():\n | { values: Record<string, unknown> }\n | { error: string; fieldId?: string } => {\n const output: Record<string, unknown> = {};\n\n for (const field of action.fields) {\n const fieldLabel = resolveLabel(field.label, tApp);\n const rawValue = values[field.id];\n\n switch (field.kind) {\n case 'text': {\n let value = '';\n if (typeof rawValue === 'string') {\n value = rawValue.trim();\n }\n if (value === '') {\n if (field.required) {\n return {\n error: resolveRequiredError(fieldLabel),\n fieldId: field.id,\n };\n }\n break;\n }\n output[field.id] = value;\n break;\n }\n case 'textarea': {\n let value = '';\n if (typeof rawValue === 'string') {\n value = rawValue.trim();\n }\n if (value === '') {\n if (field.required) {\n return {\n error: resolveRequiredError(fieldLabel),\n fieldId: field.id,\n };\n }\n break;\n }\n output[field.id] = value;\n break;\n }\n case 'number': {\n let valueString = '';\n if (typeof rawValue === 'string') {\n valueString = rawValue.trim();\n } else if (\n typeof rawValue === 'number' &&\n Number.isFinite(rawValue)\n ) {\n valueString = String(rawValue);\n }\n if (valueString === '') {\n if (field.required) {\n return {\n error: resolveRequiredError(fieldLabel),\n fieldId: field.id,\n };\n }\n break;\n }\n const parsed = Number(valueString);\n if (!Number.isFinite(parsed)) {\n return {\n error: resolveInvalidNumberError(fieldLabel),\n fieldId: field.id,\n };\n }\n output[field.id] = parsed;\n break;\n }\n case 'json': {\n let valueString = '';\n if (typeof rawValue === 'string') {\n valueString = rawValue.trim();\n }\n if (valueString === '') {\n if (field.required) {\n return {\n error: resolveRequiredError(fieldLabel),\n fieldId: field.id,\n };\n }\n break;\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(valueString);\n } catch {\n return {\n error: resolveInvalidJsonError(fieldLabel),\n fieldId: field.id,\n };\n }\n\n const jsonType = field.jsonType ?? 'object';\n if (jsonType === 'object' && !isPlainObject(parsed)) {\n return {\n error: resolveInvalidJsonObjectError(fieldLabel),\n fieldId: field.id,\n };\n }\n if (jsonType === 'array' && !Array.isArray(parsed)) {\n return {\n error: resolveInvalidJsonArrayError(fieldLabel),\n fieldId: field.id,\n };\n }\n\n output[field.id] = parsed;\n break;\n }\n case 'enum': {\n let value = '';\n if (typeof rawValue === 'string') {\n value = rawValue.trim();\n }\n if (value === '') {\n if (field.required) {\n return {\n error: resolveRequiredError(fieldLabel),\n fieldId: field.id,\n };\n }\n break;\n }\n output[field.id] = value;\n break;\n }\n case 'boolean': {\n output[field.id] = rawValue === true;\n break;\n }\n case 'entityId': {\n let value = '';\n if (typeof rawValue === 'string') {\n value = rawValue.trim();\n }\n if (value === '') {\n if (field.required) {\n return {\n error: resolveRequiredError(fieldLabel),\n fieldId: field.id,\n };\n }\n break;\n }\n output[field.id] = value;\n break;\n }\n case 'multiEnum': {\n let list: string[] = [];\n if (Array.isArray(rawValue)) {\n list = rawValue.filter((entry): entry is string => {\n return typeof entry === 'string' && entry.trim() !== '';\n });\n }\n if (list.length === 0) {\n if (field.required) {\n return {\n error: resolveRequiredError(fieldLabel),\n fieldId: field.id,\n };\n }\n break;\n }\n output[field.id] = list;\n break;\n }\n default: {\n break;\n }\n }\n }\n\n return { values: output };\n }, [\n action.fields,\n resolveInvalidJsonArrayError,\n resolveInvalidJsonError,\n resolveInvalidJsonObjectError,\n resolveInvalidNumberError,\n resolveRequiredError,\n tApp,\n values,\n ]);\n\n const handleSubmit = useCallback(() => {\n if (isSubmitting) {\n return;\n }\n\n setFormError(null);\n setFieldErrors({});\n\n const payload = buildPayload();\n if ('error' in payload) {\n setFormError(payload.error);\n if (payload.fieldId != null) {\n setFieldErrors({ [payload.fieldId]: payload.error });\n }\n return;\n }\n\n let variables: ReturnType<typeof action.getVariables>;\n try {\n variables = action.getVariables(node, payload.values);\n } catch {\n const message = t('actions.form.errors.invalidPayload');\n setFormError(message);\n return;\n }\n\n setIsSubmitting(true);\n commitMutation(environment, {\n mutation: action.mutation,\n variables,\n updater: (store) => {\n action.updater?.(store, node);\n },\n onCompleted: (response) => {\n setIsSubmitting(false);\n const mutationPayload = extractMutationPayload(response);\n if (mutationPayload != null) {\n let defaultErrorMessage = t('actions.form.errors.invalidPayload');\n if (action.toasts?.error?.message != null) {\n defaultErrorMessage = resolveLabel(\n action.toasts.error.message,\n tApp,\n );\n } else if (action.toasts?.error?.title != null) {\n defaultErrorMessage = resolveLabel(action.toasts.error.title, tApp);\n }\n\n const outcome = resolveMutationOutcome(mutationPayload, {\n defaultErrorMessage,\n mapReason: (reason) => {\n const mapped = action.mapErrorReason?.(reason, node);\n if (mapped == null) {\n return null;\n }\n if (typeof mapped === 'function') {\n return resolveLabel(mapped, tApp);\n }\n return String(mapped);\n },\n });\n if (!outcome.ok) {\n const error = new Error(outcome.message);\n setFormError(outcome.message);\n action.onError?.(error, node);\n if (action.toasts?.error != null) {\n const toastTitle = resolveLabel(action.toasts.error.title, tApp);\n let toastMessage: string | undefined;\n if (action.toasts.error.message != null) {\n toastMessage = resolveLabel(action.toasts.error.message, tApp);\n }\n toast.error(toastTitle, toastMessage);\n }\n return;\n }\n }\n\n action.onCompleted?.(response, node);\n\n let hasCustomResult = false;\n if (action.result?.render != null) {\n const renderedResult = action.result.render(response, node);\n if (renderedResult != null) {\n hasCustomResult = true;\n setResultResponse(response);\n }\n }\n if (action.toasts?.success != null) {\n const toastSpec = resolveToastSpec(action.toasts.success, tApp);\n const toastActions = resolveToastViewActions({\n toast: action.toasts.success,\n response,\n node,\n tApp,\n entities,\n defaultLabel: t('actions.view'),\n navigateTo: (to) => {\n routing?.history.push({ pathname: to });\n },\n });\n toast.push({\n kind: 'info',\n title: toastSpec.title,\n message: toastSpec.message,\n actions: toastActions,\n });\n }\n\n if (action.result != null) {\n const nextValue = action.result.getValue(response, node);\n if (typeof nextValue === 'string' && nextValue.trim() !== '') {\n setResultValue(nextValue);\n onSuccess?.();\n return;\n }\n }\n\n if (hasCustomResult) {\n onSuccess?.();\n return;\n }\n\n onSuccess?.();\n onClose();\n },\n onError: (error) => {\n setIsSubmitting(false);\n const message = t('actions.form.errors.submitFailed');\n setFormError(message);\n action.onError?.(error, node);\n if (action.toasts?.error != null) {\n const toastTitle = resolveLabel(action.toasts.error.title, tApp);\n let toastMessage: string | undefined;\n if (action.toasts.error.message != null) {\n toastMessage = resolveLabel(action.toasts.error.message, tApp);\n }\n toast.error(toastTitle, toastMessage);\n }\n },\n });\n }, [\n action,\n buildPayload,\n entities,\n environment,\n isSubmitting,\n node,\n onClose,\n onSuccess,\n routing?.history,\n t,\n tApp,\n toast,\n ]);\n\n const handleFormSubmit = useCallback(\n (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n handleSubmit();\n },\n [handleSubmit],\n );\n\n const resultLabel = useMemo(() => {\n if (action.result == null) {\n return null;\n }\n return resolveLabel(action.result.label, tApp);\n }, [action.result, tApp]);\n\n const resultRender = useMemo(() => {\n if (action.result?.render == null || resultResponse == null) {\n return null;\n }\n return action.result.render(resultResponse, node);\n }, [action.result, node, resultResponse]);\n\n const showResult =\n (resultValue != null && resultLabel != null) || resultRender != null;\n\n const submitLabel = resolveLabel(action.label, tApp);\n\n if (!isOpen) {\n return null;\n }\n\n return (\n <>\n <Modal\n isOpen={isOpen}\n onClose={handleClose}\n title={title}\n initialFocus=\"first-form-control\"\n footer={\n <div className={styles.actions}>\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"small\"\n disabled={isSubmitting}\n onClick={handleClose}\n >\n {t('actions.form.cancel')}\n </Button>\n {!showResult && (\n <Button\n type=\"submit\"\n variant=\"primary\"\n size=\"small\"\n disabled={isSubmitting}\n isLoading={isSubmitting}\n loadingLabel={t('actions.form.submitting')}\n onClick={handleSubmit}\n >\n {submitLabel}\n </Button>\n )}\n </div>\n }\n >\n <Form onSubmit={handleFormSubmit} className={styles.form}>\n <FormError message={formError} />\n <BackofficeFormSection>\n {action.fields.map((field) => {\n const fieldLabel = resolveLabel(field.label, tApp);\n let fieldDescription: string | null = null;\n if (field.description != null) {\n fieldDescription = resolveLabel(field.description, tApp);\n }\n const fieldInputId = `${formId}-${field.id}`;\n const fieldDescriptionId = `${fieldInputId}-description`;\n const fieldErrorId = `${fieldInputId}-error`;\n const fieldError = fieldErrors[field.id] ?? null;\n const isFieldInvalid = fieldError != null;\n let inputVariant: 'error' | undefined;\n let selectState: 'default' | 'error' = 'default';\n if (isFieldInvalid) {\n inputVariant = 'error';\n selectState = 'error';\n }\n let describedBy: string | undefined;\n if (fieldDescription != null && fieldError != null) {\n describedBy = `${fieldDescriptionId} ${fieldErrorId}`;\n } else if (fieldDescription != null) {\n describedBy = fieldDescriptionId;\n } else if (fieldError != null) {\n describedBy = fieldErrorId;\n }\n\n switch (field.kind) {\n case 'text': {\n const rawValue = values[field.id];\n let value = '';\n if (typeof rawValue === 'string') {\n value = rawValue;\n }\n let placeholder: string | undefined;\n if (field.placeholder != null) {\n placeholder = resolveLabel(field.placeholder, tApp);\n }\n return (\n <FormGroup key={field.id}>\n <Label htmlFor={fieldInputId} required={field.required}>\n {fieldLabel}\n </Label>\n {fieldDescription != null && (\n <span\n id={fieldDescriptionId}\n className={styles.fieldDescription}\n >\n {fieldDescription}\n </span>\n )}\n <Input\n id={fieldInputId}\n type=\"text\"\n value={value}\n placeholder={placeholder}\n aria-describedby={describedBy}\n aria-invalid={isFieldInvalid}\n disabled={isSubmitting}\n variant={inputVariant}\n onChange={(event) => {\n setFieldValue(field.id, event.target.value);\n }}\n fullWidth\n />\n {fieldError != null && (\n <span id={fieldErrorId} className={styles.fieldError}>\n {fieldError}\n </span>\n )}\n </FormGroup>\n );\n }\n case 'textarea': {\n const rawValue = values[field.id];\n let value = '';\n if (typeof rawValue === 'string') {\n value = rawValue;\n }\n let placeholder: string | undefined;\n if (field.placeholder != null) {\n placeholder = resolveLabel(field.placeholder, tApp);\n }\n return (\n <FormGroup key={field.id}>\n <Label htmlFor={fieldInputId} required={field.required}>\n {fieldLabel}\n </Label>\n {fieldDescription != null && (\n <span\n id={fieldDescriptionId}\n className={styles.fieldDescription}\n >\n {fieldDescription}\n </span>\n )}\n <Textarea\n id={fieldInputId}\n value={value}\n placeholder={placeholder}\n rows={field.rows ?? 8}\n aria-describedby={describedBy}\n aria-invalid={isFieldInvalid}\n disabled={isSubmitting}\n variant={inputVariant}\n onChange={(event) => {\n setFieldValue(field.id, event.target.value);\n }}\n fullWidth\n />\n {fieldError != null && (\n <span id={fieldErrorId} className={styles.fieldError}>\n {fieldError}\n </span>\n )}\n </FormGroup>\n );\n }\n case 'number': {\n const rawValue = values[field.id];\n let value = '';\n if (typeof rawValue === 'string') {\n value = rawValue;\n }\n let placeholder: string | undefined;\n if (field.placeholder != null) {\n placeholder = resolveLabel(field.placeholder, tApp);\n }\n return (\n <FormGroup key={field.id}>\n <Label htmlFor={fieldInputId} required={field.required}>\n {fieldLabel}\n </Label>\n {fieldDescription != null && (\n <span\n id={fieldDescriptionId}\n className={styles.fieldDescription}\n >\n {fieldDescription}\n </span>\n )}\n <Input\n id={fieldInputId}\n type=\"number\"\n value={value}\n placeholder={placeholder}\n aria-describedby={describedBy}\n aria-invalid={isFieldInvalid}\n disabled={isSubmitting}\n variant={inputVariant}\n onChange={(event) => {\n setFieldValue(field.id, event.target.value);\n }}\n fullWidth\n />\n {fieldError != null && (\n <span id={fieldErrorId} className={styles.fieldError}>\n {fieldError}\n </span>\n )}\n </FormGroup>\n );\n }\n case 'json': {\n const rawValue = values[field.id];\n let value = '';\n if (typeof rawValue === 'string') {\n value = rawValue;\n }\n let placeholder: string | undefined;\n if (field.placeholder != null) {\n placeholder = resolveLabel(field.placeholder, tApp);\n }\n return (\n <FormGroup key={field.id}>\n <Label htmlFor={fieldInputId} required={field.required}>\n {fieldLabel}\n </Label>\n {fieldDescription != null && (\n <span\n id={fieldDescriptionId}\n className={styles.fieldDescription}\n >\n {fieldDescription}\n </span>\n )}\n <Textarea\n id={fieldInputId}\n value={value}\n placeholder={placeholder}\n rows={8}\n aria-describedby={describedBy}\n aria-invalid={isFieldInvalid}\n disabled={isSubmitting}\n variant={inputVariant}\n onChange={(event) => {\n setFieldValue(field.id, event.target.value);\n }}\n fullWidth\n />\n {fieldError != null && (\n <span id={fieldErrorId} className={styles.fieldError}>\n {fieldError}\n </span>\n )}\n </FormGroup>\n );\n }\n case 'enum': {\n const rawValue = values[field.id];\n let selected = '';\n if (typeof rawValue === 'string') {\n selected = rawValue;\n }\n const options = field.options.map((option) => {\n return {\n id: option.value,\n value: option.value,\n label: resolveLabel(option.label, tApp),\n };\n });\n return (\n <FormGroup key={field.id}>\n <Label\n id={`${fieldInputId}-label`}\n required={field.required}\n >\n {fieldLabel}\n </Label>\n {fieldDescription != null && (\n <span\n id={fieldDescriptionId}\n className={styles.fieldDescription}\n >\n {fieldDescription}\n </span>\n )}\n <SimpleSelect\n options={options}\n value={selected}\n placeholder={fieldLabel}\n ariaDescribedBy={describedBy}\n ariaInvalid={isFieldInvalid}\n ariaLabelledBy={`${fieldInputId}-label`}\n isDisabled={isSubmitting}\n state={selectState}\n onChange={(nextValue) => {\n setFieldValue(field.id, nextValue);\n }}\n />\n {fieldError != null && (\n <span id={fieldErrorId} className={styles.fieldError}>\n {fieldError}\n </span>\n )}\n </FormGroup>\n );\n }\n case 'boolean': {\n const checked = values[field.id] === true;\n return (\n <FormGroup key={field.id}>\n <CheckboxField\n id={fieldInputId}\n label={fieldLabel}\n helperText={fieldDescription ?? undefined}\n error={fieldError ?? undefined}\n checked={checked}\n disabled={isSubmitting}\n onChange={(event) => {\n setFieldValue(field.id, event.target.checked);\n }}\n />\n </FormGroup>\n );\n }\n case 'entityId': {\n const rawValue = values[field.id];\n let value = '';\n if (typeof rawValue === 'string') {\n value = rawValue;\n }\n return (\n <FormGroup key={field.id}>\n <Label htmlFor={fieldInputId} required={field.required}>\n {fieldLabel}\n </Label>\n {fieldDescription != null && (\n <span\n id={fieldDescriptionId}\n className={styles.fieldDescription}\n >\n {fieldDescription}\n </span>\n )}\n <EntityIdFilterField\n id={fieldInputId}\n label={fieldLabel}\n value={value}\n ariaDescribedBy={describedBy}\n ariaInvalid={isFieldInvalid}\n disabled={isSubmitting}\n onPick={() => {\n setActiveEntityPicker({\n fieldId: field.id,\n entity: field.entity,\n label: fieldLabel,\n });\n }}\n onClear={() => {\n setFieldValue(field.id, '');\n }}\n />\n {fieldError != null && (\n <span id={fieldErrorId} className={styles.fieldError}>\n {fieldError}\n </span>\n )}\n </FormGroup>\n );\n }\n case 'multiEnum': {\n const rawValue = values[field.id];\n const fieldLegendId = `${fieldInputId}-legend`;\n let selected: string[] = [];\n if (Array.isArray(rawValue)) {\n selected = rawValue.filter((entry): entry is string => {\n return typeof entry === 'string';\n });\n }\n return (\n <FormGroup key={field.id}>\n <fieldset className={styles.fieldset}>\n <legend id={fieldLegendId} className={styles.legend}>\n {fieldLabel}\n {field.required && (\n <span className={styles.requiredMark}>*</span>\n )}\n </legend>\n {fieldDescription != null && (\n <span\n id={fieldDescriptionId}\n className={styles.fieldDescription}\n >\n {fieldDescription}\n </span>\n )}\n <div\n className={styles.checkboxGroup}\n role=\"group\"\n aria-labelledby={fieldLegendId}\n aria-describedby={describedBy}\n aria-invalid={isFieldInvalid}\n >\n {field.options.map((option, index) => {\n const optionLabel = resolveLabel(\n option.label,\n tApp,\n );\n const isChecked = selected.includes(option.value);\n return (\n <CheckboxField\n key={`${option.value}-${index}`}\n id={`${fieldInputId}-${index}`}\n label={optionLabel}\n checked={isChecked}\n disabled={isSubmitting}\n onChange={(event) => {\n let nextList = selected;\n if (event.target.checked) {\n if (!selected.includes(option.value)) {\n nextList = [...selected, option.value];\n }\n } else {\n nextList = selected.filter((value) => {\n return value !== option.value;\n });\n }\n setFieldValue(field.id, nextList);\n }}\n />\n );\n })}\n </div>\n </fieldset>\n {fieldError != null && (\n <span id={fieldErrorId} className={styles.fieldError}>\n {fieldError}\n </span>\n )}\n </FormGroup>\n );\n }\n default: {\n return null;\n }\n }\n })}\n </BackofficeFormSection>\n\n {showResult && (\n <div className={styles.resultSection}>\n {resultValue != null && resultLabel != null && (\n <HighlightCode\n badgeLabel={resultLabel}\n copyCode={resultValue}\n fallbackCodeText={resultValue}\n />\n )}\n {resultRender}\n </div>\n )}\n </Form>\n </Modal>\n <EntityIdPickerDialog\n isOpen={activeEntityPicker != null}\n entity={activeEntityPicker?.entity ?? ''}\n title={activeEntityPicker?.label ?? ''}\n onClose={() => {\n setActiveEntityPicker(null);\n }}\n onSelectId={(id) => {\n if (activeEntityPicker == null) {\n return;\n }\n setFieldValue(activeEntityPicker.fieldId, id);\n setActiveEntityPicker(null);\n }}\n />\n </>\n );\n};\n\nexport default BackofficeEntityActionFormDialog;\n"],"mappings":"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"}
1
+ {"version":3,"file":"BackofficeEntityActionFormDialog.js","names":[],"sources":["../../../../../src/components/backoffice/actions/BackofficeEntityActionFormDialog.tsx"],"sourcesContent":["import {\n type FormEvent,\n type JSX,\n useCallback,\n useContext,\n useEffect,\n useId,\n useMemo,\n useState,\n} from 'react';\nimport type { TFunction } from 'i18next';\nimport { useTranslation } from 'react-i18next';\nimport * as ReactRelay from 'react-relay';\nimport {\n type MutationPayloadBase,\n resolveMutationOutcome,\n} from '../../../relay/mutationResult.js';\nimport { Button } from '@plumile/ui/atomic/atoms/button/Button.js';\nimport { Input } from '@plumile/ui/atomic/atoms/input/Input.js';\nimport { Label } from '@plumile/ui/atomic/atoms/label/Label.js';\nimport { Modal } from '@plumile/ui/atomic/atoms/modal/Modal.js';\nimport { Textarea } from '@plumile/ui/atomic/atoms/textarea/Textarea.js';\nimport { CheckboxField } from '@plumile/ui/atomic/molecules/checkbox_field/CheckboxField.js';\nimport { Form } from '@plumile/ui/atomic/molecules/form/Form.js';\nimport { FormError } from '@plumile/ui/atomic/molecules/form_error/FormError.js';\nimport { FormGroup } from '@plumile/ui/atomic/molecules/form/FormGroup.js';\nimport { HighlightCode } from '@plumile/ui/atomic/molecules/highlight/HighlightCode.js';\nimport { useToast } from '@plumile/ui/atomic/molecules/toast/ToastProvider.js';\nimport { BackofficeFormSection } from '@plumile/ui/backoffice/molecules/backoffice_form_section/BackofficeFormSection.js';\nimport { SimpleSelect } from '@plumile/ui/components/select/SimpleSelect.js';\nimport type {\n BackofficeEntityActionFormFieldSpec,\n BackofficeEntityFormMutationActionSpec,\n I18nLabel,\n} from '@plumile/backoffice-core/types.js';\n\nimport { useBackofficeReactTranslation } from '../../../i18n/useBackofficeReactTranslation.js';\nimport { useBackofficeConfig } from '../../../provider/BackofficeConfigContext.js';\nimport { EntityIdFilterField } from '../filters/EntityIdFilterField.js';\nimport { EntityIdPickerDialog } from '../pickers/EntityIdPickerDialog.js';\nimport {\n resolveToastSpec,\n resolveToastViewActions,\n} from './toastViewAction.js';\n\nconst { commitMutation, useRelayEnvironment } = ReactRelay;\nimport RoutingContext from '@plumile/router/routing/RoutingContext.js';\n\nimport * as styles from './backofficeEntityActionFormDialog.css.js';\n\nexport type BackofficeEntityActionFormDialogProps<Node> = {\n isOpen: boolean;\n action: BackofficeEntityFormMutationActionSpec<Node>;\n node: Node;\n onClose: () => void;\n onSuccess?: () => void;\n};\n\nconst resolveLabel = (label: I18nLabel, tApp: TFunction): string => {\n return label(tApp);\n};\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> => {\n return typeof value === 'object' && value != null && !Array.isArray(value);\n};\n\nconst extractMutationPayload = (\n response: unknown,\n): MutationPayloadBase | null => {\n if (!isPlainObject(response)) {\n return null;\n }\n\n for (const value of Object.values(response)) {\n if (isPlainObject(value) && ('status' in value || 'result' in value)) {\n return value;\n }\n }\n\n return null;\n};\n\nconst buildDefaultValues = (\n fields: readonly BackofficeEntityActionFormFieldSpec[],\n): Record<string, unknown> => {\n const output: Record<string, unknown> = {};\n fields.forEach((field) => {\n if (field.kind === 'boolean') {\n output[field.id] = field.defaultValue ?? false;\n return;\n }\n if (field.kind === 'multiEnum') {\n output[field.id] = field.defaultValue ?? [];\n return;\n }\n if (field.defaultValue != null) {\n output[field.id] = field.defaultValue;\n return;\n }\n output[field.id] = '';\n });\n return output;\n};\n\nconst normalizeInitialValue = (\n field: BackofficeEntityActionFormFieldSpec,\n value: unknown,\n): unknown => {\n if (field.kind === 'number') {\n if (typeof value === 'number') {\n return String(value);\n }\n if (typeof value === 'string') {\n return value;\n }\n return '';\n }\n if (field.kind === 'multiEnum') {\n if (Array.isArray(value)) {\n return value.filter((entry): entry is string => {\n return typeof entry === 'string' && entry.trim() !== '';\n });\n }\n return [];\n }\n if (field.kind === 'boolean') {\n return value === true;\n }\n if (typeof value === 'string') {\n return value;\n }\n return value ?? '';\n};\n\nconst buildInitialValues = <Node,>(\n action: BackofficeEntityFormMutationActionSpec<Node>,\n node: Node,\n): Record<string, unknown> => {\n const defaults = buildDefaultValues(action.fields);\n if (action.getInitialValues == null) {\n return defaults;\n }\n const overrides = action.getInitialValues(node);\n const next: Record<string, unknown> = { ...defaults };\n action.fields.forEach((field) => {\n if (!(field.id in overrides)) {\n return;\n }\n next[field.id] = normalizeInitialValue(field, overrides[field.id]);\n });\n return next;\n};\n\nexport const BackofficeEntityActionFormDialog = <Node,>({\n isOpen,\n action,\n node,\n onClose,\n onSuccess,\n}: BackofficeEntityActionFormDialogProps<Node>): JSX.Element | null => {\n const { t: tApp } = useTranslation();\n const { t } = useBackofficeReactTranslation();\n const { entities } = useBackofficeConfig();\n const routing = useContext(RoutingContext);\n const environment = useRelayEnvironment();\n const toast = useToast();\n const formId = useId();\n\n const [values, setValues] = useState<Record<string, unknown>>({});\n const [formError, setFormError] = useState<string | null>(null);\n const [fieldErrors, setFieldErrors] = useState<Record<string, string>>({});\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [resultValue, setResultValue] = useState<string | null>(null);\n const [resultResponse, setResultResponse] = useState<unknown>(null);\n const [activeEntityPicker, setActiveEntityPicker] = useState<{\n fieldId: string;\n entity: string;\n label: string;\n } | null>(null);\n\n useEffect(() => {\n if (!isOpen) {\n return;\n }\n setValues(buildInitialValues(action, node));\n setFormError(null);\n setFieldErrors({});\n setResultValue(null);\n setResultResponse(null);\n }, [action, isOpen, node]);\n\n const handleClose = useCallback(() => {\n if (isSubmitting) {\n return;\n }\n onClose();\n }, [isSubmitting, onClose]);\n\n const setFieldValue = useCallback((fieldId: string, value: unknown) => {\n setValues((current) => {\n return { ...current, [fieldId]: value };\n });\n setFieldErrors((current) => {\n if (current[fieldId] == null) {\n return current;\n }\n const { [fieldId]: removedValue, ...next } = current;\n return next;\n });\n }, []);\n\n const title = resolveLabel(action.label, tApp);\n\n const resolveRequiredError = useCallback(\n (fieldLabel: string): string => {\n return t('actions.form.errors.required', {\n label: fieldLabel,\n });\n },\n [t],\n );\n\n const resolveInvalidNumberError = useCallback(\n (fieldLabel: string): string => {\n return t('actions.form.errors.invalidNumber', {\n label: fieldLabel,\n });\n },\n [t],\n );\n\n const resolveInvalidJsonError = useCallback(\n (fieldLabel: string): string => {\n return t('actions.form.errors.invalidJson', {\n label: fieldLabel,\n });\n },\n [t],\n );\n\n const resolveInvalidJsonObjectError = useCallback(\n (fieldLabel: string): string => {\n return t('actions.form.errors.invalidJsonObject', {\n label: fieldLabel,\n });\n },\n [t],\n );\n\n const resolveInvalidJsonArrayError = useCallback(\n (fieldLabel: string): string => {\n return t('actions.form.errors.invalidJsonArray', {\n label: fieldLabel,\n });\n },\n [t],\n );\n\n const buildPayload = useCallback(():\n | { values: Record<string, unknown> }\n | { error: string; fieldId?: string } => {\n const output: Record<string, unknown> = {};\n\n for (const field of action.fields) {\n const fieldLabel = resolveLabel(field.label, tApp);\n const rawValue = values[field.id];\n\n switch (field.kind) {\n case 'text': {\n let value = '';\n if (typeof rawValue === 'string') {\n value = rawValue.trim();\n }\n if (value === '') {\n if (field.required) {\n return {\n error: resolveRequiredError(fieldLabel),\n fieldId: field.id,\n };\n }\n break;\n }\n output[field.id] = value;\n break;\n }\n case 'textarea': {\n let value = '';\n if (typeof rawValue === 'string') {\n value = rawValue.trim();\n }\n if (value === '') {\n if (field.required) {\n return {\n error: resolveRequiredError(fieldLabel),\n fieldId: field.id,\n };\n }\n break;\n }\n output[field.id] = value;\n break;\n }\n case 'number': {\n let valueString = '';\n if (typeof rawValue === 'string') {\n valueString = rawValue.trim();\n } else if (\n typeof rawValue === 'number' &&\n Number.isFinite(rawValue)\n ) {\n valueString = String(rawValue);\n }\n if (valueString === '') {\n if (field.required) {\n return {\n error: resolveRequiredError(fieldLabel),\n fieldId: field.id,\n };\n }\n break;\n }\n const parsed = Number(valueString);\n if (!Number.isFinite(parsed)) {\n return {\n error: resolveInvalidNumberError(fieldLabel),\n fieldId: field.id,\n };\n }\n output[field.id] = parsed;\n break;\n }\n case 'json': {\n let valueString = '';\n if (typeof rawValue === 'string') {\n valueString = rawValue.trim();\n }\n if (valueString === '') {\n if (field.required) {\n return {\n error: resolveRequiredError(fieldLabel),\n fieldId: field.id,\n };\n }\n break;\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(valueString);\n } catch {\n return {\n error: resolveInvalidJsonError(fieldLabel),\n fieldId: field.id,\n };\n }\n\n const jsonType = field.jsonType ?? 'object';\n if (jsonType === 'object' && !isPlainObject(parsed)) {\n return {\n error: resolveInvalidJsonObjectError(fieldLabel),\n fieldId: field.id,\n };\n }\n if (jsonType === 'array' && !Array.isArray(parsed)) {\n return {\n error: resolveInvalidJsonArrayError(fieldLabel),\n fieldId: field.id,\n };\n }\n\n output[field.id] = parsed;\n break;\n }\n case 'enum': {\n let value = '';\n if (typeof rawValue === 'string') {\n value = rawValue.trim();\n }\n if (value === '') {\n if (field.required) {\n return {\n error: resolveRequiredError(fieldLabel),\n fieldId: field.id,\n };\n }\n break;\n }\n output[field.id] = value;\n break;\n }\n case 'boolean': {\n output[field.id] = rawValue === true;\n break;\n }\n case 'entityId': {\n let value = '';\n if (typeof rawValue === 'string') {\n value = rawValue.trim();\n }\n if (value === '') {\n if (field.required) {\n return {\n error: resolveRequiredError(fieldLabel),\n fieldId: field.id,\n };\n }\n break;\n }\n output[field.id] = value;\n break;\n }\n case 'multiEnum': {\n let list: string[] = [];\n if (Array.isArray(rawValue)) {\n list = rawValue.filter((entry): entry is string => {\n return typeof entry === 'string' && entry.trim() !== '';\n });\n }\n if (list.length === 0) {\n if (field.required) {\n return {\n error: resolveRequiredError(fieldLabel),\n fieldId: field.id,\n };\n }\n break;\n }\n output[field.id] = list;\n break;\n }\n default: {\n break;\n }\n }\n }\n\n return { values: output };\n }, [\n action.fields,\n resolveInvalidJsonArrayError,\n resolveInvalidJsonError,\n resolveInvalidJsonObjectError,\n resolveInvalidNumberError,\n resolveRequiredError,\n tApp,\n values,\n ]);\n\n const handleSubmit = useCallback(() => {\n if (isSubmitting) {\n return;\n }\n\n setFormError(null);\n setFieldErrors({});\n\n const payload = buildPayload();\n if ('error' in payload) {\n setFormError(payload.error);\n if (payload.fieldId != null) {\n setFieldErrors({ [payload.fieldId]: payload.error });\n }\n return;\n }\n\n let variables: ReturnType<typeof action.getVariables>;\n try {\n variables = action.getVariables(node, payload.values);\n } catch {\n const message = t('actions.form.errors.invalidPayload');\n setFormError(message);\n return;\n }\n\n setIsSubmitting(true);\n commitMutation(environment, {\n mutation: action.mutation,\n variables,\n updater: (store) => {\n action.updater?.(store, node);\n },\n onCompleted: (response) => {\n setIsSubmitting(false);\n const mutationPayload = extractMutationPayload(response);\n if (mutationPayload != null) {\n let defaultErrorMessage = t('actions.form.errors.invalidPayload');\n if (action.toasts?.error?.message != null) {\n defaultErrorMessage = resolveLabel(\n action.toasts.error.message,\n tApp,\n );\n } else if (action.toasts?.error?.title != null) {\n defaultErrorMessage = resolveLabel(action.toasts.error.title, tApp);\n }\n\n const outcome = resolveMutationOutcome(mutationPayload, {\n defaultErrorMessage,\n mapReason: (reason) => {\n const mapped = action.mapErrorReason?.(reason, node);\n if (mapped == null) {\n return null;\n }\n if (typeof mapped === 'function') {\n return resolveLabel(mapped, tApp);\n }\n return String(mapped);\n },\n });\n if (!outcome.ok) {\n const error = new Error(outcome.message);\n setFormError(outcome.message);\n action.onError?.(error, node);\n if (action.toasts?.error != null) {\n const toastTitle = resolveLabel(action.toasts.error.title, tApp);\n let toastMessage: string | undefined;\n if (action.toasts.error.message != null) {\n toastMessage = resolveLabel(action.toasts.error.message, tApp);\n }\n toast.error(toastTitle, toastMessage);\n }\n return;\n }\n }\n\n action.onCompleted?.(response, node);\n\n let hasCustomResult = false;\n if (action.result?.render != null) {\n const renderedResult = action.result.render(response, node);\n if (renderedResult != null) {\n hasCustomResult = true;\n setResultResponse(response);\n }\n }\n if (action.toasts?.success != null) {\n const toastSpec = resolveToastSpec(action.toasts.success, tApp);\n const toastActions = resolveToastViewActions({\n toast: action.toasts.success,\n response,\n node,\n tApp,\n entities,\n defaultLabel: t('actions.view'),\n navigateTo: (to) => {\n routing?.history.push({ pathname: to });\n },\n });\n toast.push({\n kind: 'info',\n title: toastSpec.title,\n message: toastSpec.message,\n actions: toastActions,\n });\n }\n\n if (action.result != null) {\n const nextValue = action.result.getValue(response, node);\n if (typeof nextValue === 'string' && nextValue.trim() !== '') {\n setResultValue(nextValue);\n onSuccess?.();\n return;\n }\n }\n\n if (hasCustomResult) {\n onSuccess?.();\n return;\n }\n\n onSuccess?.();\n onClose();\n },\n onError: (error) => {\n setIsSubmitting(false);\n const message = t('actions.form.errors.submitFailed');\n setFormError(message);\n action.onError?.(error, node);\n if (action.toasts?.error != null) {\n const toastTitle = resolveLabel(action.toasts.error.title, tApp);\n let toastMessage: string | undefined;\n if (action.toasts.error.message != null) {\n toastMessage = resolveLabel(action.toasts.error.message, tApp);\n }\n toast.error(toastTitle, toastMessage);\n }\n },\n });\n }, [\n action,\n buildPayload,\n entities,\n environment,\n isSubmitting,\n node,\n onClose,\n onSuccess,\n routing?.history,\n t,\n tApp,\n toast,\n ]);\n\n const handleFormSubmit = useCallback(\n (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n handleSubmit();\n },\n [handleSubmit],\n );\n\n const resultLabel = useMemo(() => {\n if (action.result == null) {\n return null;\n }\n return resolveLabel(action.result.label, tApp);\n }, [action.result, tApp]);\n\n const resultRender = useMemo(() => {\n if (action.result?.render == null || resultResponse == null) {\n return null;\n }\n return action.result.render(resultResponse, node);\n }, [action.result, node, resultResponse]);\n\n const showResult =\n (resultValue != null && resultLabel != null) || resultRender != null;\n\n const submitLabel = resolveLabel(action.label, tApp);\n\n if (!isOpen) {\n return null;\n }\n\n return (\n <>\n <Modal\n isOpen={isOpen}\n onClose={handleClose}\n title={title}\n initialFocus=\"first-form-control\"\n footer={\n <div className={styles.actions}>\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"small\"\n disabled={isSubmitting}\n onClick={handleClose}\n >\n {t('actions.form.cancel')}\n </Button>\n {!showResult && (\n <Button\n type=\"submit\"\n variant=\"primary\"\n size=\"small\"\n disabled={isSubmitting}\n isLoading={isSubmitting}\n loadingLabel={t('actions.form.submitting')}\n onClick={handleSubmit}\n >\n {submitLabel}\n </Button>\n )}\n </div>\n }\n >\n <Form onSubmit={handleFormSubmit} className={styles.form}>\n <FormError message={formError} />\n <BackofficeFormSection>\n {action.fields.map((field) => {\n const fieldLabel = resolveLabel(field.label, tApp);\n let fieldDescription: string | null = null;\n if (field.description != null) {\n fieldDescription = resolveLabel(field.description, tApp);\n }\n const fieldInputId = `${formId}-${field.id}`;\n const fieldDescriptionId = `${fieldInputId}-description`;\n const fieldErrorId = `${fieldInputId}-error`;\n const fieldError = fieldErrors[field.id] ?? null;\n const isFieldInvalid = fieldError != null;\n let inputVariant: 'error' | undefined;\n let selectState: 'default' | 'error' = 'default';\n if (isFieldInvalid) {\n inputVariant = 'error';\n selectState = 'error';\n }\n let describedBy: string | undefined;\n if (fieldDescription != null && fieldError != null) {\n describedBy = `${fieldDescriptionId} ${fieldErrorId}`;\n } else if (fieldDescription != null) {\n describedBy = fieldDescriptionId;\n } else if (fieldError != null) {\n describedBy = fieldErrorId;\n }\n\n switch (field.kind) {\n case 'text': {\n const rawValue = values[field.id];\n let value = '';\n if (typeof rawValue === 'string') {\n value = rawValue;\n }\n let placeholder: string | undefined;\n if (field.placeholder != null) {\n placeholder = resolveLabel(field.placeholder, tApp);\n }\n return (\n <FormGroup key={field.id}>\n <Label htmlFor={fieldInputId} required={field.required}>\n {fieldLabel}\n </Label>\n {fieldDescription != null && (\n <span\n id={fieldDescriptionId}\n className={styles.fieldDescription}\n >\n {fieldDescription}\n </span>\n )}\n <Input\n id={fieldInputId}\n type=\"text\"\n value={value}\n placeholder={placeholder}\n aria-describedby={describedBy}\n aria-invalid={isFieldInvalid}\n disabled={isSubmitting}\n variant={inputVariant}\n onChange={(event) => {\n setFieldValue(field.id, event.target.value);\n }}\n fullWidth\n />\n {fieldError != null && (\n <span id={fieldErrorId} className={styles.fieldError}>\n {fieldError}\n </span>\n )}\n </FormGroup>\n );\n }\n case 'textarea': {\n const rawValue = values[field.id];\n let value = '';\n if (typeof rawValue === 'string') {\n value = rawValue;\n }\n let placeholder: string | undefined;\n if (field.placeholder != null) {\n placeholder = resolveLabel(field.placeholder, tApp);\n }\n return (\n <FormGroup key={field.id}>\n <Label htmlFor={fieldInputId} required={field.required}>\n {fieldLabel}\n </Label>\n {fieldDescription != null && (\n <span\n id={fieldDescriptionId}\n className={styles.fieldDescription}\n >\n {fieldDescription}\n </span>\n )}\n <Textarea\n id={fieldInputId}\n value={value}\n placeholder={placeholder}\n rows={field.rows ?? 8}\n aria-describedby={describedBy}\n aria-invalid={isFieldInvalid}\n disabled={isSubmitting}\n variant={inputVariant}\n onChange={(event) => {\n setFieldValue(field.id, event.target.value);\n }}\n fullWidth\n />\n {fieldError != null && (\n <span id={fieldErrorId} className={styles.fieldError}>\n {fieldError}\n </span>\n )}\n </FormGroup>\n );\n }\n case 'number': {\n const rawValue = values[field.id];\n let value = '';\n if (typeof rawValue === 'string') {\n value = rawValue;\n }\n let placeholder: string | undefined;\n if (field.placeholder != null) {\n placeholder = resolveLabel(field.placeholder, tApp);\n }\n return (\n <FormGroup key={field.id}>\n <Label htmlFor={fieldInputId} required={field.required}>\n {fieldLabel}\n </Label>\n {fieldDescription != null && (\n <span\n id={fieldDescriptionId}\n className={styles.fieldDescription}\n >\n {fieldDescription}\n </span>\n )}\n <Input\n id={fieldInputId}\n type=\"number\"\n value={value}\n placeholder={placeholder}\n aria-describedby={describedBy}\n aria-invalid={isFieldInvalid}\n disabled={isSubmitting}\n variant={inputVariant}\n onChange={(event) => {\n setFieldValue(field.id, event.target.value);\n }}\n fullWidth\n />\n {fieldError != null && (\n <span id={fieldErrorId} className={styles.fieldError}>\n {fieldError}\n </span>\n )}\n </FormGroup>\n );\n }\n case 'json': {\n const rawValue = values[field.id];\n let value = '';\n if (typeof rawValue === 'string') {\n value = rawValue;\n }\n let placeholder: string | undefined;\n if (field.placeholder != null) {\n placeholder = resolveLabel(field.placeholder, tApp);\n }\n return (\n <FormGroup key={field.id}>\n <Label htmlFor={fieldInputId} required={field.required}>\n {fieldLabel}\n </Label>\n {fieldDescription != null && (\n <span\n id={fieldDescriptionId}\n className={styles.fieldDescription}\n >\n {fieldDescription}\n </span>\n )}\n <Textarea\n id={fieldInputId}\n value={value}\n placeholder={placeholder}\n rows={8}\n aria-describedby={describedBy}\n aria-invalid={isFieldInvalid}\n disabled={isSubmitting}\n variant={inputVariant}\n onChange={(event) => {\n setFieldValue(field.id, event.target.value);\n }}\n fullWidth\n />\n {fieldError != null && (\n <span id={fieldErrorId} className={styles.fieldError}>\n {fieldError}\n </span>\n )}\n </FormGroup>\n );\n }\n case 'enum': {\n const rawValue = values[field.id];\n let selected = '';\n if (typeof rawValue === 'string') {\n selected = rawValue;\n }\n const options = field.options.map((option) => {\n return {\n id: option.value,\n value: option.value,\n label: resolveLabel(option.label, tApp),\n };\n });\n return (\n <FormGroup key={field.id}>\n <Label\n id={`${fieldInputId}-label`}\n required={field.required}\n >\n {fieldLabel}\n </Label>\n {fieldDescription != null && (\n <span\n id={fieldDescriptionId}\n className={styles.fieldDescription}\n >\n {fieldDescription}\n </span>\n )}\n <SimpleSelect\n options={options}\n value={selected}\n placeholder={fieldLabel}\n ariaDescribedBy={describedBy}\n ariaInvalid={isFieldInvalid}\n ariaLabelledBy={`${fieldInputId}-label`}\n isDisabled={isSubmitting}\n state={selectState}\n onChange={(nextValue) => {\n setFieldValue(field.id, nextValue);\n }}\n />\n {fieldError != null && (\n <span id={fieldErrorId} className={styles.fieldError}>\n {fieldError}\n </span>\n )}\n </FormGroup>\n );\n }\n case 'boolean': {\n const checked = values[field.id] === true;\n return (\n <FormGroup key={field.id}>\n <CheckboxField\n id={fieldInputId}\n label={fieldLabel}\n helperText={fieldDescription ?? undefined}\n error={fieldError ?? undefined}\n checked={checked}\n disabled={isSubmitting}\n onChange={(event) => {\n setFieldValue(field.id, event.target.checked);\n }}\n />\n </FormGroup>\n );\n }\n case 'entityId': {\n const rawValue = values[field.id];\n let value = '';\n if (typeof rawValue === 'string') {\n value = rawValue;\n }\n return (\n <FormGroup key={field.id}>\n <Label htmlFor={fieldInputId} required={field.required}>\n {fieldLabel}\n </Label>\n {fieldDescription != null && (\n <span\n id={fieldDescriptionId}\n className={styles.fieldDescription}\n >\n {fieldDescription}\n </span>\n )}\n <EntityIdFilterField\n id={fieldInputId}\n label={fieldLabel}\n value={value}\n ariaDescribedBy={describedBy}\n ariaInvalid={isFieldInvalid}\n disabled={isSubmitting}\n onPick={() => {\n setActiveEntityPicker({\n fieldId: field.id,\n entity: field.entity,\n label: fieldLabel,\n });\n }}\n onClear={() => {\n setFieldValue(field.id, '');\n }}\n />\n {fieldError != null && (\n <span id={fieldErrorId} className={styles.fieldError}>\n {fieldError}\n </span>\n )}\n </FormGroup>\n );\n }\n case 'multiEnum': {\n const rawValue = values[field.id];\n const fieldLegendId = `${fieldInputId}-legend`;\n let selected: string[] = [];\n if (Array.isArray(rawValue)) {\n selected = rawValue.filter((entry): entry is string => {\n return typeof entry === 'string';\n });\n }\n return (\n <FormGroup key={field.id}>\n <fieldset className={styles.fieldset}>\n <legend id={fieldLegendId} className={styles.legend}>\n {fieldLabel}\n {field.required && (\n <span className={styles.requiredMark}>*</span>\n )}\n </legend>\n {fieldDescription != null && (\n <span\n id={fieldDescriptionId}\n className={styles.fieldDescription}\n >\n {fieldDescription}\n </span>\n )}\n <div\n className={styles.checkboxGroup}\n role=\"group\"\n aria-labelledby={fieldLegendId}\n aria-describedby={describedBy}\n aria-invalid={isFieldInvalid}\n >\n {field.options.map((option, index) => {\n const optionLabel = resolveLabel(\n option.label,\n tApp,\n );\n const isChecked = selected.includes(option.value);\n return (\n <CheckboxField\n key={`${option.value}-${index}`}\n id={`${fieldInputId}-${index}`}\n label={optionLabel}\n checked={isChecked}\n disabled={isSubmitting}\n onChange={(event) => {\n let nextList = selected;\n if (event.target.checked) {\n if (!selected.includes(option.value)) {\n nextList = [...selected, option.value];\n }\n } else {\n nextList = selected.filter((value) => {\n return value !== option.value;\n });\n }\n setFieldValue(field.id, nextList);\n }}\n />\n );\n })}\n </div>\n </fieldset>\n {fieldError != null && (\n <span id={fieldErrorId} className={styles.fieldError}>\n {fieldError}\n </span>\n )}\n </FormGroup>\n );\n }\n default: {\n return null;\n }\n }\n })}\n </BackofficeFormSection>\n\n {showResult && (\n <div className={styles.resultSection}>\n {resultValue != null && resultLabel != null && (\n <HighlightCode\n badgeLabel={resultLabel}\n copyCode={resultValue}\n fallbackCodeText={resultValue}\n />\n )}\n {resultRender}\n </div>\n )}\n </Form>\n </Modal>\n <EntityIdPickerDialog\n isOpen={activeEntityPicker != null}\n entity={activeEntityPicker?.entity ?? ''}\n title={activeEntityPicker?.label ?? ''}\n onClose={() => {\n setActiveEntityPicker(null);\n }}\n onSelectId={(id) => {\n if (activeEntityPicker == null) {\n return;\n }\n setFieldValue(activeEntityPicker.fieldId, id);\n setActiveEntityPicker(null);\n }}\n />\n </>\n );\n};\n\nexport default BackofficeEntityActionFormDialog;\n"],"mappings":"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"}
@@ -94,7 +94,7 @@ var { useLazyLoadQuery: y, usePaginationFragment: b } = m, x = () => {
94
94
  children: a("relations.unavailable.description")
95
95
  });
96
96
  let s = o.modules[r.target]?.config;
97
- return s == null || s.list.kind === "records" ? null : /* @__PURE__ */ f(S, {
97
+ return s == null ? null : /* @__PURE__ */ f(S, {
98
98
  title: t,
99
99
  config: s,
100
100
  relation: r,
@@ -1 +1 @@
1
- {"version":3,"file":"BackofficeDetailRelationListBlock.js","names":[],"sources":["../../../../../src/components/backoffice/detail/BackofficeDetailRelationListBlock.tsx"],"sourcesContent":["import { Suspense, useCallback, useMemo, useState, type JSX } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport * as ReactRelay from 'react-relay';\nimport type { OperationType } from 'relay-runtime';\n\nimport {\n BACKOFFICE_LIST_REFETCH_POLICY,\n BACKOFFICE_RELATED_TAB_PAGE_SIZE,\n} from '@plumile/backoffice-core/constants.js';\nimport { setWhereValue } from '@plumile/backoffice-core/filters/where.js';\nimport type {\n BackofficeListState,\n BackofficeRuntimeRelationFilterSpec,\n BackofficeRuntimeResolvedListFacetConfig,\n} from '@plumile/backoffice-core/types.js';\nimport { BackofficeTableSkeleton } from '@plumile/ui/backoffice/molecules/backoffice_table_skeleton/BackofficeTableSkeleton.js';\nimport { InlineBanner } from '@plumile/ui/components/feedback/InlineBanner.js';\n\nimport { buildDataTableColumns } from '../columns/buildDataTableColumns.js';\nimport { useBackofficeLoadMore } from '../../../hooks/useBackofficeLoadMore.js';\nimport { useBackofficeListRefetch } from '../../../hooks/useBackofficeListRefetch.js';\nimport { useBackofficeReactTranslation } from '../../../i18n/useBackofficeReactTranslation.js';\nimport { useBackofficeListEntitiesLoader } from '../../../provider/useBackofficeEntityLoader.js';\nimport { BackofficeEntityListScaffold } from '../scaffolds/BackofficeEntityListScaffold.js';\nimport { BackofficeErrorBoundary } from '../errors/BackofficeErrorBoundary.js';\n\nconst { useLazyLoadQuery, usePaginationFragment } = ReactRelay;\n\nexport type BackofficeDetailRelationListBlockProps = {\n title: string;\n relation: BackofficeRuntimeRelationFilterSpec;\n value: string | null;\n};\n\ntype RelationListContentProps = {\n title: string;\n config: BackofficeRuntimeResolvedListFacetConfig & {\n list: Exclude<\n BackofficeRuntimeResolvedListFacetConfig['list'],\n { kind: 'records' }\n >;\n };\n relation: BackofficeRuntimeRelationFilterSpec;\n value: string | null;\n};\n\ntype RelationListBlockBodyProps = {\n title: string;\n relation: BackofficeRuntimeRelationFilterSpec;\n value: string | null;\n};\n\nconst RelationListSkeleton = (): JSX.Element => {\n const { t } = useBackofficeReactTranslation();\n\n return <BackofficeTableSkeleton rows={6} ariaLabel={t('common.loading')} />;\n};\n\nconst RelationListContent = ({\n title,\n config,\n relation,\n value,\n}: RelationListContentProps): JSX.Element | null => {\n const { t: tApp } = useTranslation();\n const { t } = useBackofficeReactTranslation();\n const listConfig = config.list;\n const listDefaults = config.listDefaults ??\n listConfig.defaultState ?? { where: null, sort: null };\n\n const [state, setState] = useState<BackofficeListState<unknown, string>>({\n where: listDefaults.where as never,\n sort: listDefaults.sort ?? null,\n });\n\n const relationWhere = useMemo(() => {\n if (value == null || value.trim() === '') {\n return null;\n }\n return setWhereValue(\n state.where as Record<string, unknown> | null,\n relation.whereKey as never,\n value,\n relation.path,\n );\n }, [relation.path, relation.whereKey, state.where, value]);\n\n const effectiveWhere = relationWhere ?? (state.where as never);\n const resolvedSort = state.sort ?? listDefaults.sort;\n const variablesBase = useMemo(() => {\n return {\n where: effectiveWhere as never,\n sort: resolvedSort as never,\n count: BACKOFFICE_RELATED_TAB_PAGE_SIZE,\n cursor: null,\n };\n }, [effectiveWhere, resolvedSort]);\n\n const variables = useMemo(() => {\n return listConfig.buildQueryVariables(variablesBase);\n }, [listConfig, variablesBase]);\n\n const queryData = useLazyLoadQuery<OperationType>(\n listConfig.query,\n variables,\n { fetchPolicy: 'store-or-network' },\n );\n\n const {\n data: fragmentData,\n loadNext,\n hasNext,\n isLoadingNext,\n refetch,\n } = usePaginationFragment(listConfig.fragment, queryData as never);\n\n const connection = listConfig.getConnection(fragmentData);\n const rows = useMemo(() => {\n return connection.edges.map((edge) => {\n return listConfig.toRow(edge.node);\n });\n }, [connection.edges, listConfig]);\n\n const columns = useMemo(() => {\n return buildDataTableColumns(listConfig.columns, {\n tApp,\n t,\n });\n }, [listConfig.columns, t, tApp]);\n\n const getRowId = useCallback(\n (row: unknown) => {\n return listConfig.getRowId(row);\n },\n [listConfig],\n );\n\n const defaults = useMemo(() => {\n const baseWhere = relationWhere ?? listDefaults.where;\n return {\n where: baseWhere,\n sort: listDefaults.sort,\n count: BACKOFFICE_RELATED_TAB_PAGE_SIZE,\n cursor: null,\n };\n }, [listDefaults.sort, listDefaults.where, relationWhere]);\n\n const { onRefresh } = useBackofficeListRefetch({\n refetch,\n variables: variablesBase,\n defaults,\n fetchPolicy: BACKOFFICE_LIST_REFETCH_POLICY,\n buildQueryVariables: listConfig.buildQueryVariables,\n });\n\n const handleLoadMore = useBackofficeLoadMore({\n hasNext,\n isLoadingNext,\n loadNext,\n count: BACKOFFICE_RELATED_TAB_PAGE_SIZE,\n });\n\n return (\n <BackofficeEntityListScaffold\n config={config as never}\n state={state as never}\n pushState={(next) => {\n setState(next);\n }}\n header={{ title }}\n rows={rows}\n columns={columns as never}\n getRowId={getRowId}\n hasNextPage={hasNext}\n isLoadingMore={isLoadingNext}\n onLoadMore={handleLoadMore}\n onRefresh={onRefresh}\n totalCount={connection.totalCount ?? null}\n variant=\"embedded\"\n />\n );\n};\n\nconst RelationListBlockBody = ({\n title,\n relation,\n value,\n}: RelationListBlockBodyProps): JSX.Element | null => {\n const { t } = useBackofficeReactTranslation();\n const relatedEntityIds = useMemo(() => {\n return [relation.target];\n }, [relation.target]);\n const relatedEntitiesState =\n useBackofficeListEntitiesLoader(relatedEntityIds);\n\n if (relatedEntitiesState.status === 'loading') {\n return <BackofficeTableSkeleton rows={6} ariaLabel={t('common.loading')} />;\n }\n\n if (relatedEntitiesState.status === 'error') {\n return (\n <InlineBanner tone=\"warning\" title={t('relations.unavailable.title')}>\n {t('relations.unavailable.description')}\n </InlineBanner>\n );\n }\n\n const config = relatedEntitiesState.modules[relation.target]?.config;\n if (config == null) {\n return null;\n }\n if (config.list.kind === 'records') {\n return null;\n }\n const connectionConfig = config as RelationListContentProps['config'];\n\n return (\n <RelationListContent\n title={title}\n config={connectionConfig}\n relation={relation}\n value={value}\n />\n );\n};\n\nexport const BackofficeDetailRelationListBlock = ({\n title,\n relation,\n value,\n}: BackofficeDetailRelationListBlockProps): JSX.Element => {\n return (\n <BackofficeErrorBoundary\n fallback={() => {\n return <RelationListSkeleton />;\n }}\n >\n <Suspense fallback={<RelationListSkeleton />}>\n <RelationListBlockBody\n title={title}\n relation={relation}\n value={value}\n />\n </Suspense>\n </BackofficeErrorBoundary>\n );\n};\n\nexport default BackofficeDetailRelationListBlock;\n"],"mappings":"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"}
1
+ {"version":3,"file":"BackofficeDetailRelationListBlock.js","names":[],"sources":["../../../../../src/components/backoffice/detail/BackofficeDetailRelationListBlock.tsx"],"sourcesContent":["import { Suspense, useCallback, useMemo, useState, type JSX } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport * as ReactRelay from 'react-relay';\nimport type { OperationType } from 'relay-runtime';\n\nimport {\n BACKOFFICE_LIST_REFETCH_POLICY,\n BACKOFFICE_RELATED_TAB_PAGE_SIZE,\n} from '@plumile/backoffice-core/constants.js';\nimport { setWhereValue } from '@plumile/backoffice-core/filters/where.js';\nimport type {\n BackofficeListState,\n BackofficeRuntimeRelationFilterSpec,\n BackofficeRuntimeResolvedListFacetConfig,\n} from '@plumile/backoffice-core/types.js';\nimport { BackofficeTableSkeleton } from '@plumile/ui/backoffice/molecules/backoffice_table_skeleton/BackofficeTableSkeleton.js';\nimport { InlineBanner } from '@plumile/ui/components/feedback/InlineBanner.js';\n\nimport { buildDataTableColumns } from '../columns/buildDataTableColumns.js';\nimport { useBackofficeLoadMore } from '../../../hooks/useBackofficeLoadMore.js';\nimport { useBackofficeListRefetch } from '../../../hooks/useBackofficeListRefetch.js';\nimport { useBackofficeReactTranslation } from '../../../i18n/useBackofficeReactTranslation.js';\nimport { useBackofficeListEntitiesLoader } from '../../../provider/useBackofficeEntityLoader.js';\nimport { BackofficeEntityListScaffold } from '../scaffolds/BackofficeEntityListScaffold.js';\nimport { BackofficeErrorBoundary } from '../errors/BackofficeErrorBoundary.js';\n\nconst { useLazyLoadQuery, usePaginationFragment } = ReactRelay;\n\nexport type BackofficeDetailRelationListBlockProps = {\n title: string;\n relation: BackofficeRuntimeRelationFilterSpec;\n value: string | null;\n};\n\ntype RelationListContentProps = {\n title: string;\n config: BackofficeRuntimeResolvedListFacetConfig;\n relation: BackofficeRuntimeRelationFilterSpec;\n value: string | null;\n};\n\ntype RelationListBlockBodyProps = {\n title: string;\n relation: BackofficeRuntimeRelationFilterSpec;\n value: string | null;\n};\n\nconst RelationListSkeleton = (): JSX.Element => {\n const { t } = useBackofficeReactTranslation();\n\n return <BackofficeTableSkeleton rows={6} ariaLabel={t('common.loading')} />;\n};\n\nconst RelationListContent = ({\n title,\n config,\n relation,\n value,\n}: RelationListContentProps): JSX.Element | null => {\n const { t: tApp } = useTranslation();\n const { t } = useBackofficeReactTranslation();\n const listConfig = config.list;\n const listDefaults = config.listDefaults ??\n listConfig.defaultState ?? { where: null, sort: null };\n\n const [state, setState] = useState<BackofficeListState<unknown, string>>({\n where: listDefaults.where as never,\n sort: listDefaults.sort ?? null,\n });\n\n const relationWhere = useMemo(() => {\n if (value == null || value.trim() === '') {\n return null;\n }\n return setWhereValue(\n state.where as Record<string, unknown> | null,\n relation.whereKey as never,\n value,\n relation.path,\n );\n }, [relation.path, relation.whereKey, state.where, value]);\n\n const effectiveWhere = relationWhere ?? (state.where as never);\n const resolvedSort = state.sort ?? listDefaults.sort;\n const variablesBase = useMemo(() => {\n return {\n where: effectiveWhere as never,\n sort: resolvedSort as never,\n count: BACKOFFICE_RELATED_TAB_PAGE_SIZE,\n cursor: null,\n };\n }, [effectiveWhere, resolvedSort]);\n\n const variables = useMemo(() => {\n return listConfig.buildQueryVariables(variablesBase);\n }, [listConfig, variablesBase]);\n\n const queryData = useLazyLoadQuery<OperationType>(\n listConfig.query,\n variables,\n { fetchPolicy: 'store-or-network' },\n );\n\n const {\n data: fragmentData,\n loadNext,\n hasNext,\n isLoadingNext,\n refetch,\n } = usePaginationFragment(listConfig.fragment, queryData as never);\n\n const connection = listConfig.getConnection(fragmentData);\n const rows = useMemo(() => {\n return connection.edges.map((edge) => {\n return listConfig.toRow(edge.node);\n });\n }, [connection.edges, listConfig]);\n\n const columns = useMemo(() => {\n return buildDataTableColumns(listConfig.columns, {\n tApp,\n t,\n });\n }, [listConfig.columns, t, tApp]);\n\n const getRowId = useCallback(\n (row: unknown) => {\n return listConfig.getRowId(row);\n },\n [listConfig],\n );\n\n const defaults = useMemo(() => {\n const baseWhere = relationWhere ?? listDefaults.where;\n return {\n where: baseWhere,\n sort: listDefaults.sort,\n count: BACKOFFICE_RELATED_TAB_PAGE_SIZE,\n cursor: null,\n };\n }, [listDefaults.sort, listDefaults.where, relationWhere]);\n\n const { onRefresh } = useBackofficeListRefetch({\n refetch,\n variables: variablesBase,\n defaults,\n fetchPolicy: BACKOFFICE_LIST_REFETCH_POLICY,\n buildQueryVariables: listConfig.buildQueryVariables,\n });\n\n const handleLoadMore = useBackofficeLoadMore({\n hasNext,\n isLoadingNext,\n loadNext,\n count: BACKOFFICE_RELATED_TAB_PAGE_SIZE,\n });\n\n return (\n <BackofficeEntityListScaffold\n config={config as never}\n state={state as never}\n pushState={(next) => {\n setState(next);\n }}\n header={{ title }}\n rows={rows}\n columns={columns as never}\n getRowId={getRowId}\n hasNextPage={hasNext}\n isLoadingMore={isLoadingNext}\n onLoadMore={handleLoadMore}\n onRefresh={onRefresh}\n totalCount={connection.totalCount ?? null}\n variant=\"embedded\"\n />\n );\n};\n\nconst RelationListBlockBody = ({\n title,\n relation,\n value,\n}: RelationListBlockBodyProps): JSX.Element | null => {\n const { t } = useBackofficeReactTranslation();\n const relatedEntityIds = useMemo(() => {\n return [relation.target];\n }, [relation.target]);\n const relatedEntitiesState =\n useBackofficeListEntitiesLoader(relatedEntityIds);\n\n if (relatedEntitiesState.status === 'loading') {\n return <BackofficeTableSkeleton rows={6} ariaLabel={t('common.loading')} />;\n }\n\n if (relatedEntitiesState.status === 'error') {\n return (\n <InlineBanner tone=\"warning\" title={t('relations.unavailable.title')}>\n {t('relations.unavailable.description')}\n </InlineBanner>\n );\n }\n\n const config = relatedEntitiesState.modules[relation.target]?.config;\n if (config == null) {\n return null;\n }\n\n return (\n <RelationListContent\n title={title}\n config={config}\n relation={relation}\n value={value}\n />\n );\n};\n\nexport const BackofficeDetailRelationListBlock = ({\n title,\n relation,\n value,\n}: BackofficeDetailRelationListBlockProps): JSX.Element => {\n return (\n <BackofficeErrorBoundary\n fallback={() => {\n return <RelationListSkeleton />;\n }}\n >\n <Suspense fallback={<RelationListSkeleton />}>\n <RelationListBlockBody\n title={title}\n relation={relation}\n value={value}\n />\n </Suspense>\n </BackofficeErrorBoundary>\n );\n};\n\nexport default BackofficeDetailRelationListBlock;\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"BackofficeRelationsSummaryGrid.js","names":[],"sources":["../../../../../src/components/backoffice/detail/BackofficeRelationsSummaryGrid.tsx"],"sourcesContent":["import { type JSX, type ReactNode } from 'react';\nimport Link from '@plumile/router/routing/Link.js';\nimport { BackofficeDetailSection } from '@plumile/ui/backoffice/molecules/backoffice_detail_section/BackofficeDetailSection.js';\nimport type { MetricTone } from '@plumile/ui/components/dashboard/metric_card/MetricCard.js';\n\nimport { useBackofficeReactTranslation } from '../../../i18n/useBackofficeReactTranslation.js';\nimport * as styles from './backofficeRelationsSummaryGrid.css.js';\n\nexport type BackofficeRelationSummaryItem = {\n readonly id: string;\n readonly label: string;\n readonly count?: number | null;\n readonly href?: string;\n readonly description?: ReactNode;\n readonly tone?: MetricTone;\n};\n\nexport type BackofficeRelationsSummaryGridProps = {\n readonly title: string;\n readonly items: readonly BackofficeRelationSummaryItem[];\n};\n\nexport const BackofficeRelationsSummaryGrid = ({\n title,\n items,\n}: BackofficeRelationsSummaryGridProps): JSX.Element | null => {\n const { t } = useBackofficeReactTranslation();\n\n if (items.length === 0) {\n return null;\n }\n\n return (\n <BackofficeDetailSection title={title}>\n <div className={styles.grid}>\n {items.map((item) => {\n const countNode = item.count ?? t('common.notAvailable');\n const content = (\n <>\n <span className={styles.label}>{item.label}</span>\n <span className={styles.count}>{countNode}</span>\n {item.description != null && (\n <span className={styles.description}>{item.description}</span>\n )}\n </>\n );\n\n if (item.href == null) {\n return (\n <div className={styles.item} key={item.id}>\n {content}\n </div>\n );\n }\n\n return (\n <Link\n className={styles.item}\n key={item.id}\n to={item.href}\n preloadOnMouseEnter\n >\n {content}\n </Link>\n );\n })}\n </div>\n </BackofficeDetailSection>\n );\n};\n\nexport default BackofficeRelationsSummaryGrid;\n"],"mappings":";;;;;;AAsBA,IAAa,KAAkC,EAC7C,UACA,eAC6D;CAC7D,IAAM,EAAE,SAAM,EAA8B;CAM5C,OAJI,EAAM,WAAW,IACZ,OAIP,kBAAC,GAAD;EAAgC;YAC9B,kBAAC,OAAD;GAAK,WAAW;aACb,EAAM,KAAK,MAAS;IACnB,IAAM,IAAY,EAAK,SAAS,EAAE,qBAAqB,GACjD,IACJ,kBAAA,GAAA,EAAA,UAAA;KACE,kBAAC,QAAD;MAAM,WAAW;gBAAe,EAAK;KAAY,CAAA;KACjD,kBAAC,QAAD;MAAM,WAAW;gBAAe;KAAgB,CAAA;KAC/C,EAAK,eAAe,QACnB,kBAAC,QAAD;MAAM,WAAW;gBAAqB,EAAK;KAAkB,CAAA;IAE/D,EAAA,CAAA;IAWJ,OARI,EAAK,QAAQ,OAEb,kBAAC,OAAD;KAAK,WAAW;eACb;IACE,GAF6B,EAAK,EAElC,IAKP,kBAAC,GAAD;KACE,WAAW;KAEX,IAAI,EAAK;KACT,qBAAA;eAEC;IACG,GALC,EAAK,EAKN;GAEV,CAAC;EACE,CAAA;CACkB,CAAA;AAE7B"}
1
+ {"version":3,"file":"BackofficeRelationsSummaryGrid.js","names":[],"sources":["../../../../../src/components/backoffice/detail/BackofficeRelationsSummaryGrid.tsx"],"sourcesContent":["import { type JSX, type ReactNode } from 'react';\nimport Link from '@plumile/router/routing/Link.js';\nimport { BackofficeDetailSection } from '@plumile/ui/backoffice/molecules/backoffice_detail_section/BackofficeDetailSection.js';\nimport type { MetricTone } from '@plumile/ui/components/dashboard/metric_card/MetricCard.js';\n\nimport { useBackofficeReactTranslation } from '../../../i18n/useBackofficeReactTranslation.js';\nimport * as styles from './backofficeRelationsSummaryGrid.css.js';\n\nexport type BackofficeRelationSummaryItem = {\n readonly id: string;\n readonly label: string;\n readonly count?: ReactNode;\n readonly href?: string;\n readonly description?: ReactNode;\n readonly tone?: MetricTone;\n};\n\nexport type BackofficeRelationsSummaryGridProps = {\n readonly title: string;\n readonly items: readonly BackofficeRelationSummaryItem[];\n};\n\nexport const BackofficeRelationsSummaryGrid = ({\n title,\n items,\n}: BackofficeRelationsSummaryGridProps): JSX.Element | null => {\n const { t } = useBackofficeReactTranslation();\n\n if (items.length === 0) {\n return null;\n }\n\n return (\n <BackofficeDetailSection title={title}>\n <div className={styles.grid}>\n {items.map((item) => {\n const countNode = item.count ?? t('common.notAvailable');\n const content = (\n <>\n <span className={styles.label}>{item.label}</span>\n <span className={styles.count}>{countNode}</span>\n {item.description != null && (\n <span className={styles.description}>{item.description}</span>\n )}\n </>\n );\n\n if (item.href == null) {\n return (\n <div className={styles.item} key={item.id}>\n {content}\n </div>\n );\n }\n\n return (\n <Link\n className={styles.item}\n key={item.id}\n to={item.href}\n preloadOnMouseEnter\n >\n {content}\n </Link>\n );\n })}\n </div>\n </BackofficeDetailSection>\n );\n};\n\nexport default BackofficeRelationsSummaryGrid;\n"],"mappings":";;;;;;AAsBA,IAAa,KAAkC,EAC7C,UACA,eAC6D;CAC7D,IAAM,EAAE,SAAM,EAA8B;CAM5C,OAJI,EAAM,WAAW,IACZ,OAIP,kBAAC,GAAD;EAAgC;YAC9B,kBAAC,OAAD;GAAK,WAAW;aACb,EAAM,KAAK,MAAS;IACnB,IAAM,IAAY,EAAK,SAAS,EAAE,qBAAqB,GACjD,IACJ,kBAAA,GAAA,EAAA,UAAA;KACE,kBAAC,QAAD;MAAM,WAAW;gBAAe,EAAK;KAAY,CAAA;KACjD,kBAAC,QAAD;MAAM,WAAW;gBAAe;KAAgB,CAAA;KAC/C,EAAK,eAAe,QACnB,kBAAC,QAAD;MAAM,WAAW;gBAAqB,EAAK;KAAkB,CAAA;IAE/D,EAAA,CAAA;IAWJ,OARI,EAAK,QAAQ,OAEb,kBAAC,OAAD;KAAK,WAAW;eACb;IACE,GAF6B,EAAK,EAElC,IAKP,kBAAC,GAAD;KACE,WAAW;KAEX,IAAI,EAAK;KACT,qBAAA;eAEC;IACG,GALC,EAAK,EAKN;GAEV,CAAC;EACE,CAAA;CACkB,CAAA;AAE7B"}
@@ -1,3 +1,4 @@
1
+ /* empty css */
1
2
  /* empty css */
2
3
  //#region src/components/backoffice/filters/backofficeFilterAction.css.ts
3
4
  var e = "hwnq700 txvbqbfqq txvbqbey txvbqbls4 txvbqb19gp txvbqbjm4 txvbqbwvi txvbqb2tz txvbqb28o txvbqb2sj txvbqb1d9 txvbqb1b83 txvbqb1bhb txvbqbv txvbqb3f txvbqb7h txvbqb75 txvbqb7t txvbqb1eol txvbqb1czh txvbqb1dth qbwcue0 txvbqb1ffs txvbqb1ga0", t = "txvbqb19fm txvbqbjl1";
@@ -0,0 +1,31 @@
1
+ import { BackofficeErrorBoundary as e } from "../errors/BackofficeErrorBoundary.js";
2
+ import { useBackofficeListEntitiesLoader as t } from "../../../provider/useBackofficeEntityLoader.js";
3
+ import { Suspense as n } from "react";
4
+ import { Fragment as r, jsx as i } from "react/jsx-runtime";
5
+ import { useLazyLoadQuery as a } from "react-relay";
6
+ //#region src/components/backoffice/refs/BackofficeLazyEntityCount.tsx
7
+ var o = "store-or-network", s = ({ config: e, where: t }) => {
8
+ let { count: n } = e.list, s = n.buildVariables({ where: t }), c = a(n.query, s, { fetchPolicy: o }), l = n.getCount(c);
9
+ return l == null ? null : /* @__PURE__ */ i(r, { children: l });
10
+ }, c = ({ entity: e, where: n }) => {
11
+ let r = t([e]);
12
+ if (r.status !== "loaded") return null;
13
+ let a = r.modules[e]?.config;
14
+ return a == null ? null : /* @__PURE__ */ i(s, {
15
+ config: a,
16
+ where: n
17
+ });
18
+ }, l = ({ entity: t, where: r }) => /* @__PURE__ */ i(e, {
19
+ fallback: () => null,
20
+ children: /* @__PURE__ */ i(n, {
21
+ fallback: null,
22
+ children: /* @__PURE__ */ i(c, {
23
+ entity: t,
24
+ where: r
25
+ })
26
+ })
27
+ });
28
+ //#endregion
29
+ export { l as BackofficeLazyEntityCount, l as default };
30
+
31
+ //# sourceMappingURL=BackofficeLazyEntityCount.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BackofficeLazyEntityCount.js","names":[],"sources":["../../../../../src/components/backoffice/refs/BackofficeLazyEntityCount.tsx"],"sourcesContent":["import { Suspense, type JSX } from 'react';\nimport { useLazyLoadQuery } from 'react-relay';\nimport type { OperationType } from 'relay-runtime';\n\nimport type { BackofficeRuntimeResolvedListFacetConfig } from '@plumile/backoffice-core/types.js';\n\nimport { useBackofficeListEntitiesLoader } from '../../../provider/useBackofficeEntityLoader.js';\nimport { BackofficeErrorBoundary } from '../errors/BackofficeErrorBoundary.js';\n\nconst COUNT_FETCH_POLICY = 'store-or-network' as const;\n\nexport type BackofficeLazyEntityCountProps<\n Where extends Record<string, unknown> = Record<string, unknown>,\n> = {\n entity: string;\n where: Where | null;\n};\n\nconst BackofficeEntityCountValue = ({\n config,\n where,\n}: {\n config: BackofficeRuntimeResolvedListFacetConfig;\n where: Record<string, unknown> | null;\n}): JSX.Element | null => {\n const { count } = config.list;\n const variables = count.buildVariables({ where });\n const data = useLazyLoadQuery<OperationType>(count.query, variables, {\n fetchPolicy: COUNT_FETCH_POLICY,\n });\n const value = count.getCount(data);\n if (value == null) {\n return null;\n }\n return <>{value}</>;\n};\n\nconst BackofficeLazyEntityCountBody = ({\n entity,\n where,\n}: BackofficeLazyEntityCountProps): JSX.Element | null => {\n const relatedEntitiesState = useBackofficeListEntitiesLoader([entity]);\n if (relatedEntitiesState.status !== 'loaded') {\n return null;\n }\n\n const config = relatedEntitiesState.modules[entity]?.config;\n if (config == null) {\n return null;\n }\n\n return <BackofficeEntityCountValue config={config} where={where} />;\n};\n\nexport const BackofficeLazyEntityCount = ({\n entity,\n where,\n}: BackofficeLazyEntityCountProps): JSX.Element | null => {\n return (\n <BackofficeErrorBoundary\n fallback={() => {\n return null;\n }}\n >\n <Suspense fallback={null}>\n <BackofficeLazyEntityCountBody entity={entity} where={where} />\n </Suspense>\n </BackofficeErrorBoundary>\n );\n};\n\nexport default BackofficeLazyEntityCount;\n"],"mappings":";;;;;;AASA,IAAM,IAAqB,oBASrB,KAA8B,EAClC,WACA,eAIwB;CACxB,IAAM,EAAE,aAAU,EAAO,MACnB,IAAY,EAAM,eAAe,EAAE,SAAM,CAAC,GAC1C,IAAO,EAAgC,EAAM,OAAO,GAAW,EACnE,aAAa,EACf,CAAC,GACK,IAAQ,EAAM,SAAS,CAAI;CAIjC,OAHI,KAAS,OACJ,OAEF,kBAAA,GAAA,EAAA,UAAG,EAAQ,CAAA;AACpB,GAEM,KAAiC,EACrC,WACA,eACwD;CACxD,IAAM,IAAuB,EAAgC,CAAC,CAAM,CAAC;CACrE,IAAI,EAAqB,WAAW,UAClC,OAAO;CAGT,IAAM,IAAS,EAAqB,QAAQ,IAAS;CAKrD,OAJI,KAAU,OACL,OAGF,kBAAC,GAAD;EAAoC;EAAe;CAAQ,CAAA;AACpE,GAEa,KAA6B,EACxC,WACA,eAGE,kBAAC,GAAD;CACE,gBACS;WAGT,kBAAC,GAAD;EAAU,UAAU;YAClB,kBAAC,GAAD;GAAuC;GAAe;EAAQ,CAAA;CACtD,CAAA;AACa,CAAA"}
@@ -2,45 +2,49 @@ import { useBackofficeReactTranslation as e } from "../../../i18n/useBackofficeR
2
2
  import { useBackofficeConfig as t } from "../../../provider/BackofficeConfigContext.js";
3
3
  import { resolveBackofficeLink as n } from "../links/resolveBackofficeLink.js";
4
4
  import { BackofficeInlineLink as r } from "../links/BackofficeInlineLink.js";
5
- import { count as i, icon as a, link as o } from "./backofficeRelatedCountLink.css.js";
6
- import { useContext as s } from "react";
7
- import { jsx as c } from "react/jsx-runtime";
8
- import { useTranslation as l } from "react-i18next";
9
- import u from "@plumile/router/routing/RoutingContext.js";
10
- import { buildBackofficeListLink as d } from "@plumile/backoffice-core/state/buildListHref.js";
5
+ import { BackofficeLazyEntityCount as i } from "./BackofficeLazyEntityCount.js";
6
+ import { count as a, icon as o, link as s } from "./backofficeRelatedCountLink.css.js";
7
+ import { useContext as c } from "react";
8
+ import { jsx as l } from "react/jsx-runtime";
9
+ import { useTranslation as u } from "react-i18next";
10
+ import d from "@plumile/router/routing/RoutingContext.js";
11
+ import { buildBackofficeListLink as f } from "@plumile/backoffice-core/state/buildListHref.js";
11
12
  //#region src/components/backoffice/refs/BackofficeRelatedCountLink.tsx
12
- var f = ({ count: f, entity: p, where: m }) => {
13
- let { t: h } = l(), { t: g } = e(), { entities: _, entityManifest: v, entityRegistry: y, sidebar: b } = t(), x = s(u), S = 0;
14
- typeof f == "number" && Number.isFinite(f) && (S = f);
15
- let C = _[p];
16
- if (C == null) return /* @__PURE__ */ c("span", { children: S });
17
- let w = g("relations.openFilteredList", { label: C.label(h) }), T = y.getLoadedListEntity(p), E = {
13
+ var p = ({ count: p, entity: m, where: h }) => {
14
+ let { t: g } = u(), { t: _ } = e(), { entities: v, entityManifest: y, entityRegistry: b, sidebar: x } = t(), S = c(d), C = v[m];
15
+ if (C == null) return /* @__PURE__ */ l("span", { children: p ?? 0 });
16
+ let w = _("relations.openFilteredList", { label: C.label(g) }), T = b.getLoadedListEntity(m), E = /* @__PURE__ */ l(i, {
17
+ entity: m,
18
+ where: h
19
+ });
20
+ typeof p == "number" && Number.isFinite(p) && (E = p);
21
+ let D = {
18
22
  kind: "entity-list",
19
- entityId: p,
20
- state: { where: m }
21
- }, D = async (e) => {
22
- let t = d((await y.loadListEntity(p)).config, { where: m }), n = "";
23
+ entityId: m,
24
+ state: { where: h }
25
+ }, O = async (e) => {
26
+ let t = f((await b.loadListEntity(m)).config, { where: h }), n = "";
23
27
  t.search !== "" && (n = `?${t.search}`), e.push({
24
28
  pathname: t.pathname,
25
29
  search: n,
26
30
  hash: ""
27
31
  });
28
32
  };
29
- return /* @__PURE__ */ c(r, {
30
- target: E,
31
- className: o,
33
+ return /* @__PURE__ */ l(r, {
34
+ target: D,
35
+ className: s,
32
36
  title: w,
33
37
  ariaLabel: w,
34
38
  onClick: (e) => {
35
- if (T != null || x == null || e.defaultPrevented || e.button !== 0 || e.metaKey || e.altKey || e.ctrlKey || e.shiftKey) return;
39
+ if (T != null || S == null || e.defaultPrevented || e.button !== 0 || e.metaKey || e.altKey || e.ctrlKey || e.shiftKey) return;
36
40
  e.preventDefault();
37
- let { history: t } = x;
38
- D(t).catch(() => {
41
+ let { history: t } = S;
42
+ O(t).catch(() => {
39
43
  let e = n({
40
- target: E,
41
- manifest: v,
42
- sidebar: b,
43
- tApp: h
44
+ target: D,
45
+ manifest: y,
46
+ sidebar: x,
47
+ tApp: g
44
48
  }), r = new URL(e.href, window.location.origin);
45
49
  t.push({
46
50
  pathname: r.pathname,
@@ -49,18 +53,18 @@ var f = ({ count: f, entity: p, where: m }) => {
49
53
  });
50
54
  });
51
55
  },
52
- endAdornment: /* @__PURE__ */ c("span", {
53
- className: a,
56
+ endAdornment: /* @__PURE__ */ l("span", {
57
+ className: o,
54
58
  "aria-hidden": "true",
55
59
  children: "›"
56
60
  }),
57
- children: /* @__PURE__ */ c("span", {
58
- className: i,
59
- children: S
61
+ children: /* @__PURE__ */ l("span", {
62
+ className: a,
63
+ children: E
60
64
  })
61
65
  });
62
66
  };
63
67
  //#endregion
64
- export { f as BackofficeRelatedCountLink, f as default };
68
+ export { p as BackofficeRelatedCountLink, p as default };
65
69
 
66
70
  //# sourceMappingURL=BackofficeRelatedCountLink.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"BackofficeRelatedCountLink.js","names":[],"sources":["../../../../../src/components/backoffice/refs/BackofficeRelatedCountLink.tsx"],"sourcesContent":["import { useContext, type JSX, type MouseEvent } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport RoutingContext from '@plumile/router/routing/RoutingContext.js';\n\nimport { buildBackofficeListLink } from '@plumile/backoffice-core/state/buildListHref.js';\nimport { useBackofficeConfig } from '../../../provider/BackofficeConfigContext.js';\nimport { useBackofficeReactTranslation } from '../../../i18n/useBackofficeReactTranslation.js';\nimport { BackofficeInlineLink } from '../links/BackofficeInlineLink.js';\nimport { resolveBackofficeLink } from '../links/resolveBackofficeLink.js';\nimport type { BackofficeLinkTarget } from '../links/types.js';\n\nimport * as styles from './backofficeRelatedCountLink.css.js';\n\nexport type BackofficeRelatedCountLinkProps<\n Where extends Record<string, unknown> = Record<string, unknown>,\n> = {\n count: number | null | undefined;\n entity: string;\n where: Where;\n};\n\nexport const BackofficeRelatedCountLink = <\n Where extends Record<string, unknown> = Record<string, unknown>,\n>({\n count,\n entity,\n where,\n}: BackofficeRelatedCountLinkProps<Where>): JSX.Element => {\n const { t: tApp } = useTranslation();\n const { t } = useBackofficeReactTranslation();\n const { entities, entityManifest, entityRegistry, sidebar } =\n useBackofficeConfig();\n const routing = useContext(RoutingContext);\n let resolvedCount = 0;\n if (typeof count === 'number' && Number.isFinite(count)) {\n resolvedCount = count;\n }\n const targetManifest = entities[entity];\n if (targetManifest == null) {\n return <span>{resolvedCount}</span>;\n }\n const entityLabel = targetManifest.label(tApp);\n const actionLabel = t('relations.openFilteredList', {\n label: entityLabel,\n });\n const loadedEntity = entityRegistry.getLoadedListEntity(entity);\n const target = {\n kind: 'entity-list',\n entityId: entity,\n state: { where },\n } as BackofficeLinkTarget;\n\n const navigateWithLoadedEntity = async (\n history: NonNullable<typeof routing>['history'],\n ): Promise<void> => {\n const listEntity = await entityRegistry.loadListEntity(entity);\n const next = buildBackofficeListLink(listEntity.config, { where });\n\n let search = '';\n if (next.search !== '') {\n search = `?${next.search}`;\n }\n\n history.push({\n pathname: next.pathname,\n search,\n hash: '',\n });\n };\n\n const handleClick = (event: MouseEvent<HTMLAnchorElement>) => {\n if (\n loadedEntity != null ||\n routing == null ||\n event.defaultPrevented ||\n event.button !== 0 ||\n event.metaKey ||\n event.altKey ||\n event.ctrlKey ||\n event.shiftKey\n ) {\n return;\n }\n\n event.preventDefault();\n const { history } = routing;\n navigateWithLoadedEntity(history).catch(() => {\n const link = resolveBackofficeLink({\n target,\n manifest: entityManifest,\n sidebar,\n tApp,\n });\n const fallbackUrl = new URL(link.href, window.location.origin);\n history.push({\n pathname: fallbackUrl.pathname,\n search: fallbackUrl.search,\n hash: fallbackUrl.hash,\n });\n });\n };\n\n return (\n <BackofficeInlineLink\n target={target}\n className={styles.link}\n title={actionLabel}\n ariaLabel={actionLabel}\n onClick={handleClick}\n endAdornment={\n <span className={styles.icon} aria-hidden=\"true\">\n ›\n </span>\n }\n >\n <span className={styles.count}>{resolvedCount}</span>\n </BackofficeInlineLink>\n );\n};\n\nexport default BackofficeRelatedCountLink;\n"],"mappings":";;;;;;;;;;;AAqBA,IAAa,KAEX,EACA,OAAA,GACA,WACA,eACyD;CACzD,IAAM,EAAE,GAAG,MAAS,EAAe,GAC7B,EAAE,SAAM,EAA8B,GACtC,EAAE,aAAU,mBAAgB,mBAAgB,eAChD,EAAoB,GAChB,IAAU,EAAW,CAAc,GACrC,IAAgB;CACpB,AAAI,OAAO,KAAU,YAAY,OAAO,SAAS,CAAK,MACpD,IAAgB;CAElB,IAAM,IAAiB,EAAS;CAChC,IAAI,KAAkB,MACpB,OAAO,kBAAC,QAAD,EAAA,UAAO,EAAoB,CAAA;CAGpC,IAAM,IAAc,EAAE,8BAA8B,EAClD,OAFkB,EAAe,MAAM,CAEhC,EACT,CAAC,GACK,IAAe,EAAe,oBAAoB,CAAM,GACxD,IAAS;EACb,MAAM;EACN,UAAU;EACV,OAAO,EAAE,SAAM;CACjB,GAEM,IAA2B,OAC/B,MACkB;EAElB,IAAM,IAAO,GAAwB,MADZ,EAAe,eAAe,CAAM,GACb,QAAQ,EAAE,SAAM,CAAC,GAE7D,IAAS;EAKb,AAJI,EAAK,WAAW,OAClB,IAAS,IAAI,EAAK,WAGpB,EAAQ,KAAK;GACX,UAAU,EAAK;GACf;GACA,MAAM;EACR,CAAC;CACH;CAkCA,OACE,kBAAC,GAAD;EACU;EACR,WAAW;EACX,OAAO;EACP,WAAW;EACX,UAtCiB,MAAyC;GAC5D,IACE,KAAgB,QAChB,KAAW,QACX,EAAM,oBACN,EAAM,WAAW,KACjB,EAAM,WACN,EAAM,UACN,EAAM,WACN,EAAM,UAEN;GAGF,EAAM,eAAe;GACrB,IAAM,EAAE,eAAY;GACpB,EAAyB,CAAO,EAAE,YAAY;IAC5C,IAAM,IAAO,EAAsB;KACjC;KACA,UAAU;KACV;KACA;IACF,CAAC,GACK,IAAc,IAAI,IAAI,EAAK,MAAM,OAAO,SAAS,MAAM;IAC7D,EAAQ,KAAK;KACX,UAAU,EAAY;KACtB,QAAQ,EAAY;KACpB,MAAM,EAAY;IACpB,CAAC;GACH,CAAC;EACH;EASI,cACE,kBAAC,QAAD;GAAM,WAAW;GAAa,eAAY;aAAO;EAE3C,CAAA;YAGR,kBAAC,QAAD;GAAM,WAAW;aAAe;EAAoB,CAAA;CAChC,CAAA;AAE1B"}
1
+ {"version":3,"file":"BackofficeRelatedCountLink.js","names":[],"sources":["../../../../../src/components/backoffice/refs/BackofficeRelatedCountLink.tsx"],"sourcesContent":["import { useContext, type JSX, type MouseEvent, type ReactNode } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport RoutingContext from '@plumile/router/routing/RoutingContext.js';\n\nimport { buildBackofficeListLink } from '@plumile/backoffice-core/state/buildListHref.js';\nimport { useBackofficeConfig } from '../../../provider/BackofficeConfigContext.js';\nimport { useBackofficeReactTranslation } from '../../../i18n/useBackofficeReactTranslation.js';\nimport { BackofficeInlineLink } from '../links/BackofficeInlineLink.js';\nimport { resolveBackofficeLink } from '../links/resolveBackofficeLink.js';\nimport type { BackofficeLinkTarget } from '../links/types.js';\nimport { BackofficeLazyEntityCount } from './BackofficeLazyEntityCount.js';\n\nimport * as styles from './backofficeRelatedCountLink.css.js';\n\nexport type BackofficeRelatedCountLinkProps<\n Where extends Record<string, unknown> = Record<string, unknown>,\n> = {\n count?: number | null | undefined;\n entity: string;\n where: Where;\n};\n\nexport const BackofficeRelatedCountLink = <\n Where extends Record<string, unknown> = Record<string, unknown>,\n>({\n count,\n entity,\n where,\n}: BackofficeRelatedCountLinkProps<Where>): JSX.Element => {\n const { t: tApp } = useTranslation();\n const { t } = useBackofficeReactTranslation();\n const { entities, entityManifest, entityRegistry, sidebar } =\n useBackofficeConfig();\n const routing = useContext(RoutingContext);\n const targetManifest = entities[entity];\n if (targetManifest == null) {\n return <span>{count ?? 0}</span>;\n }\n const entityLabel = targetManifest.label(tApp);\n const actionLabel = t('relations.openFilteredList', {\n label: entityLabel,\n });\n const loadedEntity = entityRegistry.getLoadedListEntity(entity);\n let countNode: ReactNode = (\n <BackofficeLazyEntityCount entity={entity} where={where} />\n );\n if (typeof count === 'number' && Number.isFinite(count)) {\n countNode = count;\n }\n const target = {\n kind: 'entity-list',\n entityId: entity,\n state: { where },\n } as BackofficeLinkTarget;\n\n const navigateWithLoadedEntity = async (\n history: NonNullable<typeof routing>['history'],\n ): Promise<void> => {\n const listEntity = await entityRegistry.loadListEntity(entity);\n const next = buildBackofficeListLink(listEntity.config, { where });\n\n let search = '';\n if (next.search !== '') {\n search = `?${next.search}`;\n }\n\n history.push({\n pathname: next.pathname,\n search,\n hash: '',\n });\n };\n\n const handleClick = (event: MouseEvent<HTMLAnchorElement>) => {\n if (\n loadedEntity != null ||\n routing == null ||\n event.defaultPrevented ||\n event.button !== 0 ||\n event.metaKey ||\n event.altKey ||\n event.ctrlKey ||\n event.shiftKey\n ) {\n return;\n }\n\n event.preventDefault();\n const { history } = routing;\n navigateWithLoadedEntity(history).catch(() => {\n const link = resolveBackofficeLink({\n target,\n manifest: entityManifest,\n sidebar,\n tApp,\n });\n const fallbackUrl = new URL(link.href, window.location.origin);\n history.push({\n pathname: fallbackUrl.pathname,\n search: fallbackUrl.search,\n hash: fallbackUrl.hash,\n });\n });\n };\n\n return (\n <BackofficeInlineLink\n target={target}\n className={styles.link}\n title={actionLabel}\n ariaLabel={actionLabel}\n onClick={handleClick}\n endAdornment={\n <span className={styles.icon} aria-hidden=\"true\">\n ›\n </span>\n }\n >\n <span className={styles.count}>{countNode}</span>\n </BackofficeInlineLink>\n );\n};\n\nexport default BackofficeRelatedCountLink;\n"],"mappings":";;;;;;;;;;;;AAsBA,IAAa,KAEX,EACA,OAAA,GACA,WACA,eACyD;CACzD,IAAM,EAAE,GAAG,MAAS,EAAe,GAC7B,EAAE,SAAM,EAA8B,GACtC,EAAE,aAAU,mBAAgB,mBAAgB,eAChD,EAAoB,GAChB,IAAU,EAAW,CAAc,GACnC,IAAiB,EAAS;CAChC,IAAI,KAAkB,MACpB,OAAO,kBAAC,QAAD,EAAA,UAAO,KAAS,EAAQ,CAAA;CAGjC,IAAM,IAAc,EAAE,8BAA8B,EAClD,OAFkB,EAAe,MAAM,CAEhC,EACT,CAAC,GACK,IAAe,EAAe,oBAAoB,CAAM,GAC1D,IACF,kBAAC,GAAD;EAAmC;EAAe;CAAQ,CAAA;CAE5D,AAAI,OAAO,KAAU,YAAY,OAAO,SAAS,CAAK,MACpD,IAAY;CAEd,IAAM,IAAS;EACb,MAAM;EACN,UAAU;EACV,OAAO,EAAE,SAAM;CACjB,GAEM,IAA2B,OAC/B,MACkB;EAElB,IAAM,IAAO,GAAwB,MADZ,EAAe,eAAe,CAAM,GACb,QAAQ,EAAE,SAAM,CAAC,GAE7D,IAAS;EAKb,AAJI,EAAK,WAAW,OAClB,IAAS,IAAI,EAAK,WAGpB,EAAQ,KAAK;GACX,UAAU,EAAK;GACf;GACA,MAAM;EACR,CAAC;CACH;CAkCA,OACE,kBAAC,GAAD;EACU;EACR,WAAW;EACX,OAAO;EACP,WAAW;EACX,UAtCiB,MAAyC;GAC5D,IACE,KAAgB,QAChB,KAAW,QACX,EAAM,oBACN,EAAM,WAAW,KACjB,EAAM,WACN,EAAM,UACN,EAAM,WACN,EAAM,UAEN;GAGF,EAAM,eAAe;GACrB,IAAM,EAAE,eAAY;GACpB,EAAyB,CAAO,EAAE,YAAY;IAC5C,IAAM,IAAO,EAAsB;KACjC;KACA,UAAU;KACV;KACA;IACF,CAAC,GACK,IAAc,IAAI,IAAI,EAAK,MAAM,OAAO,SAAS,MAAM;IAC7D,EAAQ,KAAK;KACX,UAAU,EAAY;KACtB,QAAQ,EAAY;KACpB,MAAM,EAAY;IACpB,CAAC;GACH,CAAC;EACH;EASI,cACE,kBAAC,QAAD;GAAM,WAAW;GAAa,eAAY;aAAO;EAE3C,CAAA;YAGR,kBAAC,QAAD;GAAM,WAAW;aAAe;EAAgB,CAAA;CAC5B,CAAA;AAE1B"}
@@ -1,4 +1,3 @@
1
- /* empty css */
2
1
  /* empty css */
3
2
  //#region src/components/backoffice/refs/backofficeEntityIdRef.css.ts
4
3
  var e = "qbwcuep qbwcuen txvbqbfqq txvbqbey txvbqbhd8 txvbqb1bg1 txvbqb3f txvbqb7h txvbqb75 txvbqb7t qbwcueo txvbqb1gct qbwcue0 txvbqb1ffs txvbqb1ga0";
@@ -1 +1 @@
1
- {"version":3,"file":"useBackofficeAuth.js","names":[],"sources":["../../../src/hooks/useBackofficeAuth.ts"],"sourcesContent":["import { useCallback, useMemo, useState } from 'react';\nimport * as ReactRelay from 'react-relay';\nimport type { GraphQLTaggedNode, PayloadError } from 'relay-runtime';\n\nimport {\n createUseAuth,\n type UseAuthReturn,\n type AcceptInvitationResponse,\n type AcceptInvitationVariables,\n type BeginAuthenticationResponse,\n type BeginAuthenticationVariables,\n type BeginPasskeyLoginResponse,\n type BeginPasskeyLoginVariables,\n type CompleteMfaResponse,\n type CompleteMfaVariables,\n type FinishPasskeyLoginResponse,\n type FinishPasskeyLoginVariables,\n type LoginResponse,\n type LoginVariables,\n type LogoutResponse,\n type LogoutVariables,\n} from './useAuth.js';\nimport { useBackofficeConfig } from '../provider/BackofficeConfigContext.js';\nimport type { BackofficeLazyValue } from '../provider/lazyValue.js';\nimport { useRelayEnvironment } from '../relay/useRelayEnvironment.js';\n\nconst { commitMutation } = ReactRelay;\n\ntype MutationCommitConfig<TVariables, TResponse> = {\n variables: TVariables;\n onCompleted?: (\n response: TResponse,\n errors: readonly PayloadError[] | null,\n ) => void;\n onError?: (error: Error) => void;\n};\n\nconst toMutationLoadError = (error: unknown): Error => {\n if (error instanceof Error) {\n return error;\n }\n return new Error('Unable to load auth mutation.');\n};\n\nconst useDeferredMutation = <TVariables extends object, TResponse>(\n loadMutation: () => Promise<GraphQLTaggedNode | null>,\n) => {\n const relayEnvironment = useRelayEnvironment();\n const [inFlightCount, setInFlightCount] = useState(0);\n\n const commit = useCallback(\n (config: MutationCommitConfig<TVariables, TResponse>) => {\n setInFlightCount((count) => {\n return count + 1;\n });\n\n const finish = () => {\n setInFlightCount((count) => {\n return Math.max(0, count - 1);\n });\n };\n\n loadMutation()\n .then((mutation) => {\n if (mutation == null) {\n throw new Error('Missing auth mutation config.');\n }\n\n commitMutation(relayEnvironment, {\n mutation,\n variables: config.variables,\n onCompleted: (response, errors) => {\n finish();\n config.onCompleted?.(response as TResponse, errors ?? null);\n },\n onError: (error) => {\n finish();\n config.onError?.(error);\n },\n });\n })\n .catch((error: unknown) => {\n finish();\n config.onError?.(toMutationLoadError(error));\n });\n },\n [loadMutation, relayEnvironment],\n );\n\n return {\n commit,\n isInFlight: inFlightCount > 0,\n };\n};\n\nconst loadOptionalMutation = async <TConfig>(\n eagerMutation: GraphQLTaggedNode | null | undefined,\n lazyConfig: BackofficeLazyValue<TConfig> | null | undefined,\n selectMutation: (config: TConfig) => GraphQLTaggedNode,\n): Promise<GraphQLTaggedNode | null> => {\n if (eagerMutation != null) {\n return eagerMutation;\n }\n if (lazyConfig == null) {\n return null;\n }\n const loadedConfig = await lazyConfig.load();\n return selectMutation(loadedConfig);\n};\n\n/**\n * Provides auth actions/state backed by Relay mutations from BackofficeProvider.\n */\nexport function useBackofficeAuth(): UseAuthReturn {\n const { auth: authConfig } = useBackofficeConfig();\n const { commit: commitLogin, isInFlight: isLoginInFlight } =\n useDeferredMutation<LoginVariables, LoginResponse>(\n useCallback(async () => {\n const loginConfig = authConfig.login.get();\n return loadOptionalMutation(\n loginConfig?.loginMutation,\n authConfig.login,\n (config) => {\n return config.loginMutation;\n },\n );\n }, [authConfig.login]),\n );\n const { commit: commitLogout, isInFlight: isLogoutInFlight } =\n useDeferredMutation<LogoutVariables, LogoutResponse>(\n useCallback(async () => {\n const logoutConfig = await authConfig.logout.load();\n return logoutConfig.logoutMutation;\n }, [authConfig.logout]),\n );\n const { commit: commitCompleteMfa, isInFlight: isCompleteMfaInFlight } =\n useDeferredMutation<CompleteMfaVariables, CompleteMfaResponse>(\n useCallback(async () => {\n return loadOptionalMutation(\n authConfig.login.get()?.completeMfaMutation,\n authConfig.completeMfa,\n (config) => {\n return config.completeMfaMutation;\n },\n );\n }, [authConfig.completeMfa, authConfig.login]),\n );\n const {\n commit: commitBeginPasskeyLogin,\n isInFlight: isBeginPasskeyLoginInFlight,\n } = useDeferredMutation<\n BeginPasskeyLoginVariables,\n BeginPasskeyLoginResponse\n >(\n useCallback(async () => {\n return loadOptionalMutation(\n authConfig.login.get()?.beginPasskeyLoginMutation,\n authConfig.passkeyLogin,\n (config) => {\n return config.beginPasskeyLoginMutation;\n },\n );\n }, [authConfig.login, authConfig.passkeyLogin]),\n );\n const {\n commit: commitFinishPasskeyLogin,\n isInFlight: isFinishPasskeyLoginInFlight,\n } = useDeferredMutation<\n FinishPasskeyLoginVariables,\n FinishPasskeyLoginResponse\n >(\n useCallback(async () => {\n return loadOptionalMutation(\n authConfig.login.get()?.finishPasskeyLoginMutation,\n authConfig.passkeyLogin,\n (config) => {\n return config.finishPasskeyLoginMutation;\n },\n );\n }, [authConfig.login, authConfig.passkeyLogin]),\n );\n const {\n commit: commitBeginAuthentication,\n isInFlight: isBeginAuthenticationInFlight,\n } = useDeferredMutation<\n BeginAuthenticationVariables,\n BeginAuthenticationResponse\n >(\n useCallback(async () => {\n return loadOptionalMutation(\n authConfig.login.get()?.beginAuthenticationMutation,\n authConfig.authentication,\n (config) => {\n return config.beginAuthenticationMutation;\n },\n );\n }, [authConfig.authentication, authConfig.login]),\n );\n const {\n commit: commitAcceptInvitation,\n isInFlight: isAcceptInvitationInFlight,\n } = useDeferredMutation<AcceptInvitationVariables, AcceptInvitationResponse>(\n useCallback(async () => {\n return loadOptionalMutation(\n authConfig.login.get()?.acceptInvitationMutation,\n authConfig.acceptInvitation,\n (config) => {\n return config.acceptInvitationMutation;\n },\n );\n }, [authConfig.acceptInvitation, authConfig.login]),\n );\n const hasAcceptInvitationMutation =\n authConfig.login.get()?.acceptInvitationMutation != null ||\n authConfig.acceptInvitation != null;\n\n const useAuthWithMutations = useMemo(() => {\n let acceptInvitation:\n | {\n commit: typeof commitAcceptInvitation;\n isInFlight: boolean;\n }\n | undefined;\n if (hasAcceptInvitationMutation) {\n acceptInvitation = {\n commit: commitAcceptInvitation,\n isInFlight: isAcceptInvitationInFlight,\n };\n }\n return createUseAuth({\n login: { commit: commitLogin, isInFlight: isLoginInFlight },\n logout: { commit: commitLogout, isInFlight: isLogoutInFlight },\n completeMfa: {\n commit: commitCompleteMfa,\n isInFlight: isCompleteMfaInFlight,\n },\n beginPasskeyLogin: {\n commit: commitBeginPasskeyLogin,\n isInFlight: isBeginPasskeyLoginInFlight,\n },\n finishPasskeyLogin: {\n commit: commitFinishPasskeyLogin,\n isInFlight: isFinishPasskeyLoginInFlight,\n },\n beginAuthentication: {\n commit: commitBeginAuthentication,\n isInFlight: isBeginAuthenticationInFlight,\n },\n acceptInvitation,\n });\n }, [\n commitAcceptInvitation,\n commitBeginAuthentication,\n commitBeginPasskeyLogin,\n commitCompleteMfa,\n commitFinishPasskeyLogin,\n commitLogin,\n commitLogout,\n hasAcceptInvitationMutation,\n isAcceptInvitationInFlight,\n isBeginAuthenticationInFlight,\n isBeginPasskeyLoginInFlight,\n isCompleteMfaInFlight,\n isFinishPasskeyLoginInFlight,\n isLoginInFlight,\n isLogoutInFlight,\n ]);\n\n return useAuthWithMutations();\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"useBackofficeAuth.js","names":[],"sources":["../../../src/hooks/useBackofficeAuth.ts"],"sourcesContent":["import { useCallback, useMemo, useState } from 'react';\nimport * as ReactRelay from 'react-relay';\nimport type { GraphQLTaggedNode, PayloadError } from 'relay-runtime';\n\nimport {\n createUseAuth,\n type UseAuthReturn,\n type AcceptInvitationResponse,\n type AcceptInvitationVariables,\n type BeginAuthenticationResponse,\n type BeginAuthenticationVariables,\n type BeginPasskeyLoginResponse,\n type BeginPasskeyLoginVariables,\n type CompleteMfaResponse,\n type CompleteMfaVariables,\n type FinishPasskeyLoginResponse,\n type FinishPasskeyLoginVariables,\n type LoginResponse,\n type LoginVariables,\n type LogoutResponse,\n type LogoutVariables,\n} from './useAuth.js';\nimport { useBackofficeConfig } from '../provider/BackofficeConfigContext.js';\nimport type { BackofficeLazyValue } from '../provider/lazyValue.js';\nimport { useRelayEnvironment } from '../relay/useRelayEnvironment.js';\n\nconst { commitMutation } = ReactRelay;\n\ntype MutationCommitConfig<TVariables, TResponse> = {\n variables: TVariables;\n onCompleted?: (\n response: TResponse,\n errors: readonly PayloadError[] | null,\n ) => void;\n onError?: (error: Error) => void;\n};\n\nconst toMutationLoadError = (error: unknown): Error => {\n if (error instanceof Error) {\n return error;\n }\n return new Error('Unable to load auth mutation.');\n};\n\nconst useDeferredMutation = <TVariables extends object, TResponse>(\n loadMutation: () => Promise<GraphQLTaggedNode | null>,\n) => {\n const relayEnvironment = useRelayEnvironment();\n const [inFlightCount, setInFlightCount] = useState(0);\n\n const commit = useCallback(\n (config: MutationCommitConfig<TVariables, TResponse>) => {\n setInFlightCount((count) => {\n return count + 1;\n });\n\n const finish = () => {\n setInFlightCount((count) => {\n return Math.max(0, count - 1);\n });\n };\n\n loadMutation()\n .then((mutation) => {\n if (mutation == null) {\n throw new Error('Missing auth mutation config.');\n }\n\n commitMutation(relayEnvironment, {\n mutation,\n variables: config.variables as Record<string, unknown>,\n onCompleted: (response, errors) => {\n finish();\n config.onCompleted?.(response as TResponse, errors ?? null);\n },\n onError: (error) => {\n finish();\n config.onError?.(error);\n },\n });\n })\n .catch((error: unknown) => {\n finish();\n config.onError?.(toMutationLoadError(error));\n });\n },\n [loadMutation, relayEnvironment],\n );\n\n return {\n commit,\n isInFlight: inFlightCount > 0,\n };\n};\n\nconst loadOptionalMutation = async <TConfig>(\n eagerMutation: GraphQLTaggedNode | null | undefined,\n lazyConfig: BackofficeLazyValue<TConfig> | null | undefined,\n selectMutation: (config: TConfig) => GraphQLTaggedNode,\n): Promise<GraphQLTaggedNode | null> => {\n if (eagerMutation != null) {\n return eagerMutation;\n }\n if (lazyConfig == null) {\n return null;\n }\n const loadedConfig = await lazyConfig.load();\n return selectMutation(loadedConfig);\n};\n\n/**\n * Provides auth actions/state backed by Relay mutations from BackofficeProvider.\n */\nexport function useBackofficeAuth(): UseAuthReturn {\n const { auth: authConfig } = useBackofficeConfig();\n const { commit: commitLogin, isInFlight: isLoginInFlight } =\n useDeferredMutation<LoginVariables, LoginResponse>(\n useCallback(async () => {\n const loginConfig = authConfig.login.get();\n return loadOptionalMutation(\n loginConfig?.loginMutation,\n authConfig.login,\n (config) => {\n return config.loginMutation;\n },\n );\n }, [authConfig.login]),\n );\n const { commit: commitLogout, isInFlight: isLogoutInFlight } =\n useDeferredMutation<LogoutVariables, LogoutResponse>(\n useCallback(async () => {\n const logoutConfig = await authConfig.logout.load();\n return logoutConfig.logoutMutation;\n }, [authConfig.logout]),\n );\n const { commit: commitCompleteMfa, isInFlight: isCompleteMfaInFlight } =\n useDeferredMutation<CompleteMfaVariables, CompleteMfaResponse>(\n useCallback(async () => {\n return loadOptionalMutation(\n authConfig.login.get()?.completeMfaMutation,\n authConfig.completeMfa,\n (config) => {\n return config.completeMfaMutation;\n },\n );\n }, [authConfig.completeMfa, authConfig.login]),\n );\n const {\n commit: commitBeginPasskeyLogin,\n isInFlight: isBeginPasskeyLoginInFlight,\n } = useDeferredMutation<\n BeginPasskeyLoginVariables,\n BeginPasskeyLoginResponse\n >(\n useCallback(async () => {\n return loadOptionalMutation(\n authConfig.login.get()?.beginPasskeyLoginMutation,\n authConfig.passkeyLogin,\n (config) => {\n return config.beginPasskeyLoginMutation;\n },\n );\n }, [authConfig.login, authConfig.passkeyLogin]),\n );\n const {\n commit: commitFinishPasskeyLogin,\n isInFlight: isFinishPasskeyLoginInFlight,\n } = useDeferredMutation<\n FinishPasskeyLoginVariables,\n FinishPasskeyLoginResponse\n >(\n useCallback(async () => {\n return loadOptionalMutation(\n authConfig.login.get()?.finishPasskeyLoginMutation,\n authConfig.passkeyLogin,\n (config) => {\n return config.finishPasskeyLoginMutation;\n },\n );\n }, [authConfig.login, authConfig.passkeyLogin]),\n );\n const {\n commit: commitBeginAuthentication,\n isInFlight: isBeginAuthenticationInFlight,\n } = useDeferredMutation<\n BeginAuthenticationVariables,\n BeginAuthenticationResponse\n >(\n useCallback(async () => {\n return loadOptionalMutation(\n authConfig.login.get()?.beginAuthenticationMutation,\n authConfig.authentication,\n (config) => {\n return config.beginAuthenticationMutation;\n },\n );\n }, [authConfig.authentication, authConfig.login]),\n );\n const {\n commit: commitAcceptInvitation,\n isInFlight: isAcceptInvitationInFlight,\n } = useDeferredMutation<AcceptInvitationVariables, AcceptInvitationResponse>(\n useCallback(async () => {\n return loadOptionalMutation(\n authConfig.login.get()?.acceptInvitationMutation,\n authConfig.acceptInvitation,\n (config) => {\n return config.acceptInvitationMutation;\n },\n );\n }, [authConfig.acceptInvitation, authConfig.login]),\n );\n const hasAcceptInvitationMutation =\n authConfig.login.get()?.acceptInvitationMutation != null ||\n authConfig.acceptInvitation != null;\n\n const useAuthWithMutations = useMemo(() => {\n let acceptInvitation:\n | {\n commit: typeof commitAcceptInvitation;\n isInFlight: boolean;\n }\n | undefined;\n if (hasAcceptInvitationMutation) {\n acceptInvitation = {\n commit: commitAcceptInvitation,\n isInFlight: isAcceptInvitationInFlight,\n };\n }\n return createUseAuth({\n login: { commit: commitLogin, isInFlight: isLoginInFlight },\n logout: { commit: commitLogout, isInFlight: isLogoutInFlight },\n completeMfa: {\n commit: commitCompleteMfa,\n isInFlight: isCompleteMfaInFlight,\n },\n beginPasskeyLogin: {\n commit: commitBeginPasskeyLogin,\n isInFlight: isBeginPasskeyLoginInFlight,\n },\n finishPasskeyLogin: {\n commit: commitFinishPasskeyLogin,\n isInFlight: isFinishPasskeyLoginInFlight,\n },\n beginAuthentication: {\n commit: commitBeginAuthentication,\n isInFlight: isBeginAuthenticationInFlight,\n },\n acceptInvitation,\n });\n }, [\n commitAcceptInvitation,\n commitBeginAuthentication,\n commitBeginPasskeyLogin,\n commitCompleteMfa,\n commitFinishPasskeyLogin,\n commitLogin,\n commitLogout,\n hasAcceptInvitationMutation,\n isAcceptInvitationInFlight,\n isBeginAuthenticationInFlight,\n isBeginPasskeyLoginInFlight,\n isCompleteMfaInFlight,\n isFinishPasskeyLoginInFlight,\n isLoginInFlight,\n isLogoutInFlight,\n ]);\n\n return useAuthWithMutations();\n}\n"],"mappings":";;;;;;AA0BA,IAAM,EAAE,gBAAA,MAAmB,GAWrB,KAAuB,MACvB,aAAiB,QACZ,IAEF,gBAAI,MAAM,+BAA+B,GAG5C,KACJ,MACG;CACH,IAAM,IAAmB,EAAoB,GACvC,CAAC,GAAe,KAAoB,EAAS,CAAC;CAyCpD,OAAO;EACL,QAxCa,GACZ,MAAwD;GACvD,GAAkB,MACT,IAAQ,CAChB;GAED,IAAM,UAAe;IACnB,GAAkB,MACT,KAAK,IAAI,GAAG,IAAQ,CAAC,CAC7B;GACH;GAEA,EAAa,EACV,MAAM,MAAa;IAClB,IAAI,KAAY,MACd,MAAU,MAAM,+BAA+B;IAGjD,EAAe,GAAkB;KAC/B;KACA,WAAW,EAAO;KAClB,cAAc,GAAU,MAAW;MAEjC,AADA,EAAO,GACP,EAAO,cAAc,GAAuB,KAAU,IAAI;KAC5D;KACA,UAAU,MAAU;MAElB,AADA,EAAO,GACP,EAAO,UAAU,CAAK;KACxB;IACF,CAAC;GACH,CAAC,EACA,OAAO,MAAmB;IAEzB,AADA,EAAO,GACP,EAAO,UAAU,EAAoB,CAAK,CAAC;GAC7C,CAAC;EACL,GACA,CAAC,GAAc,CAAgB,CAI/B;EACA,YAAY,IAAgB;CAC9B;AACF,GAEM,IAAuB,OAC3B,GACA,GACA,MAEI,MAGA,KAAc,OACT,OAGF,EAAe,MADK,EAAW,KAAK,CACT;AAMpC,SAAgB,IAAmC;CACjD,IAAM,EAAE,MAAM,MAAe,EAAoB,GAC3C,EAAE,QAAQ,GAAa,YAAY,MACvC,EACE,EAAY,YAEH,EADa,EAAW,MAAM,IAEnC,GAAa,eACb,EAAW,QACV,MACQ,EAAO,aAElB,GACC,CAAC,EAAW,KAAK,CAAC,CACvB,GACI,EAAE,QAAQ,GAAc,YAAY,MACxC,EACE,EAAY,aAEH,MADoB,EAAW,OAAO,KAAK,GAC9B,gBACnB,CAAC,EAAW,MAAM,CAAC,CACxB,GACI,EAAE,QAAQ,GAAmB,YAAY,MAC7C,EACE,EAAY,YACH,EACL,EAAW,MAAM,IAAI,GAAG,qBACxB,EAAW,cACV,MACQ,EAAO,mBAElB,GACC,CAAC,EAAW,aAAa,EAAW,KAAK,CAAC,CAC/C,GACI,EACJ,QAAQ,GACR,YAAY,MACV,EAIF,EAAY,YACH,EACL,EAAW,MAAM,IAAI,GAAG,2BACxB,EAAW,eACV,MACQ,EAAO,yBAElB,GACC,CAAC,EAAW,OAAO,EAAW,YAAY,CAAC,CAChD,GACM,EACJ,QAAQ,GACR,YAAY,MACV,EAIF,EAAY,YACH,EACL,EAAW,MAAM,IAAI,GAAG,4BACxB,EAAW,eACV,MACQ,EAAO,0BAElB,GACC,CAAC,EAAW,OAAO,EAAW,YAAY,CAAC,CAChD,GACM,EACJ,QAAQ,GACR,YAAY,MACV,EAIF,EAAY,YACH,EACL,EAAW,MAAM,IAAI,GAAG,6BACxB,EAAW,iBACV,MACQ,EAAO,2BAElB,GACC,CAAC,EAAW,gBAAgB,EAAW,KAAK,CAAC,CAClD,GACM,EACJ,QAAQ,GACR,YAAY,MACV,EACF,EAAY,YACH,EACL,EAAW,MAAM,IAAI,GAAG,0BACxB,EAAW,mBACV,MACQ,EAAO,wBAElB,GACC,CAAC,EAAW,kBAAkB,EAAW,KAAK,CAAC,CACpD,GACM,IACJ,EAAW,MAAM,IAAI,GAAG,4BAA4B,QACpD,EAAW,oBAAoB;CAsDjC,OApD6B,QAAc;EACzC,IAAI;EAYJ,OANI,MACF,IAAmB;GACjB,QAAQ;GACR,YAAY;EACd,IAEK,EAAc;GACnB,OAAO;IAAE,QAAQ;IAAa,YAAY;GAAgB;GAC1D,QAAQ;IAAE,QAAQ;IAAc,YAAY;GAAiB;GAC7D,aAAa;IACX,QAAQ;IACR,YAAY;GACd;GACA,mBAAmB;IACjB,QAAQ;IACR,YAAY;GACd;GACA,oBAAoB;IAClB,QAAQ;IACR,YAAY;GACd;GACA,qBAAqB;IACnB,QAAQ;IACR,YAAY;GACd;GACA;EACF,CAAC;CACH,GAAG;EACD;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAEO,EAAqB;AAC9B"}