oip-common 0.9.0 → 0.11.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.
@@ -2,7 +2,7 @@ import * as i0 from '@angular/core';
2
2
  import { Injectable, inject, signal, computed, effect, isDevMode, DestroyRef, ChangeDetectorRef, Component, Input, InjectionToken, PLATFORM_ID, ViewChild, HostBinding, EventEmitter, Output, untracked, Renderer2, SecurityContext, ChangeDetectionStrategy, Injector, EnvironmentInjector, ViewContainerRef, makeEnvironmentProviders, importProvidersFrom } from '@angular/core';
3
3
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
4
4
  import { Subject, BehaviorSubject, of, tap, shareReplay, ReplaySubject, firstValueFrom, from, filter as filter$1 } from 'rxjs';
5
- import * as i2$1 from 'primeng/api';
5
+ import * as i3$1 from 'primeng/api';
6
6
  import { MessageService, ConfirmationService, PrimeIcons, SharedModule } from 'primeng/api';
7
7
  import { HttpErrorResponse, HttpClient as HttpClient$1, provideHttpClient, withInterceptors, withFetch } from '@angular/common/http';
8
8
  import * as i1$7 from '@ngx-translate/core';
@@ -22,47 +22,46 @@ import * as i1$1 from '@angular/forms';
22
22
  import { FormsModule, ReactiveFormsModule } from '@angular/forms';
23
23
  import * as i1$3 from '@angular/common';
24
24
  import { isPlatformBrowser, CommonModule, NgComponentOutlet, NgClass, DatePipe, PathLocationStrategy, LocationStrategy } from '@angular/common';
25
- import * as i3$3 from 'primeng/styleclass';
25
+ import * as i3$4 from 'primeng/styleclass';
26
26
  import { StyleClassModule } from 'primeng/styleclass';
27
27
  import { updatePreset, updateSurfacePalette, $t, definePreset } from '@primeng/themes';
28
28
  import Aura from '@primeng/themes/aura';
29
29
  import * as i3 from 'primeng/selectbutton';
30
30
  import { SelectButtonModule } from 'primeng/selectbutton';
31
31
  import { Tabs, TabList, Tab } from 'primeng/tabs';
32
- import * as i2$2 from 'primeng/avatar';
32
+ import * as i2$1 from 'primeng/avatar';
33
33
  import { AvatarModule } from 'primeng/avatar';
34
34
  import { ConfirmDialog } from 'primeng/confirmdialog';
35
35
  import * as i1$4 from 'primeng/badge';
36
36
  import { BadgeModule } from 'primeng/badge';
37
- import * as i3$1 from 'primeng/paginator';
37
+ import * as i3$2 from 'primeng/paginator';
38
38
  import { PaginatorModule } from 'primeng/paginator';
39
39
  import * as i7 from 'primeng/popover';
40
40
  import { Popover, PopoverModule } from 'primeng/popover';
41
41
  import * as i4 from 'primeng/progressspinner';
42
42
  import { ProgressSpinnerModule, ProgressSpinner } from 'primeng/progressspinner';
43
- import * as i9 from 'primeng/tag';
43
+ import * as i3$6 from 'primeng/tag';
44
44
  import { Tag, TagModule } from 'primeng/tag';
45
45
  import * as signalR from '@microsoft/signalr';
46
- import * as i3$2 from 'primeng/menu';
46
+ import * as i3$3 from 'primeng/menu';
47
47
  import { MenuModule } from 'primeng/menu';
48
48
  import * as i1$6 from 'primeng/contextmenu';
49
49
  import { ContextMenuModule, ContextMenu } from 'primeng/contextmenu';
50
- import * as i3$4 from 'primeng/dialog';
50
+ import * as i3$5 from 'primeng/dialog';
51
51
  import { DialogModule } from 'primeng/dialog';
52
52
  import * as i4$1 from 'primeng/inputtext';
53
53
  import { InputTextModule, InputText } from 'primeng/inputtext';
54
- import * as i2$3 from 'primeng/ripple';
54
+ import * as i2$2 from 'primeng/ripple';
55
55
  import { RippleModule } from 'primeng/ripple';
56
56
  import * as i5 from 'primeng/select';
57
57
  import { SelectModule, Select } from 'primeng/select';
58
58
  import * as i1$8 from 'primeng/fileupload';
59
59
  import { FileUploadModule } from 'primeng/fileupload';
60
60
  import { ImageModule } from 'primeng/image';
61
- import * as i1$9 from 'primeng/table';
61
+ import * as i2$4 from 'primeng/table';
62
62
  import { TableModule } from 'primeng/table';
63
- import * as i2$4 from 'primeng/toggleswitch';
63
+ import * as i2$3 from 'primeng/toggleswitch';
64
64
  import { ToggleSwitchModule } from 'primeng/toggleswitch';
65
- import { TextareaModule, Textarea } from 'primeng/textarea';
66
65
  import * as i5$1 from 'primeng/toolbar';
67
66
  import { ToolbarModule } from 'primeng/toolbar';
68
67
  import * as i5$2 from 'primeng/card';
@@ -70,6 +69,7 @@ import { CardModule } from 'primeng/card';
70
69
  import { DividerModule } from 'primeng/divider';
71
70
  import * as i6 from 'primeng/panel';
72
71
  import { PanelModule } from 'primeng/panel';
72
+ import { Textarea } from 'primeng/textarea';
73
73
  import { loadRemoteModule } from '@angular-architects/module-federation';
74
74
  import { primitive } from '@primeng/themes/aura/base';
75
75
  import { TranslateHttpLoader } from '@ngx-translate/http-loader';
@@ -411,6 +411,7 @@ class LayoutService {
411
411
  return ngDateFormat;
412
412
  }, ...(ngDevMode ? [{ debugName: "monthFormat" }] : []));
413
413
  this.timeZone = computed(() => this.layoutConfig().timeZone, ...(ngDevMode ? [{ debugName: "timeZone" }] : []));
414
+ this.firstDayOfWeek = computed(() => this.layoutConfig().firstDayOfWeek ?? 1, ...(ngDevMode ? [{ debugName: "firstDayOfWeek" }] : []));
414
415
  this.adminMode = computed(() => this.layoutConfig().adminMode ?? false, ...(ngDevMode ? [{ debugName: "adminMode" }] : []));
415
416
  this.transitionComplete = signal(false, ...(ngDevMode ? [{ debugName: "transitionComplete" }] : []));
416
417
  /**
@@ -443,6 +444,7 @@ class LayoutService {
443
444
  if (appConfigUiString != null) {
444
445
  const config = JSON.parse(appConfigUiString);
445
446
  config.timeZone ??= Intl.DateTimeFormat().resolvedOptions().timeZone;
447
+ config.firstDayOfWeek ??= 1;
446
448
  return config;
447
449
  }
448
450
  return {
@@ -456,6 +458,7 @@ class LayoutService {
456
458
  timeFormat: 'HH:mm:ss',
457
459
  dateTimeFormat: 'yyyy-MM-dd HH:mm:ss',
458
460
  timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone,
461
+ firstDayOfWeek: 1,
459
462
  adminMode: false
460
463
  };
461
464
  }
@@ -552,7 +555,7 @@ var msgService$1 = {
552
555
  secondary: "Secondary"
553
556
  };
554
557
  var primeng$1 = "";
555
- var en$k = {
558
+ var en$l = {
556
559
  userService: userService$1,
557
560
  msgService: msgService$1,
558
561
  primeng: primeng$1
@@ -760,7 +763,7 @@ var primeng = {
760
763
  zoomOut: "Уменьшить"
761
764
  }
762
765
  };
763
- var ru$k = {
766
+ var ru$l = {
764
767
  userService: userService,
765
768
  msgService: msgService,
766
769
  primeng: primeng
@@ -770,7 +773,7 @@ var ru$k = {
770
773
  * Global dictionaries shared by all components. They are bundled with the library,
771
774
  * so the application never requests `assets/i18n/{lang}.json`.
772
775
  */
773
- const globalTranslations = { en: en$k, ru: ru$k };
776
+ const globalTranslations = { en: en$l, ru: ru$l };
774
777
  /**
775
778
  * Service for managing translation loading in the application
776
779
  */
@@ -810,6 +813,8 @@ class L10nService {
810
813
  // Global dictionaries are available before the first `use()` call, so TranslateHttpLoader is never asked for them.
811
814
  L10nService.registerTranslations(globalTranslations);
812
815
  Object.entries(globalTranslations).forEach(([lang, translations]) => this.mergeTranslation(lang, translations));
816
+ // The first day of the week is a user setting, it overrides the value of the language dictionary.
817
+ effect(() => this.primeNg.setTranslation({ firstDayOfWeek: this.layoutService.firstDayOfWeek() }));
813
818
  // Static translations are merged once per language, so they have to be re-merged on every language change.
814
819
  this.translateService.onLangChange.subscribe((event) => {
815
820
  L10nService.staticTranslations.forEach((byLang) => {
@@ -904,7 +909,7 @@ class L10nService {
904
909
  if (key) {
905
910
  this.get(key);
906
911
  }
907
- this.translateService.use(selectedLanguage);
912
+ this.translateService.use(selectedLanguage).subscribe(() => this.applyPrimeNgTranslation());
908
913
  }
909
914
  init(languages) {
910
915
  this.availableLanguages = languages;
@@ -913,9 +918,17 @@ class L10nService {
913
918
  this.translateService.setDefaultLang(lang);
914
919
  this.translateService.use(lang).subscribe(() => {
915
920
  this.loadComponentTranslations('app-info');
916
- this.translateService.get('primeng').subscribe((res) => this.primeNg.setTranslation(res));
921
+ this.applyPrimeNgTranslation();
917
922
  });
918
923
  }
924
+ /**
925
+ * Passes the PrimeNG dictionary of the current language to PrimeNG, keeping the user's first day of the week
926
+ */
927
+ applyPrimeNgTranslation() {
928
+ this.translateService
929
+ .get('primeng')
930
+ .subscribe((res) => this.primeNg.setTranslation({ ...res, firstDayOfWeek: this.layoutService.firstDayOfWeek() }));
931
+ }
919
932
  instant(key, interpolateParams) {
920
933
  return this.translateService.instant(key, interpolateParams);
921
934
  }
@@ -1476,7 +1489,7 @@ var baseComponent$1 = {
1476
1489
  security: "Security",
1477
1490
  success: "Saved successfully"
1478
1491
  };
1479
- var en$j = {
1492
+ var en$k = {
1480
1493
  baseComponent: baseComponent$1
1481
1494
  };
1482
1495
 
@@ -1486,7 +1499,7 @@ var baseComponent = {
1486
1499
  security: "Безопасность",
1487
1500
  success: "Сохранено"
1488
1501
  };
1489
- var ru$j = {
1502
+ var ru$k = {
1490
1503
  baseComponent: baseComponent
1491
1504
  };
1492
1505
 
@@ -1627,7 +1640,7 @@ class BaseModuleComponent {
1627
1640
  * @type {Subject<TLocalStoreSettings>}
1628
1641
  */
1629
1642
  this.localSettingsUpdate = new Subject();
1630
- this.baseTranslations = provideTranslations({ en: en$j, ru: ru$j });
1643
+ this.baseTranslations = provideTranslations({ en: en$k, ru: ru$k });
1631
1644
  this.l10nService = inject(L10nService);
1632
1645
  this.canRead = false;
1633
1646
  this.canEdit = false;
@@ -1938,7 +1951,7 @@ var securityComponent$1 = {
1938
1951
  savedSecurity: "Security settings saved",
1939
1952
  selectRoles: "Select roles"
1940
1953
  };
1941
- var en$i = {
1954
+ var en$j = {
1942
1955
  securityComponent: securityComponent$1
1943
1956
  };
1944
1957
 
@@ -1948,13 +1961,13 @@ var securityComponent = {
1948
1961
  savedSecurity: "Настройки сохранены",
1949
1962
  selectRoles: "Выберите роли"
1950
1963
  };
1951
- var ru$i = {
1964
+ var ru$j = {
1952
1965
  securityComponent: securityComponent
1953
1966
  };
1954
1967
 
1955
1968
  class SecurityComponent {
1956
1969
  constructor() {
1957
- this.translations = provideTranslations({ en: en$i, ru: ru$i });
1970
+ this.translations = provideTranslations({ en: en$j, ru: ru$j });
1958
1971
  this.msgService = inject(MsgService);
1959
1972
  this.translateService = inject(TranslateService);
1960
1973
  this.httpClient = inject(HttpClient);
@@ -2123,7 +2136,7 @@ const APP_THEME_PRESETS_MERGE_MODE = new InjectionToken('APP_THEME_PRESETS_MERGE
2123
2136
  factory: () => 'mergeWithDefaults'
2124
2137
  });
2125
2138
 
2126
- var en$h = {
2139
+ var en$i = {
2127
2140
  "app-configurator": {
2128
2141
  primary: "Primary",
2129
2142
  surface: "Surface",
@@ -2134,7 +2147,7 @@ var en$h = {
2134
2147
  }
2135
2148
  };
2136
2149
 
2137
- var ru$h = {
2150
+ var ru$i = {
2138
2151
  "app-configurator": {
2139
2152
  primary: "Основной",
2140
2153
  surface: "Фон",
@@ -2178,7 +2191,7 @@ const PRIMARY_COLORS = [
2178
2191
  ];
2179
2192
  class AppConfiguratorComponent {
2180
2193
  constructor() {
2181
- this.translations = provideTranslations({ en: en$h, ru: ru$h });
2194
+ this.translations = provideTranslations({ en: en$i, ru: ru$i });
2182
2195
  this.router = inject(Router);
2183
2196
  this.config = inject(PrimeNG);
2184
2197
  this.layoutService = inject(LayoutService);
@@ -2699,7 +2712,7 @@ class AppConfiguratorComponent {
2699
2712
  </div>
2700
2713
  }
2701
2714
  </div>
2702
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: SelectButtonModule }, { kind: "component", type: i3.SelectButton, selector: "p-selectButton, p-selectbutton, p-select-button", inputs: ["options", "optionLabel", "optionValue", "optionDisabled", "unselectable", "tabindex", "multiple", "allowEmpty", "styleClass", "ariaLabelledBy", "dataKey", "autofocus", "size", "fluid"], outputs: ["onOptionClick", "onChange"] }, { kind: "directive", type: i2$1.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
2715
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: SelectButtonModule }, { kind: "component", type: i3.SelectButton, selector: "p-selectButton, p-selectbutton, p-select-button", inputs: ["options", "optionLabel", "optionValue", "optionDisabled", "unselectable", "tabindex", "multiple", "allowEmpty", "styleClass", "ariaLabelledBy", "dataKey", "autofocus", "size", "fluid"], outputs: ["onOptionClick", "onChange"] }, { kind: "directive", type: i3$1.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
2703
2716
  }
2704
2717
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AppConfiguratorComponent, decorators: [{
2705
2718
  type: Component,
@@ -3186,7 +3199,7 @@ var userNotifications$1 = {
3186
3199
  markAsRead: "Read",
3187
3200
  markedAsRead: "Notification marked as read"
3188
3201
  };
3189
- var en$g = {
3202
+ var en$h = {
3190
3203
  userNotifications: userNotifications$1
3191
3204
  };
3192
3205
 
@@ -3197,13 +3210,13 @@ var userNotifications = {
3197
3210
  markAsRead: "Прочитано",
3198
3211
  markedAsRead: "Оповещение отмечено прочитанным"
3199
3212
  };
3200
- var ru$g = {
3213
+ var ru$h = {
3201
3214
  userNotifications: userNotifications
3202
3215
  };
3203
3216
 
3204
3217
  class UserNotificationsComponent {
3205
3218
  constructor() {
3206
- this.translations = provideTranslations({ en: en$g, ru: ru$g });
3219
+ this.translations = provideTranslations({ en: en$h, ru: ru$h });
3207
3220
  this.notifications = [];
3208
3221
  this.totalCount = 0;
3209
3222
  this.skip = 0;
@@ -3368,7 +3381,7 @@ class UserNotificationsComponent {
3368
3381
  (onPageChange)="onPageChange($event)"></p-paginator>
3369
3382
  }
3370
3383
  </p-popover>
3371
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: BadgeModule }, { kind: "component", type: i1$4.Badge, selector: "p-badge", inputs: ["styleClass", "badgeSize", "size", "severity", "value", "badgeDisabled"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: PaginatorModule }, { kind: "component", type: i3$1.Paginator, selector: "p-paginator", inputs: ["pageLinkSize", "styleClass", "alwaysShow", "dropdownAppendTo", "templateLeft", "templateRight", "dropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showFirstLastIcon", "totalRecords", "rows", "rowsPerPageOptions", "showJumpToPageDropdown", "showJumpToPageInput", "jumpToPageItemTemplate", "showPageLinks", "locale", "dropdownItemTemplate", "first", "appendTo"], outputs: ["onPageChange"] }, { kind: "component", type: Popover, selector: "p-popover", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions"], outputs: ["onShow", "onHide"] }, { kind: "ngmodule", type: ProgressSpinnerModule }, { kind: "component", type: i4.ProgressSpinner, selector: "p-progressSpinner, p-progress-spinner, p-progressspinner", inputs: ["styleClass", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "component", type: Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "directive", type: Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip"] }, { kind: "pipe", type: i1$3.DatePipe, name: "date" }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
3384
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: BadgeModule }, { kind: "component", type: i1$4.Badge, selector: "p-badge", inputs: ["styleClass", "badgeSize", "size", "severity", "value", "badgeDisabled"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: PaginatorModule }, { kind: "component", type: i3$2.Paginator, selector: "p-paginator", inputs: ["pageLinkSize", "styleClass", "alwaysShow", "dropdownAppendTo", "templateLeft", "templateRight", "dropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showFirstLastIcon", "totalRecords", "rows", "rowsPerPageOptions", "showJumpToPageDropdown", "showJumpToPageInput", "jumpToPageItemTemplate", "showPageLinks", "locale", "dropdownItemTemplate", "first", "appendTo"], outputs: ["onPageChange"] }, { kind: "component", type: Popover, selector: "p-popover", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions"], outputs: ["onShow", "onHide"] }, { kind: "ngmodule", type: ProgressSpinnerModule }, { kind: "component", type: i4.ProgressSpinner, selector: "p-progressSpinner, p-progress-spinner, p-progressspinner", inputs: ["styleClass", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "component", type: Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "directive", type: Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip"] }, { kind: "pipe", type: i1$3.DatePipe, name: "date" }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
3372
3385
  }
3373
3386
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: UserNotificationsComponent, decorators: [{
3374
3387
  type: Component,
@@ -3593,7 +3606,7 @@ class AppTopbarApplicationSwitcherComponent {
3593
3606
  </p-button>
3594
3607
  <p-menu #applicationMenu [model]="applicationMenuItems" [popup]="true" />
3595
3608
  }
3596
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: MenuModule }, { kind: "component", type: i3$2.Menu, selector: "p-menu", inputs: ["model", "popup", "style", "styleClass", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "ariaLabel", "ariaLabelledBy", "id", "tabindex", "appendTo"], outputs: ["onShow", "onHide", "onBlur", "onFocus"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
3609
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: MenuModule }, { kind: "component", type: i3$3.Menu, selector: "p-menu", inputs: ["model", "popup", "style", "styleClass", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "ariaLabel", "ariaLabelledBy", "id", "tabindex", "appendTo"], outputs: ["onShow", "onHide", "onBlur", "onFocus"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
3597
3610
  }
3598
3611
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AppTopbarApplicationSwitcherComponent, decorators: [{
3599
3612
  type: Component,
@@ -3632,7 +3645,7 @@ var topbar$1 = {
3632
3645
  profile: "Profile",
3633
3646
  applications: "Applications"
3634
3647
  };
3635
- var en$f = {
3648
+ var en$g = {
3636
3649
  topbar: topbar$1
3637
3650
  };
3638
3651
 
@@ -3645,13 +3658,13 @@ var topbar = {
3645
3658
  profile: "Профиль",
3646
3659
  applications: "Приложения"
3647
3660
  };
3648
- var ru$f = {
3661
+ var ru$g = {
3649
3662
  topbar: topbar
3650
3663
  };
3651
3664
 
3652
3665
  class AppTopbar {
3653
3666
  constructor() {
3654
- this.translations = provideTranslations({ en: en$f, ru: ru$f });
3667
+ this.translations = provideTranslations({ en: en$g, ru: ru$g });
3655
3668
  this.securityService = inject(SecurityService);
3656
3669
  this.topBarService = inject(TopBarService);
3657
3670
  this.userService = inject(UserService);
@@ -3798,7 +3811,7 @@ class AppTopbar {
3798
3811
  </div>
3799
3812
  </div>
3800
3813
  </div>
3801
- </div>`, isInline: true, dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$5.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$3.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"], exportAs: ["ngComponentOutlet"] }, { kind: "ngmodule", type: StyleClassModule }, { kind: "directive", type: i3$3.StyleClass, selector: "[pStyleClass]", inputs: ["pStyleClass", "enterFromClass", "enterActiveClass", "enterToClass", "leaveFromClass", "leaveActiveClass", "leaveToClass", "hideOnOutsideClick", "toggleClass", "hideOnEscape", "hideOnResize", "resizeSelector"] }, { kind: "component", type: AppConfiguratorComponent, selector: "app-configurator" }, { kind: "component", type: Tabs, selector: "p-tabs", inputs: ["value", "scrollable", "lazy", "selectOnFocus", "showNavigators", "tabindex"], outputs: ["valueChange"] }, { kind: "component", type: TabList, selector: "p-tablist" }, { kind: "component", type: Tab, selector: "p-tab", inputs: ["value", "disabled"], outputs: ["valueChange"] }, { kind: "ngmodule", type: AvatarModule }, { kind: "component", type: i2$2.Avatar, selector: "p-avatar", inputs: ["label", "icon", "image", "size", "shape", "styleClass", "ariaLabel", "ariaLabelledBy"], outputs: ["onImageError"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: ConfirmDialog, selector: "p-confirmDialog, p-confirmdialog, p-confirm-dialog", inputs: ["header", "icon", "message", "style", "styleClass", "maskStyleClass", "acceptIcon", "acceptLabel", "closeAriaLabel", "acceptAriaLabel", "acceptVisible", "rejectIcon", "rejectLabel", "rejectAriaLabel", "rejectVisible", "acceptButtonStyleClass", "rejectButtonStyleClass", "closeOnEscape", "dismissableMask", "blockScroll", "rtl", "closable", "appendTo", "key", "autoZIndex", "baseZIndex", "transitionOptions", "focusTrap", "defaultFocus", "breakpoints", "modal", "visible", "position", "draggable"], outputs: ["onHide"] }, { kind: "component", type: UserNotificationsComponent, selector: "app-user-notifications" }, { kind: "component", type: AppTopbarApplicationSwitcherComponent, selector: "app-topbar-application-switcher" }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
3814
+ </div>`, isInline: true, dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$5.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$3.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"], exportAs: ["ngComponentOutlet"] }, { kind: "ngmodule", type: StyleClassModule }, { kind: "directive", type: i3$4.StyleClass, selector: "[pStyleClass]", inputs: ["pStyleClass", "enterFromClass", "enterActiveClass", "enterToClass", "leaveFromClass", "leaveActiveClass", "leaveToClass", "hideOnOutsideClick", "toggleClass", "hideOnEscape", "hideOnResize", "resizeSelector"] }, { kind: "component", type: AppConfiguratorComponent, selector: "app-configurator" }, { kind: "component", type: Tabs, selector: "p-tabs", inputs: ["value", "scrollable", "lazy", "selectOnFocus", "showNavigators", "tabindex"], outputs: ["valueChange"] }, { kind: "component", type: TabList, selector: "p-tablist" }, { kind: "component", type: Tab, selector: "p-tab", inputs: ["value", "disabled"], outputs: ["valueChange"] }, { kind: "ngmodule", type: AvatarModule }, { kind: "component", type: i2$1.Avatar, selector: "p-avatar", inputs: ["label", "icon", "image", "size", "shape", "styleClass", "ariaLabel", "ariaLabelledBy"], outputs: ["onImageError"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: ConfirmDialog, selector: "p-confirmDialog, p-confirmdialog, p-confirm-dialog", inputs: ["header", "icon", "message", "style", "styleClass", "maskStyleClass", "acceptIcon", "acceptLabel", "closeAriaLabel", "acceptAriaLabel", "acceptVisible", "rejectIcon", "rejectLabel", "rejectAriaLabel", "rejectVisible", "acceptButtonStyleClass", "rejectButtonStyleClass", "closeOnEscape", "dismissableMask", "blockScroll", "rtl", "closable", "appendTo", "key", "autoZIndex", "baseZIndex", "transitionOptions", "focusTrap", "defaultFocus", "breakpoints", "modal", "visible", "position", "draggable"], outputs: ["onHide"] }, { kind: "component", type: UserNotificationsComponent, selector: "app-user-notifications" }, { kind: "component", type: AppTopbarApplicationSwitcherComponent, selector: "app-topbar-application-switcher" }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
3802
3815
  }
3803
3816
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AppTopbar, decorators: [{
3804
3817
  type: Component,
@@ -4037,6 +4050,13 @@ class MenuApi extends HttpClient {
4037
4050
  secure: true,
4038
4051
  ...params,
4039
4052
  });
4053
+ this.copyModuleInstance = ({ id, ...query }, params = {}) => this.request({
4054
+ path: `/api/menu/copy-module-instance/${id}`,
4055
+ method: "POST",
4056
+ secure: true,
4057
+ format: "json",
4058
+ ...params,
4059
+ });
4040
4060
  this.changeOrder = (query, params = {}) => this.request({
4041
4061
  path: `/api/menu/change-order`,
4042
4062
  method: "POST",
@@ -4191,9 +4211,9 @@ class StartPageService {
4191
4211
  if (item.separator) {
4192
4212
  continue;
4193
4213
  }
4194
- if (item.items?.length) {
4214
+ if (item.isFolder || item.items?.length) {
4195
4215
  // A folder is never a landing page itself, its children are.
4196
- result.push(...this.collectNavigableLeaves(item.items));
4216
+ result.push(...this.collectNavigableLeaves(item.items ?? []));
4197
4217
  continue;
4198
4218
  }
4199
4219
  // A module without a real route would resolve back to the empty path and loop.
@@ -4318,13 +4338,22 @@ class MenuItemComponent {
4318
4338
  {
4319
4339
  label: this.localization.new,
4320
4340
  icon: PrimeIcons.PLUS,
4321
- command: (event) => this.newClick(event)
4341
+ command: (event) => this.newClick(event),
4342
+ // Only a folder can have child items.
4343
+ visible: !!item.isFolder
4322
4344
  },
4323
4345
  {
4324
4346
  label: this.localization.edit,
4325
4347
  icon: PrimeIcons.FILE_EDIT,
4326
4348
  command: (event) => this.editClick(event)
4327
4349
  },
4350
+ {
4351
+ label: this.localization.copy,
4352
+ icon: PrimeIcons.COPY,
4353
+ command: () => this.copyItem(item),
4354
+ // Only a leaf instance can be copied, folders with children are not supported.
4355
+ visible: !item.items?.length
4356
+ },
4328
4357
  { separator: true },
4329
4358
  {
4330
4359
  label: this.localization.delete,
@@ -4356,10 +4385,10 @@ class MenuItemComponent {
4356
4385
  this.contextMenu.show($event);
4357
4386
  }
4358
4387
  /**
4359
- * Builds the start page entries of the context menu. Only a navigable leaf can be a start page.
4388
+ * Builds the start page entries of the context menu. Only a navigable non-folder item can be a start page.
4360
4389
  */
4361
4390
  getStartModuleItems(item) {
4362
- if (!item?.routerLink || item.items?.length) {
4391
+ if (!item?.routerLink || item.isFolder || item.items?.length) {
4363
4392
  return [];
4364
4393
  }
4365
4394
  return item.isStart
@@ -4388,6 +4417,11 @@ class MenuItemComponent {
4388
4417
  this.msgService.success(this.localization.unsetStartModuleSuccessMessage);
4389
4418
  await this.menuService.loadMenu();
4390
4419
  }
4420
+ async copyItem(item) {
4421
+ await this.menuDataService.copyModuleInstance({ id: item.moduleInstanceId });
4422
+ this.msgService.success(this.localization.copyItemSuccessMessage);
4423
+ await this.menuService.loadMenu();
4424
+ }
4391
4425
  deleteItem(event) {
4392
4426
  this.confirmationService.confirm({
4393
4427
  header: this.localization.deleteItemConfirmHeader,
@@ -4564,7 +4598,7 @@ class MenuItemComponent {
4564
4598
  </ul>
4565
4599
  }
4566
4600
  </ng-container>
4567
- `, isInline: true, dependencies: [{ kind: "component", type: MenuItemComponent, selector: "[app-menuitem]", inputs: ["item", "index", "root", "parentKey", "menuItemCreateDialogComponent", "menuItemEditDialogComponent", "contextMenu"] }, { kind: "ngmodule", type: RippleModule }, { kind: "directive", type: i2$3.Ripple, selector: "[pRipple]" }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: ContextMenuModule }, { kind: "component", type: ConfirmDialog, selector: "p-confirmDialog, p-confirmdialog, p-confirm-dialog", inputs: ["header", "icon", "message", "style", "styleClass", "maskStyleClass", "acceptIcon", "acceptLabel", "closeAriaLabel", "acceptAriaLabel", "acceptVisible", "rejectIcon", "rejectLabel", "rejectAriaLabel", "rejectVisible", "acceptButtonStyleClass", "rejectButtonStyleClass", "closeOnEscape", "dismissableMask", "blockScroll", "rtl", "closable", "appendTo", "key", "autoZIndex", "baseZIndex", "transitionOptions", "focusTrap", "defaultFocus", "breakpoints", "modal", "visible", "position", "draggable"], outputs: ["onHide"] }] }); }
4601
+ `, isInline: true, dependencies: [{ kind: "component", type: MenuItemComponent, selector: "[app-menuitem]", inputs: ["item", "index", "root", "parentKey", "menuItemCreateDialogComponent", "menuItemEditDialogComponent", "contextMenu"] }, { kind: "ngmodule", type: RippleModule }, { kind: "directive", type: i2$2.Ripple, selector: "[pRipple]" }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: ContextMenuModule }, { kind: "component", type: ConfirmDialog, selector: "p-confirmDialog, p-confirmdialog, p-confirm-dialog", inputs: ["header", "icon", "message", "style", "styleClass", "maskStyleClass", "acceptIcon", "acceptLabel", "closeAriaLabel", "acceptAriaLabel", "acceptVisible", "rejectIcon", "rejectLabel", "rejectAriaLabel", "rejectVisible", "acceptButtonStyleClass", "rejectButtonStyleClass", "closeOnEscape", "dismissableMask", "blockScroll", "rtl", "closable", "appendTo", "key", "autoZIndex", "baseZIndex", "transitionOptions", "focusTrap", "defaultFocus", "breakpoints", "modal", "visible", "position", "draggable"], outputs: ["onHide"] }] }); }
4568
4602
  }
4569
4603
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: MenuItemComponent, decorators: [{
4570
4604
  type: Component,
@@ -4677,6 +4711,7 @@ class MenuItemCreateDialogComponent {
4677
4711
  this.msgService = inject(MsgService);
4678
4712
  this.visibleChange = new EventEmitter();
4679
4713
  this.modules = [];
4714
+ this.moduleOptions = [];
4680
4715
  this.iconOptions = Object.values(PrimeIcons)
4681
4716
  .filter((icon) => typeof icon === 'string')
4682
4717
  .map((icon) => ({
@@ -4684,14 +4719,35 @@ class MenuItemCreateDialogComponent {
4684
4719
  value: icon
4685
4720
  }))
4686
4721
  .sort((left, right) => left.label.localeCompare(right.label));
4687
- this.selectIcon = 'pi pi-box';
4722
+ this.selectIcon = MenuItemCreateDialogComponent.defaultIcon;
4688
4723
  this.saving = false;
4689
4724
  }
4725
+ static { this.defaultIcon = 'pi pi-box'; }
4690
4726
  get canSave() {
4691
4727
  return !this.saving && !!this.selectModule;
4692
4728
  }
4693
4729
  async ngOnInit() {
4694
4730
  this.modules = await this.menu.getModules();
4731
+ this.updateModuleOptions();
4732
+ }
4733
+ /**
4734
+ * Restricts the module list to the folder when the item is created at the menu root,
4735
+ * since only a folder can be placed there.
4736
+ */
4737
+ updateModuleOptions() {
4738
+ const isRoot = !this.menuService.contextMenuItem;
4739
+ this.moduleOptions = isRoot ? this.modules.filter((module) => module.isFolder) : this.modules;
4740
+ if (isRoot && this.moduleOptions.length === 1) {
4741
+ this.selectModule = this.moduleOptions[0].key;
4742
+ this.onModuleChange(this.selectModule);
4743
+ }
4744
+ else if (!this.moduleOptions.some((module) => module.key === this.selectModule)) {
4745
+ this.selectModule = undefined;
4746
+ }
4747
+ }
4748
+ onModuleChange(moduleId) {
4749
+ const module = this.modules.find((item) => item.key === moduleId);
4750
+ this.selectIcon = module?.icon || MenuItemCreateDialogComponent.defaultIcon;
4695
4751
  }
4696
4752
  changeVisible() {
4697
4753
  this.visible = !this.visible;
@@ -4728,6 +4784,7 @@ class MenuItemCreateDialogComponent {
4728
4784
  this.visibleChange.emit(this.visible);
4729
4785
  }
4730
4786
  showDialog() {
4787
+ this.updateModuleOptions();
4731
4788
  this.visible = true;
4732
4789
  this.visibleChange.emit(this.visible);
4733
4790
  }
@@ -4774,8 +4831,9 @@ class MenuItemCreateDialogComponent {
4774
4831
  placeholder="{{ 'menuItemCreateDialogComponent.selectModule' | translate }}"
4775
4832
  scrollHeight="18rem"
4776
4833
  [filter]="true"
4777
- [options]="modules"
4778
- [(ngModel)]="selectModule" />
4834
+ [options]="moduleOptions"
4835
+ [(ngModel)]="selectModule"
4836
+ (ngModelChange)="onModuleChange($event)" />
4779
4837
  </div>
4780
4838
  <div class="flex items-center gap-4 mb-4">
4781
4839
  <label class="font-semibold w-1/3" for="oip-menu-item-create-dialog-icon">
@@ -4821,7 +4879,7 @@ class MenuItemCreateDialogComponent {
4821
4879
  (click)="save()" />
4822
4880
  </div>
4823
4881
  </p-dialog>
4824
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "directive", type: i2$1.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: DialogModule }, { kind: "component", type: i3$4.Dialog, selector: "p-dialog", inputs: ["hostName", "header", "draggable", "resizable", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "breakpoints", "styleClass", "maskStyleClass", "maskStyle", "showHeader", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "closeButtonProps", "maximizeButtonProps", "visible", "style", "position", "role", "appendTo", "content", "contentTemplate", "footerTemplate", "closeIconTemplate", "maximizeIconTemplate", "minimizeIconTemplate", "headlessTemplate"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i4$1.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i5.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
4882
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "directive", type: i3$1.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: DialogModule }, { kind: "component", type: i3$5.Dialog, selector: "p-dialog", inputs: ["hostName", "header", "draggable", "resizable", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "breakpoints", "styleClass", "maskStyleClass", "maskStyle", "showHeader", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "closeButtonProps", "maximizeButtonProps", "visible", "style", "position", "role", "appendTo", "content", "contentTemplate", "footerTemplate", "closeIconTemplate", "maximizeIconTemplate", "minimizeIconTemplate", "headlessTemplate"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i4$1.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i5.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
4825
4883
  }
4826
4884
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: MenuItemCreateDialogComponent, decorators: [{
4827
4885
  type: Component,
@@ -4871,8 +4929,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
4871
4929
  placeholder="{{ 'menuItemCreateDialogComponent.selectModule' | translate }}"
4872
4930
  scrollHeight="18rem"
4873
4931
  [filter]="true"
4874
- [options]="modules"
4875
- [(ngModel)]="selectModule" />
4932
+ [options]="moduleOptions"
4933
+ [(ngModel)]="selectModule"
4934
+ (ngModelChange)="onModuleChange($event)" />
4876
4935
  </div>
4877
4936
  <div class="flex items-center gap-4 mb-4">
4878
4937
  <label class="font-semibold w-1/3" for="oip-menu-item-create-dialog-icon">
@@ -5083,7 +5142,7 @@ class MenuItemEditDialogComponent {
5083
5142
  (click)="save()" />
5084
5143
  </div>
5085
5144
  </p-dialog>
5086
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "directive", type: i2$1.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: DialogModule }, { kind: "component", type: i3$4.Dialog, selector: "p-dialog", inputs: ["hostName", "header", "draggable", "resizable", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "breakpoints", "styleClass", "maskStyleClass", "maskStyle", "showHeader", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "closeButtonProps", "maximizeButtonProps", "visible", "style", "position", "role", "appendTo", "content", "contentTemplate", "footerTemplate", "closeIconTemplate", "maximizeIconTemplate", "minimizeIconTemplate", "headlessTemplate"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i4$1.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i5.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MultiSelectModule }, { kind: "component", type: i1.MultiSelect, selector: "p-multiSelect, p-multiselect, p-multi-select", inputs: ["id", "ariaLabel", "styleClass", "panelStyle", "panelStyleClass", "inputId", "readonly", "group", "filter", "filterPlaceHolder", "filterLocale", "overlayVisible", "tabindex", "dataKey", "ariaLabelledBy", "displaySelectedLabel", "maxSelectedLabels", "selectionLimit", "selectedItemsLabel", "showToggleAll", "emptyFilterMessage", "emptyMessage", "resetFilterOnHide", "dropdownIcon", "chipIcon", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "showHeader", "filterBy", "scrollHeight", "lazy", "virtualScroll", "loading", "virtualScrollItemSize", "loadingIcon", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "autofocusFilter", "display", "autocomplete", "showClear", "autofocus", "placeholder", "options", "filterValue", "selectAll", "focusOnHover", "filterFields", "selectOnFocus", "autoOptionFocus", "highlightOnSelect", "size", "variant", "fluid", "appendTo"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onClear", "onPanelShow", "onPanelHide", "onLazyLoad", "onRemove", "onSelectAllChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
5145
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "directive", type: i3$1.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: DialogModule }, { kind: "component", type: i3$5.Dialog, selector: "p-dialog", inputs: ["hostName", "header", "draggable", "resizable", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "breakpoints", "styleClass", "maskStyleClass", "maskStyle", "showHeader", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "closeButtonProps", "maximizeButtonProps", "visible", "style", "position", "role", "appendTo", "content", "contentTemplate", "footerTemplate", "closeIconTemplate", "maximizeIconTemplate", "minimizeIconTemplate", "headlessTemplate"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i4$1.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i5.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MultiSelectModule }, { kind: "component", type: i1.MultiSelect, selector: "p-multiSelect, p-multiselect, p-multi-select", inputs: ["id", "ariaLabel", "styleClass", "panelStyle", "panelStyleClass", "inputId", "readonly", "group", "filter", "filterPlaceHolder", "filterLocale", "overlayVisible", "tabindex", "dataKey", "ariaLabelledBy", "displaySelectedLabel", "maxSelectedLabels", "selectionLimit", "selectedItemsLabel", "showToggleAll", "emptyFilterMessage", "emptyMessage", "resetFilterOnHide", "dropdownIcon", "chipIcon", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "showHeader", "filterBy", "scrollHeight", "lazy", "virtualScroll", "loading", "virtualScrollItemSize", "loadingIcon", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "autofocusFilter", "display", "autocomplete", "showClear", "autofocus", "placeholder", "options", "filterValue", "selectAll", "focusOnHover", "filterFields", "selectOnFocus", "autoOptionFocus", "highlightOnSelect", "size", "variant", "fluid", "appendTo"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onClear", "onPanelShow", "onPanelHide", "onLazyLoad", "onRemove", "onSelectAllChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
5087
5146
  }
5088
5147
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: MenuItemEditDialogComponent, decorators: [{
5089
5148
  type: Component,
@@ -5197,6 +5256,8 @@ var menuComponent$1 = {
5197
5256
  var menuItemComponent$1 = {
5198
5257
  "new": "Add",
5199
5258
  edit: "Edit",
5259
+ copy: "Copy",
5260
+ copyItemSuccessMessage: "Copied successfully",
5200
5261
  "delete": "Delete",
5201
5262
  deleteItemConfirmHeader: "Delete",
5202
5263
  deleteItemConfirmMessage: "Are you sure you want to delete the item?",
@@ -5232,7 +5293,7 @@ var menuItemCreateDialogComponent$1 = {
5232
5293
  cancel: "Cancel",
5233
5294
  save: "Save"
5234
5295
  };
5235
- var en$e = {
5296
+ var en$f = {
5236
5297
  menuComponent: menuComponent$1,
5237
5298
  menuItemComponent: menuItemComponent$1,
5238
5299
  menuItemEditDialogComponent: menuItemEditDialogComponent$1,
@@ -5246,6 +5307,8 @@ var menuComponent = {
5246
5307
  var menuItemComponent = {
5247
5308
  "new": "Добавить",
5248
5309
  edit: "Редактировать",
5310
+ copy: "Копировать",
5311
+ copyItemSuccessMessage: "Успешно скопировано",
5249
5312
  "delete": "Удалить",
5250
5313
  deleteItemConfirmHeader: "Удаление",
5251
5314
  deleteItemConfirmMessage: "Вы уверены что хотите удалить элемент?",
@@ -5281,7 +5344,7 @@ var menuItemCreateDialogComponent = {
5281
5344
  cancel: "Отмена",
5282
5345
  save: "Сохранить"
5283
5346
  };
5284
- var ru$e = {
5347
+ var ru$f = {
5285
5348
  menuComponent: menuComponent,
5286
5349
  menuItemComponent: menuItemComponent,
5287
5350
  menuItemEditDialogComponent: menuItemEditDialogComponent,
@@ -5292,7 +5355,7 @@ class MenuComponent {
5292
5355
  constructor() {
5293
5356
  // Registers the whole menu/l10n/menu.*.json bundle, which also covers
5294
5357
  // menuItemComponent, menuItemEditDialogComponent and menuItemCreateDialogComponent.
5295
- this.translations = provideTranslations({ en: en$e, ru: ru$e });
5358
+ this.translations = provideTranslations({ en: en$f, ru: ru$f });
5296
5359
  this.menuService = inject(MenuService);
5297
5360
  this.securityService = inject(SecurityService);
5298
5361
  this.translateService = inject(TranslateService);
@@ -5419,14 +5482,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
5419
5482
  var blockLoader$1 = {
5420
5483
  loading: "Loading..."
5421
5484
  };
5422
- var en$d = {
5485
+ var en$e = {
5423
5486
  blockLoader: blockLoader$1
5424
5487
  };
5425
5488
 
5426
5489
  var blockLoader = {
5427
5490
  loading: "Загрузка..."
5428
5491
  };
5429
- var ru$d = {
5492
+ var ru$e = {
5430
5493
  blockLoader: blockLoader
5431
5494
  };
5432
5495
 
@@ -5443,7 +5506,7 @@ class BlockLoaderComponent {
5443
5506
  static { this.showDelayMs = 150; }
5444
5507
  static { this.minVisibleMs = 300; }
5445
5508
  constructor() {
5446
- this.translations = provideTranslations({ en: en$d, ru: ru$d });
5509
+ this.translations = provideTranslations({ en: en$e, ru: ru$e });
5447
5510
  this.moduleLoadingService = inject(ModuleLoadingService);
5448
5511
  this.shownAt = 0;
5449
5512
  this.visible = signal(false, ...(ngDevMode ? [{ debugName: "visible" }] : []));
@@ -5575,7 +5638,7 @@ var defaultSecretsBanner$1 = {
5575
5638
  dismiss: "Dismiss"
5576
5639
  }
5577
5640
  };
5578
- var en$c = {
5641
+ var en$d = {
5579
5642
  defaultSecretsBanner: defaultSecretsBanner$1
5580
5643
  };
5581
5644
 
@@ -5597,7 +5660,7 @@ var defaultSecretsBanner = {
5597
5660
  dismiss: "Скрыть"
5598
5661
  }
5599
5662
  };
5600
- var ru$c = {
5663
+ var ru$d = {
5601
5664
  defaultSecretsBanner: defaultSecretsBanner
5602
5665
  };
5603
5666
 
@@ -5613,7 +5676,7 @@ var ru$c = {
5613
5676
  */
5614
5677
  class DefaultSecretsBannerComponent {
5615
5678
  constructor() {
5616
- this.translations = provideTranslations({ en: en$c, ru: ru$c });
5679
+ this.translations = provideTranslations({ en: en$d, ru: ru$d });
5617
5680
  this.securityApi = inject(SecurityApi);
5618
5681
  this.securityService = inject(SecurityService);
5619
5682
  this.destroyRef = inject(DestroyRef);
@@ -5955,7 +6018,7 @@ class AppFloatingConfiguratorComponent {
5955
6018
  <app-configurator />
5956
6019
  </div>
5957
6020
  </div>
5958
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: StyleClassModule }, { kind: "directive", type: i3$3.StyleClass, selector: "[pStyleClass]", inputs: ["pStyleClass", "enterFromClass", "enterActiveClass", "enterToClass", "leaveFromClass", "leaveActiveClass", "leaveToClass", "hideOnOutsideClick", "toggleClass", "hideOnEscape", "hideOnResize", "resizeSelector"] }, { kind: "component", type: AppConfiguratorComponent, selector: "app-configurator" }] }); }
6021
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: StyleClassModule }, { kind: "directive", type: i3$4.StyleClass, selector: "[pStyleClass]", inputs: ["pStyleClass", "enterFromClass", "enterActiveClass", "enterToClass", "leaveFromClass", "leaveActiveClass", "leaveToClass", "hideOnOutsideClick", "toggleClass", "hideOnEscape", "hideOnResize", "resizeSelector"] }, { kind: "component", type: AppConfiguratorComponent, selector: "app-configurator" }] }); }
5959
6022
  }
5960
6023
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AppFloatingConfiguratorComponent, decorators: [{
5961
6024
  type: Component,
@@ -5996,7 +6059,7 @@ var notfound$1 = {
5996
6059
  description: "Requested resource is not available.",
5997
6060
  button: "Go to home"
5998
6061
  };
5999
- var en$b = {
6062
+ var en$c = {
6000
6063
  notfound: notfound$1
6001
6064
  };
6002
6065
 
@@ -6006,13 +6069,13 @@ var notfound = {
6006
6069
  description: "Запрашиваемый ресурс недоступен.",
6007
6070
  button: "На главную"
6008
6071
  };
6009
- var ru$b = {
6072
+ var ru$c = {
6010
6073
  notfound: notfound
6011
6074
  };
6012
6075
 
6013
6076
  class NotfoundComponent {
6014
6077
  constructor() {
6015
- this.translations = provideTranslations({ en: en$b, ru: ru$b });
6078
+ this.translations = provideTranslations({ en: en$c, ru: ru$c });
6016
6079
  }
6017
6080
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: NotfoundComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6018
6081
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.16", type: NotfoundComponent, isStandalone: true, selector: "app-notfound", ngImport: i0, template: ` <app-floating-configurator />
@@ -6072,7 +6135,7 @@ var unauthorized$1 = {
6072
6135
  signInToContinue: "Sign in to continue",
6073
6136
  signIn: "Sign In"
6074
6137
  };
6075
- var en$a = {
6138
+ var en$b = {
6076
6139
  unauthorized: unauthorized$1
6077
6140
  };
6078
6141
 
@@ -6081,13 +6144,13 @@ var unauthorized = {
6081
6144
  signInToContinue: "Войдите чтобы продолжить",
6082
6145
  signIn: "Войти"
6083
6146
  };
6084
- var ru$a = {
6147
+ var ru$b = {
6085
6148
  unauthorized: unauthorized
6086
6149
  };
6087
6150
 
6088
6151
  class UnauthorizedComponent {
6089
6152
  constructor() {
6090
- this.translations = provideTranslations({ en: en$a, ru: ru$a });
6153
+ this.translations = provideTranslations({ en: en$b, ru: ru$b });
6091
6154
  this.securityService = inject(SecurityService);
6092
6155
  this.route = inject(ActivatedRoute);
6093
6156
  }
@@ -6187,7 +6250,7 @@ var access$1 = {
6187
6250
  message: "You do not have the necessary permissions. Please contact admins.",
6188
6251
  button: "Go to Dashboard"
6189
6252
  };
6190
- var en$9 = {
6253
+ var en$a = {
6191
6254
  access: access$1
6192
6255
  };
6193
6256
 
@@ -6196,13 +6259,13 @@ var access = {
6196
6259
  message: "У вас недостаточно прав. Пожалуйста, обратитесь к администраторам.",
6197
6260
  button: "На главную"
6198
6261
  };
6199
- var ru$9 = {
6262
+ var ru$a = {
6200
6263
  access: access
6201
6264
  };
6202
6265
 
6203
6266
  class AccessComponent {
6204
6267
  constructor() {
6205
- this.translations = provideTranslations({ en: en$9, ru: ru$9 });
6268
+ this.translations = provideTranslations({ en: en$a, ru: ru$a });
6206
6269
  }
6207
6270
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AccessComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6208
6271
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.16", type: AccessComponent, isStandalone: true, selector: "app-access", ngImport: i0, template: `<div
@@ -6235,7 +6298,7 @@ class AccessComponent {
6235
6298
  </div>
6236
6299
  </div>
6237
6300
  </div>
6238
- </div>`, isInline: true, dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i1$2.ButtonDirective, selector: "[pButton]", inputs: ["ptButtonDirective", "hostName", "text", "plain", "raised", "size", "outlined", "rounded", "iconPos", "loadingIcon", "fluid", "label", "icon", "loading", "buttonProps", "severity"] }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: RippleModule }, { kind: "directive", type: i2$3.Ripple, selector: "[pRipple]" }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
6301
+ </div>`, isInline: true, dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i1$2.ButtonDirective, selector: "[pButton]", inputs: ["ptButtonDirective", "hostName", "text", "plain", "raised", "size", "outlined", "rounded", "iconPos", "loadingIcon", "fluid", "label", "icon", "loading", "buttonProps", "severity"] }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: RippleModule }, { kind: "directive", type: i2$2.Ripple, selector: "[pRipple]" }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
6239
6302
  }
6240
6303
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AccessComponent, decorators: [{
6241
6304
  type: Component,
@@ -6282,7 +6345,7 @@ var error$1 = {
6282
6345
  message: "Requested resource is not available.",
6283
6346
  button: "Go to Dashboard"
6284
6347
  };
6285
- var en$8 = {
6348
+ var en$9 = {
6286
6349
  error: error$1
6287
6350
  };
6288
6351
 
@@ -6291,13 +6354,13 @@ var error = {
6291
6354
  message: "Запрашиваемый ресурс недоступен.",
6292
6355
  button: "На главную"
6293
6356
  };
6294
- var ru$8 = {
6357
+ var ru$9 = {
6295
6358
  error: error
6296
6359
  };
6297
6360
 
6298
6361
  class ErrorComponent {
6299
6362
  constructor() {
6300
- this.translations = provideTranslations({ en: en$8, ru: ru$8 });
6363
+ this.translations = provideTranslations({ en: en$9, ru: ru$9 });
6301
6364
  }
6302
6365
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: ErrorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6303
6366
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.16", type: ErrorComponent, isStandalone: true, selector: "app-error", ngImport: i0, template: `<div
@@ -6330,7 +6393,7 @@ class ErrorComponent {
6330
6393
  </div>
6331
6394
  </div>
6332
6395
  </div>
6333
- </div>`, isInline: true, dependencies: [{ kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i1$2.ButtonDirective, selector: "[pButton]", inputs: ["ptButtonDirective", "hostName", "text", "plain", "raised", "size", "outlined", "rounded", "iconPos", "loadingIcon", "fluid", "label", "icon", "loading", "buttonProps", "severity"] }, { kind: "ngmodule", type: RippleModule }, { kind: "directive", type: i2$3.Ripple, selector: "[pRipple]" }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
6396
+ </div>`, isInline: true, dependencies: [{ kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i1$2.ButtonDirective, selector: "[pButton]", inputs: ["ptButtonDirective", "hostName", "text", "plain", "raised", "size", "outlined", "rounded", "iconPos", "loadingIcon", "fluid", "label", "icon", "loading", "buttonProps", "severity"] }, { kind: "ngmodule", type: RippleModule }, { kind: "directive", type: i2$2.Ripple, selector: "[pRipple]" }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
6334
6397
  }
6335
6398
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: ErrorComponent, decorators: [{
6336
6399
  type: Component,
@@ -6388,7 +6451,7 @@ var profileComponent$1 = {
6388
6451
  photoDeleted: "Photo deleted",
6389
6452
  failedToDeletePhoto: "Failed to delete user photo"
6390
6453
  };
6391
- var en$7 = {
6454
+ var en$8 = {
6392
6455
  profileComponent: profileComponent$1
6393
6456
  };
6394
6457
 
@@ -6403,13 +6466,13 @@ var profileComponent = {
6403
6466
  photoDeleted: "Фото удалено",
6404
6467
  failedToDeletePhoto: "Не удалось удалить фото пользователя"
6405
6468
  };
6406
- var ru$7 = {
6469
+ var ru$8 = {
6407
6470
  profileComponent: profileComponent
6408
6471
  };
6409
6472
 
6410
6473
  class UserProfileComponent {
6411
6474
  constructor() {
6412
- this.translations = provideTranslations({ en: en$7, ru: ru$7 });
6475
+ this.translations = provideTranslations({ en: en$8, ru: ru$8 });
6413
6476
  this.userService = inject(UserService);
6414
6477
  this.msgService = inject(MsgService);
6415
6478
  this.translateService = inject(TranslateService);
@@ -6491,7 +6554,7 @@ class UserProfileComponent {
6491
6554
  (onClick)="confirmDeletePhoto($event)" />
6492
6555
  }
6493
6556
  </div>
6494
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: FileUploadModule }, { kind: "component", type: i1$8.FileUpload, selector: "p-fileupload, p-fileUpload", inputs: ["name", "url", "method", "multiple", "accept", "disabled", "auto", "withCredentials", "maxFileSize", "invalidFileSizeMessageSummary", "invalidFileSizeMessageDetail", "invalidFileTypeMessageSummary", "invalidFileTypeMessageDetail", "invalidFileLimitMessageDetail", "invalidFileLimitMessageSummary", "style", "styleClass", "previewWidth", "chooseLabel", "uploadLabel", "cancelLabel", "chooseIcon", "uploadIcon", "cancelIcon", "showUploadButton", "showCancelButton", "mode", "headers", "customUpload", "fileLimit", "uploadStyleClass", "cancelStyleClass", "removeStyleClass", "chooseStyleClass", "chooseButtonProps", "uploadButtonProps", "cancelButtonProps", "files"], outputs: ["onBeforeUpload", "onSend", "onUpload", "onError", "onClear", "onRemove", "onSelect", "onProgress", "uploadHandler", "onImageError", "onRemoveUploadedFile"] }, { kind: "ngmodule", type: ImageModule }, { kind: "ngmodule", type: AvatarModule }, { kind: "component", type: i2$2.Avatar, selector: "p-avatar", inputs: ["label", "icon", "image", "size", "shape", "styleClass", "ariaLabel", "ariaLabelledBy"], outputs: ["onImageError"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: ConfirmDialog, selector: "p-confirmDialog, p-confirmdialog, p-confirm-dialog", inputs: ["header", "icon", "message", "style", "styleClass", "maskStyleClass", "acceptIcon", "acceptLabel", "closeAriaLabel", "acceptAriaLabel", "acceptVisible", "rejectIcon", "rejectLabel", "rejectAriaLabel", "rejectVisible", "acceptButtonStyleClass", "rejectButtonStyleClass", "closeOnEscape", "dismissableMask", "blockScroll", "rtl", "closable", "appendTo", "key", "autoZIndex", "baseZIndex", "transitionOptions", "focusTrap", "defaultFocus", "breakpoints", "modal", "visible", "position", "draggable"], outputs: ["onHide"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
6557
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: FileUploadModule }, { kind: "component", type: i1$8.FileUpload, selector: "p-fileupload, p-fileUpload", inputs: ["name", "url", "method", "multiple", "accept", "disabled", "auto", "withCredentials", "maxFileSize", "invalidFileSizeMessageSummary", "invalidFileSizeMessageDetail", "invalidFileTypeMessageSummary", "invalidFileTypeMessageDetail", "invalidFileLimitMessageDetail", "invalidFileLimitMessageSummary", "style", "styleClass", "previewWidth", "chooseLabel", "uploadLabel", "cancelLabel", "chooseIcon", "uploadIcon", "cancelIcon", "showUploadButton", "showCancelButton", "mode", "headers", "customUpload", "fileLimit", "uploadStyleClass", "cancelStyleClass", "removeStyleClass", "chooseStyleClass", "chooseButtonProps", "uploadButtonProps", "cancelButtonProps", "files"], outputs: ["onBeforeUpload", "onSend", "onUpload", "onError", "onClear", "onRemove", "onSelect", "onProgress", "uploadHandler", "onImageError", "onRemoveUploadedFile"] }, { kind: "ngmodule", type: ImageModule }, { kind: "ngmodule", type: AvatarModule }, { kind: "component", type: i2$1.Avatar, selector: "p-avatar", inputs: ["label", "icon", "image", "size", "shape", "styleClass", "ariaLabel", "ariaLabelledBy"], outputs: ["onImageError"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: ConfirmDialog, selector: "p-confirmDialog, p-confirmdialog, p-confirm-dialog", inputs: ["header", "icon", "message", "style", "styleClass", "maskStyleClass", "acceptIcon", "acceptLabel", "closeAriaLabel", "acceptAriaLabel", "acceptVisible", "rejectIcon", "rejectLabel", "rejectAriaLabel", "rejectVisible", "acceptButtonStyleClass", "rejectButtonStyleClass", "closeOnEscape", "dismissableMask", "blockScroll", "rtl", "closable", "appendTo", "key", "autoZIndex", "baseZIndex", "transitionOptions", "focusTrap", "defaultFocus", "breakpoints", "modal", "visible", "position", "draggable"], outputs: ["onHide"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
6495
6558
  }
6496
6559
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: UserProfileComponent, decorators: [{
6497
6560
  type: Component,
@@ -6544,6 +6607,7 @@ var config$1 = {
6544
6607
  applicationManagement: "Application management",
6545
6608
  dateFormat: "Date format",
6546
6609
  dateTimeFormat: "Date and time format:",
6610
+ firstDayOfWeek: "First day of the week",
6547
6611
  goTo: "Go to",
6548
6612
  localization: "Localization",
6549
6613
  menu: "Menu",
@@ -6551,11 +6615,12 @@ var config$1 = {
6551
6615
  photo: "Photo",
6552
6616
  profile: "Profile",
6553
6617
  selectLanguage: "Select language",
6618
+ sessionManagement: "Session management",
6554
6619
  timeFormat: "Time format",
6555
6620
  timeZone: "Time zone",
6556
6621
  usePhoto256x256Pixel: "Use photo 256x256 pixel"
6557
6622
  };
6558
- var en$6 = {
6623
+ var en$7 = {
6559
6624
  config: config$1
6560
6625
  };
6561
6626
 
@@ -6564,6 +6629,7 @@ var config = {
6564
6629
  applicationManagement: "Управление приложениями",
6565
6630
  dateFormat: "Формат даты",
6566
6631
  dateTimeFormat: "Формат даты и времени:",
6632
+ firstDayOfWeek: "Первый день недели",
6567
6633
  goTo: "Перейти",
6568
6634
  localization: "Локализация",
6569
6635
  menu: "Меню",
@@ -6571,17 +6637,18 @@ var config = {
6571
6637
  photo: "Фото",
6572
6638
  profile: "Профиль",
6573
6639
  selectLanguage: "Выберите язык",
6640
+ sessionManagement: "Управление сессиями",
6574
6641
  timeFormat: "Формат времени",
6575
6642
  timeZone: "Часовой пояс",
6576
6643
  usePhoto256x256Pixel: "Используйте фото 256x256 пикселей"
6577
6644
  };
6578
- var ru$6 = {
6645
+ var ru$7 = {
6579
6646
  config: config
6580
6647
  };
6581
6648
 
6582
6649
  class ConfigComponent {
6583
6650
  constructor() {
6584
- this.translations = provideTranslations({ en: en$6, ru: ru$6 });
6651
+ this.translations = provideTranslations({ en: en$7, ru: ru$7 });
6585
6652
  this.layoutService = inject(LayoutService);
6586
6653
  this.l10nService = inject(L10nService);
6587
6654
  this.userService = inject(UserService);
@@ -6591,10 +6658,20 @@ class ConfigComponent {
6591
6658
  this.timeFormats = ['HH:mm:ss', 'HH:mm'];
6592
6659
  // @ts-ignore
6593
6660
  this.allTimeZones = Intl.supportedValuesOf('timeZone');
6661
+ /** Days of the week starting from Monday, named in the current language. */
6662
+ this.weekDays = computed(() => {
6663
+ const format = new Intl.DateTimeFormat(this.layoutService.language() ?? 'en', { weekday: 'long' });
6664
+ // 1 January 2024 is a Monday, so day N of that week falls on N January (Sunday - on 7 January).
6665
+ return [1, 2, 3, 4, 5, 6, 0].map((day) => {
6666
+ const name = format.format(new Date(2024, 0, day || 7));
6667
+ return { value: day, label: name.charAt(0).toUpperCase() + name.slice(1) };
6668
+ });
6669
+ }, ...(ngDevMode ? [{ debugName: "weekDays" }] : []));
6594
6670
  this.selectedLanguage = this.layoutService.language();
6595
6671
  this.selectedDateFormat = this.layoutService.dateFormat();
6596
6672
  this.selectedTimeFormat = this.layoutService.timeFormat();
6597
6673
  this.selectedTimeZone = this.layoutService.timeZone();
6674
+ this.selectedFirstDayOfWeek = this.layoutService.firstDayOfWeek();
6598
6675
  }
6599
6676
  changeLanguage() {
6600
6677
  this.layoutService.layoutConfig.update((config) => ({
@@ -6609,6 +6686,9 @@ class ConfigComponent {
6609
6686
  changeTimeFormat() {
6610
6687
  this.layoutService.layoutConfig.update((config) => ({ ...config, timeFormat: this.selectedTimeFormat }));
6611
6688
  }
6689
+ changeFirstDayOfWeek() {
6690
+ this.layoutService.layoutConfig.update((config) => ({ ...config, firstDayOfWeek: this.selectedFirstDayOfWeek }));
6691
+ }
6612
6692
  changeTimeZone() {
6613
6693
  this.layoutService.layoutConfig.update((config) => ({ ...config, timeZone: this.selectedTimeZone }));
6614
6694
  }
@@ -6679,6 +6759,16 @@ class ConfigComponent {
6679
6759
  [placeholder]="'config.timeFormat' | translate"
6680
6760
  [(ngModel)]="selectedTimeFormat"
6681
6761
  (onChange)="changeTimeFormat()" />
6762
+ <div class="mt-5">{{ 'config.firstDayOfWeek' | translate }}</div>
6763
+ <p-select
6764
+ class="w-full md:w-56"
6765
+ optionLabel="label"
6766
+ optionValue="value"
6767
+ qa-id="oip-app-config-first-day-of-week-select"
6768
+ [options]="weekDays()"
6769
+ [placeholder]="'config.firstDayOfWeek' | translate"
6770
+ [(ngModel)]="selectedFirstDayOfWeek"
6771
+ (onChange)="changeFirstDayOfWeek()" />
6682
6772
  <div class="mt-5">{{ 'config.timeZone' | translate }}</div>
6683
6773
  <p-select
6684
6774
  class="w-full md:w-56"
@@ -6716,11 +6806,19 @@ class ConfigComponent {
6716
6806
  label="{{ 'config.goTo' | translate }}"
6717
6807
  routerLink="/applications" />
6718
6808
  </div>
6809
+ <div class="flex items-center gap-2">
6810
+ <label for="oip-app-config-sessions-link">{{ 'config.sessionManagement' | translate }}</label>
6811
+ <p-button
6812
+ icon="pi pi-users"
6813
+ id="oip-app-config-sessions-link"
6814
+ label="{{ 'config.goTo' | translate }}"
6815
+ routerLink="/sessions" />
6816
+ </div>
6719
6817
  </div>
6720
6818
  </div>
6721
6819
  }
6722
6820
  </div>
6723
- `, isInline: true, dependencies: [{ kind: "component", type: UserProfileComponent, selector: "user-profile" }, { kind: "directive", type: Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: TableModule }, { kind: "ngmodule", type: ToggleSwitchModule }, { kind: "component", type: i2$4.ToggleSwitch, selector: "p-toggleswitch, p-toggleSwitch, p-toggle-switch", inputs: ["styleClass", "tabindex", "inputId", "readonly", "trueValue", "falseValue", "ariaLabel", "size", "ariaLabelledBy", "autofocus"], outputs: ["onChange"] }, { kind: "component", type: Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
6821
+ `, isInline: true, dependencies: [{ kind: "component", type: UserProfileComponent, selector: "user-profile" }, { kind: "directive", type: Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: TableModule }, { kind: "ngmodule", type: ToggleSwitchModule }, { kind: "component", type: i2$3.ToggleSwitch, selector: "p-toggleswitch, p-toggleSwitch, p-toggle-switch", inputs: ["styleClass", "tabindex", "inputId", "readonly", "trueValue", "falseValue", "ariaLabel", "size", "ariaLabelledBy", "autofocus"], outputs: ["onChange"] }, { kind: "component", type: Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
6724
6822
  }
6725
6823
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: ConfigComponent, decorators: [{
6726
6824
  type: Component,
@@ -6789,6 +6887,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
6789
6887
  [placeholder]="'config.timeFormat' | translate"
6790
6888
  [(ngModel)]="selectedTimeFormat"
6791
6889
  (onChange)="changeTimeFormat()" />
6890
+ <div class="mt-5">{{ 'config.firstDayOfWeek' | translate }}</div>
6891
+ <p-select
6892
+ class="w-full md:w-56"
6893
+ optionLabel="label"
6894
+ optionValue="value"
6895
+ qa-id="oip-app-config-first-day-of-week-select"
6896
+ [options]="weekDays()"
6897
+ [placeholder]="'config.firstDayOfWeek' | translate"
6898
+ [(ngModel)]="selectedFirstDayOfWeek"
6899
+ (onChange)="changeFirstDayOfWeek()" />
6792
6900
  <div class="mt-5">{{ 'config.timeZone' | translate }}</div>
6793
6901
  <p-select
6794
6902
  class="w-full md:w-56"
@@ -6826,6 +6934,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
6826
6934
  label="{{ 'config.goTo' | translate }}"
6827
6935
  routerLink="/applications" />
6828
6936
  </div>
6937
+ <div class="flex items-center gap-2">
6938
+ <label for="oip-app-config-sessions-link">{{ 'config.sessionManagement' | translate }}</label>
6939
+ <p-button
6940
+ icon="pi pi-users"
6941
+ id="oip-app-config-sessions-link"
6942
+ label="{{ 'config.goTo' | translate }}"
6943
+ routerLink="/sessions" />
6944
+ </div>
6829
6945
  </div>
6830
6946
  </div>
6831
6947
  }
@@ -6850,12 +6966,12 @@ var config_component = /*#__PURE__*/Object.freeze({
6850
6966
  ConfigComponent: ConfigComponent
6851
6967
  });
6852
6968
 
6853
- var en$5 = {
6969
+ var en$6 = {
6854
6970
  "db-migration": {
6855
6971
  migrationManager: "Migration manager",
6856
6972
  actions: {
6857
6973
  refresh: "Refresh",
6858
- cleanFilter: "Clean filter",
6974
+ cleanFilter: "Clear filter",
6859
6975
  applyMigration: "Apply migration"
6860
6976
  },
6861
6977
  columns: {
@@ -6866,16 +6982,20 @@ var en$5 = {
6866
6982
  },
6867
6983
  messages: {
6868
6984
  errorRefreshing: "Error refreshing database"
6869
- }
6985
+ },
6986
+ filterPlaceholder: "Filter by migration name",
6987
+ empty: "No migrations",
6988
+ yes: "Yes",
6989
+ no: "No"
6870
6990
  }
6871
6991
  };
6872
6992
 
6873
- var ru$5 = {
6993
+ var ru$6 = {
6874
6994
  "db-migration": {
6875
6995
  migrationManager: "Менеджер миграций",
6876
6996
  actions: {
6877
6997
  refresh: "Обновить",
6878
- cleanFilter: "Очистить фильтр",
6998
+ cleanFilter: "Сбросить фильтр",
6879
6999
  applyMigration: "Применить миграцию"
6880
7000
  },
6881
7001
  columns: {
@@ -6886,28 +7006,48 @@ var ru$5 = {
6886
7006
  },
6887
7007
  messages: {
6888
7008
  errorRefreshing: "Ошибка обновления базы данных"
6889
- }
7009
+ },
7010
+ filterPlaceholder: "Фильтр по имени миграции",
7011
+ empty: "Нет миграций",
7012
+ yes: "Да",
7013
+ no: "Нет"
6890
7014
  }
6891
7015
  };
6892
7016
 
6893
7017
  class DbMigrationComponent extends BaseModuleComponent {
6894
7018
  constructor() {
6895
7019
  super(...arguments);
6896
- this.translations = provideTranslations({ en: en$5, ru: ru$5 });
7020
+ this.translations = provideTranslations({ en: en$6, ru: ru$6 });
7021
+ this.data = [];
7022
+ this.loading = false;
7023
+ this.globalFilter = '';
6897
7024
  }
6898
7025
  async ngOnInit() {
6899
7026
  await super.ngOnInit();
6900
7027
  await this.refreshAction();
6901
7028
  }
6902
7029
  async refreshAction() {
6903
- this.getData()
6904
- .then((response) => {
6905
- this.data = response;
6906
- })
6907
- .catch((error) => {
7030
+ this.loading = true;
7031
+ try {
7032
+ this.data = await this.getData();
7033
+ }
7034
+ catch (error) {
6908
7035
  console.log(error);
6909
7036
  this.msgService.error(this.l10nService.instant('db-migration.messages.errorRefreshing'));
6910
- });
7037
+ }
7038
+ finally {
7039
+ this.loading = false;
7040
+ }
7041
+ }
7042
+ get hasActiveFilters() {
7043
+ if (!this.dt?.filters)
7044
+ return false;
7045
+ return Object.values(this.dt.filters).some((meta) => (Array.isArray(meta) ? meta : [meta]).some((m) => m?.value !== null && m?.value !== undefined && m?.value !== ''));
7046
+ }
7047
+ clearFilter() {
7048
+ this.globalFilter = '';
7049
+ this.dt.clearFilterValues();
7050
+ this.dt._filter();
6911
7051
  }
6912
7052
  async getData() {
6913
7053
  return this.getMigrations();
@@ -6917,85 +7057,125 @@ class DbMigrationComponent extends BaseModuleComponent {
6917
7057
  return this.applyModuleMigration(request);
6918
7058
  }
6919
7059
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DbMigrationComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
6920
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: DbMigrationComponent, isStandalone: true, selector: "db-migration", providers: [ConfirmationService], usesInheritance: true, ngImport: i0, template: `
7060
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: DbMigrationComponent, isStandalone: true, selector: "db-migration", providers: [ConfirmationService], viewQueries: [{ propertyName: "dt", first: true, predicate: ["dt"], descendants: true }], usesInheritance: true, ngImport: i0, template: `
6921
7061
  @if (isContent) {
6922
- <div class="card" style="height: 100%">
6923
- <p-confirmDialog />
6924
- <div>
6925
- <h5>{{ 'db-migration.migrationManager' | translate }}</h5>
6926
- <div class="flex flex-row gap-2">
6927
- <p-button
6928
- icon="pi pi-refresh"
6929
- severity="secondary"
6930
- tooltipPosition="bottom"
6931
- [outlined]="true"
6932
- [pTooltip]="'db-migration.actions.refresh' | translate"
6933
- (click)="refreshAction()" />
6934
- <p-button
6935
- icon="pi pi-filter-slash"
6936
- severity="secondary"
6937
- tooltipPosition="bottom"
6938
- [outlined]="true"
6939
- [pTooltip]="'db-migration.actions.cleanFilter' | translate"
6940
- (click)="dt.clear()" />
6941
- </div>
6942
- <div>
6943
- <p-table #dt dataKey="name" editMode="row" size="small" [scrollable]="true" [value]="data">
6944
- <ng-template let-columns pTemplate="header">
6945
- <tr>
6946
- <th pSortableColumn="name" scope="col">
6947
- {{ 'db-migration.columns.name' | translate }}
6948
- <p-columnFilter display="menu" field="name" type="text" />
6949
- </th>
6950
- <th scope="col">{{ 'db-migration.columns.applied' | translate }}</th>
6951
- <th scope="col">{{ 'db-migration.columns.exist' | translate }}</th>
6952
- <th scope="col">{{ 'db-migration.columns.pending' | translate }}</th>
6953
- <th scope="col"></th>
6954
- </tr>
6955
- </ng-template>
7062
+ <p-confirmDialog />
7063
+ <div class="flex flex-col md:flex-row gap-4">
7064
+ <div class="card w-full">
7065
+ <div class="mb-4">
7066
+ <p-toolbar>
7067
+ <div class="flex flex-col md:flex-row md:items-center gap-2 w-full">
7068
+ <div class="font-semibold text-lg flex items-center gap-2 mx-2">
7069
+ <i class="pi pi-database"></i>
7070
+ {{ 'db-migration.migrationManager' | translate }}
7071
+ </div>
6956
7072
 
6957
- <ng-template #body let-columns="columns" let-editing="editing" let-ri="rowIndex" let-rowData>
6958
- <tr [pEditableRow]="rowData">
6959
- <td>
6960
- {{ rowData.name }}
6961
- </td>
6962
- <td>
6963
- @if (rowData.applied) {
6964
- <p-button icon="pi pi-check" severity="success" [rounded]="true" [text]="true"></p-button>
6965
- }
6966
- </td>
6967
- <td>
6968
- @if (rowData.exist) {
6969
- <p-button icon="pi pi-check" severity="success" [rounded]="true" [text]="true" />
6970
- }
6971
- </td>
6972
- <td>
6973
- @if (rowData.pending) {
6974
- <p-button icon="pi pi-check" severity="success" [rounded]="true" [text]="true"></p-button>
6975
- }
6976
- </td>
6977
- <td>
6978
- <p-button
6979
- icon="pi pi-bolt"
6980
- pCancelEditableRow
6981
- pTooltip="{{ 'db-migration.actions.applyMigration' | translate }}"
6982
- severity="secondary"
6983
- tooltipPosition="left"
6984
- [rounded]="true"
6985
- [text]="true"
6986
- (click)="applyMigration(rowData)">
6987
- </p-button>
6988
- </td>
6989
- </tr>
6990
- </ng-template>
6991
- </p-table>
7073
+ <div class="flex-1"></div>
7074
+ <div class="flex items-center gap-1 w-full md:w-auto">
7075
+ <p-button
7076
+ icon="pi pi-refresh"
7077
+ rounded="true"
7078
+ severity="secondary"
7079
+ text="true"
7080
+ tooltipPosition="bottom"
7081
+ [loading]="loading"
7082
+ [pTooltip]="'db-migration.actions.refresh' | translate"
7083
+ (onClick)="refreshAction()"></p-button>
7084
+ <input
7085
+ class="w-full md:w-96"
7086
+ pInputText
7087
+ type="text"
7088
+ [placeholder]="'db-migration.filterPlaceholder' | translate"
7089
+ [(ngModel)]="globalFilter"
7090
+ (ngModelChange)="dt.filterGlobal($event, 'contains')" />
7091
+ <p-button
7092
+ icon="pi pi-filter-slash"
7093
+ rounded="true"
7094
+ severity="secondary"
7095
+ text="true"
7096
+ tooltipPosition="bottom"
7097
+ [disabled]="!hasActiveFilters"
7098
+ [pTooltip]="'db-migration.actions.cleanFilter' | translate"
7099
+ (onClick)="clearFilter()"></p-button>
7100
+ </div>
7101
+ </div>
7102
+ </p-toolbar>
6992
7103
  </div>
7104
+ <p-table
7105
+ #dt
7106
+ class="mt-4"
7107
+ dataKey="name"
7108
+ sortField="name"
7109
+ [sortOrder]="1"
7110
+ [paginator]="true"
7111
+ [rows]="50"
7112
+ [globalFilterFields]="['name']"
7113
+ [value]="data"
7114
+ [loading]="loading">
7115
+ <ng-template pTemplate="header">
7116
+ <tr>
7117
+ <th pSortableColumn="name" scope="col">
7118
+ {{ 'db-migration.columns.name' | translate }}
7119
+ <p-sortIcon field="name"></p-sortIcon>
7120
+ <p-columnFilter display="menu" field="name" type="text" />
7121
+ </th>
7122
+ <th pSortableColumn="applied" scope="col">
7123
+ {{ 'db-migration.columns.applied' | translate }}
7124
+ <p-sortIcon field="applied"></p-sortIcon>
7125
+ </th>
7126
+ <th pSortableColumn="exist" scope="col">
7127
+ {{ 'db-migration.columns.exist' | translate }}
7128
+ <p-sortIcon field="exist"></p-sortIcon>
7129
+ </th>
7130
+ <th pSortableColumn="pending" scope="col">
7131
+ {{ 'db-migration.columns.pending' | translate }}
7132
+ <p-sortIcon field="pending"></p-sortIcon>
7133
+ </th>
7134
+ <th style="width: 4rem" scope="col"></th>
7135
+ </tr>
7136
+ </ng-template>
7137
+ <ng-template let-migration pTemplate="body">
7138
+ <tr>
7139
+ <td>{{ migration.name }}</td>
7140
+ <td>
7141
+ <p-tag
7142
+ [severity]="migration.applied ? 'success' : 'secondary'"
7143
+ [value]="(migration.applied ? 'db-migration.yes' : 'db-migration.no') | translate"></p-tag>
7144
+ </td>
7145
+ <td>
7146
+ <p-tag
7147
+ [severity]="migration.exist ? 'success' : 'secondary'"
7148
+ [value]="(migration.exist ? 'db-migration.yes' : 'db-migration.no') | translate"></p-tag>
7149
+ </td>
7150
+ <td>
7151
+ <p-tag
7152
+ [severity]="migration.pending ? 'warn' : 'secondary'"
7153
+ [value]="(migration.pending ? 'db-migration.yes' : 'db-migration.no') | translate"></p-tag>
7154
+ </td>
7155
+ <td>
7156
+ <p-button
7157
+ icon="pi pi-bolt"
7158
+ rounded="true"
7159
+ severity="secondary"
7160
+ text="true"
7161
+ tooltipPosition="left"
7162
+ [pTooltip]="'db-migration.actions.applyMigration' | translate"
7163
+ (onClick)="applyMigration(migration)"></p-button>
7164
+ </td>
7165
+ </tr>
7166
+ </ng-template>
7167
+ <ng-template pTemplate="emptymessage">
7168
+ <tr>
7169
+ <td colspan="5">{{ 'db-migration.empty' | translate }}</td>
7170
+ </tr>
7171
+ </ng-template>
7172
+ </p-table>
6993
7173
  </div>
6994
7174
  </div>
6995
7175
  } @else if (isSecurity) {
6996
7176
  <security [controller]="controller" [id]="id" />
6997
7177
  }
6998
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: TableModule }, { kind: "component", type: i1$9.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "directive", type: i2$1.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "directive", type: i1$9.SortableColumn, selector: "[pSortableColumn]", inputs: ["pSortableColumn", "pSortableColumnDisabled"] }, { kind: "directive", type: i1$9.EditableRow, selector: "[pEditableRow]", inputs: ["pEditableRow", "pEditableRowDisabled"] }, { kind: "directive", type: i1$9.CancelEditableRow, selector: "[pCancelEditableRow]" }, { kind: "component", type: i1$9.ColumnFilter, selector: "p-columnFilter, p-column-filter, p-columnfilter", inputs: ["field", "type", "display", "showMenu", "matchMode", "operator", "showOperator", "showClearButton", "showApplyButton", "showMatchModes", "showAddButton", "hideOnClear", "placeholder", "matchModeOptions", "maxConstraints", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "locale", "localeMatcher", "currency", "currencyDisplay", "filterOn", "useGrouping", "showButtons", "ariaLabel", "filterButtonProps"], outputs: ["onShow", "onHide"] }, { kind: "ngmodule", type: SharedModule }, { kind: "ngmodule", type: TagModule }, { kind: "ngmodule", type: InputTextModule }, { kind: "ngmodule", type: TextareaModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: ConfirmDialog, selector: "p-confirmDialog, p-confirmdialog, p-confirm-dialog", inputs: ["header", "icon", "message", "style", "styleClass", "maskStyleClass", "acceptIcon", "acceptLabel", "closeAriaLabel", "acceptAriaLabel", "acceptVisible", "rejectIcon", "rejectLabel", "rejectAriaLabel", "rejectVisible", "acceptButtonStyleClass", "rejectButtonStyleClass", "closeOnEscape", "dismissableMask", "blockScroll", "rtl", "closable", "appendTo", "key", "autoZIndex", "baseZIndex", "transitionOptions", "focusTrap", "defaultFocus", "breakpoints", "modal", "visible", "position", "draggable"], outputs: ["onHide"] }, { kind: "component", type: SecurityComponent, selector: "security", inputs: ["id", "controller"] }, { kind: "directive", type: Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
7178
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: TableModule }, { kind: "component", type: i2$4.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "directive", type: i3$1.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "directive", type: i2$4.SortableColumn, selector: "[pSortableColumn]", inputs: ["pSortableColumn", "pSortableColumnDisabled"] }, { kind: "component", type: i2$4.SortIcon, selector: "p-sortIcon", inputs: ["field"] }, { kind: "component", type: i2$4.ColumnFilter, selector: "p-columnFilter, p-column-filter, p-columnfilter", inputs: ["field", "type", "display", "showMenu", "matchMode", "operator", "showOperator", "showClearButton", "showApplyButton", "showMatchModes", "showAddButton", "hideOnClear", "placeholder", "matchModeOptions", "maxConstraints", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "locale", "localeMatcher", "currency", "currencyDisplay", "filterOn", "useGrouping", "showButtons", "ariaLabel", "filterButtonProps"], outputs: ["onShow", "onHide"] }, { kind: "ngmodule", type: SharedModule }, { kind: "ngmodule", type: TagModule }, { kind: "component", type: i3$6.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i4$1.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: ToolbarModule }, { kind: "component", type: i5$1.Toolbar, selector: "p-toolbar", inputs: ["styleClass", "ariaLabelledBy"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: ConfirmDialog, selector: "p-confirmDialog, p-confirmdialog, p-confirm-dialog", inputs: ["header", "icon", "message", "style", "styleClass", "maskStyleClass", "acceptIcon", "acceptLabel", "closeAriaLabel", "acceptAriaLabel", "acceptVisible", "rejectIcon", "rejectLabel", "rejectAriaLabel", "rejectVisible", "acceptButtonStyleClass", "rejectButtonStyleClass", "closeOnEscape", "dismissableMask", "blockScroll", "rtl", "closable", "appendTo", "key", "autoZIndex", "baseZIndex", "transitionOptions", "focusTrap", "defaultFocus", "breakpoints", "modal", "visible", "position", "draggable"], outputs: ["onHide"] }, { kind: "component", type: SecurityComponent, selector: "security", inputs: ["id", "controller"] }, { kind: "directive", type: Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
6999
7179
  }
7000
7180
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DbMigrationComponent, decorators: [{
7001
7181
  type: Component,
@@ -7005,8 +7185,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
7005
7185
  SharedModule,
7006
7186
  TagModule,
7007
7187
  InputTextModule,
7008
- TextareaModule,
7009
7188
  ButtonModule,
7189
+ ToolbarModule,
7010
7190
  FormsModule,
7011
7191
  ConfirmDialog,
7012
7192
  SecurityComponent,
@@ -7016,77 +7196,117 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
7016
7196
  selector: 'db-migration',
7017
7197
  template: `
7018
7198
  @if (isContent) {
7019
- <div class="card" style="height: 100%">
7020
- <p-confirmDialog />
7021
- <div>
7022
- <h5>{{ 'db-migration.migrationManager' | translate }}</h5>
7023
- <div class="flex flex-row gap-2">
7024
- <p-button
7025
- icon="pi pi-refresh"
7026
- severity="secondary"
7027
- tooltipPosition="bottom"
7028
- [outlined]="true"
7029
- [pTooltip]="'db-migration.actions.refresh' | translate"
7030
- (click)="refreshAction()" />
7031
- <p-button
7032
- icon="pi pi-filter-slash"
7033
- severity="secondary"
7034
- tooltipPosition="bottom"
7035
- [outlined]="true"
7036
- [pTooltip]="'db-migration.actions.cleanFilter' | translate"
7037
- (click)="dt.clear()" />
7038
- </div>
7039
- <div>
7040
- <p-table #dt dataKey="name" editMode="row" size="small" [scrollable]="true" [value]="data">
7041
- <ng-template let-columns pTemplate="header">
7042
- <tr>
7043
- <th pSortableColumn="name" scope="col">
7044
- {{ 'db-migration.columns.name' | translate }}
7045
- <p-columnFilter display="menu" field="name" type="text" />
7046
- </th>
7047
- <th scope="col">{{ 'db-migration.columns.applied' | translate }}</th>
7048
- <th scope="col">{{ 'db-migration.columns.exist' | translate }}</th>
7049
- <th scope="col">{{ 'db-migration.columns.pending' | translate }}</th>
7050
- <th scope="col"></th>
7051
- </tr>
7052
- </ng-template>
7199
+ <p-confirmDialog />
7200
+ <div class="flex flex-col md:flex-row gap-4">
7201
+ <div class="card w-full">
7202
+ <div class="mb-4">
7203
+ <p-toolbar>
7204
+ <div class="flex flex-col md:flex-row md:items-center gap-2 w-full">
7205
+ <div class="font-semibold text-lg flex items-center gap-2 mx-2">
7206
+ <i class="pi pi-database"></i>
7207
+ {{ 'db-migration.migrationManager' | translate }}
7208
+ </div>
7053
7209
 
7054
- <ng-template #body let-columns="columns" let-editing="editing" let-ri="rowIndex" let-rowData>
7055
- <tr [pEditableRow]="rowData">
7056
- <td>
7057
- {{ rowData.name }}
7058
- </td>
7059
- <td>
7060
- @if (rowData.applied) {
7061
- <p-button icon="pi pi-check" severity="success" [rounded]="true" [text]="true"></p-button>
7062
- }
7063
- </td>
7064
- <td>
7065
- @if (rowData.exist) {
7066
- <p-button icon="pi pi-check" severity="success" [rounded]="true" [text]="true" />
7067
- }
7068
- </td>
7069
- <td>
7070
- @if (rowData.pending) {
7071
- <p-button icon="pi pi-check" severity="success" [rounded]="true" [text]="true"></p-button>
7072
- }
7073
- </td>
7074
- <td>
7075
- <p-button
7076
- icon="pi pi-bolt"
7077
- pCancelEditableRow
7078
- pTooltip="{{ 'db-migration.actions.applyMigration' | translate }}"
7079
- severity="secondary"
7080
- tooltipPosition="left"
7081
- [rounded]="true"
7082
- [text]="true"
7083
- (click)="applyMigration(rowData)">
7084
- </p-button>
7085
- </td>
7086
- </tr>
7087
- </ng-template>
7088
- </p-table>
7210
+ <div class="flex-1"></div>
7211
+ <div class="flex items-center gap-1 w-full md:w-auto">
7212
+ <p-button
7213
+ icon="pi pi-refresh"
7214
+ rounded="true"
7215
+ severity="secondary"
7216
+ text="true"
7217
+ tooltipPosition="bottom"
7218
+ [loading]="loading"
7219
+ [pTooltip]="'db-migration.actions.refresh' | translate"
7220
+ (onClick)="refreshAction()"></p-button>
7221
+ <input
7222
+ class="w-full md:w-96"
7223
+ pInputText
7224
+ type="text"
7225
+ [placeholder]="'db-migration.filterPlaceholder' | translate"
7226
+ [(ngModel)]="globalFilter"
7227
+ (ngModelChange)="dt.filterGlobal($event, 'contains')" />
7228
+ <p-button
7229
+ icon="pi pi-filter-slash"
7230
+ rounded="true"
7231
+ severity="secondary"
7232
+ text="true"
7233
+ tooltipPosition="bottom"
7234
+ [disabled]="!hasActiveFilters"
7235
+ [pTooltip]="'db-migration.actions.cleanFilter' | translate"
7236
+ (onClick)="clearFilter()"></p-button>
7237
+ </div>
7238
+ </div>
7239
+ </p-toolbar>
7089
7240
  </div>
7241
+ <p-table
7242
+ #dt
7243
+ class="mt-4"
7244
+ dataKey="name"
7245
+ sortField="name"
7246
+ [sortOrder]="1"
7247
+ [paginator]="true"
7248
+ [rows]="50"
7249
+ [globalFilterFields]="['name']"
7250
+ [value]="data"
7251
+ [loading]="loading">
7252
+ <ng-template pTemplate="header">
7253
+ <tr>
7254
+ <th pSortableColumn="name" scope="col">
7255
+ {{ 'db-migration.columns.name' | translate }}
7256
+ <p-sortIcon field="name"></p-sortIcon>
7257
+ <p-columnFilter display="menu" field="name" type="text" />
7258
+ </th>
7259
+ <th pSortableColumn="applied" scope="col">
7260
+ {{ 'db-migration.columns.applied' | translate }}
7261
+ <p-sortIcon field="applied"></p-sortIcon>
7262
+ </th>
7263
+ <th pSortableColumn="exist" scope="col">
7264
+ {{ 'db-migration.columns.exist' | translate }}
7265
+ <p-sortIcon field="exist"></p-sortIcon>
7266
+ </th>
7267
+ <th pSortableColumn="pending" scope="col">
7268
+ {{ 'db-migration.columns.pending' | translate }}
7269
+ <p-sortIcon field="pending"></p-sortIcon>
7270
+ </th>
7271
+ <th style="width: 4rem" scope="col"></th>
7272
+ </tr>
7273
+ </ng-template>
7274
+ <ng-template let-migration pTemplate="body">
7275
+ <tr>
7276
+ <td>{{ migration.name }}</td>
7277
+ <td>
7278
+ <p-tag
7279
+ [severity]="migration.applied ? 'success' : 'secondary'"
7280
+ [value]="(migration.applied ? 'db-migration.yes' : 'db-migration.no') | translate"></p-tag>
7281
+ </td>
7282
+ <td>
7283
+ <p-tag
7284
+ [severity]="migration.exist ? 'success' : 'secondary'"
7285
+ [value]="(migration.exist ? 'db-migration.yes' : 'db-migration.no') | translate"></p-tag>
7286
+ </td>
7287
+ <td>
7288
+ <p-tag
7289
+ [severity]="migration.pending ? 'warn' : 'secondary'"
7290
+ [value]="(migration.pending ? 'db-migration.yes' : 'db-migration.no') | translate"></p-tag>
7291
+ </td>
7292
+ <td>
7293
+ <p-button
7294
+ icon="pi pi-bolt"
7295
+ rounded="true"
7296
+ severity="secondary"
7297
+ text="true"
7298
+ tooltipPosition="left"
7299
+ [pTooltip]="'db-migration.actions.applyMigration' | translate"
7300
+ (onClick)="applyMigration(migration)"></p-button>
7301
+ </td>
7302
+ </tr>
7303
+ </ng-template>
7304
+ <ng-template pTemplate="emptymessage">
7305
+ <tr>
7306
+ <td colspan="5">{{ 'db-migration.empty' | translate }}</td>
7307
+ </tr>
7308
+ </ng-template>
7309
+ </p-table>
7090
7310
  </div>
7091
7311
  </div>
7092
7312
  } @else if (isSecurity) {
@@ -7095,7 +7315,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
7095
7315
  `,
7096
7316
  providers: [ConfirmationService]
7097
7317
  }]
7098
- }] });
7318
+ }], propDecorators: { dt: [{
7319
+ type: ViewChild,
7320
+ args: ['dt']
7321
+ }] } });
7099
7322
 
7100
7323
  var dbMigration_component = /*#__PURE__*/Object.freeze({
7101
7324
  __proto__: null,
@@ -7198,7 +7421,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
7198
7421
  type: Injectable
7199
7422
  }] });
7200
7423
 
7201
- var en$4 = {
7424
+ var en$5 = {
7202
7425
  "app-modules": {
7203
7426
  title: "Modules",
7204
7427
  refreshTooltip: "Refresh",
@@ -7212,7 +7435,8 @@ var en$4 = {
7212
7435
  currentlyLoaded: "Currently Loaded",
7213
7436
  yes: "Yes",
7214
7437
  no: "No",
7215
- deleteTooltip: "Delete"
7438
+ deleteTooltip: "Delete",
7439
+ empty: "No modules"
7216
7440
  },
7217
7441
  confirm: {
7218
7442
  header: "Warning",
@@ -7224,12 +7448,15 @@ var en$4 = {
7224
7448
  deleteSuccess: "Module deleted",
7225
7449
  deleteError: "Module delete failed",
7226
7450
  registerError: "External module registration failed",
7227
- registerSuccess: "External module registered"
7228
- }
7451
+ registerSuccess: "External module registered",
7452
+ loadError: "Failed to load modules"
7453
+ },
7454
+ filterPlaceholder: "Filter by ID or name",
7455
+ clearFilterTooltip: "Clear filter"
7229
7456
  }
7230
7457
  };
7231
7458
 
7232
- var ru$4 = {
7459
+ var ru$5 = {
7233
7460
  "app-modules": {
7234
7461
  title: "Модули",
7235
7462
  refreshTooltip: "Обновить",
@@ -7243,7 +7470,8 @@ var ru$4 = {
7243
7470
  currentlyLoaded: "Загружен",
7244
7471
  yes: "Да",
7245
7472
  no: "Нет",
7246
- deleteTooltip: "Удалить"
7473
+ deleteTooltip: "Удалить",
7474
+ empty: "Нет модулей"
7247
7475
  },
7248
7476
  confirm: {
7249
7477
  header: "Внимание",
@@ -7255,15 +7483,20 @@ var ru$4 = {
7255
7483
  deleteSuccess: "Модуль удален",
7256
7484
  deleteError: "Не удалось удалить модуль",
7257
7485
  registerError: "Не удалось зарегистрировать внешний модуль",
7258
- registerSuccess: "Внешний модуль зарегистрирован"
7259
- }
7486
+ registerSuccess: "Внешний модуль зарегистрирован",
7487
+ loadError: "Не удалось загрузить модули"
7488
+ },
7489
+ filterPlaceholder: "Фильтр по ID или имени",
7490
+ clearFilterTooltip: "Сбросить фильтр"
7260
7491
  }
7261
7492
  };
7262
7493
 
7263
- L10nService.registerTranslations({ en: en$4, ru: ru$4 });
7494
+ L10nService.registerTranslations({ en: en$5, ru: ru$5 });
7264
7495
  class AppModulesComponent {
7265
7496
  constructor() {
7266
7497
  this.modules = [];
7498
+ this.moduleFilter = '';
7499
+ this.loading = false;
7267
7500
  this.msgService = inject(MsgService);
7268
7501
  this.confirmationService = inject(ConfirmationService);
7269
7502
  this.l10nService = inject(L10nService);
@@ -7279,8 +7512,24 @@ class AppModulesComponent {
7279
7512
  this.titleService.setTitle(this.t('app-modules.title'));
7280
7513
  await this.refreshAction();
7281
7514
  }
7515
+ get filteredModules() {
7516
+ const filter = this.moduleFilter.trim().toLowerCase();
7517
+ if (!filter) {
7518
+ return this.modules;
7519
+ }
7520
+ return this.modules.filter((module) => [module.moduleId, module.name].some((value) => value?.toString().toLowerCase().includes(filter)));
7521
+ }
7282
7522
  async refreshAction() {
7283
- this.modules = await this.moduleService.getModulesWithLoadStatus();
7523
+ this.loading = true;
7524
+ try {
7525
+ this.modules = await this.moduleService.getModulesWithLoadStatus();
7526
+ }
7527
+ catch (error) {
7528
+ this.msgService.errorFromException(error, this.t('app-modules.messages.loadError'), this.t('app-modules.messages.loadError'));
7529
+ }
7530
+ finally {
7531
+ this.loading = false;
7532
+ }
7284
7533
  }
7285
7534
  get canRegisterExternalModule() {
7286
7535
  return !!this.externalModuleManifestUrl.trim() && !this.registeringExternalModule;
@@ -7343,46 +7592,91 @@ class AppModulesComponent {
7343
7592
  <p-confirmDialog></p-confirmDialog>
7344
7593
  <div class="flex flex-col md:flex-row gap-4">
7345
7594
  <div class="card w-full">
7346
- <div class="font-semibold text-xl mb-4">
7347
- {{ 'app-modules.title' | translate }}
7348
- </div>
7349
7595
  <div class="mb-4">
7350
7596
  <p-toolbar>
7351
7597
  <div class="flex flex-col md:flex-row md:items-center gap-2 w-full">
7352
- <div class="flex flex-col sm:flex-row gap-2 flex-1">
7598
+ <div class="font-semibold text-lg flex items-center gap-2 mx-2">
7599
+ <i class="pi pi-box"></i>
7600
+ {{ 'app-modules.title' | translate }}
7601
+ </div>
7602
+
7603
+ <div class="flex items-center gap-1 flex-1">
7353
7604
  <input
7354
7605
  class="w-full"
7355
7606
  pInputText
7356
7607
  type="url"
7608
+ id="oip-app-modules-manifest-url"
7357
7609
  [disabled]="registeringExternalModule"
7358
7610
  [placeholder]="'app-modules.register.manifestUrlPlaceholder' | translate"
7359
7611
  [(ngModel)]="externalModuleManifestUrl"
7360
7612
  (keydown.enter)="registerExternalModule()" />
7361
7613
  <p-button
7362
7614
  icon="pi pi-plus"
7615
+ rounded="true"
7363
7616
  severity="success"
7617
+ text="true"
7618
+ tooltipPosition="bottom"
7619
+ id="oip-app-modules-register"
7364
7620
  [disabled]="!canRegisterExternalModule"
7365
- [label]="'app-modules.register.button' | translate"
7621
+ [pTooltip]="'app-modules.register.button' | translate"
7366
7622
  [loading]="registeringExternalModule"
7367
7623
  (onClick)="registerExternalModule()"></p-button>
7368
7624
  </div>
7369
- <p-button
7370
- icon="pi pi-refresh"
7371
- rounded="true"
7372
- severity="secondary"
7373
- text="true"
7374
- tooltipPosition="bottom"
7375
- [pTooltip]="'app-modules.refreshTooltip' | translate"
7376
- (onClick)="refreshAction()"></p-button>
7625
+
7626
+ <div class="flex items-center gap-1 w-full md:w-auto">
7627
+ <p-button
7628
+ icon="pi pi-refresh"
7629
+ rounded="true"
7630
+ severity="secondary"
7631
+ text="true"
7632
+ tooltipPosition="bottom"
7633
+ [loading]="loading"
7634
+ [pTooltip]="'app-modules.refreshTooltip' | translate"
7635
+ (onClick)="refreshAction()"></p-button>
7636
+ <input
7637
+ class="w-full md:w-96"
7638
+ pInputText
7639
+ type="text"
7640
+ id="oip-app-modules-filter"
7641
+ [placeholder]="'app-modules.filterPlaceholder' | translate"
7642
+ [(ngModel)]="moduleFilter" />
7643
+ <p-button
7644
+ icon="pi pi-filter-slash"
7645
+ rounded="true"
7646
+ severity="secondary"
7647
+ text="true"
7648
+ tooltipPosition="bottom"
7649
+ id="oip-app-modules-clear-filter"
7650
+ [disabled]="!moduleFilter"
7651
+ [pTooltip]="'app-modules.clearFilterTooltip' | translate"
7652
+ (onClick)="moduleFilter = ''"></p-button>
7653
+ </div>
7377
7654
  </div>
7378
7655
  </p-toolbar>
7379
7656
  </div>
7380
- <p-table class="mt-4" [paginator]="true" [rows]="100" [value]="modules">
7657
+ <p-table
7658
+ class="mt-4"
7659
+ dataKey="moduleId"
7660
+ sortField="name"
7661
+ [sortOrder]="1"
7662
+ [paginator]="true"
7663
+ [rows]="100"
7664
+ [value]="filteredModules"
7665
+ [loading]="loading">
7381
7666
  <ng-template pTemplate="header">
7382
7667
  <tr>
7383
- <th>{{ 'app-modules.table.moduleId' | translate }}</th>
7384
- <th>{{ 'app-modules.table.name' | translate }}</th>
7385
- <th>{{ 'app-modules.table.currentlyLoaded' | translate }}</th>
7668
+ <th pSortableColumn="moduleId">
7669
+ {{ 'app-modules.table.moduleId' | translate }}
7670
+ <p-sortIcon field="moduleId"></p-sortIcon>
7671
+ </th>
7672
+ <th pSortableColumn="name">
7673
+ {{ 'app-modules.table.name' | translate }}
7674
+ <p-sortIcon field="name"></p-sortIcon>
7675
+ </th>
7676
+ <th pSortableColumn="currentlyLoaded">
7677
+ {{ 'app-modules.table.currentlyLoaded' | translate }}
7678
+ <p-sortIcon field="currentlyLoaded"></p-sortIcon>
7679
+ </th>
7386
7680
  <th style="width: 4rem"></th>
7387
7681
  </tr>
7388
7682
  </ng-template>
@@ -7409,10 +7703,15 @@ class AppModulesComponent {
7409
7703
  </td>
7410
7704
  </tr>
7411
7705
  </ng-template>
7706
+ <ng-template pTemplate="emptymessage">
7707
+ <tr>
7708
+ <td colspan="4">{{ 'app-modules.table.empty' | translate }}</td>
7709
+ </tr>
7710
+ </ng-template>
7412
7711
  </p-table>
7413
7712
  </div>
7414
7713
  </div>
7415
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: TableModule }, { kind: "component", type: i1$9.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "directive", type: i2$1.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "component", type: Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: ToolbarModule }, { kind: "component", type: i5$1.Toolbar, selector: "p-toolbar", inputs: ["styleClass", "ariaLabelledBy"] }, { kind: "directive", type: Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip"] }, { kind: "component", type: ConfirmDialog, selector: "p-confirmDialog, p-confirmdialog, p-confirm-dialog", inputs: ["header", "icon", "message", "style", "styleClass", "maskStyleClass", "acceptIcon", "acceptLabel", "closeAriaLabel", "acceptAriaLabel", "acceptVisible", "rejectIcon", "rejectLabel", "rejectAriaLabel", "rejectVisible", "acceptButtonStyleClass", "rejectButtonStyleClass", "closeOnEscape", "dismissableMask", "blockScroll", "rtl", "closable", "appendTo", "key", "autoZIndex", "baseZIndex", "transitionOptions", "focusTrap", "defaultFocus", "breakpoints", "modal", "visible", "position", "draggable"], outputs: ["onHide"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i4$1.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pSize", "variant", "fluid", "invalid"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
7714
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: TableModule }, { kind: "component", type: i2$4.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "directive", type: i3$1.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "directive", type: i2$4.SortableColumn, selector: "[pSortableColumn]", inputs: ["pSortableColumn", "pSortableColumnDisabled"] }, { kind: "component", type: i2$4.SortIcon, selector: "p-sortIcon", inputs: ["field"] }, { kind: "component", type: Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: ToolbarModule }, { kind: "component", type: i5$1.Toolbar, selector: "p-toolbar", inputs: ["styleClass", "ariaLabelledBy"] }, { kind: "directive", type: Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip"] }, { kind: "component", type: ConfirmDialog, selector: "p-confirmDialog, p-confirmdialog, p-confirm-dialog", inputs: ["header", "icon", "message", "style", "styleClass", "maskStyleClass", "acceptIcon", "acceptLabel", "closeAriaLabel", "acceptAriaLabel", "acceptVisible", "rejectIcon", "rejectLabel", "rejectAriaLabel", "rejectVisible", "acceptButtonStyleClass", "rejectButtonStyleClass", "closeOnEscape", "dismissableMask", "blockScroll", "rtl", "closable", "appendTo", "key", "autoZIndex", "baseZIndex", "transitionOptions", "focusTrap", "defaultFocus", "breakpoints", "modal", "visible", "position", "draggable"], outputs: ["onHide"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i4$1.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pSize", "variant", "fluid", "invalid"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
7416
7715
  }
7417
7716
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AppModulesComponent, decorators: [{
7418
7717
  type: Component,
@@ -7434,46 +7733,91 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
7434
7733
  <p-confirmDialog></p-confirmDialog>
7435
7734
  <div class="flex flex-col md:flex-row gap-4">
7436
7735
  <div class="card w-full">
7437
- <div class="font-semibold text-xl mb-4">
7438
- {{ 'app-modules.title' | translate }}
7439
- </div>
7440
7736
  <div class="mb-4">
7441
7737
  <p-toolbar>
7442
7738
  <div class="flex flex-col md:flex-row md:items-center gap-2 w-full">
7443
- <div class="flex flex-col sm:flex-row gap-2 flex-1">
7739
+ <div class="font-semibold text-lg flex items-center gap-2 mx-2">
7740
+ <i class="pi pi-box"></i>
7741
+ {{ 'app-modules.title' | translate }}
7742
+ </div>
7743
+
7744
+ <div class="flex items-center gap-1 flex-1">
7444
7745
  <input
7445
7746
  class="w-full"
7446
7747
  pInputText
7447
7748
  type="url"
7749
+ id="oip-app-modules-manifest-url"
7448
7750
  [disabled]="registeringExternalModule"
7449
7751
  [placeholder]="'app-modules.register.manifestUrlPlaceholder' | translate"
7450
7752
  [(ngModel)]="externalModuleManifestUrl"
7451
7753
  (keydown.enter)="registerExternalModule()" />
7452
7754
  <p-button
7453
7755
  icon="pi pi-plus"
7756
+ rounded="true"
7454
7757
  severity="success"
7758
+ text="true"
7759
+ tooltipPosition="bottom"
7760
+ id="oip-app-modules-register"
7455
7761
  [disabled]="!canRegisterExternalModule"
7456
- [label]="'app-modules.register.button' | translate"
7762
+ [pTooltip]="'app-modules.register.button' | translate"
7457
7763
  [loading]="registeringExternalModule"
7458
7764
  (onClick)="registerExternalModule()"></p-button>
7459
7765
  </div>
7460
- <p-button
7461
- icon="pi pi-refresh"
7462
- rounded="true"
7463
- severity="secondary"
7464
- text="true"
7465
- tooltipPosition="bottom"
7466
- [pTooltip]="'app-modules.refreshTooltip' | translate"
7467
- (onClick)="refreshAction()"></p-button>
7766
+
7767
+ <div class="flex items-center gap-1 w-full md:w-auto">
7768
+ <p-button
7769
+ icon="pi pi-refresh"
7770
+ rounded="true"
7771
+ severity="secondary"
7772
+ text="true"
7773
+ tooltipPosition="bottom"
7774
+ [loading]="loading"
7775
+ [pTooltip]="'app-modules.refreshTooltip' | translate"
7776
+ (onClick)="refreshAction()"></p-button>
7777
+ <input
7778
+ class="w-full md:w-96"
7779
+ pInputText
7780
+ type="text"
7781
+ id="oip-app-modules-filter"
7782
+ [placeholder]="'app-modules.filterPlaceholder' | translate"
7783
+ [(ngModel)]="moduleFilter" />
7784
+ <p-button
7785
+ icon="pi pi-filter-slash"
7786
+ rounded="true"
7787
+ severity="secondary"
7788
+ text="true"
7789
+ tooltipPosition="bottom"
7790
+ id="oip-app-modules-clear-filter"
7791
+ [disabled]="!moduleFilter"
7792
+ [pTooltip]="'app-modules.clearFilterTooltip' | translate"
7793
+ (onClick)="moduleFilter = ''"></p-button>
7794
+ </div>
7468
7795
  </div>
7469
7796
  </p-toolbar>
7470
7797
  </div>
7471
- <p-table class="mt-4" [paginator]="true" [rows]="100" [value]="modules">
7798
+ <p-table
7799
+ class="mt-4"
7800
+ dataKey="moduleId"
7801
+ sortField="name"
7802
+ [sortOrder]="1"
7803
+ [paginator]="true"
7804
+ [rows]="100"
7805
+ [value]="filteredModules"
7806
+ [loading]="loading">
7472
7807
  <ng-template pTemplate="header">
7473
7808
  <tr>
7474
- <th>{{ 'app-modules.table.moduleId' | translate }}</th>
7475
- <th>{{ 'app-modules.table.name' | translate }}</th>
7476
- <th>{{ 'app-modules.table.currentlyLoaded' | translate }}</th>
7809
+ <th pSortableColumn="moduleId">
7810
+ {{ 'app-modules.table.moduleId' | translate }}
7811
+ <p-sortIcon field="moduleId"></p-sortIcon>
7812
+ </th>
7813
+ <th pSortableColumn="name">
7814
+ {{ 'app-modules.table.name' | translate }}
7815
+ <p-sortIcon field="name"></p-sortIcon>
7816
+ </th>
7817
+ <th pSortableColumn="currentlyLoaded">
7818
+ {{ 'app-modules.table.currentlyLoaded' | translate }}
7819
+ <p-sortIcon field="currentlyLoaded"></p-sortIcon>
7820
+ </th>
7477
7821
  <th style="width: 4rem"></th>
7478
7822
  </tr>
7479
7823
  </ng-template>
@@ -7500,6 +7844,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
7500
7844
  </td>
7501
7845
  </tr>
7502
7846
  </ng-template>
7847
+ <ng-template pTemplate="emptymessage">
7848
+ <tr>
7849
+ <td colspan="4">{{ 'app-modules.table.empty' | translate }}</td>
7850
+ </tr>
7851
+ </ng-template>
7503
7852
  </p-table>
7504
7853
  </div>
7505
7854
  </div>
@@ -7512,6 +7861,580 @@ var appModules_component = /*#__PURE__*/Object.freeze({
7512
7861
  AppModulesComponent: AppModulesComponent
7513
7862
  });
7514
7863
 
7864
+ /* eslint-disable */
7865
+ /* tslint:disable */
7866
+ // @ts-nocheck
7867
+ class AuthSessionsApi extends HttpClient {
7868
+ constructor() {
7869
+ super(...arguments);
7870
+ this.getAuthSessions = (query, params = {}) => this.request({
7871
+ path: `/api/auth-sessions/get-auth-sessions`,
7872
+ method: "GET",
7873
+ query: query,
7874
+ secure: true,
7875
+ format: "json",
7876
+ ...params,
7877
+ });
7878
+ this.deleteAuthSession = ({ sessionId, ...query }, params = {}) => this.request({
7879
+ path: `/api/auth-sessions/delete-auth-session/${sessionId}`,
7880
+ method: "DELETE",
7881
+ secure: true,
7882
+ ...params,
7883
+ });
7884
+ this.deleteAuthSessionsByUser = ({ userId, ...query }, params = {}) => this.request({
7885
+ path: `/api/auth-sessions/delete-auth-sessions-by-user/${userId}`,
7886
+ method: "DELETE",
7887
+ secure: true,
7888
+ format: "json",
7889
+ ...params,
7890
+ });
7891
+ this.deleteAllAuthSessions = (params = {}) => this.request({
7892
+ path: `/api/auth-sessions/delete-all-auth-sessions`,
7893
+ method: "DELETE",
7894
+ secure: true,
7895
+ format: "json",
7896
+ ...params,
7897
+ });
7898
+ }
7899
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AuthSessionsApi, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
7900
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AuthSessionsApi }); }
7901
+ }
7902
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AuthSessionsApi, decorators: [{
7903
+ type: Injectable
7904
+ }] });
7905
+
7906
+ var en$4 = {
7907
+ "auth-sessions": {
7908
+ title: "Active sessions",
7909
+ refreshTooltip: "Refresh",
7910
+ filterPlaceholder: "Filter by user, email or IP address",
7911
+ table: {
7912
+ user: "User",
7913
+ created: "Signed in",
7914
+ lastActivity: "Last activity",
7915
+ expires: "Expires",
7916
+ ipAddress: "IP address",
7917
+ userAgent: "Browser",
7918
+ current: "Current",
7919
+ terminateTooltip: "Terminate session",
7920
+ terminateAllTooltip: "Terminate all user sessions",
7921
+ empty: "No active sessions"
7922
+ },
7923
+ confirm: {
7924
+ header: "Warning",
7925
+ terminateMessage: "Terminate the session of {{user}}?",
7926
+ terminateAllMessage: "Terminate all sessions of {{user}}?",
7927
+ cancel: "Cancel",
7928
+ terminate: "Terminate",
7929
+ terminateEveryoneMessage: "Terminate all sessions except the current one?"
7930
+ },
7931
+ messages: {
7932
+ loadError: "Failed to load sessions",
7933
+ terminateSuccess: "Session terminated",
7934
+ terminateAllSuccess: "Sessions terminated: {{count}}",
7935
+ terminateError: "Session termination failed"
7936
+ },
7937
+ terminateAllTooltip: "Terminate all except current",
7938
+ clearFilterTooltip: "Clear filter"
7939
+ }
7940
+ };
7941
+
7942
+ var ru$4 = {
7943
+ "auth-sessions": {
7944
+ title: "Активные сессии",
7945
+ refreshTooltip: "Обновить",
7946
+ filterPlaceholder: "Фильтр по пользователю, email или IP-адресу",
7947
+ table: {
7948
+ user: "Пользователь",
7949
+ created: "Вход",
7950
+ lastActivity: "Последняя активность",
7951
+ expires: "Истекает",
7952
+ ipAddress: "IP-адрес",
7953
+ userAgent: "Браузер",
7954
+ current: "Текущая",
7955
+ terminateTooltip: "Завершить сессию",
7956
+ terminateAllTooltip: "Завершить все сессии пользователя",
7957
+ empty: "Активных сессий нет"
7958
+ },
7959
+ confirm: {
7960
+ header: "Внимание",
7961
+ terminateMessage: "Завершить сессию пользователя {{user}}?",
7962
+ terminateAllMessage: "Завершить все сессии пользователя {{user}}?",
7963
+ cancel: "Отмена",
7964
+ terminate: "Завершить",
7965
+ terminateEveryoneMessage: "Завершить все сессии, кроме текущей?"
7966
+ },
7967
+ messages: {
7968
+ loadError: "Не удалось загрузить сессии",
7969
+ terminateSuccess: "Сессия завершена",
7970
+ terminateAllSuccess: "Завершено сессий: {{count}}",
7971
+ terminateError: "Не удалось завершить сессию"
7972
+ },
7973
+ terminateAllTooltip: "Завершить все, кроме текущей",
7974
+ clearFilterTooltip: "Очистить фильтр"
7975
+ }
7976
+ };
7977
+
7978
+ L10nService.registerTranslations({ en: en$4, ru: ru$4 });
7979
+ /**
7980
+ * Administrator page listing active authentication sessions with the ability to terminate them.
7981
+ */
7982
+ class AuthSessionsComponent {
7983
+ constructor() {
7984
+ this.sessions = [];
7985
+ this.userFilter = '';
7986
+ this.loading = false;
7987
+ this.msgService = inject(MsgService);
7988
+ this.confirmationService = inject(ConfirmationService);
7989
+ this.l10nService = inject(L10nService);
7990
+ this.titleService = inject(AppTitleService);
7991
+ this.layoutService = inject(LayoutService);
7992
+ this.authSessionsApi = inject(AuthSessionsApi);
7993
+ this.translationsReady = firstValueFrom(this.l10nService.loadComponentTranslations('auth-sessions'));
7994
+ }
7995
+ async ngOnInit() {
7996
+ await this.translationsReady;
7997
+ this.titleService.setTitle(this.t('auth-sessions.title'));
7998
+ await this.refreshAction();
7999
+ }
8000
+ get filteredSessions() {
8001
+ const filter = this.userFilter.trim().toLowerCase();
8002
+ if (!filter) {
8003
+ return this.sessions;
8004
+ }
8005
+ return this.sessions.filter((session) => [session.userName, session.displayName, session.email, session.userId, session.ipAddress].some((value) => value?.toLowerCase().includes(filter)));
8006
+ }
8007
+ async refreshAction() {
8008
+ this.loading = true;
8009
+ try {
8010
+ this.sessions = await this.authSessionsApi.getAuthSessions({});
8011
+ }
8012
+ catch (error) {
8013
+ this.msgService.errorFromException(error, this.t('auth-sessions.messages.loadError'), this.t('auth-sessions.messages.loadError'));
8014
+ }
8015
+ finally {
8016
+ this.loading = false;
8017
+ }
8018
+ }
8019
+ get hasOtherSessionsThanCurrent() {
8020
+ return this.sessions.some((x) => !x.isCurrent);
8021
+ }
8022
+ async terminateAllSessions() {
8023
+ await this.translationsReady;
8024
+ this.confirmationService.confirm({
8025
+ header: this.t('auth-sessions.confirm.header'),
8026
+ message: this.t('auth-sessions.confirm.terminateEveryoneMessage'),
8027
+ icon: 'pi pi-power-off',
8028
+ rejectButtonProps: {
8029
+ label: this.t('auth-sessions.confirm.cancel'),
8030
+ severity: 'secondary',
8031
+ outlined: true
8032
+ },
8033
+ acceptButtonProps: {
8034
+ label: this.t('auth-sessions.confirm.terminate'),
8035
+ severity: 'danger'
8036
+ },
8037
+ accept: async () => {
8038
+ try {
8039
+ const result = await this.authSessionsApi.deleteAllAuthSessions();
8040
+ await this.refreshAction();
8041
+ this.msgService.success(this.l10nService.instant('auth-sessions.messages.terminateAllSuccess', {
8042
+ count: result.deletedCount ?? 0
8043
+ }));
8044
+ }
8045
+ catch (error) {
8046
+ this.msgService.errorFromException(error, this.t('auth-sessions.messages.terminateError'), this.t('auth-sessions.messages.terminateError'));
8047
+ }
8048
+ }
8049
+ });
8050
+ }
8051
+ hasOtherSessions(session) {
8052
+ return this.sessions.some((x) => x.userId === session.userId && !x.isCurrent);
8053
+ }
8054
+ async terminateSession(session) {
8055
+ await this.translationsReady;
8056
+ this.confirmationService.confirm({
8057
+ header: this.t('auth-sessions.confirm.header'),
8058
+ message: this.l10nService.instant('auth-sessions.confirm.terminateMessage', {
8059
+ user: session.userName ?? session.userId ?? ''
8060
+ }),
8061
+ icon: 'pi pi-sign-out',
8062
+ rejectButtonProps: {
8063
+ label: this.t('auth-sessions.confirm.cancel'),
8064
+ severity: 'secondary',
8065
+ outlined: true
8066
+ },
8067
+ acceptButtonProps: {
8068
+ label: this.t('auth-sessions.confirm.terminate'),
8069
+ severity: 'danger'
8070
+ },
8071
+ accept: async () => {
8072
+ try {
8073
+ await this.authSessionsApi.deleteAuthSession({ sessionId: session.sessionId });
8074
+ await this.refreshAction();
8075
+ this.msgService.success(this.t('auth-sessions.messages.terminateSuccess'));
8076
+ }
8077
+ catch (error) {
8078
+ this.msgService.errorFromException(error, this.t('auth-sessions.messages.terminateError'), this.t('auth-sessions.messages.terminateError'));
8079
+ }
8080
+ }
8081
+ });
8082
+ }
8083
+ async terminateUserSessions(session) {
8084
+ await this.translationsReady;
8085
+ this.confirmationService.confirm({
8086
+ header: this.t('auth-sessions.confirm.header'),
8087
+ message: this.l10nService.instant('auth-sessions.confirm.terminateAllMessage', {
8088
+ user: session.userName ?? session.userId ?? ''
8089
+ }),
8090
+ icon: 'pi pi-user-minus',
8091
+ rejectButtonProps: {
8092
+ label: this.t('auth-sessions.confirm.cancel'),
8093
+ severity: 'secondary',
8094
+ outlined: true
8095
+ },
8096
+ acceptButtonProps: {
8097
+ label: this.t('auth-sessions.confirm.terminate'),
8098
+ severity: 'danger'
8099
+ },
8100
+ accept: async () => {
8101
+ try {
8102
+ const result = await this.authSessionsApi.deleteAuthSessionsByUser({ userId: session.userId });
8103
+ await this.refreshAction();
8104
+ this.msgService.success(this.l10nService.instant('auth-sessions.messages.terminateAllSuccess', {
8105
+ count: result.deletedCount ?? 0
8106
+ }));
8107
+ }
8108
+ catch (error) {
8109
+ this.msgService.errorFromException(error, this.t('auth-sessions.messages.terminateError'), this.t('auth-sessions.messages.terminateError'));
8110
+ }
8111
+ }
8112
+ });
8113
+ }
8114
+ t(key) {
8115
+ return this.l10nService.instant(key);
8116
+ }
8117
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AuthSessionsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
8118
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: AuthSessionsComponent, isStandalone: true, selector: "app-auth-sessions", providers: [ConfirmationService, AuthSessionsApi], ngImport: i0, template: `
8119
+ <p-confirmDialog></p-confirmDialog>
8120
+ <div class="flex flex-col md:flex-row gap-4">
8121
+ <div class="card w-full">
8122
+ <div class="mb-4">
8123
+ <p-toolbar>
8124
+ <div class="flex flex-col md:flex-row md:items-center gap-2 w-full">
8125
+ <div class="font-semibold text-lg flex items-center gap-2 mx-2">
8126
+ <i class="pi pi-users"></i>
8127
+ {{ 'auth-sessions.title' | translate }}
8128
+ </div>
8129
+
8130
+ <div class="flex-1"></div>
8131
+ <div class="flex items-center gap-1 w-full md:w-auto">
8132
+ <p-button
8133
+ icon="pi pi-refresh"
8134
+ rounded="true"
8135
+ severity="secondary"
8136
+ text="true"
8137
+ tooltipPosition="bottom"
8138
+ [loading]="loading"
8139
+ [pTooltip]="'auth-sessions.refreshTooltip' | translate"
8140
+ (onClick)="refreshAction()"></p-button>
8141
+ <p-button
8142
+ icon="pi pi-power-off"
8143
+ rounded="true"
8144
+ severity="danger"
8145
+ text="true"
8146
+ tooltipPosition="bottom"
8147
+ id="oip-auth-sessions-terminate-all"
8148
+ [disabled]="loading || !hasOtherSessionsThanCurrent"
8149
+ [pTooltip]="'auth-sessions.terminateAllTooltip' | translate"
8150
+ (onClick)="terminateAllSessions()"></p-button>
8151
+ <input
8152
+ class="w-full md:w-96"
8153
+ pInputText
8154
+ type="text"
8155
+ id="oip-auth-sessions-filter"
8156
+ [placeholder]="'auth-sessions.filterPlaceholder' | translate"
8157
+ [(ngModel)]="userFilter"/>
8158
+ <p-button
8159
+ icon="pi pi-filter-slash"
8160
+ rounded="true"
8161
+ severity="secondary"
8162
+ text="true"
8163
+ tooltipPosition="bottom"
8164
+ id="oip-auth-sessions-clear-filter"
8165
+ [disabled]="!userFilter"
8166
+ [pTooltip]="'auth-sessions.clearFilterTooltip' | translate"
8167
+ (onClick)="userFilter = ''"></p-button>
8168
+ </div>
8169
+ </div>
8170
+ </p-toolbar>
8171
+ </div>
8172
+ <p-table
8173
+ class="mt-4"
8174
+ dataKey="sessionId"
8175
+ [paginator]="true"
8176
+ [rows]="50"
8177
+ sortField="lastActivityUtc"
8178
+ [sortOrder]="-1"
8179
+ [value]="filteredSessions"
8180
+ [loading]="loading">
8181
+ <ng-template pTemplate="header">
8182
+ <tr>
8183
+ <th pSortableColumn="userName">
8184
+ {{ 'auth-sessions.table.user' | translate }}
8185
+ <p-sortIcon field="userName"></p-sortIcon>
8186
+ </th>
8187
+ <th pSortableColumn="createdUtc">
8188
+ {{ 'auth-sessions.table.created' | translate }}
8189
+ <p-sortIcon field="createdUtc"></p-sortIcon>
8190
+ </th>
8191
+ <th pSortableColumn="expiresUtc">
8192
+ {{ 'auth-sessions.table.expires' | translate }}
8193
+ <p-sortIcon field="expiresUtc"></p-sortIcon>
8194
+ </th>
8195
+ <th pSortableColumn="lastActivityUtc">
8196
+ {{ 'auth-sessions.table.lastActivity' | translate }}
8197
+ <p-sortIcon field="lastActivityUtc"></p-sortIcon>
8198
+ </th>
8199
+ <th pSortableColumn="ipAddress">
8200
+ {{ 'auth-sessions.table.ipAddress' | translate }}
8201
+ <p-sortIcon field="ipAddress"></p-sortIcon>
8202
+ </th>
8203
+ <th pSortableColumn="userAgent">
8204
+ {{ 'auth-sessions.table.userAgent' | translate }}
8205
+ <p-sortIcon field="userAgent"></p-sortIcon>
8206
+ </th>
8207
+ <th style="width: 7rem"></th>
8208
+ </tr>
8209
+ </ng-template>
8210
+ <ng-template let-session pTemplate="body">
8211
+ <tr>
8212
+ <td>
8213
+ <div class="flex items-center gap-2">
8214
+ <div class="flex flex-col">
8215
+ <span class="font-medium">{{ session.userName }}</span>
8216
+ @if (session.displayName || session.email) {
8217
+ <span class="text-sm text-muted-color">{{ session.displayName || session.email }}</span>
8218
+ }
8219
+ </div>
8220
+ @if (session.isCurrent) {
8221
+ <p-tag severity="info" [value]="'auth-sessions.table.current' | translate"></p-tag>
8222
+ }
8223
+ </div>
8224
+ </td>
8225
+ <td>{{ session.createdUtc | date: layoutService.dateTimeFormat() }}</td>
8226
+ <td>{{ session.expiresUtc | date: layoutService.dateTimeFormat() }}</td>
8227
+ <td>{{ session.lastActivityUtc | date: layoutService.dateTimeFormat() }}</td>
8228
+ <td>{{ session.ipAddress }}</td>
8229
+ <td class="max-w-80 truncate" [pTooltip]="session.userAgent" tooltipPosition="top">
8230
+ {{ session.userAgent }}
8231
+ </td>
8232
+ <td>
8233
+ <div class="flex gap-1">
8234
+ <p-button
8235
+ icon="pi pi-sign-out"
8236
+ rounded="true"
8237
+ severity="danger"
8238
+ text="true"
8239
+ tooltipPosition="bottom"
8240
+ [disabled]="session.isCurrent"
8241
+ [pTooltip]="'auth-sessions.table.terminateTooltip' | translate"
8242
+ (onClick)="terminateSession(session)"></p-button>
8243
+ <p-button
8244
+ icon="pi pi-user-minus"
8245
+ rounded="true"
8246
+ severity="danger"
8247
+ text="true"
8248
+ tooltipPosition="bottom"
8249
+ [disabled]="!session.userId || !hasOtherSessions(session)"
8250
+ [pTooltip]="'auth-sessions.table.terminateAllTooltip' | translate"
8251
+ (onClick)="terminateUserSessions(session)"></p-button>
8252
+ </div>
8253
+ </td>
8254
+ </tr>
8255
+ </ng-template>
8256
+ <ng-template pTemplate="emptymessage">
8257
+ <tr>
8258
+ <td colspan="7">{{ 'auth-sessions.table.empty' | translate }}</td>
8259
+ </tr>
8260
+ </ng-template>
8261
+ </p-table>
8262
+ </div>
8263
+ </div>
8264
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: TableModule }, { kind: "component", type: i2$4.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "directive", type: i3$1.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "directive", type: i2$4.SortableColumn, selector: "[pSortableColumn]", inputs: ["pSortableColumn", "pSortableColumnDisabled"] }, { kind: "component", type: i2$4.SortIcon, selector: "p-sortIcon", inputs: ["field"] }, { kind: "component", type: Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: ToolbarModule }, { kind: "component", type: i5$1.Toolbar, selector: "p-toolbar", inputs: ["styleClass", "ariaLabelledBy"] }, { kind: "directive", type: Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip"] }, { kind: "component", type: ConfirmDialog, selector: "p-confirmDialog, p-confirmdialog, p-confirm-dialog", inputs: ["header", "icon", "message", "style", "styleClass", "maskStyleClass", "acceptIcon", "acceptLabel", "closeAriaLabel", "acceptAriaLabel", "acceptVisible", "rejectIcon", "rejectLabel", "rejectAriaLabel", "rejectVisible", "acceptButtonStyleClass", "rejectButtonStyleClass", "closeOnEscape", "dismissableMask", "blockScroll", "rtl", "closable", "appendTo", "key", "autoZIndex", "baseZIndex", "transitionOptions", "focusTrap", "defaultFocus", "breakpoints", "modal", "visible", "position", "draggable"], outputs: ["onHide"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i4$1.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pSize", "variant", "fluid", "invalid"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }, { kind: "pipe", type: DatePipe, name: "date" }] }); }
8265
+ }
8266
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AuthSessionsComponent, decorators: [{
8267
+ type: Component,
8268
+ args: [{
8269
+ imports: [
8270
+ FormsModule,
8271
+ TableModule,
8272
+ Tag,
8273
+ ButtonModule,
8274
+ ToolbarModule,
8275
+ Tooltip,
8276
+ ConfirmDialog,
8277
+ TranslatePipe,
8278
+ InputTextModule,
8279
+ DatePipe
8280
+ ],
8281
+ providers: [ConfirmationService, AuthSessionsApi],
8282
+ selector: 'app-auth-sessions',
8283
+ template: `
8284
+ <p-confirmDialog></p-confirmDialog>
8285
+ <div class="flex flex-col md:flex-row gap-4">
8286
+ <div class="card w-full">
8287
+ <div class="mb-4">
8288
+ <p-toolbar>
8289
+ <div class="flex flex-col md:flex-row md:items-center gap-2 w-full">
8290
+ <div class="font-semibold text-lg flex items-center gap-2 mx-2">
8291
+ <i class="pi pi-users"></i>
8292
+ {{ 'auth-sessions.title' | translate }}
8293
+ </div>
8294
+
8295
+ <div class="flex-1"></div>
8296
+ <div class="flex items-center gap-1 w-full md:w-auto">
8297
+ <p-button
8298
+ icon="pi pi-refresh"
8299
+ rounded="true"
8300
+ severity="secondary"
8301
+ text="true"
8302
+ tooltipPosition="bottom"
8303
+ [loading]="loading"
8304
+ [pTooltip]="'auth-sessions.refreshTooltip' | translate"
8305
+ (onClick)="refreshAction()"></p-button>
8306
+ <p-button
8307
+ icon="pi pi-power-off"
8308
+ rounded="true"
8309
+ severity="danger"
8310
+ text="true"
8311
+ tooltipPosition="bottom"
8312
+ id="oip-auth-sessions-terminate-all"
8313
+ [disabled]="loading || !hasOtherSessionsThanCurrent"
8314
+ [pTooltip]="'auth-sessions.terminateAllTooltip' | translate"
8315
+ (onClick)="terminateAllSessions()"></p-button>
8316
+ <input
8317
+ class="w-full md:w-96"
8318
+ pInputText
8319
+ type="text"
8320
+ id="oip-auth-sessions-filter"
8321
+ [placeholder]="'auth-sessions.filterPlaceholder' | translate"
8322
+ [(ngModel)]="userFilter"/>
8323
+ <p-button
8324
+ icon="pi pi-filter-slash"
8325
+ rounded="true"
8326
+ severity="secondary"
8327
+ text="true"
8328
+ tooltipPosition="bottom"
8329
+ id="oip-auth-sessions-clear-filter"
8330
+ [disabled]="!userFilter"
8331
+ [pTooltip]="'auth-sessions.clearFilterTooltip' | translate"
8332
+ (onClick)="userFilter = ''"></p-button>
8333
+ </div>
8334
+ </div>
8335
+ </p-toolbar>
8336
+ </div>
8337
+ <p-table
8338
+ class="mt-4"
8339
+ dataKey="sessionId"
8340
+ [paginator]="true"
8341
+ [rows]="50"
8342
+ sortField="lastActivityUtc"
8343
+ [sortOrder]="-1"
8344
+ [value]="filteredSessions"
8345
+ [loading]="loading">
8346
+ <ng-template pTemplate="header">
8347
+ <tr>
8348
+ <th pSortableColumn="userName">
8349
+ {{ 'auth-sessions.table.user' | translate }}
8350
+ <p-sortIcon field="userName"></p-sortIcon>
8351
+ </th>
8352
+ <th pSortableColumn="createdUtc">
8353
+ {{ 'auth-sessions.table.created' | translate }}
8354
+ <p-sortIcon field="createdUtc"></p-sortIcon>
8355
+ </th>
8356
+ <th pSortableColumn="expiresUtc">
8357
+ {{ 'auth-sessions.table.expires' | translate }}
8358
+ <p-sortIcon field="expiresUtc"></p-sortIcon>
8359
+ </th>
8360
+ <th pSortableColumn="lastActivityUtc">
8361
+ {{ 'auth-sessions.table.lastActivity' | translate }}
8362
+ <p-sortIcon field="lastActivityUtc"></p-sortIcon>
8363
+ </th>
8364
+ <th pSortableColumn="ipAddress">
8365
+ {{ 'auth-sessions.table.ipAddress' | translate }}
8366
+ <p-sortIcon field="ipAddress"></p-sortIcon>
8367
+ </th>
8368
+ <th pSortableColumn="userAgent">
8369
+ {{ 'auth-sessions.table.userAgent' | translate }}
8370
+ <p-sortIcon field="userAgent"></p-sortIcon>
8371
+ </th>
8372
+ <th style="width: 7rem"></th>
8373
+ </tr>
8374
+ </ng-template>
8375
+ <ng-template let-session pTemplate="body">
8376
+ <tr>
8377
+ <td>
8378
+ <div class="flex items-center gap-2">
8379
+ <div class="flex flex-col">
8380
+ <span class="font-medium">{{ session.userName }}</span>
8381
+ @if (session.displayName || session.email) {
8382
+ <span class="text-sm text-muted-color">{{ session.displayName || session.email }}</span>
8383
+ }
8384
+ </div>
8385
+ @if (session.isCurrent) {
8386
+ <p-tag severity="info" [value]="'auth-sessions.table.current' | translate"></p-tag>
8387
+ }
8388
+ </div>
8389
+ </td>
8390
+ <td>{{ session.createdUtc | date: layoutService.dateTimeFormat() }}</td>
8391
+ <td>{{ session.expiresUtc | date: layoutService.dateTimeFormat() }}</td>
8392
+ <td>{{ session.lastActivityUtc | date: layoutService.dateTimeFormat() }}</td>
8393
+ <td>{{ session.ipAddress }}</td>
8394
+ <td class="max-w-80 truncate" [pTooltip]="session.userAgent" tooltipPosition="top">
8395
+ {{ session.userAgent }}
8396
+ </td>
8397
+ <td>
8398
+ <div class="flex gap-1">
8399
+ <p-button
8400
+ icon="pi pi-sign-out"
8401
+ rounded="true"
8402
+ severity="danger"
8403
+ text="true"
8404
+ tooltipPosition="bottom"
8405
+ [disabled]="session.isCurrent"
8406
+ [pTooltip]="'auth-sessions.table.terminateTooltip' | translate"
8407
+ (onClick)="terminateSession(session)"></p-button>
8408
+ <p-button
8409
+ icon="pi pi-user-minus"
8410
+ rounded="true"
8411
+ severity="danger"
8412
+ text="true"
8413
+ tooltipPosition="bottom"
8414
+ [disabled]="!session.userId || !hasOtherSessions(session)"
8415
+ [pTooltip]="'auth-sessions.table.terminateAllTooltip' | translate"
8416
+ (onClick)="terminateUserSessions(session)"></p-button>
8417
+ </div>
8418
+ </td>
8419
+ </tr>
8420
+ </ng-template>
8421
+ <ng-template pTemplate="emptymessage">
8422
+ <tr>
8423
+ <td colspan="7">{{ 'auth-sessions.table.empty' | translate }}</td>
8424
+ </tr>
8425
+ </ng-template>
8426
+ </p-table>
8427
+ </div>
8428
+ </div>
8429
+ `
8430
+ }]
8431
+ }], ctorParameters: () => [] });
8432
+
8433
+ var authSessions_component = /*#__PURE__*/Object.freeze({
8434
+ __proto__: null,
8435
+ AuthSessionsComponent: AuthSessionsComponent
8436
+ });
8437
+
7515
8438
  var ServiceType;
7516
8439
  (function (ServiceType) {
7517
8440
  ServiceType["Service"] = "Service";
@@ -7520,10 +8443,8 @@ var ServiceType;
7520
8443
 
7521
8444
  var applications$1 = {
7522
8445
  title: "Applications",
7523
- subtitle: "Manage the frontend application registry",
7524
- searchPlaceholder: "Search applications",
7525
- search: "Search",
7526
- clear: "Clear",
8446
+ searchPlaceholder: "Filter applications",
8447
+ clear: "Clear filter",
7527
8448
  add: "Add",
7528
8449
  refreshTooltip: "Refresh",
7529
8450
  empty: "No applications found",
@@ -7568,10 +8489,8 @@ var en$3 = {
7568
8489
 
7569
8490
  var applications = {
7570
8491
  title: "Приложения",
7571
- subtitle: "Управление реестром фронтенд-приложений",
7572
- searchPlaceholder: "Поиск по приложениям",
7573
- search: "Найти",
7574
- clear: "Очистить",
8492
+ searchPlaceholder: "Фильтр по приложениям",
8493
+ clear: "Сбросить фильтр",
7575
8494
  add: "Добавить",
7576
8495
  refreshTooltip: "Обновить",
7577
8496
  empty: "Приложения не найдены",
@@ -7839,65 +8758,71 @@ class ApplicationsComponent {
7839
8758
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: ApplicationsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
7840
8759
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: ApplicationsComponent, isStandalone: true, selector: "app-applications", providers: [ApplicationsApi, ConfirmationService], ngImport: i0, template: `
7841
8760
  <p-confirmDialog></p-confirmDialog>
7842
- <div class="flex flex-col gap-4">
8761
+ <div class="flex flex-col md:flex-row gap-4">
7843
8762
  <div class="card w-full">
7844
- <div class="flex flex-col gap-3 md:flex-row md:items-center md:justify-between">
7845
- <div>
7846
- <div class="font-semibold text-xl mb-1">
7847
- {{ 'applications.title' | translate }}
7848
- </div>
7849
- <p class="m-0 text-surface-500">{{ 'applications.subtitle' | translate }}</p>
7850
- </div>
7851
- <div class="flex flex-col gap-2 sm:flex-row">
7852
- <input
7853
- class="w-full sm:w-72"
7854
- pInputText
7855
- type="text"
7856
- [placeholder]="'applications.searchPlaceholder' | translate"
7857
- [(ngModel)]="globalFilter"
7858
- (keydown.enter)="applyGlobalFilter()" />
7859
- <p-button
7860
- icon="pi pi-search"
7861
- [label]="'applications.search' | translate"
7862
- (onClick)="applyGlobalFilter()"></p-button>
7863
- <p-button
7864
- icon="pi pi-filter-slash"
7865
- severity="secondary"
7866
- [label]="'applications.clear' | translate"
7867
- (onClick)="clearFilters()"></p-button>
7868
- </div>
7869
- </div>
7870
-
7871
- <div class="my-4">
8763
+ <div class="mb-4">
7872
8764
  <p-toolbar>
7873
- <p-button
7874
- icon="pi pi-plus"
7875
- severity="success"
7876
- [disabled]="loading || activeRowAction"
7877
- [label]="'applications.add' | translate"
7878
- (onClick)="beginCreateApplication()"></p-button>
7879
- <p-button
7880
- icon="pi pi-refresh"
7881
- rounded="true"
7882
- severity="secondary"
7883
- text="true"
7884
- tooltipPosition="bottom"
7885
- [disabled]="loading || activeRowAction"
7886
- [pTooltip]="'applications.refreshTooltip' | translate"
7887
- (onClick)="refreshAction()"></p-button>
8765
+ <div class="flex flex-col md:flex-row md:items-center gap-2 w-full">
8766
+ <div class="font-semibold text-lg flex items-center gap-2 mx-2">
8767
+ <i class="pi pi-th-large"></i>
8768
+ {{ 'applications.title' | translate }}
8769
+ </div>
8770
+
8771
+ <div class="flex-1"></div>
8772
+ <div class="flex items-center gap-1 w-full md:w-auto">
8773
+ <p-button
8774
+ icon="pi pi-refresh"
8775
+ rounded="true"
8776
+ severity="secondary"
8777
+ text="true"
8778
+ tooltipPosition="bottom"
8779
+ id="oip-applications-refresh"
8780
+ [loading]="loading"
8781
+ [disabled]="activeRowAction"
8782
+ [pTooltip]="'applications.refreshTooltip' | translate"
8783
+ (onClick)="refreshAction()"></p-button>
8784
+ <p-button
8785
+ icon="pi pi-plus"
8786
+ rounded="true"
8787
+ severity="success"
8788
+ text="true"
8789
+ tooltipPosition="bottom"
8790
+ id="oip-applications-add"
8791
+ [disabled]="loading || activeRowAction"
8792
+ [pTooltip]="'applications.add' | translate"
8793
+ (onClick)="beginCreateApplication()"></p-button>
8794
+ <input
8795
+ class="w-full md:w-96"
8796
+ pInputText
8797
+ type="text"
8798
+ id="oip-applications-filter"
8799
+ [placeholder]="'applications.searchPlaceholder' | translate"
8800
+ [(ngModel)]="globalFilter"
8801
+ (ngModelChange)="applyGlobalFilter()" />
8802
+ <p-button
8803
+ icon="pi pi-filter-slash"
8804
+ rounded="true"
8805
+ severity="secondary"
8806
+ text="true"
8807
+ tooltipPosition="bottom"
8808
+ id="oip-applications-clear-filter"
8809
+ [disabled]="!globalFilter"
8810
+ [pTooltip]="'applications.clear' | translate"
8811
+ (onClick)="clearFilters()"></p-button>
8812
+ </div>
8813
+ </div>
7888
8814
  </p-toolbar>
7889
8815
  </div>
7890
8816
 
7891
8817
  <p-table
7892
- #table
8818
+ class="mt-4"
7893
8819
  dataKey="code"
7894
- responsiveLayout="scroll"
7895
- [globalFilterFields]="globalFilterFields"
7896
- [loading]="loading"
8820
+ sortField="order"
8821
+ [sortOrder]="1"
7897
8822
  [paginator]="true"
7898
- [rows]="25"
7899
- [rowsPerPageOptions]="[10, 25, 50, 100]"
7900
- [value]="visibleApplications">
8823
+ [rows]="50"
8824
+ [value]="visibleApplications"
8825
+ [loading]="loading">
7901
8826
  <ng-template pTemplate="header">
7902
8827
  <tr>
7903
8828
  <th pSortableColumn="code">
@@ -8017,10 +8942,11 @@ class ApplicationsComponent {
8017
8942
  "></p-tag>
8018
8943
  </td>
8019
8944
  <td>
8020
- <div class="flex items-center justify-center gap-2">
8945
+ <div class="flex items-center justify-center gap-1">
8021
8946
  @if (application._isEditing) {
8022
8947
  <p-button
8023
8948
  icon="pi pi-check"
8949
+ rounded="true"
8024
8950
  severity="success"
8025
8951
  text="true"
8026
8952
  tooltipPosition="bottom"
@@ -8029,6 +8955,7 @@ class ApplicationsComponent {
8029
8955
  (onClick)="saveApplication(application)"></p-button>
8030
8956
  <p-button
8031
8957
  icon="pi pi-times"
8958
+ rounded="true"
8032
8959
  severity="secondary"
8033
8960
  text="true"
8034
8961
  tooltipPosition="bottom"
@@ -8038,6 +8965,7 @@ class ApplicationsComponent {
8038
8965
  } @else {
8039
8966
  <p-button
8040
8967
  icon="pi pi-pencil"
8968
+ rounded="true"
8041
8969
  text="true"
8042
8970
  tooltipPosition="bottom"
8043
8971
  [disabled]="activeRowAction"
@@ -8045,6 +8973,7 @@ class ApplicationsComponent {
8045
8973
  (onClick)="editApplication(application)"></p-button>
8046
8974
  <p-button
8047
8975
  icon="pi pi-trash"
8976
+ rounded="true"
8048
8977
  severity="danger"
8049
8978
  text="true"
8050
8979
  tooltipPosition="bottom"
@@ -8059,15 +8988,13 @@ class ApplicationsComponent {
8059
8988
 
8060
8989
  <ng-template pTemplate="emptymessage">
8061
8990
  <tr>
8062
- <td class="py-8 text-center text-surface-500" colspan="10">
8063
- {{ 'applications.empty' | translate }}
8064
- </td>
8991
+ <td colspan="10">{{ 'applications.empty' | translate }}</td>
8065
8992
  </tr>
8066
8993
  </ng-template>
8067
8994
  </p-table>
8068
8995
  </div>
8069
8996
  </div>
8070
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: TableModule }, { kind: "component", type: i1$9.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "directive", type: i2$1.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "directive", type: i1$9.SortableColumn, selector: "[pSortableColumn]", inputs: ["pSortableColumn", "pSortableColumnDisabled"] }, { kind: "component", type: i1$9.SortIcon, selector: "p-sortIcon", inputs: ["field"] }, { kind: "component", type: Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: ToolbarModule }, { kind: "component", type: i5$1.Toolbar, selector: "p-toolbar", inputs: ["styleClass", "ariaLabelledBy"] }, { kind: "directive", type: Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip"] }, { kind: "component", type: ConfirmDialog, selector: "p-confirmDialog, p-confirmdialog, p-confirm-dialog", inputs: ["header", "icon", "message", "style", "styleClass", "maskStyleClass", "acceptIcon", "acceptLabel", "closeAriaLabel", "acceptAriaLabel", "acceptVisible", "rejectIcon", "rejectLabel", "rejectAriaLabel", "rejectVisible", "acceptButtonStyleClass", "rejectButtonStyleClass", "closeOnEscape", "dismissableMask", "blockScroll", "rtl", "closable", "appendTo", "key", "autoZIndex", "baseZIndex", "transitionOptions", "focusTrap", "defaultFocus", "breakpoints", "modal", "visible", "position", "draggable"], outputs: ["onHide"] }, { kind: "directive", type: InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i5.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: ToggleSwitchModule }, { kind: "component", type: i2$4.ToggleSwitch, selector: "p-toggleswitch, p-toggleSwitch, p-toggle-switch", inputs: ["styleClass", "tabindex", "inputId", "readonly", "trueValue", "falseValue", "ariaLabel", "size", "ariaLabelledBy", "autofocus"], outputs: ["onChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
8997
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: TableModule }, { kind: "component", type: i2$4.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "directive", type: i3$1.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "directive", type: i2$4.SortableColumn, selector: "[pSortableColumn]", inputs: ["pSortableColumn", "pSortableColumnDisabled"] }, { kind: "component", type: i2$4.SortIcon, selector: "p-sortIcon", inputs: ["field"] }, { kind: "component", type: Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: ToolbarModule }, { kind: "component", type: i5$1.Toolbar, selector: "p-toolbar", inputs: ["styleClass", "ariaLabelledBy"] }, { kind: "directive", type: Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip"] }, { kind: "component", type: ConfirmDialog, selector: "p-confirmDialog, p-confirmdialog, p-confirm-dialog", inputs: ["header", "icon", "message", "style", "styleClass", "maskStyleClass", "acceptIcon", "acceptLabel", "closeAriaLabel", "acceptAriaLabel", "acceptVisible", "rejectIcon", "rejectLabel", "rejectAriaLabel", "rejectVisible", "acceptButtonStyleClass", "rejectButtonStyleClass", "closeOnEscape", "dismissableMask", "blockScroll", "rtl", "closable", "appendTo", "key", "autoZIndex", "baseZIndex", "transitionOptions", "focusTrap", "defaultFocus", "breakpoints", "modal", "visible", "position", "draggable"], outputs: ["onHide"] }, { kind: "directive", type: InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i5.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: ToggleSwitchModule }, { kind: "component", type: i2$3.ToggleSwitch, selector: "p-toggleswitch, p-toggleSwitch, p-toggle-switch", inputs: ["styleClass", "tabindex", "inputId", "readonly", "trueValue", "falseValue", "ariaLabel", "size", "ariaLabelledBy", "autofocus"], outputs: ["onChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
8071
8998
  }
8072
8999
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: ApplicationsComponent, decorators: [{
8073
9000
  type: Component,
@@ -8089,65 +9016,71 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
8089
9016
  selector: 'app-applications',
8090
9017
  template: `
8091
9018
  <p-confirmDialog></p-confirmDialog>
8092
- <div class="flex flex-col gap-4">
9019
+ <div class="flex flex-col md:flex-row gap-4">
8093
9020
  <div class="card w-full">
8094
- <div class="flex flex-col gap-3 md:flex-row md:items-center md:justify-between">
8095
- <div>
8096
- <div class="font-semibold text-xl mb-1">
8097
- {{ 'applications.title' | translate }}
8098
- </div>
8099
- <p class="m-0 text-surface-500">{{ 'applications.subtitle' | translate }}</p>
8100
- </div>
8101
- <div class="flex flex-col gap-2 sm:flex-row">
8102
- <input
8103
- class="w-full sm:w-72"
8104
- pInputText
8105
- type="text"
8106
- [placeholder]="'applications.searchPlaceholder' | translate"
8107
- [(ngModel)]="globalFilter"
8108
- (keydown.enter)="applyGlobalFilter()" />
8109
- <p-button
8110
- icon="pi pi-search"
8111
- [label]="'applications.search' | translate"
8112
- (onClick)="applyGlobalFilter()"></p-button>
8113
- <p-button
8114
- icon="pi pi-filter-slash"
8115
- severity="secondary"
8116
- [label]="'applications.clear' | translate"
8117
- (onClick)="clearFilters()"></p-button>
8118
- </div>
8119
- </div>
8120
-
8121
- <div class="my-4">
9021
+ <div class="mb-4">
8122
9022
  <p-toolbar>
8123
- <p-button
8124
- icon="pi pi-plus"
8125
- severity="success"
8126
- [disabled]="loading || activeRowAction"
8127
- [label]="'applications.add' | translate"
8128
- (onClick)="beginCreateApplication()"></p-button>
8129
- <p-button
8130
- icon="pi pi-refresh"
8131
- rounded="true"
8132
- severity="secondary"
8133
- text="true"
8134
- tooltipPosition="bottom"
8135
- [disabled]="loading || activeRowAction"
8136
- [pTooltip]="'applications.refreshTooltip' | translate"
8137
- (onClick)="refreshAction()"></p-button>
9023
+ <div class="flex flex-col md:flex-row md:items-center gap-2 w-full">
9024
+ <div class="font-semibold text-lg flex items-center gap-2 mx-2">
9025
+ <i class="pi pi-th-large"></i>
9026
+ {{ 'applications.title' | translate }}
9027
+ </div>
9028
+
9029
+ <div class="flex-1"></div>
9030
+ <div class="flex items-center gap-1 w-full md:w-auto">
9031
+ <p-button
9032
+ icon="pi pi-refresh"
9033
+ rounded="true"
9034
+ severity="secondary"
9035
+ text="true"
9036
+ tooltipPosition="bottom"
9037
+ id="oip-applications-refresh"
9038
+ [loading]="loading"
9039
+ [disabled]="activeRowAction"
9040
+ [pTooltip]="'applications.refreshTooltip' | translate"
9041
+ (onClick)="refreshAction()"></p-button>
9042
+ <p-button
9043
+ icon="pi pi-plus"
9044
+ rounded="true"
9045
+ severity="success"
9046
+ text="true"
9047
+ tooltipPosition="bottom"
9048
+ id="oip-applications-add"
9049
+ [disabled]="loading || activeRowAction"
9050
+ [pTooltip]="'applications.add' | translate"
9051
+ (onClick)="beginCreateApplication()"></p-button>
9052
+ <input
9053
+ class="w-full md:w-96"
9054
+ pInputText
9055
+ type="text"
9056
+ id="oip-applications-filter"
9057
+ [placeholder]="'applications.searchPlaceholder' | translate"
9058
+ [(ngModel)]="globalFilter"
9059
+ (ngModelChange)="applyGlobalFilter()" />
9060
+ <p-button
9061
+ icon="pi pi-filter-slash"
9062
+ rounded="true"
9063
+ severity="secondary"
9064
+ text="true"
9065
+ tooltipPosition="bottom"
9066
+ id="oip-applications-clear-filter"
9067
+ [disabled]="!globalFilter"
9068
+ [pTooltip]="'applications.clear' | translate"
9069
+ (onClick)="clearFilters()"></p-button>
9070
+ </div>
9071
+ </div>
8138
9072
  </p-toolbar>
8139
9073
  </div>
8140
9074
 
8141
9075
  <p-table
8142
- #table
9076
+ class="mt-4"
8143
9077
  dataKey="code"
8144
- responsiveLayout="scroll"
8145
- [globalFilterFields]="globalFilterFields"
8146
- [loading]="loading"
9078
+ sortField="order"
9079
+ [sortOrder]="1"
8147
9080
  [paginator]="true"
8148
- [rows]="25"
8149
- [rowsPerPageOptions]="[10, 25, 50, 100]"
8150
- [value]="visibleApplications">
9081
+ [rows]="50"
9082
+ [value]="visibleApplications"
9083
+ [loading]="loading">
8151
9084
  <ng-template pTemplate="header">
8152
9085
  <tr>
8153
9086
  <th pSortableColumn="code">
@@ -8267,10 +9200,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
8267
9200
  "></p-tag>
8268
9201
  </td>
8269
9202
  <td>
8270
- <div class="flex items-center justify-center gap-2">
9203
+ <div class="flex items-center justify-center gap-1">
8271
9204
  @if (application._isEditing) {
8272
9205
  <p-button
8273
9206
  icon="pi pi-check"
9207
+ rounded="true"
8274
9208
  severity="success"
8275
9209
  text="true"
8276
9210
  tooltipPosition="bottom"
@@ -8279,6 +9213,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
8279
9213
  (onClick)="saveApplication(application)"></p-button>
8280
9214
  <p-button
8281
9215
  icon="pi pi-times"
9216
+ rounded="true"
8282
9217
  severity="secondary"
8283
9218
  text="true"
8284
9219
  tooltipPosition="bottom"
@@ -8288,6 +9223,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
8288
9223
  } @else {
8289
9224
  <p-button
8290
9225
  icon="pi pi-pencil"
9226
+ rounded="true"
8291
9227
  text="true"
8292
9228
  tooltipPosition="bottom"
8293
9229
  [disabled]="activeRowAction"
@@ -8295,6 +9231,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
8295
9231
  (onClick)="editApplication(application)"></p-button>
8296
9232
  <p-button
8297
9233
  icon="pi pi-trash"
9234
+ rounded="true"
8298
9235
  severity="danger"
8299
9236
  text="true"
8300
9237
  tooltipPosition="bottom"
@@ -8309,9 +9246,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
8309
9246
 
8310
9247
  <ng-template pTemplate="emptymessage">
8311
9248
  <tr>
8312
- <td class="py-8 text-center text-surface-500" colspan="10">
8313
- {{ 'applications.empty' | translate }}
8314
- </td>
9249
+ <td colspan="10">{{ 'applications.empty' | translate }}</td>
8315
9250
  </tr>
8316
9251
  </ng-template>
8317
9252
  </p-table>
@@ -9250,7 +10185,7 @@ class DiscussionComponent {
9250
10185
  </div>
9251
10186
  }
9252
10187
  </section>
9253
- `, isInline: true, styles: [":host{display:block}.file-trigger{position:relative;display:inline-flex}.file-trigger input{position:absolute;inset:0;opacity:0;cursor:pointer}.markdown-preview,.history-markdown{word-break:break-word}.markdown-preview :is(h1,h2,h3),.history-markdown :is(h1,h2,h3){margin:0 0 .75rem;font-weight:600}.markdown-preview a,.history-markdown a{color:#2563eb;text-decoration:underline;text-underline-offset:.18em}.emoji-popover{display:flex;flex-wrap:wrap;gap:.5rem;max-width:16rem}.emoji-option{display:inline-flex;align-items:center;justify-content:center;width:2.5rem;height:2.5rem;font-size:1.25rem;cursor:pointer}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AvatarModule }, { kind: "component", type: i2$2.Avatar, selector: "p-avatar", inputs: ["label", "icon", "image", "size", "shape", "styleClass", "ariaLabel", "ariaLabelledBy"], outputs: ["onImageError"] }, { kind: "directive", type: i2$1.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: CardModule }, { kind: "component", type: i5$2.Card, selector: "p-card", inputs: ["header", "subheader", "style", "styleClass"] }, { kind: "component", type: ConfirmDialog, selector: "p-confirmDialog, p-confirmdialog, p-confirm-dialog", inputs: ["header", "icon", "message", "style", "styleClass", "maskStyleClass", "acceptIcon", "acceptLabel", "closeAriaLabel", "acceptAriaLabel", "acceptVisible", "rejectIcon", "rejectLabel", "rejectAriaLabel", "rejectVisible", "acceptButtonStyleClass", "rejectButtonStyleClass", "closeOnEscape", "dismissableMask", "blockScroll", "rtl", "closable", "appendTo", "key", "autoZIndex", "baseZIndex", "transitionOptions", "focusTrap", "defaultFocus", "breakpoints", "modal", "visible", "position", "draggable"], outputs: ["onHide"] }, { kind: "ngmodule", type: DividerModule }, { kind: "ngmodule", type: PanelModule }, { kind: "component", type: i6.Panel, selector: "p-panel", inputs: ["id", "toggleable", "header", "collapsed", "styleClass", "iconPos", "showHeader", "toggler", "transitionOptions", "toggleButtonProps"], outputs: ["collapsedChange", "onBeforeToggle", "onAfterToggle"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "component", type: i7.Popover, selector: "p-popover", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions"], outputs: ["onShow", "onHide"] }, { kind: "ngmodule", type: ProgressSpinnerModule }, { kind: "component", type: i4.ProgressSpinner, selector: "p-progressSpinner, p-progress-spinner, p-progressspinner", inputs: ["styleClass", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "ngmodule", type: TagModule }, { kind: "component", type: i9.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "directive", type: Textarea, selector: "[pTextarea], [pInputTextarea]", inputs: ["autoResize", "pSize", "variant", "fluid", "invalid"], outputs: ["onResize"] }, { kind: "pipe", type: i1$3.DatePipe, name: "date" }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
10188
+ `, isInline: true, styles: [":host{display:block}.file-trigger{position:relative;display:inline-flex}.file-trigger input{position:absolute;inset:0;opacity:0;cursor:pointer}.markdown-preview,.history-markdown{word-break:break-word}.markdown-preview :is(h1,h2,h3),.history-markdown :is(h1,h2,h3){margin:0 0 .75rem;font-weight:600}.markdown-preview a,.history-markdown a{color:#2563eb;text-decoration:underline;text-underline-offset:.18em}.emoji-popover{display:flex;flex-wrap:wrap;gap:.5rem;max-width:16rem}.emoji-option{display:inline-flex;align-items:center;justify-content:center;width:2.5rem;height:2.5rem;font-size:1.25rem;cursor:pointer}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AvatarModule }, { kind: "component", type: i2$1.Avatar, selector: "p-avatar", inputs: ["label", "icon", "image", "size", "shape", "styleClass", "ariaLabel", "ariaLabelledBy"], outputs: ["onImageError"] }, { kind: "directive", type: i3$1.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: CardModule }, { kind: "component", type: i5$2.Card, selector: "p-card", inputs: ["header", "subheader", "style", "styleClass"] }, { kind: "component", type: ConfirmDialog, selector: "p-confirmDialog, p-confirmdialog, p-confirm-dialog", inputs: ["header", "icon", "message", "style", "styleClass", "maskStyleClass", "acceptIcon", "acceptLabel", "closeAriaLabel", "acceptAriaLabel", "acceptVisible", "rejectIcon", "rejectLabel", "rejectAriaLabel", "rejectVisible", "acceptButtonStyleClass", "rejectButtonStyleClass", "closeOnEscape", "dismissableMask", "blockScroll", "rtl", "closable", "appendTo", "key", "autoZIndex", "baseZIndex", "transitionOptions", "focusTrap", "defaultFocus", "breakpoints", "modal", "visible", "position", "draggable"], outputs: ["onHide"] }, { kind: "ngmodule", type: DividerModule }, { kind: "ngmodule", type: PanelModule }, { kind: "component", type: i6.Panel, selector: "p-panel", inputs: ["id", "toggleable", "header", "collapsed", "styleClass", "iconPos", "showHeader", "toggler", "transitionOptions", "toggleButtonProps"], outputs: ["collapsedChange", "onBeforeToggle", "onAfterToggle"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "component", type: i7.Popover, selector: "p-popover", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions"], outputs: ["onShow", "onHide"] }, { kind: "ngmodule", type: ProgressSpinnerModule }, { kind: "component", type: i4.ProgressSpinner, selector: "p-progressSpinner, p-progress-spinner, p-progressspinner", inputs: ["styleClass", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "ngmodule", type: TagModule }, { kind: "component", type: i3$6.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "directive", type: Textarea, selector: "[pTextarea], [pInputTextarea]", inputs: ["autoResize", "pSize", "variant", "fluid", "invalid"], outputs: ["onResize"] }, { kind: "pipe", type: i1$3.DatePipe, name: "date" }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
9254
10189
  }
9255
10190
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DiscussionComponent, decorators: [{
9256
10191
  type: Component,
@@ -10837,6 +11772,15 @@ function oipModulesRoute(path = 'modules') {
10837
11772
  data: { requireAdmin: true }
10838
11773
  };
10839
11774
  }
11775
+ /** Active authentication sessions, administrators only. */
11776
+ function oipSessionsRoute(path = 'sessions') {
11777
+ return {
11778
+ path,
11779
+ loadComponent: () => Promise.resolve().then(function () { return authSessions_component; }).then((m) => m.AuthSessionsComponent),
11780
+ canActivate: [oipAuthGuard],
11781
+ data: { requireAdmin: true }
11782
+ };
11783
+ }
10840
11784
  /** Discussion module. The path must keep an `:id` segment. */
10841
11785
  function oipDiscussionRoute(path = 'discussion/:id') {
10842
11786
  return {
@@ -10904,6 +11848,7 @@ function provideOipRoutes(options = {}) {
10904
11848
  builtInRoute(features.config, oipConfigRoute, children);
10905
11849
  builtInRoute(features.applications, oipApplicationsRoute, children);
10906
11850
  builtInRoute(features.modules, oipModulesRoute, children);
11851
+ builtInRoute(features.sessions, oipSessionsRoute, children);
10907
11852
  builtInRoute(features.discussion, oipDiscussionRoute, children);
10908
11853
  builtInRoute(features.dbMigration, oipDbMigrationRoute, children);
10909
11854
  builtInRoute(features.iframeModule, oipIframeModuleRoute, children);
@@ -10943,5 +11888,5 @@ function provideOipRoutes(options = {}) {
10943
11888
  * Generated bundle index. Do not edit.
10944
11889
  */
10945
11890
 
10946
- export { APP_INFO_TOKEN, APP_THEME_PRESETS, APP_THEME_PRESETS_MERGE_MODE, AccessComponent, AppConfiguratorComponent, AppFloatingConfiguratorComponent, AppInfoService, AppLayoutComponent, AppModulesComponent, AppTopbar, AppTopbarApplicationSwitcherComponent, ApplicationRegistryService, ApplicationsApi, ApplicationsComponent, AuthGuardService, BaseModuleComponent, BffSecurityService, BlockLoaderComponent, ConfigComponent, ContentType, CustomElementExtensionModuleHostComponent, DbMigrationComponent, DefaultSecretsBannerComponent, DiscussionComponent, ErrorComponent, ExtensionLoaderService, ExtensionModuleHostComponent, FolderModuleApi, FooterComponent, HttpClient, IframeModuleApi, IframeModuleComponent, L10nService, LOGO_COMPONENT_TOKEN, LayoutService, LogoComponent, LogoService, MenuComponent, MenuService, ModuleInstanceRightsService, ModuleLoadingService, MsgService, NoModulesComponent, NotfoundComponent, NotificationApi, NotificationService, OIP_EXTENSION_EVENTS, SecurityApi, SecurityComponent, SecurityService, SidebarComponent, StartPageService, TableFilterService, TopBarService, UnauthorizedComponent, UserNotificationsComponent, UserProfileApi, UserProfileComponent, UserService, convertToPrimeNgDateFormat, defaultTheme, emitOipContextChange, emitOipError, emitOipNavigate, emitOipNotify, emitOipSettingsChange, emitOipTitleChange, langIntercept, mergeWithDefaults, moduleAccessGuard, oipAccessRoute, oipApplicationsRoute, oipAuthGuard, oipConfigRoute, oipDbMigrationRoute, oipDiscussionRoute, oipErrorRoute, oipExtensionsRoute, oipIframeModuleRoute, oipModulesRoute, oipNoModulesRoute, oipProfileRoute, oipStartRedirectGuard, oipStartRoute, provideAppInfo, provideAppThemes, provideLogoComponent, provideOip, provideOipRoutes, provideTranslations, replaceDefaults };
11891
+ export { APP_INFO_TOKEN, APP_THEME_PRESETS, APP_THEME_PRESETS_MERGE_MODE, AccessComponent, AppConfiguratorComponent, AppFloatingConfiguratorComponent, AppInfoService, AppLayoutComponent, AppModulesComponent, AppTopbar, AppTopbarApplicationSwitcherComponent, ApplicationRegistryService, ApplicationsApi, ApplicationsComponent, AuthGuardService, AuthSessionsApi, AuthSessionsComponent, BaseModuleComponent, BffSecurityService, BlockLoaderComponent, ConfigComponent, ContentType, CustomElementExtensionModuleHostComponent, DbMigrationComponent, DefaultSecretsBannerComponent, DiscussionComponent, ErrorComponent, ExtensionLoaderService, ExtensionModuleHostComponent, FolderModuleApi, FooterComponent, HttpClient, IframeModuleApi, IframeModuleComponent, L10nService, LOGO_COMPONENT_TOKEN, LayoutService, LogoComponent, LogoService, MenuComponent, MenuService, ModuleInstanceRightsService, ModuleLoadingService, MsgService, NoModulesComponent, NotfoundComponent, NotificationApi, NotificationService, OIP_EXTENSION_EVENTS, SecurityApi, SecurityComponent, SecurityService, SidebarComponent, StartPageService, TableFilterService, TopBarService, UnauthorizedComponent, UserNotificationsComponent, UserProfileApi, UserProfileComponent, UserService, convertToPrimeNgDateFormat, defaultTheme, emitOipContextChange, emitOipError, emitOipNavigate, emitOipNotify, emitOipSettingsChange, emitOipTitleChange, langIntercept, mergeWithDefaults, moduleAccessGuard, oipAccessRoute, oipApplicationsRoute, oipAuthGuard, oipConfigRoute, oipDbMigrationRoute, oipDiscussionRoute, oipErrorRoute, oipExtensionsRoute, oipIframeModuleRoute, oipModulesRoute, oipNoModulesRoute, oipProfileRoute, oipSessionsRoute, oipStartRedirectGuard, oipStartRoute, provideAppInfo, provideAppThemes, provideLogoComponent, provideOip, provideOipRoutes, provideTranslations, replaceDefaults };
10947
11892
  //# sourceMappingURL=oip-common.mjs.map