@finos/legend-application-studio 28.5.9 → 28.6.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.
@@ -20,6 +20,8 @@ import {
20
20
  MINIMUM_SERVICE_OWNERS,
21
21
  ServiceEditorState,
22
22
  SERVICE_TAB,
23
+ OWNERSHIP_OPTIONS,
24
+ type ServiceOwnerOption,
23
25
  } from '../../../../stores/editor/editor-state/element-editor-state/service/ServiceEditorState.js';
24
26
  import {
25
27
  clsx,
@@ -46,12 +48,20 @@ import {
46
48
  service_setDocumentation,
47
49
  service_setPattern,
48
50
  service_updateOwner,
51
+ service_deploymentOwnership,
52
+ service_addUserOwnership,
53
+ service_updateUserOwnership,
54
+ service_deleteValueFromUserOwnership,
49
55
  } from '../../../../stores/graph-modifier/DSL_Service_GraphModifierHelper.js';
50
56
  import {
51
57
  useApplicationNavigationContext,
52
58
  useApplicationStore,
53
59
  } from '@finos/legend-application';
54
- import { validate_ServicePattern } from '@finos/legend-graph';
60
+ import {
61
+ validate_ServicePattern,
62
+ DeploymentOwnership,
63
+ UserListOwnership,
64
+ } from '@finos/legend-graph';
55
65
  import { LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY } from '../../../../__lib__/LegendStudioApplicationNavigationContext.js';
56
66
  import { ServiceTestableEditor } from './testable/ServiceTestableEditor.js';
57
67
  import { flowResult } from 'mobx';
@@ -66,6 +76,7 @@ const ServiceGeneralEditor = observer(() => {
66
76
  const serviceState =
67
77
  editorStore.tabManagerState.getCurrentEditorState(ServiceEditorState);
68
78
  const service = serviceState.service;
79
+ const ownership = service.ownership;
69
80
  const isReadOnly = serviceState.isReadOnly;
70
81
  // Pattern
71
82
  const patternRef = useRef<HTMLInputElement>(null);
@@ -142,6 +153,61 @@ const ServiceGeneralEditor = observer(() => {
142
153
  }
143
154
  }
144
155
  };
156
+
157
+ const changeUserOwnerInputValue: React.ChangeEventHandler<
158
+ HTMLInputElement
159
+ > = (event) => setOwnerInputValue(event.target.value);
160
+
161
+ const updateDeploymentIdentifier: React.ChangeEventHandler<
162
+ HTMLInputElement
163
+ > = (event) => {
164
+ if (!isReadOnly && ownership instanceof DeploymentOwnership) {
165
+ service_deploymentOwnership(ownership, event.target.value);
166
+ }
167
+ };
168
+
169
+ const addUser = (): void => {
170
+ ownerInputs.forEach((value) => {
171
+ if (
172
+ value &&
173
+ !isReadOnly &&
174
+ ownership instanceof UserListOwnership &&
175
+ !ownership.users.includes(value)
176
+ ) {
177
+ service_addUserOwnership(ownership, value);
178
+ }
179
+ });
180
+ hideAddOrEditOwnerInput();
181
+ };
182
+
183
+ const updateUser =
184
+ (idx: number): (() => void) =>
185
+ (): void => {
186
+ if (
187
+ ownerInputValue &&
188
+ !isReadOnly &&
189
+ ownership instanceof UserListOwnership &&
190
+ !ownership.users.includes(ownerInputValue)
191
+ ) {
192
+ service_updateUserOwnership(ownership, ownerInputValue, idx);
193
+ }
194
+ };
195
+
196
+ const deleteUser =
197
+ (idx: number): (() => void) =>
198
+ (): void => {
199
+ if (!isReadOnly && ownership instanceof UserListOwnership) {
200
+ service_deleteValueFromUserOwnership(ownership, idx);
201
+ // Since we keep track of the value currently being edited using the index, we have to account for it as we delete entry
202
+ if (
203
+ typeof showOwnerEditInput === 'number' &&
204
+ showOwnerEditInput > idx
205
+ ) {
206
+ setShowOwnerEditInput(showOwnerEditInput - 1);
207
+ }
208
+ }
209
+ };
210
+
145
211
  // Other
146
212
  const changeDocumentation: React.ChangeEventHandler<HTMLTextAreaElement> = (
147
213
  event,
@@ -193,6 +259,12 @@ const ServiceGeneralEditor = observer(() => {
193
259
  setIsLoadingUsers(false);
194
260
  };
195
261
 
262
+ const onOwnershipChange = (val: ServiceOwnerOption | undefined): void => {
263
+ if (val) {
264
+ serviceState.setSelectedOwnership(val);
265
+ }
266
+ };
267
+
196
268
  useEffect(() => {
197
269
  patternRef.current?.focus();
198
270
  }, [serviceState]);
@@ -285,157 +357,350 @@ const ServiceGeneralEditor = observer(() => {
285
357
  registration"
286
358
  update={toggleAutoActivateUpdates}
287
359
  />
288
- <div className="panel__content__form__section">
289
- <div className="panel__content__form__section__header__label">
290
- Owners
291
- </div>
292
- <div className="panel__content__form__section__header__prompt">
293
- {`Specifies who can manage and operate the service (requires minimum ${MINIMUM_SERVICE_OWNERS}
294
- owners).`}
295
- </div>
296
- <div className="panel__content__form__section__list">
297
- <div
298
- className="panel__content__form__section__list__items"
299
- data-testid={
300
- LEGEND_STUDIO_TEST_ID.PANEL_CONTENT_FORM_SECTION_LIST_ITEMS
301
- }
302
- >
303
- {owners.map((value, idx) => (
304
- <div
305
- key={value}
306
- className={
307
- showOwnerEditInput === idx
308
- ? 'panel__content__form__section__list__new-item'
309
- : 'panel__content__form__section__list__item'
310
- }
311
- >
312
- {showOwnerEditInput === idx ? (
313
- <>
314
- <input
315
- className="panel__content__form__section__input panel__content__form__section__list__new-item__input"
316
- spellCheck={false}
317
- disabled={isReadOnly}
318
- value={ownerInputValue}
319
- onChange={changeOwnerInputValue}
320
- />
321
- <div className="panel__content__form__section__list__new-item__actions">
322
- <button
323
- className="panel__content__form__section__list__new-item__add-btn btn btn--dark"
324
- disabled={
325
- isReadOnly || owners.includes(ownerInputValue)
360
+ </PanelForm>
361
+ <PanelForm>
362
+ {owners.length === 0 && (
363
+ <div>
364
+ <div className="panel__content__form__section">
365
+ <div className="panel__content__form__section__header__label">
366
+ Ownership
367
+ </div>
368
+ <div className="panel__content__form__section__header__prompt">
369
+ The ownership model you want to use to control your service.
370
+ </div>
371
+ <CustomSelectorInput
372
+ options={OWNERSHIP_OPTIONS}
373
+ onChange={onOwnershipChange}
374
+ value={serviceState.selectedOwnership}
375
+ darkMode={true}
376
+ />
377
+ </div>
378
+ {ownership instanceof DeploymentOwnership && (
379
+ <div className="panel__content__form__section">
380
+ <div>
381
+ <div className="panel__content__form__section__header__label">
382
+ Deployment Identifier :
383
+ </div>
384
+ <input
385
+ className="panel__content__form__section__input"
386
+ spellCheck={false}
387
+ disabled={isReadOnly}
388
+ value={ownership.identifier}
389
+ onChange={updateDeploymentIdentifier}
390
+ />
391
+ </div>
392
+ </div>
393
+ )}
394
+ {ownership instanceof UserListOwnership && (
395
+ <div className="panel__content__form__section">
396
+ <div>
397
+ <div className="panel__content__form__section__header__label">
398
+ Users :
399
+ </div>
400
+ <div className="panel__content__form__section__list">
401
+ <div
402
+ className="panel__content__form__section__list__items"
403
+ data-testid={
404
+ LEGEND_STUDIO_TEST_ID.PANEL_CONTENT_FORM_SECTION_LIST_ITEMS
405
+ }
406
+ >
407
+ {ownership.users.map((value, idx) => (
408
+ <div
409
+ key={value}
410
+ className={
411
+ showOwnerEditInput === idx
412
+ ? 'panel__content__form__section__list__new-item'
413
+ : 'panel__content__form__section__list__item'
326
414
  }
327
- onClick={updateOwner(idx)}
328
- tabIndex={-1}
329
415
  >
330
- Save
331
- </button>
332
- <button
333
- className="panel__content__form__section__list__new-item__cancel-btn btn btn--dark"
334
- disabled={isReadOnly}
335
- onClick={hideAddOrEditOwnerInput}
336
- tabIndex={-1}
416
+ {showOwnerEditInput === idx ? (
417
+ <>
418
+ <input
419
+ className="panel__content__form__section__input panel__content__form__section__list__new-item__input"
420
+ spellCheck={false}
421
+ disabled={isReadOnly}
422
+ value={ownerInputValue}
423
+ onChange={changeUserOwnerInputValue}
424
+ />
425
+ <div className="panel__content__form__section__list__new-item__actions">
426
+ <button
427
+ className="panel__content__form__section__list__new-item__add-btn btn btn--dark"
428
+ disabled={
429
+ isReadOnly ||
430
+ ownership.users.includes(ownerInputValue)
431
+ }
432
+ onClick={updateUser(idx)}
433
+ tabIndex={-1}
434
+ >
435
+ Save
436
+ </button>
437
+ <button
438
+ className="panel__content__form__section__list__new-item__cancel-btn btn btn--dark"
439
+ disabled={isReadOnly}
440
+ onClick={hideAddOrEditOwnerInput}
441
+ tabIndex={-1}
442
+ >
443
+ Cancel
444
+ </button>
445
+ </div>
446
+ </>
447
+ ) : (
448
+ <>
449
+ <div className="panel__content__form__section__list__item__value">
450
+ {value}
451
+ </div>
452
+ <div className="panel__content__form__section__list__item__actions">
453
+ <button
454
+ className="panel__content__form__section__list__item__edit-btn"
455
+ disabled={isReadOnly}
456
+ onClick={showEditOwnerInput(value, idx)}
457
+ tabIndex={-1}
458
+ >
459
+ <PencilIcon />
460
+ </button>
461
+ <button
462
+ className="panel__content__form__section__list__item__remove-btn"
463
+ disabled={isReadOnly}
464
+ onClick={deleteUser(idx)}
465
+ tabIndex={-1}
466
+ >
467
+ <TimesIcon />
468
+ </button>
469
+ </div>
470
+ </>
471
+ )}
472
+ </div>
473
+ ))}
474
+ {showOwnerEditInput === true && (
475
+ <div className="panel__content__form__section__list__new-item">
476
+ <CustomSelectorInput
477
+ className="service-editor__owner__selector"
478
+ placeholder="Enter an owner..."
479
+ spellCheck={false}
480
+ inputValue={searchText}
481
+ options={userOptions}
482
+ allowCreating={true}
483
+ isLoading={isLoadingUsers}
484
+ disabled={isReadOnly}
485
+ darkMode={
486
+ !applicationStore.layoutService
487
+ .TEMPORARY__isLightColorThemeEnabled
488
+ }
489
+ onInputChange={onSearchTextChange}
490
+ onChange={onUserOptionChange}
491
+ isMulti={true}
492
+ />
493
+ <div className="panel__content__form__section__list__new-item__actions">
494
+ <button
495
+ className="panel__content__form__section__list__new-item__add-btn btn btn--dark service-editor__owner__action"
496
+ disabled={
497
+ isReadOnly ||
498
+ ownerInputs.some((i) =>
499
+ ownership.users.includes(i),
500
+ )
501
+ }
502
+ onClick={addUser}
503
+ tabIndex={-1}
504
+ >
505
+ Save
506
+ </button>
507
+ <button
508
+ className="panel__content__form__section__list__new-item__cancel-btn btn btn--dark service-editor__owner__action"
509
+ disabled={isReadOnly}
510
+ onClick={hideAddOrEditOwnerInput}
511
+ tabIndex={-1}
512
+ >
513
+ Cancel
514
+ </button>
515
+ </div>
516
+ </div>
517
+ )}
518
+ </div>
519
+ {ownership.users.length < MINIMUM_SERVICE_OWNERS &&
520
+ showOwnerEditInput !== true && (
521
+ <div
522
+ className="service-editor__owner__validation"
523
+ title={`${MINIMUM_SERVICE_OWNERS} owners required`}
337
524
  >
338
- Cancel
339
- </button>
340
- </div>
341
- </>
342
- ) : (
343
- <>
344
- <div className="panel__content__form__section__list__item__value">
345
- {value}
346
- </div>
347
- <div className="panel__content__form__section__list__item__actions">
525
+ <ErrorIcon />
526
+ <div className="service-editor__owner__validation-label">
527
+ Service requires at least {MINIMUM_SERVICE_OWNERS}{' '}
528
+ owners
529
+ </div>
530
+ </div>
531
+ )}
532
+ {showOwnerEditInput !== true && (
533
+ <div className="panel__content__form__section__list__new-item__add">
348
534
  <button
349
- className="panel__content__form__section__list__item__edit-btn"
350
- disabled={isReadOnly}
351
- onClick={showEditOwnerInput(value, idx)}
352
- tabIndex={-1}
353
- >
354
- <PencilIcon />
355
- </button>
356
- <button
357
- className="panel__content__form__section__list__item__remove-btn"
535
+ className="panel__content__form__section__list__new-item__add-btn btn btn--dark"
358
536
  disabled={isReadOnly}
359
- onClick={deleteOwner(idx)}
537
+ onClick={showAddOwnerInput}
360
538
  tabIndex={-1}
539
+ title="Add owner"
361
540
  >
362
- <TimesIcon />
541
+ Add Value
363
542
  </button>
364
543
  </div>
365
- </>
366
- )}
544
+ )}
545
+ </div>
367
546
  </div>
368
- ))}
369
- {showOwnerEditInput === true && (
370
- <div className="panel__content__form__section__list__new-item">
371
- <CustomSelectorInput
372
- className="service-editor__owner__selector"
373
- placeholder="Enter an owner..."
374
- spellCheck={false}
375
- inputValue={searchText}
376
- options={userOptions}
377
- allowCreating={true}
378
- isLoading={isLoadingUsers}
379
- disabled={isReadOnly}
380
- darkMode={
381
- !applicationStore.layoutService
382
- .TEMPORARY__isLightColorThemeEnabled
547
+ </div>
548
+ )}
549
+ </div>
550
+ )}
551
+ {owners.length > 0 && (
552
+ <div className="panel__content__form__section">
553
+ <div className="panel__content__form__section__header__label">
554
+ Owners (deprecated)
555
+ </div>
556
+ <div className="panel__content__form__section__header__prompt">
557
+ {`Specifies who can manage and operate the service (requires minimum ${MINIMUM_SERVICE_OWNERS}
558
+ owners).`}
559
+ </div>
560
+ <div className="panel__content__form__section__list">
561
+ <div
562
+ className="panel__content__form__section__list__items"
563
+ data-testid={
564
+ LEGEND_STUDIO_TEST_ID.PANEL_CONTENT_FORM_SECTION_LIST_ITEMS
565
+ }
566
+ >
567
+ {owners.map((value, idx) => (
568
+ <div
569
+ key={value}
570
+ className={
571
+ showOwnerEditInput === idx
572
+ ? 'panel__content__form__section__list__new-item'
573
+ : 'panel__content__form__section__list__item'
383
574
  }
384
- onInputChange={onSearchTextChange}
385
- onChange={onUserOptionChange}
386
- isMulti={true}
387
- />
388
- <div className="panel__content__form__section__list__new-item__actions">
389
- <button
390
- className="panel__content__form__section__list__new-item__add-btn btn btn--dark service-editor__owner__action"
391
- disabled={
392
- isReadOnly ||
393
- ownerInputs.some((i) => owners.includes(i))
394
- }
395
- onClick={addOwner}
396
- tabIndex={-1}
397
- >
398
- Save
399
- </button>
400
- <button
401
- className="panel__content__form__section__list__new-item__cancel-btn btn btn--dark service-editor__owner__action"
575
+ >
576
+ {showOwnerEditInput === idx ? (
577
+ <>
578
+ <input
579
+ className="panel__content__form__section__input panel__content__form__section__list__new-item__input"
580
+ spellCheck={false}
581
+ disabled={isReadOnly}
582
+ value={ownerInputValue}
583
+ onChange={changeOwnerInputValue}
584
+ />
585
+ <div className="panel__content__form__section__list__new-item__actions">
586
+ <button
587
+ className="panel__content__form__section__list__new-item__add-btn btn btn--dark"
588
+ disabled={
589
+ isReadOnly || owners.includes(ownerInputValue)
590
+ }
591
+ onClick={updateOwner(idx)}
592
+ tabIndex={-1}
593
+ >
594
+ Save
595
+ </button>
596
+ <button
597
+ className="panel__content__form__section__list__new-item__cancel-btn btn btn--dark"
598
+ disabled={isReadOnly}
599
+ onClick={hideAddOrEditOwnerInput}
600
+ tabIndex={-1}
601
+ >
602
+ Cancel
603
+ </button>
604
+ </div>
605
+ </>
606
+ ) : (
607
+ <>
608
+ <div className="panel__content__form__section__list__item__value">
609
+ {value}
610
+ </div>
611
+ <div className="panel__content__form__section__list__item__actions">
612
+ <button
613
+ className="panel__content__form__section__list__item__edit-btn"
614
+ disabled={isReadOnly}
615
+ onClick={showEditOwnerInput(value, idx)}
616
+ tabIndex={-1}
617
+ >
618
+ <PencilIcon />
619
+ </button>
620
+ <button
621
+ className="panel__content__form__section__list__item__remove-btn"
622
+ disabled={isReadOnly}
623
+ onClick={deleteOwner(idx)}
624
+ tabIndex={-1}
625
+ >
626
+ <TimesIcon />
627
+ </button>
628
+ </div>
629
+ </>
630
+ )}
631
+ </div>
632
+ ))}
633
+ {showOwnerEditInput === true && (
634
+ <div className="panel__content__form__section__list__new-item">
635
+ <CustomSelectorInput
636
+ className="service-editor__owner__selector"
637
+ placeholder="Enter an owner..."
638
+ spellCheck={false}
639
+ inputValue={searchText}
640
+ options={userOptions}
641
+ allowCreating={true}
642
+ isLoading={isLoadingUsers}
402
643
  disabled={isReadOnly}
403
- onClick={hideAddOrEditOwnerInput}
404
- tabIndex={-1}
405
- >
406
- Cancel
407
- </button>
644
+ darkMode={
645
+ !applicationStore.layoutService
646
+ .TEMPORARY__isLightColorThemeEnabled
647
+ }
648
+ onInputChange={onSearchTextChange}
649
+ onChange={onUserOptionChange}
650
+ isMulti={true}
651
+ />
652
+ <div className="panel__content__form__section__list__new-item__actions">
653
+ <button
654
+ className="panel__content__form__section__list__new-item__add-btn btn btn--dark service-editor__owner__action"
655
+ disabled={
656
+ isReadOnly ||
657
+ ownerInputs.some((i) => owners.includes(i))
658
+ }
659
+ onClick={addOwner}
660
+ tabIndex={-1}
661
+ >
662
+ Save
663
+ </button>
664
+ <button
665
+ className="panel__content__form__section__list__new-item__cancel-btn btn btn--dark service-editor__owner__action"
666
+ disabled={isReadOnly}
667
+ onClick={hideAddOrEditOwnerInput}
668
+ tabIndex={-1}
669
+ >
670
+ Cancel
671
+ </button>
672
+ </div>
408
673
  </div>
409
- </div>
410
- )}
411
- </div>
412
- {owners.length < MINIMUM_SERVICE_OWNERS &&
413
- showOwnerEditInput !== true && (
414
- <div
415
- className="service-editor__owner__validation"
416
- title={`${MINIMUM_SERVICE_OWNERS} owners required`}
417
- >
418
- <ErrorIcon />
419
- <div className="service-editor__owner__validation-label">
420
- Service requires at least {MINIMUM_SERVICE_OWNERS} owners
674
+ )}
675
+ </div>
676
+ {owners.length < MINIMUM_SERVICE_OWNERS &&
677
+ showOwnerEditInput !== true && (
678
+ <div
679
+ className="service-editor__owner__validation"
680
+ title={`${MINIMUM_SERVICE_OWNERS} owners required`}
681
+ >
682
+ <ErrorIcon />
683
+ <div className="service-editor__owner__validation-label">
684
+ Service requires at least {MINIMUM_SERVICE_OWNERS} owners
685
+ </div>
421
686
  </div>
687
+ )}
688
+ {showOwnerEditInput !== true && (
689
+ <div className="panel__content__form__section__list__new-item__add">
690
+ <button
691
+ className="panel__content__form__section__list__new-item__add-btn btn btn--dark"
692
+ disabled={isReadOnly}
693
+ onClick={showAddOwnerInput}
694
+ tabIndex={-1}
695
+ title="Add owner"
696
+ >
697
+ Add Value
698
+ </button>
422
699
  </div>
423
700
  )}
424
- {showOwnerEditInput !== true && (
425
- <div className="panel__content__form__section__list__new-item__add">
426
- <button
427
- className="panel__content__form__section__list__new-item__add-btn btn btn--dark"
428
- disabled={isReadOnly}
429
- onClick={showAddOwnerInput}
430
- tabIndex={-1}
431
- title="Add owner"
432
- >
433
- Add Value
434
- </button>
435
- </div>
436
- )}
701
+ </div>
437
702
  </div>
438
- </div>
703
+ )}
439
704
  </PanelForm>
440
705
  </PanelContentLists>
441
706
  );