@mmlogic/components 0.5.17 → 0.5.18
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/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/mosterdcomponents.cjs.js +1 -1
- package/dist/cjs/mrd-boolean-field_28.cjs.entry.js +98 -13
- package/dist/collection/components/layout/mrd-layout-section/mrd-layout-section.js +77 -11
- package/dist/collection/components/table/mrd-table/mrd-table.js +94 -8
- package/dist/collection/dev/api.js +3 -1
- package/dist/collection/dev/app.js +42 -3
- package/dist/components/mrd-layout-section.js +1 -1
- package/dist/components/mrd-table2.js +1 -1
- package/dist/esm/loader.js +1 -1
- package/dist/esm/mosterdcomponents.js +1 -1
- package/dist/esm/mrd-boolean-field_28.entry.js +98 -13
- package/dist/mosterdcomponents/cell-renderer-CMUxFREW.js.map +1 -0
- package/dist/mosterdcomponents/client-layout-BJkVeSq6.js.map +1 -0
- package/dist/mosterdcomponents/document-attachments-BufPmMRv.js.map +1 -0
- package/dist/mosterdcomponents/field-helpers-BWAp5fD8.js.map +1 -0
- package/dist/mosterdcomponents/file-upload-common-DDWuC9-3.js.map +1 -0
- package/dist/mosterdcomponents/format-gcecItcD.js.map +1 -0
- package/dist/mosterdcomponents/i18n-OzbszktW.js.map +1 -0
- package/dist/mosterdcomponents/index-1ayBojyN.js.map +1 -0
- package/dist/mosterdcomponents/index-CkcFwdPc.js.map +1 -0
- package/dist/mosterdcomponents/index.esm.js.map +1 -0
- package/dist/mosterdcomponents/mosterdcomponents.esm.js +1 -1
- package/dist/mosterdcomponents/mosterdcomponents.esm.js.map +1 -0
- package/dist/mosterdcomponents/p-29d6dcbc.entry.js +3 -0
- package/dist/mosterdcomponents/purify.es-_duHfPgC.js.map +1 -0
- package/dist/mosterdcomponents/query-params-3TXd5CUO.js.map +1 -0
- package/dist/mosterdcomponents/quill-C9pgw_k-.js.map +1 -0
- package/dist/mosterdcomponents/table-query-DJq1uKqJ.js.map +1 -0
- package/dist/mosterdcomponents/validation-B_0Lx9DE.js.map +1 -0
- package/dist/types/components/layout/mrd-layout-section/mrd-layout-section.d.ts +24 -2
- package/dist/types/components/table/mrd-table/mrd-table.d.ts +33 -3
- package/dist/types/components.d.ts +34 -4
- package/package.json +1 -1
- package/dist/mosterdcomponents/p-f72668e9.entry.js +0 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"table-query-DJq1uKqJ.js","sources":["src/components/table/mrd-table/table-query.ts"],"sourcesContent":["import { ColumnFilter, TableColumn } from '../../../utils/cell-renderer';\nimport { ViewFilter } from '../../../types/client-layout';\nimport { applyViewFilters } from '../../../utils/query-params';\n\n/**\n * Pure sort/filter/aggregation query logic for mrd-table.\n * No component state — everything is passed in.\n */\n\nexport const TEXT_TYPES = new Set(['TEXT', 'TEXTBLOCK', 'EMAIL', 'HYPERLINK']);\nexport const NUMERIC_TYPES = new Set(['INTEGER', 'DECIMAL', 'PERCENTAGE', 'CURRENCY']);\nexport const DATE_TYPES = new Set(['DATE', 'DATETIME', 'TIME']);\nexport const NO_FILTER_TYPES = new Set(['FILE', 'IMAGE']);\n\n/** Column types that cannot be sorted or filtered (not stored in PostgreSQL). */\nexport const NON_INTERACTIVE_TYPES = new Set(['LONGTEXT', 'JSON', 'FILE', 'IMAGE']);\n\n/** Wait this long (ms) after the user stops typing in the free-text search box\n * before firing the search request — mirrors REQUEST_DEBOUNCE_MS's purpose\n * (skip intermediate keystrokes) but is tuned for typing, not scrolling. */\nexport const SEARCH_DEBOUNCE_MS = 400;\n\nexport function parseDefaultSort(defaultSort: string): { field: string; dir: 'asc' | 'desc' } {\n if (!defaultSort) return { field: '', dir: 'asc' };\n const parts = defaultSort.split(',');\n return { field: parts[0].trim(), dir: parts[1]?.trim() === 'desc' ? 'desc' : 'asc' };\n}\n\n/** Raw sort query-param value, e.g. \"name\" or \"name,desc\". */\nexport function buildSortParam(field: string, dir: 'asc' | 'desc'): string {\n if (!field) return '';\n return dir === 'desc' ? `${field},desc` : field;\n}\n\n/** Query params for a page request: page + sort + filterClass + view filters + active column filters. */\nexport function buildTableQueryParams(opts: {\n page: number;\n sort: string;\n filterClass?: string | null;\n viewFilters?: ViewFilter[] | null;\n activeFilters: Iterable<ColumnFilter>;\n /** Free-text search query from the toolbar's search box (VIEW only). */\n query?: string;\n}): string {\n const p = new URLSearchParams();\n if (opts.page > 0) p.set('page', String(opts.page));\n if (opts.sort) p.set('sort', opts.sort);\n if (opts.filterClass) p.set('type', opts.filterClass);\n applyViewFilters(p, opts.viewFilters);\n if (opts.query) p.set('q', opts.query);\n for (const f of opts.activeFilters) {\n if (f.operator === 'isEmpty') { p.set(f.field, ''); continue; }\n if (f.operator === 'isNotEmpty') { p.set(f.field + '_notempty', 'true'); continue; }\n if (f.operator === 'startsWith') { p.set(f.field + '_startswith', String(f.value ?? '')); continue; }\n if (f.values?.length) { p.set(f.field, f.values.join(',')); continue; }\n if (f.value != null) p.set(f.field, String(f.value));\n if (f.from != null) p.set(f.field + '_from', String(f.from));\n if (f.to != null) p.set(f.field + '_to', String(f.to));\n }\n return p.toString();\n}\n\n/** Groups aggregate columns by function; null when the view has no aggregates. */\nexport function buildAggregationParams(columns: TableColumn[]): { sum?: string[]; avg?: string[]; count?: string[] } | null {\n const groups: { sum: string[]; avg: string[]; count: string[] } = { sum: [], avg: [], count: [] };\n for (const col of columns) {\n if (col.type !== 'FIELD' || !col.aggregate) continue;\n const fn = col.aggregate.toLowerCase() as 'sum' | 'avg' | 'count';\n if (fn in groups) groups[fn].push(col.name ?? '');\n }\n const params: { sum?: string[]; avg?: string[]; count?: string[] } = {};\n if (groups.sum.length) params.sum = groups.sum;\n if (groups.avg.length) params.avg = groups.avg;\n if (groups.count.length) params.count = groups.count;\n return Object.keys(params).length > 0 ? params : null;\n}\n\n/** Aggregation query string: the page-0 query params without page/sort, plus sum/avg/count. */\nexport function buildAggregationQs(basePageQs: string, columns: TableColumn[]): string {\n const p = new URLSearchParams(basePageQs);\n p.delete('page');\n p.delete('sort');\n const groups = buildAggregationParams(columns);\n if (groups?.sum?.length) p.set('sum', groups.sum.join(','));\n if (groups?.avg?.length) p.set('avg', groups.avg.join(','));\n if (groups?.count?.length) p.set('count', groups.count.join(','));\n return p.toString();\n}\n\n/** True when the pending filter actually constrains anything. */\nexport function filterHasValue(f: Partial<ColumnFilter>): boolean {\n if (f.operator === 'isEmpty' || f.operator === 'isNotEmpty') return true;\n if (f.values !== undefined && f.values.length > 0) return true;\n if (f.value != null && f.value !== '') return true;\n if (typeof f.value === 'boolean') return true;\n if (f.from != null && f.from !== '') return true;\n if (f.to != null && f.to !== '') return true;\n return false;\n}\n\n// ── DATETIME filters: the user edits local \"YYYY-MM-DD\" dates, the API stores UTC ISO ──\n\n/** UTC ISO string at the start (midnight) of the given local day. */\nexport function dateLocalToUTCStart(dateStr: string): string {\n if (!dateStr) return dateStr;\n const [year, month, day] = dateStr.split('-').map(Number);\n return new Date(year, month - 1, day).toISOString().replace(/\\.\\d{3}Z$/, 'Z');\n}\n\n/** Start of the day AFTER the given local date (exclusive range end). */\nexport function dateLocalToUTCEndExclusive(dateStr: string): string {\n if (!dateStr) return dateStr;\n const [year, month, day] = dateStr.split('-').map(Number);\n return new Date(year, month - 1, day + 1).toISOString().replace(/\\.\\d{3}Z$/, 'Z');\n}\n\n/** Stored UTC ISO string back to the local \"YYYY-MM-DD\" date. */\nexport function utcISOToLocalDate(utcStr: string): string {\n if (!utcStr) return utcStr;\n const d = new Date(utcStr);\n if (isNaN(d.getTime())) return utcStr;\n return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;\n}\n\n/** The stored \"to\" is the exclusive end (next midnight); subtract a day to recover the entered date. */\nexport function utcISOToLocalDateExclusiveEnd(utcStr: string): string {\n if (!utcStr) return utcStr;\n const d = new Date(utcStr);\n if (isNaN(d.getTime())) return utcStr;\n d.setDate(d.getDate() - 1);\n return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;\n}\n\n/** Applies the local→UTC conversion when a DATETIME filter is submitted.\n * Exact date → range covering the full local day. */\nexport function normalizeDatetimeFilter(f: Partial<ColumnFilter>): Partial<ColumnFilter> {\n const normalized = { ...f };\n if (f.dataType === 'DATETIME' && f.operator !== 'isEmpty' && f.operator !== 'isNotEmpty') {\n if (typeof normalized.value === 'string' && normalized.value) {\n normalized.from = dateLocalToUTCStart(normalized.value);\n normalized.to = dateLocalToUTCEndExclusive(normalized.value);\n normalized.value = undefined;\n } else {\n if (typeof normalized.from === 'string' && normalized.from)\n normalized.from = dateLocalToUTCStart(normalized.from);\n if (typeof normalized.to === 'string' && normalized.to)\n normalized.to = dateLocalToUTCEndExclusive(normalized.to);\n }\n }\n return normalized;\n}\n\n/** Converts a stored DATETIME filter back to local dates for the popup.\n * A range covering a single local day is restored to exact-date mode. */\nexport function datetimeFilterToDisplay(existing: ColumnFilter): Partial<ColumnFilter> {\n const display: Partial<ColumnFilter> = { ...existing };\n if (typeof display.from === 'string' && display.from)\n display.from = utcISOToLocalDate(display.from);\n if (typeof display.to === 'string' && display.to)\n display.to = utcISOToLocalDateExclusiveEnd(display.to);\n if (display.from && display.to && display.from === display.to) {\n return { ...display, value: display.from, from: undefined, to: undefined };\n }\n return display;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation-B_0Lx9DE.js","sources":["src/utils/validation.ts"],"sourcesContent":["import { ClientLayoutItemFieldDataType } from '../types';\n\nexport function validateRequired(value: unknown): boolean {\n if (value === null || value === undefined) return false;\n if (typeof value === 'string') return value.trim().length > 0;\n if (Array.isArray(value)) return value.length > 0;\n if (typeof value === 'object') {\n // HyperlinkValue check\n const hv = value as { href?: unknown };\n if ('href' in hv) return typeof hv.href === 'string' && hv.href.trim().length > 0;\n // CurrencyValue check\n const cv = value as { amount?: unknown };\n if ('amount' in cv) return cv.amount !== null && cv.amount !== undefined && cv.amount !== '';\n }\n return true;\n}\n\nexport function validateEmail(value: string): boolean {\n if (!value) return true;\n return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value);\n}\n\nexport function validateUrl(value: string): boolean {\n if (!value) return true;\n try {\n const url = new URL(value);\n return url.protocol === 'http:' || url.protocol === 'https:';\n } catch {\n return false;\n }\n}\n\nexport function validateNumber(value: unknown, dataType: ClientLayoutItemFieldDataType): boolean {\n if (value === null || value === undefined || value === '') return true;\n const num = Number(value);\n if (isNaN(num)) return false;\n if (dataType === ClientLayoutItemFieldDataType.INTEGER) {\n return Number.isInteger(num);\n }\n if (dataType === ClientLayoutItemFieldDataType.PERCENTAGE) {\n return num >= 0 && num <= 100;\n }\n return true;\n}\n"],"names":[],"mappings":";;;AAEM,SAAU,gBAAgB,CAAC,KAAc,EAAA;AAC7C,IAAA,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;AAAE,QAAA,OAAO,KAAK;IACvD,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC;AAC7D,IAAA,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;AAAE,QAAA,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC;AACjD,IAAA,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;;QAE7B,MAAM,EAAE,GAAG,KAA2B;QACtC,IAAI,MAAM,IAAI,EAAE;AAAE,YAAA,OAAO,OAAO,EAAE,CAAC,IAAI,KAAK,QAAQ,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC;;QAEjF,MAAM,EAAE,GAAG,KAA6B;QACxC,IAAI,QAAQ,IAAI,EAAE;AAAE,YAAA,OAAO,EAAE,CAAC,MAAM,KAAK,IAAI,IAAI,EAAE,CAAC,MAAM,KAAK,SAAS,IAAI,EAAE,CAAC,MAAM,KAAK,EAAE;;AAE9F,IAAA,OAAO,IAAI;AACb;AAEM,SAAU,aAAa,CAAC,KAAa,EAAA;AACzC,IAAA,IAAI,CAAC,KAAK;AAAE,QAAA,OAAO,IAAI;AACvB,IAAA,OAAO,4BAA4B,CAAC,IAAI,CAAC,KAAK,CAAC;AACjD;AAEM,SAAU,WAAW,CAAC,KAAa,EAAA;AACvC,IAAA,IAAI,CAAC,KAAK;AAAE,QAAA,OAAO,IAAI;AACvB,IAAA,IAAI;AACF,QAAA,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC;QAC1B,OAAO,GAAG,CAAC,QAAQ,KAAK,OAAO,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ;;IAC5D,OAAA,EAAA,EAAM;AACN,QAAA,OAAO,KAAK;;AAEhB;AAEM,SAAU,cAAc,CAAC,KAAc,EAAE,QAAuC,EAAA;IACpF,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE;AAAE,QAAA,OAAO,IAAI;AACtE,IAAA,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC;IACzB,IAAI,KAAK,CAAC,GAAG,CAAC;AAAE,QAAA,OAAO,KAAK;AAC5B,IAAA,IAAI,QAAQ,KAAK,6BAA6B,CAAC,OAAO,EAAE;AACtD,QAAA,OAAO,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC;;AAE9B,IAAA,IAAI,QAAQ,KAAK,6BAA6B,CAAC,UAAU,EAAE;AACzD,QAAA,OAAO,GAAG,IAAI,CAAC,IAAI,GAAG,IAAI,GAAG;;AAE/B,IAAA,OAAO,IAAI;AACb;;;;"}
|
|
@@ -22,6 +22,12 @@ export declare class MrdLayoutSection {
|
|
|
22
22
|
* create ("+") action and the documents view's New folder / Upload are disabled
|
|
23
23
|
* with a tooltip explaining why, so it's clear at a glance the user can't mutate data. */
|
|
24
24
|
readOnly: boolean;
|
|
25
|
+
/** When false, skips the mrdViewCheckCapabilities round trip for every VIEW/RELATED_VIEW
|
|
26
|
+
* binding and hands mrd-table/mrd-memo-container/mrd-document-container their create
|
|
27
|
+
* affordance as allowed immediately — for a tenant with no access control configured,
|
|
28
|
+
* the answer would always be mayCreate: true anyway (FINDING-0171 / TASK-0322). Default
|
|
29
|
+
* `true` keeps today's ask-and-hide behaviour unchanged. */
|
|
30
|
+
accessControlEnabled: boolean;
|
|
25
31
|
/** The active account's linked person record (userProfile.links.person), if any.
|
|
26
32
|
* Threaded to mrd-memo-container so a top-level memo VIEW (no parent record to
|
|
27
33
|
* attach a new memo to) can still offer "New memo" by falling back to the
|
|
@@ -38,6 +44,12 @@ export declare class MrdLayoutSection {
|
|
|
38
44
|
* means "not answered yet" and is treated as false (hidden), same default as mrd-table's
|
|
39
45
|
* own standalone behaviour (TASK-0299). */
|
|
40
46
|
private canCreateMap;
|
|
47
|
+
/** Companion to canCreateMap — concrete types the mrdViewCheckCapabilities answer allows,
|
|
48
|
+
* when the API reports them; passed to mrd-table's `allowedTypes` prop to narrow its
|
|
49
|
+
* create-type picker down to types a create POST would actually accept (FINDING-0176 /
|
|
50
|
+
* TASK-0314). A missing entry means "not answered yet / not reported" — mrd-table then
|
|
51
|
+
* leaves `item.createTypes` unfiltered, same as before this existed. */
|
|
52
|
+
private allowedTypesMap;
|
|
41
53
|
private historyClickOutside;
|
|
42
54
|
/** Signature last asked per view key (see emitCapabilitiesChecks()) — avoids re-emitting
|
|
43
55
|
* mrdViewCheckCapabilities on every data/items update when the binding hasn't changed. */
|
|
@@ -113,7 +125,9 @@ export declare class MrdLayoutSection {
|
|
|
113
125
|
/** Emitted once per VIEW/RELATED_VIEW binding — computed here directly, not relayed from a
|
|
114
126
|
* child (see emitCapabilitiesChecks()), so it covers mrd-table, mrd-memo-container and
|
|
115
127
|
* mrd-document-container uniformly. `name` is the view key (viewKeyFor(item)) — pass it
|
|
116
|
-
* back to setViewCanCreate() to answer it.
|
|
128
|
+
* back to setViewCanCreate() to answer it. setViewCanCreate()'s optional third argument
|
|
129
|
+
* narrows a table's `item.createTypes` picker to the concrete types the answer allows,
|
|
130
|
+
* when the API's capabilities response reports them (FINDING-0176 / TASK-0314). */
|
|
117
131
|
mrdViewCheckCapabilities: EventEmitter<{
|
|
118
132
|
name: string;
|
|
119
133
|
type: string;
|
|
@@ -188,7 +202,15 @@ export declare class MrdLayoutSection {
|
|
|
188
202
|
* canCreateMap and passed down as a plain prop to whichever body is mounted for that key
|
|
189
203
|
* (mrd-table, mrd-memo-container or mrd-document-container) — no DOM lookup needed, unlike
|
|
190
204
|
* setViewPage/setViewAggregations, since the prop flows through the next render. */
|
|
191
|
-
setViewCanCreate(name: string, value: boolean): Promise<void>;
|
|
205
|
+
setViewCanCreate(name: string, value: boolean, allowedTypes?: string[]): Promise<void>;
|
|
206
|
+
/** `canCreateMap[key]` when access control is configured (default); always allowed
|
|
207
|
+
* when `accessControlEnabled` is false, since emitCapabilitiesChecks() never asked
|
|
208
|
+
* and canCreateMap[key] would otherwise stay permanently unanswered. */
|
|
209
|
+
private effectiveCanCreate;
|
|
210
|
+
/** `allowedTypesMap[key]` when access control is configured; `undefined` (don't filter)
|
|
211
|
+
* when disabled, since emitCapabilitiesChecks() never asked and the map entry would
|
|
212
|
+
* otherwise stay permanently unanswered — see effectiveCanCreate(). */
|
|
213
|
+
private effectiveAllowedTypes;
|
|
192
214
|
/** Inject distinct values into an embedded mrd-document-list for a document view. */
|
|
193
215
|
setViewDistinct(name: string, nodeId: string, values: DistinctValue[]): Promise<void>;
|
|
194
216
|
/** Inject the uploaded file reference for a dropped file, so the document view
|
|
@@ -70,6 +70,21 @@ export declare class MrdTable {
|
|
|
70
70
|
* the answer to whichever body it mounts) — the table then trusts it directly and never
|
|
71
71
|
* asks on its own (TASK-0299). */
|
|
72
72
|
canCreate?: boolean;
|
|
73
|
+
/** Concrete types (`item.createTypes[].type`) the current user may actually create, when
|
|
74
|
+
* `item.createTypes` offers a picker for a family type — narrows it down to only the types
|
|
75
|
+
* a create POST would accept (FINDING-0176 / TASK-0314). Leave `undefined` for standalone
|
|
76
|
+
* use — the table takes it from the second argument of setCanCreate() alongside `canCreate`.
|
|
77
|
+
* Set it explicitly (e.g. from mrd-layout-section, alongside `canCreate`) when the host
|
|
78
|
+
* already has the answer. `undefined` (not yet answered, or an older host/API that doesn't
|
|
79
|
+
* report it) means "don't filter" — `item.createTypes` is shown unfiltered, same as before
|
|
80
|
+
* this existed. */
|
|
81
|
+
allowedTypes?: string[] | null;
|
|
82
|
+
/** When false, skips the standalone mrdCheckCapabilities round trip entirely and renders
|
|
83
|
+
* the create action immediately as allowed — for a tenant that has no access control
|
|
84
|
+
* configured, the answer would always be true anyway (FINDING-0171 / TASK-0322). Ignored
|
|
85
|
+
* while `canCreate` is set explicitly (the host already controls the answer directly in
|
|
86
|
+
* that mode). Default `true` keeps today's ask-and-hide behaviour unchanged. */
|
|
87
|
+
accessControlEnabled: boolean;
|
|
73
88
|
/** Clamp renderEnd when totalElements shrinks (e.g. after a filter is applied).
|
|
74
89
|
* 0 means "unknown" (hosts that rely on minKnownTotal never set it, and some reset it
|
|
75
90
|
* while a filter is being applied) — clamping to it would collapse the window to a
|
|
@@ -132,6 +147,9 @@ export declare class MrdTable {
|
|
|
132
147
|
* hidden (TASK-0299) until the host answers mrdCheckCapabilities via setCanCreate(). Ignored
|
|
133
148
|
* when the host controls `canCreate` directly; see effectiveCanCreate(). */
|
|
134
149
|
private selfCanCreate;
|
|
150
|
+
/** Self-asked companion to selfCanCreate — the concrete types setCanCreate() reported allowed,
|
|
151
|
+
* or `undefined` while unanswered / when the host's mrdCheckCapabilities answer omitted it. */
|
|
152
|
+
private selfAllowedTypes;
|
|
135
153
|
/** Fired when a page needs to be fetched. Host fetches and calls setPage().
|
|
136
154
|
* `sort` is the raw query-param value, e.g. "name" or "name,desc". */
|
|
137
155
|
mrdLoadPage: EventEmitter<{
|
|
@@ -184,7 +202,10 @@ export declare class MrdTable {
|
|
|
184
202
|
* `filterClass`, when the view declares one, is the same subtype the row fetch sends as
|
|
185
203
|
* `?type=` — e.g. a "contents" RELATED_VIEW filtered to `document` asks specifically whether
|
|
186
204
|
* a document may be created here, not any content type.
|
|
187
|
-
* The add button stays hidden until the host calls setCanCreate() (FINDING-0155 / TASK-0299).
|
|
205
|
+
* The add button stays hidden until the host calls setCanCreate() (FINDING-0155 / TASK-0299).
|
|
206
|
+
* setCanCreate()'s optional second argument narrows `item.createTypes`'s picker down to the
|
|
207
|
+
* concrete types the answer allows, when the API's capabilities response reports them
|
|
208
|
+
* (FINDING-0176 / TASK-0314). */
|
|
188
209
|
mrdCheckCapabilities: EventEmitter<{
|
|
189
210
|
type: string;
|
|
190
211
|
refType?: string;
|
|
@@ -219,7 +240,7 @@ export declare class MrdTable {
|
|
|
219
240
|
* prop is set, since the host controls it directly in that mode). Call it any time after
|
|
220
241
|
* the event fires; a stale answer for an old binding is discarded automatically
|
|
221
242
|
* (selfCanCreate is reset to false before every new mrdCheckCapabilities emission). */
|
|
222
|
-
setCanCreate(value: boolean): Promise<void>;
|
|
243
|
+
setCanCreate(value: boolean, allowedTypes?: string[]): Promise<void>;
|
|
223
244
|
disconnectedCallback(): void;
|
|
224
245
|
componentDidRender(): void;
|
|
225
246
|
/** Freeze the column widths once the first data page has rendered.
|
|
@@ -334,8 +355,17 @@ export declare class MrdTable {
|
|
|
334
355
|
* mode must not flip back to the rows prop (and its "no results") while page 0 is in flight. */
|
|
335
356
|
private get isPaginated();
|
|
336
357
|
private get columns();
|
|
337
|
-
/** `canCreate` when the host controls it directly
|
|
358
|
+
/** `canCreate` when the host controls it directly; else, when access control is disabled,
|
|
359
|
+
* always allowed; else the table's own self-asked answer. */
|
|
338
360
|
private get effectiveCanCreate();
|
|
361
|
+
/** `allowedTypes` when the host controls it directly, else the table's own self-asked
|
|
362
|
+
* answer. `undefined` means "unknown — don't filter", not "nothing allowed". */
|
|
363
|
+
private get effectiveAllowedTypes();
|
|
364
|
+
/** `item.createTypes` intersected with effectiveAllowedTypes when that is known, so the
|
|
365
|
+
* create-type picker only offers concrete types a create POST would actually accept
|
|
366
|
+
* (FINDING-0176 / TASK-0314). Unfiltered when the answer isn't known (undefined) — an
|
|
367
|
+
* older host/API that never reports allowedTypes keeps today's unfiltered behaviour. */
|
|
368
|
+
private get effectiveCreateTypes();
|
|
339
369
|
private get tableActions();
|
|
340
370
|
private toggleCreatePicker;
|
|
341
371
|
private closeCreatePicker;
|
|
@@ -521,6 +521,11 @@ export namespace Components {
|
|
|
521
521
|
"statusListItems": ClientListValue[] | null;
|
|
522
522
|
}
|
|
523
523
|
interface MrdLayoutSection {
|
|
524
|
+
/**
|
|
525
|
+
* When false, skips the mrdViewCheckCapabilities round trip for every VIEW/RELATED_VIEW binding and hands mrd-table/mrd-memo-container/mrd-document-container their create affordance as allowed immediately — for a tenant with no access control configured, the answer would always be mayCreate: true anyway (FINDING-0171 / TASK-0322). Default `true` keeps today's ask-and-hide behaviour unchanged.
|
|
526
|
+
* @default true
|
|
527
|
+
*/
|
|
528
|
+
"accessControlEnabled": boolean;
|
|
524
529
|
/**
|
|
525
530
|
* Top-level archetypes on the object dashboard. When it contains commons.document, the record is rendered as a single-document view instead of generic fields.
|
|
526
531
|
* @default []
|
|
@@ -574,7 +579,7 @@ export namespace Components {
|
|
|
574
579
|
/**
|
|
575
580
|
* Host answer to mrdViewCheckCapabilities — whether the current user may create a record for the given view's bound route. `name` is the view key from the event detail. Stored in canCreateMap and passed down as a plain prop to whichever body is mounted for that key (mrd-table, mrd-memo-container or mrd-document-container) — no DOM lookup needed, unlike setViewPage/setViewAggregations, since the prop flows through the next render.
|
|
576
581
|
*/
|
|
577
|
-
"setViewCanCreate": (name: string, value: boolean) => Promise<void>;
|
|
582
|
+
"setViewCanCreate": (name: string, value: boolean, allowedTypes?: string[]) => Promise<void>;
|
|
578
583
|
/**
|
|
579
584
|
* Inject the created document's href after a file-drop create, so the optimistic row becomes navigable (see mrdCreateObject). For a memo quick-create there is no optimistic row to resolve — simply reload the container's current body so the new memo shows up.
|
|
580
585
|
*/
|
|
@@ -1011,6 +1016,15 @@ export namespace Components {
|
|
|
1011
1016
|
"value": string;
|
|
1012
1017
|
}
|
|
1013
1018
|
interface MrdTable {
|
|
1019
|
+
/**
|
|
1020
|
+
* When false, skips the standalone mrdCheckCapabilities round trip entirely and renders the create action immediately as allowed — for a tenant that has no access control configured, the answer would always be true anyway (FINDING-0171 / TASK-0322). Ignored while `canCreate` is set explicitly (the host already controls the answer directly in that mode). Default `true` keeps today's ask-and-hide behaviour unchanged.
|
|
1021
|
+
* @default true
|
|
1022
|
+
*/
|
|
1023
|
+
"accessControlEnabled": boolean;
|
|
1024
|
+
/**
|
|
1025
|
+
* Concrete types (`item.createTypes[].type`) the current user may actually create, when `item.createTypes` offers a picker for a family type — narrows it down to only the types a create POST would accept (FINDING-0176 / TASK-0314). Leave `undefined` for standalone use — the table takes it from the second argument of setCanCreate() alongside `canCreate`. Set it explicitly (e.g. from mrd-layout-section, alongside `canCreate`) when the host already has the answer. `undefined` (not yet answered, or an older host/API that doesn't report it) means "don't filter" — `item.createTypes` is shown unfiltered, same as before this existed.
|
|
1026
|
+
*/
|
|
1027
|
+
"allowedTypes"?: string[] | null;
|
|
1014
1028
|
/**
|
|
1015
1029
|
* Whether the current user may create a record for the table's bound route. Leave `undefined` for standalone use — the table then asks on its own via mrdCheckCapabilities and hides the create button until setCanCreate() answers. Set it explicitly when a host already knows the answer (e.g. mrd-layout-section, which asks once per binding and hands the answer to whichever body it mounts) — the table then trusts it directly and never asks on its own (TASK-0299).
|
|
1016
1030
|
*/
|
|
@@ -1065,7 +1079,7 @@ export namespace Components {
|
|
|
1065
1079
|
/**
|
|
1066
1080
|
* Host answer to mrdCheckCapabilities — whether the current user may create a record for the table's currently bound route (standalone use only; ignored while the `canCreate` prop is set, since the host controls it directly in that mode). Call it any time after the event fires; a stale answer for an old binding is discarded automatically (selfCanCreate is reset to false before every new mrdCheckCapabilities emission).
|
|
1067
1081
|
*/
|
|
1068
|
-
"setCanCreate": (value: boolean) => Promise<void>;
|
|
1082
|
+
"setCanCreate": (value: boolean, allowedTypes?: string[]) => Promise<void>;
|
|
1069
1083
|
/**
|
|
1070
1084
|
* Inject the rows for a given page (0-based). Creates a new Map reference so Stencil detects the state change. When the page contains fewer rows than pageSize it is the last page. renderEnd is clamped immediately so no loading-placeholder rows appear beyond the actual data — without requiring the host to update totalElements. Pass hasNext (from _links.next in the API response) for accurate last-page detection even when rows.length === pageSize (exact multiple of page size).
|
|
1071
1085
|
*/
|
|
@@ -2617,6 +2631,11 @@ declare namespace LocalJSX {
|
|
|
2617
2631
|
"statusListItems"?: ClientListValue[] | null;
|
|
2618
2632
|
}
|
|
2619
2633
|
interface MrdLayoutSection {
|
|
2634
|
+
/**
|
|
2635
|
+
* When false, skips the mrdViewCheckCapabilities round trip for every VIEW/RELATED_VIEW binding and hands mrd-table/mrd-memo-container/mrd-document-container their create affordance as allowed immediately — for a tenant with no access control configured, the answer would always be mayCreate: true anyway (FINDING-0171 / TASK-0322). Default `true` keeps today's ask-and-hide behaviour unchanged.
|
|
2636
|
+
* @default true
|
|
2637
|
+
*/
|
|
2638
|
+
"accessControlEnabled"?: boolean;
|
|
2620
2639
|
/**
|
|
2621
2640
|
* Top-level archetypes on the object dashboard. When it contains commons.document, the record is rendered as a single-document view instead of generic fields.
|
|
2622
2641
|
* @default []
|
|
@@ -2689,7 +2708,7 @@ declare namespace LocalJSX {
|
|
|
2689
2708
|
*/
|
|
2690
2709
|
"onMrdViewAction"?: (event: MrdLayoutSectionCustomEvent<{ name: string; action: string; dataClass: string; path?: string; qs?: string; parentPath?: string | null; basicType?: string }>) => void;
|
|
2691
2710
|
/**
|
|
2692
|
-
* Emitted once per VIEW/RELATED_VIEW binding — computed here directly, not relayed from a child (see emitCapabilitiesChecks()), so it covers mrd-table, mrd-memo-container and mrd-document-container uniformly. `name` is the view key (viewKeyFor(item)) — pass it back to setViewCanCreate() to answer it.
|
|
2711
|
+
* Emitted once per VIEW/RELATED_VIEW binding — computed here directly, not relayed from a child (see emitCapabilitiesChecks()), so it covers mrd-table, mrd-memo-container and mrd-document-container uniformly. `name` is the view key (viewKeyFor(item)) — pass it back to setViewCanCreate() to answer it. setViewCanCreate()'s optional third argument narrows a table's `item.createTypes` picker to the concrete types the answer allows, when the API's capabilities response reports them (FINDING-0176 / TASK-0314).
|
|
2693
2712
|
*/
|
|
2694
2713
|
"onMrdViewCheckCapabilities"?: (event: MrdLayoutSectionCustomEvent<{ name: string; type: string; refType?: string; refId?: string; filterClass?: string }>) => void;
|
|
2695
2714
|
/**
|
|
@@ -3145,6 +3164,15 @@ declare namespace LocalJSX {
|
|
|
3145
3164
|
"value"?: string;
|
|
3146
3165
|
}
|
|
3147
3166
|
interface MrdTable {
|
|
3167
|
+
/**
|
|
3168
|
+
* When false, skips the standalone mrdCheckCapabilities round trip entirely and renders the create action immediately as allowed — for a tenant that has no access control configured, the answer would always be true anyway (FINDING-0171 / TASK-0322). Ignored while `canCreate` is set explicitly (the host already controls the answer directly in that mode). Default `true` keeps today's ask-and-hide behaviour unchanged.
|
|
3169
|
+
* @default true
|
|
3170
|
+
*/
|
|
3171
|
+
"accessControlEnabled"?: boolean;
|
|
3172
|
+
/**
|
|
3173
|
+
* Concrete types (`item.createTypes[].type`) the current user may actually create, when `item.createTypes` offers a picker for a family type — narrows it down to only the types a create POST would accept (FINDING-0176 / TASK-0314). Leave `undefined` for standalone use — the table takes it from the second argument of setCanCreate() alongside `canCreate`. Set it explicitly (e.g. from mrd-layout-section, alongside `canCreate`) when the host already has the answer. `undefined` (not yet answered, or an older host/API that doesn't report it) means "don't filter" — `item.createTypes` is shown unfiltered, same as before this existed.
|
|
3174
|
+
*/
|
|
3175
|
+
"allowedTypes"?: string[] | null;
|
|
3148
3176
|
/**
|
|
3149
3177
|
* Whether the current user may create a record for the table's bound route. Leave `undefined` for standalone use — the table then asks on its own via mrdCheckCapabilities and hides the create button until setCanCreate() answers. Set it explicitly when a host already knows the answer (e.g. mrd-layout-section, which asks once per binding and hands the answer to whichever body it mounts) — the table then trusts it directly and never asks on its own (TASK-0299).
|
|
3150
3178
|
*/
|
|
@@ -3163,7 +3191,7 @@ declare namespace LocalJSX {
|
|
|
3163
3191
|
*/
|
|
3164
3192
|
"onMrdAction"?: (event: MrdTableCustomEvent<{ action: string; path?: string; qs?: string; dataClass?: string; parentPath?: string | null; basicType?: string }>) => void;
|
|
3165
3193
|
/**
|
|
3166
|
-
* Standalone use only (never fires while the `canCreate` prop is set — see there). Fired once per table binding (initial load, and whenever the bound item, parent record or active view changes) to ask the host whether the current user may create a record here. Carries the same route the table already uses for its own rows, unconstructed — VIEW: GET /data/{tenant}/{type}/capabilities; RELATED_VIEW: GET /data/{tenant}/{refType}/{refId}/{type}/capabilities. `filterClass`, when the view declares one, is the same subtype the row fetch sends as `?type=` — e.g. a "contents" RELATED_VIEW filtered to `document` asks specifically whether a document may be created here, not any content type. The add button stays hidden until the host calls setCanCreate() (FINDING-0155 / TASK-0299).
|
|
3194
|
+
* Standalone use only (never fires while the `canCreate` prop is set — see there). Fired once per table binding (initial load, and whenever the bound item, parent record or active view changes) to ask the host whether the current user may create a record here. Carries the same route the table already uses for its own rows, unconstructed — VIEW: GET /data/{tenant}/{type}/capabilities; RELATED_VIEW: GET /data/{tenant}/{refType}/{refId}/{type}/capabilities. `filterClass`, when the view declares one, is the same subtype the row fetch sends as `?type=` — e.g. a "contents" RELATED_VIEW filtered to `document` asks specifically whether a document may be created here, not any content type. The add button stays hidden until the host calls setCanCreate() (FINDING-0155 / TASK-0299). setCanCreate()'s optional second argument narrows `item.createTypes`'s picker down to the concrete types the answer allows, when the API's capabilities response reports them (FINDING-0176 / TASK-0314).
|
|
3167
3195
|
*/
|
|
3168
3196
|
"onMrdCheckCapabilities"?: (event: MrdTableCustomEvent<{ type: string; refType?: string; refId?: string; filterClass?: string }>) => void;
|
|
3169
3197
|
/**
|
|
@@ -3431,6 +3459,7 @@ declare namespace LocalJSX {
|
|
|
3431
3459
|
interface MrdLayoutSectionAttributes {
|
|
3432
3460
|
"locale": string;
|
|
3433
3461
|
"readOnly": boolean;
|
|
3462
|
+
"accessControlEnabled": boolean;
|
|
3434
3463
|
}
|
|
3435
3464
|
interface MrdListFieldAttributes {
|
|
3436
3465
|
"name": string;
|
|
@@ -3521,6 +3550,7 @@ declare namespace LocalJSX {
|
|
|
3521
3550
|
"requestTimeoutMs": number;
|
|
3522
3551
|
"readOnly": boolean;
|
|
3523
3552
|
"canCreate": boolean;
|
|
3553
|
+
"accessControlEnabled": boolean;
|
|
3524
3554
|
}
|
|
3525
3555
|
interface MrdTextFieldAttributes {
|
|
3526
3556
|
"name": string;
|