@@ -64,27 +63,21 @@ const GroupFooter = ({
{Object.keys(group.shared.silences).length === 0 ? null : (
{Object.entries(group.shared.silences).map(([cluster, silences]) =>
- silences.map((silenceID) =>
- RenderSilence(
- alertStore,
- silenceFormStore,
- afterUpdate,
- cluster,
- silenceID
- )
- )
+ silences.map((silenceID) => (
+
+ ))
)}
)}
));
};
-GroupFooter.propTypes = {
- group: APIGroup.isRequired,
- alertmanagers: PropTypes.arrayOf(PropTypes.string).isRequired,
- afterUpdate: PropTypes.func.isRequired,
- alertStore: PropTypes.instanceOf(AlertStore).isRequired,
- silenceFormStore: PropTypes.instanceOf(SilenceFormStore).isRequired,
-};
export { GroupFooter };
diff --git a/ui/src/Components/Grid/AlertGrid/AlertGroup/GroupHeader/GroupMenu.js b/ui/src/Components/Grid/AlertGrid/AlertGroup/GroupHeader/GroupMenu.tsx
similarity index 83%
rename from ui/src/Components/Grid/AlertGrid/AlertGroup/GroupHeader/GroupMenu.js
rename to ui/src/Components/Grid/AlertGrid/AlertGroup/GroupHeader/GroupMenu.tsx
index a0f89dcce..b3f336302 100644
--- a/ui/src/Components/Grid/AlertGrid/AlertGroup/GroupHeader/GroupMenu.js
+++ b/ui/src/Components/Grid/AlertGrid/AlertGroup/GroupHeader/GroupMenu.tsx
@@ -1,5 +1,11 @@
-import React, { useRef, useState, useCallback } from "react";
-import PropTypes from "prop-types";
+import React, {
+ FC,
+ useRef,
+ useState,
+ useCallback,
+ Ref,
+ CSSProperties,
+} from "react";
import copy from "copy-to-clipboard";
@@ -10,12 +16,11 @@ import { faEllipsisV } from "@fortawesome/free-solid-svg-icons/faEllipsisV";
import { faShareSquare } from "@fortawesome/free-solid-svg-icons/faShareSquare";
import { faBellSlash } from "@fortawesome/free-solid-svg-icons/faBellSlash";
-import { APIGroup } from "Models/API";
+import { APIAlertGroupT } from "Models/APITypes";
import { FormatAlertsQ } from "Stores/AlertStore";
import { AlertStore } from "Stores/AlertStore";
import {
SilenceFormStore,
- SilenceTabNames,
AlertmanagerClustersToOption,
} from "Stores/SilenceFormStore";
import { QueryOperators, StaticLabels, FormatQuery } from "Common/Query";
@@ -29,8 +34,12 @@ const PopperModifiers = [
{ name: "offset", options: { offset: "-5px, 0px" } },
];
-const onSilenceClick = (alertStore, silenceFormStore, group) => {
- let clusters = {};
+const onSilenceClick = (
+ alertStore: AlertStore,
+ silenceFormStore: SilenceFormStore,
+ group: APIAlertGroupT
+) => {
+ let clusters: { [cluster: string]: string[] } = {};
Object.entries(alertStore.data.clustersWithoutReadOnly).forEach(
([cluster, members]) => {
members.forEach((member) => {
@@ -47,11 +56,19 @@ const onSilenceClick = (alertStore, silenceFormStore, group) => {
alertStore.settings.values.silenceForm.strip.labels,
AlertmanagerClustersToOption(clusters)
);
- silenceFormStore.tab.setTab(SilenceTabNames.Editor);
+ silenceFormStore.tab.setTab("editor");
silenceFormStore.toggle.show();
};
-const MenuContent = ({
+const MenuContent: FC<{
+ popperPlacement?: string;
+ popperRef?: Ref
;
+ popperStyle?: CSSProperties;
+ group: APIAlertGroupT;
+ afterClick: () => void;
+ alertStore: AlertStore;
+ silenceFormStore: SilenceFormStore;
+}> = ({
popperPlacement,
popperRef,
popperStyle,
@@ -110,21 +127,14 @@ const MenuContent = ({
);
};
-MenuContent.propTypes = {
- popperPlacement: PropTypes.string,
- popperRef: PropTypes.func,
- popperStyle: PropTypes.object,
- group: APIGroup.isRequired,
- afterClick: PropTypes.func.isRequired,
-};
-const GroupMenu = ({
- group,
- alertStore,
- silenceFormStore,
- themed,
- setIsMenuOpen,
-}) => {
+const GroupMenu: FC<{
+ group: APIAlertGroupT;
+ alertStore: AlertStore;
+ silenceFormStore: SilenceFormStore;
+ themed: boolean;
+ setIsMenuOpen: (isOpen: boolean) => void;
+}> = ({ group, alertStore, silenceFormStore, themed, setIsMenuOpen }) => {
const [isHidden, setIsHidden] = useState(true);
const toggle = useCallback(() => {
@@ -176,12 +186,5 @@ const GroupMenu = ({
);
};
-GroupMenu.propTypes = {
- group: APIGroup.isRequired,
- alertStore: PropTypes.instanceOf(AlertStore).isRequired,
- silenceFormStore: PropTypes.instanceOf(SilenceFormStore).isRequired,
- themed: PropTypes.bool.isRequired,
- setIsMenuOpen: PropTypes.func.isRequired,
-};
export { GroupMenu, MenuContent };
diff --git a/ui/src/Components/Grid/AlertGrid/AlertGroup/GroupHeader/index.js b/ui/src/Components/Grid/AlertGrid/AlertGroup/GroupHeader/index.tsx
similarity index 84%
rename from ui/src/Components/Grid/AlertGrid/AlertGroup/GroupHeader/index.js
rename to ui/src/Components/Grid/AlertGrid/AlertGroup/GroupHeader/index.tsx
index d2d88355f..b8db35adc 100644
--- a/ui/src/Components/Grid/AlertGrid/AlertGroup/GroupHeader/index.js
+++ b/ui/src/Components/Grid/AlertGrid/AlertGroup/GroupHeader/index.tsx
@@ -1,9 +1,8 @@
-import React from "react";
-import PropTypes from "prop-types";
+import React, { FC, MouseEvent } from "react";
import { useObserver } from "mobx-react-lite";
-import { APIGroup } from "Models/API";
+import { APIAlertGroupT } from "Models/APITypes";
import { AlertStore } from "Stores/AlertStore";
import { SilenceFormStore } from "Stores/SilenceFormStore";
import { FilteringLabel } from "Components/Labels/FilteringLabel";
@@ -13,7 +12,16 @@ import { AlertAck } from "Components/AlertAck";
import { ToggleIcon } from "Components/ToggleIcon";
import { GroupMenu } from "./GroupMenu";
-const GroupHeader = ({
+const GroupHeader: FC<{
+ isCollapsed: boolean;
+ setIsCollapsed: (isCollapsed: boolean) => void;
+ group: APIAlertGroupT;
+ alertStore: AlertStore;
+ silenceFormStore: SilenceFormStore;
+ themedCounters: boolean;
+ setIsMenuOpen: (isOpen: boolean) => void;
+ gridLabelValue: string;
+}> = ({
isCollapsed,
setIsCollapsed,
group,
@@ -23,7 +31,7 @@ const GroupHeader = ({
setIsMenuOpen,
gridLabelValue,
}) => {
- const onCollapseClick = (event) => {
+ const onCollapseClick = (event: MouseEvent) => {
// left click => toggle current group
// left click + alt => toggle all groups
setIsCollapsed(!isCollapsed);
@@ -107,15 +115,5 @@ const GroupHeader = ({
));
};
-GroupHeader.propTypes = {
- isCollapsed: PropTypes.bool.isRequired,
- setIsCollapsed: PropTypes.func.isRequired,
- group: APIGroup.isRequired,
- alertStore: PropTypes.instanceOf(AlertStore).isRequired,
- silenceFormStore: PropTypes.instanceOf(SilenceFormStore).isRequired,
- themedCounters: PropTypes.bool.isRequired,
- setIsMenuOpen: PropTypes.func.isRequired,
- gridLabelValue: PropTypes.string.isRequired,
-};
export { GroupHeader };
diff --git a/ui/src/Components/Grid/AlertGrid/AlertGroup/Silences.js b/ui/src/Components/Grid/AlertGrid/AlertGroup/Silences.tsx
similarity index 60%
rename from ui/src/Components/Grid/AlertGrid/AlertGroup/Silences.js
rename to ui/src/Components/Grid/AlertGrid/AlertGroup/Silences.tsx
index 61ed31175..b2053296b 100644
--- a/ui/src/Components/Grid/AlertGrid/AlertGroup/Silences.js
+++ b/ui/src/Components/Grid/AlertGrid/AlertGroup/Silences.tsx
@@ -1,19 +1,25 @@
-import React from "react";
-import PropTypes from "prop-types";
+import React, { FC } from "react";
+import { APISilenceT } from "Models/APITypes";
+import { AlertStore } from "Stores/AlertStore";
+import { SilenceFormStore } from "Stores/SilenceFormStore";
import { ManagedSilence } from "Components/ManagedSilence";
-const FallbackSilenceDesciption = ({ silenceID }) => {
+
+const FallbackSilenceDesciption: FC<{
+ silenceID: string;
+}> = ({ silenceID }) => {
return (
Silenced by {silenceID}
);
};
-FallbackSilenceDesciption.propTypes = {
- silenceID: PropTypes.string.isRequired,
-};
-const GetSilenceFromStore = (alertStore, cluster, silenceID) => {
+const GetSilenceFromStore = (
+ alertStore: AlertStore,
+ cluster: string,
+ silenceID: string
+): APISilenceT | null => {
const amSilences = alertStore.data.silences[cluster];
if (!amSilences) return null;
@@ -24,13 +30,13 @@ const GetSilenceFromStore = (alertStore, cluster, silenceID) => {
return silence;
};
-const RenderSilence = (
- alertStore,
- silenceFormStore,
- afterUpdate,
- cluster,
- silenceID
-) => {
+const RenderSilence: FC<{
+ alertStore: AlertStore;
+ silenceFormStore: SilenceFormStore;
+ afterUpdate: () => void;
+ cluster: string;
+ silenceID: string;
+}> = ({ alertStore, silenceFormStore, afterUpdate, cluster, silenceID }) => {
const silence = GetSilenceFromStore(alertStore, cluster, silenceID);
if (silence === null) {
diff --git a/ui/src/Components/Grid/AlertGrid/AlertGroup/index.js b/ui/src/Components/Grid/AlertGrid/AlertGroup/index.tsx
similarity index 86%
rename from ui/src/Components/Grid/AlertGrid/AlertGroup/index.js
rename to ui/src/Components/Grid/AlertGrid/AlertGroup/index.tsx
index 7b81eeda9..b83ef5f79 100644
--- a/ui/src/Components/Grid/AlertGrid/AlertGroup/index.js
+++ b/ui/src/Components/Grid/AlertGrid/AlertGroup/index.tsx
@@ -1,13 +1,13 @@
-import React, { useEffect, useCallback, useState } from "react";
-import PropTypes from "prop-types";
+import React, { FC, useEffect, useCallback, useState, ReactNode } from "react";
import { useObserver } from "mobx-react-lite";
+import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faPlus } from "@fortawesome/free-solid-svg-icons/faPlus";
import { faMinus } from "@fortawesome/free-solid-svg-icons/faMinus";
-import { APIGroup } from "Models/API";
+import { APIAlertT, APIAlertGroupT, AlertStateT } from "Models/APITypes";
import { Settings } from "Stores/Settings";
import { AlertStore } from "Stores/AlertStore";
import { SilenceFormStore } from "Stores/SilenceFormStore";
@@ -18,7 +18,11 @@ import { Alert } from "./Alert";
import { GroupFooter } from "./GroupFooter";
import { DefaultDetailsCollapseValue } from "./DetailsToggle";
-const LoadButton = ({ icon, action, tooltip }) => {
+const LoadButton: FC<{
+ icon: IconDefinition;
+ action: () => void;
+ tooltip: ReactNode;
+}> = ({ icon, action, tooltip }) => {
return (
);
};
-LoadButton.propTypes = {
- icon: FontAwesomeIcon.propTypes.icon.isRequired,
- action: PropTypes.func.isRequired,
- tooltip: PropTypes.node.isRequired,
-};
-const AllAlertsAreUsingSameAlertmanagers = (alerts) => {
+const AllAlertsAreUsingSameAlertmanagers = (alerts: APIAlertT[]): boolean => {
const usedAMs = alerts.map((alert) =>
alert.alertmanager.map((am) => am.name).sort()
);
@@ -42,7 +41,17 @@ const AllAlertsAreUsingSameAlertmanagers = (alerts) => {
);
};
-const AlertGroup = ({
+const AlertGroup: FC<{
+ group: APIAlertGroupT;
+ showAlertmanagers: boolean;
+ afterUpdate: () => void;
+ alertStore: AlertStore;
+ settingsStore: Settings;
+ silenceFormStore: SilenceFormStore;
+ groupWidth: number;
+ gridLabelValue: string;
+ initialAlertsToRender?: number;
+}> = ({
group,
showAlertmanagers,
afterUpdate,
@@ -78,7 +87,7 @@ const AlertGroup = ({
// but ensure that step wouldn't push us above totalSize
// With 9 alerts and rendering 5 initially we want to show extra 9 after one
// click, and when user clicks showLess we want to go back to 5.
- const getStepSize = (totalSize) => {
+ const getStepSize = (totalSize: number) => {
const val = Math.min(
Math.max(Math.round((totalSize - defaultRenderCount) / 5), 5),
totalSize - defaultRenderCount
@@ -121,7 +130,7 @@ const AlertGroup = ({
afterUpdate();
});
- let footerAlertmanagers = [];
+ let footerAlertmanagers: string[] = [];
let showAlertmanagersInFooter = false;
// There's no need to render @alertmanager labels if there's only 1
@@ -146,11 +155,11 @@ const AlertGroup = ({
let cardBackgroundClass = "bg-light";
if (settingsStore.alertGroupConfig.config.colorTitleBar) {
const stateList = Object.entries(group.stateCount)
- .filter(([k, v]) => v !== 0)
+ .filter(([_, v]) => v !== 0)
.map(([k, _]) => k);
if (stateList.length === 1) {
const state = stateList.pop();
- cardBackgroundClass = BackgroundClassMap[state];
+ cardBackgroundClass = BackgroundClassMap[state as AlertStateT];
themedCounters = false;
}
}
@@ -160,7 +169,7 @@ const AlertGroup = ({
className="components-grid-alertgrid-alertgroup"
style={{
width: groupWidth,
- zIndex: isMenuOpen ? 100 : null,
+ zIndex: isMenuOpen ? 100 : undefined,
}}
data-defaultrendercount={
settingsStore.alertGroupConfig.config.defaultRenderCount
@@ -236,16 +245,5 @@ const AlertGroup = ({
));
};
-AlertGroup.propTypes = {
- afterUpdate: PropTypes.func.isRequired,
- group: APIGroup.isRequired,
- showAlertmanagers: PropTypes.bool.isRequired,
- alertStore: PropTypes.instanceOf(AlertStore).isRequired,
- settingsStore: PropTypes.instanceOf(Settings).isRequired,
- silenceFormStore: PropTypes.instanceOf(SilenceFormStore).isRequired,
- groupWidth: PropTypes.number.isRequired,
- gridLabelValue: PropTypes.string.isRequired,
- initialAlertsToRender: PropTypes.number,
-};
export { AlertGroup };
diff --git a/ui/src/Components/Grid/AlertGrid/Grid.js b/ui/src/Components/Grid/AlertGrid/Grid.tsx
similarity index 91%
rename from ui/src/Components/Grid/AlertGrid/Grid.js
rename to ui/src/Components/Grid/AlertGrid/Grid.tsx
index f30273ec5..a25eb911c 100644
--- a/ui/src/Components/Grid/AlertGrid/Grid.js
+++ b/ui/src/Components/Grid/AlertGrid/Grid.tsx
@@ -1,10 +1,18 @@
-import React, { useEffect, useState, useCallback } from "react";
-import PropTypes from "prop-types";
+import React, {
+ FC,
+ useEffect,
+ useState,
+ useCallback,
+ MouseEvent,
+ Ref,
+} from "react";
import { useObserver } from "mobx-react-lite";
import debounce from "lodash.debounce";
+import { SizeDetail } from "bricks.js";
+
import TransitionGroup from "react-transition-group/TransitionGroup";
import { CSSTransition } from "react-transition-group";
@@ -16,14 +24,22 @@ import { faAngleDoubleDown } from "@fortawesome/free-solid-svg-icons/faAngleDoub
import { AlertStore } from "Stores/AlertStore";
import { Settings } from "Stores/Settings";
import { SilenceFormStore } from "Stores/SilenceFormStore";
-import { APIGrid } from "Models/API";
+import { APIGridT } from "Models/APITypes";
import { useGrid } from "Hooks/useGrid";
import { ThemeContext } from "Components/Theme";
import { DefaultDetailsCollapseValue } from "./AlertGroup/DetailsToggle";
import { AlertGroup } from "./AlertGroup";
import { Swimlane } from "./Swimlane";
-const Grid = ({
+const Grid: FC<{
+ alertStore: AlertStore;
+ silenceFormStore: SilenceFormStore;
+ settingsStore: Settings;
+ gridSizesConfig: SizeDetail[];
+ groupWidth: number;
+ grid: APIGridT;
+ outerPadding: number;
+}> = ({
alertStore,
settingsStore,
silenceFormStore,
@@ -46,7 +62,7 @@ const Grid = ({
debouncedRepack();
}, [debouncedRepack, isExpanded]);
- const onCollapseClick = (event) => {
+ const onCollapseClick = (event: MouseEvent) => {
// left click => toggle current grid
// left click + alt => toggle all grids
@@ -118,7 +134,7 @@ const Grid = ({
}
key={settingsStore.gridConfig.config.groupWidth}
style={{
paddingLeft: outerPadding + "px",
@@ -182,14 +198,5 @@ const Grid = ({
));
};
-Grid.propTypes = {
- alertStore: PropTypes.instanceOf(AlertStore).isRequired,
- settingsStore: PropTypes.instanceOf(Settings).isRequired,
- silenceFormStore: PropTypes.instanceOf(SilenceFormStore).isRequired,
- gridSizesConfig: PropTypes.array.isRequired,
- groupWidth: PropTypes.number.isRequired,
- grid: APIGrid.isRequired,
- outerPadding: PropTypes.number.isRequired,
-};
export { Grid };
diff --git a/ui/src/Components/Grid/AlertGrid/GridSize.js b/ui/src/Components/Grid/AlertGrid/GridSize.ts
similarity index 57%
rename from ui/src/Components/Grid/AlertGrid/GridSize.js
rename to ui/src/Components/Grid/AlertGrid/GridSize.ts
index fd8e93a02..827d2364d 100644
--- a/ui/src/Components/Grid/AlertGrid/GridSize.js
+++ b/ui/src/Components/Grid/AlertGrid/GridSize.ts
@@ -1,6 +1,8 @@
+import { SizeDetail } from "bricks.js";
+
// grid sizes, defines how many columns are used depending on the screen width
// this is config as expected by https://github.com/callmecavs/bricks.js#sizes
-const GridSizesConfig = (canvasWidth, baseWidth) => {
+const GridSizesConfig = (baseWidth: number): SizeDetail[] => {
const generatedSizes = [];
for (let i = 2; i < 20; i++) {
generatedSizes.push({
@@ -12,14 +14,19 @@ const GridSizesConfig = (canvasWidth, baseWidth) => {
return [...[{ columns: 1, gutter: 0 }], ...generatedSizes];
};
-const GetColumnsCount = (canvasWidth, baseWidth) =>
- [{ mq: "0px", columns: 1 }, ...GridSizesConfig(canvasWidth, baseWidth)]
+const GetColumnsCount = (canvasWidth: number, baseWidth: number): number =>
+ [{ mq: "0px", columns: 1 }, ...GridSizesConfig(baseWidth)]
.filter((gs) => gs.mq !== undefined)
- .filter((gs) => canvasWidth >= Number.parseInt(gs.mq))
+ .filter((gs) => canvasWidth >= Number.parseInt(gs.mq as string))
.map((gs) => gs.columns)
- .pop();
+ .pop() as number;
-const GetGridElementWidth = (innerWidth, outerWidth, outerPadding, baseWidth) =>
+const GetGridElementWidth = (
+ innerWidth: number,
+ outerWidth: number,
+ outerPadding: number,
+ baseWidth: number
+): number =>
Math.floor(
(innerWidth - outerPadding) / GetColumnsCount(outerWidth, baseWidth)
);
diff --git a/ui/src/Components/Grid/AlertGrid/Swimlane.js b/ui/src/Components/Grid/AlertGrid/Swimlane.tsx
similarity index 85%
rename from ui/src/Components/Grid/AlertGrid/Swimlane.js
rename to ui/src/Components/Grid/AlertGrid/Swimlane.tsx
index 22225807f..21948a2a3 100644
--- a/ui/src/Components/Grid/AlertGrid/Swimlane.js
+++ b/ui/src/Components/Grid/AlertGrid/Swimlane.tsx
@@ -1,17 +1,21 @@
-import React from "react";
-import PropTypes from "prop-types";
+import React, { FC, MouseEvent } from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faTh } from "@fortawesome/free-solid-svg-icons/faTh";
import { AlertStore } from "Stores/AlertStore";
-import { APIGrid } from "Models/API";
+import { APIGridT } from "Models/APITypes";
import { FilteringLabel } from "Components/Labels/FilteringLabel";
import { FilteringCounterBadge } from "Components/Labels/FilteringCounterBadge";
import { TooltipWrapper } from "Components/TooltipWrapper";
import { ToggleIcon } from "Components/ToggleIcon";
-const Swimlane = ({ alertStore, grid, isExpanded, onToggle }) => {
+const Swimlane: FC<{
+ alertStore: AlertStore;
+ grid: APIGridT;
+ isExpanded: boolean;
+ onToggle: (event: MouseEvent) => void;
+}> = ({ alertStore, grid, isExpanded, onToggle }) => {
return (
@@ -63,11 +67,5 @@ const Swimlane = ({ alertStore, grid, isExpanded, onToggle }) => {
);
};
-Swimlane.propTypes = {
- alertStore: PropTypes.instanceOf(AlertStore).isRequired,
- grid: APIGrid.isRequired,
- isExpanded: PropTypes.bool.isRequired,
- onToggle: PropTypes.func.isRequired,
-};
export { Swimlane };
diff --git a/ui/src/Components/Grid/AlertGrid/index.test.js b/ui/src/Components/Grid/AlertGrid/index.test.js
index d2d85f1b1..234f478ed 100644
--- a/ui/src/Components/Grid/AlertGrid/index.test.js
+++ b/ui/src/Components/Grid/AlertGrid/index.test.js
@@ -97,7 +97,7 @@ const ShallowGrid = () => {
alertStore={alertStore}
silenceFormStore={silenceFormStore}
settingsStore={settingsStore}
- gridSizesConfig={GridSizesConfig(1024, 420)}
+ gridSizesConfig={GridSizesConfig(420)}
groupWidth={420}
grid={MockGrid()}
outerPadding={0}
@@ -111,7 +111,7 @@ const MountedGrid = () => {
alertStore={alertStore}
silenceFormStore={silenceFormStore}
settingsStore={settingsStore}
- gridSizesConfig={GridSizesConfig(1024, 420)}
+ gridSizesConfig={GridSizesConfig(420)}
groupWidth={420}
grid={MockGrid()}
outerPadding={0}
diff --git a/ui/src/Components/Grid/AlertGrid/index.js b/ui/src/Components/Grid/AlertGrid/index.tsx
similarity index 74%
rename from ui/src/Components/Grid/AlertGrid/index.js
rename to ui/src/Components/Grid/AlertGrid/index.tsx
index f5eb67c63..b50fb2569 100644
--- a/ui/src/Components/Grid/AlertGrid/index.js
+++ b/ui/src/Components/Grid/AlertGrid/index.tsx
@@ -1,5 +1,4 @@
-import React, { useEffect, useState } from "react";
-import PropTypes from "prop-types";
+import React, { FC, Ref, useEffect, useState } from "react";
import { autorun } from "mobx";
import { useObserver } from "mobx-react-lite";
@@ -13,12 +12,16 @@ import { useWindowSize } from "Hooks/useWindowSize";
import { Grid } from "./Grid";
import { GridSizesConfig, GetGridElementWidth } from "./GridSize";
-const AlertGrid = ({ alertStore, settingsStore, silenceFormStore }) => {
+const AlertGrid: FC<{
+ alertStore: AlertStore;
+ silenceFormStore: SilenceFormStore;
+ settingsStore: Settings;
+}> = ({ alertStore, settingsStore, silenceFormStore }) => {
const { width: windowWidth } = useWindowSize();
const { ref, width: bodyWidth } = useDimensions();
const [gridSizesConfig, setGridSizesConfig] = useState(
- GridSizesConfig(windowWidth, settingsStore.gridConfig.config.groupWidth)
+ GridSizesConfig(settingsStore.gridConfig.config.groupWidth)
);
const [groupWidth, setGroupWidth] = useState(
GetGridElementWidth(
@@ -33,10 +36,7 @@ const AlertGrid = ({ alertStore, settingsStore, silenceFormStore }) => {
() =>
autorun(() => {
setGridSizesConfig(
- GridSizesConfig(
- windowWidth,
- settingsStore.gridConfig.config.groupWidth
- )
+ GridSizesConfig(settingsStore.gridConfig.config.groupWidth)
);
setGroupWidth(
GetGridElementWidth(
@@ -52,7 +52,7 @@ const AlertGrid = ({ alertStore, settingsStore, silenceFormStore }) => {
return useObserver(() => (
-
+ } />
{alertStore.data.grids.map((grid) => (
{
));
};
-AlertGrid.propTypes = {
- alertStore: PropTypes.instanceOf(AlertStore).isRequired,
- settingsStore: PropTypes.instanceOf(Settings).isRequired,
- silenceFormStore: PropTypes.instanceOf(SilenceFormStore).isRequired,
-};
export { AlertGrid };
diff --git a/ui/src/Components/Grid/EmptyGrid/index.js b/ui/src/Components/Grid/EmptyGrid/index.tsx
similarity index 85%
rename from ui/src/Components/Grid/EmptyGrid/index.js
rename to ui/src/Components/Grid/EmptyGrid/index.tsx
index 446164f4e..447330e3b 100644
--- a/ui/src/Components/Grid/EmptyGrid/index.js
+++ b/ui/src/Components/Grid/EmptyGrid/index.tsx
@@ -1,11 +1,11 @@
-import React from "react";
+import React, { FC } from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faMugHot } from "@fortawesome/free-solid-svg-icons/faMugHot";
import { CenteredMessage } from "Components/CenteredMessage";
-const EmptyGrid = () => (
+const EmptyGrid: FC = () => (
(
+const FatalError: FC<{ message: string }> = ({ message }) => (
(
);
-FatalError.propTypes = {
- message: PropTypes.string.isRequired,
-};
export { FatalError };
diff --git a/ui/src/Components/Grid/ReloadNeeded/index.js b/ui/src/Components/Grid/ReloadNeeded/index.tsx
similarity index 84%
rename from ui/src/Components/Grid/ReloadNeeded/index.js
rename to ui/src/Components/Grid/ReloadNeeded/index.tsx
index 45e631179..183206415 100644
--- a/ui/src/Components/Grid/ReloadNeeded/index.js
+++ b/ui/src/Components/Grid/ReloadNeeded/index.tsx
@@ -1,5 +1,4 @@
-import React, { useEffect } from "react";
-import PropTypes from "prop-types";
+import React, { FC, useEffect } from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faExclamationCircle } from "@fortawesome/free-solid-svg-icons/faExclamationCircle";
@@ -7,7 +6,9 @@ import { faSpinner } from "@fortawesome/free-solid-svg-icons/faSpinner";
import { CenteredMessage } from "Components/CenteredMessage";
-const ReloadNeeded = ({ reloadAfter }) => {
+const ReloadNeeded: FC<{
+ reloadAfter: number;
+}> = ({ reloadAfter }) => {
useEffect(() => {
const timer = setTimeout(() => window.location.reload(), reloadAfter);
return () => clearTimeout(timer);
@@ -29,8 +30,5 @@ const ReloadNeeded = ({ reloadAfter }) => {
);
};
-ReloadNeeded.propTypes = {
- reloadAfter: PropTypes.number.isRequired,
-};
export { ReloadNeeded };
diff --git a/ui/src/Components/Grid/UpgradeNeeded/index.js b/ui/src/Components/Grid/UpgradeNeeded/index.tsx
similarity index 79%
rename from ui/src/Components/Grid/UpgradeNeeded/index.js
rename to ui/src/Components/Grid/UpgradeNeeded/index.tsx
index 725ce352f..2a0aa4078 100644
--- a/ui/src/Components/Grid/UpgradeNeeded/index.js
+++ b/ui/src/Components/Grid/UpgradeNeeded/index.tsx
@@ -1,5 +1,4 @@
-import React, { useEffect } from "react";
-import PropTypes from "prop-types";
+import React, { FC, useEffect } from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faRocket } from "@fortawesome/free-solid-svg-icons/faRocket";
@@ -9,7 +8,10 @@ import { CenteredMessage } from "Components/CenteredMessage";
import "csshake/scss/csshake-slow.scss";
-const UpgradeNeeded = ({ newVersion, reloadAfter }) => {
+const UpgradeNeeded: FC<{
+ newVersion: string;
+ reloadAfter: number;
+}> = ({ newVersion, reloadAfter }) => {
useEffect(() => {
const timer = setTimeout(() => window.location.reload(), reloadAfter);
return () => clearTimeout(timer);
@@ -32,9 +34,5 @@ const UpgradeNeeded = ({ newVersion, reloadAfter }) => {
);
};
-UpgradeNeeded.propTypes = {
- newVersion: PropTypes.string.isRequired,
- reloadAfter: PropTypes.number.isRequired,
-};
export { UpgradeNeeded };
diff --git a/ui/src/Components/Grid/index.js b/ui/src/Components/Grid/index.tsx
similarity index 83%
rename from ui/src/Components/Grid/index.js
rename to ui/src/Components/Grid/index.tsx
index 4918bf0a5..b6f525ac9 100644
--- a/ui/src/Components/Grid/index.js
+++ b/ui/src/Components/Grid/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";
@@ -13,7 +12,11 @@ import { UpgradeNeeded } from "./UpgradeNeeded";
import { ReloadNeeded } from "./ReloadNeeded";
import { EmptyGrid } from "./EmptyGrid";
-const Grid = ({ alertStore, settingsStore, silenceFormStore }) => {
+const Grid: FC<{
+ alertStore: AlertStore;
+ silenceFormStore: SilenceFormStore;
+ settingsStore: Settings;
+}> = ({ alertStore, settingsStore, silenceFormStore }) => {
return useObserver(() =>
alertStore.info.upgradeNeeded ? (
@@ -50,10 +53,5 @@ const Grid = ({ alertStore, settingsStore, silenceFormStore }) => {
)
);
};
-Grid.propTypes = {
- alertStore: PropTypes.instanceOf(AlertStore).isRequired,
- settingsStore: PropTypes.instanceOf(Settings).isRequired,
- silenceFormStore: PropTypes.instanceOf(SilenceFormStore).isRequired,
-};
export { Grid };
diff --git a/ui/src/Components/Labels/FilteringCounterBadge/index.tsx b/ui/src/Components/Labels/FilteringCounterBadge/index.tsx
index 2e6eaac1d..35decbadd 100644
--- a/ui/src/Components/Labels/FilteringCounterBadge/index.tsx
+++ b/ui/src/Components/Labels/FilteringCounterBadge/index.tsx
@@ -19,9 +19,9 @@ const FilteringCounterBadge: FC<{
value: string;
counter: number;
themed: boolean;
- alwaysVisible: boolean;
- defaultColor: "light" | "primary";
- isAppend: boolean;
+ alwaysVisible?: boolean;
+ defaultColor?: "light" | "primary";
+ isAppend?: boolean;
}> = observer(
({
alertStore,
@@ -29,7 +29,7 @@ const FilteringCounterBadge: FC<{
value,
counter,
themed,
- alwaysVisible,
+ alwaysVisible = false,
defaultColor = "light",
isAppend = true,
}) => {
diff --git a/ui/src/Components/Labels/Utils.js b/ui/src/Components/Labels/Utils.ts
similarity index 69%
rename from ui/src/Components/Labels/Utils.js
rename to ui/src/Components/Labels/Utils.ts
index 698b929f0..107e37c1a 100644
--- a/ui/src/Components/Labels/Utils.js
+++ b/ui/src/Components/Labels/Utils.ts
@@ -5,13 +5,28 @@ import {
StateLabelClassMap,
} from "Common/Colors";
import { StaticLabels } from "Common/Query";
+import { AlertStateT } from "Models/APITypes";
+import { AlertStore } from "Stores/AlertStore";
-const isBackgroundDark = (brightness) => brightness <= 125;
+const isBackgroundDark = (brightness: number) => brightness <= 125;
-const GetClassAndStyle = (alertStore, name, value, extraClass, baseClass) => {
+export interface ClassAndStyleT {
+ style: { [key: string]: string | number };
+ className: string;
+ baseClassNames: string[];
+ colorClassNames: string[];
+}
+
+const GetClassAndStyle = (
+ alertStore: AlertStore,
+ name: string,
+ value: string,
+ extraClass?: string,
+ baseClass?: "badge" | "btn"
+): ClassAndStyleT => {
const elementType = baseClass || "badge";
- const data = {
+ const data: ClassAndStyleT = {
style: {},
className: "",
baseClassNames: ["components-label", elementType],
@@ -22,8 +37,8 @@ const GetClassAndStyle = (alertStore, name, value, extraClass, baseClass) => {
data.colorClassNames.push(AlertNameLabelClassMap[elementType]);
} else if (name === StaticLabels.State) {
data.colorClassNames.push(
- StateLabelClassMap[value]
- ? `${elementType}-${StateLabelClassMap[value]}`
+ StateLabelClassMap[value as AlertStateT]
+ ? `${elementType}-${StateLabelClassMap[value as AlertStateT]}`
: DefaultLabelClassMap[elementType]
);
} else if (alertStore.settings.values.staticColorLabels.includes(name)) {
diff --git a/ui/src/Components/ManagedSilence/DeleteSilence.js b/ui/src/Components/ManagedSilence/DeleteSilence.tsx
similarity index 78%
rename from ui/src/Components/ManagedSilence/DeleteSilence.js
rename to ui/src/Components/ManagedSilence/DeleteSilence.tsx
index 5b758af06..d23e5b2ad 100644
--- a/ui/src/Components/ManagedSilence/DeleteSilence.js
+++ b/ui/src/Components/ManagedSilence/DeleteSilence.tsx
@@ -1,5 +1,4 @@
-import React, { useEffect, useState } from "react";
-import PropTypes from "prop-types";
+import React, { FC, useEffect, useState, ReactNode } from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faTrash } from "@fortawesome/free-solid-svg-icons/faTrash";
@@ -7,7 +6,7 @@ import { faExclamationCircle } from "@fortawesome/free-solid-svg-icons/faExclama
import { faCheckCircle } from "@fortawesome/free-solid-svg-icons/faCheckCircle";
import { faCircleNotch } from "@fortawesome/free-solid-svg-icons/faCircleNotch";
-import { APISilence } from "Models/API";
+import { APISilenceT } from "Models/APITypes";
import { AlertStore } from "Stores/AlertStore";
import { SilenceFormStore } from "Stores/SilenceFormStore";
import { FormatQuery, QueryOperators, StaticLabels } from "Common/Query";
@@ -15,7 +14,7 @@ import { useFetchDelete } from "Hooks/useFetchDelete";
import { Modal } from "Components/Modal";
import { PaginatedAlertList } from "Components/PaginatedAlertList";
-const ProgressMessage = () => (
+const ProgressMessage: FC = () => (
(
);
-const ErrorMessage = ({ message }) => (
+const ErrorMessage: FC<{
+ message: ReactNode;
+}> = ({ message }) => (
);
-ErrorMessage.propTypes = {
- message: PropTypes.node.isRequired,
-};
-const SuccessMessage = () => (
+const SuccessMessage: FC = () => (
(
);
-const DeleteResult = ({ alertStore, cluster, silence }) => {
+const DeleteResult: FC<{
+ alertStore: AlertStore;
+ cluster: string;
+ silence: APISilenceT;
+}> = ({ alertStore, cluster, silence }) => {
const [currentTime, setCurrentTime] = useState(Math.floor(Date.now()));
const am = alertStore.data.readWriteAlertmanagers
@@ -97,19 +99,14 @@ const DeleteResult = ({ alertStore, cluster, silence }) => {
);
};
-DeleteResult.propTypes = {
- alertStore: PropTypes.instanceOf(AlertStore).isRequired,
- cluster: PropTypes.string.isRequired,
- silence: APISilence.isRequired,
-};
-const DeleteSilenceModalContent = ({
- alertStore,
- silenceFormStore,
- cluster,
- silence,
- onHide,
-}) => {
+const DeleteSilenceModalContent: FC<{
+ alertStore: AlertStore;
+ silenceFormStore: SilenceFormStore;
+ cluster: string;
+ silence: APISilenceT;
+ onHide: () => void;
+}> = ({ alertStore, silenceFormStore, cluster, silence, onHide }) => {
const [confirm, setConfirm] = useState(false);
useEffect(() => {
@@ -149,7 +146,7 @@ const DeleteSilenceModalContent = ({
);
};
-SilenceDetails.propTypes = {
- silenceFormStore: PropTypes.instanceOf(SilenceFormStore).isRequired,
- cluster: PropTypes.string.isRequired,
- silence: APISilence.isRequired,
- onEditSilence: PropTypes.func.isRequired,
- isUpper: PropTypes.bool,
-};
-SilenceDetails.defaultProps = {
- isUpper: false,
-};
export { SilenceDetails };
diff --git a/ui/src/Components/ManagedSilence/SilenceProgress.js b/ui/src/Components/ManagedSilence/SilenceProgress.tsx
similarity index 84%
rename from ui/src/Components/ManagedSilence/SilenceProgress.js
rename to ui/src/Components/ManagedSilence/SilenceProgress.tsx
index 4aea0af90..b7b8a43c5 100644
--- a/ui/src/Components/ManagedSilence/SilenceProgress.js
+++ b/ui/src/Components/ManagedSilence/SilenceProgress.tsx
@@ -1,16 +1,16 @@
-import React, { useEffect, useState } from "react";
+import React, { FC, useEffect, useState } from "react";
import { useObserver } from "mobx-react-lite";
import parseISO from "date-fns/parseISO";
import getUnixTime from "date-fns/getUnixTime";
-import { APISilence } from "Models/API";
+import { APISilenceT } from "Models/APITypes";
import { DateFromNow } from "Components/DateFromNow";
import "./SilenceProgress.scss";
-const calculatePercent = (startsAt, endsAt) => {
+const calculatePercent = (startsAt: string, endsAt: string) => {
const durationDone =
getUnixTime(new Date()) - getUnixTime(parseISO(startsAt));
const durationTotal =
@@ -18,7 +18,9 @@ const calculatePercent = (startsAt, endsAt) => {
return Math.floor((durationDone / durationTotal) * 100);
};
-const SilenceProgress = ({ silence }) => {
+const SilenceProgress: FC<{
+ silence: APISilenceT;
+}> = ({ silence }) => {
const [progress, setProgress] = useState(
calculatePercent(silence.startsAt, silence.endsAt)
);
@@ -50,16 +52,13 @@ const SilenceProgress = ({ silence }) => {
role="progressbar"
style={{ width: progress + "%" }}
aria-valuenow={progress}
- aria-valuemin="0"
- aria-valuemax="100"
+ aria-valuemin={0}
+ aria-valuemax={100}
/>
)
);
};
-SilenceProgress.propTypes = {
- silence: APISilence.isRequired,
-};
export { SilenceProgress };
diff --git a/ui/src/Components/ManagedSilence/index.js b/ui/src/Components/ManagedSilence/index.tsx
similarity index 64%
rename from ui/src/Components/ManagedSilence/index.js
rename to ui/src/Components/ManagedSilence/index.tsx
index 7c9a389fe..81aab48cc 100644
--- a/ui/src/Components/ManagedSilence/index.js
+++ b/ui/src/Components/ManagedSilence/index.tsx
@@ -1,27 +1,39 @@
-import React, { useEffect, useState } from "react";
-import PropTypes from "prop-types";
+import React, { FC, useEffect, useState } from "react";
-import { APISilence } from "Models/API";
+import { APISilenceT, APIAlertmanagerUpstreamT } from "Models/APITypes";
import { AlertStore } from "Stores/AlertStore";
-import { SilenceFormStore, SilenceTabNames } from "Stores/SilenceFormStore";
+import { SilenceFormStore } from "Stores/SilenceFormStore";
import { SilenceComment } from "./SilenceComment";
import { SilenceDetails } from "./SilenceDetails";
-const GetAlertmanager = (alertStore, cluster) =>
+const GetAlertmanager = (
+ alertStore: AlertStore,
+ cluster: string
+): APIAlertmanagerUpstreamT =>
alertStore.data.readWriteAlertmanagers
.filter((u) => u.cluster === cluster)
.slice(0, 1)[0];
-const ManagedSilence = ({
+const ManagedSilence: FC<{
+ cluster: string;
+ alertCount: number;
+ alertCountAlwaysVisible: boolean;
+ silence: APISilenceT;
+ alertStore: AlertStore;
+ silenceFormStore: SilenceFormStore;
+ isOpen?: boolean;
+ onDidUpdate?: () => void;
+ isNested?: boolean;
+}> = ({
cluster,
alertCount,
alertCountAlwaysVisible,
silence,
alertStore,
silenceFormStore,
- isOpen,
+ isOpen = false,
onDidUpdate,
- isNested,
+ isNested = false,
}) => {
useEffect(() => {
if (onDidUpdate) onDidUpdate();
@@ -34,7 +46,7 @@ const ManagedSilence = ({
silenceFormStore.data.fillFormFromSilence(alertmanager, silence);
silenceFormStore.data.resetProgress();
- silenceFormStore.tab.setTab(SilenceTabNames.Editor);
+ silenceFormStore.tab.setTab("editor");
silenceFormStore.toggle.show();
};
@@ -66,21 +78,5 @@ const ManagedSilence = ({
);
};
-ManagedSilence.propTypes = {
- cluster: PropTypes.string.isRequired,
- alertCount: PropTypes.number.isRequired,
- alertCountAlwaysVisible: PropTypes.bool.isRequired,
- silence: APISilence.isRequired,
- alertStore: PropTypes.instanceOf(AlertStore).isRequired,
- silenceFormStore: PropTypes.instanceOf(SilenceFormStore).isRequired,
- onDidUpdate: PropTypes.func,
- onDeleteModalClose: PropTypes.func,
- isOpen: PropTypes.bool,
- isNested: PropTypes.bool,
-};
-ManagedSilence.defaultProps = {
- isOpen: false,
- isNested: false,
-};
export { ManagedSilence, GetAlertmanager };
diff --git a/ui/src/Components/Modal/index.tsx b/ui/src/Components/Modal/index.tsx
index 330fe4ea4..e160f966a 100644
--- a/ui/src/Components/Modal/index.tsx
+++ b/ui/src/Components/Modal/index.tsx
@@ -54,6 +54,7 @@ const Modal: FC<{
isOpen: boolean;
isUpper?: boolean;
toggleOpen: () => void;
+ onExited?: () => void;
}> = ({
size = "lg",
isOpen,
diff --git a/ui/src/Components/NavBar/FetchIndicator/index.js b/ui/src/Components/NavBar/FetchIndicator/index.tsx
similarity index 69%
rename from ui/src/Components/NavBar/FetchIndicator/index.js
rename to ui/src/Components/NavBar/FetchIndicator/index.tsx
index 65c33a831..5fde4e743 100644
--- a/ui/src/Components/NavBar/FetchIndicator/index.js
+++ b/ui/src/Components/NavBar/FetchIndicator/index.tsx
@@ -1,15 +1,20 @@
-import React from "react";
-import PropTypes from "prop-types";
+import React, { FC } from "react";
import { useObserver } from "mobx-react-lite";
+import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faCircleNotch } from "@fortawesome/free-solid-svg-icons/faCircleNotch";
import { faPauseCircle } from "@fortawesome/free-regular-svg-icons/faPauseCircle";
import { AlertStore, AlertStoreStatuses } from "Stores/AlertStore";
-const FetchIcon = ({ icon, color, visible, spin }) => (
+const FetchIcon: FC<{
+ icon: IconDefinition;
+ color?: string;
+ visible?: boolean;
+ spin?: boolean;
+}> = ({ icon, color = "muted", visible = true, spin = false }) => (