display code in api browser
This commit is contained in:
parent
ca1321e2df
commit
97fc9179c9
10 changed files with 31 additions and 6 deletions
0
pandora/annotation/__init__.py
Normal file
0
pandora/annotation/__init__.py
Normal file
16
pandora/annotation/admin.py
Normal file
16
pandora/annotation/admin.py
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# vi:si:et:sw=4:sts=4:ts=4
|
||||
|
||||
from django.contrib import admin
|
||||
|
||||
import models
|
||||
|
||||
|
||||
class LayerAdmin(admin.ModelAdmin):
|
||||
search_fields = ['name', 'title']
|
||||
admin.site.register(models.Layer, LayerAdmin)
|
||||
|
||||
class AnnotationAdmin(admin.ModelAdmin):
|
||||
search_fields = ['name', 'title']
|
||||
admin.site.register(models.Annotation, AnnotationAdmin)
|
||||
|
||||
94
pandora/annotation/models.py
Normal file
94
pandora/annotation/models.py
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# vi:si:et:sw=4:sts=4:ts=4
|
||||
from __future__ import division, with_statement
|
||||
|
||||
from django.db import models
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
import utils
|
||||
|
||||
class Layer(models.Model):
|
||||
|
||||
class Meta:
|
||||
ordering = ('position', )
|
||||
|
||||
enabled = models.BooleanField(default=True)
|
||||
|
||||
name = models.CharField(null=True, max_length=255, unique=True)
|
||||
title = models.CharField(null=True, max_length=255)
|
||||
#text, string, string from list(fixme), date, place, person, pingback,
|
||||
#What about: smart layers? for date, place, person
|
||||
type = models.CharField(null=True, max_length=255)
|
||||
|
||||
#can this be changed per user?
|
||||
position = models.IntegerField(default=0)
|
||||
|
||||
overlap = models.BooleanField(default=True)
|
||||
overlay = models.BooleanField(default=True)
|
||||
public = models.BooleanField(default=True) #false=users only see there own bins
|
||||
|
||||
#find/sort integration
|
||||
find = models.BooleanField(default=True) #true part of find all
|
||||
#words / item duration(wpm), total words, cuts per minute, cuts, number of annotations, number of annotations/duration
|
||||
sort = models.CharField(null=True, max_length=255)
|
||||
|
||||
def properties(self):
|
||||
p = {}
|
||||
if self.find:
|
||||
p[self.name] = {'type': 'bin', 'find': True}
|
||||
if self.sort:
|
||||
print 'FIXME: need to add sort stuff'
|
||||
return p
|
||||
|
||||
def json(self):
|
||||
return {'id': self.name, 'title': self.title, 'type': self.type}
|
||||
|
||||
def __unicode__(self):
|
||||
return self.title
|
||||
|
||||
|
||||
class Annotation(models.Model):
|
||||
|
||||
#FIXME: here having a item,start index would be good
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
modified = models.DateTimeField(auto_now=True)
|
||||
user = models.ForeignKey(User)
|
||||
item = models.ForeignKey('item.Item', related_name='annotations')
|
||||
|
||||
#seconds
|
||||
start = models.FloatField(default=-1)
|
||||
end = models.FloatField(default=-1)
|
||||
|
||||
layer = models.ForeignKey(Layer)
|
||||
value = models.TextField()
|
||||
|
||||
def editable(self, user):
|
||||
if user.is_authenticated():
|
||||
if user.is_staff or \
|
||||
self.user == user or \
|
||||
user.groups.filter(id__in=self.groups.all()).count() > 0:
|
||||
return True
|
||||
return False
|
||||
|
||||
def html(self):
|
||||
if self.layer.type == 'string':
|
||||
return utils.html_parser(self.value)
|
||||
else:
|
||||
return self.value
|
||||
|
||||
def get_id(self):
|
||||
return ox.to32(self.id)
|
||||
|
||||
def json(self):
|
||||
return {
|
||||
'id': self.get_id(),
|
||||
'user': self.user.username,
|
||||
'start': self.start,
|
||||
'end': self.end,
|
||||
'value': self.value,
|
||||
'value_html': self.html(),
|
||||
'layer': self.layer.name
|
||||
}
|
||||
|
||||
def __unicode__(self):
|
||||
return u"%s/%s-%s" %(self.item, self.start, self.end)
|
||||
24
pandora/annotation/tests.py
Normal file
24
pandora/annotation/tests.py
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
"""
|
||||
This file demonstrates two different styles of tests (one doctest and one
|
||||
unittest). These will both pass when you run "manage.py test".
|
||||
|
||||
Replace these with more appropriate tests for your application.
|
||||
"""
|
||||
|
||||
from django.test import TestCase
|
||||
|
||||
|
||||
class SimpleTest(TestCase):
|
||||
|
||||
def test_basic_addition(self):
|
||||
"""
|
||||
Tests that 1 + 1 always equals 2.
|
||||
"""
|
||||
self.failUnlessEqual(1 + 1, 2)
|
||||
|
||||
__test__ = {"doctest": """
|
||||
Another way to test that 1 + 1 is equal to 2.
|
||||
|
||||
>>> 1 + 1 == 2
|
||||
True
|
||||
"""}
|
||||
38
pandora/annotation/utils.py
Normal file
38
pandora/annotation/utils.py
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# ci:si:et:sw=4:sts=4:ts=4
|
||||
import re
|
||||
import ox
|
||||
|
||||
|
||||
def html_parser(text, nofollow=True):
|
||||
text = text.replace('<i>', '__i__').replace('</i>', '__/i__')
|
||||
text = text.replace('<b>', '__b__').replace('</b>', '__/b__')
|
||||
#truns links into wiki links, make sure to only take http links
|
||||
text = re.sub('<a .*?href="(http.*?)".*?>(.*?)</a>', '[\\1 \\2]', text)
|
||||
text = ox.escape(text)
|
||||
text = text.replace('__i__', '<i>').replace('__/i__', '</i>')
|
||||
text = text.replace('__b__', '<b>').replace('__/b__', '</b>')
|
||||
if nofollow:
|
||||
nofollow_rel = ' rel="nofollow"'
|
||||
else:
|
||||
nofollow_rel = ''
|
||||
|
||||
links = re.compile('(\[(http.*?) (.*?)\])').findall(text)
|
||||
for t, link, txt in links:
|
||||
link = link.replace('http', '__LINK__').replace('.', '__DOT__')
|
||||
ll = '<a href="%s"%s>%s</a>' % (link, nofollow_rel, txt)
|
||||
text = text.replace(t, ll)
|
||||
links = re.compile('(\[(http.*?)\])').findall(text)
|
||||
for t, link in links:
|
||||
link = link.replace('http', '__LINK__').replace('.', '__DOT__')
|
||||
ll = '<a href="%s"%s>%s</a>' % (link, nofollow_rel, link)
|
||||
text = text.replace(t, ll)
|
||||
|
||||
text = ox.urlize(text, nofollow=nofollow)
|
||||
|
||||
#inpage links
|
||||
text = re.sub('\[(/.+?) (.+?)\]', '<a href="\\1">\\2</a>', text)
|
||||
|
||||
text = text.replace('__LINK__', 'http').replace('__DOT__', '.')
|
||||
text = text.replace("\n", '<br />')
|
||||
return text
|
||||
117
pandora/annotation/views.py
Normal file
117
pandora/annotation/views.py
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# vi:si:et:sw=4:sts=4:ts=4
|
||||
from __future__ import division
|
||||
|
||||
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
|
||||
|
||||
|
||||
def findAnnotations(request):
|
||||
'''
|
||||
param data {
|
||||
fixme
|
||||
}
|
||||
|
||||
return {
|
||||
'status': {'code': int, 'text': string}
|
||||
'data': {
|
||||
annotations = [{..}, {...}, ...]
|
||||
}
|
||||
}
|
||||
'''
|
||||
#FIXME: implement findItem like queries
|
||||
data = json.loads(request.POST['data'])
|
||||
response = json_response(status=200, text='ok')
|
||||
qs = models.Annotations.objects.filter(item__itemId=data['item'])
|
||||
response['data']['annotations'] = [a.json() for a in qs]
|
||||
return render_to_json_response(response)
|
||||
actions.register(findAnnotations)
|
||||
|
||||
|
||||
@login_required_json
|
||||
def addAnnotation(request):
|
||||
'''
|
||||
param data {
|
||||
item: itemId,
|
||||
layer: layerId,
|
||||
start: float,
|
||||
end: float,
|
||||
value: string
|
||||
}
|
||||
return {'status': {'code': int, 'text': string},
|
||||
'data': {
|
||||
'annotation': {}s
|
||||
}
|
||||
}
|
||||
'''
|
||||
data = json.loads(request.POST['data'])
|
||||
for key in ('item', 'layer', 'start', 'end', 'value'):
|
||||
if key not in data:
|
||||
return render_to_json_response(json_response(status=400,
|
||||
text='invalid data'))
|
||||
|
||||
item = get_object_or_404_json(models.Item, itemId=data['item'])
|
||||
layer = get_object_or_404_json(models.Layer, layerId=data['layer'])
|
||||
|
||||
annotation = models.Annotation(
|
||||
item=item,
|
||||
layer=layer,
|
||||
user=request.user,
|
||||
start=float(data['start']), end=float(data['end']),
|
||||
value=data['value'])
|
||||
annotation.save()
|
||||
response = json_response()
|
||||
response['data']['annotation'] = annotation.json()
|
||||
return render_to_json_response(response)
|
||||
|
||||
response = {'status': {'code': 501, 'text': 'not implemented'}}
|
||||
return render_to_json_response(response)
|
||||
actions.register(addAnnotation, cache=False)
|
||||
|
||||
|
||||
@login_required_json
|
||||
def removeAnnotation(request):
|
||||
'''
|
||||
param data {
|
||||
id:
|
||||
}
|
||||
return {'status': {'code': int, 'text': string},
|
||||
'data': {
|
||||
}
|
||||
}
|
||||
'''
|
||||
response = {'status': {'code': 501, 'text': 'not implemented'}}
|
||||
return render_to_json_response(response)
|
||||
actions.register(removeAnnotation, cache=False)
|
||||
|
||||
|
||||
@login_required_json
|
||||
def editAnnotation(request):
|
||||
'''
|
||||
param data {
|
||||
id:,
|
||||
start: float,
|
||||
end: float,
|
||||
value: string,
|
||||
}
|
||||
return {'status': {'code': int, 'text': string},
|
||||
'data': {
|
||||
}
|
||||
}
|
||||
'''
|
||||
response = json_response({})
|
||||
data = json.loads(request.POST['data'])
|
||||
layer = get_object_or_404_json(models.Layer, pk=data['id'])
|
||||
if layer.editable(request.user):
|
||||
response = json_response(status=501, text='not implemented')
|
||||
else:
|
||||
response = json_response(status=403, text='permission denied')
|
||||
return render_to_json_response(response)
|
||||
|
||||
response = json_response(status=501, text='not implemented')
|
||||
return render_to_json_response(response)
|
||||
actions.register(editAnnotation, cache=False)
|
||||
Loading…
Add table
Add a link
Reference in a new issue