@reltio/components 1.4.2219 → 1.4.2221

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 (57) hide show
  1. package/ExportDialog/ExportDialog.d.ts +15 -0
  2. package/ExportDialog/ExportDialog.js +144 -0
  3. package/ExportDialog/ExportDialog.module.css.js +9 -0
  4. package/ExportDialog/ExportDialog.test.d.ts +1 -0
  5. package/ExportDialog/ExportDialog.test.js +285 -0
  6. package/ExportDialog/index.d.ts +1 -0
  7. package/ExportDialog/index.js +1 -0
  8. package/SimpleAttributeEditor/SimpleAttributeEditor.js +4 -1
  9. package/SimpleAttributeEditor/SimpleAttributeEditor.test.js +40 -3
  10. package/cjs/ExportDialog/ExportDialog.d.ts +15 -0
  11. package/cjs/ExportDialog/ExportDialog.js +174 -0
  12. package/cjs/ExportDialog/ExportDialog.module.css.js +9 -0
  13. package/cjs/ExportDialog/ExportDialog.test.d.ts +1 -0
  14. package/cjs/ExportDialog/ExportDialog.test.js +290 -0
  15. package/cjs/ExportDialog/index.d.ts +1 -0
  16. package/cjs/ExportDialog/index.js +5 -0
  17. package/cjs/SimpleAttributeEditor/SimpleAttributeEditor.js +4 -1
  18. package/cjs/SimpleAttributeEditor/SimpleAttributeEditor.test.js +40 -3
  19. package/cjs/contexts/AuthoringPerspectiveViewContext/index.d.ts +2 -0
  20. package/cjs/contexts/AuthoringPerspectiveViewContext/index.js +9 -0
  21. package/cjs/contexts/MdmModuleContext/context.d.ts +2 -0
  22. package/cjs/contexts/MdmModuleContext/hooks.d.ts +1 -0
  23. package/cjs/contexts/MdmModuleContext/hooks.js +3 -1
  24. package/cjs/contexts/SnackbarContext/index.d.ts +9 -2
  25. package/cjs/features/workflow/ReassignButton/components/ReassignDialog/styles.d.ts +1 -1
  26. package/cjs/hooks/useExportController/index.d.ts +1 -0
  27. package/cjs/hooks/useExportController/index.js +5 -0
  28. package/cjs/hooks/useExportController/useExportController.d.ts +11 -0
  29. package/cjs/hooks/useExportController/useExportController.js +20 -0
  30. package/cjs/hooks/useInternalExport/index.d.ts +1 -0
  31. package/cjs/hooks/useInternalExport/index.js +5 -0
  32. package/cjs/hooks/useInternalExport/useInternalExport.d.ts +35 -0
  33. package/cjs/hooks/useInternalExport/useInternalExport.js +205 -0
  34. package/cjs/hooks/useSnackbar/useSnackbar.d.ts +2 -1
  35. package/cjs/hooks/useSnackbar/useSnackbar.js +23 -4
  36. package/cjs/index.d.ts +2 -0
  37. package/cjs/index.js +8 -4
  38. package/contexts/AuthoringPerspectiveViewContext/index.d.ts +2 -0
  39. package/contexts/AuthoringPerspectiveViewContext/index.js +3 -0
  40. package/contexts/MdmModuleContext/context.d.ts +2 -0
  41. package/contexts/MdmModuleContext/hooks.d.ts +1 -0
  42. package/contexts/MdmModuleContext/hooks.js +1 -0
  43. package/contexts/SnackbarContext/index.d.ts +9 -2
  44. package/features/workflow/ReassignButton/components/ReassignDialog/styles.d.ts +1 -1
  45. package/hooks/useExportController/index.d.ts +1 -0
  46. package/hooks/useExportController/index.js +1 -0
  47. package/hooks/useExportController/useExportController.d.ts +11 -0
  48. package/hooks/useExportController/useExportController.js +16 -0
  49. package/hooks/useInternalExport/index.d.ts +1 -0
  50. package/hooks/useInternalExport/index.js +1 -0
  51. package/hooks/useInternalExport/useInternalExport.d.ts +35 -0
  52. package/hooks/useInternalExport/useInternalExport.js +198 -0
  53. package/hooks/useSnackbar/useSnackbar.d.ts +2 -1
  54. package/hooks/useSnackbar/useSnackbar.js +24 -5
  55. package/index.d.ts +2 -0
  56. package/index.js +2 -0
  57. package/package.json +2 -2
@@ -0,0 +1,15 @@
1
+ import React from 'react';
2
+ import { ActivityFilter } from '@reltio/mdm-sdk';
3
+ type Props = {
4
+ open: boolean;
5
+ onClose: () => void;
6
+ profilesCount: number;
7
+ columnsByEntityType: Record<string, string[]>;
8
+ filter?: string;
9
+ activityFilter: ActivityFilter;
10
+ isSearchByOv: boolean;
11
+ onExternalExport: () => void;
12
+ onLoadingChange?: (loading: boolean) => void;
13
+ };
14
+ export declare const ExportDialog: ({ open, onClose, columnsByEntityType, profilesCount, onExternalExport, onLoadingChange, filter, activityFilter, isSearchByOv }: Props) => React.JSX.Element;
15
+ export {};
@@ -0,0 +1,144 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ var __generator = (this && this.__generator) || function (thisArg, body) {
11
+ 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);
12
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
13
+ function verb(n) { return function (v) { return step([n, v]); }; }
14
+ function step(op) {
15
+ if (f) throw new TypeError("Generator is already executing.");
16
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
17
+ 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;
18
+ if (y = 0, t) op = [op[0] & 2, t.value];
19
+ switch (op[0]) {
20
+ case 0: case 1: t = op; break;
21
+ case 4: _.label++; return { value: op[1], done: false };
22
+ case 5: _.label++; y = op[1]; op = [0]; continue;
23
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
24
+ default:
25
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
26
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
27
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
28
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
29
+ if (t[2]) _.ops.pop();
30
+ _.trys.pop(); continue;
31
+ }
32
+ op = body.call(thisArg, _);
33
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
34
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
35
+ }
36
+ };
37
+ import React, { useCallback, useContext, useMemo, useRef } from 'react';
38
+ import i18n from 'ui-i18n';
39
+ import Dialog from '@mui/material/Dialog';
40
+ import DialogTitle from '@mui/material/DialogTitle';
41
+ import DialogActions from '@mui/material/DialogActions';
42
+ import Button from '@mui/material/Button';
43
+ import DialogContent from '@mui/material/DialogContent';
44
+ import Typography from '@mui/material/Typography';
45
+ import TextField from '@mui/material/TextField';
46
+ import { DropDownSelector } from '../DropDownSelector';
47
+ import { useInternalExport } from '../hooks/useInternalExport';
48
+ import { SnackbarContext } from '../contexts/SnackbarContext';
49
+ import { useMdmAction } from '../contexts/MdmModuleContext';
50
+ import { showErrorMessage } from '../helpers/errors';
51
+ import { ErrorWrapper } from '../ErrorWrapper';
52
+ import styles from './ExportDialog.module.css';
53
+ export var ExportDialog = function (_a) {
54
+ var open = _a.open, onClose = _a.onClose, columnsByEntityType = _a.columnsByEntityType, profilesCount = _a.profilesCount, onExternalExport = _a.onExternalExport, onLoadingChange = _a.onLoadingChange, _b = _a.filter, filter = _b === void 0 ? '' : _b, activityFilter = _a.activityFilter, isSearchByOv = _a.isSearchByOv;
55
+ var showSnackbarMessage = useContext(SnackbarContext);
56
+ var openConsoleApp = useMdmAction('openConsoleApp');
57
+ var isExportingRef = useRef(false);
58
+ var _c = useInternalExport({
59
+ columnsByEntityType: columnsByEntityType,
60
+ dialogOpen: open,
61
+ filter: filter,
62
+ activityFilter: activityFilter,
63
+ isSearchByOv: isSearchByOv
64
+ }), exportName = _c.exportName, onChangeExportName = _c.onChangeExportName, fileFormat = _c.fileFormat, onChangeFileFormat = _c.onChangeFileFormat, formatOptions = _c.formatOptions, onExport = _c.onExport, entityTypesDetails = _c.entityTypesDetails;
65
+ var handleConfirm = useCallback(function () { return __awaiter(void 0, void 0, void 0, function () {
66
+ var result, failedCount, successfulCount, failedJobsString, errorMessage, error;
67
+ var _a, _b;
68
+ return __generator(this, function (_c) {
69
+ switch (_c.label) {
70
+ case 0:
71
+ if (isExportingRef.current)
72
+ return [2 /*return*/];
73
+ isExportingRef.current = true;
74
+ onLoadingChange === null || onLoadingChange === void 0 ? void 0 : onLoadingChange(true);
75
+ onClose();
76
+ _c.label = 1;
77
+ case 1:
78
+ _c.trys.push([1, , 3, 4]);
79
+ return [4 /*yield*/, onExport()];
80
+ case 2:
81
+ result = _c.sent();
82
+ if (result) {
83
+ failedCount = ((_a = result.failedJobs) === null || _a === void 0 ? void 0 : _a.length) || 0;
84
+ successfulCount = result.total - failedCount;
85
+ if (successfulCount > 0) {
86
+ showSnackbarMessage({
87
+ message: i18n.text("Your export job is underway. We'll send an email with the download link once it's complete."),
88
+ action: {
89
+ label: i18n.text('View progress'),
90
+ onClick: function () {
91
+ openConsoleApp('Export');
92
+ }
93
+ }
94
+ });
95
+ }
96
+ if (failedCount > 0) {
97
+ failedJobsString = (_b = result.failedJobs) === null || _b === void 0 ? void 0 : _b.join(', ');
98
+ errorMessage = i18n.text('Failed to export ${failedJobsString}.', { failedJobsString: failedJobsString });
99
+ error = new Error(errorMessage);
100
+ showErrorMessage(error, {
101
+ message: errorMessage
102
+ });
103
+ }
104
+ }
105
+ return [3 /*break*/, 4];
106
+ case 3:
107
+ isExportingRef.current = false;
108
+ onLoadingChange === null || onLoadingChange === void 0 ? void 0 : onLoadingChange(false);
109
+ return [7 /*endfinally*/];
110
+ case 4: return [2 /*return*/];
111
+ }
112
+ });
113
+ }); }, [onClose, onExport, showSnackbarMessage, openConsoleApp, onLoadingChange]);
114
+ var handleExternalExport = useCallback(function () {
115
+ onClose();
116
+ onExternalExport();
117
+ }, [onExternalExport, onClose]);
118
+ var renderDetails = useMemo(function () { return (React.createElement(React.Fragment, null, Object.values(entityTypesDetails).map(function (data, index) { return (React.createElement("span", { key: index },
119
+ React.createElement("span", { className: styles.attributesCount }, data.label),
120
+ i18n.text('(${selected}/${total} attributes)', {
121
+ selected: data.selectedAttributesCount,
122
+ total: data.totalAttributesCount
123
+ }),
124
+ index < Object.values(entityTypesDetails).length - 1 && ', ')); }))); }, [entityTypesDetails]);
125
+ return (React.createElement(Dialog, { open: open, onClose: onClose, fullWidth: true, classes: { paper: styles.dialog } },
126
+ React.createElement(DialogTitle, { classes: { root: styles.dialogTitle } }, i18n.text('Export')),
127
+ React.createElement(DialogContent, { classes: { root: styles.dialogContent } },
128
+ React.createElement(ErrorWrapper, { errorMessage: exportName ? '' : i18n.text('This field is required') },
129
+ React.createElement(TextField, { label: i18n.text('Name your export'), value: exportName, onChange: onChangeExportName, variant: 'filled', fullWidth: true, size: 'small', required: true })),
130
+ React.createElement(Typography, { variant: "subtitle2", className: styles.subtitle }, i18n.text('Data selected')),
131
+ React.createElement("div", { className: styles.summary },
132
+ React.createElement(Typography, { className: styles.totalCaption, color: "textSecondary" },
133
+ React.createElement("span", { className: styles.totalNumber }, i18n.number(profilesCount, '0,0')),
134
+ profilesCount === 1 ? i18n.text('Profile') : i18n.text('Profiles')),
135
+ React.createElement(Typography, { variant: "body2", color: "textSecondary" }, renderDetails)),
136
+ React.createElement(Typography, { variant: "subtitle2", className: styles.subtitle }, i18n.text('Export options')),
137
+ React.createElement(DropDownSelector, { height: 44, value: fileFormat, onChange: onChangeFileFormat, label: i18n.text('File format'), options: formatOptions }),
138
+ React.createElement("div", { className: styles.externalExportWrapper },
139
+ React.createElement(Typography, { component: "span", variant: "body2" }, i18n.text('Want more export options?')),
140
+ React.createElement(Button, { onClick: handleExternalExport, color: "primary" }, i18n.text('Go to export application')))),
141
+ React.createElement(DialogActions, { classes: { root: styles.dialogActions } },
142
+ React.createElement(Button, { onClick: onClose }, i18n.text('Cancel')),
143
+ React.createElement(Button, { onClick: handleConfirm, color: "primary", disabled: !exportName }, i18n.text('Export')))));
144
+ };
@@ -0,0 +1,9 @@
1
+ const styles = {"dialog":"ExportDialog-dialog--lQGKH","dialogTitle":"ExportDialog-dialogTitle--xpDLc","dialogContent":"ExportDialog-dialogContent--r--OS","dialogActions":"ExportDialog-dialogActions--jfCax","subtitle":"ExportDialog-subtitle--rwHDK","summary":"ExportDialog-summary--TlOEd","externalExportWrapper":"ExportDialog-externalExportWrapper--vaAXD","totalCaption":"ExportDialog-totalCaption--DpfR-","totalNumber":"ExportDialog-totalNumber--emHu3","attributesCount":"ExportDialog-attributesCount--NRt8X"};
2
+ if (typeof document !== 'undefined') {
3
+ const head = document.head || document.getElementsByTagName('head')[0]
4
+ const style = document.createElement('style');
5
+ style.type = 'text/css'
6
+ style.innerHTML = `.ExportDialog-dialog--lQGKH{width:600px}.ExportDialog-dialogTitle--xpDLc{padding:16px 16px 4px}.ExportDialog-dialogContent--r--OS{padding:20px 16px}.ExportDialog-dialogActions--jfCax{padding:8px}.ExportDialog-subtitle--rwHDK{margin:24px 0 6px}.ExportDialog-summary--TlOEd{background-color:#fafafa;border-radius:4px;padding:12px 16px}.ExportDialog-externalExportWrapper--vaAXD{padding:16px 0}.ExportDialog-totalCaption--DpfR-{font-size:18px;padding-bottom:8px}.ExportDialog-totalNumber--emHu3{font-size:20px;font-weight:500}.ExportDialog-attributesCount--NRt8X,.ExportDialog-totalNumber--emHu3{color:rgba(0,0,0,.87);margin-right:5px}`;
7
+ head.appendChild(style);
8
+ }
9
+ export default styles;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,285 @@
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
+ };
12
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
13
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
14
+ return new (P || (P = Promise))(function (resolve, reject) {
15
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
16
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
17
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
18
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
19
+ });
20
+ };
21
+ var __generator = (this && this.__generator) || function (thisArg, body) {
22
+ 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);
23
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
24
+ function verb(n) { return function (v) { return step([n, v]); }; }
25
+ function step(op) {
26
+ if (f) throw new TypeError("Generator is already executing.");
27
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
28
+ 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;
29
+ if (y = 0, t) op = [op[0] & 2, t.value];
30
+ switch (op[0]) {
31
+ case 0: case 1: t = op; break;
32
+ case 4: _.label++; return { value: op[1], done: false };
33
+ case 5: _.label++; y = op[1]; op = [0]; continue;
34
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
35
+ default:
36
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
37
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
38
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
39
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
40
+ if (t[2]) _.ops.pop();
41
+ _.trys.pop(); continue;
42
+ }
43
+ op = body.call(thisArg, _);
44
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
45
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
46
+ }
47
+ };
48
+ import React from 'react';
49
+ import { render, screen } from '@testing-library/react';
50
+ import userEvent from '@testing-library/user-event';
51
+ import { createTheme } from '@mui/material/styles';
52
+ import { ThemeProvider } from '@mui/styles';
53
+ import { ActivityFilter, exportData, ExportDataFormat, ExportHeaderOrder } from '@reltio/mdm-sdk';
54
+ import { SnackbarContext } from '../contexts/SnackbarContext';
55
+ import { ExportDialog } from '../ExportDialog';
56
+ import { MdmModuleProvider } from '../contexts/MdmModuleContext';
57
+ import { ErrorPopup } from '../ErrorPopup';
58
+ import { theme } from '../constants';
59
+ jest.mock('@reltio/mdm-sdk', function () { return (__assign(__assign({}, jest.requireActual('@reltio/mdm-sdk')), { exportData: jest.fn() })); });
60
+ var metadata = {
61
+ entityTypes: [
62
+ {
63
+ uri: 'configuration/entityTypes/HCP',
64
+ label: 'HCP',
65
+ attributes: [
66
+ {
67
+ uri: 'configuration/entityTypes/HCP/attributes/FirstName',
68
+ type: 'String',
69
+ name: 'FirstName',
70
+ label: 'First Name',
71
+ access: ['READ', 'CREATE', 'UPDATE', 'INITIATE_CHANGE_REQUEST']
72
+ },
73
+ {
74
+ uri: 'configuration/entityTypes/HCP/attributes/LastName',
75
+ type: 'String',
76
+ name: 'LastName',
77
+ label: 'Last Name',
78
+ access: ['READ', 'CREATE', 'UPDATE', 'INITIATE_CHANGE_REQUEST']
79
+ },
80
+ {
81
+ uri: 'configuration/entityTypes/HCP/attributes/Phone',
82
+ type: 'String',
83
+ name: 'Phone',
84
+ label: 'Phone',
85
+ access: ['READ', 'CREATE', 'UPDATE', 'INITIATE_CHANGE_REQUEST']
86
+ }
87
+ ]
88
+ },
89
+ {
90
+ uri: 'configuration/entityTypes/HCO',
91
+ label: 'HCO',
92
+ attributes: [
93
+ {
94
+ label: 'Name',
95
+ name: 'Name',
96
+ type: 'String',
97
+ uri: 'configuration/entityTypes/HCO/attributes/Name'
98
+ },
99
+ {
100
+ label: 'Status',
101
+ name: 'Status',
102
+ type: 'String',
103
+ uri: 'configuration/entityTypes/HCO/attributes/Status'
104
+ }
105
+ ]
106
+ }
107
+ ]
108
+ };
109
+ var mdmValues = {
110
+ metadata: metadata,
111
+ exportPath: '/nui/export',
112
+ tenant: {
113
+ id: 't1',
114
+ name: 't1'
115
+ }
116
+ };
117
+ var mdmActions = { openConsoleApp: jest.fn() };
118
+ var defaultProps = {
119
+ open: true,
120
+ onClose: jest.fn(),
121
+ columnsByEntityType: {
122
+ 'configuration/entityTypes/HCP': ['attributes.FirstName', 'attributes.LastName'],
123
+ 'configuration/entityTypes/HCO': []
124
+ },
125
+ profilesCount: 15,
126
+ onExternalExport: jest.fn(),
127
+ onLoadingChange: jest.fn(),
128
+ filter: "(equals(type,'configuration/entityTypes/HCP') or equals(type,'configuration/entityTypes/HCO'))",
129
+ activityFilter: ActivityFilter.ALL,
130
+ isSearchByOv: true
131
+ };
132
+ var showSnackbarMessage = jest.fn();
133
+ var setUp = function (props) {
134
+ if (props === void 0) { props = defaultProps; }
135
+ var user = userEvent.setup();
136
+ var Providers = function (_a) {
137
+ var children = _a.children;
138
+ return (React.createElement(ThemeProvider, { theme: createTheme(theme) },
139
+ React.createElement(SnackbarContext.Provider, { value: showSnackbarMessage },
140
+ React.createElement(MdmModuleProvider, { values: mdmValues, actions: mdmActions },
141
+ React.createElement(ErrorPopup, null),
142
+ children))));
143
+ };
144
+ return __assign(__assign({}, render(React.createElement(ExportDialog, __assign({}, props)), { wrapper: Providers })), { user: user });
145
+ };
146
+ describe('ExportDialog tests', function () {
147
+ beforeEach(function () {
148
+ exportData.mockResolvedValue({ status: 'scheduled' });
149
+ });
150
+ afterEach(function () {
151
+ jest.clearAllMocks();
152
+ });
153
+ it('should render dialog correctly', function () {
154
+ jest.useFakeTimers();
155
+ jest.setSystemTime(new Date(2025, 10, 25, 9, 10, 0));
156
+ setUp();
157
+ expect(screen.getByRole('dialog')).toBeInTheDocument();
158
+ expect(screen.getByLabelText('Export')).toBeInTheDocument();
159
+ expect(screen.getByText('Name your export')).toBeInTheDocument();
160
+ expect(screen.getByDisplayValue('Untitled Export Job 11252025_09:10')).toBeInTheDocument();
161
+ expect(screen.getByText('Data selected')).toBeInTheDocument();
162
+ expect(screen.getByText('15')).toBeInTheDocument();
163
+ expect(screen.getByText('Profiles')).toBeInTheDocument();
164
+ expect(screen.getByText('HCP')).toBeInTheDocument();
165
+ expect(screen.getByText('(2/13 attributes),')).toBeInTheDocument();
166
+ expect(screen.getByText('HCO')).toBeInTheDocument();
167
+ expect(screen.getByText('(12/12 attributes)')).toBeInTheDocument();
168
+ expect(screen.getByText('Export options')).toBeInTheDocument();
169
+ expect(screen.getByText('File format')).toBeInTheDocument();
170
+ expect(screen.getByText('CSV Flattened')).toBeInTheDocument();
171
+ expect(screen.getByText('Want more export options?')).toBeInTheDocument();
172
+ expect(screen.getByRole('button', { name: 'Go to export application' })).toBeInTheDocument();
173
+ expect(screen.getByRole('button', { name: 'Cancel' })).toBeInTheDocument();
174
+ expect(screen.getByRole('button', { name: 'Export' })).toBeInTheDocument();
175
+ jest.useRealTimers();
176
+ });
177
+ it('should call onClose when Cancel button is clicked', function () { return __awaiter(void 0, void 0, void 0, function () {
178
+ var user;
179
+ return __generator(this, function (_a) {
180
+ switch (_a.label) {
181
+ case 0:
182
+ user = setUp().user;
183
+ return [4 /*yield*/, user.click(screen.getByRole('button', { name: 'Cancel' }))];
184
+ case 1:
185
+ _a.sent();
186
+ expect(defaultProps.onClose).toHaveBeenCalled();
187
+ return [2 /*return*/];
188
+ }
189
+ });
190
+ }); });
191
+ it('should call onExternalExport when Go to export application button is clicked', function () { return __awaiter(void 0, void 0, void 0, function () {
192
+ var user;
193
+ return __generator(this, function (_a) {
194
+ switch (_a.label) {
195
+ case 0:
196
+ user = setUp().user;
197
+ return [4 /*yield*/, user.click(screen.getByRole('button', { name: 'Go to export application' }))];
198
+ case 1:
199
+ _a.sent();
200
+ expect(defaultProps.onExternalExport).toHaveBeenCalled();
201
+ return [2 /*return*/];
202
+ }
203
+ });
204
+ }); });
205
+ it('should call onExport once and shows snackbar action on success', function () { return __awaiter(void 0, void 0, void 0, function () {
206
+ var user;
207
+ return __generator(this, function (_a) {
208
+ switch (_a.label) {
209
+ case 0:
210
+ jest.useFakeTimers();
211
+ jest.setSystemTime(new Date(2025, 10, 25, 9, 10, 0));
212
+ user = setUp().user;
213
+ jest.useRealTimers();
214
+ return [4 /*yield*/, user.click(screen.getByRole('button', { name: 'Export' }))];
215
+ case 1:
216
+ _a.sent();
217
+ expect(defaultProps.onLoadingChange).toHaveBeenCalledWith(true);
218
+ expect(exportData).toHaveBeenCalledTimes(2);
219
+ expect(exportData).toHaveBeenCalledWith(expect.objectContaining({
220
+ exportPath: '/nui/export',
221
+ tenant: 't1',
222
+ options: {
223
+ fileFormat: ExportDataFormat.CSV,
224
+ dateFormat: 'readable',
225
+ filter: defaultProps.filter,
226
+ activeness: ActivityFilter.ALL,
227
+ options: 'parallelExecution,searchByOv',
228
+ name: 'Untitled Export Job 11252025_09:10_HCP',
229
+ select: 'attributes.FirstName,attributes.LastName'
230
+ },
231
+ includeType: ['configuration/entityTypes/HCP'],
232
+ headerOrder: ExportHeaderOrder.Select
233
+ }));
234
+ expect(exportData).toHaveBeenCalledWith(expect.objectContaining({
235
+ exportPath: '/nui/export',
236
+ tenant: 't1',
237
+ options: {
238
+ fileFormat: ExportDataFormat.CSV,
239
+ dateFormat: 'readable',
240
+ filter: defaultProps.filter,
241
+ activeness: ActivityFilter.ALL,
242
+ options: 'parallelExecution,searchByOv',
243
+ name: 'Untitled Export Job 11252025_09:10_entities',
244
+ sendHidden: false
245
+ },
246
+ includeType: ['configuration/entityTypes/HCO'],
247
+ headerOrder: ExportHeaderOrder.Default
248
+ }));
249
+ expect(defaultProps.onLoadingChange).toHaveBeenCalledWith(false);
250
+ expect(defaultProps.onClose).toHaveBeenCalled();
251
+ expect(showSnackbarMessage).toHaveBeenCalledWith({
252
+ message: "Your export job is underway. We'll send an email with the download link once it's complete.",
253
+ action: {
254
+ label: 'View progress',
255
+ onClick: expect.any(Function)
256
+ }
257
+ });
258
+ return [2 /*return*/];
259
+ }
260
+ });
261
+ }); });
262
+ it('should show error message when some export jobs failed', function () { return __awaiter(void 0, void 0, void 0, function () {
263
+ var user, errorMessage;
264
+ return __generator(this, function (_a) {
265
+ switch (_a.label) {
266
+ case 0:
267
+ exportData.mockRejectedValueOnce(new Error('Failed to export configuration/entityTypes/HCP'));
268
+ exportData.mockResolvedValueOnce({ status: 'scheduled' });
269
+ user = setUp().user;
270
+ return [4 /*yield*/, user.click(screen.getByRole('button', { name: 'Export' }))];
271
+ case 1:
272
+ _a.sent();
273
+ expect(defaultProps.onLoadingChange).toHaveBeenCalledWith(true);
274
+ expect(exportData).toHaveBeenCalledTimes(2);
275
+ expect(defaultProps.onLoadingChange).toHaveBeenCalledWith(false);
276
+ expect(defaultProps.onClose).toHaveBeenCalled();
277
+ return [4 /*yield*/, screen.findByTestId('error-message')];
278
+ case 2:
279
+ errorMessage = _a.sent();
280
+ expect(errorMessage).toHaveTextContent('Failed to export configuration/entityTypes/HCP.');
281
+ return [2 /*return*/];
282
+ }
283
+ });
284
+ }); });
285
+ });
@@ -0,0 +1 @@
1
+ export { ExportDialog } from './ExportDialog';
@@ -0,0 +1 @@
1
+ export { ExportDialog } from './ExportDialog';
@@ -47,6 +47,7 @@ import { DependentLookupAutopopulationContext } from '../contexts/DependentLooku
47
47
  import { useStyles } from './styles';
48
48
  import { AddressAutoCompleteContext } from '../contexts/AutoCompleteContext';
49
49
  import { AttributeValueContext } from '../contexts/AttributeValueContext';
50
+ import { AuthoringPerspectiveViewContext } from '../contexts/AuthoringPerspectiveViewContext';
50
51
  var AsyncMountPlaceholder = function () {
51
52
  var styles = useStyles();
52
53
  return React.createElement("div", { className: styles.placeholder });
@@ -112,8 +113,10 @@ var SimpleAttributeEditor = function (_a) {
112
113
  var hasError = !!errorMessage;
113
114
  var deletedProps = deleted ? { disabled: true, isCrossedOut: true } : {};
114
115
  var isProfilePerspectiveView = useContext(ProfilePerspectiveViewContext);
116
+ var isAuthoringPerspectiveView = useContext(AuthoringPerspectiveViewContext);
117
+ var isEntityPerspectiveView = isProfilePerspectiveView || isAuthoringPerspectiveView;
115
118
  var autopopulationContextValue = useAutopopulationContextValue({
116
- enabled: isProfilePerspectiveView && isDependentLookupAttrType(attributeType),
119
+ enabled: isEntityPerspectiveView && isDependentLookupAttrType(attributeType),
117
120
  attributeTypeUri: attributeType === null || attributeType === void 0 ? void 0 : attributeType.uri,
118
121
  valueUri: attributeValue.uri
119
122
  }).autopopulationContextValue;
@@ -54,6 +54,7 @@ import { ProfilePerspectiveViewContext } from '../contexts/ProfilePerspectiveVie
54
54
  import { ScrollType, ScrollToElementContext } from '../contexts/ScrollToElementContext';
55
55
  import { MdmModuleProvider, useMdmDependentLookupEditorContext } from '../contexts/MdmModuleContext';
56
56
  import { AlwaysVisibleAttributesContext } from '../contexts/AlwaysVisibleAttributesContext';
57
+ import { AuthoringPerspectiveViewContext } from '../contexts/AuthoringPerspectiveViewContext';
57
58
  import { useAutopopulationContextValue } from './useAutopopulationContextValue';
58
59
  import { useScrollToAttributeError } from '../hooks/useScrollToAttributeError';
59
60
  import { useAsyncMount } from '../hooks/useAsyncMount';
@@ -105,7 +106,7 @@ describe('SimpleAttributeEditor', function () {
105
106
  onDeactivateError: jest.fn()
106
107
  };
107
108
  var setUp = function (_a) {
108
- var _b = _a === void 0 ? {} : _a, _c = _b.props, props = _c === void 0 ? {} : _c, _d = _b.error, error = _d === void 0 ? null : _d, _e = _b.isProfilePerspective, isProfilePerspective = _e === void 0 ? false : _e, _f = _b.alwaysVisibleAttributes, alwaysVisibleAttributes = _f === void 0 ? [] : _f;
109
+ var _b = _a === void 0 ? {} : _a, _c = _b.props, props = _c === void 0 ? {} : _c, _d = _b.error, error = _d === void 0 ? null : _d, _e = _b.isProfilePerspective, isProfilePerspective = _e === void 0 ? false : _e, _f = _b.isAuthoringPerspective, isAuthoringPerspective = _f === void 0 ? false : _f, _g = _b.alwaysVisibleAttributes, alwaysVisibleAttributes = _g === void 0 ? [] : _g;
109
110
  var user = userEvent.setup();
110
111
  var scrollToElementContextValue = getScrollToElementContextValue(error);
111
112
  var Providers = function (_a) {
@@ -113,7 +114,8 @@ describe('SimpleAttributeEditor', function () {
113
114
  return (React.createElement(MdmModuleProvider, { values: mdmValues },
114
115
  React.createElement(AlwaysVisibleAttributesContext.Provider, { value: alwaysVisibleAttributes },
115
116
  React.createElement(ProfilePerspectiveViewContext.Provider, { value: isProfilePerspective },
116
- React.createElement(ScrollToElementContext.Provider, { value: scrollToElementContextValue }, children)))));
117
+ React.createElement(AuthoringPerspectiveViewContext.Provider, { value: isAuthoringPerspective },
118
+ React.createElement(ScrollToElementContext.Provider, { value: scrollToElementContextValue }, children))))));
117
119
  };
118
120
  return __assign({ user: user, scrollToElementContextValue: scrollToElementContextValue }, render(React.createElement(SimpleAttributeEditor, __assign({}, defaultProps, props)), { wrapper: Providers }));
119
121
  };
@@ -348,7 +350,7 @@ describe('SimpleAttributeEditor', function () {
348
350
  uri: 'configuration/entityTypes/HCA/attributes/InternalCustomer',
349
351
  dependentLookupCode: 'Code'
350
352
  };
351
- it('should call getDependentLookupEditorContext selector with correct arguments', function () { return __awaiter(void 0, void 0, void 0, function () {
353
+ it('should call getDependentLookupEditorContext selector with correct arguments for profile perspective', function () { return __awaiter(void 0, void 0, void 0, function () {
352
354
  return __generator(this, function (_a) {
353
355
  switch (_a.label) {
354
356
  case 0:
@@ -366,6 +368,24 @@ describe('SimpleAttributeEditor', function () {
366
368
  }
367
369
  });
368
370
  }); });
371
+ it('should call getDependentLookupEditorContext selector with correct arguments for authoring perspective', function () { return __awaiter(void 0, void 0, void 0, function () {
372
+ return __generator(this, function (_a) {
373
+ switch (_a.label) {
374
+ case 0:
375
+ setUp({ props: { attributeType: attributeType }, isAuthoringPerspective: true });
376
+ return [4 /*yield*/, act(function () { return Promise.resolve(); })];
377
+ case 1:
378
+ _a.sent();
379
+ expect(useMdmDependentLookupEditorContext).toHaveBeenCalledWith(defaultProps.attributeValue, attributeType);
380
+ expect(useAutopopulationContextValue).toHaveBeenCalledWith({
381
+ enabled: true,
382
+ attributeTypeUri: attributeType.uri,
383
+ valueUri: defaultProps.attributeValue.uri
384
+ });
385
+ return [2 /*return*/];
386
+ }
387
+ });
388
+ }); });
369
389
  it('should call useAutopopulationContextValue with enabled: false if component is outside of Profile perspective', function () { return __awaiter(void 0, void 0, void 0, function () {
370
390
  return __generator(this, function (_a) {
371
391
  switch (_a.label) {
@@ -383,6 +403,23 @@ describe('SimpleAttributeEditor', function () {
383
403
  }
384
404
  });
385
405
  }); });
406
+ it('should call useAutopopulationContextValue with enabled: false if component is outside of authoring perspective', function () { return __awaiter(void 0, void 0, void 0, function () {
407
+ return __generator(this, function (_a) {
408
+ switch (_a.label) {
409
+ case 0:
410
+ setUp({ props: { attributeType: attributeType }, isAuthoringPerspective: false });
411
+ return [4 /*yield*/, act(function () { return Promise.resolve(); })];
412
+ case 1:
413
+ _a.sent();
414
+ expect(useAutopopulationContextValue).toHaveBeenCalledWith({
415
+ enabled: false,
416
+ attributeTypeUri: attributeType.uri,
417
+ valueUri: defaultProps.attributeValue.uri
418
+ });
419
+ return [2 /*return*/];
420
+ }
421
+ });
422
+ }); });
386
423
  it('should render dependent lookup editor with applied result of getDependentLookupEditorContext', function () { return __awaiter(void 0, void 0, void 0, function () {
387
424
  var dlEditorContext, input;
388
425
  return __generator(this, function (_a) {
@@ -0,0 +1,15 @@
1
+ import React from 'react';
2
+ import { ActivityFilter } from '@reltio/mdm-sdk';
3
+ type Props = {
4
+ open: boolean;
5
+ onClose: () => void;
6
+ profilesCount: number;
7
+ columnsByEntityType: Record<string, string[]>;
8
+ filter?: string;
9
+ activityFilter: ActivityFilter;
10
+ isSearchByOv: boolean;
11
+ onExternalExport: () => void;
12
+ onLoadingChange?: (loading: boolean) => void;
13
+ };
14
+ export declare const ExportDialog: ({ open, onClose, columnsByEntityType, profilesCount, onExternalExport, onLoadingChange, filter, activityFilter, isSearchByOv }: Props) => React.JSX.Element;
15
+ export {};