Notification system
This commit is contained in:
@@ -5,6 +5,7 @@ from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.plugins.base import Plugin
|
||||
from couchpotato.environment import Env
|
||||
from git.repository import LocalRepository
|
||||
from datetime import datetime
|
||||
import os
|
||||
import time
|
||||
import traceback
|
||||
@@ -48,12 +49,15 @@ class Updater(Plugin):
|
||||
|
||||
def getInfo(self):
|
||||
|
||||
return jsonified({
|
||||
return jsonified(self.info())
|
||||
|
||||
def info(self):
|
||||
return {
|
||||
'repo_name': self.repo_name,
|
||||
'last_check': self.last_check,
|
||||
'update_version': self.update_version,
|
||||
'version': self.getVersion()
|
||||
})
|
||||
}
|
||||
|
||||
def getVersion(self):
|
||||
|
||||
@@ -91,14 +95,14 @@ class Updater(Plugin):
|
||||
log.info('Versions, local:%s, remote:%s' % (local.hash[:8], remote.hash[:8]))
|
||||
|
||||
if local.getDate() < remote.getDate():
|
||||
self.update_version = {
|
||||
'hash': remote.hash[:8],
|
||||
'date': remote.getDate(),
|
||||
}
|
||||
if self.conf('automatic') and not self.update_failed:
|
||||
if self.doUpdate():
|
||||
fireEventAsync('app.crappy_restart')
|
||||
else:
|
||||
self.update_version = {
|
||||
'hash': remote.hash[:8],
|
||||
'date': remote.getDate(),
|
||||
}
|
||||
if self.conf('notification'):
|
||||
fireEvent('updater.available', message = 'A new update is available', data = self.getVersion())
|
||||
|
||||
@@ -119,11 +123,16 @@ class Updater(Plugin):
|
||||
self.repo.saveStash()
|
||||
|
||||
log.info('Updating to latest version')
|
||||
info = self.info()
|
||||
self.repo.pull()
|
||||
|
||||
# Delete leftover .pyc files
|
||||
self.deletePyc()
|
||||
|
||||
# Notify before returning and restarting
|
||||
version_date = datetime.fromtimestamp(info['update_version']['date'])
|
||||
fireEvent('updater.updated', 'Updated to a new version with hash "%s", this version is from %s' % (info['update_version']['hash'], version_date), data = info)
|
||||
|
||||
return True
|
||||
except:
|
||||
log.error('Failed updating via GIT: %s' % traceback.format_exc())
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
from couchpotato import get_session
|
||||
from couchpotato.api import addApiView
|
||||
from couchpotato.core.event import addEvent, fireEvent
|
||||
from couchpotato.core.helpers.request import jsonified
|
||||
from couchpotato.core.helpers.encoding import toUnicode
|
||||
from couchpotato.core.helpers.request import jsonified, getParam
|
||||
from couchpotato.core.helpers.variable import tryInt
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.notifications.base import Notification
|
||||
from couchpotato.core.settings.model import Notification as Notif
|
||||
from sqlalchemy.sql.expression import or_
|
||||
import time
|
||||
|
||||
log = CPLog(__name__)
|
||||
@@ -11,28 +16,65 @@ log = CPLog(__name__)
|
||||
class CoreNotifier(Notification):
|
||||
|
||||
messages = []
|
||||
listen_to = [
|
||||
'movie.downloaded', 'movie.snatched',
|
||||
'updater.available', 'updater.updated',
|
||||
]
|
||||
|
||||
def __init__(self):
|
||||
super(CoreNotifier, self).__init__()
|
||||
|
||||
addEvent('notify', self.notify)
|
||||
addEvent('notify.frontend', self.frontend)
|
||||
|
||||
addApiView('core_notifier.listener', self.listener)
|
||||
addApiView('notification.markread', self.markAsRead, docs = {
|
||||
'desc': 'Mark notifications as read',
|
||||
'params': {
|
||||
'id': {'desc': 'Notification id you want to mark as read.', 'type': 'int (comma separated)'},
|
||||
},
|
||||
})
|
||||
addApiView('notification.listener', self.listener)
|
||||
|
||||
self.registerEvents()
|
||||
|
||||
|
||||
def registerEvents(self):
|
||||
|
||||
# Library update, frontend refresh
|
||||
addEvent('library.update_finish', lambda data: fireEvent('notify.frontend', type = 'library.update', data = data))
|
||||
|
||||
def notify(self, message = '', data = {}):
|
||||
self.add(data = {
|
||||
'message': message,
|
||||
'raw': data,
|
||||
def markAsRead(self):
|
||||
ids = getParam('ids').split(',')
|
||||
|
||||
db = get_session()
|
||||
|
||||
q = db.query(Notif) \
|
||||
.filter(or_(*[Notif.id == tryInt(s) for s in ids]))
|
||||
q.update({Notif.read: True})
|
||||
|
||||
db.commit()
|
||||
|
||||
return jsonified({
|
||||
'success': True
|
||||
})
|
||||
|
||||
def notify(self, message = '', data = {}):
|
||||
|
||||
db = get_session()
|
||||
|
||||
n = Notif(
|
||||
message = toUnicode(message),
|
||||
data = data
|
||||
)
|
||||
db.add(n)
|
||||
db.commit()
|
||||
|
||||
ndict = n.to_dict()
|
||||
ndict['type'] = 'notification'
|
||||
ndict['time'] = time.time()
|
||||
self.messages.append(ndict)
|
||||
|
||||
db.remove()
|
||||
|
||||
def frontend(self, type = 'notification', data = {}):
|
||||
self.messages.append({
|
||||
'time': time.time(),
|
||||
@@ -48,6 +90,15 @@ class CoreNotifier(Notification):
|
||||
if message['time'] > (time.time() - 15):
|
||||
messages.append(message)
|
||||
|
||||
# Get unread
|
||||
if getParam('init'):
|
||||
db = get_session()
|
||||
notifications = db.query(Notif).filter_by(read = False).all()
|
||||
for n in notifications:
|
||||
ndict = n.to_dict()
|
||||
ndict['type'] = 'notification'
|
||||
messages.append(ndict)
|
||||
|
||||
self.messages = []
|
||||
return jsonified({
|
||||
'success': True,
|
||||
|
||||
@@ -10,19 +10,90 @@ var NotificationBase = new Class({
|
||||
// Listener
|
||||
App.addEvent('load', self.startInterval.bind(self));
|
||||
App.addEvent('unload', self.stopTimer.bind(self));
|
||||
self.addEvent('notification', self.notify.bind(self))
|
||||
App.addEvent('notification', self.notify.bind(self));
|
||||
|
||||
// Add test buttons to settings page
|
||||
App.addEvent('load', self.addTestButtons.bind(self));
|
||||
|
||||
// Notification bar
|
||||
self.notifications = []
|
||||
App.addEvent('load', function(){
|
||||
|
||||
App.block.notification = new Block.Menu(self, {
|
||||
'class': 'notification_menu',
|
||||
'onOpen': self.markAsRead.bind(self)
|
||||
})
|
||||
$(App.block.notification).inject(App.getBlock('search'), 'after');
|
||||
self.badge = new Element('div.badge').inject(App.block.notification, 'top').hide();
|
||||
|
||||
App.getBlock('notification').addLink(new Element('a.more', {
|
||||
'href': App.createUrl('notifications'),
|
||||
'text': 'See more notifications'
|
||||
}));
|
||||
})
|
||||
|
||||
},
|
||||
|
||||
notify: function(result){
|
||||
var self = this;
|
||||
|
||||
var added = new Date();
|
||||
added.setTime(result.added*1000)
|
||||
|
||||
result.el = App.getBlock('notification').addLink(
|
||||
new Element('span').adopt(
|
||||
new Element('span.message', {'text': result.message}),
|
||||
new Element('span.added', {'text': added.timeDiffInWords(), 'title': added})
|
||||
)
|
||||
, 'top');
|
||||
self.notifications.include(result);
|
||||
|
||||
if(!result.read)
|
||||
self.setBadge(self.notifications.filter(function(n){ return !n.read}).length)
|
||||
|
||||
if(self.notifications.length >= 5){
|
||||
var n = self.notifications[self.notifications.length-5];
|
||||
n.el.destroy();
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
setBadge: function(value){
|
||||
var self = this;
|
||||
self.badge.set('text', value)
|
||||
self.badge[value ? 'show' : 'hide']()
|
||||
},
|
||||
|
||||
markAsRead: function(){
|
||||
var self = this;
|
||||
|
||||
var rn = self.notifications.filter(function(n){
|
||||
return !n.read
|
||||
})
|
||||
|
||||
var ids = []
|
||||
rn.each(function(n){
|
||||
ids.include(n.id)
|
||||
})
|
||||
|
||||
Api.request('notification.markread', {
|
||||
'data': {
|
||||
'ids': ids.join(',')
|
||||
},
|
||||
'onSuccess': function(){
|
||||
self.setBadge('')
|
||||
}
|
||||
})
|
||||
|
||||
},
|
||||
|
||||
startInterval: function(){
|
||||
var self = this;
|
||||
|
||||
self.request = Api.request('core_notifier.listener', {
|
||||
self.request = Api.request('notification.listener', {
|
||||
'initialDelay': 100,
|
||||
'delay': 3000,
|
||||
'data': {'init':true},
|
||||
'onSuccess': self.processData.bind(self)
|
||||
})
|
||||
|
||||
@@ -40,16 +111,12 @@ var NotificationBase = new Class({
|
||||
this.request.stopTimer()
|
||||
},
|
||||
|
||||
notify: function(data){
|
||||
var self = this;
|
||||
|
||||
},
|
||||
|
||||
processData: function(json){
|
||||
var self = this;
|
||||
|
||||
self.request.options.data = {}
|
||||
Array.each(json.result, function(result){
|
||||
App.fireEvent(result.type, result.data)
|
||||
App.fireEvent(result.type, result)
|
||||
})
|
||||
},
|
||||
|
||||
|
||||
@@ -116,25 +116,7 @@ var MovieList = new Class({
|
||||
'change': self.search.bind(self)
|
||||
}
|
||||
}),
|
||||
self.navigation_menu = new Element('div.more_menu').adopt(
|
||||
self.navigation_menu_ul = new Element('ul'),
|
||||
self.navigation_menu_toggle = new Element('a.button.onlay', {
|
||||
'events': {
|
||||
'click': function(){
|
||||
self.navigation_menu.toggleClass('show')
|
||||
|
||||
if(self.navigation_menu.hasClass('show'))
|
||||
this.addEvent('outerClick', function(){
|
||||
self.navigation_menu.removeClass('show')
|
||||
this.removeEvents('outerClick');
|
||||
})
|
||||
else
|
||||
this.removeEvents('outerClick');
|
||||
|
||||
}
|
||||
}
|
||||
})
|
||||
),
|
||||
self.navigation_menu = new Block.Menu(self),
|
||||
self.mass_edit_form = new Element('div.mass_edit_form').adopt(
|
||||
new Element('span.select').adopt(
|
||||
self.mass_edit_select = new Element('input[type=checkbox].inlay', {
|
||||
@@ -222,7 +204,7 @@ var MovieList = new Class({
|
||||
// Add menu or hide
|
||||
if (self.options.menu.length > 0)
|
||||
self.options.menu.each(function(menu_item){
|
||||
self.navigation_menu_ul.adopt(new Element('li').adopt(menu_item));
|
||||
self.navigation_menu.addLink(menu_item);
|
||||
})
|
||||
else
|
||||
self.navigation_menu.hide()
|
||||
@@ -268,7 +250,7 @@ var MovieList = new Class({
|
||||
'class': 'delete',
|
||||
'events': {
|
||||
'click': function(e){
|
||||
(e).stop();
|
||||
(e).preventDefault();
|
||||
Api.request('movie.delete', {
|
||||
'data': {
|
||||
'id': ids.join(',')
|
||||
|
||||
@@ -1,9 +1,3 @@
|
||||
/* @override
|
||||
http://localhost:5000/static/movie_plugin/movie.css
|
||||
http://192.168.1.20:5000/static/movie_plugin/movie.css
|
||||
http://127.0.0.1:5000/static/movie_plugin/movie.css
|
||||
*/
|
||||
|
||||
.movies {
|
||||
padding: 60px 0 20px;
|
||||
}
|
||||
@@ -454,7 +448,7 @@
|
||||
}
|
||||
|
||||
.movies .alph_nav .more_menu {
|
||||
float: right;
|
||||
margin-left: 48px;
|
||||
}
|
||||
|
||||
.movies .alph_nav .more_menu > a {
|
||||
|
||||
@@ -230,7 +230,7 @@ var IMDBAction = new Class({
|
||||
|
||||
gotoIMDB: function(e){
|
||||
var self = this;
|
||||
(e).stop();
|
||||
(e).preventDefault();
|
||||
|
||||
window.open('http://www.imdb.com/title/'+self.id+'/');
|
||||
}
|
||||
@@ -258,7 +258,7 @@ var ReleaseAction = new Class({
|
||||
|
||||
show: function(e){
|
||||
var self = this;
|
||||
(e).stop();
|
||||
(e).preventDefault();
|
||||
|
||||
if(!self.options_container){
|
||||
self.options_container = new Element('div.options').adopt(
|
||||
@@ -292,7 +292,7 @@ var ReleaseAction = new Class({
|
||||
new Element('a.download.icon', {
|
||||
'events': {
|
||||
'click': function(e){
|
||||
(e).stop();
|
||||
(e).preventDefault();
|
||||
self.download(release);
|
||||
}
|
||||
}
|
||||
@@ -300,7 +300,7 @@ var ReleaseAction = new Class({
|
||||
new Element('a.delete.icon', {
|
||||
'events': {
|
||||
'click': function(e){
|
||||
(e).stop();
|
||||
(e).preventDefault();
|
||||
self.ignore(release);
|
||||
this.getParent('.item').toggleClass('ignored')
|
||||
}
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
/* @override
|
||||
http://localhost:5000/static/movie_plugin/search.css
|
||||
http://192.168.1.20:5000/static/movie_plugin/search.css
|
||||
http://127.0.0.1:5000/static/movie_plugin/search.css
|
||||
*/
|
||||
|
||||
.search_form {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ Block.Search = new Class({
|
||||
|
||||
clear: function(e){
|
||||
var self = this;
|
||||
(e).stop();
|
||||
(e).preventDefault();
|
||||
|
||||
self.input.set('value', '');
|
||||
self.input.focus()
|
||||
@@ -283,7 +283,7 @@ Block.Search.Item = new Class({
|
||||
|
||||
add: function(e){
|
||||
var self = this;
|
||||
(e).stop();
|
||||
(e).preventDefault();
|
||||
|
||||
Api.request('movie.add', {
|
||||
'data': {
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
/* @override http://192.168.1.20:5000/static/profile_plugin/profile.css */
|
||||
|
||||
.add_new_profile {
|
||||
padding: 20px;
|
||||
display: block;
|
||||
|
||||
@@ -156,7 +156,7 @@ var Profile = new Class({
|
||||
'class': 'delete',
|
||||
'events': {
|
||||
'click': function(e){
|
||||
(e).stop();
|
||||
(e).preventDefault();
|
||||
Api.request('profile.delete', {
|
||||
'data': {
|
||||
'id': self.data.id
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
/* @override http://127.0.0.1:5000/static/quality_plugin/quality.css */
|
||||
|
||||
.group_sizes {
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
/* @override http://127.0.0.1:5000/static/wizard/wizard.css */
|
||||
|
||||
.page.wizard h1 {
|
||||
padding: 10px 30px;
|
||||
margin: 0;
|
||||
|
||||
@@ -35,7 +35,7 @@ Page.Wizard = new Class({
|
||||
'text': 'I\'m ready to start the awesomeness, wow this button is big and green!',
|
||||
'events': {
|
||||
'click': function(e){
|
||||
(e).stop();
|
||||
(e).preventDefault();
|
||||
Api.request('settings.save', {
|
||||
'data': {
|
||||
'section': 'core',
|
||||
|
||||
@@ -7,6 +7,7 @@ from libs.elixir.relationships import OneToOne
|
||||
from sqlalchemy.types import Integer, Unicode, UnicodeText, Boolean, Float, \
|
||||
String, TypeDecorator
|
||||
import json
|
||||
import time
|
||||
|
||||
options_defaults["shortnames"] = True
|
||||
|
||||
@@ -33,7 +34,7 @@ class Movie(Entity):
|
||||
The files belonging to the movie object are global for the whole movie
|
||||
such as trailers, nfo, thumbnails"""
|
||||
|
||||
last_edit = Field(Integer)
|
||||
last_edit = Field(Integer, default = lambda: int(time.time()))
|
||||
|
||||
library = ManyToOne('Library')
|
||||
status = ManyToOne('Status')
|
||||
@@ -191,8 +192,8 @@ class History(Entity):
|
||||
"""History of actions that are connected to a certain release,
|
||||
such as, renamed to, downloaded, deleted, download subtitles etc"""
|
||||
|
||||
added = Field(Integer)
|
||||
message = Field(UnicodeText())
|
||||
added = Field(Integer, default = lambda: int(time.time()))
|
||||
message = Field(UnicodeText)
|
||||
type = Field(Unicode(50))
|
||||
|
||||
release = ManyToOne('Release')
|
||||
@@ -207,6 +208,15 @@ class RenameHistory(Entity):
|
||||
file = ManyToOne('File')
|
||||
|
||||
|
||||
class Notification(Entity):
|
||||
using_options(order_by = 'added')
|
||||
|
||||
added = Field(Integer, default = lambda: int(time.time()))
|
||||
read = Field(Boolean, default = False)
|
||||
message = Field(Unicode(255))
|
||||
data = Field(JsonType)
|
||||
|
||||
|
||||
class Folder(Entity):
|
||||
"""Renamer destination folders."""
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 2.2 KiB |
@@ -0,0 +1,43 @@
|
||||
Block.Menu = new Class({
|
||||
|
||||
Extends: BlockBase,
|
||||
|
||||
options: {
|
||||
'class': 'menu'
|
||||
},
|
||||
|
||||
create: function(){
|
||||
var self = this;
|
||||
|
||||
self.el = new Element('div', {
|
||||
'class': 'more_menu '+self.options['class']
|
||||
}).adopt(
|
||||
self.more_option_ul = new Element('ul'),
|
||||
new Element('a.button.onlay', {
|
||||
'events': {
|
||||
'click': function(){
|
||||
self.el.toggleClass('show')
|
||||
self.fireEvent(self.el.hasClass('show') ? 'open' : 'close')
|
||||
|
||||
if(self.el.hasClass('show'))
|
||||
this.addEvent('outerClick', function(){
|
||||
self.el.removeClass('show')
|
||||
this.removeEvents('outerClick');
|
||||
})
|
||||
else
|
||||
this.removeEvents('outerClick');
|
||||
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
},
|
||||
|
||||
addLink: function(tab, position){
|
||||
var self = this;
|
||||
var el = new Element('li').adopt(tab).inject(self.more_option_ul, position || 'bottom');
|
||||
return el;
|
||||
}
|
||||
|
||||
});
|
||||
@@ -1,54 +0,0 @@
|
||||
Block.More = new Class({
|
||||
|
||||
Extends: BlockBase,
|
||||
|
||||
create: function(){
|
||||
var self = this;
|
||||
|
||||
self.el = new Element('div.more_menu').adopt(
|
||||
self.more_option_ul = new Element('ul').adopt(
|
||||
new Element('li').adopt(
|
||||
new Element('a.orange', {
|
||||
'text': 'Restart',
|
||||
'events': {
|
||||
'click': App.restart.bind(App)
|
||||
}
|
||||
})
|
||||
),
|
||||
new Element('li').adopt(
|
||||
new Element('a.red', {
|
||||
'text': 'Shutdown',
|
||||
'events': {
|
||||
'click': App.shutdown.bind(App)
|
||||
}
|
||||
})
|
||||
)
|
||||
),
|
||||
new Element('a.button.onlay', {
|
||||
'events': {
|
||||
'click': function(){
|
||||
self.el.toggleClass('show')
|
||||
|
||||
if(self.el.hasClass('show'))
|
||||
this.addEvent('outerClick', function(){
|
||||
self.el.removeClass('show')
|
||||
this.removeEvents('outerClick');
|
||||
})
|
||||
else
|
||||
this.removeEvents('outerClick');
|
||||
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
},
|
||||
|
||||
addLink: function(tab, position){
|
||||
var self = this
|
||||
|
||||
return new Element('li').adopt(tab).inject(self.more_option_ul, position || 'bottom')
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
@@ -43,7 +43,7 @@ var CouchPotato = new Class({
|
||||
pushState: function(e){
|
||||
var self = this;
|
||||
if((!e.meta && Browser.Platform.mac) || (!e.control && !Browser.Platform.mac)){
|
||||
(e).stop();
|
||||
(e).preventDefault();
|
||||
var url = e.target.get('href');
|
||||
if(History.getPath() != url)
|
||||
History.push(url);
|
||||
@@ -60,19 +60,34 @@ var CouchPotato = new Class({
|
||||
new Element('div').adopt(
|
||||
self.block.navigation = new Block.Navigation(self, {}),
|
||||
self.block.search = new Block.Search(self, {}),
|
||||
self.block.more = new Block.More(self, {})
|
||||
self.block.more = new Block.Menu(self, {})
|
||||
)
|
||||
),
|
||||
self.content = new Element('div.content'),
|
||||
self.block.footer = new Block.Footer(self, {})
|
||||
);
|
||||
|
||||
self.block.more.addLink(new Element('a', {
|
||||
[new Element('a.orange', {
|
||||
'text': 'Restart',
|
||||
'events': {
|
||||
'click': App.restart.bind(App)
|
||||
}
|
||||
}),
|
||||
new Element('a.red', {
|
||||
'text': 'Shutdown',
|
||||
'events': {
|
||||
'click': App.shutdown.bind(App)
|
||||
}
|
||||
}),
|
||||
new Element('a', {
|
||||
'text': 'Check for updates',
|
||||
'events': {
|
||||
'click': self.checkForUpdate.bind(self)
|
||||
}
|
||||
}))
|
||||
})].each(function(a){
|
||||
self.block.more.addLink(a)
|
||||
})
|
||||
|
||||
|
||||
new ScrollSpy({
|
||||
min: 10,
|
||||
@@ -207,6 +222,13 @@ var CouchPotato = new Class({
|
||||
|
||||
createUrl: function(action, params){
|
||||
return this.options.base_url + (action ? action+'/' : '') + (params ? '?'+Object.toQueryString(params) : '')
|
||||
},
|
||||
|
||||
notify: function(options){
|
||||
return this.growl.notify({
|
||||
title: "this scrolls away",
|
||||
text: "test - hello there. mouseover to pause away action"
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -628,7 +628,7 @@ Option.Directory = new Class({
|
||||
self.dir_list = new Element('ul', {
|
||||
'events': {
|
||||
'click:relay(li)': function(e, el){
|
||||
(e).stop();
|
||||
(e).preventDefault();
|
||||
self.selectDirectory(el.get('data-value'))
|
||||
},
|
||||
'mousewheel': function(e){
|
||||
@@ -678,7 +678,7 @@ Option.Directory = new Class({
|
||||
|
||||
hideBrowser: function(e, save){
|
||||
var self = this;
|
||||
(e).stop();
|
||||
(e).preventDefault();
|
||||
|
||||
if(save)
|
||||
self.save()
|
||||
@@ -1241,7 +1241,7 @@ Option.Combined = new Class({
|
||||
|
||||
deleteCombinedItem: function(e){
|
||||
var self = this;
|
||||
(e).stop();
|
||||
(e).preventDefault();
|
||||
|
||||
var item = e.target.getParent();
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ window.addEvent('domready', function(){
|
||||
|
||||
editMovie: function(e){
|
||||
var self = this;
|
||||
(e).stop();
|
||||
(e).preventDefault();
|
||||
|
||||
if(!self.options_container){
|
||||
self.options_container = new Element('div.options').adopt(
|
||||
@@ -89,7 +89,7 @@ window.addEvent('domready', function(){
|
||||
},
|
||||
|
||||
save: function(e){
|
||||
(e).stop();
|
||||
(e).preventDefault();
|
||||
var self = this;
|
||||
|
||||
Api.request('movie.edit', {
|
||||
@@ -129,7 +129,7 @@ window.addEvent('domready', function(){
|
||||
|
||||
doRefresh: function(e){
|
||||
var self = this;
|
||||
(e).stop();
|
||||
(e).preventDefault();
|
||||
|
||||
Api.request('movie.refresh', {
|
||||
'data': {
|
||||
@@ -160,7 +160,7 @@ window.addEvent('domready', function(){
|
||||
|
||||
showConfirm: function(e){
|
||||
var self = this;
|
||||
(e).stop();
|
||||
(e).preventDefault();
|
||||
|
||||
if(!self.delete_container){
|
||||
self.delete_container = new Element('div.delete_container').adopt(
|
||||
@@ -188,13 +188,13 @@ window.addEvent('domready', function(){
|
||||
|
||||
hideConfirm: function(e){
|
||||
var self = this;
|
||||
(e).stop();
|
||||
(e).preventDefault();
|
||||
|
||||
self.movie.slide('out');
|
||||
},
|
||||
|
||||
del: function(e){
|
||||
(e).stop();
|
||||
(e).preventDefault();
|
||||
var self = this;
|
||||
|
||||
var movie = $(self.movie);
|
||||
@@ -253,7 +253,7 @@ window.addEvent('domready', function(){
|
||||
|
||||
showFiles: function(e){
|
||||
var self = this;
|
||||
(e).stop();
|
||||
(e).preventDefault();
|
||||
|
||||
if(!self.options_container){
|
||||
self.options_container = new Element('div.options').adopt(
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
html {
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
|
||||
@@ -1,10 +1,3 @@
|
||||
/* @override
|
||||
http://localhost:5000/static/style/main.css
|
||||
http://192.168.1.20:5000/static/style/main.css
|
||||
http://127.0.0.1:5000/static/style/main.css
|
||||
http://127.0.0.1:5000/v2/_api_/static/style/main.css
|
||||
*/
|
||||
|
||||
html {
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
@@ -184,6 +177,7 @@ body > .spinner, .mask{
|
||||
}
|
||||
.header .navigation {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
width: 67.2%;
|
||||
}
|
||||
.header .navigation ul {
|
||||
@@ -239,8 +233,7 @@ body > .spinner, .mask{
|
||||
.header:hover .navigation .backtotop { color: #fff; }
|
||||
|
||||
.header .more_menu {
|
||||
float: right;
|
||||
margin-top: 20px;
|
||||
margin-left: 12px;
|
||||
}
|
||||
.header .more_menu ul {
|
||||
width: 150px;
|
||||
@@ -252,6 +245,51 @@ body > .spinner, .mask{
|
||||
|
||||
.header .more_menu .red { color: red; }
|
||||
.header .more_menu .orange { color: orange; }
|
||||
|
||||
.badge {
|
||||
position: absolute;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
text-align: center;
|
||||
line-height: 14px;
|
||||
border-radius: 50%;
|
||||
font-size: 8px;
|
||||
margin: -5px 0 0 15px;
|
||||
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;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
.header .notification_menu ul {
|
||||
width: 300px;
|
||||
margin-left: -260px;
|
||||
text-align: left;
|
||||
}
|
||||
.header .notification_menu ul:before {
|
||||
left: 296px;
|
||||
}
|
||||
|
||||
.header .notification_menu > a {
|
||||
background-position: center -209px;
|
||||
}
|
||||
|
||||
.header .notification_menu li > span {
|
||||
padding: 5px;
|
||||
display: block;
|
||||
border-bottom: 1px solid rgba(0,0,0,0.2);
|
||||
}
|
||||
.header .notification_menu li .added {
|
||||
display: block;
|
||||
font-size: 10px;
|
||||
color: #aaa;
|
||||
text-align: ;
|
||||
}
|
||||
|
||||
.header .notification_menu li .more {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.header .message.update {
|
||||
text-align: center;
|
||||
@@ -454,6 +492,10 @@ body > .spinner, .mask{
|
||||
background-color: #4c5766;
|
||||
}
|
||||
|
||||
.more_menu {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.more_menu > a {
|
||||
display: block;
|
||||
@@ -470,16 +512,30 @@ body > .spinner, .mask{
|
||||
.more_menu ul {
|
||||
display: none;
|
||||
border: 1px solid #333;
|
||||
background: rgba(0,0,0,0.8);
|
||||
background: rgba(255,255,255,0.98);
|
||||
border-radius: 3px;
|
||||
padding: 4px !important;
|
||||
position: absolute;
|
||||
z-index: 9;
|
||||
margin: 32px 0 0 -145px;
|
||||
width: 185px;
|
||||
box-shadow: 0 10px 20px -10px rgba(0,0,0,0.4);
|
||||
box-shadow: 0 10px 10px -5px rgba(0,0,0,0.4);
|
||||
list-style: none;
|
||||
text-align: center;
|
||||
color: #000;
|
||||
text-shadow: none;
|
||||
background-image: -webkit-gradient(
|
||||
linear,
|
||||
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(255,255,255) 100%
|
||||
);
|
||||
}
|
||||
|
||||
.more_menu ul:before {
|
||||
@@ -488,7 +544,7 @@ body > .spinner, .mask{
|
||||
position: relative;
|
||||
width: 0;
|
||||
border: 6px solid transparent;
|
||||
border-bottom-color: rgba(0,0,0,0.8);
|
||||
border-bottom-color: #fff;
|
||||
display: block;
|
||||
top: -16px;
|
||||
left: 146px;
|
||||
@@ -510,7 +566,7 @@ body > .spinner, .mask{
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
padding: 3px 0;
|
||||
color: #fff;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.more_menu ul li:first-child {
|
||||
@@ -519,8 +575,7 @@ body > .spinner, .mask{
|
||||
|
||||
.more_menu ul li:last-child a {
|
||||
border: none;
|
||||
color: #fff;
|
||||
}
|
||||
.more_menu ul li a:hover {
|
||||
background: rgba(255,255,255,0.1);
|
||||
background: rgba(0,0,0,0.05);
|
||||
}
|
||||
@@ -1,9 +1,3 @@
|
||||
/* @override
|
||||
http://localhost:5000/static/style/page/settings.css
|
||||
http://192.168.1.20:5000/static/style/page/settings.css
|
||||
http://127.0.0.1:5000/static/style/page/settings.css
|
||||
*/
|
||||
|
||||
.page.settings:after {
|
||||
content: ".";
|
||||
display: block;
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
<script type="text/javascript" src="{{ url_for('web.static', filename='scripts/block.js') }}"></script>
|
||||
<script type="text/javascript" src="{{ url_for('web.static', filename='scripts/block/navigation.js') }}"></script>
|
||||
<script type="text/javascript" src="{{ url_for('web.static', filename='scripts/block/footer.js') }}"></script>
|
||||
<script type="text/javascript" src="{{ url_for('web.static', filename='scripts/block/more.js') }}"></script>
|
||||
<script type="text/javascript" src="{{ url_for('web.static', filename='scripts/block/menu.js') }}"></script>
|
||||
|
||||
<script type="text/javascript" src="{{ url_for('web.static', filename='scripts/page/wanted.js') }}"></script>
|
||||
<script type="text/javascript" src="{{ url_for('web.static', filename='scripts/page/settings.js') }}"></script>
|
||||
|
||||
Reference in New Issue
Block a user