diff --git a/CHANGELOG.md b/CHANGELOG.md
index 45dba195ce..18fd00d5b1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,10 +5,17 @@
#### Improvements
- Shows without any episodes can now be added ([#6977](https://github.com/pymedusa/Medusa/pull/6977))
+- Vueified displayShow ([#6709](https://github.com/pymedusa/Medusa/pull/6709))
+ - New subtitles search UI component
+ - Direct toggle of show options on displayShow page like the checks for Subtitles, Season Folders, Paused, etc.
+ - Mark episodes as "watched"
+ - Added pagination
+ - Added search field, that searches columns like Title, File and Episode number
#### Fixes
- Fixed AnimeBytes daily search, for multi-ep results ([#7190](https://github.com/pymedusa/Medusa/pull/7190))
- Fixed rare UnicodeDecodeError when parsing titles with Python 2.7 ([#7192](https://github.com/pymedusa/Medusa/pull/7192))
+- Fixed displayShow loading of large shows with many seasons e.g. daily shows ([#6977](https://github.com/pymedusa/Medusa/pull/6977))
- Fixed torrent checker for client Transmission running on python 3 ([#7250](https://github.com/pymedusa/Medusa/pull/7250))
- Fixed provider beyond-hd due to layout changes ([#7250](https://github.com/pymedusa/Medusa/pull/7250))
- Fixed provider bj-share due to layout changes ([#7250](https://github.com/pymedusa/Medusa/pull/7250))
diff --git a/medusa/__main__.py b/medusa/__main__.py
index d5d3466c30..b68b03f265 100755
--- a/medusa/__main__.py
+++ b/medusa/__main__.py
@@ -970,7 +970,6 @@ def initialize(self, console_logging=True):
app.TIMEZONE_DISPLAY = check_setting_str(app.CFG, 'GUI', 'timezone_display', 'local')
app.POSTER_SORTBY = check_setting_str(app.CFG, 'GUI', 'poster_sortby', 'name')
app.POSTER_SORTDIR = check_setting_int(app.CFG, 'GUI', 'poster_sortdir', 1)
- app.DISPLAY_ALL_SEASONS = bool(check_setting_int(app.CFG, 'General', 'display_all_seasons', 1))
app.RECENTLY_DELETED = set()
app.RELEASES_IN_PP = []
app.GIT_REMOTE_BRANCHES = []
@@ -1602,7 +1601,6 @@ def save_config():
new_config['General']['no_restart'] = int(app.NO_RESTART)
new_config['General']['developer'] = int(app.DEVELOPER)
new_config['General']['python_version'] = app.PYTHON_VERSION
- new_config['General']['display_all_seasons'] = int(app.DISPLAY_ALL_SEASONS)
new_config['General']['news_last_read'] = app.NEWS_LAST_READ
new_config['General']['broken_providers'] = helpers.get_broken_providers() or app.BROKEN_PROVIDERS
new_config['General']['selected_root'] = int(app.SELECTED_ROOT)
diff --git a/medusa/app.py b/medusa/app.py
index 0d69459004..9f0dfdbf7c 100644
--- a/medusa/app.py
+++ b/medusa/app.py
@@ -196,7 +196,6 @@ def __init__(self):
self.SORT_ARTICLE = False
self.DEBUG = False
self.DBDEBUG = False
- self.DISPLAY_ALL_SEASONS = True
self.DEFAULT_PAGE = 'home'
self.SEEDERS_LEECHERS_IN_NOTIFY = True
self.SHOW_LIST_ORDER = ['Anime', 'Series']
diff --git a/medusa/common.py b/medusa/common.py
index dea20cf737..096faa8b27 100644
--- a/medusa/common.py
+++ b/medusa/common.py
@@ -808,8 +808,8 @@ class Overview(object):
overviewStrings = {
SKIPPED: 'skipped',
WANTED: 'wanted',
- QUAL: 'qual',
- GOOD: 'good',
+ QUAL: 'allowed',
+ GOOD: 'preferred',
UNAIRED: 'unaired',
SNATCHED: 'snatched',
# we can give these a different class later, otherwise
diff --git a/medusa/search/manual.py b/medusa/search/manual.py
index 38f6ea19bb..500a291669 100644
--- a/medusa/search/manual.py
+++ b/medusa/search/manual.py
@@ -86,23 +86,31 @@ def get_episodes(search_thread, searchstatus):
for ep_obj in search_thread.segment:
ep = series_obj.get_episode(ep_obj.season, ep_obj.episode)
results.append({
- 'indexer_id': series_obj.indexer,
- 'series_id': series_obj.series_id,
- 'episode': ep.episode,
- 'episodeindexerid': ep.indexerid,
- 'season': ep.season,
- 'searchstatus': searchstatus,
- 'status': statusStrings[ep.status],
- # TODO: `quality_name` and `quality_style` should both be removed
- # when converting forced/manual episode search to Vue (use QualityPill component directly)
- 'quality_name': Quality.qualityStrings[ep.quality],
- 'quality_style': Quality.quality_keys.get(ep.quality) or Quality.quality_keys[Quality.UNKNOWN],
- 'overview': Overview.overviewStrings[series_obj.get_overview(
- ep.status, ep.quality,
- manually_searched=ep.manually_searched
- )],
- 'queuetime': search_thread.queue_time.isoformat(),
- 'starttime': search_thread.start_time.isoformat() if search_thread.start_time else None,
+ 'show': {
+ 'indexer': series_obj.indexer,
+ 'series_id': series_obj.series_id,
+ 'slug': series_obj.slug
+ },
+ 'episode': {
+ 'episode': ep.episode,
+ 'season': ep.season,
+ 'slug': ep.slug,
+ 'indexerid': ep.indexerid,
+ 'status': statusStrings[ep.status],
+ # TODO: `quality_name` and `quality_style` should both be removed
+ # when converting forced/manual episode search to Vue (use QualityPill component directly)
+ 'quality_name': Quality.qualityStrings[ep.quality],
+ 'quality_style': Quality.quality_keys.get(ep.quality) or Quality.quality_keys[Quality.UNKNOWN],
+ 'overview': Overview.overviewStrings[series_obj.get_overview(
+ ep.status, ep.quality,
+ manually_searched=ep.manually_searched
+ )]
+ },
+ 'search': {
+ 'status': searchstatus,
+ 'queuetime': search_thread.queue_time.isoformat(),
+ 'starttime': search_thread.start_time.isoformat() if search_thread.start_time else None
+ }
})
return results
@@ -163,11 +171,11 @@ def collect_episodes_from_search_thread(series_obj):
continue
if isinstance(search_thread, ManualSearchQueueItem):
- if not [x for x in episodes if x['episodeindexerid'] in [search.indexerid for search in search_thread.segment]]:
+ if not [x for x in episodes if x['episode']['indexerid'] in [search.indexerid for search in search_thread.segment]]:
episodes += get_episodes(search_thread, searchstatus)
else:
# These are only Failed Downloads/Retry search thread items.. lets loop through the segment/episodes
- if not [i for i, j in zip(search_thread.segment, episodes) if i.indexerid == j['episodeindexerid']]:
+ if not [i for i, j in zip(search_thread.segment, episodes) if i.indexerid == j['episode']['indexerid']]:
episodes += get_episodes(search_thread, searchstatus)
return episodes
diff --git a/medusa/search/queue.py b/medusa/search/queue.py
index 6b695b9a9a..8824125433 100644
--- a/medusa/search/queue.py
+++ b/medusa/search/queue.py
@@ -105,7 +105,7 @@ def force_daily(self):
class ForcedSearchQueue(generic_queue.GenericQueue):
- """Search Queueu used for Manual, Failed Search."""
+ """Search Queue used for Manual, (forced) Backlog and Failed Search."""
def __init__(self):
"""Initialize ForcedSearch Queue."""
@@ -346,7 +346,7 @@ def __init__(self, show, segment, manual_search_type='episode'):
self.manual_search_type = manual_search_type
def run(self):
- """Run forced search thread."""
+ """Run manual search thread."""
generic_queue.QueueItem.run(self)
self.started = True
@@ -551,6 +551,9 @@ def run(self):
self.success = False
log.debug(traceback.format_exc())
+ # Keep a list with the 100 last executed searches
+ fifo(SEARCH_HISTORY, self, SEARCH_HISTORY_SIZE)
+
if self.success is None:
self.success = False
@@ -648,7 +651,7 @@ def run(self):
self.success = False
log.info(traceback.format_exc())
- # ## Keep a list with the 100 last executed searches
+ # Keep a list with the 100 last executed searches
fifo(SEARCH_HISTORY, self, SEARCH_HISTORY_SIZE)
if self.success is None:
diff --git a/medusa/server/api/v2/config.py b/medusa/server/api/v2/config.py
index 5de436ad6e..d28175bed6 100644
--- a/medusa/server/api/v2/config.py
+++ b/medusa/server/api/v2/config.py
@@ -122,7 +122,6 @@ class ConfigHandler(BaseRequestHandler):
'layout.history': EnumField(app, 'HISTORY_LAYOUT', ('compact', 'detailed'), default_value='detailed'),
'layout.home': EnumField(app, 'HOME_LAYOUT', ('poster', 'small', 'banner', 'simple', 'coverflow'),
default_value='poster'),
- 'layout.show.allSeasons': BooleanField(app, 'DISPLAY_ALL_SEASONS'),
'layout.show.specials': BooleanField(app, 'DISPLAY_SHOW_SPECIALS'),
'layout.show.showListOrder': ListField(app, 'SHOW_LIST_ORDER'),
'theme.name': StringField(app, 'THEME_NAME', setter=theme_name_setter),
@@ -558,7 +557,7 @@ def data_main():
section_data['layout']['history'] = app.HISTORY_LAYOUT
section_data['layout']['home'] = app.HOME_LAYOUT
section_data['layout']['show'] = {}
- section_data['layout']['show']['allSeasons'] = bool(app.DISPLAY_ALL_SEASONS)
+
section_data['layout']['show']['specials'] = bool(app.DISPLAY_SHOW_SPECIALS)
section_data['layout']['show']['showListOrder'] = app.SHOW_LIST_ORDER
diff --git a/medusa/server/core.py b/medusa/server/core.py
index bdb24d1c8e..0c5e68312c 100644
--- a/medusa/server/core.py
+++ b/medusa/server/core.py
@@ -77,6 +77,7 @@ def clean_url_path(*args, **kwargs):
def get_apiv2_handlers(base):
"""Return api v2 handlers."""
return [
+
# Order: Most specific to most generic
# /api/v2/search
diff --git a/medusa/server/web/config/general.py b/medusa/server/web/config/general.py
index ff968a5ee4..021758833f 100644
--- a/medusa/server/web/config/general.py
+++ b/medusa/server/web/config/general.py
@@ -72,7 +72,7 @@ def saveGeneral(self, log_dir=None, log_nr=5, log_size=1, web_port=None, notify_
fuzzy_dating=None, trim_zero=None, date_preset=None, date_preset_na=None, time_preset=None,
indexer_timeout=None, download_url=None, rootDir=None, theme_name=None, default_page=None,
git_reset=None, git_reset_branches=None, git_auth_type=0, git_username=None, git_password=None, git_token=None,
- display_all_seasons=None, subliminal_log=None, privacy_level='normal', fanart_background=None, fanart_background_opacity=None,
+ subliminal_log=None, privacy_level='normal', fanart_background=None, fanart_background_opacity=None,
dbdebug=None, fallback_plex_enable=1, fallback_plex_notifications=1, fallback_plex_timeout=3, web_root=None, ssl_ca_bundle=None):
results = []
@@ -119,7 +119,6 @@ def saveGeneral(self, log_dir=None, log_nr=5, log_size=1, web_port=None, notify_
app.SSL_CA_BUNDLE = ssl_ca_bundle
# app.LOG_DIR is set in config.change_LOG_DIR()
app.COMING_EPS_MISSED_RANGE = int(coming_eps_missed_range)
- app.DISPLAY_ALL_SEASONS = config.checkbox_to_value(display_all_seasons)
app.NOTIFY_ON_LOGIN = config.checkbox_to_value(notify_on_login)
app.WEB_PORT = int(web_port)
app.WEB_IPV6 = config.checkbox_to_value(web_ipv6)
diff --git a/medusa/server/web/home/handler.py b/medusa/server/web/home/handler.py
index bd2a216ff7..b42c1d210d 100644
--- a/medusa/server/web/home/handler.py
+++ b/medusa/server/web/home/handler.py
@@ -62,10 +62,7 @@
)
from medusa.scene_numbering import (
get_scene_absolute_numbering,
- get_scene_absolute_numbering_for_show,
get_scene_numbering,
- get_scene_numbering_for_show,
- get_xem_absolute_numbering_for_show,
get_xem_numbering_for_show,
set_scene_numbering,
xem_refresh,
@@ -763,27 +760,7 @@ def displayShow(self, indexername=None, seriesid=None, ):
if series_obj is None:
return self._genericMessage('Error', 'Show not in show list')
- min_season = 0 if app.DISPLAY_SHOW_SPECIALS else 1
-
- main_db_con = db.DBConnection()
- sql_results = main_db_con.select(
- 'SELECT * '
- 'FROM tv_episodes '
- 'WHERE indexer = ? AND showid = ? AND season >= ? '
- 'ORDER BY season DESC, episode DESC',
- [series_obj.indexer, series_obj.series_id, min_season]
- )
-
- t = PageTemplate(rh=self, filename='displayShow.mako')
-
- ep_cats = {}
-
- for cur_result in sql_results:
- cur_ep_cat = series_obj.get_overview(cur_result['status'], cur_result['quality'], manually_searched=cur_result['manually_searched'])
- if cur_ep_cat:
- ep_cats['s{season}e{episode}'.format(season=cur_result['season'], episode=cur_result['episode'])] = cur_ep_cat
-
- series_obj.exceptions = get_scene_exceptions(series_obj)
+ t = PageTemplate(rh=self, filename='index.mako')
indexer_id = int(series_obj.indexer)
series_id = int(series_obj.series_id)
@@ -805,11 +782,6 @@ def displayShow(self, indexername=None, seriesid=None, ):
})
return t.render(
- show=series_obj, sql_results=sql_results, ep_cats=ep_cats,
- scene_numbering=get_scene_numbering_for_show(series_obj),
- xem_numbering=get_xem_numbering_for_show(series_obj, refresh_data=False),
- scene_absolute_numbering=get_scene_absolute_numbering_for_show(series_obj),
- xem_absolute_numbering=get_xem_absolute_numbering_for_show(series_obj),
controller='home', action='displayShow',
)
@@ -923,10 +895,10 @@ def manualSearchCheckCache(self, indexername, seriesid, season=None, episode=Non
# Check if the requested ep is in a search thread
searched_item = [ep for ep in episodes_in_search
- if all([ep.get('indexer_id') == series_obj.identifier.indexer.id,
- ep.get('series_id') == series_obj.identifier.id,
- text_type(ep.get('season')) == season,
- text_type(ep.get('episode')) == episode])]
+ if all([ep['show']['indexer'] == series_obj.identifier.indexer.id,
+ ep['show']['series_id'] == series_obj.identifier.id,
+ text_type(ep['episode']['season']) == season,
+ text_type(ep['episode']['episode']) == episode])]
# # No last_prov_updates available, let's assume we need to refresh until we get some
# if not last_prov_updates:
@@ -959,7 +931,7 @@ def manualSearchCheckCache(self, indexername, seriesid, season=None, episode=Non
# but then check if as soon as a search has finished
# Move on and show results
# Return a list of queues the episode has been found in
- search_status = [item.get('searchstatus') for item in searched_item]
+ search_status = [item['search']['status'] for item in searched_item]
if not searched_item or all([last_prov_updates,
SEARCH_STATUS_QUEUED not in search_status,
SEARCH_STATUS_SEARCHING not in search_status,
@@ -974,7 +946,7 @@ def manualSearchCheckCache(self, indexername, seriesid, season=None, episode=Non
if not last_prov_updates and SEARCH_STATUS_FINISHED in search_status:
return {'result': refresh_results}
- return {'result': searched_item[0]['searchstatus']}
+ return {'result': searched_item[0]['search']['status']}
def snatchSelection(self, indexername, seriesid, season=None, episode=None, manual_search_type='episode',
perform_search=0, down_cur_quality=0, show_all_results=0):
@@ -1748,10 +1720,15 @@ def searchEpisode(self, indexername=None, seriesid=None, season=None, episode=No
'result': 'failure',
})
- # ## Returns the current ep_queue_item status for the current viewed show.
- # Possible status: Downloaded, Snatched, etc...
- # Returns {'show': 279530, 'episodes' : ['episode' : 6, 'season' : 1, 'searchstatus' : 'queued', 'status' : 'running', 'quality': '4013']
def getManualSearchStatus(self, indexername=None, seriesid=None):
+ """
+ Returns the current ep_queue_item status for the current viewed show.
+ Possible status: Downloaded, Snatched, etc...
+ Returns {'show': 279530, 'episodes' : ['episode' : 6, 'season' : 1, 'searchstatus' : 'queued', 'status' : 'running', 'quality': '4013']
+ :param indexername: Name of indexer. For ex. 'tvdb', 'tmdb', 'tvmaze'
+ :param seriesid: Id of series as identified by the indexer
+ :return:
+ """
indexer_id = indexer_name_to_id(indexername)
series_obj = Show.find_by_id(app.showList, indexer_id, seriesid)
episodes = collect_episodes_from_search_thread(series_obj)
@@ -1775,29 +1752,32 @@ def searchEpisodeSubtitles(self, indexername=None, seriesid=None, season=None, e
logger.log('Manual re-downloading subtitles for {show} with language {lang}'.format
(show=ep_obj.series.name, lang=lang))
new_subtitles = ep_obj.download_subtitles(lang=lang)
- except Exception:
+ except Exception as error:
return json.dumps({
'result': 'failure',
+ 'description': 'Error while downloading subtitles: {error}'.format(error=error)
})
if new_subtitles:
new_languages = [subtitles.name_from_code(code) for code in new_subtitles]
- status = 'New subtitles downloaded: {languages}'.format(languages=', '.join(new_languages))
+ description = 'New subtitles downloaded: {languages}'.format(languages=', '.join(new_languages))
result = 'success'
else:
new_languages = []
- status = 'No subtitles downloaded'
+ description = 'No subtitles downloaded'
result = 'failure'
- ui.notifications.message(ep_obj.series.name, status)
+ ui.notifications.message(ep_obj.series.name, description)
return json.dumps({
'result': result,
- 'subtitles': ','.join(ep_obj.subtitles),
- 'new_subtitles': ','.join(new_languages),
+ 'subtitles': ep_obj.subtitles,
+ 'languages': new_languages,
+ 'description': description
})
- def manual_search_subtitles(self, indexername=None, seriesid=None, season=None, episode=None, release_id=None, picked_id=None):
+ def manualSearchSubtitles(self, indexername=None, seriesid=None, season=None, episode=None, release_id=None, picked_id=None):
mode = 'downloading' if picked_id else 'searching'
+ description = ''
logger.log('Starting to manual {mode} subtitles'.format(mode=mode))
try:
if release_id:
@@ -1818,17 +1798,26 @@ def manual_search_subtitles(self, indexername=None, seriesid=None, season=None,
except IndexError:
ui.notifications.message('Outdated list', 'Please refresh page and try again')
logger.log('Outdated list. Please refresh page and try again', logger.WARNING)
- return json.dumps({'result': 'failure'})
+ return json.dumps({
+ 'result': 'failure',
+ 'description': 'Outdated list. Please refresh page and try again'
+ })
except (ValueError, TypeError) as e:
ui.notifications.message('Error', 'Please check logs')
logger.log('Error while manual {mode} subtitles. Error: {error_msg}'.format
(mode=mode, error_msg=e), logger.ERROR)
- return json.dumps({'result': 'failure'})
+ return json.dumps({
+ 'result': 'failure',
+ 'description': 'Error while manual {mode} subtitles. Error: {error_msg}'.format(mode=mode, error_msg=e)
+ })
if not os.path.isfile(video_path):
ui.notifications.message(ep_obj.series.name, "Video file no longer exists. Can't search for subtitles")
logger.log('Video file no longer exists: {video_file}'.format(video_file=video_path), logger.DEBUG)
- return json.dumps({'result': 'failure'})
+ return json.dumps({
+ 'result': 'failure',
+ 'description': 'Video file no longer exists: {video_file}'.format(video_file=video_path)
+ })
if mode == 'searching':
logger.log('Manual searching subtitles for: {0}'.format(release_name))
@@ -1837,7 +1826,11 @@ def manual_search_subtitles(self, indexername=None, seriesid=None, season=None,
ui.notifications.message(ep_obj.series.name, 'Found {} subtitles'.format(len(found_subtitles)))
else:
ui.notifications.message(ep_obj.series.name, 'No subtitle found')
- result = 'success' if found_subtitles else 'failure'
+ if found_subtitles:
+ result = 'success'
+ else:
+ result = 'failure'
+ description = 'No subtitles found'
subtitles_result = found_subtitles
else:
logger.log('Manual downloading subtitles for: {0}'.format(release_name))
@@ -1848,13 +1841,19 @@ def manual_search_subtitles(self, indexername=None, seriesid=None, season=None,
'Subtitle downloaded: {0}'.format(','.join(new_manual_subtitle)))
else:
ui.notifications.message(ep_obj.series.name, 'Failed to download subtitle for {0}'.format(release_name))
- result = 'success' if new_manual_subtitle else 'failure'
+ if new_manual_subtitle:
+ result = 'success'
+ else:
+ result = 'failure'
+ description = 'Failed to download subtitle for {0}'.format(release_name)
+
subtitles_result = new_manual_subtitle
return json.dumps({
'result': result,
'release': release_name,
- 'subtitles': subtitles_result
+ 'subtitles': subtitles_result,
+ 'description': description
})
def setSceneNumbering(self, indexername=None, seriesid=None, forSeason=None, forEpisode=None, forAbsolute=None, sceneSeason=None,
@@ -1871,6 +1870,12 @@ def setSceneNumbering(self, indexername=None, seriesid=None, forSeason=None, for
indexer_id = indexer_name_to_id(indexername)
series_obj = Show.find_by_id(app.showList, indexer_id, seriesid)
+ if not series_obj:
+ return json.dumps({
+ 'success': False,
+ 'errorMessage': 'Could not find show {0} {1} to set scene numbering'.format(indexername, seriesid),
+ })
+
# Check if this is an anime, because we can't set the Scene numbering for anime shows
if series_obj.is_anime and forAbsolute is None:
return json.dumps({
diff --git a/medusa/tv/episode.py b/medusa/tv/episode.py
index 1eb6754ac1..77e2150dc9 100644
--- a/medusa/tv/episode.py
+++ b/medusa/tv/episode.py
@@ -243,6 +243,7 @@ def __init__(self, series, season, episode, filepath=''):
self.name = ''
self.season = season
self.episode = episode
+ self.slug = 's{season:02d}e{episode:02d}'.format(season=self.season, episode=self.episode)
self.absolute_number = 0
self.description = ''
self.subtitles = []
@@ -1074,7 +1075,7 @@ def to_json(self, detailed=True):
data = {}
data['identifier'] = self.identifier
data['id'] = {self.indexer_name: self.indexerid}
- data['slug'] = 's{season:02d}e{episode:02d}'.format(season=self.season, episode=self.episode)
+ data['slug'] = self.slug
data['season'] = self.season
data['episode'] = self.episode
@@ -1103,6 +1104,7 @@ def to_json(self, detailed=True):
data['file'] = {}
data['file']['location'] = self.location
+ data['file']['name'] = os.path.basename(self.location)
if self.file_size:
data['file']['size'] = self.file_size
diff --git a/tests/apiv2/test_config.py b/tests/apiv2/test_config.py
index 1a23b6e0c3..c6caf0df69 100644
--- a/tests/apiv2/test_config.py
+++ b/tests/apiv2/test_config.py
@@ -114,7 +114,6 @@ def config_main(monkeypatch, app_config):
config_data['layout']['history'] = app.HISTORY_LAYOUT
config_data['layout']['home'] = app.HOME_LAYOUT
config_data['layout']['show'] = {}
- config_data['layout']['show']['allSeasons'] = bool(app.DISPLAY_ALL_SEASONS)
config_data['layout']['show']['specials'] = bool(app.DISPLAY_SHOW_SPECIALS)
config_data['layout']['show']['showListOrder'] = app.SHOW_LIST_ORDER
diff --git a/themes-default/slim/package.json b/themes-default/slim/package.json
index 4c6dc3e577..33d49ff54b 100644
--- a/themes-default/slim/package.json
+++ b/themes-default/slim/package.json
@@ -35,13 +35,15 @@
"country-language": "0.1.7",
"date-fns": "2.0.1",
"is-visible": "2.2.0",
+ "javascript-time-ago": "2.0.2",
"jquery": "3.4.1",
"lodash": "4.17.15",
"tablesorter": "2.31.1",
+ "v-tooltip": "2.0.2",
"vue": "2.6.10",
"vue-async-computed": "3.7.0",
- "vue-cookie": "1.1.4",
- "vue-good-table": "https://github.com/p0psicles/vue-good-table/archive/master.tar.gz",
+ "vue-cookies": "1.5.13",
+ "vue-good-table": "git+https://github.com/p0psicles/vue-good-table#25a6f282231426fbbdb44d8a6d1927e8abf21e4d",
"vue-js-modal": "1.3.31",
"vue-js-toggle-button": "1.3.2",
"vue-meta": "2.0.5",
diff --git a/themes-default/slim/src/api.js b/themes-default/slim/src/api.js
index 37e899884e..355bd25a39 100644
--- a/themes-default/slim/src/api.js
+++ b/themes-default/slim/src/api.js
@@ -8,7 +8,7 @@ export const apiKey = document.body.getAttribute('api-key');
*/
export const apiRoute = axios.create({
baseURL: webRoot + '/',
- timeout: 30000,
+ timeout: 60000,
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
diff --git a/themes-default/slim/src/components/backstretch.vue b/themes-default/slim/src/components/backstretch.vue
index a438a46eb4..399c15f75c 100644
--- a/themes-default/slim/src/components/backstretch.vue
+++ b/themes-default/slim/src/components/backstretch.vue
@@ -39,7 +39,6 @@ export default {
if (!this.enabled) {
return;
}
-
const { opacity, slug, offset } = this;
if (slug) {
const imgUrl = `${webRoot}/api/v2/series/${slug}/asset/fanart?api_key=${apiKey}`;
diff --git a/themes-default/slim/src/components/display-show.vue b/themes-default/slim/src/components/display-show.vue
new file mode 100644
index 0000000000..5b672896d6
--- /dev/null
+++ b/themes-default/slim/src/components/display-show.vue
@@ -0,0 +1,1399 @@
+
+
+
+
+
+
+
+ Season contains {{headerRow.episodes.length}} episodes with total filesize: {{addFileSize(headerRow)}}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{props.row.episode}}
+
+
+
+
+
+
+
+
+
+
+
+
Do you want to manually pick subtitles or let us choose it for you?
+Do you want to manually pick subtitles or let us choose it for you?
+Do you want to manually pick subtitles or search a subtitle with the language code {{lang}} for you?