Skip to content

Commit db5ac2c

Browse files
committed
Improve error handling
Replace alert() and console.error() with toast notifications for error handling.
1 parent e269c97 commit db5ac2c

11 files changed

+211
-80
lines changed

src/ui/components/DropdownMenu.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,29 @@
11
import { ChangeEvent, FC, useEffect, useState, useCallback } from "react";
22
import { Form } from "react-bootstrap";
33

4+
import { useToastsContext } from "../hooks/useToasts";
5+
46
type DropdownMenuProps = {
57
onSelectFeatureConfigId: (featureId: string) => void;
68
};
79

810
const DropdownMenu: FC<DropdownMenuProps> = ({ onSelectFeatureConfigId }) => {
911
const [featureConfigs, setFeatureConfigs] = useState([]);
12+
const { addToast } = useToastsContext();
1013

1114
useEffect(() => {
1215
void (async () => {
1316
try {
1417
const configs = await browser.experiments.nimbus.getFeatureConfigs();
1518
setFeatureConfigs(configs);
1619
} catch (error) {
17-
console.error(error);
20+
addToast(
21+
`Error fetching feature configurations: ${(error as Error).message ?? String(error)}`,
22+
"danger",
23+
);
1824
}
1925
})();
20-
}, []);
26+
}, [addToast]);
2127

2228
const handleChange = useCallback((event: ChangeEvent<HTMLSelectElement>) => {
2329
onSelectFeatureConfigId(event.target.value);

src/ui/components/ExperimentBrowserPage.tsx

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import { FC, useCallback, useEffect, useState } from "react";
22
import { NimbusExperiment } from "@mozilla/nimbus-schemas";
33
import { Table, Button, Container, Form, Row, Col } from "react-bootstrap";
44

5+
import { useToastsContext } from "../hooks/useToasts";
6+
57
const PROD_URL =
68
"https://experimenter.services.mozilla.com/api/v6/experiments/";
79
const STAGE_URL =
@@ -21,6 +23,7 @@ const ExperimentBrowserPage: FC = () => {
2123
const [selectedBranches, setSelectedBranches] = useState<{
2224
[key: string]: string;
2325
}>({});
26+
const { addToast } = useToastsContext();
2427

2528
const fetchExperiments = useCallback(
2629
async (forceRefresh = false) => {
@@ -36,10 +39,13 @@ const ExperimentBrowserPage: FC = () => {
3639
);
3740
setExperiments(fetchedExperiments);
3841
} catch (error) {
39-
console.error("Error fetching experiments:", error);
42+
addToast(
43+
`Error fetching experiments: ${(error as Error).message ?? String(error)}`,
44+
"danger",
45+
);
4046
}
4147
},
42-
[environment, status],
48+
[environment, status, addToast],
4349
);
4450

4551
useEffect(() => {
@@ -55,19 +61,18 @@ const ExperimentBrowserPage: FC = () => {
5561
branchSlug,
5662
);
5763
if (result) {
58-
console.log("Enrollment successful");
59-
alert("Enrollment successful");
64+
addToast("Enrollment successful", "success");
6065
} else {
61-
console.log("Enrollment failed");
62-
alert("Enrollment failed");
66+
addToast("Enrollment failed", "danger");
6367
}
6468
} catch (error) {
65-
console.error(error);
66-
alert(error);
69+
addToast(
70+
`Error enrolling into experiment: ${(error as Error).message ?? String(error)}`,
71+
"danger",
72+
);
6773
}
6874
} else {
69-
console.log("Select a branch before enrolling");
70-
alert("Select a branch before enrolling");
75+
addToast("Select a branch before enrolling", "danger");
7176
}
7277
};
7378

src/ui/components/ExperimentStorePage.tsx

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { FC, useCallback, useEffect, useState } from "react";
22
import { Table, Button, Container } from "react-bootstrap";
33

4+
import { useToastsContext } from "../hooks/useToasts";
5+
46
interface NimbusEnrollment {
57
slug: string;
68
userFacingName: string;
@@ -12,16 +14,20 @@ interface NimbusEnrollment {
1214

1315
const ExperimentStorePage: FC = () => {
1416
const [experiments, setExperiments] = useState<NimbusEnrollment[]>([]);
17+
const { addToast } = useToastsContext();
1518

1619
const fetchExperiments = useCallback(async () => {
1720
try {
1821
const experimentStore =
1922
await browser.experiments.nimbus.getExperimentStore();
2023
setExperiments(experimentStore as NimbusEnrollment[]);
2124
} catch (error) {
22-
console.error("Error fetching experiments:", error);
25+
addToast(
26+
`Error fetching experiments: ${(error as Error).message ?? String(error)}`,
27+
"danger",
28+
);
2329
}
24-
}, [experiments]);
30+
}, [experiments, addToast]);
2531

2632
useEffect(() => {
2733
void fetchExperiments();
@@ -31,26 +37,32 @@ const ExperimentStorePage: FC = () => {
3137
async (slug: string) => {
3238
try {
3339
await browser.experiments.nimbus.unenroll(slug);
34-
alert("Unenrollment successful");
40+
addToast("Unenrollment successful", "success");
3541
await fetchExperiments();
3642
} catch (error) {
37-
console.error(`Error unenrolling from experiment ${slug}:`, error);
43+
addToast(
44+
`Error unenrolling from experiment: ${(error as Error).message ?? String(error)}`,
45+
"danger",
46+
);
3847
}
3948
},
40-
[fetchExperiments],
49+
[fetchExperiments, addToast],
4150
);
4251

4352
const deleteExperiment = useCallback(
4453
async (slug: string) => {
4554
try {
4655
await browser.experiments.nimbus.deleteInactiveEnrollment(slug);
47-
alert("Deletion successful");
56+
addToast("Deletion successful", "success");
4857
await fetchExperiments();
4958
} catch (error) {
50-
console.error(`Error deleting experiment ${slug}:`, error);
59+
addToast(
60+
`Error deleting experiment: ${(error as Error).message ?? String(error)}`,
61+
"danger",
62+
);
5163
}
5264
},
53-
[fetchExperiments],
65+
[fetchExperiments, addToast],
5466
);
5567

5668
return (

src/ui/components/FeatureConfigPage.tsx

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import { ChangeEvent, FC, useState, useCallback } from "react";
2-
import { Form, Container, Row, Col } from "react-bootstrap";
2+
import { Form, Container, Button, Row, Col } from "react-bootstrap";
33

4+
import { useToastsContext } from "../hooks/useToasts";
45
import DropdownMenu from "./DropdownMenu";
56

67
const FeatureConfigPage: FC = () => {
78
const [jsonInput, setJsonInput] = useState("");
89
const [selectedFeatureId, setSelectedFeatureId] = useState("");
910
const [isRollout, setIsRollout] = useState(false);
11+
const { addToast } = useToastsContext();
1012

1113
const handleInputChange = useCallback(
1214
(event: ChangeEvent<HTMLTextAreaElement>) => {
@@ -28,11 +30,9 @@ const FeatureConfigPage: FC = () => {
2830

2931
const handleEnrollClick = useCallback(async () => {
3032
if (selectedFeatureId === "") {
31-
console.log("Invalid Input: Select feature");
32-
alert("Invalid Input: Select feature");
33+
addToast("Invalid Input: Select feature", "danger");
3334
} else if (jsonInput === "") {
34-
console.log("Invalid Input: Enter JSON");
35-
alert("Invalid Input: Enter JSON");
35+
addToast("Invalid Input: Enter JSON", "danger");
3636
} else {
3737
try {
3838
const result = await browser.experiments.nimbus.enrollWithFeatureConfig(
@@ -42,18 +42,18 @@ const FeatureConfigPage: FC = () => {
4242
);
4343

4444
if (result) {
45-
console.log("Enrollment successful");
46-
alert("Enrollment successful");
45+
addToast("Enrollment successful", "success");
4746
} else {
48-
console.log("Enrollment failed");
49-
alert("Enrollment failed");
47+
addToast("Enrollment failed", "danger");
5048
}
5149
} catch (error) {
52-
console.error(error);
53-
alert(error);
50+
addToast(
51+
`Error enrolling into experiment: ${(error as Error).message ?? String(error)}`,
52+
"danger",
53+
);
5454
}
5555
}
56-
}, [jsonInput, selectedFeatureId, isRollout]);
56+
}, [jsonInput, selectedFeatureId, isRollout, addToast]);
5757

5858
return (
5959
<Container className="main-content p-2">
@@ -83,12 +83,12 @@ const FeatureConfigPage: FC = () => {
8383
className="text-input medium-input rounded p-3 font-monospace fs-6 grey-border"
8484
/>
8585
</Form.Group>
86-
<input
87-
type="submit"
88-
value="Enroll"
89-
className="mt-2 py-3 px-4 fs-5 border-0 w-100 rounded text-white"
86+
<Button
9087
onClick={handleEnrollClick}
91-
/>
88+
className="mt-2 py-3 px-4 fs-5 border-0 w-100 rounded text-white dark-button"
89+
>
90+
Enroll
91+
</Button>
9292
</Form>
9393
</Container>
9494
);

src/ui/components/JEXLDebuggerPage.tsx

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,26 @@ import {
88
} from "react";
99
import { Container, Row, Col, Form, Button } from "react-bootstrap";
1010

11+
import { useToastsContext } from "../hooks/useToasts";
1112
import { evaluateJexl } from "../jexlParser";
1213

1314
const JEXLDebuggerPage: FC = () => {
1415
const [clientContext, setClientContext] = useState({});
1516
const [jexlExpression, setJexlExpression] = useState("");
1617
const [output, setOutput] = useState("");
18+
const { addToast } = useToastsContext();
1719

1820
const fetchClientContext = useCallback(async () => {
1921
try {
2022
const context = await browser.experiments.nimbus.getClientContext();
2123
setClientContext(context);
2224
} catch (error) {
23-
console.error("Error fetching client context:", error);
25+
addToast(
26+
`Error fetching client context: ${(error as Error).message ?? String(error)}`,
27+
"danger",
28+
);
2429
}
25-
}, []);
30+
}, [addToast]);
2631

2732
useEffect(() => {
2833
void fetchClientContext();
@@ -44,10 +49,13 @@ const JEXLDebuggerPage: FC = () => {
4449
setOutput(result);
4550
}
4651
} catch (error) {
47-
console.error(error);
4852
setOutput("Error evaluating expression");
53+
addToast(
54+
`Error evaluating expression: ${(error as Error).message ?? String(error)}`,
55+
"danger",
56+
);
4957
}
50-
}, [jexlExpression, clientContext]);
58+
}, [jexlExpression, clientContext, addToast]);
5159

5260
const memoizedClientContextEntries = useMemo(
5361
() => Object.entries(clientContext),
@@ -67,12 +75,12 @@ const JEXLDebuggerPage: FC = () => {
6775
className="text-input rounded p-3 font-monospace fs-6 grey-border"
6876
rows={8}
6977
/>
70-
<input
78+
<Button
7179
onClick={handleEvaluateClick}
72-
value="Evaluate"
73-
type="submit"
74-
className="mt-2 py-2 px-4 fs-6 border-0 w-100 rounded text-white"
75-
/>
80+
className="mt-2 py-2 px-4 fs-6 border-0 w-100 rounded text-white dark-button"
81+
>
82+
Evaluate
83+
</Button>
7684
</Col>
7785
</Row>
7886
<hr className="section-line mx-2 mb-2 mt-1" />
Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
import { ChangeEvent, FC, useState, useCallback } from "react";
2-
import { Form, Container } from "react-bootstrap";
2+
import { Form, Container, Button } from "react-bootstrap";
33

4-
const MainPage: FC = () => {
4+
import { useToastsContext } from "../hooks/useToasts";
5+
6+
const RecipeEnrollmentPage: FC = () => {
57
const [jsonInput, setJsonInput] = useState("");
8+
const { addToast } = useToastsContext();
69

710
const handleInputChange = useCallback(
811
(event: ChangeEvent<HTMLTextAreaElement>) => {
@@ -18,18 +21,18 @@ const MainPage: FC = () => {
1821
);
1922

2023
if (result) {
21-
console.log("Enrollment successful");
22-
alert("Enrollment successful");
24+
addToast("Enrollment successful", "success");
2325
setJsonInput("");
2426
} else {
25-
console.log("Enrollment failed");
26-
alert("Enrollment failed");
27+
addToast("Enrollment failed", "danger");
2728
}
2829
} catch (error) {
29-
console.error(error);
30-
alert(error);
30+
addToast(
31+
`Error enrolling into experiment: ${(error as Error).message ?? String(error)}`,
32+
"danger",
33+
);
3134
}
32-
}, [jsonInput, setJsonInput]);
35+
}, [jsonInput, setJsonInput, addToast]);
3336

3437
return (
3538
<Container className="main-content m-0 p-2">
@@ -43,15 +46,15 @@ const MainPage: FC = () => {
4346
className="text-input long-input rounded p-4 font-monospace fs-6 grey-border"
4447
/>
4548
</Form.Group>
46-
<input
49+
<Button
4750
onClick={handleEnrollClick}
48-
value="Enroll"
49-
type="submit"
50-
className="mt-2 py-3 px-4 fs-5 border-0 w-100 rounded text-white"
51-
/>
51+
className="mt-2 py-3 px-4 fs-5 border-0 w-100 rounded text-white dark-button"
52+
>
53+
Enroll
54+
</Button>
5255
</Form>
5356
</Container>
5457
);
5558
};
5659

57-
export default MainPage;
60+
export default RecipeEnrollmentPage;

0 commit comments

Comments
 (0)