even more lists stuff

This commit is contained in:
rlx 2011-01-14 09:54:35 +00:00
parent b5dc67bba1
commit 746fd10602
3 changed files with 320 additions and 207 deletions

View file

@ -352,17 +352,19 @@ def subscribeToList(request):
data = json.loads(request.POST['data']) data = json.loads(request.POST['data'])
list = get_list_or_404_json(data['id']) list = get_list_or_404_json(data['id'])
user = request.user user = request.user
if list.subscribed_users.filter(username=user.username).count() == 0: if list.status == 'public' and \
list.subscribed_users.filter(username=user.username).count() == 0:
list.subscribed_users.add(user) list.subscribed_users.add(user)
pos, created = models.Position.objects.get_or_create(list=list, user=request.user, section='public') pos, created = models.Position.objects.get_or_create(list=list, user=user, section='public')
if created: if created:
qs = models.Position.objects.filter(user=request.user, section='public') qs = models.Position.objects.filter(user=user, section='public')
pos.position = qs.aggregate(Max('position'))['position__max'] + 1 pos.position = qs.aggregate(Max('position'))['position__max'] + 1
pos.save() pos.save()
response = json_response() response = json_response()
return render_to_json_response(response) return render_to_json_response(response)
actions.register(subscribeToList, cache=False) actions.register(subscribeToList, cache=False)
@login_required_json @login_required_json
def unsubscribeFromList(request): def unsubscribeFromList(request):
''' '''
@ -380,7 +382,7 @@ def unsubscribeFromList(request):
list = get_list_or_404_json(data['id']) list = get_list_or_404_json(data['id'])
user = request.user user = request.user
list.subscribed_users.remove(user) list.subscribed_users.remove(user)
models.Position.objects.filter(list=list, user=request.user, section='public').delete() models.Position.objects.filter(list=list, user=user, section='public').delete()
response = json_response() response = json_response()
return render_to_json_response(response) return render_to_json_response(response)
actions.register(unsubscribeFromList, cache=False) actions.register(unsubscribeFromList, cache=False)
@ -416,6 +418,7 @@ def sortLists(request):
pos = qs[0] pos = qs[0]
else: else:
pos = models.Position(list=list, user=user, section=section) pos = models.Position(list=list, user=user, section=section)
if pos.position != position:
pos.position = position pos.position = position
pos.save() pos.save()
position += 1 position += 1
@ -425,6 +428,7 @@ def sortLists(request):
list = get_list_or_404_json(i) list = get_list_or_404_json(i)
pos, created = models.Position.objects.get_or_create(list=list, pos, created = models.Position.objects.get_or_create(list=list,
user=request.user, section=section) user=request.user, section=section)
if pos.position != position:
pos.position = position pos.position = position
pos.save() pos.save()
position += 1 position += 1

View file

@ -5,6 +5,7 @@ from datetime import datetime
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.db import models from django.db import models
from django.db.models import Max
from django.conf import settings from django.conf import settings
from ox.utils import json from ox.utils import json
@ -39,12 +40,14 @@ class UserProfile(models.Model):
def add(lists, section): def add(lists, section):
ids = [] ids = []
for l in lists: for l in lists:
qs = Position.objects.filter(section=section)
if section == 'featured': if section == 'featured':
pos, created = Position.objects.get_or_create(list=l, section=section) pos, created = Position.objects.get_or_create(list=l, section=section)
else: else:
pos, created = Position.objects.get_or_create(list=l, user=self.user, section=section) pos, created = Position.objects.get_or_create(list=l, user=self.user, section=section)
qs = qs.filter(user=self.user)
if created: if created:
pos.position = len(in_list) pos.position = qs.aggregate(Max('position'))['position__max'] + 1
pos.save() pos.save()
id = l.get_id() id = l.get_id()
if id not in ui['lists']: if id not in ui['lists']:

View file

@ -24,7 +24,8 @@ var pandora = new Ox.App({
sectionElement: 'buttons', sectionElement: 'buttons',
sectionLength: {}, sectionLength: {},
selectedMovies: [], selectedMovies: [],
showAllPublicLists: false showFeaturedListsBrowser: false,
showPublicListsBrowser: false
}, },
user: data.user user: data.user
}; };
@ -1529,6 +1530,186 @@ var pandora = new Ox.App({
}; };
return that; return that;
}, },
listsBar: function(id) {
var that = new Ox.Bar({
size: 24
});
app.$ui.findListInput = new Ox.Input({
placeholder: 'Find User',
width: 184 - app.ui.scrollbarSize
})
.css({
margin: '4px',
align: 'right'
})
.appendTo(that);
return that;
},
listsBrowser: function(id) {
var that = new Ox.SplitPanel({
elements: [
{
element: ui.listsBar(),
size: 24
},
{
element: app.$ui.sectionList[id == 'public' ? 1 : 2] = ui.listsList(id)
}
],
orientation: 'vertical'
});
return that;
},
listsList: function(id) {
var columnWidth = (app.user.ui.sidebarSize - app.ui.scrollbarSize - 88) / 2,
i = ['my', 'public', 'featured'].indexOf(id), // fixme: find a better way
that = new Ox.TextList({
columns: [
{
format: function() {
return $('<img>').attr({
src: 'static/oxjs/build/png/ox.ui/icon16.png'
});
},
id: 'id',
operator: '+',
title: $('<img>').attr({
src: 'static/oxjs/build/png/ox.ui/icon16.png'
}),
unique: true,
visible: true,
width: 16
},
{
id: 'user',
operator: '+',
title: 'User',
visible: true,
width: Math.floor(columnWidth)
},
{
id: 'name',
operator: '+',
title: 'Name',
visible: true,
width: Math.ceil(columnWidth)
},
{
align: 'right',
id: 'items',
operator: '-',
title: 'Items',
visible: true,
width: 40
},
{
format: function(value) {
return $('<img>')
.attr({
src: 'static/oxjs/build/png/ox.ui.' + Ox.theme() +
'/symbolFind.png'
})
.css({
opacity: value == 'static' ? 0.1 : 1
});
},
id: 'type',
operator: '+',
title: $('<img>').attr({
src: 'static/oxjs/build/png/ox.ui.' +
Ox.theme() + '/symbolFind.png'
}),
visible: true,
width: 16
},
{
clickable: true,
format: function(value) {
return $('<img>')
.attr({
src: 'static/oxjs/build/png/ox.ui.' + Ox.theme() +
'/symbol' + (id == 'public' ? 'Check' : 'Star') + '.png'
})
.css({
opacity: id == 'public' ? (value ? 1 : 0.1) :
(value == 'featured' ? 1 : 0.1)
});
},
id: id == 'public' ? 'subscribed' : 'status',
operator: '+',
title: $('<img>').attr({
src: 'static/oxjs/build/png/ox.ui.' + Ox.theme() +
'/symbol' + (id == 'public' ? 'Check' : 'Star') + '.png'
}),
visible: true,
width: 16
},
],
columnsVisible: true,
pageLength: 1000,
request: function(data, callback) {
var query = id == 'public' ? {conditions: [
{key: 'user', value: app.user.username, operator: '!'},
{key: 'status', value: 'public', operator: '='}
], operator: '&'} : {conditions: [
{key: 'status', value: 'public', operator: '='},
{key: 'status', value: 'public', operator: '='}
], operator: '|'};
return pandora.api.findLists($.extend(data, {
query: query
}), callback);
},
selected: app.user.ui.list ? [app.user.ui.list] : [],
sort: [
{key: 'name', operator: '+'}
]
})
.bindEvent({
click: function(event, data) {
if (id == 'public') {
var subscribed = that.value(data.id, 'subscribed');
pandora.api[subscribed ? 'unsubscribeFromList' : 'subscribeToList']({
id: data.id,
}, function(result) {
that.value(data.id, 'subscribed', !subscribed);
});
} else if (id == 'featured') {
pandora.api.editList({
id: data.id,
status: that.value(data.id, 'status') == 'featured' ? 'public' : 'featured'
}, function(result) {
Ox.Request.emptyCache(); // fixme: remove
app.$ui.sectionList[
result.data.user == app.user.username ? 0 : 1
].reloadList();
that.value(data.id, 'status', result.data.status);
});
}
},
init: function(event, data) {
app.ui.sectionLength[id] = data.items;
app.$ui.section[i].$content.css({
height: 40 + data.items * 16 + 'px'
});
app.$ui.sectionList[i].css({
height: 16 + data.items * 16 + 'px'
});
resizeSections();
},
select: function(event, data) {
// fixme: duplicated
if (data.ids.length) {
app.$ui.sectionList.forEach(function($list, i) {
i != 2 && $list.options('selected', []);
});
URL.set('?find=list:' + data.ids[0]);
} else {
URL.set('');
}
}
});
return that;
},
mainMenu: function() { mainMenu: function() {
var isGuest = app.user.group == 'guest', var isGuest = app.user.group == 'guest',
that = new Ox.MainMenu({ that = new Ox.MainMenu({
@ -2054,36 +2235,6 @@ var pandora = new Ox.App({
}) })
return that; return that;
}, },
publicLists: function() {
var that = new Ox.SplitPanel({
elements: [
{
element: ui.publicListsBar(),
size: 24
},
{
element: app.$ui.sectionList[1] = ui.publicListsList()
}
],
orientation: 'vertical'
});
return that;
},
publicListsBar: function() {
var that = new Ox.Bar({
size: 24
});
app.$ui.findListInput = new Ox.Input({
placeholder: 'Find User',
width: 184 - app.ui.scrollbarSize
})
.css({
margin: '4px',
align: 'right'
})
.appendTo(that);
return that;
},
publicListsDialog: function() { // fixme: unused publicListsDialog: function() { // fixme: unused
var that = new Ox.Dialog({ var that = new Ox.Dialog({
buttons: [ buttons: [
@ -2107,133 +2258,6 @@ var pandora = new Ox.App({
position: 'absolute' position: 'absolute'
}); });
return that; return that;
},
publicListsList: function() {
var columnWidth = (app.user.ui.sidebarSize - app.ui.scrollbarSize - 88) / 2,
that = new Ox.TextList({
columns: [
{
format: function() {
return $('<img>').attr({
src: 'static/oxjs/build/png/ox.ui/icon16.png'
});
},
id: 'id',
operator: '+',
title: $('<img>').attr({
src: 'static/oxjs/build/png/ox.ui/icon16.png'
}),
unique: true,
visible: true,
width: 16
},
{
id: 'user',
operator: '+',
title: 'User',
visible: true,
width: Math.floor(columnWidth)
},
{
id: 'name',
operator: '+',
title: 'Name',
visible: true,
width: Math.ceil(columnWidth)
},
{
align: 'right',
id: 'items',
operator: '-',
title: 'Items',
visible: true,
width: 40
},
{
format: function(value) {
return $('<img>')
.attr({
src: 'static/oxjs/build/png/ox.ui.' + Ox.theme() +
'/symbolFind.png'
})
.css({
opacity: value == 'static' ? 0.1 : 1
});
},
id: 'type',
operator: '+',
title: $('<img>').attr({
src: 'static/oxjs/build/png/ox.ui.' +
Ox.theme() + '/symbolFind.png'
}),
visible: true,
width: 16
},
{
clickable: true,
format: function(value) {
return $('<img>')
.attr({
src: 'static/oxjs/build/png/ox.ui.' +
Ox.theme() + '/symbolCheck.png'
})
.css({
opacity: value ? 1 : 0.1
});
},
id: 'subscribed',
operator: '+',
title: $('<img>').attr({
src: 'static/oxjs/build/png/ox.ui.' +
Ox.theme() + '/symbolCheck.png'
}),
visible: true,
width: 16
},
],
columnsVisible: true,
pageLength: 1000,
request: function(data, callback) {
var query = {conditions: [
{key: 'user', value: app.user.username, operator: '!'},
{key: 'status', value: 'public', operator: '='}
], operator: ''};
return pandora.api.findLists($.extend(data, {
query: query
}), callback);
},
selected: app.user.ui.list ? [app.user.ui.list] : [],
sort: [
{key: 'name', operator: '+'}
]
})
.bindEvent({
click: function(event, data) {
alert('click')
},
init: function(event, data) {
app.ui.sectionLength.public = data.items;
app.$ui.section[1].$content.css({
height: 40 + data.items * 16 + 'px'
});
app.$ui.sectionList[1].css({
height: 16 + data.items * 16 + 'px'
});
resizeSections();
},
select: function(event, data) {
// fixme: duplicated
if (data.ids.length) {
app.$ui.sectionList.forEach(function($list, i) {
i != 1 && $list.options('selected', []);
});
URL.set('?find=list:' + data.ids[0]);
} else {
URL.set('');
}
}
});
return that;
}, },
rightPanel: function() { rightPanel: function() {
var that = new Ox.SplitPanel({ var that = new Ox.SplitPanel({
@ -2300,8 +2324,9 @@ var pandora = new Ox.App({
}); });
return that; return that;
}, },
sectionList: function(id, i) { sectionList: function(id) {
var that = new Ox.TextList({ var i = ['my', 'public', 'featured'].indexOf(id), // fixme: find a better way
that = new Ox.TextList({
columns: [ columns: [
{ {
format: function() { format: function() {
@ -2456,12 +2481,32 @@ var pandora = new Ox.App({
var $list = app.$ui.sectionList[i]; var $list = app.$ui.sectionList[i];
URL.set(''); URL.set('');
$list.options({selected: []}); $list.options({selected: []});
if (id == 'my') {
pandora.api.removeList({ pandora.api.removeList({
id: data.ids[0] id: data.ids[0]
}, function() { }, function(result) {
Ox.Request.emptyCache(); // fixme: remove Ox.Request.emptyCache(); // fixme: remove
$list.reloadList(); $list.reloadList();
}); });
} else if (id == 'public') {
pandora.api.unsubscribeFromList({
id: data.ids[0]
}, function(result) {
Ox.Request.emptyCache(); // fixme: remove
$list.reloadList();
});
} else if (id == 'featured' && app.user.group == 'admin') {
pandora.api.editList({
id: data.ids[0],
status: 'public'
}, function(result) {
Ox.Request.emptyCache(); // fixme: remove
app.$ui.sectionList[
result.data.user == app.user.username ? 0 : 1
].reloadList();
$list.reloadList();
});
}
}, },
init: function(event, data) { init: function(event, data) {
app.ui.sectionLength[id] = data.items; // fixme: why by id, not by i? app.ui.sectionLength[id] = data.items; // fixme: why by id, not by i?
@ -2523,24 +2568,84 @@ var pandora = new Ox.App({
app.$ui.section = []; app.$ui.section = [];
app.$ui.sectionList = []; app.$ui.sectionList = [];
$.each(app.user.ui.sections, function(i, id) { $.each(app.user.ui.sections, function(i, id) {
var menu = []; var extras;
if (id == 'my') { if (id == 'my') {
menu = [ extras = [new Ox.Select({
items: [
{ id: 'new', title: 'New List...' }, { id: 'new', title: 'New List...' },
{ id: 'newfromselection', title: 'New List from Current Selection...', disabled: true }, { id: 'newfromselection', title: 'New List from Current Selection...', disabled: true },
{ id: 'newsmart', title: 'New Smart List...' }, { id: 'newsmart', title: 'New Smart List...' },
{ id: 'newfromresults', title: 'New Smart List from Current Results...', disabled: true }, { id: 'newfromresults', title: 'New Smart List from Current Results...', disabled: true },
{}, {},
{ id: 'addselection', title: 'Add Selection to List...' } { id: 'addselection', title: 'Add Selection to List...' }
]; ],
} else if (id == 'public') { max: 0,
menu = [ min: 0,
{ id: 'browse', title: 'More Public Lists...' }, selectable: false,
]; type: 'image'
})
.bindEvent({
click: function(event, data) {
var 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;
URL.set('?find=list:' + id)
Ox.Request.emptyCache(); // fixme: remove
$list.reloadList().bindEvent({load: load});
function load(event, data) {
$list.gainFocus()
.options({selected: [id]})
.editCell(id, 'name');
$list.unbindEvent({load: load}) // fixme: need bindEventOnce
} }
});
}
}
})];
} else if (id == 'public') {
extras = [new Ox.Button({
selectable: true,
style: 'symbol',
title: 'Edit',
tooltip: 'Manage Favorite Lists',
type: 'image'
})
.bindEvent({
change: function(event, data) {
app.ui.showPublicListsBrowser = !app.ui.showPublicListsBrowser;
if (app.ui.showPublicListsBrowser) {
app.$ui.sectionList[1].replaceWith(app.$ui.publicListsBrowser = ui.listsBrowser('public'));
} else {
app.$ui.publicListsBrowser.replaceWith(app.$ui.sectionList[1] = ui.sectionList('public'));
}
}
})];
} else if (id == 'featured' && app.user.group == 'admin') {
extras = [new Ox.Button({
selectable: true,
style: 'symbol',
title: 'Edit',
tooltip: 'Manage Featured Lists',
type: 'image'
})
.bindEvent({
change: function(event, data) {
app.ui.showFeaturedListsBrowser = !app.ui.showFeaturedListsBrowser;
if (app.ui.showFeaturedListsBrowser) {
app.$ui.sectionList[2].replaceWith(app.$ui.featuredListsBrowser = ui.listsBrowser('featured'));
} else {
app.$ui.featuredListsBrowser.replaceWith(app.$ui.sectionList[2] = ui.sectionList('featured'));
}
}
})]; }
app.$ui.section[i] = new Ox.CollapsePanel({ app.$ui.section[i] = new Ox.CollapsePanel({
id: id, id: id,
menu: menu, extras: extras,
size: 16, size: 16,
title: Ox.getObjectById(app.config.sections, id).title title: Ox.getObjectById(app.config.sections, id).title
}) })
@ -2566,10 +2671,7 @@ var pandora = new Ox.App({
} }
}); });
} else if (data.id == 'browse') { } else if (data.id == 'browse') {
//hasFocus = app.$ui.app.$ui.sectionList[1].hasFocus();
app.$ui.sectionList[1].replaceWith(app.$ui.publicLists = ui.publicLists()); app.$ui.sectionList[1].replaceWith(app.$ui.publicLists = ui.publicLists());
//hasFocus && app.$ui.publicLists.gainFocus();
//app.$ui.publicListsDialog = ui.publicListsDialog().open();
app.ui.showAllPublicLists = true; app.ui.showAllPublicLists = true;
} }
}, },
@ -2580,7 +2682,7 @@ var pandora = new Ox.App({
} }
}); });
$sections.push(app.$ui.section[i]); $sections.push(app.$ui.section[i]);
app.$ui.sectionList[i] = ui.sectionList(id, i) app.$ui.sectionList[i] = ui.sectionList(id)
.bindEvent({init: init}) .bindEvent({init: init})
.appendTo(app.$ui.section[i].$content); .appendTo(app.$ui.section[i].$content);
function init(event, data) { function init(event, data) {
@ -2804,6 +2906,20 @@ var pandora = new Ox.App({
return width; return width;
} }
function getSectionsHeight() {
var height = 48;
$.each(app.user.ui.showSection, function(id, show) {
height += show * app.ui.sectionLength[id] * 16;
if (id == 'public' && app.ui.showPublicListsBrowser) {
height += show * 40;
} else if (id == 'featured' && app.ui.showFeaturedListsBrowser) {
height += show * 40;
}
});
Ox.print('getSectionsHeight', height)
return height;
}
function getSectionsWidth() { function getSectionsWidth() {
var width = app.user.ui.sidebarSize; var width = app.user.ui.sidebarSize;
// fixme: don't use height(), look up in splitpanels // fixme: don't use height(), look up in splitpanels
@ -2813,19 +2929,6 @@ var pandora = new Ox.App({
return width; return width;
} }
function getSectionsHeight() {
var height = 48;
$.each(app.user.ui.showSection, function(id, show) {
Ox.print('*', id, app.ui.sectionLength[id])
height += show * app.ui.sectionLength[id] * 16;
if (id == 'public' && app.ui.showAllPublicLists) {
height += show * 40
}
});
Ox.print('getSectionsHeight', height)
return height;
}
function getSortOperator(key) { // fixme: make static function getSortOperator(key) { // fixme: make static
return ['person', 'string', 'text', 'title'].indexOf( return ['person', 'string', 'text', 'title'].indexOf(
Ox.getObjectById(app.config.sortKeys, key).type Ox.getObjectById(app.config.sortKeys, key).type
@ -2877,7 +2980,10 @@ var pandora = new Ox.App({
app.$ui.sectionList.forEach(function($list, i) { app.$ui.sectionList.forEach(function($list, i) {
var id = i == 1 ? 'id' : 'name'; var id = i == 1 ? 'id' : 'name';
$list.css({width: width + 'px'}); $list.css({width: width + 'px'});
if (i == 1 && app.ui.showAllPublicLists) { if (
i == 1 && app.ui.showPublicListsBrowser ||
i == 2 && app.ui.showFeaturedListsBrowser
) {
$list.resizeColumn('user', Math.floor((width - 88) / 2)) $list.resizeColumn('user', Math.floor((width - 88) / 2))
.resizeColumn('name', Math.floor((width - 88) / 2)); .resizeColumn('name', Math.floor((width - 88) / 2));
} else { } else {