Skip to content

Commit

Permalink
Merge pull request #136 from diging/develop
Browse files Browse the repository at this point in the history
prepare release
  • Loading branch information
jdamerow authored Mar 7, 2019
2 parents 588c931 + 2a0989e commit 6ea1483
Show file tree
Hide file tree
Showing 10 changed files with 160 additions and 26 deletions.
5 changes: 4 additions & 1 deletion annotations/annotators.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ def my_view(request, text_id):
from annotations.utils import basepath
from annotations.models import TextCollection, VogonUserDefaultProject
from urlparse import urlparse
import chardet


class Annotator(object):
Expand Down Expand Up @@ -153,11 +154,13 @@ def render_display(self, context={}):
def get_context(self):
resource = self.get_resource()
request = self.context.get('request')
content = self.get_content(resource)
detect = chardet.detect(content)
return {
'text': self.text,
'textid': self.text.id,
'title': 'Annotate Text',
'content': self.get_content(resource),
'content': content.decode(detect['encoding']).encode('utf-8'), # We are using chardet to guess the encoding becuase giles is returning everyting with a utf-8 header even if it is not utf-8
'baselocation' : basepath(request),
'userid': request.user.id,
'title': self.text.title,
Expand Down
1 change: 1 addition & 0 deletions annotations/static/annotations/css/annotators/text.css
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@
font-size: 0.8em;
padding: 5px;
border: 0.5px solid #ddd;
max-height: auto;
}
.appellation-creator .form-control {
font-size: 1.0em;
Expand Down
131 changes: 125 additions & 6 deletions annotations/static/annotations/js/annotators/text.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ var ConceptSearch = {
search: function() {
this.searching = true; // Instant feedback for the user.

this.$emit('search', this.searching); // emit search to remove concept picker

// Asynchronous quries are beautiful.
var self = this; // Need a closure since Concept is global.
var payload = {search: this.query};
Expand Down Expand Up @@ -178,7 +180,7 @@ ConceptCreator = {
name: "",
description: "",
concept_type: "",
pos: "noun",
pos: "",
concept_types: [],
error: false,
submitted: false
Expand Down Expand Up @@ -258,6 +260,7 @@ DateAppellationCreator = {
day: null,
submitted: false,
saving: false

}
},
template: `<div class="appellation-creator">
Expand Down Expand Up @@ -327,24 +330,121 @@ DateAppellationCreator = {
}
}
}
ConceptPickerItem = {
props: ['concept'],
components: {
},
template: `<div class="list-group-item concept-item clearfix" id="concept-{{ concept.interpretation.uri }}">
<div>
<a v-on:click="select" style="cursor: pointer;">{{ concept.interpretation_label }} ({{ concept.interpretation.authority }})</a>
</div>
<div class="text text-muted">{{ concept.interpretation.description }}</div>
</div>`,
methods: {
select: function() {
this.$emit('selectconcept', this.concept);
},

}
}

ConceptPicker = {
props: ['appellations'],
components: {
'concept-picker-item': ConceptPickerItem
},
data: function() {
return {
conceptsFinal: [],
appell: [],
appellationCount: [],
}
},
template: `<div class="concept-picker" style="max-height: 50vh; overflow-y: scroll;">
<concept-picker-item
v-on:selectconcept="selectConcept"
v-for="concept in conceptsFinal"
v-bind:concept=concept>
</concept-picker-item>
</div>`,
methods: {
selectConcept: function(concept) {
// Clear the concept search results.
this.concepts = [];
this.$emit('selectconcept', concept);
},
addConcepts: function (appellationMapEntires) {
var count = 0
while(count <= 3) {
var appellation = appellationMapEntires.next().value;
if (appellation == null) {
break
}
if (!this.conceptsFinal.includes(appellation[1][0])){
this.conceptsFinal.push(appellation[1][0]);
count++;
}
}
},
merge: function (appellations) {
this.conceptsFinal = [];
this.appell = appellations;
// Sort by date
function compare(a,b) {
if (Date.parse(a.created) > Date.parse(b.created))
return -1;
if (Date.parse(a.created) < Date.parse(b.created))
return 1;
return 0;
}
this.appell.sort(compare);
var appellationMap = new Map();
// set map items from appell array
this.appell.forEach(function(item){
if (appellationMap.has(item.interpretation.uri)) {
appellationMap.get(item.interpretation.uri).push(item);
} else {
appellationMap.set(item.interpretation.uri, [item]);
}
});
var appellationMapEntires = appellationMap.entries();
// add non-duplicate objects to conceptsFinal sorted by most recent
this.addConcepts(appellationMapEntires);
// sort appellationMap by length
var sortedMap = new Map([...appellationMap.entries()].sort(function (a, b) {
return b[1].length - a[1].length
}));
var sortedMapItems = sortedMap.entries();
// add non-duplicate objects to conceptsFinal sorted by most occuring
this.addConcepts(sortedMapItems);
return this.conceptsFinal;
},
},
created: function () {
this.merge(this.appellations);

},
}

AppellationCreator = {
props: ["position", "user", "text", "project"],
props: ["position", "user", "text", "project", 'appellations'],
components: {
'concept-search': ConceptSearch,
'concept-creator': ConceptCreator
'concept-creator': ConceptCreator,
'concept-picker': ConceptPicker
},
data: function() {
return {
concept: null,
create: false,
submitted: false,
saving: false
saving: false,
search: false,
display: true

}
},
template: `<div class="appellation-creator" style="max-height: 300px; overflow-y: scroll;">
template: `<div class="appellation-creator" style="max-height: 80vh; overflow-y: scroll;">
<div class="h4">
What is this?
<span class="glyphicon glyphicon-question-sign"
Expand Down Expand Up @@ -378,24 +478,42 @@ AppellationCreator = {
</div>
</div>
<concept-search
@search="setSearch"
v-if="concept == null && !create"
v-on:selectconcept="selectConcept">
</concept-search>
<concept-creator
v-if="create && concept == null"
v-on:createdconcept="createdConcept">
</concept-creator>
<concept-picker
v-show="display"
v-if="concept == null && !create"
v-bind:appellations=appellations
v-on:selectconcept="selectConcept">
</concept-picker>
<div>
<a v-on:click="cancel" class="btn btn-xs btn-danger">Cancel</a>
</div>
</div>`,

watch: {
search: function () {
if (this.search == true){
this.display = false;
}
}
},
methods: {
reset: function() {
this.concept = null;
this.create = false;
this.submitted = false;
this.saving = false;
},
setSearch: function (search) { // removes concept picker if searching concept to keep it from looking messy
this.search = search;
},
cancel: function() {
this.reset();
this.$emit('cancelappellation');
Expand Down Expand Up @@ -425,7 +543,7 @@ AppellationCreator = {
occursIn: this.text.id,
createdBy: this.user.id,
project: this.project.id,
interpretation: this.concept.uri
interpretation: this.concept.uri || this.concept.interpretation.uri
}).then(function(response) {
self.reset();
self.$emit('createdappellation', response.body);
Expand Down Expand Up @@ -1015,6 +1133,7 @@ Appellator = new Vue({
self.appellations.push(appellation);
self.selectAppellation(appellation);
this.selected_text = null;
this.updateAppellations(); // call update appellations when a new appelation is created to update list
},
createdDateAppellation: function(appellation) {
self = this;
Expand Down
23 changes: 13 additions & 10 deletions annotations/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
from django.contrib.contenttypes.models import ContentType

import requests, uuid, re
from datetime import datetime, timedelta
from django.utils import timezone
from itertools import groupby, chain
from collections import defaultdict

Expand Down Expand Up @@ -235,16 +237,17 @@ def accession_ready_relationsets():
relationsets = defaultdict(lambda: defaultdict(list))

for relationset in qs:
relationsets[relationset.occursIn.id][relationset.createdBy.id].append(relationset)
for text_id, text_rsets in relationsets.iteritems():
for user_id, user_rsets in text_rsets.iteritems():

# Update state.
def _state(obj):
obj.pending = True
obj.save()
map(_state, user_rsets)
submit_relationsets_to_quadriga.delay(map(lambda o: o.id, user_rsets), text_id, user_id, **kwargs)
timeCreated = relationset.created
if timeCreated + timedelta(days=settings.SUBMIT_WAIT_TIME['days'], hours=settings.SUBMIT_WAIT_TIME['hours'], minutes=settings.SUBMIT_WAIT_TIME['minutes']) < datetime.now(timezone.utc):
relationsets[relationset.occursIn.id][relationset.createdBy.id].append(relationset)
for text_id, text_rsets in relationsets.iteritems():
for user_id, user_rsets in text_rsets.iteritems():
# Update state.
def _state(obj):
obj.pending = True
obj.save()
map(_state, user_rsets)
submit_relationsets_to_quadriga.delay(map(lambda o: o.id, user_rsets), text_id, user_id, **kwargs)


# TODO: this should be retired.
Expand Down
5 changes: 3 additions & 2 deletions annotations/templates/annotations/vue.html
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,8 @@
v-bind:project=project
v-bind:position=selected_text
v-on:cancelappellation="cancelAppellation"
v-on:createdappellation="createdAppellation">
v-on:createdappellation="createdAppellation"
v-bind:appellations=appellations>
</appellation-creator>
</div>
<div v-bind:class="{
Expand Down Expand Up @@ -231,7 +232,7 @@
var USER_NAME = '{{ user.username }}';
var PROJECT_ID = '{{ project.id }}';
var PROJECT_NAME = '{{ project.name }}';
var TEXT_CONTENT = `{{ content|safe }}`;
var TEXT_CONTENT = `{{ content|safe }}`; // the safe tag suppresses unicode errors
var BASE_URL = '{{ base_url }}';

// Appellator is the text annotation application. Even though we load
Expand Down
5 changes: 2 additions & 3 deletions annotations/views/repository_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,21 +97,20 @@ def repository_collection(request, repository_id, collection_id):
collection = manager.collection(id=collection_id, **params)
except IOError:
return render(request, 'annotations/repository_ioerror.html', {}, status=500)

project_id = request.GET.get('project_id')
base_url = reverse('repository_collection', args=(repository_id, collection_id))
base_params = {}
if project_id:
base_params.update({'project_id': project_id})

resources = collection.get('resources', [])
context = {
'user': request.user,
'repository': repository,
'collection': collection,
'collection_id': collection_id,
'title': 'Browse collections in %s' % repository.name,
'project_id': project_id,
'resources': collection.get('resources', []),
'resources': [resource for resource in resources if resource['url']],
'subcollections': collection.get('subcollections', [])
}
previous_page, next_page = _get_pagination(collection, base_url, base_params)
Expand Down
1 change: 0 additions & 1 deletion annotations/views/rest_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,6 @@ def create(self, request, *args, **kwargs):

try:
serializer.is_valid(raise_exception=True)
print 'asdfasdfasdf'
except Exception as E:
print serializer.errors
raise E
Expand Down
Binary file modified celerybeat-schedule.db
Binary file not shown.
7 changes: 5 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ anyjson==0.3.3
black-goat-client==0.2.6
bleach==1.4.2
celery==3.1.25
certifi==2018.1.18
chardet==3.0.4
conceptpower-api==1.9
dicttoxml==1.6.6
dj-database-url==0.3.0
dj-static==0.0.6
Django==1.10.6
Expand Down Expand Up @@ -34,9 +37,9 @@ pytz==2016.10
redis==2.10.3
requests==2.13.0
requests-oauthlib==0.5.0
restable>=0.1.3
restable==0.1.3
six==1.10.0
Unidecode==0.4.20
urllib3==1.19.1
xmltodict==0.10.2
dicttoxml==1.6.6
six==1.10.0
8 changes: 7 additions & 1 deletion vogon/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@
CELERYBEAT_SCHEDULE = {
'accession_ready_relationsets': {
'task': 'annotations.tasks.accession_ready_relationsets',
'schedule': timedelta(seconds=600),
'schedule': timedelta(minutes=10,seconds=0),
},
}

Expand Down Expand Up @@ -258,3 +258,9 @@
'viaf:corporate': CORPORATE_CONCEPT_TYPE, # E40 Legal Body
'viaf:geographic': GEOGRAPHIC_CONCEPT_TYPE, # E53 Place
}

SUBMIT_WAIT_TIME = {
'days': 3,
'hours': 0,
'minutes': 0
}

0 comments on commit 6ea1483

Please sign in to comment.