UI: Improved timewindow position and clear code in alarm filter config
This commit is contained in:
		
							parent
							
								
									bff3297c56
								
							
						
					
					
						commit
						f0fbc784b4
					
				@ -17,7 +17,7 @@
 | 
			
		||||
// eslint-disable-next-line @typescript-eslint/triple-slash-reference
 | 
			
		||||
/// <reference path="../../../../src/typings/rawloader.typings.d.ts" />
 | 
			
		||||
 | 
			
		||||
import { ElementRef, Inject, Injectable, NgZone } from '@angular/core';
 | 
			
		||||
import { Inject, Injectable, NgZone } from '@angular/core';
 | 
			
		||||
import { WINDOW } from '@core/services/window.service';
 | 
			
		||||
import { ExceptionData } from '@app/shared/models/error.models';
 | 
			
		||||
import {
 | 
			
		||||
@ -45,7 +45,7 @@ import { alarmFields, alarmSeverityTranslations, alarmStatusTranslations } from
 | 
			
		||||
import { materialColors } from '@app/shared/models/material.models';
 | 
			
		||||
import { WidgetInfo } from '@home/models/widget-component.models';
 | 
			
		||||
import jsonSchemaDefaults from 'json-schema-defaults';
 | 
			
		||||
import { fromEvent, Observable, Subscription } from 'rxjs';
 | 
			
		||||
import { Observable } from 'rxjs';
 | 
			
		||||
import { publishReplay, refCount } from 'rxjs/operators';
 | 
			
		||||
import { WidgetContext } from '@app/modules/home/models/widget-component.models';
 | 
			
		||||
import {
 | 
			
		||||
@ -57,8 +57,6 @@ import {
 | 
			
		||||
import { EntityId } from '@shared/models/id/entity-id';
 | 
			
		||||
import { DatePipe } from '@angular/common';
 | 
			
		||||
import { entityTypeTranslations } from '@shared/models/entity-type.models';
 | 
			
		||||
import { OverlayRef } from '@angular/cdk/overlay';
 | 
			
		||||
import { ResizeObserver } from '@juggle/resize-observer';
 | 
			
		||||
 | 
			
		||||
const i18nRegExp = new RegExp(`{${i18nPrefix}:[^{}]+}`, 'g');
 | 
			
		||||
 | 
			
		||||
@ -530,24 +528,4 @@ export class UtilsService {
 | 
			
		||||
    return base64toObj(b64Encoded);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public updateOverlayMaxHeigth(overlay: OverlayRef, observeElementRef?: ElementRef): Subscription {
 | 
			
		||||
    const observeElement = observeElementRef ? observeElementRef.nativeElement : overlay.overlayElement.children[0];
 | 
			
		||||
 | 
			
		||||
    const setMaxHeigthOverlay = () => {
 | 
			
		||||
      const top = observeElement.getBoundingClientRect().top;
 | 
			
		||||
      const viewport = window.innerHeight;
 | 
			
		||||
      overlay.updateSize({
 | 
			
		||||
        maxHeight: viewport - top
 | 
			
		||||
      });
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const observer = new ResizeObserver(() => {
 | 
			
		||||
      setMaxHeigthOverlay();
 | 
			
		||||
      observer.unobserve(observeElement);
 | 
			
		||||
    });
 | 
			
		||||
    observer.observe(observeElement);
 | 
			
		||||
 | 
			
		||||
    return fromEvent(window, 'resize').subscribe(() => setMaxHeigthOverlay());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -31,7 +31,7 @@ import {
 | 
			
		||||
import { ControlValueAccessor, NG_VALUE_ACCESSOR, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
 | 
			
		||||
import { AlarmFilterConfig, alarmFilterConfigEquals } from '@shared/models/query/query.models';
 | 
			
		||||
import { coerceBoolean } from '@shared/decorators/coercion';
 | 
			
		||||
import { ConnectedPosition, Overlay, OverlayConfig, OverlayRef } from '@angular/cdk/overlay';
 | 
			
		||||
import { Overlay, OverlayConfig, OverlayRef } from '@angular/cdk/overlay';
 | 
			
		||||
import { TemplatePortal } from '@angular/cdk/portal';
 | 
			
		||||
import {
 | 
			
		||||
  AlarmAssigneeOption,
 | 
			
		||||
@ -44,8 +44,8 @@ import { MatChipInputEvent } from '@angular/material/chips';
 | 
			
		||||
import { COMMA, ENTER, SEMICOLON } from '@angular/cdk/keycodes';
 | 
			
		||||
import { TranslateService } from '@ngx-translate/core';
 | 
			
		||||
import { deepClone } from '@core/utils';
 | 
			
		||||
import { Subscription } from 'rxjs';
 | 
			
		||||
import { UtilsService } from '@core/services/utils.service';
 | 
			
		||||
import { fromEvent, Subscription } from 'rxjs';
 | 
			
		||||
import { POSITION_MAP } from '@shared/components/popover.models';
 | 
			
		||||
 | 
			
		||||
export const ALARM_FILTER_CONFIG_DATA = new InjectionToken<any>('AlarmFilterConfigData');
 | 
			
		||||
 | 
			
		||||
@ -128,7 +128,6 @@ export class AlarmFilterConfigComponent implements OnInit, OnDestroy, ControlVal
 | 
			
		||||
              private translate: TranslateService,
 | 
			
		||||
              private overlay: Overlay,
 | 
			
		||||
              private nativeElement: ElementRef,
 | 
			
		||||
              private utils: UtilsService,
 | 
			
		||||
              private viewContainerRef: ViewContainerRef) {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -202,14 +201,9 @@ export class AlarmFilterConfigComponent implements OnInit, OnDestroy, ControlVal
 | 
			
		||||
      minWidth: ''
 | 
			
		||||
    });
 | 
			
		||||
    config.hasBackdrop = true;
 | 
			
		||||
    const connectedPosition: ConnectedPosition = {
 | 
			
		||||
      originX: 'start',
 | 
			
		||||
      originY: 'bottom',
 | 
			
		||||
      overlayX: 'start',
 | 
			
		||||
      overlayY: 'top'
 | 
			
		||||
    };
 | 
			
		||||
    config.positionStrategy = this.overlay.position().flexibleConnectedTo(this.nativeElement)
 | 
			
		||||
      .withPositions([connectedPosition]);
 | 
			
		||||
    config.positionStrategy = this.overlay.position()
 | 
			
		||||
      .flexibleConnectedTo(this.nativeElement)
 | 
			
		||||
      .withPositions([POSITION_MAP.bottomLeft]);
 | 
			
		||||
 | 
			
		||||
    this.alarmFilterOverlayRef = this.overlay.create(config);
 | 
			
		||||
    this.alarmFilterOverlayRef.backdropClick().subscribe(() => {
 | 
			
		||||
@ -217,7 +211,9 @@ export class AlarmFilterConfigComponent implements OnInit, OnDestroy, ControlVal
 | 
			
		||||
    });
 | 
			
		||||
    this.alarmFilterOverlayRef.attach(new TemplatePortal(this.alarmFilterPanel,
 | 
			
		||||
      this.viewContainerRef));
 | 
			
		||||
    this.resizeWindows = this.utils.updateOverlayMaxHeigth(this.alarmFilterOverlayRef);
 | 
			
		||||
    this.resizeWindows = fromEvent(window, 'resize').subscribe(() => {
 | 
			
		||||
      this.alarmFilterOverlayRef.updatePosition();
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  cancel() {
 | 
			
		||||
 | 
			
		||||
@ -42,7 +42,7 @@ import cssjs from '@core/css/css';
 | 
			
		||||
import { sortItems } from '@shared/models/page/page-link';
 | 
			
		||||
import { Direction } from '@shared/models/page/sort-order';
 | 
			
		||||
import { CollectionViewer, DataSource, SelectionModel } from '@angular/cdk/collections';
 | 
			
		||||
import { BehaviorSubject, forkJoin, merge, Observable, Subject, Subscription } from 'rxjs';
 | 
			
		||||
import { BehaviorSubject, forkJoin, fromEvent, merge, Observable, Subject, Subscription } from 'rxjs';
 | 
			
		||||
import { emptyPageData, PageData } from '@shared/models/page/page-data';
 | 
			
		||||
import { debounceTime, distinctUntilChanged, map, take, takeUntil, tap } from 'rxjs/operators';
 | 
			
		||||
import { MatPaginator } from '@angular/material/paginator';
 | 
			
		||||
@ -123,6 +123,7 @@ import {
 | 
			
		||||
} from '@home/components/alarm/alarm-filter-config.component';
 | 
			
		||||
import { getCurrentAuthUser } from '@core/auth/auth.selectors';
 | 
			
		||||
import { FormBuilder } from '@angular/forms';
 | 
			
		||||
import { DEFAULT_OVERLAY_POSITIONS } from '@shared/components/popover.models';
 | 
			
		||||
 | 
			
		||||
interface AlarmsTableWidgetSettings extends TableWidgetSettings {
 | 
			
		||||
  alarmsTitle: string;
 | 
			
		||||
@ -572,14 +573,9 @@ export class AlarmsTableWidgetComponent extends PageComponent implements OnInit,
 | 
			
		||||
      height: 'fit-content',
 | 
			
		||||
      maxHeight: '75vh'
 | 
			
		||||
    });
 | 
			
		||||
    const connectedPosition: ConnectedPosition = {
 | 
			
		||||
      originX: 'end',
 | 
			
		||||
      originY: 'bottom',
 | 
			
		||||
      overlayX: 'end',
 | 
			
		||||
      overlayY: 'top'
 | 
			
		||||
    };
 | 
			
		||||
    config.positionStrategy = this.overlay.position().flexibleConnectedTo(target as HTMLElement)
 | 
			
		||||
      .withPositions([connectedPosition]);
 | 
			
		||||
    config.positionStrategy = this.overlay.position()
 | 
			
		||||
      .flexibleConnectedTo(target as HTMLElement)
 | 
			
		||||
      .withPositions(DEFAULT_OVERLAY_POSITIONS);
 | 
			
		||||
 | 
			
		||||
    const overlayRef = this.overlay.create(config);
 | 
			
		||||
    overlayRef.backdropClick().subscribe(() => {
 | 
			
		||||
@ -614,10 +610,12 @@ export class AlarmsTableWidgetComponent extends PageComponent implements OnInit,
 | 
			
		||||
    const componentRef = overlayRef.attach(new ComponentPortal(AlarmFilterConfigComponent,
 | 
			
		||||
      this.viewContainerRef, injector));
 | 
			
		||||
 | 
			
		||||
    const resizeWindows = this.utils.updateOverlayMaxHeigth(overlayRef, componentRef.location);
 | 
			
		||||
    const resizeWindows$ = fromEvent(window, 'resize').subscribe(() => {
 | 
			
		||||
      overlayRef.updatePosition();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    componentRef.onDestroy(() => {
 | 
			
		||||
      resizeWindows.unsubscribe();
 | 
			
		||||
      resizeWindows$.unsubscribe();
 | 
			
		||||
      if (componentRef.instance.panelResult) {
 | 
			
		||||
        const result = componentRef.instance.panelResult;
 | 
			
		||||
        const alarmFilter = this.entityService.resolveAlarmFilter(result, false);
 | 
			
		||||
 | 
			
		||||
@ -71,6 +71,9 @@ export const POSITION_MAP: { [key: string]: ConnectionPositionPair } = {
 | 
			
		||||
 | 
			
		||||
export const DEFAULT_POPOVER_POSITIONS = [POSITION_MAP.top, POSITION_MAP.right, POSITION_MAP.bottom, POSITION_MAP.left];
 | 
			
		||||
 | 
			
		||||
export const DEFAULT_OVERLAY_POSITIONS = [POSITION_MAP.bottomLeft, POSITION_MAP.bottomRight, POSITION_MAP.topLeft,
 | 
			
		||||
  POSITION_MAP.topRight, POSITION_MAP.left, POSITION_MAP.right];
 | 
			
		||||
 | 
			
		||||
export function getPlacementName(position: ConnectedOverlayPositionChange): PopoverPlacement | undefined {
 | 
			
		||||
  for (const placement in POSITION_MAP) {
 | 
			
		||||
    if (
 | 
			
		||||
 | 
			
		||||
@ -17,6 +17,7 @@
 | 
			
		||||
 | 
			
		||||
:host {
 | 
			
		||||
  min-width: 355px;
 | 
			
		||||
  display: block;
 | 
			
		||||
 | 
			
		||||
  @media #{$mat-xs} {
 | 
			
		||||
    min-width: 0;
 | 
			
		||||
 | 
			
		||||
@ -18,9 +18,13 @@ import {
 | 
			
		||||
  ChangeDetectorRef,
 | 
			
		||||
  Component,
 | 
			
		||||
  ElementRef,
 | 
			
		||||
  forwardRef, HostBinding,
 | 
			
		||||
  forwardRef,
 | 
			
		||||
  HostBinding,
 | 
			
		||||
  Injector,
 | 
			
		||||
  Input, OnChanges, OnInit, SimpleChanges,
 | 
			
		||||
  Input,
 | 
			
		||||
  OnChanges,
 | 
			
		||||
  OnInit,
 | 
			
		||||
  SimpleChanges,
 | 
			
		||||
  StaticProvider,
 | 
			
		||||
  ViewContainerRef
 | 
			
		||||
} from '@angular/core';
 | 
			
		||||
@ -47,15 +51,18 @@ import { TimeService } from '@core/services/time.service';
 | 
			
		||||
import { TooltipPosition } from '@angular/material/tooltip';
 | 
			
		||||
import { deepClone, isDefinedAndNotNull } from '@core/utils';
 | 
			
		||||
import { coerceBooleanProperty } from '@angular/cdk/coercion';
 | 
			
		||||
import { ConnectedPosition, Overlay, OverlayConfig, OverlayRef } from '@angular/cdk/overlay';
 | 
			
		||||
import { Overlay, OverlayConfig, OverlayRef } from '@angular/cdk/overlay';
 | 
			
		||||
import { ComponentPortal } from '@angular/cdk/portal';
 | 
			
		||||
import { coerceBoolean } from '@shared/decorators/coercion';
 | 
			
		||||
import {
 | 
			
		||||
  ComponentStyle,
 | 
			
		||||
  defaultTimewindowStyle, iconStyle,
 | 
			
		||||
  defaultTimewindowStyle,
 | 
			
		||||
  iconStyle,
 | 
			
		||||
  textStyle,
 | 
			
		||||
  TimewindowStyle
 | 
			
		||||
} from '@shared/models/widget-settings.models';
 | 
			
		||||
import { DEFAULT_OVERLAY_POSITIONS } from '@shared/components/popover.models';
 | 
			
		||||
import { fromEvent } from 'rxjs';
 | 
			
		||||
 | 
			
		||||
// @dynamic
 | 
			
		||||
@Component({
 | 
			
		||||
@ -223,14 +230,10 @@ export class TimewindowComponent implements ControlValueAccessor, OnInit, OnChan
 | 
			
		||||
      maxHeight: '80vh',
 | 
			
		||||
      height: 'min-content'
 | 
			
		||||
    });
 | 
			
		||||
    const connectedPosition: ConnectedPosition = {
 | 
			
		||||
      originX: 'start',
 | 
			
		||||
      originY: 'bottom',
 | 
			
		||||
      overlayX: 'start',
 | 
			
		||||
      overlayY: 'top'
 | 
			
		||||
    };
 | 
			
		||||
    config.positionStrategy = this.overlay.position().flexibleConnectedTo(this.nativeElement)
 | 
			
		||||
      .withPositions([connectedPosition]);
 | 
			
		||||
 | 
			
		||||
    config.positionStrategy = this.overlay.position()
 | 
			
		||||
      .flexibleConnectedTo(this.nativeElement)
 | 
			
		||||
      .withPositions(DEFAULT_OVERLAY_POSITIONS);
 | 
			
		||||
 | 
			
		||||
    const overlayRef = this.overlay.create(config);
 | 
			
		||||
    overlayRef.backdropClick().subscribe(() => {
 | 
			
		||||
@ -257,7 +260,11 @@ export class TimewindowComponent implements ControlValueAccessor, OnInit, OnChan
 | 
			
		||||
    const injector = Injector.create({parent: this.viewContainerRef.injector, providers});
 | 
			
		||||
    const componentRef = overlayRef.attach(new ComponentPortal(TimewindowPanelComponent,
 | 
			
		||||
      this.viewContainerRef, injector));
 | 
			
		||||
    const resizeWindows$ = fromEvent(window, 'resize').subscribe(() => {
 | 
			
		||||
      overlayRef.updatePosition();
 | 
			
		||||
    });
 | 
			
		||||
    componentRef.onDestroy(() => {
 | 
			
		||||
      resizeWindows$.unsubscribe();
 | 
			
		||||
      if (componentRef.instance.result) {
 | 
			
		||||
        this.innerValue = componentRef.instance.result;
 | 
			
		||||
        this.timewindowDisabled = this.isTimewindowDisabled();
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user