rendered, editFile

This commit is contained in:
j 2011-06-27 15:39:35 +02:00
parent b2d5f189e3
commit e60868843f
10 changed files with 66 additions and 36 deletions

View File

@ -20,13 +20,14 @@ import chardet
from item import utils from item import utils
from item.models import Item from item.models import Item
from person.models import get_name_sort from person.models import get_name_sort
from annotation.models import Annotation, Layer
class File(models.Model): class File(models.Model):
created = models.DateTimeField(auto_now_add=True) created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True) modified = models.DateTimeField(auto_now=True)
verified = models.BooleanField(default=False) verified = models.BooleanField(default=False)
auto = models.BooleanField(default=True)
oshash = models.CharField(max_length=16, unique=True) oshash = models.CharField(max_length=16, unique=True)
item = models.ForeignKey(Item, related_name='files') item = models.ForeignKey(Item, related_name='files')
@ -75,7 +76,7 @@ class File(models.Model):
def __unicode__(self): def __unicode__(self):
return self.name return self.name
def save(self, *args, **kwargs): def set_state(self):
instance = self.get_instance() instance = self.get_instance()
if instance: if instance:
if instance.name.lower().startswith('extras/'): if instance.name.lower().startswith('extras/'):
@ -152,6 +153,10 @@ class File(models.Model):
if self.type not in ('audio', 'video'): if self.type not in ('audio', 'video'):
self.duration = None self.duration = None
def save(self, *args, **kwargs):
if self.auto:
self.set_state()
super(File, self).save(*args, **kwargs) super(File, self).save(*args, **kwargs)
#upload and data handling #upload and data handling
@ -268,7 +273,7 @@ class File(models.Model):
'height': self.height, 'height': self.height,
'width': self.width, 'width': self.width,
'resolution': resolution, 'resolution': resolution,
'oshash': self.oshash, 'id': self.oshash,
'samplerate': self.samplerate, 'samplerate': self.samplerate,
'video_codec': self.video_codec, 'video_codec': self.video_codec,
'audio_codec': self.audio_codec, 'audio_codec': self.audio_codec,

View File

@ -119,7 +119,7 @@ actions.register(encodingProfile)
@login_required_json @login_required_json
def upload(request): def upload(request):
''' '''
oshash: string id: string
frame: [] //multipart frames frame: [] //multipart frames
file: [] //multipart file file: [] //multipart file
@ -132,7 +132,7 @@ def upload(request):
} }
''' '''
response = json_response({}) response = json_response({})
f = get_object_or_404_json(models.File, oshash=request.POST['oshash']) f = get_object_or_404_json(models.File, oshash=request.POST['id'])
if 'frame' in request.FILES: if 'frame' in request.FILES:
if f.frames.count() == 0: if f.frames.count() == 0:
for frame in request.FILES.getlist('frame'): for frame in request.FILES.getlist('frame'):
@ -164,7 +164,7 @@ class VideoChunkForm(forms.Form):
@login_required_json @login_required_json
def firefogg_upload(request): def firefogg_upload(request):
profile = request.GET['profile'] profile = request.GET['profile']
oshash = request.GET['oshash'] oshash = request.GET['id']
#handle video upload #handle video upload
if request.method == 'POST': if request.method == 'POST':
#post next chunk #post next chunk
@ -203,7 +203,7 @@ def firefogg_upload(request):
f.save() f.save()
response = { response = {
#is it possible to no hardcode url here? #is it possible to no hardcode url here?
'uploadUrl': request.build_absolute_uri('/api/upload/?oshash=%s&profile=%s' % (f.oshash, profile)), 'uploadUrl': request.build_absolute_uri('/api/upload/?id=%s&profile=%s' % (f.oshash, profile)),
'result': 1 'result': 1
} }
return render_to_json_response(response) return render_to_json_response(response)
@ -221,6 +221,7 @@ def taskStatus(request):
return render_to_json_response(response) return render_to_json_response(response)
actions.register(taskStatus, cache=False) actions.register(taskStatus, cache=False)
@login_required_json @login_required_json
def moveFiles(request): def moveFiles(request):
''' '''
@ -253,37 +254,34 @@ def moveFiles(request):
return render_to_json_response(response) return render_to_json_response(response)
actions.register(moveFiles, cache=False) actions.register(moveFiles, cache=False)
@login_required_json @login_required_json
def editFile(request): def editFile(request):
''' '''
change file / item link change file / item link
param data { param data {
oshash: hash of file id: hash of file
itemId: new itemId part:
id_extra: boolean
} }
return { return {
status: {'code': int, 'text': string}, status: {'code': int, 'text': string},
data: { data: {
imdbId:string
} }
} }
''' '''
#FIXME: permissions, need to be checked #FIXME: permissions, need to be checked
data = json.loads(request.POST['data']) data = json.loads(request.POST['data'])
f = get_object_or_404_json(models.File, oshash=data['oshash']) f = get_object_or_404_json(models.File, oshash=data['id'])
response = json_response() response = json_response()
if f.item.id != data['itemId']: if data.keys() != ('id', ):
if len(data['itemId']) != 7: for key in data:
folder = f.instances.all()[0].folder if key in ('is_extra', 'is_subtitle', 'is_video', 'is_version',
item_info = utils.parse_path(folder) 'part', 'language'):
item = get_item(item_info) setattr(f, key, data[key])
else: f.auto = False
item = get_item({'imdbId': data['itemId']})
f.item = item
f.save() f.save()
#FIXME: other things might need updating here
response = json_response(text='updated')
return render_to_json_response(response) return render_to_json_response(response)
actions.register(editFile, cache=False) actions.register(editFile, cache=False)

View File

@ -8,7 +8,7 @@ import models
class ItemAdmin(admin.ModelAdmin): class ItemAdmin(admin.ModelAdmin):
search_fields = ['itemId', 'data', 'external_data'] search_fields = ['itemId', 'data', 'external_data']
list_display = ['available', 'itemId', '__unicode__'] list_display = ['rendered', 'itemId', '__unicode__']
list_display_links = ('__unicode__', ) list_display_links = ('__unicode__', )
admin.site.register(models.Item, ItemAdmin) admin.site.register(models.Item, ItemAdmin)

View File

@ -239,7 +239,6 @@ class ItemManager(Manager):
#join query with operator #join query with operator
qs = self.get_query_set() qs = self.get_query_set()
#only include items that have hard metadata #only include items that have hard metadata
qs = qs.filter(available=True)
conditions = parseConditions(data.get('query', {}).get('conditions', []), conditions = parseConditions(data.get('query', {}).get('conditions', []),
data.get('query', {}).get('operator', '&')) data.get('query', {}).get('operator', '&'))
qs = qs.filter(conditions).distinct() qs = qs.filter(conditions).distinct()

View File

@ -100,9 +100,8 @@ class Item(models.Model):
user = models.ForeignKey(User, null=True, related_name='items') user = models.ForeignKey(User, null=True, related_name='items')
groups = models.ManyToManyField(Group, blank=True, related_name='items') groups = models.ManyToManyField(Group, blank=True, related_name='items')
#only items that have data from files are available, #while metadata is updated, files are set to rendered=False
#this is indicated by setting available to True rendered = models.BooleanField(default=False, db_index=True)
available = models.BooleanField(default=False, db_index=True)
public = models.BooleanField(default=False, db_index=True) public = models.BooleanField(default=False, db_index=True)
itemId = models.CharField(max_length=128, unique=True, blank=True) itemId = models.CharField(max_length=128, unique=True, blank=True)
@ -133,7 +132,7 @@ class Item(models.Model):
return default return default
def access(self, user): def access(self, user):
if self.public and self.available: if self.public:
return True return True
elif user.is_authenticated() and \ elif user.is_authenticated() and \
(user.is_staff or self.user == user or \ (user.is_staff or self.user == user or \
@ -333,7 +332,8 @@ class Item(models.Model):
def get_json(self, fields=None): def get_json(self, fields=None):
i = { i = {
'id': self.itemId 'id': self.itemId,
'rendered': self.rendered
} }
i.update(self.external_data) i.update(self.external_data)
i.update(self.data) i.update(self.data)
@ -526,7 +526,7 @@ class Item(models.Model):
s.volume = None s.volume = None
if 'color' in self.data: if 'color' in self.data:
s.hue, s.saturation, s.brightness = self.data['color'] s.hue, s.saturation, s.lightness = self.data['color']
else: else:
s.hue = None s.hue = None
s.saturation = None s.saturation = None
@ -657,7 +657,7 @@ class Item(models.Model):
self.make_local_posters() self.make_local_posters()
self.make_poster() self.make_poster()
self.make_icon() self.make_icon()
self.available = True self.rendered = True
self.save() self.save()
''' '''

View File

@ -553,7 +553,9 @@ def poster(request, id, size=None):
if not size: if not size:
size='large' size='large'
poster_path = os.path.join(settings.STATIC_ROOT, 'png/posterDark.48.png') poster_path = os.path.join(settings.STATIC_ROOT, 'png/posterDark.48.png')
return HttpFileResponse(poster_path, content_type='image/jpeg') response = HttpFileResponse(poster_path, content_type='image/jpeg')
response['Cache-Control'] = 'no-cache'
return response
def icon(request, id, size=None): def icon(request, id, size=None):

View File

@ -3,6 +3,7 @@
-e bzr+http://code.0x2620.org/python-ox/#egg=python-ox -e bzr+http://code.0x2620.org/python-ox/#egg=python-ox
-e bzr+http://code.0x2620.org/oxtimeline/#egg=oxtimeline -e bzr+http://code.0x2620.org/oxtimeline/#egg=oxtimeline
simplejson simplejson
chardet
-e hg+https://django-ajax-filtered-fields.googlecode.com/hg/#egg=django-ajax-filtered-fields -e hg+https://django-ajax-filtered-fields.googlecode.com/hg/#egg=django-ajax-filtered-fields
celery>2.1.1 celery>2.1.1
django-celery>2.1.1 django-celery>2.1.1

View File

@ -105,9 +105,9 @@ Ox.FilesView = function(options, self) {
}, },
{ {
align: 'left', align: 'left',
id: 'oshash', id: 'id',
operator: '+', operator: '+',
title: 'Hash', title: 'ID',
unique: true, unique: true,
visible: false, visible: false,
width: 120 width: 120

View File

@ -6,6 +6,14 @@ pandora.ui.item = function() {
pandora.$ui.contentPanel.replaceElement(1, pandora.$ui.contentPanel.replaceElement(1,
Ox.Element().html( Ox.Element().html(
'The '+pandora.site.itemName.singular+' you are looking for does not exist.')); 'The '+pandora.site.itemName.singular+' you are looking for does not exist.'));
} else if (!result.data.rendered &&
['clips', 'map',
'player', 'timeline'].indexOf(pandora.user.ui.itemView)>-1) {
pandora.$ui.contentPanel.replaceElement(1,
Ox.Element().css({margin: '16px'}).html(
'We are sorry, "' + result.data.title +
'" does not have a '+pandora.user.ui.itemView +
' view right now.'));
} else if (pandora.user.ui.itemView == 'calendar') { } else if (pandora.user.ui.itemView == 'calendar') {
pandora.$ui.contentPanel.replaceElement(1, Ox.Element().html('Calendar')); pandora.$ui.contentPanel.replaceElement(1, Ox.Element().html('Calendar'));
} else if (pandora.user.ui.itemView == 'clips') { } else if (pandora.user.ui.itemView == 'clips') {
@ -55,7 +63,7 @@ pandora.ui.item = function() {
var $form, var $form,
$edit = Ox.Element() $edit = Ox.Element()
.append($form = Ox.FormElementGroup({ .append($form = Ox.FormElementGroup({
elements: Ox.map(pandora.site.itemKeys, function(key) { elements: Ox.map(pandora.site.sortKeys, function(key) {
return Ox.Input({ return Ox.Input({
id: key.id, id: key.id,
label: key.title, label: key.title,
@ -228,7 +236,14 @@ pandora.ui.item = function() {
} }
})); }));
} else if (pandora.user.ui.itemView == 'statistics') { } else if (pandora.user.ui.itemView == 'statistics') {
pandora.$ui.contentPanel.replaceElement(1, Ox.Element().html('Statistics')); var stats = Ox.Container();
Ox.TreeList({
data: result.data,
width: 256
}).appendTo(stats);
pandora.$ui.contentPanel.replaceElement(1, stats);
} else if (pandora.user.ui.itemView == 'timeline') { } else if (pandora.user.ui.itemView == 'timeline') {
var layers = [], var layers = [],
video = result.data.stream, video = result.data.stream,

View File

@ -48,7 +48,7 @@ pandora.ui.list = function(view) { // fixme: remove view argument
}) })
.bindEvent({ .bindEvent({
columnchange: function(event, data) { columnchange: function(event, data) {
var columnWidth = {} var columnWidth = {};
pandora.UI.set(['lists', pandora.user.ui.list, 'columns'].join('|'), data.ids); pandora.UI.set(['lists', pandora.user.ui.list, 'columns'].join('|'), data.ids);
/* /*
data.ids.forEach(function(id) { data.ids.forEach(function(id) {
@ -95,6 +95,16 @@ pandora.ui.list = function(view) { // fixme: remove view argument
sort: pandora.user.ui.lists[pandora.user.ui.list].sort, sort: pandora.user.ui.lists[pandora.user.ui.list].sort,
unique: 'id' unique: 'id'
}); });
} else if (view == 'info') {
that = Ox.Element().css({margin: '16px'}).html(view + ' results view still missing.');
} else if (view == 'clips') {
that = Ox.Element().css({margin: '16px'}).html(view + ' results view still missing.');
} else if (view == 'timelines') {
that = Ox.Element().css({margin: '16px'}).html(view + ' results view still missing.');
} else if (view == 'maps') {
that = Ox.Element().css({margin: '16px'}).html(view + ' results view still missing.');
} else if (view == 'calendars') {
that = Ox.Element().css({margin: '16px'}).html(view + ' results view still missing.');
} else if (view == 'clip') { } else if (view == 'clip') {
that = Ox.IconList({ that = Ox.IconList({
item: function(data, sort, size) { item: function(data, sort, size) {