Profile sorting
This commit is contained in:
1 parent
85c3b16e69
commit
6940477e48
5 files changed
+162
-15
No files matched your search
@@ -1,3 +1,4 @@
|
|||||||
|
from couchpotato.core.helpers.variable import natcmp
|
||||||
from flask.globals import current_app
|
from flask.globals import current_app
|
||||||
from flask.helpers import json
|
from flask.helpers import json
|
||||||
from libs.werkzeug.urls import url_decode
|
from libs.werkzeug.urls import url_decode
|
||||||
@@ -42,7 +43,7 @@ def dictToList(params):
|
|||||||
new = {}
|
new = {}
|
||||||
for x, value in params.iteritems():
|
for x, value in params.iteritems():
|
||||||
try:
|
try:
|
||||||
new_value = [dictToList(value[k]) for k in sorted(value.iterkeys())]
|
new_value = [dictToList(value[k]) for k in sorted(value.iterkeys(), cmp = natcmp)]
|
||||||
except:
|
except:
|
||||||
new_value = value
|
new_value = value
|
||||||
|
|
||||||
@@ -70,4 +71,3 @@ def jsonified(*args, **kwargs):
|
|||||||
return padded_jsonify(callback, *args, **kwargs)
|
return padded_jsonify(callback, *args, **kwargs)
|
||||||
else:
|
else:
|
||||||
return jsonify('text/javascript' if Env.doDebug() else 'application/json', *args, **kwargs)
|
return jsonify('text/javascript' if Env.doDebug() else 'application/json', *args, **kwargs)
|
||||||
|
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import hashlib
|
import hashlib
|
||||||
import os.path
|
import os.path
|
||||||
|
import re
|
||||||
|
|
||||||
def isDict(object):
|
def isDict(object):
|
||||||
return isinstance(object, dict)
|
return isinstance(object, dict)
|
||||||
@@ -41,3 +42,13 @@ def cleanHost(host):
|
|||||||
host += '/'
|
host += '/'
|
||||||
|
|
||||||
return host
|
return host
|
||||||
|
|
||||||
|
def tryInt(s):
|
||||||
|
try: return int(s)
|
||||||
|
except: return s
|
||||||
|
|
||||||
|
def natsortKey(s):
|
||||||
|
return map(tryInt, re.findall(r'(\d+|\D+)', s))
|
||||||
|
|
||||||
|
def natcmp(a, b):
|
||||||
|
return cmp(natsortKey(a), natsortKey(b))
|
||||||
@@ -16,6 +16,7 @@ class ProfilePlugin(Plugin):
|
|||||||
addEvent('profile.all', self.all)
|
addEvent('profile.all', self.all)
|
||||||
|
|
||||||
addApiView('profile.save', self.save)
|
addApiView('profile.save', self.save)
|
||||||
|
addApiView('profile.save_order', self.saveOrder)
|
||||||
addApiView('profile.delete', self.delete)
|
addApiView('profile.delete', self.delete)
|
||||||
|
|
||||||
addEvent('app.initialize', self.fill)
|
addEvent('app.initialize', self.fill)
|
||||||
@@ -70,6 +71,25 @@ class ProfilePlugin(Plugin):
|
|||||||
'profile': profile_dict
|
'profile': profile_dict
|
||||||
})
|
})
|
||||||
|
|
||||||
|
def saveOrder(self):
|
||||||
|
|
||||||
|
params = getParams()
|
||||||
|
db = get_session()
|
||||||
|
|
||||||
|
order = 0
|
||||||
|
for profile in params.get('ids', []):
|
||||||
|
p = db.query(Profile).filter_by(id = profile).first()
|
||||||
|
p.hide = params.get('hidden')[order]
|
||||||
|
p.order = order
|
||||||
|
|
||||||
|
order += 1
|
||||||
|
|
||||||
|
db.commit()
|
||||||
|
|
||||||
|
return jsonified({
|
||||||
|
'success': True
|
||||||
|
})
|
||||||
|
|
||||||
def delete(self):
|
def delete(self):
|
||||||
|
|
||||||
id = getParam('id')
|
id = getParam('id')
|
||||||
|
|||||||
@@ -45,6 +45,7 @@
|
|||||||
.profile .types li {
|
.profile .types li {
|
||||||
padding: 3px 5px;
|
padding: 3px 5px;
|
||||||
border-bottom: 1px solid rgba(255,255,255,0.2);
|
border-bottom: 1px solid rgba(255,255,255,0.2);
|
||||||
|
list-style: none;
|
||||||
}
|
}
|
||||||
.profile .types li:last-child { border: 0; }
|
.profile .types li:last-child { border: 0; }
|
||||||
|
|
||||||
@@ -85,4 +86,51 @@
|
|||||||
|
|
||||||
.profile .types .type:hover:not(.is_empty) .delete {
|
.profile .types .type:hover:not(.is_empty) .delete {
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#profile_ordering {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#profile_ordering .head {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
#profile_ordering .head span {
|
||||||
|
margin: 0 10px 0 -5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#profile_ordering ul {
|
||||||
|
clear: both;
|
||||||
|
float: left;
|
||||||
|
margin-left: 20%;
|
||||||
|
width: 275px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#profile_ordering li {
|
||||||
|
clear: both;
|
||||||
|
overflow: hidden;
|
||||||
|
cursor: grab;
|
||||||
|
cursor: -moz-grab;
|
||||||
|
cursor: -webkit-grab;
|
||||||
|
border-bottom: 1px solid rgba(255,255,255,0.2);
|
||||||
|
padding: 0 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#profile_ordering li .check {
|
||||||
|
margin: 2px 10px 0 0;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
#profile_ordering li > span {
|
||||||
|
display: inline-block;
|
||||||
|
height: 20px;
|
||||||
|
vertical-align: top;
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#profile_ordering li .handle {
|
||||||
|
background: url('./handle.png') center;
|
||||||
|
width: 20px;
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
@@ -39,6 +39,7 @@ var QualityBase = new Class({
|
|||||||
self.content = tab.content;
|
self.content = tab.content;
|
||||||
|
|
||||||
self.createProfiles();
|
self.createProfiles();
|
||||||
|
self.createProfileOrdering();
|
||||||
self.createSizes();
|
self.createSizes();
|
||||||
|
|
||||||
})
|
})
|
||||||
@@ -67,6 +68,7 @@ var QualityBase = new Class({
|
|||||||
self.profile_container = new Element('div.container')
|
self.profile_container = new Element('div.container')
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Add profiles, that aren't part of the core (for editing)
|
||||||
Object.each(self.profiles, function(profile){
|
Object.each(self.profiles, function(profile){
|
||||||
if(!profile.isCore())
|
if(!profile.isCore())
|
||||||
$(profile).inject(self.profile_container, 'top')
|
$(profile).inject(self.profile_container, 'top')
|
||||||
@@ -77,15 +79,80 @@ var QualityBase = new Class({
|
|||||||
createProfilesClass: function(data){
|
createProfilesClass: function(data){
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
if(data){
|
var data = data || {'id': randomString()}
|
||||||
return self.profiles[data.id] = new Profile(data);
|
|
||||||
}
|
return self.profiles[data.id] = new Profile(data);
|
||||||
else {
|
},
|
||||||
var data = {
|
|
||||||
'id': randomString()
|
createProfileOrdering: function(){
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
var profile_list;
|
||||||
|
var group = self.settings.createGroup({
|
||||||
|
'label': 'Profile Order',
|
||||||
|
'description': 'Change the order the profiles are in the dropdown list.'
|
||||||
|
}).adopt(
|
||||||
|
new Element('.ctrlHolder#profile_ordering').adopt(
|
||||||
|
new Element('label[text=Order]'),
|
||||||
|
new Element('.head').adopt(
|
||||||
|
new Element('span.show[text=Show]'),
|
||||||
|
new Element('span.profile_label[text=Profile]')
|
||||||
|
),
|
||||||
|
profile_list = new Element('ul')
|
||||||
|
)
|
||||||
|
).inject(self.content)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Object.each(self.profiles, function(profile){
|
||||||
|
var check;
|
||||||
|
new Element('li', {'data-id': profile.data.id}).adopt(
|
||||||
|
check = new Element('input.inlay[type=checkbox]', {
|
||||||
|
'checked': !profile.data.hide,
|
||||||
|
'events': {
|
||||||
|
'change': self.saveProfileOrdering.bind(self)
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
new Element('span.profile_label', {
|
||||||
|
'text': profile.data.label
|
||||||
|
}),
|
||||||
|
new Element('span.handle')
|
||||||
|
).inject(profile_list);
|
||||||
|
|
||||||
|
new Form.Check(check);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
// Sortable
|
||||||
|
self.profile_sortable = new Sortables(profile_list, {
|
||||||
|
'revert': true,
|
||||||
|
'handle': '',
|
||||||
|
'opacity': 0.5,
|
||||||
|
'onComplete': self.saveProfileOrdering.bind(self)
|
||||||
|
});
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
saveProfileOrdering: function(){
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
var ids = [];
|
||||||
|
var hidden = [];
|
||||||
|
|
||||||
|
self.profile_sortable.list.getElements('li').each(function(el, nr){
|
||||||
|
ids.include(el.get('data-id'));
|
||||||
|
hidden[nr] = +!el.getElement('input[type=checkbox]').get('checked');
|
||||||
|
});
|
||||||
|
|
||||||
|
p(ids, hidden);
|
||||||
|
Api.request('profile.save_order', {
|
||||||
|
'data': {
|
||||||
|
'ids': ids,
|
||||||
|
'hidden': hidden
|
||||||
}
|
}
|
||||||
return self.profiles[data.id] = new Profile(data);
|
});
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -99,21 +166,22 @@ var QualityBase = new Class({
|
|||||||
'description': 'Edit the minimal and maximum sizes (in MB) for each quality.',
|
'description': 'Edit the minimal and maximum sizes (in MB) for each quality.',
|
||||||
'advanced': true
|
'advanced': true
|
||||||
}).inject(self.content)
|
}).inject(self.content)
|
||||||
|
|
||||||
|
|
||||||
new Element('div.item.head').adopt(
|
new Element('div.item.head').adopt(
|
||||||
new Element('span.label', {'text': 'Quality'}),
|
new Element('span.label', {'text': 'Quality'}),
|
||||||
new Element('span.min', {'text': 'Min'}),
|
new Element('span.min', {'text': 'Min'}),
|
||||||
new Element('span.max', {'text': 'Max'})
|
new Element('span.max', {'text': 'Max'})
|
||||||
).inject(group)
|
).inject(group)
|
||||||
|
|
||||||
Object.each(self.qualities, function(quality){
|
Object.each(self.qualities, function(quality){
|
||||||
new Element('div.item').adopt(
|
new Element('div.ctrlHolder.item').adopt(
|
||||||
new Element('span.label', {'text': quality.label}),
|
new Element('span.label', {'text': quality.label}),
|
||||||
new Element('input.min', {'value': quality.size_min}),
|
new Element('input.min', {'value': quality.size_min}),
|
||||||
new Element('input.max', {'value': quality.size_max})
|
new Element('input.max', {'value': quality.size_max})
|
||||||
).inject(group)
|
).inject(group)
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in new issue
Block a user