@yuuvis/client-framework 2.4.1 → 2.4.2

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 (30) hide show
  1. package/fesm2022/yuuvis-client-framework-forms.mjs +124 -109
  2. package/fesm2022/yuuvis-client-framework-forms.mjs.map +1 -1
  3. package/fesm2022/yuuvis-client-framework-list.mjs +38 -6
  4. package/fesm2022/yuuvis-client-framework-list.mjs.map +1 -1
  5. package/fesm2022/yuuvis-client-framework-metadata-form-defaults.mjs +1 -1
  6. package/fesm2022/yuuvis-client-framework-metadata-form-defaults.mjs.map +1 -1
  7. package/fesm2022/yuuvis-client-framework-object-relationship.mjs +63 -47
  8. package/fesm2022/yuuvis-client-framework-object-relationship.mjs.map +1 -1
  9. package/fesm2022/yuuvis-client-framework-renderer.mjs +81 -6
  10. package/fesm2022/yuuvis-client-framework-renderer.mjs.map +1 -1
  11. package/fesm2022/yuuvis-client-framework-tile-list.mjs +137 -177
  12. package/fesm2022/yuuvis-client-framework-tile-list.mjs.map +1 -1
  13. package/forms/lib/elements/data-grid/data-grid/data-grid.component.d.ts +2 -2
  14. package/forms/lib/elements/organization/organization.component.d.ts +6 -11
  15. package/forms/lib/elements/organization-set/organization-set.component.d.ts +3 -5
  16. package/lib/assets/i18n/de.json +1 -0
  17. package/lib/assets/i18n/en.json +1 -0
  18. package/list/index.d.ts +1 -0
  19. package/list/lib/list-tile/list-tile.component.d.ts +14 -0
  20. package/list/lib/list.component.d.ts +1 -0
  21. package/list/lib/list.module.d.ts +2 -1
  22. package/object-relationship/lib/actions/add-relationship/add-relationship.component.d.ts +3 -1
  23. package/object-relationship/lib/object-relationship.component.d.ts +1 -0
  24. package/object-relationship/lib/object-relationship.const.d.ts +4 -0
  25. package/package.json +12 -12
  26. package/renderer/lib/property-renderer/organization.renderer.d.ts +4 -1
  27. package/tile-list/index.d.ts +1 -1
  28. package/tile-list/lib/tile-actions-menu/tile-actions-menu.component.d.ts +11 -0
  29. package/tile-list/lib/tile-list/tile-list.component.d.ts +18 -24
  30. package/tile-list/lib/tile/tile.component.d.ts +0 -22
@@ -32,20 +32,25 @@ import { SnackBarService } from '@yuuvis/client-framework';
32
32
  const ROOT_NODE_SETTINGS = {
33
33
  size: 30,
34
34
  borderWidth: 4,
35
- borderWidthSelected: 6,
35
+ borderWidthSelected: 6
36
36
  };
37
37
  const ROOT_NODE_FONT_SETTINGS = {
38
- size: 14,
38
+ size: 14
39
39
  };
40
40
  const NODE_SETTINGS = {
41
- borderWidthSelected: 2,
41
+ borderWidthSelected: 2
42
42
  };
43
43
  const NODE_FONT_SETTINGS = {
44
- size: 12,
44
+ size: 12
45
45
  };
46
46
  const EDGE_SETTINGS = {};
47
47
  const EDGE_FONT_SETTINGS = {
48
- size: 10,
48
+ size: 10
49
+ };
50
+ // add relationship dialog settings
51
+ const ADD_RELATIONSHIP_DIALOG_OPTIONS = {
52
+ width: '500px',
53
+ maxWidth: '90vw'
49
54
  };
50
55
 
51
56
  class ObjectRelationshipService {
@@ -86,6 +91,7 @@ class ObjectRelationshipService {
86
91
  this.busy.set(true);
87
92
  // search for relations that have this object as source or target
88
93
  const query = `SELECT * FROM ${SystemType.RELATIONSHIP} WHERE ${RelationshipTypeField.SOURCE_ID} = '${originId}' OR ${RelationshipTypeField.TARGET_ID} = '${originId}'`;
94
+ // TODO: What about multi-page results?
89
95
  return this.#search
90
96
  .searchCmis(query)
91
97
  .pipe(switchMap((resRelations) => {
@@ -133,6 +139,7 @@ class ObjectRelationshipService {
133
139
  this.busy.set(false);
134
140
  if (success) {
135
141
  this.#eventService.trigger(YuvEventType.RELATIONSHIP_DELETED, { relationId });
142
+ // TODO: trigger the event will reload the resource anyway (see constructor)
136
143
  if (reloadResource) {
137
144
  this.#relationsResource.reload();
138
145
  }
@@ -172,7 +179,6 @@ class NodeSummaryComponent {
172
179
  #system;
173
180
  #router;
174
181
  openObject(link) {
175
- console.log('Navigating to link:', link);
176
182
  this.#router.navigateByUrl(link);
177
183
  }
178
184
  #propertyToRendererInput(propertyName, object) {
@@ -302,7 +308,7 @@ class RelationshipTargetSearchComponent {
302
308
  useExisting: forwardRef(() => RelationshipTargetSearchComponent),
303
309
  multi: true
304
310
  }
305
- ], ngImport: i0, template: "<mat-form-field>\n <mat-label>{{ 'yuv.object-relationship.add-relationship.target-search.label' | translate }}</mat-label>\n\n <yuv-autocomplete\n [required]=\"true\"\n [busy]=\"busy()\"\n [formControl]=\"acFormControl\"\n [autocompleteValues]=\"autocompleteRes\"\n [forceSelection]=\"true\"\n (autocompleteFnc)=\"autocompleteFn($event)\"\n [multiple]=\"true\"\n [maxItems]=\"1\"\n >\n <!-- template for chip -->\n <ng-template #chipTemplate let-item>\n <div class=\"label\">{{ item.label }}</div>\n <!-- <div class=\"meta\">{{ item.value[metaFieldProperty] }}</div> -->\n </ng-template>\n </yuv-autocomplete>\n</mat-form-field>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: YuvAutocompleteModule }, { kind: "component", type: i1$1.AutocompleteComponent, selector: "yuv-autocomplete", inputs: ["ariaLabel", "busy", "multiple", "distinctValues", "addOnBlur", "minLength", "maxItems", "forceSelection", "autocompleteValues"], outputs: ["autocompleteFnc", "acBlur"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3$1.MatLabel, selector: "mat-label" }] }); }
311
+ ], ngImport: i0, template: "<mat-form-field>\n <mat-label>{{ 'yuv.object-relationship.add-relationship.target-search.label' | translate }}</mat-label>\n\n <yuv-autocomplete\n [required]=\"true\"\n [busy]=\"busy()\"\n [formControl]=\"acFormControl\"\n [autocompleteValues]=\"autocompleteRes\"\n [forceSelection]=\"true\"\n (autocompleteFnc)=\"autocompleteFn($event)\"\n [multiple]=\"true\"\n [maxItems]=\"1\"\n >\n <!-- template for chip -->\n <ng-template #chipTemplate let-item>\n <div class=\"label\">{{ item.label }}</div>\n <!-- <div class=\"meta\">{{ item.value[metaFieldProperty] }}</div> -->\n </ng-template>\n </yuv-autocomplete>\n</mat-form-field>\n", styles: [":host mat-form-field{width:100%}\n"], dependencies: [{ kind: "ngmodule", type: YuvAutocompleteModule }, { kind: "component", type: i1$1.AutocompleteComponent, selector: "yuv-autocomplete", inputs: ["ariaLabel", "busy", "multiple", "distinctValues", "addOnBlur", "minLength", "maxItems", "forceSelection", "autocompleteValues"], outputs: ["autocompleteFnc", "acBlur"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3$1.MatLabel, selector: "mat-label" }] }); }
306
312
  }
307
313
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: RelationshipTargetSearchComponent, decorators: [{
308
314
  type: Component,
@@ -312,7 +318,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImpo
312
318
  useExisting: forwardRef(() => RelationshipTargetSearchComponent),
313
319
  multi: true
314
320
  }
315
- ], template: "<mat-form-field>\n <mat-label>{{ 'yuv.object-relationship.add-relationship.target-search.label' | translate }}</mat-label>\n\n <yuv-autocomplete\n [required]=\"true\"\n [busy]=\"busy()\"\n [formControl]=\"acFormControl\"\n [autocompleteValues]=\"autocompleteRes\"\n [forceSelection]=\"true\"\n (autocompleteFnc)=\"autocompleteFn($event)\"\n [multiple]=\"true\"\n [maxItems]=\"1\"\n >\n <!-- template for chip -->\n <ng-template #chipTemplate let-item>\n <div class=\"label\">{{ item.label }}</div>\n <!-- <div class=\"meta\">{{ item.value[metaFieldProperty] }}</div> -->\n </ng-template>\n </yuv-autocomplete>\n</mat-form-field>\n" }]
321
+ ], template: "<mat-form-field>\n <mat-label>{{ 'yuv.object-relationship.add-relationship.target-search.label' | translate }}</mat-label>\n\n <yuv-autocomplete\n [required]=\"true\"\n [busy]=\"busy()\"\n [formControl]=\"acFormControl\"\n [autocompleteValues]=\"autocompleteRes\"\n [forceSelection]=\"true\"\n (autocompleteFnc)=\"autocompleteFn($event)\"\n [multiple]=\"true\"\n [maxItems]=\"1\"\n >\n <!-- template for chip -->\n <ng-template #chipTemplate let-item>\n <div class=\"label\">{{ item.label }}</div>\n <!-- <div class=\"meta\">{{ item.value[metaFieldProperty] }}</div> -->\n </ng-template>\n </yuv-autocomplete>\n</mat-form-field>\n", styles: [":host mat-form-field{width:100%}\n"] }]
316
322
  }], ctorParameters: () => [] });
317
323
 
318
324
  class AddRelationshipComponent {
@@ -322,6 +328,7 @@ class AddRelationshipComponent {
322
328
  this.#dialogRef = inject((MatDialogRef));
323
329
  this.#dmsService = inject(DmsService);
324
330
  this.#eventService = inject(EventService);
331
+ this.translate = inject(TranslateService);
325
332
  this.object = input(this.#dialogData.object);
326
333
  this.config = input(this.#dialogData.config);
327
334
  this.supportedRelationships = computed(() => {
@@ -360,6 +367,7 @@ class AddRelationshipComponent {
360
367
  targetObject: new FormControl(null, { nonNullable: true, validators: [Validators.required] })
361
368
  }, { validators: this.#relationMatchesTargetObjectValidator });
362
369
  this.busy = signal(false);
370
+ this.error = signal(null);
363
371
  }
364
372
  #system;
365
373
  #dialogData;
@@ -371,10 +379,16 @@ class AddRelationshipComponent {
371
379
  return o1?.id === o2?.id;
372
380
  }
373
381
  submit() {
382
+ this.error.set(null);
383
+ this.busy.set(true);
374
384
  this.#addRelationship(this.form.value.relation.id, this.form.value.targetObject).subscribe({
375
- next: () => this.close(),
385
+ next: () => {
386
+ this.busy.set(false);
387
+ this.close();
388
+ },
376
389
  error: () => {
377
- // TODO: Handle error appropriately
390
+ this.error.set(this.translate.instant('yuv.object-relationship.add-relation.error-message'));
391
+ this.busy.set(false);
378
392
  }
379
393
  });
380
394
  }
@@ -391,7 +405,7 @@ class AddRelationshipComponent {
391
405
  this.#dialogRef.close();
392
406
  }
393
407
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: AddRelationshipComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
394
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.15", type: AddRelationshipComponent, isStandalone: true, selector: "yuv-add-relationship", inputs: { object: { classPropertyName: "object", publicName: "object", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<yuv-dialog class=\"not-separated\" [headertitel]=\"'yuv.object-relationship.add-relationship.headline' | translate\">\n <main [yuvBusyOverlay]=\"busy()\">\n <form [formGroup]=\"form\" (ngSubmit)=\"submit()\">\n @let sn = sourceNode();\n @if (sn) {\n <div class=\"source\">\n {{ sn.title }}\n @if (sn.description) {\n <em>{{ sn.description }}</em>\n }\n </div>\n <div class=\"line\"></div>\n }\n <mat-form-field>\n <mat-label>{{ 'cm.app.cases.action.add-link.search.relation.label' | translate }}</mat-label>\n <mat-select formControlName=\"relation\" [compareWith]=\"optionCompareWith\">\n @for (r of supportedRelationships(); track r.id) {\n <mat-option [value]=\"r\">{{ r.label }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n\n <div class=\"line\"></div>\n\n <yuv-relationship-target-search formControlName=\"targetObject\"\n [config]=\"config()\"\n [availableTargetTypes]=\"availableTargetTypes()\"\n [supportedRelationships]=\"supportedRelationships()\"\n ></yuv-relationship-target-search>\n\n @if (form.hasError('invalidRelationTargetCombination') && (form.touched || form.dirty)) {\n <mat-error class=\"error\">{{ 'yuv.object-relationship.add-relationship.error.invalidRelationTargetCombination' | translate }}</mat-error>\n }\n </form>\n </main>\n\n <footer>\n <button ymtButton=\"secondary\" type=\"button\" (click)=\"close()\" [disabled]=\"busy()\">\n {{ 'yuv.object-relationship.add-relationship.action.cancel' | translate }}\n </button>\n <button ymtButton=\"primary\" type=\"button\" (click)=\"submit()\" [disabled]=\"form.invalid || busy()\">\n {{ 'yuv.object-relationship.add-relationship.action.submit' | translate }}\n </button>\n </footer>\n</yuv-dialog>\n", styles: [":host main form{padding:var(--ymt-spacing-m);display:flex;flex-direction:column;gap:var(--ymt-spacing-xs);align-items:center}:host main form .source{border:2px solid var(--ymt-outline);border-radius:var(--ymt-corner-s);padding:var(--ymt-spacing-xs);display:flex;flex-direction:column}:host main form .source em{font-style:normal;font:var(--ymt-font-body-subtle);color:var(--ymt-text-color-subtle)}:host main form .line{width:2px;background-color:var(--ymt-outline);min-height:2em;position:relative}:host main form .line:before{content:\"\";position:absolute;transform:rotate(135deg);width:8px;inset-block-end:0;translate:-3px 2px;height:8px;border:4px solid transparent;border-block-start-color:var(--ymt-outline);border-inline-end-color:var(--ymt-outline)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }, { kind: "component", type: DialogComponent, selector: "yuv-dialog", inputs: ["headertitel"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i3$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i3$1.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "component", type: i4.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i4.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "directive", type: YmtButtonDirective, selector: "button[ymtButton], a[ymtButton]", inputs: ["ymtButton", "disabled", "aria-disabled", "disableRipple", "disabledInteractive", "button-size"] }, { kind: "component", type: RelationshipTargetSearchComponent, selector: "yuv-relationship-target-search", inputs: ["supportedRelationships", "availableTargetTypes", "config"] }, { kind: "directive", type: BusyOverlayDirective, selector: "[yuvBusyOverlay]", inputs: ["yuvBusyOverlay", "yuvBusyOverlayConfig"] }] }); }
408
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.15", type: AddRelationshipComponent, isStandalone: true, selector: "yuv-add-relationship", inputs: { object: { classPropertyName: "object", publicName: "object", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<yuv-dialog class=\"not-separated\" [headertitel]=\"'yuv.object-relationship.add-relationship.headline' | translate\">\n <main [yuvBusyOverlay]=\"busy()\">\n <form [formGroup]=\"form\" (ngSubmit)=\"submit()\">\n @let sn = sourceNode();\n @if (sn) {\n <div class=\"source\">\n {{ sn.title }}\n @if (sn.description) {\n <em>{{ sn.description }}</em>\n }\n </div>\n <div class=\"line\"></div>\n }\n <mat-form-field>\n <mat-label>{{ 'cm.app.cases.action.add-link.search.relation.label' | translate }}</mat-label>\n <mat-select formControlName=\"relation\" [compareWith]=\"optionCompareWith\">\n @for (r of supportedRelationships(); track r.id) {\n <mat-option [value]=\"r\">{{ r.label }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n\n <div class=\"line\"></div>\n\n <yuv-relationship-target-search formControlName=\"targetObject\"\n [config]=\"config()\"\n [availableTargetTypes]=\"availableTargetTypes()\"\n [supportedRelationships]=\"supportedRelationships()\"\n ></yuv-relationship-target-search>\n\n @if (form.hasError('invalidRelationTargetCombination') && (form.touched || form.dirty)) {\n <mat-error class=\"error\">{{ 'yuv.object-relationship.add-relationship.error.invalidRelationTargetCombination' | translate }}</mat-error>\n }\n \n @if (error()) {\n <div class=\"error\">{{ error() }}</div>\n }\n </form>\n </main>\n\n <footer>\n <button ymtButton=\"secondary\" type=\"button\" (click)=\"close()\" [disabled]=\"busy()\">\n {{ 'yuv.object-relationship.add-relationship.action.cancel' | translate }}\n </button>\n <button ymtButton=\"primary\" type=\"button\" (click)=\"submit()\" [disabled]=\"form.invalid || busy()\">\n {{ 'yuv.object-relationship.add-relationship.action.submit' | translate }}\n </button>\n </footer>\n</yuv-dialog>\n", styles: [":host .error{background-color:var(--ymt-danger-container);color:var(--ymt-on-danger-container);width:100%;padding:var(--ymt-spacing-m);border-radius:var(--ymt-spacing-xs)}:host main form{padding:var(--ymt-spacing-m);display:flex;flex-direction:column;gap:var(--ymt-spacing-xs);align-items:center}:host main form .source{border:2px solid var(--ymt-outline);border-radius:var(--ymt-corner-s);padding:var(--ymt-spacing-xs);display:flex;flex-direction:column}:host main form .source em{font-style:normal;font:var(--ymt-font-body-subtle);color:var(--ymt-text-color-subtle)}:host main form yuv-relationship-target-search,:host main form mat-form-field{width:100%}:host main form .line{width:2px;background-color:var(--ymt-outline);min-height:2em;position:relative}:host main form .line:before{content:\"\";position:absolute;transform:rotate(135deg);width:8px;inset-block-end:0;translate:-3px 2px;height:8px;border:4px solid transparent;border-block-start-color:var(--ymt-outline);border-inline-end-color:var(--ymt-outline)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }, { kind: "component", type: DialogComponent, selector: "yuv-dialog", inputs: ["headertitel"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i3$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i3$1.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "component", type: i4.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i4.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "directive", type: YmtButtonDirective, selector: "button[ymtButton], a[ymtButton]", inputs: ["ymtButton", "disabled", "aria-disabled", "disableRipple", "disabledInteractive", "button-size"] }, { kind: "component", type: RelationshipTargetSearchComponent, selector: "yuv-relationship-target-search", inputs: ["supportedRelationships", "availableTargetTypes", "config"] }, { kind: "directive", type: BusyOverlayDirective, selector: "[yuvBusyOverlay]", inputs: ["yuvBusyOverlay", "yuvBusyOverlayConfig"] }] }); }
395
409
  }
396
410
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: AddRelationshipComponent, decorators: [{
397
411
  type: Component,
@@ -406,7 +420,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImpo
406
420
  YmtButtonDirective,
407
421
  RelationshipTargetSearchComponent,
408
422
  BusyOverlayDirective
409
- ], template: "<yuv-dialog class=\"not-separated\" [headertitel]=\"'yuv.object-relationship.add-relationship.headline' | translate\">\n <main [yuvBusyOverlay]=\"busy()\">\n <form [formGroup]=\"form\" (ngSubmit)=\"submit()\">\n @let sn = sourceNode();\n @if (sn) {\n <div class=\"source\">\n {{ sn.title }}\n @if (sn.description) {\n <em>{{ sn.description }}</em>\n }\n </div>\n <div class=\"line\"></div>\n }\n <mat-form-field>\n <mat-label>{{ 'cm.app.cases.action.add-link.search.relation.label' | translate }}</mat-label>\n <mat-select formControlName=\"relation\" [compareWith]=\"optionCompareWith\">\n @for (r of supportedRelationships(); track r.id) {\n <mat-option [value]=\"r\">{{ r.label }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n\n <div class=\"line\"></div>\n\n <yuv-relationship-target-search formControlName=\"targetObject\"\n [config]=\"config()\"\n [availableTargetTypes]=\"availableTargetTypes()\"\n [supportedRelationships]=\"supportedRelationships()\"\n ></yuv-relationship-target-search>\n\n @if (form.hasError('invalidRelationTargetCombination') && (form.touched || form.dirty)) {\n <mat-error class=\"error\">{{ 'yuv.object-relationship.add-relationship.error.invalidRelationTargetCombination' | translate }}</mat-error>\n }\n </form>\n </main>\n\n <footer>\n <button ymtButton=\"secondary\" type=\"button\" (click)=\"close()\" [disabled]=\"busy()\">\n {{ 'yuv.object-relationship.add-relationship.action.cancel' | translate }}\n </button>\n <button ymtButton=\"primary\" type=\"button\" (click)=\"submit()\" [disabled]=\"form.invalid || busy()\">\n {{ 'yuv.object-relationship.add-relationship.action.submit' | translate }}\n </button>\n </footer>\n</yuv-dialog>\n", styles: [":host main form{padding:var(--ymt-spacing-m);display:flex;flex-direction:column;gap:var(--ymt-spacing-xs);align-items:center}:host main form .source{border:2px solid var(--ymt-outline);border-radius:var(--ymt-corner-s);padding:var(--ymt-spacing-xs);display:flex;flex-direction:column}:host main form .source em{font-style:normal;font:var(--ymt-font-body-subtle);color:var(--ymt-text-color-subtle)}:host main form .line{width:2px;background-color:var(--ymt-outline);min-height:2em;position:relative}:host main form .line:before{content:\"\";position:absolute;transform:rotate(135deg);width:8px;inset-block-end:0;translate:-3px 2px;height:8px;border:4px solid transparent;border-block-start-color:var(--ymt-outline);border-inline-end-color:var(--ymt-outline)}\n"] }]
423
+ ], template: "<yuv-dialog class=\"not-separated\" [headertitel]=\"'yuv.object-relationship.add-relationship.headline' | translate\">\n <main [yuvBusyOverlay]=\"busy()\">\n <form [formGroup]=\"form\" (ngSubmit)=\"submit()\">\n @let sn = sourceNode();\n @if (sn) {\n <div class=\"source\">\n {{ sn.title }}\n @if (sn.description) {\n <em>{{ sn.description }}</em>\n }\n </div>\n <div class=\"line\"></div>\n }\n <mat-form-field>\n <mat-label>{{ 'cm.app.cases.action.add-link.search.relation.label' | translate }}</mat-label>\n <mat-select formControlName=\"relation\" [compareWith]=\"optionCompareWith\">\n @for (r of supportedRelationships(); track r.id) {\n <mat-option [value]=\"r\">{{ r.label }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n\n <div class=\"line\"></div>\n\n <yuv-relationship-target-search formControlName=\"targetObject\"\n [config]=\"config()\"\n [availableTargetTypes]=\"availableTargetTypes()\"\n [supportedRelationships]=\"supportedRelationships()\"\n ></yuv-relationship-target-search>\n\n @if (form.hasError('invalidRelationTargetCombination') && (form.touched || form.dirty)) {\n <mat-error class=\"error\">{{ 'yuv.object-relationship.add-relationship.error.invalidRelationTargetCombination' | translate }}</mat-error>\n }\n \n @if (error()) {\n <div class=\"error\">{{ error() }}</div>\n }\n </form>\n </main>\n\n <footer>\n <button ymtButton=\"secondary\" type=\"button\" (click)=\"close()\" [disabled]=\"busy()\">\n {{ 'yuv.object-relationship.add-relationship.action.cancel' | translate }}\n </button>\n <button ymtButton=\"primary\" type=\"button\" (click)=\"submit()\" [disabled]=\"form.invalid || busy()\">\n {{ 'yuv.object-relationship.add-relationship.action.submit' | translate }}\n </button>\n </footer>\n</yuv-dialog>\n", styles: [":host .error{background-color:var(--ymt-danger-container);color:var(--ymt-on-danger-container);width:100%;padding:var(--ymt-spacing-m);border-radius:var(--ymt-spacing-xs)}:host main form{padding:var(--ymt-spacing-m);display:flex;flex-direction:column;gap:var(--ymt-spacing-xs);align-items:center}:host main form .source{border:2px solid var(--ymt-outline);border-radius:var(--ymt-corner-s);padding:var(--ymt-spacing-xs);display:flex;flex-direction:column}:host main form .source em{font-style:normal;font:var(--ymt-font-body-subtle);color:var(--ymt-text-color-subtle)}:host main form yuv-relationship-target-search,:host main form mat-form-field{width:100%}:host main form .line{width:2px;background-color:var(--ymt-outline);min-height:2em;position:relative}:host main form .line:before{content:\"\";position:absolute;transform:rotate(135deg);width:8px;inset-block-end:0;translate:-3px 2px;height:8px;border:4px solid transparent;border-block-start-color:var(--ymt-outline);border-inline-end-color:var(--ymt-outline)}\n"] }]
410
424
  }] });
411
425
 
412
426
  class ObjectRelationshipGraphComponent {
@@ -437,7 +451,6 @@ class ObjectRelationshipGraphComponent {
437
451
  const rel = this.#relations();
438
452
  if (!rel)
439
453
  return;
440
- // this.#outerObjectNodeIds = rel.objects.items.map((i) => i.fields.get(BaseObjectTypeField.OBJECT_ID) as string);
441
454
  this.#_updateGraph(rel.originId, rel.relations, rel.objects);
442
455
  });
443
456
  /**
@@ -496,6 +509,7 @@ class ObjectRelationshipGraphComponent {
496
509
  addRelationship() {
497
510
  this.#dialog
498
511
  .open(AddRelationshipComponent, {
512
+ ...ADD_RELATIONSHIP_DIALOG_OPTIONS,
499
513
  data: {
500
514
  object: this.selectedObject(),
501
515
  config: this.config()
@@ -509,7 +523,21 @@ class ObjectRelationshipGraphComponent {
509
523
  deleteRelationship() {
510
524
  this.#objectRelationshipService.deleteRelationship(this.selectedRelation().id, false).subscribe((success) => {
511
525
  if (success) {
526
+ const deletedEdge = this.#edges.get(this.selectedRelation().id);
527
+ if (!deletedEdge)
528
+ return;
529
+ const sourceNodeId = deletedEdge.from;
530
+ const targetNodeId = deletedEdge.to;
512
531
  this.#edges.remove(this.selectedRelation().id);
532
+ // check if the source/target node of the deleted edge has other connections to another node in the current graph
533
+ const otherEdgesForSource = this.#edges.get().filter((edge) => edge.from === sourceNodeId || edge.to === sourceNodeId);
534
+ const otherEdgesForTarget = this.#edges.get().filter((edge) => edge.from === targetNodeId || edge.to === targetNodeId);
535
+ if (sourceNodeId && otherEdgesForSource.length === 0) {
536
+ this.#nodes.remove(sourceNodeId);
537
+ }
538
+ if (targetNodeId && otherEdgesForTarget.length === 0) {
539
+ this.#nodes.remove(targetNodeId);
540
+ }
513
541
  }
514
542
  else {
515
543
  this.#snack.danger(this.translate.instant('yuv.object-relationship.delete-relation.error-message'));
@@ -550,7 +578,7 @@ class ObjectRelationshipGraphComponent {
550
578
  const incoming = relations.items.filter((item) => item.fields.get(RelationshipTypeField.TARGET_ID) === originId);
551
579
  const outgoing = relations.items.filter((item) => item.fields.get(RelationshipTypeField.SOURCE_ID) === originId);
552
580
  const rootNode = this.#toNode(originId);
553
- const _nodes = originId === this.#relations()?.originId
581
+ const _nodes = originId === this.#relations()?.originId && this.#nodes.get([originId]).length === 0
554
582
  ? [
555
583
  {
556
584
  ...rootNode,
@@ -567,7 +595,7 @@ class ObjectRelationshipGraphComponent {
567
595
  outgoing.forEach((item) => {
568
596
  const relatedObjectId = item.fields.get(RelationshipTypeField.TARGET_ID);
569
597
  const n = this.#toNode(relatedObjectId);
570
- const e = this.#toEdge(item, originId, relatedObjectId, 'from');
598
+ const e = this.#toEdge(item, originId, relatedObjectId, 'to');
571
599
  if (n) {
572
600
  // check if the node is already in the rendered graph
573
601
  const nodeExists = _nodes.some((node) => node.id === n.id) || this.#nodes.get([n.id]).length > 0;
@@ -582,7 +610,7 @@ class ObjectRelationshipGraphComponent {
582
610
  incoming.forEach((item) => {
583
611
  const relatedObjectId = item.fields.get(RelationshipTypeField.SOURCE_ID);
584
612
  const n = this.#toNode(relatedObjectId);
585
- const e = this.#toEdge(item, relatedObjectId, originId, 'to');
613
+ const e = this.#toEdge(item, relatedObjectId, originId, 'from');
586
614
  if (n) {
587
615
  // check if the node is already in the rendered graph
588
616
  const nodeExists = _nodes.some((node) => node.id === n.id) || this.#nodes.get([n.id]).length > 0;
@@ -716,7 +744,7 @@ class ObjectRelationshipGraphComponent {
716
744
  forceAtlas2Based: {
717
745
  // gravitationalConstant: -50,
718
746
  // centralGravity: 0.01,
719
- springLength: 200,
747
+ springLength: 200
720
748
  }
721
749
  },
722
750
  nodes: {
@@ -729,36 +757,20 @@ class ObjectRelationshipGraphComponent {
729
757
  nodes: this.#nodes,
730
758
  edges: this.#edges
731
759
  }, options);
732
- this.#network.on('selectNode', (params) => {
733
- const selectedNodeId = params.nodes[0];
734
- this.selectedObject.set(this.#objectQA[selectedNodeId]);
735
- });
736
- this.#network.on('deselectNode', (params) => {
737
- this.selectedObject.set(null);
738
- });
739
- this.#network.on('dragEnd', (params) => {
740
- const selectedNodeId = params.nodes[0];
741
- this.selectedObject.set(this.#objectQA[selectedNodeId]);
742
- });
743
- this.#network.on('selectEdge', (params) => {
744
- const selectedEdgeId = params.edges[0];
745
- const nodesSelected = params.nodes.length > 0;
746
- this.selectedRelation.set(params.edges.length === 1 && !nodesSelected ? this.#relationQA[selectedEdgeId] : null);
747
- });
748
- this.#network.on('deselectEdge', (params) => {
749
- const selectedEdgeId = params.edges[0];
750
- const nodesSelected = params.nodes.length > 0;
751
- this.selectedRelation.set(params.edges.length === 1 && !nodesSelected ? this.#relationQA[selectedEdgeId] : null);
752
- });
753
- this.#network.on('click', (params) => {
754
- const selectedNodeId = params.nodes[0];
755
- this.selectedObject.set(this.#objectQA[selectedNodeId]);
756
- });
760
+ this.#network.on('selectNode', (params) => this.#setSelection(params));
761
+ this.#network.on('deselectNode', (params) => this.#setSelection(params));
762
+ this.#network.on('dragEnd', (params) => this.#setSelection(params));
763
+ this.#network.on('selectEdge', (params) => this.#setSelection(params));
764
+ this.#network.on('deselectEdge', (params) => this.#setSelection(params));
765
+ this.#network.on('click', (params) => this.#setSelection(params));
757
766
  this.#network.on('doubleClick', (params) => {
758
- const selectedNodeId = params.nodes[0];
759
- this.#expand(selectedNodeId);
767
+ this.#expand(params.nodes[0]);
760
768
  });
761
769
  }
770
+ #setSelection(params) {
771
+ this.selectedObject.set(params.nodes.length === 1 ? this.#objectQA[params.nodes[0]] : null);
772
+ this.selectedRelation.set(params.edges.length === 1 && params.nodes.length === 0 ? this.#relationQA[params.edges[0]] : null);
773
+ }
762
774
  ngOnDestroy() {
763
775
  if (this.#network) {
764
776
  this.#network.destroy();
@@ -921,6 +933,7 @@ class ObjectRelationshipComponent {
921
933
  const obj = this.originObject();
922
934
  return obj ? this.#system.getSupportedRelationships(obj) : [];
923
935
  });
936
+ this.busy = this.#objectRelationshipService.busy;
924
937
  this.#relations = this.#objectRelationshipService.relations;
925
938
  this.#relationsEffect = effect(() => {
926
939
  const rel = this.#relations();
@@ -930,6 +943,7 @@ class ObjectRelationshipComponent {
930
943
  }
931
944
  const originId = rel.originId;
932
945
  const originItem = rel.objects?.items.find((item) => item.fields.get(BaseObjectTypeField.OBJECT_ID) === originId);
946
+ // TODO: use linked signal instead
933
947
  this.originObject.set(originItem ? new DmsObject(originItem) : null);
934
948
  });
935
949
  this.relationActions = input(null);
@@ -947,6 +961,7 @@ class ObjectRelationshipComponent {
947
961
  }
948
962
  addRelationship() {
949
963
  this.#dialog.open(AddRelationshipComponent, {
964
+ ...ADD_RELATIONSHIP_DIALOG_OPTIONS,
950
965
  data: {
951
966
  object: this.originObject(),
952
967
  config: this.config()
@@ -954,7 +969,7 @@ class ObjectRelationshipComponent {
954
969
  });
955
970
  }
956
971
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: ObjectRelationshipComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
957
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.15", type: ObjectRelationshipComponent, isStandalone: true, selector: "yuv-object-relationship", inputs: { objectId: { classPropertyName: "objectId", publicName: "objectId", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null }, relationActions: { classPropertyName: "relationActions", publicName: "relationActions", isSignal: true, isRequired: false, transformFunction: null } }, providers: [ObjectRelationshipService], ngImport: i0, template: "<ymt-pane [plain]=\"true\" [topBarActions]=\"topBarActions\">\n <ymt-pane-body>\n @if (empty()) {\n <div class=\"no-relations\">\n <mat-icon>link_off</mat-icon>\n <p>{{ 'yuv.object-relationship.no-relations' | translate }}</p>\n </div>\n } @else {\n @switch (mode()) {\n @case ('graph') {\n <yuv-object-relationship-graph [config]=\"config()\"></yuv-object-relationship-graph>\n }\n @case ('list') {\n <yuv-object-relationship-list [config]=\"config()\"> </yuv-object-relationship-list>\n }\n }\n }\n </ymt-pane-body>\n</ymt-pane>\n\n<ng-template #topBarActions>\n @if (supportedRelationships().length > 0) {\n <button ymt-icon-button icon-button-size=\"small\" [matTooltip]=\"'yuv.object-relationship.add.tooltip' | translate\" (click)=\"addRelationship()\">\n <mat-icon>add</mat-icon>\n </button>\n }\n <button\n ymt-icon-button\n icon-button-size=\"small\"\n [matTooltip]=\"mode() === 'list' ? ('yuv.object-relationship.mode.graph.tooltip' | translate) : ('yuv.object-relationship.mode.list.tooltip' | translate)\"\n (click)=\"toggleMode()\"\n >\n <mat-icon>{{ mode() === 'list' ? 'graph_3' : 'list' }}</mat-icon>\n </button>\n</ng-template>\n", styles: [":host{display:block;position:relative;height:100%;background-color:var(--ymt-surface)}:host .toggle{position:absolute;inset-block-start:var(--ymt-spacing-s);inset-inline-end:var(--ymt-spacing-s);z-index:10;background-color:var(--ymt-surface);padding:var(--ymt-spacing-xs);border-radius:var(--ymt-corner-full)}:host yuv-object-relationship-list,:host yuv-object-relationship-graph{height:100%}:host .no-relations{height:100%;display:flex;flex-direction:column;justify-content:center;align-items:center;text-align:center;padding:var(--ymt-spacing-l);gap:var(--ymt-spacing-m);overflow:hidden}:host .no-relations mat-icon{scale:4;color:var(--ymt-text-color-subtle);opacity:.5;transform:translateY(-.5em)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i2.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: MatButtonToggleModule }, { kind: "ngmodule", type: YmtPanesModule }, { kind: "component", type: i4$1.YmtPaneComponent, selector: "ymt-pane", inputs: ["topBarActions", "plain", "mode", "modeAlign"], outputs: ["paneToggled", "navigationClicked"] }, { kind: "component", type: i4$1.YmtPaneBodyComponent, selector: "ymt-pane-body" }, { kind: "directive", type: YmtIconButtonDirective, selector: "button[ymtIconButton],button[ymt-icon-button],a[ymtIconButton],a[ymt-icon-button]", inputs: ["disabled", "disableRipple", "aria-disabled", "disabledInteractive", "icon-button-size"] }, { kind: "component", type: ObjectRelationshipGraphComponent, selector: "yuv-object-relationship-graph", inputs: ["config"], outputs: ["objectSelected", "relationSelected"] }, { kind: "component", type: ObjectRelationshipListComponent, selector: "yuv-object-relationship-list", inputs: ["config"] }] }); }
972
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.15", type: ObjectRelationshipComponent, isStandalone: true, selector: "yuv-object-relationship", inputs: { objectId: { classPropertyName: "objectId", publicName: "objectId", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null }, relationActions: { classPropertyName: "relationActions", publicName: "relationActions", isSignal: true, isRequired: false, transformFunction: null } }, providers: [ObjectRelationshipService], ngImport: i0, template: "<ymt-pane [plain]=\"true\" [topBarActions]=\"topBarActions\">\n <ymt-pane-body [yuvBusyOverlay]=\"busy()\">\n @if (empty()) {\n <div class=\"no-relations\" inert>\n <mat-icon>link_off</mat-icon>\n <p>{{ 'yuv.object-relationship.no-relations' | translate }}</p>\n </div>\n }\n @switch (mode()) {\n @case ('graph') {\n <yuv-object-relationship-graph [config]=\"config()\"></yuv-object-relationship-graph>\n }\n @case ('list') {\n <yuv-object-relationship-list [config]=\"config()\"> </yuv-object-relationship-list>\n }\n }\n </ymt-pane-body>\n</ymt-pane>\n\n<ng-template #topBarActions>\n @if (supportedRelationships().length > 0) {\n <button ymt-icon-button icon-button-size=\"small\" [matTooltip]=\"'yuv.object-relationship.add.tooltip' | translate\" (click)=\"addRelationship()\">\n <mat-icon>add</mat-icon>\n </button>\n }\n <button\n ymt-icon-button\n icon-button-size=\"small\"\n [matTooltip]=\"mode() === 'list' ? ('yuv.object-relationship.mode.graph.tooltip' | translate) : ('yuv.object-relationship.mode.list.tooltip' | translate)\"\n (click)=\"toggleMode()\"\n >\n <mat-icon>{{ mode() === 'list' ? 'graph_3' : 'list' }}</mat-icon>\n </button>\n</ng-template>\n", styles: [":host{display:block;position:relative;height:100%;background-color:var(--ymt-surface)}:host .toggle{position:absolute;inset-block-start:var(--ymt-spacing-s);inset-inline-end:var(--ymt-spacing-s);z-index:10;background-color:var(--ymt-surface);padding:var(--ymt-spacing-xs);border-radius:var(--ymt-corner-full)}:host yuv-object-relationship-list,:host yuv-object-relationship-graph{height:100%}:host .no-relations{position:absolute;inset:0;display:flex;flex-direction:column;justify-content:center;align-items:center;text-align:center;padding:var(--ymt-spacing-l);gap:var(--ymt-spacing-m);overflow:hidden}:host .no-relations mat-icon{scale:4;color:var(--ymt-text-color-subtle);opacity:.5;transform:translateY(-.5em)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i2.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: MatButtonToggleModule }, { kind: "ngmodule", type: YmtPanesModule }, { kind: "component", type: i4$1.YmtPaneComponent, selector: "ymt-pane", inputs: ["topBarActions", "plain", "mode", "modeAlign"], outputs: ["paneToggled", "navigationClicked"] }, { kind: "component", type: i4$1.YmtPaneBodyComponent, selector: "ymt-pane-body" }, { kind: "directive", type: YmtIconButtonDirective, selector: "button[ymtIconButton],button[ymt-icon-button],a[ymtIconButton],a[ymt-icon-button]", inputs: ["disabled", "disableRipple", "aria-disabled", "disabledInteractive", "icon-button-size"] }, { kind: "component", type: ObjectRelationshipGraphComponent, selector: "yuv-object-relationship-graph", inputs: ["config"], outputs: ["objectSelected", "relationSelected"] }, { kind: "component", type: ObjectRelationshipListComponent, selector: "yuv-object-relationship-list", inputs: ["config"] }, { kind: "directive", type: BusyOverlayDirective, selector: "[yuvBusyOverlay]", inputs: ["yuvBusyOverlay", "yuvBusyOverlayConfig"] }] }); }
958
973
  }
959
974
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: ObjectRelationshipComponent, decorators: [{
960
975
  type: Component,
@@ -968,8 +983,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImpo
968
983
  YmtIconButtonDirective,
969
984
  ObjectRelationshipGraphComponent,
970
985
  ObjectRelationshipListComponent,
971
- YmtIconButtonDirective
972
- ], providers: [ObjectRelationshipService], template: "<ymt-pane [plain]=\"true\" [topBarActions]=\"topBarActions\">\n <ymt-pane-body>\n @if (empty()) {\n <div class=\"no-relations\">\n <mat-icon>link_off</mat-icon>\n <p>{{ 'yuv.object-relationship.no-relations' | translate }}</p>\n </div>\n } @else {\n @switch (mode()) {\n @case ('graph') {\n <yuv-object-relationship-graph [config]=\"config()\"></yuv-object-relationship-graph>\n }\n @case ('list') {\n <yuv-object-relationship-list [config]=\"config()\"> </yuv-object-relationship-list>\n }\n }\n }\n </ymt-pane-body>\n</ymt-pane>\n\n<ng-template #topBarActions>\n @if (supportedRelationships().length > 0) {\n <button ymt-icon-button icon-button-size=\"small\" [matTooltip]=\"'yuv.object-relationship.add.tooltip' | translate\" (click)=\"addRelationship()\">\n <mat-icon>add</mat-icon>\n </button>\n }\n <button\n ymt-icon-button\n icon-button-size=\"small\"\n [matTooltip]=\"mode() === 'list' ? ('yuv.object-relationship.mode.graph.tooltip' | translate) : ('yuv.object-relationship.mode.list.tooltip' | translate)\"\n (click)=\"toggleMode()\"\n >\n <mat-icon>{{ mode() === 'list' ? 'graph_3' : 'list' }}</mat-icon>\n </button>\n</ng-template>\n", styles: [":host{display:block;position:relative;height:100%;background-color:var(--ymt-surface)}:host .toggle{position:absolute;inset-block-start:var(--ymt-spacing-s);inset-inline-end:var(--ymt-spacing-s);z-index:10;background-color:var(--ymt-surface);padding:var(--ymt-spacing-xs);border-radius:var(--ymt-corner-full)}:host yuv-object-relationship-list,:host yuv-object-relationship-graph{height:100%}:host .no-relations{height:100%;display:flex;flex-direction:column;justify-content:center;align-items:center;text-align:center;padding:var(--ymt-spacing-l);gap:var(--ymt-spacing-m);overflow:hidden}:host .no-relations mat-icon{scale:4;color:var(--ymt-text-color-subtle);opacity:.5;transform:translateY(-.5em)}\n"] }]
986
+ YmtIconButtonDirective,
987
+ BusyOverlayDirective
988
+ ], providers: [ObjectRelationshipService], template: "<ymt-pane [plain]=\"true\" [topBarActions]=\"topBarActions\">\n <ymt-pane-body [yuvBusyOverlay]=\"busy()\">\n @if (empty()) {\n <div class=\"no-relations\" inert>\n <mat-icon>link_off</mat-icon>\n <p>{{ 'yuv.object-relationship.no-relations' | translate }}</p>\n </div>\n }\n @switch (mode()) {\n @case ('graph') {\n <yuv-object-relationship-graph [config]=\"config()\"></yuv-object-relationship-graph>\n }\n @case ('list') {\n <yuv-object-relationship-list [config]=\"config()\"> </yuv-object-relationship-list>\n }\n }\n </ymt-pane-body>\n</ymt-pane>\n\n<ng-template #topBarActions>\n @if (supportedRelationships().length > 0) {\n <button ymt-icon-button icon-button-size=\"small\" [matTooltip]=\"'yuv.object-relationship.add.tooltip' | translate\" (click)=\"addRelationship()\">\n <mat-icon>add</mat-icon>\n </button>\n }\n <button\n ymt-icon-button\n icon-button-size=\"small\"\n [matTooltip]=\"mode() === 'list' ? ('yuv.object-relationship.mode.graph.tooltip' | translate) : ('yuv.object-relationship.mode.list.tooltip' | translate)\"\n (click)=\"toggleMode()\"\n >\n <mat-icon>{{ mode() === 'list' ? 'graph_3' : 'list' }}</mat-icon>\n </button>\n</ng-template>\n", styles: [":host{display:block;position:relative;height:100%;background-color:var(--ymt-surface)}:host .toggle{position:absolute;inset-block-start:var(--ymt-spacing-s);inset-inline-end:var(--ymt-spacing-s);z-index:10;background-color:var(--ymt-surface);padding:var(--ymt-spacing-xs);border-radius:var(--ymt-corner-full)}:host yuv-object-relationship-list,:host yuv-object-relationship-graph{height:100%}:host .no-relations{position:absolute;inset:0;display:flex;flex-direction:column;justify-content:center;align-items:center;text-align:center;padding:var(--ymt-spacing-l);gap:var(--ymt-spacing-m);overflow:hidden}:host .no-relations mat-icon{scale:4;color:var(--ymt-text-color-subtle);opacity:.5;transform:translateY(-.5em)}\n"] }]
973
989
  }] });
974
990
 
975
991
  const cmp = [ObjectRelationshipComponent];