mirror of
https://github.com/prymitive/karma
synced 2026-05-17 04:16:42 +00:00
chore(ui): use FC for function components
This commit is contained in:
committed by
Łukasz Mierzwa
parent
c85a47ae13
commit
ab36d3bfbc
197
ui/src/App.tsx
197
ui/src/App.tsx
@@ -1,9 +1,4 @@
|
||||
import React, {
|
||||
FunctionComponent,
|
||||
useState,
|
||||
useEffect,
|
||||
useCallback,
|
||||
} from "react";
|
||||
import React, { FC, useState, useEffect, useCallback } from "react";
|
||||
|
||||
import { observer } from "mobx-react-lite";
|
||||
|
||||
@@ -34,108 +29,102 @@ interface AppProps {
|
||||
uiDefaults: UIDefaults | null;
|
||||
}
|
||||
|
||||
const App: FunctionComponent<AppProps> = observer(
|
||||
({ defaultFilters, uiDefaults }) => {
|
||||
const [alertStore] = useState<AlertStore>(new AlertStore(null));
|
||||
const [silenceFormStore] = useState<SilenceFormStore>(
|
||||
new SilenceFormStore()
|
||||
);
|
||||
const [settingsStore] = useState<Settings>(new Settings(uiDefaults));
|
||||
const App: FC<AppProps> = observer(({ defaultFilters, uiDefaults }) => {
|
||||
const [alertStore] = useState<AlertStore>(new AlertStore(null));
|
||||
const [silenceFormStore] = useState<SilenceFormStore>(new SilenceFormStore());
|
||||
const [settingsStore] = useState<Settings>(new Settings(uiDefaults));
|
||||
|
||||
useEffect(() => {
|
||||
let filters;
|
||||
// parse and decode request query args
|
||||
const p: {
|
||||
params: {
|
||||
q: string[];
|
||||
m?: string;
|
||||
};
|
||||
defaultsUsed: boolean;
|
||||
} = DecodeLocationSearch(window.location.search);
|
||||
// p.defaultsUsed means that karma URI didn't have ?q=foo query args
|
||||
if (p.defaultsUsed) {
|
||||
// no ?q=foo set, use defaults saved by the user or from backend config
|
||||
if (settingsStore.savedFilters.config.present) {
|
||||
filters = settingsStore.savedFilters.config.filters;
|
||||
} else {
|
||||
filters = defaultFilters;
|
||||
}
|
||||
} else {
|
||||
// user passed ?q=foo, use it as initial filters
|
||||
filters = p.params.q;
|
||||
}
|
||||
alertStore.filters.setFilters(filters);
|
||||
|
||||
if (p.params.m && silenceFormStore.data.fromBase64(p.params.m)) {
|
||||
silenceFormStore.toggle.show();
|
||||
}
|
||||
}, [alertStore, defaultFilters, settingsStore]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
const onPopState = useCallback(
|
||||
(event: PopStateEvent) => {
|
||||
event.preventDefault();
|
||||
const p = DecodeLocationSearch(window.location.search);
|
||||
alertStore.filters.setWithoutLocation(p.params.q);
|
||||
},
|
||||
[alertStore]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
window.onpopstate = onPopState;
|
||||
return () => {
|
||||
window.onpopstate = () => {};
|
||||
useEffect(() => {
|
||||
let filters;
|
||||
// parse and decode request query args
|
||||
const p: {
|
||||
params: {
|
||||
q: string[];
|
||||
m?: string;
|
||||
};
|
||||
}, [onPopState]);
|
||||
defaultsUsed: boolean;
|
||||
} = DecodeLocationSearch(window.location.search);
|
||||
// p.defaultsUsed means that karma URI didn't have ?q=foo query args
|
||||
if (p.defaultsUsed) {
|
||||
// no ?q=foo set, use defaults saved by the user or from backend config
|
||||
if (settingsStore.savedFilters.config.present) {
|
||||
filters = settingsStore.savedFilters.config.filters;
|
||||
} else {
|
||||
filters = defaultFilters;
|
||||
}
|
||||
} else {
|
||||
// user passed ?q=foo, use it as initial filters
|
||||
filters = p.params.q;
|
||||
}
|
||||
alertStore.filters.setFilters(filters);
|
||||
|
||||
const prefersColorScheme = useMediaPredicate("(prefers-color-scheme)");
|
||||
const prefersDark = useMediaPredicate("(prefers-color-scheme: dark)");
|
||||
if (p.params.m && silenceFormStore.data.fromBase64(p.params.m)) {
|
||||
silenceFormStore.toggle.show();
|
||||
}
|
||||
}, [alertStore, defaultFilters, settingsStore]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
return (
|
||||
<ErrorBoundary>
|
||||
<span data-theme={`${settingsStore.themeConfig.config.theme}`} />
|
||||
<ThemeContext.Provider
|
||||
value={{
|
||||
isDark:
|
||||
settingsStore.themeConfig.config.theme ===
|
||||
settingsStore.themeConfig.options.auto.value &&
|
||||
prefersColorScheme
|
||||
? prefersDark
|
||||
: settingsStore.themeConfig.config.theme ===
|
||||
settingsStore.themeConfig.options.dark.value,
|
||||
reactSelectStyles:
|
||||
settingsStore.themeConfig.config.theme ===
|
||||
settingsStore.themeConfig.options.auto.value &&
|
||||
prefersColorScheme
|
||||
? prefersDark
|
||||
? ReactSelectStyles(ReactSelectColors.Dark)
|
||||
: ReactSelectStyles(ReactSelectColors.Light)
|
||||
: settingsStore.themeConfig.config.theme ===
|
||||
settingsStore.themeConfig.options.dark.value
|
||||
const onPopState = useCallback(
|
||||
(event: PopStateEvent) => {
|
||||
event.preventDefault();
|
||||
const p = DecodeLocationSearch(window.location.search);
|
||||
alertStore.filters.setWithoutLocation(p.params.q);
|
||||
},
|
||||
[alertStore]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
window.onpopstate = onPopState;
|
||||
return () => {
|
||||
window.onpopstate = () => {};
|
||||
};
|
||||
}, [onPopState]);
|
||||
|
||||
const prefersColorScheme = useMediaPredicate("(prefers-color-scheme)");
|
||||
const prefersDark = useMediaPredicate("(prefers-color-scheme: dark)");
|
||||
|
||||
return (
|
||||
<ErrorBoundary>
|
||||
<span data-theme={`${settingsStore.themeConfig.config.theme}`} />
|
||||
<ThemeContext.Provider
|
||||
value={{
|
||||
isDark:
|
||||
settingsStore.themeConfig.config.theme ===
|
||||
settingsStore.themeConfig.options.auto.value && prefersColorScheme
|
||||
? prefersDark
|
||||
: settingsStore.themeConfig.config.theme ===
|
||||
settingsStore.themeConfig.options.dark.value,
|
||||
reactSelectStyles:
|
||||
settingsStore.themeConfig.config.theme ===
|
||||
settingsStore.themeConfig.options.auto.value && prefersColorScheme
|
||||
? prefersDark
|
||||
? ReactSelectStyles(ReactSelectColors.Dark)
|
||||
: ReactSelectStyles(ReactSelectColors.Light),
|
||||
animations: {
|
||||
duration: settingsStore.themeConfig.config.animations ? 500 : 0,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<BodyTheme />
|
||||
<React.Suspense fallback={null}>
|
||||
<NavBar
|
||||
alertStore={alertStore}
|
||||
settingsStore={settingsStore}
|
||||
silenceFormStore={silenceFormStore}
|
||||
/>
|
||||
<Grid
|
||||
alertStore={alertStore}
|
||||
settingsStore={settingsStore}
|
||||
silenceFormStore={silenceFormStore}
|
||||
/>
|
||||
<FaviconBadge alertStore={alertStore} />
|
||||
</React.Suspense>
|
||||
</ThemeContext.Provider>
|
||||
</ErrorBoundary>
|
||||
);
|
||||
}
|
||||
);
|
||||
: ReactSelectStyles(ReactSelectColors.Light)
|
||||
: settingsStore.themeConfig.config.theme ===
|
||||
settingsStore.themeConfig.options.dark.value
|
||||
? ReactSelectStyles(ReactSelectColors.Dark)
|
||||
: ReactSelectStyles(ReactSelectColors.Light),
|
||||
animations: {
|
||||
duration: settingsStore.themeConfig.config.animations ? 500 : 0,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<BodyTheme />
|
||||
<React.Suspense fallback={null}>
|
||||
<NavBar
|
||||
alertStore={alertStore}
|
||||
settingsStore={settingsStore}
|
||||
silenceFormStore={silenceFormStore}
|
||||
/>
|
||||
<Grid
|
||||
alertStore={alertStore}
|
||||
settingsStore={settingsStore}
|
||||
silenceFormStore={silenceFormStore}
|
||||
/>
|
||||
<FaviconBadge alertStore={alertStore} />
|
||||
</React.Suspense>
|
||||
</ThemeContext.Provider>
|
||||
</ErrorBoundary>
|
||||
);
|
||||
});
|
||||
|
||||
export { App };
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
import React, { FunctionComponent, ReactNode, useState } from "react";
|
||||
import React, { FC, ReactNode, useState } from "react";
|
||||
|
||||
import { ToggleIcon } from "Components/ToggleIcon";
|
||||
|
||||
const Trigger: FunctionComponent<{ text: string; isOpen: boolean }> = ({
|
||||
text,
|
||||
isOpen,
|
||||
}) => (
|
||||
const Trigger: FC<{ text: string; isOpen: boolean }> = ({ text, isOpen }) => (
|
||||
<div className="d-flex flex-row justify-content-between">
|
||||
<div>{text}</div>
|
||||
<div>
|
||||
@@ -14,7 +11,7 @@ const Trigger: FunctionComponent<{ text: string; isOpen: boolean }> = ({
|
||||
</div>
|
||||
);
|
||||
|
||||
const Accordion: FunctionComponent<{
|
||||
const Accordion: FC<{
|
||||
text: string;
|
||||
content: ReactNode;
|
||||
defaultIsOpen?: boolean;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { FunctionComponent, useState, useEffect } from "react";
|
||||
import React, { FC, useState, useEffect } from "react";
|
||||
|
||||
import parseISO from "date-fns/parseISO";
|
||||
import differenceInSeconds from "date-fns/differenceInSeconds";
|
||||
@@ -15,9 +15,7 @@ const formatLabel = (timestamp: string) => {
|
||||
});
|
||||
};
|
||||
|
||||
export const DateFromNow: FunctionComponent<{ timestamp: string }> = ({
|
||||
timestamp,
|
||||
}) => {
|
||||
export const DateFromNow: FC<{ timestamp: string }> = ({ timestamp }) => {
|
||||
const [label, setLabel] = useState<string>(formatLabel(timestamp));
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import React, { FunctionComponent } from "react";
|
||||
import React, { FC } from "react";
|
||||
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faChevronDown } from "@fortawesome/free-solid-svg-icons/faChevronDown";
|
||||
|
||||
const ToggleIcon: FunctionComponent<{
|
||||
const ToggleIcon: FC<{
|
||||
isOpen: boolean;
|
||||
className?: string;
|
||||
onClick?: () => void;
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
import React, {
|
||||
Component,
|
||||
StatelessComponent,
|
||||
ReactNode,
|
||||
ErrorInfo,
|
||||
} from "react";
|
||||
import React, { Component, FC, ReactNode, ErrorInfo } from "react";
|
||||
|
||||
import { captureException } from "@sentry/browser";
|
||||
|
||||
@@ -16,7 +11,7 @@ interface InternalErrorProps {
|
||||
progressLeft: number;
|
||||
}
|
||||
|
||||
const InternalError: StatelessComponent<InternalErrorProps> = (props) => (
|
||||
const InternalError: FC<InternalErrorProps> = (props) => (
|
||||
<div className="text-placeholder screen-center">
|
||||
<div className="container-fluid text-center">
|
||||
<h1 className="display-1">
|
||||
@@ -78,7 +73,9 @@ class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
|
||||
componentDidCatch(error: Error, { componentStack }: ErrorInfo): void {
|
||||
if (this.state.cachedError === null) {
|
||||
this.setState({ cachedError: error });
|
||||
captureException(error, { contexts: { react: { componentStack } } });
|
||||
captureException(error, {
|
||||
contexts: { react: { componentStack } },
|
||||
});
|
||||
}
|
||||
// reload after 60s, this is to fix wall monitors automatically
|
||||
// but only if the timer isn't set yet
|
||||
|
||||
Reference in New Issue
Block a user