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 @Override
protected void processRequest(VitroRequest vreq, HttpServletResponse response) { 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 errorMsg = null;
String rankPredicate = vreq.getParameter(RANK_PREDICATE_PARAMETER_NAME); String rankPredicate = vreq.getParameter(RANK_PREDICATE_PARAMETER_NAME);
if (rankPredicate == null) { if (rankPredicate == null) {
@ -45,7 +40,7 @@ public class ReorderController extends PrimitiveRdfEdit {
doError(response, errorMsg, HttpServletResponse.SC_BAD_REQUEST ); doError(response, errorMsg, HttpServletResponse.SC_BAD_REQUEST );
return; return;
} }
String[] individualUris = vreq.getParameterValues(INDIVIDUAL_PREDICATE_PARAMETER_NAME); String[] individualUris = vreq.getParameterValues(INDIVIDUAL_PREDICATE_PARAMETER_NAME);
if (individualUris == null || individualUris.length == 0) { if (individualUris == null || individualUris.length == 0) {
errorMsg = "No individuals specified"; 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("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("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("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; return map;
} }
@ -897,18 +898,6 @@ public class FreemarkerHttpServlet extends VitroHttpServlet {
"This is not a template response."); "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 @Override
public Map<String, Object> getMap() { public Map<String, Object> getMap() {
throw new UnsupportedOperationException( throw new UnsupportedOperationException(

View file

@ -241,63 +241,17 @@ public class IndividualController extends FreemarkerHttpServlet {
// if (customView!=null) { // 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 // // 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! map.put("individual", new IndividualTemplateModel(individual));
// 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());
// }
//setup highlighter for search terms //setup highlighter for search terms
checkForSearch(vreq, individual); //checkForSearch(vreq, individual);
if( individual.getURI().startsWith( vreq.getWebappDaoFactory().getDefaultNamespace() )){ if( individual.getURI().startsWith( vreq.getWebappDaoFactory().getDefaultNamespace() )){
map.put("entityLinkedDataURL", individual.getURI() + "/" + individual.getLocalName() + ".rdf"); 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; return map;
} }

View file

@ -29,15 +29,14 @@ public class UrlBuilder {
BROWSE("/browse"), BROWSE("/browse"),
CONTACT("/contact"), CONTACT("/contact"),
INDIVIDUAL("/individual"), INDIVIDUAL("/individual"),
INDIVIDUAL_LIST("/individuallist"), INDIVIDUAL_LIST("/individuallist"),
SEARCH("/search"),
TERMS_OF_USE("/termsOfUse"),
// RY put these under /admin/
LOGIN("/siteAdmin"), LOGIN("/siteAdmin"),
LOGOUT("/login_process.jsp"), LOGOUT("/login_process.jsp"),
SITE_ADMIN("/siteAdmin"); SEARCH("/search"),
SITE_ADMIN("/siteAdmin"),
TERMS_OF_USE("/termsOfUse"),
VISUALIZATION("/visualization");
private final String path; private final String path;
Route(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 long serialVersionUID = 1L;
private static final Log log = LogFactory.getLog(AutocompleteController.class); 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 static String QUERY_PARAMETER_NAME = "term";
private IndexSearcher searcher = null; private IndexSearcher searcher = null;
@ -92,8 +94,6 @@ public class AutocompleteController extends FreemarkerHttpServlet implements Sea
public void doGet(HttpServletRequest request, HttpServletResponse response) public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException { 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>(); Map<String, Object> map = new HashMap<String, Object>();
VitroRequest vreq = new VitroRequest(request); VitroRequest vreq = new VitroRequest(request);
@ -106,7 +106,7 @@ public class AutocompleteController extends FreemarkerHttpServlet implements Sea
if( vreq.getWebappDaoFactory() == null if( vreq.getWebappDaoFactory() == null
|| vreq.getWebappDaoFactory().getIndividualDao() == null ){ || vreq.getWebappDaoFactory().getIndividualDao() == null ){
log.error("makeUsableBeans() could not get IndividualDao "); log.error("makeUsableBeans() could not get IndividualDao ");
doSearchError(templateName, map, config, response); doSearchError(map, config, response);
return; return;
} }
IndividualDao iDao = vreq.getWebappDaoFactory().getIndividualDao(); IndividualDao iDao = vreq.getWebappDaoFactory().getIndividualDao();
@ -122,7 +122,7 @@ public class AutocompleteController extends FreemarkerHttpServlet implements Sea
log.debug("query for '" + qtxt +"' is " + query.toString()); log.debug("query for '" + qtxt +"' is " + query.toString());
if (query == null ) { if (query == null ) {
doNoQuery(templateName, map, config, response); doNoQuery(map, config, response);
return; return;
} }
@ -139,20 +139,20 @@ public class AutocompleteController extends FreemarkerHttpServlet implements Sea
topDocs = searcherForRequest.search(query,null,maxHitSize); topDocs = searcherForRequest.search(query,null,maxHitSize);
}catch (Exception ex){ }catch (Exception ex){
log.error(ex); log.error(ex);
doFailedSearch(templateName, map, config, response); doFailedSearch(map, config, response);
return; return;
} }
} }
if( topDocs == null || topDocs.scoreDocs == null){ if( topDocs == null || topDocs.scoreDocs == null){
log.error("topDocs for a search was null"); log.error("topDocs for a search was null");
doFailedSearch(templateName, map, config, response); doFailedSearch(map, config, response);
return; return;
} }
int hitsLength = topDocs.scoreDocs.length; int hitsLength = topDocs.scoreDocs.length;
if ( hitsLength < 1 ){ if ( hitsLength < 1 ){
doFailedSearch(templateName, map, config, response); doFailedSearch(map, config, response);
return; return;
} }
log.debug("found "+hitsLength+" hits"); log.debug("found "+hitsLength+" hits");
@ -176,11 +176,11 @@ public class AutocompleteController extends FreemarkerHttpServlet implements Sea
Collections.sort(results); Collections.sort(results);
map.put("results", results); map.put("results", results);
writeTemplate(templateName, map, config, response); writeTemplate(TEMPLATE_DEFAULT, map, config, response);
} catch (Throwable e) { } catch (Throwable e) {
log.error("AutocompleteController(): " + e); log.error("AutocompleteController(): " + e);
doSearchError(templateName, map, config, response); doSearchError(map, config, response);
return; 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) { private void doNoQuery(Map<String, Object> map, Configuration config, HttpServletResponse response) {
writeTemplate(templateName, map, config, response); writeTemplate(TEMPLATE_DEFAULT, map, config, response);
} }
private void doFailedSearch(String templateName, Map<String, Object> map, Configuration config, HttpServletResponse response) { private void doFailedSearch(Map<String, Object> map, Configuration config, HttpServletResponse response) {
writeTemplate(templateName, map, config, 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 // For now, we are not sending an error message back to the client because with the default autocomplete configuration it
// chokes. // chokes.
writeTemplate(templateName, map, config, response); writeTemplate(TEMPLATE_DEFAULT, map, config, response);
} }
public static final int MAX_QUERY_LENGTH = 500; 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.beans.Link;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.ParamMap; 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.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;
import edu.cornell.mannlib.vitro.webapp.web.ViewFinder.ClassView; import edu.cornell.mannlib.vitro.webapp.web.ViewFinder.ClassView;
@ -58,6 +59,29 @@ public class IndividualTemplateModel extends BaseTemplateModel {
return profileUrl; 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() { public String getSearchView() {
return getView(ClassView.SEARCH); return getView(ClassView.SEARCH);
@ -126,11 +150,4 @@ public class IndividualTemplateModel extends BaseTemplateModel {
return individual.getKeywords(); 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 --> <#-- Template for individual profile page -->
<#import "lib-property.ftl" as p>
<#assign editingClass>
<#if editStatus.showEditLinks>editing<#else></#if>
</#assign>
<div id="personWrap"> <div id="personWrap">
<#if editStatus.showAdminPanel> <#if editStatus.showAdminPanel>
<#include "individual-adminPanel.ftl"> <#include "individual-adminPanel.ftl">
</#if> </#if>
<div class="contents entity <#if editStatus.showEditLinks>editing</#if>"> <div class="contents entity ${editingClass}">
<div id="labelAndMoniker"> <div id="labelAndMoniker">
<#if relatedSubject??> <#if relatedSubject??>
@ -15,34 +21,44 @@
<p><a href="${relatedSubject.url}">&larr; return to ${relatedSubject.name}</a></p> <p><a href="${relatedSubject.url}">&larr; return to ${relatedSubject.name}</a></p>
<#else> <#else>
<#-- Label --> <#-- Label -->
<div class="datatypePropertyValue" id="label"> <@p.dataPropWrapper id="label">
<div class="statementWrap"> <h2>${individual.name}</h2>
<h2>${individual.name}</h2> </@p.dataPropWrapper>
<#if editStatus.showEditLinks>
</#if>
</div>
</div>
<#-- Moniker --> <#-- Moniker -->
<#if individual.moniker?has_content> <#if individual.moniker?has_content>
<div class="datatypeProperties"> <@p.dataPropsWrapper id="moniker">
<div class="datatypePropertyValue" id="moniker"> <em class="moniker">${individual.moniker}</em>
<div class="statementWrap"> </@p.dataPropsWrapper>
<em class="moniker">${individual.moniker}</em>
</div>
</div>
</div>
</#if> </#if>
</#if> </#if>
</div> <!-- labelAndMoniker --> </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> <!-- #contents -->
</div> <!-- #personWrap --> </div> <!-- #personWrap -->
${stylesheets.addFromTheme("/entity.css")} ${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??) --> <#-- 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>apples</li>
<li>bananas</li> <li>bananas</li>
<li>oranges</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 RY Consider rewriting in Java. Probably designers won't want to modify this. That would allow us to support
nested <li> elements. nested <li> elements.
@ -51,13 +51,13 @@
<li>apples</li>, <li>apples</li>,
<li>bananas</li>, <li>bananas</li>,
<li>oranges</li> <li>oranges</li>
<@firstLastListNested> </@firstLastListNested>
<@firstLastListNested delim="??"> <@firstLastListNested delim="??">
<li>apples, oranges</li>?? <li>apples, oranges</li>??
<li>bananas, lemons</li>?? <li>bananas, lemons</li>??
<li>grapefruit, limes</li> <li>grapefruit, limes</li>
<@firstLastListNested> </@firstLastListNested>
<@firstLastListNested delim="??"> <@firstLastListNested delim="??">
<li>Books <li>Books
@ -72,7 +72,7 @@
<li>Time</li> <li>Time</li>
</ul> </ul>
</li> </li>
<@firstLastListNested> </@firstLastListNested>
RY Consider rewriting in Java. Probably designers won't want to modify this. 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>