@grafana/data#formattedValueToString TypeScript Examples

The following examples show how to use @grafana/data#formattedValueToString. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: BigValueLayout.tsx    From grafana-chinese with Apache License 2.0 6 votes vote down vote up
constructor(private props: Props) {
    const { width, height, value, alignmentFactors, theme } = props;

    this.valueColor = getColorFromHexRgbOrName(value.color || 'green', theme.type);
    this.justifyCenter = shouldJustifyCenter(props);
    this.panelPadding = height > 100 ? 12 : 8;
    this.titleToAlignTo = alignmentFactors ? alignmentFactors.title : value.title;
    this.valueToAlignTo = formattedValueToString(alignmentFactors ? alignmentFactors : value);

    this.titleFontSize = 14;
    this.valueFontSize = 14;
    this.chartHeight = 0;
    this.chartWidth = 0;
    this.maxTextWidth = width - this.panelPadding * 2;
    this.maxTextHeight = height - this.panelPadding * 2;
  }
Example #2
Source File: rendering.ts    From grafana-chinese with Apache License 2.0 6 votes vote down vote up
tickValueFormatter(decimals: number, scaledDecimals: any = null) {
    const format = this.panel.yAxis.format;
    return (value: any) => {
      try {
        if (format !== 'none') {
          const v = getValueFormat(format)(value, decimals, scaledDecimals);
          return formattedValueToString(v);
        }
      } catch (err) {
        console.error(err.message || err);
      }
      return value;
    };
  }
Example #3
Source File: graph.ts    From grafana-chinese with Apache License 2.0 6 votes vote down vote up
configureAxisMode(axis: { tickFormatter: (val: any, axis: any) => string }, format: string) {
    axis.tickFormatter = (val, axis) => {
      const formatter = getValueFormat(format);

      if (!formatter) {
        throw new Error(`Unit '${format}' is not supported`);
      }
      return formattedValueToString(formatter(val, axis.tickDecimals, axis.scaledDecimals));
    };
  }
Example #4
Source File: fieldDisplayValuesProxy.ts    From grafana-chinese with Apache License 2.0 6 votes vote down vote up
export function getFieldDisplayValuesProxy(frame: DataFrame, rowIndex: number): Record<string, DisplayValue> {
  return new Proxy({} as Record<string, DisplayValue>, {
    get: (obj: any, key: string) => {
      // 1. Match the name
      let field = frame.fields.find(f => key === f.name);
      if (!field) {
        // 2. Match the array index
        const k = toNumber(key);
        field = frame.fields[k];
      }
      if (!field) {
        // 3. Match the title
        field = frame.fields.find(f => key === f.config.title);
      }
      if (!field) {
        return undefined;
      }
      if (!field.display) {
        // Lazy load the display processor
        field.display = getDisplayProcessor({
          field,
          theme: config.theme,
        });
      }
      const raw = field.values.get(rowIndex);
      const disp = field.display(raw);
      disp.toString = () => formattedValueToString(disp);
      return disp;
    },
  });
}
Example #5
Source File: DefaultCell.tsx    From grafana-chinese with Apache License 2.0 6 votes vote down vote up
DefaultCell: FC<TableCellProps> = props => {
  const { field, cell, tableStyles } = props;

  if (!field.display) {
    return null;
  }

  const displayValue = field.display(cell.value);
  return <div className={tableStyles.tableCell}>{formattedValueToString(displayValue)}</div>;
}
Example #6
Source File: BackgroundColorCell.tsx    From grafana-chinese with Apache License 2.0 6 votes vote down vote up
BackgroundColoredCell: FC<TableCellProps> = props => {
  const { cell, tableStyles, field } = props;

  if (!field.display) {
    return null;
  }

  const themeFactor = tableStyles.theme.isDark ? 1 : -0.7;
  const displayValue = field.display(cell.value);

  const bgColor2 = tinycolor(displayValue.color)
    .darken(10 * themeFactor)
    .spin(5)
    .toRgbString();

  const styles: CSSProperties = {
    background: `linear-gradient(120deg, ${bgColor2}, ${displayValue.color})`,
    borderRadius: '0px',
    color: 'white',
    height: tableStyles.cellHeight,
    padding: tableStyles.cellPadding,
  };

  return <div style={styles}>{formattedValueToString(displayValue)}</div>;
}
Example #7
Source File: LegendStatsList.tsx    From grafana-chinese with Apache License 2.0 6 votes vote down vote up
LegendItemStat: React.FunctionComponent<{ stat: DisplayValue }> = ({ stat }) => {
  return (
    <div
      className={css`
        margin-left: 6px;
      `}
    >
      {stat.title && `${capitalize(stat.title)}:`} {formattedValueToString(stat)}
    </div>
  );
}
Example #8
Source File: utils.ts    From grafana-chinese with Apache License 2.0 6 votes vote down vote up
getMultiSeriesGraphHoverInfo = (
  // x and y axis dimensions order is aligned
  yAxisDimensions: Field[],
  xAxisDimensions: Field[],
  /** Well, time basically */
  xAxisPosition: number
): {
  results: MultiSeriesHoverInfo[];
  time?: GraphSeriesValue;
} => {
  let i, field, hoverIndex, hoverDistance, pointTime;

  const results: MultiSeriesHoverInfo[] = [];

  let minDistance, minTime;

  for (i = 0; i < yAxisDimensions.length; i++) {
    field = yAxisDimensions[i];
    const time = xAxisDimensions[i];
    hoverIndex = findHoverIndexFromData(time, xAxisPosition);
    hoverDistance = xAxisPosition - time.values.get(hoverIndex);
    pointTime = time.values.get(hoverIndex);
    // Take the closest point before the cursor, or if it does not exist, the closest after
    if (
      minDistance === undefined ||
      (hoverDistance >= 0 && (hoverDistance < minDistance || minDistance < 0)) ||
      (hoverDistance < 0 && hoverDistance > minDistance)
    ) {
      minDistance = hoverDistance;
      minTime = time.display ? formattedValueToString(time.display(pointTime)) : pointTime;
    }

    const display = field.display ?? getDisplayProcessor({ field });
    const disp = display(field.values.get(hoverIndex));

    results.push({
      value: formattedValueToString(disp),
      datapointIndex: hoverIndex,
      seriesIndex: i,
      color: disp.color,
      label: field.name,
      time: time.display ? formattedValueToString(time.display(pointTime)) : pointTime,
    });
  }

  return {
    results,
    time: minTime,
  };
}
Example #9
Source File: SingleModeGraphTooltip.tsx    From grafana-chinese with Apache License 2.0 6 votes vote down vote up
SingleModeGraphTooltip: React.FC<GraphTooltipContentProps> = ({ dimensions, activeDimensions }) => {
  // not hovering over a point, skip rendering
  if (
    activeDimensions.yAxis === null ||
    activeDimensions.yAxis[1] === undefined ||
    activeDimensions.xAxis === null ||
    activeDimensions.xAxis[1] === undefined
  ) {
    return null;
  }
  const time = getValueFromDimension(dimensions.xAxis, activeDimensions.xAxis[0], activeDimensions.xAxis[1]);
  const timeField = getColumnFromDimension(dimensions.xAxis, activeDimensions.xAxis[0]);
  const processedTime = timeField.display ? formattedValueToString(timeField.display(time)) : time;

  const valueField = getColumnFromDimension(dimensions.yAxis, activeDimensions.yAxis[0]);
  const value = getValueFromDimension(dimensions.yAxis, activeDimensions.yAxis[0], activeDimensions.yAxis[1]);
  const display = valueField.display ?? getDisplayProcessor({ field: valueField });
  const disp = display(value);

  return (
    <SeriesTable
      series={[
        {
          color: disp.color,
          label: valueField.name,
          value: formattedValueToString(disp),
        },
      ]}
      timestamp={processedTime}
    />
  );
}
Example #10
Source File: PieChart.tsx    From grafana-chinese with Apache License 2.0 5 votes vote down vote up
draw() {
    const { values, pieType, strokeWidth } = this.props;

    if (values.length === 0) {
      return;
    }

    const data = values.map(datapoint => datapoint.numeric);
    const names = values.map(datapoint => formattedValueToString(datapoint));
    const colors = values.map((p, idx) => {
      if (p.color) {
        return p.color;
      }
      return grafana_colors[idx % grafana_colors.length];
    });

    const total = sum(data) || 1;
    const percents = data.map((item: number) => (item / total) * 100);

    const width = this.containerElement.offsetWidth;
    const height = this.containerElement.offsetHeight;
    const radius = Math.min(width, height) / 2;

    const outerRadius = radius - radius / 10;
    const innerRadius = pieType === PieChartType.PIE ? 0 : radius - radius / 3;

    const svg = select(this.svgElement)
      .html('')
      .attr('width', width)
      .attr('height', height)
      .append('g')
      .attr('transform', `translate(${width / 2},${height / 2})`);

    const pieChart = pie();

    const customArc = arc()
      .outerRadius(outerRadius)
      .innerRadius(innerRadius)
      .padAngle(0);

    svg
      .selectAll('path')
      .data(pieChart(data))
      .enter()
      .append('path')
      .attr('d', customArc as any)
      .attr('fill', (d: any, idx: number) => colors[idx])
      .style('fill-opacity', 0.15)
      .style('stroke', (d: any, idx: number) => colors[idx])
      .style('stroke-width', `${strokeWidth}px`)
      .on('mouseover', (d: any, idx: any) => {
        select(this.tooltipElement).style('opacity', 1);
        select(this.tooltipValueElement).text(`${names[idx]} (${percents[idx].toFixed(2)}%)`);
      })
      .on('mousemove', () => {
        select(this.tooltipElement)
          .style('top', `${event.pageY - height / 2}px`)
          .style('left', `${event.pageX}px`);
      })
      .on('mouseout', () => {
        select(this.tooltipElement).style('opacity', 0);
      });
  }
Example #11
Source File: GraphLegendItem.tsx    From grafana-chinese with Apache License 2.0 5 votes vote down vote up
GraphLegendTableRow: React.FunctionComponent<GraphLegendItemProps> = ({
  item,
  onSeriesColorChange,
  onToggleAxis,
  onLabelClick,
  className,
}) => {
  const theme = useContext(ThemeContext);
  const styles = getStyles(theme);
  return (
    <tr className={cx(styles.row, className)}>
      <td>
        <span className={styles.itemWrapper}>
          <LegendSeriesIcon
            disabled={!!onSeriesColorChange}
            color={item.color}
            onColorChange={color => {
              if (onSeriesColorChange) {
                onSeriesColorChange(item.label, color);
              }
            }}
            onToggleAxis={onToggleAxis}
            yAxis={item.yAxis}
          />
          <div
            onClick={event => {
              if (onLabelClick) {
                onLabelClick(item, event);
              }
            }}
            className={styles.label}
          >
            {item.label} {item.yAxis === 2 && <span className={styles.yAxisLabel}>(right y-axis)</span>}
          </div>
        </span>
      </td>
      {item.displayValues &&
        item.displayValues.map((stat, index) => {
          return (
            <td className={styles.value} key={`${stat.title}-${index}`}>
              {formattedValueToString(stat)}
            </td>
          );
        })}
    </tr>
  );
}
Example #12
Source File: time_series2.ts    From grafana-chinese with Apache License 2.0 5 votes vote down vote up
formatValue(value: number) {
    if (!_.isFinite(value)) {
      value = null; // Prevent NaN formatting
    }
    return formattedValueToString(this.valueFormater(value, this.decimals, this.scaledDecimals));
  }
Example #13
Source File: GraphContextMenu.tsx    From grafana-chinese with Apache License 2.0 5 votes vote down vote up
GraphContextMenu: React.FC<GraphContextMenuProps> = ({
  getContextMenuSource,
  formatSourceDate,
  items,
  dimensions,
  contextDimensions,
  ...otherProps
}) => {
  const theme = useContext(ThemeContext);
  const source = getContextMenuSource();

  //  Do not render items that do not have label specified
  const itemsToRender = items
    ? items.map(group => ({
        ...group,
        items: group.items.filter(item => item.label),
      }))
    : [];

  const renderHeader = () => {
    if (!source) {
      return null;
    }

    // If dimensions supplied, we can calculate and display value
    let value;
    if (dimensions?.yAxis && contextDimensions?.yAxis?.[1]) {
      const valueFromDimensions = getValueFromDimension(
        dimensions.yAxis,
        contextDimensions.yAxis[0],
        contextDimensions.yAxis[1]
      );
      const display = source.series.valueField.display ?? getDisplayProcessor({ field: source.series.valueField });
      value = display(valueFromDimensions);
    }

    const timeFormat = source.series.hasMsResolution ? MS_DATE_TIME_FORMAT : DEFAULT_DATE_TIME_FORMAT;
    return (
      <div
        className={css`
          padding: ${theme.spacing.xs} ${theme.spacing.sm};
          font-size: ${theme.typography.size.sm};
          z-index: ${theme.zIndex.tooltip};
        `}
      >
        <strong>{formatSourceDate(source.datapoint[0], timeFormat)}</strong>
        <div>
          <SeriesIcon color={source.series.color} />
          <span
            className={css`
              white-space: nowrap;
              padding-left: ${theme.spacing.xs};
            `}
          >
            {source.series.alias || source.series.label}
          </span>
          {value && (
            <span
              className={css`
                white-space: nowrap;
                padding-left: ${theme.spacing.md};
              `}
            >
              {formattedValueToString(value)}
            </span>
          )}
        </div>
      </div>
    );
  };

  return <ContextMenu {...otherProps} items={itemsToRender} renderHeader={renderHeader} />;
}
Example #14
Source File: linkSuppliers.ts    From grafana-chinese with Apache License 2.0 5 votes vote down vote up
getFieldLinksSupplier = (value: FieldDisplay): LinkModelSupplier<FieldDisplay> | undefined => {
  const links = value.field.links;
  if (!links || links.length === 0) {
    return undefined;
  }
  return {
    getLinks: (_scopedVars?: any) => {
      const scopedVars: DataLinkScopedVars = {};

      if (value.view) {
        const { dataFrame } = value.view;

        scopedVars['__series'] = {
          value: {
            name: dataFrame.name,
            refId: dataFrame.refId,
          },
          text: 'Series',
        };

        const field = value.colIndex !== undefined ? dataFrame.fields[value.colIndex] : undefined;
        if (field) {
          console.log('Full Field Info:', field);
          scopedVars['__field'] = {
            value: {
              name: field.name,
              labels: field.labels,
            },
            text: 'Field',
          };
        }

        if (!isNaN(value.rowIndex)) {
          const { timeField } = getTimeField(dataFrame);
          scopedVars['__value'] = {
            value: {
              raw: field.values.get(value.rowIndex),
              numeric: value.display.numeric,
              text: formattedValueToString(value.display),
              time: timeField ? timeField.values.get(value.rowIndex) : undefined,
            },
            text: 'Value',
          };

          // Expose other values on the row
          if (value.view) {
            scopedVars['__data'] = {
              value: {
                name: dataFrame.name,
                refId: dataFrame.refId,
                fields: getFieldDisplayValuesProxy(dataFrame, value.rowIndex!),
              },
              text: 'Data',
            };
          }
        } else {
          // calculation
          scopedVars['__value'] = {
            value: {
              raw: value.display.numeric,
              numeric: value.display.numeric,
              text: formattedValueToString(value.display),
              calc: value.name,
            },
            text: 'Value',
          };
        }
      } else {
        console.log('VALUE', value);
      }

      return links.map(link => {
        return getLinkSrv().getDataLinkUIModel(link, scopedVars, value);
      });
    },
  };
}
Example #15
Source File: heatmap_tooltip.ts    From grafana-chinese with Apache License 2.0 5 votes vote down vote up
countValueFormatter(decimals: number, scaledDecimals: any = null) {
    const fmt = getValueFormat('short');
    return (value: number) => {
      return formattedValueToString(fmt(value, decimals, scaledDecimals));
    };
  }
Example #16
Source File: BarGauge.tsx    From grafana-chinese with Apache License 2.0 5 votes vote down vote up
function getValueStyles(
  value: FormattedValue,
  color: string,
  width: number,
  height: number,
  orientation: VizOrientation
): CSSProperties {
  const styles: CSSProperties = {
    color: color,
    height: `${height}px`,
    width: `${width}px`,
    display: 'flex',
    alignItems: 'center',
    lineHeight: VALUE_LINE_HEIGHT,
  };

  // how many pixels in wide can the text be?
  let textWidth = width;
  const formattedValueString = formattedValueToString(value);

  if (isVertical(orientation)) {
    styles.fontSize = calculateFontSize(formattedValueString, textWidth, height, VALUE_LINE_HEIGHT);
    styles.justifyContent = `center`;
  } else {
    styles.fontSize = calculateFontSize(
      formattedValueString,
      textWidth - VALUE_LEFT_PADDING * 2,
      height,
      VALUE_LINE_HEIGHT
    );
    styles.justifyContent = `flex-end`;
    styles.paddingLeft = `${VALUE_LEFT_PADDING}px`;
    styles.paddingRight = `${VALUE_LEFT_PADDING}px`;
    // Need to remove the left padding from the text width constraints
    textWidth -= VALUE_LEFT_PADDING;

    // adjust width of title box
    styles.width = measureText(formattedValueString, styles.fontSize).width + VALUE_LEFT_PADDING * 2;
  }

  return styles;
}
Example #17
Source File: Graph2.tsx    From loudml-grafana-app with MIT License 5 votes vote down vote up
tickFormatter(val, axis) {
    const formatter = getValueFormat('short');

    if (!formatter) {
      throw new Error(`Unit '${format}' is not supported`);
    }
    return formattedValueToString(formatter(val, axis.tickDecimals, axis.scaledDecimals));
  }
Example #18
Source File: Gauge.tsx    From grafana-chinese with Apache License 2.0 4 votes vote down vote up
draw() {
    const { field, showThresholdLabels, showThresholdMarkers, width, height, theme, value } = this.props;

    const autoProps = calculateGaugeAutoProps(width, height, value.title);
    const dimension = Math.min(width, autoProps.gaugeHeight);

    const backgroundColor = selectThemeVariant(
      {
        dark: theme.colors.dark8,
        light: theme.colors.gray6,
      },
      theme.type
    );

    const gaugeWidthReduceRatio = showThresholdLabels ? 1.5 : 1;
    const gaugeWidth = Math.min(dimension / 5.5, 40) / gaugeWidthReduceRatio;
    const thresholdMarkersWidth = gaugeWidth / 5;
    const text = formattedValueToString(value);
    const fontSize = Math.min(dimension / 4, 100) * (text !== null ? this.getFontScale(text.length) : 1);

    const thresholdLabelFontSize = fontSize / 2.5;

    let min = field.min!;
    let max = field.max!;
    let numeric = value.numeric;
    if (field.thresholds?.mode === ThresholdsMode.Percentage) {
      min = 0;
      max = 100;
      if (value.percent === undefined) {
        numeric = ((numeric - min) / (max - min)) * 100;
      } else {
        numeric = value.percent! * 100;
      }
    }

    const options: any = {
      series: {
        gauges: {
          gauge: {
            min,
            max,
            background: { color: backgroundColor },
            border: { color: null },
            shadow: { show: false },
            width: gaugeWidth,
          },
          frame: { show: false },
          label: { show: false },
          layout: { margin: 0, thresholdWidth: 0, vMargin: 0 },
          cell: { border: { width: 0 } },
          threshold: {
            values: this.getFormattedThresholds(),
            label: {
              show: showThresholdLabels,
              margin: thresholdMarkersWidth + 1,
              font: { size: thresholdLabelFontSize },
            },
            show: showThresholdMarkers,
            width: thresholdMarkersWidth,
          },
          value: {
            color: value.color,
            formatter: () => {
              return text;
            },
            font: { size: fontSize, family: theme.typography.fontFamily.sansSerif },
          },
          show: true,
        },
      },
    };

    const plotSeries = {
      data: [[0, numeric]],
      label: value.title,
    };

    try {
      $.plot(this.canvasElement, [plotSeries], options);
    } catch (err) {
      console.log('Gauge rendering error', err, options, value);
    }
  }
Example #19
Source File: module.ts    From grafana-chinese with Apache License 2.0 4 votes vote down vote up
link(scope: any, elem: JQuery, attrs: any, ctrl: any) {
    const $location = this.$location;
    const linkSrv = this.linkSrv;
    const $timeout = this.$timeout;
    const $sanitize = this.$sanitize;
    const panel = ctrl.panel;
    const templateSrv = this.templateSrv;
    let linkInfo: LinkModel<any> | null = null;
    elem = elem.find('.singlestat-panel');

    function getPanelContainer() {
      return elem.closest('.panel-container');
    }

    function applyColoringThresholds(valueString: string) {
      const data = ctrl.data;
      const color = getColorForValue(data, data.value);
      if (color) {
        return '<span style="color:' + color + '">' + valueString + '</span>';
      }

      return valueString;
    }

    function getSpan(className: string, fontSizePercent: string, applyColoring: any, value: string) {
      value = $sanitize(templateSrv.replace(value, ctrl.data.scopedVars));
      value = applyColoring ? applyColoringThresholds(value) : value;
      const pixelSize = (parseInt(fontSizePercent, 10) / 100) * BASE_FONT_SIZE;
      return '<span class="' + className + '" style="font-size:' + pixelSize + 'px">' + value + '</span>';
    }

    function getBigValueHtml() {
      const data: ShowData = ctrl.data;
      let body = '<div class="singlestat-panel-value-container">';

      if (panel.prefix) {
        body += getSpan('singlestat-panel-prefix', panel.prefixFontSize, panel.colorPrefix, panel.prefix);
      }

      body += getSpan(
        'singlestat-panel-value',
        panel.valueFontSize,
        panel.colorValue,
        formattedValueToString(data.display)
      );

      if (panel.postfix) {
        body += getSpan('singlestat-panel-postfix', panel.postfixFontSize, panel.colorPostfix, panel.postfix);
      }

      body += '</div>';

      return body;
    }

    function getValueText() {
      const data: ShowData = ctrl.data;
      let result = panel.prefix ? templateSrv.replace(panel.prefix, data.scopedVars) : '';
      result += formattedValueToString(data.display);
      result += panel.postfix ? templateSrv.replace(panel.postfix, data.scopedVars) : '';

      return result;
    }

    function addGauge() {
      const data: ShowData = ctrl.data;
      const width = elem.width();
      const height = elem.height();
      // Allow to use a bit more space for wide gauges
      const dimension = Math.min(width, height * 1.3);

      ctrl.invalidGaugeRange = false;
      if (panel.gauge.minValue > panel.gauge.maxValue) {
        ctrl.invalidGaugeRange = true;
        return;
      }

      const plotCanvas = $('<div></div>');
      const plotCss = {
        top: '5px',
        margin: 'auto',
        position: 'relative',
        height: height * 0.9 + 'px',
        width: dimension + 'px',
      };

      plotCanvas.css(plotCss);

      const thresholds = [];

      for (let i = 0; i < data.thresholds.length; i++) {
        thresholds.push({
          value: data.thresholds[i],
          color: data.colorMap[i],
        });
      }
      thresholds.push({
        value: panel.gauge.maxValue,
        color: data.colorMap[data.colorMap.length - 1],
      });

      const bgColor = config.bootData.user.lightTheme ? 'rgb(230,230,230)' : 'rgb(38,38,38)';

      const fontScale = parseInt(panel.valueFontSize, 10) / 100;
      const fontSize = Math.min(dimension / 5, 100) * fontScale;
      // Reduce gauge width if threshold labels enabled
      const gaugeWidthReduceRatio = panel.gauge.thresholdLabels ? 1.5 : 1;
      const gaugeWidth = Math.min(dimension / 6, 60) / gaugeWidthReduceRatio;
      const thresholdMarkersWidth = gaugeWidth / 5;
      const thresholdLabelFontSize = fontSize / 2.5;

      const options: any = {
        series: {
          gauges: {
            gauge: {
              min: panel.gauge.minValue,
              max: panel.gauge.maxValue,
              background: { color: bgColor },
              border: { color: null },
              shadow: { show: false },
              width: gaugeWidth,
            },
            frame: { show: false },
            label: { show: false },
            layout: { margin: 0, thresholdWidth: 0 },
            cell: { border: { width: 0 } },
            threshold: {
              values: thresholds,
              label: {
                show: panel.gauge.thresholdLabels,
                margin: thresholdMarkersWidth + 1,
                font: { size: thresholdLabelFontSize },
              },
              show: panel.gauge.thresholdMarkers,
              width: thresholdMarkersWidth,
            },
            value: {
              color: panel.colorValue ? getColorForValue(data, data.display.numeric) : null,
              formatter: () => {
                return getValueText();
              },
              font: {
                size: fontSize,
                family: config.theme.typography.fontFamily.sansSerif,
              },
            },
            show: true,
          },
        },
      };

      elem.append(plotCanvas);

      const plotSeries = {
        data: [[0, data.value]],
      };

      $.plot(plotCanvas, [plotSeries], options);
    }

    function addSparkline() {
      const data: ShowData = ctrl.data;
      const width = elem.width();
      if (width < 30) {
        // element has not gotten it's width yet
        // delay sparkline render
        setTimeout(addSparkline, 30);
        return;
      }
      if (!data.sparkline || !data.sparkline.length) {
        // no sparkline data
        return;
      }

      const height = ctrl.height;
      const plotCanvas = $('<div></div>');
      const plotCss: any = {};
      plotCss.position = 'absolute';
      plotCss.bottom = '0px';

      if (panel.sparkline.full) {
        plotCss.left = '0px';
        plotCss.width = width + 'px';
        const dynamicHeightMargin = height <= 100 ? 5 : Math.round(height / 100) * 15 + 5;
        plotCss.height = height - dynamicHeightMargin + 'px';
      } else {
        plotCss.left = '0px';
        plotCss.width = width + 'px';
        plotCss.height = Math.floor(height * 0.25) + 'px';
      }

      plotCanvas.css(plotCss);

      const options = {
        legend: { show: false },
        series: {
          lines: {
            show: true,
            fill: 1,
            lineWidth: 1,
            fillColor: getColorFromHexRgbOrName(panel.sparkline.fillColor, config.theme.type),
            zero: false,
          },
        },
        yaxis: {
          show: false,
          min: panel.sparkline.ymin,
          max: panel.sparkline.ymax,
        },
        xaxis: {
          show: false,
          mode: 'time',
          min: ctrl.range.from.valueOf(),
          max: ctrl.range.to.valueOf(),
        },
        grid: { hoverable: false, show: false },
      };

      elem.append(plotCanvas);

      const plotSeries = {
        data: data.sparkline,
        color: getColorFromHexRgbOrName(panel.sparkline.lineColor, config.theme.type),
      };

      $.plot(plotCanvas, [plotSeries], options);
    }

    function render() {
      if (!ctrl.data) {
        return;
      }
      const { data, panel } = ctrl;

      // get thresholds
      data.thresholds = panel.thresholds
        ? panel.thresholds.split(',').map((strVale: string) => {
            return Number(strVale.trim());
          })
        : [];

      // Map panel colors to hex or rgb/a values
      if (panel.colors) {
        data.colorMap = panel.colors.map((color: string) => getColorFromHexRgbOrName(color, config.theme.type));
      }

      const body = panel.gauge.show ? '' : getBigValueHtml();

      if (panel.colorBackground) {
        const color = getColorForValue(data, data.display.numeric);
        if (color) {
          getPanelContainer().css('background-color', color);
          if (scope.fullscreen) {
            elem.css('background-color', color);
          } else {
            elem.css('background-color', '');
          }
        } else {
          getPanelContainer().css('background-color', '');
          elem.css('background-color', '');
        }
      } else {
        getPanelContainer().css('background-color', '');
        elem.css('background-color', '');
      }

      elem.html(body);

      if (panel.sparkline.show) {
        addSparkline();
      }

      if (panel.gauge.show) {
        addGauge();
      }

      elem.toggleClass('pointer', panel.links.length > 0);

      if (panel.links.length > 0) {
        linkInfo = linkSrv.getDataLinkUIModel(panel.links[0], data.scopedVars, {});
      } else {
        linkInfo = null;
      }
    }

    function hookupDrilldownLinkTooltip() {
      // drilldown link tooltip
      const drilldownTooltip = $('<div id="tooltip" class="">hello</div>"');

      elem.mouseleave(() => {
        if (panel.links.length === 0) {
          return;
        }
        $timeout(() => {
          drilldownTooltip.detach();
        });
      });

      elem.click(evt => {
        if (!linkInfo) {
          return;
        }
        // ignore title clicks in title
        if ($(evt).parents('.panel-header').length > 0) {
          return;
        }

        if (linkInfo.target === '_blank') {
          window.open(linkInfo.href, '_blank');
          return;
        }

        if (linkInfo.href.indexOf('http') === 0) {
          window.location.href = linkInfo.href;
        } else {
          $timeout(() => {
            $location.url(locationUtil.stripBaseFromUrl(linkInfo.href));
          });
        }

        drilldownTooltip.detach();
      });

      elem.mousemove(e => {
        if (!linkInfo) {
          return;
        }

        drilldownTooltip.text('click to go to: ' + linkInfo.title);
        drilldownTooltip.place_tt(e.pageX, e.pageY - 50);
      });
    }

    hookupDrilldownLinkTooltip();

    this.events.on(PanelEvents.render, () => {
      render();
      ctrl.renderingCompleted();
    });
  }
Example #20
Source File: renderer.ts    From grafana-chinese with Apache License 2.0 4 votes vote down vote up
createColumnFormatter(column: ColumnRender) {
    if (!column.style) {
      return this.defaultCellFormatter;
    }

    if (column.style.type === 'hidden') {
      return (v: any): undefined => undefined;
    }

    if (column.style.type === 'date') {
      return (v: any) => {
        if (v === undefined || v === null) {
          return '-';
        }

        if (_.isArray(v)) {
          v = v[0];
        }

        // if is an epoch (numeric string and len > 12)
        if (_.isString(v) && !isNaN(v as any) && v.length > 12) {
          v = parseInt(v, 10);
        }

        let date = dateTime(v);

        if (this.isUtc) {
          date = date.utc();
        }

        return date.format(column.style.dateFormat);
      };
    }

    if (column.style.type === 'string') {
      return (v: any): any => {
        if (_.isArray(v)) {
          v = v.join(', ');
        }

        const mappingType = column.style.mappingType || 0;

        if (mappingType === 1 && column.style.valueMaps) {
          for (let i = 0; i < column.style.valueMaps.length; i++) {
            const map = column.style.valueMaps[i];

            if (v === null) {
              if (map.value === 'null') {
                return map.text;
              }
              continue;
            }

            // Allow both numeric and string values to be mapped
            if ((!_.isString(v) && Number(map.value) === Number(v)) || map.value === v) {
              this.setColorState(v, column.style);
              return this.defaultCellFormatter(map.text, column.style);
            }
          }
        }

        if (mappingType === 2 && column.style.rangeMaps) {
          for (let i = 0; i < column.style.rangeMaps.length; i++) {
            const map = column.style.rangeMaps[i];

            if (v === null) {
              if (map.from === 'null' && map.to === 'null') {
                return map.text;
              }
              continue;
            }

            if (Number(map.from) <= Number(v) && Number(map.to) >= Number(v)) {
              this.setColorState(v, column.style);
              return this.defaultCellFormatter(map.text, column.style);
            }
          }
        }

        if (v === null || v === void 0) {
          return '-';
        }

        this.setColorState(v, column.style);
        return this.defaultCellFormatter(v, column.style);
      };
    }

    if (column.style.type === 'number') {
      const valueFormatter = getValueFormat(column.unit || column.style.unit);

      return (v: any): any => {
        if (v === null || v === void 0) {
          return '-';
        }

        if (isNaN(v) || _.isArray(v)) {
          return this.defaultCellFormatter(v, column.style);
        }

        this.setColorState(v, column.style);
        return formattedValueToString(valueFormatter(v, column.style.decimals, null));
      };
    }

    return (value: any) => {
      return this.defaultCellFormatter(value, column.style);
    };
  }