mirror of
https://github.com/morpheus65535/bazarr
synced 2024-12-25 09:12:38 +00:00
Added history modal for episode and tab for movie.
This commit is contained in:
parent
2d5eb867d9
commit
a9bf2ee8e4
3 changed files with 308 additions and 102 deletions
|
@ -42,7 +42,8 @@ from beaker.middleware import SessionMiddleware
|
|||
from cork import Cork
|
||||
from bottle import route, template, static_file, request, redirect, response, HTTPError, app, hook
|
||||
from datetime import timedelta
|
||||
from get_languages import load_language_in_db, language_from_alpha3
|
||||
from get_languages import load_language_in_db, language_from_alpha3, language_from_alpha2, alpha2_from_alpha3
|
||||
|
||||
from get_providers import get_providers, get_providers_auth, list_throttled_providers
|
||||
from get_series import *
|
||||
from get_episodes import *
|
||||
|
@ -1729,7 +1730,7 @@ def remove_subtitles():
|
|||
try:
|
||||
os.remove(subtitlesPath)
|
||||
result = language_from_alpha3(language) + " subtitles deleted from disk."
|
||||
history_log(0, sonarrSeriesId, sonarrEpisodeId, result)
|
||||
history_log(0, sonarrSeriesId, sonarrEpisodeId, result, language=alpha2_from_alpha3(language))
|
||||
except OSError as e:
|
||||
logging.exception('BAZARR cannot delete subtitles file: ' + subtitlesPath)
|
||||
store_subtitles(unicode(episodePath))
|
||||
|
@ -1747,7 +1748,7 @@ def remove_subtitles_movie():
|
|||
try:
|
||||
os.remove(subtitlesPath)
|
||||
result = language_from_alpha3(language) + " subtitles deleted from disk."
|
||||
history_log_movie(0, radarrId, result)
|
||||
history_log_movie(0, radarrId, result, language=alpha2_from_alpha3(language))
|
||||
except OSError as e:
|
||||
logging.exception('BAZARR cannot delete subtitles file: ' + subtitlesPath)
|
||||
store_subtitles_movie(unicode(moviePath))
|
||||
|
@ -2127,6 +2128,85 @@ def running_tasks_list():
|
|||
return dict(tasks=running_tasks)
|
||||
|
||||
|
||||
@route(base_url + 'episode_history/<no:int>')
|
||||
@custom_auth_basic(check_credentials)
|
||||
def episode_history(no):
|
||||
authorize()
|
||||
episode_history = database.execute("SELECT action, timestamp, language, provider, score FROM table_history "
|
||||
"WHERE sonarrEpisodeId=? ORDER BY timestamp DESC", (no,))
|
||||
for item in episode_history:
|
||||
if item['action'] == 0:
|
||||
item['action'] = "<div class ='ui inverted basic compact icon' data-tooltip='Subtitle file has been " \
|
||||
"erased.' data-inverted='' data-position='top left'><i class='ui trash icon'></i></div>"
|
||||
elif item['action'] == 1:
|
||||
item['action'] = "<div class ='ui inverted basic compact icon' data-tooltip='Subtitle file has been " \
|
||||
"downloaded.' data-inverted='' data-position='top left'><i class='ui download " \
|
||||
"icon'></i></div>"
|
||||
elif item['action'] == 2:
|
||||
item['action'] = "<div class ='ui inverted basic compact icon' data-tooltip='Subtitle file has been " \
|
||||
"manually downloaded.' data-inverted='' data-position='top left'><i class='ui user " \
|
||||
"icon'></i></div>"
|
||||
elif item['action'] == 3:
|
||||
item['action'] = "<div class ='ui inverted basic compact icon' data-tooltip='Subtitle file has been " \
|
||||
"upgraded.' data-inverted='' data-position='top left'><i class='ui recycle " \
|
||||
"icon'></i></div>"
|
||||
elif item['action'] == 4:
|
||||
item['action'] = "<div class ='ui inverted basic compact icon' data-tooltip='Subtitle file has been " \
|
||||
"manually uploaded.' data-inverted='' data-position='top left'><i class='ui cloud " \
|
||||
"upload icon'></i></div>"
|
||||
item['timestamp'] = "<div data-tooltip='" + \
|
||||
time.strftime('%d/%m/%Y %H:%M:%S', time.localtime(item['timestamp'])) + "'>" + \
|
||||
pretty.date(datetime.fromtimestamp(item['timestamp'])) + "</div>"
|
||||
if item['language']:
|
||||
item['language'] = language_from_alpha2(item['language'])
|
||||
else:
|
||||
item['language'] = "<i>undefined</i>"
|
||||
if item['score']:
|
||||
item['score'] = str(round((int(item['score']) * 100 / 360), 2)) + "%"
|
||||
|
||||
return dict(data=episode_history)
|
||||
|
||||
|
||||
@route(base_url + 'movie_history/<no:int>')
|
||||
@custom_auth_basic(check_credentials)
|
||||
def movie_history(no):
|
||||
authorize()
|
||||
movie_history = database.execute("SELECT action, timestamp, language, provider, score FROM table_history_movie "
|
||||
"WHERE radarrId=? ORDER BY timestamp DESC", (no,))
|
||||
for item in movie_history:
|
||||
if item['action'] == 0:
|
||||
item['action'] = "<div class ='ui inverted basic compact icon' data-tooltip='Subtitle file has been " \
|
||||
"erased.' data-inverted='' data-position='top left'><i class='ui trash icon'></i></div>"
|
||||
elif item['action'] == 1:
|
||||
item['action'] = "<div class ='ui inverted basic compact icon' data-tooltip='Subtitle file has been " \
|
||||
"downloaded.' data-inverted='' data-position='top left'><i class='ui download " \
|
||||
"icon'></i></div>"
|
||||
elif item['action'] == 2:
|
||||
item['action'] = "<div class ='ui inverted basic compact icon' data-tooltip='Subtitle file has been " \
|
||||
"manually downloaded.' data-inverted='' data-position='top left'><i class='ui user " \
|
||||
"icon'></i></div>"
|
||||
elif item['action'] == 3:
|
||||
item['action'] = "<div class ='ui inverted basic compact icon' data-tooltip='Subtitle file has been " \
|
||||
"upgraded.' data-inverted='' data-position='top left'><i class='ui recycle " \
|
||||
"icon'></i></div>"
|
||||
elif item['action'] == 4:
|
||||
item['action'] = "<div class ='ui inverted basic compact icon' data-tooltip='Subtitle file has been " \
|
||||
"manually uploaded.' data-inverted='' data-position='top left'><i class='ui cloud " \
|
||||
"upload icon'></i></div>"
|
||||
|
||||
item['timestamp'] = "<div data-tooltip='" + \
|
||||
time.strftime('%d/%m/%Y %H:%M:%S', time.localtime(item['timestamp'])) + "'>" + \
|
||||
pretty.date(datetime.fromtimestamp(item['timestamp'])) + "</div>"
|
||||
if item['language']:
|
||||
item['language'] = language_from_alpha2(item['language'])
|
||||
else:
|
||||
item['language'] = "<i>undefined</i>"
|
||||
if item['score']:
|
||||
item['score'] = str(round((int(item['score']) * 100 / 120), 2)) + '%'
|
||||
|
||||
return dict(data=movie_history)
|
||||
|
||||
|
||||
# Mute DeprecationWarning
|
||||
warnings.simplefilter("ignore", DeprecationWarning)
|
||||
server = CherryPyWSGIServer((str(settings.general.ip), (int(args.port) if args.port else int(settings.general.port))), app)
|
||||
|
|
|
@ -217,7 +217,7 @@
|
|||
% if episode['scene_name'] is not None:
|
||||
<span data-tooltip="Scenename is: {{episode['scene_name']}}" data-inverted='' data-position="top left"><i class="info circle icon"></i></span>
|
||||
% end
|
||||
<span data-tooltip="Path is: {{episode['path']}}" data-inverted='' data-position="top left">{{episode['title']}}</span>
|
||||
<span data-tooltip="Path is: {{episode['path']}}" data-inverted='' data-position="top left"><a data-series_title="{{details['title']}}" data-season="{{episode['season']}}" data-episode="{{episode['episode']}}" data-episode_title="{{episode['title']}}" data-sonarrEpisodeId="{{episode['sonarrEpisodeId']}}" class="episode_history">{{episode['title']}}</a></span>
|
||||
</td>
|
||||
<td>
|
||||
%if episode['subtitles'] is not None:
|
||||
|
@ -379,6 +379,29 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="episode_dialog ui modal">
|
||||
<i class="close icon"></i>
|
||||
<div class="header">
|
||||
<span id="series_title_span"></span> - <span id="season"></span>x<span id="episode"></span> - <span id="episode_title"></span>
|
||||
</div>
|
||||
<div class="scrolling content">
|
||||
<table id="episode_result" class="display" style="width:100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th style="text-align: left;">Language.:</th>
|
||||
<th style="text-align: left;">Provider:</th>
|
||||
<th style="text-align: left;">Score:</th>
|
||||
<th style="text-align: left;">Date:</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<button class="ui cancel button" >Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="search_dialog ui modal">
|
||||
<i class="close icon"></i>
|
||||
<div class="header">
|
||||
|
@ -531,7 +554,7 @@
|
|||
});
|
||||
});
|
||||
|
||||
$('a:not(.manual_search, .manual_upload), .menu .item, button:not(#config, .cancel, #search_missing_subtitles)').on('click', function(){
|
||||
$('a:not(.manual_search, .manual_upload, .episode_history), .menu .item, button:not(#config, .cancel, #search_missing_subtitles)').on('click', function(){
|
||||
$('#loader').addClass('active');
|
||||
});
|
||||
|
||||
|
@ -564,6 +587,51 @@
|
|||
.modal('show');
|
||||
});
|
||||
|
||||
$('.episode_history').on('click', function(){
|
||||
$("#series_title_span").html($(this).data("series_title"));
|
||||
$("#season").html($(this).data("season"));
|
||||
$("#episode").html($(this).data("episode"));
|
||||
$("#episode_title").html($(this).data("episode_title"));
|
||||
|
||||
sonarrEpisodeId = $(this).attr("data-sonarrEpisodeId");
|
||||
|
||||
$('#episode_result').DataTable( {
|
||||
destroy: true,
|
||||
language: {
|
||||
loadingRecords: '<br><div class="ui active inverted dimmer" style="width: 95%;"><div class="ui centered inline loader"></div></div><br>',
|
||||
zeroRecords: 'No History Records Found For This Episode'
|
||||
},
|
||||
paging: true,
|
||||
lengthChange: false,
|
||||
pageLength: 5,
|
||||
searching: true,
|
||||
ordering: true,
|
||||
processing: false,
|
||||
serverSide: false,
|
||||
ajax: {
|
||||
url: '{{base_url}}episode_history/' + sonarrEpisodeId
|
||||
},
|
||||
drawCallback: function(settings) {
|
||||
$('.inline.dropdown').dropdown();
|
||||
$('.ui.accordion').accordion();
|
||||
},
|
||||
columns: [
|
||||
{ data: 'action'},
|
||||
{ data: 'language' },
|
||||
{ data: 'provider' },
|
||||
{ data: 'score'},
|
||||
{ data: 'timestamp' }
|
||||
]
|
||||
} );
|
||||
|
||||
$('.episode_dialog')
|
||||
.modal({
|
||||
centered: false,
|
||||
autofocus: false
|
||||
})
|
||||
.modal('show');
|
||||
});
|
||||
|
||||
$('.manual_search').on('click', function(){
|
||||
$("#series_title_span").html($(this).data("series_title"));
|
||||
$("#season").html($(this).data("season"));
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
}
|
||||
#fondblanc {
|
||||
background-color: #ffffff;
|
||||
color: #000000;
|
||||
opacity: 0.9;
|
||||
border-radius: 1px;
|
||||
box-shadow: 0 0 3px 3px #ffffff;
|
||||
|
@ -160,6 +161,12 @@
|
|||
</div>
|
||||
|
||||
<div id="fondblanc" class="ui container">
|
||||
<div class="ui top attached tabular menu">
|
||||
<a id="subtitles_tab" class="tabs item active" data-tab="subtitles">Subtitles</a>
|
||||
<a id="history_tab" class="tabs item" data-tab="history">History</a>
|
||||
</div>
|
||||
<div class="ui bottom attached tab active segment" data-tab="subtitles">
|
||||
<div class="content">
|
||||
<table class="ui very basic single line selectable table">
|
||||
<thead>
|
||||
<tr>
|
||||
|
@ -263,6 +270,23 @@
|
|||
%>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui bottom attached tab segment" data-tab="history">
|
||||
<div class="content">
|
||||
<table id="movie_result" class="display" style="width:100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th style="text-align: left;">Language.:</th>
|
||||
<th style="text-align: left;">Provider:</th>
|
||||
<th style="text-align: left;">Score:</th>
|
||||
<th style="text-align: left;">Date:</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="config_dialog ui small modal">
|
||||
|
@ -420,6 +444,9 @@
|
|||
</html>
|
||||
|
||||
<script>
|
||||
$('.menu .item')
|
||||
.tab();
|
||||
|
||||
$('#scan_disk').on('click', function(){
|
||||
$('#loader_text').text("Scanning Disk For Existing Subtitles...");
|
||||
window.location = '{{base_url}}scan_disk_movie/{{no}}';
|
||||
|
@ -486,7 +513,7 @@
|
|||
});
|
||||
});
|
||||
|
||||
$('a, .menu .item, button:not(#config, .cancel, .manual_search, .manual_upload, #search_missing_subtitles_movie)').on('click', function(){
|
||||
$('a:not(.tabs), button:not(#config, .cancel, .manual_search, .manual_upload, #search_missing_subtitles_movie)').on('click', function(){
|
||||
$('#loader').addClass('active');
|
||||
});
|
||||
|
||||
|
@ -519,6 +546,37 @@
|
|||
.modal('show');
|
||||
});
|
||||
|
||||
$('#history_tab').on('click', function(){
|
||||
$('#movie_result').DataTable( {
|
||||
destroy: true,
|
||||
language: {
|
||||
loadingRecords: '<br><div class="ui active inverted dimmer" style="width: 95%;"><div class="ui centered inline loader"></div></div><br>',
|
||||
zeroRecords: 'No History Records Found For This Movie'
|
||||
},
|
||||
paging: true,
|
||||
lengthChange: false,
|
||||
pageLength: 5,
|
||||
searching: true,
|
||||
ordering: true,
|
||||
processing: false,
|
||||
serverSide: false,
|
||||
ajax: {
|
||||
url: '{{base_url}}movie_history/{{no}}'
|
||||
},
|
||||
drawCallback: function(settings) {
|
||||
$('.inline.dropdown').dropdown();
|
||||
$('.ui.accordion').accordion();
|
||||
},
|
||||
columns: [
|
||||
{ data: 'action'},
|
||||
{ data: 'language' },
|
||||
{ data: 'provider' },
|
||||
{ data: 'score'},
|
||||
{ data: 'timestamp' }
|
||||
]
|
||||
} );
|
||||
});
|
||||
|
||||
$('.manual_search').on('click', function(){
|
||||
$("#movie_title_span").html($(this).data("movie_title"));
|
||||
$("#movie_path_span").html($(this).attr("data-moviePath"));
|
||||
|
|
Loading…
Reference in a new issue