oip-common 0.7.0 → 0.8.1

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.
@@ -413,6 +413,11 @@ class LayoutService {
413
413
  this.timeZone = computed(() => this.layoutConfig().timeZone, ...(ngDevMode ? [{ debugName: "timeZone" }] : []));
414
414
  this.adminMode = computed(() => this.layoutConfig().adminMode ?? false, ...(ngDevMode ? [{ debugName: "adminMode" }] : []));
415
415
  this.transitionComplete = signal(false, ...(ngDevMode ? [{ debugName: "transitionComplete" }] : []));
416
+ /**
417
+ * Controls the visibility of the layout footer.
418
+ * Modules can hide the footer to free up vertical space for full-screen content.
419
+ */
420
+ this.footerVisible = signal(true, ...(ngDevMode ? [{ debugName: "footerVisible" }] : []));
416
421
  this.initialized = false;
417
422
  effect(() => {
418
423
  const config = this.layoutConfig();
@@ -544,7 +549,7 @@ var msgService$1 = {
544
549
  secondary: "Secondary"
545
550
  };
546
551
  var primeng$1 = "";
547
- var en$j = {
552
+ var en$k = {
548
553
  msgService: msgService$1,
549
554
  primeng: primeng$1
550
555
  };
@@ -748,7 +753,7 @@ var primeng = {
748
753
  zoomOut: "Уменьшить"
749
754
  }
750
755
  };
751
- var ru$j = {
756
+ var ru$k = {
752
757
  msgService: msgService,
753
758
  primeng: primeng
754
759
  };
@@ -757,7 +762,7 @@ var ru$j = {
757
762
  * Global dictionaries shared by all components. They are bundled with the library,
758
763
  * so the application never requests `assets/i18n/{lang}.json`.
759
764
  */
760
- const globalTranslations = { en: en$j, ru: ru$j };
765
+ const globalTranslations = { en: en$k, ru: ru$k };
761
766
  /**
762
767
  * Service for managing translation loading in the application
763
768
  */
@@ -1463,7 +1468,7 @@ var baseComponent$1 = {
1463
1468
  security: "Security",
1464
1469
  success: "Saved successfully"
1465
1470
  };
1466
- var en$i = {
1471
+ var en$j = {
1467
1472
  baseComponent: baseComponent$1
1468
1473
  };
1469
1474
 
@@ -1473,7 +1478,7 @@ var baseComponent = {
1473
1478
  security: "Безопасность",
1474
1479
  success: "Сохранено"
1475
1480
  };
1476
- var ru$i = {
1481
+ var ru$j = {
1477
1482
  baseComponent: baseComponent
1478
1483
  };
1479
1484
 
@@ -1545,6 +1550,11 @@ class BaseModuleComponent {
1545
1550
  */
1546
1551
  constructor() {
1547
1552
  this.isInitialized = false;
1553
+ /**
1554
+ * Set to true in a descendant to hide the layout footer while the module is active.
1555
+ * The footer is restored when the module is destroyed.
1556
+ */
1557
+ this.hideFooter = false;
1548
1558
  this.moduleInstanceReloadPromise = Promise.resolve();
1549
1559
  this.securityRoles = [];
1550
1560
  this.securitySettings = [];
@@ -1609,7 +1619,7 @@ class BaseModuleComponent {
1609
1619
  * @type {Subject<TLocalStoreSettings>}
1610
1620
  */
1611
1621
  this.localSettingsUpdate = new Subject();
1612
- this.baseTranslations = provideTranslations({ en: en$i, ru: ru$i });
1622
+ this.baseTranslations = provideTranslations({ en: en$j, ru: ru$j });
1613
1623
  this.l10nService = inject(L10nService);
1614
1624
  this.canRead = false;
1615
1625
  this.canEdit = false;
@@ -1651,22 +1661,25 @@ class BaseModuleComponent {
1651
1661
  /**
1652
1662
  * Lifecycle hook that is called when a component is destroyed.
1653
1663
  * Unsubscribes from all subscriptions to prevent memory leaks,
1654
- * resets the top bar items to an empty array, and sets the active ID
1655
- * to the ID of the first top bar item (if available).
1664
+ * restores the layout footer, resets the top bar items to an empty array,
1665
+ * and sets the active ID to the ID of the first top bar item (if available).
1656
1666
  */
1657
1667
  ngOnDestroy() {
1668
+ this.layoutService.footerVisible.set(true);
1658
1669
  this.topBarService.setTopBarItems([]);
1659
1670
  this.topBarService.activeId = this.topBarItems[0].id;
1660
1671
  this.rightsSubscription?.unsubscribe();
1661
1672
  this.subscriptions.forEach((s) => s.unsubscribe());
1662
1673
  }
1663
1674
  /**
1664
- * Initializes the component. Subscribes to translation service to set captions for top bar items,
1675
+ * Initializes the component. Applies the footer visibility declared by the module,
1676
+ * subscribes to translation service to set captions for top bar items,
1665
1677
  * sets the top bar items via the top bar service, sets the active ID,
1666
1678
  * subscribes to route parameters to get the ID, and retrieves settings.
1667
1679
  * @return {Promise<void>} A promise that resolves when the initialization is complete.
1668
1680
  */
1669
1681
  async ngOnInit() {
1682
+ this.layoutService.footerVisible.set(!this.hideFooter);
1670
1683
  this.subscriptions.push(this.translateService.stream('baseComponent').subscribe((value) => {
1671
1684
  this.topBarItems.forEach((item) => {
1672
1685
  item.caption = value[item.id];
@@ -1896,6 +1909,13 @@ class SecurityApi extends HttpClient {
1896
1909
  format: "json",
1897
1910
  ...params,
1898
1911
  });
1912
+ this.getDefaultSecretsReport = (params = {}) => this.request({
1913
+ path: `/api/security/get-default-secrets-report`,
1914
+ method: "GET",
1915
+ secure: true,
1916
+ format: "json",
1917
+ ...params,
1918
+ });
1899
1919
  }
1900
1920
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: SecurityApi, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
1901
1921
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: SecurityApi }); }
@@ -1910,7 +1930,7 @@ var securityComponent$1 = {
1910
1930
  savedSecurity: "Security settings saved",
1911
1931
  selectRoles: "Select roles"
1912
1932
  };
1913
- var en$h = {
1933
+ var en$i = {
1914
1934
  securityComponent: securityComponent$1
1915
1935
  };
1916
1936
 
@@ -1920,13 +1940,13 @@ var securityComponent = {
1920
1940
  savedSecurity: "Настройки сохранены",
1921
1941
  selectRoles: "Выберите роли"
1922
1942
  };
1923
- var ru$h = {
1943
+ var ru$i = {
1924
1944
  securityComponent: securityComponent
1925
1945
  };
1926
1946
 
1927
1947
  class SecurityComponent {
1928
1948
  constructor() {
1929
- this.translations = provideTranslations({ en: en$h, ru: ru$h });
1949
+ this.translations = provideTranslations({ en: en$i, ru: ru$i });
1930
1950
  this.msgService = inject(MsgService);
1931
1951
  this.translateService = inject(TranslateService);
1932
1952
  this.httpClient = inject(HttpClient);
@@ -2095,7 +2115,7 @@ const APP_THEME_PRESETS_MERGE_MODE = new InjectionToken('APP_THEME_PRESETS_MERGE
2095
2115
  factory: () => 'mergeWithDefaults'
2096
2116
  });
2097
2117
 
2098
- var en$g = {
2118
+ var en$h = {
2099
2119
  "app-configurator": {
2100
2120
  primary: "Primary",
2101
2121
  surface: "Surface",
@@ -2106,7 +2126,7 @@ var en$g = {
2106
2126
  }
2107
2127
  };
2108
2128
 
2109
- var ru$g = {
2129
+ var ru$h = {
2110
2130
  "app-configurator": {
2111
2131
  primary: "Основной",
2112
2132
  surface: "Фон",
@@ -2150,7 +2170,7 @@ const PRIMARY_COLORS = [
2150
2170
  ];
2151
2171
  class AppConfiguratorComponent {
2152
2172
  constructor() {
2153
- this.translations = provideTranslations({ en: en$g, ru: ru$g });
2173
+ this.translations = provideTranslations({ en: en$h, ru: ru$h });
2154
2174
  this.router = inject(Router);
2155
2175
  this.config = inject(PrimeNG);
2156
2176
  this.layoutService = inject(LayoutService);
@@ -2876,7 +2896,7 @@ class UserService {
2876
2896
  return;
2877
2897
  }
2878
2898
  this.requestedPhotoKey = photoKey;
2879
- this.userProfileApi.getUserPhoto({ format: 'blob' }).then((data) => {
2899
+ this.userProfileApi.getUserPhoto().then((data) => {
2880
2900
  this.createImageFromBlob(data);
2881
2901
  this.photoLoaded = true;
2882
2902
  }, (error) => {
@@ -3158,7 +3178,7 @@ var userNotifications$1 = {
3158
3178
  markAsRead: "Read",
3159
3179
  markedAsRead: "Notification marked as read"
3160
3180
  };
3161
- var en$f = {
3181
+ var en$g = {
3162
3182
  userNotifications: userNotifications$1
3163
3183
  };
3164
3184
 
@@ -3169,13 +3189,13 @@ var userNotifications = {
3169
3189
  markAsRead: "Прочитано",
3170
3190
  markedAsRead: "Оповещение отмечено прочитанным"
3171
3191
  };
3172
- var ru$f = {
3192
+ var ru$g = {
3173
3193
  userNotifications: userNotifications
3174
3194
  };
3175
3195
 
3176
3196
  class UserNotificationsComponent {
3177
3197
  constructor() {
3178
- this.translations = provideTranslations({ en: en$f, ru: ru$f });
3198
+ this.translations = provideTranslations({ en: en$g, ru: ru$g });
3179
3199
  this.notifications = [];
3180
3200
  this.totalCount = 0;
3181
3201
  this.skip = 0;
@@ -3604,7 +3624,7 @@ var topbar$1 = {
3604
3624
  profile: "Profile",
3605
3625
  applications: "Applications"
3606
3626
  };
3607
- var en$e = {
3627
+ var en$f = {
3608
3628
  topbar: topbar$1
3609
3629
  };
3610
3630
 
@@ -3617,13 +3637,13 @@ var topbar = {
3617
3637
  profile: "Профиль",
3618
3638
  applications: "Приложения"
3619
3639
  };
3620
- var ru$e = {
3640
+ var ru$f = {
3621
3641
  topbar: topbar
3622
3642
  };
3623
3643
 
3624
3644
  class AppTopbar {
3625
3645
  constructor() {
3626
- this.translations = provideTranslations({ en: en$e, ru: ru$e });
3646
+ this.translations = provideTranslations({ en: en$f, ru: ru$f });
3627
3647
  this.securityService = inject(SecurityService);
3628
3648
  this.topBarService = inject(TopBarService);
3629
3649
  this.userService = inject(UserService);
@@ -5204,7 +5224,7 @@ var menuItemCreateDialogComponent$1 = {
5204
5224
  cancel: "Cancel",
5205
5225
  save: "Save"
5206
5226
  };
5207
- var en$d = {
5227
+ var en$e = {
5208
5228
  menuComponent: menuComponent$1,
5209
5229
  menuItemComponent: menuItemComponent$1,
5210
5230
  menuItemEditDialogComponent: menuItemEditDialogComponent$1,
@@ -5253,7 +5273,7 @@ var menuItemCreateDialogComponent = {
5253
5273
  cancel: "Отмена",
5254
5274
  save: "Сохранить"
5255
5275
  };
5256
- var ru$d = {
5276
+ var ru$e = {
5257
5277
  menuComponent: menuComponent,
5258
5278
  menuItemComponent: menuItemComponent,
5259
5279
  menuItemEditDialogComponent: menuItemEditDialogComponent,
@@ -5264,7 +5284,7 @@ class MenuComponent {
5264
5284
  constructor() {
5265
5285
  // Registers the whole menu/l10n/menu.*.json bundle, which also covers
5266
5286
  // menuItemComponent, menuItemEditDialogComponent and menuItemCreateDialogComponent.
5267
- this.translations = provideTranslations({ en: en$d, ru: ru$d });
5287
+ this.translations = provideTranslations({ en: en$e, ru: ru$e });
5268
5288
  this.menuService = inject(MenuService);
5269
5289
  this.securityService = inject(SecurityService);
5270
5290
  this.translateService = inject(TranslateService);
@@ -5391,14 +5411,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
5391
5411
  var blockLoader$1 = {
5392
5412
  loading: "Loading..."
5393
5413
  };
5394
- var en$c = {
5414
+ var en$d = {
5395
5415
  blockLoader: blockLoader$1
5396
5416
  };
5397
5417
 
5398
5418
  var blockLoader = {
5399
5419
  loading: "Загрузка..."
5400
5420
  };
5401
- var ru$c = {
5421
+ var ru$d = {
5402
5422
  blockLoader: blockLoader
5403
5423
  };
5404
5424
 
@@ -5415,7 +5435,7 @@ class BlockLoaderComponent {
5415
5435
  static { this.showDelayMs = 150; }
5416
5436
  static { this.minVisibleMs = 300; }
5417
5437
  constructor() {
5418
- this.translations = provideTranslations({ en: en$c, ru: ru$c });
5438
+ this.translations = provideTranslations({ en: en$d, ru: ru$d });
5419
5439
  this.moduleLoadingService = inject(ModuleLoadingService);
5420
5440
  this.shownAt = 0;
5421
5441
  this.visible = signal(false, ...(ngDevMode ? [{ debugName: "visible" }] : []));
@@ -5529,6 +5549,229 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
5529
5549
  }]
5530
5550
  }], ctorParameters: () => [] });
5531
5551
 
5552
+ var defaultSecretsBanner$1 = {
5553
+ title: "Default secrets are still in use",
5554
+ description: "{{count}} of {{checked}} secret settings still hold a value shipped with the repository or are empty. Override them before this installation is used for real data.",
5555
+ kind: {
5556
+ ShippedDefault: "shipped default",
5557
+ Missing: "missing"
5558
+ },
5559
+ columns: {
5560
+ configKey: "Setting",
5561
+ kind: "Problem",
5562
+ environmentVariable: "Environment variable"
5563
+ },
5564
+ actions: {
5565
+ details: "Details",
5566
+ hide: "Hide",
5567
+ dismiss: "Dismiss"
5568
+ }
5569
+ };
5570
+ var en$c = {
5571
+ defaultSecretsBanner: defaultSecretsBanner$1
5572
+ };
5573
+
5574
+ var defaultSecretsBanner = {
5575
+ title: "Используются секреты по умолчанию",
5576
+ description: "{{count}} из {{checked}} секретных настроек всё ещё содержат значение из репозитория или пусты. Переопределите их, прежде чем использовать эту установку с реальными данными.",
5577
+ kind: {
5578
+ ShippedDefault: "значение по умолчанию",
5579
+ Missing: "не задано"
5580
+ },
5581
+ columns: {
5582
+ configKey: "Настройка",
5583
+ kind: "Проблема",
5584
+ environmentVariable: "Переменная окружения"
5585
+ },
5586
+ actions: {
5587
+ details: "Подробнее",
5588
+ hide: "Свернуть",
5589
+ dismiss: "Скрыть"
5590
+ }
5591
+ };
5592
+ var ru$c = {
5593
+ defaultSecretsBanner: defaultSecretsBanner
5594
+ };
5595
+
5596
+ /**
5597
+ * Administrator banner listing the secret settings that still hold a value shipped with the repository.
5598
+ *
5599
+ * The report comes from the same cached validator that feeds the startup log and the `default-secrets`
5600
+ * health check, so the three never disagree. Only administrators see it - the endpoint is admin-only.
5601
+ *
5602
+ * Whether the banner is raised at all is decided by the server through `showBanner`: findings are reported in
5603
+ * every environment, but the banner appears only in Production. Set `ASPNETCORE_ENVIRONMENT=Production` to see
5604
+ * it locally.
5605
+ */
5606
+ class DefaultSecretsBannerComponent {
5607
+ constructor() {
5608
+ this.translations = provideTranslations({ en: en$c, ru: ru$c });
5609
+ this.securityApi = inject(SecurityApi);
5610
+ this.securityService = inject(SecurityService);
5611
+ this.destroyRef = inject(DestroyRef);
5612
+ this.report = signal(null, ...(ngDevMode ? [{ debugName: "report" }] : []));
5613
+ this.expanded = signal(false, ...(ngDevMode ? [{ debugName: "expanded" }] : []));
5614
+ }
5615
+ ngOnInit() {
5616
+ // `payload` emits on every auth() call, and the auth guard calls it on every route activation. The report
5617
+ // cannot change while the page is open, so wait for the first payload that belongs to an administrator and
5618
+ // request it exactly once. A non-administrator never issues the request at all - it would only earn a 403.
5619
+ this.securityService.payload
5620
+ .pipe(filter(() => this.securityService.isAdmin()), take(1), takeUntilDestroyed(this.destroyRef))
5621
+ .subscribe(() => this.load());
5622
+ }
5623
+ kindLabel(finding) {
5624
+ return `defaultSecretsBanner.kind.${finding.kind}`;
5625
+ }
5626
+ dismiss() {
5627
+ this.report.set(null);
5628
+ }
5629
+ load() {
5630
+ this.securityApi
5631
+ .getDefaultSecretsReport()
5632
+ .then((data) => this.report.set(data?.showBanner ? data : null))
5633
+ // A service without the endpoint, or a revoked admin role, must not break the layout.
5634
+ .catch(() => this.report.set(null));
5635
+ }
5636
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DefaultSecretsBannerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5637
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: DefaultSecretsBannerComponent, isStandalone: true, selector: "default-secrets-banner", ngImport: i0, template: `
5638
+ @if (report(); as data) {
5639
+ <div
5640
+ class="mb-4 rounded-border border border-orange-300 bg-orange-50 p-4 dark:border-orange-700 dark:bg-orange-950">
5641
+ <div class="flex flex-row items-start gap-3">
5642
+ <i class="pi pi-exclamation-triangle mt-1 text-xl text-orange-600 dark:text-orange-400"></i>
5643
+ <div class="flex flex-col gap-1">
5644
+ <span class="font-bold text-surface-900 dark:text-surface-0">
5645
+ {{ 'defaultSecretsBanner.title' | translate }}
5646
+ </span>
5647
+ <span class="text-surface-700 dark:text-surface-200">
5648
+ {{
5649
+ 'defaultSecretsBanner.description'
5650
+ | translate: { count: data.findings?.length ?? 0, checked: data.checkedCount ?? 0 }
5651
+ }}
5652
+ </span>
5653
+ </div>
5654
+ <div class="ml-auto flex flex-row gap-2">
5655
+ <p-button
5656
+ severity="secondary"
5657
+ size="small"
5658
+ [icon]="expanded() ? 'pi pi-chevron-up' : 'pi pi-chevron-down'"
5659
+ [label]="
5660
+ (expanded() ? 'defaultSecretsBanner.actions.hide' : 'defaultSecretsBanner.actions.details') | translate
5661
+ "
5662
+ [text]="true"
5663
+ (click)="expanded.set(!expanded())" />
5664
+ <p-button
5665
+ icon="pi pi-times"
5666
+ severity="secondary"
5667
+ size="small"
5668
+ [ariaLabel]="'defaultSecretsBanner.actions.dismiss' | translate"
5669
+ [text]="true"
5670
+ (click)="dismiss()" />
5671
+ </div>
5672
+ </div>
5673
+
5674
+ @if (expanded()) {
5675
+ <div class="mt-3 overflow-x-auto">
5676
+ <table class="w-full text-left text-sm">
5677
+ <thead>
5678
+ <tr class="text-surface-600 dark:text-surface-300">
5679
+ <th class="py-1 pr-4" scope="col">{{ 'defaultSecretsBanner.columns.configKey' | translate }}</th>
5680
+ <th class="py-1 pr-4" scope="col">{{ 'defaultSecretsBanner.columns.kind' | translate }}</th>
5681
+ <th class="py-1" scope="col">
5682
+ {{ 'defaultSecretsBanner.columns.environmentVariable' | translate }}
5683
+ </th>
5684
+ </tr>
5685
+ </thead>
5686
+ <tbody>
5687
+ @for (finding of data.findings; track finding.configKey) {
5688
+ <tr class="text-surface-900 dark:text-surface-0">
5689
+ <td class="py-1 pr-4 font-mono">{{ finding.configKey }}</td>
5690
+ <td class="py-1 pr-4">{{ kindLabel(finding) | translate }}</td>
5691
+ <td class="py-1 font-mono">{{ finding.environmentVariable }}</td>
5692
+ </tr>
5693
+ }
5694
+ </tbody>
5695
+ </table>
5696
+ </div>
5697
+ }
5698
+ </div>
5699
+ }
5700
+ `, 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: "pipe", type: TranslatePipe, name: "translate" }] }); }
5701
+ }
5702
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DefaultSecretsBannerComponent, decorators: [{
5703
+ type: Component,
5704
+ args: [{
5705
+ selector: 'default-secrets-banner',
5706
+ standalone: true,
5707
+ imports: [ButtonModule, TranslatePipe],
5708
+ template: `
5709
+ @if (report(); as data) {
5710
+ <div
5711
+ class="mb-4 rounded-border border border-orange-300 bg-orange-50 p-4 dark:border-orange-700 dark:bg-orange-950">
5712
+ <div class="flex flex-row items-start gap-3">
5713
+ <i class="pi pi-exclamation-triangle mt-1 text-xl text-orange-600 dark:text-orange-400"></i>
5714
+ <div class="flex flex-col gap-1">
5715
+ <span class="font-bold text-surface-900 dark:text-surface-0">
5716
+ {{ 'defaultSecretsBanner.title' | translate }}
5717
+ </span>
5718
+ <span class="text-surface-700 dark:text-surface-200">
5719
+ {{
5720
+ 'defaultSecretsBanner.description'
5721
+ | translate: { count: data.findings?.length ?? 0, checked: data.checkedCount ?? 0 }
5722
+ }}
5723
+ </span>
5724
+ </div>
5725
+ <div class="ml-auto flex flex-row gap-2">
5726
+ <p-button
5727
+ severity="secondary"
5728
+ size="small"
5729
+ [icon]="expanded() ? 'pi pi-chevron-up' : 'pi pi-chevron-down'"
5730
+ [label]="
5731
+ (expanded() ? 'defaultSecretsBanner.actions.hide' : 'defaultSecretsBanner.actions.details') | translate
5732
+ "
5733
+ [text]="true"
5734
+ (click)="expanded.set(!expanded())" />
5735
+ <p-button
5736
+ icon="pi pi-times"
5737
+ severity="secondary"
5738
+ size="small"
5739
+ [ariaLabel]="'defaultSecretsBanner.actions.dismiss' | translate"
5740
+ [text]="true"
5741
+ (click)="dismiss()" />
5742
+ </div>
5743
+ </div>
5744
+
5745
+ @if (expanded()) {
5746
+ <div class="mt-3 overflow-x-auto">
5747
+ <table class="w-full text-left text-sm">
5748
+ <thead>
5749
+ <tr class="text-surface-600 dark:text-surface-300">
5750
+ <th class="py-1 pr-4" scope="col">{{ 'defaultSecretsBanner.columns.configKey' | translate }}</th>
5751
+ <th class="py-1 pr-4" scope="col">{{ 'defaultSecretsBanner.columns.kind' | translate }}</th>
5752
+ <th class="py-1" scope="col">
5753
+ {{ 'defaultSecretsBanner.columns.environmentVariable' | translate }}
5754
+ </th>
5755
+ </tr>
5756
+ </thead>
5757
+ <tbody>
5758
+ @for (finding of data.findings; track finding.configKey) {
5759
+ <tr class="text-surface-900 dark:text-surface-0">
5760
+ <td class="py-1 pr-4 font-mono">{{ finding.configKey }}</td>
5761
+ <td class="py-1 pr-4">{{ kindLabel(finding) | translate }}</td>
5762
+ <td class="py-1 font-mono">{{ finding.environmentVariable }}</td>
5763
+ </tr>
5764
+ }
5765
+ </tbody>
5766
+ </table>
5767
+ </div>
5768
+ }
5769
+ </div>
5770
+ }
5771
+ `
5772
+ }]
5773
+ }] });
5774
+
5532
5775
  class AppLayoutComponent {
5533
5776
  constructor() {
5534
5777
  this.layoutService = inject(LayoutService);
@@ -5607,37 +5850,51 @@ class AppLayoutComponent {
5607
5850
  }
5608
5851
  }
5609
5852
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AppLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5610
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.16", type: AppLayoutComponent, isStandalone: true, selector: "app-layout", providers: [MenuService, MenuApi], viewQueries: [{ propertyName: "appSidebar", first: true, predicate: SidebarComponent, descendants: true }, { propertyName: "appTopBar", first: true, predicate: AppTopbar, descendants: true }], ngImport: i0, template: `
5853
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: AppLayoutComponent, isStandalone: true, selector: "app-layout", providers: [MenuService, MenuApi], viewQueries: [{ propertyName: "appSidebar", first: true, predicate: SidebarComponent, descendants: true }, { propertyName: "appTopBar", first: true, predicate: AppTopbar, descendants: true }], ngImport: i0, template: `
5611
5854
  <div class="layout-wrapper" [ngClass]="containerClass">
5612
5855
  <app-topbar></app-topbar>
5613
5856
  <app-sidebar></app-sidebar>
5614
5857
  <div class="layout-main-container">
5858
+ <default-secrets-banner />
5615
5859
  <div class="layout-main">
5616
5860
  <router-outlet></router-outlet>
5617
5861
  </div>
5618
- <app-footer></app-footer>
5862
+ @if (layoutService.footerVisible()) {
5863
+ <app-footer></app-footer>
5864
+ }
5619
5865
  </div>
5620
5866
  <div class="layout-mask animate-fadein"></div>
5621
5867
  </div>
5622
5868
  <!-- Outside the wrapper on purpose: the blocker marks the wrapper inert while it is visible. -->
5623
5869
  <block-loader />
5624
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: AppTopbar, selector: "app-topbar" }, { kind: "component", type: SidebarComponent, selector: "app-sidebar" }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$5.RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "component", type: FooterComponent, selector: "app-footer" }, { kind: "component", type: BlockLoaderComponent, selector: "block-loader" }] }); }
5870
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: AppTopbar, selector: "app-topbar" }, { kind: "component", type: SidebarComponent, selector: "app-sidebar" }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$5.RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "component", type: FooterComponent, selector: "app-footer" }, { kind: "component", type: BlockLoaderComponent, selector: "block-loader" }, { kind: "component", type: DefaultSecretsBannerComponent, selector: "default-secrets-banner" }] }); }
5625
5871
  }
5626
5872
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AppLayoutComponent, decorators: [{
5627
5873
  type: Component,
5628
5874
  args: [{
5629
5875
  selector: 'app-layout',
5630
5876
  standalone: true,
5631
- imports: [CommonModule, AppTopbar, SidebarComponent, RouterModule, FooterComponent, BlockLoaderComponent],
5877
+ imports: [
5878
+ CommonModule,
5879
+ AppTopbar,
5880
+ SidebarComponent,
5881
+ RouterModule,
5882
+ FooterComponent,
5883
+ BlockLoaderComponent,
5884
+ DefaultSecretsBannerComponent
5885
+ ],
5632
5886
  template: `
5633
5887
  <div class="layout-wrapper" [ngClass]="containerClass">
5634
5888
  <app-topbar></app-topbar>
5635
5889
  <app-sidebar></app-sidebar>
5636
5890
  <div class="layout-main-container">
5891
+ <default-secrets-banner />
5637
5892
  <div class="layout-main">
5638
5893
  <router-outlet></router-outlet>
5639
5894
  </div>
5640
- <app-footer></app-footer>
5895
+ @if (layoutService.footerVisible()) {
5896
+ <app-footer></app-footer>
5897
+ }
5641
5898
  </div>
5642
5899
  <div class="layout-mask animate-fadein"></div>
5643
5900
  </div>
@@ -10680,5 +10937,5 @@ function provideOipRoutes(options = {}) {
10680
10937
  * Generated bundle index. Do not edit.
10681
10938
  */
10682
10939
 
10683
- 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, 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 };
10940
+ 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 };
10684
10941
  //# sourceMappingURL=oip-common.mjs.map