@finos/legend-application-studio 28.19.14 → 28.19.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/__lib__/LegendStudioTesting.d.ts +2 -1
- package/lib/__lib__/LegendStudioTesting.d.ts.map +1 -1
- package/lib/__lib__/LegendStudioTesting.js +1 -0
- package/lib/__lib__/LegendStudioTesting.js.map +1 -1
- package/lib/application/LegendStudioApplicationConfig.d.ts +13 -0
- package/lib/application/LegendStudioApplicationConfig.d.ts.map +1 -1
- package/lib/application/LegendStudioApplicationConfig.js +22 -0
- package/lib/application/LegendStudioApplicationConfig.js.map +1 -1
- package/lib/components/editor/editor-group/dataProduct/DataPoductEditor.d.ts +8 -2
- package/lib/components/editor/editor-group/dataProduct/DataPoductEditor.d.ts.map +1 -1
- package/lib/components/editor/editor-group/dataProduct/DataPoductEditor.js +379 -253
- package/lib/components/editor/editor-group/dataProduct/DataPoductEditor.js.map +1 -1
- package/lib/components/editor/side-bar/CreateNewElementModal.d.ts.map +1 -1
- package/lib/components/editor/side-bar/CreateNewElementModal.js +1 -2
- package/lib/components/editor/side-bar/CreateNewElementModal.js.map +1 -1
- package/lib/index.css +2 -2
- package/lib/index.css.map +1 -1
- package/lib/package.json +1 -1
- package/lib/stores/editor/NewElementState.d.ts.map +1 -1
- package/lib/stores/editor/NewElementState.js +6 -3
- package/lib/stores/editor/NewElementState.js.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.d.ts +20 -9
- package/lib/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.d.ts.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.js +72 -24
- package/lib/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.js.map +1 -1
- package/lib/stores/graph-modifier/DSL_DataProduct_GraphModifierHelper.d.ts +4 -1
- package/lib/stores/graph-modifier/DSL_DataProduct_GraphModifierHelper.d.ts.map +1 -1
- package/lib/stores/graph-modifier/DSL_DataProduct_GraphModifierHelper.js +10 -1
- package/lib/stores/graph-modifier/DSL_DataProduct_GraphModifierHelper.js.map +1 -1
- package/package.json +9 -9
- package/src/__lib__/LegendStudioTesting.ts +1 -0
- package/src/application/LegendStudioApplicationConfig.ts +33 -0
- package/src/components/editor/editor-group/dataProduct/DataPoductEditor.tsx +971 -745
- package/src/components/editor/side-bar/CreateNewElementModal.tsx +0 -15
- package/src/stores/editor/NewElementState.ts +8 -1
- package/src/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.ts +122 -26
- package/src/stores/graph-modifier/DSL_DataProduct_GraphModifierHelper.ts +28 -2
@@ -16,20 +16,22 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
16
16
|
*/
|
17
17
|
import { observer } from 'mobx-react-lite';
|
18
18
|
import { useEditorStore } from '../../EditorStoreProvider.js';
|
19
|
-
import { DataProductEditorState, generateUrlToDeployOnOpen, LakehouseAccessPointState, } from '../../../../stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.js';
|
20
|
-
import { clsx, LockIcon, PanelContent, PanelHeader, PanelHeaderActions, Dialog,
|
21
|
-
import React, { useRef, useState, useEffect, } from 'react';
|
19
|
+
import { DATA_PRODUCT_TAB, DataProductEditorState, generateUrlToDeployOnOpen, LakehouseAccessPointState, } from '../../../../stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.js';
|
20
|
+
import { clsx, LockIcon, PanelContent, PanelHeader, PanelHeaderActions, Dialog, TimesIcon, PlusIcon, PanelHeaderActionItem, RocketIcon, ListEditor, Modal, ModalHeader, ModalTitle, ModalBody, ModalFooter, ModalFooterButton, PencilEditIcon, PanelFormTextField, ControlledDropdownMenu, MenuContent, MenuContentItem, CaretDownIcon, WarningIcon, PanelFormSection, useDragPreviewLayer, DragPreviewLayer, PanelDnDEntry, PanelEntryDragHandle, HomeIcon, QuestionCircleIcon, ErrorWarnIcon, GroupWorkIcon, CustomSelectorInput, Switch, BuildingIcon, Tooltip, InfoCircleIcon, } from '@finos/legend-art';
|
21
|
+
import React, { useRef, useState, useEffect, useCallback, } from 'react';
|
22
22
|
import { filterByType } from '@finos/legend-shared';
|
23
23
|
import { InlineLambdaEditor } from '@finos/legend-query-builder';
|
24
24
|
import { action, flowResult } from 'mobx';
|
25
25
|
import { useAuth } from 'react-oidc-context';
|
26
26
|
import { CODE_EDITOR_LANGUAGE } from '@finos/legend-code-editor';
|
27
27
|
import { CodeEditor } from '@finos/legend-lego/code-editor';
|
28
|
-
import { LakehouseTargetEnv, Email } from '@finos/legend-graph';
|
29
|
-
import { accessPointGroup_setDescription, accessPointGroup_setName, dataProduct_setDescription, dataProduct_setSupportInfoIfAbsent, dataProduct_setTitle, supportInfo_setDocumentationUrl, supportInfo_setWebsite, supportInfo_setFaqUrl, supportInfo_setSupportUrl, supportInfo_addEmail, supportInfo_deleteEmail, } from '../../../../stores/graph-modifier/DSL_DataProduct_GraphModifierHelper.js';
|
28
|
+
import { LakehouseTargetEnv, Email, StereotypeExplicitReference, } from '@finos/legend-graph';
|
29
|
+
import { accessPointGroup_setDescription, accessPointGroup_setName, dataProduct_setDescription, dataProduct_setSupportInfoIfAbsent, dataProduct_setTitle, supportInfo_setDocumentationUrl, supportInfo_setWebsite, supportInfo_setFaqUrl, supportInfo_setSupportUrl, supportInfo_addEmail, supportInfo_deleteEmail, accessPoint_setClassification, } from '../../../../stores/graph-modifier/DSL_DataProduct_GraphModifierHelper.js';
|
30
30
|
import { LEGEND_STUDIO_TEST_ID } from '../../../../__lib__/LegendStudioTesting.js';
|
31
31
|
import { LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY } from '../../../../__lib__/LegendStudioApplicationNavigationContext.js';
|
32
32
|
import { ActionAlertActionType, ActionAlertType, useApplicationNavigationContext, } from '@finos/legend-application';
|
33
|
+
import { useDrag, useDrop } from 'react-dnd';
|
34
|
+
import { annotatedElement_addStereotype, annotatedElement_deleteStereotype, } from '../../../../stores/graph-modifier/DomainGraphModifierHelper.js';
|
33
35
|
export var AP_GROUP_MODAL_ERRORS;
|
34
36
|
(function (AP_GROUP_MODAL_ERRORS) {
|
35
37
|
AP_GROUP_MODAL_ERRORS["GROUP_NAME_EMPTY"] = "Group Name is empty";
|
@@ -39,166 +41,99 @@ export var AP_GROUP_MODAL_ERRORS;
|
|
39
41
|
AP_GROUP_MODAL_ERRORS["AP_NAME_EXISTS"] = "Access Point Name already exists";
|
40
42
|
AP_GROUP_MODAL_ERRORS["AP_DESCRIPTION_EMPTY"] = "Access Point Description is empty";
|
41
43
|
})(AP_GROUP_MODAL_ERRORS || (AP_GROUP_MODAL_ERRORS = {}));
|
42
|
-
export const AP_EMPTY_DESC_WARNING = '
|
43
|
-
const
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
const
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
44
|
+
export const AP_EMPTY_DESC_WARNING = 'Click here to describe the data this access point produces';
|
45
|
+
const AP_DND_TYPE = 'ACCESS_POINT';
|
46
|
+
const AP_GROUP_DND_TYPE = 'ACCESS_POINT_GROUP';
|
47
|
+
const newNamePlaceholder = '';
|
48
|
+
const HoverTextArea = ({ text: text, handleMouseOver, handleMouseOut, className, }) => {
|
49
|
+
return (_jsx("div", { onMouseOver: handleMouseOver, onMouseOut: handleMouseOut, className: clsx(className), children: text }));
|
50
|
+
};
|
51
|
+
const hoverIcon = () => {
|
52
|
+
return (_jsx("div", { "data-testid": LEGEND_STUDIO_TEST_ID.HOVER_EDIT_ICON, children: _jsx(PencilEditIcon, {}) }));
|
53
|
+
};
|
54
|
+
const AccessPointTitle = observer((props) => {
|
55
|
+
const { accessPoint } = props;
|
56
|
+
const [editingName, setEditingName] = useState(accessPoint.id === newNamePlaceholder);
|
57
|
+
const handleNameEdit = () => setEditingName(true);
|
58
|
+
const handleNameBlur = () => {
|
59
|
+
if (accessPoint.id !== newNamePlaceholder) {
|
60
|
+
setEditingName(false);
|
58
61
|
}
|
59
62
|
};
|
60
|
-
const
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
: dataProductEditorState.accessPoints
|
71
|
-
.map((e) => e.id)
|
72
|
-
.includes(id ?? '')
|
73
|
-
? AP_GROUP_MODAL_ERRORS.AP_NAME_EXISTS
|
74
|
-
: undefined;
|
75
|
-
const descriptionErrors = description === ''
|
76
|
-
? AP_GROUP_MODAL_ERRORS.AP_DESCRIPTION_EMPTY
|
77
|
-
: undefined;
|
78
|
-
return (_jsx(Dialog, { open: true, onClose: handleClose, TransitionProps: {
|
79
|
-
onEnter: handleEnter,
|
80
|
-
}, classes: {
|
81
|
-
container: 'search-modal__container',
|
82
|
-
}, PaperProps: {
|
83
|
-
classes: {
|
84
|
-
root: 'search-modal__inner-container',
|
85
|
-
},
|
86
|
-
}, children: _jsxs("form", { onSubmit: (event) => {
|
87
|
-
event.preventDefault();
|
88
|
-
handleSubmit();
|
89
|
-
}, className: clsx('modal search-modal', {
|
90
|
-
'modal--dark': true,
|
91
|
-
}), style: {
|
92
|
-
display: 'flex',
|
93
|
-
flexDirection: 'column',
|
94
|
-
gap: '1rem',
|
95
|
-
}, children: [_jsx("div", { className: "modal__title", children: "New Access Point" }), _jsxs("div", { children: [_jsx("div", { className: "panel__content__form__section__header__label", children: "Name" }), _jsx(InputWithInlineValidation, { className: clsx('input new-access-point-modal__id-input', {
|
96
|
-
'input--dark': true,
|
97
|
-
}), ref: accessPointInputRef, spellCheck: false, value: id ?? '', onChange: handleIdChange, placeholder: "Access Point Name", error: nameErrors })] }), _jsxs("div", { children: [_jsx("div", { className: "panel__content__form__section__header__label", children: "Description" }), _jsx(InputWithInlineValidation, { className: clsx('input new-access-point-modal__id-input', {
|
98
|
-
'input--dark': true,
|
99
|
-
}), spellCheck: false, value: description ?? '', onChange: handleDescriptionChange, placeholder: "Access Point Description", error: descriptionErrors })] }), _jsx("div", {}), _jsx(PanelDivider, {}), _jsx("div", { className: "search-modal__actions", children: _jsx("button", { className: clsx('btn btn--primary', {
|
100
|
-
'btn--dark': true,
|
101
|
-
}), disabled: disableCreateButton, children: "Create" }) })] }) }));
|
63
|
+
const updateAccessPointName = action((event) => {
|
64
|
+
if (!event.target.value.includes(' ')) {
|
65
|
+
accessPoint.id = event.target.value;
|
66
|
+
}
|
67
|
+
});
|
68
|
+
return editingName ? (_jsx("textarea", { className: "access-point-editor__name", spellCheck: false, value: accessPoint.id, onChange: updateAccessPointName, placeholder: 'Access Point Name', onBlur: handleNameBlur, style: {
|
69
|
+
borderColor: accessPoint.id === newNamePlaceholder
|
70
|
+
? 'var(--color-red-300)'
|
71
|
+
: 'transparent',
|
72
|
+
} })) : (_jsx("div", { onClick: handleNameEdit, title: "Click to edit access point title", children: _jsx("div", { className: "access-point-editor__name__label", children: accessPoint.id }) }));
|
102
73
|
});
|
103
|
-
const
|
104
|
-
const {
|
105
|
-
const
|
106
|
-
const
|
107
|
-
const
|
108
|
-
|
109
|
-
|
110
|
-
const
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
74
|
+
const AccessPointClassification = observer((props) => {
|
75
|
+
const { accessPoint, groupState } = props;
|
76
|
+
const applicationStore = useEditorStore().applicationStore;
|
77
|
+
const CHOOSE_CLASSIFICATION = 'Choose Classification';
|
78
|
+
const updateAccessPointClassificationTextbox = action((event) => {
|
79
|
+
accessPoint.classification = event.target.value;
|
80
|
+
});
|
81
|
+
const conditionalClassifications = () => {
|
82
|
+
if (groupState.containsPublicStereotype) {
|
83
|
+
return (applicationStore.config.options.dataProductConfig
|
84
|
+
?.publicClassifications ?? []);
|
85
|
+
}
|
86
|
+
else {
|
87
|
+
return (applicationStore.config.options.dataProductConfig?.classifications ??
|
88
|
+
[]);
|
89
|
+
}
|
119
90
|
};
|
120
|
-
const
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
:
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
!apName ||
|
143
|
-
!apDescription ||
|
144
|
-
Boolean(groupNameErrors ??
|
145
|
-
groupDescriptionErrors ??
|
146
|
-
apNameErrors ??
|
147
|
-
apDescriptionErrors);
|
148
|
-
const handleSubmit = () => {
|
149
|
-
if (!disableCreateButton && apName) {
|
150
|
-
const createdGroup = dataProductEditorState.createGroupAndAdd(groupName, groupDescription);
|
151
|
-
dataProductEditorState.addAccessPoint(apName, apDescription, createdGroup);
|
152
|
-
handleClose();
|
91
|
+
const classificationOptions = [CHOOSE_CLASSIFICATION]
|
92
|
+
.concat(conditionalClassifications())
|
93
|
+
.map((classfication) => ({
|
94
|
+
label: classfication,
|
95
|
+
value: classfication,
|
96
|
+
}));
|
97
|
+
const updateAccessPointClassificationFromDropdown = action((val) => {
|
98
|
+
accessPoint_setClassification(accessPoint, val?.value === CHOOSE_CLASSIFICATION ? undefined : val?.value);
|
99
|
+
});
|
100
|
+
const currentClassification = accessPoint.classification !== undefined
|
101
|
+
? {
|
102
|
+
label: accessPoint.classification,
|
103
|
+
value: accessPoint.classification,
|
104
|
+
}
|
105
|
+
: {
|
106
|
+
label: CHOOSE_CLASSIFICATION,
|
107
|
+
value: CHOOSE_CLASSIFICATION,
|
108
|
+
};
|
109
|
+
const classificationDocumentationLink = () => {
|
110
|
+
const docLink = applicationStore.config.options.dataProductConfig?.classificationDoc;
|
111
|
+
if (docLink) {
|
112
|
+
applicationStore.navigationService.navigator.visitAddress(docLink);
|
153
113
|
}
|
154
114
|
};
|
155
|
-
return (_jsx(
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
},
|
163
|
-
}, children: _jsxs("form", { onSubmit: (event) => {
|
164
|
-
event.preventDefault();
|
165
|
-
handleSubmit();
|
166
|
-
}, className: clsx('modal search-modal', {
|
167
|
-
'modal--dark': true,
|
168
|
-
}), style: {
|
169
|
-
display: 'flex',
|
170
|
-
flexDirection: 'column',
|
171
|
-
gap: '1rem',
|
172
|
-
}, children: [_jsx("div", { className: "modal__title", children: "New Access Point Group" }), _jsxs("div", { children: [_jsx("div", { className: "panel__content__form__section__header__label", children: "Group Name" }), _jsx(InputWithInlineValidation, { className: clsx('input new-access-point-modal__id-input', {
|
173
|
-
'input--dark': true,
|
174
|
-
}), ref: accessPointGroupInputRef, spellCheck: false, value: groupName ?? '', onChange: handleGroupNameChange, placeholder: "Access Point Group Name", error: groupNameErrors })] }), _jsxs("div", { children: [_jsx("div", { className: "panel__content__form__section__header__label", children: "Group Description" }), _jsx(InputWithInlineValidation, { className: clsx('input new-access-point-modal__id-input', {
|
175
|
-
'input--dark': true,
|
176
|
-
}), spellCheck: false, value: groupDescription ?? '', onChange: handleGroupDescriptionChange, placeholder: "Access Point Group Description", error: groupDescriptionErrors })] }), _jsxs("div", { children: [_jsx("div", { className: "panel__content__form__section__header__label", children: "Access Point" }), _jsxs("div", { className: "new-access-point-group-modal", children: [_jsx("div", { className: "panel__content__form__section__header__label", children: "Name" }), _jsx(InputWithInlineValidation, { className: clsx('input new-access-point-modal__id-input', {
|
177
|
-
'input--dark': true,
|
178
|
-
}), spellCheck: false, value: apName ?? '', onChange: handleApNameChange, placeholder: "Access Point Name", error: apNameErrors }), _jsx("div", { className: "panel__content__form__section__header__label", children: "Description" }), _jsx(InputWithInlineValidation, { className: clsx('input new-access-point-modal__id-input', {
|
179
|
-
'input--dark': true,
|
180
|
-
}), spellCheck: false, value: apDescription ?? '', onChange: handleApDescriptionChange, placeholder: "Access Point Description", error: apDescriptionErrors })] })] }), _jsx(PanelDivider, {}), _jsx("div", { className: "search-modal__actions", children: _jsx("button", { className: clsx('btn btn--primary', {
|
181
|
-
'btn--dark': true,
|
182
|
-
}), disabled: disableCreateButton, children: "Create" }) })] }) }));
|
115
|
+
return (_jsxs("div", { className: "access-point-editor__classification", children: [classificationOptions.length > 1 ? (_jsx("div", { children: _jsx(CustomSelectorInput, { className: "explorer__new-element-modal__driver__dropdown", options: classificationOptions, onChange: updateAccessPointClassificationFromDropdown, value: currentClassification, darkMode: !applicationStore.layoutService
|
116
|
+
.TEMPORARY__isLightColorThemeEnabled }) })) : (_jsx("textarea", { className: "panel__content__form__section__input", spellCheck: false, value: accessPoint.classification ?? '', onChange: updateAccessPointClassificationTextbox, placeholder: "Add classification", style: {
|
117
|
+
overflow: 'hidden',
|
118
|
+
width: '125px',
|
119
|
+
resize: 'none',
|
120
|
+
padding: '0.25rem',
|
121
|
+
} })), _jsx(Tooltip, { title: "Learn more about data classification scheme here.", arrow: true, placement: 'top', children: _jsx("button", { onClick: classificationDocumentationLink, children: _jsx(InfoCircleIcon, {}) }) })] }));
|
183
122
|
});
|
184
|
-
const HoverTextArea = ({ text: text, handleMouseOver, handleMouseOut, className, }) => {
|
185
|
-
return (_jsx("div", { onMouseOver: handleMouseOver, onMouseOut: handleMouseOut, className: clsx(className), children: text }));
|
186
|
-
};
|
187
|
-
const hoverIcon = () => {
|
188
|
-
return (_jsx("div", { "data-testid": LEGEND_STUDIO_TEST_ID.HOVER_EDIT_ICON, children: _jsx(PencilEditIcon, {}) }));
|
189
|
-
};
|
190
123
|
export const LakehouseDataProductAcccessPointEditor = observer((props) => {
|
191
124
|
const { accessPointState } = props;
|
125
|
+
const editorStore = useEditorStore();
|
192
126
|
const accessPoint = accessPointState.accessPoint;
|
193
|
-
const
|
127
|
+
const groupState = accessPointState.state;
|
194
128
|
const lambdaEditorState = accessPointState.lambdaState;
|
195
|
-
const propertyHasParserError =
|
129
|
+
const propertyHasParserError = groupState.accessPointStates
|
196
130
|
.filter(filterByType(LakehouseAccessPointState))
|
197
131
|
.find((pm) => pm.lambdaState.parserError);
|
198
132
|
const [editingDescription, setEditingDescription] = useState(false);
|
199
133
|
const [isHovering, setIsHovering] = useState(false);
|
200
|
-
const
|
201
|
-
const
|
134
|
+
const ref = useRef(null);
|
135
|
+
const handleDescriptionEdit = () => setEditingDescription(true);
|
136
|
+
const handleDescriptionBlur = () => {
|
202
137
|
setEditingDescription(false);
|
203
138
|
setIsHovering(false);
|
204
139
|
};
|
@@ -214,37 +149,73 @@ export const LakehouseDataProductAcccessPointEditor = observer((props) => {
|
|
214
149
|
const updateAccessPointTargetEnvironment = action((targetEnvironment) => {
|
215
150
|
accessPoint.targetEnvironment = targetEnvironment;
|
216
151
|
});
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
});
|
236
|
-
|
237
|
-
|
238
|
-
const
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
152
|
+
const handleRemoveAccessPoint = () => {
|
153
|
+
editorStore.applicationStore.alertService.setActionAlertInfo({
|
154
|
+
message: `Are you sure you want to delete Access Point ${accessPoint.id}?`,
|
155
|
+
type: ActionAlertType.CAUTION,
|
156
|
+
actions: [
|
157
|
+
{
|
158
|
+
label: 'Confirm',
|
159
|
+
type: ActionAlertActionType.PROCEED_WITH_CAUTION,
|
160
|
+
handler: () => {
|
161
|
+
groupState.deleteAccessPoint(accessPointState);
|
162
|
+
},
|
163
|
+
},
|
164
|
+
{
|
165
|
+
label: 'Cancel',
|
166
|
+
type: ActionAlertActionType.PROCEED,
|
167
|
+
default: true,
|
168
|
+
},
|
169
|
+
],
|
170
|
+
});
|
171
|
+
};
|
172
|
+
//Drag and drop - reorder access points/move between groups
|
173
|
+
const handleHover = useCallback((item) => {
|
174
|
+
const draggingProperty = item.accessPointState;
|
175
|
+
const hoveredProperty = accessPointState;
|
176
|
+
groupState.swapAccessPoints(draggingProperty, hoveredProperty);
|
177
|
+
}, [accessPointState, groupState]);
|
178
|
+
const [{ isBeingDraggedAP }, dropConnector] = useDrop(() => ({
|
179
|
+
accept: [AP_DND_TYPE],
|
180
|
+
hover: (item) => handleHover(item),
|
181
|
+
collect: (monitor) => ({
|
182
|
+
isBeingDraggedAP: monitor.getItem()
|
183
|
+
?.accessPointState,
|
184
|
+
}),
|
185
|
+
}), [handleHover]);
|
186
|
+
const isBeingDragged = accessPoint === isBeingDraggedAP?.accessPoint;
|
187
|
+
const [, dragConnector, dragPreviewConnector] = useDrag(() => ({
|
188
|
+
type: AP_DND_TYPE,
|
189
|
+
item: () => ({
|
190
|
+
accessPointState: accessPointState,
|
191
|
+
}),
|
192
|
+
collect: (monitor) => ({
|
193
|
+
isDragging: monitor.isDragging(),
|
194
|
+
}),
|
195
|
+
}), [accessPointState]);
|
196
|
+
dragConnector(ref);
|
197
|
+
dropConnector(ref);
|
198
|
+
useDragPreviewLayer(dragPreviewConnector);
|
199
|
+
return (_jsx(PanelDnDEntry, { ref: ref, placeholder: _jsx("div", { className: "dnd__placeholder--light" }), showPlaceholder: isBeingDragged, children: _jsxs("div", { className: clsx('access-point-editor', {
|
200
|
+
backdrop__element: propertyHasParserError,
|
201
|
+
}), children: [_jsx(PanelEntryDragHandle, { dragSourceConnector: ref, isDragging: isBeingDragged, title: 'Drag this Access Point to another group', className: "access-point-editor__dnd-handle" }), _jsxs("div", { style: { flex: 1 }, children: [_jsxs("div", { className: "access-point-editor__metadata", children: [_jsx(AccessPointTitle, { accessPoint: accessPoint }), editingDescription ? (_jsx("textarea", { className: "panel__content__form__section__input", spellCheck: false, value: accessPoint.description ?? '', onChange: updateAccessPointDescription, placeholder: "Access Point description", onBlur: handleDescriptionBlur, style: {
|
202
|
+
overflow: 'hidden',
|
203
|
+
resize: 'none',
|
204
|
+
padding: '0.25rem',
|
205
|
+
} })) : (_jsxs("div", { onClick: handleDescriptionEdit, title: "Click to edit access point description", className: "access-point-editor__description-container", children: [accessPoint.description ? (_jsx(HoverTextArea, { text: accessPoint.description, handleMouseOver: handleMouseOver, handleMouseOut: handleMouseOut })) : (_jsxs("div", { className: "access-point-editor__group-container__description--warning", onMouseOver: handleMouseOver, onMouseOut: handleMouseOut, children: [_jsx(WarningIcon, {}), AP_EMPTY_DESC_WARNING] })), isHovering && hoverIcon()] })), _jsxs("div", { className: "access-point-editor__info", children: [editorStore.applicationStore.config.options
|
206
|
+
.dataProductConfig && (_jsx(AccessPointClassification, { accessPoint: accessPoint, groupState: groupState })), _jsxs("div", { className: clsx('access-point-editor__type'), title: 'Change target environment', children: [_jsx("div", { className: "access-point-editor__type__label", children: accessPoint.targetEnvironment }), _jsx(ControlledDropdownMenu, { className: "access-point-editor__dropdown", content: _jsx(MenuContent, { children: Object.values(LakehouseTargetEnv).map((environment) => (_jsx(MenuContentItem, { className: "btn__dropdown-combo__option", onClick: () => updateAccessPointTargetEnvironment(environment), children: environment }, environment))) }), menuProps: {
|
207
|
+
anchorOrigin: {
|
208
|
+
vertical: 'bottom',
|
209
|
+
horizontal: 'right',
|
210
|
+
},
|
211
|
+
transformOrigin: {
|
212
|
+
vertical: 'top',
|
213
|
+
horizontal: 'right',
|
214
|
+
},
|
215
|
+
}, children: _jsx(CaretDownIcon, {}) })] })] })] }), _jsx("div", { className: "access-point-editor__content", children: _jsxs("div", { className: "access-point-editor__generic-entry", children: [_jsx("div", { className: "access-point-editor__entry__container", children: _jsx("div", { className: "access-point-editor__entry", children: _jsx(InlineLambdaEditor, { className: 'access-point-editor__lambda-editor', disabled: lambdaEditorState.val.state.state
|
216
|
+
.isConvertingTransformLambdaObjects, lambdaEditorState: lambdaEditorState, forceBackdrop: Boolean(lambdaEditorState.parserError) }) }) }), _jsx("button", { className: "access-point-editor__generic-entry__remove-btn", onClick: () => {
|
217
|
+
handleRemoveAccessPoint();
|
218
|
+
}, tabIndex: -1, title: "Remove", children: _jsx(TimesIcon, {}) })] }) })] })] }) }));
|
248
219
|
});
|
249
220
|
const DataProductDeploymentResponseModal = observer((props) => {
|
250
221
|
const { state } = props;
|
@@ -256,13 +227,32 @@ const DataProductDeploymentResponseModal = observer((props) => {
|
|
256
227
|
paper: 'editor-modal__content',
|
257
228
|
}, onClose: closeModal, children: _jsxs(Modal, { darkMode: !applicationStore.layoutService.TEMPORARY__isLightColorThemeEnabled, className: "editor-modal", children: [_jsx(ModalHeader, { children: _jsx(ModalTitle, { title: "Data Product Deployment Response" }) }), _jsx(ModalBody, { children: _jsx(PanelContent, { children: _jsx(CodeEditor, { inputValue: JSON.stringify(state.deployResponse?.content ?? {}, null, 2), isReadOnly: true, language: CODE_EDITOR_LANGUAGE.JSON }) }) }), _jsx(ModalFooter, { children: _jsx(ModalFooterButton, { onClick: closeModal, text: "Close", type: "secondary" }) })] }) }));
|
258
229
|
});
|
259
|
-
const
|
230
|
+
const AccessPointGroupPublicToggle = observer((props) => {
|
231
|
+
const { groupState } = props;
|
232
|
+
const handleSwitchChange = (event) => {
|
233
|
+
const isChecked = event.target.checked;
|
234
|
+
if (isChecked && groupState.publicStereotype) {
|
235
|
+
annotatedElement_addStereotype(groupState.value, StereotypeExplicitReference.create(groupState.publicStereotype));
|
236
|
+
}
|
237
|
+
else if (groupState.containsPublicStereotype) {
|
238
|
+
annotatedElement_deleteStereotype(groupState.value, groupState.containsPublicStereotype);
|
239
|
+
}
|
240
|
+
};
|
241
|
+
return (_jsxs("div", { className: "access-point-editor__toggle", children: [_jsx(Switch, { checked: Boolean(groupState.containsPublicStereotype), onChange: handleSwitchChange, sx: {
|
242
|
+
'& .MuiSwitch-track': {
|
243
|
+
backgroundColor: groupState.containsPublicStereotype
|
244
|
+
? 'default'
|
245
|
+
: 'var(--color-light-grey-400)',
|
246
|
+
},
|
247
|
+
} }), _jsx(BuildingIcon, {}), "Enterprise Data. Anyone at the firm can access this without approvals."] }));
|
248
|
+
});
|
249
|
+
const AccessPointGroupEditor = observer((props) => {
|
260
250
|
const { groupState, isReadOnly } = props;
|
261
251
|
const editorStore = useEditorStore();
|
262
252
|
const productEditorState = groupState.state;
|
263
253
|
const [editingDescription, setEditingDescription] = useState(false);
|
264
254
|
const [isHoveringDescription, setIsHoveringDescription] = useState(false);
|
265
|
-
const [editingName, setEditingName] = useState(
|
255
|
+
const [editingName, setEditingName] = useState(groupState.value.id === newNamePlaceholder);
|
266
256
|
const [isHoveringName, setIsHoveringName] = useState(false);
|
267
257
|
const handleDescriptionEdit = () => setEditingDescription(true);
|
268
258
|
const handleDescriptionBlur = () => {
|
@@ -280,8 +270,10 @@ const AccessPointGroupSection = observer((props) => {
|
|
280
270
|
};
|
281
271
|
const handleNameEdit = () => setEditingName(true);
|
282
272
|
const handleNameBlur = () => {
|
283
|
-
|
284
|
-
|
273
|
+
if (groupState.value.id !== newNamePlaceholder) {
|
274
|
+
setEditingName(false);
|
275
|
+
setIsHoveringName(false);
|
276
|
+
}
|
285
277
|
};
|
286
278
|
const handleMouseOverName = () => {
|
287
279
|
setIsHoveringName(true);
|
@@ -290,87 +282,184 @@ const AccessPointGroupSection = observer((props) => {
|
|
290
282
|
setIsHoveringName(false);
|
291
283
|
};
|
292
284
|
const updateGroupName = (val) => {
|
293
|
-
if (val) {
|
285
|
+
if (val && !val.includes(' ')) {
|
294
286
|
accessPointGroup_setName(groupState.value, val);
|
295
287
|
}
|
296
288
|
};
|
297
289
|
const handleRemoveAccessPointGroup = () => {
|
298
290
|
editorStore.applicationStore.alertService.setActionAlertInfo({
|
299
|
-
message: `
|
291
|
+
message: `Are you sure you want to delete Access Point Group ${groupState.value.id} and all of its Access Points?`,
|
300
292
|
type: ActionAlertType.CAUTION,
|
301
293
|
actions: [
|
302
294
|
{
|
303
|
-
label: '
|
304
|
-
type: ActionAlertActionType.PROCEED,
|
305
|
-
default: true,
|
306
|
-
},
|
307
|
-
{
|
308
|
-
label: 'Proceed',
|
295
|
+
label: 'Confirm',
|
309
296
|
type: ActionAlertActionType.PROCEED_WITH_CAUTION,
|
310
297
|
handler: () => {
|
311
298
|
productEditorState.deleteAccessPointGroup(groupState);
|
312
299
|
},
|
313
300
|
},
|
301
|
+
{
|
302
|
+
label: 'Cancel',
|
303
|
+
type: ActionAlertActionType.PROCEED,
|
304
|
+
default: true,
|
305
|
+
},
|
314
306
|
],
|
315
307
|
});
|
316
308
|
};
|
317
|
-
const
|
318
|
-
productEditorState.
|
319
|
-
productEditorState.setAccessPointModal(true);
|
309
|
+
const handleAddAccessPoint = () => {
|
310
|
+
productEditorState.addAccessPoint(newNamePlaceholder, undefined, productEditorState.selectedGroupState ?? groupState);
|
320
311
|
};
|
321
|
-
return (_jsxs("div", { className: "access-point-editor__group-container", children: [_jsxs("div", { className: "access-point-editor__group-container__title-editor", children: [editingName ? (_jsx("textarea", { className: "panel__content__form__section__input", spellCheck: false, value: groupState.value.id, onChange: (event) => updateGroupName(event.target.value), placeholder: "Access Point Group Name", onBlur: handleNameBlur, style: {
|
312
|
+
return (_jsxs("div", { className: "access-point-editor__group-container", "data-testid": LEGEND_STUDIO_TEST_ID.ACCESS_POINT_GROUP_EDITOR, children: [_jsxs("div", { className: "access-point-editor__group-container__title-editor", children: [editingName ? (_jsx("textarea", { className: "panel__content__form__section__input", spellCheck: false, value: groupState.value.id, onChange: (event) => updateGroupName(event.target.value), placeholder: "Access Point Group Name", onBlur: handleNameBlur, style: {
|
322
313
|
overflow: 'hidden',
|
323
314
|
resize: 'none',
|
324
315
|
padding: '0.25rem',
|
316
|
+
borderColor: groupState.value.id === newNamePlaceholder
|
317
|
+
? 'var(--color-red-300)'
|
318
|
+
: 'transparent',
|
319
|
+
borderWidth: 'thin',
|
325
320
|
} })) : (_jsxs("div", { onClick: handleNameEdit, title: "Click to edit group name", className: "access-point-editor__group-container__title", children: [_jsx(HoverTextArea, { text: groupState.value.id, handleMouseOver: handleMouseOverName, handleMouseOut: handleMouseOutName, className: "access-point-editor__group-container__title" }), isHoveringName && hoverIcon()] })), _jsx("button", { className: "access-point-editor__generic-entry__remove-btn--group", onClick: () => {
|
326
|
-
// productEditorState.deleteAccessPointGroup(groupState);
|
327
321
|
handleRemoveAccessPointGroup();
|
328
322
|
}, tabIndex: -1, title: "Remove Access Point Group", children: _jsx(TimesIcon, {}) })] }), _jsx("div", { className: "access-point-editor__group-container__description-editor", children: editingDescription ? (_jsx("textarea", { className: "panel__content__form__section__input", spellCheck: false, value: groupState.value.description ?? '', onChange: (event) => updateGroupDescription(event.target.value), placeholder: "Provide a description for this Access Point Group", onBlur: handleDescriptionBlur, style: {
|
329
323
|
overflow: 'hidden',
|
330
324
|
resize: 'none',
|
331
325
|
padding: '0.25rem',
|
332
|
-
} })) : (_jsxs("div", { onClick: handleDescriptionEdit, title: "Click to edit group description", className: "access-point-editor__description-container", children: [groupState.value.description ? (_jsx(HoverTextArea, { text: groupState.value.description, handleMouseOver: handleMouseOverDescription, handleMouseOut: handleMouseOutDescription, className: "access-point-editor__group-container__description" })) : (_jsxs("div", { className: "access-point-editor__group-container__description--warning", onMouseOver: handleMouseOverDescription, onMouseOut: handleMouseOutDescription, children: [_jsx(WarningIcon, {}), "
|
333
|
-
|
334
|
-
|
326
|
+
} })) : (_jsxs("div", { onClick: handleDescriptionEdit, title: "Click to edit group description", className: "access-point-editor__description-container", children: [groupState.value.description ? (_jsx(HoverTextArea, { text: groupState.value.description, handleMouseOver: handleMouseOverDescription, handleMouseOut: handleMouseOutDescription, className: "access-point-editor__group-container__description" })) : (_jsxs("div", { className: "access-point-editor__group-container__description--warning", onMouseOver: handleMouseOverDescription, onMouseOut: handleMouseOutDescription, children: [_jsx(WarningIcon, {}), "Users request access at the access point group level. Click here to add a meaningful description to guide users."] })), isHoveringDescription && hoverIcon()] })) }), editorStore.applicationStore.config.options.dataProductConfig && (_jsx(AccessPointGroupPublicToggle, { groupState: groupState })), _jsxs(PanelHeader, { className: "panel__header--access-point", children: [_jsx("div", { className: "panel__header__title", children: "Access Points" }), _jsx(PanelHeaderActions, { children: _jsx(PanelHeaderActionItem, { className: "panel__header__action", onClick: handleAddAccessPoint, disabled: isReadOnly, title: "Create new access point", children: _jsx(PlusIcon, {}) }) })] }), groupState.accessPointStates.length === 0 && (_jsxs("div", { className: "access-point-editor__group-container__description--warning", children: [_jsx(WarningIcon, {}), "This group needs at least one access point defined."] })), _jsx("div", { style: { gap: '1rem', display: 'flex', flexDirection: 'column' }, children: groupState.accessPointStates
|
327
|
+
.filter(filterByType(LakehouseAccessPointState))
|
328
|
+
.map((apState) => (_jsx(LakehouseDataProductAcccessPointEditor, { isReadOnly: isReadOnly, accessPointState: apState }, apState.uuid))) })] }));
|
335
329
|
});
|
336
|
-
|
337
|
-
const
|
338
|
-
const
|
339
|
-
|
340
|
-
const accessPointStates = dataProductEditorState.accessPointGroupStates
|
341
|
-
.map((e) => e.accessPointStates)
|
342
|
-
.flat();
|
343
|
-
const isReadOnly = dataProductEditorState.isReadOnly;
|
344
|
-
const openNewModal = () => {
|
345
|
-
dataProductEditorState.setAccessPointGroupModal(true);
|
330
|
+
const GroupTabRenderer = observer((props) => {
|
331
|
+
const { group, dataProductEditorState } = props;
|
332
|
+
const changeGroup = (newGroup) => {
|
333
|
+
dataProductEditorState.setSelectedGroupState(newGroup);
|
346
334
|
};
|
347
|
-
const
|
348
|
-
const
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
.signinRedirect({
|
354
|
-
state: generateUrlToDeployOnOpen(dataProductEditorState),
|
355
|
-
})
|
356
|
-
.catch(editorStore.applicationStore.alertUnhandledError);
|
357
|
-
return;
|
358
|
-
}
|
359
|
-
// Use the token for deployment
|
360
|
-
const token = auth.user?.access_token;
|
361
|
-
if (token) {
|
362
|
-
flowResult(dataProductEditorState.deploy(token)).catch(editorStore.applicationStore.alertUnhandledError);
|
363
|
-
}
|
364
|
-
else {
|
365
|
-
editorStore.applicationStore.notificationService.notifyError('Authentication failed. No token available.');
|
366
|
-
}
|
335
|
+
const selectedGroupState = dataProductEditorState.selectedGroupState;
|
336
|
+
const ref = useRef(null);
|
337
|
+
const groupError = () => {
|
338
|
+
return (group.accessPointStates.length === 0 ||
|
339
|
+
group.value.id === newNamePlaceholder ||
|
340
|
+
Boolean(group.accessPointStates.find((apState) => apState.accessPoint.id === newNamePlaceholder)));
|
367
341
|
};
|
342
|
+
//Drag and Drop - reorder groups and accept access points from other groups
|
343
|
+
const handleHover = useCallback((item) => {
|
344
|
+
const draggingProperty = item.groupState;
|
345
|
+
const hoveredProperty = group;
|
346
|
+
dataProductEditorState.swapAccessPointGroups(draggingProperty, hoveredProperty);
|
347
|
+
}, [group, dataProductEditorState]);
|
348
|
+
const [{ isOver }, dropConnector] = useDrop(() => ({
|
349
|
+
accept: [AP_GROUP_DND_TYPE, AP_DND_TYPE],
|
350
|
+
hover: (item, monitor) => {
|
351
|
+
const itemType = monitor.getItemType();
|
352
|
+
if (itemType === AP_GROUP_DND_TYPE) {
|
353
|
+
const groupItem = item;
|
354
|
+
handleHover(groupItem);
|
355
|
+
}
|
356
|
+
},
|
357
|
+
drop: (item, monitor) => {
|
358
|
+
const itemType = monitor.getItemType();
|
359
|
+
if (itemType === AP_DND_TYPE) {
|
360
|
+
const accessPointItem = item;
|
361
|
+
group.addAccessPoint(accessPointItem.accessPointState);
|
362
|
+
accessPointItem.accessPointState.state.deleteAccessPoint(accessPointItem.accessPointState);
|
363
|
+
accessPointItem.accessPointState.changeGroupState(group);
|
364
|
+
}
|
365
|
+
},
|
366
|
+
collect: (monitor) => ({
|
367
|
+
isBeingDraggedAPG: monitor.getItemType() === AP_GROUP_DND_TYPE
|
368
|
+
? monitor.getItem()?.groupState
|
369
|
+
: undefined,
|
370
|
+
isBeingDraggedAP: monitor.getItemType() === AP_DND_TYPE
|
371
|
+
? monitor.getItem()
|
372
|
+
?.accessPointState
|
373
|
+
: undefined,
|
374
|
+
isOver: monitor.isOver(),
|
375
|
+
}),
|
376
|
+
}), [handleHover]);
|
377
|
+
const [, dragConnector, dragPreviewConnector] = useDrag(() => ({
|
378
|
+
type: AP_GROUP_DND_TYPE,
|
379
|
+
item: () => ({
|
380
|
+
groupState: group,
|
381
|
+
}),
|
382
|
+
collect: (monitor) => ({
|
383
|
+
isDragging: monitor.isDragging(),
|
384
|
+
}),
|
385
|
+
}), [group]);
|
386
|
+
dragConnector(ref);
|
387
|
+
dropConnector(ref);
|
388
|
+
dragPreviewConnector(ref);
|
389
|
+
return (_jsxs("div", { ref: ref, onClick: () => changeGroup(group), className: clsx('service-editor__tab', {
|
390
|
+
'service-editor__tab--active': group === selectedGroupState,
|
391
|
+
}), style: {
|
392
|
+
backgroundColor: isOver
|
393
|
+
? 'var(--color-dark-grey-100)'
|
394
|
+
: 'var(--color-dark-grey-50)',
|
395
|
+
}, children: [group.value.id, "\u00A0", groupError() && (_jsx(ErrorWarnIcon, { title: "Resolve Access Point Group error(s)", style: { color: 'var(--color-red-300)' } }))] }, group.uuid));
|
396
|
+
});
|
397
|
+
const AccessPointGroupTab = observer((props) => {
|
398
|
+
const { dataProductEditorState, isReadOnly } = props;
|
399
|
+
const groupStates = dataProductEditorState.accessPointGroupStates;
|
400
|
+
const selectedGroupState = dataProductEditorState.selectedGroupState;
|
401
|
+
const handleAddAccessPointGroup = () => {
|
402
|
+
const newGroup = dataProductEditorState.createGroupAndAdd(newNamePlaceholder);
|
403
|
+
dataProductEditorState.setSelectedGroupState(newGroup);
|
404
|
+
};
|
405
|
+
const AccessPointDragPreviewLayer = () => (_jsx(DragPreviewLayer, { labelGetter: (item) => {
|
406
|
+
return item.accessPointState.accessPoint.id;
|
407
|
+
}, types: [AP_DND_TYPE] }));
|
408
|
+
const disableAddGroup = Boolean(dataProductEditorState.accessPointGroupStates.find((group) => group.value.id === newNamePlaceholder));
|
409
|
+
return (_jsxs("div", { className: "panel", style: { overflow: 'visible' }, children: [_jsx(AccessPointDragPreviewLayer, {}), _jsx("div", { className: "panel__content__form__section__header__label", style: { paddingLeft: '1rem' }, children: "Access Point Groups" }), _jsxs(PanelHeader, { children: [_jsxs("div", { className: "uml-element-editor__tabs", children: [groupStates.map((group) => {
|
410
|
+
return (_jsx(GroupTabRenderer, { group: group, dataProductEditorState: dataProductEditorState }, group.uuid));
|
411
|
+
}), _jsx(PanelHeaderActionItem, { className: "panel__header__action", onClick: handleAddAccessPointGroup, disabled: isReadOnly || disableAddGroup, title: disableAddGroup
|
412
|
+
? 'Provide all group names'
|
413
|
+
: 'Create new access point group', children: _jsx(PlusIcon, {}) })] }), _jsx(PanelHeaderActions, {})] }), _jsx(PanelContent, { children: selectedGroupState && (_jsx(AccessPointGroupEditor, { groupState: selectedGroupState, isReadOnly: isReadOnly }, selectedGroupState.uuid)) }), dataProductEditorState.deployResponse && (_jsx(DataProductDeploymentResponseModal, { state: dataProductEditorState }))] }));
|
414
|
+
});
|
415
|
+
const DataProductSidebar = observer((props) => {
|
416
|
+
const { dataProductEditorState } = props;
|
417
|
+
const sidebarTabs = [
|
418
|
+
{
|
419
|
+
label: DATA_PRODUCT_TAB.HOME,
|
420
|
+
icon: _jsx(HomeIcon, {}),
|
421
|
+
},
|
422
|
+
{
|
423
|
+
label: DATA_PRODUCT_TAB.APG,
|
424
|
+
title: 'Access Point Groups',
|
425
|
+
icon: _jsx(GroupWorkIcon, {}),
|
426
|
+
},
|
427
|
+
{
|
428
|
+
label: DATA_PRODUCT_TAB.SUPPORT,
|
429
|
+
icon: _jsx(QuestionCircleIcon, {}),
|
430
|
+
},
|
431
|
+
];
|
432
|
+
return (_jsx("div", { className: "data-space__viewer__activity-bar", style: { position: 'static', maxHeight: '100%' }, children: _jsx("div", { className: "data-space__viewer__activity-bar__items", children: sidebarTabs.map((activity) => (_jsxs("button", { className: clsx('data-space__viewer__activity-bar__item', {
|
433
|
+
'data-space__viewer__activity-bar__item--active': dataProductEditorState.selectedTab === activity.label,
|
434
|
+
}), onClick: () => dataProductEditorState.setSelectedTab(activity.label), tabIndex: -1, title: activity.title ?? activity.label, style: {
|
435
|
+
flexDirection: 'column',
|
436
|
+
fontSize: '12px',
|
437
|
+
margin: '1rem 0rem',
|
438
|
+
}, children: [activity.icon, activity.label] }, activity.label))) }) }));
|
439
|
+
});
|
440
|
+
const HomeTab = observer((props) => {
|
441
|
+
const { product, isReadOnly } = props;
|
368
442
|
const updateDataProductTitle = (val) => {
|
369
443
|
dataProduct_setTitle(product, val ?? '');
|
370
444
|
};
|
371
445
|
const updateDataProductDescription = (event) => {
|
372
446
|
dataProduct_setDescription(product, event.target.value);
|
373
447
|
};
|
448
|
+
return (_jsxs("div", { style: { flexDirection: 'column', display: 'flex' }, children: [_jsx(PanelFormTextField, { name: "Title", value: product.title, prompt: "Provide a descriptive name for the Data Product to appear in Marketplace.", update: updateDataProductTitle, placeholder: "Enter title" }), _jsxs("div", { style: { margin: '1rem' }, children: [_jsx("div", { className: "panel__content__form__section__header__label", children: "Description" }), _jsx("div", { className: "panel__content__form__section__header__prompt", style: {
|
449
|
+
color: product.description === '' || product.description === undefined
|
450
|
+
? 'var(--color-red-300)'
|
451
|
+
: 'var(--color-light-grey-400)',
|
452
|
+
}, children: "Clearly describe the purpose, content, and intended use of the Data Product." }), _jsx("textarea", { className: "panel__content__form__section__textarea", spellCheck: false, disabled: isReadOnly, value: product.description, onChange: updateDataProductDescription, style: {
|
453
|
+
padding: '0.5rem',
|
454
|
+
width: '45rem',
|
455
|
+
maxWidth: '45rem !important',
|
456
|
+
borderColor: product.description === '' || product.description === undefined
|
457
|
+
? 'var(--color-red-300)'
|
458
|
+
: 'transparent',
|
459
|
+
} })] })] }));
|
460
|
+
});
|
461
|
+
const SupportTab = observer((props) => {
|
462
|
+
const { product, isReadOnly } = props;
|
374
463
|
const updateSupportInfoDocumentationUrl = (val) => {
|
375
464
|
dataProduct_setSupportInfoIfAbsent(product);
|
376
465
|
if (product.supportInfo) {
|
@@ -395,19 +484,6 @@ export const DataProductEditor = observer(() => {
|
|
395
484
|
supportInfo_setSupportUrl(product.supportInfo, val ?? '');
|
396
485
|
}
|
397
486
|
};
|
398
|
-
useApplicationNavigationContext(LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY.DATA_PRODUCT_EDITOR);
|
399
|
-
useEffect(() => {
|
400
|
-
flowResult(dataProductEditorState.convertAccessPointsFuncObjects()).catch(dataProductEditorState.editorStore.applicationStore.alertUnhandledError);
|
401
|
-
}, [dataProductEditorState]);
|
402
|
-
useEffect(() => {
|
403
|
-
if (dataProductEditorState.deployOnOpen) {
|
404
|
-
flowResult(dataProductEditorState.deploy(auth.user?.access_token)).catch(editorStore.applicationStore.alertUnhandledError);
|
405
|
-
}
|
406
|
-
}, [
|
407
|
-
auth,
|
408
|
-
editorStore.applicationStore.alertUnhandledError,
|
409
|
-
dataProductEditorState,
|
410
|
-
]);
|
411
487
|
const handleSupportInfoEmailAdd = (address, title) => {
|
412
488
|
dataProduct_setSupportInfoIfAbsent(product);
|
413
489
|
if (product.supportInfo) {
|
@@ -419,12 +495,12 @@ export const DataProductEditor = observer(() => {
|
|
419
495
|
supportInfo_deleteEmail(product.supportInfo, email);
|
420
496
|
}
|
421
497
|
};
|
422
|
-
const SupportEmailComponent = observer((
|
423
|
-
const { item } =
|
498
|
+
const SupportEmailComponent = observer((supportEmailProps) => {
|
499
|
+
const { item } = supportEmailProps;
|
424
500
|
return (_jsxs("div", { className: "panel__content__form__section__list__item__rows", children: [_jsxs("div", { className: "row", children: [_jsx("label", { className: "label", children: "Address" }), _jsx("div", { className: "textbox", children: item.address })] }), _jsxs("div", { className: "row", children: [_jsx("label", { className: "label", children: "Title" }), _jsx("div", { className: "textbox", children: item.title })] })] }));
|
425
501
|
});
|
426
|
-
const NewSupportEmailComponent = observer((
|
427
|
-
const { onFinishEditing } =
|
502
|
+
const NewSupportEmailComponent = observer((newSupportEmailProps) => {
|
503
|
+
const { onFinishEditing } = newSupportEmailProps;
|
428
504
|
const [address, setAddress] = useState('');
|
429
505
|
const [title, setTitle] = useState('');
|
430
506
|
return (_jsxs("div", { className: "data-product-editor__support-info__new-email", children: [_jsx("div", { className: "panel__content__form__section__list__new-item__input", children: _jsx("input", { className: "input input-group__input panel__content__form__section__input input--dark", type: "email", placeholder: "Enter email", value: address, onChange: (event) => {
|
@@ -438,10 +514,60 @@ export const DataProductEditor = observer(() => {
|
|
438
514
|
onFinishEditing();
|
439
515
|
}, children: "Save" })] }));
|
440
516
|
});
|
441
|
-
return (
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
517
|
+
return (_jsxs(PanelFormSection, { children: [_jsx("div", { className: "panel__content__form__section__header__label", children: "Support Information" }), _jsx("div", { className: "panel__content__form__section__header__prompt", children: "Configure support information for this Lakehouse Data Product." }), _jsx(PanelFormTextField, { name: "Documentation URL", value: product.supportInfo?.documentationUrl ?? '', update: updateSupportInfoDocumentationUrl, placeholder: "Enter Documentation URL" }), _jsx(PanelFormTextField, { name: "Website", value: product.supportInfo?.website, update: updateSupportInfoWebsite, placeholder: "Enter Website" }), _jsx(PanelFormTextField, { name: "FAQ URL", value: product.supportInfo?.faqUrl, update: updateSupportInfoFaqUrl, placeholder: "Enter FAQ URL" }), _jsx(PanelFormTextField, { name: "Support URL", value: product.supportInfo?.supportUrl, update: updateSupportInfoSupportUrl, placeholder: "Enter Support URL" }), _jsx(ListEditor, { title: "Emails", items: product.supportInfo?.emails, keySelector: (email) => email.address + email.title, ItemComponent: SupportEmailComponent, NewItemComponent: NewSupportEmailComponent, handleRemoveItem: handleSupportInfoEmailRemove, isReadOnly: isReadOnly, emptyMessage: "No emails specified" })] }));
|
518
|
+
});
|
519
|
+
export const DataProductEditor = observer(() => {
|
520
|
+
const editorStore = useEditorStore();
|
521
|
+
const dataProductEditorState = editorStore.tabManagerState.getCurrentEditorState(DataProductEditorState);
|
522
|
+
const product = dataProductEditorState.product;
|
523
|
+
const isReadOnly = dataProductEditorState.isReadOnly;
|
524
|
+
const auth = useAuth();
|
525
|
+
const deployDataProduct = () => {
|
526
|
+
// Trigger OAuth flow if not authenticated
|
527
|
+
if (!auth.isAuthenticated) {
|
528
|
+
// remove this redirect if we move to do oauth at the beginning of opening studio
|
529
|
+
auth
|
530
|
+
.signinRedirect({
|
531
|
+
state: generateUrlToDeployOnOpen(dataProductEditorState),
|
532
|
+
})
|
533
|
+
.catch(editorStore.applicationStore.alertUnhandledError);
|
534
|
+
return;
|
535
|
+
}
|
536
|
+
// Use the token for deployment
|
537
|
+
const token = auth.user?.access_token;
|
538
|
+
if (token) {
|
539
|
+
flowResult(dataProductEditorState.deploy(token)).catch(editorStore.applicationStore.alertUnhandledError);
|
540
|
+
}
|
541
|
+
else {
|
542
|
+
editorStore.applicationStore.notificationService.notifyError('Authentication failed. No token available.');
|
543
|
+
}
|
544
|
+
};
|
545
|
+
const selectedActivity = dataProductEditorState.selectedTab;
|
546
|
+
const renderActivivtyBarTab = () => {
|
547
|
+
switch (selectedActivity) {
|
548
|
+
case DATA_PRODUCT_TAB.HOME:
|
549
|
+
return _jsx(HomeTab, { product: product, isReadOnly: isReadOnly });
|
550
|
+
case DATA_PRODUCT_TAB.SUPPORT:
|
551
|
+
return _jsx(SupportTab, { product: product, isReadOnly: isReadOnly });
|
552
|
+
case DATA_PRODUCT_TAB.APG:
|
553
|
+
return (_jsx(AccessPointGroupTab, { dataProductEditorState: dataProductEditorState, isReadOnly: isReadOnly }));
|
554
|
+
default:
|
555
|
+
return null;
|
556
|
+
}
|
557
|
+
};
|
558
|
+
useApplicationNavigationContext(LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY.DATA_PRODUCT_EDITOR);
|
559
|
+
useEffect(() => {
|
560
|
+
flowResult(dataProductEditorState.convertAccessPointsFuncObjects()).catch(dataProductEditorState.editorStore.applicationStore.alertUnhandledError);
|
561
|
+
}, [dataProductEditorState]);
|
562
|
+
useEffect(() => {
|
563
|
+
if (dataProductEditorState.deployOnOpen) {
|
564
|
+
flowResult(dataProductEditorState.deploy(auth.user?.access_token)).catch(editorStore.applicationStore.alertUnhandledError);
|
565
|
+
}
|
566
|
+
}, [
|
567
|
+
auth,
|
568
|
+
editorStore.applicationStore.alertUnhandledError,
|
569
|
+
dataProductEditorState,
|
570
|
+
]);
|
571
|
+
return (_jsx("div", { className: "data-product-editor", children: _jsxs("div", { className: "panel", children: [_jsxs("div", { className: "panel__header", children: [_jsxs("div", { className: "panel__header__title", children: [isReadOnly && (_jsx("div", { className: "uml-element-editor__header__lock", children: _jsx(LockIcon, {}) })), _jsx("div", { className: "panel__header__title__label", children: "data product" })] }), _jsx(PanelHeaderActions, { children: _jsx("div", { className: "btn__dropdown-combo btn__dropdown-combo--primary", children: _jsxs("button", { className: "btn__dropdown-combo__label", onClick: deployDataProduct, title: dataProductEditorState.deployValidationMessage, tabIndex: -1, disabled: !dataProductEditorState.deployValidationMessage, children: [_jsx(RocketIcon, { className: "btn__dropdown-combo__label__icon" }), _jsx("div", { className: "btn__dropdown-combo__label__title", children: "Deploy" })] }) }) })] }), _jsxs("div", { className: "panel", style: { padding: '1rem', flexDirection: 'row' }, children: [_jsx(DataProductSidebar, { dataProductEditorState: dataProductEditorState }), renderActivivtyBarTab()] })] }) }));
|
446
572
|
});
|
447
573
|
//# sourceMappingURL=DataPoductEditor.js.map
|