FELIX-3111 : Separate OBR Plugin
FELIX-3107 : Separate Shell Plugin
FELIX-3099 : Separate Deployment Admin plugin
FELIX-3100 : Separate SCR plugin

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1169777 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/webconsole-plugins/ds/src/main/resources/res/plugin.html b/webconsole-plugins/ds/src/main/resources/res/plugin.html
new file mode 100644
index 0000000..fa0f8c1
--- /dev/null
+++ b/webconsole-plugins/ds/src/main/resources/res/plugin.html
@@ -0,0 +1,67 @@
+<script type="text/javascript" src="${pluginRoot}/res/plugin.js"></script>

+<script type="text/javascript">

+// <![CDATA[

+var drawDetails = ${__drawDetails__};

+var scrData = ${__data__};

+// i18n

+var i18n = {

+	'Bundle'                 : '${scr.prop.bundle}',

+	'Default State'          : '${scr.prop.defstate}',

+	'Activation'             : '${scr.prop.activation}',

+	'Service Type'           : '${scr.serv.type}',

+	'Services'               : '${scr.serv}',

+	'Properties'             : '${scr.prop.properties}',

+	'Implementation Class'   : '${scr.prop.class}',

+	'Component Factory Name' : '${scr.prop.componentfactory}',

+	'Configuration Policy'   : '${scr.prop.configurationpolicy}',

+	stat_no_service          : "${scr.status.no_service}",

+	stat_no_components       : "${scr.status.no_components}",

+	stat_ok                  : "${scr.status.ok}"

+}

+// ]]>

+</script>

+<p class="statline">&nbsp;</p>

+

+

+<div id="scr"> <!-- data available -->

+	<!-- top header -->

+	<form method='post' enctype='multipart/form-data' action="${pluginRoot}">

+		<div class="ui-widget-header ui-corner-top buttonGroup">

+			<button class='reloadButton' type='button' name='reload'>${reload}</button>

+		</div>

+	</form>

+	

+	<table id="plugin_table" class="tablesorter nicetable noauto">

+	<thead>

+		<tr>

+			<th class="col_Id">${id}</th>

+			<th class="col_Name">${scr.title.name}</th>

+			<th class="col_Status">${scr.title.status}</th>

+			<th class="col_Actions">${scr.title.actions}</th>

+		</tr>

+	</thead>

+	<tbody>

+		<tr>

+			<td>&nbsp;</td> <!-- id -->

+			<td> <!-- name with arrow -->

+				<div class="bIcon ui-icon ui-icon-triangle-1-e" style="float:left" title="${scr.details.tip}">&nbsp;</div>

+			</td> 

+			<td>&nbsp;</td> <!-- status -->

+			<td>

+				<ul class="icons">

+					<li class="dynhover ui-helper-hidden" title="${scr.action.enable}"><span class="ui-icon ui-icon-play">&nbsp;</span></li>

+					<li class="dynhover ui-helper-hidden" title="${scr.action.disable}"><span class="ui-icon ui-icon-stop">&nbsp;</span></li>

+					<li class="dynhover ui-helper-hidden" title="${scr.action.configure}"><span class="ui-icon ui-icon-wrench">&nbsp;</span></li>

+				</ul>

+			</td>

+		</tr>

+	</tbody>

+	</table>

+</div> <!-- end data available -->

+

+<!-- bottom header -->

+<form method='post' enctype='multipart/form-data' action="${pluginRoot}">

+	<div class="ui-widget-header ui-corner-bottom buttonGroup">

+		<button class='reloadButton' type='button' name='reload'>${reload}</button>

+	</div>

+</form>

diff --git a/webconsole-plugins/ds/src/main/resources/res/plugin.js b/webconsole-plugins/ds/src/main/resources/res/plugin.js
new file mode 100644
index 0000000..d1fa357
--- /dev/null
+++ b/webconsole-plugins/ds/src/main/resources/res/plugin.js
@@ -0,0 +1,183 @@
+/*
+ * 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 renderData( eventData )  {
+	switch(eventData.status) {
+		case -1: // no event admin
+			$('.statline').html(i18n.stat_no_service);
+			$('#scr').addClass('ui-helper-hidden');
+			break;
+		case  0: // no components
+			$('.statline').html(i18n.stat_no_components);
+			$('#scr').addClass('ui-helper-hidden');
+			break;
+		default:
+			$('.statline').html(i18n.stat_ok.msgFormat(eventData.status));
+			$('#scr').removeClass('ui-helper-hidden');
+
+			tableBody.empty();
+			for ( var idx in eventData.data ) {
+				entry( eventData.data[idx] );
+			}
+			if ( drawDetails ) renderDetails(eventData);
+			initStaticWidgets();
+	}
+}
+
+function getEntryId(/* Object */ dataEntry) {
+    var id = dataEntry.id;
+    if (id < 0) {
+        id = dataEntry.name;
+        if (dataEntry.pid) {
+            id += '/' + dataEntry.pid;
+        }
+    }
+    return id;
+}
+
+function entry( /* Object */ dataEntry ) {
+	var idPath = getEntryId(dataEntry);
+	var id = idPath.replace(/[./-]/g, '_');
+	var name = dataEntry.name;
+	var _ = tableEntryTemplate.clone().appendTo(tableBody).attr('id', 'entry' + id);
+
+	_.find('.bIcon').attr('id', 'img' + id).click(function() {
+		showDetails(idPath);
+	}).after(drawDetails ? name : ('<a href="' + pluginRoot + '/' + idPath + '">' + name + '</a>'));
+
+	_.find('td:eq(0)').text( dataEntry.id );
+	_.find('td:eq(2)').text( dataEntry.state );
+
+	// setup buttons
+	if ( dataEntry.stateRaw == 1 || dataEntry.stateRaw == 1024 ) { // disabled or disabling
+		_.find('li:eq(0)').removeClass('ui-helper-hidden').click(function() { changeDataEntryState(idPath, 'enable') });
+	} else {
+		_.find('li:eq(1)').removeClass('ui-helper-hidden').click(function() { changeDataEntryState(idPath, 'disable') });
+	}
+	if ( dataEntry.configurable ) _.find('li:eq(2)').removeClass('ui-helper-hidden').click(function() { // configure
+		changeDataEntryState(dataEntry.pid, 'configure');
+	});	
+}
+
+function changeDataEntryState(/* long */ id, /* String */ action) {
+	if ( action == 'configure') {
+		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 hideDetails( id ) {
+	var __test__ = $('#img' + id);
+	$('#img' + id).each(function() {
+		$('#pluginInlineDetails').remove();
+		$(this).
+			removeClass('ui-icon-triangle-1-w').//left
+			removeClass('ui-icon-triangle-1-s').//down
+			addClass('ui-icon-triangle-1-e').//right
+		    attr('title', 'Details').
+			unbind('click').click(function() {showDetails(id)});
+	});
+}
+
+function renderDetails( data ) {
+	data = data.data[0];
+	var id = getEntryId(data).replace(/[./-]/g, '_');
+	$('#pluginInlineDetails').remove();
+	var __test__ = $('#entry' + id);
+	$('#entry' + id + ' > td').eq(1).append('<div id="pluginInlineDetails"/>');
+	$('#img' + id).each(function() {
+		if ( drawDetails ) {
+			var ref = window.location.pathname;
+			ref = ref.substring(0, ref.lastIndexOf('/'));
+			$(this).
+				removeClass('ui-icon-triangle-1-e').//right
+				removeClass('ui-icon-triangle-1-s').//down
+				addClass('ui-icon-triangle-1-w').//left
+				attr('title', 'Back').
+				unbind('click').click(function() {window.location = ref});
+		} else {
+			$(this).
+				removeClass('ui-icon-triangle-1-w').//left
+				removeClass('ui-icon-triangle-1-e').//right
+				addClass('ui-icon-triangle-1-s').//down
+				attr('title', 'Hide Details').
+				unbind('click').click(function() {hideDetails(id)});
+		}
+	});
+	$('#pluginInlineDetails').append('<table border="0"><tbody></tbody></table>');
+	var details = data.props;
+	for (var idx in details) {
+		var prop = details[idx];
+		var key = i18n[prop.key] ? i18n[prop.key] : prop.key; // i18n
+
+		var txt = '<tr><td class="aligntop" noWrap="true" style="border:0px none">' + 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);
+	}
+}
+
+var tableBody = false;
+var tableEntryTemplate = false;
+var pluginTable = false;
+
+$(document).ready(function(){
+	pluginTable = $('#plugin_table');
+	tableBody = pluginTable.find('tbody');
+	tableEntryTemplate = tableBody.find('tr').clone();
+
+	renderData(scrData);
+
+	$('.reloadButton').click(document.location.reload);
+
+	pluginTable.tablesorter({
+		headers: {
+			0: { sorter:'digit'},
+			3: { sorter: false }
+		},
+		sortList: [[1,0]],
+		textExtraction:mixedLinksExtraction
+	});
+});
+