@finos/legend-application-studio 28.18.147 → 28.19.0

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 (160) hide show
  1. package/lib/application/LegendIngestionConfiguration.d.ts +1 -5
  2. package/lib/application/LegendIngestionConfiguration.d.ts.map +1 -1
  3. package/lib/application/LegendIngestionConfiguration.js +1 -8
  4. package/lib/application/LegendIngestionConfiguration.js.map +1 -1
  5. package/lib/components/ElementIconUtils.d.ts.map +1 -1
  6. package/lib/components/ElementIconUtils.js +3 -1
  7. package/lib/components/ElementIconUtils.js.map +1 -1
  8. package/lib/components/editor/editor-group/EditorGroup.d.ts +2 -0
  9. package/lib/components/editor/editor-group/EditorGroup.d.ts.map +1 -1
  10. package/lib/components/editor/editor-group/EditorGroup.js +16 -2
  11. package/lib/components/editor/editor-group/EditorGroup.js.map +1 -1
  12. package/lib/components/editor/editor-group/RuntimeEditor.d.ts.map +1 -1
  13. package/lib/components/editor/editor-group/RuntimeEditor.js +3 -1
  14. package/lib/components/editor/editor-group/RuntimeEditor.js.map +1 -1
  15. package/lib/components/editor/editor-group/connection-editor/RelationalDatabaseConnectionEditor.d.ts.map +1 -1
  16. package/lib/components/editor/editor-group/connection-editor/RelationalDatabaseConnectionEditor.js +3 -3
  17. package/lib/components/editor/editor-group/connection-editor/RelationalDatabaseConnectionEditor.js.map +1 -1
  18. package/lib/components/editor/editor-group/dataProduct/DataPoductEditor.d.ts.map +1 -1
  19. package/lib/components/editor/editor-group/dataProduct/DataPoductEditor.js +140 -26
  20. package/lib/components/editor/editor-group/dataProduct/DataPoductEditor.js.map +1 -1
  21. package/lib/components/editor/editor-group/function-activator/FunctionEditor.d.ts +1 -0
  22. package/lib/components/editor/editor-group/function-activator/FunctionEditor.d.ts.map +1 -1
  23. package/lib/components/editor/editor-group/function-activator/FunctionEditor.js +21 -3
  24. package/lib/components/editor/editor-group/function-activator/FunctionEditor.js.map +1 -1
  25. package/lib/{stores/ingestion/AdhocDataProductDeployResponse.js → components/editor/editor-group/function-activator/MemSQLFunctionActivatorEditor.d.ts} +3 -8
  26. package/lib/components/editor/editor-group/function-activator/MemSQLFunctionActivatorEditor.d.ts.map +1 -0
  27. package/lib/components/editor/editor-group/function-activator/MemSQLFunctionActivatorEditor.js +89 -0
  28. package/lib/components/editor/editor-group/function-activator/MemSQLFunctionActivatorEditor.js.map +1 -0
  29. package/lib/components/editor/editor-group/ingest-editor/IngestDefinitionEditor.js +1 -1
  30. package/lib/components/editor/editor-group/ingest-editor/IngestDefinitionEditor.js.map +1 -1
  31. package/lib/components/editor/editor-group/service-editor/ServiceExecutionQueryEditor.d.ts.map +1 -1
  32. package/lib/components/editor/editor-group/service-editor/ServiceExecutionQueryEditor.js +1 -2
  33. package/lib/components/editor/editor-group/service-editor/ServiceExecutionQueryEditor.js.map +1 -1
  34. package/lib/components/editor/side-bar/CreateNewElementModal.d.ts.map +1 -1
  35. package/lib/components/editor/side-bar/CreateNewElementModal.js +7 -7
  36. package/lib/components/editor/side-bar/CreateNewElementModal.js.map +1 -1
  37. package/lib/index.css +2 -2
  38. package/lib/index.css.map +1 -1
  39. package/lib/index.d.ts +2 -0
  40. package/lib/index.d.ts.map +1 -1
  41. package/lib/index.js +2 -0
  42. package/lib/index.js.map +1 -1
  43. package/lib/package.json +2 -1
  44. package/lib/stores/editor/EditorGraphState.d.ts.map +1 -1
  45. package/lib/stores/editor/EditorGraphState.js +4 -1
  46. package/lib/stores/editor/EditorGraphState.js.map +1 -1
  47. package/lib/stores/editor/EditorStore.d.ts +2 -2
  48. package/lib/stores/editor/EditorStore.d.ts.map +1 -1
  49. package/lib/stores/editor/EditorStore.js +2 -2
  50. package/lib/stores/editor/EditorStore.js.map +1 -1
  51. package/lib/stores/editor/EditorTabManagerState.d.ts.map +1 -1
  52. package/lib/stores/editor/EditorTabManagerState.js +5 -1
  53. package/lib/stores/editor/EditorTabManagerState.js.map +1 -1
  54. package/lib/stores/editor/NewElementState.d.ts +2 -0
  55. package/lib/stores/editor/NewElementState.d.ts.map +1 -1
  56. package/lib/stores/editor/NewElementState.js +10 -2
  57. package/lib/stores/editor/NewElementState.js.map +1 -1
  58. package/lib/stores/editor/data-cube/LegendStudioDataCubeHelper.d.ts +2 -2
  59. package/lib/stores/editor/data-cube/LegendStudioDataCubeHelper.d.ts.map +1 -1
  60. package/lib/stores/editor/data-cube/LegendStudioDataCubeHelper.js +4 -3
  61. package/lib/stores/editor/data-cube/LegendStudioDataCubeHelper.js.map +1 -1
  62. package/lib/stores/editor/editor-state/element-editor-state/FunctionActivatorState.d.ts.map +1 -1
  63. package/lib/stores/editor/editor-state/element-editor-state/FunctionActivatorState.js +14 -1
  64. package/lib/stores/editor/editor-state/element-editor-state/FunctionActivatorState.js.map +1 -1
  65. package/lib/stores/editor/editor-state/element-editor-state/FunctionEditorState.d.ts +3 -0
  66. package/lib/stores/editor/editor-state/element-editor-state/FunctionEditorState.d.ts.map +1 -1
  67. package/lib/stores/editor/editor-state/element-editor-state/FunctionEditorState.js +24 -1
  68. package/lib/stores/editor/editor-state/element-editor-state/FunctionEditorState.js.map +1 -1
  69. package/lib/stores/editor/editor-state/element-editor-state/connection/ConnectionEditorState.d.ts.map +1 -1
  70. package/lib/stores/editor/editor-state/element-editor-state/connection/ConnectionEditorState.js +3 -2
  71. package/lib/stores/editor/editor-state/element-editor-state/connection/ConnectionEditorState.js.map +1 -1
  72. package/lib/stores/editor/editor-state/element-editor-state/connection/DatabaseBuilderState.d.ts.map +1 -1
  73. package/lib/stores/editor/editor-state/element-editor-state/connection/DatabaseBuilderState.js +4 -1
  74. package/lib/stores/editor/editor-state/element-editor-state/connection/DatabaseBuilderState.js.map +1 -1
  75. package/lib/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.d.ts +9 -4
  76. package/lib/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.d.ts.map +1 -1
  77. package/lib/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.js +23 -4
  78. package/lib/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.js.map +1 -1
  79. package/lib/stores/editor/editor-state/element-editor-state/function-activator/HostedServiceFunctionActivatorEditorState.js +3 -3
  80. package/lib/stores/editor/editor-state/element-editor-state/function-activator/HostedServiceFunctionActivatorEditorState.js.map +1 -1
  81. package/lib/stores/editor/editor-state/element-editor-state/function-activator/MemSQLFunctionActivatorEditorState.d.ts +33 -0
  82. package/lib/stores/editor/editor-state/element-editor-state/function-activator/MemSQLFunctionActivatorEditorState.d.ts.map +1 -0
  83. package/lib/stores/editor/editor-state/element-editor-state/function-activator/MemSQLFunctionActivatorEditorState.js +86 -0
  84. package/lib/stores/editor/editor-state/element-editor-state/function-activator/MemSQLFunctionActivatorEditorState.js.map +1 -0
  85. package/lib/stores/editor/editor-state/element-editor-state/function-activator/SnowflakeAppFunctionActivatorEditorState.d.ts.map +1 -1
  86. package/lib/stores/editor/editor-state/element-editor-state/function-activator/SnowflakeAppFunctionActivatorEditorState.js +28 -2
  87. package/lib/stores/editor/editor-state/element-editor-state/function-activator/SnowflakeAppFunctionActivatorEditorState.js.map +1 -1
  88. package/lib/stores/editor/editor-state/element-editor-state/ingest/IngestDefinitionEditorState.d.ts +2 -3
  89. package/lib/stores/editor/editor-state/element-editor-state/ingest/IngestDefinitionEditorState.d.ts.map +1 -1
  90. package/lib/stores/editor/editor-state/element-editor-state/ingest/IngestDefinitionEditorState.js.map +1 -1
  91. package/lib/stores/editor/editor-state/element-editor-state/service/ServiceExecutionState.d.ts +4 -1
  92. package/lib/stores/editor/editor-state/element-editor-state/service/ServiceExecutionState.d.ts.map +1 -1
  93. package/lib/stores/editor/editor-state/element-editor-state/service/ServiceExecutionState.js +24 -1
  94. package/lib/stores/editor/editor-state/element-editor-state/service/ServiceExecutionState.js.map +1 -1
  95. package/lib/stores/editor/panel-group/SQLPlaygroundPanelState.js +1 -1
  96. package/lib/stores/editor/panel-group/SQLPlaygroundPanelState.js.map +1 -1
  97. package/lib/stores/editor/utils/ModelClassifierUtils.d.ts +1 -0
  98. package/lib/stores/editor/utils/ModelClassifierUtils.d.ts.map +1 -1
  99. package/lib/stores/editor/utils/ModelClassifierUtils.js +1 -0
  100. package/lib/stores/editor/utils/ModelClassifierUtils.js.map +1 -1
  101. package/lib/stores/graph-modifier/DSL_DataProduct_GraphModifierHelper.d.ts +3 -2
  102. package/lib/stores/graph-modifier/DSL_DataProduct_GraphModifierHelper.d.ts.map +1 -1
  103. package/lib/stores/graph-modifier/DSL_DataProduct_GraphModifierHelper.js +7 -4
  104. package/lib/stores/graph-modifier/DSL_DataProduct_GraphModifierHelper.js.map +1 -1
  105. package/package.json +9 -8
  106. package/src/application/LegendIngestionConfiguration.ts +1 -12
  107. package/src/components/ElementIconUtils.tsx +3 -0
  108. package/src/components/editor/editor-group/EditorGroup.tsx +29 -8
  109. package/src/components/editor/editor-group/RuntimeEditor.tsx +3 -1
  110. package/src/components/editor/editor-group/connection-editor/RelationalDatabaseConnectionEditor.tsx +3 -2
  111. package/src/components/editor/editor-group/dataProduct/DataPoductEditor.tsx +375 -65
  112. package/src/components/editor/editor-group/function-activator/FunctionEditor.tsx +40 -2
  113. package/src/components/editor/editor-group/function-activator/MemSQLFunctionActivatorEditor.tsx +269 -0
  114. package/src/components/editor/editor-group/ingest-editor/IngestDefinitionEditor.tsx +1 -1
  115. package/src/components/editor/editor-group/service-editor/ServiceExecutionQueryEditor.tsx +1 -2
  116. package/src/components/editor/side-bar/CreateNewElementModal.tsx +38 -6
  117. package/src/index.ts +2 -0
  118. package/src/stores/editor/EditorGraphState.ts +3 -0
  119. package/src/stores/editor/EditorStore.ts +7 -5
  120. package/src/stores/editor/EditorTabManagerState.ts +4 -0
  121. package/src/stores/editor/NewElementState.ts +13 -2
  122. package/src/stores/editor/data-cube/LegendStudioDataCubeHelper.ts +14 -2
  123. package/src/stores/editor/editor-state/element-editor-state/FunctionActivatorState.ts +15 -0
  124. package/src/stores/editor/editor-state/element-editor-state/FunctionEditorState.ts +50 -0
  125. package/src/stores/editor/editor-state/element-editor-state/connection/ConnectionEditorState.ts +3 -2
  126. package/src/stores/editor/editor-state/element-editor-state/connection/DatabaseBuilderState.ts +4 -1
  127. package/src/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.ts +31 -5
  128. package/src/stores/editor/editor-state/element-editor-state/function-activator/HostedServiceFunctionActivatorEditorState.ts +3 -3
  129. package/src/stores/editor/editor-state/element-editor-state/function-activator/MemSQLFunctionActivatorEditorState.ts +130 -0
  130. package/src/stores/editor/editor-state/element-editor-state/function-activator/SnowflakeAppFunctionActivatorEditorState.ts +38 -7
  131. package/src/stores/editor/editor-state/element-editor-state/ingest/IngestDefinitionEditorState.ts +3 -3
  132. package/src/stores/editor/editor-state/element-editor-state/service/ServiceExecutionState.ts +51 -0
  133. package/src/stores/editor/panel-group/SQLPlaygroundPanelState.ts +1 -1
  134. package/src/stores/editor/utils/ModelClassifierUtils.ts +1 -0
  135. package/src/stores/graph-modifier/DSL_DataProduct_GraphModifierHelper.ts +10 -4
  136. package/tsconfig.json +2 -5
  137. package/lib/stores/ingestion/AdhocDataProductDeployResponse.d.ts +0 -21
  138. package/lib/stores/ingestion/AdhocDataProductDeployResponse.d.ts.map +0 -1
  139. package/lib/stores/ingestion/AdhocDataProductDeployResponse.js.map +0 -1
  140. package/lib/stores/ingestion/IngestDeploymentServerClient.d.ts +0 -35
  141. package/lib/stores/ingestion/IngestDeploymentServerClient.d.ts.map +0 -1
  142. package/lib/stores/ingestion/IngestDeploymentServerClient.js +0 -58
  143. package/lib/stores/ingestion/IngestDeploymentServerClient.js.map +0 -1
  144. package/lib/stores/ingestion/IngestDiscoveryServerClient.d.ts +0 -26
  145. package/lib/stores/ingestion/IngestDiscoveryServerClient.d.ts.map +0 -1
  146. package/lib/stores/ingestion/IngestDiscoveryServerClient.js +0 -35
  147. package/lib/stores/ingestion/IngestDiscoveryServerClient.js.map +0 -1
  148. package/lib/stores/ingestion/IngestionDeploymentResponse.d.ts +0 -41
  149. package/lib/stores/ingestion/IngestionDeploymentResponse.d.ts.map +0 -1
  150. package/lib/stores/ingestion/IngestionDeploymentResponse.js +0 -56
  151. package/lib/stores/ingestion/IngestionDeploymentResponse.js.map +0 -1
  152. package/lib/stores/ingestion/IngestionManager.d.ts +0 -38
  153. package/lib/stores/ingestion/IngestionManager.d.ts.map +0 -1
  154. package/lib/stores/ingestion/IngestionManager.js +0 -111
  155. package/lib/stores/ingestion/IngestionManager.js.map +0 -1
  156. package/src/stores/ingestion/AdhocDataProductDeployResponse.ts +0 -29
  157. package/src/stores/ingestion/IngestDeploymentServerClient.ts +0 -112
  158. package/src/stores/ingestion/IngestDiscoveryServerClient.ts +0 -52
  159. package/src/stores/ingestion/IngestionDeploymentResponse.ts +0 -74
  160. package/src/stores/ingestion/IngestionManager.ts +0 -219
@@ -58,13 +58,10 @@ import { action, flowResult } from 'mobx';
58
58
  import { useAuth } from 'react-oidc-context';
59
59
  import { CODE_EDITOR_LANGUAGE } from '@finos/legend-code-editor';
60
60
  import { CodeEditor } from '@finos/legend-lego/code-editor';
61
- import {
62
- type AccessPointGroup,
63
- LakehouseTargetEnv,
64
- type LakehouseAccessPoint,
65
- } from '@finos/legend-graph';
61
+ import { LakehouseTargetEnv } from '@finos/legend-graph';
66
62
  import {
67
63
  accessPointGroup_setDescription,
64
+ accessPointGroup_setName,
68
65
  dataProduct_setDescription,
69
66
  dataProduct_setTitle,
70
67
  } from '../../../../stores/graph-modifier/DSL_DataProduct_GraphModifierHelper.js';
@@ -88,7 +85,13 @@ const NewAccessPointAccessPOint = observer(
88
85
  };
89
86
  const handleSubmit = () => {
90
87
  if (id) {
91
- dataProductEditorState.addAccessPoint(id, description, 'default');
88
+ const accessPointGroup =
89
+ dataProductEditorState.editingGroupState ?? 'default';
90
+ dataProductEditorState.addAccessPoint(
91
+ id,
92
+ description,
93
+ accessPointGroup,
94
+ );
92
95
  handleClose();
93
96
  }
94
97
  };
@@ -98,15 +101,20 @@ const NewAccessPointAccessPOint = observer(
98
101
  const disableCreateButton =
99
102
  id === '' ||
100
103
  id === undefined ||
104
+ description === '' ||
105
+ description === undefined ||
101
106
  dataProductEditorState.accessPoints.map((e) => e.id).includes(id);
102
- const errors =
107
+ const nameErrors =
103
108
  id === ''
104
- ? `ID is empty`
109
+ ? `Name is empty`
105
110
  : dataProductEditorState.accessPoints
106
111
  .map((e) => e.id)
107
112
  .includes(id ?? '')
108
- ? `ID already exists`
113
+ ? `Name already exists`
109
114
  : undefined;
115
+
116
+ const descriptionErrors =
117
+ description === '' ? `Description is empty` : undefined;
110
118
  return (
111
119
  <Dialog
112
120
  open={true}
@@ -131,11 +139,16 @@ const NewAccessPointAccessPOint = observer(
131
139
  className={clsx('modal search-modal', {
132
140
  'modal--dark': true,
133
141
  })}
142
+ style={{
143
+ display: 'flex',
144
+ flexDirection: 'column',
145
+ gap: '1rem',
146
+ }}
134
147
  >
135
148
  <div className="modal__title">New Access Point</div>
136
149
  <div>
137
150
  <div className="panel__content__form__section__header__label">
138
- ID
151
+ Name
139
152
  </div>
140
153
  <InputWithInlineValidation
141
154
  className={clsx('input new-access-point-modal__id-input', {
@@ -146,7 +159,7 @@ const NewAccessPointAccessPOint = observer(
146
159
  value={id}
147
160
  onChange={handleIdChange}
148
161
  placeholder="Access Point ID"
149
- error={errors}
162
+ error={nameErrors}
150
163
  />
151
164
  </div>
152
165
  <div>
@@ -161,9 +174,10 @@ const NewAccessPointAccessPOint = observer(
161
174
  value={description}
162
175
  onChange={handleDescriptionChange}
163
176
  placeholder="Access Point Description"
164
- error={errors}
177
+ error={descriptionErrors}
165
178
  />
166
179
  </div>
180
+ <div></div>
167
181
  <PanelDivider />
168
182
  <div className="search-modal__actions">
169
183
  <button
@@ -181,15 +195,205 @@ const NewAccessPointAccessPOint = observer(
181
195
  },
182
196
  );
183
197
 
184
- interface DescriptionTextAreaProps {
185
- accessPoint: LakehouseAccessPoint | AccessPointGroup;
198
+ const NewAccessPointGroupModal = observer(
199
+ (props: { dataProductEditorState: DataProductEditorState }) => {
200
+ const { dataProductEditorState: dataProductEditorState } = props;
201
+ const accessPointGroupInputRef = useRef<HTMLInputElement>(null);
202
+ const [groupName, setGroupName] = useState<string | undefined>(undefined);
203
+ const handleGroupNameChange: React.ChangeEventHandler<HTMLInputElement> = (
204
+ event,
205
+ ) => setGroupName(event.target.value);
206
+ const [groupDescription, setGroupDescription] = useState<
207
+ string | undefined
208
+ >(undefined);
209
+ const handleGroupDescriptionChange: React.ChangeEventHandler<
210
+ HTMLInputElement
211
+ > = (event) => setGroupDescription(event.target.value);
212
+ const [apName, setApName] = useState<string | undefined>(undefined);
213
+ const handleApNameChange: React.ChangeEventHandler<HTMLInputElement> = (
214
+ event,
215
+ ) => setApName(event.target.value);
216
+ const [apDescription, setApDescription] = useState<string | undefined>(
217
+ undefined,
218
+ );
219
+ const handleApDescriptionChange: React.ChangeEventHandler<
220
+ HTMLInputElement
221
+ > = (event) => setApDescription(event.target.value);
222
+ const handleClose = () => {
223
+ dataProductEditorState.setAccessPointGroupModal(false);
224
+ };
225
+ const handleEnter = (): void => {
226
+ accessPointGroupInputRef.current?.focus();
227
+ };
228
+
229
+ const groupNameErrors =
230
+ groupName === ''
231
+ ? `Group Name is empty`
232
+ : dataProductEditorState.accessPointGroupStates
233
+ .map((e) => e.value.id)
234
+ .includes(groupName ?? '')
235
+ ? `Group Name already exists`
236
+ : undefined;
237
+ const groupDescriptionErrors =
238
+ groupDescription === '' ? `Group Description is empty` : undefined;
239
+ const apNameErrors =
240
+ apName === ''
241
+ ? `Access Point Name is empty`
242
+ : dataProductEditorState.accessPoints
243
+ .map((e) => e.id)
244
+ .includes(apName ?? '')
245
+ ? `Access Point Name already exists`
246
+ : undefined;
247
+ const apDescriptionErrors =
248
+ apDescription === '' ? `Access Point Description is empty` : undefined;
249
+
250
+ const disableCreateButton =
251
+ !groupName ||
252
+ !groupDescription ||
253
+ !apName ||
254
+ !apDescription ||
255
+ Boolean(
256
+ groupNameErrors ??
257
+ groupDescriptionErrors ??
258
+ apNameErrors ??
259
+ apDescriptionErrors,
260
+ );
261
+ const handleSubmit = () => {
262
+ if (!disableCreateButton && apName) {
263
+ const createdGroup = dataProductEditorState.createGroupAndAdd(
264
+ groupName,
265
+ groupDescription,
266
+ );
267
+ dataProductEditorState.addAccessPoint(
268
+ apName,
269
+ apDescription,
270
+ createdGroup,
271
+ );
272
+ handleClose();
273
+ }
274
+ };
275
+
276
+ return (
277
+ <Dialog
278
+ open={true}
279
+ onClose={handleClose}
280
+ TransitionProps={{
281
+ onEnter: handleEnter,
282
+ }}
283
+ classes={{
284
+ container: 'search-modal__container',
285
+ }}
286
+ PaperProps={{
287
+ classes: {
288
+ root: 'search-modal__inner-container',
289
+ },
290
+ }}
291
+ >
292
+ <form
293
+ onSubmit={(event) => {
294
+ event.preventDefault();
295
+ handleSubmit();
296
+ }}
297
+ className={clsx('modal search-modal', {
298
+ 'modal--dark': true,
299
+ })}
300
+ style={{
301
+ display: 'flex',
302
+ flexDirection: 'column',
303
+ gap: '1rem',
304
+ }}
305
+ >
306
+ <div className="modal__title">New Access Point Group</div>
307
+ <div>
308
+ <div className="panel__content__form__section__header__label">
309
+ Group Name
310
+ </div>
311
+ <InputWithInlineValidation
312
+ className={clsx('input new-access-point-modal__id-input', {
313
+ 'input--dark': true,
314
+ })}
315
+ ref={accessPointGroupInputRef}
316
+ spellCheck={false}
317
+ value={groupName}
318
+ onChange={handleGroupNameChange}
319
+ placeholder="Access Point Group Name"
320
+ error={groupNameErrors}
321
+ />
322
+ </div>
323
+ <div>
324
+ <div className="panel__content__form__section__header__label">
325
+ Group Description
326
+ </div>
327
+ <InputWithInlineValidation
328
+ className={clsx('input new-access-point-modal__id-input', {
329
+ 'input--dark': true,
330
+ })}
331
+ spellCheck={false}
332
+ value={groupDescription}
333
+ onChange={handleGroupDescriptionChange}
334
+ placeholder="Access Point Group Description"
335
+ error={groupDescriptionErrors}
336
+ />
337
+ </div>
338
+ <div>
339
+ <div className="panel__content__form__section__header__label">
340
+ Access Point
341
+ </div>
342
+ <div className="new-access-point-group-modal">
343
+ <div className="panel__content__form__section__header__label">
344
+ Name
345
+ </div>
346
+ <InputWithInlineValidation
347
+ className={clsx('input new-access-point-modal__id-input', {
348
+ 'input--dark': true,
349
+ })}
350
+ spellCheck={false}
351
+ value={apName}
352
+ onChange={handleApNameChange}
353
+ placeholder="Access Point Name"
354
+ error={apNameErrors}
355
+ />
356
+ <div className="panel__content__form__section__header__label">
357
+ Description
358
+ </div>
359
+ <InputWithInlineValidation
360
+ className={clsx('input new-access-point-modal__id-input', {
361
+ 'input--dark': true,
362
+ })}
363
+ spellCheck={false}
364
+ value={apDescription}
365
+ onChange={handleApDescriptionChange}
366
+ placeholder="Access Point Description"
367
+ error={apDescriptionErrors}
368
+ />
369
+ </div>
370
+ </div>
371
+ <PanelDivider />
372
+ <div className="search-modal__actions">
373
+ <button
374
+ className={clsx('btn btn--primary', {
375
+ 'btn--dark': true,
376
+ })}
377
+ disabled={disableCreateButton}
378
+ >
379
+ Create
380
+ </button>
381
+ </div>
382
+ </form>
383
+ </Dialog>
384
+ );
385
+ },
386
+ );
387
+
388
+ interface HoverTextAreaProps {
389
+ text: string;
186
390
  handleMouseOver: (event: React.MouseEvent<HTMLDivElement>) => void;
187
391
  handleMouseOut: (event: React.MouseEvent<HTMLDivElement>) => void;
188
392
  className?: string;
189
393
  }
190
394
 
191
- const DescriptionTextArea: React.FC<DescriptionTextAreaProps> = ({
192
- accessPoint,
395
+ const HoverTextArea: React.FC<HoverTextAreaProps> = ({
396
+ text: text,
193
397
  handleMouseOver,
194
398
  handleMouseOut,
195
399
  className,
@@ -200,7 +404,7 @@ const DescriptionTextArea: React.FC<DescriptionTextAreaProps> = ({
200
404
  onMouseOut={handleMouseOut}
201
405
  className={clsx(className)}
202
406
  >
203
- {accessPoint.description}
407
+ {text}
204
408
  </div>
205
409
  );
206
410
  };
@@ -282,14 +486,26 @@ export const LakehouseDataProductAcccessPointEditor = observer(
282
486
  ) : (
283
487
  <div
284
488
  onClick={handleEdit}
285
- title="Click to edit description"
489
+ title="Click to edit access point description"
286
490
  className="access-point-editor__description-container"
287
491
  >
288
- <DescriptionTextArea
289
- accessPoint={accessPoint}
290
- handleMouseOver={handleMouseOver}
291
- handleMouseOut={handleMouseOut}
292
- />
492
+ {accessPoint.description ? (
493
+ <HoverTextArea
494
+ text={accessPoint.description}
495
+ handleMouseOver={handleMouseOver}
496
+ handleMouseOut={handleMouseOut}
497
+ />
498
+ ) : (
499
+ <div
500
+ className="access-point-editor__group-container__description--warning"
501
+ onMouseOver={handleMouseOver}
502
+ onMouseOut={handleMouseOut}
503
+ >
504
+ <WarningIcon />
505
+ Describe the data this access point produces
506
+ </div>
507
+ )}
508
+
293
509
  {isHovering && hoverIcon()}
294
510
  </div>
295
511
  )}
@@ -384,15 +600,15 @@ const DataProductEditorSplashScreen = observer(
384
600
  return (
385
601
  <div ref={ref} className="data-product-editor__splash-screen">
386
602
  <div
387
- onClick={() => dataProductEditorState.setAccessPointModal(true)}
603
+ onClick={() => dataProductEditorState.setAccessPointGroupModal(true)}
388
604
  className="data-product-editor__splash-screen__label"
389
605
  >
390
- Add Access Point
606
+ Add Access Point Group
391
607
  </div>
392
608
  <div className="data-product-editor__splash-screen__spacing"></div>
393
609
  <div
394
- onClick={() => dataProductEditorState.setAccessPointModal(true)}
395
- title="Add new Access Point"
610
+ onClick={() => dataProductEditorState.setAccessPointGroupModal(true)}
611
+ title="Add new Access Point Group"
396
612
  className={clsx('data-product-editor__splash-screen__logo', {
397
613
  'data-product-editor__splash-screen__logo--hidden': !showLogo,
398
614
  })}
@@ -457,31 +673,95 @@ const DataProductDeploymentResponseModal = observer(
457
673
  const AccessPointGroupSection = observer(
458
674
  (props: { groupState: AccessPointGroupState; isReadOnly: boolean }) => {
459
675
  const { groupState, isReadOnly } = props;
676
+ const productEditorState = groupState.state;
460
677
  const [editingDescription, setEditingDescription] = useState(false);
461
- const [isHovering, setIsHovering] = useState(false);
678
+ const [isHoveringDescription, setIsHoveringDescription] = useState(false);
679
+ const [editingName, setEditingName] = useState(false);
680
+ const [isHoveringName, setIsHoveringName] = useState(false);
462
681
 
463
- const handleEdit = () => setEditingDescription(true);
464
- const handleBlur = () => {
682
+ const handleDescriptionEdit = () => setEditingDescription(true);
683
+ const handleDescriptionBlur = () => {
465
684
  setEditingDescription(false);
466
- setIsHovering(false);
685
+ setIsHoveringDescription(false);
467
686
  };
468
- const handleMouseOver: React.MouseEventHandler<HTMLDivElement> = () => {
469
- setIsHovering(true);
687
+ const handleMouseOverDescription: React.MouseEventHandler<
688
+ HTMLDivElement
689
+ > = () => {
690
+ setIsHoveringDescription(true);
470
691
  };
471
- const handleMouseOut: React.MouseEventHandler<HTMLDivElement> = () => {
472
- setIsHovering(false);
692
+ const handleMouseOutDescription: React.MouseEventHandler<
693
+ HTMLDivElement
694
+ > = () => {
695
+ setIsHoveringDescription(false);
473
696
  };
474
-
475
697
  const updateGroupDescription = (val: string): void => {
476
698
  accessPointGroup_setDescription(groupState.value, val);
477
699
  };
700
+
701
+ const handleNameEdit = () => setEditingName(true);
702
+ const handleNameBlur = () => {
703
+ setEditingName(false);
704
+ setIsHoveringName(false);
705
+ };
706
+ const handleMouseOverName: React.MouseEventHandler<HTMLDivElement> = () => {
707
+ setIsHoveringName(true);
708
+ };
709
+ const handleMouseOutName: React.MouseEventHandler<HTMLDivElement> = () => {
710
+ setIsHoveringName(false);
711
+ };
712
+ const updateGroupName = (val: string): void => {
713
+ if (val) {
714
+ accessPointGroup_setName(groupState.value, val);
715
+ }
716
+ };
717
+
718
+ const openNewModal = () => {
719
+ productEditorState.setEditingGroupState(groupState);
720
+ productEditorState.setAccessPointModal(true);
721
+ };
478
722
  return (
479
- <div
480
- key={groupState.value.id}
481
- className="access-point-editor__group-container"
482
- >
483
- <div className="access-point-editor__group-container__title">
484
- {groupState.value.id}
723
+ <div className="access-point-editor__group-container">
724
+ <div className="access-point-editor__group-container__title-editor">
725
+ {editingName ? (
726
+ <textarea
727
+ className="panel__content__form__section__input"
728
+ spellCheck={false}
729
+ value={groupState.value.id}
730
+ onChange={(event) => updateGroupName(event.target.value)}
731
+ placeholder="Access Point Group Name"
732
+ onBlur={handleNameBlur}
733
+ style={{
734
+ overflow: 'hidden',
735
+ resize: 'none',
736
+ padding: '0.25rem',
737
+ }}
738
+ />
739
+ ) : (
740
+ <div
741
+ onClick={handleNameEdit}
742
+ title="Click to edit group name"
743
+ className="access-point-editor__group-container__title"
744
+ >
745
+ <HoverTextArea
746
+ text={groupState.value.id}
747
+ handleMouseOver={handleMouseOverName}
748
+ handleMouseOut={handleMouseOutName}
749
+ className="access-point-editor__group-container__title"
750
+ />
751
+
752
+ {isHoveringName && hoverIcon()}
753
+ </div>
754
+ )}
755
+ <button
756
+ className="access-point-editor__generic-entry__remove-btn--group"
757
+ onClick={() => {
758
+ productEditorState.deleteAccessPointGroup(groupState);
759
+ }}
760
+ tabIndex={-1}
761
+ title="Remove Access Point Group"
762
+ >
763
+ <TimesIcon />
764
+ </button>
485
765
  </div>
486
766
  <div className="access-point-editor__group-container__description-editor">
487
767
  {editingDescription ? (
@@ -491,7 +771,7 @@ const AccessPointGroupSection = observer(
491
771
  value={groupState.value.description ?? ''}
492
772
  onChange={(event) => updateGroupDescription(event.target.value)}
493
773
  placeholder="Provide a description for this Access Point Group"
494
- onBlur={handleBlur}
774
+ onBlur={handleDescriptionBlur}
495
775
  style={{
496
776
  overflow: 'hidden',
497
777
  resize: 'none',
@@ -500,31 +780,46 @@ const AccessPointGroupSection = observer(
500
780
  />
501
781
  ) : (
502
782
  <div
503
- onClick={handleEdit}
504
- title="Click to edit description"
783
+ onClick={handleDescriptionEdit}
784
+ title="Click to edit group description"
505
785
  className="access-point-editor__description-container"
506
786
  >
507
787
  {groupState.value.description ? (
508
- <DescriptionTextArea
509
- accessPoint={groupState.value}
510
- handleMouseOver={handleMouseOver}
511
- handleMouseOut={handleMouseOut}
788
+ <HoverTextArea
789
+ text={groupState.value.description}
790
+ handleMouseOver={handleMouseOverDescription}
791
+ handleMouseOut={handleMouseOutDescription}
512
792
  className="access-point-editor__group-container__description"
513
793
  />
514
794
  ) : (
515
795
  <div
516
796
  className="access-point-editor__group-container__description--warning"
517
- onMouseOver={handleMouseOver}
518
- onMouseOut={handleMouseOut}
797
+ onMouseOver={handleMouseOverDescription}
798
+ onMouseOut={handleMouseOutDescription}
519
799
  >
520
800
  <WarningIcon />
521
- No description provided
801
+ Describe this access point group to clarify what users are
802
+ requesting access to. Entitlements are provisioned at the
803
+ group level.
522
804
  </div>
523
805
  )}
524
- {isHovering && hoverIcon()}
806
+ {isHoveringDescription && hoverIcon()}
525
807
  </div>
526
808
  )}
527
809
  </div>
810
+ <PanelHeader className="panel__header--access-point">
811
+ <div className="panel__header__title">Access Points</div>
812
+ <PanelHeaderActions>
813
+ <PanelHeaderActionItem
814
+ className="panel__header__action"
815
+ onClick={openNewModal}
816
+ disabled={isReadOnly}
817
+ title="Create new access point"
818
+ >
819
+ <PlusIcon />
820
+ </PanelHeaderActionItem>
821
+ </PanelHeaderActions>
822
+ </PanelHeader>
528
823
  {groupState.accessPointStates
529
824
  .filter(filterByType(LakehouseAccessPointState))
530
825
  .map((apState) => (
@@ -534,6 +829,11 @@ const AccessPointGroupSection = observer(
534
829
  accessPointState={apState}
535
830
  />
536
831
  ))}
832
+ {productEditorState.accessPointModal && (
833
+ <NewAccessPointAccessPOint
834
+ dataProductEditorState={productEditorState}
835
+ />
836
+ )}
537
837
  </div>
538
838
  );
539
839
  },
@@ -549,7 +849,7 @@ export const DataProductEditor = observer(() => {
549
849
  .flat();
550
850
  const isReadOnly = dataProductEditorState.isReadOnly;
551
851
  const openNewModal = () => {
552
- dataProductEditorState.setAccessPointModal(true);
852
+ dataProductEditorState.setAccessPointGroupModal(true);
553
853
  };
554
854
  const auth = useAuth();
555
855
  const deployDataProduct = (): void => {
@@ -647,29 +947,34 @@ export const DataProductEditor = observer(() => {
647
947
  <div className="panel" style={{ overflow: 'auto' }}>
648
948
  <PanelHeader>
649
949
  <div className="panel__header__title">
650
- <div className="panel__header__title__label">access points</div>
950
+ <div className="panel__header__title__label">
951
+ access point groups
952
+ </div>
651
953
  </div>
652
954
  <PanelHeaderActions>
653
955
  <PanelHeaderActionItem
654
956
  className="panel__header__action"
655
957
  onClick={openNewModal}
656
958
  disabled={isReadOnly}
657
- title="Create new access point"
959
+ title="Create new access point group"
658
960
  >
659
961
  <PlusIcon />
660
962
  </PanelHeaderActionItem>
661
963
  </PanelHeaderActions>
662
964
  </PanelHeader>
663
965
  <PanelContent>
664
- <div style={{ overflow: 'auto' }}>
966
+ <div
967
+ style={{ overflow: 'auto', margin: '1rem', marginLeft: '1.5rem' }}
968
+ >
665
969
  {dataProductEditorState.accessPointGroupStates.map(
666
- (groupState) => (
667
- <AccessPointGroupSection
668
- key={groupState.value.id}
669
- groupState={groupState}
670
- isReadOnly={isReadOnly}
671
- />
672
- ),
970
+ (groupState) =>
971
+ groupState.accessPointStates.length > 0 && (
972
+ <AccessPointGroupSection
973
+ key={groupState.uuid}
974
+ groupState={groupState}
975
+ isReadOnly={isReadOnly}
976
+ />
977
+ ),
673
978
  )}
674
979
  </div>
675
980
  {!accessPointStates.length && (
@@ -679,10 +984,15 @@ export const DataProductEditor = observer(() => {
679
984
  )}
680
985
  </PanelContent>
681
986
 
682
- {dataProductEditorState.accessPointModal && (
987
+ {/* {dataProductEditorState.accessPointModal && (
683
988
  <NewAccessPointAccessPOint
684
989
  dataProductEditorState={dataProductEditorState}
685
990
  />
991
+ )} */}
992
+ {dataProductEditorState.accessPointGroupModal && (
993
+ <NewAccessPointGroupModal
994
+ dataProductEditorState={dataProductEditorState}
995
+ />
686
996
  )}
687
997
  {dataProductEditorState.deployResponse && (
688
998
  <DataProductDeploymentResponseModal