improvements to map
This commit is contained in:
parent
228c612fff
commit
40d2a86524
6 changed files with 261 additions and 52 deletions
|
@ -1,35 +1,151 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# vi:si:et:sw=4:sts=4:ts=4
|
||||
from django.db.models import Q, Manager
|
||||
from ox.django.query import QuerySet
|
||||
|
||||
def parseCondition(condition, user):
|
||||
'''
|
||||
condition: {
|
||||
value: "war"
|
||||
}
|
||||
or
|
||||
condition: {
|
||||
key: "year",
|
||||
value: "1970-1980,
|
||||
operator: "!="
|
||||
}
|
||||
...
|
||||
'''
|
||||
k = condition.get('key', 'name')
|
||||
k = {
|
||||
'user': 'user__username',
|
||||
}.get(k, k)
|
||||
if not k:
|
||||
k = 'name'
|
||||
v = condition['value']
|
||||
op = condition.get('operator', None)
|
||||
if not op:
|
||||
op = ''
|
||||
if op.startswith('!'):
|
||||
op = op[1:]
|
||||
exclude = True
|
||||
else:
|
||||
exclude = False
|
||||
if k == 'id':
|
||||
v = v.split('/')
|
||||
if len(v) == 2:
|
||||
q = Q(user__username=v[0], name=v[1])
|
||||
else:
|
||||
q = Q(id__in=[])
|
||||
return q
|
||||
if isinstance(v, bool): #featured and public flag
|
||||
key = k
|
||||
else:
|
||||
if op == '=':
|
||||
key = '%s__iexact'%k
|
||||
elif op == '^':
|
||||
v = v[1:]
|
||||
key = '%s__istartswith'%k
|
||||
elif op == '$':
|
||||
v = v[:-1]
|
||||
key = '%s__iendswith'%k
|
||||
else: # default
|
||||
key = '%s__icontains'%k
|
||||
|
||||
key = str(key)
|
||||
if exclude:
|
||||
q = ~Q(**{key: v})
|
||||
else:
|
||||
q = Q(**{key: v})
|
||||
return q
|
||||
|
||||
def parseConditions(conditions, operator, user):
|
||||
'''
|
||||
conditions: [
|
||||
{
|
||||
value: "war"
|
||||
}
|
||||
{
|
||||
key: "year",
|
||||
value: "1970-1980,
|
||||
operator: "!="
|
||||
},
|
||||
{
|
||||
key: "country",
|
||||
value: "f",
|
||||
operator: "^"
|
||||
}
|
||||
],
|
||||
operator: "&"
|
||||
'''
|
||||
conn = []
|
||||
for condition in conditions:
|
||||
if 'conditions' in condition:
|
||||
q = parseConditions(condition['conditions'],
|
||||
condition.get('operator', '&'), user)
|
||||
if q:
|
||||
conn.append(q)
|
||||
pass
|
||||
else:
|
||||
if condition.get('value', '') != '' or \
|
||||
condition.get('operator', '') == '=':
|
||||
conn.append(parseCondition(condition, user))
|
||||
if conn:
|
||||
q = conn[0]
|
||||
for c in conn[1:]:
|
||||
if operator == '|':
|
||||
q = q | c
|
||||
else:
|
||||
q = q & c
|
||||
return q
|
||||
return None
|
||||
|
||||
|
||||
|
||||
class PlaceManager(Manager):
|
||||
|
||||
def get_query_set(self):
|
||||
return super(PlaceManager, self).get_query_set()
|
||||
return QuerySet(self.model)
|
||||
|
||||
def find(self, q='', south=-180.0, west=-180.0, north=180.0, east=180.0):
|
||||
def find(self, data, user):
|
||||
'''
|
||||
query: {
|
||||
conditions: [
|
||||
{
|
||||
value: "war"
|
||||
}
|
||||
{
|
||||
key: "year",
|
||||
value: "1970-1980,
|
||||
operator: "!="
|
||||
},
|
||||
{
|
||||
key: "country",
|
||||
value: "f",
|
||||
operator: "^"
|
||||
}
|
||||
],
|
||||
operator: "&"
|
||||
}
|
||||
'''
|
||||
|
||||
#join query with operator
|
||||
qs = self.get_query_set()
|
||||
|
||||
south=data['area']['south']
|
||||
west=data['area']['west']
|
||||
north=data['area']['north']
|
||||
east=data['area']['east']
|
||||
qs = qs.filter(Q(
|
||||
Q(Q(south__gt=south)|Q(south__lt=north)|Q(west__gt=west)|Q(west__lt=east)) &
|
||||
Q(Q(south__gt=south)|Q(south__lt=north)|Q(west__lt=east)|Q(east__gt=east)) &
|
||||
Q(Q(north__gt=south)|Q(north__lt=north)|Q(west__gt=west)|Q(west__lt=east)) &
|
||||
Q(Q(north__gt=south)|Q(north__lt=north)|Q(east__gt=west)|Q(east__lt=east))
|
||||
))
|
||||
if q:
|
||||
qs = qs.filter(name_find__icontains=q)
|
||||
|
||||
conditions = parseConditions(data['query'].get('conditions', []),
|
||||
data['query'].get('operator', '&'),
|
||||
user)
|
||||
if conditions:
|
||||
qs = qs.filter(conditions)
|
||||
return qs
|
||||
'''
|
||||
#only return locations that have layers of videos visible to current user
|
||||
if not identity.current.anonymous:
|
||||
user = identity.current.user
|
||||
if not user.in_group('admin'):
|
||||
query = AND(query,
|
||||
id == Layer.q.locationID, Layer.q.videoID == Video.q.id,
|
||||
OR(Video.q.public == True, Video.q.creatorID == user.id)
|
||||
)
|
||||
else:
|
||||
query = AND(query,
|
||||
id == Layer.q.locationID, Layer.q.videoID == Video.q.id,
|
||||
Video.q.public == True)
|
||||
'''
|
||||
|
|
|
@ -25,6 +25,7 @@ class Place(models.Model):
|
|||
|
||||
geoname = models.CharField(max_length=1024, unique=True)
|
||||
geoname_sort = models.CharField(max_length=1024, unique=True)
|
||||
countryCode = models.CharField(max_length=16, default='')
|
||||
|
||||
wikipediaId = models.CharField(max_length=1000, blank=True)
|
||||
|
||||
|
@ -58,7 +59,7 @@ class Place(models.Model):
|
|||
'user': self.user.username,
|
||||
}
|
||||
for key in ('created', 'modified',
|
||||
'name', 'geoname',
|
||||
'name', 'geoname', 'countryCode',
|
||||
'south', 'west', 'north', 'east',
|
||||
'lat', 'lng', 'size'):
|
||||
j[key] = getattr(self, key)
|
||||
|
|
|
@ -21,6 +21,7 @@ def addPlace(request):
|
|||
param data {
|
||||
name: "",
|
||||
geoname: "",
|
||||
countryCode: '',
|
||||
south: float,
|
||||
west: float,
|
||||
north: float,
|
||||
|
@ -45,7 +46,7 @@ def addPlace(request):
|
|||
for key in data:
|
||||
setattr(place, key, data[key])
|
||||
place.save()
|
||||
response = json_response(status=200, text='created')
|
||||
response = json_response(place.json())
|
||||
else:
|
||||
response = json_response(status=403, text='place name exists')
|
||||
return render_to_json_response(response)
|
||||
|
@ -72,14 +73,17 @@ def editPlace(request):
|
|||
for name in names:
|
||||
if models.Place.objects.filter(name_find__icontains=u'|%s|'%name).exclude(id=place.id).count() != 0:
|
||||
conflict = True
|
||||
if 'geoname' in data:
|
||||
if models.Place.objects.filter(geoname=data['geoname']).exclude(id=place.id).count() != 0:
|
||||
conflict = True
|
||||
if not conflict:
|
||||
for key in data:
|
||||
if key != 'id':
|
||||
setattr(place, key, data[key])
|
||||
place.save()
|
||||
response = json_response(status=200, text='updated')
|
||||
response = json_response(place.json())
|
||||
else:
|
||||
response = json_response(status=403, text='place name/alias conflict')
|
||||
response = json_response(status=403, text='place name/geoname conflict')
|
||||
else:
|
||||
response = json_response(status=403, text='permission denied')
|
||||
return render_to_json_response(response)
|
||||
|
@ -108,13 +112,30 @@ actions.register(removePlace, cache=False)
|
|||
def parse_query(data, user):
|
||||
query = {}
|
||||
query['range'] = [0, 100]
|
||||
query['sort'] = [{'key':'user', 'operator':'+'}, {'key':'name', 'operator':'+'}]
|
||||
for key in ('keys', 'group', 'list', 'range', 'ids', 'sort'):
|
||||
query['sort'] = [{'key':'name', 'operator':'+'}]
|
||||
query['area'] = {'south': -180.0, 'west': -180.0, 'north': 180.0, 'east': 180.0}
|
||||
for key in ('area', 'keys', 'group', 'list', 'range', 'ids', 'sort', 'query'):
|
||||
if key in data:
|
||||
query[key] = data[key]
|
||||
query['qs'] = models.Place.objects.all()
|
||||
query['qs'] = models.Place.objects.find(query, user)
|
||||
return query
|
||||
|
||||
def order_query(qs, sort):
|
||||
order_by = []
|
||||
for e in sort:
|
||||
operator = e['operator']
|
||||
if operator != '-':
|
||||
operator = ''
|
||||
key = {
|
||||
'name': 'name_sort',
|
||||
'geoname': 'geoname_sort',
|
||||
}.get(e['key'], e['key'])
|
||||
order = '%s%s' % (operator, key)
|
||||
order_by.append(order)
|
||||
if order_by:
|
||||
qs = qs.order_by(*order_by, nulls_last=True)
|
||||
return qs
|
||||
|
||||
def findPlaces(request):
|
||||
'''
|
||||
param data {
|
||||
|
@ -185,7 +206,7 @@ Positions
|
|||
response = json_response()
|
||||
|
||||
query = parse_query(data, request.user)
|
||||
qs = query['qs']
|
||||
qs = order_query(query['qs'], query['sort'])
|
||||
if 'keys' in data:
|
||||
qs = qs[query['range'][0]:query['range'][1]]
|
||||
response['data']['items'] = [p.json(request.user) for p in qs]
|
||||
|
|
|
@ -17,6 +17,7 @@ if(typeof(console)=='undefined') {
|
|||
<script type="text/javascript" src="/static/oxjs/build/js/ox.load.js"></script>
|
||||
<script type="text/javascript" src="/static/oxjs/build/js/ox.js"></script>
|
||||
<script type="text/javascript" src="/static/oxjs/build/js/ox.ui.js"></script>
|
||||
<script type="text/javascript" src="/static/oxjs/build/js/ox.map.js"></script><!-- fixme: lazyload -->
|
||||
<script type="text/javascript" src="/static/js/pandora.js"></script>
|
||||
<!--
|
||||
<script type="text/javascript" src="/static/js/pandora.local.js"></script> -->
|
||||
|
|
|
@ -79,7 +79,7 @@ function constructList() {
|
|||
columnsMovable: false,
|
||||
columnsRemovable: false,
|
||||
id: 'actionList',
|
||||
request: function(data, callback) {
|
||||
items: function(data, callback) {
|
||||
function _sort(a, b) {
|
||||
if(a.name > b.name)
|
||||
return 1;
|
||||
|
|
|
@ -571,16 +571,16 @@
|
|||
width: ratio >= 1 ? size : size * ratio
|
||||
};
|
||||
},
|
||||
keys: ['director', 'id', 'poster', 'title', 'year'],
|
||||
max: 1,
|
||||
min: 1,
|
||||
orientation: 'horizontal',
|
||||
request: function(data, callback) {
|
||||
items: function(data, callback) {
|
||||
//Ox.print('data, Query.toObject', data, Query.toObject())
|
||||
pandora.api.find($.extend(data, {
|
||||
query: Query.toObject()
|
||||
}), callback);
|
||||
},
|
||||
keys: ['director', 'id', 'poster', 'title', 'year'],
|
||||
max: 1,
|
||||
min: 1,
|
||||
orientation: 'horizontal',
|
||||
selected: [app.user.ui.item],
|
||||
size: 64,
|
||||
sort: app.user.ui.lists[app.user.ui.list].sort,
|
||||
|
@ -962,8 +962,7 @@
|
|||
},
|
||||
],
|
||||
columnsVisible: true,
|
||||
pageLength: 1000,
|
||||
request: function(data, callback) {
|
||||
items: function(data, callback) {
|
||||
var query = id == 'favorite' ? {conditions: [
|
||||
{key: 'user', value: app.user.username, operator: '!'},
|
||||
{key: 'status', value: 'public', operator: '='}
|
||||
|
@ -975,6 +974,7 @@
|
|||
query: query
|
||||
}), callback);
|
||||
},
|
||||
pageLength: 1000,
|
||||
// fixme: select if previously selected
|
||||
// selected: app.user.ui.list ? [app.user.ui.list] : [],
|
||||
sort: [
|
||||
|
@ -1062,9 +1062,7 @@
|
|||
width: app.user.ui.sidebarSize - 16
|
||||
}
|
||||
],
|
||||
max: 1,
|
||||
min: 1,
|
||||
request: function(data, callback) {
|
||||
items: function(data, callback) {
|
||||
var result = {data: {}};
|
||||
if (!data.range) {
|
||||
result.data.items = Ox.getObjectById(app.ui.sectionFolders.site, id).items.length;
|
||||
|
@ -1073,6 +1071,8 @@
|
|||
}
|
||||
callback(result);
|
||||
},
|
||||
max: 1,
|
||||
min: 1,
|
||||
sort: [{key: '', operator: ''}]
|
||||
})
|
||||
.bindEvent({
|
||||
|
@ -1165,10 +1165,7 @@
|
|||
width: 16
|
||||
}
|
||||
],
|
||||
max: 1,
|
||||
min: 0,
|
||||
pageLength: 1000,
|
||||
request: function(data, callback) {
|
||||
items: function(data, callback) {
|
||||
var query;
|
||||
if (id == 'personal') {
|
||||
query = {conditions: [
|
||||
|
@ -1187,6 +1184,9 @@
|
|||
query: query
|
||||
}), callback);
|
||||
},
|
||||
max: 1,
|
||||
min: 0,
|
||||
pageLength: 1000,
|
||||
sort: [
|
||||
{key: 'position', operator: '+'}
|
||||
],
|
||||
|
@ -1535,7 +1535,7 @@
|
|||
],
|
||||
columnsVisible: true,
|
||||
id: 'group_' + id,
|
||||
request: function(data, callback) {
|
||||
items: function(data, callback) {
|
||||
//Ox.print('sending request', data)
|
||||
delete data.keys;
|
||||
//alert(id + " Query.toObject " + JSON.stringify(Query.toObject(id)) + ' ' + JSON.stringify(data))
|
||||
|
@ -1958,7 +1958,7 @@
|
|||
columnsResizable: true,
|
||||
columnsVisible: true,
|
||||
id: 'list',
|
||||
request: function(data, callback) {
|
||||
items: function(data, callback) {
|
||||
//Ox.print('data, Query.toObject', data, Query.toObject())
|
||||
pandora.api.find($.extend(data, {
|
||||
query: Query.toObject()
|
||||
|
@ -2005,13 +2005,13 @@
|
|||
width: ratio >= 1 ? size : size * ratio
|
||||
};
|
||||
},
|
||||
keys: ['director', 'id', 'poster', 'title', 'year'],
|
||||
request: function(data, callback) {
|
||||
items: function(data, callback) {
|
||||
//Ox.print('data, Query.toObject', data, Query.toObject())
|
||||
pandora.api.find($.extend(data, {
|
||||
query: Query.toObject()
|
||||
}), callback);
|
||||
},
|
||||
keys: ['director', 'id', 'poster', 'title', 'year'],
|
||||
size: 128,
|
||||
sort: app.user.ui.lists[app.user.ui.list].sort,
|
||||
unique: 'id'
|
||||
|
@ -2113,7 +2113,7 @@
|
|||
orientation: 'horizontal'
|
||||
})
|
||||
.bindEvent('resize', function() {
|
||||
app.$ui.map.triggerResize();
|
||||
app.$ui.map.resize();
|
||||
});
|
||||
} else {
|
||||
$list = new Ox.Element('<div>')
|
||||
|
@ -2574,6 +2574,8 @@
|
|||
app.$ui.accountDialog = (app.user.level == 'guest' ?
|
||||
ui.accountDialog('login') : ui.accountLogoutDialog()).open();
|
||||
} else if (data.id == 'places') {
|
||||
app.$ui.placesDialog = ui.placesDialog().open();
|
||||
/*
|
||||
var $manage = new Ox.SplitPanel({
|
||||
elements: [
|
||||
{
|
||||
|
@ -2690,7 +2692,7 @@
|
|||
.bindEvent({
|
||||
submit: function(event, data) {
|
||||
app.$ui.map.find(data.value, function(location) {
|
||||
/*
|
||||
|
||||
app.$ui.placeNameInput.options({
|
||||
disabled: false,
|
||||
value: location.name
|
||||
|
@ -2708,7 +2710,7 @@
|
|||
app.$ui.addPlaceButton.options({
|
||||
disabled: false
|
||||
});
|
||||
*/
|
||||
|
||||
});
|
||||
}
|
||||
})
|
||||
|
@ -2845,6 +2847,7 @@
|
|||
}).css({
|
||||
overflow: 'hidden'
|
||||
}).append($manage).open();
|
||||
*/
|
||||
} else if (data.id == 'query') {
|
||||
var $dialog = new Ox.Dialog({
|
||||
buttons: [
|
||||
|
@ -2895,6 +2898,73 @@
|
|||
})
|
||||
return that;
|
||||
},
|
||||
placesDialog: function() {
|
||||
var height = Math.round(document.height * 0.8),
|
||||
width = Math.round(document.width * 0.8),
|
||||
that = new Ox.Dialog({
|
||||
buttons: [
|
||||
new Ox.Button({
|
||||
id: 'done',
|
||||
title: 'Done'
|
||||
}).bindEvent({
|
||||
click: function() {
|
||||
that.close();
|
||||
}
|
||||
})
|
||||
],
|
||||
content: app.$ui.placesElement = new Ox.ListMap({
|
||||
height: height - 48,
|
||||
places: function(data, callback) {
|
||||
return pandora.api.findPlaces($.extend(data, {
|
||||
query: {conditions: [], operator: ''}
|
||||
}), callback);
|
||||
},
|
||||
width: width
|
||||
})
|
||||
.bindEvent({
|
||||
addplace: function(event, data) {
|
||||
Ox.print('ADDPLACE', data)
|
||||
pandora.api.addPlace(data.place, function(result) {
|
||||
var id = result.data.id;
|
||||
Ox.print("ID", result.data.id, result)
|
||||
Ox.Request.clearCache(); // fixme: remove
|
||||
Ox.print('AAAAA')
|
||||
app.$ui.placesElement
|
||||
.reloadList()
|
||||
.bindEvent({loadlist: load});
|
||||
Ox.print('BBBBB')
|
||||
function load(event, data) {
|
||||
Ox.print('LOAD')
|
||||
app.$ui.placesElement
|
||||
.focusList()
|
||||
.options({selected: [id]})
|
||||
.unbindEvent({loadlist: load}); // fixme: need bindEventOnce
|
||||
}
|
||||
});
|
||||
},
|
||||
removeplace: function(event, data) {
|
||||
pandora.api.removePlace(data.id, function(result) {
|
||||
// fixme: duplicated
|
||||
Ox.Request.clearCache(); // fixme: remove
|
||||
app.$ui.placesElement
|
||||
.reloadList()
|
||||
.bindEvent({loadlist: load});
|
||||
function load(event, data) {
|
||||
app.$ui.placesElement
|
||||
.focusList()
|
||||
.unbindEvent({loadlist: load}); // fixme: need bindEventOnce
|
||||
}
|
||||
});
|
||||
}
|
||||
}),
|
||||
height: height,
|
||||
keys: {enter: 'done', escape: 'done'},
|
||||
padding: 0,
|
||||
title: 'Manage Places',
|
||||
width: width
|
||||
});
|
||||
return that;
|
||||
},
|
||||
publicListsDialog: function() { // fixme: unused
|
||||
var that = new Ox.Dialog({
|
||||
buttons: [
|
||||
|
@ -2957,7 +3027,7 @@
|
|||
resizeGroups(data);
|
||||
app.$ui.list.size();
|
||||
if (app.user.ui.lists[app.user.ui.list].listView == 'map') {
|
||||
app.$ui.map.triggerResize();
|
||||
app.$ui.map.resize();
|
||||
}
|
||||
} else {
|
||||
app.$ui.browser.scrollToSelection();
|
||||
|
@ -3305,7 +3375,7 @@
|
|||
function reloadGroups(i) {
|
||||
var query = Query.toObject();
|
||||
app.$ui.list.options({
|
||||
request: function(data, callback) {
|
||||
items: function(data, callback) {
|
||||
return pandora.api.find($.extend(data, {
|
||||
query: query
|
||||
}), callback);
|
||||
|
@ -3315,7 +3385,7 @@
|
|||
if (i_ != i) {
|
||||
//Ox.print('setting groups request', i, i_)
|
||||
app.$ui.groups[i_].options({
|
||||
request: function(data, callback) {
|
||||
items: function(data, callback) {
|
||||
delete data.keys;
|
||||
return pandora.api.find($.extend(data, {
|
||||
group: group_.id,
|
||||
|
@ -3398,7 +3468,7 @@
|
|||
app.$ui.list.size();
|
||||
resizeGroups(app.$ui.rightPanel.width());
|
||||
if (app.user.ui.listView == 'map') {
|
||||
app.$ui.map.triggerResize();
|
||||
app.$ui.map.resize();
|
||||
}
|
||||
} else {
|
||||
//Ox.print('app.$ui.window.resize');
|
||||
|
|
Loading…
Reference in a new issue