summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorLASER-Yi <[email protected]>2021-08-17 22:27:33 +0800
committerLASER-Yi <[email protected]>2021-08-17 22:27:33 +0800
commit8348118ff297f59a1d442828f5204ef1cdc1f386 (patch)
tree5a41272ab6b74734b1f139059e9a267109022733
parent156cf1882c0de7f7f2d990781a8b6d2c80bb1a6a (diff)
downloadbazarr-8348118ff297f59a1d442828f5204ef1cdc1f386.tar.gz
bazarr-8348118ff297f59a1d442828f5204ef1cdc1f386.zip
Add pagination support to history page
-rw-r--r--bazarr/api.py6
-rw-r--r--frontend/src/@redux/actions/movie.ts12
-rw-r--r--frontend/src/@redux/actions/series.ts12
-rw-r--r--frontend/src/@redux/hooks/movies.ts3
-rw-r--r--frontend/src/@redux/hooks/series.ts3
-rw-r--r--frontend/src/@redux/reducers/movie.ts10
-rw-r--r--frontend/src/@redux/reducers/series.ts10
-rw-r--r--frontend/src/@socketio/reducer.ts6
-rw-r--r--frontend/src/@types/api.d.ts1
-rw-r--r--frontend/src/History/Movies/index.tsx6
-rw-r--r--frontend/src/History/Series/index.tsx6
-rw-r--r--frontend/src/History/generic/index.tsx34
-rw-r--r--frontend/src/apis/episodes.ts24
-rw-r--r--frontend/src/apis/movies.ts26
-rw-r--r--frontend/src/components/modals/HistoryModal.tsx12
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>