From b2eb4f11fd71cadca6e63d027b02f0477b7c5148 Mon Sep 17 00:00:00 2001 From: Stas Vilchik Date: Wed, 9 Nov 2016 14:03:23 +0100 Subject: [PATCH] SONAR-8374 Make the "Me" option more visible on the "Issues" page --- .../src/main/js/apps/component-issues/app.js | 6 ++ .../src/main/js/apps/issues/HeaderView.js | 61 +++++++++++++++++++ .../sonar-web/src/main/js/apps/issues/app.js | 6 ++ .../src/main/js/apps/issues/controller.js | 48 ++------------- .../js/apps/issues/facets/assignee-facet.js | 11 ++-- .../main/js/apps/issues/facets/mode-facet.js | 13 ++-- .../src/main/js/apps/issues/layout.js | 6 +- .../src/main/js/apps/issues/styles.css | 16 +++++ .../facets/issues-assignee-facet.hbs | 10 --- .../templates/facets/issues-mode-facet.hbs | 27 ++++---- .../facets/issues-my-issues-facet.hbs | 12 ++++ .../apps/issues/templates/issues-layout.hbs | 4 +- .../resources/org/sonar/l10n/core.properties | 1 + 13 files changed, 133 insertions(+), 88 deletions(-) create mode 100644 server/sonar-web/src/main/js/apps/issues/HeaderView.js create mode 100644 server/sonar-web/src/main/js/apps/issues/styles.css create mode 100644 server/sonar-web/src/main/js/apps/issues/templates/facets/issues-my-issues-facet.hbs diff --git a/server/sonar-web/src/main/js/apps/component-issues/app.js b/server/sonar-web/src/main/js/apps/component-issues/app.js index 7768330dd43..7397e84eed9 100644 --- a/server/sonar-web/src/main/js/apps/component-issues/app.js +++ b/server/sonar-web/src/main/js/apps/component-issues/app.js @@ -30,6 +30,7 @@ import Router from '../issues/router'; import WorkspaceListView from '../issues/workspace-list-view'; import WorkspaceHeaderView from '../issues/workspace-header-view'; import FacetsView from './../issues/facets-view'; +import HeaderView from './../issues/HeaderView'; const App = new Marionette.Application(); const init = function () { @@ -73,6 +74,11 @@ const init = function () { }); this.layout.facetsRegion.show(this.facetsView); + this.headerView = new HeaderView({ + app: this + }); + this.layout.filtersRegion.show(this.headerView); + key.setScope('list'); App.router = new Router({ app: App }); Backbone.history.start(); diff --git a/server/sonar-web/src/main/js/apps/issues/HeaderView.js b/server/sonar-web/src/main/js/apps/issues/HeaderView.js new file mode 100644 index 00000000000..01d6e6cc546 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/HeaderView.js @@ -0,0 +1,61 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import Marionette from 'backbone.marionette'; +import Template from './templates/facets/issues-my-issues-facet.hbs'; + +export default Marionette.ItemView.extend({ + template: Template, + className: 'issues-header-inner', + + events: { + 'change [name="issues-page-my"]': 'onMyIssuesChange' + }, + + initialize () { + this.listenTo(this.options.app.state, 'change:query', this.render); + }, + + onMyIssuesChange () { + const mode = this.$('[name="issues-page-my"]:checked').val(); + if (mode === 'my') { + this.options.app.state.updateFilter({ + assigned_to_me: 'true', + assignees: null, + assigned: null + }); + } else { + this.options.app.state.updateFilter({ + assigned_to_me: null, + assignees: null, + assigned: null + }); + } + }, + serializeData () { + const me = !!this.options.app.state.get('query').assigned_to_me; + return { + ...Marionette.ItemView.prototype.serializeData.apply(this, arguments), + me, + isContext: this.options.app.state.get('isContext'), + user: window.SS.user + }; + } +}); + diff --git a/server/sonar-web/src/main/js/apps/issues/app.js b/server/sonar-web/src/main/js/apps/issues/app.js index bc083906618..4623b55988f 100644 --- a/server/sonar-web/src/main/js/apps/issues/app.js +++ b/server/sonar-web/src/main/js/apps/issues/app.js @@ -29,6 +29,7 @@ import Router from './router'; import WorkspaceListView from './workspace-list-view'; import WorkspaceHeaderView from './workspace-header-view'; import FacetsView from './facets-view'; +import HeaderView from './HeaderView'; const App = new Marionette.Application(); const init = function () { @@ -63,6 +64,11 @@ const init = function () { }); this.layout.facetsRegion.show(this.facetsView); + this.headerView = new HeaderView({ + app: this + }); + this.layout.filtersRegion.show(this.headerView); + key.setScope('list'); App.router = new Router({ app: App }); Backbone.history.start(); diff --git a/server/sonar-web/src/main/js/apps/issues/controller.js b/server/sonar-web/src/main/js/apps/issues/controller.js index aa5d45d3d00..11512cd4c48 100644 --- a/server/sonar-web/src/main/js/apps/issues/controller.js +++ b/server/sonar-web/src/main/js/apps/issues/controller.js @@ -26,14 +26,6 @@ import ComponentViewer from './component-viewer/main'; const FACET_DATA_FIELDS = ['components', 'users', 'rules', 'languages']; export default Controller.extend({ - _facetsFromServer () { - const facets = Controller.prototype._facetsFromServer.apply(this, arguments) || []; - if (facets.indexOf('assignees') !== -1) { - facets.push('assigned_to_me'); - } - return facets; - }, - _issuesParameters () { return { p: this.options.app.state.get('page'), @@ -45,15 +37,6 @@ export default Controller.extend({ }; }, - _myIssuesFromResponse (r) { - const myIssuesData = _.findWhere(r.facets, { property: 'assigned_to_me' }); - if ((myIssuesData != null) && _.isArray(myIssuesData.values) && myIssuesData.values.length > 0) { - return this.options.app.state.set({ myIssues: myIssuesData.values[0].count }, { silent: true }); - } else { - return this.options.app.state.unset('myIssues', { silent: true }); - } - }, - fetchList (firstPage) { const that = this; if (firstPage == null) { @@ -65,6 +48,9 @@ export default Controller.extend({ } const data = this._issuesParameters(); _.extend(data, this.options.app.state.get('query')); + if (this.options.app.state.get('query').assigned_to_me) { + _.extend(data, { assignees: '__me__' }); + } if (this.options.app.state.get('isContext')) { _.extend(data, this.options.app.state.get('contextQuery')); } @@ -80,10 +66,7 @@ export default Controller.extend({ that.options.app.facets[field] = r[field]; }); that.options.app.facets.reset(that._allFacets()); - that.options.app.facets.add(_.reject(r.facets, function (f) { - return f.property === 'assigned_to_me'; - }), { merge: true }); - that._myIssuesFromResponse(r); + that.options.app.facets.add(r.facets, { merge: true }); that.enableFacets(that._enabledFacets()); if (firstPage) { that.options.app.state.set({ @@ -117,9 +100,6 @@ export default Controller.extend({ requestFacet (id) { const that = this; - if (id === 'assignees') { - return this.requestAssigneeFacet(); - } const facet = this.options.app.facets.get(id); const data = _.extend({ facets: id, ps: 1, additionalFields: '_all' }, this.options.app.state.get('query')); if (this.options.app.state.get('isContext')) { @@ -136,26 +116,6 @@ export default Controller.extend({ }); }, - requestAssigneeFacet () { - const that = this; - const facet = this.options.app.facets.get('assignees'); - const data = _.extend({ facets: 'assignees,assigned_to_me', ps: 1, additionalFields: '_all' }, - this.options.app.state.get('query')); - if (this.options.app.state.get('isContext')) { - _.extend(data, this.options.app.state.get('contextQuery')); - } - return $.get(window.baseUrl + '/api/issues/search', data, function (r) { - FACET_DATA_FIELDS.forEach(function (field) { - that.options.app.facets[field] = that._mergeCollections(that.options.app.facets[field], r[field]); - }); - const facetData = _.findWhere(r.facets, { property: 'assignees' }); - that._myIssuesFromResponse(r); - if (facetData != null) { - return facet.set(facetData); - } - }); - }, - newSearch () { this.options.app.state.unset('filter'); return this.options.app.state.setQuery({ resolved: 'false' }); diff --git a/server/sonar-web/src/main/js/apps/issues/facets/assignee-facet.js b/server/sonar-web/src/main/js/apps/issues/facets/assignee-facet.js index f67204b3278..bea677a4290 100644 --- a/server/sonar-web/src/main/js/apps/issues/facets/assignee-facet.js +++ b/server/sonar-web/src/main/js/apps/issues/facets/assignee-facet.js @@ -56,12 +56,14 @@ export default CustomValuesFacet.extend({ const value = checked ? 'false' : null; return this.options.app.state.updateFilter({ assigned: value, - assignees: null + assignees: null, + assigned_to_me: null }); } else { return this.options.app.state.updateFilter({ assigned: null, - assignees: this.getValue() + assignees: this.getValue(), + assigned_to_me: null }); } }, @@ -110,13 +112,8 @@ export default CustomValuesFacet.extend({ }); }, - getNumberOfMyIssues () { - return this.options.app.state.get('myIssues'); - }, - serializeData () { return _.extend(CustomValuesFacet.prototype.serializeData.apply(this, arguments), { - myIssues: this.getNumberOfMyIssues(), values: this.sortValues(this.getValuesWithLabels()) }); } diff --git a/server/sonar-web/src/main/js/apps/issues/facets/mode-facet.js b/server/sonar-web/src/main/js/apps/issues/facets/mode-facet.js index 5b4ca34ced7..8612111c2e4 100644 --- a/server/sonar-web/src/main/js/apps/issues/facets/mode-facet.js +++ b/server/sonar-web/src/main/js/apps/issues/facets/mode-facet.js @@ -17,6 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import $ from 'jquery'; import _ from 'underscore'; import BaseFacet from './base-facet'; import Template from '../templates/facets/issues-mode-facet.hbs'; @@ -24,13 +25,11 @@ import Template from '../templates/facets/issues-mode-facet.hbs'; export default BaseFacet.extend({ template: Template, - events: { - 'change [name="issues-page-mode"]': 'onModeChange' - }, - - onModeChange () { - const mode = this.$('[name="issues-page-mode"]:checked').val(); - this.options.app.state.updateFilter({ facetMode: mode }); + toggleFacet (e) { + const isCount = $(e.currentTarget).is('[data-value="count"]'); + return this.options.app.state.updateFilter({ + facetMode: isCount ? 'count' : 'effort' + }); }, serializeData () { diff --git a/server/sonar-web/src/main/js/apps/issues/layout.js b/server/sonar-web/src/main/js/apps/issues/layout.js index 1b36f36c231..3eeb76f0188 100644 --- a/server/sonar-web/src/main/js/apps/issues/layout.js +++ b/server/sonar-web/src/main/js/apps/issues/layout.js @@ -21,12 +21,13 @@ import $ from 'jquery'; import _ from 'underscore'; import Marionette from 'backbone.marionette'; import Template from './templates/issues-layout.hbs'; +import './styles.css'; export default Marionette.LayoutView.extend({ template: Template, regions: { - filtersRegion: '.search-navigator-filters', + filtersRegion: '.issues-header', facetsRegion: '.search-navigator-facets', workspaceHeaderRegion: '.search-navigator-workspace-header', workspaceListRegion: '.search-navigator-workspace-list', @@ -34,9 +35,6 @@ export default Marionette.LayoutView.extend({ }, onRender () { - if (this.options.app.state.get('isContext')) { - this.$(this.filtersRegion.el).addClass('hidden'); - } this.$('.search-navigator').addClass('sticky'); const top = this.$('.search-navigator').offset().top; this.$('.search-navigator-workspace-header').css({ top }); diff --git a/server/sonar-web/src/main/js/apps/issues/styles.css b/server/sonar-web/src/main/js/apps/issues/styles.css new file mode 100644 index 00000000000..5534dc2e508 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/styles.css @@ -0,0 +1,16 @@ +.issues-header-inner { + padding: 32px 10px 15px; + background-color: #f3f3f3; + text-align: center; +} + +.issues-header-inner:empty { + display: none; +} + +.issues-header-order { + display: inline-block; + vertical-align: top; + margin-right: 20px; + font-size: 12px; +} diff --git a/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-assignee-facet.hbs b/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-assignee-facet.hbs index 4121c2eee5c..9fb23f78ab8 100644 --- a/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-assignee-facet.hbs +++ b/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-assignee-facet.hbs @@ -1,16 +1,6 @@ {{> "_issues-facet-header"}}
- {{#notNull myIssues}} - - {{t "me"}} - - {{formatFacetValue myIssues state.facetMode}} - - -
- {{/notNull}} - {{#each values}} {{#eq val ""}} {{! unassigned }} diff --git a/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-mode-facet.hbs b/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-mode-facet.hbs index 26dc6a0a5ab..af69286d92a 100644 --- a/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-mode-facet.hbs +++ b/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-mode-facet.hbs @@ -1,14 +1,15 @@ -
-
    -
  • - - -
  • -
  • - - -
  • -
+
+ {{t 'issues.facet.mode'}} +
+ + + diff --git a/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-my-issues-facet.hbs b/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-my-issues-facet.hbs new file mode 100644 index 00000000000..ce38e1f7f64 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-my-issues-facet.hbs @@ -0,0 +1,12 @@ +{{#if user}} +
    +
  • + + +
  • +
  • + + +
  • +
+{{/if}} diff --git a/server/sonar-web/src/main/js/apps/issues/templates/issues-layout.hbs b/server/sonar-web/src/main/js/apps/issues/templates/issues-layout.hbs index 393845b0394..83add61b366 100644 --- a/server/sonar-web/src/main/js/apps/issues/templates/issues-layout.hbs +++ b/server/sonar-web/src/main/js/apps/issues/templates/issues-layout.hbs @@ -1,8 +1,6 @@
-
-

{{t "issues"}}

-
+
diff --git a/sonar-core/src/main/resources/org/sonar/l10n/core.properties b/sonar-core/src/main/resources/org/sonar/l10n/core.properties index 7fd2e16ce66..51f92174704 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -773,6 +773,7 @@ issues.facet.createdAt.last_month=Last month issues.facet.createdAt.last_year=Last year issues.facet.authors=Author issues.facet.issues=Issue Key +issues.facet.mode=Display Mode issues.facet.mode.issues=Issues issues.facet.mode.effort=Effort -- 2.39.5