diff --git a/src/App.js b/src/App.js index 8374f4bef..c08f3fe3a 100644 --- a/src/App.js +++ b/src/App.js @@ -1,40 +1,11 @@ import './css/App.less'; +import React from 'react'; import { Route, BrowserRouter as Router, Routes } from 'react-router-dom'; import { IntlProvider } from 'react-intl'; import { Provider } from 'react-redux'; -import queryManager from './middleware/queryManager/queryManager'; import { ComplaintDetail } from './components/ComplaintDetail/ComplaintDetail'; -import React from 'react'; import { SearchComponents } from './components/Search/SearchComponents'; -import synchUrl from './middleware/synchUrl/synchUrl'; -import { configureStore } from '@reduxjs/toolkit'; -import aggReducer from './reducers/aggs/aggs'; -import detailReducer from './reducers/detail/detail'; -import filtersReducer from './reducers/filters/filtersSlice'; -import mapReducer from './reducers/map/map'; -import queryReducer from './reducers/query/query'; -import resultsReducer from './reducers/results/results'; -import routesReducer from './reducers/routes/routesSlice'; -import trendsReducer from './reducers/trends/trends'; -import viewReducer from './reducers/view/view'; - -// required format for redux-devtools-extension -const store = configureStore({ - devTools: true, - reducer: { - aggs: aggReducer, - detail: detailReducer, - filters: filtersReducer, - map: mapReducer, - query: queryReducer, - results: resultsReducer, - routes: routesReducer, - trends: trendsReducer, - view: viewReducer, - }, - middleware: (getDefaultMiddleware) => - getDefaultMiddleware().concat([queryManager, synchUrl]), -}); +import store from './app/store'; /* eslint-disable camelcase */ export const DetailComponents = () => { @@ -46,9 +17,7 @@ export const DetailComponents = () => { ); }; -/* eslint-enable camelcase */ -// eslint-disable-next-line react/no-multi-comp /** * Main App Component * diff --git a/src/actions/complaints.js b/src/actions/complaints.js index 03d131e04..682a158e1 100644 --- a/src/actions/complaints.js +++ b/src/actions/complaints.js @@ -30,6 +30,7 @@ import { complaintsApiFailed, complaintsReceived, } from '../reducers/results/results'; +import { buildUri } from '../api/url/url'; // ---------------------------------------------------------------------------- // Routing action @@ -119,7 +120,7 @@ export function getAggregations() { export function getComplaints() { return (dispatch, getState) => { const store = getState(); - const qs = store.query.queryString; + const qs = buildUri(store); const uri = API_PLACEHOLDER + qs; // This call is already in process if (uri === store.results.activeCall) { @@ -161,7 +162,7 @@ export function getComplaintDetail(id) { export function getStates() { return (dispatch, getState) => { const store = getState(); - const qs = 'geo/states/' + store.query.queryString; + const qs = 'geo/states/' + buildUri(store); const uri = API_PLACEHOLDER + qs + '&no_aggs=true'; // This call is already in process @@ -185,8 +186,9 @@ export function getStates() { export function getTrends() { return (dispatch, getState) => { const store = getState(); - const qs = 'trends/' + store.query.queryString; + const qs = 'trends/' + buildUri(store); const uri = API_PLACEHOLDER + qs + '&no_aggs=true'; + //const uri = API_PLACEHOLDER + 'trends' + buildUri(store) + '&no_aggs=true'; // This call is already in process if (uri === store.trends.activeCall) { return null; diff --git a/src/actions/routes.js b/src/actions/routes.js index b7bf7963f..83093a8de 100644 --- a/src/actions/routes.js +++ b/src/actions/routes.js @@ -1,4 +1,5 @@ import { routeChanged } from '../reducers/routes/routesSlice'; +import queryString from 'query-string'; const isEqual = require('react-fast-compare'); // ---------------------------------------------------------------------------- @@ -45,14 +46,28 @@ export function changeRoute(path, params) { // eslint-disable-next-line complexity return function (dispatch, getState) { const store = getState(); - console.log('CR', path, params); const normalized = normalizeRouteParams(params); const { routes } = store; const sameRoute = routes.path === path && isEqual(routes.params, normalized); - if (sameRoute === false) { dispatch(routeChanged(path, normalized)); } }; } + +/** + * Converts a Location object into structures needed by the reducers + * + * @param {Location} location - information about the host, path and query string + * @returns {object} the pathname and a dictionary of the query string params + */ +export function processLocation(location) { + const qs = location.search; + const params = queryString.parse(qs); + + return { + pathname: location.pathname, + params, + }; +} diff --git a/src/api/params/params.js b/src/api/params/params.js index 72d815110..5310cb6fe 100644 --- a/src/api/params/params.js +++ b/src/api/params/params.js @@ -81,58 +81,6 @@ export function extractReducerAttributes(reducer, attributes) { // ---------------------------------------------------------------------------- // parameter objects <--> reducer -/** - * Selects specific variables from the geo reducer to be used in a query string - * - * @param {object} state - the current state of geo in the Redux store - * @returns {object} a dictionary of strings - */ -export function extractGeoParams(state) { - const { - boundingBox, - center, - centroidsEnabled, - geographicLevel, - geoShading, - mapType, - zoom, - } = state.geo; - - const { almanacId, almanacLevel } = state.almanac; - - const almanacParams = almanacId - ? { - almanacId, - almanacLevel, - } - : {}; - - const boundingBoxParams = boundingBox - ? { - north: boundingBox.north.toString(10), - south: boundingBox.south.toString(10), - west: boundingBox.west.toString(10), - east: boundingBox.east.toString(10), - } - : {}; - - return mapType === 'leaflet' - ? { - ...almanacParams, - ...boundingBoxParams, - centroidsEnabled, - // censusYear is not specific to geo - geographicLevel, - geoShading, - lat: center.lat.toString(10), - lng: center.lng.toString(10), - zoom: zoom.toString(10), - } - : { - ...almanacParams, - geographicLevel, - }; -} export const buildSort = (sort) => { const sortMap = { @@ -196,29 +144,6 @@ export function extractQueryParams(queryState) { return params; } -/** - * Selects specific values from the query reducer to be used in a query string for saved list complaints return - * - * @param {object} state - the current state in the Redux store - * @returns {object} a dictionary of strings - */ -export function extractSavedListQueryParams(state) { - const { query } = state; - const params = { - frm: query.from, - index_name: query._index, - no_aggs: true, - size: query.size, - sort: buildSort(query.sort), - }; - - if (query.searchAfter) { - params.search_after = query.searchAfter; - } - - return params; -} - /** * helper function to parse out age to use in query string * @@ -311,13 +236,12 @@ export function extractAgeParams(ageRange = {}) { * @returns {object} a dictionary of strings */ export function extractTrendsParams(state) { - const { focus, lens, subLens, trend_depth } = state.trends; - const { interval } = state.viewModel; + const { dateInterval, focus, lens, subLens, trend_depth } = state.trends; const params = { lens: lens.replace(' ', '_').toLowerCase(), trend_depth, - trend_interval: interval.toLowerCase(), + trend_interval: dateInterval.toLowerCase(), }; if (subLens) { diff --git a/src/api/url/url.js b/src/api/url/url.js index 89cb96012..652e2e3b0 100644 --- a/src/api/url/url.js +++ b/src/api/url/url.js @@ -1,8 +1,9 @@ /* eslint-disable camelcase */ import * as paramFns from '../params/params'; -import * as constants from '../../constants'; import queryString from 'query-string'; +import { MODE_LIST, MODE_MAP, MODE_TRENDS } from '../../constants'; +const uri = '/'; /** * Creates an aggregation query * @@ -11,169 +12,45 @@ import queryString from 'query-string'; */ export function buildAggregationUri(state) { const params = paramFns.extractAggregationParams(state); - - const { viewMode } = state.viewModel; - - let uri = URI_COMPLAINTS; - - switch (viewMode) { - case constants.MODE_ATTACHMENT: - uri = URI_ATTACHMENT; - break; - - case constants.MODE_MORE_LIKE_COMPLAINT: - uri = `${URI_COMPLAINTS}/${state.query.mltId}/mlt`; - break; - - case constants.MODE_COMPARE: - case constants.MODE_GEO: - case constants.MODE_LIST_COMPLAINTS: - case constants.MODE_TRENDS: - uri = URI_COMPLAINTS; - break; - - case constants.MODE_TELL_YOUR_STORY: - uri = URI_TELL_YOUR_STORY; - break; - - default: - throw new Error('V2 does not currently support ' + viewMode); - } - // Add the no-hits param params.size = 0; return formatUri(uri, params); } -/** - * Creates an almanac query - * - * @param {object} state - The current state in the Redux store. - * @returns {string} The full endpoint url. - */ -export function buildAlmanacUri(state) { - const { almanac, filters, geo, query } = state; - const { almanacId, almanacLevel } = almanac; - const { geographicLevel } = geo; - - const params = Object.assign( - { - almanacLevel, - index_name: query._index, - }, - paramFns.extractBasicParams(filters, query), - ); - - const level = geographicLevel.toLowerCase(); - const uri = `${URI_ALMANAC}/${level}/${almanacId}`; - return formatUri(uri, params); -} - -/** - * Determines the full url of history endpoint based on the state. - * - * @param {object} state - The current state in the Redux store. - * @param {string} tab - The current state in the Redux store. - * @returns {string} The full endpoint url. - */ -export function buildHistoryUri(state, tab) { - let uri; - switch (tab) { - case constants.HistoryTabs.Searches: - uri = '/search-history'; - break; - case constants.HistoryTabs.Exports: - uri = '/export-history'; - break; - case constants.HistoryTabs.SavedSearches: - default: - uri = '/saved-searches'; - } - - const params = { - limit: 100, - }; - - if ( - tab === constants.HistoryTabs.Searches || - tab === constants.HistoryTabs.Exports - ) { - params.index_name = state.query._index; - } - - return formatUri(uri, params); -} - -/** - * Determines the full peers url based on the state - * - * @param {object} state - The current state in the Redux store. - * @returns {string} The full peers endpoint url. - */ -export function buildPeersUri(state) { - const { compareItem } = state.comparisons; - const uri = `${URI_PEERS}/${compareItem}`; - const params = { index_name: 'complaint-peers' }; - - return formatUri(uri, params); -} - /** * Determines the full url based on the state * * @param {object} state - The app state in Redux. - * @param {string} endpoint - The api endpoint * @returns {string} The url with parameters for the endpoint */ -export function buildUri(state, endpoint = '') { - const uri = endpoint === '' ? getEndpointPath(state) : endpoint; - const { filters, geo, query, viewModel } = state; - const { viewMode } = viewModel; +export function buildUri(state) { + const { filters, query, view } = state; + const { tab } = view; let params; - switch (viewMode) { - case constants.MODE_ATTACHMENT: - case constants.MODE_LIST_COMPLAINTS: - params = paramFns.extractBasicParams(filters, geo, query); + switch (tab) { + case MODE_LIST: + params = paramFns.extractBasicParams(filters, query); params.no_aggs = true; break; - case constants.MODE_MORE_LIKE_COMPLAINT: - params = paramFns.extractBasicParams(filters, geo, query); - break; - - case constants.MODE_COMPARE: + case MODE_MAP: params = Object.assign( { no_aggs: true }, - paramFns.extractBasicParams(filters, geo, query), - paramFns.extractCompareParams(state), + paramFns.extractBasicParams(filters, query), ); break; - case constants.MODE_GEO: - params = Object.assign( - { no_aggs: true }, - paramFns.extractBasicParams(filters, geo, query), - paramFns.extractGeoParams(state), - ); - break; - - case constants.MODE_TRENDS: + case MODE_TRENDS: + default: params = Object.assign( { no_aggs: true }, - paramFns.extractBasicParams(filters, geo, query), + paramFns.extractBasicParams(filters, query), paramFns.extractTrendsParams(state), ); break; - - case constants.MODE_TELL_YOUR_STORY: - params = paramFns.extractTysParams(state); - break; - - default: - throw new Error('V2 does not currently support ' + viewMode); } return formatUri(uri, params); @@ -219,53 +96,3 @@ export const genMLTHref = (id) => { export function genBackLink(indexPath) { return '/' + indexPath + '/q'; } - -/** - * Generates url to the History page - * - * @param {string} indexPath - complaints or stories - * @param {string} tab - The history tab we want to direct history to - * @returns {string} The url. - */ -export function genHistoryHref(indexPath, tab) { - const tabName = tab ? tab : constants.HistoryTabs.SavedSearches; - return `/${indexPath}/history/${tabName}?`; -} - -/** - * Determines the correct endpoint based on the state - * - * @param {object} state - The current state in the Redux store. - * @returns {string} the endpoint url (without query string). - */ -export function getEndpointPath(state) { - const { searchFields } = state.query; - const { viewMode } = state.viewModel; - - let path = viewMode in pathMap ? pathMap[viewMode] : URI_COMPLAINTS; - - if (viewMode === constants.MODE_MORE_LIKE_COMPLAINT) { - path += '/' + state.query.mltId + '/mlt'; - } - - if (viewMode === constants.MODE_COMPARE) { - const { compareItem } = state.comparisons; - path += `/${compareItem}`; - } - - const docModes = [constants.MODE_DOCUMENT, constants.MODE_TYS_DOCUMENT]; - if (docModes.includes(viewMode)) { - const { id } = state.document; - if (searchFields === constants.SearchFields.Attachments) { - path += `/${id}`; - } - } - - if (viewMode === constants.MODE_GEO) { - const { geographicLevel } = state.geo; - const searchField = constants.geographicLevels[geographicLevel].searchField; - path += `/${searchField}/complaints`; - } - - return path; -} diff --git a/src/app/store.js b/src/app/store.js new file mode 100644 index 000000000..0531fe8d7 --- /dev/null +++ b/src/app/store.js @@ -0,0 +1,29 @@ +import queryManager from '../middleware/queryManager/queryManager'; +import synchUrl from '../middleware/synchUrl/synchUrl'; +import aggReducer from '../reducers/aggs/aggs'; +import detailReducer from '../reducers/detail/detail'; +import filtersReducer from '../reducers/filters/filtersSlice'; +import mapReducer from '../reducers/map/map'; +import queryReducer from '../reducers/query/query'; +import resultsReducer from '../reducers/results/results'; +import routesReducer from '../reducers/routes/routesSlice'; +import trendsReducer from '../reducers/trends/trends'; +import viewReducer from '../reducers/view/view'; +import { configureStore } from '@reduxjs/toolkit'; + +export default configureStore({ + devTools: true, + reducer: { + aggs: aggReducer, + detail: detailReducer, + filters: filtersReducer, + map: mapReducer, + query: queryReducer, + results: resultsReducer, + routes: routesReducer, + trends: trendsReducer, + view: viewReducer, + }, + middleware: (getDefaultMiddleware) => + getDefaultMiddleware().concat([queryManager, synchUrl]), +}); diff --git a/src/middleware/queryManager/queryManager.js b/src/middleware/queryManager/queryManager.js index 42ad9ada2..dfa190039 100644 --- a/src/middleware/queryManager/queryManager.js +++ b/src/middleware/queryManager/queryManager.js @@ -1,7 +1,7 @@ import * as constants from '../../constants'; import { sendHitsQuery, sendQuery } from '../../actions/complaints'; -export const queryManager = (store) => (next) => (action) => { +export const queryManager = (store) => (next) => async (action) => { // call the next function // Pass the action forward in the chain // eslint-disable-next-line callback-return @@ -11,7 +11,6 @@ export const queryManager = (store) => (next) => (action) => { // eslint-disable-next-line callback-return const result = next(action); const requery = action.meta?.requery ?? constants.REQUERY_NEVER; - // const state = store.getState(); if (requery === constants.REQUERY_ALWAYS) { store.dispatch(sendQuery()); diff --git a/src/middleware/synchUrl/synchUrl.js b/src/middleware/synchUrl/synchUrl.js index 998267a89..cbde99452 100644 --- a/src/middleware/synchUrl/synchUrl.js +++ b/src/middleware/synchUrl/synchUrl.js @@ -4,7 +4,6 @@ import queryString from 'query-string'; import { MODE_MAP, MODE_TRENDS, PERSIST_NONE } from '../../constants'; import { extractAgeParams, - extractGeoParams, extractReducerAttributes, } from '../../api/params/params'; @@ -20,8 +19,6 @@ function buildGeoParams(state, viewMode) { return Object.assign( {}, - // API params - extractGeoParams(state), // App-only params extractReducerAttributes(state.geo, ['dataNormalization', 'mapType']), ); @@ -135,23 +132,19 @@ const synchUrl = (store) => (next) => (action) => { // Get the current state const state = store.getState(); - console.log('sadfasd'); - console.log(result); - console.log(action); // Only process certain messages const persist = action.meta?.persist ?? PERSIST_NONE; - console.log(persist); + if (persist.indexOf('PERSIST_SAVE') !== 0) { return result; } const params = extractQueryStringParams(state); - - console.log('AFTER!'); // See if processing should continue // Update the application const history = createBrowserHistory(); const location = history.location; + // if (location.search !== search && !location.pathname.includes('/detail/')) { history.push({ pathname: location.pathname, @@ -159,7 +152,6 @@ const synchUrl = (store) => (next) => (action) => { }); // And record the change in Redux to prevent ROUTE_CHANGED storms store.dispatch(appUrlChanged(location.pathname, params)); - // } return result; }; diff --git a/src/reducers/filters/filtersSlice.js b/src/reducers/filters/filtersSlice.js index 9192430e3..9c7a55bce 100644 --- a/src/reducers/filters/filtersSlice.js +++ b/src/reducers/filters/filtersSlice.js @@ -1,6 +1,10 @@ // default filter state import { createSlice } from '@reduxjs/toolkit'; -import { REQUERY_ALWAYS, REQUERY_NEVER } from '../../constants'; +import { + PERSIST_SAVE_QUERY_STRING, + REQUERY_ALWAYS, + REQUERY_NEVER, +} from '../../constants'; import { coalesce, enablePer1000, processUrlArrayParams } from '../../utils'; import * as types from '../../constants'; import { enforceValues } from '../../utils/reducers'; @@ -52,6 +56,7 @@ export const filtersSlice = createSlice({ return { payload: { filterName, filterValue }, meta: { + persist: PERSIST_SAVE_QUERY_STRING, requery: REQUERY_ALWAYS, }, }; @@ -74,6 +79,7 @@ export const filtersSlice = createSlice({ return { payload: { filterName, filterValue }, meta: { + persist: PERSIST_SAVE_QUERY_STRING, requery: REQUERY_ALWAYS, }, }; @@ -102,6 +108,7 @@ export const filtersSlice = createSlice({ return { payload: { filterName, values }, meta: { + persist: PERSIST_SAVE_QUERY_STRING, requery: REQUERY_ALWAYS, }, }; @@ -121,6 +128,7 @@ export const filtersSlice = createSlice({ return { payload: { filterName, filterValue }, meta: { + persist: PERSIST_SAVE_QUERY_STRING, requery: REQUERY_ALWAYS, }, }; @@ -160,6 +168,7 @@ export const filtersSlice = createSlice({ values, }, meta: { + persist: PERSIST_SAVE_QUERY_STRING, requery: REQUERY_ALWAYS, }, }; @@ -180,6 +189,7 @@ export const filtersSlice = createSlice({ return { payload: { filterName, values }, meta: { + persist: PERSIST_SAVE_QUERY_STRING, requery: REQUERY_ALWAYS, }, }; @@ -206,6 +216,7 @@ export const filtersSlice = createSlice({ return { payload: { selectedState }, meta: { + persist: PERSIST_SAVE_QUERY_STRING, requery: REQUERY_ALWAYS, }, }; @@ -219,6 +230,7 @@ export const filtersSlice = createSlice({ return { payload, meta: { + persist: PERSIST_SAVE_QUERY_STRING, requery: REQUERY_ALWAYS, }, }; @@ -237,6 +249,7 @@ export const filtersSlice = createSlice({ return { payload: { selectedState }, meta: { + persist: PERSIST_SAVE_QUERY_STRING, requery: REQUERY_ALWAYS, }, }; @@ -256,6 +269,7 @@ export const filtersSlice = createSlice({ filterName, }, meta: { + persist: PERSIST_SAVE_QUERY_STRING, requery: REQUERY_ALWAYS, }, }; diff --git a/src/reducers/map/map.js b/src/reducers/map/map.js index 545d4b1e8..ddc2af1db 100644 --- a/src/reducers/map/map.js +++ b/src/reducers/map/map.js @@ -1,7 +1,11 @@ // reducer for the Map Tab import { processAggregations } from '../trends/trends'; import { processErrorMessage } from '../../utils'; -import { TILE_MAP_STATES } from '../../constants'; +import { + PERSIST_SAVE_QUERY_STRING, + REQUERY_NEVER, + TILE_MAP_STATES, +} from '../../constants'; import { createSlice } from '@reduxjs/toolkit'; export const mapState = { @@ -46,21 +50,34 @@ export const mapSlice = createSlice({ state.error = false; }, }, - statesReceived(state, action) { - const aggregations = action.payload.aggregations; - const { state: stateData } = aggregations; - // add in "issue" if we ever need issue row chart again - const keys = ['product']; - const results = {}; - processAggregations(keys, state, aggregations, results); - results.state = processStateAggregations(stateData); + statesReceived: { + reducer: (state, action) => { + const aggregations = action.payload.aggregations; + const { state: stateData } = aggregations; + // add in "issue" if we ever need issue row chart again + const keys = ['product']; + const results = {}; + processAggregations(keys, state, aggregations, results); + results.state = processStateAggregations(stateData); - return { - ...state, - activeCall: '', - error: false, - results, - }; + return { + ...state, + activeCall: '', + error: false, + results, + }; + }, + prepare: (items) => { + return { + payload: { + data: items, + }, + meta: { + persist: PERSIST_SAVE_QUERY_STRING, + requery: REQUERY_NEVER, + }, + }; + }, }, statesApiFailed(state, action) { return { diff --git a/src/reducers/query/query.js b/src/reducers/query/query.js index 2987e28f2..5bc17ec9a 100644 --- a/src/reducers/query/query.js +++ b/src/reducers/query/query.js @@ -12,6 +12,7 @@ import dayjs from 'dayjs'; import { isGreaterThanYear } from '../../utils/trends'; import { createSlice } from '@reduxjs/toolkit'; import { + PERSIST_SAVE_QUERY_STRING, REQUERY_ALWAYS, REQUERY_HITS_ONLY, REQUERY_NEVER, @@ -141,27 +142,6 @@ export const querySlice = createSlice({ }; }, }, - changeDateInterval: { - reducer: (state, action) => { - state.dateInterval = enforceValues( - action.payload.dateInterval, - 'dateInterval', - ); - validateDateInterval(state); - state.queryString = stateToQS(state); - state.search = stateToURL(state); - }, - prepare: (dateInterval) => { - return { - payload: { - dateInterval, - }, - meta: { - requery: REQUERY_ALWAYS, - }, - }; - }, - }, changeDateRange: { // eslint-disable-next-line complexity reducer: (state, action) => { @@ -179,10 +159,6 @@ export const querySlice = createSlice({ ? res[dateRange] : state.date_received_min; state.date_received_max = maxDate; - state.dateInterval = - dateRange === 'All' && state.tab === types.MODE_TRENDS - ? 'Week' - : state.dateInterval || queryState.dateInterval; validateDateInterval(state); state.queryString = stateToQS(state); state.search = stateToURL(state); @@ -193,6 +169,7 @@ export const querySlice = createSlice({ dateRange, }, meta: { + persist: PERSIST_SAVE_QUERY_STRING, requery: REQUERY_ALWAYS, }, }; @@ -246,6 +223,7 @@ export const querySlice = createSlice({ maxDate, }, meta: { + persist: PERSIST_SAVE_QUERY_STRING, requery: REQUERY_ALWAYS, }, }; @@ -266,6 +244,7 @@ export const querySlice = createSlice({ return { payload: { searchField }, meta: { + persist: PERSIST_SAVE_QUERY_STRING, requery: REQUERY_ALWAYS, }, }; @@ -286,6 +265,7 @@ export const querySlice = createSlice({ return { payload: { searchText }, meta: { + persist: PERSIST_SAVE_QUERY_STRING, requery: REQUERY_ALWAYS, }, }; @@ -323,6 +303,7 @@ export const querySlice = createSlice({ return { payload, meta: { + persist: PERSIST_SAVE_QUERY_STRING, requery: REQUERY_ALWAYS, }, }; @@ -356,6 +337,7 @@ export const querySlice = createSlice({ return { payload, meta: { + persist: PERSIST_SAVE_QUERY_STRING, requery: REQUERY_HITS_ONLY, }, }; @@ -376,6 +358,7 @@ export const querySlice = createSlice({ return { payload, meta: { + persist: PERSIST_SAVE_QUERY_STRING, requery: REQUERY_HITS_ONLY, }, }; @@ -394,6 +377,7 @@ export const querySlice = createSlice({ return { payload: { size }, meta: { + persist: PERSIST_SAVE_QUERY_STRING, requery: REQUERY_HITS_ONLY, }, }; @@ -412,6 +396,7 @@ export const querySlice = createSlice({ return { payload: { sort }, meta: { + persist: PERSIST_SAVE_QUERY_STRING, requery: REQUERY_HITS_ONLY, }, }; diff --git a/src/reducers/results/results.js b/src/reducers/results/results.js index 933c35b03..3a2dcfb74 100644 --- a/src/reducers/results/results.js +++ b/src/reducers/results/results.js @@ -2,6 +2,7 @@ import { createSlice } from '@reduxjs/toolkit'; import cloneDeep from 'lodash/cloneDeep'; +import { PERSIST_SAVE_QUERY_STRING, REQUERY_NEVER } from '../../constants'; export const resultsState = { activeCall: '', @@ -29,6 +30,10 @@ export const resultsSlice = createSlice({ return { payload: { data: items, + meta: { + persist: PERSIST_SAVE_QUERY_STRING, + requery: REQUERY_NEVER, + }, }, }; }, diff --git a/src/reducers/routes/routesSlice.js b/src/reducers/routes/routesSlice.js index 1fe87da43..8ac223895 100644 --- a/src/reducers/routes/routesSlice.js +++ b/src/reducers/routes/routesSlice.js @@ -13,7 +13,9 @@ export const updateParams = (state, action) => { }; export const routesState = { - path: '/', + // path has to be empty so that synchURL fires when the page loads through + // useLocation / routes.js + path: '', params: {}, }; diff --git a/src/reducers/trends/trends.js b/src/reducers/trends/trends.js index bd343ccd0..c75d183e3 100644 --- a/src/reducers/trends/trends.js +++ b/src/reducers/trends/trends.js @@ -16,9 +16,15 @@ import { updateDateBuckets, } from '../../utils/chart'; import { isDateEqual } from '../../utils/formatDate'; -import { MODE_TRENDS, REQUERY_ALWAYS, REQUERY_NEVER } from '../../constants'; +import { + MODE_TRENDS, + PERSIST_SAVE_QUERY_STRING, + REQUERY_ALWAYS, + REQUERY_NEVER, +} from '../../constants'; import { pruneOther } from '../../utils/trends'; import { createSlice } from '@reduxjs/toolkit'; +import { validateDateInterval } from '../query/query'; export const emptyResults = () => ({ dateRangeArea: [], @@ -40,6 +46,7 @@ export const getDefaultState = () => {}, { chartType: 'line', + dateInterval: 'Month', focus: '', lens: 'Product', subLens: 'sub_product', @@ -63,11 +70,33 @@ export const trendsSlice = createSlice({ return { payload: { chartType: chartType }, meta: { + persist: PERSIST_SAVE_QUERY_STRING, requery: REQUERY_NEVER, }, }; }, }, + changeDateInterval: { + reducer: (state, action) => { + state.dateInterval = enforceValues( + action.payload.dateInterval, + 'dateInterval', + ); + + validateDateInterval(state); + }, + prepare: (dateInterval) => { + return { + payload: { + dateInterval, + }, + meta: { + persist: PERSIST_SAVE_QUERY_STRING, + requery: REQUERY_ALWAYS, + }, + }; + }, + }, dataLensChanged: { reducer: (state, action) => { const lens = enforceValues(action.payload.lens, 'lens'); @@ -97,6 +126,7 @@ export const trendsSlice = createSlice({ return { payload: { lens: lens }, meta: { + persist: PERSIST_SAVE_QUERY_STRING, requery: REQUERY_ALWAYS, }, }; @@ -113,6 +143,7 @@ export const trendsSlice = createSlice({ return { payload: { subLens }, meta: { + persist: PERSIST_SAVE_QUERY_STRING, requery: REQUERY_ALWAYS, }, }; @@ -126,6 +157,7 @@ export const trendsSlice = createSlice({ return { payload: { depth }, meta: { + persist: PERSIST_SAVE_QUERY_STRING, requery: REQUERY_ALWAYS, }, }; @@ -138,6 +170,7 @@ export const trendsSlice = createSlice({ prepare: () => { return { meta: { + persist: PERSIST_SAVE_QUERY_STRING, requery: REQUERY_ALWAYS, }, }; @@ -155,6 +188,10 @@ export const trendsSlice = createSlice({ prepare: (focus, lens, filterValues) => { return { payload: { focus, lens, filterValues }, + meta: { + persist: PERSIST_SAVE_QUERY_STRING, + requery: REQUERY_ALWAYS, + }, }; }, }, @@ -171,6 +208,7 @@ export const trendsSlice = createSlice({ prepare: () => { return { meta: { + persist: PERSIST_SAVE_QUERY_STRING, requery: REQUERY_ALWAYS, }, }; @@ -302,6 +340,7 @@ export const trendsSlice = createSlice({ data: items, }, meta: { + persist: PERSIST_SAVE_QUERY_STRING, requery: REQUERY_NEVER, }, }; diff --git a/src/reducers/view/view.js b/src/reducers/view/view.js index 95d349703..cf1cb66e2 100644 --- a/src/reducers/view/view.js +++ b/src/reducers/view/view.js @@ -1,6 +1,10 @@ import { processUrlArrayParams } from '../../utils'; import { createSlice } from '@reduxjs/toolkit'; -import { REQUERY_HITS_ONLY, REQUERY_NEVER } from '../../constants'; +import { + PERSIST_SAVE_QUERY_STRING, + REQUERY_HITS_ONLY, + REQUERY_NEVER, +} from '../../constants'; import * as types from '../../constants'; import { enforceValues } from '../../utils/reducers'; @@ -84,6 +88,7 @@ export const viewSlice = createSlice({ return { payload: { tab }, meta: { + persist: PERSIST_SAVE_QUERY_STRING, requery: REQUERY_HITS_ONLY, }, }; @@ -93,27 +98,11 @@ export const viewSlice = createSlice({ reducer: (state) => { state.showTour = false; }, - prepare: (payload) => { - return { - payload, - meta: { - requery: REQUERY_NEVER, - }, - }; - }, }, tourShown: { reducer: (state) => { state.showTour = true; }, - prepare: (payload) => { - return { - payload, - meta: { - requery: REQUERY_NEVER, - }, - }; - }, }, collapseRow: { reducer: (state, action) => {