@c8y/ngx-components 1023.83.4 → 1023.85.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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sources":["../../api/api.model.ts","../../api/interceptor.model.ts","../../api/http-handler.model.ts","../../api/api.service.ts","../../api/data.module.ts","../../api/services.ts"],"sourcesContent":[null,null,null,null,null,null],"names":[],"mappings":";;;;;;;;AAKC;;;;;AAMA;;;;AAKC;AACA;AACA;AACD;;;ACdC;AACD;AAED;;AAEC;;;ACMC;AACA;AACD;;ACND;AAUc;AANZ;AACA;;;;AAKoB;AAcpB;;;;;AAKG;AACH;AAOA;;;;;AAKG;AACH;AAOA;;;AAGG;AACH;AAIA;;;AAGG;AACH;AAIA;;;AAGG;;;;;;AAeH;;;;AAIG;AACH;AAaA;;;;;AAKG;;AASH;;;;AAIG;AACH;AAIA;;;;AAIG;AACH;AAIA;AAYA;;;AAcD;;ACxGD;;;AAGG;AACH;AAeA;;AAEG;AACH;AAIE;AAGA;;;;AAMD;;ACrED;;;"}
1
+ {"version":3,"file":"index.d.ts","sources":["../../api/api.model.ts","../../api/interceptor.model.ts","../../api/http-handler.model.ts","../../api/api.service.ts","../../api/data.module.ts","../../api/services.ts"],"sourcesContent":[null,null,null,null,null,null],"names":[],"mappings":";;;;;;;;AAKC;;;;;AAMA;;;;AAKC;AACA;AACA;AACD;;;ACdC;AACD;AAED;;AAEC;;;ACMC;AACA;AACD;;ACND;AAUc;AANZ;AACA;;;;AAKoB;AAcpB;;;;;AAKG;AACH;AAOA;;;;;AAKG;AACH;AAOA;;;AAGG;AACH;AAIA;;;AAGG;AACH;AAIA;;;AAGG;;;;;;AAeH;;;;AAIG;AACH;AAaA;;;;;AAKG;;AASH;;;;AAIG;AACH;AAIA;;;;AAIG;AACH;AAIA;AAYA;;;AAcD;;ACpGD;;;AAGG;AACH;AAOA;;AAEG;AACH;AAIE;AAGA;;;;AAMD;;ACjED;;;"}
@@ -53,6 +53,8 @@ interface CockpitConfig {
53
53
  appTitle?: string;
54
54
  htmlWidgetDisableSanitization?: boolean;
55
55
  htmlWidgetDefaultToAdvancedMode?: boolean;
56
+ showAssetsAsTopNode?: boolean;
57
+ showGroupsAsTopNode?: boolean;
56
58
  }
57
59
  declare const DEFAULT_CONFIG: CockpitConfig;
58
60
  interface CockpitConfigRootNode {
@@ -107,6 +109,7 @@ declare class CockpitConfigService {
107
109
  refresh(): void;
108
110
  setRootNodes(): Promise<void>;
109
111
  getAppDashboardName(): string;
112
+ private setTopNodeList;
110
113
  private storeApplicationConfig;
111
114
  private addNodesToFactories;
112
115
  private registerFilterForFeatures;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sources":["../../cockpit-config/cockpit-config.guard.ts","../../cockpit-config/cockpit-config.model.ts","../../cockpit-config/cockpit-config.service.ts","../../cockpit-config/cockpit-configuration.component.ts","../../cockpit-config/setup/cockpit-setup-step.ts","../../cockpit-config/setup/cockpit-setup-step1.component.ts","../../cockpit-config/setup/cockpit-setup-step2.component.ts","../../cockpit-config/setup/cockpit-setup-step3.component.ts","../../cockpit-config/setup/cockpit-setup-step4.component.ts","../../cockpit-config/feature-config.component.ts","../../cockpit-config/root-node-config.component.ts","../../cockpit-config/home-dashboard-config.component.ts","../../cockpit-config/misc-config.component.ts","../../cockpit-config/setup/cockpit-setup-stepper-buttons.component.ts","../../cockpit-config/cockpit-config.module.ts"],"sourcesContent":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],"names":[],"mappings":";;;;;;;;;;;;;;;AAWA;AAaI;AACA;AACA;AAXF;;AAcA;AAOA;;;AAMD;;AC1CD;AACA;;;AAIE;;;;;;;;;;;;;AAaE;;;;;AAKF;;;;;;AAMD;AAED;;;;;AA8BC;AAED;AACE;;AAEG;AACH;AACA;;AAEG;AACH;AACA;;AAEG;AACH;AACD;AAED;;ACvDA;AAmBI;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACmD;;;;AAlBrD;AAEA;AAOU;;AA8BV;;;AAGG;;AAOH;;;AAGG;;;;;;AAoEH;AASA;AAWA;AAmBA;AAIA;AAcA;AAWA;;;AAeD;;AClND;AAiCI;AACA;AACA;AAVF;;AAEG;;AAGH;;AAQA;;AAEG;;AAKH;;AAEG;;AAUH;;AAEG;AACH;AAQA;;AAEG;;AAMH;;AAEG;;;;AAOJ;;ACzGD;AAKW;;;;;;;;AAHT;;;;AA+BD;;AClBD;AAkBW;;;;;;;AAHT;;AAeA;;;AAGD;;ACtCD;AAaW;;;;;;;;;;AAUV;;ACvBD;AAaW;;;;;;;;;;AAUV;;ACvBD;AAaW;;;;;;;;;;AAUV;;AC1BD;AAeE;AACA;AAEA;;;AAGD;;ACjBD;;AAsBW;AAGT;AAEA;;;AAGG;;;;AASJ;;ACzCD;AAiBc;;AARZ;;AAEG;;AAGH;;AAEG;AACiB;AAEpB;;AAEG;AACH;AAwBA;;AAEG;;;;AAUJ;;ACpED;;;;AAQC;;ACTD;AAMW;AACC;AACA;;;AACX;;ACiBD;AA6Dc;AAAQ;;;;AAGrB;;;"}
1
+ {"version":3,"file":"index.d.ts","sources":["../../cockpit-config/cockpit-config.guard.ts","../../cockpit-config/cockpit-config.model.ts","../../cockpit-config/cockpit-config.service.ts","../../cockpit-config/cockpit-configuration.component.ts","../../cockpit-config/setup/cockpit-setup-step.ts","../../cockpit-config/setup/cockpit-setup-step1.component.ts","../../cockpit-config/setup/cockpit-setup-step2.component.ts","../../cockpit-config/setup/cockpit-setup-step3.component.ts","../../cockpit-config/setup/cockpit-setup-step4.component.ts","../../cockpit-config/feature-config.component.ts","../../cockpit-config/root-node-config.component.ts","../../cockpit-config/home-dashboard-config.component.ts","../../cockpit-config/misc-config.component.ts","../../cockpit-config/setup/cockpit-setup-stepper-buttons.component.ts","../../cockpit-config/cockpit-config.module.ts"],"sourcesContent":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],"names":[],"mappings":";;;;;;;;;;;;;;;AAWA;AAaI;AACA;AACA;AAXF;;AAcA;AAOA;;;AAMD;;AC1CD;AACA;;;AAIE;;;;;;;;;;;;;AAaE;;;;;AAKF;;;;;;;;AAQD;AAED;;;;;AAgCC;AAED;AACE;;AAEG;AACH;AACA;;AAEG;AACH;AACA;;AAEG;AACH;AACD;AAED;;AC3DA;AAmBI;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACmD;;;;AAlBrD;AAEA;AAOU;;AAiCV;;;AAGG;;AAOH;;;AAGG;;;;;;;AAyGH;AASA;AAWA;AAmBA;AAIA;AAcA;AAWA;;;AAeD;;AC1PD;AAgCI;AACA;AACA;AAVF;;AAEG;;AAGH;;AAQA;;AAEG;;AAKH;;AAEG;;AAUH;;AAEG;AACH;AAQA;;AAEG;;AAMH;;AAEG;;;;AAOJ;;ACxGD;AAKW;;;;;;;;AAHT;;;;AA+BD;;AClBD;AAkBW;;;;;;;AAHT;;AAeA;;;AAGD;;ACtCD;AAaW;;;;;;;;;;AAUV;;ACvBD;AAaW;;;;;;;;;;AAUV;;ACvBD;AAaW;;;;;;;;;;AAUV;;AC1BD;AAeE;AACA;AAEA;;;AAGD;;ACjBD;;AAsBW;AAGT;AAEA;;;AAGG;;;;AASJ;;ACzCD;AAiBc;;AARZ;;AAEG;;AAGH;;AAEG;AACiB;AAEpB;;AAEG;AACH;AAwBA;;AAEG;;;;AAUJ;;ACpED;;;;AAQC;;ACTD;AAMW;AACC;AACA;;;AACX;;ACiBD;AA6Dc;AAAQ;;;;AAGrB;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sources":["../../feature-toggles/index.ts"],"sourcesContent":[null],"names":[],"mappings":";;AAYA,cAAA,sBAAA,EAAA,QAAA;;;;"}
1
+ {"version":3,"file":"index.d.ts","sources":["../../feature-toggles/index.ts"],"sourcesContent":[null],"names":[],"mappings":";;AA2BA,cAAA,sBAAA,EAAA,QAAA;;;;"}
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Injectable, Optional, SkipSelf, runInInjectionContext, Injector, inject, provideAppInitializer, NgModule } from '@angular/core';
2
+ import { Injectable, Optional, SkipSelf, runInInjectionContext, Injector, inject, NgModule } from '@angular/core';
3
3
  import * as i1 from '@c8y/client';
4
4
  import { FetchClient, BasicAuth, CookieAuth, Realtime, EventBinaryService, EventService, InventoryService, MeasurementService, AlarmService, OperationBulkService, OperationService, ApplicationService, UserService, TenantService, SystemOptionsService, TenantOptionsService, TenantSecurityOptionsService, TenantLoginOptionsService, AuditService, InventoryRoleService, InventoryBinaryService, DeviceRegistrationService, DeviceRegistrationBulkService, UserRoleService, UserGroupService, IdentityService, TrustedCertificateService, CrlService, SmartGroupsService, SmartRulesService, FeatureService, BearerAuthFromSessionStorage } from '@c8y/client';
5
5
  import { from, Subject, pipe } from 'rxjs';
@@ -236,7 +236,12 @@ function toProvider(provide) {
236
236
  return runInInjectionContext(Injector.create({
237
237
  providers: [...existingProviders, { provide, useClass: provide, deps: deps }]
238
238
  }), () => {
239
- return inject(provide);
239
+ const instance = inject(provide);
240
+ if (instance instanceof FetchClient) {
241
+ const auth = pickAuthStrategy(BearerAuthFromSessionStorage, BasicAuth, CookieAuth);
242
+ instance.setAuth(auth);
243
+ }
244
+ return instance;
240
245
  });
241
246
  }
242
247
  };
@@ -248,15 +253,7 @@ function toProvider(provide) {
248
253
  function provideClientLibServices() {
249
254
  const providers = defaultServicesFromClientLib
250
255
  .map(service => toProvider(service))
251
- .concat([
252
- { provide: ApiService, useClass: ApiService, deps: [FetchClient] },
253
- // ensure that the auth strategy is set before the app is initialized
254
- provideAppInitializer(() => {
255
- const client = inject(FetchClient);
256
- const auth = pickAuthStrategy(BearerAuthFromSessionStorage, BasicAuth, CookieAuth);
257
- client.setAuth(auth);
258
- })
259
- ]);
256
+ .concat([{ provide: ApiService, useClass: ApiService, deps: [FetchClient] }]);
260
257
  return providers;
261
258
  }
262
259
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"c8y-ngx-components-api.mjs","sources":["../../api/interceptor.model.ts","../../api/http-handler.model.ts","../../api/api.service.ts","../../api/services.ts","../../api/data.module.ts","../../api/index.ts","../../api/c8y-ngx-components-api.ts"],"sourcesContent":["import { ApiCall } from './api.model';\nimport { Observable } from 'rxjs';\nimport { IFetchResponse } from '@c8y/client';\n\nexport interface HttpInterceptor {\n intercept(req: ApiCall, next: HttpHandler): Observable<IFetchResponse>;\n}\n\nexport abstract class HttpHandler {\n abstract handle(req: ApiCall): Observable<IFetchResponse>;\n}\n","import { ApiCall } from './api.model';\nimport { Observable, from } from 'rxjs';\nimport { FetchClient, IFetchResponse } from '@c8y/client';\nimport { HttpHandler, HttpInterceptor } from './interceptor.model';\n\nexport class HttpInterceptHandler extends HttpHandler {\n constructor(protected interceptor: HttpInterceptor, protected nextHandler: HttpHandler) {\n super();\n }\n\n handle(req: ApiCall): Observable<IFetchResponse> {\n return this.interceptor.intercept(req, this.nextHandler);\n }\n}\n\nexport interface RequestStartAndFinish {\n onStart(req: ApiCall): void;\n onFinish(res: ApiCall): void;\n}\n\nexport class HttpRequestHandler extends HttpHandler {\n constructor(protected fetch: FetchClient['fetch'], protected apiService?: RequestStartAndFinish) {\n super();\n }\n\n handle(req: ApiCall): Observable<IFetchResponse> {\n const { options, url } = req;\n const { method } = options;\n this.apiService?.onStart({ method, options, url });\n let fetchPromise = this.fetch(url, options);\n if (typeof options.responseInterceptor === 'function') {\n fetchPromise = fetchPromise.then(options.responseInterceptor);\n }\n fetchPromise.then(\n (response: IFetchResponse) => this.apiService?.onFinish({ method, options, url, response }),\n (response: IFetchResponse) => this.apiService?.onFinish({ method, options, url, response })\n );\n return from(fetchPromise);\n }\n}\n","import { Injectable } from '@angular/core';\nimport { FetchClient, IFetchOptions, IFetchResponse } from '@c8y/client';\nimport { MonoTypeOperatorFunction, Observable, Subject, pipe } from 'rxjs';\nimport { distinctUntilChanged, filter, map, scan, shareReplay } from 'rxjs/operators';\nimport { ApiCall, ApiCallOptions } from './api.model';\nimport {\n HttpInterceptHandler,\n HttpRequestHandler,\n RequestStartAndFinish\n} from './http-handler.model';\nimport { HttpHandler, HttpInterceptor } from './interceptor.model';\n\n@Injectable({\n providedIn: 'root'\n})\nexport class ApiService implements RequestStartAndFinish {\n calls: Observable<ApiCall>;\n isLoading$: Observable<boolean>;\n private callsSubject = new Subject<ApiCall>();\n private interceptors = new Map<string, HttpInterceptor>();\n private interceptorCounter = 0;\n\n constructor(private client: FetchClient) {\n this.calls = this.callsSubject.asObservable();\n this.hookIntoClientFetch();\n\n this.isLoading$ = this.calls.pipe(\n filter(({ url }) => !/notification\\/realtime/.test(url)),\n map(({ phase }) => (phase === 'start' ? 1 : -1)),\n scan((count, item) => count + item, 0),\n map(count => count > 0),\n distinctUntilChanged(),\n shareReplay(1)\n );\n }\n\n /**\n * Allows to hook into the responses received by the FetchClient.\n * This is meant to be used to react on the responses, not for manipulation of the responses.\n * @param hookFilter A filter function to filter for specific responses.\n * @returns An Observable of the filtered responses.\n */\n hookResponse(hookFilter: (call: ApiCall) => boolean): Observable<ApiCall> {\n return this.callsSubject.pipe(\n filter(({ phase }) => phase === 'finish'),\n filter(hookFilter)\n );\n }\n\n /**\n * Allows to hook into the requests performed by the FetchClient.\n * This is meant to be used to react on the requests, not for manipulation of the requests.\n * @param hookFilter A filter function to filter for specific requests.\n * @returns An Observable of the filtered requests.\n */\n hookRequest(hookFilter: (call: ApiCall) => boolean): Observable<ApiCall> {\n return this.callsSubject.pipe(\n filter(({ phase }) => phase === 'start'),\n filter(hookFilter)\n );\n }\n\n /**\n * Notifies observers that an API call has finished.\n * @param call The API call that has finished.\n */\n onFinish(call: ApiCall): void {\n this.callsSubject.next({ phase: 'finish', ...call });\n }\n\n /**\n * Notifies observers that an API call has started.\n * @param call The API call that has started.\n */\n onStart(call: ApiCall): void {\n this.callsSubject.next({ phase: 'start', ...call });\n }\n\n /**\n * Resolves data from an API call response.\n * @returns A Promise containing an object with resolved data, method, and URL.\n */\n resolveData<T = unknown>(call: ApiCall): Promise<{ data: T; method: string; url: string }> {\n const { response, method, url } = call;\n if ('data' in response) {\n return Promise.resolve({ data: response.data, method, url });\n } else {\n // No Content success status, for example DELETE request.\n if ((response as Response)?.status === 204) {\n return Promise.resolve({ data: null, method, url });\n }\n const cb = data => ({ data, method, url });\n return (response as Response).clone().json().then(cb, cb);\n }\n }\n\n /**\n * Can be added to a pipe to exclude any permission call. Permission calls are PUT\n * request with only an id in it, to verify if the user has access to this managed object.\n * @returns The operator to be added to a pipe.\n */\n excludePermissionCall(): MonoTypeOperatorFunction<ApiCall> {\n return pipe(\n filter(({ method, options }) => {\n if (method === 'PUT' && options.body && typeof options.body === 'string') {\n const parsedBody = JSON.parse(options.body as string);\n const bodyKeys = Object.keys(parsedBody);\n return !(bodyKeys.length === 1 && bodyKeys[0] === 'id');\n }\n return true;\n })\n );\n }\n\n /**\n * Allows to intercept requests performed via the FetchClient requests.\n * @param interceptor The interceptor to be added.\n * @param id An optional unique identifier for the interceptor. The chain of interceptors is ordered by this id. And it can be used to remove the interceptor later on.\n * @returns The id of the interceptor (same as provided id if one was provided, otherwise an id will be generated).\n */\n addInterceptor(interceptor: HttpInterceptor, id?: string): string {\n if (!id) {\n id = `${++this.interceptorCounter}`;\n }\n this.interceptors.set(id, interceptor);\n return id;\n }\n\n /**\n * Allows to remove a previously added interceptor by it's id.\n * @param id The id of the interceptor that should be removed.\n * @returns true if an interceptor existed and has been removed, or false if id does not exist.\n */\n removeInterceptor(id: string): boolean {\n return this.interceptors.delete(id);\n }\n\n /**\n * Checks if an interceptor with a given id exists.\n * @param id The id of the interceptor.\n * @returns - Returns true if an interceptor with the given id exists, otherwise false.\n */\n hasInterceptor(id: string): boolean {\n return this.interceptors.has(id);\n }\n\n private hookIntoClientFetch() {\n const fetch: FetchClient['fetch'] = this.client.fetch.bind(this.client);\n const requestHandler = new HttpRequestHandler(fetch, this);\n this.client.fetch = async (\n url,\n options: ApiCallOptions & IFetchOptions = { method: 'GET' }\n ) => {\n const { method } = options;\n return this.createInterceptorChain({ url, options, method }, requestHandler).toPromise();\n };\n }\n\n private createInterceptorChain(\n call: ApiCall,\n requestHandler: HttpRequestHandler\n ): Observable<IFetchResponse> {\n let handler: HttpHandler = requestHandler;\n // Do some sorting to always apply the interceptors in the specific order\n const sortedInterceptorIds = Array.from(this.interceptors.keys()).sort((a, b) =>\n b.localeCompare(a)\n );\n for (const interceptorId of sortedInterceptorIds) {\n handler = new HttpInterceptHandler(this.interceptors.get(interceptorId), handler);\n }\n return handler.handle(call);\n }\n}\n","import {\n FetchClient,\n BasicAuth,\n CookieAuth,\n Realtime,\n EventBinaryService,\n EventService,\n InventoryService,\n MeasurementService,\n AlarmService,\n OperationBulkService,\n OperationService,\n ApplicationService,\n UserService,\n TenantService,\n SystemOptionsService,\n TenantOptionsService,\n TenantSecurityOptionsService,\n TenantLoginOptionsService,\n AuditService,\n InventoryRoleService,\n InventoryBinaryService,\n DeviceRegistrationService,\n DeviceRegistrationBulkService,\n UserRoleService,\n UserGroupService,\n IdentityService,\n TrustedCertificateService,\n CrlService,\n SmartGroupsService,\n SmartRulesService,\n FeatureService\n} from '@c8y/client';\n\nexport const defaultServicesFromClientLib = [\n FetchClient,\n BasicAuth,\n CookieAuth,\n Realtime,\n EventBinaryService,\n EventService,\n InventoryService,\n MeasurementService,\n AlarmService,\n OperationBulkService,\n OperationService,\n ApplicationService,\n UserService,\n TenantService,\n SystemOptionsService,\n TenantOptionsService,\n TenantSecurityOptionsService,\n TenantLoginOptionsService,\n AuditService,\n InventoryRoleService,\n InventoryBinaryService,\n DeviceRegistrationService,\n DeviceRegistrationBulkService,\n UserRoleService,\n UserGroupService,\n IdentityService,\n TrustedCertificateService,\n CrlService,\n SmartGroupsService,\n SmartRulesService,\n FeatureService\n] as const;\n","import {\n inject,\n Injector,\n ModuleWithProviders,\n NgModule,\n Optional,\n provideAppInitializer,\n Provider,\n runInInjectionContext,\n SkipSelf,\n Type,\n ValueProvider\n} from '@angular/core';\nimport {\n BasicAuth,\n FetchClient,\n Realtime,\n CookieAuth,\n BearerAuthFromSessionStorage\n} from '@c8y/client';\nimport { ApiService } from './api.service';\nimport { defaultServicesFromClientLib } from './services';\nimport { pickAuthStrategy } from '@c8y/bootstrap';\n\nfunction toProvider<T>(provide: Type<T>): Provider {\n let deps: Array<Type<FetchClient | Realtime | CookieAuth>> = [FetchClient, Realtime];\n if (provide === FetchClient) {\n deps = [CookieAuth];\n }\n if (provide === BasicAuth || provide === CookieAuth) {\n deps = [];\n }\n if (provide === Realtime) {\n deps = [FetchClient];\n }\n const depsWithExistingProvider = [\n [provide, new Optional(), new SkipSelf()], // let's see if we can find an existing provider (possibly null)\n ...deps\n ];\n return {\n provide,\n deps: depsWithExistingProvider,\n useFactory: (...args) => {\n // if there was an existing provider, it would be first in the list and we can return it\n if (args.length && args[0] !== null) {\n return args[0];\n }\n\n // otherwise we need to drop the first element as it would be null\n const providers = args.slice(1);\n // the other providers are the dependencies we need. They match the order of the deps array\n const existingProviders: ValueProvider[] = deps.map((dep, index) => {\n return { provide: dep, useValue: providers[index] };\n });\n\n // use this to dependency inject the dependencies and instantiate the class\n return runInInjectionContext(\n Injector.create({\n providers: [...existingProviders, { provide, useClass: provide, deps: deps }]\n }),\n () => {\n return inject(provide);\n }\n );\n }\n };\n}\n\n/**\n * Provides all services from `@c8y/client` library.\n * @returns An array of providers for all services from `@c8y/client` library.\n */\nexport function provideClientLibServices(): Provider[] {\n const providers: Provider[] = defaultServicesFromClientLib\n .map(service => toProvider(service as any))\n .concat([\n { provide: ApiService, useClass: ApiService, deps: [FetchClient] },\n // ensure that the auth strategy is set before the app is initialized\n provideAppInitializer(() => {\n const client = inject(FetchClient);\n const auth = pickAuthStrategy(BearerAuthFromSessionStorage, BasicAuth, CookieAuth);\n client.setAuth(auth);\n })\n ]);\n return providers;\n}\n\n/**\n * @deprecated use provideClientLibServices instead\n */\n@NgModule({\n providers: provideClientLibServices()\n})\nexport class DataModule {\n static providers(): Provider[] {\n return provideClientLibServices();\n }\n static forRoot(): ModuleWithProviders<DataModule> {\n return {\n ngModule: DataModule,\n providers: provideClientLibServices()\n };\n }\n}\n","export * from './api.service';\nexport * from './api.model';\nexport * from './data.module';\nexport * from './services';\nexport * from './interceptor.model';\n// do not expose as it might confuse people on what to implement\n// export * from './http-handler.model';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"c8y-ngx-components-api.mjs","sources":["../../api/interceptor.model.ts","../../api/http-handler.model.ts","../../api/api.service.ts","../../api/services.ts","../../api/data.module.ts","../../api/index.ts","../../api/c8y-ngx-components-api.ts"],"sourcesContent":["import { ApiCall } from './api.model';\nimport { Observable } from 'rxjs';\nimport { IFetchResponse } from '@c8y/client';\n\nexport interface HttpInterceptor {\n intercept(req: ApiCall, next: HttpHandler): Observable<IFetchResponse>;\n}\n\nexport abstract class HttpHandler {\n abstract handle(req: ApiCall): Observable<IFetchResponse>;\n}\n","import { ApiCall } from './api.model';\nimport { Observable, from } from 'rxjs';\nimport { FetchClient, IFetchResponse } from '@c8y/client';\nimport { HttpHandler, HttpInterceptor } from './interceptor.model';\n\nexport class HttpInterceptHandler extends HttpHandler {\n constructor(protected interceptor: HttpInterceptor, protected nextHandler: HttpHandler) {\n super();\n }\n\n handle(req: ApiCall): Observable<IFetchResponse> {\n return this.interceptor.intercept(req, this.nextHandler);\n }\n}\n\nexport interface RequestStartAndFinish {\n onStart(req: ApiCall): void;\n onFinish(res: ApiCall): void;\n}\n\nexport class HttpRequestHandler extends HttpHandler {\n constructor(protected fetch: FetchClient['fetch'], protected apiService?: RequestStartAndFinish) {\n super();\n }\n\n handle(req: ApiCall): Observable<IFetchResponse> {\n const { options, url } = req;\n const { method } = options;\n this.apiService?.onStart({ method, options, url });\n let fetchPromise = this.fetch(url, options);\n if (typeof options.responseInterceptor === 'function') {\n fetchPromise = fetchPromise.then(options.responseInterceptor);\n }\n fetchPromise.then(\n (response: IFetchResponse) => this.apiService?.onFinish({ method, options, url, response }),\n (response: IFetchResponse) => this.apiService?.onFinish({ method, options, url, response })\n );\n return from(fetchPromise);\n }\n}\n","import { Injectable } from '@angular/core';\nimport { FetchClient, IFetchOptions, IFetchResponse } from '@c8y/client';\nimport { MonoTypeOperatorFunction, Observable, Subject, pipe } from 'rxjs';\nimport { distinctUntilChanged, filter, map, scan, shareReplay } from 'rxjs/operators';\nimport { ApiCall, ApiCallOptions } from './api.model';\nimport {\n HttpInterceptHandler,\n HttpRequestHandler,\n RequestStartAndFinish\n} from './http-handler.model';\nimport { HttpHandler, HttpInterceptor } from './interceptor.model';\n\n@Injectable({\n providedIn: 'root'\n})\nexport class ApiService implements RequestStartAndFinish {\n calls: Observable<ApiCall>;\n isLoading$: Observable<boolean>;\n private callsSubject = new Subject<ApiCall>();\n private interceptors = new Map<string, HttpInterceptor>();\n private interceptorCounter = 0;\n\n constructor(private client: FetchClient) {\n this.calls = this.callsSubject.asObservable();\n this.hookIntoClientFetch();\n\n this.isLoading$ = this.calls.pipe(\n filter(({ url }) => !/notification\\/realtime/.test(url)),\n map(({ phase }) => (phase === 'start' ? 1 : -1)),\n scan((count, item) => count + item, 0),\n map(count => count > 0),\n distinctUntilChanged(),\n shareReplay(1)\n );\n }\n\n /**\n * Allows to hook into the responses received by the FetchClient.\n * This is meant to be used to react on the responses, not for manipulation of the responses.\n * @param hookFilter A filter function to filter for specific responses.\n * @returns An Observable of the filtered responses.\n */\n hookResponse(hookFilter: (call: ApiCall) => boolean): Observable<ApiCall> {\n return this.callsSubject.pipe(\n filter(({ phase }) => phase === 'finish'),\n filter(hookFilter)\n );\n }\n\n /**\n * Allows to hook into the requests performed by the FetchClient.\n * This is meant to be used to react on the requests, not for manipulation of the requests.\n * @param hookFilter A filter function to filter for specific requests.\n * @returns An Observable of the filtered requests.\n */\n hookRequest(hookFilter: (call: ApiCall) => boolean): Observable<ApiCall> {\n return this.callsSubject.pipe(\n filter(({ phase }) => phase === 'start'),\n filter(hookFilter)\n );\n }\n\n /**\n * Notifies observers that an API call has finished.\n * @param call The API call that has finished.\n */\n onFinish(call: ApiCall): void {\n this.callsSubject.next({ phase: 'finish', ...call });\n }\n\n /**\n * Notifies observers that an API call has started.\n * @param call The API call that has started.\n */\n onStart(call: ApiCall): void {\n this.callsSubject.next({ phase: 'start', ...call });\n }\n\n /**\n * Resolves data from an API call response.\n * @returns A Promise containing an object with resolved data, method, and URL.\n */\n resolveData<T = unknown>(call: ApiCall): Promise<{ data: T; method: string; url: string }> {\n const { response, method, url } = call;\n if ('data' in response) {\n return Promise.resolve({ data: response.data, method, url });\n } else {\n // No Content success status, for example DELETE request.\n if ((response as Response)?.status === 204) {\n return Promise.resolve({ data: null, method, url });\n }\n const cb = data => ({ data, method, url });\n return (response as Response).clone().json().then(cb, cb);\n }\n }\n\n /**\n * Can be added to a pipe to exclude any permission call. Permission calls are PUT\n * request with only an id in it, to verify if the user has access to this managed object.\n * @returns The operator to be added to a pipe.\n */\n excludePermissionCall(): MonoTypeOperatorFunction<ApiCall> {\n return pipe(\n filter(({ method, options }) => {\n if (method === 'PUT' && options.body && typeof options.body === 'string') {\n const parsedBody = JSON.parse(options.body as string);\n const bodyKeys = Object.keys(parsedBody);\n return !(bodyKeys.length === 1 && bodyKeys[0] === 'id');\n }\n return true;\n })\n );\n }\n\n /**\n * Allows to intercept requests performed via the FetchClient requests.\n * @param interceptor The interceptor to be added.\n * @param id An optional unique identifier for the interceptor. The chain of interceptors is ordered by this id. And it can be used to remove the interceptor later on.\n * @returns The id of the interceptor (same as provided id if one was provided, otherwise an id will be generated).\n */\n addInterceptor(interceptor: HttpInterceptor, id?: string): string {\n if (!id) {\n id = `${++this.interceptorCounter}`;\n }\n this.interceptors.set(id, interceptor);\n return id;\n }\n\n /**\n * Allows to remove a previously added interceptor by it's id.\n * @param id The id of the interceptor that should be removed.\n * @returns true if an interceptor existed and has been removed, or false if id does not exist.\n */\n removeInterceptor(id: string): boolean {\n return this.interceptors.delete(id);\n }\n\n /**\n * Checks if an interceptor with a given id exists.\n * @param id The id of the interceptor.\n * @returns - Returns true if an interceptor with the given id exists, otherwise false.\n */\n hasInterceptor(id: string): boolean {\n return this.interceptors.has(id);\n }\n\n private hookIntoClientFetch() {\n const fetch: FetchClient['fetch'] = this.client.fetch.bind(this.client);\n const requestHandler = new HttpRequestHandler(fetch, this);\n this.client.fetch = async (\n url,\n options: ApiCallOptions & IFetchOptions = { method: 'GET' }\n ) => {\n const { method } = options;\n return this.createInterceptorChain({ url, options, method }, requestHandler).toPromise();\n };\n }\n\n private createInterceptorChain(\n call: ApiCall,\n requestHandler: HttpRequestHandler\n ): Observable<IFetchResponse> {\n let handler: HttpHandler = requestHandler;\n // Do some sorting to always apply the interceptors in the specific order\n const sortedInterceptorIds = Array.from(this.interceptors.keys()).sort((a, b) =>\n b.localeCompare(a)\n );\n for (const interceptorId of sortedInterceptorIds) {\n handler = new HttpInterceptHandler(this.interceptors.get(interceptorId), handler);\n }\n return handler.handle(call);\n }\n}\n","import {\n FetchClient,\n BasicAuth,\n CookieAuth,\n Realtime,\n EventBinaryService,\n EventService,\n InventoryService,\n MeasurementService,\n AlarmService,\n OperationBulkService,\n OperationService,\n ApplicationService,\n UserService,\n TenantService,\n SystemOptionsService,\n TenantOptionsService,\n TenantSecurityOptionsService,\n TenantLoginOptionsService,\n AuditService,\n InventoryRoleService,\n InventoryBinaryService,\n DeviceRegistrationService,\n DeviceRegistrationBulkService,\n UserRoleService,\n UserGroupService,\n IdentityService,\n TrustedCertificateService,\n CrlService,\n SmartGroupsService,\n SmartRulesService,\n FeatureService\n} from '@c8y/client';\n\nexport const defaultServicesFromClientLib = [\n FetchClient,\n BasicAuth,\n CookieAuth,\n Realtime,\n EventBinaryService,\n EventService,\n InventoryService,\n MeasurementService,\n AlarmService,\n OperationBulkService,\n OperationService,\n ApplicationService,\n UserService,\n TenantService,\n SystemOptionsService,\n TenantOptionsService,\n TenantSecurityOptionsService,\n TenantLoginOptionsService,\n AuditService,\n InventoryRoleService,\n InventoryBinaryService,\n DeviceRegistrationService,\n DeviceRegistrationBulkService,\n UserRoleService,\n UserGroupService,\n IdentityService,\n TrustedCertificateService,\n CrlService,\n SmartGroupsService,\n SmartRulesService,\n FeatureService\n] as const;\n","import {\n inject,\n Injector,\n ModuleWithProviders,\n NgModule,\n Optional,\n Provider,\n runInInjectionContext,\n SkipSelf,\n Type,\n ValueProvider\n} from '@angular/core';\nimport { pickAuthStrategy } from '@c8y/bootstrap';\nimport {\n BasicAuth,\n BearerAuthFromSessionStorage,\n CookieAuth,\n FetchClient,\n Realtime\n} from '@c8y/client';\nimport { ApiService } from './api.service';\nimport { defaultServicesFromClientLib } from './services';\n\nfunction toProvider<T>(provide: Type<T>): Provider {\n let deps: Array<Type<FetchClient | Realtime | CookieAuth>> = [FetchClient, Realtime];\n if (provide === FetchClient) {\n deps = [CookieAuth];\n }\n if (provide === BasicAuth || provide === CookieAuth) {\n deps = [];\n }\n if (provide === Realtime) {\n deps = [FetchClient];\n }\n const depsWithExistingProvider = [\n [provide, new Optional(), new SkipSelf()], // let's see if we can find an existing provider (possibly null)\n ...deps\n ];\n return {\n provide,\n deps: depsWithExistingProvider,\n useFactory: (...args) => {\n // if there was an existing provider, it would be first in the list and we can return it\n if (args.length && args[0] !== null) {\n return args[0];\n }\n\n // otherwise we need to drop the first element as it would be null\n const providers = args.slice(1);\n // the other providers are the dependencies we need. They match the order of the deps array\n const existingProviders: ValueProvider[] = deps.map((dep, index) => {\n return { provide: dep, useValue: providers[index] };\n });\n\n // use this to dependency inject the dependencies and instantiate the class\n return runInInjectionContext(\n Injector.create({\n providers: [...existingProviders, { provide, useClass: provide, deps: deps }]\n }),\n () => {\n const instance = inject(provide);\n if (instance instanceof FetchClient) {\n const auth = pickAuthStrategy(BearerAuthFromSessionStorage, BasicAuth, CookieAuth);\n instance.setAuth(auth);\n }\n return instance;\n }\n );\n }\n };\n}\n\n/**\n * Provides all services from `@c8y/client` library.\n * @returns An array of providers for all services from `@c8y/client` library.\n */\nexport function provideClientLibServices(): Provider[] {\n const providers: Provider[] = defaultServicesFromClientLib\n .map(service => toProvider(service as any))\n .concat([{ provide: ApiService, useClass: ApiService, deps: [FetchClient] }]);\n return providers;\n}\n\n/**\n * @deprecated use provideClientLibServices instead\n */\n@NgModule({\n providers: provideClientLibServices()\n})\nexport class DataModule {\n static providers(): Provider[] {\n return provideClientLibServices();\n }\n static forRoot(): ModuleWithProviders<DataModule> {\n return {\n ngModule: DataModule,\n providers: provideClientLibServices()\n };\n }\n}\n","export * from './api.service';\nexport * from './api.model';\nexport * from './data.module';\nexport * from './services';\nexport * from './interceptor.model';\n// do not expose as it might confuse people on what to implement\n// export * from './http-handler.model';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -12,6 +12,7 @@ import { PopoverDirective, PopoverModule } from 'ngx-bootstrap/popover';
12
12
  import { TooltipDirective, TooltipModule } from 'ngx-bootstrap/tooltip';
13
13
  import * as i3 from '@c8y/client';
14
14
  import { isUndefined, uniqBy, startCase } from 'lodash-es';
15
+ import { combineLatest } from 'rxjs';
15
16
  import { take, map, filter } from 'rxjs/operators';
16
17
  import * as i5 from '@angular/forms';
17
18
  import { FormsModule } from '@angular/forms';
@@ -43,7 +44,9 @@ const DEFAULT_CONFIG = {
43
44
  class: 'c8y-cockpit'
44
45
  },
45
46
  htmlWidgetDisableSanitization: false,
46
- htmlWidgetDefaultToAdvancedMode: false
47
+ htmlWidgetDefaultToAdvancedMode: false,
48
+ showAssetsAsTopNode: false,
49
+ showGroupsAsTopNode: false
47
50
  };
48
51
  var HomeDashboardType;
49
52
  (function (HomeDashboardType) {
@@ -128,7 +131,10 @@ class CockpitConfigService {
128
131
  this.currentConfig = { ...DEFAULT_CONFIG, ...config };
129
132
  }
130
133
  });
131
- this.appState.currentApplicationConfig.pipe(take(1)).subscribe(() => {
134
+ // if currentUser and currentApplicationConfig are ready, we set the root nodes
135
+ combineLatest([this.appState.currentUser, this.appState.currentApplicationConfig])
136
+ .pipe(take(1))
137
+ .subscribe(() => {
132
138
  this.setRootNodes();
133
139
  });
134
140
  }
@@ -174,6 +180,12 @@ class CockpitConfigService {
174
180
  async setRootNodes() {
175
181
  this.addNodesToFactories();
176
182
  this.nodes.length = 0;
183
+ if (this.currentConfig.showAssetsAsTopNode) {
184
+ await this.setTopNodeList('asset');
185
+ }
186
+ if (this.currentConfig.showGroupsAsTopNode) {
187
+ await this.setTopNodeList('group');
188
+ }
177
189
  for (const node of this.currentConfig.rootNodes) {
178
190
  try {
179
191
  const { data } = await this.inventoryService.detail(node.id);
@@ -197,6 +209,31 @@ class CockpitConfigService {
197
209
  getAppDashboardName() {
198
210
  return `${DEFAULT_HOME_DASHBOARD_NAME.substring(0, DEFAULT_HOME_DASHBOARD_NAME.length - 1)}_${this.appState.state.app.id}`;
199
211
  }
212
+ async setTopNodeList(type) {
213
+ try {
214
+ const { data } = await this.inventoryService.list({
215
+ query: type === 'asset'
216
+ ? '$filter=(has(c8y_IsAsset)) $orderby=name asc'
217
+ : '$filter=(has(c8y_IsDeviceGroup) and not(has(c8y_IsAsset))) $orderby=name asc',
218
+ pageSize: 500,
219
+ onlyRoots: true
220
+ });
221
+ if (data && data.length > 0) {
222
+ data.forEach(asset => {
223
+ this.nodes.push(this.assetNodeService.createAssetNode({
224
+ mo: asset,
225
+ hideDevices: false,
226
+ priority: isUndefined(this.moduleConfig?.rootNodePriority)
227
+ ? this.DEFAULT_NODE_PRIORITY
228
+ : this.moduleConfig.rootNodePriority
229
+ }));
230
+ });
231
+ }
232
+ }
233
+ catch (error) {
234
+ // do nothing
235
+ }
236
+ }
200
237
  async storeApplicationConfig(config) {
201
238
  await this.appState.updateCurrentApplicationConfig(config);
202
239
  }
@@ -329,7 +366,7 @@ class RootNodeConfigComponent {
329
366
  }
330
367
  }
331
368
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: RootNodeConfigComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
332
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: RootNodeConfigComponent, isStandalone: true, selector: "c8y-root-node-config", inputs: { config: "config", disabled: "disabled" }, outputs: { onUpdate: "onUpdate" }, ngImport: i0, template: "<div class=\"col-sm-6\">\n <label\n title=\"{{ 'Current top level nodes' | translate }}\"\n translate\n >\n Current top level nodes\n </label>\n <c8y-list-group class=\"separator-top\">\n @if (config.rootNodes.length === 0) {\n <c8y-li>\n <c8y-ui-empty-state\n [icon]=\"'folder-open'\"\n [title]=\"'No top level nodes set.' | translate\"\n [horizontal]=\"true\"\n ></c8y-ui-empty-state>\n </c8y-li>\n }\n @for (node of config.rootNodes; track node.id; let index = $index) {\n <c8y-li>\n @if (node.id | getGroupIcon | async; as icon) {\n <c8y-li-icon [icon]=\"icon\"></c8y-li-icon>\n } @else {\n <c8y-li-icon\n class=\"icon-spin loadingIndicator\"\n [icon]=\"'circle-o-notch'\"\n ></c8y-li-icon>\n }\n <div class=\"content-flex-30\">\n <div class=\"col-6\">\n <div\n class=\"text-truncate\"\n title=\"{{ node.name }}\"\n >\n {{ node.name }}\n </div>\n </div>\n <div class=\"col-4\">\n <label\n class=\"c8y-switch c8y-switch--inline d-flex\"\n title=\"{{ 'Hide devices' | translate }}\"\n >\n <input\n name=\"node.{{ index }}.hideDevices\"\n type=\"checkbox\"\n [(ngModel)]=\"node.hideDevices\"\n (change)=\"onUpdate.emit()\"\n [disabled]=\"disabled\"\n />\n <span></span>\n <small class=\"text-truncate a-s-center l-h-1\">{{ 'Hide devices' | translate }}</small>\n </label>\n </div>\n <div class=\"col-2 text-right\">\n <div class=\"d-flex fit-w\">\n <button\n class=\"btn-dot btn-dot--danger m-l-auto\"\n [attr.aria-label]=\"'Remove' | translate\"\n tooltip=\"{{ 'Remove' | translate }}\"\n type=\"button\"\n [disabled]=\"disabled\"\n [delay]=\"500\"\n (click)=\"removeNavigatorNode(node)\"\n >\n <i c8yIcon=\"minus-circle\"></i>\n </button>\n </div>\n </div>\n </div>\n </c8y-li>\n }\n </c8y-list-group>\n</div>\n\n<div\n class=\"col-sm-6 col-md-5\"\n style=\"height: calc(100vh - 430px)\"\n>\n <label\n title=\"{{ 'Select top level nodes' | translate }}\"\n translate\n >\n Select top level nodes\n </label>\n <c8y-asset-selector\n class=\"border-top d-block\"\n name=\"rootNodes\"\n [config]=\"{ groupsOnly: true, multi: true, groupsSelectable: true }\"\n [(ngModel)]=\"config.rootNodes\"\n [disabled]=\"disabled\"\n (onSelected)=\"onUpdate.emit()\"\n ></c8y-asset-selector>\n</div>\n", dependencies: [{ kind: "directive", type: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "component", type: ListGroupComponent, selector: "c8y-list-group" }, { kind: "component", type: ListItemComponent, selector: "c8y-list-item, c8y-li", inputs: ["active", "highlighted", "emptyActions", "dense", "collapsed", "selectable"], outputs: ["collapsedChange"] }, { kind: "component", type: EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "component", type: ListItemIconComponent, selector: "c8y-list-item-icon, c8y-li-icon", inputs: ["icon", "status"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i5.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: TooltipDirective, selector: "[tooltip], [tooltipHtml]", inputs: ["adaptivePosition", "tooltip", "placement", "triggers", "container", "containerClass", "boundariesElement", "isOpen", "isDisabled", "delay", "tooltipHtml", "tooltipPlacement", "tooltipIsOpen", "tooltipEnable", "tooltipAppendToBody", "tooltipAnimation", "tooltipClass", "tooltipContext", "tooltipPopupDelay", "tooltipFadeDuration", "tooltipTrigger"], outputs: ["tooltipChange", "onShown", "onHidden", "tooltipStateChanged"], exportAs: ["bs-tooltip"] }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "component", type: AssetSelectorComponent, selector: "c8y-asset-selector", inputs: ["config", "active", "index", "asset", "selectedDevice", "selected", "rootNode", "selectedItems", "container", "isNodeSelectable", "disabled"], outputs: ["onSelected", "onClearSelected", "onRowSelected", "onLoad"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: GetGroupIconPipe, name: "getGroupIcon" }] }); }
369
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: RootNodeConfigComponent, isStandalone: true, selector: "c8y-root-node-config", inputs: { config: "config", disabled: "disabled" }, outputs: { onUpdate: "onUpdate" }, ngImport: i0, template: "<div class=\"col-sm-6\">\n <label\n title=\"{{ 'Current top level nodes' | translate }}\"\n translate\n >\n Current top level nodes\n </label>\n <c8y-list-group class=\"separator-top\">\n @if (config.rootNodes.length === 0) {\n <c8y-li>\n <c8y-ui-empty-state\n [icon]=\"'folder-open'\"\n [title]=\"'No top level nodes set.' | translate\"\n [horizontal]=\"true\"\n ></c8y-ui-empty-state>\n </c8y-li>\n }\n @for (node of config.rootNodes; track node.id; let index = $index) {\n <c8y-li>\n @if (node.id | getGroupIcon | async; as icon) {\n <c8y-li-icon [icon]=\"icon\"></c8y-li-icon>\n } @else {\n <c8y-li-icon\n class=\"icon-spin loadingIndicator\"\n [icon]=\"'circle-o-notch'\"\n ></c8y-li-icon>\n }\n <div class=\"content-flex-30\">\n <div class=\"col-6\">\n <div\n class=\"text-truncate\"\n title=\"{{ node.name }}\"\n >\n {{ node.name }}\n </div>\n </div>\n <div class=\"col-4\">\n <label\n class=\"c8y-switch c8y-switch--inline d-flex\"\n title=\"{{ 'Hide devices' | translate }}\"\n >\n <input\n name=\"node.{{ index }}.hideDevices\"\n type=\"checkbox\"\n [(ngModel)]=\"node.hideDevices\"\n (change)=\"onUpdate.emit()\"\n [disabled]=\"disabled\"\n />\n <span></span>\n <small class=\"text-truncate a-s-center l-h-1\">{{ 'Hide devices' | translate }}</small>\n </label>\n </div>\n <div class=\"col-2 text-right\">\n <div class=\"d-flex fit-w\">\n <button\n class=\"btn-dot btn-dot--danger m-l-auto\"\n [attr.aria-label]=\"'Remove' | translate\"\n tooltip=\"{{ 'Remove' | translate }}\"\n type=\"button\"\n [disabled]=\"disabled\"\n [delay]=\"500\"\n (click)=\"removeNavigatorNode(node)\"\n >\n <i c8yIcon=\"minus-circle\"></i>\n </button>\n </div>\n </div>\n </div>\n </c8y-li>\n }\n </c8y-list-group>\n</div>\n\n<div class=\"col-sm-6 col-md-5\">\n <label\n title=\"{{ 'Select top level nodes' | translate }}\"\n translate\n >\n Select top level nodes\n </label>\n <c8y-asset-selector\n class=\"border-top d-block\"\n name=\"rootNodes\"\n [config]=\"{ groupsOnly: true, multi: true, groupsSelectable: true }\"\n [(ngModel)]=\"config.rootNodes\"\n [disabled]=\"disabled\"\n (onSelected)=\"onUpdate.emit()\"\n ></c8y-asset-selector>\n</div>\n", dependencies: [{ kind: "directive", type: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "component", type: ListGroupComponent, selector: "c8y-list-group" }, { kind: "component", type: ListItemComponent, selector: "c8y-list-item, c8y-li", inputs: ["active", "highlighted", "emptyActions", "dense", "collapsed", "selectable"], outputs: ["collapsedChange"] }, { kind: "component", type: EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "component", type: ListItemIconComponent, selector: "c8y-list-item-icon, c8y-li-icon", inputs: ["icon", "status"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i5.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: TooltipDirective, selector: "[tooltip], [tooltipHtml]", inputs: ["adaptivePosition", "tooltip", "placement", "triggers", "container", "containerClass", "boundariesElement", "isOpen", "isDisabled", "delay", "tooltipHtml", "tooltipPlacement", "tooltipIsOpen", "tooltipEnable", "tooltipAppendToBody", "tooltipAnimation", "tooltipClass", "tooltipContext", "tooltipPopupDelay", "tooltipFadeDuration", "tooltipTrigger"], outputs: ["tooltipChange", "onShown", "onHidden", "tooltipStateChanged"], exportAs: ["bs-tooltip"] }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "component", type: AssetSelectorComponent, selector: "c8y-asset-selector", inputs: ["config", "active", "index", "asset", "selectedDevice", "selected", "rootNode", "selectedItems", "container", "isNodeSelectable", "disabled"], outputs: ["onSelected", "onClearSelected", "onRowSelected", "onLoad"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: GetGroupIconPipe, name: "getGroupIcon" }] }); }
333
370
  }
334
371
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: RootNodeConfigComponent, decorators: [{
335
372
  type: Component,
@@ -346,7 +383,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
346
383
  C8yTranslatePipe,
347
384
  AsyncPipe,
348
385
  GetGroupIconPipe
349
- ], template: "<div class=\"col-sm-6\">\n <label\n title=\"{{ 'Current top level nodes' | translate }}\"\n translate\n >\n Current top level nodes\n </label>\n <c8y-list-group class=\"separator-top\">\n @if (config.rootNodes.length === 0) {\n <c8y-li>\n <c8y-ui-empty-state\n [icon]=\"'folder-open'\"\n [title]=\"'No top level nodes set.' | translate\"\n [horizontal]=\"true\"\n ></c8y-ui-empty-state>\n </c8y-li>\n }\n @for (node of config.rootNodes; track node.id; let index = $index) {\n <c8y-li>\n @if (node.id | getGroupIcon | async; as icon) {\n <c8y-li-icon [icon]=\"icon\"></c8y-li-icon>\n } @else {\n <c8y-li-icon\n class=\"icon-spin loadingIndicator\"\n [icon]=\"'circle-o-notch'\"\n ></c8y-li-icon>\n }\n <div class=\"content-flex-30\">\n <div class=\"col-6\">\n <div\n class=\"text-truncate\"\n title=\"{{ node.name }}\"\n >\n {{ node.name }}\n </div>\n </div>\n <div class=\"col-4\">\n <label\n class=\"c8y-switch c8y-switch--inline d-flex\"\n title=\"{{ 'Hide devices' | translate }}\"\n >\n <input\n name=\"node.{{ index }}.hideDevices\"\n type=\"checkbox\"\n [(ngModel)]=\"node.hideDevices\"\n (change)=\"onUpdate.emit()\"\n [disabled]=\"disabled\"\n />\n <span></span>\n <small class=\"text-truncate a-s-center l-h-1\">{{ 'Hide devices' | translate }}</small>\n </label>\n </div>\n <div class=\"col-2 text-right\">\n <div class=\"d-flex fit-w\">\n <button\n class=\"btn-dot btn-dot--danger m-l-auto\"\n [attr.aria-label]=\"'Remove' | translate\"\n tooltip=\"{{ 'Remove' | translate }}\"\n type=\"button\"\n [disabled]=\"disabled\"\n [delay]=\"500\"\n (click)=\"removeNavigatorNode(node)\"\n >\n <i c8yIcon=\"minus-circle\"></i>\n </button>\n </div>\n </div>\n </div>\n </c8y-li>\n }\n </c8y-list-group>\n</div>\n\n<div\n class=\"col-sm-6 col-md-5\"\n style=\"height: calc(100vh - 430px)\"\n>\n <label\n title=\"{{ 'Select top level nodes' | translate }}\"\n translate\n >\n Select top level nodes\n </label>\n <c8y-asset-selector\n class=\"border-top d-block\"\n name=\"rootNodes\"\n [config]=\"{ groupsOnly: true, multi: true, groupsSelectable: true }\"\n [(ngModel)]=\"config.rootNodes\"\n [disabled]=\"disabled\"\n (onSelected)=\"onUpdate.emit()\"\n ></c8y-asset-selector>\n</div>\n" }]
386
+ ], template: "<div class=\"col-sm-6\">\n <label\n title=\"{{ 'Current top level nodes' | translate }}\"\n translate\n >\n Current top level nodes\n </label>\n <c8y-list-group class=\"separator-top\">\n @if (config.rootNodes.length === 0) {\n <c8y-li>\n <c8y-ui-empty-state\n [icon]=\"'folder-open'\"\n [title]=\"'No top level nodes set.' | translate\"\n [horizontal]=\"true\"\n ></c8y-ui-empty-state>\n </c8y-li>\n }\n @for (node of config.rootNodes; track node.id; let index = $index) {\n <c8y-li>\n @if (node.id | getGroupIcon | async; as icon) {\n <c8y-li-icon [icon]=\"icon\"></c8y-li-icon>\n } @else {\n <c8y-li-icon\n class=\"icon-spin loadingIndicator\"\n [icon]=\"'circle-o-notch'\"\n ></c8y-li-icon>\n }\n <div class=\"content-flex-30\">\n <div class=\"col-6\">\n <div\n class=\"text-truncate\"\n title=\"{{ node.name }}\"\n >\n {{ node.name }}\n </div>\n </div>\n <div class=\"col-4\">\n <label\n class=\"c8y-switch c8y-switch--inline d-flex\"\n title=\"{{ 'Hide devices' | translate }}\"\n >\n <input\n name=\"node.{{ index }}.hideDevices\"\n type=\"checkbox\"\n [(ngModel)]=\"node.hideDevices\"\n (change)=\"onUpdate.emit()\"\n [disabled]=\"disabled\"\n />\n <span></span>\n <small class=\"text-truncate a-s-center l-h-1\">{{ 'Hide devices' | translate }}</small>\n </label>\n </div>\n <div class=\"col-2 text-right\">\n <div class=\"d-flex fit-w\">\n <button\n class=\"btn-dot btn-dot--danger m-l-auto\"\n [attr.aria-label]=\"'Remove' | translate\"\n tooltip=\"{{ 'Remove' | translate }}\"\n type=\"button\"\n [disabled]=\"disabled\"\n [delay]=\"500\"\n (click)=\"removeNavigatorNode(node)\"\n >\n <i c8yIcon=\"minus-circle\"></i>\n </button>\n </div>\n </div>\n </div>\n </c8y-li>\n }\n </c8y-list-group>\n</div>\n\n<div class=\"col-sm-6 col-md-5\">\n <label\n title=\"{{ 'Select top level nodes' | translate }}\"\n translate\n >\n Select top level nodes\n </label>\n <c8y-asset-selector\n class=\"border-top d-block\"\n name=\"rootNodes\"\n [config]=\"{ groupsOnly: true, multi: true, groupsSelectable: true }\"\n [(ngModel)]=\"config.rootNodes\"\n [disabled]=\"disabled\"\n (onSelected)=\"onUpdate.emit()\"\n ></c8y-asset-selector>\n</div>\n" }]
350
387
  }], propDecorators: { config: [{
351
388
  type: Input
352
389
  }], disabled: [{
@@ -469,7 +506,7 @@ class CockpitConfigurationComponent {
469
506
  this.rootNodeDisabled = false;
470
507
  }
471
508
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: CockpitConfigurationComponent, deps: [{ token: CockpitConfigService }, { token: i1.AlertService }, { token: i1.AppStateService }], target: i0.ɵɵFactoryTarget.Component }); }
472
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: CockpitConfigurationComponent, isStandalone: true, selector: "c8y-cockpit-configuration", ngImport: i0, template: "<c8y-title>{{ 'Application configuration' | translate }}</c8y-title>\n<c8y-breadcrumb>\n <c8y-breadcrumb-item\n [icon]=\"'c8y-tools'\"\n [label]=\"'Configuration' | translate\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item\n [icon]=\"'c8y-tools'\"\n [label]=\"'Application configuration' | translate\"\n ></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n<div class=\"row\">\n <div class=\"col-lg-12 col-lg-max\">\n <form #configForm=\"ngForm\">\n <div class=\"card card--fullpage\">\n <div class=\"card-header separator\">\n <div class=\"card-title\">\n {{ config.appTitle || ('Cockpit' | translate) }} {{ 'configuration' | translate }}\n </div>\n </div>\n\n <div class=\"inner-scroll\">\n <div class=\"card-block p-t-0 p-b-0\">\n <fieldset class=\"row separator-bottom p-t-24 p-b-24\">\n <div class=\"col-xs-12 col-sm-3 col-md-2 text-left-xs text-right-sm\">\n <div\n class=\"h4 text-medium d-inline-block m-r-4\"\n translate\n >\n Title, icon, and navigator collapse\n </div>\n </div>\n <div class=\"col-xs-12 col-sm-9 col-md-8 p-l-16\">\n <div class=\"d-flex a-i-start gap-16\">\n <div class=\"form-group d-inline-block\">\n <label>{{ 'Icon' | translate }}</label>\n <c8y-icon-selector-wrapper\n [selectedIcon]=\"config?.icon?.class || 'c8y-cockpit'\"\n [iconSize]=\"24\"\n (onSelect)=\"iconSelectionChange($event)\"\n ></c8y-icon-selector-wrapper>\n </div>\n <div class=\"form-group flex-grow\">\n <label\n for=\"confAppTitle\"\n translate\n >\n Change application title\n </label>\n <input\n class=\"form-control\"\n id=\"confAppTitle\"\n placeholder=\"{{ 'e.g. Cockpit' | translate }} \"\n type=\"text\"\n maxlength=\"254\"\n [(ngModel)]=\"config.appTitle\"\n [ngModelOptions]=\"{ standalone: true }\"\n />\n </div>\n </div>\n\n <c8y-misc-config [config]=\"config\"></c8y-misc-config>\n </div>\n </fieldset>\n <fieldset class=\"row separator-bottom p-t-24 p-b-24\">\n <div class=\"col-xs-12 col-sm-3 col-md-2 text-left-xs text-right-sm\">\n <div class=\"d-inline-flex m-b-16\">\n <div\n class=\"h4 text-medium m-r-4\"\n translate\n >\n Features\n </div>\n <button\n class=\"btn-help btn-help--sm\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{\n 'Define which are the enabled features in the current application.'\n | translate\n }}\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n ></button>\n </div>\n </div>\n <div class=\"col-xs-12 col-sm-9 col-md-8\">\n <c8y-feature-config\n [config]=\"config\"\n (onUpdate)=\"updateFeatures()\"\n ></c8y-feature-config>\n </div>\n </fieldset>\n <fieldset class=\"row separator-bottom p-t-24 p-b-24\">\n <div class=\"col-xs-12 col-sm-3 col-md-2 text-left-xs text-right-sm\">\n <div class=\"d-inline-flex m-b-16\">\n <div\n class=\"h4 text-medium m-r-8\"\n translate\n >\n Top level nodes\n </div>\n <button\n class=\"btn-help btn-help--sm\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{\n 'Select which nodes to display in the top level of the navigator menu. By default, only Groups is shown.'\n | translate\n }}\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n ></button>\n </div>\n </div>\n <div class=\"col-xs-12 col-sm-10 col-md-10\">\n <div class=\"row\">\n <c8y-root-node-config\n [config]=\"config\"\n (onUpdate)=\"updateRootNodes()\"\n [disabled]=\"rootNodeDisabled\"\n ></c8y-root-node-config>\n </div>\n </div>\n </fieldset>\n\n <fieldset\n class=\"row separator-bottom p-t-24 p-b-24\"\n *ngIf=\"'CockpitDashboardModule' | c8yPluginLoaded | async\"\n >\n <div class=\"col-xs-12 col-sm-3 col-md-2 text-left-xs text-right-sm\">\n <div class=\"d-inline-flex m-b-16\">\n <div\n class=\"h4 text-medium m-r-8\"\n translate\n >\n Home dashboard\n </div>\n <button\n class=\"btn-help btn-help--sm\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{\n 'The homepage of this application. By default, it is a customizable dashboard displaying the most important alarms and shortcuts to frequently used features.'\n | translate\n }}\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n ></button>\n </div>\n </div>\n <div class=\"col-xs-12 col-sm-9 col-md-8\">\n <c8y-home-dashboard-config [config]=\"config\"></c8y-home-dashboard-config>\n </div>\n </fieldset>\n\n <fieldset\n class=\"row p-t-24 p-b-24\"\n *ngIf=\"'htmlWidgetProviders' | c8yPluginLoaded | async\"\n >\n <div class=\"col-xs-12 col-sm-3 col-md-2 text-left-xs text-right-sm\">\n <div class=\"d-inline-flex m-b-16\">\n <div\n class=\"h4 text-medium m-r-8\"\n translate\n >\n HTML widget\n </div>\n </div>\n </div>\n <div class=\"col-xs-12 col-sm-9 col-md-8\">\n <c8y-li>\n <c8y-li-icon icon=\"code1\"></c8y-li-icon>\n <div class=\"d-flex a-i-center\">\n <div class=\"p-r-16\">\n <p> {{ 'Disable sanitization' | translate }}</p>\n <p>\n <small translate>\n By default, every unsecure HTML is removed from the HTML widget. You can disable\n this behavior in this application and allow unsecure HTML to be used.\n </small>\n </p>\n </div>\n <label class=\"c8y-switch c8y-switch--inline m-l-auto\">\n <input\n [attr.aria-label]=\"'Disable sanitization' | translate\"\n name=\"htmlWidgetDisableSanitization\"\n type=\"checkbox\"\n [(ngModel)]=\"config.htmlWidgetDisableSanitization\"\n />\n <span></span>\n </label>\n </div>\n </c8y-li>\n <c8y-li class=\"\">\n <c8y-li-icon icon=\"settings\"></c8y-li-icon>\n <div class=\"d-flex a-i-center\">\n <div class=\"p-r-16\">\n <p>{{ 'Enforce advanced mode' | translate }}</p>\n <p>\n <small translate>\n If set to true, the HTML widget configuration will always be opened in the advanced mode\n (web component mode).\n </small>\n </p>\n </div>\n <label class=\"c8y-switch c8y-switch--inline m-l-auto\">\n <input\n [attr.aria-label]=\"'Enforce advanced mode' | translate\"\n name=\"htmlWidgetDefaultToAdvancedMode\"\n type=\"checkbox\"\n [(ngModel)]=\"config.htmlWidgetDefaultToAdvancedMode\"\n />\n <span></span>\n </label>\n </div>\n </c8y-li>\n </div>\n </fieldset>\n </div>\n </div>\n <div class=\"card-footer separator\">\n <button\n class=\"btn btn-primary\"\n title=\"{{ 'Save' | translate }}\"\n type=\"submit\"\n [disabled]=\"!configForm.form.valid\"\n (click)=\"save()\"\n [actionName]=\"'cockpitConfigurationSaved'\"\n [actionData]=\"{ config: config }\"\n c8yProductExperience\n >\n {{ 'Save' | translate }}\n </button>\n </div>\n </div>\n </form>\n </div>\n</div>\n", dependencies: [{ kind: "component", type: TitleComponent, selector: "c8y-title", inputs: ["pageTitleUpdate"] }, { kind: "component", type: BreadcrumbComponent, selector: "c8y-breadcrumb" }, { kind: "component", type: BreadcrumbItemComponent, selector: "c8y-breadcrumb-item", inputs: ["icon", "translate", "label", "path", "injector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i5.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i5.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: i5.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i5.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i5.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "component", type: IconSelectorWrapperComponent, selector: "c8y-icon-selector-wrapper", inputs: ["canRemoveIcon", "selectedIcon", "iconSize"], outputs: ["onSelect"] }, { kind: "component", type: MiscConfigComponent, selector: "c8y-misc-config", inputs: ["config"] }, { kind: "directive", type: PopoverDirective, selector: "[popover]", inputs: ["adaptivePosition", "boundariesElement", "popover", "popoverContext", "popoverTitle", "placement", "outsideClick", "triggers", "container", "containerClass", "isOpen", "delay"], outputs: ["onShown", "onHidden"], exportAs: ["bs-popover"] }, { kind: "component", type: FeatureConfigComponent, selector: "c8y-feature-config", inputs: ["config"], outputs: ["onUpdate"] }, { kind: "component", type: RootNodeConfigComponent, selector: "c8y-root-node-config", inputs: ["config", "disabled"], outputs: ["onUpdate"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: HomeDashboardConfigComponent, selector: "c8y-home-dashboard-config", inputs: ["config"] }, { kind: "component", type: ListItemComponent, selector: "c8y-list-item, c8y-li", inputs: ["active", "highlighted", "emptyActions", "dense", "collapsed", "selectable"], outputs: ["collapsedChange"] }, { kind: "component", type: ListItemIconComponent, selector: "c8y-list-item-icon, c8y-li-icon", inputs: ["icon", "status"] }, { kind: "directive", type: ProductExperienceDirective, selector: "[c8yProductExperience]", inputs: ["actionName", "actionData", "inherit", "suppressDataOverriding"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: PluginLoadedPipe, name: "c8yPluginLoaded" }] }); }
509
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: CockpitConfigurationComponent, isStandalone: true, selector: "c8y-cockpit-configuration", ngImport: i0, template: "<c8y-title>{{ 'Application configuration' | translate }}</c8y-title>\n<c8y-breadcrumb>\n <c8y-breadcrumb-item\n [icon]=\"'c8y-tools'\"\n [label]=\"'Configuration' | translate\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item\n [icon]=\"'c8y-tools'\"\n [label]=\"'Application configuration' | translate\"\n ></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n<div class=\"row\">\n <div class=\"col-lg-12 col-lg-max\">\n <form #configForm=\"ngForm\">\n <div class=\"card card--fullpage\">\n <div class=\"card-header separator\">\n <div class=\"card-title\">\n {{ config.appTitle || ('Cockpit' | translate) }} {{ 'configuration' | translate }}\n </div>\n </div>\n\n <div class=\"inner-scroll\">\n <div class=\"card-block p-t-0 p-b-0\">\n <fieldset class=\"row separator-bottom p-t-24 p-b-24\">\n <div class=\"col-xs-12 col-sm-3 col-md-2 text-left-xs text-right-sm\">\n <div\n class=\"h4 text-medium d-inline-block m-r-4\"\n translate\n >\n Title, icon, and navigator collapse\n </div>\n </div>\n <div class=\"col-xs-12 col-sm-9 col-md-8 p-l-16\">\n <div class=\"d-flex a-i-start gap-16\">\n <div class=\"form-group d-inline-block\">\n <label>{{ 'Icon' | translate }}</label>\n <c8y-icon-selector-wrapper\n [selectedIcon]=\"config?.icon?.class || 'c8y-cockpit'\"\n [iconSize]=\"24\"\n (onSelect)=\"iconSelectionChange($event)\"\n ></c8y-icon-selector-wrapper>\n </div>\n <div class=\"form-group flex-grow\">\n <label\n for=\"confAppTitle\"\n translate\n >\n Change application title\n </label>\n <input\n class=\"form-control\"\n id=\"confAppTitle\"\n placeholder=\"{{ 'e.g. Cockpit' | translate }} \"\n type=\"text\"\n maxlength=\"254\"\n [(ngModel)]=\"config.appTitle\"\n [ngModelOptions]=\"{ standalone: true }\"\n />\n </div>\n </div>\n\n <c8y-misc-config [config]=\"config\"></c8y-misc-config>\n </div>\n </fieldset>\n <fieldset class=\"row separator-bottom p-t-24 p-b-24\">\n <div class=\"col-xs-12 col-sm-3 col-md-2 text-left-xs text-right-sm\">\n <div class=\"d-inline-flex m-b-16\">\n <div\n class=\"h4 text-medium m-r-4\"\n translate\n >\n Features\n </div>\n <button\n class=\"btn-help btn-help--sm\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{\n 'Define which are the enabled features in the current application.'\n | translate\n }}\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n ></button>\n </div>\n </div>\n <div class=\"col-xs-12 col-sm-9 col-md-8\">\n <c8y-feature-config\n [config]=\"config\"\n (onUpdate)=\"updateFeatures()\"\n ></c8y-feature-config>\n </div>\n </fieldset>\n <fieldset class=\"row separator-bottom p-t-24 p-b-24\">\n <div class=\"col-xs-12 col-sm-3 col-md-2 text-left-xs text-right-sm\">\n <div class=\"d-inline-flex m-b-16\">\n <div\n class=\"h4 text-medium m-r-8\"\n translate\n >\n Top level nodes\n </div>\n <button\n class=\"btn-help btn-help--sm\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{\n 'Select which nodes to display in the top level of the navigator menu. By default, only Groups is shown.'\n | translate\n }}\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n ></button>\n </div>\n </div>\n <div class=\"col-xs-12 col-sm-10 col-md-10\">\n <div class=\"row\">\n <c8y-root-node-config\n [config]=\"config\"\n (onUpdate)=\"updateRootNodes()\"\n [disabled]=\"rootNodeDisabled\"\n ></c8y-root-node-config>\n </div>\n </div>\n <div class=\"col-xs-12 col-sm-9 col-md-8 col-sm-offset-3 col-md-offset-2\">\n <div class=\"row\">\n <c8y-li class=\"m-t-16\">\n <c8y-li-icon icon=\"c8y-group-open\"></c8y-li-icon>\n <div class=\"d-flex a-i-center\">\n <div class=\"p-r-16\">\n <p>{{ 'Show groups as top-level' | translate }}</p>\n <p>\n <small translate>\n Show all root groups as top-level nodes in the navigator menu (only the\n first 500 groups will be shown as top-level nodes).\n </small>\n </p>\n </div>\n <label class=\"c8y-switch c8y-switch--inline m-l-auto\">\n <input\n [attr.aria-label]=\"'Show groups as top-level' | translate\"\n name=\"showGroupsAsTopNode\"\n type=\"checkbox\"\n [(ngModel)]=\"config.showGroupsAsTopNode\"\n (change)=\"updateRootNodes()\"\n />\n <span></span>\n </label>\n </div>\n </c8y-li>\n <c8y-li>\n <c8y-li-icon icon=\"c8y-enterprise\"></c8y-li-icon>\n <div class=\"d-flex a-i-center\">\n <div class=\"p-r-16\">\n <p>{{ 'Show assets as top-level' | translate }}</p>\n <p>\n <small translate>\n Show all root assets as top-level nodes in the navigator menu (only the\n first 500 assets will be shown as top-level nodes).\n </small>\n </p>\n </div>\n <label class=\"c8y-switch c8y-switch--inline m-l-auto\">\n <input\n [attr.aria-label]=\"'Show assets as top-level' | translate\"\n name=\"showAssetsAsTopNode\"\n type=\"checkbox\"\n [(ngModel)]=\"config.showAssetsAsTopNode\"\n (change)=\"updateRootNodes()\"\n />\n <span></span>\n </label>\n </div>\n </c8y-li>\n </div>\n </div>\n </fieldset>\n\n @if ('CockpitDashboardModule' | c8yPluginLoaded | async) {\n <fieldset class=\"row separator-bottom p-t-24 p-b-24\">\n <div class=\"col-xs-12 col-sm-3 col-md-2 text-left-xs text-right-sm\">\n <div class=\"d-inline-flex m-b-16\">\n <div\n class=\"h4 text-medium m-r-8\"\n translate\n >\n Home dashboard\n </div>\n <button\n class=\"btn-help btn-help--sm\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{\n 'The homepage of this application. By default, it is a customizable dashboard displaying the most important alarms and shortcuts to frequently used features.'\n | translate\n }}\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n ></button>\n </div>\n </div>\n <div class=\"col-xs-12 col-sm-9 col-md-8\">\n <c8y-home-dashboard-config [config]=\"config\"></c8y-home-dashboard-config>\n </div>\n </fieldset>\n }\n\n @if ('htmlWidgetProviders' | c8yPluginLoaded | async) {\n <fieldset class=\"row p-t-24 p-b-24\">\n <div class=\"col-xs-12 col-sm-3 col-md-2 text-left-xs text-right-sm\">\n <div class=\"d-inline-flex m-b-16\">\n <div\n class=\"h4 text-medium m-r-8\"\n translate\n >\n HTML widget\n </div>\n </div>\n </div>\n <div class=\"col-xs-12 col-sm-9 col-md-8\">\n <c8y-li>\n <c8y-li-icon icon=\"code1\"></c8y-li-icon>\n <div class=\"d-flex a-i-center\">\n <div class=\"p-r-16\">\n <p>{{ 'Disable sanitization' | translate }}</p>\n <p>\n <small translate>\n By default, every unsecure HTML is removed from the HTML widget. You can\n disable this behavior in this application and allow unsecure HTML to be\n used.\n </small>\n </p>\n </div>\n <label class=\"c8y-switch c8y-switch--inline m-l-auto\">\n <input\n [attr.aria-label]=\"'Disable sanitization' | translate\"\n name=\"htmlWidgetDisableSanitization\"\n type=\"checkbox\"\n [(ngModel)]=\"config.htmlWidgetDisableSanitization\"\n />\n <span></span>\n </label>\n </div>\n </c8y-li>\n <c8y-li class=\"\">\n <c8y-li-icon icon=\"settings\"></c8y-li-icon>\n <div class=\"d-flex a-i-center\">\n <div class=\"p-r-16\">\n <p>{{ 'Enforce advanced mode' | translate }}</p>\n <p>\n <small translate>\n If set to true, the HTML widget configuration will always be opened in\n the advanced mode (web component mode).\n </small>\n </p>\n </div>\n <label class=\"c8y-switch c8y-switch--inline m-l-auto\">\n <input\n [attr.aria-label]=\"'Enforce advanced mode' | translate\"\n name=\"htmlWidgetDefaultToAdvancedMode\"\n type=\"checkbox\"\n [(ngModel)]=\"config.htmlWidgetDefaultToAdvancedMode\"\n />\n <span></span>\n </label>\n </div>\n </c8y-li>\n </div>\n </fieldset>\n }\n </div>\n </div>\n <div class=\"card-footer separator\">\n <button\n class=\"btn btn-primary\"\n title=\"{{ 'Save' | translate }}\"\n type=\"submit\"\n [disabled]=\"!configForm.form.valid\"\n (click)=\"save()\"\n [actionName]=\"'cockpitConfigurationSaved'\"\n [actionData]=\"{ config: config }\"\n c8yProductExperience\n >\n {{ 'Save' | translate }}\n </button>\n </div>\n </div>\n </form>\n </div>\n</div>\n", dependencies: [{ kind: "component", type: TitleComponent, selector: "c8y-title", inputs: ["pageTitleUpdate"] }, { kind: "component", type: BreadcrumbComponent, selector: "c8y-breadcrumb" }, { kind: "component", type: BreadcrumbItemComponent, selector: "c8y-breadcrumb-item", inputs: ["icon", "translate", "label", "path", "injector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i5.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i5.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: i5.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i5.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i5.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "component", type: IconSelectorWrapperComponent, selector: "c8y-icon-selector-wrapper", inputs: ["canRemoveIcon", "selectedIcon", "iconSize"], outputs: ["onSelect"] }, { kind: "component", type: MiscConfigComponent, selector: "c8y-misc-config", inputs: ["config"] }, { kind: "directive", type: PopoverDirective, selector: "[popover]", inputs: ["adaptivePosition", "boundariesElement", "popover", "popoverContext", "popoverTitle", "placement", "outsideClick", "triggers", "container", "containerClass", "isOpen", "delay"], outputs: ["onShown", "onHidden"], exportAs: ["bs-popover"] }, { kind: "component", type: FeatureConfigComponent, selector: "c8y-feature-config", inputs: ["config"], outputs: ["onUpdate"] }, { kind: "component", type: RootNodeConfigComponent, selector: "c8y-root-node-config", inputs: ["config", "disabled"], outputs: ["onUpdate"] }, { kind: "component", type: HomeDashboardConfigComponent, selector: "c8y-home-dashboard-config", inputs: ["config"] }, { kind: "component", type: ListItemComponent, selector: "c8y-list-item, c8y-li", inputs: ["active", "highlighted", "emptyActions", "dense", "collapsed", "selectable"], outputs: ["collapsedChange"] }, { kind: "component", type: ListItemIconComponent, selector: "c8y-list-item-icon, c8y-li-icon", inputs: ["icon", "status"] }, { kind: "directive", type: ProductExperienceDirective, selector: "[c8yProductExperience]", inputs: ["actionName", "actionData", "inherit", "suppressDataOverriding"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: PluginLoadedPipe, name: "c8yPluginLoaded" }] }); }
473
510
  }
474
511
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: CockpitConfigurationComponent, decorators: [{
475
512
  type: Component,
@@ -484,7 +521,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
484
521
  PopoverDirective,
485
522
  FeatureConfigComponent,
486
523
  RootNodeConfigComponent,
487
- NgIf,
488
524
  HomeDashboardConfigComponent,
489
525
  ListItemComponent,
490
526
  ListItemIconComponent,
@@ -492,7 +528,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
492
528
  C8yTranslatePipe,
493
529
  AsyncPipe,
494
530
  PluginLoadedPipe
495
- ], template: "<c8y-title>{{ 'Application configuration' | translate }}</c8y-title>\n<c8y-breadcrumb>\n <c8y-breadcrumb-item\n [icon]=\"'c8y-tools'\"\n [label]=\"'Configuration' | translate\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item\n [icon]=\"'c8y-tools'\"\n [label]=\"'Application configuration' | translate\"\n ></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n<div class=\"row\">\n <div class=\"col-lg-12 col-lg-max\">\n <form #configForm=\"ngForm\">\n <div class=\"card card--fullpage\">\n <div class=\"card-header separator\">\n <div class=\"card-title\">\n {{ config.appTitle || ('Cockpit' | translate) }} {{ 'configuration' | translate }}\n </div>\n </div>\n\n <div class=\"inner-scroll\">\n <div class=\"card-block p-t-0 p-b-0\">\n <fieldset class=\"row separator-bottom p-t-24 p-b-24\">\n <div class=\"col-xs-12 col-sm-3 col-md-2 text-left-xs text-right-sm\">\n <div\n class=\"h4 text-medium d-inline-block m-r-4\"\n translate\n >\n Title, icon, and navigator collapse\n </div>\n </div>\n <div class=\"col-xs-12 col-sm-9 col-md-8 p-l-16\">\n <div class=\"d-flex a-i-start gap-16\">\n <div class=\"form-group d-inline-block\">\n <label>{{ 'Icon' | translate }}</label>\n <c8y-icon-selector-wrapper\n [selectedIcon]=\"config?.icon?.class || 'c8y-cockpit'\"\n [iconSize]=\"24\"\n (onSelect)=\"iconSelectionChange($event)\"\n ></c8y-icon-selector-wrapper>\n </div>\n <div class=\"form-group flex-grow\">\n <label\n for=\"confAppTitle\"\n translate\n >\n Change application title\n </label>\n <input\n class=\"form-control\"\n id=\"confAppTitle\"\n placeholder=\"{{ 'e.g. Cockpit' | translate }} \"\n type=\"text\"\n maxlength=\"254\"\n [(ngModel)]=\"config.appTitle\"\n [ngModelOptions]=\"{ standalone: true }\"\n />\n </div>\n </div>\n\n <c8y-misc-config [config]=\"config\"></c8y-misc-config>\n </div>\n </fieldset>\n <fieldset class=\"row separator-bottom p-t-24 p-b-24\">\n <div class=\"col-xs-12 col-sm-3 col-md-2 text-left-xs text-right-sm\">\n <div class=\"d-inline-flex m-b-16\">\n <div\n class=\"h4 text-medium m-r-4\"\n translate\n >\n Features\n </div>\n <button\n class=\"btn-help btn-help--sm\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{\n 'Define which are the enabled features in the current application.'\n | translate\n }}\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n ></button>\n </div>\n </div>\n <div class=\"col-xs-12 col-sm-9 col-md-8\">\n <c8y-feature-config\n [config]=\"config\"\n (onUpdate)=\"updateFeatures()\"\n ></c8y-feature-config>\n </div>\n </fieldset>\n <fieldset class=\"row separator-bottom p-t-24 p-b-24\">\n <div class=\"col-xs-12 col-sm-3 col-md-2 text-left-xs text-right-sm\">\n <div class=\"d-inline-flex m-b-16\">\n <div\n class=\"h4 text-medium m-r-8\"\n translate\n >\n Top level nodes\n </div>\n <button\n class=\"btn-help btn-help--sm\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{\n 'Select which nodes to display in the top level of the navigator menu. By default, only Groups is shown.'\n | translate\n }}\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n ></button>\n </div>\n </div>\n <div class=\"col-xs-12 col-sm-10 col-md-10\">\n <div class=\"row\">\n <c8y-root-node-config\n [config]=\"config\"\n (onUpdate)=\"updateRootNodes()\"\n [disabled]=\"rootNodeDisabled\"\n ></c8y-root-node-config>\n </div>\n </div>\n </fieldset>\n\n <fieldset\n class=\"row separator-bottom p-t-24 p-b-24\"\n *ngIf=\"'CockpitDashboardModule' | c8yPluginLoaded | async\"\n >\n <div class=\"col-xs-12 col-sm-3 col-md-2 text-left-xs text-right-sm\">\n <div class=\"d-inline-flex m-b-16\">\n <div\n class=\"h4 text-medium m-r-8\"\n translate\n >\n Home dashboard\n </div>\n <button\n class=\"btn-help btn-help--sm\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{\n 'The homepage of this application. By default, it is a customizable dashboard displaying the most important alarms and shortcuts to frequently used features.'\n | translate\n }}\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n ></button>\n </div>\n </div>\n <div class=\"col-xs-12 col-sm-9 col-md-8\">\n <c8y-home-dashboard-config [config]=\"config\"></c8y-home-dashboard-config>\n </div>\n </fieldset>\n\n <fieldset\n class=\"row p-t-24 p-b-24\"\n *ngIf=\"'htmlWidgetProviders' | c8yPluginLoaded | async\"\n >\n <div class=\"col-xs-12 col-sm-3 col-md-2 text-left-xs text-right-sm\">\n <div class=\"d-inline-flex m-b-16\">\n <div\n class=\"h4 text-medium m-r-8\"\n translate\n >\n HTML widget\n </div>\n </div>\n </div>\n <div class=\"col-xs-12 col-sm-9 col-md-8\">\n <c8y-li>\n <c8y-li-icon icon=\"code1\"></c8y-li-icon>\n <div class=\"d-flex a-i-center\">\n <div class=\"p-r-16\">\n <p> {{ 'Disable sanitization' | translate }}</p>\n <p>\n <small translate>\n By default, every unsecure HTML is removed from the HTML widget. You can disable\n this behavior in this application and allow unsecure HTML to be used.\n </small>\n </p>\n </div>\n <label class=\"c8y-switch c8y-switch--inline m-l-auto\">\n <input\n [attr.aria-label]=\"'Disable sanitization' | translate\"\n name=\"htmlWidgetDisableSanitization\"\n type=\"checkbox\"\n [(ngModel)]=\"config.htmlWidgetDisableSanitization\"\n />\n <span></span>\n </label>\n </div>\n </c8y-li>\n <c8y-li class=\"\">\n <c8y-li-icon icon=\"settings\"></c8y-li-icon>\n <div class=\"d-flex a-i-center\">\n <div class=\"p-r-16\">\n <p>{{ 'Enforce advanced mode' | translate }}</p>\n <p>\n <small translate>\n If set to true, the HTML widget configuration will always be opened in the advanced mode\n (web component mode).\n </small>\n </p>\n </div>\n <label class=\"c8y-switch c8y-switch--inline m-l-auto\">\n <input\n [attr.aria-label]=\"'Enforce advanced mode' | translate\"\n name=\"htmlWidgetDefaultToAdvancedMode\"\n type=\"checkbox\"\n [(ngModel)]=\"config.htmlWidgetDefaultToAdvancedMode\"\n />\n <span></span>\n </label>\n </div>\n </c8y-li>\n </div>\n </fieldset>\n </div>\n </div>\n <div class=\"card-footer separator\">\n <button\n class=\"btn btn-primary\"\n title=\"{{ 'Save' | translate }}\"\n type=\"submit\"\n [disabled]=\"!configForm.form.valid\"\n (click)=\"save()\"\n [actionName]=\"'cockpitConfigurationSaved'\"\n [actionData]=\"{ config: config }\"\n c8yProductExperience\n >\n {{ 'Save' | translate }}\n </button>\n </div>\n </div>\n </form>\n </div>\n</div>\n" }]
531
+ ], template: "<c8y-title>{{ 'Application configuration' | translate }}</c8y-title>\n<c8y-breadcrumb>\n <c8y-breadcrumb-item\n [icon]=\"'c8y-tools'\"\n [label]=\"'Configuration' | translate\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item\n [icon]=\"'c8y-tools'\"\n [label]=\"'Application configuration' | translate\"\n ></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n<div class=\"row\">\n <div class=\"col-lg-12 col-lg-max\">\n <form #configForm=\"ngForm\">\n <div class=\"card card--fullpage\">\n <div class=\"card-header separator\">\n <div class=\"card-title\">\n {{ config.appTitle || ('Cockpit' | translate) }} {{ 'configuration' | translate }}\n </div>\n </div>\n\n <div class=\"inner-scroll\">\n <div class=\"card-block p-t-0 p-b-0\">\n <fieldset class=\"row separator-bottom p-t-24 p-b-24\">\n <div class=\"col-xs-12 col-sm-3 col-md-2 text-left-xs text-right-sm\">\n <div\n class=\"h4 text-medium d-inline-block m-r-4\"\n translate\n >\n Title, icon, and navigator collapse\n </div>\n </div>\n <div class=\"col-xs-12 col-sm-9 col-md-8 p-l-16\">\n <div class=\"d-flex a-i-start gap-16\">\n <div class=\"form-group d-inline-block\">\n <label>{{ 'Icon' | translate }}</label>\n <c8y-icon-selector-wrapper\n [selectedIcon]=\"config?.icon?.class || 'c8y-cockpit'\"\n [iconSize]=\"24\"\n (onSelect)=\"iconSelectionChange($event)\"\n ></c8y-icon-selector-wrapper>\n </div>\n <div class=\"form-group flex-grow\">\n <label\n for=\"confAppTitle\"\n translate\n >\n Change application title\n </label>\n <input\n class=\"form-control\"\n id=\"confAppTitle\"\n placeholder=\"{{ 'e.g. Cockpit' | translate }} \"\n type=\"text\"\n maxlength=\"254\"\n [(ngModel)]=\"config.appTitle\"\n [ngModelOptions]=\"{ standalone: true }\"\n />\n </div>\n </div>\n\n <c8y-misc-config [config]=\"config\"></c8y-misc-config>\n </div>\n </fieldset>\n <fieldset class=\"row separator-bottom p-t-24 p-b-24\">\n <div class=\"col-xs-12 col-sm-3 col-md-2 text-left-xs text-right-sm\">\n <div class=\"d-inline-flex m-b-16\">\n <div\n class=\"h4 text-medium m-r-4\"\n translate\n >\n Features\n </div>\n <button\n class=\"btn-help btn-help--sm\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{\n 'Define which are the enabled features in the current application.'\n | translate\n }}\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n ></button>\n </div>\n </div>\n <div class=\"col-xs-12 col-sm-9 col-md-8\">\n <c8y-feature-config\n [config]=\"config\"\n (onUpdate)=\"updateFeatures()\"\n ></c8y-feature-config>\n </div>\n </fieldset>\n <fieldset class=\"row separator-bottom p-t-24 p-b-24\">\n <div class=\"col-xs-12 col-sm-3 col-md-2 text-left-xs text-right-sm\">\n <div class=\"d-inline-flex m-b-16\">\n <div\n class=\"h4 text-medium m-r-8\"\n translate\n >\n Top level nodes\n </div>\n <button\n class=\"btn-help btn-help--sm\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{\n 'Select which nodes to display in the top level of the navigator menu. By default, only Groups is shown.'\n | translate\n }}\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n ></button>\n </div>\n </div>\n <div class=\"col-xs-12 col-sm-10 col-md-10\">\n <div class=\"row\">\n <c8y-root-node-config\n [config]=\"config\"\n (onUpdate)=\"updateRootNodes()\"\n [disabled]=\"rootNodeDisabled\"\n ></c8y-root-node-config>\n </div>\n </div>\n <div class=\"col-xs-12 col-sm-9 col-md-8 col-sm-offset-3 col-md-offset-2\">\n <div class=\"row\">\n <c8y-li class=\"m-t-16\">\n <c8y-li-icon icon=\"c8y-group-open\"></c8y-li-icon>\n <div class=\"d-flex a-i-center\">\n <div class=\"p-r-16\">\n <p>{{ 'Show groups as top-level' | translate }}</p>\n <p>\n <small translate>\n Show all root groups as top-level nodes in the navigator menu (only the\n first 500 groups will be shown as top-level nodes).\n </small>\n </p>\n </div>\n <label class=\"c8y-switch c8y-switch--inline m-l-auto\">\n <input\n [attr.aria-label]=\"'Show groups as top-level' | translate\"\n name=\"showGroupsAsTopNode\"\n type=\"checkbox\"\n [(ngModel)]=\"config.showGroupsAsTopNode\"\n (change)=\"updateRootNodes()\"\n />\n <span></span>\n </label>\n </div>\n </c8y-li>\n <c8y-li>\n <c8y-li-icon icon=\"c8y-enterprise\"></c8y-li-icon>\n <div class=\"d-flex a-i-center\">\n <div class=\"p-r-16\">\n <p>{{ 'Show assets as top-level' | translate }}</p>\n <p>\n <small translate>\n Show all root assets as top-level nodes in the navigator menu (only the\n first 500 assets will be shown as top-level nodes).\n </small>\n </p>\n </div>\n <label class=\"c8y-switch c8y-switch--inline m-l-auto\">\n <input\n [attr.aria-label]=\"'Show assets as top-level' | translate\"\n name=\"showAssetsAsTopNode\"\n type=\"checkbox\"\n [(ngModel)]=\"config.showAssetsAsTopNode\"\n (change)=\"updateRootNodes()\"\n />\n <span></span>\n </label>\n </div>\n </c8y-li>\n </div>\n </div>\n </fieldset>\n\n @if ('CockpitDashboardModule' | c8yPluginLoaded | async) {\n <fieldset class=\"row separator-bottom p-t-24 p-b-24\">\n <div class=\"col-xs-12 col-sm-3 col-md-2 text-left-xs text-right-sm\">\n <div class=\"d-inline-flex m-b-16\">\n <div\n class=\"h4 text-medium m-r-8\"\n translate\n >\n Home dashboard\n </div>\n <button\n class=\"btn-help btn-help--sm\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{\n 'The homepage of this application. By default, it is a customizable dashboard displaying the most important alarms and shortcuts to frequently used features.'\n | translate\n }}\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n ></button>\n </div>\n </div>\n <div class=\"col-xs-12 col-sm-9 col-md-8\">\n <c8y-home-dashboard-config [config]=\"config\"></c8y-home-dashboard-config>\n </div>\n </fieldset>\n }\n\n @if ('htmlWidgetProviders' | c8yPluginLoaded | async) {\n <fieldset class=\"row p-t-24 p-b-24\">\n <div class=\"col-xs-12 col-sm-3 col-md-2 text-left-xs text-right-sm\">\n <div class=\"d-inline-flex m-b-16\">\n <div\n class=\"h4 text-medium m-r-8\"\n translate\n >\n HTML widget\n </div>\n </div>\n </div>\n <div class=\"col-xs-12 col-sm-9 col-md-8\">\n <c8y-li>\n <c8y-li-icon icon=\"code1\"></c8y-li-icon>\n <div class=\"d-flex a-i-center\">\n <div class=\"p-r-16\">\n <p>{{ 'Disable sanitization' | translate }}</p>\n <p>\n <small translate>\n By default, every unsecure HTML is removed from the HTML widget. You can\n disable this behavior in this application and allow unsecure HTML to be\n used.\n </small>\n </p>\n </div>\n <label class=\"c8y-switch c8y-switch--inline m-l-auto\">\n <input\n [attr.aria-label]=\"'Disable sanitization' | translate\"\n name=\"htmlWidgetDisableSanitization\"\n type=\"checkbox\"\n [(ngModel)]=\"config.htmlWidgetDisableSanitization\"\n />\n <span></span>\n </label>\n </div>\n </c8y-li>\n <c8y-li class=\"\">\n <c8y-li-icon icon=\"settings\"></c8y-li-icon>\n <div class=\"d-flex a-i-center\">\n <div class=\"p-r-16\">\n <p>{{ 'Enforce advanced mode' | translate }}</p>\n <p>\n <small translate>\n If set to true, the HTML widget configuration will always be opened in\n the advanced mode (web component mode).\n </small>\n </p>\n </div>\n <label class=\"c8y-switch c8y-switch--inline m-l-auto\">\n <input\n [attr.aria-label]=\"'Enforce advanced mode' | translate\"\n name=\"htmlWidgetDefaultToAdvancedMode\"\n type=\"checkbox\"\n [(ngModel)]=\"config.htmlWidgetDefaultToAdvancedMode\"\n />\n <span></span>\n </label>\n </div>\n </c8y-li>\n </div>\n </fieldset>\n }\n </div>\n </div>\n <div class=\"card-footer separator\">\n <button\n class=\"btn btn-primary\"\n title=\"{{ 'Save' | translate }}\"\n type=\"submit\"\n [disabled]=\"!configForm.form.valid\"\n (click)=\"save()\"\n [actionName]=\"'cockpitConfigurationSaved'\"\n [actionData]=\"{ config: config }\"\n c8yProductExperience\n >\n {{ 'Save' | translate }}\n </button>\n </div>\n </div>\n </form>\n </div>\n</div>\n" }]
496
532
  }], ctorParameters: () => [{ type: CockpitConfigService }, { type: i1.AlertService }, { type: i1.AppStateService }] });
497
533
 
498
534
  class CockpitSetupStep {