@finos/legend-application-studio 28.18.42 → 28.18.44

Sign up to get free protection for your applications and to get access to all the features.
Files changed (22) hide show
  1. package/lib/components/editor/editor-group/function-activator/ActivatorFormComponents.d.ts +23 -0
  2. package/lib/components/editor/editor-group/function-activator/ActivatorFormComponents.d.ts.map +1 -0
  3. package/lib/components/editor/editor-group/function-activator/ActivatorFormComponents.js +34 -0
  4. package/lib/components/editor/editor-group/function-activator/ActivatorFormComponents.js.map +1 -0
  5. package/lib/components/editor/editor-group/function-activator/HostedServiceFunctionActivatorEditor.d.ts.map +1 -1
  6. package/lib/components/editor/editor-group/function-activator/HostedServiceFunctionActivatorEditor.js +76 -108
  7. package/lib/components/editor/editor-group/function-activator/HostedServiceFunctionActivatorEditor.js.map +1 -1
  8. package/lib/components/editor/editor-group/function-activator/SnowflakeAppFunctionActivatorEditor.d.ts.map +1 -1
  9. package/lib/components/editor/editor-group/function-activator/SnowflakeAppFunctionActivatorEditor.js +4 -13
  10. package/lib/components/editor/editor-group/function-activator/SnowflakeAppFunctionActivatorEditor.js.map +1 -1
  11. package/lib/index.css +1 -1
  12. package/lib/package.json +1 -1
  13. package/lib/stores/editor/editor-state/element-editor-state/function-activator/HostedServiceFunctionActivatorEditorState.d.ts +8 -3
  14. package/lib/stores/editor/editor-state/element-editor-state/function-activator/HostedServiceFunctionActivatorEditorState.d.ts.map +1 -1
  15. package/lib/stores/editor/editor-state/element-editor-state/function-activator/HostedServiceFunctionActivatorEditorState.js +15 -10
  16. package/lib/stores/editor/editor-state/element-editor-state/function-activator/HostedServiceFunctionActivatorEditorState.js.map +1 -1
  17. package/package.json +6 -6
  18. package/src/components/editor/editor-group/function-activator/ActivatorFormComponents.tsx +97 -0
  19. package/src/components/editor/editor-group/function-activator/HostedServiceFunctionActivatorEditor.tsx +347 -482
  20. package/src/components/editor/editor-group/function-activator/SnowflakeAppFunctionActivatorEditor.tsx +7 -42
  21. package/src/stores/editor/editor-state/element-editor-state/function-activator/HostedServiceFunctionActivatorEditorState.ts +18 -11
  22. package/tsconfig.json +1 -0
@@ -25,14 +25,19 @@ import {
25
25
  PanelFormBooleanField,
26
26
  PanelFormValidatedTextField,
27
27
  TimesIcon,
28
- CustomSelectorInput,
29
- PencilIcon,
30
- ErrorIcon,
28
+ clsx,
29
+ PlusIcon,
31
30
  } from '@finos/legend-art';
32
31
  import {
33
- DeploymentOwner,
34
- UserList,
32
+ Profile,
33
+ StereotypeExplicitReference,
34
+ type StereotypeReference,
35
+ type TaggedValue,
35
36
  generateFunctionPrettyName,
37
+ stub_Profile,
38
+ stub_Stereotype,
39
+ stub_Tag,
40
+ stub_TaggedValue,
36
41
  validate_ServicePattern,
37
42
  } from '@finos/legend-graph';
38
43
  import { observer } from 'mobx-react-lite';
@@ -40,9 +45,7 @@ import { useApplicationStore } from '@finos/legend-application';
40
45
  import { useEditorStore } from '../../EditorStoreProvider.js';
41
46
  import {
42
47
  HostedServiceFunctionActivatorEditorState,
43
- OWNERSHIP_OPTIONS,
44
- type HostedServiceOwnerOption,
45
- MINIMUM_HOSTED_SERVICE_OWNERS,
48
+ ACTIVATOR_EDITOR_TAB,
46
49
  } from '../../../../stores/editor/editor-state/element-editor-state/function-activator/HostedServiceFunctionActivatorEditorState.js';
47
50
  import {
48
51
  hostedService_setAutoActivateUpdates,
@@ -50,18 +53,31 @@ import {
50
53
  hostedService_setPattern,
51
54
  hostedService_removePatternParameter,
52
55
  hostedService_setStoreModel,
53
- hostedService_setGenerateLineage,
54
- activator_setDeploymentOwner,
55
- activator_updateUserOwnership,
56
- activator_deleteValueFromUserOwnership,
57
- activator_addUserOwner,
58
56
  } from '../../../../stores/graph-modifier/DSL_FunctionActivator_GraphModifierHelper.js';
59
- import { useEffect, useMemo, useRef, useState } from 'react';
60
- import { LEGEND_STUDIO_TEST_ID } from '../../../../__lib__/LegendStudioTesting.js';
61
- import { debounce } from '@finos/legend-shared';
57
+ import { useCallback, useEffect, useRef, useState } from 'react';
58
+ import { prettyCONSTName } from '@finos/legend-shared';
62
59
  import { flowResult } from 'mobx';
63
-
64
- type UserOption = { label: string; value: string };
60
+ import { ActivatorOwnershipForm } from './ActivatorFormComponents.js';
61
+ import {
62
+ annotatedElement_addStereotype,
63
+ annotatedElement_addTaggedValue,
64
+ annotatedElement_deleteStereotype,
65
+ annotatedElement_deleteTaggedValue,
66
+ } from '../../../../stores/graph-modifier/DomainGraphModifierHelper.js';
67
+ import {
68
+ CORE_DND_TYPE,
69
+ type ElementDragSource,
70
+ type UMLEditorElementDropTarget,
71
+ } from '../../../../stores/editor/utils/DnDUtils.js';
72
+ import { useDrop } from 'react-dnd';
73
+ import {
74
+ TaggedValueDragPreviewLayer,
75
+ TaggedValueEditor,
76
+ } from '../uml-editor/TaggedValueEditor.js';
77
+ import {
78
+ StereotypeDragPreviewLayer,
79
+ StereotypeSelector,
80
+ } from '../uml-editor/StereotypeSelector.js';
65
81
 
66
82
  export const HostedServiceFunctionActivatorEditor = observer(() => {
67
83
  const editorStore = useEditorStore();
@@ -69,9 +85,103 @@ export const HostedServiceFunctionActivatorEditor = observer(() => {
69
85
  const editorState = editorStore.tabManagerState.getCurrentEditorState(
70
86
  HostedServiceFunctionActivatorEditorState,
71
87
  );
88
+ const activatorElement = editorState.element;
72
89
  const isReadOnly = editorState.isReadOnly;
90
+ const selectedTab = editorState.selectedTab;
91
+ let addButtonTitle = '';
92
+ switch (selectedTab) {
93
+ case ACTIVATOR_EDITOR_TAB.TAGGED_VALUES:
94
+ addButtonTitle = 'Add tagged value';
95
+ break;
96
+ case ACTIVATOR_EDITOR_TAB.STEREOTYPES:
97
+ addButtonTitle = 'Add stereotype';
98
+ break;
99
+ default:
100
+ break;
101
+ }
102
+
103
+ // Tagged Values and Stereotype
104
+ const add = (): void => {
105
+ if (!isReadOnly) {
106
+ if (selectedTab === ACTIVATOR_EDITOR_TAB.TAGGED_VALUES) {
107
+ annotatedElement_addTaggedValue(
108
+ activatorElement,
109
+ stub_TaggedValue(stub_Tag(stub_Profile())),
110
+ );
111
+ } else if (selectedTab === ACTIVATOR_EDITOR_TAB.STEREOTYPES) {
112
+ annotatedElement_addStereotype(
113
+ activatorElement,
114
+ StereotypeExplicitReference.create(stub_Stereotype(stub_Profile())),
115
+ );
116
+ }
117
+ }
118
+ };
119
+ const handleDropTaggedValue = useCallback(
120
+ (item: UMLEditorElementDropTarget): void => {
121
+ if (!isReadOnly && item.data.packageableElement instanceof Profile) {
122
+ annotatedElement_addTaggedValue(
123
+ activatorElement,
124
+ stub_TaggedValue(stub_Tag(item.data.packageableElement)),
125
+ );
126
+ }
127
+ },
128
+ [activatorElement, isReadOnly],
129
+ );
130
+ const [{ isTaggedValueDragOver }, dropTaggedValueRef] = useDrop<
131
+ ElementDragSource,
132
+ void,
133
+ { isTaggedValueDragOver: boolean }
134
+ >(
135
+ () => ({
136
+ accept: [CORE_DND_TYPE.PROJECT_EXPLORER_PROFILE],
137
+ drop: (item) => handleDropTaggedValue(item),
138
+ collect: (monitor) => ({
139
+ isTaggedValueDragOver: monitor.isOver({ shallow: true }),
140
+ }),
141
+ }),
142
+ [handleDropTaggedValue],
143
+ );
144
+ const handleDropStereotype = useCallback(
145
+ (item: UMLEditorElementDropTarget): void => {
146
+ if (!isReadOnly && item.data.packageableElement instanceof Profile) {
147
+ annotatedElement_addStereotype(
148
+ activatorElement,
149
+ StereotypeExplicitReference.create(
150
+ stub_Stereotype(item.data.packageableElement),
151
+ ),
152
+ );
153
+ }
154
+ },
155
+ [activatorElement, isReadOnly],
156
+ );
157
+ const [{ isStereotypeDragOver }, dropStereotypeRef] = useDrop<
158
+ ElementDragSource,
159
+ void,
160
+ { isStereotypeDragOver: boolean }
161
+ >(
162
+ () => ({
163
+ accept: [CORE_DND_TYPE.PROJECT_EXPLORER_PROFILE],
164
+ drop: (item) => handleDropStereotype(item),
165
+ collect: (monitor) => ({
166
+ isStereotypeDragOver: monitor.isOver({ shallow: true }),
167
+ }),
168
+ }),
169
+ [handleDropStereotype],
170
+ );
171
+ const _deleteStereotype =
172
+ (val: StereotypeReference): (() => void) =>
173
+ (): void =>
174
+ annotatedElement_deleteStereotype(activatorElement, val);
175
+ const _deleteTaggedValue =
176
+ (val: TaggedValue): (() => void) =>
177
+ (): void =>
178
+ annotatedElement_deleteTaggedValue(activatorElement, val);
179
+ const changeTab =
180
+ (tab: ACTIVATOR_EDITOR_TAB): (() => void) =>
181
+ (): void =>
182
+ editorState.setSelectedTab(tab);
183
+
73
184
  const activator = editorState.activator;
74
- const ownership = activator.ownership;
75
185
  const visitFunction = (): void =>
76
186
  editorState.editorStore.graphEditorMode.openElement(
77
187
  activator.function.value,
@@ -99,10 +209,6 @@ export const HostedServiceFunctionActivatorEditor = observer(() => {
99
209
  hostedService_setStoreModel(activator, !activator.storeModel);
100
210
  };
101
211
 
102
- const toggleGenerateLineage = (): void => {
103
- hostedService_setGenerateLineage(activator, !activator.generateLineage);
104
- };
105
-
106
212
  const toggleAutoActivateUpdates = (): void => {
107
213
  hostedService_setAutoActivateUpdates(
108
214
  activator,
@@ -117,127 +223,6 @@ export const HostedServiceFunctionActivatorEditor = observer(() => {
117
223
  : undefined;
118
224
  };
119
225
 
120
- //Ownership
121
- const [showOwnerEditInput, setShowOwnerEditInput] = useState<
122
- boolean | number
123
- >(false);
124
- const [ownerInputValue, setOwnerInputValue] = useState<string>('');
125
- const [searchText, setSearchText] = useState('');
126
- const [userOptions, setUserOptions] = useState<UserOption[]>([]);
127
- const [isLoadingUsers, setIsLoadingUsers] = useState<boolean>(false);
128
- const [ownerInputs, setOwnerInputs] = useState<string[]>([]);
129
- const showAddOwnerInput = (): void => setShowOwnerEditInput(true);
130
-
131
- const onOwnershipChange = (
132
- val: HostedServiceOwnerOption | undefined,
133
- ): void => {
134
- if (val) {
135
- editorState.setSelectedOwnership(val);
136
- }
137
- };
138
-
139
- const updateDeploymentIdentifier: React.ChangeEventHandler<
140
- HTMLInputElement
141
- > = (event) => {
142
- if (!isReadOnly && ownership instanceof DeploymentOwner) {
143
- activator_setDeploymentOwner(ownership, event.target.value);
144
- }
145
- };
146
-
147
- const changeUserOwnerInputValue: React.ChangeEventHandler<
148
- HTMLInputElement
149
- > = (event) => setOwnerInputValue(event.target.value);
150
-
151
- const updateUser =
152
- (idx: number): (() => void) =>
153
- (): void => {
154
- if (
155
- ownerInputValue &&
156
- ownership instanceof UserList &&
157
- !ownership.users.includes(ownerInputValue)
158
- ) {
159
- activator_updateUserOwnership(ownership, ownerInputValue, idx);
160
- }
161
- };
162
-
163
- const showEditOwnerInput =
164
- (value: string, idx: number): (() => void) =>
165
- (): void => {
166
- setOwnerInputValue(value);
167
- setShowOwnerEditInput(idx);
168
- };
169
-
170
- const hideAddOrEditOwnerInput = (): void => {
171
- setShowOwnerEditInput(false);
172
- setOwnerInputValue('');
173
- };
174
-
175
- const deleteUser =
176
- (idx: number): (() => void) =>
177
- (): void => {
178
- if (!isReadOnly && ownership instanceof UserList) {
179
- activator_deleteValueFromUserOwnership(ownership, idx);
180
- if (
181
- typeof showOwnerEditInput === 'number' &&
182
- showOwnerEditInput > idx
183
- ) {
184
- setShowOwnerEditInput(showOwnerEditInput - 1);
185
- }
186
- }
187
- };
188
-
189
- const debouncedSearchUsers = useMemo(
190
- () =>
191
- debounce((input: string): void => {
192
- setIsLoadingUsers(true);
193
- flowResult(editorState.searchUsers(input))
194
- .then((users) =>
195
- setUserOptions(
196
- users.map((u) => ({
197
- value: u.userId,
198
- label: u.userId,
199
- })),
200
- ),
201
- )
202
- .then(() => setIsLoadingUsers(false))
203
- .catch(editorState.editorStore.applicationStore.alertUnhandledError);
204
- }, 500),
205
- [editorState],
206
- );
207
-
208
- const onSearchTextChange = (value: string): void => {
209
- if (value !== searchText) {
210
- setSearchText(value);
211
- debouncedSearchUsers.cancel();
212
- if (value.length >= 3) {
213
- debouncedSearchUsers(value);
214
- } else if (value.length === 0) {
215
- setUserOptions([]);
216
- setIsLoadingUsers(false);
217
- }
218
- }
219
- };
220
-
221
- const onUserOptionChange = (options: UserOption[]): void => {
222
- setOwnerInputs(options.map((op) => op.label));
223
- setUserOptions([]);
224
- debouncedSearchUsers.cancel();
225
- setIsLoadingUsers(false);
226
- };
227
-
228
- const addUser = (): void => {
229
- ownerInputs.forEach((value) => {
230
- if (
231
- value &&
232
- ownership instanceof UserList &&
233
- !ownership.users.includes(value)
234
- ) {
235
- activator_addUserOwner(ownership, value);
236
- }
237
- });
238
- hideAddOrEditOwnerInput();
239
- };
240
-
241
226
  //Pattern
242
227
  const patternRef = useRef<HTMLInputElement>(null);
243
228
  const [pattern, setPattern] = useState(activator.pattern);
@@ -269,363 +254,243 @@ export const HostedServiceFunctionActivatorEditor = observer(() => {
269
254
  editorState.deployState.isInProgress,
270
255
  )}
271
256
  />
272
- <PanelContent>
273
- <div className="hosted-service-function-activator-editor__header">
274
- <div className="hosted-service-function-activator-editor__header__label">
275
- Rest Service Activator
276
- </div>
277
- <div className="hosted-service-function-activator-editor__header__actions">
278
- <button
279
- className="hosted-service-function-activator-editor__header__actions__action hosted-service-function-activator-editor__header__actions__action--primary"
280
- onClick={validate}
281
- disabled={editorState.validateState.isInProgress}
282
- tabIndex={-1}
283
- title="Click Validate to verify your activator before deployment"
257
+ <div className="panel__header function-editor__tabs__header">
258
+ <div className="function-editor__tabs">
259
+ {Object.values(ACTIVATOR_EDITOR_TAB).map((tab) => (
260
+ <div
261
+ key={tab}
262
+ onClick={changeTab(tab)}
263
+ className={clsx('function-editor__tab', {
264
+ 'function-editor__tab--active': tab === selectedTab,
265
+ })}
284
266
  >
285
- Validate
286
- </button>
287
- <button
288
- className="hosted-service-function-activator-editor__header__actions__action hosted-service-function-activator-editor__header__actions__action--primary"
289
- onClick={deploy}
290
- disabled={editorState.deployState.isInProgress}
291
- title="Deploy to sandbox"
292
- tabIndex={-1}
293
- >
294
- Deploy to Sandbox
295
- </button>
296
- </div>
297
- </div>
298
- <PanelForm>
299
- <PanelFormValidatedTextField
300
- ref={patternRef}
301
- name="URL Pattern"
302
- isReadOnly={isReadOnly}
303
- className="service-editor__pattern__input"
304
- errorMessageClassName="service-editor__pattern__input"
305
- prompt={
306
- <>
307
- Specifies the URL pattern of the service (e.g. /myService/
308
- <span className="service-editor__pattern__example__param">{`{param}`}</span>
309
- )
310
- </>
311
- }
312
- update={(value: string | undefined): void => {
313
- updatePattern(value ?? '');
314
- }}
315
- validate={getValidationMessage}
316
- value={pattern}
317
- />
318
- </PanelForm>
319
- <PanelForm>
320
- <div className="panel__content__form__section service-editor__parameters">
321
- <div className="panel__content__form__section__header__label">
322
- Parameters
323
- </div>
324
- <div className="panel__content__form__section__header__prompt">
325
- URL parameters (each must be surrounded by curly braces) will be
326
- passed as arguments for the execution query. Note that if the
327
- service is configured to use multi-execution, one of the URL
328
- parameters must be chosen as the execution key.
267
+ {prettyCONSTName(tab)}
329
268
  </div>
330
- <div className="service-editor__parameters__list">
331
- {!activator.patternParameters.length && (
332
- <div className="service-editor__parameters__list__empty">
333
- No parameter
334
- </div>
335
- )}
336
- {Boolean(activator.patternParameters.length) &&
337
- activator.patternParameters.map((parameter) => (
338
- <div key={parameter} className="service-editor__parameter">
339
- <div className="service-editor__parameter__text">
340
- {parameter}
341
- </div>
342
- <div className="service-editor__parameter__actions">
343
- <button
344
- className="service-editor__parameter__action"
345
- disabled={isReadOnly}
346
- onClick={removePatternParameter(parameter)}
347
- title="Remove parameter"
348
- tabIndex={-1}
349
- >
350
- <TimesIcon />
351
- </button>
352
- </div>
353
- </div>
354
- ))}
355
- </div>
356
- </div>
357
- </PanelForm>
358
- <PanelForm>
359
- <div className="panel__content__form__section">
360
- <div className="panel__content__form__section__header__label">
361
- Function
362
- </div>
363
- </div>
364
- <div className="hosted-service-function-activator-editor__configuration__items">
365
- <div className="hosted-service-function-activator-editor__configuration__item">
366
- <div className="btn--sm hosted-service-function-activator-editor__configuration__item__label">
367
- <PURE_FunctionIcon />
269
+ ))}
270
+ </div>
271
+ {selectedTab !== ACTIVATOR_EDITOR_TAB.DEFINITION && (
272
+ <button
273
+ className="panel__header__action"
274
+ disabled={isReadOnly}
275
+ onClick={add}
276
+ tabIndex={-1}
277
+ title={addButtonTitle}
278
+ >
279
+ <PlusIcon />
280
+ </button>
281
+ )}
282
+ </div>
283
+ <PanelContent>
284
+ {selectedTab === ACTIVATOR_EDITOR_TAB.DEFINITION && (
285
+ <div>
286
+ <div className="hosted-service-function-activator-editor__header">
287
+ <div className="hosted-service-function-activator-editor__header__label">
288
+ Rest Service Activator
289
+ </div>
290
+ <div className="hosted-service-function-activator-editor__header__actions">
291
+ <button
292
+ className="hosted-service-function-activator-editor__header__actions__action hosted-service-function-activator-editor__header__actions__action--primary"
293
+ onClick={validate}
294
+ disabled={editorState.validateState.isInProgress}
295
+ tabIndex={-1}
296
+ title="Click Validate to verify your activator before deployment"
297
+ >
298
+ Validate
299
+ </button>
300
+ <button
301
+ className="hosted-service-function-activator-editor__header__actions__action hosted-service-function-activator-editor__header__actions__action--primary"
302
+ onClick={deploy}
303
+ disabled={editorState.deployState.isInProgress}
304
+ title="Deploy to sandbox"
305
+ tabIndex={-1}
306
+ >
307
+ Deploy to Sandbox
308
+ </button>
368
309
  </div>
369
- <input
370
- className="panel__content__form__section__input"
371
- spellCheck={false}
372
- disabled={true}
373
- value={generateFunctionPrettyName(activator.function.value, {
374
- fullPath: true,
375
- spacing: false,
376
- })}
377
- />
378
- <button
379
- className="btn--dark btn--sm hosted-service-function-activator-editor__configuration__item__btn"
380
- onClick={visitFunction}
381
- tabIndex={-1}
382
- title="See Function"
383
- >
384
- <LongArrowRightIcon />
385
- </button>
386
- </div>
387
- </div>
388
- </PanelForm>
389
- <PanelForm>
390
- <div className="panel__content__form__section">
391
- <div className="panel__content__form__section__header__label">
392
- Documentation
393
310
  </div>
394
- <div className="panel__content__form__section__header__prompt">{`Provide a brief description of the service's functionalities and usage`}</div>
395
- <textarea
396
- className="panel__content__form__section__textarea service-editor__documentation__input"
397
- spellCheck={false}
398
- disabled={isReadOnly}
399
- value={activator.documentation}
400
- onChange={changeDocumentation}
401
- />
402
- </div>
403
- </PanelForm>
404
- <PanelForm>
405
- <PanelFormBooleanField
406
- isReadOnly={isReadOnly}
407
- value={activator.autoActivateUpdates}
408
- name="Auto Activate Updates"
409
- prompt="Specifies if the new generation should be automatically activated;
410
- only valid when latest revision is selected upon service
411
- registration"
412
- update={toggleAutoActivateUpdates}
413
- />
414
- </PanelForm>
415
- <PanelForm>
416
- <PanelFormBooleanField
417
- isReadOnly={isReadOnly}
418
- value={activator.storeModel}
419
- name="Store Model"
420
- prompt="Use Store Model (slower)"
421
- update={toggleUseStoreModel}
422
- />
423
- </PanelForm>
424
- <PanelForm>
425
- <PanelFormBooleanField
426
- isReadOnly={isReadOnly}
427
- value={activator.generateLineage}
428
- name="Generate Lineage"
429
- prompt="Generate Lineage (slower)"
430
- update={toggleGenerateLineage}
431
- />
432
- </PanelForm>
433
- <PanelForm>
434
- {
435
- <div>
436
- <div className="panel__content__form__section">
311
+ <PanelForm>
312
+ <PanelFormValidatedTextField
313
+ ref={patternRef}
314
+ name="URL Pattern"
315
+ isReadOnly={isReadOnly}
316
+ className="service-editor__pattern__input"
317
+ errorMessageClassName="service-editor__pattern__input"
318
+ prompt={
319
+ <>
320
+ Specifies the URL pattern of the service (e.g. /myService/
321
+ <span className="service-editor__pattern__example__param">{`{param}`}</span>
322
+ )
323
+ </>
324
+ }
325
+ update={(value: string | undefined): void => {
326
+ updatePattern(value ?? '');
327
+ }}
328
+ validate={getValidationMessage}
329
+ value={pattern}
330
+ />
331
+ </PanelForm>
332
+ <PanelForm>
333
+ <div className="panel__content__form__section service-editor__parameters">
437
334
  <div className="panel__content__form__section__header__label">
438
- Ownership
335
+ Parameters
439
336
  </div>
440
337
  <div className="panel__content__form__section__header__prompt">
441
- The ownership model you want to use to control your service.
442
- </div>
443
- <CustomSelectorInput
444
- options={OWNERSHIP_OPTIONS}
445
- onChange={onOwnershipChange}
446
- value={editorState.selectedOwnership}
447
- darkMode={
448
- !applicationStore.layoutService
449
- .TEMPORARY__isLightColorThemeEnabled
450
- }
451
- />
452
- </div>
453
- {ownership instanceof DeploymentOwner && (
454
- <div className="panel__content__form__section">
455
- <div>
456
- <div className="panel__content__form__section__header__label">
457
- Deployment Identifier :
458
- </div>
459
- <input
460
- className="panel__content__form__section__input"
461
- spellCheck={false}
462
- disabled={isReadOnly}
463
- value={ownership.id}
464
- onChange={updateDeploymentIdentifier}
465
- />
466
- </div>
338
+ URL parameters (each must be surrounded by curly braces)
339
+ will be passed as arguments for the execution query. Note
340
+ that if the service is configured to use multi-execution,
341
+ one of the URL parameters must be chosen as the execution
342
+ key.
467
343
  </div>
468
- )}
469
- {ownership instanceof UserList && (
470
- <div className="panel__content__form__section">
471
- <div>
472
- <div className="panel__content__form__section__header__label">
473
- Users :
344
+ <div className="service-editor__parameters__list">
345
+ {!activator.patternParameters.length && (
346
+ <div className="service-editor__parameters__list__empty">
347
+ No parameter
474
348
  </div>
475
- <div className="panel__content__form__section__list">
349
+ )}
350
+ {Boolean(activator.patternParameters.length) &&
351
+ activator.patternParameters.map((parameter) => (
476
352
  <div
477
- className="panel__content__form__section__list__items"
478
- data-testid={
479
- LEGEND_STUDIO_TEST_ID.PANEL_CONTENT_FORM_SECTION_LIST_ITEMS
480
- }
353
+ key={parameter}
354
+ className="service-editor__parameter"
481
355
  >
482
- {ownership.users.map((value, idx) => (
483
- <div
484
- key={value}
485
- className={
486
- showOwnerEditInput === idx
487
- ? 'panel__content__form__section__list__new-item'
488
- : 'panel__content__form__section__list__item'
489
- }
490
- >
491
- {showOwnerEditInput === idx ? (
492
- <>
493
- <input
494
- className="panel__content__form__section__input panel__content__form__section__list__new-item__input"
495
- spellCheck={false}
496
- disabled={isReadOnly}
497
- value={ownerInputValue}
498
- onChange={changeUserOwnerInputValue}
499
- />
500
- <div className="panel__content__form__section__list__new-item__actions">
501
- <button
502
- className="panel__content__form__section__list__new-item__add-btn btn btn--dark"
503
- disabled={
504
- isReadOnly ||
505
- ownership.users.includes(
506
- ownerInputValue,
507
- )
508
- }
509
- onClick={updateUser(idx)}
510
- tabIndex={-1}
511
- >
512
- Save
513
- </button>
514
- <button
515
- className="panel__content__form__section__list__new-item__cancel-btn btn btn--dark"
516
- disabled={isReadOnly}
517
- onClick={hideAddOrEditOwnerInput}
518
- tabIndex={-1}
519
- >
520
- Cancel
521
- </button>
522
- </div>
523
- </>
524
- ) : (
525
- <>
526
- <div className="panel__content__form__section__list__item__value">
527
- {value}
528
- </div>
529
- <div className="panel__content__form__section__list__item__actions">
530
- <button
531
- className="panel__content__form__section__list__item__edit-btn"
532
- disabled={isReadOnly}
533
- onClick={showEditOwnerInput(value, idx)}
534
- tabIndex={-1}
535
- >
536
- <PencilIcon />
537
- </button>
538
- <button
539
- className="panel__content__form__section__list__item__remove-btn"
540
- disabled={isReadOnly}
541
- onClick={deleteUser(idx)}
542
- tabIndex={-1}
543
- >
544
- <TimesIcon />
545
- </button>
546
- </div>
547
- </>
548
- )}
549
- </div>
550
- ))}
551
- {showOwnerEditInput === true && (
552
- <div className="panel__content__form__section__list__new-item">
553
- <CustomSelectorInput
554
- className="service-editor__owner__selector"
555
- placeholder="Enter an owner..."
556
- inputValue={searchText}
557
- options={userOptions}
558
- allowCreating={true}
559
- isLoading={isLoadingUsers}
560
- disabled={isReadOnly}
561
- darkMode={
562
- !applicationStore.layoutService
563
- .TEMPORARY__isLightColorThemeEnabled
564
- }
565
- onInputChange={onSearchTextChange}
566
- onChange={onUserOptionChange}
567
- isMulti={true}
568
- />
569
- <div className="panel__content__form__section__list__new-item__actions">
570
- <button
571
- className="panel__content__form__section__list__new-item__add-btn btn btn--dark service-editor__owner__action"
572
- disabled={
573
- isReadOnly ||
574
- ownerInputs.some((i) =>
575
- ownership.users.includes(i),
576
- )
577
- }
578
- onClick={addUser}
579
- tabIndex={-1}
580
- >
581
- Save
582
- </button>
583
- <button
584
- className="panel__content__form__section__list__new-item__cancel-btn btn btn--dark service-editor__owner__action"
585
- disabled={isReadOnly}
586
- onClick={hideAddOrEditOwnerInput}
587
- tabIndex={-1}
588
- >
589
- Cancel
590
- </button>
591
- </div>
592
- </div>
593
- )}
594
- </div>
595
- {ownership.users.length <
596
- MINIMUM_HOSTED_SERVICE_OWNERS &&
597
- showOwnerEditInput !== true && (
598
- <div
599
- className="service-editor__owner__validation"
600
- title={`${MINIMUM_HOSTED_SERVICE_OWNERS} owners required`}
601
- >
602
- <ErrorIcon />
603
- <div className="service-editor__owner__validation-label">
604
- Service requires at least{' '}
605
- {MINIMUM_HOSTED_SERVICE_OWNERS} owners
606
- </div>
607
- </div>
608
- )}
609
- {showOwnerEditInput !== true && (
610
- <div className="panel__content__form__section__list__new-item__add">
356
+ <div className="service-editor__parameter__text">
357
+ {parameter}
358
+ </div>
359
+ <div className="service-editor__parameter__actions">
611
360
  <button
612
- className="panel__content__form__section__list__new-item__add-btn btn btn--dark"
361
+ className="service-editor__parameter__action"
613
362
  disabled={isReadOnly}
614
- onClick={showAddOwnerInput}
363
+ onClick={removePatternParameter(parameter)}
364
+ title="Remove parameter"
615
365
  tabIndex={-1}
616
- title="Add owner"
617
366
  >
618
- Add Value
367
+ <TimesIcon />
619
368
  </button>
620
369
  </div>
621
- )}
622
- </div>
370
+ </div>
371
+ ))}
372
+ </div>
373
+ </div>
374
+ </PanelForm>
375
+ <PanelForm>
376
+ <div className="panel__content__form__section">
377
+ <div className="panel__content__form__section__header__label">
378
+ Function
379
+ </div>
380
+ </div>
381
+ <div className="hosted-service-function-activator-editor__configuration__items">
382
+ <div className="hosted-service-function-activator-editor__configuration__item">
383
+ <div className="btn--sm hosted-service-function-activator-editor__configuration__item__label">
384
+ <PURE_FunctionIcon />
623
385
  </div>
386
+ <input
387
+ className="panel__content__form__section__input"
388
+ spellCheck={false}
389
+ disabled={true}
390
+ value={generateFunctionPrettyName(
391
+ activator.function.value,
392
+ {
393
+ fullPath: true,
394
+ spacing: false,
395
+ },
396
+ )}
397
+ />
398
+ <button
399
+ className="btn--dark btn--sm hosted-service-function-activator-editor__configuration__item__btn"
400
+ onClick={visitFunction}
401
+ tabIndex={-1}
402
+ title="See Function"
403
+ >
404
+ <LongArrowRightIcon />
405
+ </button>
624
406
  </div>
625
- )}
626
- </div>
627
- }
628
- </PanelForm>
407
+ </div>
408
+ </PanelForm>
409
+ <PanelForm>
410
+ <div className="panel__content__form__section">
411
+ <div className="panel__content__form__section__header__label">
412
+ Documentation
413
+ </div>
414
+ <div className="panel__content__form__section__header__prompt">{`Provide a brief description of the service's functionalities and usage`}</div>
415
+ <textarea
416
+ className="panel__content__form__section__textarea service-editor__documentation__input"
417
+ spellCheck={false}
418
+ disabled={isReadOnly}
419
+ value={activator.documentation}
420
+ onChange={changeDocumentation}
421
+ />
422
+ </div>
423
+ </PanelForm>
424
+ <PanelForm>
425
+ <PanelFormBooleanField
426
+ isReadOnly={isReadOnly}
427
+ value={activator.autoActivateUpdates}
428
+ name="Auto Activate Updates"
429
+ prompt="Specifies if the new generation should be automatically activated;
430
+ only valid when latest revision is selected upon service
431
+ registration"
432
+ update={toggleAutoActivateUpdates}
433
+ />
434
+ </PanelForm>
435
+ <PanelForm>
436
+ <PanelFormBooleanField
437
+ isReadOnly={isReadOnly}
438
+ value={activator.storeModel}
439
+ name="Store Model"
440
+ prompt="Use Store Model (slower)"
441
+ update={toggleUseStoreModel}
442
+ />
443
+ </PanelForm>
444
+ <PanelForm>
445
+ <ActivatorOwnershipForm
446
+ activator={activator}
447
+ isReadOnly={isReadOnly}
448
+ />
449
+ </PanelForm>
450
+ </div>
451
+ )}
452
+ {selectedTab === ACTIVATOR_EDITOR_TAB.TAGGED_VALUES && (
453
+ <div
454
+ ref={dropTaggedValueRef}
455
+ className={clsx('panel__content__lists', {
456
+ 'panel__content__lists--dnd-over':
457
+ isTaggedValueDragOver && !isReadOnly,
458
+ })}
459
+ >
460
+ <TaggedValueDragPreviewLayer />
461
+ {activatorElement.taggedValues.map((taggedValue) => (
462
+ <TaggedValueEditor
463
+ annotatedElement={activatorElement}
464
+ key={taggedValue._UUID}
465
+ taggedValue={taggedValue}
466
+ deleteValue={_deleteTaggedValue(taggedValue)}
467
+ isReadOnly={isReadOnly}
468
+ darkTheme={true}
469
+ />
470
+ ))}
471
+ </div>
472
+ )}
473
+ {selectedTab === ACTIVATOR_EDITOR_TAB.STEREOTYPES && (
474
+ <div
475
+ ref={dropStereotypeRef}
476
+ className={clsx('panel__content__lists', {
477
+ 'panel__content__lists--dnd-over':
478
+ isStereotypeDragOver && !isReadOnly,
479
+ })}
480
+ >
481
+ <StereotypeDragPreviewLayer />
482
+ {activatorElement.stereotypes.map((stereotype) => (
483
+ <StereotypeSelector
484
+ key={stereotype.value._UUID}
485
+ annotatedElement={activatorElement}
486
+ stereotype={stereotype}
487
+ deleteStereotype={_deleteStereotype(stereotype)}
488
+ isReadOnly={isReadOnly}
489
+ darkTheme={true}
490
+ />
491
+ ))}
492
+ </div>
493
+ )}
629
494
  </PanelContent>
630
495
  </Panel>
631
496
  </div>