From 4066a0f10ac28f955726829f3a11e619014ef49a Mon Sep 17 00:00:00 2001 From: sharkykh Date: Tue, 24 Jul 2018 20:35:09 +0300 Subject: [PATCH 1/4] Remove unused Python imports --- themes-default/slim/views/displayShow.mako | 5 +---- themes-default/slim/views/partials/showheader.mako | 7 ++----- themes/dark/templates/displayShow.mako | 5 +---- themes/dark/templates/partials/showheader.mako | 7 ++----- themes/light/templates/displayShow.mako | 5 +---- themes/light/templates/partials/showheader.mako | 7 ++----- 6 files changed, 9 insertions(+), 27 deletions(-) diff --git a/themes-default/slim/views/displayShow.mako b/themes-default/slim/views/displayShow.mako index a7fe9ef991..65eb52ef41 100644 --- a/themes-default/slim/views/displayShow.mako +++ b/themes-default/slim/views/displayShow.mako @@ -2,13 +2,10 @@ <%! import datetime import urllib - import ntpath from medusa import app, helpers, subtitles, sbdatetime, network_timezones from medusa.common import SKIPPED, WANTED, UNAIRED, ARCHIVED, IGNORED, FAILED, DOWNLOADED, SNATCHED, SNATCHED_PROPER, SNATCHED_BEST - from medusa.common import Quality, qualityPresets, statusStrings, Overview + from medusa.common import Quality, statusStrings, Overview from medusa.helper.common import pretty_file_size - from medusa.indexers.indexer_api import indexerApi - from medusa.indexers.utils import mappings %> <%block name="scripts"> diff --git a/themes-default/slim/views/partials/showheader.mako b/themes-default/slim/views/partials/showheader.mako index 46ea90c9a1..407cd7df7d 100644 --- a/themes-default/slim/views/partials/showheader.mako +++ b/themes-default/slim/views/partials/showheader.mako @@ -1,10 +1,7 @@ <%! - import datetime - import urllib - import ntpath import operator - from medusa import app, helpers, subtitles, sbdatetime, network_timezones - from medusa.common import SKIPPED, WANTED, UNAIRED, ARCHIVED, IGNORED, FAILED, DOWNLOADED + from medusa import app, helpers, subtitles, network_timezones + from medusa.common import SKIPPED, WANTED, ARCHIVED, IGNORED, FAILED, DOWNLOADED from medusa.common import Quality, qualityPresets, statusStrings, Overview from medusa.helper.common import pretty_file_size from medusa.indexers.indexer_api import indexerApi diff --git a/themes/dark/templates/displayShow.mako b/themes/dark/templates/displayShow.mako index a7fe9ef991..65eb52ef41 100644 --- a/themes/dark/templates/displayShow.mako +++ b/themes/dark/templates/displayShow.mako @@ -2,13 +2,10 @@ <%! import datetime import urllib - import ntpath from medusa import app, helpers, subtitles, sbdatetime, network_timezones from medusa.common import SKIPPED, WANTED, UNAIRED, ARCHIVED, IGNORED, FAILED, DOWNLOADED, SNATCHED, SNATCHED_PROPER, SNATCHED_BEST - from medusa.common import Quality, qualityPresets, statusStrings, Overview + from medusa.common import Quality, statusStrings, Overview from medusa.helper.common import pretty_file_size - from medusa.indexers.indexer_api import indexerApi - from medusa.indexers.utils import mappings %> <%block name="scripts"> diff --git a/themes/dark/templates/partials/showheader.mako b/themes/dark/templates/partials/showheader.mako index 46ea90c9a1..407cd7df7d 100644 --- a/themes/dark/templates/partials/showheader.mako +++ b/themes/dark/templates/partials/showheader.mako @@ -1,10 +1,7 @@ <%! - import datetime - import urllib - import ntpath import operator - from medusa import app, helpers, subtitles, sbdatetime, network_timezones - from medusa.common import SKIPPED, WANTED, UNAIRED, ARCHIVED, IGNORED, FAILED, DOWNLOADED + from medusa import app, helpers, subtitles, network_timezones + from medusa.common import SKIPPED, WANTED, ARCHIVED, IGNORED, FAILED, DOWNLOADED from medusa.common import Quality, qualityPresets, statusStrings, Overview from medusa.helper.common import pretty_file_size from medusa.indexers.indexer_api import indexerApi diff --git a/themes/light/templates/displayShow.mako b/themes/light/templates/displayShow.mako index a7fe9ef991..65eb52ef41 100644 --- a/themes/light/templates/displayShow.mako +++ b/themes/light/templates/displayShow.mako @@ -2,13 +2,10 @@ <%! import datetime import urllib - import ntpath from medusa import app, helpers, subtitles, sbdatetime, network_timezones from medusa.common import SKIPPED, WANTED, UNAIRED, ARCHIVED, IGNORED, FAILED, DOWNLOADED, SNATCHED, SNATCHED_PROPER, SNATCHED_BEST - from medusa.common import Quality, qualityPresets, statusStrings, Overview + from medusa.common import Quality, statusStrings, Overview from medusa.helper.common import pretty_file_size - from medusa.indexers.indexer_api import indexerApi - from medusa.indexers.utils import mappings %> <%block name="scripts"> diff --git a/themes/light/templates/partials/showheader.mako b/themes/light/templates/partials/showheader.mako index 46ea90c9a1..407cd7df7d 100644 --- a/themes/light/templates/partials/showheader.mako +++ b/themes/light/templates/partials/showheader.mako @@ -1,10 +1,7 @@ <%! - import datetime - import urllib - import ntpath import operator - from medusa import app, helpers, subtitles, sbdatetime, network_timezones - from medusa.common import SKIPPED, WANTED, UNAIRED, ARCHIVED, IGNORED, FAILED, DOWNLOADED + from medusa import app, helpers, subtitles, network_timezones + from medusa.common import SKIPPED, WANTED, ARCHIVED, IGNORED, FAILED, DOWNLOADED from medusa.common import Quality, qualityPresets, statusStrings, Overview from medusa.helper.common import pretty_file_size from medusa.indexers.indexer_api import indexerApi From 77ab9c9c8020c542540a793dc40d2ea45f42c531 Mon Sep 17 00:00:00 2001 From: sharkykh Date: Wed, 25 Jul 2018 09:33:28 +0300 Subject: [PATCH 2/4] displayShow: Moved JS to mako Fixes forced search and subtitle search --- .../slim/static/js/home/display-show.js | 441 ------------------ themes-default/slim/views/displayShow.mako | 441 +++++++++++++++++- themes-default/slim/views/layouts/main.mako | 1 - themes/dark/assets/js/home/display-show.js | 441 ------------------ .../dark/assets/js/home/display-show.js.map | 1 - themes/dark/templates/displayShow.mako | 441 +++++++++++++++++- themes/dark/templates/layouts/main.mako | 1 - themes/light/assets/js/home/display-show.js | 441 ------------------ .../light/assets/js/home/display-show.js.map | 1 - themes/light/templates/displayShow.mako | 441 +++++++++++++++++- themes/light/templates/layouts/main.mako | 1 - 11 files changed, 1320 insertions(+), 1331 deletions(-) delete mode 100644 themes-default/slim/static/js/home/display-show.js delete mode 100644 themes/dark/assets/js/home/display-show.js delete mode 100644 themes/dark/assets/js/home/display-show.js.map delete mode 100644 themes/light/assets/js/home/display-show.js delete mode 100644 themes/light/assets/js/home/display-show.js.map diff --git a/themes-default/slim/static/js/home/display-show.js b/themes-default/slim/static/js/home/display-show.js deleted file mode 100644 index bef3a32e57..0000000000 --- a/themes-default/slim/static/js/home/display-show.js +++ /dev/null @@ -1,441 +0,0 @@ -MEDUSA.home.displayShow = function() { // eslint-disable-line max-lines - $('.imdbPlot').on('click', function() { - $(this).prev('span').toggle(); - if ($(this).html() === '..show less') { - $(this).html('..show more'); - } else { - $(this).html('..show less'); - } - moveSummaryBackground(); - movecheckboxControlsBackground(); - }); - - // Adjust the summary background position and size on page load and resize - function moveSummaryBackground() { - const height = $('#summary').height() + 10; - const top = $('#summary').offset().top + 5; - $('#summaryBackground').height(height); - $('#summaryBackground').offset({ top, left: 0 }); - $('#summaryBackground').show(); - } - - function movecheckboxControlsBackground() { - const height = $('#checkboxControls').height() + 10; - const top = $('#checkboxControls').offset().top - 3; - $('#checkboxControlsBackground').height(height); - $('#checkboxControlsBackground').offset({ top, left: 0 }); - $('#checkboxControlsBackground').show(); - } - - $(window).resize(() => { - moveSummaryBackground(); - movecheckboxControlsBackground(); - }); - - $(() => { - moveSummaryBackground(); - movecheckboxControlsBackground(); - }); - - $.ajaxEpSearch({ - colorRow: true - }); - - startAjaxEpisodeSubtitles(); // eslint-disable-line no-undef - $.ajaxEpSubtitlesSearch(); - $.ajaxEpRedownloadSubtitle(); - - const setQuality = (quality, seriesSlug, episodes) => { - const patchData = {}; - episodes.forEach(episode => { - patchData[episode] = { quality: parseInt(quality, 10) }; - }); - - api.patch('series/' + seriesSlug + '/episodes', patchData).then(response => { - log.info(response.data); - window.location.reload(); - }).catch(error => { - log.error(error.data); - }); - }; - - $('#seasonJump').on('change', function() { - const id = $('#seasonJump option:selected').val(); - if (id && id !== 'jump') { - const season = $('#seasonJump option:selected').data('season'); - $('html,body').animate({ scrollTop: $('[name="' + id.substring(1) + '"]').offset().top - 100 }, 'slow'); - $('#collapseSeason-' + season).collapse('show'); - location.hash = id; - } - $(this).val('jump'); - }); - - $('#changeStatus').on('click', () => { - const epArr = []; - const status = $('#statusSelect').val(); - const quality = $('#qualitySelect').val(); - const seriesSlug = $('#series-slug').val(); - - $('.epCheck').each(function() { - if (this.checked === true) { - epArr.push($(this).attr('id')); - } - }); - - if (epArr.length === 0) { - return false; - } - - if (quality) { - setQuality(quality, seriesSlug, epArr); - } - - if (status) { - window.location.href = $('base').attr('href') + 'home/setStatus?' + - 'indexername=' + $('#indexer-name').attr('value') + - '&seriesid=' + $('#series-id').attr('value') + - '&eps=' + epArr.join('|') + - '&status=' + status; - } - }); - - $('.seasonCheck').on('click', function() { - const seasCheck = this; - const seasNo = $(seasCheck).attr('id'); - - $('#collapseSeason-' + seasNo).collapse('show'); - const seasonIdentifier = 's' + seasNo; - $('.epCheck:visible').each(function() { - const epParts = $(this).attr('id').split('e'); - if (epParts[0] === seasonIdentifier) { - this.checked = seasCheck.checked; - } - }); - }); - - let lastCheck = null; - $('.epCheck').on('click', function(event) { - if (!lastCheck || !event.shiftKey) { - lastCheck = this; - return; - } - - const check = this; - let found = 0; - - $('.epCheck').each(function() { - if (found === 1) { - this.checked = lastCheck.checked; - } - - if (found === 2) { - return false; - } - - if (this === check || this === lastCheck) { - found++; - } - }); - }); - - // Selects all visible episode checkboxes. - $('.seriesCheck').on('click', () => { - $('.epCheck:visible').each(function() { - this.checked = true; - }); - $('.seasonCheck:visible').each(function() { - this.checked = true; - }); - }); - - // Clears all visible episode checkboxes and the season selectors - $('.clearAll').on('click', () => { - $('.epCheck:visible').each(function() { - this.checked = false; - }); - $('.seasonCheck:visible').each(function() { - this.checked = false; - }); - }); - - // Show/hide different types of rows when the checkboxes are changed - $('#checkboxControls input').on('change', function() { - const whichClass = $(this).attr('id'); - $(this).showHideRows(whichClass); - }); - - // Initially show/hide all the rows according to the checkboxes - $('#checkboxControls input').each(function() { - const status = $(this).prop('checked'); - $('tr.' + $(this).attr('id')).each(function() { - if (status) { - $(this).show(); - } else { - $(this).hide(); - } - }); - }); - - $.fn.showHideRows = function(whichClass) { - const status = $('#checkboxControls > input, #' + whichClass).prop('checked'); - $('tr.' + whichClass).each(function() { - if (status) { - $(this).show(); - } else { - $(this).hide(); - } - }); - - // Hide season headers with no episodes under them - $('tr.seasonheader').each(function() { - let numRows = 0; - const seasonNo = $(this).attr('id'); - $('tr.' + seasonNo + ' :visible').each(() => { - numRows++; - }); - if (numRows === 0) { - $(this).hide(); - $('#' + seasonNo + '-cols').hide(); - } else { - $(this).show(); - $('#' + seasonNo + '-cols').show(); - } - }); - }; - - function setEpisodeSceneNumbering(forSeason, forEpisode, sceneSeason, sceneEpisode) { - const indexerName = $('#indexer-name').val(); - const seriesId = $('#series-id').val(); - - if (sceneSeason === '') { - sceneSeason = null; - } - if (sceneEpisode === '') { - sceneEpisode = null; - } - - $.getJSON('home/setSceneNumbering', { - indexername: indexerName, - seriesid: seriesId, - forSeason, - forEpisode, - sceneSeason, - sceneEpisode - }, data => { - // Set the values we get back - if (data.sceneSeason === null || data.sceneEpisode === null) { - $('#sceneSeasonXEpisode_' + seriesId + '_' + forSeason + '_' + forEpisode).val(''); - } else { - $('#sceneSeasonXEpisode_' + seriesId + '_' + forSeason + '_' + forEpisode).val(data.sceneSeason + 'x' + data.sceneEpisode); - } - if (!data.success) { - if (data.errorMessage) { - alert(data.errorMessage); // eslint-disable-line no-alert - } else { - alert('Update failed.'); // eslint-disable-line no-alert - } - } - }); - } - - function setAbsoluteSceneNumbering(forAbsolute, sceneAbsolute) { - const indexerName = $('#indexer-name').val(); - const seriesId = $('#series-id').val(); - - if (sceneAbsolute === '') { - sceneAbsolute = null; - } - - $.getJSON('home/setSceneNumbering', { - indexername: indexerName, - seriesid: seriesId, - forAbsolute, - sceneAbsolute - }, data => { - // Set the values we get back - if (data.sceneAbsolute === null) { - $('#sceneAbsolute_' + seriesId + '_' + forAbsolute).val(''); - } else { - $('#sceneAbsolute_' + seriesId + '_' + forAbsolute).val(data.sceneAbsolute); - } - - if (!data.success) { - if (data.errorMessage) { - alert(data.errorMessage); // eslint-disable-line no-alert - } else { - alert('Update failed.'); // eslint-disable-line no-alert - } - } - }); - } - - function setInputValidInvalid(valid, el) { - if (valid) { - $(el).css({ - 'background-color': '#90EE90', // Green - 'color': '#FFF', // eslint-disable-line quote-props - 'font-weight': 'bold' - }); - return true; - } - $(el).css({ - 'background-color': '#FF0000', // Red - 'color': '#FFF!important', // eslint-disable-line quote-props - 'font-weight': 'bold' - }); - return false; - } - - $('.sceneSeasonXEpisode').on('change', function() { - // Strip non-numeric characters - const value = $(this).val(); - $(this).val(value.replace(/[^0-9xX]*/g, '')); - const forSeason = $(this).attr('data-for-season'); - const forEpisode = $(this).attr('data-for-episode'); - - // If empty reset the field - if (value === '') { - setEpisodeSceneNumbering(forSeason, forEpisode, null, null); - return; - } - - const m = $(this).val().match(/^(\d+)x(\d+)$/i); - const onlyEpisode = $(this).val().match(/^(\d+)$/i); - let sceneSeason = null; - let sceneEpisode = null; - let isValid = false; - if (m) { - sceneSeason = m[1]; - sceneEpisode = m[2]; - isValid = setInputValidInvalid(true, $(this)); - } else if (onlyEpisode) { - // For example when '5' is filled in instead of '1x5', asume it's the first season - sceneSeason = forSeason; - sceneEpisode = onlyEpisode[1]; - isValid = setInputValidInvalid(true, $(this)); - } else { - isValid = setInputValidInvalid(false, $(this)); - } - - if (isValid) { - setEpisodeSceneNumbering(forSeason, forEpisode, sceneSeason, sceneEpisode); - } - }); - - $('.sceneAbsolute').on('change', function() { - // Strip non-numeric characters - $(this).val($(this).val().replace(/[^0-9xX]*/g, '')); - const forAbsolute = $(this).attr('data-for-absolute'); - - const m = $(this).val().match(/^(\d{1,3})$/i); - let sceneAbsolute = null; - if (m) { - sceneAbsolute = m[1]; - } - setAbsoluteSceneNumbering(forAbsolute, sceneAbsolute); - }); - - $.fn.generateStars = function() { - return this.each((i, e) => { - $(e).html($('').width($(e).text() * 12)); - }); - }; - - $('.imdbstars').generateStars(); - - $('#showTable, #animeTable').tablesorter({ - widgets: ['saveSort', 'stickyHeaders', 'columnSelector'], - widgetOptions: { - columnSelector_saveColumns: true, // eslint-disable-line camelcase - columnSelector_layout: '', // eslint-disable-line camelcase - columnSelector_mediaquery: false, // eslint-disable-line camelcase - columnSelector_cssChecked: 'checked' // eslint-disable-line camelcase - } - }); - - $('#popover').popover({ - placement: 'bottom', - html: true, // Required if content has HTML - content: '
' - }).on('shown.bs.popover', () => { // Bootstrap popover event triggered when the popover opens - $.tablesorter.columnSelector.attachTo($('#showTable, #animeTable'), '#popover-target'); - }); - - // Moved and rewritten this from displayShow. This changes the button when clicked for collapsing/expanding the - // Season to Show Episodes or Hide Episodes. - $(() => { - $('.collapse.toggle').on('hide.bs.collapse', function() { - const reg = /collapseSeason-(\d+)/g; - const result = reg.exec(this.id); - $('#showseason-' + result[1]).text('Show Episodes'); - $('#season-' + result[1] + '-cols').addClass('shadow'); - }); - $('.collapse.toggle').on('show.bs.collapse', function() { - const reg = /collapseSeason-(\d+)/g; - const result = reg.exec(this.id); - $('#showseason-' + result[1]).text('Hide Episodes'); - $('#season-' + result[1] + '-cols').removeClass('shadow'); - }); - }); - - // Set the season exception based on using the get_xem_numbering_for_show() for animes if available in data.xemNumbering, - // or else try to map using just the data.season_exceptions. - function setSeasonSceneException(data) { - $.each(data.seasonExceptions, (season, nameExceptions) => { - let foundInXem = false; - // Check if it is a season name exception, we don't handle the show name exceptions here - if (season >= 0) { - // Loop through the xem mapping, and check if there is a xem_season, that needs to show the season name exception - $.each(data.xemNumbering, (indexerSeason, xemSeason) => { - if (xemSeason === parseInt(season, 10)) { - foundInXem = true; - $('', { - id: 'xem-exception-season-' + xemSeason, - alt: '[xem]', - height: '16', - width: '16', - src: 'images/xem.png', - title: nameExceptions.join(', ') - }).appendTo('[data-season=' + indexerSeason + ']'); - } - }); - - // This is not a xem season exception, let's set the exceptions as a medusa exception - if (!foundInXem) { - $('', { - id: 'xem-exception-season-' + season, - alt: '[medusa]', - height: '16', - width: '16', - src: 'images/ico/favicon-16.png', - title: nameExceptions.join(', ') - }).appendTo('[data-season=' + season + ']'); - } - } - }); - } - - // @TODO: OMG: This is just a basic json, in future it should be based on the CRUD route. - // Get the season exceptions and the xem season mappings. - $.getJSON('home/getSeasonSceneExceptions', { - indexername: $('#indexer-name').val(), - seriesid: $('#series-id').val() // eslint-disable-line camelcase - }, data => { - setSeasonSceneException(data); - }); - - $('.display-specials a').on('click', function() { - api.patch('config/main', { - layout: { - show: { - specials: $(this).text() !== 'Hide' - } - } - }).then(response => { - log.info(response.data); - window.location.reload(); - }).catch(error => { - log.error(error.data); - }); - }); -}; diff --git a/themes-default/slim/views/displayShow.mako b/themes-default/slim/views/displayShow.mako index 65eb52ef41..964bb6282b 100644 --- a/themes-default/slim/views/displayShow.mako +++ b/themes-default/slim/views/displayShow.mako @@ -27,12 +27,451 @@ const startVue = () => { $store.dispatch('getShows'); // Used by show-selector component }, mounted() { - // Adjust the summary background position and size on page load and resize + const { + moveSummaryBackground, + movecheckboxControlsBackground, + setQuality, + setEpisodeSceneNumbering, + setAbsoluteSceneNumbering, + setInputValidInvalid, + setSeasonSceneException, + showHideRows, + } = this; + + $(window).resize(() => { + moveSummaryBackground(); + movecheckboxControlsBackground(); + }); + this.$once('loaded', () => { this.$nextTick(() => { + // Adjust the summary background position and size window.dispatchEvent(new Event('resize')); + + $.ajaxEpSearch({ + colorRow: true + }); + + startAjaxEpisodeSubtitles(); // eslint-disable-line no-undef + $.ajaxEpSubtitlesSearch(); + $.ajaxEpRedownloadSubtitle(); + }); + }); + + $(document.body).on('click', '.imdbPlot', event => { + const $target = $(event.currentTarget); + $target.prev('span').toggle(); + if ($target.html() === '..show less') { + $target.html('..show more'); + } else { + $target.html('..show less'); + } + moveSummaryBackground(); + movecheckboxControlsBackground(); + }); + + $(document.body).on('change', '#seasonJump', (event) => { + const id = $('#seasonJump option:selected').val(); + if (id && id !== 'jump') { + const season = $('#seasonJump option:selected').data('season'); + $('html,body').animate({ scrollTop: $('[name="' + id.substring(1) + '"]').offset().top - 100 }, 'slow'); + $('#collapseSeason-' + season).collapse('show'); + location.hash = id; + } + $(event.currentTarget).val('jump'); + }); + + $(document.body).on('click', '#changeStatus', () => { + const epArr = []; + const status = $('#statusSelect').val(); + const quality = $('#qualitySelect').val(); + const seriesSlug = $('#series-slug').val(); + + $('.epCheck').each((index, element) => { + if (element.checked === true) { + epArr.push($(element).attr('id')); + } + }); + + if (epArr.length === 0) { + return false; + } + + if (quality) { + setQuality(quality, seriesSlug, epArr); + } + + if (status) { + window.location.href = $('base').attr('href') + 'home/setStatus?' + + 'indexername=' + $('#indexer-name').attr('value') + + '&seriesid=' + $('#series-id').attr('value') + + '&eps=' + epArr.join('|') + + '&status=' + status; + } + }); + + $(document.body).on('click', '.seasonCheck', event => { + const seasCheck = event.currentTarget; + const seasNo = $(seasCheck).attr('id'); + + $('#collapseSeason-' + seasNo).collapse('show'); + const seasonIdentifier = 's' + seasNo; + $('.epCheck:visible').each((index, element) => { + const epParts = $(element).attr('id').split('e'); + if (epParts[0] === seasonIdentifier) { + element.checked = seasCheck.checked; + } + }); + }); + + let lastCheck = null; + $(document.body).on('click', '.epCheck', event => { + const target = event.currentTarget; + if (!lastCheck || !event.shiftKey) { + lastCheck = target; + return; + } + + const check = target; + let found = 0; + + $('.epCheck').each((index, element) => { + if (found === 1) { + element.checked = lastCheck.checked; + } + + if (found === 2) { + return false; + } + + if (element === check || element === lastCheck) { + found++; + } + }); + }); + + // Selects all visible episode checkboxes. + $(document.body).on('click', '.seriesCheck', () => { + $('.epCheck:visible').each((index, element) => { + element.checked = true; + }); + $('.seasonCheck:visible').each((index, element) => { + element.checked = true; + }); + }); + + // Clears all visible episode checkboxes and the season selectors + $(document.body).on('click', '.clearAll', () => { + $('.epCheck:visible').each((index, element) => { + element.checked = false; + }); + $('.seasonCheck:visible').each((index, element) => { + element.checked = false; + }); + }); + + // Show/hide different types of rows when the checkboxes are changed + $(document.body).on('change', '#checkboxControls input', event => { + const whichClass = $(event.currentTarget).attr('id'); + showHideRows(whichClass); + }); + + // Initially show/hide all the rows according to the checkboxes + $('#checkboxControls input').each((index, element) => { + const status = $(element).prop('checked'); + $('tr.' + $(element).attr('id')).each((index, tableRow) => { + if (status) { + $(tableRow).show(); + } else { + $(tableRow).hide(); + } }); }); + + $(document.body).on('change', '.sceneSeasonXEpisode', event => { + const target = event.currentTarget; + // Strip non-numeric characters + const value = $(target).val(); + $(target).val(value.replace(/[^0-9xX]*/g, '')); + const forSeason = $(target).attr('data-for-season'); + const forEpisode = $(target).attr('data-for-episode'); + + // If empty reset the field + if (value === '') { + setEpisodeSceneNumbering(forSeason, forEpisode, null, null); + return; + } + + const m = $(target).val().match(/^(\d+)x(\d+)$/i); + const onlyEpisode = $(target).val().match(/^(\d+)$/i); + let sceneSeason = null; + let sceneEpisode = null; + let isValid = false; + if (m) { + sceneSeason = m[1]; + sceneEpisode = m[2]; + isValid = setInputValidInvalid(true, $(target)); + } else if (onlyEpisode) { + // For example when '5' is filled in instead of '1x5', asume it's the first season + sceneSeason = forSeason; + sceneEpisode = onlyEpisode[1]; + isValid = setInputValidInvalid(true, $(target)); + } else { + isValid = setInputValidInvalid(false, $(target)); + } + + if (isValid) { + setEpisodeSceneNumbering(forSeason, forEpisode, sceneSeason, sceneEpisode); + } + }); + + $(document.body).on('change', '.sceneAbsolute', event => { + const target = event.currentTarget; + // Strip non-numeric characters + $(target).val($(target).val().replace(/[^0-9xX]*/g, '')); + const forAbsolute = $(target).attr('data-for-absolute'); + + const m = $(target).val().match(/^(\d{1,3})$/i); + let sceneAbsolute = null; + if (m) { + sceneAbsolute = m[1]; + } + setAbsoluteSceneNumbering(forAbsolute, sceneAbsolute); + }); + + $('#showTable, #animeTable').tablesorter({ + widgets: ['saveSort', 'stickyHeaders', 'columnSelector'], + widgetOptions: { + columnSelector_saveColumns: true, // eslint-disable-line camelcase + columnSelector_layout: '', // eslint-disable-line camelcase + columnSelector_mediaquery: false, // eslint-disable-line camelcase + columnSelector_cssChecked: 'checked' // eslint-disable-line camelcase + } + }); + + $('#popover').popover({ + placement: 'bottom', + html: true, // Required if content has HTML + content: '
' + }).on('shown.bs.popover', () => { // Bootstrap popover event triggered when the popover opens + $.tablesorter.columnSelector.attachTo($('#showTable, #animeTable'), '#popover-target'); + }); + + // Moved and rewritten this from displayShow. This changes the button when clicked for collapsing/expanding the + // Season to Show Episodes or Hide Episodes. + $('.collapse.toggle').on('hide.bs.collapse', function() { + const reg = /collapseSeason-(\d+)/g; + const result = reg.exec(this.id); + $('#showseason-' + result[1]).text('Show Episodes'); + $('#season-' + result[1] + '-cols').addClass('shadow'); + }); + $('.collapse.toggle').on('show.bs.collapse', function() { + const reg = /collapseSeason-(\d+)/g; + const result = reg.exec(this.id); + $('#showseason-' + result[1]).text('Hide Episodes'); + $('#season-' + result[1] + '-cols').removeClass('shadow'); + }); + + // Generate IMDB stars + $('.imdbstars').each((index, element) => { + $(element).html($('').width($(element).text() * 12)); + }); + + // @TODO: OMG: This is just a basic json, in future it should be based on the CRUD route. + // Get the season exceptions and the xem season mappings. + $.getJSON('home/getSeasonSceneExceptions', { + indexername: $('#indexer-name').val(), + seriesid: $('#series-id').val() // eslint-disable-line camelcase + }, data => { + setSeasonSceneException(data); + }); + + $(document.body).on('click', '.display-specials a', event => { + api.patch('config/main', { + layout: { + show: { + specials: $(event.currentTarget).text() !== 'Hide' + } + } + }).then(response => { + log.info(response.data); + window.location.reload(); + }).catch(error => { + log.error(error.data); + }); + }); + }, + methods: { + // Adjust the summary background position and size on page load and resize + moveSummaryBackground() { + const height = $('#summary').height() + 10; + const top = $('#summary').offset().top + 5; + $('#summaryBackground').height(height); + $('#summaryBackground').offset({ top, left: 0 }); + $('#summaryBackground').show(); + }, + movecheckboxControlsBackground() { + const height = $('#checkboxControls').height() + 10; + const top = $('#checkboxControls').offset().top - 3; + $('#checkboxControlsBackground').height(height); + $('#checkboxControlsBackground').offset({ top, left: 0 }); + $('#checkboxControlsBackground').show(); + }, + setQuality(quality, seriesSlug, episodes) { + const patchData = {}; + episodes.forEach(episode => { + patchData[episode] = { quality: parseInt(quality, 10) }; + }); + + api.patch('series/' + seriesSlug + '/episodes', patchData).then(response => { + log.info(response.data); + window.location.reload(); + }).catch(error => { + log.error(error.data); + }); + }, + setEpisodeSceneNumbering(forSeason, forEpisode, sceneSeason, sceneEpisode) { + const indexerName = $('#indexer-name').val(); + const seriesId = $('#series-id').val(); + + if (sceneSeason === '') { + sceneSeason = null; + } + if (sceneEpisode === '') { + sceneEpisode = null; + } + + $.getJSON('home/setSceneNumbering', { + indexername: indexerName, + seriesid: seriesId, + forSeason, + forEpisode, + sceneSeason, + sceneEpisode + }, data => { + // Set the values we get back + if (data.sceneSeason === null || data.sceneEpisode === null) { + $('#sceneSeasonXEpisode_' + seriesId + '_' + forSeason + '_' + forEpisode).val(''); + } else { + $('#sceneSeasonXEpisode_' + seriesId + '_' + forSeason + '_' + forEpisode).val(data.sceneSeason + 'x' + data.sceneEpisode); + } + if (!data.success) { + if (data.errorMessage) { + alert(data.errorMessage); // eslint-disable-line no-alert + } else { + alert('Update failed.'); // eslint-disable-line no-alert + } + } + }); + }, + setAbsoluteSceneNumbering(forAbsolute, sceneAbsolute) { + const indexerName = $('#indexer-name').val(); + const seriesId = $('#series-id').val(); + + if (sceneAbsolute === '') { + sceneAbsolute = null; + } + + $.getJSON('home/setSceneNumbering', { + indexername: indexerName, + seriesid: seriesId, + forAbsolute, + sceneAbsolute + }, data => { + // Set the values we get back + if (data.sceneAbsolute === null) { + $('#sceneAbsolute_' + seriesId + '_' + forAbsolute).val(''); + } else { + $('#sceneAbsolute_' + seriesId + '_' + forAbsolute).val(data.sceneAbsolute); + } + + if (!data.success) { + if (data.errorMessage) { + alert(data.errorMessage); // eslint-disable-line no-alert + } else { + alert('Update failed.'); // eslint-disable-line no-alert + } + } + }); + }, + setInputValidInvalid(valid, el) { + if (valid) { + $(el).css({ + 'background-color': '#90EE90', // Green + 'color': '#FFF', // eslint-disable-line quote-props + 'font-weight': 'bold' + }); + return true; + } + $(el).css({ + 'background-color': '#FF0000', // Red + 'color': '#FFF!important', // eslint-disable-line quote-props + 'font-weight': 'bold' + }); + return false; + }, + // Set the season exception based on using the get_xem_numbering_for_show() for animes if available in data.xemNumbering, + // or else try to map using just the data.season_exceptions. + setSeasonSceneException(data) { + $.each(data.seasonExceptions, (season, nameExceptions) => { + let foundInXem = false; + // Check if it is a season name exception, we don't handle the show name exceptions here + if (season >= 0) { + // Loop through the xem mapping, and check if there is a xem_season, that needs to show the season name exception + $.each(data.xemNumbering, (indexerSeason, xemSeason) => { + if (xemSeason === parseInt(season, 10)) { + foundInXem = true; + $('', { + id: 'xem-exception-season-' + xemSeason, + alt: '[xem]', + height: '16', + width: '16', + src: 'images/xem.png', + title: nameExceptions.join(', ') + }).appendTo('[data-season=' + indexerSeason + ']'); + } + }); + + // This is not a xem season exception, let's set the exceptions as a medusa exception + if (!foundInXem) { + $('', { + id: 'xem-exception-season-' + season, + alt: '[medusa]', + height: '16', + width: '16', + src: 'images/ico/favicon-16.png', + title: nameExceptions.join(', ') + }).appendTo('[data-season=' + season + ']'); + } + } + }); + }, + showHideRows(whichClass) { + const status = $('#checkboxControls > input, #' + whichClass).prop('checked'); + $('tr.' + whichClass).each((index, element) => { + if (status) { + $(element).show(); + } else { + $(element).hide(); + } + }); + + // Hide season headers with no episodes under them + $('tr.seasonheader').each((index, element) => { + let numRows = 0; + const seasonNo = $(element).attr('id'); + $('tr.' + seasonNo + ' :visible').each(() => { + numRows++; + }); + if (numRows === 0) { + $(element).hide(); + $('#' + seasonNo + '-cols').hide(); + } else { + $(element).show(); + $('#' + seasonNo + '-cols').show(); + } + }); + } } }); }; diff --git a/themes-default/slim/views/layouts/main.mako b/themes-default/slim/views/layouts/main.mako index d14510ad2e..b346b7e3fb 100644 --- a/themes-default/slim/views/layouts/main.mako +++ b/themes-default/slim/views/layouts/main.mako @@ -100,7 +100,6 @@ - diff --git a/themes/dark/assets/js/home/display-show.js b/themes/dark/assets/js/home/display-show.js deleted file mode 100644 index bef3a32e57..0000000000 --- a/themes/dark/assets/js/home/display-show.js +++ /dev/null @@ -1,441 +0,0 @@ -MEDUSA.home.displayShow = function() { // eslint-disable-line max-lines - $('.imdbPlot').on('click', function() { - $(this).prev('span').toggle(); - if ($(this).html() === '..show less') { - $(this).html('..show more'); - } else { - $(this).html('..show less'); - } - moveSummaryBackground(); - movecheckboxControlsBackground(); - }); - - // Adjust the summary background position and size on page load and resize - function moveSummaryBackground() { - const height = $('#summary').height() + 10; - const top = $('#summary').offset().top + 5; - $('#summaryBackground').height(height); - $('#summaryBackground').offset({ top, left: 0 }); - $('#summaryBackground').show(); - } - - function movecheckboxControlsBackground() { - const height = $('#checkboxControls').height() + 10; - const top = $('#checkboxControls').offset().top - 3; - $('#checkboxControlsBackground').height(height); - $('#checkboxControlsBackground').offset({ top, left: 0 }); - $('#checkboxControlsBackground').show(); - } - - $(window).resize(() => { - moveSummaryBackground(); - movecheckboxControlsBackground(); - }); - - $(() => { - moveSummaryBackground(); - movecheckboxControlsBackground(); - }); - - $.ajaxEpSearch({ - colorRow: true - }); - - startAjaxEpisodeSubtitles(); // eslint-disable-line no-undef - $.ajaxEpSubtitlesSearch(); - $.ajaxEpRedownloadSubtitle(); - - const setQuality = (quality, seriesSlug, episodes) => { - const patchData = {}; - episodes.forEach(episode => { - patchData[episode] = { quality: parseInt(quality, 10) }; - }); - - api.patch('series/' + seriesSlug + '/episodes', patchData).then(response => { - log.info(response.data); - window.location.reload(); - }).catch(error => { - log.error(error.data); - }); - }; - - $('#seasonJump').on('change', function() { - const id = $('#seasonJump option:selected').val(); - if (id && id !== 'jump') { - const season = $('#seasonJump option:selected').data('season'); - $('html,body').animate({ scrollTop: $('[name="' + id.substring(1) + '"]').offset().top - 100 }, 'slow'); - $('#collapseSeason-' + season).collapse('show'); - location.hash = id; - } - $(this).val('jump'); - }); - - $('#changeStatus').on('click', () => { - const epArr = []; - const status = $('#statusSelect').val(); - const quality = $('#qualitySelect').val(); - const seriesSlug = $('#series-slug').val(); - - $('.epCheck').each(function() { - if (this.checked === true) { - epArr.push($(this).attr('id')); - } - }); - - if (epArr.length === 0) { - return false; - } - - if (quality) { - setQuality(quality, seriesSlug, epArr); - } - - if (status) { - window.location.href = $('base').attr('href') + 'home/setStatus?' + - 'indexername=' + $('#indexer-name').attr('value') + - '&seriesid=' + $('#series-id').attr('value') + - '&eps=' + epArr.join('|') + - '&status=' + status; - } - }); - - $('.seasonCheck').on('click', function() { - const seasCheck = this; - const seasNo = $(seasCheck).attr('id'); - - $('#collapseSeason-' + seasNo).collapse('show'); - const seasonIdentifier = 's' + seasNo; - $('.epCheck:visible').each(function() { - const epParts = $(this).attr('id').split('e'); - if (epParts[0] === seasonIdentifier) { - this.checked = seasCheck.checked; - } - }); - }); - - let lastCheck = null; - $('.epCheck').on('click', function(event) { - if (!lastCheck || !event.shiftKey) { - lastCheck = this; - return; - } - - const check = this; - let found = 0; - - $('.epCheck').each(function() { - if (found === 1) { - this.checked = lastCheck.checked; - } - - if (found === 2) { - return false; - } - - if (this === check || this === lastCheck) { - found++; - } - }); - }); - - // Selects all visible episode checkboxes. - $('.seriesCheck').on('click', () => { - $('.epCheck:visible').each(function() { - this.checked = true; - }); - $('.seasonCheck:visible').each(function() { - this.checked = true; - }); - }); - - // Clears all visible episode checkboxes and the season selectors - $('.clearAll').on('click', () => { - $('.epCheck:visible').each(function() { - this.checked = false; - }); - $('.seasonCheck:visible').each(function() { - this.checked = false; - }); - }); - - // Show/hide different types of rows when the checkboxes are changed - $('#checkboxControls input').on('change', function() { - const whichClass = $(this).attr('id'); - $(this).showHideRows(whichClass); - }); - - // Initially show/hide all the rows according to the checkboxes - $('#checkboxControls input').each(function() { - const status = $(this).prop('checked'); - $('tr.' + $(this).attr('id')).each(function() { - if (status) { - $(this).show(); - } else { - $(this).hide(); - } - }); - }); - - $.fn.showHideRows = function(whichClass) { - const status = $('#checkboxControls > input, #' + whichClass).prop('checked'); - $('tr.' + whichClass).each(function() { - if (status) { - $(this).show(); - } else { - $(this).hide(); - } - }); - - // Hide season headers with no episodes under them - $('tr.seasonheader').each(function() { - let numRows = 0; - const seasonNo = $(this).attr('id'); - $('tr.' + seasonNo + ' :visible').each(() => { - numRows++; - }); - if (numRows === 0) { - $(this).hide(); - $('#' + seasonNo + '-cols').hide(); - } else { - $(this).show(); - $('#' + seasonNo + '-cols').show(); - } - }); - }; - - function setEpisodeSceneNumbering(forSeason, forEpisode, sceneSeason, sceneEpisode) { - const indexerName = $('#indexer-name').val(); - const seriesId = $('#series-id').val(); - - if (sceneSeason === '') { - sceneSeason = null; - } - if (sceneEpisode === '') { - sceneEpisode = null; - } - - $.getJSON('home/setSceneNumbering', { - indexername: indexerName, - seriesid: seriesId, - forSeason, - forEpisode, - sceneSeason, - sceneEpisode - }, data => { - // Set the values we get back - if (data.sceneSeason === null || data.sceneEpisode === null) { - $('#sceneSeasonXEpisode_' + seriesId + '_' + forSeason + '_' + forEpisode).val(''); - } else { - $('#sceneSeasonXEpisode_' + seriesId + '_' + forSeason + '_' + forEpisode).val(data.sceneSeason + 'x' + data.sceneEpisode); - } - if (!data.success) { - if (data.errorMessage) { - alert(data.errorMessage); // eslint-disable-line no-alert - } else { - alert('Update failed.'); // eslint-disable-line no-alert - } - } - }); - } - - function setAbsoluteSceneNumbering(forAbsolute, sceneAbsolute) { - const indexerName = $('#indexer-name').val(); - const seriesId = $('#series-id').val(); - - if (sceneAbsolute === '') { - sceneAbsolute = null; - } - - $.getJSON('home/setSceneNumbering', { - indexername: indexerName, - seriesid: seriesId, - forAbsolute, - sceneAbsolute - }, data => { - // Set the values we get back - if (data.sceneAbsolute === null) { - $('#sceneAbsolute_' + seriesId + '_' + forAbsolute).val(''); - } else { - $('#sceneAbsolute_' + seriesId + '_' + forAbsolute).val(data.sceneAbsolute); - } - - if (!data.success) { - if (data.errorMessage) { - alert(data.errorMessage); // eslint-disable-line no-alert - } else { - alert('Update failed.'); // eslint-disable-line no-alert - } - } - }); - } - - function setInputValidInvalid(valid, el) { - if (valid) { - $(el).css({ - 'background-color': '#90EE90', // Green - 'color': '#FFF', // eslint-disable-line quote-props - 'font-weight': 'bold' - }); - return true; - } - $(el).css({ - 'background-color': '#FF0000', // Red - 'color': '#FFF!important', // eslint-disable-line quote-props - 'font-weight': 'bold' - }); - return false; - } - - $('.sceneSeasonXEpisode').on('change', function() { - // Strip non-numeric characters - const value = $(this).val(); - $(this).val(value.replace(/[^0-9xX]*/g, '')); - const forSeason = $(this).attr('data-for-season'); - const forEpisode = $(this).attr('data-for-episode'); - - // If empty reset the field - if (value === '') { - setEpisodeSceneNumbering(forSeason, forEpisode, null, null); - return; - } - - const m = $(this).val().match(/^(\d+)x(\d+)$/i); - const onlyEpisode = $(this).val().match(/^(\d+)$/i); - let sceneSeason = null; - let sceneEpisode = null; - let isValid = false; - if (m) { - sceneSeason = m[1]; - sceneEpisode = m[2]; - isValid = setInputValidInvalid(true, $(this)); - } else if (onlyEpisode) { - // For example when '5' is filled in instead of '1x5', asume it's the first season - sceneSeason = forSeason; - sceneEpisode = onlyEpisode[1]; - isValid = setInputValidInvalid(true, $(this)); - } else { - isValid = setInputValidInvalid(false, $(this)); - } - - if (isValid) { - setEpisodeSceneNumbering(forSeason, forEpisode, sceneSeason, sceneEpisode); - } - }); - - $('.sceneAbsolute').on('change', function() { - // Strip non-numeric characters - $(this).val($(this).val().replace(/[^0-9xX]*/g, '')); - const forAbsolute = $(this).attr('data-for-absolute'); - - const m = $(this).val().match(/^(\d{1,3})$/i); - let sceneAbsolute = null; - if (m) { - sceneAbsolute = m[1]; - } - setAbsoluteSceneNumbering(forAbsolute, sceneAbsolute); - }); - - $.fn.generateStars = function() { - return this.each((i, e) => { - $(e).html($('').width($(e).text() * 12)); - }); - }; - - $('.imdbstars').generateStars(); - - $('#showTable, #animeTable').tablesorter({ - widgets: ['saveSort', 'stickyHeaders', 'columnSelector'], - widgetOptions: { - columnSelector_saveColumns: true, // eslint-disable-line camelcase - columnSelector_layout: '', // eslint-disable-line camelcase - columnSelector_mediaquery: false, // eslint-disable-line camelcase - columnSelector_cssChecked: 'checked' // eslint-disable-line camelcase - } - }); - - $('#popover').popover({ - placement: 'bottom', - html: true, // Required if content has HTML - content: '
' - }).on('shown.bs.popover', () => { // Bootstrap popover event triggered when the popover opens - $.tablesorter.columnSelector.attachTo($('#showTable, #animeTable'), '#popover-target'); - }); - - // Moved and rewritten this from displayShow. This changes the button when clicked for collapsing/expanding the - // Season to Show Episodes or Hide Episodes. - $(() => { - $('.collapse.toggle').on('hide.bs.collapse', function() { - const reg = /collapseSeason-(\d+)/g; - const result = reg.exec(this.id); - $('#showseason-' + result[1]).text('Show Episodes'); - $('#season-' + result[1] + '-cols').addClass('shadow'); - }); - $('.collapse.toggle').on('show.bs.collapse', function() { - const reg = /collapseSeason-(\d+)/g; - const result = reg.exec(this.id); - $('#showseason-' + result[1]).text('Hide Episodes'); - $('#season-' + result[1] + '-cols').removeClass('shadow'); - }); - }); - - // Set the season exception based on using the get_xem_numbering_for_show() for animes if available in data.xemNumbering, - // or else try to map using just the data.season_exceptions. - function setSeasonSceneException(data) { - $.each(data.seasonExceptions, (season, nameExceptions) => { - let foundInXem = false; - // Check if it is a season name exception, we don't handle the show name exceptions here - if (season >= 0) { - // Loop through the xem mapping, and check if there is a xem_season, that needs to show the season name exception - $.each(data.xemNumbering, (indexerSeason, xemSeason) => { - if (xemSeason === parseInt(season, 10)) { - foundInXem = true; - $('', { - id: 'xem-exception-season-' + xemSeason, - alt: '[xem]', - height: '16', - width: '16', - src: 'images/xem.png', - title: nameExceptions.join(', ') - }).appendTo('[data-season=' + indexerSeason + ']'); - } - }); - - // This is not a xem season exception, let's set the exceptions as a medusa exception - if (!foundInXem) { - $('', { - id: 'xem-exception-season-' + season, - alt: '[medusa]', - height: '16', - width: '16', - src: 'images/ico/favicon-16.png', - title: nameExceptions.join(', ') - }).appendTo('[data-season=' + season + ']'); - } - } - }); - } - - // @TODO: OMG: This is just a basic json, in future it should be based on the CRUD route. - // Get the season exceptions and the xem season mappings. - $.getJSON('home/getSeasonSceneExceptions', { - indexername: $('#indexer-name').val(), - seriesid: $('#series-id').val() // eslint-disable-line camelcase - }, data => { - setSeasonSceneException(data); - }); - - $('.display-specials a').on('click', function() { - api.patch('config/main', { - layout: { - show: { - specials: $(this).text() !== 'Hide' - } - } - }).then(response => { - log.info(response.data); - window.location.reload(); - }).catch(error => { - log.error(error.data); - }); - }); -}; diff --git a/themes/dark/assets/js/home/display-show.js.map b/themes/dark/assets/js/home/display-show.js.map deleted file mode 100644 index 839906e221..0000000000 --- a/themes/dark/assets/js/home/display-show.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"names":[],"mappings":"","sources":["js/home/display-show.js"],"sourcesContent":["(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c=\"function\"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error(\"Cannot find module '\"+i+\"'\");throw a.code=\"MODULE_NOT_FOUND\",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u=\"function\"==typeof require&&require,i=0;i input, #' + whichClass).prop('checked');\n $('tr.' + whichClass).each(function () {\n if (status) {\n $(this).show();\n } else {\n $(this).hide();\n }\n });\n\n // Hide season headers with no episodes under them\n $('tr.seasonheader').each(function () {\n var numRows = 0;\n var seasonNo = $(this).attr('id');\n $('tr.' + seasonNo + ' :visible').each(function () {\n numRows++;\n });\n if (numRows === 0) {\n $(this).hide();\n $('#' + seasonNo + '-cols').hide();\n } else {\n $(this).show();\n $('#' + seasonNo + '-cols').show();\n }\n });\n };\n\n function setEpisodeSceneNumbering(forSeason, forEpisode, sceneSeason, sceneEpisode) {\n var indexerName = $('#indexer-name').val();\n var seriesId = $('#series-id').val();\n\n if (sceneSeason === '') {\n sceneSeason = null;\n }\n if (sceneEpisode === '') {\n sceneEpisode = null;\n }\n\n $.getJSON('home/setSceneNumbering', {\n indexername: indexerName,\n seriesid: seriesId,\n forSeason: forSeason,\n forEpisode: forEpisode,\n sceneSeason: sceneSeason,\n sceneEpisode: sceneEpisode\n }, function (data) {\n // Set the values we get back\n if (data.sceneSeason === null || data.sceneEpisode === null) {\n $('#sceneSeasonXEpisode_' + seriesId + '_' + forSeason + '_' + forEpisode).val('');\n } else {\n $('#sceneSeasonXEpisode_' + seriesId + '_' + forSeason + '_' + forEpisode).val(data.sceneSeason + 'x' + data.sceneEpisode);\n }\n if (!data.success) {\n if (data.errorMessage) {\n alert(data.errorMessage); // eslint-disable-line no-alert\n } else {\n alert('Update failed.'); // eslint-disable-line no-alert\n }\n }\n });\n }\n\n function setAbsoluteSceneNumbering(forAbsolute, sceneAbsolute) {\n var indexerName = $('#indexer-name').val();\n var seriesId = $('#series-id').val();\n\n if (sceneAbsolute === '') {\n sceneAbsolute = null;\n }\n\n $.getJSON('home/setSceneNumbering', {\n indexername: indexerName,\n seriesid: seriesId,\n forAbsolute: forAbsolute,\n sceneAbsolute: sceneAbsolute\n }, function (data) {\n // Set the values we get back\n if (data.sceneAbsolute === null) {\n $('#sceneAbsolute_' + seriesId + '_' + forAbsolute).val('');\n } else {\n $('#sceneAbsolute_' + seriesId + '_' + forAbsolute).val(data.sceneAbsolute);\n }\n\n if (!data.success) {\n if (data.errorMessage) {\n alert(data.errorMessage); // eslint-disable-line no-alert\n } else {\n alert('Update failed.'); // eslint-disable-line no-alert\n }\n }\n });\n }\n\n function setInputValidInvalid(valid, el) {\n if (valid) {\n $(el).css({\n 'background-color': '#90EE90', // Green\n 'color': '#FFF', // eslint-disable-line quote-props\n 'font-weight': 'bold'\n });\n return true;\n }\n $(el).css({\n 'background-color': '#FF0000', // Red\n 'color': '#FFF!important', // eslint-disable-line quote-props\n 'font-weight': 'bold'\n });\n return false;\n }\n\n $('.sceneSeasonXEpisode').on('change', function () {\n // Strip non-numeric characters\n var value = $(this).val();\n $(this).val(value.replace(/[^0-9xX]*/g, ''));\n var forSeason = $(this).attr('data-for-season');\n var forEpisode = $(this).attr('data-for-episode');\n\n // If empty reset the field\n if (value === '') {\n setEpisodeSceneNumbering(forSeason, forEpisode, null, null);\n return;\n }\n\n var m = $(this).val().match(/^(\\d+)x(\\d+)$/i);\n var onlyEpisode = $(this).val().match(/^(\\d+)$/i);\n var sceneSeason = null;\n var sceneEpisode = null;\n var isValid = false;\n if (m) {\n sceneSeason = m[1];\n sceneEpisode = m[2];\n isValid = setInputValidInvalid(true, $(this));\n } else if (onlyEpisode) {\n // For example when '5' is filled in instead of '1x5', asume it's the first season\n sceneSeason = forSeason;\n sceneEpisode = onlyEpisode[1];\n isValid = setInputValidInvalid(true, $(this));\n } else {\n isValid = setInputValidInvalid(false, $(this));\n }\n\n if (isValid) {\n setEpisodeSceneNumbering(forSeason, forEpisode, sceneSeason, sceneEpisode);\n }\n });\n\n $('.sceneAbsolute').on('change', function () {\n // Strip non-numeric characters\n $(this).val($(this).val().replace(/[^0-9xX]*/g, ''));\n var forAbsolute = $(this).attr('data-for-absolute');\n\n var m = $(this).val().match(/^(\\d{1,3})$/i);\n var sceneAbsolute = null;\n if (m) {\n sceneAbsolute = m[1];\n }\n setAbsoluteSceneNumbering(forAbsolute, sceneAbsolute);\n });\n\n $.fn.generateStars = function () {\n return this.each(function (i, e) {\n $(e).html($('').width($(e).text() * 12));\n });\n };\n\n $('.imdbstars').generateStars();\n\n $('#showTable, #animeTable').tablesorter({\n widgets: ['saveSort', 'stickyHeaders', 'columnSelector'],\n widgetOptions: {\n columnSelector_saveColumns: true, // eslint-disable-line camelcase\n columnSelector_layout: '', // eslint-disable-line camelcase\n columnSelector_mediaquery: false, // eslint-disable-line camelcase\n columnSelector_cssChecked: 'checked' // eslint-disable-line camelcase\n }\n });\n\n $('#popover').popover({\n placement: 'bottom',\n html: true, // Required if content has HTML\n content: '
'\n }).on('shown.bs.popover', function () {\n // Bootstrap popover event triggered when the popover opens\n $.tablesorter.columnSelector.attachTo($('#showTable, #animeTable'), '#popover-target');\n });\n\n // Moved and rewritten this from displayShow. This changes the button when clicked for collapsing/expanding the\n // Season to Show Episodes or Hide Episodes.\n $(function () {\n $('.collapse.toggle').on('hide.bs.collapse', function () {\n var reg = /collapseSeason-(\\d+)/g;\n var result = reg.exec(this.id);\n $('#showseason-' + result[1]).text('Show Episodes');\n $('#season-' + result[1] + '-cols').addClass('shadow');\n });\n $('.collapse.toggle').on('show.bs.collapse', function () {\n var reg = /collapseSeason-(\\d+)/g;\n var result = reg.exec(this.id);\n $('#showseason-' + result[1]).text('Hide Episodes');\n $('#season-' + result[1] + '-cols').removeClass('shadow');\n });\n });\n\n // Set the season exception based on using the get_xem_numbering_for_show() for animes if available in data.xemNumbering,\n // or else try to map using just the data.season_exceptions.\n function setSeasonSceneException(data) {\n $.each(data.seasonExceptions, function (season, nameExceptions) {\n var foundInXem = false;\n // Check if it is a season name exception, we don't handle the show name exceptions here\n if (season >= 0) {\n // Loop through the xem mapping, and check if there is a xem_season, that needs to show the season name exception\n $.each(data.xemNumbering, function (indexerSeason, xemSeason) {\n if (xemSeason === parseInt(season, 10)) {\n foundInXem = true;\n $('', {\n id: 'xem-exception-season-' + xemSeason,\n alt: '[xem]',\n height: '16',\n width: '16',\n src: 'images/xem.png',\n title: nameExceptions.join(', ')\n }).appendTo('[data-season=' + indexerSeason + ']');\n }\n });\n\n // This is not a xem season exception, let's set the exceptions as a medusa exception\n if (!foundInXem) {\n $('', {\n id: 'xem-exception-season-' + season,\n alt: '[medusa]',\n height: '16',\n width: '16',\n src: 'images/ico/favicon-16.png',\n title: nameExceptions.join(', ')\n }).appendTo('[data-season=' + season + ']');\n }\n }\n });\n }\n\n // @TODO: OMG: This is just a basic json, in future it should be based on the CRUD route.\n // Get the season exceptions and the xem season mappings.\n $.getJSON('home/getSeasonSceneExceptions', {\n indexername: $('#indexer-name').val(),\n seriesid: $('#series-id').val() // eslint-disable-line camelcase\n }, function (data) {\n setSeasonSceneException(data);\n });\n\n $('.display-specials a').on('click', function () {\n api.patch('config/main', {\n layout: {\n show: {\n specials: $(this).text() !== 'Hide'\n }\n }\n }).then(function (response) {\n log.info(response.data);\n window.location.reload();\n }).catch(function (error) {\n log.error(error.data);\n });\n });\n};\n\n},{}]},{},[1]);\n"],"file":"display-show.js"} \ No newline at end of file diff --git a/themes/dark/templates/displayShow.mako b/themes/dark/templates/displayShow.mako index 65eb52ef41..964bb6282b 100644 --- a/themes/dark/templates/displayShow.mako +++ b/themes/dark/templates/displayShow.mako @@ -27,12 +27,451 @@ const startVue = () => { $store.dispatch('getShows'); // Used by show-selector component }, mounted() { - // Adjust the summary background position and size on page load and resize + const { + moveSummaryBackground, + movecheckboxControlsBackground, + setQuality, + setEpisodeSceneNumbering, + setAbsoluteSceneNumbering, + setInputValidInvalid, + setSeasonSceneException, + showHideRows, + } = this; + + $(window).resize(() => { + moveSummaryBackground(); + movecheckboxControlsBackground(); + }); + this.$once('loaded', () => { this.$nextTick(() => { + // Adjust the summary background position and size window.dispatchEvent(new Event('resize')); + + $.ajaxEpSearch({ + colorRow: true + }); + + startAjaxEpisodeSubtitles(); // eslint-disable-line no-undef + $.ajaxEpSubtitlesSearch(); + $.ajaxEpRedownloadSubtitle(); + }); + }); + + $(document.body).on('click', '.imdbPlot', event => { + const $target = $(event.currentTarget); + $target.prev('span').toggle(); + if ($target.html() === '..show less') { + $target.html('..show more'); + } else { + $target.html('..show less'); + } + moveSummaryBackground(); + movecheckboxControlsBackground(); + }); + + $(document.body).on('change', '#seasonJump', (event) => { + const id = $('#seasonJump option:selected').val(); + if (id && id !== 'jump') { + const season = $('#seasonJump option:selected').data('season'); + $('html,body').animate({ scrollTop: $('[name="' + id.substring(1) + '"]').offset().top - 100 }, 'slow'); + $('#collapseSeason-' + season).collapse('show'); + location.hash = id; + } + $(event.currentTarget).val('jump'); + }); + + $(document.body).on('click', '#changeStatus', () => { + const epArr = []; + const status = $('#statusSelect').val(); + const quality = $('#qualitySelect').val(); + const seriesSlug = $('#series-slug').val(); + + $('.epCheck').each((index, element) => { + if (element.checked === true) { + epArr.push($(element).attr('id')); + } + }); + + if (epArr.length === 0) { + return false; + } + + if (quality) { + setQuality(quality, seriesSlug, epArr); + } + + if (status) { + window.location.href = $('base').attr('href') + 'home/setStatus?' + + 'indexername=' + $('#indexer-name').attr('value') + + '&seriesid=' + $('#series-id').attr('value') + + '&eps=' + epArr.join('|') + + '&status=' + status; + } + }); + + $(document.body).on('click', '.seasonCheck', event => { + const seasCheck = event.currentTarget; + const seasNo = $(seasCheck).attr('id'); + + $('#collapseSeason-' + seasNo).collapse('show'); + const seasonIdentifier = 's' + seasNo; + $('.epCheck:visible').each((index, element) => { + const epParts = $(element).attr('id').split('e'); + if (epParts[0] === seasonIdentifier) { + element.checked = seasCheck.checked; + } + }); + }); + + let lastCheck = null; + $(document.body).on('click', '.epCheck', event => { + const target = event.currentTarget; + if (!lastCheck || !event.shiftKey) { + lastCheck = target; + return; + } + + const check = target; + let found = 0; + + $('.epCheck').each((index, element) => { + if (found === 1) { + element.checked = lastCheck.checked; + } + + if (found === 2) { + return false; + } + + if (element === check || element === lastCheck) { + found++; + } + }); + }); + + // Selects all visible episode checkboxes. + $(document.body).on('click', '.seriesCheck', () => { + $('.epCheck:visible').each((index, element) => { + element.checked = true; + }); + $('.seasonCheck:visible').each((index, element) => { + element.checked = true; + }); + }); + + // Clears all visible episode checkboxes and the season selectors + $(document.body).on('click', '.clearAll', () => { + $('.epCheck:visible').each((index, element) => { + element.checked = false; + }); + $('.seasonCheck:visible').each((index, element) => { + element.checked = false; + }); + }); + + // Show/hide different types of rows when the checkboxes are changed + $(document.body).on('change', '#checkboxControls input', event => { + const whichClass = $(event.currentTarget).attr('id'); + showHideRows(whichClass); + }); + + // Initially show/hide all the rows according to the checkboxes + $('#checkboxControls input').each((index, element) => { + const status = $(element).prop('checked'); + $('tr.' + $(element).attr('id')).each((index, tableRow) => { + if (status) { + $(tableRow).show(); + } else { + $(tableRow).hide(); + } }); }); + + $(document.body).on('change', '.sceneSeasonXEpisode', event => { + const target = event.currentTarget; + // Strip non-numeric characters + const value = $(target).val(); + $(target).val(value.replace(/[^0-9xX]*/g, '')); + const forSeason = $(target).attr('data-for-season'); + const forEpisode = $(target).attr('data-for-episode'); + + // If empty reset the field + if (value === '') { + setEpisodeSceneNumbering(forSeason, forEpisode, null, null); + return; + } + + const m = $(target).val().match(/^(\d+)x(\d+)$/i); + const onlyEpisode = $(target).val().match(/^(\d+)$/i); + let sceneSeason = null; + let sceneEpisode = null; + let isValid = false; + if (m) { + sceneSeason = m[1]; + sceneEpisode = m[2]; + isValid = setInputValidInvalid(true, $(target)); + } else if (onlyEpisode) { + // For example when '5' is filled in instead of '1x5', asume it's the first season + sceneSeason = forSeason; + sceneEpisode = onlyEpisode[1]; + isValid = setInputValidInvalid(true, $(target)); + } else { + isValid = setInputValidInvalid(false, $(target)); + } + + if (isValid) { + setEpisodeSceneNumbering(forSeason, forEpisode, sceneSeason, sceneEpisode); + } + }); + + $(document.body).on('change', '.sceneAbsolute', event => { + const target = event.currentTarget; + // Strip non-numeric characters + $(target).val($(target).val().replace(/[^0-9xX]*/g, '')); + const forAbsolute = $(target).attr('data-for-absolute'); + + const m = $(target).val().match(/^(\d{1,3})$/i); + let sceneAbsolute = null; + if (m) { + sceneAbsolute = m[1]; + } + setAbsoluteSceneNumbering(forAbsolute, sceneAbsolute); + }); + + $('#showTable, #animeTable').tablesorter({ + widgets: ['saveSort', 'stickyHeaders', 'columnSelector'], + widgetOptions: { + columnSelector_saveColumns: true, // eslint-disable-line camelcase + columnSelector_layout: '', // eslint-disable-line camelcase + columnSelector_mediaquery: false, // eslint-disable-line camelcase + columnSelector_cssChecked: 'checked' // eslint-disable-line camelcase + } + }); + + $('#popover').popover({ + placement: 'bottom', + html: true, // Required if content has HTML + content: '
' + }).on('shown.bs.popover', () => { // Bootstrap popover event triggered when the popover opens + $.tablesorter.columnSelector.attachTo($('#showTable, #animeTable'), '#popover-target'); + }); + + // Moved and rewritten this from displayShow. This changes the button when clicked for collapsing/expanding the + // Season to Show Episodes or Hide Episodes. + $('.collapse.toggle').on('hide.bs.collapse', function() { + const reg = /collapseSeason-(\d+)/g; + const result = reg.exec(this.id); + $('#showseason-' + result[1]).text('Show Episodes'); + $('#season-' + result[1] + '-cols').addClass('shadow'); + }); + $('.collapse.toggle').on('show.bs.collapse', function() { + const reg = /collapseSeason-(\d+)/g; + const result = reg.exec(this.id); + $('#showseason-' + result[1]).text('Hide Episodes'); + $('#season-' + result[1] + '-cols').removeClass('shadow'); + }); + + // Generate IMDB stars + $('.imdbstars').each((index, element) => { + $(element).html($('').width($(element).text() * 12)); + }); + + // @TODO: OMG: This is just a basic json, in future it should be based on the CRUD route. + // Get the season exceptions and the xem season mappings. + $.getJSON('home/getSeasonSceneExceptions', { + indexername: $('#indexer-name').val(), + seriesid: $('#series-id').val() // eslint-disable-line camelcase + }, data => { + setSeasonSceneException(data); + }); + + $(document.body).on('click', '.display-specials a', event => { + api.patch('config/main', { + layout: { + show: { + specials: $(event.currentTarget).text() !== 'Hide' + } + } + }).then(response => { + log.info(response.data); + window.location.reload(); + }).catch(error => { + log.error(error.data); + }); + }); + }, + methods: { + // Adjust the summary background position and size on page load and resize + moveSummaryBackground() { + const height = $('#summary').height() + 10; + const top = $('#summary').offset().top + 5; + $('#summaryBackground').height(height); + $('#summaryBackground').offset({ top, left: 0 }); + $('#summaryBackground').show(); + }, + movecheckboxControlsBackground() { + const height = $('#checkboxControls').height() + 10; + const top = $('#checkboxControls').offset().top - 3; + $('#checkboxControlsBackground').height(height); + $('#checkboxControlsBackground').offset({ top, left: 0 }); + $('#checkboxControlsBackground').show(); + }, + setQuality(quality, seriesSlug, episodes) { + const patchData = {}; + episodes.forEach(episode => { + patchData[episode] = { quality: parseInt(quality, 10) }; + }); + + api.patch('series/' + seriesSlug + '/episodes', patchData).then(response => { + log.info(response.data); + window.location.reload(); + }).catch(error => { + log.error(error.data); + }); + }, + setEpisodeSceneNumbering(forSeason, forEpisode, sceneSeason, sceneEpisode) { + const indexerName = $('#indexer-name').val(); + const seriesId = $('#series-id').val(); + + if (sceneSeason === '') { + sceneSeason = null; + } + if (sceneEpisode === '') { + sceneEpisode = null; + } + + $.getJSON('home/setSceneNumbering', { + indexername: indexerName, + seriesid: seriesId, + forSeason, + forEpisode, + sceneSeason, + sceneEpisode + }, data => { + // Set the values we get back + if (data.sceneSeason === null || data.sceneEpisode === null) { + $('#sceneSeasonXEpisode_' + seriesId + '_' + forSeason + '_' + forEpisode).val(''); + } else { + $('#sceneSeasonXEpisode_' + seriesId + '_' + forSeason + '_' + forEpisode).val(data.sceneSeason + 'x' + data.sceneEpisode); + } + if (!data.success) { + if (data.errorMessage) { + alert(data.errorMessage); // eslint-disable-line no-alert + } else { + alert('Update failed.'); // eslint-disable-line no-alert + } + } + }); + }, + setAbsoluteSceneNumbering(forAbsolute, sceneAbsolute) { + const indexerName = $('#indexer-name').val(); + const seriesId = $('#series-id').val(); + + if (sceneAbsolute === '') { + sceneAbsolute = null; + } + + $.getJSON('home/setSceneNumbering', { + indexername: indexerName, + seriesid: seriesId, + forAbsolute, + sceneAbsolute + }, data => { + // Set the values we get back + if (data.sceneAbsolute === null) { + $('#sceneAbsolute_' + seriesId + '_' + forAbsolute).val(''); + } else { + $('#sceneAbsolute_' + seriesId + '_' + forAbsolute).val(data.sceneAbsolute); + } + + if (!data.success) { + if (data.errorMessage) { + alert(data.errorMessage); // eslint-disable-line no-alert + } else { + alert('Update failed.'); // eslint-disable-line no-alert + } + } + }); + }, + setInputValidInvalid(valid, el) { + if (valid) { + $(el).css({ + 'background-color': '#90EE90', // Green + 'color': '#FFF', // eslint-disable-line quote-props + 'font-weight': 'bold' + }); + return true; + } + $(el).css({ + 'background-color': '#FF0000', // Red + 'color': '#FFF!important', // eslint-disable-line quote-props + 'font-weight': 'bold' + }); + return false; + }, + // Set the season exception based on using the get_xem_numbering_for_show() for animes if available in data.xemNumbering, + // or else try to map using just the data.season_exceptions. + setSeasonSceneException(data) { + $.each(data.seasonExceptions, (season, nameExceptions) => { + let foundInXem = false; + // Check if it is a season name exception, we don't handle the show name exceptions here + if (season >= 0) { + // Loop through the xem mapping, and check if there is a xem_season, that needs to show the season name exception + $.each(data.xemNumbering, (indexerSeason, xemSeason) => { + if (xemSeason === parseInt(season, 10)) { + foundInXem = true; + $('', { + id: 'xem-exception-season-' + xemSeason, + alt: '[xem]', + height: '16', + width: '16', + src: 'images/xem.png', + title: nameExceptions.join(', ') + }).appendTo('[data-season=' + indexerSeason + ']'); + } + }); + + // This is not a xem season exception, let's set the exceptions as a medusa exception + if (!foundInXem) { + $('', { + id: 'xem-exception-season-' + season, + alt: '[medusa]', + height: '16', + width: '16', + src: 'images/ico/favicon-16.png', + title: nameExceptions.join(', ') + }).appendTo('[data-season=' + season + ']'); + } + } + }); + }, + showHideRows(whichClass) { + const status = $('#checkboxControls > input, #' + whichClass).prop('checked'); + $('tr.' + whichClass).each((index, element) => { + if (status) { + $(element).show(); + } else { + $(element).hide(); + } + }); + + // Hide season headers with no episodes under them + $('tr.seasonheader').each((index, element) => { + let numRows = 0; + const seasonNo = $(element).attr('id'); + $('tr.' + seasonNo + ' :visible').each(() => { + numRows++; + }); + if (numRows === 0) { + $(element).hide(); + $('#' + seasonNo + '-cols').hide(); + } else { + $(element).show(); + $('#' + seasonNo + '-cols').show(); + } + }); + } } }); }; diff --git a/themes/dark/templates/layouts/main.mako b/themes/dark/templates/layouts/main.mako index d14510ad2e..b346b7e3fb 100644 --- a/themes/dark/templates/layouts/main.mako +++ b/themes/dark/templates/layouts/main.mako @@ -100,7 +100,6 @@ - diff --git a/themes/light/assets/js/home/display-show.js b/themes/light/assets/js/home/display-show.js deleted file mode 100644 index bef3a32e57..0000000000 --- a/themes/light/assets/js/home/display-show.js +++ /dev/null @@ -1,441 +0,0 @@ -MEDUSA.home.displayShow = function() { // eslint-disable-line max-lines - $('.imdbPlot').on('click', function() { - $(this).prev('span').toggle(); - if ($(this).html() === '..show less') { - $(this).html('..show more'); - } else { - $(this).html('..show less'); - } - moveSummaryBackground(); - movecheckboxControlsBackground(); - }); - - // Adjust the summary background position and size on page load and resize - function moveSummaryBackground() { - const height = $('#summary').height() + 10; - const top = $('#summary').offset().top + 5; - $('#summaryBackground').height(height); - $('#summaryBackground').offset({ top, left: 0 }); - $('#summaryBackground').show(); - } - - function movecheckboxControlsBackground() { - const height = $('#checkboxControls').height() + 10; - const top = $('#checkboxControls').offset().top - 3; - $('#checkboxControlsBackground').height(height); - $('#checkboxControlsBackground').offset({ top, left: 0 }); - $('#checkboxControlsBackground').show(); - } - - $(window).resize(() => { - moveSummaryBackground(); - movecheckboxControlsBackground(); - }); - - $(() => { - moveSummaryBackground(); - movecheckboxControlsBackground(); - }); - - $.ajaxEpSearch({ - colorRow: true - }); - - startAjaxEpisodeSubtitles(); // eslint-disable-line no-undef - $.ajaxEpSubtitlesSearch(); - $.ajaxEpRedownloadSubtitle(); - - const setQuality = (quality, seriesSlug, episodes) => { - const patchData = {}; - episodes.forEach(episode => { - patchData[episode] = { quality: parseInt(quality, 10) }; - }); - - api.patch('series/' + seriesSlug + '/episodes', patchData).then(response => { - log.info(response.data); - window.location.reload(); - }).catch(error => { - log.error(error.data); - }); - }; - - $('#seasonJump').on('change', function() { - const id = $('#seasonJump option:selected').val(); - if (id && id !== 'jump') { - const season = $('#seasonJump option:selected').data('season'); - $('html,body').animate({ scrollTop: $('[name="' + id.substring(1) + '"]').offset().top - 100 }, 'slow'); - $('#collapseSeason-' + season).collapse('show'); - location.hash = id; - } - $(this).val('jump'); - }); - - $('#changeStatus').on('click', () => { - const epArr = []; - const status = $('#statusSelect').val(); - const quality = $('#qualitySelect').val(); - const seriesSlug = $('#series-slug').val(); - - $('.epCheck').each(function() { - if (this.checked === true) { - epArr.push($(this).attr('id')); - } - }); - - if (epArr.length === 0) { - return false; - } - - if (quality) { - setQuality(quality, seriesSlug, epArr); - } - - if (status) { - window.location.href = $('base').attr('href') + 'home/setStatus?' + - 'indexername=' + $('#indexer-name').attr('value') + - '&seriesid=' + $('#series-id').attr('value') + - '&eps=' + epArr.join('|') + - '&status=' + status; - } - }); - - $('.seasonCheck').on('click', function() { - const seasCheck = this; - const seasNo = $(seasCheck).attr('id'); - - $('#collapseSeason-' + seasNo).collapse('show'); - const seasonIdentifier = 's' + seasNo; - $('.epCheck:visible').each(function() { - const epParts = $(this).attr('id').split('e'); - if (epParts[0] === seasonIdentifier) { - this.checked = seasCheck.checked; - } - }); - }); - - let lastCheck = null; - $('.epCheck').on('click', function(event) { - if (!lastCheck || !event.shiftKey) { - lastCheck = this; - return; - } - - const check = this; - let found = 0; - - $('.epCheck').each(function() { - if (found === 1) { - this.checked = lastCheck.checked; - } - - if (found === 2) { - return false; - } - - if (this === check || this === lastCheck) { - found++; - } - }); - }); - - // Selects all visible episode checkboxes. - $('.seriesCheck').on('click', () => { - $('.epCheck:visible').each(function() { - this.checked = true; - }); - $('.seasonCheck:visible').each(function() { - this.checked = true; - }); - }); - - // Clears all visible episode checkboxes and the season selectors - $('.clearAll').on('click', () => { - $('.epCheck:visible').each(function() { - this.checked = false; - }); - $('.seasonCheck:visible').each(function() { - this.checked = false; - }); - }); - - // Show/hide different types of rows when the checkboxes are changed - $('#checkboxControls input').on('change', function() { - const whichClass = $(this).attr('id'); - $(this).showHideRows(whichClass); - }); - - // Initially show/hide all the rows according to the checkboxes - $('#checkboxControls input').each(function() { - const status = $(this).prop('checked'); - $('tr.' + $(this).attr('id')).each(function() { - if (status) { - $(this).show(); - } else { - $(this).hide(); - } - }); - }); - - $.fn.showHideRows = function(whichClass) { - const status = $('#checkboxControls > input, #' + whichClass).prop('checked'); - $('tr.' + whichClass).each(function() { - if (status) { - $(this).show(); - } else { - $(this).hide(); - } - }); - - // Hide season headers with no episodes under them - $('tr.seasonheader').each(function() { - let numRows = 0; - const seasonNo = $(this).attr('id'); - $('tr.' + seasonNo + ' :visible').each(() => { - numRows++; - }); - if (numRows === 0) { - $(this).hide(); - $('#' + seasonNo + '-cols').hide(); - } else { - $(this).show(); - $('#' + seasonNo + '-cols').show(); - } - }); - }; - - function setEpisodeSceneNumbering(forSeason, forEpisode, sceneSeason, sceneEpisode) { - const indexerName = $('#indexer-name').val(); - const seriesId = $('#series-id').val(); - - if (sceneSeason === '') { - sceneSeason = null; - } - if (sceneEpisode === '') { - sceneEpisode = null; - } - - $.getJSON('home/setSceneNumbering', { - indexername: indexerName, - seriesid: seriesId, - forSeason, - forEpisode, - sceneSeason, - sceneEpisode - }, data => { - // Set the values we get back - if (data.sceneSeason === null || data.sceneEpisode === null) { - $('#sceneSeasonXEpisode_' + seriesId + '_' + forSeason + '_' + forEpisode).val(''); - } else { - $('#sceneSeasonXEpisode_' + seriesId + '_' + forSeason + '_' + forEpisode).val(data.sceneSeason + 'x' + data.sceneEpisode); - } - if (!data.success) { - if (data.errorMessage) { - alert(data.errorMessage); // eslint-disable-line no-alert - } else { - alert('Update failed.'); // eslint-disable-line no-alert - } - } - }); - } - - function setAbsoluteSceneNumbering(forAbsolute, sceneAbsolute) { - const indexerName = $('#indexer-name').val(); - const seriesId = $('#series-id').val(); - - if (sceneAbsolute === '') { - sceneAbsolute = null; - } - - $.getJSON('home/setSceneNumbering', { - indexername: indexerName, - seriesid: seriesId, - forAbsolute, - sceneAbsolute - }, data => { - // Set the values we get back - if (data.sceneAbsolute === null) { - $('#sceneAbsolute_' + seriesId + '_' + forAbsolute).val(''); - } else { - $('#sceneAbsolute_' + seriesId + '_' + forAbsolute).val(data.sceneAbsolute); - } - - if (!data.success) { - if (data.errorMessage) { - alert(data.errorMessage); // eslint-disable-line no-alert - } else { - alert('Update failed.'); // eslint-disable-line no-alert - } - } - }); - } - - function setInputValidInvalid(valid, el) { - if (valid) { - $(el).css({ - 'background-color': '#90EE90', // Green - 'color': '#FFF', // eslint-disable-line quote-props - 'font-weight': 'bold' - }); - return true; - } - $(el).css({ - 'background-color': '#FF0000', // Red - 'color': '#FFF!important', // eslint-disable-line quote-props - 'font-weight': 'bold' - }); - return false; - } - - $('.sceneSeasonXEpisode').on('change', function() { - // Strip non-numeric characters - const value = $(this).val(); - $(this).val(value.replace(/[^0-9xX]*/g, '')); - const forSeason = $(this).attr('data-for-season'); - const forEpisode = $(this).attr('data-for-episode'); - - // If empty reset the field - if (value === '') { - setEpisodeSceneNumbering(forSeason, forEpisode, null, null); - return; - } - - const m = $(this).val().match(/^(\d+)x(\d+)$/i); - const onlyEpisode = $(this).val().match(/^(\d+)$/i); - let sceneSeason = null; - let sceneEpisode = null; - let isValid = false; - if (m) { - sceneSeason = m[1]; - sceneEpisode = m[2]; - isValid = setInputValidInvalid(true, $(this)); - } else if (onlyEpisode) { - // For example when '5' is filled in instead of '1x5', asume it's the first season - sceneSeason = forSeason; - sceneEpisode = onlyEpisode[1]; - isValid = setInputValidInvalid(true, $(this)); - } else { - isValid = setInputValidInvalid(false, $(this)); - } - - if (isValid) { - setEpisodeSceneNumbering(forSeason, forEpisode, sceneSeason, sceneEpisode); - } - }); - - $('.sceneAbsolute').on('change', function() { - // Strip non-numeric characters - $(this).val($(this).val().replace(/[^0-9xX]*/g, '')); - const forAbsolute = $(this).attr('data-for-absolute'); - - const m = $(this).val().match(/^(\d{1,3})$/i); - let sceneAbsolute = null; - if (m) { - sceneAbsolute = m[1]; - } - setAbsoluteSceneNumbering(forAbsolute, sceneAbsolute); - }); - - $.fn.generateStars = function() { - return this.each((i, e) => { - $(e).html($('').width($(e).text() * 12)); - }); - }; - - $('.imdbstars').generateStars(); - - $('#showTable, #animeTable').tablesorter({ - widgets: ['saveSort', 'stickyHeaders', 'columnSelector'], - widgetOptions: { - columnSelector_saveColumns: true, // eslint-disable-line camelcase - columnSelector_layout: '', // eslint-disable-line camelcase - columnSelector_mediaquery: false, // eslint-disable-line camelcase - columnSelector_cssChecked: 'checked' // eslint-disable-line camelcase - } - }); - - $('#popover').popover({ - placement: 'bottom', - html: true, // Required if content has HTML - content: '
' - }).on('shown.bs.popover', () => { // Bootstrap popover event triggered when the popover opens - $.tablesorter.columnSelector.attachTo($('#showTable, #animeTable'), '#popover-target'); - }); - - // Moved and rewritten this from displayShow. This changes the button when clicked for collapsing/expanding the - // Season to Show Episodes or Hide Episodes. - $(() => { - $('.collapse.toggle').on('hide.bs.collapse', function() { - const reg = /collapseSeason-(\d+)/g; - const result = reg.exec(this.id); - $('#showseason-' + result[1]).text('Show Episodes'); - $('#season-' + result[1] + '-cols').addClass('shadow'); - }); - $('.collapse.toggle').on('show.bs.collapse', function() { - const reg = /collapseSeason-(\d+)/g; - const result = reg.exec(this.id); - $('#showseason-' + result[1]).text('Hide Episodes'); - $('#season-' + result[1] + '-cols').removeClass('shadow'); - }); - }); - - // Set the season exception based on using the get_xem_numbering_for_show() for animes if available in data.xemNumbering, - // or else try to map using just the data.season_exceptions. - function setSeasonSceneException(data) { - $.each(data.seasonExceptions, (season, nameExceptions) => { - let foundInXem = false; - // Check if it is a season name exception, we don't handle the show name exceptions here - if (season >= 0) { - // Loop through the xem mapping, and check if there is a xem_season, that needs to show the season name exception - $.each(data.xemNumbering, (indexerSeason, xemSeason) => { - if (xemSeason === parseInt(season, 10)) { - foundInXem = true; - $('', { - id: 'xem-exception-season-' + xemSeason, - alt: '[xem]', - height: '16', - width: '16', - src: 'images/xem.png', - title: nameExceptions.join(', ') - }).appendTo('[data-season=' + indexerSeason + ']'); - } - }); - - // This is not a xem season exception, let's set the exceptions as a medusa exception - if (!foundInXem) { - $('', { - id: 'xem-exception-season-' + season, - alt: '[medusa]', - height: '16', - width: '16', - src: 'images/ico/favicon-16.png', - title: nameExceptions.join(', ') - }).appendTo('[data-season=' + season + ']'); - } - } - }); - } - - // @TODO: OMG: This is just a basic json, in future it should be based on the CRUD route. - // Get the season exceptions and the xem season mappings. - $.getJSON('home/getSeasonSceneExceptions', { - indexername: $('#indexer-name').val(), - seriesid: $('#series-id').val() // eslint-disable-line camelcase - }, data => { - setSeasonSceneException(data); - }); - - $('.display-specials a').on('click', function() { - api.patch('config/main', { - layout: { - show: { - specials: $(this).text() !== 'Hide' - } - } - }).then(response => { - log.info(response.data); - window.location.reload(); - }).catch(error => { - log.error(error.data); - }); - }); -}; diff --git a/themes/light/assets/js/home/display-show.js.map b/themes/light/assets/js/home/display-show.js.map deleted file mode 100644 index 839906e221..0000000000 --- a/themes/light/assets/js/home/display-show.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"names":[],"mappings":"","sources":["js/home/display-show.js"],"sourcesContent":["(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c=\"function\"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error(\"Cannot find module '\"+i+\"'\");throw a.code=\"MODULE_NOT_FOUND\",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u=\"function\"==typeof require&&require,i=0;i input, #' + whichClass).prop('checked');\n $('tr.' + whichClass).each(function () {\n if (status) {\n $(this).show();\n } else {\n $(this).hide();\n }\n });\n\n // Hide season headers with no episodes under them\n $('tr.seasonheader').each(function () {\n var numRows = 0;\n var seasonNo = $(this).attr('id');\n $('tr.' + seasonNo + ' :visible').each(function () {\n numRows++;\n });\n if (numRows === 0) {\n $(this).hide();\n $('#' + seasonNo + '-cols').hide();\n } else {\n $(this).show();\n $('#' + seasonNo + '-cols').show();\n }\n });\n };\n\n function setEpisodeSceneNumbering(forSeason, forEpisode, sceneSeason, sceneEpisode) {\n var indexerName = $('#indexer-name').val();\n var seriesId = $('#series-id').val();\n\n if (sceneSeason === '') {\n sceneSeason = null;\n }\n if (sceneEpisode === '') {\n sceneEpisode = null;\n }\n\n $.getJSON('home/setSceneNumbering', {\n indexername: indexerName,\n seriesid: seriesId,\n forSeason: forSeason,\n forEpisode: forEpisode,\n sceneSeason: sceneSeason,\n sceneEpisode: sceneEpisode\n }, function (data) {\n // Set the values we get back\n if (data.sceneSeason === null || data.sceneEpisode === null) {\n $('#sceneSeasonXEpisode_' + seriesId + '_' + forSeason + '_' + forEpisode).val('');\n } else {\n $('#sceneSeasonXEpisode_' + seriesId + '_' + forSeason + '_' + forEpisode).val(data.sceneSeason + 'x' + data.sceneEpisode);\n }\n if (!data.success) {\n if (data.errorMessage) {\n alert(data.errorMessage); // eslint-disable-line no-alert\n } else {\n alert('Update failed.'); // eslint-disable-line no-alert\n }\n }\n });\n }\n\n function setAbsoluteSceneNumbering(forAbsolute, sceneAbsolute) {\n var indexerName = $('#indexer-name').val();\n var seriesId = $('#series-id').val();\n\n if (sceneAbsolute === '') {\n sceneAbsolute = null;\n }\n\n $.getJSON('home/setSceneNumbering', {\n indexername: indexerName,\n seriesid: seriesId,\n forAbsolute: forAbsolute,\n sceneAbsolute: sceneAbsolute\n }, function (data) {\n // Set the values we get back\n if (data.sceneAbsolute === null) {\n $('#sceneAbsolute_' + seriesId + '_' + forAbsolute).val('');\n } else {\n $('#sceneAbsolute_' + seriesId + '_' + forAbsolute).val(data.sceneAbsolute);\n }\n\n if (!data.success) {\n if (data.errorMessage) {\n alert(data.errorMessage); // eslint-disable-line no-alert\n } else {\n alert('Update failed.'); // eslint-disable-line no-alert\n }\n }\n });\n }\n\n function setInputValidInvalid(valid, el) {\n if (valid) {\n $(el).css({\n 'background-color': '#90EE90', // Green\n 'color': '#FFF', // eslint-disable-line quote-props\n 'font-weight': 'bold'\n });\n return true;\n }\n $(el).css({\n 'background-color': '#FF0000', // Red\n 'color': '#FFF!important', // eslint-disable-line quote-props\n 'font-weight': 'bold'\n });\n return false;\n }\n\n $('.sceneSeasonXEpisode').on('change', function () {\n // Strip non-numeric characters\n var value = $(this).val();\n $(this).val(value.replace(/[^0-9xX]*/g, ''));\n var forSeason = $(this).attr('data-for-season');\n var forEpisode = $(this).attr('data-for-episode');\n\n // If empty reset the field\n if (value === '') {\n setEpisodeSceneNumbering(forSeason, forEpisode, null, null);\n return;\n }\n\n var m = $(this).val().match(/^(\\d+)x(\\d+)$/i);\n var onlyEpisode = $(this).val().match(/^(\\d+)$/i);\n var sceneSeason = null;\n var sceneEpisode = null;\n var isValid = false;\n if (m) {\n sceneSeason = m[1];\n sceneEpisode = m[2];\n isValid = setInputValidInvalid(true, $(this));\n } else if (onlyEpisode) {\n // For example when '5' is filled in instead of '1x5', asume it's the first season\n sceneSeason = forSeason;\n sceneEpisode = onlyEpisode[1];\n isValid = setInputValidInvalid(true, $(this));\n } else {\n isValid = setInputValidInvalid(false, $(this));\n }\n\n if (isValid) {\n setEpisodeSceneNumbering(forSeason, forEpisode, sceneSeason, sceneEpisode);\n }\n });\n\n $('.sceneAbsolute').on('change', function () {\n // Strip non-numeric characters\n $(this).val($(this).val().replace(/[^0-9xX]*/g, ''));\n var forAbsolute = $(this).attr('data-for-absolute');\n\n var m = $(this).val().match(/^(\\d{1,3})$/i);\n var sceneAbsolute = null;\n if (m) {\n sceneAbsolute = m[1];\n }\n setAbsoluteSceneNumbering(forAbsolute, sceneAbsolute);\n });\n\n $.fn.generateStars = function () {\n return this.each(function (i, e) {\n $(e).html($('').width($(e).text() * 12));\n });\n };\n\n $('.imdbstars').generateStars();\n\n $('#showTable, #animeTable').tablesorter({\n widgets: ['saveSort', 'stickyHeaders', 'columnSelector'],\n widgetOptions: {\n columnSelector_saveColumns: true, // eslint-disable-line camelcase\n columnSelector_layout: '', // eslint-disable-line camelcase\n columnSelector_mediaquery: false, // eslint-disable-line camelcase\n columnSelector_cssChecked: 'checked' // eslint-disable-line camelcase\n }\n });\n\n $('#popover').popover({\n placement: 'bottom',\n html: true, // Required if content has HTML\n content: '
'\n }).on('shown.bs.popover', function () {\n // Bootstrap popover event triggered when the popover opens\n $.tablesorter.columnSelector.attachTo($('#showTable, #animeTable'), '#popover-target');\n });\n\n // Moved and rewritten this from displayShow. This changes the button when clicked for collapsing/expanding the\n // Season to Show Episodes or Hide Episodes.\n $(function () {\n $('.collapse.toggle').on('hide.bs.collapse', function () {\n var reg = /collapseSeason-(\\d+)/g;\n var result = reg.exec(this.id);\n $('#showseason-' + result[1]).text('Show Episodes');\n $('#season-' + result[1] + '-cols').addClass('shadow');\n });\n $('.collapse.toggle').on('show.bs.collapse', function () {\n var reg = /collapseSeason-(\\d+)/g;\n var result = reg.exec(this.id);\n $('#showseason-' + result[1]).text('Hide Episodes');\n $('#season-' + result[1] + '-cols').removeClass('shadow');\n });\n });\n\n // Set the season exception based on using the get_xem_numbering_for_show() for animes if available in data.xemNumbering,\n // or else try to map using just the data.season_exceptions.\n function setSeasonSceneException(data) {\n $.each(data.seasonExceptions, function (season, nameExceptions) {\n var foundInXem = false;\n // Check if it is a season name exception, we don't handle the show name exceptions here\n if (season >= 0) {\n // Loop through the xem mapping, and check if there is a xem_season, that needs to show the season name exception\n $.each(data.xemNumbering, function (indexerSeason, xemSeason) {\n if (xemSeason === parseInt(season, 10)) {\n foundInXem = true;\n $('', {\n id: 'xem-exception-season-' + xemSeason,\n alt: '[xem]',\n height: '16',\n width: '16',\n src: 'images/xem.png',\n title: nameExceptions.join(', ')\n }).appendTo('[data-season=' + indexerSeason + ']');\n }\n });\n\n // This is not a xem season exception, let's set the exceptions as a medusa exception\n if (!foundInXem) {\n $('', {\n id: 'xem-exception-season-' + season,\n alt: '[medusa]',\n height: '16',\n width: '16',\n src: 'images/ico/favicon-16.png',\n title: nameExceptions.join(', ')\n }).appendTo('[data-season=' + season + ']');\n }\n }\n });\n }\n\n // @TODO: OMG: This is just a basic json, in future it should be based on the CRUD route.\n // Get the season exceptions and the xem season mappings.\n $.getJSON('home/getSeasonSceneExceptions', {\n indexername: $('#indexer-name').val(),\n seriesid: $('#series-id').val() // eslint-disable-line camelcase\n }, function (data) {\n setSeasonSceneException(data);\n });\n\n $('.display-specials a').on('click', function () {\n api.patch('config/main', {\n layout: {\n show: {\n specials: $(this).text() !== 'Hide'\n }\n }\n }).then(function (response) {\n log.info(response.data);\n window.location.reload();\n }).catch(function (error) {\n log.error(error.data);\n });\n });\n};\n\n},{}]},{},[1]);\n"],"file":"display-show.js"} \ No newline at end of file diff --git a/themes/light/templates/displayShow.mako b/themes/light/templates/displayShow.mako index 65eb52ef41..964bb6282b 100644 --- a/themes/light/templates/displayShow.mako +++ b/themes/light/templates/displayShow.mako @@ -27,12 +27,451 @@ const startVue = () => { $store.dispatch('getShows'); // Used by show-selector component }, mounted() { - // Adjust the summary background position and size on page load and resize + const { + moveSummaryBackground, + movecheckboxControlsBackground, + setQuality, + setEpisodeSceneNumbering, + setAbsoluteSceneNumbering, + setInputValidInvalid, + setSeasonSceneException, + showHideRows, + } = this; + + $(window).resize(() => { + moveSummaryBackground(); + movecheckboxControlsBackground(); + }); + this.$once('loaded', () => { this.$nextTick(() => { + // Adjust the summary background position and size window.dispatchEvent(new Event('resize')); + + $.ajaxEpSearch({ + colorRow: true + }); + + startAjaxEpisodeSubtitles(); // eslint-disable-line no-undef + $.ajaxEpSubtitlesSearch(); + $.ajaxEpRedownloadSubtitle(); + }); + }); + + $(document.body).on('click', '.imdbPlot', event => { + const $target = $(event.currentTarget); + $target.prev('span').toggle(); + if ($target.html() === '..show less') { + $target.html('..show more'); + } else { + $target.html('..show less'); + } + moveSummaryBackground(); + movecheckboxControlsBackground(); + }); + + $(document.body).on('change', '#seasonJump', (event) => { + const id = $('#seasonJump option:selected').val(); + if (id && id !== 'jump') { + const season = $('#seasonJump option:selected').data('season'); + $('html,body').animate({ scrollTop: $('[name="' + id.substring(1) + '"]').offset().top - 100 }, 'slow'); + $('#collapseSeason-' + season).collapse('show'); + location.hash = id; + } + $(event.currentTarget).val('jump'); + }); + + $(document.body).on('click', '#changeStatus', () => { + const epArr = []; + const status = $('#statusSelect').val(); + const quality = $('#qualitySelect').val(); + const seriesSlug = $('#series-slug').val(); + + $('.epCheck').each((index, element) => { + if (element.checked === true) { + epArr.push($(element).attr('id')); + } + }); + + if (epArr.length === 0) { + return false; + } + + if (quality) { + setQuality(quality, seriesSlug, epArr); + } + + if (status) { + window.location.href = $('base').attr('href') + 'home/setStatus?' + + 'indexername=' + $('#indexer-name').attr('value') + + '&seriesid=' + $('#series-id').attr('value') + + '&eps=' + epArr.join('|') + + '&status=' + status; + } + }); + + $(document.body).on('click', '.seasonCheck', event => { + const seasCheck = event.currentTarget; + const seasNo = $(seasCheck).attr('id'); + + $('#collapseSeason-' + seasNo).collapse('show'); + const seasonIdentifier = 's' + seasNo; + $('.epCheck:visible').each((index, element) => { + const epParts = $(element).attr('id').split('e'); + if (epParts[0] === seasonIdentifier) { + element.checked = seasCheck.checked; + } + }); + }); + + let lastCheck = null; + $(document.body).on('click', '.epCheck', event => { + const target = event.currentTarget; + if (!lastCheck || !event.shiftKey) { + lastCheck = target; + return; + } + + const check = target; + let found = 0; + + $('.epCheck').each((index, element) => { + if (found === 1) { + element.checked = lastCheck.checked; + } + + if (found === 2) { + return false; + } + + if (element === check || element === lastCheck) { + found++; + } + }); + }); + + // Selects all visible episode checkboxes. + $(document.body).on('click', '.seriesCheck', () => { + $('.epCheck:visible').each((index, element) => { + element.checked = true; + }); + $('.seasonCheck:visible').each((index, element) => { + element.checked = true; + }); + }); + + // Clears all visible episode checkboxes and the season selectors + $(document.body).on('click', '.clearAll', () => { + $('.epCheck:visible').each((index, element) => { + element.checked = false; + }); + $('.seasonCheck:visible').each((index, element) => { + element.checked = false; + }); + }); + + // Show/hide different types of rows when the checkboxes are changed + $(document.body).on('change', '#checkboxControls input', event => { + const whichClass = $(event.currentTarget).attr('id'); + showHideRows(whichClass); + }); + + // Initially show/hide all the rows according to the checkboxes + $('#checkboxControls input').each((index, element) => { + const status = $(element).prop('checked'); + $('tr.' + $(element).attr('id')).each((index, tableRow) => { + if (status) { + $(tableRow).show(); + } else { + $(tableRow).hide(); + } }); }); + + $(document.body).on('change', '.sceneSeasonXEpisode', event => { + const target = event.currentTarget; + // Strip non-numeric characters + const value = $(target).val(); + $(target).val(value.replace(/[^0-9xX]*/g, '')); + const forSeason = $(target).attr('data-for-season'); + const forEpisode = $(target).attr('data-for-episode'); + + // If empty reset the field + if (value === '') { + setEpisodeSceneNumbering(forSeason, forEpisode, null, null); + return; + } + + const m = $(target).val().match(/^(\d+)x(\d+)$/i); + const onlyEpisode = $(target).val().match(/^(\d+)$/i); + let sceneSeason = null; + let sceneEpisode = null; + let isValid = false; + if (m) { + sceneSeason = m[1]; + sceneEpisode = m[2]; + isValid = setInputValidInvalid(true, $(target)); + } else if (onlyEpisode) { + // For example when '5' is filled in instead of '1x5', asume it's the first season + sceneSeason = forSeason; + sceneEpisode = onlyEpisode[1]; + isValid = setInputValidInvalid(true, $(target)); + } else { + isValid = setInputValidInvalid(false, $(target)); + } + + if (isValid) { + setEpisodeSceneNumbering(forSeason, forEpisode, sceneSeason, sceneEpisode); + } + }); + + $(document.body).on('change', '.sceneAbsolute', event => { + const target = event.currentTarget; + // Strip non-numeric characters + $(target).val($(target).val().replace(/[^0-9xX]*/g, '')); + const forAbsolute = $(target).attr('data-for-absolute'); + + const m = $(target).val().match(/^(\d{1,3})$/i); + let sceneAbsolute = null; + if (m) { + sceneAbsolute = m[1]; + } + setAbsoluteSceneNumbering(forAbsolute, sceneAbsolute); + }); + + $('#showTable, #animeTable').tablesorter({ + widgets: ['saveSort', 'stickyHeaders', 'columnSelector'], + widgetOptions: { + columnSelector_saveColumns: true, // eslint-disable-line camelcase + columnSelector_layout: '', // eslint-disable-line camelcase + columnSelector_mediaquery: false, // eslint-disable-line camelcase + columnSelector_cssChecked: 'checked' // eslint-disable-line camelcase + } + }); + + $('#popover').popover({ + placement: 'bottom', + html: true, // Required if content has HTML + content: '
' + }).on('shown.bs.popover', () => { // Bootstrap popover event triggered when the popover opens + $.tablesorter.columnSelector.attachTo($('#showTable, #animeTable'), '#popover-target'); + }); + + // Moved and rewritten this from displayShow. This changes the button when clicked for collapsing/expanding the + // Season to Show Episodes or Hide Episodes. + $('.collapse.toggle').on('hide.bs.collapse', function() { + const reg = /collapseSeason-(\d+)/g; + const result = reg.exec(this.id); + $('#showseason-' + result[1]).text('Show Episodes'); + $('#season-' + result[1] + '-cols').addClass('shadow'); + }); + $('.collapse.toggle').on('show.bs.collapse', function() { + const reg = /collapseSeason-(\d+)/g; + const result = reg.exec(this.id); + $('#showseason-' + result[1]).text('Hide Episodes'); + $('#season-' + result[1] + '-cols').removeClass('shadow'); + }); + + // Generate IMDB stars + $('.imdbstars').each((index, element) => { + $(element).html($('').width($(element).text() * 12)); + }); + + // @TODO: OMG: This is just a basic json, in future it should be based on the CRUD route. + // Get the season exceptions and the xem season mappings. + $.getJSON('home/getSeasonSceneExceptions', { + indexername: $('#indexer-name').val(), + seriesid: $('#series-id').val() // eslint-disable-line camelcase + }, data => { + setSeasonSceneException(data); + }); + + $(document.body).on('click', '.display-specials a', event => { + api.patch('config/main', { + layout: { + show: { + specials: $(event.currentTarget).text() !== 'Hide' + } + } + }).then(response => { + log.info(response.data); + window.location.reload(); + }).catch(error => { + log.error(error.data); + }); + }); + }, + methods: { + // Adjust the summary background position and size on page load and resize + moveSummaryBackground() { + const height = $('#summary').height() + 10; + const top = $('#summary').offset().top + 5; + $('#summaryBackground').height(height); + $('#summaryBackground').offset({ top, left: 0 }); + $('#summaryBackground').show(); + }, + movecheckboxControlsBackground() { + const height = $('#checkboxControls').height() + 10; + const top = $('#checkboxControls').offset().top - 3; + $('#checkboxControlsBackground').height(height); + $('#checkboxControlsBackground').offset({ top, left: 0 }); + $('#checkboxControlsBackground').show(); + }, + setQuality(quality, seriesSlug, episodes) { + const patchData = {}; + episodes.forEach(episode => { + patchData[episode] = { quality: parseInt(quality, 10) }; + }); + + api.patch('series/' + seriesSlug + '/episodes', patchData).then(response => { + log.info(response.data); + window.location.reload(); + }).catch(error => { + log.error(error.data); + }); + }, + setEpisodeSceneNumbering(forSeason, forEpisode, sceneSeason, sceneEpisode) { + const indexerName = $('#indexer-name').val(); + const seriesId = $('#series-id').val(); + + if (sceneSeason === '') { + sceneSeason = null; + } + if (sceneEpisode === '') { + sceneEpisode = null; + } + + $.getJSON('home/setSceneNumbering', { + indexername: indexerName, + seriesid: seriesId, + forSeason, + forEpisode, + sceneSeason, + sceneEpisode + }, data => { + // Set the values we get back + if (data.sceneSeason === null || data.sceneEpisode === null) { + $('#sceneSeasonXEpisode_' + seriesId + '_' + forSeason + '_' + forEpisode).val(''); + } else { + $('#sceneSeasonXEpisode_' + seriesId + '_' + forSeason + '_' + forEpisode).val(data.sceneSeason + 'x' + data.sceneEpisode); + } + if (!data.success) { + if (data.errorMessage) { + alert(data.errorMessage); // eslint-disable-line no-alert + } else { + alert('Update failed.'); // eslint-disable-line no-alert + } + } + }); + }, + setAbsoluteSceneNumbering(forAbsolute, sceneAbsolute) { + const indexerName = $('#indexer-name').val(); + const seriesId = $('#series-id').val(); + + if (sceneAbsolute === '') { + sceneAbsolute = null; + } + + $.getJSON('home/setSceneNumbering', { + indexername: indexerName, + seriesid: seriesId, + forAbsolute, + sceneAbsolute + }, data => { + // Set the values we get back + if (data.sceneAbsolute === null) { + $('#sceneAbsolute_' + seriesId + '_' + forAbsolute).val(''); + } else { + $('#sceneAbsolute_' + seriesId + '_' + forAbsolute).val(data.sceneAbsolute); + } + + if (!data.success) { + if (data.errorMessage) { + alert(data.errorMessage); // eslint-disable-line no-alert + } else { + alert('Update failed.'); // eslint-disable-line no-alert + } + } + }); + }, + setInputValidInvalid(valid, el) { + if (valid) { + $(el).css({ + 'background-color': '#90EE90', // Green + 'color': '#FFF', // eslint-disable-line quote-props + 'font-weight': 'bold' + }); + return true; + } + $(el).css({ + 'background-color': '#FF0000', // Red + 'color': '#FFF!important', // eslint-disable-line quote-props + 'font-weight': 'bold' + }); + return false; + }, + // Set the season exception based on using the get_xem_numbering_for_show() for animes if available in data.xemNumbering, + // or else try to map using just the data.season_exceptions. + setSeasonSceneException(data) { + $.each(data.seasonExceptions, (season, nameExceptions) => { + let foundInXem = false; + // Check if it is a season name exception, we don't handle the show name exceptions here + if (season >= 0) { + // Loop through the xem mapping, and check if there is a xem_season, that needs to show the season name exception + $.each(data.xemNumbering, (indexerSeason, xemSeason) => { + if (xemSeason === parseInt(season, 10)) { + foundInXem = true; + $('', { + id: 'xem-exception-season-' + xemSeason, + alt: '[xem]', + height: '16', + width: '16', + src: 'images/xem.png', + title: nameExceptions.join(', ') + }).appendTo('[data-season=' + indexerSeason + ']'); + } + }); + + // This is not a xem season exception, let's set the exceptions as a medusa exception + if (!foundInXem) { + $('', { + id: 'xem-exception-season-' + season, + alt: '[medusa]', + height: '16', + width: '16', + src: 'images/ico/favicon-16.png', + title: nameExceptions.join(', ') + }).appendTo('[data-season=' + season + ']'); + } + } + }); + }, + showHideRows(whichClass) { + const status = $('#checkboxControls > input, #' + whichClass).prop('checked'); + $('tr.' + whichClass).each((index, element) => { + if (status) { + $(element).show(); + } else { + $(element).hide(); + } + }); + + // Hide season headers with no episodes under them + $('tr.seasonheader').each((index, element) => { + let numRows = 0; + const seasonNo = $(element).attr('id'); + $('tr.' + seasonNo + ' :visible').each(() => { + numRows++; + }); + if (numRows === 0) { + $(element).hide(); + $('#' + seasonNo + '-cols').hide(); + } else { + $(element).show(); + $('#' + seasonNo + '-cols').show(); + } + }); + } } }); }; diff --git a/themes/light/templates/layouts/main.mako b/themes/light/templates/layouts/main.mako index d14510ad2e..b346b7e3fb 100644 --- a/themes/light/templates/layouts/main.mako +++ b/themes/light/templates/layouts/main.mako @@ -100,7 +100,6 @@ - From 02c572c8b4c8f8e58bbfe5e9c3970aaea1844735 Mon Sep 17 00:00:00 2001 From: sharkykh Date: Wed, 25 Jul 2018 09:38:23 +0300 Subject: [PATCH 3/4] Fix schedule forced search --- themes-default/slim/views/schedule.mako | 3 +-- themes/dark/templates/schedule.mako | 3 +-- themes/light/templates/schedule.mako | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/themes-default/slim/views/schedule.mako b/themes-default/slim/views/schedule.mako index 212cd4bfa1..9e876f80c8 100644 --- a/themes-default/slim/views/schedule.mako +++ b/themes-default/slim/views/schedule.mako @@ -33,8 +33,7 @@ const startVue = () => { const { $store, $route } = this; // $store.dispatch('getShows'); - const unwatch = this.$watch('layout', () => { - unwatch(); + this.$once('loaded', () => { const { config, layout } = this; if (layout === 'list') { const sortCodes = { diff --git a/themes/dark/templates/schedule.mako b/themes/dark/templates/schedule.mako index 212cd4bfa1..9e876f80c8 100644 --- a/themes/dark/templates/schedule.mako +++ b/themes/dark/templates/schedule.mako @@ -33,8 +33,7 @@ const startVue = () => { const { $store, $route } = this; // $store.dispatch('getShows'); - const unwatch = this.$watch('layout', () => { - unwatch(); + this.$once('loaded', () => { const { config, layout } = this; if (layout === 'list') { const sortCodes = { diff --git a/themes/light/templates/schedule.mako b/themes/light/templates/schedule.mako index 212cd4bfa1..9e876f80c8 100644 --- a/themes/light/templates/schedule.mako +++ b/themes/light/templates/schedule.mako @@ -33,8 +33,7 @@ const startVue = () => { const { $store, $route } = this; // $store.dispatch('getShows'); - const unwatch = this.$watch('layout', () => { - unwatch(); + this.$once('loaded', () => { const { config, layout } = this; if (layout === 'list') { const sortCodes = { From ece5a99b8aefb92b65d677ea77f7c95b4f9d1809 Mon Sep 17 00:00:00 2001 From: sharkykh Date: Wed, 25 Jul 2018 09:50:25 +0300 Subject: [PATCH 4/4] subtitleMissedPP subtitle search --- .../js/manage/subtitle-missed-post-process.js | 28 --------------- themes-default/slim/views/layouts/main.mako | 1 - .../slim/views/manage_subtitleMissedPP.mako | 34 +++++++++++++++++-- .../js/manage/subtitle-missed-post-process.js | 28 --------------- .../subtitle-missed-post-process.js.map | 1 - themes/dark/templates/layouts/main.mako | 1 - .../templates/manage_subtitleMissedPP.mako | 34 +++++++++++++++++-- .../js/manage/subtitle-missed-post-process.js | 28 --------------- .../subtitle-missed-post-process.js.map | 1 - themes/light/templates/layouts/main.mako | 1 - .../templates/manage_subtitleMissedPP.mako | 34 +++++++++++++++++-- 11 files changed, 96 insertions(+), 95 deletions(-) delete mode 100644 themes-default/slim/static/js/manage/subtitle-missed-post-process.js delete mode 100644 themes/dark/assets/js/manage/subtitle-missed-post-process.js delete mode 100644 themes/dark/assets/js/manage/subtitle-missed-post-process.js.map delete mode 100644 themes/light/assets/js/manage/subtitle-missed-post-process.js delete mode 100644 themes/light/assets/js/manage/subtitle-missed-post-process.js.map diff --git a/themes-default/slim/static/js/manage/subtitle-missed-post-process.js b/themes-default/slim/static/js/manage/subtitle-missed-post-process.js deleted file mode 100644 index a42df68363..0000000000 --- a/themes-default/slim/static/js/manage/subtitle-missed-post-process.js +++ /dev/null @@ -1,28 +0,0 @@ -MEDUSA.manage.subtitleMissedPP = function() { - startAjaxEpisodeSubtitles(); // eslint-disable-line no-undef - $.ajaxEpSubtitlesSearch(); - - $('#releasesPP:has(tbody tr)').tablesorter({ - sortList: [[3, 1], [0, 0]], - textExtraction: { - 0(node) { return $(node).find('a').text().toLowerCase(); }, // eslint-disable-line brace-style - 1(node) { return $(node).text().toLowerCase(); }, // eslint-disable-line brace-style - 2(node) { return $(node).find('span').text().toLowerCase(); }, // eslint-disable-line brace-style - 3(node) { return $(node).find('span').attr('datetime'); } // eslint-disable-line brace-style - }, - widgets: ['saveSort', 'filter'], - headers: { - 0: { sorter: 'show' }, - 1: { sorter: 'episode' }, - 2: { sorter: 'release' }, - 3: { sorter: 'realISODate' }, - 4: { sorter: false, filter: false } - }, - widgetOptions: { - filter_columnFilters: true, // eslint-disable-line camelcase - filter_hideFilters: true, // eslint-disable-line camelcase - filter_saveFilters: true, // eslint-disable-line camelcase - columnSelector_mediaquery: false // eslint-disable-line camelcase - } - }); -}; diff --git a/themes-default/slim/views/layouts/main.mako b/themes-default/slim/views/layouts/main.mako index b346b7e3fb..051e620136 100644 --- a/themes-default/slim/views/layouts/main.mako +++ b/themes-default/slim/views/layouts/main.mako @@ -110,7 +110,6 @@ - diff --git a/themes-default/slim/views/manage_subtitleMissedPP.mako b/themes-default/slim/views/manage_subtitleMissedPP.mako index 014b030796..e3fcf2351e 100644 --- a/themes-default/slim/views/manage_subtitleMissedPP.mako +++ b/themes-default/slim/views/manage_subtitleMissedPP.mako @@ -1,11 +1,11 @@ <%inherit file="/layouts/main.mako"/> <%! - from medusa import app import os + + from medusa import app from medusa.helper.common import episode_num %> <%block name="scripts"> - - diff --git a/themes/dark/templates/manage_subtitleMissedPP.mako b/themes/dark/templates/manage_subtitleMissedPP.mako index 014b030796..e3fcf2351e 100644 --- a/themes/dark/templates/manage_subtitleMissedPP.mako +++ b/themes/dark/templates/manage_subtitleMissedPP.mako @@ -1,11 +1,11 @@ <%inherit file="/layouts/main.mako"/> <%! - from medusa import app import os + + from medusa import app from medusa.helper.common import episode_num %> <%block name="scripts"> - - diff --git a/themes/light/templates/manage_subtitleMissedPP.mako b/themes/light/templates/manage_subtitleMissedPP.mako index 014b030796..e3fcf2351e 100644 --- a/themes/light/templates/manage_subtitleMissedPP.mako +++ b/themes/light/templates/manage_subtitleMissedPP.mako @@ -1,11 +1,11 @@ <%inherit file="/layouts/main.mako"/> <%! - from medusa import app import os + + from medusa import app from medusa.helper.common import episode_num %> <%block name="scripts"> -