FELIX-919 : Use new table layout for components panel, fix some layout problems and add new configure option.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@742728 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/webconsole/src/main/resources/res/imgs/component_disable.png b/webconsole/src/main/resources/res/imgs/component_disable.png
new file mode 100644
index 0000000..e6f75d2
--- /dev/null
+++ b/webconsole/src/main/resources/res/imgs/component_disable.png
Binary files differ
diff --git a/webconsole/src/main/resources/res/imgs/component_edit.png b/webconsole/src/main/resources/res/imgs/component_edit.png
new file mode 100644
index 0000000..67817e6
--- /dev/null
+++ b/webconsole/src/main/resources/res/imgs/component_edit.png
Binary files differ
diff --git a/webconsole/src/main/resources/res/imgs/component_enable.png b/webconsole/src/main/resources/res/imgs/component_enable.png
new file mode 100644
index 0000000..f8c8ec6
--- /dev/null
+++ b/webconsole/src/main/resources/res/imgs/component_enable.png
Binary files differ
diff --git a/webconsole/src/main/resources/res/ui/admin.css b/webconsole/src/main/resources/res/ui/admin.css
index 8e7a2c0..37f201c 100644
--- a/webconsole/src/main/resources/res/ui/admin.css
+++ b/webconsole/src/main/resources/res/ui/admin.css
@@ -568,11 +568,14 @@
div.buttons {
background-color: #6181A9;
height: 30px;
+ text-align: right;
+ vertical-align: middle;
+ padding-right: 10px;
+ padding-top: 8px;
}
div.button {
- float:right;
- margin-top: 5px;
- margin-right: 10px;
+ display: inline-block;
+ margin-left: 10px;
}
div.fullwidth {
width: 100%;
@@ -582,7 +585,9 @@
background-color: #F5F5F5;
padding-left: 10px;
border: 1px solid #CCCCCC;
- font-size: 13px;
+ font-family: Verdana, Arial, Helvetica, san-serif;
+ font-size: 11px;
+ font-weight: normal;
color: #222222;
line-height: 19px;
margin-bottom: 10px;
diff --git a/webconsole/src/main/resources/res/ui/bundles.js b/webconsole/src/main/resources/res/ui/bundles.js
index 830af0d..75ec6dd 100644
--- a/webconsole/src/main/resources/res/ui/bundles.js
+++ b/webconsole/src/main/resources/res/ui/bundles.js
@@ -32,9 +32,8 @@
}
function renderButtons( buttons ) {
- $("#plugin_content").append( "<div class='fullwidth'><div class='buttons'>" +
- "<form method='post' enctype='multipart/form-data'><div style='padding-top:5px;'>" +
- buttons + "</div></form></div></div>" );
+ $("#plugin_content").append( "<form method='post' enctype='multipart/form-data'><div class='fullwidth'><div class='buttons'>" +
+ buttons + "</div></div></form>" );
}
function renderData( eventData ) {
@@ -87,8 +86,8 @@
src: appRoot + "/res/imgs/arrow_right.png",
border: "none",
id: 'img' + id,
- title: "Back",
- alt: "Back",
+ title: "Details",
+ alt: "Details",
width: 14,
height: 14,
onClick: 'showDetails(' + id + ');'
diff --git a/webconsole/src/main/resources/res/ui/components.js b/webconsole/src/main/resources/res/ui/components.js
new file mode 100644
index 0000000..c6b1fac
--- /dev/null
+++ b/webconsole/src/main/resources/res/ui/components.js
@@ -0,0 +1,226 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+function renderStatusLine() {
+ $("#plugin_content").append( "<div class='fullwidth'><div class='statusline'/></div>" );
+}
+
+function renderView( /* Array of String */ columns, /* Array of String */ buttons ) {
+ renderStatusLine();
+ renderButtons(buttons);
+ var txt = "<div class='table'><table id='plugin_table' class='tablelayout'><thead><tr>";
+ for ( var name in columns ) {
+ txt = txt + "<th class='col_" + columns[name] + "'>" + columns[name] + "</th>";
+ }
+ txt = txt + "</tr></thead><tbody></tbody></table></div>";
+ $("#plugin_content").append( txt );
+ renderButtons(buttons);
+ renderStatusLine();
+}
+
+function renderButtons( buttons ) {
+ $("#plugin_content").append( "<form method='post' enctype='multipart/form-data'><div class='fullwidth'><div class='buttons'>" +
+ buttons + "</div></div></form>" );
+}
+
+function renderData( eventData ) {
+ $(".statusline").empty().append(eventData.status);
+ $("#plugin_table > tbody > tr").remove();
+ for ( var idx in eventData.data ) {
+ entry( eventData.data[idx] );
+ }
+ $("#plugin_table").trigger("update");
+ if ( drawDetails ) {
+ renderDetails(eventData);
+ }
+}
+
+function entry( /* Object */ dataEntry ) {
+ var trElement = tr( null, { id: "entry" + dataEntry.id } );
+ entryInternal( trElement, dataEntry );
+ $("#plugin_table > tbody").append(trElement);
+}
+
+function actionButton( /* Element */ parent, /* string */ id, /* Obj */ action, /* string */ pid ) {
+ var enabled = action.enabled;
+ var op = action.link;
+ var opLabel = action.name;
+ var img = action.image;
+
+ var arg = id;
+ if ( op == "edit" ) {
+ arg = pid
+ }
+ var input = createElement( "input", null, {
+ type: 'image',
+ title: opLabel,
+ alt: opLabel,
+ src: imgRoot + '/component_' + img + '.png',
+ onClick: 'changeDataEntryState("' + arg + '", "' + op + '");'
+ });
+
+ if (!enabled) {
+ input.setAttribute( "disabled", true );
+ }
+ var div = createElement("div");
+ div.setAttribute("style", "float:left; margin-left:10px;");
+ div.appendChild(input);
+ parent.appendChild( div );
+}
+
+function entryInternal( /* Element */ parent, /* Object */ dataEntry ) {
+ var id = dataEntry.id;
+ var name = dataEntry.name;
+ var state = dataEntry.state;
+
+ var inputElement = createElement("img", "rightButton", {
+ src: appRoot + "/res/imgs/arrow_right.png",
+ border: "none",
+ id: 'img' + id,
+ title: "Details",
+ alt: "Details",
+ width: 14,
+ height: 14,
+ onClick: 'showDetails(' + id + ');'
+ });
+ var titleElement;
+ if ( drawDetails ) {
+ titleElement = text(name);
+ } else {
+ titleElement = createElement ("a", null, {
+ href: window.location.pathname + "/" + id
+ });
+ titleElement.appendChild(text(name));
+ }
+
+ parent.appendChild( td( null, null, [ text( id ) ] ) );
+ parent.appendChild( td( null, null, [ inputElement, text(" "), titleElement ] ) );
+ parent.appendChild( td( null, null, [ text( state ) ] ) );
+ var actionsTd = td( null, null );
+
+ for ( var a in dataEntry.actions ) {
+ actionButton( actionsTd, id, dataEntry.actions[a], dataEntry.pid );
+ }
+ parent.appendChild( actionsTd );
+}
+
+function changeDataEntryState(/* long */ id, /* String */ action) {
+ if ( action == "edit") {
+ window.location = appRoot + "/configMgr/" + id;
+ return;
+ }
+ $.post(pluginRoot + "/" + id, {"action":action}, function(data) {
+ renderData(data);
+ }, "json");
+}
+
+function showDetails( id ) {
+ $.get(pluginRoot + "/" + id + ".json", null, function(data) {
+ renderDetails(data);
+ }, "json");
+}
+
+function loadData() {
+ $.get(pluginRoot + "/.json", null, function(data) {
+ renderData(data);
+ }, "json");
+}
+
+function hideDetails( id ) {
+ $("#img" + id).each(function() {
+ $("#pluginInlineDetails").remove();
+ this.setAttribute("src", appRoot + "/res/imgs/arrow_right.png");
+ this.setAttribute("onClick", "showDetails('" + id + "')");
+ this.setAttribute("title", "Details");
+ this.setAttribute("alt", "Details");
+ });
+}
+
+function renderDetails( data ) {
+ data = data.data[0];
+ $("#entry" + data.id + " > td").eq(1).append("<div id='pluginInlineDetails'/>");
+ $("#img" + data.id).each(function() {
+ if ( drawDetails ) {
+ this.setAttribute("src", appRoot + "/res/imgs/arrow_left.png");
+ var ref = window.location.pathname;
+ ref = ref.substring(0, ref.lastIndexOf('/'));
+ this.setAttribute("onClick", "window.location = '" + ref + "';");
+ this.setAttribute("title", "Back");
+ this.setAttribute("alt", "Back");
+ } else {
+ this.setAttribute("src", appRoot + "/res/imgs/arrow_down.png");
+ this.setAttribute("onClick", "hideDetails('" + data.id + "')");
+ this.setAttribute("title", "Hide Details");
+ this.setAttribute("alt", "Hide Details");
+ }
+ });
+ $("#pluginInlineDetails").append("<table border='0'><tbody></tbody></table>");
+ var details = data.props;
+ for (var idx in details) {
+ var prop = details[idx];
+
+ var txt = "<tr><td class='aligntop' noWrap='true' style='border:0px none'>" + prop.key + "</td><td class='aligntop' style='border:0px none'>";
+ if (prop.value) {
+ if ( $.isArray(prop.value) ) {
+ var i = 0;
+ for(var pi in prop.value) {
+ var value = prop.value[pi];
+ if (i > 0) { txt = txt + "<br/>"; }
+ var span;
+ if (value.substring(0, 2) == "!!") {
+ txt = txt + "<span style='color: red;'>" + value + "</span>";
+ } else {
+ txt = txt + value;
+ }
+ i++;
+ }
+ } else {
+ txt = txt + prop.value;
+ }
+ } else {
+ txt = txt + "\u00a0";
+ }
+ txt = txt + "</td></tr>";
+ $("#pluginInlineDetails > table > tbody").append(txt);
+ }
+}
+
+function renderComponents(data) {
+ $(document).ready(function(){
+ renderView( ["Id", "Name", "Status", "Actions"],
+ "<div class='button'><button class='reloadButton' type='button' name='reload'>Reload</button></div>");
+ renderData(data);
+
+ $(".reloadButton").click(loadData);
+
+ var extractMethod = function(node) {
+ var link = node.getElementsByTagName("a");
+ if ( link && link.length == 1 ) {
+ return link[0].innerHTML;
+ }
+ return node.innerHTML;
+ };
+ $("#plugin_table").tablesorter({
+ headers: {
+ 0: { sorter:"digit"},
+ 3: { sorter: false }
+ },
+ sortList: [[1,0]],
+ textExtraction:extractMethod
+ });
+ });
+}
+
diff --git a/webconsole/src/main/resources/res/ui/datatable.js b/webconsole/src/main/resources/res/ui/datatable.js
deleted file mode 100644
index 9158026..0000000
--- a/webconsole/src/main/resources/res/ui/datatable.js
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-function renderDataTable( /* Array of Data Objects */ components )
-{
- // number of actions plus 3 -- id, name and state
- var columns = components.numActions + 3;
-
- header( columns );
-
- if (components.error)
- {
- error( columns, components.error );
- }
- else
- {
- data ( components.data );
- }
-
- footer( columns );
-}
-
-
-function header( /* int */ columns )
-{
- document.write( "<table class='content' cellpadding='0' cellspacing='0' width='100%'>" );
-
- document.write( "<tr class='content'>" );
- document.write( "<td colspan='" + columns + "' class='content'> </th>" );
- document.write( "</tr>" );
-
- document.write( "<tr class='content'>" );
- document.write( "<th class='content'>ID</th>" );
- document.write( "<th class='content' width='100%'>Name</th>" );
- document.write( "<th class='content'>Status</th>" );
- document.write( "<th class='content' colspan='" + (columns - 3) + "'>Actions</th>" );
- document.write( "</tr>" );
-
-}
-
-
-function error( /* int */ columns, /* String */ message )
-{
- document.write( "<tr class='content'>" );
- document.write( "<td class='content'> </td>" );
- document.write( "<td class='content' colspan='" + (columns - 1) + "'>" + message + "</td>" );
- document.write( "</tr>" );
-}
-
-
-function data( /* Array of Object */ dataArray )
-{
- // render components
- if (dataArray.length == 1)
- {
- entry( dataArray[0], true );
- }
- else {
- for ( var idx in dataArray )
- {
- entry( dataArray[idx] );
- }
- }
-}
-
-
-function footer( /* int */ columns )
-{
- document.write( "<tr class='content'>" );
- document.write( "<td colspan='" + columns + "' class='content'> </th>" );
- document.write( "</tr>" );
-
- document.write( "</table>" );
-}
-
-
-function entry( /* Object */ dataEntry, /* boolean */ singleEntry )
-{
- var trElement = tr( null, { id: "entry" + dataEntry.id } );
- entryInternal( trElement, dataEntry, singleEntry );
- document.write( serialize( trElement ) );
-
- // dataEntry detailed properties
- trElement = tr( null, { id: "entry" + dataEntry.id + "_details" } );
- if (dataEntry.props)
- {
- getDataEntryDetails( trElement, dataEntry.props );
- }
- document.write( serialize( trElement ) );
-}
-
-
-function entryInternal( /* Element */ parent, /* Object */ dataEntry, /* boolean */ singleEntry )
-{
-
- var id = dataEntry.id;
- var name = dataEntry.name;
- var state = dataEntry.state;
- var icon = singleEntry ? "left" : (dataEntry.props ? "down" : "right");
- var event = singleEntry ? "history.back()" : "showDataEntryDetails(" + id + ")";
-
- parent.appendChild( td( "content right", null, [ text( id ) ] ) );
-
- parent.appendChild( td( "content", null, [
- createElement( "img", null, {
- src: appRoot + "/res/imgs/" + icon + ".gif",
- onClick: event,
- id: "entry" + id + "_inline"
- } ),
- text( "\u00a0" ),
- createElement( "a", null, {
- href: pluginRoot + "/" + id
- }, [ text( name ) ]
- )]
- )
- );
-
- parent.appendChild( td( "content center", null, [ text( state ) ] ) );
-
- for ( var aidx in dataEntry.actions )
- {
- var action = dataEntry.actions[aidx];
- parent.appendChild( actionButton( action.enabled, id, action.link, action.name, action.title ) );
- }
-}
-
-
-/* Element */ function actionButton( /* boolean */ enabled, /* long */ id, /* String */ op, /* String */ opLabel, /* String */ title )
-{
- var buttonTd = td( "content", { align: "right" } );
- if ( op )
- {
- var input;
- if ( title ) {
- input = createElement( "input", null, {
- type: 'image',
- alt: opLabel,
- src: imgRoot + '/bundle_' + title + '.gif',
- onClick: 'changeDataEntryState(' + id + ', "' + op + '");'
- });
-
- } else {
- var input = createElement( "input", "submit", {
- type: 'button',
- value: opLabel,
- onClick: 'changeDataEntryState(' + id + ', "' + op + '");'
- });
- }
- if (!enabled)
- {
- input.setAttribute( "disabled", true );
- }
- buttonTd.appendChild( input );
- }
- else
- {
- addText( buttonTd, "\u00a0" );
- }
-
- return buttonTd;
-}
-
-
-function getDataEntryDetails( /* Element */ parent, /* Array of Object */ details )
-{
- parent.appendChild( addText( td( "content"), "\u00a0" ) );
-
- var tdEl = td( "content", { colspan: 4 } );
- parent.appendChild( tdEl );
-
- var tableEl = createElement( "table", null, { border: 0 } );
- tdEl.appendChild( tableEl );
-
- var tbody = createElement( "tbody" );
- tableEl.appendChild( tbody );
- for (var idx in details)
- {
- var prop = details[idx];
-
-
- var trEl = tr();
- trEl.appendChild( addText( td( "aligntop", { noWrap: true } ), prop.key ) );
-
- var proptd = td( "aligntop" );
- trEl.appendChild( proptd );
-
- if (prop.value)
- {
- var values = new String( prop.value ).split( "<br />" );
- for (var i=0; i < values.length; i++)
- {
- if (i > 0) { proptd.appendChild( createElement( "br" ) ); }
-
- var span;
- if (values[i].substring(0, 2) == "!!") {
- span = createElement( "span", null, { style: { color: "red" } } );
- proptd.appendChild( span );
- } else {
- span = proptd;
- }
-
- addText( span, values[i] );
- }
- }
- else
- {
- addText( proptd, "\u00a0" );
- }
-
- tbody.appendChild( trEl );
- }
- }
-
-
-function showDetails(bundleId)
-{
- var span = document.getElementById('bundle' + bundleId + '_details');
-}
-
-
-function showDataEntryDetails( id )
-{
- var span = document.getElementById( 'entry' + id + '_details' );
- if (span)
- {
- if (span.firstChild)
- {
- clearChildren( span );
- newLinkValue( id, appRoot + "/res/imgs/right.gif" );
- }
- else
- {
- sendRequest( 'POST', pluginRoot + '/' + id, displayDataEntryDetails );
- newLinkValue( id, appRoot + "/res/imgs/down.gif" );
- }
- }
-}
-
-
-function newLinkValue( /* long */ id, /* String */ newLinkValue )
-{
-
- var link = document.getElementById( "entry" + id + "_inline" );
- if (link)
- {
- link.src = newLinkValue;
- }
-}
-
-
-function displayDataEntryDetails( obj )
-{
- var span = document.getElementById('entry' + obj.id + '_details');
- if (span)
- {
- clearChildren( span );
- getDataEntryDetails( span, obj.props );
- }
-
-}
-
-
-function changeDataEntryState(/* long */ id, /* String */ action)
-{
- var parm = pluginRoot + "/" + id + "?action=" + action;
- sendRequest('POST', parm, dataEntryStateChanged);
-}
-
-
-function dataEntryStateChanged(obj)
-{
- if (obj.reload)
- {
- document.location = document.location;
- }
- else
- {
- var id = obj.id;
- if (obj.state)
- {
- // has status, so draw the line
- if (obj.props)
- {
- var span = document.getElementById('entry' + id + '_details');
- if (span && span.firstChild)
- {
- clearChildren( span );
- getDataEntryDetails( span, obj.props );
- }
- else
- {
- obj.props = false;
- }
- }
-
- var span = document.getElementById('entry' + id);
- if (span)
- {
- clearChildren( span );
- entryInternal( span, obj );
- }
- }
- else
- {
- // no status, dataEntry has been removed/uninstalled
- var span = document.getElementById('entry' + id);
- if (span)
- {
- span.parentNode.removeChild(span);
- }
- var span = document.getElementById('entry' + id + '_details');
- if (span)
- {
- span.parentNode.removeChild(span);
- }
- }
- }
-}
-
-
diff --git a/webconsole/src/main/resources/res/ui/events.js b/webconsole/src/main/resources/res/ui/events.js
index b888d88..62764c1 100644
--- a/webconsole/src/main/resources/res/ui/events.js
+++ b/webconsole/src/main/resources/res/ui/events.js
@@ -108,14 +108,14 @@
function renderEvents() {
renderView( ["Received", "Topic", "Properties"],
- ["<button id='reloadButton' type='button' name='reload'>Reload</button>",
- "<button id='clearButton' type='button' name='clear'>Clear List</button>"]);
+ ["<button class='clearButton' type='button' name='clear'>Clear List</button>",
+ "<button class='reloadButton' type='button' name='reload'>Reload</button>"]);
loadData();
$("#events").tablesorter();
- $("#reloadButton").click(loadData);
- $("#clearButton").click(function () {
+ $(".reloadButton").click(loadData);
+ $(".clearButton").click(function () {
$("#events > tbody > tr").remove();
$.post(pluginRoot, { "action":"clear" }, function(data) {
renderData(data);