diff --git a/media/js/glosses_toggle_edit.js b/media/js/glosses_toggle_edit.js
index ab546b22a..1ed23b0e4 100644
--- a/media/js/glosses_toggle_edit.js
+++ b/media/js/glosses_toggle_edit.js
@@ -112,6 +112,23 @@ function toggle_locprim(data) {
var cell = ""+locprim+"";
hCell.html(cell);
}
+
+function toggle_language_fields(data) {
+ if ($.isEmptyObject(data)) {
+ return;
+ };
+ var glossid = data.glossid;
+ var errors = data.errors;
+ var errors_lookup = '#errors_' + glossid;
+ var errorsElt = $(errors_lookup);
+ var glossCell = "ERRORS
";
+ for (var err in errors) {
+ glossCell = glossCell + "
"+errors[err]+"
";
+ }
+ glossCell = glossCell + "
";
+ errorsElt.html(glossCell);
+}
+
$(document).ready(function() {
// setup required for Ajax POST
@@ -187,7 +204,6 @@ $(document).ready(function() {
$('.quick_handedness').click(function(e)
{
e.preventDefault();
- console.log('handedness');
var glossid = $(this).attr('value');
var handedness = $(this).attr("data-handedness");
$.ajax({
@@ -201,7 +217,6 @@ $(document).ready(function() {
$('.quick_domhndsh').click(function(e)
{
e.preventDefault();
- console.log('domhndsh');
var glossid = $(this).attr('value');
var domhndsh = $(this).attr("data-domhndsh");
$.ajax({
@@ -215,7 +230,6 @@ $(document).ready(function() {
$('.quick_subhndsh').click(function(e)
{
e.preventDefault();
- console.log('subhndsh');
var glossid = $(this).attr('value');
var subhndsh = $(this).attr("data-subhndsh");
$.ajax({
@@ -229,7 +243,6 @@ $(document).ready(function() {
$('.quick_locprim').click(function(e)
{
e.preventDefault();
- console.log('locprim');
var glossid = $(this).attr('value');
var locprim = $(this).attr("data-locprim");
$.ajax({
@@ -240,4 +253,35 @@ $(document).ready(function() {
success : toggle_locprim
});
});
+
+ $('.quick_language_fields').click(function(e)
+ {
+ e.preventDefault();
+ var glossid = $(this).attr('value');
+ var errors_lookup = '#errors_' + glossid;
+ $(errors_lookup).empty()
+ var update = { 'csrfmiddlewaretoken': csrf_token };
+ for (var i=0; i < language_2chars.length; i++) {
+ var lang2char = language_2chars[i];
+ var lemma_field_key = 'lemma_' + glossid + '_'+ lang2char;
+ var lemma_field_lookup = '#'+lemma_field_key;
+ var lemma_field_value = $(lemma_field_lookup).val();
+ if (lemma_field_value != '') {
+ update[lemma_field_key] = lemma_field_value;
+ }
+ var annotation_field_key = 'annotation_' + glossid + '_'+ lang2char;
+ var annotation_field_lookup = '#'+annotation_field_key;
+ var annotation_field_value = $(annotation_field_lookup).val();
+ if (annotation_field_value != '') {
+ update[annotation_field_key] = annotation_field_value;
+ }
+ }
+ $.ajax({
+ url : url + "/dictionary/update/toggle_language_fields/" + glossid,
+ type: 'POST',
+ data: update,
+ datatype: "json",
+ success : toggle_language_fields
+ });
+ });
});
diff --git a/signbank/dictionary/adminviews.py b/signbank/dictionary/adminviews.py
index 631e1d73d..480341f35 100755
--- a/signbank/dictionary/adminviews.py
+++ b/signbank/dictionary/adminviews.py
@@ -6515,10 +6515,13 @@ def get_context_data(self, **kwargs):
if not selected_datasets or selected_datasets.count() > 1:
dataset_languages = Language.objects.filter(id=get_default_language_id())
else:
- dataset_languages = get_dataset_languages(selected_datasets).order_by('id')
+ dataset_languages = get_dataset_languages(selected_datasets).order_by('-id')
context['dataset_languages'] = dataset_languages
+ language_2chars = [str(language.language_code_2char) for language in dataset_languages]
+ context['language_2chars'] = language_2chars
+
search_form = KeyMappingSearchForm(self.request.GET, languages=dataset_languages)
context['searchform'] = search_form
diff --git a/signbank/dictionary/batch_edit.py b/signbank/dictionary/batch_edit.py
index e7f2ec7f6..864dcbb34 100644
--- a/signbank/dictionary/batch_edit.py
+++ b/signbank/dictionary/batch_edit.py
@@ -14,7 +14,7 @@
def internal_batch_update_fields_for_gloss(gloss):
- languages = gloss.lemma.dataset.translation_languages
+ languages = gloss.lemma.dataset.translation_languages.all()
gloss_prefix = str(gloss.id) + '_'
internal_batch_fields = []
for language in languages:
@@ -32,6 +32,37 @@ def internal_batch_update_fields_for_gloss(gloss):
return internal_batch_fields
+def get_value_dict(request, gloss):
+ internal_language_fields = internal_batch_update_fields_for_gloss(gloss)
+ value_dict = dict()
+ for field in internal_language_fields:
+ if field in request.POST.keys():
+ value = request.POST.get(field, '')
+ value_dict[field] = value.strip()
+ return value_dict
+
+
+def get_gloss_language_fields(gloss):
+ gloss_prefix = str(gloss.id) + '_'
+ dataset_languages = gloss.dataset.translation_languages.all()
+ language_fields_dict = dict()
+ for language in dataset_languages:
+ lemmaidglosstranslations = gloss.lemma.lemmaidglosstranslation_set.filter(language=language)
+ field_name = BatchEditForm.gloss_lemma_field_prefix + gloss_prefix + language.language_code_2char
+ if lemmaidglosstranslations.count() > 0:
+ language_fields_dict[field_name] = lemmaidglosstranslations.first().text
+ else:
+ language_fields_dict[field_name] = ''
+ for language in dataset_languages:
+ annotationidglosstranslation = gloss.annotationidglosstranslation_set.filter(language=language)
+ field_name = BatchEditForm.gloss_annotation_field_prefix + gloss_prefix + language.language_code_2char
+ if annotationidglosstranslation.count() > 0:
+ language_fields_dict[field_name] = annotationidglosstranslation.first().text
+ else:
+ language_fields_dict[field_name] = ''
+ return language_fields_dict
+
+
def get_sense_numbers(gloss):
senses_mapping = dict()
glosssenses = GlossSense.objects.filter(gloss=gloss).order_by('order')
@@ -66,6 +97,102 @@ def add_gloss_update_to_revision_history(user, gloss, field, oldvalue, newvalue)
revision.save()
+def update_lemma_translation(gloss, language_code_2char, new_value):
+ language = Language.objects.get(language_code_2char=language_code_2char)
+ try:
+ lemma_idgloss_translation = LemmaIdglossTranslation.objects.get(lemma=gloss.lemma, language=language)
+ except ObjectDoesNotExist:
+ # create an empty translation for this gloss and language
+ lemma_idgloss_translation = LemmaIdglossTranslation(lemma=gloss.lemma, language=language)
+
+ try:
+ lemma_idgloss_translation.text = new_value
+ lemma_idgloss_translation.save()
+ except (DatabaseError, ValidationError):
+ pass
+
+
+def update_annotation_translation(gloss, language_code_2char, new_value):
+ language = Language.objects.get(language_code_2char=language_code_2char)
+ try:
+ annotation_idgloss_translation = AnnotationIdglossTranslation.objects.get(gloss=gloss, language=language)
+ except ObjectDoesNotExist:
+ # create an empty translation for this gloss and language
+ annotation_idgloss_translation = AnnotationIdglossTranslation(gloss=gloss, language=language)
+
+ try:
+ annotation_idgloss_translation.text = new_value
+ annotation_idgloss_translation.save()
+ except (DatabaseError, ValidationError):
+ pass
+
+
+def check_constraints_on_gloss_language_fields(gloss, value_dict):
+ gloss_prefix = str(gloss.id) + '_'
+
+ errors = []
+
+ dataset = gloss.lemma.dataset
+ lemmaidglosstranslations = {}
+ for language in dataset.translation_languages.all():
+ lemma_key = 'lemma_' + gloss_prefix + language.language_code_2char
+ if lemma_key in value_dict.keys():
+ lemmaidglosstranslations[language] = value_dict[lemma_key]
+
+ if lemmaidglosstranslations:
+ # the lemma translations are being updated
+ lemma_group_glossset = Gloss.objects.filter(lemma=gloss.lemma)
+ if lemma_group_glossset.count() > 1:
+ more_than_one_gloss_in_lemma_group = gettext("More than one gloss in lemma group.")
+ errors.append(more_than_one_gloss_in_lemma_group)
+
+ annotationidglosstranslations = {}
+ for language in dataset.translation_languages.all():
+ annotation_key = 'annotation__' + gloss_prefix + language.language_code_2char
+ if annotation_key in value_dict.keys():
+ annotationidglosstranslations[language] = value_dict[annotation_key]
+
+ # check lemma translations
+ lemmas_per_language_translation = dict()
+ for language, lemmaidglosstranslation_text in lemmaidglosstranslations.items():
+ lemmatranslation_for_this_text_language = LemmaIdglossTranslation.objects.filter(
+ lemma__dataset=dataset, language=language, text__iexact=lemmaidglosstranslation_text)
+ lemmas_per_language_translation[language] = lemmatranslation_for_this_text_language
+
+ existing_lemmas = []
+ for language, lemmas in lemmas_per_language_translation.items():
+ if lemmas.count():
+ e5 = gettext("Lemma ID Gloss") + " (" + language.name + ") " + gettext("already exists.")
+ errors.append(e5)
+ if lemmas.first().lemma.pk not in existing_lemmas:
+ existing_lemmas.append(lemmas.first().lemma.pk)
+ if len(existing_lemmas) > 1:
+ e6 = gettext("Lemma translations refer to different already existing lemmas.")
+ errors.append(e6)
+
+ # check annotation translations
+ annotations_per_language_translation = dict()
+ for language, annotationidglosstranslation_text in annotationidglosstranslations.items():
+ annotationtranslation_for_this_text_language = AnnotationIdglossTranslation.objects.filter(
+ gloss__lemma__dataset=dataset, language=language, text__iexact=annotationidglosstranslation_text)
+ annotations_per_language_translation[language] = annotationtranslation_for_this_text_language
+
+ existing_glosses = []
+ for language, annotations in annotations_per_language_translation.items():
+ if annotations.count():
+ this_annotation = annotations.first()
+ if this_annotation.id not in existing_glosses and this_annotation.id != gloss.id:
+ existing_glosses.append(this_annotation.id)
+ e7 = gettext('Annotation ID Gloss') + " (" + language.name + ') ' + gettext(
+ 'already exists.')
+ errors.append(e7)
+ if len(existing_glosses) > 1:
+ e6 = gettext("Annotation translations refer to different already existing glosses.")
+ errors.append(e6)
+
+ return errors
+
+
def batch_edit_update_gloss(request, glossid):
"""Update the gloss fields"""
if not request.user.is_authenticated:
@@ -74,4 +201,33 @@ def batch_edit_update_gloss(request, glossid):
if not request.user.has_perm('dictionary.change_gloss'):
return {}
+ result = dict()
+
gloss = get_object_or_404(Gloss, id=glossid)
+
+ value_dict = get_value_dict(request, gloss)
+ language_fields_dict = get_gloss_language_fields(gloss)
+ fields_to_update = dict()
+ for key in value_dict.keys():
+ if value_dict[key] != language_fields_dict[key]:
+ fields_to_update[key] = value_dict[key]
+
+ errors = check_constraints_on_gloss_language_fields(gloss, fields_to_update)
+ if errors:
+ result['glossid'] = glossid
+ result['errors'] = errors
+ return result
+
+ for key in fields_to_update.keys():
+ original_value = language_fields_dict[key]
+ newvalue = fields_to_update[key]
+ language = key[-2:]
+ if key.startswith('lemma'):
+ update_lemma_translation(gloss, key[-2:], newvalue)
+ add_gloss_update_to_revision_history(request.user, gloss, 'lemma_'+language, original_value, newvalue)
+ elif key.startswith('annotation'):
+ update_annotation_translation(gloss, key[-2:], newvalue)
+ add_gloss_update_to_revision_history(request.user, gloss, 'annotation_'+language, original_value, newvalue)
+ gloss.lastUpdated = DT.datetime.now(tz=get_current_timezone())
+ gloss.save()
+ return result
diff --git a/signbank/dictionary/templates/dictionary/admin_batch_edit_view.html b/signbank/dictionary/templates/dictionary/admin_batch_edit_view.html
index 019097a50..47007e6ff 100644
--- a/signbank/dictionary/templates/dictionary/admin_batch_edit_view.html
+++ b/signbank/dictionary/templates/dictionary/admin_batch_edit_view.html
@@ -23,6 +23,7 @@
var multiple_select_fields = {{MULTIPLE_SELECT_GLOSS_FIELDS|safe}};
var query_parameters_keys = {{query_parameters_keys|safe}};
var query_parameters_dict = {{query_parameters|safe}};
+var language_2chars = {{language_2chars|safe}};
@@ -271,7 +272,7 @@
{% trans "On initial view, the most recent query results are shown." %}
{% trans "Gloss" %}
-
{% trans "Fields" %}
+
{% trans "Fields" %}
{% trans "Quick Toggles" %}
{% trans "Tags" %}
@@ -344,53 +345,63 @@
{% trans "On initial view, the most recent query results are shown." %}
{% csrf_token %}
- {% for dataset_lang in dataset_languages %}
- {% with gloss.lemma|get_lemma_idgloss_translation:dataset_lang as lemmaidglosstranslation %}
-
- {% trans "Lemma" %} ({{dataset_lang.language_code_2char|upper}})
+ {% for dataset_lang in dataset_languages %}
+
+ {% trans "Lemma" %} ({{dataset_lang.name}})
+ {% endfor %}
+
+
+ {% for dataset_lang in dataset_languages %}
+ {% with gloss.lemma|get_lemma_idgloss_translation:dataset_lang as lemmaidglosstranslation %}
-
{% endwith %}
{% endfor %}
- {% for dataset_lang in dataset_languages %}
- {% with gloss|get_annotation_idgloss_translation_no_default:dataset_lang as annotationidglosstranslation %}
+
-
- {% trans "Annotation" %} ({{dataset_lang.language_code_2char|upper}})
+ {% for dataset_lang in dataset_languages %}
+
+ {% trans "Annotation" %} ({{dataset_lang.name}})
+ {% endfor %}
+
+
+ {% for dataset_lang in dataset_languages %}
+ {% with gloss|get_annotation_idgloss_translation_no_default:dataset_lang as annotationidglosstranslation %}
-
{% endwith %}
{% endfor %}
+
{% with gloss|get_senses_mapping as senses_mapping %}
{% for order, translations in senses_mapping.items %}
- {% for sense_lang, sensetranslation in translations.items %}
- {% with sense_lang|upper as language %}
-
- {% trans "Sense" %} #{{order}} ({{language}})
+ {% for dataset_lang in dataset_languages %}
+
+ {% trans "Sense" %} #{{order}} ({{dataset_lang.name}})
+ {% endfor %}
+
+
+ {% for sense_lang, sensetranslation in translations.items %}