From 842fecfd7d7ecff4a4e638db3556a3104971d05a Mon Sep 17 00:00:00 2001 From: "D. Ror" Date: Fri, 8 Mar 2024 10:52:52 -0500 Subject: [PATCH] Clean up goal redux to match other redux (#2974) --- src/components/App/DefaultState.ts | 4 +-- src/components/GoalTimeline/index.tsx | 5 +--- .../GoalTimeline/tests/GoalRedux.test.tsx | 18 ++++++------- .../GoalTimeline/tests/index.test.tsx | 8 +++--- .../ProjectScreen/CreateProjectActions.ts | 2 +- .../Redux/CharacterInventoryActions.ts | 8 +++--- .../tests/CharacterInventoryActions.test.tsx | 10 ++++---- src/goals/DefaultGoal/BaseGoalScreen.tsx | 2 +- src/goals/DefaultGoal/NextGoalScreen.tsx | 2 +- .../MergeDupsStep/SaveDeferButtons.tsx | 2 +- .../MergeDuplicates/Redux/MergeDupsActions.ts | 8 +++--- .../Redux/GoalActions.ts | 6 ++--- .../Redux/GoalReducer.ts | 2 +- .../Redux/GoalReduxTypes.ts} | 20 +++++++-------- .../Redux/ReviewEntriesActions.ts | 5 +--- .../Redux/tests/ReviewEntriesActions.test.tsx | 2 +- src/goals/ReviewEntries/tests/index.test.tsx | 2 +- src/rootReducer.ts | 2 +- src/types/goals.ts | 25 ++++++------------- src/types/index.ts | 2 +- 20 files changed, 60 insertions(+), 75 deletions(-) rename src/{components/GoalTimeline => goals}/Redux/GoalActions.ts (99%) rename src/{components/GoalTimeline => goals}/Redux/GoalReducer.ts (98%) rename src/{components/GoalTimeline/DefaultState.ts => goals/Redux/GoalReduxTypes.ts} (61%) diff --git a/src/components/App/DefaultState.ts b/src/components/App/DefaultState.ts index 25186a03dd..afb78a040e 100644 --- a/src/components/App/DefaultState.ts +++ b/src/components/App/DefaultState.ts @@ -1,4 +1,3 @@ -import { defaultState as goalTimelineState } from "components/GoalTimeline/DefaultState"; import { defaultState as loginState } from "components/Login/Redux/LoginReduxTypes"; import { defaultState as currentProjectState } from "components/Project/ProjectReduxTypes"; import { defaultState as exportProjectState } from "components/ProjectExport/Redux/ExportProjectReduxTypes"; @@ -6,6 +5,7 @@ import { defaultState as pronunciationsState } from "components/Pronunciations/R import { defaultState as treeViewState } from "components/TreeView/Redux/TreeViewReduxTypes"; import { defaultState as characterInventoryState } from "goals/CharacterInventory/Redux/CharacterInventoryReduxTypes"; import { defaultState as mergeDuplicateGoal } from "goals/MergeDuplicates/Redux/MergeDupsReduxTypes"; +import { defaultState as goalsState } from "goals/Redux/GoalReduxTypes"; import { defaultState as reviewEntriesState } from "goals/ReviewEntries/Redux/ReviewEntriesReduxTypes"; import { defaultState as analyticsState } from "types/Redux/analyticsReduxTypes"; @@ -23,7 +23,7 @@ export const defaultState = { pronunciationsState: { ...pronunciationsState }, //goal timeline and current goal - goalsState: { ...goalTimelineState }, + goalsState: { ...goalsState }, //merge duplicates goal and review deferred duplicates goal mergeDuplicateGoal: { ...mergeDuplicateGoal }, diff --git a/src/components/GoalTimeline/index.tsx b/src/components/GoalTimeline/index.tsx index b354192fe7..54954cbc59 100644 --- a/src/components/GoalTimeline/index.tsx +++ b/src/components/GoalTimeline/index.tsx @@ -10,10 +10,7 @@ import { useTranslation } from "react-i18next"; import { getCurrentPermissions, getGraylistEntries } from "backend"; import GoalList from "components/GoalTimeline/GoalList"; -import { - asyncAddGoal, - asyncGetUserEdits, -} from "components/GoalTimeline/Redux/GoalActions"; +import { asyncAddGoal, asyncGetUserEdits } from "goals/Redux/GoalActions"; import { StoreState } from "types"; import { Goal, GoalType } from "types/goals"; import { useAppDispatch, useAppSelector } from "types/hooks"; diff --git a/src/components/GoalTimeline/tests/GoalRedux.test.tsx b/src/components/GoalTimeline/tests/GoalRedux.test.tsx index 0a62d9bde8..2a2afbff6e 100644 --- a/src/components/GoalTimeline/tests/GoalRedux.test.tsx +++ b/src/components/GoalTimeline/tests/GoalRedux.test.tsx @@ -5,15 +5,6 @@ import "tests/reactI18nextMock"; import { Edit, MergeUndoIds, Permission, User, UserEdit } from "api/models"; import * as LocalStorage from "backend/localStorage"; import GoalTimeline from "components/GoalTimeline"; -import { - addCharInvChangesToGoal, - addCompletedMergeToGoal, - asyncAddGoal, - asyncAdvanceStep, - asyncGetUserEdits, - asyncUpdateGoal, - setCurrentGoal, -} from "components/GoalTimeline/Redux/GoalActions"; import { CharacterChange, CharacterStatus, @@ -28,6 +19,15 @@ import { ReviewDeferredDups, } from "goals/MergeDuplicates/MergeDupsTypes"; import { goalDataMock } from "goals/MergeDuplicates/Redux/tests/MergeDupsDataMock"; +import { + addCharInvChangesToGoal, + addCompletedMergeToGoal, + asyncAddGoal, + asyncAdvanceStep, + asyncGetUserEdits, + asyncUpdateGoal, + setCurrentGoal, +} from "goals/Redux/GoalActions"; import { setupStore } from "store"; import { GoalStatus, GoalType } from "types/goals"; import { Path } from "types/path"; diff --git a/src/components/GoalTimeline/tests/index.test.tsx b/src/components/GoalTimeline/tests/index.test.tsx index 8ba3017ee0..6ac4e07b3e 100644 --- a/src/components/GoalTimeline/tests/index.test.tsx +++ b/src/components/GoalTimeline/tests/index.test.tsx @@ -7,19 +7,19 @@ import "tests/reactI18nextMock"; import { Permission } from "api/models"; import GoalTimeline, { createSuggestionData } from "components/GoalTimeline"; -import { defaultState } from "components/GoalTimeline/DefaultState"; -import { Goal, GoalType, GoalsState } from "types/goals"; +import { type GoalsState, defaultState } from "goals/Redux/GoalReduxTypes"; +import { Goal, GoalType } from "types/goals"; import { goalTypeToGoal } from "utilities/goalUtilities"; jest.mock("backend", () => ({ getCurrentPermissions: () => mockGetCurrentPermissions(), getGraylistEntries: (maxLists: number) => mockGetGraylistEntries(maxLists), })); -jest.mock("components/GoalTimeline/Redux/GoalActions", () => ({ +jest.mock("components/Pronunciations/Recorder"); +jest.mock("goals/Redux/GoalActions", () => ({ asyncAddGoal: (goal: Goal) => mockChooseGoal(goal), asyncGetUserEdits: () => jest.fn(), })); -jest.mock("components/Pronunciations/Recorder"); jest.mock("types/hooks", () => { return { ...jest.requireActual("types/hooks"), diff --git a/src/components/ProjectScreen/CreateProjectActions.ts b/src/components/ProjectScreen/CreateProjectActions.ts index 7270655fc4..25dedabca9 100644 --- a/src/components/ProjectScreen/CreateProjectActions.ts +++ b/src/components/ProjectScreen/CreateProjectActions.ts @@ -1,8 +1,8 @@ import { WritingSystem } from "api/models"; import { createProject, finishUploadLift, getProject } from "backend"; import router from "browserRouter"; -import { asyncCreateUserEdits } from "components/GoalTimeline/Redux/GoalActions"; import { setNewCurrentProject } from "components/Project/ProjectActions"; +import { asyncCreateUserEdits } from "goals/Redux/GoalActions"; import { StoreStateDispatch } from "types/Redux/actions"; import { Path } from "types/path"; import { newProject } from "types/project"; diff --git a/src/goals/CharacterInventory/Redux/CharacterInventoryActions.ts b/src/goals/CharacterInventory/Redux/CharacterInventoryActions.ts index c14ac5bc33..56d02e5a6c 100644 --- a/src/goals/CharacterInventory/Redux/CharacterInventoryActions.ts +++ b/src/goals/CharacterInventory/Redux/CharacterInventoryActions.ts @@ -3,10 +3,6 @@ import { Action, PayloadAction } from "@reduxjs/toolkit"; import { Project } from "api/models"; import { getFrontierWords } from "backend"; import router from "browserRouter"; -import { - addCharInvChangesToGoal, - asyncUpdateGoal, -} from "components/GoalTimeline/Redux/GoalActions"; import { asyncUpdateCurrentProject } from "components/Project/ProjectActions"; import { CharacterStatus, @@ -27,6 +23,10 @@ import { CharacterSetEntry, getCharacterStatus, } from "goals/CharacterInventory/Redux/CharacterInventoryReduxTypes"; +import { + addCharInvChangesToGoal, + asyncUpdateGoal, +} from "goals/Redux/GoalActions"; import { StoreState } from "types"; import { StoreStateDispatch } from "types/Redux/actions"; import { Path } from "types/path"; diff --git a/src/goals/CharacterInventory/Redux/tests/CharacterInventoryActions.test.tsx b/src/goals/CharacterInventory/Redux/tests/CharacterInventoryActions.test.tsx index 1151c04b77..1a71e2c5ba 100644 --- a/src/goals/CharacterInventory/Redux/tests/CharacterInventoryActions.test.tsx +++ b/src/goals/CharacterInventory/Redux/tests/CharacterInventoryActions.test.tsx @@ -27,15 +27,15 @@ jest.mock("backend", () => ({ getFrontierWords: (...args: any[]) => mockGetFrontierWords(...args), })); jest.mock("browserRouter"); -jest.mock("components/GoalTimeline/Redux/GoalActions", () => ({ - asyncUpdateGoal: (...args: any[]) => mockAsyncUpdateGoal(...args), - addCharInvChangesToGoal: (...args: any[]) => - mockAddCharInvChangesToGoal(...args), -})); jest.mock("components/Project/ProjectActions", () => ({ asyncUpdateCurrentProject: (...args: any[]) => mockAsyncUpdateCurrentProject(...args), })); +jest.mock("goals/Redux/GoalActions", () => ({ + asyncUpdateGoal: (...args: any[]) => mockAsyncUpdateGoal(...args), + addCharInvChangesToGoal: (...args: any[]) => + mockAddCharInvChangesToGoal(...args), +})); const mockAddCharInvChangesToGoal = jest.fn(); const mockAsyncUpdateCurrentProject = jest.fn(); diff --git a/src/goals/DefaultGoal/BaseGoalScreen.tsx b/src/goals/DefaultGoal/BaseGoalScreen.tsx index dbcb5fd7f4..3e7b4fbefb 100644 --- a/src/goals/DefaultGoal/BaseGoalScreen.tsx +++ b/src/goals/DefaultGoal/BaseGoalScreen.tsx @@ -1,11 +1,11 @@ import loadable from "@loadable/component"; import { ReactElement, useEffect } from "react"; -import { setCurrentGoal } from "components/GoalTimeline/Redux/GoalActions"; import PageNotFound from "components/PageNotFound/component"; import DisplayProgress from "goals/DefaultGoal/DisplayProgress"; import Loading from "goals/DefaultGoal/Loading"; import { clearTree } from "goals/MergeDuplicates/Redux/MergeDupsActions"; +import { setCurrentGoal } from "goals/Redux/GoalActions"; import { resetReviewEntries } from "goals/ReviewEntries/Redux/ReviewEntriesActions"; import { StoreState } from "types"; import { Goal, GoalStatus, GoalType } from "types/goals"; diff --git a/src/goals/DefaultGoal/NextGoalScreen.tsx b/src/goals/DefaultGoal/NextGoalScreen.tsx index ff4d45f03d..f001c263a9 100644 --- a/src/goals/DefaultGoal/NextGoalScreen.tsx +++ b/src/goals/DefaultGoal/NextGoalScreen.tsx @@ -1,9 +1,9 @@ import { ReactElement } from "react"; import { useNavigate } from "react-router-dom"; -import { asyncAddGoal } from "components/GoalTimeline/Redux/GoalActions"; import PageNotFound from "components/PageNotFound/component"; import MergeDupsContinueDialog from "goals/MergeDuplicates/MergeDupsContinueDialog"; +import { asyncAddGoal } from "goals/Redux/GoalActions"; import { StoreState } from "types"; import { GoalType } from "types/goals"; import { useAppDispatch, useAppSelector } from "types/hooks"; diff --git a/src/goals/MergeDuplicates/MergeDupsStep/SaveDeferButtons.tsx b/src/goals/MergeDuplicates/MergeDupsStep/SaveDeferButtons.tsx index 2417432cec..d1a4655989 100644 --- a/src/goals/MergeDuplicates/MergeDupsStep/SaveDeferButtons.tsx +++ b/src/goals/MergeDuplicates/MergeDupsStep/SaveDeferButtons.tsx @@ -3,12 +3,12 @@ import { ReactElement, useState } from "react"; import { useTranslation } from "react-i18next"; import { LoadingButton } from "components/Buttons"; -import { asyncAdvanceStep } from "components/GoalTimeline/Redux/GoalActions"; import { deferMerge, mergeAll, setSidebar, } from "goals/MergeDuplicates/Redux/MergeDupsActions"; +import { asyncAdvanceStep } from "goals/Redux/GoalActions"; import { useAppDispatch } from "types/hooks"; import theme from "types/theme"; diff --git a/src/goals/MergeDuplicates/Redux/MergeDupsActions.ts b/src/goals/MergeDuplicates/Redux/MergeDupsActions.ts index dd753a3683..25ef8cbdf2 100644 --- a/src/goals/MergeDuplicates/Redux/MergeDupsActions.ts +++ b/src/goals/MergeDuplicates/Redux/MergeDupsActions.ts @@ -2,10 +2,6 @@ import { Action, PayloadAction } from "@reduxjs/toolkit"; import { Word } from "api/models"; import * as backend from "backend"; -import { - addCompletedMergeToGoal, - asyncUpdateGoal, -} from "components/GoalTimeline/Redux/GoalActions"; import { defaultSidebar, MergeTreeReference, @@ -38,6 +34,10 @@ import { OrderSensePayload, SetVernacularPayload, } from "goals/MergeDuplicates/Redux/MergeDupsReduxTypes"; +import { + addCompletedMergeToGoal, + asyncUpdateGoal, +} from "goals/Redux/GoalActions"; import { StoreState } from "types"; import { StoreStateDispatch } from "types/Redux/actions"; diff --git a/src/components/GoalTimeline/Redux/GoalActions.ts b/src/goals/Redux/GoalActions.ts similarity index 99% rename from src/components/GoalTimeline/Redux/GoalActions.ts rename to src/goals/Redux/GoalActions.ts index 8fefda2b4c..d798161155 100644 --- a/src/components/GoalTimeline/Redux/GoalActions.ts +++ b/src/goals/Redux/GoalActions.ts @@ -5,6 +5,8 @@ import * as Backend from "backend"; import { getDuplicates, getGraylistEntries } from "backend"; import { getCurrentUser, getProjectId } from "backend/localStorage"; import router from "browserRouter"; +import { CharacterChange } from "goals/CharacterInventory/CharacterInventoryTypes"; +import { dispatchMergeStepData } from "goals/MergeDuplicates/Redux/MergeDupsActions"; import { addCharInvChangesToGoalAction, addCompletedMergeToGoalAction, @@ -15,9 +17,7 @@ import { setGoalDataAction, setGoalStatusAction, updateStepFromDataAction, -} from "components/GoalTimeline/Redux/GoalReducer"; -import { CharacterChange } from "goals/CharacterInventory/CharacterInventoryTypes"; -import { dispatchMergeStepData } from "goals/MergeDuplicates/Redux/MergeDupsActions"; +} from "goals/Redux/GoalReducer"; import { EntryEdit } from "goals/ReviewEntries/ReviewEntriesTypes"; import { StoreState } from "types"; import { StoreStateDispatch } from "types/Redux/actions"; diff --git a/src/components/GoalTimeline/Redux/GoalReducer.ts b/src/goals/Redux/GoalReducer.ts similarity index 98% rename from src/components/GoalTimeline/Redux/GoalReducer.ts rename to src/goals/Redux/GoalReducer.ts index a54b8b3141..64da779845 100644 --- a/src/components/GoalTimeline/Redux/GoalReducer.ts +++ b/src/goals/Redux/GoalReducer.ts @@ -1,10 +1,10 @@ import { createSlice } from "@reduxjs/toolkit"; -import { defaultState } from "components/GoalTimeline/DefaultState"; import { MergeDupsData, MergesCompleted, } from "goals/MergeDuplicates/MergeDupsTypes"; +import { defaultState } from "goals/Redux/GoalReduxTypes"; import { EntriesEdited, EntryEdit, diff --git a/src/components/GoalTimeline/DefaultState.ts b/src/goals/Redux/GoalReduxTypes.ts similarity index 61% rename from src/components/GoalTimeline/DefaultState.ts rename to src/goals/Redux/GoalReduxTypes.ts index aa0ec6565c..e27e8b3261 100644 --- a/src/components/GoalTimeline/DefaultState.ts +++ b/src/goals/Redux/GoalReduxTypes.ts @@ -1,4 +1,13 @@ -import { Goal, GoalsState, GoalType } from "types/goals"; +import { Goal, GoalType } from "types/goals"; + +// The representation of goals in the redux store +export interface GoalsState { + allGoalTypes: GoalType[]; + currentGoal: Goal; + goalTypeSuggestions: GoalType[]; + history: Goal[]; + previousGoalType: GoalType; +} // GoalType.ReviewDeferredDups is also implemented, // but is conditionally available @@ -15,12 +24,3 @@ export const defaultState: GoalsState = { history: [], previousGoalType: GoalType.Default, }; - -export function emptyGoalState(): GoalsState { - return { - ...defaultState, - allGoalTypes: [], - currentGoal: { ...new Goal(), guid: expect.any(String) }, - goalTypeSuggestions: [], - }; -} diff --git a/src/goals/ReviewEntries/Redux/ReviewEntriesActions.ts b/src/goals/ReviewEntries/Redux/ReviewEntriesActions.ts index f8e002b989..039afd8816 100644 --- a/src/goals/ReviewEntries/Redux/ReviewEntriesActions.ts +++ b/src/goals/ReviewEntries/Redux/ReviewEntriesActions.ts @@ -2,11 +2,8 @@ import { Action, PayloadAction } from "@reduxjs/toolkit"; import { Pronunciation, Sense, Word } from "api/models"; import * as backend from "backend"; -import { - addEntryEditToGoal, - asyncUpdateGoal, -} from "components/GoalTimeline/Redux/GoalActions"; import { uploadFileFromPronunciation } from "components/Pronunciations/utilities"; +import { addEntryEditToGoal, asyncUpdateGoal } from "goals/Redux/GoalActions"; import { deleteWordAction, resetReviewEntriesAction, diff --git a/src/goals/ReviewEntries/Redux/tests/ReviewEntriesActions.test.tsx b/src/goals/ReviewEntries/Redux/tests/ReviewEntriesActions.test.tsx index a078a11340..696f6a0e3c 100644 --- a/src/goals/ReviewEntries/Redux/tests/ReviewEntriesActions.test.tsx +++ b/src/goals/ReviewEntries/Redux/tests/ReviewEntriesActions.test.tsx @@ -46,7 +46,7 @@ jest.mock("backend", () => ({ updateWord: (word: Word) => mockUpdateWord(word), uploadAudio: (args: any[]) => mockUploadAudio(...args), })); -jest.mock("components/GoalTimeline/Redux/GoalActions", () => ({ +jest.mock("goals/Redux/GoalActions", () => ({ addEntryEditToGoal: () => jest.fn(), asyncUpdateGoal: () => jest.fn(), })); diff --git a/src/goals/ReviewEntries/tests/index.test.tsx b/src/goals/ReviewEntries/tests/index.test.tsx index 491a28ebd6..aeaccd2480 100644 --- a/src/goals/ReviewEntries/tests/index.test.tsx +++ b/src/goals/ReviewEntries/tests/index.test.tsx @@ -38,7 +38,7 @@ jest.mock("backend", () => ({ getFrontierWords: (...args: any[]) => mockGetFrontierWords(...args), })); jest.mock("components/TreeView", () => "div"); -jest.mock("components/GoalTimeline/Redux/GoalActions", () => ({})); +jest.mock("goals/Redux/GoalActions", () => ({})); jest.mock("types/hooks", () => ({ useAppDispatch: () => jest.fn(), })); diff --git a/src/rootReducer.ts b/src/rootReducer.ts index edb50d192b..44f7357bea 100644 --- a/src/rootReducer.ts +++ b/src/rootReducer.ts @@ -1,6 +1,5 @@ import { combineReducers, Reducer } from "redux"; -import goalsReducer from "components/GoalTimeline/Redux/GoalReducer"; import loginReducer from "components/Login/Redux/LoginReducer"; import projectReducer from "components/Project/ProjectReducer"; import exportProjectReducer from "components/ProjectExport/Redux/ExportProjectReducer"; @@ -8,6 +7,7 @@ import pronunciationsReducer from "components/Pronunciations/Redux/Pronunciation import treeViewReducer from "components/TreeView/Redux/TreeViewReducer"; import characterInventoryReducer from "goals/CharacterInventory/Redux/CharacterInventoryReducer"; import mergeDupStepReducer from "goals/MergeDuplicates/Redux/MergeDupsReducer"; +import goalsReducer from "goals/Redux/GoalReducer"; import reviewEntriesReducer from "goals/ReviewEntries/Redux/ReviewEntriesReducer"; import { StoreState } from "types"; import analyticsReducer from "types/Redux/analytics"; diff --git a/src/types/goals.ts b/src/types/goals.ts index bc8baab366..716b5d9300 100644 --- a/src/types/goals.ts +++ b/src/types/goals.ts @@ -1,17 +1,17 @@ import { v4 } from "uuid"; -import { User } from "api/models"; +import { type User } from "api/models"; import { - CharInvChanges, - CharInvData, - CharInvStepData, + type CharInvChanges, + type CharInvData, + type CharInvStepData, } from "goals/CharacterInventory/CharacterInventoryTypes"; import { - MergeDupsData, - MergeStepData, - MergesCompleted, + type MergeDupsData, + type MergeStepData, + type MergesCompleted, } from "goals/MergeDuplicates/MergeDupsTypes"; -import { EntriesEdited } from "goals/ReviewEntries/ReviewEntriesTypes"; +import { type EntriesEdited } from "goals/ReviewEntries/ReviewEntriesTypes"; import { newUser } from "types/user"; export type GoalData = CharInvData | MergeDupsData; @@ -23,15 +23,6 @@ export interface GoalProps { goal?: Goal; } -// The representation of goals in the redux store -export interface GoalsState { - allGoalTypes: GoalType[]; - currentGoal: Goal; - goalTypeSuggestions: GoalType[]; - history: Goal[]; - previousGoalType: GoalType; -} - // The enum value is a permanent id for UserEdits and should not be changed. export enum GoalType { Default = -1, diff --git a/src/types/index.ts b/src/types/index.ts index 024d8c07b1..3a90814fb3 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -5,9 +5,9 @@ import { PronunciationsState } from "components/Pronunciations/Redux/Pronunciati import { TreeViewState } from "components/TreeView/Redux/TreeViewReduxTypes"; import { CharacterInventoryState } from "goals/CharacterInventory/Redux/CharacterInventoryReduxTypes"; import { MergeTreeState } from "goals/MergeDuplicates/Redux/MergeDupsReduxTypes"; +import { GoalsState } from "goals/Redux/GoalReduxTypes"; import { ReviewEntriesState } from "goals/ReviewEntries/Redux/ReviewEntriesReduxTypes"; import { AnalyticsState } from "types/Redux/analyticsReduxTypes"; -import { GoalsState } from "types/goals"; //root store structure export interface StoreState {