NIHVIVO-650 Display image on new (Freemarker) individual profile page. Add <@url /> directive to generate img src value.
This commit is contained in:
parent
7004af4f73
commit
72d43f05a5
11 changed files with 216 additions and 118 deletions
|
@ -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";
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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}">← 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??) -->
|
|
@ -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.
|
||||
-->
|
||||
|
|
43
webapp/web/templates/freemarker/lib/lib-property.ftl
Normal file
43
webapp/web/templates/freemarker/lib/lib-property.ftl
Normal 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>
|
Loading…
Add table
Reference in a new issue