@open-mercato/core 0.6.6-develop.6529.1.e1de4b3f27 → 0.6.6-develop.6531.1.87e9d31db6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +1 -1
- package/dist/modules/dictionaries/fields/dictionary.js +56 -41
- package/dist/modules/dictionaries/fields/dictionary.js.map +2 -2
- package/dist/modules/entities/backend/entities/system/[entityId]/page.meta.js +1 -0
- package/dist/modules/entities/backend/entities/system/[entityId]/page.meta.js.map +2 -2
- package/dist/modules/entities/backend/entities/user/[entityId]/page.js +49 -49
- package/dist/modules/entities/backend/entities/user/[entityId]/page.js.map +2 -2
- package/dist/modules/entities/backend/entities/user/[entityId]/page.meta.js +1 -0
- package/dist/modules/entities/backend/entities/user/[entityId]/page.meta.js.map +2 -2
- package/dist/modules/sales/components/documents/AddressesSection.js +6 -2
- package/dist/modules/sales/components/documents/AddressesSection.js.map +2 -2
- package/dist/modules/sales/components/documents/SalesDocumentForm.js +44 -0
- package/dist/modules/sales/components/documents/SalesDocumentForm.js.map +2 -2
- package/dist/modules/sales/components/documents/ShipmentDialog.js +59 -38
- package/dist/modules/sales/components/documents/ShipmentDialog.js.map +2 -2
- package/package.json +7 -7
- package/src/modules/dictionaries/fields/dictionary.tsx +55 -32
- package/src/modules/dictionaries/i18n/de.json +2 -0
- package/src/modules/dictionaries/i18n/en.json +2 -0
- package/src/modules/dictionaries/i18n/es.json +2 -0
- package/src/modules/dictionaries/i18n/pl.json +2 -0
- package/src/modules/entities/backend/entities/system/[entityId]/page.meta.ts +1 -0
- package/src/modules/entities/backend/entities/user/[entityId]/page.meta.ts +1 -0
- package/src/modules/entities/backend/entities/user/[entityId]/page.tsx +51 -49
- package/src/modules/entities/i18n/de.json +34 -0
- package/src/modules/entities/i18n/en.json +34 -0
- package/src/modules/entities/i18n/es.json +34 -0
- package/src/modules/entities/i18n/pl.json +34 -0
- package/src/modules/sales/components/documents/AddressesSection.tsx +6 -2
- package/src/modules/sales/components/documents/SalesDocumentForm.tsx +46 -0
- package/src/modules/sales/components/documents/ShipmentDialog.tsx +65 -40
package/.turbo/turbo-build.log
CHANGED
|
@@ -49,9 +49,12 @@ function DictionaryFieldDefEditor({ def, onChange }) {
|
|
|
49
49
|
const [error, setError] = React.useState(null);
|
|
50
50
|
const multiId = React.useId();
|
|
51
51
|
const inlineCreateId = React.useId();
|
|
52
|
+
const inlineCreateHintId = React.useId();
|
|
53
|
+
const defaultValueHintId = React.useId();
|
|
52
54
|
const selectedId = typeof def?.configJson?.dictionaryId === "string" ? def?.configJson?.dictionaryId : "";
|
|
53
55
|
const inlineCreate = def?.configJson?.dictionaryInlineCreate !== false;
|
|
54
56
|
const isMulti = def?.configJson?.multi === true;
|
|
57
|
+
const inlineCreateDisabled = !selectedId || isMulti;
|
|
55
58
|
const errorLoadLabel = t("dictionaries.customFields.errorLoad", "Failed to load dictionaries.");
|
|
56
59
|
React.useEffect(() => {
|
|
57
60
|
let cancelled = false;
|
|
@@ -120,47 +123,56 @@ function DictionaryFieldDefEditor({ def, onChange }) {
|
|
|
120
123
|
/* @__PURE__ */ jsx("span", { children: t("dictionaries.customFields.selectedHint", "Entries from this dictionary populate the field.") }),
|
|
121
124
|
/* @__PURE__ */ jsx("a", { href: manageHref, className: "font-medium text-primary hover:underline", target: "_blank", rel: "noreferrer", children: t("dictionaries.customFields.manageLink", "Manage dictionaries") })
|
|
122
125
|
] }) : null,
|
|
123
|
-
/* @__PURE__ */ jsxs("div", { className: "
|
|
124
|
-
/* @__PURE__ */
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
126
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
127
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 sm:flex-row sm:flex-wrap sm:items-center sm:gap-x-4", children: [
|
|
128
|
+
/* @__PURE__ */ jsxs("div", { className: "inline-flex items-center gap-2 text-xs", children: [
|
|
129
|
+
/* @__PURE__ */ jsx(
|
|
130
|
+
Checkbox,
|
|
131
|
+
{
|
|
132
|
+
id: multiId,
|
|
133
|
+
checked: isMulti,
|
|
134
|
+
onCheckedChange: (checked) => {
|
|
135
|
+
const enabled = checked === true;
|
|
136
|
+
onChange({ multi: enabled, defaultValue: enabled ? void 0 : def?.configJson?.defaultValue });
|
|
137
|
+
},
|
|
138
|
+
disabled: !selectedId
|
|
139
|
+
}
|
|
140
|
+
),
|
|
141
|
+
/* @__PURE__ */ jsx(
|
|
142
|
+
"label",
|
|
143
|
+
{
|
|
144
|
+
htmlFor: multiId,
|
|
145
|
+
className: selectedId ? "cursor-pointer select-none" : "cursor-not-allowed opacity-60",
|
|
146
|
+
children: t("dictionaries.customFields.allowMultiple", "Allow selecting multiple entries")
|
|
147
|
+
}
|
|
148
|
+
)
|
|
149
|
+
] }),
|
|
150
|
+
/* @__PURE__ */ jsxs("div", { className: "inline-flex items-center gap-2 text-xs", children: [
|
|
151
|
+
/* @__PURE__ */ jsx(
|
|
152
|
+
Checkbox,
|
|
153
|
+
{
|
|
154
|
+
id: inlineCreateId,
|
|
155
|
+
checked: !isMulti && inlineCreate,
|
|
156
|
+
onCheckedChange: (checked) => onChange({ dictionaryInlineCreate: checked === true }),
|
|
157
|
+
disabled: inlineCreateDisabled,
|
|
158
|
+
"aria-describedby": isMulti ? inlineCreateHintId : void 0
|
|
159
|
+
}
|
|
160
|
+
),
|
|
161
|
+
/* @__PURE__ */ jsx(
|
|
162
|
+
"label",
|
|
163
|
+
{
|
|
164
|
+
htmlFor: inlineCreateId,
|
|
165
|
+
className: !inlineCreateDisabled ? "cursor-pointer select-none" : "cursor-not-allowed opacity-60",
|
|
166
|
+
children: t("dictionaries.customFields.allowInlineCreate", "Allow inline creation inside forms")
|
|
167
|
+
}
|
|
168
|
+
)
|
|
169
|
+
] })
|
|
170
|
+
] }),
|
|
171
|
+
isMulti ? /* @__PURE__ */ jsx("p", { id: inlineCreateHintId, className: "text-xs text-muted-foreground", children: t(
|
|
172
|
+
"dictionaries.customFields.inlineCreateSingleOnly",
|
|
173
|
+
"Inline creation is available for single-entry dictionary fields only."
|
|
174
|
+
) }) : null
|
|
144
175
|
] }),
|
|
145
|
-
!isMulti ? /* @__PURE__ */ jsxs("div", { className: "inline-flex items-center gap-2 text-xs", children: [
|
|
146
|
-
/* @__PURE__ */ jsx(
|
|
147
|
-
Checkbox,
|
|
148
|
-
{
|
|
149
|
-
id: inlineCreateId,
|
|
150
|
-
checked: inlineCreate,
|
|
151
|
-
onCheckedChange: (checked) => onChange({ dictionaryInlineCreate: checked === true }),
|
|
152
|
-
disabled: !selectedId
|
|
153
|
-
}
|
|
154
|
-
),
|
|
155
|
-
/* @__PURE__ */ jsx(
|
|
156
|
-
"label",
|
|
157
|
-
{
|
|
158
|
-
htmlFor: inlineCreateId,
|
|
159
|
-
className: selectedId ? "cursor-pointer select-none" : "cursor-not-allowed opacity-60",
|
|
160
|
-
children: t("dictionaries.customFields.allowInlineCreate", "Allow inline creation inside forms")
|
|
161
|
-
}
|
|
162
|
-
)
|
|
163
|
-
] }) : null,
|
|
164
176
|
selectedId && !isMulti ? /* @__PURE__ */ jsx(
|
|
165
177
|
DictionaryDefaultSelector,
|
|
166
178
|
{
|
|
@@ -168,7 +180,10 @@ function DictionaryFieldDefEditor({ def, onChange }) {
|
|
|
168
180
|
defaultValue: typeof def?.configJson?.defaultValue === "string" ? def.configJson.defaultValue : "",
|
|
169
181
|
onChange: (value) => onChange({ defaultValue: value || void 0 })
|
|
170
182
|
}
|
|
171
|
-
) :
|
|
183
|
+
) : selectedId && isMulti ? /* @__PURE__ */ jsx("div", { className: "inline-flex items-center gap-2 text-xs", children: /* @__PURE__ */ jsx("p", { id: defaultValueHintId, className: "text-xs text-muted-foreground", children: t(
|
|
184
|
+
"dictionaries.customFields.defaultValueMultiUnavailable",
|
|
185
|
+
"Default values are not available for multi-select dictionary fields."
|
|
186
|
+
) }) }) : null
|
|
172
187
|
] });
|
|
173
188
|
}
|
|
174
189
|
function DictionaryFieldInput({ value, setValue, disabled, def }) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/dictionaries/fields/dictionary.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport type { CrudCustomFieldRenderProps } from '@open-mercato/ui/backend/CrudForm'\nimport { FieldRegistry } from '@open-mercato/ui/backend/fields/registry'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { Checkbox } from '@open-mercato/ui/primitives/checkbox'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@open-mercato/ui/primitives/select'\nimport { DictionarySelectControl } from '../components/DictionarySelectControl'\nimport { useDictionaryEntries } from '../components/hooks/useDictionaryEntries'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('dictionaries').child({ component: 'dictionary-field' })\n\ntype DictionaryFieldDefinition = {\n dictionaryId?: string\n dictionaryInlineCreate?: boolean\n multi?: boolean\n defaultValue?: string\n}\n\ntype Props = CrudCustomFieldRenderProps & { def?: DictionaryFieldDefinition }\n\ntype DictionarySummary = {\n id: string\n name: string\n key: string\n isActive: boolean\n}\n\nfunction DictionaryDefaultSelector({\n dictionaryId,\n defaultValue,\n onChange,\n}: {\n dictionaryId: string\n defaultValue: string\n onChange: (value: string) => void\n}) {\n const t = useT()\n const { data, isLoading } = useDictionaryEntries(dictionaryId)\n const entries = data?.entries ?? []\n const isStale = defaultValue && entries.length > 0 && !entries.some((e) => e.value === defaultValue)\n\n return (\n <div className=\"space-y-1\">\n <label className=\"text-xs font-medium text-muted-foreground\">\n {t('dictionaries.customFields.defaultValue', 'Default value')}\n </label>\n <Select\n value={defaultValue ?? ''}\n onValueChange={(next) => onChange(next ?? '')}\n >\n <SelectTrigger size=\"sm\">\n <SelectValue placeholder={t('dictionaries.customFields.defaultValueNone', 'No default')} />\n </SelectTrigger>\n <SelectContent>\n {entries.map((entry) => (\n <SelectItem key={entry.value} value={entry.value}>\n {entry.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n {isLoading ? (\n <p className=\"text-xs text-muted-foreground\">\n {t('dictionaries.customFields.loading', 'Loading dictionaries\u2026')}\n </p>\n ) : null}\n {isStale ? (\n <p className=\"text-xs text-status-warning-text\">\n {t('dictionaries.customFields.defaultValueStale', 'Default entry not found \u2014 it may have been deleted or renamed.')}\n </p>\n ) : null}\n </div>\n )\n}\n\nfunction DictionaryFieldDefEditor({ def, onChange }: { def: { configJson?: DictionaryFieldDefinition } | undefined; onChange: (patch: Partial<DictionaryFieldDefinition>) => void }) {\n const t = useT()\n const [items, setItems] = React.useState<DictionarySummary[]>([])\n const [loading, setLoading] = React.useState(false)\n const [error, setError] = React.useState<string | null>(null)\n const multiId = React.useId()\n const inlineCreateId = React.useId()\n const selectedId = typeof def?.configJson?.dictionaryId === 'string' ? def?.configJson?.dictionaryId : ''\n const inlineCreate = def?.configJson?.dictionaryInlineCreate !== false\n const isMulti = def?.configJson?.multi === true\n const errorLoadLabel = t('dictionaries.customFields.errorLoad', 'Failed to load dictionaries.')\n\n React.useEffect(() => {\n let cancelled = false\n async function load() {\n setLoading(true)\n setError(null)\n try {\n const call = await apiCall<{ items?: unknown[]; error?: string }>(\n '/api/dictionaries?includeInactive=true',\n )\n if (!call.ok) {\n const message =\n typeof call.result?.error === 'string' ? call.result.error : 'Failed to load dictionaries'\n throw new Error(message)\n }\n const entries = Array.isArray(call.result?.items) ? call.result!.items : []\n if (!cancelled) {\n setItems(\n entries.map((entry: any) => ({\n id: String(entry.id),\n name: typeof entry.name === 'string' && entry.name.trim().length ? entry.name : String(entry.key ?? entry.id),\n key: typeof entry.key === 'string' ? entry.key : '',\n isActive: entry.isActive !== false,\n })),\n )\n }\n } catch (err) {\n if (!cancelled) {\n logger.error('Failed to load dictionaries list', { err })\n setError(errorLoadLabel)\n }\n } finally {\n if (!cancelled) {\n setLoading(false)\n }\n }\n }\n load().catch(() => {})\n return () => {\n cancelled = true\n }\n }, [errorLoadLabel])\n\n const manageHref = '/backend/config/dictionaries'\n\n return (\n <div className=\"mt-3 space-y-3 rounded border border-dashed border-muted-foreground/40 bg-muted/30 p-3\">\n <div className=\"space-y-1\">\n <label className=\"text-xs font-medium text-muted-foreground\">\n {t('dictionaries.customFields.dictionaryLabel', 'Dictionary source')}\n </label>\n <Select\n value={selectedId ?? ''}\n onValueChange={(next) => onChange({ dictionaryId: next || undefined })}\n >\n <SelectTrigger size=\"sm\">\n <SelectValue placeholder={t('dictionaries.customFields.dictionaryPlaceholder', 'Select a dictionary')} />\n </SelectTrigger>\n <SelectContent>\n {items.map((item) => (\n <SelectItem key={item.id} value={item.id}>\n {item.name}\n {item.isActive ? '' : ` (${t('dictionaries.customFields.inactive', 'inactive')})`}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n {loading ? (\n <p className=\"text-xs text-muted-foreground\">\n {t('dictionaries.customFields.loading', 'Loading dictionaries\u2026')}\n </p>\n ) : null}\n {error ? <p className=\"text-xs text-status-error-text\">{error}</p> : null}\n {!loading && !error && items.length === 0 ? (\n <p className=\"text-xs text-muted-foreground\">\n {t('dictionaries.customFields.empty', 'No dictionaries available yet. Create one first.')}\n </p>\n ) : null}\n </div>\n {selectedId ? (\n <div className=\"flex flex-wrap items-center justify-between gap-2 rounded bg-background/80 px-2 py-1 text-xs text-muted-foreground\">\n <span>{t('dictionaries.customFields.selectedHint', 'Entries from this dictionary populate the field.')}</span>\n <a href={manageHref} className=\"font-medium text-primary hover:underline\" target=\"_blank\" rel=\"noreferrer\">\n {t('dictionaries.customFields.manageLink', 'Manage dictionaries')}\n </a>\n </div>\n ) : null}\n <div className=\"inline-flex items-center gap-2 text-xs\">\n <Checkbox\n id={multiId}\n checked={isMulti}\n onCheckedChange={(checked) => {\n const enabled = checked === true\n onChange({ multi: enabled, defaultValue: enabled ? undefined : def?.configJson?.defaultValue })\n }}\n disabled={!selectedId}\n />\n <label\n htmlFor={multiId}\n className={selectedId ? 'cursor-pointer select-none' : 'cursor-not-allowed opacity-60'}\n >\n {t('dictionaries.customFields.allowMultiple', 'Allow selecting multiple entries')}\n </label>\n </div>\n {!isMulti ? (\n <div className=\"inline-flex items-center gap-2 text-xs\">\n <Checkbox\n id={inlineCreateId}\n checked={inlineCreate}\n onCheckedChange={(checked) => onChange({ dictionaryInlineCreate: checked === true })}\n disabled={!selectedId}\n />\n <label\n htmlFor={inlineCreateId}\n className={selectedId ? 'cursor-pointer select-none' : 'cursor-not-allowed opacity-60'}\n >\n {t('dictionaries.customFields.allowInlineCreate', 'Allow inline creation inside forms')}\n </label>\n </div>\n ) : null}\n {selectedId && !isMulti ? (\n <DictionaryDefaultSelector\n dictionaryId={selectedId}\n defaultValue={typeof def?.configJson?.defaultValue === 'string' ? def.configJson.defaultValue : ''}\n onChange={(value) => onChange({ defaultValue: value || undefined })}\n />\n ) : null}\n </div>\n )\n}\n\nfunction DictionaryFieldInput({ value, setValue, disabled, def }: Props) {\n const t = useT()\n const dictionaryId = def?.dictionaryId\n if (!dictionaryId) {\n return (\n <div className=\"rounded border border-dashed p-3 text-sm text-muted-foreground\">\n {t('dictionaries.config.entries.error.load', 'Failed to load dictionary entries.')}\n </div>\n )\n }\n const normalizedValue = typeof value === 'string' ? value : Array.isArray(value) ? String(value[0] ?? '') : undefined\n return (\n <DictionarySelectControl\n dictionaryId={dictionaryId}\n value={normalizedValue ?? ''}\n onChange={(next) => setValue(next ?? undefined)}\n allowInlineCreate={def?.dictionaryInlineCreate !== false}\n disabled={disabled}\n />\n )\n}\n\nFieldRegistry.register('dictionary', {\n input: DictionaryFieldInput,\n defEditor: (props) => <DictionaryFieldDefEditor {...props} />,\n})\n"],
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport type { CrudCustomFieldRenderProps } from '@open-mercato/ui/backend/CrudForm'\nimport { FieldRegistry } from '@open-mercato/ui/backend/fields/registry'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { Checkbox } from '@open-mercato/ui/primitives/checkbox'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@open-mercato/ui/primitives/select'\nimport { DictionarySelectControl } from '../components/DictionarySelectControl'\nimport { useDictionaryEntries } from '../components/hooks/useDictionaryEntries'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('dictionaries').child({ component: 'dictionary-field' })\n\ntype DictionaryFieldDefinition = {\n dictionaryId?: string\n dictionaryInlineCreate?: boolean\n multi?: boolean\n defaultValue?: string\n}\n\ntype Props = CrudCustomFieldRenderProps & { def?: DictionaryFieldDefinition }\n\ntype DictionarySummary = {\n id: string\n name: string\n key: string\n isActive: boolean\n}\n\nfunction DictionaryDefaultSelector({\n dictionaryId,\n defaultValue,\n onChange,\n}: {\n dictionaryId: string\n defaultValue: string\n onChange: (value: string) => void\n}) {\n const t = useT()\n const { data, isLoading } = useDictionaryEntries(dictionaryId)\n const entries = data?.entries ?? []\n const isStale = defaultValue && entries.length > 0 && !entries.some((e) => e.value === defaultValue)\n\n return (\n <div className=\"space-y-1\">\n <label className=\"text-xs font-medium text-muted-foreground\">\n {t('dictionaries.customFields.defaultValue', 'Default value')}\n </label>\n <Select\n value={defaultValue ?? ''}\n onValueChange={(next) => onChange(next ?? '')}\n >\n <SelectTrigger size=\"sm\">\n <SelectValue placeholder={t('dictionaries.customFields.defaultValueNone', 'No default')} />\n </SelectTrigger>\n <SelectContent>\n {entries.map((entry) => (\n <SelectItem key={entry.value} value={entry.value}>\n {entry.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n {isLoading ? (\n <p className=\"text-xs text-muted-foreground\">\n {t('dictionaries.customFields.loading', 'Loading dictionaries\u2026')}\n </p>\n ) : null}\n {isStale ? (\n <p className=\"text-xs text-status-warning-text\">\n {t('dictionaries.customFields.defaultValueStale', 'Default entry not found \u2014 it may have been deleted or renamed.')}\n </p>\n ) : null}\n </div>\n )\n}\n\nfunction DictionaryFieldDefEditor({ def, onChange }: { def: { configJson?: DictionaryFieldDefinition } | undefined; onChange: (patch: Partial<DictionaryFieldDefinition>) => void }) {\n const t = useT()\n const [items, setItems] = React.useState<DictionarySummary[]>([])\n const [loading, setLoading] = React.useState(false)\n const [error, setError] = React.useState<string | null>(null)\n const multiId = React.useId()\n const inlineCreateId = React.useId()\n const inlineCreateHintId = React.useId()\n const defaultValueHintId = React.useId()\n const selectedId = typeof def?.configJson?.dictionaryId === 'string' ? def?.configJson?.dictionaryId : ''\n const inlineCreate = def?.configJson?.dictionaryInlineCreate !== false\n const isMulti = def?.configJson?.multi === true\n const inlineCreateDisabled = !selectedId || isMulti\n const errorLoadLabel = t('dictionaries.customFields.errorLoad', 'Failed to load dictionaries.')\n\n React.useEffect(() => {\n let cancelled = false\n async function load() {\n setLoading(true)\n setError(null)\n try {\n const call = await apiCall<{ items?: unknown[]; error?: string }>(\n '/api/dictionaries?includeInactive=true',\n )\n if (!call.ok) {\n const message =\n typeof call.result?.error === 'string' ? call.result.error : 'Failed to load dictionaries'\n throw new Error(message)\n }\n const entries = Array.isArray(call.result?.items) ? call.result!.items : []\n if (!cancelled) {\n setItems(\n entries.map((entry: any) => ({\n id: String(entry.id),\n name: typeof entry.name === 'string' && entry.name.trim().length ? entry.name : String(entry.key ?? entry.id),\n key: typeof entry.key === 'string' ? entry.key : '',\n isActive: entry.isActive !== false,\n })),\n )\n }\n } catch (err) {\n if (!cancelled) {\n logger.error('Failed to load dictionaries list', { err })\n setError(errorLoadLabel)\n }\n } finally {\n if (!cancelled) {\n setLoading(false)\n }\n }\n }\n load().catch(() => {})\n return () => {\n cancelled = true\n }\n }, [errorLoadLabel])\n\n const manageHref = '/backend/config/dictionaries'\n\n return (\n <div className=\"mt-3 space-y-3 rounded border border-dashed border-muted-foreground/40 bg-muted/30 p-3\">\n <div className=\"space-y-1\">\n <label className=\"text-xs font-medium text-muted-foreground\">\n {t('dictionaries.customFields.dictionaryLabel', 'Dictionary source')}\n </label>\n <Select\n value={selectedId ?? ''}\n onValueChange={(next) => onChange({ dictionaryId: next || undefined })}\n >\n <SelectTrigger size=\"sm\">\n <SelectValue placeholder={t('dictionaries.customFields.dictionaryPlaceholder', 'Select a dictionary')} />\n </SelectTrigger>\n <SelectContent>\n {items.map((item) => (\n <SelectItem key={item.id} value={item.id}>\n {item.name}\n {item.isActive ? '' : ` (${t('dictionaries.customFields.inactive', 'inactive')})`}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n {loading ? (\n <p className=\"text-xs text-muted-foreground\">\n {t('dictionaries.customFields.loading', 'Loading dictionaries\u2026')}\n </p>\n ) : null}\n {error ? <p className=\"text-xs text-status-error-text\">{error}</p> : null}\n {!loading && !error && items.length === 0 ? (\n <p className=\"text-xs text-muted-foreground\">\n {t('dictionaries.customFields.empty', 'No dictionaries available yet. Create one first.')}\n </p>\n ) : null}\n </div>\n {selectedId ? (\n <div className=\"flex flex-wrap items-center justify-between gap-2 rounded bg-background/80 px-2 py-1 text-xs text-muted-foreground\">\n <span>{t('dictionaries.customFields.selectedHint', 'Entries from this dictionary populate the field.')}</span>\n <a href={manageHref} className=\"font-medium text-primary hover:underline\" target=\"_blank\" rel=\"noreferrer\">\n {t('dictionaries.customFields.manageLink', 'Manage dictionaries')}\n </a>\n </div>\n ) : null}\n <div className=\"space-y-2\">\n <div className=\"flex flex-col gap-2 sm:flex-row sm:flex-wrap sm:items-center sm:gap-x-4\">\n <div className=\"inline-flex items-center gap-2 text-xs\">\n <Checkbox\n id={multiId}\n checked={isMulti}\n onCheckedChange={(checked) => {\n const enabled = checked === true\n onChange({ multi: enabled, defaultValue: enabled ? undefined : def?.configJson?.defaultValue })\n }}\n disabled={!selectedId}\n />\n <label\n htmlFor={multiId}\n className={selectedId ? 'cursor-pointer select-none' : 'cursor-not-allowed opacity-60'}\n >\n {t('dictionaries.customFields.allowMultiple', 'Allow selecting multiple entries')}\n </label>\n </div>\n <div className=\"inline-flex items-center gap-2 text-xs\">\n <Checkbox\n id={inlineCreateId}\n checked={!isMulti && inlineCreate}\n onCheckedChange={(checked) => onChange({ dictionaryInlineCreate: checked === true })}\n disabled={inlineCreateDisabled}\n aria-describedby={isMulti ? inlineCreateHintId : undefined}\n />\n <label\n htmlFor={inlineCreateId}\n className={!inlineCreateDisabled ? 'cursor-pointer select-none' : 'cursor-not-allowed opacity-60'}\n >\n {t('dictionaries.customFields.allowInlineCreate', 'Allow inline creation inside forms')}\n </label>\n </div>\n </div>\n {isMulti ? (\n <p id={inlineCreateHintId} className=\"text-xs text-muted-foreground\">\n {t(\n 'dictionaries.customFields.inlineCreateSingleOnly',\n 'Inline creation is available for single-entry dictionary fields only.',\n )}\n </p>\n ) : null}\n </div>\n {selectedId && !isMulti ? (\n <DictionaryDefaultSelector\n dictionaryId={selectedId}\n defaultValue={typeof def?.configJson?.defaultValue === 'string' ? def.configJson.defaultValue : ''}\n onChange={(value) => onChange({ defaultValue: value || undefined })}\n />\n ) : selectedId && isMulti ? (\n <div className=\"inline-flex items-center gap-2 text-xs\">\n <p id={defaultValueHintId} className=\"text-xs text-muted-foreground\">\n {t(\n 'dictionaries.customFields.defaultValueMultiUnavailable',\n 'Default values are not available for multi-select dictionary fields.',\n )}\n </p>\n </div>\n ) : null}\n </div>\n )\n}\n\nfunction DictionaryFieldInput({ value, setValue, disabled, def }: Props) {\n const t = useT()\n const dictionaryId = def?.dictionaryId\n if (!dictionaryId) {\n return (\n <div className=\"rounded border border-dashed p-3 text-sm text-muted-foreground\">\n {t('dictionaries.config.entries.error.load', 'Failed to load dictionary entries.')}\n </div>\n )\n }\n const normalizedValue = typeof value === 'string' ? value : Array.isArray(value) ? String(value[0] ?? '') : undefined\n return (\n <DictionarySelectControl\n dictionaryId={dictionaryId}\n value={normalizedValue ?? ''}\n onChange={(next) => setValue(next ?? undefined)}\n allowInlineCreate={def?.dictionaryInlineCreate !== false}\n disabled={disabled}\n />\n )\n}\n\nFieldRegistry.register('dictionary', {\n input: DictionaryFieldInput,\n defEditor: (props) => <DictionaryFieldDefEditor {...props} />,\n})\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../../src/modules/entities/backend/entities/system/%5BentityId%5D/page.meta.ts"],
|
|
4
|
-
"sourcesContent": ["export const metadata = {\n requireAuth: true,\n requireFeatures: ['entities.definitions.manage'],\n pageTitle: 'Edit Definitions',\n pageGroup: 'Data designer',\n navHidden: true,\n}\n"],
|
|
5
|
-
"mappings": "AAAO,MAAM,WAAW;AAAA,EACtB,aAAa;AAAA,EACb,iBAAiB,CAAC,6BAA6B;AAAA,EAC/C,WAAW;AAAA,EACX,WAAW;AAAA,EACX,WAAW;AACb;",
|
|
4
|
+
"sourcesContent": ["export const metadata = {\n requireAuth: true,\n requireFeatures: ['entities.definitions.manage'],\n pageTitle: 'Edit Definitions',\n pageTitleKey: 'entities.userEntities.edit.pageTitle',\n pageGroup: 'Data designer',\n navHidden: true,\n}\n"],
|
|
5
|
+
"mappings": "AAAO,MAAM,WAAW;AAAA,EACtB,aAAa;AAAA,EACb,iBAAiB,CAAC,6BAA6B;AAAA,EAC/C,WAAW;AAAA,EACX,cAAc;AAAA,EACd,WAAW;AAAA,EACX,WAAW;AACb;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -149,7 +149,7 @@ function EditDefinitionsPage({ params }) {
|
|
|
149
149
|
const entJson = await readApiResultOrThrow(
|
|
150
150
|
"/api/entities/entities",
|
|
151
151
|
void 0,
|
|
152
|
-
{ errorMessage: "Failed to load entity metadata", fallback: { items: [] } }
|
|
152
|
+
{ errorMessage: t("entities.userEntities.edit.errors.loadMetadataFailed", "Failed to load entity metadata"), fallback: { items: [] } }
|
|
153
153
|
);
|
|
154
154
|
const ent = (entJson.items || []).find((x) => x.entityId === entityId);
|
|
155
155
|
if (mounted) {
|
|
@@ -175,7 +175,7 @@ function EditDefinitionsPage({ params }) {
|
|
|
175
175
|
const json = await readApiResultOrThrow(
|
|
176
176
|
`/api/entities/definitions.manage?entityId=${encodeURIComponent(entityId)}`,
|
|
177
177
|
void 0,
|
|
178
|
-
{ errorMessage: "Failed to load entity definitions", fallback: { items: [], deletedKeys: [] } }
|
|
178
|
+
{ errorMessage: t("entities.userEntities.edit.errors.loadDefinitionsFailed", "Failed to load entity definitions"), fallback: { items: [], deletedKeys: [] } }
|
|
179
179
|
);
|
|
180
180
|
if (mounted) {
|
|
181
181
|
const loaded = (json.items || []).map((d) => ({ key: d.key, kind: d.kind, configJson: d.configJson || {}, isActive: d.isActive !== false }));
|
|
@@ -198,7 +198,7 @@ function EditDefinitionsPage({ params }) {
|
|
|
198
198
|
setSingleFieldsetPerRecord(json.settings?.singleFieldsetPerRecord !== false);
|
|
199
199
|
}
|
|
200
200
|
} catch (e) {
|
|
201
|
-
if (mounted) setError(e.message || "Failed to load");
|
|
201
|
+
if (mounted) setError(e.message || t("entities.userEntities.edit.errors.loadFailed", "Failed to load"));
|
|
202
202
|
} finally {
|
|
203
203
|
if (mounted) setLoading(false);
|
|
204
204
|
}
|
|
@@ -207,7 +207,7 @@ function EditDefinitionsPage({ params }) {
|
|
|
207
207
|
return () => {
|
|
208
208
|
mounted = false;
|
|
209
209
|
};
|
|
210
|
-
}, [entityId]);
|
|
210
|
+
}, [entityId, t]);
|
|
211
211
|
function addField() {
|
|
212
212
|
setDefs((arr) => [
|
|
213
213
|
...arr,
|
|
@@ -227,12 +227,12 @@ function EditDefinitionsPage({ params }) {
|
|
|
227
227
|
body: JSON.stringify({ entityId, key })
|
|
228
228
|
});
|
|
229
229
|
if (!call.ok) {
|
|
230
|
-
await raiseCrudError(call.response, "Failed to restore field");
|
|
230
|
+
await raiseCrudError(call.response, t("entities.userEntities.edit.errors.restoreFieldFailed", "Failed to restore field"));
|
|
231
231
|
}
|
|
232
232
|
const j2 = await readApiResultOrThrow(
|
|
233
233
|
`/api/entities/definitions.manage?entityId=${encodeURIComponent(entityId)}`,
|
|
234
234
|
void 0,
|
|
235
|
-
{ errorMessage: "Failed to reload field definitions", fallback: { items: [], deletedKeys: [] } }
|
|
235
|
+
{ errorMessage: t("entities.userEntities.edit.errors.reloadDefinitionsFailed", "Failed to reload field definitions"), fallback: { items: [], deletedKeys: [] } }
|
|
236
236
|
);
|
|
237
237
|
const loaded = (j2.items || []).map((d) => ({ key: d.key, kind: d.kind, configJson: d.configJson || {}, isActive: d.isActive !== false }));
|
|
238
238
|
loaded.sort(
|
|
@@ -241,10 +241,10 @@ function EditDefinitionsPage({ params }) {
|
|
|
241
241
|
setDefs(loaded);
|
|
242
242
|
setDefsVersion(readVersionToken(j2.version));
|
|
243
243
|
setDeletedKeys(Array.isArray(j2.deletedKeys) ? j2.deletedKeys : []);
|
|
244
|
-
flash(
|
|
244
|
+
flash(t("entities.userEntities.edit.flash.restoredField", "Restored {{key}}", { key }), "success");
|
|
245
245
|
await invalidateCustomFieldDefs(queryClient, entityId);
|
|
246
246
|
} catch (e) {
|
|
247
|
-
flash(e?.message || "Failed to restore field", "error");
|
|
247
|
+
flash(e?.message || t("entities.userEntities.edit.errors.restoreFieldFailed", "Failed to restore field"), "error");
|
|
248
248
|
}
|
|
249
249
|
}
|
|
250
250
|
async function saveAll() {
|
|
@@ -252,8 +252,8 @@ function EditDefinitionsPage({ params }) {
|
|
|
252
252
|
setError(null);
|
|
253
253
|
try {
|
|
254
254
|
if (!validateAll()) {
|
|
255
|
-
flash("Please fix validation errors in field definitions", "error");
|
|
256
|
-
throw new Error("Validation failed");
|
|
255
|
+
flash(t("entities.customFields.errors.validation", "Please fix validation errors in field definitions."), "error");
|
|
256
|
+
throw new Error(t("entities.userEntities.edit.errors.validationFailed", "Validation failed"));
|
|
257
257
|
}
|
|
258
258
|
const payload = {
|
|
259
259
|
entityId,
|
|
@@ -274,13 +274,13 @@ function EditDefinitionsPage({ params }) {
|
|
|
274
274
|
);
|
|
275
275
|
if (!call.ok) {
|
|
276
276
|
if (surfaceRecordConflict({ status: call.status, body: call.result }, t)) return;
|
|
277
|
-
await raiseCrudError(call.response, "Failed to save definitions");
|
|
277
|
+
await raiseCrudError(call.response, t("entities.customFields.errors.saveFailed", "Failed to save field definitions."));
|
|
278
278
|
}
|
|
279
279
|
setDefsVersion(readVersionToken(call.result?.version));
|
|
280
280
|
await invalidateCustomFieldDefs(queryClient, entityId);
|
|
281
|
-
router.push(`/backend/entities/user?flash
|
|
281
|
+
router.push(`/backend/entities/user?flash=${encodeURIComponent(t("entities.customFields.flash.saved", "Definitions saved"))}&type=success`);
|
|
282
282
|
} catch (e) {
|
|
283
|
-
setError(e.message || "Failed to save");
|
|
283
|
+
setError(e.message || t("entities.customFields.errors.saveFailed", "Failed to save field definitions."));
|
|
284
284
|
} finally {
|
|
285
285
|
setSaving(false);
|
|
286
286
|
}
|
|
@@ -296,11 +296,11 @@ function EditDefinitionsPage({ params }) {
|
|
|
296
296
|
body: JSON.stringify({ entityId, key: def.key })
|
|
297
297
|
});
|
|
298
298
|
if (!call.ok) {
|
|
299
|
-
await raiseCrudError(call.response, "Failed to delete field");
|
|
299
|
+
await raiseCrudError(call.response, t("entities.customFields.errors.deleteFailed", "Failed to delete field."));
|
|
300
300
|
}
|
|
301
301
|
setDefsVersion(readVersionToken(call.result?.version));
|
|
302
302
|
} catch (error2) {
|
|
303
|
-
const message = error2 instanceof Error ? error2.message : "Failed to delete field";
|
|
303
|
+
const message = error2 instanceof Error ? error2.message : t("entities.customFields.errors.deleteFailed", "Failed to delete field.");
|
|
304
304
|
flash(message, "error");
|
|
305
305
|
return;
|
|
306
306
|
}
|
|
@@ -341,7 +341,7 @@ function EditDefinitionsPage({ params }) {
|
|
|
341
341
|
if (!orderDirty) return;
|
|
342
342
|
setOrderSaving(true);
|
|
343
343
|
try {
|
|
344
|
-
if (!validateAll()) throw new Error("Validation failed");
|
|
344
|
+
if (!validateAll()) throw new Error(t("entities.userEntities.edit.errors.validationFailed", "Validation failed"));
|
|
345
345
|
const payload = {
|
|
346
346
|
entityId,
|
|
347
347
|
definitions: defs.filter((d) => !!d.key).map((d) => ({
|
|
@@ -364,14 +364,14 @@ function EditDefinitionsPage({ params }) {
|
|
|
364
364
|
setOrderDirty(false);
|
|
365
365
|
return;
|
|
366
366
|
}
|
|
367
|
-
await raiseCrudError(call.response, "Failed to save order");
|
|
367
|
+
await raiseCrudError(call.response, t("entities.userEntities.edit.errors.saveOrderFailed", "Failed to save order"));
|
|
368
368
|
}
|
|
369
369
|
setDefsVersion(readVersionToken(call.result?.version));
|
|
370
370
|
setOrderDirty(false);
|
|
371
|
-
flash("Order saved", "success");
|
|
371
|
+
flash(t("entities.userEntities.edit.flash.orderSaved", "Order saved"), "success");
|
|
372
372
|
await invalidateCustomFieldDefs(queryClient, entityId);
|
|
373
373
|
} catch (e) {
|
|
374
|
-
flash(e?.message || "Failed to save order", "error");
|
|
374
|
+
flash(e?.message || t("entities.userEntities.edit.errors.saveOrderFailed", "Failed to save order"), "error");
|
|
375
375
|
} finally {
|
|
376
376
|
setOrderSaving(false);
|
|
377
377
|
}
|
|
@@ -384,21 +384,21 @@ function EditDefinitionsPage({ params }) {
|
|
|
384
384
|
});
|
|
385
385
|
const metadataFieldsReadOnly = entitySource === "code";
|
|
386
386
|
const fields = [
|
|
387
|
-
{ id: "label", label: "Label", type: "text", required: true, readOnly: metadataFieldsReadOnly },
|
|
388
|
-
{ id: "description", label: "Description", type: "textarea", readOnly: metadataFieldsReadOnly },
|
|
387
|
+
{ id: "label", label: t("entities.userEntities.form.label.label", "Label"), type: "text", required: true, readOnly: metadataFieldsReadOnly },
|
|
388
|
+
{ id: "description", label: t("entities.userEntities.form.description.label", "Description"), type: "textarea", readOnly: metadataFieldsReadOnly },
|
|
389
389
|
{
|
|
390
390
|
id: "defaultEditor",
|
|
391
|
-
label: "Default Editor (multiline)",
|
|
391
|
+
label: t("entities.userEntities.form.defaultEditor.label", "Default Editor (multiline)"),
|
|
392
392
|
type: "select",
|
|
393
393
|
readOnly: metadataFieldsReadOnly,
|
|
394
394
|
options: [
|
|
395
|
-
{ value: "", label: "Default (Markdown)" },
|
|
396
|
-
{ value: "markdown", label: "Markdown (UIW)" },
|
|
397
|
-
{ value: "simpleMarkdown", label: "Simple Markdown" },
|
|
398
|
-
{ value: "htmlRichText", label: "HTML Rich Text" }
|
|
395
|
+
{ value: "", label: t("entities.userEntities.form.defaultEditor.options.default", "Default (Markdown)") },
|
|
396
|
+
{ value: "markdown", label: t("entities.userEntities.form.defaultEditor.options.markdown", "Markdown (UIW)") },
|
|
397
|
+
{ value: "simpleMarkdown", label: t("entities.userEntities.form.defaultEditor.options.simpleMarkdown", "Simple Markdown") },
|
|
398
|
+
{ value: "htmlRichText", label: t("entities.userEntities.form.defaultEditor.options.htmlRichText", "HTML Rich Text") }
|
|
399
399
|
]
|
|
400
400
|
},
|
|
401
|
-
...entitySource === "custom" ? [{ id: "showInSidebar", label: "Show in sidebar", type: "checkbox" }] : []
|
|
401
|
+
...entitySource === "custom" ? [{ id: "showInSidebar", label: t("entities.userEntities.form.showInSidebar.label", "Show in sidebar"), type: "checkbox" }] : []
|
|
402
402
|
];
|
|
403
403
|
const renderFieldDefinitions = React.useCallback(
|
|
404
404
|
() => /* @__PURE__ */ jsx(
|
|
@@ -441,7 +441,7 @@ function EditDefinitionsPage({ params }) {
|
|
|
441
441
|
});
|
|
442
442
|
setOrderDirty(true);
|
|
443
443
|
},
|
|
444
|
-
orderNotice: orderDirty ? { dirty: true, saving: orderSaving, message: "Reordered
|
|
444
|
+
orderNotice: orderDirty ? { dirty: true, saving: orderSaving, message: t("entities.userEntities.edit.orderNotice", "Reordered - will auto-save on blur") } : void 0,
|
|
445
445
|
addButtonLabel: t("entities.customFields.editor.addField", "Add Field"),
|
|
446
446
|
translate: t,
|
|
447
447
|
listRef,
|
|
@@ -458,31 +458,31 @@ function EditDefinitionsPage({ params }) {
|
|
|
458
458
|
}
|
|
459
459
|
}
|
|
460
460
|
),
|
|
461
|
-
[defs, defErrors, deletedKeys, fieldsets, activeFieldset, singleFieldsetPerRecord, orderDirty, orderSaving, addField, removeField, restoreField, saveOrderIfDirty]
|
|
461
|
+
[defs, defErrors, deletedKeys, fieldsets, activeFieldset, singleFieldsetPerRecord, orderDirty, orderSaving, addField, removeField, restoreField, saveOrderIfDirty, t]
|
|
462
462
|
);
|
|
463
|
-
const definitionsGroup = { id: "definitions", title: "Field Definitions", column: 1, component: renderFieldDefinitions };
|
|
463
|
+
const definitionsGroup = { id: "definitions", title: t("entities.userEntities.edit.groups.definitions", "Field Definitions"), column: 1, component: renderFieldDefinitions };
|
|
464
464
|
const groups = [
|
|
465
|
-
{ id: "settings", title: "Entity Settings", column: 1, fields: entitySource === "custom" ? ["label", "description", "defaultEditor", "showInSidebar"] : ["label", "description", "defaultEditor"] },
|
|
465
|
+
{ id: "settings", title: t("entities.userEntities.edit.groups.settings", "Entity Settings"), column: 1, fields: entitySource === "custom" ? ["label", "description", "defaultEditor", "showInSidebar"] : ["label", "description", "defaultEditor"] },
|
|
466
466
|
definitionsGroup
|
|
467
467
|
];
|
|
468
468
|
const handleCrudFormSubmit = React.useCallback(async (vals) => {
|
|
469
469
|
if (!entityId) {
|
|
470
|
-
throw createCrudFormError("Invalid entity ID");
|
|
470
|
+
throw createCrudFormError(t("entities.userEntities.edit.errors.invalidEntityId", "Invalid entity ID"));
|
|
471
471
|
}
|
|
472
472
|
if (!validateAll()) {
|
|
473
|
-
flash("Please fix validation errors in field definitions", "error");
|
|
474
|
-
throw createCrudFormError("Please fix validation errors in field definitions");
|
|
473
|
+
flash(t("entities.customFields.errors.validation", "Please fix validation errors in field definitions."), "error");
|
|
474
|
+
throw createCrudFormError(t("entities.customFields.errors.validation", "Please fix validation errors in field definitions."));
|
|
475
475
|
}
|
|
476
476
|
if (shouldRegisterEntityMetadata(entitySource)) {
|
|
477
477
|
const entityPayload = buildEntityMetadataPayload(entitySource, vals);
|
|
478
|
-
if (!entityPayload) throw createCrudFormError("Validation failed");
|
|
478
|
+
if (!entityPayload) throw createCrudFormError(t("entities.userEntities.edit.errors.validationFailed", "Validation failed"));
|
|
479
479
|
const callEntity = await apiCall("/api/entities/entities", {
|
|
480
480
|
method: "POST",
|
|
481
481
|
headers: { "content-type": "application/json" },
|
|
482
482
|
body: JSON.stringify({ entityId, ...entityPayload })
|
|
483
483
|
});
|
|
484
484
|
if (!callEntity.ok) {
|
|
485
|
-
await raiseCrudError(callEntity.response, "Failed to save entity");
|
|
485
|
+
await raiseCrudError(callEntity.response, t("entities.userEntities.edit.errors.saveEntityFailed", "Failed to save entity"));
|
|
486
486
|
}
|
|
487
487
|
try {
|
|
488
488
|
window.dispatchEvent(new Event("om:refresh-sidebar"));
|
|
@@ -504,7 +504,7 @@ function EditDefinitionsPage({ params }) {
|
|
|
504
504
|
})
|
|
505
505
|
);
|
|
506
506
|
if (!callDefs.ok) {
|
|
507
|
-
await raiseCrudError(callDefs.response, "Failed to save definitions");
|
|
507
|
+
await raiseCrudError(callDefs.response, t("entities.customFields.errors.saveFailed", "Failed to save field definitions."));
|
|
508
508
|
}
|
|
509
509
|
setDefsVersion(readVersionToken(callDefs.result?.version));
|
|
510
510
|
try {
|
|
@@ -512,12 +512,12 @@ function EditDefinitionsPage({ params }) {
|
|
|
512
512
|
} catch {
|
|
513
513
|
}
|
|
514
514
|
await invalidateCustomFieldDefs(queryClient, entityId);
|
|
515
|
-
flash("Definitions saved", "success");
|
|
516
|
-
}, [buildFieldsetPayload, defs, defsVersion, entityId, entitySource, queryClient, singleFieldsetPerRecord, validateAll]);
|
|
515
|
+
flash(t("entities.customFields.flash.saved", "Definitions saved"), "success");
|
|
516
|
+
}, [buildFieldsetPayload, defs, defsVersion, entityId, entitySource, queryClient, singleFieldsetPerRecord, t, validateAll]);
|
|
517
517
|
if (!entityId) {
|
|
518
518
|
return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */ jsx("div", { className: "p-6", children: /* @__PURE__ */ jsxs(Alert, { variant: "destructive", children: [
|
|
519
|
-
/* @__PURE__ */ jsx(AlertTitle, { children: "Invalid entity" }),
|
|
520
|
-
/* @__PURE__ */ jsx(AlertDescription, { children: "The requested entity ID is missing or invalid." })
|
|
519
|
+
/* @__PURE__ */ jsx(AlertTitle, { children: t("entities.userEntities.edit.errors.invalidEntityTitle", "Invalid entity") }),
|
|
520
|
+
/* @__PURE__ */ jsx(AlertDescription, { children: t("entities.userEntities.edit.errors.invalidEntityDescription", "The requested entity ID is missing or invalid.") })
|
|
521
521
|
] }) }) }) });
|
|
522
522
|
}
|
|
523
523
|
if (embedFieldsetView) {
|
|
@@ -525,12 +525,12 @@ function EditDefinitionsPage({ params }) {
|
|
|
525
525
|
CrudForm,
|
|
526
526
|
{
|
|
527
527
|
schema: entityFormSchema,
|
|
528
|
-
title:
|
|
528
|
+
title: t("entities.userEntities.edit.fieldsetTitle", "Edit fieldset: {{name}}", { name: requestedFieldset ?? entityId }),
|
|
529
529
|
fields: [],
|
|
530
530
|
groups: [definitionsGroup],
|
|
531
531
|
initialValues: entityInitial,
|
|
532
532
|
isLoading: entityFormLoading || loading,
|
|
533
|
-
submitLabel: "Save",
|
|
533
|
+
submitLabel: t("entities.userEntities.records.form.submitSave", "Save"),
|
|
534
534
|
deleteVisible: false,
|
|
535
535
|
backHref: void 0,
|
|
536
536
|
cancelHref: void 0,
|
|
@@ -544,24 +544,24 @@ function EditDefinitionsPage({ params }) {
|
|
|
544
544
|
CrudForm,
|
|
545
545
|
{
|
|
546
546
|
schema: entityFormSchema,
|
|
547
|
-
title:
|
|
547
|
+
title: t("entities.userEntities.edit.title", "Edit Entity: {{entityId}}", { entityId }),
|
|
548
548
|
backHref: entitySource === "code" ? "/backend/entities/system" : "/backend/entities/user",
|
|
549
549
|
fields,
|
|
550
550
|
groups,
|
|
551
551
|
initialValues: entityInitial,
|
|
552
552
|
isLoading: entityFormLoading || loading,
|
|
553
|
-
submitLabel: "Save",
|
|
553
|
+
submitLabel: t("entities.userEntities.records.form.submitSave", "Save"),
|
|
554
554
|
deleteVisible: entitySource === "custom",
|
|
555
|
-
extraActions: entitySource === "custom" ? /* @__PURE__ */ jsx(Button, { variant: "outline", asChild: true, children: /* @__PURE__ */ jsx(Link, { href: `/backend/entities/user/${encodeURIComponent(entityId)}/records`, children: "Show Records" }) }) : null,
|
|
555
|
+
extraActions: entitySource === "custom" ? /* @__PURE__ */ jsx(Button, { variant: "outline", asChild: true, children: /* @__PURE__ */ jsx(Link, { href: `/backend/entities/user/${encodeURIComponent(entityId)}/records`, children: t("entities.userEntities.edit.showRecords", "Show Records") }) }) : null,
|
|
556
556
|
cancelHref: entitySource === "code" ? "/backend/entities/system" : "/backend/entities/user",
|
|
557
|
-
successRedirect: entitySource === "code" ?
|
|
557
|
+
successRedirect: entitySource === "code" ? `/backend/entities/system?flash=${encodeURIComponent(t("entities.customFields.flash.saved", "Definitions saved"))}&type=success` : `/backend/entities/user?flash=${encodeURIComponent(t("entities.customFields.flash.saved", "Definitions saved"))}&type=success`,
|
|
558
558
|
onSubmit: handleCrudFormSubmit,
|
|
559
559
|
onDelete: entitySource === "custom" ? async () => {
|
|
560
560
|
const callDelete = await apiCall("/api/entities/entities", { method: "DELETE", headers: { "content-type": "application/json" }, body: JSON.stringify({ entityId }) });
|
|
561
561
|
if (!callDelete.ok) {
|
|
562
|
-
await raiseCrudError(callDelete.response, "Failed to delete entity");
|
|
562
|
+
await raiseCrudError(callDelete.response, t("entities.userEntities.edit.errors.deleteEntityFailed", "Failed to delete entity"));
|
|
563
563
|
}
|
|
564
|
-
flash("Entity deleted", "success");
|
|
564
|
+
flash(t("entities.userEntities.edit.flash.entityDeleted", "Entity deleted"), "success");
|
|
565
565
|
try {
|
|
566
566
|
window.dispatchEvent(new Event("om:refresh-sidebar"));
|
|
567
567
|
} catch {
|