FELIX-569 : Improve Configuration Page - Apply patch from Valentin Valchev
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@921443 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/webconsole/src/main/resources/OSGI-INF/l10n/bundle.properties b/webconsole/src/main/resources/OSGI-INF/l10n/bundle.properties
index 3e1eba6..c431bf1 100644
--- a/webconsole/src/main/resources/OSGI-INF/l10n/bundle.properties
+++ b/webconsole/src/main/resources/OSGI-INF/l10n/bundle.properties
@@ -170,7 +170,10 @@
config.del.config=Configuration:
config.del.bundle=Bundle:
config.unbind.ask=Are you sure to unbind this configuration ?
-
+config.factories.title=Factory Configurations
+config.configurations.title=Configurations
+config.create.tip=Create new factory configuration
+config.edit.tip=Edit the configuration values
# License plugin
license.status.ok=The following bundles contains license files.
diff --git a/webconsole/src/main/resources/res/ui/config.css b/webconsole/src/main/resources/res/ui/config.css
index 8f96a81..55e62f7 100644
--- a/webconsole/src/main/resources/res/ui/config.css
+++ b/webconsole/src/main/resources/res/ui/config.css
@@ -27,6 +27,8 @@
margin:0;
padding:0
}
-.multiselect {
- display: block;
-}
+.multiselect { display: block }
+.col_Actions { width: 6em !important }
+.pointer { cursor: pointer }
+#editor, div.ui-dialog-buttonpane button { font-size: 50% }
+#factoryTableCaption { margin-top: 1.5em }
diff --git a/webconsole/src/main/resources/res/ui/config.js b/webconsole/src/main/resources/res/ui/config.js
index 01d2624..7e96f45 100644
--- a/webconsole/src/main/resources/res/ui/config.js
+++ b/webconsole/src/main/resources/res/ui/config.js
@@ -14,58 +14,40 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+// tables container - will get hidden, when no config service available
+var configContent = false;
+
+// config table list
+var configTable = false;
+var configBody = false;
+var configRow = false;
+
+// factories table list
+var factoryTable = false;
+var factoryBody = false;
+var factoryRow = false;
-function configure() {
- var select = document.getElementById('configSelection_pid');
- var pid = select.options[select.selectedIndex].value;
- var parm = pluginRoot + '/' + pid;
- $.post(parm, null, displayConfigForm, "json");
-}
+// editor dialog
+var editor = false;
-
-function create() {
- var select = document.getElementById('configSelection_factory');
- var pid = select.options[select.selectedIndex].value;
- var parm = pluginRoot + '/' + pid + '?create=true';
- $.post(parm, null, displayConfigForm, "json");
+function configure(pid, create) {
+ var uri = pluginRoot + '/' + pid;
+ $.post(create ? uri + '?create=1' : uri, null, displayConfigForm, 'json');
}
function displayConfigForm(obj) {
- var span1 = document.getElementById('configField');
- var span2 = document.getElementById('factoryField');
- if (!span1 && !span2) {
- return;
- }
-
- var parent = span1 ? span1.parentNode : span2.parentNode;
-
- clearChildren( parent );
-
- if (span1) {
- parent.appendChild( span1 );
- }
- if (span2) {
- parent.appendChild( span2 );
- }
-
- var trEl = tr( null );
- var tdEl = createElement( "th", null, { colSpan: "2" } );
- addText( tdEl, obj.title );
- trEl.appendChild( tdEl );
- parent.appendChild( trEl );
+ var parent = document.getElementById('editorTable');
+ clearChildren( parent )
- trEl = tr( );
+ var trEl = tr( );
parent.appendChild( trEl );
- tdEl = td( );
- addText( tdEl, "\u00a0" );
- trEl.appendChild( tdEl );
-
- tdEl = td( );
+ var tdEl = td( null, { colSpan: "2" } );
trEl.appendChild( tdEl );
var formEl = createElement( "form", null, {
+ id : "editorForm",
method: "POST",
action: pluginRoot + "/" + obj.pid
});
@@ -133,28 +115,9 @@
{
printForm(bodyEl, obj);
}
-
- trEl = tr( );
- bodyEl.appendChild( trEl );
-
- tdEl = td( );
- addText( tdEl, "\u00a0" );
- trEl.appendChild( tdEl );
-
- tdEl = td( );
- trEl.appendChild( tdEl );
-
- // define this TD as innerHTML otherwise the onClick event handler
- // of the Delete button is not accepted by IE6 (!)...
- var innerHTML = '<input type="submit" name="submit" value="'+i18n.save+'" />';
- innerHTML += ' ';
- innerHTML += '<input type="reset" name="reset" value="'+i18n.reset+'" />';
- innerHTML += ' ';
- innerHTML += '<input type="submit" name="delete" value="'+i18n.del+'" onClick="return confirmDelete(\'' + obj.pid + '\', \'' + obj.bundleLocation + '\');"/>';
- tdEl.innerHTML = innerHTML;
printConfigurationInfo(parent, obj);
- initStaticWidgets($(parent));
+ initStaticWidgets(editor.attr('__pid', obj.pid).dialog('option', 'title', obj.title).dialog('open'));
}
function printTextArea(/* Element */ parent, props )
@@ -291,29 +254,7 @@
])
])
);
-
- if (obj.bundleLocation)
- {
- var form = createElement( "form", null, {
- method: "POST",
- action: pluginRoot + "/" + obj.pid
- });
- // define this form contents as innerHTML otherwise the onClick
- // event handler of the Unbind button is not accepted by IE6 (!)...
- var formInner = '<input type="hidden" name="unbind" value="true"/>';
- formInner += '<input type="submit" name="submit" value="'+i18n.unbind_btn+'" class="ui-state-default ui-corner-all" title="'+i18n.unbind_tip+'" onClick="return confirmUnbind(\'' + obj.pid + '\', \'' + obj.bundleLocation + '\');"/>';
- form.innerHTML = formInner;
-
- parent.appendChild( tr( null, null, [
- td( null, null, [
- text( " " )
- ]),
- td( null, null, [ form ] )
- ])
- );
- }
- //$(form).ready(initStaticWidgets);
}
@@ -475,7 +416,7 @@
function confirmDelete(/* String */ title, /* String */ location)
{
- return configConfirm(i18n.unbind_ask, title, location);
+ return configConfirm(i18n.del_ask, title, location);
}
function confirmUnbind(/* String */ title, /* String */ location)
@@ -483,26 +424,95 @@
return configConfirm(i18n.unbind_ask, title, location);
}
-function addOption(list, target)
-{
- var html = "";
- for (i in list) {
- var sel = list[i].id == selectedPid ? '" selected="selected' : '';
- html += '<option value="' + list[i].id + sel + '">' + list[i].name + '</option>';
- }
- if (html) target.html(html);
+function addConfig(conf) {
+ var tr = configRow.clone().appendTo(configBody);
+ tr.find('td:eq(0)').text(conf.fpid ? conf.fpid : '-'); // fpid
+ tr.find('td:eq(1)').text(conf.name).click(function() { // name & edit
+ configure(conf.id);
+ });
+ tr.find('td:eq(2)').html(conf.bundle ? '<a href="' + pluginRoot + '/../bundles/' + conf.bundle + '">' + conf.bundle_name + '</a>' : '-'); // binding
+
+ // buttons
+ tr.find('li:eq(0)').click(function() { // edit
+ configure(conf.id);
+ });
+ tr.find('li:eq(2)').click(function() { // delete
+ if ( confirmDelete(conf.id, conf.bundle_name) ) {
+ $.post(pluginRoot + '/' + conf.id + '?apply=1&delete=1', null, function() {
+ document.location.href = pluginRoot;
+ }, 'json');
+ }
+ });
+ if (conf.bundle) tr.find('li:eq(1)').click(function() { // unbind
+ if ( confirmUnbind(conf.id, conf.bundle_name) ) {
+ $.post(pluginRoot + '/' + conf.id + '?apply=1&delete=1', null, function() {
+ document.location.href = pluginRoot + '/' + conf.id;
+ }, 'json');
+ }
+ }).removeClass('ui-state-disabled');
}
-var configSelection_pid = false;
-var configSelection_factory = false;
+function addFactoryConfig(conf) {
+ var tr = factoryRow.clone().appendTo(factoryBody);
+ tr.find('td:eq(0)').text(conf.id); // fpid
+ tr.find('td:eq(1)').text(conf.name).click(function() { // name & edit
+ configure(conf.id, true);
+ });
+ // buttons
+ tr.find('li:eq(0)').click(function() { // edit
+ configure(conf.id, true);
+ });
+}
+
$(document).ready(function() {
- configSelection_pid = $('#configSelection_pid');
- configSelection_factory = $('#configSelection_factory');
- $(".statline").html(configData.status ? i18n.stat_ok : i18n.stat_missing);
- $("#config_content").css("display", configData.status ? "block" : "none");
- if (configData.status) {
- addOption(configData.pids, $("#configSelection_pid"));
- addOption(configData.fpids, $("#configSelection_factory"));
+ configContent = $('#configContent');
+ // config table list
+ configTable = configContent.find('table:eq(0)').tablesorter({
+ headers: { 3: { sorter: false } },
+ textExtraction:mixedLinksExtraction
+ });
+ configBody = configTable.find('tbody');
+ configRow = configBody.find('tr').clone();
+
+ // factories table list
+ factoryTable = configContent.find('table:eq(1)').tablesorter({
+ headers: { 2: { sorter: false } }
+ });
+ factoryBody = factoryTable.find('tbody');
+ factoryRow = factoryBody.find('tr').clone();
+
+ // setup button - cannot inline in dialog option because of i18n
+ var _buttons = {};
+ _buttons[i18n.abort] = function() {
+ $(this).dialog('close');
}
- if (selectedPid) configure();
+ _buttons[i18n.reset] = function() {
+ var form = document.getElementById('editorForm');
+ if (form) form.reset();
+ }
+ _buttons[i18n.save] = function() {
+ $.post(pluginRoot + '/' + $(this).attr('__pid') + '?' + $(this).find('form').serialize());
+ $(this).dialog('close');
+ }
+ // prepare editor, but don't open yet!
+ editor = $('#editor').dialog({
+ autoOpen : false,
+ modal : true,
+ width : '90%',
+ closeText: i18n.abort,
+ buttons : _buttons
+ });
+
+ // display the configuration data
+ $(".statline").html(configData.status ? i18n.stat_ok : i18n.stat_missing);
+ if (configData.status) {
+ configBody.empty(); factoryBody.empty();
+
+ for(var i in configData.pids) addConfig(configData.pids[i]);
+ for(var i in configData.fpids) addFactoryConfig(configData.fpids[i]);
+ initStaticWidgets(configContent);
+ } else {
+ configContent.addClass('ui-helper-hidden');
+ }
+ if (selectedPid) configure(selectedPid);
});
\ No newline at end of file
diff --git a/webconsole/src/main/resources/templates/config.html b/webconsole/src/main/resources/templates/config.html
index 6c4b3d2..34629c5 100644
--- a/webconsole/src/main/resources/templates/config.html
+++ b/webconsole/src/main/resources/templates/config.html
@@ -1,4 +1,4 @@
-<script type="text/javascript" src="res/ui/config.js"></script>
+<script type="text/javascript" src="res/ui/config.js"></script>
<script type="text/javascript">
// <![CDATA[
// data
@@ -10,6 +10,7 @@
save : '${save}',
reset : '${reset}',
del : '${delete}',
+ abort : '${abort}',
props_title : '${config.properties}',
props_enter : '${config.properties.enter}', // "Enter Name-Value pairs of configuration properties"
cfg_title : '${config.info.title}', // "Configuration Information"
@@ -22,10 +23,7 @@
del_ask : '${config.del.ask}', // "Are you sure to delete this configuration ?";
del_config : '${config.del.config}', // "Configuration: ";
del_bundle : '${config.del.bundle}', // "Bundle: ";
- unbind_ask : '${config.unbind.ask}', // "Are you sure to unbind this configuration ?"
- 'xx' : '${config.form.properties}',
- 'xx' : '${config.form.properties}',
-
+ unbind_ask : '${config.unbind.ask}' // "Are you sure to unbind this configuration ?"
}
// ]]>
</script>
@@ -33,27 +31,65 @@
<!-- status line -->
<p class="statline"> </p>
-<div id="config_content" >
- <table class="nicetable">
- <tr id="configField">
- <td>Configurations</td>
- <td>
- <select name="pid" id="configSelection_pid" onchange="configure();">
- <option> </option>
- </select>
-
- <button onclick="configure();">Configure</button>
- </td>
- </tr>
- <tr id="factoryField">
- <td>Factory Configurations</td>
- <td>
- <select name="pid" id="configSelection_factory" onchange="create();">
- <option> </option>
- </select>
-
- <button onclick="create();">Create</button>
- </td>
- </tr>
+
+<div id="configContent" >
+ <div id="fPidsSelect" class="ui-widget-header ui-corner-top buttonGroup">
+ ${config.configurations.title}
+ </div>
+ <table class="tablesorter nicetable noauto">
+ <thead>
+ <tr>
+ <th class="col_FPID">Factory PID</th>
+ <th class="col_Name">Name</th>
+ <th class="col_Binding">Bundle</th>
+ <th class="col_Actions" style="width: 7em">Actions</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td> </td>
+ <td class="pointer"> </td>
+ <td> </td>
+ <td>
+ <ul class="icons">
+ <li class="dynhover" title="${config.edit.tip}"><span class="ui-icon ui-icon-pencil"> </span></li>
+ <li class="ui-state-disabled dynhover" title="${config.unbind.tip}"><span class="ui-icon ui-icon-transferthick-e-w"> </span></li>
+ <li class="dynhover" title="${delete}"><span class="ui-icon ui-icon-trash"> </span></li>
+ </ul>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+
+ <div id="factoryTableCaption" class="ui-widget-header ui-corner-top buttonGroup">
+ ${config.factories.title}
+ </div>
+ <table class="tablesorter nicetable noauto">
+ <thead>
+ <tr>
+ <th class="col_FPID">Factory PID</th>
+ <th class="col_Name">Name</th>
+ <th class="col_Actions" style="width: 7em">Actions</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td> </td>
+ <td class="pointer"> </td>
+ <td>
+ <ul class="icons">
+ <li class="dynhover" title="${config.create.tip}"><span class="ui-icon ui-icon-plusthick"> </span></li>
+ </ul>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+
+</div>
+
+<!-- placeholder for property editor -->
+<div id="editor" class="ui-helper-hidden">
+ <table id="editorTable" class="nicetable">
+ <tr><td> </td></tr>
</table>
</div>