diff --git a/pandora/item/managers.py b/pandora/item/managers.py
index c641c832a..7fb32b8fa 100644
--- a/pandora/item/managers.py
+++ b/pandora/item/managers.py
@@ -87,12 +87,13 @@ def parseCondition(condition):
if len(l) == 2:
lqs = List.objects.filter(name=l[1], user__username=l[0])
if lqs.count() == 1:
- if lqs[0].query.get('static', False) == False:
- data = lqs[0].query
- q = parseConditions(data['conditions'],
+ l = lqs[0]
+ if l.query.get('static', False) == False:
+ data = l.query
+ q = parseConditions(data.get('conditions', []),
data.get('operator', '&'))
else:
- q = Q(id__in=lqs[0].items.all())
+ q = Q(id__in=l.items.all())
return q
else: #number or date
@@ -237,7 +238,7 @@ class ItemManager(Manager):
qs = self.get_query_set()
#only include items that have hard metadata
qs = qs.filter(available=True)
- conditions = parseConditions(data['query']['conditions'],
+ conditions = parseConditions(data['query'].get('conditions', []),
data['query'].get('operator', '&'))
if conditions:
qs = qs.filter(conditions)
diff --git a/pandora/item/utils.py b/pandora/item/utils.py
index 9812bbaad..90ffda7c9 100644
--- a/pandora/item/utils.py
+++ b/pandora/item/utils.py
@@ -206,3 +206,16 @@ def sort_title(title):
#pad numbered titles
title = re.sub('(\d+)', lambda x: '%010d' % int(x.group(0)), title)
return title.strip()
+
+def get_positions(ids, pos):
+ '''
+ >>> get_positions([1,2,3,4], [2,4])
+ {2: 1, 4: 3}
+ '''
+ positions = {}
+ for i in pos:
+ try:
+ positions[i] = ids.index(i)
+ except:
+ pass
+ return positions
diff --git a/pandora/item/views.py b/pandora/item/views.py
index 24cbdcf42..7643adb2d 100644
--- a/pandora/item/views.py
+++ b/pandora/item/views.py
@@ -70,16 +70,6 @@ def _parse_query(data, user):
return query
-def _get_positions(ids, get_ids):
- positions = {}
- for i in get_ids:
- try:
- positions[i] = ids.index(i)
- except:
- pass
- return positions
-
-
def find(request):
'''
param data {
@@ -184,7 +174,7 @@ Positions
#FIXME: this does not scale for larger results
response['data']['positions'] = {}
ids = [j['value'] for j in qs]
- response['data']['positions'] = _get_positions(ids, query['ids'])
+ response['data']['positions'] = utils.get_positions(ids, query['ids'])
elif 'range' in data:
qs = qs[query['range'][0]:query['range'][1]]
diff --git a/pandora/itemlist/models.py b/pandora/itemlist/models.py
index 083f899df..a3b7b2c97 100644
--- a/pandora/itemlist/models.py
+++ b/pandora/itemlist/models.py
@@ -25,6 +25,7 @@ class List(models.Model):
query = DictField(default={"static": True})
type= models.CharField(max_length=255, default='static')
+ #is through table still required?
items = models.ManyToManyField('item.Item', related_name='lists',
through='ListItem')
diff --git a/pandora/itemlist/views.py b/pandora/itemlist/views.py
index b17e70c48..293dc4ca6 100644
--- a/pandora/itemlist/views.py
+++ b/pandora/itemlist/views.py
@@ -2,12 +2,14 @@
# vi:si:et:sw=4:sts=4:ts=4
from __future__ import division
+from django.db.models import Max
from ox.utils import json
from ox.django.decorators import login_required_json
from ox.django.shortcuts import render_to_json_response, get_object_or_404_json, json_response
import models
from api.actions import actions
+from item import utils
def get_list_or_404_json(id):
@@ -31,17 +33,15 @@ def _parse_query(data, user):
query = {}
query['range'] = [0, 100]
query['sort'] = [{'key':'user', 'operator':'+'}, {'key':'name', 'operator':'+'}]
- #query['sort'] = [{'key':'position__position', 'operator':'+'}]
- query['sort'] = [{'key':'name', 'operator':'+'}]
for key in ('keys', 'group', 'list', 'range', 'ids', 'sort'):
if key in data:
query[key] = data[key]
query['qs'] = models.List.objects.find(data, user)
return query
+
def findLists(request):
'''
- FIXME: support key: subscribed
param data {
query: {
conditions: [
@@ -78,12 +78,17 @@ def findLists(request):
#order
is_section_request = query['sort'] == [{u'operator': u'+', u'key': u'position'}]
- is_featured = len(filter(lambda x: x['key'] == 'status' and x['value'] == 'featured' and x['operator'] == '=', data['query'].get('conditions', []))) > 0
+ def is_featured_condition(x):
+ return x['key'] == 'status' and \
+ x['value'] == 'featured' and \
+ x['operator'] == '='
+ is_featured = len(filter(is_featured_condition, data['query'].get('conditions', []))) > 0
if is_section_request:
qs = query['qs']
if not is_featured:
- qs = qs.filter(position__in=models.Position.objects.filter(user=request.user))
+ if not request.user.is_anonymous():
+ qs = qs.filter(position__in=models.Position.objects.filter(user=request.user))
qs = qs.order_by('position__position')
else:
qs = _order_query(query['qs'], query['sort'])
@@ -94,6 +99,9 @@ def findLists(request):
qs = qs[query['range'][0]:query['range'][1]]
response['data']['items'] = [l.json(data['keys'], request.user) for l in qs]
+ elif 'ids' in data:
+ ids = [i.get_id() for i in qs]
+ response['data']['positions'] = utils.get_positions(ids, query['ids'])
else:
response['data']['items'] = qs.count()
return render_to_json_response(response)
@@ -105,7 +113,7 @@ def addListItem(request):
param data
{list: listId,
item: itemId,
- quert: ...
+ query: ...
}
return {
status: {'code': int, 'text': string},
@@ -124,7 +132,6 @@ def addListItem(request):
response = json_response(status=403, text='not allowed')
elif 'query' in data:
response = json_response(status=501, text='not implemented')
-
else:
response = json_response(status=501, text='not implemented')
return render_to_json_response(response)
@@ -168,7 +175,6 @@ def addList(request):
'''
param data {
name: value,
- position: int
}
return {
status: {'code': int, 'text': string},
@@ -185,9 +191,31 @@ def addList(request):
name = data['name'] + ' (%d)' % num
list = models.List(name = name, user=request.user)
list.save()
+ for key in data:
+ if key == 'query' and not data['query']:
+ setattr(list, key, {"static":True})
+ elif key == 'query':
+ setattr(list, key, data[key])
+ elif key == 'type':
+ if data[key] == 'static':
+ list.query = {"static":True}
+ list.type = 'static'
+ else:
+ list.type = 'dynamic'
+ if list.query.get('static', False):
+ list.query = {}
+ elif key == 'status':
+ value = data[key]
+ if value not in list._status:
+ value = list._status[0]
+ setattr(list, key, value)
+
+ list.save()
+
pos, created = models.Position.objects.get_or_create(list=list,
user=request.user, section='my')
- pos.position = data['position']
+ qs = models.Position.objects.filter(user=request.user, section='my')
+ pos.position = qs.aggregate(Max('position'))['position__max'] + 1
pos.save()
response = json_response(status=200, text='created')
response['data'] = list.json()
@@ -216,35 +244,35 @@ def editList(request):
if list.editable(request.user):
response = json_response()
for key in data:
- if key in ('name', 'status', 'query', 'type'):
- if key in data:
- if key == 'query' and not data['query']:
- setattr(list, key, {"static":True})
- elif key == 'type':
- if data[key] == 'static':
- list.query = {"static":True}
- list.type = 'static'
- else:
- list.type = 'dynamic'
- if list.query.get('static', False):
- list.query = {}
- elif key == 'status':
- value = data[key]
- if value not in list._status:
- value = list._status[0]
- setattr(list, key, value)
- if value == 'private':
- for user in list.subscribed_users.all():
- list.subscribed_users.remove(user)
- elif key == 'name':
- name = data['name']
- num = 1
- while models.List.objects.filter(name=name, user=list.user).exclude(id=list.id).count()>0:
- num += 1
- name = data['name'] + ' (%d)' % num
- setattr(list, key, name)
- else:
- setattr(list, key, data[key])
+ if key == 'query' and not data['query']:
+ setattr(list, key, {"static":True})
+ elif key == 'query':
+ setattr(list, key, data[key])
+ elif key == 'type':
+ if data[key] == 'static':
+ list.query = {"static":True}
+ list.type = 'static'
+ else:
+ list.type = 'dynamic'
+ if list.query.get('static', False):
+ list.query = {}
+ elif key == 'status':
+ value = data[key]
+ if value not in list._status:
+ value = list._status[0]
+ setattr(list, key, value)
+ if value == 'private':
+ for user in list.subscribed_users.all():
+ list.subscribed_users.remove(user)
+ elif key == 'name':
+ name = data['name'].strip()
+ if not name:
+ name = "Untitled"
+ num = 1
+ while models.List.objects.filter(name=name, user=list.user).exclude(id=list.id).count()>0:
+ num += 1
+ name = data['name'] + ' (%d)' % num
+ setattr(list, key, name)
if 'position' in data:
pos, created = models.Position.objects.get_or_create(list=list, user=request.user)
diff --git a/static/js/pandora.api.js b/static/js/pandora.api.js
index eb5a429fb..3e72b325d 100755
--- a/static/js/pandora.api.js
+++ b/static/js/pandora.api.js
@@ -68,14 +68,14 @@ function constructList() {
if(!data.keys) {
app.api.api(function(results) {
var items = [];
- $.each(results.data.actions, function(i, k) {items.push({'name': k})});
+ $.each(results.data.actions, function(i, k) {items.push({'name': i})});
var result = {'data': {'items': items.length}};
callback(result);
});
} else {
app.api.api(function(results) {
var items = [];
- $.each(results.data.actions, function(i, k) {items.push({'name': k})});
+ $.each(results.data.actions, function(i, k) {items.push({'name': i})});
var result = {'data': {'items': items}};
callback(result);
});
diff --git a/static/js/pandora.js b/static/js/pandora.js
index 899501a3f..0bfa4c0eb 100755
--- a/static/js/pandora.js
+++ b/static/js/pandora.js
@@ -1095,6 +1095,7 @@ var pandora = new Ox.App({
app.$ui.sectionbar.append(app.$ui.sectionButtons = ui.sectionButtons());
}
///*
+ Ox.print('data', data);
app.$ui.leftPanel.find('.OxTextList').css({
width: data + 'px'
});
@@ -1105,8 +1106,9 @@ var pandora = new Ox.App({
width: data + 'px'
});
app.$ui.leftPanel.find('.OxCell.OxColumnName').css({
- width: (data - 88) + 'px'
+ width: (data - 96) + 'px'
});
+ Ox.print(app.$ui.leftPanel.find('.OxCell.OxColumnName').css('width'))
//*/
//Ox.print('resize', data, data / app.ui.infoRatio + 16);
app.$ui.leftPanel.size('infoPanel', Math.round(data / app.ui.infoRatio) + 16);
@@ -1288,7 +1290,7 @@ var pandora = new Ox.App({
app.$ui.previewDialog.close();
delete app.$ui.previewDialog;
},
- load: function(event, data) {
+ init: function(event, data) {
app.$ui.total.html(ui.status('total', data));
data = [];
$.each(app.config.totals, function(i, v) {
@@ -2110,7 +2112,7 @@ var pandora = new Ox.App({
var $sections = [];
app.$ui.sectionLists = [];
$.each(app.user.ui.sections, function(i, id) {
- var menu = [];
+ var $section, menu = [];
if (id == 'my') {
menu = [
{ id: 'new', title: 'New List...' },
@@ -2125,12 +2127,37 @@ var pandora = new Ox.App({
{ id: 'browse', title: 'More Public Lists...' },
];
}
- var $section = new Ox.CollapsePanel({
- id: id,
- menu: menu,
- size: 16,
- title: Ox.getObjectById(app.config.sections, id).title
- });
+ $section = new Ox.CollapsePanel({
+ id: id,
+ menu: menu,
+ size: 16,
+ title: Ox.getObjectById(app.config.sections, id).title
+ })
+ .bindEvent({
+ click: function(event, data) {
+ var $list = app.$ui.sectionLists[i],
+ id;
+ if (data.id == 'new' || data.id == 'newsmart') {
+ pandora.api.addList({
+ name: 'Untitled',
+ status: 'private',
+ type: data.id == 'new' ? 'static' : 'smart'
+ }, function(result) {
+ id = result.data.id;
+ Ox.Request.emptyCache(); // fixme: remove
+ $list.reloadList()
+ .bindEvent({load: load});
+ });
+ }
+ function load(event, data) {
+ $list.gainFocus()
+ .options({selected: [id]})
+ .editCell(id, 'name');
+ Ox.print('load', id, $list.options('selected'))
+ $list.unbindEvent({load: load}) // fixme: need bindEventOnce
+ }
+ }
+ });
$sections.push($section);
app.$ui.sectionLists[i] = new Ox.TextList({
columns: [
@@ -2255,7 +2282,7 @@ var pandora = new Ox.App({
})
.bindEvent({
click: function(event, data) {
- var list = app.$ui.sectionLists[i];
+ var $list = app.$ui.sectionLists[i];
if (data.key == 'type') {
var $dialog = new Ox.Dialog({
buttons: [
@@ -2281,13 +2308,24 @@ var pandora = new Ox.App({
} else if (data.key == 'status') {
pandora.api.editList({
id: data.id,
- status: list.value(data.id, data.key) == 'private' ? 'public' : 'private'
+ status: $list.value(data.id, data.key) == 'private' ? 'public' : 'private'
}, function(result) {
- list.value(result.data.id, 'status', result.data.status);
+ $list.value(result.data.id, 'status', result.data.status);
});
}
},
- load: function(event, data) {
+ 'delete': function(event, data) {
+ var $list = app.$ui.sectionLists[i];
+ URL.set('');
+ $list.options({selected: []});
+ pandora.api.removeList({
+ id: data.ids[0]
+ }, function() {
+ Ox.Request.emptyCache(); // fixme: remove
+ $list.reloadList();
+ });
+ },
+ init: function(event, data) {
$section.$content.css({
height: data.items * 16 + 'px'
});
@@ -2307,17 +2345,24 @@ var pandora = new Ox.App({
});
},
select: function(event, data) {
- app.$ui.sectionLists.forEach(function($list, i_) {
- i != i_ && $list.options('selected', []);
- });
- URL.set('?find=list:' + data.ids[0]);
+ if (data.ids.length) {
+ app.$ui.sectionLists.forEach(function($list, i_) {
+ i != i_ && $list.options('selected', []);
+ });
+ URL.set('?find=list:' + data.ids[0]);
+ } else {
+ URL.set('');
+ }
},
submit: function(event, data) {
data_ = {id: data.id};
data_[data.key] = data.value;
pandora.api.editList(data_, function(result) {
- app.$ui.sectionLists[i].value(data.id, 'name', result.data.name);
- app.$ui.sectionLists[i].value(data.id, 'id', result.data.id);
+ if (result.data.name != data_.name) {
+ app.$ui.sectionLists[i].value(data.id, 'name', result.data.name);
+ app.$ui.sectionLists[i].value(data.id, 'id', result.data.id);
+ URL.set('?find=list:' + result.data.id);
+ }
});
}
})
@@ -2879,1676 +2924,4 @@ var pandora = new Ox.App({
load();
-});
-
-
-
-// Objects
-
-/*
- // Menu
-
-
- Ox.Event.bind('change_viewmovies', function(event, data) {
- app.$ui.viewSelect.selectItem(data.id);
- });
- Ox.Event.bind('change_find', function(event, data) {
- app.$ui.findInput.changeLabel(data.id);
- });
- Ox.Event.bind('click_query', function(event, data) {
- var $dialog = new Ox.Dialog({
- buttons: [
- {
- click: function() {
- $dialog.close();
- },
- id: 'close',
- title: 'Close',
- value: 'Close'
- }
- ],
- id: 'query',
- title: 'Query'
- }).append(Query.toString() + '
' + JSON.stringify(Query.toObject())).open();
- });
-
- // Resize
-
- Ox.Event.bind('click_show_query', function(event, data) {
- var query = constructQuery(),
- html = 'Conditions
' + $.map(query.conditions, function(v) {
- return v.key + ' ' + v.operator + ' ' + v.value;
- }).join('
') + '
Operator: ' + query.operator,
- $dialog = new Ox.Dialog({
- buttons: [
- {
- value: 'Close',
- click: function() {
- $dialog.close();
- }
- }
- ],
- title: 'Show Query'
- })
- .append(html)
- .open();
- });
-
-// Functions
-*/
-
-/*
-
-app.constructAnnotations = function() {
- var $annotations = new Ox.Element();
- $.each(app.constructBins(), function(i, $bin) {
- $annotations.append($bin);
- });
- return $annotations;
-}
-
-app.constructApp = function() {
- return new Ox.SplitPanel({
- elements: [
- {
- element: app.$ui.mainMenu,
- size: 20
- },
- {
- element: app.$ui.mainPanel = new Ox.SplitPanel({
- elements: [
- {
- collapsible: true,
- element: app.$ui.leftPanel = new Ox.SplitPanel({
- elements: [
- {
- element: app.$ui.sectionbar,
- size: 24
- },
- {
- element: app.$ui.lists.options({
- id: 'listsPanel'
- })
- },
- {
- collapsible: true,
- element: app.$ui.info.options({
- id: 'infoPanel'
- }),
- size: app.user.ui.listsSize / app.ui.infoRatio + 16
- }
- ],
- id: 'leftPanel',
- orientation: 'vertical'
- })
- .bindEvent('resize', function(event, data) {
- Ox.print('resize', data, data / app.ui.infoRatio + 16);
- app.$ui.leftPanel.size('infoPanel', Math.round(data / app.ui.infoRatio) + 16);
- }),
- resizable: true,
- resize: [128, 256, 384, 512],
- size: app.user.ui.listsSize
- },
- {
- element: app.$ui.rightPanel = new Ox.SplitPanel({
- elements: [
- {
- element: app.$ui.toolbar.css({ zIndex: 2 }), // fixme: remove later
- size: 24
- },
- {
- element: app.constructContentPanel()
- },
- {
- element: app.$ui.statusbar,
- size: 16
- }
- ],
- id: 'rightPanel',
- orientation: 'vertical'
- })
- .bindEvent('resize', function(event, data) {
- var widths = $.map(app.ui.groups, function(v, i) {
- return app.getGroupWidth(i, data);
- });
- Ox.print('widths', widths);
- app.$ui.groupsOuterPanel.size(0, widths[0].list).size(2, widths[4].list);
- app.$ui.groupsInnerPanel.size(0, widths[1].list).size(2, widths[3].list);
- $.each(app.$ui.groups, function(i, list) {
- list.resizeColumn('name', widths[i].column);
- });
- app.$ui.list.size();
- })
- }
- ],
- orientation: 'horizontal'
- })
- }
- ],
- orientation: 'vertical'
- });
-}
-
-app.constructBins = function() {
- var $bins = [];
- $.each(app.config.layers, function(i, layer) {
- var $bin = new Ox.CollapsePanel({
- id: layer.id,
- size: 16,
- title: layer.title
- });
- $bins.push($bin);
- $bin.$content.append(
- $('