All files / src/app/components/multi-select-signals multi-select-signals.component.ts

97.05% Statements 66/68
86.36% Branches 19/22
100% Functions 18/18
96.61% Lines 57/59

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128                            68x 9x 9x 9x 9x 9x 9x 9x 9x 9x   9x 9x 9x 9x     9x     9x 9x 9x   9x 20x 20x 12x 11x     1x   12x 1x   12x     8x       9x       9x   9x   900x 100x 100x 1x     900x   9x 9x           25x 18x   38x     90x     2501x 38x         100x 7x         16x       45x 45x 45x         56x 117x 117x 117x 85x       117x 117x            
import { Component, EventEmitter, OnInit, OnChanges, Input, Output } from '@angular/core';
import { TwinpadApiService } from '../../services/twinpad-api.service';
import { Signal } from '../../models/signals';
import { MultiSelectModule } from 'primeng/multiselect';
import { FormsModule } from '@angular/forms';
import { Router, ActivatedRoute, Params } from '@angular/router';
 
 
@Component({
  selector: 'app-multi-select-signals',
  imports: [MultiSelectModule, FormsModule],
  templateUrl: './multi-select-signals.component.html',
  styleUrl: './multi-select-signals.component.scss'
})
export class MultiSelectSignalsComponent implements OnInit, OnChanges {
  @Input() selectionLimit: number | null = null;
  @Input() isLive: boolean = true;
  @Input() graphId: string = "";
  @Output() selectionChanged = new EventEmitter<string[]>();
  @Output() finishedLoadingSignals = new EventEmitter<boolean>();
  virtualScrollItemSize: number = 25;
  totalSignals: number = 0;
  isFiltering: boolean = false;
  signalIds: string[] = [];
  signalsById: Map<string, Signal>;
  signalIdsToDisplay: string[] = [];
  signalIdsToPlot: string[] = [];
  loadedFromUrl: boolean = false;
  querySignalId: string = "signal_id";
 
 
  constructor(private twinpadApiService: TwinpadApiService, private router: Router, private route: ActivatedRoute) { }
 
  ngOnInit(): void {
    this.signalIds = [];
    this.signalsById = new Map();
    this.querySignalId = `signal_id${this.graphId}`;
 
    this.route.queryParams.subscribe(params => {
      const signalIds = params[this.querySignalId];
      if (signalIds) {
        if (signalIds instanceof Array) {
          this.signalIdsToPlot = signalIds;
        }
        else {
          this.signalIdsToPlot = [signalIds];
        }
        if (!this.signalIds || this.signalIds.length == 0) {
          this.signalIds = this.signalIdsToPlot.map(x => x);
        }
        this.loadedFromUrl = true;
      }
      else {
        this.signalIdsToPlot = [];
      }
    });
 
    this.loadSignalIds(this.loadedFromUrl);
  }
 
  loadSignalIds(loadedFromUrl: boolean) {
    this.twinpadApiService.getSignalsIds().subscribe({
      next: signalIds => {
        for (const signalId of signalIds) {
          // This is done to not disturb the signals' order when they've been added from url query
          if (loadedFromUrl) {
            const index: number = this.signalIds.indexOf(signalId);
            if (index > -1) {
              this.signalIds.splice(index, 1);
            }
          }
          this.signalIds.push(signalId);
        }
        this.filterSignalIds();
        this.finishedLoadingSignals.emit(true);
      }
    });
  }
 
  filterSignalIds() {
    if (this.isLive) {
      this.twinpadApiService.devicesBehaviorSubject$.subscribe({
        next: devices => {
          Iif (devices === undefined) {
            return;
          }
          const downDeviceIds: string[] = devices.filter(device => device.status !== "up").map(device => device.device_id);
          // display only signals of devices who are not down
          // can't filter on devices who are up since some signals don't come from real devices (data storage)
          this.signalIdsToDisplay = this.signalIds.filter(signalId => downDeviceIds.indexOf(signalId.split(".")[0]) === -1);
          this.cleanSelectedSignals();
        }
      });
    }
    else {
      this.signalIdsToDisplay = this.signalIds.map(signalId => signalId);
      this.cleanSelectedSignals();
    }
  }
 
  ngOnChanges() {
    this.filterSignalIds();
  }
 
  cleanSelectedSignals() {
    const newSelection = this.signalIdsToPlot.filter(signalId => this.signalIdsToDisplay.indexOf(signalId) !== -1);
    Eif (newSelection !== this.signalIdsToPlot) {
      this.onChangeSelection(newSelection);
    }
  }
 
  onChangeSelection(newSelection: string[]){
    this.route.queryParams.subscribe(queryParams => {
      const params: Params = {};
      const signal_id_string = this.querySignalId;
      for (const [key, value] of Object.entries(queryParams)) {
        Iif (key !== signal_id_string) {
          params[key] = value;
        }
      }
      params[signal_id_string] = newSelection;
      this.router.navigate([], {
        queryParams: params
      });
    });
  }
}