@finos/legend-application-studio 28.19.35 → 28.19.36
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/components/editor/editor-group/dataProduct/DataProductEditor.d.ts +13 -2
- package/lib/components/editor/editor-group/dataProduct/DataProductEditor.d.ts.map +1 -1
- package/lib/components/editor/editor-group/dataProduct/DataProductEditor.js +104 -20
- package/lib/components/editor/editor-group/dataProduct/DataProductEditor.js.map +1 -1
- package/lib/components/editor/side-bar/CreateNewElementModal.d.ts.map +1 -1
- package/lib/components/editor/side-bar/CreateNewElementModal.js +15 -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 +6 -2
- package/lib/stores/editor/NewElementState.d.ts.map +1 -1
- package/lib/stores/editor/NewElementState.js +25 -12
- package/lib/stores/editor/NewElementState.js.map +1 -1
- package/lib/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.d.ts +25 -1
- 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 +98 -4
- 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 +14 -1
- package/lib/stores/graph-modifier/DSL_DataProduct_GraphModifierHelper.d.ts.map +1 -1
- package/lib/stores/graph-modifier/DSL_DataProduct_GraphModifierHelper.js +42 -2
- package/lib/stores/graph-modifier/DSL_DataProduct_GraphModifierHelper.js.map +1 -1
- package/package.json +9 -9
- package/src/components/editor/editor-group/dataProduct/DataProductEditor.tsx +357 -41
- package/src/components/editor/side-bar/CreateNewElementModal.tsx +33 -0
- package/src/stores/editor/NewElementState.ts +25 -12
- package/src/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.ts +162 -3
- package/src/stores/graph-modifier/DSL_DataProduct_GraphModifierHelper.ts +90 -5
@@ -23,6 +23,7 @@ import {
|
|
23
23
|
DataProductEditorState,
|
24
24
|
generateUrlToDeployOnOpen,
|
25
25
|
LakehouseAccessPointState,
|
26
|
+
ModelAccessPointGroupState,
|
26
27
|
} from '../../../../stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.js';
|
27
28
|
import {
|
28
29
|
BugIcon,
|
@@ -74,6 +75,8 @@ import {
|
|
74
75
|
UploadIcon,
|
75
76
|
useDragPreviewLayer,
|
76
77
|
WarningIcon,
|
78
|
+
LongArrowRightIcon,
|
79
|
+
PURE_MappingIcon,
|
77
80
|
} from '@finos/legend-art';
|
78
81
|
import {
|
79
82
|
type ChangeEventHandler,
|
@@ -94,12 +97,19 @@ import {
|
|
94
97
|
type V1_DataProductArtifactAccessPointGroup,
|
95
98
|
type V1_DataProductArtifactAccessPointImplementation,
|
96
99
|
type V1_DataProductArtifactGeneration,
|
100
|
+
type Mapping,
|
101
|
+
type PackageableRuntime,
|
102
|
+
type DataProductRuntimeInfo,
|
103
|
+
type PackageableElement,
|
104
|
+
type DataProductElementScope,
|
105
|
+
type DataProductElement,
|
97
106
|
DataProductEmbeddedImageIcon,
|
98
107
|
DataProductLibraryIcon,
|
99
108
|
Email,
|
100
109
|
LakehouseTargetEnv,
|
101
110
|
StereotypeExplicitReference,
|
102
111
|
V1_DataProductIconLibraryId,
|
112
|
+
validate_PureExecutionMapping,
|
103
113
|
} from '@finos/legend-graph';
|
104
114
|
import {
|
105
115
|
accessPoint_setClassification,
|
@@ -115,6 +125,8 @@ import {
|
|
115
125
|
supportInfo_setDocumentationUrl,
|
116
126
|
supportInfo_setFaqUrl,
|
117
127
|
supportInfo_setLinkLabel,
|
128
|
+
runtimeInfo_setId,
|
129
|
+
runtimeInfo_setDescription,
|
118
130
|
supportInfo_setSupportUrl,
|
119
131
|
supportInfo_setWebsite,
|
120
132
|
} from '../../../../stores/graph-modifier/DSL_DataProduct_GraphModifierHelper.js';
|
@@ -130,6 +142,10 @@ import {
|
|
130
142
|
annotatedElement_addStereotype,
|
131
143
|
annotatedElement_deleteStereotype,
|
132
144
|
} from '../../../../stores/graph-modifier/DomainGraphModifierHelper.js';
|
145
|
+
import {
|
146
|
+
buildElementOption,
|
147
|
+
type PackageableElementOption,
|
148
|
+
} from '@finos/legend-lego/graph-editor';
|
133
149
|
|
134
150
|
export enum AP_GROUP_MODAL_ERRORS {
|
135
151
|
GROUP_NAME_EMPTY = 'Group Name is empty',
|
@@ -405,7 +421,7 @@ const AccessPointGenerationViewer = observer(
|
|
405
421
|
},
|
406
422
|
);
|
407
423
|
|
408
|
-
export const
|
424
|
+
export const LakehouseDataProductAccessPointEditor = observer(
|
409
425
|
(props: {
|
410
426
|
accessPointState: LakehouseAccessPointState;
|
411
427
|
isReadOnly: boolean;
|
@@ -838,6 +854,309 @@ const AccessPointGroupPublicToggle = observer(
|
|
838
854
|
},
|
839
855
|
);
|
840
856
|
|
857
|
+
export const CompatibleRuntimesEditor = observer(
|
858
|
+
(props: { groupState: ModelAccessPointGroupState }) => {
|
859
|
+
const { groupState } = props;
|
860
|
+
const group = groupState.value;
|
861
|
+
|
862
|
+
const handleSelectRuntime = (runtime: DataProductRuntimeInfo) => {
|
863
|
+
groupState.setDefaultRuntime(runtime);
|
864
|
+
};
|
865
|
+
|
866
|
+
// Event handlers
|
867
|
+
const handleAddRuntime = (option: {
|
868
|
+
label: string;
|
869
|
+
value: PackageableRuntime;
|
870
|
+
}): void => {
|
871
|
+
if (typeof option.value === 'object') {
|
872
|
+
groupState.addCompatibleRuntime(option.value);
|
873
|
+
}
|
874
|
+
};
|
875
|
+
|
876
|
+
const handleRemoveRuntime = (runtime: DataProductRuntimeInfo): void => {
|
877
|
+
groupState.removeCompatibleRuntime(runtime);
|
878
|
+
};
|
879
|
+
|
880
|
+
const handleRuntimeTitleChange = (
|
881
|
+
runtimeInfo: DataProductRuntimeInfo,
|
882
|
+
value: string | undefined,
|
883
|
+
): void => {
|
884
|
+
runtimeInfo_setId(runtimeInfo, value ?? '');
|
885
|
+
};
|
886
|
+
|
887
|
+
const handleRuntimeDescriptionChange = (
|
888
|
+
runtimeInfo: DataProductRuntimeInfo,
|
889
|
+
value: string | undefined,
|
890
|
+
): void => {
|
891
|
+
runtimeInfo_setDescription(runtimeInfo, value);
|
892
|
+
};
|
893
|
+
|
894
|
+
// ListEditor component renderers
|
895
|
+
const RuntimeComponent = observer(
|
896
|
+
(runtimeComponentProps: {
|
897
|
+
item: DataProductRuntimeInfo;
|
898
|
+
}): React.ReactElement => {
|
899
|
+
const { item } = runtimeComponentProps;
|
900
|
+
|
901
|
+
return (
|
902
|
+
<>
|
903
|
+
<div className="panel__content__form__section__list__item__content">
|
904
|
+
<div className="panel__content__form__section__header__label">
|
905
|
+
Default?
|
906
|
+
</div>
|
907
|
+
<input
|
908
|
+
type="radio"
|
909
|
+
name="defaultRuntimeRadio"
|
910
|
+
value={item.id}
|
911
|
+
checked={group.defaultRuntime === item}
|
912
|
+
onChange={() => handleSelectRuntime(item)}
|
913
|
+
/>
|
914
|
+
</div>
|
915
|
+
<div className="panel__content__form__section__list__item__content">
|
916
|
+
<div className="panel__content__form__section__header__label">
|
917
|
+
Runtime
|
918
|
+
</div>
|
919
|
+
<div className="panel__content__form__section__list__item__content__title">
|
920
|
+
{item.runtime.value.path}
|
921
|
+
</div>
|
922
|
+
</div>
|
923
|
+
<div className="panel__content__form__section__list__item__form">
|
924
|
+
<PanelFormTextField
|
925
|
+
name="Title"
|
926
|
+
value={item.id}
|
927
|
+
update={(value) => handleRuntimeTitleChange(item, value)}
|
928
|
+
placeholder="Enter title"
|
929
|
+
className="dataSpace-editor__general__diagrams__title"
|
930
|
+
/>
|
931
|
+
<PanelFormTextField
|
932
|
+
name="Description"
|
933
|
+
value={item.description ?? ''}
|
934
|
+
update={(value) => handleRuntimeDescriptionChange(item, value)}
|
935
|
+
placeholder="Enter description"
|
936
|
+
className="dataSpace-editor__general__diagrams__description"
|
937
|
+
/>
|
938
|
+
</div>
|
939
|
+
</>
|
940
|
+
);
|
941
|
+
},
|
942
|
+
);
|
943
|
+
|
944
|
+
const NewRuntimeComponent = observer(
|
945
|
+
(newRuntimeProps: {
|
946
|
+
onFinishEditing: () => void;
|
947
|
+
}): React.ReactElement => {
|
948
|
+
const { onFinishEditing } = newRuntimeProps;
|
949
|
+
|
950
|
+
return (
|
951
|
+
<div className="panel__content__form__section__list__new-item__input">
|
952
|
+
<CustomSelectorInput
|
953
|
+
options={groupState.getCompatibleRuntimeOptions()}
|
954
|
+
onChange={(event: {
|
955
|
+
label: string;
|
956
|
+
value: PackageableRuntime;
|
957
|
+
}) => {
|
958
|
+
onFinishEditing();
|
959
|
+
handleAddRuntime(event);
|
960
|
+
}}
|
961
|
+
placeholder="Select a runtime to add..."
|
962
|
+
darkMode={true}
|
963
|
+
/>
|
964
|
+
</div>
|
965
|
+
);
|
966
|
+
},
|
967
|
+
);
|
968
|
+
|
969
|
+
return (
|
970
|
+
<ListEditor
|
971
|
+
title="Compatible Runtimes"
|
972
|
+
prompt="Add compatible runtimes to include in this Data Product. Set a title and description for each runtime."
|
973
|
+
items={group.compatibleRuntimes}
|
974
|
+
keySelector={(element: DataProductRuntimeInfo) =>
|
975
|
+
element.runtime.value.path
|
976
|
+
}
|
977
|
+
ItemComponent={RuntimeComponent}
|
978
|
+
NewItemComponent={NewRuntimeComponent}
|
979
|
+
handleRemoveItem={handleRemoveRuntime}
|
980
|
+
isReadOnly={groupState.state.isReadOnly}
|
981
|
+
emptyMessage="No runtimes specified"
|
982
|
+
emptyClassName="data-product-editor__empty-runtime"
|
983
|
+
/>
|
984
|
+
);
|
985
|
+
},
|
986
|
+
);
|
987
|
+
|
988
|
+
export const FeaturedElementsEditor = observer(
|
989
|
+
(props: { groupState: ModelAccessPointGroupState; isReadOnly: boolean }) => {
|
990
|
+
const { groupState, isReadOnly } = props;
|
991
|
+
const group = groupState.value;
|
992
|
+
|
993
|
+
// Event handlers
|
994
|
+
const handleAddElement = (option: {
|
995
|
+
label: string;
|
996
|
+
value: DataProductElement;
|
997
|
+
}): void => {
|
998
|
+
if (typeof option.value === 'object') {
|
999
|
+
groupState.addFeaturedElement(option.value);
|
1000
|
+
}
|
1001
|
+
};
|
1002
|
+
|
1003
|
+
const handleRemoveElement = (element: DataProductElementScope): void => {
|
1004
|
+
groupState.removeFeaturedElement(element);
|
1005
|
+
};
|
1006
|
+
|
1007
|
+
const handleElementExcludeChange = (
|
1008
|
+
element: DataProductElementScope,
|
1009
|
+
event: React.ChangeEvent<HTMLInputElement>,
|
1010
|
+
): void => {
|
1011
|
+
groupState.excludeFeaturedElement(element, event.target.checked);
|
1012
|
+
};
|
1013
|
+
|
1014
|
+
// ListEditor component renderers
|
1015
|
+
const ElementComponent = observer(
|
1016
|
+
(elementComponentProps: {
|
1017
|
+
item: DataProductElementScope;
|
1018
|
+
}): React.ReactElement => {
|
1019
|
+
const { item } = elementComponentProps;
|
1020
|
+
|
1021
|
+
return (
|
1022
|
+
<div className="data-product-editor__element-item">
|
1023
|
+
<div className="panel__content__form__section__list__item__content__label">
|
1024
|
+
{item.element.value.path}
|
1025
|
+
</div>
|
1026
|
+
<div className="panel__content__form__section__list__item__content__actions">
|
1027
|
+
<div className="panel__content__form__section__list__item__content__actions-exclude">
|
1028
|
+
<Checkbox
|
1029
|
+
disabled={isReadOnly}
|
1030
|
+
checked={item.exclude ?? false}
|
1031
|
+
onChange={(event) => handleElementExcludeChange(item, event)}
|
1032
|
+
size="small"
|
1033
|
+
className="panel__content__form__section__list__item__content__actions-exclude__btn"
|
1034
|
+
/>
|
1035
|
+
<span className="panel__content__form__section__list__item__content__actions__label">
|
1036
|
+
Exclude
|
1037
|
+
</span>
|
1038
|
+
</div>
|
1039
|
+
</div>
|
1040
|
+
</div>
|
1041
|
+
);
|
1042
|
+
},
|
1043
|
+
);
|
1044
|
+
|
1045
|
+
const NewElementComponent = observer(
|
1046
|
+
(newElementProps: { onFinishEditing: () => void }) => {
|
1047
|
+
const { onFinishEditing } = newElementProps;
|
1048
|
+
|
1049
|
+
return (
|
1050
|
+
<div className="panel__content__form__section__list__new-item__input">
|
1051
|
+
<CustomSelectorInput
|
1052
|
+
options={groupState.getFeaturedElementOptions()}
|
1053
|
+
onChange={(event: {
|
1054
|
+
label: string;
|
1055
|
+
value: DataProductElement;
|
1056
|
+
}) => {
|
1057
|
+
onFinishEditing();
|
1058
|
+
handleAddElement(event);
|
1059
|
+
}}
|
1060
|
+
placeholder="Select an element to add..."
|
1061
|
+
darkMode={true}
|
1062
|
+
/>
|
1063
|
+
</div>
|
1064
|
+
);
|
1065
|
+
},
|
1066
|
+
);
|
1067
|
+
|
1068
|
+
return (
|
1069
|
+
<ListEditor
|
1070
|
+
title="Featured Elements"
|
1071
|
+
prompt="Add classes and associations to display under Models Documentation. Use the exclude checkbox to exclude certain elements from this Data Product entirely."
|
1072
|
+
items={group.featuredElements}
|
1073
|
+
keySelector={(element: DataProductElementScope) =>
|
1074
|
+
element.element.value.path
|
1075
|
+
}
|
1076
|
+
ItemComponent={ElementComponent}
|
1077
|
+
NewItemComponent={NewElementComponent}
|
1078
|
+
handleRemoveItem={handleRemoveElement}
|
1079
|
+
isReadOnly={isReadOnly}
|
1080
|
+
emptyMessage="No elements specified"
|
1081
|
+
/>
|
1082
|
+
);
|
1083
|
+
},
|
1084
|
+
);
|
1085
|
+
|
1086
|
+
const ModelAccessPointGroupEditor = observer(
|
1087
|
+
(props: { groupState: ModelAccessPointGroupState; isReadOnly: boolean }) => {
|
1088
|
+
const { groupState, isReadOnly } = props;
|
1089
|
+
const editorStore = useEditorStore();
|
1090
|
+
|
1091
|
+
// mapping
|
1092
|
+
const mapping = groupState.value.mapping;
|
1093
|
+
const isMappingEmpty = validate_PureExecutionMapping(
|
1094
|
+
groupState.value.mapping.value,
|
1095
|
+
);
|
1096
|
+
const mappingOptions =
|
1097
|
+
groupState.state.editorStore.graphManagerState.usableMappings.map(
|
1098
|
+
buildElementOption,
|
1099
|
+
);
|
1100
|
+
const selectedMappingOption = {
|
1101
|
+
value: mapping.value,
|
1102
|
+
label: mapping.value.path === '' ? '(none)' : mapping.value.path,
|
1103
|
+
} as PackageableElementOption<Mapping>;
|
1104
|
+
const onMappingChange = (val: PackageableElementOption<Mapping>): void => {
|
1105
|
+
if (val.value !== mapping.value) {
|
1106
|
+
groupState.setMapping(val.value);
|
1107
|
+
}
|
1108
|
+
};
|
1109
|
+
|
1110
|
+
const visitElement = (element: PackageableElement): void => {
|
1111
|
+
editorStore.graphEditorMode.openElement(element);
|
1112
|
+
};
|
1113
|
+
|
1114
|
+
return (
|
1115
|
+
<div className="data-product-editor__model-apg-editor">
|
1116
|
+
<div className="data-product-editor__model-apg-editor__label">
|
1117
|
+
Mapping
|
1118
|
+
</div>
|
1119
|
+
<div
|
1120
|
+
className="service-execution-editor__configuration__item"
|
1121
|
+
style={{ padding: '0 1rem' }}
|
1122
|
+
>
|
1123
|
+
<div className="btn--sm service-execution-editor__configuration__item__label">
|
1124
|
+
<PURE_MappingIcon />
|
1125
|
+
</div>
|
1126
|
+
<CustomSelectorInput
|
1127
|
+
className="panel__content__form__section__dropdown service-execution-editor__configuration__item__dropdown"
|
1128
|
+
disabled={isReadOnly}
|
1129
|
+
options={mappingOptions}
|
1130
|
+
onChange={onMappingChange}
|
1131
|
+
value={selectedMappingOption}
|
1132
|
+
darkMode={
|
1133
|
+
!groupState.state.editorStore.applicationStore.layoutService
|
1134
|
+
.TEMPORARY__isLightColorThemeEnabled
|
1135
|
+
}
|
1136
|
+
hasError={Boolean(isMappingEmpty)}
|
1137
|
+
/>
|
1138
|
+
<button
|
1139
|
+
className="btn--dark btn--sm service-execution-editor__configuration__item__btn"
|
1140
|
+
onClick={() => {
|
1141
|
+
visitElement(groupState.value.mapping.value);
|
1142
|
+
}}
|
1143
|
+
tabIndex={-1}
|
1144
|
+
title="See mapping"
|
1145
|
+
disabled={Boolean(isMappingEmpty)}
|
1146
|
+
>
|
1147
|
+
<LongArrowRightIcon />
|
1148
|
+
</button>
|
1149
|
+
</div>
|
1150
|
+
<CompatibleRuntimesEditor groupState={groupState} />
|
1151
|
+
<FeaturedElementsEditor
|
1152
|
+
groupState={groupState}
|
1153
|
+
isReadOnly={isReadOnly}
|
1154
|
+
/>
|
1155
|
+
</div>
|
1156
|
+
);
|
1157
|
+
},
|
1158
|
+
);
|
1159
|
+
|
841
1160
|
const AccessPointGroupEditor = observer(
|
842
1161
|
(props: { groupState: AccessPointGroupState; isReadOnly: boolean }) => {
|
843
1162
|
const { groupState, isReadOnly } = props;
|
@@ -849,7 +1168,6 @@ const AccessPointGroupEditor = observer(
|
|
849
1168
|
groupState.value.id === newNamePlaceholder,
|
850
1169
|
);
|
851
1170
|
const [isHoveringName, setIsHoveringName] = useState(false);
|
852
|
-
|
853
1171
|
const handleDescriptionEdit = () => setEditingDescription(true);
|
854
1172
|
const handleDescriptionBlur = () => {
|
855
1173
|
setEditingDescription(false);
|
@@ -958,16 +1276,18 @@ const AccessPointGroupEditor = observer(
|
|
958
1276
|
{isHoveringName && hoverIcon()}
|
959
1277
|
</div>
|
960
1278
|
)}
|
961
|
-
|
962
|
-
|
963
|
-
|
964
|
-
|
965
|
-
|
966
|
-
|
967
|
-
|
968
|
-
|
969
|
-
|
970
|
-
|
1279
|
+
{!groupState.state.modelledDataProduct && (
|
1280
|
+
<button
|
1281
|
+
className="access-point-editor__generic-entry__remove-btn--group"
|
1282
|
+
onClick={() => {
|
1283
|
+
handleRemoveAccessPointGroup();
|
1284
|
+
}}
|
1285
|
+
tabIndex={-1}
|
1286
|
+
title="Remove Access Point Group"
|
1287
|
+
>
|
1288
|
+
<TimesIcon />
|
1289
|
+
</button>
|
1290
|
+
)}
|
971
1291
|
</div>
|
972
1292
|
<div className="access-point-editor__group-container__description-editor">
|
973
1293
|
{editingDescription ? (
|
@@ -1015,13 +1335,20 @@ const AccessPointGroupEditor = observer(
|
|
1015
1335
|
{editorStore.applicationStore.config.options.dataProductConfig && (
|
1016
1336
|
<AccessPointGroupPublicToggle groupState={groupState} />
|
1017
1337
|
)}
|
1338
|
+
{groupState instanceof ModelAccessPointGroupState && (
|
1339
|
+
<ModelAccessPointGroupEditor
|
1340
|
+
groupState={groupState}
|
1341
|
+
isReadOnly={isReadOnly}
|
1342
|
+
/>
|
1343
|
+
)}
|
1018
1344
|
<PanelHeader className="panel__header--access-point">
|
1019
1345
|
<div className="panel__header__title">Access Points</div>
|
1020
1346
|
<PanelHeaderActions>
|
1347
|
+
{/* TODO: remove disabling this button for MAPG when Function Access Points are ready */}
|
1021
1348
|
<PanelHeaderActionItem
|
1022
1349
|
className="panel__header__action"
|
1023
1350
|
onClick={handleAddAccessPoint}
|
1024
|
-
disabled={isReadOnly}
|
1351
|
+
disabled={isReadOnly || productEditorState.modelledDataProduct}
|
1025
1352
|
title="Create new access point"
|
1026
1353
|
>
|
1027
1354
|
<PlusIcon />
|
@@ -1041,7 +1368,7 @@ const AccessPointGroupEditor = observer(
|
|
1041
1368
|
{groupState.accessPointStates
|
1042
1369
|
.filter(filterByType(LakehouseAccessPointState))
|
1043
1370
|
.map((apState) => (
|
1044
|
-
<
|
1371
|
+
<LakehouseDataProductAccessPointEditor
|
1045
1372
|
key={apState.uuid}
|
1046
1373
|
isReadOnly={isReadOnly}
|
1047
1374
|
accessPointState={apState}
|
@@ -1065,18 +1392,6 @@ const GroupTabRenderer = observer(
|
|
1065
1392
|
const selectedGroupState = dataProductEditorState.selectedGroupState;
|
1066
1393
|
const ref = useRef<HTMLDivElement>(null);
|
1067
1394
|
|
1068
|
-
const groupError = (): boolean => {
|
1069
|
-
return (
|
1070
|
-
group.accessPointStates.length === 0 ||
|
1071
|
-
group.value.id === newNamePlaceholder ||
|
1072
|
-
Boolean(
|
1073
|
-
group.accessPointStates.find(
|
1074
|
-
(apState) => apState.accessPoint.id === newNamePlaceholder,
|
1075
|
-
),
|
1076
|
-
)
|
1077
|
-
);
|
1078
|
-
};
|
1079
|
-
|
1080
1395
|
//Drag and Drop - reorder groups and accept access points from other groups
|
1081
1396
|
const handleHover = useCallback(
|
1082
1397
|
(item: APGDragSource): void => {
|
@@ -1162,10 +1477,11 @@ const GroupTabRenderer = observer(
|
|
1162
1477
|
? 'var(--color-dark-grey-100)'
|
1163
1478
|
: 'var(--color-dark-grey-50)',
|
1164
1479
|
}}
|
1480
|
+
role="tab"
|
1165
1481
|
>
|
1166
1482
|
{group.value.id}
|
1167
1483
|
|
1168
|
-
{
|
1484
|
+
{group.hasErrors() && (
|
1169
1485
|
<ErrorWarnIcon
|
1170
1486
|
title="Resolve Access Point Group error(s)"
|
1171
1487
|
style={{ color: 'var(--color-red-300)' }}
|
@@ -1225,21 +1541,21 @@ const AccessPointGroupTab = observer(
|
|
1225
1541
|
/>
|
1226
1542
|
);
|
1227
1543
|
})}
|
1228
|
-
|
1229
|
-
|
1230
|
-
|
1231
|
-
|
1232
|
-
|
1233
|
-
|
1234
|
-
|
1235
|
-
|
1236
|
-
|
1237
|
-
|
1238
|
-
|
1239
|
-
|
1544
|
+
{!dataProductEditorState.modelledDataProduct && (
|
1545
|
+
<PanelHeaderActionItem
|
1546
|
+
className="panel__header__action"
|
1547
|
+
onClick={handleAddAccessPointGroup}
|
1548
|
+
disabled={isReadOnly || disableAddGroup}
|
1549
|
+
title={
|
1550
|
+
disableAddGroup
|
1551
|
+
? 'Provide all group names'
|
1552
|
+
: 'Create new access point group'
|
1553
|
+
}
|
1554
|
+
>
|
1555
|
+
<PlusIcon />
|
1556
|
+
</PanelHeaderActionItem>
|
1557
|
+
)}
|
1240
1558
|
</div>
|
1241
|
-
|
1242
|
-
<PanelHeaderActions></PanelHeaderActions>
|
1243
1559
|
</PanelHeader>
|
1244
1560
|
<PanelContent>
|
1245
1561
|
{selectedGroupState && (
|
@@ -29,6 +29,7 @@ import {
|
|
29
29
|
type RuntimeOption,
|
30
30
|
NewLakehouseDataProductDriver,
|
31
31
|
NewRuntimeType,
|
32
|
+
DataProductType,
|
32
33
|
} from '../../../stores/editor/NewElementState.js';
|
33
34
|
import { Dialog, compareLabelFn, CustomSelectorInput } from '@finos/legend-art';
|
34
35
|
import type { EditorStore } from '../../../stores/editor/EditorStore.js';
|
@@ -488,6 +489,23 @@ const NewLakehouseDataProductEditor = observer(() => {
|
|
488
489
|
const handleTitleChange: React.ChangeEventHandler<HTMLInputElement> = (
|
489
490
|
event,
|
490
491
|
) => newProductDriver.setTitle(event.target.value);
|
492
|
+
|
493
|
+
const type = newProductDriver.type;
|
494
|
+
const typeOptions = Object.values(DataProductType).map((typeOption) => ({
|
495
|
+
label: prettyCONSTName(typeOption),
|
496
|
+
value: typeOption,
|
497
|
+
}));
|
498
|
+
const typeOption = {
|
499
|
+
value: type,
|
500
|
+
label: prettyCONSTName(type),
|
501
|
+
};
|
502
|
+
const onTypeChange = (val: {
|
503
|
+
value: DataProductType;
|
504
|
+
label: string;
|
505
|
+
}): void => {
|
506
|
+
newProductDriver.setType(val.value);
|
507
|
+
};
|
508
|
+
|
491
509
|
return (
|
492
510
|
<>
|
493
511
|
<div className="panel__content__form__section__header__label">Title</div>
|
@@ -500,6 +518,21 @@ const NewLakehouseDataProductEditor = observer(() => {
|
|
500
518
|
placeholder={`Choose a title for this Data Product to display in Marketplace`}
|
501
519
|
/>
|
502
520
|
</div>
|
521
|
+
<div className="panel__content__form__section__header__label">
|
522
|
+
Data Product Type
|
523
|
+
</div>
|
524
|
+
<div className="explorer__new-element-modal__driver">
|
525
|
+
<CustomSelectorInput
|
526
|
+
className="explorer__new-element-modal__driver__dropdown"
|
527
|
+
options={typeOptions}
|
528
|
+
onChange={onTypeChange}
|
529
|
+
value={typeOption}
|
530
|
+
darkMode={
|
531
|
+
!editorStore.applicationStore.layoutService
|
532
|
+
.TEMPORARY__isLightColorThemeEnabled
|
533
|
+
}
|
534
|
+
/>
|
535
|
+
</div>
|
503
536
|
</>
|
504
537
|
);
|
505
538
|
});
|
@@ -87,6 +87,9 @@ import {
|
|
87
87
|
LakehouseRuntime,
|
88
88
|
type Runtime,
|
89
89
|
AccessPointGroup,
|
90
|
+
ModelAccessPointGroup,
|
91
|
+
stub_Mapping,
|
92
|
+
DataProductRuntimeInfo,
|
90
93
|
} from '@finos/legend-graph';
|
91
94
|
import type { DSL_Mapping_LegendStudioApplicationPlugin_Extension } from '../extensions/DSL_Mapping_LegendStudioApplicationPlugin_Extension.js';
|
92
95
|
import {
|
@@ -113,7 +116,6 @@ import { EmbeddedDataType } from './editor-state/ExternalFormatState.js';
|
|
113
116
|
import { createEmbeddedData } from './editor-state/element-editor-state/data/EmbeddedDataState.js';
|
114
117
|
import {
|
115
118
|
dataProduct_addAccessPointGroup,
|
116
|
-
dataProduct_setDescription,
|
117
119
|
dataProduct_setTitle,
|
118
120
|
} from '../graph-modifier/DSL_DataProduct_GraphModifierHelper.js';
|
119
121
|
|
@@ -512,19 +514,23 @@ export class NewPackageableConnectionDriver extends NewElementDriver<Packageable
|
|
512
514
|
}
|
513
515
|
}
|
514
516
|
|
517
|
+
export enum DataProductType {
|
518
|
+
LAKEHOUSE = 'LAKEHOUSE',
|
519
|
+
MODELLED = 'MODELLED',
|
520
|
+
}
|
521
|
+
|
515
522
|
export class NewLakehouseDataProductDriver extends NewElementDriver<DataProduct> {
|
516
523
|
title: string;
|
517
|
-
|
524
|
+
type = DataProductType.LAKEHOUSE;
|
518
525
|
|
519
526
|
constructor(editorStore: EditorStore) {
|
520
527
|
super(editorStore);
|
521
528
|
this.title = '';
|
522
|
-
this.description = '';
|
523
529
|
makeObservable(this, {
|
524
530
|
title: observable,
|
525
|
-
|
531
|
+
type: observable,
|
532
|
+
setType: action,
|
526
533
|
setTitle: action,
|
527
|
-
setDescription: action,
|
528
534
|
isValid: computed,
|
529
535
|
});
|
530
536
|
}
|
@@ -532,21 +538,28 @@ export class NewLakehouseDataProductDriver extends NewElementDriver<DataProduct>
|
|
532
538
|
override get isValid(): boolean {
|
533
539
|
return Boolean(this.title);
|
534
540
|
}
|
535
|
-
|
536
541
|
setTitle(val: string) {
|
537
542
|
this.title = val;
|
538
543
|
}
|
539
|
-
|
540
|
-
this.
|
544
|
+
setType(val: DataProductType) {
|
545
|
+
this.type = val;
|
541
546
|
}
|
542
547
|
override createElement(name: string): DataProduct {
|
543
548
|
const dataProduct = new DataProduct(name);
|
544
549
|
dataProduct_setTitle(dataProduct, this.title);
|
545
|
-
dataProduct_setDescription(dataProduct, this.description);
|
546
550
|
|
547
|
-
|
548
|
-
|
549
|
-
|
551
|
+
if (this.type === DataProductType.LAKEHOUSE) {
|
552
|
+
const defaultGroup = new AccessPointGroup();
|
553
|
+
defaultGroup.id = 'default';
|
554
|
+
dataProduct_addAccessPointGroup(dataProduct, defaultGroup);
|
555
|
+
} else {
|
556
|
+
const defaultGroup = new ModelAccessPointGroup();
|
557
|
+
defaultGroup.id = 'default';
|
558
|
+
defaultGroup.mapping =
|
559
|
+
PackageableElementExplicitReference.create(stub_Mapping());
|
560
|
+
defaultGroup.defaultRuntime = new DataProductRuntimeInfo();
|
561
|
+
dataProduct_addAccessPointGroup(dataProduct, defaultGroup);
|
562
|
+
}
|
550
563
|
|
551
564
|
return dataProduct;
|
552
565
|
}
|