@mmlogic/components 0.5.1 → 0.5.2
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/cell-renderer-CmaO0CZT.js +862 -0
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/mosterdcomponents.cjs.js +1 -1
- package/dist/cjs/mrd-boolean-field_23.cjs.entry.js +2490 -817
- package/dist/cjs/mrd-merge-view.cjs.entry.js +273 -0
- package/dist/collection/collection-manifest.json +1 -0
- package/dist/collection/components/fields/mrd-textarea-field/mrd-textarea-field.js +9 -5
- package/dist/collection/components/merge/mrd-merge-view/merge-diff.js +99 -0
- package/dist/collection/components/merge/mrd-merge-view/merge-parts.js +44 -0
- package/dist/collection/components/merge/mrd-merge-view/mrd-merge-view.css +244 -0
- package/dist/collection/components/merge/mrd-merge-view/mrd-merge-view.js +397 -0
- package/dist/collection/dev/api.js +24 -0
- package/dist/collection/dev/app.js +84 -4
- package/dist/collection/utils/cell-renderer.js +6 -1
- package/dist/collection/utils/i18n.js +104 -0
- package/dist/components/cell-renderer.js +1 -0
- package/dist/components/format.js +1 -1
- package/dist/components/i18n.js +1 -1
- package/dist/components/mrd-layout-section.js +1 -1
- package/dist/components/mrd-merge-view.d.ts +11 -0
- package/dist/components/mrd-merge-view.js +1 -0
- package/dist/components/mrd-table2.js +1 -1
- package/dist/components/mrd-textarea-field2.js +2 -1
- package/dist/esm/cell-renderer-D63AUZxa.js +854 -0
- package/dist/esm/loader.js +1 -1
- package/dist/esm/mosterdcomponents.js +1 -1
- package/dist/esm/mrd-boolean-field_23.entry.js +2420 -747
- package/dist/esm/mrd-merge-view.entry.js +271 -0
- package/dist/mosterdcomponents/mosterdcomponents.esm.js +1 -1
- package/dist/mosterdcomponents/p-2e16a7d0.entry.js +1 -0
- package/dist/mosterdcomponents/p-CnqDM0Gb.js +1 -0
- package/dist/mosterdcomponents/p-b5f38707.entry.js +3 -0
- package/dist/types/components/fields/mrd-textarea-field/mrd-textarea-field.d.ts +1 -0
- package/dist/types/components/merge/mrd-merge-view/merge-diff.d.ts +43 -0
- package/dist/types/components/merge/mrd-merge-view/merge-parts.d.ts +37 -0
- package/dist/types/components/merge/mrd-merge-view/mrd-merge-view.d.ts +68 -0
- package/dist/types/components.d.ts +151 -0
- package/package.json +2 -1
- package/dist/mosterdcomponents/p-cdecc698.entry.js +0 -1
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
:host {
|
|
2
|
+
display: block;
|
|
3
|
+
width: 100%;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.mrd-merge-view {
|
|
7
|
+
font-family: var(--mrd-font-family);
|
|
8
|
+
font-size: var(--mrd-font-size-sm);
|
|
9
|
+
color: var(--mrd-color-neutral-900);
|
|
10
|
+
}
|
|
11
|
+
.mrd-merge-view__hint {
|
|
12
|
+
margin: 0 0 var(--mrd-space-4);
|
|
13
|
+
color: var(--mrd-color-neutral-600);
|
|
14
|
+
}
|
|
15
|
+
.mrd-merge-view__heading {
|
|
16
|
+
margin: 0 0 var(--mrd-space-4);
|
|
17
|
+
font-size: var(--mrd-font-size-lg);
|
|
18
|
+
font-weight: var(--mrd-font-weight-semibold);
|
|
19
|
+
}
|
|
20
|
+
.mrd-merge-view__search-wrapper {
|
|
21
|
+
position: relative;
|
|
22
|
+
display: flex;
|
|
23
|
+
align-items: center;
|
|
24
|
+
}
|
|
25
|
+
.mrd-merge-view__search {
|
|
26
|
+
width: 100%;
|
|
27
|
+
height: var(--mrd-input-height);
|
|
28
|
+
padding: var(--mrd-input-padding-y) var(--mrd-input-padding-x);
|
|
29
|
+
border: var(--mrd-border-width) solid var(--mrd-border-color);
|
|
30
|
+
border-radius: var(--mrd-border-radius);
|
|
31
|
+
background: var(--mrd-input-bg);
|
|
32
|
+
color: var(--mrd-input-color);
|
|
33
|
+
font-size: var(--mrd-font-size-sm);
|
|
34
|
+
}
|
|
35
|
+
.mrd-merge-view__search:focus {
|
|
36
|
+
outline: none;
|
|
37
|
+
border-color: var(--mrd-border-color-focus);
|
|
38
|
+
box-shadow: var(--mrd-shadow-focus);
|
|
39
|
+
}
|
|
40
|
+
.mrd-merge-view__spinner {
|
|
41
|
+
position: absolute;
|
|
42
|
+
right: var(--mrd-space-3);
|
|
43
|
+
width: 1rem;
|
|
44
|
+
height: 1rem;
|
|
45
|
+
border: 2px solid var(--mrd-color-neutral-300);
|
|
46
|
+
border-top-color: var(--mrd-color-primary);
|
|
47
|
+
border-radius: var(--mrd-border-radius-full);
|
|
48
|
+
animation: mrd-merge-view-spin var(--mrd-transition-slow) linear infinite;
|
|
49
|
+
}
|
|
50
|
+
.mrd-merge-view__results {
|
|
51
|
+
margin-top: var(--mrd-space-2);
|
|
52
|
+
border: var(--mrd-border-width) solid var(--mrd-border-color);
|
|
53
|
+
border-radius: var(--mrd-border-radius);
|
|
54
|
+
overflow: hidden;
|
|
55
|
+
}
|
|
56
|
+
.mrd-merge-view__no-results {
|
|
57
|
+
padding: var(--mrd-space-3) var(--mrd-space-4);
|
|
58
|
+
color: var(--mrd-color-neutral-500);
|
|
59
|
+
}
|
|
60
|
+
.mrd-merge-view__result-item {
|
|
61
|
+
display: flex;
|
|
62
|
+
align-items: center;
|
|
63
|
+
justify-content: space-between;
|
|
64
|
+
gap: var(--mrd-space-3);
|
|
65
|
+
padding: var(--mrd-space-2) var(--mrd-space-4);
|
|
66
|
+
}
|
|
67
|
+
.mrd-merge-view__result-item:not(:last-child) {
|
|
68
|
+
border-bottom: var(--mrd-border-width) solid var(--mrd-border-color);
|
|
69
|
+
}
|
|
70
|
+
.mrd-merge-view__result-label {
|
|
71
|
+
font-weight: var(--mrd-font-weight-medium);
|
|
72
|
+
}
|
|
73
|
+
.mrd-merge-view__no-conflicts {
|
|
74
|
+
color: var(--mrd-color-neutral-600);
|
|
75
|
+
}
|
|
76
|
+
.mrd-merge-view__table {
|
|
77
|
+
width: 100%;
|
|
78
|
+
border-collapse: collapse;
|
|
79
|
+
margin-bottom: var(--mrd-space-4);
|
|
80
|
+
}
|
|
81
|
+
.mrd-merge-view__header {
|
|
82
|
+
text-align: left;
|
|
83
|
+
padding: var(--mrd-space-2) var(--mrd-space-3);
|
|
84
|
+
border-bottom: 2px solid var(--mrd-border-color);
|
|
85
|
+
font-size: var(--mrd-font-size-xs);
|
|
86
|
+
text-transform: uppercase;
|
|
87
|
+
letter-spacing: 0.04em;
|
|
88
|
+
color: var(--mrd-color-neutral-600);
|
|
89
|
+
}
|
|
90
|
+
.mrd-merge-view__header-name {
|
|
91
|
+
display: block;
|
|
92
|
+
text-transform: none;
|
|
93
|
+
letter-spacing: normal;
|
|
94
|
+
font-size: var(--mrd-font-size-sm);
|
|
95
|
+
font-weight: var(--mrd-font-weight-medium);
|
|
96
|
+
color: var(--mrd-color-neutral-900);
|
|
97
|
+
margin-top: var(--mrd-space-1);
|
|
98
|
+
}
|
|
99
|
+
.mrd-merge-view__row:nth-child(even) {
|
|
100
|
+
background: var(--mrd-color-neutral-50);
|
|
101
|
+
}
|
|
102
|
+
.mrd-merge-view__cell {
|
|
103
|
+
padding: var(--mrd-space-2) var(--mrd-space-3);
|
|
104
|
+
border-bottom: var(--mrd-border-width) solid var(--mrd-border-color);
|
|
105
|
+
vertical-align: top;
|
|
106
|
+
}
|
|
107
|
+
.mrd-merge-view__cell--label {
|
|
108
|
+
font-weight: var(--mrd-font-weight-medium);
|
|
109
|
+
white-space: nowrap;
|
|
110
|
+
}
|
|
111
|
+
.mrd-merge-view__option {
|
|
112
|
+
display: flex;
|
|
113
|
+
align-items: flex-start;
|
|
114
|
+
gap: var(--mrd-space-2);
|
|
115
|
+
cursor: pointer;
|
|
116
|
+
}
|
|
117
|
+
.mrd-merge-view__option input[type=radio] {
|
|
118
|
+
margin-top: 0.2em;
|
|
119
|
+
}
|
|
120
|
+
.mrd-merge-view__history-wrap {
|
|
121
|
+
position: relative;
|
|
122
|
+
display: inline-flex;
|
|
123
|
+
align-items: center;
|
|
124
|
+
margin-left: var(--mrd-space-1);
|
|
125
|
+
}
|
|
126
|
+
.mrd-merge-view__history-btn {
|
|
127
|
+
display: inline-flex;
|
|
128
|
+
align-items: center;
|
|
129
|
+
justify-content: center;
|
|
130
|
+
width: 1.25rem;
|
|
131
|
+
height: 1.25rem;
|
|
132
|
+
padding: 0;
|
|
133
|
+
background: transparent;
|
|
134
|
+
border: none;
|
|
135
|
+
border-radius: var(--mrd-border-radius-sm);
|
|
136
|
+
color: var(--mrd-color-neutral-400);
|
|
137
|
+
cursor: pointer;
|
|
138
|
+
flex-shrink: 0;
|
|
139
|
+
transition: color var(--mrd-transition-fast), background-color var(--mrd-transition-fast);
|
|
140
|
+
}
|
|
141
|
+
.mrd-merge-view__history-btn:hover {
|
|
142
|
+
color: var(--mrd-color-neutral-700);
|
|
143
|
+
background-color: var(--mrd-color-neutral-100);
|
|
144
|
+
}
|
|
145
|
+
.mrd-merge-view__history-btn:focus {
|
|
146
|
+
outline: none;
|
|
147
|
+
box-shadow: var(--mrd-shadow-focus);
|
|
148
|
+
}
|
|
149
|
+
.mrd-merge-view__history-icon {
|
|
150
|
+
width: 0.875rem;
|
|
151
|
+
height: 0.875rem;
|
|
152
|
+
}
|
|
153
|
+
.mrd-merge-view__history-popover {
|
|
154
|
+
position: absolute;
|
|
155
|
+
top: calc(100% + 0.25rem);
|
|
156
|
+
left: 0;
|
|
157
|
+
min-width: 18rem;
|
|
158
|
+
max-width: 18rem;
|
|
159
|
+
background-color: var(--mrd-color-white);
|
|
160
|
+
border: var(--mrd-border-width) solid var(--mrd-border-color);
|
|
161
|
+
border-radius: var(--mrd-border-radius-md);
|
|
162
|
+
box-shadow: var(--mrd-shadow-md);
|
|
163
|
+
padding: var(--mrd-space-1) 0;
|
|
164
|
+
z-index: var(--mrd-z-dropdown);
|
|
165
|
+
}
|
|
166
|
+
.mrd-merge-view__history-entry {
|
|
167
|
+
font-size: var(--mrd-font-size-sm);
|
|
168
|
+
color: var(--mrd-color-neutral-700);
|
|
169
|
+
padding: var(--mrd-space-2) var(--mrd-space-3);
|
|
170
|
+
line-height: var(--mrd-line-height-normal);
|
|
171
|
+
}
|
|
172
|
+
.mrd-merge-view__history-entry:not(:last-child) {
|
|
173
|
+
border-bottom: var(--mrd-border-width) solid var(--mrd-color-neutral-100);
|
|
174
|
+
}
|
|
175
|
+
.mrd-merge-view__auto-note {
|
|
176
|
+
margin-bottom: var(--mrd-space-4);
|
|
177
|
+
padding: var(--mrd-space-3) var(--mrd-space-4);
|
|
178
|
+
background: var(--mrd-color-neutral-50);
|
|
179
|
+
border: var(--mrd-border-width) solid var(--mrd-border-color);
|
|
180
|
+
border-radius: var(--mrd-border-radius);
|
|
181
|
+
color: var(--mrd-color-neutral-700);
|
|
182
|
+
}
|
|
183
|
+
.mrd-merge-view__auto-note p {
|
|
184
|
+
margin: 0 0 var(--mrd-space-1);
|
|
185
|
+
font-weight: var(--mrd-font-weight-medium);
|
|
186
|
+
}
|
|
187
|
+
.mrd-merge-view__auto-note ul {
|
|
188
|
+
margin: 0;
|
|
189
|
+
padding-left: var(--mrd-space-5);
|
|
190
|
+
}
|
|
191
|
+
.mrd-merge-view__summary-list {
|
|
192
|
+
margin: 0 0 var(--mrd-space-4);
|
|
193
|
+
padding-left: var(--mrd-space-5);
|
|
194
|
+
}
|
|
195
|
+
.mrd-merge-view__warning {
|
|
196
|
+
padding: var(--mrd-space-3) var(--mrd-space-4);
|
|
197
|
+
background: var(--mrd-color-danger-light);
|
|
198
|
+
border: var(--mrd-border-width) solid var(--mrd-color-danger);
|
|
199
|
+
border-radius: var(--mrd-border-radius);
|
|
200
|
+
color: var(--mrd-color-danger-dark);
|
|
201
|
+
margin-bottom: var(--mrd-space-4);
|
|
202
|
+
}
|
|
203
|
+
.mrd-merge-view__actions {
|
|
204
|
+
display: flex;
|
|
205
|
+
gap: var(--mrd-space-3);
|
|
206
|
+
}
|
|
207
|
+
.mrd-merge-view__btn {
|
|
208
|
+
height: var(--mrd-input-height-sm);
|
|
209
|
+
padding: 0 var(--mrd-space-4);
|
|
210
|
+
border-radius: var(--mrd-border-radius);
|
|
211
|
+
border: var(--mrd-border-width) solid transparent;
|
|
212
|
+
font-size: var(--mrd-font-size-sm);
|
|
213
|
+
font-weight: var(--mrd-font-weight-medium);
|
|
214
|
+
cursor: pointer;
|
|
215
|
+
transition: background-color var(--mrd-transition-fast), border-color var(--mrd-transition-fast);
|
|
216
|
+
}
|
|
217
|
+
.mrd-merge-view__btn--primary {
|
|
218
|
+
background: var(--mrd-color-primary);
|
|
219
|
+
color: var(--mrd-color-white);
|
|
220
|
+
}
|
|
221
|
+
.mrd-merge-view__btn--primary:hover {
|
|
222
|
+
background: var(--mrd-color-primary-hover);
|
|
223
|
+
}
|
|
224
|
+
.mrd-merge-view__btn--secondary {
|
|
225
|
+
background: var(--mrd-color-white);
|
|
226
|
+
border-color: var(--mrd-border-color);
|
|
227
|
+
color: var(--mrd-color-neutral-700);
|
|
228
|
+
}
|
|
229
|
+
.mrd-merge-view__btn--secondary:hover {
|
|
230
|
+
background: var(--mrd-color-neutral-50);
|
|
231
|
+
}
|
|
232
|
+
.mrd-merge-view__btn--danger {
|
|
233
|
+
background: var(--mrd-color-danger);
|
|
234
|
+
color: var(--mrd-color-white);
|
|
235
|
+
}
|
|
236
|
+
.mrd-merge-view__btn--danger:hover {
|
|
237
|
+
background: var(--mrd-color-danger-dark);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
@keyframes mrd-merge-view-spin {
|
|
241
|
+
to {
|
|
242
|
+
transform: rotate(360deg);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
import { Host, h } from "@stencil/core";
|
|
2
|
+
import { diffFields, buildPatch, candidateLabel } from "./merge-diff";
|
|
3
|
+
import { MergeSearchStep, MergeCompareStep, MergeConfirmStep } from "./merge-parts";
|
|
4
|
+
/**
|
|
5
|
+
* Merges two DataObjects of the same basic type (FINDING-0114 / TASK-0177).
|
|
6
|
+
* Never performs network I/O itself: it emits `mrdSearch` (host searches and
|
|
7
|
+
* calls `setSearchResults()`, mirroring mrd-relation-field) and `mrdMerge`
|
|
8
|
+
* (host calls the merge endpoint — `POST {winnerHref}/merge` with
|
|
9
|
+
* `{ loser: loserHref, patch }`, per DataController.merge()).
|
|
10
|
+
*
|
|
11
|
+
* Has no exit/cancel affordance of its own — hosts show this inside their
|
|
12
|
+
* own overlay-page chrome (its close button), the same way mrd-layout-section
|
|
13
|
+
* never renders a page-level close button either.
|
|
14
|
+
*/
|
|
15
|
+
export class MrdMergeView {
|
|
16
|
+
constructor() {
|
|
17
|
+
this.locale = navigator.language;
|
|
18
|
+
/** Dot-notation class, passed through on mrdSearch (host may use it to pick the right search endpoint). */
|
|
19
|
+
this.basicType = '';
|
|
20
|
+
/** URL segment for the search endpoint; falls back to basicType when absent. */
|
|
21
|
+
this.mostSignificantClass = '';
|
|
22
|
+
/** Flat FIELD/RELATION items describing the basic type's schema (host flattens SECTION/GROUP, same as mrd-table's `columns`). */
|
|
23
|
+
this.fields = [];
|
|
24
|
+
/** Href of A (winner) — the object the merge screen was opened from. */
|
|
25
|
+
this.currentHref = '';
|
|
26
|
+
/** A's full raw record: flat fields + `_links`, the same row shape CellRenderer.render expects. */
|
|
27
|
+
this.currentRecord = {};
|
|
28
|
+
/** Display name for A, shown in the compare step's column header. */
|
|
29
|
+
this.currentLabel = '';
|
|
30
|
+
this.step = 'search';
|
|
31
|
+
this.searchQuery = '';
|
|
32
|
+
this.searchResults = [];
|
|
33
|
+
this.isLoading = false;
|
|
34
|
+
this.candidate = null;
|
|
35
|
+
this.resolutions = {};
|
|
36
|
+
/** Which history badge popover is open, keyed e.g. `legalName:A` / `legalName:confirm`. */
|
|
37
|
+
this.openHistoryKey = null;
|
|
38
|
+
this.historyClickOutside = null;
|
|
39
|
+
this.searchDebounce = null;
|
|
40
|
+
this.handleSearchInput = (query) => {
|
|
41
|
+
this.searchQuery = query;
|
|
42
|
+
if (this.searchDebounce)
|
|
43
|
+
clearTimeout(this.searchDebounce);
|
|
44
|
+
if (query.trim().length >= 2) {
|
|
45
|
+
this.isLoading = true;
|
|
46
|
+
this.searchDebounce = setTimeout(() => {
|
|
47
|
+
this.mrdSearch.emit({
|
|
48
|
+
query,
|
|
49
|
+
basicType: this.basicType,
|
|
50
|
+
mostSignificantClass: this.mostSignificantClass || undefined,
|
|
51
|
+
});
|
|
52
|
+
}, 300);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
this.searchResults = [];
|
|
56
|
+
this.isLoading = false;
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
this.handleSelect = (record) => {
|
|
60
|
+
this.candidate = record;
|
|
61
|
+
const { conflicts } = diffFields(this.fields, this.currentRecord, record);
|
|
62
|
+
const resolutions = {};
|
|
63
|
+
conflicts.forEach(({ item }) => { var _a; resolutions[(_a = item.name) !== null && _a !== void 0 ? _a : ''] = 'A'; });
|
|
64
|
+
this.resolutions = resolutions;
|
|
65
|
+
this.openHistoryKey = null;
|
|
66
|
+
this.step = 'compare';
|
|
67
|
+
};
|
|
68
|
+
this.handleChangeCandidate = () => {
|
|
69
|
+
this.candidate = null;
|
|
70
|
+
this.resolutions = {};
|
|
71
|
+
this.openHistoryKey = null;
|
|
72
|
+
this.step = 'search';
|
|
73
|
+
};
|
|
74
|
+
this.handleResolve = (name, side) => {
|
|
75
|
+
this.resolutions = Object.assign(Object.assign({}, this.resolutions), { [name]: side });
|
|
76
|
+
};
|
|
77
|
+
this.handleToggleHistory = (key) => {
|
|
78
|
+
this.openHistoryKey = key;
|
|
79
|
+
};
|
|
80
|
+
this.handleContinue = () => {
|
|
81
|
+
this.step = 'confirm';
|
|
82
|
+
};
|
|
83
|
+
this.handleBack = () => {
|
|
84
|
+
this.step = 'compare';
|
|
85
|
+
};
|
|
86
|
+
this.handleConfirm = () => {
|
|
87
|
+
var _a, _b, _c, _d;
|
|
88
|
+
if (!this.candidate)
|
|
89
|
+
return;
|
|
90
|
+
const diff = diffFields(this.fields, this.currentRecord, this.candidate);
|
|
91
|
+
const patch = buildPatch(diff, this.resolutions);
|
|
92
|
+
const loserHref = (_d = (_c = (_b = (_a = this.candidate) === 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 : '';
|
|
93
|
+
this.mrdMerge.emit({ winnerHref: this.currentHref, loserHref, patch });
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
connectedCallback() {
|
|
97
|
+
this.historyClickOutside = (e) => {
|
|
98
|
+
if (!this.el.contains(e.target))
|
|
99
|
+
this.openHistoryKey = null;
|
|
100
|
+
};
|
|
101
|
+
document.addEventListener('mousedown', this.historyClickOutside);
|
|
102
|
+
}
|
|
103
|
+
disconnectedCallback() {
|
|
104
|
+
if (this.historyClickOutside) {
|
|
105
|
+
document.removeEventListener('mousedown', this.historyClickOutside);
|
|
106
|
+
this.historyClickOutside = null;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Stores search results, filtering out A itself regardless of what the
|
|
111
|
+
* host's search returns — A must never appear as a mergeable candidate.
|
|
112
|
+
*/
|
|
113
|
+
async setSearchResults(records) {
|
|
114
|
+
this.searchResults = (records !== null && records !== void 0 ? records : []).filter(r => { var _a, _b, _c; return ((_c = (_b = (_a = r === null || r === void 0 ? void 0 : r._links) === null || _a === void 0 ? void 0 : _a.self) === null || _b === void 0 ? void 0 : _b.href) !== null && _c !== void 0 ? _c : null) !== this.currentHref; });
|
|
115
|
+
this.isLoading = false;
|
|
116
|
+
}
|
|
117
|
+
async setLoading(loading) {
|
|
118
|
+
this.isLoading = loading;
|
|
119
|
+
}
|
|
120
|
+
render() {
|
|
121
|
+
var _a, _b;
|
|
122
|
+
let stepContent;
|
|
123
|
+
if (this.step === 'search') {
|
|
124
|
+
stepContent = (h(MergeSearchStep, { key: '4b79504f62f85274c9cd9681b6819c2318f4246a', locale: this.locale, searchQuery: this.searchQuery, searchResults: this.searchResults, isLoading: this.isLoading, onSearchInput: this.handleSearchInput, onSelect: this.handleSelect }));
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
const diff = diffFields(this.fields, this.currentRecord, this.candidate);
|
|
128
|
+
const bLabel = candidateLabel(this.candidate);
|
|
129
|
+
stepContent = this.step === 'compare' ? (h(MergeCompareStep, { locale: this.locale, currentLabel: this.currentLabel, candidateLabel: bLabel, conflicts: diff.conflicts, autoFilled: diff.autoFilled, recordA: this.currentRecord, recordB: (_a = this.candidate) !== null && _a !== void 0 ? _a : {}, resolutions: this.resolutions, openHistoryKey: this.openHistoryKey, onResolve: this.handleResolve, onToggleHistory: this.handleToggleHistory, onChangeCandidate: this.handleChangeCandidate, onContinue: this.handleContinue })) : (h(MergeConfirmStep, { locale: this.locale, candidateLabel: bLabel, conflicts: diff.conflicts, autoFilled: diff.autoFilled, resolutions: this.resolutions, recordB: (_b = this.candidate) !== null && _b !== void 0 ? _b : {}, openHistoryKey: this.openHistoryKey, onToggleHistory: this.handleToggleHistory, onBack: this.handleBack, onConfirm: this.handleConfirm }));
|
|
130
|
+
}
|
|
131
|
+
return (h(Host, { key: 'f3fc046fa728646e2ff686d2eae30024da3121e1' }, h("div", { key: '55bef786973d22dce49be021cfb78588b119139c', class: "mrd-merge-view" }, stepContent)));
|
|
132
|
+
}
|
|
133
|
+
static get is() { return "mrd-merge-view"; }
|
|
134
|
+
static get encapsulation() { return "scoped"; }
|
|
135
|
+
static get originalStyleUrls() {
|
|
136
|
+
return {
|
|
137
|
+
"$": ["mrd-merge-view.scss"]
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
static get styleUrls() {
|
|
141
|
+
return {
|
|
142
|
+
"$": ["mrd-merge-view.css"]
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
static get properties() {
|
|
146
|
+
return {
|
|
147
|
+
"locale": {
|
|
148
|
+
"type": "string",
|
|
149
|
+
"mutable": false,
|
|
150
|
+
"complexType": {
|
|
151
|
+
"original": "string",
|
|
152
|
+
"resolved": "string",
|
|
153
|
+
"references": {}
|
|
154
|
+
},
|
|
155
|
+
"required": false,
|
|
156
|
+
"optional": false,
|
|
157
|
+
"docs": {
|
|
158
|
+
"tags": [],
|
|
159
|
+
"text": ""
|
|
160
|
+
},
|
|
161
|
+
"getter": false,
|
|
162
|
+
"setter": false,
|
|
163
|
+
"reflect": false,
|
|
164
|
+
"attribute": "locale",
|
|
165
|
+
"defaultValue": "navigator.language"
|
|
166
|
+
},
|
|
167
|
+
"basicType": {
|
|
168
|
+
"type": "string",
|
|
169
|
+
"mutable": false,
|
|
170
|
+
"complexType": {
|
|
171
|
+
"original": "string",
|
|
172
|
+
"resolved": "string",
|
|
173
|
+
"references": {}
|
|
174
|
+
},
|
|
175
|
+
"required": false,
|
|
176
|
+
"optional": false,
|
|
177
|
+
"docs": {
|
|
178
|
+
"tags": [],
|
|
179
|
+
"text": "Dot-notation class, passed through on mrdSearch (host may use it to pick the right search endpoint)."
|
|
180
|
+
},
|
|
181
|
+
"getter": false,
|
|
182
|
+
"setter": false,
|
|
183
|
+
"reflect": false,
|
|
184
|
+
"attribute": "basic-type",
|
|
185
|
+
"defaultValue": "''"
|
|
186
|
+
},
|
|
187
|
+
"mostSignificantClass": {
|
|
188
|
+
"type": "string",
|
|
189
|
+
"mutable": false,
|
|
190
|
+
"complexType": {
|
|
191
|
+
"original": "string",
|
|
192
|
+
"resolved": "string",
|
|
193
|
+
"references": {}
|
|
194
|
+
},
|
|
195
|
+
"required": false,
|
|
196
|
+
"optional": false,
|
|
197
|
+
"docs": {
|
|
198
|
+
"tags": [],
|
|
199
|
+
"text": "URL segment for the search endpoint; falls back to basicType when absent."
|
|
200
|
+
},
|
|
201
|
+
"getter": false,
|
|
202
|
+
"setter": false,
|
|
203
|
+
"reflect": false,
|
|
204
|
+
"attribute": "most-significant-class",
|
|
205
|
+
"defaultValue": "''"
|
|
206
|
+
},
|
|
207
|
+
"fields": {
|
|
208
|
+
"type": "unknown",
|
|
209
|
+
"mutable": false,
|
|
210
|
+
"complexType": {
|
|
211
|
+
"original": "ClientLayoutItem[]",
|
|
212
|
+
"resolved": "ClientLayoutItem[]",
|
|
213
|
+
"references": {
|
|
214
|
+
"ClientLayoutItem": {
|
|
215
|
+
"location": "import",
|
|
216
|
+
"path": "../../../types/client-layout",
|
|
217
|
+
"id": "src/types/client-layout.ts::ClientLayoutItem",
|
|
218
|
+
"referenceLocation": "ClientLayoutItem"
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
},
|
|
222
|
+
"required": false,
|
|
223
|
+
"optional": false,
|
|
224
|
+
"docs": {
|
|
225
|
+
"tags": [],
|
|
226
|
+
"text": "Flat FIELD/RELATION items describing the basic type's schema (host flattens SECTION/GROUP, same as mrd-table's `columns`)."
|
|
227
|
+
},
|
|
228
|
+
"getter": false,
|
|
229
|
+
"setter": false,
|
|
230
|
+
"defaultValue": "[]"
|
|
231
|
+
},
|
|
232
|
+
"currentHref": {
|
|
233
|
+
"type": "string",
|
|
234
|
+
"mutable": false,
|
|
235
|
+
"complexType": {
|
|
236
|
+
"original": "string",
|
|
237
|
+
"resolved": "string",
|
|
238
|
+
"references": {}
|
|
239
|
+
},
|
|
240
|
+
"required": false,
|
|
241
|
+
"optional": false,
|
|
242
|
+
"docs": {
|
|
243
|
+
"tags": [],
|
|
244
|
+
"text": "Href of A (winner) \u2014 the object the merge screen was opened from."
|
|
245
|
+
},
|
|
246
|
+
"getter": false,
|
|
247
|
+
"setter": false,
|
|
248
|
+
"reflect": false,
|
|
249
|
+
"attribute": "current-href",
|
|
250
|
+
"defaultValue": "''"
|
|
251
|
+
},
|
|
252
|
+
"currentRecord": {
|
|
253
|
+
"type": "unknown",
|
|
254
|
+
"mutable": false,
|
|
255
|
+
"complexType": {
|
|
256
|
+
"original": "Record<string, any>",
|
|
257
|
+
"resolved": "any | string",
|
|
258
|
+
"references": {
|
|
259
|
+
"Record": {
|
|
260
|
+
"location": "global",
|
|
261
|
+
"id": "global::Record"
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
},
|
|
265
|
+
"required": false,
|
|
266
|
+
"optional": false,
|
|
267
|
+
"docs": {
|
|
268
|
+
"tags": [],
|
|
269
|
+
"text": "A's full raw record: flat fields + `_links`, the same row shape CellRenderer.render expects."
|
|
270
|
+
},
|
|
271
|
+
"getter": false,
|
|
272
|
+
"setter": false,
|
|
273
|
+
"defaultValue": "{}"
|
|
274
|
+
},
|
|
275
|
+
"currentLabel": {
|
|
276
|
+
"type": "string",
|
|
277
|
+
"mutable": false,
|
|
278
|
+
"complexType": {
|
|
279
|
+
"original": "string",
|
|
280
|
+
"resolved": "string",
|
|
281
|
+
"references": {}
|
|
282
|
+
},
|
|
283
|
+
"required": false,
|
|
284
|
+
"optional": false,
|
|
285
|
+
"docs": {
|
|
286
|
+
"tags": [],
|
|
287
|
+
"text": "Display name for A, shown in the compare step's column header."
|
|
288
|
+
},
|
|
289
|
+
"getter": false,
|
|
290
|
+
"setter": false,
|
|
291
|
+
"reflect": false,
|
|
292
|
+
"attribute": "current-label",
|
|
293
|
+
"defaultValue": "''"
|
|
294
|
+
}
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
static get states() {
|
|
298
|
+
return {
|
|
299
|
+
"step": {},
|
|
300
|
+
"searchQuery": {},
|
|
301
|
+
"searchResults": {},
|
|
302
|
+
"isLoading": {},
|
|
303
|
+
"candidate": {},
|
|
304
|
+
"resolutions": {},
|
|
305
|
+
"openHistoryKey": {}
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
static get events() {
|
|
309
|
+
return [{
|
|
310
|
+
"method": "mrdSearch",
|
|
311
|
+
"name": "mrdSearch",
|
|
312
|
+
"bubbles": true,
|
|
313
|
+
"cancelable": true,
|
|
314
|
+
"composed": true,
|
|
315
|
+
"docs": {
|
|
316
|
+
"tags": [],
|
|
317
|
+
"text": ""
|
|
318
|
+
},
|
|
319
|
+
"complexType": {
|
|
320
|
+
"original": "{ query: string; basicType: string; mostSignificantClass?: string }",
|
|
321
|
+
"resolved": "{ query: string; basicType: string; mostSignificantClass?: string | undefined; }",
|
|
322
|
+
"references": {}
|
|
323
|
+
}
|
|
324
|
+
}, {
|
|
325
|
+
"method": "mrdMerge",
|
|
326
|
+
"name": "mrdMerge",
|
|
327
|
+
"bubbles": true,
|
|
328
|
+
"cancelable": true,
|
|
329
|
+
"composed": true,
|
|
330
|
+
"docs": {
|
|
331
|
+
"tags": [],
|
|
332
|
+
"text": ""
|
|
333
|
+
},
|
|
334
|
+
"complexType": {
|
|
335
|
+
"original": "{ winnerHref: string; loserHref: string; patch: Record<string, unknown> }",
|
|
336
|
+
"resolved": "{ winnerHref: string; loserHref: string; patch: Record<string, unknown>; }",
|
|
337
|
+
"references": {
|
|
338
|
+
"Record": {
|
|
339
|
+
"location": "global",
|
|
340
|
+
"id": "global::Record"
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
}];
|
|
345
|
+
}
|
|
346
|
+
static get methods() {
|
|
347
|
+
return {
|
|
348
|
+
"setSearchResults": {
|
|
349
|
+
"complexType": {
|
|
350
|
+
"signature": "(records: Record<string, any>[]) => Promise<void>",
|
|
351
|
+
"parameters": [{
|
|
352
|
+
"name": "records",
|
|
353
|
+
"type": "Record<string, any>[]",
|
|
354
|
+
"docs": ""
|
|
355
|
+
}],
|
|
356
|
+
"references": {
|
|
357
|
+
"Promise": {
|
|
358
|
+
"location": "global",
|
|
359
|
+
"id": "global::Promise"
|
|
360
|
+
},
|
|
361
|
+
"Record": {
|
|
362
|
+
"location": "global",
|
|
363
|
+
"id": "global::Record"
|
|
364
|
+
}
|
|
365
|
+
},
|
|
366
|
+
"return": "Promise<void>"
|
|
367
|
+
},
|
|
368
|
+
"docs": {
|
|
369
|
+
"text": "Stores search results, filtering out A itself regardless of what the\nhost's search returns \u2014 A must never appear as a mergeable candidate.",
|
|
370
|
+
"tags": []
|
|
371
|
+
}
|
|
372
|
+
},
|
|
373
|
+
"setLoading": {
|
|
374
|
+
"complexType": {
|
|
375
|
+
"signature": "(loading: boolean) => Promise<void>",
|
|
376
|
+
"parameters": [{
|
|
377
|
+
"name": "loading",
|
|
378
|
+
"type": "boolean",
|
|
379
|
+
"docs": ""
|
|
380
|
+
}],
|
|
381
|
+
"references": {
|
|
382
|
+
"Promise": {
|
|
383
|
+
"location": "global",
|
|
384
|
+
"id": "global::Promise"
|
|
385
|
+
}
|
|
386
|
+
},
|
|
387
|
+
"return": "Promise<void>"
|
|
388
|
+
},
|
|
389
|
+
"docs": {
|
|
390
|
+
"text": "",
|
|
391
|
+
"tags": []
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
static get elementRef() { return "el"; }
|
|
397
|
+
}
|
|
@@ -135,6 +135,30 @@ async function apiSearchRelation(token, tenantCode, mostSignificantClass, query)
|
|
|
135
135
|
}));
|
|
136
136
|
}
|
|
137
137
|
|
|
138
|
+
/**
|
|
139
|
+
* Search for merge candidates. Unlike apiSearchRelation, this does NOT map
|
|
140
|
+
* results down to {id, label} — mrd-merge-view needs the full raw records
|
|
141
|
+
* (fields + _links) up front so it can diff without a second fetch per
|
|
142
|
+
* candidate once one is selected.
|
|
143
|
+
*/
|
|
144
|
+
async function apiSearchMergeCandidates(token, tenantCode, mostSignificantClass, query) {
|
|
145
|
+
const q = encodeURIComponent(query);
|
|
146
|
+
const { ok, status, body } = await apiRequest('GET', `/data/${tenantCode}/${mostSignificantClass}?q=${q}`, token);
|
|
147
|
+
if (!ok) throw new Error(`${status}: ${typeof body === 'string' ? body : JSON.stringify(body)}`);
|
|
148
|
+
return (body._embedded && body._embedded[mostSignificantClass]) || [];
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Merge two DataObjects of the same basic type. Mirrors DataController.merge():
|
|
153
|
+
* POST {winnerHref}/merge with { loser: loserHref, patch }. Returns the
|
|
154
|
+
* patched winner record on success.
|
|
155
|
+
*/
|
|
156
|
+
async function apiMerge(token, winnerHref, loserHref, patch) {
|
|
157
|
+
const { ok, status, body } = await apiRequest('POST', `${winnerHref}/merge`, token, { loser: loserHref, patch });
|
|
158
|
+
if (!ok) throw new Error(`${status}: ${typeof body === 'string' ? body : JSON.stringify(body)}`);
|
|
159
|
+
return body;
|
|
160
|
+
}
|
|
161
|
+
|
|
138
162
|
/* =====================================================================
|
|
139
163
|
LAYOUT MAPPERS
|
|
140
164
|
mrd-form and mrd-field now accept the flat API format directly.
|