This commit is contained in:
Janez Troha
2012-07-01 01:57:47 +02:00
18 changed files with 219 additions and 139 deletions
+1 -2
View File
@@ -37,10 +37,9 @@ class Loader(object):
# Create data dir if needed # Create data dir if needed
if self.options.data_dir: if self.options.data_dir:
self.data_dir = self.options.data_dir self.data_dir = self.options.data_dir
else: else:
self.data_dir = os.path.expanduser(Env.setting('data_dir')) self.data_dir = os.path.expanduser(Env.setting('data_dir'))
if self.data_dir == '': if self.data_dir == '':
self.data_dir = getDataDir() self.data_dir = getDataDir()
+11 -1
View File
@@ -18,7 +18,10 @@ log = CPLog(__name__)
class Core(Plugin): class Core(Plugin):
ignore_restart = ['Core.restart', 'Core.shutdown', 'Updater.check'] ignore_restart = [
'Core.restart', 'Core.shutdown',
'Updater.check', 'Updater.autoUpdate',
]
shutdown_started = False shutdown_started = False
def __init__(self): def __init__(self):
@@ -43,6 +46,7 @@ class Core(Plugin):
addEvent('app.base_url', self.createBaseUrl) addEvent('app.base_url', self.createBaseUrl)
addEvent('app.api_url', self.createApiUrl) addEvent('app.api_url', self.createApiUrl)
addEvent('app.version', self.version) addEvent('app.version', self.version)
addEvent('app.load', self.checkDataDir)
addEvent('setting.save.core.password', self.md5Password) addEvent('setting.save.core.password', self.md5Password)
addEvent('setting.save.core.api_key', self.checkApikey) addEvent('setting.save.core.api_key', self.checkApikey)
@@ -54,6 +58,12 @@ class Core(Plugin):
def checkApikey(self, value): def checkApikey(self, value):
return value if value and len(value) > 3 else uuid4().hex return value if value and len(value) > 3 else uuid4().hex
def checkDataDir(self):
if Env.get('app_dir') in Env.get('data_dir'):
log.error('You should NOT use your CouchPotato directory to save your settings in. Files will get overwritten or be deleted.')
return True
def available(self): def available(self):
return jsonified({ return jsonified({
'succes': True 'succes': True
+15 -2
View File
@@ -20,6 +20,8 @@ log = CPLog(__name__)
class Updater(Plugin): class Updater(Plugin):
available_notified = False
def __init__(self): def __init__(self):
if Env.get('desktop'): if Env.get('desktop'):
@@ -64,13 +66,18 @@ class Updater(Plugin):
fireEventAsync('app.restart') fireEventAsync('app.restart')
return True
return False
def check(self): def check(self):
if self.isDisabled(): if self.isDisabled():
return return
if self.updater.check(): if self.updater.check():
if self.conf('notification') and not self.conf('automatic'): if not self.available_notified and self.conf('notification') and not self.conf('automatic'):
fireEvent('updater.available', message = 'A new update is available', data = self.updater.info()) fireEvent('updater.available', message = 'A new update is available', data = self.updater.info())
self.available_notified = True
return True return True
return False return False
@@ -168,7 +175,6 @@ class GitUpdater(BaseUpdater):
self.repo.saveStash() self.repo.saveStash()
log.info('Updating to latest version') log.info('Updating to latest version')
info = self.info()
self.repo.pull() self.repo.pull()
# Delete leftover .pyc files # Delete leftover .pyc files
@@ -302,6 +308,13 @@ class SourceUpdater(BaseUpdater):
except Exception, e: except Exception, e:
log.error('Failed overwriting file: %s', e) log.error('Failed overwriting file: %s', e)
if Env.get('app_dir') not in Env.get('data_dir'):
for still_exists in existing_files:
try:
os.remove(still_exists)
except:
log.error('Failed removing non-used file: %s', traceback.format_exc())
def removeDir(self, path): def removeDir(self, path):
try: try:
@@ -22,8 +22,10 @@ var UpdaterBase = new Class({
if(json.update_available) if(json.update_available)
self.doUpdate(); self.doUpdate();
else else {
App.unBlockPage() App.unBlockPage();
App.fireEvent('message', 'No updates available');
}
} }
}) })
+5 -4
View File
@@ -136,23 +136,24 @@ class CoreNotifier(Notification):
#db.close() #db.close()
return True return True
def frontend(self, type = 'notification', data = {}): def frontend(self, type = 'notification', data = {}, message = None):
self.m_lock.acquire() self.m_lock.acquire()
message = { notification = {
'message_id': str(uuid.uuid4()), 'message_id': str(uuid.uuid4()),
'time': time.time(), 'time': time.time(),
'type': type, 'type': type,
'data': data, 'data': data,
'message': message,
} }
self.messages.append(message) self.messages.append(notification)
while len(self.listeners) > 0 and not self.shuttingDown(): while len(self.listeners) > 0 and not self.shuttingDown():
try: try:
listener, last_id = self.listeners.pop() listener, last_id = self.listeners.pop()
listener({ listener({
'success': True, 'success': True,
'result': [message], 'result': [notification],
}) })
except: except:
break break
@@ -11,6 +11,7 @@ var NotificationBase = new Class({
App.addEvent('unload', self.stopPoll.bind(self)); App.addEvent('unload', self.stopPoll.bind(self));
App.addEvent('reload', self.startInterval.bind(self, [true])); App.addEvent('reload', self.startInterval.bind(self, [true]));
App.addEvent('notification', self.notify.bind(self)); App.addEvent('notification', self.notify.bind(self));
App.addEvent('message', self.showMessage.bind(self));
// Add test buttons to settings page // Add test buttons to settings page
App.addEvent('load', self.addTestButtons.bind(self)); App.addEvent('load', self.addTestButtons.bind(self));
@@ -86,7 +87,7 @@ var NotificationBase = new Class({
startInterval: function(force){ startInterval: function(force){
var self = this; var self = this;
if(self.stopped && !force){ if(self.stopped && !force){
self.stopped = false; self.stopped = false;
return; return;
@@ -126,11 +127,12 @@ var NotificationBase = new Class({
processData: function(json){ processData: function(json){
var self = this; var self = this;
// Process data // Process data
if(json){ if(json){
Array.each(json.result, function(result){ Array.each(json.result, function(result){
App.fireEvent(result.type, result) App.fireEvent(result.type, result);
if(result.message && result.read === undefined)
self.showMessage(result.message);
}) })
if(json.result.length > 0) if(json.result.length > 0)
@@ -141,6 +143,30 @@ var NotificationBase = new Class({
self.startPoll() self.startPoll()
}, },
showMessage: function(message){
var self = this;
if(!self.message_container)
self.message_container = new Element('div.messages').inject(document.body);
var new_message = new Element('div.message', {
'text': message
}).inject(self.message_container);
setTimeout(function(){
new_message.addClass('show')
}, 10);
setTimeout(function(){
new_message.addClass('hide')
setTimeout(function(){
new_message.destroy();
}, 1000);
}, 4000);
},
// Notification setting tests
addTestButtons: function(){ addTestButtons: function(){
var self = this; var self = this;
+7 -4
View File
@@ -46,10 +46,13 @@ class Plex(Notification):
def notify(self, message = '', data = {}, listener = None): def notify(self, message = '', data = {}, listener = None):
if self.isDisabled(): return if self.isDisabled(): return
for host in [x.strip() + ':3000' for x in self.conf('host').split(",")]: hosts = [x.strip() + ':3000' for x in self.conf('host').split(",")]
self.send({'command': 'ExecBuiltIn', 'parameter': 'Notification(CouchPotato, %s)' % message}, host) successful = 0
for host in hosts:
if self.send({'command': 'ExecBuiltIn', 'parameter': 'Notification(CouchPotato, %s)' % message}, host):
successful += 1
return True return successful == len(hosts)
def send(self, command, host): def send(self, command, host):
@@ -60,7 +63,7 @@ class Plex(Notification):
try: try:
self.urlopen(url, headers = headers, show_error = False) self.urlopen(url, headers = headers, show_error = False)
except: except:
log.error("Couldn't sent command to Plex") log.error("Couldn't sent command to Plex: %s", traceback.format_exc())
return False return False
log.info('Plex notification to %s successful.', host) log.info('Plex notification to %s successful.', host)
+10 -9
View File
@@ -78,15 +78,16 @@ Page.Log = new Class({
addColors: function(text){ addColors: function(text){
var self = this; var self = this;
var text = new Element('div', { text = text
'html': text .replace(/&/g, '&')
}).get('text') .replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
text = text.replace(/\u001b\[31m/gi, '</span><span class="error">') .replace(/"/g, '&quot;')
text = text.replace(/\u001b\[36m/gi, '</span><span class="debug">') .replace(/\u001b\[31m/gi, '</span><span class="error">')
text = text.replace(/\u001b\[33m/gi, '</span><span class="debug">') .replace(/\u001b\[36m/gi, '</span><span class="debug">')
text = text.replace(/\u001b\[0m\n/gi, '</span><span class="time">') .replace(/\u001b\[33m/gi, '</span><span class="debug">')
text = text.replace(/\u001b\[0m/gi, '</span><span>') .replace(/\u001b\[0m\n/gi, '</span><span class="time">')
.replace(/\u001b\[0m/gi, '</span><span>')
return '<span class="time">' + text + '</span>'; return '<span class="time">' + text + '</span>';
} }
+2 -2
View File
@@ -240,7 +240,6 @@ class MoviePlugin(Plugin):
db = get_session() db = get_session()
for id in getParam('id').split(','): for id in getParam('id').split(','):
fireEvent('notify.frontend', type = 'movie.busy.%s' % id, data = True)
movie = db.query(Movie).filter_by(id = id).first() movie = db.query(Movie).filter_by(id = id).first()
if movie: if movie:
@@ -250,6 +249,7 @@ class MoviePlugin(Plugin):
for title in movie.library.titles: for title in movie.library.titles:
if title.default: default_title = title.title if title.default: default_title = title.title
fireEvent('notify.frontend', type = 'movie.busy.%s' % id, data = True, message = 'Updating "%s"' % default_title)
fireEventAsync('library.update', identifier = movie.library.identifier, default_title = default_title, force = True, on_complete = self.createOnComplete(id)) fireEventAsync('library.update', identifier = movie.library.identifier, default_title = default_title, force = True, on_complete = self.createOnComplete(id))
@@ -342,7 +342,7 @@ class MoviePlugin(Plugin):
onComplete() onComplete()
if added: if added:
fireEvent('notify.frontend', type = 'movie.added', data = movie_dict) fireEvent('notify.frontend', type = 'movie.added', data = movie_dict, message = 'Successfully added "%s" to your wanted list.' % params.get('title', ''))
#db.close() #db.close()
return movie_dict return movie_dict
@@ -17,10 +17,13 @@ var Movie = new Class({
self.parent(self, options); self.parent(self, options);
App.addEvent('movie.update.'+data.id, self.update.bind(self)); App.addEvent('movie.update.'+data.id, self.update.bind(self));
App.addEvent('movie.busy.'+data.id, function(notification){
if(notification.data) ['movie.busy', 'searcher.started'].each(function(listener){
self.busy(true) App.addEvent(listener+'.'+data.id, function(notification){
}); if(notification.data)
self.busy(true)
});
})
}, },
busy: function(set_busy){ busy: function(set_busy){
+1 -1
View File
@@ -84,7 +84,7 @@ class Searcher(Plugin):
if not default_title: if not default_title:
return return
fireEvent('notify.frontend', type = 'searcher.started.%s' % movie['id'], data = True) fireEvent('notify.frontend', type = 'searcher.started.%s' % movie['id'], data = True, message = 'Searching for "%s"' % default_title)
ret = False ret = False
for quality_type in movie['profile']['types']: for quality_type in movie['profile']['types']:
@@ -89,7 +89,7 @@ class IMDBAPI(MovieProvider):
'poster': [movie.get('Poster', '')] if movie.get('Poster') and len(movie.get('Poster', '')) > 4 else [], 'poster': [movie.get('Poster', '')] if movie.get('Poster') and len(movie.get('Poster', '')) > 4 else [],
}, },
'rating': { 'rating': {
'imdb': (tryFloat(movie.get('imdbRating', 0)), tryInt(movie.get('imdbVotes', ''))), 'imdb': (tryFloat(movie.get('imdbRating', 0)), tryInt(movie.get('imdbVotes', '').replace(',', ''))),
#'rotten': (tryFloat(movie.get('tomatoRating', 0)), tryInt(movie.get('tomatoReviews', 0))), #'rotten': (tryFloat(movie.get('tomatoRating', 0)), tryInt(movie.get('tomatoReviews', 0))),
}, },
'imdb': str(movie.get('imdbID', '')), 'imdb': str(movie.get('imdbID', '')),
+13 -6
View File
@@ -20,14 +20,12 @@ import warnings
def getOptions(base_path, args): def getOptions(base_path, args):
data_dir = getDataDir()
# Options # Options
parser = ArgumentParser(prog = 'CouchPotato.py') parser = ArgumentParser(prog = 'CouchPotato.py')
parser.add_argument('--config_file', default = os.path.join(data_dir, 'settings.conf'), parser.add_argument('--data_dir',
dest = 'config_file', help = 'Absolute or ~/ path of the settings file (default ./_data/settings.conf)')
parser.add_argument('--data_dir', default = data_dir,
dest = 'data_dir', help = 'Absolute or ~/ path of the data dir') dest = 'data_dir', help = 'Absolute or ~/ path of the data dir')
parser.add_argument('--config_file',
dest = 'config_file', help = 'Absolute or ~/ path of the settings file (default DATA_DIR/settings.conf)')
parser.add_argument('--debug', action = 'store_true', parser.add_argument('--debug', action = 'store_true',
dest = 'debug', help = 'Debug mode') dest = 'debug', help = 'Debug mode')
parser.add_argument('--console_log', action = 'store_true', parser.add_argument('--console_log', action = 'store_true',
@@ -36,12 +34,21 @@ def getOptions(base_path, args):
dest = 'quiet', help = 'No console logging') dest = 'quiet', help = 'No console logging')
parser.add_argument('--daemon', action = 'store_true', parser.add_argument('--daemon', action = 'store_true',
dest = 'daemon', help = 'Daemonize the app') dest = 'daemon', help = 'Daemonize the app')
parser.add_argument('--pid_file', default = os.path.join(data_dir, 'couchpotato.pid'), parser.add_argument('--pid_file',
dest = 'pid_file', help = 'Path to pidfile needed for daemon') dest = 'pid_file', help = 'Path to pidfile needed for daemon')
options = parser.parse_args(args) options = parser.parse_args(args)
data_dir = os.path.expanduser(options.data_dir if options.data_dir else getDataDir())
if not options.config_file:
options.config_file = os.path.join(data_dir, 'settings.conf')
if not options.pid_file:
options.pid_file = os.path.join(data_dir, 'couchpotato.pid')
options.config_file = os.path.expanduser(options.config_file) options.config_file = os.path.expanduser(options.config_file)
options.pid_file = os.path.expanduser(options.pid_file)
return options return options
+1 -1
View File
@@ -80,7 +80,7 @@ var CouchPotato = new Class({
} }
}), }),
new Element('a', { new Element('a', {
'text': 'Check for updates', 'text': 'Update to latest',
'events': { 'events': {
'click': self.checkForUpdate.bind(self, null) 'click': self.checkForUpdate.bind(self, null)
} }
@@ -1,5 +1,5 @@
/** /**
* StyleFix 1.0.2 * StyleFix 1.0.3
* @author Lea Verou * @author Lea Verou
* MIT license * MIT license
*/ */
@@ -52,8 +52,10 @@ var self = window.StyleFix = {
}); });
// behavior URLs shoudn’t be converted (Issue #19) // behavior URLs shoudn’t be converted (Issue #19)
css = css.replace(RegExp('\\b(behavior:\\s*?url\\(\'?"?)' + base, 'gi'), '$1'); // base should be escaped before added to RegExp (Issue #81)
} var escaped_base = base.replace(/([\\\^\$*+[\]?{}.=!:(|)])/g,"\\$1");
css = css.replace(RegExp('\\b(behavior:\\s*?url\\(\'?"?)' + escaped_base, 'gi'), '$1');
}
var style = document.createElement('style'); var style = document.createElement('style');
style.textContent = css; style.textContent = css;
@@ -63,6 +65,8 @@ var self = window.StyleFix = {
parent.insertBefore(style, link); parent.insertBefore(style, link);
parent.removeChild(link); parent.removeChild(link);
style.media = link.media; // Duplicate is intentional. See issue #31
} }
}; };
@@ -84,6 +88,9 @@ var self = window.StyleFix = {
}, },
styleElement: function(style) { styleElement: function(style) {
if (style.hasAttribute('data-noprefix')) {
return;
}
var disabled = style.disabled; var disabled = style.disabled;
style.textContent = self.fix(style.textContent, true, style); style.textContent = self.fix(style.textContent, true, style);
@@ -150,7 +157,7 @@ function $(expr, con) {
})(); })();
/** /**
* PrefixFree 1.0.5 * PrefixFree 1.0.6
* @author Lea Verou * @author Lea Verou
* MIT license * MIT license
*/ */
@@ -160,36 +167,39 @@ if(!window.StyleFix || !window.getComputedStyle) {
return; return;
} }
// Private helper
function fix(what, before, after, replacement, css) {
what = self[what];
if(what.length) {
var regex = RegExp(before + '(' + what.join('|') + ')' + after, 'gi');
css = css.replace(regex, replacement);
}
return css;
}
var self = window.PrefixFree = { var self = window.PrefixFree = {
prefixCSS: function(css, raw) { prefixCSS: function(css, raw) {
var prefix = self.prefix; var prefix = self.prefix;
function fix(what, before, after, replacement) { css = fix('functions', '(\\s|:|,)', '\\s*\\(', '$1' + prefix + '$2(', css);
what = self[what]; css = fix('keywords', '(\\s|:)', '(\\s|;|\\}|$)', '$1' + prefix + '$2$3', css);
css = fix('properties', '(^|\\{|\\s|;)', '\\s*:', '$1' + prefix + '$2:', css);
if(what.length) {
var regex = RegExp(before + '(' + what.join('|') + ')' + after, 'gi');
css = css.replace(regex, replacement);
}
}
fix('functions', '(\\s|:|,)', '\\s*\\(', '$1' + prefix + '$2(');
fix('keywords', '(\\s|:)', '(\\s|;|\\}|$)', '$1' + prefix + '$2$3');
fix('properties', '(^|\\{|\\s|;)', '\\s*:', '$1' + prefix + '$2:');
// Prefix properties *inside* values (issue #8) // Prefix properties *inside* values (issue #8)
if (self.properties.length) { if (self.properties.length) {
var regex = RegExp('\\b(' + self.properties.join('|') + ')(?!:)', 'gi'); var regex = RegExp('\\b(' + self.properties.join('|') + ')(?!:)', 'gi');
fix('valueProperties', '\\b', ':(.+?);', function($0) { css = fix('valueProperties', '\\b', ':(.+?);', function($0) {
return $0.replace(regex, prefix + "$1") return $0.replace(regex, prefix + "$1")
}); }, css);
} }
if(raw) { if(raw) {
fix('selectors', '', '\\b', self.prefixSelector); css = fix('selectors', '', '\\b', self.prefixSelector, css);
fix('atrules', '@', '\\b', '@' + prefix + '$1'); css = fix('atrules', '@', '\\b', '@' + prefix + '$1', css);
} }
// Fix double prefixing // Fix double prefixing
@@ -198,11 +208,25 @@ var self = window.PrefixFree = {
return css; return css;
}, },
// Warning: prefixXXX functions prefix no matter what, even if the XXX is supported prefix-less property: function(property) {
return (self.properties.indexOf(property)? self.prefix : '') + property;
},
value: function(value, property) {
value = fix('functions', '(^|\\s|,)', '\\s*\\(', '$1' + self.prefix + '$2(', value);
value = fix('keywords', '(^|\\s)', '(\\s|$)', '$1' + self.prefix + '$2$3', value);
// TODO properties inside values
return value;
},
// Warning: Prefixes no matter what, even if the selector is supported prefix-less
prefixSelector: function(selector) { prefixSelector: function(selector) {
return selector.replace(/^:{1,2}/, function($0) { return $0 + self.prefix }) return selector.replace(/^:{1,2}/, function($0) { return $0 + self.prefix })
}, },
// Warning: Prefixes no matter what, even if the property is supported prefix-less
prefixProperty: function(property, camelCase) { prefixProperty: function(property, camelCase) {
var prefixed = self.prefix + property; var prefixed = self.prefix + property;
@@ -334,7 +358,9 @@ var keywords = {
'zoom-out': 'cursor', 'zoom-out': 'cursor',
'box': 'display', 'box': 'display',
'flexbox': 'display', 'flexbox': 'display',
'inline-flexbox': 'display' 'inline-flexbox': 'display',
'flex': 'display',
'inline-flex': 'display'
}; };
self.functions = []; self.functions = [];
+54 -34
View File
@@ -21,9 +21,9 @@ body {
} }
* { * {
-moz-box-sizing: border-box; -webkit-box-sizing: border-box;
-webkit-box-sizing: border-box; -moz-box-sizing: border-box;
box-sizing: border-box; box-sizing: border-box;
} }
pre { pre {
@@ -267,10 +267,9 @@ body > .spinner, .mask{
font-size: 8px; font-size: 8px;
margin: -5px 0 0 15px; margin: -5px 0 0 15px;
box-shadow: inset 0 1px 0 rgba(255,255,255,.6), 0 0 3px rgba(0,0,0,.7); box-shadow: inset 0 1px 0 rgba(255,255,255,.6), 0 0 3px rgba(0,0,0,.7);
background: -webkit-gradient(linear, left bottom, left top, from(rgba(255,255,255,.3)), to(rgba(255,255,255,.1)));
background: -moz-linear-gradient(center bottom, rgba(255,255,255,.3) 0%, rgba(255,255,255,.1) 100%);
background-color: #1b79b8; background-color: #1b79b8;
text-shadow: none; text-shadow: none;
background-image: linear-gradient(0deg, rgba(255,255,255,.3) 0%, rgba(255,255,255,.1) 100%);
} }
.header .notification_menu .wrapper { .header .notification_menu .wrapper {
@@ -354,16 +353,8 @@ body > .spinner, .mask{
border-radius:30px; border-radius:30px;
box-shadow: 0 1px 1px rgba(0,0,0,0.35), inset 0 1px 0px rgba(255,255,255,0.20); box-shadow: 0 1px 1px rgba(0,0,0,0.35), inset 0 1px 0px rgba(255,255,255,0.20);
background: url('../images/sprite.png') no-repeat 94% -53px, linear-gradient(
background: url('../images/sprite.png') no-repeat 94% -53px, -webkit-gradient( 270deg,
linear,
left bottom,
left top,
color-stop(0, #406db8),
color-stop(1, #5b9bd1)
);
background: url('../images/sprite.png') no-repeat 94% -53px, -moz-linear-gradient(
center top,
#5b9bd1 0%, #5b9bd1 0%,
#406db8 100% #406db8 100%
); );
@@ -448,15 +439,8 @@ body > .spinner, .mask{
border: 1px solid #252930; border: 1px solid #252930;
box-shadow: inset 0 1px 0px rgba(255,255,255,0.20), 0 0 3px rgba(0,0,0, 0.2); box-shadow: inset 0 1px 0px rgba(255,255,255,0.20), 0 0 3px rgba(0,0,0, 0.2);
background: rgb(55,62,74); background: rgb(55,62,74);
background-image: -webkit-gradient( background-image: linear-gradient(
linear, 90deg,
left bottom,
left top,
color-stop(0, rgb(55,62,74)),
color-stop(1, rgb(73,83,98))
);
background-image: -moz-linear-gradient(
center bottom,
rgb(55,62,74) 0%, rgb(55,62,74) 0%,
rgb(73,83,98) 100% rgb(73,83,98) 100%
); );
@@ -544,15 +528,8 @@ body > .spinner, .mask{
text-align: center; text-align: center;
color: #000; color: #000;
text-shadow: none; text-shadow: none;
background-image: -webkit-gradient( background-image: linear-gradient(
linear, 45deg,
left bottom,
right top,
color-stop(0, rgb(200,200,200)),
color-stop(1, rgb(255,255,255))
);
background-image: -moz-linear-gradient(
left bottom,
rgb(200,200,200) 0%, rgb(200,200,200) 0%,
rgb(255,255,255) 100% rgb(255,255,255) 100%
); );
@@ -601,4 +578,47 @@ body > .spinner, .mask{
} }
.more_menu .wrapper li a:hover { .more_menu .wrapper li a:hover {
background: rgba(0,0,0,0.05); background: rgba(0,0,0,0.05);
} }
.messages {
position: absolute;
right: 0;
bottom: 0;
padding: 2px;
width: 240px;
z-index: 2;
overflow: hidden;
font-size: 14px;
font-weight: bold;
}
.messages .message {
text-align: center;
border-radius: 2px;
margin: 2px 0 0 0;
height: 0;
overflow: hidden;
transition: all .6s cubic-bezier(0.9,0,0.1,1);
box-shadow: 0 1px 1px rgba(0,0,0,0.35), inset 0 1px 0px rgba(255,255,255,0.20);
background-image: linear-gradient(
270deg,
#5b9bd1 0%,
#406db8 100%
);
width: 100%;
padding: 0 5px;
visibility: hidden;
max-height: 0;
}
.messages .message.show {
visibility: visible;
height: auto;
padding-top: 3px;
padding-bottom: 3px;
min-height: 1px;
max-height: 400px;
}
.messages .message.hide {
margin-left: 240px;
opacity: 0;
}
+9 -38
View File
@@ -16,17 +16,9 @@
padding: 40px 0; padding: 40px 0;
margin: 0; margin: 0;
min-height: 470px; min-height: 470px;
background-image: linear-gradient(
background-image: -webkit-gradient( 20deg,
linear, rgba(0,0,0,0) 50%,
right top,
40% 4%,
color-stop(0, rgba(0,0,0, 0.3)),
color-stop(1, rgba(0,0,0, 0))
);
background-image: -moz-linear-gradient(
10% 0% 16deg,
rgba(0,0,0,0) 0%,
rgba(0,0,0,0.3) 100% rgba(0,0,0,0.3) 100%
); );
} }
@@ -364,30 +356,16 @@
border-radius: 2px; border-radius: 2px;
} }
.page .tag_input > ul:hover > li.choice { .page .tag_input > ul:hover > li.choice {
background: -webkit-gradient( background: linear-gradient(
linear, 270deg,
left bottom,
left top,
color-stop(0, rgba(255,255,255,0.1)),
color-stop(1, rgba(255,255,255,0.3))
);
background: -moz-linear-gradient(
center top,
rgba(255,255,255,0.3) 0%, rgba(255,255,255,0.3) 0%,
rgba(255,255,255,0.1) 100% rgba(255,255,255,0.1) 100%
); );
} }
.page .tag_input > ul > li.choice:hover, .page .tag_input > ul > li.choice:hover,
.page .tag_input > ul > li.choice.selected { .page .tag_input > ul > li.choice.selected {
background: -webkit-gradient( background: linear-gradient(
linear, 270deg,
left bottom,
left top,
color-stop(0, #406db8),
color-stop(1, #5b9bd1)
);
background: -moz-linear-gradient(
center top,
#5b9bd1 0%, #5b9bd1 0%,
#406db8 100% #406db8 100%
); );
@@ -425,15 +403,8 @@
margin: -9px 0 0 -16px; margin: -9px 0 0 -16px;
border-radius: 30px 30px 0 0; border-radius: 30px 30px 0 0;
cursor: pointer; cursor: pointer;
background: url('../../images/icon.delete.png') no-repeat center 2px, -webkit-gradient( background: url('../../images/icon.delete.png') no-repeat center 2px, -webkit-linear-gradient(
linear, 270deg,
left bottom,
left top,
color-stop(0, #5b9bd1),
color-stop(1, #5b9bd1)
);
background: url('../../images/icon.delete.png') no-repeat center 2px, -moz-linear-gradient(
center top,
#5b9bd1 0%, #5b9bd1 0%,
#5b9bd1 100% #5b9bd1 100%
); );
-2
View File
@@ -10,9 +10,7 @@
<script type="text/javascript" src="{{ url_for('web.static', filename='scripts/library/mootools.js') }}"></script> <script type="text/javascript" src="{{ url_for('web.static', filename='scripts/library/mootools.js') }}"></script>
<script type="text/javascript" src="{{ url_for('web.static', filename='scripts/library/mootools_more.js') }}"></script> <script type="text/javascript" src="{{ url_for('web.static', filename='scripts/library/mootools_more.js') }}"></script>
{% if not env.get('dev') %}
<script type="text/javascript" src="{{ url_for('web.static', filename='scripts/library/prefix_free.js') }}"></script> <script type="text/javascript" src="{{ url_for('web.static', filename='scripts/library/prefix_free.js') }}"></script>
{% endif %}
<script type="text/javascript" src="{{ url_for('web.static', filename='scripts/library/uniform.js') }}"></script> <script type="text/javascript" src="{{ url_for('web.static', filename='scripts/library/uniform.js') }}"></script>
<script type="text/javascript" src="{{ url_for('web.static', filename='scripts/library/form_replacement/form_check.js') }}"></script> <script type="text/javascript" src="{{ url_for('web.static', filename='scripts/library/form_replacement/form_check.js') }}"></script>
<script type="text/javascript" src="{{ url_for('web.static', filename='scripts/library/form_replacement/form_radio.js') }}"></script> <script type="text/javascript" src="{{ url_for('web.static', filename='scripts/library/form_replacement/form_radio.js') }}"></script>