Implemented FELIX-2202
Update Events plugin to JQuery UI
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@923242 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/webconsole-plugins/event/pom.xml b/webconsole-plugins/event/pom.xml
index bfa5dc9..7acad96 100644
--- a/webconsole-plugins/event/pom.xml
+++ b/webconsole-plugins/event/pom.xml
@@ -44,6 +44,23 @@
<build>
<plugins>
+ <!-- translate UTF-8 encoded properties files to ISO-8859-1 -->
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>native2ascii-maven-plugin</artifactId>
+ <version>1.0-alpha-1</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>native2ascii</goal>
+ </goals>
+ <configuration>
+ <encoding>UTF-8</encoding>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
diff --git a/webconsole-plugins/event/src/main/java/org/apache/felix/webconsole/plugins/event/internal/Activator.java b/webconsole-plugins/event/src/main/java/org/apache/felix/webconsole/plugins/event/internal/Activator.java
index 1f34924..704c824 100644
--- a/webconsole-plugins/event/src/main/java/org/apache/felix/webconsole/plugins/event/internal/Activator.java
+++ b/webconsole-plugins/event/src/main/java/org/apache/felix/webconsole/plugins/event/internal/Activator.java
@@ -59,7 +59,7 @@
props.put( Constants.SERVICE_DESCRIPTION, "Event Plugin for the Apache Felix Web Console" );
props.put( Constants.SERVICE_VENDOR, "The Apache Software Foundation" );
props.put( "felix.webconsole.label", "events");
- props.put( "felix.webconsole.title", "Events");
+ props.put( "felix.webconsole.title", "%plugin.events.title");
props.put( "felix.webconsole.css", "/events/res/ui/events.css");
this.pluginRegistration = context.registerService(Servlet.class.getName(),
plugin,
diff --git a/webconsole-plugins/event/src/main/java/org/apache/felix/webconsole/plugins/event/internal/PluginServlet.java b/webconsole-plugins/event/src/main/java/org/apache/felix/webconsole/plugins/event/internal/PluginServlet.java
index ebdf884..1a4e141 100644
--- a/webconsole-plugins/event/src/main/java/org/apache/felix/webconsole/plugins/event/internal/PluginServlet.java
+++ b/webconsole-plugins/event/src/main/java/org/apache/felix/webconsole/plugins/event/internal/PluginServlet.java
@@ -17,7 +17,9 @@
package org.apache.felix.webconsole.plugins.event.internal;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.io.PrintWriter;
import java.net.URL;
import java.util.*;
@@ -43,10 +45,55 @@
/** Is the config admin available? */
private volatile boolean configAdminAvailable = false;
+
+ private final String TEMPLATE;
public PluginServlet()
{
this.collector = new EventCollector(null);
+ TEMPLATE = readTemplateFile(getClass(), "/res/events.html");
+ }
+
+ private final String readTemplateFile(final Class clazz, final String templateFile)
+ {
+ InputStream templateStream = getClass().getResourceAsStream(templateFile);
+ if (templateStream != null)
+ {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ byte[] data = new byte[1024];
+ try
+ {
+ int len = 0;
+ while ((len = templateStream.read(data)) > 0)
+ {
+ baos.write(data, 0, len);
+ }
+ return baos.toString("UTF-8");
+ }
+ catch (IOException e)
+ {
+ // don't use new Exception(message, cause) because cause is 1.4+
+ throw new RuntimeException("readTemplateFile: Error loading "
+ + templateFile + ": " + e);
+ }
+ finally
+ {
+ try
+ {
+ templateStream.close();
+ }
+ catch (IOException e)
+ {
+ /* ignore */
+ }
+
+ }
+ }
+
+ // template file does not exist, return an empty string
+ log("readTemplateFile: File '" + templateFile + "' not found through class "
+ + clazz);
+ return "";
}
/**
@@ -154,17 +201,9 @@
throws ServletException, IOException
{
final PrintWriter pw = response.getWriter();
-
- final String appRoot = ( String ) request.getAttribute( "felix.webconsole.appRoot" );
- pw.println( "<script src='" + appRoot + "/events/res/ui/" + "events.js" + "' language='JavaScript'></script>" );
-
- pw.println( "<div id='plugin_content'/>");
-
- pw.println( "<script type='text/javascript'>" );
- pw.println( "// <![CDATA[" );
- pw.println( "renderEvents( );" );
- pw.println( "// ]]>" );
- pw.println( "</script>" );
+ //final String appRoot = ( String ) request.getAttribute( "felix.webconsole.appRoot" );
+ //pw.println( "<script src='" + appRoot + "/events/res/ui/" + "events.js" + "' type='text/javascript'></script>" );
+ pw.print(TEMPLATE);
}
public URL getResource(String path)
diff --git a/webconsole-plugins/event/src/main/native2ascii/OSGI-INF/l10n/bundle_bg.properties b/webconsole-plugins/event/src/main/native2ascii/OSGI-INF/l10n/bundle_bg.properties
new file mode 100644
index 0000000..9679953
--- /dev/null
+++ b/webconsole-plugins/event/src/main/native2ascii/OSGI-INF/l10n/bundle_bg.properties
@@ -0,0 +1,40 @@
+#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.
+
+#
+# Web Console strings for reference all strings here are commented.
+# This file may be used to produce a translation of the strings
+#
+# Note that properties files are ISO-8859-1 encoded. To provide translations
+# for languages requiring different character encodings, you may use the
+# native2ascii Maven Plugin from http://mojo.codehaus.org/native2ascii-maven-plugin/
+# to translate the natively encoded files to ISO-8859-1 during bundle build
+#
+# Translations requiring non-ISO-8859-1 encoding are placed in the
+# src/main/native2ascii/OSGI-INF/l10n folder and are converted using said
+# plugin while building the bundle
+#
+
+# buttons on top
+displayTimeline=??????? ????????
+displayList=??????
+clear=??????????
+
+# table headers
+received=???????
+topic=????
+properties=????????
+
+plugin.events.title=???????
diff --git a/webconsole-plugins/event/src/main/resources/OSGI-INF/l10n/bundle.properties b/webconsole-plugins/event/src/main/resources/OSGI-INF/l10n/bundle.properties
new file mode 100644
index 0000000..9402ce8
--- /dev/null
+++ b/webconsole-plugins/event/src/main/resources/OSGI-INF/l10n/bundle.properties
@@ -0,0 +1,40 @@
+#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.
+
+#
+# Web Console strings for reference all strings here are commented.
+# This file may be used to produce a translation of the strings
+#
+# Note that properties files are ISO-8859-1 encoded. To provide translations
+# for languages requiring different character encodings, you may use the
+# native2ascii Maven Plugin from http://mojo.codehaus.org/native2ascii-maven-plugin/
+# to translate the natively encoded files to ISO-8859-1 during bundle build
+#
+# Translations requiring non-ISO-8859-1 encoding are placed in the
+# src/main/native2ascii/OSGI-INF/l10n folder and are converted using said
+# plugin while building the bundle
+#
+
+# buttons on top
+displayTimeline=Timeline
+displayList=List
+clear=Clear Events
+
+# table headers
+received=Received
+topic=Event Topic
+properties=Event Properties
+
+plugin.events.title=Events
\ No newline at end of file
diff --git a/webconsole-plugins/event/src/main/resources/res/events.html b/webconsole-plugins/event/src/main/resources/res/events.html
new file mode 100644
index 0000000..e721a3d
--- /dev/null
+++ b/webconsole-plugins/event/src/main/resources/res/events.html
@@ -0,0 +1,37 @@
+<script type="text/javascript" src="${pluginRoot}/res/ui/events.js"></script>
+<script type="text/javascript">
+var i18n = {
+ displayTimeline: '${displayTimeline}',
+ displayList : '${displayList}'
+}
+</script>
+
+<!-- status line -->
+<p class="statline"> </p>
+
+<!-- table caption -->
+<div class="ui-widget-header ui-corner-top buttonGroup">
+ <button id="switch">${displayTimeline}</button>
+ <button id="clear">${clear}</button>
+ <button id="reload">${reload}</button>
+</div>
+
+<!-- table -->
+<table id="eventsTable" class="tablesorter nicetable">
+ <thead>
+ <tr>
+ <th class="col_Received">${received}</th>
+ <th class="col_Topic">${topic}</th>
+ <th class="col_Props">${properties}</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td> </td>
+ <td> </td>
+ <td> </td>
+ </tr>
+ </tbody>
+</table>
+
+<div id="timeline" class="ui-helper-hidden"> </div>
diff --git a/webconsole-plugins/event/src/main/resources/res/ui/events.css b/webconsole-plugins/event/src/main/resources/res/ui/events.css
index ae0f3e8..68833ac 100644
--- a/webconsole-plugins/event/src/main/resources/res/ui/events.css
+++ b/webconsole-plugins/event/src/main/resources/res/ui/events.css
@@ -14,15 +14,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-.eventservice {
- background-color: #ADFF2F;
-}
-.eventbundle {
- background-color: #FFCACD;
-}
-.eventframework {
- background-color: #DCDCDC;
-}
-.eventconfig {
- background-color: #FFD700;
-}
\ No newline at end of file
+#timeline { width: 100%; overflow-x: scroll }
+.event { overflow:visible; white-space:nowrap }
+.eventservice { background-color: #ADFF2F }
+.eventbundle { background-color: #FFCACD }
+.eventconfig { background-color: #FFD700 }
+.eventframework { background-color: #DCDCDC }
+
+.propName { padding: 0 4px 0 0 }
+.propVal { padding: 0 0 0 4px }
\ No newline at end of file
diff --git a/webconsole-plugins/event/src/main/resources/res/ui/events.js b/webconsole-plugins/event/src/main/resources/res/ui/events.js
index acb3951..7a6d1a0 100644
--- a/webconsole-plugins/event/src/main/resources/res/ui/events.js
+++ b/webconsole-plugins/event/src/main/resources/res/ui/events.js
@@ -14,92 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-var view = 0;
-
-function renderStatusLine() {
- $("#plugin_content").append( "<div class='fullwidth'><div class='statusline'/></div>" );
-}
-
-function renderView( /* Array of String */ columns, /* 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 ( view == 1 ) {
- $("#timeline").remove();
- $("div.table").append( "<div id='timeline' width='100%'></div>" );
- for ( var idx in eventData.data ) {
- entryTimeline( eventData.data[idx] );
- }
- }
-}
-
-function entry( /* Object */ dataEntry ) {
- var trElement = tr( null, { id: "entry" + dataEntry.id } );
- entryInternal( trElement, dataEntry );
- $("#plugin_table > tbody").append(trElement);
-}
-
-function entryTimeline( /* Object */ dataEntry ) {
- var txt = "<div class='event" + dataEntry.category + "' style='overflow:visible;white-space:nowrap;width:" + dataEntry.width + "%;'>";
- txt = txt + "<b>" + dataEntry.offset + "</b> <b>" + dataEntry.topic + "</b>";
- if ( dataEntry.info ) {
- txt = txt + " : " + dataEntry.info;
- }
- txt = txt + "</div>";
- $("#timeline").prepend(txt);
-}
-
-function entryInternal( /* Element */ parent, /* Object */ dataEntry ) {
- var id = dataEntry.id;
- var topic = dataEntry.topic;
- var properties = dataEntry.properties;
-
- parent.appendChild( td( null, null, [ text( printDate(dataEntry.received) ) ] ) );
- parent.appendChild( td( null, null, [ text( topic ) ] ) );
-
- var propE;
- if ( dataEntry.info ) {
- propE = text(dataEntry.info);
- } else {
- var tableE = createElement("table");
- var bodyE = createElement("tbody");
- tableE.appendChild(bodyE);
-
- for( var p in dataEntry.properties ) {
- var c1 = td(null, null, [text(p)]);
- $(c1).css("border", "0px none");
- $(c1).css("padding", "0 4px 0 0");
- var c2 = td(null, null, [text(dataEntry.properties[p])]);
- $(c2).css("border", "0px none");
- $(c2).css("padding", "0 0 0 4px");
- bodyE.appendChild(tr(null, null, [ c1, c2 ]));
- }
- propE = tableE;
- }
-
- parent.appendChild( td( null, null, [propE] ) );
-}
+var eventsTable = false;
/* displays a date in the user's local timezone */
function printDate(time) {
@@ -107,43 +22,77 @@
return date.toLocaleString();
}
-function loadData() {
- $.get(pluginRoot + "/data.json", null, function(data) {
- renderData(data);
- }, "json");
+function renderData( eventData ) {
+ $('.statline').html(eventData.status); // FIXME:
+
+ // append table view
+ eventsBody.empty();
+ for ( var i in eventData.data ) entry( eventData.data[i] );
+ eventsTable.trigger('update').trigger('applyWidgets');
+
+ // append timeline view
+ timeline.empty();
+ for ( var i in eventData.data ) entryTimeline( eventData.data[i] );
}
-function switchView() {
- if ( view == 0 ) {
- view = 1;
- $("#plugin_table").hide();
- $(".switchButton").empty();
- $(".switchButton").append("List");
- loadData();
- } else {
- view = 0;
- $("#timeline").remove();
- $("#plugin_table").show();
- $(".switchButton").empty();
- $(".switchButton").append("Timeline");
- }
+
+function entryTimeline( /* Object */ dataEntry ) {
+ var txt = '<div class="event event' + dataEntry.category + '" style="width:' + dataEntry.width + '%">' +
+ '<b>' + dataEntry.offset + '</b> <b>' + dataEntry.topic + '</b>';
+ if ( dataEntry.info ) txt += ' : ' + dataEntry.info;
+ txt += '</div>';
+ timeline.prepend(txt);
}
-function renderEvents() {
- $(document).ready(function(){
- renderView( ["Received", "Topic", "Properties"],
- "<button class='switchButton' type='button' name='switch'>Timeline</button>" +
- "<button class='clearButton' type='button' name='clear'>Clear List</button>" +
- "<button class='reloadButton' type='button' name='reload'>Reload</button>");
- loadData();
-
- $("#plugin_table").tablesorter();
- $(".reloadButton").click(loadData);
- $(".switchButton").click(switchView);
- $(".clearButton").click(function () {
- $("#plugin_table > tbody > tr").remove();
- $.post(pluginRoot, { "action":"clear" }, function(data) {
- renderData(data);
- }, "json");
- });
+
+function entry( /* Object */ dataEntry ) {
+ var properties = dataEntry.properties;
+
+ var propE;
+ if ( dataEntry.info ) {
+ propE = text(dataEntry.info);
+ } else {
+ var propE = createElement('table', 'nicetable');
+ var bodyE = createElement('tbody');
+ propE.appendChild(bodyE);
+
+ for( var p in dataEntry.properties ) {
+ bodyE.appendChild(tr(null, null, [
+ td(null, 'propName', [text(p)]),
+ td(null, 'propVal', [text(dataEntry.properties[p])])
+ ]));
+ }
+ }
+
+ $(tr( null, { id: 'entry' + dataEntry.id }, [
+ td( null, null, [ text( printDate(dataEntry.received) ) ] ),
+ td( null, null, [ text( dataEntry.topic ) ] ),
+ propE
+ ])).appendTo(eventsBody);
+}
+
+var timeline = false;
+$(document).ready(function(){
+ eventsTable = $('#eventsTable');
+ eventsBody = eventsTable.find('tbody');
+ timeline = $('#timeline');
+
+ $('#clear').click(function () {
+ $.post(pluginRoot, { 'action':'clear' }, renderData, 'json');
});
-}
+ $('#switch').click(function() {
+ var timelineHidden = timeline.hasClass('ui-helper-hidden');
+ if (timelineHidden) {
+ $(this).text(i18n.displayList);
+ timeline.removeClass('ui-helper-hidden');
+ eventsTable.addClass('ui-helper-hidden');
+ } else {
+ $(this).text(i18n.displayTimeline);
+ timeline.addClass('ui-helper-hidden');
+ eventsTable.removeClass('ui-helper-hidden');
+ }
+ });
+ $('#reload').click(function() {
+ $.get(pluginRoot + '/data.json', null, renderData, 'json');
+ //renderData(eventData);
+ }).click();
+});