{"version":3,"file":"c8y-ngx-components-widgets-implementations-kpi.mjs","sources":["../../widgets/implementations/kpi/kpi-widget.model.ts","../../widgets/implementations/kpi/kpi-widget-view/kpi-widget-view.component.ts","../../widgets/implementations/kpi/kpi-widget-view/kpi-widget-view.component.html","../../widgets/implementations/kpi/kpi-widget-config/kpi-widget-config.component.ts","../../widgets/implementations/kpi/kpi-widget-config/kpi-widget-config.component.html","../../widgets/implementations/kpi/c8y-ngx-components-widgets-implementations-kpi.ts"],"sourcesContent":["import { KPIDetails } from '@c8y/ngx-components/datapoint-selector';\nimport { SupportedIconsSuggestions } from '@c8y/ngx-components/icon-selector/icons';\nimport type { GlobalContextState } from '@c8y/ngx-components/global-context';\n\nexport interface KpiWidgetConfig extends Partial<GlobalContextState> {\n  datapoints: KPIDetails[];\n  icon?: SupportedIconsSuggestions | null;\n  showTimestamp?: boolean | null;\n  showTrend?: boolean | null;\n  showIcon?: boolean | null;\n  numberOfDecimalPlaces?: number | null;\n  fontSize?: number | null;\n}\n\nexport interface MeasurementValue {\n  unit?: string;\n  value: number;\n  date: string;\n}\n\nexport enum ColorClass {\n  danger = 'text-danger',\n  warning = 'text-warning',\n  unknown = ''\n}\n\nexport type KpiState = {\n  latestMeasurement: MeasurementValue;\n  previousValue: MeasurementValue | undefined;\n  trend: string;\n  unit: string;\n  colorClass: ColorClass;\n};\n","import {\n  ChangeDetectionStrategy,\n  Component,\n  DestroyRef,\n  inject,\n  Input,\n  OnChanges,\n  OnInit,\n  signal,\n  SimpleChanges\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { IMeasurement } from '@c8y/client';\nimport {\n  C8yTranslateDirective,\n  C8yTranslatePipe,\n  DashboardChildComponent,\n  DatePipe,\n  EmptyStateComponent,\n  IconDirective,\n  LoadingComponent,\n  MeasurementRealtimeService\n} from '@c8y/ngx-components';\nimport { ContextDashboardComponent } from '@c8y/ngx-components/context-dashboard';\nimport { KPIDetails } from '@c8y/ngx-components/datapoint-selector';\nimport {\n  DisplayMode,\n  GLOBAL_CONTEXT_DISPLAY_MODE,\n  GlobalContextConnectorComponent,\n  GlobalContextState,\n  LocalControlsComponent,\n  PRESET_NAME,\n  PresetName,\n  REFRESH_OPTION,\n  WidgetConfigMigrationService\n} from '@c8y/ngx-components/global-context';\nimport { isEqual, merge as mergeObj } from 'lodash-es';\nimport { BehaviorSubject, combineLatest, merge as merge$, NEVER, Observable, Subject } from 'rxjs';\nimport {\n  distinctUntilChanged,\n  filter,\n  map,\n  pairwise,\n  share,\n  startWith,\n  switchMap,\n  tap\n} from 'rxjs/operators';\nimport { ColorClass, KpiState, KpiWidgetConfig, MeasurementValue } from '../kpi-widget.model';\nimport { AsyncPipe, DecimalPipe, NgClass, NgStyle } from '@angular/common';\n\n@Component({\n  selector: 'c8y-kpi-widget-view',\n  templateUrl: './kpi-widget-view.component.html',\n  standalone: true,\n  imports: [\n    AsyncPipe,\n    DatePipe,\n    DecimalPipe,\n    NgClass,\n    NgStyle,\n    C8yTranslatePipe,\n    C8yTranslateDirective,\n    IconDirective,\n    LoadingComponent,\n    EmptyStateComponent,\n    GlobalContextConnectorComponent,\n    LocalControlsComponent\n  ],\n  providers: [MeasurementRealtimeService],\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  host: { class: 'd-col fit-h' }\n})\nexport class KpiWidgetViewComponent implements OnChanges, OnInit {\n  @Input() config: KpiWidgetConfig = { datapoints: [] };\n\n  displayMode = signal<DisplayMode>(GLOBAL_CONTEXT_DISPLAY_MODE.DASHBOARD);\n  contextConfig = signal<GlobalContextState>({});\n  isLinkedToGlobal = signal<boolean | undefined>(undefined);\n  widgetControls = signal<PresetName>(PRESET_NAME.KPI);\n  isHistoryMode = signal(false);\n\n  state$: Observable<KpiState | null> = NEVER;\n  noDataInitiallyInDB = signal(false);\n\n  readonly GLOBAL_CONTEXT_DISPLAY_MODE = GLOBAL_CONTEXT_DISPLAY_MODE;\n\n  private dashboardChild = inject(DashboardChildComponent, { optional: true });\n  private dashboard = inject(ContextDashboardComponent, { optional: true });\n  private measurementRealtime = inject(MeasurementRealtimeService);\n  private widgetConfigMigrationService = inject(WidgetConfigMigrationService);\n  private destroyRef = inject(DestroyRef);\n\n  private context$ = new BehaviorSubject<GlobalContextState | null>(null);\n  private refresh$ = new Subject<void>();\n  private lastDatapoint: KPIDetails | null = null;\n\n  ngOnInit(): void {\n    this.config = mergeObj(\n      this.config,\n      this.widgetConfigMigrationService.migrateWidgetConfig(this.config)\n    );\n\n    this.syncDisplayState();\n    this.buildStatePipeline();\n\n    if (!this.isDashboardMode()) {\n      this.emitContext(this.config);\n    }\n  }\n\n  ngOnChanges(changes: SimpleChanges): void {\n    const cfg = changes.config?.currentValue as KpiWidgetConfig;\n    if (!cfg) {\n      return;\n    }\n    this.config = cfg;\n    this.syncDisplayState();\n\n    if (this.isOnRealDashboard()) {\n      return;\n    }\n    if (this.isDashboardPreviewWaitingForContext()) {\n      return;\n    }\n    this.emitContext(this.config, this.hasDatapointChanged());\n  }\n\n  onContextChange(event: { context: GlobalContextState; diff: GlobalContextState }): void {\n    this.contextConfig.set(event.context);\n    this.emitContext(event.context);\n  }\n\n  onRefresh(): void {\n    this.refresh$.next();\n  }\n\n  getDashboardChild(): DashboardChildComponent {\n    return this.dashboardChild;\n  }\n\n  setupObservable(datapoint: KPIDetails, context: GlobalContextState): Observable<KpiState> {\n    const isHistory = context.refreshOption === REFRESH_OPTION.HISTORY;\n    const isPaused = !isHistory && context.isAutoRefreshEnabled === false;\n    this.isHistoryMode.set(isHistory);\n    this.noDataInitiallyInDB.set(false);\n\n    let source$: Observable<MeasurementValue>;\n    if (isPaused) {\n      source$ = this.getHistoryMeasurement$(datapoint, {});\n    } else if (isHistory) {\n      source$ = this.getHistoryMeasurement$(datapoint, context);\n    } else {\n      source$ = this.getLiveMeasurement$(datapoint);\n    }\n\n    const shared$ = source$.pipe(share());\n    const lastTwo$ = shared$.pipe(pairwise());\n\n    return combineLatest([\n      shared$,\n      lastTwo$.pipe(\n        map(([prev]) => prev),\n        startWith(undefined as MeasurementValue | undefined)\n      ),\n      this.getTrend$(lastTwo$),\n      shared$.pipe(\n        map(m => datapoint.unit || m.unit || ''),\n        startWith(''),\n        distinctUntilChanged()\n      ),\n      this.getColorClass$(shared$, datapoint)\n    ]).pipe(\n      map(([latestMeasurement, previousValue, trend, unit, colorClass]) => ({\n        latestMeasurement,\n        previousValue,\n        trend,\n        unit,\n        colorClass\n      }))\n    );\n  }\n\n  private buildStatePipeline(): void {\n    const readState = () => ({ ctx: this.context$.value, dp: this.findActiveDatapoint() });\n\n    this.state$ = merge$(\n      this.context$.pipe(map(readState), distinctUntilChanged(isEqual)),\n      this.refresh$.pipe(map(readState))\n    ).pipe(\n      filter((s): s is { ctx: GlobalContextState; dp: KPIDetails } => !!s.ctx && !!s.dp),\n      switchMap(({ ctx, dp }) => {\n        this.assignContextFromContextDashboard(dp);\n        return this.setupObservable(dp, ctx).pipe(startWith(null as KpiState | null));\n      }),\n      takeUntilDestroyed(this.destroyRef)\n    );\n  }\n\n  private syncDisplayState(): void {\n    const newMode = this.resolveDisplayMode();\n    if (this.displayMode() !== newMode) {\n      this.displayMode.set(newMode);\n    }\n\n    const newCtx = this.extractContext(this.config);\n    if (!isEqual(this.contextConfig(), newCtx)) {\n      this.contextConfig.set(newCtx);\n    }\n  }\n\n  private emitContext(source: Partial<GlobalContextState>, force = false): void {\n    const ctx = this.extractContext(source);\n    if (force || !isEqual(this.context$.value, ctx)) {\n      this.context$.next(ctx);\n    }\n  }\n\n  private isDashboardMode(): boolean {\n    return this.resolveDisplayMode() === GLOBAL_CONTEXT_DISPLAY_MODE.DASHBOARD;\n  }\n\n  private isOnRealDashboard(): boolean {\n    return this.isDashboardMode() && !!this.dashboardChild;\n  }\n\n  private isDashboardPreviewWaitingForContext(): boolean {\n    return this.isDashboardMode() && !this.config.isGlobalContextReady;\n  }\n\n  private resolveDisplayMode(): DisplayMode {\n    return (this.config?.displayMode || GLOBAL_CONTEXT_DISPLAY_MODE.CONFIG) as DisplayMode;\n  }\n\n  private extractContext(source: Partial<GlobalContextState>): GlobalContextState {\n    return {\n      dateTimeContext: source.dateTimeContext,\n      isAutoRefreshEnabled: source.isAutoRefreshEnabled,\n      refreshInterval: source.refreshInterval,\n      refreshOption: source.refreshOption\n    };\n  }\n\n  private findActiveDatapoint(): KPIDetails | undefined {\n    return this.config?.datapoints?.find(dp => dp?.__active);\n  }\n\n  private hasDatapointChanged(): boolean {\n    const dp = this.findActiveDatapoint();\n    if (!dp) {\n      return false;\n    }\n    const prev = this.lastDatapoint;\n    this.lastDatapoint = dp;\n    return (\n      !prev ||\n      dp.fragment !== prev.fragment ||\n      dp.series !== prev.series ||\n      dp.__target?.id !== prev.__target?.id ||\n      dp.unit !== prev.unit ||\n      dp.redRangeMin !== prev.redRangeMin ||\n      dp.redRangeMax !== prev.redRangeMax ||\n      dp.yellowRangeMin !== prev.yellowRangeMin ||\n      dp.yellowRangeMax !== prev.yellowRangeMax\n    );\n  }\n\n  private getLiveMeasurement$(datapoint: KPIDetails): Observable<MeasurementValue> {\n    return this.measurementRealtime\n      .latestValueOfSpecificMeasurement$(\n        datapoint.fragment,\n        datapoint.series,\n        datapoint.__target,\n        this.config.showTrend ? 2 : 1,\n        true\n      )\n      .pipe(\n        tap(m => {\n          if (!m) this.noDataInitiallyInDB.set(true);\n        }),\n        filter(m => !!m),\n        map(m => this.toMeasurementValue(m, datapoint))\n      );\n  }\n\n  private getHistoryMeasurement$(\n    datapoint: KPIDetails,\n    context: GlobalContextState\n  ): Observable<MeasurementValue> {\n    return this.measurementRealtime\n      .lastMeasurement$(\n        datapoint.fragment,\n        datapoint.series,\n        datapoint.__target,\n        1,\n        true,\n        context.dateTimeContext?.dateFrom,\n        context.dateTimeContext?.dateTo\n      )\n      .pipe(\n        tap(m => {\n          if (!m) this.noDataInitiallyInDB.set(true);\n        }),\n        filter(m => !!m),\n        map(m => this.toMeasurementValue(m, datapoint))\n      );\n  }\n\n  private toMeasurementValue(m: IMeasurement, dp: KPIDetails): MeasurementValue {\n    return {\n      unit: m[dp.fragment][dp.series].unit,\n      value: m[dp.fragment][dp.series].value,\n      date: m.time as string\n    };\n  }\n\n  private getColorClass$(\n    measurement$: Observable<MeasurementValue>,\n    datapoint: KPIDetails\n  ): Observable<ColorClass> {\n    return measurement$.pipe(\n      map(m => {\n        if (this.inRange(datapoint, m.value, 'redRangeMin', 'redRangeMax')) {\n          return ColorClass.danger;\n        }\n        if (this.inRange(datapoint, m.value, 'yellowRangeMin', 'yellowRangeMax')) {\n          return ColorClass.warning;\n        }\n        return ColorClass.unknown;\n      }),\n      startWith(ColorClass.unknown),\n      distinctUntilChanged()\n    );\n  }\n\n  private getTrend$(lastTwo$: Observable<MeasurementValue[]>): Observable<string> {\n    return lastTwo$.pipe(\n      map(([prev, curr]) => {\n        if (prev.value < curr.value) return '45deg';\n        if (prev.value > curr.value) return '135deg';\n        return '90deg';\n      }),\n      startWith('90deg'),\n      distinctUntilChanged()\n    );\n  }\n\n  private inRange(dp: KPIDetails, value: number, minKey: string, maxKey: string): boolean {\n    return (\n      typeof dp[minKey] === 'number' &&\n      typeof dp[maxKey] === 'number' &&\n      value >= dp[minKey] &&\n      value < dp[maxKey]\n    );\n  }\n\n  private assignContextFromContextDashboard(datapoint: KPIDetails): void {\n    if (!this.dashboard?.isDeviceTypeDashboard) {\n      return;\n    }\n    const context = this.dashboard?.context;\n    if (context?.id) {\n      datapoint.__target = { name: context.name, id: context.id };\n    }\n  }\n}\n","@if (displayMode() === GLOBAL_CONTEXT_DISPLAY_MODE.DASHBOARD && getDashboardChild()) {\n  <c8y-global-context-connector\n    [controls]=\"widgetControls()\"\n    [config]=\"contextConfig()\"\n    [dashboardChild]=\"getDashboardChild()\"\n    [linked]=\"isLinkedToGlobal()\"\n    [emitRefresh]=\"false\"\n    (configChange)=\"onContextChange($event)\"\n    (refresh)=\"onRefresh()\"\n  ></c8y-global-context-connector>\n} @else if (displayMode() !== GLOBAL_CONTEXT_DISPLAY_MODE.DASHBOARD) {\n  <c8y-local-controls\n    [controls]=\"widgetControls()\"\n    [displayMode]=\"displayMode()\"\n    [config]=\"contextConfig()\"\n    [emitRefresh]=\"false\"\n    (configChange)=\"onContextChange($event)\"\n    (refresh)=\"onRefresh()\"\n  ></c8y-local-controls>\n}\n\n@if (state$ | async; as lastState) {\n  <div class=\"kpi-widget__container d-flex d-col flex-grow fit-w a-i-center j-c-center\">\n    <div class=\"d-flex a-i-center j-c-center fit-w\">\n      @if (config.icon && config.showIcon) {\n        <div\n          class=\"m-r-16 flex-no-shrink text-muted\"\n          [ngClass]=\"lastState.colorClass\"\n        >\n          <i\n            class=\"icon-32\"\n            [c8yIcon]=\"config.icon\"\n          ></i>\n        </div>\n      }\n      <div class=\"text-truncate\">\n        <span\n          class=\"text-truncate text-medium\"\n          [ngStyle]=\"{ 'font-size': (config.fontSize || '36') + 'px' }\"\n          title=\"{{\n            lastState.colorClass === 'text-danger'\n              ? ('Within red range:' | translate)\n              : lastState.colorClass === 'text-warning'\n                ? ('Within yellow range:' | translate)\n                : ''\n          }} {{\n            lastState.latestMeasurement.value\n              | number\n                : '1.' +\n                    (config.numberOfDecimalPlaces || '0') +\n                    '-' +\n                    (config.numberOfDecimalPlaces || '0')\n          }} {{ lastState.unit || '' }}\"\n          [ngClass]=\"lastState.colorClass\"\n        >\n          {{\n            lastState.latestMeasurement.value\n              | number\n                : '1.' +\n                    (config.numberOfDecimalPlaces || '0') +\n                    '-' +\n                    (config.numberOfDecimalPlaces || '0')\n          }}\n          <small class=\"text-regular\">{{ lastState.unit || '' }}</small>\n        </span>\n      </div>\n      @if (config?.showTrend && lastState.previousValue; as previousValue) {\n        <div class=\"dot dot-info dot-30 m-l-16 flex-no-shrink\">\n          <i\n            class=\"icon-20\"\n            c8yIcon=\"arrow-dotted-up\"\n            [ngStyle]=\"{ transform: 'rotate(' + lastState.trend + ')' }\"\n            [title]=\"\n              ('Previous value' | translate) +\n              ': ' +\n              (previousValue.value\n                | number\n                  : '1.' +\n                      (config.numberOfDecimalPlaces || '0') +\n                      '-' +\n                      (config.numberOfDecimalPlaces || '0')) +\n              ' (' +\n              (previousValue.date | c8yDate: 'medium') +\n              ')'\n            \"\n          ></i>\n        </div>\n      }\n    </div>\n    <div class=\"d-flex d-col a-i-center\">\n      @if (config?.showTimestamp) {\n        <p class=\"icon-flex text-center text-muted small m-b-0\">\n          <i c8yIcon=\"calendar\"></i>\n          {{ lastState.latestMeasurement.date | c8yDate: 'medium' }}\n        </p>\n      }\n      @if (isHistoryMode()) {\n        <p class=\"text-center text-muted small m-b-0\">\n          <span translate>Last measurement in selected time range</span>\n        </p>\n      }\n    </div>\n  </div>\n} @else {\n  <div class=\"d-flex flex-grow fit-w j-c-center a-i-center\">\n    @let noDataSubtitleLive = 'Waiting for measurements to be created.' | translate;\n    @let noDataSubtitleHistory = 'No data available for the selected time period.' | translate;\n    @if (noDataInitiallyInDB()) {\n      <c8y-ui-empty-state\n        [icon]=\"'line-chart'\"\n        [title]=\"'No measurement to display.' | translate\"\n        [subtitle]=\"isHistoryMode() ? noDataSubtitleHistory : noDataSubtitleLive\"\n        [horizontal]=\"true\"\n      ></c8y-ui-empty-state>\n    } @else {\n      <c8y-loading></c8y-loading>\n    }\n  </div>\n}\n","import {\n  ChangeDetectionStrategy,\n  Component,\n  DestroyRef,\n  inject,\n  Input,\n  OnChanges,\n  OnInit,\n  SimpleChanges,\n  TemplateRef,\n  ViewChild\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport {\n  AbstractControl,\n  ControlContainer,\n  FormBuilder,\n  NgForm,\n  ReactiveFormsModule,\n  ValidationErrors,\n  ValidatorFn,\n  Validators\n} from '@angular/forms';\nimport {\n  C8yTranslateDirective,\n  C8yTranslatePipe,\n  C8yValidators,\n  EmptyStateComponent,\n  FormGroupComponent,\n  GuideDocsComponent,\n  GuideHrefDirective,\n  MessagesComponent,\n  OnBeforeSave\n} from '@c8y/ngx-components';\nimport { WidgetConfigComponent, WidgetConfigService } from '@c8y/ngx-components/context-dashboard';\nimport {\n  DatapointAttributesFormConfig,\n  DatapointSelectorModalOptions,\n  DatapointSelectorModule,\n  KPIDetails\n} from '@c8y/ngx-components/datapoint-selector';\nimport { IconSelectorModule } from '@c8y/ngx-components/icon-selector';\nimport { PopoverModule } from 'ngx-bootstrap/popover';\nimport { Observable } from 'rxjs';\nimport { debounceTime, filter } from 'rxjs/operators';\nimport { KpiWidgetViewComponent } from '../kpi-widget-view/kpi-widget-view.component';\nimport { KpiWidgetConfig } from '../kpi-widget.model';\n\nexport function exactlyASingleDatapointActive(): ValidatorFn {\n  return (control: AbstractControl): ValidationErrors | null => {\n    const datapoints: KPIDetails[] = control.value;\n    if (!datapoints?.length) {\n      return null;\n    }\n    return datapoints.filter(dp => dp.__active).length === 1\n      ? null\n      : { exactlyOneDatapointNeedsToBeActive: true };\n  };\n}\n\n@Component({\n  selector: 'c8y-kpi-widget-config',\n  templateUrl: './kpi-widget-config.component.html',\n  standalone: true,\n  imports: [\n    ReactiveFormsModule,\n    C8yTranslatePipe,\n    C8yTranslateDirective,\n    FormGroupComponent,\n    MessagesComponent,\n    EmptyStateComponent,\n    GuideDocsComponent,\n    GuideHrefDirective,\n    DatapointSelectorModule,\n    IconSelectorModule,\n    PopoverModule,\n    KpiWidgetViewComponent\n  ],\n  viewProviders: [{ provide: ControlContainer, useExisting: NgForm }],\n  changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class KpiWidgetConfigComponent implements OnChanges, OnInit, OnBeforeSave {\n  @ViewChild('kpiPreview')\n  set previewMapSet(template: TemplateRef<unknown>) {\n    this.widgetConfigService.setPreview(template || null);\n  }\n\n  @Input() config: KpiWidgetConfig;\n\n  previewActiveDatapoint: KPIDetails;\n  datapointSelectionConfig: Partial<DatapointSelectorModalOptions> = {};\n  defaultFormOptions: Partial<DatapointAttributesFormConfig> = {\n    showRedRange: true,\n    showYellowRange: true\n  };\n  formGroup: ReturnType<KpiWidgetConfigComponent['createForm']>;\n  previewConfig: KpiWidgetConfig;\n\n  private destroyRef = inject(DestroyRef);\n  private limits = {\n    fontSizeMax: 72,\n    fontSizeMin: 18,\n    numberOfDecimalPlacesMax: 10,\n    numberOfDecimalPlacesMin: 0\n  } as const;\n\n  constructor(\n    private formBuilder: FormBuilder,\n    private form: NgForm,\n    private widgetConfig: WidgetConfigComponent,\n    private widgetConfigService: WidgetConfigService\n  ) {}\n\n  onBeforeSave(config?: KpiWidgetConfig): boolean | Promise<boolean> | Observable<boolean> {\n    if (this.formGroup.valid) {\n      Object.assign(config, this.formGroup.value);\n      return true;\n    }\n    return false;\n  }\n\n  ngOnChanges(changes: SimpleChanges): void {\n    if (this.formGroup && changes.config) {\n      this.formGroup.controls.datapoints.patchValue(this.config.datapoints || []);\n    }\n  }\n\n  ngOnInit(): void {\n    if (this.widgetConfig.context?.id) {\n      this.datapointSelectionConfig.contextAsset = this.widgetConfig.context;\n    }\n\n    this.previewConfig = { ...this.config };\n    this.initForm();\n\n    if (this.config?.datapoints) {\n      this.formGroup.patchValue({ datapoints: this.config.datapoints });\n      this.previewActiveDatapoint = this.config.datapoints.find(dp => dp.__active);\n    }\n\n    this.widgetConfigService.currentConfig$\n      .pipe(\n        filter(c => !!c),\n        takeUntilDestroyed(this.destroyRef)\n      )\n      .subscribe(c => {\n        this.previewConfig = { ...this.previewConfig, ...c, ...this.formGroup.value };\n      });\n  }\n\n  private initForm(): void {\n    this.formGroup = this.createForm();\n    this.form.form.addControl('config', this.formGroup);\n    this.formGroup.patchValue(this.config);\n\n    this.formGroup.valueChanges\n      .pipe(debounceTime(100), takeUntilDestroyed(this.destroyRef))\n      .subscribe(formValue => {\n        if (formValue.datapoints) {\n          this.previewActiveDatapoint = formValue.datapoints.find(dp => dp.__active);\n        }\n\n        if (this.formGroup.valid) {\n          this.previewConfig = { ...this.config, ...this.applyLimitsToPreview(formValue) };\n        }\n\n        Object.assign(this.config, formValue);\n      });\n  }\n\n  private applyLimitsToPreview(formValue: Partial<KpiWidgetConfig>): Partial<KpiWidgetConfig> {\n    const result = { ...formValue };\n\n    if (result.numberOfDecimalPlaces !== undefined) {\n      result.numberOfDecimalPlaces = this.clamp(\n        result.numberOfDecimalPlaces,\n        this.limits.numberOfDecimalPlacesMin,\n        this.limits.numberOfDecimalPlacesMax\n      );\n    }\n\n    if (result.fontSize !== undefined) {\n      result.fontSize = this.clamp(\n        result.fontSize,\n        this.limits.fontSizeMin,\n        this.limits.fontSizeMax\n      );\n    }\n\n    return result;\n  }\n\n  private clamp(value: number, min: number, max: number): number {\n    return Math.max(min, Math.min(max, value));\n  }\n\n  private createForm() {\n    return this.formBuilder.group({\n      numberOfDecimalPlaces: [\n        2,\n        [\n          Validators.required,\n          Validators.min(this.limits.numberOfDecimalPlacesMin),\n          Validators.max(this.limits.numberOfDecimalPlacesMax),\n          C8yValidators.integerValidator()\n        ]\n      ],\n      showTimestamp: [true, []],\n      showTrend: [true, []],\n      showIcon: [true, []],\n      icon: ['water', [Validators.required, Validators.minLength(1)]],\n      fontSize: [\n        36,\n        [\n          Validators.required,\n          Validators.min(this.limits.fontSizeMin),\n          Validators.max(this.limits.fontSizeMax)\n        ]\n      ],\n      datapoints: this.formBuilder.control(new Array<KPIDetails>(), [\n        Validators.required,\n        Validators.minLength(1),\n        exactlyASingleDatapointActive()\n      ])\n    });\n  }\n}\n","<form [formGroup]=\"formGroup\">\n  <fieldset class=\"c8y-fieldset\">\n    <legend>{{ 'Layout' | translate }}</legend>\n    <div class=\"d-flex a-i-center gap-8\">\n      <div class=\"form-group form-group-sm m-b-16\">\n        <label translate>Icon</label>\n        <c8y-icon-selector-wrapper\n          [iconSize]=\"16\"\n          name=\"icon\"\n          formControlName=\"icon\"\n        ></c8y-icon-selector-wrapper>\n      </div>\n      <c8y-form-group class=\"form-group-sm m-b-16 flex-grow\">\n        <label\n          [title]=\"'Font size of measurement value (px)' | translate\"\n          translate\n        >\n          Font size of measurement value (px)\n        </label>\n        <input\n          class=\"form-control\"\n          name=\"fontSize\"\n          type=\"number\"\n          formControlName=\"fontSize\"\n          [placeholder]=\"'e.g. {{ example }}' | translate: { example: 36 }\"\n        />\n        <c8y-messages\n          [show]=\"formGroup.controls?.fontSize?.touched && formGroup?.controls?.fontSize?.errors\"\n        ></c8y-messages>\n      </c8y-form-group>\n    </div>\n  </fieldset>\n\n  <fieldset class=\"c8y-fieldset\">\n    <legend>{{ 'Display' | translate }}</legend>\n    <div class=\"d-flex gap-16 flex-wrap\">\n      <c8y-form-group class=\"m-b-8\">\n        <label\n          class=\"c8y-checkbox\"\n          [title]=\"'Show timestamp' | translate\"\n        >\n          <input\n            name=\"showTimestamp\"\n            type=\"checkbox\"\n            formControlName=\"showTimestamp\"\n          />\n          <span></span>\n          <span translate>Show timestamp</span>\n        </label>\n      </c8y-form-group>\n\n      <c8y-form-group class=\"m-b-8\">\n        <label\n          class=\"c8y-checkbox\"\n          [title]=\"'Show icon' | translate\"\n        >\n          <input\n            name=\"showIcon\"\n            type=\"checkbox\"\n            formControlName=\"showIcon\"\n          />\n          <span></span>\n          <span translate>Show icon</span>\n        </label>\n      </c8y-form-group>\n\n      <c8y-form-group class=\"m-b-8\">\n        <label\n          class=\"c8y-checkbox\"\n          [title]=\"'Show trend icon' | translate\"\n        >\n          <input\n            name=\"showTrend\"\n            type=\"checkbox\"\n            formControlName=\"showTrend\"\n          />\n          <span></span>\n          <span translate>Show trend icon</span>\n          <button\n            class=\"btn-help btn-help--sm\"\n            [attr.aria-label]=\"'Help' | translate\"\n            popover=\"{{\n              'Indicates the trend between the last two measurement values.' | translate\n            }}\"\n            placement=\"right\"\n            triggers=\"focus\"\n            container=\"body\"\n            type=\"button\"\n          ></button>\n        </label>\n      </c8y-form-group>\n    </div>\n  </fieldset>\n\n  <fieldset class=\"c8y-fieldset\">\n    <legend translate>Number of decimal places</legend>\n    <c8y-form-group class=\"form-group-sm m-b-20\">\n      <input\n        class=\"form-control\"\n        name=\"numberOfDecimalPlaces\"\n        type=\"number\"\n        formControlName=\"numberOfDecimalPlaces\"\n        [placeholder]=\"'e.g. {{ example }}' | translate: { example: 1 }\"\n      />\n      <c8y-messages\n        [show]=\"\n          formGroup.controls?.numberOfDecimalPlaces?.touched &&\n          formGroup?.controls?.numberOfDecimalPlaces?.errors\n        \"\n      ></c8y-messages>\n    </c8y-form-group>\n  </fieldset>\n</form>\n\n<ng-template #kpiPreview>\n  @if (formGroup && formGroup.value) {\n    @if (formGroup.value.datapoints?.length > 0 && previewActiveDatapoint) {\n      <div style=\"height: 300px\">\n        <c8y-kpi-widget-view [config]=\"previewConfig\"></c8y-kpi-widget-view>\n      </div>\n    } @else {\n      <div class=\"col-md-6 d-col a-i-start j-c-center\">\n        <c8y-ui-empty-state\n          [icon]=\"'c8y-data-points'\"\n          [title]=\"'No data points selected' | translate\"\n          [subtitle]=\"'Select data point to render content' | translate\"\n          [horizontal]=\"false\"\n          data-cy=\"kpi-widget--empty-state-no-data-point-selected\"\n        >\n          <p c8y-guide-docs>\n            <small\n              translate\n              ngNonBindable\n            >\n              Find out more in the\n              <a c8y-guide-href=\"/docs/cockpit/widgets-collection/#kpi\">user documentation</a>.\n            </small>\n          </p>\n        </c8y-ui-empty-state>\n      </div>\n    }\n  }\n</ng-template>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["mergeObj","merge$"],"mappings":"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"}