@mmlogic/components 0.3.9 → 0.3.11
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_22.cjs.entry.js → mrd-boolean-field_23.cjs.entry.js} +684 -41
- package/dist/collection/collection-manifest.json +1 -0
- package/dist/collection/components/mrd-document-container/mrd-document-container.js +421 -0
- package/dist/collection/components/mrd-document-container/mrd-document-container.scss +79 -0
- package/dist/collection/components/mrd-document-list/mrd-document-list.js +653 -16
- package/dist/collection/components/mrd-document-list/mrd-document-list.scss +66 -0
- package/dist/collection/components/mrd-document-view/mrd-document-view.js +1 -1
- 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 +165 -14
- package/dist/collection/components/mrd-layout-section/mrd-layout-section.scss +0 -44
- 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 +47 -0
- package/dist/collection/utils/i18n.js +12 -0
- package/dist/components/i18n.js +1 -1
- package/dist/components/mrd-document-container.d.ts +11 -0
- package/dist/components/mrd-document-container.js +1 -0
- package/dist/components/mrd-document-container2.js +1 -0
- package/dist/components/mrd-document-list2.js +1 -1
- package/dist/components/mrd-document-view2.js +1 -1
- 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-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/loader.js +1 -1
- package/dist/esm/mosterdcomponents.js +1 -1
- package/dist/esm/{mrd-boolean-field_22.entry.js → mrd-boolean-field_23.entry.js} +684 -42
- package/dist/mosterdcomponents/mosterdcomponents.esm.js +1 -1
- package/dist/mosterdcomponents/p-a9618055.entry.js +1 -0
- package/dist/types/components/mrd-document-container/mrd-document-container.d.ts +99 -0
- package/dist/types/components/mrd-document-list/mrd-document-list.d.ts +126 -1
- package/dist/types/components/mrd-layout-section/mrd-layout-section.d.ts +32 -5
- package/dist/types/components.d.ts +250 -0
- package/dist/types/types/client-layout.d.ts +5 -0
- package/package.json +1 -1
- package/dist/mosterdcomponents/p-b547291b.entry.js +0 -1
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
:host {
|
|
2
2
|
display: block;
|
|
3
|
+
height: 100%;
|
|
3
4
|
}
|
|
4
5
|
|
|
5
6
|
.mrd-document-list {
|
|
6
7
|
padding: var(--mrd-space-2) 0;
|
|
8
|
+
min-height: 100%;
|
|
9
|
+
box-sizing: border-box;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/* Whole-area highlight while a file/document is dragged over the root (dossier
|
|
13
|
+
context) — makes the drop target obvious, Finder-style. */
|
|
14
|
+
.mrd-document-list--drop-active {
|
|
15
|
+
outline: 2px dashed var(--mrd-color-primary);
|
|
16
|
+
outline-offset: -4px;
|
|
17
|
+
background: var(--mrd-color-primary-50, rgba(22, 163, 74, 0.06));
|
|
7
18
|
}
|
|
8
19
|
|
|
9
20
|
.mrd-document-list__row {
|
|
@@ -22,6 +33,61 @@
|
|
|
22
33
|
background: var(--mrd-color-neutral-50);
|
|
23
34
|
}
|
|
24
35
|
|
|
36
|
+
.mrd-document-list__row--selected {
|
|
37
|
+
background: var(--mrd-color-primary-50, rgba(22, 163, 74, 0.1));
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.mrd-document-list__row--selected:hover {
|
|
41
|
+
background: var(--mrd-color-primary-50, rgba(22, 163, 74, 0.1));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.mrd-document-list__row--pending .mrd-document-list__label {
|
|
45
|
+
font-style: italic;
|
|
46
|
+
color: var(--mrd-color-neutral-500);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.mrd-document-list__row--doc {
|
|
50
|
+
cursor: grab;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.mrd-document-list__row--doc:active {
|
|
54
|
+
cursor: grabbing;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.mrd-document-list__row--drop {
|
|
58
|
+
background: var(--mrd-color-primary-50, rgba(22, 163, 74, 0.1));
|
|
59
|
+
box-shadow: inset 0 0 0 1px var(--mrd-color-primary);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.mrd-document-list__row--drop:hover {
|
|
63
|
+
background: var(--mrd-color-primary-50, rgba(22, 163, 74, 0.1));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.mrd-document-list__row--edit {
|
|
67
|
+
cursor: default;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.mrd-document-list__name-input {
|
|
71
|
+
flex: 1;
|
|
72
|
+
min-width: 0;
|
|
73
|
+
height: 1.625rem;
|
|
74
|
+
padding: 0 var(--mrd-space-2);
|
|
75
|
+
font-size: var(--mrd-font-size-sm);
|
|
76
|
+
font-family: inherit;
|
|
77
|
+
color: var(--mrd-color-neutral-800);
|
|
78
|
+
border: 1px solid var(--mrd-color-primary);
|
|
79
|
+
border-radius: var(--mrd-border-radius);
|
|
80
|
+
outline: none;
|
|
81
|
+
box-shadow: var(--mrd-shadow-focus);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.mrd-document-list__error {
|
|
85
|
+
font-size: var(--mrd-font-size-xs);
|
|
86
|
+
color: var(--mrd-color-danger, #dc2626);
|
|
87
|
+
padding-top: 0.125rem;
|
|
88
|
+
padding-bottom: 0.25rem;
|
|
89
|
+
}
|
|
90
|
+
|
|
25
91
|
.mrd-document-list__row--dossier .mrd-document-list__label {
|
|
26
92
|
font-weight: var(--mrd-font-weight-semibold);
|
|
27
93
|
}
|
|
@@ -56,7 +56,7 @@ export class MrdDocumentView {
|
|
|
56
56
|
const date = dateRaw != null && dateRaw !== '' ? formatDate(dateRaw, this.locale) : null;
|
|
57
57
|
const summaryRaw = this.slotValue('summary');
|
|
58
58
|
const summary = summaryRaw != null && summaryRaw !== '' ? String(summaryRaw) : null;
|
|
59
|
-
return (h(Host, { key: '
|
|
59
|
+
return (h(Host, { key: '0a2071925ecdb21738376d66fa4babf4590e694c' }, h("div", { key: 'a2d29c0b6e211cab142adc780466bc885a602e96', class: "mrd-document-view" }, this.renderContainer(), title && h("h1", { key: '7f5ac202c21bc8a70f0dd15e2e1fa06e651b5bce', class: "mrd-document-view__title" }, title), date && h("p", { key: 'b1dce94d5fd8bfd5e078644f631a38f91b87e7ff', class: "mrd-document-view__date" }, date), this.renderFile(), summary && (h("div", { key: '588b9ca40a49ae9ea303852620bde75333b440ab', class: "mrd-document-view__summary" }, h("div", { key: 'd3b8adb85ac346b72451e789c10aedd539c966de', class: "mrd-document-view__summary-body", innerHTML: summary }))))));
|
|
60
60
|
}
|
|
61
61
|
static get is() { return "mrd-document-view"; }
|
|
62
62
|
static get encapsulation() { return "scoped"; }
|
|
@@ -31,7 +31,7 @@ export class MrdEmailField {
|
|
|
31
31
|
}
|
|
32
32
|
render() {
|
|
33
33
|
const hasError = !!this.error;
|
|
34
|
-
return (h(Host, { key: '
|
|
34
|
+
return (h(Host, { key: '0d442ab2a711c26c83fcdbf0fd8cd006d8dd8649' }, h("div", { key: 'ceb2a80679514c4c5b888fe096c90ed6cc973f64', class: "mrd-email-field" }, this.label && (h("label", { key: '663f95eff1002ee56cfc3104514bf31b47e26750', class: `mrd-email-field__label${this.required ? ' mrd-email-field__label--required' : ''}` }, this.label)), h("input", { key: '42dbdec25a47b37cfd68d00d0b8a481f96fe8241', class: `mrd-email-field__input${hasError ? ' mrd-email-field__input--error' : ''}`, type: "email", name: this.name, value: this.value, placeholder: this.placeholder || 'name@example.com', required: this.required, disabled: this.disabled, onInput: this.handleInput, onBlur: this.handleBlur }), hasError && h("span", { key: '626ee856ceaa7051fb9dd1de8b7cbd708e83f617', class: "mrd-email-field__error" }, this.error))));
|
|
35
35
|
}
|
|
36
36
|
static get is() { return "mrd-email-field"; }
|
|
37
37
|
static get encapsulation() { return "scoped"; }
|
|
@@ -85,7 +85,7 @@ export class MrdFileField {
|
|
|
85
85
|
hasError ? 'mrd-file-field__zone--error' : '',
|
|
86
86
|
this.disabled || this.uploading ? 'mrd-file-field__zone--disabled' : '',
|
|
87
87
|
].filter(Boolean).join(' ');
|
|
88
|
-
return (h(Host, { key: '
|
|
88
|
+
return (h(Host, { key: '095bb39f3cb1680cf5e7e51bdfd06d8eb087f237' }, h("div", { key: '7e5b5fe6e63b6530221083c8bcb82bcac59a5fe7', class: "mrd-file-field" }, this.label && (h("label", { key: 'c34723f4199371d6fe8ea87463d878b89c038590', class: `mrd-file-field__label${this.required ? ' mrd-file-field__label--required' : ''}` }, this.label)), h("div", { key: '4727667345d3cd4a5c65a431744a09f366943c13', class: zoneClass, onClick: this.handleZoneClick, onDragOver: this.handleDragOver, onDragLeave: this.handleDragLeave, onDrop: this.handleDrop }, h("input", { key: '45ed41c0f094dbe269561c8586e473f908cdf4a4', ref: el => (this.fileInputRef = el), class: "mrd-file-field__input", type: "file", name: this.name, accept: this.accept, disabled: this.disabled || this.uploading, required: this.required && !hasFile, onChange: this.handleInputChange }), hasFile ? (h("div", { class: "mrd-file-field__selected" }, this.uploading ? (h("span", { class: "mrd-file-field__spinner", "aria-label": t('loading', this.locale) })) : (h("svg", { class: "mrd-file-field__icon", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2" }, h("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }), h("polyline", { points: "14 2 14 8 20 8" }))), h("span", { class: "mrd-file-field__filename" }, this.fileName), !this.uploading && (h("button", { class: "mrd-file-field__clear", type: "button", onClick: this.handleClear, "aria-label": t('clear', this.locale) }, "\u2715")))) : (h("div", { class: "mrd-file-field__prompt" }, h("svg", { class: "mrd-file-field__upload-icon", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2" }, h("polyline", { points: "16 16 12 12 8 16" }), h("line", { x1: "12", y1: "12", x2: "12", y2: "21" }), h("path", { d: "M20.39 18.39A5 5 0 0 0 18 9h-1.26A8 8 0 1 0 3 16.3" })), h("span", null, t('drop_file_here', this.locale), ' ', h("span", { class: "mrd-file-field__browse" }, t('browse', this.locale)))))), hasError && h("span", { key: '00ce94ead3c32ed63e903cfd9d8480084a308d84', class: "mrd-file-field__error" }, this.error))));
|
|
89
89
|
}
|
|
90
90
|
static get is() { return "mrd-file-field"; }
|
|
91
91
|
static get encapsulation() { return "scoped"; }
|
|
@@ -99,7 +99,7 @@ export class MrdImageField {
|
|
|
99
99
|
hasError ? 'mrd-image-field__zone--error' : '',
|
|
100
100
|
this.disabled || this.uploading ? 'mrd-image-field__zone--disabled' : '',
|
|
101
101
|
].filter(Boolean).join(' ');
|
|
102
|
-
return (h(Host, { key: '
|
|
102
|
+
return (h(Host, { key: '97db2df72839f36b7a46e153a5dd1c208c52b522' }, h("div", { key: 'c8f2d3d858f90d322d26082aaf5adb57acfc78f4', class: "mrd-image-field" }, this.label && (h("label", { key: '6625e5031ff0b7c06f76c1ea0387f1bd5c1858a4', class: `mrd-image-field__label${this.required ? ' mrd-image-field__label--required' : ''}` }, this.label)), h("div", { key: '364216e6a96e845e21c42e821fdff02bd2612ff8', class: zoneClass, onClick: this.handleZoneClick, onDragOver: this.handleDragOver, onDragLeave: this.handleDragLeave, onDrop: this.handleDrop }, h("input", { key: '0487706ddd9f48cda1cb0c2a178809d90674486b', ref: el => (this.fileInputRef = el), class: "mrd-image-field__input", type: "file", name: this.name, accept: this.accept, disabled: this.disabled || this.uploading, required: this.required && !this.previewUrl, onChange: this.handleInputChange }), this.previewUrl ? (h("div", { class: "mrd-image-field__preview-container" }, h("div", { class: "mrd-image-field__preview-thumb" }, h("img", { class: "mrd-image-field__preview", src: this.previewUrl, alt: this.fileName }), this.uploading && h("div", { class: "mrd-image-field__preview-overlay" }, h("span", { class: "mrd-image-field__spinner" }))), h("div", { class: "mrd-image-field__preview-info" }, h("span", { class: "mrd-image-field__preview-name" }, this.fileName), this.uploading && (h("span", { class: "mrd-image-field__upload-status" }, t('loading', this.locale)))), !this.uploading && (h("button", { class: "mrd-image-field__clear", type: "button", onClick: this.handleClear, "aria-label": t('clear', this.locale) }, t('remove', this.locale))))) : (h("div", { class: "mrd-image-field__prompt" }, h("svg", { class: "mrd-image-field__upload-icon", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2" }, h("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2", ry: "2" }), h("circle", { cx: "8.5", cy: "8.5", r: "1.5" }), h("polyline", { points: "21 15 16 10 5 21" })), h("span", null, t('drop_file_here', this.locale), ' ', h("span", { class: "mrd-image-field__browse" }, t('browse', this.locale)))))), hasError && h("span", { key: 'bd505ef4f4b67c4e9138d8825c6e600f583f4cab', class: "mrd-image-field__error" }, this.error))));
|
|
103
103
|
}
|
|
104
104
|
static get is() { return "mrd-image-field"; }
|
|
105
105
|
static get encapsulation() { return "scoped"; }
|
|
@@ -22,8 +22,6 @@ export class MrdLayoutSection {
|
|
|
22
22
|
this.imagePreviewUrl = null;
|
|
23
23
|
this.imagePreviews = {};
|
|
24
24
|
this.openHistoryField = null;
|
|
25
|
-
/** Per-view display mode for document collection views. Default 'tree'. */
|
|
26
|
-
this.docViewMode = {};
|
|
27
25
|
this.historyClickOutside = null;
|
|
28
26
|
this.searchTimers = {};
|
|
29
27
|
this.handleViewLoadPage = (e, name) => {
|
|
@@ -140,6 +138,20 @@ export class MrdLayoutSection {
|
|
|
140
138
|
if (list === null || list === void 0 ? void 0 : list.setDistinct)
|
|
141
139
|
await list.setDistinct(nodeId, values);
|
|
142
140
|
}
|
|
141
|
+
/** Inject the uploaded file reference for a dropped file, so the document view
|
|
142
|
+
* can request creation of the new document (see mrdViewUpload). */
|
|
143
|
+
async setViewFileReference(name, uri) {
|
|
144
|
+
const list = this.el.querySelector(`mrd-document-list[data-doclist="${name}"]`);
|
|
145
|
+
if (list === null || list === void 0 ? void 0 : list.setFileReference)
|
|
146
|
+
await list.setFileReference(uri);
|
|
147
|
+
}
|
|
148
|
+
/** Inject the created document's href after a file-drop create, so the
|
|
149
|
+
* optimistic row becomes navigable (see mrdCreateObject). */
|
|
150
|
+
async setViewCreatedObject(name, href) {
|
|
151
|
+
const list = this.el.querySelector(`mrd-document-list[data-doclist="${name}"]`);
|
|
152
|
+
if (list === null || list === void 0 ? void 0 : list.setCreatedHref)
|
|
153
|
+
await list.setCreatedHref(href);
|
|
154
|
+
}
|
|
143
155
|
/** Provide a resolved URL for an IMAGE field. Shows as thumbnail; clicking opens the lightbox. */
|
|
144
156
|
async setImagePreview(fieldName, url) {
|
|
145
157
|
this.imagePreviews = Object.assign(Object.assign({}, this.imagePreviews), { [fieldName]: url });
|
|
@@ -288,7 +300,7 @@ export class MrdLayoutSection {
|
|
|
288
300
|
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)))))))));
|
|
289
301
|
}
|
|
290
302
|
renderRelatedView(item) {
|
|
291
|
-
var _a, _b, _c, _d, _e, _f, _g, _h
|
|
303
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
292
304
|
const key = this.viewKeyFor(item);
|
|
293
305
|
if (!key)
|
|
294
306
|
return null;
|
|
@@ -301,25 +313,55 @@ export class MrdLayoutSection {
|
|
|
301
313
|
// The API publishes `archetypes` on the VIEW/RELATED_VIEW item itself
|
|
302
314
|
// (sibling of `view`), not inside `view`.
|
|
303
315
|
const docArchetype = resolveArchetype((_g = item.archetypes) !== null && _g !== void 0 ? _g : (_h = item.view) === null || _h === void 0 ? void 0 : _h.archetypes, ARCHETYPE_DOCUMENT);
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
316
|
+
// Canonical parent href for single-container seeding: use the RELATED_VIEW's
|
|
317
|
+
// fromClass (base class) rather than the route class, so polymorphic subtypes
|
|
318
|
+
// resolve to the same container the documents actually reference.
|
|
319
|
+
const containerHref = this.buildContainerHref(item, selfHref, parentId);
|
|
320
|
+
return (h("div", { class: "mrd-layout-section__related-view", key: `view-${key}` }, showTitle && item.label && h("h3", { class: "mrd-layout-section__related-view-title" }, item.label), docArchetype
|
|
321
|
+
? this.renderDocumentContainer(item, key, parentId, docArchetype, containerHref)
|
|
307
322
|
: this.renderTable(item, key, parentId)));
|
|
308
323
|
}
|
|
309
|
-
/**
|
|
310
|
-
|
|
311
|
-
|
|
324
|
+
/** Build the canonical parent href `/{base}/{tenant}/{fromClass}/{parentId}` from
|
|
325
|
+
* the object's self href. Empty unless it is a RELATED_VIEW with a fromClass. */
|
|
326
|
+
buildContainerHref(item, selfHref, parentId) {
|
|
327
|
+
if (item.type !== ClientLayoutItemType.RELATED_VIEW || !item.fromClass || !parentId)
|
|
328
|
+
return '';
|
|
329
|
+
const segs = selfHref.split('/').filter(Boolean);
|
|
330
|
+
if (segs.length < 2)
|
|
331
|
+
return '';
|
|
332
|
+
const [base, tenant] = segs;
|
|
333
|
+
return `/${base}/${tenant}/${item.fromClass}/${parentId}`;
|
|
312
334
|
}
|
|
313
|
-
|
|
314
|
-
|
|
335
|
+
/** Document collection view: owns the view-switch + collection actions and
|
|
336
|
+
* swaps between the folder tree and the flat table. Events are re-emitted to
|
|
337
|
+
* the host with the view key, exactly as the raw list/table events were. */
|
|
338
|
+
renderDocumentContainer(item, key, parentId, archetype, containerHref) {
|
|
339
|
+
return (h("mrd-document-container", { item: item, archetype: archetype, parentId: parentId, containerHref: containerHref, viewKey: key, locale: this.locale, onMrdLoadDistinct: (e) => {
|
|
315
340
|
e.stopPropagation();
|
|
316
341
|
this.mrdLoadViewDistinct.emit(Object.assign({ name: key }, e.detail));
|
|
317
342
|
}, onMrdLoadPage: (e) => {
|
|
318
343
|
e.stopPropagation();
|
|
319
344
|
this.mrdLoadViewPage.emit(Object.assign({ name: key }, e.detail));
|
|
345
|
+
}, onMrdLoadAggregations: (e) => {
|
|
346
|
+
var _a;
|
|
347
|
+
e.stopPropagation();
|
|
348
|
+
this.mrdLoadViewAggregations.emit(Object.assign({ name: key, dataClass: (_a = item.dataClass) !== null && _a !== void 0 ? _a : key }, e.detail));
|
|
320
349
|
}, onMrdNavigate: (e) => {
|
|
321
350
|
e.stopPropagation();
|
|
322
351
|
this.mrdNavigate.emit(e.detail);
|
|
352
|
+
}, onMrdAction: (e) => {
|
|
353
|
+
var _a;
|
|
354
|
+
e.stopPropagation();
|
|
355
|
+
this.mrdViewAction.emit(Object.assign({ name: key, dataClass: (_a = item.dataClass) !== null && _a !== void 0 ? _a : key }, e.detail));
|
|
356
|
+
}, onMrdUpdateObject: (e) => {
|
|
357
|
+
e.stopPropagation();
|
|
358
|
+
this.mrdUpdateObject.emit(e.detail);
|
|
359
|
+
}, onMrdUpload: (e) => {
|
|
360
|
+
e.stopPropagation();
|
|
361
|
+
this.mrdViewUpload.emit(Object.assign({ name: key }, e.detail));
|
|
362
|
+
}, onMrdCreateObject: (e) => {
|
|
363
|
+
e.stopPropagation();
|
|
364
|
+
this.mrdCreateObject.emit(Object.assign({ name: key }, e.detail));
|
|
323
365
|
} }));
|
|
324
366
|
}
|
|
325
367
|
renderTable(item, key, parentId) {
|
|
@@ -390,7 +432,7 @@ export class MrdLayoutSection {
|
|
|
390
432
|
}
|
|
391
433
|
render() {
|
|
392
434
|
const docArchetype = resolveArchetype(this.archetypes, ARCHETYPE_DOCUMENT);
|
|
393
|
-
return (h(Host, { key: '
|
|
435
|
+
return (h(Host, { key: '231f5c3e282375b5850291611645fe3c904831bb' }, h("div", { key: '314e39ec3aa1eabeb1a98f6e6d63fcf07e13ccec', class: "mrd-layout-section" }, docArchetype
|
|
394
436
|
? this.renderDocumentObject(docArchetype)
|
|
395
437
|
: this.items.map(item => this.renderItem(item))), this.renderImageModal()));
|
|
396
438
|
}
|
|
@@ -561,8 +603,7 @@ export class MrdLayoutSection {
|
|
|
561
603
|
"searchResultsMap": {},
|
|
562
604
|
"imagePreviewUrl": {},
|
|
563
605
|
"imagePreviews": {},
|
|
564
|
-
"openHistoryField": {}
|
|
565
|
-
"docViewMode": {}
|
|
606
|
+
"openHistoryField": {}
|
|
566
607
|
};
|
|
567
608
|
}
|
|
568
609
|
static get events() {
|
|
@@ -693,6 +734,66 @@ export class MrdLayoutSection {
|
|
|
693
734
|
"resolved": "{ name: string; nodeId: string; distinct: string; path: string; qs: string; }",
|
|
694
735
|
"references": {}
|
|
695
736
|
}
|
|
737
|
+
}, {
|
|
738
|
+
"method": "mrdUpdateObject",
|
|
739
|
+
"name": "mrdUpdateObject",
|
|
740
|
+
"bubbles": true,
|
|
741
|
+
"cancelable": true,
|
|
742
|
+
"composed": true,
|
|
743
|
+
"docs": {
|
|
744
|
+
"tags": [],
|
|
745
|
+
"text": "Generic \"update an existing object\" request from an embedded document view\n(a document dragged into another folder). Host PATCHes `href` with `values`."
|
|
746
|
+
},
|
|
747
|
+
"complexType": {
|
|
748
|
+
"original": "{ href: string; values: Record<string, unknown> }",
|
|
749
|
+
"resolved": "{ href: string; values: Record<string, unknown>; }",
|
|
750
|
+
"references": {
|
|
751
|
+
"Record": {
|
|
752
|
+
"location": "global",
|
|
753
|
+
"id": "global::Record"
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
}, {
|
|
758
|
+
"method": "mrdViewUpload",
|
|
759
|
+
"name": "mrdViewUpload",
|
|
760
|
+
"bubbles": true,
|
|
761
|
+
"cancelable": true,
|
|
762
|
+
"composed": true,
|
|
763
|
+
"docs": {
|
|
764
|
+
"tags": [],
|
|
765
|
+
"text": "An external file was dropped on a document view; host uploads and calls\nsetViewFileReference(name, uri)."
|
|
766
|
+
},
|
|
767
|
+
"complexType": {
|
|
768
|
+
"original": "{ name: string; file: File }",
|
|
769
|
+
"resolved": "{ name: string; file: File; }",
|
|
770
|
+
"references": {
|
|
771
|
+
"File": {
|
|
772
|
+
"location": "global",
|
|
773
|
+
"id": "global::File"
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
}, {
|
|
778
|
+
"method": "mrdCreateObject",
|
|
779
|
+
"name": "mrdCreateObject",
|
|
780
|
+
"bubbles": true,
|
|
781
|
+
"cancelable": true,
|
|
782
|
+
"composed": true,
|
|
783
|
+
"docs": {
|
|
784
|
+
"tags": [],
|
|
785
|
+
"text": "Create a new document from an uploaded file; host POSTs `values` to `path`,\nthen calls setViewCreatedObject(name, href) with the new object's href."
|
|
786
|
+
},
|
|
787
|
+
"complexType": {
|
|
788
|
+
"original": "{ name: string; path: string; values: Record<string, unknown> }",
|
|
789
|
+
"resolved": "{ name: string; path: string; values: Record<string, unknown>; }",
|
|
790
|
+
"references": {
|
|
791
|
+
"Record": {
|
|
792
|
+
"location": "global",
|
|
793
|
+
"id": "global::Record"
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
}
|
|
696
797
|
}];
|
|
697
798
|
}
|
|
698
799
|
static get methods() {
|
|
@@ -829,6 +930,56 @@ export class MrdLayoutSection {
|
|
|
829
930
|
"tags": []
|
|
830
931
|
}
|
|
831
932
|
},
|
|
933
|
+
"setViewFileReference": {
|
|
934
|
+
"complexType": {
|
|
935
|
+
"signature": "(name: string, uri: string) => Promise<void>",
|
|
936
|
+
"parameters": [{
|
|
937
|
+
"name": "name",
|
|
938
|
+
"type": "string",
|
|
939
|
+
"docs": ""
|
|
940
|
+
}, {
|
|
941
|
+
"name": "uri",
|
|
942
|
+
"type": "string",
|
|
943
|
+
"docs": ""
|
|
944
|
+
}],
|
|
945
|
+
"references": {
|
|
946
|
+
"Promise": {
|
|
947
|
+
"location": "global",
|
|
948
|
+
"id": "global::Promise"
|
|
949
|
+
}
|
|
950
|
+
},
|
|
951
|
+
"return": "Promise<void>"
|
|
952
|
+
},
|
|
953
|
+
"docs": {
|
|
954
|
+
"text": "Inject the uploaded file reference for a dropped file, so the document view\ncan request creation of the new document (see mrdViewUpload).",
|
|
955
|
+
"tags": []
|
|
956
|
+
}
|
|
957
|
+
},
|
|
958
|
+
"setViewCreatedObject": {
|
|
959
|
+
"complexType": {
|
|
960
|
+
"signature": "(name: string, href: string) => Promise<void>",
|
|
961
|
+
"parameters": [{
|
|
962
|
+
"name": "name",
|
|
963
|
+
"type": "string",
|
|
964
|
+
"docs": ""
|
|
965
|
+
}, {
|
|
966
|
+
"name": "href",
|
|
967
|
+
"type": "string",
|
|
968
|
+
"docs": ""
|
|
969
|
+
}],
|
|
970
|
+
"references": {
|
|
971
|
+
"Promise": {
|
|
972
|
+
"location": "global",
|
|
973
|
+
"id": "global::Promise"
|
|
974
|
+
}
|
|
975
|
+
},
|
|
976
|
+
"return": "Promise<void>"
|
|
977
|
+
},
|
|
978
|
+
"docs": {
|
|
979
|
+
"text": "Inject the created document's href after a file-drop create, so the\noptimistic row becomes navigable (see mrdCreateObject).",
|
|
980
|
+
"tags": []
|
|
981
|
+
}
|
|
982
|
+
},
|
|
832
983
|
"setImagePreview": {
|
|
833
984
|
"complexType": {
|
|
834
985
|
"signature": "(fieldName: string, url: string) => Promise<void>",
|
|
@@ -269,50 +269,6 @@
|
|
|
269
269
|
margin: 0 0 var(--mrd-space-3) 0;
|
|
270
270
|
}
|
|
271
271
|
|
|
272
|
-
.mrd-layout-section__doc-toolbar {
|
|
273
|
-
display: flex;
|
|
274
|
-
align-items: center;
|
|
275
|
-
justify-content: flex-end;
|
|
276
|
-
gap: var(--mrd-space-2);
|
|
277
|
-
padding: var(--mrd-space-2) 0;
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
.mrd-layout-section__seg {
|
|
281
|
-
display: inline-flex;
|
|
282
|
-
gap: 2px;
|
|
283
|
-
padding: 2px;
|
|
284
|
-
background: var(--mrd-color-neutral-100);
|
|
285
|
-
border-radius: var(--mrd-border-radius);
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
.mrd-layout-section__seg-btn {
|
|
289
|
-
width: 1.875rem;
|
|
290
|
-
height: 1.625rem;
|
|
291
|
-
display: grid;
|
|
292
|
-
place-items: center;
|
|
293
|
-
border: none;
|
|
294
|
-
background: none;
|
|
295
|
-
border-radius: var(--mrd-border-radius-sm);
|
|
296
|
-
color: var(--mrd-color-neutral-500);
|
|
297
|
-
cursor: pointer;
|
|
298
|
-
transition: color var(--mrd-transition-fast), background var(--mrd-transition-fast);
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
.mrd-layout-section__seg-btn:hover {
|
|
302
|
-
color: var(--mrd-color-neutral-800);
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
.mrd-layout-section__seg-btn[aria-pressed='true'] {
|
|
306
|
-
background: var(--mrd-color-white);
|
|
307
|
-
color: var(--mrd-color-primary-dark);
|
|
308
|
-
box-shadow: var(--mrd-shadow-sm);
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
.mrd-layout-section__seg-btn svg {
|
|
312
|
-
width: 1rem;
|
|
313
|
-
height: 1rem;
|
|
314
|
-
}
|
|
315
|
-
|
|
316
272
|
.mrd-layout-section__search {
|
|
317
273
|
position: relative;
|
|
318
274
|
margin: var(--mrd-space-2) 0;
|
|
@@ -28,7 +28,7 @@ export class MrdLongtextField {
|
|
|
28
28
|
}
|
|
29
29
|
render() {
|
|
30
30
|
const hasError = !!this.error;
|
|
31
|
-
return (h(Host, { key: '
|
|
31
|
+
return (h(Host, { key: 'f00f81944748f8f09e22d44befe5e288456b7cc8' }, h("div", { key: '7b0ae9cf5b6b684cddb648fe4db6005494322535', class: "mrd-longtext-field" }, this.label && (h("label", { key: '3fc6a8710d0e98fe685c45d214a88ae1b0947973', class: `mrd-longtext-field__label${this.required ? ' mrd-longtext-field__label--required' : ''}` }, this.label)), this.disabled ? (h("pre", { class: "mrd-longtext-field__content" }, this.value)) : (h("textarea", { class: `mrd-longtext-field__input${hasError ? ' mrd-longtext-field__input--error' : ''}`, name: this.name, placeholder: this.placeholder, required: this.required, rows: 10, onInput: this.handleInput, onBlur: this.handleBlur }, this.value)), hasError && h("span", { key: 'e96f1dbc6c00a1602f4ce3c97d514a229aeb7cb7', class: "mrd-longtext-field__error" }, this.error))));
|
|
32
32
|
}
|
|
33
33
|
static get is() { return "mrd-longtext-field"; }
|
|
34
34
|
static get encapsulation() { return "scoped"; }
|
|
@@ -69,7 +69,7 @@ export class MrdNumberField {
|
|
|
69
69
|
const hasError = !!this.error;
|
|
70
70
|
const suffix = this.dataType === ClientLayoutItemFieldDataType.PERCENTAGE ? '%' :
|
|
71
71
|
this.dataType === ClientLayoutItemFieldDataType.DECIMAL ? '' : '';
|
|
72
|
-
return (h(Host, { key: '
|
|
72
|
+
return (h(Host, { key: 'b034a3cc8d841641c0ec167e138904586b044121' }, h("div", { key: '7379bfadb8bd0c4e0a945a37013053a4e22477ab', class: "mrd-number-field" }, this.label && (h("label", { key: '5518d40b7158e17704633c2b95ac7e3efc0c5568', class: `mrd-number-field__label${this.required ? ' mrd-number-field__label--required' : ''}` }, this.label)), h("div", { key: '38ad9f3c945d66c23bd77c743306e916eaefed7f', class: "mrd-number-field__input-wrapper" }, h("input", { key: 'ac8b4bc1ea4431cc9306664522ebfda21760ae83', class: `mrd-number-field__input${hasError ? ' mrd-number-field__input--error' : ''}`, type: "text", inputMode: "decimal", name: this.name, value: this.displayValue, placeholder: this.placeholder || (suffix ? `0${suffix}` : '0'), required: this.required, disabled: this.disabled, onInput: this.handleInput, onBlur: this.handleBlur, onFocus: this.handleFocus })), hasError && h("span", { key: '09f5a58b769c81acdf4bdd48f9325934c4bb875d', class: "mrd-number-field__error" }, this.error))));
|
|
73
73
|
}
|
|
74
74
|
static get is() { return "mrd-number-field"; }
|
|
75
75
|
static get encapsulation() { return "scoped"; }
|
|
@@ -28,9 +28,9 @@ export class MrdSecretField {
|
|
|
28
28
|
}
|
|
29
29
|
render() {
|
|
30
30
|
const hasError = !!this.error;
|
|
31
|
-
return (h(Host, { key: '
|
|
31
|
+
return (h(Host, { key: 'c850ec5bc5967ca0aefca7d7cb65ecae121a9dc1' }, h("div", { key: '3249ffbc441422af054a20806dd8dfce954a8ffc', class: "mrd-secret-field" }, this.label && (h("label", { key: '0b4a86da9cafad32f153af1bc5487a4e9b941e2f', class: `mrd-secret-field__label${this.required ? ' mrd-secret-field__label--required' : ''}` }, this.label)), this.disabled
|
|
32
32
|
? (h("span", { class: "mrd-secret-field__masked", "aria-label": this.label }, this.value ? '••••••••' : ''))
|
|
33
|
-
: (h("input", { class: `mrd-secret-field__input${hasError ? ' mrd-secret-field__input--error' : ''}`, type: "password", name: this.name, value: this.value, placeholder: this.placeholder, required: this.required, autocomplete: "new-password", onInput: this.handleInput, onBlur: this.handleBlur })), hasError && h("span", { key: '
|
|
33
|
+
: (h("input", { class: `mrd-secret-field__input${hasError ? ' mrd-secret-field__input--error' : ''}`, type: "password", name: this.name, value: this.value, placeholder: this.placeholder, required: this.required, autocomplete: "new-password", onInput: this.handleInput, onBlur: this.handleBlur })), hasError && h("span", { key: 'b0d0105f3d43d2e214f070b24e745dbce0e33977', class: "mrd-secret-field__error" }, this.error))));
|
|
34
34
|
}
|
|
35
35
|
static get is() { return "mrd-secret-field"; }
|
|
36
36
|
static get encapsulation() { return "scoped"; }
|
|
@@ -28,7 +28,7 @@ export class MrdTextField {
|
|
|
28
28
|
}
|
|
29
29
|
render() {
|
|
30
30
|
const hasError = !!this.error;
|
|
31
|
-
return (h(Host, { key: '
|
|
31
|
+
return (h(Host, { key: 'e9252b251faf98ab190e643b97c13fa32d12ef22' }, h("div", { key: '37f4259a111c293f2fe12f321f08c00c25e77feb', class: "mrd-text-field" }, this.label && (h("label", { key: 'c59e0346fb71a765ea38629b03c06341567ed210', class: `mrd-text-field__label${this.required ? ' mrd-text-field__label--required' : ''}` }, this.label)), h("input", { key: 'dc09953a672472348719f29904d900966d945843', class: `mrd-text-field__input${hasError ? ' mrd-text-field__input--error' : ''}`, type: "text", name: this.name, value: this.value, placeholder: this.placeholder, required: this.required, disabled: this.disabled, onInput: this.handleInput, onBlur: this.handleBlur }), hasError && h("span", { key: '037653857a372854a16b28ebf8994b23e3e0d696', class: "mrd-text-field__error" }, this.error))));
|
|
32
32
|
}
|
|
33
33
|
static get is() { return "mrd-text-field"; }
|
|
34
34
|
static get encapsulation() { return "scoped"; }
|
|
@@ -66,7 +66,7 @@ export class MrdTextareaField {
|
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
render() {
|
|
69
|
-
return (h(Host, { key: '
|
|
69
|
+
return (h(Host, { key: 'fe7824c81e082c3f2c1cf18c11dde20cb1f40f2c' }, h("div", { key: 'adf394a7e146d16bc79006873a209b11d88b2e17', class: "mrd-textarea-field" }, this.label && (h("label", { key: '1b0dd2b4cf26c55a0af05c67a3178edc0c9d56c4', class: `mrd-textarea-field__label${this.required ? ' mrd-textarea-field__label--required' : ''}` }, this.label)), h("div", { key: '7c8fe88b222af0beed08db492aa9f6d890e0dc5b', class: `mrd-textarea-field__container${this.error ? ' mrd-textarea-field__container--error' : ''}` }, h("div", { key: '295968283e94812cb04660117c5bdeaf3647469c', class: "mrd-textarea-field__editor" })), this.error && h("span", { key: '5b5ab61053ab0792d4c249de04bd1d13b51469bf', class: "mrd-textarea-field__error" }, this.error))));
|
|
70
70
|
}
|
|
71
71
|
static get is() { return "mrd-textarea-field"; }
|
|
72
72
|
static get encapsulation() { return "scoped"; }
|
|
@@ -27,7 +27,7 @@ export class MrdTimeField {
|
|
|
27
27
|
}
|
|
28
28
|
render() {
|
|
29
29
|
const hasError = !!this.error;
|
|
30
|
-
return (h(Host, { key: '
|
|
30
|
+
return (h(Host, { key: '579219a478e31325b5a676465807c1d936724a2b' }, h("div", { key: '51b25f6e083a29989505c0ad79edbcd3b0060736', class: "mrd-time-field" }, this.label && (h("label", { key: '67d98bebb8803deea2d2a4a63f36706789ccd8c7', class: `mrd-time-field__label${this.required ? ' mrd-time-field__label--required' : ''}` }, this.label)), h("input", { key: '734741e0db1bdd5886fef37bba3b2f8d7200a0ab', class: `mrd-time-field__input${hasError ? ' mrd-time-field__input--error' : ''}`, type: "time", name: this.name, value: this.value, required: this.required, disabled: this.disabled, onChange: this.handleChange, onBlur: this.handleBlur }), hasError && h("span", { key: '0dbd168d14966dc56a77c97cd8fd8f9b208a4bf5', class: "mrd-time-field__error" }, this.error))));
|
|
31
31
|
}
|
|
32
32
|
static get is() { return "mrd-time-field"; }
|
|
33
33
|
static get encapsulation() { return "scoped"; }
|
|
@@ -440,6 +440,53 @@ async function renderSection(index) {
|
|
|
440
440
|
section.addEventListener('mrdDownload', (e) => logEvent('mrdDownload', e.detail));
|
|
441
441
|
section.addEventListener('mrdSearch', (e) => logEvent('mrdSearch', e.detail));
|
|
442
442
|
|
|
443
|
+
// Generic in-place update (e.g. a document dragged into another folder).
|
|
444
|
+
// Fire-and-forget PATCH; the component already updated its tree optimistically.
|
|
445
|
+
section.addEventListener('mrdUpdateObject', async (e) => {
|
|
446
|
+
if (generation !== _sectionGeneration) return;
|
|
447
|
+
const { href, values } = e.detail;
|
|
448
|
+
logEvent('mrdUpdateObject', e.detail);
|
|
449
|
+
try {
|
|
450
|
+
const result = await apiRequest('PATCH', href, authGetToken(), values);
|
|
451
|
+
if (!result.ok) console.error('[mrdUpdateObject] mislukt', result.status, result.body);
|
|
452
|
+
} catch (err) {
|
|
453
|
+
console.error('[mrdUpdateObject] mislukt', href, err);
|
|
454
|
+
}
|
|
455
|
+
});
|
|
456
|
+
|
|
457
|
+
// External file dropped on a folder: upload it, then hand the reference back to
|
|
458
|
+
// the component (same flow as mrd-form's mrdUpload → setFieldValue).
|
|
459
|
+
section.addEventListener('mrdViewUpload', async (e) => {
|
|
460
|
+
if (generation !== _sectionGeneration) return;
|
|
461
|
+
const { name, file } = e.detail;
|
|
462
|
+
logEvent('mrdViewUpload', { name, file: file?.name });
|
|
463
|
+
try {
|
|
464
|
+
const uri = await apiUploadFile(authGetToken(), _selectedTenant, file);
|
|
465
|
+
await section.setViewFileReference(name, uri);
|
|
466
|
+
} catch (err) {
|
|
467
|
+
console.error('[mrdViewUpload] upload mislukt', name, err);
|
|
468
|
+
}
|
|
469
|
+
});
|
|
470
|
+
|
|
471
|
+
// Create a new document from the uploaded file. POST; a 400 would be where the
|
|
472
|
+
// real host opens the create-form fallback (out of scope for the dev page).
|
|
473
|
+
section.addEventListener('mrdCreateObject', async (e) => {
|
|
474
|
+
if (generation !== _sectionGeneration) return;
|
|
475
|
+
const { name, path, values } = e.detail;
|
|
476
|
+
logEvent('mrdCreateObject', e.detail);
|
|
477
|
+
try {
|
|
478
|
+
const result = await apiRequest('POST', `${_baseHref}${path}`, authGetToken(), values);
|
|
479
|
+
if (result.ok) {
|
|
480
|
+
const href = result.body?._links?.self?.href;
|
|
481
|
+
if (href) await section.setViewCreatedObject(name, href);
|
|
482
|
+
} else {
|
|
483
|
+
console.error('[mrdCreateObject] mislukt', result.status, result.body);
|
|
484
|
+
}
|
|
485
|
+
} catch (err) {
|
|
486
|
+
console.error('[mrdCreateObject] mislukt', path, err);
|
|
487
|
+
}
|
|
488
|
+
});
|
|
489
|
+
|
|
443
490
|
container.appendChild(section);
|
|
444
491
|
}
|
|
445
492
|
|
|
@@ -64,6 +64,12 @@ const translations = {
|
|
|
64
64
|
history_until: 'tot',
|
|
65
65
|
history_badge_tooltip: 'Vorige waarden',
|
|
66
66
|
hyperlink_name: 'Linktekst (optioneel)',
|
|
67
|
+
// mrd-document-list
|
|
68
|
+
new_folder: 'Nieuwe folder',
|
|
69
|
+
folder_name_placeholder: 'Foldernaam',
|
|
70
|
+
folder_no_slash: "Een foldernaam mag geen '/' bevatten",
|
|
71
|
+
folder_duplicate: 'Er bestaat al een folder met deze naam',
|
|
72
|
+
doc_empty_drop: 'Nog geen documenten — sleep bestanden hierheen',
|
|
67
73
|
},
|
|
68
74
|
en: {
|
|
69
75
|
required: 'This field is required',
|
|
@@ -130,6 +136,12 @@ const translations = {
|
|
|
130
136
|
history_until: 'until',
|
|
131
137
|
history_badge_tooltip: 'Previous values',
|
|
132
138
|
hyperlink_name: 'Link text (optional)',
|
|
139
|
+
// mrd-document-list
|
|
140
|
+
new_folder: 'New folder',
|
|
141
|
+
folder_name_placeholder: 'Folder name',
|
|
142
|
+
folder_no_slash: "A folder name cannot contain '/'",
|
|
143
|
+
folder_duplicate: 'A folder with this name already exists',
|
|
144
|
+
doc_empty_drop: 'No documents yet — drop files here',
|
|
133
145
|
},
|
|
134
146
|
ar: {
|
|
135
147
|
required: 'هذا الحقل مطلوب',
|