@reltio/components 1.4.2276 → 1.4.2277

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.
@@ -1,10 +1,11 @@
1
1
  import React from 'react';
2
- import { Entity, Metadata, Match, EntitiesMap } from '@reltio/mdm-sdk';
2
+ import { Entity, Metadata, EntitiesMap } from '@reltio/mdm-sdk';
3
3
  import { MatchRuleVariant } from '../types';
4
+ import type { MatchWithRuleLabels } from '../hooks/useMatchesLoader/types';
4
5
  type Props = {
5
6
  entitiesMap: EntitiesMap;
6
7
  entity: Entity;
7
- match: Match;
8
+ match: MatchWithRuleLabels;
8
9
  metadata: Metadata;
9
10
  variant?: MatchRuleVariant;
10
11
  };
@@ -1,3 +1,14 @@
1
+ var __assign = (this && this.__assign) || function () {
2
+ __assign = Object.assign || function(t) {
3
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
4
+ s = arguments[i];
5
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
+ t[p] = s[p];
7
+ }
8
+ return t;
9
+ };
10
+ return __assign.apply(this, arguments);
11
+ };
1
12
  import React from 'react';
2
13
  import { getMatchRules, getTransitiveMatchRules, isTransitiveMatch, NOT_MATCH } from '@reltio/mdm-sdk';
3
14
  import { SimpleMatchRulesBlock } from '../SimpleMatchRulesBlock';
@@ -11,7 +22,10 @@ export var MatchRulesBlock = function (_a) {
11
22
  return null;
12
23
  }
13
24
  var isTransitive = isTransitiveMatch(match);
14
- var matchRules = getMatchRules(metadata, entity.type, (match.matchRules || []).concat(match.negativeRules || []));
25
+ var matchRules = getMatchRules(metadata, entity.type, (match.matchRules || []).concat(match.negativeRules || [])).map(function (matchRule) {
26
+ var _a;
27
+ return (__assign(__assign({}, matchRule), { label: ((_a = match.matchRuleLabels) === null || _a === void 0 ? void 0 : _a[matchRule.uri]) || matchRule.label }));
28
+ });
15
29
  var rules = matchRules.filter(function (_a) {
16
30
  var uri = _a.uri;
17
31
  return uri !== NOT_MATCH;
@@ -163,6 +163,31 @@ describe('MatchRulesBlock test', function () {
163
163
  matchRules: [metadata.entityTypes[0].matchGroups[2]]
164
164
  }));
165
165
  });
166
+ it('should use data tenant match rule labels for rules that are not in customer tenant metadata', function () {
167
+ var _a;
168
+ var dataTenantMatchRuleUri = 'configuration/entityTypes/HCP/matchGroups/DataTenantRule';
169
+ var match = {
170
+ matchRules: [dataTenantMatchRuleUri],
171
+ matchRuleLabels: (_a = {},
172
+ _a[dataTenantMatchRuleUri] = 'Data Tenant Match Rule',
173
+ _a),
174
+ object: {
175
+ uri: 'entities/dataTenantEntity',
176
+ type: 'configuration/entityTypes/HCP',
177
+ dataTenant: 'dt1'
178
+ }
179
+ };
180
+ render(React.createElement(MatchRulesBlock, { match: match, metadata: metadata, entity: entity, entitiesMap: {} }));
181
+ expect(mockTransitiveMatchRules).not.toHaveBeenCalled();
182
+ expect(mockSimpleMatchRulesBuilder).toHaveBeenCalledWith(expect.objectContaining({
183
+ matchRules: [
184
+ {
185
+ uri: dataTenantMatchRuleUri,
186
+ label: 'Data Tenant Match Rule'
187
+ }
188
+ ]
189
+ }));
190
+ });
166
191
  it('should render SimpleMatchRulesBuilder for non transitive match and work correctly with negativeRules', function () {
167
192
  render(React.createElement(MatchRulesBlock, { match: potentialMatches[4], metadata: metadata, entity: entity, entitiesMap: {} }));
168
193
  expect(mockTransitiveMatchRules).not.toHaveBeenCalled();
@@ -1,10 +1,11 @@
1
1
  import React from 'react';
2
- import { Entity, Metadata, Match, EntitiesMap } from '@reltio/mdm-sdk';
2
+ import { Entity, Metadata, EntitiesMap } from '@reltio/mdm-sdk';
3
3
  import { MatchRuleVariant } from '../types';
4
+ import type { MatchWithRuleLabels } from '../hooks/useMatchesLoader/types';
4
5
  type Props = {
5
6
  entitiesMap: EntitiesMap;
6
7
  entity: Entity;
7
- match: Match;
8
+ match: MatchWithRuleLabels;
8
9
  metadata: Metadata;
9
10
  variant?: MatchRuleVariant;
10
11
  };
@@ -1,4 +1,15 @@
1
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
+ };
2
13
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
14
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
15
  };
@@ -17,7 +28,10 @@ var MatchRulesBlock = function (_a) {
17
28
  return null;
18
29
  }
19
30
  var isTransitive = (0, mdm_sdk_1.isTransitiveMatch)(match);
20
- var matchRules = (0, mdm_sdk_1.getMatchRules)(metadata, entity.type, (match.matchRules || []).concat(match.negativeRules || []));
31
+ var matchRules = (0, mdm_sdk_1.getMatchRules)(metadata, entity.type, (match.matchRules || []).concat(match.negativeRules || [])).map(function (matchRule) {
32
+ var _a;
33
+ return (__assign(__assign({}, matchRule), { label: ((_a = match.matchRuleLabels) === null || _a === void 0 ? void 0 : _a[matchRule.uri]) || matchRule.label }));
34
+ });
21
35
  var rules = matchRules.filter(function (_a) {
22
36
  var uri = _a.uri;
23
37
  return uri !== mdm_sdk_1.NOT_MATCH;
@@ -168,6 +168,31 @@ describe('MatchRulesBlock test', function () {
168
168
  matchRules: [metadata.entityTypes[0].matchGroups[2]]
169
169
  }));
170
170
  });
171
+ it('should use data tenant match rule labels for rules that are not in customer tenant metadata', function () {
172
+ var _a;
173
+ var dataTenantMatchRuleUri = 'configuration/entityTypes/HCP/matchGroups/DataTenantRule';
174
+ var match = {
175
+ matchRules: [dataTenantMatchRuleUri],
176
+ matchRuleLabels: (_a = {},
177
+ _a[dataTenantMatchRuleUri] = 'Data Tenant Match Rule',
178
+ _a),
179
+ object: {
180
+ uri: 'entities/dataTenantEntity',
181
+ type: 'configuration/entityTypes/HCP',
182
+ dataTenant: 'dt1'
183
+ }
184
+ };
185
+ (0, react_2.render)(react_1.default.createElement(MatchRulesBlock_1.MatchRulesBlock, { match: match, metadata: metadata, entity: entity, entitiesMap: {} }));
186
+ expect(mockTransitiveMatchRules).not.toHaveBeenCalled();
187
+ expect(mockSimpleMatchRulesBuilder).toHaveBeenCalledWith(expect.objectContaining({
188
+ matchRules: [
189
+ {
190
+ uri: dataTenantMatchRuleUri,
191
+ label: 'Data Tenant Match Rule'
192
+ }
193
+ ]
194
+ }));
195
+ });
171
196
  it('should render SimpleMatchRulesBuilder for non transitive match and work correctly with negativeRules', function () {
172
197
  (0, react_2.render)(react_1.default.createElement(MatchRulesBlock_1.MatchRulesBlock, { match: potentialMatches[4], metadata: metadata, entity: entity, entitiesMap: {} }));
173
198
  expect(mockTransitiveMatchRules).not.toHaveBeenCalled();
@@ -0,0 +1,4 @@
1
+ import { Match } from '@reltio/mdm-sdk';
2
+ export type MatchWithRuleLabels = Match & {
3
+ matchRuleLabels?: Record<string, string>;
4
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,4 +1,5 @@
1
- import { Entity, Match, SortingField, EntitiesMap } from '@reltio/mdm-sdk';
1
+ import { Entity, SortingField, EntitiesMap } from '@reltio/mdm-sdk';
2
+ import type { MatchWithRuleLabels } from './types';
2
3
  type Props = {
3
4
  enabled: boolean;
4
5
  entity: Entity;
@@ -17,7 +18,7 @@ type Props = {
17
18
  };
18
19
  export declare const useMatchesLoader: ({ enabled, entity, filter, rules, onFinishLoading, onStartLoading, options, page, rowsPerPage, sorting, markMatchedValues }: Props) => {
19
20
  total: number;
20
- matches: Match[];
21
+ matches: MatchWithRuleLabels[];
21
22
  entitiesMap: EntitiesMap<Pick<Entity, "label" | "type" | "uri">>;
22
23
  loadMatches: () => void;
23
24
  };
@@ -17,18 +17,48 @@ var mdm_sdk_1 = require("@reltio/mdm-sdk");
17
17
  var usePagingSimulator_1 = require("../usePagingSimulator");
18
18
  var useSafePromise_1 = require("../useSafePromise");
19
19
  var MdmModuleContext_1 = require("../../contexts/MdmModuleContext");
20
+ var matchRuleLabelsCache = new Map();
21
+ // Match rule labels are static per (dtssPath, customerTenant), so the request is
22
+ // cached and reused across reloads (paging, filtering, sorting) instead of being
23
+ // refetched every time matches are loaded. Failed requests are evicted so a later
24
+ // load can retry.
25
+ var getCachedDataTenantMatchRuleLabels = function (dtssPath, customerTenant) {
26
+ var cacheKey = "".concat(dtssPath, "::").concat(customerTenant);
27
+ var cachedRequest = matchRuleLabelsCache.get(cacheKey);
28
+ if (cachedRequest !== undefined) {
29
+ return cachedRequest;
30
+ }
31
+ var request = (0, mdm_sdk_1.getDataTenantMatchGroups)({ dtssPath: dtssPath, customerTenant: customerTenant }).catch(function () {
32
+ matchRuleLabelsCache.delete(cacheKey);
33
+ return {};
34
+ });
35
+ matchRuleLabelsCache.set(cacheKey, request);
36
+ return request;
37
+ };
38
+ var addDataTenantMatchRuleLabels = function (matches, entity, matchRuleLabels) {
39
+ if (!Object.keys(matchRuleLabels).length) {
40
+ return matches;
41
+ }
42
+ return matches.map(function (match) {
43
+ var _a;
44
+ return ((0, mdm_sdk_1.isDataTenantEntity)(entity) || (0, mdm_sdk_1.isDataTenantEntity)(match.object)) &&
45
+ ((_a = match.matchRules) === null || _a === void 0 ? void 0 : _a.some(function (matchRuleUri) { return matchRuleLabels[matchRuleUri]; }))
46
+ ? __assign(__assign({}, match), { matchRuleLabels: matchRuleLabels }) : match;
47
+ });
48
+ };
20
49
  var useMatchesLoader = function (_a) {
21
50
  var enabled = _a.enabled, entity = _a.entity, filter = _a.filter, rules = _a.rules, onFinishLoading = _a.onFinishLoading, onStartLoading = _a.onStartLoading, options = _a.options, page = _a.page, rowsPerPage = _a.rowsPerPage, sorting = _a.sorting, markMatchedValues = _a.markMatchedValues;
22
51
  var _b = sorting || {}, order = _b.order, field = _b.field;
23
52
  var _c = (0, react_1.useState)(0), total = _c[0], setTotal = _c[1];
24
53
  var _d = (0, react_1.useState)([]), matches = _d[0], setMatches = _d[1];
25
- var _e = (0, react_1.useState)({}), entitiesMap = _e[0], setEntitiesMap = _e[1];
54
+ var _e = (0, react_1.useState)({}), matchRuleLabels = _e[0], setMatchRuleLabels = _e[1];
55
+ var _f = (0, react_1.useState)({}), entitiesMap = _f[0], setEntitiesMap = _f[1];
26
56
  var metadata = (0, MdmModuleContext_1.useMdmMetadata)();
27
57
  var tenant = (0, MdmModuleContext_1.useMdmTenant)();
28
58
  var dtssPath = (0, MdmModuleContext_1.useMdmDtssPath)();
29
59
  var dataTenants = (0, MdmModuleContext_1.useMdmDataTenantsWithIdBuilder)();
30
60
  var showMasking = (0, MdmModuleContext_1.useMdmShowMasking)();
31
- var _f = (0, MdmModuleContext_1.useMdmGlobalSearchRequestOptions)() || {}, activityFilter = _f.activityFilter, globalFilter = _f.globalFilter;
61
+ var _g = (0, MdmModuleContext_1.useMdmGlobalSearchRequestOptions)() || {}, activityFilter = _g.activityFilter, globalFilter = _g.globalFilter;
32
62
  var activeness = typeof options.showInactiveEntities === 'boolean'
33
63
  ? options.showInactiveEntities
34
64
  ? mdm_sdk_1.ActivityFilter.ALL
@@ -51,6 +81,7 @@ var useMatchesLoader = function (_a) {
51
81
  var getTransitiveMatchesWithPaging = (0, usePagingSimulator_1.usePagingSimulator)(getTransitiveMatchesWithDtss);
52
82
  var getPagedMatchesForDataTenantEntity = (0, usePagingSimulator_1.usePagingSimulator)(mdm_sdk_1.getMatchesForDataTenantEntity);
53
83
  var safePromise = (0, useSafePromise_1.useSafePromise)();
84
+ var safeMatchRuleLabelsPromise = (0, useSafePromise_1.useSafePromise)();
54
85
  var getMatches = (0, react_1.useCallback)(function (force) {
55
86
  if (force === void 0) { force = false; }
56
87
  if (!enabled || (0, mdm_sdk_1.isTempUri)(entityUri)) {
@@ -60,7 +91,7 @@ var useMatchesLoader = function (_a) {
60
91
  return;
61
92
  }
62
93
  onStartLoading === null || onStartLoading === void 0 ? void 0 : onStartLoading();
63
- safePromise((0, mdm_sdk_1.isDataTenantEntity)(entity)
94
+ var matchesRequest = (0, mdm_sdk_1.isDataTenantEntity)(entity)
64
95
  ? getPagedMatchesForDataTenantEntity({
65
96
  dtssPath: dtssPath,
66
97
  entity: entity,
@@ -80,7 +111,8 @@ var useMatchesLoader = function (_a) {
80
111
  markMatchedValues: markMatchedValues,
81
112
  deep: options.showTransitiveMatches ? undefined : 1,
82
113
  activeness: activeness
83
- }, showMasking)), { offset: page * rowsPerPage, force: force })))
114
+ }, showMasking)), { offset: page * rowsPerPage, force: force }));
115
+ safePromise(matchesRequest)
84
116
  .then(function (result) {
85
117
  var response = result.response, total = result.total, originalResponse = result.originalResponse;
86
118
  setTotal(total);
@@ -126,12 +158,27 @@ var useMatchesLoader = function (_a) {
126
158
  (0, react_1.useEffect)(function () {
127
159
  getMatches();
128
160
  }, [getMatches]);
161
+ // Match rule labels are loaded independently of the matches request so the
162
+ // matches list renders without waiting for them; they are applied as a
163
+ // derived layer once available. Keyed on a stable boolean rather than the
164
+ // dataTenants array reference to avoid re-firing on every render.
165
+ var hasDataTenants = !!(dataTenants === null || dataTenants === void 0 ? void 0 : dataTenants.length);
166
+ (0, react_1.useEffect)(function () {
167
+ if (!dtssPath || !tenant || !hasDataTenants) {
168
+ setMatchRuleLabels({});
169
+ return;
170
+ }
171
+ safeMatchRuleLabelsPromise(getCachedDataTenantMatchRuleLabels(dtssPath, tenant))
172
+ .then(setMatchRuleLabels)
173
+ .catch(function () { return setMatchRuleLabels({}); });
174
+ }, [dtssPath, tenant, hasDataTenants, safeMatchRuleLabelsPromise]);
175
+ var matchesWithRuleLabels = (0, react_1.useMemo)(function () { return addDataTenantMatchRuleLabels(matches, entity, matchRuleLabels); }, [matches, entity, matchRuleLabels]);
129
176
  var loadMatches = (0, react_1.useCallback)(function () {
130
177
  getMatches(true);
131
178
  }, [getMatches]);
132
179
  return {
133
180
  total: total,
134
- matches: matches,
181
+ matches: matchesWithRuleLabels,
135
182
  entitiesMap: entitiesMap,
136
183
  loadMatches: loadMatches
137
184
  };
@@ -55,7 +55,7 @@ var mdm_sdk_1 = require("@reltio/mdm-sdk");
55
55
  var react_2 = require("@testing-library/react");
56
56
  var MdmModuleContext_1 = require("../../contexts/MdmModuleContext");
57
57
  var useMatchesLoader_1 = require("./useMatchesLoader");
58
- jest.mock('@reltio/mdm-sdk', function () { return (__assign(__assign({}, jest.requireActual('@reltio/mdm-sdk')), { getTransitiveMatches: jest.fn(), getMatchesForDataTenantEntity: jest.fn(), isDataTenantEntity: jest.fn().mockImplementation(function (entity) { return !!entity.dataTenant; }) })); });
58
+ jest.mock('@reltio/mdm-sdk', function () { return (__assign(__assign({}, jest.requireActual('@reltio/mdm-sdk')), { getTransitiveMatches: jest.fn(), getMatchesForDataTenantEntity: jest.fn(), getDataTenantMatchGroups: jest.fn(), isDataTenantEntity: jest.fn().mockImplementation(function (entity) { return !!entity.dataTenant; }) })); });
59
59
  /**
60
60
  * useMatchesLoader runs a useEffect that calls getMatches() on mount. getMatches() is async:
61
61
  * it calls the SDK (getTransitiveMatches / getMatchesForDataTenantEntity), and when the
@@ -192,4 +192,47 @@ describe('Test useMatchesLoader hook', function () {
192
192
  }
193
193
  });
194
194
  }); });
195
+ it('should add data tenant match rule labels to DTSS matches', function () { return __awaiter(void 0, void 0, void 0, function () {
196
+ var matchRuleUri, result;
197
+ var _a;
198
+ return __generator(this, function (_b) {
199
+ switch (_b.label) {
200
+ case 0:
201
+ matchRuleUri = 'configuration/entityTypes/HCP/matchGroups/DataTenantRule';
202
+ mdm_sdk_1.getMatchesForDataTenantEntity.mockResolvedValueOnce([
203
+ {
204
+ object: {
205
+ uri: 'entities/customerTenantMatch',
206
+ type: 'configuration/entityTypes/HCP'
207
+ },
208
+ matchRules: [matchRuleUri]
209
+ }
210
+ ]);
211
+ mdm_sdk_1.getDataTenantMatchGroups.mockResolvedValueOnce((_a = {},
212
+ _a[matchRuleUri] = 'Data Tenant Match Rule',
213
+ _a));
214
+ result = setUp({
215
+ props: __assign(__assign({}, defaultProps), { entity: __assign(__assign({}, defaultProps.entity), { dataTenant: 'tenantId4' }) }),
216
+ mdmValues: __assign(__assign({}, defaultMdmValues), { dtssPath: 'dtssPath/', tenant: { id: 'customerTenant', name: 'customerTenant' } })
217
+ }).result;
218
+ return [4 /*yield*/, (0, react_2.waitFor)(function () {
219
+ var _a;
220
+ expect(result.current.matches).toEqual([
221
+ expect.objectContaining({
222
+ matchRuleLabels: (_a = {},
223
+ _a[matchRuleUri] = 'Data Tenant Match Rule',
224
+ _a)
225
+ })
226
+ ]);
227
+ })];
228
+ case 1:
229
+ _b.sent();
230
+ expect(mdm_sdk_1.getDataTenantMatchGroups).toHaveBeenCalledWith({
231
+ dtssPath: 'dtssPath/',
232
+ customerTenant: 'customerTenant'
233
+ });
234
+ return [2 /*return*/];
235
+ }
236
+ });
237
+ }); });
195
238
  });
@@ -0,0 +1,4 @@
1
+ import { Match } from '@reltio/mdm-sdk';
2
+ export type MatchWithRuleLabels = Match & {
3
+ matchRuleLabels?: Record<string, string>;
4
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -1,4 +1,5 @@
1
- import { Entity, Match, SortingField, EntitiesMap } from '@reltio/mdm-sdk';
1
+ import { Entity, SortingField, EntitiesMap } from '@reltio/mdm-sdk';
2
+ import type { MatchWithRuleLabels } from './types';
2
3
  type Props = {
3
4
  enabled: boolean;
4
5
  entity: Entity;
@@ -17,7 +18,7 @@ type Props = {
17
18
  };
18
19
  export declare const useMatchesLoader: ({ enabled, entity, filter, rules, onFinishLoading, onStartLoading, options, page, rowsPerPage, sorting, markMatchedValues }: Props) => {
19
20
  total: number;
20
- matches: Match[];
21
+ matches: MatchWithRuleLabels[];
21
22
  entitiesMap: EntitiesMap<Pick<Entity, "label" | "type" | "uri">>;
22
23
  loadMatches: () => void;
23
24
  };
@@ -10,22 +10,52 @@ var __assign = (this && this.__assign) || function () {
10
10
  return __assign.apply(this, arguments);
11
11
  };
12
12
  import { useCallback, useEffect, useMemo, useState } from 'react';
13
- import { ActivityFilter, collectAllTransitiveEntitiesUris, getEntitiesMapForTransitiveMatches, getMatchesForDataTenantEntity, getMatchesFromDataTenants, getTransitiveMatches, isDataTenantEntity, isTempUri, withDtssPotentialItems, addGlobalFilterToQuery, addGetTransitiveMatchesMaskingOptions } from '@reltio/mdm-sdk';
13
+ import { ActivityFilter, collectAllTransitiveEntitiesUris, getEntitiesMapForTransitiveMatches, getDataTenantMatchGroups, getMatchesForDataTenantEntity, getMatchesFromDataTenants, getTransitiveMatches, isDataTenantEntity, isTempUri, withDtssPotentialItems, addGlobalFilterToQuery, addGetTransitiveMatchesMaskingOptions } from '@reltio/mdm-sdk';
14
14
  import { usePagingSimulator } from '../usePagingSimulator';
15
15
  import { useSafePromise } from '../useSafePromise';
16
16
  import { useMdmDataTenantsWithIdBuilder, useMdmDtssPath, useMdmGlobalSearchRequestOptions, useMdmMetadata, useMdmTenant, useMdmShowMasking } from '../../contexts/MdmModuleContext';
17
+ var matchRuleLabelsCache = new Map();
18
+ // Match rule labels are static per (dtssPath, customerTenant), so the request is
19
+ // cached and reused across reloads (paging, filtering, sorting) instead of being
20
+ // refetched every time matches are loaded. Failed requests are evicted so a later
21
+ // load can retry.
22
+ var getCachedDataTenantMatchRuleLabels = function (dtssPath, customerTenant) {
23
+ var cacheKey = "".concat(dtssPath, "::").concat(customerTenant);
24
+ var cachedRequest = matchRuleLabelsCache.get(cacheKey);
25
+ if (cachedRequest !== undefined) {
26
+ return cachedRequest;
27
+ }
28
+ var request = getDataTenantMatchGroups({ dtssPath: dtssPath, customerTenant: customerTenant }).catch(function () {
29
+ matchRuleLabelsCache.delete(cacheKey);
30
+ return {};
31
+ });
32
+ matchRuleLabelsCache.set(cacheKey, request);
33
+ return request;
34
+ };
35
+ var addDataTenantMatchRuleLabels = function (matches, entity, matchRuleLabels) {
36
+ if (!Object.keys(matchRuleLabels).length) {
37
+ return matches;
38
+ }
39
+ return matches.map(function (match) {
40
+ var _a;
41
+ return (isDataTenantEntity(entity) || isDataTenantEntity(match.object)) &&
42
+ ((_a = match.matchRules) === null || _a === void 0 ? void 0 : _a.some(function (matchRuleUri) { return matchRuleLabels[matchRuleUri]; }))
43
+ ? __assign(__assign({}, match), { matchRuleLabels: matchRuleLabels }) : match;
44
+ });
45
+ };
17
46
  export var useMatchesLoader = function (_a) {
18
47
  var enabled = _a.enabled, entity = _a.entity, filter = _a.filter, rules = _a.rules, onFinishLoading = _a.onFinishLoading, onStartLoading = _a.onStartLoading, options = _a.options, page = _a.page, rowsPerPage = _a.rowsPerPage, sorting = _a.sorting, markMatchedValues = _a.markMatchedValues;
19
48
  var _b = sorting || {}, order = _b.order, field = _b.field;
20
49
  var _c = useState(0), total = _c[0], setTotal = _c[1];
21
50
  var _d = useState([]), matches = _d[0], setMatches = _d[1];
22
- var _e = useState({}), entitiesMap = _e[0], setEntitiesMap = _e[1];
51
+ var _e = useState({}), matchRuleLabels = _e[0], setMatchRuleLabels = _e[1];
52
+ var _f = useState({}), entitiesMap = _f[0], setEntitiesMap = _f[1];
23
53
  var metadata = useMdmMetadata();
24
54
  var tenant = useMdmTenant();
25
55
  var dtssPath = useMdmDtssPath();
26
56
  var dataTenants = useMdmDataTenantsWithIdBuilder();
27
57
  var showMasking = useMdmShowMasking();
28
- var _f = useMdmGlobalSearchRequestOptions() || {}, activityFilter = _f.activityFilter, globalFilter = _f.globalFilter;
58
+ var _g = useMdmGlobalSearchRequestOptions() || {}, activityFilter = _g.activityFilter, globalFilter = _g.globalFilter;
29
59
  var activeness = typeof options.showInactiveEntities === 'boolean'
30
60
  ? options.showInactiveEntities
31
61
  ? ActivityFilter.ALL
@@ -48,6 +78,7 @@ export var useMatchesLoader = function (_a) {
48
78
  var getTransitiveMatchesWithPaging = usePagingSimulator(getTransitiveMatchesWithDtss);
49
79
  var getPagedMatchesForDataTenantEntity = usePagingSimulator(getMatchesForDataTenantEntity);
50
80
  var safePromise = useSafePromise();
81
+ var safeMatchRuleLabelsPromise = useSafePromise();
51
82
  var getMatches = useCallback(function (force) {
52
83
  if (force === void 0) { force = false; }
53
84
  if (!enabled || isTempUri(entityUri)) {
@@ -57,7 +88,7 @@ export var useMatchesLoader = function (_a) {
57
88
  return;
58
89
  }
59
90
  onStartLoading === null || onStartLoading === void 0 ? void 0 : onStartLoading();
60
- safePromise(isDataTenantEntity(entity)
91
+ var matchesRequest = isDataTenantEntity(entity)
61
92
  ? getPagedMatchesForDataTenantEntity({
62
93
  dtssPath: dtssPath,
63
94
  entity: entity,
@@ -77,7 +108,8 @@ export var useMatchesLoader = function (_a) {
77
108
  markMatchedValues: markMatchedValues,
78
109
  deep: options.showTransitiveMatches ? undefined : 1,
79
110
  activeness: activeness
80
- }, showMasking)), { offset: page * rowsPerPage, force: force })))
111
+ }, showMasking)), { offset: page * rowsPerPage, force: force }));
112
+ safePromise(matchesRequest)
81
113
  .then(function (result) {
82
114
  var response = result.response, total = result.total, originalResponse = result.originalResponse;
83
115
  setTotal(total);
@@ -123,12 +155,27 @@ export var useMatchesLoader = function (_a) {
123
155
  useEffect(function () {
124
156
  getMatches();
125
157
  }, [getMatches]);
158
+ // Match rule labels are loaded independently of the matches request so the
159
+ // matches list renders without waiting for them; they are applied as a
160
+ // derived layer once available. Keyed on a stable boolean rather than the
161
+ // dataTenants array reference to avoid re-firing on every render.
162
+ var hasDataTenants = !!(dataTenants === null || dataTenants === void 0 ? void 0 : dataTenants.length);
163
+ useEffect(function () {
164
+ if (!dtssPath || !tenant || !hasDataTenants) {
165
+ setMatchRuleLabels({});
166
+ return;
167
+ }
168
+ safeMatchRuleLabelsPromise(getCachedDataTenantMatchRuleLabels(dtssPath, tenant))
169
+ .then(setMatchRuleLabels)
170
+ .catch(function () { return setMatchRuleLabels({}); });
171
+ }, [dtssPath, tenant, hasDataTenants, safeMatchRuleLabelsPromise]);
172
+ var matchesWithRuleLabels = useMemo(function () { return addDataTenantMatchRuleLabels(matches, entity, matchRuleLabels); }, [matches, entity, matchRuleLabels]);
126
173
  var loadMatches = useCallback(function () {
127
174
  getMatches(true);
128
175
  }, [getMatches]);
129
176
  return {
130
177
  total: total,
131
- matches: matches,
178
+ matches: matchesWithRuleLabels,
132
179
  entitiesMap: entitiesMap,
133
180
  loadMatches: loadMatches
134
181
  };
@@ -46,11 +46,11 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
46
46
  }
47
47
  };
48
48
  import React from 'react';
49
- import { getTransitiveMatches, getMatchesForDataTenantEntity } from '@reltio/mdm-sdk';
49
+ import { getTransitiveMatches, getMatchesForDataTenantEntity, getDataTenantMatchGroups } from '@reltio/mdm-sdk';
50
50
  import { renderHook, waitFor } from '@testing-library/react';
51
51
  import { MdmModuleProvider } from '../../contexts/MdmModuleContext';
52
52
  import { useMatchesLoader } from './useMatchesLoader';
53
- jest.mock('@reltio/mdm-sdk', function () { return (__assign(__assign({}, jest.requireActual('@reltio/mdm-sdk')), { getTransitiveMatches: jest.fn(), getMatchesForDataTenantEntity: jest.fn(), isDataTenantEntity: jest.fn().mockImplementation(function (entity) { return !!entity.dataTenant; }) })); });
53
+ jest.mock('@reltio/mdm-sdk', function () { return (__assign(__assign({}, jest.requireActual('@reltio/mdm-sdk')), { getTransitiveMatches: jest.fn(), getMatchesForDataTenantEntity: jest.fn(), getDataTenantMatchGroups: jest.fn(), isDataTenantEntity: jest.fn().mockImplementation(function (entity) { return !!entity.dataTenant; }) })); });
54
54
  /**
55
55
  * useMatchesLoader runs a useEffect that calls getMatches() on mount. getMatches() is async:
56
56
  * it calls the SDK (getTransitiveMatches / getMatchesForDataTenantEntity), and when the
@@ -187,4 +187,47 @@ describe('Test useMatchesLoader hook', function () {
187
187
  }
188
188
  });
189
189
  }); });
190
+ it('should add data tenant match rule labels to DTSS matches', function () { return __awaiter(void 0, void 0, void 0, function () {
191
+ var matchRuleUri, result;
192
+ var _a;
193
+ return __generator(this, function (_b) {
194
+ switch (_b.label) {
195
+ case 0:
196
+ matchRuleUri = 'configuration/entityTypes/HCP/matchGroups/DataTenantRule';
197
+ getMatchesForDataTenantEntity.mockResolvedValueOnce([
198
+ {
199
+ object: {
200
+ uri: 'entities/customerTenantMatch',
201
+ type: 'configuration/entityTypes/HCP'
202
+ },
203
+ matchRules: [matchRuleUri]
204
+ }
205
+ ]);
206
+ getDataTenantMatchGroups.mockResolvedValueOnce((_a = {},
207
+ _a[matchRuleUri] = 'Data Tenant Match Rule',
208
+ _a));
209
+ result = setUp({
210
+ props: __assign(__assign({}, defaultProps), { entity: __assign(__assign({}, defaultProps.entity), { dataTenant: 'tenantId4' }) }),
211
+ mdmValues: __assign(__assign({}, defaultMdmValues), { dtssPath: 'dtssPath/', tenant: { id: 'customerTenant', name: 'customerTenant' } })
212
+ }).result;
213
+ return [4 /*yield*/, waitFor(function () {
214
+ var _a;
215
+ expect(result.current.matches).toEqual([
216
+ expect.objectContaining({
217
+ matchRuleLabels: (_a = {},
218
+ _a[matchRuleUri] = 'Data Tenant Match Rule',
219
+ _a)
220
+ })
221
+ ]);
222
+ })];
223
+ case 1:
224
+ _b.sent();
225
+ expect(getDataTenantMatchGroups).toHaveBeenCalledWith({
226
+ dtssPath: 'dtssPath/',
227
+ customerTenant: 'customerTenant'
228
+ });
229
+ return [2 /*return*/];
230
+ }
231
+ });
232
+ }); });
190
233
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reltio/components",
3
- "version": "1.4.2276",
3
+ "version": "1.4.2277",
4
4
  "license": "SEE LICENSE IN LICENSE FILE",
5
5
  "main": "./cjs/index.js",
6
6
  "module": "./index.js",
@@ -11,7 +11,7 @@
11
11
  "@fluentui/react-context-selector": "^9.1.26",
12
12
  "@googlemaps/markerclusterer": "^2.5.3",
13
13
  "@react-sigma/core": "3.4.0",
14
- "@reltio/mdm-sdk": "^1.4.2052",
14
+ "@reltio/mdm-sdk": "^1.4.2053",
15
15
  "@vis.gl/react-google-maps": "^1.3.0",
16
16
  "d3-cloud": "^1.2.5",
17
17
  "d3-geo": "^2.0.1",