From d1ecaccc5b0dde6eae347d7621c197b2705df436 Mon Sep 17 00:00:00 2001 From: j2blake Date: Thu, 3 Nov 2011 23:20:22 +0000 Subject: [PATCH] NIHVIVO-2343 First shot at the Manage Proxies page. --- .../controller/AbstractPageHandler.java | 4 +- .../ManageProxiesController.java | 43 +++++ .../manageproxies/ManageProxiesListPage.java | 166 ++++++++++++++++ .../ProxyRelationshipSelectionCriteria.java | 16 ++ .../freemarker/BaseSiteAdminController.java | 5 + webapp/web/WEB-INF/web.xml | 9 + webapp/web/js/account/accountProxyCommon.js | 68 ++++++- .../web/js/account/accountProxyItemsPanel.js | 180 ++++++++++++++++++ .../js/account/accountProxyProxiesPanel.js | 2 +- .../accounts/userAccounts-myProxiesPanel.ftl | 3 +- .../body/manageproxies/manageProxies-list.ftl | 109 +++++++++++ .../siteAdmin/siteAdmin-siteConfiguration.ftl | 4 + 12 files changed, 604 insertions(+), 5 deletions(-) create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/manageproxies/ManageProxiesController.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/manageproxies/ManageProxiesListPage.java create mode 100644 webapp/web/js/account/accountProxyItemsPanel.js create mode 100644 webapp/web/templates/freemarker/body/manageproxies/manageProxies-list.ftl diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/AbstractPageHandler.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/AbstractPageHandler.java index e5aecfbcd..1f444e963 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/AbstractPageHandler.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/AbstractPageHandler.java @@ -38,6 +38,7 @@ public abstract class AbstractPageHandler { protected final VitroRequest vreq; protected final ServletContext ctx; protected final OntModel userAccountsModel; + protected final OntModel unionModel; protected final UserAccountsDao userAccountsDao; protected final VClassDao vclassDao; protected final IndividualDao indDao; @@ -48,8 +49,9 @@ public abstract class AbstractPageHandler { this.vreq = vreq; this.ctx = vreq.getSession().getServletContext(); - OntModelSelector oms = ModelContext.getBaseOntModelSelector(ctx); + OntModelSelector oms = ModelContext.getUnionOntModelSelector(ctx); userAccountsModel = oms.getUserAccountsModel(); + unionModel = oms.getFullModel(); WebappDaoFactory wdf = (WebappDaoFactory) this.ctx .getAttribute("webappDaoFactory"); diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/manageproxies/ManageProxiesController.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/manageproxies/ManageProxiesController.java new file mode 100644 index 000000000..806c85804 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/manageproxies/ManageProxiesController.java @@ -0,0 +1,43 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.controller.accounts.manageproxies; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.Actions; +import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages.ManageProxies; +import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; +import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerHttpServlet; +import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues; + +/** + * Parcel out the different actions required of the ManageProxies GUI. + */ +public class ManageProxiesController extends FreemarkerHttpServlet { + private static final Log log = LogFactory + .getLog(ManageProxiesController.class); + + @Override + protected Actions requiredActions(VitroRequest vreq) { + return new Actions(new ManageProxies()); + } + + @Override + protected ResponseValues processRequest(VitroRequest vreq) { + if (log.isDebugEnabled()) { + dumpRequestParameters(vreq); + } + + String action = vreq.getPathInfo(); + log.debug("action = '" + action + "'"); + + return handleListRequest(vreq); + } + + private ResponseValues handleListRequest(VitroRequest vreq) { + ManageProxiesListPage page = new ManageProxiesListPage(vreq); + return page.showPage(); + } + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/manageproxies/ManageProxiesListPage.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/manageproxies/ManageProxiesListPage.java new file mode 100644 index 000000000..d327cdded --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/manageproxies/ManageProxiesListPage.java @@ -0,0 +1,166 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.controller.accounts.manageproxies; + +import static edu.cornell.mannlib.vitro.webapp.controller.accounts.manageproxies.ProxyRelationshipSelectionCriteria.DEFAULT_RELATIONSHIPS_PER_PAGE; + +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.config.ConfigurationProperties; +import edu.cornell.mannlib.vitro.webapp.controller.AbstractPageHandler; +import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; +import edu.cornell.mannlib.vitro.webapp.controller.accounts.manageproxies.ProxyRelationshipSelectionCriteria.ProxyRelationshipView; +import edu.cornell.mannlib.vitro.webapp.controller.accounts.manageproxies.ProxyRelationshipSelector.Context; +import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder; +import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues; +import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues; + +/** + * TODO + */ +public class ManageProxiesListPage extends AbstractPageHandler { + private static final Log log = LogFactory + .getLog(ManageProxiesListPage.class); + + public static final String PARAMETER_RELATIONSHIPS_PER_PAGE = "relationshipsPerPage"; + public static final String PARAMETER_PAGE_INDEX = "pageIndex"; + public static final String PARAMETER_VIEW_TYPE = "viewType"; + public static final String PARAMETER_SEARCH_TERM = "searchTerm"; + + private static final String TEMPLATE_NAME = "manageProxies-list.ftl"; + + private static final String DEFAULT_IMAGE_URL = UrlBuilder + .getUrl("/images/placeholders/person.thumbnail.jpg"); + + private final Context selectorContext; + + private ProxyRelationshipSelectionCriteria criteria = ProxyRelationshipSelectionCriteria.DEFAULT_CRITERIA; + + public ManageProxiesListPage(VitroRequest vreq) { + super(vreq); + + selectorContext = new Context(userAccountsModel, unionModel, + getMatchingProperty()); + parseParameters(); + } + + private String getMatchingProperty() { + return ConfigurationProperties.getBean(vreq).getProperty( + "selfEditing.idMatchingProperty", ""); + } + + /** + * Build the criteria from the request parameters. + */ + private void parseParameters() { + int relationshipsPerPage = getIntegerParameter( + PARAMETER_RELATIONSHIPS_PER_PAGE, + DEFAULT_RELATIONSHIPS_PER_PAGE); + int pageIndex = getIntegerParameter(PARAMETER_PAGE_INDEX, 1); + ProxyRelationshipView viewType = ProxyRelationshipView.fromKeyword(vreq + .getParameter(PARAMETER_VIEW_TYPE)); + String searchTerm = getStringParameter(PARAMETER_SEARCH_TERM, ""); + + criteria = new ProxyRelationshipSelectionCriteria(relationshipsPerPage, + pageIndex, viewType, searchTerm); + + log.debug("selection criteria is: " + criteria); + } + + public ResponseValues showPage() { + ProxyRelationshipSelection selection = ProxyRelationshipSelector + .select(selectorContext, criteria); + Map body = buildTemplateBodyMap(selection); + return new TemplateResponseValues(TEMPLATE_NAME, body); + } + + private Map buildTemplateBodyMap( + ProxyRelationshipSelection selection) { + Map body = new HashMap(); + + body.put("relationshipsPerPage", criteria.getRelationshipsPerPage()); + body.put("pageIndex", criteria.getPageIndex()); + body.put("viewType", criteria.getViewBy()); + body.put("searchTerm", criteria.getSearchTerm()); + + body.put("relationships", wrapProxyRelationships(selection)); + body.put("total", selection.getTotalResultCount()); + body.put("page", buildPageMap(selection)); + + body.put("matchingProperty", getMatchingProperty()); + + body.put("formUrls", buildUrlsMap()); + + return body; + } + + private List wrapProxyRelationships( + ProxyRelationshipSelection selection) { + List wrapped = new ArrayList(); + for (ProxyRelationship r : selection.getProxyRelationships()) { + wrapped.add(new ProxyRelationship(wrapItemList(r.getProxyInfos()), + wrapItemList(r.getProfileInfos()))); + } + return wrapped; + } + + private List wrapItemList(List items) { + List wrapped = new ArrayList(); + for (ProxyItemInfo item : items) { + wrapped.add(wrapItem(item)); + } + return wrapped; + } + + private ProxyItemInfo wrapItem(ProxyItemInfo item) { + if (item.getImageUrl().isEmpty()) { + return new ProxyItemInfo(item.getUri(), item.getLabel(), + item.getClassLabel(), DEFAULT_IMAGE_URL); + } else { + return new ProxyItemInfo(item.getUri(), item.getLabel(), + item.getClassLabel(), UrlBuilder.getUrl(item.getImageUrl())); + } + } + + private Map buildPageMap( + ProxyRelationshipSelection selection) { + int currentPage = selection.getCriteria().getPageIndex(); + + float pageCount = ((float) selection.getTotalResultCount()) + / selection.getCriteria().getRelationshipsPerPage(); + int lastPage = (int) Math.ceil(pageCount); + + Map map = new HashMap(); + + map.put("current", currentPage); + map.put("first", 1); + map.put("last", lastPage); + + if (currentPage < lastPage) { + map.put("next", currentPage + 1); + } + if (currentPage > 1) { + map.put("previous", currentPage - 1); + } + + return map; + } + + protected Map buildUrlsMap() { + Map map = new HashMap(); + + map.put("list", UrlBuilder.getUrl("/manageProxies/list")); + map.put("edit", UrlBuilder.getUrl("/manageProxies/edit")); + map.put("sparqlQueryAjax", UrlBuilder.getUrl("/ajax/sparqlQuery")); + map.put("defaultImageUrl", DEFAULT_IMAGE_URL); + + return map; + } + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/manageproxies/ProxyRelationshipSelectionCriteria.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/manageproxies/ProxyRelationshipSelectionCriteria.java index 4f7389944..c3e4d8074 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/manageproxies/ProxyRelationshipSelectionCriteria.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/manageproxies/ProxyRelationshipSelectionCriteria.java @@ -2,6 +2,7 @@ package edu.cornell.mannlib.vitro.webapp.controller.accounts.manageproxies; + /** * On what basis are we selecting proxy relationships? * @@ -23,6 +24,21 @@ public class ProxyRelationshipSelectionCriteria { BY_PROXY, BY_PROFILE; public static ProxyRelationshipView DEFAULT_VIEW = BY_PROXY; + + public static ProxyRelationshipView fromKeyword(String keyword) { + if (keyword == null) { + return DEFAULT_VIEW; + } + + for (ProxyRelationshipView v : ProxyRelationshipView.values()) { + if (v.toString().equals(keyword)) { + return v; + } + } + + return DEFAULT_VIEW; + } + } /** How many relationships should we bring back, at most? */ diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/BaseSiteAdminController.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/BaseSiteAdminController.java index 7e687eafc..e6a7ce5ef 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/BaseSiteAdminController.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/BaseSiteAdminController.java @@ -21,6 +21,7 @@ import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages.EditIndivi import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages.EditOntology; import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages.EditSiteInformation; import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages.ManageMenus; +import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages.ManageOwnProxies; import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages.ManageUserAccounts; import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages.SeeSiteAdminPage; import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages.SeeStartupStatus; @@ -131,6 +132,10 @@ public class BaseSiteAdminController extends FreemarkerHttpServlet { data.put("userAccounts", UrlBuilder.getUrl("/accountsAdmin")); } + if (PolicyHelper.isAuthorizedForActions(vreq, new ManageOwnProxies())) { + data.put("manageProxies", UrlBuilder.getUrl("/manageProxies")); + } + if (PolicyHelper.isAuthorizedForActions(vreq, new EditSiteInformation())) { data.put("siteInfo", UrlBuilder.getUrl("/editForm", "controller", "ApplicationBean")); } diff --git a/webapp/web/WEB-INF/web.xml b/webapp/web/WEB-INF/web.xml index a5fc9d3af..1484a5cb4 100644 --- a/webapp/web/WEB-INF/web.xml +++ b/webapp/web/WEB-INF/web.xml @@ -657,6 +657,15 @@ /accounts/* + + ManageProxies + edu.cornell.mannlib.vitro.webapp.controller.accounts.manageproxies.ManageProxiesController + + + ManageProxies + /manageProxies/* + + ShowAuth edu.cornell.mannlib.vitro.webapp.controller.admin.ShowAuthController diff --git a/webapp/web/js/account/accountProxyCommon.js b/webapp/web/js/account/accountProxyCommon.js index 45bc2d37d..601acd44a 100644 --- a/webapp/web/js/account/accountProxyCommon.js +++ b/webapp/web/js/account/accountProxyCommon.js @@ -4,6 +4,72 @@ * A collection of building blocks for the proxy-management UI. */ +/* + * ---------------------------------------------------------------------------- + * itemElement + * ---------------------------------------------------------------------------- + * Display information about an entity according to the template. The entity + * can be either: + * a profile -- Individual to be edited. + * a proxy -- User Account to do the editing, optionally with info from a + * profile associated with that individual. + * + * You provide: + * template -- the HTML text that determines how the element should look. + * The template must be a single HTML element, which may contain + * any number of sub-elements. It needs to have a single outer + * wrapper, however. + * uri, label, classLabel, imageUrl -- as described below + * remove -- a function that we can call when the user clicks on the remove + * link or button. We will pass a reference to this struct. + * ---------------------------------------------------------------------------- + * The template must inlude a link or button with attribute templatePart="remove" + * + * The template may include tokens to be replaced, from the following: + * %uri% -- the URI of the individual being displayed + * %label& -- the label of the individual. + * %classLabel% -- the label of the most specific class of the individual. + * %imageUrl% -- the URL that will fetch the image of the individual, + * or a placeholder image. + * ---------------------------------------------------------------------------- + * This relies on magic names for the styles: + * existingProxyItem -- for an item that was present when the page was loaded + * newProxyItem -- for an item that was added since the page was loaded + * removedProxyItem -- added to an item when the "remove" link is cheked. + * ---------------------------------------------------------------------------- + */ +function itemElement(template, uri, label, classLabel, imageUrl, removeInfo) { + var self = this; + + this.uri = uri; + this.label = label; + this.classLabel = classLabel; + this.imageUrl = (imageUrl) ? imageUrl : imageUrl="../images/placeholders/person.thumbnail.jpg"; + this.removeInfo = removeInfo; + + this.toString = function() { + return "proxyInfoElement: " + content; + } + + this.element = function() { + var content = template.replace(/%uri%/g, this.uri) + .replace(/%label%/g, this.label) + .replace(/%classLabel%/g, this.classLabel) + .replace(/%imageUrl%/g, this.imageUrl); + + var element = $(content); + element.addClass("proxyInfoElement"); + + var removeLink = $("[templatePart='remove']", element).first(); + removeLink.click(function(event) { + self.removeInfo(self); + return false; + }); + + return element; + } +} + /* * ---------------------------------------------------------------------------- * proxyInfoElement @@ -53,8 +119,6 @@ function proxyInfoElement(template, uri, label, classLabel, imageUrl, removeInfo .replace(/%classLabel%/g, this.classLabel) .replace(/%imageUrl%/g, this.imageUrl); - - var element = $("
" + content + "
"); var removeLink = $("[templatePart='remove']", element).first(); diff --git a/webapp/web/js/account/accountProxyItemsPanel.js b/webapp/web/js/account/accountProxyItemsPanel.js new file mode 100644 index 000000000..abefb1d20 --- /dev/null +++ b/webapp/web/js/account/accountProxyItemsPanel.js @@ -0,0 +1,180 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +/* + * ---------------------------------------------------------------------------- + * proxyItemsPanel + * ---------------------------------------------------------------------------- + * Display an AJAX-enabled list of proxy-related items (either proxies or + * profiles). + * + * The list may start out with a population of items. items may be added by + * selecting them in the auto-complete box. Items may be removed by clicking + * the "remove" link next to that item. + * + * A hidden field will hold the URI for each item, so when the form is submitted, + * the controller can determine the list of items. + * ---------------------------------------------------------------------------- + * You provide: + * p -- the DOM element that contains the template and the data. + * It also contains the autocomplete field. + * ---------------------------------------------------------------------------- + */ +function proxyItemsPanel(panel, contextInfo) { + var self = this; + + this.itemData = []; + + var excludedUris = contextInfo.excludedUris; + var dataContainerElement = $("[name='proxyData']", panel).first(); + var autoCompleteField = $("input[name='proxySelectorAC']", panel).first(); + var searchStatusField = $("span[name='proxySelectorSearchStatus']", panel).first(); + + var parseTemplate = function(dataContainer) { + var templateDiv = $("div[name='template']", dataContainer) + var templateHtml = templateDiv.html(); + templateDiv.remove(); + return templateHtml; + }; + var templateHtml = parseTemplate(dataContainerElement); + + var displayItemData = function() { + $(".proxyInfoElement", dataContainerElement).remove(); + + for (i = 0; i < self.itemData.length; i++) { + self.itemData[i].element().appendTo(dataContainerElement); + } + } + + var getItemData = function() { + return self.itemData; + } + + /* callback function */ + var addItemData = function(selection) { + var imageUrl = contextInfo.defaultImageUrl; + if (selection.imageUrl) { + imageUrl = contextInfo.baseUrl + selection.imageUrl; + } + + var info = new itemElement(templateHtml, selection.uri, selection.label, selection.classLabel, + imageUrl, removeItem); + self.itemData.unshift(info); + displayItemData(); + } + + var removeItem = function(info) { + var idx = self.itemData.indexOf(info); + if (idx != -1) { + self.itemData.splice(idx, 1); + } + displayItemData(); + } + + var parseOriginalData = function() { + var dataDivs = $("div[name='data']", dataContainerElement) + var data = []; + for (i = 0; i < dataDivs.length; i++) { + var dd = dataDivs[i]; + var uri = $("p[name='uri']", dd).text(); + var label = $("p[name='label']", dd).text(); + var classLabel = $("p[name='classLabel']", dd).text(); + var imageUrl = $("p[name='imageUrl']", dd).text(); + data.push(new itemElement(templateHtml, uri, label, classLabel, imageUrl, removeItem)); + } + return data; + } + this.itemData = parseOriginalData(); + + var setupAutoCompleteFields = function() { + var parms = { + query: contextInfo.query, + model: contextInfo.model, + url: contextInfo.sparqlQueryUrl + }; + var updateStatus = new statusFieldUpdater(searchStatusField, 3).setText; + var autocompleteInfo = new proxyAutocomplete(parms, excludedUris, getItemData, addItemData, updateStatus) + autoCompleteField.autocomplete(autocompleteInfo); + } + setupAutoCompleteFields(); + + displayItemData(); +} + +function statusFieldUpdater(element, minLength) { + var emptyText = element.text(); + var moreCharsText = element.attr('moreCharsText'); + var noMatchText = element.attr('noMatchText'); + + this.setText = function(searchTermLength, numberOfResults) { + if (numberOfResults > 0) { + element.text(''); + } else if (searchTermLength == 0) { + element.text(emptyText); + } else if (searchTermLength < minLength) { + element.text(moreCharsText); + } else { + element.text(noMatchText); + } + } +} + +var profileQuery = "" + + "PREFIX fn: \n" + + "PREFIX rdfs: \n" + + "PREFIX foaf: \n" + + "PREFIX vitro: \n" + + "PREFIX vpublic: \n" + + "PREFIX auth: \n" + + "\n" + + "SELECT DISTINCT ?uri ?label ?classLabel ?imageUrl \n" + + "WHERE { \n" + + " ?uri a foaf:Person ; \n" + + " rdfs:label ?label ; \n" + + " OPTIONAL { \n" + + " ?uri vitro:mostSpecificType ?type. \n" + + " ?type rdfs:label ?classLabel \n" + + " } \n" + + " OPTIONAL { \n" + + " ?uri vpublic:mainImage ?imageUri. \n" + + " ?imageUri vpublic:thumbnailImage ?thumbUri. \n" + + " ?thumbUri vpublic:downloadLocation ?thumbstreamUri. \n" + + " ?thumbstreamUri vpublic:directDownloadUrl ?imageUrl. \n" + + " } \n" + + " FILTER (REGEX(str(?label), '^%term%', 'i')) \n" + + "} \n" + + "ORDER BY ASC(?label) \n" + + "LIMIT 25 \n"; + + +$(document).ready(function() { + var disableFormInUnsupportedBrowsers = function() { + var disableWrapper = $('#ie67DisableWrapper'); + + // Check for unsupported browsers only if the element exists on the page + if (disableWrapper.length) { + if (vitro.browserUtils.isIELessThan8()) { + disableWrapper.show(); + $('.noIE67').hide(); + return true; + } + } + return false; + }; + + if (disableFormInUnsupportedBrowsers()) { + return; + } + + $("div[name='proxyProfilesPanel']").each(function(i) { + var context = { + excludedUris: [], + baseUrl: proxyContextInfo.baseUrl, + sparqlQueryUrl: proxyContextInfo.sparqlQueryUrl, + defaultImageUrl: proxyContextInfo.defaultImageUrl, + query: profileQuery, + model: '' + } + var ppp = new proxyItemsPanel(this, context); + this["ppp"]=ppp; + }); +}); diff --git a/webapp/web/js/account/accountProxyProxiesPanel.js b/webapp/web/js/account/accountProxyProxiesPanel.js index aea4b7e65..bd7177955 100644 --- a/webapp/web/js/account/accountProxyProxiesPanel.js +++ b/webapp/web/js/account/accountProxyProxiesPanel.js @@ -168,7 +168,7 @@ function searchStatusField(element, minLength) { this.setText = function(searchTermLength, numberOfResults) { if (numberOfResults > 0) { - element.text = ''; + element.text(''); } else if (searchTermLength == 0) { element.text(emptyText); } else if (searchTermLength < minLength) { diff --git a/webapp/web/templates/freemarker/body/accounts/userAccounts-myProxiesPanel.ftl b/webapp/web/templates/freemarker/body/accounts/userAccounts-myProxiesPanel.ftl index a0e87f56d..4e8262f08 100644 --- a/webapp/web/templates/freemarker/body/accounts/userAccounts-myProxiesPanel.ftl +++ b/webapp/web/templates/freemarker/body/accounts/userAccounts-myProxiesPanel.ftl @@ -60,4 +60,5 @@ var proxyMechanism = { ${scripts.add('', '', '', - '')} + '', + '')} \ No newline at end of file diff --git a/webapp/web/templates/freemarker/body/manageproxies/manageProxies-list.ftl b/webapp/web/templates/freemarker/body/manageproxies/manageProxies-list.ftl new file mode 100644 index 000000000..4041efa8f --- /dev/null +++ b/webapp/web/templates/freemarker/body/manageproxies/manageProxies-list.ftl @@ -0,0 +1,109 @@ +<#-- $This file is distributed under the terms of the license in /doc/license.txt$ --> + +<#-- Template for displaying list of user accounts --> + + +${stylesheets.add('')} +${stylesheets.add('')} +${stylesheets.add('')} +${stylesheets.add('')} + +

+ <#if page.previous??> + Previous + + ${page.current} of ${page.last} + <#if page.next??> + Next + +

+ +<#list relationships as r> +
+ + + + + + +
+ <#assign p = r.proxyInfos[0]> + + + +
+ ${p.label} + + ${p.label}} | + ${p.classLabel} +
+ +
+ + +
+
+

Add profile

+

+

+   +

+ +

Selected profiles:

+ + <#-- Magic div thst holds all of the proxy data and the template that shows how to display it. --> +
+ <#list r.profileInfos as p> +
+

${p.uri}

+

${p.label}

+

${p.classLabel}

+

${p.imageUrl}

+
+ + + <#-- + Each proxy will be shown using the HTML inside this element. + It must contain at least: + -- a link with templatePart="remove" + -- a hidden input field with templatePart="uriField" + --> +
+ + + + + +
+ %label% + + %label% | %classLabel% +
+ Remove selection +
+ +
+
+
+ +
+
+ + + + +${scripts.add('', + '')} +${scripts.add('', + '', + '', + '')} diff --git a/webapp/web/templates/freemarker/body/siteAdmin/siteAdmin-siteConfiguration.ftl b/webapp/web/templates/freemarker/body/siteAdmin/siteAdmin-siteConfiguration.ftl index 23de61321..cb178fe0e 100644 --- a/webapp/web/templates/freemarker/body/siteAdmin/siteAdmin-siteConfiguration.ftl +++ b/webapp/web/templates/freemarker/body/siteAdmin/siteAdmin-siteConfiguration.ftl @@ -23,6 +23,10 @@
  • User accounts
  • + <#if siteConfig.manageProxies?has_content> +
  • Manage Proxies
  • + + <#if siteConfig.startupStatus?has_content>
  • Startup Status