@finos/legend-application-studio 28.18.41 → 28.18.43

Sign up to get free protection for your applications and to get access to all the features.
@@ -28,11 +28,21 @@ import {
28
28
  CustomSelectorInput,
29
29
  PencilIcon,
30
30
  ErrorIcon,
31
+ clsx,
32
+ PlusIcon,
31
33
  } from '@finos/legend-art';
32
34
  import {
33
35
  DeploymentOwner,
36
+ Profile,
37
+ StereotypeExplicitReference,
38
+ type StereotypeReference,
39
+ type TaggedValue,
34
40
  UserList,
35
41
  generateFunctionPrettyName,
42
+ stub_Profile,
43
+ stub_Stereotype,
44
+ stub_Tag,
45
+ stub_TaggedValue,
36
46
  validate_ServicePattern,
37
47
  } from '@finos/legend-graph';
38
48
  import { observer } from 'mobx-react-lite';
@@ -43,6 +53,7 @@ import {
43
53
  OWNERSHIP_OPTIONS,
44
54
  type HostedServiceOwnerOption,
45
55
  MINIMUM_HOSTED_SERVICE_OWNERS,
56
+ ACTIVATOR_EDITOR_TAB,
46
57
  } from '../../../../stores/editor/editor-state/element-editor-state/function-activator/HostedServiceFunctionActivatorEditorState.js';
47
58
  import {
48
59
  hostedService_setAutoActivateUpdates,
@@ -56,10 +67,30 @@ import {
56
67
  activator_deleteValueFromUserOwnership,
57
68
  activator_addUserOwner,
58
69
  } from '../../../../stores/graph-modifier/DSL_FunctionActivator_GraphModifierHelper.js';
59
- import { useEffect, useMemo, useRef, useState } from 'react';
70
+ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
60
71
  import { LEGEND_STUDIO_TEST_ID } from '../../../../__lib__/LegendStudioTesting.js';
61
- import { debounce } from '@finos/legend-shared';
72
+ import { debounce, prettyCONSTName } from '@finos/legend-shared';
62
73
  import { flowResult } from 'mobx';
74
+ import {
75
+ annotatedElement_addStereotype,
76
+ annotatedElement_addTaggedValue,
77
+ annotatedElement_deleteStereotype,
78
+ annotatedElement_deleteTaggedValue,
79
+ } from '../../../../stores/graph-modifier/DomainGraphModifierHelper.js';
80
+ import {
81
+ CORE_DND_TYPE,
82
+ type ElementDragSource,
83
+ type UMLEditorElementDropTarget,
84
+ } from '../../../../stores/editor/utils/DnDUtils.js';
85
+ import { useDrop } from 'react-dnd';
86
+ import {
87
+ TaggedValueDragPreviewLayer,
88
+ TaggedValueEditor,
89
+ } from '../uml-editor/TaggedValueEditor.js';
90
+ import {
91
+ StereotypeDragPreviewLayer,
92
+ StereotypeSelector,
93
+ } from '../uml-editor/StereotypeSelector.js';
63
94
 
64
95
  type UserOption = { label: string; value: string };
65
96
 
@@ -69,7 +100,102 @@ export const HostedServiceFunctionActivatorEditor = observer(() => {
69
100
  const editorState = editorStore.tabManagerState.getCurrentEditorState(
70
101
  HostedServiceFunctionActivatorEditorState,
71
102
  );
103
+ const activatorElement = editorState.element;
72
104
  const isReadOnly = editorState.isReadOnly;
105
+ const selectedTab = editorState.selectedTab;
106
+ let addButtonTitle = '';
107
+ switch (selectedTab) {
108
+ case ACTIVATOR_EDITOR_TAB.TAGGED_VALUES:
109
+ addButtonTitle = 'Add tagged value';
110
+ break;
111
+ case ACTIVATOR_EDITOR_TAB.STEREOTYPES:
112
+ addButtonTitle = 'Add stereotype';
113
+ break;
114
+ default:
115
+ break;
116
+ }
117
+
118
+ // Tagged Values and Stereotype
119
+ const add = (): void => {
120
+ if (!isReadOnly) {
121
+ if (selectedTab === ACTIVATOR_EDITOR_TAB.TAGGED_VALUES) {
122
+ annotatedElement_addTaggedValue(
123
+ activatorElement,
124
+ stub_TaggedValue(stub_Tag(stub_Profile())),
125
+ );
126
+ } else if (selectedTab === ACTIVATOR_EDITOR_TAB.STEREOTYPES) {
127
+ annotatedElement_addStereotype(
128
+ activatorElement,
129
+ StereotypeExplicitReference.create(stub_Stereotype(stub_Profile())),
130
+ );
131
+ }
132
+ }
133
+ };
134
+ const handleDropTaggedValue = useCallback(
135
+ (item: UMLEditorElementDropTarget): void => {
136
+ if (!isReadOnly && item.data.packageableElement instanceof Profile) {
137
+ annotatedElement_addTaggedValue(
138
+ activatorElement,
139
+ stub_TaggedValue(stub_Tag(item.data.packageableElement)),
140
+ );
141
+ }
142
+ },
143
+ [activatorElement, isReadOnly],
144
+ );
145
+ const [{ isTaggedValueDragOver }, dropTaggedValueRef] = useDrop<
146
+ ElementDragSource,
147
+ void,
148
+ { isTaggedValueDragOver: boolean }
149
+ >(
150
+ () => ({
151
+ accept: [CORE_DND_TYPE.PROJECT_EXPLORER_PROFILE],
152
+ drop: (item) => handleDropTaggedValue(item),
153
+ collect: (monitor) => ({
154
+ isTaggedValueDragOver: monitor.isOver({ shallow: true }),
155
+ }),
156
+ }),
157
+ [handleDropTaggedValue],
158
+ );
159
+ const handleDropStereotype = useCallback(
160
+ (item: UMLEditorElementDropTarget): void => {
161
+ if (!isReadOnly && item.data.packageableElement instanceof Profile) {
162
+ annotatedElement_addStereotype(
163
+ activatorElement,
164
+ StereotypeExplicitReference.create(
165
+ stub_Stereotype(item.data.packageableElement),
166
+ ),
167
+ );
168
+ }
169
+ },
170
+ [activatorElement, isReadOnly],
171
+ );
172
+ const [{ isStereotypeDragOver }, dropStereotypeRef] = useDrop<
173
+ ElementDragSource,
174
+ void,
175
+ { isStereotypeDragOver: boolean }
176
+ >(
177
+ () => ({
178
+ accept: [CORE_DND_TYPE.PROJECT_EXPLORER_PROFILE],
179
+ drop: (item) => handleDropStereotype(item),
180
+ collect: (monitor) => ({
181
+ isStereotypeDragOver: monitor.isOver({ shallow: true }),
182
+ }),
183
+ }),
184
+ [handleDropStereotype],
185
+ );
186
+ const _deleteStereotype =
187
+ (val: StereotypeReference): (() => void) =>
188
+ (): void =>
189
+ annotatedElement_deleteStereotype(activatorElement, val);
190
+ const _deleteTaggedValue =
191
+ (val: TaggedValue): (() => void) =>
192
+ (): void =>
193
+ annotatedElement_deleteTaggedValue(activatorElement, val);
194
+ const changeTab =
195
+ (tab: ACTIVATOR_EDITOR_TAB): (() => void) =>
196
+ (): void =>
197
+ editorState.setSelectedTab(tab);
198
+
73
199
  const activator = editorState.activator;
74
200
  const ownership = activator.ownership;
75
201
  const visitFunction = (): void =>
@@ -269,250 +395,358 @@ export const HostedServiceFunctionActivatorEditor = observer(() => {
269
395
  editorState.deployState.isInProgress,
270
396
  )}
271
397
  />
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"
284
- >
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}
398
+ <div className="panel__header function-editor__tabs__header">
399
+ <div className="function-editor__tabs">
400
+ {Object.values(ACTIVATOR_EDITOR_TAB).map((tab) => (
401
+ <div
402
+ key={tab}
403
+ onClick={changeTab(tab)}
404
+ className={clsx('function-editor__tab', {
405
+ 'function-editor__tab--active': tab === selectedTab,
406
+ })}
293
407
  >
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
408
+ {prettyCONSTName(tab)}
323
409
  </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.
410
+ ))}
411
+ </div>
412
+ {selectedTab !== ACTIVATOR_EDITOR_TAB.DEFINITION && (
413
+ <button
414
+ className="panel__header__action"
415
+ disabled={isReadOnly}
416
+ onClick={add}
417
+ tabIndex={-1}
418
+ title={addButtonTitle}
419
+ >
420
+ <PlusIcon />
421
+ </button>
422
+ )}
423
+ </div>
424
+ <PanelContent>
425
+ {selectedTab === ACTIVATOR_EDITOR_TAB.DEFINITION && (
426
+ <div>
427
+ <div className="hosted-service-function-activator-editor__header">
428
+ <div className="hosted-service-function-activator-editor__header__label">
429
+ Rest Service Activator
430
+ </div>
431
+ <div className="hosted-service-function-activator-editor__header__actions">
432
+ <button
433
+ className="hosted-service-function-activator-editor__header__actions__action hosted-service-function-activator-editor__header__actions__action--primary"
434
+ onClick={validate}
435
+ disabled={editorState.validateState.isInProgress}
436
+ tabIndex={-1}
437
+ title="Click Validate to verify your activator before deployment"
438
+ >
439
+ Validate
440
+ </button>
441
+ <button
442
+ className="hosted-service-function-activator-editor__header__actions__action hosted-service-function-activator-editor__header__actions__action--primary"
443
+ onClick={deploy}
444
+ disabled={editorState.deployState.isInProgress}
445
+ title="Deploy to sandbox"
446
+ tabIndex={-1}
447
+ >
448
+ Deploy to Sandbox
449
+ </button>
450
+ </div>
329
451
  </div>
330
- <div className="service-editor__parameters__list">
331
- {!activator.patternParameters.length && (
332
- <div className="service-editor__parameters__list__empty">
333
- No parameter
452
+ <PanelForm>
453
+ <PanelFormValidatedTextField
454
+ ref={patternRef}
455
+ name="URL Pattern"
456
+ isReadOnly={isReadOnly}
457
+ className="service-editor__pattern__input"
458
+ errorMessageClassName="service-editor__pattern__input"
459
+ prompt={
460
+ <>
461
+ Specifies the URL pattern of the service (e.g. /myService/
462
+ <span className="service-editor__pattern__example__param">{`{param}`}</span>
463
+ )
464
+ </>
465
+ }
466
+ update={(value: string | undefined): void => {
467
+ updatePattern(value ?? '');
468
+ }}
469
+ validate={getValidationMessage}
470
+ value={pattern}
471
+ />
472
+ </PanelForm>
473
+ <PanelForm>
474
+ <div className="panel__content__form__section service-editor__parameters">
475
+ <div className="panel__content__form__section__header__label">
476
+ Parameters
477
+ </div>
478
+ <div className="panel__content__form__section__header__prompt">
479
+ URL parameters (each must be surrounded by curly braces)
480
+ will be passed as arguments for the execution query. Note
481
+ that if the service is configured to use multi-execution,
482
+ one of the URL parameters must be chosen as the execution
483
+ key.
334
484
  </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}
485
+ <div className="service-editor__parameters__list">
486
+ {!activator.patternParameters.length && (
487
+ <div className="service-editor__parameters__list__empty">
488
+ No parameter
341
489
  </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}
490
+ )}
491
+ {Boolean(activator.patternParameters.length) &&
492
+ activator.patternParameters.map((parameter) => (
493
+ <div
494
+ key={parameter}
495
+ className="service-editor__parameter"
349
496
  >
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 />
497
+ <div className="service-editor__parameter__text">
498
+ {parameter}
499
+ </div>
500
+ <div className="service-editor__parameter__actions">
501
+ <button
502
+ className="service-editor__parameter__action"
503
+ disabled={isReadOnly}
504
+ onClick={removePatternParameter(parameter)}
505
+ title="Remove parameter"
506
+ tabIndex={-1}
507
+ >
508
+ <TimesIcon />
509
+ </button>
510
+ </div>
511
+ </div>
512
+ ))}
513
+ </div>
368
514
  </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
- </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>
515
+ </PanelForm>
516
+ <PanelForm>
436
517
  <div className="panel__content__form__section">
437
518
  <div className="panel__content__form__section__header__label">
438
- Ownership
519
+ Function
439
520
  </div>
440
- <div className="panel__content__form__section__header__prompt">
441
- The ownership model you want to use to control your service.
521
+ </div>
522
+ <div className="hosted-service-function-activator-editor__configuration__items">
523
+ <div className="hosted-service-function-activator-editor__configuration__item">
524
+ <div className="btn--sm hosted-service-function-activator-editor__configuration__item__label">
525
+ <PURE_FunctionIcon />
526
+ </div>
527
+ <input
528
+ className="panel__content__form__section__input"
529
+ spellCheck={false}
530
+ disabled={true}
531
+ value={generateFunctionPrettyName(
532
+ activator.function.value,
533
+ {
534
+ fullPath: true,
535
+ spacing: false,
536
+ },
537
+ )}
538
+ />
539
+ <button
540
+ className="btn--dark btn--sm hosted-service-function-activator-editor__configuration__item__btn"
541
+ onClick={visitFunction}
542
+ tabIndex={-1}
543
+ title="See Function"
544
+ >
545
+ <LongArrowRightIcon />
546
+ </button>
442
547
  </div>
443
- <CustomSelectorInput
444
- options={OWNERSHIP_OPTIONS}
445
- onChange={onOwnershipChange}
446
- value={editorState.selectedOwnership}
447
- darkMode={
448
- !applicationStore.layoutService
449
- .TEMPORARY__isLightColorThemeEnabled
450
- }
548
+ </div>
549
+ </PanelForm>
550
+ <PanelForm>
551
+ <div className="panel__content__form__section">
552
+ <div className="panel__content__form__section__header__label">
553
+ Documentation
554
+ </div>
555
+ <div className="panel__content__form__section__header__prompt">{`Provide a brief description of the service's functionalities and usage`}</div>
556
+ <textarea
557
+ className="panel__content__form__section__textarea service-editor__documentation__input"
558
+ spellCheck={false}
559
+ disabled={isReadOnly}
560
+ value={activator.documentation}
561
+ onChange={changeDocumentation}
451
562
  />
452
563
  </div>
453
- {ownership instanceof DeploymentOwner && (
454
- <div className="panel__content__form__section">
455
- <div>
564
+ </PanelForm>
565
+ <PanelForm>
566
+ <PanelFormBooleanField
567
+ isReadOnly={isReadOnly}
568
+ value={activator.autoActivateUpdates}
569
+ name="Auto Activate Updates"
570
+ prompt="Specifies if the new generation should be automatically activated;
571
+ only valid when latest revision is selected upon service
572
+ registration"
573
+ update={toggleAutoActivateUpdates}
574
+ />
575
+ </PanelForm>
576
+ <PanelForm>
577
+ <PanelFormBooleanField
578
+ isReadOnly={isReadOnly}
579
+ value={activator.storeModel}
580
+ name="Store Model"
581
+ prompt="Use Store Model (slower)"
582
+ update={toggleUseStoreModel}
583
+ />
584
+ </PanelForm>
585
+ <PanelForm>
586
+ <PanelFormBooleanField
587
+ isReadOnly={isReadOnly}
588
+ value={activator.generateLineage}
589
+ name="Generate Lineage"
590
+ prompt="Generate Lineage (slower)"
591
+ update={toggleGenerateLineage}
592
+ />
593
+ </PanelForm>
594
+ <PanelForm>
595
+ {
596
+ <div>
597
+ <div className="panel__content__form__section">
456
598
  <div className="panel__content__form__section__header__label">
457
- Deployment Identifier :
599
+ Ownership
600
+ </div>
601
+ <div className="panel__content__form__section__header__prompt">
602
+ The ownership model you want to use to control your
603
+ service.
458
604
  </div>
459
- <input
460
- className="panel__content__form__section__input"
461
- spellCheck={false}
462
- disabled={isReadOnly}
463
- value={ownership.id}
464
- onChange={updateDeploymentIdentifier}
605
+ <CustomSelectorInput
606
+ options={OWNERSHIP_OPTIONS}
607
+ onChange={onOwnershipChange}
608
+ value={editorState.selectedOwnership}
609
+ darkMode={
610
+ !applicationStore.layoutService
611
+ .TEMPORARY__isLightColorThemeEnabled
612
+ }
465
613
  />
466
614
  </div>
467
- </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 :
615
+ {ownership instanceof DeploymentOwner && (
616
+ <div className="panel__content__form__section">
617
+ <div>
618
+ <div className="panel__content__form__section__header__label">
619
+ Deployment Identifier :
620
+ </div>
621
+ <input
622
+ className="panel__content__form__section__input"
623
+ spellCheck={false}
624
+ disabled={isReadOnly}
625
+ value={ownership.id}
626
+ onChange={updateDeploymentIdentifier}
627
+ />
628
+ </div>
474
629
  </div>
475
- <div className="panel__content__form__section__list">
476
- <div
477
- className="panel__content__form__section__list__items"
478
- data-testid={
479
- LEGEND_STUDIO_TEST_ID.PANEL_CONTENT_FORM_SECTION_LIST_ITEMS
480
- }
481
- >
482
- {ownership.users.map((value, idx) => (
630
+ )}
631
+ {ownership instanceof UserList && (
632
+ <div className="panel__content__form__section">
633
+ <div>
634
+ <div className="panel__content__form__section__header__label">
635
+ Users :
636
+ </div>
637
+ <div className="panel__content__form__section__list">
483
638
  <div
484
- key={value}
485
- className={
486
- showOwnerEditInput === idx
487
- ? 'panel__content__form__section__list__new-item'
488
- : 'panel__content__form__section__list__item'
639
+ className="panel__content__form__section__list__items"
640
+ data-testid={
641
+ LEGEND_STUDIO_TEST_ID.PANEL_CONTENT_FORM_SECTION_LIST_ITEMS
489
642
  }
490
643
  >
491
- {showOwnerEditInput === idx ? (
492
- <>
493
- <input
494
- className="panel__content__form__section__input panel__content__form__section__list__new-item__input"
495
- spellCheck={false}
644
+ {ownership.users.map((value, idx) => (
645
+ <div
646
+ key={value}
647
+ className={
648
+ showOwnerEditInput === idx
649
+ ? 'panel__content__form__section__list__new-item'
650
+ : 'panel__content__form__section__list__item'
651
+ }
652
+ >
653
+ {showOwnerEditInput === idx ? (
654
+ <>
655
+ <input
656
+ className="panel__content__form__section__input panel__content__form__section__list__new-item__input"
657
+ spellCheck={false}
658
+ disabled={isReadOnly}
659
+ value={ownerInputValue}
660
+ onChange={changeUserOwnerInputValue}
661
+ />
662
+ <div className="panel__content__form__section__list__new-item__actions">
663
+ <button
664
+ className="panel__content__form__section__list__new-item__add-btn btn btn--dark"
665
+ disabled={
666
+ isReadOnly ||
667
+ ownership.users.includes(
668
+ ownerInputValue,
669
+ )
670
+ }
671
+ onClick={updateUser(idx)}
672
+ tabIndex={-1}
673
+ >
674
+ Save
675
+ </button>
676
+ <button
677
+ className="panel__content__form__section__list__new-item__cancel-btn btn btn--dark"
678
+ disabled={isReadOnly}
679
+ onClick={hideAddOrEditOwnerInput}
680
+ tabIndex={-1}
681
+ >
682
+ Cancel
683
+ </button>
684
+ </div>
685
+ </>
686
+ ) : (
687
+ <>
688
+ <div className="panel__content__form__section__list__item__value">
689
+ {value}
690
+ </div>
691
+ <div className="panel__content__form__section__list__item__actions">
692
+ <button
693
+ className="panel__content__form__section__list__item__edit-btn"
694
+ disabled={isReadOnly}
695
+ onClick={showEditOwnerInput(
696
+ value,
697
+ idx,
698
+ )}
699
+ tabIndex={-1}
700
+ >
701
+ <PencilIcon />
702
+ </button>
703
+ <button
704
+ className="panel__content__form__section__list__item__remove-btn"
705
+ disabled={isReadOnly}
706
+ onClick={deleteUser(idx)}
707
+ tabIndex={-1}
708
+ >
709
+ <TimesIcon />
710
+ </button>
711
+ </div>
712
+ </>
713
+ )}
714
+ </div>
715
+ ))}
716
+ {showOwnerEditInput === true && (
717
+ <div className="panel__content__form__section__list__new-item">
718
+ <CustomSelectorInput
719
+ className="service-editor__owner__selector"
720
+ placeholder="Enter an owner..."
721
+ inputValue={searchText}
722
+ options={userOptions}
723
+ allowCreating={true}
724
+ isLoading={isLoadingUsers}
496
725
  disabled={isReadOnly}
497
- value={ownerInputValue}
498
- onChange={changeUserOwnerInputValue}
726
+ darkMode={
727
+ !applicationStore.layoutService
728
+ .TEMPORARY__isLightColorThemeEnabled
729
+ }
730
+ onInputChange={onSearchTextChange}
731
+ onChange={onUserOptionChange}
732
+ isMulti={true}
499
733
  />
500
734
  <div className="panel__content__form__section__list__new-item__actions">
501
735
  <button
502
- className="panel__content__form__section__list__new-item__add-btn btn btn--dark"
736
+ className="panel__content__form__section__list__new-item__add-btn btn btn--dark service-editor__owner__action"
503
737
  disabled={
504
738
  isReadOnly ||
505
- ownership.users.includes(
506
- ownerInputValue,
739
+ ownerInputs.some((i) =>
740
+ ownership.users.includes(i),
507
741
  )
508
742
  }
509
- onClick={updateUser(idx)}
743
+ onClick={addUser}
510
744
  tabIndex={-1}
511
745
  >
512
746
  Save
513
747
  </button>
514
748
  <button
515
- className="panel__content__form__section__list__new-item__cancel-btn btn btn--dark"
749
+ className="panel__content__form__section__list__new-item__cancel-btn btn btn--dark service-editor__owner__action"
516
750
  disabled={isReadOnly}
517
751
  onClick={hideAddOrEditOwnerInput}
518
752
  tabIndex={-1}
@@ -520,112 +754,87 @@ export const HostedServiceFunctionActivatorEditor = observer(() => {
520
754
  Cancel
521
755
  </button>
522
756
  </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
- </>
757
+ </div>
548
758
  )}
549
759
  </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}
760
+ {ownership.users.length <
761
+ MINIMUM_HOSTED_SERVICE_OWNERS &&
762
+ showOwnerEditInput !== true && (
763
+ <div
764
+ className="service-editor__owner__validation"
765
+ title={`${MINIMUM_HOSTED_SERVICE_OWNERS} owners required`}
580
766
  >
581
- Save
582
- </button>
767
+ <ErrorIcon />
768
+ <div className="service-editor__owner__validation-label">
769
+ Service requires at least{' '}
770
+ {MINIMUM_HOSTED_SERVICE_OWNERS} owners
771
+ </div>
772
+ </div>
773
+ )}
774
+ {showOwnerEditInput !== true && (
775
+ <div className="panel__content__form__section__list__new-item__add">
583
776
  <button
584
- className="panel__content__form__section__list__new-item__cancel-btn btn btn--dark service-editor__owner__action"
777
+ className="panel__content__form__section__list__new-item__add-btn btn btn--dark"
585
778
  disabled={isReadOnly}
586
- onClick={hideAddOrEditOwnerInput}
779
+ onClick={showAddOwnerInput}
587
780
  tabIndex={-1}
781
+ title="Add owner"
588
782
  >
589
- Cancel
783
+ Add Value
590
784
  </button>
591
785
  </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">
611
- <button
612
- className="panel__content__form__section__list__new-item__add-btn btn btn--dark"
613
- disabled={isReadOnly}
614
- onClick={showAddOwnerInput}
615
- tabIndex={-1}
616
- title="Add owner"
617
- >
618
- Add Value
619
- </button>
786
+ )}
620
787
  </div>
621
- )}
788
+ </div>
622
789
  </div>
623
- </div>
790
+ )}
624
791
  </div>
625
- )}
626
- </div>
627
- }
628
- </PanelForm>
792
+ }
793
+ </PanelForm>
794
+ </div>
795
+ )}
796
+ {selectedTab === ACTIVATOR_EDITOR_TAB.TAGGED_VALUES && (
797
+ <div
798
+ ref={dropTaggedValueRef}
799
+ className={clsx('panel__content__lists', {
800
+ 'panel__content__lists--dnd-over':
801
+ isTaggedValueDragOver && !isReadOnly,
802
+ })}
803
+ >
804
+ <TaggedValueDragPreviewLayer />
805
+ {activatorElement.taggedValues.map((taggedValue) => (
806
+ <TaggedValueEditor
807
+ annotatedElement={activatorElement}
808
+ key={taggedValue._UUID}
809
+ taggedValue={taggedValue}
810
+ deleteValue={_deleteTaggedValue(taggedValue)}
811
+ isReadOnly={isReadOnly}
812
+ darkTheme={true}
813
+ />
814
+ ))}
815
+ </div>
816
+ )}
817
+ {selectedTab === ACTIVATOR_EDITOR_TAB.STEREOTYPES && (
818
+ <div
819
+ ref={dropStereotypeRef}
820
+ className={clsx('panel__content__lists', {
821
+ 'panel__content__lists--dnd-over':
822
+ isStereotypeDragOver && !isReadOnly,
823
+ })}
824
+ >
825
+ <StereotypeDragPreviewLayer />
826
+ {activatorElement.stereotypes.map((stereotype) => (
827
+ <StereotypeSelector
828
+ key={stereotype.value._UUID}
829
+ annotatedElement={activatorElement}
830
+ stereotype={stereotype}
831
+ deleteStereotype={_deleteStereotype(stereotype)}
832
+ isReadOnly={isReadOnly}
833
+ darkTheme={true}
834
+ />
835
+ ))}
836
+ </div>
837
+ )}
629
838
  </PanelContent>
630
839
  </Panel>
631
840
  </div>