@mmlogic/components 0.3.8 → 0.3.9
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/index.cjs.js +13 -0
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/mosterdcomponents.cjs.js +1 -1
- package/dist/cjs/{mrd-boolean-field_20.cjs.entry.js → mrd-boolean-field_22.cjs.entry.js} +504 -23
- package/dist/collection/collection-manifest.json +2 -0
- package/dist/collection/components/mrd-boolean-field/mrd-boolean-field.js +1 -1
- package/dist/collection/components/mrd-currency-field/mrd-currency-field.js +1 -1
- package/dist/collection/components/mrd-date-field/mrd-date-field.js +1 -1
- package/dist/collection/components/mrd-datetime-field/mrd-datetime-field.js +1 -1
- package/dist/collection/components/mrd-document-list/mrd-document-list.js +578 -0
- package/dist/collection/components/mrd-document-list/mrd-document-list.scss +126 -0
- package/dist/collection/components/mrd-document-view/mrd-document-view.js +177 -0
- package/dist/collection/components/mrd-document-view/mrd-document-view.scss +121 -0
- package/dist/collection/components/mrd-email-field/mrd-email-field.js +1 -1
- package/dist/collection/components/mrd-file-field/mrd-file-field.js +1 -1
- package/dist/collection/components/mrd-image-field/mrd-image-field.js +1 -1
- package/dist/collection/components/mrd-layout-section/mrd-layout-section.js +153 -15
- package/dist/collection/components/mrd-layout-section/mrd-layout-section.scss +46 -3
- package/dist/collection/components/mrd-longtext-field/mrd-longtext-field.js +1 -1
- package/dist/collection/components/mrd-number-field/mrd-number-field.js +1 -1
- package/dist/collection/components/mrd-secret-field/mrd-secret-field.js +2 -2
- package/dist/collection/components/mrd-text-field/mrd-text-field.js +1 -1
- package/dist/collection/components/mrd-textarea-field/mrd-textarea-field.js +1 -1
- package/dist/collection/components/mrd-time-field/mrd-time-field.js +1 -1
- package/dist/collection/dev/app.js +19 -2
- package/dist/collection/types/client-layout.js +10 -0
- package/dist/collection/utils/i18n.js +24 -0
- package/dist/components/client-layout.js +1 -1
- package/dist/components/format.js +1 -1
- package/dist/components/i18n.js +1 -1
- package/dist/components/index.js +1 -1
- package/dist/components/mrd-boolean-field2.js +1 -1
- package/dist/components/mrd-currency-field2.js +1 -1
- package/dist/components/mrd-date-field2.js +1 -1
- package/dist/components/mrd-datetime-field2.js +1 -1
- package/dist/components/mrd-document-list.d.ts +11 -0
- package/dist/components/mrd-document-list.js +1 -0
- package/dist/components/mrd-document-list2.js +1 -0
- package/dist/components/mrd-document-view.d.ts +11 -0
- package/dist/components/mrd-document-view.js +1 -0
- package/dist/components/mrd-document-view2.js +1 -0
- package/dist/components/mrd-email-field2.js +1 -1
- package/dist/components/mrd-file-field2.js +1 -1
- package/dist/components/mrd-image-field2.js +1 -1
- package/dist/components/mrd-layout-section.js +1 -1
- package/dist/components/mrd-longtext-field2.js +1 -1
- package/dist/components/mrd-number-field2.js +1 -1
- package/dist/components/mrd-secret-field2.js +1 -1
- package/dist/components/mrd-table2.js +1 -1
- package/dist/components/mrd-text-field2.js +1 -1
- package/dist/components/mrd-textarea-field2.js +1 -1
- package/dist/components/mrd-time-field2.js +1 -1
- package/dist/esm/index.js +11 -1
- package/dist/esm/loader.js +1 -1
- package/dist/esm/mosterdcomponents.js +1 -1
- package/dist/esm/{mrd-boolean-field_20.entry.js → mrd-boolean-field_22.entry.js} +504 -25
- package/dist/mosterdcomponents/index.esm.js +1 -1
- package/dist/mosterdcomponents/mosterdcomponents.css +1 -1
- package/dist/mosterdcomponents/mosterdcomponents.esm.js +1 -1
- package/dist/mosterdcomponents/p-b547291b.entry.js +1 -0
- package/dist/types/components/mrd-document-list/mrd-document-list.d.ts +108 -0
- package/dist/types/components/mrd-document-view/mrd-document-view.d.ts +36 -0
- package/dist/types/components/mrd-layout-section/mrd-layout-section.d.ts +33 -6
- package/dist/types/components.d.ts +290 -15
- package/dist/types/types/client-layout.d.ts +38 -0
- package/package.json +1 -1
- package/dist/mosterdcomponents/cell-renderer-CbRwLOo8.js.map +0 -1
- package/dist/mosterdcomponents/client-layout-D88nn5zf.js.map +0 -1
- package/dist/mosterdcomponents/format-BAfsQfy1.js.map +0 -1
- package/dist/mosterdcomponents/i18n-hoGGKbKU.js.map +0 -1
- package/dist/mosterdcomponents/index-6yQUNVww.js.map +0 -1
- package/dist/mosterdcomponents/index-I5SuYv7a.js.map +0 -1
- package/dist/mosterdcomponents/index.esm.js.map +0 -1
- package/dist/mosterdcomponents/mosterdcomponents.esm.js.map +0 -1
- package/dist/mosterdcomponents/p-7bfaee51.entry.js +0 -1
- package/dist/mosterdcomponents/quill-C9pgw_k-.js.map +0 -1
- package/dist/mosterdcomponents/validation-ixb43cqU.js.map +0 -1
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"entries": [
|
|
3
|
+
"components/mrd-document-list/mrd-document-list.js",
|
|
3
4
|
"components/mrd-boolean-field/mrd-boolean-field.js",
|
|
4
5
|
"components/mrd-currency-field/mrd-currency-field.js",
|
|
5
6
|
"components/mrd-date-field/mrd-date-field.js",
|
|
6
7
|
"components/mrd-datetime-field/mrd-datetime-field.js",
|
|
8
|
+
"components/mrd-document-view/mrd-document-view.js",
|
|
7
9
|
"components/mrd-email-field/mrd-email-field.js",
|
|
8
10
|
"components/mrd-field/mrd-field.js",
|
|
9
11
|
"components/mrd-file-field/mrd-file-field.js",
|
|
@@ -20,7 +20,7 @@ export class MrdBooleanField {
|
|
|
20
20
|
this.checked = !!this.value;
|
|
21
21
|
}
|
|
22
22
|
render() {
|
|
23
|
-
return (h(Host, { key: '
|
|
23
|
+
return (h(Host, { key: '38e65a1c7971912f8259d09281b272d7cbd446f2' }, h("div", { key: 'e10919998731d744cc2a13130c5f355c9b8fc9aa', class: "mrd-boolean-field" }, h("label", { key: 'db85a2c80cc62fdfd25237e3f5c7750bf1666819', class: "mrd-boolean-field__toggle-label" }, h("input", { key: 'cddd7004593fa4671abb89f4f805c4a009db99ef', class: "mrd-boolean-field__checkbox", type: "checkbox", name: this.name, checked: this.checked, disabled: this.disabled, onChange: this.handleChange, onBlur: this.handleBlur }), h("span", { key: 'f90f0ed6d74d6688e51b8d85a5397a0597d95ad8', class: "mrd-boolean-field__toggle", "aria-hidden": "true" }), this.label && (h("span", { key: '7e4582b1d9a5b08c00c220bec53baa6c14cbfe43', class: `mrd-boolean-field__text${this.required ? ' mrd-boolean-field__text--required' : ''}` }, this.label))))));
|
|
24
24
|
}
|
|
25
25
|
static get is() { return "mrd-boolean-field"; }
|
|
26
26
|
static get encapsulation() { return "scoped"; }
|
|
@@ -48,7 +48,7 @@ export class MrdCurrencyField {
|
|
|
48
48
|
}
|
|
49
49
|
render() {
|
|
50
50
|
const hasError = !!this.error;
|
|
51
|
-
return (h(Host, { key: '
|
|
51
|
+
return (h(Host, { key: 'fe3520c44d831caf36b388cb5968a9518b16cb8b' }, h("div", { key: '50c1fd2d53038e46da575d3e46e1ec26c2da423b', class: "mrd-currency-field" }, this.label && (h("label", { key: 'a2649d41bf6e3765c8a62ba6559c64c41615027a', class: `mrd-currency-field__label${this.required ? ' mrd-currency-field__label--required' : ''}` }, this.label)), h("div", { key: '952b51f315b4a5c05a8373ce3a3f1041086ba8b8', class: "mrd-currency-field__row" }, h("input", { key: '137a72ffc5d79fc8e0a8cf44c012d84a50c26d5b', class: `mrd-currency-field__amount${hasError ? ' mrd-currency-field__amount--error' : ''}`, type: "text", inputMode: "decimal", name: `${this.name}_amount`, value: this.amountDisplay, placeholder: "0.00", required: this.required, disabled: this.disabled, onInput: this.handleAmountInput, onBlur: this.handleAmountBlur }), h("select", { key: '1755854ca9b76dc4b41ad84b6b788685931ace36', class: "mrd-currency-field__currency", disabled: this.disabled, onChange: this.handleCurrencyChange }, COMMON_CURRENCIES.map(c => (h("option", { key: c, value: c, selected: c === this.currency }, c))))), hasError && h("span", { key: '0f10eb98c2e6444651d79d1de92acd0dbcc7133b', class: "mrd-currency-field__error" }, this.error))));
|
|
52
52
|
}
|
|
53
53
|
static get is() { return "mrd-currency-field"; }
|
|
54
54
|
static get encapsulation() { return "scoped"; }
|
|
@@ -27,7 +27,7 @@ export class MrdDateField {
|
|
|
27
27
|
}
|
|
28
28
|
render() {
|
|
29
29
|
const hasError = !!this.error;
|
|
30
|
-
return (h(Host, { key: '
|
|
30
|
+
return (h(Host, { key: '2c0dc2311068a5c759fe8efe58a98a71a9cf4b7b' }, h("div", { key: 'ee1cc0e9a2943cc42439825b8f21cd3492eaca05', class: "mrd-date-field" }, this.label && (h("label", { key: '3f836a991e676b6070a8b3800edfce00cc0d3b3d', class: `mrd-date-field__label${this.required ? ' mrd-date-field__label--required' : ''}` }, this.label)), h("input", { key: '575185661987eea3dc91950f51995b2cc75debea', class: `mrd-date-field__input${hasError ? ' mrd-date-field__input--error' : ''}`, type: "date", name: this.name, value: this.value, required: this.required, disabled: this.disabled, onChange: this.handleChange, onBlur: this.handleBlur }), hasError && h("span", { key: '480ec99200989f3dc543d9afc648d83d31992b3c', class: "mrd-date-field__error" }, this.error))));
|
|
31
31
|
}
|
|
32
32
|
static get is() { return "mrd-date-field"; }
|
|
33
33
|
static get encapsulation() { return "scoped"; }
|
|
@@ -54,7 +54,7 @@ export class MrdDatetimeField {
|
|
|
54
54
|
}
|
|
55
55
|
render() {
|
|
56
56
|
const hasError = !!this.error;
|
|
57
|
-
return (h(Host, { key: '
|
|
57
|
+
return (h(Host, { key: 'ea8b3b68100ffdb316bc5048f82d85d238bb2e4b' }, h("div", { key: 'c192c6998ee474aaf4df7b3b97ae0bd61f6d624d', class: "mrd-datetime-field" }, this.label && (h("label", { key: '1fbd66c17d76508f0d698a2c258be6779e98d85e', class: `mrd-datetime-field__label${this.required ? ' mrd-datetime-field__label--required' : ''}` }, this.label)), h("input", { key: 'fc9612c062a1cab5076a06598cabf227adce996c', class: `mrd-datetime-field__input${hasError ? ' mrd-datetime-field__input--error' : ''}`, type: "datetime-local", name: this.name, value: this.localValue, required: this.required, disabled: this.disabled, onChange: this.handleChange, onBlur: this.handleBlur }), hasError && h("span", { key: '8788ac01739302f6ad61010b238ff38d45e1b68a', class: "mrd-datetime-field__error" }, this.error))));
|
|
58
58
|
}
|
|
59
59
|
static get is() { return "mrd-datetime-field"; }
|
|
60
60
|
static get encapsulation() { return "scoped"; }
|
|
@@ -0,0 +1,578 @@
|
|
|
1
|
+
import { Host, h } from "@stencil/core";
|
|
2
|
+
import { ClientLayoutItemType } from "../../types/client-layout";
|
|
3
|
+
import { t } from "../../utils/i18n";
|
|
4
|
+
import { formatDate } from "../../utils/format";
|
|
5
|
+
/**
|
|
6
|
+
* Archetype-driven document collection view. Renders documents as a lazy,
|
|
7
|
+
* file-explorer-style folder tree, grouped by the `commons.document` archetype's
|
|
8
|
+
* `container` (dossier, the top folder) and `folder` (a path string like
|
|
9
|
+
* `/draft documents/may 2020`, the sub-path beneath it).
|
|
10
|
+
*
|
|
11
|
+
* Loading is lazy per level, mirroring the /distinct endpoint (FINDING-0106):
|
|
12
|
+
* - on load → `mrdLoadDistinct` for the `container` relation → top folders;
|
|
13
|
+
* - on expanding a container → `mrdLoadDistinct` for the `folder` field, filtered
|
|
14
|
+
* by `{containerField}_href` → all folder path strings for that container
|
|
15
|
+
* (the client splits them on `/` and builds the sub-tree locally);
|
|
16
|
+
* - on expanding a node that holds documents → `mrdLoadPage` (a plain filtered list
|
|
17
|
+
* load, the same one a table page uses), filtered by container + exact folder string.
|
|
18
|
+
*
|
|
19
|
+
* When exactly one container exists (e.g. a dossier detail page) the container
|
|
20
|
+
* level is hidden and its folder tree is shown directly at the root.
|
|
21
|
+
*/
|
|
22
|
+
export class MrdDocumentList {
|
|
23
|
+
constructor() {
|
|
24
|
+
/** The VIEW or RELATED_VIEW layout item (dataClass, fromClass, view config). */
|
|
25
|
+
this.item = null;
|
|
26
|
+
/** Parent record id — required for RELATED_VIEW path building. */
|
|
27
|
+
this.parentId = '';
|
|
28
|
+
this.locale = navigator.language;
|
|
29
|
+
this.containers = [];
|
|
30
|
+
this.rootLoading = true;
|
|
31
|
+
/** True when the single-container level is collapsed away (dossier context). */
|
|
32
|
+
this.singleContainer = false;
|
|
33
|
+
this.nodeIndex = new Map();
|
|
34
|
+
}
|
|
35
|
+
componentDidLoad() {
|
|
36
|
+
this.emitContainerDistinct();
|
|
37
|
+
}
|
|
38
|
+
// ── Slot field names ─────────────────────────────────────────────────────
|
|
39
|
+
get containerField() {
|
|
40
|
+
var _a, _b, _c;
|
|
41
|
+
return (_c = (_b = (_a = this.archetype) === null || _a === void 0 ? void 0 : _a.slots) === null || _b === void 0 ? void 0 : _b.container) !== null && _c !== void 0 ? _c : 'container';
|
|
42
|
+
}
|
|
43
|
+
get folderField() {
|
|
44
|
+
var _a, _b, _c;
|
|
45
|
+
return (_c = (_b = (_a = this.archetype) === null || _a === void 0 ? void 0 : _a.slots) === null || _b === void 0 ? void 0 : _b.folder) !== null && _c !== void 0 ? _c : 'folder';
|
|
46
|
+
}
|
|
47
|
+
get titleField() {
|
|
48
|
+
var _a, _b, _c;
|
|
49
|
+
return (_c = (_b = (_a = this.archetype) === null || _a === void 0 ? void 0 : _a.slots) === null || _b === void 0 ? void 0 : _b.title) !== null && _c !== void 0 ? _c : 'name';
|
|
50
|
+
}
|
|
51
|
+
get dateField() {
|
|
52
|
+
var _a, _b;
|
|
53
|
+
return (_b = (_a = this.archetype) === null || _a === void 0 ? void 0 : _a.slots) === null || _b === void 0 ? void 0 : _b.date;
|
|
54
|
+
}
|
|
55
|
+
// ── Path / query building (mirrors mrd-table conventions) ────────────────
|
|
56
|
+
/** VIEW: `/{dataClass}`; RELATED_VIEW: `/{fromClass}/{parentId}/{dataClass}`. */
|
|
57
|
+
buildDataPath() {
|
|
58
|
+
var _a, _b, _c;
|
|
59
|
+
const it = this.item;
|
|
60
|
+
const dataClass = (_b = (_a = it === null || it === void 0 ? void 0 : it.dataClass) !== null && _a !== void 0 ? _a : it === null || it === void 0 ? void 0 : it.relatedClass) !== null && _b !== void 0 ? _b : '';
|
|
61
|
+
if ((it === null || it === void 0 ? void 0 : it.type) === ClientLayoutItemType.RELATED_VIEW) {
|
|
62
|
+
return `/${(_c = it.fromClass) !== null && _c !== void 0 ? _c : ''}/${this.parentId}/${dataClass}`;
|
|
63
|
+
}
|
|
64
|
+
return `/${dataClass}`;
|
|
65
|
+
}
|
|
66
|
+
/** View-level static filters + filterClass, shared by every request. */
|
|
67
|
+
baseParams() {
|
|
68
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
69
|
+
const p = new URLSearchParams();
|
|
70
|
+
const filterClass = (_a = this.item) === null || _a === void 0 ? void 0 : _a.filterClass;
|
|
71
|
+
if (filterClass)
|
|
72
|
+
p.set('type', filterClass);
|
|
73
|
+
for (const f of ((_d = (_c = (_b = this.item) === null || _b === void 0 ? void 0 : _b.view) === null || _c === void 0 ? void 0 : _c.filter) !== null && _d !== void 0 ? _d : [])) {
|
|
74
|
+
if (!f.name)
|
|
75
|
+
continue;
|
|
76
|
+
if (f.operator === 'EMPTY') {
|
|
77
|
+
p.set(f.name, '');
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
if (f.operator === 'NOT_EMPTY') {
|
|
81
|
+
p.set(f.name + '_notempty', 'true');
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
if (f.operator === 'STARTS_WITH') {
|
|
85
|
+
p.set(f.name + '_startswith', String((_e = f.value) !== null && _e !== void 0 ? _e : ''));
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
if (f.operator === 'FROM') {
|
|
89
|
+
p.set(f.name + '_from', String((_f = f.value) !== null && _f !== void 0 ? _f : ''));
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
if (f.operator === 'TO') {
|
|
93
|
+
p.set(f.name + '_to', String((_g = f.value) !== null && _g !== void 0 ? _g : ''));
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
if (f.value != null) {
|
|
97
|
+
p.set(f.name, String(f.value));
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return p;
|
|
101
|
+
}
|
|
102
|
+
emitContainerDistinct() {
|
|
103
|
+
const p = this.baseParams();
|
|
104
|
+
p.set('distinct', this.containerField);
|
|
105
|
+
this.mrdLoadDistinct.emit({
|
|
106
|
+
nodeId: MrdDocumentList.ROOT,
|
|
107
|
+
distinct: this.containerField,
|
|
108
|
+
path: this.buildDataPath() + '/distinct',
|
|
109
|
+
qs: p.toString(),
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
emitFolderDistinct(container) {
|
|
113
|
+
var _a;
|
|
114
|
+
const p = this.baseParams();
|
|
115
|
+
p.set('distinct', this.folderField);
|
|
116
|
+
p.set(this.containerField + '_href', (_a = container.href) !== null && _a !== void 0 ? _a : '');
|
|
117
|
+
container.loading = true;
|
|
118
|
+
this.mrdLoadDistinct.emit({
|
|
119
|
+
nodeId: container.id,
|
|
120
|
+
distinct: this.folderField,
|
|
121
|
+
path: this.buildDataPath() + '/distinct',
|
|
122
|
+
qs: p.toString(),
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
emitDocuments(container, node) {
|
|
126
|
+
var _a, _b;
|
|
127
|
+
const p = this.baseParams();
|
|
128
|
+
p.set(this.containerField + '_href', (_a = container.href) !== null && _a !== void 0 ? _a : '');
|
|
129
|
+
p.set(this.folderField, (_b = node.fullPath) !== null && _b !== void 0 ? _b : '');
|
|
130
|
+
node.loading = true;
|
|
131
|
+
this.mrdLoadPage.emit({
|
|
132
|
+
nodeId: node.id,
|
|
133
|
+
page: 0,
|
|
134
|
+
sort: '',
|
|
135
|
+
path: this.buildDataPath(),
|
|
136
|
+
qs: p.toString(),
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
// ── Public injection API ─────────────────────────────────────────────────
|
|
140
|
+
/** Inject distinct values for a node. `nodeId` is the sentinel root (containers)
|
|
141
|
+
* or a container node id (folders). */
|
|
142
|
+
async setDistinct(nodeId, values) {
|
|
143
|
+
if (nodeId === MrdDocumentList.ROOT) {
|
|
144
|
+
this.applyContainers(values);
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
this.applyFolders(nodeId, values);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/** Inject the documents loaded for one folder node. */
|
|
151
|
+
async setDocuments(nodeId, docs) {
|
|
152
|
+
const node = this.nodeIndex.get(nodeId);
|
|
153
|
+
if (!node)
|
|
154
|
+
return;
|
|
155
|
+
node.docs = docs !== null && docs !== void 0 ? docs : [];
|
|
156
|
+
node.docsLoaded = true;
|
|
157
|
+
node.loading = false;
|
|
158
|
+
this.bump();
|
|
159
|
+
}
|
|
160
|
+
applyContainers(values) {
|
|
161
|
+
const nodes = [];
|
|
162
|
+
for (const v of values) {
|
|
163
|
+
if (!v.value || typeof v.value !== 'object')
|
|
164
|
+
continue;
|
|
165
|
+
const href = v.value.href;
|
|
166
|
+
const node = this.makeContainerNode(href, v.value.name, v.count);
|
|
167
|
+
nodes.push(node);
|
|
168
|
+
this.nodeIndex.set(node.id, node);
|
|
169
|
+
}
|
|
170
|
+
this.containers = nodes;
|
|
171
|
+
this.rootLoading = false;
|
|
172
|
+
this.singleContainer = nodes.length === 1;
|
|
173
|
+
// Single container (dossier context): collapse the level away, load its folders now.
|
|
174
|
+
if (this.singleContainer) {
|
|
175
|
+
const only = nodes[0];
|
|
176
|
+
only.open = true;
|
|
177
|
+
this.emitFolderDistinct(only);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
applyFolders(containerId, values) {
|
|
181
|
+
const container = this.nodeIndex.get(containerId);
|
|
182
|
+
if (!container)
|
|
183
|
+
return;
|
|
184
|
+
container.children = [];
|
|
185
|
+
container.hasDocs = false;
|
|
186
|
+
container.docCount = 0;
|
|
187
|
+
for (const v of values) {
|
|
188
|
+
const raw = typeof v.value === 'string' ? v.value : v.value == null ? '' : String(v.value);
|
|
189
|
+
const segs = this.splitFolder(raw);
|
|
190
|
+
if (segs.length === 0) {
|
|
191
|
+
// Root documents — the container's own direct documents.
|
|
192
|
+
container.hasDocs = true;
|
|
193
|
+
container.docCount = v.count;
|
|
194
|
+
container.fullPath = raw;
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
let node = container;
|
|
198
|
+
const acc = [];
|
|
199
|
+
for (const seg of segs) {
|
|
200
|
+
acc.push(seg);
|
|
201
|
+
let child = node.children.find(c => c.label === seg);
|
|
202
|
+
if (!child) {
|
|
203
|
+
child = this.makeFolderNode(container.id + '/' + acc.join('/'), seg);
|
|
204
|
+
node.children.push(child);
|
|
205
|
+
this.nodeIndex.set(child.id, child);
|
|
206
|
+
}
|
|
207
|
+
node = child;
|
|
208
|
+
}
|
|
209
|
+
node.hasDocs = true;
|
|
210
|
+
node.docCount = v.count;
|
|
211
|
+
node.fullPath = raw;
|
|
212
|
+
}
|
|
213
|
+
this.computeTotals(container);
|
|
214
|
+
container.foldersLoaded = true;
|
|
215
|
+
container.loading = false;
|
|
216
|
+
// If the container has root documents, load them now (they show inline on expand).
|
|
217
|
+
if (container.hasDocs && !container.docsLoaded) {
|
|
218
|
+
this.emitDocuments(container, container);
|
|
219
|
+
}
|
|
220
|
+
this.bump();
|
|
221
|
+
}
|
|
222
|
+
// ── Tree helpers ─────────────────────────────────────────────────────────
|
|
223
|
+
/** Normalise a folder path: null/""/"/" → root ([]); else split on "/" dropping empties. */
|
|
224
|
+
splitFolder(path) {
|
|
225
|
+
if (path == null)
|
|
226
|
+
return [];
|
|
227
|
+
const s = String(path).trim();
|
|
228
|
+
if (s === '' || s === '/')
|
|
229
|
+
return [];
|
|
230
|
+
return s.split('/').map(x => x.trim()).filter(Boolean);
|
|
231
|
+
}
|
|
232
|
+
makeContainerNode(href, label, count) {
|
|
233
|
+
return {
|
|
234
|
+
id: 'c:' + href, kind: 'container', label, href,
|
|
235
|
+
hasDocs: false, docCount: 0, totalCount: count, children: [],
|
|
236
|
+
open: false, loading: false, foldersLoaded: false, docsLoaded: false, docs: [],
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
makeFolderNode(id, label) {
|
|
240
|
+
return {
|
|
241
|
+
id, kind: 'folder', label,
|
|
242
|
+
hasDocs: false, docCount: 0, totalCount: 0, children: [],
|
|
243
|
+
open: false, loading: false, foldersLoaded: false, docsLoaded: false, docs: [],
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
computeTotals(node) {
|
|
247
|
+
let total = node.docCount;
|
|
248
|
+
for (const c of node.children)
|
|
249
|
+
total += this.computeTotals(c);
|
|
250
|
+
node.totalCount = total;
|
|
251
|
+
return total;
|
|
252
|
+
}
|
|
253
|
+
/** Force a re-render after mutating nodes in place. */
|
|
254
|
+
bump() {
|
|
255
|
+
this.containers = [...this.containers];
|
|
256
|
+
}
|
|
257
|
+
// ── Interaction ──────────────────────────────────────────────────────────
|
|
258
|
+
toggleContainer(node) {
|
|
259
|
+
node.open = !node.open;
|
|
260
|
+
if (node.open && !node.foldersLoaded && !node.loading) {
|
|
261
|
+
this.emitFolderDistinct(node);
|
|
262
|
+
}
|
|
263
|
+
this.bump();
|
|
264
|
+
}
|
|
265
|
+
toggleFolder(container, node) {
|
|
266
|
+
node.open = !node.open;
|
|
267
|
+
if (node.open && node.hasDocs && !node.docsLoaded && !node.loading) {
|
|
268
|
+
this.emitDocuments(container, node);
|
|
269
|
+
}
|
|
270
|
+
this.bump();
|
|
271
|
+
}
|
|
272
|
+
openDoc(doc) {
|
|
273
|
+
var _a, _b, _c, _d;
|
|
274
|
+
const href = (_b = (_a = doc === null || doc === void 0 ? void 0 : doc._links) === null || _a === void 0 ? void 0 : _a.self) === null || _b === void 0 ? void 0 : _b.href;
|
|
275
|
+
const label = (_d = (_c = doc === null || doc === void 0 ? void 0 : doc[this.titleField]) !== null && _c !== void 0 ? _c : doc === null || doc === void 0 ? void 0 : doc.name) !== null && _d !== void 0 ? _d : '';
|
|
276
|
+
this.mrdNavigate.emit({ href, label });
|
|
277
|
+
}
|
|
278
|
+
// ── Render ───────────────────────────────────────────────────────────────
|
|
279
|
+
renderChevron(open, leaf) {
|
|
280
|
+
return (h("span", { class: `mrd-document-list__chev${leaf ? ' mrd-document-list__chev--leaf' : ''}${open ? ' mrd-document-list__chev--open' : ''}` }, 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: "M9 6l6 6-6 6" }))));
|
|
281
|
+
}
|
|
282
|
+
renderDossierIcon() {
|
|
283
|
+
return (h("svg", { class: "mrd-document-list__icon mrd-document-list__icon--dossier", 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" })));
|
|
284
|
+
}
|
|
285
|
+
renderFolderIcon() {
|
|
286
|
+
return (h("svg", { class: "mrd-document-list__icon mrd-document-list__icon--folder", 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" })));
|
|
287
|
+
}
|
|
288
|
+
renderDocIcon() {
|
|
289
|
+
return (h("svg", { class: "mrd-document-list__icon mrd-document-list__icon--doc", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true" }, h("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }), h("path", { d: "M14 2v6h6" })));
|
|
290
|
+
}
|
|
291
|
+
indent(depth) {
|
|
292
|
+
return h("span", { class: "mrd-document-list__indent", style: { width: `${depth * 18}px` } });
|
|
293
|
+
}
|
|
294
|
+
renderDocRow(doc, depth) {
|
|
295
|
+
var _a, _b, _c, _d, _e;
|
|
296
|
+
const label = (_b = (_a = doc === null || doc === void 0 ? void 0 : doc[this.titleField]) !== null && _a !== void 0 ? _a : doc === null || doc === void 0 ? void 0 : doc.name) !== null && _b !== void 0 ? _b : '';
|
|
297
|
+
const dateRaw = this.dateField ? doc === null || doc === void 0 ? void 0 : doc[this.dateField] : undefined;
|
|
298
|
+
const date = dateRaw ? formatDate(dateRaw, this.locale) : '';
|
|
299
|
+
return (h("div", { class: "mrd-document-list__row mrd-document-list__row--doc", key: (_e = (_d = (_c = doc === null || doc === void 0 ? void 0 : doc._links) === null || _c === void 0 ? void 0 : _c.self) === null || _d === void 0 ? void 0 : _d.href) !== null && _e !== void 0 ? _e : label, onClick: () => this.openDoc(doc) }, this.indent(depth), this.renderChevron(false, true), this.renderDocIcon(), h("span", { class: "mrd-document-list__label" }, label), date && h("span", { class: "mrd-document-list__date" }, date)));
|
|
300
|
+
}
|
|
301
|
+
renderLoadingRow(depth) {
|
|
302
|
+
return (h("div", { class: "mrd-document-list__loading", key: "loading" }, this.indent(depth), h("span", { class: "mrd-document-list__spinner" }), t('loading', this.locale)));
|
|
303
|
+
}
|
|
304
|
+
renderChildren(container, node, depth) {
|
|
305
|
+
const out = [];
|
|
306
|
+
// Direct documents of this node (root docs live on the container node).
|
|
307
|
+
if (node.hasDocs) {
|
|
308
|
+
if (node.docsLoaded) {
|
|
309
|
+
for (const doc of node.docs)
|
|
310
|
+
out.push(this.renderDocRow(doc, depth));
|
|
311
|
+
}
|
|
312
|
+
else if (node.loading) {
|
|
313
|
+
out.push(this.renderLoadingRow(depth));
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
// Child folders.
|
|
317
|
+
for (const child of node.children) {
|
|
318
|
+
out.push(this.renderFolderNode(container, child, depth));
|
|
319
|
+
}
|
|
320
|
+
return out;
|
|
321
|
+
}
|
|
322
|
+
renderFolderNode(container, node, depth) {
|
|
323
|
+
const leaf = node.children.length === 0 && !node.hasDocs;
|
|
324
|
+
return (h("div", { class: "mrd-document-list__node", key: node.id }, h("div", { class: "mrd-document-list__row", onClick: () => this.toggleFolder(container, node) }, this.indent(depth), this.renderChevron(node.open, leaf), this.renderFolderIcon(), h("span", { class: "mrd-document-list__label" }, node.label), h("span", { class: "mrd-document-list__count" }, node.totalCount)), node.open && h("div", { class: "mrd-document-list__kids" }, this.renderChildren(container, node, depth + 1))));
|
|
325
|
+
}
|
|
326
|
+
renderContainerNode(node, depth) {
|
|
327
|
+
return (h("div", { class: "mrd-document-list__node", key: node.id }, h("div", { class: "mrd-document-list__row mrd-document-list__row--dossier", onClick: () => this.toggleContainer(node) }, this.indent(depth), this.renderChevron(node.open, false), this.renderDossierIcon(), h("span", { class: "mrd-document-list__label" }, node.label), h("span", { class: "mrd-document-list__count" }, node.totalCount)), node.open && (h("div", { class: "mrd-document-list__kids" }, node.loading && !node.foldersLoaded
|
|
328
|
+
? this.renderLoadingRow(depth + 1)
|
|
329
|
+
: this.renderChildren(node, node, depth + 1)))));
|
|
330
|
+
}
|
|
331
|
+
render() {
|
|
332
|
+
let body;
|
|
333
|
+
if (this.rootLoading) {
|
|
334
|
+
body = this.renderLoadingRow(0);
|
|
335
|
+
}
|
|
336
|
+
else if (this.containers.length === 0) {
|
|
337
|
+
body = h("div", { key: '0c4190bb86543e2d37cc1584b3495eb6eab5664c', class: "mrd-document-list__empty" }, t('no_results', this.locale));
|
|
338
|
+
}
|
|
339
|
+
else if (this.singleContainer) {
|
|
340
|
+
// Dossier context: render the single container's folder tree at the root.
|
|
341
|
+
const only = this.containers[0];
|
|
342
|
+
body = only.loading && !only.foldersLoaded
|
|
343
|
+
? this.renderLoadingRow(0)
|
|
344
|
+
: this.renderChildren(only, only, 0);
|
|
345
|
+
}
|
|
346
|
+
else {
|
|
347
|
+
body = this.containers.map(c => this.renderContainerNode(c, 0));
|
|
348
|
+
}
|
|
349
|
+
return (h(Host, { key: '4e38d9ef5a1df137a41516a47dc5debbea6b2f35' }, h("div", { key: '6d2f162624e5bbc8650a2978a3b045c21fe13ea3', class: "mrd-document-list" }, body)));
|
|
350
|
+
}
|
|
351
|
+
static get is() { return "mrd-document-list"; }
|
|
352
|
+
static get encapsulation() { return "scoped"; }
|
|
353
|
+
static get originalStyleUrls() {
|
|
354
|
+
return {
|
|
355
|
+
"$": ["mrd-document-list.scss"]
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
static get styleUrls() {
|
|
359
|
+
return {
|
|
360
|
+
"$": ["mrd-document-list.css"]
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
static get properties() {
|
|
364
|
+
return {
|
|
365
|
+
"item": {
|
|
366
|
+
"type": "unknown",
|
|
367
|
+
"mutable": false,
|
|
368
|
+
"complexType": {
|
|
369
|
+
"original": "ClientLayoutItem | null",
|
|
370
|
+
"resolved": "ClientLayoutItem | null",
|
|
371
|
+
"references": {
|
|
372
|
+
"ClientLayoutItem": {
|
|
373
|
+
"location": "import",
|
|
374
|
+
"path": "../../types/client-layout",
|
|
375
|
+
"id": "src/types/client-layout.ts::ClientLayoutItem",
|
|
376
|
+
"referenceLocation": "ClientLayoutItem"
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
},
|
|
380
|
+
"required": false,
|
|
381
|
+
"optional": false,
|
|
382
|
+
"docs": {
|
|
383
|
+
"tags": [],
|
|
384
|
+
"text": "The VIEW or RELATED_VIEW layout item (dataClass, fromClass, view config)."
|
|
385
|
+
},
|
|
386
|
+
"getter": false,
|
|
387
|
+
"setter": false,
|
|
388
|
+
"defaultValue": "null"
|
|
389
|
+
},
|
|
390
|
+
"archetype": {
|
|
391
|
+
"type": "unknown",
|
|
392
|
+
"mutable": false,
|
|
393
|
+
"complexType": {
|
|
394
|
+
"original": "ClientArchetype",
|
|
395
|
+
"resolved": "ClientArchetype",
|
|
396
|
+
"references": {
|
|
397
|
+
"ClientArchetype": {
|
|
398
|
+
"location": "import",
|
|
399
|
+
"path": "../../types/client-layout",
|
|
400
|
+
"id": "src/types/client-layout.ts::ClientArchetype",
|
|
401
|
+
"referenceLocation": "ClientArchetype"
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
},
|
|
405
|
+
"required": true,
|
|
406
|
+
"optional": false,
|
|
407
|
+
"docs": {
|
|
408
|
+
"tags": [],
|
|
409
|
+
"text": "Resolved `commons.document` binding: slot name \u2192 concrete field/relation name."
|
|
410
|
+
},
|
|
411
|
+
"getter": false,
|
|
412
|
+
"setter": false
|
|
413
|
+
},
|
|
414
|
+
"parentId": {
|
|
415
|
+
"type": "string",
|
|
416
|
+
"mutable": false,
|
|
417
|
+
"complexType": {
|
|
418
|
+
"original": "string",
|
|
419
|
+
"resolved": "string",
|
|
420
|
+
"references": {}
|
|
421
|
+
},
|
|
422
|
+
"required": false,
|
|
423
|
+
"optional": false,
|
|
424
|
+
"docs": {
|
|
425
|
+
"tags": [],
|
|
426
|
+
"text": "Parent record id \u2014 required for RELATED_VIEW path building."
|
|
427
|
+
},
|
|
428
|
+
"getter": false,
|
|
429
|
+
"setter": false,
|
|
430
|
+
"reflect": false,
|
|
431
|
+
"attribute": "parent-id",
|
|
432
|
+
"defaultValue": "''"
|
|
433
|
+
},
|
|
434
|
+
"locale": {
|
|
435
|
+
"type": "string",
|
|
436
|
+
"mutable": false,
|
|
437
|
+
"complexType": {
|
|
438
|
+
"original": "string",
|
|
439
|
+
"resolved": "string",
|
|
440
|
+
"references": {}
|
|
441
|
+
},
|
|
442
|
+
"required": false,
|
|
443
|
+
"optional": false,
|
|
444
|
+
"docs": {
|
|
445
|
+
"tags": [],
|
|
446
|
+
"text": ""
|
|
447
|
+
},
|
|
448
|
+
"getter": false,
|
|
449
|
+
"setter": false,
|
|
450
|
+
"reflect": false,
|
|
451
|
+
"attribute": "locale",
|
|
452
|
+
"defaultValue": "navigator.language"
|
|
453
|
+
}
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
static get states() {
|
|
457
|
+
return {
|
|
458
|
+
"containers": {},
|
|
459
|
+
"rootLoading": {},
|
|
460
|
+
"singleContainer": {}
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
static get events() {
|
|
464
|
+
return [{
|
|
465
|
+
"method": "mrdLoadDistinct",
|
|
466
|
+
"name": "mrdLoadDistinct",
|
|
467
|
+
"bubbles": true,
|
|
468
|
+
"cancelable": true,
|
|
469
|
+
"composed": true,
|
|
470
|
+
"docs": {
|
|
471
|
+
"tags": [],
|
|
472
|
+
"text": "Request distinct values for a field/relation. Host fetches `{path}?{qs}` and calls `setDistinct(nodeId, values)`."
|
|
473
|
+
},
|
|
474
|
+
"complexType": {
|
|
475
|
+
"original": "{ nodeId: string; distinct: string; path: string; qs: string }",
|
|
476
|
+
"resolved": "{ nodeId: string; distinct: string; path: string; qs: string; }",
|
|
477
|
+
"references": {}
|
|
478
|
+
}
|
|
479
|
+
}, {
|
|
480
|
+
"method": "mrdLoadPage",
|
|
481
|
+
"name": "mrdLoadPage",
|
|
482
|
+
"bubbles": true,
|
|
483
|
+
"cancelable": true,
|
|
484
|
+
"composed": true,
|
|
485
|
+
"docs": {
|
|
486
|
+
"tags": [],
|
|
487
|
+
"text": "Request the documents in one folder \u2014 the same filtered list load a table does.\nHost fetches `{path}?{qs}` and calls `setDocuments(nodeId, docs)` (via setViewPage)."
|
|
488
|
+
},
|
|
489
|
+
"complexType": {
|
|
490
|
+
"original": "{ nodeId: string; page: number; sort: string; path: string; qs: string }",
|
|
491
|
+
"resolved": "{ nodeId: string; page: number; sort: string; path: string; qs: string; }",
|
|
492
|
+
"references": {}
|
|
493
|
+
}
|
|
494
|
+
}, {
|
|
495
|
+
"method": "mrdNavigate",
|
|
496
|
+
"name": "mrdNavigate",
|
|
497
|
+
"bubbles": true,
|
|
498
|
+
"cancelable": true,
|
|
499
|
+
"composed": true,
|
|
500
|
+
"docs": {
|
|
501
|
+
"tags": [],
|
|
502
|
+
"text": "A document row was clicked. Host routes to the document object page."
|
|
503
|
+
},
|
|
504
|
+
"complexType": {
|
|
505
|
+
"original": "{ href?: string; label: string }",
|
|
506
|
+
"resolved": "{ href?: string | undefined; label: string; }",
|
|
507
|
+
"references": {}
|
|
508
|
+
}
|
|
509
|
+
}];
|
|
510
|
+
}
|
|
511
|
+
static get methods() {
|
|
512
|
+
return {
|
|
513
|
+
"setDistinct": {
|
|
514
|
+
"complexType": {
|
|
515
|
+
"signature": "(nodeId: string, values: DistinctValue[]) => Promise<void>",
|
|
516
|
+
"parameters": [{
|
|
517
|
+
"name": "nodeId",
|
|
518
|
+
"type": "string",
|
|
519
|
+
"docs": ""
|
|
520
|
+
}, {
|
|
521
|
+
"name": "values",
|
|
522
|
+
"type": "DistinctValue[]",
|
|
523
|
+
"docs": ""
|
|
524
|
+
}],
|
|
525
|
+
"references": {
|
|
526
|
+
"Promise": {
|
|
527
|
+
"location": "global",
|
|
528
|
+
"id": "global::Promise"
|
|
529
|
+
},
|
|
530
|
+
"DistinctValue": {
|
|
531
|
+
"location": "local",
|
|
532
|
+
"path": "/Users/michiel/Mosterd/mosterd-components/src/components/mrd-document-list/mrd-document-list.tsx",
|
|
533
|
+
"id": "src/components/mrd-document-list/mrd-document-list.tsx::DistinctValue"
|
|
534
|
+
}
|
|
535
|
+
},
|
|
536
|
+
"return": "Promise<void>"
|
|
537
|
+
},
|
|
538
|
+
"docs": {
|
|
539
|
+
"text": "Inject distinct values for a node. `nodeId` is the sentinel root (containers)\nor a container node id (folders).",
|
|
540
|
+
"tags": []
|
|
541
|
+
}
|
|
542
|
+
},
|
|
543
|
+
"setDocuments": {
|
|
544
|
+
"complexType": {
|
|
545
|
+
"signature": "(nodeId: string, docs: DocRow[]) => Promise<void>",
|
|
546
|
+
"parameters": [{
|
|
547
|
+
"name": "nodeId",
|
|
548
|
+
"type": "string",
|
|
549
|
+
"docs": ""
|
|
550
|
+
}, {
|
|
551
|
+
"name": "docs",
|
|
552
|
+
"type": "DocRow[]",
|
|
553
|
+
"docs": ""
|
|
554
|
+
}],
|
|
555
|
+
"references": {
|
|
556
|
+
"Promise": {
|
|
557
|
+
"location": "global",
|
|
558
|
+
"id": "global::Promise"
|
|
559
|
+
},
|
|
560
|
+
"DocRow": {
|
|
561
|
+
"location": "local",
|
|
562
|
+
"path": "/Users/michiel/Mosterd/mosterd-components/src/components/mrd-document-list/mrd-document-list.tsx",
|
|
563
|
+
"id": "src/components/mrd-document-list/mrd-document-list.tsx::DocRow"
|
|
564
|
+
}
|
|
565
|
+
},
|
|
566
|
+
"return": "Promise<void>"
|
|
567
|
+
},
|
|
568
|
+
"docs": {
|
|
569
|
+
"text": "Inject the documents loaded for one folder node.",
|
|
570
|
+
"tags": []
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
};
|
|
574
|
+
}
|
|
575
|
+
static get elementRef() { return "el"; }
|
|
576
|
+
}
|
|
577
|
+
/** Root sentinel id for the container-level distinct request. */
|
|
578
|
+
MrdDocumentList.ROOT = '__root__';
|