pull/884/head
Moravčík, Marian 5 years ago
parent 4282fe8f50
commit 7af7037c95

@ -136,6 +136,16 @@ def check_credentials(user, pw):
return False
@app.context_processor
def restart_processor():
def restart_required():
db = database.execute("SELECT configured, updated FROM system")
for i in db:
restart_required = i
return restart_required
return dict(restart_required=restart_required()['configured'], update_required=restart_required()['updated'], ast=ast, settings=settings)
def api_authorize():
if 'apikey' in request.GET.dict:
if request.GET.dict['apikey'][0] == settings.auth.apikey:
@ -153,7 +163,7 @@ def post_get(name, default=''):
@app.route(base_url + 'login/')
def login_form():
msg = request.query.get('msg', '')
return render_template('login', base_url=base_url, msg=msg)
return render_template('login.html', base_url=base_url, msg=msg)
@app.route(base_url + 'login/', methods=['POST'])
@ -174,7 +184,6 @@ def logout():
@app.route(base_url + 'shutdown/')
# @custom_auth_basic(check_credentials)
def shutdown():
try:
server.stop()
except:
@ -194,7 +203,6 @@ def shutdown():
@app.route(base_url + 'restart/')
# @custom_auth_basic(check_credentials)
def restart():
try:
server.stop()
except:
@ -215,8 +223,6 @@ def restart():
@app.route(base_url + 'wizard/')
@custom_auth_basic(check_credentials)
def wizard():
# Get languages list
settings_languages = database.execute("SELECT * FROM table_settings_languages ORDER BY name")
# Get providers list
@ -230,8 +236,6 @@ def wizard():
@app.route(base_url + 'save_wizard', methods=['POST'])
# @custom_auth_basic(check_credentials)
def save_wizard():
settings_general_ip = request.form.get('settings_general_ip')
settings_general_port = request.form.get('settings_general_port')
settings_general_baseurl = request.form.get('settings_general_baseurl')
@ -446,7 +450,6 @@ def save_wizard():
@app.route(base_url + 'emptylog')
# @custom_auth_basic(check_credentials)
def emptylog():
ref = request.environ['HTTP_REFERER']
empty_log()
@ -458,14 +461,12 @@ def emptylog():
@app.route(base_url + 'bazarr.log')
# @custom_auth_basic(check_credentials)
def download_log():
return static_file('bazarr.log', root=os.path.join(args.config_dir, 'log/'), download='bazarr.log')
@app.route(base_url + 'image_proxy/<path:url>', methods=['GET'])
# @custom_auth_basic(check_credentials)
def image_proxy(url):
apikey = settings.sonarr.apikey
url_image = url_sonarr_short() + '/' + url + '?apikey=' + apikey
try:
@ -483,7 +484,6 @@ def image_proxy(url):
@app.route(base_url + 'image_proxy_movies/<path:url>', methods=['GET'])
# @custom_auth_basic(check_credentials)
def image_proxy_movies(url):
apikey = settings.radarr.apikey
try:
url_image = (url_radarr_short() + '/' + url + '?apikey=' + apikey).replace('/fanart.jpg', '/banner.jpg')
@ -503,7 +503,6 @@ def image_proxy_movies(url):
@app.route(base_url)
# @custom_auth_basic(check_credentials)
def redirect_root():
if settings.general.getboolean('use_sonarr'):
return redirect(base_url + 'series')
elif settings.general.getboolean('use_radarr'):
@ -517,8 +516,6 @@ def redirect_root():
@app.route(base_url + 'series/')
# @custom_auth_basic(check_credentials)
def series():
series_count = database.execute("SELECT COUNT(*) as count FROM table_shows", only_one=True)['count']
page = request.data
if not page:
@ -564,7 +561,7 @@ def series():
"table_episodes.sonarrSeriesId WHERE table_shows.languages IS NOT 'None'"
+ total_subtitles_clause + " GROUP BY table_shows.sonarrSeriesId")
return render_template('series', bazarr_version=bazarr_version, rows=data, missing_subtitles_list=missing_subtitles_list,
return render_template('series.html', bazarr_version=bazarr_version, rows=data, missing_subtitles_list=missing_subtitles_list,
total_subtitles_list=total_subtitles_list, languages=languages, missing_count=series_count,
page=page, max_page=max_page, base_url=base_url,
single_language=settings.general.getboolean('single_language'), page_size=page_size,
@ -574,7 +571,6 @@ def series():
@app.route(base_url + 'serieseditor/')
# @custom_auth_basic(check_credentials)
def serieseditor():
# Get missing count
missing_count = database.execute("SELECT COUNT(*) as count FROM table_shows", only_one=True)['count']
@ -588,7 +584,7 @@ def serieseditor():
# Get languages list
languages = database.execute("SELECT code2, name FROM table_settings_languages WHERE enabled=1")
return render_template('serieseditor', bazarr_version=bazarr_version, rows=data, languages=languages,
return render_template('serieseditor.html', bazarr_version=bazarr_version, rows=data, languages=languages,
missing_count=missing_count, base_url=base_url,
single_language=settings.general.getboolean('single_language'), current_port=settings.general.port)
@ -596,7 +592,7 @@ def serieseditor():
@app.route(base_url + 'search_json/<query>', methods=['GET'])
# @custom_auth_basic(check_credentials)
def search_json(query):
query = '%' + query + '%'
search_list = []
@ -624,7 +620,7 @@ def search_json(query):
@app.route(base_url + 'edit_series/<int:no>', methods=['POST'])
# @custom_auth_basic(check_credentials)
def edit_series(no):
ref = request.environ['HTTP_REFERER']
lang = request.form.getlist('languages')
@ -662,7 +658,7 @@ def edit_series(no):
@app.route(base_url + 'edit_serieseditor', methods=['POST'])
# @custom_auth_basic(check_credentials)
def edit_serieseditor():
ref = request.environ['HTTP_REFERER']
series = request.form.get('series')
@ -692,7 +688,7 @@ def edit_serieseditor():
@app.route(base_url + 'episodes/<int:no>', methods=['GET'])
# @custom_auth_basic(check_credentials)
def episodes(no):
series_details = database.execute("SELECT title, overview, poster, fanart, hearing_impaired, tvdbId, "
"audio_language, languages, path, forced FROM table_shows WHERE "
@ -716,7 +712,7 @@ def episodes(no):
for key, season in itertools.groupby(episodes, lambda x: x['season']):
seasons_list.append(list(season))
return render_template('episodes', bazarr_version=bazarr_version, no=no, details=series_details,
return render_template('episodes.html', bazarr_version=bazarr_version, no=no, details=series_details,
languages=languages, seasons=seasons_list, url_sonarr_short=url_sonarr_short(), base_url=base_url,
tvdbid=tvdbid, number=number, current_port=settings.general.port)
@ -724,7 +720,7 @@ def episodes(no):
@app.route(base_url + 'movies')
# @custom_auth_basic(check_credentials)
def movies():
missing_count = database.execute("SELECT COUNT(*) as count FROM table_movies", only_one=True)['count']
page = request.data
@ -742,7 +738,7 @@ def movies():
languages = database.execute("SELECT code2, name FROM table_settings_languages WHERE enabled=1")
return render_template('movies', bazarr_version=bazarr_version, rows=data, languages=languages,
return render_template('movies.html', bazarr_version=bazarr_version, rows=data, languages=languages,
missing_count=missing_count, page=page, max_page=max_page, base_url=base_url,
single_language=settings.general.getboolean('single_language'), page_size=page_size,
current_port=settings.general.port)
@ -751,7 +747,7 @@ def movies():
@app.route(base_url + 'movieseditor')
# @custom_auth_basic(check_credentials)
def movieseditor():
missing_count = database.execute("SELECT COUNT(*) as count FROM table_movies", only_one=True)['count']
@ -762,7 +758,7 @@ def movieseditor():
languages = database.execute("SELECT code2, name FROM table_settings_languages WHERE enabled=1")
return render_template('movieseditor', bazarr_version=bazarr_version, rows=data, languages=languages,
return render_template('movieseditor.html', bazarr_version=bazarr_version, rows=data, languages=languages,
missing_count=missing_count, base_url=base_url, single_language=
settings.general.getboolean('single_language'), current_port=settings.general.port)
@ -770,7 +766,7 @@ def movieseditor():
@app.route(base_url + 'edit_movieseditor', methods=['POST'])
# @custom_auth_basic(check_credentials)
def edit_movieseditor():
ref = request.environ['HTTP_REFERER']
movies = request.form.get('movies')
@ -800,7 +796,7 @@ def edit_movieseditor():
@app.route(base_url + 'edit_movie/<int:no>', methods=['POST'])
# @custom_auth_basic(check_credentials)
def edit_movie(no):
ref = request.environ['HTTP_REFERER']
lang = request.form.getlist('languages')
@ -838,7 +834,7 @@ def edit_movie(no):
@app.route(base_url + 'movie/<int:no>', methods=['GET'])
# @custom_auth_basic(check_credentials)
def movie(no):
movies_details = database.execute("SELECT title, overview, poster, fanart, hearing_impaired, tmdbId, "
"audio_language, languages, path, subtitles, radarrId, missing_subtitles, "
@ -851,7 +847,7 @@ def movie(no):
languages = database.execute("SELECT code2, name FROM table_settings_languages WHERE enabled=1")
return render_template('movie', bazarr_version=bazarr_version, no=no, details=movies_details,
return render_template('movie.html', bazarr_version=bazarr_version, no=no, details=movies_details,
languages=languages, url_radarr_short=url_radarr_short(), base_url=base_url, tmdbid=tmdbid,
current_port=settings.general.port)
@ -859,7 +855,7 @@ def movie(no):
@app.route(base_url + 'scan_disk/<int:no>', methods=['GET'])
# @custom_auth_basic(check_credentials)
def scan_disk(no):
ref = request.environ['HTTP_REFERER']
series_scan_subtitles(no)
@ -870,7 +866,7 @@ def scan_disk(no):
@app.route(base_url + 'scan_disk_movie/<int:no>', methods=['GET'])
# @custom_auth_basic(check_credentials)
def scan_disk_movie(no):
ref = request.environ['HTTP_REFERER']
movies_scan_subtitles(no)
@ -881,7 +877,7 @@ def scan_disk_movie(no):
@app.route(base_url + 'search_missing_subtitles/<int:no>', methods=['GET'])
# @custom_auth_basic(check_credentials)
def search_missing_subtitles(no):
ref = request.environ['HTTP_REFERER']
add_job(series_download_subtitles, args=[no], name=('search_missing_subtitles_' + str(no)))
@ -892,7 +888,7 @@ def search_missing_subtitles(no):
@app.route(base_url + 'search_missing_subtitles_movie/<int:no>', methods=['GET'])
# @custom_auth_basic(check_credentials)
def search_missing_subtitles_movie(no):
ref = request.environ['HTTP_REFERER']
add_job(movies_download_subtitles, args=[no], name=('movies_download_subtitles_' + str(no)))
@ -903,19 +899,19 @@ def search_missing_subtitles_movie(no):
@app.route(base_url + 'history')
# @custom_auth_basic(check_credentials)
def history():
return render_template('history', bazarr_version=bazarr_version, base_url=base_url, current_port=settings.general.port)
@app.route(base_url + 'historyseries')
# @custom_auth_basic(check_credentials)
def historyseries():
row_count = database.execute("SELECT COUNT(*) as count FROM table_history LEFT JOIN table_shows on "
"table_history.sonarrSeriesId = table_shows.sonarrSeriesId WHERE "
"table_shows.title is not NULL", only_one=True)['count']
page = request.args.page
page = request.data
if page == "":
page = "1"
page_size = int(settings.general.page_size)
@ -981,7 +977,7 @@ def historyseries():
if int(upgradable_episode['score']) < 360:
upgradable_episodes_not_perfect.append(upgradable_episode)
return render_template('historyseries', bazarr_version=bazarr_version, rows=data, row_count=row_count,
return render_template('historyseries.html', bazarr_version=bazarr_version, rows=data, row_count=row_count,
page=page, max_page=max_page, stats=stats, base_url=base_url, page_size=page_size,
current_port=settings.general.port, upgradable_episodes=upgradable_episodes_not_perfect)
@ -989,12 +985,12 @@ def historyseries():
@app.route(base_url + 'historymovies')
# @custom_auth_basic(check_credentials)
def historymovies():
row_count = database.execute("SELECT COUNT(*) as count FROM table_history_movie LEFT JOIN table_movies ON "
"table_history_movie.radarrId=table_movies.radarrId "
"WHERE table_movies.title is not NULL", only_one=True)['count']
page = request.args.page
page = request.data
if page == "":
page = "1"
page_size = int(settings.general.page_size)
@ -1058,7 +1054,7 @@ def historymovies():
if int(upgradable_movie['score']) < 120:
upgradable_movies_not_perfect.append(upgradable_movie)
return render_template('historymovies', bazarr_version=bazarr_version, rows=data, row_count=row_count,
return render_template('historymovies.html', bazarr_version=bazarr_version, rows=data, row_count=row_count,
page=page, max_page=max_page, stats=stats, base_url=base_url, page_size=page_size,
current_port=settings.general.port, upgradable_movies=upgradable_movies_not_perfect)
@ -1066,14 +1062,14 @@ def historymovies():
@app.route(base_url + 'wanted')
# @custom_auth_basic(check_credentials)
def wanted():
return render_template('wanted', bazarr_version=bazarr_version, base_url=base_url, current_port=settings.general.port)
return render_template('wanted.html', bazarr_version=bazarr_version, base_url=base_url, current_port=settings.general.port)
@app.route(base_url + 'wantedseries')
# @custom_auth_basic(check_credentials)
def wantedseries():
if settings.sonarr.getboolean('only_monitored'):
monitored_only_query_string = " AND monitored='True'"
@ -1082,7 +1078,7 @@ def wantedseries():
missing_count = database.execute("SELECT COUNT(*) as count FROM table_episodes WHERE missing_subtitles != '[]'" +
monitored_only_query_string, only_one=True)['count']
page = request.args.page
page = request.data
if page == "":
page = "1"
page_size = int(settings.general.page_size)
@ -1100,14 +1096,14 @@ def wantedseries():
# path_replace
dict_mapper.path_replace(data)
return render_template('wantedseries', bazarr_version=bazarr_version, rows=data, missing_count=missing_count, page=page,
return render_template('wantedseries.html', bazarr_version=bazarr_version, rows=data, missing_count=missing_count, page=page,
max_page=max_page, base_url=base_url, page_size=page_size, current_port=settings.general.port)
@app.route(base_url + 'wantedmovies')
# @custom_auth_basic(check_credentials)
def wantedmovies():
if settings.radarr.getboolean('only_monitored'):
monitored_only_query_string = " AND monitored='True'"
@ -1130,7 +1126,7 @@ def wantedmovies():
# path_replace
dict_mapper.path_replace_movie(data)
return render_template('wantedmovies', bazarr_version=bazarr_version, rows=data,
return render_template('wantedmovies.html', bazarr_version=bazarr_version, rows=data,
missing_count=missing_count, page=page, max_page=max_page, base_url=base_url, page_size=page_size,
current_port=settings.general.port)
@ -1138,7 +1134,7 @@ def wantedmovies():
@app.route(base_url + 'wanted_search_missing_subtitles')
# @custom_auth_basic(check_credentials)
def wanted_search_missing_subtitles_list():
ref = request.environ['HTTP_REFERER']
add_job(wanted_search_missing_subtitles, name='manual_wanted_search_missing_subtitles')
@ -1149,7 +1145,7 @@ def wanted_search_missing_subtitles_list():
@app.route(base_url + 'settings/')
# @custom_auth_basic(check_credentials)
def _settings():
settings_languages = database.execute("SELECT * FROM table_settings_languages ORDER BY name")
settings_providers = sorted(provider_manager.names())
@ -1163,7 +1159,7 @@ def _settings():
@app.route(base_url + 'save_settings', methods=['POST'])
# @custom_auth_basic(check_credentials)
def save_settings():
ref = request.environ['HTTP_REFERER']
settings_general_ip = request.form.get('settings_general_ip')
@ -1381,29 +1377,6 @@ def save_settings():
settings.auth.type = text_type(settings_auth_type)
settings.auth.username = text_type(settings_auth_username)
settings.auth.password = hashlib.md5(settings_auth_password.encode('utf-8')).hexdigest()
if settings_auth_username not in aaa._store.users:
cork = Cork(os.path.normpath(os.path.join(args.config_dir, 'config')), initialize=True)
cork._store.roles[''] = 100
cork._store.save_roles()
cork._store.users[settings_auth_username] = {
'role': '',
'hash': cork._hash(settings_auth_username, settings_auth_password),
'email_addr': '',
'desc': '',
'creation_date': time.time()
}
cork._store.save_users()
if settings_auth_type == 'basic' or settings_auth_type == 'None':
pass
else:
aaa._beaker_session.delete()
else:
if settings.auth.password != settings_auth_password:
aaa.user(settings_auth_username).update(role='', pwd=settings_auth_password)
if settings_auth_type == 'basic' or settings_auth_type == 'None':
pass
else:
aaa._beaker_session.delete()
settings.auth.apikey = request.form.get('settings_auth_apikey')
settings_sonarr_ip = request.form.get('settings_sonarr_ip')
@ -1593,7 +1566,7 @@ def save_settings():
@app.route(base_url + 'check_update')
# @custom_auth_basic(check_credentials)
def check_update():
ref = request.environ['HTTP_REFERER']
if not args.no_update:
@ -1605,7 +1578,7 @@ def check_update():
@app.route(base_url + 'system')
# @custom_auth_basic(check_credentials)
def system():
def get_time_from_interval(td_object):
seconds = int(td_object.total_seconds())
@ -1678,7 +1651,7 @@ def system():
page_size = int(settings.general.page_size)
return render_template('system', bazarr_version=bazarr_version,
return render_template('system.html', bazarr_version=bazarr_version,
sonarr_version=sonarr_version, radarr_version=radarr_version,
operating_system=platform.platform(), python_version=platform.python_version(),
config_dir=args.config_dir, bazarr_dir=os.path.normcase(os.path.dirname(os.path.dirname(__file__))),
@ -1689,7 +1662,7 @@ def system():
@app.route(base_url + 'logs')
# @custom_auth_basic(check_credentials)
def get_logs():
logs = []
with open(os.path.join(args.config_dir, 'log', 'bazarr.log')) as file:
for line in file.readlines():
@ -1704,7 +1677,7 @@ def get_logs():
@app.route(base_url + 'execute/<taskid>')
# @custom_auth_basic(check_credentials)
def execute_task(taskid):
ref = request.environ['HTTP_REFERER']
execute_now(taskid)
@ -1715,7 +1688,7 @@ def execute_task(taskid):
@app.route(base_url + 'remove_subtitles', methods=['POST'])
# @custom_auth_basic(check_credentials)
def remove_subtitles():
episodePath = request.form.get('episodePath')
language = request.form.get('language')
subtitlesPath = request.form.get('subtitlesPath')
@ -1734,7 +1707,7 @@ def remove_subtitles():
@app.route(base_url + 'remove_subtitles_movie', methods=['POST'])
# @custom_auth_basic(check_credentials)
def remove_subtitles_movie():
moviePath = request.form.get('moviePath')
language = request.form.get('language')
subtitlesPath = request.form.get('subtitlesPath')
@ -1752,7 +1725,7 @@ def remove_subtitles_movie():
@app.route(base_url + 'get_subtitle', methods=['POST'])
# @custom_auth_basic(check_credentials)
def get_subtitle():
ref = request.environ['HTTP_REFERER']
episodePath = request.form.get('episodePath')
@ -1788,7 +1761,7 @@ def get_subtitle():
@app.route(base_url + 'manual_search', methods=['POST'])
# @custom_auth_basic(check_credentials)
def manual_search_json():
episodePath = request.form.get('episodePath')
sceneName = request.form.get('sceneName')
@ -1807,7 +1780,7 @@ def manual_search_json():
@app.route(base_url + 'manual_get_subtitle', methods=['POST'])
# @custom_auth_basic(check_credentials)
def manual_get_subtitle():
ref = request.environ['HTTP_REFERER']
episodePath = request.form.get('episodePath')
@ -1845,7 +1818,7 @@ def manual_get_subtitle():
@app.route(base_url + 'manual_upload_subtitle', methods=['POST'])
# @custom_auth_basic(check_credentials)
def perform_manual_upload_subtitle():
ref = request.environ['HTTP_REFERER']
episodePath = request.form.get('episodePath')
@ -1889,7 +1862,7 @@ def perform_manual_upload_subtitle():
@app.route(base_url + 'get_subtitle_movie', methods=['POST'])
# @custom_auth_basic(check_credentials)
def get_subtitle_movie():
ref = request.environ['HTTP_REFERER']
moviePath = request.form.get('moviePath')
@ -1924,7 +1897,7 @@ def get_subtitle_movie():
@app.route(base_url + 'manual_search_movie', methods=['POST'])
# @custom_auth_basic(check_credentials)
def manual_search_movie_json():
moviePath = request.form.get('moviePath')
sceneName = request.form.get('sceneName')
@ -1943,7 +1916,7 @@ def manual_search_movie_json():
@app.route(base_url + 'manual_get_subtitle_movie', methods=['POST'])
# @custom_auth_basic(check_credentials)
def manual_get_subtitle_movie():
ref = request.environ['HTTP_REFERER']
moviePath = request.form.get('moviePath')
@ -1979,7 +1952,7 @@ def manual_get_subtitle_movie():
@app.route(base_url + 'manual_upload_subtitle_movie', methods=['POST'])
# @custom_auth_basic(check_credentials)
def perform_manual_upload_subtitle_movie():
ref = request.environ['HTTP_REFERER']
moviePath = request.form.get('moviePath')
@ -2086,7 +2059,7 @@ def api_movies_history():
@app.route(base_url + 'test_url/<protocol>/<path:url>', methods=['GET'])
# @custom_auth_basic(check_credentials)
def test_url(protocol, url):
url = six.moves.urllib.parse.unquote(url)
try:
result = requests.get(protocol + "://" + url, allow_redirects=False, verify=False).json()['version']
@ -2099,7 +2072,7 @@ def test_url(protocol, url):
@app.route(base_url + 'test_notification/<protocol>/<path:provider>', methods=['GET'])
# @custom_auth_basic(check_credentials)
def test_notification(protocol, provider):
provider = six.moves.urllib.parse.unquote(provider)
apobj = apprise.Apprise()
apobj.add(protocol + "://" + provider)
@ -2113,7 +2086,7 @@ def test_notification(protocol, provider):
@app.route(base_url + 'notifications')
# @custom_auth_basic(check_credentials)
def notifications():
if queueconfig.notifications:
return queueconfig.notifications.read()
else:
@ -2123,14 +2096,14 @@ def notifications():
@app.route(base_url + 'running_tasks')
# @custom_auth_basic(check_credentials)
def running_tasks_list():
return dict(tasks=running_tasks)
@app.route(base_url + 'episode_history/<int:no>')
# @custom_auth_basic(check_credentials)
def episode_history(no):
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:
@ -2169,7 +2142,7 @@ def episode_history(no):
@app.route(base_url + 'movie_history/<int:no>')
# @custom_auth_basic(check_credentials)
def movie_history(no):
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:

@ -1,360 +1,399 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<meta name="mobile-web-app-capable" content="yes"/>
<meta name="apple-mobile-web-app-capable" content="yes"/>
<link href="{{base_url}}static/noty/noty.css" rel="stylesheet">
<script src="{{base_url}}static/noty/noty.min.js" type="text/javascript"></script>
<style>
#divmenu {
padding-top: 1em;
}
.menu_segment {
padding: 0em !important;
border: none !important;
margin: 0em !important;
background: none !important;
}
#icon_menu {
background: transparent !important;
border: solid;
border-width: 1px;
border-color: white;
}
.prompt {
background-color: #333333 !important;
color: white !important;
border-radius: 3px !important;
}
.searchicon {
color: white !important;
}
.ui.progress .bar>.progress {
right: auto;
left: .5em;
color: black !important;
}
.ui.disabled.progress.notification_progress {
opacity: unset !important;
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<meta name="mobile-web-app-capable" content="yes"/>
<meta name="apple-mobile-web-app-capable" content="yes"/>
<link href="{{ base_url }}static/noty/noty.css" rel="stylesheet">
<script src="{{ base_url }}static/noty/noty.min.js" type="text/javascript"></script>
<style>
#divmenu {
padding-top: 1em;
}
.menu_segment {
padding: 0em !important;
border: none !important;
margin: 0em !important;
background: none !important;
}
#icon_menu {
background: transparent !important;
border: solid;
border-width: 1px;
border-color: white;
}
.prompt {
background-color: #333333 !important;
color: white !important;
border-radius: 3px !important;
}
.searchicon {
color: white !important;
}
.ui.progress .bar > .progress {
right: auto;
left: .5em;
color: black !important;
}
.ui.disabled.progress.notification_progress {
opacity: unset !important;
}
div.disabled {
pointer-events: none;
}
button.disabled {
pointer-events: none;
}
@media only screen and (max-width: 1024px) {
.logo {
width: 36px;
height: auto;
}
div.disabled { pointer-events: none; }
button.disabled { pointer-events: none; }
@media only screen and (max-width: 1024px) {
.logo {
width: 36px;
height: auto;
}
}
</style>
</head>
<body>
% from get_args import args
% from get_providers import update_throttled_provider
% update_throttled_provider()
% import ast
% import datetime
% import os
% from database import database
% import operator
% from config import settings
% from functools import reduce
%if settings.sonarr.getboolean('only_monitored'):
% monitored_only_query_string_sonarr = ' AND monitored = "True"'
%else:
% monitored_only_query_string_sonarr = ""
%end
%if settings.radarr.getboolean('only_monitored'):
% monitored_only_query_string_radarr = ' AND monitored = "True"'
%else:
% monitored_only_query_string_radarr = ""
%end
% wanted_series = database.execute("SELECT COUNT(*) as count FROM table_episodes WHERE missing_subtitles != '[]'" + monitored_only_query_string_sonarr, only_one=True)['count']
% wanted_movies = database.execute("SELECT COUNT(*) as count FROM table_movies WHERE missing_subtitles != '[]'" + monitored_only_query_string_radarr, only_one=True)['count']
% from get_providers import list_throttled_providers
% throttled_providers_count = len(eval(str(settings.general.throtteled_providers)))
<div id="divmenu" class="ui container">
<div class="ui grid">
<div class="three wide column">
<div class="ui compact segment menu_segment">
<a href="{{base_url}}"><img class="logo" src="{{base_url}}static/logo128.png"></a>
</div>
</div>
<div class="ten wide right aligned compact column">
<div id="button_menu" class="ui center aligned segment menu_segment" hidden="hidden">
<div class="ui inverted compact borderless labeled icon massive menu menu_segment">
% if settings.general.getboolean('use_sonarr'):
<a class="item" href="{{base_url}}series">
<i class="play icon"></i>
Series
</a>
% end
% if settings.general.getboolean('use_radarr'):
<a class="item" href="{{base_url}}movies">
<i class="film icon"></i>
Movies
</a>
% end
<a class="item" href="{{base_url}}history">
<i class="wait icon"></i>
History
</a>
<a class="item" href="{{base_url}}wanted">
<i class="warning sign icon">
% if settings.general.getboolean('use_sonarr') and wanted_series > 0:
<div id="wanted_series" class="floating ui tiny yellow label" style="left:90% !important;top:0.5em !important;">
{{wanted_series}}
</div>
% end
% if settings.general.getboolean('use_radarr') and wanted_movies > 0:
<div id="wanted_movies" class="floating ui tiny green label" style="left:90% !important;top:3em !important;">
{{wanted_movies}}
</div>
% end
</i>
Wanted
</a>
<a class="item" href="{{base_url}}settings">
<i class="settings icon"></i>
Settings
</a>
<a class="item" href="{{base_url}}system">
<i class="laptop icon">
% if throttled_providers_count:
<div class="floating ui tiny yellow label" style="left:90% !important;top:0.5em !important;">
{{throttled_providers_count}}
</div>
% end
</i>
System
</a>
<a id="donate" class="item" href="https://beerpay.io/morpheus65535/bazarr">
<i class="red heart icon"></i>
Donate
</a>
</div>
</div>
<div class="ui center aligned segment menu_segment">
<div class="ui grid">
<div id="search_column" class="centered column">
<div class="ui fluid search">
<div class="ui left icon fluid input">
<input class="prompt" type="text" placeholder="Search in your library">
<i class="searchicon search icon"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="three wide right aligned column">
<div id="dropdown_menu" class="ui segment menu_segment" hidden="hidden">
<div id="icon_menu" class="ui compact tiny icon menu">
<div id="dropdown_menu_button" class="ui floating right dropdown item">
<i class="inverted bars icon"></i>
<div class="ui menu">
% if settings.general.getboolean('use_sonarr'):
<a class="item" href="{{base_url}}series">
<i class="play icon"></i>
Series
</a>
% end
% if settings.general.getboolean('use_radarr'):
<a class="item" href="{{base_url}}movies">
<i class="film icon"></i>
Movies
</a>
% end
<a class="item" href="{{base_url}}history">
<i class="wait icon"></i>
History
</a>
<a class="item" href="{{base_url}}wanted">
<i class="warning sign icon"></i>
<span style="margin-right: 1em;">Wanted</span>
% if settings.general.getboolean('use_sonarr') and wanted_series > 0:
<div class="ui tiny yellow label">
{{wanted_series}}
</div>
% end
% if settings.general.getboolean('use_radarr') and wanted_movies > 0:
<div class="ui tiny green label">
{{wanted_movies}}
</div>
% end
</a>
<a class="item" href="{{base_url}}settings">
<i class="settings icon"></i>
Settings
</a>
<a class="item" href="{{base_url}}system">
<i class="laptop icon">
% if throttled_providers_count:
<div class="floating ui tiny yellow label" style="left:90% !important;top:0.5em !important;">
{{throttled_providers_count}}
</div>
% end
</i>
System
</a>
<a id="donate" class="item" href="https://beerpay.io/morpheus65535/bazarr">
<i class="red heart icon"></i>
Donate
</a>
</div>
</div>
</div>
</div>
</div>
</div>
% restart_required = database.execute("SELECT configured, updated FROM system")
% for item in restart_required:
% restart_required = item
% break
% end
% if restart_required['updated'] == '1' and restart_required['configured'] == '1':
<div class='ui center aligned grid'><div class='fifteen wide column'><div class="ui red message">Bazarr Needs To Be Restarted To Apply The Last Update & Changes To General Settings. Click <a href=# id="restart_link">Here</a> To Restart.</div></div></div>
% elif restart_required['updated'] == '1':
<div class='ui center aligned grid'><div class='fifteen wide column'><div class="ui red message">Bazarr Needs To Be Restarted To Apply Changes To The Last Update. Click <a href=# id="restart_link">Here</a> To Restart.</div></div></div>
% elif restart_required['configured'] == '1':
<div class='ui center aligned grid'><div class='fifteen wide column'><div class="ui red message">Bazarr Needs To Be Restarted To Apply Changes To General Settings. Click <a href=# id="restart_link">Here</a> To Restart.</div></div></div>
% end
% from six import PY2
% import datetime
% if PY2:
<div class='ui left aligned grid'>
<div class='fluid column'>
<div class="ui yellow icon message">
<i class="python icon"></i>
<div class="content">
<div class="header">Python deprecation warning</div>
Bazarr is now compatible with Python 3.6 and newer. You should upgrade Python as we'll drop support for Python 2.7.x by the end of 2019.
<div class="ui bulleted list">
% if os.name == 'posix':
<div class="item">If you are running under Docker, don't worry, we'll take care of this for you. Just pull the new image.</div>
% end
% if os.name == 'nt':
<div class="item">If you have installed using the Windows Installer, we'll provide a new installer soon.</div>
% end
<div class="item">If you are running from source, it's up to you to install Python 3 and use it to run Bazarr.</div>
</div>
</div>
</div>
</div>
</div>
% end
}
</style>
</head>
<body>
% from get_args import args
% from get_providers import update_throttled_provider
% update_throttled_provider()
% import ast
% import datetime
% import os
% from database import database
% import operator
% from config import settings
% from functools import reduce
%if settings.sonarr.getboolean('only_monitored'):
% monitored_only_query_string_sonarr = ' AND monitored = "True"'
%else:
% monitored_only_query_string_sonarr = ""
%end
%if settings.radarr.getboolean('only_monitored'):
% monitored_only_query_string_radarr = ' AND monitored = "True"'
%else:
% monitored_only_query_string_radarr = ""
%end
% wanted_series = database.execute("SELECT COUNT(*) as count FROM table_episodes WHERE missing_subtitles != '[]'" +
monitored_only_query_string_sonarr, only_one=True)['count']
% wanted_movies = database.execute("SELECT COUNT(*) as count FROM table_movies WHERE missing_subtitles != '[]'" +
monitored_only_query_string_radarr, only_one=True)['count']
% from get_providers import list_throttled_providers
{% set throttled_providers_count = settings.general.throtteled_providers|length %}
<div id="divmenu" class="ui container">
<div class="ui grid">
<div class="three wide column">
<div class="ui compact segment menu_segment">
<a href="{{ base_url }}"><img class="logo" src="{{ base_url }}static/logo128.png"></a>
</div>
</div>
<div class="ten wide right aligned compact column">
<div id="button_menu" class="ui center aligned segment menu_segment" hidden="hidden">
<div class="ui inverted compact borderless labeled icon massive menu menu_segment">
{% if settings.general.getboolean('use_sonarr') %}
<a class="item" href="{{ base_url }}series">
<i class="play icon"></i>
Series
</a>
{% endif %}
{% if settings.general.getboolean('use_radarr') %}
<a class="item" href="{{ base_url }}movies">
<i class="film icon"></i>
Movies
</a>
{% endif %}
<a class="item" href="{{ base_url }}history">
<i class="wait icon"></i>
History
</a>
<a class="item" href="{{ base_url }}wanted">
<i class="warning sign icon">
{% if settings.general.getboolean('use_sonarr') and wanted_series > 0 %}
<div id="wanted_series" class="floating ui tiny yellow label"
style="left:90% !important;top:0.5em !important;">
{{ wanted_series }}
</div>
{% endif %}
{% if settings.general.getboolean('use_radarr') and wanted_movies > 0 %}
<div id="wanted_movies" class="floating ui tiny green label"
style="left:90% !important;top:3em !important;">
{{ wanted_movies }}
</div>
{% endif %}
</i>
Wanted
</a>
<a class="item" href="{{ base_url }}settings">
<i class="settings icon"></i>
Settings
</a>
<a class="item" href="{{ base_url }}system">
<i class="laptop icon">
{% if throttled_providers_count %}
<div class="floating ui tiny yellow label"
style="left:90% !important;top:0.5em !important;">
{{ throttled_providers_count }}
</div>
{% endif %}
</i>
System
</a>
<a id="donate" class="item" href="https://beerpay.io/morpheus65535/bazarr">
<i class="red heart icon"></i>
Donate
</a>
</div>
</div>
<div class="ui center aligned segment menu_segment">
<div class="ui grid">
<div id="search_column" class="centered column">
<div class="ui fluid search">
<div class="ui left icon fluid input">
<input class="prompt" type="text" placeholder="Search in your library">
<i class="searchicon search icon"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="three wide right aligned column">
<div id="dropdown_menu" class="ui segment menu_segment" hidden="hidden">
<div id="icon_menu" class="ui compact tiny icon menu">
<div id="dropdown_menu_button" class="ui floating right dropdown item">
<i class="inverted bars icon"></i>
<div class="ui menu">
{% if settings.general.getboolean('use_sonarr') %}
<a class="item" href="{{ base_url }}series">
<i class="play icon"></i>
Series
</a>
{% endif %}
{% if settings.general.getboolean('use_radarr') %}
<a class="item" href="{{ base_url }}movies">
<i class="film icon"></i>
Movies
</a>
{% endif %}
<a class="item" href="{{ base_url }}history">
<i class="wait icon"></i>
History
</a>
<a class="item" href="{{ base_url }}wanted">
<i class="warning sign icon"></i>
<span style="margin-right: 1em;">Wanted</span>
{% if settings.general.getboolean('use_sonarr') and wanted_series > 0 %}
<div class="ui tiny yellow label">
{{ wanted_series }}
</div>
{% endif %}
{% if settings.general.getboolean('use_radarr') and wanted_movies > 0 %}
<div class="ui tiny green label">
{{ wanted_movies }}
</div>
{% endif %}
</a>
<a class="item" href="{{ base_url }}settings">
<i class="settings icon"></i>
Settings
</a>
<a class="item" href="{{ base_url }}system">
<i class="laptop icon">
{% if throttled_providers_count %}
<div class="floating ui tiny yellow label"
style="left:90% !important;top:0.5em !important;">
{{ throttled_providers_count }}
</div>
{% endif %}
</i>
System
</a>
<a id="donate" class="item" href="https://beerpay.io/morpheus65535/bazarr">
<i class="red heart icon"></i>
Donate
</a>
</div>
</div>
</div>
</div>
</div>
</div>
{% if update_required == '1' and restart_required == '1' %}
<div class='ui center aligned grid'>
<div class='fifteen wide column'>
<div class="ui red message">Bazarr Needs To Be Restarted To Apply The Last Update & Changes To General
Settings. Click <a href=# id="restart_link">Here</a> To Restart.
</div>
</div>
</div>
{% elif updaterequired == '1' %}
<div class='ui center aligned grid'>
<div class='fifteen wide column'>
<div class="ui red message">Bazarr Needs To Be Restarted To Apply Changes To The Last Update. Click <a
href=# id="restart_link">Here</a> To Restart.
</div>
</div>
</div>
{% elif restart_required == '1' %}
<div class='ui center aligned grid'>
<div class='fifteen wide column'>
<div class="ui red message">Bazarr Needs To Be Restarted To Apply Changes To General Settings. Click <a
href=# id="restart_link">Here</a> To Restart.
</div>
</div>
</div>
</body>
{% endif %}
% from six import PY2
% import datetime
% if PY2:
<div class='ui left aligned grid'>
<div class='fluid column'>
<div class="ui yellow icon message">
<i class="python icon"></i>
<div class="content">
<div class="header">Python deprecation warning</div>
Bazarr is now compatible with Python 3.6 and newer. You should upgrade Python as we'll drop support
for Python 2.7.x by the end of 2019.
<div class="ui bulleted list">
% if os.name == 'posix':
<div class="item">If you are running under Docker, don't worry, we'll take care of this for you.
Just pull the new image.
</div>
% end
% if os.name == 'nt':
<div class="item">If you have installed using the Windows Installer, we'll provide a new
installer soon.
</div>
% end
<div class="item">If you are running from source, it's up to you to install Python 3 and use it
to run Bazarr.
</div>
</div>
</div>
</div>
</div>
</div>
% end
</div>
</body>
</html>
<script>
$('.ui.dropdown').dropdown();
$('.ui.dropdown').dropdown();
$('.ui.search')
.search({
apiSettings: {
url: '{{base_url}}search_json/{query}',
onResponse: function(results) {
onResponse: function (results) {
const response = {
results : []
results: []
};
$.each(results.items, function(index, item) {
$.each(results.items, function (index, item) {
response.results.push({
title : item.name,
url : item.url
title: item.name,
url: item.url
});
});
return response;
}
},
minCharacters : 2
minCharacters: 2
})
;
if (window.location.href.indexOf("episodes") > -1) {
$('.menu_segment').css('background', 'rgba(0, 0, 0, 0.8)');
$('.menu_segment').css('border-color', '#000000');
$('#divmenu').css('background', 'rgba(0, 0, 0, 0.8)');
$('#divmenu').css('box-shadow', '0 0 5px 5px #000000');
}
else if (window.location.href.indexOf("movie/") > -1) {
$('.menu_segment').css('background', 'rgba(0, 0, 0, 0.9)');
$('.menu_segment').css('border-color', '#000000');
$('#divmenu').css('background', 'rgba(0, 0, 0, 0.8)');
$('#divmenu').css('box-shadow', '0 0 5px 5px #000000');
$('.menu_segment').css('background', 'rgba(0, 0, 0, 0.8)');
$('.menu_segment').css('border-color', '#000000');
$('#divmenu').css('background', 'rgba(0, 0, 0, 0.8)');
$('#divmenu').css('box-shadow', '0 0 5px 5px #000000');
} else if (window.location.href.indexOf("movie/") > -1) {
$('.menu_segment').css('background', 'rgba(0, 0, 0, 0.9)');
$('.menu_segment').css('border-color', '#000000');
$('#divmenu').css('background', 'rgba(0, 0, 0, 0.8)');
$('#divmenu').css('box-shadow', '0 0 5px 5px #000000');
} else {
$('.menu_segment').css('background', '#272727');
$('.menu_segment').css('border-color', '#272727');
$('#divmenu').css('background', '#272727');
}
else {
$('.menu_segment').css('background', '#272727');
$('.menu_segment').css('border-color', '#272727');
$('#divmenu').css('background', '#272727');
$('#restart_link').on('click', function () {
$('#loader_text').text("Bazarr is restarting. Please Wait...");
$.ajax({
url: {{url_for('restart')}},
async: true,
error: (function () {
setTimeout(function () {
setInterval(ping, 2000);
}, 8000);
})
})
});
function ping() {
$.ajax({
url: "{{url_for('redirect_root')}}",
success: function (result) {
window.location.href = "{{url_for('redirect_root')}}";
}
});
}
$('#restart_link').on('click', function(){
$('#loader_text').text("Bazarr is restarting. Please Wait...");
$.ajax({
url: {{url_for('restart')}},
async: true,
error: (function(){
setTimeout(function(){ setInterval(ping, 2000); },8000);
})
})
});
function ping() {
$.ajax({
url: {{url_for('redirect_root')}},
success: function(result) {
window.location.href= {{url_for('redirect_root')}};
}
});
}
$( window ).on('resize', function () {
if($(window).width() < 1024){
$('#button_menu').hide();
$('#dropdown_menu').show();
$('#search_column').removeClass('ten wide');
} else {
$('#dropdown_menu').hide();
$('#button_menu').show();
$('#search_column').addClass('ten wide');
}
}).resize();
var url_notifications = location.protocol +"//" + window.location.host + "{{base_url}}notifications";
var notificationTimeout;
var timeout;
var killer;
var item = {};
var length = {};
function doNotificationsAjax() {
$(window).on('resize', function () {
if ($(window).width() < 1024) {
$('#button_menu').hide();
$('#dropdown_menu').show();
$('#search_column').removeClass('ten wide');
} else {
$('#dropdown_menu').hide();
$('#button_menu').show();
$('#search_column').addClass('ten wide');
}
}).resize();
var url_notifications = location.protocol + "//" + window.location.host + "{{base_url}}notifications";
var notificationTimeout;
var timeout;
var killer;
var item = {};
var length = {};
function doNotificationsAjax() {
$.ajax({
url: {{url_for('notifications')}},
url: "{{url_for('notifications')}}",
success: function (data) {
if (data !== "") {
data = JSON.parse(data);
var msg = data[0];
var type = data[1];
var duration = data[2];
var button = data[3];
var queue = data[4];
var item = data[5];
var length = data[6];
if (length === 0) {
var message = msg;
} else {
var message = msg + '<p><div class="ui disabled progress notification_progress" data-value=' + item + ' data-total=' + length + ' style="margin-bottom: -0.25em"><div class="bar"><div class="progress"></div></div></div>'
}
if (data !== "") {
data = JSON.parse(data);
var msg = data[0];
var type = data[1];
var duration = data[2];
var button = data[3];
var queue = data[4];
var item = data[5];
var length = data[6];
if (length === 0) {
var message = msg;
} else {
var message = msg + '<p><div class="ui disabled progress notification_progress" data-value=' + item + ' data-total=' + length + ' style="margin-bottom: -0.25em"><div class="bar"><div class="progress"></div></div></div>'
}
if (duration === 'temporary') {
timeout = 3000;
@ -362,79 +401,85 @@
} else if (duration === 'long') {
timeout = 15000;
killer = queue;
} else {
timeout = false;
killer = false;
}
if (button === 'refresh') {
button = [ Noty.button('Refresh', 'ui tiny primary button', function () { window.location.reload() }) ];
} else if (button === 'restart') {
// to be completed
button = [ Noty.button('Restart', 'ui tiny primary button', function () { alert('Restart Not Implemented Yet!') }) ];
} else {
button = [];
}
new Noty({
text: message,
progressBar: false,
animation: {
open: null,
close: null
},
type: type,
layout: 'bottomRight',
theme: 'semanticui',
queue: queue,
timeout: timeout,
killer: killer,
buttons: button,
force: false
}).show();
$('.notification_progress').progress({
duration : 0,
autoSuccess: false,
} else {
timeout = false;
killer = false;
}
if (button === 'refresh') {
button = [Noty.button('Refresh', 'ui tiny primary button', function () {
window.location.reload()
})];
} else if (button === 'restart') {
// to be completed
button = [Noty.button('Restart', 'ui tiny primary button', function () {
alert('Restart Not Implemented Yet!')
})];
} else {
button = [];
}
new Noty({
text: message,
progressBar: false,
animation: {
open: null,
close: null
},
type: type,
layout: 'bottomRight',
theme: 'semanticui',
queue: queue,
timeout: timeout,
killer: killer,
buttons: button,
force: false
}).show();
$('.notification_progress').progress({
duration: 0,
autoSuccess: false,
label: 'ratio',
text: {
ratio: '{value} / {total}'
}
});
}
});
}
},
complete: function (data) {
// Schedule the next
if (data.responseText !== "") {
notificationTimeout = setTimeout(doNotificationsAjax, 100);
} else {
notificationTimeout = setTimeout(doNotificationsAjax, 5000);
}
},
error: function () {
if (data.responseText !== "") {
notificationTimeout = setTimeout(doNotificationsAjax, 100);
} else {
notificationTimeout = setTimeout(doNotificationsAjax, 5000);
}
}
},
error: function () {
notificationTimeout = setTimeout(doNotificationsAjax, 5000);
}
});
}
notificationTimeout = setTimeout(doNotificationsAjax, 1000);
var tasksTimeout;
function doTasksAjax() {
var tasksTimeout;
function doTasksAjax() {
$.ajax({
url: {{url_for('running_tasks_list')}},
url: "{{url_for('running_tasks_list')}}",
dataType: 'json',
success: function (data) {
$('#tasks > tbody > tr').each(function() {
if ($.inArray($(this).attr('id'), data['tasks']) > -1) {
$(this).find('td:last').find('div:first').addClass('disabled');
$(this).find('td:last').find('div:first').find('i:first').addClass('loading');
} else {
$(this).find('td:last').find('div:first').removeClass('disabled');
$(this).find('td:last').find('div:first').find('i:first').removeClass('loading');
}
});
if ($.inArray('wanted_search_missing_subtitles', data['tasks']) > -1) {
$('#tasks > tbody > tr').each(function () {
if ($.inArray($(this).attr('id'), data['tasks']) > -1) {
$(this).find('td:last').find('div:first').addClass('disabled');
$(this).find('td:last').find('div:first').find('i:first').addClass('loading');
} else {
$(this).find('td:last').find('div:first').removeClass('disabled');
$(this).find('td:last').find('div:first').find('i:first').removeClass('loading');
}
});
if ($.inArray('wanted_search_missing_subtitles', data['tasks']) > -1) {
$('#wanted_search_missing_subtitles').addClass('disabled');
$('#wanted_search_missing_subtitles_movies').addClass('disabled');
$('#wanted_search_missing_subtitles').find('i:first').addClass('loading');
@ -446,8 +491,9 @@
$('#wanted_search_missing_subtitles_movies').find('i:first').removeClass('loading');
}
%if 'no' in locals():
if ($.inArray('search_missing_subtitles_{{no}}', data['tasks']) > -1) {
%
if 'no' in locals():
if ($.inArray('search_missing_subtitles_{{no}}', data['tasks']) > -1) {
$('#search_missing_subtitles').addClass('disabled');
$('#search_missing_subtitles').find('i:first').addClass('loading');
} else {
@ -455,14 +501,15 @@
$('#search_missing_subtitles').find('i:first').removeClass('loading');
}
if ($.inArray('search_missing_subtitles_movie_{{no}}', data['tasks']) > -1) {
if ($.inArray('search_missing_subtitles_movie_{{no}}', data['tasks']) > -1) {
$('#search_missing_subtitles_movie').addClass('disabled');
$('#search_missing_subtitles_movie').find('i:first').addClass('loading');
} else {
$('#search_missing_subtitles_movie').removeClass('disabled');
$('#search_missing_subtitles_movie').find('i:first').removeClass('loading');
}
%end
%
end
},
complete: function (data) {
// Schedule the next
@ -470,10 +517,11 @@
}
});
}
tasksTimeout = setTimeout(doTasksAjax, 500);
$(window).bind('beforeunload', function(){
clearTimeout(tasksTimeout);
clearTimeout(notificationTimeout);
});
$(window).bind('beforeunload', function () {
clearTimeout(tasksTimeout);
clearTimeout(notificationTimeout);
});
</script>

@ -78,7 +78,7 @@
</div>
</form>
</div>
{% include 'footer.tpl' %}
{% include 'footer.html' %}
</body>
</html>

@ -137,7 +137,7 @@
</div>
</form>
</div>
{% include 'footer.tpl' %}
{% include 'footer.html' %}
</body>
</html>

Loading…
Cancel
Save