ngOnInit()

in web/frontend/src/app/pages/streams/components/deltix-charts/charts/deltix-charts.component.ts [235:488]


  ngOnInit() {
    this.globalSettings$ = this.globalSettingService.getFilters();
    this.currentTab$ = this.appStore.pipe(select(getActiveOrFirstTab));
    this.httpError$ = this.everChartFeedService.onHttpError();
    this.httpErrorText$ = this.httpError$.pipe(map(httpError => httpError.error.message || httpError.error.error));
    
    this.noPoints$ = this.everChartFeedService.onNoPoints();
    
    this.globalSettings$.pipe(takeUntil(this.destroy$)).subscribe((filters) => {
      const filter_date_format = filters.dateFormat[0];
      const filter_time_format = filters.timeFormat[0];
      this.filter_timezone = filters.timezone[0];
      this.date_format = filter_date_format;
      this.time_format = filter_time_format;
      this.datetime_separator = getFormatSeparator(this.date_format);
      
      this.format = filter_date_format + ' ' + filter_time_format;
      this.bsFormat = filter_date_format.toUpperCase() + ' ' + filter_time_format;
      this.bsFormat = this.bsFormat.replace('tt', 'A');
      this.bsFormat = this.bsFormat.replace(/f/g, 'S');
    });
    
    this.chartExchangeService
      .onManuallyCHanged()
      .pipe(takeUntil(this.destroy$))
      .subscribe(() => {
        this.retry();
      });
    
    this.chartDate$ = combineLatest([this.globalSettings$, this.currentTab$]).pipe(
      filter(([settings, tab]) => Boolean(tab?.filter?.from && tab?.filter?.to)),
      map(([settings, tab]) => {
        if (
          new Date(tab.filter.to).getTime() - new Date(tab.filter.from).getTime() >
          1000 * 60 * 60 * 24
        ) {
          return '';
        }
        return formatDateTime(tab.filter.from, settings.dateFormat[0], settings.timezone[0].name);
      }),
    );
    
    this.resize$
      .pipe(debounceTime(350), distinctUntilChanged(equal), takeUntil(this.destroy$))
      .subscribe(({width, height}) => {
        this.everChartFeedService.setWidth(width);
        this.onContainerResize(width, height);
      });
    
    this.tooltipData$ = combineLatest([
      this.mouseMove$.pipe(
        distinctUntilChanged(
          (p: { time: number; points: any; yVal: number }, c) =>
            `${p.time}-${p.yVal}` === `${c.time}-${c.yVal}`,
        ),
      ),
      this.currentTab$,
      this.hideTooltip$,
    ]).pipe(
      auditTime(75),
      switchMap(([moveEvent, tab, hideTooltip]) => {
        const storageAndColors$: Observable<[{ colors: StoredColorsMap, showLines: string[] }, Partial<DeltixChartStorage> | null]> = moveEvent.points && tab.filter.chart_type === ChartTypes.LINEAR ?
          combineLatest([this.linearChartsService.showLinesAndColors(), this.everChartFeedService.storage$.pipe(filter(s => !!s?.data))]) :
          of([{colors: {}, showLines: []}, null]);
        
        return storageAndColors$.pipe(
          map(([linesAndColors, storage]) => [moveEvent, tab, hideTooltip, linesAndColors, storage]),
        );
      }),
      
      map(([moveEvent, tab, hideTooltip, linesAndColors, storage]: [MouseMoveEvent, TabModel, boolean, { colors: StoredColorsMap, showLines: string[] }, Partial<DeltixChartStorage> | null]) => {
        if (!moveEvent.time || hideTooltip) {
          return null;
        }
        
        const point = JSON.parse(JSON.stringify(moveEvent.points));
        const isBars = barChartTypes.includes(tab?.filter.chart_type);
        const isBBO = tab?.filter.chart_type === ChartTypes.TRADES_BBO;
        const isLinear = tab.filter.chart_type === ChartTypes.LINEAR;
        
        if (this.pointIsTrade(point, moveEvent.yVal)) {
          delete point.BBO;
        } else {
          delete point.TRADES;
        }
        
        const borderGreen =
          (point.BARS && point.BARS.open < point.BARS.close) ||
          (point.BBO && point.BBO.askPrice > point.BBO.bidPrice);
        const borderRed =
          (point.BARS && point.BARS.open > point.BARS.close) ||
          (point.BBO && point.BBO.askPrice < point.BBO.bidPrice);
        
        const borderBlue = !borderRed && !borderGreen;
        
        let borderColor = null;
        const colorNames = {};
        Object.keys(linesAndColors.colors).forEach(key => colorNames[this.linearId(key)] = key);
        if (isLinear) {
          const lineName = Object.keys(point).find(key => moveEvent.yVal === point[key].value);
          if (lineName) {
            borderColor = this.colorToString(linesAndColors.colors[colorNames[lineName]]);
          }
        }
        
        let from;
        let to;
        
        if (point.BARS) {
          const aggregation = tab.filter.period.aggregation;
          from = this.formatTooltipBarTime(aggregation, moveEvent.time - tab.filter.period.aggregation);
          to = this.formatTooltipBarTime(aggregation, moveEvent.time);
        }
        
        const values = {};
        
        if (isLinear) {
          const firstKey = Object.keys(point)[0];
          storage.data?.find(p => {
            const isCurrent = p.time === point[firstKey].time;
            Object.keys(p.points).forEach(key => {
              values[key] = p.points[key].value;
            });
            return isCurrent;
          });
        }
  
        const linearData = linesAndColors.showLines.map(line => {
          let value = values[this.linearId(line)];
      
          if (value === undefined || isNaN(value)) {
            value = '-';
          }
    
          return {
            name: line,
            value,
            isHighlight: moveEvent.yVal === point[this.linearId(line)]?.value,
            highlightColor: this.colorToString(linesAndColors.colors[line]),
          };
        });
        
        return {
          time: formatDateTime(moveEvent.time, this.format, this.filter_timezone.name),
          point,
          from,
          to,
          yVal: moveEvent.yVal,
          isBars,
          isL2: tab?.filter.chart_type === ChartTypes.PRICES_L2,
          isLinear,
          linearData,
          isBBO,
          borderGreen,
          borderRed,
          borderBlue,
          borderColor,
        };
      }),
    );
  
    this.magnetCoordinates$ = combineLatest([
      this.mouseMove$,
      this.currentTab$.pipe(
        map((tab) => ({
          from: tab?.filter ? new Date(tab.filter.from).getTime() : 0,
          to: tab?.filter ? new Date(tab.filter.to).getTime() : 0,
        })),
      ),
    ]).pipe(map((([data, {from, to}]) => {
      const {width, height} = this.getSize();
      if (!data.time) {
        return null;
      }
      
      let yInPx = 0;
      const widthInMs = to - from;
      const xCoordRatio = data.time <= to ? (data.time - from) / widthInMs : 0.95;
      const x = Math.max(0, Math.round(xCoordRatio * width));
      
      const pads = this.appFacade.getStateFor('everChart', '1').app.pads;
      if (pads.LINEAR) {
        const pad = pads.LINEAR;
        const decimalsL = pad.max.next.toString().split('.')[1]?.length || 0;
        const multi = Math.pow(10, decimalsL);
        
        yInPx = this.getYCoordinate(data.yVal * multi, height, pad.min.next * multi, pad.max.next * multi);
      }
     
      return {
        x,
        y: data.y,
        yInPx,
      };
    })));
    
    this.tooltipPosition$ = combineLatest([
      this.magnetCoordinates$,
      this.tooltipDimensions(),
      this.mouseMove$,
    ]).pipe(
      map(([coordinates, dimensions, data]) => {
        if (!coordinates || !data.time) {
          return null;
        }
  
        const {height} = this.getSize();
        const bottomPadding = 25;
        const mousePadding = 10;
        
        const dimensionHeight =
          typeof dimensions.height === 'function' ? dimensions.height(data) : dimensions.height;
        
        const dimensionWidth =
          typeof dimensions.width === 'function' ? dimensions.width(data) : dimensions.width;

        const xInPx = coordinates.x - mousePadding;
        const left = xInPx - dimensionWidth < 0 ? xInPx + mousePadding * 2 : xInPx - dimensionWidth;
        
        return {
          top: Math.min(
            Math.max(0, coordinates.y - dimensionHeight - mousePadding),
            height - bottomPadding - dimensionHeight,
          ),
          left,
          height: dimensionHeight,
          width: dimensionWidth,
        };
      }),
    );
    
    this.tooltipPosition$.pipe(takeUntil(this.destroy$)).subscribe((position) => {
      if (!position) {
        return;
      }
      
      this.elementRef.nativeElement.style.setProperty('--tooltip-top', `${position.top}px`);
      this.elementRef.nativeElement.style.setProperty('--tooltip-left', `${position.left}px`);
      this.elementRef.nativeElement.style.setProperty('--tooltip-height', `${position.height}px`);
      this.elementRef.nativeElement.style.setProperty('--tooltip-width', `${position.width}px`);
    });
    
    this.hideLine$ = combineLatest([
      this.dragging$.pipe(distinctUntilChanged()),
      this.endOfStreamOutOfRange$,
      this.httpError$,
      this.noPoints$,
    ]).pipe(
      map(
        ([dragging, outOfRange, httpError, noPoints]) =>
          dragging || outOfRange || !!httpError || noPoints,
      ),
    );
  }