Refactor list filter query functionality

This commit is contained in:
Infinite
2020-02-07 20:58:23 +01:00
parent 0fdde7726b
commit 690596aa34
4 changed files with 57 additions and 54 deletions

View File

@@ -1,5 +1,6 @@
import { debounce } from "lodash"; import { debounce } from "lodash";
import React, { SyntheticEvent, useCallback, useState } from "react"; import React, { SyntheticEvent, useCallback, useState } from "react";
import { SortDirectionEnum } from 'src/core/generated-graphql';
import { import {
Badge, Badge,
Button, Button,
@@ -24,7 +25,7 @@ interface IListFilterOperation {
interface IListFilterProps { interface IListFilterProps {
onChangePageSize: (pageSize: number) => void; onChangePageSize: (pageSize: number) => void;
onChangeQuery: (query: string) => void; onChangeQuery: (query: string) => void;
onChangeSortDirection: (sortDirection: "asc" | "desc") => void; onChangeSortDirection: (sortDirection: SortDirectionEnum) => void;
onChangeSortBy: (sortBy: string) => void; onChangeSortBy: (sortBy: string) => void;
onChangeDisplayMode: (displayMode: DisplayMode) => void; onChangeDisplayMode: (displayMode: DisplayMode) => void;
onAddCriterion: (criterion: Criterion, oldId?: string) => void; onAddCriterion: (criterion: Criterion, oldId?: string) => void;
@@ -64,10 +65,10 @@ export const ListFilter: React.FC<IListFilterProps> = (
} }
function onChangeSortDirection() { function onChangeSortDirection() {
if (props.filter.sortDirection === "asc") { if (props.filter.sortDirection === SortDirectionEnum.Asc) {
props.onChangeSortDirection("desc"); props.onChangeSortDirection(SortDirectionEnum.Desc);
} else { } else {
props.onChangeSortDirection("asc"); props.onChangeSortDirection(SortDirectionEnum.Asc);
} }
} }
@@ -279,7 +280,7 @@ export const ListFilter: React.FC<IListFilterProps> = (
<OverlayTrigger <OverlayTrigger
overlay={ overlay={
<Tooltip id="sort-direction-tooltip"> <Tooltip id="sort-direction-tooltip">
{props.filter.sortDirection === "asc" {props.filter.sortDirection === SortDirectionEnum.Asc
? "Ascending" ? "Ascending"
: "Descending"} : "Descending"}
</Tooltip> </Tooltip>
@@ -288,7 +289,7 @@ export const ListFilter: React.FC<IListFilterProps> = (
<Button variant="secondary" onClick={onChangeSortDirection}> <Button variant="secondary" onClick={onChangeSortDirection}>
<Icon <Icon
icon={ icon={
props.filter.sortDirection === "asc" props.filter.sortDirection === SortDirectionEnum.Asc
? "caret-up" ? "caret-up"
: "caret-down" : "caret-down"
} }

View File

@@ -27,7 +27,7 @@ export const PerformerList: React.FC = () => {
result: FindPerformersQueryResult, result: FindPerformersQueryResult,
filter: ListFilterModel filter: ListFilterModel
) { ) {
if (result.data && result.data.findPerformers) { if (result.data?.findPerformers) {
const { count } = result.data.findPerformers; const { count } = result.data.findPerformers;
const index = Math.floor(Math.random() * count); const index = Math.floor(Math.random() * count);
const filterCopy = _.cloneDeep(filter); const filterCopy = _.cloneDeep(filter);
@@ -50,7 +50,7 @@ export const PerformerList: React.FC = () => {
result: FindPerformersQueryResult, result: FindPerformersQueryResult,
filter: ListFilterModel filter: ListFilterModel
) { ) {
if (!result.data || !result.data.findPerformers) { if (!result.data?.findPerformers) {
return; return;
} }
if (filter.displayMode === DisplayMode.Grid) { if (filter.displayMode === DisplayMode.Grid) {

View File

@@ -1,9 +1,10 @@
import _ from "lodash"; import _ from "lodash";
import queryString from "query-string"; import queryString from "query-string";
import React, { useState } from "react"; import React, { useState, useEffect } from "react";
import { ApolloError } from "apollo-client"; import { ApolloError } from "apollo-client";
import { useHistory } from "react-router-dom"; import { useHistory, useLocation } from "react-router-dom";
import { import {
SortDirectionEnum,
SlimSceneDataFragment, SlimSceneDataFragment,
SceneMarkerDataFragment, SceneMarkerDataFragment,
GalleryDataFragment, GalleryDataFragment,
@@ -74,10 +75,11 @@ const useList = <QueryResult extends IQueryResult, QueryData extends IDataItem>(
options: IListHookOptions<QueryResult> & IQuery<QueryResult, QueryData> options: IListHookOptions<QueryResult> & IQuery<QueryResult, QueryData>
): IListHookData => { ): IListHookData => {
const history = useHistory(); const history = useHistory();
const location = useLocation();
const [filter, setFilter] = useState<ListFilterModel>( const [filter, setFilter] = useState<ListFilterModel>(
new ListFilterModel( new ListFilterModel(
options.filterMode, options.filterMode,
options.subComponent ? "" : queryString.parse(history.location.search) options.subComponent ? "" : queryString.parse(location.search)
) )
); );
const [selectedIds, setSelectedIds] = useState<Set<string>>(new Set()); const [selectedIds, setSelectedIds] = useState<Set<string>>(new Set());
@@ -88,6 +90,15 @@ 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(() => (
setFilter(
new ListFilterModel(
options.filterMode,
options.subComponent ? "" : queryString.parse(location.search)
)
)
), [location, options.filterMode, options.subComponent]);
function getFilter() { function getFilter() {
if (!options.filterHook) { if (!options.filterHook) {
return filter; return filter;
@@ -108,7 +119,6 @@ const useList = <QueryResult extends IQueryResult, QueryData extends IDataItem>(
const newFilter = _.cloneDeep(filter); const newFilter = _.cloneDeep(filter);
newFilter.itemsPerPage = pageSize; newFilter.itemsPerPage = pageSize;
newFilter.currentPage = 1; newFilter.currentPage = 1;
setFilter(newFilter);
updateQueryParams(newFilter); updateQueryParams(newFilter);
} }
@@ -116,14 +126,12 @@ const useList = <QueryResult extends IQueryResult, QueryData extends IDataItem>(
const newFilter = _.cloneDeep(filter); const newFilter = _.cloneDeep(filter);
newFilter.searchTerm = query; newFilter.searchTerm = query;
newFilter.currentPage = 1; newFilter.currentPage = 1;
setFilter(newFilter);
updateQueryParams(newFilter); updateQueryParams(newFilter);
} }
function onChangeSortDirection(sortDirection: "asc" | "desc") { function onChangeSortDirection(sortDirection: SortDirectionEnum) {
const newFilter = _.cloneDeep(filter); const newFilter = _.cloneDeep(filter);
newFilter.sortDirection = sortDirection; newFilter.sortDirection = sortDirection;
setFilter(newFilter);
updateQueryParams(newFilter); updateQueryParams(newFilter);
} }
@@ -131,14 +139,12 @@ const useList = <QueryResult extends IQueryResult, QueryData extends IDataItem>(
const newFilter = _.cloneDeep(filter); const newFilter = _.cloneDeep(filter);
newFilter.sortBy = sortBy; newFilter.sortBy = sortBy;
newFilter.currentPage = 1; newFilter.currentPage = 1;
setFilter(newFilter);
updateQueryParams(newFilter); updateQueryParams(newFilter);
} }
function onChangeDisplayMode(displayMode: DisplayMode) { function onChangeDisplayMode(displayMode: DisplayMode) {
const newFilter = _.cloneDeep(filter); const newFilter = _.cloneDeep(filter);
newFilter.displayMode = displayMode; newFilter.displayMode = displayMode;
setFilter(newFilter);
updateQueryParams(newFilter); updateQueryParams(newFilter);
} }
@@ -165,7 +171,6 @@ const useList = <QueryResult extends IQueryResult, QueryData extends IDataItem>(
}); });
newFilter.currentPage = 1; newFilter.currentPage = 1;
setFilter(newFilter);
updateQueryParams(newFilter); updateQueryParams(newFilter);
} }
@@ -175,14 +180,12 @@ const useList = <QueryResult extends IQueryResult, QueryData extends IDataItem>(
criterion => criterion.getId() !== removedCriterion.getId() criterion => criterion.getId() !== removedCriterion.getId()
); );
newFilter.currentPage = 1; newFilter.currentPage = 1;
setFilter(newFilter);
updateQueryParams(newFilter); updateQueryParams(newFilter);
} }
function onChangePage(page: number) { function onChangePage(page: number) {
const newFilter = _.cloneDeep(filter); const newFilter = _.cloneDeep(filter);
newFilter.currentPage = page; newFilter.currentPage = page;
setFilter(newFilter);
updateQueryParams(newFilter); updateQueryParams(newFilter);
} }

View File

@@ -48,6 +48,7 @@ import { makeCriteria } from "./criteria/utils";
import { DisplayMode, FilterMode } from "./types"; import { DisplayMode, FilterMode } from "./types";
interface IQueryParameters { interface IQueryParameters {
items?: string;
sortby?: string; sortby?: string;
sortdir?: string; sortdir?: string;
disp?: string; disp?: string;
@@ -56,16 +57,24 @@ interface IQueryParameters {
c?: string[]; c?: string[];
} }
const DEFAULT_PARAMS = {
sortDirection: SortDirectionEnum.Asc,
displayMode: DisplayMode.Grid,
currentPage: 1,
itemsPerPage: 40
};
// TODO: handle customCriteria // TODO: handle customCriteria
export class ListFilterModel { export class ListFilterModel {
public filterMode: FilterMode = FilterMode.Scenes; public filterMode: FilterMode = FilterMode.Scenes;
public searchTerm?: string; public searchTerm?: string;
public currentPage = 1; public currentPage = DEFAULT_PARAMS.currentPage;
public itemsPerPage = 40; public itemsPerPage = DEFAULT_PARAMS.itemsPerPage;
public sortDirection: "asc" | "desc" = "asc"; public sortDirection: SortDirectionEnum = SortDirectionEnum.Asc;
public sortBy?: string; public sortBy?: string;
public sortByOptions: string[] = []; public sortByOptions: string[] = [];
public displayMode: DisplayMode = DisplayMode.Grid; public displayMode: DisplayMode = DEFAULT_PARAMS.displayMode;
public displayModeOptions: DisplayMode[] = []; public displayModeOptions: DisplayMode[] = [];
public criterionOptions: ICriterionOption[] = []; public criterionOptions: ICriterionOption[] = [];
public criteria: Array<Criterion<any, any>> = []; public criteria: Array<Criterion<any, any>> = [];
@@ -78,9 +87,7 @@ export class ListFilterModel {
public constructor(filterMode: FilterMode, rawParms?: any) { public constructor(filterMode: FilterMode, rawParms?: any) {
switch (filterMode) { switch (filterMode) {
case FilterMode.Scenes: case FilterMode.Scenes:
if (!!this.sortBy === false) { this.sortBy = "date";
this.sortBy = "date";
}
this.sortByOptions = [ this.sortByOptions = [
"title", "title",
"path", "path",
@@ -110,9 +117,7 @@ export class ListFilterModel {
]; ];
break; break;
case FilterMode.Performers: { case FilterMode.Performers: {
if (!!this.sortBy === false) { this.sortBy = "name";
this.sortBy = "name";
}
this.sortByOptions = ["name", "height", "birthdate", "scenes_count"]; this.sortByOptions = ["name", "height", "birthdate", "scenes_count"];
this.displayModeOptions = [DisplayMode.Grid, DisplayMode.List]; this.displayModeOptions = [DisplayMode.Grid, DisplayMode.List];
@@ -143,25 +148,19 @@ export class ListFilterModel {
break; break;
} }
case FilterMode.Studios: case FilterMode.Studios:
if (!!this.sortBy === false) { this.sortBy = "name";
this.sortBy = "name";
}
this.sortByOptions = ["name", "scenes_count"]; this.sortByOptions = ["name", "scenes_count"];
this.displayModeOptions = [DisplayMode.Grid]; this.displayModeOptions = [DisplayMode.Grid];
this.criterionOptions = [new NoneCriterionOption()]; this.criterionOptions = [new NoneCriterionOption()];
break; break;
case FilterMode.Galleries: case FilterMode.Galleries:
if (!!this.sortBy === false) { this.sortBy = "path";
this.sortBy = "path";
}
this.sortByOptions = ["path"]; this.sortByOptions = ["path"];
this.displayModeOptions = [DisplayMode.List]; this.displayModeOptions = [DisplayMode.List];
this.criterionOptions = [new NoneCriterionOption()]; this.criterionOptions = [new NoneCriterionOption()];
break; break;
case FilterMode.SceneMarkers: case FilterMode.SceneMarkers:
if (!!this.sortBy === false) { this.sortBy = "title";
this.sortBy = "title";
}
this.sortByOptions = [ this.sortByOptions = [
"title", "title",
"seconds", "seconds",
@@ -208,18 +207,20 @@ export class ListFilterModel {
} }
} }
} }
if (params.sortdir === "asc" || params.sortdir === "desc") { this.sortDirection = params.sortdir === "desc"
this.sortDirection = params.sortdir; ? SortDirectionEnum.Desc
: SortDirectionEnum.Asc;
if (params.disp) {
this.displayMode = Number.parseInt(params.disp, 10);
} }
if (params.disp !== undefined) { if (params.q) {
this.displayMode = parseInt(params.disp, 10);
}
if (params.q !== undefined) {
this.searchTerm = params.q; this.searchTerm = params.q;
} }
if (params.p !== undefined) { if (params.p) {
this.currentPage = Number(params.p); this.currentPage = Number.parseInt(params.p, 10);
} }
if (params.items)
this.itemsPerPage = Number.parseInt(params.items, 10);
if (params.c !== undefined) { if (params.c !== undefined) {
this.criteria = []; this.criteria = [];
@@ -275,11 +276,12 @@ export class ListFilterModel {
}); });
const result = { const result = {
items: this.itemsPerPage !== DEFAULT_PARAMS.itemsPerPage ? this.itemsPerPage : undefined,
sortby: this.getSortBy(), sortby: this.getSortBy(),
sortdir: this.sortDirection, sortdir: this.sortDirection === SortDirectionEnum.Desc ? "desc" : undefined,
disp: this.displayMode, disp: this.displayMode !== DEFAULT_PARAMS.displayMode ? this.displayMode : undefined,
q: this.searchTerm, q: this.searchTerm,
p: this.currentPage, p: this.currentPage !== DEFAULT_PARAMS.currentPage ? this.currentPage : undefined,
c: encodedCriteria c: encodedCriteria
}; };
return queryString.stringify(result, { encode: false }); return queryString.stringify(result, { encode: false });
@@ -293,10 +295,7 @@ export class ListFilterModel {
page: this.currentPage, page: this.currentPage,
per_page: this.itemsPerPage, per_page: this.itemsPerPage,
sort: this.getSortBy(), sort: this.getSortBy(),
direction: direction: this.sortDirection
this.sortDirection === "asc"
? SortDirectionEnum.Asc
: SortDirectionEnum.Desc
}; };
} }