@reltio/components 1.4.2159 → 1.4.2160

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.
Files changed (43) hide show
  1. package/AddressAutocompleteEditor/AddressAutocompleteEditor.d.ts +10 -0
  2. package/AddressAutocompleteEditor/AddressAutocompleteEditor.js +223 -0
  3. package/AddressAutocompleteEditor/AddressAutocompleteEditor.module.css.js +9 -0
  4. package/AddressAutocompleteEditor/AddressAutocompleteEditor.test.d.ts +1 -0
  5. package/AddressAutocompleteEditor/AddressAutocompleteEditor.test.js +522 -0
  6. package/AddressAutocompleteEditor/helpers.d.ts +10 -0
  7. package/AddressAutocompleteEditor/helpers.js +18 -0
  8. package/AddressAutocompleteEditor/index.d.ts +1 -0
  9. package/AddressAutocompleteEditor/index.js +1 -0
  10. package/EditModeAttributesPager/components/AttributeRenderer/AttributeRenderer.js +1 -1
  11. package/EditorsFactory/EditorsFactory.js +4 -0
  12. package/ReferenceAttributeEditor/ReferenceAttributeEditor.js +5 -3
  13. package/RelationEditor/RelationEditor.js +6 -4
  14. package/SimpleAttributeEditor/SimpleAttributeEditor.d.ts +1 -0
  15. package/SimpleAttributeEditor/SimpleAttributeEditor.js +15 -4
  16. package/cjs/AddressAutocompleteEditor/AddressAutocompleteEditor.d.ts +10 -0
  17. package/cjs/AddressAutocompleteEditor/AddressAutocompleteEditor.js +253 -0
  18. package/cjs/AddressAutocompleteEditor/AddressAutocompleteEditor.module.css.js +9 -0
  19. package/cjs/AddressAutocompleteEditor/AddressAutocompleteEditor.test.d.ts +1 -0
  20. package/cjs/AddressAutocompleteEditor/AddressAutocompleteEditor.test.js +527 -0
  21. package/cjs/AddressAutocompleteEditor/helpers.d.ts +10 -0
  22. package/cjs/AddressAutocompleteEditor/helpers.js +24 -0
  23. package/cjs/AddressAutocompleteEditor/index.d.ts +1 -0
  24. package/cjs/AddressAutocompleteEditor/index.js +5 -0
  25. package/cjs/EditModeAttributesPager/components/AttributeRenderer/AttributeRenderer.js +1 -1
  26. package/cjs/EditorsFactory/EditorsFactory.js +4 -0
  27. package/cjs/ReferenceAttributeEditor/ReferenceAttributeEditor.js +5 -3
  28. package/cjs/RelationEditor/RelationEditor.js +6 -4
  29. package/cjs/SimpleAttributeEditor/SimpleAttributeEditor.d.ts +1 -0
  30. package/cjs/SimpleAttributeEditor/SimpleAttributeEditor.js +14 -3
  31. package/cjs/contexts/AttributeValueContext/index.d.ts +3 -0
  32. package/cjs/contexts/AttributeValueContext/index.js +9 -0
  33. package/cjs/contexts/AutoCompleteContext/helpers.d.ts +24 -0
  34. package/cjs/contexts/AutoCompleteContext/helpers.js +165 -0
  35. package/cjs/contexts/AutoCompleteContext/index.d.ts +12 -0
  36. package/cjs/contexts/AutoCompleteContext/index.js +83 -0
  37. package/contexts/AttributeValueContext/index.d.ts +3 -0
  38. package/contexts/AttributeValueContext/index.js +3 -0
  39. package/contexts/AutoCompleteContext/helpers.d.ts +24 -0
  40. package/contexts/AutoCompleteContext/helpers.js +159 -0
  41. package/contexts/AutoCompleteContext/index.d.ts +12 -0
  42. package/contexts/AutoCompleteContext/index.js +56 -0
  43. package/package.json +2 -2
@@ -0,0 +1,527 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
14
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
15
+ return new (P || (P = Promise))(function (resolve, reject) {
16
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
17
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
18
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
19
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
20
+ });
21
+ };
22
+ var __generator = (this && this.__generator) || function (thisArg, body) {
23
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
24
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
25
+ function verb(n) { return function (v) { return step([n, v]); }; }
26
+ function step(op) {
27
+ if (f) throw new TypeError("Generator is already executing.");
28
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
29
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
30
+ if (y = 0, t) op = [op[0] & 2, t.value];
31
+ switch (op[0]) {
32
+ case 0: case 1: t = op; break;
33
+ case 4: _.label++; return { value: op[1], done: false };
34
+ case 5: _.label++; y = op[1]; op = [0]; continue;
35
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
36
+ default:
37
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
38
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
39
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
40
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
41
+ if (t[2]) _.ops.pop();
42
+ _.trys.pop(); continue;
43
+ }
44
+ op = body.call(thisArg, _);
45
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
46
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
47
+ }
48
+ };
49
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
50
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
51
+ if (ar || !(i in from)) {
52
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
53
+ ar[i] = from[i];
54
+ }
55
+ }
56
+ return to.concat(ar || Array.prototype.slice.call(from));
57
+ };
58
+ var __importDefault = (this && this.__importDefault) || function (mod) {
59
+ return (mod && mod.__esModule) ? mod : { "default": mod };
60
+ };
61
+ Object.defineProperty(exports, "__esModule", { value: true });
62
+ var react_1 = __importDefault(require("react"));
63
+ var ramda_1 = require("ramda");
64
+ var react_2 = require("@testing-library/react");
65
+ var user_event_1 = __importDefault(require("@testing-library/user-event"));
66
+ var AddressAutocompleteEditor_1 = require("./AddressAutocompleteEditor");
67
+ var MdmModuleContext_1 = require("../contexts/MdmModuleContext");
68
+ var mdm_sdk_1 = require("@reltio/mdm-sdk");
69
+ var AutoCompleteContext_1 = require("../contexts/AutoCompleteContext");
70
+ var AttributeValueContext_1 = require("../contexts/AttributeValueContext");
71
+ jest.mock('@reltio/mdm-sdk', function () { return (__assign(__assign({}, jest.requireActual('@reltio/mdm-sdk')), { searchAddresses: jest.fn(), fetchAddressDetails: jest.fn(), debounce: function (fn) { return fn; } })); });
72
+ var tempUriCounter = 1;
73
+ var getTempUriCounter = function () {
74
+ return tempUriCounter++;
75
+ };
76
+ var resetTempUriCounter = function () {
77
+ tempUriCounter = 1;
78
+ return tempUriCounter;
79
+ };
80
+ jest.mock('nanoid', function () {
81
+ return {
82
+ customAlphabet: function () { return function () { return "tempuri".concat(getTempUriCounter(), "_"); }; }
83
+ };
84
+ });
85
+ var mockSearchAddresses = mdm_sdk_1.searchAddresses;
86
+ var mockFetchAddressDetails = mdm_sdk_1.fetchAddressDetails;
87
+ var defaultProps = {
88
+ value: '',
89
+ onChange: jest.fn(),
90
+ fullWidth: true,
91
+ attributeTypeUri: 'configuration/entityTypes/Location/attributes/AddressInput'
92
+ };
93
+ var mockAddressSearchResults = [
94
+ {
95
+ Id: 'address-1',
96
+ Type: mdm_sdk_1.AddressType.Address,
97
+ Text: 'Avenida Jose Malhoa 22, Lisbon',
98
+ Description: 'Jose Malhoa 22'
99
+ }
100
+ ];
101
+ var mockAddressDetails = [
102
+ {
103
+ Id: 'address-1',
104
+ PostalCode: '1070-040',
105
+ City: 'Lisbon',
106
+ Country: 'PT',
107
+ Line1: 'Avenida Jose Malhoa 22'
108
+ }
109
+ ];
110
+ var mockMetadata = {
111
+ entityTypes: [
112
+ {
113
+ uri: 'configuration/entityTypes/Location',
114
+ label: 'Location',
115
+ attributes: [
116
+ {
117
+ uri: 'configuration/entityTypes/Location/attributes/AddressInput',
118
+ name: 'AddressInput',
119
+ label: 'AddressInput',
120
+ type: mdm_sdk_1.DataTypes.TYPE_STRING
121
+ },
122
+ {
123
+ uri: 'configuration/entityTypes/Location/attributes/City',
124
+ name: 'City',
125
+ label: 'City',
126
+ type: mdm_sdk_1.DataTypes.TYPE_STRING
127
+ },
128
+ {
129
+ uri: 'configuration/entityTypes/Location/attributes/AddressLine1',
130
+ name: 'AddressLine1',
131
+ label: 'AddressLine1',
132
+ type: mdm_sdk_1.DataTypes.TYPE_STRING
133
+ },
134
+ {
135
+ uri: 'configuration/entityTypes/Location/attributes/Country',
136
+ name: 'Country',
137
+ label: 'Country',
138
+ type: mdm_sdk_1.DataTypes.TYPE_STRING
139
+ },
140
+ {
141
+ uri: 'configuration/entityTypes/Location/attributes/AddressNested',
142
+ name: 'AddressNested',
143
+ label: 'AddressNested',
144
+ type: mdm_sdk_1.DataTypes.TYPE_NESTED,
145
+ attributes: [
146
+ {
147
+ uri: 'configuration/entityTypes/Location/attributes/AddressNested/attributes/AddressInput',
148
+ name: 'AddressInput',
149
+ label: 'AddressInput',
150
+ type: mdm_sdk_1.DataTypes.TYPE_STRING
151
+ },
152
+ {
153
+ uri: 'configuration/entityTypes/Location/attributes/AddressNested/attributes/City',
154
+ name: 'City',
155
+ label: 'City',
156
+ type: mdm_sdk_1.DataTypes.TYPE_STRING
157
+ }
158
+ ]
159
+ }
160
+ ],
161
+ cleanseConfig: {
162
+ mappings: [],
163
+ addressAutoCompleteConfig: {
164
+ minSearchTextLen: 3,
165
+ providerOpts: {
166
+ defaultCountries: 'PT;US',
167
+ limit: 10
168
+ },
169
+ inputMapping: [
170
+ {
171
+ attribute: 'configuration/entityTypes/Location/attributes/AddressInput',
172
+ cleanseAttribute: mdm_sdk_1.InputCleanseAttributeType.Text,
173
+ allValues: false,
174
+ mandatory: false
175
+ },
176
+ {
177
+ attribute: 'configuration/entityTypes/Location/attributes/Country',
178
+ cleanseAttribute: mdm_sdk_1.InputCleanseAttributeType.Countries,
179
+ allValues: false,
180
+ mandatory: false
181
+ }
182
+ ],
183
+ outputMapping: [
184
+ {
185
+ attribute: 'configuration/entityTypes/Location/attributes/City',
186
+ cleanseAttribute: 'City',
187
+ allValues: false,
188
+ mandatory: false
189
+ },
190
+ {
191
+ attribute: 'configuration/entityTypes/Location/attributes/AddressLine1',
192
+ cleanseAttribute: 'Line1',
193
+ allValues: false,
194
+ mandatory: false
195
+ }
196
+ ]
197
+ }
198
+ }
199
+ }
200
+ ]
201
+ };
202
+ var mockEntity = {
203
+ uri: 'entities/entity1',
204
+ type: 'configuration/entityTypes/Location',
205
+ label: 'Entity 1'
206
+ };
207
+ var mockModifiedEntity = {
208
+ uri: 'entities/entity1',
209
+ type: 'configuration/entityTypes/Location',
210
+ label: 'Entity 1'
211
+ };
212
+ var mockMdmValues = {
213
+ metadata: mockMetadata,
214
+ entity: mockEntity,
215
+ entityWithDiff: mockEntity,
216
+ modifiedEntities: {
217
+ 'entities/entity1': mockModifiedEntity
218
+ }
219
+ };
220
+ var mockMdmActions = {
221
+ modifyAttribute: jest.fn()
222
+ };
223
+ var setUp = function (props, mdmValues, attributeValue) {
224
+ if (props === void 0) { props = {}; }
225
+ if (mdmValues === void 0) { mdmValues = {}; }
226
+ if (attributeValue === void 0) { attributeValue = {}; }
227
+ var Providers = function (_a) {
228
+ var children = _a.children;
229
+ return (react_1.default.createElement(MdmModuleContext_1.MdmModuleProvider, { values: __assign(__assign({}, mockMdmValues), mdmValues), actions: mockMdmActions },
230
+ react_1.default.createElement(AutoCompleteContext_1.AddressAutoCompleteProvider, null,
231
+ react_1.default.createElement(AttributeValueContext_1.AttributeValueContext.Provider, { value: __assign({ uri: 'entities/entity1/attributes/AddressInput/value', type: defaultProps.attributeTypeUri, value: '' }, attributeValue) }, children))));
232
+ };
233
+ return __assign(__assign({}, (0, react_2.render)(react_1.default.createElement(AddressAutocompleteEditor_1.AddressAutocompleteEditor, __assign({}, defaultProps, props)), { wrapper: Providers })), { user: user_event_1.default.setup() });
234
+ };
235
+ describe('AddressAutocompleteEditor', function () {
236
+ beforeAll(function () {
237
+ jest.spyOn(Date, 'now').mockImplementation(function () { return 1752748853454; });
238
+ });
239
+ afterAll(function () {
240
+ Date.now.mockRestore();
241
+ });
242
+ beforeEach(function () {
243
+ jest.clearAllMocks();
244
+ resetTempUriCounter();
245
+ mockSearchAddresses.mockResolvedValue(mockAddressSearchResults);
246
+ mockFetchAddressDetails.mockResolvedValue(mockAddressDetails);
247
+ });
248
+ it('should render main components', function () { return __awaiter(void 0, void 0, void 0, function () {
249
+ var user, input;
250
+ return __generator(this, function (_a) {
251
+ switch (_a.label) {
252
+ case 0:
253
+ user = setUp().user;
254
+ expect(react_2.screen.getByRole('combobox')).toBeInTheDocument();
255
+ expect(react_2.screen.getByPlaceholderText('Start typing to autocomplete')).toBeInTheDocument();
256
+ return [4 /*yield*/, user.type(react_2.screen.getByRole('combobox'), 'Lisbon')];
257
+ case 1:
258
+ _a.sent();
259
+ input = react_2.screen.getByRole('combobox');
260
+ return [4 /*yield*/, user.click(input)];
261
+ case 2:
262
+ _a.sent();
263
+ return [4 /*yield*/, user.paste('Lisbon')];
264
+ case 3:
265
+ _a.sent();
266
+ expect(react_2.screen.getByText('To search in a different country, update the Country field')).toBeInTheDocument();
267
+ expect(react_2.screen.getByText('Searching in: PT, US')).toBeInTheDocument();
268
+ expect(react_2.screen.getByText('Avenida Jose Malhoa 22, Lisbon')).toBeInTheDocument();
269
+ return [2 /*return*/];
270
+ }
271
+ });
272
+ }); });
273
+ it('should show loading state during search', function () { return __awaiter(void 0, void 0, void 0, function () {
274
+ var resolveSearch, searchPromise, user, input;
275
+ return __generator(this, function (_a) {
276
+ switch (_a.label) {
277
+ case 0:
278
+ searchPromise = new Promise(function (resolve) {
279
+ resolveSearch = resolve;
280
+ });
281
+ mockSearchAddresses.mockReturnValue(searchPromise);
282
+ user = setUp().user;
283
+ input = react_2.screen.getByRole('combobox');
284
+ return [4 /*yield*/, user.click(input)];
285
+ case 1:
286
+ _a.sent();
287
+ return [4 /*yield*/, user.paste('Lisbon')];
288
+ case 2:
289
+ _a.sent();
290
+ expect(react_2.screen.getByText('Searching addresses...')).toBeInTheDocument();
291
+ resolveSearch([]);
292
+ return [4 /*yield*/, (0, react_2.waitForElementToBeRemoved)(function () { return react_2.screen.queryByText('Searching addresses...'); })];
293
+ case 3:
294
+ _a.sent();
295
+ return [2 /*return*/];
296
+ }
297
+ });
298
+ }); });
299
+ describe('Address search', function () {
300
+ it('should fetch address suggestions when user types minimum characters', function () { return __awaiter(void 0, void 0, void 0, function () {
301
+ var user, input;
302
+ return __generator(this, function (_a) {
303
+ switch (_a.label) {
304
+ case 0:
305
+ mockSearchAddresses.mockResolvedValue([
306
+ { Id: '1', Type: mdm_sdk_1.AddressType.Address, Text: '123 Main St', Description: 'Test' }
307
+ ]);
308
+ user = setUp().user;
309
+ input = react_2.screen.getByRole('combobox');
310
+ return [4 /*yield*/, user.click(input)];
311
+ case 1:
312
+ _a.sent();
313
+ return [4 /*yield*/, user.paste('Main St')];
314
+ case 2:
315
+ _a.sent();
316
+ expect(mockSearchAddresses).toHaveBeenCalledWith({
317
+ text: 'Main St',
318
+ limit: 10,
319
+ countries: ['PT', 'US']
320
+ });
321
+ return [2 /*return*/];
322
+ }
323
+ });
324
+ }); });
325
+ it('should not fetch suggestions when input is too short', function () { return __awaiter(void 0, void 0, void 0, function () {
326
+ var user, input;
327
+ return __generator(this, function (_a) {
328
+ switch (_a.label) {
329
+ case 0:
330
+ user = setUp().user;
331
+ input = react_2.screen.getByRole('combobox');
332
+ return [4 /*yield*/, user.click(input)];
333
+ case 1:
334
+ _a.sent();
335
+ return [4 /*yield*/, user.paste('Li')];
336
+ case 2:
337
+ _a.sent();
338
+ expect(mockSearchAddresses).not.toHaveBeenCalled();
339
+ return [2 /*return*/];
340
+ }
341
+ });
342
+ }); });
343
+ });
344
+ describe('Option selection', function () {
345
+ it('should handle option selection correctly', function () { return __awaiter(void 0, void 0, void 0, function () {
346
+ var onChange, user, input, option;
347
+ return __generator(this, function (_a) {
348
+ switch (_a.label) {
349
+ case 0:
350
+ onChange = jest.fn();
351
+ user = setUp({ onChange: onChange }).user;
352
+ input = react_2.screen.getByRole('combobox');
353
+ return [4 /*yield*/, user.click(input)];
354
+ case 1:
355
+ _a.sent();
356
+ return [4 /*yield*/, user.paste('Lisbon')];
357
+ case 2:
358
+ _a.sent();
359
+ expect(react_2.screen.getByText('Avenida Jose Malhoa 22, Lisbon')).toBeInTheDocument();
360
+ option = react_2.screen.getByText('Avenida Jose Malhoa 22, Lisbon');
361
+ return [4 /*yield*/, user.click(option)];
362
+ case 3:
363
+ _a.sent();
364
+ expect(onChange).toHaveBeenCalledWith('Avenida Jose Malhoa 22, Lisbon');
365
+ expect(mockFetchAddressDetails).toHaveBeenCalledWith('address-1');
366
+ expect(mockMdmActions.modifyAttribute).toHaveBeenCalledWith({
367
+ attributeType: mockMetadata.entityTypes[0].attributes[1],
368
+ uri: 'entities/entity1/attributes/City/uri$$tempuri1_1752748853454',
369
+ value: 'Lisbon'
370
+ });
371
+ expect(mockMdmActions.modifyAttribute).toHaveBeenCalledWith({
372
+ attributeType: mockMetadata.entityTypes[0].attributes[2],
373
+ uri: 'entities/entity1/attributes/AddressLine1/uri$$tempuri2_1752748853454',
374
+ value: 'Avenida Jose Malhoa 22'
375
+ });
376
+ return [2 /*return*/];
377
+ }
378
+ });
379
+ }); });
380
+ it('should not select container options', function () { return __awaiter(void 0, void 0, void 0, function () {
381
+ var onChange, user, input, option;
382
+ return __generator(this, function (_a) {
383
+ switch (_a.label) {
384
+ case 0:
385
+ onChange = jest.fn();
386
+ mockSearchAddresses.mockResolvedValue([
387
+ { Id: 'container-1', Type: mdm_sdk_1.AddressType.Container, Text: 'Container Option', Description: 'Container' }
388
+ ]);
389
+ user = setUp({ onChange: onChange }).user;
390
+ input = react_2.screen.getByRole('combobox');
391
+ return [4 /*yield*/, user.click(input)];
392
+ case 1:
393
+ _a.sent();
394
+ return [4 /*yield*/, user.paste('Lisbon')];
395
+ case 2:
396
+ _a.sent();
397
+ expect(react_2.screen.getByText('Container Option')).toBeInTheDocument();
398
+ option = react_2.screen.getByText('Container Option');
399
+ return [4 /*yield*/, user.click(option)];
400
+ case 3:
401
+ _a.sent();
402
+ expect(onChange).not.toHaveBeenCalled();
403
+ expect(mockFetchAddressDetails).not.toHaveBeenCalled();
404
+ return [2 /*return*/];
405
+ }
406
+ });
407
+ }); });
408
+ it('should populate only attributes under the trigger attribute for nested attributes', function () { return __awaiter(void 0, void 0, void 0, function () {
409
+ var onChange, attributeTypeUri, addressAutoCompleteConfig, metadata, mdmValues, attributeValue, user, input, option;
410
+ return __generator(this, function (_a) {
411
+ switch (_a.label) {
412
+ case 0:
413
+ onChange = jest.fn();
414
+ attributeTypeUri = 'configuration/entityTypes/Location/attributes/AddressNested/attributes/AddressInput';
415
+ addressAutoCompleteConfig = __assign({}, mockMetadata.entityTypes[0].cleanseConfig.addressAutoCompleteConfig);
416
+ addressAutoCompleteConfig.inputMapping = __spreadArray(__spreadArray([], addressAutoCompleteConfig.inputMapping, true), [
417
+ {
418
+ attribute: 'configuration/entityTypes/Location/attributes/AddressNested/attributes/AddressInput',
419
+ cleanseAttribute: mdm_sdk_1.InputCleanseAttributeType.Text,
420
+ allValues: false,
421
+ mandatory: false
422
+ }
423
+ ], false);
424
+ addressAutoCompleteConfig.outputMapping = __spreadArray(__spreadArray([], addressAutoCompleteConfig.outputMapping, true), [
425
+ {
426
+ attribute: 'configuration/entityTypes/Location/attributes/AddressNested/attributes/City',
427
+ cleanseAttribute: 'City',
428
+ allValues: false,
429
+ mandatory: false
430
+ }
431
+ ], false);
432
+ metadata = (0, ramda_1.assocPath)(['entityTypes', 0, 'cleanseConfig', 'addressAutoCompleteConfig'], addressAutoCompleteConfig, mockMetadata);
433
+ mdmValues = __assign(__assign({}, mockMdmValues), { metadata: metadata });
434
+ attributeValue = {
435
+ uri: 'entities/entity1/attributes/AddressNested/AddressNestedUri/AddressInput/AddressInputUri',
436
+ type: attributeTypeUri
437
+ };
438
+ user = setUp({ attributeTypeUri: attributeTypeUri, onChange: onChange }, mdmValues, attributeValue).user;
439
+ input = react_2.screen.getByRole('combobox');
440
+ return [4 /*yield*/, user.click(input)];
441
+ case 1:
442
+ _a.sent();
443
+ return [4 /*yield*/, user.paste('Lisbon')];
444
+ case 2:
445
+ _a.sent();
446
+ expect(react_2.screen.getByText('Avenida Jose Malhoa 22, Lisbon')).toBeInTheDocument();
447
+ option = react_2.screen.getByText('Avenida Jose Malhoa 22, Lisbon');
448
+ return [4 /*yield*/, user.click(option)];
449
+ case 3:
450
+ _a.sent();
451
+ expect(onChange).toHaveBeenCalledWith('Avenida Jose Malhoa 22, Lisbon');
452
+ expect(mockFetchAddressDetails).toHaveBeenCalledWith('address-1');
453
+ expect(mockMdmActions.modifyAttribute).toHaveBeenCalledTimes(1);
454
+ expect(mockMdmActions.modifyAttribute).toHaveBeenCalledWith({
455
+ attributeType: mockMetadata.entityTypes[0].attributes[4].attributes[1],
456
+ uri: 'entities/entity1/attributes/AddressNested/AddressNestedUri/City/uri$$tempuri1_1752748853454',
457
+ value: 'Lisbon'
458
+ });
459
+ return [2 /*return*/];
460
+ }
461
+ });
462
+ }); });
463
+ });
464
+ describe('Autocomplete settings', function () {
465
+ it('should use default autocomplete settings, when no settings from metadata', function () { return __awaiter(void 0, void 0, void 0, function () {
466
+ var metadata, user, input;
467
+ return __generator(this, function (_a) {
468
+ switch (_a.label) {
469
+ case 0:
470
+ metadata = {
471
+ entityTypes: [
472
+ __assign(__assign({}, mockMetadata.entityTypes[0]), { cleanseConfig: {
473
+ addressAutoCompleteConfig: undefined
474
+ } })
475
+ ]
476
+ };
477
+ user = setUp({}, {
478
+ metadata: metadata
479
+ }).user;
480
+ input = react_2.screen.getByRole('combobox');
481
+ return [4 /*yield*/, user.click(input)];
482
+ case 1:
483
+ _a.sent();
484
+ return [4 /*yield*/, user.paste('Li')];
485
+ case 2:
486
+ _a.sent();
487
+ expect(mockSearchAddresses).not.toHaveBeenCalled();
488
+ return [4 /*yield*/, user.paste('sbon')];
489
+ case 3:
490
+ _a.sent();
491
+ expect(mockSearchAddresses).toHaveBeenCalledWith({
492
+ text: 'Lisbon',
493
+ limit: 10,
494
+ countries: []
495
+ });
496
+ return [2 /*return*/];
497
+ }
498
+ });
499
+ }); });
500
+ it('should use autocomplete settings from metadata', function () { return __awaiter(void 0, void 0, void 0, function () {
501
+ var user, input;
502
+ return __generator(this, function (_a) {
503
+ switch (_a.label) {
504
+ case 0:
505
+ user = setUp().user;
506
+ input = react_2.screen.getByRole('combobox');
507
+ return [4 /*yield*/, user.click(input)];
508
+ case 1:
509
+ _a.sent();
510
+ return [4 /*yield*/, user.paste('Li')];
511
+ case 2:
512
+ _a.sent();
513
+ expect(mockSearchAddresses).not.toHaveBeenCalled();
514
+ return [4 /*yield*/, user.paste('sbon')];
515
+ case 3:
516
+ _a.sent();
517
+ expect(mockSearchAddresses).toHaveBeenCalledWith({
518
+ text: 'Lisbon',
519
+ limit: 10,
520
+ countries: ['PT', 'US']
521
+ });
522
+ return [2 /*return*/];
523
+ }
524
+ });
525
+ }); });
526
+ });
527
+ });
@@ -0,0 +1,10 @@
1
+ import { AddressSearchResult } from '@reltio/mdm-sdk';
2
+ export type AddressOption = {
3
+ id: string;
4
+ type: string;
5
+ fullAddress: string;
6
+ description?: string;
7
+ };
8
+ export declare const convertSearchResultToOption: (result: AddressSearchResult) => AddressOption;
9
+ export declare const getOptionLabel: (option: AddressOption | string) => string;
10
+ export declare const isOptionEqualToValue: (option: AddressOption, value: string) => boolean;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isOptionEqualToValue = exports.getOptionLabel = exports.convertSearchResultToOption = void 0;
4
+ var mdm_sdk_1 = require("@reltio/mdm-sdk");
5
+ var convertSearchResultToOption = function (result) {
6
+ return {
7
+ id: result.Id,
8
+ type: result.Type,
9
+ fullAddress: result.Text,
10
+ description: result.Description
11
+ };
12
+ };
13
+ exports.convertSearchResultToOption = convertSearchResultToOption;
14
+ var getOptionLabel = function (option) {
15
+ return typeof option === 'string' ? option : option.fullAddress;
16
+ };
17
+ exports.getOptionLabel = getOptionLabel;
18
+ var isOptionEqualToValue = function (option, value) {
19
+ if (option.type === mdm_sdk_1.AddressType.Container) {
20
+ return false;
21
+ }
22
+ return option.fullAddress === value;
23
+ };
24
+ exports.isOptionEqualToValue = isOptionEqualToValue;
@@ -0,0 +1 @@
1
+ export { AddressAutocompleteEditor } from './AddressAutocompleteEditor';
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AddressAutocompleteEditor = void 0;
4
+ var AddressAutocompleteEditor_1 = require("./AddressAutocompleteEditor");
5
+ Object.defineProperty(exports, "AddressAutocompleteEditor", { enumerable: true, get: function () { return AddressAutocompleteEditor_1.AddressAutocompleteEditor; } });
@@ -128,7 +128,7 @@ var AttributeRenderer = function (_a) {
128
128
  isEditableMode && react_1.default.createElement(CardinalityMessage_1.CardinalityMessage, { cardinality: cardinality }),
129
129
  isEditableMode && react_1.default.createElement(ErrorMessage_1.ErrorMessage, { message: errorMessage, className: styles.typeError }),
130
130
  react_1.default.createElement("div", { className: styles.attributesWrapper },
131
- shownValues.map(function (value, idx) { return (react_1.default.createElement(EditModeAttributesFactory_1.EditModeAttribute, { key: value.uri, attributeValue: value, attributeType: attributeType, lazy: showEmpty && !isRequired, showEmptyEditors: showEmptyEditors, errors: errors, ownError: (0, mdm_sdk_1.getAttributeOwnError)(value, idx, attributeType.uri, errors), mode: mode, crosswalks: crosswalks, onAddOneMore: lastIndex === idx ? onAddOneMore : null, onAddAttributes: onAddAttributes, onDeleteAttribute: onDelete, onChangeAttribute: onChangeAttribute, onDeactivateError: onDeactivateError, additionalControlsRenderer: additionalControlsRenderer, className: idx === 0 ? highlightedClassName : null, ref: idx === 0 ? attributeRef : null, isEmptyEditor: showEmpty })); }),
131
+ shownValues.map(function (value, idx) { return (react_1.default.createElement(EditModeAttributesFactory_1.EditModeAttribute, { key: value.uri, attributeValue: value, attributeType: attributeType, lazy: showEmpty && !isRequired, showEmptyEditors: showEmptyEditors, errors: errors, ownError: (0, mdm_sdk_1.getAttributeOwnError)(value, idx, attributeType.uri, errors), mode: mode, crosswalks: crosswalks, onAddOneMore: lastIndex === idx ? onAddOneMore : null, onAddAttributes: onAddAttributes, onDeleteAttribute: onDelete, onChangeAttribute: onChangeAttribute, onDeactivateError: onDeactivateError, additionalControlsRenderer: additionalControlsRenderer, className: idx === 0 ? highlightedClassName : null, ref: idx === 0 ? attributeRef : null, isFirstEditor: idx === 0, isEmptyEditor: showEmpty })); }),
132
132
  showMore && (react_1.default.createElement(ShowMore_1.ShowMore, { moreNumber: (0, ramda_1.min)(max, hiddenValuesCount), valueNumber: hiddenValuesCount, onClick: onShowMore })),
133
133
  showLess && react_1.default.createElement(ShowLess_1.ShowLess, { onClick: onShowLess })))));
134
134
  };
@@ -38,9 +38,11 @@ var TypeaheadEditor_1 = require("../TypeaheadEditor");
38
38
  var DependentLookupEditor_1 = require("../DependentLookupEditor");
39
39
  var FileTypeEditor_1 = require("../FileTypeEditor");
40
40
  var SelectEditor_1 = require("../SelectEditor");
41
+ var AddressAutocompleteEditor_1 = require("../AddressAutocompleteEditor/AddressAutocompleteEditor");
41
42
  var EditorsFactory = /** @class */ (function () {
42
43
  function EditorsFactory() {
43
44
  }
45
+ // prettier-ignore
44
46
  EditorsFactory.build = function (type, _a) {
45
47
  if (_a === void 0) { _a = {}; }
46
48
  var fullWidth = _a.fullWidth, TextFieldProps = _a.TextFieldProps, color = _a.color, booleanRadioEditorClassName = _a.booleanRadioEditorClassName, otherProps = __rest(_a, ["fullWidth", "TextFieldProps", "color", "booleanRadioEditorClassName"]);
@@ -89,6 +91,8 @@ var EditorsFactory = /** @class */ (function () {
89
91
  return react_1.default.createElement(DependentLookupEditor_1.DependentLookupEditor, __assign({ fullWidth: fullWidth, TextFieldProps: TextFieldProps }, otherProps));
90
92
  case mdm_sdk_1.DataTypes.TYPE_FILE:
91
93
  return react_1.default.createElement(FileTypeEditor_1.FileTypeEditor, __assign({}, otherProps));
94
+ case mdm_sdk_1.DataTypes.TYPE_ADDRESS_AUTOCOMPLETE:
95
+ return react_1.default.createElement(AddressAutocompleteEditor_1.AddressAutocompleteEditor, __assign({ fullWidth: fullWidth }, TextFieldProps, otherProps));
92
96
  default:
93
97
  return react_1.default.createElement(TextEditor_1.TextEditor, __assign({ fullWidth: fullWidth }, TextFieldProps, otherProps));
94
98
  }
@@ -60,6 +60,7 @@ var ConfigPermissionsContext_1 = require("../contexts/ConfigPermissionsContext")
60
60
  var ScrollToElementContext_1 = require("../contexts/ScrollToElementContext");
61
61
  var MdmModuleContext_1 = require("../contexts/MdmModuleContext");
62
62
  var useScrollToAttributeError_1 = require("../hooks/useScrollToAttributeError");
63
+ var AutoCompleteContext_1 = require("../contexts/AutoCompleteContext");
63
64
  var styles_1 = require("./styles");
64
65
  var ReferenceAttributeEditor = function (props) {
65
66
  var _a;
@@ -150,9 +151,10 @@ var ReferenceAttributeEditor = function (props) {
150
151
  return (react_1.default.createElement(EditModeComplexAttribute_1.EditModeComplexAttribute, __assign({}, ownProps, { label: (0, mdm_sdk_1.getLabel)(label), attributeTypesList: editableAttrTypes, crosswalks: allCrosswalks, metadata: metadata }),
151
152
  react_1.default.createElement("div", { ref: ref, className: errorClassName },
152
153
  react_1.default.createElement(ErrorWrapper_1.ErrorWrapper, { errorMessage: errorMessage },
153
- react_1.default.createElement(EntitySelector_1.EntitySelector, { className: (0, classnames_1.default)(styles.item, (_a = {},
154
- _a[styles.dense] = errorMessage || (selectedEntity && (0, mdm_sdk_1.isTempUri)(selectedEntity.entityUri)),
155
- _a)), entity: selectedEntity || {}, entityTypesUris: entityTypesUris, globalSearchRequestOptions: globalSearchRequestOptions, mode: mode, isDisabled: !canChangeReferencedEntity || !!attributeValue.masked, onChange: onChangeEntity, onCreate: canCreateReferencedEntity ? onCreateEntity : undefined, metadata: metadata, attributeTypesSelectionStrategy: newEntityAttrTypesSelectionStrategy, isMasked: isMasked })))));
154
+ react_1.default.createElement(AutoCompleteContext_1.AddressAutoCompleteProvider, { entityUri: entityUri },
155
+ react_1.default.createElement(EntitySelector_1.EntitySelector, { className: (0, classnames_1.default)(styles.item, (_a = {},
156
+ _a[styles.dense] = errorMessage || (selectedEntity && (0, mdm_sdk_1.isTempUri)(selectedEntity.entityUri)),
157
+ _a)), entity: selectedEntity || {}, entityTypesUris: entityTypesUris, globalSearchRequestOptions: globalSearchRequestOptions, mode: mode, isDisabled: !canChangeReferencedEntity || !!attributeValue.masked, onChange: onChangeEntity, onCreate: canCreateReferencedEntity ? onCreateEntity : undefined, metadata: metadata, attributeTypesSelectionStrategy: newEntityAttrTypesSelectionStrategy, isMasked: isMasked }))))));
156
158
  };
157
159
  exports.default = (0, withContext_1.withContext)(ScrollToElementContext_1.ScrollToElementContext, function (contextValue, _a) {
158
160
  var attributeValue = _a.attributeValue, attributeType = _a.attributeType;
@@ -53,6 +53,7 @@ var ConfigPermissionsContext_1 = require("../contexts/ConfigPermissionsContext")
53
53
  var ScrollToElementContext_1 = require("../contexts/ScrollToElementContext");
54
54
  var MdmModuleContext_1 = require("../contexts/MdmModuleContext");
55
55
  var HiddenAttributesContext_1 = require("../contexts/HiddenAttributesContext");
56
+ var AutoCompleteContext_1 = require("../contexts/AutoCompleteContext");
56
57
  var useScrollToAttributeError_1 = require("../hooks/useScrollToAttributeError");
57
58
  var styles_1 = require("./styles");
58
59
  var areRelatedEntitiesChanged = function (initial, actual) {
@@ -226,10 +227,11 @@ var RelationEditor = function (_a) {
226
227
  Boolean(relationType) && (react_1.default.createElement(ConfigPermissionsContext_1.ConfigPermissionsContextProvider, null,
227
228
  react_1.default.createElement("div", { ref: ref, className: errorClassName },
228
229
  react_1.default.createElement(ErrorWrapper_1.ErrorWrapper, { errorMessage: errorMessage },
229
- react_1.default.createElement(EntitySelector_1.EntitySelector, { className: (0, classnames_1.default)(styles.item, (_b = {},
230
- _b[styles.dense] = errorMessage ||
231
- (connection.entity && (0, mdm_sdk_1.isTempUri)(connection.entity.entityUri)),
232
- _b)), entity: connection.entity || {}, entityTypesUris: getEntityTypesUris() || [], globalSearchRequestOptions: globalSearchRequestOptions, mode: mode, onChange: onChangeEntity, onCreate: canCreateNewEntity ? onCreateEntity : undefined, metadata: metadata, attributeTypesSelectionStrategy: mdm_sdk_1.relationEditorAttributeTypesSelectionStrategy, isMasked: isMasked }))),
230
+ react_1.default.createElement(AutoCompleteContext_1.AddressAutoCompleteProvider, { entityUri: entityUri },
231
+ react_1.default.createElement(EntitySelector_1.EntitySelector, { className: (0, classnames_1.default)(styles.item, (_b = {},
232
+ _b[styles.dense] = errorMessage ||
233
+ (connection.entity && (0, mdm_sdk_1.isTempUri)(connection.entity.entityUri)),
234
+ _b)), entity: connection.entity || {}, entityTypesUris: getEntityTypesUris() || [], globalSearchRequestOptions: globalSearchRequestOptions, mode: mode, onChange: onChangeEntity, onCreate: canCreateNewEntity ? onCreateEntity : undefined, metadata: metadata, attributeTypesSelectionStrategy: mdm_sdk_1.relationEditorAttributeTypesSelectionStrategy, isMasked: isMasked })))),
233
235
  react_1.default.createElement(HiddenAttributesContext_1.HiddenAttributesContext.Provider, { value: emptyHiddenAttributes },
234
236
  react_1.default.createElement(EditModeAttributesList_1.EditModeAttributesList, { className: styles.item, attrTypes: firstLevelRelationAttrTypes, entity: attributeListEntity, showEmptyEditors: true, mode: mode, parentUri: relationUri, onAddAttributes: onAddAttributes, onChangeAttribute: onChangeAttribute, onDeleteAttribute: onDeleteAttribute }))))),
235
237
  react_1.default.createElement("div", { className: styles.actionButtons },