Skip to content

Commit 369bc32

Browse files
committed
feat(explorer): replace play/pause button with a Refresh button
+ Add a 'Off' option in the update interval select to replace the 'pause'.
1 parent 98890a8 commit 369bc32

File tree

10 files changed

+78
-55
lines changed

10 files changed

+78
-55
lines changed

mithril-explorer/__tests__/store.test.js

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ import default_available_aggregators from "@/aggregators-list";
22
import { signedEntityType } from "@/constants";
33
import { poolsSlice } from "@/store/poolsSlice";
44
import {
5+
changeRefreshSeed,
56
removeSelectedAggregator,
67
selectAggregator,
78
settingsSlice,
89
setUpdateInterval,
9-
toggleAutoUpdate,
1010
} from "@/store/settingsSlice";
1111
import { saveToLocalStorage, storeBuilder } from "@/store/store";
1212
import { waitFor } from "@testing-library/react";
@@ -67,24 +67,47 @@ describe("Store Initialization", () => {
6767
expect(store.getState()).toEqual(expected);
6868
});
6969

70-
it("Can toggle autoUpdate", () => {
71-
const store = initStore();
72-
73-
store.dispatch(toggleAutoUpdate());
74-
expect(store.getState().settings.autoUpdate).toEqual(false);
70+
it("Can change refreshSeed", () => {
71+
const initialSeed = 123;
72+
const store = initStore({
73+
settings: {
74+
refreshSeed: initialSeed,
75+
...settingsSlice.getInitialState(),
76+
},
77+
});
7578

76-
store.dispatch(toggleAutoUpdate());
77-
expect(store.getState().settings.autoUpdate).toEqual(true);
79+
store.dispatch(changeRefreshSeed());
80+
expect(store.getState().settings.refreshSeed).not.toEqual(initialSeed);
7881
});
7982

80-
it("Can change updateInterval", () => {
81-
const store = initStore();
83+
it("Set updateInterval to a number", () => {
84+
const store = initStore({
85+
settings: {
86+
updateInterval: 0,
87+
...settingsSlice.getInitialState(),
88+
},
89+
});
8290
const expected = 124325;
8391

8492
store.dispatch(setUpdateInterval(expected));
8593
expect(store.getState().settings.updateInterval).toEqual(expected);
8694
});
8795

96+
it.each(["string", 1.123, "143", null, undefined])(
97+
"Set updateInterval to something that is not an integer should yield undefined ('%s')",
98+
(value) => {
99+
const store = initStore({
100+
settings: {
101+
updateInterval: 1000,
102+
...settingsSlice.getInitialState(),
103+
},
104+
});
105+
106+
store.dispatch(setUpdateInterval(value));
107+
expect(store.getState().settings.updateInterval).toEqual(undefined);
108+
},
109+
);
110+
88111
it("Can change selectedAggregator", () => {
89112
const store = initStore();
90113
const expected = default_available_aggregators[2];

mithril-explorer/src/components/AggregatorStatus/index.js

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export default function AggregatorStatus() {
6262
const aggregatorStatusEndpoint = useSelector((state) => `${selectedAggregator(state)}/status`);
6363
const [registrationPageUrl, setRegistrationPageUrl] = useState(undefined);
6464
const [inOutRegistrationsPageUrl, setInOutRegistrationsPageUrl] = useState(undefined);
65-
const autoUpdate = useSelector((state) => state.settings.autoUpdate);
65+
const refreshSeed = useSelector((state) => state.settings.refreshSeed);
6666
const updateInterval = useSelector((state) => state.settings.updateInterval);
6767
const [fallbackToEpochSetting, setFallbackToEpochSetting] = useState(false);
6868
const [showContent, setShowContent] = useState(true);
@@ -86,13 +86,11 @@ export default function AggregatorStatus() {
8686
// Fetch it once without waiting
8787
fetchAggregatorStatus();
8888

89-
if (autoUpdate) {
90-
const interval = setInterval(() => {
91-
fetchAggregatorStatus();
92-
}, updateInterval);
89+
if (updateInterval) {
90+
const interval = setInterval(fetchAggregatorStatus, updateInterval);
9391
return () => clearInterval(interval);
9492
}
95-
}, [aggregatorStatusEndpoint, updateInterval, autoUpdate]);
93+
}, [aggregatorStatusEndpoint, updateInterval, refreshSeed]);
9694

9795
useEffect(() => {
9896
if (!checkUrl(currentAggregator)) {

mithril-explorer/src/components/Artifacts/CardanoDbSnapshotsList/index.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export default function CardanoDbSnapshotsList(props) {
1414
const artifactsEndpoint = useSelector(
1515
(state) => `${selectedAggregator(state)}/artifact/snapshots`,
1616
);
17-
const autoUpdate = useSelector((state) => state.settings.autoUpdate);
17+
const refreshSeed = useSelector((state) => state.settings.refreshSeed);
1818
const updateInterval = useSelector((state) => state.settings.updateInterval);
1919

2020
useEffect(() => {
@@ -31,11 +31,11 @@ export default function CardanoDbSnapshotsList(props) {
3131
// Fetch them once without waiting
3232
fetchSnapshots();
3333

34-
if (autoUpdate) {
34+
if (updateInterval) {
3535
const interval = setInterval(fetchSnapshots, updateInterval);
3636
return () => clearInterval(interval);
3737
}
38-
}, [artifactsEndpoint, updateInterval, autoUpdate]);
38+
}, [artifactsEndpoint, updateInterval, refreshSeed]);
3939

4040
function handleCertificateHashChange(hash) {
4141
setSelectedCertificateHash(hash);

mithril-explorer/src/components/Artifacts/CardanoStakeDistributionsList/index.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export default function CardanoStakeDistributionsList(props) {
1313
const artifactsEndpoint = useSelector(
1414
(state) => `${selectedAggregator(state)}/artifact/cardano-stake-distributions`,
1515
);
16-
const autoUpdate = useSelector((state) => state.settings.autoUpdate);
16+
const refreshSeed = useSelector((state) => state.settings.refreshSeed);
1717
const updateInterval = useSelector((state) => state.settings.updateInterval);
1818

1919
useEffect(() => {
@@ -30,11 +30,11 @@ export default function CardanoStakeDistributionsList(props) {
3030
// Fetch them once without waiting
3131
fetchCardanoStakeDistribution();
3232

33-
if (autoUpdate) {
33+
if (updateInterval) {
3434
const interval = setInterval(fetchCardanoStakeDistribution, updateInterval);
3535
return () => clearInterval(interval);
3636
}
37-
}, [artifactsEndpoint, updateInterval, autoUpdate]);
37+
}, [artifactsEndpoint, updateInterval, refreshSeed]);
3838

3939
function handleCertificateHashChange(hash) {
4040
setSelectedCertificateHash(hash);

mithril-explorer/src/components/Artifacts/CardanoTransactionsSnapshotsList/index.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export default function CardanoTransactionsSnapshotsList(props) {
1818
const artifactsEndpoint = useSelector(
1919
(state) => `${selectedAggregator(state)}/artifact/cardano-transactions`,
2020
);
21-
const autoUpdate = useSelector((state) => state.settings.autoUpdate);
21+
const refreshSeed = useSelector((state) => state.settings.refreshSeed);
2222
const updateInterval = useSelector((state) => state.settings.updateInterval);
2323
const currentAggregatorCapabilities = useSelector((state) =>
2424
selectedAggregatorCapabilities(state),
@@ -38,11 +38,11 @@ export default function CardanoTransactionsSnapshotsList(props) {
3838
// Fetch them once without waiting
3939
fetchSnapshots();
4040

41-
if (autoUpdate) {
41+
if (updateInterval) {
4242
const interval = setInterval(fetchSnapshots, updateInterval);
4343
return () => clearInterval(interval);
4444
}
45-
}, [artifactsEndpoint, updateInterval, autoUpdate]);
45+
}, [artifactsEndpoint, updateInterval, refreshSeed]);
4646

4747
function handleCertificateHashChange(hash) {
4848
setSelectedCertificateHash(hash);

mithril-explorer/src/components/Artifacts/CertificatesList/index.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export default function CertificatesList(props) {
1212
const [selectedCertificateHash, setSelectedCertificateHash] = useState(undefined);
1313
const aggregator = useSelector(selectedAggregator);
1414
const certificatesEndpoint = useSelector((state) => `${selectedAggregator(state)}/certificates`);
15-
const autoUpdate = useSelector((state) => state.settings.autoUpdate);
15+
const refreshSeed = useSelector((state) => state.settings.refreshSeed);
1616
const updateInterval = useSelector((state) => state.settings.updateInterval);
1717

1818
useEffect(() => {
@@ -29,11 +29,11 @@ export default function CertificatesList(props) {
2929
// Fetch them once without waiting
3030
fetchCertificates();
3131

32-
if (autoUpdate) {
32+
if (updateInterval) {
3333
const interval = setInterval(fetchCertificates, updateInterval);
3434
return () => clearInterval(interval);
3535
}
36-
}, [certificatesEndpoint, updateInterval, autoUpdate]);
36+
}, [certificatesEndpoint, updateInterval, refreshSeed]);
3737

3838
function handleCertificateHashChange(hash) {
3939
setSelectedCertificateHash(hash);

mithril-explorer/src/components/Artifacts/MithrilStakeDistributionsList/index.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export default function MithrilStakeDistributionsList(props) {
1313
const artifactsEndpoint = useSelector(
1414
(state) => `${selectedAggregator(state)}/artifact/mithril-stake-distributions`,
1515
);
16-
const autoUpdate = useSelector((state) => state.settings.autoUpdate);
16+
const refreshSeed = useSelector((state) => state.settings.refreshSeed);
1717
const updateInterval = useSelector((state) => state.settings.updateInterval);
1818

1919
useEffect(() => {
@@ -30,11 +30,11 @@ export default function MithrilStakeDistributionsList(props) {
3030
// Fetch them once without waiting
3131
fetchMithrilStakeDistribution();
3232

33-
if (autoUpdate) {
33+
if (updateInterval) {
3434
const interval = setInterval(fetchMithrilStakeDistribution, updateInterval);
3535
return () => clearInterval(interval);
3636
}
37-
}, [artifactsEndpoint, updateInterval, autoUpdate]);
37+
}, [artifactsEndpoint, updateInterval, refreshSeed]);
3838

3939
function handleCertificateHashChange(hash) {
4040
setSelectedCertificateHash(hash);

mithril-explorer/src/components/EpochSettings/index.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export default function EpochSettings() {
1313
const epochSettingsEndpoint = useSelector(
1414
(state) => `${selectedAggregator(state)}/epoch-settings`,
1515
);
16-
const autoUpdate = useSelector((state) => state.settings.autoUpdate);
16+
const refreshSeed = useSelector((state) => state.settings.refreshSeed);
1717
const updateInterval = useSelector((state) => state.settings.updateInterval);
1818
const [registrationPageUrl, setRegistrationPageUrl] = useState(undefined);
1919
const [inOutRegistrationsPageUrl, setInOutRegistrationsPageUrl] = useState(undefined);
@@ -32,11 +32,11 @@ export default function EpochSettings() {
3232
// Fetch it once without waiting
3333
fetchEpochSettings();
3434

35-
if (autoUpdate) {
35+
if (updateInterval) {
3636
const interval = setInterval(fetchEpochSettings, updateInterval);
3737
return () => clearInterval(interval);
3838
}
39-
}, [epochSettingsEndpoint, updateInterval, autoUpdate]);
39+
}, [epochSettingsEndpoint, updateInterval, refreshSeed]);
4040

4141
useEffect(() => {
4242
if (checkUrl(currentAggregator)) {

mithril-explorer/src/components/IntervalSetter/index.js

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,29 @@
11
import { useDispatch, useSelector } from "react-redux";
2-
import { Button, Col, Form, InputGroup } from "react-bootstrap";
3-
import { setUpdateInterval, toggleAutoUpdate } from "@/store/settingsSlice";
2+
import { Button, Col, Form, InputGroup, OverlayTrigger, Tooltip } from "react-bootstrap";
3+
import { setUpdateInterval, changeRefreshSeed } from "@/store/settingsSlice";
44

55
export default function IntervalSetter(props) {
6-
const autoUpdate = useSelector((state) => state.settings.autoUpdate);
76
const updateInterval = useSelector((state) => state.settings.updateInterval);
87
const dispatch = useDispatch();
98

109
return (
1110
<Form.Group as={Col} className={props.className}>
12-
<Form.Label>Update Interval:</Form.Label>
11+
<Form.Label>Auto refresh:</Form.Label>
1312
<InputGroup>
14-
<Button
15-
type="button"
16-
onClick={() => dispatch(toggleAutoUpdate())}
17-
variant={autoUpdate ? "primary" : "success"}>
18-
{autoUpdate ? "Pause ⏸" : "Resume ▶"}
13+
<Button type="button" onClick={() => dispatch(changeRefreshSeed())} variant="primary">
14+
Refresh
1915
</Button>
20-
<Form.Select
21-
value={updateInterval}
22-
onChange={(e) => dispatch(setUpdateInterval(e.target.value))}>
23-
<option value={1000}>1 seconds</option>
24-
<option value={5000}>5 seconds</option>
25-
<option value={10000}>10 seconds</option>
26-
</Form.Select>
16+
<OverlayTrigger overlay={<Tooltip>Set auto-refresh interval</Tooltip>}>
17+
<Form.Select
18+
aria-label="Auto refresh interval"
19+
value={updateInterval}
20+
onChange={(e) => dispatch(setUpdateInterval(parseInt(e.target.value)))}>
21+
<option value={undefined}>Off</option>
22+
<option value={1000}>1 second</option>
23+
<option value={5000}>5 seconds</option>
24+
<option value={10000}>10 seconds</option>
25+
</Form.Select>
26+
</OverlayTrigger>
2727
</InputGroup>
2828
</Form.Group>
2929
);

mithril-explorer/src/store/settingsSlice.js

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import { checkUrl } from "@/utils";
55
import { defaultAggregatorCapabilities } from "@/constants";
66

77
export const initialState = {
8-
autoUpdate: true,
98
updateInterval: 10000,
9+
refreshSeed: 0,
1010
selectedAggregator: default_available_aggregators[0],
1111
availableAggregators: default_available_aggregators,
1212
aggregatorCapabilities: defaultAggregatorCapabilities,
@@ -18,10 +18,12 @@ export const settingsSlice = createSlice({
1818
initialState: initialState,
1919
reducers: {
2020
setUpdateInterval: (state, action) => {
21-
state.updateInterval = action.payload;
21+
const interval = action.payload;
22+
state.updateInterval =
23+
!Number.isNaN(interval) && Number.isInteger(interval) ? interval : undefined;
2224
},
23-
toggleAutoUpdate: (state) => {
24-
state.autoUpdate = !state.autoUpdate;
25+
changeRefreshSeed: (state) => {
26+
state.refreshSeed = Math.random();
2527
},
2628
selectAggregator: (state, action) => {
2729
if (!checkUrl(action.payload)) {
@@ -80,7 +82,7 @@ export const addSettingsListeners = (listenerMiddleware) => {
8082

8183
export const {
8284
setUpdateInterval,
83-
toggleAutoUpdate,
85+
changeRefreshSeed,
8486
selectAggregator,
8587
removeSelectedAggregator,
8688
updateSelectedAggregatorCapabilities,

0 commit comments

Comments
 (0)