diff options
author | LASER-Yi <[email protected]> | 2021-08-17 22:27:33 +0800 |
---|---|---|
committer | LASER-Yi <[email protected]> | 2021-08-17 22:27:33 +0800 |
commit | 8348118ff297f59a1d442828f5204ef1cdc1f386 (patch) | |
tree | 5a41272ab6b74734b1f139059e9a267109022733 | |
parent | 156cf1882c0de7f7f2d990781a8b6d2c80bb1a6a (diff) | |
download | bazarr-8348118ff297f59a1d442828f5204ef1cdc1f386.tar.gz bazarr-8348118ff297f59a1d442828f5204ef1cdc1f386.zip |
Add pagination support to history page
-rw-r--r-- | bazarr/api.py | 6 | ||||
-rw-r--r-- | frontend/src/@redux/actions/movie.ts | 12 | ||||
-rw-r--r-- | frontend/src/@redux/actions/series.ts | 12 | ||||
-rw-r--r-- | frontend/src/@redux/hooks/movies.ts | 3 | ||||
-rw-r--r-- | frontend/src/@redux/hooks/series.ts | 3 | ||||
-rw-r--r-- | frontend/src/@redux/reducers/movie.ts | 10 | ||||
-rw-r--r-- | frontend/src/@redux/reducers/series.ts | 10 | ||||
-rw-r--r-- | frontend/src/@socketio/reducer.ts | 6 | ||||
-rw-r--r-- | frontend/src/@types/api.d.ts | 1 | ||||
-rw-r--r-- | frontend/src/History/Movies/index.tsx | 6 | ||||
-rw-r--r-- | frontend/src/History/Series/index.tsx | 6 | ||||
-rw-r--r-- | frontend/src/History/generic/index.tsx | 34 | ||||
-rw-r--r-- | frontend/src/apis/episodes.ts | 24 | ||||
-rw-r--r-- | frontend/src/apis/movies.ts | 26 | ||||
-rw-r--r-- | frontend/src/components/modals/HistoryModal.tsx | 12 |
15 files changed, 92 insertions, 79 deletions
diff --git a/bazarr/api.py b/bazarr/api.py index 5e56f61f7..29a4c8486 100644 --- a/bazarr/api.py +++ b/bazarr/api.py @@ -1419,7 +1419,8 @@ class EpisodesHistory(Resource): if episodeid: query_conditions.append((TableEpisodes.sonarrEpisodeId == episodeid)) query_condition = reduce(operator.and_, query_conditions) - episode_history = TableHistory.select(TableShows.title.alias('seriesTitle'), + episode_history = TableHistory.select(TableHistory.id, + TableShows.title.alias('seriesTitle'), TableEpisodes.monitored, TableEpisodes.season.concat('x').concat(TableEpisodes.episode).alias('episode_number'), TableEpisodes.title.alias('episodeTitle'), @@ -1535,7 +1536,8 @@ class MoviesHistory(Resource): query_conditions.append((TableMovies.radarrId == radarrid)) query_condition = reduce(operator.and_, query_conditions) - movie_history = TableHistoryMovie.select(TableHistoryMovie.action, + movie_history = TableHistoryMovie.select(TableHistoryMovie.id, + TableHistoryMovie.action, TableMovies.title, TableHistoryMovie.timestamp, TableHistoryMovie.description, diff --git a/frontend/src/@redux/actions/movie.ts b/frontend/src/@redux/actions/movie.ts index 6deafc770..af9aa4c1b 100644 --- a/frontend/src/@redux/actions/movie.ts +++ b/frontend/src/@redux/actions/movie.ts @@ -55,15 +55,17 @@ export const movieUpdateWantedByRange = createAsyncThunk( } ); -export const movieUpdateHistory = createAsyncThunk( - "movies/history/update", - async () => { - const response = await MoviesApi.history(); +export const movieUpdateHistoryByRange = createAsyncThunk( + "movies/history/update/range", + async (params: Parameter.Range) => { + const response = await MoviesApi.history(params); return response; } ); -export const movieMarkHistoryDirty = createAction("movies/history/mark_dirty"); +export const movieMarkHistoryDirty = createAction<number[]>( + "movies/history/mark_dirty" +); export const movieUpdateBlacklist = createAsyncThunk( "movies/blacklist/update", diff --git a/frontend/src/@redux/actions/series.ts b/frontend/src/@redux/actions/series.ts index 41e79408a..a9ab035a6 100644 --- a/frontend/src/@redux/actions/series.ts +++ b/frontend/src/@redux/actions/series.ts @@ -77,15 +77,17 @@ export const episodeUpdateById = createAsyncThunk( } ); -export const episodesUpdateHistory = createAsyncThunk( - "episodes/history/update", - async () => { - const response = await EpisodesApi.history(); +export const episodesUpdateHistoryByRange = createAsyncThunk( + "episodes/history/update/range", + async (param: Parameter.Range) => { + const response = await EpisodesApi.history(param); return response; } ); -export const episodesMarkHistoryDirty = createAction("episodes/history/update"); +export const episodesMarkHistoryDirty = createAction<number[]>( + "episodes/history/update" +); export const episodesUpdateBlacklist = createAsyncThunk( "episodes/blacklist/update", diff --git a/frontend/src/@redux/hooks/movies.ts b/frontend/src/@redux/hooks/movies.ts index 0a027818e..df8a82272 100644 --- a/frontend/src/@redux/hooks/movies.ts +++ b/frontend/src/@redux/hooks/movies.ts @@ -3,7 +3,6 @@ import { useEntityItemById, useEntityToList } from "../../utilites"; import { movieUpdateBlacklist, movieUpdateById, - movieUpdateHistory, movieUpdateWantedById, } from "../actions"; import { useAutoDirtyUpdate, useAutoUpdate } from "./async"; @@ -62,9 +61,7 @@ export function useBlacklistMovies() { } export function useMoviesHistory() { - const update = useReduxAction(movieUpdateHistory); const items = useReduxStore((s) => s.movies.historyList); - useAutoUpdate(items, update); return items; } diff --git a/frontend/src/@redux/hooks/series.ts b/frontend/src/@redux/hooks/series.ts index 0de8df2cc..d37b7eb32 100644 --- a/frontend/src/@redux/hooks/series.ts +++ b/frontend/src/@redux/hooks/series.ts @@ -2,7 +2,6 @@ import { useCallback, useEffect, useMemo } from "react"; import { useEntityItemById, useEntityToList } from "../../utilites"; import { episodesUpdateBlacklist, - episodesUpdateHistory, episodeUpdateById, episodeUpdateBySeriesId, seriesUpdateById, @@ -94,9 +93,7 @@ export function useBlacklistSeries() { } export function useSeriesHistory() { - const update = useReduxAction(episodesUpdateHistory); const items = useReduxStore((s) => s.series.historyList); - useAutoUpdate(items, update); return items; } diff --git a/frontend/src/@redux/reducers/movie.ts b/frontend/src/@redux/reducers/movie.ts index 7de902801..78ad5e86c 100644 --- a/frontend/src/@redux/reducers/movie.ts +++ b/frontend/src/@redux/reducers/movie.ts @@ -10,7 +10,7 @@ import { movieUpdateBlacklist, movieUpdateById, movieUpdateByRange, - movieUpdateHistory, + movieUpdateHistoryByRange, movieUpdateWantedById, movieUpdateWantedByRange, } from "../actions"; @@ -23,14 +23,14 @@ import { interface Movie { movieList: Async.Entity<Item.Movie>; wantedMovieList: Async.Entity<Wanted.Movie>; - historyList: Async.Item<History.Movie[]>; + historyList: Async.Entity<History.Movie>; blacklist: Async.Item<Blacklist.Movie[]>; } const defaultMovie: Movie = { movieList: AsyncUtility.getDefaultEntity("radarrId"), wantedMovieList: AsyncUtility.getDefaultEntity("radarrId"), - historyList: AsyncUtility.getDefaultItem(), + historyList: AsyncUtility.getDefaultEntity("id"), blacklist: AsyncUtility.getDefaultItem(), }; @@ -50,8 +50,8 @@ const reducer = createReducer(defaultMovie, (builder) => { dirty: movieMarkWantedDirtyById, }); - createAsyncItemReducer(builder, (s) => s.historyList, { - all: movieUpdateHistory, + createAsyncEntityReducer(builder, (s) => s.historyList, { + range: movieUpdateHistoryByRange, dirty: movieMarkHistoryDirty, }); diff --git a/frontend/src/@redux/reducers/series.ts b/frontend/src/@redux/reducers/series.ts index 1facde9f1..1ce6dbc25 100644 --- a/frontend/src/@redux/reducers/series.ts +++ b/frontend/src/@redux/reducers/series.ts @@ -5,7 +5,7 @@ import { episodesMarkHistoryDirty, episodesRemoveById, episodesUpdateBlacklist, - episodesUpdateHistory, + episodesUpdateHistoryByRange, episodeUpdateById, episodeUpdateBySeriesId, seriesMarkDirtyById, @@ -29,7 +29,7 @@ interface Series { seriesList: Async.Entity<Item.Series>; wantedEpisodesList: Async.Entity<Wanted.Episode>; episodeList: Async.List<Item.Episode>; - historyList: Async.Item<History.Episode[]>; + historyList: Async.Entity<History.Episode>; blacklist: Async.Item<Blacklist.Episode[]>; } @@ -37,7 +37,7 @@ const defaultSeries: Series = { seriesList: AsyncUtility.getDefaultEntity("sonarrSeriesId"), wantedEpisodesList: AsyncUtility.getDefaultEntity("sonarrEpisodeId"), episodeList: AsyncUtility.getDefaultList("sonarrEpisodeId"), - historyList: AsyncUtility.getDefaultItem(), + historyList: AsyncUtility.getDefaultEntity("id"), blacklist: AsyncUtility.getDefaultItem(), }; @@ -72,8 +72,8 @@ const reducer = createReducer(defaultSeries, (builder) => { dirty: seriesMarkWantedDirtyById, }); - createAsyncItemReducer(builder, (s) => s.historyList, { - all: episodesUpdateHistory, + createAsyncEntityReducer(builder, (s) => s.historyList, { + range: episodesUpdateHistoryByRange, dirty: episodesMarkHistoryDirty, }); diff --git a/frontend/src/@socketio/reducer.ts b/frontend/src/@socketio/reducer.ts index 8ed251a97..153915939 100644 --- a/frontend/src/@socketio/reducer.ts +++ b/frontend/src/@socketio/reducer.ts @@ -2,11 +2,9 @@ import { ActionCreator } from "@reduxjs/toolkit"; import { episodesMarkBlacklistDirty, episodesMarkDirtyById, - episodesMarkHistoryDirty, episodesRemoveById, movieMarkBlacklistDirty, movieMarkDirtyById, - movieMarkHistoryDirty, movieMarkWantedDirtyById, movieRemoveById, movieRemoveWantedById, @@ -130,7 +128,7 @@ export function createDefaultReducer(): SocketIO.Reducer[] { }, { key: "movie-history", - any: bindReduxAction(movieMarkHistoryDirty), + // any: bindReduxAction(movieMarkHistoryDirty), }, { key: "movie-blacklist", @@ -138,7 +136,7 @@ export function createDefaultReducer(): SocketIO.Reducer[] { }, { key: "episode-history", - any: bindReduxAction(episodesMarkHistoryDirty), + // any: bindReduxAction(episodesMarkHistoryDirty), }, { key: "episode-blacklist", diff --git a/frontend/src/@types/api.d.ts b/frontend/src/@types/api.d.ts index bcc5abed9..043753879 100644 --- a/frontend/src/@types/api.d.ts +++ b/frontend/src/@types/api.d.ts @@ -195,6 +195,7 @@ declare namespace History { TagType & MonitoredType & Partial<ItemHistoryType> & { + id: number; action: number; blacklisted: boolean; score?: string; diff --git a/frontend/src/History/Movies/index.tsx b/frontend/src/History/Movies/index.tsx index 7669bf30c..9a387ecae 100644 --- a/frontend/src/History/Movies/index.tsx +++ b/frontend/src/History/Movies/index.tsx @@ -4,7 +4,9 @@ import React, { FunctionComponent, useMemo } from "react"; import { Badge, OverlayTrigger, Popover } from "react-bootstrap"; import { Link } from "react-router-dom"; import { Column } from "react-table"; +import { movieUpdateHistoryByRange } from "../../@redux/actions"; import { useMoviesHistory } from "../../@redux/hooks"; +import { useReduxAction } from "../../@redux/hooks/base"; import { MoviesApi } from "../../apis"; import { HistoryIcon, LanguageText, TextPopover } from "../../components"; import { BlacklistButton } from "../../generic/blacklist"; @@ -14,6 +16,7 @@ interface Props {} const MoviesHistoryView: FunctionComponent<Props> = () => { const movies = useMoviesHistory(); + const loader = useReduxAction(movieUpdateHistoryByRange); const columns: Column<History.Movie>[] = useMemo<Column<History.Movie>[]>( () => [ @@ -128,7 +131,8 @@ const MoviesHistoryView: FunctionComponent<Props> = () => { <HistoryGenericView type="movies" state={movies} - columns={columns as Column<History.Base>[]} + loader={loader} + columns={columns} ></HistoryGenericView> ); }; diff --git a/frontend/src/History/Series/index.tsx b/frontend/src/History/Series/index.tsx index 6c82d84a1..e96c3e689 100644 --- a/frontend/src/History/Series/index.tsx +++ b/frontend/src/History/Series/index.tsx @@ -4,7 +4,9 @@ import React, { FunctionComponent, useMemo } from "react"; import { Badge, OverlayTrigger, Popover } from "react-bootstrap"; import { Link } from "react-router-dom"; import { Column } from "react-table"; +import { episodesUpdateHistoryByRange } from "../../@redux/actions"; import { useSeriesHistory } from "../../@redux/hooks"; +import { useReduxAction } from "../../@redux/hooks/base"; import { EpisodesApi } from "../../apis"; import { HistoryIcon, LanguageText, TextPopover } from "../../components"; import { BlacklistButton } from "../../generic/blacklist"; @@ -14,6 +16,7 @@ interface Props {} const SeriesHistoryView: FunctionComponent<Props> = () => { const series = useSeriesHistory(); + const loader = useReduxAction(episodesUpdateHistoryByRange); const columns: Column<History.Episode>[] = useMemo<Column<History.Episode>[]>( () => [ @@ -137,7 +140,8 @@ const SeriesHistoryView: FunctionComponent<Props> = () => { <HistoryGenericView type="series" state={series} - columns={columns as Column<History.Base>[]} + loader={loader} + columns={columns} ></HistoryGenericView> ); }; diff --git a/frontend/src/History/generic/index.tsx b/frontend/src/History/generic/index.tsx index 58dbe5acd..0775c6fae 100644 --- a/frontend/src/History/generic/index.tsx +++ b/frontend/src/History/generic/index.tsx @@ -1,21 +1,23 @@ import { capitalize } from "lodash"; -import React, { FunctionComponent } from "react"; +import React from "react"; import { Container, Row } from "react-bootstrap"; import { Helmet } from "react-helmet"; import { Column } from "react-table"; -import { AsyncOverlay, PageTable } from "../../components"; +import { AsyncPageTable } from "../../components"; -interface Props { +interface Props<T extends History.Base> { type: "movies" | "series"; - state: Readonly<Async.Item<History.Base[]>>; - columns: Column<History.Base>[]; + state: Readonly<Async.Entity<T>>; + loader: (param: Parameter.Range) => void; + columns: Column<T>[]; } -const HistoryGenericView: FunctionComponent<Props> = ({ +function HistoryGenericView<T extends History.Base = History.Base>({ state, + loader, columns, type, -}) => { +}: Props<T>) { const typeName = capitalize(type); return ( <Container fluid> @@ -23,18 +25,16 @@ const HistoryGenericView: FunctionComponent<Props> = ({ <title>{typeName} History - Bazarr</title> </Helmet> <Row> - <AsyncOverlay ctx={state}> - {({ content }) => ( - <PageTable - emptyText={`Nothing Found in ${typeName} History`} - columns={columns} - data={content ?? []} - ></PageTable> - )} - </AsyncOverlay> + <AsyncPageTable + emptyText={`Nothing Found in ${typeName} History`} + entity={state} + loader={loader} + columns={columns} + data={[]} + ></AsyncPageTable> </Row> </Container> ); -}; +} export default HistoryGenericView; diff --git a/frontend/src/apis/episodes.ts b/frontend/src/apis/episodes.ts index 4b8eefa0e..e369918d5 100644 --- a/frontend/src/apis/episodes.ts +++ b/frontend/src/apis/episodes.ts @@ -53,16 +53,20 @@ class EpisodeApi extends BaseApi { }); } - async history(episodeid?: number): Promise<History.Episode[]> { - return new Promise<History.Episode[]>((resolve, reject) => { - this.get<DataWrapper<History.Episode[]>>("/history", { episodeid }) - .then((result) => { - resolve(result.data.data); - }) - .catch((reason) => { - reject(reason); - }); - }); + async history(params: Parameter.Range) { + const response = await this.get<AsyncDataWrapper<History.Episode>>( + "/history", + params + ); + return response.data; + } + + async historyBy(episodeid: number) { + const response = await this.get<AsyncDataWrapper<History.Episode>>( + "/history", + { episodeid } + ); + return response.data; } async downloadSubtitles( diff --git a/frontend/src/apis/movies.ts b/frontend/src/apis/movies.ts index ac6bad5ae..aa978a77e 100644 --- a/frontend/src/apis/movies.ts +++ b/frontend/src/apis/movies.ts @@ -93,18 +93,20 @@ class MovieApi extends BaseApi { }); } - async history(id?: number): Promise<History.Movie[]> { - return new Promise<History.Movie[]>((resolve, reject) => { - this.get<DataWrapper<History.Movie[]>>("/history", { - radarrid: id, - }) - .then((result) => { - resolve(result.data.data); - }) - .catch((reason) => { - reject(reason); - }); - }); + async history(params: Parameter.Range) { + const response = await this.get<AsyncDataWrapper<History.Movie>>( + "/history", + params + ); + return response.data; + } + + async historyBy(radarrid: number) { + const response = await this.get<AsyncDataWrapper<History.Movie>>( + "/history", + { radarrid } + ); + return response.data; } async action(action: FormType.MoviesAction) { diff --git a/frontend/src/components/modals/HistoryModal.tsx b/frontend/src/components/modals/HistoryModal.tsx index 79f14b9ff..9e19d8295 100644 --- a/frontend/src/components/modals/HistoryModal.tsx +++ b/frontend/src/components/modals/HistoryModal.tsx @@ -14,8 +14,8 @@ export const MovieHistoryModal: FunctionComponent<BaseModalProps> = (props) => { const movie = useModalPayload<Item.Movie>(modal.modalKey); const [history, updateHistory] = useAsyncRequest( - MoviesApi.history.bind(MoviesApi), - [] + MoviesApi.historyBy.bind(MoviesApi), + { data: [], total: 0 } ); const update = useCallback(() => { @@ -98,7 +98,7 @@ export const MovieHistoryModal: FunctionComponent<BaseModalProps> = (props) => { <PageTable emptyText="No History Found" columns={columns} - data={content} + data={content.data} ></PageTable> )} </AsyncOverlay> @@ -114,8 +114,8 @@ export const EpisodeHistoryModal: FunctionComponent< const episode = useModalPayload<Item.Episode>(props.modalKey); const [history, updateHistory] = useAsyncRequest( - EpisodesApi.history.bind(EpisodesApi), - [] + EpisodesApi.historyBy.bind(EpisodesApi), + { data: [], total: 0 } ); const update = useCallback(() => { @@ -199,7 +199,7 @@ export const EpisodeHistoryModal: FunctionComponent< <PageTable emptyText="No History Found" columns={columns} - data={content} + data={content.data} ></PageTable> )} </AsyncOverlay> |