diff --git a/src/mapSearch/mapSearchPage.tsx b/src/mapSearch/mapSearchPage.tsx index 9b1b249..0c653c6 100644 --- a/src/mapSearch/mapSearchPage.tsx +++ b/src/mapSearch/mapSearchPage.tsx @@ -11,12 +11,14 @@ import BlockLoader from '../loader/blockLoader'; import { fetchPlotSearchAttributes, fetchPlotSearches, + fetchPlotSearchStages, fetchPlotSearchTypes, } from '../plotSearch/actions'; import { ApiAttributes } from '../api/types'; import { PlotSearch, + PlotSearchStage, PlotSearchSubtype, PlotSearchTarget, PlotSearchType, @@ -30,9 +32,11 @@ interface State { isFetchingPlotSearches: boolean; isFetchingPlotSearchAttributes: boolean; isFetchingPlotSearchTypes: boolean; + isFetchingPlotSearchStages: boolean; plotSearches: Array; plotSearchAttributes: ApiAttributes; plotSearchTypes: Array; + plotSearchStages: Array; favourite: Favourite; } @@ -41,12 +45,15 @@ interface Props { fetchPlotSearches: (payload?: { params: Record }) => void; fetchPlotSearchAttributes: () => void; fetchPlotSearchTypes: () => void; + fetchPlotSearchStages: () => void; isFetchingPlotSearches: boolean; isFetchingPlotSearchAttributes: boolean; isFetchingPlotSearchTypes: boolean; + isFetchingPlotSearchStages: boolean; plotSearches: Array; plotSearchAttributes: ApiAttributes; plotSearchTypes: Array; + plotSearchStages: Array; favourite: Favourite; } @@ -69,10 +76,13 @@ const MapSearchPage = (props: Props): JSX.Element => { fetchPlotSearches, fetchPlotSearchAttributes, fetchPlotSearchTypes, + fetchPlotSearchStages, isFetchingPlotSearches, isFetchingPlotSearchAttributes, isFetchingPlotSearchTypes, + isFetchingPlotSearchStages, plotSearchTypes, + plotSearchStages, plotSearches, favourite, } = props; @@ -127,11 +137,17 @@ const MapSearchPage = (props: Props): JSX.Element => { }, [id, plotSearches]); useEffect(() => { - fetchPlotSearches({ params: { search_class: searchClass } }); fetchPlotSearchAttributes(); fetchPlotSearchTypes(); + fetchPlotSearchStages(); }, []); + useEffect(() => { + if (!isFetchingPlotSearchStages && plotSearchStages.length > 0) { + fetchPlotSearches({ params: { search_class: searchClass } }); + } + }, [isFetchingPlotSearchStages]); + useEffect(() => { let newOptions = [...(plotSearchTypes || [])]; @@ -186,7 +202,8 @@ const MapSearchPage = (props: Props): JSX.Element => { if ( isFetchingPlotSearches || isFetchingPlotSearchAttributes || - isFetchingPlotSearchTypes + isFetchingPlotSearchTypes || + isFetchingPlotSearchStages ) { return ; } @@ -235,6 +252,8 @@ const mapStateToProps = (state: RootState): State => ({ isFetchingPlotSearchAttributes: state.plotSearch.isFetchingPlotSearchAttributes, isFetchingPlotSearchTypes: state.plotSearch.isFetchingPlotSearchTypes, + isFetchingPlotSearchStages: state.plotSearch.isFetchingPlotSearchStages, + plotSearchStages: state.plotSearch.plotSearchStages, favourite: state.favourite.favourite, }); @@ -242,4 +261,5 @@ export default connect(mapStateToProps, { fetchPlotSearches, fetchPlotSearchAttributes, fetchPlotSearchTypes, + fetchPlotSearchStages, })(MapSearchPage); diff --git a/src/plotSearch/actions.ts b/src/plotSearch/actions.ts index 6e49fbf..494debb 100644 --- a/src/plotSearch/actions.ts +++ b/src/plotSearch/actions.ts @@ -3,14 +3,18 @@ import { Action } from 'redux'; import { FETCH_PLOT_SEARCH_ATTRIBUTES, + FETCH_PLOT_SEARCH_STAGES, FETCH_PLOT_SEARCH_TYPES, FETCH_PLOT_SEARCHES, PLOT_SEARCH_ATTRIBUTES_NOT_FOUND, + PLOT_SEARCH_STAGES_NOT_FOUND, PLOT_SEARCH_TYPES_NOT_FOUND, PLOT_SEARCHES_NOT_FOUND, PlotSearch, + PlotSearchStage, PlotSearchType, RECEIVE_PLOT_SEARCH_ATTRIBUTES, + RECEIVE_PLOT_SEARCH_STAGES, RECEIVE_PLOT_SEARCH_TYPES, RECEIVE_PLOT_SEARCHES, } from './types'; @@ -46,3 +50,13 @@ export const receivePlotSearchTypes = ( export const plotSearchTypesNotFound = (): Action => createAction(PLOT_SEARCH_TYPES_NOT_FOUND)(); + +export const fetchPlotSearchStages = (): Action => + createAction(FETCH_PLOT_SEARCH_STAGES)(); + +export const receivePlotSearchStages = ( + payload: Array +): Action => createAction(RECEIVE_PLOT_SEARCH_STAGES)(payload); + +export const plotSearchStagesNotFound = (): Action => + createAction(PLOT_SEARCH_STAGES_NOT_FOUND)(); diff --git a/src/plotSearch/reducer.ts b/src/plotSearch/reducer.ts index d09b2db..df30d67 100644 --- a/src/plotSearch/reducer.ts +++ b/src/plotSearch/reducer.ts @@ -1,16 +1,20 @@ import { createSlice } from '@reduxjs/toolkit'; import { FETCH_PLOT_SEARCH_ATTRIBUTES, + FETCH_PLOT_SEARCH_STAGES, FETCH_PLOT_SEARCH_TYPES, FETCH_PLOT_SEARCHES, PLOT_SEARCHES_NOT_FOUND, PlotSearch, + PlotSearchStage, PlotSearchType, RECEIVE_PLOT_SEARCH_ATTRIBUTES, + RECEIVE_PLOT_SEARCH_STAGES, RECEIVE_PLOT_SEARCH_TYPES, RECEIVE_PLOT_SEARCHES, ReceivePlotSearchAttributesAction, ReceivePlotSearchesAction, + ReceivePlotSearchStagesAction, ReceivePlotSearchTypesAction, } from './types'; import { ApiAttributes } from '../api/types'; @@ -19,18 +23,22 @@ type CurrentDisplayState = { plotSearches: Array; plotSearchAttributes: ApiAttributes; plotSearchTypes: Array; + plotSearchStages: Array; isFetchingPlotSearches: boolean; isFetchingPlotSearchAttributes: boolean; isFetchingPlotSearchTypes: boolean; + isFetchingPlotSearchStages: boolean; }; const initialState: CurrentDisplayState = { plotSearches: [], plotSearchAttributes: {}, plotSearchTypes: [], + plotSearchStages: [], isFetchingPlotSearches: false, isFetchingPlotSearchAttributes: false, isFetchingPlotSearchTypes: false, + isFetchingPlotSearchStages: false, }; const plotSearchSlice = createSlice({ @@ -71,6 +79,16 @@ const plotSearchSlice = createSlice({ [FETCH_PLOT_SEARCH_TYPES]: (state) => { state.isFetchingPlotSearchTypes = true; }, + [RECEIVE_PLOT_SEARCH_STAGES]: ( + state, + { payload }: ReceivePlotSearchStagesAction + ) => { + state.plotSearchStages = payload; + state.isFetchingPlotSearchStages = false; + }, + [FETCH_PLOT_SEARCH_STAGES]: (state) => { + state.isFetchingPlotSearchStages = true; + }, }, }); diff --git a/src/plotSearch/requests.ts b/src/plotSearch/requests.ts index feda956..8b50130 100644 --- a/src/plotSearch/requests.ts +++ b/src/plotSearch/requests.ts @@ -27,3 +27,11 @@ export const fetchPlotSearchTypesRequest = (): Generator< > => { return callApi(new Request(createUrl('plot_search_type/'))); }; + +export const fetchPlotSearchStagesRequest = (): Generator< + Effect, + ApiCallResult, + Response +> => { + return callApi(new Request(createUrl('plot_search_stage/'))); +}; diff --git a/src/plotSearch/saga.ts b/src/plotSearch/saga.ts index 1e1a814..49c84a9 100644 --- a/src/plotSearch/saga.ts +++ b/src/plotSearch/saga.ts @@ -1,7 +1,16 @@ -import { all, call, Effect, fork, put, takeLatest } from 'redux-saga/effects'; +import { + all, + call, + Effect, + fork, + put, + select, + takeLatest, +} from 'redux-saga/effects'; import { fetchPlotSearchAttributesRequest, fetchPlotSearchesRequest, + fetchPlotSearchStagesRequest, fetchPlotSearchTypesRequest, } from './requests'; import { @@ -11,28 +20,45 @@ import { FETCH_PLOT_SEARCH_TYPES, PlotSearchType, PlotSearchFromBackend, + PlotSearchStage, + FETCH_PLOT_SEARCH_STAGES, } from './types'; import { plotSearchAttributesNotFound, plotSearchesNotFound, + plotSearchStagesNotFound, plotSearchTypesNotFound, receivePlotSearchAttributes, receivePlotSearches, + receivePlotSearchStages, receivePlotSearchTypes, } from './actions'; import { parsePlotSearches } from './helpers'; import { ApiCallResult } from '../api/callApi'; import { ApiAttributes } from '../api/types'; import { logError } from '../root/helpers'; +import { RootState } from '../root/rootReducer'; function* fetchPlotSearchesSaga({ payload, -}: FetchPlotSearchesAction): Generator { +}: FetchPlotSearchesAction): Generator { try { - const { response, bodyAsJson } = yield call( - fetchPlotSearchesRequest, - payload?.params + const stages: Array = yield select( + (state: RootState) => state.plotSearch.plotSearchStages ); + const ongoingId = stages.find((stage) => stage.stage === 'in_action')?.id; + + if (!ongoingId) { + logError('Could not find ongoing stage ID'); + yield put(plotSearchesNotFound()); + return; + } + + const result: ApiCallResult = yield call(fetchPlotSearchesRequest, { + stage: '' + ongoingId, + ...(payload?.params || {}), + }); + const { response, bodyAsJson } = result; switch (response.status) { case 200: @@ -102,6 +128,27 @@ function* fetchPlotSearchTypesSaga(): Generator { } } +function* fetchPlotSearchStagesSaga(): Generator { + try { + const { response, bodyAsJson } = yield call(fetchPlotSearchStagesRequest); + + switch (response.status) { + case 200: + yield put( + receivePlotSearchStages(bodyAsJson?.results as Array) + ); + break; + default: + yield put(plotSearchStagesNotFound()); + break; + } + } catch (e) { + logError(e); + yield put(plotSearchStagesNotFound()); + throw e; + } +} + export default function* plotSearchSaga(): Generator { yield all([ fork(function* (): Generator { @@ -111,6 +158,7 @@ export default function* plotSearchSaga(): Generator { fetchPlotSearchAttributesSaga ); yield takeLatest(FETCH_PLOT_SEARCH_TYPES, fetchPlotSearchTypesSaga); + yield takeLatest(FETCH_PLOT_SEARCH_STAGES, fetchPlotSearchStagesSaga); }), ]); } diff --git a/src/plotSearch/types.ts b/src/plotSearch/types.ts index 14b62b3..caaea3c 100644 --- a/src/plotSearch/types.ts +++ b/src/plotSearch/types.ts @@ -57,6 +57,24 @@ export interface PlotSearchTypesNotFoundAction { type: typeof PLOT_SEARCH_TYPES_NOT_FOUND; } +export const FETCH_PLOT_SEARCH_STAGES = 'plotSearch/FETCH_PLOT_SEARCH_STAGES'; +export interface FetchPlotSearchStagesAction { + type: typeof FETCH_PLOT_SEARCH_STAGES; +} + +export const RECEIVE_PLOT_SEARCH_STAGES = + 'plotSearch/RECEIVE_PLOT_SEARCH_STAGES'; +export interface ReceivePlotSearchStagesAction { + type: typeof RECEIVE_PLOT_SEARCH_STAGES; + payload: Array; +} + +export const PLOT_SEARCH_STAGES_NOT_FOUND = + 'plotSearch/PLOT_SEARCH_STAGES_NOT_FOUND'; +export interface PlotSearchStagesNotFoundAction { + type: typeof PLOT_SEARCH_STAGES_NOT_FOUND; +} + export type PlotSearchType = { id: number; name: string; @@ -70,6 +88,12 @@ export type PlotSearchSubtype = { show_district: boolean; }; +export type PlotSearchStage = { + id: number; + name: string; + stage: string; +}; + export type PlotSearchTypeReference = { id: number; name: string; @@ -81,7 +105,7 @@ export type PlotSearchSubtypeReference = { plot_search_type: number; }; -export type PlotSearchStage = { +export type PlotSearchStageReference = { id: number; name: string; }; @@ -268,7 +292,7 @@ export type PlotSearchFromBackend = { id: number; type: PlotSearchTypeReference; subtype: PlotSearchSubtypeReference; - stage: PlotSearchStage; + stage: PlotSearchStageReference; search_class: string; form: Form; decisions: Array; @@ -285,7 +309,7 @@ export type PlotSearch = { id: number; type: PlotSearchTypeReference; subtype: PlotSearchSubtypeReference; - stage: PlotSearchStage; + stage: PlotSearchStageReference; search_class: string; form: Form; decisions: Array;