NIHVIVO-650 Display image on new (Freemarker) individual profile page. Add <@url /> directive to generate img src value.

This commit is contained in:
rjy7 2010-09-21 16:05:36 +00:00
parent 7004af4f73
commit 72d43f05a5
11 changed files with 216 additions and 118 deletions

View file

@ -32,11 +32,6 @@ public class ReorderController extends PrimitiveRdfEdit {
@Override
protected void processRequest(VitroRequest vreq, HttpServletResponse response) {
//String templateName = "autocompleteResults.ftl";
//Map<String, Object> map = new HashMap<String, Object>();
//Configuration config = getConfig(vreq);
//PortalFlag portalFlag = vreq.getPortalFlag();
String errorMsg = null;
String rankPredicate = vreq.getParameter(RANK_PREDICATE_PARAMETER_NAME);
if (rankPredicate == null) {
@ -45,7 +40,7 @@ public class ReorderController extends PrimitiveRdfEdit {
doError(response, errorMsg, HttpServletResponse.SC_BAD_REQUEST );
return;
}
String[] individualUris = vreq.getParameterValues(INDIVIDUAL_PREDICATE_PARAMETER_NAME);
if (individualUris == null || individualUris.length == 0) {
errorMsg = "No individuals specified";

View file

@ -431,6 +431,7 @@ public class FreemarkerHttpServlet extends VitroHttpServlet {
map.put("dump", new edu.cornell.mannlib.vitro.webapp.web.directives.dump.DumpDirective());
map.put("dumpAll", new edu.cornell.mannlib.vitro.webapp.web.directives.dump.DumpAllDirective());
map.put("help", new edu.cornell.mannlib.vitro.webapp.web.directives.dump.HelpDirective());
map.put("url", new edu.cornell.mannlib.vitro.webapp.web.directives.UrlDirective());
return map;
}
@ -897,18 +898,6 @@ public class FreemarkerHttpServlet extends VitroHttpServlet {
"This is not a template response.");
}
@Override
public int getStatusCode() {
throw new UnsupportedOperationException(
"This is not a BaseResponseValues response.");
}
@Override
public void setStatusCode(int statusCode) {
throw new UnsupportedOperationException(
"This is not a BaseResponseValues response.");
}
@Override
public Map<String, Object> getMap() {
throw new UnsupportedOperationException(

View file

@ -241,63 +241,17 @@ public class IndividualController extends FreemarkerHttpServlet {
// if (customView!=null) {
// // insert test for whether a css files of the same name exists, and populate the customCss string for use when construction the header
// }
//String netid = iwDao.getNetId(indiv.getURI());
//data.put("netid", netid);
//data.put("vclassName", vclassName);
// RY We should not have references to a specific ontology in the vitro code!
// Figure out how to move this out of here.
boolean isPerson = individual.isVClass("http://xmlns.com/foaf/0.1/Person");
map.put("isPerson", isPerson);
if (isPerson) {
map.put("visualizationUrl", UrlBuilder.getUrl("/visualization",
"uri", individual.getURI()));
}
// RY Would like to use IndividualTemplateModel object, but may just end up copying all methods. Since object is put in template
// with a read-only wrapper, it should be restrictive enough.
map.put("individual",individual); //data.put("individual", new IndividualTemplateModel(indiv));
//Portal portal = vreq.getPortal();
//data.put("portal",String.valueOf(portal));
// String view= getViewFromRequest(vreq);
// if( view == null){
// if (customView == null) {
// view = default_jsp;
// data.put("bodyJsp","/"+Controllers.ENTITY_JSP);
// log.debug("no custom view and no view parameter in request for rendering "+indiv.getName());
// } else {
// view = default_jsp;
// log.debug("setting custom view templates/entity/"+ customView + " for rendering "+indiv.getName());
// data.put("bodyJsp", "/templates/entity/"+customView);
// }
// data.put("entityPropsListJsp",Controllers.ENTITY_PROP_LIST_JSP);
// data.put("entityDatapropsListJsp",Controllers.ENTITY_DATAPROP_LIST_JSP);
// data.put("entityMergedPropsListJsp",Controllers.ENTITY_MERGED_PROP_LIST_GROUPED_JSP);
// data.put("entityKeywordsListJsp",Controllers.ENTITY_KEYWORDS_LIST_JSP);
// } else {
// log.debug("Found view parameter "+view+" in request for rendering "+indiv.getName());
// }
map.put("individual", new IndividualTemplateModel(individual));
//setup highlighter for search terms
checkForSearch(vreq, individual);
//checkForSearch(vreq, individual);
if( individual.getURI().startsWith( vreq.getWebappDaoFactory().getDefaultNamespace() )){
map.put("entityLinkedDataURL", individual.getURI() + "/" + individual.getLocalName() + ".rdf");
}
// generate link to RDF representation for semantic web clients like Piggy Bank
// BJL 2008-07-16: I'm temporarily commenting this out because I forgot we need to make sure it filters out the hidden properties
// generate url for this entity
// String individualToRDF = "http://"+vreq.getServerName()+":"+vreq.getServerPort()+vreq.getContextPath()+"/entity?home=1&uri="+forURL(entity.getURI())+"&view=rdf.rdf";
//css += "<link rel='alternate' type='application/rdf+xml' title='"+entity.getName()+"' href='"+individualToRDF+"' />";
//RequestDispatcher rd = vreq.getRequestDispatcher( view );
//rd.forward(vreq,res);
return map;
}

View file

@ -29,15 +29,14 @@ public class UrlBuilder {
BROWSE("/browse"),
CONTACT("/contact"),
INDIVIDUAL("/individual"),
INDIVIDUAL_LIST("/individuallist"),
SEARCH("/search"),
TERMS_OF_USE("/termsOfUse"),
// RY put these under /admin/
INDIVIDUAL_LIST("/individuallist"),
LOGIN("/siteAdmin"),
LOGOUT("/login_process.jsp"),
SITE_ADMIN("/siteAdmin");
SEARCH("/search"),
SITE_ADMIN("/siteAdmin"),
TERMS_OF_USE("/termsOfUse"),
VISUALIZATION("/visualization");
private final String path;
Route(String path) {

View file

@ -63,7 +63,9 @@ public class AutocompleteController extends FreemarkerHttpServlet implements Sea
private static final long serialVersionUID = 1L;
private static final Log log = LogFactory.getLog(AutocompleteController.class);
private static final String TEMPLATE_DEFAULT = "autocompleteResults.ftl";
private static String QUERY_PARAMETER_NAME = "term";
private IndexSearcher searcher = null;
@ -92,8 +94,6 @@ public class AutocompleteController extends FreemarkerHttpServlet implements Sea
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
// String templateName = request.getServletPath().equals("/autocomplete") ? "autocompleteResults.ftl" : "selectResults.ftl";
String templateName = "autocompleteResults.ftl";
Map<String, Object> map = new HashMap<String, Object>();
VitroRequest vreq = new VitroRequest(request);
@ -106,7 +106,7 @@ public class AutocompleteController extends FreemarkerHttpServlet implements Sea
if( vreq.getWebappDaoFactory() == null
|| vreq.getWebappDaoFactory().getIndividualDao() == null ){
log.error("makeUsableBeans() could not get IndividualDao ");
doSearchError(templateName, map, config, response);
doSearchError(map, config, response);
return;
}
IndividualDao iDao = vreq.getWebappDaoFactory().getIndividualDao();
@ -122,7 +122,7 @@ public class AutocompleteController extends FreemarkerHttpServlet implements Sea
log.debug("query for '" + qtxt +"' is " + query.toString());
if (query == null ) {
doNoQuery(templateName, map, config, response);
doNoQuery(map, config, response);
return;
}
@ -139,20 +139,20 @@ public class AutocompleteController extends FreemarkerHttpServlet implements Sea
topDocs = searcherForRequest.search(query,null,maxHitSize);
}catch (Exception ex){
log.error(ex);
doFailedSearch(templateName, map, config, response);
doFailedSearch(map, config, response);
return;
}
}
if( topDocs == null || topDocs.scoreDocs == null){
log.error("topDocs for a search was null");
doFailedSearch(templateName, map, config, response);
doFailedSearch(map, config, response);
return;
}
int hitsLength = topDocs.scoreDocs.length;
if ( hitsLength < 1 ){
doFailedSearch(templateName, map, config, response);
doFailedSearch(map, config, response);
return;
}
log.debug("found "+hitsLength+" hits");
@ -176,11 +176,11 @@ public class AutocompleteController extends FreemarkerHttpServlet implements Sea
Collections.sort(results);
map.put("results", results);
writeTemplate(templateName, map, config, response);
writeTemplate(TEMPLATE_DEFAULT, map, config, response);
} catch (Throwable e) {
log.error("AutocompleteController(): " + e);
doSearchError(templateName, map, config, response);
doSearchError(map, config, response);
return;
}
}
@ -441,18 +441,18 @@ public class AutocompleteController extends FreemarkerHttpServlet implements Sea
}
private void doNoQuery(String templateName, Map<String, Object> map, Configuration config, HttpServletResponse response) {
writeTemplate(templateName, map, config, response);
private void doNoQuery(Map<String, Object> map, Configuration config, HttpServletResponse response) {
writeTemplate(TEMPLATE_DEFAULT, map, config, response);
}
private void doFailedSearch(String templateName, Map<String, Object> map, Configuration config, HttpServletResponse response) {
writeTemplate(templateName, map, config, response);
private void doFailedSearch(Map<String, Object> map, Configuration config, HttpServletResponse response) {
writeTemplate(TEMPLATE_DEFAULT, map, config, response);
}
private void doSearchError(String templateName, Map<String, Object> map, Configuration config, HttpServletResponse response) {
private void doSearchError(Map<String, Object> map, Configuration config, HttpServletResponse response) {
// For now, we are not sending an error message back to the client because with the default autocomplete configuration it
// chokes.
writeTemplate(templateName, map, config, response);
writeTemplate(TEMPLATE_DEFAULT, map, config, response);
}
public static final int MAX_QUERY_LENGTH = 500;

View file

@ -0,0 +1,85 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.web.directives;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder;
import freemarker.core.Environment;
import freemarker.template.Configuration;
import freemarker.template.TemplateDirectiveBody;
import freemarker.template.TemplateException;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelException;
/**
* Template directive to be used to get image src values.
* Parameters are not needed, therefore not supported.
* @author rjy7
*
*/
public class UrlDirective extends BaseTemplateDirectiveModel {
private static final Log log = LogFactory.getLog(UrlDirective.class);
@Override
public void execute(Environment env, Map params, TemplateModel[] loopVars,
TemplateDirectiveBody body) throws TemplateException, IOException {
if (loopVars.length != 0) {
throw new TemplateModelException(
"The url directive doesn't allow loop variables.");
}
if (body != null) {
throw new TemplateModelException(
"The url directive doesn't allow nested content.");
}
String path = params.get("path").toString();
if (path == null) {
throw new TemplateModelException(
"The url directive requires a value for parameter 'path'.");
}
if (!path.startsWith("/")) {
throw new TemplateModelException(
"The url directive requires that the value of parameter 'path' is an absolute path starting with '/'.");
}
String url = UrlBuilder.getUrl(path);
Writer out = env.getOut();
out.write(url);
}
public String help(Configuration config) {
Map<String, Object> map = new HashMap<String, Object>();
String name = getDirectiveName();
map.put("name", name);
map.put("effect", "Generate a full url from a path. Use for generating src attribute of image tags.");
map.put("comments", "The path should be an absolute path, starting with '/'.");
Map<String, String> params = new HashMap<String, String>();
params.put("path", "path");
map.put("params", params);
List<String> examples = new ArrayList<String>();
examples.add("<@" + name + " path=\"/images/dummyImages/person.thumbnail.jpg\" />");
map.put("examples", examples);
return mergeToHelpTemplate(map, config);
}
}

View file

@ -14,6 +14,7 @@ import edu.cornell.mannlib.vitro.webapp.beans.Individual;
import edu.cornell.mannlib.vitro.webapp.beans.Link;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.ParamMap;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.Route;
import edu.cornell.mannlib.vitro.webapp.utils.StringUtils;
import edu.cornell.mannlib.vitro.webapp.web.ViewFinder;
import edu.cornell.mannlib.vitro.webapp.web.ViewFinder.ClassView;
@ -58,6 +59,29 @@ public class IndividualTemplateModel extends BaseTemplateModel {
return profileUrl;
}
public String getVisualizationUrl() {
return isPerson() ? getUrl(Route.VISUALIZATION.path(), "uri", getUri()) : null;
}
// RY We should not have references to a specific ontology in the vitro code!
// Figure out how to move this out of here.
// We could subclass IndividualTemplateModel in the VIVO code and add the isPerson()
// and getVisualizationUrl() methods there, but we still need to know whether to
// instantiate the IndividualTemplateModel or the VivoIndividualTemplateModel class.
public boolean isPerson() {
return individual.isVClass("http://xmlns.com/foaf/0.1/Person");
}
public String getImageUrl() {
String imageUrl = individual.getImageUrl();
return imageUrl == null ? null : getUrl(imageUrl);
}
public String getThumbUrl() {
String thumbUrl = individual.getThumbUrl();
return thumbUrl == null ? null : getUrl(thumbUrl);
}
public String getSearchView() {
return getView(ClassView.SEARCH);
@ -126,11 +150,4 @@ public class IndividualTemplateModel extends BaseTemplateModel {
return individual.getKeywords();
}
public String getImageUrl() {
return individual.getImageUrl();
}
public String getThumbUrl() {
return individual.getThumbUrl();
}
}

View file

@ -2,12 +2,18 @@
<#-- Template for individual profile page -->
<#import "lib-property.ftl" as p>
<#assign editingClass>
<#if editStatus.showEditLinks>editing<#else></#if>
</#assign>
<div id="personWrap">
<#if editStatus.showAdminPanel>
<#include "individual-adminPanel.ftl">
</#if>
<div class="contents entity <#if editStatus.showEditLinks>editing</#if>">
<div class="contents entity ${editingClass}">
<div id="labelAndMoniker">
<#if relatedSubject??>
@ -15,34 +21,44 @@
<p><a href="${relatedSubject.url}">&larr; return to ${relatedSubject.name}</a></p>
<#else>
<#-- Label -->
<div class="datatypePropertyValue" id="label">
<div class="statementWrap">
<h2>${individual.name}</h2>
<#if editStatus.showEditLinks>
</#if>
</div>
</div>
<@p.dataPropWrapper id="label">
<h2>${individual.name}</h2>
</@p.dataPropWrapper>
<#-- Moniker -->
<#if individual.moniker?has_content>
<div class="datatypeProperties">
<div class="datatypePropertyValue" id="moniker">
<div class="statementWrap">
<em class="moniker">${individual.moniker}</em>
</div>
</div>
</div>
<@p.dataPropsWrapper id="moniker">
<em class="moniker">${individual.moniker}</em>
</@p.dataPropsWrapper>
</#if>
</#if>
</div> <!-- labelAndMoniker -->
<#include "individual-sparklineVisualization.ftl">
<#include "individual-sparklineVisualization.ftl">
<div id="dprop-vitro-image" class="propsItem ${editingClass}">
<#if individual.thumbUrl??>
<@p.dataPropsWrapper id="thumbnail">
<a class="image" href="${individual.imageUrl}">
<img src="${individual.thumbUrl}"
title="click to view larger image"
alt="${individual.name}" width="115" />
</a>
</@p.dataPropsWrapper>
<#elseif individual.person>
<@p.dataPropsWrapper id="thumbnail">
<img src="<@url path='/images/dummyImages/person.thumbnail.jpg' />" "
alt="placeholder image" width="115" />
</@p.dataPropsWrapper>
</#if>
</div>
</div> <!-- #contents -->
</div> <!-- #personWrap -->
${stylesheets.addFromTheme("/entity.css")}
<#-- RY Figure out which of these scripts really need to go into the head, and which are needed at all (e.g., tinyMCE??) -->

View file

@ -15,7 +15,7 @@
<li>apples</li>
<li>bananas</li>
<li>oranges</li>
<@firstLastList>
</@firstLastList>
RY Consider rewriting in Java. Probably designers won't want to modify this. That would allow us to support
nested <li> elements.
@ -51,13 +51,13 @@
<li>apples</li>,
<li>bananas</li>,
<li>oranges</li>
<@firstLastListNested>
</@firstLastListNested>
<@firstLastListNested delim="??">
<li>apples, oranges</li>??
<li>bananas, lemons</li>??
<li>grapefruit, limes</li>
<@firstLastListNested>
</@firstLastListNested>
<@firstLastListNested delim="??">
<li>Books
@ -72,7 +72,7 @@
<li>Time</li>
</ul>
</li>
<@firstLastListNested>
</@firstLastListNested>
RY Consider rewriting in Java. Probably designers won't want to modify this.
-->

View file

@ -0,0 +1,43 @@
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
<#-- Macros for display of individual properties -->
<#--
Macro: dataPropWrapper
Wrap a dataproperty in the appropriate divs
Usage:
<@dataPropWrapper id="myId" editStatus=true>
<#nested>
</@dataPropWrapper>
-->
<#macro dataPropWrapper id editStatus=false>
<div class="datatypePropertyValue" id="${id}">
<div class="statementWrap">
<#nested>
</div>
</div>
</#macro>
<#---------------------------------------------------------------------------->
<#--
Macro: dataPropsWrapper
Wrap a dataproperty in the appropriate divs
Usage:
<@dataPropsWrapper id="myId" editStatus=true>
<#nested>
</@dataPropsWrapper>
-->
<#macro dataPropsWrapper id editStatus=false>
<div class="datatypeProperties">
<@dataPropWrapper id=id editStatus=editStatus>
<#nested>
</@dataPropWrapper>
</div>
</#macro>