Maintain filter parameters in session (#326)

This commit is contained in:
Infinite 2020-02-07 22:57:11 +01:00
parent 690596aa34
commit 4e5c65f90d
2 changed files with 75 additions and 26 deletions

View File

@ -1,6 +1,6 @@
import _ from "lodash"; import _ from "lodash";
import queryString from "query-string"; import queryString from "query-string";
import React, { useState, useEffect } from "react"; import React, { useState, useEffect, useRef } from "react";
import { ApolloError } from "apollo-client"; import { ApolloError } from "apollo-client";
import { useHistory, useLocation } from "react-router-dom"; import { useHistory, useLocation } from "react-router-dom";
import { import {
@ -16,6 +16,7 @@ import {
FindStudiosQueryResult, FindStudiosQueryResult,
FindPerformersQueryResult FindPerformersQueryResult
} from "src/core/generated-graphql"; } from "src/core/generated-graphql";
import { useInterfaceLocalForage } from 'src/hooks/LocalForage';
import { LoadingIndicator } from "src/components/Shared"; import { LoadingIndicator } from "src/components/Shared";
import { ListFilter } from "src/components/List/ListFilter"; import { ListFilter } from "src/components/List/ListFilter";
import { Pagination } from "src/components/List/Pagination"; import { Pagination } from "src/components/List/Pagination";
@ -74,6 +75,8 @@ interface IQuery<T extends IQueryResult, T2 extends IDataItem> {
const useList = <QueryResult extends IQueryResult, QueryData extends IDataItem>( const useList = <QueryResult extends IQueryResult, QueryData extends IDataItem>(
options: IListHookOptions<QueryResult> & IQuery<QueryResult, QueryData> options: IListHookOptions<QueryResult> & IQuery<QueryResult, QueryData>
): IListHookData => { ): IListHookData => {
const [interfaceForage, setInterfaceForage] = useInterfaceLocalForage();
const forageInitialised = useRef(false);
const history = useHistory(); const history = useHistory();
const location = useLocation(); const location = useLocation();
const [filter, setFilter] = useState<ListFilterModel>( const [filter, setFilter] = useState<ListFilterModel>(
@ -90,14 +93,56 @@ const useList = <QueryResult extends IQueryResult, QueryData extends IDataItem>(
const totalCount = options.getCount(result); const totalCount = options.getCount(result);
const items = options.getData(result); const items = options.getData(result);
useEffect(() => ( useEffect(() => {
setFilter( if(!forageInitialised.current && !interfaceForage.loading) {
new ListFilterModel( forageInitialised.current = true;
// Don't use query parameters for sub-components
if(options.subComponent)
return;
// Don't read localForage if page already had query parameters
if(history.location.search)
return;
const queryData = interfaceForage.data?.queries[options.filterMode];
if(!queryData)
return;
const newFilter = new ListFilterModel(
options.filterMode, options.filterMode,
options.subComponent ? "" : queryString.parse(location.search) queryString.parse(queryData.filter)
) );
) newFilter.currentPage = queryData.currentPage;
), [location, options.filterMode, options.subComponent]); newFilter.itemsPerPage = queryData.itemsPerPage;
const newLocation = { ...history.location };
newLocation.search = queryData.filter;
history.replace(newLocation);
}
}, [interfaceForage.data, interfaceForage.loading, history, options.subComponent, options.filterMode]);
useEffect(() => {
if(options.subComponent)
return;
const newFilter = new ListFilterModel(
options.filterMode,
options.subComponent ? "" : queryString.parse(location.search)
);
setFilter(newFilter);
if(forageInitialised.current) {
setInterfaceForage((d) => {
const dataClone = _.cloneDeep(d);
dataClone!.queries[options.filterMode] = {
filter: location.search,
itemsPerPage: newFilter.itemsPerPage,
currentPage: newFilter.currentPage
};
return dataClone;
});
}
}, [location, options.filterMode, options.subComponent, setInterfaceForage]);
function getFilter() { function getFilter() {
if (!options.filterHook) { if (!options.filterHook) {

View File

@ -1,22 +1,26 @@
import localForage from "localforage"; import localForage from "localforage";
import _ from "lodash"; import _ from "lodash";
import React from "react"; import React, { Dispatch, SetStateAction } from "react";
interface IInterfaceWallConfig {} interface IInterfaceWallConfig {}
export interface IInterfaceConfig { export interface IInterfaceConfig {
wall: IInterfaceWallConfig; wall: IInterfaceWallConfig;
queries: any;
} }
type ValidTypes = IInterfaceConfig | undefined; type ValidTypes = IInterfaceConfig | undefined;
interface ILocalForage<T> { interface ILocalForage<T> {
data: T; data: T;
setData: React.Dispatch<React.SetStateAction<T>>; setData: Dispatch<SetStateAction<T>>;
error: Error | null; error: Error | null;
loading: boolean;
} }
function useLocalForage(item: string): ILocalForage<ValidTypes> { function useLocalForage(item: string): ILocalForage<ValidTypes> {
const [json, setJson] = React.useState<ValidTypes>(undefined); const [json, setJson] = React.useState<ValidTypes>(undefined);
const [err, setErr] = React.useState(null);
const [loaded, setLoaded] = React.useState<boolean>(false);
const prevJson = React.useRef<ValidTypes>(undefined); const prevJson = React.useRef<ValidTypes>(undefined);
React.useEffect(() => { React.useEffect(() => {
@ -29,7 +33,6 @@ function useLocalForage(item: string): ILocalForage<ValidTypes> {
runAsync(); runAsync();
}); });
const [err, setErr] = React.useState(null);
React.useEffect(() => { React.useEffect(() => {
async function runAsync() { async function runAsync() {
try { try {
@ -42,26 +45,27 @@ function useLocalForage(item: string): ILocalForage<ValidTypes> {
} catch (error) { } catch (error) {
setErr(error); setErr(error);
} }
setLoaded(true);
} }
runAsync(); runAsync();
}); });
return { data: json, setData: setJson, error: err }; return {data: json, setData: setJson, error: err, loading: !loaded};
} }
export function useInterfaceLocalForage(): ILocalForage< export function useInterfaceLocalForage(): [ILocalForage<IInterfaceConfig | undefined>, Dispatch<SetStateAction<IInterfaceConfig | undefined>>] {
IInterfaceConfig | undefined
> {
const result = useLocalForage("interface"); const result = useLocalForage("interface");
// Set defaults
React.useEffect(() => { let returnVal = result;
if (result.data === undefined) { if(!result.data?.queries) {
result.setData({ returnVal = {
wall: { ...result,
// nothing here currently data: {
} wall: {},
}); queries: {}
} }
}); };
return result; }
return [returnVal, result.setData];;
} }