mirror of
https://github.com/stashapp/stash.git
synced 2025-12-17 12:24:38 +03:00
Gallery view persistence (#1105)
* Persist gallery image view separately from primary image view
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
### 🎨 Improvements
|
### 🎨 Improvements
|
||||||
|
* Remember gallery images view mode.
|
||||||
* Add option to skip checking of insecure SSL certificates when scraping.
|
* Add option to skip checking of insecure SSL certificates when scraping.
|
||||||
* Auto-play video previews on mobile devices.
|
* Auto-play video previews on mobile devices.
|
||||||
* Replace hover menu with dropdown menu for O-Counter.
|
* Replace hover menu with dropdown menu for O-Counter.
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { Route, Switch } from "react-router-dom";
|
import { Route, Switch } from "react-router-dom";
|
||||||
|
import { PersistanceLevel } from "src/hooks/ListHook";
|
||||||
import { Gallery } from "./GalleryDetails/Gallery";
|
import { Gallery } from "./GalleryDetails/Gallery";
|
||||||
import { GalleryList } from "./GalleryList";
|
import { GalleryList } from "./GalleryList";
|
||||||
|
|
||||||
@@ -8,7 +9,9 @@ const Galleries = () => (
|
|||||||
<Route
|
<Route
|
||||||
exact
|
exact
|
||||||
path="/galleries"
|
path="/galleries"
|
||||||
render={(props) => <GalleryList {...props} persistState />}
|
render={(props) => (
|
||||||
|
<GalleryList {...props} persistState={PersistanceLevel.ALL} />
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
<Route path="/galleries/:id/:tab?" component={Gallery} />
|
<Route path="/galleries/:id/:tab?" component={Gallery} />
|
||||||
</Switch>
|
</Switch>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { ImageList } from "src/components/Images/ImageList";
|
|||||||
import { showWhenSelected } from "src/hooks/ListHook";
|
import { showWhenSelected } from "src/hooks/ListHook";
|
||||||
import { mutateAddGalleryImages } from "src/core/StashService";
|
import { mutateAddGalleryImages } from "src/core/StashService";
|
||||||
import { useToast } from "src/hooks";
|
import { useToast } from "src/hooks";
|
||||||
|
import { TextUtils } from "src/utils";
|
||||||
|
|
||||||
interface IGalleryAddProps {
|
interface IGalleryAddProps {
|
||||||
gallery: Partial<GQL.GalleryDataFragment>;
|
gallery: Partial<GQL.GalleryDataFragment>;
|
||||||
@@ -17,7 +18,7 @@ export const GalleryAddPanel: React.FC<IGalleryAddProps> = ({ gallery }) => {
|
|||||||
function filterHook(filter: ListFilterModel) {
|
function filterHook(filter: ListFilterModel) {
|
||||||
const galleryValue = {
|
const galleryValue = {
|
||||||
id: gallery.id!,
|
id: gallery.id!,
|
||||||
label: gallery.title ?? gallery.path ?? "",
|
label: gallery.title ?? TextUtils.fileNameFromPath(gallery.path ?? ""),
|
||||||
};
|
};
|
||||||
// if galleries is already present, then we modify it, otherwise add
|
// if galleries is already present, then we modify it, otherwise add
|
||||||
let galleryCriterion = filter.criteria.find((c) => {
|
let galleryCriterion = filter.criteria.find((c) => {
|
||||||
@@ -77,10 +78,6 @@ export const GalleryAddPanel: React.FC<IGalleryAddProps> = ({ gallery }) => {
|
|||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ImageList
|
<ImageList filterHook={filterHook} extraOperations={otherOperations} />
|
||||||
filterHook={filterHook}
|
|
||||||
extraOperations={otherOperations}
|
|
||||||
persistState={false}
|
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,8 +4,9 @@ import { GalleriesCriterion } from "src/models/list-filter/criteria/galleries";
|
|||||||
import { ListFilterModel } from "src/models/list-filter/filter";
|
import { ListFilterModel } from "src/models/list-filter/filter";
|
||||||
import { ImageList } from "src/components/Images/ImageList";
|
import { ImageList } from "src/components/Images/ImageList";
|
||||||
import { mutateRemoveGalleryImages } from "src/core/StashService";
|
import { mutateRemoveGalleryImages } from "src/core/StashService";
|
||||||
import { showWhenSelected } from "src/hooks/ListHook";
|
import { showWhenSelected, PersistanceLevel } from "src/hooks/ListHook";
|
||||||
import { useToast } from "src/hooks";
|
import { useToast } from "src/hooks";
|
||||||
|
import { TextUtils } from "src/utils";
|
||||||
|
|
||||||
interface IGalleryDetailsProps {
|
interface IGalleryDetailsProps {
|
||||||
gallery: GQL.GalleryDataFragment;
|
gallery: GQL.GalleryDataFragment;
|
||||||
@@ -19,7 +20,7 @@ export const GalleryImagesPanel: React.FC<IGalleryDetailsProps> = ({
|
|||||||
function filterHook(filter: ListFilterModel) {
|
function filterHook(filter: ListFilterModel) {
|
||||||
const galleryValue = {
|
const galleryValue = {
|
||||||
id: gallery.id!,
|
id: gallery.id!,
|
||||||
label: gallery.title ?? gallery.path ?? "",
|
label: gallery.title ?? TextUtils.fileNameFromPath(gallery.path ?? ""),
|
||||||
};
|
};
|
||||||
// if galleries is already present, then we modify it, otherwise add
|
// if galleries is already present, then we modify it, otherwise add
|
||||||
let galleryCriterion = filter.criteria.find((c) => {
|
let galleryCriterion = filter.criteria.find((c) => {
|
||||||
@@ -82,7 +83,8 @@ export const GalleryImagesPanel: React.FC<IGalleryDetailsProps> = ({
|
|||||||
<ImageList
|
<ImageList
|
||||||
filterHook={filterHook}
|
filterHook={filterHook}
|
||||||
extraOperations={otherOperations}
|
extraOperations={otherOperations}
|
||||||
persistState={false}
|
persistState={PersistanceLevel.VIEW}
|
||||||
|
persistanceKey="galleryimages"
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -8,7 +8,8 @@ import {
|
|||||||
GallerySlimDataFragment,
|
GallerySlimDataFragment,
|
||||||
} from "src/core/generated-graphql";
|
} from "src/core/generated-graphql";
|
||||||
import { useGalleriesList } from "src/hooks";
|
import { useGalleriesList } from "src/hooks";
|
||||||
import { showWhenSelected } from "src/hooks/ListHook";
|
import { TextUtils } from "src/utils";
|
||||||
|
import { showWhenSelected, PersistanceLevel } from "src/hooks/ListHook";
|
||||||
import { ListFilterModel } from "src/models/list-filter/filter";
|
import { ListFilterModel } from "src/models/list-filter/filter";
|
||||||
import { DisplayMode } from "src/models/list-filter/types";
|
import { DisplayMode } from "src/models/list-filter/types";
|
||||||
import { queryFindGalleries } from "src/core/StashService";
|
import { queryFindGalleries } from "src/core/StashService";
|
||||||
@@ -20,7 +21,7 @@ import { ExportDialog } from "../Shared/ExportDialog";
|
|||||||
|
|
||||||
interface IGalleryList {
|
interface IGalleryList {
|
||||||
filterHook?: (filter: ListFilterModel) => ListFilterModel;
|
filterHook?: (filter: ListFilterModel) => ListFilterModel;
|
||||||
persistState?: boolean;
|
persistState?: PersistanceLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const GalleryList: React.FC<IGalleryList> = ({
|
export const GalleryList: React.FC<IGalleryList> = ({
|
||||||
@@ -202,7 +203,9 @@ export const GalleryList: React.FC<IGalleryList> = ({
|
|||||||
</td>
|
</td>
|
||||||
<td className="d-none d-sm-block">
|
<td className="d-none d-sm-block">
|
||||||
<Link to={`/galleries/${gallery.id}`}>
|
<Link to={`/galleries/${gallery.id}`}>
|
||||||
{gallery.title ?? gallery.path} ({gallery.image_count}{" "}
|
{gallery.title ??
|
||||||
|
TextUtils.fileNameFromPath(gallery.path ?? "")}{" "}
|
||||||
|
({gallery.image_count}{" "}
|
||||||
{gallery.image_count === 1 ? "image" : "images"})
|
{gallery.image_count === 1 ? "image" : "images"})
|
||||||
</Link>
|
</Link>
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ const GalleryWallCard: React.FC<IProps> = ({ gallery }) => {
|
|||||||
? "landscape"
|
? "landscape"
|
||||||
: "portrait";
|
: "portrait";
|
||||||
const cover = gallery?.cover?.paths.thumbnail ?? "";
|
const cover = gallery?.cover?.paths.thumbnail ?? "";
|
||||||
const title = gallery.title ?? gallery.path;
|
const title = gallery.title ?? TextUtils.fileNameFromPath(gallery.path ?? "");
|
||||||
const performerNames = gallery.performers.map((p) => p.name);
|
const performerNames = gallery.performers.map((p) => p.name);
|
||||||
const performers =
|
const performers =
|
||||||
performerNames.length >= 2
|
performerNames.length >= 2
|
||||||
|
|||||||
@@ -12,7 +12,11 @@ import { useImagesList, useLightbox } from "src/hooks";
|
|||||||
import { TextUtils } from "src/utils";
|
import { TextUtils } from "src/utils";
|
||||||
import { ListFilterModel } from "src/models/list-filter/filter";
|
import { ListFilterModel } from "src/models/list-filter/filter";
|
||||||
import { DisplayMode } from "src/models/list-filter/types";
|
import { DisplayMode } from "src/models/list-filter/types";
|
||||||
import { IListHookOperation, showWhenSelected } from "src/hooks/ListHook";
|
import {
|
||||||
|
IListHookOperation,
|
||||||
|
showWhenSelected,
|
||||||
|
PersistanceLevel,
|
||||||
|
} from "src/hooks/ListHook";
|
||||||
import { ImageCard } from "./ImageCard";
|
import { ImageCard } from "./ImageCard";
|
||||||
import { EditImagesDialog } from "./EditImagesDialog";
|
import { EditImagesDialog } from "./EditImagesDialog";
|
||||||
import { DeleteImagesDialog } from "./DeleteImagesDialog";
|
import { DeleteImagesDialog } from "./DeleteImagesDialog";
|
||||||
@@ -79,13 +83,15 @@ const ImageWall: React.FC<IImageWallProps> = ({
|
|||||||
|
|
||||||
interface IImageList {
|
interface IImageList {
|
||||||
filterHook?: (filter: ListFilterModel) => ListFilterModel;
|
filterHook?: (filter: ListFilterModel) => ListFilterModel;
|
||||||
persistState?: boolean;
|
persistState?: PersistanceLevel;
|
||||||
|
persistanceKey?: string;
|
||||||
extraOperations?: IListHookOperation<FindImagesQueryResult>[];
|
extraOperations?: IListHookOperation<FindImagesQueryResult>[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ImageList: React.FC<IImageList> = ({
|
export const ImageList: React.FC<IImageList> = ({
|
||||||
filterHook,
|
filterHook,
|
||||||
persistState,
|
persistState,
|
||||||
|
persistanceKey,
|
||||||
extraOperations,
|
extraOperations,
|
||||||
}) => {
|
}) => {
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
@@ -131,6 +137,7 @@ export const ImageList: React.FC<IImageList> = ({
|
|||||||
filterHook,
|
filterHook,
|
||||||
addKeybinds,
|
addKeybinds,
|
||||||
persistState,
|
persistState,
|
||||||
|
persistanceKey,
|
||||||
});
|
});
|
||||||
|
|
||||||
async function viewRandom(
|
async function viewRandom(
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { Route, Switch } from "react-router-dom";
|
import { Route, Switch } from "react-router-dom";
|
||||||
|
import { PersistanceLevel } from "src/hooks/ListHook";
|
||||||
import { Image } from "./ImageDetails/Image";
|
import { Image } from "./ImageDetails/Image";
|
||||||
import { ImageList } from "./ImageList";
|
import { ImageList } from "./ImageList";
|
||||||
|
|
||||||
@@ -8,7 +9,9 @@ const Images = () => (
|
|||||||
<Route
|
<Route
|
||||||
exact
|
exact
|
||||||
path="/images"
|
path="/images"
|
||||||
render={(props) => <ImageList persistState {...props} />}
|
render={(props) => (
|
||||||
|
<ImageList persistState={PersistanceLevel.ALL} {...props} />
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
<Route path="/images/:id" component={Image} />
|
<Route path="/images/:id" component={Image} />
|
||||||
</Switch>
|
</Switch>
|
||||||
|
|||||||
@@ -9,7 +9,11 @@ import {
|
|||||||
import { ListFilterModel } from "src/models/list-filter/filter";
|
import { ListFilterModel } from "src/models/list-filter/filter";
|
||||||
import { DisplayMode } from "src/models/list-filter/types";
|
import { DisplayMode } from "src/models/list-filter/types";
|
||||||
import { queryFindMovies, useMoviesDestroy } from "src/core/StashService";
|
import { queryFindMovies, useMoviesDestroy } from "src/core/StashService";
|
||||||
import { showWhenSelected, useMoviesList } from "src/hooks/ListHook";
|
import {
|
||||||
|
showWhenSelected,
|
||||||
|
useMoviesList,
|
||||||
|
PersistanceLevel,
|
||||||
|
} from "src/hooks/ListHook";
|
||||||
import { ExportDialog, DeleteEntityDialog } from "src/components/Shared";
|
import { ExportDialog, DeleteEntityDialog } from "src/components/Shared";
|
||||||
import { MovieCard } from "./MovieCard";
|
import { MovieCard } from "./MovieCard";
|
||||||
|
|
||||||
@@ -65,7 +69,7 @@ export const MovieList: React.FC = () => {
|
|||||||
addKeybinds,
|
addKeybinds,
|
||||||
otherOperations,
|
otherOperations,
|
||||||
selectable: true,
|
selectable: true,
|
||||||
persistState: true,
|
persistState: PersistanceLevel.ALL,
|
||||||
renderDeleteDialog,
|
renderDeleteDialog,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import {
|
|||||||
usePerformersDestroy,
|
usePerformersDestroy,
|
||||||
} from "src/core/StashService";
|
} from "src/core/StashService";
|
||||||
import { usePerformersList } from "src/hooks";
|
import { usePerformersList } from "src/hooks";
|
||||||
import { showWhenSelected } from "src/hooks/ListHook";
|
import { showWhenSelected, PersistanceLevel } from "src/hooks/ListHook";
|
||||||
import { ListFilterModel } from "src/models/list-filter/filter";
|
import { ListFilterModel } from "src/models/list-filter/filter";
|
||||||
import { DisplayMode } from "src/models/list-filter/types";
|
import { DisplayMode } from "src/models/list-filter/types";
|
||||||
import { ExportDialog, DeleteEntityDialog } from "src/components/Shared";
|
import { ExportDialog, DeleteEntityDialog } from "src/components/Shared";
|
||||||
@@ -100,7 +100,7 @@ export const PerformerList: React.FC = () => {
|
|||||||
renderContent,
|
renderContent,
|
||||||
addKeybinds,
|
addKeybinds,
|
||||||
selectable: true,
|
selectable: true,
|
||||||
persistState: true,
|
persistState: PersistanceLevel.ALL,
|
||||||
renderDeleteDialog,
|
renderDeleteDialog,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { queryFindScenes } from "src/core/StashService";
|
|||||||
import { useScenesList } from "src/hooks";
|
import { useScenesList } from "src/hooks";
|
||||||
import { ListFilterModel } from "src/models/list-filter/filter";
|
import { ListFilterModel } from "src/models/list-filter/filter";
|
||||||
import { DisplayMode } from "src/models/list-filter/types";
|
import { DisplayMode } from "src/models/list-filter/types";
|
||||||
import { showWhenSelected } from "src/hooks/ListHook";
|
import { showWhenSelected, PersistanceLevel } from "src/hooks/ListHook";
|
||||||
import Tagger from "src/components/Tagger";
|
import Tagger from "src/components/Tagger";
|
||||||
import { WallPanel } from "../Wall/WallPanel";
|
import { WallPanel } from "../Wall/WallPanel";
|
||||||
import { SceneCard } from "./SceneCard";
|
import { SceneCard } from "./SceneCard";
|
||||||
@@ -22,7 +22,7 @@ import { ExportDialog } from "../Shared/ExportDialog";
|
|||||||
|
|
||||||
interface ISceneList {
|
interface ISceneList {
|
||||||
filterHook?: (filter: ListFilterModel) => ListFilterModel;
|
filterHook?: (filter: ListFilterModel) => ListFilterModel;
|
||||||
persistState?: boolean;
|
persistState?: PersistanceLevel.ALL;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SceneList: React.FC<ISceneList> = ({
|
export const SceneList: React.FC<ISceneList> = ({
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { FindSceneMarkersQueryResult } from "src/core/generated-graphql";
|
|||||||
import { queryFindSceneMarkers } from "src/core/StashService";
|
import { queryFindSceneMarkers } from "src/core/StashService";
|
||||||
import { NavUtils } from "src/utils";
|
import { NavUtils } from "src/utils";
|
||||||
import { useSceneMarkersList } from "src/hooks";
|
import { useSceneMarkersList } from "src/hooks";
|
||||||
|
import { PersistanceLevel } from "src/hooks/ListHook";
|
||||||
import { ListFilterModel } from "src/models/list-filter/filter";
|
import { ListFilterModel } from "src/models/list-filter/filter";
|
||||||
import { DisplayMode } from "src/models/list-filter/types";
|
import { DisplayMode } from "src/models/list-filter/types";
|
||||||
import { WallPanel } from "../Wall/WallPanel";
|
import { WallPanel } from "../Wall/WallPanel";
|
||||||
@@ -41,7 +42,7 @@ export const SceneMarkerList: React.FC<ISceneMarkerList> = ({ filterHook }) => {
|
|||||||
renderContent,
|
renderContent,
|
||||||
filterHook,
|
filterHook,
|
||||||
addKeybinds,
|
addKeybinds,
|
||||||
persistState: true,
|
persistState: PersistanceLevel.ALL,
|
||||||
});
|
});
|
||||||
|
|
||||||
async function playRandom(
|
async function playRandom(
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { Route, Switch } from "react-router-dom";
|
import { Route, Switch } from "react-router-dom";
|
||||||
|
import { PersistanceLevel } from "src/hooks/ListHook";
|
||||||
import { Scene } from "./SceneDetails/Scene";
|
import { Scene } from "./SceneDetails/Scene";
|
||||||
import { SceneList } from "./SceneList";
|
import { SceneList } from "./SceneList";
|
||||||
import { SceneMarkerList } from "./SceneMarkerList";
|
import { SceneMarkerList } from "./SceneMarkerList";
|
||||||
@@ -9,7 +10,9 @@ const Scenes = () => (
|
|||||||
<Route
|
<Route
|
||||||
exact
|
exact
|
||||||
path="/scenes"
|
path="/scenes"
|
||||||
render={(props) => <SceneList persistState {...props} />}
|
render={(props) => (
|
||||||
|
<SceneList persistState={PersistanceLevel.ALL} {...props} />
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
<Route exact path="/scenes/markers" component={SceneMarkerList} />
|
<Route exact path="/scenes/markers" component={SceneMarkerList} />
|
||||||
<Route path="/scenes/:id" component={Scene} />
|
<Route path="/scenes/:id" component={Scene} />
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import {
|
|||||||
SlimStudioDataFragment,
|
SlimStudioDataFragment,
|
||||||
} from "src/core/generated-graphql";
|
} from "src/core/generated-graphql";
|
||||||
import { useStudiosList } from "src/hooks";
|
import { useStudiosList } from "src/hooks";
|
||||||
import { showWhenSelected } from "src/hooks/ListHook";
|
import { showWhenSelected, PersistanceLevel } from "src/hooks/ListHook";
|
||||||
import { ListFilterModel } from "src/models/list-filter/filter";
|
import { ListFilterModel } from "src/models/list-filter/filter";
|
||||||
import { DisplayMode } from "src/models/list-filter/types";
|
import { DisplayMode } from "src/models/list-filter/types";
|
||||||
import { queryFindStudios, useStudiosDestroy } from "src/core/StashService";
|
import { queryFindStudios, useStudiosDestroy } from "src/core/StashService";
|
||||||
@@ -131,7 +131,7 @@ export const StudioList: React.FC<IStudioList> = ({
|
|||||||
addKeybinds,
|
addKeybinds,
|
||||||
otherOperations,
|
otherOperations,
|
||||||
selectable: true,
|
selectable: true,
|
||||||
persistState: !fromParent,
|
persistState: !fromParent ? PersistanceLevel.ALL : PersistanceLevel.NONE,
|
||||||
renderDeleteDialog,
|
renderDeleteDialog,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,11 @@ import Mousetrap from "mousetrap";
|
|||||||
import { FindTagsQueryResult } from "src/core/generated-graphql";
|
import { FindTagsQueryResult } from "src/core/generated-graphql";
|
||||||
import { ListFilterModel } from "src/models/list-filter/filter";
|
import { ListFilterModel } from "src/models/list-filter/filter";
|
||||||
import { DisplayMode } from "src/models/list-filter/types";
|
import { DisplayMode } from "src/models/list-filter/types";
|
||||||
import { showWhenSelected, useTagsList } from "src/hooks/ListHook";
|
import {
|
||||||
|
showWhenSelected,
|
||||||
|
useTagsList,
|
||||||
|
PersistanceLevel,
|
||||||
|
} from "src/hooks/ListHook";
|
||||||
import { Button } from "react-bootstrap";
|
import { Button } from "react-bootstrap";
|
||||||
import { Link, useHistory } from "react-router-dom";
|
import { Link, useHistory } from "react-router-dom";
|
||||||
import * as GQL from "src/core/generated-graphql";
|
import * as GQL from "src/core/generated-graphql";
|
||||||
@@ -144,7 +148,7 @@ export const TagList: React.FC<ITagList> = ({ filterHook }) => {
|
|||||||
selectable: true,
|
selectable: true,
|
||||||
zoomable: true,
|
zoomable: true,
|
||||||
defaultZoomIndex: 0,
|
defaultZoomIndex: 0,
|
||||||
persistState: true,
|
persistState: PersistanceLevel.ALL,
|
||||||
renderDeleteDialog,
|
renderDeleteDialog,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -79,8 +79,15 @@ export interface IListHookOperation<T> {
|
|||||||
postRefetch?: boolean;
|
postRefetch?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum PersistanceLevel {
|
||||||
|
NONE,
|
||||||
|
ALL,
|
||||||
|
VIEW,
|
||||||
|
}
|
||||||
|
|
||||||
interface IListHookOptions<T, E> {
|
interface IListHookOptions<T, E> {
|
||||||
persistState?: boolean;
|
persistState?: PersistanceLevel;
|
||||||
|
persistanceKey?: string;
|
||||||
filterHook?: (filter: ListFilterModel) => ListFilterModel;
|
filterHook?: (filter: ListFilterModel) => ListFilterModel;
|
||||||
zoomable?: boolean;
|
zoomable?: boolean;
|
||||||
selectable?: boolean;
|
selectable?: boolean;
|
||||||
@@ -421,22 +428,36 @@ const useList = <QueryResult extends IQueryResult, QueryData extends IDataItem>(
|
|||||||
);
|
);
|
||||||
// Store initial pathname to prevent hooks from operating outside this page
|
// Store initial pathname to prevent hooks from operating outside this page
|
||||||
const originalPathName = useRef(location.pathname);
|
const originalPathName = useRef(location.pathname);
|
||||||
|
const persistanceKey = options.persistanceKey ?? options.filterMode;
|
||||||
|
|
||||||
const [filter, setFilter] = useState<ListFilterModel>(
|
const [filter, setFilter] = useState<ListFilterModel>(
|
||||||
new ListFilterModel(options.filterMode, queryString.parse(location.search))
|
new ListFilterModel(options.filterMode, queryString.parse(location.search))
|
||||||
);
|
);
|
||||||
|
|
||||||
const updateInterfaceConfig = useCallback(
|
const updateInterfaceConfig = useCallback(
|
||||||
(updatedFilter: ListFilterModel) => {
|
(updatedFilter: ListFilterModel, level: PersistanceLevel) => {
|
||||||
setInterfaceState({
|
setInterfaceState((prevState) => {
|
||||||
[options.filterMode]: {
|
if (level === PersistanceLevel.VIEW) {
|
||||||
|
return {
|
||||||
|
[persistanceKey]: {
|
||||||
|
...prevState[persistanceKey],
|
||||||
|
filter: queryString.stringify({
|
||||||
|
...queryString.parse(prevState[persistanceKey]?.filter ?? ""),
|
||||||
|
disp: updatedFilter.displayMode,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
[persistanceKey]: {
|
||||||
filter: updatedFilter.makeQueryParameters(),
|
filter: updatedFilter.makeQueryParameters(),
|
||||||
itemsPerPage: updatedFilter.itemsPerPage,
|
itemsPerPage: updatedFilter.itemsPerPage,
|
||||||
currentPage: updatedFilter.currentPage,
|
currentPage: updatedFilter.currentPage,
|
||||||
},
|
},
|
||||||
|
};
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
[options.filterMode, setInterfaceState]
|
[persistanceKey, setInterfaceState]
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -451,20 +472,25 @@ const useList = <QueryResult extends IQueryResult, QueryData extends IDataItem>(
|
|||||||
|
|
||||||
if (!options.persistState) return;
|
if (!options.persistState) return;
|
||||||
|
|
||||||
const storedQuery = interfaceState.data?.[options.filterMode];
|
const storedQuery = interfaceState.data?.[persistanceKey];
|
||||||
if (!storedQuery) return;
|
if (!storedQuery) return;
|
||||||
|
|
||||||
const queryFilter = queryString.parse(history.location.search);
|
const queryFilter = queryString.parse(history.location.search);
|
||||||
const storedFilter = queryString.parse(storedQuery.filter);
|
const storedFilter = queryString.parse(storedQuery.filter);
|
||||||
|
|
||||||
|
const activeFilter =
|
||||||
|
options.persistState === PersistanceLevel.ALL
|
||||||
|
? storedFilter
|
||||||
|
: { disp: storedFilter.disp };
|
||||||
const query = history.location.search
|
const query = history.location.search
|
||||||
? {
|
? {
|
||||||
sortby: storedFilter.sortby,
|
sortby: activeFilter.sortby,
|
||||||
sortdir: storedFilter.sortdir,
|
sortdir: activeFilter.sortdir,
|
||||||
disp: storedFilter.disp,
|
disp: activeFilter.disp,
|
||||||
perPage: storedFilter.perPage,
|
perPage: activeFilter.perPage,
|
||||||
...queryFilter,
|
...queryFilter,
|
||||||
}
|
}
|
||||||
: storedFilter;
|
: activeFilter;
|
||||||
|
|
||||||
const newFilter = new ListFilterModel(options.filterMode, query);
|
const newFilter = new ListFilterModel(options.filterMode, query);
|
||||||
|
|
||||||
@@ -474,7 +500,7 @@ const useList = <QueryResult extends IQueryResult, QueryData extends IDataItem>(
|
|||||||
newLocation.search = newFilter.makeQueryParameters();
|
newLocation.search = newFilter.makeQueryParameters();
|
||||||
if (newLocation.search !== filter.makeQueryParameters()) {
|
if (newLocation.search !== filter.makeQueryParameters()) {
|
||||||
setFilter(newFilter);
|
setFilter(newFilter);
|
||||||
updateInterfaceConfig(newFilter);
|
updateInterfaceConfig(newFilter, options.persistState);
|
||||||
}
|
}
|
||||||
// If constructed search is different from current, update it as well
|
// If constructed search is different from current, update it as well
|
||||||
if (newLocation.search !== location.search) {
|
if (newLocation.search !== location.search) {
|
||||||
@@ -488,6 +514,7 @@ const useList = <QueryResult extends IQueryResult, QueryData extends IDataItem>(
|
|||||||
history,
|
history,
|
||||||
location.search,
|
location.search,
|
||||||
options.filterMode,
|
options.filterMode,
|
||||||
|
persistanceKey,
|
||||||
forageInitialised,
|
forageInitialised,
|
||||||
updateInterfaceConfig,
|
updateInterfaceConfig,
|
||||||
options.persistState,
|
options.persistState,
|
||||||
@@ -499,7 +526,7 @@ const useList = <QueryResult extends IQueryResult, QueryData extends IDataItem>(
|
|||||||
newLocation.search = listFilter.makeQueryParameters();
|
newLocation.search = listFilter.makeQueryParameters();
|
||||||
history.replace(newLocation);
|
history.replace(newLocation);
|
||||||
if (options.persistState) {
|
if (options.persistState) {
|
||||||
updateInterfaceConfig(listFilter);
|
updateInterfaceConfig(listFilter, options.persistState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user