Skip to content

Commit

Permalink
Added a "load more" button to recommended shows, be able to paginate …
Browse files Browse the repository at this point in the history
…results (#10380)

* Add pagination to the recommended show api.

* Reduce the pagination limit to 500

* Renamed to load more.

* Added loading spinner

* Fix loader

* refactor

* Fix eslint

Co-authored-by: rogierhelmer <rogier.helmer@maxserv.com>
  • Loading branch information
p0psicles and RogierHelmerAtWork authored Mar 2, 2022
1 parent 135f75d commit bb4fb0c
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 59 deletions.
24 changes: 10 additions & 14 deletions medusa/server/api/v2/recommended.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,27 +39,23 @@ class RecommendedHandler(BaseRequestHandler):

def get(self, identifier, path_param=None):
"""Query available recommended show lists."""
if identifier and not RecommendedHandler.IDENTIFIER_TO_LIST.get(identifier):
if identifier and not RecommendedHandler.IDENTIFIER_TO_LIST.get(identifier) and identifier != 'categories':
return self._bad_request("Invalid recommended list identifier '{0}'".format(identifier))

data = {'shows': [], 'trakt': {'removedFromMedusa': []}}

shows = get_recommended_shows(source=RecommendedHandler.IDENTIFIER_TO_LIST.get(identifier))

if shows:
data['shows'] = [show.to_json() for show in shows]

data['trakt']['removedFromMedusa'] = []
if app.USE_TRAKT:
if identifier == 'trakt' and path_param == 'removed' and app.USE_TRAKT:
data = {'removedFromMedusa': [], 'blacklistEnabled': None}
try:
data['trakt']['removedFromMedusa'] = TraktPopular().get_removed_from_medusa()
data['removedFromMedusa'] = TraktPopular().get_removed_from_medusa()
except Exception:
log.warning('Could not get the `removed from medusa` list')
data['trakt']['blacklistEnabled'] = app.TRAKT_BLACKLIST_NAME != ''
data['blacklistEnabled'] = app.TRAKT_BLACKLIST_NAME != ''
return self._ok(data)

data['categories'] = get_categories()
if identifier == 'categories':
return self._ok(get_categories())

return self._ok(data)
shows = get_recommended_shows(source=RecommendedHandler.IDENTIFIER_TO_LIST.get(identifier))
return self._paginate([show.to_json() for show in shows], sort='-rating')

def post(self, identifier, path_param=None):
"""Force the start of a recommended show queue item."""
Expand Down
47 changes: 35 additions & 12 deletions themes-default/slim/src/components/recommended.vue
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,10 @@
Search for new recommended shows from {{sourceToString[selectedSource]}}
</button>
</div>

<div v-else-if="page[selectedSource] !== -1" class="load-more">
<state-switch v-if="loadingShows" state="loading" />
<button v-else class="btn-medusa" @click="getMore">Load More</button>
</div>
</div> <!-- End of col -->
</div> <!-- End of row -->
</div>
Expand All @@ -86,6 +89,7 @@ import AddShowOptions from './add-show-options.vue';
import {
ConfigTemplate,
ConfigToggleSlider,
StateSwitch,
TraktAuthentication
} from './helpers';
import RecommendedPoster from './recommended-poster.vue';
Expand All @@ -99,6 +103,7 @@ export default {
ConfigTemplate,
ConfigToggleSlider,
FontAwesomeIcon,
StateSwitch,
RecommendedPoster,
TraktAuthentication,
Isotope
Expand Down Expand Up @@ -198,27 +203,28 @@ export default {
showTraktAuthDialog: false,
traktWarning: false,
traktWarningMessage: '',
showsLoaded: false
showsLoaded: false,
loadingShows: false
};
},
async mounted() {
const { getRecommendedShows, sourceToString } = this;
const identifiers = Object.values(sourceToString);
const { getRecommendedShows, getRecommendedShowsOptions, sourceToString } = this;
const sources = Object.keys(sourceToString);
await getRecommendedShowsOptions();
for (const identifier of identifiers) {
for (const source of sources) {
this.loadingShows = true;
// eslint-disable-next-line no-await-in-loop
await getRecommendedShows(identifier);
await getRecommendedShows(source);
this.loadingShows = false;
}
this.showsLoaded = true;
this.$nextTick(() => {
this.isotopeLayout();
});
this.$once('loaded', () => {
this.configLoaded = true;
});
this.$watch('recommendedLists', () => {
this.setSelectedList(this.selectedSource);
});
Expand All @@ -231,7 +237,8 @@ export default {
traktConfig: state => state.recommended.trakt,
recommendedLists: state => state.recommended.categories,
queueitems: state => state.queue.queueitems,
sourceToString: state => state.recommended.sourceToString
sourceToString: state => state.recommended.sourceToString,
page: state => state.recommended.page
}),
filteredShowsByList() {
const { imgLazyLoad, recommendedShows, selectedSource, selectedList } = this;
Expand Down Expand Up @@ -262,13 +269,18 @@ export default {
},
listOptions() {
const { recommendedLists, selectedSource } = this;
if (!recommendedLists || !(selectedSource in recommendedLists)) {
return;
}
const sourceLists = recommendedLists[selectedSource] || [];
return sourceLists.map(list => ({ text: list, value: list }));
}
},
methods: {
...mapActions({
getRecommendedShows: 'getRecommendedShows'
getRecommendedShows: 'getRecommendedShows',
getRecommendedShowsOptions: 'getRecommendedShowsOptions',
getMoreShows: 'getMoreShows'
}),
containerClass(show) {
let classes = 'recommended-container default-poster show-row';
Expand Down Expand Up @@ -355,6 +367,13 @@ export default {
);
}
}
},
getMore() {
this.loadingShows = true;
this.getMoreShows(this.selectedSource)
.finally(() => {
this.loadingShows = false;
});
}
},
watch: {
Expand Down Expand Up @@ -410,4 +429,8 @@ span.trakt-warning {
color: red;
}
.load-more {
display: flex;
justify-content: center;
}
</style>
66 changes: 45 additions & 21 deletions themes-default/slim/src/store/modules/recommended.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import { api } from '../../api';
import {
ADD_RECOMMENDED_SHOW,
SET_RECOMMENDED_SHOWS,
SET_RECOMMENDED_SHOWS_OPTIONS
SET_RECOMMENDED_SHOWS_TRAKT_REMOVED,
SET_RECOMMENDED_SHOWS_CATEGORIES
} from '../mutation-types';

const IMDB = 10;
Expand All @@ -12,6 +13,13 @@ const TRAKT = 12;
const ANILIST = 13;

const state = {
limit: 500,
page: {
[IMDB]: 1,
[ANIDB]: 1,
[TRAKT]: 1,
[ANILIST]: 1
},
shows: [],
trakt: {
removedFromMedusa: [],
Expand Down Expand Up @@ -56,24 +64,23 @@ const mutations = {
Vue.set(state.shows, state.shows.indexOf(existingShow), newShow);
console.debug(`Merged ${newShow.title || newShow.source + String(newShow.seriesId)}`, newShow);
},
[SET_RECOMMENDED_SHOWS](state, { shows, identifier }) {
if (identifier) {
// If an identifier has been passed, remove the old shows for this identifier.
const source = Number(Object.keys(state.sourceToString).find(key => state.sourceToString[key] === identifier));
state.shows = state.shows.filter(show => show.source !== source);
} else {
// No identifier passed, meaning remove all shows from store.
state.shows = [];
[SET_RECOMMENDED_SHOWS](state, { shows, source }) {
if (shows.length < state.limit) {
state.page[source] = -1;
}
state.shows = [...state.shows, ...shows];
},
[SET_RECOMMENDED_SHOWS_OPTIONS](state, data) {
state.trakt.removedFromMedusa = data.trakt.removedFromMedusa;
state.trakt.blacklistEnabled = data.trakt.blacklistEnabled;
state.trakt.availableLists = data.trakt.availableLists;
state.categories = data.categories;
[SET_RECOMMENDED_SHOWS_TRAKT_REMOVED](state, data) {
state.trakt.removedFromMedusa = data.removedFromMedusa;
state.trakt.blacklistEnabled = data.blacklistEnabled;
state.trakt.availableLists = data.availableLists;
},
[SET_RECOMMENDED_SHOWS_CATEGORIES](state, data) {
state.categories = data;
},
increasePage(state, source) {
state.page[source] += 1;
}

};

const getters = {};
Expand All @@ -83,16 +90,33 @@ const actions = {
* Get recommended shows from API and commit them to the store.
*
* @param {*} context - The store context.
* @param {String} identifier - Identifier for the recommended shows list.
* @param {String} source - Identifier for the recommended shows list.
* @returns {(undefined|Promise)} undefined if `shows` was provided or the API response if not.
*/
getRecommendedShows({ commit }, identifier) {
identifier = identifier ? identifier : '';
return api.get(`/recommended/${identifier}`, { timeout: 60000 })
getRecommendedShows({ state, commit }, source) {
if (state.page[source] === -1) {
return;
}
const identifier = source ? state.sourceToString[source] : '';
const { page } = state;
return api.get(`/recommended/${identifier}?page=${page[source]}&limit=${state.limit}`, { timeout: 60000 })
.then(response => {
commit(SET_RECOMMENDED_SHOWS, { shows: response.data.shows, identifier });
commit(SET_RECOMMENDED_SHOWS_OPTIONS, response.data);
commit(SET_RECOMMENDED_SHOWS, { shows: response.data, source });
});
},
getRecommendedShowsOptions({ commit }) {
api.get('/recommended/trakt/removed', { timeout: 60000 })
.then(response => {
commit(SET_RECOMMENDED_SHOWS_TRAKT_REMOVED, response.data);
});
api.get('/recommended/categories', { timeout: 60000 })
.then(response => {
commit(SET_RECOMMENDED_SHOWS_CATEGORIES, response.data);
});
},
getMoreShows({ commit, dispatch }, source) {
commit('increasePage', source);
return dispatch('getRecommendedShows', source);
}
};

Expand Down
6 changes: 4 additions & 2 deletions themes-default/slim/src/store/mutation-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ const ADD_SHOW_EPISODE = '📺 Shows season with episodes added to store';
const ADD_STATS = 'ℹ️ Statistics added to store';
const ADD_RECOMMENDED_SHOW = '📺 Recommended Show added to store';
const SET_RECOMMENDED_SHOWS = '📺 Recommended Shows added to store';
const SET_RECOMMENDED_SHOWS_OPTIONS = '📺 Recommended Show Options added to store';
const SET_RECOMMENDED_SHOWS_TRAKT_REMOVED = '📺 Recommended Show Trakt removed added to store';
const SET_RECOMMENDED_SHOWS_CATEGORIES = '📺 Recommended Show categories added to store';
const SET_STATS = 'SET_STATS';
const SET_MAX_DOWNLOAD_COUNT = 'SET_MAX_DOWNLOAD_COUNT';
const ADD_SHOW_SCENE_EXCEPTION = '📺 Add a scene exception';
Expand Down Expand Up @@ -68,7 +69,8 @@ export {
ADD_SHOW_CONFIG,
ADD_RECOMMENDED_SHOW,
SET_RECOMMENDED_SHOWS,
SET_RECOMMENDED_SHOWS_OPTIONS,
SET_RECOMMENDED_SHOWS_TRAKT_REMOVED,
SET_RECOMMENDED_SHOWS_CATEGORIES,
ADD_SHOWS,
ADD_SHOW_EPISODE,
ADD_REMOTE_BRANCHES,
Expand Down
Loading

0 comments on commit bb4fb0c

Please sign in to comment.