UI: Updated shared component
This commit is contained in:
		
							parent
							
								
									43176d37fc
								
							
						
					
					
						commit
						e5d6b2bf1b
					
				@ -21,7 +21,8 @@ import {
 | 
			
		||||
  Component,
 | 
			
		||||
  ElementRef,
 | 
			
		||||
  EventEmitter,
 | 
			
		||||
  Input, NgZone,
 | 
			
		||||
  Input,
 | 
			
		||||
  NgZone,
 | 
			
		||||
  OnChanges,
 | 
			
		||||
  OnDestroy,
 | 
			
		||||
  OnInit,
 | 
			
		||||
@ -59,7 +60,7 @@ import { EntityTypeTranslation } from '@shared/models/entity-type.models';
 | 
			
		||||
import { DialogService } from '@core/services/dialog.service';
 | 
			
		||||
import { AddEntityDialogComponent } from './add-entity-dialog.component';
 | 
			
		||||
import { AddEntityDialogData, EntityAction } from '@home/models/entity/entity-component.models';
 | 
			
		||||
import { calculateIntervalStartEndTime, HistoryWindowType, Timewindow } from '@shared/models/time/time.models';
 | 
			
		||||
import { getTimePageLinkInterval, Timewindow } from '@shared/models/time/time.models';
 | 
			
		||||
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
 | 
			
		||||
import { TbAnchorComponent } from '@shared/components/tb-anchor.component';
 | 
			
		||||
import { isDefined, isEqual, isNotEmptyStr, isUndefined } from '@core/utils';
 | 
			
		||||
@ -259,7 +260,7 @@ export class EntitiesTableComponent extends PageComponent implements IEntitiesTa
 | 
			
		||||
 | 
			
		||||
    if (this.entitiesTableConfig.useTimePageLink) {
 | 
			
		||||
      this.timewindow = this.entitiesTableConfig.defaultTimewindowInterval;
 | 
			
		||||
      const interval = this.getTimePageLinkInterval();
 | 
			
		||||
      const interval = getTimePageLinkInterval(this.timewindow);
 | 
			
		||||
      this.pageLink = new TimePageLink(10, 0, null, sortOrder,
 | 
			
		||||
        interval.startTime, interval.endTime);
 | 
			
		||||
    } else {
 | 
			
		||||
@ -424,7 +425,7 @@ export class EntitiesTableComponent extends PageComponent implements IEntitiesTa
 | 
			
		||||
    }
 | 
			
		||||
    if (this.entitiesTableConfig.useTimePageLink) {
 | 
			
		||||
      const timePageLink = this.pageLink as TimePageLink;
 | 
			
		||||
      const interval = this.getTimePageLinkInterval();
 | 
			
		||||
      const interval = getTimePageLinkInterval(this.timewindow);
 | 
			
		||||
      timePageLink.startTime = interval.startTime;
 | 
			
		||||
      timePageLink.endTime = interval.endTime;
 | 
			
		||||
    }
 | 
			
		||||
@ -434,31 +435,6 @@ export class EntitiesTableComponent extends PageComponent implements IEntitiesTa
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private getTimePageLinkInterval(): {startTime?: number; endTime?: number} {
 | 
			
		||||
    const interval: {startTime?: number; endTime?: number} = {};
 | 
			
		||||
    switch (this.timewindow.history.historyType) {
 | 
			
		||||
      case HistoryWindowType.LAST_INTERVAL:
 | 
			
		||||
        const currentTime = Date.now();
 | 
			
		||||
        interval.startTime = currentTime - this.timewindow.history.timewindowMs;
 | 
			
		||||
        interval.endTime = currentTime;
 | 
			
		||||
        break;
 | 
			
		||||
      case HistoryWindowType.FIXED:
 | 
			
		||||
        interval.startTime = this.timewindow.history.fixedTimewindow.startTimeMs;
 | 
			
		||||
        interval.endTime = this.timewindow.history.fixedTimewindow.endTimeMs;
 | 
			
		||||
        break;
 | 
			
		||||
      case HistoryWindowType.INTERVAL:
 | 
			
		||||
        const startEndTime = calculateIntervalStartEndTime(this.timewindow.history.quickInterval);
 | 
			
		||||
        interval.startTime = startEndTime[0];
 | 
			
		||||
        interval.endTime = startEndTime[1];
 | 
			
		||||
        break;
 | 
			
		||||
      case HistoryWindowType.FOR_ALL_TIME:
 | 
			
		||||
        interval.startTime = null;
 | 
			
		||||
        interval.endTime = null;
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    return interval;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private dataLoaded(col?: number, row?: number) {
 | 
			
		||||
    if (isFinite(col) && isFinite(row)) {
 | 
			
		||||
      this.clearCellCache(col, row);
 | 
			
		||||
 | 
			
		||||
@ -17,16 +17,20 @@
 | 
			
		||||
-->
 | 
			
		||||
<div class="tb-entity-list-select flex flex-row" [formGroup]="entityListSelectFormGroup">
 | 
			
		||||
  <tb-entity-type-select
 | 
			
		||||
    [inlineField]="inlineField"
 | 
			
		||||
    [class.flex-1]="inlineField && !modelValue.entityType"
 | 
			
		||||
    style="min-width: 100px; padding-right: 8px;"
 | 
			
		||||
    *ngIf="displayEntityTypeSelect"
 | 
			
		||||
    [showLabel]="true"
 | 
			
		||||
    [required]="required"
 | 
			
		||||
    [useAliasEntityTypes]="useAliasEntityTypes"
 | 
			
		||||
    [allowedEntityTypes]="allowedEntityTypes"
 | 
			
		||||
    [filterAllowedEntityTypes]="filterAllowedEntityTypes"
 | 
			
		||||
    formControlName="entityType">
 | 
			
		||||
  </tb-entity-type-select>
 | 
			
		||||
  <tb-entity-list
 | 
			
		||||
    class="flex-1"
 | 
			
		||||
    [inlineField]="inlineField"
 | 
			
		||||
    [class.tb-not-empty]="modelValue.ids?.length > 0"
 | 
			
		||||
    *ngIf="modelValue.entityType"
 | 
			
		||||
    [required]="required"
 | 
			
		||||
 | 
			
		||||
@ -14,16 +14,13 @@
 | 
			
		||||
/// limitations under the License.
 | 
			
		||||
///
 | 
			
		||||
 | 
			
		||||
import { AfterViewInit, Component, DestroyRef, forwardRef, Input, OnInit } from '@angular/core';
 | 
			
		||||
import { ControlValueAccessor, UntypedFormBuilder, UntypedFormGroup, NG_VALUE_ACCESSOR } from '@angular/forms';
 | 
			
		||||
import { Store } from '@ngrx/store';
 | 
			
		||||
import { AppState } from '@core/core.state';
 | 
			
		||||
import { TranslateService } from '@ngx-translate/core';
 | 
			
		||||
import { booleanAttribute, Component, DestroyRef, forwardRef, Input, OnInit } from '@angular/core';
 | 
			
		||||
import { ControlValueAccessor, NG_VALUE_ACCESSOR, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
 | 
			
		||||
import { AliasEntityType, EntityType } from '@shared/models/entity-type.models';
 | 
			
		||||
import { EntityService } from '@core/http/entity.service';
 | 
			
		||||
import { EntityId } from '@shared/models/id/entity-id';
 | 
			
		||||
import { coerceBooleanProperty } from '@angular/cdk/coercion';
 | 
			
		||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
 | 
			
		||||
import { isDefinedAndNotNull } from '@core/utils';
 | 
			
		||||
 | 
			
		||||
interface EntityListSelectModel {
 | 
			
		||||
  entityType: EntityType | AliasEntityType;
 | 
			
		||||
@ -41,7 +38,7 @@ interface EntityListSelectModel {
 | 
			
		||||
  }]
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
export class EntityListSelectComponent implements ControlValueAccessor, OnInit, AfterViewInit {
 | 
			
		||||
export class EntityListSelectComponent implements ControlValueAccessor, OnInit {
 | 
			
		||||
 | 
			
		||||
  entityListSelectFormGroup: UntypedFormGroup;
 | 
			
		||||
 | 
			
		||||
@ -53,27 +50,28 @@ export class EntityListSelectComponent implements ControlValueAccessor, OnInit,
 | 
			
		||||
  @Input()
 | 
			
		||||
  useAliasEntityTypes: boolean;
 | 
			
		||||
 | 
			
		||||
  private requiredValue: boolean;
 | 
			
		||||
  get required(): boolean {
 | 
			
		||||
    return this.requiredValue;
 | 
			
		||||
  }
 | 
			
		||||
  @Input()
 | 
			
		||||
  set required(value: boolean) {
 | 
			
		||||
    this.requiredValue = coerceBooleanProperty(value);
 | 
			
		||||
  }
 | 
			
		||||
  @Input({transform: booleanAttribute})
 | 
			
		||||
  required: boolean;
 | 
			
		||||
 | 
			
		||||
  @Input()
 | 
			
		||||
  disabled: boolean;
 | 
			
		||||
 | 
			
		||||
  @Input({transform: booleanAttribute})
 | 
			
		||||
  inlineField: boolean;
 | 
			
		||||
 | 
			
		||||
  @Input({transform: booleanAttribute})
 | 
			
		||||
  filterAllowedEntityTypes = true;
 | 
			
		||||
 | 
			
		||||
  @Input()
 | 
			
		||||
  predefinedEntityType: EntityType | AliasEntityType;
 | 
			
		||||
 | 
			
		||||
  displayEntityTypeSelect: boolean;
 | 
			
		||||
 | 
			
		||||
  private readonly defaultEntityType: EntityType | AliasEntityType = null;
 | 
			
		||||
  private defaultEntityType: EntityType | AliasEntityType = null;
 | 
			
		||||
 | 
			
		||||
  private propagateChange = (v: any) => { };
 | 
			
		||||
  private propagateChange = (_v: any) => { };
 | 
			
		||||
 | 
			
		||||
  constructor(private store: Store<AppState>,
 | 
			
		||||
              private entityService: EntityService,
 | 
			
		||||
              public translate: TranslateService,
 | 
			
		||||
  constructor(private entityService: EntityService,
 | 
			
		||||
              private fb: UntypedFormBuilder,
 | 
			
		||||
              private destroyRef: DestroyRef) {
 | 
			
		||||
 | 
			
		||||
@ -96,7 +94,7 @@ export class EntityListSelectComponent implements ControlValueAccessor, OnInit,
 | 
			
		||||
    this.propagateChange = fn;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  registerOnTouched(fn: any): void {
 | 
			
		||||
  registerOnTouched(_fn: any): void {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnInit() {
 | 
			
		||||
@ -114,9 +112,9 @@ export class EntityListSelectComponent implements ControlValueAccessor, OnInit,
 | 
			
		||||
        this.updateView(this.modelValue.entityType, values);
 | 
			
		||||
      }
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngAfterViewInit(): void {
 | 
			
		||||
    if (isDefinedAndNotNull(this.predefinedEntityType)) {
 | 
			
		||||
      this.defaultEntityType = this.predefinedEntityType;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  setDisabledState(isDisabled: boolean): void {
 | 
			
		||||
@ -145,7 +143,7 @@ export class EntityListSelectComponent implements ControlValueAccessor, OnInit,
 | 
			
		||||
    this.entityListSelectFormGroup.get('entityIds').patchValue([...this.modelValue.ids], {emitEvent: true});
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  updateView(entityType: EntityType | AliasEntityType | null, entityIds: Array<string> | null) {
 | 
			
		||||
  private updateView(entityType: EntityType | AliasEntityType | null, entityIds: Array<string> | null) {
 | 
			
		||||
    if (this.modelValue.entityType !== entityType ||
 | 
			
		||||
      !this.compareIds(this.modelValue.ids, entityIds)) {
 | 
			
		||||
      this.modelValue = {
 | 
			
		||||
@ -156,7 +154,7 @@ export class EntityListSelectComponent implements ControlValueAccessor, OnInit,
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  compareIds(ids1: Array<string> | null, ids2: Array<string> | null): boolean {
 | 
			
		||||
  private compareIds(ids1: Array<string> | null, ids2: Array<string> | null): boolean {
 | 
			
		||||
    if (ids1 !== null && ids2 !== null) {
 | 
			
		||||
      return JSON.stringify(ids1) === JSON.stringify(ids2);
 | 
			
		||||
    } else {
 | 
			
		||||
@ -164,7 +162,7 @@ export class EntityListSelectComponent implements ControlValueAccessor, OnInit,
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  toEntityIds(modelValue: EntityListSelectModel): Array<EntityId> {
 | 
			
		||||
  private toEntityIds(modelValue: EntityListSelectModel): Array<EntityId> {
 | 
			
		||||
    if (modelValue !== null && modelValue.entityType && modelValue.ids && modelValue.ids.length > 0) {
 | 
			
		||||
      const entityType = modelValue.entityType;
 | 
			
		||||
      return modelValue.ids.map(id => ({entityType, id}));
 | 
			
		||||
 | 
			
		||||
@ -15,8 +15,13 @@
 | 
			
		||||
    limitations under the License.
 | 
			
		||||
 | 
			
		||||
-->
 | 
			
		||||
<mat-form-field [formGroup]="entityListFormGroup" class="mat-block" [class.tb-chip-list]="!labelText" [appearance]="appearance" [subscriptSizing]="subscriptSizing">
 | 
			
		||||
  <mat-label *ngIf="labelText">{{ labelText }}</mat-label>
 | 
			
		||||
<mat-form-field [formGroup]="entityListFormGroup" class="mat-block"
 | 
			
		||||
                [appearance]="inlineField ? 'outline' : appearance"
 | 
			
		||||
                [class.tb-chip-list]="!labelText && !inlineField"
 | 
			
		||||
                [class.tb-chips]="inlineField"
 | 
			
		||||
                [class.flex]="inlineField"
 | 
			
		||||
                [subscriptSizing]="inlineField ? 'dynamic' : subscriptSizing">
 | 
			
		||||
  <mat-label *ngIf="!inlineField && labelText">{{ labelText }}</mat-label>  <mat-label *ngIf="labelText">{{ labelText }}</mat-label>
 | 
			
		||||
  <mat-chip-grid #chipList formControlName="entities">
 | 
			
		||||
    <mat-chip-row
 | 
			
		||||
      *ngFor="let entity of entities"
 | 
			
		||||
@ -48,16 +53,16 @@
 | 
			
		||||
        </div>
 | 
			
		||||
        <ng-template #searchNotEmpty>
 | 
			
		||||
          <span>
 | 
			
		||||
          {{ translate.get('entity.no-entities-matching', {entity: searchText}) | async }}
 | 
			
		||||
          {{ 'entity.no-entities-matching' | translate: {entity: searchText} }}
 | 
			
		||||
          </span>
 | 
			
		||||
        </ng-template>
 | 
			
		||||
      </div>
 | 
			
		||||
    </mat-option>
 | 
			
		||||
  </mat-autocomplete>
 | 
			
		||||
  <mat-hint *ngIf="hint">
 | 
			
		||||
  <mat-hint *ngIf="!inlineField && hint">
 | 
			
		||||
    {{ hint }}
 | 
			
		||||
  </mat-hint>
 | 
			
		||||
  <mat-error *ngIf="entityListFormGroup.get('entities').hasError('required')">
 | 
			
		||||
  <mat-error *ngIf="!inlineField && entityListFormGroup.get('entities').hasError('required')">
 | 
			
		||||
    {{ requiredText }}
 | 
			
		||||
  </mat-error>
 | 
			
		||||
  <div matSuffix>
 | 
			
		||||
 | 
			
		||||
@ -14,17 +14,7 @@
 | 
			
		||||
/// limitations under the License.
 | 
			
		||||
///
 | 
			
		||||
 | 
			
		||||
import {
 | 
			
		||||
  AfterViewInit,
 | 
			
		||||
  Component,
 | 
			
		||||
  ElementRef,
 | 
			
		||||
  forwardRef,
 | 
			
		||||
  Input,
 | 
			
		||||
  OnChanges,
 | 
			
		||||
  OnInit,
 | 
			
		||||
  SimpleChanges,
 | 
			
		||||
  ViewChild
 | 
			
		||||
} from '@angular/core';
 | 
			
		||||
import { Component, ElementRef, forwardRef, Input, OnChanges, OnInit, SimpleChanges, ViewChild } from '@angular/core';
 | 
			
		||||
import {
 | 
			
		||||
  ControlValueAccessor,
 | 
			
		||||
  NG_VALIDATORS,
 | 
			
		||||
@ -65,7 +55,7 @@ import { isArray } from 'lodash';
 | 
			
		||||
    }
 | 
			
		||||
  ]
 | 
			
		||||
})
 | 
			
		||||
export class EntityListComponent implements ControlValueAccessor, OnInit, AfterViewInit, OnChanges {
 | 
			
		||||
export class EntityListComponent implements ControlValueAccessor, OnInit, OnChanges {
 | 
			
		||||
 | 
			
		||||
  entityListFormGroup: UntypedFormGroup;
 | 
			
		||||
 | 
			
		||||
@ -115,6 +105,10 @@ export class EntityListComponent implements ControlValueAccessor, OnInit, AfterV
 | 
			
		||||
  @coerceBoolean()
 | 
			
		||||
  syncIdsWithDB = false;
 | 
			
		||||
 | 
			
		||||
  @Input()
 | 
			
		||||
  @coerceBoolean()
 | 
			
		||||
  inlineField: boolean;
 | 
			
		||||
 | 
			
		||||
  @ViewChild('entityInput') entityInput: ElementRef<HTMLInputElement>;
 | 
			
		||||
  @ViewChild('entityAutocomplete') matAutocomplete: MatAutocomplete;
 | 
			
		||||
  @ViewChild('chipList', {static: true}) chipList: MatChipGrid;
 | 
			
		||||
@ -126,9 +120,9 @@ export class EntityListComponent implements ControlValueAccessor, OnInit, AfterV
 | 
			
		||||
 | 
			
		||||
  private dirty = false;
 | 
			
		||||
 | 
			
		||||
  private propagateChange = (v: any) => { };
 | 
			
		||||
  private propagateChange = (_v: any) => { };
 | 
			
		||||
 | 
			
		||||
  constructor(public translate: TranslateService,
 | 
			
		||||
  constructor(private translate: TranslateService,
 | 
			
		||||
              private entityService: EntityService,
 | 
			
		||||
              private fb: UntypedFormBuilder) {
 | 
			
		||||
    this.entityListFormGroup = this.fb.group({
 | 
			
		||||
@ -146,7 +140,7 @@ export class EntityListComponent implements ControlValueAccessor, OnInit, AfterV
 | 
			
		||||
    this.propagateChange = fn;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  registerOnTouched(fn: any): void {
 | 
			
		||||
  registerOnTouched(_fn: any): void {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnInit() {
 | 
			
		||||
@ -178,9 +172,6 @@ export class EntityListComponent implements ControlValueAccessor, OnInit, AfterV
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngAfterViewInit(): void {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  setDisabledState(isDisabled: boolean): void {
 | 
			
		||||
    this.disabled = isDisabled;
 | 
			
		||||
    if (isDisabled) {
 | 
			
		||||
 | 
			
		||||
@ -15,14 +15,16 @@
 | 
			
		||||
    limitations under the License.
 | 
			
		||||
 | 
			
		||||
-->
 | 
			
		||||
<mat-form-field [formGroup]="entityTypeFormGroup" [appearance]="appearance">
 | 
			
		||||
  <mat-label *ngIf="showLabel">{{ 'entity.type' | translate }}</mat-label>
 | 
			
		||||
<mat-form-field [formGroup]="entityTypeFormGroup"
 | 
			
		||||
                [subscriptSizing]="inlineField ? 'dynamic' : 'fixed'"
 | 
			
		||||
                [appearance]="inlineField ? 'outline' : appearance">
 | 
			
		||||
  <mat-label *ngIf="showLabel && !inlineField">{{ label }}</mat-label>
 | 
			
		||||
  <mat-select [required]="required" formControlName="entityType">
 | 
			
		||||
    <mat-option *ngFor="let type of entityTypes" [value]="type">
 | 
			
		||||
      {{ displayEntityTypeFn(type) }}
 | 
			
		||||
    </mat-option>
 | 
			
		||||
  </mat-select>
 | 
			
		||||
  <mat-error *ngIf="entityTypeFormGroup.get('entityType').hasError('required')">
 | 
			
		||||
  <mat-error *ngIf="!inlineField && entityTypeFormGroup.get('entityType').hasError('required')">
 | 
			
		||||
    {{ 'entity.type-required' | translate }}
 | 
			
		||||
  </mat-error>
 | 
			
		||||
</mat-form-field>
 | 
			
		||||
 | 
			
		||||
@ -52,6 +52,9 @@ export class EntityTypeSelectComponent implements ControlValueAccessor, OnInit,
 | 
			
		||||
  @coerceBoolean()
 | 
			
		||||
  showLabel: boolean;
 | 
			
		||||
 | 
			
		||||
  @Input()
 | 
			
		||||
  label = this.translate.instant('entity.type');
 | 
			
		||||
 | 
			
		||||
  @Input()
 | 
			
		||||
  @coerceBoolean()
 | 
			
		||||
  required: boolean;
 | 
			
		||||
@ -65,12 +68,16 @@ export class EntityTypeSelectComponent implements ControlValueAccessor, OnInit,
 | 
			
		||||
  @Input()
 | 
			
		||||
  appearance: MatFormFieldAppearance = 'fill';
 | 
			
		||||
 | 
			
		||||
  @Input()
 | 
			
		||||
  @coerceBoolean()
 | 
			
		||||
  inlineField: boolean;
 | 
			
		||||
 | 
			
		||||
  entityTypes: Array<EntityType | AliasEntityType | string>;
 | 
			
		||||
 | 
			
		||||
  private propagateChange = (v: any) => { };
 | 
			
		||||
  private propagateChange = (_v: any) => { };
 | 
			
		||||
 | 
			
		||||
  constructor(private entityService: EntityService,
 | 
			
		||||
              public translate: TranslateService,
 | 
			
		||||
              private translate: TranslateService,
 | 
			
		||||
              private fb: UntypedFormBuilder,
 | 
			
		||||
              private destroyRef: DestroyRef) {
 | 
			
		||||
    this.entityTypeFormGroup = this.fb.group({
 | 
			
		||||
@ -82,7 +89,7 @@ export class EntityTypeSelectComponent implements ControlValueAccessor, OnInit,
 | 
			
		||||
    this.propagateChange = fn;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  registerOnTouched(fn: any): void {
 | 
			
		||||
  registerOnTouched(_fn: any): void {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnInit() {
 | 
			
		||||
@ -97,7 +104,7 @@ export class EntityTypeSelectComponent implements ControlValueAccessor, OnInit,
 | 
			
		||||
      takeUntilDestroyed(this.destroyRef)
 | 
			
		||||
    ).subscribe(
 | 
			
		||||
      (value) => {
 | 
			
		||||
        let modelValue;
 | 
			
		||||
        let modelValue: EntityType | AliasEntityType;
 | 
			
		||||
        if (!value || value === '') {
 | 
			
		||||
          modelValue = null;
 | 
			
		||||
        } else {
 | 
			
		||||
 | 
			
		||||
@ -27,7 +27,7 @@
 | 
			
		||||
    </button>
 | 
			
		||||
  </div>
 | 
			
		||||
 | 
			
		||||
  <div class="tb-timewindow-form-content tb-form-panel no-border">
 | 
			
		||||
  <div class="tb-timewindow-form-content tb-form-panel no-border" [class.no-padding]="!panelMode">
 | 
			
		||||
    <ng-container *ngIf="timewindowForm.get('selectedTab').value === timewindowTypes.REALTIME">
 | 
			
		||||
      <section class="tb-form-panel stroked" *ngIf="realtimeIntervalSelectionAvailable; else timezoneSelectionPanel">
 | 
			
		||||
        <div class="tb-flex space-between"
 | 
			
		||||
@ -189,8 +189,8 @@
 | 
			
		||||
                 formControlName="timezone">
 | 
			
		||||
    </tb-timezone>
 | 
			
		||||
  </ng-template>
 | 
			
		||||
  <mat-divider></mat-divider>
 | 
			
		||||
  <div class="tb-panel-actions tb-flex flex-end no-gap">
 | 
			
		||||
  <mat-divider *ngIf="panelMode"></mat-divider>
 | 
			
		||||
  <div class="tb-panel-actions tb-flex flex-end no-gap" *ngIf="panelMode">
 | 
			
		||||
    <button type="button"
 | 
			
		||||
            mat-button
 | 
			
		||||
            [disabled]="(isLoading$ | async)"
 | 
			
		||||
 | 
			
		||||
@ -14,7 +14,17 @@
 | 
			
		||||
/// limitations under the License.
 | 
			
		||||
///
 | 
			
		||||
 | 
			
		||||
import { Component, Inject, InjectionToken, OnDestroy, OnInit, ViewContainerRef } from '@angular/core';
 | 
			
		||||
import {
 | 
			
		||||
  Component,
 | 
			
		||||
  EventEmitter,
 | 
			
		||||
  Inject,
 | 
			
		||||
  InjectionToken,
 | 
			
		||||
  OnDestroy,
 | 
			
		||||
  OnInit,
 | 
			
		||||
  Optional,
 | 
			
		||||
  Output,
 | 
			
		||||
  ViewContainerRef
 | 
			
		||||
} from '@angular/core';
 | 
			
		||||
import {
 | 
			
		||||
  AggregationType,
 | 
			
		||||
  currentHistoryTimewindow,
 | 
			
		||||
@ -57,6 +67,7 @@ export interface TimewindowPanelData {
 | 
			
		||||
  aggregation: boolean;
 | 
			
		||||
  timezone: boolean;
 | 
			
		||||
  isEdit: boolean;
 | 
			
		||||
  panelMode: boolean;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const TIMEWINDOW_PANEL_DATA = new InjectionToken<any>('TimewindowPanelData');
 | 
			
		||||
@ -68,6 +79,9 @@ export const TIMEWINDOW_PANEL_DATA = new InjectionToken<any>('TimewindowPanelDat
 | 
			
		||||
})
 | 
			
		||||
export class TimewindowPanelComponent extends PageComponent implements OnInit, OnDestroy {
 | 
			
		||||
 | 
			
		||||
  @Output()
 | 
			
		||||
  changeTimewindow = new EventEmitter<Timewindow>();
 | 
			
		||||
 | 
			
		||||
  historyOnly = false;
 | 
			
		||||
 | 
			
		||||
  forAllTimeEnabled = false;
 | 
			
		||||
@ -80,6 +94,8 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit, O
 | 
			
		||||
 | 
			
		||||
  isEdit = false;
 | 
			
		||||
 | 
			
		||||
  panelMode = true;
 | 
			
		||||
 | 
			
		||||
  timewindow: Timewindow;
 | 
			
		||||
 | 
			
		||||
  timewindowForm: UntypedFormGroup;
 | 
			
		||||
@ -125,7 +141,7 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit, O
 | 
			
		||||
  private destroy$ = new Subject<void>();
 | 
			
		||||
 | 
			
		||||
  constructor(@Inject(TIMEWINDOW_PANEL_DATA) public data: TimewindowPanelData,
 | 
			
		||||
              public overlayRef: OverlayRef,
 | 
			
		||||
              @Optional() public overlayRef: OverlayRef,
 | 
			
		||||
              protected store: Store<AppState>,
 | 
			
		||||
              public fb: UntypedFormBuilder,
 | 
			
		||||
              private timeService: TimeService,
 | 
			
		||||
@ -140,6 +156,7 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit, O
 | 
			
		||||
    this.aggregation = data.aggregation;
 | 
			
		||||
    this.timezone = data.timezone;
 | 
			
		||||
    this.isEdit = data.isEdit;
 | 
			
		||||
    this.panelMode = data.panelMode;
 | 
			
		||||
 | 
			
		||||
    this.updateTimewindowAdvancedParams();
 | 
			
		||||
 | 
			
		||||
@ -356,6 +373,15 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit, O
 | 
			
		||||
    ).subscribe((selectedTab: TimewindowType) => {
 | 
			
		||||
      this.onTimewindowTypeChange(selectedTab);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    if (!this.panelMode) {
 | 
			
		||||
      this.timewindowForm.valueChanges.pipe(
 | 
			
		||||
        takeUntil(this.destroy$)
 | 
			
		||||
      ).subscribe(() => {
 | 
			
		||||
        this.prepareTimewindowConfig();
 | 
			
		||||
        this.changeTimewindow.emit(this.timewindow);
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnDestroy() {
 | 
			
		||||
@ -381,7 +407,7 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit, O
 | 
			
		||||
  update() {
 | 
			
		||||
    this.prepareTimewindowConfig();
 | 
			
		||||
    this.result = this.timewindow;
 | 
			
		||||
    this.overlayRef.dispose();
 | 
			
		||||
    this.overlayRef?.dispose();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private prepareTimewindowConfig() {
 | 
			
		||||
@ -483,7 +509,7 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit, O
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  cancel() {
 | 
			
		||||
    this.overlayRef.dispose();
 | 
			
		||||
    this.overlayRef?.dispose();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  get minRealtimeAggInterval() {
 | 
			
		||||
 | 
			
		||||
@ -15,7 +15,7 @@
 | 
			
		||||
    limitations under the License.
 | 
			
		||||
 | 
			
		||||
-->
 | 
			
		||||
<button *ngIf="asButton && !strokedButton && !flatButton"
 | 
			
		||||
<button *ngIf="asButton && panelMode && !strokedButton && !flatButton"
 | 
			
		||||
        [disabled]="timewindowDisabled"
 | 
			
		||||
        type="button"
 | 
			
		||||
        mat-raised-button color="primary"
 | 
			
		||||
@ -23,7 +23,7 @@
 | 
			
		||||
  <mat-icon class="material-icons">query_builder</mat-icon>
 | 
			
		||||
  <span>{{displayValue()}}</span>
 | 
			
		||||
</button>
 | 
			
		||||
<button *ngIf="asButton && strokedButton"
 | 
			
		||||
<button *ngIf="asButton && panelMode && strokedButton"
 | 
			
		||||
        [disabled]="timewindowDisabled"
 | 
			
		||||
        type="button"
 | 
			
		||||
        mat-stroked-button color="primary"
 | 
			
		||||
@ -31,7 +31,7 @@
 | 
			
		||||
  <mat-icon class="material-icons">query_builder</mat-icon>
 | 
			
		||||
  <span>{{displayValue()}}</span>
 | 
			
		||||
</button>
 | 
			
		||||
<button *ngIf="asButton && flatButton"
 | 
			
		||||
<button *ngIf="asButton && panelMode && flatButton"
 | 
			
		||||
        [disabled]="timewindowDisabled"
 | 
			
		||||
        type="button"
 | 
			
		||||
        mat-button
 | 
			
		||||
@ -39,7 +39,7 @@
 | 
			
		||||
  <mat-icon class="material-icons">query_builder</mat-icon>
 | 
			
		||||
  <span>{{displayValue()}}</span>
 | 
			
		||||
</button>
 | 
			
		||||
<section *ngIf="!asButton"
 | 
			
		||||
<section *ngIf="!asButton && panelMode"
 | 
			
		||||
         class="tb-timewindow"
 | 
			
		||||
         [class]="{'no-padding': noPadding}"
 | 
			
		||||
         matTooltip="{{ 'timewindow.edit' | translate }}"
 | 
			
		||||
@ -55,3 +55,4 @@
 | 
			
		||||
  <tb-icon *ngIf="computedTimewindowStyle.showIcon && computedTimewindowStyle.iconPosition === 'right'"
 | 
			
		||||
           [style]="timewindowIconStyle">{{ computedTimewindowStyle.icon }}</tb-icon>
 | 
			
		||||
</section>
 | 
			
		||||
<ng-container #panelContainer></ng-container>
 | 
			
		||||
 | 
			
		||||
@ -17,6 +17,7 @@
 | 
			
		||||
import {
 | 
			
		||||
  ChangeDetectorRef,
 | 
			
		||||
  Component,
 | 
			
		||||
  DestroyRef,
 | 
			
		||||
  ElementRef,
 | 
			
		||||
  forwardRef,
 | 
			
		||||
  HostBinding,
 | 
			
		||||
@ -26,6 +27,7 @@ import {
 | 
			
		||||
  OnInit,
 | 
			
		||||
  SimpleChanges,
 | 
			
		||||
  StaticProvider,
 | 
			
		||||
  ViewChild,
 | 
			
		||||
  ViewContainerRef
 | 
			
		||||
} from '@angular/core';
 | 
			
		||||
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
 | 
			
		||||
@ -63,6 +65,7 @@ import {
 | 
			
		||||
} from '@shared/models/widget-settings.models';
 | 
			
		||||
import { DEFAULT_OVERLAY_POSITIONS } from '@shared/models/overlay.models';
 | 
			
		||||
import { fromEvent } from 'rxjs';
 | 
			
		||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
 | 
			
		||||
 | 
			
		||||
// @dynamic
 | 
			
		||||
@Component({
 | 
			
		||||
@ -79,6 +82,8 @@ import { fromEvent } from 'rxjs';
 | 
			
		||||
})
 | 
			
		||||
export class TimewindowComponent implements ControlValueAccessor, OnInit, OnChanges {
 | 
			
		||||
 | 
			
		||||
  @ViewChild('panelContainer', { read: ViewContainerRef, static: true }) panelContainer: ViewContainerRef;
 | 
			
		||||
 | 
			
		||||
  historyOnlyValue = false;
 | 
			
		||||
 | 
			
		||||
  @Input()
 | 
			
		||||
@ -180,6 +185,10 @@ export class TimewindowComponent implements ControlValueAccessor, OnInit, OnChan
 | 
			
		||||
  @coerceBoolean()
 | 
			
		||||
  disabled: boolean;
 | 
			
		||||
 | 
			
		||||
  @Input()
 | 
			
		||||
  @coerceBoolean()
 | 
			
		||||
  panelMode = true;
 | 
			
		||||
 | 
			
		||||
  innerValue: Timewindow;
 | 
			
		||||
 | 
			
		||||
  timewindowDisabled: boolean;
 | 
			
		||||
@ -197,7 +206,8 @@ export class TimewindowComponent implements ControlValueAccessor, OnInit, OnChan
 | 
			
		||||
              private datePipe: DatePipe,
 | 
			
		||||
              private cd: ChangeDetectorRef,
 | 
			
		||||
              private nativeElement: ElementRef,
 | 
			
		||||
              public viewContainerRef: ViewContainerRef) {
 | 
			
		||||
              private viewContainerRef: ViewContainerRef,
 | 
			
		||||
              private destroyRef: DestroyRef) {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnInit() {
 | 
			
		||||
@ -249,7 +259,8 @@ export class TimewindowComponent implements ControlValueAccessor, OnInit, OnChan
 | 
			
		||||
          quickIntervalOnly: this.quickIntervalOnly,
 | 
			
		||||
          aggregation: this.aggregation,
 | 
			
		||||
          timezone: this.timezone,
 | 
			
		||||
          isEdit: this.isEdit
 | 
			
		||||
          isEdit: this.isEdit,
 | 
			
		||||
          panelMode: this.panelMode,
 | 
			
		||||
        } as TimewindowPanelData
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
@ -317,6 +328,9 @@ export class TimewindowComponent implements ControlValueAccessor, OnInit, OnChan
 | 
			
		||||
    } else {
 | 
			
		||||
      this.updateDisplayValue();
 | 
			
		||||
    }
 | 
			
		||||
    if (!this.panelMode) {
 | 
			
		||||
      this.createPanel();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  notifyChanged() {
 | 
			
		||||
@ -328,6 +342,9 @@ export class TimewindowComponent implements ControlValueAccessor, OnInit, OnChan
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  updateDisplayValue() {
 | 
			
		||||
    if (!this.panelMode) {
 | 
			
		||||
      return
 | 
			
		||||
    }
 | 
			
		||||
    if (this.innerValue.selectedTab === TimewindowType.REALTIME && !this.historyOnly) {
 | 
			
		||||
      this.innerValue.displayValue = this.displayTypePrefix ? (this.translate.instant('timewindow.realtime') + ' - ') : '';
 | 
			
		||||
      if (this.innerValue.realtime.realtimeType === RealtimeWindowType.INTERVAL) {
 | 
			
		||||
@ -373,4 +390,29 @@ export class TimewindowComponent implements ControlValueAccessor, OnInit, OnChan
 | 
			
		||||
      )));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private createPanel() {
 | 
			
		||||
    this.panelContainer.clear();
 | 
			
		||||
    const panelData = {
 | 
			
		||||
      timewindow: deepClone(this.innerValue),
 | 
			
		||||
      historyOnly: this.historyOnly,
 | 
			
		||||
      forAllTimeEnabled: this.forAllTimeEnabled,
 | 
			
		||||
      quickIntervalOnly: this.quickIntervalOnly,
 | 
			
		||||
      aggregation: this.aggregation,
 | 
			
		||||
      timezone: this.timezone,
 | 
			
		||||
      isEdit: this.isEdit,
 | 
			
		||||
      panelMode: this.panelMode,
 | 
			
		||||
    }
 | 
			
		||||
    const injector = Injector.create({
 | 
			
		||||
      providers: [{ provide: TIMEWINDOW_PANEL_DATA, useValue: panelData }],
 | 
			
		||||
      parent: this.viewContainerRef.injector
 | 
			
		||||
    });
 | 
			
		||||
    const componentRef = this.panelContainer.createComponent(TimewindowPanelComponent, {index: 0, injector});
 | 
			
		||||
    componentRef.instance.changeTimewindow.pipe(
 | 
			
		||||
      takeUntilDestroyed(this.destroyRef)
 | 
			
		||||
    ).subscribe(value => {
 | 
			
		||||
      this.innerValue = value;
 | 
			
		||||
      this.timewindowDisabled = this.isTimewindowDisabled();
 | 
			
		||||
      this.notifyChanged();
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1406,3 +1406,28 @@ export const calculateInterval = (startTime: number, endTime: number,
 | 
			
		||||
 | 
			
		||||
export const getCurrentTimeForComparison = (timeForComparison: moment_.unitOfTime.DurationConstructor, tz?: string): moment_.Moment =>
 | 
			
		||||
  getCurrentTime(tz).subtract(1, timeForComparison);
 | 
			
		||||
 | 
			
		||||
export const getTimePageLinkInterval = (timewindow: Timewindow): {startTime?: number; endTime?: number} => {
 | 
			
		||||
  const interval: {startTime?: number; endTime?: number} = {};
 | 
			
		||||
  switch (timewindow.history.historyType) {
 | 
			
		||||
    case HistoryWindowType.LAST_INTERVAL:
 | 
			
		||||
      const currentTime = Date.now();
 | 
			
		||||
      interval.startTime = currentTime - timewindow.history.timewindowMs;
 | 
			
		||||
      interval.endTime = currentTime;
 | 
			
		||||
      break;
 | 
			
		||||
    case HistoryWindowType.FIXED:
 | 
			
		||||
      interval.startTime = timewindow.history.fixedTimewindow.startTimeMs;
 | 
			
		||||
      interval.endTime = timewindow.history.fixedTimewindow.endTimeMs;
 | 
			
		||||
      break;
 | 
			
		||||
    case HistoryWindowType.INTERVAL:
 | 
			
		||||
      const startEndTime = calculateIntervalStartEndTime(timewindow.history.quickInterval);
 | 
			
		||||
      interval.startTime = startEndTime[0];
 | 
			
		||||
      interval.endTime = startEndTime[1];
 | 
			
		||||
      break;
 | 
			
		||||
    case HistoryWindowType.FOR_ALL_TIME:
 | 
			
		||||
      interval.startTime = null;
 | 
			
		||||
      interval.endTime = null;
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
  return interval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user