Commit 431681b6 authored by Ubbo Veentjer's avatar Ubbo Veentjer
Browse files

add a controller advice component for common model additions

improves #56
parent e1ca5003
Pipeline #139134 passed with stages
in 9 minutes and 45 seconds
package info.textgrid.rep;
import java.util.Locale;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ModelAttribute;
import info.textgrid.rep.i18n.I18N;
import info.textgrid.rep.i18n.I18NProvider;
import info.textgrid.rep.service.TgrepConfigurationService;
/**
* Add ModelAttributes to all Controllers which are needed for
* all Models like i18n (the translation map) or the config
*
* @author Ubbo Veentjer
*/
@ControllerAdvice
public class CommonModelControllerAdvice {
private TgrepConfigurationService tgrepConfig;
private I18NProvider i18nProvider;
@Autowired
public CommonModelControllerAdvice(I18NProvider i18nProvider, TgrepConfigurationService tgrepConfig) {
this.i18nProvider = i18nProvider;
this.tgrepConfig = tgrepConfig;
}
@ModelAttribute
public void handleRequest(Model model, Locale locale) {
I18N i18n = i18nProvider.getI18N(locale);
// translation array
model.addAttribute("i18n", i18n.getTranslationMap());
model.addAttribute("language", i18n.getLanguage());
// config
model.addAttribute("config", this.tgrepConfig);
}
}
...@@ -2,37 +2,24 @@ package info.textgrid.rep; ...@@ -2,37 +2,24 @@ package info.textgrid.rep;
import java.util.Locale; import java.util.Locale;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.error.ErrorController; import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.ui.Model; import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import info.textgrid.rep.i18n.I18N;
import info.textgrid.rep.i18n.I18NProvider;
@Controller @Controller
public class TGRepErrorController implements ErrorController { public class TGRepErrorController implements ErrorController {
@Autowired
private I18NProvider i18nProvider;
@RequestMapping("/error") @RequestMapping("/error")
public String handleError(Model model, Locale locale, HttpServletRequest request) { public String handleError(Model model, Locale locale, HttpServletRequest request) {
I18N i18n = i18nProvider.getI18N(locale);
if(request.getAttribute("javax.servlet.error.exception") != null) { if(request.getAttribute("javax.servlet.error.exception") != null) {
Exception exception = (Exception) request.getAttribute("javax.servlet.error.exception"); Exception exception = (Exception) request.getAttribute("javax.servlet.error.exception");
model.addAttribute("exception", exception.getMessage()); model.addAttribute("exception", exception.getMessage());
model.addAttribute("stacktrace", exception.getStackTrace()); model.addAttribute("stacktrace", exception.getStackTrace());
} }
model.addAttribute("statusCode", request.getAttribute("javax.servlet.error.status_code")); model.addAttribute("statusCode", request.getAttribute("javax.servlet.error.status_code"));
// translation array
model.addAttribute("i18n", i18n.getTranslationMap());
model.addAttribute("language", i18n.getLanguage());
return "error"; return "error";
} }
......
package info.textgrid.rep.advancedsearch; package info.textgrid.rep.advancedsearch;
import java.util.Locale;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.ui.Model; import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import info.textgrid.rep.i18n.I18N;
import info.textgrid.rep.i18n.I18NProvider;
@Controller @Controller
public class AdvancedSearchController { public class AdvancedSearchController {
private static final Log log = LogFactory.getLog(AdvancedSearchController.class); private static final Log log = LogFactory.getLog(AdvancedSearchController.class);
private I18NProvider i18nProvider;
@Autowired
public AdvancedSearchController(I18NProvider i18nProvider) {
this.i18nProvider = i18nProvider;
}
@GetMapping("/advanced-search") @GetMapping("/advanced-search")
public String render( public String render(Model model) {
Locale locale,
Model model) {
I18N i18n = i18nProvider.getI18N(locale);
model.addAttribute("i18n", i18n.getTranslationMap());
model.addAttribute("language", i18n.getLanguage());
return "advancedsearch"; return "advancedsearch";
} }
......
...@@ -15,7 +15,6 @@ import org.springframework.web.bind.annotation.SessionAttributes; ...@@ -15,7 +15,6 @@ import org.springframework.web.bind.annotation.SessionAttributes;
import info.textgrid.namespaces.middleware.tgsearch.ResultType; import info.textgrid.namespaces.middleware.tgsearch.ResultType;
import info.textgrid.rep.i18n.I18N; import info.textgrid.rep.i18n.I18N;
import info.textgrid.rep.i18n.I18NProvider; import info.textgrid.rep.i18n.I18NProvider;
import info.textgrid.rep.service.TgrepConfigurationService;
import info.textgrid.rep.service.TgsearchClientService; import info.textgrid.rep.service.TgsearchClientService;
import info.textgrid.rep.shared.ViewMode; import info.textgrid.rep.shared.ViewMode;
...@@ -26,9 +25,6 @@ public class BasketController { ...@@ -26,9 +25,6 @@ public class BasketController {
@Autowired @Autowired
private TgsearchClientService tgsearchClientService; private TgsearchClientService tgsearchClientService;
@Autowired
private TgrepConfigurationService tgrepConfig;
@Autowired @Autowired
private I18NProvider i18nProvider; private I18NProvider i18nProvider;
...@@ -65,14 +61,7 @@ public class BasketController { ...@@ -65,14 +61,7 @@ public class BasketController {
model.addAttribute("viewmodes", viewmodes); model.addAttribute("viewmodes", viewmodes);
model.addAttribute("results", results); model.addAttribute("results", results);
model.addAttribute("aggregatorUrl", tgrepConfig.getTextgridHost()+"/1.0/aggregator");
model.addAttribute("voyantUrl", tgrepConfig.getToolVoyantHost());
model.addAttribute("basketItemString", basket.getItemsAsString()); model.addAttribute("basketItemString", basket.getItemsAsString());
model.addAttribute("textgridHost", this.tgrepConfig.getTextgridHost());
// translation array
model.addAttribute("i18n", i18n.getTranslationMap());
model.addAttribute("language", i18n.getLanguage());
return "basket"; return "basket";
......
...@@ -6,7 +6,6 @@ import java.io.UnsupportedEncodingException; ...@@ -6,7 +6,6 @@ import java.io.UnsupportedEncodingException;
import java.math.BigInteger; import java.math.BigInteger;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
...@@ -68,11 +67,7 @@ public class BrowseController { ...@@ -68,11 +67,7 @@ public class BrowseController {
I18N i18n = i18nProvider.getI18N(locale); I18N i18n = i18nProvider.getI18N(locale);
// common variables for browse-root aggregations and browse single items // common variables for browse-root aggregations and browse single items
model.addAttribute("handleHost", this.tgrepConfig.getHandleHost());
model.addAttribute("textgridHost", this.tgrepConfig.getTextgridHost());
model.addAttribute("mode", mode); model.addAttribute("mode", mode);
model.addAttribute("i18n", i18n.getTranslationMap());
model.addAttribute("language", i18n.getLanguage());
// if no id, browse all root aggregations // if no id, browse all root aggregations
if (id == null || id.equals("root")) { if (id == null || id.equals("root")) {
...@@ -202,7 +197,7 @@ public class BrowseController { ...@@ -202,7 +197,7 @@ public class BrowseController {
} }
// Voyant // Voyant
tools.add(new ViewMode("Voyant", tgrepConfig.getToolVoyantHost() + "/?input=" + tgrepConfig.getTextgridHost() + "/1.0/tgcrud-public/rest/" + id + "/data", false)); tools.add(new ViewMode("Voyant", tgrepConfig.getVoyantHost() + "/?input=" + tgrepConfig.getTextgridHost() + "/1.0/tgcrud-public/rest/" + id + "/data", false));
// Annotate // Annotate
tools.add(new ViewMode("Annotate", tgrepConfig.getToolAnnotateHost() + "/data.html?uri=" + id, false, "annotation-button")); tools.add(new ViewMode("Annotate", tgrepConfig.getToolAnnotateHost() + "/data.html?uri=" + id, false, "annotation-button"));
......
...@@ -12,8 +12,6 @@ import org.springframework.web.bind.annotation.GetMapping; ...@@ -12,8 +12,6 @@ import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import info.textgrid.namespaces.middleware.tgsearch.FacetType; import info.textgrid.namespaces.middleware.tgsearch.FacetType;
import info.textgrid.rep.i18n.I18N;
import info.textgrid.rep.i18n.I18NProvider;
import info.textgrid.rep.service.TgsearchClientService; import info.textgrid.rep.service.TgsearchClientService;
@Controller @Controller
...@@ -22,9 +20,6 @@ public class BrowseFacetController { ...@@ -22,9 +20,6 @@ public class BrowseFacetController {
@Autowired @Autowired
private TgsearchClientService tgsearchClientService; private TgsearchClientService tgsearchClientService;
@Autowired
private I18NProvider i18nProvider;
private static final Log log = LogFactory.getLog(BrowseFacetController.class); private static final Log log = LogFactory.getLog(BrowseFacetController.class);
@GetMapping("/facet/{facet}") @GetMapping("/facet/{facet}")
...@@ -35,9 +30,7 @@ public class BrowseFacetController { ...@@ -35,9 +30,7 @@ public class BrowseFacetController {
@RequestParam(value="limit", required=false, defaultValue="0") int limit, @RequestParam(value="limit", required=false, defaultValue="0") int limit,
@RequestParam(value="order", required=false, defaultValue="count.desc") String order) { @RequestParam(value="order", required=false, defaultValue="count.desc") String order) {
I18N i18n = i18nProvider.getI18N(locale);
// boolean sandbox = Utils.userWantsSandbox(PortalUtil.getUserId(renderRequest)); // boolean sandbox = Utils.userWantsSandbox(PortalUtil.getUserId(renderRequest));
boolean sandbox = false; boolean sandbox = false;
// list facets configured for this portlet // list facets configured for this portlet
...@@ -46,8 +39,6 @@ public class BrowseFacetController { ...@@ -46,8 +39,6 @@ public class BrowseFacetController {
List<FacetType> facets = tgsearchClientService.listFacet(facetList, limit, order, sandbox) List<FacetType> facets = tgsearchClientService.listFacet(facetList, limit, order, sandbox)
.getFacetGroup().get(0).getFacet(); .getFacetGroup().get(0).getFacet();
model.addAttribute("i18n", i18n.getTranslationMap());
model.addAttribute("language", i18n.getLanguage());
model.addAttribute("facets", facets); model.addAttribute("facets", facets);
model.addAttribute("facet", facet); model.addAttribute("facet", facet);
return "browsefacet"; return "browsefacet";
......
package info.textgrid.rep.markdown; package info.textgrid.rep.markdown;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Locale; import java.util.Locale;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.commonmark.node.Node;
import org.commonmark.parser.Parser;
import org.commonmark.renderer.html.HtmlRenderer;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader; import org.springframework.core.io.ResourceLoader;
...@@ -61,8 +57,6 @@ public class DocController { ...@@ -61,8 +57,6 @@ public class DocController {
} }
model.addAttribute("content", content); model.addAttribute("content", content);
model.addAttribute("i18n", i18n.getTranslationMap());
model.addAttribute("language", i18n.getLanguage());
return "markdown"; return "markdown";
......
...@@ -17,7 +17,6 @@ import org.springframework.web.util.HtmlUtils; ...@@ -17,7 +17,6 @@ import org.springframework.web.util.HtmlUtils;
import info.textgrid.namespaces.middleware.tgsearch.Response; import info.textgrid.namespaces.middleware.tgsearch.Response;
import info.textgrid.rep.i18n.I18N; import info.textgrid.rep.i18n.I18N;
import info.textgrid.rep.i18n.I18NProvider; import info.textgrid.rep.i18n.I18NProvider;
import info.textgrid.rep.service.TgrepConfigurationService;
import info.textgrid.rep.service.TgsearchClientService; import info.textgrid.rep.service.TgsearchClientService;
import info.textgrid.rep.shared.Pager; import info.textgrid.rep.shared.Pager;
import info.textgrid.rep.shared.Utils; import info.textgrid.rep.shared.Utils;
...@@ -29,9 +28,6 @@ public class SearchController { ...@@ -29,9 +28,6 @@ public class SearchController {
@Autowired @Autowired
private TgsearchClientService tgsearchClientService; private TgsearchClientService tgsearchClientService;
@Autowired
private TgrepConfigurationService tgrepConfig;
@Autowired @Autowired
private I18NProvider i18nProvider; private I18NProvider i18nProvider;
...@@ -96,15 +92,8 @@ public class SearchController { ...@@ -96,15 +92,8 @@ public class SearchController {
model.addAttribute("limit", limit); model.addAttribute("limit", limit);
model.addAttribute("filter", filter); model.addAttribute("filter", filter);
model.addAttribute("filterQueryString", Utils.getFilterQueryString(filter)); model.addAttribute("filterQueryString", Utils.getFilterQueryString(filter));
model.addAttribute("aggregatorUrl", this.tgrepConfig.getTextgridHost() + "/1.0/aggregator");
model.addAttribute("aggregatorSandboxParam", aggregatorSandboxParam); model.addAttribute("aggregatorSandboxParam", aggregatorSandboxParam);
model.addAttribute("realQueryString", realQueryString); model.addAttribute("realQueryString", realQueryString);
model.addAttribute("textgridHost", this.tgrepConfig.getTextgridHost());
model.addAttribute("handleHost", this.tgrepConfig.getHandleHost());
// translation array
model.addAttribute("i18n", i18n.getTranslationMap());
model.addAttribute("language", i18n.getLanguage());
// which .jsp to render // which .jsp to render
return "search"; return "search";
......
...@@ -16,7 +16,7 @@ public class TgrepConfigurationService { ...@@ -16,7 +16,7 @@ public class TgrepConfigurationService {
@Value("${handle.host}") @Value("${handle.host}")
private String handleHost; private String handleHost;
@Value("${tool.voyant.host}") @Value("${tool.voyant.host}")
private String toolVoyantHost; private String voyantHost;
@Value("${tool.annotate.host}") @Value("${tool.annotate.host}")
private String toolAnnotateHost; private String toolAnnotateHost;
@Value("${tool.mirador.host}") @Value("${tool.mirador.host}")
...@@ -40,11 +40,11 @@ public class TgrepConfigurationService { ...@@ -40,11 +40,11 @@ public class TgrepConfigurationService {
this.handleHost = handleHost; this.handleHost = handleHost;
} }
public String getToolVoyantHost() { public String getVoyantHost() {
return toolVoyantHost; return voyantHost;
} }
public void setToolVoyantHost(String toolVoyantHost) { public void setToolVoyantHost(String voyantHost) {
this.toolVoyantHost = toolVoyantHost; this.voyantHost = voyantHost;
} }
public String getToolAnnotateHost() { public String getToolAnnotateHost() {
...@@ -75,11 +75,16 @@ public class TgrepConfigurationService { ...@@ -75,11 +75,16 @@ public class TgrepConfigurationService {
this.toolSwitchboardHost = toolSwitchboardHost; this.toolSwitchboardHost = toolSwitchboardHost;
} }
// composed
public String getAggregatorUrl() {
return getTextgridHost()+"/1.0/aggregator";
}
@PostConstruct @PostConstruct
public void postConstruct() { public void postConstruct() {
log.info("textgrid host: " + textgridHost); log.info("textgrid host: " + textgridHost);
log.info("handle host: " + handleHost); log.info("handle host: " + handleHost);
log.info("voyant host: " + toolVoyantHost); log.info("voyant host: " + voyantHost);
log.info("annotate host: " + toolAnnotateHost); log.info("annotate host: " + toolAnnotateHost);
log.info("mirador host: " + toolMiradorHost); log.info("mirador host: " + toolMiradorHost);
log.info("digilib host: " + toolDigilibHost); log.info("digilib host: " + toolDigilibHost);
......
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
<h3 class="tgrep sidebar_subheading">${i18n['tools']}</h3> <h3 class="tgrep sidebar_subheading">${i18n['tools']}</h3>
<ul class="tgrep sidebar_list"> <ul class="tgrep sidebar_list">
<li class="tgrep sidebar_item"> <li class="tgrep sidebar_item">
<a class="aggregator-items" href="${voyantUrl}?input=${aggregatorUrl}/zip/${basketItemString}?meta=false&only=text/xml" rel="noindex nofollow" class="tgrep sidebar_link">Voyant</a> <a class="aggregator-items" href="${config.voyantHost}?input=${config.aggregatorUrl}/zip/${basketItemString}?meta=false&only=text/xml" rel="noindex nofollow" class="tgrep sidebar_link">Voyant</a>
</li> </li>
</ul> </ul>
</section> </section>
...@@ -62,9 +62,9 @@ ...@@ -62,9 +62,9 @@
<div class="tg dropdown" role="group"> <div class="tg dropdown" role="group">
<a class="tg dropdown_toggle">${i18n['download-all']}</a> <a class="tg dropdown_toggle">${i18n['download-all']}</a>
<ul class="tg dropdown_menu"> <ul class="tg dropdown_menu">
<li class="tg dropdown_item"><a class="aggregator-items tg dropdown_link" href="${aggregatorUrl}/epub/${basketItemString}" data-type="ebook">E-Book</a></li> <li class="tg dropdown_item"><a class="aggregator-items tg dropdown_link" href="${config.aggregatorUrl}/epub/${basketItemString}" data-type="ebook">E-Book</a></li>
<li class="tg dropdown_item"><a class="aggregator-items tg dropdown_link" href="${aggregatorUrl}/zip/${basketItemString}" data-type="zip">ZIP</a></li> <li class="tg dropdown_item"><a class="aggregator-items tg dropdown_link" href="${config.aggregatorUrl}/zip/${basketItemString}" data-type="zip">ZIP</a></li>
<li class="tg dropdown_item"><a class="aggregator-items tg dropdown_link" href="${aggregatorUrl}/teicorpus/${basketItemString}" data-type="teicorpus">TEI-Corpus</a></li> <li class="tg dropdown_item"><a class="aggregator-items tg dropdown_link" href="${config.aggregatorUrl}/teicorpus/${basketItemString}" data-type="teicorpus">TEI-Corpus</a></li>
</ul> </ul>
</div> </div>
</div> </div>
......
...@@ -78,7 +78,7 @@ ...@@ -78,7 +78,7 @@
</c:if> </c:if>
<c:if test="${not empty metadata.object.generic.generated.pid[0].value}"> <c:if test="${not empty metadata.object.generic.generated.pid[0].value}">
<dt>${i18n['pid']}</dt> <dt>${i18n['pid']}</dt>
<dd><a href="${handleHost}/${fn:substringAfter(metadata.object.generic.generated.pid[0].value, 'hdl:')}">${metadata.object.generic.generated.pid[0].value}</a><br/> <dd><a href="${config.handleHost}/${fn:substringAfter(metadata.object.generic.generated.pid[0].value, 'hdl:')}">${metadata.object.generic.generated.pid[0].value}</a><br/>
<a href="#citation">${i18n['citation']}</a></dd> <a href="#citation">${i18n['citation']}</a></dd>
</c:if> </c:if>
</dl> </dl>
...@@ -101,44 +101,44 @@ ...@@ -101,44 +101,44 @@
<h3 class="tgrep sidebar_subheading">${i18n['download']}</h3> <h3 class="tgrep sidebar_subheading">${i18n['download']}</h3>
<ul class="tgrep sidebar_list"> <ul class="tgrep sidebar_list">
<li> <li>
<a href="${textgridHost}/1.0/tgcrud-public/rest/${metadata.object.generic.generated.textgridUri.value}/data"> <a href="${config.textgridHost}/1.0/tgcrud-public/rest/${metadata.object.generic.generated.textgridUri.value}/data">
${i18n['object']} <c:if test="${isTEI}">(TEI)</c:if> ${i18n['object']} <c:if test="${isTEI}">(TEI)</c:if>
</a> </a>
</li> </li>
<li> <li>
<a href="${textgridHost}/1.0/tgcrud-public/rest/${metadata.object.generic.generated.textgridUri.value}/metadata"> <a href="${config.textgridHost}/1.0/tgcrud-public/rest/${metadata.object.generic.generated.textgridUri.value}/metadata">
${i18n['metadata']} (XML) ${i18n['metadata']} (XML)
</a> </a>
</li> </li>
<li> <li>
<a href="${textgridHost}/1.0/tgcrud-public/rest/${metadata.object.generic.generated.textgridUri.value}/tech"> <a href="${config.textgridHost}/1.0/tgcrud-public/rest/${metadata.object.generic.generated.textgridUri.value}/tech">
${i18n['techmd']} (XML) ${i18n['techmd']} (XML)
</a> </a>
</li> </li>
<c:if test="${isTEI}"> <c:if test="${isTEI}">
<li> <li>
<a href="${textgridHost}/1.0/aggregator/text/${metadata.object.generic.generated.textgridUri.value}"> <a href="${config.textgridHost}/1.0/aggregator/text/${metadata.object.generic.generated.textgridUri.value}">
Plain Text (txt) Plain Text (txt)
</a> </a>
</li> </li>
<li> <li>
<a href="${textgridHost}/1.0/aggregator/epub/${metadata.object.generic.generated.textgridUri.value}"> <a href="${config.textgridHost}/1.0/aggregator/epub/${metadata.object.generic.generated.textgridUri.value}">
E-Book (epub) E-Book (epub)
</a> </a>
</li> </li>
<li> <li>
<a href="${textgridHost}/1.0/aggregator/html/${metadata.object.generic.generated.textgridUri.value}"> <a href="${config.textgridHost}/1.0/aggregator/html/${metadata.object.generic.generated.textgridUri.value}">
HTML HTML
</a> </a>
</li> </li>
<li> <li>
<a href="${textgridHost}/1.0/aggregator/zip/${metadata.object.generic.generated.textgridUri.value}"> <a href="${config.textgridHost}/1.0/aggregator/zip/${metadata.object.generic.generated.textgridUri.value}">
ZIP ZIP
</a> </a>
</li> </li>
</c:if> </c:if>
<c:if test="${fn:contains(metadata.object.generic.provided.format, 'aggregation')}"> <c:if test="${fn:contains(metadata.object.generic.provided.format, 'aggregation')}">
<a href="${textgridHost}/1.0/aggregator/teicorpus/${metadata.object.generic.generated.textgridUri.value}"> <a href="${config.textgridHost}/1.0/aggregator/teicorpus/${metadata.object.generic.generated.textgridUri.value}">
TEI-Corpus (XML) TEI-Corpus (XML)
</a> </a>
</c:if> </c:if>
...@@ -247,11 +247,11 @@ ...@@ -247,11 +247,11 @@
defaultZoomLevel: 1, defaultZoomLevel: 1,
//sequenceMode: true, //sequenceMode: true,
prefixUrl: "/images/openseadragon/", prefixUrl: "/images/openseadragon/",
tileSources: "${textgridHost}/1.0/digilib/rest/IIIF/${metadata.object.generic.generated.textgridUri.value}/info.json" tileSources: "${config.textgridHost}/1.0/digilib/rest/IIIF/${metadata.object.generic.generated.textgridUri.value}/info.json"