diff --git a/pkg/ui/react-app/.eslintrc.json b/pkg/ui/react-app/.eslintrc.json
index 395ca48af2..5112fe4732 100644
--- a/pkg/ui/react-app/.eslintrc.json
+++ b/pkg/ui/react-app/.eslintrc.json
@@ -6,7 +6,7 @@
"plugin:prettier/recommended"
],
"rules": {
- "@typescript-eslint/camelcase": "warn",
+ "camelcase": "warn",
"eol-last": [
"error",
"always"
diff --git a/pkg/ui/react-app/package.json b/pkg/ui/react-app/package.json
index 63438f0a0e..032a28c860 100644
--- a/pkg/ui/react-app/package.json
+++ b/pkg/ui/react-app/package.json
@@ -3,49 +3,49 @@
"version": "0.1.0",
"private": true,
"dependencies": {
- "@fortawesome/fontawesome-svg-core": "^1.2.14",
- "@fortawesome/free-solid-svg-icons": "^5.7.1",
- "@fortawesome/react-fontawesome": "^0.1.4",
- "@reach/router": "^1.2.1",
- "@testing-library/react-hooks": "^3.1.1",
- "@types/jest": "^24.0.20",
- "@types/jquery": "^3.5.1",
- "@types/node": "^12.11.1",
- "@types/reach__router": "^1.2.6",
- "@types/react": "^16.8.2",
- "@types/react-copy-to-clipboard": "^4.3.0",
- "@types/react-dom": "^16.8.0",
+ "@fortawesome/fontawesome-svg-core": "^1.2.34",
+ "@fortawesome/free-solid-svg-icons": "^5.15.2",
+ "@fortawesome/react-fontawesome": "^0.1.14",
+ "@reach/router": "^1.3.4",
+ "@testing-library/react-hooks": "^5.0.3",
+ "@types/jest": "^26.0.20",
+ "@types/jquery": "^3.5.5",
+ "@types/node": "^14.14.30",
+ "@types/reach__router": "^1.3.7",
+ "@types/react": "^17.0.2",
+ "@types/react-copy-to-clipboard": "^5.0.0",
+ "@types/react-dom": "^17.0.1",
"@types/react-resize-detector": "^4.0.2",
- "@types/react-select": "^3.0.20",
- "@types/sanitize-html": "^1.20.2",
- "bootstrap": "^4.2.1",
+ "@types/react-select": "^4.0.13",
+ "@types/sanitize-html": "^1.27.1",
+ "bootstrap": "^4.6.0",
"css.escape": "^1.5.1",
- "downshift": "^3.2.2",
- "enzyme-to-json": "^3.4.3",
+ "downshift": "^6.1.0",
+ "enzyme-to-json": "^3.6.1",
"fuzzy": "^0.1.3",
"i": "^0.3.6",
- "jest-fetch-mock": "^2.1.2",
+ "jest-fetch-mock": "^3.0.3",
"jquery": "^3.5.1",
"jquery.flot.tooltip": "^0.9.0",
- "jsdom": "^15.2.0",
- "moment": "^2.24.0",
- "moment-timezone": "^0.5.23",
- "popper.js": "^1.14.3",
- "query-string": "^6.13.1",
- "rc-slider": "^9.3.1",
- "react": "^16.7.0",
- "react-copy-to-clipboard": "^5.0.1",
- "react-dom": "^16.7.0",
+ "jsdom": "^16.4.0",
+ "moment": "^2.29.1",
+ "moment-timezone": "^0.5.33",
+ "popper.js": "^1.16.1",
+ "query-string": "^6.14.0",
+ "rc-slider": "^9.7.1",
+ "react": "^16.14.0",
+ "react-copy-to-clipboard": "^5.0.3",
+ "react-dom": "^16.14.0",
"react-resize-detector": "^4.2.1",
- "react-scripts": "^3.4.0",
- "react-select": "^3.1.0",
- "react-test-renderer": "^16.9.0",
- "reactstrap": "^8.0.1",
- "sanitize-html": "^1.20.1",
- "tempusdominus-bootstrap-4": "^5.1.2",
- "tempusdominus-core": "^5.0.3",
- "typescript": "^3.3.3",
- "use-query-params": "^1.1.6"
+ "react-scripts": "^3.4.4",
+ "react-select": "^4.1.0",
+ "react-test-renderer": "^16.14.0",
+ "reactstrap": "^8.9.0",
+ "sanitize-html": "^2.3.2",
+ "tempusdominus-bootstrap-4": "^5.39.0",
+ "tempusdominus-core": "^5.19.0",
+ "typescript": "^4.1.5",
+ "use-query-params": "^1.1.9"
},
"scripts": {
"start": "react-scripts start",
@@ -68,29 +68,29 @@
"not op_mini all"
],
"devDependencies": {
- "@types/enzyme": "^3.10.3",
- "@types/enzyme-adapter-react-16": "^1.0.5",
- "@types/flot": "0.0.31",
- "@types/moment-timezone": "^0.5.10",
- "@types/reactstrap": "^8.0.5",
- "@types/sinon": "^7.5.0",
- "@typescript-eslint/eslint-plugin": "2.x",
- "@typescript-eslint/parser": "2.x",
+ "@types/enzyme": "^3.10.8",
+ "@types/enzyme-adapter-react-16": "^1.0.6",
+ "@types/flot": "^0.0.31",
+ "@types/moment-timezone": "^0.5.30",
+ "@types/reactstrap": "^8.7.2",
+ "@types/sinon": "^9.0.10",
+ "@typescript-eslint/eslint-plugin": "^4.15.1",
+ "@typescript-eslint/parser": "^4.15.1",
"babel-eslint": "10.x",
- "enzyme": "^3.10.0",
- "enzyme-adapter-react-16": "^1.15.1",
+ "enzyme": "^3.11.0",
+ "enzyme-adapter-react-16": "^1.15.6",
"eslint": "6.x",
- "eslint-config-prettier": "^6.4.0",
- "eslint-config-react-app": "^5.0.2",
- "eslint-plugin-flowtype": "3.x",
- "eslint-plugin-import": "2.x",
- "eslint-plugin-jsx-a11y": "6.x",
- "eslint-plugin-prettier": "^3.1.1",
- "eslint-plugin-react": "7.x",
- "eslint-plugin-react-hooks": "1.x",
+ "eslint-config-prettier": "^7.2.0",
+ "eslint-config-react-app": "^6.0.0",
+ "eslint-plugin-flowtype": "^5.2.2",
+ "eslint-plugin-import": "^2.22.1",
+ "eslint-plugin-jsx-a11y": "^6.4.1",
+ "eslint-plugin-prettier": "^3.3.1",
+ "eslint-plugin-react": "^7.22.0",
+ "eslint-plugin-react-hooks": "^4.2.0",
"jest-fetch-mock": "^2.1.2",
- "prettier": "^1.18.2",
- "sinon": "^7.5.0"
+ "prettier": "^2.2.1",
+ "sinon": "^9.2.4"
},
"proxy": "http://localhost:10902",
"jest": {
diff --git a/pkg/ui/react-app/src/App.test.tsx b/pkg/ui/react-app/src/App.test.tsx
index 6bc7434958..d6679f0f44 100755
--- a/pkg/ui/react-app/src/App.test.tsx
+++ b/pkg/ui/react-app/src/App.test.tsx
@@ -13,7 +13,7 @@ describe('App', () => {
expect(app.find(Navigation)).toHaveLength(1);
});
it('routes', () => {
- [Alerts, Config, Flags, Rules, ServiceDiscovery, Status, Targets, TSDBStatus, PanelList].forEach(component => {
+ [Alerts, Config, Flags, Rules, ServiceDiscovery, Status, Targets, TSDBStatus, PanelList].forEach((component) => {
const c = app.find(component);
expect(c).toHaveLength(1);
expect(c.prop('pathPrefix')).toBe('/path/prefix');
diff --git a/pkg/ui/react-app/src/components/Checkbox.test.tsx b/pkg/ui/react-app/src/components/Checkbox.test.tsx
index 52258f72dd..0abebbaf02 100755
--- a/pkg/ui/react-app/src/components/Checkbox.test.tsx
+++ b/pkg/ui/react-app/src/components/Checkbox.test.tsx
@@ -8,7 +8,7 @@ const MockCmp: React.FC = () =>
;
describe('Checkbox', () => {
it('renders with subcomponents', () => {
const checkBox = shallow();
- [FormGroup, Input, Label].forEach(component => expect(checkBox.find(component)).toHaveLength(1));
+ [FormGroup, Input, Label].forEach((component) => expect(checkBox.find(component)).toHaveLength(1));
});
it('passes down the correct FormGroup props', () => {
diff --git a/pkg/ui/react-app/src/components/ToggleMoreLess.test.tsx b/pkg/ui/react-app/src/components/ToggleMoreLess.test.tsx
index dc3c5a0f94..cc683efae4 100644
--- a/pkg/ui/react-app/src/components/ToggleMoreLess.test.tsx
+++ b/pkg/ui/react-app/src/components/ToggleMoreLess.test.tsx
@@ -23,11 +23,6 @@ describe('ToggleMoreLess', () => {
it('renders a show less btn if clicked', () => {
tggleBtn.find(Button).simulate('click');
- expect(
- tggleBtn
- .find(Button)
- .render()
- .text()
- ).toEqual('show less');
+ expect(tggleBtn.find(Button).render().text()).toEqual('show less');
});
});
diff --git a/pkg/ui/react-app/src/components/withStatusIndicator.tsx b/pkg/ui/react-app/src/components/withStatusIndicator.tsx
index 7ab8080169..b33197fe01 100644
--- a/pkg/ui/react-app/src/components/withStatusIndicator.tsx
+++ b/pkg/ui/react-app/src/components/withStatusIndicator.tsx
@@ -10,7 +10,7 @@ interface StatusIndicatorProps {
componentTitle?: string;
}
-export const withStatusIndicator = (Component: ComponentType): FC => ({
+export const withStatusIndicator = (Component: ComponentType): FC => ({
error,
isLoading,
customErrorMsg,
diff --git a/pkg/ui/react-app/src/hooks/useFetch.ts b/pkg/ui/react-app/src/hooks/useFetch.ts
index 5f18b369a9..c2b82bac0a 100644
--- a/pkg/ui/react-app/src/hooks/useFetch.ts
+++ b/pkg/ui/react-app/src/hooks/useFetch.ts
@@ -8,7 +8,7 @@ export interface FetchState {
isLoading: boolean;
}
-export const useFetch = (url: string, options?: RequestInit): FetchState => {
+export const useFetch = (url: string, options?: RequestInit): FetchState => {
const [response, setResponse] = useState>({ status: 'start fetching' } as any);
const [error, setError] = useState();
const [isLoading, setIsLoading] = useState(true);
diff --git a/pkg/ui/react-app/src/pages/alerts/AlertContents.tsx b/pkg/ui/react-app/src/pages/alerts/AlertContents.tsx
index 7dfbced135..01edb129d6 100644
--- a/pkg/ui/react-app/src/pages/alerts/AlertContents.tsx
+++ b/pkg/ui/react-app/src/pages/alerts/AlertContents.tsx
@@ -81,7 +81,7 @@ const AlertsContent: FC = ({ groups = [], statsCount }) => {
{groups.map((group, i) => {
- const hasFilterOn = group.rules.some(rule => filter[rule.state]);
+ const hasFilterOn = group.rules.some((rule) => filter[rule.state]);
return hasFilterOn ? (
diff --git a/pkg/ui/react-app/src/pages/alerts/Alerts.tsx b/pkg/ui/react-app/src/pages/alerts/Alerts.tsx
index c6fef5b767..32cf90b9e0 100644
--- a/pkg/ui/react-app/src/pages/alerts/Alerts.tsx
+++ b/pkg/ui/react-app/src/pages/alerts/Alerts.tsx
@@ -17,7 +17,7 @@ const Alerts: FC = ({ pathPrefix = '' })
};
if (response.data && response.data.groups) {
- response.data.groups.forEach(el => el.rules.forEach(r => ruleStatsCount[r.state]++));
+ response.data.groups.forEach((el) => el.rules.forEach((r) => ruleStatsCount[r.state]++));
}
return ;
diff --git a/pkg/ui/react-app/src/pages/flags/Flags.tsx b/pkg/ui/react-app/src/pages/flags/Flags.tsx
index 8f9ec7e3d5..03fdf50fc8 100644
--- a/pkg/ui/react-app/src/pages/flags/Flags.tsx
+++ b/pkg/ui/react-app/src/pages/flags/Flags.tsx
@@ -19,7 +19,7 @@ export const FlagsContent: FC = ({ data = {} }) => {
Command-Line Flags
- {Object.keys(data).map(key => (
+ {Object.keys(data).map((key) => (
{key} |
{data[key]} |
diff --git a/pkg/ui/react-app/src/pages/graph/DataTable.test.tsx b/pkg/ui/react-app/src/pages/graph/DataTable.test.tsx
index 8a95f74101..2b12ba4f97 100755
--- a/pkg/ui/react-app/src/pages/graph/DataTable.test.tsx
+++ b/pkg/ui/react-app/src/pages/graph/DataTable.test.tsx
@@ -69,12 +69,7 @@ describe('DataTable', () => {
const table = dataTable.find(Table);
table.find('tr').forEach((row, idx) => {
expect(row.find(SeriesName)).toHaveLength(1);
- expect(
- row
- .find('td')
- .at(1)
- .text()
- ).toEqual(`${idx}`);
+ expect(row.find('td').at(1).text()).toEqual(`${idx}`);
});
});
});
@@ -83,7 +78,7 @@ describe('DataTable', () => {
const dataTableProps: QueryResult = {
data: {
resultType: 'vector',
- result: Array.from(Array(10001).keys()).map(i => {
+ result: Array.from(Array(10001).keys()).map((i) => {
return {
metric: {
__name__: `metric_name_${i}`,
@@ -104,12 +99,7 @@ describe('DataTable', () => {
it('renders a warning', () => {
const alerts = dataTable.find(UncontrolledAlert);
- expect(
- alerts
- .first()
- .render()
- .text()
- ).toContain('Warning: Fetched 10001 metrics, only displaying first 10000.');
+ expect(alerts.first().render().text()).toContain('Warning: Fetched 10001 metrics, only displaying first 10000.');
});
});
@@ -117,7 +107,7 @@ describe('DataTable', () => {
const dataTableProps: QueryResult = {
data: {
resultType: 'vector',
- result: Array.from(Array(1001).keys()).map(i => {
+ result: Array.from(Array(1001).keys()).map((i) => {
return {
metric: {
__name__: `metric_name_${i}`,
@@ -133,12 +123,9 @@ describe('DataTable', () => {
it('renders a warning', () => {
const alerts = dataTable.find(UncontrolledAlert);
- expect(
- alerts
- .first()
- .render()
- .text()
- ).toContain('Notice: Showing more than 1000 series, turning off label formatting for performance reasons.');
+ expect(alerts.first().render().text()).toContain(
+ 'Notice: Showing more than 1000 series, turning off label formatting for performance reasons.'
+ );
});
});
diff --git a/pkg/ui/react-app/src/pages/graph/DataTable.tsx b/pkg/ui/react-app/src/pages/graph/DataTable.tsx
index c8126ad356..2a25b6f323 100644
--- a/pkg/ui/react-app/src/pages/graph/DataTable.tsx
+++ b/pkg/ui/react-app/src/pages/graph/DataTable.tsx
@@ -79,7 +79,7 @@ const DataTable: FC = ({ data }) => {
case 'matrix':
rows = (limitSeries(data.result) as RangeSamples[]).map((s, index) => {
const valueText = s.values
- .map(v => {
+ .map((v) => {
return v[1] + ' @' + v[0];
})
.join('\n');
diff --git a/pkg/ui/react-app/src/pages/graph/ExpressionInput.test.tsx b/pkg/ui/react-app/src/pages/graph/ExpressionInput.test.tsx
index d532101a35..65107b9355 100644
--- a/pkg/ui/react-app/src/pages/graph/ExpressionInput.test.tsx
+++ b/pkg/ui/react-app/src/pages/graph/ExpressionInput.test.tsx
@@ -49,14 +49,14 @@ describe('ExpressionInput', () => {
});
it('renders a search icon when it is not loading', () => {
- const addon = expressionInput.find(InputGroupAddon).filterWhere(addon => addon.prop('addonType') === 'prepend');
+ const addon = expressionInput.find(InputGroupAddon).filterWhere((addon) => addon.prop('addonType') === 'prepend');
const icon = addon.find(FontAwesomeIcon);
expect(icon.prop('icon')).toEqual(faSearch);
});
it('renders a loading icon when it is loading', () => {
const expressionInput = mount();
- const addon = expressionInput.find(InputGroupAddon).filterWhere(addon => addon.prop('addonType') === 'prepend');
+ const addon = expressionInput.find(InputGroupAddon).filterWhere((addon) => addon.prop('addonType') === 'prepend');
const icon = addon.find(FontAwesomeIcon);
expect(icon.prop('icon')).toEqual(faSpinner);
expect(icon.prop('spin')).toBe(true);
@@ -77,7 +77,7 @@ describe('ExpressionInput', () => {
const downshift = expressionInput.find(Downshift);
const input = downshift.find(Input);
downshift.setState({ isOpen: false });
- ['Home', 'End', 'ArrowUp', 'ArrowDown'].forEach(key => {
+ ['Home', 'End', 'ArrowUp', 'ArrowDown'].forEach((key) => {
const event = getKeyEvent(key);
input.simulate('keydown', event);
const nativeEvent = event.nativeEvent as any;
@@ -124,7 +124,7 @@ describe('ExpressionInput', () => {
const spyExecuteQuery = jest.fn();
const props = { ...expressionInputProps, executeQuery: spyExecuteQuery };
const wrapper = mount();
- const btn = wrapper.find(Button).filterWhere(btn => btn.hasClass('execute-btn'));
+ const btn = wrapper.find(Button).filterWhere((btn) => btn.hasClass('execute-btn'));
btn.simulate('click');
expect(spyExecuteQuery).toHaveBeenCalledTimes(1);
});
@@ -233,7 +233,7 @@ describe('ExpressionInput', () => {
const downshift = expressionInput.find(Downshift);
const input = downshift.find(Input);
downshift.setState({ isOpen: true });
- ['ArrowUp', 'ArrowDown'].forEach(key => {
+ ['ArrowUp', 'ArrowDown'].forEach((key) => {
const event = getKeyEvent(key);
input.simulate('keydown', event);
const nativeEvent = event.nativeEvent as any;
@@ -255,7 +255,7 @@ describe('ExpressionInput', () => {
const ul = downshift.find('ul');
expect(ul.prop('className')).toEqual('card list-group');
const items = ul.find('li');
- expect(items.map(item => item.text()).join(', ')).toEqual(
+ expect(items.map((item) => item.text()).join(', ')).toEqual(
'node_cpu_guest_seconds_total, node_cpu_seconds_total, instance:node_cpu_utilisation:rate1m'
);
});
@@ -263,7 +263,7 @@ describe('ExpressionInput', () => {
});
it('renders an execute Button', () => {
- const addon = expressionInput.find(InputGroupAddon).filterWhere(addon => addon.prop('addonType') === 'append');
+ const addon = expressionInput.find(InputGroupAddon).filterWhere((addon) => addon.prop('addonType') === 'append');
const button = addon.find(Button);
expect(button.prop('className')).toEqual('execute-btn');
expect(button.prop('color')).toEqual('primary');
diff --git a/pkg/ui/react-app/src/pages/graph/ExpressionInput.tsx b/pkg/ui/react-app/src/pages/graph/ExpressionInput.tsx
index 6bce6c2d21..d52e9876d5 100644
--- a/pkg/ui/react-app/src/pages/graph/ExpressionInput.tsx
+++ b/pkg/ui/react-app/src/pages/graph/ExpressionInput.tsx
@@ -45,9 +45,9 @@ class ExpressionInput extends Component {
+ setValue = (value: string | null) => {
const { onExpressionChange } = this.props;
- onExpressionChange(value);
+ onExpressionChange(value as string);
this.setState({ height: 'auto' }, this.setHeight);
};
@@ -130,7 +130,7 @@ class ExpressionInput extends Component
- {downshift => (
+ {(downshift) => (
diff --git a/pkg/ui/react-app/src/pages/graph/Graph.test.tsx b/pkg/ui/react-app/src/pages/graph/Graph.test.tsx
index bddd639462..bacaec955b 100644
--- a/pkg/ui/react-app/src/pages/graph/Graph.test.tsx
+++ b/pkg/ui/react-app/src/pages/graph/Graph.test.tsx
@@ -58,9 +58,9 @@ describe('Graph', () => {
};
it('renders a graph with props', () => {
const graph = shallow();
- const div = graph.find('div').filterWhere(elem => elem.prop('className') === 'graph');
+ const div = graph.find('div').filterWhere((elem) => elem.prop('className') === 'graph');
const resize = div.find(ReactResizeDetector);
- const innerdiv = div.find('div').filterWhere(elem => elem.prop('className') === 'graph-chart');
+ const innerdiv = div.find('div').filterWhere((elem) => elem.prop('className') === 'graph-chart');
expect(resize.prop('handleWidth')).toBe(true);
expect(div).toHaveLength(1);
expect(innerdiv).toHaveLength(1);
@@ -236,10 +236,7 @@ describe('Graph', () => {
);
(graph.instance() as any).plot(); // create chart
const spyPlotSetAndDraw = jest.spyOn(graph.instance() as any, 'plotSetAndDraw');
- graph
- .find('.legend-item')
- .at(0)
- .simulate('mouseover');
+ graph.find('.legend-item').at(0).simulate('mouseover');
expect(spyPlotSetAndDraw).toHaveBeenCalledTimes(1);
});
it('should call spyPlotSetAndDraw with chartDate from state as default value', () => {
diff --git a/pkg/ui/react-app/src/pages/graph/GraphControls.test.tsx b/pkg/ui/react-app/src/pages/graph/GraphControls.test.tsx
index fb28a1a508..d8e289df9d 100755
--- a/pkg/ui/react-app/src/pages/graph/GraphControls.test.tsx
+++ b/pkg/ui/react-app/src/pages/graph/GraphControls.test.tsx
@@ -60,9 +60,9 @@ describe('GraphControls', () => {
title: 'Increase range',
icon: faPlus,
},
- ].forEach(testCase => {
+ ].forEach((testCase) => {
const controls = shallow();
- const addon = controls.find(InputGroupAddon).filterWhere(addon => addon.prop('addonType') === testCase.position);
+ const addon = controls.find(InputGroupAddon).filterWhere((addon) => addon.prop('addonType') === testCase.position);
const button = addon.find(Button);
const icon = button.find(FontAwesomeIcon);
expect(button.prop('title')).toEqual(testCase.title);
@@ -110,7 +110,7 @@ describe('GraphControls', () => {
it('renders a resolution Input with props', () => {
const controls = shallow();
- const input = controls.find(Input).filterWhere(input => input.prop('className') === 'resolution-input');
+ const input = controls.find(Input).filterWhere((input) => input.prop('className') === 'resolution-input');
expect(input.prop('placeholder')).toEqual('Res. (s)');
expect(input.prop('defaultValue')).toEqual('10');
expect(input.prop('innerRef')).toEqual({ current: null });
@@ -136,10 +136,10 @@ describe('GraphControls', () => {
icon: faChartArea,
active: false,
},
- ].forEach(testCase => {
+ ].forEach((testCase) => {
const controls = shallow();
const group = controls.find(ButtonGroup);
- const btn = group.find(Button).filterWhere(btn => btn.prop('title') === testCase.title);
+ const btn = group.find(Button).filterWhere((btn) => btn.prop('title') === testCase.title);
expect(btn.prop('active')).toEqual(testCase.active);
const icon = btn.find(FontAwesomeIcon);
expect(icon.prop('icon')).toEqual(testCase.icon);
@@ -156,14 +156,14 @@ describe('GraphControls', () => {
title: 'Show stacked graph',
active: false,
},
- ].forEach(testCase => {
+ ].forEach((testCase) => {
const results: boolean[] = [];
const onChange = (stacked: boolean): void => {
results.push(stacked);
};
const controls = shallow();
const group = controls.find(ButtonGroup);
- const btn = group.find(Button).filterWhere(btn => btn.prop('title') === testCase.title);
+ const btn = group.find(Button).filterWhere((btn) => btn.prop('title') === testCase.title);
const onClick = btn.prop('onClick');
if (onClick) {
onClick({} as React.MouseEvent);
@@ -178,7 +178,7 @@ describe('GraphControls', () => {
it('renders a select box for max source resolution', () => {
const controls = shallow();
- const input = controls.find(Input).filterWhere(input => input.prop('className') === 'max-source-resolution-input');
+ const input = controls.find(Input).filterWhere((input) => input.prop('className') === 'max-source-resolution-input');
expect(input.prop('type')).toEqual('select');
expect(input.prop('value')).toEqual('0s');
});
diff --git a/pkg/ui/react-app/src/pages/graph/GraphControls.tsx b/pkg/ui/react-app/src/pages/graph/GraphControls.tsx
index 4ca59d8a0d..9cfb00001c 100644
--- a/pkg/ui/react-app/src/pages/graph/GraphControls.tsx
+++ b/pkg/ui/react-app/src/pages/graph/GraphControls.tsx
@@ -101,7 +101,7 @@ class GraphControls extends Component {
render() {
return (
-