Merge branch 'release/0.5.0'
42
CHANGES.md
|
@ -1,3 +1,45 @@
|
|||
### 0.5.0 (2014-12-21 11:40:00 UTC)
|
||||
|
||||
* Fix searches freezing due to unescaped ignored or required words
|
||||
* Add failed database to unit tests tear down function
|
||||
* Fix purging of database files in tear down function during unit tests
|
||||
* Add ability to auto focus Search Show box on Home page and control this option via General Config/Interface
|
||||
* Change some provider images. Add a few new images
|
||||
* Remove redundant Coming Eps template code used in the old UI
|
||||
* Change update Plex notifier (port from SickBeard)
|
||||
* Change Plex notifications to allow authenticated library updates (port from mmccurdy07/Sick-Beard)
|
||||
* Change Config/Notifications/Plex logo and description (adapted port from mmccurdy07/Sick-Beard)
|
||||
* Add ability for CSS/JS to target a specific page and layout
|
||||
* Remove legacy sickbeard updater and build automation code
|
||||
* Fix multiple instances of SG being able to start
|
||||
* Fix garbled text appearing during startup in console
|
||||
* Fix startup code order and general re-factoring (adapted from midgetspy/Sick-Beard)
|
||||
* Add database migration code
|
||||
* Change KickassTorrents provider URLs
|
||||
* Fix missing Content-Type headers for posters and banners
|
||||
* Remove config Backup & Restore
|
||||
* Fix article removal for sorting on Display Show, and API pages
|
||||
* Fix visual positioning of sprites on Config page
|
||||
* Fix missing navbar gradients for all browsers
|
||||
* Update qTip2 to v2.2.1
|
||||
* Overhaul all Add Show pages
|
||||
* Fix Display Show next/previous when show list is split
|
||||
* Change Display Show next/previous when show list is not split to loop around
|
||||
* Fix SQL statements that have dynamic table names to use proper syntax
|
||||
* Fix port checking code preventing startup directly after a SG restart
|
||||
* Add a link from the footer number of snatched to episode snatched overview page. The link to the
|
||||
Episode Overview page is available on all pages except on the Episode Overview page
|
||||
* Change the default state for all check boxes on the Episode Overview page to not checked
|
||||
* Add validation to Go button to ensure at least one item is checked on Episode Overview page
|
||||
* Add highlight to current status text in header on Episode Overview page
|
||||
* Fix table alignment on homepage
|
||||
* Fix duplicate entries in cache database
|
||||
* Fix network sorting on home page
|
||||
* Fix restart issue
|
||||
* Fix to use new TorrentDay URLs
|
||||
* Fix typo in menu item Manage/Update XBMC
|
||||
|
||||
|
||||
### 0.4.0 (2014-12-04 10:50:00 UTC)
|
||||
|
||||
* Change footer stats to not add newlines when copy/pasting from them
|
||||
|
|
77
SickBeard.py
|
@ -226,13 +226,13 @@ class SickGear(object):
|
|||
if self.runAsDaemon:
|
||||
pid_dir = os.path.dirname(self.PIDFILE)
|
||||
if not os.access(pid_dir, os.F_OK):
|
||||
sys.exit("PID dir: " + pid_dir + " doesn't exist. Exiting.")
|
||||
sys.exit(u"PID dir: %s doesn't exist. Exiting." % pid_dir)
|
||||
if not os.access(pid_dir, os.W_OK):
|
||||
sys.exit("PID dir: " + pid_dir + " must be writable (write permissions). Exiting.")
|
||||
sys.exit(u'PID dir: %s must be writable (write permissions). Exiting.' % pid_dir)
|
||||
|
||||
else:
|
||||
if self.consoleLogging:
|
||||
sys.stdout.write("Not running in daemon mode. PID file creation disabled.\n")
|
||||
print u'Not running in daemon mode. PID file creation disabled'
|
||||
|
||||
self.CREATEPID = False
|
||||
|
||||
|
@ -244,34 +244,28 @@ class SickGear(object):
|
|||
if not os.access(sickbeard.DATA_DIR, os.F_OK):
|
||||
try:
|
||||
os.makedirs(sickbeard.DATA_DIR, 0744)
|
||||
except os.error, e:
|
||||
raise SystemExit("Unable to create datadir '" + sickbeard.DATA_DIR + "'")
|
||||
except os.error:
|
||||
sys.exit(u'Unable to create data directory: %s + Exiting.' % sickbeard.DATA_DIR)
|
||||
|
||||
# Make sure we can write to the data dir
|
||||
if not os.access(sickbeard.DATA_DIR, os.W_OK):
|
||||
raise SystemExit("Datadir must be writeable '" + sickbeard.DATA_DIR + "'")
|
||||
sys.exit(u'Data directory: %s must be writable (write permissions). Exiting.' % sickbeard.DATA_DIR)
|
||||
|
||||
# Make sure we can write to the config file
|
||||
if not os.access(sickbeard.CONFIG_FILE, os.W_OK):
|
||||
if os.path.isfile(sickbeard.CONFIG_FILE):
|
||||
raise SystemExit("Config file '" + sickbeard.CONFIG_FILE + "' must be writeable.")
|
||||
sys.exit(u'Config file: %s must be writeable (write permissions). Exiting.' % sickbeard.CONFIG_FILE)
|
||||
elif not os.access(os.path.dirname(sickbeard.CONFIG_FILE), os.W_OK):
|
||||
raise SystemExit(
|
||||
"Config file root dir '" + os.path.dirname(sickbeard.CONFIG_FILE) + "' must be writeable.")
|
||||
|
||||
# Check if we need to perform a restore first
|
||||
restoreDir = os.path.join(sickbeard.DATA_DIR, 'restore')
|
||||
if os.path.exists(restoreDir):
|
||||
if self.restore(restoreDir, sickbeard.DATA_DIR):
|
||||
logger.log(u"Restore successful...")
|
||||
else:
|
||||
logger.log(u"Restore FAILED!", logger.ERROR)
|
||||
|
||||
sys.exit(u'Config file directory: %s must be writeable (write permissions). Exiting'
|
||||
% os.path.dirname(sickbeard.CONFIG_FILE))
|
||||
os.chdir(sickbeard.DATA_DIR)
|
||||
|
||||
if self.consoleLogging:
|
||||
print u'Starting up SickGear from %s' % sickbeard.CONFIG_FILE
|
||||
|
||||
# Load the config and publish it to the sickbeard package
|
||||
if not os.path.isfile(sickbeard.CONFIG_FILE):
|
||||
logger.log(u"Unable to find '" + sickbeard.CONFIG_FILE + "' , all settings will be default!", logger.ERROR)
|
||||
print u'Unable to find "%s", all settings will be default!' % sickbeard.CONFIG_FILE
|
||||
|
||||
sickbeard.CFG = ConfigObj(sickbeard.CONFIG_FILE)
|
||||
|
||||
|
@ -279,15 +273,13 @@ class SickGear(object):
|
|||
|
||||
if CUR_DB_VERSION > 0:
|
||||
if CUR_DB_VERSION < MIN_DB_VERSION:
|
||||
raise SystemExit("Your database version (" + str(
|
||||
CUR_DB_VERSION) + ") is too old to migrate from with this version of SickGear (" + str(
|
||||
MIN_DB_VERSION) + ").\n" + \
|
||||
"Upgrade using a previous version of SB first, or start with no database file to begin fresh.")
|
||||
print u'Your database version (%s) is too old to migrate from with this version of SickGear' \
|
||||
% CUR_DB_VERSION
|
||||
sys.exit(u'Upgrade using a previous version of SG first, or start with no database file to begin fresh')
|
||||
if CUR_DB_VERSION > MAX_DB_VERSION:
|
||||
raise SystemExit("Your database version (" + str(
|
||||
CUR_DB_VERSION) + ") has been incremented past what this version of SickGear supports (" + str(
|
||||
MAX_DB_VERSION) + ").\n" + \
|
||||
"If you have used other forks of SB, your database may be unusable due to their modifications.")
|
||||
print u'Your database version (%s) has been incremented past what this version of SickGear supports' \
|
||||
% CUR_DB_VERSION
|
||||
sys.exit(u'If you have used other forks of SB, your database may be unusable due to their modifications')
|
||||
|
||||
# Initialize the config and our threads
|
||||
sickbeard.initialize(consoleLogging=self.consoleLogging)
|
||||
|
@ -298,9 +290,6 @@ class SickGear(object):
|
|||
# Get PID
|
||||
sickbeard.PID = os.getpid()
|
||||
|
||||
# Build from the DB to start with
|
||||
self.loadShowsFromDB()
|
||||
|
||||
if self.forcedPort:
|
||||
logger.log(u"Forcing web server to port " + str(self.forcedPort))
|
||||
self.startPort = self.forcedPort
|
||||
|
@ -339,9 +328,12 @@ class SickGear(object):
|
|||
|
||||
# start web server
|
||||
try:
|
||||
# used to check if existing SG instances have been started
|
||||
sickbeard.helpers.wait_for_free_port(self.web_options['host'], self.web_options['port'])
|
||||
|
||||
self.webserver = WebServer(self.web_options)
|
||||
self.webserver.start()
|
||||
except IOError:
|
||||
except Exception:
|
||||
logger.log(u"Unable to start web server, is something else running on port %d?" % self.startPort,
|
||||
logger.ERROR)
|
||||
if sickbeard.LAUNCH_BROWSER and not self.runAsDaemon:
|
||||
|
@ -349,8 +341,16 @@ class SickGear(object):
|
|||
sickbeard.launchBrowser(self.startPort)
|
||||
os._exit(1)
|
||||
|
||||
if self.consoleLogging:
|
||||
print "Starting up SickGear " + sickbeard.BRANCH + " from " + sickbeard.CONFIG_FILE
|
||||
# Check if we need to perform a restore first
|
||||
restoreDir = os.path.join(sickbeard.DATA_DIR, 'restore')
|
||||
if os.path.exists(restoreDir):
|
||||
if self.restore(restoreDir, sickbeard.DATA_DIR):
|
||||
logger.log(u"Restore successful...")
|
||||
else:
|
||||
logger.log_error_and_exit(u"Restore FAILED!", logger.ERROR)
|
||||
|
||||
# Build from the DB to start with
|
||||
self.loadShowsFromDB()
|
||||
|
||||
# Fire up all our threads
|
||||
sickbeard.start()
|
||||
|
@ -503,17 +503,6 @@ class SickGear(object):
|
|||
|
||||
if install_type in ('git', 'source'):
|
||||
popen_list = [sys.executable, sickbeard.MY_FULLNAME]
|
||||
elif install_type == 'win':
|
||||
if hasattr(sys, 'frozen'):
|
||||
# c:\dir\to\updater.exe 12345 c:\dir\to\sickbeard.exe
|
||||
popen_list = [os.path.join(sickbeard.PROG_DIR, 'updater.exe'), str(sickbeard.PID),
|
||||
sys.executable]
|
||||
else:
|
||||
logger.log(u"Unknown SB launch method, please file a bug report about this", logger.ERROR)
|
||||
popen_list = [sys.executable, os.path.join(sickbeard.PROG_DIR, 'updater.py'),
|
||||
str(sickbeard.PID),
|
||||
sys.executable,
|
||||
sickbeard.MY_FULLNAME]
|
||||
|
||||
if popen_list:
|
||||
popen_list += sickbeard.MY_ARGS
|
||||
|
|
24
TODO.txt
|
@ -1,24 +0,0 @@
|
|||
2014-10-02
|
||||
-Move the sql from the *.tmpl files
|
||||
-Add anidb indexer
|
||||
-Add supplemental data from anidb during postprocessing
|
||||
-Fix grabbing non-propers as propers for certain air-by-date shows
|
||||
-Add prefer torrents/usenet and allow custom delay between grabs from torrents/usenet
|
||||
-Better postprocessing handling for torrents
|
||||
|
||||
2014-10-07
|
||||
-Add release groups/require words/ignore words to add show page
|
||||
-Add 'add show and add another show' button to add show page
|
||||
-Change the hardcoded global ignore words to optional
|
||||
|
||||
2014-10-08
|
||||
-Add login page for http auth as opposed to browser dialog box
|
||||
|
||||
2014-10-13
|
||||
-Fix broken backlog
|
||||
-Fix season searches
|
||||
|
||||
2014-10-21
|
||||
-Remove qtip from config providers and go back to tab
|
||||
-Find out why superfish & supersubs js breaks provider sorting
|
||||
-Ability to save poster sorting and asc/desc in config
|
|
@ -171,11 +171,6 @@ inc_top.tmpl
|
|||
background: url("../images/ico/favicon-16x16.png") 0 0 no-repeat;
|
||||
}
|
||||
|
||||
[class^="icon16-"],
|
||||
[class*=" icon16-"] {
|
||||
background-image: url("../images/glyphicons-config.png");
|
||||
}
|
||||
|
||||
.ui-autocomplete-loading {
|
||||
background: white url("../images/loading16.gif") right center no-repeat;
|
||||
}
|
||||
|
@ -538,10 +533,6 @@ home.tmpl
|
|||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.search {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.ui-progressbar {
|
||||
height: 20px;
|
||||
line-height: 18px;
|
||||
|
@ -782,122 +773,38 @@ td.tvShow a:hover {
|
|||
/* =======================================================================
|
||||
home_addShows.tmpl
|
||||
========================================================================== */
|
||||
|
||||
#addShowPortal {
|
||||
width: 700px;
|
||||
padding: 10px 0;
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
#addShowPortal a {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
div.button {
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
div.buttontext {
|
||||
display: table-cell;
|
||||
padding-left: 20px;
|
||||
text-align: left;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
div.buttontext h3 {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
div.buttontext p {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.icon-addnewshow {
|
||||
background-image: url("../images/addshows/add-new32-white.png");
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.icon-addtrendingshow {
|
||||
background-image: url("../images/addshows/add-trending32-white.png");
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.icon-addrecommendedshow {
|
||||
background-image: url("../images/addshows/add-trakt32-white.png");
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.icon-addexistingshow {
|
||||
background-image: url("../images/addshows/add-existing32-white.png");
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
/* =======================================================================
|
||||
home_newShow.tmpl
|
||||
========================================================================== */
|
||||
#addShowForm, #recommendedShowsForm {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
#newShowPortal {
|
||||
width: 800px;
|
||||
padding: 10px 0;
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
#displayText {
|
||||
padding: 8px;
|
||||
overflow: hidden;
|
||||
font-size: 14px;
|
||||
background-color: #3d3d3d;
|
||||
border: 1px solid #111;
|
||||
}
|
||||
|
||||
#searchResults input[type="radio"] {
|
||||
vertical-align: -2px;
|
||||
background-color: rgb(17, 120, 179);
|
||||
border: 0;
|
||||
}
|
||||
|
||||
/* =======================================================================
|
||||
home_addExistingShow.tmpl
|
||||
========================================================================== */
|
||||
|
||||
.existingtabs {
|
||||
padding: 1em 1.4em;
|
||||
}
|
||||
|
||||
ul#rootDirStaticList {
|
||||
width: 90%;
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
ul#rootDirStaticList li {
|
||||
padding: 4px 5px 4px 5px;
|
||||
margin: 2px;
|
||||
list-style: none outside none;
|
||||
cursor: pointer;
|
||||
background: #3d3d3d;
|
||||
}
|
||||
|
||||
ul#rootDirStaticList li label {
|
||||
margin-top: 5px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
ul#rootDirStaticList li input[type="checkbox"] {
|
||||
vertical-align: -2px;
|
||||
}
|
||||
|
||||
/* =======================================================================
|
||||
home_trendingShows.tmpl
|
||||
========================================================================== */
|
||||
|
@ -1541,32 +1448,6 @@ select .selected {
|
|||
border-top: 1px dotted #666666;
|
||||
}
|
||||
|
||||
[class^="icon16-"], [class*=" icon16-"] {
|
||||
background-image: url("../images/glyphicons-config.png");
|
||||
background-repeat: no-repeat;
|
||||
display: inline-block;
|
||||
height: 16px;
|
||||
vertical-align: text-top;
|
||||
width: 16px;
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
.icon16-github {
|
||||
background-position: 0 0;
|
||||
}
|
||||
.icon16-mirc {
|
||||
background-position: -26px 0;
|
||||
}
|
||||
.icon16-sg {
|
||||
background-position: -52px 0;
|
||||
}
|
||||
.icon16-web {
|
||||
background-position: -78px 0;
|
||||
}
|
||||
.icon16-win {
|
||||
background-position: -104px 0;
|
||||
}
|
||||
|
||||
/* =======================================================================
|
||||
config_postProcessing.tmpl
|
||||
========================================================================== */
|
||||
|
@ -1869,11 +1750,6 @@ body {
|
|||
background-color: #222;
|
||||
}
|
||||
|
||||
html * {
|
||||
outline: 0 !important;
|
||||
}
|
||||
|
||||
|
||||
input[type="radio"] {
|
||||
margin: 2px 0px 0px;
|
||||
line-height: normal;
|
||||
|
@ -1897,8 +1773,12 @@ input, textarea, select, .uneditable-input {
|
|||
.navbar-default {
|
||||
background-color: #15528F;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#297AB8', endColorstr='#15528F');
|
||||
background: -webkit-gradient(linear, left top, left bottom, from(#297AB8), to(#15528F));
|
||||
background: -moz-linear-gradient(top, #297AB8, #15528F);
|
||||
background-image: -ms-linear-gradient(top, #297AB8 0%, #15528F 100%);
|
||||
background-image: -moz-linear-gradient(top, #297AB8 0%, #15528F 100%);
|
||||
background-image: -o-linear-gradient(top, #297AB8 0%, #15528F 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #297AB8), color-stop(1, #15528F));
|
||||
background-image: -webkit-linear-gradient(top, #297AB8 0%, #15528F 100%);
|
||||
background-image: linear-gradient(to bottom, #297AB8 0%, #15528F 100%);
|
||||
border-color: #3e3f3a;
|
||||
}
|
||||
|
||||
|
@ -2033,12 +1913,6 @@ fieldset[disabled] .navbar-default .btn-link:focus {
|
|||
color: #000000;
|
||||
}
|
||||
|
||||
.form-control-inline {
|
||||
min-width: 0;
|
||||
width: auto;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.btn {
|
||||
color: #fff;
|
||||
text-shadow: 0 1px 1px rgba(0, 0, 0, 0.75);
|
||||
|
@ -2083,7 +1957,6 @@ fieldset[disabled] .navbar-default .btn-link:focus {
|
|||
|
||||
.btn:hover {
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
background-color: #2672B6;
|
||||
*background-color: #2672B6;
|
||||
background-position: 0 -150px;
|
||||
|
@ -2116,8 +1989,7 @@ fieldset[disabled] .navbar-default .btn-link:focus {
|
|||
.btn.disabled,
|
||||
.btn[disabled] {
|
||||
cursor: default;
|
||||
background-color: #15528F;
|
||||
background-image: none;
|
||||
background: #15528F none;
|
||||
opacity: 0.65;
|
||||
filter: alpha(opacity=65);
|
||||
-webkit-box-shadow: none;
|
||||
|
@ -2125,19 +1997,6 @@ fieldset[disabled] .navbar-default .btn-link:focus {
|
|||
box-shadow: none;
|
||||
}
|
||||
|
||||
.btn-large {
|
||||
padding: 9px 14px;
|
||||
font-size: 15px;
|
||||
line-height: normal;
|
||||
-webkit-border-radius: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.btn-large [class^="icon-"] {
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
.btn-small {
|
||||
padding: 5px 9px;
|
||||
font-size: 11px;
|
||||
|
@ -2397,60 +2256,16 @@ pre {
|
|||
/* =======================================================================
|
||||
input sizing (for config pages)
|
||||
========================================================================== */
|
||||
#pickShow optgroup,
|
||||
#editAProvider optgroup {
|
||||
color: #eee;
|
||||
background-color: rgb(51, 51, 51);
|
||||
background-color: rgb(51, 51, 51);
|
||||
}
|
||||
|
||||
#pickShow optgroup option,
|
||||
#editAProvider optgroup option {
|
||||
color: #222;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
#config select {
|
||||
min-width: 0;
|
||||
width: auto;
|
||||
display: inline;
|
||||
margin-top: -4px;
|
||||
}
|
||||
|
||||
.btn-inline {
|
||||
margin-top: -3px;
|
||||
}
|
||||
|
||||
.input75 {
|
||||
width: 75px;
|
||||
margin-top: -4px;
|
||||
}
|
||||
|
||||
.input100 {
|
||||
width: 100px;
|
||||
margin-top: -4px;
|
||||
}
|
||||
|
||||
.input150 {
|
||||
width: 150px;
|
||||
margin-top: -4px;
|
||||
}
|
||||
|
||||
.input200 {
|
||||
width: 200px;
|
||||
margin-top: -4px;
|
||||
}
|
||||
|
||||
.input250 {
|
||||
width: 250px;
|
||||
margin-top: -4px;
|
||||
}
|
||||
|
||||
.input300 {
|
||||
width: 300px;
|
||||
margin-top: -4px;
|
||||
}
|
||||
|
||||
.input350 {
|
||||
width: 350px;
|
||||
margin-top: -4px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
/* =======================================================================
|
||||
|
@ -2529,92 +2344,31 @@ browser.css
|
|||
|
||||
|
||||
/* =======================================================================
|
||||
formWizard.css
|
||||
formWizard
|
||||
========================================================================== */
|
||||
|
||||
fieldset.sectionwrap {
|
||||
width: 800px;
|
||||
padding: 5px;
|
||||
text-align: left;
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
.step,
|
||||
legend.legendStep {
|
||||
color: #ffffff;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
div.stepsguide {
|
||||
margin-bottom: 15px;
|
||||
overflow: hidden;
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
div.stepsguide .step {
|
||||
float: left;
|
||||
width: 266px;
|
||||
font: bold 24px Arial;
|
||||
}
|
||||
|
||||
div.stepsguide .step p {
|
||||
margin: 12px 0;
|
||||
border-bottom: 4px solid #23AFDC;
|
||||
border-color: #23AFDC;
|
||||
}
|
||||
|
||||
div.stepsguide .disabledstep {
|
||||
color: #c4c4c4;
|
||||
.disabledstep {
|
||||
color: #646464;
|
||||
}
|
||||
|
||||
div.stepsguide .disabledstep p {
|
||||
border-bottom: 4px solid #1178B3;
|
||||
}
|
||||
|
||||
div.stepsguide .step .smalltext {
|
||||
font-size: 13px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
div.formpaginate {
|
||||
width: 800px;
|
||||
margin-top: 1em;
|
||||
overflow: auto;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
border-color: #1178B3;
|
||||
}
|
||||
|
||||
div.formpaginate .prev, div.formpaginate .next {
|
||||
padding: 3px 6px;
|
||||
color: #fff;
|
||||
cursor: hand;
|
||||
cursor: pointer;
|
||||
background: #2265A1;
|
||||
-webkit-border-radius: 6px;
|
||||
-moz-border-radius: 6px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.stepDiv {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
/* step 3 related */
|
||||
#customQuality {
|
||||
display: block;
|
||||
padding: 10px 0;
|
||||
overflow: hidden;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
#customQualityWrapper div.component-group-desc {
|
||||
float: left;
|
||||
width: 165px;
|
||||
}
|
||||
|
||||
#customQualityWrapper div.component-group-desc p {
|
||||
width: 85%;
|
||||
margin: .8em 0;
|
||||
font-size: 1.2em;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
|
@ -2660,10 +2414,7 @@ tablesorter.css
|
|||
|
||||
.tablesorter th,
|
||||
.tablesorter td {
|
||||
padding: 4px;
|
||||
border-top: #222 1px solid;
|
||||
border-left: #222 1px solid;
|
||||
vertical-align: middle;
|
||||
border-color: #222;
|
||||
}
|
||||
|
||||
/* remove extra border from left edge */
|
||||
|
@ -2674,31 +2425,22 @@ tablesorter.css
|
|||
|
||||
.tablesorter th {
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
text-shadow: -1px -1px 0 rgba(0,0,0,0.3);
|
||||
background-color: #15528F;
|
||||
border-collapse: collapse;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.tablesorter .tablesorter-header {
|
||||
padding: 4px 18px 4px 18px;
|
||||
cursor: pointer;
|
||||
background-image: url(data:image/gif;base64,R0lGODlhFQAJAIAAAP///////yH5BAEAAAEALAAAAAAVAAkAAAIXjI+AywnaYnhUMoqt3gZXPmVg94yJVQAAOw==);
|
||||
background-position: center right;
|
||||
background-repeat: no-repeat;
|
||||
background: #15528F url(data:image/gif;base64,R0lGODlhFQAJAIAAAP///////yH5BAEAAAEALAAAAAAVAAkAAAIXjI+AywnaYnhUMoqt3gZXPmVg94yJVQAAOw==) no-repeat center right;
|
||||
/* background-image: url(../images/tablesorter/bg.gif); */
|
||||
}
|
||||
|
||||
.tablesorter thead .tablesorter-headerDesc {
|
||||
background-color: #297AB8;
|
||||
background-image: url(data:image/gif;base64,R0lGODlhFQAEAIAAAP///////yH5BAEAAAEALAAAAAAVAAQAAAINjB+gC+jP2ptn0WskLQA7);
|
||||
background: #297AB8 url(data:image/gif;base64,R0lGODlhFQAEAIAAAP///////yH5BAEAAAEALAAAAAAVAAQAAAINjB+gC+jP2ptn0WskLQA7) no-repeat center right;
|
||||
/* background-image: url(../images/tablesorter/asc.gif); */
|
||||
}
|
||||
|
||||
.tablesorter thead .tablesorter-headerAsc {
|
||||
background-color: #297AB8;
|
||||
background-image: url(data:image/gif;base64,R0lGODlhFQAEAIAAAP///////yH5BAEAAAEALAAAAAAVAAQAAAINjI8Bya2wnINUMopZAQA7);
|
||||
background: #297AB8 url(data:image/gif;base64,R0lGODlhFQAEAIAAAP///////yH5BAEAAAEALAAAAAAVAAQAAAINjI8Bya2wnINUMopZAQA7) no-repeat center right;
|
||||
/* background-image: url(../images/tablesorter/desc.gif); */
|
||||
}
|
||||
|
||||
|
@ -2761,10 +2503,9 @@ thead.tablesorter-stickyHeader {
|
|||
|
||||
.tablesorter tfoot a {
|
||||
color:#fff;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#showListTable tbody {
|
||||
#showListTable tbody {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
|
@ -2903,6 +2644,25 @@ span.token-input-delete-token {
|
|||
margin: 0 1px;
|
||||
}
|
||||
|
||||
.step-one #searchResults .alt {
|
||||
background-color: rgb(40, 40, 40);
|
||||
}
|
||||
|
||||
#addRootDirTable td label .filepath,
|
||||
.grey-text {
|
||||
color:#999
|
||||
}
|
||||
|
||||
#newShowPortal #displayText .show-name,
|
||||
#newShowPortal #displayText .show-dest,
|
||||
#newShowPortal #displayText p {
|
||||
color: rgb(200, 200, 200)
|
||||
}
|
||||
|
||||
#newShowPortal #displayText .show-name,
|
||||
#newShowPortal #displayText .show-dest {
|
||||
color: rgb(255, 255, 255)
|
||||
}
|
||||
/* =======================================================================
|
||||
jquery.confirm.css
|
||||
========================================================================== */
|
||||
|
|
1
gui/slick/css/lib/jquery.qtip-2.0.1.min.css
vendored
3
gui/slick/css/lib/jquery.qtip-2.2.1.min.css
vendored
Normal file
|
@ -167,12 +167,7 @@ inc_top.tmpl
|
|||
background-image: url("../images/menu/menu-icons-white.png");
|
||||
}
|
||||
|
||||
[class^="icon16-"],
|
||||
[class*=" icon16-"] {
|
||||
background-image: url("../images/glyphicons-config.png");
|
||||
}
|
||||
|
||||
.ui-autocomplete-loading {
|
||||
.ui-autocomplete-loading {
|
||||
background: white url("../images/loading16.gif") right center no-repeat;
|
||||
}
|
||||
|
||||
|
@ -525,10 +520,6 @@ home.tmpl
|
|||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.search {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.ui-progressbar {
|
||||
height: 20px;
|
||||
line-height: 18px;
|
||||
|
@ -769,122 +760,38 @@ td.tvShow a:hover {
|
|||
/* =======================================================================
|
||||
home_addShows.tmpl
|
||||
========================================================================== */
|
||||
|
||||
#addShowPortal {
|
||||
width: 700px;
|
||||
padding: 10px 0;
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
#addShowPortal a {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
div.button {
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
div.buttontext {
|
||||
display: table-cell;
|
||||
padding-left: 20px;
|
||||
text-align: left;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
div.buttontext h3 {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
div.buttontext p {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.icon-addnewshow {
|
||||
background-image: url("../images/addshows/add-new32-black.png");
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.icon-addtrendingshow {
|
||||
background-image: url("../images/addshows/add-trending32-black.png");
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.icon-addrecommendedshow {
|
||||
background-image: url("../images/addshows/add-trakt32-black.png");
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.icon-addexistingshow {
|
||||
background-image: url("../images/addshows/add-existing32-black.png");
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
/* =======================================================================
|
||||
home_newShow.tmpl
|
||||
========================================================================== */
|
||||
#addShowForm, #recommendedShowsForm {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
#newShowPortal {
|
||||
width: 800px;
|
||||
padding: 10px 0;
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
#displayText {
|
||||
padding: 8px;
|
||||
overflow: hidden;
|
||||
font-size: 14px;
|
||||
background-color: #efefef;
|
||||
border: 1px solid #dfdede;
|
||||
}
|
||||
|
||||
#searchResults input[type="radio"] {
|
||||
vertical-align: -2px;
|
||||
border-color: #dfdede;
|
||||
}
|
||||
|
||||
/* =======================================================================
|
||||
home_addExistingShow.tmpl
|
||||
========================================================================== */
|
||||
|
||||
.existingtabs {
|
||||
padding: 1em 1.4em;
|
||||
}
|
||||
|
||||
ul#rootDirStaticList {
|
||||
width: 90%;
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
ul#rootDirStaticList li {
|
||||
padding: 4px 5px 4px 5px;
|
||||
margin: 2px;
|
||||
list-style: none outside none;
|
||||
cursor: pointer;
|
||||
background: url('../css/lib/images/ui-bg_highlight-soft_75_efefef_1x100.png') repeat-x scroll 50% 50% #EFEFEF;
|
||||
}
|
||||
|
||||
ul#rootDirStaticList li label {
|
||||
margin-top: 5px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
ul#rootDirStaticList li input[type="checkbox"] {
|
||||
vertical-align: -2px;
|
||||
}
|
||||
|
||||
/* =======================================================================
|
||||
home_trendingShows.tmpl
|
||||
========================================================================== */
|
||||
|
@ -1518,32 +1425,6 @@ select .selected {
|
|||
border-top: 1px dotted #666666;
|
||||
}
|
||||
|
||||
[class^="icon16-"], [class*=" icon16-"] {
|
||||
background-image: url("../images/glyphicons-config.png");
|
||||
background-repeat: no-repeat;
|
||||
display: inline-block;
|
||||
height: 16px;
|
||||
vertical-align: text-top;
|
||||
width: 16px;
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
.icon16-github {
|
||||
background-position: 0 0;
|
||||
}
|
||||
.icon16-mirc {
|
||||
background-position: -26px 0;
|
||||
}
|
||||
.icon16-sg {
|
||||
background-position: -52px 0;
|
||||
}
|
||||
.icon16-web {
|
||||
background-position: -78px 0;
|
||||
}
|
||||
.icon16-win {
|
||||
background-position: -104px 0;
|
||||
}
|
||||
|
||||
/* =======================================================================
|
||||
config_postProcessing.tmpl
|
||||
========================================================================== */
|
||||
|
@ -1848,10 +1729,6 @@ body {
|
|||
color: #000;
|
||||
}
|
||||
|
||||
html * {
|
||||
outline: 0 !important;
|
||||
}
|
||||
|
||||
input[type="radio"] {
|
||||
margin: 2px 0px 0px;
|
||||
line-height: normal;
|
||||
|
@ -1875,8 +1752,12 @@ input, textarea, select, .uneditable-input {
|
|||
.navbar-default {
|
||||
background-color: #333333;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#555555', endColorstr='#333333');
|
||||
background: -webkit-gradient(linear, left top, left bottom, from(#555), to(#333));
|
||||
background: -moz-linear-gradient(top, #555, #333);
|
||||
background-image: -ms-linear-gradient(top, #555555 0%, #333333 100%);
|
||||
background-image: -moz-linear-gradient(top, #555555 0%, #333333 100%);
|
||||
background-image: -o-linear-gradient(top, #555555 0%, #333333 100%);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #555555), color-stop(1, #333333));
|
||||
background-image: -webkit-linear-gradient(top, #555555 0%, #333333 100%);
|
||||
background-image: linear-gradient(to bottom, #555555 0%, #333333 100%);
|
||||
border-color: #3e3f3a;
|
||||
}
|
||||
|
||||
|
@ -2058,7 +1939,6 @@ fieldset[disabled] .navbar-default .btn-link:focus {
|
|||
|
||||
.btn:hover {
|
||||
color: #333333;
|
||||
text-decoration: none;
|
||||
background-color: #e6e6e6;
|
||||
*background-color: #d9d9d9;
|
||||
background-position: 0 -15px;
|
||||
|
@ -2089,8 +1969,7 @@ fieldset[disabled] .navbar-default .btn-link:focus {
|
|||
.btn.disabled,
|
||||
.btn[disabled] {
|
||||
cursor: default;
|
||||
background-color: #e6e6e6;
|
||||
background-image: none;
|
||||
background: #e6e6e6 none;
|
||||
opacity: 0.65;
|
||||
filter: alpha(opacity=65);
|
||||
-webkit-box-shadow: none;
|
||||
|
@ -2098,19 +1977,6 @@ fieldset[disabled] .navbar-default .btn-link:focus {
|
|||
box-shadow: none;
|
||||
}
|
||||
|
||||
.btn-large {
|
||||
padding: 9px 14px;
|
||||
font-size: 15px;
|
||||
line-height: normal;
|
||||
-webkit-border-radius: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.btn-large [class^="icon-"] {
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
.btn-small {
|
||||
padding: 5px 9px;
|
||||
font-size: 11px;
|
||||
|
@ -2370,60 +2236,16 @@ pre {
|
|||
/* =======================================================================
|
||||
input sizing (for config pages)
|
||||
========================================================================== */
|
||||
#pickShow optgroup,
|
||||
#editAProvider optgroup {
|
||||
color: #eee;
|
||||
background-color: #888;
|
||||
background-color: #888;
|
||||
}
|
||||
|
||||
#pickShow optgroup option,
|
||||
#editAProvider optgroup option {
|
||||
color: #222;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
#config select {
|
||||
min-width: 0;
|
||||
width: auto;
|
||||
display: inline;
|
||||
margin-top: -4px;
|
||||
}
|
||||
|
||||
.btn-inline {
|
||||
margin-top: -3px;
|
||||
}
|
||||
|
||||
.input75 {
|
||||
width: 75px;
|
||||
margin-top: -4px;
|
||||
}
|
||||
|
||||
.input100 {
|
||||
width: 100px;
|
||||
margin-top: -4px;
|
||||
}
|
||||
|
||||
.input150 {
|
||||
width: 150px;
|
||||
margin-top: -4px;
|
||||
}
|
||||
|
||||
.input200 {
|
||||
width: 200px;
|
||||
margin-top: -4px;
|
||||
}
|
||||
|
||||
.input250 {
|
||||
width: 250px;
|
||||
margin-top: -4px;
|
||||
}
|
||||
|
||||
.input300 {
|
||||
width: 300px;
|
||||
margin-top: -4px;
|
||||
}
|
||||
|
||||
.input350 {
|
||||
width: 350px;
|
||||
margin-top: -4px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
/* =======================================================================
|
||||
|
@ -2501,92 +2323,31 @@ browser.css
|
|||
|
||||
|
||||
/* =======================================================================
|
||||
formWizard.css
|
||||
formWizard
|
||||
========================================================================== */
|
||||
|
||||
fieldset.sectionwrap {
|
||||
width: 800px;
|
||||
padding: 5px;
|
||||
text-align: left;
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
.step,
|
||||
legend.legendStep {
|
||||
color: #57442b;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
div.stepsguide {
|
||||
margin-bottom: 15px;
|
||||
overflow: hidden;
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
div.stepsguide .step {
|
||||
float: left;
|
||||
width: 266px;
|
||||
font: bold 24px Arial;
|
||||
}
|
||||
|
||||
div.stepsguide .step p {
|
||||
margin: 12px 0;
|
||||
border-bottom: 4px solid #57442b;
|
||||
border-color: #57442b;
|
||||
}
|
||||
|
||||
div.stepsguide .disabledstep {
|
||||
.disabledstep {
|
||||
color: #c4c4c4;
|
||||
}
|
||||
|
||||
div.stepsguide .disabledstep p {
|
||||
border-bottom: 4px solid #8a775e;
|
||||
}
|
||||
|
||||
div.stepsguide .step .smalltext {
|
||||
font-size: 13px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
div.formpaginate {
|
||||
width: 800px;
|
||||
margin-top: 1em;
|
||||
overflow: auto;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
border-color: #8a775e;
|
||||
}
|
||||
|
||||
div.formpaginate .prev, div.formpaginate .next {
|
||||
padding: 3px 6px;
|
||||
color: #fff;
|
||||
cursor: hand;
|
||||
cursor: pointer;
|
||||
background: #57442b;
|
||||
-webkit-border-radius: 6px;
|
||||
-moz-border-radius: 6px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.stepDiv {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
/* step 3 related */
|
||||
#customQuality {
|
||||
display: block;
|
||||
padding: 10px 0;
|
||||
overflow: hidden;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
#customQualityWrapper div.component-group-desc {
|
||||
float: left;
|
||||
width: 165px;
|
||||
}
|
||||
|
||||
#customQualityWrapper div.component-group-desc p {
|
||||
width: 85%;
|
||||
margin: .8em 0;
|
||||
font-size: 1.2em;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
|
@ -2606,10 +2367,7 @@ tablesorter.css
|
|||
|
||||
.tablesorter th,
|
||||
.tablesorter td {
|
||||
padding: 4px;
|
||||
border-top: #fff 1px solid;
|
||||
border-left: #fff 1px solid;
|
||||
vertical-align: middle;
|
||||
border-color: #fff;
|
||||
}
|
||||
|
||||
/* remove extra border from left edge */
|
||||
|
@ -2620,32 +2378,23 @@ tablesorter.css
|
|||
|
||||
.tablesorter th {
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
text-shadow: -1px -1px 0 rgba(0,0,0,0.3);
|
||||
background-color: #333;
|
||||
border-collapse: collapse;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.tablesorter .tablesorter-header {
|
||||
padding: 4px 18px 4px 18px;
|
||||
cursor: pointer;
|
||||
background-image: url(data:image/gif;base64,R0lGODlhFQAJAIAAAP///////yH5BAEAAAEALAAAAAAVAAkAAAIXjI+AywnaYnhUMoqt3gZXPmVg94yJVQAAOw==);
|
||||
background-position: center right;
|
||||
background-repeat: no-repeat;
|
||||
background: #333 url(data:image/gif;base64,R0lGODlhFQAJAIAAAP///////yH5BAEAAAEALAAAAAAVAAkAAAIXjI+AywnaYnhUMoqt3gZXPmVg94yJVQAAOw==) no-repeat center right;
|
||||
/* background-image: url(../images/tablesorter/bg.gif); */
|
||||
}
|
||||
|
||||
.tablesorter thead .tablesorter-headerDesc {
|
||||
background-color: #555;
|
||||
background-image: url(data:image/gif;base64,R0lGODlhFQAEAIAAAP///////yH5BAEAAAEALAAAAAAVAAQAAAINjB+gC+jP2ptn0WskLQA7);
|
||||
background: #555 url(data:image/gif;base64,R0lGODlhFQAEAIAAAP///////yH5BAEAAAEALAAAAAAVAAQAAAINjB+gC+jP2ptn0WskLQA7) no-repeat center right;
|
||||
/* background-image: url(../images/tablesorter/asc.gif); */
|
||||
}
|
||||
|
||||
.tablesorter thead .tablesorter-headerAsc {
|
||||
background-color: #555;
|
||||
background-image: url(data:image/gif;base64,R0lGODlhFQAEAIAAAP///////yH5BAEAAAEALAAAAAAVAAQAAAINjI8Bya2wnINUMopZAQA7);
|
||||
/* background-image: url(../images/tablesorter/desc.gif); */
|
||||
background: #555 url(data:image/gif;base64,R0lGODlhFQAEAIAAAP///////yH5BAEAAAEALAAAAAAVAAQAAAINjI8Bya2wnINUMopZAQA7) no-repeat center right;
|
||||
/* background-image: url(../images/tablesorter/desc.gif); */
|
||||
}
|
||||
|
||||
.tablesorter thead .sorter-false {
|
||||
|
@ -2707,7 +2456,6 @@ thead.tablesorter-stickyHeader {
|
|||
|
||||
.tablesorter tfoot a {
|
||||
color:#fff;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* =======================================================================
|
||||
|
@ -2844,6 +2592,25 @@ span.token-input-delete-token {
|
|||
margin: 0 1px;
|
||||
}
|
||||
|
||||
.step-one #searchResults .alt {
|
||||
background-color: rgb(245, 245, 245);
|
||||
}
|
||||
|
||||
#addRootDirTable td label .filepath,
|
||||
.grey-text {
|
||||
color:#666
|
||||
}
|
||||
|
||||
#newShowPortal #displayText .show-name,
|
||||
#newShowPortal #displayText .show-dest,
|
||||
#newShowPortal #displayText p {
|
||||
color: rgb(153, 153, 153);
|
||||
}
|
||||
|
||||
#newShowPortal #displayText .show-name,
|
||||
#newShowPortal #displayText .show-dest {
|
||||
color: rgb(87, 68, 43);
|
||||
}
|
||||
/* =======================================================================
|
||||
jquery.confirm.css
|
||||
========================================================================== */
|
||||
|
|
|
@ -167,12 +167,7 @@ inc_top.tmpl
|
|||
background-image: url("../images/menu/menu-icons-white.png");
|
||||
}
|
||||
|
||||
[class^="icon16-"],
|
||||
[class*=" icon16-"] {
|
||||
background-image: url("../images/glyphicons-config.png");
|
||||
}
|
||||
|
||||
.ui-autocomplete-loading {
|
||||
.ui-autocomplete-loading {
|
||||
background: white url("../images/loading16.gif") right center no-repeat;
|
||||
}
|
||||
|
||||
|
@ -516,7 +511,6 @@ home.tmpl
|
|||
border: 1px solid #ccc;
|
||||
overflow: hidden;
|
||||
height: 66px;
|
||||
overflow: hidden;
|
||||
border-radius: 8px;
|
||||
vertical-align: top;
|
||||
width: 360px;
|
||||
|
@ -535,9 +529,13 @@ home.tmpl
|
|||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.search {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
#HomeLayout { margin-top: -35px; }
|
||||
#HomeLayout.not-poster { height: 75px }
|
||||
#HomeLayout div.not-poster { position:relative; top:38px; }
|
||||
#HomeLayout span.not-poster { margin-top: -30px }
|
||||
#HomeLayout.poster { margin-top: -35px; }
|
||||
#HomeLayout span.poster { margin-bottom:10px }
|
||||
#search_show_name { margin-top: 0 }
|
||||
|
||||
.ui-progressbar {
|
||||
height: 20px;
|
||||
|
@ -793,31 +791,42 @@ home_addShows.tmpl
|
|||
========================================================================== */
|
||||
|
||||
#addShowPortal {
|
||||
width: 700px;
|
||||
width: 750px;
|
||||
padding: 10px 0;
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
#addShowPortal a {
|
||||
padding: 10px;
|
||||
/* padding: 10px;*/
|
||||
padding: 0px 20px;
|
||||
width: 360px;
|
||||
|
||||
float: left;
|
||||
margin: 0 15px 15px 0;
|
||||
}
|
||||
|
||||
div.button {
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
padding-left: 10px;
|
||||
/* padding-left: 10px;*/
|
||||
}
|
||||
|
||||
div.buttontext {
|
||||
display: table-cell;
|
||||
/*
|
||||
padding-left: 20px;
|
||||
padding: 10px 15px;
|
||||
*/
|
||||
padding: 10px 0px 10px 15px;
|
||||
text-align: left;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
div.buttontext p {
|
||||
margin: 0
|
||||
}
|
||||
div.buttontext h3 {
|
||||
margin-top: 10px;
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
div.buttontext p {
|
||||
|
@ -851,13 +860,19 @@ div.buttontext p {
|
|||
/* =======================================================================
|
||||
home_newShow.tmpl
|
||||
========================================================================== */
|
||||
#addShowForm, #recommendedShowsForm {
|
||||
#addShowForm,
|
||||
#newShowPortal,
|
||||
fieldset.sectionwrap,
|
||||
div.formpaginate {
|
||||
width: 801px
|
||||
}
|
||||
|
||||
#addShowForm {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
#newShowPortal {
|
||||
width: 800px;
|
||||
padding: 10px 0;
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
|
@ -867,20 +882,44 @@ home_newShow.tmpl
|
|||
padding: 8px;
|
||||
overflow: hidden;
|
||||
font-size: 14px;
|
||||
background-color: #efefef;
|
||||
border: 1px solid #dfdede;
|
||||
border: 1px solid;
|
||||
}
|
||||
|
||||
#searchResults input[type="radio"] {
|
||||
vertical-align: -2px;
|
||||
}
|
||||
|
||||
#addShowForm #promptForSettings,
|
||||
#addShowForm #rootDirStaticList input,
|
||||
#addShowForm div.field-pair input,
|
||||
#addShowForm div.field-pair select {
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
#addShowForm #customQualityWrapper div.component-group-desc p {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
#addShowForm #nameToSearch {
|
||||
width: 460px;
|
||||
margin-top: 0
|
||||
}
|
||||
|
||||
#addShowForm #providedIndexer,
|
||||
#addShowForm #indexerLangSelect {
|
||||
margin-left: 7px
|
||||
}
|
||||
|
||||
#addShowForm #searchName {
|
||||
margin-left: 10px
|
||||
}
|
||||
|
||||
/* =======================================================================
|
||||
home_addExistingShow.tmpl
|
||||
========================================================================== */
|
||||
|
||||
.existingtabs {
|
||||
padding: 1em 1.4em;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
ul#rootDirStaticList {
|
||||
|
@ -888,14 +927,15 @@ ul#rootDirStaticList {
|
|||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
text-align: left;
|
||||
list-style-type: none;
|
||||
padding: 0
|
||||
}
|
||||
|
||||
ul#rootDirStaticList li {
|
||||
padding: 4px 5px 4px 5px;
|
||||
margin: 2px;
|
||||
padding: 4px 10px;
|
||||
margin: 2px 0;
|
||||
list-style: none outside none;
|
||||
cursor: pointer;
|
||||
background: url('../css/lib/images/ui-bg_highlight-soft_75_efefef_1x100.png') repeat-x scroll 50% 50% #EFEFEF;
|
||||
}
|
||||
|
||||
ul#rootDirStaticList li label {
|
||||
|
@ -1538,15 +1578,27 @@ config*.tmpl
|
|||
color: #666;
|
||||
}
|
||||
|
||||
#config div.field-pair {
|
||||
padding: 12px 0px;
|
||||
.stepDiv #customQualityWrapper h4 {
|
||||
margin-top: 6px;
|
||||
padding: 0 0
|
||||
}
|
||||
|
||||
.stepDiv div.field-pair {
|
||||
padding: 0 0 10px
|
||||
}
|
||||
|
||||
#config div.field-pair {
|
||||
padding: 12px 0
|
||||
}
|
||||
|
||||
.stepDiv .component-desc select,
|
||||
.stepDiv .component-desc input,
|
||||
#config div.field-pair select,
|
||||
#config div.field-pair input {
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
.stepDiv .component-desc input,
|
||||
#config div.field-pair input {
|
||||
float: left;
|
||||
}
|
||||
|
@ -1555,6 +1607,11 @@ config*.tmpl
|
|||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.stepDiv span.component-title.input {
|
||||
line-height: 30px
|
||||
}
|
||||
|
||||
.stepDiv span.component-title,
|
||||
#config span.component-title {
|
||||
float: left;
|
||||
width: 172px;
|
||||
|
@ -1563,6 +1620,11 @@ config*.tmpl
|
|||
font-weight: bold;
|
||||
}
|
||||
|
||||
#addShowForm .stepDiv span.component-desc {
|
||||
width:578px;
|
||||
}
|
||||
|
||||
.stepDiv span.component-desc,
|
||||
#config span.component-desc {
|
||||
font-size: 12px;
|
||||
font-weight: normal;
|
||||
|
@ -1684,14 +1746,14 @@ select .selected {
|
|||
border-top: 1px dotted #666666;
|
||||
}
|
||||
|
||||
[class^="icon16-"], [class*=" icon16-"] {
|
||||
background-image: url("../images/glyphicons-config.png");
|
||||
background-repeat: no-repeat;
|
||||
display: inline-block;
|
||||
[class^="icon16-"],
|
||||
[class*=" icon16-"] {
|
||||
background: url('../images/glyphicons-config.png') no-repeat;
|
||||
display: block;
|
||||
height: 16px;
|
||||
vertical-align: text-top;
|
||||
width: 16px;
|
||||
margin-top: 1px;
|
||||
float: left;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.icon16-github {
|
||||
|
@ -2298,9 +2360,9 @@ fieldset[disabled] .navbar-default .btn-link:focus {
|
|||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.btn-large [class^="icon-"] {
|
||||
/*.btn-large [class^="icon-"] {
|
||||
margin-top: 1px;
|
||||
}
|
||||
}*/
|
||||
|
||||
.btn-small {
|
||||
padding: 5px 9px;
|
||||
|
@ -2681,45 +2743,46 @@ browser.css
|
|||
|
||||
|
||||
/* =======================================================================
|
||||
formWizard.css
|
||||
formWizard
|
||||
========================================================================== */
|
||||
|
||||
fieldset.sectionwrap {
|
||||
width: 800px;
|
||||
padding: 5px;
|
||||
padding: 5px 0;
|
||||
text-align: left;
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
.step-one #searchResults legend.legendStep {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
div.stepsguide .step,
|
||||
legend.legendStep {
|
||||
color: #57442b;
|
||||
margin-bottom: 0px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
legend.legendStep p {
|
||||
padding-left: 15px;
|
||||
}
|
||||
|
||||
div.stepsguide {
|
||||
margin-bottom: 15px;
|
||||
overflow: hidden;
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
div.stepsguide .step {
|
||||
float: left;
|
||||
width: 266px;
|
||||
width: 267px;
|
||||
font: bold 24px Arial;
|
||||
}
|
||||
|
||||
div.stepsguide .step p {
|
||||
margin: 12px 0;
|
||||
border-bottom: 4px solid #57442b;
|
||||
}
|
||||
|
||||
div.stepsguide .disabledstep {
|
||||
color: #c4c4c4;
|
||||
margin: 12px 0 0;
|
||||
border-bottom: 5px solid;
|
||||
}
|
||||
|
||||
div.stepsguide .disabledstep p {
|
||||
border-bottom: 4px solid #8a775e;
|
||||
border-bottom: 2px solid;
|
||||
}
|
||||
|
||||
div.stepsguide .step .smalltext {
|
||||
|
@ -2728,56 +2791,41 @@ div.stepsguide .step .smalltext {
|
|||
}
|
||||
|
||||
div.formpaginate {
|
||||
width: 800px;
|
||||
margin-top: 1em;
|
||||
overflow: auto;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.step-outer {
|
||||
overflow: hidden
|
||||
}
|
||||
|
||||
div.formpaginate .prev, div.formpaginate .next {
|
||||
padding: 3px 6px;
|
||||
color: #fff;
|
||||
cursor: hand;
|
||||
cursor: pointer;
|
||||
background: #57442b;
|
||||
-webkit-border-radius: 6px;
|
||||
-moz-border-radius: 6px;
|
||||
border-radius: 6px;
|
||||
-moz-border-radius: 6px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.stepDiv {
|
||||
padding: 15px;
|
||||
}
|
||||
.stepDiv.parent-folder {
|
||||
padding: 15px 0 0;
|
||||
width: 430px;
|
||||
margin: 0px auto;
|
||||
}
|
||||
|
||||
#tabs .nocheck,
|
||||
.stepDiv .nocheck {
|
||||
padding-left: 16px;
|
||||
}
|
||||
|
||||
#tabs label span.component-title,
|
||||
.stepDiv label span.component-title {
|
||||
padding-bottom: 6px;
|
||||
float: left;
|
||||
width: 172px;
|
||||
margin-right: 10px;
|
||||
font-size: 13px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#tabs label span.component-desc,
|
||||
.stepDiv label span.component-desc {
|
||||
padding-bottom: 6px;
|
||||
font-size: 12px;
|
||||
font-weight: normal;
|
||||
display:inline-block;
|
||||
width:475px;
|
||||
}
|
||||
|
||||
/* step 3 related */
|
||||
#customQuality {
|
||||
display: block;
|
||||
padding: 10px 0;
|
||||
padding: 0 0 10px 0;
|
||||
overflow: hidden;
|
||||
clear: both;
|
||||
}
|
||||
|
@ -2791,7 +2839,6 @@ div.formpaginate .prev, div.formpaginate .next {
|
|||
width: 85%;
|
||||
margin: .8em 0;
|
||||
font-size: 1.2em;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* =======================================================================
|
||||
|
@ -2811,11 +2858,15 @@ tablesorter.css
|
|||
.tablesorter th,
|
||||
.tablesorter td {
|
||||
padding: 4px;
|
||||
border-top: #fff 1px solid;
|
||||
border-left: #fff 1px solid;
|
||||
border-top: 1px solid;
|
||||
border-left: 1px solid;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
#addRootDirTable.tablesorter td {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
/* remove extra border from left edge */
|
||||
.tablesorter th:first-child,
|
||||
.tablesorter td:first-child {
|
||||
|
@ -2823,10 +2874,7 @@ tablesorter.css
|
|||
}
|
||||
|
||||
.tablesorter th {
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
text-shadow: -1px -1px 0 rgba(0,0,0,0.3);
|
||||
background-color: #333;
|
||||
border-collapse: collapse;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
@ -2834,22 +2882,7 @@ tablesorter.css
|
|||
.tablesorter .tablesorter-header {
|
||||
padding: 4px 18px 4px 18px;
|
||||
cursor: pointer;
|
||||
background-image: url(data:image/gif;base64,R0lGODlhFQAJAIAAAP///////yH5BAEAAAEALAAAAAAVAAkAAAIXjI+AywnaYnhUMoqt3gZXPmVg94yJVQAAOw==);
|
||||
background-position: center right;
|
||||
background-repeat: no-repeat;
|
||||
/* background-image: url(../images/tablesorter/bg.gif); */
|
||||
}
|
||||
|
||||
.tablesorter thead .tablesorter-headerDesc {
|
||||
background-color: #555;
|
||||
background-image: url(data:image/gif;base64,R0lGODlhFQAEAIAAAP///////yH5BAEAAAEALAAAAAAVAAQAAAINjB+gC+jP2ptn0WskLQA7);
|
||||
/* background-image: url(../images/tablesorter/asc.gif); */
|
||||
}
|
||||
|
||||
.tablesorter thead .tablesorter-headerAsc {
|
||||
background-color: #555;
|
||||
background-image: url(data:image/gif;base64,R0lGODlhFQAEAIAAAP///////yH5BAEAAAEALAAAAAAVAAQAAAINjI8Bya2wnINUMopZAQA7);
|
||||
/* background-image: url(../images/tablesorter/desc.gif); */
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.tablesorter thead .sorter-false {
|
||||
|
@ -2910,7 +2943,6 @@ thead.tablesorter-stickyHeader {
|
|||
}
|
||||
|
||||
.tablesorter tfoot a {
|
||||
color:#fff;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
|
@ -3053,6 +3085,42 @@ span.token-input-delete-token {
|
|||
margin: 0 1px;
|
||||
}
|
||||
|
||||
.stepDiv #searchResults div {
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
.stepDiv #searchResults #searchingAnim {
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
.stepone-result-title {
|
||||
font-weight: 600;
|
||||
margin-left: 10px
|
||||
}
|
||||
|
||||
.stepone-result-date,
|
||||
.stepone-result-db,
|
||||
.stepone-result-overview {
|
||||
margin-left: 5px
|
||||
}
|
||||
.stepone-result-db img {
|
||||
margin-top: 3px;
|
||||
vertical-align: top;
|
||||
}
|
||||
#newShowPortal #displayText .show-name,
|
||||
#newShowPortal #displayText .show-dest,
|
||||
#newShowPortal #displayText p {
|
||||
margin: 0;
|
||||
}
|
||||
#newShowPortal #displayText .show-name,
|
||||
#newShowPortal #displayText .show-dest {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
#addRootDirTable td label .filepath {
|
||||
font-weight: 900
|
||||
}
|
||||
|
||||
.boldest {font-weight: 900}
|
||||
.red-text {color:#d33}
|
||||
.clear-left {clear:left}
|
||||
|
|
BIN
gui/slick/images/network/esquire network.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
gui/slick/images/network/smithsonian channel.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 136 B After Width: | Height: | Size: 177 B |
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 2.8 KiB |
BIN
gui/slick/images/providers/nzb_is.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
gui/slick/images/providers/nzbs_in.png
Normal file
After Width: | Height: | Size: 191 B |
Before Width: | Height: | Size: 209 B After Width: | Height: | Size: 180 B |
Before Width: | Height: | Size: 338 B After Width: | Height: | Size: 250 B |
Before Width: | Height: | Size: 977 B After Width: | Height: | Size: 204 B |
Before Width: | Height: | Size: 268 B After Width: | Height: | Size: 213 B |
|
@ -1,102 +0,0 @@
|
|||
#import os.path
|
||||
#import datetime
|
||||
#import locale
|
||||
#import sickbeard
|
||||
#from sickbeard.common import *
|
||||
#from sickbeard.sbdatetime import *
|
||||
#from sickbeard import config
|
||||
#from sickbeard import metadata
|
||||
#from sickbeard.metadata.generic import GenericMetadata
|
||||
#set global $title = "Config - Backup/Restore"
|
||||
#set global $header = "Backup/Restore"
|
||||
|
||||
#set global $sbPath="../.."
|
||||
|
||||
#set global $topmenu="config"#
|
||||
#include $os.path.join($sickbeard.PROG_DIR, "gui/slick/interfaces/default/inc_top.tmpl")
|
||||
|
||||
<script type="text/javascript" src="$sbRoot/js/configBackupRestore.js?$sbPID"></script>
|
||||
|
||||
#if $varExists('header')
|
||||
<h1 class="header">$header</h1>
|
||||
#else
|
||||
<h1 class="title">$title</h1>
|
||||
#end if
|
||||
|
||||
#set $indexer = 0
|
||||
#if $sickbeard.INDEXER_DEFAULT
|
||||
#set $indexer = $sickbeard.INDEXER_DEFAULT
|
||||
#end if
|
||||
|
||||
<script type="text/javascript" src="$sbRoot/js/config.js?$sbPID"></script>
|
||||
|
||||
<div id="config">
|
||||
<div id="config-content">
|
||||
|
||||
<form name="configForm" method="post" action="backuprestore">
|
||||
<div id="config-components">
|
||||
<ul>
|
||||
<li><a href="#core-component-group1">Backup</a></li>
|
||||
<li><a href="#core-component-group2">Restore</a></li>
|
||||
</ul>
|
||||
|
||||
<div id="core-component-group1" class="component-group clearfix">
|
||||
<div class="component-group-desc">
|
||||
<h3>Backup</h3>
|
||||
<p><b>Backup your main database file and config.</b></p>
|
||||
</div>
|
||||
|
||||
<fieldset class="component-group-list">
|
||||
<div class="field-pair">
|
||||
Select the folder you wish to save your backup file to:
|
||||
|
||||
<br/><br/>
|
||||
|
||||
<input type="text" name="backupDir" id="backupDir" class="form-control input-sm input350" />
|
||||
<input class="btn btn-inline" type="button" value="Backup" id="Backup" />
|
||||
|
||||
<br/>
|
||||
|
||||
</div>
|
||||
<div class="Backup" id="Backup-result"></div>
|
||||
</fieldset>
|
||||
|
||||
</div><!-- /component-group1 //-->
|
||||
|
||||
<div id="core-component-group2" class="component-group clearfix">
|
||||
<div class="component-group-desc">
|
||||
<h3>Restore</h3>
|
||||
<p><b>Restore your main database file and config.</b></p>
|
||||
</div>
|
||||
|
||||
<fieldset class="component-group-list">
|
||||
<div class="field-pair">
|
||||
Select the backup file you wish to restore:
|
||||
|
||||
<br/><br/>
|
||||
|
||||
<input type="text" name="backupFile" id="backupFile" class="form-control input-sm input350" />
|
||||
<input class="btn btn-inline" type="button" value="Restore" id="Restore" />
|
||||
|
||||
<br/>
|
||||
|
||||
</div>
|
||||
<div class="Restore" id="Restore-result"></div>
|
||||
</fieldset>
|
||||
</div><!-- /component-group2 //-->
|
||||
</div><!-- /config-components -->
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="clearfix"></div>
|
||||
|
||||
<script type="text/javascript" charset="utf-8">
|
||||
<!--
|
||||
jQuery('#backupDir').fileBrowser({ title: 'Select backup folder to save to', key: 'backupPath' });
|
||||
jQuery('#backupFile').fileBrowser({ title: 'Select backup files to restore', key: 'backupFile', includeFiles: 1 });
|
||||
jQuery('#config-components').tabs();
|
||||
//-->
|
||||
</script>
|
||||
|
||||
#include $os.path.join($sickbeard.PROG_DIR,"gui/slick/interfaces/default/inc_bottom.tmpl")
|
|
@ -215,6 +215,16 @@
|
|||
</label>
|
||||
</div>
|
||||
|
||||
<div class="field-pair">
|
||||
<label for="home_search_focus">
|
||||
<span class="component-title">Give show list search focus</span>
|
||||
<span class="component-desc">
|
||||
<input type="checkbox" name="home_search_focus" id="home_search_focus" #if $sickbeard.HOME_SEARCH_FOCUS then 'checked="checked"' else ''#/>
|
||||
<p>page refresh on "Show List" will start search box focused</p>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="field-pair">
|
||||
<label for="sort_article">
|
||||
<span class="component-title">Sort with "The", "A", "An"</span>
|
||||
|
|
|
@ -159,7 +159,7 @@
|
|||
<div class="component-group-desc">
|
||||
<img class="notifier-icon" src="$sbRoot/images/notifiers/plex.png" alt="" title="Plex Media Server" />
|
||||
<h3><a href="<%= anon_url('http://www.plexapp.com/') %>" rel="noreferrer" onclick="window.open(this.href, '_blank'); return false;">Plex Media Server</a></h3>
|
||||
<p>Experience your media on a visually stunning, easy to use interface on your Mac connected to your TV. Your media library has never looked this good!</p>
|
||||
<p>Plex organizes all of your personal media, wherever you keep it, so you can enjoy it on any device</p>
|
||||
<p class="plexinfo hide">For sending notifications to Plex Home Theater (PHT) clients, use the XBMC notifier with port <b>3005</b>.</p>
|
||||
</div>
|
||||
<fieldset class="component-group-list">
|
||||
|
@ -222,12 +222,12 @@
|
|||
</div>
|
||||
<div class="field-pair">
|
||||
<label for="plex_host">
|
||||
<span class="component-title">Plex Client IP:Port</span>
|
||||
<span class="component-title">Plex client IP:Port</span>
|
||||
<input type="text" name="plex_host" id="plex_host" value="$sickbeard.PLEX_HOST" class="form-control input-sm input350" />
|
||||
</label>
|
||||
<label>
|
||||
<span class="component-title"> </span>
|
||||
<span class="component-desc">host running Plex Client (eg. 192.168.1.100:3000)</span>
|
||||
<span class="component-desc">host running Plex client (eg. 192.168.1.100:3000)</span>
|
||||
</label>
|
||||
<label>
|
||||
<span class="component-title"> </span>
|
||||
|
@ -236,22 +236,22 @@
|
|||
</div>
|
||||
<div class="field-pair">
|
||||
<label for="plex_username">
|
||||
<span class="component-title">Plex Client username</span>
|
||||
<span class="component-title">Plex client username</span>
|
||||
<input type="text" name="plex_username" id="plex_username" value="$sickbeard.PLEX_USERNAME" class="form-control input-sm input250" />
|
||||
</label>
|
||||
<label>
|
||||
<span class="component-title"> </span>
|
||||
<span class="component-desc">username for your Plex client API (blank for none)</span>
|
||||
<span class="component-desc">needed if your client / server requires authentication (blank for none)</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
<label for="plex_password">
|
||||
<span class="component-title">Plex Client password</span>
|
||||
<span class="component-title">Plex client password</span>
|
||||
<input type="password" name="plex_password" id="plex_password" value="$sickbeard.PLEX_PASSWORD" class="form-control input-sm input250" />
|
||||
</label>
|
||||
<label>
|
||||
<span class="component-title"> </span>
|
||||
<span class="component-desc">password for your Plex client API (blank for none)</span>
|
||||
<span class="component-desc">needed if your client / server requires authentication (blank for none)</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="testNotification" id="testPLEX-result">Click below to test.</div>
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
$(this).qtip({
|
||||
show: {solo:true},
|
||||
position: {viewport:$(window), my:'left center', adjust:{ y: -10, x: 2 }},
|
||||
style: {tip:{corner:true, method:'polygon'}, classes:'qtip-rounded qtip-shadow ui-tooltip-sb'}
|
||||
style: {classes:'qtip-rounded qtip-shadow'}
|
||||
});
|
||||
});
|
||||
#end raw
|
||||
|
@ -52,7 +52,7 @@
|
|||
};
|
||||
|
||||
\$('.imdbstars').generateStars();
|
||||
|
||||
TVShowList = [${tvshow_id_csv}]
|
||||
});
|
||||
//-->
|
||||
</script>
|
||||
|
|
|
@ -65,7 +65,6 @@
|
|||
<input type="hidden" name="show" value="$show.indexerid" />
|
||||
<b>Location:</b> <input type="text" name="location" id="location" value="$show._location" class="form-control form-control-inline input-sm input350" /><br />
|
||||
<br />
|
||||
<b>Quality:</b>
|
||||
#set $qualities = $common.Quality.splitQuality(int($show.quality))
|
||||
#set global $anyQualities = $qualities[0]
|
||||
#set global $bestQualities = $qualities[1]
|
||||
|
|
|
@ -49,110 +49,112 @@
|
|||
<!--
|
||||
|
||||
\$.tablesorter.addParser({
|
||||
id: 'loadingNames',
|
||||
is: function(s) {
|
||||
return false;
|
||||
},
|
||||
format: function(s) {
|
||||
if (s.indexOf('Loading...') == 0)
|
||||
return s.replace('Loading...','000');
|
||||
id: 'loadingNames',
|
||||
is: function(s) {
|
||||
return false;
|
||||
},
|
||||
format: function(s) {
|
||||
if (s.indexOf('Loading...') == 0)
|
||||
return s.replace('Loading...','000');
|
||||
else
|
||||
#if not $sickbeard.SORT_ARTICLE:
|
||||
return (s || '').replace(/^(?:(?:A(?!\s+to)n?)|The)\s(\w)/i, '$1');
|
||||
#else:
|
||||
return (s || '');
|
||||
#end if
|
||||
},
|
||||
type: 'text'
|
||||
},
|
||||
type: 'text'
|
||||
});
|
||||
|
||||
\$.tablesorter.addParser({
|
||||
id: 'quality',
|
||||
is: function(s) {
|
||||
return false;
|
||||
},
|
||||
format: function(s) {
|
||||
return s.replace('hd1080p',5).replace('hd720p',4).replace('hd',3).replace('sd',2).replace('any',1).replace('custom',7);
|
||||
},
|
||||
type: 'numeric'
|
||||
id: 'quality',
|
||||
is: function(s) {
|
||||
return false;
|
||||
},
|
||||
format: function(s) {
|
||||
return s.replace('hd1080p',5).replace('hd720p',4).replace('hd',3).replace('sd',2).replace('any',1).replace('custom',7);
|
||||
},
|
||||
type: 'numeric'
|
||||
});
|
||||
|
||||
\$(document).ready(function(){
|
||||
|
||||
\$("img#network").on('error', function(){
|
||||
\$(this).parent().text(\$(this).attr('alt'));
|
||||
\$(this).remove();
|
||||
});
|
||||
\$("img#network").on('error', function(){
|
||||
\$(this).parent().text(\$(this).attr('alt'));
|
||||
\$(this).remove();
|
||||
});
|
||||
|
||||
\$("#showListTableShows:has(tbody tr)").tablesorter({
|
||||
sortList: [[5,1],[1,0]],
|
||||
textExtraction: {
|
||||
\$("#showListTableShows:has(tbody tr)").tablesorter({
|
||||
sortList: [[5,1],[1,0]],
|
||||
textExtraction: {
|
||||
0: function(node) { return \$(node).find("span").text().toLowerCase(); },
|
||||
2: function(node) { return \$(node).find("span").text().toLowerCase(); },
|
||||
3: function(node) { return \$(node).find("span").text().toLowerCase(); },
|
||||
4: function(node) { return \$(node).find("span").text(); },
|
||||
5: function(node) { return \$(node).find("img").attr("alt"); }
|
||||
},
|
||||
widgets: ['saveSort', 'zebra', 'stickyHeaders', 'filter'],
|
||||
headers: {
|
||||
},
|
||||
widgets: ['saveSort', 'zebra', 'stickyHeaders', 'filter'],
|
||||
headers: {
|
||||
0: { sorter: 'isoDate' },
|
||||
1: { sorter: 'loadingNames' },
|
||||
3: { sorter: 'quality' },
|
||||
4: { sorter: 'eps' }
|
||||
},
|
||||
},
|
||||
widgetOptions : {
|
||||
filter_columnFilters: false,
|
||||
filter_columnFilters: false,
|
||||
filter_reset: '.resetshows'
|
||||
},
|
||||
sortStable: true
|
||||
});
|
||||
sortStable: true
|
||||
});
|
||||
|
||||
\$("#showListTableAnime:has(tbody tr)").tablesorter({
|
||||
sortList: [[5,1],[1,0]],
|
||||
textExtraction: {
|
||||
sortList: [[5,1],[1,0]],
|
||||
textExtraction: {
|
||||
0: function(node) { return \$(node).find("span").text().toLowerCase(); },
|
||||
2: function(node) { return \$(node).find("span").text().toLowerCase(); },
|
||||
3: function(node) { return \$(node).find("span").text().toLowerCase(); },
|
||||
4: function(node) { return \$(node).find("span").text(); },
|
||||
5: function(node) { return \$(node).find("img").attr("alt"); }
|
||||
},
|
||||
widgets: ['saveSort', 'zebra', 'stickyHeaders', 'filter'],
|
||||
headers: {
|
||||
},
|
||||
widgets: ['saveSort', 'zebra', 'stickyHeaders', 'filter'],
|
||||
headers: {
|
||||
0: { sorter: 'isoDate' },
|
||||
1: { sorter: 'loadingNames' },
|
||||
3: { sorter: 'quality' },
|
||||
4: { sorter: 'eps' }
|
||||
},
|
||||
},
|
||||
widgetOptions : {
|
||||
filter_columnFilters: false,
|
||||
filter_columnFilters: false,
|
||||
filter_reset: '.resetanime'
|
||||
},
|
||||
sortStable: true
|
||||
});
|
||||
sortStable: true
|
||||
});
|
||||
|
||||
\$.tablesorter.filter.bindSearch( "#showListTableShows", \$('.search') );
|
||||
|
||||
#if $sickbeard.ANIME_SPLIT_HOME:
|
||||
#if $sickbeard.ANIME_SPLIT_HOME:
|
||||
\$.tablesorter.filter.bindSearch( "#showListTableAnime", \$('.search') );
|
||||
#end if
|
||||
|
||||
#end if
|
||||
|
||||
#set $fuzzydate = 'airdate'
|
||||
#if $sickbeard.FUZZY_DATING:
|
||||
fuzzyMoment({
|
||||
dtInline : #if $layout == 'poster' then "true" else "false"#,
|
||||
containerClass : '.${fuzzydate}',
|
||||
dateHasTime : false,
|
||||
dateFormat : '${sickbeard.DATE_PRESET}',
|
||||
timeFormat : '${sickbeard.TIME_PRESET}',
|
||||
trimZero : #if $sickbeard.TRIM_ZERO then "true" else "false"#
|
||||
});
|
||||
fuzzyMoment({
|
||||
dtInline : #if $layout == 'poster' then "true" else "false"#,
|
||||
containerClass : '.${fuzzydate}',
|
||||
dateHasTime : false,
|
||||
dateFormat : '${sickbeard.DATE_PRESET}',
|
||||
timeFormat : '${sickbeard.TIME_PRESET}',
|
||||
trimZero : #if $sickbeard.TRIM_ZERO then "true" else "false"#
|
||||
});
|
||||
#end if
|
||||
|
||||
|
||||
var \$container = [\$('#container'), \$('#container-anime')];
|
||||
|
||||
|
||||
jQuery.each(\$container, function (j) {
|
||||
this.isotope({
|
||||
this.isotope({
|
||||
itemSelector: '.show',
|
||||
sortBy : '$sickbeard.POSTER_SORTBY',
|
||||
sortAscending: $sickbeard.POSTER_SORTDIR,
|
||||
sortBy : '$sickbeard.POSTER_SORTBY',
|
||||
sortAscending: $sickbeard.POSTER_SORTDIR,
|
||||
layoutMode: 'masonry',
|
||||
masonry: {
|
||||
columnWidth: 12,
|
||||
|
@ -170,7 +172,7 @@
|
|||
network: '[data-network]',
|
||||
date: function( itemElem ) {
|
||||
var date = \$( itemElem ).attr('data-date');
|
||||
return date.length && parseInt( date, 10 ) || Number.POSITIVE_INFINITY;
|
||||
return date.length && parseInt( date, 10 ) || Number.POSITIVE_INFINITY;
|
||||
},
|
||||
progress: function( itemElem ) {
|
||||
var progress = \$( itemElem ).attr('data-progress');
|
||||
|
@ -184,7 +186,7 @@
|
|||
var sortValue = this.value;
|
||||
\$('#container').isotope({ sortBy: sortValue });
|
||||
\$('#container-anime').isotope({ sortBy: sortValue });
|
||||
\$.get(this.options[this.selectedIndex].getAttribute('data-sort'));
|
||||
\$.get(this.options[this.selectedIndex].getAttribute('data-sort'));
|
||||
});
|
||||
|
||||
\$('#postersortdirection').on( 'change', function() {
|
||||
|
@ -192,57 +194,64 @@
|
|||
sortDirection = sortDirection == 'true';
|
||||
\$('#container').isotope({ sortAscending: sortDirection });
|
||||
\$('#container-anime').isotope({ sortAscending: sortDirection });
|
||||
\$.get(this.options[this.selectedIndex].getAttribute('data-sort'));
|
||||
\$.get(this.options[this.selectedIndex].getAttribute('data-sort'));
|
||||
});
|
||||
|
||||
#if $sickbeard.HOME_SEARCH_FOCUS
|
||||
\$('#search_show_name').focus();
|
||||
#end if
|
||||
});
|
||||
|
||||
//-->
|
||||
</script>
|
||||
|
||||
#if $varExists('header')
|
||||
<h1 class="header">$header</h1>
|
||||
<h1 class="header" style="margin-bottom:0">$header</h1>
|
||||
#else
|
||||
<h1 class="title">$title</h1>
|
||||
<h1 class="title" style="margin-bottom:0">$title</h1>
|
||||
#end if
|
||||
|
||||
<div id="HomeLayout" class="pull-right" style="margin-top: -40px;">
|
||||
<span> Layout:
|
||||
<select name="layout" class="form-control form-control-inline input-sm" onchange="location = this.options[this.selectedIndex].value;">
|
||||
#set $tab = 1
|
||||
|
||||
#if $layout != 'poster':
|
||||
<div id="HomeLayout" class="pull-right not-poster">
|
||||
<div class="not-poster">
|
||||
<input id="search_show_name" class="search form-control form-control-inline input-sm input200" type="search" data-column="1" placeholder="Search Show Name" tabindex="$tab#set $tab += 1#">
|
||||
<button type="button" class="resetshows resetanime btn btn-inline" tabindex="$tab#set $tab += 1#">Reset Search</button>
|
||||
</div>
|
||||
<span class="pull-right not-poster"> Layout:
|
||||
#else
|
||||
<div id="HomeLayout" class="pull-right poster">
|
||||
<span class="pull-right poster">Layout:
|
||||
#end if
|
||||
|
||||
<select name="layout" class="form-control form-control-inline input-sm" onchange="location = this.options[this.selectedIndex].value;" tabindex="$tab#set $tab += 1#">
|
||||
<option value="$sbRoot/setHomeLayout/?layout=poster" #if $sickbeard.HOME_LAYOUT == "poster" then "selected=\"selected\"" else ""#>Poster</option>
|
||||
<option value="$sbRoot/setHomeLayout/?layout=small" #if $sickbeard.HOME_LAYOUT == "small" then "selected=\"selected\"" else ""#>Small Poster</option>
|
||||
<option value="$sbRoot/setHomeLayout/?layout=banner" #if $sickbeard.HOME_LAYOUT == "banner" then "selected=\"selected\"" else ""#>Banner</option>
|
||||
<option value="$sbRoot/setHomeLayout/?layout=simple" #if $sickbeard.HOME_LAYOUT == "simple" then "selected=\"selected\"" else ""#>Simple</option>
|
||||
</select>
|
||||
</span>
|
||||
|
||||
#if $layout == 'poster':
|
||||
|
||||
<span> Sort By:
|
||||
<select id="postersort" class="form-control form-control-inline input-sm">
|
||||
<option value="name" data-sort="$sbRoot/setPosterSortBy/?sort=name" #if $sickbeard.POSTER_SORTBY == "name" then "selected=\"selected\"" else ""#>Name</option>
|
||||
<option value="date" data-sort="$sbRoot/setPosterSortBy/?sort=date" #if $sickbeard.POSTER_SORTBY == "date" then "selected=\"selected\"" else ""#>Next Episode</option>
|
||||
<option value="network" data-sort="$sbRoot/setPosterSortBy/?sort=network" #if $sickbeard.POSTER_SORTBY == "network" then "selected=\"selected\"" else ""#>Network</option>
|
||||
<option value="progress" data-sort="$sbRoot/setPosterSortBy/?sort=progress" #if $sickbeard.POSTER_SORTBY == "progress" then "selected=\"selected\"" else ""#>Progress</option>
|
||||
|
||||
#if $layout == 'poster':
|
||||
<span>Sort By:
|
||||
<select id="postersort" class="form-control form-control-inline input-sm" tabindex="$tab#set $tab += 1#">
|
||||
<option value="name" data-sort="$sbRoot/setPosterSortBy/?sort=name" #if $sickbeard.POSTER_SORTBY == "name" then "selected=\"selected\"" else ""#>Name</option>
|
||||
<option value="date" data-sort="$sbRoot/setPosterSortBy/?sort=date" #if $sickbeard.POSTER_SORTBY == "date" then "selected=\"selected\"" else ""#>Next Episode</option>
|
||||
<option value="network" data-sort="$sbRoot/setPosterSortBy/?sort=network" #if $sickbeard.POSTER_SORTBY == "network" then "selected=\"selected\"" else ""#>Network</option>
|
||||
<option value="progress" data-sort="$sbRoot/setPosterSortBy/?sort=progress" #if $sickbeard.POSTER_SORTBY == "progress" then "selected=\"selected\"" else ""#>Progress</option>
|
||||
</select>
|
||||
</span>
|
||||
|
||||
<span> Sort Order:
|
||||
<select id="postersortdirection" class="form-control form-control-inline input-sm">
|
||||
<option value="true" data-sort="$sbRoot/setPosterSortDir/?direction=1" #if $sickbeard.POSTER_SORTDIR == 1 then "selected=\"selected\"" else ""#>Asc</option>
|
||||
<option value="false" data-sort="$sbRoot/setPosterSortDir/?direction=0" #if $sickbeard.POSTER_SORTDIR == 0 then "selected=\"selected\"" else ""#>Desc</option>
|
||||
<span style="margin:0 0 0 5px">Sort Order:
|
||||
<select id="postersortdirection" class="form-control form-control-inline input-sm" tabindex="$tab#set $tab += 1#">
|
||||
<option value="true" data-sort="$sbRoot/setPosterSortDir/?direction=1" #if $sickbeard.POSTER_SORTDIR == 1 then "selected=\"selected\"" else ""#>Asc</option>
|
||||
<option value="false" data-sort="$sbRoot/setPosterSortDir/?direction=0" #if $sickbeard.POSTER_SORTDIR == 0 then "selected=\"selected\"" else ""#>Desc</option>
|
||||
</select>
|
||||
</span>
|
||||
|
||||
|
||||
#end if
|
||||
#end if
|
||||
</div>
|
||||
|
||||
#if $layout != 'poster':
|
||||
<div class="pull-right">
|
||||
<input class="search form-control form-control-inline input-sm input200" type="search" data-column="1" placeholder="Search Show Name"> <button type="button" class="resetshows resetanime btn btn-inline">Reset Search</button>
|
||||
</div>
|
||||
#end if
|
||||
|
||||
#for $curShowlist in $showlists:
|
||||
#set $curListType = $curShowlist[0]
|
||||
|
@ -256,11 +265,11 @@
|
|||
<div class="posterview">
|
||||
#for $curLoadingShow in $sickbeard.showQueueScheduler.action.loadingShowList:
|
||||
|
||||
#if $curLoadingShow.show != None and $curLoadingShow.show in $sickbeard.showList:
|
||||
#continue
|
||||
#end if
|
||||
|
||||
#if $curLoadingShow.show == None:
|
||||
#if $curLoadingShow.show != None and $curLoadingShow.show in $sickbeard.showList:
|
||||
#continue
|
||||
#end if
|
||||
|
||||
#if $curLoadingShow.show == None:
|
||||
<div class="show" data-name="0" data-date="010101" data-network="0" data-progress="101">
|
||||
<img alt="" title="$curLoadingShow.show_name" class="show-image" style="border-bottom: 1px solid #111;" src="$sbRoot/images/poster.png" />
|
||||
<div class="show-details">
|
||||
|
@ -269,7 +278,7 @@
|
|||
</div>
|
||||
|
||||
#end if
|
||||
|
||||
|
||||
#end for
|
||||
|
||||
$myShowList.sort(lambda x, y: cmp(x.name, y.name))
|
||||
|
@ -328,8 +337,8 @@ $myShowList.sort(lambda x, y: cmp(x.name, y.name))
|
|||
#set $den = 1
|
||||
#end if
|
||||
|
||||
#set $progressbar_percent = $nom * 100 / $den
|
||||
|
||||
#set $progressbar_percent = $nom * 100 / $den
|
||||
|
||||
#set $data_date = '6000000000.0'
|
||||
#if $cur_airs_next:
|
||||
#set $data_date = $time.mktime($sbdatetime.sbdatetime.convert_to_setting($network_timezones.parse_date_time($cur_airs_next,$curShow.airs,$curShow.network)).timetuple())
|
||||
|
@ -388,9 +397,9 @@ $myShowList.sort(lambda x, y: cmp(x.name, y.name))
|
|||
#set $output_html = $display_status
|
||||
#end if
|
||||
#end if
|
||||
$output_html
|
||||
$output_html
|
||||
#end if
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table width="100%" cellspacing="1" border="0" cellpadding="0">
|
||||
<tr>
|
||||
|
@ -399,29 +408,28 @@ $myShowList.sort(lambda x, y: cmp(x.name, y.name))
|
|||
</td>
|
||||
|
||||
<td class="show-table">
|
||||
#if $layout != 'simple':
|
||||
#if $curShow.network:
|
||||
#if $layout != 'simple':
|
||||
#if $curShow.network:
|
||||
<img class="show-network-image" src="$sbRoot/images/network/${curShow.network.replace(u"\u00C9",'e').lower()}.png" alt="$curShow.network" title="$curShow.network" />
|
||||
#else:
|
||||
#else:
|
||||
<img class="show-network-image" src="$sbRoot/images/network/nonetwork.png" alt="No Network" title="No Network" />
|
||||
#end if
|
||||
#else:
|
||||
#end if
|
||||
#else:
|
||||
$curShow.network
|
||||
#end if
|
||||
#end if
|
||||
</td>
|
||||
|
||||
<td class="show-table">
|
||||
#if $curShow.quality in $qualityPresets:
|
||||
#if $curShow.quality in $qualityPresets:
|
||||
<span class="show-quality">$qualityPresetStrings[$curShow.quality]</span>
|
||||
#else:
|
||||
#else:
|
||||
<span class="show-quality">Custom</span>
|
||||
#end if
|
||||
#end if
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
#end for
|
||||
|
@ -432,7 +440,7 @@ $myShowList.sort(lambda x, y: cmp(x.name, y.name))
|
|||
|
||||
<table id="showListTable$curListType" class="tablesorter" cellspacing="1" border="0" cellpadding="0">
|
||||
|
||||
<thead>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="nowrap">Next Ep</th>
|
||||
<th>Show</th>
|
||||
|
@ -443,37 +451,37 @@ $myShowList.sort(lambda x, y: cmp(x.name, y.name))
|
|||
<th>Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tfoot>
|
||||
<tr>
|
||||
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th rowspan="1" colspan="1" align="center"><a href="$sbRoot/home/addShows/">Add Show</a></th>
|
||||
<th rowspan="1" colspan="6"></th>
|
||||
</tr>
|
||||
</tfoot>
|
||||
|
||||
</tr>
|
||||
</tfoot>
|
||||
|
||||
<tbody>
|
||||
|
||||
#for $curLoadingShow in $sickbeard.showQueueScheduler.action.loadingShowList:
|
||||
|
||||
#if $curLoadingShow.show != None and $curLoadingShow.show in $sickbeard.showList:
|
||||
#continue
|
||||
#end if
|
||||
|
||||
<tr>
|
||||
<td align="center">(loading)</td>
|
||||
<td></td>
|
||||
<td>
|
||||
#if $curLoadingShow.show == None:
|
||||
Loading... ($curLoadingShow.show_name)
|
||||
#else:
|
||||
<a href="displayShow?show=$curLoadingShow.show.indexerid">$curLoadingShow.show.name</a>
|
||||
#if $curLoadingShow.show != None and $curLoadingShow.show in $sickbeard.showList:
|
||||
#continue
|
||||
#end if
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td align="center">(loading)</td>
|
||||
<td>
|
||||
#if $curLoadingShow.show == None:
|
||||
Loading... ($curLoadingShow.show_name)
|
||||
#else:
|
||||
<a href="displayShow?show=$curLoadingShow.show.indexerid">$curLoadingShow.show.name</a>
|
||||
#end if
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
#end for
|
||||
|
||||
$myShowList.sort(lambda x, y: cmp(x.name, y.name))
|
||||
|
@ -524,58 +532,59 @@ $myShowList.sort(lambda x, y: cmp(x.name, y.name))
|
|||
#set $den = 1
|
||||
#end if
|
||||
|
||||
#set $progressbar_percent = $nom * 100 / $den
|
||||
#set $progressbar_percent = $nom * 100 / $den
|
||||
|
||||
<tr>
|
||||
<tr>
|
||||
|
||||
#if $cur_airs_next
|
||||
#if $cur_airs_next
|
||||
#set $ldatetime = $sbdatetime.sbdatetime.convert_to_setting($network_timezones.parse_date_time($cur_airs_next,$curShow.airs,$curShow.network))
|
||||
<td align="center" class="nowrap"><div class="${fuzzydate}">$sbdatetime.sbdatetime.sbfdate($ldatetime)</div><span class="sort_data">$time.mktime($ldatetime.timetuple())</span></td>
|
||||
#else:
|
||||
<td align="center" class="nowrap"></td>
|
||||
<td align="center" class="nowrap"></td>
|
||||
#end if
|
||||
|
||||
#if $layout == 'small':
|
||||
<td class="tvShow">
|
||||
<div class="imgsmallposter $layout">
|
||||
<a href="$sbRoot/showPoster/?show=$curShow.indexerid&which=poster" rel="dialog" title="$curShow.name">
|
||||
<img src="$sbRoot/showPoster/?show=$curShow.indexerid&which=poster_thumb" class="$layout" alt="$curShow.indexerid"/>
|
||||
</a>
|
||||
|
||||
#if $layout == 'small':
|
||||
<td class="tvShow">
|
||||
<div class="imgsmallposter $layout">
|
||||
<a href="$sbRoot/showPoster/?show=$curShow.indexerid&which=poster" rel="dialog" title="$curShow.name">
|
||||
<img src="$sbRoot/showPoster/?show=$curShow.indexerid&which=poster_thumb" class="$layout" alt="$curShow.indexerid"/>
|
||||
</a>
|
||||
<a href="$sbRoot/home/displayShow?show=$curShow.indexerid" style="vertical-align: middle;">$curShow.name</a>
|
||||
</div>
|
||||
</td>
|
||||
</div>
|
||||
</td>
|
||||
#else if $layout == 'banner':
|
||||
<td>
|
||||
<span style="display: none;">$curShow.name</span>
|
||||
<div class="imgbanner $layout">
|
||||
<a href="$sbRoot/home/displayShow?show=$curShow.indexerid">
|
||||
<img src="$sbRoot/showPoster/?show=$curShow.indexerid&which=banner" class="$layout" alt="$curShow.indexerid" title="$curShow.name"/>
|
||||
</div>
|
||||
</td>
|
||||
#else if $layout == 'simple':
|
||||
<td class="tvShow"><a href="$sbRoot/home/displayShow?show=$curShow.indexerid">$curShow.name</a></td>
|
||||
<td>
|
||||
<span style="display: none;">$curShow.name</span>
|
||||
<div class="imgbanner $layout">
|
||||
<a href="$sbRoot/home/displayShow?show=$curShow.indexerid">
|
||||
<img src="$sbRoot/showPoster/?show=$curShow.indexerid&which=banner" class="$layout" alt="$curShow.indexerid" title="$curShow.name"/>
|
||||
</div>
|
||||
</td>
|
||||
#else if $layout == 'simple':
|
||||
<td class="tvShow"><a href="$sbRoot/home/displayShow?show=$curShow.indexerid">$curShow.name</a></td>
|
||||
#end if
|
||||
|
||||
#if $layout != 'simple':
|
||||
<td align="center">
|
||||
#if $curShow.network:
|
||||
<img id="network" width="54" height="27" src="$sbRoot/images/network/${curShow.network.replace(u"\u00C9",'e').lower()}.png" alt="$curShow.network" title="$curShow.network" />
|
||||
#else:
|
||||
<img id="network" width="54" height="27" src="$sbRoot/images/network/nonetwork.png" alt="No Network" title="No Network" />
|
||||
#end if
|
||||
<span style="display: none;">$curShow.network</span>
|
||||
<img id="network" width="54" height="27" src="$sbRoot/images/network/${curShow.network.replace(u"\u00C9",'e').lower()}.png" alt="$curShow.network" title="$curShow.network" />
|
||||
#else:
|
||||
<img id="network" width="54" height="27" src="$sbRoot/images/network/nonetwork.png" alt="No Network" title="No Network" />
|
||||
#end if
|
||||
</td>
|
||||
#else:
|
||||
#else:
|
||||
<td>
|
||||
$curShow.network
|
||||
<span>$curShow.network</span>
|
||||
</td>
|
||||
#end if
|
||||
#end if
|
||||
|
||||
#if $curShow.quality in $qualityPresets:
|
||||
#if $curShow.quality in $qualityPresets:
|
||||
<td align="center"><span class="quality $qualityPresetStrings[$curShow.quality]">$qualityPresetStrings[$curShow.quality]</span></td>
|
||||
#else:
|
||||
#else:
|
||||
<td align="center"><span class="quality Custom">Custom</span></td>
|
||||
#end if
|
||||
|
||||
#end if
|
||||
|
||||
<td align="center"><span style="display: none;">$progressbar_percent</span><div id="progressbar$curShow.indexerid" style="position:relative;"></div>
|
||||
<script type="text/javascript">
|
||||
<!--
|
||||
|
@ -601,12 +610,12 @@ $myShowList.sort(lambda x, y: cmp(x.name, y.name))
|
|||
//-->
|
||||
</script>
|
||||
</td>
|
||||
|
||||
<td align="center">
|
||||
|
||||
<td align="center">
|
||||
<img src="$sbRoot/images/#if int($curShow.paused) == 0 and $curShow.status != "Ended" then "yes16.png\" alt=\"Y\"" else "no16.png\" alt=\"N\""# width="16" height="16" />
|
||||
</td>
|
||||
|
||||
<td align="center">
|
||||
<td align="center">
|
||||
|
||||
#set $display_status = $curShow.status
|
||||
#if None is not $display_status
|
||||
|
@ -619,7 +628,7 @@ $myShowList.sort(lambda x, y: cmp(x.name, y.name))
|
|||
$display_status
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
#end for
|
||||
</tbody>
|
||||
|
|
|
@ -1,17 +1,15 @@
|
|||
#import os.path
|
||||
#import sickbeard
|
||||
#from sickbeard.common import *
|
||||
#set global $title="Existing Show"
|
||||
#set global $header="Existing Show"
|
||||
#set global $title = 'Existing Show'
|
||||
#set global $header = 'Existing Show'
|
||||
|
||||
#set global $sbPath="../.."
|
||||
#set global $sbPath = '../..'
|
||||
|
||||
#set global $statpath="../.."#
|
||||
#set global $topmenu="home"#
|
||||
#set global $statpath = '../..'
|
||||
#set global $topmenu = 'home'
|
||||
#import os.path
|
||||
#include $os.path.join($sickbeard.PROG_DIR, "gui/slick/interfaces/default/inc_top.tmpl")
|
||||
|
||||
<form id="addShowForm" method="post" action="$sbRoot/home/addShows/addNewShow" accept-charset="utf-8">
|
||||
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_top.tmpl')
|
||||
|
||||
<script type="text/javascript" src="$sbRoot/js/qualityChooser.js?$sbPID"></script>
|
||||
<script type="text/javascript" src="$sbRoot/js/addExistingShow.js?$sbPID"></script>
|
||||
|
@ -21,7 +19,7 @@
|
|||
<script type="text/javascript" charset="utf-8">
|
||||
<!--
|
||||
\$(document).ready(function(){
|
||||
\$( "#tabs" ).tabs({
|
||||
\$( '#tabs' ).tabs({
|
||||
collapsible: true,
|
||||
selected: #if $sickbeard.ROOT_DIRS then '-1' else '0'#
|
||||
});
|
||||
|
@ -29,41 +27,55 @@
|
|||
//-->
|
||||
</script>
|
||||
|
||||
#if $varExists('header')
|
||||
#if $varExists('header')
|
||||
<h1 class="header">$header</h1>
|
||||
#else
|
||||
#else
|
||||
<h1 class="title">$title</h1>
|
||||
#end if
|
||||
|
||||
<div id="tabs">
|
||||
<ul>
|
||||
<li><a href="#tabs-1">Manage Directories</a></li>
|
||||
<li><a href="#tabs-2">Customize Options</a></li>
|
||||
</ul>
|
||||
<div id="tabs-1" class="existingtabs">
|
||||
#include $os.path.join($sickbeard.PROG_DIR, "gui/slick/interfaces/default/inc_rootDirs.tmpl")
|
||||
</div>
|
||||
<div id="tabs-2" class="existingtabs">
|
||||
#include $os.path.join($sickbeard.PROG_DIR, "gui/slick/interfaces/default/inc_addShowOptions.tmpl")
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<image class="preload-image" style="position:absolute;top:-999px" src="$sbRoot/images/loading32<%= '-dark' if 'dark' == sickbeard.THEME_NAME else '' %>.gif" width="32" height="32" border="0">
|
||||
|
||||
<p>SickGear can add existing shows, using the current options, by using locally stored NFO/XML metadata to eliminate user interaction.<br />
|
||||
If you would rather have SickGear prompt you to customize each show, then use the checkbox below.</p>
|
||||
<form id="addShowForm" method="post" action="$sbRoot/home/addShows/addNewShow" accept-charset="utf-8">
|
||||
|
||||
<p><input type="checkbox" name="promptForSettings" id="promptForSettings" /> <label for="promptForSettings">Prompt me to set settings for each show</label></p>
|
||||
<p>Tip: shows are added quicker when usable show nfo and xml metadata is found</p>
|
||||
|
||||
<hr />
|
||||
<p style="margin-top:15px">
|
||||
<input type="checkbox" id="promptForSettings" name="promptForSettings" style="vertical-align: top;" />
|
||||
<label for="promptForSettings">Enable to change the following options per show, otherwise use these options with all shows added below</label>
|
||||
</p>
|
||||
|
||||
<h5><b>Displaying folders within these directories which aren't already added to SickGear:</b></h5>
|
||||
<div id="tabs">
|
||||
<ul>
|
||||
<li><a href="#tabs-1">Manage parent folders</a></li>
|
||||
<li><a href="#tabs-2">Custom options</a></li>
|
||||
</ul>
|
||||
<div id="tabs-1" class="existingtabs">
|
||||
<div style="width: 430px; margin: 0px auto">
|
||||
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_rootDirs.tmpl')
|
||||
</div>
|
||||
</div>
|
||||
<div id="tabs-2">
|
||||
<div class="stepDiv">
|
||||
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_addShowOptions.tmpl')
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ul id="rootDirStaticList"><li></li></ul>
|
||||
<br />
|
||||
<hr />
|
||||
|
||||
<br />
|
||||
<div id="tableDiv"></div>
|
||||
<br />
|
||||
<input class="btn btn-primary" type="button" value="Submit" id="submitShowDirs" />
|
||||
<p>The following parent folder(s) are scanned for existing shows. Toggle a folder to display shows</p>
|
||||
|
||||
<ul id="rootDirStaticList">
|
||||
<li></li>
|
||||
</ul>
|
||||
|
||||
<p>shows <span class="boldest">not known</span> to SickGear are listed below...</p>
|
||||
|
||||
<div id="tableDiv"></div>
|
||||
|
||||
<br />
|
||||
<input class="btn btn-primary" type="button" value="Submit" id="submitShowDirs" />
|
||||
|
||||
</form>
|
||||
#include $os.path.join($sickbeard.PROG_DIR,"gui/slick/interfaces/default/inc_bottom.tmpl")
|
||||
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_bottom.tmpl')
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
#import os.path
|
||||
#import urllib
|
||||
#import sickbeard
|
||||
#set global $title="Add Show"
|
||||
#set global $header="Add Show"
|
||||
#set global $title = 'Add Show'
|
||||
#set global $header = 'Add Show'
|
||||
|
||||
#set global $sbPath="../.."
|
||||
#set global $sbPath = '../..'
|
||||
|
||||
#set global $statpath="../.."#
|
||||
#set global $topmenu="home"#
|
||||
#set global $statpath = '../..'
|
||||
#set global $topmenu = 'home'
|
||||
#import os.path
|
||||
|
||||
#include $os.path.join($sickbeard.PROG_DIR, "gui/slick/interfaces/default/inc_top.tmpl")
|
||||
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_top.tmpl')
|
||||
|
||||
#if $varExists('header')
|
||||
<h1 class="header">$header</h1>
|
||||
|
@ -18,46 +18,49 @@
|
|||
<h1 class="title">$title</h1>
|
||||
#end if
|
||||
|
||||
<div id="addShowPortal">
|
||||
<div id="addShowPortal">
|
||||
|
||||
<a href="$sbRoot/home/addShows/newShow/" id="btnNewShow" class="btn btn-large">
|
||||
<div class="button"><div class="icon-addnewshow"></div></div>
|
||||
<div class="buttontext">
|
||||
<h3>Add New Show</h3>
|
||||
<p>For shows that you haven't downloaded yet, this option finds a show on theTVDB.com and TVRage.com, creates a directory for its episodes, and adds it to SickGear.</p>
|
||||
</div>
|
||||
</a>
|
||||
<a class="btn btn-large" href="$sbRoot/home/addShows/newShow/">
|
||||
<div class="button"><div class="icon-addnewshow"></div></div>
|
||||
<div class="buttontext">
|
||||
<h3>Add New Show</h3>
|
||||
<p>Search a TV database for a show to add. A new folder will be created for episodes</p>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<br/><br/>
|
||||
<a href="$sbRoot/home/addShows/trendingShows/" id="btnNewShow" class="btn btn-large">
|
||||
<div class="button"><div class="icon-addtrendingshow"></div></div>
|
||||
<div class="buttontext">
|
||||
<h3>Add Trending Show</h3>
|
||||
<p>For shows that you haven't downloaded yet, this option lets you choose from a list of current trending shows with ratings to add, creates a directory for its episodes, and adds it to SickGear.</p>
|
||||
</div>
|
||||
</a>
|
||||
<a class="btn btn-large" href="$sbRoot/home/addShows/trendingShows/">
|
||||
<div class="button"><div class="icon-addtrendingshow"></div></div>
|
||||
<div class="buttontext">
|
||||
<h3>Add From Trending</h3>
|
||||
<p>Browse a current trending show list to add from. A folder for episodes will be created</p>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<br/><br/>
|
||||
#if $sickbeard.USE_TRAKT == True:
|
||||
<a href="$sbRoot/home/addShows/recommendedShows/" id="btnNewShow" class="btn btn-large">
|
||||
<div class="button"><div class="icon-addrecommendedshow"></div></div>
|
||||
<div class="buttontext">
|
||||
<h3>Add Recommended Shows</h3>
|
||||
<p>For shows that you haven't downloaded yet, this option recommends shows to add based on your Trakt.tv show library, creates a directory for its episodes, and adds it to SickGear.</p>
|
||||
</div>
|
||||
</a>
|
||||
<a class="btn btn-large" href="$sbRoot/home/addShows/existingShows/">
|
||||
<div class="button"><div class="icon-addexistingshow"></div></div>
|
||||
<div class="buttontext">
|
||||
<h3>Add Existing Shows</h3>
|
||||
<p>Scan parent folders for shows and episode metadata to import into SickGear</p>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<br/><br/>
|
||||
#end if
|
||||
<a href="$sbRoot/home/addShows/existingShows/" id="btnExistingShow" class="btn btn-large">
|
||||
<div class="button"><div class="icon-addexistingshow"></div></div>
|
||||
<div class="buttontext">
|
||||
<h3>Add Existing Shows</h3>
|
||||
<p>Use this option to add shows that already have a folder created on your hard drive. SickGear will scan your existing metadata/episodes and add the show accordingly.</p>
|
||||
</div>
|
||||
</a>
|
||||
#if True == $sickbeard.USE_TRAKT:
|
||||
<a class="btn btn-large" href="$sbRoot/home/addShows/recommendedShows/">
|
||||
<div class="button"><div class="icon-addrecommendedshow"></div></div>
|
||||
<div class="buttontext">
|
||||
<h3>Add Recommended</h3>
|
||||
<p>Browse recommendations based on your Trakt.tv show library to add to SickGear</p>
|
||||
</div>
|
||||
</a>
|
||||
#else
|
||||
<div class="buttontext" style="padding:10px 5px">
|
||||
<p>There's more... unlock another button to browse<br />
|
||||
recommended shows based on your Trakt.tv show<br />
|
||||
library by enabling Trakt in Config/Notifications/Social</p>
|
||||
</div>
|
||||
#end if
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div style="clear:both"> </div>
|
||||
|
||||
|
||||
#include $os.path.join($sickbeard.PROG_DIR,"gui/slick/interfaces/default/inc_bottom.tmpl")
|
||||
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_bottom.tmpl')
|
|
@ -2,10 +2,10 @@
|
|||
#from sickbeard.helpers import anon_url
|
||||
|
||||
<table id="addRootDirTable" class="sickbeardTable tablesorter">
|
||||
<thead><tr><th class="col-checkbox"><input type="checkbox" id="checkAll" checked=checked></th><th>Directory</th><th width="20%">Show Name (tvshow.nfo)<th width="20%">Indexer</td></tr></thead>
|
||||
<thead><tr><th class="col-checkbox"><input type="checkbox" id="checkAll" checked=checked></th><th>Parent\show folder</th><th width="20%">Show name<br />(tvshow.nfo)<th width="15%">TV database</td></tr></thead>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th rowspan="1" colspan="4" align="left"><a href="#" style="padding-left: 10px;" class="showManage">Manage Directories</a></th>
|
||||
<th rowspan="1" colspan="4" align="left"><a href="#" class="showManage">Manage Directories</a></th>
|
||||
</tr>
|
||||
</tfoot>
|
||||
<tbody>
|
||||
|
@ -31,7 +31,7 @@
|
|||
<td class="col-checkbox"><input type="checkbox" id="$show_id" class="dirCheck" checked=checked></td>
|
||||
<td><label for="$show_id">$curDir['display_dir']</label></td>
|
||||
#if $curDir['existing_info'][1] and $indexer > 0:
|
||||
<td><a href="<%= anon_url(sickbeard.indexerApi(indexer).config['show_url'], curDir['existing_info'][0]) %>">$curDir['existing_info'][1]</a></td>
|
||||
<td><a href="<%= anon_url(sickbeard.indexerApi(indexer).config['show_url'], curDir['existing_info'][0]) %>" target="_new">$curDir['existing_info'][1]</a></td>
|
||||
#else:
|
||||
<td>?</td>
|
||||
#end if
|
||||
|
|
|
@ -24,15 +24,17 @@
|
|||
<h1 class="title">$title</h1>
|
||||
#end if
|
||||
|
||||
<image class="preload-image" style="position:absolute;top:-999px" src="$sbRoot/images/loading32<%= '-dark' if 'dark' == sickbeard.THEME_NAME else '' %>.gif" width="32" height="32" border="0">
|
||||
|
||||
<div id="newShowPortal">
|
||||
|
||||
<div id="displayText">aoeu</div>
|
||||
<br />
|
||||
|
||||
<form id="addShowForm" method="post" action="$sbRoot/home/addShows/addNewShow" accept-charset="utf-8" style="width: 800px;">
|
||||
<form id="addShowForm" method="post" action="$sbRoot/home/addShows/addNewShow" accept-charset="utf-8">
|
||||
|
||||
<fieldset class="sectionwrap">
|
||||
<legend class="legendStep">Find a show on the TVDB or TVRAGE</legend>
|
||||
<fieldset class="sectionwrap step-one">
|
||||
<legend class="legendStep"><p>Find show at a TV database</p></legend>
|
||||
|
||||
<div class="stepDiv">
|
||||
<input type="hidden" id="indexer_timeout" value="$sickbeard.INDEXER_TIMEOUT" />
|
||||
|
@ -48,10 +50,10 @@
|
|||
#else
|
||||
<input type="text" id="nameToSearch" value="$default_show_name" class="form-control form-control-inline input-sm input350" />
|
||||
|
||||
<span style="float:right">
|
||||
<select name="indexerLang" id="indexerLangSelect" class="form-control form-control-inline input-sm">
|
||||
<option value="en" selected="selected">en</option>
|
||||
</select><b>*</b>
|
||||
|
||||
</select><b> *</b>
|
||||
<select name="providedIndexer" id="providedIndexer" class="form-control form-control-inline input-sm">
|
||||
<option value="0" #if $provided_indexer == 0 then "selected=\"selected\"" else ""#>All Indexers</option>
|
||||
#for $indexer in $indexers
|
||||
|
@ -60,21 +62,21 @@
|
|||
</select>
|
||||
|
||||
<input class="btn btn-inline" type="button" id="searchName" value="Search" />
|
||||
</span>
|
||||
<br />
|
||||
<p style="margin:5px 0 15px"><b>*</b> SickGear supports english episodes. The language choice is used for fetching metadata and episode filenames</p>
|
||||
|
||||
<br />
|
||||
<b>*</b> This will only affect the language of the retrieved metadata file contents and episode filenames.<br />
|
||||
This <b>DOES NOT</b> allow SickGear to download non-english TV episodes!<br />
|
||||
<br />
|
||||
<div id="searchResults" style="height: 100%;"><br/></div>
|
||||
<div id="searchResults" style="height: 100%"></div>
|
||||
#end if
|
||||
|
||||
</div>
|
||||
<div style="clear:both"> </div>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="sectionwrap">
|
||||
<legend class="legendStep">Pick the parent folder</legend>
|
||||
<fieldset class="sectionwrap step-two">
|
||||
<legend class="legendStep"><p>Pick parent folder</p></legend>
|
||||
|
||||
<div class="stepDiv">
|
||||
<div class="stepDiv parent-folder">
|
||||
#if $provided_show_dir
|
||||
Pre-chosen Destination Folder: <b>$provided_show_dir</b> <br />
|
||||
<input type="hidden" id="fullShowPath" name="fullShowPath" value="$provided_show_dir" /><br />
|
||||
|
@ -82,13 +84,15 @@
|
|||
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_rootDirs.tmpl')
|
||||
#end if
|
||||
</div>
|
||||
<div style="clear:both"> </div>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="sectionwrap">
|
||||
<legend class="legendStep">Customize options</legend>
|
||||
<fieldset class="sectionwrap step-three">
|
||||
<legend class="legendStep"><p>Set custom options</p></legend>
|
||||
<div class="stepDiv">
|
||||
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_addShowOptions.tmpl')
|
||||
</div>
|
||||
<div style="clear:both"> </div>
|
||||
</fieldset>
|
||||
|
||||
#for $curNextDir in $other_shows
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
|
||||
#include $os.path.join($sickbeard.PROG_DIR, "gui/slick/interfaces/default/inc_top.tmpl")
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="$sbRoot/css/formwizard.css?$sbPID" />
|
||||
<script type="text/javascript" src="$sbRoot/js/formwizard.js?$sbPID"></script>
|
||||
<script type="text/javascript" src="$sbRoot/js/qualityChooser.js?$sbPID"></script>
|
||||
<script type="text/javascript" src="$sbRoot/js/recommendedShows.js?$sbPID"></script>
|
||||
|
@ -24,35 +23,40 @@
|
|||
<h1 class="title">$title</h1>
|
||||
#end if
|
||||
|
||||
<image class="preload-image" style="position:absolute;top:-999px" src="$sbRoot/images/loading32<%= '-dark' if 'dark' == sickbeard.THEME_NAME else '' %>.gif" width="32" height="32" border="0">
|
||||
|
||||
<div id="newShowPortal">
|
||||
|
||||
<div id="displayText"></div>
|
||||
<br />
|
||||
|
||||
<form id="recommendedShowsForm" method="post" action="$sbRoot/home/addShows/addRecommendedShow" accept-charset="utf-8" style="width: 800px;">
|
||||
<form id="addShowForm" method="post" action="$sbRoot/home/addShows/addRecommendedShow" accept-charset="utf-8">
|
||||
|
||||
<fieldset class="sectionwrap">
|
||||
<legend class="legendStep">Select a recommended show</legend>
|
||||
<fieldset class="sectionwrap step-one">
|
||||
<legend class="legendStep"><p>Select a recommended show</p></legend>
|
||||
|
||||
<div class="stepDiv">
|
||||
<div id="searchResults" style="height: 100%;"><br/></div>
|
||||
</div>
|
||||
<div style="clear:both"> </div>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="sectionwrap">
|
||||
<legend class="legendStep">Pick the parent folder</legend>
|
||||
<fieldset class="sectionwrap step-two">
|
||||
<legend class="legendStep"><p>Pick parent folder</p></legend>
|
||||
|
||||
<div class="stepDiv">
|
||||
<div class="stepDiv parent-folder">
|
||||
#include $os.path.join($sickbeard.PROG_DIR, "gui/slick/interfaces/default/inc_rootDirs.tmpl")
|
||||
</div>
|
||||
<div style="clear:both"> </div>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="sectionwrap">
|
||||
<legend class="legendStep">Customize options</legend>
|
||||
<fieldset class="sectionwrap step-three">
|
||||
<legend class="legendStep"><p>Set custom options</p></legend>
|
||||
|
||||
<div class="stepDiv">
|
||||
#include $os.path.join($sickbeard.PROG_DIR, "gui/slick/interfaces/default/inc_addShowOptions.tmpl")
|
||||
</div>
|
||||
<div style="clear:both"> </div>
|
||||
</fieldset>
|
||||
</form>
|
||||
|
||||
|
|
|
@ -2,62 +2,77 @@
|
|||
#from sickbeard.common import *
|
||||
#from sickbeard import subtitles
|
||||
|
||||
#if $sickbeard.USE_SUBTITLES:
|
||||
<div class="field-pair alt">
|
||||
<input type="checkbox" name="subtitles" id="subtitles" #if $sickbeard.SUBTITLES_DEFAULT then "checked=\"checked\"" else ""# />
|
||||
<label for="subtitles" class="clearfix">
|
||||
<span class="component-title">Subtitles</span>
|
||||
<span class="component-desc">Download subtitles for this show?</span>
|
||||
</label>
|
||||
</div>
|
||||
#end if
|
||||
|
||||
<div class="field-pair">
|
||||
<label for="statusSelect" class="nocheck clearfix">
|
||||
<span class="component-title">
|
||||
<select name="defaultStatus" id="statusSelect" class="form-control form-control-inline input-sm">
|
||||
#for $curStatus in [$SKIPPED, $WANTED, $ARCHIVED, $IGNORED]:
|
||||
<option value="$curStatus" #if $sickbeard.STATUS_DEFAULT == $curStatus then 'selected="selected"' else ''#>$statusStrings[$curStatus]</option>
|
||||
#end for
|
||||
</select>
|
||||
</span>
|
||||
<span class="component-desc">Set the initial status of missing episodes</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="field-pair alt">
|
||||
<input class="cb" type="checkbox" name="flatten_folders" id="flatten_folders" #if $sickbeard.FLATTEN_FOLDERS_DEFAULT then "checked=\"checked\"" else ""# />
|
||||
<label for="flatten_folders" class="clearfix">
|
||||
<span class="component-title">Flatten Folders</span>
|
||||
<span class="component-desc">Disregard sub-folders?</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
<label for="statusSelect">
|
||||
<span class="component-title input">Initial episode status</span>
|
||||
<span class="component-desc">
|
||||
<select name="defaultStatus" id="statusSelect" class="form-control form-control-inline input-sm">
|
||||
#for $curStatus in [$SKIPPED, $WANTED, $ARCHIVED, $IGNORED]:
|
||||
<option value="$curStatus" #if $sickbeard.STATUS_DEFAULT == $curStatus then 'selected="selected"' else ''#>$statusStrings[$curStatus]</option>
|
||||
#end for
|
||||
</select>
|
||||
<span>set the initial status of missing episodes</span>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="field-pair alt">
|
||||
<input type="checkbox" name="anime" id="anime" #if $sickbeard.ANIME_DEFAULT then "checked=\"checked\"" else ""# />
|
||||
<label for="anime" class="clearfix">
|
||||
<span class="component-title">Anime</span>
|
||||
<span class="component-desc">Is this show an Anime?</span>
|
||||
</label>
|
||||
</div>
|
||||
<p class="grey-text">Tip: The following options are <span style="font-weight:800">edit</span>able later in the detail view of the show</p>
|
||||
</div>
|
||||
|
||||
<div class="field-pair alt">
|
||||
<input type="checkbox" name="scene" id="scene" #if $sickbeard.SCENE_DEFAULT then "checked=\"checked\"" else ""# />
|
||||
<label for="scene" class="clearfix">
|
||||
<span class="component-title">Scene Numbering</span>
|
||||
<span class="component-desc">Is this show scene numbered?</span>
|
||||
</label>
|
||||
</div>
|
||||
#if $sickbeard.USE_SUBTITLES:
|
||||
<div class="field-pair alt">
|
||||
<label for="subtitles">
|
||||
<span class="component-title">Subtitles</span>
|
||||
<span class="component-desc">
|
||||
<input type="checkbox" name="subtitles" id="subtitles" #if $sickbeard.SUBTITLES_DEFAULT then "checked=\"checked\"" else ""# />
|
||||
<p>download subtitles for this show</p>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
#end if
|
||||
|
||||
#set $qualities = $Quality.splitQuality($sickbeard.QUALITY_DEFAULT)
|
||||
#set global $anyQualities = $qualities[0]
|
||||
#set global $bestQualities = $qualities[1]
|
||||
#include $os.path.join($sickbeard.PROG_DIR, "gui/slick/interfaces/default/inc_qualityChooser.tmpl")
|
||||
|
||||
<br>
|
||||
<div class="field-pair alt">
|
||||
<label for="saveDefaultsButton" class="nocheck clearfix">
|
||||
<span class="component-title"><input class="btn btn-inline" type="button" id="saveDefaultsButton" value="Save Defaults" disabled="disabled" /></span>
|
||||
<span class="component-desc">Persist current values as the defaults</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="field-pair alt">
|
||||
<label for="flatten_folders">
|
||||
<span class="component-title">Flatten folders</span>
|
||||
<span class="component-desc">
|
||||
<input class="cb" type="checkbox" name="flatten_folders" id="flatten_folders" #if $sickbeard.FLATTEN_FOLDERS_DEFAULT then "checked=\"checked\"" else ""# />
|
||||
<p>do not create sub folders</p>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="field-pair alt">
|
||||
<label for="anime">
|
||||
<span class="component-title">Anime</span>
|
||||
<span class="component-desc">
|
||||
<input type="checkbox" name="anime" id="anime" #if $sickbeard.ANIME_DEFAULT then "checked=\"checked\"" else ""# />
|
||||
<p>use anime processing for this show</p>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="field-pair alt">
|
||||
<label for="scene">
|
||||
<span class="component-title">Scene numbering</span>
|
||||
<span class="component-desc">
|
||||
<input type="checkbox" name="scene" id="scene" #if $sickbeard.SCENE_DEFAULT then "checked=\"checked\"" else ""# />
|
||||
<p>enable if episodes are numbered by scene releases and not by the TV network</p>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
#set $qualities = $Quality.splitQuality($sickbeard.QUALITY_DEFAULT)
|
||||
#set global $anyQualities = $qualities[0]
|
||||
#set global $bestQualities = $qualities[1]
|
||||
#include $os.path.join($sickbeard.PROG_DIR, "gui/slick/interfaces/default/inc_qualityChooser.tmpl")
|
||||
|
||||
<div class="field-pair alt" style="margin-top:30px">
|
||||
<label for="saveDefaultsButton">
|
||||
<span class="component-title">Save options as defaults</span>
|
||||
<span class="component-desc">
|
||||
<input class="btn btn-inline" type="button" id="saveDefaultsButton" value="Save Defaults" disabled="disabled" />
|
||||
<p>reuse the above options when adding more shows</p>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
|
|
|
@ -38,9 +38,30 @@
|
|||
#set $ep_downloaded = 0
|
||||
#set $ep_total = 0
|
||||
#end if
|
||||
#try
|
||||
#set $localRoot = $sbRoot
|
||||
#except NotFound
|
||||
#set $localRoot = ''
|
||||
#end try
|
||||
#try
|
||||
#set $localheader = $header
|
||||
#except NotFound
|
||||
#set $localheader = ''
|
||||
#end try
|
||||
|
||||
<span class="footerhighlight">$shows_total</span> shows (<span class="footerhighlight">$shows_active</span> active)
|
||||
| <span class="footerhighlight"><%= ep_downloaded %></span><%= ('', ' (<span class="footerhighlight">+%s</span> snatched)' % str(ep_snatched))[ep_snatched > 0] %> / <span class="footerhighlight">$ep_total</span> episodes downloaded
|
||||
| <span class="footerhighlight"><%= ep_downloaded %></span>
|
||||
<%= (
|
||||
'',\
|
||||
' (<span class="footerhighlight">+%s</span> snatched)' % \
|
||||
(
|
||||
str(ep_snatched),
|
||||
'<a href="%s/manage/episodeStatuses?whichStatus=2" title="View overview of snatched episodes">%s</a>' % \
|
||||
(localRoot, str(ep_snatched))
|
||||
)['Episode Overview' != localheader]
|
||||
)[0 < ep_snatched]
|
||||
%>
|
||||
/ <span class="footerhighlight">$ep_total</span> episodes downloaded
|
||||
| daily search: <span class="footerhighlight"><%= str(sickbeard.dailySearchScheduler.timeLeft()).split('.')[0] %></span>
|
||||
| backlog search: <span class="footerhighlight">$sbdatetime.sbdatetime.sbfdate($sickbeard.backlogSearchScheduler.nextRun())</span>
|
||||
|
||||
|
|
|
@ -2,46 +2,48 @@
|
|||
#from sickbeard.common import Quality, qualityPresets, qualityPresetStrings
|
||||
|
||||
<div class="field-pair">
|
||||
<label for="qualityPreset" class="nocheck clearfix">
|
||||
<label for="qualityPreset" class="clearfix">
|
||||
#set $overall_quality = $Quality.combineQualities($anyQualities, $bestQualities)
|
||||
<span class="component-title">
|
||||
<span class="component-title input">Quality</span>
|
||||
<span class="component-desc">
|
||||
#set $selected = None
|
||||
<select id="qualityPreset" class="form-control form-control-inline input-sm">
|
||||
<option value="0">Custom</option>
|
||||
<select id="qualityPreset" class="form-control form-control-inline input-sm">
|
||||
<option value="0">Custom</option>
|
||||
#for $curPreset in sorted($qualityPresets):
|
||||
<option value="$curPreset" #if $curPreset == $overall_quality then "selected=\"selected\"" else ""# #if $qualityPresetStrings[$curPreset].endswith("0p") then "style=\"padding-left: 15px;\"" else ""#>$qualityPresetStrings[$curPreset]</option>
|
||||
<option value="$curPreset" #if $curPreset == $overall_quality then "selected=\"selected\"" else ""# #if $qualityPresetStrings[$curPreset].endswith("0p") then "style=\"padding-left: 15px;\"" else ""#>$qualityPresetStrings[$curPreset]</option>
|
||||
#end for
|
||||
</select>
|
||||
</span>
|
||||
<span class="component-desc">Preferred quality of episodes to be download</span>
|
||||
|
||||
</label>
|
||||
</select>
|
||||
<span>preferred episode quality to download</span>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div id="customQualityWrapper">
|
||||
<div id="customQuality">
|
||||
<div class="component-group-desc">
|
||||
<p>One of the <b>Initial</b> quality selections must be obtained before SickGear will attempt to process the <b>Archive</b> selections.</p>
|
||||
</div>
|
||||
<div class="component-group-desc">
|
||||
<p>One of the <em>Initial</em> quality selections must succeed before attempting to process <em>Archive</em> selections.</p>
|
||||
</div>
|
||||
|
||||
<div style="padding-right: 40px; text-align: center;" class="float-left">
|
||||
<h4>Initial</h4>
|
||||
#set $anyQualityList = filter(lambda x: x > $Quality.NONE, $Quality.qualityStrings)
|
||||
<select id="anyQualities" name="anyQualities" multiple="multiple" size="$len($anyQualityList)" class="form-control form-control-inline input-sm">
|
||||
#for $curQuality in sorted($anyQualityList):
|
||||
<option value="$curQuality" #if $curQuality in $anyQualities then "selected=\"selected\"" else ""#>$Quality.qualityStrings[$curQuality]</option>
|
||||
#end for
|
||||
</select>
|
||||
</div>
|
||||
<span class="component-desc">
|
||||
<div style="float:left; padding-right: 40px">
|
||||
<h4>Initial</h4>
|
||||
#set $anyQualityList = filter(lambda x: x > $Quality.NONE, $Quality.qualityStrings)
|
||||
<select id="anyQualities" name="anyQualities" multiple="multiple" size="$len($anyQualityList)" class="form-control form-control-inline input-sm">
|
||||
#for $curQuality in sorted($anyQualityList):
|
||||
<option value="$curQuality" #if $curQuality in $anyQualities then "selected=\"selected\"" else ""#>$Quality.qualityStrings[$curQuality]</option>
|
||||
#end for
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div style="text-align: center;" class="float-left">
|
||||
<h4>Archive</h4>
|
||||
#set $bestQualityList = filter(lambda x: x > $Quality.SDTV and x < $Quality.UNKNOWN, $Quality.qualityStrings)
|
||||
<select id="bestQualities" name="bestQualities" multiple="multiple" size="$len($bestQualityList)" class="form-control form-control-inline input-sm">
|
||||
#for $curQuality in sorted($bestQualityList):
|
||||
<option value="$curQuality" #if $curQuality in $bestQualities then "selected=\"selected\"" else ""#>$Quality.qualityStrings[$curQuality]</option>
|
||||
#end for
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div style="float:left">
|
||||
<h4>Archive</h4>
|
||||
#set $bestQualityList = filter(lambda x: x > $Quality.SDTV and x < $Quality.UNKNOWN, $Quality.qualityStrings)
|
||||
<select id="bestQualities" name="bestQualities" multiple="multiple" size="$len($bestQualityList)" class="form-control form-control-inline input-sm">
|
||||
#for $curQuality in sorted($bestQualityList):
|
||||
<option value="$curQuality" #if $curQuality in $bestQualities then "selected=\"selected\"" else ""#>$Quality.qualityStrings[$curQuality]</option>
|
||||
#end for
|
||||
</select>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
|
||||
<title>SickGear - BRANCH:[$sickbeard.BRANCH] - $title</title>
|
||||
|
||||
<!--[if lt IE 9]>
|
||||
|
@ -37,7 +37,7 @@
|
|||
<link rel="stylesheet" type="text/css" href="$sbRoot/css/lib/bootstrap.css?$sbPID"/>
|
||||
<link rel="stylesheet" type="text/css" href="$sbRoot/css/browser.css?$sbPID" />
|
||||
<link rel="stylesheet" type="text/css" href="$sbRoot/css/lib/jquery-ui-1.10.4.custom.css?$sbPID" />
|
||||
<link rel="stylesheet" type="text/css" href="$sbRoot/css/lib/jquery.qtip-2.0.1.min.css?$sbPID"/>
|
||||
<link rel="stylesheet" type="text/css" href="$sbRoot/css/lib/jquery.qtip-2.2.1.min.css?$sbPID"/>
|
||||
<link rel="stylesheet" type="text/css" href="$sbRoot/css/lib/pnotify.custom.min.css?$sbPID" />
|
||||
<link rel="stylesheet" type="text/css" href="$sbRoot/css/style.css?$sbPID"/>
|
||||
<link rel="stylesheet" type="text/css" href="$sbRoot/css/${sickbeard.THEME_NAME}.css?$sbPID" />
|
||||
|
@ -52,7 +52,7 @@
|
|||
<script type="text/javascript" src="$sbRoot/js/lib/jquery.selectboxes.min.js?$sbPID"></script>
|
||||
<script type="text/javascript" src="$sbRoot/js/lib/jquery.tablesorter-2.17.7.min.js?$sbPID"></script>
|
||||
<script type="text/javascript" src="$sbRoot/js/lib/jquery.tablesorter.widgets-2.17.7.min.js?$sbPID"></script>
|
||||
<script type="text/javascript" src="$sbRoot/js/lib/jquery.qtip-2.0.1.min.js?$sbPID"></script>
|
||||
<script type="text/javascript" src="$sbRoot/js/lib/jquery.qtip-2.2.1.min.js?$sbPID"></script>
|
||||
<script type="text/javascript" src="$sbRoot/js/lib/pnotify.custom.min.js"></script>
|
||||
<script type="text/javascript" src="$sbRoot/js/lib/jquery.form-3.35.js?$sbPID"></script>
|
||||
<script type="text/javascript" src="$sbRoot/js/lib/jquery.ui.touch-punch-0.2.2.min.js?$sbPID"></script>
|
||||
|
@ -61,10 +61,10 @@
|
|||
<script type="text/javascript" src="$sbRoot/js/script.js?$sbPID"></script>
|
||||
|
||||
|
||||
#if $sickbeard.FUZZY_DATING:
|
||||
#if $sickbeard.FUZZY_DATING:
|
||||
<script type="text/javascript" src="$sbRoot/js/moment/moment.min.js?$sbPID"></script>
|
||||
<script type="text/javascript" src="$sbRoot/js/fuzzyMoment.js?$sbPID"></script>
|
||||
#end if
|
||||
#end if
|
||||
<script type="text/javascript" charset="utf-8">
|
||||
<!--
|
||||
sbRoot = '$sbRoot'; // needed for browser.js & ajaxNotifications.js
|
||||
|
@ -98,7 +98,6 @@
|
|||
\$("#SubMenu a:contains('Anime')").addClass('btn').html('<span class="submenu-icon-anime pull-left"></span> Anime');
|
||||
\$("#SubMenu a:contains('Settings')").addClass('btn').html('<span class="ui-icon ui-icon-search pull-left"></span> Search Settings');
|
||||
\$("#SubMenu a:contains('Provider')").addClass('btn').html('<span class="ui-icon ui-icon-search pull-left"></span> Search Providers');
|
||||
\$("#SubMenu a:contains('Backup/Restore')").addClass('btn').html('<span class="ui-icon ui-icon-gear pull-left"></span> Backup/Restore');
|
||||
\$("#SubMenu a:contains('General')").addClass('btn').html('<span class="ui-icon ui-icon-gear pull-left"></span> General');
|
||||
\$("#SubMenu a:contains('Episode Status')").addClass('btn').html('<span class="ui-icon ui-icon-transferthick-e-w pull-left"></span> Episode Status Management');
|
||||
\$("#SubMenu a:contains('Missed Subtitle')").addClass('btn').html('<span class="ui-icon ui-icon-transferthick-e-w pull-left"></span> Missed Subtitles');
|
||||
|
@ -119,13 +118,13 @@
|
|||
\$("#NAV$topmenu").addClass("active");
|
||||
|
||||
\$('.dropdown-toggle').dropdownHover();
|
||||
|
||||
|
||||
});
|
||||
//-->
|
||||
</script>
|
||||
<script type="text/javascript" src="$sbRoot/js/confirmations.js?$sbPID"></script>
|
||||
<script type="text/javascript" src="$sbRoot/js/confirmations.js?$sbPID"></script>
|
||||
</head>
|
||||
|
||||
#set $tab = 4
|
||||
<body>
|
||||
<nav class="navbar navbar-default navbar-fixed-top" role="navigation">
|
||||
<div class="container-fluid">
|
||||
|
@ -136,84 +135,83 @@
|
|||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="$sbRoot/home/" title="SickGear"><img alt="SickGear" src="$sbRoot/images/sickgear.png" style="height: 50px;" class="img-responsive pull-left" /></a>
|
||||
<a href="$sbRoot/home/" class="navbar-brand" tabindex="-1" title="SickGear"><img alt="SickGear" src="$sbRoot/images/sickgear.png" style="height: 50px;" class="img-responsive pull-left" /></a>
|
||||
</div>
|
||||
|
||||
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li id="NAVhome" class="dropdown">
|
||||
<a href="$sbRoot/home/" class="dropdown-toggle" data-toggle="dropdown">Shows <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="$sbRoot/home/"><i class="menu-icon-home"></i> Show List</a></li>
|
||||
<li><a href="$sbRoot/home/addShows/"><i class="menu-icon-addshow"></i> Add Shows</a></li>
|
||||
<li><a href="$sbRoot/home/postprocess/"><i class="menu-icon-postprocess"></i> Manual Post-Processing</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li id="NAVcomingEpisodes">
|
||||
<a href="$sbRoot/comingEpisodes/">Coming Episodes</a>
|
||||
</li>
|
||||
|
||||
<li id="NAVhistory">
|
||||
<a href="$sbRoot/history/">History</a>
|
||||
</li>
|
||||
|
||||
<li id="NAVmanage" class="dropdown">
|
||||
<a href="$sbRoot/manage/" class="dropdown-toggle" data-toggle="dropdown">Manage <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="$sbRoot/manage/"><i class="menu-icon-manage"></i> Mass Update</a></li>
|
||||
<li><a href="$sbRoot/manage/backlogOverview/"><i class="menu-icon-backlog-view"></i> Backlog Overview</a></li>
|
||||
<li><a href="$sbRoot/manage/manageSearches/"><i class="menu-icon-manage-searches"></i> Manage Searches</a></li>
|
||||
<li><a href="$sbRoot/manage/episodeStatuses/"><i class="menu-icon-backlog"></i> Episode Status Management</a></li>
|
||||
#if $sickbeard.USE_PLEX and $sickbeard.PLEX_SERVER_HOST != "":
|
||||
<li><a href="$sbRoot/home/updatePLEX/"><i class="menu-icon-backlog-view"></i> Update PLEX</a></li>
|
||||
#end if
|
||||
#if $sickbeard.USE_XBMC and $sickbeard.XBMC_HOST != "":
|
||||
<li><a href="$sbRoot/home/updateXBMC/"><i class="menu-icon-xbmc"></i> Update XBMC</a></li>
|
||||
#end if
|
||||
#if $sickbeard.USE_TORRENTS and $sickbeard.TORRENT_METHOD != 'blackhole' \
|
||||
and ($sickbeard.ENABLE_HTTPS and $sickbeard.TORRENT_HOST[:5] == 'https' \
|
||||
or not $sickbeard.ENABLE_HTTPS and $sickbeard.TORRENT_HOST[:5] == 'http:'):
|
||||
<li><a href="$sbRoot/manage/manageTorrents/"><i class="menu-icon-bittorrent"></i> Manage Torrents</a></li>
|
||||
#end if
|
||||
#if $sickbeard.USE_FAILED_DOWNLOADS:
|
||||
<li><a href="$sbRoot/manage/failedDownloads/"><i class="menu-icon-failed-download"></i> Failed Downloads</a></li>
|
||||
#end if
|
||||
#if $sickbeard.USE_SUBTITLES:
|
||||
<li><a href="$sbRoot/manage/subtitleMissed/"><i class="menu-icon-backlog"></i> Missed Subtitle Management</a></li>
|
||||
#end if
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li id="NAVerrorlogs" class="dropdown">
|
||||
<a href="$sbRoot/errorlogs/" class="dropdown-toggle" data-toggle="dropdown">$logPageTitle <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="$sbRoot/errorlogs/"><i class="menu-icon-viewlog-errors"></i> View Log (Errors)</a></li>
|
||||
<li><a href="$sbRoot/errorlogs/viewlog/"><i class="menu-icon-viewlog"></i> View Log</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li id="NAVconfig" class="dropdown">
|
||||
<a href="$sbRoot/config/" class="dropdown-toggle" data-toggle="dropdown"><img src="$sbRoot/images/menu/system18.png" class="navbaricon hidden-xs" /><b class="caret hidden-xs"></b><span class="visible-xs">Config <b class="caret"></b></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="$sbRoot/config/"><i class="menu-icon-help"></i> Help & Info</a></li>
|
||||
<li><a href="$sbRoot/config/general/"><i class="menu-icon-config"></i> General</a></li>
|
||||
<li><a href="$sbRoot/config/backuprestore/"><i class="menu-icon-config"></i> Backup & Restore</a></li>
|
||||
<li><a href="$sbRoot/config/search/"><i class="menu-icon-config"></i> Search Settings</a></li>
|
||||
<li><a href="$sbRoot/config/providers/"><i class="menu-icon-config"></i> Search Providers</a></li>
|
||||
<li><a href="$sbRoot/config/subtitles/"><i class="menu-icon-config"></i> Subtitles Settings</a></li>
|
||||
<li><a href="$sbRoot/config/postProcessing/"><i class="menu-icon-config"></i> Post Processing</a></li>
|
||||
<li><a href="$sbRoot/config/notifications/"><i class="menu-icon-config"></i> Notifications</a></li>
|
||||
<li><a href="$sbRoot/config/anime/"><i class="menu-icon-config"></i> Anime</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><img src="$sbRoot/images/menu/system18-2.png" class="navbaricon hidden-xs" /><b class="caret hidden-xs"></b><span class="visible-xs">System <b class="caret"></b></span></a>
|
||||
<a href="$sbRoot/home/" class="dropdown-toggle" data-toggle="dropdown" tabindex="$tab#set $tab += 1#">Shows <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="$sbRoot/manage/manageSearches/forceVersionCheck"><i class="menu-icon-update"></i> Force Version Check</a></li>
|
||||
<li><a href="$sbRoot/home/restart/?pid=$sbPID" class="confirm restart"><i class="menu-icon-restart"></i> Restart</a></li>
|
||||
<li><a href="$sbRoot/home/shutdown/?pid=$sbPID" class="confirm shutdown"><i class="menu-icon-shutdown"></i> Shutdown</a></li>
|
||||
<li><a href="$sbRoot/home/" tabindex="$tab#set $tab += 1#"><i class="menu-icon-home"></i> Show List</a></li>
|
||||
<li><a href="$sbRoot/home/addShows/" tabindex="$tab#set $tab += 1#"><i class="menu-icon-addshow"></i> Add Shows</a></li>
|
||||
<li><a href="$sbRoot/home/postprocess/" tabindex="$tab#set $tab += 1#"><i class="menu-icon-postprocess"></i> Manual Post-Processing</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li id="NAVcomingEpisodes">
|
||||
<a href="$sbRoot/comingEpisodes/" tabindex="$tab#set $tab += 1#">Coming Episodes</a>
|
||||
</li>
|
||||
|
||||
<li id="NAVhistory">
|
||||
<a href="$sbRoot/history/" tabindex="$tab#set $tab += 1#">History</a>
|
||||
</li>
|
||||
|
||||
<li id="NAVmanage" class="dropdown">
|
||||
<a href="$sbRoot/manage/" class="dropdown-toggle" data-toggle="dropdown" tabindex="$tab#set $tab += 1#">Manage <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="$sbRoot/manage/" tabindex="$tab#set $tab += 1#"><i class="menu-icon-manage"></i> Mass Update</a></li>
|
||||
<li><a href="$sbRoot/manage/backlogOverview/" tabindex="$tab#set $tab += 1#"><i class="menu-icon-backlog-view"></i> Backlog Overview</a></li>
|
||||
<li><a href="$sbRoot/manage/manageSearches/" tabindex="$tab#set $tab += 1#"><i class="menu-icon-manage-searches"></i> Manage Searches</a></li>
|
||||
<li><a href="$sbRoot/manage/episodeStatuses/" tabindex="$tab#set $tab += 1#"><i class="menu-icon-backlog"></i> Episode Status Management</a></li>
|
||||
#if $sickbeard.USE_PLEX and $sickbeard.PLEX_SERVER_HOST != "":
|
||||
<li><a href="$sbRoot/home/updatePLEX/" tabindex="$tab#set $tab += 1#"><i class="menu-icon-backlog-view"></i> Update PLEX</a></li>
|
||||
#end if
|
||||
#if $sickbeard.USE_XBMC and $sickbeard.XBMC_HOST != "":
|
||||
<li><a href="$sbRoot/home/updateXBMC/" tabindex="$tab#set $tab += 1#"><i class="menu-icon-xbmc"></i> Update XBMC</a></li>
|
||||
#end if
|
||||
#if $sickbeard.USE_TORRENTS and $sickbeard.TORRENT_METHOD != 'blackhole' \
|
||||
and ($sickbeard.ENABLE_HTTPS and $sickbeard.TORRENT_HOST[:5] == 'https' \
|
||||
or not $sickbeard.ENABLE_HTTPS and $sickbeard.TORRENT_HOST[:5] == 'http:'):
|
||||
<li><a href="$sbRoot/manage/manageTorrents/" tabindex="$tab#set $tab += 1#"><i class="menu-icon-bittorrent"></i> Manage Torrents</a></li>
|
||||
#end if
|
||||
#if $sickbeard.USE_FAILED_DOWNLOADS:
|
||||
<li><a href="$sbRoot/manage/failedDownloads/" tabindex="$tab#set $tab += 1#"><i class="menu-icon-failed-download"></i> Failed Downloads</a></li>
|
||||
#end if
|
||||
#if $sickbeard.USE_SUBTITLES:
|
||||
<li><a href="$sbRoot/manage/subtitleMissed/" tabindex="$tab#set $tab += 1#"><i class="menu-icon-backlog"></i> Missed Subtitle Management</a></li>
|
||||
#end if
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li id="NAVerrorlogs" class="dropdown">
|
||||
<a href="$sbRoot/errorlogs/" class="dropdown-toggle" data-toggle="dropdown" tabindex="$tab#set $tab += 1#">$logPageTitle <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="$sbRoot/errorlogs/"><i class="menu-icon-viewlog-errors" tabindex="$tab#set $tab += 1#"></i> View Log (Errors)</a></li>
|
||||
<li><a href="$sbRoot/errorlogs/viewlog/"><i class="menu-icon-viewlog" tabindex="$tab#set $tab += 1#"></i> View Log</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li id="NAVconfig" class="dropdown">
|
||||
<a href="$sbRoot/config/" class="dropdown-toggle" data-toggle="dropdown" tabindex="$tab#set $tab += 1#"><img src="$sbRoot/images/menu/system18.png" class="navbaricon hidden-xs" /><b class="caret hidden-xs"></b><span class="visible-xs">Config <b class="caret"></b></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="$sbRoot/config/" tabindex="$tab#set $tab += 1#"><i class="menu-icon-help"></i> Help & Info</a></li>
|
||||
<li><a href="$sbRoot/config/general/" tabindex="$tab#set $tab += 1#"><i class="menu-icon-config"></i> General</a></li>
|
||||
<li><a href="$sbRoot/config/search/" tabindex="$tab#set $tab += 1#"><i class="menu-icon-config"></i> Search Settings</a></li>
|
||||
<li><a href="$sbRoot/config/providers/" tabindex="$tab#set $tab += 1#"><i class="menu-icon-config"></i> Search Providers</a></li>
|
||||
<li><a href="$sbRoot/config/subtitles/" tabindex="$tab#set $tab += 1#"><i class="menu-icon-config"></i> Subtitles Settings</a></li>
|
||||
<li><a href="$sbRoot/config/postProcessing/" tabindex="$tab#set $tab += 1#"><i class="menu-icon-config"></i> Post Processing</a></li>
|
||||
<li><a href="$sbRoot/config/notifications/" tabindex="$tab#set $tab += 1#"><i class="menu-icon-config"></i> Notifications</a></li>
|
||||
<li><a href="$sbRoot/config/anime/" tabindex="$tab#set $tab += 1#"><i class="menu-icon-config"></i> Anime</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" tabindex="$tab#set $tab += 1#"><img src="$sbRoot/images/menu/system18-2.png" class="navbaricon hidden-xs" /><b class="caret hidden-xs"></b><span class="visible-xs">System <b class="caret"></b></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="$sbRoot/manage/manageSearches/forceVersionCheck" tabindex="$tab#set $tab += 1#"><i class="menu-icon-update"></i> Force Version Check</a></li>
|
||||
<li><a href="$sbRoot/home/restart/?pid=$sbPID" class="confirm restart" tabindex="$tab#set $tab += 1#"><i class="menu-icon-restart"></i> Restart</a></li>
|
||||
<li><a href="$sbRoot/home/shutdown/?pid=$sbPID" class="confirm shutdown" tabindex="$tab#set $tab += 1#"><i class="menu-icon-shutdown"></i> Shutdown</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
@ -222,35 +220,47 @@
|
|||
</div><!-- /.container-fluid -->
|
||||
</nav>
|
||||
|
||||
#if $varExists('submenu'):
|
||||
#if $varExists('submenu'):
|
||||
<div id="SubMenu">
|
||||
<span>
|
||||
#set $first = True
|
||||
#for $menuItem in $submenu:
|
||||
#if 'requires' not in $menuItem or $menuItem.requires():
|
||||
#if type($menuItem.path) == dict:
|
||||
#if $first then "" else "</span><span>"#<b>$menuItem.title</b>
|
||||
#set $first = False
|
||||
#set $inner_first = True
|
||||
#for $cur_link in $menuItem.path:
|
||||
#if $inner_first then "" else "· "#<a class="inner" href="$sbRoot/$menuItem.path[$cur_link]">$cur_link</a>
|
||||
#set $inner_first = False
|
||||
#end for
|
||||
#else
|
||||
#if $first then "" else ""#<a href="$sbRoot/$menuItem.path" #if 'confirm' in $menuItem then "class=\"confirm\"" else "" #>$menuItem.title</a>
|
||||
#set $first = False
|
||||
#end if
|
||||
#end if
|
||||
#end for
|
||||
</span>
|
||||
<span>
|
||||
#set $first = True
|
||||
#for $menuItem in $submenu:
|
||||
#if 'requires' not in $menuItem or $menuItem.requires():
|
||||
#if type($menuItem.path) == dict:
|
||||
#if $first then "" else "</span><span>"#<b>$menuItem.title</b>
|
||||
#set $first = False
|
||||
#set $inner_first = True
|
||||
#for $cur_link in $menuItem.path:
|
||||
#if $inner_first then "" else "· "#<a class="inner" href="$sbRoot/$menuItem.path[$cur_link]">$cur_link</a>
|
||||
#set $inner_first = False
|
||||
#end for
|
||||
#else
|
||||
#if $first then "" else ""#<a href="$sbRoot/$menuItem.path" #if 'confirm' in $menuItem then "class=\"confirm\"" else "" # tabindex="$tab#set $tab += 1#">$menuItem.title</a>
|
||||
#set $first = False
|
||||
#end if
|
||||
#end if
|
||||
#end for
|
||||
</span>
|
||||
</div>
|
||||
#end if
|
||||
|
||||
#if $sickbeard.NEWEST_VERSION_STRING:
|
||||
#end if
|
||||
|
||||
#if $sickbeard.NEWEST_VERSION_STRING:
|
||||
<div class="alert alert-success upgrade-notification" role="alert">
|
||||
<span>$sickbeard.NEWEST_VERSION_STRING</span>
|
||||
</div>
|
||||
#end if
|
||||
#end if
|
||||
|
||||
<div id="contentWrapper">
|
||||
<div id="content">
|
||||
#set $items = []
|
||||
#try
|
||||
$items.append($topmenu)
|
||||
#except (NameError, NotFound):
|
||||
#pass
|
||||
#end try
|
||||
#try
|
||||
$items.append($layout)
|
||||
#except (NameError, NotFound):
|
||||
#pass
|
||||
#end try
|
||||
#set $page_class = ('', ' class="%s"' % '_'.join($items).lower().replace(' ', '-'))[0 < len($items)]
|
||||
<div id="contentWrapper">
|
||||
<div id="content"$page_class>
|
||||
|
|
|
@ -40,7 +40,7 @@ Manage episodes with status <select name="whichStatus" class="form-control form-
|
|||
<form action="$sbRoot/manage/changeEpisodeStatuses" method="post">
|
||||
<input type="hidden" id="oldStatus" name="oldStatus" value="$whichStatus" />
|
||||
|
||||
<h2>Shows containing $common.statusStrings[$int($whichStatus)] episodes</h2>
|
||||
<h2><span class="grey-text">Shows containing</span> $common.statusStrings[$int($whichStatus)] <span class="grey-text">episodes</span></h2>
|
||||
|
||||
<br />
|
||||
|
||||
|
@ -65,7 +65,7 @@ $statusList.append($common.FAILED)
|
|||
<option value="$curStatus">$common.statusStrings[$curStatus]</option>
|
||||
#end for
|
||||
</select>
|
||||
<input class="btn btn-inline" type="submit" value="Go" />
|
||||
<input class="btn btn-inline go" type="submit" value="Go" />
|
||||
|
||||
<div>
|
||||
<button type="button" class="btn btn-xs selectAllShows">Select all</a></button>
|
||||
|
@ -76,7 +76,7 @@ $statusList.append($common.FAILED)
|
|||
<table class="sickbeardTable manageTable" cellspacing="1" border="0" cellpadding="0">
|
||||
#for $cur_indexer_id in $sorted_show_ids:
|
||||
<tr id="$cur_indexer_id">
|
||||
<th><input type="checkbox" class="allCheck" id="allCheck-$cur_indexer_id" name="$cur_indexer_id-all" checked="checked" /></th>
|
||||
<th><input type="checkbox" class="allCheck" id="allCheck-$cur_indexer_id" name="$cur_indexer_id-all" /></th>
|
||||
<th colspan="2" style="width: 100%; text-align: left;"><a class="whitelink" href="$sbRoot/home/displayShow?show=$cur_indexer_id">$show_names[$cur_indexer_id]</a> ($ep_counts[$cur_indexer_id]) <input type="button" class="pull-right get_more_eps btn" id="$cur_indexer_id" value="Expand" /></th>
|
||||
</tr>
|
||||
#end for
|
||||
|
|
|
@ -1,78 +1,93 @@
|
|||
$(document).ready(function() {
|
||||
$(document).ready(function(){
|
||||
|
||||
$('#checkAll').live('click', function(){
|
||||
|
||||
var seasCheck = this;
|
||||
var tableDiv = $('#tableDiv');
|
||||
|
||||
$('.dirCheck').each(function(){
|
||||
this.checked = seasCheck.checked;
|
||||
});
|
||||
});
|
||||
tableDiv.on('click', '#checkAll', function(){
|
||||
|
||||
$('#submitShowDirs').click(function(){
|
||||
var cbToggle = this.checked;
|
||||
|
||||
var dirArr = new Array();
|
||||
$('.dirCheck').each(function(){
|
||||
this.checked = cbToggle;
|
||||
});
|
||||
});
|
||||
|
||||
$('.dirCheck').each(function(i,w) {
|
||||
if (this.checked == true) {
|
||||
var show = $(this).attr('id');
|
||||
var indexer = $(this).closest('tr').find('select').val();
|
||||
dirArr.push(encodeURIComponent(indexer + '|' + show));
|
||||
}
|
||||
});
|
||||
$('#submitShowDirs').click(function(){
|
||||
|
||||
if (dirArr.length == 0)
|
||||
return false;
|
||||
var dirArr = [];
|
||||
|
||||
url = sbRoot+'/home/addShows/addExistingShows?promptForSettings='+ ($('#promptForSettings').prop('checked') ? 'on' : 'off');
|
||||
$('.dirCheck').each(function(){
|
||||
if (true == this.checked){
|
||||
var show = $(this).attr('id');
|
||||
var indexer = $(this).closest('tr').find('select').val();
|
||||
dirArr.push(encodeURIComponent(indexer + '|' + show));
|
||||
}
|
||||
});
|
||||
|
||||
url += '&shows_to_add='+dirArr.join('&shows_to_add=');
|
||||
if (0 == dirArr.length)
|
||||
return false;
|
||||
|
||||
window.location.href = url;
|
||||
});
|
||||
window.location.href = sbRoot + '/home/addShows/addExistingShows'
|
||||
+ '?promptForSettings=' + ($('#promptForSettings').prop('checked') ? 'on' : 'off')
|
||||
+ '&shows_to_add=' + dirArr.join('&shows_to_add=');
|
||||
});
|
||||
|
||||
|
||||
function loadContent() {
|
||||
var url = '';
|
||||
$('.dir_check').each(function(i,w){
|
||||
if ($(w).is(':checked')) {
|
||||
if (url.length)
|
||||
url += '&';
|
||||
url += 'rootDir=' + encodeURIComponent($(w).attr('id'));
|
||||
}
|
||||
});
|
||||
function loadContent(){
|
||||
var url = '';
|
||||
$('.dir_check').each(function(i, w){
|
||||
if ($(w).is(':checked')){
|
||||
url += (url.length ? '&' : '')
|
||||
+ 'rootDir=' + encodeURIComponent($(w).attr('id'));
|
||||
}
|
||||
});
|
||||
|
||||
$('#tableDiv').html('<img id="searchingAnim" src="' + sbRoot + '/images/loading32' + themeSpinner + '.gif" height="32" width="32" /> loading folders...');
|
||||
$.get(sbRoot+'/home/addShows/massAddTable', url, function(data) {
|
||||
$('#tableDiv').html(data);
|
||||
$("#addRootDirTable").tablesorter({
|
||||
//sortList: [[1,0]],
|
||||
widgets: ['zebra'],
|
||||
headers: {
|
||||
0: { sorter: false }
|
||||
}
|
||||
});
|
||||
});
|
||||
$('#tableDiv').html('<img id="searchingAnim"'
|
||||
+ ' style="margin-right:10px"'
|
||||
+ ' src="' + sbRoot + '/images/loading32' + themeSpinner + '.gif"'
|
||||
+ ' height="32" width="32" />'
|
||||
+ ' scanning parent folders...');
|
||||
|
||||
}
|
||||
$.get(sbRoot + '/home/addShows/massAddTable',
|
||||
url,
|
||||
function(data){
|
||||
$('#tableDiv').html(data);
|
||||
$('#addRootDirTable').tablesorter({
|
||||
sortList: [[1,0]],
|
||||
widgets: ['zebra'],
|
||||
headers: {
|
||||
0: { sorter: false }
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
var last_txt = '';
|
||||
$('#rootDirText').change(function() {
|
||||
if (last_txt == $('#rootDirText').val())
|
||||
return false;
|
||||
else
|
||||
last_txt = $('#rootDirText').val();
|
||||
$('#rootDirStaticList').html('');
|
||||
$('#rootDirs option').each(function(i, w) {
|
||||
$('#rootDirStaticList').append('<li class="ui-state-default ui-corner-all"><input type="checkbox" class="dir_check" id="'+$(w).val()+'" checked=checked> <label for="'+$(w).val()+'" style="color:#09A2FF;"><b>'+$(w).val()+'</b></label></li>')
|
||||
});
|
||||
loadContent();
|
||||
});
|
||||
|
||||
$('.dir_check').live('click', loadContent);
|
||||
var last_txt = '', new_text = '', id;
|
||||
$('#rootDirText').change(function(){
|
||||
if (last_txt == (new_text = $('#rootDirText').val()))
|
||||
return false;
|
||||
|
||||
$('.showManage').live('click', function() {
|
||||
$( "#tabs" ).tabs( 'select', 0 );
|
||||
});
|
||||
last_txt = new_text;
|
||||
$('#rootDirStaticList').html('');
|
||||
$('#rootDirs').find('option').each(function(i, w){
|
||||
id = $(w).val();
|
||||
$('#rootDirStaticList').append('<li class="ui-state-default ui-corner-all">'
|
||||
+ '<input id="' + id + '" type="checkbox"' + ' checked=checked'
|
||||
+ ' class="dir_check"'
|
||||
+ ' />'
|
||||
+ ' <label for="' + id + '"'
|
||||
+ ' style="color:#09A2FF">'
|
||||
+ '<b>' + id + '</b></label>'
|
||||
+ '</li>')
|
||||
});
|
||||
loadContent();
|
||||
});
|
||||
|
||||
$('#rootDirStaticList').on('click', '.dir_check', loadContent);
|
||||
|
||||
tableDiv.on('click', '.showManage', function(event) {
|
||||
event.preventDefault();
|
||||
$('#tabs').tabs('option', 'active', 0);
|
||||
$('html,body').animate({scrollTop: 0}, 1000);
|
||||
});
|
||||
|
||||
});
|
|
@ -1,24 +0,0 @@
|
|||
$(document).ready(function(){
|
||||
var loading = '<img src="' + sbRoot + '/images/loading16' + themeSpinner + '.gif" height="16" width="16" />';
|
||||
|
||||
$('#Backup').click(function() {
|
||||
$("#Backup").attr("disabled", true);
|
||||
$('#Backup-result').html(loading);
|
||||
var backupDir = $("#backupDir").val();
|
||||
$.get(sbRoot + "/config/backup", {'backupDir': backupDir})
|
||||
.done(function (data) {
|
||||
$('#Backup-result').html(data);
|
||||
$("#Backup").attr("disabled", false);
|
||||
});
|
||||
});
|
||||
$('#Restore').click(function() {
|
||||
$("#Restore").attr("disabled", true);
|
||||
$('#Restore-result').html(loading);
|
||||
var backupFile = $("#backupFile").val();
|
||||
$.get(sbRoot + "/config/restore", {'backupFile': backupFile})
|
||||
.done(function (data) {
|
||||
$('#Restore-result').html(data);
|
||||
$("#Restore").attr("disabled", false);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -17,7 +17,7 @@ $(document).ready(function () {
|
|||
} else {
|
||||
$('#unpack').qtip('option', {
|
||||
'content.text': 'Unrar Executable not found.',
|
||||
'style.classes': 'qtip-rounded qtip-shadow qtip-red'
|
||||
'style.classes': 'qtip-red qtip-rounded qtip-shadow'
|
||||
});
|
||||
$('#unpack').qtip('toggle', true);
|
||||
$('#unpack').css('background-color', '#FFFFDD');
|
||||
|
@ -56,21 +56,21 @@ $(document).ready(function () {
|
|||
if (data == "invalid") {
|
||||
$('#naming_pattern').qtip('option', {
|
||||
'content.text': 'This pattern is invalid.',
|
||||
'style.classes': 'qtip-rounded qtip-shadow qtip-red'
|
||||
'style.classes': 'qtip-red qtip-rounded qtip-shadow'
|
||||
});
|
||||
$('#naming_pattern').qtip('toggle', true);
|
||||
$('#naming_pattern').css('background-color', '#FFDDDD');
|
||||
} else if (data == "seasonfolders") {
|
||||
$('#naming_pattern').qtip('option', {
|
||||
'content.text': 'This pattern would be invalid without the folders, using it will force "Flatten" off for all shows.',
|
||||
'style.classes': 'qtip-rounded qtip-shadow qtip-red'
|
||||
'style.classes': 'qtip-red qtip-rounded qtip-shadow'
|
||||
});
|
||||
$('#naming_pattern').qtip('toggle', true);
|
||||
$('#naming_pattern').css('background-color', '#FFFFDD');
|
||||
} else {
|
||||
$('#naming_pattern').qtip('option', {
|
||||
'content.text': 'This pattern is valid.',
|
||||
'style.classes': 'qtip-rounded qtip-shadow qtip-green'
|
||||
'style.classes': 'qtip-green qtip-rounded qtip-shadow'
|
||||
});
|
||||
$('#naming_pattern').qtip('toggle', false);
|
||||
$('#naming_pattern').css('background-color', '#FFFFFF');
|
||||
|
@ -97,21 +97,21 @@ $(document).ready(function () {
|
|||
if (data == "invalid") {
|
||||
$('#naming_abd_pattern').qtip('option', {
|
||||
'content.text': 'This pattern is invalid.',
|
||||
'style.classes': 'qtip-rounded qtip-shadow qtip-red'
|
||||
'style.classes': 'qtip-red qtip-rounded qtip-shadow'
|
||||
});
|
||||
$('#naming_abd_pattern').qtip('toggle', true);
|
||||
$('#naming_abd_pattern').css('background-color', '#FFDDDD');
|
||||
} else if (data == "seasonfolders") {
|
||||
$('#naming_abd_pattern').qtip('option', {
|
||||
'content.text': 'This pattern would be invalid without the folders, using it will force "Flatten" off for all shows.',
|
||||
'style.classes': 'qtip-rounded qtip-shadow qtip-red'
|
||||
'style.classes': 'qtip-red qtip-rounded qtip-shadow'
|
||||
});
|
||||
$('#naming_abd_pattern').qtip('toggle', true);
|
||||
$('#naming_abd_pattern').css('background-color', '#FFFFDD');
|
||||
} else {
|
||||
$('#naming_abd_pattern').qtip('option', {
|
||||
'content.text': 'This pattern is valid.',
|
||||
'style.classes': 'qtip-rounded qtip-shadow qtip-green'
|
||||
'style.classes': 'qtip-green qtip-rounded qtip-shadow'
|
||||
});
|
||||
$('#naming_abd_pattern').qtip('toggle', false);
|
||||
$('#naming_abd_pattern').css('background-color', '#FFFFFF');
|
||||
|
@ -138,21 +138,21 @@ $(document).ready(function () {
|
|||
if (data == "invalid") {
|
||||
$('#naming_sports_pattern').qtip('option', {
|
||||
'content.text': 'This pattern is invalid.',
|
||||
'style.classes': 'qtip-rounded qtip-shadow qtip-red'
|
||||
'style.classes': 'qtip-red qtip-rounded qtip-shadow'
|
||||
});
|
||||
$('#naming_sports_pattern').qtip('toggle', true);
|
||||
$('#naming_sports_pattern').css('background-color', '#FFDDDD');
|
||||
} else if (data == "seasonfolders") {
|
||||
$('#naming_sports_pattern').qtip('option', {
|
||||
'content.text': 'This pattern would be invalid without the folders, using it will force "Flatten" off for all shows.',
|
||||
'style.classes': 'qtip-rounded qtip-shadow qtip-red'
|
||||
'style.classes': 'qtip-red qtip-rounded qtip-shadow'
|
||||
});
|
||||
$('#naming_sports_pattern').qtip('toggle', true);
|
||||
$('#naming_sports_pattern').css('background-color', '#FFFFDD');
|
||||
} else {
|
||||
$('#naming_sports_pattern').qtip('option', {
|
||||
'content.text': 'This pattern is valid.',
|
||||
'style.classes': 'qtip-rounded qtip-shadow qtip-green'
|
||||
'style.classes': 'qtip-green qtip-rounded qtip-shadow'
|
||||
});
|
||||
$('#naming_sports_pattern').qtip('toggle', false);
|
||||
$('#naming_sports_pattern').css('background-color', '#FFFFFF');
|
||||
|
@ -179,21 +179,21 @@ $(document).ready(function () {
|
|||
if (data == "invalid") {
|
||||
$('#naming_sports_pattern').qtip('option', {
|
||||
'content.text': 'This pattern is invalid.',
|
||||
'style.classes': 'qtip-rounded qtip-shadow qtip-red'
|
||||
'style.classes': 'qtip-red qtip-rounded qtip-shadow'
|
||||
});
|
||||
$('#naming_sports_pattern').qtip('toggle', true);
|
||||
$('#naming_sports_pattern').css('background-color', '#FFDDDD');
|
||||
} else if (data == "seasonfolders") {
|
||||
$('#naming_sports_pattern').qtip('option', {
|
||||
'content.text': 'This pattern would be invalid without the folders, using it will force "Flatten" off for all shows.',
|
||||
'style.classes': 'qtip-rounded qtip-shadow qtip-red'
|
||||
'style.classes': 'qtip-red qtip-rounded qtip-shadow'
|
||||
});
|
||||
$('#naming_sports_pattern').qtip('toggle', true);
|
||||
$('#naming_sports_pattern').css('background-color', '#FFFFDD');
|
||||
} else {
|
||||
$('#naming_sports_pattern').qtip('option', {
|
||||
'content.text': 'This pattern is valid.',
|
||||
'style.classes': 'qtip-rounded qtip-shadow qtip-green'
|
||||
'style.classes': 'qtip-green qtip-rounded qtip-shadow'
|
||||
});
|
||||
$('#naming_sports_pattern').qtip('toggle', false);
|
||||
$('#naming_sports_pattern').css('background-color', '#FFFFFF');
|
||||
|
@ -232,21 +232,21 @@ $(document).ready(function () {
|
|||
if (data == "invalid") {
|
||||
$('#naming_anime_pattern').qtip('option', {
|
||||
'content.text': 'This pattern is invalid.',
|
||||
'style.classes': 'qtip-rounded qtip-shadow qtip-red'
|
||||
'style.classes': 'qtip-red qtip-rounded qtip-shadow'
|
||||
});
|
||||
$('#naming_anime_pattern').qtip('toggle', true);
|
||||
$('#naming_anime_pattern').css('background-color', '#FFDDDD');
|
||||
} else if (data == "seasonfolders") {
|
||||
$('#naming_anime_pattern').qtip('option', {
|
||||
'content.text': 'This pattern would be invalid without the folders, using it will force "Flatten" off for all shows.',
|
||||
'style.classes': 'qtip-rounded qtip-shadow qtip-red'
|
||||
'style.classes': 'qtip-red qtip-rounded qtip-shadow'
|
||||
});
|
||||
$('#naming_anime_pattern').qtip('toggle', true);
|
||||
$('#naming_anime_pattern').css('background-color', '#FFFFDD');
|
||||
} else {
|
||||
$('#naming_anime_pattern').qtip('option', {
|
||||
'content.text': 'This pattern is valid.',
|
||||
'style.classes': 'qtip-rounded qtip-shadow qtip-green'
|
||||
'style.classes': 'qtip-green qtip-rounded qtip-shadow'
|
||||
});
|
||||
$('#naming_anime_pattern').qtip('toggle', false);
|
||||
$('#naming_anime_pattern').css('background-color', '#FFFFFF');
|
||||
|
@ -485,35 +485,27 @@ $(document).ready(function () {
|
|||
}
|
||||
|
||||
$(this).refreshMetadataConfig(true);
|
||||
$('img[title]').qtip( {
|
||||
$('img[title]').qtip({
|
||||
position: {
|
||||
viewport: $(window),
|
||||
at: 'bottom center',
|
||||
my: 'top right'
|
||||
my: 'top right',
|
||||
at: 'bottom center'
|
||||
},
|
||||
style: {
|
||||
tip: {
|
||||
corner: true,
|
||||
method: 'polygon'
|
||||
},
|
||||
classes: 'qtip-shadow qtip-dark'
|
||||
classes: 'qtip-dark qtip-rounded qtip-shadow'
|
||||
}
|
||||
});
|
||||
$('i[title]').qtip( {
|
||||
$('i[title]').qtip({
|
||||
position: {
|
||||
viewport: $(window),
|
||||
at: 'top center',
|
||||
my: 'bottom center'
|
||||
my: 'bottom center',
|
||||
at: 'top center'
|
||||
},
|
||||
style: {
|
||||
tip: {
|
||||
corner: true,
|
||||
method: 'polygon'
|
||||
},
|
||||
classes: 'qtip-rounded qtip-shadow ui-tooltip-sb'
|
||||
classes: 'qtip-rounded qtip-shadow'
|
||||
}
|
||||
});
|
||||
$('.custom-pattern,#unpack').qtip( {
|
||||
$('.custom-pattern,#unpack').qtip({
|
||||
content: 'validating...',
|
||||
show: {
|
||||
event: false,
|
||||
|
@ -522,15 +514,11 @@ $(document).ready(function () {
|
|||
hide: false,
|
||||
position: {
|
||||
viewport: $(window),
|
||||
at: 'center left',
|
||||
my: 'center right'
|
||||
my: 'right center',
|
||||
at: 'left center'
|
||||
},
|
||||
style: {
|
||||
tip: {
|
||||
corner: true,
|
||||
method: 'polygon'
|
||||
},
|
||||
classes: 'qtip-rounded qtip-shadow qtip-red'
|
||||
classes: 'qtip-red qtip-rounded qtip-shadow'
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -13,14 +13,14 @@ $(document).ready(function () {
|
|||
$(this).val('jump');
|
||||
});
|
||||
|
||||
$("#prevShow").click(function () {
|
||||
$('#pickShow option:selected').prev('option').attr('selected', 'selected');
|
||||
$("#pickShow").change();
|
||||
});
|
||||
|
||||
$("#nextShow").click(function () {
|
||||
$('#pickShow option:selected').next('option').attr('selected', 'selected');
|
||||
$("#pickShow").change();
|
||||
$('#prevShow, #nextShow').click(function () {
|
||||
var select$ = $('#pickShow'),
|
||||
index = $.inArray(select$.find('option:selected').val()*1, TVShowList);
|
||||
select$.find('option[value="' + TVShowList[('nextShow' === $(this).attr('id')
|
||||
? (index < TVShowList.length - 1 ? index + 1 : 0)
|
||||
: (0 < index ? index - 1 : TVShowList.length - 1))] + '"]').attr('selected', 'selected');
|
||||
select$.change();
|
||||
return false;
|
||||
});
|
||||
|
||||
$('#changeStatus').click(function () {
|
||||
|
|
|
@ -1,111 +1,136 @@
|
|||
/*jQuery Form to Form Wizard (Initial: Oct 1st, 2010)
|
||||
* This notice must stay intact for usage
|
||||
* Author: Dynamic Drive at http://www.dynamicdrive.com/
|
||||
* Visit http://www.dynamicdrive.com/ for full source code
|
||||
*/
|
||||
/* jQuery Form to Form Wizard (Initial: Oct 1st, 2010)
|
||||
* This notice must stay intact for usage
|
||||
* Author: Dynamic Drive at http://www.dynamicdrive.com/
|
||||
* Visit http://www.dynamicdrive.com/ for full source code
|
||||
*/
|
||||
|
||||
//Oct 21st, 2010: Script updated to v1.1, which adds basic form validation functionality, triggered each time the user goes from one page to the next, or tries to submit the form.
|
||||
|
||||
//jQuery.noConflict()
|
||||
// Oct 21st, 2010: Script updated to v1.1, which adds basic form validation functionality, triggered each time the user goes from one page to the next, or tries to submit the form.
|
||||
// jQuery.noConflict()
|
||||
|
||||
|
||||
function formtowizard(options){
|
||||
this.setting=jQuery.extend({persistsection:false, revealfx:['slide', 500], oninit:function(){}, onpagechangestart:function(){}}, options)
|
||||
this.currentsection=-1
|
||||
function FormToWizard(options){
|
||||
this.setting = jQuery.extend({fieldsetborderwidth:2, persistsection:false, revealfx:['slide', 500],
|
||||
oninit:function(){}, onpagechangestart:function(){}}, options);
|
||||
this.currentsection = -1;
|
||||
this.init(this.setting)
|
||||
}
|
||||
|
||||
formtowizard.prototype={
|
||||
|
||||
createfieldsets:function($theform, arr){ //reserved function for future version (dynamically wraps form elements with a fieldset element)
|
||||
$theform.find('fieldset.sectionwrap').removeClass('sectionwrap') //make sure no fieldsets carry 'sectionwrap' before proceeding
|
||||
var $startelement=$theform.find(':first-child') //reference first element inside form
|
||||
for (var i=0; i<arr.length; i++){ //loop thru "break" elements
|
||||
var $fieldsetelements=$startelement.nextUntil('#'+arr[i].breakafter+', *[name='+arr[i].breakafter+']').andSelf() //reference all elements from start element to break element (nextUntil() is jQuery 1.4 function)
|
||||
$fieldsetelements.add($fieldsetelements.next()).wrapAll('<fieldset class="sectionwrap" />') //wrap these elements with fieldset element
|
||||
$startelement=$theform.find('fieldset.sectionwrap').eq(i).prepend('<legend class="legendStep">'+arr[i].legend+'</legend>').next() //increment startelement to begin at the end of the just inserted fieldset element
|
||||
}
|
||||
},
|
||||
FormToWizard.prototype = {
|
||||
|
||||
loadsection:function(rawi, bypasshooks){
|
||||
var thiswizard=this
|
||||
//doload Boolean checks to see whether to load next section (true if bypasshooks param is true or onpagechangestart() event handler doesn't return false)
|
||||
var doload=bypasshooks || this.setting.onpagechangestart(jQuery, this.currentsection, this.sections.$sections.eq(this.currentsection))
|
||||
doload=(doload===false)? false : true //unless doload is explicitly false, set to true
|
||||
if (!bypasshooks && this.setting.validate){
|
||||
var outcome=this.validate(this.currentsection)
|
||||
if (outcome===false)
|
||||
doload=false
|
||||
}
|
||||
var i=(rawi=="prev")? this.currentsection-1 : (rawi=="next")? this.currentsection+1 : parseInt(rawi) //get index of next section to show
|
||||
i=(i<0)? this.sections.count-1 : (i>this.sections.count-1)? 0 : i //make sure i doesn't exceed min/max limit
|
||||
if (i<this.sections.count && doload){ //if next section to show isn't the same as the current section shown
|
||||
this.$thesteps.eq(this.currentsection).addClass('disabledstep').end().eq(i).removeClass('disabledstep') //dull current "step" text then highlight next "step" text
|
||||
if (this.setting.revealfx[0]=="slide"){
|
||||
this.sections.$sections.css("visibility", "visible")
|
||||
this.sections.$outerwrapper.stop().animate({height: this.sections.$sections.eq(i).outerHeight()}, this.setting.revealfx[1]) //animate fieldset wrapper's height to accomodate next section's height
|
||||
this.sections.$innerwrapper.stop().animate({left:-i*this.maxfieldsetwidth}, this.setting.revealfx[1], function(){ //slide next section into view
|
||||
thiswizard.sections.$sections.each(function(thissec){
|
||||
if (thissec!=i) //hide fieldset sections currently not in veiw, so tabbing doesn't go to elements within them (and mess up layout)
|
||||
thiswizard.sections.$sections.eq(thissec).css("visibility", "hidden")
|
||||
|
||||
//doload Boolean checks to see whether to load next section (true if bypasshooks param is true or onpagechangestart() event handler doesn't return false)
|
||||
var doload = bypasshooks || this.setting.onpagechangestart(jQuery, this.currentsection, this.sections.$sections.eq(this.currentsection)),
|
||||
tabIndex,
|
||||
thiswizard = this;
|
||||
|
||||
doload = (doload !== false); //unless doload is explicitly false, set to true
|
||||
if (!bypasshooks && this.setting.validate && false === this.validate(this.currentsection))
|
||||
doload = false;
|
||||
|
||||
//get index of next section to show
|
||||
tabIndex = ('prev' == rawi
|
||||
? this.currentsection - 1
|
||||
: ('next' == rawi
|
||||
? this.currentsection + 1
|
||||
: parseInt(rawi)));
|
||||
|
||||
//don't exceed min/max limit
|
||||
tabIndex = (tabIndex < 0
|
||||
? this.sections.count - 1
|
||||
: (tabIndex > (this.sections.count - 1)
|
||||
? 0
|
||||
: tabIndex));
|
||||
|
||||
//if next section to show isn't the same as the current section shown
|
||||
if (tabIndex < this.sections.count && doload){
|
||||
//dull current 'step' text then highlight next 'step' text
|
||||
this.$thesteps.eq(this.currentsection).addClass('disabledstep').end().eq(tabIndex).removeClass('disabledstep');
|
||||
|
||||
if ('slide' == this.setting.revealfx[0]) {
|
||||
this.sections.$sections.css('visibility', 'visible');
|
||||
//animate fieldset wrapper's height to accommodate next section's height
|
||||
this.sections.$outerwrapper.stop().animate({height: this.sections.$sections.eq(tabIndex).outerHeight()}, this.setting.revealfx[1]);
|
||||
//slide next section into view
|
||||
this.sections.$innerwrapper.stop().animate({left: -tabIndex * this.maxfieldsetwidth}, this.setting.revealfx[1], function () {
|
||||
thiswizard.sections.$sections.each(function (thissec) {
|
||||
//hide fieldset sections currently not in view, so tabbing doesn't go to elements within them (and mess up layout)
|
||||
if (tabIndex != thissec)
|
||||
thiswizard.sections.$sections.eq(thissec).css('visibility', 'hidden')
|
||||
})
|
||||
})
|
||||
}
|
||||
else if (this.setting.revealfx[0]=="fade"){ //if fx is "fade"
|
||||
this.sections.$sections.eq(this.currentsection).hide().end().eq(i).fadeIn(this.setting.revealfx[1], function(){
|
||||
else if ('fade' == this.setting.revealfx[0]) { //if fx is 'fade'
|
||||
this.sections.$sections.eq(this.currentsection).hide().end().eq(tabIndex).fadeIn(this.setting.revealfx[1], function () {
|
||||
if (document.all && this.style && this.style.removeAttribute)
|
||||
this.style.removeAttribute('filter') //fix IE clearType problem
|
||||
//fix IE clearType problem
|
||||
this.style.removeAttribute('filter');
|
||||
})
|
||||
} else {
|
||||
this.sections.$sections.eq(this.currentsection).hide().end().eq(tabIndex).show()
|
||||
}
|
||||
else{
|
||||
this.sections.$sections.eq(this.currentsection).hide().end().eq(i).show()
|
||||
}
|
||||
this.paginatediv.$status.text("Page "+(i+1)+" of "+this.sections.count) //update current page status text
|
||||
this.paginatediv.$navlinks.css('visibility', 'visible')
|
||||
if (i==0) //hide "prev" link
|
||||
this.paginatediv.$navlinks.eq(0).css('visibility', 'hidden')
|
||||
else if (i==this.sections.count-1) //hide "next" link
|
||||
this.paginatediv.$navlinks.eq(1).css('visibility', 'hidden')
|
||||
//update current page status text
|
||||
this.paginatediv.$status.text('step ' + (tabIndex + 1) + ' / ' + this.sections.count);
|
||||
this.paginatediv.$navlinks.css('visibility', 'visible');
|
||||
|
||||
if (0 == tabIndex) //hide 'prev' link
|
||||
this.paginatediv.$navlinks.eq(0).css('visibility', 'hidden');
|
||||
else if ((this.sections.count - 1) == tabIndex)
|
||||
//hide 'next' link
|
||||
this.paginatediv.$navlinks.eq(1).css('visibility', 'hidden');
|
||||
|
||||
if (this.setting.persistsection) //enable persistence?
|
||||
formtowizard.routines.setCookie(this.setting.formid+"_persist", i)
|
||||
this.currentsection=i
|
||||
if(i === 0) { setTimeout(function() { $('#nameToSearch').focus(); }, 250); }
|
||||
FormToWizard.routines.setCookie(this.setting.formid + '_persist', tabIndex);
|
||||
this.currentsection = tabIndex;
|
||||
if (0 === tabIndex) {
|
||||
setTimeout(function () {
|
||||
$('#nameToSearch').focus();
|
||||
}, 250);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
addvalidatefields:function(){
|
||||
var $=jQuery, setting=this.setting, theform=this.$theform.get(0), validatefields=[]
|
||||
var validatefields=setting.validate //array of form element ids to validate
|
||||
for (var i=0; i<validatefields.length; i++){
|
||||
var el=theform.elements[validatefields[i]] //reference form element
|
||||
if (el){ //if element is defined
|
||||
var $section=$(el).parents('fieldset.sectionwrap:eq(0)') //find fieldset.sectionwrap this form element belongs to
|
||||
if ($section.length==1){ //if element is within a fieldset.sectionwrap element
|
||||
$section.data('elements').push(el) //cache this element inside corresponding section
|
||||
var $ = jQuery,
|
||||
setting = this.setting,
|
||||
theform = this.$theform.get(0),
|
||||
validatefields = setting.validate; //array of form element ids to validate
|
||||
|
||||
for (var i = 0; i < validatefields.length; i++){
|
||||
var el = theform.elements[validatefields[i]]; //reference form element
|
||||
if (el){
|
||||
//find fieldset.sectionwrap this form element belongs to
|
||||
var $section = $(el).parents('fieldset.sectionwrap:eq(0)');
|
||||
//if element is within a fieldset.sectionwrap element
|
||||
if ($section.length == 1){
|
||||
//cache this element inside corresponding section
|
||||
$section.data('elements').push(el);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
validate:function(section){
|
||||
var elements=this.sections.$sections.eq(section).data('elements') //reference elements within this section that should be validated
|
||||
var validated=true, invalidtext=["Please fill out the following fields:\n"]
|
||||
//reference elements within this section that should be validated
|
||||
var elements = this.sections.$sections.eq(section).data('elements');
|
||||
var validated = true, invalidtext = ['Please fill out the following fields:' + "\n"];
|
||||
function invalidate(el){
|
||||
validated=false
|
||||
invalidtext.push("- "+ (el.id || el.name))
|
||||
validated = false;
|
||||
invalidtext.push('- '+ (el.id || el.name))
|
||||
}
|
||||
for (var i=0; i<elements.length; i++){
|
||||
if (/(text)/.test(elements[i].type) && elements[i].value==""){ //text and textarea elements
|
||||
for (var i = 0; i < elements.length; i++){
|
||||
if (/(text)/.test(elements[i].type) && elements[i].value == ''){
|
||||
//text and textarea elements
|
||||
invalidate(elements[i])
|
||||
}
|
||||
else if (/(select)/.test(elements[i].type) && (elements[i].selectedIndex==-1 || elements[i].options[elements[i].selectedIndex].text=="")){ //select elements
|
||||
} else if (/(select)/.test(elements[i].type) && (elements[i].selectedIndex == -1 || elements[i].options[elements[i].selectedIndex].text == '')){
|
||||
//select elements
|
||||
invalidate(elements[i])
|
||||
}
|
||||
else if (elements[i].type==undefined && elements[i].length>0){ //radio and checkbox elements
|
||||
var onechecked=false
|
||||
for (var r=0; r<elements[i].length; r++){
|
||||
if (elements[i][r].checked==true){
|
||||
onechecked=true
|
||||
} else if (undefined == elements[i].type && 0 < elements[i].length){
|
||||
//radio and checkbox elements
|
||||
var onechecked = false;
|
||||
for (var r = 0; r < elements[i].length; r++){
|
||||
if (elements[i][r].checked == true){
|
||||
onechecked = true;
|
||||
break
|
||||
}
|
||||
}
|
||||
|
@ -115,98 +140,154 @@ formtowizard.prototype={
|
|||
}
|
||||
}
|
||||
if (!validated)
|
||||
alert(invalidtext.join('\n'))
|
||||
alert(invalidtext.join("\n"));
|
||||
return validated
|
||||
},
|
||||
|
||||
|
||||
init:function(setting){
|
||||
var thiswizard=this
|
||||
var thiswizard = this;
|
||||
jQuery(function($){ //on document.ready
|
||||
var $theform=$('#'+setting.formid)
|
||||
if ($theform.length==0) //if form with specified ID doesn't exist, try name attribute instead
|
||||
$theform=$('form[name='+setting.formid+']')
|
||||
if (setting.manualfieldsets && setting.manualfieldsets.length>0)
|
||||
thiswizard.createfieldsets($theform, setting.manualfieldsets)
|
||||
var $stepsguide=$('<div class="stepsguide" />') //create Steps Container to house the "steps" text
|
||||
var $sections=$theform.find('fieldset.sectionwrap').hide() //find all fieldset elements within form and hide them initially
|
||||
if (setting.revealfx[0]=="slide"){ //create outer DIV that will house all the fieldset.sectionwrap elements
|
||||
$sectionswrapper=$('<div style="position:relative;overflow:hidden;"></div>').insertBefore($sections.eq(0)) //add DIV above the first fieldset.sectionwrap element
|
||||
$sectionswrapper_inner=$('<div style="position:absolute;left:0;top:0;"></div>') //create inner DIV of $sectionswrapper that will scroll to reveal a fieldset element
|
||||
var $theform = $('#' + setting.formid),
|
||||
//create Steps Container to house the 'steps' text
|
||||
$stepsguide = $('<div class="stepsguide" />'),
|
||||
|
||||
//find all fieldsets within form and hide them initially
|
||||
$sections = $theform.find('fieldset.sectionwrap').hide(),
|
||||
$sectionswrapper = '',
|
||||
$sectionswrapper_inner = '';
|
||||
|
||||
if (0 == $theform.length)
|
||||
//if form with specified ID doesn't exist, try name attribute instead
|
||||
$theform = $('form[name=' + setting.formid + ']');
|
||||
|
||||
if ('slide' == setting.revealfx[0]) {
|
||||
//create outer DIV that will house all the fieldset.sectionwrap elements
|
||||
//add DIV above the first fieldset.sectionwrap element
|
||||
$sectionswrapper = $('<div class="step-outer" style="position:relative"></div>').insertBefore($sections.eq(0));
|
||||
//create inner DIV of $sectionswrapper that will scroll to reveal a fieldset element
|
||||
$sectionswrapper_inner = $('<div class="step-inner" style="position:absolute; left:0"></div>');
|
||||
}
|
||||
var maxfieldsetwidth=$sections.eq(0).outerWidth() //variable to get width of widest fieldset.sectionwrap
|
||||
$sections.slice(1).each(function(i){ //loop through $sections (starting from 2nd one)
|
||||
maxfieldsetwidth=Math.max($(this).outerWidth(), maxfieldsetwidth)
|
||||
})
|
||||
maxfieldsetwidth+=2 //add 2px to final width to reveal fieldset border (if not removed via CSS)
|
||||
thiswizard.maxfieldsetwidth=maxfieldsetwidth
|
||||
$sections.each(function(i){ //loop through $sections again
|
||||
var $section=$(this)
|
||||
if (setting.revealfx[0]=="slide"){
|
||||
$section.data('page', i).css({position:'absolute', top:0, left:maxfieldsetwidth*i}).appendTo($sectionswrapper_inner) //set fieldset position to "absolute" and move it to inside sectionswrapper_inner DIV
|
||||
|
||||
//variable to get width of widest fieldset.sectionwrap
|
||||
var maxfieldsetwidth = $sections.eq(0).outerWidth();
|
||||
|
||||
//loop through $sections (starting from 2nd one)
|
||||
$sections.slice(1).each(function(){
|
||||
maxfieldsetwidth = Math.max($(this).outerWidth(), maxfieldsetwidth)
|
||||
});
|
||||
|
||||
//add default 2px or param px to final width to reveal fieldset border (if not removed via CSS)
|
||||
maxfieldsetwidth += setting.fieldsetborderwidth;
|
||||
thiswizard.maxfieldsetwidth = maxfieldsetwidth;
|
||||
|
||||
//loop through $sections again
|
||||
$sections.each(function(i){
|
||||
var $section = $(this);
|
||||
if ('slide' == setting.revealfx[0]) {
|
||||
//set fieldset position to 'absolute' and move it to inside sectionswrapper_inner DIV
|
||||
$section.data('page', i).css({position: 'absolute', left: maxfieldsetwidth * i}).appendTo($sectionswrapper_inner);
|
||||
}
|
||||
$section.data('elements', []) //empty array to contain elements within this section that should be validated for data (applicable only if validate option is defined)
|
||||
//create each "step" DIV and add it to main Steps Container:
|
||||
var $thestep=$('<div class="step disabledstep" />').data('section', i).html('Step '+(i+1)+'<div class="smalltext">'+$section.find('legend:eq(0)').text()+'<p></p></div>').appendTo($stepsguide)
|
||||
$thestep.click(function(){ //assign behavior to each step div
|
||||
//empty array to contain elements within this section that should be validated for data (applicable only if validate option is defined)
|
||||
$section.data('elements', []);
|
||||
|
||||
//create each 'step' DIV and add it to main Steps Container:
|
||||
var $stepwords = ['first', 'second', 'third'], $thestep = $('<div class="step disabledstep" />').data('section', i).html(($stepwords[i]
|
||||
+ ' step') + '<div class="smalltext">' + $section.find('legend:eq(0)').text() + '<p></p></div>').appendTo($stepsguide);
|
||||
|
||||
//assign behavior to each step div
|
||||
$thestep.click(function(){
|
||||
thiswizard.loadsection($(this).data('section'))
|
||||
})
|
||||
})
|
||||
if (setting.revealfx[0]=="slide"){
|
||||
$sectionswrapper.width(maxfieldsetwidth) //set fieldset wrapper to width of widest fieldset
|
||||
$sectionswrapper.append($sectionswrapper_inner) //add $sectionswrapper_inner as a child of $sectionswrapper
|
||||
});
|
||||
|
||||
if ('slide' == setting.revealfx[0]) {
|
||||
$sectionswrapper.width(maxfieldsetwidth); //set fieldset wrapper to width of widest fieldset
|
||||
$sectionswrapper.append($sectionswrapper_inner); //add $sectionswrapper_inner as a child of $sectionswrapper
|
||||
$stepsguide.append('<div style="clear:both"> </div>')
|
||||
}
|
||||
$theform.prepend($stepsguide) //add $thesteps div to the beginning of the form
|
||||
|
||||
//add $thesteps div to the beginning of the form
|
||||
$theform.prepend($stepsguide);
|
||||
|
||||
//$stepsguide.insertBefore($sectionswrapper) //add Steps Container before sectionswrapper container
|
||||
var $thesteps=$stepsguide.find('div.step')
|
||||
var $thesteps = $stepsguide.find('div.step');
|
||||
|
||||
//create pagination DIV and add it to end of form:
|
||||
var $paginatediv=$('<div class="formpaginate" style="overflow:hidden;"><span class="prev" style="float:left">Prev</span> <span class="status">Step 1 of </span> <span class="next" style="float:right">Next</span></div>')
|
||||
$theform.append($paginatediv)
|
||||
thiswizard.$theform=$theform
|
||||
if (setting.revealfx[0]=="slide"){
|
||||
thiswizard.sections={$outerwrapper:$sectionswrapper, $innerwrapper:$sectionswrapper_inner, $sections:$sections, count:$sections.length} //remember various parts of section container
|
||||
var $paginatediv = $('<div class="formpaginate">'
|
||||
+ '<span class="prev" style="float:left">Prev</span>'
|
||||
+ ' <span class="status">step 1 of </span>'
|
||||
+ ' <span class="next" style="float:right">Next</span>'
|
||||
+ '</div>');
|
||||
$theform.append($paginatediv);
|
||||
|
||||
thiswizard.$theform = $theform;
|
||||
if ('slide' == setting.revealfx[0]) {
|
||||
//remember various parts of section container
|
||||
thiswizard.sections = {
|
||||
$outerwrapper: $sectionswrapper,
|
||||
$innerwrapper: $sectionswrapper_inner,
|
||||
$sections: $sections,
|
||||
count: $sections.length
|
||||
};
|
||||
thiswizard.sections.$sections.show()
|
||||
} else {
|
||||
//remember various parts of section container
|
||||
thiswizard.sections = {
|
||||
$sections: $sections,
|
||||
count: $sections.length
|
||||
};
|
||||
}
|
||||
else{
|
||||
thiswizard.sections={$sections:$sections, count:$sections.length} //remember various parts of section container
|
||||
}
|
||||
thiswizard.$thesteps=$thesteps //remember this ref
|
||||
thiswizard.paginatediv={$main:$paginatediv, $navlinks:$paginatediv.find('span.prev, span.next'), $status:$paginatediv.find('span.status')} //remember various parts of pagination DIV
|
||||
thiswizard.paginatediv.$main.click(function(e){ //assign behavior to pagination buttons
|
||||
thiswizard.$thesteps = $thesteps;
|
||||
|
||||
//remember various parts of pagination DIV
|
||||
thiswizard.paginatediv = {
|
||||
$main: $paginatediv,
|
||||
$navlinks: $paginatediv.find('span.prev, span.next'),
|
||||
$status: $paginatediv.find('span.status')
|
||||
};
|
||||
|
||||
//assign behavior to pagination buttons
|
||||
thiswizard.paginatediv.$main.click(function(e){
|
||||
if (/(prev)|(next)/.test(e.target.className))
|
||||
thiswizard.loadsection(e.target.className)
|
||||
})
|
||||
var i=(setting.persistsection)? formtowizard.routines.getCookie(setting.formid+"_persist") : 0
|
||||
thiswizard.loadsection(i||0, true) //show the first section
|
||||
thiswizard.setting.oninit($, i, $sections.eq(i)) //call oninit event handler
|
||||
if (setting.validate){ //if validate array defined
|
||||
thiswizard.addvalidatefields() //seek out and cache form elements that should be validated
|
||||
});
|
||||
|
||||
var i = (setting.persistsection ? FormToWizard.routines.getCookie(setting.formid + '_persist') : 0);
|
||||
|
||||
//show the first section
|
||||
thiswizard.loadsection(i||0, true);
|
||||
|
||||
//call oninit event handler
|
||||
thiswizard.setting.oninit($, i, $sections.eq(i));
|
||||
|
||||
//if validate array defined
|
||||
if (setting.validate){
|
||||
//seek out and cache form elements that should be validated
|
||||
thiswizard.addvalidatefields();
|
||||
thiswizard.$theform.submit(function(){
|
||||
var returnval=true
|
||||
for (var i=0; i<thiswizard.sections.count; i++){
|
||||
for (var i = 0; i < thiswizard.sections.count; i++){
|
||||
if (!thiswizard.validate(i)){
|
||||
thiswizard.loadsection(i, true)
|
||||
returnval=false
|
||||
break
|
||||
thiswizard.loadsection(i, true);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return returnval //allow or disallow form submission
|
||||
return true;
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
formtowizard.routines={
|
||||
FormToWizard.routines = {
|
||||
|
||||
getCookie:function(Name){
|
||||
var re=new RegExp(Name+"=[^;]+", "i"); //construct RE to search for target name/value pair
|
||||
getCookie:function(Name){
|
||||
var re = new RegExp(Name + '=[^;]+', 'i'); //construct RE to search for target name/value pair
|
||||
if (document.cookie.match(re)) //if cookie found
|
||||
return document.cookie.match(re)[0].split("=")[1] //return its value
|
||||
return document.cookie.match(re)[0].split('=')[1]; //return its value
|
||||
return null
|
||||
},
|
||||
|
||||
setCookie:function(name, value){
|
||||
document.cookie = name+"=" + value + ";path=/"
|
||||
document.cookie = name + '=' + value + ';path=/';
|
||||
}
|
||||
}
|
||||
};
|
|
@ -54,11 +54,7 @@
|
|||
}
|
||||
},
|
||||
style: {
|
||||
tip: {
|
||||
corner: true,
|
||||
method: 'polygon'
|
||||
},
|
||||
classes: 'qtip-rounded qtip-dark qtip-shadow ui-tooltip-sb'
|
||||
classes: 'qtip-dark qtip-rounded qtip-shadow'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
2
gui/slick/js/lib/jquery.qtip-2.0.1.min.js
vendored
5
gui/slick/js/lib/jquery.qtip-2.2.1.min.js
vendored
Normal file
13
gui/slick/js/lib/jquery.qtip-2012-04-26.min.js
vendored
|
@ -1,34 +1,40 @@
|
|||
$(document).ready(function() {
|
||||
|
||||
function make_row(indexer_id, season, episode, name, checked) {
|
||||
if (checked)
|
||||
var checked = ' checked';
|
||||
else
|
||||
var checked = '';
|
||||
|
||||
var row_class = $('#row_class').val();
|
||||
|
||||
var row = '';
|
||||
row += ' <tr class="'+row_class+'">';
|
||||
row += ' <td class="tableleft" align="center"><input type="checkbox" class="'+indexer_id+'-epcheck" name="'+indexer_id+'-'+season+'x'+episode+'"'+checked+'></td>';
|
||||
row += ' <td>'+season+'x'+episode+'</td>';
|
||||
row += ' <td class="tableright" style="width: 100%">'+name+'</td>';
|
||||
row += ' </tr>'
|
||||
|
||||
return row;
|
||||
var checkedbox = (checked ? ' checked' : ''),
|
||||
row_class = $('#row_class').val();
|
||||
|
||||
return ' <tr class="' + row_class + '">'
|
||||
+ ' <td class="tableleft" align="center">'
|
||||
+ '<input type="checkbox"'
|
||||
+ ' class="' + indexer_id + '-epcheck"'
|
||||
+ ' name="' + indexer_id + '-' + season + 'x' + episode + '"'
|
||||
+ checkedbox+'></td>'
|
||||
+ ' <td>' + season + 'x' + episode + '</td>'
|
||||
+ ' <td class="tableright" style="width: 100%">' + name + '</td>'
|
||||
+ ' </tr>';
|
||||
}
|
||||
|
||||
$('.go').click(function() {
|
||||
var selected;
|
||||
|
||||
if (selected = (0 === $('input[class*="-epcheck"]:checked').length))
|
||||
alert('Please select at least one episode');
|
||||
|
||||
return !selected
|
||||
});
|
||||
|
||||
$('.allCheck').click(function(){
|
||||
var indexer_id = $(this).attr('id').split('-')[1];
|
||||
$('.'+indexer_id+'-epcheck').prop('checked', $(this).prop('checked'));
|
||||
$('.' + indexer_id + '-epcheck').prop('checked', $(this).prop('checked'));
|
||||
});
|
||||
|
||||
$('.get_more_eps').click(function(){
|
||||
var cur_indexer_id = $(this).attr('id');
|
||||
var checked = $('#allCheck-'+cur_indexer_id).prop('checked');
|
||||
var last_row = $('tr#'+cur_indexer_id);
|
||||
var checked = $('#allCheck-' + cur_indexer_id).prop('checked');
|
||||
var last_row = $('tr#' + cur_indexer_id);
|
||||
|
||||
$.getJSON(sbRoot+'/manage/showEpisodeStatuses',
|
||||
$.getJSON(sbRoot + '/manage/showEpisodeStatuses',
|
||||
{
|
||||
indexer_id: cur_indexer_id,
|
||||
whichStatus: $('#oldStatus').val()
|
||||
|
|
|
@ -1,227 +1,278 @@
|
|||
$(document).ready(function () {
|
||||
|
||||
function populateSelect() {
|
||||
if (!$('#nameToSearch').length) {
|
||||
return;
|
||||
}
|
||||
function populateSelect() {
|
||||
if (!$('#nameToSearch').length)
|
||||
return;
|
||||
|
||||
if ($('#indexerLangSelect option').length <= 1) {
|
||||
$.getJSON(sbRoot + '/home/addShows/getIndexerLanguages', {}, function (data) {
|
||||
var selected, resultStr = '';
|
||||
if (1 >= $('#indexerLangSelect').find('option').length) {
|
||||
|
||||
if (data.results.length === 0) {
|
||||
resultStr = '<option value="en" selected="selected">en</option>';
|
||||
} else {
|
||||
$.each(data.results, function (index, obj) {
|
||||
if (resultStr == '') {
|
||||
selected = ' selected="selected"';
|
||||
} else {
|
||||
selected = '';
|
||||
}
|
||||
$.getJSON(sbRoot + '/home/addShows/getIndexerLanguages', {}, function (data) {
|
||||
|
||||
resultStr += '<option value="' + obj + '"' + selected + '>' + obj + '</option>';
|
||||
});
|
||||
}
|
||||
var resultStr = '',
|
||||
selected = ' selected="selected"',
|
||||
elIndexerLang = $('#indexerLangSelect');
|
||||
|
||||
$('#indexerLangSelect').html(resultStr);
|
||||
$('#indexerLangSelect').change(function () { searchIndexers(); });
|
||||
});
|
||||
}
|
||||
}
|
||||
if (0 === data.results.length) {
|
||||
resultStr = '<option value="en"' + selected + '>en</option>';
|
||||
} else {
|
||||
$.each(data.results, function (index, obj) {
|
||||
resultStr += '<option value="' + obj + '"'
|
||||
+ ('' == resultStr ? selected : '')
|
||||
+ '>' + obj + '</option>';
|
||||
});
|
||||
}
|
||||
|
||||
var searchRequestXhr = null;
|
||||
elIndexerLang.html(resultStr);
|
||||
elIndexerLang.change(function () {
|
||||
searchIndexers();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function searchIndexers() {
|
||||
if (!$('#nameToSearch').val().length) {
|
||||
return;
|
||||
}
|
||||
var searchRequestXhr = null;
|
||||
|
||||
if (searchRequestXhr) searchRequestXhr.abort();
|
||||
function searchIndexers() {
|
||||
var elNameToSearch = $('#nameToSearch');
|
||||
|
||||
var searchingFor = $('#nameToSearch').val() + ' on ' + $('#providedIndexer option:selected').text() + ' in ' + $('#indexerLangSelect').val();
|
||||
$('#searchResults').empty().html('<img id="searchingAnim" src="' + sbRoot + '/images/loading32' + themeSpinner + '.gif" height="32" width="32" /> searching ' + searchingFor + '...');
|
||||
if (!elNameToSearch.val().length)
|
||||
return;
|
||||
|
||||
searchRequestXhr = $.ajax({
|
||||
url: sbRoot + '/home/addShows/searchIndexersForShowName',
|
||||
data: {'search_term': $('#nameToSearch').val(), 'lang': $('#indexerLangSelect').val(), 'indexer': $('#providedIndexer').val()},
|
||||
timeout: parseInt($('#indexer_timeout').val(), 10) * 1000,
|
||||
dataType: 'json',
|
||||
error: function () {
|
||||
$('#searchResults').empty().html('search timed out, try again or try another indexer');
|
||||
},
|
||||
success: function (data) {
|
||||
var firstResult = true;
|
||||
var resultStr = '<fieldset>\n<legend>Search Results:</legend>\n';
|
||||
var checked = '';
|
||||
if (searchRequestXhr)
|
||||
searchRequestXhr.abort();
|
||||
|
||||
if (data.results.length === 0) {
|
||||
resultStr += '<b>No results found, try a different search.</b>';
|
||||
} else {
|
||||
$.each(data.results, function (index, obj) {
|
||||
if (firstResult) {
|
||||
checked = ' checked';
|
||||
firstResult = false;
|
||||
} else {
|
||||
checked = '';
|
||||
}
|
||||
var elTvDatabase = $('#providedIndexer'),
|
||||
elIndexerLang = $('#indexerLangSelect'),
|
||||
searchingFor = elNameToSearch.val() + ' on ' + elTvDatabase.find('option:selected').text() + ' in ' + elIndexerLang.val();
|
||||
|
||||
var whichSeries = obj.join('|');
|
||||
$('#searchResults').empty().html('<img id="searchingAnim" src="' + sbRoot + '/images/loading32' + themeSpinner + '.gif" height="32" width="32" /> searching ' + searchingFor + '...');
|
||||
|
||||
searchRequestXhr = $.ajax({
|
||||
url: sbRoot + '/home/addShows/searchIndexersForShowName',
|
||||
data: {
|
||||
'search_term': elNameToSearch.val(),
|
||||
'lang': elIndexerLang.val(),
|
||||
'indexer': elTvDatabase.val()
|
||||
},
|
||||
timeout: parseInt($('#indexer_timeout').val(), 10) * 1000,
|
||||
dataType: 'json',
|
||||
error: function () {
|
||||
$('#searchResults').empty().html('search timed out, try again or try another database');
|
||||
},
|
||||
success: function (data) {
|
||||
var resultStr = '', checked = '', rowType, row = 0;
|
||||
|
||||
resultStr += '<input type="radio" id="whichSeries" name="whichSeries" value="' + whichSeries + '"' + checked + ' /> ';
|
||||
if (data.langid && data.langid != "") {
|
||||
resultStr += '<a href="' + anonURL + obj[2] + obj[3] + '&lid=' + data.langid + '" onclick=\"window.open(this.href, \'_blank\'); return false;\" ><b>' + obj[4] + '</b></a>';
|
||||
} else {
|
||||
resultStr += '<a href="' + anonURL + obj[2] + obj[3] + '" onclick=\"window.open(this.href, \'_blank\'); return false;\" ><b>' + obj[4] + '</b></a>';
|
||||
}
|
||||
if (0 === data.results.length) {
|
||||
resultStr += '<span class="boldest">Sorry, no results found. Try a different search.</span>';
|
||||
} else {
|
||||
$.each(data.results, function (index, obj) {
|
||||
checked = (0 == row ? ' checked' : '');
|
||||
rowType = (0 == row % 2 ? '' : ' class="alt"');
|
||||
row++;
|
||||
|
||||
if (obj[5] !== null) {
|
||||
var startDate = new Date(obj[5]);
|
||||
var today = new Date();
|
||||
if (startDate > today) {
|
||||
resultStr += ' (will debut on ' + obj[5] + ')';
|
||||
} else {
|
||||
resultStr += ' (started on ' + obj[5] + ')';
|
||||
}
|
||||
}
|
||||
var whichSeries = obj.join('|'),
|
||||
showstartdate = '';
|
||||
|
||||
if (obj[0] !== null) {
|
||||
resultStr += ' [' + obj[0] + ']';
|
||||
}
|
||||
if (null !== obj[5]) {
|
||||
var startDate = new Date(obj[5]);
|
||||
var today = new Date();
|
||||
showstartdate = ' <span class="stepone-result-date">('
|
||||
+ (startDate > today ? 'will debut' : 'started')
|
||||
+ ' on ' + obj[5] + ')</span>';
|
||||
}
|
||||
|
||||
resultStr += '<br />';
|
||||
});
|
||||
resultStr += '</ul>';
|
||||
}
|
||||
resultStr += '</fieldset>';
|
||||
$('#searchResults').html(resultStr);
|
||||
updateSampleText();
|
||||
myform.loadsection(0);
|
||||
}
|
||||
});
|
||||
}
|
||||
resultStr += '<div' + rowType + '>'
|
||||
+ '<input id="whichSeries" type="radio"'
|
||||
+ ' class="stepone-result-radio"'
|
||||
+ ' title="Add show <span style=\'color: rgb(66, 139, 202)\'>' + obj[4] + '</span>"'
|
||||
+ ' name="whichSeries"'
|
||||
+ ' value="' + whichSeries + '"'
|
||||
+ checked
|
||||
+ ' />'
|
||||
+ '<a'
|
||||
+ ' class="stepone-result-title"'
|
||||
+ ' title="View detail for <span style=\'color: rgb(66, 139, 202)\'>' + obj[4] + '</span>"'
|
||||
+ ' href="' + anonURL + obj[2] + obj[3] + ((data.langid && '' != data.langid) ? '&lid=' + data.langid : '') + '"'
|
||||
+ ' onclick="window.open(this.href, \'_blank\'); return false;"'
|
||||
+ '>' + obj[4] + '</a>'
|
||||
+ showstartdate
|
||||
+ (null == obj[0] ? ''
|
||||
: ' <span class="stepone-result-db grey-text">' + '[' + obj[0] + ']' + '</span>')
|
||||
+ '</div>' + "\n";
|
||||
});
|
||||
}
|
||||
$('#searchResults').html(
|
||||
'<fieldset>' + "\n" + '<legend class="legendStep" style="margin-bottom: 15px">'
|
||||
+ (0 < row ? row : 'No')
|
||||
+ ' search result' + (1 == row ? '' : 's') + '...</legend>' + "\n"
|
||||
+ resultStr
|
||||
+ '</fieldset>'
|
||||
);
|
||||
updateSampleText();
|
||||
myform.loadsection(0);
|
||||
$('.stepone-result-radio, .stepone-result-title').each(addQTip);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$('#searchName').click(function () { searchIndexers(); });
|
||||
var elNameToSearch = $('#nameToSearch'),
|
||||
elSearchName = $('#searchName');
|
||||
|
||||
if ($('#nameToSearch').length && $('#nameToSearch').val().length) {
|
||||
$('#searchName').click();
|
||||
}
|
||||
elSearchName.click(function () { searchIndexers(); });
|
||||
|
||||
$('#addShowButton').click(function () {
|
||||
// if they haven't picked a show don't let them submit
|
||||
if (!$("input:radio[name='whichSeries']:checked").val() && !$("input:hidden[name='whichSeries']").val().length) {
|
||||
alert('You must choose a show to continue');
|
||||
return false;
|
||||
}
|
||||
if (elNameToSearch.length && elNameToSearch.val().length) {
|
||||
elSearchName.click();
|
||||
}
|
||||
|
||||
$('#addShowForm').submit();
|
||||
});
|
||||
$('#addShowButton').click(function () {
|
||||
// if they haven't picked a show don't let them submit
|
||||
if (!$('input:radio[name="whichSeries"]:checked').val()
|
||||
&& !$('input:hidden[name="whichSeries"]').val().length) {
|
||||
alert('You must choose a show to continue');
|
||||
return false;
|
||||
}
|
||||
$('#addShowForm').submit();
|
||||
});
|
||||
|
||||
$('#skipShowButton').click(function () {
|
||||
$('#skipShow').val('1');
|
||||
$('#addShowForm').submit();
|
||||
});
|
||||
$('#skipShowButton').click(function () {
|
||||
$('#skipShow').val('1');
|
||||
$('#addShowForm').submit();
|
||||
});
|
||||
|
||||
$('#qualityPreset').change(function () {
|
||||
myform.loadsection(2);
|
||||
});
|
||||
$('#qualityPreset').change(function () {
|
||||
myform.loadsection(2);
|
||||
});
|
||||
|
||||
/***********************************************
|
||||
* jQuery Form to Form Wizard- (c) Dynamic Drive (www.dynamicdrive.com)
|
||||
* This notice MUST stay intact for legal use
|
||||
* Visit http://www.dynamicdrive.com/ for this script and 100s more.
|
||||
***********************************************/
|
||||
/***********************************************
|
||||
* jQuery Form to Form Wizard- (c) Dynamic Drive (www.dynamicdrive.com)
|
||||
* This notice MUST stay intact for legal use
|
||||
* Visit http://www.dynamicdrive.com/ for this script and 100s more.
|
||||
***********************************************/
|
||||
|
||||
var myform = new formtowizard({
|
||||
formid: 'addShowForm',
|
||||
revealfx: ['slide', 500],
|
||||
oninit: function () {
|
||||
populateSelect();
|
||||
updateSampleText();
|
||||
if ($('input:hidden[name=whichSeries]').length && $('#fullShowPath').length) {
|
||||
goToStep(3);
|
||||
}
|
||||
}
|
||||
});
|
||||
var myform = new FormToWizard({
|
||||
fieldsetborderwidth: 0,
|
||||
formid: 'addShowForm',
|
||||
revealfx: ['slide', 500],
|
||||
oninit: function () {
|
||||
populateSelect();
|
||||
updateSampleText();
|
||||
if ($('input:hidden[name="whichSeries"]').length && $('#fullShowPath').length) {
|
||||
goToStep(3);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function goToStep(num) {
|
||||
$('.step').each(function () {
|
||||
if ($.data(this, 'section') + 1 == num) {
|
||||
$(this).click();
|
||||
}
|
||||
});
|
||||
}
|
||||
function goToStep(num) {
|
||||
$('.step').each(function () {
|
||||
if ($.data(this, 'section') + 1 == num) {
|
||||
$(this).click();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$('#nameToSearch').focus();
|
||||
elNameToSearch.focus();
|
||||
|
||||
function updateSampleText() {
|
||||
// if something's selected then we have some behavior to figure out
|
||||
function updateSampleText() {
|
||||
// if something's selected then we have some behavior to figure out
|
||||
|
||||
var show_name, sep_char;
|
||||
// if they've picked a radio button then use that
|
||||
if ($('input:radio[name=whichSeries]:checked').length) {
|
||||
show_name = $('input:radio[name=whichSeries]:checked').val().split('|')[4];
|
||||
}
|
||||
// if we provided a show in the hidden field, use that
|
||||
else if ($('input:hidden[name=whichSeries]').length && $('input:hidden[name=whichSeries]').val().length) {
|
||||
show_name = $('#providedName').val();
|
||||
} else {
|
||||
show_name = '';
|
||||
}
|
||||
var show_name,
|
||||
sep_char,
|
||||
elRadio = $('input:radio[name="whichSeries"]:checked'),
|
||||
elInput = $('input:hidden[name="whichSeries"]'),
|
||||
elRootDirs = $('#rootDirs'),
|
||||
elFullShowPath = $('#fullShowPath');
|
||||
|
||||
var sample_text = 'Adding show <b>' + show_name + '</b> into <b>';
|
||||
// if they've picked a radio button then use that
|
||||
if (elRadio.length) {
|
||||
show_name = elRadio.val().split('|')[4];
|
||||
}
|
||||
// if we provided a show in the hidden field, use that
|
||||
else if (elInput.length && elInput.val().length) {
|
||||
show_name = $('#providedName').val();
|
||||
} else {
|
||||
show_name = '';
|
||||
}
|
||||
|
||||
// if we have a root dir selected, figure out the path
|
||||
if ($("#rootDirs option:selected").length) {
|
||||
var root_dir_text = $('#rootDirs option:selected').val();
|
||||
if (root_dir_text.indexOf('/') >= 0) {
|
||||
sep_char = '/';
|
||||
} else if (root_dir_text.indexOf('\\') >= 0) {
|
||||
sep_char = '\\';
|
||||
} else {
|
||||
sep_char = '';
|
||||
}
|
||||
var sample_text = '<p>Adding show <span class="show-name">' + show_name + '</span>'
|
||||
+ ('' == show_name ? 'into<br />' : '<br />into')
|
||||
+ ' <span class="show-dest">';
|
||||
|
||||
if (root_dir_text.substr(sample_text.length - 1) != sep_char) {
|
||||
root_dir_text += sep_char;
|
||||
}
|
||||
root_dir_text += '<i>||</i>' + sep_char;
|
||||
// if we have a root dir selected, figure out the path
|
||||
if (elRootDirs.find('option:selected').length) {
|
||||
var root_dir_text = elRootDirs.find('option:selected').val();
|
||||
if (root_dir_text.indexOf('/') >= 0) {
|
||||
sep_char = '/';
|
||||
} else if (root_dir_text.indexOf('\\') >= 0) {
|
||||
sep_char = '\\';
|
||||
} else {
|
||||
sep_char = '';
|
||||
}
|
||||
|
||||
sample_text += root_dir_text;
|
||||
} else if ($('#fullShowPath').length && $('#fullShowPath').val().length) {
|
||||
sample_text += $('#fullShowPath').val();
|
||||
} else {
|
||||
sample_text += 'unknown dir.';
|
||||
}
|
||||
if (root_dir_text.substr(sample_text.length - 1) != sep_char) {
|
||||
root_dir_text += sep_char;
|
||||
}
|
||||
root_dir_text += '<i>||</i>' + sep_char;
|
||||
|
||||
sample_text += '</b>';
|
||||
sample_text += root_dir_text;
|
||||
} else if (elFullShowPath.length && elFullShowPath.val().length) {
|
||||
sample_text += elFullShowPath.val();
|
||||
} else {
|
||||
sample_text += 'unknown dir.';
|
||||
}
|
||||
|
||||
// if we have a show name then sanitize and use it for the dir name
|
||||
if (show_name.length) {
|
||||
$.get(sbRoot + '/home/addShows/sanitizeFileName', {name: show_name}, function (data) {
|
||||
$('#displayText').html(sample_text.replace('||', data));
|
||||
});
|
||||
// if not then it's unknown
|
||||
} else {
|
||||
$('#displayText').html(sample_text.replace('||', '??'));
|
||||
}
|
||||
sample_text += '</span></p>';
|
||||
|
||||
// also toggle the add show button
|
||||
if (($("#rootDirs option:selected").length || ($('#fullShowPath').length && $('#fullShowPath').val().length)) &&
|
||||
($('input:radio[name=whichSeries]:checked').length) || ($('input:hidden[name=whichSeries]').length && $('input:hidden[name=whichSeries]').val().length)) {
|
||||
$('#addShowButton').attr('disabled', false);
|
||||
} else {
|
||||
$('#addShowButton').attr('disabled', true);
|
||||
}
|
||||
}
|
||||
// if we have a show name then sanitize and use it for the dir name
|
||||
if (show_name.length) {
|
||||
$.get(sbRoot + '/home/addShows/sanitizeFileName', {name: show_name}, function (data) {
|
||||
$('#displayText').html(sample_text.replace('||', data));
|
||||
});
|
||||
// if not then it's unknown
|
||||
} else {
|
||||
$('#displayText').html(sample_text.replace('||', '??'));
|
||||
}
|
||||
|
||||
$('#rootDirText').change(updateSampleText);
|
||||
$('#whichSeries').live('change', updateSampleText);
|
||||
// also toggle the add show button
|
||||
if ((elRootDirs.find('option:selected').length || (elFullShowPath.length && elFullShowPath.val().length)) &&
|
||||
(elRadio.length) || (elInput.length && elInput.val().length)) {
|
||||
$('#addShowButton').attr('disabled', false);
|
||||
} else {
|
||||
$('#addShowButton').attr('disabled', true);
|
||||
}
|
||||
}
|
||||
|
||||
$('#nameToSearch').keyup(function (event) {
|
||||
if (event.keyCode == 13) {
|
||||
$('#searchName').click();
|
||||
}
|
||||
});
|
||||
$('#rootDirText').change(updateSampleText);
|
||||
|
||||
$('#searchResults').on('click', '.stepone-result-radio', updateSampleText);
|
||||
|
||||
elNameToSearch.keyup(function (event) {
|
||||
if (event.keyCode == 13) {
|
||||
elSearchName.click();
|
||||
}
|
||||
});
|
||||
|
||||
var addQTip = (function() {
|
||||
$(this).css('cursor', 'help');
|
||||
$(this).qtip({
|
||||
show: {
|
||||
solo: true
|
||||
},
|
||||
position: {
|
||||
viewport: $(window),
|
||||
my: 'left center',
|
||||
adjust: {
|
||||
y: -10,
|
||||
x: 2
|
||||
}
|
||||
},
|
||||
style: {
|
||||
tip: {
|
||||
corner: true,
|
||||
method: 'polygon'
|
||||
},
|
||||
classes: 'qtip-rounded qtip-bootstrap qtip-shadow ui-tooltip-sb'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -1,20 +1,27 @@
|
|||
$(function () {
|
||||
$('.plotInfo').each(function () {
|
||||
match = $(this).attr("id").match(/^plot_info_(\d+)_(\d+)_(\d+)$/);
|
||||
var match = $(this).attr('id').match(/^plot_info_(\d+)_(\d+)_(\d+)$/);
|
||||
$(this).qtip({
|
||||
content: {
|
||||
text: 'Loading...',
|
||||
ajax: {
|
||||
url: $("#sbRoot").val() + '/home/plotDetails',
|
||||
type: 'GET',
|
||||
data: {
|
||||
show: match[1],
|
||||
episode: match[3],
|
||||
season: match[2]
|
||||
},
|
||||
success: function (data, status) {
|
||||
this.set('content.text', data);
|
||||
}
|
||||
text: function(event, api) {
|
||||
// deferred object ensuring the request is only made once
|
||||
$.ajax({
|
||||
url: $('#sbRoot').val() + '/home/plotDetails',
|
||||
type: 'GET',
|
||||
data: {
|
||||
show: match[1],
|
||||
episode: match[3],
|
||||
season: match[2]
|
||||
}
|
||||
})
|
||||
.then(function(content) {
|
||||
// Set the tooltip content upon successful retrieval
|
||||
api.set('content.text', content);
|
||||
}, function(xhr, status, error) {
|
||||
// Upon failure... set the tooltip content to the status and error value
|
||||
api.set('content.text', status + ': ' + error);
|
||||
});
|
||||
return 'Loading...'; // Set initial text
|
||||
}
|
||||
},
|
||||
show: {
|
||||
|
@ -29,11 +36,7 @@ $(function () {
|
|||
}
|
||||
},
|
||||
style: {
|
||||
tip: {
|
||||
corner: true,
|
||||
method: 'polygon'
|
||||
},
|
||||
classes: 'qtip-rounded qtip-shadow ui-tooltip-sb'
|
||||
classes: 'qtip-rounded qtip-shadow'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,36 +1,31 @@
|
|||
function setFromPresets (preset) {
|
||||
var elCustomQuality = $('#customQuality'),
|
||||
selected = 'selected';
|
||||
if (0 == preset) {
|
||||
elCustomQuality.show();
|
||||
return;
|
||||
}
|
||||
|
||||
elCustomQuality.hide();
|
||||
|
||||
$('#anyQualities').find('option').each(function() {
|
||||
var result = preset & $(this).val();
|
||||
$(this).attr(selected, (0 < result ? selected : false));
|
||||
});
|
||||
|
||||
$('#bestQualities').find('option').each(function() {
|
||||
var result = preset & ($(this).val() << 16);
|
||||
$(this).attr(selected, (result > 0 ? selected: false));
|
||||
});
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
function setFromPresets (preset) {
|
||||
if (preset == 0) {
|
||||
$('#customQuality').show();
|
||||
return;
|
||||
} else {
|
||||
$('#customQuality').hide();
|
||||
}
|
||||
var elQualityPreset = $('#qualityPreset'),
|
||||
selected = ':selected';
|
||||
|
||||
$('#anyQualities option').each(function(i) {
|
||||
var result = preset & $(this).val();
|
||||
if (result > 0) {
|
||||
$(this).attr('selected', 'selected');
|
||||
} else {
|
||||
$(this).attr('selected', false);
|
||||
}
|
||||
});
|
||||
elQualityPreset.change(function() {
|
||||
setFromPresets($('#qualityPreset').find(selected).val());
|
||||
});
|
||||
|
||||
$('#bestQualities option').each(function(i) {
|
||||
var result = preset & ($(this).val() << 16);
|
||||
if (result > 0) {
|
||||
$(this).attr('selected', 'selected');
|
||||
} else {
|
||||
$(this).attr('selected', false);
|
||||
}
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$('#qualityPreset').change(function() {
|
||||
setFromPresets($('#qualityPreset :selected').val());
|
||||
});
|
||||
|
||||
setFromPresets($('#qualityPreset :selected').val());
|
||||
});
|
||||
setFromPresets(elQualityPreset.find(selected).val());
|
||||
});
|
|
@ -15,15 +15,11 @@ $(function () {
|
|||
at: 'center left',
|
||||
adjust: {
|
||||
y: 0,
|
||||
x: -6
|
||||
x: -2
|
||||
}
|
||||
},
|
||||
style: {
|
||||
tip: {
|
||||
corner: true,
|
||||
method: 'polygon'
|
||||
},
|
||||
classes: 'qtip-rounded qtip-shadow ui-tooltip-sb'
|
||||
classes: 'qtip-rounded qtip-shadow'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,144 +1,211 @@
|
|||
$(document).ready(function () {
|
||||
function getRecommendedShows() {
|
||||
$.getJSON(sbRoot + '/home/addShows/getRecommendedShows', {}, function (data) {
|
||||
var firstResult = true;
|
||||
var resultStr = '<fieldset>\n<legend>Recommended Shows:</legend>\n';
|
||||
var checked = '';
|
||||
$(document).ready(function (){
|
||||
|
||||
if (data.results.length === 0) {
|
||||
resultStr += '<b>No recommended shows found, update your watched shows list on trakt.tv.</b>';
|
||||
} else {
|
||||
$.each(data.results, function (index, obj) {
|
||||
if (firstResult) {
|
||||
checked = ' checked';
|
||||
firstResult = false;
|
||||
} else {
|
||||
checked = '';
|
||||
}
|
||||
function getRecommendedShows(){
|
||||
|
||||
var whichSeries = obj.join('|');
|
||||
$('#searchResults').empty().html('<img id="searchingAnim"'
|
||||
+ ' src="' + sbRoot + '/images/loading32' + themeSpinner + '.gif"'
|
||||
+ ' height="32" width="32" />'
|
||||
+ ' fetching recommendations...');
|
||||
|
||||
resultStr += '<input type="radio" id="whichSeries" name="whichSeries" value="' + whichSeries + '"' + checked + ' /> ';
|
||||
resultStr += '<a href="' + anonURL + obj[1] + '" onclick="window.open(this.href, \'_blank\'); return false;"><b>' + obj[2] + '</b></a>';
|
||||
$.getJSON(sbRoot + '/home/addShows/getRecommendedShows',
|
||||
{},
|
||||
function (data){
|
||||
var resultStr = '', checked = '', rowType, row = 0;
|
||||
|
||||
if (obj[4] !== null) {
|
||||
var startDate = new Date(obj[4]);
|
||||
var today = new Date();
|
||||
if (startDate > today) {
|
||||
resultStr += ' (will debut on ' + obj[4] + ')';
|
||||
} else {
|
||||
resultStr += ' (started on ' + obj[4] + ')';
|
||||
}
|
||||
}
|
||||
if (null === data || 0 === data.results.length){
|
||||
resultStr += '<p>Sorry, no recommended shows found, this can happen from time to time.</p>'
|
||||
+ '<p>However, if the issue persists, then try updating your watched shows list on trakt.tv</p>';
|
||||
} else {
|
||||
|
||||
if (obj[0] !== null) {
|
||||
resultStr += ' [' + obj[0] + ']';
|
||||
}
|
||||
$.each(data.results, function (index, obj){
|
||||
checked = (0 == row ? ' checked' : '');
|
||||
rowType = (0 == row % 2 ? '' : ' class="alt"');
|
||||
row++;
|
||||
|
||||
if (obj[3] !== null) {
|
||||
resultStr += '<br />' + obj[3];
|
||||
}
|
||||
var whichSeries = obj[6] + '|' + obj[0] + '|' + obj[1] + '|' + obj[2] + '|' + obj[3],
|
||||
showstartdate = '';
|
||||
|
||||
resultStr += '<p /><br />';
|
||||
});
|
||||
resultStr += '</ul>';
|
||||
}
|
||||
resultStr += '</fieldset>';
|
||||
$('#searchResults').html(resultStr);
|
||||
updateSampleText();
|
||||
myform.loadsection(0);
|
||||
});
|
||||
}
|
||||
if (null !== obj[3]){
|
||||
var startDate = new Date(obj[3]);
|
||||
var today = new Date();
|
||||
showstartdate = ' <span class="stepone-result-date">('
|
||||
+ (startDate > today ? 'will debut' : 'started')
|
||||
+ ' on ' + obj[3] + ')</span>';
|
||||
}
|
||||
|
||||
$('#addShowButton').click(function () {
|
||||
// if they haven't picked a show don't let them submit
|
||||
if (!$("input:radio[name='whichSeries']:checked").val() && !$("input:hidden[name='whichSeries']").val().length) {
|
||||
alert('You must choose a show to continue');
|
||||
return false;
|
||||
}
|
||||
resultStr += '<div' + rowType + '>'
|
||||
+ '<input id="whichSeries" type="radio"'
|
||||
+ ' class="stepone-result-radio"'
|
||||
+ ' style="float:left;margin-top:4px"'
|
||||
+ ' title="Add show <span style=\'color: rgb(66, 139, 202)\'>' + obj[1] + '</span>"'
|
||||
+ ' name="whichSeries"'
|
||||
+ ' value="' + whichSeries + '"'
|
||||
+ checked
|
||||
+ ' />'
|
||||
+ '<div style="margin-left:20px">'
|
||||
+ '<a'
|
||||
+ ' class="stepone-result-title"'
|
||||
+ ' style="margin-left:5px"'
|
||||
+ ' title="View <span class=\'boldest\'>Trakt</span> detail for <span style=\'color: rgb(66, 139, 202)\'>' + obj[1] + '</span>"'
|
||||
+ ' href="' + anonURL + obj[0] + '"'
|
||||
+ ' onclick="window.open(this.href, \'_blank\'); return false;"'
|
||||
+ '>' + obj[1] + '</a>'
|
||||
+ showstartdate
|
||||
+ (null == obj[6] ? ''
|
||||
: ' '
|
||||
+ '<span class="stepone-result-db grey-text">'
|
||||
+ '<a class="service" href="' + anonURL + obj[7] + '"'
|
||||
+ ' onclick="window.open(this.href, \'_blank\'); return false;"'
|
||||
+ ' title="View <span class=\'boldest\'>' + obj[4] + '</span> detail for <span style=\'color: rgb(66, 139, 202)\'>' + obj[1] + '</span>"'
|
||||
+ '>'
|
||||
+ '<img alt="' + obj[4] + '" height="16" width="16" src="' + sbRoot + '/images/' + obj[5] + '" />'
|
||||
+ ''
|
||||
+ '</a>'
|
||||
+ '</span>'
|
||||
)
|
||||
+ (null == obj[10] ? ''
|
||||
: ' '
|
||||
+ '<span class="stepone-result-db grey-text">'
|
||||
+ '<a class="service" href="' + anonURL + obj[11] + '"'
|
||||
+ ' onclick="window.open(this.href, \'_blank\'); return false;"'
|
||||
+ ' title="View <span class=\'boldest\'>' + obj[8] + '</span> detail for <span style=\'color: rgb(66, 139, 202)\'>' + obj[1] + '</span>"'
|
||||
+ '>'
|
||||
+ '<img alt="' + obj[8] + '" height="16" width="16" src="' + sbRoot + '/images/' + obj[9] + '" />'
|
||||
+ ''
|
||||
+ '</a>'
|
||||
+ '</span>'
|
||||
)
|
||||
+ (null == obj[2] ? ''
|
||||
: ' <div class="stepone-result-overview grey-text">' + obj[2] + '</div>')
|
||||
+ '</div></div>';
|
||||
});
|
||||
}
|
||||
|
||||
$('#recommendedShowsForm').submit();
|
||||
});
|
||||
$('#searchResults').html(
|
||||
'<fieldset>' + "\n" + '<legend class="legendStep" style="margin-bottom: 15px">'
|
||||
+ (0 < row ? row : 'No')
|
||||
+ ' recommended result' + (1 == row ? '' : 's') + '...</legend>' + "\n"
|
||||
+ resultStr
|
||||
+ '</fieldset>'
|
||||
);
|
||||
updateSampleText();
|
||||
myform.loadsection(0);
|
||||
$('.stepone-result-radio, .stepone-result-title, .service').each(addQTip);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
$('#qualityPreset').change(function () {
|
||||
myform.loadsection(2);
|
||||
});
|
||||
$('#addShowButton').click(function () {
|
||||
// if they haven't picked a show don't let them submit
|
||||
if (!$('input:radio[name="whichSeries"]:checked').val()
|
||||
&& !$('input:hidden[name="whichSeries"]').val().length) {
|
||||
alert('You must choose a show to continue');
|
||||
return false;
|
||||
}
|
||||
$('#addShowForm').submit();
|
||||
});
|
||||
|
||||
var myform = new formtowizard({
|
||||
formid: 'recommendedShowsForm',
|
||||
revealfx: ['slide', 500],
|
||||
oninit: function () {
|
||||
getRecommendedShows();
|
||||
updateSampleText();
|
||||
}
|
||||
});
|
||||
$('#qualityPreset').change(function (){
|
||||
myform.loadsection(2);
|
||||
});
|
||||
|
||||
function goToStep(num) {
|
||||
$('.step').each(function () {
|
||||
if ($.data(this, 'section') + 1 == num) {
|
||||
$(this).click();
|
||||
}
|
||||
});
|
||||
}
|
||||
var myform = new FormToWizard({
|
||||
fieldsetborderwidth: 0,
|
||||
formid: 'addShowForm',
|
||||
revealfx: ['slide', 500],
|
||||
oninit: function (){
|
||||
getRecommendedShows();
|
||||
updateSampleText();
|
||||
}
|
||||
});
|
||||
|
||||
function updateSampleText() {
|
||||
// if something's selected then we have some behavior to figure out
|
||||
function goToStep(num){
|
||||
$('.step').each(function (){
|
||||
if ($.data(this, 'section') + 1 == num){
|
||||
$(this).click();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var show_name, sep_char;
|
||||
// if they've picked a radio button then use that
|
||||
if ($('input:radio[name=whichSeries]:checked').length) {
|
||||
show_name = $('input:radio[name=whichSeries]:checked').val().split('|')[2];
|
||||
} else {
|
||||
show_name = '';
|
||||
}
|
||||
function updateSampleText(){
|
||||
// if something's selected then we have some behavior to figure out
|
||||
|
||||
var sample_text = 'Adding show <b>' + show_name + '</b> into <b>';
|
||||
var elRadio = $('input:radio[name="whichSeries"]:checked'),
|
||||
elFullShowPath = $('#fullShowPath'),
|
||||
sep_char = '',
|
||||
root_dirs = $('#rootDirs'),
|
||||
// if they've picked a radio button then use that
|
||||
show_name = (elRadio.length ? elRadio.val().split('|')[2] : ''),
|
||||
sample_text = '<p>Adding show <span class="show-name">' + show_name + '</span>'
|
||||
+ ('' == show_name ? 'into<br />' : '<br />into')
|
||||
+ ' <span class="show-dest">';
|
||||
|
||||
// if we have a root dir selected, figure out the path
|
||||
if ($("#rootDirs option:selected").length) {
|
||||
var root_dir_text = $('#rootDirs option:selected').val();
|
||||
if (root_dir_text.indexOf('/') >= 0) {
|
||||
sep_char = '/';
|
||||
} else if (root_dir_text.indexOf('\\') >= 0) {
|
||||
sep_char = '\\';
|
||||
} else {
|
||||
sep_char = '';
|
||||
}
|
||||
// if we have a root dir selected, figure out the path
|
||||
if (root_dirs.find('option:selected').length){
|
||||
var root_dir_text = root_dirs.find('option:selected').val();
|
||||
if (0 <= root_dir_text.indexOf('/')){
|
||||
sep_char = '/';
|
||||
} else if (0 <= root_dir_text.indexOf('\\')){
|
||||
sep_char = '\\';
|
||||
}
|
||||
|
||||
if (root_dir_text.substr(sample_text.length - 1) != sep_char) {
|
||||
root_dir_text += sep_char;
|
||||
}
|
||||
root_dir_text += '<i>||</i>' + sep_char;
|
||||
root_dir_text += (sep_char != root_dir_text.substr(sample_text.length - 1)
|
||||
? sep_char : '')
|
||||
+ '<i>||</i>' + sep_char;
|
||||
|
||||
sample_text += root_dir_text;
|
||||
} else if ($('#fullShowPath').length && $('#fullShowPath').val().length) {
|
||||
sample_text += $('#fullShowPath').val();
|
||||
} else {
|
||||
sample_text += 'unknown dir.';
|
||||
}
|
||||
sample_text += root_dir_text;
|
||||
} else if (elFullShowPath.length && elFullShowPath.val().length){
|
||||
sample_text += elFullShowPath.val();
|
||||
} else {
|
||||
sample_text += 'unknown dir.';
|
||||
}
|
||||
|
||||
sample_text += '</b>';
|
||||
sample_text += '</span></p>';
|
||||
|
||||
// if we have a show name then sanitize and use it for the dir name
|
||||
if (show_name.length) {
|
||||
$.get(sbRoot + '/home/addShows/sanitizeFileName', {name: show_name}, function (data) {
|
||||
$('#displayText').html(sample_text.replace('||', data));
|
||||
});
|
||||
// if not then it's unknown
|
||||
} else {
|
||||
$('#displayText').html(sample_text.replace('||', '??'));
|
||||
}
|
||||
// if we have a show name then sanitize and use it for the dir name
|
||||
if (show_name.length){
|
||||
$.get(sbRoot + '/home/addShows/sanitizeFileName', {name: show_name}, function (data){
|
||||
$('#displayText').html(sample_text.replace('||', data));
|
||||
});
|
||||
// if not then it's unknown
|
||||
} else {
|
||||
$('#displayText').html(sample_text.replace('||', '??'));
|
||||
}
|
||||
|
||||
// also toggle the add show button
|
||||
if (($("#rootDirs option:selected").length || ($('#fullShowPath').length && $('#fullShowPath').val().length)) &&
|
||||
($('input:radio[name=whichSeries]:checked').length)) {
|
||||
$('#addShowButton').attr('disabled', false);
|
||||
} else {
|
||||
$('#addShowButton').attr('disabled', true);
|
||||
}
|
||||
}
|
||||
// also toggle the add show button
|
||||
$('#addShowButton').attr('disabled',
|
||||
((root_dirs.find('option:selected').length
|
||||
|| (elFullShowPath.length && elFullShowPath.val().length))
|
||||
&& elRadio.length
|
||||
? false : true));
|
||||
}
|
||||
|
||||
$('#rootDirText').change(updateSampleText);
|
||||
$('#whichSeries').live('change', updateSampleText);
|
||||
var addQTip = (function(){
|
||||
$(this).css('cursor', 'help');
|
||||
$(this).qtip({
|
||||
show: {
|
||||
solo: true
|
||||
},
|
||||
position: {
|
||||
viewport: $(window),
|
||||
my: 'left center',
|
||||
adjust: {
|
||||
y: -10,
|
||||
x: 2
|
||||
}
|
||||
},
|
||||
style: {
|
||||
tip: {
|
||||
corner: true,
|
||||
method: 'polygon'
|
||||
},
|
||||
classes: 'qtip-rounded qtip-bootstrap qtip-shadow ui-tooltip-sb'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('#rootDirText').change(updateSampleText);
|
||||
|
||||
$('#searchResults').on('click', '.stepone-result-radio', updateSampleText);
|
||||
|
||||
});
|
||||
|
|
|
@ -1,17 +1,25 @@
|
|||
$(function () {
|
||||
$('.title span').each(function () {
|
||||
var match = $(this).parent().attr('id').match(/^scene_exception_(\d+)$/);
|
||||
$(this).qtip({
|
||||
content: {
|
||||
text: 'Loading...',
|
||||
ajax: {
|
||||
url: $("#sbRoot").val() + '/home/sceneExceptions',
|
||||
type: 'GET',
|
||||
data: {
|
||||
show: match[1]
|
||||
},
|
||||
success: function (data, status) {
|
||||
this.set('content.text', data);
|
||||
}
|
||||
text: function(event, api) {
|
||||
// deferred object ensuring the request is only made once
|
||||
$.ajax({
|
||||
url: $('#sbRoot').val() + '/home/sceneExceptions',
|
||||
type: 'GET',
|
||||
data: {
|
||||
show: match[1]
|
||||
}
|
||||
})
|
||||
.then(function(content) {
|
||||
// Set the tooltip content upon successful retrieval
|
||||
api.set('content.text', content);
|
||||
}, function(xhr, status, error) {
|
||||
// Upon failure... set the tooltip content to the status and error value
|
||||
api.set('content.text', status + ': ' + error);
|
||||
});
|
||||
return 'Loading...'; // Set initial text
|
||||
}
|
||||
},
|
||||
show: {
|
||||
|
@ -19,19 +27,15 @@ $(function () {
|
|||
},
|
||||
position: {
|
||||
viewport: $(window),
|
||||
my: 'left middle',
|
||||
at: 'right middle',
|
||||
my: 'left center',
|
||||
at: 'right center',
|
||||
adjust: {
|
||||
y: 0,
|
||||
x: 10
|
||||
x: 2
|
||||
}
|
||||
},
|
||||
style: {
|
||||
tip: {
|
||||
corner: true,
|
||||
method: 'polygon'
|
||||
},
|
||||
classes: 'qtip-rounded qtip-shadow ui-tooltip-sb'
|
||||
classes: 'qtip-rounded qtip-shadow'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
282
setup.py
|
@ -1,282 +0,0 @@
|
|||
import re
|
||||
import urllib
|
||||
import ConfigParser
|
||||
import sys
|
||||
import os
|
||||
import shutil
|
||||
import zipfile
|
||||
import subprocess
|
||||
import fnmatch
|
||||
import googlecode_upload
|
||||
|
||||
from distutils.core import setup
|
||||
|
||||
try:
|
||||
import py2exe
|
||||
except:
|
||||
print "The Python module py2exe is required"
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
import pygithub.github
|
||||
except:
|
||||
print "The Python module pyGitHub is required"
|
||||
sys.exit(1)
|
||||
|
||||
# mostly stolen from the SABnzbd package.py file
|
||||
name = 'SickGear'
|
||||
version = '0.1'
|
||||
|
||||
release = name + '-' + version
|
||||
|
||||
Win32ConsoleName = 'SickBeard-console.exe'
|
||||
Win32WindowName = 'SickBeard.exe'
|
||||
|
||||
|
||||
def findLatestBuild():
|
||||
regex = "http\://SickGear\.googlecode\.com/files/SickGear\-win32\-alpha\-build(\d+)(?:\.\d+)?\.zip"
|
||||
|
||||
svnFile = urllib.urlopen("http://code.google.com/p/SickGear/downloads/list")
|
||||
|
||||
for curLine in svnFile.readlines():
|
||||
match = re.search(regex, curLine)
|
||||
if match:
|
||||
groups = match.groups()
|
||||
return int(groups[0])
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def recursive_find_data_files(root_dir, allowed_extensions=('*')):
|
||||
to_return = {}
|
||||
for (dirpath, dirnames, filenames) in os.walk(root_dir):
|
||||
if not filenames:
|
||||
continue
|
||||
|
||||
for cur_filename in filenames:
|
||||
|
||||
matches_pattern = False
|
||||
for cur_pattern in allowed_extensions:
|
||||
if fnmatch.fnmatch(cur_filename, '*.' + cur_pattern):
|
||||
matches_pattern = True
|
||||
if not matches_pattern:
|
||||
continue
|
||||
|
||||
cur_filepath = os.path.join(dirpath, cur_filename)
|
||||
to_return.setdefault(dirpath, []).append(cur_filepath)
|
||||
|
||||
return sorted(to_return.items())
|
||||
|
||||
|
||||
def find_all_libraries(root_dirs):
|
||||
libs = []
|
||||
|
||||
for cur_root_dir in root_dirs:
|
||||
for (dirpath, dirnames, filenames) in os.walk(cur_root_dir):
|
||||
if '__init__.py' not in filenames:
|
||||
continue
|
||||
|
||||
libs.append(dirpath.replace(os.sep, '.'))
|
||||
|
||||
return libs
|
||||
|
||||
|
||||
def allFiles(dir):
|
||||
files = []
|
||||
for file in os.listdir(dir):
|
||||
fullFile = os.path.join(dir, file)
|
||||
if os.path.isdir(fullFile):
|
||||
files += allFiles(fullFile)
|
||||
else:
|
||||
files.append(fullFile)
|
||||
|
||||
return files
|
||||
|
||||
# save the original arguments and replace them with the py2exe args
|
||||
oldArgs = []
|
||||
if len(sys.argv) > 1:
|
||||
oldArgs = sys.argv[1:]
|
||||
del sys.argv[1:]
|
||||
|
||||
sys.argv.append('py2exe')
|
||||
|
||||
# clear the dist dir
|
||||
if os.path.isdir('dist'):
|
||||
shutil.rmtree('dist')
|
||||
|
||||
# root source dir
|
||||
compile_dir = os.path.dirname(os.path.normpath(os.path.abspath(sys.argv[0])))
|
||||
|
||||
if not 'nopull' in oldArgs:
|
||||
# pull new source from git
|
||||
print 'Updating source from git'
|
||||
p = subprocess.Popen('git pull origin master', shell=True, cwd=compile_dir)
|
||||
o, e = p.communicate()
|
||||
|
||||
# figure out what build this is going to be
|
||||
latestBuild = findLatestBuild()
|
||||
if 'test' in oldArgs:
|
||||
currentBuildNumber = str(latestBuild) + 'a'
|
||||
else:
|
||||
currentBuildNumber = latestBuild + 1
|
||||
|
||||
# set up the compilation options
|
||||
data_files = recursive_find_data_files('data', ['gif', 'png', 'jpg', 'ico', 'js', 'css', 'tmpl'])
|
||||
|
||||
options = dict(
|
||||
name=name,
|
||||
version=release,
|
||||
author='SickGear',
|
||||
author_email='SickGear@outlook.com',
|
||||
description=name + ' ' + release,
|
||||
scripts=['SickBeard.py'],
|
||||
packages=find_all_libraries(['sickbeard', 'lib']),
|
||||
)
|
||||
|
||||
# set up py2exe to generate the console app
|
||||
program = [{'script': 'SickBeard.py'}]
|
||||
options['options'] = {'py2exe':
|
||||
{
|
||||
'bundle_files': 3,
|
||||
'packages': ['Cheetah'],
|
||||
'excludes': ['Tkconstants', 'Tkinter', 'tcl'],
|
||||
'optimize': 2,
|
||||
'compressed': 0
|
||||
}
|
||||
}
|
||||
options['zipfile'] = 'lib/SickGear.zip'
|
||||
options['console'] = program
|
||||
options['data_files'] = data_files
|
||||
|
||||
# compile sickbeard-console.exe
|
||||
setup(**options)
|
||||
|
||||
# rename the exe to sickbeard-console.exe
|
||||
try:
|
||||
if os.path.exists("dist/%s" % Win32ConsoleName):
|
||||
os.remove("dist/%s" % Win32ConsoleName)
|
||||
os.rename("dist/%s" % Win32WindowName, "dist/%s" % Win32ConsoleName)
|
||||
except:
|
||||
print "Cannot create dist/%s" % Win32ConsoleName
|
||||
# sys.exit(1)
|
||||
|
||||
# we don't need this stuff when we make the 2nd exe
|
||||
del options['console']
|
||||
del options['data_files']
|
||||
options['windows'] = program
|
||||
|
||||
# compile sickbeard.exe
|
||||
setup(**options)
|
||||
|
||||
# compile sabToSickbeard.exe using the existing setup.py script
|
||||
auto_process_dir = os.path.join(compile_dir, 'autoProcessTV')
|
||||
p = subprocess.Popen([sys.executable, os.path.join(auto_process_dir, 'setup.py')], cwd=auto_process_dir, shell=True)
|
||||
o, e = p.communicate()
|
||||
|
||||
# copy autoProcessTV files to the dist dir
|
||||
auto_process_files = ['autoProcessTV/sabToSickBeard.py',
|
||||
'autoProcessTV/hellaToSickBeard.py',
|
||||
'autoProcessTV/autoProcessTV.py',
|
||||
'autoProcessTV/autoProcessTV.cfg.sample',
|
||||
'autoProcessTV/sabToSickBeard.exe']
|
||||
|
||||
os.makedirs('dist/autoProcessTV')
|
||||
|
||||
for curFile in auto_process_files:
|
||||
newFile = os.path.join('dist', curFile)
|
||||
print "Copying file from", curFile, "to", newFile
|
||||
shutil.copy(curFile, newFile)
|
||||
|
||||
# compile updater.exe
|
||||
setup(
|
||||
options={'py2exe': {'bundle_files': 1}},
|
||||
zipfile=None,
|
||||
console=['updater.py'], requires=['Cheetah']
|
||||
)
|
||||
|
||||
if 'test' in oldArgs:
|
||||
print "Ignoring changelog for test build"
|
||||
else:
|
||||
# start building the CHANGELOG.txt
|
||||
print 'Creating changelog'
|
||||
gh = github.GitHub()
|
||||
|
||||
# read the old changelog and find the last commit from that build
|
||||
lastCommit = ""
|
||||
try:
|
||||
cl = open("CHANGELOG.txt", "r")
|
||||
lastCommit = cl.readlines()[0].strip()
|
||||
cl.close()
|
||||
except:
|
||||
print "I guess there's no changelog"
|
||||
|
||||
newestCommit = ""
|
||||
changeString = ""
|
||||
|
||||
# cycle through all the git commits and save their commit messages
|
||||
for curCommit in gh.commits.forBranch('SickGear', 'SickGear'):
|
||||
if curCommit.id == lastCommit:
|
||||
break
|
||||
|
||||
if newestCommit == "":
|
||||
newestCommit = curCommit.id
|
||||
|
||||
changeString += curCommit.message + "\n\n"
|
||||
|
||||
# if we didn't find any changes don't make a changelog file
|
||||
if newestCommit != "":
|
||||
newChangelog = open("CHANGELOG.txt", "w")
|
||||
newChangelog.write(newestCommit + "\n\n")
|
||||
newChangelog.write("Changelog for build " + str(currentBuildNumber) + "\n\n")
|
||||
newChangelog.write(changeString)
|
||||
newChangelog.close()
|
||||
else:
|
||||
print "No changes found, keeping old changelog"
|
||||
|
||||
# put the changelog in the compile dir
|
||||
if os.path.exists("CHANGELOG.txt"):
|
||||
shutil.copy('CHANGELOG.txt', 'dist/')
|
||||
|
||||
# figure out what we're going to call the zip file
|
||||
print 'Zipping files...'
|
||||
zipFilename = 'SickGear-win32-alpha-build' + str(currentBuildNumber)
|
||||
if os.path.isfile(zipFilename + '.zip'):
|
||||
zipNum = 2
|
||||
while os.path.isfile(zipFilename + '.{0:0>2}.zip'.format(str(zipNum))):
|
||||
zipNum += 1
|
||||
zipFilename = zipFilename + '.{0:0>2}'.format(str(zipNum))
|
||||
|
||||
# get a list of files to add to the zip
|
||||
zipFileList = allFiles('dist/')
|
||||
|
||||
# add all files to the zip
|
||||
z = zipfile.ZipFile(zipFilename + '.zip', 'w', zipfile.ZIP_DEFLATED)
|
||||
for file in zipFileList:
|
||||
z.write(file, file.replace('dist/', zipFilename + '/'))
|
||||
z.close()
|
||||
|
||||
print "Created zip at", zipFilename
|
||||
|
||||
# i store my google code username/pw in a config so i can have this file in public source control
|
||||
config = ConfigParser.ConfigParser()
|
||||
configFilename = os.path.join(compile_dir, "gc.ini")
|
||||
config.read(configFilename)
|
||||
|
||||
gc_username = config.get("GC", "username")
|
||||
gc_password = config.get("GC", "password")
|
||||
|
||||
# upload to google code unless I tell it not to
|
||||
if "noup" not in oldArgs and "test" not in oldArgs:
|
||||
print "Uploading zip to google code"
|
||||
googlecode_upload.upload(os.path.abspath(zipFilename + ".zip"), "SickGear", gc_username, gc_password,
|
||||
"Win32 alpha build " + str(currentBuildNumber) + " (unstable/development release)",
|
||||
["Featured", "Type-Executable", "OpSys-Windows"])
|
||||
|
||||
if 'nopush' not in oldArgs and 'test' not in oldArgs:
|
||||
# tag commit as a new build and push changes to github
|
||||
print 'Tagging commit and pushing'
|
||||
p = subprocess.Popen('git tag -a "build-' + str(currentBuildNumber) + '" -m "Windows build ' + zipFilename + '"',
|
||||
shell=True, cwd=compile_dir)
|
||||
o, e = p.communicate()
|
||||
p = subprocess.Popen('git push --tags origin windows_binaries', shell=True, cwd=compile_dir)
|
||||
o, e = p.communicate()
|
|
@ -147,6 +147,7 @@ ROOT_DIRS = None
|
|||
UPDATE_SHOWS_ON_START = False
|
||||
TRASH_REMOVE_SHOW = False
|
||||
TRASH_ROTATE_LOGS = False
|
||||
HOME_SEARCH_FOCUS = True
|
||||
SORT_ARTICLE = False
|
||||
DEBUG = False
|
||||
|
||||
|
@ -474,7 +475,7 @@ def initialize(consoleLogging=True):
|
|||
USE_TRAKT, TRAKT_USERNAME, TRAKT_PASSWORD, TRAKT_API, TRAKT_REMOVE_WATCHLIST, TRAKT_USE_WATCHLIST, TRAKT_METHOD_ADD, TRAKT_START_PAUSED, traktCheckerScheduler, TRAKT_USE_RECOMMENDED, TRAKT_SYNC, TRAKT_DEFAULT_INDEXER, TRAKT_REMOVE_SERIESLIST, \
|
||||
USE_PLEX, PLEX_NOTIFY_ONSNATCH, PLEX_NOTIFY_ONDOWNLOAD, PLEX_NOTIFY_ONSUBTITLEDOWNLOAD, PLEX_UPDATE_LIBRARY, \
|
||||
PLEX_SERVER_HOST, PLEX_HOST, PLEX_USERNAME, PLEX_PASSWORD, DEFAULT_BACKLOG_FREQUENCY, MIN_BACKLOG_FREQUENCY, BACKLOG_STARTUP, SKIP_REMOVED_FILES, \
|
||||
showUpdateScheduler, __INITIALIZED__, LAUNCH_BROWSER, UPDATE_SHOWS_ON_START, TRASH_REMOVE_SHOW, TRASH_ROTATE_LOGS, SORT_ARTICLE, showList, loadingShowList, \
|
||||
showUpdateScheduler, __INITIALIZED__, LAUNCH_BROWSER, UPDATE_SHOWS_ON_START, TRASH_REMOVE_SHOW, TRASH_ROTATE_LOGS, HOME_SEARCH_FOCUS, SORT_ARTICLE, showList, loadingShowList, \
|
||||
NEWZNAB_DATA, NZBS, NZBS_UID, NZBS_HASH, INDEXER_DEFAULT, INDEXER_TIMEOUT, USENET_RETENTION, TORRENT_DIR, \
|
||||
QUALITY_DEFAULT, FLATTEN_FOLDERS_DEFAULT, SUBTITLES_DEFAULT, STATUS_DEFAULT, DAILYSEARCH_STARTUP, \
|
||||
GROWL_NOTIFY_ONSNATCH, GROWL_NOTIFY_ONDOWNLOAD, GROWL_NOTIFY_ONSUBTITLEDOWNLOAD, TWITTER_NOTIFY_ONSNATCH, TWITTER_NOTIFY_ONDOWNLOAD, TWITTER_NOTIFY_ONSUBTITLEDOWNLOAD, \
|
||||
|
@ -610,6 +611,7 @@ def initialize(consoleLogging=True):
|
|||
TRASH_REMOVE_SHOW = bool(check_setting_int(CFG, 'General', 'trash_remove_show', 0))
|
||||
TRASH_ROTATE_LOGS = bool(check_setting_int(CFG, 'General', 'trash_rotate_logs', 0))
|
||||
|
||||
HOME_SEARCH_FOCUS = bool(check_setting_int(CFG, 'General', 'home_search_focus', HOME_SEARCH_FOCUS))
|
||||
SORT_ARTICLE = bool(check_setting_int(CFG, 'General', 'sort_article', 0))
|
||||
|
||||
USE_API = bool(check_setting_int(CFG, 'General', 'use_api', 0))
|
||||
|
@ -1067,7 +1069,7 @@ def initialize(consoleLogging=True):
|
|||
|
||||
# initialize the main SB database
|
||||
myDB = db.DBConnection()
|
||||
db.upgradeDatabase(myDB, mainDB.InitialSchema)
|
||||
db.MigrationCode(myDB)
|
||||
|
||||
# initialize the cache database
|
||||
myDB = db.DBConnection('cache.db')
|
||||
|
@ -1430,6 +1432,7 @@ def save_config():
|
|||
new_config['General']['update_shows_on_start'] = int(UPDATE_SHOWS_ON_START)
|
||||
new_config['General']['trash_remove_show'] = int(TRASH_REMOVE_SHOW)
|
||||
new_config['General']['trash_rotate_logs'] = int(TRASH_ROTATE_LOGS)
|
||||
new_config['General']['home_search_focus'] = int(HOME_SEARCH_FOCUS)
|
||||
new_config['General']['sort_article'] = int(SORT_ARTICLE)
|
||||
new_config['General']['proxy_setting'] = PROXY_SETTING
|
||||
new_config['General']['proxy_indexers'] = int(PROXY_INDEXERS)
|
||||
|
|
|
@ -98,7 +98,7 @@ class BlackAndWhiteList(object):
|
|||
def _add_keywords(self, table, range, values):
|
||||
myDB = db.DBConnection()
|
||||
for value in values:
|
||||
myDB.action("INSERT INTO " + table + " (show_id, range , keyword) VALUES (?,?,?)", [self.show_id, range, value])
|
||||
myDB.action("INSERT INTO [" + table + "] (show_id, range , keyword) VALUES (?,?,?)", [self.show_id, range, value])
|
||||
|
||||
self.refresh()
|
||||
|
||||
|
@ -117,18 +117,18 @@ class BlackAndWhiteList(object):
|
|||
def _del_all_keywords(self, table):
|
||||
logger.log(u"Deleting all " + table + " keywords for " + str(self.show_id), logger.DEBUG)
|
||||
myDB = db.DBConnection()
|
||||
myDB.action("DELETE FROM " + table + " WHERE show_id = ?", [self.show_id])
|
||||
myDB.action("DELETE FROM [" + table + "] WHERE show_id = ?", [self.show_id])
|
||||
self.refresh()
|
||||
|
||||
def _del_all_keywords_for(self, table, range):
|
||||
logger.log(u"Deleting all " + range + " " + table + " keywords for " + str(self.show_id), logger.DEBUG)
|
||||
myDB = db.DBConnection()
|
||||
myDB.action("DELETE FROM " + table + " WHERE show_id = ? and range = ?", [self.show_id, range])
|
||||
myDB.action("DELETE FROM [" + table + "] WHERE show_id = ? and range = ?", [self.show_id, range])
|
||||
self.refresh()
|
||||
|
||||
def _load_list(self, table):
|
||||
myDB = db.DBConnection()
|
||||
sqlResults = myDB.select("SELECT range,keyword FROM " + table + " WHERE show_id = ? ", [self.show_id])
|
||||
sqlResults = myDB.select("SELECT range,keyword FROM [" + table + "] WHERE show_id = ? ", [self.show_id])
|
||||
if not sqlResults or not len(sqlResults):
|
||||
return ([], {})
|
||||
|
||||
|
|
164
sickbeard/db.py
|
@ -229,20 +229,20 @@ class DBConnection(object):
|
|||
|
||||
genParams = lambda myDict: [x + " = ?" for x in myDict.keys()]
|
||||
|
||||
query = "UPDATE " + tableName + " SET " + ", ".join(genParams(valueDict)) + " WHERE " + " AND ".join(
|
||||
query = "UPDATE [" + tableName + "] SET " + ", ".join(genParams(valueDict)) + " WHERE " + " AND ".join(
|
||||
genParams(keyDict))
|
||||
|
||||
self.action(query, valueDict.values() + keyDict.values())
|
||||
|
||||
if self.connection.total_changes == changesBefore:
|
||||
query = "INSERT INTO " + tableName + " (" + ", ".join(valueDict.keys() + keyDict.keys()) + ")" + \
|
||||
query = "INSERT INTO [" + tableName + "] (" + ", ".join(valueDict.keys() + keyDict.keys()) + ")" + \
|
||||
" VALUES (" + ", ".join(["?"] * len(valueDict.keys() + keyDict.keys())) + ")"
|
||||
self.action(query, valueDict.values() + keyDict.values())
|
||||
|
||||
def tableInfo(self, tableName):
|
||||
|
||||
# FIXME ? binding is not supported here, but I cannot find a way to escape a string manually
|
||||
sqlResult = self.select("PRAGMA table_info(%s)" % tableName)
|
||||
sqlResult = self.select("PRAGMA table_info([%s])" % tableName)
|
||||
columns = {}
|
||||
for column in sqlResult:
|
||||
columns[column['name']] = {'type': column['type']}
|
||||
|
@ -261,9 +261,17 @@ class DBConnection(object):
|
|||
def hasColumn(self, tableName, column):
|
||||
return column in self.tableInfo(tableName)
|
||||
|
||||
def hasIndex(self, tableName, index):
|
||||
sqlResults = self.select('PRAGMA index_list([%s])' % tableName)
|
||||
for result in sqlResults:
|
||||
if result['name'] == index:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def addColumn(self, table, column, type="NUMERIC", default=0):
|
||||
self.action("ALTER TABLE %s ADD %s %s" % (table, column, type))
|
||||
self.action("UPDATE %s SET %s = ?" % (table, column), (default,))
|
||||
self.action("ALTER TABLE [%s] ADD %s %s" % (table, column, type))
|
||||
self.action("UPDATE [%s] SET %s = ?" % (table, column), (default,))
|
||||
|
||||
def close(self):
|
||||
"""Close database connection"""
|
||||
|
@ -353,8 +361,71 @@ class SchemaUpgrade(object):
|
|||
return column in self.connection.tableInfo(tableName)
|
||||
|
||||
def addColumn(self, table, column, type="NUMERIC", default=0):
|
||||
self.connection.action("ALTER TABLE %s ADD %s %s" % (table, column, type))
|
||||
self.connection.action("UPDATE %s SET %s = ?" % (table, column), (default,))
|
||||
self.connection.action("ALTER TABLE [%s] ADD %s %s" % (table, column, type))
|
||||
self.connection.action("UPDATE [%s] SET %s = ?" % (table, column), (default,))
|
||||
|
||||
def dropColumn(self, table, column):
|
||||
# get old table columns and store the ones we want to keep
|
||||
result = self.connection.select('pragma table_info([%s])' % table)
|
||||
keptColumns = [c for c in result if c['name'] != column]
|
||||
|
||||
keptColumnsNames = []
|
||||
final = []
|
||||
pk = []
|
||||
|
||||
# copy the old table schema, column by column
|
||||
for column in keptColumns:
|
||||
|
||||
keptColumnsNames.append(column['name'])
|
||||
|
||||
cl = []
|
||||
cl.append(column['name'])
|
||||
cl.append(column['type'])
|
||||
|
||||
'''
|
||||
To be implemented if ever required
|
||||
if column['dflt_value']:
|
||||
cl.append(str(column['dflt_value']))
|
||||
|
||||
if column['notnull']:
|
||||
cl.append(column['notnull'])
|
||||
'''
|
||||
|
||||
if int(column['pk']) != 0:
|
||||
pk.append(column['name'])
|
||||
|
||||
b = ' '.join(cl)
|
||||
final.append(b)
|
||||
|
||||
# join all the table column creation fields
|
||||
final = ', '.join(final)
|
||||
keptColumnsNames = ', '.join(keptColumnsNames)
|
||||
|
||||
# generate sql for the new table creation
|
||||
if len(pk) == 0:
|
||||
sql = 'CREATE TABLE [%s_new] (%s)' % (table, final)
|
||||
else:
|
||||
pk = ', '.join(pk)
|
||||
sql = 'CREATE TABLE [%s_new] (%s, PRIMARY KEY(%s))' % (table, final, pk)
|
||||
|
||||
# create new temporary table and copy the old table data across, barring the removed column
|
||||
self.connection.action(sql)
|
||||
self.connection.action('INSERT INTO [%s_new] SELECT %s FROM [%s]' % (table, keptColumnsNames, table))
|
||||
|
||||
# copy the old indexes from the old table
|
||||
result = self.connection.select('SELECT sql FROM sqlite_master WHERE tbl_name=? and type="index"', [table])
|
||||
|
||||
# remove the old table and rename the new table to take it's place
|
||||
self.connection.action('DROP TABLE [%s]' % table)
|
||||
self.connection.action('ALTER TABLE [%s_new] RENAME TO [%s]' % (table, table))
|
||||
|
||||
# write any indexes to the new table
|
||||
if len(result) > 0:
|
||||
for index in result:
|
||||
self.connection.action(index['sql'])
|
||||
|
||||
# vacuum the db as we will have a lot of space to reclaim after dropping tables
|
||||
self.connection.action("VACUUM")
|
||||
|
||||
def checkDBVersion(self):
|
||||
return self.connection.checkDBVersion()
|
||||
|
@ -363,3 +434,82 @@ class SchemaUpgrade(object):
|
|||
new_version = self.checkDBVersion() + 1
|
||||
self.connection.action("UPDATE db_version SET db_version = ?", [new_version])
|
||||
return new_version
|
||||
|
||||
def setDBVersion(self, new_version):
|
||||
self.connection.action("UPDATE db_version SET db_version = ?", [new_version])
|
||||
return new_version
|
||||
|
||||
|
||||
def MigrationCode(myDB):
|
||||
|
||||
schema = {
|
||||
0: sickbeard.mainDB.InitialSchema, # 0->20000
|
||||
9: sickbeard.mainDB.AddSizeAndSceneNameFields,
|
||||
10: sickbeard.mainDB.RenameSeasonFolders,
|
||||
11: sickbeard.mainDB.Add1080pAndRawHDQualities,
|
||||
12: sickbeard.mainDB.AddShowidTvdbidIndex,
|
||||
13: sickbeard.mainDB.AddLastUpdateTVDB,
|
||||
14: sickbeard.mainDB.AddDBIncreaseTo15,
|
||||
15: sickbeard.mainDB.AddIMDbInfo,
|
||||
16: sickbeard.mainDB.AddProperNamingSupport,
|
||||
17: sickbeard.mainDB.AddEmailSubscriptionTable,
|
||||
18: sickbeard.mainDB.AddProperSearch,
|
||||
19: sickbeard.mainDB.AddDvdOrderOption,
|
||||
20: sickbeard.mainDB.AddSubtitlesSupport,
|
||||
21: sickbeard.mainDB.ConvertTVShowsToIndexerScheme,
|
||||
22: sickbeard.mainDB.ConvertTVEpisodesToIndexerScheme,
|
||||
23: sickbeard.mainDB.ConvertIMDBInfoToIndexerScheme,
|
||||
24: sickbeard.mainDB.ConvertInfoToIndexerScheme,
|
||||
25: sickbeard.mainDB.AddArchiveFirstMatchOption,
|
||||
26: sickbeard.mainDB.AddSceneNumbering,
|
||||
27: sickbeard.mainDB.ConvertIndexerToInteger,
|
||||
28: sickbeard.mainDB.AddRequireAndIgnoreWords,
|
||||
29: sickbeard.mainDB.AddSportsOption,
|
||||
30: sickbeard.mainDB.AddSceneNumberingToTvEpisodes,
|
||||
31: sickbeard.mainDB.AddAnimeTVShow,
|
||||
32: sickbeard.mainDB.AddAbsoluteNumbering,
|
||||
33: sickbeard.mainDB.AddSceneAbsoluteNumbering,
|
||||
34: sickbeard.mainDB.AddAnimeBlacklistWhitelist,
|
||||
35: sickbeard.mainDB.AddSceneAbsoluteNumbering2,
|
||||
36: sickbeard.mainDB.AddXemRefresh,
|
||||
37: sickbeard.mainDB.AddSceneToTvShows,
|
||||
38: sickbeard.mainDB.AddIndexerMapping,
|
||||
39: sickbeard.mainDB.AddVersionToTvEpisodes,
|
||||
|
||||
40: sickbeard.mainDB.BumpDatabaseVersion,
|
||||
41: sickbeard.mainDB.Migrate41,
|
||||
|
||||
10000: sickbeard.mainDB.SickGearDatabaseVersion,
|
||||
10001: sickbeard.mainDB.RemoveDefaultEpStatusFromTvShows
|
||||
|
||||
#20000: sickbeard.mainDB.AddCoolSickGearFeature1,
|
||||
#20001: sickbeard.mainDB.AddCoolSickGearFeature2,
|
||||
#20002: sickbeard.mainDB.AddCoolSickGearFeature3,
|
||||
}
|
||||
|
||||
db_version = myDB.checkDBVersion()
|
||||
logger.log(u'Detected database version: v' + str(db_version), logger.DEBUG)
|
||||
|
||||
if not (db_version in schema):
|
||||
if db_version == sickbeard.mainDB.MAX_DB_VERSION:
|
||||
logger.log(u'Database schema is up-to-date, no upgrade required')
|
||||
elif db_version < 10000:
|
||||
logger.log_error_and_exit(u'SickGear does not currently support upgrading from this database version')
|
||||
else:
|
||||
logger.log_error_and_exit(u'Invalid database version')
|
||||
|
||||
else:
|
||||
|
||||
while db_version < sickbeard.mainDB.MAX_DB_VERSION:
|
||||
try:
|
||||
update = schema[db_version](myDB)
|
||||
db_version = update.execute()
|
||||
except Exception, e:
|
||||
myDB.close()
|
||||
logger.log(u'Failed to update database with error: ' + ex(e) + ' attempting recovery...', logger.ERROR)
|
||||
|
||||
if restoreDatabase(db_version):
|
||||
# initialize the main SB database
|
||||
logger.log_error_and_exit(u'Successfully restored database version:' + str(db_version))
|
||||
else:
|
||||
logger.log_error_and_exit(u'Failed to restore database version:' + str(db_version))
|
|
@ -1430,4 +1430,75 @@ def get_size(start_path='.'):
|
|||
|
||||
|
||||
def remove_article(text=''):
|
||||
return re.sub(r'(?i)/^(?:(?:A(?!\s+to)n?)|The)\s(\w)', r'\1', text)
|
||||
return re.sub(r'(?i)^(?:(?:A(?!\s+to)n?)|The)\s(\w)', r'\1', text)
|
||||
|
||||
|
||||
def client_host(server_host):
|
||||
'''Extracted from cherrypy libs
|
||||
Return the host on which a client can connect to the given listener.'''
|
||||
if server_host == '0.0.0.0':
|
||||
# 0.0.0.0 is INADDR_ANY, which should answer on localhost.
|
||||
return '127.0.0.1'
|
||||
if server_host in ('::', '::0', '::0.0.0.0'):
|
||||
# :: is IN6ADDR_ANY, which should answer on localhost.
|
||||
# ::0 and ::0.0.0.0 are non-canonical but common ways to write
|
||||
# IN6ADDR_ANY.
|
||||
return '::1'
|
||||
return server_host
|
||||
|
||||
|
||||
def wait_for_free_port(host, port):
|
||||
'''Extracted from cherrypy libs
|
||||
Wait for the specified port to become free (drop requests).'''
|
||||
if not host:
|
||||
raise ValueError("Host values of '' or None are not allowed.")
|
||||
for trial in range(50):
|
||||
try:
|
||||
# we are expecting a free port, so reduce the timeout
|
||||
check_port(host, port, timeout=0.1)
|
||||
except IOError:
|
||||
# Give the old server thread time to free the port.
|
||||
time.sleep(0.1)
|
||||
else:
|
||||
return
|
||||
|
||||
raise IOError("Port %r not free on %r" % (port, host))
|
||||
|
||||
|
||||
def check_port(host, port, timeout=1.0):
|
||||
'''Extracted from cherrypy libs
|
||||
Raise an error if the given port is not free on the given host.'''
|
||||
if not host:
|
||||
raise ValueError("Host values of '' or None are not allowed.")
|
||||
host = client_host(host)
|
||||
port = int(port)
|
||||
|
||||
import socket
|
||||
|
||||
# AF_INET or AF_INET6 socket
|
||||
# Get the correct address family for our host (allows IPv6 addresses)
|
||||
try:
|
||||
info = socket.getaddrinfo(host, port, socket.AF_UNSPEC,
|
||||
socket.SOCK_STREAM)
|
||||
except socket.gaierror:
|
||||
if ':' in host:
|
||||
info = [(socket.AF_INET6, socket.SOCK_STREAM, 0, "", (host, port, 0, 0))]
|
||||
else:
|
||||
info = [(socket.AF_INET, socket.SOCK_STREAM, 0, "", (host, port))]
|
||||
|
||||
for res in info:
|
||||
af, socktype, proto, canonname, sa = res
|
||||
s = None
|
||||
try:
|
||||
s = socket.socket(af, socktype, proto)
|
||||
# See http://groups.google.com/group/cherrypy-users/
|
||||
# browse_frm/thread/bbfe5eb39c904fe0
|
||||
s.settimeout(timeout)
|
||||
s.connect((host, port))
|
||||
s.close()
|
||||
raise IOError("Port %s is in use on %s; perhaps the previous "
|
||||
"httpserver did not shut down properly." %
|
||||
(repr(port), repr(host)))
|
||||
except socket.error:
|
||||
if s:
|
||||
s.close()
|
||||
|
|
|
@ -27,33 +27,113 @@ from sickbeard import common
|
|||
from sickbeard.exceptions import ex
|
||||
from sickbeard.encodingKludge import fixStupidEncodings
|
||||
|
||||
from sickbeard.notifiers.xbmc import XBMCNotifier
|
||||
|
||||
# TODO: switch over to using ElementTree
|
||||
from xml.dom import minidom
|
||||
try:
|
||||
import xml.etree.cElementTree as etree
|
||||
except ImportError:
|
||||
import elementtree.ElementTree as etree
|
||||
|
||||
|
||||
class PLEXNotifier(XBMCNotifier):
|
||||
def _notify_pmc(self, message, title="SickGear", host=None, username=None, password=None, force=False):
|
||||
class PLEXNotifier:
|
||||
|
||||
def _send_to_plex(self, command, host, username=None, password=None):
|
||||
"""Handles communication to Plex hosts via HTTP API
|
||||
|
||||
Args:
|
||||
command: Dictionary of field/data pairs, encoded via urllib and passed to the legacy xbmcCmds HTTP API
|
||||
host: Plex host:port
|
||||
username: Plex API username
|
||||
password: Plex API password
|
||||
|
||||
Returns:
|
||||
Returns 'OK' for successful commands or False if there was an error
|
||||
|
||||
"""
|
||||
|
||||
# fill in omitted parameters
|
||||
if not host:
|
||||
if sickbeard.PLEX_HOST:
|
||||
host = sickbeard.PLEX_HOST # Use the default Plex host
|
||||
else:
|
||||
logger.log(u"No Plex host specified, check your settings", logger.DEBUG)
|
||||
return False
|
||||
if not username:
|
||||
username = sickbeard.PLEX_USERNAME
|
||||
if not password:
|
||||
password = sickbeard.PLEX_PASSWORD
|
||||
|
||||
# suppress notifications if the notifier is disabled but the notify options are checked
|
||||
if not sickbeard.USE_PLEX and not force:
|
||||
logger.log("Notification for Plex not enabled, skipping this notification", logger.DEBUG)
|
||||
if not host:
|
||||
logger.log(u"PLEX: No host specified, check your settings", logger.ERROR)
|
||||
return False
|
||||
|
||||
return self._notify_xbmc(message=message, title=title, host=host, username=username, password=password,
|
||||
force=True)
|
||||
for key in command:
|
||||
if type(command[key]) == unicode:
|
||||
command[key] = command[key].encode('utf-8')
|
||||
|
||||
enc_command = urllib.urlencode(command)
|
||||
logger.log(u"PLEX: Encoded API command: " + enc_command, logger.DEBUG)
|
||||
|
||||
url = 'http://%s/xbmcCmds/xbmcHttp/?%s' % (host, enc_command)
|
||||
try:
|
||||
req = urllib2.Request(url)
|
||||
# if we have a password, use authentication
|
||||
if password:
|
||||
base64string = base64.encodestring('%s:%s' % (username, password))[:-1]
|
||||
authheader = "Basic %s" % base64string
|
||||
req.add_header("Authorization", authheader)
|
||||
logger.log(u"PLEX: Contacting (with auth header) via url: " + url, logger.DEBUG)
|
||||
else:
|
||||
logger.log(u"PLEX: Contacting via url: " + url, logger.DEBUG)
|
||||
|
||||
response = urllib2.urlopen(req)
|
||||
|
||||
result = response.read().decode(sickbeard.SYS_ENCODING)
|
||||
response.close()
|
||||
|
||||
logger.log(u"PLEX: HTTP response: " + result.replace('\n', ''), logger.DEBUG)
|
||||
# could return result response = re.compile('<html><li>(.+\w)</html>').findall(result)
|
||||
return 'OK'
|
||||
|
||||
except (urllib2.URLError, IOError), e:
|
||||
logger.log(u"PLEX: Warning: Couldn't contact Plex at " + fixStupidEncodings(url) + " " + ex(e), logger.WARNING)
|
||||
return False
|
||||
|
||||
def _notify(self, message, title="SickGear", host=None, username=None, password=None, force=False):
|
||||
"""Internal wrapper for the notify_snatch and notify_download functions
|
||||
|
||||
Args:
|
||||
message: Message body of the notice to send
|
||||
title: Title of the notice to send
|
||||
host: Plex Media Client(s) host:port
|
||||
username: Plex username
|
||||
password: Plex password
|
||||
force: Used for the Test method to override config safety checks
|
||||
|
||||
Returns:
|
||||
Returns a list results in the format of host:ip:result
|
||||
The result will either be 'OK' or False, this is used to be parsed by the calling function.
|
||||
|
||||
"""
|
||||
|
||||
# suppress notifications if the notifier is disabled but the notify options are checked
|
||||
if not sickbeard.USE_PLEX and not force:
|
||||
return False
|
||||
|
||||
# fill in omitted parameters
|
||||
if not host:
|
||||
host = sickbeard.PLEX_HOST
|
||||
if not username:
|
||||
username = sickbeard.PLEX_USERNAME
|
||||
if not password:
|
||||
password = sickbeard.PLEX_PASSWORD
|
||||
|
||||
result = ''
|
||||
for curHost in [x.strip() for x in host.split(",")]:
|
||||
logger.log(u"PLEX: Sending notification to '" + curHost + "' - " + message, logger.MESSAGE)
|
||||
|
||||
command = {'command': 'ExecBuiltIn', 'parameter': 'Notification(' + title.encode("utf-8") + ',' + message.encode("utf-8") + ')'}
|
||||
notifyResult = self._send_to_plex(command, curHost, username, password)
|
||||
if notifyResult:
|
||||
result += curHost + ':' + str(notifyResult)
|
||||
|
||||
return result
|
||||
|
||||
##############################################################################
|
||||
# Public functions
|
||||
##############################################################################
|
||||
|
||||
def notify_snatch(self, ep_name):
|
||||
if sickbeard.PLEX_NOTIFY_ONSNATCH:
|
||||
|
@ -74,10 +154,9 @@ class PLEXNotifier(XBMCNotifier):
|
|||
self._notify_pmc(update_text + new_version, title)
|
||||
|
||||
def test_notify(self, host, username, password):
|
||||
return self._notify_pmc("Testing Plex notifications from SickGear", "Test Notification", host, username,
|
||||
password, force=True)
|
||||
return self._notify("This is a test notification from SickGear", "Test", host, username, password, force=True)
|
||||
|
||||
def update_library(self):
|
||||
def update_library(self, ep_obj=None, host=None, username=None, password=None):
|
||||
"""Handles updating the Plex Media Server host via HTTP API
|
||||
|
||||
Plex Media Server currently only supports updating the whole video library and not a specific path.
|
||||
|
@ -87,36 +166,68 @@ class PLEXNotifier(XBMCNotifier):
|
|||
|
||||
"""
|
||||
|
||||
# fill in omitted parameters
|
||||
if not host:
|
||||
host = sickbeard.PLEX_SERVER_HOST
|
||||
if not username:
|
||||
username = sickbeard.PLEX_USERNAME
|
||||
if not password:
|
||||
password = sickbeard.PLEX_PASSWORD
|
||||
|
||||
if sickbeard.USE_PLEX and sickbeard.PLEX_UPDATE_LIBRARY:
|
||||
if not sickbeard.PLEX_SERVER_HOST:
|
||||
logger.log(u"No Plex Media Server host specified, check your settings", logger.DEBUG)
|
||||
logger.log(u"PLEX: No Plex Media Server host specified, check your settings", logger.DEBUG)
|
||||
return False
|
||||
|
||||
logger.log(u"Updating library for the Plex Media Server host: " + sickbeard.PLEX_SERVER_HOST,
|
||||
logger.MESSAGE)
|
||||
logger.log(u"PLEX: Updating library for the Plex Media Server host: " + host, logger.MESSAGE)
|
||||
|
||||
url = "http://%s/library/sections" % sickbeard.PLEX_SERVER_HOST
|
||||
# if username and password were provided, fetch the auth token from plex.tv
|
||||
token_arg = ""
|
||||
if username and password:
|
||||
|
||||
logger.log(u"PLEX: fetching credentials for Plex user: " + username, logger.DEBUG)
|
||||
req = urllib2.Request("https://plex.tv/users/sign_in.xml", data="")
|
||||
base64string = base64.encodestring('%s:%s' % (username, password))[:-1]
|
||||
authheader = "Basic %s" % base64string
|
||||
req.add_header("Authorization", authheader)
|
||||
req.add_header("X-Plex-Client-Identifier", "Sick-Beard-Notifier")
|
||||
|
||||
try:
|
||||
response = urllib2.urlopen(req)
|
||||
except urllib2.URLError, e:
|
||||
logger.log(u"PLEX: Error fetching credentials from from plex.tv for user %s: %s" % (username, ex(e)), logger.MESSAGE)
|
||||
return False
|
||||
|
||||
try:
|
||||
auth_tree = etree.parse(response)
|
||||
token = auth_tree.findall(".//authentication-token")[0].text
|
||||
token_arg = "?X-Plex-Token=" + token
|
||||
except (ValueError, IndexError) as e:
|
||||
logger.log(u"PLEX: Error parsing plex.tv response: " + ex(e), logger.MESSAGE)
|
||||
return False
|
||||
|
||||
url = "http://%s/library/sections%s" % (sickbeard.PLEX_SERVER_HOST, token_arg)
|
||||
try:
|
||||
xml_sections = minidom.parse(urllib.urlopen(url))
|
||||
xml_tree = etree.parse(urllib.urlopen(url))
|
||||
media_container = xml_tree.getroot()
|
||||
except IOError, e:
|
||||
logger.log(u"Error while trying to contact Plex Media Server: " + ex(e), logger.ERROR)
|
||||
logger.log(u"PLEX: Error while trying to contact Plex Media Server: " + ex(e), logger.ERROR)
|
||||
return False
|
||||
|
||||
sections = xml_sections.getElementsByTagName('Directory')
|
||||
sections = media_container.findall('.//Directory')
|
||||
if not sections:
|
||||
logger.log(u"Plex Media Server not running on: " + sickbeard.PLEX_SERVER_HOST, logger.MESSAGE)
|
||||
logger.log(u"PLEX: Plex Media Server not running on: " + sickbeard.PLEX_SERVER_HOST, logger.MESSAGE)
|
||||
return False
|
||||
|
||||
for s in sections:
|
||||
if s.getAttribute('type') == "show":
|
||||
url = "http://%s/library/sections/%s/refresh" % (sickbeard.PLEX_SERVER_HOST, s.getAttribute('key'))
|
||||
for section in sections:
|
||||
if section.attrib['type'] == "show":
|
||||
url = "http://%s/library/sections/%s/refresh%s" % (sickbeard.PLEX_SERVER_HOST, section.attrib['key'], token_arg)
|
||||
try:
|
||||
urllib.urlopen(url)
|
||||
except Exception, e:
|
||||
logger.log(u"Error updating library section for Plex Media Server: " + ex(e), logger.ERROR)
|
||||
logger.log(u"PLEX: Error updating library section for Plex Media Server: " + ex(e), logger.ERROR)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
notifier = PLEXNotifier
|
||||
|
|
|
@ -61,8 +61,8 @@ class KATProvider(generic.TorrentProvider):
|
|||
|
||||
self.cache = KATCache(self)
|
||||
|
||||
self.urls = ['http://kickass.to/', 'http://katproxy.com/', 'http://www.kickmirror.com/']
|
||||
self.url = 'https://kickass.to/'
|
||||
self.urls = ['http://kickass.so/', 'http://katproxy.com/', 'http://www.kickmirror.com/']
|
||||
self.url = 'https://kickass.so/'
|
||||
|
||||
def isEnabled(self):
|
||||
return self.enabled
|
||||
|
|
|
@ -35,10 +35,10 @@ from sickbeard.helpers import sanitizeSceneName
|
|||
|
||||
|
||||
class TorrentDayProvider(generic.TorrentProvider):
|
||||
urls = {'base_url': 'http://www.torrentday.com',
|
||||
'login': 'http://www.torrentday.com/torrents/',
|
||||
'search': 'http://www.torrentday.com/V3/API/API.php',
|
||||
'download': 'http://www.torrentday.com/download.php/%s/%s'
|
||||
urls = {'base_url': 'https://torrentday.eu',
|
||||
'login': 'https://torrentday.eu/torrents/',
|
||||
'search': 'https://torrentday.eu/V3/API/API.php',
|
||||
'download': 'https://torrentday.eu/download.php/%s/%s'
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
|
|
|
@ -59,20 +59,20 @@ def filterBadReleases(name, parse=True):
|
|||
# if any of the bad strings are in the name then say no
|
||||
if sickbeard.IGNORE_WORDS:
|
||||
resultFilters.extend(sickbeard.IGNORE_WORDS.split(','))
|
||||
filters = [re.compile('(^|[\W_])%s($|[\W_])' % filter.strip(), re.I) for filter in resultFilters]
|
||||
filters = [re.compile('(^|[\W_])%s($|[\W_])' % re.escape(filter.strip()), re.I) for filter in resultFilters]
|
||||
for regfilter in filters:
|
||||
if regfilter.search(name):
|
||||
logger.log(u"Invalid scene release: " + name + " contains pattern: " + regfilter.pattern + ", ignoring it",
|
||||
logger.log(u"Invalid scene release: " + name + " contained: " + regfilter.pattern + ", ignoring it",
|
||||
logger.DEBUG)
|
||||
return False
|
||||
|
||||
# if any of the good strings aren't in the name then say no
|
||||
if sickbeard.REQUIRE_WORDS:
|
||||
require_words = sickbeard.REQUIRE_WORDS.split(',')
|
||||
filters = [re.compile('(^|[\W_])%s($|[\W_])' % filter.strip(), re.I) for filter in require_words]
|
||||
filters = [re.compile('(^|[\W_])%s($|[\W_])' % re.escape(filter.strip()), re.I) for filter in require_words]
|
||||
for regfilter in filters:
|
||||
if not regfilter.search(name):
|
||||
logger.log(u"Invalid scene release: " + name + " doesn't contain pattern: " + regfilter.pattern + ", ignoring it",
|
||||
logger.log(u"Invalid scene release: " + name + " didn't contain: " + regfilter.pattern + ", ignoring it",
|
||||
logger.DEBUG)
|
||||
return False
|
||||
|
||||
|
|
|
@ -36,41 +36,44 @@ import itertools
|
|||
|
||||
class CacheDBConnection(db.DBConnection):
|
||||
def __init__(self, providerName):
|
||||
db.DBConnection.__init__(self, "cache.db")
|
||||
db.DBConnection.__init__(self, 'cache.db')
|
||||
|
||||
# Create the table if it's not already there
|
||||
try:
|
||||
if not self.hasTable(providerName):
|
||||
self.action(
|
||||
"CREATE TABLE [" + providerName + "] (name TEXT, season NUMERIC, episodes TEXT, indexerid NUMERIC, url TEXT, time NUMERIC, quality TEXT, release_group TEXT)")
|
||||
else:
|
||||
'CREATE TABLE [' + providerName + '] (name TEXT, season NUMERIC, episodes TEXT, indexerid NUMERIC, url TEXT, time NUMERIC, quality TEXT, release_group TEXT)')
|
||||
self.action(
|
||||
'CREATE UNIQUE INDEX IF NOT EXISTS [idx_' + providerName + '_url] ON [' + providerName + '] (url)')
|
||||
elif not self.hasIndex(providerName, 'idx_%s_url' % providerName):
|
||||
sqlResults = self.select(
|
||||
"SELECT url, COUNT(url) as count FROM [" + providerName + "] GROUP BY url HAVING count > 1")
|
||||
'SELECT url, COUNT(url) as count FROM [' + providerName + '] GROUP BY url HAVING count > 1')
|
||||
|
||||
for cur_dupe in sqlResults:
|
||||
self.action("DELETE FROM [" + providerName + "] WHERE url = ?", [cur_dupe["url"]])
|
||||
self.action('DELETE FROM [' + providerName + '] WHERE url = ?', [cur_dupe['url']])
|
||||
|
||||
self.action(
|
||||
'CREATE UNIQUE INDEX IF NOT EXISTS [idx_' + providerName + '_url] ON [' + providerName + '] (url)')
|
||||
|
||||
# add unique index to prevent further dupes from happening if one does not exist
|
||||
self.action("CREATE UNIQUE INDEX IF NOT EXISTS idx_url ON [" + providerName + "] (url)")
|
||||
|
||||
# add release_group column to table if missing
|
||||
if not self.hasColumn(providerName, 'release_group'):
|
||||
self.addColumn(providerName, 'release_group', "TEXT", "")
|
||||
self.addColumn(providerName, 'release_group', 'TEXT', '')
|
||||
|
||||
# add version column to table if missing
|
||||
if not self.hasColumn(providerName, 'version'):
|
||||
self.addColumn(providerName, 'version', "NUMERIC", "-1")
|
||||
self.addColumn(providerName, 'version', 'NUMERIC', '-1')
|
||||
|
||||
except Exception, e:
|
||||
if str(e) != "table [" + providerName + "] already exists":
|
||||
if str(e) != 'table [' + providerName + '] already exists':
|
||||
raise
|
||||
|
||||
# Create the table if it's not already there
|
||||
try:
|
||||
if not self.hasTable('lastUpdate'):
|
||||
self.action("CREATE TABLE lastUpdate (provider TEXT, time NUMERIC)")
|
||||
self.action('CREATE TABLE lastUpdate (provider TEXT, time NUMERIC)')
|
||||
except Exception, e:
|
||||
if str(e) != "table lastUpdate already exists":
|
||||
if str(e) != 'table lastUpdate already exists':
|
||||
raise
|
||||
|
||||
class TVCache():
|
||||
|
@ -91,7 +94,7 @@ class TVCache():
|
|||
def _clearCache(self):
|
||||
if self.shouldClearCache():
|
||||
myDB = self._getDB()
|
||||
myDB.action("DELETE FROM [" + self.providerID + "] WHERE 1")
|
||||
myDB.action('DELETE FROM [' + self.providerID + '] WHERE 1')
|
||||
|
||||
def _get_title_and_url(self, item):
|
||||
# override this in the provider if daily search has a different data layout to backlog searches
|
||||
|
@ -151,22 +154,22 @@ class TVCache():
|
|||
title = self._translateTitle(title)
|
||||
url = self._translateLinkURL(url)
|
||||
|
||||
logger.log(u"Attempting to add item to cache: " + title, logger.DEBUG)
|
||||
logger.log(u'Attempting to add item to cache: ' + title, logger.DEBUG)
|
||||
return self._addCacheEntry(title, url)
|
||||
|
||||
else:
|
||||
logger.log(
|
||||
u"The data returned from the " + self.provider.name + " feed is incomplete, this result is unusable",
|
||||
u'The data returned from the ' + self.provider.name + ' feed is incomplete, this result is unusable',
|
||||
logger.DEBUG)
|
||||
return None
|
||||
|
||||
|
||||
def _getLastUpdate(self):
|
||||
myDB = self._getDB()
|
||||
sqlResults = myDB.select("SELECT time FROM lastUpdate WHERE provider = ?", [self.providerID])
|
||||
sqlResults = myDB.select('SELECT time FROM lastUpdate WHERE provider = ?', [self.providerID])
|
||||
|
||||
if sqlResults:
|
||||
lastTime = int(sqlResults[0]["time"])
|
||||
lastTime = int(sqlResults[0]['time'])
|
||||
if lastTime > int(time.mktime(datetime.datetime.today().timetuple())):
|
||||
lastTime = 0
|
||||
else:
|
||||
|
@ -176,10 +179,10 @@ class TVCache():
|
|||
|
||||
def _getLastSearch(self):
|
||||
myDB = self._getDB()
|
||||
sqlResults = myDB.select("SELECT time FROM lastSearch WHERE provider = ?", [self.providerID])
|
||||
sqlResults = myDB.select('SELECT time FROM lastSearch WHERE provider = ?', [self.providerID])
|
||||
|
||||
if sqlResults:
|
||||
lastTime = int(sqlResults[0]["time"])
|
||||
lastTime = int(sqlResults[0]['time'])
|
||||
if lastTime > int(time.mktime(datetime.datetime.today().timetuple())):
|
||||
lastTime = 0
|
||||
else:
|
||||
|
@ -193,7 +196,7 @@ class TVCache():
|
|||
toDate = datetime.datetime.today()
|
||||
|
||||
myDB = self._getDB()
|
||||
myDB.upsert("lastUpdate",
|
||||
myDB.upsert('lastUpdate',
|
||||
{'time': int(time.mktime(toDate.timetuple()))},
|
||||
{'provider': self.providerID})
|
||||
|
||||
|
@ -202,7 +205,7 @@ class TVCache():
|
|||
toDate = datetime.datetime.today()
|
||||
|
||||
myDB = self._getDB()
|
||||
myDB.upsert("lastSearch",
|
||||
myDB.upsert('lastSearch',
|
||||
{'time': int(time.mktime(toDate.timetuple()))},
|
||||
{'provider': self.providerID})
|
||||
|
||||
|
@ -212,7 +215,7 @@ class TVCache():
|
|||
def shouldUpdate(self):
|
||||
# if we've updated recently then skip the update
|
||||
if datetime.datetime.today() - self.lastUpdate < datetime.timedelta(minutes=self.minTime):
|
||||
logger.log(u"Last update was too soon, using old cache: today()-" + str(self.lastUpdate) + "<" + str(
|
||||
logger.log(u'Last update was too soon, using old cache: today()-' + str(self.lastUpdate) + '<' + str(
|
||||
datetime.timedelta(minutes=self.minTime)), logger.DEBUG)
|
||||
return False
|
||||
|
||||
|
@ -239,10 +242,10 @@ class TVCache():
|
|||
myParser = NameParser(showObj=showObj, convert=True)
|
||||
parse_result = myParser.parse(name)
|
||||
except InvalidNameException:
|
||||
logger.log(u"Unable to parse the filename " + name + " into a valid episode", logger.DEBUG)
|
||||
logger.log(u'Unable to parse the filename ' + name + ' into a valid episode', logger.DEBUG)
|
||||
return None
|
||||
except InvalidShowException:
|
||||
logger.log(u"Unable to parse the filename " + name + " into a valid show", logger.DEBUG)
|
||||
logger.log(u'Unable to parse the filename ' + name + ' into a valid show', logger.DEBUG)
|
||||
return None
|
||||
|
||||
if not parse_result or not parse_result.series_name:
|
||||
|
@ -254,7 +257,7 @@ class TVCache():
|
|||
|
||||
if season and episodes:
|
||||
# store episodes as a seperated string
|
||||
episodeText = "|" + "|".join(map(str, episodes)) + "|"
|
||||
episodeText = '|' + '|'.join(map(str, episodes)) + '|'
|
||||
|
||||
# get the current timestamp
|
||||
curTimestamp = int(time.mktime(datetime.datetime.today().timetuple()))
|
||||
|
@ -271,10 +274,10 @@ class TVCache():
|
|||
# get version
|
||||
version = parse_result.version
|
||||
|
||||
logger.log(u"Added RSS item: [" + name + "] to cache: [" + self.providerID + "]", logger.DEBUG)
|
||||
logger.log(u'Added RSS item: [' + name + '] to cache: [' + self.providerID + ']', logger.DEBUG)
|
||||
|
||||
return [
|
||||
"INSERT OR IGNORE INTO [" + self.providerID + "] (name, season, episodes, indexerid, url, time, quality, release_group, version) VALUES (?,?,?,?,?,?,?,?,?)",
|
||||
'INSERT OR IGNORE INTO [' + self.providerID + '] (name, season, episodes, indexerid, url, time, quality, release_group, version) VALUES (?,?,?,?,?,?,?,?,?)',
|
||||
[name, season, episodeText, parse_result.show.indexerid, url, curTimestamp, quality, release_group, version]]
|
||||
|
||||
|
||||
|
@ -285,12 +288,12 @@ class TVCache():
|
|||
else:
|
||||
return []
|
||||
|
||||
def listPropers(self, date=None, delimiter="."):
|
||||
def listPropers(self, date=None, delimiter='.'):
|
||||
myDB = self._getDB()
|
||||
sql = "SELECT * FROM [" + self.providerID + "] WHERE name LIKE '%.PROPER.%' OR name LIKE '%.REPACK.%'"
|
||||
|
||||
if date != None:
|
||||
sql += " AND time >= " + str(int(time.mktime(date.timetuple())))
|
||||
sql += ' AND time >= ' + str(int(time.mktime(date.timetuple())))
|
||||
|
||||
return filter(lambda x: x['indexerid'] != 0, myDB.select(sql))
|
||||
|
||||
|
@ -302,14 +305,14 @@ class TVCache():
|
|||
myDB = self._getDB()
|
||||
if type(episode) != list:
|
||||
sqlResults = myDB.select(
|
||||
"SELECT * FROM [" + self.providerID + "] WHERE indexerid = ? AND season = ? AND episodes LIKE ?",
|
||||
[episode.show.indexerid, episode.season, "%|" + str(episode.episode) + "|%"])
|
||||
'SELECT * FROM [' + self.providerID + '] WHERE indexerid = ? AND season = ? AND episodes LIKE ?',
|
||||
[episode.show.indexerid, episode.season, '%|' + str(episode.episode) + '|%'])
|
||||
else:
|
||||
for epObj in episode:
|
||||
cl.append([
|
||||
"SELECT * FROM [" + self.providerID + "] WHERE indexerid = ? AND season = ? AND episodes LIKE ? "
|
||||
"AND quality IN (" + ",".join([str(x) for x in epObj.wantedQuality]) + ")",
|
||||
[epObj.show.indexerid, epObj.season, "%|" + str(epObj.episode) + "|%"]])
|
||||
'SELECT * FROM [' + self.providerID + '] WHERE indexerid = ? AND season = ? AND episodes LIKE ? '
|
||||
'AND quality IN (' + ','.join([str(x) for x in epObj.wantedQuality]) + ')',
|
||||
[epObj.show.indexerid, epObj.season, '%|' + str(epObj.episode) + '|%']])
|
||||
|
||||
sqlResults = myDB.mass_action(cl, fetchall=True)
|
||||
sqlResults = list(itertools.chain(*sqlResults))
|
||||
|
@ -318,45 +321,45 @@ class TVCache():
|
|||
for curResult in sqlResults:
|
||||
|
||||
# skip non-tv crap
|
||||
if not show_name_helpers.filterBadReleases(curResult["name"], parse=False):
|
||||
if not show_name_helpers.filterBadReleases(curResult['name'], parse=False):
|
||||
continue
|
||||
|
||||
# get the show object, or if it's not one of our shows then ignore it
|
||||
showObj = helpers.findCertainShow(sickbeard.showList, int(curResult["indexerid"]))
|
||||
showObj = helpers.findCertainShow(sickbeard.showList, int(curResult['indexerid']))
|
||||
if not showObj:
|
||||
continue
|
||||
|
||||
# skip if provider is anime only and show is not anime
|
||||
if self.provider.anime_only and not showObj.is_anime:
|
||||
logger.log(u"" + str(showObj.name) + " is not an anime, skiping", logger.DEBUG)
|
||||
logger.log(u'' + str(showObj.name) + ' is not an anime, skiping', logger.DEBUG)
|
||||
continue
|
||||
|
||||
# get season and ep data (ignoring multi-eps for now)
|
||||
curSeason = int(curResult["season"])
|
||||
curSeason = int(curResult['season'])
|
||||
if curSeason == -1:
|
||||
continue
|
||||
curEp = curResult["episodes"].split("|")[1]
|
||||
curEp = curResult['episodes'].split('|')[1]
|
||||
if not curEp:
|
||||
continue
|
||||
curEp = int(curEp)
|
||||
|
||||
curQuality = int(curResult["quality"])
|
||||
curReleaseGroup = curResult["release_group"]
|
||||
curVersion = curResult["version"]
|
||||
curQuality = int(curResult['quality'])
|
||||
curReleaseGroup = curResult['release_group']
|
||||
curVersion = curResult['version']
|
||||
|
||||
# if the show says we want that episode then add it to the list
|
||||
if not showObj.wantEpisode(curSeason, curEp, curQuality, manualSearch):
|
||||
logger.log(u"Skipping " + curResult["name"] + " because we don't want an episode that's " +
|
||||
logger.log(u'Skipping ' + curResult['name'] + ' because we don\'t want an episode that\'s ' +
|
||||
Quality.qualityStrings[curQuality], logger.DEBUG)
|
||||
continue
|
||||
|
||||
epObj = showObj.getEpisode(curSeason, curEp)
|
||||
|
||||
# build a result object
|
||||
title = curResult["name"]
|
||||
url = curResult["url"]
|
||||
title = curResult['name']
|
||||
url = curResult['url']
|
||||
|
||||
logger.log(u"Found result " + title + " at " + url)
|
||||
logger.log(u'Found result ' + title + ' at ' + url)
|
||||
|
||||
result = self.provider.getResult([epObj])
|
||||
result.show = showObj
|
||||
|
|
|
@ -61,6 +61,7 @@ from sickbeard.scene_numbering import get_scene_numbering, set_scene_numbering,
|
|||
from sickbeard.blackandwhitelist import BlackAndWhiteList
|
||||
|
||||
from browser import WebFileBrowser
|
||||
from mimetypes import MimeTypes
|
||||
|
||||
from lib.dateutil import tz
|
||||
from lib.unrar2 import RarFile
|
||||
|
@ -234,7 +235,9 @@ class MainHandler(RequestHandler):
|
|||
func = getattr(klass, 'index', None)
|
||||
|
||||
if callable(func):
|
||||
return func(**args)
|
||||
out = func(**args)
|
||||
self._headers = klass._headers
|
||||
return out
|
||||
|
||||
raise HTTPError(404)
|
||||
|
||||
|
@ -264,7 +267,7 @@ class MainHandler(RequestHandler):
|
|||
else:
|
||||
default_image_name = 'banner.png'
|
||||
|
||||
default_image_path = ek.ek(os.path.join, sickbeard.PROG_DIR, 'gui', 'slick', 'images', default_image_name)
|
||||
image_path = ek.ek(os.path.join, sickbeard.PROG_DIR, 'gui', 'slick', 'images', default_image_name)
|
||||
if show and sickbeard.helpers.findCertainShow(sickbeard.showList, int(show)):
|
||||
cache_obj = image_cache.ImageCache()
|
||||
|
||||
|
@ -279,10 +282,11 @@ class MainHandler(RequestHandler):
|
|||
image_file_name = cache_obj.banner_thumb_path(show)
|
||||
|
||||
if ek.ek(os.path.isfile, image_file_name):
|
||||
with file(image_file_name, 'rb') as img:
|
||||
return img.read()
|
||||
image_path = image_file_name
|
||||
|
||||
with file(default_image_path, 'rb') as img:
|
||||
mime_type, encoding = MimeTypes().guess_type(image_path)
|
||||
self.set_header('Content-Type', mime_type)
|
||||
with file(image_path, 'rb') as img:
|
||||
return img.read()
|
||||
|
||||
def setHomeLayout(self, layout):
|
||||
|
@ -425,25 +429,6 @@ class MainHandler(RequestHandler):
|
|||
sql_results.sort(sorts[sickbeard.COMING_EPS_SORT])
|
||||
|
||||
t = PageTemplate(headers=self.request.headers, file="comingEpisodes.tmpl")
|
||||
# paused_item = { 'title': '', 'path': 'toggleComingEpsDisplayPaused' }
|
||||
# paused_item['title'] = 'Hide Paused' if sickbeard.COMING_EPS_DISPLAY_PAUSED else 'Show Paused'
|
||||
paused_item = {'title': 'View Paused:', 'path': {'': ''}}
|
||||
paused_item['path'] = {'Hide': 'toggleComingEpsDisplayPaused'} if sickbeard.COMING_EPS_DISPLAY_PAUSED else {
|
||||
'Show': 'toggleComingEpsDisplayPaused'}
|
||||
t.submenu = [
|
||||
{'title': 'Sort by:', 'path': {'Date': 'setComingEpsSort/?sort=date',
|
||||
'Show': 'setComingEpsSort/?sort=show',
|
||||
'Network': 'setComingEpsSort/?sort=network',
|
||||
}},
|
||||
|
||||
{'title': 'Layout:', 'path': {'Banner': 'setComingEpsLayout/?layout=banner',
|
||||
'Poster': 'setComingEpsLayout/?layout=poster',
|
||||
'List': 'setComingEpsLayout/?layout=list',
|
||||
'Calendar': 'setComingEpsLayout/?layout=calendar',
|
||||
}},
|
||||
paused_item,
|
||||
]
|
||||
|
||||
t.next_week = datetime.datetime.combine(next_week_dt, datetime.time(tzinfo=network_timezones.sb_timezone))
|
||||
t.today = datetime.datetime.now(network_timezones.sb_timezone)
|
||||
t.sql_results = sql_results
|
||||
|
@ -1467,7 +1452,6 @@ class History(MainHandler):
|
|||
|
||||
ConfigMenu = [
|
||||
{'title': 'General', 'path': 'config/general/'},
|
||||
{'title': 'Backup/Restore', 'path': 'config/backuprestore/'},
|
||||
{'title': 'Search Settings', 'path': 'config/search/'},
|
||||
{'title': 'Search Providers', 'path': 'config/providers/'},
|
||||
{'title': 'Subtitles Settings', 'path': 'config/subtitles/'},
|
||||
|
@ -1544,7 +1528,7 @@ class ConfigGeneral(MainHandler):
|
|||
update_shows_on_start=None, trash_remove_show=None, trash_rotate_logs=None, update_frequency=None, launch_browser=None, web_username=None,
|
||||
use_api=None, api_key=None, indexer_default=None, timezone_display=None, cpu_preset=None,
|
||||
web_password=None, version_notify=None, enable_https=None, https_cert=None, https_key=None,
|
||||
handle_reverse_proxy=None, sort_article=None, auto_update=None, notify_on_update=None,
|
||||
handle_reverse_proxy=None, home_search_focus=None, sort_article=None, auto_update=None, notify_on_update=None,
|
||||
proxy_setting=None, proxy_indexers=None, anon_redirect=None, git_path=None, git_remote=None, calendar_unprotected=None,
|
||||
fuzzy_dating=None, trim_zero=None, date_preset=None, date_preset_na=None, time_preset=None,
|
||||
indexer_timeout=None, rootDir=None, theme_name=None):
|
||||
|
@ -1563,6 +1547,7 @@ class ConfigGeneral(MainHandler):
|
|||
sickbeard.TRASH_ROTATE_LOGS = config.checkbox_to_value(trash_rotate_logs)
|
||||
config.change_UPDATE_FREQUENCY(update_frequency)
|
||||
sickbeard.LAUNCH_BROWSER = config.checkbox_to_value(launch_browser)
|
||||
sickbeard.HOME_SEARCH_FOCUS = config.checkbox_to_value(home_search_focus)
|
||||
sickbeard.SORT_ARTICLE = config.checkbox_to_value(sort_article)
|
||||
sickbeard.CPU_PRESET = cpu_preset
|
||||
sickbeard.ANON_REDIRECT = anon_redirect
|
||||
|
@ -1632,53 +1617,6 @@ class ConfigGeneral(MainHandler):
|
|||
redirect("/config/general/")
|
||||
|
||||
|
||||
class ConfigBackupRestore(MainHandler):
|
||||
def index(self, *args, **kwargs):
|
||||
t = PageTemplate(headers=self.request.headers, file="config_backuprestore.tmpl")
|
||||
t.submenu = ConfigMenu
|
||||
return _munge(t)
|
||||
|
||||
def backup(self, backupDir=None):
|
||||
|
||||
finalResult = ''
|
||||
|
||||
if backupDir:
|
||||
source = [os.path.join(sickbeard.DATA_DIR, 'sickbeard.db'), sickbeard.CONFIG_FILE]
|
||||
target = os.path.join(backupDir, 'SickGear-' + time.strftime('%Y%m%d%H%M%S') + '.zip')
|
||||
|
||||
if helpers.makeZip(source, target):
|
||||
finalResult += "Successful backup to " + target
|
||||
else:
|
||||
finalResult += "Backup FAILED"
|
||||
else:
|
||||
finalResult += "You need to choose a folder to save your backup to!"
|
||||
|
||||
finalResult += "<br />\n"
|
||||
|
||||
return finalResult
|
||||
|
||||
|
||||
def restore(self, backupFile=None):
|
||||
|
||||
finalResult = ''
|
||||
|
||||
if backupFile:
|
||||
source = backupFile
|
||||
target_dir = os.path.join(sickbeard.DATA_DIR, 'restore')
|
||||
|
||||
if helpers.extractZip(source, target_dir):
|
||||
finalResult += "Successfully extracted restore files to " + target_dir
|
||||
finalResult += "<br>Restart SickGear to complete the restore."
|
||||
else:
|
||||
finalResult += "Restore FAILED"
|
||||
else:
|
||||
finalResult += "You need to select a backup file to restore!"
|
||||
|
||||
finalResult += "<br />\n"
|
||||
|
||||
return finalResult
|
||||
|
||||
|
||||
class ConfigSearch(MainHandler):
|
||||
def index(self, *args, **kwargs):
|
||||
|
||||
|
@ -2701,7 +2639,6 @@ class Config(MainHandler):
|
|||
|
||||
# map class names to urls
|
||||
general = ConfigGeneral
|
||||
backuprestore = ConfigBackupRestore
|
||||
search = ConfigSearch
|
||||
providers = ConfigProviders
|
||||
subtitles = ConfigSubtitles
|
||||
|
@ -2873,7 +2810,7 @@ class NewHomeAddShows(MainHandler):
|
|||
|
||||
cur_dir = {
|
||||
'dir': cur_path,
|
||||
'display_dir': '<b>' + ek.ek(os.path.dirname, cur_path) + os.sep + '</b>' + ek.ek(
|
||||
'display_dir': '<span class="filepath">' + ek.ek(os.path.dirname, cur_path) + os.sep + '</span>' + ek.ek(
|
||||
os.path.basename,
|
||||
cur_path),
|
||||
}
|
||||
|
@ -2890,6 +2827,9 @@ class NewHomeAddShows(MainHandler):
|
|||
|
||||
indexer_id = show_name = indexer = None
|
||||
for cur_provider in sickbeard.metadata_provider_dict.values():
|
||||
if indexer_id and show_name:
|
||||
continue
|
||||
|
||||
(indexer_id, show_name, indexer) = cur_provider.retrieveShowMetadata(cur_path)
|
||||
|
||||
# default to TVDB if indexer was not detected
|
||||
|
@ -2917,6 +2857,10 @@ class NewHomeAddShows(MainHandler):
|
|||
Display the new show page which collects a tvdb id, folder, and extra options and
|
||||
posts them to addNewShow
|
||||
"""
|
||||
self.set_header('Cache-Control', 'no-cache, no-store, must-revalidate')
|
||||
self.set_header('Pragma', 'no-cache')
|
||||
self.set_header('Expires', '0')
|
||||
|
||||
t = PageTemplate(headers=self.request.headers, file="home_newShow.tmpl")
|
||||
t.submenu = HomeMenu()
|
||||
|
||||
|
@ -2962,6 +2906,10 @@ class NewHomeAddShows(MainHandler):
|
|||
Display the new show page which collects a tvdb id, folder, and extra options and
|
||||
posts them to addNewShow
|
||||
"""
|
||||
self.set_header('Cache-Control', 'no-cache, no-store, must-revalidate')
|
||||
self.set_header('Pragma', 'no-cache')
|
||||
self.set_header('Expires', '0')
|
||||
|
||||
t = PageTemplate(headers=self.request.headers, file="home_recommendedShows.tmpl")
|
||||
t.submenu = HomeMenu()
|
||||
|
||||
|
@ -2983,11 +2931,21 @@ class NewHomeAddShows(MainHandler):
|
|||
return
|
||||
|
||||
map(final_results.append,
|
||||
([int(show['tvdb_id'] or 0) if sickbeard.TRAKT_DEFAULT_INDEXER == 1 else int(show['tvdb_id'] or 0),
|
||||
show['url'], show['title'], show['overview'],
|
||||
datetime.date.fromtimestamp(int(show['first_aired']) / 1000.0).strftime('%Y%m%d')] for show in
|
||||
recommendedlist if not helpers.findCertainShow(sickbeard.showList, indexerid=int(show['tvdb_id']))))
|
||||
([show['url'],
|
||||
show['title'],
|
||||
show['overview'],
|
||||
sbdatetime.sbdatetime.sbfdate(datetime.date.fromtimestamp(int(show['first_aired']))),
|
||||
sickbeard.indexerApi(1).name,
|
||||
sickbeard.indexerApi(1).config['icon'],
|
||||
int(show['tvdb_id'] or 0),
|
||||
'%s%s' % (sickbeard.indexerApi(1).config['show_url'], int(show['tvdb_id'] or 0)),
|
||||
sickbeard.indexerApi(2).name,
|
||||
sickbeard.indexerApi(2).config['icon'],
|
||||
int(show['tvrage_id'] or 0),
|
||||
'%s%s' % (sickbeard.indexerApi(2).config['show_url'], int(show['tvrage_id'] or 0))
|
||||
] for show in recommendedlist if not helpers.findCertainShow(sickbeard.showList, indexerid=int(show['tvdb_id']))))
|
||||
|
||||
self.set_header('Content-Type', 'application/json')
|
||||
return json.dumps({'results': final_results})
|
||||
|
||||
def addRecommendedShow(self, whichSeries=None, indexerLang="en", rootDir=None, defaultStatus=None,
|
||||
|
@ -3771,10 +3729,17 @@ class Home(MainHandler):
|
|||
shows.append(show)
|
||||
t.sortedShowLists = [["Shows", sorted(shows, lambda x, y: cmp(titler(x.name), titler(y.name)))],
|
||||
["Anime", sorted(anime, lambda x, y: cmp(titler(x.name), titler(y.name)))]]
|
||||
|
||||
else:
|
||||
t.sortedShowLists = [
|
||||
["Shows", sorted(sickbeard.showList, lambda x, y: cmp(titler(x.name), titler(y.name)))]]
|
||||
|
||||
tvshows = []
|
||||
for tvshow_types in t.sortedShowLists:
|
||||
for tvshow in tvshow_types[1]:
|
||||
tvshows.append(tvshow.indexerid)
|
||||
t.tvshow_id_csv = ','.join(str(x) for x in tvshows)
|
||||
|
||||
t.bwl = None
|
||||
if showObj.is_anime:
|
||||
t.bwl = BlackAndWhiteList(showObj.indexerid)
|
||||
|
|
|
@ -136,6 +136,4 @@ class WebServer(threading.Thread):
|
|||
|
||||
def shutDown(self):
|
||||
self.alive = False
|
||||
if self.server:
|
||||
self.server.stop()
|
||||
self.io_loop.stop()
|
||||
self.io_loop.stop()
|
|
@ -29,7 +29,7 @@ class DBBasicTests(test.SickbeardTestDBCase):
|
|||
|
||||
def test_select(self):
|
||||
self.db.select("SELECT * FROM tv_episodes WHERE showid = ? AND location != ''", [0000])
|
||||
|
||||
self.db.close()
|
||||
|
||||
if __name__ == '__main__':
|
||||
print "=================="
|
||||
|
|
68
tests/migration_tests.py
Normal file
|
@ -0,0 +1,68 @@
|
|||
import sys
|
||||
import os.path
|
||||
import glob
|
||||
import unittest
|
||||
import test_lib as test
|
||||
import sickbeard
|
||||
from time import sleep
|
||||
from sickbeard import db
|
||||
|
||||
sys.path.append(os.path.abspath('..'))
|
||||
sys.path.append(os.path.abspath('../lib'))
|
||||
|
||||
sickbeard.SYS_ENCODING = 'UTF-8'
|
||||
|
||||
|
||||
class MigrationBasicTests(test.SickbeardTestDBCase):
|
||||
def setUp(self):
|
||||
pass
|
||||
|
||||
def tearDown(self):
|
||||
pass
|
||||
|
||||
def test_migrations(self):
|
||||
schema = {
|
||||
0: sickbeard.mainDB.InitialSchema,
|
||||
31: sickbeard.mainDB.AddAnimeTVShow,
|
||||
32: sickbeard.mainDB.AddAbsoluteNumbering,
|
||||
33: sickbeard.mainDB.AddSceneAbsoluteNumbering,
|
||||
34: sickbeard.mainDB.AddAnimeBlacklistWhitelist,
|
||||
35: sickbeard.mainDB.AddSceneAbsoluteNumbering2,
|
||||
36: sickbeard.mainDB.AddXemRefresh,
|
||||
37: sickbeard.mainDB.AddSceneToTvShows,
|
||||
38: sickbeard.mainDB.AddIndexerMapping,
|
||||
39: sickbeard.mainDB.AddVersionToTvEpisodes,
|
||||
41: AddDefaultEpStatusToTvShows,
|
||||
}
|
||||
|
||||
count = 1
|
||||
while count < len(schema.keys()):
|
||||
myDB = db.DBConnection()
|
||||
|
||||
for version in sorted(schema.keys())[:count]:
|
||||
update = schema[version](myDB)
|
||||
update.execute()
|
||||
sleep(0.1)
|
||||
|
||||
db.MigrationCode(myDB)
|
||||
myDB.close()
|
||||
for filename in glob.glob(os.path.join(test.TESTDIR, test.TESTDBNAME) +'*'):
|
||||
os.remove(filename)
|
||||
|
||||
sleep(0.1)
|
||||
count += 1
|
||||
|
||||
|
||||
class AddDefaultEpStatusToTvShows(db.SchemaUpgrade):
|
||||
def execute(self):
|
||||
self.addColumn("tv_shows", "default_ep_status", "TEXT", "")
|
||||
self.setDBVersion(41)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print "=================="
|
||||
print "STARTING - MIGRATION TESTS"
|
||||
print "=================="
|
||||
print "######################################################################"
|
||||
suite = unittest.TestLoader().loadTestsFromTestCase(MigrationBasicTests)
|
||||
unittest.TextTestRunner(verbosity=2).run(suite)
|
|
@ -20,11 +20,11 @@
|
|||
from __future__ import with_statement
|
||||
|
||||
import unittest
|
||||
|
||||
import sqlite3
|
||||
|
||||
import glob
|
||||
import sys
|
||||
import os.path
|
||||
|
||||
sys.path.append(os.path.abspath('..'))
|
||||
sys.path.append(os.path.abspath('../lib'))
|
||||
|
||||
|
@ -34,7 +34,7 @@ import shutil
|
|||
from sickbeard import encodingKludge as ek, providers, tvcache
|
||||
from sickbeard import db
|
||||
from sickbeard.databases import mainDB
|
||||
from sickbeard.databases import cache_db
|
||||
from sickbeard.databases import cache_db, failed_db
|
||||
|
||||
#=================
|
||||
# test globals
|
||||
|
@ -42,7 +42,7 @@ from sickbeard.databases import cache_db
|
|||
TESTDIR = os.path.abspath('.')
|
||||
TESTDBNAME = "sickbeard.db"
|
||||
TESTCACHEDBNAME = "cache.db"
|
||||
|
||||
TESTFAILEDDBNAME = "failed.db"
|
||||
|
||||
SHOWNAME = u"show name"
|
||||
SEASON = 4
|
||||
|
@ -102,6 +102,7 @@ createTestCacheFolder()
|
|||
#=================
|
||||
def _dummy_saveConfig():
|
||||
return True
|
||||
|
||||
# this overrides the sickbeard save_config which gets called during a db upgrade
|
||||
# this might be considered a hack
|
||||
mainDB.sickbeard.save_config = _dummy_saveConfig
|
||||
|
@ -165,7 +166,6 @@ class TestCacheDBConnection(TestDBConnection, object):
|
|||
sickbeard.db.DBConnection = TestDBConnection
|
||||
sickbeard.tvcache.CacheDBConnection = TestCacheDBConnection
|
||||
|
||||
|
||||
#=================
|
||||
# test functions
|
||||
#=================
|
||||
|
@ -173,24 +173,31 @@ def setUp_test_db():
|
|||
"""upgrades the db to the latest version
|
||||
"""
|
||||
# upgrading the db
|
||||
db.upgradeDatabase(db.DBConnection(), mainDB.InitialSchema)
|
||||
db.MigrationCode(db.DBConnection())
|
||||
|
||||
# fix up any db problems
|
||||
db.sanityCheckDatabase(db.DBConnection(), mainDB.MainSanityCheck)
|
||||
|
||||
#and for cache.b too
|
||||
# and for cachedb too
|
||||
db.upgradeDatabase(db.DBConnection("cache.db"), cache_db.InitialSchema)
|
||||
|
||||
# and for faileddb too
|
||||
db.upgradeDatabase(db.DBConnection("failed.db"), failed_db.InitialSchema)
|
||||
|
||||
|
||||
def tearDown_test_db():
|
||||
"""Deletes the test db
|
||||
although this seams not to work on my system it leaves me with an zero kb file
|
||||
"""
|
||||
# uncomment next line so leave the db intact between test and at the end
|
||||
return False
|
||||
if os.path.exists(os.path.join(TESTDIR, TESTDBNAME)):
|
||||
os.remove(os.path.join(TESTDIR, TESTDBNAME))
|
||||
#return False
|
||||
|
||||
for filename in glob.glob(os.path.join(TESTDIR, TESTDBNAME) + '*'):
|
||||
os.remove(filename)
|
||||
if os.path.exists(os.path.join(TESTDIR, TESTCACHEDBNAME)):
|
||||
os.remove(os.path.join(TESTDIR, TESTCACHEDBNAME))
|
||||
if os.path.exists(os.path.join(TESTDIR, TESTFAILEDDBNAME)):
|
||||
os.remove(os.path.join(TESTDIR, TESTFAILEDDBNAME))
|
||||
|
||||
|
||||
def setUp_test_episode_file():
|
||||
|
|
96
updater.py
|
@ -1,96 +0,0 @@
|
|||
import subprocess, os, time, sys, os.path, shutil, re
|
||||
|
||||
try:
|
||||
log_file = open('sb-update.log', 'w')
|
||||
except:
|
||||
print "Unable to open sb-update.log, not saving output"
|
||||
log_file = None
|
||||
|
||||
def log(string):
|
||||
if log_file:
|
||||
log_file.write(string+'\n')
|
||||
print string
|
||||
|
||||
def isProcRunning(pid):
|
||||
"""See if a pid is running or not"""
|
||||
|
||||
tasklist_cmd = 'tasklist /FI "PID eq '+str(pid)+'" /FO CSV'
|
||||
|
||||
p = subprocess.Popen(tasklist_cmd, stdout=subprocess.PIPE)
|
||||
out, err = p.communicate()
|
||||
|
||||
results = out.split('\r\n')
|
||||
|
||||
regex = '".*\\.exe","'+str(pid)+'",("[^"]*",?){3}'
|
||||
|
||||
for cur_line in results:
|
||||
if re.match(regex, cur_line, re.I):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
if len(sys.argv) < 3:
|
||||
log("Invalid call.")
|
||||
sys.exit()
|
||||
|
||||
try:
|
||||
|
||||
# this should be retrieved from sys.args
|
||||
pid = sys.argv[1]
|
||||
|
||||
# process to re-launch
|
||||
sb_executable = sys.argv[2:]
|
||||
|
||||
sb_closed = False
|
||||
|
||||
# try 15 times to make sure it's closed
|
||||
for i in range(15):
|
||||
isRunning = isProcRunning(pid)
|
||||
if isRunning:
|
||||
time.sleep(5)
|
||||
continue
|
||||
else:
|
||||
sb_closed = True
|
||||
break
|
||||
|
||||
if not sb_closed:
|
||||
log("SickGear didn't close, unable to update. You'll have to manually restart it.")
|
||||
sys.exit()
|
||||
|
||||
sb_root = os.path.dirname(sb_executable[0])
|
||||
sb_update_dir = os.path.join(sb_root, 'sb-update')
|
||||
|
||||
# do the update if applicable
|
||||
if os.path.isdir(sb_update_dir):
|
||||
# find update dir name
|
||||
update_dir_contents = os.listdir(sb_update_dir)
|
||||
if len(update_dir_contents) != 1:
|
||||
log("Invalid update data, update failed.")
|
||||
sys.exit()
|
||||
content_dir = os.path.join(sb_update_dir, update_dir_contents[0])
|
||||
|
||||
# copy everything from sb_update_dir to sb_root
|
||||
for dirname, dirnames, filenames in os.walk(content_dir):
|
||||
dirname = dirname[len(content_dir)+1:]
|
||||
for curfile in filenames:
|
||||
if curfile == 'updater.exe':
|
||||
continue
|
||||
old_path = os.path.join(content_dir, dirname, curfile)
|
||||
new_path = os.path.join(sb_root, dirname, curfile)
|
||||
|
||||
if os.path.isfile(new_path):
|
||||
os.remove(new_path)
|
||||
os.renames(old_path, new_path)
|
||||
|
||||
if os.path.isdir(sb_update_dir):
|
||||
shutil.rmtree(sb_update_dir)
|
||||
|
||||
# re-launch SB
|
||||
p = subprocess.Popen(sb_executable, cwd=os.getcwd())
|
||||
|
||||
except Exception, e:
|
||||
log("Exception while updating: "+str(e))
|
||||
raise
|
||||
|
||||
if log_file:
|
||||
log_file.close()
|