Skip to content

Commit

Permalink
Merge pull request #25 from seroanalytics/i15
Browse files Browse the repository at this point in the history
add end sesison button
  • Loading branch information
hillalex authored Oct 24, 2024
2 parents 0f19850 + b1e4979 commit b049fb8
Show file tree
Hide file tree
Showing 8 changed files with 71 additions and 6 deletions.
1 change: 1 addition & 0 deletions src/RootContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export enum ActionType {
SELECT_SCALE = "SELECT_SCALE",
SET_SPLINE_OPTIONS = "SET_SPLINE_OPTIONS",
SET_INDIVIDUAL_OPTIONS = "SET_INDIVIDUAL_OPTIONS",
SESSION_ENDED = "SESSION_ENDED"
}

export interface RootAction {
Expand Down
5 changes: 2 additions & 3 deletions src/components/ManageDatasets.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,8 @@ export function ManageDatasets() {
<Col xs={12} sm={{span: 6, offset: 3}}>
<Form>
<p><Info className={"me-2"}/>Files you upload are
only accessible to you and
will be deleted automatically when you close your
browser.</p>
only accessible to you. Files will be deleted automatically when you close your
browser, or instantly when you click the "End session" link on the top right.</p>
<fieldset>
{state.datasetNames.length > 0 &&
<ListDatasets/>
Expand Down
18 changes: 17 additions & 1 deletion src/components/TopNav.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import {Container, Nav, Navbar} from "react-bootstrap";
import ThemeSwitch from "./ThemeSwitch";
import React from "react";
import React, {useContext} from "react";
import {RootContext, RootDispatchContext} from "../RootContext";
import {dataService} from "../services/dataService";

interface Props {
theme: string
Expand All @@ -18,6 +20,15 @@ function GithubLogo() {
export default function TopNav({
theme, setTheme
}: Props) {

const state = useContext(RootContext);
const dispatch = useContext(RootDispatchContext);

const endSession = async () => {
await dataService(state.language, dispatch)
.endSession()
}

return <Navbar expand="lg" className={"bg-light"}>
<Container fluid>
<img alt="SeroViz logo"
Expand All @@ -31,6 +42,11 @@ export default function TopNav({
<Nav.Link href="/docs">Docs</Nav.Link>
</Nav>
</Navbar.Collapse>
<Nav>
<Nav.Link onClick={endSession}>
End session
</Nav.Link>
</Nav>
<ThemeSwitch theme={theme} setTheme={setTheme}></ThemeSwitch>
<a className="text-body-secondary"
href="https://github.com/seroanalytics/seroviz">
Expand Down
4 changes: 3 additions & 1 deletion src/reducers/rootReducer.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {AppState} from "../types";
import {ActionType, RootAction} from "../RootContext";
import {ActionType, initialState, RootAction} from "../RootContext";
import {datasetReducer} from "./datasetReducer";

export const rootReducer = (state: AppState, action: RootAction): AppState => {
Expand All @@ -26,6 +26,8 @@ export const rootReducer = (state: AppState, action: RootAction): AppState => {
return {...state, uploadError: null}
case ActionType.DATASET_NAMES_FETCHED:
return {...state, datasetNames: action.payload}
case ActionType.SESSION_ENDED:
return {...initialState}
default:
return datasetReducer(state, action)
}
Expand Down
7 changes: 7 additions & 0 deletions src/services/dataService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,13 @@ export class DataService {
.withError(ActionType.ERROR_ADDED)
.delete("/dataset/" + dataset + "/")
}

async endSession() {
return await this._api
.withSuccess(ActionType.SESSION_ENDED)
.ignoreErrors()
.delete("/session/")
}
}

export const dataService = (lang: string, dispatch: Dispatch<RootAction>) => new DataService(new APIService(lang, dispatch));
File renamed without changes.
29 changes: 29 additions & 0 deletions test/components/TopNav.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import {mockAppState, mockAxios, mockSuccess} from "../mocks";
import {userEvent} from "@testing-library/user-event";
import {render, screen} from "@testing-library/react";
import {
ActionType,
RootContext,
RootDispatchContext
} from "../../src/RootContext";
import TopNav from "../../src/components/TopNav";

test("user can end session", async () => {
mockAxios.onDelete(`/session/`)
.reply(200, mockSuccess("OK"));

let state = mockAppState();
const dispatch = jest.fn();
const user = userEvent.setup();

render(<RootContext.Provider value={state}>
<RootDispatchContext.Provider
value={dispatch}><TopNav theme={"light"} setTheme={jest.fn()}/>
</RootDispatchContext.Provider>
</RootContext.Provider>);

const links = screen.getAllByRole("button") as HTMLAnchorElement[];
const endSession = links.find(l => l.textContent === "End session")!!;
await user.click(endSession);
expect(dispatch.mock.calls[1][0].type).toBe(ActionType.SESSION_ENDED);
});
13 changes: 12 additions & 1 deletion test/rootReducer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
mockDatasetNames, mockDatasetSettings,
mockError
} from "./mocks";
import {ActionType} from "../src/RootContext";
import {ActionType, initialState} from "../src/RootContext";
import {rootReducer} from "../src/reducers/rootReducer";

describe("rootReducer", () => {
Expand Down Expand Up @@ -200,4 +200,15 @@ describe("rootReducer", () => {
{type: ActionType.DATASET_DELETED, payload: "d1"});
expect(newState.datasetNames).toEqual(["d2"]);
});

it("should revert to initial state on SESSION_DELETED", () => {
const state = mockAppState({
datasetNames: ["d1", "d2"],
selectedDataset: "d1",
selectedPlot: "individual"
});
const newState = rootReducer(state,
{type: ActionType.SESSION_ENDED, payload: null});
expect(newState).toEqual(initialState);
});
});

0 comments on commit b049fb8

Please sign in to comment.