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