Preparatory modifications before server-side contribution validation
authorveltr
Fri, 27 Sep 2013 19:12:00 +0200
changeset 127 a50e4ee7fcf2
parent 126 5768acb94ca7
child 128 a2845e7dafd9
Preparatory modifications before server-side contribution validation
src/jocondelab/static/jocondelab/js/front-notice.js
src/jocondelab/templates/jocondelab/front_describe.html
src/jocondelab/templates/jocondelab/front_notice.html
src/jocondelab/views/ajax.py
--- a/src/jocondelab/static/jocondelab/js/front-notice.js	Fri Sep 27 17:22:22 2013 +0200
+++ b/src/jocondelab/static/jocondelab/js/front-notice.js	Fri Sep 27 19:12:00 2013 +0200
@@ -9,74 +9,51 @@
         eventCache = {},
         errorCache = {};
         
-    var frSparqlTpl = _.template(
+    var sparqlTpl = _.template(
         'select distinct * where { ?s rdfs:label "<%= label %>"@<%= lang %> . '
-        + 'OPTIONAL { ?s rdfs:label ?l. ?s dbpedia-owl:abstract ?a. FILTER(lang(?a)=lang(?l)) }. '
-        + 'OPTIONAL { ?s dbpedia-owl:thumbnail ?t }. OPTIONAL { ?s dbpedia-owl:wikiPageRedirects ?r }.' 
-        + 'OPTIONAL { ?r rdfs:label ?lr. ?r dbpedia-owl:abstract ?ar FILTER(lang(?ar)=lang(?lr)) }. '
+        + 'OPTIONAL { ?s dbpedia-owl:abstract ?a. FILTER(langMatches(lang(?a),"<%= lang %>")) }. '
+        + 'OPTIONAL { ?s dbpedia-owl:thumbnail ?t }. '
+        + 'OPTIONAL { ?s dbpedia-owl:wikiPageRedirects ?r }. ' 
+        + 'OPTIONAL { ?r rdfs:label ?lr. FILTER(langMatches(lang(?lr),"<%= lang %>")) }. '
         + 'OPTIONAL { ?r dbpedia-owl:thumbnail ?tr }. '
-        + 'FILTER(!regex(?s, ":[^/]+$" ) && regex(?s, "^http://fr.dbpedia.org/resource/")) }'
-//        + 'OPTIONAL { ?s dbpedia-owl:wikiPageDisambiguates ?d }. OPTIONAL { ?d rdfs:label ?ld FILTER( langMatches( lang(?ld), "en" ) ) }. '
+        + 'OPTIONAL { ?s dbpedia-owl:wikiPageDisambiguates ?d }. '
+        + 'OPTIONAL { ?d rdfs:label ?ld FILTER( langMatches(lang(?ld), "<%= lang %>") ) }. '
+        + 'FILTER(!regex(?s, ":[^/]+$" ) && regex(?s, "^http://[^/]+/resource/")) }'
     );
-    
-    var otherSparqlTpl = _.template(
-        'select distinct * where { '
-        + '?s foaf:isPrimaryTopicOf <<%= wikipedia_url %>>. '
-        + 'OPTIONAL { ?s dbpedia-owl:wikiPageRedirects ?r }. '
-        + 'OPTIONAL { ?s rdfs:label ?l . ?s dbpedia-owl:abstract ?a . FILTER(lang(?l)=lang(?a)) }. ' 
-        + 'OPTIONAL { ?s dbpedia-owl:thumbnail ?t }. '
-        + 'OPTIONAL { ?r rdfs:label ?lr . ?r dbpedia-owl:abstract ?ar . FILTER(lang(?lr)=lang(?ar)) }. '
-        + 'OPTIONAL { ?r dbpedia-owl:thumbnail ?tr }. '
-        + '}'
-    );
-        
+            
     function getDbpedia(label, callback, errorcb) {
         
-        function onBindingsLoaded(sparqlData, initialData) {
+        function onBindingsLoaded(sparqlData) {
             var bindings = sparqlData.results.bindings,
-                res = initialData || {};
-            res.translations = _(sparqlData.results.bindings).map(function(b) {
-                var t = {}
-                t.dbpedia_uri = b.s.value;
-                if (b.r) { t.dbpedia_uri = b.r.value; }
-                if (b.a) { t.abstract = b.a.value; }
-                if (b.ar) { t.abstract = b.ar.value; }
-                if (b.t) { t.thumbnail = b.t.value; }
-                if (b.tr) { t.thumbnail = b.tr.value; }
-                if (b.l) {
-                    t.label = b.l.value;
-                    t.language = b.l["xml:lang"];
-                }
-                if (b.lr) {
-                    t.label = b.lr.value;
-                    t.language = b.lr["xml:lang"];
-                }
-                if (!t.label) {
-                    t.label = label;
-                }
-                if (!t.language) {
-                    t.language = lang;
-                }
-                return t;
-            });
-            res.local = _(res.translations).find(function(t) {
-                return t.language === lang;
-            }) || {};
-            res.label = res.local.label || label;
-            res.dbpedia_uri = res.translations[0].dbpedia_uri;
-            res.wikipedia_url = "http://" + lang + ".wikipedia.org/wiki/" + encodeURIComponent(res.label.replace(/ /g,'_'));
+                b = bindings[0],
+                res = {
+                    label: label,
+                    wikipedia_url: "http://" + lang + ".wikipedia.org/wiki/" + encodeURIComponent(label.replace(/ /g,'_'))
+                };
+            
+            if (b.a) { res.abstract = b.a.value; }
+            if (b.ar) { res.abstract = b.ar.value; }
+            if (b.t) { res.thumbnail = b.t.value; }
+            if (b.tr) { res.thumbnail = b.tr.value; }
+            if (b.lr) {
+                res.disambiguations = [];
+                res.disambiguations.push(b.lr.value);
+            }
+            if (b.s) { res.dbpedia_uri = b.s.value; }
+            if (bindings.length > 1) {
+                res.disambiguations = res.disambiguations || [];
+                _(bindings).each(function(bb) {
+                    if (bb.ld) {
+                        res.disambiguations.push(bb.ld.value);
+                    }
+                });
+            }
+            
             dbpCache[label] = res;
             _(eventCache[label]).each(function(cb) {
-                cb(label, res);
+                cb(res);
             });
             delete eventCache[label];
-            if (res.label !== label) {
-                dbpCache[res.label] = res;
-                _(eventCache[res.label]).each(function(cb) {
-                    cb(res.label, res);
-                });
-                delete eventCache[res.label];
-            }
         }
         
         function onError() {
@@ -89,7 +66,7 @@
         
         if (dbpCache[label]) {
             //console.log("Data already in cache", dbpCache[label]);
-            if (typeof callback === "function") { callback(label, dbpCache[label]); }
+            if (typeof callback === "function") { callback(dbpCache[label]); }
             return;
         }
         if (dbpCache[label] === false) {
@@ -108,37 +85,36 @@
             $.ajax({
                 url: urls.wikipedia.fr.dbpedia_sparql_url,
                 data: {
-                    query: frSparqlTpl( { label: label, lang: lang } ),
+                    query: sparqlTpl( { label: label, lang: lang } ),
                     format: "application/sparql-results+json"
                 },
                 dataType: "json",
                 success: function(data) {
                     if (data.results.bindings.length) {
                         //console.log("Data found in french DbPedia", data.results.bindings[0]);
-                        onBindingsLoaded(data, { dbpedia_language: "fr" });
+                        onBindingsLoaded(data);
                     } else {
                         if (lang !== "fr" && urls.wikipedia[lang]) {
-                            var wk_url = urls.wikipedia[lang].page_url + '/' + encodeURIComponent(label.replace(/ /g,'_'));
                             $.ajax({
                                 url: urls.wikipedia[lang].dbpedia_sparql_url,
                                 data: {
-                                    query: otherSparqlTpl({ wikipedia_url: wk_url }),
+                                    query: sparqlTpl({ label: label, lang: lang }),
                                     format: "application/sparql-results+json"
                                 },
                                 dataType: "json",
                                 success: function(data) {
                                     if (data.results.bindings.length) {
-                                        //console.log("Data found in "+lang+" DbPedia", data.results.bindings[0]);
-                                        onBindingsLoaded(data, { dbpedia_language: lang });
+                                        //console.log("Data found in", lang, "DbPedia", data.results.bindings[0]);
+                                        onBindingsLoaded(data);
                                     } else {
-                                        //console.log("Data not found in "+lang+" DbPedia");
+                                        //console.log("Data not found in", lang, "DbPedia");
                                         onError();
                                     }
                                 },
                                 error: onError
                             });
                         } else {
-                            //console.log("Data not found in french DbPedia and there is no known endpoint for "+lang);
+                            //console.log("Data not found in french DbPedia and there is no known endpoint for ", lang);
                             onError();
                         }
                     }
@@ -170,32 +146,82 @@
         }
     }
     
-    function showOverlay(label, termdata) {
+    function showOverlay(termdata) {
         if (!$curitem) {
             return;
         }
         var o = $curitem.offset();
         $overlay.css({
-            top: o.top + $curitem.outerHeight(true),
+            top: o.top + $curitem.outerHeight(),
             left: o.left - $overlay.outerWidth(true),
         }).show().attr("data-dbpedia-uri", termdata.dbpedia_uri);
-        if (termdata.local.thumbnail) {
-            $overlayImg.attr("src",termdata.local.thumbnail).show();
+        if (termdata.thumbnail) {
+            $overlayImg.attr("src",termdata.thumbnail).show();
         } else {
             $overlayImg.hide();
         }
         $h2.text(termdata.label);
-        if (label !== termdata.label) {
-            $h2.prepend($('<span style="font-style: italic;">').text(label  + " → "));
+        $abstract.text((termdata.abstract || "").replace(/^(.{240,260})\s.+$/,'$1…').substr(0,261));
+        if (termdata.disambiguations) {
+            var ul = $('<ul>');
+            _(termdata.disambiguations).forEach(function(d) {
+                ul.append(
+                    $('<li>').append(
+                        $('<a href="#">').click(function() {
+                            $(".notice-contribution-field").val(d);
+                            return false;
+                        }).text(" → " + d)
+                    )
+                );
+            });
+            $abstract.append(ul);
         }
-        $abstract.text((termdata.local.abstract || "").replace(/^(.{240,260})\s.+$/,'$1…').substr(0,261));
         $source.attr("href", termdata.wikipedia_url);
     }
     
     var tmpTemplate = '<li class="notice-term term-translated"></li>',
-        $ntl = $(".notice-contribution-list");
+        $ntl = $(".notice-contribution-list"),
+        $ncf = $(".notice-contribution-field");
     
-    $(".notice-contribution-field").autocomplete({
+    $(".contribution-frame").submit(function() {
+        var val = $ncf.val(),
+            dbpedia_uri = dbpCache[val] ? dbpCache[val].dbpedia_uri : undefined,
+            $tmpItem = $(tmpTemplate).text(gettext("Validating Resource…"));
+        console.log("Submitting", val);
+        $ncf.val("");
+        $ntl.append($tmpItem);
+        $.ajax({
+            url: urls.ajax_contribute,
+            dataType: "html",
+            type: "POST",
+            data: {
+                csrfmiddlewaretoken: csrf_token,
+                notice_id: notice_id,
+                label: val,
+//TODO: STOP SENDING dbpedia_uri WHEN IT WILL BE VALIDATED ON THE SERVER-SIDE !
+                dbpedia_uri: dbpedia_uri,
+                thesaurus_label: $ncf.attr("data-thesaurus-label")
+            },
+            success: function(html) {
+                var $el = $(html),
+                    samecontrib = $ntl.find("[data-contribution-id='" + $el.attr("data-contribution-id") + "']");
+                if (samecontrib.length) {
+                    samecontrib.replaceWith($el);
+                } else {
+                    $ntl.append($el);
+                }
+                $tmpItem.remove();
+                dbpediaBox.bind($el);
+            },
+            error: function() {
+                $tmpItem.remove();
+                alert("Couldn't validate term");
+            }
+        });
+        return false;
+    });
+    
+    $ncf.autocomplete({
         source: function( request, response ) {
             if (labelsCache[request.term]) {
                 response(labelsCache[request.term]);
@@ -230,49 +256,8 @@
             getDbpedia(ui.item.label, showOverlay);
         },
         select: function(e, ui) {
-            var $this = $(this),
-                $tmpItem = $(tmpTemplate);
-            $ntl.append($tmpItem);
-            $tmpItem.text(gettext("Validating Resource…"));
-            $this.val("");
-            getDbpedia(ui.item.label, function(label, termdata) {
-                $tmpItem.text(gettext("Saving contribution…"));
-                if (termdata.dbpedia_uri) {
-                    $.ajax({
-                        url: urls.ajax_contribute,
-                        dataType: "html",
-                        type: "POST",
-                        data: {
-                            csrfmiddlewaretoken: csrf_token,
-                            notice_id: notice_id,
-                            dbpedia_language: termdata.dbpedia_language,
-                            dbpedia_uri: termdata.dbpedia_uri,
-                            translations: JSON.stringify(termdata.translations),
-                            thesaurus_label: $this.attr("data-thesaurus-label")
-                        },
-                        success: function(html) {
-                            var $el = $(html),
-                                samecontrib = $ntl.find("[data-contribution-id='" + $el.attr("data-contribution-id") + "']");
-                            if (samecontrib.length) {
-                                samecontrib.replaceWith($el);
-                            } else {
-                                $ntl.append($el);
-                            }
-                            $tmpItem.remove();
-                            dbpediaBox.bind($el);
-                        },
-                        error: function() {
-                            $tmpItem.remove();
-                        }
-                    });
-                } else {
-                    $tmpItem.remove();
-                    alert(gettext("No DbPedia resource found for term") + " " + ui.item.label);
-                }
-            }, function() {
-                $tmpItem.remove();
-                alert(gettext("No DbPedia resource found for term") + " " + ui.item.label);
-            });
+            $ncf.val(ui.item.label);
+            $(".contribution-frame").submit();
             return false;
         },
         close: function(e, ui) {
--- a/src/jocondelab/templates/jocondelab/front_describe.html	Fri Sep 27 17:22:22 2013 +0200
+++ b/src/jocondelab/templates/jocondelab/front_describe.html	Fri Sep 27 19:12:00 2013 +0200
@@ -6,12 +6,12 @@
 {% block breadcrumbs %}<a href="{% url 'random_describe' %}">{% trans "Contibuer à l'iconographie" %}</a>{% endblock %}
 
 {% block contribution %}
-    <div class="contribution-frame description-frame">
+    <form class="contribution-frame description-frame">
         <h2>{% trans "Complétez l'iconographie" %}</h2>
         <input class="notice-contribution-field" data-thesaurus-label="REPR" type="text" size="60" placeholder="{% trans 'Que voyez-vous dans cette oeuvre ?' %}" />
         <ul class="notice-term-list notice-contribution-list contribution-novote"></ul>
         <p class="button-links">
             <a href="{% url 'random_describe' %}">{% trans 'Décrire une autre oeuvre' %}</a>
         </p>
-    </div>
+    </form>
 {% endblock %}
--- a/src/jocondelab/templates/jocondelab/front_notice.html	Fri Sep 27 17:22:22 2013 +0200
+++ b/src/jocondelab/templates/jocondelab/front_notice.html	Fri Sep 27 19:12:00 2013 +0200
@@ -123,7 +123,7 @@
                     </p>
 
 {% block contribution %}
-                    <div class="contribution-frame folksonomy-frame">
+                    <form class="contribution-frame folksonomy-frame">
                         <h2>{% trans 'Contribution (Folksonomie)' %}</h2>
                         <input class="notice-contribution-field" type="text" size="60" placeholder="{% trans 'Complétez les mots-clés de la fiche' %}" />
                         <ul class="notice-term-list notice-contribution-list">
@@ -131,7 +131,7 @@
                             {% include "jocondelab/partial/contributed_item.html" %}
                         {% endfor %}
                         </ul>
-                    </div>
+                    </form>
 {% endblock %}
 
                 </div>
--- a/src/jocondelab/views/ajax.py	Fri Sep 27 17:22:22 2013 +0200
+++ b/src/jocondelab/views/ajax.py	Fri Sep 27 19:12:00 2013 +0200
@@ -132,29 +132,28 @@
     def post(self, request):
         
         notice_id = request.POST.get('notice_id', None)
-        dbpedia_language = request.POST.get('dbpedia_language', None)
-        dbpedia_uri = request.POST.get('dbpedia_uri', None)
+        lang = request.LANGUAGE_CODE[:2]
+        dbpedia_uri = request.POST.get('dbpedia_uri', None) #TODO: Remove it and regenerate from Wikipedia/Dbpedia
         thesaurus_label = request.POST.get('thesaurus_label', None)
-        translations = json.loads(request.POST.get('translations', '[]'))
+        label = request.POST.get('label', None)
         
         thobj = Thesaurus.objects.get(label=thesaurus_label) if thesaurus_label else None
         notobj = Notice.objects.get(id=notice_id)
-        termobj, created = ContributedTerm.objects.get_or_create(dbpedia_uri=dbpedia_uri, dbpedia_language=dbpedia_language)
+        
+        # Contributed Term should be validated and Dbpedia uris should be regenerated by SPARQL Queries
+        
+        termobj, created = ContributedTerm.objects.get_or_create(dbpedia_uri=dbpedia_uri)
         controbj, created = Contribution.objects.get_or_create(term=termobj, thesaurus=thobj, notice=notobj, defaults={'contribution_count': 1})
         if not created:
             controbj.contribution_count += 1
             controbj.save()
-        for t in translations:
-            abstract = t.get('abstract', None)
-            thumbnail = t.get('thumbnail', None)
-            label = t['label']
-            language = t.get('language',request.LANGUAGE_CODE[:2])
-            fieldsobj, created = ContributedFields.objects.get_or_create(term=termobj, dbpedia_uri=dbpedia_uri, language_code=language, defaults={'abstract': abstract, 'label': label, 'thumbnail': thumbnail})
-            if not created:
-                fieldsobj.abstract = abstract
-                fieldsobj.thumbnail = thumbnail
-                fieldsobj.label = label
-                fieldsobj.save()
+        
+        # Translated labels should also be regenerated from dbpedia.
+        
+        fieldsobj, created = ContributedFields.objects.get_or_create(term=termobj, dbpedia_uri=dbpedia_uri, language_code=lang, defaults={'label': label})
+        if not created:
+            fieldsobj.label = label
+            fieldsobj.save()
         return self.render_contribution(controbj, request)