NIHVIVO 2599 and 2702 updates to addAuthorToPub to allow selection of organizations

This commit is contained in:
tworrall 2012-06-07 15:20:49 +00:00
parent 39cb99321f
commit 805ddb1d1e
4 changed files with 268 additions and 46 deletions

View file

@ -18,6 +18,7 @@
<#assign lastNameValue = lvf.getFormFieldValue(editSubmission, editConfiguration, "lastName") />
<#assign firstNameValue = lvf.getFormFieldValue(editSubmission, editConfiguration, "firstName") />
<#assign middleNameValue = lvf.getFormFieldValue(editSubmission, editConfiguration, "middleName") />
<#assign orgNameValue = lvf.getFormFieldValue(editSubmission, editConfiguration, "orgName") />
@ -104,6 +105,15 @@
<form id="addAuthorForm" action ="${submitUrl}" class="customForm noIE67">
<h3>Add an Author</h3>
<div style="display:inline">
<input type="radio" name="authorType" class="person-radio" value="" role="radio" checked style="display:inline;margin-top:20px" />
<label class="inline" for="Person" >Person</label>
<input type="radio" name="authorType" class="org-radio" value="http://xmlns.com/foaf/0.1/Organization" role="radio" style="display:inline;margin-left:18px" />
<label class="inline" for="Organization">Organization</label>
</div>
<section id="personFields" role="personContainer">
<#--These wrapper paragraph elements are important because javascript hides parent of these fields, since last name
should be visible even when first name/middle name are not, the parents should be separate for each field-->
<p class="inline">
@ -116,22 +126,39 @@
<input size="20" type="text" id="firstName" name="firstName" value="${firstNameValue}" role="input" />
</p>
<p class="inline">
<label for="middleName">Middle name <span class='hint'>(initial okay)</span></label>
<input size="20" type="text" id="middleName" name="middleName" value="${middleNameValue}" role="input" />
</p>
<input type="hidden" id="label" name="label" value="" role="input" /> <!-- Field value populated by JavaScript -->
<div id="selectedAuthor" class="acSelection">
<p class="inline">
<label>Selected author:&nbsp;</label>
<span class="acSelectionInfo" id="selectedAuthorName"></span>
<a href="${urls.base}/individual?uri=" class="verifyMatch" title="verify match">(Verify this match)</a>
<a href="${urls.base}/individual?uri=" id="personLink" class="verifyMatch" title="verify match">(Verify this match)</a>
<input type="hidden" id="personUri" name="personUri" value="" role="input" /> <!-- Field value populated by JavaScript -->
</p>
</div>
</section>
<section id="organizationFields" role="organization">
<p class="inline">
<label for="orgName">Organization name <span class='requiredHint'> *</span></label>
<input size="38" type="text" id="orgName" name="orgName" value="${orgNameValue}" role="input" />
</p>
<div id="selectedOrg" class="acSelection">
<p class="inline">
<label>Selected organization:&nbsp;</label>
<span id="selectedOrgName"></span>
<a href="${urls.base}/individual?uri=" id="orgLink" title="verify match">(Verify this match)</a>
<input type="hidden" id="orgUri" name="orgUri" value="" role="input" /> <!-- Field value populated by JavaScript -->
</p>
</div>
</section>
<input type="hidden" id="label" name="label" value="" role="input" /> <!-- Field value populated by JavaScript -->
<input type="hidden" name="rank" id="rank" value="${newRank}" role="input" />
<p class="submit">
@ -149,7 +176,10 @@
<script type="text/javascript">
var customFormData = {
rankPredicate: '${rankPredicate}',
acUrl: '${urls.base}/autocomplete?type=http://xmlns.com/foaf/0.1/Person&tokenize=true',
acUrl: '${urls.base}/autocomplete?type=',
tokenize: '&tokenize=true',
personUrl: 'http://xmlns.com/foaf/0.1/Person',
orgUrl: 'http://xmlns.com/foaf/0.1/Organization',
reorderUrl: '${urls.base}/edit/reorder'
};
</script>

View file

@ -60,8 +60,20 @@ var addAuthorForm = {
this.selectedAuthor = $('#selectedAuthor');
this.selectedAuthorName = $('#selectedAuthorName');
this.acHelpTextClass = 'acSelectorWithHelpText';
this.verifyMatch = this.form.find('.verifyMatch');
this.verifyMatch = this.form.find('.verifyMatch');
this.personRadio = $('input.person-radio');
this.orgRadio = $('input.org-radio');
this.personSection = $('section#personFields');
this.orgSection = $('section#organizationFields');
this.orgName = $('input#orgName');
this.orgNameWrapper = this.orgName.parent();
this.orgUriField = $('input#orgUri');
this.selectedOrg = $('div#selectedOrg');
this.selectedOrgName = $('span#selectedOrgName');
this.orgLink = $('a#orgLink');
this.personLink = $('a#personLink');
this.orgSection.hide();
},
// Initial page setup. Called only at page load.
@ -138,7 +150,7 @@ var addAuthorForm = {
// however.
$('#lastName').val('');
// Set the initial autocomplete help text in the acSelector field.
this.addAcHelpText();
this.addAcHelpText(this.acSelector);
return false;
@ -151,11 +163,13 @@ var addAuthorForm = {
// Hide the button that shows the form
this.showFormButtonWrapper.hide();
this.hideSelectedAuthor();
this.hideSelectedPerson();
this.hideSelectedOrg();
this.cancel.unbind('click');
this.cancel.bind('click', function() {
addAuthorForm.showAuthorListOnlyView();
addAuthorForm.setAuthorType("person");
return false;
});
@ -169,12 +183,18 @@ var addAuthorForm = {
//this.lastNameField.focus();
},
hideSelectedAuthor: function() {
hideSelectedPerson: function() {
this.selectedAuthor.hide();
this.selectedAuthorName.html('');
this.personUriField.val('');
},
hideSelectedOrg: function() {
this.selectedOrg.hide();
this.selectedOrgName.html('');
this.orgUriField.val('');
},
showFieldsForNewPerson: function() {
this.firstNameWrapper.show();
this.middleNameWrapper.show();
@ -193,9 +213,22 @@ var addAuthorForm = {
// Make cache a property of this so we can access it after removing
// an author.
this.acCache = {};
this.setAcFilter();
this.setAcFilter();
var $acField;
var urlString;
var authType;
this.lastNameField.autocomplete({
if ( this.personRadio.attr("checked") ) {
$acField = this.lastNameField;
urlString = addAuthorForm.acUrl + addAuthorForm.personUrl + addAuthorForm.tokenize;
authType = "person";
}
else {
$acField = this.orgName;
urlString = addAuthorForm.acUrl + addAuthorForm.orgUrl + addAuthorForm.tokenize;
authType = "org";
}
$acField.autocomplete({
minLength: 2,
source: function(request, response) {
if (request.term in addAuthorForm.acCache) {
@ -209,7 +242,7 @@ var addAuthorForm = {
// here instead of a get. Add the exclude uris to the data
// rather than to the url.
$.ajax({
url: addAuthorForm.acUrl,
url: urlString,
dataType: 'json',
data: {
term: request.term
@ -232,7 +265,7 @@ var addAuthorForm = {
// select event has been triggered. To trigger a select, the user must hit enter
// or click on the selection with the mouse. This appears to confuse some users.
select: function(event, ui) {
addAuthorForm.showSelectedAuthor(ui);
addAuthorForm.showSelectedAuthor(ui,authType);
}
});
@ -288,27 +321,41 @@ var addAuthorForm = {
},
// Action taken after selecting an author from the autocomplete list
showSelectedAuthor: function(ui) {
showSelectedAuthor: function(ui,authType) {
this.personUriField.val(ui.item.uri);
this.selectedAuthor.show();
if ( authType == "person" ) {
this.personUriField.val(ui.item.uri);
this.selectedAuthor.show();
// Transfer the name from the autocomplete to the selected author
// name display, and hide the last name field.
this.selectedAuthorName.html(ui.item.label);
// NB For some reason this doesn't delete the value from the last name
// field when the form is redisplayed. Thus it's done explicitly in initFormView.
this.hideFields(this.lastNameWrapper);
// These get displayed if the selection was made through an enter keystroke,
// since the keydown event on the last name field is also triggered (and
// executes first). So re-hide them here.
this.hideFieldsForNewPerson();
this.personLink.attr('href', this.verifyMatch.data('baseHref') + ui.item.uri);
}
else {
// do the same as above but for the organization fields
this.orgUriField.val(ui.item.uri);
this.selectedOrg.show();
this.selectedOrgName.html(ui.item.label);
this.hideFields(this.orgNameWrapper);
this.orgLink.attr('href', this.verifyMatch.data('baseHref') + ui.item.uri);
}
// Transfer the name from the autocomplete to the selected author
// name display, and hide the last name field.
this.selectedAuthorName.html(ui.item.label);
// NB For some reason this doesn't delete the value from the last name
// field when the form is redisplayed. Thus it's done explicitly in initFormView.
this.hideFields(this.lastNameWrapper);
// These get displayed if the selection was made through an enter keystroke,
// since the keydown event on the last name field is also triggered (and
// executes first). So re-hide them here.
this.hideFieldsForNewPerson();
this.verifyMatch.attr('href', this.verifyMatch.data('baseHref') + ui.item.uri);
// Cancel restores initial form view
this.cancel.unbind('click');
this.cancel.bind('click', function() {
addAuthorForm.initFormView();
addAuthorForm.setAuthorType(authType);
return false;
});
},
@ -432,11 +479,20 @@ var addAuthorForm = {
return false;
});
this.orgRadio.click(function() {
addAuthorForm.setAuthorType("org");
});
this.personRadio.click(function() {
addAuthorForm.setAuthorType("person");
});
this.form.submit(function() {
// NB Important JavaScript scope issue: if we call it this way, this = addAuthorForm
// in prepareSubmit. If we do this.form.submit(this.prepareSubmit); then
// this != addAuthorForm in prepareSubmit.
addAuthorForm.deleteAcHelpText();
$selectedObj = addAuthorForm.form.find('input.acSelector');
addAuthorForm.deleteAcHelpText($selectedObj);
addAuthorForm.prepareSubmit();
});
@ -451,17 +507,30 @@ var addAuthorForm = {
addAuthorForm.onLastNameChange();
});
this.verifyMatch.click(function() {
this.personLink.click(function() {
window.open($(this).attr('href'), 'verifyMatchWindow', 'width=640,height=640,scrollbars=yes,resizable=yes,status=yes,toolbar=no,menubar=no,location=no');
return false;
});
this.orgLink.click(function() {
window.open($(this).attr('href'), 'verifyMatchWindow', 'width=640,height=640,scrollbars=yes,resizable=yes,status=yes,toolbar=no,menubar=no,location=no');
return false;
});
this.acSelector.focus(function() {
addAuthorForm.deleteAcHelpText();
addAuthorForm.deleteAcHelpText(this);
});
this.acSelector.blur(function() {
addAuthorForm.addAcHelpText();
addAuthorForm.addAcHelpText(this);
});
this.orgName.focus(function() {
addAuthorForm.deleteAcHelpText(this);
});
this.orgName.blur(function() {
addAuthorForm.addAcHelpText(this);
});
// When hitting enter in last name field, show first and middle name fields.
@ -495,7 +564,7 @@ var addAuthorForm = {
name;
// If selecting an existing person, don't submit name fields
if (this.personUriField.val() != '') {
if (this.personUriField.val() != '' || this.orgUriField.val() != '' || this.orgName.val() != '' ) {
this.firstNameField.attr('disabled', 'disabled');
this.middleNameField.attr('disabled', 'disabled');
this.lastNameField.attr('disabled', 'disabled');
@ -639,21 +708,94 @@ var addAuthorForm = {
},
// Set the initial help text in the lastName field and change the class name.
addAcHelpText: function() {
addAcHelpText: function(selectedObj) {
var typeText;
if (!this.acSelector.val()) {
this.acSelector.val("Select an existing Author or add a new one.")
if ( $(selectedObj).attr('id') == "lastName" ) {
typeText = "Author";
}
else {
typeText = "Organization";
}
if (!$(selectedObj).val()) {
$(selectedObj).val("Select an existing " + typeText + " or add a new one.")
.addClass(this.acHelpTextClass);
}
},
deleteAcHelpText: function() {
if (this.acSelector.hasClass(this.acHelpTextClass)) {
this.acSelector.val('')
.removeClass(this.acHelpTextClass);
}
deleteAcHelpText: function(selectedObj) {
if ($(selectedObj).hasClass(this.acHelpTextClass)) {
$(selectedObj).val('')
.removeClass(this.acHelpTextClass);
}
},
// Depending on whether the author is a person or an organization,
// we need to set the correct class names for fields like the acSelector, acSelection, etc.
// as well as clear and disable fields, call other functions ...
setAuthorType: function(authType) {
if ( authType == "org" ) {
this.personSection.hide();
this.orgSection.show();
// person fields
this.personRadio.attr('checked', false); // needed for reset when cancel button is clicked
this.acSelector.removeClass("acSelector");
this.acSelector.removeClass(this.acHelpTextClass);
this.selectedAuthor.removeClass("acSelection");
this.selectedAuthorName.removeClass("acSelectionInfo");
this.personLink.removeClass("verifyMatch");
this.acSelector.attr('disabled', 'disabled');
this.firstNameField.attr('disabled', 'disabled');
this.middleNameField.attr('disabled', 'disabled');
this.lastNameField.attr('disabled', 'disabled');
this.acSelector.val('');
this.firstNameField.val('');
this.middleNameField.val('');
this.lastNameField.val('');
// org fields
this.orgRadio.attr('checked', true); // needed for reset when cancel button is clicked
this.orgName.addClass("acSelector");
this.selectedOrg.addClass("acSelection");
this.selectedOrgName.addClass("acSelectionInfo");
this.orgLink.addClass("verifyMatch");
this.orgName.attr('disabled', '');
this.orgUriField.attr('disabled', '');
addAuthorForm.addAcHelpText(this.orgName);
addAuthorForm.initAutocomplete();
addAuthorForm.hideSelectedPerson();
}
else if ( authType == "person" ) {
this.orgSection.hide();
this.personSection.show();
// org fields
this.orgRadio.attr('checked', false); // needed for reset when cancel button is clicked
this.orgName.removeClass("acSelector");
this.orgName.removeClass(this.acHelpTextClass);
this.selectedOrg.removeClass("acSelection");
this.selectedOrgName.removeClass("acSelectionInfo");
this.orgLink.removeClass("verifyMatch");
this.orgName.attr('disabled', 'disabled');
this.orgUriField.attr('disabled', 'disabled');
this.orgName.val('');
this.orgUriField.val('');
// person fields
this.acSelector.addClass("acSelector");
this.personRadio.attr('checked', true); // needed for reset when cancel button is clicked
this.selectedAuthor.addClass("acSelection");
this.selectedAuthorName.addClass("acSelectionInfo");
this.personLink.addClass("verifyMatch");
this.acSelector.attr('disabled', '');
this.firstNameField.attr('disabled', '');
this.middleNameField.attr('disabled', '');
this.lastNameField.attr('disabled', '');
addAuthorForm.addAcHelpText(this.acSelector);
addAuthorForm.initAutocomplete();
addAuthorForm.hideSelectedOrg();
}
}
};
$(document).ready(function() {

View file

@ -2,10 +2,14 @@
package edu.cornell.mannlib.vitro.webapp.edit.n3editing;
import java.lang.String;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import com.hp.hpl.jena.rdf.model.Literal;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.N3ValidatorVTwo;
@ -27,12 +31,22 @@ public class PublicationHasAuthorValidator implements N3ValidatorVTwo {
Map<String,String> errors = new HashMap<String,String>();
List<String> personUri = urisFromForm.get("personUri");
List<String> orgUri = urisFromForm.get("orgUri");
List<Literal> orgNameList = literalsFromForm.get("orgName");
if (allListElementsEmpty(personUri)) {
personUri = null;
}
// If there's a personUri, then we're done. The firstName and lastName fields are
if (allListElementsEmpty(orgUri)) {
orgUri = null;
}
Literal orgName = null;
if(orgNameList != null && orgNameList.size() > 0) {
orgName = orgNameList.get(0);
}
// If there's a personUri, orgUri or orgName, then we're done. The firstName and lastName fields are
// disabled and so don't get submitted.
if (personUri != null) {
if (personUri != null || orgUri != null || orgName != null ) {
return null;
}

View file

@ -57,6 +57,7 @@ public class AddAuthorsToInformationResourceGenerator extends VivoBaseGenerator
editConfiguration.addNewResource("authorshipUri", DEFAULT_NS_TOKEN);
editConfiguration.addNewResource("newPerson", DEFAULT_NS_TOKEN);
editConfiguration.addNewResource("newOrg", DEFAULT_NS_TOKEN);
//In scope
setUrisAndLiteralsInScope(editConfiguration, vreq);
@ -118,7 +119,9 @@ public class AddAuthorsToInformationResourceGenerator extends VivoBaseGenerator
getN3NewPersonLastName(),
getN3NewPerson(),
getN3AuthorshipRank(),
getN3ForExistingPerson());
getN3ForExistingPerson(),
getN3NewOrg(),
getN3ForExistingOrg());
}
@ -152,6 +155,19 @@ public class AddAuthorsToInformationResourceGenerator extends VivoBaseGenerator
"?personUri core:authorInAuthorship ?authorshipUri .";
}
private String getN3NewOrg() {
return getN3PrefixString() +
"?newOrg a foaf:Organization ;\n" +
"<" + RDFS.label.getURI() + "> ?orgName .\n" +
"?authorshipUri core:linkedAuthor ?newOrg .\n" +
"?newOrg core:authorInAuthorship ?authorshipUri . ";
}
private String getN3ForExistingOrg() {
return getN3PrefixString() +
"?authorshipUri core:linkedAuthor ?orgUri .\n" +
"?orgUri core:authorInAuthorship ?authorshipUri .";
}
/** Get new resources */
//A new authorship uri will always be created when an author is added
//A new person may be added if a person not in the system will be added as author
@ -161,6 +177,7 @@ public class AddAuthorsToInformationResourceGenerator extends VivoBaseGenerator
HashMap<String, String> newResources = new HashMap<String, String>();
newResources.put("authorshipUri", DEFAULT_NS_TOKEN);
newResources.put("newPerson", DEFAULT_NS_TOKEN);
newResources.put("newOrg", DEFAULT_NS_TOKEN);
return newResources;
}
@ -180,6 +197,7 @@ public class AddAuthorsToInformationResourceGenerator extends VivoBaseGenerator
List<String> urisOnForm = new ArrayList<String>();
//If an existing person is being used as an author, need to get the person uri
urisOnForm.add("personUri");
urisOnForm.add("orgUri");
editConfiguration.setUrisOnform(urisOnForm);
//for person who is not in system, need to add first name, last name and middle name
@ -188,6 +206,7 @@ public class AddAuthorsToInformationResourceGenerator extends VivoBaseGenerator
"middleName",
"lastName",
"rank",
"orgName",
"label");
editConfiguration.setLiteralsOnForm(literalsOnForm);
}
@ -216,6 +235,8 @@ public class AddAuthorsToInformationResourceGenerator extends VivoBaseGenerator
setLastNameField(editConfiguration);
setRankField(editConfiguration);
setPersonUriField(editConfiguration);
setOrgUriField(editConfiguration);
setOrgNameField(editConfiguration);
}
private void setLabelField(EditConfigurationVTwo editConfiguration) {
@ -278,6 +299,21 @@ public class AddAuthorsToInformationResourceGenerator extends VivoBaseGenerator
}
private void setOrgUriField(EditConfigurationVTwo editConfiguration) {
editConfiguration.addField(new FieldVTwo().
setName("orgUri")
//.setObjectClassUri(personClass)
);
}
private void setOrgNameField(EditConfigurationVTwo editConfiguration) {
editConfiguration.addField(new FieldVTwo().
setName("orgName").
setValidators(list("datatype:" + XSD.xstring.toString())).
setRangeDatatypeUri(XSD.xstring.toString())
);
}
//Form specific data
public void addFormSpecificData(EditConfigurationVTwo editConfiguration, VitroRequest vreq) {
HashMap<String, Object> formSpecificData = new HashMap<String, Object>();