basic annotation based clips view

This commit is contained in:
j 2011-06-16 22:00:10 +02:00
parent 215e2be746
commit 1a075b6cb0
6 changed files with 174 additions and 37 deletions

View file

@ -101,7 +101,7 @@ class Annotation(models.Model):
def get_id(self): def get_id(self):
return ox.to32(self.id) return ox.to32(self.id)
def json(self, layer=False): def json(self, layer=False, keys=None):
j = { j = {
'id': self.get_id(), 'id': self.get_id(),
'user': self.user.username, 'user': self.user.username,
@ -113,6 +113,16 @@ class Annotation(models.Model):
} }
if layer: if layer:
j['layer'] = self.layer.name j['layer'] = self.layer.name
if keys:
_j = {}
for key in keys:
if key in j:
_j[key] = j[key]
j = _j
if 'aspectRatio' in keys:
j['aspectRatio'] = self.item.stream_aspect
if 'item' in keys:
j['item'] = self.item.itemId
return j return j
def __unicode__(self): def __unicode__(self):

View file

@ -12,13 +12,34 @@ from app.models import site_config
from item.models import Item from item.models import Item
from api.actions import actions from api.actions import actions
from item import utils
from item.models import Item
import models import models
def parse_query(data, user):
query = {}
query['range'] = [0, 100]
query['sort'] = [{'key':'in', 'operator':'+'}]
for key in ('value', 'layer', 'in', 'out'):
if key in data:
query[key] = data[key]
query['qs'] = models.Annotation.objects.all()
if 'itemQuery' in data:
item_query = Item.objects.find({'query': data['itemQuery']}, user)
query['qs'] = query['qs'].filter(item__in=item_query)
return query
def order_query(qs, sort):
qs = qs.order_by('start')
return qs
def findAnnotations(request): def findAnnotations(request):
''' '''
param data { param data {
fixme query: ...
itemQuery: ...
} }
return { return {
@ -28,11 +49,30 @@ def findAnnotations(request):
} }
} }
''' '''
#FIXME: implement findItem like queries
data = json.loads(request.POST['data']) data = json.loads(request.POST['data'])
response = json_response(status=200, text='ok') response = json_response()
qs = models.Annotations.objects.filter(item__itemId=data['item'])
response['data']['annotations'] = [a.json() for a in qs] query = parse_query(data, request.user)
qs = order_query(query['qs'], query['sort'])
if 'keys' in data:
qs = qs[query['range'][0]:query['range'][1]]
response['data']['items'] = [p.json(keys=data['keys']) for p in qs]
elif 'position' in query:
ids = [i.get_id() for i in qs]
data['conditions'] = data['conditions'] + {
'value': data['position'],
'key': query['sort'][0]['key'],
'operator': '^'
}
query = parse_query(data, request.user)
qs = order_query(query['qs'], query['sort'])
if qs.count() > 0:
response['data']['position'] = utils.get_positions(ids, [qs[0].itemId])[0]
elif 'positions' in data:
ids = [i.get_id() for i in qs]
response['data']['positions'] = utils.get_positions(ids, data['positions'])
else:
response['data']['items'] = qs.count()
return render_to_json_response(response) return render_to_json_response(response)
actions.register(findAnnotations) actions.register(findAnnotations)

View file

@ -124,7 +124,7 @@ def parse_query(data, user):
query = {} query = {}
query['range'] = [0, 100] query['range'] = [0, 100]
query['sort'] = [{'key':'name', 'operator':'+'}] query['sort'] = [{'key':'name', 'operator':'+'}]
for key in ('keys', 'group', 'list', 'range', 'position', 'positions', 'sort', 'query'): for key in ('keys', 'group', 'list', 'range', 'sort', 'query'):
if key in data: if key in data:
query[key] = data[key] query[key] = data[key]
query['qs'] = models.Place.objects.find(query, user) query['qs'] = models.Place.objects.find(query, user)
@ -231,7 +231,7 @@ Positions
elif 'position' in query: elif 'position' in query:
ids = [i.get_id() for i in qs] ids = [i.get_id() for i in qs]
data['conditions'] = data['conditions'] + { data['conditions'] = data['conditions'] + {
'value': query['position'], 'value': data['position'],
'key': query['sort'][0]['key'], 'key': query['sort'][0]['key'],
'operator': '^' 'operator': '^'
} }
@ -241,7 +241,7 @@ Positions
response['data']['position'] = utils.get_positions(ids, [qs[0].itemId])[0] response['data']['position'] = utils.get_positions(ids, [qs[0].itemId])[0]
elif 'positions' in data: elif 'positions' in data:
ids = [i.get_id() for i in qs] ids = [i.get_id() for i in qs]
response['data']['positions'] = utils.get_positions(ids, query['positions']) response['data']['positions'] = utils.get_positions(ids, data['positions'])
else: else:
response['data']['items'] = qs.count() response['data']['items'] = qs.count()
response['data']['area'] = qs.aggregate( response['data']['area'] = qs.aggregate(

View file

@ -1,4 +1,5 @@
// vim: et:ts=4:sw=4:sts=4:ft=js // vim: et:ts=4:sw=4:sts=4:ft=js
pandora.enterFullscreen = function() { pandora.enterFullscreen = function() {
pandora.$ui.appPanel.size(0, 0); pandora.$ui.appPanel.size(0, 0);
pandora.user.ui.showSidebar && pandora.$ui.mainPanel.size(0, 0); pandora.user.ui.showSidebar && pandora.$ui.mainPanel.size(0, 0);
@ -10,8 +11,8 @@ pandora.enterFullscreen = function() {
pandora.$ui.player.options({ pandora.$ui.player.options({
height: pandora.$document.height() - 2, height: pandora.$document.height() - 2,
width: pandora.$document.width() - 2 width: pandora.$document.width() - 2
}) });
} };
pandora.exitFullscreen = function() { pandora.exitFullscreen = function() {
pandora.$ui.appPanel.size(0, 20); pandora.$ui.appPanel.size(0, 20);
@ -21,14 +22,15 @@ pandora.exitFullscreen = function() {
top: 24 + (-112 - Ox.UI.SCROLLBAR_SIZE) + 'px' // fixme: rightPanel.size(0, 0) doesn't preserve negative top of browser top: 24 + (-112 - Ox.UI.SCROLLBAR_SIZE) + 'px' // fixme: rightPanel.size(0, 0) doesn't preserve negative top of browser
}); });
pandora.user.ui.showMovies && pandora.$ui.contentPanel.size(0, 112 + Ox.UI.SCROLLBAR_SIZE); pandora.user.ui.showMovies && pandora.$ui.contentPanel.size(0, 112 + Ox.UI.SCROLLBAR_SIZE);
} };
pandora.getFoldersHeight = function() { pandora.getFoldersHeight = function() {
var height = 48; var height = 48;
pandora.site.sectionFolders[pandora.user.ui.section].forEach(function(folder, i) { pandora.site.sectionFolders[pandora.user.ui.section].forEach(function(folder, i) {
height += pandora.user.ui.showFolder[pandora.user.ui.section][folder.id] * ( height += pandora.user.ui.showFolder[pandora.user.ui.section][folder.id] * (
!!folder.showBrowser * 40 + folder.items * 16 !!folder.showBrowser * 40 + folder.items * 16
); );
Ox.print('h', height) Ox.print('h', height);
}); });
/* /*
$.each(pandora.user.ui.showFolder[pandora.user.ui.section], function(id, show) { $.each(pandora.user.ui.showFolder[pandora.user.ui.section], function(id, show) {
@ -40,53 +42,80 @@ pandora.getFoldersHeight = function() {
}); });
*/ */
return height; return height;
} };
pandora.getFoldersWidth = function() { pandora.getFoldersWidth = function() {
var width = pandora.user.ui.sidebarSize; var width = pandora.user.ui.sidebarSize;
// fixme: don't use height(), look up in splitpanels // fixme: don't use height(), look up in splitpanels
Ox.print(pandora.getFoldersHeight(), '>', pandora.$ui.leftPanel.height() - 24 - 1 - pandora.$ui.info.height()) Ox.print(pandora.getFoldersHeight(), '>', pandora.$ui.leftPanel.height() - 24 - 1 - pandora.$ui.info.height());
if (pandora.getFoldersHeight() > pandora.$ui.leftPanel.height() - 24 - 1 - pandora.$ui.info.height()) { if (pandora.getFoldersHeight() > pandora.$ui.leftPanel.height() - 24 - 1 - pandora.$ui.info.height()) {
width -= Ox.UI.SCROLLBAR_SIZE; width -= Ox.UI.SCROLLBAR_SIZE;
} }
return width; return width;
} };
pandora.getGroupWidth = function(pos, panelWidth) { // fixme: don't pass panelWidth pandora.getGroupWidth = function(pos, panelWidth) { // fixme: don't pass panelWidth
var width = {}; var width = {};
width.list = Math.floor(panelWidth / 5) + (panelWidth % 5 > pos); width.list = Math.floor(panelWidth / 5) + (panelWidth % 5 > pos);
width.column = width.list - 40 - Ox.UI.SCROLLBAR_SIZE; width.column = width.list - 40 - Ox.UI.SCROLLBAR_SIZE;
return width; return width;
} };
pandora.getSortOperator = function(key) { // fixme: make static pandora.getSortOperator = function(key) { // fixme: make static
var type = Ox.getObjectById(pandora.site.itemKeys, key).type; var type = Ox.getObjectById(pandora.site.itemKeys, key).type;
return ['hue', 'string', 'text'].indexOf( return ['hue', 'string', 'text'].indexOf(
Ox.isArray(type) ? type[0] : type Ox.isArray(type) ? type[0] : type
) > -1 ? '+' : '-'; ) > -1 ? '+' : '-';
} };
pandora.login = function(data) { pandora.login = function(data) {
pandora.user = data.user; pandora.user = data.user;
Ox.Theme(pandora.user.ui.theme); Ox.Theme(pandora.user.ui.theme);
pandora.$ui.appPanel.reload(); pandora.$ui.appPanel.reload();
} };
pandora.logout = function(data) { pandora.logout = function(data) {
pandora.user = data.user; pandora.user = data.user;
Ox.Theme(pandora.site.user.ui.theme); Ox.Theme(pandora.site.user.ui.theme);
pandora.$ui.appPanel.reload(); pandora.$ui.appPanel.reload();
} };
pandora.reloadGroups = function(i) { pandora.reloadGroups = function(i) {
var query = pandora.Query.toObject(); var query = pandora.Query.toObject(),
pandora.$ui.list.options({ view = pandora.user.ui.lists[pandora.user.ui.list].listView;
items: function(data, callback) { if(view == 'clip') {
return pandora.api.find($.extend(data, { pandora.$ui.list.options({
query: query items: function(data, callback) {
}), callback); return pandora.api.findAnnotations($.extend(data, {
} itemQuery: query
}); }), callback);
}
});
} else if (view == 'map') {
pandora.$ui.list.options({
items: function(data, callback) {
return pandora.api.findPlaces($.extend(data, {
itemQuery: query
}), callback);
}
});
} else if (view == 'calendar') {
pandora.$ui.list.options({
items: function(data, callback) {
return pandora.api.findEvents($.extend(data, {
itemQuery: query
}), callback);
}
});
} else {
pandora.$ui.list.options({
items: function(data, callback) {
return pandora.api.find($.extend(data, {
query: query
}), callback);
}
});
}
$.each(pandora.user.queryGroups, function(i_, group_) { $.each(pandora.user.queryGroups, function(i_, group_) {
if (i_ != i) { if (i_ != i) {
//Ox.print('setting groups request', i, i_) //Ox.print('setting groups request', i, i_)
@ -135,7 +164,7 @@ pandora.reloadList = function() {
} }
}) })
.reloadList(); .reloadList();
} };
pandora.resizeGroups = function(width) { pandora.resizeGroups = function(width) {
var widths = $.map(pandora.user.queryGroups, function(v, i) { var widths = $.map(pandora.user.queryGroups, function(v, i) {
@ -147,7 +176,7 @@ pandora.resizeGroups = function(width) {
$.each(pandora.$ui.groups, function(i, list) { $.each(pandora.$ui.groups, function(i, list) {
list.resizeColumn('name', widths[i].column); list.resizeColumn('name', widths[i].column);
}); });
} };
pandora.resizeFolders = function() { pandora.resizeFolders = function() {
var width = pandora.getFoldersWidth(), var width = pandora.getFoldersWidth(),
@ -178,11 +207,11 @@ pandora.resizeFolders = function() {
pandora.$ui.folder[i].update(); pandora.$ui.folder[i].update();
} }
}); });
} };
pandora.saveVideoPosition = function() { pandora.saveVideoPosition = function() {
//alert(JSON.stringify(['videoPosition|' + old.user.ui.item, pandora.$ui[old.user.ui.itemView == 'player' ? 'player' : 'editor'].options('position')])); //alert(JSON.stringify(['videoPosition|' + old.user.ui.item, pandora.$ui[old.user.ui.itemView == 'player' ? 'player' : 'editor'].options('position')]));
} };
pandora.selectList = function() { pandora.selectList = function() {
if (pandora.user.ui.list) { if (pandora.user.ui.list) {
@ -208,7 +237,7 @@ pandora.selectList = function() {
//pandora.user.ui.listQuery.conditions = []; // fixme: Query should read from pandora.ui.list, and not need pandora.ui.listQuery to be reset //pandora.user.ui.listQuery.conditions = []; // fixme: Query should read from pandora.ui.list, and not need pandora.ui.listQuery to be reset
//pandora.URL.set(pandora.Query.toString()); //pandora.URL.set(pandora.Query.toString());
} }
}) });
} }
} };

View file

@ -9,7 +9,38 @@ pandora.ui.item = function() {
} 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') {
pandora.$ui.contentPanel.replaceElement(1, Ox.Element().html('Clips')); pandora.$ui.contentPanel.replaceElement(1, new Ox.IconList({
item: function(data, sort, size) {
size = size || 128;
var ratio = result.data.stream.aspectRatio,
width = ratio>1?size:size*ratio,
height = ratio>1?size/ratio:size,
url = '/' + pandora.user.ui.item + '/frame/' + size + '/' + data['in'] + '.jpg';
return {
height: height,
id: data['id'],
info: Ox.formatDuration(data['in'], 'short') +' - '+ Ox.formatDuration(data['out'], 'short'),
title: data.value,
url: url,
width: width
};
},
items: function(data, callback) {
pandora.api.findAnnotations($.extend(data, {
itemQuery: {
conditions:[{
key: 'id',
value: pandora.user.ui.item,
operator: '='
}]
}
}), callback);
},
keys: ['id', 'value', 'in', 'out'],
size: 128,
sort: pandora.user.ui.lists[pandora.user.ui.list].sort,
unique: 'id'
}));
} else if (pandora.user.ui.itemView == 'info') { } else if (pandora.user.ui.itemView == 'info') {
//Ox.print('result.data', result.data) //Ox.print('result.data', result.data)
if (pandora.user.level == 'admin') { if (pandora.user.level == 'admin') {

View file

@ -94,7 +94,34 @@ pandora.ui.list = function(view) { // fixme: remove view argument
size: 128, size: 128,
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 == 'clip') {
that = new Ox.IconList({
item: function(data, sort, size) {
size = size || 128;
var ratio = data.aspectRatio,
width = size,
height = size/ratio,
url = '/' + data.item + '/frame/' + size + '/'+data['in'] + '.jpg';
return {
height: height,
id: data['id'],
info: Ox.formatDuration(data['in'], 'short') +' - '+ Ox.formatDuration(data['out'], 'short'),
title: data.value,
url: url,
width: width
};
},
items: function(data, callback) {
pandora.api.findAnnotations($.extend(data, {
itemQuery: pandora.Query.toObject()
}), callback);
},
keys: ['id', 'value', 'in', 'out', 'aspectRatio', 'item'],
size: 128,
sort: pandora.user.ui.lists[pandora.user.ui.list].sort,
unique: 'id'
});
} else if (view == 'map') { } else if (view == 'map') {
that = new Ox.SplitPanel({ that = new Ox.SplitPanel({
elements: [ elements: [
@ -178,7 +205,7 @@ pandora.ui.list = function(view) { // fixme: remove view argument
pandora.$ui.folderList.forEach(function($list, i) { pandora.$ui.folderList.forEach(function($list, i) {
$list.removeClass('OxDrop'); $list.removeClass('OxDrop');
}); });
}, }
}).bindEvent({ }).bindEvent({
closepreview: function(event, data) { closepreview: function(event, data) {
pandora.$ui.previewDialog.close(); pandora.$ui.previewDialog.close();