NIHVIVO 2465 and 2485 display and manage multiple rdfs labels

This commit is contained in:
tworrall 2012-06-13 18:41:25 +00:00
parent b9f3b35c7d
commit 3099c26c9a
9 changed files with 339 additions and 6 deletions

View file

@ -0,0 +1,100 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.controller.freemarker;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
import java.util.Enumeration;
import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.hp.hpl.jena.query.QuerySolution;
import com.hp.hpl.jena.query.ResultSet;
import com.hp.hpl.jena.rdf.model.Literal;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.datatypes.RDFDatatype ;
import edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission;
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.Actions;
import edu.cornell.mannlib.vitro.webapp.beans.Individual;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerHttpServlet;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
import edu.cornell.mannlib.vitro.webapp.dao.jena.QueryUtils;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
public class ManageLabelsForIndividualController extends FreemarkerHttpServlet {
private static final Log log = LogFactory.getLog(ManageLabelsForIndividualController.class.getName());
private static final String TEMPLATE_NAME = "manageLabelsForIndividual.ftl";
@Override
protected Actions requiredActions(VitroRequest vreq) {
return SimplePermission.DO_FRONT_END_EDITING.ACTIONS;
}
@Override
protected ResponseValues processRequest(VitroRequest vreq) {
Map<String, Object> body = new HashMap<String, Object>();
String subjectUri = vreq.getParameter("subjectUri");
body.put("subjectUri", subjectUri);
ArrayList<Literal> labels = getLabels(subjectUri, vreq);
log.debug("labels = " + labels) ;
body.put("labels", labels);
Individual subject = vreq.getWebappDaoFactory().getIndividualDao().getIndividualByURI(subjectUri);
if( subject != null && subject.getName() != null ){
body.put("subjectName", subject.getName());
}else{
body.put("subjectName", null);
}
return new TemplateResponseValues(TEMPLATE_NAME, body);
}
private static String LABEL_QUERY = ""
+ "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n"
+ "SELECT DISTINCT ?label WHERE { \n"
+ " ?subject rdfs:label ?label \n"
+ "} ORDER BY ?label";
ArrayList<Literal> getLabels(String subjectUri, VitroRequest vreq) {
String queryStr = QueryUtils.subUriForQueryVar(LABEL_QUERY, "subject", subjectUri);
log.debug("queryStr = " + queryStr);
ArrayList<Literal> labels = new ArrayList<Literal>();
try {
ResultSet results = QueryUtils.getQueryResults(queryStr, vreq);
while (results.hasNext()) {
QuerySolution soln = results.nextSolution();
Literal nodeLiteral = soln.get("label").asLiteral();
labels.add(nodeLiteral);
}
} catch (Exception e) {
log.error(e, e);
}
return labels;
}
}

View file

@ -3,6 +3,8 @@
package edu.cornell.mannlib.vitro.webapp.controller.individual;
import java.io.IOException;
import java.lang.Integer;
import java.lang.String;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
@ -11,6 +13,9 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.JSONException;
import com.hp.hpl.jena.query.QuerySolution;
import com.hp.hpl.jena.query.ResultSet;
import edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission;
import edu.cornell.mannlib.vitro.webapp.auth.policy.PolicyHelper;
import edu.cornell.mannlib.vitro.webapp.beans.Individual;
@ -22,6 +27,7 @@ import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.Res
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
import edu.cornell.mannlib.vitro.webapp.dao.DisplayVocabulary;
import edu.cornell.mannlib.vitro.webapp.dao.IndividualDao;
import edu.cornell.mannlib.vitro.webapp.dao.jena.QueryUtils;
import edu.cornell.mannlib.vitro.webapp.dao.ObjectPropertyDao;
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
@ -81,6 +87,7 @@ class IndividualResponseBuilder {
* into the data model: no real data can be modified.
*/
// body.put("individual", wrap(itm, BeansWrapper.EXPOSE_SAFE));
body.put("labelCount", getLabelCount(itm.getUri(), vreq));
body.put("individual", wrap(itm, new ReadOnlyBeansWrapper()));
body.put("headContent", getRdfLinkTag(itm));
@ -232,4 +239,37 @@ class IndividualResponseBuilder {
return map;
}
private static String PUBLICATION_QUERY = ""
+ "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n"
+ "SELECT ( str(COUNT(?label)) AS ?labelCount ) WHERE { \n"
+ " ?subject rdfs:label ?label \n"
+ " FILTER isLiteral(?label) \n"
+ "}" ;
private static Integer getLabelCount(String subjectUri, VitroRequest vreq) {
String queryStr = QueryUtils.subUriForQueryVar(PUBLICATION_QUERY, "subject", subjectUri);
log.debug("queryStr = " + queryStr);
int theCount = 0;
// String status = "one";
try {
ResultSet results = QueryUtils.getQueryResults(queryStr, vreq);
if (results.hasNext()) {
QuerySolution soln = results.nextSolution();
String countStr = soln.get("labelCount").toString();
log.debug("countStr = " + countStr);
theCount = Integer.parseInt(countStr);
// log.debug("theCount = " + theCount);
// if ( theCount > 1 ) {
// status = "multiple";
// }
}
} catch (Exception e) {
log.error(e, e);
}
// log.debug("status = " + status);
return theCount;
}
}

View file

@ -694,6 +694,15 @@
<url-pattern>/accounts/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>ManageLabelsForIndividualController</servlet-name>
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.freemarker.ManageLabelsForIndividualController</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ManageLabelsForIndividualController</servlet-name>
<url-pattern>/manageLabels</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>ManageProxies</servlet-name>
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.accounts.manageproxies.ManageProxiesController</servlet-class>

View file

@ -225,4 +225,25 @@ ul.dropdown ul ul {
}
ul.dropdown li:hover > ul {
visibility: visible;
}
/* ------ MANAGE LABELS ------ */
section#rdfsLabels {
margin-left:20px;
}
section#rdfsLabels li:first-child {
margin-top:20px;
}
section#rdfsLabels li {
margin-bottom:15px;
}
section#rdfsLabels li label {
font-size:1em;
padding-left:5px;
}
section#rdfsLabels a.cancel {
color:#F70;
}
p#mngLabelsText {
margin-left:25px;
margin-bottom:12px;
}

View file

@ -0,0 +1,88 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
var manageLabels = {
/* *** Initial page setup *** */
onLoad: function() {
this.mixIn();
this.initPage();
var selectedRadio;
},
mixIn: function() {
// Get the custom form data from the page
$.extend(this, customFormData);
},
// Initial page setup. Called only at page load.
initPage: function() {
$('input#submit').attr('disabled', 'disabled');
$('input#submit').addClass('disabledSubmit');
this.bindEventListeners();
},
bindEventListeners: function() {
$('input:radio').click( function() {
manageLabels.selectedRadio = $(this);
$('input#submit').attr('disabled', '');
$('input#submit').removeClass('disabledSubmit');
});
$('input#submit').click( function() {
manageLabels.processLabel(manageLabels.selectedRadio);
});
},
processLabel: function(selectedRadio) {
// PrimitiveDelete only handles one statement, so we have to use PrimitiveRdfEdit to handle multiple
// retractions if they exist. But PrimitiveRdfEdit also handles assertions, so pass an empty string
// for "additions"
var add = "";
var retract = "";
$('input:radio').each( function() {
if ( !$(this).is(':checked') ) {
retract += " <" + manageLabels.individualUri + "> <http://www.w3.org/2000/01/rdf-schema#label> "
+ "\"" + $(this).attr('id') + "\"" + $(this).attr('tagOrType') + " ." ;
}
});
retract = retract.substring(0,retract.length -1);
$.ajax({
url: manageLabels.processingUrl,
type: 'POST',
data: {
additions: add,
retractions: retract
},
dataType: 'json',
context: selectedRadio, // context for callback
complete: function(request, status) {
if (status == 'success') {
window.location = $('a.cancel').attr('href');
}
else {
alert('Error processing request: the unchecked labels could not be deleted.');
selectedRadio.removeAttr('checked');
}
}
});
},
};
$(document).ready(function() {
manageLabels.onLoad();
});

View file

@ -1,4 +1,7 @@
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
<#if !labelCount??>
<#assign labelCount = 0 >
</#if>
<#-- Default individual profile page template -->
<#--@dumpAll /-->
@ -28,8 +31,8 @@
<#else>
<h1 class="fn">
<#-- Label -->
<@p.label individual editable />
<@p.label individual editable labelCount />
<#-- Most-specific types -->
<@p.mostSpecificTypes individual /><img id="uriIcon" title="${individual.uri}" class="middle" src="${urls.images}/individual/uriIcon.gif" alt="uri icon"/>
</h1>

View file

@ -0,0 +1,64 @@
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
<#-- Custom form for managing labels for individuals -->
<#assign labelStr = "" >
<#assign languageTag = "" >
<#assign labelSeq = [] >
<#if subjectName?? >
<h2>Manage Labels for ${subjectName}</h2>
<#else>
<h2>Manage Labels</h2>
</#if>
<p id="mngLabelsText">
Multiple labels exist for this profile but there should only be one. Select the label you want displayed on the profile page, and the others will be deleted.
</p>
<section id="rdfsLabels" role="container">
<ul>
<#list labels as label>
<#-- the query will return labels with their language tag or datatype, if any. So strip those out -->
<#if label?? && ( label?index_of("@") > -1 ) >
<#assign labelStr = label?substring(0, label?index_of("@")) >
<#assign tagOrTypeStr = label?substring(label?index_of("@")) >
<#elseif label?? && ( label?index_of("^^") > -1 ) >
<#assign labelStr = label?substring(0, label?index_of("^^")) >
<#assign tagOrTypeStr = label?substring(label?index_of("^^")) >
<#assign tagOrTypeStr = tagOrTypeStr?replace("^^http","^^<http") >
<#assign tagOrTypeStr = tagOrTypeStr?replace("#string","#string>") >
<#else>
<#assign labelStr = label >
<#assign tagOrTypeStr = "" >
</#if>
<li>
<input type="radio" class="labelCheckbox" name="labelCheckbox" id="${labelStr}" tagOrType="${tagOrTypeStr!}" role="radio" />
<label class="inline">${labelStr}
<#if labelSeq?seq_contains(labelStr)>
(duplicate value)
</#if>
</label>
</li>
<#assign labelSeq = labelSeq + [labelStr]>
</#list>
</ul>
<br />
<p>
<input type="button" class="submit" id="submit" value="Save" role="button" role="input" />
<span class="or"> or </span>
<a href="${urls.referringPage}" class="cancel" title="cancel" >Cancel</a>
</p>
</section>
<script type="text/javascript">
var customFormData = {
processingUrl: '${urls.base}/edit/primitiveRdfEdit',
individualUri: '${subjectUri!}'
};
</script>
${stylesheets.add('<link rel="stylesheet" href="${urls.base}/js/jquery-ui/css/smoothness/jquery-ui-1.8.9.custom.css" />')}
${scripts.add('<script type="text/javascript" src="${urls.base}/js/utils.js"></script>',
'<script type="text/javascript" src="${urls.base}/js/jquery-ui/js/jquery-ui-1.8.9.custom.min.js"></script>',
'<script type="text/javascript" src="${urls.base}/js/individual/manageLabelsForIndividual.js"></script>')}

View file

@ -28,13 +28,13 @@
<#list group.properties as property>
<article class="property" role="article">
<#-- Property display name -->
<#if property.localName == "authorInAuthorship" >
<#if property.localName == "authorInAuthorship" && editable>
<h3 id="${property.localName}">${property.name} <@p.addLink property editable /> <@p.verboseDisplay property />
<a id="managePropLink" href="${urls.base}/managePublications?subjectUri=${subjectUri[1]!}" title="manage publications" <#if verbose>style="padding-top:10px"</#if> >
manage publications
</a>
</h3>
<#elseif property.localName == "hasResearcherRole">
<#elseif property.localName == "hasResearcherRole" && editable>
<h3 id="${property.localName}">${property.name} <@p.addLink property editable /> <@p.verboseDisplay property />
<a id="managePropLink" href="${urls.base}/manageGrants?subjectUri=${subjectUri[1]!}" title="manage grants & projects" <#if verbose>style="padding-top:10px"</#if> >
manage grants & projects

View file

@ -202,10 +202,18 @@ name will be used as the label. -->
</#macro>
<#-- Label -->
<#macro label individual editable>
<#macro label individual editable labelCount>
<#local label = individual.nameStatement>
${label.value}
<@editingLinks "label" label editable />
<#if (labelCount > 1) && editable >
<span class="inline">
<a id="manageLabels" href="${urls.base}/manageLabels?subjectUri=${individual.uri!}" style="margin-left:20px;font-size:0.7em">
manage labels
</a>
</span>
<#else>
<@editingLinks "label" label editable />
</#if>
</#macro>
<#-- Most specific types -->