mirror of https://github.com/grafana/grafana.git
				
				
				
			
		
			
				
	
	
		
			154 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
			
		
		
	
	
			154 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
import React, { FC, FormEvent } from 'react';
 | 
						|
import { css, cx } from '@emotion/css';
 | 
						|
import { GrafanaTheme, SelectableValue } from '@grafana/data';
 | 
						|
import { Button, ButtonSelect, Icon, InlineFieldRow, Input, Select, useStyles } from '@grafana/ui';
 | 
						|
import alertDef, { EvalFunction } from '../../alerting/state/alertDef';
 | 
						|
import { ClassicCondition, ReducerType } from '../types';
 | 
						|
 | 
						|
interface Props {
 | 
						|
  condition: ClassicCondition;
 | 
						|
  onChange: (condition: ClassicCondition) => void;
 | 
						|
  onRemoveCondition: (id: number) => void;
 | 
						|
  index: number;
 | 
						|
  refIds: Array<SelectableValue<string>>;
 | 
						|
}
 | 
						|
 | 
						|
const reducerFunctions = alertDef.reducerTypes.map((rt) => ({ label: rt.text, value: rt.value }));
 | 
						|
const evalOperators = alertDef.evalOperators.map((eo) => ({ label: eo.text, value: eo.value }));
 | 
						|
const evalFunctions = alertDef.evalFunctions.map((ef) => ({ label: ef.text, value: ef.value }));
 | 
						|
 | 
						|
export const Condition: FC<Props> = ({ condition, index, onChange, onRemoveCondition, refIds }) => {
 | 
						|
  const styles = useStyles(getStyles);
 | 
						|
 | 
						|
  const onEvalOperatorChange = (evalOperator: SelectableValue<string>) => {
 | 
						|
    onChange({
 | 
						|
      ...condition,
 | 
						|
      operator: { type: evalOperator.value! },
 | 
						|
    });
 | 
						|
  };
 | 
						|
 | 
						|
  const onReducerFunctionChange = (conditionFunction: SelectableValue<string>) => {
 | 
						|
    onChange({
 | 
						|
      ...condition,
 | 
						|
      reducer: { type: conditionFunction.value! as ReducerType, params: [] },
 | 
						|
    });
 | 
						|
  };
 | 
						|
 | 
						|
  const onRefIdChange = (refId: SelectableValue<string>) => {
 | 
						|
    onChange({
 | 
						|
      ...condition,
 | 
						|
      query: { params: [refId.value!] },
 | 
						|
    });
 | 
						|
  };
 | 
						|
 | 
						|
  const onEvalFunctionChange = (evalFunction: SelectableValue<EvalFunction>) => {
 | 
						|
    onChange({
 | 
						|
      ...condition,
 | 
						|
      evaluator: { params: [], type: evalFunction.value! },
 | 
						|
    });
 | 
						|
  };
 | 
						|
 | 
						|
  const onEvaluateValueChange = (event: FormEvent<HTMLInputElement>, index: number) => {
 | 
						|
    const newValue = parseFloat(event.currentTarget.value);
 | 
						|
    const newParams = [...condition.evaluator.params];
 | 
						|
    newParams[index] = newValue;
 | 
						|
 | 
						|
    onChange({
 | 
						|
      ...condition,
 | 
						|
      evaluator: { ...condition.evaluator, params: newParams },
 | 
						|
    });
 | 
						|
  };
 | 
						|
 | 
						|
  const buttonWidth = css`
 | 
						|
    width: 60px;
 | 
						|
  `;
 | 
						|
 | 
						|
  const isRange =
 | 
						|
    condition.evaluator.type === EvalFunction.IsWithinRange || condition.evaluator.type === EvalFunction.IsOutsideRange;
 | 
						|
 | 
						|
  return (
 | 
						|
    <InlineFieldRow>
 | 
						|
      {index === 0 ? (
 | 
						|
        <div className={cx(styles.button, buttonWidth)}>WHEN</div>
 | 
						|
      ) : (
 | 
						|
        <ButtonSelect
 | 
						|
          className={cx(styles.buttonSelectText, buttonWidth)}
 | 
						|
          options={evalOperators}
 | 
						|
          onChange={onEvalOperatorChange}
 | 
						|
          value={evalOperators.find((ea) => ea.value === condition.operator!.type)}
 | 
						|
        />
 | 
						|
      )}
 | 
						|
      <Select
 | 
						|
        options={reducerFunctions}
 | 
						|
        onChange={onReducerFunctionChange}
 | 
						|
        width={20}
 | 
						|
        value={reducerFunctions.find((rf) => rf.value === condition.reducer.type)}
 | 
						|
      />
 | 
						|
      <div className={styles.button}>OF</div>
 | 
						|
      <Select
 | 
						|
        onChange={onRefIdChange}
 | 
						|
        options={refIds}
 | 
						|
        width={15}
 | 
						|
        value={refIds.find((r) => r.value === condition.query.params[0])}
 | 
						|
      />
 | 
						|
      <ButtonSelect
 | 
						|
        className={styles.buttonSelectText}
 | 
						|
        options={evalFunctions}
 | 
						|
        onChange={onEvalFunctionChange}
 | 
						|
        value={evalFunctions.find((ef) => ef.value === condition.evaluator.type)}
 | 
						|
      />
 | 
						|
      {isRange ? (
 | 
						|
        <>
 | 
						|
          <Input
 | 
						|
            type="number"
 | 
						|
            width={10}
 | 
						|
            onChange={(event) => onEvaluateValueChange(event, 0)}
 | 
						|
            value={condition.evaluator.params[0]}
 | 
						|
          />
 | 
						|
          <div className={styles.button}>TO</div>
 | 
						|
          <Input
 | 
						|
            type="number"
 | 
						|
            width={10}
 | 
						|
            onChange={(event) => onEvaluateValueChange(event, 1)}
 | 
						|
            value={condition.evaluator.params[1]}
 | 
						|
          />
 | 
						|
        </>
 | 
						|
      ) : condition.evaluator.type !== EvalFunction.HasNoValue ? (
 | 
						|
        <Input
 | 
						|
          type="number"
 | 
						|
          width={10}
 | 
						|
          onChange={(event) => onEvaluateValueChange(event, 0)}
 | 
						|
          value={condition.evaluator.params[0]}
 | 
						|
        />
 | 
						|
      ) : null}
 | 
						|
 | 
						|
      <Button variant="secondary" onClick={() => onRemoveCondition(index)}>
 | 
						|
        <Icon name="trash-alt" />
 | 
						|
      </Button>
 | 
						|
    </InlineFieldRow>
 | 
						|
  );
 | 
						|
};
 | 
						|
 | 
						|
const getStyles = (theme: GrafanaTheme) => {
 | 
						|
  const buttonStyle = css`
 | 
						|
    color: ${theme.colors.textBlue};
 | 
						|
    font-size: ${theme.typography.size.sm};
 | 
						|
  `;
 | 
						|
  return {
 | 
						|
    buttonSelectText: buttonStyle,
 | 
						|
    button: cx(
 | 
						|
      css`
 | 
						|
        display: flex;
 | 
						|
        align-items: center;
 | 
						|
        border-radius: ${theme.border.radius.sm};
 | 
						|
        font-weight: ${theme.typography.weight.semibold};
 | 
						|
        border: 1px solid ${theme.colors.border1};
 | 
						|
        white-space: nowrap;
 | 
						|
        padding: 0 ${theme.spacing.sm};
 | 
						|
        background-color: ${theme.colors.bodyBg};
 | 
						|
      `,
 | 
						|
      buttonStyle
 | 
						|
    ),
 | 
						|
  };
 | 
						|
};
 |