summaryrefslogtreecommitdiff
path: root/qpid/java/broker-plugins
diff options
context:
space:
mode:
Diffstat (limited to 'qpid/java/broker-plugins')
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/index.html39
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/ConsoleHelper.js73
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/TimeZoneSelector.js23
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/grid/EnhancedFilter.js2
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/grid/EnhancedFilterTools.js43
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/grid/GridUpdater.js62
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Preferences.js33
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/PreferencesProviderFields.js8
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/UserPreferences.js3
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/logs/LogViewer.js2
10 files changed, 231 insertions, 57 deletions
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/index.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/index.html
index dbb0c111c0..f17e8d8bba 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/index.html
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/index.html
@@ -57,33 +57,24 @@
</script>
<script>
- var qpidHelpLocation = "http://qpid.apache.org/releases/qpid-";
- var qpidHelpURL = null;
- var qpidPreferences = null;
+ var qpidManagementHelper = null;
require([
- "dojo/_base/xhr",
"dojo/parser",
- "qpid/management/Preferences",
"qpid/authorization/checkUser",
+ "qpid/common/ConsoleHelper",
"dijit/layout/BorderContainer",
"dijit/layout/TabContainer",
"dijit/layout/ContentPane",
"dijit/TitlePane",
+ "dijit/Menu",
+ "dijit/MenuItem",
"qpid/management/treeView",
"qpid/management/controller",
"qpid/common/footer"
- ], function(xhr, parser, Preferences, User){
+ ], function(parser, User, ConsoleHelper){
parser.parse();
+ qpidManagementHelper = ConsoleHelper;
User.getUserAndUpdateUI();
- qpidPreferences = new Preferences();
- xhr.get({
- sync: true,
- url: "rest/helper?action=version",
- handleAs: "json"
- }).then(function(qpidVersion) {
- qpidHelpURL = qpidHelpLocation + qpidVersion + "/java-broker/book/index.html";
- });
-
});
</script>
@@ -98,20 +89,10 @@
<div id="authenticatedUserControls" data-dojo-type="dijit.form.DropDownButton" data-dojo-props="iconClass: 'preferencesIcon', style:{'max-width': '100px'}">
<div data-dojo-type="dijit.Menu">
<div data-dojo-type="dijit.MenuItem" data-dojo-props="onClick: function(){window.location='logout';}" >Log out</div>
- <div data-dojo-type="dijit.MenuItem" data-dojo-props="
- iconClass: 'dijitIconFunction',
- onClick: function(){ qpidPreferences.showDialog(); } ">
- Preferences
- </div>
- <!--
- <div data-dojo-type="dijit.MenuItem" data-dojo-props="iconClass: 'dijitIconMail', onClick: function(){ console.log('TODO'); }">
- Contacts
- </div>
- -->
- <div data-dojo-type="dijit.MenuItem" data-dojo-props="iconClass: 'helpIcon', onClick: function(){
- var newWindow = window.open(qpidHelpURL,'QpidHelp','height=600,width=600,scrollbars=1,location=1,resizable=1,status=0,toolbar=0,titlebar=1,menubar=0',true); newWindow.focus(); } ">
- Help
- </div>
+ <div data-dojo-type="dijit.MenuItem"
+ data-dojo-props="iconClass:'dijitIconFunction',onClick: function(){qpidManagementHelper.showPreferencesDialog();}">Preferences</div>
+ <div data-dojo-type="dijit.MenuItem"
+ data-dojo-props="iconClass: 'helpIcon', onClick: function(){qpidManagementHelper.showHelp();}">Help</div>
</div>
</div>
</div>
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/ConsoleHelper.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/ConsoleHelper.js
new file mode 100644
index 0000000000..fdc07f27ca
--- /dev/null
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/ConsoleHelper.js
@@ -0,0 +1,73 @@
+/*
+ *
+ * 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.
+ *
+ */
+define(["dojo/_base/xhr", "dojo/domReady!"], function (xhr) {
+
+ var qpidHelpLocation = "http://qpid.apache.org/releases/qpid-";
+ var preferencesDialog = null;
+ var helpURL = null;
+ var qpidVersion = null;
+
+ return {
+ showPreferencesDialog: function () {
+ if (preferencesDialog == null)
+ {
+ require(["qpid/management/Preferences", "dojo/ready"], function(PreferencesDialog, ready){
+ ready(function(){
+ preferencesDialog = new PreferencesDialog();
+ preferencesDialog.showDialog();
+ });
+ });
+ }
+ else
+ {
+ preferencesDialog.showDialog();
+ }
+ },
+ getVersion: function()
+ {
+ if (!qpidVersion)
+ {
+ xhr.get({
+ sync: true,
+ url: "rest/helper?action=version",
+ handleAs: "json"
+ }).then(function(version) {
+ qpidVersion = version;
+ });
+ }
+ return qpidVersion;
+ },
+ getHelpUrl: function()
+ {
+ if (!helpURL)
+ {
+ helpURL = qpidHelpLocation + this.getVersion() + "/java-broker/book/index.html";
+ }
+ return helpURL;
+ },
+ showHelp: function()
+ {
+ var newWindow = window.open(this.getHelpUrl(),'QpidHelp','height=600,width=600,scrollbars=1,location=1,resizable=1,status=0,toolbar=0,titlebar=1,menubar=0', true);
+ newWindow.focus();
+ }
+ };
+
+});
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/TimeZoneSelector.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/TimeZoneSelector.js
index 7d0a02afca..fa4bd8c873 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/TimeZoneSelector.js
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/TimeZoneSelector.js
@@ -114,6 +114,7 @@ function (declare, array, domConstruct, parser, query, domStyle, Memory, _Widget
}
self._citySelector.set("disabled", checked);
self._regionSelector.set("disabled", checked);
+ self._handleOnChange(self.value);
});
this._regionSelector.on("change", function(value){
if (value=="undefined")
@@ -122,6 +123,7 @@ function (declare, array, domConstruct, parser, query, domStyle, Memory, _Widget
self._citySelector.query.region = /.*/;
self.value = null;
self._citySelector.set("value", null);
+ self._handleOnChange(self.value);
}
else
{
@@ -141,6 +143,7 @@ function (declare, array, domConstruct, parser, query, domStyle, Memory, _Widget
this._citySelector.on("change", function(value){
self.value = value;
+ self._handleOnChange(value);
});
this._setValueAttr(this._args.value);
@@ -176,6 +179,7 @@ function (declare, array, domConstruct, parser, query, domStyle, Memory, _Widget
this._regionSelector.set("value", "undefined");
}
this.value = value;
+ this._handleOnChange(value);
},
destroy: function()
@@ -188,6 +192,25 @@ function (declare, array, domConstruct, parser, query, domStyle, Memory, _Widget
_regionSelector: null;
_citySelector: null;
_utcSelector: null;
+ },
+
+ onChange: function(newValue){},
+
+ _handleOnChange: function(newValue)
+ {
+ if (this._lastValueReported != newValue)
+ {
+ this._lastValueReported = newValue;
+ if(this._onChangeHandle)
+ {
+ this._onChangeHandle.remove();
+ }
+ this._onChangeHandle = this.defer(function()
+ {
+ this._onChangeHandle = null;
+ this.onChange(newValue);
+ });
+ }
}
});
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/grid/EnhancedFilter.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/grid/EnhancedFilter.js
index 21046ad283..262210f879 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/grid/EnhancedFilter.js
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/grid/EnhancedFilter.js
@@ -96,6 +96,7 @@ define([
}
this.defaulGridRowLimit = args.defaulGridRowLimit;
this.disableFiltering = args.disableFiltering;
+ this.displayLastUpdateTime = args.displayLastUpdateTime;
//Install UI components
var obj = { "plugin": this };
@@ -147,6 +148,7 @@ define([
filterDefDialog: this.filterDefDialog,
defaulGridRowLimit: this.defaulGridRowLimit,
disableFiltering: this.disableFiltering,
+ displayLastUpdateTime: this.displayLastUpdateTime,
nls: nls,
ruleCountToConfirmClearFilter: this.ruleCountToConfirmClearFilter
});
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/grid/EnhancedFilterTools.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/grid/EnhancedFilterTools.js
index 475edaadfd..187ed8cfc6 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/grid/EnhancedFilterTools.js
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/grid/EnhancedFilterTools.js
@@ -22,12 +22,15 @@
define([
"dojo/_base/declare",
"dojo/_base/event",
+ "dojo/dom-construct",
+ "dojo/date/locale",
"dijit/form/Button",
"dijit/form/ToggleButton",
"qpid/common/grid/RowNumberLimitDialog",
"qpid/common/grid/ColumnDefDialog",
- "qpid/common/grid/FilterSummary"
-], function(declare, event, Button, ToggleButton, RowNumberLimitDialog, ColumnDefDialog, FilterSummary){
+ "qpid/common/grid/FilterSummary",
+ "qpid/management/UserPreferences"
+], function(declare, event, domConstruct, locale, Button, ToggleButton, RowNumberLimitDialog, ColumnDefDialog, FilterSummary, UserPreferences){
var _stopEvent = function (evt){
try{
@@ -65,6 +68,7 @@ define([
this.clearFilterDialog = params.clearFilterDialog;
this.filterDefDialog = params.filterDefDialog;
this.ruleCountToConfirmClearFilter = params.ruleCountToConfirmClearFilter;
+ this.displayLastUpdateTime = params.hasOwnProperty("displayLastUpdateTime")?params.displayLastUpdateTime:true;
this._addRefreshButtons();
this._addRowLimitButton(params.defaulGridRowLimit);
@@ -168,6 +172,38 @@ define([
this.filterBar.addChild(this.autoRefreshButton);
this.filterBar.addChild(this.refreshButton);
+
+ if (this.displayLastUpdateTime)
+ {
+ var updateStatusPanel = domConstruct.create("div");
+ var updateTimeLabel = domConstruct.create("span", {innerHTML: "Update time: ", "class": "formLabel-labelCell", "style": "padding-right: 5px;padding-left: 5px"}, updateStatusPanel);
+ var updateTimeLabelPreferredTZ = domConstruct.create("span", {innerHTML: "Preferred timezone:", "style": "padding-right: 5px"}, updateStatusPanel);
+ var updateTimePreferredTZ = domConstruct.create("span", {"style": "padding-right: 5px"}, updateStatusPanel);
+ var updateTimeLabelBrowserTZ = domConstruct.create("span", {innerHTML: "Browser timezone:", "style": "padding-right: 5px"}, updateStatusPanel);
+ var updateTimeBrowserTZ = domConstruct.create("span", {"style": "padding-right: 5px"}, updateStatusPanel);
+
+ var lastUpdateTimeUpdater = function(data)
+ {
+ var userTimeZone = UserPreferences.timeZone;
+ var displayStyle = userTimeZone? "inline" : "none";
+ updateTimeLabelPreferredTZ.style.display = displayStyle;
+ updateTimePreferredTZ.style.display = displayStyle;
+ var formatOptions = {selector: "time", timePattern: "HH:mm:ss.SSS", appendTimeZone: true, addOffset: true};
+ var updateTime = new Date();
+ updateTimePreferredTZ.innerHTML = UserPreferences.formatDateTime(updateTime.getTime(), formatOptions);
+ updateTimeBrowserTZ.innerHTML = locale.format(updateTime, formatOptions);
+ };
+
+ if (self.grid.updater.store)
+ {
+ // data have been already provided/or fetched
+ // set last update time to current time
+ lastUpdateTimeUpdater();
+ }
+
+ self.grid.updater.addOnUpdate(lastUpdateTimeUpdater);
+ domConstruct.place(updateStatusPanel, this.grid.viewsHeaderNode, "before");
+ }
},
_addRowLimitButton: function(defaulGridRowLimit)
@@ -241,6 +277,9 @@ define([
this.filterDefButton.on("click", function(e){
_stopEvent(e);
+
+ // a bit of a hack to force dialog to rebuild the criteria controls in order to get rid from empty rule controls
+ self.filterDefDialog._criteriasChanged = true;
self.filterDefDialog.showDialog();
});
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/grid/GridUpdater.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/grid/GridUpdater.js
index 1aadd719dd..8d58b6dec0 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/grid/GridUpdater.js
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/grid/GridUpdater.js
@@ -39,7 +39,11 @@ define(["dojo/_base/xhr",
this.updatable = args.hasOwnProperty("updatable") ? args.updatable : true ;
this.serviceUrl = args.serviceUrl;
- this.onUpdate = args.onUpdate;
+ this.onUpdate = [];
+ if (args.onUpdate)
+ {
+ this.onUpdate.push(args.onUpdate);
+ }
this.dataTransformer = args.dataTransformer;
this.appendData = args.append;
@@ -146,17 +150,10 @@ define(["dojo/_base/xhr",
if (data)
{
- try
- {
- if ((dataSet || self.updateOrAppend(data)) && self.onUpdate)
- {
- self.onUpdate(data);
- }
- }
- catch(e)
- {
- console.error(e);
- }
+ if ((dataSet || self.updateOrAppend(data)) && self.onUpdate.length > 0)
+ {
+ self.fireUpdate(data);
+ }
}
};
@@ -191,6 +188,7 @@ define(["dojo/_base/xhr",
this.store = null;
this.memoryStore = null;
this.grid = null;
+ this.onUpdate = null;
};
GridUpdater.prototype.updateOrAppend = function(data)
@@ -232,10 +230,7 @@ define(["dojo/_base/xhr",
finally
{
this.updating = false;
- if (this.onUpdate)
- {
- this.onUpdate(data);
- }
+ this.fireUpdate(data);
}
}
@@ -263,5 +258,40 @@ define(["dojo/_base/xhr",
}
};
+ GridUpdater.prototype.fireUpdate=function(data)
+ {
+ if (this.onUpdate.length > 0)
+ {
+ for(var i=0; i<this.onUpdate.length;i++)
+ {
+ var onUpdate= this.onUpdate[i];
+ try
+ {
+ onUpdate(data);
+ }
+ catch(e)
+ {
+ if (console && console.error)
+ {
+ console.error(e);
+ }
+ }
+ }
+ }
+ };
+
+ GridUpdater.prototype.addOnUpdate = function(obj) {
+ this.onUpdate.push(obj);
+ };
+
+ GridUpdater.prototype.removeOnUpdate = function(obj) {
+ for(var i = 0; i < this.onUpdate.length; i++) {
+ if(this.onUpdate[i] === obj) {
+ this.onUpdate.splice(i,1);
+ return;
+ }
+ }
+ };
+
return GridUpdater;
});
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Preferences.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Preferences.js
index 18396d7b8d..64299d62f6 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Preferences.js
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Preferences.js
@@ -71,20 +71,21 @@ function (declare, xhr, event, connect, dom, domConstruct, parser, json, Memory,
{
var name = preferenceNames[i];
this[name] = registry.byId("preferences." + name);
+ this[name].on("change", function(val){that._toggleSetButtons();});
}
this.setButton = registry.byId("preferences.setButton");
this.setAndCloseButton = registry.byId("preferences.setAndCloseButton");
- this.setButton.on("click", function(e){that._savePreferences(e, false)});
- this.setAndCloseButton.on("click", function(e){that._savePreferences(e, true)});
+ this.setButton.on("click", function(e){that._savePreferences(e, false);});
+ this.setAndCloseButton.on("click", function(e){that._savePreferences(e, true);});
this.theForm = registry.byId("preferences.preferencesForm");
this.usersGrid = registry.byId("preferences.users");
this.usersGrid.set("structure", [ { name: "User", field: "name", width: "50%"},
{ name: "Authentication Provider", field: "authenticationProvider", width: "50%"}]);
this.deleteButton = registry.byId("preferences.deleteButton");
this.deleteAndCloseButton = registry.byId("preferences.deleteAndCloseButton");
- this.deleteButton.on("click", function(e){that._deletePreferences(false)});
- this.deleteAndCloseButton.on("click", function(e){that._deletePreferences(true)});
+ this.deleteButton.on("click", function(e){that._deletePreferences(false);});
+ this.deleteAndCloseButton.on("click", function(e){that._deletePreferences(true);});
var deletePreferencesButtonToggler = function(rowIndex){
var data = that.usersGrid.selection.getSelected();
@@ -160,8 +161,8 @@ function (declare, xhr, event, connect, dom, domConstruct, parser, json, Memory,
{
that._loadUserPreferences();
}
- alert("Preferences stored successfully");
}
+ that._toggleSetButtons();
},
function(error){alert("Error:" + error);}
);
@@ -220,6 +221,7 @@ function (declare, xhr, event, connect, dom, domConstruct, parser, json, Memory,
}
}
}
+ this._toggleSetButtons();
},
_loadUserPreferences : function()
@@ -245,6 +247,27 @@ function (declare, xhr, event, connect, dom, domConstruct, parser, json, Memory,
that.usersGrid.set("store", usersDataStore);
that.usersGrid._refresh();
});
+ },
+
+ _toggleSetButtons: function()
+ {
+ var changed = false;
+ for(var i=0; i<preferenceNames.length; i++)
+ {
+ var name = preferenceNames[i];
+ var preferenceWidget = this[name];
+ if (preferenceWidget)
+ {
+ var value = preferenceWidget.hasOwnProperty("checked") ? preferenceWidget.checked : preferenceWidget.get("value");
+ if (value != UserPreferences[name])
+ {
+ changed = true;
+ break;
+ }
+ }
+ }
+ this.setButton.set("disabled", !changed);
+ this.setAndCloseButton.set("disabled", !changed);
}
});
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/PreferencesProviderFields.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/PreferencesProviderFields.js
index 39e852f94e..ebf06377f4 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/PreferencesProviderFields.js
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/PreferencesProviderFields.js
@@ -48,6 +48,9 @@ define(["dojo/_base/xhr",
{
if(type && string.trim(type) != "")
{
+ var disableOnEditing = PreferencesProviderFields.data? true: false;
+ PreferencesProviderFields.name.set("disabled", disableOnEditing);
+ PreferencesProviderFields.type.set("disabled", disableOnEditing);
if (PreferencesProviderFields.currentType != type)
{
require(["qpid/management/authenticationprovider/preferences/" + type.toLowerCase() + "/add"],
@@ -58,9 +61,6 @@ define(["dojo/_base/xhr",
{
PreferencesProviderFields.details.destroy();
}
- var disableOnEditing = PreferencesProviderFields.data? true: false;
- PreferencesProviderFields.name.set("disabled", disableOnEditing);
- PreferencesProviderFields.type.set("disabled", disableOnEditing);
PreferencesProviderFields.details = typeFields;
typeFields.show(PreferencesProviderFields.fieldsContainer, PreferencesProviderFields.data);
PreferencesProviderFields.currentType = type;
@@ -68,7 +68,7 @@ define(["dojo/_base/xhr",
}
else
{
- PreferencesProviderFields.disable(false);
+ PreferencesProviderFields.details.disable(false);
}
}
else
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/UserPreferences.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/UserPreferences.js
index f6746dd865..89a22a9e6e 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/UserPreferences.js
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/UserPreferences.js
@@ -29,6 +29,9 @@ define(["dojo/_base/xhr",
var UserPreferences = {
+ /* set time zone to 'UTC' by default*/
+ timeZone: "UTC",
+
loadPreferences : function(callbackSuccessFunction, callbackErrorFunction)
{
var that = this;
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/logs/LogViewer.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/logs/LogViewer.js
index c1f1164aa8..364d5403a3 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/logs/LogViewer.js
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/logs/LogViewer.js
@@ -154,7 +154,7 @@ define(["dojo/_base/xhr",
sortFields: [{attribute: 'id', descending: true}],
plugins:{
nestedSorting:true,
- enhancedFilter:{defaulGridRowLimit: defaulGridRowLimit},
+ enhancedFilter:{defaulGridRowLimit: defaulGridRowLimit,displayLastUpdateTime:true},
indirectSelection: false,
pagination: {defaultPageSize: 10}
}