@mmlogic/components 0.5.16 → 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 +244 -21
- package/dist/collection/collection-manifest.json +2 -2
- package/dist/collection/components/documents/mrd-document-container/mrd-document-container.js +31 -4
- package/dist/collection/components/layout/mrd-layout-section/mrd-layout-section.js +196 -11
- package/dist/collection/components/memo/mrd-memo-container/mrd-memo-container.js +28 -4
- package/dist/collection/components/table/mrd-table/mrd-table.js +193 -4
- package/dist/collection/dev/api.js +19 -0
- package/dist/collection/dev/app.js +75 -0
- package/dist/components/mrd-document-container2.js +1 -1
- package/dist/components/mrd-layout-section.js +1 -1
- package/dist/components/mrd-memo-container2.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 +244 -21
- package/dist/mosterdcomponents/mosterdcomponents.esm.js +1 -1
- package/dist/mosterdcomponents/p-29d6dcbc.entry.js +3 -0
- package/dist/types/components/documents/mrd-document-container/mrd-document-container.d.ts +7 -0
- package/dist/types/components/layout/mrd-layout-section/mrd-layout-section.d.ts +69 -0
- package/dist/types/components/memo/mrd-memo-container/mrd-memo-container.d.ts +4 -0
- package/dist/types/components/table/mrd-table/mrd-table.d.ts +75 -0
- package/dist/types/components.d.ts +79 -0
- package/package.json +1 -1
- package/dist/mosterdcomponents/p-8a7fa81d.entry.js +0 -3
package/dist/collection/components/documents/mrd-document-container/mrd-document-container.js
CHANGED
|
@@ -32,6 +32,13 @@ export class MrdDocumentContainer {
|
|
|
32
32
|
* (with a tooltip explaining why) and the embedded table/list get it passed
|
|
33
33
|
* through so their own create/upload/drag-drop paths are disabled too. */
|
|
34
34
|
this.readOnly = false;
|
|
35
|
+
/** Whether the current user may create a document here — set by mrd-layout-section from
|
|
36
|
+
* its generic capability check (TASK-0299/FINDING-0155), the same answer the embedded
|
|
37
|
+
* table gets in list mode. Named `mayCreate` (not `canCreate`) to avoid colliding with
|
|
38
|
+
* the existing `canCreate` state below, which tracks something unrelated: whether the
|
|
39
|
+
* folder tree currently has a valid drop target selected. Defaults to false (hidden)
|
|
40
|
+
* until confirmed, same as mrd-table. */
|
|
41
|
+
this.mayCreate = false;
|
|
35
42
|
/** Active body: folder tree or flat table. */
|
|
36
43
|
this.mode = 'tree';
|
|
37
44
|
/** Whether the folder tree currently has a valid target for "New folder". */
|
|
@@ -46,7 +53,7 @@ export class MrdDocumentContainer {
|
|
|
46
53
|
};
|
|
47
54
|
this.pickFile = () => {
|
|
48
55
|
var _a;
|
|
49
|
-
if (this.readOnly)
|
|
56
|
+
if (this.readOnly || !this.mayCreate)
|
|
50
57
|
return;
|
|
51
58
|
(_a = this.fileInputEl) === null || _a === void 0 ? void 0 : _a.click();
|
|
52
59
|
};
|
|
@@ -84,7 +91,7 @@ export class MrdDocumentContainer {
|
|
|
84
91
|
}
|
|
85
92
|
// ── Toolbar ────────────────────────────────────────────────────────────────
|
|
86
93
|
renderToolbar() {
|
|
87
|
-
return (h("div", { class: "mrd-document-container__toolbar" }, this.mode === 'tree' && (h("button", { type: "button", class: "mrd-document-container__action", disabled: this.readOnly || !this.canCreate, title: this.readOnly ? t('readonly_access', this.locale) : undefined, onClick: this.createFolder }, h("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true" }, h("path", { d: "M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" }), h("path", { d: "M12 11v4M10 13h4" })), t('new_folder', this.locale))), this.mode === 'tree' && (h("button", { type: "button", class: "mrd-document-container__action", disabled: this.readOnly || !this.canCreate, title: this.readOnly ? t('readonly_access', this.locale) : (this.targetLabel ? `${t('doc_upload_to', this.locale)} ${this.targetLabel}` : undefined), onClick: this.pickFile }, h("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true" }, h("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }), h("path", { d: "M12 3v13M7 8l5-5 5 5" })), t('doc_upload', this.locale))), h("input", { type: "file", class: "mrd-document-container__file-input", ref: el => (this.fileInputEl = el), onChange: this.onFilePicked }), h("div", { class: "mrd-document-container__seg", role: "group", "aria-label": t('doc_view_switch', this.locale) }, h("button", { class: "mrd-document-container__seg-btn", "aria-pressed": String(this.mode === 'tree'), title: t('doc_view_tree', this.locale), "aria-label": t('doc_view_tree', this.locale), onClick: () => this.setMode('tree') }, h("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true" }, h("path", { d: "M3 5h6M3 12h9M3 19h6" }), h("circle", { cx: "18", cy: "5", r: "1.6" }), h("circle", { cx: "18", cy: "19", r: "1.6" }), h("path", { d: "M16 12h4" }))), h("button", { class: "mrd-document-container__seg-btn", "aria-pressed": String(this.mode === 'list'), title: t('doc_view_list', this.locale), "aria-label": t('doc_view_list', this.locale), onClick: () => this.setMode('list') }, h("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true" }, h("path", { d: "M8 6h13M8 12h13M8 18h13M3 6h.01M3 12h.01M3 18h.01" }))))));
|
|
94
|
+
return (h("div", { class: "mrd-document-container__toolbar" }, this.mode === 'tree' && this.mayCreate && (h("button", { type: "button", class: "mrd-document-container__action", disabled: this.readOnly || !this.canCreate, title: this.readOnly ? t('readonly_access', this.locale) : undefined, onClick: this.createFolder }, h("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true" }, h("path", { d: "M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" }), h("path", { d: "M12 11v4M10 13h4" })), t('new_folder', this.locale))), this.mode === 'tree' && this.mayCreate && (h("button", { type: "button", class: "mrd-document-container__action", disabled: this.readOnly || !this.canCreate, title: this.readOnly ? t('readonly_access', this.locale) : (this.targetLabel ? `${t('doc_upload_to', this.locale)} ${this.targetLabel}` : undefined), onClick: this.pickFile }, h("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true" }, h("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }), h("path", { d: "M12 3v13M7 8l5-5 5 5" })), t('doc_upload', this.locale))), h("input", { type: "file", class: "mrd-document-container__file-input", ref: el => (this.fileInputEl = el), onChange: this.onFilePicked }), h("div", { class: "mrd-document-container__seg", role: "group", "aria-label": t('doc_view_switch', this.locale) }, h("button", { class: "mrd-document-container__seg-btn", "aria-pressed": String(this.mode === 'tree'), title: t('doc_view_tree', this.locale), "aria-label": t('doc_view_tree', this.locale), onClick: () => this.setMode('tree') }, h("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true" }, h("path", { d: "M3 5h6M3 12h9M3 19h6" }), h("circle", { cx: "18", cy: "5", r: "1.6" }), h("circle", { cx: "18", cy: "19", r: "1.6" }), h("path", { d: "M16 12h4" }))), h("button", { class: "mrd-document-container__seg-btn", "aria-pressed": String(this.mode === 'list'), title: t('doc_view_list', this.locale), "aria-label": t('doc_view_list', this.locale), onClick: () => this.setMode('list') }, h("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true" }, h("path", { d: "M8 6h13M8 12h13M8 18h13M3 6h.01M3 12h.01M3 18h.01" }))))));
|
|
88
95
|
}
|
|
89
96
|
// ── Bodies ───────────────────────────────────────────────────────────────
|
|
90
97
|
renderTree() {
|
|
@@ -115,7 +122,7 @@ export class MrdDocumentContainer {
|
|
|
115
122
|
} }));
|
|
116
123
|
}
|
|
117
124
|
renderList() {
|
|
118
|
-
return (h("mrd-table", { "data-view": this.viewKey, ref: el => (this.tableEl = el), item: this.item, parentId: this.parentId, locale: this.locale, readOnly: this.readOnly, onMrdLoadPage: (e) => {
|
|
125
|
+
return (h("mrd-table", { "data-view": this.viewKey, ref: el => (this.tableEl = el), item: this.item, parentId: this.parentId, locale: this.locale, readOnly: this.readOnly, canCreate: this.mayCreate, onMrdLoadPage: (e) => {
|
|
119
126
|
e.stopPropagation();
|
|
120
127
|
this.mrdLoadPage.emit(e.detail);
|
|
121
128
|
}, onMrdLoadAggregations: (e) => {
|
|
@@ -139,7 +146,7 @@ export class MrdDocumentContainer {
|
|
|
139
146
|
}
|
|
140
147
|
render() {
|
|
141
148
|
const treeMode = this.mode === 'tree';
|
|
142
|
-
return (h(Host, { key: '
|
|
149
|
+
return (h(Host, { key: '4b674a508ac7ddf6af80a40836b72dc65f41c741' }, this.renderToolbar(), h("div", { key: '19968916f685a2e3cd075dabf170f67fb104251c', class: {
|
|
143
150
|
'mrd-document-container__body': true,
|
|
144
151
|
'mrd-document-container__body--tree': treeMode,
|
|
145
152
|
}, style: treeMode ? { height: `${this.height}px`, overflowY: 'auto' } : {} }, treeMode ? this.renderTree() : this.renderList())));
|
|
@@ -326,6 +333,26 @@ export class MrdDocumentContainer {
|
|
|
326
333
|
"reflect": false,
|
|
327
334
|
"attribute": "read-only",
|
|
328
335
|
"defaultValue": "false"
|
|
336
|
+
},
|
|
337
|
+
"mayCreate": {
|
|
338
|
+
"type": "boolean",
|
|
339
|
+
"mutable": false,
|
|
340
|
+
"complexType": {
|
|
341
|
+
"original": "boolean",
|
|
342
|
+
"resolved": "boolean",
|
|
343
|
+
"references": {}
|
|
344
|
+
},
|
|
345
|
+
"required": false,
|
|
346
|
+
"optional": false,
|
|
347
|
+
"docs": {
|
|
348
|
+
"tags": [],
|
|
349
|
+
"text": "Whether the current user may create a document here \u2014 set by mrd-layout-section from\nits generic capability check (TASK-0299/FINDING-0155), the same answer the embedded\ntable gets in list mode. Named `mayCreate` (not `canCreate`) to avoid colliding with\nthe existing `canCreate` state below, which tracks something unrelated: whether the\nfolder tree currently has a valid drop target selected. Defaults to false (hidden)\nuntil confirmed, same as mrd-table."
|
|
350
|
+
},
|
|
351
|
+
"getter": false,
|
|
352
|
+
"setter": false,
|
|
353
|
+
"reflect": false,
|
|
354
|
+
"attribute": "may-create",
|
|
355
|
+
"defaultValue": "false"
|
|
329
356
|
}
|
|
330
357
|
};
|
|
331
358
|
}
|
|
@@ -21,6 +21,12 @@ export class MrdLayoutSection {
|
|
|
21
21
|
* create ("+") action and the documents view's New folder / Upload are disabled
|
|
22
22
|
* with a tooltip explaining why, so it's clear at a glance the user can't mutate data. */
|
|
23
23
|
this.readOnly = false;
|
|
24
|
+
/** When false, skips the mrdViewCheckCapabilities round trip for every VIEW/RELATED_VIEW
|
|
25
|
+
* binding and hands mrd-table/mrd-memo-container/mrd-document-container their create
|
|
26
|
+
* affordance as allowed immediately — for a tenant with no access control configured,
|
|
27
|
+
* the answer would always be mayCreate: true anyway (FINDING-0171 / TASK-0322). Default
|
|
28
|
+
* `true` keeps today's ask-and-hide behaviour unchanged. */
|
|
29
|
+
this.accessControlEnabled = true;
|
|
24
30
|
/** The active account's linked person record (userProfile.links.person), if any.
|
|
25
31
|
* Threaded to mrd-memo-container so a top-level memo VIEW (no parent record to
|
|
26
32
|
* attach a new memo to) can still offer "New memo" by falling back to the
|
|
@@ -31,7 +37,22 @@ export class MrdLayoutSection {
|
|
|
31
37
|
this.imagePreviewUrl = null;
|
|
32
38
|
this.imagePreviews = {};
|
|
33
39
|
this.openHistoryField = null;
|
|
40
|
+
/** Answers to mrdViewCheckCapabilities, keyed by view key — see emitCapabilitiesChecks().
|
|
41
|
+
* Passed straight down as a `canCreate`/`mayCreate` prop to whichever body (mrd-table,
|
|
42
|
+
* mrd-memo-container, mrd-document-container) is mounted for that key; a missing entry
|
|
43
|
+
* means "not answered yet" and is treated as false (hidden), same default as mrd-table's
|
|
44
|
+
* own standalone behaviour (TASK-0299). */
|
|
45
|
+
this.canCreateMap = {};
|
|
46
|
+
/** Companion to canCreateMap — concrete types the mrdViewCheckCapabilities answer allows,
|
|
47
|
+
* when the API reports them; passed to mrd-table's `allowedTypes` prop to narrow its
|
|
48
|
+
* create-type picker down to types a create POST would actually accept (FINDING-0176 /
|
|
49
|
+
* TASK-0314). A missing entry means "not answered yet / not reported" — mrd-table then
|
|
50
|
+
* leaves `item.createTypes` unfiltered, same as before this existed. */
|
|
51
|
+
this.allowedTypesMap = {};
|
|
34
52
|
this.historyClickOutside = null;
|
|
53
|
+
/** Signature last asked per view key (see emitCapabilitiesChecks()) — avoids re-emitting
|
|
54
|
+
* mrdViewCheckCapabilities on every data/items update when the binding hasn't changed. */
|
|
55
|
+
this.capabilitiesAsked = new Map();
|
|
35
56
|
this.searchTimers = {};
|
|
36
57
|
this.handleViewLoadPage = (e, name) => {
|
|
37
58
|
e.stopPropagation();
|
|
@@ -51,6 +72,10 @@ export class MrdLayoutSection {
|
|
|
51
72
|
};
|
|
52
73
|
}
|
|
53
74
|
componentDidLoad() {
|
|
75
|
+
// No DOM/child-hydration dependency, unlike initEmbeddedTables()/emitLoadImages() below —
|
|
76
|
+
// run it immediately rather than deferring, so the host's answer (setViewCanCreate) can
|
|
77
|
+
// land before the child bodies even mount.
|
|
78
|
+
this.emitCapabilitiesChecks();
|
|
54
79
|
setTimeout(() => {
|
|
55
80
|
this.initEmbeddedTables();
|
|
56
81
|
this.emitLoadImages();
|
|
@@ -69,9 +94,15 @@ export class MrdLayoutSection {
|
|
|
69
94
|
}
|
|
70
95
|
dataChanged(newVal) {
|
|
71
96
|
if (newVal && Object.keys(newVal).length > 0) {
|
|
97
|
+
this.emitCapabilitiesChecks();
|
|
72
98
|
setTimeout(() => this.initEmbeddedTables(), 0);
|
|
73
99
|
}
|
|
74
100
|
}
|
|
101
|
+
/** A host can swap `items` (e.g. a different dashboard layout) without `data` changing —
|
|
102
|
+
* dataChanged() alone would miss that binding change. */
|
|
103
|
+
itemsChanged() {
|
|
104
|
+
this.emitCapabilitiesChecks();
|
|
105
|
+
}
|
|
75
106
|
async initEmbeddedTables() {
|
|
76
107
|
const tables = this.el.querySelectorAll('mrd-table[data-view]');
|
|
77
108
|
for (const table of Array.from(tables)) {
|
|
@@ -99,6 +130,70 @@ export class MrdLayoutSection {
|
|
|
99
130
|
}
|
|
100
131
|
}
|
|
101
132
|
}
|
|
133
|
+
/** Parent record id extracted from `data._links.self.href` — the same value every
|
|
134
|
+
* VIEW/RELATED_VIEW item on this record shares, used for RELATED_VIEW path construction
|
|
135
|
+
* (renderRelatedView) and capability checks (emitCapabilitiesChecks). */
|
|
136
|
+
computeParentId() {
|
|
137
|
+
var _a, _b, _c, _d, _e;
|
|
138
|
+
const selfHref = (_d = (_c = (_b = (_a = this.data) === null || _a === void 0 ? void 0 : _a._links) === null || _b === void 0 ? void 0 : _b.self) === null || _c === void 0 ? void 0 : _c.href) !== null && _d !== void 0 ? _d : '';
|
|
139
|
+
return (_e = selfHref.split('/').filter(Boolean).pop()) !== null && _e !== void 0 ? _e : '';
|
|
140
|
+
}
|
|
141
|
+
/** Asks, once per VIEW/RELATED_VIEW binding, whether the current user may create a record
|
|
142
|
+
* there — the single generic place for this check (TASK-0299/FINDING-0155), so mrd-table,
|
|
143
|
+
* mrd-memo-container and mrd-document-container all get the answer the same way: as a plain
|
|
144
|
+
* `canCreate`/`mayCreate` prop from this component, computed here and handed down in
|
|
145
|
+
* renderTable()/renderMemoContainer()/renderDocumentContainer() — none of the three leaf
|
|
146
|
+
* components need to ask on their own when rendered through mrd-layout-section (mrd-table's
|
|
147
|
+
* own self-ask only kicks in for standalone use, i.e. its `canCreate` prop left undefined).
|
|
148
|
+
*
|
|
149
|
+
* The route/path variables mirror what each renderer already uses for its own rows —
|
|
150
|
+
* `type` = `dataClass`, `refType`/`refId` = `fromClass`/parentId for a RELATED_VIEW, and
|
|
151
|
+
* `filterClass` when the view is scoped to one subtype (the same value sent as `?type=` on
|
|
152
|
+
* the row fetch). A signature (not just the key) is tracked per binding so a genuine route
|
|
153
|
+
* change re-asks and hides again, without re-asking on every unrelated data/items update. */
|
|
154
|
+
emitCapabilitiesChecks() {
|
|
155
|
+
var _a, _b, _c, _d;
|
|
156
|
+
if (!this.accessControlEnabled)
|
|
157
|
+
return;
|
|
158
|
+
const parentId = this.computeParentId();
|
|
159
|
+
for (const item of flattenItems(this.items)) {
|
|
160
|
+
if (item.type !== ClientLayoutItemType.VIEW && item.type !== ClientLayoutItemType.RELATED_VIEW)
|
|
161
|
+
continue;
|
|
162
|
+
const key = viewKeyFor(item);
|
|
163
|
+
if (!key || !item.view)
|
|
164
|
+
continue;
|
|
165
|
+
const isRelatedView = item.type === ClientLayoutItemType.RELATED_VIEW;
|
|
166
|
+
const type = (_b = (_a = item.dataClass) !== null && _a !== void 0 ? _a : item.relatedClass) !== null && _b !== void 0 ? _b : key;
|
|
167
|
+
const refType = isRelatedView ? ((_c = item.fromClass) !== null && _c !== void 0 ? _c : '') : undefined;
|
|
168
|
+
const refId = isRelatedView ? parentId : undefined;
|
|
169
|
+
const filterClass = (_d = item.filterClass) !== null && _d !== void 0 ? _d : undefined;
|
|
170
|
+
// A host binding `items` and `data` as separate properties (e.g. Angular's
|
|
171
|
+
// `[items]="…" [data]="…"` on <mrd-layout-section>) can apply them in either
|
|
172
|
+
// order — itemsChanged() can fire while `data` still holds its default `{}`,
|
|
173
|
+
// before the real record (and its self href) has landed. Asking here would
|
|
174
|
+
// emit refId: '' for a RELATED_VIEW, which a host's `refType && refId` check
|
|
175
|
+
// reads as "no parent" and answers via the plain, unscoped capabilities route
|
|
176
|
+
// instead of the parent-scoped one (FINDING-0175 / TASK-0316). Skip without
|
|
177
|
+
// marking capabilitiesAsked, so the real ask fires once dataChanged() lands.
|
|
178
|
+
if (isRelatedView && !refId)
|
|
179
|
+
continue;
|
|
180
|
+
const signature = JSON.stringify([type, refType, refId, filterClass]);
|
|
181
|
+
if (this.capabilitiesAsked.get(key) === signature)
|
|
182
|
+
continue;
|
|
183
|
+
this.capabilitiesAsked.set(key, signature);
|
|
184
|
+
if (key in this.canCreateMap) {
|
|
185
|
+
const next = Object.assign({}, this.canCreateMap);
|
|
186
|
+
delete next[key];
|
|
187
|
+
this.canCreateMap = next;
|
|
188
|
+
}
|
|
189
|
+
if (key in this.allowedTypesMap) {
|
|
190
|
+
const next = Object.assign({}, this.allowedTypesMap);
|
|
191
|
+
delete next[key];
|
|
192
|
+
this.allowedTypesMap = next;
|
|
193
|
+
}
|
|
194
|
+
this.mrdViewCheckCapabilities.emit(Object.assign(Object.assign({ name: key, type }, (refType !== undefined ? { refType, refId } : {})), (filterClass ? { filterClass } : {})));
|
|
195
|
+
}
|
|
196
|
+
}
|
|
102
197
|
/** Inject search results. Pass dataClass to target a specific SEARCH item; omit when there is only one. */
|
|
103
198
|
async setSearchResults(results, dataClass) {
|
|
104
199
|
const key = dataClass !== null && dataClass !== void 0 ? dataClass : this.resolveSearchKey();
|
|
@@ -140,6 +235,28 @@ export class MrdLayoutSection {
|
|
|
140
235
|
return;
|
|
141
236
|
await table.setAggregations(data);
|
|
142
237
|
}
|
|
238
|
+
/** Host answer to mrdViewCheckCapabilities — whether the current user may create a record
|
|
239
|
+
* for the given view's bound route. `name` is the view key from the event detail. Stored in
|
|
240
|
+
* canCreateMap and passed down as a plain prop to whichever body is mounted for that key
|
|
241
|
+
* (mrd-table, mrd-memo-container or mrd-document-container) — no DOM lookup needed, unlike
|
|
242
|
+
* setViewPage/setViewAggregations, since the prop flows through the next render. */
|
|
243
|
+
async setViewCanCreate(name, value, allowedTypes) {
|
|
244
|
+
this.canCreateMap = Object.assign(Object.assign({}, this.canCreateMap), { [name]: value });
|
|
245
|
+
this.allowedTypesMap = Object.assign(Object.assign({}, this.allowedTypesMap), { [name]: allowedTypes });
|
|
246
|
+
}
|
|
247
|
+
/** `canCreateMap[key]` when access control is configured (default); always allowed
|
|
248
|
+
* when `accessControlEnabled` is false, since emitCapabilitiesChecks() never asked
|
|
249
|
+
* and canCreateMap[key] would otherwise stay permanently unanswered. */
|
|
250
|
+
effectiveCanCreate(key) {
|
|
251
|
+
var _a;
|
|
252
|
+
return this.accessControlEnabled ? ((_a = this.canCreateMap[key]) !== null && _a !== void 0 ? _a : false) : true;
|
|
253
|
+
}
|
|
254
|
+
/** `allowedTypesMap[key]` when access control is configured; `undefined` (don't filter)
|
|
255
|
+
* when disabled, since emitCapabilitiesChecks() never asked and the map entry would
|
|
256
|
+
* otherwise stay permanently unanswered — see effectiveCanCreate(). */
|
|
257
|
+
effectiveAllowedTypes(key) {
|
|
258
|
+
return this.accessControlEnabled ? this.allowedTypesMap[key] : undefined;
|
|
259
|
+
}
|
|
143
260
|
/** Inject distinct values into an embedded mrd-document-list for a document view. */
|
|
144
261
|
async setViewDistinct(name, nodeId, values) {
|
|
145
262
|
const list = this.el.querySelector(`mrd-document-list[data-doclist="${name}"]`);
|
|
@@ -227,20 +344,19 @@ export class MrdLayoutSection {
|
|
|
227
344
|
return (h("div", { class: "mrd-layout-section__search", key: `search-${dataClass}` }, h("div", { class: "mrd-layout-section__search-wrap" }, h("svg", { class: "mrd-layout-section__search-icon", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 20 20", fill: "currentColor", "aria-hidden": "true" }, h("path", { "fill-rule": "evenodd", d: "M9 3.5a5.5 5.5 0 100 11 5.5 5.5 0 000-11zM2 9a7 7 0 1112.452 4.391l3.328 3.329a.75.75 0 11-1.06 1.06l-3.329-3.328A7 7 0 012 9z", "clip-rule": "evenodd" })), h("input", { class: "mrd-layout-section__search-input", type: "text", value: query, placeholder: (_c = item.label) !== null && _c !== void 0 ? _c : '', onInput: e => this.handleSearchInput(dataClass, e.target.value) })), results.length > 0 && (h("ul", { class: "mrd-layout-section__search-results" }, results.map(r => (h("li", { key: r.id, class: "mrd-layout-section__search-result" }, h("button", { class: "mrd-layout-section__search-result-btn", onClick: () => this.mrdNavigate.emit({ href: r.id, label: r.label }) }, h("span", { class: "mrd-layout-section__search-result-label" }, r.label), r.description && h("span", { class: "mrd-layout-section__search-result-desc" }, r.description)))))))));
|
|
228
345
|
}
|
|
229
346
|
renderRelatedView(item) {
|
|
230
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k
|
|
347
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
231
348
|
const key = viewKeyFor(item);
|
|
232
349
|
if (!key)
|
|
233
350
|
return null;
|
|
234
351
|
if (!item.view)
|
|
235
352
|
return null;
|
|
236
353
|
const showTitle = (_a = item.showTitle) !== null && _a !== void 0 ? _a : false;
|
|
237
|
-
// Extract parentId from data._links.self.href for RELATED_VIEW path construction
|
|
238
354
|
const selfHref = (_e = (_d = (_c = (_b = this.data) === null || _b === void 0 ? void 0 : _b._links) === null || _c === void 0 ? void 0 : _c.self) === null || _d === void 0 ? void 0 : _d.href) !== null && _e !== void 0 ? _e : '';
|
|
239
|
-
const parentId =
|
|
355
|
+
const parentId = this.computeParentId();
|
|
240
356
|
// The API publishes `archetypes` on the VIEW/RELATED_VIEW item itself
|
|
241
357
|
// (sibling of `view`), not inside `view`.
|
|
242
|
-
const docArchetype = resolveArchetype((
|
|
243
|
-
const memoArchetype = !docArchetype ? resolveArchetype((
|
|
358
|
+
const docArchetype = resolveArchetype((_f = item.archetypes) !== null && _f !== void 0 ? _f : (_g = item.view) === null || _g === void 0 ? void 0 : _g.archetypes, ARCHETYPE_DOCUMENT);
|
|
359
|
+
const memoArchetype = !docArchetype ? resolveArchetype((_h = item.archetypes) !== null && _h !== void 0 ? _h : (_j = item.view) === null || _j === void 0 ? void 0 : _j.archetypes, ARCHETYPE_MEMO) : undefined;
|
|
244
360
|
// Canonical parent href for single-container seeding: use the RELATED_VIEW's
|
|
245
361
|
// fromClass (base class) rather than the route class, so polymorphic subtypes
|
|
246
362
|
// resolve to the same container the documents actually reference.
|
|
@@ -251,7 +367,7 @@ export class MrdLayoutSection {
|
|
|
251
367
|
// back to this parent; only when it matches the container slot does the
|
|
252
368
|
// parent's own href double as the memo's container.
|
|
253
369
|
const memoContainerRelated = item.type !== ClientLayoutItemType.RELATED_VIEW
|
|
254
|
-
|| item.inverseRelation === ((
|
|
370
|
+
|| item.inverseRelation === ((_k = memoArchetype === null || memoArchetype === void 0 ? void 0 : memoArchetype.slots) === null || _k === void 0 ? void 0 : _k.container);
|
|
255
371
|
const memoContainerHref = memoContainerRelated ? containerHref : '';
|
|
256
372
|
// Distinct from memoContainerRelated: only a genuine container-scoped
|
|
257
373
|
// RELATED_VIEW (a company's own memo tab) makes every card's container
|
|
@@ -264,7 +380,7 @@ export class MrdLayoutSection {
|
|
|
264
380
|
* swaps between the folder tree and the flat table. Events are re-emitted to
|
|
265
381
|
* the host with the view key, exactly as the raw list/table events were. */
|
|
266
382
|
renderDocumentContainer(item, key, parentId, archetype, containerHref) {
|
|
267
|
-
return (h("mrd-document-container", { item: item, archetype: archetype, parentId: parentId, containerHref: containerHref, viewKey: key, locale: this.locale, readOnly: this.readOnly, onMrdLoadDistinct: (e) => {
|
|
383
|
+
return (h("mrd-document-container", { item: item, archetype: archetype, parentId: parentId, containerHref: containerHref, viewKey: key, locale: this.locale, readOnly: this.readOnly, mayCreate: this.effectiveCanCreate(key), onMrdLoadDistinct: (e) => {
|
|
268
384
|
e.stopPropagation();
|
|
269
385
|
this.mrdLoadViewDistinct.emit(Object.assign({ name: key }, e.detail));
|
|
270
386
|
}, onMrdLoadPage: (e) => {
|
|
@@ -301,7 +417,7 @@ export class MrdLayoutSection {
|
|
|
301
417
|
renderMemoContainer(item, key, parentId, archetype, containerHref, containerRelated, showContainerLink) {
|
|
302
418
|
var _a, _b, _c, _d;
|
|
303
419
|
const labelsListItems = (_d = (_c = (_b = (_a = item.view) === null || _a === void 0 ? void 0 : _a.values) === null || _b === void 0 ? void 0 : _b.find(v => { var _a; return v.name === ((_a = archetype.slots) === null || _a === void 0 ? void 0 : _a.labels); })) === null || _c === void 0 ? void 0 : _c.listItems) !== null && _d !== void 0 ? _d : null;
|
|
304
|
-
return (h("mrd-memo-container", { "data-view": key, item: item, archetype: archetype, parentId: parentId, containerHref: containerHref, containerRelated: containerRelated, showContainerLink: showContainerLink, viewKey: key, locale: this.locale, readOnly: this.readOnly, me: this.me, labelsListItems: labelsListItems, onMrdNavigate: (e) => {
|
|
420
|
+
return (h("mrd-memo-container", { "data-view": key, item: item, archetype: archetype, parentId: parentId, containerHref: containerHref, containerRelated: containerRelated, showContainerLink: showContainerLink, viewKey: key, locale: this.locale, readOnly: this.readOnly, canCreate: this.effectiveCanCreate(key), me: this.me, labelsListItems: labelsListItems, onMrdNavigate: (e) => {
|
|
305
421
|
var _a;
|
|
306
422
|
e.stopPropagation();
|
|
307
423
|
this.mrdNavigate.emit(Object.assign(Object.assign({}, e.detail), { navigateBehaviour: (_a = item.navigateBehaviour) !== null && _a !== void 0 ? _a : ClientLayoutNavigateBehaviour.PAGE }));
|
|
@@ -328,7 +444,7 @@ export class MrdLayoutSection {
|
|
|
328
444
|
} }));
|
|
329
445
|
}
|
|
330
446
|
renderTable(item, key, parentId) {
|
|
331
|
-
return (h("mrd-table", { "data-view": key, item: item, parentId: parentId, locale: this.locale, readOnly: this.readOnly, onMrdLoadPage: (e) => this.handleViewLoadPage(e, key), onMrdLoadAggregations: (e) => {
|
|
447
|
+
return (h("mrd-table", { "data-view": key, item: item, parentId: parentId, locale: this.locale, readOnly: this.readOnly, canCreate: this.effectiveCanCreate(key), allowedTypes: this.effectiveAllowedTypes(key), accessControlEnabled: this.accessControlEnabled, onMrdLoadPage: (e) => this.handleViewLoadPage(e, key), onMrdLoadAggregations: (e) => {
|
|
332
448
|
var _a;
|
|
333
449
|
e.stopPropagation();
|
|
334
450
|
this.mrdLoadViewAggregations.emit(Object.assign({ name: key, dataClass: (_a = item.dataClass) !== null && _a !== void 0 ? _a : key }, e.detail));
|
|
@@ -466,7 +582,7 @@ export class MrdLayoutSection {
|
|
|
466
582
|
const emailArchetype = !docArchetype && !invoiceArchetype ? resolveArchetype(this.archetypes, ARCHETYPE_EMAIL) : undefined;
|
|
467
583
|
const memoArchetype = !docArchetype && !invoiceArchetype && !emailArchetype ? resolveArchetype(this.archetypes, ARCHETYPE_MEMO) : undefined;
|
|
468
584
|
const anyArchetype = docArchetype || invoiceArchetype || emailArchetype || memoArchetype;
|
|
469
|
-
return (h(Host, { key: '
|
|
585
|
+
return (h(Host, { key: '97351c57865614662e888b3c0278a61d866a74e1' }, h("div", { key: '43e8f0fda8fcd3300b879d05ac692ce331c896d5', class: "mrd-layout-section" }, docArchetype && this.renderDocumentObject(docArchetype), invoiceArchetype && this.renderInvoiceObject(invoiceArchetype), emailArchetype && this.renderEmailObject(emailArchetype), memoArchetype && this.renderMemoObject(memoArchetype), !anyArchetype && this.items.map((item, i) => this.renderItem(item, this.items, i))), this.renderImageModal()));
|
|
470
586
|
}
|
|
471
587
|
static get is() { return "mrd-layout-section"; }
|
|
472
588
|
static get encapsulation() { return "scoped"; }
|
|
@@ -647,6 +763,26 @@ export class MrdLayoutSection {
|
|
|
647
763
|
"attribute": "read-only",
|
|
648
764
|
"defaultValue": "false"
|
|
649
765
|
},
|
|
766
|
+
"accessControlEnabled": {
|
|
767
|
+
"type": "boolean",
|
|
768
|
+
"mutable": false,
|
|
769
|
+
"complexType": {
|
|
770
|
+
"original": "boolean",
|
|
771
|
+
"resolved": "boolean",
|
|
772
|
+
"references": {}
|
|
773
|
+
},
|
|
774
|
+
"required": false,
|
|
775
|
+
"optional": false,
|
|
776
|
+
"docs": {
|
|
777
|
+
"tags": [],
|
|
778
|
+
"text": "When false, skips the mrdViewCheckCapabilities round trip for every VIEW/RELATED_VIEW\nbinding and hands mrd-table/mrd-memo-container/mrd-document-container their create\naffordance as allowed immediately \u2014 for a tenant with no access control configured,\nthe answer would always be mayCreate: true anyway (FINDING-0171 / TASK-0322). Default\n`true` keeps today's ask-and-hide behaviour unchanged."
|
|
779
|
+
},
|
|
780
|
+
"getter": false,
|
|
781
|
+
"setter": false,
|
|
782
|
+
"reflect": false,
|
|
783
|
+
"attribute": "access-control-enabled",
|
|
784
|
+
"defaultValue": "true"
|
|
785
|
+
},
|
|
650
786
|
"me": {
|
|
651
787
|
"type": "unknown",
|
|
652
788
|
"mutable": false,
|
|
@@ -680,7 +816,9 @@ export class MrdLayoutSection {
|
|
|
680
816
|
"searchResultsMap": {},
|
|
681
817
|
"imagePreviewUrl": {},
|
|
682
818
|
"imagePreviews": {},
|
|
683
|
-
"openHistoryField": {}
|
|
819
|
+
"openHistoryField": {},
|
|
820
|
+
"canCreateMap": {},
|
|
821
|
+
"allowedTypesMap": {}
|
|
684
822
|
};
|
|
685
823
|
}
|
|
686
824
|
static get events() {
|
|
@@ -851,6 +989,21 @@ export class MrdLayoutSection {
|
|
|
851
989
|
"resolved": "{ name: string; nodeId: string; distinct: string; path: string; qs: string; }",
|
|
852
990
|
"references": {}
|
|
853
991
|
}
|
|
992
|
+
}, {
|
|
993
|
+
"method": "mrdViewCheckCapabilities",
|
|
994
|
+
"name": "mrdViewCheckCapabilities",
|
|
995
|
+
"bubbles": true,
|
|
996
|
+
"cancelable": true,
|
|
997
|
+
"composed": true,
|
|
998
|
+
"docs": {
|
|
999
|
+
"tags": [],
|
|
1000
|
+
"text": "Emitted once per VIEW/RELATED_VIEW binding \u2014 computed here directly, not relayed from a\nchild (see emitCapabilitiesChecks()), so it covers mrd-table, mrd-memo-container and\nmrd-document-container uniformly. `name` is the view key (viewKeyFor(item)) \u2014 pass it\nback to setViewCanCreate() to answer it. setViewCanCreate()'s optional third argument\nnarrows a table's `item.createTypes` picker to the concrete types the answer allows,\nwhen the API's capabilities response reports them (FINDING-0176 / TASK-0314)."
|
|
1001
|
+
},
|
|
1002
|
+
"complexType": {
|
|
1003
|
+
"original": "{ name: string; type: string; refType?: string; refId?: string; filterClass?: string }",
|
|
1004
|
+
"resolved": "{ name: string; type: string; refType?: string | undefined; refId?: string | undefined; filterClass?: string | undefined; }",
|
|
1005
|
+
"references": {}
|
|
1006
|
+
}
|
|
854
1007
|
}, {
|
|
855
1008
|
"method": "mrdUpdateObject",
|
|
856
1009
|
"name": "mrdUpdateObject",
|
|
@@ -1043,6 +1196,35 @@ export class MrdLayoutSection {
|
|
|
1043
1196
|
"tags": []
|
|
1044
1197
|
}
|
|
1045
1198
|
},
|
|
1199
|
+
"setViewCanCreate": {
|
|
1200
|
+
"complexType": {
|
|
1201
|
+
"signature": "(name: string, value: boolean, allowedTypes?: string[]) => Promise<void>",
|
|
1202
|
+
"parameters": [{
|
|
1203
|
+
"name": "name",
|
|
1204
|
+
"type": "string",
|
|
1205
|
+
"docs": ""
|
|
1206
|
+
}, {
|
|
1207
|
+
"name": "value",
|
|
1208
|
+
"type": "boolean",
|
|
1209
|
+
"docs": ""
|
|
1210
|
+
}, {
|
|
1211
|
+
"name": "allowedTypes",
|
|
1212
|
+
"type": "string[] | undefined",
|
|
1213
|
+
"docs": ""
|
|
1214
|
+
}],
|
|
1215
|
+
"references": {
|
|
1216
|
+
"Promise": {
|
|
1217
|
+
"location": "global",
|
|
1218
|
+
"id": "global::Promise"
|
|
1219
|
+
}
|
|
1220
|
+
},
|
|
1221
|
+
"return": "Promise<void>"
|
|
1222
|
+
},
|
|
1223
|
+
"docs": {
|
|
1224
|
+
"text": "Host answer to mrdViewCheckCapabilities \u2014 whether the current user may create a record\nfor the given view's bound route. `name` is the view key from the event detail. Stored in\ncanCreateMap and passed down as a plain prop to whichever body is mounted for that key\n(mrd-table, mrd-memo-container or mrd-document-container) \u2014 no DOM lookup needed, unlike\nsetViewPage/setViewAggregations, since the prop flows through the next render.",
|
|
1225
|
+
"tags": []
|
|
1226
|
+
}
|
|
1227
|
+
},
|
|
1046
1228
|
"setViewDistinct": {
|
|
1047
1229
|
"complexType": {
|
|
1048
1230
|
"signature": "(name: string, nodeId: string, values: DistinctValue[]) => Promise<void>",
|
|
@@ -1197,6 +1379,9 @@ export class MrdLayoutSection {
|
|
|
1197
1379
|
return [{
|
|
1198
1380
|
"propName": "data",
|
|
1199
1381
|
"methodName": "dataChanged"
|
|
1382
|
+
}, {
|
|
1383
|
+
"propName": "items",
|
|
1384
|
+
"methodName": "itemsChanged"
|
|
1200
1385
|
}];
|
|
1201
1386
|
}
|
|
1202
1387
|
}
|
|
@@ -53,6 +53,10 @@ export class MrdMemoContainer {
|
|
|
53
53
|
* tooltip, cards/rows are not clickable, and the embedded table's own
|
|
54
54
|
* create action is disabled too. */
|
|
55
55
|
this.readOnly = false;
|
|
56
|
+
/** Whether the current user may create a memo here — set by mrd-layout-section from its
|
|
57
|
+
* generic capability check (TASK-0299/FINDING-0155), the same answer the embedded table
|
|
58
|
+
* gets in table mode. Defaults to false (hidden) until confirmed, same as mrd-table. */
|
|
59
|
+
this.canCreate = false;
|
|
56
60
|
/** The active account's linked person record (userProfile.links.person), if any.
|
|
57
61
|
* Used both to gate "New memo" (see effectiveContainerHref) and, on submit, to
|
|
58
62
|
* fill the author slot. */
|
|
@@ -285,7 +289,7 @@ export class MrdMemoContainer {
|
|
|
285
289
|
* the dialog), so without it there is nothing valid to create — regardless
|
|
286
290
|
* of whether a parent record already supplies a container. */
|
|
287
291
|
get canAdd() {
|
|
288
|
-
return !this.readOnly && !!this.meHref() && !!this.effectiveContainerHref;
|
|
292
|
+
return this.canCreate && !this.readOnly && !!this.meHref() && !!this.effectiveContainerHref;
|
|
289
293
|
}
|
|
290
294
|
/** Path for creating a new memo: `/{dataClass}` for a top-level VIEW, or
|
|
291
295
|
* `/{fromClass}/{parentId}/{dataClass}` when nested under a parent record. */
|
|
@@ -299,7 +303,7 @@ export class MrdMemoContainer {
|
|
|
299
303
|
});
|
|
300
304
|
}
|
|
301
305
|
renderToolbar() {
|
|
302
|
-
return (h("div", { class: "mrd-memo-container__toolbar" }, this.mode === 'cards' && (h("button", { type: "button", class: "mrd-memo-container__action", disabled: !this.canAdd, title: this.readOnly ? t('readonly_access', this.locale) : undefined, onClick: this.openCreate }, h("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true" }, h("path", { d: "M12 5v14M5 12h14" })), t('memo_new', this.locale))), h("div", { class: "mrd-memo-container__seg", role: "group", "aria-label": t('doc_view_switch', this.locale) }, h("button", { class: "mrd-memo-container__seg-btn", "aria-pressed": String(this.mode === 'cards'), title: t('memo_view_cards', this.locale), "aria-label": t('memo_view_cards', this.locale), onClick: () => this.setMode('cards') }, h("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true" }, h("rect", { x: "3", y: "4", width: "7", height: "7", rx: "1" }), h("rect", { x: "14", y: "4", width: "7", height: "7", rx: "1" }), h("rect", { x: "3", y: "15", width: "7", height: "5", rx: "1" }), h("rect", { x: "14", y: "15", width: "7", height: "5", rx: "1" }))), h("button", { class: "mrd-memo-container__seg-btn", "aria-pressed": String(this.mode === 'table'), title: t('memo_view_table', this.locale), "aria-label": t('memo_view_table', this.locale), onClick: () => this.setMode('table') }, h("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true" }, h("path", { d: "M8 6h13M8 12h13M8 18h13M3 6h.01M3 12h.01M3 18h.01" }))))));
|
|
306
|
+
return (h("div", { class: "mrd-memo-container__toolbar" }, this.mode === 'cards' && this.canCreate && (h("button", { type: "button", class: "mrd-memo-container__action", disabled: !this.canAdd, title: this.readOnly ? t('readonly_access', this.locale) : undefined, onClick: this.openCreate }, h("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true" }, h("path", { d: "M12 5v14M5 12h14" })), t('memo_new', this.locale))), h("div", { class: "mrd-memo-container__seg", role: "group", "aria-label": t('doc_view_switch', this.locale) }, h("button", { class: "mrd-memo-container__seg-btn", "aria-pressed": String(this.mode === 'cards'), title: t('memo_view_cards', this.locale), "aria-label": t('memo_view_cards', this.locale), onClick: () => this.setMode('cards') }, h("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true" }, h("rect", { x: "3", y: "4", width: "7", height: "7", rx: "1" }), h("rect", { x: "14", y: "4", width: "7", height: "7", rx: "1" }), h("rect", { x: "3", y: "15", width: "7", height: "5", rx: "1" }), h("rect", { x: "14", y: "15", width: "7", height: "5", rx: "1" }))), h("button", { class: "mrd-memo-container__seg-btn", "aria-pressed": String(this.mode === 'table'), title: t('memo_view_table', this.locale), "aria-label": t('memo_view_table', this.locale), onClick: () => this.setMode('table') }, h("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true" }, h("path", { d: "M8 6h13M8 12h13M8 18h13M3 6h.01M3 12h.01M3 18h.01" }))))));
|
|
303
307
|
}
|
|
304
308
|
renderDeleteConfirm() {
|
|
305
309
|
return (h("div", null, h("h2", { class: "mrd-memo-container__modal-title" }, t('memo_delete_confirm_title', this.locale)), h("p", { class: "mrd-memo-container__modal-warning" }, t('memo_delete_confirm_body', this.locale)), h("div", { class: "mrd-memo-container__modal-actions" }, h("button", { type: "button", class: "mrd-memo-container__modal-cancel", onClick: this.cancelDeleteConfirm }, t('cancel', this.locale)), h("button", { type: "button", class: "mrd-memo-container__modal-delete-confirm", onClick: this.confirmDelete }, t('delete', this.locale)))));
|
|
@@ -336,7 +340,7 @@ export class MrdMemoContainer {
|
|
|
336
340
|
} }));
|
|
337
341
|
}
|
|
338
342
|
renderTable() {
|
|
339
|
-
return (h("mrd-table", { "data-view": this.viewKey, ref: el => (this.tableEl = el), item: this.item, parentId: this.parentId, locale: this.locale, readOnly: this.readOnly, onMrdLoadPage: (e) => {
|
|
343
|
+
return (h("mrd-table", { "data-view": this.viewKey, ref: el => (this.tableEl = el), item: this.item, parentId: this.parentId, locale: this.locale, readOnly: this.readOnly, canCreate: this.canCreate, onMrdLoadPage: (e) => {
|
|
340
344
|
e.stopPropagation();
|
|
341
345
|
this.mrdLoadPage.emit(e.detail);
|
|
342
346
|
}, onMrdLoadAggregations: (e) => {
|
|
@@ -351,7 +355,7 @@ export class MrdMemoContainer {
|
|
|
351
355
|
} }));
|
|
352
356
|
}
|
|
353
357
|
render() {
|
|
354
|
-
return (h(Host, { key: '
|
|
358
|
+
return (h(Host, { key: 'b0479aad6dc49935442183fcbdf30c07c2c490ff' }, this.renderToolbar(), h("div", { key: '40d0fb882186001ad4984c1ba64c5a5c529f4d76', class: "mrd-memo-container__body" }, this.mode === 'cards' ? this.renderCards() : this.renderTable()), this.renderDialog()));
|
|
355
359
|
}
|
|
356
360
|
static get is() { return "mrd-memo-container"; }
|
|
357
361
|
static get encapsulation() { return "scoped"; }
|
|
@@ -581,6 +585,26 @@ export class MrdMemoContainer {
|
|
|
581
585
|
"attribute": "read-only",
|
|
582
586
|
"defaultValue": "false"
|
|
583
587
|
},
|
|
588
|
+
"canCreate": {
|
|
589
|
+
"type": "boolean",
|
|
590
|
+
"mutable": false,
|
|
591
|
+
"complexType": {
|
|
592
|
+
"original": "boolean",
|
|
593
|
+
"resolved": "boolean",
|
|
594
|
+
"references": {}
|
|
595
|
+
},
|
|
596
|
+
"required": false,
|
|
597
|
+
"optional": false,
|
|
598
|
+
"docs": {
|
|
599
|
+
"tags": [],
|
|
600
|
+
"text": "Whether the current user may create a memo here \u2014 set by mrd-layout-section from its\ngeneric capability check (TASK-0299/FINDING-0155), the same answer the embedded table\ngets in table mode. Defaults to false (hidden) until confirmed, same as mrd-table."
|
|
601
|
+
},
|
|
602
|
+
"getter": false,
|
|
603
|
+
"setter": false,
|
|
604
|
+
"reflect": false,
|
|
605
|
+
"attribute": "can-create",
|
|
606
|
+
"defaultValue": "false"
|
|
607
|
+
},
|
|
584
608
|
"me": {
|
|
585
609
|
"type": "unknown",
|
|
586
610
|
"mutable": false,
|