This is an automated email from the ASF dual-hosted git repository. orudyy pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/qpid-broker-j.git
The following commit(s) were added to refs/heads/master by this push: new 00bf31f QPID-8314: [Broker-J][WMC] Allow selection of all messages displayed in the message table 00bf31f is described below commit 00bf31f99d8395de7876c9bfaaa45378cd9d67c3 Author: Alex Rudyy <oru...@apache.org> AuthorDate: Tue Jul 2 18:25:47 2019 +0100 QPID-8314: [Broker-J][WMC] Allow selection of all messages displayed in the message table --- .../src/main/java/resources/css/common.css | 12 +- .../resources/js/qpid/management/Management.js | 28 +- .../resources/js/qpid/management/MessageStore.js | 60 +++++ .../java/resources/js/qpid/management/Queue.js | 285 ++++++++++++--------- .../js/qpid/management/query/StoreUpdater.js | 17 +- .../src/main/java/resources/showQueue.html | 4 +- 6 files changed, 267 insertions(+), 139 deletions(-) diff --git a/broker-plugins/management-http/src/main/java/resources/css/common.css b/broker-plugins/management-http/src/main/java/resources/css/common.css index a12ac7d..4646275 100644 --- a/broker-plugins/management-http/src/main/java/resources/css/common.css +++ b/broker-plugins/management-http/src/main/java/resources/css/common.css @@ -114,11 +114,6 @@ h1 { } -div .messages { - width: 100%; - height: 350px; -} - .formBox { margin: 10px 5px; } @@ -837,3 +832,10 @@ td.advancedSearchField, col.autoWidth { .logViewer .field-logger { width: 20%;} .logViewer .field-threadName { width: 10%;} .logViewer .field-message { width: auto;} + +.queueMessages .field-selected { width: 2em; } +.queueMessages .field-id { width: 15%; } +.queueMessages .field-messageId { width: 20%; } +.queueMessages .field-size { width: 20%;} +.queueMessages .field-state { width: 20%; } +.queueMessages .field-arrivalTime { width: auto } diff --git a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Management.js b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Management.js index 0b181f4..777e972 100644 --- a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Management.js +++ b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Management.js @@ -108,7 +108,7 @@ define(["dojo/_base/lang", if (request) { - shallowCopy(request, requestOptions, ["url"]); + shallowCopy(request, requestOptions, ["url", "returnOriginalPromise"]); if (requestOptions.data && requestOptions.headers && requestOptions.headers["Content-Type"] && requestOptions.headers["Content-Type"] == "application/json" && typeof requestOptions.data != "string") @@ -137,6 +137,12 @@ define(["dojo/_base/lang", } } })); + + if ("returnOriginalPromise" in request && request.returnOriginalPromise === true) + { + return promise; + } + var errorHandler = this.errorHandler; // decorate promise in order to use a default error handler when 'then' method is invoked without providing error handler @@ -253,6 +259,25 @@ define(["dojo/_base/lang", return this.get(request); }; + Management.prototype.invoke = function (modelObj, parameters, requestOptions) + { + var url = this.objectToURL(modelObj); + var request = {url: url}; + + if (requestOptions) + { + lang.mixin(request, requestOptions); + } + + if (parameters) + { + request.query = parameters; + } + request.returnOriginalPromise = true; + + return this.get(request); + }; + // summary: // Creates object as specified in data parameter with given category and with given parent parentModelObject // category: String? @@ -624,6 +649,7 @@ define(["dojo/_base/lang", query: {} }; shallowCopy(query, request.query, ["parent", "category"]); + request.returnOriginalPromise = true; return this.get(request); }; diff --git a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/MessageStore.js b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/MessageStore.js new file mode 100644 index 0000000..74184bc --- /dev/null +++ b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/MessageStore.js @@ -0,0 +1,60 @@ +define([ + 'dojo/_base/lang', + 'dojo/_base/declare', + 'dstore/Store', + 'dstore/QueryResults' +], function (lang, declare, Store, QueryResults) { + + return declare("qpid.management.queue.MessageStore", [Store], { + + modelObject: null, + management: null, + operationName: "getMessageInfo", + operationArguments: {includeHeaders: false}, + totalLength: null, + + fetch: function () { + return this._request(); + }, + + fetchRange: function (kwArgs) { + return this._request(kwArgs); + }, + + _request: function (kwArgs) { + var modelObj = { + name: this.operationName, + parent: this.modelObject, + type: this.modelObject.type + }; + var query = lang.clone(this.operationArguments); + if (kwArgs && kwArgs.hasOwnProperty("start")) + { + query.first = kwArgs.start; + } + if (kwArgs && kwArgs.hasOwnProperty("end")) + { + query.last = kwArgs.end; + } + var headers = lang.mixin({Accept: "application/javascript, application/json"}, kwArgs.headers); + var messages = this.management.invoke(modelObj, query, {headers: headers}, true); + var depth = this._getQueueDepth(); + return new QueryResults(messages, {totalLength: depth}); + }, + + _getQueueDepth: function () { + var modelObj = { + name: "getStatistics", + parent: this.modelObject, + type: this.modelObject.type + }; + return this.management.load(modelObj, {statistics: ["queueDepthMessages"]}) + .then(function (data) { + return data["queueDepthMessages"]; + }, function (error) { + return 0; + }); + } + + }); +}); diff --git a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Queue.js b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Queue.js index 2bbc4ec..d1c6c93 100644 --- a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Queue.js +++ b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Queue.js @@ -36,15 +36,20 @@ define(["dojo/_base/declare", "qpid/management/moveCopyMessages", "qpid/management/showMessage", "qpid/management/addQueue", - "qpid/common/JsonRest", - "dojox/grid/EnhancedGrid", "qpid/management/query/QueryGrid", "qpid/common/StatisticsWidget", - "dojo/data/ObjectStore", "dojox/html/entities", "dojo/text!showQueue.html", - "dojox/grid/enhanced/plugins/Pagination", - "dojox/grid/enhanced/plugins/IndirectSelection", + "dgrid/Grid", + "dgrid/Selector", + "dgrid/Keyboard", + "dgrid/Selection", + "dgrid/extensions/Pagination", + "dgrid/extensions/ColumnResizer", + "dgrid/extensions/DijitRegistry", + "dojo/aspect", + "qpid/management/MessageStore", + "qpid/management/query/StoreUpdater", "dojo/domReady!"], function (declare, lang, @@ -64,13 +69,20 @@ define(["dojo/_base/declare", moveMessages, showMessage, addQueue, - JsonRest, - EnhancedGrid, QueryGrid, StatisticsWidget, - ObjectStore, entities, - template) + template, + Grid, + Selector, + Keyboard, + Selection, + Pagination, + ColumnResizer, + DijitRegistry, + aspect, + MessageStore, + StoreUpdater) { function Queue(kwArgs) @@ -112,87 +124,6 @@ define(["dojo/_base/declare", { that.queueUpdater = new QueueUpdater(that); - // double encode to allow slashes in object names. - var myStore = new JsonRest({ - management: that.management, - modelObject: that.modelObj, - queryOperation: "getMessageInfo", - queryParams: {includeHeaders: false}, - totalRetriever: function () - { - if (that.queueUpdater.queueData && that.queueUpdater.queueData.queueDepthMessages !== undefined) - { - return that.queueUpdater.queueData.queueDepthMessages; - } - return that.management.query( - { - parent: that.modelObj.parent, - category: "queue", - select: "queueDepthMessages", - where: "name='" + that.modelObj.name.replace(/'/g, "'''") + "'" - }) - .then(function (data) - { - return data && data.results && data.results[0] ? data.results[0][0] : 0; - }, function (error) - { - return undefined; - }); - } - }); - var messageGridDiv = query(".messages", contentPane.containerNode)[0]; - that.dataStore = new ObjectStore({objectStore: myStore}); - var userPreferences = this.management.userPreferences; - that.grid = new EnhancedGrid({ - store: that.dataStore, - autoHeight: 10, - keepSelection: true, - structure: [{ - name: "Payload Size", - field: "size", - width: "40%" - }, { - name: "State", - field: "state", - width: "30%" - }, - - { - name: "Arrival", - field: "arrivalTime", - width: "30%", - formatter: function (val) - { - return userPreferences.formatDateTime(val, { - addOffset: true, - appendTimeZone: true - }); - } - }], - plugins: { - pagination: { - pageSizes: ["10", "25", "50", "100"], - description: true, - sizeSwitch: true, - pageStepper: true, - gotoButton: true, - maxPageStep: 4, - position: "bottom" - }, - indirectSelection: true - }, - canSort: function (col) - { - return false; - } - }, messageGridDiv); - - connect.connect(that.grid, "onRowDblClick", that.grid, function (evt) - { - var idx = evt.rowIndex, theItem = this.getItem(idx); - showMessage.show(that.management, that.modelObj, theItem); - }); - var deleteMessagesButton = query(".deleteMessagesButton", contentPane.containerNode)[0]; var deleteWidget = registry.byNode(deleteMessagesButton); connect.connect(deleteWidget, "onClick", function (evt) @@ -256,29 +187,21 @@ define(["dojo/_base/declare", Queue.prototype.deleteMessages = function () { - var data = this.grid.selection.getSelected(); - if (data.length) + var selected = this.queueUpdater.getSelectedMessageIDs(); + if (selected.length > 0) { - if (confirm("Delete " + data.length + " messages?")) + var confirmationRequest = "Delete " + selected.length + " message" + (selected.length > 1 ? "s" : "" )+ "?"; + if (confirm(confirmationRequest)) { var modelObj = { type: "queue", name: "deleteMessages", parent: this.modelObj }; - var parameters = {messageIds: []}; - for (var i = 0; i < data.length; i++) - { - if (data[i]) - { - parameters.messageIds.push(data[i].id); - } - } - - this.management.update(modelObj, parameters) + this.management.update(modelObj, {messageIds: selected}) .then(lang.hitch(this, function () { - this.grid.selection.deselectAll(); + this.queueUpdater.clearMessageSelection(); this.reloadGridData(); })); } @@ -295,21 +218,14 @@ define(["dojo/_base/declare", }; this.management.update(modelObj, {}).then(lang.hitch(this, function () { - this.grid.selection.deselectAll(); + this.queueUpdater.clearMessageSelection(); this.reloadGridData(); })); } }; Queue.prototype.refreshMessages = function () { - var currentPage = this.grid.pagination.currentPage; - var currentPageSize = this.grid.pagination.currentPageSize; - var first = (currentPage - 1 ) * currentPageSize; - var last = currentPage * currentPageSize; - this.grid.setQuery({ - first: first, - last: last - }); + this.queueUpdater.refreshMessages(); }; Queue.prototype.reloadGridData = function () { @@ -318,26 +234,20 @@ define(["dojo/_base/declare", Queue.prototype.moveOrCopyMessages = function (obj) { var move = obj.move; - var data = this.grid.selection.getSelected(); - if (data.length) + var data = this.queueUpdater.getSelectedMessageIDs(); + if (data.length > 0) { - var i, putData = {messages: []}; + var putData = {messages: data}; if (move) { putData.move = true; } - for (i = 0; i < data.length; i++) - { - if (data[i]) - { - putData.messages.push(data[i].id); - } - } + moveMessages.show(this.management, this.modelObj, putData, lang.hitch(this, function () { if (move) { - this.grid.selection.deselectAll(); + this.queueUpdater.clearMessageSelection(); this.reloadGridData(); } })); @@ -348,7 +258,6 @@ define(["dojo/_base/declare", Queue.prototype.startup = function () { - this.grid.startup(); }; Queue.prototype.close = function () @@ -496,8 +405,134 @@ define(["dojo/_base/declare", { that.consumersGrid.resize(); }); + + this._messagesGrid = this._buildMessagesGrid(findNode); } + QueueUpdater.prototype.clearMessageSelection = function() + { + this._messagesGrid.clearSelection(); + }; + + QueueUpdater.prototype.refreshMessages = function() + { + this._messagesStore.updateRange(); + }; + + QueueUpdater.prototype.getSelectedMessageIDs = function () + { + var selected = []; + var selection = this._messagesGrid.selection || {}; + for (var item in selection) + { + if (selection.hasOwnProperty(item) && selection[item]) + { + selected.push(parseInt(item)); + } + } + return selected; + }; + + QueueUpdater.prototype._buildMessagesGrid = function(findNode) + { + var Store = declare([MessageStore, StoreUpdater], + { + track: function () { + return this; + }, + + _createSubCollection: function () { + return this; + } + }); + + this._messagesStore = new Store({ + idProperty: "id", + modelObject: this.modelObj, + management: this.management + }); + + var userPreferences = this.management.userPreferences; + var MessagesGrid = declare([Grid, + Keyboard, + Selection, + Selector, + Pagination, + ColumnResizer, + DijitRegistry + ]); + + var messagesGrid = new MessagesGrid({ + rowsPerPage: 10, + selectionMode: 'none', + detectChanges: true, + deselectOnRefresh: false, + allowSelectAll: true, + cellNavigation: true, + className: 'dgrid-autoheight', + pageSizeOptions: [10, 20, 30, 40, 50, 100], + adjustLastColumn: true, + collection: this._messagesStore, + highlightRow: function () { + }, + columns: [ + { + label: 'All', + selector: 'checkbox', + field: "selected", + sortable: false + }, + { + label: "ID", + field: "id", + sortable: false + }, { + label: "Payload Size", + field: "size", + formatter: formatter.formatBytes, + sortable: false + }, { + label: "State", + field: "state", + sortable: false + }, { + label: "Arrival", + field: "arrivalTime", + sortable: false, + formatter: function (value, object) { + return userPreferences.formatDateTime(value, + { + addOffset: true, + appendTimeZone: true + }); + } + } + ] + }, findNode("messagesGrid")); + + var management = this.management; + var modelObj = this.modelObj; + messagesGrid.on('.dgrid-row:dblclick', lang.hitch(this, function (event) { + showMessage.show(management, modelObj, messagesGrid.row(event)); + })); + messagesGrid.on('.dgrid-row:keypress', lang.hitch(this, function (event) { + if (event.keyCode === keys.ENTER) + { + showMessage.show(management, modelObj, messagesGrid.row(event)); + } + })); + + messagesGrid.startup(); + var queueMessagesPanel = registry.byNode(findNode("queueMessages")); + aspect.after(queueMessagesPanel, "toggle", function () { + if (queueMessagesPanel.get("open") === true) + { + messagesGrid.refresh(); + } + }); + return messagesGrid; + }; + function renderMaximumQueueDepthMessages(valueElement, value, bytes) { var text; diff --git a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/StoreUpdater.js b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/StoreUpdater.js index df0a547..1a02925 100644 --- a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/StoreUpdater.js +++ b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/StoreUpdater.js @@ -132,6 +132,7 @@ define(["dojo/_base/declare", var newResults = results.slice(0); var idProperty = this.idProperty; var newResultsIdToIndexMap = createIdToIndexMap(newResults, idProperty); + var total = data.totalLength; if (this._currentResults) { var currentResults = this._currentResults.slice(0); @@ -142,7 +143,7 @@ define(["dojo/_base/declare", var newResultIndex = newResultsIdToIndexMap[id]; if (newResultIndex === undefined) { - this._pushChange("delete", currentResult, offset + i, offset + i); + this._pushChange("delete", currentResult, offset + i, offset + i, total); currentResults.splice(i, 1); updateIdToIndexMap(currentResults, idProperty, @@ -165,7 +166,7 @@ define(["dojo/_base/declare", idProperty, this._currentResultsIdToIndexMap, j); - this._pushChange("add", newResult, offset + j); + this._pushChange("add", newResult, offset + j, -1, total); } else { @@ -175,12 +176,12 @@ define(["dojo/_base/declare", currentResults[j] = newResult; if (!util.equals(newResult, currentResult)) { - this._pushChange("update", newResult, offset + j, previousIndex + offset); + this._pushChange("update", newResult, offset + j, previousIndex + offset, total); } } else { - this._pushChange("update", newResult, offset + j, previousIndex + offset); + this._pushChange("update", newResult, offset + j, previousIndex + offset, total); currentResults.splice(previousIndex, 1); currentResults.splice(j, 0, currentResult); updateIdToIndexMap(currentResults, @@ -195,7 +196,7 @@ define(["dojo/_base/declare", { for (var j = 0; j < newResults.length; j++) { - this._pushChange("add", newResults[j], offset + j); + this._pushChange("add", newResults[j], offset + j, -1, total); } } @@ -203,7 +204,7 @@ define(["dojo/_base/declare", this._currentResultsIdToIndexMap = newResultsIdToIndexMap; } }, - _pushChange: function (change, item, currentIndex, previousIndex) + _pushChange: function (change, item, currentIndex, previousIndex, total) { if (this.targetStore) { @@ -231,6 +232,10 @@ define(["dojo/_base/declare", "index": currentIndex, "previousIndex": previousIndex }; + if (total >= 0) + { + event.totalLength = total; + } this.emit(change, event); } } diff --git a/broker-plugins/management-http/src/main/java/resources/showQueue.html b/broker-plugins/management-http/src/main/java/resources/showQueue.html index aa3f2db..a4b1936 100644 --- a/broker-plugins/management-http/src/main/java/resources/showQueue.html +++ b/broker-plugins/management-http/src/main/java/resources/showQueue.html @@ -120,8 +120,8 @@ <div class="consumers"></div> </div> <br/> - <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Messages'"> - <div class="messages"></div> + <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Messages'" class="queueMessages"> + <div class="messagesGrid"></div> <button data-dojo-type="dijit.form.Button" class="deleteMessagesButton" type="button">Delete Messages</button> <button data-dojo-type="dijit.form.Button" class="clearQueueButton" type="button">Clear Queue</button> <button data-dojo-type="dijit.form.Button" class="moveMessagesButton" type="button">Move Messages</button> --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@qpid.apache.org For additional commands, e-mail: commits-h...@qpid.apache.org