forked from 0x2620/pandora
places backend, cleanup padma metadata
This commit is contained in:
parent
44d4479a00
commit
bf518ae603
9 changed files with 137 additions and 87 deletions
|
@ -20,8 +20,10 @@
|
||||||
"canDeleteItems": {"admin": true},
|
"canDeleteItems": {"admin": true},
|
||||||
"canDownloadVideo": {"guest": 0, "member": 0, "friend": 4, "staff": 4, "admin": 4},
|
"canDownloadVideo": {"guest": 0, "member": 0, "friend": 4, "staff": 4, "admin": 4},
|
||||||
"canEditAnnotations": {"staff": true, "admin": true},
|
"canEditAnnotations": {"staff": true, "admin": true},
|
||||||
|
"canEditEvents": {"staff": true, "admin": true},
|
||||||
"canEditFeaturedLists": {"staff": true, "admin": true},
|
"canEditFeaturedLists": {"staff": true, "admin": true},
|
||||||
"canEditMetadata": {"staff": true, "admin": true},
|
"canEditMetadata": {"staff": true, "admin": true},
|
||||||
|
"canEditPlaces": {"staff": true, "admin": true},
|
||||||
"canEditSitePages": {"staff": true, "admin": true},
|
"canEditSitePages": {"staff": true, "admin": true},
|
||||||
"canEditUsers": {"admin": true},
|
"canEditUsers": {"admin": true},
|
||||||
"canPlayClips": {"guest": 2, "member": 2, "friend": 4, "staff": 4, "admin": 4},
|
"canPlayClips": {"guest": 2, "member": 2, "friend": 4, "staff": 4, "admin": 4},
|
||||||
|
|
|
@ -108,12 +108,12 @@ class Annotation(models.Model):
|
||||||
settings.CONFIG['layers']):
|
settings.CONFIG['layers']):
|
||||||
update_matching_events.delay(self.id)
|
update_matching_events.delay(self.id)
|
||||||
|
|
||||||
def json(self, layer=False, keys=None):
|
def json(self, layer=False, keys=None, user=None):
|
||||||
j = {
|
j = {
|
||||||
'user': self.user.username,
|
'user': self.user.username,
|
||||||
}
|
}
|
||||||
for field in ('id', 'in', 'out', 'value', 'created', 'modified'):
|
for key in ('id', 'in', 'out', 'value', 'created', 'modified'):
|
||||||
j[field] = getattr(self, {
|
j[key] = getattr(self, {
|
||||||
'duration': 'clip__duration',
|
'duration': 'clip__duration',
|
||||||
'hue': 'clip__hue',
|
'hue': 'clip__hue',
|
||||||
'id': 'public_id',
|
'id': 'public_id',
|
||||||
|
@ -122,7 +122,18 @@ class Annotation(models.Model):
|
||||||
'out': 'end',
|
'out': 'end',
|
||||||
'saturation': 'clip__saturation',
|
'saturation': 'clip__saturation',
|
||||||
'volume': 'clip__volume',
|
'volume': 'clip__volume',
|
||||||
}.get(field, field))
|
}.get(key, key))
|
||||||
|
|
||||||
|
l = self.get_layer()
|
||||||
|
if l['type'] == 'place':
|
||||||
|
qs = self.places.all()
|
||||||
|
if qs.count() > 0:
|
||||||
|
j['place'] = qs[0].json(user=user)
|
||||||
|
elif l['type'] == 'event':
|
||||||
|
qs = self.events.all()
|
||||||
|
if qs.count() > 0:
|
||||||
|
j['event'] = qs[0].json(user=user)
|
||||||
|
|
||||||
if layer or (keys and 'layer' in keys):
|
if layer or (keys and 'layer' in keys):
|
||||||
j['layer'] = self.layer
|
j['layer'] = self.layer
|
||||||
if keys:
|
if keys:
|
||||||
|
|
|
@ -64,8 +64,9 @@ class Event(models.Model):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
def editable(self, user):
|
def editable(self, user):
|
||||||
if self.user == user or user.is_staff:
|
if user and not user.is_anonymous() \
|
||||||
return True
|
and (self.user == user or user.get_profile().capability('canEditEvents')):
|
||||||
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_matches(self):
|
def get_matches(self):
|
||||||
|
@ -137,6 +138,7 @@ class Event(models.Model):
|
||||||
def json(self, user=None):
|
def json(self, user=None):
|
||||||
j = {
|
j = {
|
||||||
'id': self.get_id(),
|
'id': self.get_id(),
|
||||||
|
'editable': self.editable(user)
|
||||||
}
|
}
|
||||||
if self.user:
|
if self.user:
|
||||||
j['user'] = self.user.username
|
j['user'] = self.user.username
|
||||||
|
|
|
@ -435,7 +435,7 @@ class Item(models.Model):
|
||||||
user = None
|
user = None
|
||||||
qs = qs.filter(user=user)
|
qs = qs.filter(user=user)
|
||||||
for a in qs.order_by('start'):
|
for a in qs.order_by('start'):
|
||||||
ll.append(a.json())
|
ll.append(a.json(user=user))
|
||||||
return layers
|
return layers
|
||||||
|
|
||||||
def get_json(self, keys=None):
|
def get_json(self, keys=None):
|
||||||
|
@ -545,7 +545,12 @@ class Item(models.Model):
|
||||||
save(i,
|
save(i,
|
||||||
'\n'.join([f.path for f in self.files.all()]))
|
'\n'.join([f.path for f in self.files.all()]))
|
||||||
elif key['type'] == 'layer':
|
elif key['type'] == 'layer':
|
||||||
qs = Annotation.objects.filter(layer=i, item=self).order_by('start')
|
qs = Annotation.objects.filter(item=self)
|
||||||
|
if i == 'annotations':
|
||||||
|
qs = qs.filter(layer__in=Annotation.public_layers())
|
||||||
|
else:
|
||||||
|
qs = qs.filter(layer=i)
|
||||||
|
qs = qs.order_by('start')
|
||||||
save(i, u'\n'.join([l.findvalue for l in qs]))
|
save(i, u'\n'.join([l.findvalue for l in qs]))
|
||||||
elif i != '*' and i not in self.facet_keys:
|
elif i != '*' and i not in self.facet_keys:
|
||||||
value = self.get(i)
|
value = self.get(i)
|
||||||
|
|
|
@ -20,8 +20,10 @@
|
||||||
"canDeleteItems": {"admin": true},
|
"canDeleteItems": {"admin": true},
|
||||||
"canDownloadVideo": {"guest": 1, "member": 1, "staff": 4, "admin": 4},
|
"canDownloadVideo": {"guest": 1, "member": 1, "staff": 4, "admin": 4},
|
||||||
"canEditAnnotations": {"staff": true, "admin": true},
|
"canEditAnnotations": {"staff": true, "admin": true},
|
||||||
|
"canEditEvents": {"staff": true, "admin": true},
|
||||||
"canEditFeaturedLists": {"staff": true, "admin": true},
|
"canEditFeaturedLists": {"staff": true, "admin": true},
|
||||||
"canEditMetadata": {"staff": true, "admin": true},
|
"canEditMetadata": {"staff": true, "admin": true},
|
||||||
|
"canEditPlaces": {"staff": true, "admin": true},
|
||||||
"canEditSitePages": {"staff": true, "admin": true},
|
"canEditSitePages": {"staff": true, "admin": true},
|
||||||
"canEditUsers": {"admin": true},
|
"canEditUsers": {"admin": true},
|
||||||
"canPlayClips": {"guest": 1, "member": 1, "staff": 4, "admin": 4},
|
"canPlayClips": {"guest": 1, "member": 1, "staff": 4, "admin": 4},
|
||||||
|
@ -98,42 +100,12 @@
|
||||||
"sort": "title"
|
"sort": "title"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "director",
|
"id": "source",
|
||||||
"title": "Director",
|
"title": "Source",
|
||||||
"type": ["string"],
|
"type": "string",
|
||||||
"autocomplete": true,
|
|
||||||
"columnRequired": true,
|
|
||||||
"columnWidth": 180,
|
|
||||||
"filter": true,
|
|
||||||
"find": true,
|
|
||||||
"sort": "person"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "cinematographer",
|
|
||||||
"title": "Cinematographer",
|
|
||||||
"type": ["string"],
|
|
||||||
"autocomplete": true,
|
"autocomplete": true,
|
||||||
"columnWidth": 180,
|
"columnWidth": 180,
|
||||||
"filter": true,
|
"filter": true,
|
||||||
"find": true,
|
|
||||||
"sort": "person"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "features",
|
|
||||||
"title": "Features",
|
|
||||||
"type": ["string"],
|
|
||||||
"autocomplete": true,
|
|
||||||
"columnRequired": true,
|
|
||||||
"columnWidth": 180,
|
|
||||||
"filter": true,
|
|
||||||
"find": true,
|
|
||||||
"sort": "person"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "name",
|
|
||||||
"title": "Name",
|
|
||||||
"type": ["string"],
|
|
||||||
"autocomplete": true,
|
|
||||||
"find": true
|
"find": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -145,14 +117,70 @@
|
||||||
"filter": true,
|
"filter": true,
|
||||||
"find": true
|
"find": true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "topic",
|
||||||
|
"title": "Topic",
|
||||||
|
"type": ["string"],
|
||||||
|
"autocomplete": true,
|
||||||
|
"columnWidth": 180,
|
||||||
|
"filter": true,
|
||||||
|
"find": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "name",
|
||||||
|
"title": "People",
|
||||||
|
"type": ["string"],
|
||||||
|
"autocomplete": true,
|
||||||
|
"find": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "annotations",
|
||||||
|
"title": "Annotation",
|
||||||
|
"type": "string",
|
||||||
|
"find": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "keywords",
|
||||||
|
"title": "Keywords",
|
||||||
|
"type": "layer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "director",
|
||||||
|
"title": "Director",
|
||||||
|
"type": ["string"],
|
||||||
|
"autocomplete": true,
|
||||||
|
"columnRequired": true,
|
||||||
|
"columnWidth": 180,
|
||||||
|
"filter": true,
|
||||||
|
"sort": "person"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "cinematographer",
|
||||||
|
"title": "Cinematographer",
|
||||||
|
"type": ["string"],
|
||||||
|
"autocomplete": true,
|
||||||
|
"columnWidth": 180,
|
||||||
|
"filter": true,
|
||||||
|
"sort": "person"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "features",
|
||||||
|
"title": "Features",
|
||||||
|
"type": ["string"],
|
||||||
|
"autocomplete": true,
|
||||||
|
"columnRequired": true,
|
||||||
|
"columnWidth": 180,
|
||||||
|
"filter": true,
|
||||||
|
"sort": "person"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "year",
|
"id": "year",
|
||||||
"title": "Year",
|
"title": "Year",
|
||||||
"type": "year",
|
"type": "year",
|
||||||
"autocomplete": true,
|
"autocomplete": true,
|
||||||
"columnWidth": 60,
|
"columnWidth": 60,
|
||||||
"filter": true,
|
"filter": true
|
||||||
"find": true
|
//"find": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "language",
|
"id": "language",
|
||||||
|
@ -170,24 +198,6 @@
|
||||||
"columnWidth": 60,
|
"columnWidth": 60,
|
||||||
"format": {"type": "duration", "args": [0, "medium"]}
|
"format": {"type": "duration", "args": [0, "medium"]}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"id": "source",
|
|
||||||
"title": "Source",
|
|
||||||
"type": "string",
|
|
||||||
"autocomplete": true,
|
|
||||||
"columnWidth": 180,
|
|
||||||
"filter": true,
|
|
||||||
"find": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "topic",
|
|
||||||
"title": "Topic",
|
|
||||||
"type": ["string"],
|
|
||||||
"autocomplete": true,
|
|
||||||
"columnWidth": 180,
|
|
||||||
"filter": true,
|
|
||||||
"find": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"id": "location",
|
"id": "location",
|
||||||
"title": "Location",
|
"title": "Location",
|
||||||
|
@ -226,26 +236,22 @@
|
||||||
{
|
{
|
||||||
"id": "places",
|
"id": "places",
|
||||||
"title": "Places",
|
"title": "Places",
|
||||||
"type": "layer",
|
"type": "layer"
|
||||||
"find": true
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "keywords",
|
"id": "events",
|
||||||
"title": "Keywords",
|
"title": "Events",
|
||||||
"type": "layer",
|
"type": "layer"
|
||||||
"find": true
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "descriptions",
|
"id": "descriptions",
|
||||||
"title": "Descriptions",
|
"title": "Descriptions",
|
||||||
"type": "layer",
|
"type": "layer"
|
||||||
"find": true
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "transcripts",
|
"id": "transcripts",
|
||||||
"title": "Transcripts",
|
"title": "Transcripts",
|
||||||
"type": "layer",
|
"type": "layer"
|
||||||
"find": true
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "duration",
|
"id": "duration",
|
||||||
|
|
|
@ -57,12 +57,9 @@ class Place(models.Model):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
def editable(self, user):
|
def editable(self, user):
|
||||||
if not user or user.is_anonymous():
|
if user and not user.is_anonymous() \
|
||||||
level = 'guest'
|
and (self.user == user or user.get_profile().capability('canEditPlaces')):
|
||||||
else:
|
return True
|
||||||
level = user.get_profile().get_level()
|
|
||||||
if self.user == user or level in ('admin', 'staff'):
|
|
||||||
return True
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_id(self):
|
def get_id(self):
|
||||||
|
@ -83,8 +80,6 @@ class Place(models.Model):
|
||||||
return j
|
return j
|
||||||
|
|
||||||
def get_matches(self):
|
def get_matches(self):
|
||||||
layers = [l['id'] for l in filter(lambda l: l['type'] == 'place' or l.get('hasPlaces'),
|
|
||||||
settings.CONFIG['layers'])]
|
|
||||||
super_matches = []
|
super_matches = []
|
||||||
q = Q(name_find__contains=" " + self.name)|Q(name_find__contains="|%s"%self.name)
|
q = Q(name_find__contains=" " + self.name)|Q(name_find__contains="|%s"%self.name)
|
||||||
for name in self.alternativeNames:
|
for name in self.alternativeNames:
|
||||||
|
@ -94,11 +89,30 @@ class Place(models.Model):
|
||||||
for name in [self.name] + list(self.alternativeNames):
|
for name in [self.name] + list(self.alternativeNames):
|
||||||
if name in othername:
|
if name in othername:
|
||||||
super_matches.append(othername)
|
super_matches.append(othername)
|
||||||
q = Q(value__icontains=" " + self.name)|Q(value__istartswith=self.name)
|
|
||||||
for name in self.alternativeNames:
|
|
||||||
q = q|Q(value__icontains=" " + name)|Q(value__istartswith=name)
|
exact = [l['id'] for l in filter(lambda l: l['type'] == 'place', settings.CONFIG['layers'])]
|
||||||
|
if exact:
|
||||||
|
q = Q(value__iexact=self.name)
|
||||||
|
for name in self.alternativeNames:
|
||||||
|
q = q|Q(value__iexact=name)
|
||||||
|
f = q&Q(layer__in=exact)
|
||||||
|
else:
|
||||||
|
f = None
|
||||||
|
|
||||||
|
contains = [l['id'] for l in filter(lambda l: l.get('hasPlaces'), settings.CONFIG['layers'])]
|
||||||
|
if contains:
|
||||||
|
q = Q(value__icontains=" " + self.name)|Q(value__istartswith=self.name)
|
||||||
|
for name in self.alternativeNames:
|
||||||
|
q = q|Q(value__icontains=" " + name)|Q(value__istartswith=name)
|
||||||
|
contains_matches = q&Q(layer__in=contains)
|
||||||
|
if f:
|
||||||
|
f = contains_matches | f
|
||||||
|
else:
|
||||||
|
f = contains_matches
|
||||||
|
|
||||||
matches = []
|
matches = []
|
||||||
for a in Annotation.objects.filter(layer__in=layers).filter(q):
|
for a in Annotation.objects.filter(f):
|
||||||
value = a.value.lower()
|
value = a.value.lower()
|
||||||
for name in super_matches:
|
for name in super_matches:
|
||||||
value = value.replace(name.lower(), '')
|
value = value.replace(name.lower(), '')
|
||||||
|
@ -125,7 +139,11 @@ class Place(models.Model):
|
||||||
for i in Item.objects.filter(id__in=ids).exclude(id__in=self.items.all()):
|
for i in Item.objects.filter(id__in=ids).exclude(id__in=self.items.all()):
|
||||||
self.items.add(i)
|
self.items.add(i)
|
||||||
if self.matches != numberofmatches:
|
if self.matches != numberofmatches:
|
||||||
Place.objects.filter(id=self.id).update(matches=numberofmatches)
|
if numberofmatches:
|
||||||
|
Place.objects.filter(id=self.id).update(matches=numberofmatches)
|
||||||
|
else:
|
||||||
|
self.matches = numberofmatches
|
||||||
|
self.save()
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
if not self.name_sort:
|
if not self.name_sort:
|
||||||
|
|
|
@ -90,7 +90,11 @@ def editPlace(request):
|
||||||
conflict = False
|
conflict = False
|
||||||
conflict_names = []
|
conflict_names = []
|
||||||
conflict_geoname = ''
|
conflict_geoname = ''
|
||||||
for name in names + data.get('alternativeNames', []):
|
alternative_names = data.get('alternativeNames', [])
|
||||||
|
if alternative_names:
|
||||||
|
alternative_names = filter(lambda n: n.strip(), alternative_names)
|
||||||
|
data['alternativeNames'] = alternative_names
|
||||||
|
for name in names + alternative_names:
|
||||||
if models.Place.objects.filter(name_find__icontains=u'|%s|'%name).exclude(id=place.id).count() != 0:
|
if models.Place.objects.filter(name_find__icontains=u'|%s|'%name).exclude(id=place.id).count() != 0:
|
||||||
conflict = True
|
conflict = True
|
||||||
conflict_names.append(name)
|
conflict_names.append(name)
|
||||||
|
|
|
@ -64,7 +64,8 @@ pandora.ui.clipList = function(videoRatio) {
|
||||||
// if the item query contains a layer condition,
|
// if the item query contains a layer condition,
|
||||||
// then this condition is added to the clip query
|
// then this condition is added to the clip query
|
||||||
itemsQuery.conditions.forEach(function(condition) {
|
itemsQuery.conditions.forEach(function(condition) {
|
||||||
if (Ox.getIndexById(pandora.site.layers, condition.key) > -1) {
|
if (condition.key == 'annotations'
|
||||||
|
|| Ox.getIndexById(pandora.site.layers, condition.key) > -1) {
|
||||||
query.conditions.push(condition);
|
query.conditions.push(condition);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -839,7 +839,8 @@ pandora.isClipView = function(view, item) {
|
||||||
|
|
||||||
pandora.isItemFind = function(find) {
|
pandora.isItemFind = function(find) {
|
||||||
return find.conditions.length == 1
|
return find.conditions.length == 1
|
||||||
&& Ox.getIndexById(pandora.site.layers, find.conditions[0].key) > -1
|
&& (find.conditions[0].key == 'annotations'
|
||||||
|
||Ox.getIndexById(pandora.site.layers, find.conditions[0].key) > -1)
|
||||||
&& find.conditions[0].operator == '=';
|
&& find.conditions[0].operator == '=';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue