prometheus

Форк
0
/
GraphControls.tsx 
198 строк · 6.4 Кб
1
import React, { Component } from 'react';
2
import { Button, ButtonGroup, Form, Input, InputGroup, InputGroupAddon } from 'reactstrap';
3

4
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
5
import { faChartArea, faChartLine, faMinus, faPlus, faBarChart } from '@fortawesome/free-solid-svg-icons';
6
import TimeInput from './TimeInput';
7
import { formatDuration, parseDuration } from '../../utils';
8
import { GraphDisplayMode } from './Panel';
9

10
interface GraphControlsProps {
11
  range: number;
12
  endTime: number | null;
13
  useLocalTime: boolean;
14
  resolution: number | null;
15
  displayMode: GraphDisplayMode;
16
  isHeatmapData: boolean;
17
  showExemplars: boolean;
18
  onChangeRange: (range: number) => void;
19
  onChangeEndTime: (endTime: number | null) => void;
20
  onChangeResolution: (resolution: number | null) => void;
21
  onChangeShowExemplars: (show: boolean) => void;
22
  onChangeDisplayMode: (mode: GraphDisplayMode) => void;
23
}
24

25
class GraphControls extends Component<GraphControlsProps> {
26
  private rangeRef = React.createRef<HTMLInputElement>();
27
  private resolutionRef = React.createRef<HTMLInputElement>();
28

29
  rangeSteps = [
30
    1,
31
    10,
32
    60,
33
    5 * 60,
34
    15 * 60,
35
    30 * 60,
36
    60 * 60,
37
    2 * 60 * 60,
38
    6 * 60 * 60,
39
    12 * 60 * 60,
40
    24 * 60 * 60,
41
    48 * 60 * 60,
42
    7 * 24 * 60 * 60,
43
    14 * 24 * 60 * 60,
44
    28 * 24 * 60 * 60,
45
    56 * 24 * 60 * 60,
46
    112 * 24 * 60 * 60,
47
    182 * 24 * 60 * 60,
48
    365 * 24 * 60 * 60,
49
    730 * 24 * 60 * 60,
50
  ].map((s) => s * 1000);
51

52
  onChangeRangeInput = (rangeText: string): void => {
53
    const range = parseDuration(rangeText);
54
    if (range === null) {
55
      this.changeRangeInput(this.props.range);
56
    } else {
57
      this.props.onChangeRange(range);
58
    }
59
  };
60

61
  changeRangeInput = (range: number): void => {
62
    if (this.rangeRef.current !== null) {
63
      this.rangeRef.current.value = formatDuration(range);
64
    }
65
  };
66

67
  increaseRange = (): void => {
68
    for (const range of this.rangeSteps) {
69
      if (this.props.range < range) {
70
        this.changeRangeInput(range);
71
        this.props.onChangeRange(range);
72
        return;
73
      }
74
    }
75
  };
76

77
  decreaseRange = (): void => {
78
    for (const range of this.rangeSteps.slice().reverse()) {
79
      if (this.props.range > range) {
80
        this.changeRangeInput(range);
81
        this.props.onChangeRange(range);
82
        return;
83
      }
84
    }
85
  };
86

87
  changeResolutionInput = (resolution: number | null): void => {
88
    if (this.resolutionRef.current !== null) {
89
      this.resolutionRef.current.value = resolution !== null ? resolution.toString() : '';
90
    }
91
  };
92

93
  componentDidUpdate(prevProps: GraphControlsProps): void {
94
    if (prevProps.range !== this.props.range) {
95
      this.changeRangeInput(this.props.range);
96
    }
97
    if (prevProps.resolution !== this.props.resolution) {
98
      this.changeResolutionInput(this.props.resolution);
99
    }
100
  }
101

102
  render(): JSX.Element {
103
    return (
104
      <Form inline className="graph-controls" onSubmit={(e) => e.preventDefault()}>
105
        <InputGroup className="range-input" size="sm">
106
          <InputGroupAddon addonType="prepend">
107
            <Button title="Decrease range" onClick={this.decreaseRange}>
108
              <FontAwesomeIcon icon={faMinus} fixedWidth />
109
            </Button>
110
          </InputGroupAddon>
111

112
          <Input
113
            defaultValue={formatDuration(this.props.range)}
114
            innerRef={this.rangeRef}
115
            onBlur={() => {
116
              if (this.rangeRef.current) {
117
                this.onChangeRangeInput(this.rangeRef.current.value);
118
              }
119
            }}
120
            onKeyDown={(e: React.KeyboardEvent<HTMLInputElement>) =>
121
              e.key === 'Enter' && this.rangeRef.current && this.onChangeRangeInput(this.rangeRef.current.value)
122
            }
123
          />
124

125
          <InputGroupAddon addonType="append">
126
            <Button title="Increase range" onClick={this.increaseRange}>
127
              <FontAwesomeIcon icon={faPlus} fixedWidth />
128
            </Button>
129
          </InputGroupAddon>
130
        </InputGroup>
131

132
        <TimeInput
133
          time={this.props.endTime}
134
          useLocalTime={this.props.useLocalTime}
135
          range={this.props.range}
136
          placeholder="End time"
137
          onChangeTime={this.props.onChangeEndTime}
138
        />
139

140
        <Input
141
          placeholder="Res. (s)"
142
          className="resolution-input"
143
          defaultValue={this.props.resolution !== null ? this.props.resolution.toString() : ''}
144
          innerRef={this.resolutionRef}
145
          onBlur={() => {
146
            if (this.resolutionRef.current) {
147
              const res = parseInt(this.resolutionRef.current.value);
148
              this.props.onChangeResolution(res ? res : null);
149
            }
150
          }}
151
          bsSize="sm"
152
        />
153

154
        <ButtonGroup className="stacked-input" size="sm">
155
          <Button
156
            title="Show unstacked line graph"
157
            onClick={() => this.props.onChangeDisplayMode(GraphDisplayMode.Lines)}
158
            active={this.props.displayMode === GraphDisplayMode.Lines}
159
          >
160
            <FontAwesomeIcon icon={faChartLine} fixedWidth />
161
          </Button>
162
          <Button
163
            title="Show stacked graph"
164
            onClick={() => this.props.onChangeDisplayMode(GraphDisplayMode.Stacked)}
165
            active={this.props.displayMode === GraphDisplayMode.Stacked}
166
          >
167
            <FontAwesomeIcon icon={faChartArea} fixedWidth />
168
          </Button>
169
          {/* TODO: Consider replacing this button with a select dropdown in the future,
170
               to allow users to choose from multiple histogram series if available. */}
171
          {this.props.isHeatmapData && (
172
            <Button
173
              title="Show heatmap graph"
174
              onClick={() => this.props.onChangeDisplayMode(GraphDisplayMode.Heatmap)}
175
              active={this.props.displayMode === GraphDisplayMode.Heatmap}
176
            >
177
              <FontAwesomeIcon icon={faBarChart} fixedWidth />
178
            </Button>
179
          )}
180
        </ButtonGroup>
181

182
        <ButtonGroup className="show-exemplars" size="sm">
183
          {this.props.showExemplars ? (
184
            <Button title="Hide exemplars" onClick={() => this.props.onChangeShowExemplars(false)} active={true}>
185
              Hide Exemplars
186
            </Button>
187
          ) : (
188
            <Button title="Show exemplars" onClick={() => this.props.onChangeShowExemplars(true)} active={false}>
189
              Show Exemplars
190
            </Button>
191
          )}
192
        </ButtonGroup>
193
      </Form>
194
    );
195
  }
196
}
197

198
export default GraphControls;
199

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.