From 74f777e0d1f4fdd86efb082d8ee01b9f84f31687 Mon Sep 17 00:00:00 2001
From: j <0x006A@0x2620.org>
Date: Tue, 18 Oct 2011 22:06:01 +0200
Subject: [PATCH 1/5] show selected/wanted files
---
pandora/archive/models.py | 30 ++++++++++-----------
pandora/archive/views.py | 30 +++++++++++++--------
pandora/item/models.py | 24 +++++++++++------
pandora/item/views.py | 32 ++++++++++++++++++++++
static/js/pandora/ui/filesView.js | 45 +++++++++++++++++++++++++++----
5 files changed, 121 insertions(+), 40 deletions(-)
diff --git a/pandora/archive/models.py b/pandora/archive/models.py
index cee5e8d7..37552ee9 100644
--- a/pandora/archive/models.py
+++ b/pandora/archive/models.py
@@ -261,28 +261,26 @@ class File(models.Model):
if resolution == (0, 0):
resolution = None
duration = self.duration
- if self.get_type() != 'video':
+ if self.type != 'video':
duration = None
data = {
+ 'audioCodec': self.audio_codec,
'available': self.available,
'duration': duration,
'framerate': self.framerate,
- #'height': self.height,
- #'width': self.width,
- 'resolution': resolution,
'id': self.oshash,
- 'samplerate': self.samplerate,
- 'video_codec': self.video_codec,
- 'audio_codec': self.audio_codec,
- 'path': self.path,
- 'size': self.size,
- #'info': self.info,
- 'users': list(set([u.username
- for u in User.objects.filter(volumes__files__in=self.instances.all())])),
'instances': [i.json() for i in self.instances.all()],
- 'type': self.get_type(),
- 'part': self.get_part()
+ 'part': self.part,
+ 'path': self.path,
+ 'resolution': resolution,
+ 'samplerate': self.samplerate,
+ 'selected': self.selected,
+ 'size': self.size,
+ 'type': self.type,
+ 'videoCodec': self.video_codec,
+ 'wanted': self.wanted,
}
+ data['users'] = [i['user'] for i in data['instances']]
if keys:
for k in data.keys():
if k not in keys:
@@ -290,7 +288,6 @@ class File(models.Model):
return data
def get_part(self):
- #FIXME: this breaks for sub/idx/srt
if os.path.splitext(self.path)[-1] in ('.sub', '.idx', '.srt'):
name = os.path.splitext(self.path)[0]
if self.language:
@@ -388,9 +385,10 @@ class Instance(models.Model):
def json(self):
return {
+ 'ignore': self.ignore,
+ 'path': self.path,
'user': self.volume.user.username,
'volume': self.volume.name,
- 'path': self.path
}
def frame_path(frame, name):
diff --git a/pandora/archive/views.py b/pandora/archive/views.py
index f8ac0b08..3a475b78 100644
--- a/pandora/archive/views.py
+++ b/pandora/archive/views.py
@@ -7,7 +7,7 @@ from datetime import datetime
from django import forms
from django.shortcuts import get_object_or_404, redirect
from django.conf import settings
-from django.db.models import Count, Sum
+from django.db.models import Count
import ox
from ox.utils import json
@@ -288,7 +288,8 @@ def editFile(request):
param data {
id: hash of file
part:
- id_extra: boolean
+ language:
+ ignore: boolean
}
return {
@@ -297,17 +298,26 @@ def editFile(request):
}
}
'''
- #FIXME: permissions, need to be checked
data = json.loads(request.POST['data'])
f = get_object_or_404_json(models.File, oshash=data['id'])
response = json_response()
- if data.keys() != ('id', ):
- for key in data:
- if key in ('is_extra', 'is_subtitle', 'is_video', 'is_version',
- 'part', 'language'):
+ if f.editable(request.user):
+ update = False
+ #FIXME: should all instances be ignored?
+ if 'ignore' in data:
+ f.instances.update(ignore=True)
+ #FIXME: is this to slow to run sync?
+ f.item.update_selected()
+ for key in ('part', 'language'):
+ if key in data:
setattr(f, key, data[key])
- f.auto = False
- f.save()
+ f.auto = False
+ update = True
+ if update:
+ f.save()
+ response = json_response(status=200, text='updated')
+ else:
+ response = json_response(status=403, text='permissino denied')
return render_to_json_response(response)
actions.register(editFile, cache=False)
@@ -415,8 +425,6 @@ Positions
}
'''
data = json.loads(request.POST['data'])
- if settings.JSON_DEBUG:
- print json.dumps(data, indent=2)
query = parse_query(data, request.user)
response = json_response({})
diff --git a/pandora/item/models.py b/pandora/item/models.py
index 83889e21..e125a159 100644
--- a/pandora/item/models.py
+++ b/pandora/item/models.py
@@ -59,7 +59,7 @@ def get_id(info):
if settings.DATA_SERVICE:
r = external_data('getId', info)
if r['status']['code'] == 200:
- imdbId = r['data']['imdbId']
+ imdbId = r['data']['id']
return imdbId
return None
@@ -542,6 +542,8 @@ class Item(models.Model):
def set_value(s, name, value):
if not value:
value = None
+ if isinstance(value, basestring):
+ value = value.lower()
setattr(s, name, value)
base_keys = (
@@ -553,7 +555,7 @@ class Item(models.Model):
'lightness',
'volume',
'clips',
- 'cuts',
+ 'numberofcuts',
'cutsperminute',
'words',
'wordsperminute',
@@ -622,8 +624,8 @@ class Item(models.Model):
# sort values based on data from videos
s.words = sum([len(a.value.split()) for a in self.annotations.all()])
+ s.clips= self.clips.count()
- s.clips = 0 #FIXME: get clips from all layers or something
videos = self.files.filter(selected=True, is_video=True)
if videos.count() > 0:
s.duration = sum([v.duration for v in videos])
@@ -657,9 +659,9 @@ class Item(models.Model):
s.hue = None
s.saturation = None
s.brighness = None
- s.cuts = len(self.data.get('cuts', []))
+ s.numberofcuts = len(self.data.get('cuts', []))
if s.duration:
- s.cutsperminute = s.cuts / (s.duration/60)
+ s.cutsperminute = s.numberofcuts / (s.duration/60)
s.wordsperminute = s.words / (s.duration / 60)
else:
s.cutsperminute = None
@@ -667,7 +669,6 @@ class Item(models.Model):
s.popularity = self.accessed.aggregate(Sum('accessed'))['accessed__sum']
s.save()
-
def update_facets(self):
#FIXME: what to do with Unkown Director, Year, Country etc.
for key in self.facet_keys + ['title']:
@@ -735,8 +736,10 @@ class Item(models.Model):
return os.path.join(settings.MEDIA_ROOT, self.path(), 'timeline')
def get_files(self, user):
- #FIXME: limit by user
- return [f.json() for f in self.files.all()]
+ files = self.files.all().select_related()
+ if user.get_profile().get_level() != 'admin':
+ files = files.filter(instances__volume__user=user)
+ return [f.json() for f in files]
def users_with_files(self):
return User.objects.filter(
@@ -764,6 +767,7 @@ class Item(models.Model):
for s in self.sets():
if s.filter(Q(is_video=True)|Q(is_audio=True)).filter(available=False).count() == 0:
update = False
+ self.files.exclude(id__in=s).exclude(part=None).update(part=None)
deselect = self.files.filter(selected=True).exclude(id__in=s)
if deselect.count() > 0:
deselect.update(selected=False)
@@ -771,6 +775,10 @@ class Item(models.Model):
if s.filter(selected=False).count() > 0:
s.update(selected=True, wanted=False)
update = True
+ for f in s:
+ if f.get_part() != f.part:
+ f.save()
+ update = True
if update:
self.rendered = False
self.save()
diff --git a/pandora/item/views.py b/pandora/item/views.py
index 10d27363..745a8e56 100644
--- a/pandora/item/views.py
+++ b/pandora/item/views.py
@@ -326,6 +326,38 @@ def autocomplete(request):
return render_to_json_response(response)
actions.register(autocomplete)
+def findId(request):
+ '''
+ param data {
+ 'query': query,
+ 'sort': array,
+ 'range': array
+ }
+
+ '''
+ data = json.loads(request.POST['data'])
+ response = json_response({})
+ response['data']['items'] = []
+ '''
+ FIXME: can not handle query for director []
+ query = parse_query(data, request.user)
+ qs = _order_query(query['qs'], query['sort'])
+ if qs.count() == 1:
+ response['data']['items'] = [i.get_json(data['keys']) for i in qs]
+ elif settings.DATA_SERVICE:
+ '''
+ if settings.DATA_SERVICE:
+ '''
+ info = {}
+ for c in data['query']['conditions']:
+ info[c['key']] = c['value']
+ r = models.external_data('getId', info)
+ '''
+ r = models.external_data('getId', data)
+ if r['status']['code'] == 200:
+ response['data']['items'] = [r['data']]
+ return render_to_json_response(response)
+actions.register(findId)
def get(request):
'''
diff --git a/static/js/pandora/ui/filesView.js b/static/js/pandora/ui/filesView.js
index 16140b9b..bd307b56 100644
--- a/static/js/pandora/ui/filesView.js
+++ b/static/js/pandora/ui/filesView.js
@@ -45,13 +45,36 @@ pandora.ui.filesView = function(options, self) {
self.$filesList = Ox.TextList({
columns: [
+ {
+ format: function(value, data) {
+ Ox.print('File', value, data.wanted, data);
+ return $('')
+ .attr({
+ src: data.wanted ? Ox.UI.getImageURL('symbolStar') :
+ Ox.UI.getImageURL('symbolCheck')
+ })
+ .css({
+ width: '10px',
+ height: '10px',
+ padding: '3px',
+ opacity: (value || data.wanted) ? 1 : 0
+ });
+ },
+ id: 'selected',
+ operator: '-',
+ title: $('').attr({
+ src: Ox.UI.getImageURL('symbolCheck')
+ }),
+ visible: true,
+ width: 16
+ },
{
align: 'left',
id: 'users',
operator: '+',
title: 'Users',
visible: true,
- width: 120
+ width: 50
},
{
align: 'left',
@@ -133,11 +156,12 @@ pandora.ui.filesView = function(options, self) {
conditions: [{
key: 'id',
value: self.options.id,
- operator: '='
+ operator: '=='
}]
}
}), callback);
},
+ keys: ['wanted'],
scrollbarVisible: true,
sort: [{key: 'path', operator: '+'}]
})
@@ -202,13 +226,14 @@ pandora.ui.filesView = function(options, self) {
change: function(data) {
var conditions;
if (data.value.length) {
+ /*
if (key == 'id') {
- conditions = [{key: 'id', value: data.value, operator: '='}]
+ conditions = [{key: 'id', value: data.value, operator: '=='}]
} else {
conditions = Ox.map(['title', 'director', 'year'], function(key) {
var value = self['$' + key + 'Input'].options('value')
return value.length ? {key: key, value: value, operator: '='} : null;
- })
+ });
}
pandora.api.find({
keys: ['title', 'director', 'year', 'id'],
@@ -218,6 +243,15 @@ pandora.ui.filesView = function(options, self) {
},
range: [0, 2]
}, function(result) {
+ */
+ conditions = {};
+ Ox.map(['id', 'title', 'director', 'year'], function(key) {
+ var value = self['$' + key + 'Input'].options('value');
+ if(value.length) {
+ conditions[key] = value;
+ }
+ });
+ pandora.api.findId(conditions, function(result) {
var length = result.data.items.length;
if (length == 0) {
if (key != 'id') {
@@ -234,7 +268,7 @@ pandora.ui.filesView = function(options, self) {
} else {
self.$idInput.options({value: ''});
}
- })
+ });
}
}
});
@@ -345,6 +379,7 @@ pandora.ui.filesView = function(options, self) {
}
});
updateForm();
+ self.$titleInput.triggerEvent('change', {value: result.data['title']});
});
}
From 1c33fea5bb89a3a62d2345606df19d14d667f714 Mon Sep 17 00:00:00 2001
From: j <0x006A@0x2620.org>
Date: Tue, 18 Oct 2011 22:30:32 +0200
Subject: [PATCH 2/5] part bug
---
pandora/archive/models.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pandora/archive/models.py b/pandora/archive/models.py
index 37552ee9..f6199e8e 100644
--- a/pandora/archive/models.py
+++ b/pandora/archive/models.py
@@ -295,7 +295,7 @@ class File(models.Model):
qs = self.item.files.filter(Q(is_video=True)|Q(is_audio=True),
selected=True, path__startswith=name)
if qs.count()>0:
- return qs[0].part
+ return qs[0].get_part()
if self.selected:
files = list(self.item.files.filter(type=self.type, language=self.language,
selected=self.selected).order_by('sort_path'))
From 764e992fcc92cf5c70cdb4b49da32ab087713f3d Mon Sep 17 00:00:00 2001
From: j <0x006A@0x2620.org>
Date: Tue, 18 Oct 2011 23:02:30 +0200
Subject: [PATCH 3/5] status
---
static/js/pandora/ui/status.js | 28 +++++++++++++++++++---------
1 file changed, 19 insertions(+), 9 deletions(-)
diff --git a/static/js/pandora/ui/status.js b/static/js/pandora/ui/status.js
index 0367e10b..1c80e082 100644
--- a/static/js/pandora/ui/status.js
+++ b/static/js/pandora/ui/status.js
@@ -1,13 +1,23 @@
// vim: et:ts=4:sw=4:sts=4:ft=javascript
pandora.ui.status = function(key, data) {
- var that = Ox.toTitleCase(key) + ': ' + [
- Ox.formatNumber(data.items) + ' '+ (data.items != 1 ? pandora.site.itemName.plural : pandora.site.itemName.singular),
- Ox.formatDuration(data.runtime, 'short'),
- data.files + ' file' + (data.files != 1 ? 's' : ''),
- Ox.formatDuration(data.duration),
- Ox.formatValue(data.size, 'B'),
- Ox.formatValue(data.pixels, 'px')
- ].join(', ');
- return that;
+ var itemName = data.items != 1 ? pandora.site.itemName.plural : pandora.site.itemName.singular,
+ segments = [],
+ that = Ox.toTitleCase(key) + ': ';
+ if (!pandora.user.ui.item && pandora.user.ui.listView == 'clip') {
+ itemName = data.items != 1 ? 'Clips' : 'Clip';
+ }
+
+ segments.push(Ox.formatNumber(data.items) + ' '+ itemName);
+ if (data.runtime)
+ segments.push(Ox.formatDuration(data.runtime, 'short'));
+ if (data.files)
+ segments.push(data.files + ' file' + (data.files != 1 ? 's' : ''));
+ if (data.duration)
+ segments.push(Ox.formatDuration(data.duration));
+ if (data.size)
+ segments.push(Ox.formatValue(data.size, 'B'));
+ if (data.pixels)
+ segments.push(Ox.formatValue(data.pixels, 'px'));
+ return that + segments.join(', ');
};
From 24f94a092ec50e9f333083a95337f8413be9ac01 Mon Sep 17 00:00:00 2001
From: j <0x006A@0x2620.org>
Date: Tue, 18 Oct 2011 23:28:58 +0200
Subject: [PATCH 4/5] email
---
pandora/user/models.py | 7 +------
1 file changed, 1 insertion(+), 6 deletions(-)
diff --git a/pandora/user/models.py b/pandora/user/models.py
index c1128eb0..3797c69b 100644
--- a/pandora/user/models.py
+++ b/pandora/user/models.py
@@ -33,11 +33,6 @@ class UserProfile(models.Model):
info = DictField(default={})
notes = models.TextField(default='')
- def get_preferences(self):
- prefs = self.preferences
- prefs['email'] = self.user.email
- return prefs
-
def get_ui(self):
return get_ui(self.ui, self.user)
@@ -154,7 +149,7 @@ def init_user(user, request=None):
result[key] = getattr(user, key)
result['level'] = profile.get_level()
result['groups'] = [g.name for g in user.groups.all()]
- result['preferences'] = profile.get_preferences()
+ result['email'] = user.email
result['ui'] = profile.get_ui()
result['volumes'] = [v.json() for v in user.volumes.all()]
return result
From 45bb18ef9658704f21d310b0e652152c73707ed9 Mon Sep 17 00:00:00 2001
From: j <0x006A@0x2620.org>
Date: Tue, 18 Oct 2011 23:41:54 +0200
Subject: [PATCH 5/5] editPreferences
---
pandora/user/views.py | 35 ++++++++++++++++++++---------------
1 file changed, 20 insertions(+), 15 deletions(-)
diff --git a/pandora/user/views.py b/pandora/user/views.py
index 524e5e1b..8737a4af 100644
--- a/pandora/user/views.py
+++ b/pandora/user/views.py
@@ -577,29 +577,34 @@ def getPositionById(list, key):
@login_required_json
-def setPreferences(request):
+def editPreferences(request):
'''
param data {
- key.subkey: value
+ key: value
}
+ keys: email, password
return
'''
data = json.loads(request.POST['data'])
- keys = re.sub('([^\\\\])\.', '\\1\n', data.keys()[0]).split('\n')
- value = data.values()[0]
- profile = request.user.get_profile()
- p = profile.preferences
- while len(keys)>1:
- key = keys.pop(0)
- if isinstance(p, list):
- p = p[getPositionById(p, key)]
- else:
- p = p[key]
- p[keys[0]] = value
- profile.save()
+ errors = {}
+ change = False
response = json_response()
+ if 'email' in data:
+ if models.User.objects.filter(
+ email=data['email']).exclude(username=request.user.username).count()>0:
+ errors['email'] = 'Email address already in use'
+ else:
+ change = True
+ request.user.email = data['email']
+ if 'password' in data:
+ change = True
+ request.user.password = data['password']
+ if change:
+ request.user.save()
+ if errors:
+ response = json_response({ 'errors': errors})
return render_to_json_response(response)
-actions.register(setPreferences, cache=False)
+actions.register(editPreferences, cache=False)
def resetUI(request):