From 4a166615589e43322fc950a5a30b11e41e55ee1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Mierzwa?= Date: Tue, 14 Jul 2020 20:18:40 +0100 Subject: [PATCH] chore(ui): migrate more components to typescript --- ui/src/Common/Select.ts | 14 +- .../AlertAck/{index.js => index.tsx} | 40 +++--- ...Content.js => InhibitedByModalContent.tsx} | 14 +- .../InhibitedByModal/{index.js => index.tsx} | 13 +- .../InlineEdit/{index.js => index.tsx} | 35 +++-- .../LabelSetList/{index.js => index.tsx} | 19 ++- .../FilterInputLabel/{index.js => index.tsx} | 24 +--- .../{index.js => index.tsx} | 34 ++--- .../FilteringLabel/{index.js => index.tsx} | 11 +- .../HistoryLabel/{index.js => index.tsx} | 16 +-- .../LabelWithPercent/{index.js => index.tsx} | 32 ++--- .../StaticLabel/{index.js => index.tsx} | 9 +- ...js => AlertGroupCollapseConfiguration.tsx} | 25 ++-- .../Configuration/AlertGroupConfiguration.js | 35 ----- .../Configuration/AlertGroupConfiguration.tsx | 32 +++++ ...ion.js => AlertGroupSortConfiguration.tsx} | 32 ++--- ...arColor.js => AlertGroupTitleBarColor.tsx} | 16 +-- ...onfiguration.js => FetchConfiguration.tsx} | 17 +-- ...guration.js => FilterBarConfiguration.tsx} | 16 +-- .../{GridLabelName.js => GridLabelName.tsx} | 22 ++- ...guration.js => MultiGridConfiguration.tsx} | 16 +-- .../{SortLabelName.js => SortLabelName.tsx} | 29 ++-- ...onfiguration.js => ThemeConfiguration.tsx} | 26 ++-- .../Configuration/{index.js => index.tsx} | 12 +- .../MainModal/{Help.js => Help.tsx} | 36 ++--- ...inModalContent.js => MainModalContent.tsx} | 44 +++--- .../MainModal/{index.js => index.tsx} | 13 +- .../OverviewModal/OverviewModalContent.js | 131 ----------------- .../OverviewModal/OverviewModalContent.tsx | 135 ++++++++++++++++++ .../OverviewModal/{index.js => index.tsx} | 11 +- .../Components/PaginatedAlertList/index.tsx | 2 +- ui/src/Components/Pagination/index.tsx | 2 +- ui/src/Components/SilenceModal/SilenceForm.js | 6 +- .../SilenceMatch/LabelValueInput.test.js | 16 +-- .../SilenceMatch/MatchCounter.test.js | 17 +-- .../SilenceModal/SilenceMatch/index.test.js | 11 +- .../SilenceModal/SilencePreview/index.test.js | 4 +- .../Components/SilenceModal/index.stories.js | 4 +- ui/src/Hooks/useFetchAny.ts | 4 +- ui/src/Models/APITypes.ts | 3 +- ui/src/Stores/Settings.ts | 16 +-- ui/src/Stores/SilenceFormStore.test.js | 21 ++- ui/src/Stores/SilenceFormStore.ts | 32 ++--- 43 files changed, 491 insertions(+), 556 deletions(-) rename ui/src/Components/AlertAck/{index.js => index.tsx} (86%) rename ui/src/Components/InhibitedByModal/{InhibitedByModalContent.js => InhibitedByModalContent.tsx} (71%) rename ui/src/Components/InhibitedByModal/{index.js => index.tsx} (83%) rename ui/src/Components/InlineEdit/{index.js => index.tsx} (71%) rename ui/src/Components/LabelSetList/{index.js => index.tsx} (83%) rename ui/src/Components/Labels/FilterInputLabel/{index.js => index.tsx} (83%) rename ui/src/Components/Labels/FilteringCounterBadge/{index.js => index.tsx} (78%) rename ui/src/Components/Labels/FilteringLabel/{index.js => index.tsx} (81%) rename ui/src/Components/Labels/HistoryLabel/{index.js => index.tsx} (64%) rename ui/src/Components/Labels/LabelWithPercent/{index.js => index.tsx} (81%) rename ui/src/Components/Labels/StaticLabel/{index.js => index.tsx} (70%) rename ui/src/Components/MainModal/Configuration/{AlertGroupCollapseConfiguration.js => AlertGroupCollapseConfiguration.tsx} (68%) delete mode 100644 ui/src/Components/MainModal/Configuration/AlertGroupConfiguration.js create mode 100644 ui/src/Components/MainModal/Configuration/AlertGroupConfiguration.tsx rename ui/src/Components/MainModal/Configuration/{AlertGroupSortConfiguration.js => AlertGroupSortConfiguration.tsx} (76%) rename ui/src/Components/MainModal/Configuration/{AlertGroupTitleBarColor.js => AlertGroupTitleBarColor.tsx} (69%) rename ui/src/Components/MainModal/Configuration/{FetchConfiguration.js => FetchConfiguration.tsx} (58%) rename ui/src/Components/MainModal/Configuration/{FilterBarConfiguration.js => FilterBarConfiguration.tsx} (68%) rename ui/src/Components/MainModal/Configuration/{GridLabelName.js => GridLabelName.tsx} (72%) rename ui/src/Components/MainModal/Configuration/{MultiGridConfiguration.js => MultiGridConfiguration.tsx} (76%) rename ui/src/Components/MainModal/Configuration/{SortLabelName.js => SortLabelName.tsx} (56%) rename ui/src/Components/MainModal/Configuration/{ThemeConfiguration.js => ThemeConfiguration.tsx} (62%) rename ui/src/Components/MainModal/Configuration/{index.js => index.tsx} (89%) rename ui/src/Components/MainModal/{Help.js => Help.tsx} (94%) rename ui/src/Components/MainModal/{MainModalContent.js => MainModalContent.tsx} (58%) rename ui/src/Components/MainModal/{index.js => index.tsx} (84%) delete mode 100644 ui/src/Components/OverviewModal/OverviewModalContent.js create mode 100644 ui/src/Components/OverviewModal/OverviewModalContent.tsx rename ui/src/Components/OverviewModal/{index.js => index.tsx} (87%) diff --git a/ui/src/Common/Select.ts b/ui/src/Common/Select.ts index 4063e4e74..ea55d34bd 100644 --- a/ui/src/Common/Select.ts +++ b/ui/src/Common/Select.ts @@ -1,5 +1,13 @@ -const NewLabelName = (v: string) => `New label: ${v}`; +export const NewLabelName = (v: string) => `New label: ${v}`; -const NewLabelValue = (v: string) => `New value: ${v}`; +export const NewLabelValue = (v: string) => `New value: ${v}`; -export { NewLabelName, NewLabelValue }; +export interface OptionT { + label: string; + value: string; +} + +export const StringToOption = (value: string): OptionT => ({ + label: value, + value: value, +}); diff --git a/ui/src/Components/AlertAck/index.js b/ui/src/Components/AlertAck/index.tsx similarity index 86% rename from ui/src/Components/AlertAck/index.js rename to ui/src/Components/AlertAck/index.tsx index ffa3c9f3d..20e72b2c7 100644 --- a/ui/src/Components/AlertAck/index.js +++ b/ui/src/Components/AlertAck/index.tsx @@ -1,5 +1,4 @@ -import React, { useEffect, useState } from "react"; -import PropTypes from "prop-types"; +import React, { FC, useEffect, useState } from "react"; import { toJS } from "mobx"; import { useObserver } from "mobx-react-lite"; @@ -12,19 +11,29 @@ import { faCheckCircle } from "@fortawesome/free-solid-svg-icons/faCheckCircle"; import { faSpinner } from "@fortawesome/free-solid-svg-icons/faSpinner"; import { faExclamationCircle } from "@fortawesome/free-solid-svg-icons/faExclamationCircle"; -import { APIGroup } from "Models/API"; +import { APIAlertGroupT, AlertmanagerSilencePayloadT } from "Models/APITypes"; import { AlertStore } from "Stores/AlertStore"; import { SilenceFormStore, MatchersFromGroup, GenerateAlertmanagerSilenceData, } from "Stores/SilenceFormStore"; -import { useFetchAny } from "Hooks/useFetchAny"; +import { useFetchAny, UpstreamT } from "Hooks/useFetchAny"; import { TooltipWrapper } from "Components/TooltipWrapper"; -const AlertAck = ({ alertStore, silenceFormStore, group }) => { - const [clusters, setClusters] = useState([]); - const [upstreams, setUpstreams] = useState([]); +interface ClusterT { + payload: AlertmanagerSilencePayloadT; + clusterName: string; + members: string[]; +} + +const AlertAck: FC<{ + alertStore: AlertStore; + silenceFormStore: SilenceFormStore; + group: APIAlertGroupT; +}> = ({ alertStore, silenceFormStore, group }) => { + const [clusters, setClusters] = useState([] as ClusterT[]); + const [upstreams, setUpstreams] = useState([] as UpstreamT[]); const [currentCluster, setCurrentCluster] = useState(0); const [isAcking, setIsAcking] = useState(false); @@ -46,15 +55,15 @@ const AlertAck = ({ alertStore, silenceFormStore, group }) => { } const alertmanagers = Object.entries(group.alertmanagerCount) - .filter(([amName, alertCount]) => alertCount > 0) + .filter(([_, alertCount]) => alertCount > 0) .map(([amName, _]) => amName); const clusters = Object.entries( alertStore.data.clustersWithoutReadOnly - ).filter(([clusterName, clusterMembers]) => + ).filter(([_, clusterMembers]) => alertmanagers.some((m) => clusterMembers.includes(m)) ); - let c = []; + let c: ClusterT[] = []; for (const [clusterName, clusterMembers] of clusters) { const durationSeconds = toJS( alertStore.settings.values.alertAcknowledgement.durationSeconds @@ -94,7 +103,7 @@ const AlertAck = ({ alertStore, silenceFormStore, group }) => { if (clusters.length) { reset(); const cluster = clusters[currentCluster]; - let u = []; + let u: UpstreamT[] = []; cluster.members.forEach((amName) => { const am = alertStore.data.getAlertmanagerByName(amName); if (am !== undefined) { @@ -119,9 +128,9 @@ const AlertAck = ({ alertStore, silenceFormStore, group }) => { }, [alertStore.data, clusters, currentCluster, reset]); useEffect(() => { - let timer; + let timer: number; if (!isAcking && error) { - timer = setTimeout(() => { + timer = window.setTimeout(() => { setUpstreams([]); setIsAcking(false); reset(); @@ -168,10 +177,5 @@ const AlertAck = ({ alertStore, silenceFormStore, group }) => { ) ); }; -AlertAck.propTypes = { - alertStore: PropTypes.instanceOf(AlertStore).isRequired, - silenceFormStore: PropTypes.instanceOf(SilenceFormStore).isRequired, - group: APIGroup.isRequired, -}; export { AlertAck }; diff --git a/ui/src/Components/InhibitedByModal/InhibitedByModalContent.js b/ui/src/Components/InhibitedByModal/InhibitedByModalContent.tsx similarity index 71% rename from ui/src/Components/InhibitedByModal/InhibitedByModalContent.js rename to ui/src/Components/InhibitedByModal/InhibitedByModalContent.tsx index 28780fe1a..ba43abdf8 100644 --- a/ui/src/Components/InhibitedByModal/InhibitedByModalContent.js +++ b/ui/src/Components/InhibitedByModal/InhibitedByModalContent.tsx @@ -1,11 +1,14 @@ -import React from "react"; -import PropTypes from "prop-types"; +import React, { FC } from "react"; import { AlertStore } from "Stores/AlertStore"; import { FormatQuery, QueryOperators, StaticLabels } from "Common/Query"; import { PaginatedAlertList } from "Components/PaginatedAlertList"; -const InhibitedByModalContent = ({ alertStore, fingerprints, onHide }) => { +const InhibitedByModalContent: FC<{ + alertStore: AlertStore; + fingerprints: string[]; + onHide: () => void; +}> = ({ alertStore, fingerprints, onHide }) => { return (
@@ -29,10 +32,5 @@ const InhibitedByModalContent = ({ alertStore, fingerprints, onHide }) => { ); }; -InhibitedByModalContent.propTypes = { - alertStore: PropTypes.instanceOf(AlertStore).isRequired, - fingerprints: PropTypes.arrayOf(PropTypes.string).isRequired, - onHide: PropTypes.func.isRequired, -}; export { InhibitedByModalContent }; diff --git a/ui/src/Components/InhibitedByModal/index.js b/ui/src/Components/InhibitedByModal/index.tsx similarity index 83% rename from ui/src/Components/InhibitedByModal/index.js rename to ui/src/Components/InhibitedByModal/index.tsx index 54800bcb0..2fa41f71c 100644 --- a/ui/src/Components/InhibitedByModal/index.js +++ b/ui/src/Components/InhibitedByModal/index.tsx @@ -1,5 +1,4 @@ -import React, { useState, useCallback } from "react"; -import PropTypes from "prop-types"; +import React, { FC, useState, useCallback } from "react"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faSpinner } from "@fortawesome/free-solid-svg-icons/faSpinner"; @@ -16,7 +15,10 @@ const InhibitedByModalContent = React.lazy(() => })) ); -const InhibitedByModal = ({ alertStore, fingerprints }) => { +const InhibitedByModal: FC<{ + alertStore: AlertStore; + fingerprints: string[]; +}> = ({ alertStore, fingerprints }) => { const [isVisible, setIsVisible] = useState(false); const toggle = useCallback(() => setIsVisible(!isVisible), [isVisible]); @@ -42,7 +44,6 @@ const InhibitedByModal = ({ alertStore, fingerprints }) => { setIsVisible(false)} - isVisible={isVisible} fingerprints={fingerprints} /> @@ -50,9 +51,5 @@ const InhibitedByModal = ({ alertStore, fingerprints }) => { ); }; -InhibitedByModal.propTypes = { - alertStore: PropTypes.instanceOf(AlertStore).isRequired, - fingerprints: PropTypes.arrayOf(PropTypes.string).isRequired, -}; export { InhibitedByModal }; diff --git a/ui/src/Components/InlineEdit/index.js b/ui/src/Components/InlineEdit/index.tsx similarity index 71% rename from ui/src/Components/InlineEdit/index.js rename to ui/src/Components/InlineEdit/index.tsx index 24b3312a9..8aac4bba6 100644 --- a/ui/src/Components/InlineEdit/index.js +++ b/ui/src/Components/InlineEdit/index.tsx @@ -1,9 +1,22 @@ -import React, { useState, useRef, useEffect } from "react"; -import PropTypes from "prop-types"; +import React, { + FC, + useState, + useRef, + useEffect, + KeyboardEvent, + ChangeEvent, +} from "react"; import { useOnClickOutside } from "Hooks/useOnClickOutside"; -const InlineEdit = ({ +const InlineEdit: FC<{ + className: string; + classNameEditing: string; + value: string; + onChange: (value: string) => void; + onEnterEditing: () => void; + onExitEditing: () => void; +}> = ({ className, classNameEditing, value, @@ -11,8 +24,8 @@ const InlineEdit = ({ onEnterEditing, onExitEditing, }) => { - const ref = useRef(null); - const [editedValue, setEditedValue] = useState(null); + const ref = useRef(null as null | HTMLInputElement); + const [editedValue, setEditedValue] = useState(null as null | string); const [isEditing, setIsEditing] = useState(false); const startEditing = () => { @@ -30,11 +43,11 @@ const InlineEdit = ({ } }; - const onInput = (event) => { + const onInput = (event: ChangeEvent) => { setEditedValue(event.target.value.trim()); }; - const onKeyDown = (event) => { + const onKeyDown = (event: KeyboardEvent) => { if (event.keyCode === 13) { if (editedValue) { onChange(editedValue); @@ -75,13 +88,5 @@ const InlineEdit = ({ ); }; -InlineEdit.propTypes = { - className: PropTypes.string, - classNameEditing: PropTypes.string, - value: PropTypes.string.isRequired, - onChange: PropTypes.func.isRequired, - onEnterEditing: PropTypes.func, - onExitEditing: PropTypes.func, -}; export { InlineEdit }; diff --git a/ui/src/Components/LabelSetList/index.js b/ui/src/Components/LabelSetList/index.tsx similarity index 83% rename from ui/src/Components/LabelSetList/index.js rename to ui/src/Components/LabelSetList/index.tsx index b0e647520..33296a5e6 100644 --- a/ui/src/Components/LabelSetList/index.js +++ b/ui/src/Components/LabelSetList/index.tsx @@ -1,7 +1,7 @@ -import React, { useState } from "react"; -import PropTypes from "prop-types"; +import React, { FC, useState } from "react"; import { AlertStore } from "Stores/AlertStore"; +import { APIAlertGroupT } from "Models/APITypes"; import { IsMobile } from "Common/Device"; import { hashObject } from "Common/Hash"; import { StaticLabel } from "Components/Labels/StaticLabel"; @@ -9,8 +9,8 @@ import { PageSelect } from "Components/Pagination"; // take a list of groups and outputs a list of label sets, this ignores // the receiver, so we'll end up with only unique alerts -const GroupListToUniqueLabelsList = (groups) => { - const alerts = {}; +const GroupListToUniqueLabelsList = (groups: APIAlertGroupT[]) => { + const alerts: { [alertHash: string]: { [labelName: string]: string } } = {}; for (const group of groups) { for (const alert of group.alerts) { const alertLabels = Object.assign( @@ -26,7 +26,11 @@ const GroupListToUniqueLabelsList = (groups) => { return Object.values(alerts); }; -const LabelSetList = ({ alertStore, labelsList, title }) => { +const LabelSetList: FC<{ + alertStore: AlertStore; + labelsList: { [labelName: string]: string }[]; + title?: string; +}> = ({ alertStore, labelsList, title }) => { const [activePage, setActivePage] = useState(1); const maxPerPage = IsMobile() ? 5 : 10; @@ -70,10 +74,5 @@ const LabelSetList = ({ alertStore, labelsList, title }) => {
); }; -LabelSetList.propTypes = { - alertStore: PropTypes.instanceOf(AlertStore).isRequired, - labelsList: PropTypes.arrayOf(PropTypes.object).isRequired, - title: PropTypes.string, -}; export { LabelSetList, GroupListToUniqueLabelsList }; diff --git a/ui/src/Components/Labels/FilterInputLabel/index.js b/ui/src/Components/Labels/FilterInputLabel/index.tsx similarity index 83% rename from ui/src/Components/Labels/FilterInputLabel/index.js rename to ui/src/Components/Labels/FilterInputLabel/index.tsx index 7f89e5e3f..c6358e29c 100644 --- a/ui/src/Components/Labels/FilterInputLabel/index.js +++ b/ui/src/Components/Labels/FilterInputLabel/index.tsx @@ -1,5 +1,4 @@ -import React from "react"; -import PropTypes from "prop-types"; +import React, { FC } from "react"; import { useObserver } from "mobx-react-lite"; @@ -8,14 +7,17 @@ import { faExclamationCircle } from "@fortawesome/free-solid-svg-icons/faExclama import { faSpinner } from "@fortawesome/free-solid-svg-icons/faSpinner"; import { faTimes } from "@fortawesome/free-solid-svg-icons/faTimes"; -import { AlertStore } from "Stores/AlertStore"; +import { AlertStore, FilterT } from "Stores/AlertStore"; import { QueryOperators } from "Common/Query"; import { TooltipWrapper } from "Components/TooltipWrapper"; import { GetClassAndStyle } from "Components/Labels/Utils"; import { InlineEdit } from "Components/InlineEdit"; -const FilterInputLabel = ({ alertStore, filter }) => { - const onChange = (val) => { +const FilterInputLabel: FC<{ + alertStore: AlertStore; + filter: FilterT; +}> = ({ alertStore, filter }) => { + const onChange = (val: string) => { alertStore.status.resume(); // if filter is empty string then remove it if (val === "") { @@ -80,17 +82,5 @@ const FilterInputLabel = ({ alertStore, filter }) => { )); }; -FilterInputLabel.propTypes = { - alertStore: PropTypes.instanceOf(AlertStore).isRequired, - filter: PropTypes.shape({ - raw: PropTypes.string, - applied: PropTypes.bool, - isValid: PropTypes.bool, - hits: PropTypes.number, - name: PropTypes.string, - matcher: PropTypes.string, - value: PropTypes.string, - }), -}; export { FilterInputLabel }; diff --git a/ui/src/Components/Labels/FilteringCounterBadge/index.js b/ui/src/Components/Labels/FilteringCounterBadge/index.tsx similarity index 78% rename from ui/src/Components/Labels/FilteringCounterBadge/index.js rename to ui/src/Components/Labels/FilteringCounterBadge/index.tsx index e76f66845..2e6eaac1d 100644 --- a/ui/src/Components/Labels/FilteringCounterBadge/index.js +++ b/ui/src/Components/Labels/FilteringCounterBadge/index.tsx @@ -1,5 +1,4 @@ -import React, { useCallback } from "react"; -import PropTypes from "prop-types"; +import React, { FC, useCallback, MouseEvent } from "react"; import { observer } from "mobx-react-lite"; @@ -14,7 +13,16 @@ import { useFlashTransition } from "Hooks/useFlashTransition"; // Same as FilteringLabel but for labels that are counters (usually @state) // and only renders a pill badge with the counter, it doesn't render anything // if the counter is 0 -const FilteringCounterBadge = observer( +const FilteringCounterBadge: FC<{ + alertStore: AlertStore; + name: string; + value: string; + counter: number; + themed: boolean; + alwaysVisible: boolean; + defaultColor: "light" | "primary"; + isAppend: boolean; +}> = observer( ({ alertStore, name, @@ -22,13 +30,13 @@ const FilteringCounterBadge = observer( counter, themed, alwaysVisible, - defaultColor, - isAppend, + defaultColor = "light", + isAppend = true, }) => { const { ref, props } = useFlashTransition(counter); const handleClick = useCallback( - (event) => { + (event: MouseEvent) => { // left click => apply foo=bar filter // left click + alt => apply foo!=bar filter const operator = @@ -82,19 +90,5 @@ const FilteringCounterBadge = observer( ); } ); -FilteringCounterBadge.propTypes = { - alertStore: PropTypes.instanceOf(AlertStore).isRequired, - name: PropTypes.string.isRequired, - value: PropTypes.string.isRequired, - counter: PropTypes.number.isRequired, - themed: PropTypes.bool.isRequired, - alwaysVisible: PropTypes.bool, - defaultColor: PropTypes.oneOf(["light", "primary"]), - isAppend: PropTypes.bool, -}; -FilteringCounterBadge.defaultProps = { - defaultColor: "light", - isAppend: true, -}; export { FilteringCounterBadge }; diff --git a/ui/src/Components/Labels/FilteringLabel/index.js b/ui/src/Components/Labels/FilteringLabel/index.tsx similarity index 81% rename from ui/src/Components/Labels/FilteringLabel/index.js rename to ui/src/Components/Labels/FilteringLabel/index.tsx index 467b28e82..66ec33183 100644 --- a/ui/src/Components/Labels/FilteringLabel/index.js +++ b/ui/src/Components/Labels/FilteringLabel/index.tsx @@ -1,14 +1,19 @@ -import React, { useCallback } from "react"; +import React, { FC, useCallback, MouseEvent } from "react"; import { useObserver } from "mobx-react-lite"; +import { AlertStore } from "Stores/AlertStore"; import { QueryOperators, FormatQuery } from "Common/Query"; import { TooltipWrapper } from "Components/TooltipWrapper"; import { GetClassAndStyle } from "Components/Labels/Utils"; -const FilteringLabel = ({ alertStore, name, value }) => { +const FilteringLabel: FC<{ + alertStore: AlertStore; + name: string; + value: string; +}> = ({ alertStore, name, value }) => { const handleClick = useCallback( - (event) => { + (event: MouseEvent) => { // left click => apply foo=bar filter // left click + alt => apply foo!=bar filter const operator = diff --git a/ui/src/Components/Labels/HistoryLabel/index.js b/ui/src/Components/Labels/HistoryLabel/index.tsx similarity index 64% rename from ui/src/Components/Labels/HistoryLabel/index.js rename to ui/src/Components/Labels/HistoryLabel/index.tsx index d3e8749ad..fc91d4c75 100644 --- a/ui/src/Components/Labels/HistoryLabel/index.js +++ b/ui/src/Components/Labels/HistoryLabel/index.tsx @@ -1,5 +1,4 @@ -import React from "react"; -import PropTypes from "prop-types"; +import React, { FC } from "react"; import { useObserver } from "mobx-react-lite"; @@ -7,7 +6,12 @@ import { QueryOperators } from "Common/Query"; import { AlertStore } from "Stores/AlertStore"; import { GetClassAndStyle } from "Components/Labels/Utils"; -const HistoryLabel = ({ alertStore, name, matcher, value }) => { +const HistoryLabel: FC<{ + alertStore: AlertStore; + name: string; + matcher: string; + value: string; +}> = ({ alertStore, name, matcher, value }) => { const cs = GetClassAndStyle( alertStore, matcher === QueryOperators.Equal ? name : "", @@ -22,11 +26,5 @@ const HistoryLabel = ({ alertStore, name, matcher, value }) => { )); }; -HistoryLabel.propTypes = { - alertStore: PropTypes.instanceOf(AlertStore).isRequired, - name: PropTypes.string.isRequired, - value: PropTypes.string.isRequired, - matcher: PropTypes.string.isRequired, -}; export { HistoryLabel }; diff --git a/ui/src/Components/Labels/LabelWithPercent/index.js b/ui/src/Components/Labels/LabelWithPercent/index.tsx similarity index 81% rename from ui/src/Components/Labels/LabelWithPercent/index.js rename to ui/src/Components/Labels/LabelWithPercent/index.tsx index a6e3b9bc3..a7c75aac5 100644 --- a/ui/src/Components/Labels/LabelWithPercent/index.js +++ b/ui/src/Components/Labels/LabelWithPercent/index.tsx @@ -1,5 +1,4 @@ -import React, { useCallback } from "react"; -import PropTypes from "prop-types"; +import React, { FC, useCallback, MouseEvent } from "react"; import { observer } from "mobx-react-lite"; @@ -10,10 +9,18 @@ import { AlertStore } from "Stores/AlertStore"; import { QueryOperators, FormatQuery } from "Common/Query"; import { GetClassAndStyle } from "Components/Labels/Utils"; -const LabelWithPercent = observer( +const LabelWithPercent: FC<{ + alertStore: AlertStore; + name: string; + value: string; + hits: number; + percent: number; + offset: number; + isActive: boolean; +}> = observer( ({ alertStore, name, value, hits, percent, offset, isActive }) => { const handleClick = useCallback( - (event) => { + (event: MouseEvent) => { // left click => apply foo=bar filter // left click + alt => apply foo!=bar filter const operator = @@ -70,8 +77,8 @@ const LabelWithPercent = observer( role="progressbar" style={{ width: offset + "%" }} aria-valuenow={offset} - aria-valuemin="0" - aria-valuemax="100" + aria-valuemin={0} + aria-valuemax={100} /> )}
); } ); -LabelWithPercent.propTypes = { - alertStore: PropTypes.instanceOf(AlertStore).isRequired, - name: PropTypes.string.isRequired, - value: PropTypes.string.isRequired, - hits: PropTypes.number.isRequired, - percent: PropTypes.number.isRequired, - offset: PropTypes.number.isRequired, - isActive: PropTypes.bool.isRequired, -}; export { LabelWithPercent }; diff --git a/ui/src/Components/Labels/StaticLabel/index.js b/ui/src/Components/Labels/StaticLabel/index.tsx similarity index 70% rename from ui/src/Components/Labels/StaticLabel/index.js rename to ui/src/Components/Labels/StaticLabel/index.tsx index a16f800f1..fe795735f 100644 --- a/ui/src/Components/Labels/StaticLabel/index.js +++ b/ui/src/Components/Labels/StaticLabel/index.tsx @@ -1,11 +1,16 @@ -import React from "react"; +import React, { FC } from "react"; import { useObserver } from "mobx-react-lite"; +import { AlertStore } from "Stores/AlertStore"; import { GetClassAndStyle } from "Components/Labels/Utils"; // Renders a static label element, no click actions, no hover -const StaticLabel = ({ alertStore, name, value }) => { +const StaticLabel: FC<{ + alertStore: AlertStore; + name: string; + value: string; +}> = ({ alertStore, name, value }) => { const cs = GetClassAndStyle(alertStore, name, value); return useObserver(() => ( diff --git a/ui/src/Components/MainModal/Configuration/AlertGroupCollapseConfiguration.js b/ui/src/Components/MainModal/Configuration/AlertGroupCollapseConfiguration.tsx similarity index 68% rename from ui/src/Components/MainModal/Configuration/AlertGroupCollapseConfiguration.js rename to ui/src/Components/MainModal/Configuration/AlertGroupCollapseConfiguration.tsx index bb6e9e085..f22913d8c 100644 --- a/ui/src/Components/MainModal/Configuration/AlertGroupCollapseConfiguration.js +++ b/ui/src/Components/MainModal/Configuration/AlertGroupCollapseConfiguration.tsx @@ -1,32 +1,34 @@ -import React from "react"; -import PropTypes from "prop-types"; +import React, { FC } from "react"; import { useObserver } from "mobx-react-lite"; import Select from "react-select"; -import { Settings } from "Stores/Settings"; +import { OptionT } from "Common/Select"; +import { Settings, CollapseStateT } from "Stores/Settings"; import { ThemeContext } from "Components/Theme"; -const AlertGroupCollapseConfiguration = ({ settingsStore }) => { +const AlertGroupCollapseConfiguration: FC<{ + settingsStore: Settings; +}> = ({ settingsStore }) => { if ( !Object.values(settingsStore.alertGroupConfig.options) .map((o) => o.value) .includes(settingsStore.alertGroupConfig.config.defaultCollapseState) ) { settingsStore.alertGroupConfig.config.defaultCollapseState = - settingsStore.alertGroupConfig.options.collapsedOnMobile.value; + "collapsedOnMobile"; } - const valueToOption = (val) => { + const valueToOption = (val: CollapseStateT): OptionT => { return { label: settingsStore.alertGroupConfig.options[val].label, value: val, }; }; - const onCollapseChange = (newValue, actionMeta) => { - settingsStore.alertGroupConfig.config.defaultCollapseState = newValue.value; + const onCollapseChange = (newValue: CollapseStateT) => { + settingsStore.alertGroupConfig.config.defaultCollapseState = newValue; }; const context = React.useContext(ThemeContext); @@ -41,14 +43,13 @@ const AlertGroupCollapseConfiguration = ({ settingsStore }) => { settingsStore.alertGroupConfig.config.defaultCollapseState )} options={Object.values(settingsStore.alertGroupConfig.options)} - onChange={onCollapseChange} + onChange={(option) => + onCollapseChange((option as OptionT).value as CollapseStateT) + } hideSelectedOptions /> )); }; -AlertGroupCollapseConfiguration.propTypes = { - settingsStore: PropTypes.instanceOf(Settings).isRequired, -}; export { AlertGroupCollapseConfiguration }; diff --git a/ui/src/Components/MainModal/Configuration/AlertGroupConfiguration.js b/ui/src/Components/MainModal/Configuration/AlertGroupConfiguration.js deleted file mode 100644 index dd45f0707..000000000 --- a/ui/src/Components/MainModal/Configuration/AlertGroupConfiguration.js +++ /dev/null @@ -1,35 +0,0 @@ -import React, { useState } from "react"; -import PropTypes from "prop-types"; - -import InputRange from "react-input-range"; - -import { Settings } from "Stores/Settings"; - -const AlertGroupConfiguration = ({ settingsStore }) => { - const [defaultRenderCount, setDefaultRenderCount] = useState( - settingsStore.alertGroupConfig.config.defaultRenderCount - ); - - const onChangeComplete = (value) => { - settingsStore.alertGroupConfig.setDefaultRenderCount(value); - }; - - return ( -
- -
- ); -}; -AlertGroupConfiguration.propTypes = { - settingsStore: PropTypes.instanceOf(Settings).isRequired, -}; - -export { AlertGroupConfiguration }; diff --git a/ui/src/Components/MainModal/Configuration/AlertGroupConfiguration.tsx b/ui/src/Components/MainModal/Configuration/AlertGroupConfiguration.tsx new file mode 100644 index 000000000..1e139fb00 --- /dev/null +++ b/ui/src/Components/MainModal/Configuration/AlertGroupConfiguration.tsx @@ -0,0 +1,32 @@ +import React, { FC, useState } from "react"; + +import InputRange from "react-input-range"; + +import { Settings } from "Stores/Settings"; + +const AlertGroupConfiguration: FC<{ + settingsStore: Settings; +}> = ({ settingsStore }) => { + const [defaultRenderCount, setDefaultRenderCount] = useState( + settingsStore.alertGroupConfig.config.defaultRenderCount as number + ); + + const onChangeComplete = (value: number) => { + settingsStore.alertGroupConfig.setDefaultRenderCount(value as number); + }; + + return ( +
+ setDefaultRenderCount(value as number)} + onChangeComplete={(value) => onChangeComplete(value as number)} + /> +
+ ); +}; + +export { AlertGroupConfiguration }; diff --git a/ui/src/Components/MainModal/Configuration/AlertGroupSortConfiguration.js b/ui/src/Components/MainModal/Configuration/AlertGroupSortConfiguration.tsx similarity index 76% rename from ui/src/Components/MainModal/Configuration/AlertGroupSortConfiguration.js rename to ui/src/Components/MainModal/Configuration/AlertGroupSortConfiguration.tsx index 12f72aec9..0cefbe0ee 100644 --- a/ui/src/Components/MainModal/Configuration/AlertGroupSortConfiguration.js +++ b/ui/src/Components/MainModal/Configuration/AlertGroupSortConfiguration.tsx @@ -1,33 +1,34 @@ -import React from "react"; -import PropTypes from "prop-types"; +import React, { FC } from "react"; import { useObserver } from "mobx-react-lite"; import Select from "react-select"; -import { Settings } from "Stores/Settings"; +import { Settings, SortOrderT } from "Stores/Settings"; +import { OptionT } from "Common/Select"; import { ThemeContext } from "Components/Theme"; import { SortLabelName } from "./SortLabelName"; -const AlertGroupSortConfiguration = ({ settingsStore }) => { +const AlertGroupSortConfiguration: FC<{ + settingsStore: Settings; +}> = ({ settingsStore }) => { if ( !Object.values(settingsStore.gridConfig.options) .map((o) => o.value) .includes(settingsStore.gridConfig.config.sortOrder) ) { - settingsStore.gridConfig.config.sortOrder = - settingsStore.gridConfig.options.default.value; + settingsStore.gridConfig.config.sortOrder = "default"; } - const onSortOrderChange = (newValue, actionMeta) => { - settingsStore.gridConfig.config.sortOrder = newValue.value; + const onSortOrderChange = (value: SortOrderT) => { + settingsStore.gridConfig.config.sortOrder = value; }; - const onSortReverseChange = (event) => { - settingsStore.gridConfig.config.reverseSort = event.target.checked; + const onSortReverseChange = (value: boolean) => { + settingsStore.gridConfig.config.reverseSort = value; }; - const valueToOption = (val) => { + const valueToOption = (val: SortOrderT) => { return { label: settingsStore.gridConfig.options[val].label, value: val }; }; @@ -51,7 +52,9 @@ const AlertGroupSortConfiguration = ({ settingsStore }) => { settingsStore.gridConfig.config.sortOrder )} options={Object.values(settingsStore.gridConfig.options)} - onChange={onSortOrderChange} + onChange={(option) => + onSortOrderChange((option as OptionT).value as SortOrderT) + } hideSelectedOptions /> @@ -70,7 +73,7 @@ const AlertGroupSortConfiguration = ({ settingsStore }) => { type="checkbox" value="" checked={settingsStore.gridConfig.config.reverseSort || false} - onChange={onSortReverseChange} + onChange={(event) => onSortReverseChange(event.target.checked)} />