Merged HEAD-BUG-FIX (5.1/Cloud) to HEAD (5.1/Cloud)

92620: ACE-3703 - Refactor Repository Admin Console framework to allow the basic framework to work in Community version
     - Framework base moved to web-client project.
     - Refactored Enterprise admin console to base from the web-client one.
     - Empty Community admin console start page


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@94892 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Alan Davis
2015-01-31 11:53:46 +00:00
parent 62d2d8bcbb
commit 46c4d07af0
10 changed files with 1214 additions and 4 deletions

View File

@@ -0,0 +1,169 @@
/*
* Copyright 2005-2015 Alfresco Software, Ltd. All rights reserved.
*
* License rights for this program may be obtained from Alfresco Software, Ltd.
* pursuant to a written agreement and any use of this program without such an
* agreement is prohibited.
*/
/**
* Repository Admin Console
*
* Common JavaScript library functions.
*/
/* Admin JavaScript namespace - public functions exposed through this namespace. */
var Admin = Admin || {};
(function() {
/**
* Return an indexed array of available Admin console tools.
*
* [
* {
* id: <script identifier>,
* label: <display label>,
* group: <group identifier>,
* groupLabel: <group display label>,
* description: <description>,
* selected: <true if currently selected tool>
* }
* ...
* ]
*/
Admin.getConsoleTools = function getConsoleTools(currentToolId)
{
// return an map of group->tool[] information
var toolInfo = {};
// collect the tools required for the Admin Console
var tools = utils.findWebScripts("AdminConsole");
// process each tool and generate the data so that a label+link can
// be output by the component template for each tool required
for (var i = 0; i < tools.length; i++)
{
var tool = tools[i],
id = tool.id,
scriptName = id.substring(id.lastIndexOf('/') + 1, id.lastIndexOf('.'));
// use the webscript ID to generate message bundle IDs
var labelId = "admin-console.tool." + scriptName + ".label",
descId = "admin-console.tool." + scriptName + ".description";
// identify console tool grouping if any
// simple convention is used to resolve group - last element of the webscript package path after 'admin'
// for example: org.alfresco.repository.admin.system = system
// package paths not matching the convention will be placed in the default root group
// the I18N label is named: admin-console.tool.group.<yourgroupid>
var group = "",
groupLabelId = null,
paths = tool.scriptPath.split('/');
if (paths[paths.length-2] == "admin")
{
// found webscript package grouping
group = paths[paths.length-1];
groupLabelId = "admin-console.tool.group." + group;
}
var info =
{
id: scriptName,
label: msg.get(labelId) != labelId ? msg.get(labelId) : tool.shortName,
group: group,
groupLabel: group != "" ? (msg.get(groupLabelId) != groupLabelId ? msg.get(groupLabelId) : String(group).replace(/_/g, " ")) : "",
description: msg.get(descId) != descId ? msg.get(descId) : tool.description,
selected: (currentToolId == scriptName)
};
// process family metadata
var isCommunity = (utils.getRestrictions().licenseMode == "UNKNOWN"),
index = -1,
addTool = true,
familys = tool.familys.toArray();
for (var f=0; f<familys.length; f++)
{
// find the index if specified
if (familys[f].indexOf("AdminConsole:Index:") !== -1)
{
index = parseInt(familys[f].substring("AdminConsole:Index:".length), 10);
}
// find community only pages
if (familys[f] == "AdminConsole:Edition:Community")
{
addTool = isCommunity;
}
}
// only add tools if not filtered from the list
if (addTool)
{
// generate the tool info structure
if (!toolInfo[group])
{
toolInfo[group] = [];
}
// add to group - with specific index if specified in descriptor
if (index === -1)
{
toolInfo[group].push(info);
}
else
{
toolInfo[group].splice(index, 0, info);
}
}
}
// convert to simple indexed array now we have completed the group processing
var toolsArray = [];
for each (var g in toolInfo)
{
toolsArray.push(g);
}
toolsArray.sort(function(a,b) {
return a[0].group > b[0].group ? 1 : -1
});
return toolsArray;
}
/**
* Return the script ID of the default Admin Console tool (first tool indexed in the list)
*/
Admin.getDefaultTool = function getDefaultTool()
{
var tools = Admin.getConsoleTools(),
tool = tools[0][0];
return tool.id;
}
/**
* Return an object containing IP metadata about the server instance.
*/
Admin.getServerMetaData = function getServerMetaData()
{
return {
hostname: utils.hostName,
hostaddress: utils.hostAddress
};
}
Admin.encodeHtml = function encodeHtml(s)
{
if (!s)
{
return "";
}
s = "" + s;
return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
}
})();
/**
* END Repository Admin Console - Common JavaScript library functions.
*/

View File

@@ -0,0 +1,13 @@
<webscript>
<shortname>Admin Console - Community Summary</shortname>
<description><![CDATA[Admin Console WebScript that displays the Community Summary page.]]></description>
<url>/admin/admin-communitysummary</url>
<family>AdminConsole</family>
<family>AdminConsole:Index:0</family>
<!-- COMMUNITY ONLY -->
<family>AdminConsole:Edition:Community</family>
<format default="html">argument</format>
<authentication>admin</authentication>
<lifecycle>internal</lifecycle>
<transaction allow="readonly">required</transaction>
</webscript>

View File

@@ -0,0 +1,24 @@
<#include "admin-template.ftl" />
<@page title=msg("admin-console.tool.admin-communitysummary.label") readonly=true>
<@section label=msg("communitysummary.system-information") />
<div class="column-left">
<#--<@attrfield attribute=sysPropsAttributes["alfresco.home"] label=msg("communitysummary.system-information.alfresco-home") />
<@attrfield attribute=alfrescoAttributes["Edition"] label=msg("communitysummary.system-information.alfresco-edition") />
<@attrfield attribute=alfrescoAttributes["VersionNumber"] label=msg("communitysummary.system-information.alfresco-version") />
<@attrfield attribute=sysPropsAttributes["java.home"] label=msg("communitysummary.system-information.java-home") />
<@attrfield attribute=sysPropsAttributes["java.version"] label=msg("communitysummary.system-information.java-version") />
<@attrfield attribute=sysPropsAttributes["java.vm.vendor"] label=msg("communitysummary.system-information.java-vm-vendor") />-->
</div>
<div class="column-right">
<#--<@attrfield attribute=sysPropsAttributes["os.name"] label=msg("communitysummary.system-information.operating-system") />
<@attrfield attribute=sysPropsAttributes["os.version"] label=msg("communitysummary.system-information.version") />
<@attrfield attribute=sysPropsAttributes["os.arch"] label=msg("communitysummary.system-information.architecture") />
<@attrfield attribute=memoryAttributes["FreeMemory"] label=msg("communitysummary.system-information.free-memory") />
<@attrfield attribute=memoryAttributes["MaxMemory"] label=msg("communitysummary.system-information.maximum-memory") />
<@attrfield attribute=memoryAttributes["TotalMemory"] label=msg("communitysummary.system-information.total-memory") />-->
</div>
</@page>

View File

@@ -0,0 +1,14 @@
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/repository/admin/admin-common.lib.js">
/**
* Repository Admin Console
*
* Community Summary GET method
*/
function main()
{
model.tools = Admin.getConsoleTools("admin-communitysummary");
model.metadata = Admin.getServerMetaData();
}
main();

View File

@@ -0,0 +1 @@
communitysummary.system-information=System Information

View File

@@ -0,0 +1,10 @@
<webscript>
<shortname>Admin Console - root page</shortname>
<description><![CDATA[Admin Console WebScript that retrieves available admin console tools and redirects to the first one.]]></description>
<url>/admin</url>
<url>/admin/</url>
<format default="html">argument</format>
<authentication>admin</authentication>
<lifecycle>internal</lifecycle>
<transaction allow="readonly">required</transaction>
</webscript>

View File

@@ -0,0 +1,16 @@
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/repository/admin/admin-common.lib.js">
/**
* Repository Admin Console
*
* Root page GET method
*/
function main()
{
var surl = url.service + (url.service.lastIndexOf('/') !== url.service.length() - 1 ? '/' : "");
status.code = 301;
status.location = surl + Admin.getDefaultTool();
status.redirect = true;
}
main();

View File

@@ -0,0 +1,823 @@
<#--
ADMIN TEMPLATE MACROS
-->
<#--
Template outer "page" macro.
@param title - Title msg for the page
@param readonly (default:false) - boolean read only flag, if true will not display the Submit buttons.
@param controller (default:"/enterprise/admin") - optionally override the Form controller
@param params (default:"") - url encoded params to be added to the HTML form URL
-->
<#macro page title readonly=false controller="/enterprise/admin" params="" dialog=false>
<#assign FORM_ID="admin-jmx-form" />
<#if metadata??>
<#assign HOSTNAME>${msg("admin-console.host")}: ${metadata.hostname}</#assign>
<#assign HOSTADDR>${msg("admin-console.ipaddress")}: ${metadata.hostaddress}</#assign>
</#if>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Alfresco &raquo; ${title?html}<#if metadata??> [${HOSTNAME} ${HOSTADDR}]</#if></title>
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
<link rel="stylesheet" type="text/css" href="${url.context}/css/reset.css" />
<link rel="stylesheet" type="text/css" href="${url.context}/css/alfresco.css" />
<link rel="stylesheet" type="text/css" href="${url.context}/admin/css/admin.css" />
<!--[if IE 8 ]><style type="text/css">.dialog{width:100%}</style><![endif]-->
<script type="text/javascript">//<![CDATA[
/* JavaScript global helper methods and event handlers */
var el = function el(id)
{
return document.getElementById(id);
}
/* Admin namespace helper methods */
var Admin = Admin || {};
(function() {
/* private scoped values */
_dialog = null;
_dialogScrollPosition = null;
/* publicly accessable helper functions */
/**
* String trim helper
*
* @param s {string} String to trim pre and post whitespace from
* @return trimmed string value - returns empty string for null or undefined input
*/
Admin.trim = function trim(s)
{
return s ? s.replace(/^\s+|\s+$/g, "") : "";
}
/**
* String HTML encoding helper
*
* @param s {string} String to HTML encode
* @return encoded string value - returns empty string for null or undefined input
*/
Admin.html = function html(s)
{
if (!s)
{
return "";
}
s = "" + s;
return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
}
/**
* Helper to add a named DOM event listener function to an object
*
* @param obj {Element} DOM object to add the named event listener too
* @param event {string} Event name e.g. "click"
* @param fn {function} Event handler function to invoke
*/
Admin.addEventListener = function addEventListener(obj, event, fn)
{
if (obj.addEventListener)
{
obj.addEventListener(event, fn, false);
}
else
{
obj.attachEvent("on" + event, fn);
}
}
/**
* DIV Section toggle event handler
*
* @param a {Element} Anchor element that fired the toggle event
*/
Admin.sectionToggle = function sectionToggle(a)
{
<#-- NOTE: dependent on template structure in @tsection macro below -->
// walk the DOM nodes to get to the toggle div element
var div = a.parentElement.parentElement.getElementsByTagName("div")[0].getElementsByTagName("div")[0];
if (Admin.toggleHiddenElement(div))
{
// will now be open
a.innerHTML = "\u25BC";
}
else
{
// will now be closed
a.innerHTML = "\u25BA";
}
}
/**
* Toggle the "hidden" class for a given DOM element
*
* @param el {Element} Element to add/remove the "hidden" class to
*/
Admin.toggleHiddenElement = function toggleHiddenElement(el)
{
var clazzes = el.className.split(" "),
foundHidden = false;
for (var i = 0; i < clazzes.length; i++)
{
// found the toggle el - switch display class
if (foundHidden = (clazzes[i] === "hidden"))
{
clazzes.splice(i, 1);
break;
}
}
if (!foundHidden)
{
clazzes.push("hidden");
}
// apply new classes to the el
el.className = clazzes.join(" ");
return foundHidden;
}
Admin.addClass = function addClass(el, c)
{
var clazzes = el.className.split(" "), found = false;
for (var i = 0; i < clazzes.length; i++)
{
if (found = (clazzes[i] === c)) break;
}
if (!found)
{
el.className += " " + c;
}
}
Admin.removeClass = function removeClass(el, c)
{
var clazzes = el.className.split(" ");
for (var i = 0; i < clazzes.length; i++)
{
if (clazzes[i] === c)
{
clazzes.splice(i, 1);
break;
}
}
el.className = clazzes.join(" ");
}
/**
* Add a row to an existing table
*
* @param table {Element} The table DOM element
* @param row {Array} Array of cell data to add
* @param index {Integer} Index to insert at - default is add to end
*/
Admin.addTableRow = function addTableRow(table, row, index)
{
var tr = table.insertRow(index !== undefined ? index : -1);
for (var i=0, td; i<row.length; i++)
{
td = tr.insertCell(-1);
td.innerHTML = row[i];
}
}
/**
* Show the contents of a URL in a dialog styled IFrame
*
* @param url {String} URL in the same domain to display in the dialog frame
*/
Admin.showDialog = function showDialog(url, compact)
{
if (!_dialog)
{
// generate IFrame for the dialog contents
var iframe = document.createElement('iframe');
iframe.name = iframe.id = 'admin-dialog';
iframe.src = url;
iframe.frameBorder = 0;
iframe.className = (compact? 'dialog compact' : 'dialog');
_dialog = iframe;
// generate a shield over the background elements
var shield = document.createElement('div');
shield.id = "shield";
shield.className = 'shield';
// display the elements and hide background scrollbars
document.body.appendChild(shield);
document.body.appendChild(iframe);
document.body.style.overflow = 'hidden';
// scroll to top and record last Y scroll position
_dialogScrollPosition = window.pageYOffset;
window.scrollTo(0,0);
}
}
/**
* Remove any existing dialog frame and restore background elements
*/
Admin.removeDialog = function removeDialog(state, args)
{
if (_dialog)
{
// remove the dialog IFrame and shield from the DOM
_dialog.parentNode.removeChild(_dialog);
var shield = el("shield");
shield.parentNode.removeChild(shield);
// restore background scrollbars
document.body.style.overflow = "";
// scroll back
window.scrollTo(0, _dialogScrollPosition);
_dialog = null;
if (state)
{
switch (state)
{
case "saved":
Admin.ondialogFinished(args);
break;
}
}
}
}
/**
* Default ondialogFinished event handler with empty impl.
* Dialog templates can override this to add additional processing.
*/
Admin.ondialogFinished = function ondialogFinished(args)
{
}
/**
* Ajax request helper
*
* @param config {Object} Of the form:
* {
* method: "GET|POST|PUT|DELETE",
* url: "endpointurl",
* data: {object to be posted},
* requestContentType: "application/json",
* responseContentType: "application/json",
* fnSuccess: successHandler(response),
* fnFailure: failureHandler(response)
* }
*/
Admin.request = function request(config)
{
var req = new XMLHttpRequest();
var data = config.data || {};
if (req.overrideMimeType) req.overrideMimeType((config.responseContentType ? config.responseContentType : "application/json") + "; charset=utf-8");
req.open(config.method ? config.method : "GET", config.url);
req.setRequestHeader("Accept", config.requestContentType ? config.requestContentType : "application/json");
req.onreadystatechange = function() {
if (req.readyState === 4)
{
if (req.status === 200)
{
// success - call handler
if (config.fnSuccess)
{
var json;
try
{
json = !config.responseContentType || config.responseContentType === "application/json" ? JSON.parse(req.responseText) : null;
}
catch (e)
{
// Developer JSON response error (e.g. malformed response text)
alert(e + "\n" + req.status + "\n" + req.responseText);
}
config.fnSuccess.call(this, {
responseText: req.responseText,
responseStatus: req.status,
responseJSON: json
});
}
}
else
{
// failure - call handler
if (config.fnFailure)
{
config.fnFailure.call(this, {
responseText: req.responseText,
responseStatus: req.status
});
}
else
{
// default error handler
alert("${msg("admin-console.requesterror")}\n\n" + res.responseText + "\n\n" + res.responseStatus);
}
}
}
};
if (config.method === "POST" || config.method === "PUT")
{
// TODO: support form url encoded
req.send(JSON.stringify(data));
}
else
{
req.send(null);
}
}
/**
* Perform binary file upload to a given service URL. Uses hidden iframe technique to give
* an Ajax like upload with support for earlier browser APIs.
*
* @param fileId ID of the File element to POST
* @param url URL of the service endpoint
* @param successHandler Success handler function - passed JSON object response as argument
* @param failureHandler Failure handler function - no arguments
*/
Admin.uploadFile = function uploadFile(fileId, url, successHandler, failureHandler)
{
var file = el(fileId),
ownerDocument = file.ownerDocument,
pwindow = ownerDocument.defaultView || ownerDocument.parentWindow,
iframe = ownerDocument.createElement("iframe");
iframe.style.display = "none";
iframe.name = "AdminUploadFrame";
iframe.id = iframe.name;
ownerDocument.body.appendChild(iframe);
// target the frame properly in IE
pwindow.frames[iframe.name].name = iframe.name;
Admin.addEventListener(iframe, 'load', function() {
var frame = document.getElementById(iframe.name);
if (frame.contentDocument)
{
content = frame.contentDocument.body.textContent;
}
else if (frame.contentWindow)
{
content = frame.contentWindow.document.body.textContent;
}
try
{
if (successHandler)
{
var json = JSON.parse(content);
successHandler.call(this, json);
}
}
catch (e)
{
if (failureHandler)
{
failureHandler.call(this);
}
}
});
var form = ownerDocument.createElement("form");
ownerDocument.body.appendChild(form);
form.style.display = "none";
form.method = "post";
form.encoding = "multipart/form-data";
form.enctype = "multipart/form-data";
form.target = iframe.name;
form.action = url;
form.appendChild(file);
form.submit();
}
/**
* Switch an input field between test and password to show and hide the text.
*
* @param id {String} ID of the password field
* @param button {Element} The button that was clicked
*/
Admin.togglePassword = function togglePassword(id, button)
{
var field = el(id);
if(field.type === "password")
{
button.value = "${msg("admin-console.password.hide")?html}";
field.type = "text";
}
else
{
button.value = "${msg("admin-console.password.show")?html}";
field.type = "password";
}
}
})();
/* Page load handler */
Admin.addEventListener(window, 'load', function() {
// get the root form element
var form = el("${FORM_ID}");
// ensure ENTER press in a Form field doesn't submit the Form
Admin.addEventListener(form, 'keypress', function(e) {
if (e.keyCode === 13)
{
e.preventDefault ? e.preventDefault() : event.returnValue = false;
}
return true;
});
// highlight first form input field
var fields = form.getElementsByTagName("input");
for (var i=0; i<fields.length; i++)
{
if (fields[i].type === "text" || fields[i].type === "textarea")
{
if (!fields[i].readOnly)
{
fields[i].focus();
break;
}
}
}
// escape key handler to close dialog page
Admin.addEventListener(document, 'keypress', function(e) {
if (e.keyCode === 27)
{
top.window.Admin.removeDialog();
}
});
});
//]]></script>
</head>
<#if !dialog>
<body>
<#--
Template for a full page view
-->
<div class="sticky-wrapper">
<div class="header">
<span><a href="${url.serviceContext}/enterprise/admin">${msg("admin-console.header")}</a></span><#if metadata??><span class="meta">${HOSTNAME}</span><span class="meta">${HOSTADDR}</span></#if>
<div style="float:right"><a href="http://docs.alfresco.com/5.0/concepts/ch-administering.html" target="_blank">${msg("admin-console.help")}</a></div>
</div>
<div class="navigation-wrapper">
<div class="navigation">
<#-- A console tool is defined as a member of the 'AdminConsole' WebScript family -->
<#local tool=""/>
<#if tools??>
<ul>
<#list tools as group>
<#list group as tool>
<#if tool_index = 0 && tool.group != ""></ul><h3>${tool.groupLabel}</h3><ul></#if>
<li class="<#if tool.selected><#local tool=tool.id/>selected</#if>"><a href="${tool.id}" class="tool-link" title="${tool.description?html}">${tool.label?html}</a></li>
</#list>
</#list>
</#if>
</ul>
</div>
<div class="main-wrapper">
<div class="title">
<span class="logo"><img src="${url.context}/images/logo/logo.png" width="145" height="48" alt="" /></span>
<span class="logo-separator">&nbsp;</span>
<h1>${title?html}</h1>
</div>
<#-- User information messages -->
<#if args.m??>
<div class="message">
${.now?string("HH:mm:ss")} - ${msg(args.m)?html}
<a href="#" onclick="this.parentElement.style.display='none';" title="${msg("admin-console.close")}">[X]</a>
</div>
</#if>
<#if args.e??>
<div class="message error">
${.now?string("HH:mm:ss")} - ${msg(args.e)?html}
<a href="#" onclick="this.parentElement.style.display='none';" title="${msg("admin-console.close")}">[X]</a>
</div>
</#if>
<div class="main">
<form id="${FORM_ID}" action="${url.serviceContext}${controller}?t=${tool}<#if params!="">&${params}</#if>" enctype="multipart/form-data" accept-charset="utf-8" method="post">
<#-- Template-specific markup -->
<#nested>
<#if !readonly>
<div class="submission buttons">
<input type="submit" value="${msg("admin-console.save")}" />
<input class="cancel" type="button" value="${msg("admin-console.cancel")}" onclick="location.href='${url.service}'" />
</div>
</#if>
</form>
</div>
</div>
</div>
<div class="push"></div>
</div>
<div class="footer">
Alfresco Software, Inc. &copy; 2005-2014 All rights reserved.
</div>
<#else>
<body class="dialog-body">
<#--
Template for a dialog page view
-->
<div>
<div class="navigation-wrapper">
<div>
<div class="title">
<span class="logo"><img src="${url.context}/images/logo/logo.png" width="145" height="48" alt="" /></span>
<span class="logo-separator">&nbsp;</span>
<h1>${title?html}</h1>
</div>
<div class="main">
<form id="${FORM_ID}" action="${url.serviceContext}/enterprise/admin/admin-dialog<#if params!="">&${params}</#if>" enctype="multipart/form-data" accept-charset="utf-8" method="post">
<#-- Template-specific markup -->
<#nested>
</form>
</div>
</div>
</div>
</div>
</#if>
</body>
</html>
</#macro>
<#macro dialogbuttons save=false close=true>
<div class="buttons">
<#-- Template-specific markup -->
<#nested>
<#if save><input type="submit" value="${msg("admin-console.save")}" /></#if>
<#if close><input class="cancel" type="button" value="${msg("admin-console.close")}" onclick="top.window.Admin.removeDialog();" /></#if>
</div>
</#macro>
<#--
Template section macros.
-->
<#macro section label>
<h2>${label?html}</h2>
<div class="section">
<#nested>
</div>
</#macro>
<#macro tsection label closed=true>
<div>
<h2>${label?html} <a class="action toggler" href="#" onclick="Admin.sectionToggle(this);return false;"><#if closed>&#x25BA;<#else>&#x25BC;</#if></a></h2>
<div class="section">
<div class="toggle <#if closed>hidden</#if>">
<#nested>
</div>
</div>
</div>
</#macro>
<#--
Template field macros and value conversion.
-->
<#function cvalue type value="">
<#switch type>
<#case "java.util.Date">
<#if value?has_content>
<#return value?datetime>
<#else>
<#return value>
</#if>
<#break>
<#case "boolean">
<#return value?string>
<#break>
<#case "java.lang.Long">
<#return value>
<#break>
<#default>
<#return value>
</#switch>
</#function>
<#macro control attribute>
<#if attribute.readonly>
<@attrfield attribute=attribute />
<#else>
<#switch attribute.type>
<#case "java.util.Date">
<@attrtext attribute=attribute />
<#break>
<#case "boolean">
<@attrcheckbox attribute=attribute />
<#break>
<#case "java.lang.Long">
<@attrtext attribute=attribute />
<#break>
<#default>
<@attrtext attribute=attribute />
</#switch>
</#if>
</#macro>
<#-- Hidden field -->
<#macro hidden name value="" id="">
<input type="hidden" <#if id?has_content>id="${id?html}"</#if> name="${name?html}" value="${value?html}" />
</#macro>
<#macro attrhidden attribute name=attribute.qname id="">
<@hidden name=name value=cvalue(attribute.type, attribute.value) id=id />
</#macro>
<#-- Label and simple read-only field -->
<#macro field label="" description="" value="" style="">
<div class="control field"<#if style?has_content> style="${style?html}"</#if>>
<#if label?has_content><span class="label">${label?html}:</span></#if>
<#if value?has_content><span class="value">${value?html}</span></#if>
<#if description?has_content><span class="description">${description?html}</span></#if>
<#nested>
</div>
</#macro>
<#macro attrfield attribute label=attribute.name description="" style="">
<@field label=label description=description value=cvalue(attribute.type, attribute.value) style=style>
<#nested>
</@field>
</#macro>
<#-- Label and text input field -->
<#macro text name label="" description="" value="" maxlength=255 id="" style="" controlStyle="" valueStyle="" placeholder="" escape=true>
<div class="control text"<#if style?has_content> style="${style?html}"</#if>>
<#if label?has_content><span class="label">${label?html}:</span></#if>
<span class="value"<#if valueStyle?has_content> style="${valueStyle?html}"</#if>><input <#if id?has_content>id="${id?html}"</#if> name="${name?html}" value="${value?html}" maxlength="${maxlength?c}" tabindex="0" <#if placeholder?has_content>placeholder="${placeholder?html}"</#if> <#if controlStyle?has_content>style="${controlStyle?html}"</#if>/></span>
<#if description?has_content><span class="description"><#if escape>${description?html}<#else>${description}</#if></span></#if>
</div>
</#macro>
<#macro attrtext attribute label=attribute.name description="" maxlength=255 id="" style="" controlStyle="" valueStyle="" placeholder="" escape=true>
<@text name=attribute.qname label=label description=description value=cvalue(attribute.type, attribute.value) maxlength=maxlength id=id style=style controlStyle=controlStyle valueStyle=valueStyle placeholder=placeholder escape=escape />
</#macro>
<#-- Label and password input field -->
<#macro password id name label="" description="" value="" maxlength=255 style="" controlStyle="" visibilitytoggle=false>
<div class="control text password"<#if style?has_content> style="${style?html}"</#if>>
<#if label?has_content><span class="label">${label?html}:</span></#if>
<span class="value"><input id="${id?html}" name="${name?html}" value="${value?html}" maxlength="${maxlength?c}" type="password" tabindex="0" <#if controlStyle?has_content>style="${controlStyle?html}"</#if>/></span>
<#if visibilitytoggle><@button label=msg("admin-console.password.show")?html onclick="Admin.togglePassword('${id?html}', this);" /></#if>
<#if description?has_content><span class="description">${description?html}</span></#if>
</div>
</#macro>
<#macro attrpassword attribute label=attribute.name id=attribute.qname description="" maxlength=255 style="" controlStyle="" visibilitytoggle=false populatevalue=false>
<#if populatevalue>
<@password name=attribute.qname label=label id=id description=description value=cvalue(attribute.type, attribute.value) maxlength=maxlength style=style controlStyle=controlStyle visibilitytoggle=visibilitytoggle />
<#else>
<@password name=attribute.qname label=label id=id description=description maxlength=maxlength style=style controlStyle=controlStyle visibilitytoggle=visibilitytoggle />
</#if>
</#macro>
<#-- Label and text area field -->
<#macro textarea name label="" description="" value="" maxlength=255 id="" style="" controlStyle="">
<div class="control textarea"<#if style?has_content> style="${style?html}"</#if>>
<#if label?has_content><span class="label">${label?html}:</span></#if>
<span class="value"><textarea <#if id?has_content>id="${id?html}"</#if> name="${name?html}" maxlength="${maxlength?c}" tabindex="0" <#if controlStyle?has_content>style="${controlStyle?html}"</#if>>${value?html}</textarea></span>
<#if description?has_content><span class="description">${description?html}</span></#if>
</div>
</#macro>
<#macro attrtextarea attribute label=attribute.name description="" maxlength=255 id="" style="" controlStyle="">
<@textarea name=attribute.qname label=label description=description value=cvalue(attribute.type, attribute.value) maxlength=maxlength id=id style=style controlStyle=controlStyle />
</#macro>
<#-- Label and checkbox boolean field -->
<#macro checkbox name label description="" value="false" id="" style="" controlStyle="">
<div class="control checkbox"<#if style?has_content> style="${style?html}"</#if>>
<span class="label">${label?html}:</span>
<span class="value">
<input <#if id?has_content>id="${id?html}"</#if> name="" onchange="el('${name?html}').value = (this.checked ? 'true' : 'false');" type="checkbox" <#if value="true">checked="checked"</#if> tabindex="0" <#if controlStyle?has_content>style="${controlStyle?html}"</#if>/>
<input id="${name?html}" name="${name?html}" type="hidden" value="<#if value="true">true<#else>false</#if>" />
</span>
<#if description?has_content><span class="description">${description?html}</span></#if>
<#nested>
</div>
</#macro>
<#macro attrcheckbox attribute label=attribute.name description="" id="" style="" controlStyle="">
<@checkbox name=attribute.qname label=label description=description value=cvalue(attribute.type, attribute.value) id=id style=style controlStyle=controlStyle>
<#nested>
</@checkbox>
</#macro>
<#-- Status read-only boolean field -->
<#macro status label description="" value="false" style="">
<#if value != "">
<#if value="true"><#local tooltip=msg("admin-console.enabled")?html><#else><#local tooltip=msg("admin-console.disabled")?html></#if>
<div class="control status"<#if style?has_content> style="${style?html}"</#if>>
<span class="label">${label?html}:</span>
<span class="value">
<img src="${url.context}/admin/images/<#if value="true">enabled<#else>disabled</#if>.gif" width="16" height="16" alt="${tooltip}" title="${tooltip}" />
<span>${tooltip}</span>
</span>
<#if description?has_content><span class="description">${description?html}</span></#if>
</div>
<#else>
<div class="control status"<#if style?has_content> style="${style?html}"</#if>>
<span class="label">${label?html}:</span>
<span class="value">
<span>${msg("admin-console.unavailable")}</span>
</span>
<#if description?has_content><span class="description">${description?html}</span></#if>
</div>
</#if>
</#macro>
<#macro attrstatus attribute="" label=attribute.name description="" style="">
<#-- Special handling for missing attribute - as some JMX objects can be temporarily unavailable -->
<#if attribute?has_content>
<@status label=label description=description value=cvalue(attribute.type, attribute.value) style=style />
<#else>
<@status label=label description=description value="" style=style />
</#if>
</#macro>
<#-- Label and Options Drop-Down list -->
<#macro options name label="" description="" value="" id="" style="" valueStyle="" onchange="" onclick="" escape=true>
<div class="control options"<#if style?has_content> style="${style?html}"</#if>>
<#if label?has_content><span class="label">${label?html}:</span></#if>
<span class="value"<#if valueStyle?has_content> style="${valueStyle?html}"</#if>>
<select <#if id?has_content>id="${id?html}"</#if> name="${name?html}" tabindex="0"<#if onchange?has_content> onchange="${onchange?html}"</#if><#if onclick?has_content> onclick="${onclick?html}"</#if>>
<#assign _value=value>
<#nested>
</select>
</span>
<#if description?has_content><span class="description"><#if escape>${description?html}<#else>${description}</#if></span></#if>
</div>
</#macro>
<#macro option label value>
<option value="${value?html}" <#if value=_value>selected="selected"</#if>>${label?html}</option>
</#macro>
<#macro attroptions attribute label=attribute.name description="" id="" style="" valueStyle="" onchange="" escape=true>
<@options name=attribute.qname label=label description=description value=cvalue(attribute.type, attribute.value) id=id style=style valueStyle="" onchange="" escape=escape>
<#nested>
</@options>
</#macro>
<#-- Label and Radio Button list -->
<#macro radios name label="" description="" value="" style="">
<div class="control radio"<#if style?has_content> style="${style?html}"</#if>>
<#if label?has_content><span class="label">${label?html}:</span></#if>
<span class="value">
<#assign _name=name>
<#assign _value=value>
<#nested>
</span>
<#if description?has_content><span class="description">${description?html}</span></#if>
</div>
</#macro>
<#macro radio label value id="">
<div class="radiovalue">
<input <#if id?has_content>id="${id?html}"</#if> type="radio" name="${_name?html}" value="${value?html}" <#if value=_value>checked="checked"</#if> tabindex="0" />
<span class="radiolabel">${label?html}</span>
</div>
</#macro>
<#-- Ordered and Unordered list of values -->
<#macro list listtype label="" description="" value="" style="">
<div class="control list"<#if style?has_content> style="${style?html}"</#if>>
<#if label?has_content><span class="label">${label?html}:</span></#if>
<${listtype?html}>
<#list value?split(",") as x>
<li>${x?html}</li>
</#list>
</${listtype?html}>
<#if description?has_content><span class="description">${description?html}</span></#if>
</div>
</#macro>
<#macro ulist label="" description="" value="" style="">
<@list listtype="ul" label=label description=description value=value style=style />
</#macro>
<#macro olist label="" description="" value="" style="">
<@list listtype="ol" label=label description=description value=value style=style />
</#macro>
<#macro attrulist attribute label=attribute.name description="" style="">
<@ulist label=label description=description value=cvalue(attribute.type, attribute.value) style=style />
</#macro>
<#macro attrolist attribute label=attribute.name description="" style="">
<@olist label=label description=description value=cvalue(attribute.type, attribute.value) style=style />
</#macro>
<#-- Simple button with JavaScript event handler -->
<#macro button label description="" onclick="" style="" id="" class="" disabled="false">
<input class="<#if class?has_content>${class?html}<#else>inline</#if>" <#if id?has_content>id="${id?html}"</#if> <#if style?has_content>style="${style?html}"</#if> type="button" value="${label?html}" onclick="${onclick?html}" <#if disabled="true">disabled="true"</#if> />
<#if description?has_content><span class="description">${description?html}</span></#if>
</#macro>

View File

@@ -1899,4 +1899,19 @@
<property name="suggesterService" ref="suggesterService"/>
</bean>
<!-- JavaScript extensions -->
<!-- Extend the utils class to provide additional Remote APIs -->
<bean id="utilsScript" parent="baseJavaScriptExtension" class="org.alfresco.web.scripts.WebScriptUtils">
<property name="extensionName">
<value>utils</value>
</property>
<property name="serviceRegistry">
<ref bean="ServiceRegistry" />
</property>
<property name="nodeService" ref="nodeService"/>
<property name="repositoryContainer">
<ref bean="webscripts.container" />
</property>
</bean>
</beans>

View File

@@ -0,0 +1,125 @@
/*
* Copyright (C) 2005-2015 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.web.scripts;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.alfresco.repo.jscript.ScriptUtils;
import org.alfresco.repo.web.scripts.RepositoryContainer;
import org.alfresco.service.cmr.admin.RepoUsage;
import org.alfresco.service.cmr.repository.StoreRef;
import org.springframework.extensions.webscripts.WebScript;
/**
* Override of the JavaScript API ScriptUtils bean "utilsScript" to provide additional
* Remote API methods using objects not available to base Repository project.
* <p>
* See "web-scripts-application-context.xml" for bean definition.
*
* @since 4.2.0
* @since 5.1 (Moved to Remote API project)
* @author Kevin Roast
*/
public class WebScriptUtils extends ScriptUtils
{
protected RepositoryContainer repositoryContainer;
public void setRepositoryContainer(RepositoryContainer repositoryContainer)
{
this.repositoryContainer = repositoryContainer;
}
/**
* Searches for webscript components with the given family name.
*
* @param family the family
*
* @return An array of webscripts that match the given family name
*/
public Object[] findWebScripts(String family)
{
List<Object> values = new ArrayList<Object>();
for (WebScript webscript : this.repositoryContainer.getRegistry().getWebScripts())
{
if (family != null)
{
Set<String> familys = webscript.getDescription().getFamilys();
if (familys != null && familys.contains(family))
{
values.add(webscript.getDescription());
}
}
else
{
values.add(webscript.getDescription());
}
}
return values.toArray(new Object[values.size()]);
}
public String getHostAddress()
{
try
{
return InetAddress.getLocalHost().getHostAddress();
}
catch (UnknownHostException e)
{
return "Unknown";
}
}
public String getHostName()
{
try
{
return InetAddress.getLocalHost().getHostName();
}
catch (UnknownHostException e)
{
return "Unknown";
}
}
public RepoUsage getRestrictions()
{
return this.services.getRepoAdminService().getRestrictions();
}
public RepoUsage getUsage()
{
return this.services.getRepoAdminService().getUsage();
}
/**
* Gets the list of repository stores
*
* @return stores
*/
public List<StoreRef> getStores()
{
return this.services.getNodeService().getStores();
}
}