VIVO-743: custom form to add a person to a project

This commit is contained in:
Tim Worrall 2014-05-30 16:22:53 -04:00
parent 5575bda929
commit 02a2fe600c
6 changed files with 450 additions and 1 deletions

View file

@ -878,3 +878,4 @@ missing_credential = falta credencial
grant_administered_by = conceder administrado por
missing_grant = falta de subvención
editor_of_entry = editor de para
researcher_role = El papel del investigador en el proyecto

View file

@ -0,0 +1,81 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
var projectHasParticipantUtils = {
onLoad: function(blankSentinel) {
this.sentinel = '';
if ( blankSentinel ) { this.sentinel = blankSentinel; }
this.initObjectReferences();
this.bindEventListeners();
$.extend(this, vitro.customFormUtils);
$.extend(this, i18nStrings);
if ( this.findValidationErrors() ) {
this.resetLastNameLabel();
}
},
initObjectReferences: function() {
this.form = $('#projectHasParticipant');
this.person = $('#person');
this.fauxLabel = $('#maskLabelBuilding');
this.firstName = $('#firstName');
this.lastName = $('#lastName');
this.personUri = $('#personUri');
// may not need this
this.firstName.attr('disabled', '');
},
bindEventListeners: function() {
this.idCache = {};
this.form.submit(function() {
projectHasParticipantUtils.resolveFirstLastNames();
});
},
resolveFirstLastNames: function() {
var firstName,
lastName,
name;
// If selecting an existing person, don't submit name fields
if (this.personUri.val() == '' || this.personUri.val() == this.sentinel ) {
firstName = this.firstName.val();
lastName = this.person.val();
name = lastName;
if (firstName) {
name += ', ' + firstName;
}
// we don't want the user to see the label getting built, so hide the acSelector
// field and display a bogus field that just has the last name in it.
this.fauxLabel.val(lastName);
this.person.hide();
this.fauxLabel.show();
this.person.val(name);
this.lastName.val(lastName);
}
else {
this.firstName.attr('disabled', 'disabled');
this.lastName.attr('disabled', 'disabled');
}
},
resetLastNameLabel: function() {
var indx = this.person.val().indexOf(", ");
if ( indx != -1 ) {
var temp = this.person.val().substr(0,indx);
this.person.val(temp);
}
},
}

View file

@ -0,0 +1,181 @@
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
<#-- this is in request.subject.name -->
<#-- leaving this edit/add mode code in for reference in case we decide we need it -->
<#import "lib-vivo-form.ftl" as lvf>
<#assign subjectName=""/>
<#assign roleActivityUri="mysteryRoleActivityURI"/>
<#assign personLabel="mysteryPersonLabel"/>
<#--Retrieve certain edit configuration information-->
<#assign editMode = editConfiguration.pageData.editMode />
<#assign htmlForElements = editConfiguration.pageData.htmlForElements />
<#--The blank sentinel indicates what value should be put in a URI when no autocomplete result has been selected.
If the blank value is non-null or non-empty, n3 editing for an existing object will remove the original relationship
if nothing is selected for that object-->
<#assign blankSentinel = "" />
<#if editConfigurationConstants?has_content && editConfigurationConstants?keys?seq_contains("BLANK_SENTINEL")>
<#assign blankSentinel = editConfigurationConstants["BLANK_SENTINEL"] />
</#if>
<#--This flag is for clearing the label field on submission for an existing object being selected from autocomplete.
Set this flag on the input acUriReceiver where you would like this behavior to occur. -->
<#assign flagClearLabelForExisting = "flagClearLabelForExisting" />
<#--Retrieve variables needed-->
<#assign firstNameValue = lvf.getFormFieldValue(editSubmission, editConfiguration, "firstName")/>
<#assign lastNameValue = lvf.getFormFieldValue(editSubmission, editConfiguration, "lastName") />
<#assign personLabelValue = lvf.getFormFieldValue(editSubmission, editConfiguration, "personLabel") />
<#assign personLabelDisplayValue = lvf.getFormFieldValue(editSubmission, editConfiguration, "personLabelDisplay") />
<#assign existingPersonValue = lvf.getFormFieldValue(editSubmission, editConfiguration, "existingPerson") />
<#assign roleLabelValue = lvf.getFormFieldValue(editSubmission, editConfiguration, "roleLabel") />
<#-- If edit submission exists, then retrieve validation errors if they exist-->
<#if editSubmission?has_content && editSubmission.submissionExists = true && editSubmission.validationErrors?has_content>
<#assign submissionErrors = editSubmission.validationErrors/>
</#if>
<#if editMode == "edit" || editMode == "repair">
<#assign titleVerb="${i18n().edit_capitalized}">
<#assign submitButtonText="${i18n().save_changes}">
<#assign disabledVal="disabled">
<#else>
<#assign titleVerb="${i18n().create_capitalized}">
<#assign submitButtonText="${i18n().create_entry}">
<#assign disabledVal=""/>
</#if>
<#assign requiredHint = "<span class='requiredHint'> *</span>" />
<#assign yearHint = "<span class='hint'>(${i18n().year_hint_format})</span>" />
<h2>${titleVerb}&nbsp;${i18n().researcher}&nbsp;${i18n().to} ${editConfiguration.subjectName}</h2>
<#--Display error messages if any-->
<#if submissionErrors?has_content>
<#if personLabelDisplayValue?has_content >
<#assign personLabelValue = personLabelDisplayValue />
</#if>
<section id="error-alert" role="alert">
<img src="${urls.images}/iconAlert.png" width="24" height="24" alert="${i18n().error_alert_icon}" />
<p>
<#--below shows examples of both printing out all error messages and checking the error message for a specific field-->
<#list submissionErrors?keys as errorFieldName>
<#if errorFieldName == "startField">
<#if submissionErrors[errorFieldName]?contains("before")>
${i18n().start_year_must_precede_end}
<#else>
${submissionErrors[errorFieldName]}
</#if>
<br />
<#elseif errorFieldName == "endField">
<#if submissionErrors[errorFieldName]?contains("after")>
${i18n().end_year_must_be_later}
<#else>
${submissionErrors[errorFieldName]}
</#if>
<#else>
${submissionErrors[errorFieldName]}
</#if>
</#list>
<#--Checking if Person Type field is empty-->
<#if lvf.submissionErrorExists(editSubmission, "personType")>
${i18n().select_person_type}
</#if>
<#--Checking if Person Name field is empty-->
<#if lvf.submissionErrorExists(editSubmission, "personLabel")>
${i18n().select_an_person_name}
</#if>
<#--Checking if Training Type field is empty-->
<#if lvf.submissionErrorExists(editSubmission, "trainingType")>
${i18n().select_educational_training_value}<br />
</#if>
</p>
</section>
</#if>
<@lvf.unsupportedBrowser urls.base />
<section id="projectHasParticipant" role="region">
<form id="projectHasParticipant" class="customForm noIE67" action="${submitUrl}" role="add/edit organizational training">
<p >
<label for="person">${i18n().person_capitalized}: ${i18n().last_name} ${requiredHint}<span style="padding-left:322px">${i18n().first_name} ${requiredHint}</span></label>
<input class="acSelector" size="50" type="text" acGroupName="person" id="person" name="personLabel" value="${personLabelValue}" >
<input type="text" size="50" id="maskLabelBuilding" name="maskLabelBuilding" value="" style="display:none" >
<input size="30" type="text" id="firstName" name="firstName" value="${firstNameValue}" ><br />
<input type="hidden" id="lastName" name="lastName" value="">
<input class="display" type="hidden" acGroupName="person" id="personDisplay" name="personLabelDisplay" value="${personLabelDisplayValue}" >
</p>
<div class="acSelection" acGroupName="person">
<p class="inline">
<label>${i18n().selected_person}:</label>
<span class="acSelectionInfo"></span>
<a href="" class="verifyMatch" title="${i18n().verify_match_capitalized}">(${i18n().verify_match_capitalized}</a> ${i18n().or}
<a href="#" class="changeSelection" id="changeSelection">${i18n().change_selection})</a>
</p>
<input class="acUriReceiver" type="hidden" id="personUri" name="existingPerson" value="${existingPersonValue}" ${flagClearLabelForExisting}="true" />
</div>
<p>
<label for="dept">${i18n().researcher_role} ${requiredHint}</label>
<input size="50" type="text" id="roleLabel" name="roleLabel" value="${roleLabelValue}" />
</p>
<#--End draw elements-->
<input type="hidden" id="editKey" name="editKey" value="${editKey}"/>
<p class="submit">
<input type="submit" id="submit" value="${submitButtonText}"/><span class="or"> ${i18n().or} </span>
<a class="cancel" href="${cancelUrl}" title="${i18n().cancel_title}">${i18n().cancel_link}</a>
</p>
<p id="requiredLegend" class="requiredHint">* ${i18n().required_fields}</p>
</form>
<script type="text/javascript">
var customFormData = {
acUrl: '${urls.base}/autocomplete?tokenize=true&stem=true',
editMode: '${editMode}',
acTypes: {person: 'http://xmlns.com/foaf/0.1/Person'},
defaultTypeName: 'person',
baseHref: '${urls.base}/individual?uri=',
blankSentinel: '${blankSentinel}',
flagClearLabelForExisting: '${flagClearLabelForExisting}',
subjectName: '${editConfiguration.subjectName}'
};
var i18nStrings = {
selectAnExisting: '${i18n().select_an_existing}',
orCreateNewOne: '${i18n().or_create_new_one}',
selectedString: '${i18n().selected}'
};
$(document).ready(function() {
projectHasParticipantUtils.onLoad('${blankSentinel}');
});
</script>
</section>
${stylesheets.add('<link rel="stylesheet" href="${urls.base}/js/jquery-ui/css/smoothness/jquery-ui-1.8.9.custom.css" />')}
${stylesheets.add('<link rel="stylesheet" href="${urls.base}/templates/freemarker/edit/forms/css/customForm.css" />')}
${stylesheets.add('<link rel="stylesheet" href="${urls.base}/templates/freemarker/edit/forms/css/customFormWithAutocomplete.css" />')}
${scripts.add('<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/customFormUtils.js"></script>',
'<script type="text/javascript" src="${urls.base}/js/extensions/String.js"></script>',
'<script type="text/javascript" src="${urls.base}/js/browserUtils.js"></script>',
'<script type="text/javascript" src="${urls.base}/js/jquery_plugins/jquery.bgiframe.pack.js"></script>',
'<script type="text/javascript" src="${urls.base}/templates/freemarker/edit/forms/js/projectHasParticipantUtils.js"></script>',
'<script type="text/javascript" src="${urls.base}/templates/freemarker/edit/forms/js/customFormWithAutocomplete.js"></script>')}

View file

@ -1745,6 +1745,7 @@ local:bfo_0000055Config a :ObjectPropertyDisplayConfig ;
vitro:displayRankAnnot 17;
vitro:hiddenFromDisplayBelowRoleLevelAnnot role:public ;
vitro:prohibitedFromUpdateBelowRoleLevelAnnot role:nobody ;
vitro:customEntryFormAnnot "edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.generators.ProjectHasParticipantGenerator"^^<http://www.w3.org/2001/XMLSchema#string> ;
:propertyGroup <http://vivoweb.org/ontology#vitroPropertyGroupoverview> .
### grant roles using the core:relates property ###

View file

@ -0,0 +1,184 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.generators;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import javax.servlet.http.HttpSession;
import com.hp.hpl.jena.vocabulary.XSD;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.FirstAndLastNameValidator;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.DateTimeIntervalValidationVTwo;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.DateTimeWithPrecisionVTwo;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationVTwo;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.fields.ChildVClassesOptions;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.fields.ChildVClassesWithParent;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.fields.FieldVTwo;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.fields.IndividualsViaVClassOptions;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.validators.AntiXssValidation;
import edu.cornell.mannlib.vitro.webapp.utils.FrontEndEditingUtils.EditMode;
import edu.cornell.mannlib.vitro.webapp.utils.generators.EditModeUtils;
public class ProjectHasParticipantGenerator extends VivoBaseGenerator implements EditConfigurationGenerator{
//TODO: can we get rid of the session and get it form the vreq?
public EditConfigurationVTwo getEditConfiguration(VitroRequest vreq, HttpSession session) throws Exception {
EditConfigurationVTwo conf = new EditConfigurationVTwo();
initBasics(conf, vreq);
initPropertyParameters(vreq, session, conf);
initObjectPropForm(conf, vreq);
conf.setTemplate("projectHasParticipant.ftl");
conf.setVarNameForSubject("project");
conf.setVarNameForPredicate("predicate");
conf.setVarNameForObject("projectRole");
conf.setN3Required( Arrays.asList( n3ForNewProjectRole ) );
conf.setN3Optional(Arrays.asList( n3ForNewPerson, n3ForExistingPerson, firstNameAssertion, lastNameAssertion ) );
conf.addNewResource("projectRole", DEFAULT_NS_FOR_NEW_RESOURCE);
conf.addNewResource("newPerson",DEFAULT_NS_FOR_NEW_RESOURCE);
conf.addNewResource("vcardPerson", DEFAULT_NS_FOR_NEW_RESOURCE);
conf.addNewResource("vcardName", DEFAULT_NS_FOR_NEW_RESOURCE);
//uris in scope: none
//literals in scope: none
conf.setUrisOnform( Arrays.asList( "existingPerson"));
conf.setLiteralsOnForm( Arrays.asList("personLabel", "personLabelDisplay", "roleLabel",
"roleLabeldisplay", "firstName", "lastName"));
conf.addSparqlForExistingLiteral("personLabel", personLabelQuery);
conf.addSparqlForExistingLiteral("roleLabel", roleLabelQuery);
conf.addSparqlForExistingUris("existingPerson", existingPersonQuery);
conf.addField( new FieldVTwo().
setName("existingPerson")
//options will be added in browser by auto complete JS
);
conf.addField( new FieldVTwo().
setName("personLabel").
setRangeDatatypeUri(XSD.xstring.toString() ).
setValidators( list("datatype:" + XSD.xstring.toString())));
conf.addField( new FieldVTwo().
setName("roleLabel").
setRangeDatatypeUri(XSD.xstring.toString() ).
setValidators( list("datatype:" + XSD.xstring.toString(),"nonempty")));
conf.addField( new FieldVTwo().
setName("personLabelDisplay").
setRangeDatatypeUri(XSD.xstring.toString() ));
conf.addField( new FieldVTwo().
setName("roleLabelDisplay").
setRangeDatatypeUri(XSD.xstring.toString() ));
conf.addField( new FieldVTwo().
setName("firstName").
setRangeDatatypeUri(XSD.xstring.toString() ).
setValidators( list("datatype:" + XSD.xstring.toString()) )
);
conf.addField( new FieldVTwo().
setName("lastName").
setRangeDatatypeUri(XSD.xstring.toString() ).
setValidators( list("datatype:" + XSD.xstring.toString()) )
);
//Add validator
conf.addValidator(new AntiXssValidation());
conf.addValidator(new FirstAndLastNameValidator("existingPerson"));
//Adding additional data, specifically edit mode
addFormSpecificData(conf, vreq);
prepare(vreq, conf);
return conf;
}
/* N3 assertions for working with educational training */
final static String n3ForNewProjectRole =
"@prefix core: <"+ vivoCore +"> .\n" +
"@prefix rdfs: <"+ rdfs +"> . \n"+
"?project <http://purl.obolibrary.org/obo/BFO_0000055> ?projectRole .\n" +
"?projectRole a <http://vivoweb.org/ontology/core#ResearcherRole> .\n" +
"?projectRole <http://purl.obolibrary.org/obo/BFO_0000054> ?project . \n" +
"?projectRole <"+ label +"> ?roleLabel . \n" ;
final static String n3ForNewPerson =
"?projectRole <http://purl.obolibrary.org/obo/RO_0000052> ?newPerson . \n" +
"?newPerson <http://purl.obolibrary.org/obo/RO_0000053> ?projectRole . \n" +
"?newPerson a <http://xmlns.com/foaf/0.1/Person> . \n" +
"?newPerson <"+ label +"> ?personLabel . ";
final static String n3ForExistingPerson =
"?projectRole <http://purl.obolibrary.org/obo/RO_0000052> ?existingPerson . \n" +
"?existingPerson <http://purl.obolibrary.org/obo/RO_0000053> ?projectRole . \n" +
" ";
final static String firstNameAssertion =
"@prefix vcard: <http://www.w3.org/2006/vcard/ns#> . \n" +
"?newPerson <http://purl.obolibrary.org/obo/ARG_2000028> ?vcardPerson . \n" +
"?vcardPerson <http://purl.obolibrary.org/obo/ARG_2000029> ?newPerson . \n" +
"?vcardPerson a <http://www.w3.org/2006/vcard/ns#Individual> . \n" +
"?vcardPerson vcard:hasName ?vcardName . \n" +
"?vcardName a <http://www.w3.org/2006/vcard/ns#Name> . \n" +
"?vcardName vcard:givenName ?firstName .";
final static String lastNameAssertion =
"@prefix vcard: <http://www.w3.org/2006/vcard/ns#> . \n" +
"?newPerson <http://purl.obolibrary.org/obo/ARG_2000028> ?vcardPerson . \n" +
"?vcardPerson <http://purl.obolibrary.org/obo/ARG_2000029> ?newPerson . \n" +
"?vcardPerson a <http://www.w3.org/2006/vcard/ns#Individual> . \n" +
"?vcardPerson vcard:hasName ?vcardName . \n" +
"?vcardName a <http://www.w3.org/2006/vcard/ns#Name> . \n" +
"?vcardName vcard:familyName ?lastName .";
/* Queries for editing an existing educational training entry */
final static String roleLabelQuery =
"SELECT ?roleLabel WHERE {\n"+
"?projectRole <"+ label +"> ?roleLabel }\n";
final static String existingPersonQuery =
"PREFIX rdfs: <"+ rdfs +"> \n"+
"SELECT ?existingPerson WHERE {\n"+
"?projectRole <http://purl.obolibrary.org/obo/RO_0000057> ?existingPerson . \n" +
"?existingPerson <http://purl.obolibrary.org/obo/RO_0000056> ?projectRole . \n" +
"?existingPerson a <http://xmlns.com/foaf/0.1/Person> . \n " +
" }";
final static String personLabelQuery =
"PREFIX rdfs: <"+ rdfs +"> \n"+
"SELECT ?existingPersonLabel WHERE {\n"+
"?projectRole <http://purl.obolibrary.org/obo/RO_0000057> ?existingPerson . \n" +
"?existingPerson <http://purl.obolibrary.org/obo/RO_0000056> ?projectRole .\n"+
"?existingPerson <"+ label +"> ?existingPersonLabel .\n"+
"?existingPerson a <http://xmlns.com/foaf/0.1/Person> . \n " +
" }";
//Adding form specific data such as edit mode
public void addFormSpecificData(EditConfigurationVTwo editConfiguration, VitroRequest vreq) {
HashMap<String, Object> formSpecificData = new HashMap<String, Object>();
formSpecificData.put("editMode", getEditMode(vreq).name().toLowerCase());
editConfiguration.setFormSpecificData(formSpecificData);
}
public EditMode getEditMode(VitroRequest vreq) {
List<String> predicates = new ArrayList<String>();
predicates.add("http://purl.obolibrary.org/obo/RO_0000053");
return EditModeUtils.getEditMode(vreq, predicates);
}
}

View file

@ -883,4 +883,5 @@ administering_organization_for = administering organization for
missing_credential = missing credential
grant_administered_by = grant being administered by
missing_grant = missing grant
editor_of_entry = editor of entry for
editor_of_entry = editor of entry for
researcher_role = Researcher's role in the project