Modified: qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/DropDownSelect.js URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/DropDownSelect.js?rev=1741469&r1=1741468&r2=1741469&view=diff ============================================================================== --- qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/DropDownSelect.js (original) +++ qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/DropDownSelect.js Thu Apr 28 16:22:56 2016 @@ -119,6 +119,7 @@ function(declare, lang, array, json, dom */ _optionsGrid: null, _descending: false, + _selectedItems: [], postCreate: function() { @@ -162,12 +163,36 @@ function(declare, lang, array, json, dom deselectOnRefresh: false }, this.optionsGrid); - grid.on('dgrid-select', lang.hitch(this, this._selectionChanged)); - grid.on('dgrid-deselect', lang.hitch(this, this._selectionChanged)); + grid.on('dgrid-select', lang.hitch(this, this._gridSelected)); + grid.on('dgrid-deselect', lang.hitch(this, this._gridDeselected)); grid.on('dgrid-sort', lang.hitch(this, function(event){this._descending = event.sort[0].descending})); grid.setTotal(this.items ? this.items.length : 0); this._optionsGrid = grid; }, + _gridSelected: function(event) + { + for (var i = 0; i < event.rows.length; ++i) + { + this._selectedItems.push(event.rows[i].data); + } + this._selectionChanged(); + }, + _gridDeselected: function(event) + { + for (var i = 0; i < event.rows.length; ++i) + { + var id = event.rows[i].id; + for (var j = 0; j < this._selectedItems.length; ++j) + { + if (this._selectedItems[j].id === id) + { + this._selectedItems.splice(j, 1); + break; + } + } + } + this._selectionChanged(); + }, _setDataAttr:function(data) { if (data.idProperty) @@ -181,11 +206,7 @@ function(declare, lang, array, json, dom } var store; - if (data.store) - { - store = data.store; - } - else if (data.items) + if (data.items) { store = new Memory({data: data.items, idProperty: this.idProperty}); this.items = data.items; @@ -206,32 +227,56 @@ function(declare, lang, array, json, dom this._selectGrid(data.selected); } }, + _findItemById: function(items, idValue) + { + for (var i = 0; i < items.length; ++i) + { + if (items[i][this.idProperty] === idValue) + { + return items[i]; + } + } + return null; + }, _selectGrid: function(selected) { - var selectedRowIds = lang.clone(this._optionsGrid.selection || {}); - if (selected && selected.length && this.store) - { - for(var i=0;i<selected.length;i++) + var items = []; + if (selected && selected.length && !selected[0].hasOwnProperty(this.idProperty)) { - var id = selected[i] && selected[i].hasOwnProperty(this.idProperty) ? selected[i][this.idProperty] : selected[i]; - if (id in selectedRowIds) - { - delete selectedRowIds[id]; - } - else - { - this._optionsGrid.select(id, null, true); - } + for (var i = 0; i < selected.length; ++i) + { + var item = this._findItemById(this.items, selected[i]); + if (item) + { + items.push(item); + } + } + } + else + { + items = lang.clone(selected); } - } - for (var id in selectedRowIds) - { - if (this._optionsGrid.selection[id]) + var selectedItems = lang.clone(this._selectedItems); + for (var i = 0; i < selectedItems.length; ++i) { - this._optionsGrid.select(id, null, false); + var currentItem = selectedItems[i]; + var item = this._findItemById(items, currentItem[this.idProperty]); + if (!item) + { + this._optionsGrid.deselect(currentItem); + } } - } + for (var i = 0; i < items.length; ++i) + { + var currentItem = items[i]; + var item = this._findItemById(this._selectedItems, currentItem[this.idProperty]); + if (!item) + { + this._optionsGrid.select(currentItem); + } + } + this._selectedItems = items; }, _onClear: function() { @@ -262,7 +307,7 @@ function(declare, lang, array, json, dom }, _selectionChanged: function(event) { - this.doneButton.set("disabled", !this._isSelected()); + this.doneButton.set("disabled", this._selectedItems.length === 0); }, _getOptionColumns: function() { @@ -270,42 +315,18 @@ function(declare, lang, array, json, dom columns[this.nameProperty] = { label:"Name", sortable: true } return columns; }, - _isSelected: function() - { - var selectionFound = false; - for (var id in this._optionsGrid.selection) - { - if (this._optionsGrid.selection[id]) - { - selectionFound = true; - break; - } - } - return selectionFound; - }, _getSelectedItemsAttr: function() { - var selected = []; - if (this.store && this._optionsGrid.selection) - { - for (var id in this._optionsGrid.selection) - { - if (this._optionsGrid.selection[id]) - { - selected.push(id); - } - } - } - var filter = new this.store.Filter().in(this.idProperty, selected); - var promise = this.store.filter(filter).fetch(); - return promise; + return lang.clone(this._selectedItems); }, _reset: function(items) { this._onClear(); - items = items || []; - this._selectGrid(items); + if (items) + { + this._selectGrid(items); + } } }); @@ -344,13 +365,7 @@ function(declare, lang, array, json, dom _setDataAttr:function(data) { this._optionsPanel.set("data", data); - var promise = this._optionsPanel.get("selectedItems"); - dojo.when(promise, - lang.hitch(this, - function(selectedItems) - { - this._selectedItems = selectedItems; - })); + this._selectedItems = this._optionsPanel.get("selectedItems"); }, _getSelectedItemsAttr: function() { @@ -358,13 +373,10 @@ function(declare, lang, array, json, dom }, _onSelectionDone: function() { - var promise = this._optionsPanel.get("selectedItems"); - dojo.when(promise, lang.hitch(this, function(selectedItems) - { - this._selectedItems = selectedItems; - this._hideAndResetSearch(selectedItems); - this.emit("change", selectedItems); - })); + this._selectedItems = this._optionsPanel.get("selectedItems"); + popup.close(this._optionsDialog); + this._optionsPanel._reset(); + this.emit("change", this._selectedItems); }, _hideAndResetSearch: function() { @@ -375,11 +387,11 @@ function(declare, lang, array, json, dom { this._optionsPanel._reset(this._selectedItems); }, - _setDisabled:function(value) + _setDisabledAttr:function(value) { this._selectButton.set("disabled", value); }, - _getDisabled:function() + _getDisabledAttr:function() { return this._selectButton.get("disabled") },
Modified: qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/QueryBuilder.js URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/QueryBuilder.js?rev=1741469&r1=1741468&r2=1741469&view=diff ============================================================================== --- qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/QueryBuilder.js (original) +++ qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/QueryBuilder.js Thu Apr 28 16:22:56 2016 @@ -33,6 +33,7 @@ define(["dojo/_base/declare", "dgrid/extensions/ColumnResizer", "dstore/Memory", 'dstore/legacy/DstoreAdapter', + "qpid/management/query/QueryStore", "qpid/management/query/DropDownSelect", "qpid/management/query/WhereExpression", "dojo/Evented", @@ -72,27 +73,12 @@ define(["dojo/_base/declare", ColumnResizer, Memory, DstoreAdapter, - DropDownSelect, - WhereExpression + QueryStore ) { - var arrayToSelectExpression = function(value) - { - var expression = ""; - if (lang.isArray(value)) - { - for(var i=0; i<value.length ;i++) - { - var selection = value[i] && value[i].hasOwnProperty("attributeName") ? - value[i].attributeName : value[i]; - expression = expression + (i > 0 ? "," : "") + selection; - } - } - return expression; - }; var predefinedCategories = [ {id: "queue", name: "Queue"}, {id: "connection", name: "Connection"} ]; - return declare( "qpid.management.query.QueryBuilder", + var QueryBuilder = declare( "qpid.management.query.QueryBuilder", [dijit._Widget, dijit._TemplatedMixin, dijit._WidgetsInTemplateMixin], { //Strip out the apache comment header from the template html as comments unsupported. @@ -104,15 +90,16 @@ define(["dojo/_base/declare", scope:null, categoryName: null, advancedSearch: null, - selectExpression: null, - whereExpression: null, + advancedSelect: null, + advancedWhere: null, standardSearch: null, - selectColumnsButton: null, - selectWhereButton: null, + standardSelectChooser: null, + standardWhereChooser: null, searchButton: null, modeButton: null, - whereExpressionBuilder: null, + standardWhereExpressionBuilder: null, queryResultGrid: null, + advancedOrderBy: null, /** * constructor parameter @@ -123,14 +110,12 @@ define(["dojo/_base/declare", * Inner fields */ _standardMode: true, - _standardModeLastWhereExpression: null, - _standardModeLastSelectExpression: null, _scopeModelObjects: {}, _categorySelector: null, _searchScopeSelector: null, - _lastCategory: null, - _lastSearchQuery: null, - _showWarningOnChangesInAdvancedMode: true, + _lastStandardModeSelect: [], + _sort: [], + _lastHeaders: [], constructor: function(args) { @@ -152,214 +137,218 @@ define(["dojo/_base/declare", this._createCategoryList(); // advanced mode widgets - this.whereExpression.on("blur", lang.hitch(this, this._showAdvanceModeWarningIfRequired)); - this.selectExpression.on("blur", lang.hitch(this, this._showAdvanceModeWarningIfRequired)); - this.selectExpression.on("change", lang.hitch(this, this._advancedModeSelectChanged)); - this.selectExpression.on("keyUp", lang.hitch(this, this._advancedModeKeyPressed)); - this.whereExpression.on("keyUp", lang.hitch(this, this._advancedModeKeyPressed)); + this.advancedSelect.on("change", lang.hitch(this, this._toggleSearchButton)); + this.advancedSelect.on("blur", lang.hitch(this, this._advancedModeSelectChanged)); + this.advancedWhere.on("blur", lang.hitch(this, this._advancedModeWhereChanged)); + this.advancedOrderBy.on("blur", lang.hitch(this, this._advancedModeOrderByChanged)); + this.advancedSelect.on("keyDown", lang.hitch(this, this._advancedModeKeyPressed)); + this.advancedWhere.on("keyDown", lang.hitch(this, this._advancedModeKeyPressed)); + this.advancedOrderBy.on("keyDown", lang.hitch(this, this._advancedModeKeyPressed)); // standard mode widgets - this.selectColumnsButton.on("change", lang.hitch(this, this._standardModeSelectChanged)); - this.selectColumnsButton.startup(); - this.selectWhereButton.startup(); - this.whereExpressionBuilder.set("whereFieldsSelector", this.selectWhereButton ); - this.whereExpressionBuilder.set("userPreferences", this._management.userPreferences ); - this.whereExpressionBuilder.startup(); - this.whereExpressionBuilder.on("change", lang.hitch(this, this._standardModeWhereChanged)); + this.standardSelectChooser.on("change", lang.hitch(this, this._standardModeSelectChanged)); + this.standardSelectChooser.startup(); + this.standardWhereChooser.startup(); + this.standardWhereExpressionBuilder.set("whereFieldsSelector", this.standardWhereChooser ); + this.standardWhereExpressionBuilder.set("userPreferences", this._management.userPreferences ); + this.standardWhereExpressionBuilder.startup(); + this.standardWhereExpressionBuilder.on("change", lang.hitch(this, this._standardModeWhereChanged)); // search & mode buttons this.searchButton.on("click", lang.hitch(this, this.search)); - this.modeButton.on("click", lang.hitch(this, this._modeChanged)); + this.modeButton.on("click", lang.hitch(this, this._showModeSwitchWarningIfRequired)); + this._buildGrid(); this._categoryChanged(); this._toggleSearchButton(); }, search: function() { - var select, where, callback; - if (this._standardMode) - { - select = this._standardModeLastSelectExpression; - where = this._standardModeLastWhereExpression; - } - else - { - select = this.selectExpression.value; - where = this.whereExpression.value; - callback = lang.hitch(this, this._resetStandardSearchWidgetsIfAdvancedChanged); - } - - var category = this._categorySelector.value.toLowerCase(); - if (select && category) - { + var category = this._categorySelector.value.toLowerCase(); var scope = this._searchScopeSelector.value; - this._lastSearchQuery = {scope:scope, select: select, where: where, category: category}; var modelObj = this._scopeModelObjects[scope]; - this._doSearch( modelObj, category, select, where, callback); - } + this._store.selectClause = this._store.selectClause; + this._store.where = this._store.where; + this._store.category = category; + this._store.parent = modelObj; + this._store.orderBy = this._store.orderBy; + this._resultsGrid.refresh(); }, - _doSearch: function(modelObj, category, select, where, callback) + _showModeSwitchWarningIfRequired: function() + { + var userPreferences = this._management.userPreferences; + var displayWarning = (!userPreferences || !userPreferences.query || + (userPreferences.query.displaySwitchModeWarning == undefined || + userPreferences.query.displaySwitchModeWarning)); + if (this._standardMode && displayWarning && QueryBuilder.showWarningOnModeChange) + { + if (!this._switchModeWarningDialog) + { + var formattedMessage = "<div>Switching to advanced mode is a one-way street,<br/>" + + "switching back from advanced mode to standard mode will<br/>" + + "completely reset the query.</div>"; + this._switchModeWarningDialog = new qpid.management.query.MessageDialog({ + title: "Warning!", + message: formattedMessage}, + domConstruct.create("div")); + this._switchModeWarningDialog.on("execute", + lang.hitch(this, function(stopDisplaying) + { + if (stopDisplaying) + { + if (!userPreferences.query) + { + userPreferences.query = {}; + } + userPreferences.query.displaySwitchModeWarning = false; + userPreferences.save({query: userPreferences.query}, + null, + function(error){console.log("Saving user preferences failed: " + error);} + ); + } + else + { + QueryBuilder.showWarningOnModeChange = false; + } + this._modeChanged(); + })); + } + this._switchModeWarningDialog.show(); + } + else + { + this._modeChanged(); + } + }, + _advancedModeSelectChanged: function() { - var that = this; - var result = this._management.query({select: select, - where: where, - parent: modelObj, - category: category}); - result.then(function(data) - { - that._showResults(data.results, data.headers); - if (callback) - { - callback(); - } - }, - function(error) - { - if (error && error.response && error.response.status == 404) - { - that._showResults([], []); - } - else - { - alert(error.message ? error.message: error); - } - }); + this._store.selectClause = this.advancedSelect.value; + }, + _advancedModeWhereChanged: function() + { + this._store.where = this.advancedWhere.value; + }, + _advancedModeOrderByChanged: function() + { + this._store.orderBy = this.advancedOrderBy.value; + }, + _toggleSearchButton: function(select) + { + var criteriaNotSet = !select; + this.searchButton.set("disabled",criteriaNotSet); + this.searchButton.set("title", criteriaNotSet?"Please, choose fields to display in order to enable search":"Search"); }, - _showAdvanceModeWarningIfRequired: function() + _buildOrderByExpression: function() { - if (!this._standardMode && - ( this.selectExpression.value != this._standardModeLastSelectExpression || - this.whereExpression.value != this._standardModeLastWhereExpression )) + var orderByExpression = ""; + if (this._sort && this._sort.length) { - var userPreferences = this._management.userPreferences; - var displayWarning = !userPreferences || !userPreferences.query || - (userPreferences.query.displaySwitchModeWarning == undefined - || userPreferences.query.displaySwitchModeWarning ); - if (displayWarning && this._showWarningOnChangesInAdvancedMode) + var orders = [] + for (var i = 0; i < this._sort.length; ++i) { - if (!this._switchModeWarningDialog) - { - var that = this; - var formattedMessage = "<div>On switching to Standard Mode,</div>" - + " <div>all modifications made to where clause</div>" - + " <div>and any expressions within the select clause will be lost.</div>"; - this._switchModeWarningDialog = new qpid.management.query.MessageDialog({title: "Warning!", - message: formattedMessage}, - domConstruct.create("div")); - this._switchModeWarningDialog.on( "execute", - function(stopDisplaying) - { - if (stopDisplaying) - { - if (!userPreferences.query) - { - userPreferences.query= {}; - } - userPreferences.query.displaySwitchModeWarning = false; - userPreferences.save({query: userPreferences.query}); - - } - else - { - that._showWarningOnChangesInAdvancedMode = false; - } - that.search(); - }); - this._switchModeWarningDialog.on( "cancel", - function(val) - { - that.whereExpression.set("value", that._standardModeLastWhereExpression); - that.selectExpression.set("value", that._standardModeLastSelectExpression); - }); - } - this._switchModeWarningDialog.show(); - return true; + orders.push(parseInt(this._sort[i].property) + (this._sort[i].descending? " desc" : "")); } + orderByExpression = orders.join(","); } - return false; + this.advancedOrderBy.set("value", orderByExpression); + return orderByExpression; }, - _advancedModeSelectChanged: function() + _buildSelectExpression: function(value) { - this._toggleSearchButton(this.selectExpression.value); + var expression = ""; + if (lang.isArray(value)) + { + for(var i=0; i<value.length ;i++) + { + var selection = value[i] && value[i].hasOwnProperty("attributeName") ? + value[i].attributeName : value[i]; + expression = expression + (i > 0 ? "," : "") + selection; + } + } + return expression; }, - _toggleSearchButton: function(select) + _normalizeSorting: function(selectedColumns) { - var criteriaNotSet = !select; - this.searchButton.set("disabled",criteriaNotSet); - this.searchButton.set("title", criteriaNotSet?"Please, choose fields to display in order to enable search":"Search"); + var newSort = []; + for (var i = 0; i < this._sort.length; ++i) { + var sortColumnIndex = parseInt(this._sort[i].property) - 1; + var sortDescending = this._sort[i].descending; + if (sortColumnIndex < this._lastStandardModeSelect.length) { + var oldSortedColumnName = this._lastStandardModeSelect[sortColumnIndex].attributeName; + for (var j = 0; j < selectedColumns.length; ++j) { + if (selectedColumns[j].attributeName === oldSortedColumnName) { + newSort.push({ + property: "" + (j + 1), + descending: sortDescending + }); + break; + } + } + } + } + this._sort = newSort; }, - _standardModeSelectChanged: function(result) + _standardModeSelectChanged: function(selectedColumns) { - this._standardModeLastSelectExpression = arrayToSelectExpression(result); - this.selectExpression.set("value", this._standardModeLastSelectExpression); + this._normalizeSorting(selectedColumns); + this._store.orderBy = this._buildOrderByExpression(); + this._store.selectClause = this._buildSelectExpression(selectedColumns); + this._lastStandardModeSelect = lang.clone(selectedColumns); + this._toggleSearchButton(this._store.selectClause); this.search(); }, _standardModeWhereChanged: function(result) { - this._standardModeLastWhereExpression = result; - this.whereExpression.set("value", result); + this._store.where = result; this.search(); }, - _resetStandardSearchWidgetsIfAdvancedChanged: function() + _buildGrid: function() { - if (this._standardModeLastWhereExpression && this._standardModeLastWhereExpression != this.whereExpression.value) - { - this._standardModeLastWhereExpression = ""; - this.whereExpressionBuilder.clearWhereCriteria(); - } - - if (this._standardModeLastSelectExpression != this.selectExpression.value) - { - this._standardModeLastSelectExpression = this.selectExpression.value; + this._store = new QueryStore({ + management: this.management, + category: this._categorySelector.value.toLowerCase(), + parent: this._scopeModelObjects[this._searchScopeSelector.value], + zeroBased: false}); - // update selected from headers ignoring id - var headers = lang.clone(this._lastHeaders); - headers.shift(); - this.selectColumnsButton.set("data", {selected: headers}); - var promise = this.selectColumnsButton.get("selectedItems"); - dojo.when(promise, - lang.hitch(this, - function(selectedItems) - { - var val = arrayToSelectExpression(selectedItems); - this._standardModeLastSelectExpression = val; - })); - } - }, - _showResults:function(items, headers) - { - this._lastHeaders = headers; - var store = new Memory({data: items, idProperty: 0}); - if (!this._resultsGrid) - { - if (items && items.length) - { - this._buildGrid(store, this._lastHeaders); - } - } - else - { - this._resultsGrid.set("collection", store); - this._resultsGrid.set("columns", this._getColumns(this._lastHeaders)); - this._resultsGrid.refresh(); - } - }, - _buildGrid: function(store, headers) - { var CustomGrid = declare([ Grid, Keyboard, Selection, Pagination, ColumnResizer ]); - var grid = new CustomGrid({ - columns: this._getColumns(headers), - collection: store, + + var grid = new CustomGrid({ collection: this._store, rowsPerPage: 100, selectionMode: 'single', cellNavigation: false, className: 'dgrid-autoheight', + pageSizeOptions: [10,20,30,40,50,100,1000,10000,100000], adjustLastColumn: true }, this.queryResultGrid); + this._store.on("changeHeaders", lang.hitch(this, function(event) { + this._store.useCachedResults = true; + grid.set("columns", this._getColumns(event.headers)); + this._resultsGrid.resize(); + })); this._resultsGrid = grid; this._resultsGrid.startup(); this._resultsGrid.on('.dgrid-row:dblclick', lang.hitch(this, this._onRowClick)); + this._resultsGrid.on("dgrid-sort", lang.hitch(this, function(event) { + for (var i = 0; i < this._sort.length; ++i) { + if (this._sort[i].property == event.sort[0].property) { + this._sort.splice(i, 1); + break; + } + } + this._sort.splice(0, 0, event.sort[0]); + this._store.orderBy = this._buildOrderByExpression(); + event.preventDefault(); + event.stopPropagation(); + this.search(); + })); + this._resultsGrid.on("dgrid-refresh-complete", + lang.hitch(this, + function() + { + this._store.useCachedResults = false; + this._resultsGrid.updateSortArrow(this._sort, true); + })); }, _onRowClick: function (event) { @@ -408,20 +397,16 @@ define(["dojo/_base/declare", } }); }, - _getColumns: function(attributes) + _getColumns: function(headers) { + this._lastHeaders = headers; var columns = []; - if (attributes) + if (headers) { - for (var i in attributes) + for (var i = 0; i < headers.length; ++i) { - if (i == 0) - { - // skip first id column as it was added by management - continue; - } - var attribute = attributes[i]; - var column = {label: attribute, field: i}; + var attribute = headers[i]; + var column = {label: attribute, field: "" + (i + 1), sortable: true}; columns.push(column); if (this._columns) { @@ -485,7 +470,7 @@ define(["dojo/_base/declare", _createScopeList: function() { var that = this; - var result = this._management.query({select: "$parent.name as parentName, name", + var result = this._management.query({select: "id, $parent.name as parentName, name", category : "virtualhost"}); var deferred = new dojo.Deferred(); result.then(function(data) @@ -563,95 +548,94 @@ define(["dojo/_base/declare", }, _categoryChanged: function() { - var metadata = this._getCategoryMetadata(this._categorySelector.value); - var disableMetadataDependant = !metadata; - this.selectWhereButton.set("disabled", disableMetadataDependant); - this.selectColumnsButton.set("disabled", disableMetadataDependant); - this.searchButton.set("disabled", disableMetadataDependant); - if (disableMetadataDependant) - { - dijit.showTooltip( - this._categorySelector.get("invalidMessage"), - this._categorySelector.domNode, - this._categorySelector.get("tooltipPosition"), - !this._categorySelector.isLeftToRight() - ); - } - else - { - if (this._lastCategory != this._categorySelector.value) + this._resetSearch(); + var metadata = this._getCategoryMetadata(this._categorySelector.value); + var disableMetadataDependant = !metadata; + this.standardWhereChooser.set("disabled", disableMetadataDependant); + this.standardSelectChooser.set("disabled", disableMetadataDependant); + this.searchButton.set("disabled", disableMetadataDependant || !this._store.selectClause); + this.modeButton.set("disabled", disableMetadataDependant); + this.advancedSelect.set("disabled", disableMetadataDependant); + this.advancedWhere.set("disabled", disableMetadataDependant); + this.advancedOrderBy.set("disabled", disableMetadataDependant); + + if (disableMetadataDependant) { - this._standardModeLastWhereExpression = ""; - this._lastCategory = this._categorySelector.value; - this.selectExpression.set("value", ""); - this.whereExpression.set("value", ""); - this.whereExpressionBuilder.clearWhereCriteria(); - var data = this._combineTypeAttributesAndStatistics(metadata); - this._columns = data.asObject; - this.selectColumnsButton.set("data", {items: data.asArray, - idProperty: "id", - selected:[], - nameProperty: "attributeName"}); - this.selectWhereButton.set("data", {items: data.asArray, - selected:[], - idProperty: "id", - nameProperty: "attributeName"}); - this._showResults([], []); + dijit.showTooltip( + this._categorySelector.get("invalidMessage"), + this._categorySelector.domNode, + this._categorySelector.get("tooltipPosition"), + !this._categorySelector.isLeftToRight() + ); + } + else + { + var data = this._combineTypeAttributesAndStatistics(metadata); + this._columns = data.asObject; + this.standardSelectChooser.set("data", {items: data.asArray, + idProperty: "id", + selected:[], + nameProperty: "attributeName"}); + this.standardWhereChooser.set("data", {items: data.asArray, + selected:[], + idProperty: "id", + nameProperty: "attributeName"}); } - } }, _advancedModeKeyPressed:function(evt) { var key = evt.keyCode; - if (key == dojo.keys.ENTER && this.selectExpression.value) + if (key == dojo.keys.ENTER) { - if (!this._showAdvanceModeWarningIfRequired()) - { + evt.preventDefault(); + evt.stopPropagation(); + this._store.selectClause = this.advancedSelect.value; + this._store.where = this.advancedWhere.value; + this._store.orderBy = this.advancedOrderBy.value; this.search(); - } } }, _modeChanged: function() { - this._standardMode = !this._standardMode + this._standardMode = !this._standardMode; if (!this._standardMode) { this.modeButton.set("label", "Standard"); this.modeButton.set("title", "Switch to 'Standard' search"); - this.selectExpression.set("disabled", false); - this.whereExpression.set("disabled", false); + this.advancedSelect.set("disabled", false); + this.advancedWhere.set("disabled", false); this.standardSearch.style.display = "none"; - this.whereExpressionBuilder.domNode.style.display = "none"; + this.standardWhereExpressionBuilder.domNode.style.display = "none"; this.advancedSearch.style.display = ""; - if (this._lastSearchQuery && - (this._lastSearchQuery.select != this.selectExpression.value || - this._lastSearchQuery.where != this.whereExpression.value || - this._lastSearchQuery.category != this._categorySelector.value || - this._lastSearchQuery.scope != this._searchScopeSelector.value)) - { - this.search(); - } + this.advancedSelect.set("value", this._store.selectClause); + this.advancedWhere.set("value", this._store.where); + this.advancedOrderBy.set("value", this._store.orderBy); } else { this.modeButton.set("label", "Advanced"); this.modeButton.set("title", "Switch to 'Advanced' search using SQL-like expressions"); - this.selectExpression.set("disabled", true); - this.whereExpression.set("disabled", true); + this.advancedSelect.set("disabled", true); + this.advancedWhere.set("disabled", true); this.standardSearch.style.display = ""; - this.whereExpressionBuilder.domNode.style.display = ""; + this.standardWhereExpressionBuilder.domNode.style.display = ""; this.advancedSearch.style.display = "none"; - - if (this._lastSearchQuery && - (this._lastSearchQuery.select != this._standardModeLastSelectExpression || - this._lastSearchQuery.where != this._standardModeLastWhereExpression || - this._lastSearchQuery.category != this._categorySelector.value || - this._lastSearchQuery.scope != this._searchScopeSelector.value)) - { - this.search(); - } + this._resetSearch(); } }, + _resetSearch: function() + { + this._store.where = ""; + this._store.selectClause = ""; + this._store.orderBy = ""; + this.standardSelectChooser.set("data", {selected: []}); + this.standardWhereExpressionBuilder.clearWhereCriteria(); + this._sort = []; + this.advancedSelect.set("value", this._store.selectClause); + this.advancedWhere.set("value", this._store.where); + this.advancedOrderBy.set("value", this._store.orderBy); + this.search(); + }, _getCategoryMetadata: function(value) { if (value) @@ -718,4 +702,8 @@ define(["dojo/_base/declare", return {asArray: columnsArray, asObject: columnsObject}; } }); + + QueryBuilder.showWarningOnModeChange = true; + + return QueryBuilder; }); Added: qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/QueryStore.js URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/QueryStore.js?rev=1741469&view=auto ============================================================================== --- qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/QueryStore.js (added) +++ qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/QueryStore.js Thu Apr 28 16:22:56 2016 @@ -0,0 +1,162 @@ +/* + * + * 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/lang', + 'dojo/_base/declare', + "dojo/Evented", + "dojo/json", + 'dstore/Store', + 'dstore/QueryResults', + "dojo/Deferred" +], function (lang, declare, Evented, json, Store, QueryResults,Deferred) { + + return declare("qpid.management.query.QueryStore", [Store, Evented], { + + management: null, + selectClause: null, + where: null, + category: null, + parent: null, + useCachedResults: false, + zeroBased: true, + _lastHeaders: [], + _lastResponsePromise: null, + + fetch: function (kwArgs) { + return this._request(kwArgs); + }, + + fetchRange: function (kwArgs) { + return this._request(kwArgs); + }, + + _request: function (kwArgs) { + + + if (!this.selectClause) { + this._emitChangeHeadersIfNecessary([]); + var deferred = new Deferred(); + deferred.resolve([]); + return new QueryResults(deferred.promise); + } + + var queryRequest = { + category: this.category, + select: this.selectClause ? this.selectClause + ",id" : "id" + }; + + if (this.parent) { + queryRequest.parent = this.parent; + } + + if (this.where) { + queryRequest.where = this.where; + } + + if ("start" in kwArgs) { + queryRequest.offset = kwArgs.start; + } + + if ("end" in kwArgs) { + queryRequest.limit = kwArgs.end - (queryRequest.offset ? queryRequest.offset : 0); + } + + if (this.orderBy) { + queryRequest.orderBy = this.orderBy; + } + + if (this.useCachedResults) { + return this._createQueryResults(this._lastResponsePromise); + } + + var responsePromise = this.management.query(queryRequest); + responsePromise.then(lang.hitch(this, function(data) { + var headers = lang.clone(data.headers); + headers.pop(); + this._emitChangeHeadersIfNecessary(headers); + }), lang.hitch(this, function(error) { + this._emitChangeHeadersIfNecessary([]); + })); + + this._lastResponsePromise = responsePromise; + return this._createQueryResults(this._lastResponsePromise); + }, + + _createQueryResults: function(responsePromise) { + var that = this; + var queryResultData = { + data: responsePromise.then(function (data) { + var dataResults = data.results; + var results = []; + for (var i = 0, l = dataResults.length; i < l; ++i) { + var result = dataResults[i]; + var item = {id: result[result.length - 1]}; + + // excluding id, as we already added id field + for(var j = 0, rl = result.length - 1; j < rl ; ++j ){ + // sql uses 1-based index in ORDER BY + var field = this.zeroBased ? j : j + 1; + item[new String(field)] = result[j]; + } + results.push(item); + } + return results; + }, function(error) { + this.management.errorHandler(error); + return []; + }), + total: responsePromise.then(function (data) { + return data.total; + }, function(error) { + return 0; + }) + }; + return new QueryResults(queryResultData.data, { + totalLength: queryResultData.total + }); + }, + + _emitChangeHeadersIfNecessary: function (headers) { + if (!this._equalStringArrays(headers, this._lastHeaders)) { + this._lastHeaders = headers; + this.emit("changeHeaders", {headers: headers}); + } + }, + + // override from dstore.Store to not copy collection + _createSubCollection: function() { + return this; + }, + + _equalStringArrays: function(a, b) { + if (a.length != b.length) { + return false; + } + for (var i = 0; i < a.length; ++i) { + if (a[i] != b[i]) { + return false; + } + } + return true; + } + }); +}); Modified: qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/query/QueryBuilder.html URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/query/QueryBuilder.html?rev=1741469&r1=1741468&r2=1741469&view=diff ============================================================================== --- qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/query/QueryBuilder.html (original) +++ qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/query/QueryBuilder.html Thu Apr 28 16:22:56 2016 @@ -23,12 +23,12 @@ <label>Category : <span data-dojo-attach-point="categoryName"></span></label> <span data-dojo-attach-point="standardSearch"> <span data-dojo-type="qpid/management/query/DropDownSelect" - data-dojo-attach-point="selectColumnsButton" + data-dojo-attach-point="standardSelectChooser" data-dojo-props="title: 'Select fields to display',label:'Columns'"> </span> <span data-dojo-type="qpid/management/query/DropDownSelect" - data-dojo-attach-point="selectWhereButton" + data-dojo-attach-point="standardWhereChooser" data-dojo-props="title: 'Specify Filtering Conditions',label:'Conditions'"> </span> </span> @@ -40,13 +40,13 @@ data-dojo-props="title:'Switch to \'Advanced\' search using SQL-like expressions'" class="alignRight">Advanced</div> <div class="clear"></div> - <div data-dojo-attach-point="whereExpressionBuilder" + <div data-dojo-attach-point="standardWhereExpressionBuilder" data-dojo-type="qpid/management/query/WhereExpression" class="dijitToolbar"></div> <div data-dojo-attach-point="advancedSearch" style="display:none;"> <div class="advancedSearchItem"> <div class="advancedSearchLabel">Select :</div> <div class="advancedSearchField"> - <textarea data-dojo-attach-point="selectExpression" type="text" + <textarea data-dojo-attach-point="advancedSelect" type="text" data-dojo-type="dijit/form/SimpleTextarea" data-dojo-props=" name: 'select', rows: 1, @@ -59,13 +59,26 @@ <div class="advancedSearchItem"> <div class="advancedSearchLabel">Where : </div> <div class="advancedSearchField" > - <textarea data-dojo-attach-point="whereExpression" type="text" + <textarea data-dojo-attach-point="advancedWhere" type="text" data-dojo-type="dijit/form/SimpleTextarea" data-dojo-props=" name: 'where', rows: 1, intermediateChanges: true, placeHolder: 'where expression', - title: 'Enter sql like where conditions', + title: 'Enter where conditions using sql syntax', + promptMessage: 'Use JMS filter syntax to specify where conditions'" rows="1"></textarea> + </div> + </div> + <div class="advancedSearchItem"> + <div class="advancedSearchLabel">Order : </div> + <div class="advancedSearchField" > + <textarea data-dojo-attach-point="advancedOrderBy" type="text" + data-dojo-type="dijit/form/SimpleTextarea" + data-dojo-props=" name: 'orderBy', + rows: 1, + intermediateChanges: true, + placeHolder: 'order expression', + title: 'Enter order by conditions using sql syntax', promptMessage: 'Use JMS filter syntax to specify where conditions'" rows="1"></textarea> </div> </div> Modified: qpid/java/trunk/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/query/ConfiguredObjectQueryTest.java URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/query/ConfiguredObjectQueryTest.java?rev=1741469&r1=1741468&r2=1741469&view=diff ============================================================================== --- qpid/java/trunk/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/query/ConfiguredObjectQueryTest.java (original) +++ qpid/java/trunk/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/query/ConfiguredObjectQueryTest.java Thu Apr 28 16:22:56 2016 @@ -25,6 +25,7 @@ import static org.mockito.Mockito.when; import java.util.ArrayList; import java.util.Calendar; +import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.Iterator; @@ -96,6 +97,7 @@ public class ConfiguredObjectQueryTest e {{ put(ConfiguredObject.ID, object1Uuid); put(ConfiguredObject.NAME, object1Name); + put("foo", "bar"); }}); ConfiguredObject obj2 = createCO(new HashMap<String, Object>() @@ -147,6 +149,21 @@ public class ConfiguredObjectQueryTest e assertEquals("Unexpected row", Lists.newArrayList(objectUuid, 1234), row); } + public void testSelectClause_NonExistingColumn() throws Exception + { + ConfiguredObject obj = createCO(new HashMap<String, Object>() + {{ + put(ConfiguredObject.ID, UUID.randomUUID()); + }}); + _objects.add(obj); + + _query = new ConfiguredObjectQuery(_objects, String.format("foo"), null); + List<List<Object>> results = _query.getResults(); + assertEquals("Unexpected number of results", 1, results.size()); + assertEquals("Unexpected headers", Collections.singletonList("foo"), _query.getHeaders()); + assertEquals("Unexpected row", Collections.singletonList(null), results.get(0)); + } + public void testSelectClause_ColumnAliases() throws Exception { final UUID objectUuid = UUID.randomUUID(); @@ -459,6 +476,185 @@ public class ConfiguredObjectQueryTest e } } + public void testSingleOrderByClause() throws Exception + { + final int NUMBER_OF_OBJECTS = 3; + + for (int i = 0; i < NUMBER_OF_OBJECTS; ++i) + { + final int foo = (i + 1) % NUMBER_OF_OBJECTS; + ConfiguredObject object = createCO(new HashMap<String, Object>() + {{ + put("foo", foo); + }}); + _objects.add(object); + } + + ConfiguredObject object = createCO(new HashMap<String, Object>() + {{ + put("foo", null); + }}); + _objects.add(object); + + List<List<Object>> results; + + _query = new ConfiguredObjectQuery(_objects, "foo", null, "foo ASC"); + results = _query.getResults(); + assertQueryResults(new Object[][]{{null}, {0}, {1}, {2}}, results); + + _query = new ConfiguredObjectQuery(_objects, "foo", null, "foo DESC"); + results = _query.getResults(); + assertQueryResults(new Object[][]{{2}, {1}, {0}, {null}}, results); + + // if not specified order should be ASC + _query = new ConfiguredObjectQuery(_objects, "foo", null, "foo"); + results = _query.getResults(); + assertQueryResults(new Object[][]{{null}, {0}, {1}, {2}}, results); + } + + public void testTwoOrderByClauses() throws Exception + { + ConfiguredObject object; + + object = createCO(new HashMap<String, Object>() + {{ + put("foo", 1); + put("bar", 1); + }}); + _objects.add(object); + + object = createCO(new HashMap<String, Object>() + {{ + put("foo", 1); + put("bar", 2); + }}); + _objects.add(object); + + object = createCO(new HashMap<String, Object>() + {{ + put("foo", 2); + put("bar", 0); + }}); + _objects.add(object); + + _query = new ConfiguredObjectQuery(_objects, "foo,bar", null, "foo, bar"); + assertQueryResults(new Object[][]{{1, 1}, {1, 2}, {2, 0}}, _query.getResults()); + + _query = new ConfiguredObjectQuery(_objects, "foo,bar", null, "foo DESC, bar"); + assertQueryResults(new Object[][]{{2, 0}, {1, 1}, {1, 2}}, _query.getResults()); + + _query = new ConfiguredObjectQuery(_objects, "foo,bar", null, "foo DESC, bar DESC"); + assertQueryResults(new Object[][]{{2, 0}, {1, 2}, {1, 1}}, _query.getResults()); + + _query = new ConfiguredObjectQuery(_objects, "foo,bar", null, "foo, bar DESC"); + assertQueryResults(new Object[][]{{1, 2}, {1, 1}, {2, 0}}, _query.getResults()); + + _query = new ConfiguredObjectQuery(_objects, "foo,bar", null, "bar, foo"); + assertQueryResults(new Object[][]{{2, 0}, {1, 1}, {1, 2}}, _query.getResults()); + + _query = new ConfiguredObjectQuery(_objects, "foo,bar", null, "bar DESC, foo"); + assertQueryResults(new Object[][]{{1, 2}, {1, 1}, {2, 0}}, _query.getResults()); + + _query = new ConfiguredObjectQuery(_objects, "foo,bar", null, "bar, foo DESC"); + assertQueryResults(new Object[][]{{2, 0}, {1, 1}, {1, 2}}, _query.getResults()); + + _query = new ConfiguredObjectQuery(_objects, "foo,bar", null, "bar DESC, foo DESC"); + assertQueryResults(new Object[][]{{1, 2}, {1, 1}, {2, 0}}, _query.getResults()); + + _query = new ConfiguredObjectQuery(_objects, "foo,bar", null, "boo DESC, foo DESC, bar"); + assertQueryResults(new Object[][]{{2, 0}, {1, 1}, {1, 2}}, _query.getResults()); + + _query = new ConfiguredObjectQuery(_objects, "foo, bar", null, "1, 2"); + assertQueryResults(new Object[][]{{1, 1}, {1, 2}, {2, 0}}, _query.getResults()); + + _query = new ConfiguredObjectQuery(_objects, "foo, bar", null, "2, 1"); + assertQueryResults(new Object[][]{{2, 0}, {1, 1}, {1, 2}}, _query.getResults()); + + _query = new ConfiguredObjectQuery(_objects, "foo, bar", null, "foo, 2 DESC"); + assertQueryResults(new Object[][]{{1, 2}, {1, 1}, {2, 0}}, _query.getResults()); + } + + public void testOrderByWithInvalidColumnIndex() + { + try + { + new ConfiguredObjectQuery(_objects, "id", null, "2"); + fail("Exception is expected for column index out of bounds"); + } + catch (EvaluationException e) + { + // pass + } + + try + { + new ConfiguredObjectQuery(_objects, "id", null, "0 DESC"); + fail("Exception is expected for column index 0"); + } + catch (EvaluationException e) + { + // pass + } + } + + + public void testLimitWithoutOffset() throws Exception + { + int numberOfTestObjects = 3; + for(int i=0;i<numberOfTestObjects;i++) + { + final String name = "test-" + i; + ConfiguredObject object = createCO(new HashMap<String, Object>() + {{ + put("name", name); + }}); + _objects.add(object); + } + + _query = new ConfiguredObjectQuery(_objects, "name", null, "name", "1", "0"); + assertQueryResults(new Object[][]{{"test-0"}}, _query.getResults()); + + _query = new ConfiguredObjectQuery(_objects, "name", null, "name", "1", "1"); + assertQueryResults(new Object[][]{{"test-1"}}, _query.getResults()); + + _query = new ConfiguredObjectQuery(_objects, "name", null, "name", "1", "3"); + assertQueryResults(new Object[0][1], _query.getResults()); + + _query = new ConfiguredObjectQuery(_objects, "name", null, "name", "-1", "1"); + assertQueryResults(new Object[][]{{"test-1"},{"test-2"}}, _query.getResults()); + + _query = new ConfiguredObjectQuery(_objects, "name", null, "name", "-1", "-4"); + assertQueryResults(new Object[][]{{"test-0"},{"test-1"},{"test-2"}}, _query.getResults()); + + _query = new ConfiguredObjectQuery(_objects, "name", null, "name", "-1", "-2"); + assertQueryResults(new Object[][]{{"test-1"},{"test-2"}}, _query.getResults()); + + _query = new ConfiguredObjectQuery(_objects, "name", null, "name", "invalidLimit", "invalidOffset"); + assertQueryResults(new Object[][]{{"test-0"},{"test-1"},{"test-2"}}, _query.getResults()); + + _query = new ConfiguredObjectQuery(_objects, "name", null, "name", null, null); + assertQueryResults(new Object[][]{{"test-0"},{"test-1"},{"test-2"}}, _query.getResults()); + } + + private void assertQueryResults(final Object[][] expectedAttributes, + final List<List<Object>> results) + { + final int rows = expectedAttributes.length; + assertEquals("Unexpected number of result rows", rows, results.size()); + if (rows > 0) + { + final int cols = expectedAttributes[0].length; + for (int row = 0; row < rows; ++row) + { + assertEquals("Unexpected number of result columns", cols, results.get(row).size()); + for (int col = 0; col < cols; ++col) + { + assertEquals("Unexpected row order", expectedAttributes[row][col], results.get(row).get(col)); + } + } + } + } + private ConfiguredObject createCO(final HashMap<String, Object> map) { ConfiguredObject object = mock(ConfiguredObject.class); --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
