diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsPage.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsPage.java
index 4b42f2fa5..22b3c667c 100644
--- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsPage.java
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsPage.java
@@ -36,6 +36,9 @@ public abstract class UserAccountsPage extends AbstractPageHandler {
private static final String PERSON_CLASS_URI = "http://xmlns.com/foaf/0.1/Person";
+ private static final String DEFAULT_IMAGE_URL = UrlBuilder
+ .getUrl("/images/placeholders/person.thumbnail.jpg");
+
/**
* After the account is created, or the password is reset, the user has this
* many days to repond to the email.
@@ -102,6 +105,7 @@ public abstract class UserAccountsPage extends AbstractPageHandler {
UrlBuilder.getUrl("/accounts/firstTimeExternal"));
map.put("accountsAjax", UrlBuilder.getUrl("/accountsAjax"));
map.put("sparqlQueryAjax", UrlBuilder.getUrl("/ajax/sparqlQuery"));
+ map.put("defaultImageUrl", DEFAULT_IMAGE_URL);
return map;
}
diff --git a/webapp/web/js/account/accountProxyCommon.js b/webapp/web/js/account/accountProxyCommon.js
index 601acd44a..19be955be 100644
--- a/webapp/web/js/account/accountProxyCommon.js
+++ b/webapp/web/js/account/accountProxyCommon.js
@@ -48,7 +48,7 @@ function itemElement(template, uri, label, classLabel, imageUrl, removeInfo) {
this.removeInfo = removeInfo;
this.toString = function() {
- return "proxyInfoElement: " + content;
+ return "itemElement: " + content;
}
this.element = function() {
@@ -70,67 +70,6 @@ function itemElement(template, uri, label, classLabel, imageUrl, removeInfo) {
}
}
-/*
- * ----------------------------------------------------------------------------
- * proxyInfoElement
- * ----------------------------------------------------------------------------
- * 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.
- * 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 proxyInfoElement(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.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 + "
");
-
- var removeLink = $("[templatePart='remove']", element).first();
- removeLink.click(function(event) {
- removeInfo(self);
- return false;
- });
-
- return element;
- }
-}
-
/*
* ----------------------------------------------------------------------------
* proxyAutoComplete
@@ -141,11 +80,11 @@ function proxyInfoElement(template, uri, label, classLabel, imageUrl, removeInfo
* parms -- a map containing the URL of the AJAX controller, the query, and
* the model selector.
* excludedUris -- these URIs are always filtered out of the results.
- * getProxyInfos -- a function that will return an array of proxyInfoElements
+ * getProxyInfos -- a function that will return an array of itemElements
* that are already present in the list and so should be filtered out of
* the autocomplete response.
* addProxyInfo -- a function that we can call when an item is selected.
- * It will take the selection info, build a proxyInfoElement, and add
+ * It will take the selection info, build an itemElement, and add
* it to the panel.
* reportSearchStatus -- a function that we can call when a search is done. It
* will accept the length of the search term and the number of results,
diff --git a/webapp/web/js/account/accountProxyItemsPanel.js b/webapp/web/js/account/accountProxyItemsPanel.js
index abefb1d20..447bef705 100644
--- a/webapp/web/js/account/accountProxyItemsPanel.js
+++ b/webapp/web/js/account/accountProxyItemsPanel.js
@@ -35,9 +35,9 @@ function proxyItemsPanel(panel, contextInfo) {
templateDiv.remove();
return templateHtml;
};
- var templateHtml = parseTemplate(dataContainerElement);
+ this.templateHtml = parseTemplate(dataContainerElement);
- var displayItemData = function() {
+ this.displayItemData = function() {
$(".proxyInfoElement", dataContainerElement).remove();
for (i = 0; i < self.itemData.length; i++) {
@@ -49,27 +49,35 @@ function proxyItemsPanel(panel, contextInfo) {
return self.itemData;
}
- /* callback function */
- var addItemData = function(selection) {
+ this.removeItem = function(info) {
+ var idx = self.itemData.indexOf(info);
+ if (idx != -1) {
+ self.itemData.splice(idx, 1);
+ }
+ self.displayItemData();
+ }
+
+ this.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);
+ var classLabel = selection.classLabel ? selection.classLabel : "";
+
+ var info = new itemElement(self.templateHtml, selection.uri, selection.label, classLabel,
+ imageUrl, self.removeItem);
self.itemData.unshift(info);
- displayItemData();
+ self.displayItemData();
+ self.getAdditionalData(self, info, selection.externalAuthId)
}
- var removeItem = function(info) {
- var idx = self.itemData.indexOf(info);
- if (idx != -1) {
- self.itemData.splice(idx, 1);
- }
- displayItemData();
+ this.getAdditionalData = function(parent, info, externalAuthId) {
+ // For the plain vanilla panel, this need not do anything. For the
+ // proxy panel, this will be replaced by a function that does another
+ // AJAX call to get the classLabel and imageUrl.
}
-
+
var parseOriginalData = function() {
var dataDivs = $("div[name='data']", dataContainerElement)
var data = [];
@@ -79,7 +87,7 @@ function proxyItemsPanel(panel, contextInfo) {
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));
+ data.push(new itemElement(self.templateHtml, uri, label, classLabel, imageUrl, self.removeItem));
}
return data;
}
@@ -92,12 +100,12 @@ function proxyItemsPanel(panel, contextInfo) {
url: contextInfo.sparqlQueryUrl
};
var updateStatus = new statusFieldUpdater(searchStatusField, 3).setText;
- var autocompleteInfo = new proxyAutocomplete(parms, excludedUris, getItemData, addItemData, updateStatus)
+ var autocompleteInfo = new proxyAutocomplete(parms, excludedUris, getItemData, self.addItemData, updateStatus)
autoCompleteField.autocomplete(autocompleteInfo);
}
setupAutoCompleteFields();
- displayItemData();
+ self.displayItemData();
}
function statusFieldUpdater(element, minLength) {
@@ -145,7 +153,77 @@ var profileQuery = ""
+ "ORDER BY ASC(?label) \n"
+ "LIMIT 25 \n";
+var proxyQuery = ""
+ + "PREFIX fn: \n"
+ + "PREFIX auth: \n"
+ + "\n"
+ + "SELECT DISTINCT ?uri ?label ?externalAuthId \n"
+ + "WHERE { \n"
+ + " ?uri a auth:UserAccount ; \n"
+ + " auth:firstName ?firstName ; \n"
+ + " auth:lastName ?lastName . \n"
+ + " LET ( ?label := fn:concat(?lastName, ', ', ?firstName) )"
+ + " OPTIONAL { ?uri auth:externalAuthId ?externalAuthId } \n"
+ + " FILTER (REGEX(?label, '^%term%', 'i')) \n"
+ + "} \n"
+ + "ORDER BY ASC(?lastName) ASC(?firstName) \n"
+ + "LIMIT 25 \n";
+var moreInfoQuery = ""
+ + "PREFIX rdfs: \n"
+ + "PREFIX vitro: \n"
+ + "PREFIX p.1: \n"
+ + " \n"
+ + "SELECT ?uri ?classLabel ?imageUrl \n"
+ + "WHERE \n"
+ + "{ \n"
+ + " ?uri <%matchingProperty%> '%externalAuthId%'. \n"
+ + " \n"
+ + " OPTIONAL { \n"
+ + " ?uri vitro:mostSpecificType ?type. \n"
+ + " ?type rdfs:label ?classLabel \n"
+ + " } \n"
+ + " \n"
+ + " OPTIONAL { \n"
+ + " ?uri p.1:mainImage ?imageUri. \n"
+ + " ?imageUri p.1:thumbnailImage ?thumbUri. \n"
+ + " ?thumbUri p.1:downloadLocation ?thumbstreamUri. \n"
+ + " ?thumbstreamUri p.1:directDownloadUrl ?imageUrl. \n"
+ + " } \n"
+ + "} \n"
+ + "LIMIT 1 \n";
+
+/*
+ * This function will allow a proxy panel to execute another query for each proxy.
+ */
+var getAdditionalProxyInfo = function(parent, info, externalAuthId) {
+ $.ajax({
+ url: proxyContextInfo.sparqlQueryUrl,
+ dataType: 'json',
+ data: {
+ query: moreInfoQuery.replace("%matchingProperty%", proxyContextInfo.matchingProperty)
+ .replace("%externalAuthId%", externalAuthId)
+ },
+ complete: function(xhr, status) {
+ var results = $.parseJSON(xhr.responseText);
+ var parsed = sparqlUtils.parseSparqlResults(results);
+ if (parsed.length > 0) {
+ if ("classLabel" in parsed[0]) {
+ info.classLabel = parsed[0].classLabel;
+ }
+ if ("imageUrl" in parsed[0]) {
+ info.imageUrl = proxyContextInfo.baseUrl + parsed[0].imageUrl;
+ }
+ parent.displayItemData();
+ }
+ }
+ });
+}
+
+
+/*
+ * Execute this when the page loads.
+ */
$(document).ready(function() {
var disableFormInUnsupportedBrowsers = function() {
var disableWrapper = $('#ie67DisableWrapper');
@@ -161,10 +239,15 @@ $(document).ready(function() {
return false;
};
+ /* If we don't support this form in this browser, just stop here. */
if (disableFormInUnsupportedBrowsers()) {
return;
}
+ /*
+ * For each proxyProfilesPanel, create a plain vanilla panel using the
+ * profile query against the main model.
+ */
$("div[name='proxyProfilesPanel']").each(function(i) {
var context = {
excludedUris: [],
@@ -174,7 +257,25 @@ $(document).ready(function() {
query: profileQuery,
model: ''
}
- var ppp = new proxyItemsPanel(this, context);
- this["ppp"]=ppp;
+ this["proxyItemsPanel"] = new proxyItemsPanel(this, context);
+ });
+
+ /*
+ * For each proxyProxiesPanel, we start with a plain panel using the proxy
+ * query against the user accounts model. Then we augment it with a method
+ * that will fetch more info from the main model for each proxy.
+ */
+ $("div[name='proxyProxiesPanel']").each(function(i) {
+ var context = {
+ excludedUris: [],
+ baseUrl: proxyContextInfo.baseUrl,
+ sparqlQueryUrl: proxyContextInfo.sparqlQueryUrl,
+ defaultImageUrl: proxyContextInfo.defaultImageUrl,
+ query: proxyQuery,
+ model: 'userAccounts'
+ }
+ var pip = new proxyItemsPanel(this, context);
+ pip.getAdditionalData = getAdditionalProxyInfo;
+ this["proxyItemsPanel"] = pip;
});
});
diff --git a/webapp/web/js/account/accountProxyProxiesPanel.js b/webapp/web/js/account/accountProxyProxiesPanel.js
deleted file mode 100644
index bd7177955..000000000
--- a/webapp/web/js/account/accountProxyProxiesPanel.js
+++ /dev/null
@@ -1,187 +0,0 @@
-/* $This file is distributed under the terms of the license in /doc/license.txt$ */
-
-function proxyProxiesPanel(p) {
- var query = ""
- + "PREFIX fn: \n"
- + "PREFIX auth: \n"
- + "\n"
- + "SELECT DISTINCT ?uri ?label ?externalAuthId \n"
- + "WHERE { \n"
- + " ?uri a auth:UserAccount ; \n"
- + " auth:firstName ?firstName ; \n"
- + " auth:lastName ?lastName . \n"
- + " LET ( ?label := fn:concat(?lastName, ', ', ?firstName) )"
- + " OPTIONAL { ?uri auth:externalAuthId ?externalAuthId } \n"
- + " FILTER (REGEX(?label, '^%term%', 'i')) \n"
- + "} \n"
- + "ORDER BY ASC(?lastName) ASC(?firstName) \n"
- + "LIMIT 25 \n";
-
- var moreInfoQuery = ""
- + "PREFIX rdfs: \n"
- + "PREFIX vitro: \n"
- + "PREFIX p.1: \n"
- + " \n"
- + "SELECT ?uri ?classLabel ?imageUrl \n"
- + "WHERE \n"
- + "{ \n"
- + " ?uri <%matchingProperty%> '%externalAuthId%'. \n"
- + " \n"
- + " OPTIONAL { \n"
- + " ?uri vitro:mostSpecificType ?type. \n"
- + " ?type rdfs:label ?classLabel \n"
- + " } \n"
- + " \n"
- + " OPTIONAL { \n"
- + " ?uri p.1:mainImage ?imageUri. \n"
- + " ?imageUri p.1:thumbnailImage ?thumbUri. \n"
- + " ?thumbUri p.1:downloadLocation ?thumbstreamUri. \n"
- + " ?thumbstreamUri p.1:directDownloadUrl ?imageUrl. \n"
- + " } \n"
- + "} \n"
- + "LIMIT 1 \n";
-
- var self = this;
-
- var excludedUris = [proxyMechanism.myAccountUri];
-
- var removeProxyInfo = function(info) {
- self.removeProxyInfo(info)
- }
-
- this.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;
- };
-
- this.parseProxyTemplate = function() {
- var templateDiv = $("div[name='template']", this.proxyDataDiv)
- this.templateHtml = templateDiv.html();
- templateDiv.remove();
- };
-
- this.removeProxyInfo = function(info) {
- var idx = self.proxyData.indexOf(info);
- if (idx != -1) {
- self.proxyData.splice(idx, 1);
- }
- self.displayProxyData();
- }
-
- this.parseProxyData = function() {
- var datas = $("div[name='data']", this.proxyDataDiv)
-
- this.proxyData = []
- for (i = 0; i < datas.length; i++) {
- var data = datas[i];
- var uri = $("p[name='uri']", data).text();
- var label = $("p[name='label']", data).text();
- var classLabel = $("p[name='classLabel']", data).text();
- var imageUrl = $("p[name='imageUrl']", data).text();
- this.proxyData.push(new proxyInfoElement(this.templateHtml, uri, label, classLabel, imageUrl, removeProxyInfo));
- }
- }
-
- this.displayProxyData = function() {
- $("div[name='proxyInfoElement']", this.proxyDataDiv).remove();
-
- for (i = 0; i < this.proxyData.length; i++) {
- this.proxyData[i].element().appendTo(this.proxyDataDiv);
- }
- }
-
- if (this.disableFormInUnsupportedBrowsers()) {
- return;
- }
-
- this.getAdditionalInfo = function(info, externalAuthId) {
- $.ajax({
- url: proxyMechanism.sparqlQueryUrl,
- dataType: 'json',
- data: {
- query: moreInfoQuery.replace("%matchingProperty%", proxyMechanism.matchingProperty)
- .replace("%externalAuthId%", externalAuthId)
- },
- complete: function(xhr, status) {
- var results = $.parseJSON(xhr.responseText);
- var parsed = sparqlUtils.parseSparqlResults(results);
- if (parsed.length > 0) {
- if ("classLabel" in parsed[0]) {
- info.classLabel = parsed[0].classLabel;
- }
- if ("imageUrl" in parsed[0]) {
- info.imageUrl = proxyMechanism.baseUrl + parsed[0].imageUrl;
- }
- self.displayProxyData();
- }
- }
- });
- }
-
- this.panel = p;
- this.proxyDataDiv = $("div[name='proxyData']", this.panel).first();
- this.addAutoCompleteField = $("input[name='proxySelectorAC']", this.panel).first();
- this.searchStatusField = $("span[name='proxySelectorSearchStatus']", this.panel).first();
-
- this.parseProxyTemplate();
- this.parseProxyData();
- this.displayProxyData();
-
- this.getProxyInfos = function() {
- return self.proxyData;
- }
-
- this.addProxyInfo = function(selection) {
- var info = new proxyInfoElement(self.templateHtml, selection.uri, selection.label, "", "", removeProxyInfo)
- self.proxyData.unshift(info);
- self.getAdditionalInfo(info, selection.externalAuthId)
- self.displayProxyData();
- }
-
-
- this.setupAutoCompleteFields = function() {
- var parms = {
- query: query,
- model: "userAccounts",
- url: proxyMechanism.sparqlQueryUrl
- };
- var reportSearchStatus = new searchStatusField(this.searchStatusField, 3).setText;
- this.addAutoCompleteField.autocomplete(new proxyAutocomplete(parms, excludedUris, this.getProxyInfos, this.addProxyInfo, reportSearchStatus));
- }
-
- this.setupAutoCompleteFields();
-}
-
-function searchStatusField(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);
- }
- }
-}
-
-$(document).ready(function() {
- $("div[name='proxyProxiesPanel']").each(function(i) {
- var ppp = new proxyProxiesPanel(this);
- this["ppp"]=ppp;
- });
-});
diff --git a/webapp/web/templates/freemarker/body/accounts/userAccounts-myProxiesPanel.ftl b/webapp/web/templates/freemarker/body/accounts/userAccounts-myProxiesPanel.ftl
index 4e8262f08..263226a80 100644
--- a/webapp/web/templates/freemarker/body/accounts/userAccounts-myProxiesPanel.ftl
+++ b/webapp/web/templates/freemarker/body/accounts/userAccounts-myProxiesPanel.ftl
@@ -49,16 +49,16 @@ ${stylesheets.add('
-var proxyMechanism = {
+var proxyContextInfo = {
baseUrl: '${urls.base}',
sparqlQueryUrl: '${formUrls.sparqlQueryAjax}',
+ defaultImageUrl: '${formUrls.defaultImageUrl}',
matchingProperty: '${matchingProperty}',
- myAccountUri: '${myAccountUri}'
};
${scripts.add('',
'',
'',
- '',
+ '',
'')}
\ No newline at end of file