From 8d3e45ed0c33cbf63b9c44be5b2c2f9e0dad9a50 Mon Sep 17 00:00:00 2001 From: Stas Vilchik Date: Mon, 1 Jun 2015 13:53:12 +0200 Subject: [PATCH] move issues page from coffee to js --- server/sonar-web/Gruntfile.coffee | 19 +- .../coffee/apps/issues/app-context.coffee | 131 --------- .../main/coffee/apps/issues/app-new.coffee | 109 -------- .../issues/component-viewer/issue-view.coffee | 36 --- .../apps/issues/component-viewer/main.coffee | 192 -------------- .../main/coffee/apps/issues/controller.coffee | 225 ---------------- .../coffee/apps/issues/facets-view.coffee | 83 ------ .../issues/facets/action-plan-facet.coffee | 72 ----- .../apps/issues/facets/assignee-facet.coffee | 105 -------- .../apps/issues/facets/author-facet.coffee | 47 ---- .../apps/issues/facets/base-facet.coffee | 37 --- .../apps/issues/facets/context-facet.coffee | 35 --- .../issues/facets/creation-date-facet.coffee | 141 ---------- .../issues/facets/custom-values-facet.coffee | 71 ----- .../apps/issues/facets/file-facet.coffee | 56 ---- .../apps/issues/facets/issue-key-facet.coffee | 43 --- .../apps/issues/facets/language-facet.coffee | 67 ----- .../apps/issues/facets/module-facet.coffee | 44 ---- .../apps/issues/facets/project-facet.coffee | 83 ------ .../apps/issues/facets/reporter-facet.coffee | 54 ---- .../issues/facets/resolution-facet.coffee | 61 ----- .../apps/issues/facets/rule-facet.coffee | 71 ----- .../apps/issues/facets/severity-facet.coffee | 36 --- .../apps/issues/facets/status-facet.coffee | 35 --- .../apps/issues/facets/tag-facet.coffee | 63 ----- .../coffee/apps/issues/filters-view.coffee | 97 ------- .../apps/issues/issue-filter-view.coffee | 47 ---- .../src/main/coffee/apps/issues/layout.coffee | 69 ----- .../coffee/apps/issues/models/facet.coffee | 37 --- .../coffee/apps/issues/models/facets.coffee | 28 -- .../coffee/apps/issues/models/filter.coffee | 30 --- .../coffee/apps/issues/models/filters.coffee | 28 -- .../coffee/apps/issues/models/issues.coffee | 80 ------ .../coffee/apps/issues/models/state.coffee | 47 ---- .../src/main/coffee/apps/issues/router.coffee | 58 ---- .../templates/facets/_issues-facet-header.hbs | 4 - .../facets/issues-action-plan-facet.hbs | 18 -- .../facets/issues-assignee-facet.hbs | 30 --- .../templates/facets/issues-base-facet.hbs | 10 - .../facets/issues-creation-date-facet.hbs | 32 --- .../facets/issues-custom-values-facet.hbs | 14 - .../templates/facets/issues-file-facet.hbs | 10 - .../facets/issues-issue-key-facet.hbs | 7 - .../facets/issues-resolution-facet.hbs | 20 -- .../facets/issues-severity-facet.hbs | 11 - .../templates/facets/issues-status-facet.hbs | 11 - .../apps/issues/templates/issues-filters.hbs | 55 ---- .../templates/issues-issue-filter-form.hbs | 71 ----- .../issues/templates/issues-issue-filter.hbs | 5 - .../apps/issues/templates/issues-layout.hbs | 11 - .../templates/issues-workspace-header.hbs | 37 --- .../templates/issues-workspace-home.hbs | 77 ------ .../issues-workspace-list-component.hbs | 13 - .../templates/issues-workspace-list.hbs | 5 - .../apps/issues/workspace-header-view.coffee | 64 ----- .../apps/issues/workspace-home-view.coffee | 149 ----------- .../issues/workspace-list-empty-view.coffee | 28 -- .../issues/workspace-list-item-view.coffee | 118 --------- .../apps/issues/workspace-list-view.coffee | 103 -------- .../src/main/js/apps/issues/app-context.js | 105 ++++++++ .../src/main/js/apps/issues/app-new.js | 82 ++++++ .../issues/component-viewer/issue-view.js | 18 ++ .../js/apps/issues/component-viewer/main.js | 204 ++++++++++++++ .../src/main/js/apps/issues/controller.js | 249 ++++++++++++++++++ .../src/main/js/apps/issues/facets-view.js | 65 +++++ .../apps/issues/facets/action-plan-facet.js | 68 +++++ .../js/apps/issues/facets/assignee-facet.js | 108 ++++++++ .../js/apps/issues/facets/author-facet.js | 44 ++++ .../main/js/apps/issues/facets/base-facet.js | 19 ++ .../js/apps/issues/facets/context-facet.js | 16 ++ .../apps/issues/facets/creation-date-facet.js | 131 +++++++++ .../apps/issues/facets/custom-values-facet.js | 70 +++++ .../main/js/apps/issues/facets/file-facet.js | 43 +++ .../js/apps/issues/facets/issue-key-facet.js | 24 ++ .../js/apps/issues/facets/language-facet.js | 67 +++++ .../js/apps/issues/facets/module-facet.js | 30 +++ .../js/apps/issues/facets/project-facet.js | 83 ++++++ .../js/apps/issues/facets/reporter-facet.js | 46 ++++ .../js/apps/issues/facets/resolution-facet.js | 52 ++++ .../main/js/apps/issues/facets/rule-facet.js | 78 ++++++ .../js/apps/issues/facets/severity-facet.js | 17 ++ .../js/apps/issues/facets/status-facet.js | 17 ++ .../main/js/apps/issues/facets/tag-facet.js | 56 ++++ .../src/main/js/apps/issues/filters-view.js | 93 +++++++ .../main/js/apps/issues/issue-filter-view.js | 29 ++ .../src/main/js/apps/issues/layout.js | 55 ++++ .../src/main/js/apps/issues/models/facet.js | 20 ++ .../src/main/js/apps/issues/models/facets.js | 9 + .../src/main/js/apps/issues/models/filter.js | 17 ++ .../src/main/js/apps/issues/models/filters.js | 9 + .../src/main/js/apps/issues/models/issues.js | 65 +++++ .../src/main/js/apps/issues/models/state.js | 58 ++++ .../src/main/js/apps/issues/router.js | 45 ++++ .../issues/templates/_issues-filter-name.hbs | 2 +- .../templates/facets/_issues-facet-header.hbs | 4 + .../facets/issues-action-plan-facet.hbs | 18 ++ .../facets/issues-assignee-facet.hbs | 30 +++ .../templates/facets/issues-base-facet.hbs | 10 + .../templates/facets/issues-context-facet.hbs | 2 +- .../facets/issues-creation-date-facet.hbs | 32 +++ .../facets/issues-custom-values-facet.hbs | 14 + .../templates/facets/issues-file-facet.hbs | 10 + .../facets/issues-issue-key-facet.hbs | 7 + .../facets/issues-resolution-facet.hbs | 20 ++ .../facets/issues-severity-facet.hbs | 11 + .../templates/facets/issues-status-facet.hbs | 11 + .../apps/issues/templates/issues-filters.hbs | 55 ++++ .../templates/issues-issue-filter-form.hbs | 71 +++++ .../issues/templates/issues-issue-filter.hbs | 5 + .../apps/issues/templates/issues-layout.hbs | 11 + .../templates/issues-workspace-header.hbs | 37 +++ .../templates/issues-workspace-home.hbs | 77 ++++++ .../issues-workspace-list-component.hbs | 13 + .../templates/issues-workspace-list.hbs | 5 + .../js/apps/issues/workspace-header-view.js | 47 ++++ .../js/apps/issues/workspace-home-view.js | 160 +++++++++++ .../apps/issues/workspace-list-empty-view.js | 11 + .../apps/issues/workspace-list-item-view.js | 113 ++++++++ .../js/apps/issues/workspace-list-view.js | 106 ++++++++ 119 files changed, 2974 insertions(+), 3340 deletions(-) delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/app-context.coffee delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/app-new.coffee delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/component-viewer/issue-view.coffee delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/component-viewer/main.coffee delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/controller.coffee delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/facets-view.coffee delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/facets/action-plan-facet.coffee delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/facets/assignee-facet.coffee delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/facets/author-facet.coffee delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/facets/base-facet.coffee delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/facets/context-facet.coffee delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/facets/creation-date-facet.coffee delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/facets/custom-values-facet.coffee delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/facets/file-facet.coffee delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/facets/issue-key-facet.coffee delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/facets/language-facet.coffee delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/facets/module-facet.coffee delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/facets/project-facet.coffee delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/facets/reporter-facet.coffee delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/facets/resolution-facet.coffee delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/facets/rule-facet.coffee delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/facets/severity-facet.coffee delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/facets/status-facet.coffee delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/facets/tag-facet.coffee delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/filters-view.coffee delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/issue-filter-view.coffee delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/layout.coffee delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/models/facet.coffee delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/models/facets.coffee delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/models/filter.coffee delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/models/filters.coffee delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/models/issues.coffee delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/models/state.coffee delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/router.coffee delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/templates/facets/_issues-facet-header.hbs delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/templates/facets/issues-action-plan-facet.hbs delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/templates/facets/issues-assignee-facet.hbs delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/templates/facets/issues-base-facet.hbs delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/templates/facets/issues-creation-date-facet.hbs delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/templates/facets/issues-custom-values-facet.hbs delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/templates/facets/issues-file-facet.hbs delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/templates/facets/issues-issue-key-facet.hbs delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/templates/facets/issues-resolution-facet.hbs delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/templates/facets/issues-severity-facet.hbs delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/templates/facets/issues-status-facet.hbs delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/templates/issues-filters.hbs delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/templates/issues-issue-filter-form.hbs delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/templates/issues-issue-filter.hbs delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/templates/issues-layout.hbs delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/templates/issues-workspace-header.hbs delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/templates/issues-workspace-home.hbs delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/templates/issues-workspace-list-component.hbs delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/templates/issues-workspace-list.hbs delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/workspace-header-view.coffee delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/workspace-home-view.coffee delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/workspace-list-empty-view.coffee delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/workspace-list-item-view.coffee delete mode 100644 server/sonar-web/src/main/coffee/apps/issues/workspace-list-view.coffee create mode 100644 server/sonar-web/src/main/js/apps/issues/app-context.js create mode 100644 server/sonar-web/src/main/js/apps/issues/app-new.js create mode 100644 server/sonar-web/src/main/js/apps/issues/component-viewer/issue-view.js create mode 100644 server/sonar-web/src/main/js/apps/issues/component-viewer/main.js create mode 100644 server/sonar-web/src/main/js/apps/issues/controller.js create mode 100644 server/sonar-web/src/main/js/apps/issues/facets-view.js create mode 100644 server/sonar-web/src/main/js/apps/issues/facets/action-plan-facet.js create mode 100644 server/sonar-web/src/main/js/apps/issues/facets/assignee-facet.js create mode 100644 server/sonar-web/src/main/js/apps/issues/facets/author-facet.js create mode 100644 server/sonar-web/src/main/js/apps/issues/facets/base-facet.js create mode 100644 server/sonar-web/src/main/js/apps/issues/facets/context-facet.js create mode 100644 server/sonar-web/src/main/js/apps/issues/facets/creation-date-facet.js create mode 100644 server/sonar-web/src/main/js/apps/issues/facets/custom-values-facet.js create mode 100644 server/sonar-web/src/main/js/apps/issues/facets/file-facet.js create mode 100644 server/sonar-web/src/main/js/apps/issues/facets/issue-key-facet.js create mode 100644 server/sonar-web/src/main/js/apps/issues/facets/language-facet.js create mode 100644 server/sonar-web/src/main/js/apps/issues/facets/module-facet.js create mode 100644 server/sonar-web/src/main/js/apps/issues/facets/project-facet.js create mode 100644 server/sonar-web/src/main/js/apps/issues/facets/reporter-facet.js create mode 100644 server/sonar-web/src/main/js/apps/issues/facets/resolution-facet.js create mode 100644 server/sonar-web/src/main/js/apps/issues/facets/rule-facet.js create mode 100644 server/sonar-web/src/main/js/apps/issues/facets/severity-facet.js create mode 100644 server/sonar-web/src/main/js/apps/issues/facets/status-facet.js create mode 100644 server/sonar-web/src/main/js/apps/issues/facets/tag-facet.js create mode 100644 server/sonar-web/src/main/js/apps/issues/filters-view.js create mode 100644 server/sonar-web/src/main/js/apps/issues/issue-filter-view.js create mode 100644 server/sonar-web/src/main/js/apps/issues/layout.js create mode 100644 server/sonar-web/src/main/js/apps/issues/models/facet.js create mode 100644 server/sonar-web/src/main/js/apps/issues/models/facets.js create mode 100644 server/sonar-web/src/main/js/apps/issues/models/filter.js create mode 100644 server/sonar-web/src/main/js/apps/issues/models/filters.js create mode 100644 server/sonar-web/src/main/js/apps/issues/models/issues.js create mode 100644 server/sonar-web/src/main/js/apps/issues/models/state.js create mode 100644 server/sonar-web/src/main/js/apps/issues/router.js rename server/sonar-web/src/main/{coffee => js}/apps/issues/templates/_issues-filter-name.hbs (92%) create mode 100644 server/sonar-web/src/main/js/apps/issues/templates/facets/_issues-facet-header.hbs create mode 100644 server/sonar-web/src/main/js/apps/issues/templates/facets/issues-action-plan-facet.hbs create mode 100644 server/sonar-web/src/main/js/apps/issues/templates/facets/issues-assignee-facet.hbs create mode 100644 server/sonar-web/src/main/js/apps/issues/templates/facets/issues-base-facet.hbs rename server/sonar-web/src/main/{coffee => js}/apps/issues/templates/facets/issues-context-facet.hbs (73%) create mode 100644 server/sonar-web/src/main/js/apps/issues/templates/facets/issues-creation-date-facet.hbs create mode 100644 server/sonar-web/src/main/js/apps/issues/templates/facets/issues-custom-values-facet.hbs create mode 100644 server/sonar-web/src/main/js/apps/issues/templates/facets/issues-file-facet.hbs create mode 100644 server/sonar-web/src/main/js/apps/issues/templates/facets/issues-issue-key-facet.hbs create mode 100644 server/sonar-web/src/main/js/apps/issues/templates/facets/issues-resolution-facet.hbs create mode 100644 server/sonar-web/src/main/js/apps/issues/templates/facets/issues-severity-facet.hbs create mode 100644 server/sonar-web/src/main/js/apps/issues/templates/facets/issues-status-facet.hbs create mode 100644 server/sonar-web/src/main/js/apps/issues/templates/issues-filters.hbs create mode 100644 server/sonar-web/src/main/js/apps/issues/templates/issues-issue-filter-form.hbs create mode 100644 server/sonar-web/src/main/js/apps/issues/templates/issues-issue-filter.hbs create mode 100644 server/sonar-web/src/main/js/apps/issues/templates/issues-layout.hbs create mode 100644 server/sonar-web/src/main/js/apps/issues/templates/issues-workspace-header.hbs create mode 100644 server/sonar-web/src/main/js/apps/issues/templates/issues-workspace-home.hbs create mode 100644 server/sonar-web/src/main/js/apps/issues/templates/issues-workspace-list-component.hbs create mode 100644 server/sonar-web/src/main/js/apps/issues/templates/issues-workspace-list.hbs create mode 100644 server/sonar-web/src/main/js/apps/issues/workspace-header-view.js create mode 100644 server/sonar-web/src/main/js/apps/issues/workspace-home-view.js create mode 100644 server/sonar-web/src/main/js/apps/issues/workspace-list-empty-view.js create mode 100644 server/sonar-web/src/main/js/apps/issues/workspace-list-item-view.js create mode 100644 server/sonar-web/src/main/js/apps/issues/workspace-list-view.js diff --git a/server/sonar-web/Gruntfile.coffee b/server/sonar-web/Gruntfile.coffee index 2339f6fe636..ff402d13cb0 100644 --- a/server/sonar-web/Gruntfile.coffee +++ b/server/sonar-web/Gruntfile.coffee @@ -35,17 +35,6 @@ module.exports = (grunt) -> ] - coffee: - build: - files: [ - expand: true - cwd: '<%= SOURCE_PATH %>/coffee' - src: ['**/*.coffee'] - dest: '<%= BUILD_PATH %>/js' - ext: '.js' - ] - - concat: build: files: @@ -206,7 +195,7 @@ module.exports = (grunt) -> '<%= SOURCE_PATH %>/js/components/issue/templates/**/*.hbs' ] '<%= BUILD_PATH %>/js/apps/issues/templates.js': [ - '<%= SOURCE_PATH %>/coffee/apps/issues/templates/**/*.hbs' + '<%= SOURCE_PATH %>/js/apps/issues/templates/**/*.hbs' ] '<%= BUILD_PATH %>/js/apps/api-documentation/templates.js': [ '<%= SOURCE_PATH %>/js/apps/api-documentation/templates/**/*.hbs' @@ -383,10 +372,6 @@ module.exports = (grunt) -> files: '<%= SOURCE_PATH %>/less/**/*.less' tasks: ['less:build', 'copy:assets-css'] - coffee: - files: '<%= SOURCE_PATH %>/coffee/**/*.coffee' - tasks: ['coffee:build', 'copy:js', 'concat:build', 'copy:assets-all-js'] - js: files: '<%= SOURCE_PATH %>/js/**/*.js' tasks: ['copy:js', 'concat:build', 'copy:assets-all-js'] @@ -398,7 +383,7 @@ module.exports = (grunt) -> # Basic tasks grunt.registerTask 'prepare', - ['clean:css', 'clean:js', 'clean:build', 'less:build', 'coffee:build', 'handlebars:build', 'copy:js', 'concat:build'] + ['clean:css', 'clean:js', 'clean:build', 'less:build', 'handlebars:build', 'copy:js', 'concat:build'] grunt.registerTask 'build-fast-suffix', ['copy:assets-css', 'copy:assets-all-js'] diff --git a/server/sonar-web/src/main/coffee/apps/issues/app-context.coffee b/server/sonar-web/src/main/coffee/apps/issues/app-context.coffee deleted file mode 100644 index 556b93e1e00..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/app-context.coffee +++ /dev/null @@ -1,131 +0,0 @@ -# -# SonarQube, open source software quality management tool. -# Copyright (C) 2008-2014 SonarSource -# mailto:contact AT sonarsource DOT com -# -# SonarQube 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. -# -# SonarQube 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. -# -define [ - './models/state' - './layout' - './models/issues' - 'components/navigator/models/facets' - './models/filters' - - './controller' - './router' - - './workspace-list-view' - './workspace-header-view' - - './facets-view' - './filters-view' -], ( - State - Layout - Issues - Facets - Filters - - Controller - Router - - WorkspaceListView - WorkspaceHeaderView - - FacetsView - FiltersView -) -> - - $ = jQuery - App = new Marionette.Application - - - App.getContextQuery = -> - componentUuids: window.config.resource - - - App.getRestrictedFacets = -> - 'TRK': ['projectUuids'] - 'BRC': ['projectUuids'] - 'DIR': ['projectUuids', 'moduleUuids', 'directories'] - 'DEV': ['authors'] - 'DEV_PRJ': ['projectUuids', 'authors'] - - - App.updateContextFacets = -> - facets = @state.get 'facets' - allFacets = @state.get 'allFacets' - facetsFromServer = @state.get 'facetsFromServer' - @state.set - facets: facets - allFacets: _.difference allFacets, @getRestrictedFacets()[window.config.resourceQualifier] - facetsFromServer: _.difference facetsFromServer, @getRestrictedFacets()[window.config.resourceQualifier] - - - App.addInitializer -> - @state = new State - isContext: true, - contextQuery: @getContextQuery() - contextComponentUuid: window.config.resource - contextComponentName: window.config.resourceName - contextComponentQualifier: window.config.resourceQualifier - @updateContextFacets() - @list = new Issues() - @facets = new Facets() - @filters = new Filters() - - - App.addInitializer -> - @layout = new Layout app: @ - $('.issues').empty().append @layout.render().el - $('#footer').addClass('search-navigator-footer'); - - - App.addInitializer -> - @controller = new Controller app: @ - - - App.addInitializer -> - @issuesView = new WorkspaceListView - app: @ - collection: @list - @layout.workspaceListRegion.show @issuesView - @issuesView.bindScrollEvents() - - - App.addInitializer -> - @workspaceHeaderView = new WorkspaceHeaderView - app: @ - collection: @list - @layout.workspaceHeaderRegion.show @workspaceHeaderView - - - App.addInitializer -> - @facetsView = new FacetsView - app: @ - collection: @facets - @layout.facetsRegion.show @facetsView - - - App.addInitializer -> - @controller.fetchFilters().done => - key.setScope 'list' - @router = new Router app: @ - Backbone.history.start() - - - l10nXHR = window.requestMessages() - jQuery.when(l10nXHR).done -> App.start() diff --git a/server/sonar-web/src/main/coffee/apps/issues/app-new.coffee b/server/sonar-web/src/main/coffee/apps/issues/app-new.coffee deleted file mode 100644 index c69a48e6207..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/app-new.coffee +++ /dev/null @@ -1,109 +0,0 @@ -# -# SonarQube, open source software quality management tool. -# Copyright (C) 2008-2014 SonarSource -# mailto:contact AT sonarsource DOT com -# -# SonarQube 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. -# -# SonarQube 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. -# -define [ - './models/state' - './layout' - './models/issues' - 'components/navigator/models/facets' - './models/filters' - - './controller' - './router' - - './workspace-list-view' - './workspace-header-view' - - './facets-view' - './filters-view' -], ( - State - Layout - Issues - Facets - Filters - - Controller - Router - - WorkspaceListView - WorkspaceHeaderView - - FacetsView - FiltersView -) -> - - $ = jQuery - App = new Marionette.Application - - App.addInitializer -> - @state = new State() - @list = new Issues() - @facets = new Facets() - @filters = new Filters() - - - App.addInitializer -> - @layout = new Layout app: @ - $('.issues').empty().append @layout.render().el - $('#footer').addClass('search-navigator-footer'); - - - App.addInitializer -> - @controller = new Controller app: @ - - - App.addInitializer -> - @issuesView = new WorkspaceListView - app: @ - collection: @list - @layout.workspaceListRegion.show @issuesView - @issuesView.bindScrollEvents() - - - App.addInitializer -> - @workspaceHeaderView = new WorkspaceHeaderView - app: @ - collection: @list - @layout.workspaceHeaderRegion.show @workspaceHeaderView - - - App.addInitializer -> - @facetsView = new FacetsView - app: @ - collection: @facets - @layout.facetsRegion.show @facetsView - - - App.addInitializer -> - @filtersView = new FiltersView - app: @ - collection: @filters - @layout.filtersRegion.show @filtersView - - - App.addInitializer -> - @controller.fetchFilters().done => - key.setScope 'list' - @router = new Router app: @ - Backbone.history.start() - - - l10nXHR = window.requestMessages() - jQuery.when(l10nXHR).done -> App.start() diff --git a/server/sonar-web/src/main/coffee/apps/issues/component-viewer/issue-view.coffee b/server/sonar-web/src/main/coffee/apps/issues/component-viewer/issue-view.coffee deleted file mode 100644 index b626cff1070..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/component-viewer/issue-view.coffee +++ /dev/null @@ -1,36 +0,0 @@ -# -# SonarQube, open source software quality management tool. -# Copyright (C) 2008-2014 SonarSource -# mailto:contact AT sonarsource DOT com -# -# SonarQube 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. -# -# SonarQube 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. -# - -define [ - '../workspace-list-item-view' -], ( - IssueView -) -> - - class extends IssueView - - onRender: -> - super - @$el.removeClass 'issue-navigate-right' - - - serializeData: -> - _.extend super, - showComponent: false diff --git a/server/sonar-web/src/main/coffee/apps/issues/component-viewer/main.coffee b/server/sonar-web/src/main/coffee/apps/issues/component-viewer/main.coffee deleted file mode 100644 index 1a23d070331..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/component-viewer/main.coffee +++ /dev/null @@ -1,192 +0,0 @@ -# -# SonarQube, open source software quality management tool. -# Copyright (C) 2008-2014 SonarSource -# mailto:contact AT sonarsource DOT com -# -# SonarQube 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. -# -# SonarQube 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. -# - -define [ - 'components/source-viewer/main' - '../models/issues' - './issue-view' - '../templates' -], ( - SourceViewer - Issues - IssueView -) -> - - $ = jQuery - - TOP_OFFSET = 38 - BOTTOM_OFFSET = 10 - - - class extends SourceViewer - - events: -> - _.extend super, - 'click .js-close-component-viewer': 'closeComponentViewer' - 'click .code-issue': 'selectIssue' - - - initialize: (options) -> - super - @listenTo options.app.state, 'change:selectedIndex', @select - - - onLoaded: -> - super - @bindShortcuts() - if @baseIssue? - @scrollToLine @baseIssue.get 'line' - - - bindShortcuts: -> - doAction = (action) => - selectedIssueView = @getSelectedIssueEl() - return unless selectedIssueView - selectedIssueView.find(".js-issue-#{action}").click() - - key 'up', 'componentViewer', => - @options.app.controller.selectPrev() - false - - key 'down', 'componentViewer', => - @options.app.controller.selectNext() - false - - key 'left,backspace', 'componentViewer', => - @options.app.controller.closeComponentViewer() - false - - key 'f', 'componentViewer', -> doAction 'transition' - key 'a', 'componentViewer', -> doAction 'assign' - key 'm', 'componentViewer', -> doAction 'assign-to-me' - key 'p', 'componentViewer', -> doAction 'plan' - key 'i', 'componentViewer', -> doAction 'set-severity' - key 'c', 'componentViewer', -> doAction 'comment' - - - unbindShortcuts: -> - key.deleteScope 'componentViewer' - - - onClose: -> - super - @unbindScrollEvents() - @unbindShortcuts() - - - select: -> - selected = @options.app.state.get 'selectedIndex' - selectedIssue = @options.app.list.at selected - if selectedIssue.get('component') == @model.get('key') - @scrollToIssue selectedIssue.get('key') - else - @unbindShortcuts() - @options.app.controller.showComponentViewer selectedIssue - - - getSelectedIssueEl: -> - selected = @options.app.state.get 'selectedIndex' - return null unless selected? - selectedIssue = @options.app.list.at selected - return null unless selectedIssue? - selectedIssueView = @$("#issue-#{selectedIssue.get('key')}") - if selectedIssueView.length > 0 then selectedIssueView else null - - - selectIssue: (e) -> - key = $(e.currentTarget).data 'issue-key' - issue = @issues.find (issue) -> issue.get('key') == key - index = @options.app.list.indexOf issue - @options.app.state.set selectedIndex: index - - - scrollToIssue: (key) -> - el = @$("#issue-#{key}") - if el.length > 0 - line = el.closest('[data-line-number]').data 'line-number' - this.scrollToLine line - else - @unbindShortcuts() - selected = @options.app.state.get 'selectedIndex' - selectedIssue = @options.app.list.at selected - @options.app.controller.showComponentViewer selectedIssue - - - openFileByIssue: (issue) -> - @baseIssue = issue - componentKey = issue.get 'component' - componentUuid = issue.get 'componentUuid' - @open componentUuid, componentKey - - - linesLimit: -> - line = @LINES_LIMIT / 2 - if @baseIssue? && @baseIssue.has('line') - line = Math.max line, @baseIssue.get('line') - from: line - @LINES_LIMIT / 2 + 1 - to: line + @LINES_LIMIT / 2 - - - limitIssues: (issues) -> - index = @ISSUES_LIMIT / 2 - if @baseIssue? && @baseIssue.has('index') - index = Math.max index, @baseIssue.get('index') - x = issues.filter (issue) => - Math.abs(issue.get('index') - index) <= @ISSUES_LIMIT / 2 - x - - - requestIssues: -> - if @options.app.list.last().get('component') == @model.get('key') - r = @options.app.controller.fetchNextPage() - else r = $.Deferred().resolve().promise() - r.done => - @issues.reset @options.app.list.filter (issue) => issue.get('component') == @model.key() - @issues.reset @limitIssues @issues - @addIssuesPerLineMeta @issues - - - renderIssues: -> - @issues.forEach @renderIssue, @ - @$('.source-line-issues').addClass('hidden'); - - - renderIssue: (issue) -> - issueView = new IssueView - el: '#issue-' + issue.get('key') - model: issue - app: @options.app - @issueViews.push issueView - issueView.render() - - - addNextIssuesPage: -> - componentKey = @model.get 'key' - @issues.add @options.app.list.filter (issue) => issue.get('component') == componentKey - - - scrollToLine: (line) -> - row = @$("[data-line-number=#{line}]") - goal = if row.length > 0 then row.offset().top - 200 else 0 - $(window).scrollTop goal - - - closeComponentViewer: -> - @options.app.controller.closeComponentViewer() diff --git a/server/sonar-web/src/main/coffee/apps/issues/controller.coffee b/server/sonar-web/src/main/coffee/apps/issues/controller.coffee deleted file mode 100644 index 18749e884a4..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/controller.coffee +++ /dev/null @@ -1,225 +0,0 @@ -# -# SonarQube, open source software quality management tool. -# Copyright (C) 2008-2014 SonarSource -# mailto:contact AT sonarsource DOT com -# -# SonarQube 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. -# -# SonarQube 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. -# - -define [ - 'components/navigator/controller' - - './component-viewer/main' - './workspace-home-view' -], ( - Controller - - ComponentViewer - HomeView -) -> - - $ = jQuery - EXTRA_FIELDS = 'actions,transitions,assigneeName,reporterName,actionPlanName' - FACET_DATA_FIELDS = ['components', 'projects', 'users', 'rules', 'actionPlans', 'languages'] - - - class extends Controller - - _facetsFromServer: -> - facets = super || [] - facets.push 'assigned_to_me' - facets - - - _issuesParameters: -> - p: @options.app.state.get 'page' - ps: @pageSize - s: 'FILE_LINE' - asc: true - extra_fields: EXTRA_FIELDS - facets: @_facetsFromServer().join() - - - _myIssuesFromResponse: (r) -> - myIssuesData = _.findWhere r.facets, property: 'assigned_to_me' - if myIssuesData? && _.isArray(myIssuesData.values) && myIssuesData.values.length > 0 - @options.app.state.set { myIssues: myIssuesData.values[0].count }, { silent: true } - else - @options.app.state.unset 'myIssues', { silent: true } - - - fetchList: (firstPage = true) -> - if firstPage - @options.app.state.set { selectedIndex: 0, page: 1 }, { silent: true } - @hideHomePage() - @closeComponentViewer() - - data = @_issuesParameters() - _.extend data, @options.app.state.get 'query' - _.extend data, @options.app.state.get 'contextQuery' if @options.app.state.get 'isContext' - - $.get "#{baseUrl}/api/issues/search", data - .done (r) => - issues = @options.app.list.parseIssues r - if firstPage - @options.app.list.reset issues - else - @options.app.list.add issues - @options.app.list.setIndex() - FACET_DATA_FIELDS.forEach (field) => @options.app.facets[field] = r[field] - @options.app.facets.reset @_allFacets() - @options.app.facets.add _.reject(r.facets, (f) -> f.property == 'assigned_to_me'), merge: true - @_myIssuesFromResponse r - @enableFacets @_enabledFacets() - @options.app.state.set - page: r.p - pageSize: r.ps - total: r.total - maxResultsReached: r.p * r.ps >= r.total - if firstPage && @isIssuePermalink() - @showComponentViewer @options.app.list.first() - - - isIssuePermalink: -> - query = @options.app.state.get('query') - query.issues? && @options.app.list.length == 1 - - - fetchFilters: -> - $.get "#{baseUrl}/api/issue_filters/app", (r) => - @options.app.state.set - canBulkChange: r.canBulkChange - canManageFilters: r.canManageFilters - @options.app.filters.reset r.favorites - - - _mergeCollections: (a, b) -> - collection = new Backbone.Collection a - collection.add b, merge: true - collection.toJSON() - - - requestFacet: (id) -> - return @requestAssigneeFacet() if id == 'assignees' - facet = @options.app.facets.get id - data = _.extend { facets: id, ps: 1 }, @options.app.state.get('query') - _.extend data, @options.app.state.get 'contextQuery' if @options.app.state.get 'isContext' - $.get "#{baseUrl}/api/issues/search", data, (r) => - FACET_DATA_FIELDS.forEach (field) => - @options.app.facets[field] = @_mergeCollections @options.app.facets[field], r[field] - facetData = _.findWhere r.facets, property: id - facet.set facetData if facetData? - - - requestAssigneeFacet: -> - facet = @options.app.facets.get 'assignees' - data = _.extend { facets: 'assignees,assigned_to_me', ps: 1 }, @options.app.state.get('query') - _.extend data, @options.app.state.get 'contextQuery' if @options.app.state.get 'isContext' - $.get "#{baseUrl}/api/issues/search", data, (r) => - FACET_DATA_FIELDS.forEach (field) => - @options.app.facets[field] = @_mergeCollections @options.app.facets[field], r[field] - facetData = _.findWhere r.facets, property: 'assignees' - @_myIssuesFromResponse r - facet.set facetData if facetData? - - - newSearch: -> - @options.app.state.unset 'filter' - @options.app.state.setQuery resolved: 'false' - - - applyFilter: (filter, ignoreQuery = false) -> - unless ignoreQuery - filterQuery = @parseQuery filter.get 'query' - @options.app.state.setQuery filterQuery - @options.app.state.set filter: filter, changed: false - - - parseQuery: -> - q = super - # Do not allow to modify the sorting - delete q.asc - delete q.s - q - - - getQuery: (separator = '|', addContext = false) -> - filter = @options.app.state.get 'query' - _.extend filter, @options.app.state.get 'contextQuery' if addContext && @options.app.state.get 'isContext' - route = [] - _.map filter, (value, property) -> - route.push '' + property + '=' + encodeURIComponent(value) - route.join separator - - - getRoute: -> - filter = @options.app.state.get 'filter' - query = super - if filter? - if @options.app.state.get('changed') && query.length > 0 - query = "id=#{filter.id}|#{query}" - else - query = "id=#{filter.id}" - query - - - _prepareComponent: (issue) -> - key: issue.get 'component' - name: issue.get 'componentLongName' - qualifier: issue.get 'componentQualifier' - project: issue.get 'project' - projectName: issue.get 'projectLongName' - - - showComponentViewer: (issue) -> - @options.app.layout.workspaceComponentViewerRegion.reset() - key.setScope 'componentViewer' - @options.app.issuesView.unbindScrollEvents() - @options.app.state.set 'component', @_prepareComponent(issue) - @options.app.componentViewer = new ComponentViewer app: @options.app - @options.app.layout.workspaceComponentViewerRegion.show @options.app.componentViewer - @options.app.layout.showComponentViewer() - @options.app.componentViewer.openFileByIssue issue - - - closeComponentViewer: -> - key.setScope 'list' - # close all popups - $('body').click() - @options.app.state.unset 'component' - @options.app.layout.workspaceComponentViewerRegion.reset() - @options.app.layout.hideComponentViewer() - @options.app.issuesView.bindScrollEvents() - @options.app.issuesView.scrollTo() - - - showHomePage: -> - @fetchList() - @options.app.layout.workspaceComponentViewerRegion.reset() - key.setScope 'home' - @options.app.issuesView.unbindScrollEvents() - @options.app.homeView = new HomeView app: @options.app - @options.app.layout.workspaceHomeRegion.show @options.app.homeView - @options.app.layout.showHomePage() - - - hideHomePage: -> - @options.app.layout.workspaceComponentViewerRegion.reset() - @options.app.layout.workspaceHomeRegion.reset() - key.setScope 'list' - @options.app.layout.hideHomePage() - @options.app.issuesView.bindScrollEvents() - @options.app.issuesView.scrollTo() - diff --git a/server/sonar-web/src/main/coffee/apps/issues/facets-view.coffee b/server/sonar-web/src/main/coffee/apps/issues/facets-view.coffee deleted file mode 100644 index a8a17947ffd..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/facets-view.coffee +++ /dev/null @@ -1,83 +0,0 @@ -# -# SonarQube, open source software quality management tool. -# Copyright (C) 2008-2014 SonarSource -# mailto:contact AT sonarsource DOT com -# -# SonarQube 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. -# -# SonarQube 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. -# - -define [ - 'components/navigator/facets-view' - - './facets/base-facet' - './facets/severity-facet' - './facets/status-facet' - './facets/project-facet' - './facets/module-facet' - './facets/assignee-facet' - './facets/rule-facet' - './facets/tag-facet' - './facets/resolution-facet' - './facets/creation-date-facet' - './facets/action-plan-facet' - './facets/file-facet' - './facets/reporter-facet' - './facets/language-facet' - './facets/author-facet' - './facets/issue-key-facet' - './facets/context-facet' -], ( - FacetsView - - BaseFacet - SeverityFacet - StatusFacet - ProjectFacet - ModuleFacet - AssigneeFacet - RuleFacet - TagFacet - ResolutionFacet - CreationDateFacet - ActionPlanFacet - FileFacet - ReporterFacet - LanguageFacet - AuthorFacet - IssueKeyFacet - ContextFacet -) -> - - class extends FacetsView - - getItemView: (model) -> - switch model.get 'property' - when 'severities' then SeverityFacet - when 'statuses' then StatusFacet - when 'assignees' then AssigneeFacet - when 'resolutions' then ResolutionFacet - when 'createdAt' then CreationDateFacet - when 'projectUuids' then ProjectFacet - when 'moduleUuids' then ModuleFacet - when 'rules' then RuleFacet - when 'tags' then TagFacet - when 'actionPlans' then ActionPlanFacet - when 'fileUuids' then FileFacet - when 'reporters' then ReporterFacet - when 'languages' then LanguageFacet - when 'authors' then AuthorFacet - when 'issues' then IssueKeyFacet - when 'context' then ContextFacet - else BaseFacet diff --git a/server/sonar-web/src/main/coffee/apps/issues/facets/action-plan-facet.coffee b/server/sonar-web/src/main/coffee/apps/issues/facets/action-plan-facet.coffee deleted file mode 100644 index a2a746e1007..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/facets/action-plan-facet.coffee +++ /dev/null @@ -1,72 +0,0 @@ -# -# SonarQube, open source software quality management tool. -# Copyright (C) 2008-2014 SonarSource -# mailto:contact AT sonarsource DOT com -# -# SonarQube 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. -# -# SonarQube 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. -# - -define [ - './base-facet' - '../templates' -], ( - BaseFacet -) -> - - $ = jQuery - - - class extends BaseFacet - template: Templates['issues-action-plan-facet'] - - - onRender: -> - super - value = @options.app.state.get('query')['planned'] - if value? && (!value || value == 'false') - @$('.js-facet').filter("[data-unplanned]").addClass 'active' - - - toggleFacet: (e) -> - unplanned = $(e.currentTarget).is "[data-unplanned]" - $(e.currentTarget).toggleClass 'active' - if unplanned - checked = $(e.currentTarget).is '.active' - value = if checked then 'false' else null - @options.app.state.updateFilter planned: value, actionPlans: null - else - @options.app.state.updateFilter planned: null, actionPlans: @getValue() - - - getValuesWithLabels: -> - values = @model.getValues() - actionPlans = @options.app.facets.actionPlans - values.forEach (v) => - key = v.val - label = null - if key - actionPlan = _.findWhere actionPlans, key: key - label = actionPlan.name if actionPlan? - v.label = label - values - - - disable: -> - @options.app.state.updateFilter planned: null, actionPlans: null - - - serializeData: -> - _.extend super, - values: @getValuesWithLabels() diff --git a/server/sonar-web/src/main/coffee/apps/issues/facets/assignee-facet.coffee b/server/sonar-web/src/main/coffee/apps/issues/facets/assignee-facet.coffee deleted file mode 100644 index 83d0a78da80..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/facets/assignee-facet.coffee +++ /dev/null @@ -1,105 +0,0 @@ -# -# SonarQube, open source software quality management tool. -# Copyright (C) 2008-2014 SonarSource -# mailto:contact AT sonarsource DOT com -# -# SonarQube 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. -# -# SonarQube 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. -# - -define [ - './custom-values-facet' - '../templates' -], ( - CustomValuesFacet -) -> - - $ = jQuery - - - class extends CustomValuesFacet - template: Templates['issues-assignee-facet'] - - - getUrl: -> - "#{baseUrl}/api/users/search" - - prepareAjaxSearch: -> - quietMillis: 300 - url: @getUrl() - data: (term, page) -> { q: term, p: page } - results: window.usersToSelect2 - - onRender: -> - super - value = @options.app.state.get('query')['assigned'] - if value? && (!value || value == 'false') - @$('.js-facet').filter("[data-unassigned]").addClass 'active' - - - toggleFacet: (e) -> - unassigned = $(e.currentTarget).is "[data-unassigned]" - $(e.currentTarget).toggleClass 'active' - if unassigned - checked = $(e.currentTarget).is '.active' - value = if checked then 'false' else null - @options.app.state.updateFilter assigned: value, assignees: null - else - @options.app.state.updateFilter assigned: null, assignees: @getValue() - - - getValuesWithLabels: -> - values = @model.getValues() - users = @options.app.facets.users - values.forEach (v) => - login = v.val - name = '' - if login - user = _.findWhere users, login: login - name = user.name if user? - v.label = name - values - - - disable: -> - @options.app.state.updateFilter assigned: null, assignees: null - - - addCustomValue: -> - property = @model.get 'property' - customValue = @$('.js-custom-value').select2 'val' - value = @getValue() - value += ',' if value.length > 0 - value += customValue - obj = {} - obj[property] = value - obj.assigned = null - @options.app.state.updateFilter obj - - - sortValues: (values) -> - # put "unassigned" first - _.sortBy values, (v) -> - x = if v.val == '' then -999999 else -v.count - x - - - getNumberOfMyIssues: -> - @options.app.state.get 'myIssues' - - - serializeData: -> - _.extend super, - myIssues: @getNumberOfMyIssues() - values: @sortValues @getValuesWithLabels() diff --git a/server/sonar-web/src/main/coffee/apps/issues/facets/author-facet.coffee b/server/sonar-web/src/main/coffee/apps/issues/facets/author-facet.coffee deleted file mode 100644 index 25e8c989749..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/facets/author-facet.coffee +++ /dev/null @@ -1,47 +0,0 @@ -# -# SonarQube, open source software quality management tool. -# Copyright (C) 2008-2014 SonarSource -# mailto:contact AT sonarsource DOT com -# -# SonarQube 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. -# -# SonarQube 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. -# - -define [ - './custom-values-facet' -], ( - CustomValuesFacet -) -> - - - class extends CustomValuesFacet - - getUrl: -> - "#{baseUrl}/api/issues/authors" - - - prepareSearch: -> - @$('.js-custom-value').select2 - placeholder: 'Search...' - minimumInputLength: 2 - allowClear: false - formatNoMatches: -> t 'select2.noMatches' - formatSearching: -> t 'select2.searching' - formatInputTooShort: -> tp 'select2.tooShort', 2 - width: '100%' - ajax: - quietMillis: 300 - url: @getUrl() - data: (term) -> { q: term, ps: 25 } - results: (data) -> { more: false, results: data.authors.map (author) -> { id: author, text: author } } diff --git a/server/sonar-web/src/main/coffee/apps/issues/facets/base-facet.coffee b/server/sonar-web/src/main/coffee/apps/issues/facets/base-facet.coffee deleted file mode 100644 index 4d41996b164..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/facets/base-facet.coffee +++ /dev/null @@ -1,37 +0,0 @@ -# -# SonarQube, open source software quality management tool. -# Copyright (C) 2008-2014 SonarSource -# mailto:contact AT sonarsource DOT com -# -# SonarQube 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. -# -# SonarQube 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. -# - -define [ - 'components/navigator/facets/base-facet' - '../templates' -], ( - BaseFacet -) -> - - class extends BaseFacet - template: Templates['issues-base-facet'] - - onRender: -> - super - @$('[data-toggle="tooltip"]').tooltip container: 'body' - - - onClose: -> - @$('[data-toggle="tooltip"]').tooltip 'destroy' diff --git a/server/sonar-web/src/main/coffee/apps/issues/facets/context-facet.coffee b/server/sonar-web/src/main/coffee/apps/issues/facets/context-facet.coffee deleted file mode 100644 index 3809f07b856..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/facets/context-facet.coffee +++ /dev/null @@ -1,35 +0,0 @@ -# -# SonarQube, open source software quality management tool. -# Copyright (C) 2008-2014 SonarSource -# mailto:contact AT sonarsource DOT com -# -# SonarQube 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. -# -# SonarQube 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. -# - -define [ - './base-facet' - '../templates' -], ( - BaseFacet -) -> - - - class extends BaseFacet - template: Templates['issues-context-facet'] - - - serializeData: -> - _.extend super, - state: @options.app.state.toJSON() diff --git a/server/sonar-web/src/main/coffee/apps/issues/facets/creation-date-facet.coffee b/server/sonar-web/src/main/coffee/apps/issues/facets/creation-date-facet.coffee deleted file mode 100644 index c1a29019ba1..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/facets/creation-date-facet.coffee +++ /dev/null @@ -1,141 +0,0 @@ -# -# SonarQube, open source software quality management tool. -# Copyright (C) 2008-2014 SonarSource -# mailto:contact AT sonarsource DOT com -# -# SonarQube 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. -# -# SonarQube 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. -# - -define [ - './base-facet' - '../templates' -], ( - BaseFacet -) -> - - $ = jQuery - - - class extends BaseFacet - template: Templates['issues-creation-date-facet'] - - - events: -> - _.extend super, - 'change input': 'applyFacet' - 'click .js-select-period-start': 'selectPeriodStart' - 'click .js-select-period-end': 'selectPeriodEnd' - - 'click .sonar-d3 rect': 'selectBar' - - 'click .js-all': 'onAllClick' - 'click .js-last-week': 'onLastWeekClick' - 'click .js-last-month': 'onLastMonthClick' - 'click .js-last-year': 'onLastYearClick' - - - onRender: -> - @$el.toggleClass 'search-navigator-facet-box-collapsed', !@model.get('enabled') - - @$('input').datepicker - dateFormat: 'yy-mm-dd' - changeMonth: true - changeYear: true - - props = ['createdAfter', 'createdBefore', 'createdAt'] - query = @options.app.state.get 'query' - props.forEach (prop) => - value = query[prop] - @$("input[name=#{prop}]").val value if value? - - values = @model.getValues() - unless _.isArray(values) && values.length > 0 - date = moment() - values = [] - for i in [0..10] - values.push count: 0, val: date.toDate().toString() - date = date.subtract 1, 'days' - values.reverse() - @$('.js-barchart').barchart values - - - selectPeriodStart: -> - @$('.js-period-start').datepicker 'show' - - - selectPeriodEnd: -> - @$('.js-period-end').datepicker 'show' - - - applyFacet: -> - obj = createdAt: null, createdInLast: null - @$('input').each -> - property = $(@).prop 'name' - value = $(@).val() - obj[property] = value - @options.app.state.updateFilter obj - - - disable: -> - @options.app.state.updateFilter - createdAfter: null - createdBefore: null - createdAt: null - createdInLast: null - - - selectBar: (e) -> - periodStart = $(e.currentTarget).data 'period-start' - periodEnd = $(e.currentTarget).data 'period-end' - @options.app.state.updateFilter - createdAfter: periodStart - createdBefore: periodEnd - createdAt: null - createdInLast: null - - - selectPeriod: (period) -> - @options.app.state.updateFilter - createdAfter: null - createdBefore: null - createdAt: null - createdInLast: period - - - onAllClick: -> - @disable() - - - onLastWeekClick: (e) -> - e.preventDefault() - @selectPeriod '1w' - - - onLastMonthClick: (e) -> - e.preventDefault() - @selectPeriod '1m' - - - onLastYearClick: (e) -> - e.preventDefault() - @selectPeriod '1y' - - - serializeData: -> - _.extend super, - periodStart: @options.app.state.get('query').createdAfter - periodEnd: @options.app.state.get('query').createdBefore - createdAt: @options.app.state.get('query').createdAt - createdInLast: @options.app.state.get('query').createdInLast diff --git a/server/sonar-web/src/main/coffee/apps/issues/facets/custom-values-facet.coffee b/server/sonar-web/src/main/coffee/apps/issues/facets/custom-values-facet.coffee deleted file mode 100644 index 9cd45d02579..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/facets/custom-values-facet.coffee +++ /dev/null @@ -1,71 +0,0 @@ -# -# SonarQube, open source software quality management tool. -# Copyright (C) 2008-2014 SonarSource -# mailto:contact AT sonarsource DOT com -# -# SonarQube 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. -# -# SonarQube 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. -# - -define [ - './base-facet' - '../templates' -], ( - BaseFacet -) -> - - - class extends BaseFacet - template: Templates['issues-custom-values-facet'] - - - events: -> - _.extend super, - 'change .js-custom-value': 'addCustomValue' - - - getUrl: -> - - - onRender: -> - super - @prepareSearch() - - - prepareSearch: -> - @$('.js-custom-value').select2 - placeholder: 'Search...' - minimumInputLength: 2 - allowClear: false - formatNoMatches: -> t 'select2.noMatches' - formatSearching: -> t 'select2.searching' - formatInputTooShort: -> tp 'select2.tooShort', 2 - width: '100%' - ajax: @prepareAjaxSearch() - - prepareAjaxSearch: -> - quietMillis: 300 - url: @getUrl() - data: (term, page) -> { s: term, p: page } - results: (data) -> { more: data.more, results: data.results } - - addCustomValue: -> - property = @model.get 'property' - customValue = @$('.js-custom-value').select2 'val' - value = @getValue() - value += ',' if value.length > 0 - value += customValue - obj = {} - obj[property] = value - @options.app.state.updateFilter obj diff --git a/server/sonar-web/src/main/coffee/apps/issues/facets/file-facet.coffee b/server/sonar-web/src/main/coffee/apps/issues/facets/file-facet.coffee deleted file mode 100644 index 62081444f4b..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/facets/file-facet.coffee +++ /dev/null @@ -1,56 +0,0 @@ -# -# SonarQube, open source software quality management tool. -# Copyright (C) 2008-2014 SonarSource -# mailto:contact AT sonarsource DOT com -# -# SonarQube 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. -# -# SonarQube 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. -# - -define [ - './base-facet' - '../templates' -], ( - BaseFacet -) -> - - $ = jQuery - - - class extends BaseFacet - template: Templates['issues-file-facet'] - - - onRender: -> - super - maxValueWidth = _.max @$('.facet-stat').map(-> $(@).outerWidth()).get() - @$('.facet-name').css 'padding-right', maxValueWidth - - - getValuesWithLabels: -> - values = @model.getValues() - source = @options.app.facets.components - values.forEach (v) => - key = v.val - label = null - if key - item = _.findWhere source, uuid: key - label = item.longName if item? - v.label = label - values - - - serializeData: -> - _.extend super, - values: @sortValues @getValuesWithLabels() diff --git a/server/sonar-web/src/main/coffee/apps/issues/facets/issue-key-facet.coffee b/server/sonar-web/src/main/coffee/apps/issues/facets/issue-key-facet.coffee deleted file mode 100644 index 53afcf4f441..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/facets/issue-key-facet.coffee +++ /dev/null @@ -1,43 +0,0 @@ -# -# SonarQube, open source software quality management tool. -# Copyright (C) 2008-2014 SonarSource -# mailto:contact AT sonarsource DOT com -# -# SonarQube 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. -# -# SonarQube 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. -# - -define [ - './base-facet' - '../templates' -], ( - BaseFacet -) -> - - - class extends BaseFacet - template: Templates['issues-issue-key-facet'] - - - onRender: -> - @$el.toggleClass 'hidden', !@options.app.state.get('query').issues - - - disable: -> - @options.app.state.updateFilter issues: null - - - serializeData: -> - _.extend super, - issues: @options.app.state.get('query').issues diff --git a/server/sonar-web/src/main/coffee/apps/issues/facets/language-facet.coffee b/server/sonar-web/src/main/coffee/apps/issues/facets/language-facet.coffee deleted file mode 100644 index 3d67584dd02..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/facets/language-facet.coffee +++ /dev/null @@ -1,67 +0,0 @@ -# -# SonarQube, open source software quality management tool. -# Copyright (C) 2008-2014 SonarSource -# mailto:contact AT sonarsource DOT com -# -# SonarQube 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. -# -# SonarQube 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. -# - -define [ - './custom-values-facet' -], ( - CustomValuesFacet -) -> - - - class extends CustomValuesFacet - - getUrl: -> - "#{baseUrl}/api/languages/list" - - - prepareSearch: -> - @$('.js-custom-value').select2 - placeholder: 'Search...' - minimumInputLength: 2 - allowClear: false - formatNoMatches: -> t 'select2.noMatches' - formatSearching: -> t 'select2.searching' - formatInputTooShort: -> tp 'select2.tooShort', 2 - width: '100%' - ajax: - quietMillis: 300 - url: @getUrl() - data: (term) -> { q: term, ps: 0 } - results: (data) -> - more: false - results: data.languages.map (lang) -> { id: lang.key, text: lang.name } - - - getValuesWithLabels: -> - values = @model.getValues() - source = @options.app.facets.languages - values.forEach (v) => - key = v.val - label = null - if key - item = _.findWhere source, key: key - label = item.name if item? - v.label = label - values - - - serializeData: -> - _.extend super, - values: @sortValues @getValuesWithLabels() diff --git a/server/sonar-web/src/main/coffee/apps/issues/facets/module-facet.coffee b/server/sonar-web/src/main/coffee/apps/issues/facets/module-facet.coffee deleted file mode 100644 index 425f4b5c2d4..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/facets/module-facet.coffee +++ /dev/null @@ -1,44 +0,0 @@ -# -# SonarQube, open source software quality management tool. -# Copyright (C) 2008-2014 SonarSource -# mailto:contact AT sonarsource DOT com -# -# SonarQube 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. -# -# SonarQube 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. -# - -define [ - './base-facet' -], ( - BaseFacet -) -> - - class extends BaseFacet - - getValuesWithLabels: -> - values = @model.getValues() - components = @options.app.facets.components - values.forEach (v) => - uuid = v.val - label = uuid - if uuid - component = _.findWhere components, uuid: uuid - label = component.longName if component? - v.label = label - values - - - serializeData: -> - _.extend super, - values: @sortValues @getValuesWithLabels() diff --git a/server/sonar-web/src/main/coffee/apps/issues/facets/project-facet.coffee b/server/sonar-web/src/main/coffee/apps/issues/facets/project-facet.coffee deleted file mode 100644 index d7ea58a1dca..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/facets/project-facet.coffee +++ /dev/null @@ -1,83 +0,0 @@ -# -# SonarQube, open source software quality management tool. -# Copyright (C) 2008-2014 SonarSource -# mailto:contact AT sonarsource DOT com -# -# SonarQube 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. -# -# SonarQube 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. -# - -define [ - './custom-values-facet' -], ( - CustomValuesFacet -) -> - - - class extends CustomValuesFacet - - getUrl: -> - q = @options.app.state.get 'contextComponentQualifier' - if q == 'VW' || q == 'SVW' - "#{baseUrl}/api/components/search" - else - "#{baseUrl}/api/resources/search?f=s2&q=TRK&display_uuid=true" - - - prepareSearch: -> - q = @options.app.state.get 'contextComponentQualifier' - if q == 'VW' || q == 'SVW' - @prepareSearchForViews() - else super - - - prepareSearchForViews: -> - componentUuid = this.options.app.state.get 'contextComponentUuid' - @$('.js-custom-value').select2 - placeholder: 'Search...' - minimumInputLength: 2 - allowClear: false - formatNoMatches: -> t 'select2.noMatches' - formatSearching: -> t 'select2.searching' - formatInputTooShort: -> tp 'select2.tooShort', 2 - width: '100%' - ajax: - quietMillis: 300 - url: @getUrl() - data: (term, page) -> - q: term - componentUuid: componentUuid - p: page - ps: 25 - results: (data) -> - more: data.p * data.ps < data.total, - results: data.components.map (c) -> id: c.uuid, text: c.name - - - getValuesWithLabels: -> - values = @model.getValues() - projects = @options.app.facets.projects - values.forEach (v) => - uuid = v.val - label = '' - if uuid - project = _.findWhere projects, uuid: uuid - label = project.longName if project? - v.label = label - values - - - serializeData: -> - _.extend super, - values: @sortValues @getValuesWithLabels() diff --git a/server/sonar-web/src/main/coffee/apps/issues/facets/reporter-facet.coffee b/server/sonar-web/src/main/coffee/apps/issues/facets/reporter-facet.coffee deleted file mode 100644 index e8e10a4d06f..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/facets/reporter-facet.coffee +++ /dev/null @@ -1,54 +0,0 @@ -# -# SonarQube, open source software quality management tool. -# Copyright (C) 2008-2014 SonarSource -# mailto:contact AT sonarsource DOT com -# -# SonarQube 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. -# -# SonarQube 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. -# - -define [ - './custom-values-facet' -], ( - CustomValuesFacet -) -> - - - class extends CustomValuesFacet - - getUrl: -> - "#{baseUrl}/api/users/search" - - prepareAjaxSearch: -> - quietMillis: 300 - url: @getUrl() - data: (term, page) -> { q: term, p: page } - results: window.usersToSelect2 - - getValuesWithLabels: -> - values = @model.getValues() - source = @options.app.facets.users - values.forEach (v) => - key = v.val - label = null - if key - item = _.findWhere source, login: key - label = item.name if item? - v.label = label - values - - - serializeData: -> - _.extend super, - values: @sortValues @getValuesWithLabels() diff --git a/server/sonar-web/src/main/coffee/apps/issues/facets/resolution-facet.coffee b/server/sonar-web/src/main/coffee/apps/issues/facets/resolution-facet.coffee deleted file mode 100644 index 7c7eef0bd74..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/facets/resolution-facet.coffee +++ /dev/null @@ -1,61 +0,0 @@ -# -# SonarQube, open source software quality management tool. -# Copyright (C) 2008-2014 SonarSource -# mailto:contact AT sonarsource DOT com -# -# SonarQube 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. -# -# SonarQube 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. -# - -define [ - './base-facet' - '../templates' -], ( - BaseFacet -) -> - - $ = jQuery - - - class extends BaseFacet - template: Templates['issues-resolution-facet'] - - - onRender: -> - super - - value = @options.app.state.get('query')['resolved'] - if value? && (!value || value == 'false') - @$('.js-facet').filter("[data-unresolved]").addClass 'active' - - - toggleFacet: (e) -> - unresolved = $(e.currentTarget).is "[data-unresolved]" - $(e.currentTarget).toggleClass 'active' - if unresolved - checked = $(e.currentTarget).is '.active' - value = if checked then 'false' else null - @options.app.state.updateFilter resolved: value, resolutions: null - else - @options.app.state.updateFilter resolved: null, resolutions: @getValue() - - - disable: -> - @options.app.state.updateFilter resolved: null, resolutions: null - - - sortValues: (values) -> - order = ['', 'FIXED', 'FALSE-POSITIVE', 'WONTFIX', 'REMOVED'] - _.sortBy values, (v) -> order.indexOf v.val - diff --git a/server/sonar-web/src/main/coffee/apps/issues/facets/rule-facet.coffee b/server/sonar-web/src/main/coffee/apps/issues/facets/rule-facet.coffee deleted file mode 100644 index 25ea9f9dd9c..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/facets/rule-facet.coffee +++ /dev/null @@ -1,71 +0,0 @@ -# -# SonarQube, open source software quality management tool. -# Copyright (C) 2008-2014 SonarSource -# mailto:contact AT sonarsource DOT com -# -# SonarQube 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. -# -# SonarQube 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. -# - -define [ - './custom-values-facet' -], ( - CustomValuesFacet -) -> - - - class extends CustomValuesFacet - - prepareSearch: -> - url = "#{baseUrl}/api/rules/search?f=name,langName" - languages = @options.app.state.get('query').languages - if languages? - url += "&languages=#{languages}" - @$('.js-custom-value').select2 - placeholder: 'Search...' - minimumInputLength: 2 - allowClear: false - formatNoMatches: -> t 'select2.noMatches' - formatSearching: -> t 'select2.searching' - formatInputTooShort: -> tp 'select2.tooShort', 2 - width: '100%' - ajax: - quietMillis: 300 - url: url - data: (term, page) -> { q: term, p: page } - results: (data) -> - results = data.rules.map (rule) -> - id: rule.key, text: "(#{rule.langName}) #{rule.name}" - { more: (data.p * data.ps < data.total), results: results } - - - getValuesWithLabels: -> - values = @model.getValues() - rules = @options.app.facets.rules - values.forEach (v) => - key = v.val - label = '' - extra = '' - if key - rule = _.findWhere rules, key: key - label = rule.name if rule? - extra = rule.langName if rule? - v.label = label - v.extra = extra - values - - - serializeData: -> - _.extend super, - values: @sortValues @getValuesWithLabels() diff --git a/server/sonar-web/src/main/coffee/apps/issues/facets/severity-facet.coffee b/server/sonar-web/src/main/coffee/apps/issues/facets/severity-facet.coffee deleted file mode 100644 index c0639ef97a6..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/facets/severity-facet.coffee +++ /dev/null @@ -1,36 +0,0 @@ -# -# SonarQube, open source software quality management tool. -# Copyright (C) 2008-2014 SonarSource -# mailto:contact AT sonarsource DOT com -# -# SonarQube 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. -# -# SonarQube 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. -# - -define [ - './base-facet' - '../templates' -], ( - BaseFacet -) -> - - - class extends BaseFacet - template: Templates['issues-severity-facet'] - - - sortValues: (values) -> - order = ['BLOCKER', 'MINOR', 'CRITICAL', 'INFO', 'MAJOR'] - _.sortBy values, (v) -> order.indexOf v.val - diff --git a/server/sonar-web/src/main/coffee/apps/issues/facets/status-facet.coffee b/server/sonar-web/src/main/coffee/apps/issues/facets/status-facet.coffee deleted file mode 100644 index f3a0eb7a040..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/facets/status-facet.coffee +++ /dev/null @@ -1,35 +0,0 @@ -# -# SonarQube, open source software quality management tool. -# Copyright (C) 2008-2014 SonarSource -# mailto:contact AT sonarsource DOT com -# -# SonarQube 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. -# -# SonarQube 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. -# - -define [ - './base-facet' - '../templates' -], ( - BaseFacet -) -> - - - class extends BaseFacet - template: Templates['issues-status-facet'] - - - sortValues: (values) -> - order = ['OPEN', 'RESOLVED', 'REOPENED', 'CLOSED', 'CONFIRMED'] - _.sortBy values, (v) -> order.indexOf v.val diff --git a/server/sonar-web/src/main/coffee/apps/issues/facets/tag-facet.coffee b/server/sonar-web/src/main/coffee/apps/issues/facets/tag-facet.coffee deleted file mode 100644 index fb061cf96f8..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/facets/tag-facet.coffee +++ /dev/null @@ -1,63 +0,0 @@ -# -# SonarQube, open source software quality management tool. -# Copyright (C) 2008-2014 SonarSource -# mailto:contact AT sonarsource DOT com -# -# SonarQube 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. -# -# SonarQube 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. -# - -define [ - './custom-values-facet' -], ( - CustomValuesFacet -) -> - - - class extends CustomValuesFacet - - prepareSearch: -> - url = "#{baseUrl}/api/issues/tags?ps=10" - tags = @options.app.state.get('query').tags - if tags? - url += "&tags=#{tags}" - @$('.js-custom-value').select2 - placeholder: 'Search...' - minimumInputLength: 0 - allowClear: false - formatNoMatches: -> t 'select2.noMatches' - formatSearching: -> t 'select2.searching' - width: '100%' - ajax: - quietMillis: 300 - url: url - data: (term, page) -> { q: term, ps: 10 } - results: (data) -> - results = data.tags.map (tag) -> - id: tag, text: tag - { more: false, results: results } - - - getValuesWithLabels: -> - values = @model.getValues() - tags = @options.app.facets.tags - values.forEach (v) => - v.label = v.val - v.extra = '' - values - - - serializeData: -> - _.extend super, - values: @sortValues @getValuesWithLabels() diff --git a/server/sonar-web/src/main/coffee/apps/issues/filters-view.coffee b/server/sonar-web/src/main/coffee/apps/issues/filters-view.coffee deleted file mode 100644 index 71024317783..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/filters-view.coffee +++ /dev/null @@ -1,97 +0,0 @@ -# -# SonarQube, open source software quality management tool. -# Copyright (C) 2008-2014 SonarSource -# mailto:contact AT sonarsource DOT com -# -# SonarQube 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. -# -# SonarQube 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. -# - -define [ - './templates' -], -> - - $ = jQuery - - - class extends Marionette.ItemView - template: Templates['issues-filters'] - - - events: - 'click .js-toggle-filters': 'toggleFilters' - 'click .js-filter': 'applyFilter' - 'click .js-filter-save-as': 'saveAs' - 'click .js-filter-save': 'save' - 'click .js-filter-copy': 'copy' - 'click .js-filter-edit': 'edit' - - - initialize: (options) -> - @listenTo options.app.state, 'change:filter', @render - @listenTo options.app.state, 'change:changed', @render - @listenTo options.app.filters, 'all', @render - window.onSaveAs = window.onCopy = window.onEdit = (id) => - $('#modal').dialog 'close' - @options.app.controller.fetchFilters().done => - filter = @collection.get id - filter.fetch().done => @options.app.controller.applyFilter filter - - - onRender: -> - @$el.toggleClass 'search-navigator-filters-selected', @options.app.state.has('filter') - - - toggleFilters: (e) -> - e.stopPropagation() - @$('.search-navigator-filters-list').toggle() - $('body').on 'click.issues-filters', => - $('body').off 'click.issues-filters' - @$('.search-navigator-filters-list').hide() - - - applyFilter: (e) -> - id = $(e.currentTarget).data 'id' - filter = @collection.get id - filter.fetch().done => @options.app.controller.applyFilter filter - - - saveAs: -> - query = @options.app.controller.getQuery '&' - url = "#{baseUrl}/issues/save_as_form?#{query}" - openModalWindow url, {} - - - save: -> - query = @options.app.controller.getQuery '&' - url = "#{baseUrl}/issues/save/#{@options.app.state.get('filter').id}?#{query}" - $.post(url).done => - @options.app.state.set changed: false - - - copy: -> - url = "#{baseUrl}/issues/copy_form/#{@options.app.state.get('filter').id}" - openModalWindow url, {} - - - edit: -> - url = "#{baseUrl}/issues/edit_form/#{@options.app.state.get('filter').id}" - openModalWindow url, {} - - - serializeData: -> - _.extend super, - state: @options.app.state.toJSON() - filter: @options.app.state.get('filter')?.toJSON() - currentUser: window.SS.user diff --git a/server/sonar-web/src/main/coffee/apps/issues/issue-filter-view.coffee b/server/sonar-web/src/main/coffee/apps/issues/issue-filter-view.coffee deleted file mode 100644 index cb3ee4d95f7..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/issue-filter-view.coffee +++ /dev/null @@ -1,47 +0,0 @@ -# -# SonarQube, open source software quality management tool. -# Copyright (C) 2008-2014 SonarSource -# mailto:contact AT sonarsource DOT com -# -# SonarQube 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. -# -# SonarQube 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. -# - -define [ - 'components/issue/views/action-options-view' - './templates' -], ( - ActionOptionsView -) -> - - $ = jQuery - - - class extends ActionOptionsView - template: Templates['issues-issue-filter-form'] - - - selectInitialOption: -> - @makeActive @getOptions().first() - - - selectOption: (e) -> - property = $(e.currentTarget).data 'property' - value = $(e.currentTarget).data 'value' - @trigger 'select', property, value - super - - - serializeData: -> - _.extend super, s: @model.get 'severity' diff --git a/server/sonar-web/src/main/coffee/apps/issues/layout.coffee b/server/sonar-web/src/main/coffee/apps/issues/layout.coffee deleted file mode 100644 index ac81d542e7c..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/layout.coffee +++ /dev/null @@ -1,69 +0,0 @@ -# -# SonarQube, open source software quality management tool. -# Copyright (C) 2008-2014 SonarSource -# mailto:contact AT sonarsource DOT com -# -# SonarQube 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. -# -# SonarQube 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. -# - -define [ - './templates' -], -> - - $ = jQuery - - - class extends Marionette.Layout - template: Templates['issues-layout'] - - - regions: - filtersRegion: '.search-navigator-filters' - facetsRegion: '.search-navigator-facets' - workspaceHeaderRegion: '.search-navigator-workspace-header' - workspaceListRegion: '.search-navigator-workspace-list' - workspaceComponentViewerRegion: '.issues-workspace-component-viewer' - workspaceHomeRegion: '.issues-workspace-home' - - - onRender: -> - @$(@filtersRegion.el).addClass('hidden') if @options.app.state.get('isContext') - $('.search-navigator').addClass 'sticky' - top = $('.search-navigator').offset().top - @$('.search-navigator-workspace-header').css top: top - @$('.search-navigator-side').css({ top: top }).isolatedScroll() - - - showSpinner: (region) -> - @[region].show new Marionette.ItemView - template: _.template('') - - - showComponentViewer: -> - @scroll = $(window).scrollTop() - $('.issues').addClass 'issues-extended-view' - - - hideComponentViewer: -> - $('.issues').removeClass 'issues-extended-view' - $(window).scrollTop @scroll if @scroll? - - - showHomePage: -> - $('.issues').addClass 'issues-home-view' - - - hideHomePage: -> - $('.issues').removeClass 'issues-home-view' diff --git a/server/sonar-web/src/main/coffee/apps/issues/models/facet.coffee b/server/sonar-web/src/main/coffee/apps/issues/models/facet.coffee deleted file mode 100644 index 96bc2d81e00..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/models/facet.coffee +++ /dev/null @@ -1,37 +0,0 @@ -# -# SonarQube, open source software quality management tool. -# Copyright (C) 2008-2014 SonarSource -# mailto:contact AT sonarsource DOT com -# -# SonarQube 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. -# -# SonarQube 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. -# - -define -> - - class extends Backbone.Model - idAttribute: 'property' - - - defaults: - enabled: false - - - getValues: -> - @get('values') || [] - - - toggle: -> - enabled = @get 'enabled' - @set enabled: !enabled diff --git a/server/sonar-web/src/main/coffee/apps/issues/models/facets.coffee b/server/sonar-web/src/main/coffee/apps/issues/models/facets.coffee deleted file mode 100644 index 3f6a957b3d7..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/models/facets.coffee +++ /dev/null @@ -1,28 +0,0 @@ -# -# SonarQube, open source software quality management tool. -# Copyright (C) 2008-2014 SonarSource -# mailto:contact AT sonarsource DOT com -# -# SonarQube 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. -# -# SonarQube 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. -# - -define [ - './facet' -], ( - Facet -) -> - - class extends Backbone.Collection - model: Facet diff --git a/server/sonar-web/src/main/coffee/apps/issues/models/filter.coffee b/server/sonar-web/src/main/coffee/apps/issues/models/filter.coffee deleted file mode 100644 index 9759bc31ff1..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/models/filter.coffee +++ /dev/null @@ -1,30 +0,0 @@ -# -# SonarQube, open source software quality management tool. -# Copyright (C) 2008-2014 SonarSource -# mailto:contact AT sonarsource DOT com -# -# SonarQube 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. -# -# SonarQube 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. -# - -define -> - - class extends Backbone.Model - - url: -> - "/api/issue_filters/show/#{@id}" - - - parse: (r) -> - if r.filter? then r.filter else r diff --git a/server/sonar-web/src/main/coffee/apps/issues/models/filters.coffee b/server/sonar-web/src/main/coffee/apps/issues/models/filters.coffee deleted file mode 100644 index b002dba96a6..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/models/filters.coffee +++ /dev/null @@ -1,28 +0,0 @@ -# -# SonarQube, open source software quality management tool. -# Copyright (C) 2008-2014 SonarSource -# mailto:contact AT sonarsource DOT com -# -# SonarQube 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. -# -# SonarQube 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. -# - -define [ - './filter' -], ( - Filter -) -> - - class extends Backbone.Collection - model: Filter diff --git a/server/sonar-web/src/main/coffee/apps/issues/models/issues.coffee b/server/sonar-web/src/main/coffee/apps/issues/models/issues.coffee deleted file mode 100644 index d98b2632120..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/models/issues.coffee +++ /dev/null @@ -1,80 +0,0 @@ -# -# SonarQube, open source software quality management tool. -# Copyright (C) 2008-2014 SonarSource -# mailto:contact AT sonarsource DOT com -# -# SonarQube 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. -# -# SonarQube 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. -# - -define [ - 'components/issue/models/issue' -], ( - Issue -) -> - - class extends Backbone.Collection - model: Issue - - url: -> - "#{baseUrl}/api/issues/search" - - - # Used to parse /api/issues/search response - parseIssues: (r) -> - find = (source, key, keyField) -> - searchDict = {} - searchDict[keyField || 'key'] = key - _.findWhere(source, searchDict) || key - - r.issues.map (issue, index) -> - component = find r.components, issue.component - project = find r.projects, issue.project - subProject = find r.components, issue.subProject - rule = find r.rules, issue.rule - assignee = find r.users, issue.assignee, 'login' - - _.extend issue, - index: index - - if component - _.extend issue, - componentUuid: component.uuid - componentLongName: component.longName - componentQualifier: component.qualifier - - if project - _.extend issue, - projectLongName: project.longName - projectUuid: project.uuid - - if subProject - _.extend issue, - subProjectLongName: subProject.longName - subProjectUuid: subProject.uuid - - if rule - _.extend issue, - ruleName: rule.name - - if assignee - _.extend issue, - assigneeEmail: assignee.email - - issue - - - setIndex: -> - @forEach (issue, index) -> - issue.set index: index diff --git a/server/sonar-web/src/main/coffee/apps/issues/models/state.coffee b/server/sonar-web/src/main/coffee/apps/issues/models/state.coffee deleted file mode 100644 index b0588d25f7d..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/models/state.coffee +++ /dev/null @@ -1,47 +0,0 @@ -# -# SonarQube, open source software quality management tool. -# Copyright (C) 2008-2014 SonarSource -# mailto:contact AT sonarsource DOT com -# -# SonarQube 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. -# -# SonarQube 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. -# - -define [ - 'components/navigator/models/state' -], (State) -> - class extends State - - defaults: - page: 1 - maxResultsReached: false - query: {} - facets: ['severities', 'resolutions'] - isContext: false - - allFacets: ['issues', 'severities', 'resolutions', 'statuses', 'createdAt', 'rules', 'tags', 'projectUuids', - 'moduleUuids', 'directories', 'fileUuids', 'assignees', 'reporters', 'authors', 'languages', - 'actionPlans'], - facetsFromServer: ['severities', 'statuses', 'resolutions', 'actionPlans', 'projectUuids', 'directories', 'rules', - 'moduleUuids', 'tags', 'assignees', 'reporters', 'authors', 'fileUuids', 'languages', - 'createdAt'], - transform: { - 'resolved': 'resolutions' - 'assigned': 'assignees' - 'planned': 'actionPlans' - 'createdBefore': 'createdAt' - 'createdAfter': 'createdAt' - 'createdInLast': 'createdAt' - } - diff --git a/server/sonar-web/src/main/coffee/apps/issues/router.coffee b/server/sonar-web/src/main/coffee/apps/issues/router.coffee deleted file mode 100644 index ca220549f1f..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/router.coffee +++ /dev/null @@ -1,58 +0,0 @@ -# -# SonarQube, open source software quality management tool. -# Copyright (C) 2008-2014 SonarSource -# mailto:contact AT sonarsource DOT com -# -# SonarQube 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. -# -# SonarQube 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. -# - -define [ - 'components/navigator/router' -], ( - Router -) -> - - class extends Router - routes: - '': 'home' - ':query': 'index' - - - initialize: (options) -> - super - @listenTo options.app.state, 'change:filter', @updateRoute - - - home: -> - if @options.app.state.get 'isContext' - @navigate 'resolved=false', { trigger: true, replace: true } - else - @options.app.controller.showHomePage() - - - index: (query) -> - query = @options.app.controller.parseQuery query - if query.id? - filter = @options.app.filters.get query.id - delete query.id - filter.fetch().done => - if Object.keys(query).length > 0 - @options.app.controller.applyFilter filter, true - @options.app.state.setQuery query - @options.app.state.set changed: true - else - @options.app.controller.applyFilter filter - else - @options.app.state.setQuery query diff --git a/server/sonar-web/src/main/coffee/apps/issues/templates/facets/_issues-facet-header.hbs b/server/sonar-web/src/main/coffee/apps/issues/templates/facets/_issues-facet-header.hbs deleted file mode 100644 index 3b57c6021ea..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/templates/facets/_issues-facet-header.hbs +++ /dev/null @@ -1,4 +0,0 @@ - - - {{t 'issues.facet' property}} - diff --git a/server/sonar-web/src/main/coffee/apps/issues/templates/facets/issues-action-plan-facet.hbs b/server/sonar-web/src/main/coffee/apps/issues/templates/facets/issues-action-plan-facet.hbs deleted file mode 100644 index 20958a58b4c..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/templates/facets/issues-action-plan-facet.hbs +++ /dev/null @@ -1,18 +0,0 @@ -{{> '_issues-facet-header'}} - -
- {{#each values}} - {{#eq val ''}} - {{! unplanned }} - - {{t 'issue.unplanned'}} - {{numberShort count}} - - {{else}} - - {{label}} - {{numberShort count}} - - {{/eq}} - {{/each}} -
diff --git a/server/sonar-web/src/main/coffee/apps/issues/templates/facets/issues-assignee-facet.hbs b/server/sonar-web/src/main/coffee/apps/issues/templates/facets/issues-assignee-facet.hbs deleted file mode 100644 index 9654cf06f1e..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/templates/facets/issues-assignee-facet.hbs +++ /dev/null @@ -1,30 +0,0 @@ -{{> '_issues-facet-header'}} - -
- {{#notNull myIssues}} - - {{t 'me'}} - {{myIssues}} - -
- {{/notNull}} - - {{#each values}} - {{#eq val ''}} - {{! unassigned }} - - {{t 'unassigned'}} - {{numberShort count}} - - {{else}} - - {{label}} - {{numberShort count}} - - {{/eq}} - {{/each}} - -
- -
-
diff --git a/server/sonar-web/src/main/coffee/apps/issues/templates/facets/issues-base-facet.hbs b/server/sonar-web/src/main/coffee/apps/issues/templates/facets/issues-base-facet.hbs deleted file mode 100644 index f5b0f44f777..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/templates/facets/issues-base-facet.hbs +++ /dev/null @@ -1,10 +0,0 @@ -{{> '_issues-facet-header'}} - -
- {{#each values}} - - {{default label val}} - {{numberShort count}} - - {{/each}} -
diff --git a/server/sonar-web/src/main/coffee/apps/issues/templates/facets/issues-creation-date-facet.hbs b/server/sonar-web/src/main/coffee/apps/issues/templates/facets/issues-creation-date-facet.hbs deleted file mode 100644 index 4cc52cc4ae6..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/templates/facets/issues-creation-date-facet.hbs +++ /dev/null @@ -1,32 +0,0 @@ -{{> '_issues-facet-header'}} - -{{#if createdAt}} - -
- {{dt createdAt}} ({{fromNow createdAt}}) -
-{{else}} -
-
- - - -
-{{/if}} diff --git a/server/sonar-web/src/main/coffee/apps/issues/templates/facets/issues-custom-values-facet.hbs b/server/sonar-web/src/main/coffee/apps/issues/templates/facets/issues-custom-values-facet.hbs deleted file mode 100644 index c7d8a081ef1..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/templates/facets/issues-custom-values-facet.hbs +++ /dev/null @@ -1,14 +0,0 @@ -{{> '_issues-facet-header'}} - -
- {{#each values}} - - {{default label val}} - {{numberShort count}} - - {{/each}} - -
- -
-
diff --git a/server/sonar-web/src/main/coffee/apps/issues/templates/facets/issues-file-facet.hbs b/server/sonar-web/src/main/coffee/apps/issues/templates/facets/issues-file-facet.hbs deleted file mode 100644 index 530959b7d72..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/templates/facets/issues-file-facet.hbs +++ /dev/null @@ -1,10 +0,0 @@ -{{> '_issues-facet-header'}} - -
- {{#each values}} - - {{default label val}} - {{numberShort count}} - - {{/each}} -
diff --git a/server/sonar-web/src/main/coffee/apps/issues/templates/facets/issues-issue-key-facet.hbs b/server/sonar-web/src/main/coffee/apps/issues/templates/facets/issues-issue-key-facet.hbs deleted file mode 100644 index d68931e4487..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/templates/facets/issues-issue-key-facet.hbs +++ /dev/null @@ -1,7 +0,0 @@ -{{> '_issues-facet-header'}} - -
-
- {{issues}} -
-
diff --git a/server/sonar-web/src/main/coffee/apps/issues/templates/facets/issues-resolution-facet.hbs b/server/sonar-web/src/main/coffee/apps/issues/templates/facets/issues-resolution-facet.hbs deleted file mode 100644 index 08c1b25a15a..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/templates/facets/issues-resolution-facet.hbs +++ /dev/null @@ -1,20 +0,0 @@ -{{> '_issues-facet-header'}} - -
- {{#each values}} - {{#eq val ''}} - {{! unresolved }} - - {{t 'unresolved'}} - {{numberShort count}} - - {{else}} - - {{t 'issue.resolution' val}} - {{numberShort count}} - - {{/eq}} - {{/each}} -
diff --git a/server/sonar-web/src/main/coffee/apps/issues/templates/facets/issues-severity-facet.hbs b/server/sonar-web/src/main/coffee/apps/issues/templates/facets/issues-severity-facet.hbs deleted file mode 100644 index 96a6470ef72..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/templates/facets/issues-severity-facet.hbs +++ /dev/null @@ -1,11 +0,0 @@ -{{> '_issues-facet-header'}} - -
- {{#each values}} - - {{severityIcon val}} {{t 'severity' val}} - {{numberShort count}} - - {{/each}} -
diff --git a/server/sonar-web/src/main/coffee/apps/issues/templates/facets/issues-status-facet.hbs b/server/sonar-web/src/main/coffee/apps/issues/templates/facets/issues-status-facet.hbs deleted file mode 100644 index 33e556abf5e..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/templates/facets/issues-status-facet.hbs +++ /dev/null @@ -1,11 +0,0 @@ -{{> '_issues-facet-header'}} - -
- {{#each values}} - - {{statusIcon val}} {{t 'issue.status' val}} - {{numberShort count}} - - {{/each}} -
diff --git a/server/sonar-web/src/main/coffee/apps/issues/templates/issues-filters.hbs b/server/sonar-web/src/main/coffee/apps/issues/templates/issues-filters.hbs deleted file mode 100644 index a197f5335d1..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/templates/issues-filters.hbs +++ /dev/null @@ -1,55 +0,0 @@ -

- {{#if state.canManageFilters}} - - {{> '_issues-filter-name'}} - - - {{#if filter.description}} -
{{filter.description}}
- {{/if}} - {{else}} - {{t 'issues'}} - {{/if}} -

- -
-
- {{#if state.canManageFilters}} - {{#if filter.canModify}} - {{#if state.changed}} - - {{/if}} - {{/if}} - - {{#unless filter.id}} - - {{/unless}} - - {{#if filter.id}} - {{#unless state.changed}} - - {{/unless}} - {{/if}} - - {{#if filter.canModify}} - {{#if filter.id}} - - {{/if}} - {{/if}} - {{/if}} -
-
diff --git a/server/sonar-web/src/main/coffee/apps/issues/templates/issues-issue-filter-form.hbs b/server/sonar-web/src/main/coffee/apps/issues/templates/issues-issue-filter-form.hbs deleted file mode 100644 index 01515749698..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/templates/issues-issue-filter-form.hbs +++ /dev/null @@ -1,71 +0,0 @@ -
{{t 'issue.filter_similar_issues'}}
- -
- - {{severityIcon severity}} {{t 'severity' severity}} - - - - {{statusIcon status}} {{t 'issue.status' status}} - - - {{#if resolution}} - - {{t 'issue.resolution' resolution}} - - {{else}} - - {{t 'unresolved'}} - - {{/if}} - - {{#if assignee}} - - {{t 'assigned_to'}} {{assigneeName}} - - {{else}} - - {{t 'unassigned'}} - - {{/if}} - - {{#if actionPlan}} - - {{t 'issue.planned_for'}} {{actionPlanName}} - - {{else}} - - {{t 'issue.unplanned'}} - - {{/if}} - -
- - - {{limitString ruleName}} - - - {{#each tags}} - -  {{this}} - - {{/each}} - -
- - - {{qualifierIcon 'TRK'}} {{projectLongName}} - - - {{#if subProject}} - - {{qualifierIcon 'BRC'}} {{subProjectLongName}} - - {{/if}} - - - {{qualifierIcon componentQualifier}} {{fileFromPath componentLongName}} - -
- -
diff --git a/server/sonar-web/src/main/coffee/apps/issues/templates/issues-issue-filter.hbs b/server/sonar-web/src/main/coffee/apps/issues/templates/issues-issue-filter.hbs deleted file mode 100644 index 875bc3bc4a5..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/templates/issues-issue-filter.hbs +++ /dev/null @@ -1,5 +0,0 @@ -
- -   - -
diff --git a/server/sonar-web/src/main/coffee/apps/issues/templates/issues-layout.hbs b/server/sonar-web/src/main/coffee/apps/issues/templates/issues-layout.hbs deleted file mode 100644 index 5a61d1f66bf..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/templates/issues-layout.hbs +++ /dev/null @@ -1,11 +0,0 @@ -
-
-
-
- -
-
-
-
-
-
diff --git a/server/sonar-web/src/main/coffee/apps/issues/templates/issues-workspace-header.hbs b/server/sonar-web/src/main/coffee/apps/issues/templates/issues-workspace-header.hbs deleted file mode 100644 index 4b4958fd1d1..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/templates/issues-workspace-header.hbs +++ /dev/null @@ -1,37 +0,0 @@ -
- {{#if state.component}} - {{t 'issues.return_to_list'}}    - - {{#with state.component}} - {{qualifierIcon 'TRK'}} {{projectName}} -    - {{qualifierIcon qualifier}} {{name}} - {{/with}} - {{else}} -   - {{/if}} -
- - -
- {{#notNull state.total}} -
- {{#gt state.total 0}} - - {{sum state.selectedIndex 1}} / {{state.total}} - - {{else}} - 0 / 0 - {{/gt}} -
- {{/notNull}} - - -
- - - {{#if state.canBulkChange}} - - {{/if}} -
-
diff --git a/server/sonar-web/src/main/coffee/apps/issues/templates/issues-workspace-home.hbs b/server/sonar-web/src/main/coffee/apps/issues/templates/issues-workspace-home.hbs deleted file mode 100644 index 3889dcdd978..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/templates/issues-workspace-home.hbs +++ /dev/null @@ -1,77 +0,0 @@ -
-
-
-

{{t 'issues.home.recent_issues'}}

-

({{t 'issues.home.over_last_week'}})

- -
-

{{t 'issues.home.projects'}}

- - {{#each projects}} - - - - - {{/each}} -
{{qualifierIcon 'TRK'}} {{label}}+{{numberShort count}}
-

{{t 'issues.home.authors'}}

- - {{#each authors}} - - - - - {{/each}} -
{{val}}+{{numberShort count}}
-

{{t 'issues.home.tags'}}

-
    - {{#each tags}} -
  • {{val}}
  • - {{/each}} -
-
- - {{#if user}} -
-

{{t 'issues.home.my_recent_issues'}}

-

({{t 'issues.home.over_last_week'}})

- -
- {{#notEmpty myProjects}} -

{{t 'issues.home.projects'}}

- - {{#each myProjects}} - - - - - {{/each}} -
{{qualifierIcon 'TRK'}} {{label}}+{{numberShort count}}
- {{/notEmpty}} - {{#notEmpty myTags}} -

{{t 'issues.home.tags'}}

-
    - {{#each myTags}} -
  • {{val}}
  • - {{/each}} -
- {{/notEmpty}} - {{#notEmpty filters}} -

- {{t 'issues.home.my_filters'}}

-
    - {{#each filters}} -
  • - {{name}} -
  • - {{/each}} -
- {{/notEmpty}} -
- {{/if}} -
-
diff --git a/server/sonar-web/src/main/coffee/apps/issues/templates/issues-workspace-list-component.hbs b/server/sonar-web/src/main/coffee/apps/issues/templates/issues-workspace-list-component.hbs deleted file mode 100644 index d5d0b439952..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/templates/issues-workspace-list-component.hbs +++ /dev/null @@ -1,13 +0,0 @@ -
- - {{qualifierIcon 'TRK'}} {{projectLongName}} - - {{#if subProject}} - - {{qualifierIcon 'TRK'}} {{subProjectLongName}} - - {{/if}} - - {{qualifierIcon componentQualifier}} {{componentLongName}} - -
diff --git a/server/sonar-web/src/main/coffee/apps/issues/templates/issues-workspace-list.hbs b/server/sonar-web/src/main/coffee/apps/issues/templates/issues-workspace-list.hbs deleted file mode 100644 index 37421cb75c2..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/templates/issues-workspace-list.hbs +++ /dev/null @@ -1,5 +0,0 @@ -
- -
- -
diff --git a/server/sonar-web/src/main/coffee/apps/issues/workspace-header-view.coffee b/server/sonar-web/src/main/coffee/apps/issues/workspace-header-view.coffee deleted file mode 100644 index 7672d1ac41c..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/workspace-header-view.coffee +++ /dev/null @@ -1,64 +0,0 @@ -# -# SonarQube, open source software quality management tool. -# Copyright (C) 2008-2014 SonarSource -# mailto:contact AT sonarsource DOT com -# -# SonarQube 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. -# -# SonarQube 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. -# - -define [ - 'components/navigator/workspace-header-view' - './templates' -], ( - WorkspaceHeaderView -) -> - - $ = jQuery - - - class extends WorkspaceHeaderView - template: Templates['issues-workspace-header'] - - - events: -> - _.extend super, - 'click .js-back': 'returnToList' - 'click .js-new-search': 'newSearch' - - - initialize: -> - super - @_onBulkIssues = window.onBulkIssues - window.onBulkIssues = => - $('#modal').dialog 'close' - @options.app.controller.fetchList() - - - onClose: -> - window.onBulkIssues = @_onBulkIssues - - - returnToList: -> - @options.app.controller.closeComponentViewer() - - - newSearch: -> - @options.app.controller.newSearch() - - - bulkChange: -> - query = @options.app.controller.getQuery '&', true - url = "#{baseUrl}/issues/bulk_change_form?#{query}" - openModalWindow url, {} diff --git a/server/sonar-web/src/main/coffee/apps/issues/workspace-home-view.coffee b/server/sonar-web/src/main/coffee/apps/issues/workspace-home-view.coffee deleted file mode 100644 index 6bf9c15fcee..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/workspace-home-view.coffee +++ /dev/null @@ -1,149 +0,0 @@ -# -# SonarQube, open source software quality management tool. -# Copyright (C) 2008-2014 SonarSource -# mailto:contact AT sonarsource DOT com -# -# SonarQube 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. -# -# SonarQube 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. -# - -define [ - 'widgets/issue-filter/widget' - './templates' -], (IssueFilter) -> - - $ = jQuery - - - Handlebars.registerHelper 'issuesHomeLink', (property, value) -> - "#{baseUrl}/issues/search#resolved=false|createdInLast=1w|#{property}=#{encodeURIComponent value}" - - Handlebars.registerHelper 'myIssuesHomeLink', (property, value) -> - "#{baseUrl}/issues/search#resolved=false|createdInLast=1w|assignees=__me__|#{property}=#{encodeURIComponent value}" - - Handlebars.registerHelper 'issueFilterHomeLink', (id) -> - "#{baseUrl}/issues/search#id=#{id}" - - - class extends Marionette.ItemView - template: Templates['issues-workspace-home'] - - - modelEvents: - 'change': 'render' - - - events: - 'click .js-barchart rect': 'selectBar' - 'click .js-my-barchart rect': 'selectMyBar' - - - initialize: -> - @model = new Backbone.Model - @requestIssues() - @requestMyIssues() - - - _getProjects: (r) -> - projectFacet = _.findWhere r.facets, property: 'projectUuids' - if projectFacet? - values = _.head projectFacet.values, 3 - values.forEach (v) => - project = _.findWhere r.projects, uuid: v.val - v.label = project.longName - values - - - _getAuthors: (r) -> - authorFacet = _.findWhere r.facets, property: 'authors' - if authorFacet? - values = _.head authorFacet.values, 3 - values - - - _getTags: (r) -> - MIN_SIZE = 10 - MAX_SIZE = 24 - tagFacet = _.findWhere r.facets, property: 'tags' - if tagFacet? - values = _.head tagFacet.values, 10 - minCount = _.min(values, (v) -> v.count).count - maxCount = _.max(values, (v) -> v.count).count - scale = d3.scale.linear().domain([minCount, maxCount]).range([MIN_SIZE, MAX_SIZE]) - values.forEach (v) => - v.size = scale v.count - values - - - requestIssues: -> - url = "#{baseUrl}/api/issues/search" - options = - resolved: false - createdInLast: '1w' - ps: 1 - facets: 'createdAt,projectUuids,authors,tags' - $.get(url, options).done (r) => - @model.set - createdAt: _.findWhere(r.facets, property: 'createdAt')?.values - projects: @_getProjects r - authors: @_getAuthors r - tags: @_getTags r - - - requestMyIssues: -> - url = "#{baseUrl}/api/issues/search" - options = - resolved: false - createdInLast: '1w' - assignees: '__me__' - ps: 1 - facets: 'createdAt,projectUuids,authors,tags' - $.get(url, options).done (r) => - @model.set - myCreatedAt: _.findWhere(r.facets, property: 'createdAt')?.values - myProjects: @_getProjects r - myTags: @_getTags r - - - onRender: -> - values = @model.get 'createdAt' - myValues = @model.get 'myCreatedAt' - @$('.js-barchart').barchart values if values? - @$('.js-my-barchart').barchart myValues if myValues? - @$('[data-toggle="tooltip"]').tooltip container: 'body' - - - selectBar: (e) -> - periodStart = $(e.currentTarget).data 'period-start' - periodEnd = $(e.currentTarget).data 'period-end' - @options.app.state.setQuery - resolved: false - createdAfter: periodStart - createdBefore: periodEnd - - - selectMyBar: (e) -> - periodStart = $(e.currentTarget).data 'period-start' - periodEnd = $(e.currentTarget).data 'period-end' - @options.app.state.setQuery - resolved: false - assignees: '__me__' - createdAfter: periodStart - createdBefore: periodEnd - - - serializeData: -> - _.extend super, - user: window.SS.user - filters: _.sortBy @options.app.filters.toJSON(), 'name' diff --git a/server/sonar-web/src/main/coffee/apps/issues/workspace-list-empty-view.coffee b/server/sonar-web/src/main/coffee/apps/issues/workspace-list-empty-view.coffee deleted file mode 100644 index 23bba0eef47..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/workspace-list-empty-view.coffee +++ /dev/null @@ -1,28 +0,0 @@ -# -# SonarQube, open source software quality management tool. -# Copyright (C) 2008-2014 SonarSource -# mailto:contact AT sonarsource DOT com -# -# SonarQube 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. -# -# SonarQube 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. -# - -define -> - - class extends Marionette.ItemView - className: 'search-navigator-no-results' - - - template: -> - t 'issue_filter.no_issues' diff --git a/server/sonar-web/src/main/coffee/apps/issues/workspace-list-item-view.coffee b/server/sonar-web/src/main/coffee/apps/issues/workspace-list-item-view.coffee deleted file mode 100644 index 62b223fb57f..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/workspace-list-item-view.coffee +++ /dev/null @@ -1,118 +0,0 @@ -# -# SonarQube, open source software quality management tool. -# Copyright (C) 2008-2014 SonarSource -# mailto:contact AT sonarsource DOT com -# -# SonarQube 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. -# -# SonarQube 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. -# - -define [ - 'components/issue/issue-view' - './issue-filter-view' - './templates' -], ( - IssueView - IssueFilterView -) -> - - $ = jQuery - - SHOULD_NULL = - any: ['issues'] - resolutions: ['resolved'] - resolved: ['resolutions'] - assignees: ['assigned'] - assigned: ['assignees'] - actionPlans: ['planned'] - planned: ['actionPlans'] - - class extends IssueView - filterTemplate: Templates['issues-issue-filter'] - - events: -> - _.extend super, - 'click': 'selectCurrent' - 'dblclick': 'openComponentViewer' - 'click .js-issue-navigate': 'openComponentViewer' - 'click .js-issue-filter': 'onIssueFilterClick' - - - initialize: (options) -> - super - @listenTo options.app.state, 'change:selectedIndex', @select - - - onRender: -> - super - @select() - @addFilterSelect() - @$el.addClass 'issue-navigate-right' - - - onIssueFilterClick: (e) -> - e.preventDefault() - e.stopPropagation() - $('body').click() - @popup = new IssueFilterView - triggerEl: $(e.currentTarget) - bottomRight: true - model: @model - @popup.on 'select', (property, value) => - obj = {} - obj[property] = '' + value - SHOULD_NULL.any.forEach (p) -> obj[p] = null - if SHOULD_NULL[property]? - SHOULD_NULL[property].forEach (p) -> obj[p] = null - @options.app.state.updateFilter obj - @popup.close() - @popup.render() - - - - addFilterSelect: -> - @$('.issue-table-meta-cell-first').find('.issue-meta-list').append @filterTemplate @model.toJSON() - - - select: -> - selected = @model.get('index') == @options.app.state.get 'selectedIndex' - @$el.toggleClass 'selected', selected - - - selectCurrent: -> - @options.app.state.set selectedIndex: @model.get('index') - - - resetIssue: (options) -> - key = @model.get 'key' - componentUuid = @model.get 'componentUuid' - index = @model.get 'index' - @model.clear silent: true - @model.set { key: key, componentUuid: componentUuid, index: index }, { silent: true } - @model.fetch(options) - .done => - @trigger 'reset' - - - openComponentViewer: -> - @options.app.state.set selectedIndex: @model.get('index') - if @options.app.state.has 'component' - @options.app.controller.closeComponentViewer() - else - @options.app.controller.showComponentViewer @model - - - serializeData: -> - _.extend super, - showComponent: true diff --git a/server/sonar-web/src/main/coffee/apps/issues/workspace-list-view.coffee b/server/sonar-web/src/main/coffee/apps/issues/workspace-list-view.coffee deleted file mode 100644 index 889b03310a2..00000000000 --- a/server/sonar-web/src/main/coffee/apps/issues/workspace-list-view.coffee +++ /dev/null @@ -1,103 +0,0 @@ -# -# SonarQube, open source software quality management tool. -# Copyright (C) 2008-2014 SonarSource -# mailto:contact AT sonarsource DOT com -# -# SonarQube 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. -# -# SonarQube 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. -# - -define [ - 'components/navigator/workspace-list-view' - './workspace-list-item-view' - './workspace-list-empty-view' - './templates' -], ( - WorkspaceListView - IssueView - EmptyView -) -> - - $ = jQuery - - COMPONENT_HEIGHT = 29 - BOTTOM_OFFSET = 10 - - - class extends WorkspaceListView - template: Templates['issues-workspace-list'] - componentTemplate: Templates['issues-workspace-list-component'] - itemView: IssueView - itemViewContainer: '.js-list' - emptyView: EmptyView - - - bindShortcuts: -> - doAction = (action) => - selectedIssue = @collection.at @options.app.state.get 'selectedIndex' - return unless selectedIssue? - selectedIssueView = @children.findByModel selectedIssue - selectedIssueView.$(".js-issue-#{action}").click() - - super - - key 'right', 'list', => - selectedIssue = @collection.at @options.app.state.get 'selectedIndex' - @options.app.controller.showComponentViewer selectedIssue - return false - - key 'f', 'list', -> doAction 'transition' - key 'a', 'list', -> doAction 'assign' - key 'm', 'list', -> doAction 'assign-to-me' - key 'p', 'list', -> doAction 'plan' - key 'i', 'list', -> doAction 'set-severity' - key 'c', 'list', -> doAction 'comment' - key 't', 'list', -> doAction 'edit-tags' - - - scrollTo: -> - selectedIssue = @collection.at @options.app.state.get 'selectedIndex' - return unless selectedIssue? - selectedIssueView = @children.findByModel selectedIssue - parentTopOffset = @$el.offset().top - viewTop = selectedIssueView.$el.offset().top - parentTopOffset - if selectedIssueView.$el.prev().is('.issues-workspace-list-component') - viewTop -= COMPONENT_HEIGHT - viewBottom = selectedIssueView.$el.offset().top + selectedIssueView.$el.outerHeight() + BOTTOM_OFFSET - windowTop = $(window).scrollTop() - windowBottom = windowTop + $(window).height() - if viewTop < windowTop - $(window).scrollTop viewTop - if viewBottom > windowBottom - $(window).scrollTop $(window).scrollTop() - windowBottom + viewBottom - - - appendHtml: (compositeView, itemView, index) -> - $container = this.getItemViewContainer compositeView - model = @collection.at(index) - if model? - prev = @collection.at(index - 1) - putComponent = !prev? - if prev? - fullComponent = [model.get('project'), model.get('component')].join ' ' - fullPrevComponent = [prev.get('project'), prev.get('component')].join ' ' - putComponent = true unless fullComponent == fullPrevComponent - if putComponent - $container.append @componentTemplate model.toJSON() - $container.append itemView.el - - - closeChildren: -> - super - @$('.issues-workspace-list-component').remove() diff --git a/server/sonar-web/src/main/js/apps/issues/app-context.js b/server/sonar-web/src/main/js/apps/issues/app-context.js new file mode 100644 index 00000000000..bcef0841779 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/app-context.js @@ -0,0 +1,105 @@ +define([ + './models/state', + './layout', + './models/issues', + 'components/navigator/models/facets', + './models/filters', + './controller', + './router', + './workspace-list-view', + './workspace-header-view', + './facets-view' +], function (State, Layout, Issues, Facets, Filters, Controller, Router, WorkspaceListView, WorkspaceHeaderView, + FacetsView) { + + var $ = jQuery, + App = new Marionette.Application(); + + App.getContextQuery = function () { + return { componentUuids: window.config.resource }; + }; + + App.getRestrictedFacets = function () { + return { + 'TRK': ['projectUuids'], + 'BRC': ['projectUuids'], + 'DIR': ['projectUuids', 'moduleUuids', 'directories'], + 'DEV': ['authors'], + 'DEV_PRJ': ['projectUuids', 'authors'] + }; + }; + + App.updateContextFacets = function () { + var facets = this.state.get('facets'), + allFacets = this.state.get('allFacets'), + facetsFromServer = this.state.get('facetsFromServer'); + return this.state.set({ + facets: facets, + allFacets: _.difference(allFacets, this.getRestrictedFacets()[window.config.resourceQualifier]), + facetsFromServer: _.difference(facetsFromServer, this.getRestrictedFacets()[window.config.resourceQualifier]) + }); + }; + + App.addInitializer(function () { + this.state = new State({ + isContext: true, + contextQuery: this.getContextQuery(), + contextComponentUuid: window.config.resource, + contextComponentName: window.config.resourceName, + contextComponentQualifier: window.config.resourceQualifier + }); + this.updateContextFacets(); + this.list = new Issues(); + this.facets = new Facets(); + this.filters = new Filters(); + }); + + App.addInitializer(function () { + this.layout = new Layout({ app: this }); + $('.issues').empty().append(this.layout.render().el); + $('#footer').addClass('search-navigator-footer'); + }); + + App.addInitializer(function () { + this.controller = new Controller({ app: this }); + }); + + App.addInitializer(function () { + this.issuesView = new WorkspaceListView({ + app: this, + collection: this.list + }); + this.layout.workspaceListRegion.show(this.issuesView); + this.issuesView.bindScrollEvents(); + }); + + App.addInitializer(function () { + this.workspaceHeaderView = new WorkspaceHeaderView({ + app: this, + collection: this.list + }); + this.layout.workspaceHeaderRegion.show(this.workspaceHeaderView); + }); + + App.addInitializer(function () { + this.facetsView = new FacetsView({ + app: this, + collection: this.facets + }); + this.layout.facetsRegion.show(this.facetsView); + }); + + App.addInitializer(function () { + return this.controller.fetchFilters().done(function () { + key.setScope('list'); + App.router = new Router({ app: App }); + Backbone.history.start(); + }); + }); + + var l10nXHR = window.requestMessages(); + return jQuery.when(l10nXHR).done(function () { + return App.start(); + }); + +}); diff --git a/server/sonar-web/src/main/js/apps/issues/app-new.js b/server/sonar-web/src/main/js/apps/issues/app-new.js new file mode 100644 index 00000000000..07b047bfcd8 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/app-new.js @@ -0,0 +1,82 @@ +define([ + './models/state', + './layout', + './models/issues', + 'components/navigator/models/facets', + './models/filters', + './controller', + './router', + './workspace-list-view', + './workspace-header-view', + './facets-view', + './filters-view' +], function (State, Layout, Issues, Facets, Filters, Controller, Router, WorkspaceListView, WorkspaceHeaderView, + FacetsView, FiltersView) { + + var $ = jQuery, + App = new Marionette.Application(); + + App.addInitializer(function () { + this.state = new State(); + this.list = new Issues(); + this.facets = new Facets(); + this.filters = new Filters(); + }); + + App.addInitializer(function () { + this.layout = new Layout({ app: this }); + $('.issues').empty().append(this.layout.render().el); + $('#footer').addClass('search-navigator-footer'); + }); + + App.addInitializer(function () { + this.controller = new Controller({ app: this }); + }); + + App.addInitializer(function () { + this.issuesView = new WorkspaceListView({ + app: this, + collection: this.list + }); + this.layout.workspaceListRegion.show(this.issuesView); + this.issuesView.bindScrollEvents(); + }); + + App.addInitializer(function () { + this.workspaceHeaderView = new WorkspaceHeaderView({ + app: this, + collection: this.list + }); + this.layout.workspaceHeaderRegion.show(this.workspaceHeaderView); + }); + + App.addInitializer(function () { + this.facetsView = new FacetsView({ + app: this, + collection: this.facets + }); + this.layout.facetsRegion.show(this.facetsView); + }); + + App.addInitializer(function () { + this.filtersView = new FiltersView({ + app: this, + collection: this.filters + }); + this.layout.filtersRegion.show(this.filtersView); + }); + + App.addInitializer(function () { + this.controller.fetchFilters().done(function () { + key.setScope('list'); + App.router = new Router({ app: App }); + Backbone.history.start(); + }); + }); + + var l10nXHR = window.requestMessages(); + return jQuery.when(l10nXHR).done(function () { + return App.start(); + }); + +}); diff --git a/server/sonar-web/src/main/js/apps/issues/component-viewer/issue-view.js b/server/sonar-web/src/main/js/apps/issues/component-viewer/issue-view.js new file mode 100644 index 00000000000..6d8a6f73207 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/component-viewer/issue-view.js @@ -0,0 +1,18 @@ +define([ + '../workspace-list-item-view' +], function (IssueView) { + + return IssueView.extend({ + onRender: function () { + IssueView.prototype.onRender.apply(this, arguments); + this.$el.removeClass('issue-navigate-right'); + }, + + serializeData: function () { + return _.extend(IssueView.prototype.serializeData.apply(this, arguments), { + showComponent: false + }); + } + }); + +}); diff --git a/server/sonar-web/src/main/js/apps/issues/component-viewer/main.js b/server/sonar-web/src/main/js/apps/issues/component-viewer/main.js new file mode 100644 index 00000000000..a702c4a4d7f --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/component-viewer/main.js @@ -0,0 +1,204 @@ +define([ + 'components/source-viewer/main', + '../models/issues', + './issue-view', + '../templates' +], function (SourceViewer, Issues, IssueView) { + + var $ = jQuery; + + return SourceViewer.extend({ + events: function () { + return _.extend(SourceViewer.prototype.events.apply(this, arguments), { + 'click .js-close-component-viewer': 'closeComponentViewer', + 'click .code-issue': 'selectIssue' + }); + }, + + initialize: function (options) { + SourceViewer.prototype.initialize.apply(this, arguments); + return this.listenTo(options.app.state, 'change:selectedIndex', this.select); + }, + + onLoaded: function () { + SourceViewer.prototype.onLoaded.apply(this, arguments); + this.bindShortcuts(); + if (this.baseIssue != null) { + return this.scrollToLine(this.baseIssue.get('line')); + } + }, + + bindShortcuts: function () { + var that = this; + var doAction = function (action) { + var selectedIssueView = that.getSelectedIssueEl(); + if (!selectedIssueView) { + return; + } + return selectedIssueView.find('.js-issue-' + action).click(); + }; + key('up', 'componentViewer', function () { + that.options.app.controller.selectPrev(); + return false; + }); + key('down', 'componentViewer', function () { + that.options.app.controller.selectNext(); + return false; + }); + key('left,backspace', 'componentViewer', function () { + that.options.app.controller.closeComponentViewer(); + return false; + }); + key('f', 'componentViewer', function () { + return doAction('transition'); + }); + key('a', 'componentViewer', function () { + return doAction('assign'); + }); + key('m', 'componentViewer', function () { + return doAction('assign-to-me'); + }); + key('p', 'componentViewer', function () { + return doAction('plan'); + }); + key('i', 'componentViewer', function () { + return doAction('set-severity'); + }); + return key('c', 'componentViewer', function () { + return doAction('comment'); + }); + }, + + unbindShortcuts: function () { + return key.deleteScope('componentViewer'); + }, + + onClose: function () { + SourceViewer.prototype.onClose.apply(this, arguments); + this.unbindScrollEvents(); + return this.unbindShortcuts(); + }, + + select: function () { + var selected = this.options.app.state.get('selectedIndex'), + selectedIssue = this.options.app.list.at(selected); + if (selectedIssue.get('component') === this.model.get('key')) { + return this.scrollToIssue(selectedIssue.get('key')); + } else { + this.unbindShortcuts(); + return this.options.app.controller.showComponentViewer(selectedIssue); + } + }, + + getSelectedIssueEl: function () { + var selected = this.options.app.state.get('selectedIndex'); + if (selected == null) { + return null; + } + var selectedIssue = this.options.app.list.at(selected); + if (selectedIssue == null) { + return null; + } + var selectedIssueView = this.$('#issue-' + (selectedIssue.get('key'))); + if (selectedIssueView.length > 0) { + return selectedIssueView; + } else { + return null; + } + }, + + selectIssue: function (e) { + var key = $(e.currentTarget).data('issue-key'), + issue = this.issues.find(function (issue) { + return issue.get('key') === key; + }), + index = this.options.app.list.indexOf(issue); + return this.options.app.state.set({ selectedIndex: index }); + }, + + scrollToIssue: function (key) { + var el = this.$('#issue-' + key); + if (el.length > 0) { + var line = el.closest('[data-line-number]').data('line-number'); + return this.scrollToLine(line); + } else { + this.unbindShortcuts(); + var selected = this.options.app.state.get('selectedIndex'), + selectedIssue = this.options.app.list.at(selected); + return this.options.app.controller.showComponentViewer(selectedIssue); + } + }, + + openFileByIssue: function (issue) { + this.baseIssue = issue; + var componentKey = issue.get('component'), + componentUuid = issue.get('componentUuid'); + return this.open(componentUuid, componentKey); + }, + + linesLimit: function () { + var line = this.LINES_LIMIT / 2; + if ((this.baseIssue != null) && this.baseIssue.has('line')) { + line = Math.max(line, this.baseIssue.get('line')); + } + return { + from: line - this.LINES_LIMIT / 2 + 1, + to: line + this.LINES_LIMIT / 2 + }; + }, + + limitIssues: function (issues) { + var that = this; + var index = this.ISSUES_LIMIT / 2; + if ((this.baseIssue != null) && this.baseIssue.has('index')) { + index = Math.max(index, this.baseIssue.get('index')); + } + return issues.filter(function (issue) { + return Math.abs(issue.get('index') - index) <= that.ISSUES_LIMIT / 2; + }); + }, + + requestIssues: function () { + var that = this; + var r; + if (this.options.app.list.last().get('component') === this.model.get('key')) { + r = this.options.app.controller.fetchNextPage(); + } else { + r = $.Deferred().resolve().promise(); + } + return r.done(function () { + that.issues.reset(that.options.app.list.filter(function (issue) { + return issue.get('component') === that.model.key(); + })); + that.issues.reset(that.limitIssues(that.issues)); + return that.addIssuesPerLineMeta(that.issues); + }); + }, + + renderIssues: function () { + this.issues.forEach(this.renderIssue, this); + return this.$('.source-line-issues').addClass('hidden'); + }, + + renderIssue: function (issue) { + var issueView = new IssueView({ + el: '#issue-' + issue.get('key'), + model: issue, + app: this.options.app + }); + this.issueViews.push(issueView); + return issueView.render(); + }, + + scrollToLine: function (line) { + var row = this.$('[data-line-number=' + line + ']'), + goal = row.length > 0 ? row.offset().top - 200 : 0; + return $(window).scrollTop(goal); + }, + + closeComponentViewer: function () { + return this.options.app.controller.closeComponentViewer(); + } + }); + +}); diff --git a/server/sonar-web/src/main/js/apps/issues/controller.js b/server/sonar-web/src/main/js/apps/issues/controller.js new file mode 100644 index 00000000000..15ccdda827f --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/controller.js @@ -0,0 +1,249 @@ +define([ + 'components/navigator/controller', + './component-viewer/main', + './workspace-home-view' +], function (Controller, ComponentViewer, HomeView) { + + var $ = jQuery, + EXTRA_FIELDS = 'actions,transitions,assigneeName,reporterName,actionPlanName', + FACET_DATA_FIELDS = ['components', 'projects', 'users', 'rules', 'actionPlans', 'languages']; + + return Controller.extend({ + _facetsFromServer: function () { + var facets = Controller.prototype._facetsFromServer.apply(this, arguments) || []; + facets.push('assigned_to_me'); + return facets; + }, + + _issuesParameters: function () { + return { + p: this.options.app.state.get('page'), + ps: this.pageSize, + s: 'FILE_LINE', + asc: true, + extra_fields: EXTRA_FIELDS, + facets: this._facetsFromServer().join() + }; + }, + + _myIssuesFromResponse: function (r) { + var 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: function (firstPage) { + var that = this; + if (firstPage == null) { + firstPage = true; + } + if (firstPage) { + this.options.app.state.set({ selectedIndex: 0, page: 1 }, { silent: true }); + this.hideHomePage(); + this.closeComponentViewer(); + } + var data = this._issuesParameters(); + _.extend(data, this.options.app.state.get('query')); + if (this.options.app.state.get('isContext')) { + _.extend(data, this.options.app.state.get('contextQuery')); + } + return $.get(baseUrl + '/api/issues/search', data).done(function (r) { + var issues = that.options.app.list.parseIssues(r); + if (firstPage) { + that.options.app.list.reset(issues); + } else { + that.options.app.list.add(issues); + } + that.options.app.list.setIndex(); + FACET_DATA_FIELDS.forEach(function (field) { + 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.enableFacets(that._enabledFacets()); + that.options.app.state.set({ + page: r.p, + pageSize: r.ps, + total: r.total, + maxResultsReached: r.p * r.ps >= r.total + }); + if (firstPage && that.isIssuePermalink()) { + return that.showComponentViewer(that.options.app.list.first()); + } + }); + }, + + isIssuePermalink: function () { + var query = this.options.app.state.get('query'); + return (query.issues != null) && this.options.app.list.length === 1; + }, + + fetchFilters: function () { + var that = this; + return $.get(baseUrl + '/api/issue_filters/app', function (r) { + that.options.app.state.set({ + canBulkChange: r.canBulkChange, + canManageFilters: r.canManageFilters + }); + return that.options.app.filters.reset(r.favorites); + }); + }, + + _mergeCollections: function (a, b) { + var collection = new Backbone.Collection(a); + collection.add(b, { merge: true }); + return collection.toJSON(); + }, + + requestFacet: function (id) { + var that = this; + if (id === 'assignees') { + return this.requestAssigneeFacet(); + } + var facet = this.options.app.facets.get(id), + data = _.extend({ facets: id, ps: 1 }, this.options.app.state.get('query')); + if (this.options.app.state.get('isContext')) { + _.extend(data, this.options.app.state.get('contextQuery')); + } + return $.get(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]); + }); + var facetData = _.findWhere(r.facets, { property: id }); + if (facetData != null) { + return facet.set(facetData); + } + }); + }, + + requestAssigneeFacet: function () { + var that = this; + var facet = this.options.app.facets.get('assignees'), + data = _.extend({ facets: 'assignees,assigned_to_me', ps: 1 }, this.options.app.state.get('query')); + if (this.options.app.state.get('isContext')) { + _.extend(data, this.options.app.state.get('contextQuery')); + } + return $.get(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]); + }); + var facetData = _.findWhere(r.facets, { property: 'assignees' }); + that._myIssuesFromResponse(r); + if (facetData != null) { + return facet.set(facetData); + } + }); + }, + + newSearch: function () { + this.options.app.state.unset('filter'); + return this.options.app.state.setQuery({ resolved: 'false' }); + }, + + applyFilter: function (filter, ignoreQuery) { + if (ignoreQuery == null) { + ignoreQuery = false; + } + if (!ignoreQuery) { + var filterQuery = this.parseQuery(filter.get('query')); + this.options.app.state.setQuery(filterQuery); + } + return this.options.app.state.set({ filter: filter, changed: false }); + }, + + parseQuery: function () { + var q = Controller.prototype.parseQuery.apply(this, arguments); + delete q.asc; + delete q.s; + return q; + }, + + getQuery: function (separator, addContext) { + if (separator == null) { + separator = '|'; + } + if (addContext == null) { + addContext = false; + } + var filter = this.options.app.state.get('query'); + if (addContext && this.options.app.state.get('isContext')) { + _.extend(filter, this.options.app.state.get('contextQuery')); + } + var route = []; + _.map(filter, function (value, property) { + return route.push('' + property + '=' + encodeURIComponent(value)); + }); + return route.join(separator); + }, + + getRoute: function () { + var filter = this.options.app.state.get('filter'), + query = Controller.prototype.getRoute.apply(this, arguments); + if (filter != null) { + if (this.options.app.state.get('changed') && query.length > 0) { + query = 'id=' + filter.id + '|' + query; + } else { + query = 'id=' + filter.id; + } + } + return query; + }, + + _prepareComponent: function (issue) { + return { + key: issue.get('component'), + name: issue.get('componentLongName'), + qualifier: issue.get('componentQualifier'), + project: issue.get('project'), + projectName: issue.get('projectLongName') + }; + }, + + showComponentViewer: function (issue) { + this.options.app.layout.workspaceComponentViewerRegion.reset(); + key.setScope('componentViewer'); + this.options.app.issuesView.unbindScrollEvents(); + this.options.app.state.set('component', this._prepareComponent(issue)); + this.options.app.componentViewer = new ComponentViewer({ app: this.options.app }); + this.options.app.layout.workspaceComponentViewerRegion.show(this.options.app.componentViewer); + this.options.app.layout.showComponentViewer(); + return this.options.app.componentViewer.openFileByIssue(issue); + }, + + closeComponentViewer: function () { + key.setScope('list'); + $('body').click(); + this.options.app.state.unset('component'); + this.options.app.layout.workspaceComponentViewerRegion.reset(); + this.options.app.layout.hideComponentViewer(); + this.options.app.issuesView.bindScrollEvents(); + return this.options.app.issuesView.scrollTo(); + }, + + showHomePage: function () { + this.fetchList(); + this.options.app.layout.workspaceComponentViewerRegion.reset(); + key.setScope('home'); + this.options.app.issuesView.unbindScrollEvents(); + this.options.app.homeView = new HomeView({ app: this.options.app }); + this.options.app.layout.workspaceHomeRegion.show(this.options.app.homeView); + return this.options.app.layout.showHomePage(); + }, + + hideHomePage: function () { + this.options.app.layout.workspaceComponentViewerRegion.reset(); + this.options.app.layout.workspaceHomeRegion.reset(); + key.setScope('list'); + this.options.app.layout.hideHomePage(); + this.options.app.issuesView.bindScrollEvents(); + return this.options.app.issuesView.scrollTo(); + } + }); + +}); diff --git a/server/sonar-web/src/main/js/apps/issues/facets-view.js b/server/sonar-web/src/main/js/apps/issues/facets-view.js new file mode 100644 index 00000000000..2409c25b019 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/facets-view.js @@ -0,0 +1,65 @@ +define([ + 'components/navigator/facets-view', + './facets/base-facet', + './facets/severity-facet', + './facets/status-facet', + './facets/project-facet', + './facets/module-facet', + './facets/assignee-facet', + './facets/rule-facet', + './facets/tag-facet', + './facets/resolution-facet', + './facets/creation-date-facet', + './facets/action-plan-facet', + './facets/file-facet', + './facets/reporter-facet', + './facets/language-facet', + './facets/author-facet', + './facets/issue-key-facet', + './facets/context-facet' +], function (FacetsView, BaseFacet, SeverityFacet, StatusFacet, ProjectFacet, ModuleFacet, AssigneeFacet, RuleFacet, + TagFacet, ResolutionFacet, CreationDateFacet, ActionPlanFacet, FileFacet, ReporterFacet, LanguageFacet, + AuthorFacet, IssueKeyFacet, ContextFacet) { + + return FacetsView.extend({ + getItemView: function (model) { + switch (model.get('property')) { + case 'severities': + return SeverityFacet; + case 'statuses': + return StatusFacet; + case 'assignees': + return AssigneeFacet; + case 'resolutions': + return ResolutionFacet; + case 'createdAt': + return CreationDateFacet; + case 'projectUuids': + return ProjectFacet; + case 'moduleUuids': + return ModuleFacet; + case 'rules': + return RuleFacet; + case 'tags': + return TagFacet; + case 'actionPlans': + return ActionPlanFacet; + case 'fileUuids': + return FileFacet; + case 'reporters': + return ReporterFacet; + case 'languages': + return LanguageFacet; + case 'authors': + return AuthorFacet; + case 'issues': + return IssueKeyFacet; + case 'context': + return ContextFacet; + default: + return BaseFacet; + } + } + }); + +}); diff --git a/server/sonar-web/src/main/js/apps/issues/facets/action-plan-facet.js b/server/sonar-web/src/main/js/apps/issues/facets/action-plan-facet.js new file mode 100644 index 00000000000..d85fa9e5dfd --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/facets/action-plan-facet.js @@ -0,0 +1,68 @@ +define([ + './base-facet', + '../templates' +], function (BaseFacet) { + + var $ = jQuery; + + return BaseFacet.extend({ + template: Templates['issues-action-plan-facet'], + + onRender: function () { + BaseFacet.prototype.onRender.apply(this, arguments); + var value = this.options.app.state.get('query').planned; + if ((value != null) && (!value || value === 'false')) { + return this.$('.js-facet').filter('[data-unplanned]').addClass('active'); + } + }, + + toggleFacet: function (e) { + var unplanned = $(e.currentTarget).is('[data-unplanned]'); + $(e.currentTarget).toggleClass('active'); + if (unplanned) { + var checked = $(e.currentTarget).is('.active'), + value = checked ? 'false' : null; + return this.options.app.state.updateFilter({ + planned: value, + actionPlans: null + }); + } else { + return this.options.app.state.updateFilter({ + planned: null, + actionPlans: this.getValue() + }); + } + }, + + getValuesWithLabels: function () { + var values = this.model.getValues(), + actionPlans = this.options.app.facets.actionPlans; + values.forEach(function (v) { + var key = v.val, + label = null; + if (key) { + var actionPlan = _.findWhere(actionPlans, { key: key }); + if (actionPlan != null) { + label = actionPlan.name; + } + } + v.label = label; + }); + return values; + }, + + disable: function () { + return this.options.app.state.updateFilter({ + planned: null, + actionPlans: null + }); + }, + + serializeData: function () { + return _.extend(BaseFacet.prototype.serializeData.apply(this, arguments), { + values: this.getValuesWithLabels() + }); + } + }); + +}); 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 new file mode 100644 index 00000000000..3645b7215d6 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/facets/assignee-facet.js @@ -0,0 +1,108 @@ +define([ + './custom-values-facet', + '../templates' +], function (CustomValuesFacet) { + + var $ = jQuery; + + return CustomValuesFacet.extend({ + template: Templates['issues-assignee-facet'], + + getUrl: function () { + return baseUrl + '/api/users/search'; + }, + + prepareAjaxSearch: function () { + return { + quietMillis: 300, + url: this.getUrl(), + data: function (term, page) { + return { q: term, p: page }; + }, + results: window.usersToSelect2 + }; + }, + + onRender: function () { + CustomValuesFacet.prototype.onRender.apply(this, arguments); + var value = this.options.app.state.get('query').assigned; + if ((value != null) && (!value || value === 'false')) { + return this.$('.js-facet').filter('[data-unassigned]').addClass('active'); + } + }, + + toggleFacet: function (e) { + var unassigned = $(e.currentTarget).is('[data-unassigned]'); + $(e.currentTarget).toggleClass('active'); + if (unassigned) { + var checked = $(e.currentTarget).is('.active'), + value = checked ? 'false' : null; + return this.options.app.state.updateFilter({ + assigned: value, + assignees: null + }); + } else { + return this.options.app.state.updateFilter({ + assigned: null, + assignees: this.getValue() + }); + } + }, + + getValuesWithLabels: function () { + var values = this.model.getValues(), + users = this.options.app.facets.users; + values.forEach(function (v) { + var login = v.val, + name = ''; + if (login) { + var user = _.findWhere(users, { login: login }); + if (user != null) { + name = user.name; + } + } + v.label = name; + }); + return values; + }, + + disable: function () { + return this.options.app.state.updateFilter({ + assigned: null, + assignees: null + }); + }, + + addCustomValue: function () { + var property = this.model.get('property'), + customValue = this.$('.js-custom-value').select2('val'), + value = this.getValue(); + if (value.length > 0) { + value += ','; + } + value += customValue; + var obj = {}; + obj[property] = value; + obj.assigned = null; + return this.options.app.state.updateFilter(obj); + }, + + sortValues: function (values) { + return _.sortBy(values, function (v) { + return v.val === '' ? -999999 : -v.count; + }); + }, + + getNumberOfMyIssues: function () { + return this.options.app.state.get('myIssues'); + }, + + serializeData: function () { + 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/author-facet.js b/server/sonar-web/src/main/js/apps/issues/facets/author-facet.js new file mode 100644 index 00000000000..ee987a3d067 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/facets/author-facet.js @@ -0,0 +1,44 @@ +define([ + './custom-values-facet' +], function (CustomValuesFacet) { + + return CustomValuesFacet.extend({ + getUrl: function () { + return baseUrl + '/api/issues/authors'; + }, + + prepareSearch: function () { + return this.$('.js-custom-value').select2({ + placeholder: 'Search...', + minimumInputLength: 2, + allowClear: false, + formatNoMatches: function () { + return t('select2.noMatches'); + }, + formatSearching: function () { + return t('select2.searching'); + }, + formatInputTooShort: function () { + return tp('select2.tooShort', 2); + }, + width: '100%', + ajax: { + quietMillis: 300, + url: this.getUrl(), + data: function (term) { + return { q: term, ps: 25 }; + }, + results: function (data) { + return { + more: false, + results: data.authors.map(function (author) { + return { id: author, text: author }; + }) + }; + } + } + }); + } + }); + +}); diff --git a/server/sonar-web/src/main/js/apps/issues/facets/base-facet.js b/server/sonar-web/src/main/js/apps/issues/facets/base-facet.js new file mode 100644 index 00000000000..1376e8b6611 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/facets/base-facet.js @@ -0,0 +1,19 @@ +define([ + 'components/navigator/facets/base-facet', + '../templates' +], function (BaseFacet) { + + return BaseFacet.extend({ + template: Templates['issues-base-facet'], + + onRender: function () { + BaseFacet.prototype.onRender.apply(this, arguments); + return this.$('[data-toggle="tooltip"]').tooltip({ container: 'body' }); + }, + + onClose: function () { + return this.$('[data-toggle="tooltip"]').tooltip('destroy'); + } + }); + +}); diff --git a/server/sonar-web/src/main/js/apps/issues/facets/context-facet.js b/server/sonar-web/src/main/js/apps/issues/facets/context-facet.js new file mode 100644 index 00000000000..48c88c8f1c0 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/facets/context-facet.js @@ -0,0 +1,16 @@ +define([ + './base-facet', + '../templates' +], function (BaseFacet) { + + return BaseFacet.extend({ + template: Templates['issues-context-facet'], + + serializeData: function () { + return _.extend(BaseFacet.prototype.serializeData.apply(this, arguments), { + state: this.options.app.state.toJSON() + }); + } + }); + +}); diff --git a/server/sonar-web/src/main/js/apps/issues/facets/creation-date-facet.js b/server/sonar-web/src/main/js/apps/issues/facets/creation-date-facet.js new file mode 100644 index 00000000000..30305f317f1 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/facets/creation-date-facet.js @@ -0,0 +1,131 @@ +define([ + './base-facet', + '../templates' +], function (BaseFacet) { + + var $ = jQuery; + + return BaseFacet.extend({ + template: Templates['issues-creation-date-facet'], + + events: function () { + return _.extend(BaseFacet.prototype.events.apply(this, arguments), { + 'change input': 'applyFacet', + 'click .js-select-period-start': 'selectPeriodStart', + 'click .js-select-period-end': 'selectPeriodEnd', + 'click .sonar-d3 rect': 'selectBar', + 'click .js-all': 'onAllClick', + 'click .js-last-week': 'onLastWeekClick', + 'click .js-last-month': 'onLastMonthClick', + 'click .js-last-year': 'onLastYearClick' + }); + }, + + onRender: function () { + var that = this; + this.$el.toggleClass('search-navigator-facet-box-collapsed', !this.model.get('enabled')); + this.$('input').datepicker({ + dateFormat: 'yy-mm-dd', + changeMonth: true, + changeYear: true + }); + var props = ['createdAfter', 'createdBefore', 'createdAt'], + query = this.options.app.state.get('query'); + props.forEach(function (prop) { + var value = query[prop]; + if (value != null) { + return that.$('input[name=' + prop + ']').val(value); + } + }); + var values = this.model.getValues(); + if (!(_.isArray(values) && values.length > 0)) { + var date = moment(), + i, j; + values = []; + for (i = j = 0; j <= 10; i = ++j) { + values.push({ count: 0, val: date.toDate().toString() }); + date = date.subtract(1, 'days'); + } + values.reverse(); + } + return this.$('.js-barchart').barchart(values); + }, + + selectPeriodStart: function () { + return this.$('.js-period-start').datepicker('show'); + }, + + selectPeriodEnd: function () { + return this.$('.js-period-end').datepicker('show'); + }, + + applyFacet: function () { + var obj = { createdAt: null, createdInLast: null }; + this.$('input').each(function () { + var property, value; + property = $(this).prop('name'); + value = $(this).val(); + obj[property] = value; + }); + return this.options.app.state.updateFilter(obj); + }, + + disable: function () { + return this.options.app.state.updateFilter({ + createdAfter: null, + createdBefore: null, + createdAt: null, + createdInLast: null + }); + }, + + selectBar: function (e) { + var periodStart = $(e.currentTarget).data('period-start'), + periodEnd = $(e.currentTarget).data('period-end'); + return this.options.app.state.updateFilter({ + createdAfter: periodStart, + createdBefore: periodEnd, + createdAt: null, + createdInLast: null + }); + }, + + selectPeriod: function (period) { + return this.options.app.state.updateFilter({ + createdAfter: null, + createdBefore: null, + createdAt: null, + createdInLast: period + }); + }, + + onAllClick: function () { + return this.disable(); + }, + + onLastWeekClick: function (e) { + e.preventDefault(); + return this.selectPeriod('1w'); + }, + + onLastMonthClick: function (e) { + e.preventDefault(); + return this.selectPeriod('1m'); + }, + + onLastYearClick: function (e) { + e.preventDefault(); + return this.selectPeriod('1y'); + }, + + serializeData: function () { + return _.extend(BaseFacet.prototype.serializeData.apply(this, arguments), { + periodStart: this.options.app.state.get('query').createdAfter, + periodEnd: this.options.app.state.get('query').createdBefore, + createdAt: this.options.app.state.get('query').createdAt, + createdInLast: this.options.app.state.get('query').createdInLast + }); + } + }); + +}); diff --git a/server/sonar-web/src/main/js/apps/issues/facets/custom-values-facet.js b/server/sonar-web/src/main/js/apps/issues/facets/custom-values-facet.js new file mode 100644 index 00000000000..11b3aebdd74 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/facets/custom-values-facet.js @@ -0,0 +1,70 @@ +define([ + './base-facet', + '../templates' +], function (BaseFacet) { + + return BaseFacet.extend({ + template: Templates['issues-custom-values-facet'], + + events: function () { + return _.extend(BaseFacet.prototype.events.apply(this, arguments), { + 'change .js-custom-value': 'addCustomValue' + }); + }, + + getUrl: function () { + + }, + + onRender: function () { + BaseFacet.prototype.onRender.apply(this, arguments); + return this.prepareSearch(); + }, + + prepareSearch: function () { + return this.$('.js-custom-value').select2({ + placeholder: 'Search...', + minimumInputLength: 2, + allowClear: false, + formatNoMatches: function () { + return t('select2.noMatches'); + }, + formatSearching: function () { + return t('select2.searching'); + }, + formatInputTooShort: function () { + return tp('select2.tooShort', 2); + }, + width: '100%', + ajax: this.prepareAjaxSearch() + }); + }, + + prepareAjaxSearch: function () { + return { + quietMillis: 300, + url: this.getUrl(), + data: function (term, page) { + return { s: term, p: page }; + }, + results: function (data) { + return { more: data.more, results: data.results }; + } + }; + }, + + addCustomValue: function () { + var property = this.model.get('property'), + customValue = this.$('.js-custom-value').select2('val'), + value = this.getValue(); + if (value.length > 0) { + value += ','; + } + value += customValue; + var obj = {}; + obj[property] = value; + return this.options.app.state.updateFilter(obj); + } + }); + +}); diff --git a/server/sonar-web/src/main/js/apps/issues/facets/file-facet.js b/server/sonar-web/src/main/js/apps/issues/facets/file-facet.js new file mode 100644 index 00000000000..d01340e6d3c --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/facets/file-facet.js @@ -0,0 +1,43 @@ +define([ + './base-facet', + '../templates' +], function (BaseFacet) { + + var $ = jQuery; + + return BaseFacet.extend({ + template: Templates['issues-file-facet'], + + onRender: function () { + BaseFacet.prototype.onRender.apply(this, arguments); + var maxValueWidth = _.max(this.$('.facet-stat').map(function () { + return $(this).outerWidth(); + }).get()); + return this.$('.facet-name').css('padding-right', maxValueWidth); + }, + + getValuesWithLabels: function () { + var values = this.model.getValues(), + source = this.options.app.facets.components; + values.forEach(function (v) { + var key = v.val, + label = null; + if (key) { + var item = _.findWhere(source, { uuid: key }); + if (item != null) { + label = item.longName; + } + } + v.label = label; + }); + return values; + }, + + serializeData: function () { + return _.extend(BaseFacet.prototype.serializeData.apply(this, arguments), { + values: this.sortValues(this.getValuesWithLabels()) + }); + } + }); + +}); diff --git a/server/sonar-web/src/main/js/apps/issues/facets/issue-key-facet.js b/server/sonar-web/src/main/js/apps/issues/facets/issue-key-facet.js new file mode 100644 index 00000000000..2d309b85a3e --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/facets/issue-key-facet.js @@ -0,0 +1,24 @@ +define([ + './base-facet', + '../templates' +], function (BaseFacet) { + + return BaseFacet.extend({ + template: Templates['issues-issue-key-facet'], + + onRender: function () { + return this.$el.toggleClass('hidden', !this.options.app.state.get('query').issues); + }, + + disable: function () { + return this.options.app.state.updateFilter({ issues: null }); + }, + + serializeData: function () { + return _.extend(BaseFacet.prototype.serializeData.apply(this, arguments), { + issues: this.options.app.state.get('query').issues + }); + } + }); + +}); diff --git a/server/sonar-web/src/main/js/apps/issues/facets/language-facet.js b/server/sonar-web/src/main/js/apps/issues/facets/language-facet.js new file mode 100644 index 00000000000..3418158fba4 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/facets/language-facet.js @@ -0,0 +1,67 @@ +define([ + './custom-values-facet' +], function (CustomValuesFacet) { + + return CustomValuesFacet.extend({ + getUrl: function () { + return baseUrl + '/api/languages/list'; + }, + + prepareSearch: function () { + return this.$('.js-custom-value').select2({ + placeholder: 'Search...', + minimumInputLength: 2, + allowClear: false, + formatNoMatches: function () { + return t('select2.noMatches'); + }, + formatSearching: function () { + return t('select2.searching'); + }, + formatInputTooShort: function () { + return tp('select2.tooShort', 2); + }, + width: '100%', + ajax: { + quietMillis: 300, + url: this.getUrl(), + data: function (term) { + return { q: term, ps: 0 }; + }, + results: function (data) { + return { + more: false, + results: data.languages.map(function (lang) { + return { id: lang.key, text: lang.name }; + }) + }; + } + } + }); + }, + + getValuesWithLabels: function () { + var values = this.model.getValues(), + source = this.options.app.facets.languages; + values.forEach(function (v) { + var key = v.val, + label = null; + if (key) { + var item = _.findWhere(source, { key: key }); + if (item != null) { + label = item.name; + } + } + v.label = label; + }); + return values; + }, + + serializeData: function () { + return _.extend(CustomValuesFacet.prototype.serializeData.apply(this, arguments), { + values: this.sortValues(this.getValuesWithLabels()) + }); + } + }); + +}); diff --git a/server/sonar-web/src/main/js/apps/issues/facets/module-facet.js b/server/sonar-web/src/main/js/apps/issues/facets/module-facet.js new file mode 100644 index 00000000000..96c4a1de07f --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/facets/module-facet.js @@ -0,0 +1,30 @@ +define([ + './base-facet' +], function (BaseFacet) { + + return BaseFacet.extend({ + getValuesWithLabels: function () { + var values = this.model.getValues(), + components = this.options.app.facets.components; + values.forEach(function (v) { + var uuid = v.val, + label = uuid; + if (uuid) { + var component = _.findWhere(components, { uuid: uuid }); + if (component != null) { + label = component.longName; + } + } + v.label = label; + }); + return values; + }, + + serializeData: function () { + return _.extend(BaseFacet.prototype.serializeData.apply(this, arguments), { + values: this.sortValues(this.getValuesWithLabels()) + }); + } + }); + +}); diff --git a/server/sonar-web/src/main/js/apps/issues/facets/project-facet.js b/server/sonar-web/src/main/js/apps/issues/facets/project-facet.js new file mode 100644 index 00000000000..ad7126b427d --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/facets/project-facet.js @@ -0,0 +1,83 @@ +define([ + './custom-values-facet' +], function (CustomValuesFacet) { + + return CustomValuesFacet.extend({ + + getUrl: function () { + var q = this.options.app.state.get('contextComponentQualifier'); + if (q === 'VW' || q === 'SVW') { + return baseUrl + '/api/components/search'; + } else { + return baseUrl + '/api/resources/search?f=s2&q=TRK&display_uuid=true'; + } + }, + + prepareSearch: function () { + var q = this.options.app.state.get('contextComponentQualifier'); + if (q === 'VW' || q === 'SVW') { + return this.prepareSearchForViews(); + } else { + return CustomValuesFacet.prototype.prepareSearch.apply(this, arguments); + } + }, + + prepareSearchForViews: function () { + var componentUuid = this.options.app.state.get('contextComponentUuid'); + return this.$('.js-custom-value').select2({ + placeholder: 'Search...', + minimumInputLength: 2, + allowClear: false, + formatNoMatches: function () { + return t('select2.noMatches'); + }, + formatSearching: function () { + return t('select2.searching'); + }, + formatInputTooShort: function () { + return tp('select2.tooShort', 2); + }, + width: '100%', + ajax: { + quietMillis: 300, + url: this.getUrl(), + data: function (term, page) { + return { q: term, componentUuid: componentUuid, p: page, ps: 25 }; + }, + results: function (data) { + return { + more: data.p * data.ps < data.total, + results: data.components.map(function (c) { + return { id: c.uuid, text: c.name }; + }) + }; + } + } + }); + }, + + getValuesWithLabels: function () { + var values = this.model.getValues(), + projects = this.options.app.facets.projects; + values.forEach(function (v) { + var uuid = v.val, + label = ''; + if (uuid) { + var project = _.findWhere(projects, { uuid: uuid }); + if (project != null) { + label = project.longName; + } + } + v.label = label; + }); + return values; + }, + + serializeData: function () { + return _.extend(CustomValuesFacet.prototype.serializeData.apply(this, arguments), { + values: this.sortValues(this.getValuesWithLabels()) + }); + } + }); + +}); diff --git a/server/sonar-web/src/main/js/apps/issues/facets/reporter-facet.js b/server/sonar-web/src/main/js/apps/issues/facets/reporter-facet.js new file mode 100644 index 00000000000..6340aefe04f --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/facets/reporter-facet.js @@ -0,0 +1,46 @@ +define([ + './custom-values-facet' +], function (CustomValuesFacet) { + + return CustomValuesFacet.extend({ + getUrl: function () { + return baseUrl + '/api/users/search'; + }, + + prepareAjaxSearch: function () { + return { + quietMillis: 300, + url: this.getUrl(), + data: function (term, page) { + return { q: term, p: page }; + }, + results: window.usersToSelect2 + }; + }, + + getValuesWithLabels: function () { + var values = this.model.getValues(), + source = this.options.app.facets.users; + values.forEach(function (v) { + var item, key, label; + key = v.val; + label = null; + if (key) { + item = _.findWhere(source, { login: key }); + if (item != null) { + label = item.name; + } + } + v.label = label; + }); + return values; + }, + + serializeData: function () { + return _.extend(CustomValuesFacet.prototype.serializeData.apply(this, arguments), { + values: this.sortValues(this.getValuesWithLabels()) + }); + } + }); + +}); diff --git a/server/sonar-web/src/main/js/apps/issues/facets/resolution-facet.js b/server/sonar-web/src/main/js/apps/issues/facets/resolution-facet.js new file mode 100644 index 00000000000..75dd3e78289 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/facets/resolution-facet.js @@ -0,0 +1,52 @@ +define([ + './base-facet', + '../templates' +], function (BaseFacet) { + + var $ = jQuery; + + return BaseFacet.extend({ + template: Templates['issues-resolution-facet'], + + onRender: function () { + BaseFacet.prototype.onRender.apply(this, arguments); + var value = this.options.app.state.get('query').resolved; + if ((value != null) && (!value || value === 'false')) { + return this.$('.js-facet').filter('[data-unresolved]').addClass('active'); + } + }, + + toggleFacet: function (e) { + var unresolved = $(e.currentTarget).is('[data-unresolved]'); + $(e.currentTarget).toggleClass('active'); + if (unresolved) { + var checked = $(e.currentTarget).is('.active'), + value = checked ? 'false' : null; + return this.options.app.state.updateFilter({ + resolved: value, + resolutions: null + }); + } else { + return this.options.app.state.updateFilter({ + resolved: null, + resolutions: this.getValue() + }); + } + }, + + disable: function () { + return this.options.app.state.updateFilter({ + resolved: null, + resolutions: null + }); + }, + + sortValues: function (values) { + var order = ['', 'FIXED', 'FALSE-POSITIVE', 'WONTFIX', 'REMOVED']; + return _.sortBy(values, function (v) { + return order.indexOf(v.val); + }); + } + }); + +}); diff --git a/server/sonar-web/src/main/js/apps/issues/facets/rule-facet.js b/server/sonar-web/src/main/js/apps/issues/facets/rule-facet.js new file mode 100644 index 00000000000..569fcf6c7de --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/facets/rule-facet.js @@ -0,0 +1,78 @@ +define([ + './custom-values-facet' +], function (CustomValuesFacet) { + + return CustomValuesFacet.extend({ + prepareSearch: function () { + var url = baseUrl + '/api/rules/search?f=name,langName', + languages = this.options.app.state.get('query').languages; + if (languages != null) { + url += '&languages=' + languages; + } + return this.$('.js-custom-value').select2({ + placeholder: 'Search...', + minimumInputLength: 2, + allowClear: false, + formatNoMatches: function () { + return t('select2.noMatches'); + }, + formatSearching: function () { + return t('select2.searching'); + }, + formatInputTooShort: function () { + return tp('select2.tooShort', 2); + }, + width: '100%', + ajax: { + quietMillis: 300, + url: url, + data: function (term, page) { + return { q: term, p: page }; + }, + results: function (data) { + var results; + results = data.rules.map(function (rule) { + return { + id: rule.key, + text: '(' + rule.langName + ') ' + rule.name + }; + }); + return { + more: data.p * data.ps < data.total, + results: results + }; + } + } + }); + }, + + getValuesWithLabels: function () { + var values = this.model.getValues(), + rules = this.options.app.facets.rules; + values.forEach(function (v) { + var key = v.val, + label = '', + extra = ''; + if (key) { + var rule = _.findWhere(rules, { key: key }); + if (rule != null) { + label = rule.name; + } + if (rule != null) { + extra = rule.langName; + } + } + v.label = label; + v.extra = extra; + }); + return values; + }, + + serializeData: function () { + return _.extend(CustomValuesFacet.prototype.serializeData.apply(this, arguments), { + values: this.sortValues(this.getValuesWithLabels()) + }); + } + }); + +}); diff --git a/server/sonar-web/src/main/js/apps/issues/facets/severity-facet.js b/server/sonar-web/src/main/js/apps/issues/facets/severity-facet.js new file mode 100644 index 00000000000..eccaf546684 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/facets/severity-facet.js @@ -0,0 +1,17 @@ +define([ + './base-facet', + '../templates' +], function (BaseFacet) { + + return BaseFacet.extend({ + template: Templates['issues-severity-facet'], + + sortValues: function (values) { + var order = ['BLOCKER', 'MINOR', 'CRITICAL', 'INFO', 'MAJOR']; + return _.sortBy(values, function (v) { + return order.indexOf(v.val); + }); + } + }); + +}); diff --git a/server/sonar-web/src/main/js/apps/issues/facets/status-facet.js b/server/sonar-web/src/main/js/apps/issues/facets/status-facet.js new file mode 100644 index 00000000000..08db6d508f8 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/facets/status-facet.js @@ -0,0 +1,17 @@ +define([ + './base-facet', + '../templates' +], function (BaseFacet) { + + return BaseFacet.extend({ + template: Templates['issues-status-facet'], + + sortValues: function (values) { + var order = ['OPEN', 'RESOLVED', 'REOPENED', 'CLOSED', 'CONFIRMED']; + return _.sortBy(values, function (v) { + return order.indexOf(v.val); + }); + } + }); + +}); diff --git a/server/sonar-web/src/main/js/apps/issues/facets/tag-facet.js b/server/sonar-web/src/main/js/apps/issues/facets/tag-facet.js new file mode 100644 index 00000000000..7752451272b --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/facets/tag-facet.js @@ -0,0 +1,56 @@ +define([ + './custom-values-facet' +], function (CustomValuesFacet) { + + return CustomValuesFacet.extend({ + prepareSearch: function () { + var url = baseUrl + '/api/issues/tags?ps=10', + tags = this.options.app.state.get('query').tags; + if (tags != null) { + url += '&tags=' + tags; + } + return this.$('.js-custom-value').select2({ + placeholder: 'Search...', + minimumInputLength: 0, + allowClear: false, + formatNoMatches: function () { + return t('select2.noMatches'); + }, + formatSearching: function () { + return t('select2.searching'); + }, + width: '100%', + ajax: { + quietMillis: 300, + url: url, + data: function (term) { + return { q: term, ps: 10 }; + }, + results: function (data) { + var results = data.tags.map(function (tag) { + return { id: tag, text: tag }; + }); + return { more: false, results: results }; + } + } + }); + }, + + getValuesWithLabels: function () { + var values = this.model.getValues(), + tags = this.options.app.facets.tags; + values.forEach(function (v) { + v.label = v.val; + v.extra = ''; + }); + return values; + }, + + serializeData: function () { + return _.extend(CustomValuesFacet.prototype.serializeData.apply(this, arguments), { + values: this.sortValues(this.getValuesWithLabels()) + }); + } + }); + +}); diff --git a/server/sonar-web/src/main/js/apps/issues/filters-view.js b/server/sonar-web/src/main/js/apps/issues/filters-view.js new file mode 100644 index 00000000000..03813eff3c0 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/filters-view.js @@ -0,0 +1,93 @@ +define([ + './templates' +], function () { + + var $ = jQuery; + + return Marionette.ItemView.extend({ + template: Templates['issues-filters'], + + events: { + 'click .js-toggle-filters': 'toggleFilters', + 'click .js-filter': 'applyFilter', + 'click .js-filter-save-as': 'saveAs', + 'click .js-filter-save': 'save', + 'click .js-filter-copy': 'copy', + 'click .js-filter-edit': 'edit' + }, + + initialize: function (options) { + var that = this; + this.listenTo(options.app.state, 'change:filter', this.render); + this.listenTo(options.app.state, 'change:changed', this.render); + this.listenTo(options.app.filters, 'all', this.render); + window.onSaveAs = window.onCopy = window.onEdit = function (id) { + $('#modal').dialog('close'); + return that.options.app.controller.fetchFilters().done(function () { + var filter = that.collection.get(id); + return filter.fetch().done(function () { + return that.options.app.controller.applyFilter(filter); + }); + }); + }; + }, + + onRender: function () { + this.$el.toggleClass('search-navigator-filters-selected', this.options.app.state.has('filter')); + }, + + toggleFilters: function (e) { + var that = this; + e.stopPropagation(); + this.$('.search-navigator-filters-list').toggle(); + return $('body').on('click.issues-filters', function () { + $('body').off('click.issues-filters'); + return that.$('.search-navigator-filters-list').hide(); + }); + }, + + applyFilter: function (e) { + var that = this; + var id = $(e.currentTarget).data('id'), + filter = this.collection.get(id); + return filter.fetch().done(function () { + return that.options.app.controller.applyFilter(filter); + }); + }, + + saveAs: function () { + var query = this.options.app.controller.getQuery('&'), + url = baseUrl + '/issues/save_as_form?' + query; + window.openModalWindow(url, {}); + }, + + save: function () { + var that = this; + var query = this.options.app.controller.getQuery('&'), + url = baseUrl + '/issues/save/' + (this.options.app.state.get('filter').id) + '?' + query; + return $.post(url).done(function () { + return that.options.app.state.set({ changed: false }); + }); + }, + + copy: function () { + var url = baseUrl + '/issues/copy_form/' + (this.options.app.state.get('filter').id); + window.openModalWindow(url, {}); + }, + + edit: function () { + var url = baseUrl + '/issues/edit_form/' + (this.options.app.state.get('filter').id); + window.openModalWindow(url, {}); + }, + + serializeData: function () { + var filter = this.options.app.state.get('filter'); + return _.extend(Marionette.ItemView.prototype.serializeData.apply(this, arguments), { + state: this.options.app.state.toJSON(), + filter: filter != null ? filter.toJSON() : null, + currentUser: window.SS.user + }); + } + }); + +}); diff --git a/server/sonar-web/src/main/js/apps/issues/issue-filter-view.js b/server/sonar-web/src/main/js/apps/issues/issue-filter-view.js new file mode 100644 index 00000000000..67f9a617d45 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/issue-filter-view.js @@ -0,0 +1,29 @@ +define([ + 'components/issue/views/action-options-view', + './templates' +], function (ActionOptionsView) { + + var $ = jQuery; + + return ActionOptionsView.extend({ + template: Templates['issues-issue-filter-form'], + + selectInitialOption: function () { + return this.makeActive(this.getOptions().first()); + }, + + selectOption: function (e) { + var property = $(e.currentTarget).data('property'), + value = $(e.currentTarget).data('value'); + this.trigger('select', property, value); + return ActionOptionsView.prototype.selectOption.apply(this, arguments); + }, + + serializeData: function () { + return _.extend(ActionOptionsView.prototype.serializeData.apply(this, arguments), { + s: this.model.get('severity') + }); + } + }); + +}); diff --git a/server/sonar-web/src/main/js/apps/issues/layout.js b/server/sonar-web/src/main/js/apps/issues/layout.js new file mode 100644 index 00000000000..06b2f893af6 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/layout.js @@ -0,0 +1,55 @@ +define([ + './templates' +], function () { + + var $ = jQuery; + return Marionette.Layout.extend({ + template: Templates['issues-layout'], + + regions: { + filtersRegion: '.search-navigator-filters', + facetsRegion: '.search-navigator-facets', + workspaceHeaderRegion: '.search-navigator-workspace-header', + workspaceListRegion: '.search-navigator-workspace-list', + workspaceComponentViewerRegion: '.issues-workspace-component-viewer', + workspaceHomeRegion: '.issues-workspace-home' + }, + + onRender: function () { + if (this.options.app.state.get('isContext')) { + this.$(this.filtersRegion.el).addClass('hidden'); + } + $('.search-navigator').addClass('sticky'); + var top = $('.search-navigator').offset().top; + this.$('.search-navigator-workspace-header').css({ top: top }); + this.$('.search-navigator-side').css({ top: top }).isolatedScroll(); + }, + + showSpinner: function (region) { + return this[region].show(new Marionette.ItemView({ + template: _.template('') + })); + }, + + showComponentViewer: function () { + this.scroll = $(window).scrollTop(); + $('.issues').addClass('issues-extended-view'); + }, + + hideComponentViewer: function () { + $('.issues').removeClass('issues-extended-view'); + if (this.scroll != null) { + $(window).scrollTop(this.scroll); + } + }, + + showHomePage: function () { + $('.issues').addClass('issues-home-view'); + }, + + hideHomePage: function () { + $('.issues').removeClass('issues-home-view'); + } + }); + +}); diff --git a/server/sonar-web/src/main/js/apps/issues/models/facet.js b/server/sonar-web/src/main/js/apps/issues/models/facet.js new file mode 100644 index 00000000000..3716ba52d19 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/models/facet.js @@ -0,0 +1,20 @@ +define(function () { + + return Backbone.Model.extend({ + idAttribute: 'property', + + defaults: { + enabled: false + }, + + getValues: function () { + return this.get('values') || []; + }, + + toggle: function () { + var enabled = this.get('enabled'); + return this.set({ enabled: !enabled }); + } + }); + +}); diff --git a/server/sonar-web/src/main/js/apps/issues/models/facets.js b/server/sonar-web/src/main/js/apps/issues/models/facets.js new file mode 100644 index 00000000000..31c685de08d --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/models/facets.js @@ -0,0 +1,9 @@ +define([ + './facet' +], function (Facet) { + + return Backbone.Collection.extend({ + model: Facet + }); + +}); diff --git a/server/sonar-web/src/main/js/apps/issues/models/filter.js b/server/sonar-web/src/main/js/apps/issues/models/filter.js new file mode 100644 index 00000000000..42b11507ee1 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/models/filter.js @@ -0,0 +1,17 @@ +define(function () { + + return Backbone.Model.extend({ + url: function () { + return '/api/issue_filters/show/' + this.id; + }, + + parse: function (r) { + if (r.filter != null) { + return r.filter; + } else { + return r; + } + } + }); + +}); diff --git a/server/sonar-web/src/main/js/apps/issues/models/filters.js b/server/sonar-web/src/main/js/apps/issues/models/filters.js new file mode 100644 index 00000000000..bb66327e423 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/models/filters.js @@ -0,0 +1,9 @@ +define([ + './filter' +], function (Filter) { + + return Backbone.Collection.extend({ + model: Filter + }); + +}); diff --git a/server/sonar-web/src/main/js/apps/issues/models/issues.js b/server/sonar-web/src/main/js/apps/issues/models/issues.js new file mode 100644 index 00000000000..af41dd3fe12 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/models/issues.js @@ -0,0 +1,65 @@ +define([ + 'components/issue/models/issue' +], function (Issue) { + + return Backbone.Collection.extend({ + model: Issue, + + url: function () { + return baseUrl + '/api/issues/search'; + }, + + parseIssues: function (r) { + var find = function (source, key, keyField) { + var searchDict = {}; + searchDict[keyField || 'key'] = key; + return _.findWhere(source, searchDict) || key; + }; + return r.issues.map(function (issue, index) { + var component = find(r.components, issue.component), + project = find(r.projects, issue.project), + subProject = find(r.components, issue.subProject), + rule = find(r.rules, issue.rule), + assignee = find(r.users, issue.assignee, 'login'); + _.extend(issue, { index: index }); + if (component) { + _.extend(issue, { + componentUuid: component.uuid, + componentLongName: component.longName, + componentQualifier: component.qualifier + }); + } + if (project) { + _.extend(issue, { + projectLongName: project.longName, + projectUuid: project.uuid + }); + } + if (subProject) { + _.extend(issue, { + subProjectLongName: subProject.longName, + subProjectUuid: subProject.uuid + }); + } + if (rule) { + _.extend(issue, { + ruleName: rule.name + }); + } + if (assignee) { + _.extend(issue, { + assigneeEmail: assignee.email + }); + } + return issue; + }); + }, + + setIndex: function () { + return this.forEach(function (issue, index) { + return issue.set({ index: index }); + }); + } + }); + +}); diff --git a/server/sonar-web/src/main/js/apps/issues/models/state.js b/server/sonar-web/src/main/js/apps/issues/models/state.js new file mode 100644 index 00000000000..38814d71111 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/models/state.js @@ -0,0 +1,58 @@ +define([ + 'components/navigator/models/state' +], function (State) { + + return State.extend({ + defaults: { + page: 1, + maxResultsReached: false, + query: {}, + facets: ['severities', 'resolutions'], + isContext: false, + allFacets: [ + 'issues', + 'severities', + 'resolutions', + 'statuses', + 'createdAt', + 'rules', + 'tags', + 'projectUuids', + 'moduleUuids', + 'directories', + 'fileUuids', + 'assignees', + 'reporters', + 'authors', + 'languages', + 'actionPlans' + ], + facetsFromServer: [ + 'severities', + 'statuses', + 'resolutions', + 'actionPlans', + 'projectUuids', + 'directories', + 'rules', + 'moduleUuids', + 'tags', + 'assignees', + 'reporters', + 'authors', + 'fileUuids', + 'languages', + 'createdAt' + ], + transform: { + 'resolved': 'resolutions', + 'assigned': 'assignees', + 'planned': 'actionPlans', + 'createdBefore': 'createdAt', + 'createdAfter': 'createdAt', + 'createdInLast': 'createdAt' + } + } + }); + +}); diff --git a/server/sonar-web/src/main/js/apps/issues/router.js b/server/sonar-web/src/main/js/apps/issues/router.js new file mode 100644 index 00000000000..519689e8f40 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/router.js @@ -0,0 +1,45 @@ +define([ + 'components/navigator/router' +], function (Router) { + + return Router.extend({ + routes: { + '': 'home', + ':query': 'index' + }, + + initialize: function (options) { + Router.prototype.initialize.apply(this, arguments); + this.listenTo(options.app.state, 'change:filter', this.updateRoute); + }, + + home: function () { + if (this.options.app.state.get('isContext')) { + return this.navigate('resolved=false', { trigger: true, replace: true }); + } else { + return this.options.app.controller.showHomePage(); + } + }, + + index: function (query) { + var that = this; + query = this.options.app.controller.parseQuery(query); + if (query.id != null) { + var filter = this.options.app.filters.get(query.id); + delete query.id; + return filter.fetch().done(function () { + if (Object.keys(query).length > 0) { + that.options.app.controller.applyFilter(filter, true); + that.options.app.state.setQuery(query); + that.options.app.state.set({ changed: true }); + } else { + that.options.app.controller.applyFilter(filter); + } + }); + } else { + return this.options.app.state.setQuery(query); + } + } + }); + +}); diff --git a/server/sonar-web/src/main/coffee/apps/issues/templates/_issues-filter-name.hbs b/server/sonar-web/src/main/js/apps/issues/templates/_issues-filter-name.hbs similarity index 92% rename from server/sonar-web/src/main/coffee/apps/issues/templates/_issues-filter-name.hbs rename to server/sonar-web/src/main/js/apps/issues/templates/_issues-filter-name.hbs index 374d15ab48f..22b760eac1a 100644 --- a/server/sonar-web/src/main/coffee/apps/issues/templates/_issues-filter-name.hbs +++ b/server/sonar-web/src/main/js/apps/issues/templates/_issues-filter-name.hbs @@ -1,6 +1,6 @@ {{#if filter.name}} {{filter.name}} - + {{#unless filter.shared}} [{{t 'issue_filter.private'}}] {{else}} diff --git a/server/sonar-web/src/main/js/apps/issues/templates/facets/_issues-facet-header.hbs b/server/sonar-web/src/main/js/apps/issues/templates/facets/_issues-facet-header.hbs new file mode 100644 index 00000000000..8e012d1fd67 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/templates/facets/_issues-facet-header.hbs @@ -0,0 +1,4 @@ + + + {{t 'issues.facet' property}} + diff --git a/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-action-plan-facet.hbs b/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-action-plan-facet.hbs new file mode 100644 index 00000000000..e934608d214 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-action-plan-facet.hbs @@ -0,0 +1,18 @@ +{{> '_issues-facet-header'}} + +
+ {{#each values}} + {{#eq val ''}} + {{! unplanned }} + + {{t 'issue.unplanned'}} + {{numberShort count}} + + {{else}} + + {{label}} + {{numberShort count}} + + {{/eq}} + {{/each}} +
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 new file mode 100644 index 00000000000..44d4b341f72 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-assignee-facet.hbs @@ -0,0 +1,30 @@ +{{> '_issues-facet-header'}} + +
+ {{#notNull myIssues}} + + {{t 'me'}} + {{myIssues}} + +
+ {{/notNull}} + + {{#each values}} + {{#eq val ''}} + {{! unassigned }} + + {{t 'unassigned'}} + {{numberShort count}} + + {{else}} + + {{label}} + {{numberShort count}} + + {{/eq}} + {{/each}} + +
+ +
+
diff --git a/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-base-facet.hbs b/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-base-facet.hbs new file mode 100644 index 00000000000..d8b5f0b0179 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-base-facet.hbs @@ -0,0 +1,10 @@ +{{> '_issues-facet-header'}} + +
+ {{#each values}} + + {{default label val}} + {{numberShort count}} + + {{/each}} +
diff --git a/server/sonar-web/src/main/coffee/apps/issues/templates/facets/issues-context-facet.hbs b/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-context-facet.hbs similarity index 73% rename from server/sonar-web/src/main/coffee/apps/issues/templates/facets/issues-context-facet.hbs rename to server/sonar-web/src/main/js/apps/issues/templates/facets/issues-context-facet.hbs index 9f981c07c1a..5c570f8718c 100644 --- a/server/sonar-web/src/main/coffee/apps/issues/templates/facets/issues-context-facet.hbs +++ b/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-context-facet.hbs @@ -1,3 +1,3 @@ -
+
Issues of    {{qualifierIcon state.contextComponentQualifier}} {{state.contextComponentName}}
diff --git a/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-creation-date-facet.hbs b/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-creation-date-facet.hbs new file mode 100644 index 00000000000..9003a170522 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-creation-date-facet.hbs @@ -0,0 +1,32 @@ +{{> '_issues-facet-header'}} + +{{#if createdAt}} + +
+ {{dt createdAt}} ({{fromNow createdAt}}) +
+{{else}} + +{{/if}} diff --git a/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-custom-values-facet.hbs b/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-custom-values-facet.hbs new file mode 100644 index 00000000000..30372e84ae0 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-custom-values-facet.hbs @@ -0,0 +1,14 @@ +{{> '_issues-facet-header'}} + +
+ {{#each values}} + + {{default label val}} + {{numberShort count}} + + {{/each}} + +
+ +
+
diff --git a/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-file-facet.hbs b/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-file-facet.hbs new file mode 100644 index 00000000000..c070fb7785a --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-file-facet.hbs @@ -0,0 +1,10 @@ +{{> '_issues-facet-header'}} + +
+ {{#each values}} + + {{default label val}} + {{numberShort count}} + + {{/each}} +
diff --git a/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-issue-key-facet.hbs b/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-issue-key-facet.hbs new file mode 100644 index 00000000000..540e9a00014 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-issue-key-facet.hbs @@ -0,0 +1,7 @@ +{{> '_issues-facet-header'}} + +
+
+ {{issues}} +
+
diff --git a/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-resolution-facet.hbs b/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-resolution-facet.hbs new file mode 100644 index 00000000000..6fb81c5548f --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-resolution-facet.hbs @@ -0,0 +1,20 @@ +{{> '_issues-facet-header'}} + +
+ {{#each values}} + {{#eq val ''}} + {{! unresolved }} + + {{t 'unresolved'}} + {{numberShort count}} + + {{else}} + + {{t 'issue.resolution' val}} + {{numberShort count}} + + {{/eq}} + {{/each}} +
diff --git a/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-severity-facet.hbs b/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-severity-facet.hbs new file mode 100644 index 00000000000..92ff7b52444 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-severity-facet.hbs @@ -0,0 +1,11 @@ +{{> '_issues-facet-header'}} + + diff --git a/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-status-facet.hbs b/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-status-facet.hbs new file mode 100644 index 00000000000..55a78a63bf1 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-status-facet.hbs @@ -0,0 +1,11 @@ +{{> '_issues-facet-header'}} + + diff --git a/server/sonar-web/src/main/js/apps/issues/templates/issues-filters.hbs b/server/sonar-web/src/main/js/apps/issues/templates/issues-filters.hbs new file mode 100644 index 00000000000..e010deb9a0e --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/templates/issues-filters.hbs @@ -0,0 +1,55 @@ +

+ {{#if state.canManageFilters}} + + {{> '_issues-filter-name'}} + + + {{#if filter.description}} +
{{filter.description}}
+ {{/if}} + {{else}} + {{t 'issues'}} + {{/if}} +

+ +
+
+ {{#if state.canManageFilters}} + {{#if filter.canModify}} + {{#if state.changed}} + + {{/if}} + {{/if}} + + {{#unless filter.id}} + + {{/unless}} + + {{#if filter.id}} + {{#unless state.changed}} + + {{/unless}} + {{/if}} + + {{#if filter.canModify}} + {{#if filter.id}} + + {{/if}} + {{/if}} + {{/if}} +
+
diff --git a/server/sonar-web/src/main/js/apps/issues/templates/issues-issue-filter-form.hbs b/server/sonar-web/src/main/js/apps/issues/templates/issues-issue-filter-form.hbs new file mode 100644 index 00000000000..1954f67f62d --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/templates/issues-issue-filter-form.hbs @@ -0,0 +1,71 @@ +
{{t 'issue.filter_similar_issues'}}
+ + + +
diff --git a/server/sonar-web/src/main/js/apps/issues/templates/issues-issue-filter.hbs b/server/sonar-web/src/main/js/apps/issues/templates/issues-issue-filter.hbs new file mode 100644 index 00000000000..3ab307c3958 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/templates/issues-issue-filter.hbs @@ -0,0 +1,5 @@ + 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 new file mode 100644 index 00000000000..cd434ab2340 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/templates/issues-layout.hbs @@ -0,0 +1,11 @@ +
+
+
+
+ +
+
+
+
+
+
diff --git a/server/sonar-web/src/main/js/apps/issues/templates/issues-workspace-header.hbs b/server/sonar-web/src/main/js/apps/issues/templates/issues-workspace-header.hbs new file mode 100644 index 00000000000..2c7d2d6e3ee --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/templates/issues-workspace-header.hbs @@ -0,0 +1,37 @@ +
+ {{#if state.component}} + {{t 'issues.return_to_list'}}    + + {{#with state.component}} + {{qualifierIcon 'TRK'}} {{projectName}} +    + {{qualifierIcon qualifier}} {{name}} + {{/with}} + {{else}} +   + {{/if}} +
+ + +
+ {{#notNull state.total}} +
+ {{#gt state.total 0}} + + {{sum state.selectedIndex 1}} / {{state.total}} + + {{else}} + 0 / 0 + {{/gt}} +
+ {{/notNull}} + + +
+ + + {{#if state.canBulkChange}} + + {{/if}} +
+
diff --git a/server/sonar-web/src/main/js/apps/issues/templates/issues-workspace-home.hbs b/server/sonar-web/src/main/js/apps/issues/templates/issues-workspace-home.hbs new file mode 100644 index 00000000000..374dad390b7 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/templates/issues-workspace-home.hbs @@ -0,0 +1,77 @@ +
+
+
+

{{t 'issues.home.recent_issues'}}

+

({{t 'issues.home.over_last_week'}})

+ +
+

{{t 'issues.home.projects'}}

+ + {{#each projects}} + + + + + {{/each}} +
{{qualifierIcon 'TRK'}} {{label}}+{{numberShort count}}
+

{{t 'issues.home.authors'}}

+ + {{#each authors}} + + + + + {{/each}} +
{{val}}+{{numberShort count}}
+

{{t 'issues.home.tags'}}

+
    + {{#each tags}} +
  • {{val}}
  • + {{/each}} +
+
+ + {{#if user}} +
+

{{t 'issues.home.my_recent_issues'}}

+

({{t 'issues.home.over_last_week'}})

+ +
+ {{#notEmpty myProjects}} +

{{t 'issues.home.projects'}}

+ + {{#each myProjects}} + + + + + {{/each}} +
{{qualifierIcon 'TRK'}} {{label}}+{{numberShort count}}
+ {{/notEmpty}} + {{#notEmpty myTags}} +

{{t 'issues.home.tags'}}

+
    + {{#each myTags}} +
  • {{val}}
  • + {{/each}} +
+ {{/notEmpty}} + {{#notEmpty filters}} +

+ {{t 'issues.home.my_filters'}}

+
    + {{#each filters}} +
  • + {{name}} +
  • + {{/each}} +
+ {{/notEmpty}} +
+ {{/if}} +
+
diff --git a/server/sonar-web/src/main/js/apps/issues/templates/issues-workspace-list-component.hbs b/server/sonar-web/src/main/js/apps/issues/templates/issues-workspace-list-component.hbs new file mode 100644 index 00000000000..73d15ac8fbe --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/templates/issues-workspace-list-component.hbs @@ -0,0 +1,13 @@ + diff --git a/server/sonar-web/src/main/js/apps/issues/templates/issues-workspace-list.hbs b/server/sonar-web/src/main/js/apps/issues/templates/issues-workspace-list.hbs new file mode 100644 index 00000000000..a81b673736c --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/templates/issues-workspace-list.hbs @@ -0,0 +1,5 @@ +
+ +
+ +
diff --git a/server/sonar-web/src/main/js/apps/issues/workspace-header-view.js b/server/sonar-web/src/main/js/apps/issues/workspace-header-view.js new file mode 100644 index 00000000000..620b68bfccd --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/workspace-header-view.js @@ -0,0 +1,47 @@ +define([ + 'components/navigator/workspace-header-view', + './templates' +], function (WorkspaceHeaderView) { + + var $ = jQuery; + + return WorkspaceHeaderView.extend({ + template: Templates['issues-workspace-header'], + + events: function () { + return _.extend(WorkspaceHeaderView.prototype.events.apply(this, arguments), { + 'click .js-back': 'returnToList', + 'click .js-new-search': 'newSearch' + }); + }, + + initialize: function () { + var that = this; + WorkspaceHeaderView.prototype.initialize.apply(this, arguments); + this._onBulkIssues = window.onBulkIssues; + window.onBulkIssues = function () { + $('#modal').dialog('close'); + return that.options.app.controller.fetchList(); + }; + }, + + onClose: function () { + window.onBulkIssues = this._onBulkIssues; + }, + + returnToList: function () { + this.options.app.controller.closeComponentViewer(); + }, + + newSearch: function () { + this.options.app.controller.newSearch(); + }, + + bulkChange: function () { + var query = this.options.app.controller.getQuery('&', true), + url = baseUrl + '/issues/bulk_change_form?' + query; + window.openModalWindow(url, {}); + } + }); + +}); diff --git a/server/sonar-web/src/main/js/apps/issues/workspace-home-view.js b/server/sonar-web/src/main/js/apps/issues/workspace-home-view.js new file mode 100644 index 00000000000..408900fb63e --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/workspace-home-view.js @@ -0,0 +1,160 @@ +define([ + 'widgets/issue-filter/widget', + './templates' +], function (IssueFilter) { + + var $ = jQuery; + + Handlebars.registerHelper('issuesHomeLink', function (property, value) { + return baseUrl + '/issues/search#resolved=false|createdInLast=1w|' + + property + '=' + (encodeURIComponent(value)); + }); + + Handlebars.registerHelper('myIssuesHomeLink', function (property, value) { + return baseUrl + '/issues/search#resolved=false|createdInLast=1w|assignees=__me__|' + + property + '=' + (encodeURIComponent(value)); + }); + + Handlebars.registerHelper('issueFilterHomeLink', function (id) { + return baseUrl + '/issues/search#id=' + id; + }); + + return Marionette.ItemView.extend({ + template: Templates['issues-workspace-home'], + + modelEvents: { + 'change': 'render' + }, + + events: { + 'click .js-barchart rect': 'selectBar', + 'click .js-my-barchart rect': 'selectMyBar' + }, + + initialize: function () { + this.model = new Backbone.Model(); + this.requestIssues(); + this.requestMyIssues(); + }, + + _getProjects: function (r) { + var projectFacet = _.findWhere(r.facets, { property: 'projectUuids' }); + if (projectFacet != null) { + var values = _.head(projectFacet.values, 3); + values.forEach(function (v) { + var project = _.findWhere(r.projects, { uuid: v.val }); + v.label = project.longName; + }); + return values; + } + }, + + _getAuthors: function (r) { + var authorFacet = _.findWhere(r.facets, { property: 'authors' }); + if (authorFacet != null) { + return _.head(authorFacet.values, 3); + } + }, + + _getTags: function (r) { + var MIN_SIZE = 10, + MAX_SIZE = 24, + tagFacet = _.findWhere(r.facets, { property: 'tags' }); + if (tagFacet != null) { + var values = _.head(tagFacet.values, 10), + minCount = _.min(values, function (v) { + return v.count; + }).count, + maxCount = _.max(values, function (v) { + return v.count; + }).count, + scale = d3.scale.linear().domain([minCount, maxCount]).range([MIN_SIZE, MAX_SIZE]); + values.forEach(function (v) { + v.size = scale(v.count); + }); + return values; + } + }, + + requestIssues: function () { + var that = this; + var url = baseUrl + '/api/issues/search', + options = { + resolved: false, + createdInLast: '1w', + ps: 1, + facets: 'createdAt,projectUuids,authors,tags' + }; + return $.get(url, options).done(function (r) { + var createdAt = _.findWhere(r.facets, { property: 'createdAt' }); + that.model.set({ + createdAt: createdAt != null ? createdAt.values : null, + projects: that._getProjects(r), + authors: that._getAuthors(r), + tags: that._getTags(r) + }); + }); + }, + + requestMyIssues: function () { + var that = this; + var url = baseUrl + '/api/issues/search', + options = { + resolved: false, + createdInLast: '1w', + assignees: '__me__', + ps: 1, + facets: 'createdAt,projectUuids,authors,tags' + }; + return $.get(url, options).done(function (r) { + var createdAt = _.findWhere(r.facets, { property: 'createdAt' }); + return that.model.set({ + myCreatedAt: createdAt != null ? createdAt.values : null, + myProjects: that._getProjects(r), + myTags: that._getTags(r) + }); + }); + }, + + onRender: function () { + var values = this.model.get('createdAt'), + myValues = this.model.get('myCreatedAt'); + if (values != null) { + this.$('.js-barchart').barchart(values); + } + if (myValues != null) { + this.$('.js-my-barchart').barchart(myValues); + } + this.$('[data-toggle="tooltip"]').tooltip({ container: 'body' }); + }, + + selectBar: function (e) { + var periodStart = $(e.currentTarget).data('period-start'), + periodEnd = $(e.currentTarget).data('period-end'); + this.options.app.state.setQuery({ + resolved: false, + createdAfter: periodStart, + createdBefore: periodEnd + }); + }, + + selectMyBar: function (e) { + var periodStart = $(e.currentTarget).data('period-start'), + periodEnd = $(e.currentTarget).data('period-end'); + this.options.app.state.setQuery({ + resolved: false, + assignees: '__me__', + createdAfter: periodStart, + createdBefore: periodEnd + }); + }, + + serializeData: function () { + return _.extend(Marionette.ItemView.prototype.serializeData.apply(this, arguments), { + user: window.SS.user, + filters: _.sortBy(this.options.app.filters.toJSON(), 'name') + }); + } + }); + +}); diff --git a/server/sonar-web/src/main/js/apps/issues/workspace-list-empty-view.js b/server/sonar-web/src/main/js/apps/issues/workspace-list-empty-view.js new file mode 100644 index 00000000000..ada57f15a2d --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/workspace-list-empty-view.js @@ -0,0 +1,11 @@ +define(function () { + + return Marionette.ItemView.extend({ + className: 'search-navigator-no-results', + + template: function () { + return t('issue_filter.no_issues'); + } + }); + +}); diff --git a/server/sonar-web/src/main/js/apps/issues/workspace-list-item-view.js b/server/sonar-web/src/main/js/apps/issues/workspace-list-item-view.js new file mode 100644 index 00000000000..6d3df9c6901 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/workspace-list-item-view.js @@ -0,0 +1,113 @@ +define([ + 'components/issue/issue-view', + './issue-filter-view', + './templates' +], function (IssueView, IssueFilterView) { + + var $ = jQuery, + SHOULD_NULL = { + any: ['issues'], + resolutions: ['resolved'], + resolved: ['resolutions'], + assignees: ['assigned'], + assigned: ['assignees'], + actionPlans: ['planned'], + planned: ['actionPlans'] + }; + + return IssueView.extend({ + filterTemplate: Templates['issues-issue-filter'], + + events: function () { + return _.extend(IssueView.prototype.events.apply(this, arguments), { + 'click': 'selectCurrent', + 'dblclick': 'openComponentViewer', + 'click .js-issue-navigate': 'openComponentViewer', + 'click .js-issue-filter': 'onIssueFilterClick' + }); + }, + + initialize: function (options) { + IssueView.prototype.initialize.apply(this, arguments); + this.listenTo(options.app.state, 'change:selectedIndex', this.select); + }, + + onRender: function () { + IssueView.prototype.onRender.apply(this, arguments); + this.select(); + this.addFilterSelect(); + this.$el.addClass('issue-navigate-right'); + }, + + onIssueFilterClick: function (e) { + var that = this; + e.preventDefault(); + e.stopPropagation(); + $('body').click(); + this.popup = new IssueFilterView({ + triggerEl: $(e.currentTarget), + bottomRight: true, + model: this.model + }); + this.popup.on('select', function (property, value) { + var obj; + obj = {}; + obj[property] = '' + value; + SHOULD_NULL.any.forEach(function (p) { + obj[p] = null; + }); + if (SHOULD_NULL[property] != null) { + SHOULD_NULL[property].forEach(function (p) { + obj[p] = null; + }); + } + that.options.app.state.updateFilter(obj); + that.popup.close(); + }); + this.popup.render(); + }, + + addFilterSelect: function () { + this.$('.issue-table-meta-cell-first') + .find('.issue-meta-list') + .append(this.filterTemplate(this.model.toJSON())); + }, + + select: function () { + var selected = this.model.get('index') === this.options.app.state.get('selectedIndex'); + this.$el.toggleClass('selected', selected); + }, + + selectCurrent: function () { + this.options.app.state.set({ selectedIndex: this.model.get('index') }); + }, + + resetIssue: function (options) { + var that = this; + var key = this.model.get('key'), + componentUuid = this.model.get('componentUuid'), + index = this.model.get('index'); + this.model.clear({ silent: true }); + this.model.set({ key: key, componentUuid: componentUuid, index: index }, { silent: true }); + return this.model.fetch(options).done(function () { + return that.trigger('reset'); + }); + }, + + openComponentViewer: function () { + this.options.app.state.set({ selectedIndex: this.model.get('index') }); + if (this.options.app.state.has('component')) { + return this.options.app.controller.closeComponentViewer(); + } else { + return this.options.app.controller.showComponentViewer(this.model); + } + }, + + serializeData: function () { + return _.extend(IssueView.prototype.serializeData.apply(this, arguments), { + showComponent: true + }); + } + }); + +}); diff --git a/server/sonar-web/src/main/js/apps/issues/workspace-list-view.js b/server/sonar-web/src/main/js/apps/issues/workspace-list-view.js new file mode 100644 index 00000000000..37e7ade70e9 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/issues/workspace-list-view.js @@ -0,0 +1,106 @@ +define([ + 'components/navigator/workspace-list-view', + './workspace-list-item-view', + './workspace-list-empty-view', + './templates' +], function (WorkspaceListView, IssueView, EmptyView) { + + var $ = jQuery, + COMPONENT_HEIGHT = 29, + BOTTOM_OFFSET = 10; + + return WorkspaceListView.extend({ + template: Templates['issues-workspace-list'], + componentTemplate: Templates['issues-workspace-list-component'], + itemView: IssueView, + itemViewContainer: '.js-list', + emptyView: EmptyView, + + bindShortcuts: function () { + var that = this; + var doAction = function (action) { + var selectedIssue = that.collection.at(that.options.app.state.get('selectedIndex')); + if (selectedIssue == null) { + return; + } + var selectedIssueView = that.children.findByModel(selectedIssue); + selectedIssueView.$('.js-issue-' + action).click(); + }; + WorkspaceListView.prototype.bindShortcuts.apply(this, arguments); + key('right', 'list', function () { + var selectedIssue = that.collection.at(that.options.app.state.get('selectedIndex')); + that.options.app.controller.showComponentViewer(selectedIssue); + return false; + }); + key('f', 'list', function () { + return doAction('transition'); + }); + key('a', 'list', function () { + return doAction('assign'); + }); + key('m', 'list', function () { + return doAction('assign-to-me'); + }); + key('p', 'list', function () { + return doAction('plan'); + }); + key('i', 'list', function () { + return doAction('set-severity'); + }); + key('c', 'list', function () { + return doAction('comment'); + }); + return key('t', 'list', function () { + return doAction('edit-tags'); + }); + }, + + scrollTo: function () { + var selectedIssue = this.collection.at(this.options.app.state.get('selectedIndex')); + if (selectedIssue == null) { + return; + } + var selectedIssueView = this.children.findByModel(selectedIssue), + parentTopOffset = this.$el.offset().top, + viewTop = selectedIssueView.$el.offset().top - parentTopOffset; + if (selectedIssueView.$el.prev().is('.issues-workspace-list-component')) { + viewTop -= COMPONENT_HEIGHT; + } + var viewBottom = selectedIssueView.$el.offset().top + selectedIssueView.$el.outerHeight() + BOTTOM_OFFSET, + windowTop = $(window).scrollTop(), + windowBottom = windowTop + $(window).height(); + if (viewTop < windowTop) { + $(window).scrollTop(viewTop); + } + if (viewBottom > windowBottom) { + $(window).scrollTop($(window).scrollTop() - windowBottom + viewBottom); + } + }, + + appendHtml: function (compositeView, itemView, index) { + var $container = this.getItemViewContainer(compositeView), + model = this.collection.at(index); + if (model != null) { + var prev = this.collection.at(index - 1), + putComponent = prev == null; + if (prev != null) { + var fullComponent = [model.get('project'), model.get('component')].join(' '), + fullPrevComponent = [prev.get('project'), prev.get('component')].join(' '); + if (fullComponent !== fullPrevComponent) { + putComponent = true; + } + } + if (putComponent) { + $container.append(this.componentTemplate(model.toJSON())); + } + } + $container.append(itemView.el); + }, + + closeChildren: function () { + WorkspaceListView.prototype.closeChildren.apply(this, arguments); + this.$('.issues-workspace-list-component').remove(); + } + }); + +}); -- 2.39.5