diff options
author | Stas Vilchik <vilchiks@gmail.com> | 2015-09-29 15:22:40 +0200 |
---|---|---|
committer | Stas Vilchik <vilchiks@gmail.com> | 2015-09-29 15:22:40 +0200 |
commit | b8a80269e55fee3e0590c925a5c37f8d18c5c932 (patch) | |
tree | dd1efe864cd73986f4894797f28f5fd3c1f7319b /server/sonar-web/src/main/js | |
parent | be7978644b590068fe21fe047ccb75b3c0b8f326 (diff) | |
download | sonarqube-b8a80269e55fee3e0590c925a5c37f8d18c5c932.tar.gz sonarqube-b8a80269e55fee3e0590c925a5c37f8d18c5c932.zip |
migrate js components to es2015 modules
Diffstat (limited to 'server/sonar-web/src/main/js')
65 files changed, 5854 insertions, 5942 deletions
diff --git a/server/sonar-web/src/main/js/components/common/action-options-view.js b/server/sonar-web/src/main/js/components/common/action-options-view.js index cf3a9b26d9e..061d3dffd7f 100644 --- a/server/sonar-web/src/main/js/components/common/action-options-view.js +++ b/server/sonar-web/src/main/js/components/common/action-options-view.js @@ -1,116 +1,113 @@ -define([ - 'components/common/popup' -], function (PopupView) { - - var $ = jQuery; - - return PopupView.extend({ - className: 'bubble-popup bubble-popup-menu', - keyScope: 'action-options', - - ui: { - options: '.menu > li > a' - }, - - events: function () { - return { - 'click @ui.options': 'selectOption', - 'mouseenter @ui.options': 'activateOptionByPointer' - }; - }, - - initialize: function () { - this.bindShortcuts(); - }, - - onRender: function () { - PopupView.prototype.onRender.apply(this, arguments); - this.selectInitialOption(); - }, - - getOptions: function () { - return this.$('.menu > li > a'); - }, - - getActiveOption: function () { - return this.getOptions().filter('.active'); - }, - - makeActive: function (option) { - if (option.length > 0) { - this.getOptions().removeClass('active').tooltip('hide'); - option.addClass('active').tooltip('show'); - } - }, - - selectInitialOption: function () { - this.makeActive(this.getOptions().first()); - }, - - selectNextOption: function () { - this.makeActive(this.getActiveOption().parent().nextAll('li:not(.divider)').first().children('a')); +import $ from 'jquery'; +import PopupView from 'components/common/popup'; + +export default PopupView.extend({ + className: 'bubble-popup bubble-popup-menu', + keyScope: 'action-options', + + ui: { + options: '.menu > li > a' + }, + + events: function () { + return { + 'click @ui.options': 'selectOption', + 'mouseenter @ui.options': 'activateOptionByPointer' + }; + }, + + initialize: function () { + this.bindShortcuts(); + }, + + onRender: function () { + PopupView.prototype.onRender.apply(this, arguments); + this.selectInitialOption(); + }, + + getOptions: function () { + return this.$('.menu > li > a'); + }, + + getActiveOption: function () { + return this.getOptions().filter('.active'); + }, + + makeActive: function (option) { + if (option.length > 0) { + this.getOptions().removeClass('active').tooltip('hide'); + option.addClass('active').tooltip('show'); + } + }, + + selectInitialOption: function () { + this.makeActive(this.getOptions().first()); + }, + + selectNextOption: function () { + this.makeActive(this.getActiveOption().parent().nextAll('li:not(.divider)').first().children('a')); + return false; + }, + + selectPreviousOption: function () { + this.makeActive(this.getActiveOption().parent().prevAll('li:not(.divider)').first().children('a')); + return false; + }, + + activateOptionByPointer: function (e) { + this.makeActive($(e.currentTarget)); + }, + + bindShortcuts: function () { + var that = this; + this.currentKeyScope = key.getScope(); + key.setScope(this.keyScope); + key('down', this.keyScope, function () { + return that.selectNextOption(); + }); + key('up', this.keyScope, function () { + return that.selectPreviousOption(); + }); + key('return', this.keyScope, function () { + return that.selectActiveOption(); + }); + key('escape', this.keyScope, function () { + return that.destroy(); + }); + key('backspace', this.keyScope, function () { return false; - }, - - selectPreviousOption: function () { - this.makeActive(this.getActiveOption().parent().prevAll('li:not(.divider)').first().children('a')); + }); + key('shift+tab', this.keyScope, function () { return false; - }, - - activateOptionByPointer: function (e) { - this.makeActive($(e.currentTarget)); - }, - - bindShortcuts: function () { - var that = this; - this.currentKeyScope = key.getScope(); - key.setScope(this.keyScope); - key('down', this.keyScope, function () { - return that.selectNextOption(); - }); - key('up', this.keyScope, function () { - return that.selectPreviousOption(); - }); - key('return', this.keyScope, function () { - return that.selectActiveOption(); - }); - key('escape', this.keyScope, function () { - return that.destroy(); - }); - key('backspace', this.keyScope, function () { - return false; - }); - key('shift+tab', this.keyScope, function () { - return false; - }); - }, - - unbindShortcuts: function () { - key.unbind('down', this.keyScope); - key.unbind('up', this.keyScope); - key.unbind('return', this.keyScope); - key.unbind('escape', this.keyScope); - key.unbind('backspace', this.keyScope); - key.unbind('tab', this.keyScope); - key.unbind('shift+tab', this.keyScope); - key.setScope(this.currentKeyScope); - }, - - onDestroy: function () { - PopupView.prototype.onDestroy.apply(this, arguments); - this.unbindShortcuts(); - this.$('[data-toggle="tooltip"]').tooltip('destroy'); - $('.tooltip').remove(); - }, - - selectOption: function (e) { - e.preventDefault(); - this.destroy(); - }, - - selectActiveOption: function () { - this.getActiveOption().click(); - } - }); - + }); + }, + + unbindShortcuts: function () { + key.unbind('down', this.keyScope); + key.unbind('up', this.keyScope); + key.unbind('return', this.keyScope); + key.unbind('escape', this.keyScope); + key.unbind('backspace', this.keyScope); + key.unbind('tab', this.keyScope); + key.unbind('shift+tab', this.keyScope); + key.setScope(this.currentKeyScope); + }, + + onDestroy: function () { + PopupView.prototype.onDestroy.apply(this, arguments); + this.unbindShortcuts(); + this.$('[data-toggle="tooltip"]').tooltip('destroy'); + $('.tooltip').remove(); + }, + + selectOption: function (e) { + e.preventDefault(); + this.destroy(); + }, + + selectActiveOption: function () { + this.getActiveOption().click(); + } }); + + diff --git a/server/sonar-web/src/main/js/components/common/file-upload.js b/server/sonar-web/src/main/js/components/common/file-upload.js index f3fdc891df6..91295e71f5e 100644 --- a/server/sonar-web/src/main/js/components/common/file-upload.js +++ b/server/sonar-web/src/main/js/components/common/file-upload.js @@ -1,46 +1,45 @@ -define(function () { - - var $ = jQuery; - - function createFrame () { - var uuid = _.uniqueId('upload-form-'); - return $('<iframe></iframe>') - .prop('frameborder', 0) - .prop('width', 0) - .prop('height', 0) - .prop('id', uuid) - .prop('name', uuid) - .css('display', 'none'); - } - - return function (options) { - var deferred = new $.Deferred(), - body = $('body'), - frame = createFrame(), - parent = options.form.parent(), - clonedForm = options.form.detach(); - - clonedForm - .prop('target', frame.prop('id')) - .appendTo(frame); - - frame.appendTo(body); - - frame.on('load', function () { - var result = this.contentWindow.document.body.textContent; - try { - var js = JSON.parse(result); - deferred.resolve(js); - } catch (e) { - deferred.resolve(result); - } - clonedForm.detach().appendTo(parent); - frame.off('load').remove(); - }); - - clonedForm.submit(); - - return deferred.promise(); - }; - -}); +import $ from 'jquery'; +import _ from 'underscore'; + +function createFrame () { + var uuid = _.uniqueId('upload-form-'); + return $('<iframe></iframe>') + .prop('frameborder', 0) + .prop('width', 0) + .prop('height', 0) + .prop('id', uuid) + .prop('name', uuid) + .css('display', 'none'); +} + +export default function (options) { + var deferred = new $.Deferred(), + body = $('body'), + frame = createFrame(), + parent = options.form.parent(), + clonedForm = options.form.detach(); + + clonedForm + .prop('target', frame.prop('id')) + .appendTo(frame); + + frame.appendTo(body); + + frame.on('load', function () { + var result = this.contentWindow.document.body.textContent; + try { + var js = JSON.parse(result); + deferred.resolve(js); + } catch (e) { + deferred.resolve(result); + } + clonedForm.detach().appendTo(parent); + frame.off('load').remove(); + }); + + clonedForm.submit(); + + return deferred.promise(); +} + + diff --git a/server/sonar-web/src/main/js/components/common/modal-form.js b/server/sonar-web/src/main/js/components/common/modal-form.js index aa23023c279..86ae8b89387 100644 --- a/server/sonar-web/src/main/js/components/common/modal-form.js +++ b/server/sonar-web/src/main/js/components/common/modal-form.js @@ -1,67 +1,68 @@ -define(['components/common/modals'], function (ModalView) { +import _ from 'underscore'; +import ModalView from 'components/common/modals'; - return ModalView.extend({ +export default ModalView.extend({ - ui: function () { - return { - messagesContainer: '.js-modal-messages' - }; - }, + ui: function () { + return { + messagesContainer: '.js-modal-messages' + }; + }, - events: function () { - return _.extend(ModalView.prototype.events.apply(this, arguments), { - 'keydown input,textarea,select': 'onInputKeydown', - 'submit form': 'onFormSubmit' - }); - }, + events: function () { + return _.extend(ModalView.prototype.events.apply(this, arguments), { + 'keydown input,textarea,select': 'onInputKeydown', + 'submit form': 'onFormSubmit' + }); + }, - onRender: function () { - ModalView.prototype.onRender.apply(this, arguments); - var that = this; - setTimeout(function () { - that.$(':tabbable').first().focus(); - }, 0); - }, + onRender: function () { + ModalView.prototype.onRender.apply(this, arguments); + var that = this; + setTimeout(function () { + that.$(':tabbable').first().focus(); + }, 0); + }, - onInputKeydown: function (e) { - if (e.keyCode === 27) { - // escape - this.destroy(); - } - }, + onInputKeydown: function (e) { + if (e.keyCode === 27) { + // escape + this.destroy(); + } + }, - onFormSubmit: function (e) { - e.preventDefault(); - }, + onFormSubmit: function (e) { + e.preventDefault(); + }, - showErrors: function (errors, warnings) { - var container = this.ui.messagesContainer.empty(); - if (_.isArray(errors)) { - errors.forEach(function (error) { - var html = '<div class="alert alert-danger">' + error.msg + '</div>'; - container.append(html); - }); - } - if (_.isArray(warnings)) { - warnings.forEach(function (warn) { - var html = '<div class="alert alert-warning">' + warn.msg + '</div>'; - container.append(html); - }); - } - this.ui.messagesContainer.scrollParent().scrollTop(0); - }, + showErrors: function (errors, warnings) { + var container = this.ui.messagesContainer.empty(); + if (_.isArray(errors)) { + errors.forEach(function (error) { + var html = '<div class="alert alert-danger">' + error.msg + '</div>'; + container.append(html); + }); + } + if (_.isArray(warnings)) { + warnings.forEach(function (warn) { + var html = '<div class="alert alert-warning">' + warn.msg + '</div>'; + container.append(html); + }); + } + this.ui.messagesContainer.scrollParent().scrollTop(0); + }, - disableForm: function () { - var form = this.$('form'); - this.disabledFields = form.find(':input:not(:disabled)'); - this.disabledFields.prop('disabled', true); - }, + disableForm: function () { + var form = this.$('form'); + this.disabledFields = form.find(':input:not(:disabled)'); + this.disabledFields.prop('disabled', true); + }, - enableForm: function () { - if (this.disabledFields != null) { - this.disabledFields.prop('disabled', false); - } + enableForm: function () { + if (this.disabledFields != null) { + this.disabledFields.prop('disabled', false); } - }); - + } }); + + diff --git a/server/sonar-web/src/main/js/components/common/modals.js b/server/sonar-web/src/main/js/components/common/modals.js index 5060b2a80ad..931ca8e4604 100644 --- a/server/sonar-web/src/main/js/components/common/modals.js +++ b/server/sonar-web/src/main/js/components/common/modals.js @@ -1,74 +1,74 @@ -define(function () { +import $ from 'jquery'; +import Marionette from 'backbone.marionette'; - var $ = jQuery, - EVENT_SCOPE = 'modal'; +const EVENT_SCOPE = 'modal'; - return Marionette.ItemView.extend({ - className: 'modal', - overlayClassName: 'modal-overlay', - htmlClassName: 'modal-open', +export default Marionette.ItemView.extend({ + className: 'modal', + overlayClassName: 'modal-overlay', + htmlClassName: 'modal-open', - events: function () { - return { - 'click .js-modal-close': 'onCloseClick' - }; - }, + events: function () { + return { + 'click .js-modal-close': 'onCloseClick' + }; + }, - onRender: function () { - var that = this; - this.$el.detach().appendTo($('body')); - $('html').addClass(this.htmlClassName); - this.renderOverlay(); - this.keyScope = key.getScope(); - key.setScope('modal'); - key('escape', 'modal', function () { - that.destroy(); - return false; - }); - this.show(); - if (!!this.options.large) { - this.$el.addClass('modal-large'); - } - }, - - show: function () { - var that = this; - setTimeout(function () { - that.$el.addClass('in'); - $('.' + that.overlayClassName).addClass('in'); - }, 0); - }, - - onDestroy: function () { - $('html').removeClass(this.htmlClassName); - this.removeOverlay(); - key.deleteScope('modal'); - key.setScope(this.keyScope); - }, + onRender: function () { + var that = this; + this.$el.detach().appendTo($('body')); + $('html').addClass(this.htmlClassName); + this.renderOverlay(); + this.keyScope = key.getScope(); + key.setScope('modal'); + key('escape', 'modal', function () { + that.destroy(); + return false; + }); + this.show(); + if (!!this.options.large) { + this.$el.addClass('modal-large'); + } + }, - onCloseClick: function (e) { - e.preventDefault(); - this.destroy(); - }, + show: function () { + var that = this; + setTimeout(function () { + that.$el.addClass('in'); + $('.' + that.overlayClassName).addClass('in'); + }, 0); + }, - renderOverlay: function () { - var overlay = $('.' + this.overlayClassName); - if (overlay.length === 0) { - $('<div class="' + this.overlayClassName + '"></div>').appendTo($('body')); - } - }, + onDestroy: function () { + $('html').removeClass(this.htmlClassName); + this.removeOverlay(); + key.deleteScope('modal'); + key.setScope(this.keyScope); + }, - removeOverlay: function () { - $('.' + this.overlayClassName).remove(); - }, + onCloseClick: function (e) { + e.preventDefault(); + this.destroy(); + }, - attachCloseEvents: function () { - var that = this; - $('body').on('click.' + EVENT_SCOPE, function () { - $('body').off('click.' + EVENT_SCOPE); - that.destroy(); - }); + renderOverlay: function () { + var overlay = $('.' + this.overlayClassName); + if (overlay.length === 0) { + $('<div class="' + this.overlayClassName + '"></div>').appendTo($('body')); } - }); + }, + removeOverlay: function () { + $('.' + this.overlayClassName).remove(); + }, + + attachCloseEvents: function () { + var that = this; + $('body').on('click.' + EVENT_SCOPE, function () { + $('body').off('click.' + EVENT_SCOPE); + that.destroy(); + }); + } }); + + diff --git a/server/sonar-web/src/main/js/components/common/popup.js b/server/sonar-web/src/main/js/components/common/popup.js index a3d15c1bbb8..b7b1651b658 100644 --- a/server/sonar-web/src/main/js/components/common/popup.js +++ b/server/sonar-web/src/main/js/components/common/popup.js @@ -1,53 +1,52 @@ -define(function () { +import $ from 'jquery'; +import Marionette from 'backbone.marionette'; - var $ = jQuery; +export default Marionette.ItemView.extend({ + className: 'bubble-popup', - return Marionette.ItemView.extend({ - className: 'bubble-popup', - - onRender: function () { - this.$el.detach().appendTo($('body')); - if (this.options.bottom) { - this.$el.addClass('bubble-popup-bottom'); - this.$el.css({ - top: this.options.triggerEl.offset().top + this.options.triggerEl.outerHeight(), - left: this.options.triggerEl.offset().left - }); - } else if (this.options.bottomRight) { - this.$el.addClass('bubble-popup-bottom-right'); - this.$el.css({ - top: this.options.triggerEl.offset().top + this.options.triggerEl.outerHeight(), - right: $(window).width() - this.options.triggerEl.offset().left - this.options.triggerEl.outerWidth() - }); - } else { - this.$el.css({ - top: this.options.triggerEl.offset().top, - left: this.options.triggerEl.offset().left + this.options.triggerEl.outerWidth() - }); - } - this.attachCloseEvents(); - }, - - attachCloseEvents: function () { - var that = this; - key('escape', function () { - that.destroy(); + onRender: function () { + this.$el.detach().appendTo($('body')); + if (this.options.bottom) { + this.$el.addClass('bubble-popup-bottom'); + this.$el.css({ + top: this.options.triggerEl.offset().top + this.options.triggerEl.outerHeight(), + left: this.options.triggerEl.offset().left }); - $('body').on('click.bubble-popup', function () { - $('body').off('click.bubble-popup'); - that.destroy(); + } else if (this.options.bottomRight) { + this.$el.addClass('bubble-popup-bottom-right'); + this.$el.css({ + top: this.options.triggerEl.offset().top + this.options.triggerEl.outerHeight(), + right: $(window).width() - this.options.triggerEl.offset().left - this.options.triggerEl.outerWidth() }); - this.options.triggerEl.on('click.bubble-popup', function (e) { - that.options.triggerEl.off('click.bubble-popup'); - e.stopPropagation(); - that.destroy(); + } else { + this.$el.css({ + top: this.options.triggerEl.offset().top, + left: this.options.triggerEl.offset().left + this.options.triggerEl.outerWidth() }); - }, + } + this.attachCloseEvents(); + }, - onDestroy: function () { + attachCloseEvents: function () { + var that = this; + key('escape', function () { + that.destroy(); + }); + $('body').on('click.bubble-popup', function () { $('body').off('click.bubble-popup'); - this.options.triggerEl.off('click.bubble-popup'); - } - }); + that.destroy(); + }); + this.options.triggerEl.on('click.bubble-popup', function (e) { + that.options.triggerEl.off('click.bubble-popup'); + e.stopPropagation(); + that.destroy(); + }); + }, + onDestroy: function () { + $('body').off('click.bubble-popup'); + this.options.triggerEl.off('click.bubble-popup'); + } }); + + diff --git a/server/sonar-web/src/main/js/components/common/select-list.js b/server/sonar-web/src/main/js/components/common/select-list.js index a632eb60f89..be096e6128b 100644 --- a/server/sonar-web/src/main/js/components/common/select-list.js +++ b/server/sonar-web/src/main/js/components/common/select-list.js @@ -1,452 +1,453 @@ -define(function () { - - var $ = jQuery, - showError = null; - - /* - * SelectList Collection - */ - - var SelectListCollection = Backbone.Collection.extend({ - - initialize: function (options) { - this.options = options; - }, - - parse: function (r) { - return this.options.parse.call(this, r); - }, - - fetch: function (options) { - var data = $.extend({ - page: 1, - pageSize: 100 - }, options.data || {}), - settings = $.extend({}, options, { data: data }); - - this.settings = { - url: settings.url, - data: data - }; - - Backbone.Collection.prototype.fetch.call(this, settings); - }, - - fetchNextPage: function (options) { - if (this.more) { - var nextPage = this.settings.data.page + 1, - settings = $.extend(this.settings, options); - - settings.data.page = nextPage; - settings.remove = false; - this.fetch(settings); - } else { - options.error(); - } +import $ from 'jquery'; +import _ from 'underscore'; +import Backbone from 'backbone'; + +var showError = null; + +/* + * SelectList Collection + */ + +var SelectListCollection = Backbone.Collection.extend({ + + initialize: function (options) { + this.options = options; + }, + + parse: function (r) { + return this.options.parse.call(this, r); + }, + + fetch: function (options) { + var data = $.extend({ + page: 1, + pageSize: 100 + }, options.data || {}), + settings = $.extend({}, options, { data: data }); + + this.settings = { + url: settings.url, + data: data + }; + + Backbone.Collection.prototype.fetch.call(this, settings); + }, + + fetchNextPage: function (options) { + if (this.more) { + var nextPage = this.settings.data.page + 1, + settings = $.extend(this.settings, options); + + settings.data.page = nextPage; + settings.remove = false; + this.fetch(settings); + } else { + options.error(); } + } - }); - - - /* - * SelectList Item View - */ - - var SelectListItemView = Backbone.View.extend({ - tagName: 'li', - - template: function (d) { - return '<input class="select-list-list-checkbox" type="checkbox">' + - '<div class="select-list-list-item">' + d + '</div>'; - }, - - events: { - 'change .select-list-list-checkbox': 'toggle' - }, +}); - initialize: function (options) { - this.listenTo(this.model, 'change', this.render); - this.settings = options.settings; - }, - render: function () { - this.$el.html(this.template(this.settings.format(this.model.toJSON()))); - this.$('input').prop('name', this.model.get('name')); - this.$el.toggleClass('selected', this.model.get('selected')); - this.$('.select-list-list-checkbox') - .prop('title', - this.model.get('selected') ? - this.settings.tooltips.deselect : - this.settings.tooltips.select) - .prop('checked', this.model.get('selected')); +/* + * SelectList Item View + */ + +var SelectListItemView = Backbone.View.extend({ + tagName: 'li', + + template: function (d) { + return '<input class="select-list-list-checkbox" type="checkbox">' + + '<div class="select-list-list-item">' + d + '</div>'; + }, + + events: { + 'change .select-list-list-checkbox': 'toggle' + }, + + initialize: function (options) { + this.listenTo(this.model, 'change', this.render); + this.settings = options.settings; + }, + + render: function () { + this.$el.html(this.template(this.settings.format(this.model.toJSON()))); + this.$('input').prop('name', this.model.get('name')); + this.$el.toggleClass('selected', this.model.get('selected')); + this.$('.select-list-list-checkbox') + .prop('title', + this.model.get('selected') ? + this.settings.tooltips.deselect : + this.settings.tooltips.select) + .prop('checked', this.model.get('selected')); + + if (this.settings.readOnly) { + this.$('.select-list-list-checkbox').prop('disabled', true); + } + }, - if (this.settings.readOnly) { - this.$('.select-list-list-checkbox').prop('disabled', true); - } - }, - - remove: function (postpone) { - if (postpone) { - var that = this; - that.$el.addClass(this.model.get('selected') ? 'added' : 'removed'); - setTimeout(function () { - Backbone.View.prototype.remove.call(that, arguments); - }, 500); - } else { - Backbone.View.prototype.remove.call(this, arguments); + remove: function (postpone) { + if (postpone) { + var that = this; + that.$el.addClass(this.model.get('selected') ? 'added' : 'removed'); + setTimeout(function () { + Backbone.View.prototype.remove.call(that, arguments); + }, 500); + } else { + Backbone.View.prototype.remove.call(this, arguments); + } + }, + + toggle: function () { + var selected = this.model.get('selected'), + that = this, + url = selected ? this.settings.deselectUrl : this.settings.selectUrl, + data = $.extend({}, this.settings.extra || {}); + + data[this.settings.selectParameter] = this.model.get(this.settings.selectParameterValue); + + that.$el.addClass('progress'); + $.ajax({ + url: url, + type: 'POST', + data: data, + statusCode: { + // do not show global error + 400: null, + 401: null, + 403: null, + 500: null } - }, - - toggle: function () { - var selected = this.model.get('selected'), - that = this, - url = selected ? this.settings.deselectUrl : this.settings.selectUrl, - data = $.extend({}, this.settings.extra || {}); + }) + .done(function () { + that.model.set('selected', !selected); + }) + .fail(function (jqXHR) { + that.render(); + showError(jqXHR); + }) + .always(function () { + that.$el.removeClass('progress'); + }); + } +}); - data[this.settings.selectParameter] = this.model.get(this.settings.selectParameterValue); - that.$el.addClass('progress'); - $.ajax({ - url: url, - type: 'POST', - data: data, - statusCode: { - // do not show global error - 400: null, - 401: null, - 403: null, - 500: null +/* + * SelectList View + */ + +var SelectListView = Backbone.View.extend({ + template: function (l) { + return '<div class="select-list-container">' + + '<div class="select-list-control">' + + '<div class="select-list-check-control">' + + '<a class="select-list-control-button" name="selected">' + l.selected + '</a>' + + '<a class="select-list-control-button" name="deselected">' + l.deselected + '</a>' + + '<a class="select-list-control-button" name="all">' + l.all + '</a>' + + '</div>' + + '<div class="select-list-search-control">' + + '<form class="search-box">' + + '<span class="search-box-submit button-clean"><i class="icon-search"></i></span>' + + '<input class="search-box-input" type="search" name="q" placeholder="Search" maxlength="100" autocomplete="off">' + + '</form>' + + '</div>' + + '</div>' + + '<div class="select-list-list-container">' + + '<ul class="select-list-list"></ul>' + + '</div>' + + '</div>'; + }, + + events: { + 'click .select-list-control-button[name=selected]': 'showSelected', + 'click .select-list-control-button[name=deselected]': 'showDeselected', + 'click .select-list-control-button[name=all]': 'showAll' + }, + + initialize: function (options) { + this.listenTo(this.collection, 'add', this.renderListItem); + this.listenTo(this.collection, 'reset', this.renderList); + this.listenTo(this.collection, 'remove', this.removeModel); + this.listenTo(this.collection, 'change:selected', this.confirmFilter); + this.settings = options.settings; + + var that = this; + this.showFetchSpinner = function () { + that.$listContainer.addClass('loading'); + }; + this.hideFetchSpinner = function () { + that.$listContainer.removeClass('loading'); + }; + + var onScroll = function () { + that.showFetchSpinner(); + + that.collection.fetchNextPage({ + success: function () { + that.hideFetchSpinner(); + }, + error: function () { + that.hideFetchSpinner(); } - }) - .done(function () { - that.model.set('selected', !selected); - }) - .fail(function (jqXHR) { - that.render(); - showError(jqXHR); - }) - .always(function () { - that.$el.removeClass('progress'); + }); + }; + this.onScroll = _.throttle(onScroll, 1000); + }, + + render: function () { + var that = this, + keyup = function () { + that.search(); + }; + + this.$el.html(this.template(this.settings.labels)) + .width(this.settings.width); + + this.$listContainer = this.$('.select-list-list-container'); + if (!this.settings.readOnly) { + this.$listContainer + .height(this.settings.height) + .css('overflow', 'auto') + .on('scroll', function () { + that.scroll(); }); + } else { + this.$listContainer.addClass('select-list-list-container-readonly'); } - }); + this.$list = this.$('.select-list-list'); - /* - * SelectList View - */ - - var SelectListView = Backbone.View.extend({ - template: function (l) { - return '<div class="select-list-container">' + - '<div class="select-list-control">' + - '<div class="select-list-check-control">' + - '<a class="select-list-control-button" name="selected">' + l.selected + '</a>' + - '<a class="select-list-control-button" name="deselected">' + l.deselected + '</a>' + - '<a class="select-list-control-button" name="all">' + l.all + '</a>' + - '</div>' + - '<div class="select-list-search-control">' + - '<form class="search-box">' + - '<span class="search-box-submit button-clean"><i class="icon-search"></i></span>' + - '<input class="search-box-input" type="search" name="q" placeholder="Search" maxlength="100" autocomplete="off">' + - '</form>' + - '</div>' + - '</div>' + - '<div class="select-list-list-container">' + - '<ul class="select-list-list"></ul>' + - '</div>' + - '</div>'; - }, - - events: { - 'click .select-list-control-button[name=selected]': 'showSelected', - 'click .select-list-control-button[name=deselected]': 'showDeselected', - 'click .select-list-control-button[name=all]': 'showAll' - }, - - initialize: function (options) { - this.listenTo(this.collection, 'add', this.renderListItem); - this.listenTo(this.collection, 'reset', this.renderList); - this.listenTo(this.collection, 'remove', this.removeModel); - this.listenTo(this.collection, 'change:selected', this.confirmFilter); - this.settings = options.settings; - - var that = this; - this.showFetchSpinner = function () { - that.$listContainer.addClass('loading'); - }; - this.hideFetchSpinner = function () { - that.$listContainer.removeClass('loading'); - }; - - var onScroll = function () { - that.showFetchSpinner(); - - that.collection.fetchNextPage({ - success: function () { - that.hideFetchSpinner(); - }, - error: function () { - that.hideFetchSpinner(); - } - }); - }; - this.onScroll = _.throttle(onScroll, 1000); - }, - - render: function () { - var that = this, - keyup = function () { - that.search(); - }; - - this.$el.html(this.template(this.settings.labels)) - .width(this.settings.width); - - this.$listContainer = this.$('.select-list-list-container'); - if (!this.settings.readOnly) { - this.$listContainer - .height(this.settings.height) - .css('overflow', 'auto') - .on('scroll', function () { - that.scroll(); - }); - } else { - this.$listContainer.addClass('select-list-list-container-readonly'); - } + var searchInput = this.$('.select-list-search-control input') + .on('keyup', _.debounce(keyup, 250)) + .on('search', _.debounce(keyup, 250)); - this.$list = this.$('.select-list-list'); + if (this.settings.focusSearch) { + setTimeout(function () { + searchInput.focus(); + }, 250); + } - var searchInput = this.$('.select-list-search-control input') - .on('keyup', _.debounce(keyup, 250)) - .on('search', _.debounce(keyup, 250)); + this.listItemViews = []; - if (this.settings.focusSearch) { - setTimeout(function () { - searchInput.focus(); - }, 250); + showError = function (jqXHR) { + var message = window.t('default_error_message'); + if (jqXHR != null && jqXHR.responseJSON != null && jqXHR.responseJSON.errors != null) { + message = _.pluck(jqXHR.responseJSON.errors, 'msg').join('. '); } - this.listItemViews = []; - - showError = function (jqXHR) { - var message = window.t('default_error_message'); - if (jqXHR != null && jqXHR.responseJSON != null && jqXHR.responseJSON.errors != null) { - message = _.pluck(jqXHR.responseJSON.errors, 'msg').join('. '); - } + that.$el.prevAll('.alert').remove(); + $('<div>') + .addClass('alert alert-danger').text(message) + .insertBefore(that.$el); + }; - that.$el.prevAll('.alert').remove(); - $('<div>') - .addClass('alert alert-danger').text(message) - .insertBefore(that.$el); - }; + if (this.settings.readOnly) { + this.$('.select-list-control').remove(); + } + }, + renderList: function () { + this.listItemViews.forEach(function (view) { + view.remove(); + }); + this.listItemViews = []; + if (this.collection.length > 0) { + this.collection.each(this.renderListItem, this); + } else { if (this.settings.readOnly) { - this.$('.select-list-control').remove(); + this.renderEmpty(); } - }, + } + this.$listContainer.scrollTop(0); + }, - renderList: function () { - this.listItemViews.forEach(function (view) { - view.remove(); + renderListItem: function (item) { + var itemView = new SelectListItemView({ + model: item, + settings: this.settings + }); + this.listItemViews.push(itemView); + this.$list.append(itemView.el); + itemView.render(); + }, + + renderEmpty: function () { + this.$list.append('<li class="empty-message">' + this.settings.labels.noResults + '</li>'); + }, + + confirmFilter: function (model) { + if (this.currentFilter !== 'all') { + this.collection.remove(model); + } + }, + + removeModel: function (model, collection, options) { + this.listItemViews[options.index].remove(true); + this.listItemViews.splice(options.index, 1); + }, + + filterBySelection: function (filter) { + var that = this; + filter = this.currentFilter = filter || this.currentFilter; + + if (filter != null) { + this.$('.select-list-check-control').toggleClass('disabled', false); + this.$('.select-list-search-control').toggleClass('disabled', true); + this.$('.select-list-search-control input').val(''); + + this.$('.select-list-control-button').removeClass('active') + .filter('[name=' + filter + ']').addClass('active'); + + this.showFetchSpinner(); + + this.collection.fetch({ + url: this.settings.searchUrl, + reset: true, + data: { selected: filter }, + success: function () { + that.hideFetchSpinner(); + }, + error: showError }); - this.listItemViews = []; - if (this.collection.length > 0) { - this.collection.each(this.renderListItem, this); - } else { - if (this.settings.readOnly) { - this.renderEmpty(); - } - } - this.$listContainer.scrollTop(0); - }, - - renderListItem: function (item) { - var itemView = new SelectListItemView({ - model: item, - settings: this.settings + } + }, + + showSelected: function () { + this.filterBySelection('selected'); + }, + + showDeselected: function () { + this.filterBySelection('deselected'); + }, + + showAll: function () { + this.filterBySelection('all'); + }, + + search: function () { + var query = this.$('.select-list-search-control input').val(), + hasQuery = query.length > 0, + that = this, + data = {}; + + this.$('.select-list-check-control').toggleClass('disabled', hasQuery); + this.$('.select-list-search-control').toggleClass('disabled', !hasQuery); + + if (hasQuery) { + this.showFetchSpinner(); + this.currentFilter = 'all'; + + data[this.settings.queryParam] = query; + data.selected = 'all'; + this.collection.fetch({ + url: this.settings.searchUrl, + reset: true, + data: data, + success: function () { + that.hideFetchSpinner(); + }, + error: showError }); - this.listItemViews.push(itemView); - this.$list.append(itemView.el); - itemView.render(); - }, - - renderEmpty: function () { - this.$list.append('<li class="empty-message">' + this.settings.labels.noResults + '</li>'); - }, - - confirmFilter: function (model) { - if (this.currentFilter !== 'all') { - this.collection.remove(model); - } - }, - - removeModel: function (model, collection, options) { - this.listItemViews[options.index].remove(true); - this.listItemViews.splice(options.index, 1); - }, - - filterBySelection: function (filter) { - var that = this; - filter = this.currentFilter = filter || this.currentFilter; - - if (filter != null) { - this.$('.select-list-check-control').toggleClass('disabled', false); - this.$('.select-list-search-control').toggleClass('disabled', true); - this.$('.select-list-search-control input').val(''); - - this.$('.select-list-control-button').removeClass('active') - .filter('[name=' + filter + ']').addClass('active'); - - this.showFetchSpinner(); - - this.collection.fetch({ - url: this.settings.searchUrl, - reset: true, - data: { selected: filter }, - success: function () { - that.hideFetchSpinner(); - }, - error: showError - }); - } - }, - - showSelected: function () { - this.filterBySelection('selected'); - }, - - showDeselected: function () { - this.filterBySelection('deselected'); - }, - - showAll: function () { - this.filterBySelection('all'); - }, - - search: function () { - var query = this.$('.select-list-search-control input').val(), - hasQuery = query.length > 0, - that = this, - data = {}; - - this.$('.select-list-check-control').toggleClass('disabled', hasQuery); - this.$('.select-list-search-control').toggleClass('disabled', !hasQuery); - - if (hasQuery) { - this.showFetchSpinner(); - this.currentFilter = 'all'; - - data[this.settings.queryParam] = query; - data.selected = 'all'; - this.collection.fetch({ - url: this.settings.searchUrl, - reset: true, - data: data, - success: function () { - that.hideFetchSpinner(); - }, - error: showError - }); - } else { - this.filterBySelection(); - } - }, + } else { + this.filterBySelection(); + } + }, - searchByQuery: function (query) { - this.$('.select-list-search-control input').val(query); - this.search(); - }, + searchByQuery: function (query) { + this.$('.select-list-search-control input').val(query); + this.search(); + }, - clearSearch: function () { - this.filterBySelection(); - }, + clearSearch: function () { + this.filterBySelection(); + }, - scroll: function () { - var scrollBottom = this.$listContainer.scrollTop() >= - this.$list[0].scrollHeight - this.$listContainer.outerHeight(); + scroll: function () { + var scrollBottom = this.$listContainer.scrollTop() >= + this.$list[0].scrollHeight - this.$listContainer.outerHeight(); - if (scrollBottom && this.collection.more) { - this.onScroll(); - } + if (scrollBottom && this.collection.more) { + this.onScroll(); } + } - }); +}); - /* - * SelectList Entry Point - */ +/* + * SelectList Entry Point + */ - window.SelectList = function (options) { - this.settings = $.extend(window.SelectList.defaults, options); +window.SelectList = function (options) { + this.settings = $.extend(window.SelectList.defaults, options); - this.collection = new SelectListCollection({ - parse: this.settings.parse - }); + this.collection = new SelectListCollection({ + parse: this.settings.parse + }); - this.view = new SelectListView({ - el: this.settings.el, - collection: this.collection, - settings: this.settings - }); + this.view = new SelectListView({ + el: this.settings.el, + collection: this.collection, + settings: this.settings + }); - this.view.render(); - this.filter('selected'); - return this; - }; + this.view.render(); + this.filter('selected'); + return this; +}; - /* - * SelectList API Methods - */ +/* + * SelectList API Methods + */ - window.SelectList.prototype.filter = function (filter) { - this.view.filterBySelection(filter); - return this; - }; +window.SelectList.prototype.filter = function (filter) { + this.view.filterBySelection(filter); + return this; +}; - window.SelectList.prototype.search = function (query) { - this.view.searchByQuery(query); - return this; - }; +window.SelectList.prototype.search = function (query) { + this.view.searchByQuery(query); + return this; +}; - /* - * SelectList Defaults - */ +/* + * SelectList Defaults + */ - window.SelectList.defaults = { - width: '50%', - height: 400, +window.SelectList.defaults = { + width: '50%', + height: 400, - readOnly: false, - focusSearch: true, + readOnly: false, + focusSearch: true, - format: function (item) { - return item.value; - }, + format: function (item) { + return item.value; + }, - parse: function (r) { - this.more = r.more; - return r.results; - }, + parse: function (r) { + this.more = r.more; + return r.results; + }, - queryParam: 'query', + queryParam: 'query', - labels: { - selected: 'Selected', - deselected: 'Deselected', - all: 'All', - noResults: '' - }, + labels: { + selected: 'Selected', + deselected: 'Deselected', + all: 'All', + noResults: '' + }, - tooltips: { - select: 'Click this to select item', - deselect: 'Click this to deselect item' - }, + tooltips: { + select: 'Click this to select item', + deselect: 'Click this to deselect item' + }, + + errorMessage: 'Something gone wrong, try to reload the page and try again.' +}; - errorMessage: 'Something gone wrong, try to reload the page and try again.' - }; -}); diff --git a/server/sonar-web/src/main/js/components/common/selectable-collection-view.js b/server/sonar-web/src/main/js/components/common/selectable-collection-view.js index 5445f9578b7..1e369438c7f 100644 --- a/server/sonar-web/src/main/js/components/common/selectable-collection-view.js +++ b/server/sonar-web/src/main/js/components/common/selectable-collection-view.js @@ -1,66 +1,66 @@ -define(function () { +import Marionette from 'backbone.marionette'; - return Marionette.CollectionView.extend({ +export default Marionette.CollectionView.extend({ - initialize: function () { - this.resetSelectedIndex(); - this.listenTo(this.collection, 'reset', this.resetSelectedIndex); - }, + initialize: function () { + this.resetSelectedIndex(); + this.listenTo(this.collection, 'reset', this.resetSelectedIndex); + }, - childViewOptions: function (model, index) { - return { index: index }; - }, + childViewOptions: function (model, index) { + return { index: index }; + }, - resetSelectedIndex: function () { - this.selectedIndex = 0; - }, + resetSelectedIndex: function () { + this.selectedIndex = 0; + }, - onRender: function () { - this.selectCurrent(); - }, + onRender: function () { + this.selectCurrent(); + }, - submitCurrent: function () { - var view = this.children.findByIndex(this.selectedIndex); - if (view != null) { - view.submit(); - } - }, - - selectCurrent: function () { - this.selectItem(this.selectedIndex); - }, + submitCurrent: function () { + var view = this.children.findByIndex(this.selectedIndex); + if (view != null) { + view.submit(); + } + }, - selectNext: function () { - if (this.selectedIndex < this.collection.length - 1) { - this.deselectItem(this.selectedIndex); - this.selectedIndex++; - this.selectItem(this.selectedIndex); - } - }, + selectCurrent: function () { + this.selectItem(this.selectedIndex); + }, - selectPrev: function () { - if (this.selectedIndex > 0) { - this.deselectItem(this.selectedIndex); - this.selectedIndex--; - this.selectItem(this.selectedIndex); - } - }, + selectNext: function () { + if (this.selectedIndex < this.collection.length - 1) { + this.deselectItem(this.selectedIndex); + this.selectedIndex++; + this.selectItem(this.selectedIndex); + } + }, - selectItem: function (index) { - if (index >= 0 && index < this.collection.length) { - var view = this.children.findByIndex(index); - if (view != null) { - view.select(); - } - } - }, + selectPrev: function () { + if (this.selectedIndex > 0) { + this.deselectItem(this.selectedIndex); + this.selectedIndex--; + this.selectItem(this.selectedIndex); + } + }, - deselectItem: function (index) { + selectItem: function (index) { + if (index >= 0 && index < this.collection.length) { var view = this.children.findByIndex(index); if (view != null) { - view.deselect(); + view.select(); } } - }); + }, + deselectItem: function (index) { + var view = this.children.findByIndex(index); + if (view != null) { + view.deselect(); + } + } }); + + diff --git a/server/sonar-web/src/main/js/components/issue/collections/action-plans.js b/server/sonar-web/src/main/js/components/issue/collections/action-plans.js index 8cbef0a1a32..08b934e4f11 100644 --- a/server/sonar-web/src/main/js/components/issue/collections/action-plans.js +++ b/server/sonar-web/src/main/js/components/issue/collections/action-plans.js @@ -1,13 +1,13 @@ -define([], function () { +import Backbone from 'backbone'; - return Backbone.Collection.extend({ - url: function () { - return baseUrl + '/api/action_plans/search'; - }, - - parse: function (r) { - return r.actionPlans; - } - }); +export default Backbone.Collection.extend({ + url: function () { + return baseUrl + '/api/action_plans/search'; + }, + parse: function (r) { + return r.actionPlans; + } }); + + diff --git a/server/sonar-web/src/main/js/components/issue/collections/issues.js b/server/sonar-web/src/main/js/components/issue/collections/issues.js index ecad7d8405f..f6be646eddc 100644 --- a/server/sonar-web/src/main/js/components/issue/collections/issues.js +++ b/server/sonar-web/src/main/js/components/issue/collections/issues.js @@ -1,75 +1,75 @@ -define([ - '../models/issue' -], function (Issue) { +import _ from 'underscore'; +import Backbone from 'backbone'; +import Issue from '../models/issue'; - return Backbone.Collection.extend({ - model: Issue, +export default Backbone.Collection.extend({ + model: Issue, - url: function () { - return baseUrl + '/api/issues/search'; - }, + url: function () { + return baseUrl + '/api/issues/search'; + }, - _injectRelational: function (issue, source, baseField, lookupField) { - var baseValue = issue[baseField]; - if (baseValue != null && _.size(source)) { - var lookupValue = _.find(source, function (candidate) { - return candidate[lookupField] === baseValue; - }); - if (lookupValue != null) { - Object.keys(lookupValue).forEach(function (key) { - var newKey = baseField + key.charAt(0).toUpperCase() + key.slice(1); - issue[newKey] = lookupValue[key]; - }); - } - } - return issue; - }, - - _injectCommentsRelational: function (issue, users) { - if (issue.comments) { - var that = this; - var newComments = issue.comments.map(function (comment) { - var newComment = _.extend({}, comment, { author: comment.login }); - delete newComment.login; - newComment = that._injectRelational(newComment, users, 'author', 'login'); - return newComment; + _injectRelational: function (issue, source, baseField, lookupField) { + var baseValue = issue[baseField]; + if (baseValue != null && _.size(source)) { + var lookupValue = _.find(source, function (candidate) { + return candidate[lookupField] === baseValue; + }); + if (lookupValue != null) { + Object.keys(lookupValue).forEach(function (key) { + var newKey = baseField + key.charAt(0).toUpperCase() + key.slice(1); + issue[newKey] = lookupValue[key]; }); - issue = _.extend({}, issue, { comments: newComments }); } - return issue; - }, - - _prepareClosed: function (issue) { - if (issue.status === 'CLOSED') { - issue.flows = []; - delete issue.textRange; - } - return issue; - }, + } + return issue; + }, - parse: function (r) { + _injectCommentsRelational: function (issue, users) { + if (issue.comments) { var that = this; - - this.paging = { - p: r.p, - ps: r.ps, - total: r.total, - maxResultsReached: r.p * r.ps >= r.total - }; - - return r.issues.map(function (issue) { - issue = that._injectRelational(issue, r.components, 'component', 'key'); - issue = that._injectRelational(issue, r.components, 'project', 'key'); - issue = that._injectRelational(issue, r.components, 'subProject', 'key'); - issue = that._injectRelational(issue, r.rules, 'rule', 'key'); - issue = that._injectRelational(issue, r.users, 'assignee', 'login'); - issue = that._injectRelational(issue, r.users, 'reporter', 'login'); - issue = that._injectRelational(issue, r.actionPlans, 'actionPlan', 'key'); - issue = that._injectCommentsRelational(issue, r.users); - issue = that._prepareClosed(issue); - return issue; + var newComments = issue.comments.map(function (comment) { + var newComment = _.extend({}, comment, { author: comment.login }); + delete newComment.login; + newComment = that._injectRelational(newComment, users, 'author', 'login'); + return newComment; }); + issue = _.extend({}, issue, { comments: newComments }); } - }); + return issue; + }, + + _prepareClosed: function (issue) { + if (issue.status === 'CLOSED') { + issue.flows = []; + delete issue.textRange; + } + return issue; + }, + + parse: function (r) { + var that = this; + this.paging = { + p: r.p, + ps: r.ps, + total: r.total, + maxResultsReached: r.p * r.ps >= r.total + }; + + return r.issues.map(function (issue) { + issue = that._injectRelational(issue, r.components, 'component', 'key'); + issue = that._injectRelational(issue, r.components, 'project', 'key'); + issue = that._injectRelational(issue, r.components, 'subProject', 'key'); + issue = that._injectRelational(issue, r.rules, 'rule', 'key'); + issue = that._injectRelational(issue, r.users, 'assignee', 'login'); + issue = that._injectRelational(issue, r.users, 'reporter', 'login'); + issue = that._injectRelational(issue, r.actionPlans, 'actionPlan', 'key'); + issue = that._injectCommentsRelational(issue, r.users); + issue = that._prepareClosed(issue); + return issue; + }); + } }); + + diff --git a/server/sonar-web/src/main/js/components/issue/issue-view.js b/server/sonar-web/src/main/js/components/issue/issue-view.js index e5b8bf95d7e..5c91f18d23d 100644 --- a/server/sonar-web/src/main/js/components/issue/issue-view.js +++ b/server/sonar-web/src/main/js/components/issue/issue-view.js @@ -1,246 +1,241 @@ -define([ - './models/changelog', - './views/changelog-view', - './collections/action-plans', - './views/issue-popup', - './views/transitions-form-view', - './views/assign-form-view', - './views/comment-form-view', - './views/plan-form-view', - './views/set-severity-form-view', - './views/more-actions-view', - './views/tags-form-view', - 'components/workspace/main', - './templates' -], function (ChangeLog, ChangeLogView, ActionPlans, IssuePopup, TransitionsFormView, AssignFormView, CommentFormView, - PlanFormView, SetSeverityFormView, MoreActionsView, TagsFormView, Workspace) { - - var $ = jQuery; - - return Marionette.ItemView.extend({ - className: 'issue', - template: Templates.issue, - - modelEvents: { - 'change': 'render', - 'transition': 'onTransition' - }, - - events: function () { - return { - 'click .js-issue-comment': 'onComment', - 'click .js-issue-comment-edit': 'editComment', - 'click .js-issue-comment-delete': 'deleteComment', - 'click .js-issue-transition': 'transition', - 'click .js-issue-set-severity': 'setSeverity', - 'click .js-issue-assign': 'assign', - 'click .js-issue-assign-to-me': 'assignToMe', - 'click .js-issue-plan': 'plan', - 'click .js-issue-show-changelog': 'showChangeLog', - 'click .js-issue-rule': 'showRule', - 'click .js-issue-edit-tags': 'editTags', - 'click .js-issue-locations': 'showLocations' - }; - }, - - onRender: function () { - this.$el.attr('data-key', this.model.get('key')); - }, - - disableControls: function () { - this.$(':input').prop('disabled', true); - }, - - enableControls: function () { - this.$(':input').prop('disabled', false); - }, - - resetIssue: function (options) { - var that = this; - var key = this.model.get('key'), - componentUuid = this.model.get('componentUuid'); - this.model.reset({ key: key, componentUuid: componentUuid }, { silent: true }); - return this.model.fetch(options).done(function () { - return that.trigger('reset'); - }); - }, - - showChangeLog: function (e) { - var that = this; - var t = $(e.currentTarget), - changeLog = new ChangeLog(); - return changeLog.fetch({ - data: { issue: this.model.get('key') } - }).done(function () { - if (that.popup) { - that.popup.destroy(); - } - that.popup = new ChangeLogView({ - triggerEl: t, - bottomRight: true, - collection: changeLog, - issue: that.model - }); - that.popup.render(); - }); - }, - - updateAfterAction: function (fetch) { - if (this.popup) { - this.popup.destroy(); - } - if (fetch) { - this.resetIssue(); +import $ from 'jquery'; +import _ from 'underscore'; +import Backbone from 'backbone'; +import Marionette from 'backbone.marionette'; +import ChangeLog from './models/changelog'; +import ChangeLogView from './views/changelog-view'; +import ActionPlans from './collections/action-plans'; +import TransitionsFormView from './views/transitions-form-view'; +import AssignFormView from './views/assign-form-view'; +import CommentFormView from './views/comment-form-view'; +import PlanFormView from './views/plan-form-view'; +import SetSeverityFormView from './views/set-severity-form-view'; +import TagsFormView from './views/tags-form-view'; +import Workspace from 'components/workspace/main'; +import './templates'; + +export default Marionette.ItemView.extend({ + className: 'issue', + template: Templates.issue, + + modelEvents: { + 'change': 'render', + 'transition': 'onTransition' + }, + + events: function () { + return { + 'click .js-issue-comment': 'onComment', + 'click .js-issue-comment-edit': 'editComment', + 'click .js-issue-comment-delete': 'deleteComment', + 'click .js-issue-transition': 'transition', + 'click .js-issue-set-severity': 'setSeverity', + 'click .js-issue-assign': 'assign', + 'click .js-issue-assign-to-me': 'assignToMe', + 'click .js-issue-plan': 'plan', + 'click .js-issue-show-changelog': 'showChangeLog', + 'click .js-issue-rule': 'showRule', + 'click .js-issue-edit-tags': 'editTags', + 'click .js-issue-locations': 'showLocations' + }; + }, + + onRender: function () { + this.$el.attr('data-key', this.model.get('key')); + }, + + disableControls: function () { + this.$(':input').prop('disabled', true); + }, + + enableControls: function () { + this.$(':input').prop('disabled', false); + }, + + resetIssue: function (options) { + var that = this; + var key = this.model.get('key'), + componentUuid = this.model.get('componentUuid'); + this.model.reset({ key: key, componentUuid: componentUuid }, { silent: true }); + return this.model.fetch(options).done(function () { + return that.trigger('reset'); + }); + }, + + showChangeLog: function (e) { + var that = this; + var t = $(e.currentTarget), + changeLog = new ChangeLog(); + return changeLog.fetch({ + data: { issue: this.model.get('key') } + }).done(function () { + if (that.popup) { + that.popup.destroy(); } - }, - - onComment: function (e) { - e.stopPropagation(); - this.comment(); - }, - - comment: function (options) { - $('body').click(); - this.popup = new CommentFormView({ - triggerEl: this.$('.js-issue-comment'), - bottom: true, - issue: this.model, - detailView: this, - additionalOptions: options - }); - this.popup.render(); - }, - - editComment: function (e) { - e.stopPropagation(); - $('body').click(); - var commentEl = $(e.currentTarget).closest('.issue-comment'), - commentKey = commentEl.data('comment-key'), - comment = _.findWhere(this.model.get('comments'), { key: commentKey }); - this.popup = new CommentFormView({ - triggerEl: $(e.currentTarget), + that.popup = new ChangeLogView({ + triggerEl: t, bottomRight: true, - model: new Backbone.Model(comment), - issue: this.model, - detailView: this - }); - this.popup.render(); - }, - - deleteComment: function (e) { - var that = this; - var commentKey = $(e.target).closest('[data-comment-key]').data('comment-key'), - confirmMsg = $(e.target).data('confirm-msg'); - if (confirm(confirmMsg)) { - this.disableControls(); - return $.ajax({ - type: 'POST', - url: baseUrl + '/api/issues/delete_comment?key=' + commentKey - }).done(function () { - that.updateAfterAction(true); - }); - } - }, - - transition: function (e) { - e.stopPropagation(); - $('body').click(); - this.popup = new TransitionsFormView({ - triggerEl: $(e.currentTarget), - bottom: true, - model: this.model, - view: this + collection: changeLog, + issue: that.model }); - this.popup.render(); - }, + that.popup.render(); + }); + }, - setSeverity: function (e) { - e.stopPropagation(); - $('body').click(); - this.popup = new SetSeverityFormView({ - triggerEl: $(e.currentTarget), - bottom: true, - model: this.model - }); - this.popup.render(); - }, - - assign: function (e) { - e.stopPropagation(); - $('body').click(); - this.popup = new AssignFormView({ - triggerEl: $(e.currentTarget), - bottom: true, - model: this.model - }); - this.popup.render(); - }, - - assignToMe: function () { - var view = new AssignFormView({ - model: this.model, - triggerEl: $('body') - }); - view.submit(window.SS.user, window.SS.userName); - view.destroy(); - }, - - plan: function (e) { - var that = this; - var t = $(e.currentTarget), - actionPlans = new ActionPlans(); - return actionPlans.fetch({ - reset: true, - data: { project: this.model.get('project') } + updateAfterAction: function (fetch) { + if (this.popup) { + this.popup.destroy(); + } + if (fetch) { + this.resetIssue(); + } + }, + + onComment: function (e) { + e.stopPropagation(); + this.comment(); + }, + + comment: function (options) { + $('body').click(); + this.popup = new CommentFormView({ + triggerEl: this.$('.js-issue-comment'), + bottom: true, + issue: this.model, + detailView: this, + additionalOptions: options + }); + this.popup.render(); + }, + + editComment: function (e) { + e.stopPropagation(); + $('body').click(); + var commentEl = $(e.currentTarget).closest('.issue-comment'), + commentKey = commentEl.data('comment-key'), + comment = _.findWhere(this.model.get('comments'), { key: commentKey }); + this.popup = new CommentFormView({ + triggerEl: $(e.currentTarget), + bottomRight: true, + model: new Backbone.Model(comment), + issue: this.model, + detailView: this + }); + this.popup.render(); + }, + + deleteComment: function (e) { + var that = this; + var commentKey = $(e.target).closest('[data-comment-key]').data('comment-key'), + confirmMsg = $(e.target).data('confirm-msg'); + if (confirm(confirmMsg)) { + this.disableControls(); + return $.ajax({ + type: 'POST', + url: baseUrl + '/api/issues/delete_comment?key=' + commentKey }).done(function () { - e.stopPropagation(); - $('body').click(); - that.popup = new PlanFormView({ - triggerEl: t, - bottom: true, - model: that.model, - collection: actionPlans - }); - that.popup.render(); + that.updateAfterAction(true); }); - }, - - showRule: function () { - if (Workspace == null) { - Workspace = require('components/workspace/main'); - } - var ruleKey = this.model.get('rule'); - Workspace.openRule({ key: ruleKey }); - }, - - editTags: function (e) { + } + }, + + transition: function (e) { + e.stopPropagation(); + $('body').click(); + this.popup = new TransitionsFormView({ + triggerEl: $(e.currentTarget), + bottom: true, + model: this.model, + view: this + }); + this.popup.render(); + }, + + setSeverity: function (e) { + e.stopPropagation(); + $('body').click(); + this.popup = new SetSeverityFormView({ + triggerEl: $(e.currentTarget), + bottom: true, + model: this.model + }); + this.popup.render(); + }, + + assign: function (e) { + e.stopPropagation(); + $('body').click(); + this.popup = new AssignFormView({ + triggerEl: $(e.currentTarget), + bottom: true, + model: this.model + }); + this.popup.render(); + }, + + assignToMe: function () { + var view = new AssignFormView({ + model: this.model, + triggerEl: $('body') + }); + view.submit(window.SS.user, window.SS.userName); + view.destroy(); + }, + + plan: function (e) { + var that = this; + var t = $(e.currentTarget), + actionPlans = new ActionPlans(); + return actionPlans.fetch({ + reset: true, + data: { project: this.model.get('project') } + }).done(function () { e.stopPropagation(); $('body').click(); - this.popup = new TagsFormView({ - triggerEl: $(e.currentTarget), - bottomRight: true, - model: this.model - }); - this.popup.render(); - }, - - showLocations: function () { - this.model.trigger('locations', this.model); - }, - - onTransition: function (transition) { - if (transition === 'falsepositive' || transition === 'wontfix') { - this.comment({ fromTransition: true }); - } - }, - - serializeData: function () { - var issueKey = encodeURIComponent(this.model.get('key')); - return _.extend(Marionette.ItemView.prototype.serializeData.apply(this, arguments), { - permalink: baseUrl + '/issues/search#issues=' + issueKey, - hasSecondaryLocations: this.model.get('flows').length + that.popup = new PlanFormView({ + triggerEl: t, + bottom: true, + model: that.model, + collection: actionPlans }); + that.popup.render(); + }); + }, + + showRule: function () { + var ruleKey = this.model.get('rule'); + var RealWorkspace = Workspace.openComponent ? Workspace : require('components/workspace/main'); + RealWorkspace.openRule({ key: ruleKey }); + }, + + editTags: function (e) { + e.stopPropagation(); + $('body').click(); + this.popup = new TagsFormView({ + triggerEl: $(e.currentTarget), + bottomRight: true, + model: this.model + }); + this.popup.render(); + }, + + showLocations: function () { + this.model.trigger('locations', this.model); + }, + + onTransition: function (transition) { + if (transition === 'falsepositive' || transition === 'wontfix') { + this.comment({ fromTransition: true }); } - }); - + }, + + serializeData: function () { + var issueKey = encodeURIComponent(this.model.get('key')); + return _.extend(Marionette.ItemView.prototype.serializeData.apply(this, arguments), { + permalink: baseUrl + '/issues/search#issues=' + issueKey, + hasSecondaryLocations: this.model.get('flows').length + }); + } }); + + diff --git a/server/sonar-web/src/main/js/components/issue/manual-issue-view.js b/server/sonar-web/src/main/js/components/issue/manual-issue-view.js index 2f819f62f2b..31b318a4ac8 100644 --- a/server/sonar-web/src/main/js/components/issue/manual-issue-view.js +++ b/server/sonar-web/src/main/js/components/issue/manual-issue-view.js @@ -1,80 +1,79 @@ -define([ - './models/issue', - './templates' -], function (Issue) { +import $ from 'jquery'; +import _ from 'underscore'; +import Marionette from 'backbone.marionette'; +import Issue from './models/issue'; +import './templates'; - var $ = jQuery; +export default Marionette.ItemView.extend({ + template: Templates['manual-issue'], - return Marionette.ItemView.extend({ - template: Templates['manual-issue'], + events: { + 'submit .js-manual-issue-form': 'formSubmit', + 'click .js-cancel': 'cancel' + }, - events: { - 'submit .js-manual-issue-form': 'formSubmit', - 'click .js-cancel': 'cancel' - }, + initialize: function () { + var that = this; + this.rules = []; + $.get(baseUrl + '/api/rules/search?repositories=manual&f=name&ps=9999999').done(function (r) { + that.rules = r.rules; + that.render(); + }); + }, - initialize: function () { - var that = this; - this.rules = []; - $.get(baseUrl + '/api/rules/search?repositories=manual&f=name&ps=9999999').done(function (r) { - that.rules = r.rules; - that.render(); - }); - }, + onRender: function () { + this.delegateEvents(); + this.$('[name=rule]').select2({ + width: '250px', + minimumResultsForSearch: 10 + }); + if (this.rules.length > 0) { + this.$('[name=rule]').select2('open'); + } + if (key != null) { + this.key = key.getScope(); + key.setScope(''); + } + }, - onRender: function () { - this.delegateEvents(); - this.$('[name=rule]').select2({ - width: '250px', - minimumResultsForSearch: 10 - }); - if (this.rules.length > 0) { - this.$('[name=rule]').select2('open'); - } - if (key != null) { - this.key = key.getScope(); - key.setScope(''); - } - }, + onDestroy: function () { + if (key != null && this.key != null) { + key.setScope(this.key); + } + }, - onDestroy: function () { - if (key != null && this.key != null) { - key.setScope(this.key); - } - }, + formSubmit: function (e) { + var that = this; + e.preventDefault(); + var issue = new Issue({ + component: this.options.component, + line: this.options.line, + message: this.$('[name="message"]').val(), + rule: this.$('[name="rule"]').val() + }); + issue.save().done(function () { + that.addIssue(issue); + }); + }, - formSubmit: function (e) { - var that = this; - e.preventDefault(); - var issue = new Issue({ - component: this.options.component, - line: this.options.line, - message: this.$('[name="message"]').val(), - rule: this.$('[name="rule"]').val() - }); - issue.save().done(function () { - that.addIssue(issue); - }); - }, + addIssue: function (issue) { + var that = this; + return issue.fetch().done(function () { + that.trigger('add', issue); + that.destroy(); + }); + }, - addIssue: function (issue) { - var that = this; - return issue.fetch().done(function () { - that.trigger('add', issue); - that.destroy(); - }); - }, + cancel: function (e) { + e.preventDefault(); + this.destroy(); + }, - cancel: function (e) { - e.preventDefault(); - this.destroy(); - }, + serializeData: function () { + return _.extend(this._super(), { + rules: _.sortBy(this.rules, 'name') + }); + } +}); - serializeData: function () { - return _.extend(this._super(), { - rules: _.sortBy(this.rules, 'name') - }); - } - }); -}); diff --git a/server/sonar-web/src/main/js/components/issue/models/changelog.js b/server/sonar-web/src/main/js/components/issue/models/changelog.js index a7efe2b886a..bf43428b8ec 100644 --- a/server/sonar-web/src/main/js/components/issue/models/changelog.js +++ b/server/sonar-web/src/main/js/components/issue/models/changelog.js @@ -1,13 +1,13 @@ -define([], function () { +import Backbone from 'backbone'; - return Backbone.Collection.extend({ - url: function () { - return baseUrl + '/api/issues/changelog'; - }, - - parse: function (r) { - return r.changelog; - } - }); +export default Backbone.Collection.extend({ + url: function () { + return baseUrl + '/api/issues/changelog'; + }, + parse: function (r) { + return r.changelog; + } }); + + diff --git a/server/sonar-web/src/main/js/components/issue/models/issue.js b/server/sonar-web/src/main/js/components/issue/models/issue.js index 2e664aa7790..d543750ae5d 100644 --- a/server/sonar-web/src/main/js/components/issue/models/issue.js +++ b/server/sonar-web/src/main/js/components/issue/models/issue.js @@ -1,218 +1,219 @@ -define(function () { - - return Backbone.Model.extend({ - idAttribute: 'key', - - defaults: function () { - return { - flows: [] - }; - }, - - url: function () { - return baseUrl + '/api/issues'; - }, - - urlRoot: function () { - return baseUrl + '/api/issues'; - }, - - parse: function (r) { - var issue = _.size(r.issues) > 0 ? r.issues[0] : r.issue; - if (issue) { - issue = this._injectRelational(issue, r.components, 'component', 'key'); - issue = this._injectRelational(issue, r.components, 'project', 'key'); - issue = this._injectRelational(issue, r.components, 'subProject', 'key'); - issue = this._injectRelational(issue, r.rules, 'rule', 'key'); - issue = this._injectRelational(issue, r.users, 'assignee', 'login'); - issue = this._injectRelational(issue, r.users, 'reporter', 'login'); - issue = this._injectRelational(issue, r.actionPlans, 'actionPlan', 'key'); - issue = this._injectCommentsRelational(issue, r.users); - issue = this._prepareClosed(issue); - return issue; - } else { - return r; - } - }, - - _injectRelational: function (issue, source, baseField, lookupField) { - var baseValue = issue[baseField]; - if (baseValue != null && _.size(source)) { - var lookupValue = _.find(source, function (candidate) { - return candidate[lookupField] === baseValue; - }); - if (lookupValue != null) { - Object.keys(lookupValue).forEach(function (key) { - var newKey = baseField + key.charAt(0).toUpperCase() + key.slice(1); - issue[newKey] = lookupValue[key]; - }); - } - } - return issue; - }, - - _injectCommentsRelational: function (issue, users) { - if (issue.comments) { - var that = this; - var newComments = issue.comments.map(function (comment) { - var newComment = _.extend({}, comment, { author: comment.login }); - delete newComment.login; - newComment = that._injectRelational(newComment, users, 'author', 'login'); - return newComment; - }); - issue = _.extend({}, issue, { comments: newComments }); - } +import _ from 'underscore'; +import Backbone from 'backbone'; + +export default Backbone.Model.extend({ + idAttribute: 'key', + + defaults: function () { + return { + flows: [] + }; + }, + + url: function () { + return baseUrl + '/api/issues'; + }, + + urlRoot: function () { + return baseUrl + '/api/issues'; + }, + + parse: function (r) { + var issue = _.size(r.issues) > 0 ? r.issues[0] : r.issue; + if (issue) { + issue = this._injectRelational(issue, r.components, 'component', 'key'); + issue = this._injectRelational(issue, r.components, 'project', 'key'); + issue = this._injectRelational(issue, r.components, 'subProject', 'key'); + issue = this._injectRelational(issue, r.rules, 'rule', 'key'); + issue = this._injectRelational(issue, r.users, 'assignee', 'login'); + issue = this._injectRelational(issue, r.users, 'reporter', 'login'); + issue = this._injectRelational(issue, r.actionPlans, 'actionPlan', 'key'); + issue = this._injectCommentsRelational(issue, r.users); + issue = this._prepareClosed(issue); return issue; - }, + } else { + return r; + } + }, - _prepareClosed: function (issue) { - if (issue.status === 'CLOSED') { - issue.flows = []; - delete issue.textRange; - } - return issue; - }, - - sync: function (method, model, options) { - var opts = options || {}; - opts.contentType = 'application/x-www-form-urlencoded'; - if (method === 'read') { - _.extend(opts, { - type: 'GET', - url: this.urlRoot() + '/search', - data: { - issues: model.id, - additionalFields: '_all' - } - }); - } - if (method === 'create') { - _.extend(opts, { - type: 'POST', - url: this.urlRoot() + '/create', - data: { - component: model.get('component'), - line: model.get('line'), - message: model.get('message'), - rule: model.get('rule'), - severity: model.get('severity') - } + _injectRelational: function (issue, source, baseField, lookupField) { + var baseValue = issue[baseField]; + if (baseValue != null && _.size(source)) { + var lookupValue = _.find(source, function (candidate) { + return candidate[lookupField] === baseValue; + }); + if (lookupValue != null) { + Object.keys(lookupValue).forEach(function (key) { + var newKey = baseField + key.charAt(0).toUpperCase() + key.slice(1); + issue[newKey] = lookupValue[key]; }); } - var xhr = options.xhr = Backbone.ajax(opts); - model.trigger('request', model, xhr, opts); - return xhr; - }, - - /** - * Reset issue attributes (delete old, replace with new) - * @param attrs - * @param options - * @returns {Object} - */ - reset: function (attrs, options) { - for (var key in this.attributes) { - if (this.attributes.hasOwnProperty(key) && !(key in attrs)) { - attrs[key] = void 0; - } - } - return this.set(attrs, options); - }, - - /** - * Do an action over an issue - * @param {Object|null} options Options for jQuery ajax - * @returns {jqXHR} - * @private - */ - _action: function (options) { - var model = this; - var success = function (r) { - var attrs = model.parse(r); - model.reset(attrs); - if (options.success) { - options.success(model, r, options); - } - }; - var opts = _.extend({ type: 'POST' }, options, { success: success }); - var xhr = options.xhr = Backbone.ajax(opts); - model.trigger('request', model, xhr, opts); - return xhr; - }, - - /** - * Assign issue - * @param {String|null} assignee Assignee, can be null to unassign issue - * @param {Object|null} options Options for jQuery ajax - * @returns {jqXHR} - */ - assign: function (assignee, options) { - var opts = _.extend({ - url: this.urlRoot() + '/assign', - data: { issue: this.id, assignee: assignee } - }, options); - return this._action(opts); - }, - - /** - * Plan issue - * @param {String|null} plan Action Plan, can be null to unplan issue - * @param {Object|null} options Options for jQuery ajax - * @returns {jqXHR} - */ - plan: function (plan, options) { - var opts = _.extend({ - url: this.urlRoot() + '/plan', - data: { issue: this.id, plan: plan } - }, options); - return this._action(opts); - }, - - /** - * Set severity of issue - * @param {String|null} severity Severity - * @param {Object|null} options Options for jQuery ajax - * @returns {jqXHR} - */ - setSeverity: function (severity, options) { - var opts = _.extend({ - url: this.urlRoot() + '/set_severity', - data: { issue: this.id, severity: severity } - }, options); - return this._action(opts); - }, - - /** - * Do transition on issue - * @param {String|null} transition Transition - * @param {Object|null} options Options for jQuery ajax - * @returns {jqXHR} - */ - transition: function (transition, options) { + } + return issue; + }, + + _injectCommentsRelational: function (issue, users) { + if (issue.comments) { var that = this; - var opts = _.extend({ - url: this.urlRoot() + '/do_transition', - data: { issue: this.id, transition: transition } - }, options); - return this._action(opts).done(function () { - that.trigger('transition', transition); + var newComments = issue.comments.map(function (comment) { + var newComment = _.extend({}, comment, { author: comment.login }); + delete newComment.login; + newComment = that._injectRelational(newComment, users, 'author', 'login'); + return newComment; }); - }, + issue = _.extend({}, issue, { comments: newComments }); + } + return issue; + }, - getLinearLocations: function () { - var textRange = this.get('textRange'); - if (!textRange) { - return []; + _prepareClosed: function (issue) { + if (issue.status === 'CLOSED') { + issue.flows = []; + delete issue.textRange; + } + return issue; + }, + + sync: function (method, model, options) { + var opts = options || {}; + opts.contentType = 'application/x-www-form-urlencoded'; + if (method === 'read') { + _.extend(opts, { + type: 'GET', + url: this.urlRoot() + '/search', + data: { + issues: model.id, + additionalFields: '_all' + } + }); + } + if (method === 'create') { + _.extend(opts, { + type: 'POST', + url: this.urlRoot() + '/create', + data: { + component: model.get('component'), + line: model.get('line'), + message: model.get('message'), + rule: model.get('rule'), + severity: model.get('severity') + } + }); + } + var xhr = options.xhr = Backbone.ajax(opts); + model.trigger('request', model, xhr, opts); + return xhr; + }, + + /** + * Reset issue attributes (delete old, replace with new) + * @param attrs + * @param options + * @returns {Object} + */ + reset: function (attrs, options) { + for (var key in this.attributes) { + if (this.attributes.hasOwnProperty(key) && !(key in attrs)) { + attrs[key] = void 0; } - var locations = []; - for (var line = textRange.startLine; line <= textRange.endLine; line++) { - // TODO fix 999999 - var from = line === textRange.startLine ? textRange.startOffset : 0, - to = line === textRange.endLine ? textRange.endOffset : 999999; - locations.push({ line: line, from: from, to: to }); + } + return this.set(attrs, options); + }, + + /** + * Do an action over an issue + * @param {Object|null} options Options for jQuery ajax + * @returns {jqXHR} + * @private + */ + _action: function (options) { + var model = this; + var success = function (r) { + var attrs = model.parse(r); + model.reset(attrs); + if (options.success) { + options.success(model, r, options); } - return locations; + }; + var opts = _.extend({ type: 'POST' }, options, { success: success }); + var xhr = options.xhr = Backbone.ajax(opts); + model.trigger('request', model, xhr, opts); + return xhr; + }, + + /** + * Assign issue + * @param {String|null} assignee Assignee, can be null to unassign issue + * @param {Object|null} options Options for jQuery ajax + * @returns {jqXHR} + */ + assign: function (assignee, options) { + var opts = _.extend({ + url: this.urlRoot() + '/assign', + data: { issue: this.id, assignee: assignee } + }, options); + return this._action(opts); + }, + + /** + * Plan issue + * @param {String|null} plan Action Plan, can be null to unplan issue + * @param {Object|null} options Options for jQuery ajax + * @returns {jqXHR} + */ + plan: function (plan, options) { + var opts = _.extend({ + url: this.urlRoot() + '/plan', + data: { issue: this.id, plan: plan } + }, options); + return this._action(opts); + }, + + /** + * Set severity of issue + * @param {String|null} severity Severity + * @param {Object|null} options Options for jQuery ajax + * @returns {jqXHR} + */ + setSeverity: function (severity, options) { + var opts = _.extend({ + url: this.urlRoot() + '/set_severity', + data: { issue: this.id, severity: severity } + }, options); + return this._action(opts); + }, + + /** + * Do transition on issue + * @param {String|null} transition Transition + * @param {Object|null} options Options for jQuery ajax + * @returns {jqXHR} + */ + transition: function (transition, options) { + var that = this; + var opts = _.extend({ + url: this.urlRoot() + '/do_transition', + data: { issue: this.id, transition: transition } + }, options); + return this._action(opts).done(function () { + that.trigger('transition', transition); + }); + }, + + getLinearLocations: function () { + var textRange = this.get('textRange'); + if (!textRange) { + return []; } - }); - + var locations = []; + for (var line = textRange.startLine; line <= textRange.endLine; line++) { + // TODO fix 999999 + var from = line === textRange.startLine ? textRange.startOffset : 0, + to = line === textRange.endLine ? textRange.endOffset : 999999; + locations.push({ line: line, from: from, to: to }); + } + return locations; + } }); + + diff --git a/server/sonar-web/src/main/js/components/issue/views/assign-form-view.js b/server/sonar-web/src/main/js/components/issue/views/assign-form-view.js index c4cd0e5b0f9..b99d8ab8e90 100644 --- a/server/sonar-web/src/main/js/components/issue/views/assign-form-view.js +++ b/server/sonar-web/src/main/js/components/issue/views/assign-form-view.js @@ -1,143 +1,141 @@ -define([ - 'components/common/action-options-view', - '../templates' -], function (ActionOptionsView) { - - var $ = jQuery; - - return ActionOptionsView.extend({ - template: Templates['issue-assign-form'], - optionTemplate: Templates['issue-assign-form-option'], - - events: function () { - return _.extend(ActionOptionsView.prototype.events.apply(this, arguments), { - 'click input': 'onInputClick', - 'keydown input': 'onInputKeydown', - 'keyup input': 'onInputKeyup' - }); - }, +import $ from 'jquery'; +import _ from 'underscore'; +import ActionOptionsView from 'components/common/action-options-view'; +import '../templates'; + +export default ActionOptionsView.extend({ + template: Templates['issue-assign-form'], + optionTemplate: Templates['issue-assign-form-option'], + + events: function () { + return _.extend(ActionOptionsView.prototype.events.apply(this, arguments), { + 'click input': 'onInputClick', + 'keydown input': 'onInputKeydown', + 'keyup input': 'onInputKeyup' + }); + }, + + initialize: function () { + this._super(); + this.assignees = null; + this.debouncedSearch = _.debounce(this.search, 250); + }, + + getAssignee: function () { + return this.model.get('assignee'); + }, + + getAssigneeName: function () { + return this.model.get('assigneeName'); + }, + + onRender: function () { + var that = this; + this._super(); + this.renderTags(); + setTimeout(function () { + that.$('input').focus(); + }, 100); + }, + + renderTags: function () { + this.$('.menu').empty(); + this.getAssignees().forEach(this.renderAssignee, this); + this.bindUIElements(); + this.selectInitialOption(); + }, + + renderAssignee: function (assignee) { + var html = this.optionTemplate(assignee); + this.$('.menu').append(html); + }, + + selectOption: function (e) { + var assignee = $(e.currentTarget).data('value'), + assigneeName = $(e.currentTarget).data('text'); + this.submit(assignee, assigneeName); + return this._super(e); + }, + + submit: function (assignee) { + return this.model.assign(assignee); + }, + + onInputClick: function (e) { + e.stopPropagation(); + }, + + onInputKeydown: function (e) { + this.query = this.$('input').val(); + if (e.keyCode === 38) { + this.selectPreviousOption(); + } + if (e.keyCode === 40) { + this.selectNextOption(); + } + if (e.keyCode === 13) { + this.selectActiveOption(); + } + if (e.keyCode === 27) { + this.destroy(); + } + if ([9, 13, 27, 38, 40].indexOf(e.keyCode) !== -1) { + return false; + } + }, - initialize: function () { - this._super(); - this.assignees = null; - this.debouncedSearch = _.debounce(this.search, 250); - }, - - getAssignee: function () { - return this.model.get('assignee'); - }, - - getAssigneeName: function () { - return this.model.get('assigneeName'); - }, - - onRender: function () { - var that = this; - this._super(); - this.renderTags(); - setTimeout(function () { - that.$('input').focus(); - }, 100); - }, - - renderTags: function () { - this.$('.menu').empty(); - this.getAssignees().forEach(this.renderAssignee, this); - this.bindUIElements(); - this.selectInitialOption(); - }, - - renderAssignee: function (assignee) { - var html = this.optionTemplate(assignee); - this.$('.menu').append(html); - }, - - selectOption: function (e) { - var assignee = $(e.currentTarget).data('value'), - assigneeName = $(e.currentTarget).data('text'); - this.submit(assignee, assigneeName); - return this._super(e); - }, - - submit: function (assignee) { - return this.model.assign(assignee); - }, - - onInputClick: function (e) { - e.stopPropagation(); - }, - - onInputKeydown: function (e) { - this.query = this.$('input').val(); - if (e.keyCode === 38) { - this.selectPreviousOption(); - } - if (e.keyCode === 40) { - this.selectNextOption(); - } - if (e.keyCode === 13) { - this.selectActiveOption(); - } - if (e.keyCode === 27) { - this.destroy(); - } - if ([9, 13, 27, 38, 40].indexOf(e.keyCode) !== -1) { - return false; - } - }, - - onInputKeyup: function () { - var query = this.$('input').val(); - if (query !== this.query) { - if (query.length < 2) { - query = ''; - } - this.query = query; - this.debouncedSearch(query); + onInputKeyup: function () { + var query = this.$('input').val(); + if (query !== this.query) { + if (query.length < 2) { + query = ''; } - }, - - search: function (query) { - var that = this; - if (query.length > 1) { - $.get(baseUrl + '/api/users/search', { q: query }).done(function (data) { - that.resetAssignees(data.users); - }); - } else { - this.resetAssignees(); - } - }, - - resetAssignees: function (users) { - if (users) { - this.assignees = users.map(function (user) { - return { id: user.login, text: user.name }; - }); - } else { - this.assignees = null; - } - this.renderTags(); - }, + this.query = query; + this.debouncedSearch(query); + } + }, - getAssignees: function () { - if (this.assignees) { - return this.assignees; - } - var assignees = [{ id: '', text: t('unassigned') }], - currentUser = window.SS.user, - currentUserName = window.SS.userName; - assignees.push({ id: currentUser, text: currentUserName }); - if (this.getAssignee()) { - assignees.push({ id: this.getAssignee(), text: this.getAssigneeName() }); - } - return this.makeUnique(assignees); - }, + search: function (query) { + var that = this; + if (query.length > 1) { + $.get(baseUrl + '/api/users/search', { q: query }).done(function (data) { + that.resetAssignees(data.users); + }); + } else { + this.resetAssignees(); + } + }, - makeUnique: function (assignees) { - return _.uniq(assignees, false, function (assignee) { - return assignee.id; + resetAssignees: function (users) { + if (users) { + this.assignees = users.map(function (user) { + return { id: user.login, text: user.name }; }); + } else { + this.assignees = null; } - }); + this.renderTags(); + }, + getAssignees: function () { + if (this.assignees) { + return this.assignees; + } + var assignees = [{ id: '', text: t('unassigned') }], + currentUser = window.SS.user, + currentUserName = window.SS.userName; + assignees.push({ id: currentUser, text: currentUserName }); + if (this.getAssignee()) { + assignees.push({ id: this.getAssignee(), text: this.getAssigneeName() }); + } + return this.makeUnique(assignees); + }, + + makeUnique: function (assignees) { + return _.uniq(assignees, false, function (assignee) { + return assignee.id; + }); + } }); + + diff --git a/server/sonar-web/src/main/js/components/issue/views/changelog-view.js b/server/sonar-web/src/main/js/components/issue/views/changelog-view.js index b834d90054c..f7c51f88a7f 100644 --- a/server/sonar-web/src/main/js/components/issue/views/changelog-view.js +++ b/server/sonar-web/src/main/js/components/issue/views/changelog-view.js @@ -1,20 +1,19 @@ -define([ - 'components/common/popup', - '../templates' -], function (PopupView) { +import _ from 'underscore'; +import PopupView from 'components/common/popup'; +import '../templates'; - return PopupView.extend({ - template: Templates['issue-changelog'], +export default PopupView.extend({ + template: Templates['issue-changelog'], - collectionEvents: { - 'sync': 'render' - }, - - serializeData: function () { - return _.extend(PopupView.prototype.serializeData.apply(this, arguments), { - issue: this.options.issue.toJSON() - }); - } - }); + collectionEvents: { + 'sync': 'render' + }, + serializeData: function () { + return _.extend(PopupView.prototype.serializeData.apply(this, arguments), { + issue: this.options.issue.toJSON() + }); + } }); + + diff --git a/server/sonar-web/src/main/js/components/issue/views/comment-form-view.js b/server/sonar-web/src/main/js/components/issue/views/comment-form-view.js index ef07d6e717b..ee2f1c91e87 100644 --- a/server/sonar-web/src/main/js/components/issue/views/comment-form-view.js +++ b/server/sonar-web/src/main/js/components/issue/views/comment-form-view.js @@ -1,91 +1,89 @@ -define([ - 'components/common/popup', - '../templates' -], function (PopupView) { +import $ from 'jquery'; +import _ from 'underscore'; +import PopupView from 'components/common/popup'; +import '../templates'; - var $ = jQuery; +export default PopupView.extend({ + className: 'bubble-popup issue-comment-bubble-popup', + template: Templates['comment-form'], - return PopupView.extend({ - className: 'bubble-popup issue-comment-bubble-popup', - template: Templates['comment-form'], + ui: { + textarea: '.issue-comment-form-text textarea', + cancelButton: '.js-issue-comment-cancel', + submitButton: '.js-issue-comment-submit' + }, - ui: { - textarea: '.issue-comment-form-text textarea', - cancelButton: '.js-issue-comment-cancel', - submitButton: '.js-issue-comment-submit' - }, + events: { + 'click': 'onClick', + 'keydown @ui.textarea': 'onKeydown', + 'keyup @ui.textarea': 'toggleSubmit', + 'click @ui.cancelButton': 'cancel', + 'click @ui.submitButton': 'submit' + }, - events: { - 'click': 'onClick', - 'keydown @ui.textarea': 'onKeydown', - 'keyup @ui.textarea': 'toggleSubmit', - 'click @ui.cancelButton': 'cancel', - 'click @ui.submitButton': 'submit' - }, + onRender: function () { + var that = this; + PopupView.prototype.onRender.apply(this, arguments); + setTimeout(function () { + that.ui.textarea.focus(); + }, 100); + }, - onRender: function () { - var that = this; - PopupView.prototype.onRender.apply(this, arguments); - setTimeout(function () { - that.ui.textarea.focus(); - }, 100); - }, + toggleSubmit: function () { + this.ui.submitButton.prop('disabled', this.ui.textarea.val().length === 0); + }, - toggleSubmit: function () { - this.ui.submitButton.prop('disabled', this.ui.textarea.val().length === 0); - }, + onClick: function (e) { + e.stopPropagation(); + }, - onClick: function (e) { - e.stopPropagation(); - }, - - onKeydown: function (e) { - if (e.keyCode === 27) { - this.destroy(); - } - }, - - cancel: function () { - this.options.detailView.updateAfterAction(false); - }, + onKeydown: function (e) { + if (e.keyCode === 27) { + this.destroy(); + } + }, - disableForm: function () { - this.$(':input').prop('disabled', true); - }, + cancel: function () { + this.options.detailView.updateAfterAction(false); + }, - enableForm: function () { - this.$(':input').prop('disabled', false); - }, + disableForm: function () { + this.$(':input').prop('disabled', true); + }, - submit: function () { - var that = this; - var text = this.ui.textarea.val(), - update = this.model && this.model.has('key'), - method = update ? 'edit_comment' : 'add_comment', - url = baseUrl + '/api/issues/' + method, - data = { text: text }; - if (update) { - data.key = this.model.get('key'); - } else { - data.issue = this.options.issue.id; - } - this.disableForm(); - this.options.detailView.disableControls(); - return $.post(url, data) - .done(function () { - that.options.detailView.updateAfterAction(true); - }).fail(function () { - that.enableForm(); - that.options.detailView.enableControls(); - }); - }, + enableForm: function () { + this.$(':input').prop('disabled', false); + }, - serializeData: function () { - var options = _.defaults(this.options.additionalOptions, { fromTransition: false }); - return _.extend(PopupView.prototype.serializeData.apply(this, arguments), { - options: options - }); + submit: function () { + var that = this; + var text = this.ui.textarea.val(), + update = this.model && this.model.has('key'), + method = update ? 'edit_comment' : 'add_comment', + url = baseUrl + '/api/issues/' + method, + data = { text: text }; + if (update) { + data.key = this.model.get('key'); + } else { + data.issue = this.options.issue.id; } - }); + this.disableForm(); + this.options.detailView.disableControls(); + return $.post(url, data) + .done(function () { + that.options.detailView.updateAfterAction(true); + }).fail(function () { + that.enableForm(); + that.options.detailView.enableControls(); + }); + }, + serializeData: function () { + var options = _.defaults(this.options.additionalOptions, { fromTransition: false }); + return _.extend(PopupView.prototype.serializeData.apply(this, arguments), { + options: options + }); + } }); + + diff --git a/server/sonar-web/src/main/js/components/issue/views/issue-popup.js b/server/sonar-web/src/main/js/components/issue/views/issue-popup.js index 9c36ad104b5..e8160c8ef66 100644 --- a/server/sonar-web/src/main/js/components/issue/views/issue-popup.js +++ b/server/sonar-web/src/main/js/components/issue/views/issue-popup.js @@ -1,33 +1,31 @@ -define([ - 'components/common/popup' -], function (PopupView) { +import PopupView from 'components/common/popup'; - return PopupView.extend({ - className: 'bubble-popup issue-bubble-popup', +export default PopupView.extend({ + className: 'bubble-popup issue-bubble-popup', - template: function () { - return '<div class="bubble-popup-arrow"></div>'; - }, + template: function () { + return '<div class="bubble-popup-arrow"></div>'; + }, - events: function () { - return { - 'click .js-issue-form-cancel': 'destroy' - }; - }, + events: function () { + return { + 'click .js-issue-form-cancel': 'destroy' + }; + }, - onRender: function () { - PopupView.prototype.onRender.apply(this, arguments); - this.options.view.$el.appendTo(this.$el); - this.options.view.render(); - }, + onRender: function () { + PopupView.prototype.onRender.apply(this, arguments); + this.options.view.$el.appendTo(this.$el); + this.options.view.render(); + }, - onDestroy: function () { - this.options.view.destroy(); - }, + onDestroy: function () { + this.options.view.destroy(); + }, - attachCloseEvents: function () { - - } - }); + attachCloseEvents: function () { + } }); + + diff --git a/server/sonar-web/src/main/js/components/issue/views/more-actions-view.js b/server/sonar-web/src/main/js/components/issue/views/more-actions-view.js index 5b1c85e53b8..4fa157c1533 100644 --- a/server/sonar-web/src/main/js/components/issue/views/more-actions-view.js +++ b/server/sonar-web/src/main/js/components/issue/views/more-actions-view.js @@ -1,23 +1,20 @@ -define([ - 'components/common/popup', - '../templates' -], function (PopupView) { +import $ from 'jquery'; +import PopupView from 'components/common/popup'; +import '../templates'; - var $ = jQuery; +export default PopupView.extend({ + template: Templates['issue-more-actions'], - return PopupView.extend({ - template: Templates['issue-more-actions'], + events: function () { + return { + 'click .js-issue-action': 'action' + }; + }, - events: function () { - return { - 'click .js-issue-action': 'action' - }; - }, + action: function (e) { + var actionKey = $(e.currentTarget).data('action'); + return this.options.detailView.action(actionKey); + } +}); - action: function (e) { - var actionKey = $(e.currentTarget).data('action'); - return this.options.detailView.action(actionKey); - } - }); -}); diff --git a/server/sonar-web/src/main/js/components/issue/views/plan-form-view.js b/server/sonar-web/src/main/js/components/issue/views/plan-form-view.js index 4c459a0a60d..a0459ed7765 100644 --- a/server/sonar-web/src/main/js/components/issue/views/plan-form-view.js +++ b/server/sonar-web/src/main/js/components/issue/views/plan-form-view.js @@ -1,45 +1,39 @@ -define([ - 'components/common/action-options-view', - '../templates' -], function (ActionOptionsView) { - - var $ = jQuery; - - return ActionOptionsView.extend({ - template: Templates['issue-plan-form'], - - getActionPlan: function () { - return this.model.get('actionPlan') || ''; - }, - - getActionPlanName: function () { - return this.model.get('actionPlanName'); - }, - - selectInitialOption: function () { - this.makeActive(this.getOptions().filter('[data-value="' + this.getActionPlan() + '"]')); - }, - - selectOption: function (e) { - var actionPlan = $(e.currentTarget).data('value'), - actionPlanName = $(e.currentTarget).data('text'); - this.submit(actionPlan, actionPlanName); - return ActionOptionsView.prototype.selectOption.apply(this, arguments); - }, - - submit: function (actionPlan) { - return this.model.plan(actionPlan); - }, - - getActionPlans: function () { - return [{ key: '', name: t('issue.unplanned') }].concat(this.collection.toJSON()); - }, - - serializeData: function () { - return _.extend(ActionOptionsView.prototype.serializeData.apply(this, arguments), { - items: this.getActionPlans() - }); - } - }); - +import $ from 'jquery'; +import _ from 'underscore'; +import ActionOptionsView from 'components/common/action-options-view'; +import '../templates'; + +export default ActionOptionsView.extend({ + template: Templates['issue-plan-form'], + + getActionPlan: function () { + return this.model.get('actionPlan') || ''; + }, + + selectInitialOption: function () { + this.makeActive(this.getOptions().filter('[data-value="' + this.getActionPlan() + '"]')); + }, + + selectOption: function (e) { + var actionPlan = $(e.currentTarget).data('value'), + actionPlanName = $(e.currentTarget).data('text'); + this.submit(actionPlan, actionPlanName); + return ActionOptionsView.prototype.selectOption.apply(this, arguments); + }, + + submit: function (actionPlan) { + return this.model.plan(actionPlan); + }, + + getActionPlans: function () { + return [{ key: '', name: t('issue.unplanned') }].concat(this.collection.toJSON()); + }, + + serializeData: function () { + return _.extend(ActionOptionsView.prototype.serializeData.apply(this, arguments), { + items: this.getActionPlans() + }); + } }); + + diff --git a/server/sonar-web/src/main/js/components/issue/views/set-severity-form-view.js b/server/sonar-web/src/main/js/components/issue/views/set-severity-form-view.js index eef98aa9d70..50fd125f0d2 100644 --- a/server/sonar-web/src/main/js/components/issue/views/set-severity-form-view.js +++ b/server/sonar-web/src/main/js/components/issue/views/set-severity-form-view.js @@ -1,36 +1,34 @@ -define([ - 'components/common/action-options-view', - '../templates' -], function (ActionOptionsView) { - - var $ = jQuery; - - return ActionOptionsView.extend({ - template: Templates['issue-set-severity-form'], - - getTransition: function () { - return this.model.get('severity'); - }, - - selectInitialOption: function () { - return this.makeActive(this.getOptions().filter('[data-value="' + this.getTransition() + '"]')); - }, - - selectOption: function (e) { - var severity = $(e.currentTarget).data('value'); - this.submit(severity); - return ActionOptionsView.prototype.selectOption.apply(this, arguments); - }, - - submit: function (severity) { - return this.model.setSeverity(severity); - }, +import $ from 'jquery'; +import _ from 'underscore'; +import ActionOptionsView from 'components/common/action-options-view'; +import '../templates'; + +export default ActionOptionsView.extend({ + template: Templates['issue-set-severity-form'], + + getTransition: function () { + return this.model.get('severity'); + }, + + selectInitialOption: function () { + return this.makeActive(this.getOptions().filter('[data-value="' + this.getTransition() + '"]')); + }, + + selectOption: function (e) { + var severity = $(e.currentTarget).data('value'); + this.submit(severity); + return ActionOptionsView.prototype.selectOption.apply(this, arguments); + }, + + submit: function (severity) { + return this.model.setSeverity(severity); + }, + + serializeData: function () { + return _.extend(ActionOptionsView.prototype.serializeData.apply(this, arguments), { + items: ['BLOCKER', 'CRITICAL', 'MAJOR', 'MINOR', 'INFO'] + }); + } +}); - serializeData: function () { - return _.extend(ActionOptionsView.prototype.serializeData.apply(this, arguments), { - items: ['BLOCKER', 'CRITICAL', 'MAJOR', 'MINOR', 'INFO'] - }); - } - }); -}); diff --git a/server/sonar-web/src/main/js/components/issue/views/tags-form-view.js b/server/sonar-web/src/main/js/components/issue/views/tags-form-view.js index 6aa05af0998..9a3716841e0 100644 --- a/server/sonar-web/src/main/js/components/issue/views/tags-form-view.js +++ b/server/sonar-web/src/main/js/components/issue/views/tags-form-view.js @@ -1,177 +1,175 @@ -define([ - 'components/common/action-options-view', - '../templates' -], function (ActionOptionsView) { - - var $ = jQuery; - - return ActionOptionsView.extend({ - template: Templates['issue-tags-form'], - optionTemplate: Templates['issue-tags-form-option'], - - modelEvents: { - 'change:tags': 'renderTags' - }, - - events: function () { - return _.extend(ActionOptionsView.prototype.events.apply(this, arguments), { - 'click input': 'onInputClick', - 'keydown input': 'onInputKeydown', - 'keyup input': 'onInputKeyup' - }); - }, - - initialize: function () { - ActionOptionsView.prototype.initialize.apply(this, arguments); - this.query = ''; - this.tags = []; - this.selected = 0; - this.debouncedSearch = _.debounce(this.search, 250); - this.requestTags(); - }, - - requestTags: function (query) { - var that = this; - return $.get(baseUrl + '/api/issues/tags', { ps: 10, q: query }).done(function (data) { - that.tags = data.tags; - that.renderTags(); - }); - }, - - onRender: function () { - var that = this; - ActionOptionsView.prototype.onRender.apply(this, arguments); - this.renderTags(); - setTimeout(function () { - that.$('input').focus(); - }, 100); - }, - - selectInitialOption: function () { - this.selected = Math.max(Math.min(this.selected, this.getOptions().length - 1), 0); - this.makeActive(this.getOptions().eq(this.selected)); - }, - - filterTags: function (tags) { - var that = this; - return _.filter(tags, function (tag) { - return tag.indexOf(that.query) !== -1; - }); - }, - - renderTags: function () { - this.$('.menu').empty(); - this.filterTags(this.getTags()).forEach(this.renderSelectedTag, this); - this.filterTags(_.difference(this.tags, this.getTags())).forEach(this.renderTag, this); - if (this.query.length > 0 && this.tags.indexOf(this.query) === -1 && this.getTags().indexOf(this.query) === -1) { - this.renderCustomTag(this.query); - } - this.selectInitialOption(); - }, - - renderSelectedTag: function (tag) { - var html = this.optionTemplate({ - tag: tag, - selected: true, - custom: false - }); - return this.$('.menu').append(html); - }, - - renderTag: function (tag) { - var html = this.optionTemplate({ - tag: tag, - selected: false, - custom: false - }); - return this.$('.menu').append(html); - }, - - renderCustomTag: function (tag) { - var html = this.optionTemplate({ - tag: tag, - selected: false, - custom: true - }); - return this.$('.menu').append(html); - }, - - selectOption: function (e) { - e.preventDefault(); - e.stopPropagation(); - var tags = this.getTags().slice(), - tag = $(e.currentTarget).data('value'); - if ($(e.currentTarget).data('selected') != null) { - tags = _.without(tags, tag); - } else { - tags.push(tag); - } - this.selected = this.getOptions().index($(e.currentTarget)); - return this.submit(tags); - }, - - submit: function (tags) { - var that = this; - var _tags = this.getTags(); - this.model.set({ tags: tags }); - return $.ajax({ - type: 'POST', - url: baseUrl + '/api/issues/set_tags', - data: { - key: this.model.id, - tags: tags.join() - } - }).fail(function () { - return that.model.set({ tags: _tags }); - }); - }, - - onInputClick: function (e) { - e.stopPropagation(); - }, - - onInputKeydown: function (e) { - this.query = this.$('input').val(); - if (e.keyCode === 38) { - this.selectPreviousOption(); - } - if (e.keyCode === 40) { - this.selectNextOption(); - } - if (e.keyCode === 13) { - this.selectActiveOption(); - } - if (e.keyCode === 27) { - this.destroy(); - } - if ([9, 13, 27, 38, 40].indexOf(e.keyCode) !== -1) { - return false; - } - }, - - onInputKeyup: function () { - var query = this.$('input').val(); - if (query !== this.query) { - this.query = query; - this.debouncedSearch(query); +import $ from 'jquery'; +import _ from 'underscore'; +import ActionOptionsView from 'components/common/action-options-view'; +import '../templates'; + +export default ActionOptionsView.extend({ + template: Templates['issue-tags-form'], + optionTemplate: Templates['issue-tags-form-option'], + + modelEvents: { + 'change:tags': 'renderTags' + }, + + events: function () { + return _.extend(ActionOptionsView.prototype.events.apply(this, arguments), { + 'click input': 'onInputClick', + 'keydown input': 'onInputKeydown', + 'keyup input': 'onInputKeyup' + }); + }, + + initialize: function () { + ActionOptionsView.prototype.initialize.apply(this, arguments); + this.query = ''; + this.tags = []; + this.selected = 0; + this.debouncedSearch = _.debounce(this.search, 250); + this.requestTags(); + }, + + requestTags: function (query) { + var that = this; + return $.get(baseUrl + '/api/issues/tags', { ps: 10, q: query }).done(function (data) { + that.tags = data.tags; + that.renderTags(); + }); + }, + + onRender: function () { + var that = this; + ActionOptionsView.prototype.onRender.apply(this, arguments); + this.renderTags(); + setTimeout(function () { + that.$('input').focus(); + }, 100); + }, + + selectInitialOption: function () { + this.selected = Math.max(Math.min(this.selected, this.getOptions().length - 1), 0); + this.makeActive(this.getOptions().eq(this.selected)); + }, + + filterTags: function (tags) { + var that = this; + return _.filter(tags, function (tag) { + return tag.indexOf(that.query) !== -1; + }); + }, + + renderTags: function () { + this.$('.menu').empty(); + this.filterTags(this.getTags()).forEach(this.renderSelectedTag, this); + this.filterTags(_.difference(this.tags, this.getTags())).forEach(this.renderTag, this); + if (this.query.length > 0 && this.tags.indexOf(this.query) === -1 && this.getTags().indexOf(this.query) === -1) { + this.renderCustomTag(this.query); + } + this.selectInitialOption(); + }, + + renderSelectedTag: function (tag) { + var html = this.optionTemplate({ + tag: tag, + selected: true, + custom: false + }); + return this.$('.menu').append(html); + }, + + renderTag: function (tag) { + var html = this.optionTemplate({ + tag: tag, + selected: false, + custom: false + }); + return this.$('.menu').append(html); + }, + + renderCustomTag: function (tag) { + var html = this.optionTemplate({ + tag: tag, + selected: false, + custom: true + }); + return this.$('.menu').append(html); + }, + + selectOption: function (e) { + e.preventDefault(); + e.stopPropagation(); + var tags = this.getTags().slice(), + tag = $(e.currentTarget).data('value'); + if ($(e.currentTarget).data('selected') != null) { + tags = _.without(tags, tag); + } else { + tags.push(tag); + } + this.selected = this.getOptions().index($(e.currentTarget)); + return this.submit(tags); + }, + + submit: function (tags) { + var that = this; + var _tags = this.getTags(); + this.model.set({ tags: tags }); + return $.ajax({ + type: 'POST', + url: baseUrl + '/api/issues/set_tags', + data: { + key: this.model.id, + tags: tags.join() } - }, + }).fail(function () { + return that.model.set({ tags: _tags }); + }); + }, + + onInputClick: function (e) { + e.stopPropagation(); + }, + + onInputKeydown: function (e) { + this.query = this.$('input').val(); + if (e.keyCode === 38) { + this.selectPreviousOption(); + } + if (e.keyCode === 40) { + this.selectNextOption(); + } + if (e.keyCode === 13) { + this.selectActiveOption(); + } + if (e.keyCode === 27) { + this.destroy(); + } + if ([9, 13, 27, 38, 40].indexOf(e.keyCode) !== -1) { + return false; + } + }, - search: function (query) { + onInputKeyup: function () { + var query = this.$('input').val(); + if (query !== this.query) { this.query = query; - return this.requestTags(query); - }, - - resetAssignees: function (users) { - this.assignees = users.map(function (user) { - return { id: user.login, text: user.name }; - }); - this.renderTags(); - }, - - getTags: function () { - return this.model.get('tags') || []; + this.debouncedSearch(query); } - }); - + }, + + search: function (query) { + this.query = query; + return this.requestTags(query); + }, + + resetAssignees: function (users) { + this.assignees = users.map(function (user) { + return { id: user.login, text: user.name }; + }); + this.renderTags(); + }, + + getTags: function () { + return this.model.get('tags') || []; + } }); + + diff --git a/server/sonar-web/src/main/js/components/issue/views/transitions-form-view.js b/server/sonar-web/src/main/js/components/issue/views/transitions-form-view.js index 773db9fe2d0..80da2defc34 100644 --- a/server/sonar-web/src/main/js/components/issue/views/transitions-form-view.js +++ b/server/sonar-web/src/main/js/components/issue/views/transitions-form-view.js @@ -1,26 +1,23 @@ -define([ - 'components/common/action-options-view', - '../templates' -], function (ActionOptionsView) { +import $ from 'jquery'; +import ActionOptionsView from 'components/common/action-options-view'; +import '../templates'; - var $ = jQuery; +export default ActionOptionsView.extend({ + template: Templates['issue-transitions-form'], - return ActionOptionsView.extend({ - template: Templates['issue-transitions-form'], + selectInitialOption: function () { + this.makeActive(this.getOptions().first()); + }, - selectInitialOption: function () { - this.makeActive(this.getOptions().first()); - }, + selectOption: function (e) { + var transition = $(e.currentTarget).data('value'); + this.submit(transition); + return ActionOptionsView.prototype.selectOption.apply(this, arguments); + }, - selectOption: function (e) { - var transition = $(e.currentTarget).data('value'); - this.submit(transition); - return ActionOptionsView.prototype.selectOption.apply(this, arguments); - }, + submit: function (transition) { + return this.model.transition(transition); + } +}); - submit: function (transition) { - return this.model.transition(transition); - } - }); -}); diff --git a/server/sonar-web/src/main/js/components/navigator/controller.js b/server/sonar-web/src/main/js/components/navigator/controller.js index 89d8b6cc8d9..ebb80f73b31 100644 --- a/server/sonar-web/src/main/js/components/navigator/controller.js +++ b/server/sonar-web/src/main/js/components/navigator/controller.js @@ -1,137 +1,138 @@ -define(function () { - - return Marionette.Controller.extend({ - pageSize: 50, - - initialize: function (options) { - this.app = options.app; - this.listenTo(options.app.state, 'change:query', this.fetchList); - }, - - _allFacets: function () { - return this.options.app.state.get('allFacets').map(function (facet) { - return {property: facet}; - }); - }, - - _enabledFacets: function () { - var that = this, - facets = this.options.app.state.get('facets'), - criteria = Object.keys(this.options.app.state.get('query')); - facets = facets.concat(criteria); - facets = facets.map(function (facet) { - return that.options.app.state.get('transform')[facet] != null ? - that.options.app.state.get('transform')[facet] : facet; - }); - return facets.filter(function (facet) { - return that.options.app.state.get('allFacets').indexOf(facet) !== -1; - }); - }, - - _facetsFromServer: function () { - var that = this, - facets = this._enabledFacets(); - return facets.filter(function (facet) { - return that.options.app.state.get('facetsFromServer').indexOf(facet) !== -1; - }); - }, - - fetchList: function () { - - }, - - fetchNextPage: function () { - this.options.app.state.nextPage(); - return this.fetchList(false); - }, - - enableFacet: function (id) { - var facet = this.options.app.facets.get(id); - if (facet.has('values') || this.options.app.state.get('facetsFromServer').indexOf(id) === -1) { - facet.set({enabled: true}); - } else { - this.requestFacet(id) - .done(function () { - facet.set({enabled: true}); - }); - } - }, - - disableFacet: function (id) { - var facet = this.options.app.facets.get(id); - facet.set({enabled: false}); - this.options.app.facetsView.children.findByModel(facet).disable(); - }, - - toggleFacet: function (id) { - var facet = this.options.app.facets.get(id); - if (facet.get('enabled')) { - this.disableFacet(id); - } else { - this.enableFacet(id); - } - }, - - enableFacets: function (facets) { - facets.forEach(this.enableFacet, this); - }, - - newSearch: function () { - this.options.app.state.setQuery({}); - }, - - parseQuery: function (query, separator) { - separator = separator || '|'; - var q = {}; - (query || '').split(separator).forEach(function (t) { - var tokens = t.split('='); - if (tokens[0] && tokens[1] != null) { - q[tokens[0]] = decodeURIComponent(tokens[1]); - } - }); - return q; - }, - - getQuery: function (separator) { - separator = separator || '|'; - var filter = this.options.app.state.get('query'), - route = []; - _.map(filter, function (value, property) { - route.push('' + property + '=' + encodeURIComponent(value)); - }); - return route.join(separator); - }, - - getRoute: function (separator) { - separator = separator || '|'; - return this.getQuery(separator); - }, - - selectNext: function () { - var index = this.options.app.state.get('selectedIndex') + 1; - if (index < this.options.app.list.length) { - this.options.app.state.set({ selectedIndex: index }); - } else { - if (!this.options.app.state.get('maxResultsReached')) { - var that = this; - this.fetchNextPage().done(function () { - that.options.app.state.set({ selectedIndex: index }); +import _ from 'underscore'; +import Marionette from 'backbone.marionette'; + +export default Marionette.Controller.extend({ + pageSize: 50, + + initialize: function (options) { + this.app = options.app; + this.listenTo(options.app.state, 'change:query', this.fetchList); + }, + + _allFacets: function () { + return this.options.app.state.get('allFacets').map(function (facet) { + return { property: facet }; + }); + }, + + _enabledFacets: function () { + var that = this, + facets = this.options.app.state.get('facets'), + criteria = Object.keys(this.options.app.state.get('query')); + facets = facets.concat(criteria); + facets = facets.map(function (facet) { + return that.options.app.state.get('transform')[facet] != null ? + that.options.app.state.get('transform')[facet] : facet; + }); + return facets.filter(function (facet) { + return that.options.app.state.get('allFacets').indexOf(facet) !== -1; + }); + }, + + _facetsFromServer: function () { + var that = this, + facets = this._enabledFacets(); + return facets.filter(function (facet) { + return that.options.app.state.get('facetsFromServer').indexOf(facet) !== -1; + }); + }, + + fetchList: function () { + + }, + + fetchNextPage: function () { + this.options.app.state.nextPage(); + return this.fetchList(false); + }, + + enableFacet: function (id) { + var facet = this.options.app.facets.get(id); + if (facet.has('values') || this.options.app.state.get('facetsFromServer').indexOf(id) === -1) { + facet.set({ enabled: true }); + } else { + this.requestFacet(id) + .done(function () { + facet.set({ enabled: true }); }); - } else { - this.options.app.list.trigger('limitReached'); - } + } + }, + + disableFacet: function (id) { + var facet = this.options.app.facets.get(id); + facet.set({ enabled: false }); + this.options.app.facetsView.children.findByModel(facet).disable(); + }, + + toggleFacet: function (id) { + var facet = this.options.app.facets.get(id); + if (facet.get('enabled')) { + this.disableFacet(id); + } else { + this.enableFacet(id); + } + }, + + enableFacets: function (facets) { + facets.forEach(this.enableFacet, this); + }, + + newSearch: function () { + this.options.app.state.setQuery({}); + }, + + parseQuery: function (query, separator) { + separator = separator || '|'; + var q = {}; + (query || '').split(separator).forEach(function (t) { + var tokens = t.split('='); + if (tokens[0] && tokens[1] != null) { + q[tokens[0]] = decodeURIComponent(tokens[1]); } - }, - - selectPrev: function () { - var index = this.options.app.state.get('selectedIndex') - 1; - if (index >= 0) { - this.options.app.state.set({ selectedIndex: index }); + }); + return q; + }, + + getQuery: function (separator) { + separator = separator || '|'; + var filter = this.options.app.state.get('query'), + route = []; + _.map(filter, function (value, property) { + route.push('' + property + '=' + encodeURIComponent(value)); + }); + return route.join(separator); + }, + + getRoute: function (separator) { + separator = separator || '|'; + return this.getQuery(separator); + }, + + selectNext: function () { + var index = this.options.app.state.get('selectedIndex') + 1; + if (index < this.options.app.list.length) { + this.options.app.state.set({ selectedIndex: index }); + } else { + if (!this.options.app.state.get('maxResultsReached')) { + var that = this; + this.fetchNextPage().done(function () { + that.options.app.state.set({ selectedIndex: index }); + }); } else { this.options.app.list.trigger('limitReached'); } } - - }); + }, + + selectPrev: function () { + var index = this.options.app.state.get('selectedIndex') - 1; + if (index >= 0) { + this.options.app.state.set({ selectedIndex: index }); + } else { + this.options.app.list.trigger('limitReached'); + } + } }); + + diff --git a/server/sonar-web/src/main/js/components/navigator/facets-view.js b/server/sonar-web/src/main/js/components/navigator/facets-view.js index 1a668ec71e1..4471ca7de8b 100644 --- a/server/sonar-web/src/main/js/components/navigator/facets-view.js +++ b/server/sonar-web/src/main/js/components/navigator/facets-view.js @@ -1,36 +1,35 @@ -define([ - 'components/navigator/facets/base-facet' -], function (BaseFacet) { - - return Marionette.CollectionView.extend({ - className: 'search-navigator-facets-list', - - childViewOptions: function () { - return { - app: this.options.app - }; - }, - - getChildView: function () { - return BaseFacet; - }, - - collectionEvents: function () { - return { - 'change:enabled': 'updateState' - }; - }, - - updateState: function () { - var enabledFacets = this.collection.filter(function (model) { - return model.get('enabled'); - }), - enabledFacetIds = enabledFacets.map(function (model) { - return model.id; - }); - this.options.app.state.set({facets: enabledFacetIds}); - } - - }); +import Marionette from 'backbone.marionette'; +import BaseFacet from 'components/navigator/facets/base-facet'; + +export default Marionette.CollectionView.extend({ + className: 'search-navigator-facets-list', + + childViewOptions: function () { + return { + app: this.options.app + }; + }, + + getChildView: function () { + return BaseFacet; + }, + + collectionEvents: function () { + return { + 'change:enabled': 'updateState' + }; + }, + + updateState: function () { + var enabledFacets = this.collection.filter(function (model) { + return model.get('enabled'); + }), + enabledFacetIds = enabledFacets.map(function (model) { + return model.id; + }); + this.options.app.state.set({ facets: enabledFacetIds }); + } }); + + diff --git a/server/sonar-web/src/main/js/components/navigator/facets/base-facet.js b/server/sonar-web/src/main/js/components/navigator/facets/base-facet.js index 0d613f55456..4038ab088e1 100644 --- a/server/sonar-web/src/main/js/components/navigator/facets/base-facet.js +++ b/server/sonar-web/src/main/js/components/navigator/facets/base-facet.js @@ -1,102 +1,102 @@ -define(function () { +import $ from 'jquery'; +import _ from 'underscore'; +import Marionette from 'backbone.marionette'; - var $ = jQuery; +export default Marionette.ItemView.extend({ + className: 'search-navigator-facet-box', + forbiddenClassName: 'search-navigator-facet-box-forbidden', - return Marionette.ItemView.extend({ - className: 'search-navigator-facet-box', - forbiddenClassName: 'search-navigator-facet-box-forbidden', + modelEvents: function () { + return { + 'change': 'render' + }; + }, - modelEvents: function () { - return { - 'change': 'render' - }; - }, + events: function () { + return { + 'click .js-facet-toggle': 'toggle', + 'click .js-facet': 'toggleFacet' + }; + }, - events: function () { - return { - 'click .js-facet-toggle': 'toggle', - 'click .js-facet': 'toggleFacet' - }; - }, - - onRender: function () { - this.$el.toggleClass('search-navigator-facet-box-collapsed', !this.model.get('enabled')); - this.$el.attr('data-property', this.model.get('property')); - var that = this, - property = this.model.get('property'), - value = this.options.app.state.get('query')[property]; - if (typeof value === 'string') { - value.split(',').forEach(function (s) { - var facet = that.$('.js-facet').filter('[data-value="' + s + '"]'); - if (facet.length > 0) { - facet.addClass('active'); - } - }); - } - }, + onRender: function () { + this.$el.toggleClass('search-navigator-facet-box-collapsed', !this.model.get('enabled')); + this.$el.attr('data-property', this.model.get('property')); + var that = this, + property = this.model.get('property'), + value = this.options.app.state.get('query')[property]; + if (typeof value === 'string') { + value.split(',').forEach(function (s) { + var facet = that.$('.js-facet').filter('[data-value="' + s + '"]'); + if (facet.length > 0) { + facet.addClass('active'); + } + }); + } + }, - toggle: function () { - if (!this.isForbidden()) { - this.options.app.controller.toggleFacet(this.model.id); - } - }, + toggle: function () { + if (!this.isForbidden()) { + this.options.app.controller.toggleFacet(this.model.id); + } + }, - getValue: function () { - return this.$('.js-facet.active').map(function () { - return $(this).data('value'); - }).get().join(); - }, + getValue: function () { + return this.$('.js-facet.active').map(function () { + return $(this).data('value'); + }).get().join(); + }, - toggleFacet: function (e) { - $(e.currentTarget).toggleClass('active'); - var property = this.model.get('property'), - obj = {}; - obj[property] = this.getValue(); - this.options.app.state.updateFilter(obj); - }, + toggleFacet: function (e) { + $(e.currentTarget).toggleClass('active'); + var property = this.model.get('property'), + obj = {}; + obj[property] = this.getValue(); + this.options.app.state.updateFilter(obj); + }, - disable: function () { - var property = this.model.get('property'), - obj = {}; - obj[property] = null; - this.options.app.state.updateFilter(obj); - }, + disable: function () { + var property = this.model.get('property'), + obj = {}; + obj[property] = null; + this.options.app.state.updateFilter(obj); + }, - forbid: function () { - this.options.app.controller.disableFacet(this.model.id); - this.$el.addClass(this.forbiddenClassName); - }, + forbid: function () { + this.options.app.controller.disableFacet(this.model.id); + this.$el.addClass(this.forbiddenClassName); + }, - allow: function () { - this.$el.removeClass(this.forbiddenClassName); - }, + allow: function () { + this.$el.removeClass(this.forbiddenClassName); + }, - isForbidden: function () { - return this.$el.hasClass(this.forbiddenClassName); - }, + isForbidden: function () { + return this.$el.hasClass(this.forbiddenClassName); + }, - sortValues: function (values) { - return values.slice().sort(function (left, right) { - if (left.count !== right.count) { - return right.count - left.count; + sortValues: function (values) { + return values.slice().sort(function (left, right) { + if (left.count !== right.count) { + return right.count - left.count; + } + if (left.val !== right.val) { + if (left.val > right.val) { + return 1; } - if (left.val !== right.val) { - if (left.val > right.val) { - return 1; - } - if (left.val < right.val) { - return -1; - } + if (left.val < right.val) { + return -1; } - return 0; - }); - }, - - serializeData: function () { - return _.extend(Marionette.ItemView.prototype.serializeData.apply(this, arguments), { - values: this.sortValues(this.model.getValues()) - }); - } - }); + } + return 0; + }); + }, + serializeData: function () { + return _.extend(Marionette.ItemView.prototype.serializeData.apply(this, arguments), { + values: this.sortValues(this.model.getValues()) + }); + } }); + + diff --git a/server/sonar-web/src/main/js/components/navigator/filters/ajax-select-filters.js b/server/sonar-web/src/main/js/components/navigator/filters/ajax-select-filters.js index c427c91102f..c97990b940f 100644 --- a/server/sonar-web/src/main/js/components/navigator/filters/ajax-select-filters.js +++ b/server/sonar-web/src/main/js/components/navigator/filters/ajax-select-filters.js @@ -1,489 +1,482 @@ -define([ - 'jquery', - './base-filters', - './choice-filters', - '../templates' -], function ($, BaseFilters, ChoiceFilters) { +import $ from 'jquery'; +import _ from 'underscore'; +import Backbone from 'backbone'; +import BaseFilters from './base-filters'; +import ChoiceFilters from './choice-filters'; +import '../templates'; - var PAGE_SIZE = 100; +var PAGE_SIZE = 100; - var Suggestions = Backbone.Collection.extend({ - comparator: 'text', +var Suggestions = Backbone.Collection.extend({ + comparator: 'text', - initialize: function() { - this.more = false; - this.page = 0; - }, + initialize: function () { + this.more = false; + this.page = 0; + }, - parse: function(r) { - this.more = r.more; - return r.results; - }, + parse: function (r) { + this.more = r.more; + return r.results; + }, - fetch: function(options) { - this.data = _.extend({ - p: 1, - ps: PAGE_SIZE - }, options.data || {}); + fetch: function (options) { + this.data = _.extend({ + p: 1, + ps: PAGE_SIZE + }, options.data || {}); - var settings = _.extend({}, options, { data: this.data }); - return Backbone.Collection.prototype.fetch.call(this, settings); - }, + var settings = _.extend({}, options, { data: this.data }); + return Backbone.Collection.prototype.fetch.call(this, settings); + }, - fetchNextPage: function(options) { - if (this.more) { - this.data.p += 1; - var settings = _.extend({ remove: false }, options, { data: this.data }); - return this.fetch(settings); - } - return false; + fetchNextPage: function (options) { + if (this.more) { + this.data.p += 1; + var settings = _.extend({ remove: false }, options, { data: this.data }); + return this.fetch(settings); } + return false; + } - }); - - - - var UserSuggestions = Suggestions.extend({ +}); - url: function() { - return baseUrl + '/api/users/search'; - }, - parse: function(response) { - var parsedResponse = window.usersToSelect2(response); - this.more = parsedResponse.more; - this.results = parsedResponse.results; - } +var UserSuggestions = Suggestions.extend({ - }); + url: function () { + return baseUrl + '/api/users/search'; + }, + parse: function (response) { + var parsedResponse = window.usersToSelect2(response); + this.more = parsedResponse.more; + this.results = parsedResponse.results; + } +}); - var ProjectSuggestions = Suggestions.extend({ - url: function() { - return baseUrl + '/api/resources/search?f=s2&q=TRK&display_key=true'; - } +var ProjectSuggestions = Suggestions.extend({ - }); + url: function () { + return baseUrl + '/api/resources/search?f=s2&q=TRK&display_key=true'; + } +}); - var ComponentSuggestions = Suggestions.extend({ +var ComponentSuggestions = Suggestions.extend({ - url: function() { - return baseUrl + '/api/resources/search?f=s2&qp=supportsGlobalDashboards&display_key=true'; - }, + url: function () { + return baseUrl + '/api/resources/search?f=s2&qp=supportsGlobalDashboards&display_key=true'; + }, - parse: function(r) { - this.more = r.more; + parse: function (r) { + this.more = r.more; - // If results are divided into categories - if (r.results.length > 0 && r.results[0].children) { - var results = []; - _.each(r.results, function(category) { - _.each(category.children, function(child) { - child.category = category.text; - results.push(child); - }); + // If results are divided into categories + if (r.results.length > 0 && r.results[0].children) { + var results = []; + _.each(r.results, function (category) { + _.each(category.children, function (child) { + child.category = category.text; + results.push(child); }); - return results; - } else { - return r.results; - } + }); + return results; + } else { + return r.results; } + } - }); - +}); - var AjaxSelectDetailsFilterView = ChoiceFilters.DetailsChoiceFilterView.extend({ - template: Templates['ajax-select-filter'], - listTemplate: Templates['choice-filter-template'], - searchKey: 's', +var AjaxSelectDetailsFilterView = ChoiceFilters.DetailsChoiceFilterView.extend({ + template: Templates['ajax-select-filter'], + listTemplate: Templates['choice-filter-template'], + searchKey: 's', - render: function() { - ChoiceFilters.DetailsChoiceFilterView.prototype.render.apply(this, arguments); + render: function () { + ChoiceFilters.DetailsChoiceFilterView.prototype.render.apply(this, arguments); - var that = this, - keyup = function(e) { - if (e.keyCode !== 37 && e.keyCode !== 38 && e.keyCode !== 39 && e.keyCode !== 40) { - that.search(); - } - }, - debouncedKeyup = _.debounce(keyup, 250), - scroll = function() { that.scroll(); }, - throttledScroll = _.throttle(scroll, 1000); - - this.$('.navigator-filter-search input') - .off('keyup keydown') - .on('keyup', debouncedKeyup) - .on('keydown', this.keydown); - - this.$('.choices') - .off('scroll') - .on('scroll', throttledScroll); - }, - - - search: function() { - var that = this; - this.query = this.$('.navigator-filter-search input').val(); - if (this.query.length > 1) { - this.$el.addClass('fetching'); - var selected = that.options.filterView.getSelected(), - data = { ps: PAGE_SIZE }; - data[this.searchKey] = this.query; - this.options.filterView.choices.fetch({ - data: data, - success: function() { - selected.forEach(function(item) { - that.options.filterView.choices.unshift(item); - }); - _.each(that.model.get('choices'), function(v, k) { - if (k[0] === '!') { - that.options.filterView.choices.add(new Backbone.Model({ id: k, text: v })); - } - }); - that.updateLists(); - that.$el.removeClass('fetching'); - that.$('.navigator-filter-search').removeClass('fetching-error'); - }, - error: function() { - that.showSearchError(); + var that = this, + keyup = function (e) { + if (e.keyCode !== 37 && e.keyCode !== 38 && e.keyCode !== 39 && e.keyCode !== 40) { + that.search(); } - }); - } else { - this.resetChoices(); - this.updateLists(); - } - }, - - - showSearchError: function() { - this.$el.removeClass('fetching'); - this.$('.navigator-filter-search').addClass('fetching-error'); - }, - - - scroll: function() { - var that = this, - el = this.$('.choices'), - scrollBottom = el.scrollTop() >= el[0].scrollHeight - el.outerHeight(); - - if (scrollBottom) { - this.options.filterView.choices.fetchNextPage().done(function() { + }, + debouncedKeyup = _.debounce(keyup, 250), + scroll = function () { + that.scroll(); + }, + throttledScroll = _.throttle(scroll, 1000); + + this.$('.navigator-filter-search input') + .off('keyup keydown') + .on('keyup', debouncedKeyup) + .on('keydown', this.keydown); + + this.$('.choices') + .off('scroll') + .on('scroll', throttledScroll); + }, + + + search: function () { + var that = this; + this.query = this.$('.navigator-filter-search input').val(); + if (this.query.length > 1) { + this.$el.addClass('fetching'); + var selected = that.options.filterView.getSelected(), + data = { ps: PAGE_SIZE }; + data[this.searchKey] = this.query; + this.options.filterView.choices.fetch({ + data: data, + success: function () { + selected.forEach(function (item) { + that.options.filterView.choices.unshift(item); + }); + _.each(that.model.get('choices'), function (v, k) { + if (k[0] === '!') { + that.options.filterView.choices.add(new Backbone.Model({ id: k, text: v })); + } + }); that.updateLists(); - }); - } - }, + that.$el.removeClass('fetching'); + that.$('.navigator-filter-search').removeClass('fetching-error'); + }, + error: function () { + that.showSearchError(); + } + }); + } else { + this.resetChoices(); + this.updateLists(); + } + }, - keydown: function(e) { - if (_([38, 40, 13]).indexOf(e.keyCode) !== -1) { - e.preventDefault(); - } - }, + showSearchError: function () { + this.$el.removeClass('fetching'); + this.$('.navigator-filter-search').addClass('fetching-error'); + }, - resetChoices: function() { - var that = this; - this.options.filterView.choices.reset(this.options.filterView.choices.filter(function(item) { - return item.get('checked'); - })); - _.each(this.model.get('choices'), function(v, k) { - that.options.filterView.choices.add(new Backbone.Model({ id: k, text: v })); + scroll: function () { + var that = this, + el = this.$('.choices'), + scrollBottom = el.scrollTop() >= el[0].scrollHeight - el.outerHeight(); + + if (scrollBottom) { + this.options.filterView.choices.fetchNextPage().done(function () { + that.updateLists(); }); - }, + } + }, - onShow: function() { - ChoiceFilters.DetailsChoiceFilterView.prototype.onShow.apply(this, arguments); - this.resetChoices(); - this.render(); - this.$('.navigator-filter-search input').focus(); + keydown: function (e) { + if (_([38, 40, 13]).indexOf(e.keyCode) !== -1) { + e.preventDefault(); } + }, - }); + resetChoices: function () { + var that = this; + this.options.filterView.choices.reset(this.options.filterView.choices.filter(function (item) { + return item.get('checked'); + })); + _.each(this.model.get('choices'), function (v, k) { + that.options.filterView.choices.add(new Backbone.Model({ id: k, text: v })); + }); + }, - var AjaxSelectFilterView = ChoiceFilters.ChoiceFilterView.extend({ + onShow: function () { + ChoiceFilters.DetailsChoiceFilterView.prototype.onShow.apply(this, arguments); + this.resetChoices(); + this.render(); + this.$('.navigator-filter-search input').focus(); + } - initialize: function(options) { - ChoiceFilters.ChoiceFilterView.prototype.initialize.call(this, { - detailsView: (options && options.detailsView) ? options.detailsView : AjaxSelectDetailsFilterView - }); - }, +}); - isDefaultValue: function() { - return this.getSelected().length === 0; - }, +var AjaxSelectFilterView = ChoiceFilters.ChoiceFilterView.extend({ + initialize: function (options) { + ChoiceFilters.ChoiceFilterView.prototype.initialize.call(this, { + detailsView: (options && options.detailsView) ? options.detailsView : AjaxSelectDetailsFilterView + }); + }, - renderInput: function() { - var value = this.model.get('value') || [], - input = $('<input>') - .prop('name', this.model.get('property')) - .prop('type', 'hidden') - .css('display', 'none') - .val(value.join()); - input.appendTo(this.$el); - }, + isDefaultValue: function () { + return this.getSelected().length === 0; + }, - restoreFromQuery: function(q) { - var param = _.findWhere(q, { key: this.model.get('property') }); - if (this.model.get('choices')) { - _.each(this.model.get('choices'), function(v, k) { - if (k[0] === '!') { - var x = _.findWhere(q, { key: k.substr(1) }); - if (x == null) { - return; - } - if (!param) { - param = { value: k }; - } else { - param.value += ',' + k; - } - } - }); - } + renderInput: function () { + var value = this.model.get('value') || [], + input = $('<input>') + .prop('name', this.model.get('property')) + .prop('type', 'hidden') + .css('display', 'none') + .val(value.join()); + input.appendTo(this.$el); + }, - if (param && param.value) { - this.model.set('enabled', true); - this.restore(param.value, param); - } else { - this.clear(); - } - }, + restoreFromQuery: function (q) { + var param = _.findWhere(q, { key: this.model.get('property') }); - restore: function(value, param) { - var that = this; - if (_.isString(value)) { - value = value.split(','); - } + if (this.model.get('choices')) { + _.each(this.model.get('choices'), function (v, k) { + if (k[0] === '!') { + var x = _.findWhere(q, { key: k.substr(1) }); + if (x == null) { + return; + } + if (!param) { + param = { value: k }; + } else { + param.value += ',' + k; + } + } + }); + } - if (this.choices && value.length > 0) { - this.model.set({ value: value, enabled: true }); + if (param && param.value) { + this.model.set('enabled', true); + this.restore(param.value, param); + } else { + this.clear(); + } + }, - var opposite = _.filter(value, function(item) { - return item[0] === '!'; - }); - opposite.forEach(function(item) { - that.choices.add(new Backbone.Model({ - id: item, - text: that.model.get('choices')[item], - checked: true - })); - }); - value = _.reject(value, function(item) { - return item[0] === '!'; - }); - if (_.isArray(param.text) && param.text.length === value.length) { - this.restoreFromText(value, param.text); - } else { - this.restoreByRequests(value); - } - } else { - this.clear(); - } - }, + restore: function (value, param) { + var that = this; + if (_.isString(value)) { + value = value.split(','); + } + if (this.choices && value.length > 0) { + this.model.set({ value: value, enabled: true }); - restoreFromText: function(value, text) { - var that = this; - _.each(value, function(v, i) { + var opposite = _.filter(value, function (item) { + return item[0] === '!'; + }); + opposite.forEach(function (item) { that.choices.add(new Backbone.Model({ - id: v, - text: text[i], + id: item, + text: that.model.get('choices')[item], checked: true })); }); - this.onRestore(value); - }, - - - restoreByRequests: function(value) { - var that = this, - requests = _.map(value, function(v) { - return that.createRequest(v); - }); - $.when.apply($, requests).done(function () { - that.onRestore(value); + value = _.reject(value, function (item) { + return item[0] === '!'; }); - }, + if (_.isArray(param.text) && param.text.length === value.length) { + this.restoreFromText(value, param.text); + } else { + this.restoreByRequests(value); + } + } else { + this.clear(); + } + }, - onRestore: function() { - this.detailsView.updateLists(); - this.renderBase(); - }, + restoreFromText: function (value, text) { + var that = this; + _.each(value, function (v, i) { + that.choices.add(new Backbone.Model({ + id: v, + text: text[i], + checked: true + })); + }); + this.onRestore(value); + }, - clear: function() { - this.model.unset('value'); - if (this.choices) { - this.choices.reset([]); - } - this.render(); - }, + restoreByRequests: function (value) { + var that = this, + requests = _.map(value, function (v) { + return that.createRequest(v); + }); + $.when.apply($, requests).done(function () { + that.onRestore(value); + }); + }, - createRequest: function() {} - }); + onRestore: function () { + this.detailsView.updateLists(); + this.renderBase(); + }, + clear: function () { + this.model.unset('value'); + if (this.choices) { + this.choices.reset([]); + } + this.render(); + }, - var ComponentFilterView = AjaxSelectFilterView.extend({ - initialize: function() { - AjaxSelectFilterView.prototype.initialize.call(this, { - detailsView: AjaxSelectDetailsFilterView - }); - this.choices = new ComponentSuggestions(); - }, - - - createRequest: function(v) { - var that = this; - return $ - .ajax({ - url: baseUrl + '/api/resources', - type: 'GET', - data: { resource: v } - }) - .done(function (r) { - that.selection.add(new Backbone.Model({ - id: r[0].key, - text: r[0].name - })); - }); - } + createRequest: function () { + } - }); +}); +var ComponentFilterView = AjaxSelectFilterView.extend({ + + initialize: function () { + AjaxSelectFilterView.prototype.initialize.call(this, { + detailsView: AjaxSelectDetailsFilterView + }); + this.choices = new ComponentSuggestions(); + }, + + + createRequest: function (v) { + var that = this; + return $ + .ajax({ + url: baseUrl + '/api/resources', + type: 'GET', + data: { resource: v } + }) + .done(function (r) { + that.selection.add(new Backbone.Model({ + id: r[0].key, + text: r[0].name + })); + }); + } - var ProjectFilterView = AjaxSelectFilterView.extend({ +}); - initialize: function() { - BaseFilters.BaseFilterView.prototype.initialize.call(this, { - detailsView: AjaxSelectDetailsFilterView - }); - this.choices = new ProjectSuggestions(); - }, - - - createRequest: function(v) { - var that = this; - return $ - .ajax({ - url: baseUrl + '/api/resources', - type: 'GET', - data: { resource: v } - }) - .done(function (r) { - that.choices.add(new Backbone.Model({ - id: r[0].key, - text: r[0].name, - checked: true - })); - }); - } +var ProjectFilterView = AjaxSelectFilterView.extend({ - }); + initialize: function () { + BaseFilters.BaseFilterView.prototype.initialize.call(this, { + detailsView: AjaxSelectDetailsFilterView + }); + this.choices = new ProjectSuggestions(); + }, - var AssigneeFilterView = AjaxSelectFilterView.extend({ + createRequest: function (v) { + var that = this; + return $ + .ajax({ + url: baseUrl + '/api/resources', + type: 'GET', + data: { resource: v } + }) + .done(function (r) { + that.choices.add(new Backbone.Model({ + id: r[0].key, + text: r[0].name, + checked: true + })); + }); + } - initialize: function() { - BaseFilters.BaseFilterView.prototype.initialize.call(this, { - detailsView: AjaxSelectDetailsFilterView - }); +}); - this.choices = new UserSuggestions(); - }, - - createRequest: function(v) { - var that = this; - return $ - .ajax({ - url: baseUrl + '/api/users/search', - type: 'GET', - data: { q: v } - }) - .done(function (r) { - that.choices.add(new Backbone.Model({ - id: r.users[0].login, - text: r.users[0].name + ' (' + r.users[0].login + ')', - checked: true - })); - }); - } - }); +var AssigneeFilterView = AjaxSelectFilterView.extend({ + initialize: function () { + BaseFilters.BaseFilterView.prototype.initialize.call(this, { + detailsView: AjaxSelectDetailsFilterView + }); + this.choices = new UserSuggestions(); + }, - var ReporterFilterView = AjaxSelectFilterView.extend({ + createRequest: function (v) { + var that = this; + return $ + .ajax({ + url: baseUrl + '/api/users/search', + type: 'GET', + data: { q: v } + }) + .done(function (r) { + that.choices.add(new Backbone.Model({ + id: r.users[0].login, + text: r.users[0].name + ' (' + r.users[0].login + ')', + checked: true + })); + }); + } - initialize: function() { - BaseFilters.BaseFilterView.prototype.initialize.call(this, { - detailsView: AjaxSelectDetailsFilterView - }); +}); - this.selection = new UserSuggestions(); - this.choices = new UserSuggestions(); - }, - - - createRequest: function(v) { - var that = this; - return $ - .ajax({ - url: baseUrl + '/api/users/search', - type: 'GET', - data: { q: v } - }) - .done(function (r) { - that.choices.add(new Backbone.Model({ - id: r.users[0].login, - text: r.users[0].name + ' (' + r.users[0].login + ')', - checked: true - })); - }); - } - }); +var ReporterFilterView = AjaxSelectFilterView.extend({ + initialize: function () { + BaseFilters.BaseFilterView.prototype.initialize.call(this, { + detailsView: AjaxSelectDetailsFilterView + }); + this.selection = new UserSuggestions(); + this.choices = new UserSuggestions(); + }, - /* - * Export public classes - */ - return { - Suggestions: Suggestions, - AjaxSelectDetailsFilterView: AjaxSelectDetailsFilterView, - AjaxSelectFilterView: AjaxSelectFilterView, - ProjectFilterView: ProjectFilterView, - ComponentFilterView: ComponentFilterView, - AssigneeFilterView: AssigneeFilterView, - ReporterFilterView: ReporterFilterView - }; + createRequest: function (v) { + var that = this; + return $ + .ajax({ + url: baseUrl + '/api/users/search', + type: 'GET', + data: { q: v } + }) + .done(function (r) { + that.choices.add(new Backbone.Model({ + id: r.users[0].login, + text: r.users[0].name + ' (' + r.users[0].login + ')', + checked: true + })); + }); + } }); + + +/* + * Export public classes + */ + +export default { + Suggestions: Suggestions, + AjaxSelectDetailsFilterView: AjaxSelectDetailsFilterView, + AjaxSelectFilterView: AjaxSelectFilterView, + ProjectFilterView: ProjectFilterView, + ComponentFilterView: ComponentFilterView, + AssigneeFilterView: AssigneeFilterView, + ReporterFilterView: ReporterFilterView +}; + + diff --git a/server/sonar-web/src/main/js/components/navigator/filters/base-filters.js b/server/sonar-web/src/main/js/components/navigator/filters/base-filters.js index 938b76028ee..a0d96287987 100644 --- a/server/sonar-web/src/main/js/components/navigator/filters/base-filters.js +++ b/server/sonar-web/src/main/js/components/navigator/filters/base-filters.js @@ -1,235 +1,235 @@ -define([ - 'jquery', - '../templates' -], function ($) { - - var Filter = Backbone.Model.extend({ - - defaults: { - enabled: true, - optional: false, - multiple: true, - placeholder: '' - } +import $ from 'jquery'; +import _ from 'underscore'; +import Backbone from 'backbone'; +import Marionette from 'backbone.marionette'; +import '../templates'; - }); +var Filter = Backbone.Model.extend({ + defaults: { + enabled: true, + optional: false, + multiple: true, + placeholder: '' + } +}); - var Filters = Backbone.Collection.extend({ - model: Filter - }); +var Filters = Backbone.Collection.extend({ + model: Filter +}); - var DetailsFilterView = Marionette.ItemView.extend({ - template: Templates['base-details-filter'], - className: 'navigator-filter-details', +var DetailsFilterView = Marionette.ItemView.extend({ + template: Templates['base-details-filter'], + className: 'navigator-filter-details', - initialize: function() { - this.$el.on('click', function(e) { - e.stopPropagation(); - }); - this.$el.attr('id', 'filter-' + this.model.get('property')); - }, + initialize: function () { + this.$el.on('click', function (e) { + e.stopPropagation(); + }); + this.$el.attr('id', 'filter-' + this.model.get('property')); + }, - onShow: function() {}, - onHide: function() {} - }); + onShow: function () { + }, + onHide: function () { + } +}); +var BaseFilterView = Marionette.ItemView.extend({ + template: Templates['base-filter'], + className: 'navigator-filter', - var BaseFilterView = Marionette.ItemView.extend({ - template: Templates['base-filter'], - className: 'navigator-filter', + events: function () { + return { + 'click': 'toggleDetails', + 'click .navigator-filter-disable': 'disable' + }; + }, - events: function() { - return { - 'click': 'toggleDetails', - 'click .navigator-filter-disable': 'disable' - }; - }, + modelEvents: { + 'change:enabled': 'focus', + 'change:value': 'renderBase', - modelEvents: { - 'change:enabled': 'focus', - 'change:value': 'renderBase', + // for more criteria filter + 'change:filters': 'render' + }, - // for more criteria filter - 'change:filters': 'render' - }, + initialize: function (options) { + Marionette.ItemView.prototype.initialize.apply(this, arguments); - initialize: function(options) { - Marionette.ItemView.prototype.initialize.apply(this, arguments); + var detailsView = (options && options.detailsView) || DetailsFilterView; + this.detailsView = new detailsView({ + model: this.model, + filterView: this + }); - var detailsView = (options && options.detailsView) || DetailsFilterView; - this.detailsView = new detailsView({ - model: this.model, - filterView: this - }); + this.model.view = this; + }, - this.model.view = this; - }, + attachDetailsView: function () { + this.detailsView.$el.detach().appendTo($('body')); + }, - attachDetailsView: function() { - this.detailsView.$el.detach().appendTo($('body')); - }, + render: function () { + this.renderBase(); - render: function() { - this.renderBase(); + this.attachDetailsView(); + this.detailsView.render(); - this.attachDetailsView(); - this.detailsView.render(); + this.$el.toggleClass( + 'navigator-filter-disabled', + !this.model.get('enabled')); - this.$el.toggleClass( - 'navigator-filter-disabled', - !this.model.get('enabled')); + this.$el.toggleClass( + 'navigator-filter-optional', + this.model.get('optional')); + }, - this.$el.toggleClass( - 'navigator-filter-optional', - this.model.get('optional')); - }, + renderBase: function () { + Marionette.ItemView.prototype.render.apply(this, arguments); + this.renderInput(); - renderBase: function() { - Marionette.ItemView.prototype.render.apply(this, arguments); - this.renderInput(); + var title = this.model.get('name') + ': ' + this.renderValue(); + this.$el.prop('title', title); + this.$el.attr('data-property', this.model.get('property')); + }, - var title = this.model.get('name') + ': ' + this.renderValue(); - this.$el.prop('title', title); - this.$el.attr('data-property', this.model.get('property')); - }, + renderInput: function () { + }, - renderInput: function() {}, + focus: function () { + this.render(); + }, - focus: function() { - this.render(); - }, + toggleDetails: function (e) { + e.stopPropagation(); + this.options.filterBarView.selected = this.options.filterBarView.getEnabledFilters().index(this.$el); + if (this.$el.hasClass('active')) { + key.setScope('list'); + this.hideDetails(); + } else { + key.setScope('filters'); + this.showDetails(); + } + }, - toggleDetails: function(e) { - e.stopPropagation(); - this.options.filterBarView.selected = this.options.filterBarView.getEnabledFilters().index(this.$el); - if (this.$el.hasClass('active')) { - key.setScope('list'); - this.hideDetails(); - } else { - key.setScope('filters'); - this.showDetails(); - } - }, + showDetails: function () { + this.registerShowedDetails(); - showDetails: function() { - this.registerShowedDetails(); + var top = this.$el.offset().top + this.$el.outerHeight() - 1, + left = this.$el.offset().left; - var top = this.$el.offset().top + this.$el.outerHeight() - 1, - left = this.$el.offset().left; + this.detailsView.$el.css({ top: top, left: left }).addClass('active'); + this.$el.addClass('active'); + this.detailsView.onShow(); + }, - this.detailsView.$el.css({ top: top, left: left }).addClass('active'); - this.$el.addClass('active'); - this.detailsView.onShow(); - }, + registerShowedDetails: function () { + this.options.filterBarView.hideDetails(); + this.options.filterBarView.showedView = this; + }, - registerShowedDetails: function() { - this.options.filterBarView.hideDetails(); - this.options.filterBarView.showedView = this; - }, + hideDetails: function () { + this.detailsView.$el.removeClass('active'); + this.$el.removeClass('active'); + this.detailsView.onHide(); + }, - hideDetails: function() { - this.detailsView.$el.removeClass('active'); - this.$el.removeClass('active'); - this.detailsView.onHide(); - }, + isActive: function () { + return this.$el.is('.active'); + }, - isActive: function() { - return this.$el.is('.active'); - }, + renderValue: function () { + return this.model.get('value') || 'unset'; + }, - renderValue: function() { - return this.model.get('value') || 'unset'; - }, + isDefaultValue: function () { + return true; + }, - isDefaultValue: function() { - return true; - }, + restoreFromQuery: function (q) { + var param = _.findWhere(q, { key: this.model.get('property') }); + if (param && param.value) { + this.model.set('enabled', true); + this.restore(param.value, param); + } else { + this.clear(); + } + }, - restoreFromQuery: function(q) { - var param = _.findWhere(q, { key: this.model.get('property') }); - if (param && param.value) { - this.model.set('enabled', true); - this.restore(param.value, param); - } else { - this.clear(); - } - }, + restore: function (value) { + this.model.set({ value: value }, { silent: true }); + this.renderBase(); + }, - restore: function(value) { - this.model.set({ value: value }, { silent: true }); - this.renderBase(); - }, + clear: function () { + this.model.unset('value'); + }, - clear: function() { - this.model.unset('value'); - }, + disable: function (e) { + e.stopPropagation(); + this.hideDetails(); + this.options.filterBarView.hideDetails(); + this.model.set({ + enabled: false, + value: null + }); + }, - disable: function(e) { - e.stopPropagation(); - this.hideDetails(); - this.options.filterBarView.hideDetails(); - this.model.set({ - enabled: false, - value: null - }); - }, - - - formatValue: function() { - var q = {}; - if (this.model.has('property') && this.model.has('value') && this.model.get('value')) { - q[this.model.get('property')] = this.model.get('value'); - } - return q; - }, - - - serializeData: function() { - return _.extend({}, this.model.toJSON(), { - value: this.renderValue(), - defaultValue: this.isDefaultValue() - }); + + formatValue: function () { + var q = {}; + if (this.model.has('property') && this.model.has('value') && this.model.get('value')) { + q[this.model.get('property')] = this.model.get('value'); } + return q; + }, - }); + serializeData: function () { + return _.extend({}, this.model.toJSON(), { + value: this.renderValue(), + defaultValue: this.isDefaultValue() + }); + } +}); - /* - * Export public classes - */ - return { - Filter: Filter, - Filters: Filters, - BaseFilterView: BaseFilterView, - DetailsFilterView: DetailsFilterView - }; +/* + * Export public classes + */ + +export default { + Filter: Filter, + Filters: Filters, + BaseFilterView: BaseFilterView, + DetailsFilterView: DetailsFilterView +}; + -}); diff --git a/server/sonar-web/src/main/js/components/navigator/filters/checkbox-filters.js b/server/sonar-web/src/main/js/components/navigator/filters/checkbox-filters.js index 964dfa1ff81..08152fd9388 100644 --- a/server/sonar-web/src/main/js/components/navigator/filters/checkbox-filters.js +++ b/server/sonar-web/src/main/js/components/navigator/filters/checkbox-filters.js @@ -1,54 +1,53 @@ -define([ - 'jquery', - './base-filters', - '../templates' -], function ($, BaseFilters) { +import $ from 'jquery'; +import BaseFilters from './base-filters'; +import '../templates'; - return BaseFilters.BaseFilterView.extend({ - template: Templates['checkbox-filter'], - className: 'navigator-filter navigator-filter-inline', +export default BaseFilters.BaseFilterView.extend({ + template: Templates['checkbox-filter'], + className: 'navigator-filter navigator-filter-inline', - events: function() { - return { - 'click .navigator-filter-disable': 'disable' - }; - }, + events: function () { + return { + 'click .navigator-filter-disable': 'disable' + }; + }, - showDetails: function() {}, + showDetails: function () { + }, - renderInput: function() { - if (this.model.get('enabled')) { - $('<input>') - .prop('name', this.model.get('property')) - .prop('type', 'checkbox') - .prop('value', 'true') - .prop('checked', true) - .css('display', 'none') - .appendTo(this.$el); - } - }, - + renderInput: function () { + if (this.model.get('enabled')) { + $('<input>') + .prop('name', this.model.get('property')) + .prop('type', 'checkbox') + .prop('value', 'true') + .prop('checked', true) + .css('display', 'none') + .appendTo(this.$el); + } + }, - renderValue: function() { - return this.model.get('value'); - }, + renderValue: function () { + return this.model.get('value'); + }, - isDefaultValue: function() { - return false; - }, + isDefaultValue: function () { + return false; + }, - restore: function(value) { - this.model.set({ - value: value, - enabled: true - }); - } - }); + restore: function (value) { + this.model.set({ + value: value, + enabled: true + }); + } }); + + diff --git a/server/sonar-web/src/main/js/components/navigator/filters/choice-filters.js b/server/sonar-web/src/main/js/components/navigator/filters/choice-filters.js index f65a5b58876..e3451731d72 100644 --- a/server/sonar-web/src/main/js/components/navigator/filters/choice-filters.js +++ b/server/sonar-web/src/main/js/components/navigator/filters/choice-filters.js @@ -1,392 +1,390 @@ -define([ - 'jquery', - './base-filters', - '../templates' -], function ($, BaseFilters) { +import $ from 'jquery'; +import _ from 'underscore'; +import Backbone from 'backbone'; +import BaseFilters from './base-filters'; +import '../templates'; - var DetailsChoiceFilterView = BaseFilters.DetailsFilterView.extend({ - template: Templates['choice-filter'], - itemTemplate: Templates['choice-filter-item'], +var DetailsChoiceFilterView = BaseFilters.DetailsFilterView.extend({ + template: Templates['choice-filter'], + itemTemplate: Templates['choice-filter-item'], - events: function() { - return { - 'click label': 'onCheck' - }; - }, + events: function () { + return { + 'click label': 'onCheck' + }; + }, - render: function() { - BaseFilters.DetailsFilterView.prototype.render.apply(this, arguments); - this.updateLists(); - }, + render: function () { + BaseFilters.DetailsFilterView.prototype.render.apply(this, arguments); + this.updateLists(); + }, - renderList: function(collection, selector) { - var that = this, - container = this.$(selector); + renderList: function (collection, selector) { + var that = this, + container = this.$(selector); - container.empty().toggleClass('hidden', collection.length === 0); - collection.each(function (item) { - container.append( + container.empty().toggleClass('hidden', collection.length === 0); + collection.each(function (item) { + container.append( that.itemTemplate(_.extend(item.toJSON(), { multiple: that.model.get('multiple') && item.get('id')[0] !== '!' })) - ); - }); - }, + ); + }); + }, - updateLists: function() { - var choices = new Backbone.Collection(this.options.filterView.choices.reject(function(item) { - return item.get('id')[0] === '!'; - })), - opposite = new Backbone.Collection(this.options.filterView.choices.filter(function(item) { - return item.get('id')[0] === '!'; - })); + updateLists: function () { + var choices = new Backbone.Collection(this.options.filterView.choices.reject(function (item) { + return item.get('id')[0] === '!'; + })), + opposite = new Backbone.Collection(this.options.filterView.choices.filter(function (item) { + return item.get('id')[0] === '!'; + })); - this.renderList(choices, '.choices'); - this.renderList(opposite, '.opposite'); + this.renderList(choices, '.choices'); + this.renderList(opposite, '.opposite'); - var current = this.currentChoice || 0; - this.updateCurrent(current); - }, + var current = this.currentChoice || 0; + this.updateCurrent(current); + }, - onCheck: function(e) { - var checkbox = jQuery(e.currentTarget), - id = checkbox.data('id'), - checked = checkbox.find('.icon-checkbox-checked').length > 0; + onCheck: function (e) { + var checkbox = $(e.currentTarget), + id = checkbox.data('id'), + checked = checkbox.find('.icon-checkbox-checked').length > 0; - if (this.model.get('multiple')) { - if (checkbox.closest('.opposite').length > 0) { - this.options.filterView.choices.each(function(item) { - item.set('checked', false); - }); - } else { - this.options.filterView.choices.filter(function(item) { - return item.get('id')[0] === '!'; - }).forEach(function(item) { - item.set('checked', false); - }); - } + if (this.model.get('multiple')) { + if (checkbox.closest('.opposite').length > 0) { + this.options.filterView.choices.each(function (item) { + item.set('checked', false); + }); } else { - this.options.filterView.choices.each(function(item) { + this.options.filterView.choices.filter(function (item) { + return item.get('id')[0] === '!'; + }).forEach(function (item) { item.set('checked', false); }); } + } else { + this.options.filterView.choices.each(function (item) { + item.set('checked', false); + }); + } - this.options.filterView.choices.get(id).set('checked', !checked); - this.updateValue(); - this.updateLists(); - }, - - - updateValue: function() { - this.model.set('value', this.options.filterView.getSelected().map(function(m) { - return m.get('id'); - })); - }, - - - updateCurrent: function(index) { - this.currentChoice = index; - this.$('label').removeClass('current') - .eq(this.currentChoice).addClass('current'); - }, - - - onShow: function() { - this.bindedOnKeyDown = _.bind(this.onKeyDown, this); - $('body').on('keydown', this.bindedOnKeyDown); - }, - - - onHide: function() { - $('body').off('keydown', this.bindedOnKeyDown); - }, - - - onKeyDown: function(e) { - switch (e.keyCode) { - case 38: - e.preventDefault(); - this.selectPrevChoice(); - break; - case 40: - e.preventDefault(); - this.selectNextChoice(); - break; - case 13: - e.preventDefault(); - this.selectCurrent(); - break; - default: - // Not a functional key - then skip - break; - } - }, + this.options.filterView.choices.get(id).set('checked', !checked); + this.updateValue(); + this.updateLists(); + }, + + + updateValue: function () { + this.model.set('value', this.options.filterView.getSelected().map(function (m) { + return m.get('id'); + })); + }, + + + updateCurrent: function (index) { + this.currentChoice = index; + this.$('label').removeClass('current') + .eq(this.currentChoice).addClass('current'); + }, + + + onShow: function () { + this.bindedOnKeyDown = _.bind(this.onKeyDown, this); + $('body').on('keydown', this.bindedOnKeyDown); + }, + + + onHide: function () { + $('body').off('keydown', this.bindedOnKeyDown); + }, + + + onKeyDown: function (e) { + switch (e.keyCode) { + case 38: + e.preventDefault(); + this.selectPrevChoice(); + break; + case 40: + e.preventDefault(); + this.selectNextChoice(); + break; + case 13: + e.preventDefault(); + this.selectCurrent(); + break; + default: + // Not a functional key - then skip + break; + } + }, - selectNextChoice: function() { - if (this.$('label').length > this.currentChoice + 1) { - this.updateCurrent(this.currentChoice + 1); - this.scrollNext(); - } - }, + selectNextChoice: function () { + if (this.$('label').length > this.currentChoice + 1) { + this.updateCurrent(this.currentChoice + 1); + this.scrollNext(); + } + }, - scrollNext: function() { - var currentLabel = this.$('label').eq(this.currentChoice); - if (currentLabel.length > 0) { - var list = currentLabel.closest('ul'), - labelPos = currentLabel.offset().top - list.offset().top + list.scrollTop(), - deltaScroll = labelPos - list.height() + currentLabel.outerHeight(); + scrollNext: function () { + var currentLabel = this.$('label').eq(this.currentChoice); + if (currentLabel.length > 0) { + var list = currentLabel.closest('ul'), + labelPos = currentLabel.offset().top - list.offset().top + list.scrollTop(), + deltaScroll = labelPos - list.height() + currentLabel.outerHeight(); - if (deltaScroll > 0) { - list.scrollTop(deltaScroll); - } + if (deltaScroll > 0) { + list.scrollTop(deltaScroll); } - }, + } + }, - selectPrevChoice: function() { - if (this.currentChoice > 0) { - this.updateCurrent(this.currentChoice - 1); - this.scrollPrev(); - } - }, + selectPrevChoice: function () { + if (this.currentChoice > 0) { + this.updateCurrent(this.currentChoice - 1); + this.scrollPrev(); + } + }, - scrollPrev: function() { - var currentLabel = this.$('label').eq(this.currentChoice); - if (currentLabel.length > 0) { - var list = currentLabel.closest('ul'), - labelPos = currentLabel.offset().top - list.offset().top; + scrollPrev: function () { + var currentLabel = this.$('label').eq(this.currentChoice); + if (currentLabel.length > 0) { + var list = currentLabel.closest('ul'), + labelPos = currentLabel.offset().top - list.offset().top; - if (labelPos < 0) { - list.scrollTop(list.scrollTop() + labelPos); - } + if (labelPos < 0) { + list.scrollTop(list.scrollTop() + labelPos); } - }, - - - selectCurrent: function() { - var cb = this.$('label').eq(this.currentChoice); - cb.click(); - }, - - - serializeData: function() { - return _.extend({}, this.model.toJSON(), { - choices: new Backbone.Collection(this.options.filterView.choices.reject(function(item) { - return item.get('id')[0] === '!'; - })).toJSON(), - opposite: new Backbone.Collection(this.options.filterView.choices.filter(function(item) { - return item.get('id')[0] === '!'; - })).toJSON() - }); } + }, - }); + selectCurrent: function () { + var cb = this.$('label').eq(this.currentChoice); + cb.click(); + }, - var ChoiceFilterView = BaseFilters.BaseFilterView.extend({ + serializeData: function () { + return _.extend({}, this.model.toJSON(), { + choices: new Backbone.Collection(this.options.filterView.choices.reject(function (item) { + return item.get('id')[0] === '!'; + })).toJSON(), + opposite: new Backbone.Collection(this.options.filterView.choices.filter(function (item) { + return item.get('id')[0] === '!'; + })).toJSON() + }); + } - initialize: function(options) { - BaseFilters.BaseFilterView.prototype.initialize.call(this, { - detailsView: (options && options.detailsView) ? options.detailsView : DetailsChoiceFilterView - }); +}); - var index = 0, - icons = this.model.get('choiceIcons'); - this.choices = new Backbone.Collection( - _.map(this.model.get('choices'), function(value, key) { - var model = new Backbone.Model({ - id: key, - text: value, - checked: false, - index: index++ - }); +var ChoiceFilterView = BaseFilters.BaseFilterView.extend({ - if (icons && icons[key]) { - model.set('icon', icons[key]); - } + initialize: function (options) { + BaseFilters.BaseFilterView.prototype.initialize.call(this, { + detailsView: (options && options.detailsView) ? options.detailsView : DetailsChoiceFilterView + }); - return model; - }), { comparator: 'index' } - ); - }, + var index = 0, + icons = this.model.get('choiceIcons'); + this.choices = new Backbone.Collection( + _.map(this.model.get('choices'), function (value, key) { + var model = new Backbone.Model({ + id: key, + text: value, + checked: false, + index: index++ + }); - getSelected: function() { - return this.choices.filter(function(m) { - return m.get('checked'); - }); - }, - - - renderInput: function() { - var input = $('<select>') - .prop('name', this.model.get('property')) - .prop('multiple', true) - .css('display', 'none'); - this.choices.each(function(item) { - var option = $('<option>') - .prop('value', item.get('id')) - .prop('selected', item.get('checked')) - .text(item.get('text')); - option.appendTo(input); + if (icons && icons[key]) { + model.set('icon', icons[key]); + } + + return model; + }), { comparator: 'index' } + ); + }, + + + getSelected: function () { + return this.choices.filter(function (m) { + return m.get('checked'); + }); + }, + + + renderInput: function () { + var input = $('<select>') + .prop('name', this.model.get('property')) + .prop('multiple', true) + .css('display', 'none'); + this.choices.each(function (item) { + var option = $('<option>') + .prop('value', item.get('id')) + .prop('selected', item.get('checked')) + .text(item.get('text')); + option.appendTo(input); + }); + input.appendTo(this.$el); + }, + + + renderValue: function () { + var value = this.getSelected().map(function (item) { + return item.get('text'); + }), + defaultValue = this.model.has('defaultValue') ? + this.model.get('defaultValue') : + this.model.get('multiple') ? t('all') : t('any'); + + return this.isDefaultValue() ? defaultValue : value.join(', '); + }, + + + isDefaultValue: function () { + var selected = this.getSelected(); + return selected.length === 0; + }, + + + disable: function () { + this.choices.each(function (item) { + item.set('checked', false); + }); + BaseFilters.BaseFilterView.prototype.disable.apply(this, arguments); + }, + + + restoreFromQuery: function (q) { + var param = _.findWhere(q, { key: this.model.get('property') }); + + if (this.choices) { + this.choices.forEach(function (item) { + if (item.get('id')[0] === '!') { + var x = _.findWhere(q, { key: item.get('id').substr(1) }); + if (item.get('id').indexOf('=') >= 0) { + var key = item.get('id').split('=')[0].substr(1); + var value = item.get('id').split('=')[1]; + x = _.findWhere(q, { key: key, value: value }); + } + if (x == null) { + return; + } + if (!param) { + param = { value: item.get('id') }; + } else { + param.value += ',' + item.get('id'); + } + } }); - input.appendTo(this.$el); - }, + } + if (param && param.value) { + this.model.set('enabled', true); + this.restore(param.value, param); + } else { + this.clear(); + } + }, - renderValue: function() { - var value = this.getSelected().map(function(item) { - return item.get('text'); - }), - defaultValue = this.model.has('defaultValue') ? - this.model.get('defaultValue') : - this.model.get('multiple') ? t('all') : t('any'); - return this.isDefaultValue() ? defaultValue : value.join(', '); - }, + restore: function (value) { + if (_.isString(value)) { + value = value.split(','); + } + if (this.choices && value.length > 0) { + var that = this; - isDefaultValue: function() { - var selected = this.getSelected(); - return selected.length === 0; - }, + that.choices.each(function (item) { + item.set('checked', false); + }); + var unknownValues = []; - disable: function() { - this.choices.each(function(item) { - item.set('checked', false); + _.each(value, function (v) { + var cModel = that.choices.findWhere({ id: v }); + if (cModel) { + cModel.set('checked', true); + } else { + unknownValues.push(v); + } }); - BaseFilters.BaseFilterView.prototype.disable.apply(this, arguments); - }, - - - restoreFromQuery: function(q) { - var param = _.findWhere(q, { key: this.model.get('property') }); - - if (this.choices) { - this.choices.forEach(function(item) { - if (item.get('id')[0] === '!') { - var x = _.findWhere(q, { key: item.get('id').substr(1) }); - if (item.get('id').indexOf('=') >= 0) { - var key = item.get('id').split('=')[0].substr(1); - var value = item.get('id').split('=')[1]; - x = _.findWhere(q, { key: key, value: value }); - } - if (x == null) { - return; - } - if (!param) { - param = { value: item.get('id') }; - } else { - param.value += ',' + item.get('id'); - } - } - }); - } - if (param && param.value) { - this.model.set('enabled', true); - this.restore(param.value, param); - } else { - this.clear(); - } - }, + value = _.difference(value, unknownValues); + this.model.set({ + value: value, + enabled: true + }); - restore: function(value) { - if (_.isString(value)) { - value = value.split(','); - } + this.render(); + } else { + this.clear(); + } + }, - if (this.choices && value.length > 0) { - var that = this; - that.choices.each(function(item) { - item.set('checked', false); - }); + clear: function () { + if (this.choices) { + this.choices.each(function (item) { + item.set('checked', false); + }); + } + this.model.unset('value'); + this.detailsView.render(); + if (this.detailsView.updateCurrent) { + this.detailsView.updateCurrent(0); + } + }, - var unknownValues = []; - _.each(value, function(v) { - var cModel = that.choices.findWhere({ id: v }); - if (cModel) { - cModel.set('checked', true); + formatValue: function () { + var q = {}; + if (this.model.has('property') && this.model.has('value') && this.model.get('value').length > 0) { + var opposite = _.filter(this.model.get('value'), function (item) { + return item[0] === '!'; + }); + if (opposite.length > 0) { + opposite.forEach(function (item) { + if (item.indexOf('=') >= 0) { + var paramValue = item.split('='); + q[paramValue[0].substr(1)] = paramValue[1]; } else { - unknownValues.push(v); + q[item.substr(1)] = false; } }); - - value = _.difference(value, unknownValues); - - this.model.set({ - value: value, - enabled: true - }); - - this.render(); } else { - this.clear(); - } - }, - - - clear: function() { - if (this.choices) { - this.choices.each(function(item) { - item.set('checked', false); - }); + q[this.model.get('property')] = this.model.get('value').join(','); } - this.model.unset('value'); - this.detailsView.render(); - if (this.detailsView.updateCurrent) { - this.detailsView.updateCurrent(0); - } - }, - - - formatValue: function() { - var q = {}; - if (this.model.has('property') && this.model.has('value') && this.model.get('value').length > 0) { - var opposite = _.filter(this.model.get('value'), function(item) { - return item[0] === '!'; - }); - if (opposite.length > 0) { - opposite.forEach(function(item) { - if (item.indexOf('=') >= 0) { - var paramValue = item.split('='); - q[paramValue[0].substr(1)] = paramValue[1]; - } else { - q[item.substr(1)] = false; - } - }); - } else { - q[this.model.get('property')] = this.model.get('value').join(','); - } - } - return q; } + return q; + } - }); +}); +/* + * Export public classes + */ - /* - * Export public classes - */ +export default { + DetailsChoiceFilterView: DetailsChoiceFilterView, + ChoiceFilterView: ChoiceFilterView +}; - return { - DetailsChoiceFilterView: DetailsChoiceFilterView, - ChoiceFilterView: ChoiceFilterView - }; -}); diff --git a/server/sonar-web/src/main/js/components/navigator/filters/favorite-filters.js b/server/sonar-web/src/main/js/components/navigator/filters/favorite-filters.js index e623a83b276..fcf16bb0f0b 100644 --- a/server/sonar-web/src/main/js/components/navigator/filters/favorite-filters.js +++ b/server/sonar-web/src/main/js/components/navigator/filters/favorite-filters.js @@ -1,84 +1,82 @@ -define([ - 'jquery', - './base-filters', - './choice-filters', - '../templates' -], function ($, BaseFilters, ChoiceFilters) { +import $ from 'jquery'; +import _ from 'underscore'; +import BaseFilters from './base-filters'; +import ChoiceFilters from './choice-filters'; +import '../templates'; - var DetailsFavoriteFilterView = BaseFilters.DetailsFilterView.extend({ - template: Templates['favorite-details-filter'], +var DetailsFavoriteFilterView = BaseFilters.DetailsFilterView.extend({ + template: Templates['favorite-details-filter'], - events: { - 'click label[data-id]': 'applyFavorite', - 'click .manage label': 'manage' - }, + events: { + 'click label[data-id]': 'applyFavorite', + 'click .manage label': 'manage' + }, - applyFavorite: function(e) { - var id = $(e.target).data('id'); - window.location = baseUrl + this.model.get('favoriteUrl') + '/' + id; - }, + applyFavorite: function (e) { + var id = $(e.target).data('id'); + window.location = baseUrl + this.model.get('favoriteUrl') + '/' + id; + }, - manage: function() { - window.location = baseUrl + this.model.get('manageUrl'); - }, + manage: function () { + window.location = baseUrl + this.model.get('manageUrl'); + }, - serializeData: function() { - var choices = this.model.get('choices'), - choicesArray = - _.sortBy( - _.map(choices, function (v, k) { - return { v: v, k: k }; - }), - 'v'); + serializeData: function () { + var choices = this.model.get('choices'), + choicesArray = + _.sortBy( + _.map(choices, function (v, k) { + return { v: v, k: k }; + }), + 'v'); - return _.extend({}, this.model.toJSON(), { - choicesArray: choicesArray - }); - } - - }); + return _.extend({}, this.model.toJSON(), { + choicesArray: choicesArray + }); + } +}); - var FavoriteFilterView = ChoiceFilters.ChoiceFilterView.extend({ - template: Templates['favorite-filter'], - className: 'navigator-filter navigator-filter-favorite', +var FavoriteFilterView = ChoiceFilters.ChoiceFilterView.extend({ + template: Templates['favorite-filter'], + className: 'navigator-filter navigator-filter-favorite', - initialize: function() { - ChoiceFilters.ChoiceFilterView.prototype.initialize.call(this, { - detailsView: DetailsFavoriteFilterView - }); - }, + initialize: function () { + ChoiceFilters.ChoiceFilterView.prototype.initialize.call(this, { + detailsView: DetailsFavoriteFilterView + }); + }, - renderValue: function() { - return ''; - }, + renderValue: function () { + return ''; + }, - renderInput: function() {}, + renderInput: function () { + }, - isDefaultValue: function() { - return false; - } + isDefaultValue: function () { + return false; + } - }); +}); +/* + * Export public classes + */ - /* - * Export public classes - */ +export default { + DetailsFavoriteFilterView: DetailsFavoriteFilterView, + FavoriteFilterView: FavoriteFilterView +}; - return { - DetailsFavoriteFilterView: DetailsFavoriteFilterView, - FavoriteFilterView: FavoriteFilterView - }; -}); diff --git a/server/sonar-web/src/main/js/components/navigator/filters/filter-bar.js b/server/sonar-web/src/main/js/components/navigator/filters/filter-bar.js index f63e2dbad83..17419cf5042 100644 --- a/server/sonar-web/src/main/js/components/navigator/filters/filter-bar.js +++ b/server/sonar-web/src/main/js/components/navigator/filters/filter-bar.js @@ -1,179 +1,175 @@ -define( - [ - 'jquery', - './base-filters', - './more-criteria-filters', - './favorite-filters' - ], - function ($, BaseFilters, MoreCriteriaFilters) { - - return Marionette.CompositeView.extend({ - childViewContainer: '.navigator-filters-list', - - - collectionEvents: { - 'change:enabled': 'changeEnabled' - }, - - - getChildView: function (item) { - return item.get('type') || BaseFilters.BaseFilterView; - }, - - - childViewOptions: function () { - return { - filterBarView: this, - app: this.options.app - }; - }, - - - initialize: function () { - Marionette.CompositeView.prototype.initialize.apply(this, arguments); - - var that = this; - $('body').on('click', function () { - that.hideDetails(); - }); - this.addMoreCriteriaFilter(); - - key.filter = function (e) { - var r = true, - el = jQuery(e.target), - box = el.closest('.navigator-filter-details-inner'), - tabbableSet = box.find(':tabbable'), - isElFocusable = el.is(':input') || el.is('a'), - isInsideDialog = el.closest('.ui-dialog').length > 0; - if (isElFocusable) { - if (!isInsideDialog && (e.keyCode === 9 || e.keyCode === 27)) { - r = tabbableSet.index(el) >= tabbableSet.length - 1; - } else { - r = false; - } - } - return r; - }; - key('tab', 'list', function() { - key.setScope('filters'); - that.selectFirst(); - return false; - }); - key('shift+tab', 'filters', function() { - that.selectPrev(); - return false; - }); - key('tab', 'filters', function() { - that.selectNext(); - return false; - }); - key('escape', 'filters', function() { - that.hideDetails(); - this.selected = -1; - key.setScope('list'); - }); - }, - - - getEnabledFilters: function() { - return this.$(this.childViewContainer).children() - .not('.navigator-filter-disabled') - .not('.navigator-filter-inactive') - .not('.navigator-filter-favorite'); - }, - - - selectFirst: function() { - this.selected = -1; - this.selectNext(); - }, - - - selectPrev: function() { - var filters = this.getEnabledFilters(); - if (this.selected > 0) { - filters.eq(this.selected).blur(); - this.selected--; - filters.eq(this.selected).click(); - this.$('.navigator-filter-submit').blur(); - } - }, - - - selectNext: function() { - var filters = this.getEnabledFilters(); - if (this.selected < filters.length - 1) { - filters.eq(this.selected).blur(); - this.selected++; - filters.eq(this.selected).click(); - } else { - this.selected = filters.length; - this.hideDetails(); - this.$('.navigator-filter-submit').focus(); - } - }, - - - addMoreCriteriaFilter: function() { - var disabledFilters = this.collection.where({ enabled: false }); - if (disabledFilters.length > 0) { - this.moreCriteriaFilter = new BaseFilters.Filter({ - type: MoreCriteriaFilters.MoreCriteriaFilterView, - enabled: true, - optional: false, - filters: disabledFilters - }); - this.collection.add(this.moreCriteriaFilter); - } - }, - - - onAddChild: function (childView) { - if (childView.model.get('type') === MoreCriteriaFilters.FavoriteFilterView) { - jQuery('.navigator-header').addClass('navigator-header-favorite'); - } - }, - - - restoreFromQuery: function (q) { - this.collection.each(function (item) { - item.set('enabled', !item.get('optional')); - item.view.clear(); - item.view.restoreFromQuery(q); - }); - }, - - - hideDetails: function () { - if (_.isObject(this.showedView)) { - this.showedView.hideDetails(); - } - }, - - - enableFilter: function (id) { - var filter = this.collection.get(id), - filterView = filter.view; - - filterView.$el.detach().insertBefore(this.$('.navigator-filter-more-criteria')); - filter.set('enabled', true); - filterView.showDetails(); - }, - - - changeEnabled: function () { - var disabledFilters = _.reject(this.collection.where({ enabled: false }), function (filter) { - return filter.get('type') === MoreCriteriaFilters.MoreCriteriaFilterView; - }); - - if (disabledFilters.length === 0) { - this.moreCriteriaFilter.set({ enabled: false }, { silent: true }); - } else { - this.moreCriteriaFilter.set({ enabled: true }, { silent: true }); - } - this.moreCriteriaFilter.set('filters', disabledFilters); - } +import $ from 'jquery'; +import _ from 'underscore'; +import Marionette from 'backbone.marionette'; +import BaseFilters from './base-filters'; +import MoreCriteriaFilters from './more-criteria-filters'; +import './favorite-filters'; + +export default Marionette.CompositeView.extend({ + childViewContainer: '.navigator-filters-list', + + + collectionEvents: { + 'change:enabled': 'changeEnabled' + }, + + + getChildView: function (item) { + return item.get('type') || BaseFilters.BaseFilterView; + }, + + + childViewOptions: function () { + return { + filterBarView: this, + app: this.options.app + }; + }, + + initialize: function () { + Marionette.CompositeView.prototype.initialize.apply(this, arguments); + + var that = this; + $('body').on('click', function () { + that.hideDetails(); + }); + this.addMoreCriteriaFilter(); + + key.filter = function (e) { + var r = true, + el = $(e.target), + box = el.closest('.navigator-filter-details-inner'), + tabbableSet = box.find(':tabbable'), + isElFocusable = el.is(':input') || el.is('a'), + isInsideDialog = el.closest('.ui-dialog').length > 0; + if (isElFocusable) { + if (!isInsideDialog && (e.keyCode === 9 || e.keyCode === 27)) { + r = tabbableSet.index(el) >= tabbableSet.length - 1; + } else { + r = false; + } + } + return r; + }; + key('tab', 'list', function () { + key.setScope('filters'); + that.selectFirst(); + return false; + }); + key('shift+tab', 'filters', function () { + that.selectPrev(); + return false; + }); + key('tab', 'filters', function () { + that.selectNext(); + return false; + }); + key('escape', 'filters', function () { + that.hideDetails(); + this.selected = -1; + key.setScope('list'); + }); + }, + + + getEnabledFilters: function () { + return this.$(this.childViewContainer).children() + .not('.navigator-filter-disabled') + .not('.navigator-filter-inactive') + .not('.navigator-filter-favorite'); + }, + + + selectFirst: function () { + this.selected = -1; + this.selectNext(); + }, + + + selectPrev: function () { + var filters = this.getEnabledFilters(); + if (this.selected > 0) { + filters.eq(this.selected).blur(); + this.selected--; + filters.eq(this.selected).click(); + this.$('.navigator-filter-submit').blur(); + } + }, + + + selectNext: function () { + var filters = this.getEnabledFilters(); + if (this.selected < filters.length - 1) { + filters.eq(this.selected).blur(); + this.selected++; + filters.eq(this.selected).click(); + } else { + this.selected = filters.length; + this.hideDetails(); + this.$('.navigator-filter-submit').focus(); + } + }, + + + addMoreCriteriaFilter: function () { + var disabledFilters = this.collection.where({ enabled: false }); + if (disabledFilters.length > 0) { + this.moreCriteriaFilter = new BaseFilters.Filter({ + type: MoreCriteriaFilters.MoreCriteriaFilterView, + enabled: true, + optional: false, + filters: disabledFilters }); + this.collection.add(this.moreCriteriaFilter); + } + }, + + + onAddChild: function (childView) { + if (childView.model.get('type') === MoreCriteriaFilters.FavoriteFilterView) { + $('.navigator-header').addClass('navigator-header-favorite'); + } + }, + + + restoreFromQuery: function (q) { + this.collection.each(function (item) { + item.set('enabled', !item.get('optional')); + item.view.clear(); + item.view.restoreFromQuery(q); + }); + }, + + hideDetails: function () { + if (_.isObject(this.showedView)) { + this.showedView.hideDetails(); + } + }, + + + enableFilter: function (id) { + var filter = this.collection.get(id), + filterView = filter.view; + + filterView.$el.detach().insertBefore(this.$('.navigator-filter-more-criteria')); + filter.set('enabled', true); + filterView.showDetails(); + }, + + + changeEnabled: function () { + var disabledFilters = _.reject(this.collection.where({ enabled: false }), function (filter) { + return filter.get('type') === MoreCriteriaFilters.MoreCriteriaFilterView; }); + + if (disabledFilters.length === 0) { + this.moreCriteriaFilter.set({ enabled: false }, { silent: true }); + } else { + this.moreCriteriaFilter.set({ enabled: true }, { silent: true }); + } + this.moreCriteriaFilter.set('filters', disabledFilters); + } + +}); diff --git a/server/sonar-web/src/main/js/components/navigator/filters/metric-filters.js b/server/sonar-web/src/main/js/components/navigator/filters/metric-filters.js index a746e90f75e..0125f3abf50 100644 --- a/server/sonar-web/src/main/js/components/navigator/filters/metric-filters.js +++ b/server/sonar-web/src/main/js/components/navigator/filters/metric-filters.js @@ -1,198 +1,196 @@ -define([ - 'jquery', - './base-filters', - '../templates' -], function ($, BaseFilters) { - - var DetailsMetricFilterView = BaseFilters.DetailsFilterView.extend({ - template: Templates['metric-filter'], - - - events: { - 'change :input': 'inputChanged' - }, - - - inputChanged: function() { - var metric = this.$('[name=metric]').val(), - isDifferentialMetric = metric.indexOf('new_') === 0, - periodSelect = this.$('[name=period]'), - period = periodSelect.val(), - optionZero = periodSelect.children('[value="0"]'), - value = { - metric: metric, - metricText: this.$('[name=metric] option:selected').text(), - period: period, - periodText: this.$('[name=period] option:selected').text(), - op: this.$('[name=op]').val(), - opText: this.$('[name=op] option:selected').text(), - val: this.$('[name=val]').val(), - valText: this.$('[name=val]').originalVal() - }; - - if (isDifferentialMetric) { - optionZero.remove(); - if (period === '0') { - period = '1'; - } - } else { - if (optionZero.length === 0) { - periodSelect.prepend(this.periodZeroOption); - } +import $ from 'jquery'; +import _ from 'underscore'; +import BaseFilters from './base-filters'; +import '../templates'; + +var DetailsMetricFilterView = BaseFilters.DetailsFilterView.extend({ + template: Templates['metric-filter'], + + + events: { + 'change :input': 'inputChanged' + }, + + + inputChanged: function () { + var metric = this.$('[name=metric]').val(), + isDifferentialMetric = metric.indexOf('new_') === 0, + periodSelect = this.$('[name=period]'), + period = periodSelect.val(), + optionZero = periodSelect.children('[value="0"]'), + value = { + metric: metric, + metricText: this.$('[name=metric] option:selected').text(), + period: period, + periodText: this.$('[name=period] option:selected').text(), + op: this.$('[name=op]').val(), + opText: this.$('[name=op] option:selected').text(), + val: this.$('[name=val]').val(), + valText: this.$('[name=val]').originalVal() + }; + + if (isDifferentialMetric) { + optionZero.remove(); + if (period === '0') { + period = '1'; } - periodSelect.select2('destroy').val(period).select2({ - width: '100%', - minimumResultsForSearch: 100 - }); - - this.updateDataType(value); - this.model.set('value', value); - }, - - - updateDataType: function(value) { - var metric = _.find(window.SS.metrics, function(m) { - return m.metric.name === value.metric; - }); - if (metric) { - this.$('[name=val]').data('type', metric.metric.val_type); - if (metric.metric.val_type === 'WORK_DUR') { - this.$('[name=val]').prop('placeholder', '1d 7h 59min'); - } - if (metric.metric.val_type === 'RATING') { - this.$('[name=val]').prop('placeholder', 'A'); - } + } else { + if (optionZero.length === 0) { + periodSelect.prepend(this.periodZeroOption); } - }, - - - onRender: function() { - var periodZeroLabel = this.$('[name=period]').children('[value="0"]').html(); - this.periodZeroOption = '<option value="0">' + periodZeroLabel + '</option>'; - - var value = this.model.get('value') || {}; - this.$('[name=metric]').val(value.metric).select2({ - width: '100%', - placeholder: window.SS.phrases.metric - }); - this.$('[name=period]').val(value.period || 0).select2({ - width: '100%', - minimumResultsForSearch: 100 - }); - this.$('[name=op]').val(value.op || 'eq').select2({ - width: '60px', - placeholder: '=', - minimumResultsForSearch: 100 - }); - this.updateDataType(value); - this.$('[name=val]').val(value.val); - this.inputChanged(); - }, - - - onShow: function() { - var select = this.$('[name=metric]'); - if (this.model.get('value').metric === '') { - select.select2('open'); - } else { - select.select2('focus'); + } + periodSelect.select2('destroy').val(period).select2({ + width: '100%', + minimumResultsForSearch: 100 + }); + + this.updateDataType(value); + this.model.set('value', value); + }, + + + updateDataType: function (value) { + var metric = _.find(window.SS.metrics, function (m) { + return m.metric.name === value.metric; + }); + if (metric) { + this.$('[name=val]').data('type', metric.metric.val_type); + if (metric.metric.val_type === 'WORK_DUR') { + this.$('[name=val]').prop('placeholder', '1d 7h 59min'); + } + if (metric.metric.val_type === 'RATING') { + this.$('[name=val]').prop('placeholder', 'A'); } } + }, + + + onRender: function () { + var periodZeroLabel = this.$('[name=period]').children('[value="0"]').html(); + this.periodZeroOption = '<option value="0">' + periodZeroLabel + '</option>'; + + var value = this.model.get('value') || {}; + this.$('[name=metric]').val(value.metric).select2({ + width: '100%', + placeholder: window.SS.phrases.metric + }); + this.$('[name=period]').val(value.period || 0).select2({ + width: '100%', + minimumResultsForSearch: 100 + }); + this.$('[name=op]').val(value.op || 'eq').select2({ + width: '60px', + placeholder: '=', + minimumResultsForSearch: 100 + }); + this.updateDataType(value); + this.$('[name=val]').val(value.val); + this.inputChanged(); + }, + + + onShow: function () { + var select = this.$('[name=metric]'); + if (this.model.get('value').metric === '') { + select.select2('open'); + } else { + select.select2('focus'); + } + } - }); - +}); - return BaseFilters.BaseFilterView.extend({ +export default BaseFilters.BaseFilterView.extend({ + + initialize: function () { + BaseFilters.BaseFilterView.prototype.initialize.call(this, { + detailsView: DetailsMetricFilterView + }); + + this.groupMetrics(); + }, + + + groupMetrics: function () { + var metrics = _.map(this.model.get('metrics'), function (metric) { + return metric.metric; + }), + groupedMetrics = + _.sortBy( + _.map( + _.groupBy(metrics, 'domain'), + function (metricList, domain) { + return { + domain: domain, + metrics: _.sortBy(metricList, 'short_name') + }; + }), + 'domain' + ); + this.model.set('groupedMetrics', groupedMetrics); + }, + + + renderValue: function () { + return this.isDefaultValue() ? + window.SS.phrases.notSet : + this.model.get('value').metricText + ' ' + this.model.get('value').opText + ' ' + + this.model.get('value').valText; + }, + + + renderInput: function () { + var that = this, + value = this.model.get('value'); + + if (_.isObject(value) && value.metric && value.op && (value.val != null)) { + _.each(['metric', 'period', 'op', 'val'], function (key) { + var v = value[key]; + if (key === 'period' && v === '0') { + v = ''; + } - initialize: function() { - BaseFilters.BaseFilterView.prototype.initialize.call(this, { - detailsView: DetailsMetricFilterView + $('<input>') + .prop('name', that.model.get('property') + '_' + key) + .prop('type', 'hidden') + .css('display', 'none') + .val(v) + .appendTo(that.$el); }); + } + }, - this.groupMetrics(); - }, - - - groupMetrics: function() { - var metrics = _.map(this.model.get('metrics'), function (metric) { - return metric.metric; - }), - groupedMetrics = - _.sortBy( - _.map( - _.groupBy(metrics, 'domain'), - function (metricList, domain) { - return { - domain: domain, - metrics: _.sortBy(metricList, 'short_name') - }; - }), - 'domain' - ); - this.model.set('groupedMetrics', groupedMetrics); - }, - - - renderValue: function() { - return this.isDefaultValue() ? - window.SS.phrases.notSet : - this.model.get('value').metricText + ' ' + this.model.get('value').opText + ' ' + - this.model.get('value').valText; - }, - - - renderInput: function() { - var that = this, - value = this.model.get('value'); - - if (_.isObject(value) && value.metric && value.op && (value.val != null)) { - _.each(['metric', 'period', 'op', 'val'], function(key) { - var v = value[key]; - if (key === 'period' && v === '0') { - v = ''; - } - - $('<input>') - .prop('name', that.model.get('property') + '_' + key) - .prop('type', 'hidden') - .css('display', 'none') - .val(v) - .appendTo(that.$el); - }); - } - }, + isDefaultValue: function () { + var value = this.model.get('value'); + if (!_.isObject(value)) { + return true; + } + return !(value.metric && value.op && (value.val != null)); + }, - isDefaultValue: function() { - var value = this.model.get('value'); - if (!_.isObject(value)) { - return true; - } - return !(value.metric && value.op && (value.val != null)); - }, + restoreFromQuery: function (q) { + var that = this, + value = {}; + _.each(['metric', 'period', 'op', 'val'], function (p) { + var property = that.model.get('property') + '_' + p, + pValue = _.findWhere(q, { key: property }); - restoreFromQuery: function(q) { - var that = this, - value = {}; - _.each(['metric', 'period', 'op', 'val'], function(p) { - var property = that.model.get('property') + '_' + p, - pValue = _.findWhere(q, { key: property }); + if (pValue && pValue.value) { + value[p] = pValue.value; + } + }); - if (pValue && pValue.value) { - value[p] = pValue.value; - } + if (value && value.metric && value.op && (value.val != null)) { + this.model.set({ + value: value, + enabled: true }); - - if (value && value.metric && value.op && (value.val != null)) { - this.model.set({ - value: value, - enabled: true - }); - } } - - }); + } }); + + diff --git a/server/sonar-web/src/main/js/components/navigator/filters/more-criteria-filters.js b/server/sonar-web/src/main/js/components/navigator/filters/more-criteria-filters.js index ffb08db20f4..cab8a35d67a 100644 --- a/server/sonar-web/src/main/js/components/navigator/filters/more-criteria-filters.js +++ b/server/sonar-web/src/main/js/components/navigator/filters/more-criteria-filters.js @@ -1,104 +1,101 @@ -define([ - 'jquery', - './base-filters', - './choice-filters', - '../templates' -], function ($, BaseFilters, ChoiceFilters) { +import $ from 'jquery'; +import _ from 'underscore'; +import ChoiceFilters from './choice-filters'; +import '../templates'; - var DetailsMoreCriteriaFilterView = ChoiceFilters.DetailsChoiceFilterView.extend({ - template: Templates['more-criteria-details-filter'], +var DetailsMoreCriteriaFilterView = ChoiceFilters.DetailsChoiceFilterView.extend({ + template: Templates['more-criteria-details-filter'], - events: { - 'click label[data-id]:not(.inactive)': 'enableFilter' - }, + events: { + 'click label[data-id]:not(.inactive)': 'enableFilter' + }, - enableById: function(id) { - this.model.view.options.filterBarView.enableFilter(id); - this.model.view.hideDetails(); - }, + enableById: function (id) { + this.model.view.options.filterBarView.enableFilter(id); + this.model.view.hideDetails(); + }, - enableByProperty: function(property) { - var filter = _.find(this.model.get('filters'), function(f) { - return f.get('property') === property; - }); - if (filter) { - this.enableById(filter.cid); - } - }, + enableByProperty: function (property) { + var filter = _.find(this.model.get('filters'), function (f) { + return f.get('property') === property; + }); + if (filter) { + this.enableById(filter.cid); + } + }, - enableFilter: function(e) { - var id = $(e.target).data('id'); - this.enableById(id); - this.updateCurrent(0); - }, + enableFilter: function (e) { + var id = $(e.target).data('id'); + this.enableById(id); + this.updateCurrent(0); + }, - selectCurrent: function() { - this.$('label').eq(this.currentChoice).click(); - }, + selectCurrent: function () { + this.$('label').eq(this.currentChoice).click(); + }, - serializeData: function() { - var filters = this.model.get('filters').map(function(filter) { - return _.extend(filter.toJSON(), { id: filter.cid }); - }), - getName = function(filter) { - return filter.name; - }, - uniqueFilters = _.unique(filters, getName), - sortedFilters = _.sortBy(uniqueFilters, getName); - return _.extend(this.model.toJSON(), { filters: sortedFilters }); - } + serializeData: function () { + var filters = this.model.get('filters').map(function (filter) { + return _.extend(filter.toJSON(), { id: filter.cid }); + }), + getName = function (filter) { + return filter.name; + }, + uniqueFilters = _.unique(filters, getName), + sortedFilters = _.sortBy(uniqueFilters, getName); + return _.extend(this.model.toJSON(), { filters: sortedFilters }); + } - }); +}); +var MoreCriteriaFilterView = ChoiceFilters.ChoiceFilterView.extend({ + template: Templates['more-criteria-filter'], + className: 'navigator-filter navigator-filter-more-criteria', - var MoreCriteriaFilterView = ChoiceFilters.ChoiceFilterView.extend({ - template: Templates['more-criteria-filter'], - className: 'navigator-filter navigator-filter-more-criteria', + initialize: function () { + ChoiceFilters.ChoiceFilterView.prototype.initialize.call(this, { + detailsView: DetailsMoreCriteriaFilterView + }); + }, - initialize: function() { - ChoiceFilters.ChoiceFilterView.prototype.initialize.call(this, { - detailsView: DetailsMoreCriteriaFilterView - }); - }, + renderValue: function () { + return ''; + }, - renderValue: function() { - return ''; - }, + renderInput: function () { + }, - renderInput: function() {}, + renderBase: function () { + ChoiceFilters.ChoiceFilterView.prototype.renderBase.call(this); + this.$el.prop('title', ''); + }, - renderBase: function() { - ChoiceFilters.ChoiceFilterView.prototype.renderBase.call(this); - this.$el.prop('title', ''); - }, + isDefaultValue: function () { + return false; + } - isDefaultValue: function() { - return false; - } - - }); +}); +/* + * Export public classes + */ - /* - * Export public classes - */ +export default { + DetailsMoreCriteriaFilterView: DetailsMoreCriteriaFilterView, + MoreCriteriaFilterView: MoreCriteriaFilterView +}; - return { - DetailsMoreCriteriaFilterView: DetailsMoreCriteriaFilterView, - MoreCriteriaFilterView: MoreCriteriaFilterView - }; -}); diff --git a/server/sonar-web/src/main/js/components/navigator/filters/range-filters.js b/server/sonar-web/src/main/js/components/navigator/filters/range-filters.js index 09d1c447f11..6f5d9b7d8d0 100644 --- a/server/sonar-web/src/main/js/components/navigator/filters/range-filters.js +++ b/server/sonar-web/src/main/js/components/navigator/filters/range-filters.js @@ -1,208 +1,204 @@ -define([ - 'jquery', - './base-filters', - '../templates' -], function ($, BaseFilters) { +import $ from 'jquery'; +import _ from 'underscore'; +import BaseFilters from './base-filters'; +import '../templates'; - var DetailsRangeFilterView = BaseFilters.DetailsFilterView.extend({ - template: Templates['range-filter'], +var DetailsRangeFilterView = BaseFilters.DetailsFilterView.extend({ + template: Templates['range-filter'], - events: { - 'change input': 'change' - }, + events: { + 'change input': 'change' + }, - change: function() { - var value = {}, - valueFrom = this.$('input').eq(0).val(), - valueTo = this.$('input').eq(1).val(); + change: function () { + var value = {}, + valueFrom = this.$('input').eq(0).val(), + valueTo = this.$('input').eq(1).val(); - if (valueFrom.length > 0) { - value[this.model.get('propertyFrom')] = valueFrom; - } - - if (valueTo.length > 0) { - value[this.model.get('propertyTo')] = valueTo; - } + if (valueFrom.length > 0) { + value[this.model.get('propertyFrom')] = valueFrom; + } - this.model.set('value', value); - }, + if (valueTo.length > 0) { + value[this.model.get('propertyTo')] = valueTo; + } + this.model.set('value', value); + }, - populateInputs: function() { - var value = this.model.get('value'), - propertyFrom = this.model.get('propertyFrom'), - propertyTo = this.model.get('propertyTo'), - valueFrom = _.isObject(value) && value[propertyFrom], - valueTo = _.isObject(value) && value[propertyTo]; - this.$('input').eq(0).val(valueFrom || ''); - this.$('input').eq(1).val(valueTo || ''); - }, + populateInputs: function () { + var value = this.model.get('value'), + propertyFrom = this.model.get('propertyFrom'), + propertyTo = this.model.get('propertyTo'), + valueFrom = _.isObject(value) && value[propertyFrom], + valueTo = _.isObject(value) && value[propertyTo]; + this.$('input').eq(0).val(valueFrom || ''); + this.$('input').eq(1).val(valueTo || ''); + }, - onShow: function() { - this.$(':input:first').focus(); - } - }); + onShow: function () { + this.$(':input:first').focus(); + } +}); - var RangeFilterView = BaseFilters.BaseFilterView.extend({ +var RangeFilterView = BaseFilters.BaseFilterView.extend({ - initialize: function() { - BaseFilters.BaseFilterView.prototype.initialize.call(this, { - detailsView: DetailsRangeFilterView - }); - }, + initialize: function () { + BaseFilters.BaseFilterView.prototype.initialize.call(this, { + detailsView: DetailsRangeFilterView + }); + }, - renderValue: function() { - if (!this.isDefaultValue()) { - var value = _.values(this.model.get('value')); - return value.join(' — '); - } else { - return window.SS.phrases.any; + renderValue: function () { + if (!this.isDefaultValue()) { + var value = _.values(this.model.get('value')); + return value.join(' — '); + } else { + return window.SS.phrases.any; + } + }, + + + renderInput: function () { + var value = this.model.get('value'), + propertyFrom = this.model.get('propertyFrom'), + propertyTo = this.model.get('propertyTo'), + valueFrom = _.isObject(value) && value[propertyFrom], + valueTo = _.isObject(value) && value[propertyTo]; + + $('<input>') + .prop('name', propertyFrom) + .prop('type', 'hidden') + .css('display', 'none') + .val(valueFrom || '') + .appendTo(this.$el); + + $('<input>') + .prop('name', propertyTo) + .prop('type', 'hidden') + .css('display', 'none') + .val(valueTo || '') + .appendTo(this.$el); + }, + + + isDefaultValue: function () { + var value = this.model.get('value'), + propertyFrom = this.model.get('propertyFrom'), + propertyTo = this.model.get('propertyTo'), + valueFrom = _.isObject(value) && value[propertyFrom], + valueTo = _.isObject(value) && value[propertyTo]; + + return !valueFrom && !valueTo; + }, + + + restoreFromQuery: function (q) { + var paramFrom = _.findWhere(q, { key: this.model.get('propertyFrom') }), + paramTo = _.findWhere(q, { key: this.model.get('propertyTo') }), + value = {}; + + if ((paramFrom && paramFrom.value) || (paramTo && paramTo.value)) { + if (paramFrom && paramFrom.value) { + value[this.model.get('propertyFrom')] = paramFrom.value; } - }, - - - renderInput: function() { - var value = this.model.get('value'), - propertyFrom = this.model.get('propertyFrom'), - propertyTo = this.model.get('propertyTo'), - valueFrom = _.isObject(value) && value[propertyFrom], - valueTo = _.isObject(value) && value[propertyTo]; - - $('<input>') - .prop('name', propertyFrom) - .prop('type', 'hidden') - .css('display', 'none') - .val(valueFrom || '') - .appendTo(this.$el); - - $('<input>') - .prop('name', propertyTo) - .prop('type', 'hidden') - .css('display', 'none') - .val(valueTo || '') - .appendTo(this.$el); - }, - - - isDefaultValue: function() { - var value = this.model.get('value'), - propertyFrom = this.model.get('propertyFrom'), - propertyTo = this.model.get('propertyTo'), - valueFrom = _.isObject(value) && value[propertyFrom], - valueTo = _.isObject(value) && value[propertyTo]; - - return !valueFrom && !valueTo; - }, - - - restoreFromQuery: function(q) { - var paramFrom = _.findWhere(q, { key: this.model.get('propertyFrom') }), - paramTo = _.findWhere(q, { key: this.model.get('propertyTo') }), - value = {}; - - if ((paramFrom && paramFrom.value) || (paramTo && paramTo.value)) { - if (paramFrom && paramFrom.value) { - value[this.model.get('propertyFrom')] = paramFrom.value; - } - - if (paramTo && paramTo.value) { - value[this.model.get('propertyTo')] = paramTo.value; - } - this.model.set({ - value: value, - enabled: true - }); - - this.detailsView.populateInputs(); + if (paramTo && paramTo.value) { + value[this.model.get('propertyTo')] = paramTo.value; } - }, + this.model.set({ + value: value, + enabled: true + }); + + this.detailsView.populateInputs(); + } + }, - restore: function(value) { - if (this.choices && this.selection && value.length > 0) { - var that = this; - this.choices.add(this.selection.models); - this.selection.reset([]); - _.each(value, function(v) { - var cModel = that.choices.findWhere({ id: v }); + restore: function (value) { + if (this.choices && this.selection && value.length > 0) { + var that = this; + this.choices.add(this.selection.models); + this.selection.reset([]); - if (cModel) { - that.selection.add(cModel); - that.choices.remove(cModel); - } - }); + _.each(value, function (v) { + var cModel = that.choices.findWhere({ id: v }); - this.detailsView.updateLists(); + if (cModel) { + that.selection.add(cModel); + that.choices.remove(cModel); + } + }); - this.model.set({ - value: value, - enabled: true - }); - } - }, + this.detailsView.updateLists(); + this.model.set({ + value: value, + enabled: true + }); + } + }, - formatValue: function() { - return this.model.get('value'); - }, + formatValue: function () { + return this.model.get('value'); + }, - clear: function() { - this.model.unset('value'); - this.detailsView.render(); - } - }); + clear: function () { + this.model.unset('value'); + this.detailsView.render(); + } +}); - var DateRangeFilterView = RangeFilterView.extend({ +var DateRangeFilterView = RangeFilterView.extend({ - render: function() { - RangeFilterView.prototype.render.apply(this, arguments); - this.detailsView.$('input') - .prop('placeholder', '1970-01-31') - .datepicker({ - dateFormat: 'yy-mm-dd', - changeMonth: true, - changeYear: true - }) - .on('change', function () { - jQuery(this).datepicker('setDate', jQuery(this).val()); - }); - }, + render: function () { + RangeFilterView.prototype.render.apply(this, arguments); + this.detailsView.$('input') + .prop('placeholder', '1970-01-31') + .datepicker({ + dateFormat: 'yy-mm-dd', + changeMonth: true, + changeYear: true + }) + .on('change', function () { + $(this).datepicker('setDate', $(this).val()); + }); + }, - renderValue: function() { - if (!this.isDefaultValue()) { - var value = _.values(this.model.get('value')); - return value.join(' — '); - } else { - return window.SS.phrases.anytime; - } + renderValue: function () { + if (!this.isDefaultValue()) { + var value = _.values(this.model.get('value')); + return value.join(' — '); + } else { + return window.SS.phrases.anytime; } + } - }); +}); +/* + * Export public classes + */ - /* - * Export public classes - */ +export default { + RangeFilterView: RangeFilterView, + DateRangeFilterView: DateRangeFilterView +}; - return { - RangeFilterView: RangeFilterView, - DateRangeFilterView: DateRangeFilterView - }; -}); diff --git a/server/sonar-web/src/main/js/components/navigator/filters/string-filters.js b/server/sonar-web/src/main/js/components/navigator/filters/string-filters.js index 20512c322dd..f1145c3732e 100644 --- a/server/sonar-web/src/main/js/components/navigator/filters/string-filters.js +++ b/server/sonar-web/src/main/js/components/navigator/filters/string-filters.js @@ -1,81 +1,79 @@ -define([ - 'jquery', - './base-filters', - '../templates' -], function ($, BaseFilters) { +import $ from 'jquery'; +import _ from 'underscore'; +import BaseFilters from './base-filters'; +import '../templates'; - var DetailsStringFilterView = BaseFilters.DetailsFilterView.extend({ - template: Templates['string-filter'], +var DetailsStringFilterView = BaseFilters.DetailsFilterView.extend({ + template: Templates['string-filter'], - events: { - 'change input': 'change' - }, + events: { + 'change input': 'change' + }, - change: function(e) { - this.model.set('value', $(e.target).val()); - }, + change: function (e) { + this.model.set('value', $(e.target).val()); + }, - onShow: function() { - BaseFilters.DetailsFilterView.prototype.onShow.apply(this, arguments); - this.$(':input').focus(); - }, + onShow: function () { + BaseFilters.DetailsFilterView.prototype.onShow.apply(this, arguments); + this.$(':input').focus(); + }, - serializeData: function() { - return _.extend({}, this.model.toJSON(), { - value: this.model.get('value') || '' - }); - } + serializeData: function () { + return _.extend({}, this.model.toJSON(), { + value: this.model.get('value') || '' + }); + } - }); +}); +export default BaseFilters.BaseFilterView.extend({ - return BaseFilters.BaseFilterView.extend({ + initialize: function () { + BaseFilters.BaseFilterView.prototype.initialize.call(this, { + detailsView: DetailsStringFilterView + }); + }, - initialize: function() { - BaseFilters.BaseFilterView.prototype.initialize.call(this, { - detailsView: DetailsStringFilterView - }); - }, + renderValue: function () { + return this.isDefaultValue() ? '—' : this.model.get('value'); + }, - renderValue: function() { - return this.isDefaultValue() ? '—' : this.model.get('value'); - }, + renderInput: function () { + $('<input>') + .prop('name', this.model.get('property')) + .prop('type', 'hidden') + .css('display', 'none') + .val(this.model.get('value') || '') + .appendTo(this.$el); + }, - renderInput: function() { - $('<input>') - .prop('name', this.model.get('property')) - .prop('type', 'hidden') - .css('display', 'none') - .val(this.model.get('value') || '') - .appendTo(this.$el); - }, + isDefaultValue: function () { + return !this.model.get('value'); + }, - isDefaultValue: function() { - return !this.model.get('value'); - }, + restore: function (value) { + this.model.set({ + value: value, + enabled: true + }); + }, - restore: function(value) { - this.model.set({ - value: value, - enabled: true - }); - }, + clear: function () { + this.model.unset('value'); + this.detailsView.render(); + } - clear: function() { - this.model.unset('value'); - this.detailsView.render(); - } +}); - }); -}); diff --git a/server/sonar-web/src/main/js/components/navigator/models/facet.js b/server/sonar-web/src/main/js/components/navigator/models/facet.js index b154fb58c7f..ab7486a9a10 100644 --- a/server/sonar-web/src/main/js/components/navigator/models/facet.js +++ b/server/sonar-web/src/main/js/components/navigator/models/facet.js @@ -1,20 +1,20 @@ -define(function () { +import Backbone from 'backbone'; - return Backbone.Model.extend({ - idAttribute: 'property', +export default Backbone.Model.extend({ + idAttribute: 'property', - defaults: { - enabled: false - }, + defaults: { + enabled: false + }, - getValues: function () { - return this.get('values') || []; - }, - - toggle: function () { - var enabled = this.get('enabled'); - this.set({ enabled: !enabled }); - } - }); + getValues: function () { + return this.get('values') || []; + }, + toggle: function () { + var enabled = this.get('enabled'); + this.set({ enabled: !enabled }); + } }); + + diff --git a/server/sonar-web/src/main/js/components/navigator/models/facets.js b/server/sonar-web/src/main/js/components/navigator/models/facets.js index 730dabe7054..482783957b5 100644 --- a/server/sonar-web/src/main/js/components/navigator/models/facets.js +++ b/server/sonar-web/src/main/js/components/navigator/models/facets.js @@ -1,9 +1,8 @@ -define([ - 'components/navigator/models/facet' -], function (Facet) { - - return Backbone.Collection.extend({ - model: Facet - }); +import Backbone from 'backbone'; +import Facet from 'components/navigator/models/facet'; +export default Backbone.Collection.extend({ + model: Facet }); + + diff --git a/server/sonar-web/src/main/js/components/navigator/models/state.js b/server/sonar-web/src/main/js/components/navigator/models/state.js index b72840991d8..b2977bd1fff 100644 --- a/server/sonar-web/src/main/js/components/navigator/models/state.js +++ b/server/sonar-web/src/main/js/components/navigator/models/state.js @@ -1,53 +1,54 @@ -define(function () { - - return Backbone.Model.extend({ - defaults: function () { - return { - page: 1, - maxResultsReached: false, - query: {}, - facets: [] - }; - }, - - nextPage: function () { - var page = this.get('page'); - this.set({ page: page + 1 }); - }, - - clearQuery: function (query) { - var q = {}; - Object.keys(query).forEach(function (key) { - if (query[key]) { - q[key] = query[key]; - } - }); - return q; - }, - - _areQueriesEqual: function (a, b) { - var equal = Object.keys(a).length === Object.keys(b).length; - Object.keys(a).forEach(function (key) { - equal = equal && a[key] === b[key]; - }); - return equal; - }, - - updateFilter: function (obj, options) { - var oldQuery = this.get('query'), - query = _.extend({}, oldQuery, obj), - opts = _.defaults(options || {}, { force: false }); - query = this.clearQuery(query); - if (opts.force || !this._areQueriesEqual(oldQuery, query)) { - this.setQuery(query); +import _ from 'underscore'; +import Backbone from 'backbone'; + +export default Backbone.Model.extend({ + defaults: function () { + return { + page: 1, + maxResultsReached: false, + query: {}, + facets: [] + }; + }, + + nextPage: function () { + var page = this.get('page'); + this.set({ page: page + 1 }); + }, + + clearQuery: function (query) { + var q = {}; + Object.keys(query).forEach(function (key) { + if (query[key]) { + q[key] = query[key]; } - }, + }); + return q; + }, - setQuery: function (query) { - this.set({ query: query }, { silent: true }); - this.set({ changed: true }); - this.trigger('change:query'); + _areQueriesEqual: function (a, b) { + var equal = Object.keys(a).length === Object.keys(b).length; + Object.keys(a).forEach(function (key) { + equal = equal && a[key] === b[key]; + }); + return equal; + }, + + updateFilter: function (obj, options) { + var oldQuery = this.get('query'), + query = _.extend({}, oldQuery, obj), + opts = _.defaults(options || {}, { force: false }); + query = this.clearQuery(query); + if (opts.force || !this._areQueriesEqual(oldQuery, query)) { + this.setQuery(query); } - }); + }, + setQuery: function (query) { + this.set({ query: query }, { silent: true }); + this.set({ changed: true }); + this.trigger('change:query'); + } }); + + diff --git a/server/sonar-web/src/main/js/components/navigator/router.js b/server/sonar-web/src/main/js/components/navigator/router.js index c7e18f2eb12..4b3071933f5 100644 --- a/server/sonar-web/src/main/js/components/navigator/router.js +++ b/server/sonar-web/src/main/js/components/navigator/router.js @@ -1,27 +1,27 @@ -define(function () { +import Backbone from 'backbone'; - return Backbone.Router.extend({ - routeSeparator: '|', +export default Backbone.Router.extend({ + routeSeparator: '|', - routes: { - '': 'index', - ':query': 'index' - }, + routes: { + '': 'index', + ':query': 'index' + }, - initialize: function (options) { - this.options = options; - this.listenTo(this.options.app.state, 'change:query', this.updateRoute); - }, + initialize: function (options) { + this.options = options; + this.listenTo(this.options.app.state, 'change:query', this.updateRoute); + }, - index: function (query) { - query = this.options.app.controller.parseQuery(query); - this.options.app.state.setQuery(query); - }, - - updateRoute: function () { - var route = this.options.app.controller.getRoute(); - this.navigate(route); - } - }); + index: function (query) { + query = this.options.app.controller.parseQuery(query); + this.options.app.state.setQuery(query); + }, + updateRoute: function () { + var route = this.options.app.controller.getRoute(); + this.navigate(route); + } }); + + diff --git a/server/sonar-web/src/main/js/components/navigator/workspace-header-view.js b/server/sonar-web/src/main/js/components/navigator/workspace-header-view.js index 2b88ab6d2aa..593fe55ae83 100644 --- a/server/sonar-web/src/main/js/components/navigator/workspace-header-view.js +++ b/server/sonar-web/src/main/js/components/navigator/workspace-header-view.js @@ -1,79 +1,80 @@ -define(function () { - - return Marionette.ItemView.extend({ - - collectionEvents: function () { - return { - 'all': 'shouldRender', - 'limitReached': 'flashPagination' - }; - }, - - events: function () { - return { - 'click .js-bulk-change': 'onBulkChangeClick', - 'click .js-reload': 'reload', - 'click .js-next': 'selectNext', - 'click .js-prev': 'selectPrev' - }; - }, - - initialize: function (options) { - this.listenTo(options.app.state, 'change', this.render); - }, - - onRender: function () { - this.$('[data-toggle="tooltip"]').tooltip({ container: 'body', placement: 'bottom' }); - }, - - onBeforeRender: function () { - this.$('[data-toggle="tooltip"]').tooltip('destroy'); - }, - - onDestroy: function () { - this.$('[data-toggle="tooltip"]').tooltip('destroy'); - }, - - onBulkChangeClick: function (e) { - e.preventDefault(); - this.bulkChange(); - }, - - bulkChange: function () { - - }, - - shouldRender: function (event) { - if (event !== 'limitReached') { - this.render(); - } - }, - - reload: function () { - this.options.app.controller.fetchList(); - }, - - selectNext: function () { - this.options.app.controller.selectNext(); - }, - - selectPrev: function () { - this.options.app.controller.selectPrev(); - }, - - flashPagination: function () { - var flashElement = this.$('.search-navigator-header-pagination'); - flashElement.addClass('in'); - setTimeout(function () { - flashElement.removeClass('in'); - }, 2000); - }, - - serializeData: function () { - return _.extend(Marionette.ItemView.prototype.serializeData.apply(this, arguments), { - state: this.options.app.state.toJSON() - }); +import _ from 'underscore'; +import Marionette from 'backbone.marionette'; + +export default Marionette.ItemView.extend({ + + collectionEvents: function () { + return { + 'all': 'shouldRender', + 'limitReached': 'flashPagination' + }; + }, + + events: function () { + return { + 'click .js-bulk-change': 'onBulkChangeClick', + 'click .js-reload': 'reload', + 'click .js-next': 'selectNext', + 'click .js-prev': 'selectPrev' + }; + }, + + initialize: function (options) { + this.listenTo(options.app.state, 'change', this.render); + }, + + onRender: function () { + this.$('[data-toggle="tooltip"]').tooltip({ container: 'body', placement: 'bottom' }); + }, + + onBeforeRender: function () { + this.$('[data-toggle="tooltip"]').tooltip('destroy'); + }, + + onDestroy: function () { + this.$('[data-toggle="tooltip"]').tooltip('destroy'); + }, + + onBulkChangeClick: function (e) { + e.preventDefault(); + this.bulkChange(); + }, + + bulkChange: function () { + + }, + + shouldRender: function (event) { + if (event !== 'limitReached') { + this.render(); } - }); - + }, + + reload: function () { + this.options.app.controller.fetchList(); + }, + + selectNext: function () { + this.options.app.controller.selectNext(); + }, + + selectPrev: function () { + this.options.app.controller.selectPrev(); + }, + + flashPagination: function () { + var flashElement = this.$('.search-navigator-header-pagination'); + flashElement.addClass('in'); + setTimeout(function () { + flashElement.removeClass('in'); + }, 2000); + }, + + serializeData: function () { + return _.extend(Marionette.ItemView.prototype.serializeData.apply(this, arguments), { + state: this.options.app.state.toJSON() + }); + } }); + + diff --git a/server/sonar-web/src/main/js/components/navigator/workspace-list-item-view.js b/server/sonar-web/src/main/js/components/navigator/workspace-list-item-view.js index 2a2e6555c86..8f810a24182 100644 --- a/server/sonar-web/src/main/js/components/navigator/workspace-list-item-view.js +++ b/server/sonar-web/src/main/js/components/navigator/workspace-list-item-view.js @@ -1,24 +1,24 @@ -define(function () { +import Marionette from 'backbone.marionette'; - return Marionette.ItemView.extend({ +export default Marionette.ItemView.extend({ - initialize: function (options) { - this.listenTo(options.app.state, 'change:selectedIndex', this.select); - }, + initialize: function (options) { + this.listenTo(options.app.state, 'change:selectedIndex', this.select); + }, - onRender: function () { - this.select(); - }, + onRender: function () { + this.select(); + }, - select: function () { - var selected = this.model.get('index') === this.options.app.state.get('selectedIndex'); - this.$el.toggleClass('selected', selected); - }, + 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') }); - } - - }); + selectCurrent: function () { + this.options.app.state.set({ selectedIndex: this.model.get('index') }); + } }); + + diff --git a/server/sonar-web/src/main/js/components/navigator/workspace-list-view.js b/server/sonar-web/src/main/js/components/navigator/workspace-list-view.js index 01aaa035125..8bafcb89109 100644 --- a/server/sonar-web/src/main/js/components/navigator/workspace-list-view.js +++ b/server/sonar-web/src/main/js/components/navigator/workspace-list-view.js @@ -1,110 +1,111 @@ -define(function () { - - var $ = jQuery, - BOTTOM_OFFSET = 60; - - return Marionette.CompositeView.extend({ - - ui: { - loadMore: '.js-more', - lastElementReached: '.js-last-element-reached' - }, - - childViewOptions: function () { - return { - app: this.options.app - }; - }, - - collectionEvents: { - 'reset': 'scrollToTop' - }, - - initialize: function (options) { - this.loadMoreThrottled = _.throttle(this.loadMore, 1000, {trailing: false}); - this.listenTo(options.app.state, 'change:maxResultsReached', this.toggleLoadMore); - this.listenTo(options.app.state, 'change:selectedIndex', this.scrollTo); - this.bindShortcuts(); - }, - - onDestroy: function () { - this.unbindScrollEvents(); - this.unbindShortcuts(); - }, - - onRender: function () { - this.toggleLoadMore(); - }, - - toggleLoadMore: function () { - var maxResultsReached = this.options.app.state.get('maxResultsReached'); - this.ui.loadMore.toggle(!maxResultsReached); - this.ui.lastElementReached.toggle(maxResultsReached); - }, - - bindScrollEvents: function () { +import $ from 'jquery'; +import _ from 'underscore'; +import Marionette from 'backbone.marionette'; + +const BOTTOM_OFFSET = 60; + +export default Marionette.CompositeView.extend({ + + ui: { + loadMore: '.js-more', + lastElementReached: '.js-last-element-reached' + }, + + childViewOptions: function () { + return { + app: this.options.app + }; + }, + + collectionEvents: { + 'reset': 'scrollToTop' + }, + + initialize: function (options) { + this.loadMoreThrottled = _.throttle(this.loadMore, 1000, { trailing: false }); + this.listenTo(options.app.state, 'change:maxResultsReached', this.toggleLoadMore); + this.listenTo(options.app.state, 'change:selectedIndex', this.scrollTo); + this.bindShortcuts(); + }, + + onDestroy: function () { + this.unbindScrollEvents(); + this.unbindShortcuts(); + }, + + onRender: function () { + this.toggleLoadMore(); + }, + + toggleLoadMore: function () { + var maxResultsReached = this.options.app.state.get('maxResultsReached'); + this.ui.loadMore.toggle(!maxResultsReached); + this.ui.lastElementReached.toggle(maxResultsReached); + }, + + bindScrollEvents: function () { + var that = this; + $(window).on('scroll.workspace-list-view', function () { + that.onScroll(); + }); + }, + + unbindScrollEvents: function () { + $(window).off('scroll.workspace-list-view'); + }, + + bindShortcuts: function () { + var that = this; + key('up', 'list', function () { + that.options.app.controller.selectPrev(); + return false; + }); + + key('down', 'list', function () { + that.options.app.controller.selectNext(); + return false; + }); + }, + + loadMore: function () { + if (!this.options.app.state.get('maxResultsReached')) { var that = this; - $(window).on('scroll.workspace-list-view', function () { - that.onScroll(); + this.unbindScrollEvents(); + this.options.app.controller.fetchNextPage().done(function () { + that.bindScrollEvents(); }); - }, + } + }, - unbindScrollEvents: function () { - $(window).off('scroll.workspace-list-view'); - }, + onScroll: function () { + if ($(window).scrollTop() + $(window).height() >= this.ui.loadMore.offset().top) { + this.loadMoreThrottled(); + } + }, - bindShortcuts: function () { - var that = this; - key('up', 'list', function () { - that.options.app.controller.selectPrev(); - return false; - }); + scrollToTop: function () { + this.$el.scrollParent().scrollTop(0); + }, - key('down', 'list', function () { - that.options.app.controller.selectNext(); - return false; - }); - }, - - loadMore: function () { - if (!this.options.app.state.get('maxResultsReached')) { - var that = this; - this.unbindScrollEvents(); - this.options.app.controller.fetchNextPage().done(function () { - that.bindScrollEvents(); - }); - } - }, - - onScroll: function () { - if ($(window).scrollTop() + $(window).height() >= this.ui.loadMore.offset().top) { - this.loadMoreThrottled(); - } - }, - - scrollToTop: function () { - this.$el.scrollParent().scrollTop(0); - }, - - scrollTo: function () { - var selected = this.collection.at(this.options.app.state.get('selectedIndex')); - if (selected == null) { - return; - } - var selectedView = this.children.findByModel(selected), - parentTopOffset = this.$el.offset().top, - viewTop = selectedView.$el.offset().top - parentTopOffset, - viewBottom = selectedView.$el.offset().top + selectedView.$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); - } + scrollTo: function () { + var selected = this.collection.at(this.options.app.state.get('selectedIndex')); + if (selected == null) { + return; } - - }); + var selectedView = this.children.findByModel(selected), + parentTopOffset = this.$el.offset().top, + viewTop = selectedView.$el.offset().top - parentTopOffset, + viewBottom = selectedView.$el.offset().top + selectedView.$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); + } + } }); + + diff --git a/server/sonar-web/src/main/js/components/select-list/controls.jsx b/server/sonar-web/src/main/js/components/select-list/controls.jsx index 47c5bb46531..e351fb01229 100644 --- a/server/sonar-web/src/main/js/components/select-list/controls.jsx +++ b/server/sonar-web/src/main/js/components/select-list/controls.jsx @@ -1,5 +1,5 @@ +import _ from 'underscore'; import React from 'react'; -import classNames from '../../libs/third-party/classNames'; import RadioToggle from '../shared/radio-toggle'; export default React.createClass({ @@ -21,7 +21,7 @@ export default React.createClass({ this.props.loadDeselected(); break; default: - this.props.loadAll() + this.props.loadAll(); } }, diff --git a/server/sonar-web/src/main/js/components/select-list/footer.jsx b/server/sonar-web/src/main/js/components/select-list/footer.jsx index b60e32e9a73..b1efeb4086a 100644 --- a/server/sonar-web/src/main/js/components/select-list/footer.jsx +++ b/server/sonar-web/src/main/js/components/select-list/footer.jsx @@ -1,5 +1,4 @@ import React from 'react'; -import Checkbox from '../shared/checkbox'; export default React.createClass({ propTypes: { diff --git a/server/sonar-web/src/main/js/components/select-list/item.jsx b/server/sonar-web/src/main/js/components/select-list/item.jsx index 2f0fe6da345..5e7ed129de1 100644 --- a/server/sonar-web/src/main/js/components/select-list/item.jsx +++ b/server/sonar-web/src/main/js/components/select-list/item.jsx @@ -10,7 +10,11 @@ export default React.createClass({ }, onCheck(checked) { - checked ? this.props.selectItem(this.props.item) : this.props.deselectItem(this.props.item); + if (checked) { + this.props.selectItem(this.props.item); + } else { + this.props.deselectItem(this.props.item); + } }, render() { diff --git a/server/sonar-web/src/main/js/components/shared/favorite.jsx b/server/sonar-web/src/main/js/components/shared/favorite.jsx index 09601d31cd1..f75d03b4cb4 100644 --- a/server/sonar-web/src/main/js/components/shared/favorite.jsx +++ b/server/sonar-web/src/main/js/components/shared/favorite.jsx @@ -1,7 +1,6 @@ +import $ from 'jquery'; import React from 'react'; -let $ = jQuery; - export default React.createClass({ propTypes: { component: React.PropTypes.string.isRequired, @@ -14,7 +13,11 @@ export default React.createClass({ toggleFavorite(e) { e.preventDefault(); - this.state.favorite ? this.removeFavorite() : this.addFavorite(); + if (this.state.favorite) { + this.removeFavorite(); + } else { + this.addFavorite(); + } }, addFavorite() { @@ -34,7 +37,7 @@ export default React.createClass({ <path d="M15.4275,5.77678C15.4275,5.90773 15.3501,6.05059 15.1953,6.20536L11.9542,9.36608L12.7221,13.8304C12.728,13.872 12.731,13.9316 12.731,14.0089C12.731,14.1339 12.6998,14.2396 12.6373,14.3259C12.5748,14.4122 12.484,14.4554 12.3649,14.4554C12.2518,14.4554 12.1328,14.4197 12.0078,14.3482L7.99888,12.2411L3.98995,14.3482C3.85901,14.4197 3.73996,14.4554 3.63281,14.4554C3.50781,14.4554 3.41406,14.4122 3.35156,14.3259C3.28906,14.2396 3.25781,14.1339 3.25781,14.0089C3.25781,13.9732 3.26377,13.9137 3.27567,13.8304L4.04353,9.36608L0.793531,6.20536C0.644719,6.04464 0.570313,5.90178 0.570313,5.77678C0.570313,5.55654 0.736979,5.41964 1.07031,5.36606L5.55245,4.71428L7.56138,0.651781C7.67447,0.407729 7.8203,0.285703 7.99888,0.285703C8.17745,0.285703 8.32328,0.407729 8.43638,0.651781L10.4453,4.71428L14.9274,5.36606C15.2608,5.41964 15.4274,5.55654 15.4274,5.77678L15.4275,5.77678Z" style={{ fillRule: 'nonzero' }}/> </svg> - ) + ); }, render() { diff --git a/server/sonar-web/src/main/js/components/source-viewer/header.js b/server/sonar-web/src/main/js/components/source-viewer/header.js index 351540c655c..5f72fb686f2 100644 --- a/server/sonar-web/src/main/js/components/source-viewer/header.js +++ b/server/sonar-web/src/main/js/components/source-viewer/header.js @@ -1,82 +1,82 @@ -define([ - './more-actions', - './measures-overlay', - './templates' -], function (MoreActionsView, MeasuresOverlay) { +import $ from 'jquery'; +import _ from 'underscore'; +import Marionette from 'backbone.marionette'; +import MoreActionsView from './more-actions'; +import MeasuresOverlay from './measures-overlay'; +import './templates'; - var $ = jQuery, - API_FAVORITE = baseUrl + '/api/favourites'; +var API_FAVORITE = baseUrl + '/api/favourites'; - return Marionette.ItemView.extend({ - template: Templates['source-viewer-header'], +export default Marionette.ItemView.extend({ + template: Templates['source-viewer-header'], - events: function () { - return { - 'click .js-favorite': 'toggleFavorite', - 'click .js-actions': 'showMoreActions', - 'click .js-permalink': 'getPermalink' - }; - }, + events: function () { + return { + 'click .js-favorite': 'toggleFavorite', + 'click .js-actions': 'showMoreActions', + 'click .js-permalink': 'getPermalink' + }; + }, - toggleFavorite: function () { - var that = this; - if (this.model.get('fav')) { - $.ajax({ - url: API_FAVORITE + '/' + this.model.get('key'), - type: 'DELETE' - }).done(function () { - that.model.set('fav', false); - that.render(); - }); - } - else { - $.ajax({ - url: API_FAVORITE, - type: 'POST', - data: { - key: this.model.get('key') - } - }).done(function () { - that.model.set('fav', true); - that.render(); - }); - } - }, - - showMoreActions: function (e) { - e.stopPropagation(); - $('body').click(); - var view = new MoreActionsView({ parent: this }); - view.render().$el.appendTo(this.$el); - }, + toggleFavorite: function () { + var that = this; + if (this.model.get('fav')) { + $.ajax({ + url: API_FAVORITE + '/' + this.model.get('key'), + type: 'DELETE' + }).done(function () { + that.model.set('fav', false); + that.render(); + }); + } + else { + $.ajax({ + url: API_FAVORITE, + type: 'POST', + data: { + key: this.model.get('key') + } + }).done(function () { + that.model.set('fav', true); + that.render(); + }); + } + }, - getPermalink: function () { - var query = 'id=' + encodeURIComponent(this.model.get('key')), - windowParams = 'resizable=1,scrollbars=1,status=1'; - if (this.options.viewer.highlightedLine) { - query = query + '&line=' + this.options.viewer.highlightedLine; - } - window.open(baseUrl + '/component/index?' + query, this.model.get('name'), windowParams); - }, + showMoreActions: function (e) { + e.stopPropagation(); + $('body').click(); + var view = new MoreActionsView({ parent: this }); + view.render().$el.appendTo(this.$el); + }, - showRawSources: function () { - var url = baseUrl + '/api/sources/raw?key=' + encodeURIComponent(this.model.get('key')), - windowParams = 'resizable=1,scrollbars=1,status=1'; - window.open(url, this.model.get('name'), windowParams); - }, + getPermalink: function () { + var query = 'id=' + encodeURIComponent(this.model.get('key')), + windowParams = 'resizable=1,scrollbars=1,status=1'; + if (this.options.viewer.highlightedLine) { + query = query + '&line=' + this.options.viewer.highlightedLine; + } + window.open(baseUrl + '/component/index?' + query, this.model.get('name'), windowParams); + }, - showMeasures: function () { - new MeasuresOverlay({ - model: this.model, - large: true - }).render(); - }, + showRawSources: function () { + var url = baseUrl + '/api/sources/raw?key=' + encodeURIComponent(this.model.get('key')), + windowParams = 'resizable=1,scrollbars=1,status=1'; + window.open(url, this.model.get('name'), windowParams); + }, - serializeData: function () { - return _.extend(Marionette.ItemView.prototype.serializeData.apply(this, arguments), { - path: this.model.get('path') || this.model.get('longName') - }); - } - }); + showMeasures: function () { + new MeasuresOverlay({ + model: this.model, + large: true + }).render(); + }, + serializeData: function () { + return _.extend(Marionette.ItemView.prototype.serializeData.apply(this, arguments), { + path: this.model.get('path') || this.model.get('longName') + }); + } }); + + diff --git a/server/sonar-web/src/main/js/components/source-viewer/helpers/code-with-issue-locations-helper.js b/server/sonar-web/src/main/js/components/source-viewer/helpers/code-with-issue-locations-helper.js index eed0d5f26d4..0a1537002fd 100644 --- a/server/sonar-web/src/main/js/components/source-viewer/helpers/code-with-issue-locations-helper.js +++ b/server/sonar-web/src/main/js/components/source-viewer/helpers/code-with-issue-locations-helper.js @@ -1,127 +1,127 @@ -define(function () { +import _ from 'underscore'; - /** - * Intersect two ranges - * @param {number} s1 Start position of the first range - * @param {number} e1 End position of the first range - * @param {number} s2 Start position of the second range - * @param {number} e2 End position of the second range - * @returns {{from: number, to: number}} - */ - function intersect (s1, e1, s2, e2) { - return { from: Math.max(s1, s2), to: Math.min(e1, e2) }; - } +/** + * Intersect two ranges + * @param {number} s1 Start position of the first range + * @param {number} e1 End position of the first range + * @param {number} s2 Start position of the second range + * @param {number} e2 End position of the second range + * @returns {{from: number, to: number}} + */ +function intersect (s1, e1, s2, e2) { + return { from: Math.max(s1, s2), to: Math.min(e1, e2) }; +} - /** - * Get the substring of a string - * @param {string} str A string - * @param {number} from "From" offset - * @param {number} to "To" offset - * @param {number} acc Global offset to eliminate - * @returns {string} - */ - function part (str, from, to, acc) { - // we do not want negative number as the first argument of `substr` - return from >= acc ? str.substr(from - acc, to - from) : str.substr(0, to - from); - } +/** + * Get the substring of a string + * @param {string} str A string + * @param {number} from "From" offset + * @param {number} to "To" offset + * @param {number} acc Global offset to eliminate + * @returns {string} + */ +function part (str, from, to, acc) { + // we do not want negative number as the first argument of `substr` + return from >= acc ? str.substr(from - acc, to - from) : str.substr(0, to - from); +} - /** - * Split a code html into tokens - * @param {string} code - * @returns {Array} - */ - function splitByTokens (code) { - var container = document.createElement('div'), - tokens = []; - container.innerHTML = code; - [].forEach.call(container.childNodes, function (node) { - if (node.nodeType === 1) { - // ELEMENT NODE - tokens.push({ className: node.className, text: node.textContent }); +/** + * Split a code html into tokens + * @param {string} code + * @returns {Array} + */ +function splitByTokens (code) { + var container = document.createElement('div'), + tokens = []; + container.innerHTML = code; + [].forEach.call(container.childNodes, function (node) { + if (node.nodeType === 1) { + // ELEMENT NODE + tokens.push({ className: node.className, text: node.textContent }); + } + if (node.nodeType === 3) { + // TEXT NODE + tokens.push({ className: '', text: node.nodeValue }); + } + }); + return tokens; +} + + +/** + * Highlight issue locations in the list of tokens + * @param {Array} tokens + * @param {Array} issueLocations + * @param {string} className + * @returns {Array} + */ +function highlightIssueLocations (tokens, issueLocations, className) { + issueLocations.forEach(function (location) { + var nextTokens = [], + acc = 0; + tokens.forEach(function (token) { + var x = intersect(acc, acc + token.text.length, location.from, location.to); + var p1 = part(token.text, acc, x.from, acc), + p2 = part(token.text, x.from, x.to, acc), + p3 = part(token.text, x.to, acc + token.text.length, acc); + if (p1.length) { + nextTokens.push({ className: token.className, text: p1 }); } - if (node.nodeType === 3) { - // TEXT NODE - tokens.push({ className: '', text: node.nodeValue }); + if (p2.length) { + var newClassName = token.className.indexOf(className) === -1 ? + [token.className, className].join(' ') : token.className; + nextTokens.push({ className: newClassName, text: p2 }); } + if (p3.length) { + nextTokens.push({ className: token.className, text: p3 }); + } + acc += token.text.length; }); - return tokens; - } + tokens = nextTokens.slice(); + }); + return tokens; +} - /** - * Highlight issue locations in the list of tokens - * @param {Array} tokens - * @param {Array} issueLocations - * @param {string} className - * @returns {Array} - */ - function highlightIssueLocations (tokens, issueLocations, className) { - issueLocations.forEach(function (location) { - var nextTokens = [], - acc = 0; - tokens.forEach(function (token) { - var x = intersect(acc, acc + token.text.length, location.from, location.to); - var p1 = part(token.text, acc, x.from, acc), - p2 = part(token.text, x.from, x.to, acc), - p3 = part(token.text, x.to, acc + token.text.length, acc); - if (p1.length) { - nextTokens.push({ className: token.className, text: p1 }); - } - if (p2.length) { - var newClassName = token.className.indexOf(className) === -1 ? - [token.className, className].join(' ') : token.className; - nextTokens.push({ className: newClassName, text: p2 }); - } - if (p3.length) { - nextTokens.push({ className: token.className, text: p3 }); - } - acc += token.text.length; - }); - tokens = nextTokens.slice(); - }); - return tokens; - } +/** + * Generate an html string from the list of tokens + * @param {Array} tokens + * @returns {string} + */ +function generateHTML (tokens) { + return tokens.map(function (token) { + return '<span class="' + token.className + '">' + _.escape(token.text) + '</span>'; + }).join(''); +} - /** - * Generate an html string from the list of tokens - * @param {Array} tokens - * @returns {string} - */ - function generateHTML (tokens) { - return tokens.map(function (token) { - return '<span class="' + token.className + '">' + _.escape(token.text) + '</span>'; - }).join(''); - } +/** + * Take the initial source code, split by tokens, + * highlight issues and generate result html + * @param {string} code + * @param {Array} issueLocations + * @param {string} [optionalClassName] + * @returns {string} + */ +function doTheStuff (code, issueLocations, optionalClassName) { + var _code = code || ' '; + var _issueLocations = issueLocations || []; + var _className = optionalClassName ? optionalClassName : 'source-line-code-issue'; + return generateHTML(highlightIssueLocations(splitByTokens(_code), _issueLocations, _className)); +} +if (typeof Handlebars !== 'undefined') { /** - * Take the initial source code, split by tokens, - * highlight issues and generate result html - * @param {string} code - * @param {Array} issueLocations - * @param {string} [optionalClassName] - * @returns {string} + * Handlebars helper to highlight issue locations in the source code */ - function doTheStuff (code, issueLocations, optionalClassName) { - var _code = code || ' '; - var _issueLocations = issueLocations || []; - var _className = optionalClassName ? optionalClassName : 'source-line-code-issue'; - return generateHTML(highlightIssueLocations(splitByTokens(_code), _issueLocations, _className)); - } - - - if (typeof Handlebars !== 'undefined') { - /** - * Handlebars helper to highlight issue locations in the source code - */ - Handlebars.registerHelper('codeWithIssueLocations', function (code, issueLocations) { - return doTheStuff(code, issueLocations); - }); - } + Handlebars.registerHelper('codeWithIssueLocations', function (code, issueLocations) { + return doTheStuff(code, issueLocations); + }); +} + +export default doTheStuff; - return doTheStuff; -}); diff --git a/server/sonar-web/src/main/js/components/source-viewer/main.js b/server/sonar-web/src/main/js/components/source-viewer/main.js index d4963669643..05a94e07e53 100644 --- a/server/sonar-web/src/main/js/components/source-viewer/main.js +++ b/server/sonar-web/src/main/js/components/source-viewer/main.js @@ -1,808 +1,795 @@ -define([ - './source', - 'components/issue/models/issue', - 'components/issue/collections/issues', - 'components/issue/issue-view', - './header', - './popups/scm-popup', - './popups/coverage-popup', - './popups/duplication-popup', - './popups/line-actions-popup', - - './helpers/code-with-issue-locations-helper', - './templates' - ], - function (Source, - Issue, - Issues, - IssueView, - HeaderView, - SCMPopupView, - CoveragePopupView, - DuplicationPopupView, - LineActionsPopupView, - highlightLocations) { - - var $ = jQuery, - HIGHLIGHTED_ROW_CLASS = 'source-line-highlighted'; - - return Marionette.LayoutView.extend({ - className: 'source-viewer', - template: Templates['source-viewer'], - issueLocationTemplate: Templates['source-viewer-issue-location'], - - ISSUES_LIMIT: 3000, - LINES_LIMIT: 1000, - TOTAL_LINES_LIMIT: 3000, - LINES_AROUND: 500, - - regions: { - headerRegion: '.source-viewer-header' - }, - - ui: { - sourceBeforeSpinner: '.js-component-viewer-source-before', - sourceAfterSpinner: '.js-component-viewer-source-after' - }, - - events: function () { - return { - 'click .sym': 'highlightUsages', - 'click .source-line-scm': 'showSCMPopup', - 'click .source-line-covered': 'showCoveragePopup', - 'click .source-line-partially-covered': 'showCoveragePopup', - 'click .source-line-uncovered': 'showCoveragePopup', - 'click .source-line-duplications': 'showDuplications', - 'click .source-line-duplications-extra': 'showDuplicationPopup', - 'click .source-line-with-issues': 'onLineIssuesClick', - 'click .source-line-number[data-line-number]': 'onLineNumberClick', - 'mouseenter .source-line-filtered .source-line-filtered-container': 'showFilteredTooltip', - 'mouseleave .source-line-filtered .source-line-filtered-container': 'hideFilteredTooltip' - }; - }, - - initialize: function () { - if (this.model == null) { - this.model = new Source(); - } - this.issues = new Issues(); - this.listenTo(this.issues, 'change:severity', this.onIssuesSeverityChange); - this.listenTo(this.issues, 'locations', this.toggleIssueLocations); - this.issueViews = []; - this.loadSourceBeforeThrottled = _.throttle(this.loadSourceBefore, 1000); - this.loadSourceAfterThrottled = _.throttle(this.loadSourceAfter, 1000); - this.highlightedLine = null; - this.listenTo(this, 'loaded', this.onLoaded); - }, - - renderHeader: function () { - this.headerRegion.show(new HeaderView({ - viewer: this, - model: this.model - })); - }, - - onRender: function () { - this.renderHeader(); - this.renderIssues(); - if (this.model.has('filterLinesFunc')) { - this.filterLines(this.model.get('filterLinesFunc')); - } - this.$('[data-toggle="tooltip"]').tooltip({ container: 'body' }); - }, - - onDestroy: function () { - this.issueViews.forEach(function (view) { - return view.destroy(); - }); - this.issueViews = []; - this.clearTooltips(); - }, - - clearTooltips: function () { - this.$('[data-toggle="tooltip"]').tooltip('destroy'); - }, - - onLoaded: function () { - this.bindScrollEvents(); - }, - - open: function (id, options) { - var that = this, - opts = typeof options === 'object' ? options : {}, - finalize = function () { - that.requestIssues().done(function () { - that.render(); - that.trigger('loaded'); - }); - }; - _.extend(this.options, _.defaults(opts, { workspace: false })); - this.model - .clear() - .set(_.result(this.model, 'defaults')) - .set({ uuid: id }); - this.requestComponent().done(function () { - that.requestSource() - .done(finalize) - .fail(function () { - that.model.set({ - source: [ - { line: 0 } - ] - }); - finalize(); - }); - }); - return this; - }, - - requestComponent: function () { - var that = this, - url = baseUrl + '/api/components/app', - data = { uuid: this.model.id }; - return $.ajax({ - type: 'GET', - url: url, - data: data, - statusCode: { - 404: function () { - that.model.set({ exist: false }); - that.render(); - that.trigger('loaded'); - } - } - }).done(function (data) { - that.model.set(data); - that.model.set({ isUnitTest: data.q === 'UTS' }); - }); - }, - - linesLimit: function () { - return { - from: 1, - to: this.LINES_LIMIT - }; - }, - - getUTCoverageStatus: function (row) { - var status = null; - if (row.utLineHits > 0) { - status = 'partially-covered'; - } - if (row.utLineHits > 0 && row.utConditions === row.utCoveredConditions) { - status = 'covered'; - } - if (row.utLineHits === 0 || row.utCoveredConditions === 0) { - status = 'uncovered'; - } - return status; - }, - - getItCoverageStatus: function (row) { - var status = null; - if (row.itLineHits > 0) { - status = 'partially-covered'; - } - if (row.itLineHits > 0 && row.itConditions === row.itCoveredConditions) { - status = 'covered'; - } - if (row.itLineHits === 0 || row.itCoveredConditions === 0) { - status = 'uncovered'; - } - return status; - }, - - requestSource: function () { - var that = this, - url = baseUrl + '/api/sources/lines', - options = _.extend({ uuid: this.model.id }, this.linesLimit()); - return $.get(url, options).done(function (data) { - var source = (data.sources || []).slice(0); - if (source.length === 0 || (source.length > 0 && _.first(source).line === 1)) { - source.unshift({ line: 0 }); - } - source = source.map(function (row) { - return _.extend(row, { - utCoverageStatus: that.getUTCoverageStatus(row), - itCoverageStatus: that.getItCoverageStatus(row) - }); - }); - var firstLine = _.first(source).line, - linesRequested = options.to - options.from + 1; - that.model.set({ - source: source, - hasUTCoverage: that.model.hasUTCoverage(source), - hasITCoverage: that.model.hasITCoverage(source), - hasSourceBefore: firstLine > 1, - hasSourceAfter: data.sources.length === linesRequested - }); - that.model.checkIfHasDuplications(); - }).fail(function (request) { - if (request.status === 403) { - that.model.set({ - source: [], - hasSourceBefore: false, - hasSourceAfter: false, - canSeeCode: false - }); - } - }); - }, - - requestDuplications: function () { - var that = this, - url = baseUrl + '/api/duplications/show', - options = { uuid: this.model.id }; - return $.get(url, options, function (data) { - var hasDuplications = (data != null) && (data.duplications != null), - duplications = []; - if (hasDuplications) { - duplications = {}; - data.duplications.forEach(function (d) { - d.blocks.forEach(function (b) { - if (b._ref === '1') { - var lineFrom = b.from, - lineTo = b.from + b.size - 1; - for (var j = lineFrom; j <= lineTo; j++) { - duplications[j] = true; - } - } - }); - }); - duplications = _.pairs(duplications).map(function (line) { - return { - line: +line[0], - duplicated: line[1] - }; - }); - } - that.model.addMeta(duplications); - that.model.addDuplications(data.duplications); - that.model.set({ - duplications: data.duplications, - duplicationsParsed: duplications, - duplicationFiles: data.files - }); - }); - }, - - requestIssues: function () { - var that = this, - options = { - data: { - componentUuids: this.model.id, - f: 'component,componentId,project,subProject,rule,status,resolution,author,reporter,assignee,debt,' + - 'line,message,severity,actionPlan,creationDate,updateDate,closeDate,tags,comments,attr,actions,' + - 'transitions,actionPlanName', - additionalFields: '_all', - resolved: false, - s: 'FILE_LINE', - asc: true, - ps: this.ISSUES_LIMIT - } - }; - return this.issues.fetch(options).done(function () { - that.addIssuesPerLineMeta(that.issues); - }); - }, - - _sortBySeverity: function (issues) { - var order = ['BLOCKER', 'CRITICAL', 'MAJOR', 'MINOR', 'INFO']; - return _.sortBy(issues, function (issue) { - return order.indexOf(issue.severity); - }); - }, - - addIssuesPerLineMeta: function (issues) { - var that = this, - lines = {}; - issues.forEach(function (issue) { - var line = issue.get('line') || 0; - if (!_.isArray(lines[line])) { - lines[line] = []; - } - lines[line].push(issue.toJSON()); - }); - var issuesPerLine = _.pairs(lines).map(function (line) { - return { - line: +line[0], - issues: that._sortBySeverity(line[1]) - }; - }); - this.model.addMeta(issuesPerLine); - this.addIssueLocationsMeta(issues); - }, - - addIssueLocationsMeta: function (issues) { - var issueLocations = []; - issues.forEach(function (issue) { - issue.getLinearLocations().forEach(function (location) { - var record = _.findWhere(issueLocations, { line: location.line }); - if (record) { - record.issueLocations.push({ from: location.from, to: location.to }); - } else { - issueLocations.push({ - line: location.line, - issueLocations: [{ from: location.from, to: location.to }] - }); - } - }); - }); - this.model.addMeta(issueLocations); - }, - - renderIssues: function () { - this.$('.issue-list').addClass('hidden'); - }, - - renderIssue: function (issue) { - var issueView = new IssueView({ - el: '#issue-' + issue.get('key'), - model: issue - }); - this.issueViews.push(issueView); - issueView.render(); - }, - - addIssue: function (issue) { - var line = issue.get('line') || 0, - code = this.$('.source-line-code[data-line-number=' + line + ']'), - issueBox = '<div class="issue" id="issue-' + issue.get('key') + '" data-key="' + issue.get('key') + '">'; - code.addClass('has-issues'); - var issueList = code.find('.issue-list'); - if (issueList.length === 0) { - code.append('<div class="issue-list"></div>'); - issueList = code.find('.issue-list'); - } - issueList - .append(issueBox) - .removeClass('hidden'); - this.renderIssue(issue); - }, - - showIssuesForLine: function (line) { - this.$('.source-line-code[data-line-number="' + line + '"]').find('.issue-list').removeClass('hidden'); - var issues = this.issues.filter(function (issue) { - return (issue.get('line') === line) || (!issue.get('line') && !line); - }); - issues.forEach(this.renderIssue, this); - }, - - onIssuesSeverityChange: function () { - var that = this; - this.addIssuesPerLineMeta(this.issues); - this.$('.source-line-with-issues').each(function () { - var line = +$(this).data('line-number'), - row = _.findWhere(that.model.get('source'), { line: line }), - issue = _.first(row.issues); - $(this).html('<i class="icon-severity-' + issue.severity.toLowerCase() + '"></i>'); - }); - }, - - highlightUsages: function (e) { - var highlighted = $(e.currentTarget).is('.highlighted'), - key = e.currentTarget.className.split(/\s+/)[0]; - this.$('.sym.highlighted').removeClass('highlighted'); - if (!highlighted) { - this.$('.sym.' + key).addClass('highlighted'); - } - }, - - showSCMPopup: function (e) { - e.stopPropagation(); - $('body').click(); - var line = +$(e.currentTarget).data('line-number'), - row = _.findWhere(this.model.get('source'), { line: line }), - popup = new SCMPopupView({ - triggerEl: $(e.currentTarget), - model: new Backbone.Model(row) - }); - popup.render(); - }, - - showCoveragePopup: function (e) { - e.stopPropagation(); - $('body').click(); - this.clearTooltips(); - var line = $(e.currentTarget).data('line-number'), - row = _.findWhere(this.model.get('source'), { line: line }), - url = baseUrl + '/api/tests/list', - options = { - sourceFileUuid: this.model.id, - sourceFileLineNumber: line, - ps: 1000 - }; - return $.get(url, options).done(function (data) { - var popup = new CoveragePopupView({ - collection: new Backbone.Collection(data.tests), - row: row, - tests: $(e.currentTarget).data('tests'), - triggerEl: $(e.currentTarget) - }); - popup.render(); - }); - }, - - showDuplications: function (e) { - var that = this, - lineNumber = $(e.currentTarget).closest('.source-line').data('line-number'); - this.clearTooltips(); - this.requestDuplications().done(function () { +import $ from 'jquery'; +import _ from 'underscore'; +import Backbone from 'backbone'; +import Marionette from 'backbone.marionette'; +import Source from './source'; +import Issues from 'components/issue/collections/issues'; +import IssueView from 'components/issue/issue-view'; +import HeaderView from './header'; +import SCMPopupView from './popups/scm-popup'; +import CoveragePopupView from './popups/coverage-popup'; +import DuplicationPopupView from './popups/duplication-popup'; +import LineActionsPopupView from './popups/line-actions-popup'; +import highlightLocations from './helpers/code-with-issue-locations-helper'; +import './templates'; + +var HIGHLIGHTED_ROW_CLASS = 'source-line-highlighted'; + +export default Marionette.LayoutView.extend({ + className: 'source-viewer', + template: Templates['source-viewer'], + issueLocationTemplate: Templates['source-viewer-issue-location'], + + ISSUES_LIMIT: 3000, + LINES_LIMIT: 1000, + TOTAL_LINES_LIMIT: 3000, + LINES_AROUND: 500, + + regions: { + headerRegion: '.source-viewer-header' + }, + + ui: { + sourceBeforeSpinner: '.js-component-viewer-source-before', + sourceAfterSpinner: '.js-component-viewer-source-after' + }, + + events: function () { + return { + 'click .sym': 'highlightUsages', + 'click .source-line-scm': 'showSCMPopup', + 'click .source-line-covered': 'showCoveragePopup', + 'click .source-line-partially-covered': 'showCoveragePopup', + 'click .source-line-uncovered': 'showCoveragePopup', + 'click .source-line-duplications': 'showDuplications', + 'click .source-line-duplications-extra': 'showDuplicationPopup', + 'click .source-line-with-issues': 'onLineIssuesClick', + 'click .source-line-number[data-line-number]': 'onLineNumberClick', + 'mouseenter .source-line-filtered .source-line-filtered-container': 'showFilteredTooltip', + 'mouseleave .source-line-filtered .source-line-filtered-container': 'hideFilteredTooltip' + }; + }, + + initialize: function () { + if (this.model == null) { + this.model = new Source(); + } + this.issues = new Issues(); + this.listenTo(this.issues, 'change:severity', this.onIssuesSeverityChange); + this.listenTo(this.issues, 'locations', this.toggleIssueLocations); + this.issueViews = []; + this.loadSourceBeforeThrottled = _.throttle(this.loadSourceBefore, 1000); + this.loadSourceAfterThrottled = _.throttle(this.loadSourceAfter, 1000); + this.highlightedLine = null; + this.listenTo(this, 'loaded', this.onLoaded); + }, + + renderHeader: function () { + this.headerRegion.show(new HeaderView({ + viewer: this, + model: this.model + })); + }, + + onRender: function () { + this.renderHeader(); + this.renderIssues(); + if (this.model.has('filterLinesFunc')) { + this.filterLines(this.model.get('filterLinesFunc')); + } + this.$('[data-toggle="tooltip"]').tooltip({ container: 'body' }); + }, + + onDestroy: function () { + this.issueViews.forEach(function (view) { + return view.destroy(); + }); + this.issueViews = []; + this.clearTooltips(); + }, + + clearTooltips: function () { + this.$('[data-toggle="tooltip"]').tooltip('destroy'); + }, + + onLoaded: function () { + this.bindScrollEvents(); + }, + + open: function (id, options) { + var that = this, + opts = typeof options === 'object' ? options : {}, + finalize = function () { + that.requestIssues().done(function () { that.render(); - that.$el.addClass('source-duplications-expanded'); - - // immediately show dropdown popup if there is only one duplicated block - if (that.model.get('duplications').length === 1) { - var dupsBlock = that.$('.source-line[data-line-number=' + lineNumber + ']') - .find('.source-line-duplications-extra'); - dupsBlock.click(); - } - }); - }, - - showDuplicationPopup: function (e) { - e.stopPropagation(); - $('body').click(); - this.clearTooltips(); - var index = $(e.currentTarget).data('index'), - line = $(e.currentTarget).data('line-number'), - blocks = this.model.get('duplications')[index - 1].blocks, - inRemovedComponent = _.some(blocks, function (b) { - return b._ref == null; - }), - foundOne = false; - blocks = _.filter(blocks, function (b) { - var outOfBounds = b.from > line || b.from + b.size < line, - currentFile = b._ref === '1', - shouldDisplayForCurrentFile = outOfBounds || foundOne, - shouldDisplay = !currentFile || (currentFile && shouldDisplayForCurrentFile), - isOk = (b._ref != null) && shouldDisplay; - if (b._ref === '1' && !outOfBounds) { - foundOne = true; - } - return isOk; - }); - var popup = new DuplicationPopupView({ - triggerEl: $(e.currentTarget), - model: this.model, - inRemovedComponent: inRemovedComponent, - collection: new Backbone.Collection(blocks) - }); - popup.render(); - }, - - onLineIssuesClick: function (e) { - var line = $(e.currentTarget).data('line-number'), - issuesList = $(e.currentTarget).parent().find('.issue-list'), - areIssuesRendered = issuesList.find('.issue-inner').length > 0; - if (issuesList.is('.hidden')) { - if (areIssuesRendered) { - issuesList.removeClass('hidden'); - } else { - this.showIssuesForLine(line); - } - } else { - issuesList.addClass('hidden'); - } - }, - - showLineActionsPopup: function (e) { - e.stopPropagation(); - $('body').click(); - var that = this, - line = $(e.currentTarget).data('line-number'), - popup = new LineActionsPopupView({ - triggerEl: $(e.currentTarget), - model: this.model, - line: line, - row: $(e.currentTarget).closest('.source-line') - }); - popup.on('onManualIssueAdded', function (issue) { - that.addIssue(issue); + that.trigger('loaded'); }); - popup.render(); - }, - - onLineNumberClick: function (e) { - var row = $(e.currentTarget).closest('.source-line'), - line = row.data('line-number'), - highlighted = row.is('.' + HIGHLIGHTED_ROW_CLASS); - if (!highlighted) { - this.highlightLine(line); - this.showLineActionsPopup(e); - } else { - this.removeHighlighting(); - } - }, - - removeHighlighting: function () { - this.highlightedLine = null; - this.$('.' + HIGHLIGHTED_ROW_CLASS).removeClass(HIGHLIGHTED_ROW_CLASS); - }, - - highlightLine: function (line) { - var row = this.$('.source-line[data-line-number=' + line + ']'); - this.removeHighlighting(); - this.highlightedLine = line; - row.addClass(HIGHLIGHTED_ROW_CLASS); - return this; - }, - - bindScrollEvents: function () { - var that = this; - this.$el.scrollParent().on('scroll.source-viewer', function () { - that.onScroll(); - }); - }, - - unbindScrollEvents: function () { - this.$el.scrollParent().off('scroll.source-viewer'); - }, - - onScroll: function () { - var p = this.$el.scrollParent(); - if (p.is(document)) { - p = $(window); - } - var pTopOffset = p.offset() != null ? p.offset().top : 0, - pPosition = p.scrollTop() + pTopOffset; - if (this.model.get('hasSourceBefore') && (pPosition <= this.ui.sourceBeforeSpinner.offset().top)) { - this.loadSourceBeforeThrottled(); - } - if (this.model.get('hasSourceAfter') && (pPosition + p.height() >= this.ui.sourceAfterSpinner.offset().top)) { - return this.loadSourceAfterThrottled(); - } - }, - - scrollToLine: function (line) { - var row = this.$('.source-line[data-line-number=' + line + ']'); - if (row.length > 0) { - var p = this.$el.scrollParent(); - if (p.is(document)) { - p = $(window); - } - var pTopOffset = p.offset() != null ? p.offset().top : 0, - pHeight = p.height(), - goal = row.offset().top - pHeight / 3 - pTopOffset; - p.scrollTop(goal); - } - return this; - }, - - scrollToFirstLine: function (line) { - var row = this.$('.source-line[data-line-number=' + line + ']'); - if (row.length > 0) { - var p = this.$el.scrollParent(); - if (p.is(document)) { - p = $(window); - } - var pTopOffset = p.offset() != null ? p.offset().top : 0, - goal = row.offset().top - pTopOffset; - p.scrollTop(goal); - } - return this; - }, - - scrollToLastLine: function (line) { - var row = this.$('.source-line[data-line-number=' + line + ']'); - if (row.length > 0) { - var p = this.$el.scrollParent(); - if (p.is(document)) { - p = $(window); - } - var pTopOffset = p.offset() != null ? p.offset().top : 0, - pHeight = p.height(), - goal = row.offset().top - pTopOffset - pHeight + row.height(); - p.scrollTop(goal); - } - return this; - }, - - loadSourceBefore: function () { - this.unbindScrollEvents(); - var that = this, - source = this.model.get('source'), - firstLine = _.first(source).line, - url = baseUrl + '/api/sources/lines', - options = { - uuid: this.model.id, - from: firstLine - this.LINES_AROUND, - to: firstLine - 1 - }; - return $.get(url, options).done(function (data) { - source = (data.sources || []).concat(source); - if (source.length > that.TOTAL_LINES_LIMIT + 1) { - source = source.slice(0, that.TOTAL_LINES_LIMIT); - that.model.set({ hasSourceAfter: true }); - } - if (source.length === 0 || (source.length > 0 && _.first(source).line === 1)) { - source.unshift({ line: 0 }); - } - source = source.map(function (row) { - return _.extend(row, { - utCoverageStatus: that.getUTCoverageStatus(row), - itCoverageStatus: that.getItCoverageStatus(row) - }); - }); + }; + _.extend(this.options, _.defaults(opts, { workspace: false })); + this.model + .clear() + .set(_.result(this.model, 'defaults')) + .set({ uuid: id }); + this.requestComponent().done(function () { + that.requestSource() + .done(finalize) + .fail(function () { that.model.set({ - source: source, - hasUTCoverage: that.model.hasUTCoverage(source), - hasITCoverage: that.model.hasITCoverage(source), - hasSourceBefore: (data.sources.length === that.LINES_AROUND) && (_.first(source).line > 0) + source: [ + { line: 0 } + ] }); - that.addIssuesPerLineMeta(that.issues); - if (that.model.has('duplications')) { - that.model.addDuplications(that.model.get('duplications')); - that.model.addMeta(that.model.get('duplicationsParsed')); - } - that.model.checkIfHasDuplications(); - that.render(); - that.scrollToFirstLine(firstLine); - if (that.model.get('hasSourceBefore') || that.model.get('hasSourceAfter')) { - that.bindScrollEvents(); - } + finalize(); }); - }, - - loadSourceAfter: function () { - this.unbindScrollEvents(); - var that = this, - source = this.model.get('source'), - lastLine = _.last(source).line, - url = baseUrl + '/api/sources/lines', - options = { - uuid: this.model.id, - from: lastLine + 1, - to: lastLine + this.LINES_AROUND - }; - return $.get(url, options).done(function (data) { - source = source.concat(data.sources); - if (source.length > that.TOTAL_LINES_LIMIT + 1) { - source = source.slice(source.length - that.TOTAL_LINES_LIMIT); - that.model.set({ hasSourceBefore: true }); - } - source = source.map(function (row) { - return _.extend(row, { - utCoverageStatus: that.getUTCoverageStatus(row), - itCoverageStatus: that.getItCoverageStatus(row) - }); - }); - that.model.set({ - source: source, - hasUTCoverage: that.model.hasUTCoverage(source), - hasITCoverage: that.model.hasITCoverage(source), - hasSourceAfter: data.sources.length === that.LINES_AROUND - }); - that.addIssuesPerLineMeta(that.issues); - if (that.model.has('duplications')) { - that.model.addDuplications(that.model.get('duplications')); - that.model.addMeta(that.model.get('duplicationsParsed')); - } - that.model.checkIfHasDuplications(); - that.render(); - that.scrollToLastLine(lastLine); - if (that.model.get('hasSourceBefore') || that.model.get('hasSourceAfter')) { - that.bindScrollEvents(); - } - }).fail(function () { - that.model.set({ - hasSourceAfter: false - }); - that.render(); - if (that.model.get('hasSourceBefore') || that.model.get('hasSourceAfter')) { - that.bindScrollEvents(); + }); + return this; + }, + + requestComponent: function () { + var that = this, + url = baseUrl + '/api/components/app', + data = { uuid: this.model.id }; + return $.ajax({ + type: 'GET', + url: url, + data: data, + statusCode: { + 404: function () { + that.model.set({ exist: false }); + that.render(); + that.trigger('loaded'); + } + } + }).done(function (data) { + that.model.set(data); + that.model.set({ isUnitTest: data.q === 'UTS' }); + }); + }, + + linesLimit: function () { + return { + from: 1, + to: this.LINES_LIMIT + }; + }, + + getUTCoverageStatus: function (row) { + var status = null; + if (row.utLineHits > 0) { + status = 'partially-covered'; + } + if (row.utLineHits > 0 && row.utConditions === row.utCoveredConditions) { + status = 'covered'; + } + if (row.utLineHits === 0 || row.utCoveredConditions === 0) { + status = 'uncovered'; + } + return status; + }, + + getItCoverageStatus: function (row) { + var status = null; + if (row.itLineHits > 0) { + status = 'partially-covered'; + } + if (row.itLineHits > 0 && row.itConditions === row.itCoveredConditions) { + status = 'covered'; + } + if (row.itLineHits === 0 || row.itCoveredConditions === 0) { + status = 'uncovered'; + } + return status; + }, + + requestSource: function () { + var that = this, + url = baseUrl + '/api/sources/lines', + options = _.extend({ uuid: this.model.id }, this.linesLimit()); + return $.get(url, options).done(function (data) { + var source = (data.sources || []).slice(0); + if (source.length === 0 || (source.length > 0 && _.first(source).line === 1)) { + source.unshift({ line: 0 }); + } + source = source.map(function (row) { + return _.extend(row, { + utCoverageStatus: that.getUTCoverageStatus(row), + itCoverageStatus: that.getItCoverageStatus(row) + }); + }); + var firstLine = _.first(source).line, + linesRequested = options.to - options.from + 1; + that.model.set({ + source: source, + hasUTCoverage: that.model.hasUTCoverage(source), + hasITCoverage: that.model.hasITCoverage(source), + hasSourceBefore: firstLine > 1, + hasSourceAfter: data.sources.length === linesRequested + }); + that.model.checkIfHasDuplications(); + }).fail(function (request) { + if (request.status === 403) { + that.model.set({ + source: [], + hasSourceBefore: false, + hasSourceAfter: false, + canSeeCode: false + }); + } + }); + }, + + requestDuplications: function () { + var that = this, + url = baseUrl + '/api/duplications/show', + options = { uuid: this.model.id }; + return $.get(url, options, function (data) { + var hasDuplications = (data != null) && (data.duplications != null), + duplications = []; + if (hasDuplications) { + duplications = {}; + data.duplications.forEach(function (d) { + d.blocks.forEach(function (b) { + if (b._ref === '1') { + var lineFrom = b.from, + lineTo = b.from + b.size - 1; + for (var j = lineFrom; j <= lineTo; j++) { + duplications[j] = true; + } } }); - }, - - filterLines: function (func) { - var lines = this.model.get('source'), - $lines = this.$('.source-line'); - this.model.set('filterLinesFunc', func); - lines.forEach(function (line, idx) { - var $line = $($lines[idx]), - filtered = func(line) && line.line > 0; - $line.toggleClass('source-line-shadowed', !filtered); - $line.toggleClass('source-line-filtered', filtered); - }); - }, - - filterLinesByDate: function (date, label) { - var sinceDate = moment(date).toDate(); - this.sinceLabel = label; - this.filterLines(function (line) { - var scmDate = moment(line.scmDate).toDate(); - return scmDate >= sinceDate; - }); - }, - - showFilteredTooltip: function (e) { - $(e.currentTarget).tooltip({ - container: 'body', - placement: 'right', - title: tp('source_viewer.tooltip.new_code', this.sinceLabel), - trigger: 'manual' - }).tooltip('show'); - }, - - hideFilteredTooltip: function (e) { - $(e.currentTarget).tooltip('destroy'); - }, - - toggleIssueLocations: function (issue) { - if (this.locationsShowFor === issue) { - this.hideIssueLocations(); - } else { - this.hideIssueLocations(); - this.showIssueLocations(issue); + }); + duplications = _.pairs(duplications).map(function (line) { + return { + line: +line[0], + duplicated: line[1] + }; + }); + } + that.model.addMeta(duplications); + that.model.addDuplications(data.duplications); + that.model.set({ + duplications: data.duplications, + duplicationsParsed: duplications, + duplicationFiles: data.files + }); + }); + }, + + requestIssues: function () { + var that = this, + options = { + data: { + componentUuids: this.model.id, + f: 'component,componentId,project,subProject,rule,status,resolution,author,reporter,assignee,debt,' + + 'line,message,severity,actionPlan,creationDate,updateDate,closeDate,tags,comments,attr,actions,' + + 'transitions,actionPlanName', + additionalFields: '_all', + resolved: false, + s: 'FILE_LINE', + asc: true, + ps: this.ISSUES_LIMIT } - }, + }; + return this.issues.fetch(options).done(function () { + that.addIssuesPerLineMeta(that.issues); + }); + }, - showIssueLocations: function (issue) { - this.locationsShowFor = issue; - var primaryLocation = { - msg: issue.get('message'), - textRange: issue.get('textRange') - }, - _locations = [primaryLocation]; - issue.get('flows').forEach(function (flow) { - var flowLocationsCount = _.size(flow.locations); - var flowLocations = flow.locations.map(function (location, index) { - var _location = _.extend({}, location); - if (flowLocationsCount > 1) { - _.extend(_location, { index: flowLocationsCount - index }); - } - return _location; - }); - _locations = [].concat(_locations, flowLocations); + _sortBySeverity: function (issues) { + var order = ['BLOCKER', 'CRITICAL', 'MAJOR', 'MINOR', 'INFO']; + return _.sortBy(issues, function (issue) { + return order.indexOf(issue.severity); + }); + }, + + addIssuesPerLineMeta: function (issues) { + var that = this, + lines = {}; + issues.forEach(function (issue) { + var line = issue.get('line') || 0; + if (!_.isArray(lines[line])) { + lines[line] = []; + } + lines[line].push(issue.toJSON()); + }); + var issuesPerLine = _.pairs(lines).map(function (line) { + return { + line: +line[0], + issues: that._sortBySeverity(line[1]) + }; + }); + this.model.addMeta(issuesPerLine); + this.addIssueLocationsMeta(issues); + }, + + addIssueLocationsMeta: function (issues) { + var issueLocations = []; + issues.forEach(function (issue) { + issue.getLinearLocations().forEach(function (location) { + var record = _.findWhere(issueLocations, { line: location.line }); + if (record) { + record.issueLocations.push({ from: location.from, to: location.to }); + } else { + issueLocations.push({ + line: location.line, + issueLocations: [{ from: location.from, to: location.to }] }); - _locations.forEach(this.showIssueLocation, this); - }, - - showIssueLocation: function (location, index) { - if (location && location.textRange) { - var line = location.textRange.startLine, - row = this.$('.source-line-code[data-line-number="' + line + '"]'); - - if (index > 0 && _.size(location.msg)) { - // render location marker only for - // secondary locations and execution flows - // and only if message is not empty - var renderedFlowLocation = this.renderIssueLocation(location); - row.find('.source-line-issue-locations').prepend(renderedFlowLocation); - } - - this.highlightIssueLocationInCode(location); - } - }, - - renderIssueLocation: function (location) { - location.msg = location.msg ? location.msg : ' '; - return this.issueLocationTemplate(location); - }, - - highlightIssueLocationInCode: function (location) { - for (var line = location.textRange.startLine; line <= location.textRange.endLine; line++) { - var row = this.$('.source-line-code[data-line-number="' + line + '"]'); - - // get location for the current line - var from = line === location.textRange.startLine ? location.textRange.startOffset : 0, - to = line === location.textRange.endLine ? location.textRange.endOffset : 999999, - _location = { from: from, to: to }; + } + }); + }); + this.model.addMeta(issueLocations); + }, - // mark issue location in the source code - var codeEl = row.find('.source-line-code-inner > pre'), - code = codeEl.html(), - newCode = highlightLocations(code, [_location], 'source-line-code-secondary-issue'); - codeEl.html(newCode); - } - }, + renderIssues: function () { + this.$('.issue-list').addClass('hidden'); + }, - hideIssueLocations: function () { - this.locationsShowFor = null; - this.$('.source-line-issue-locations').empty(); - this.$('.source-line-code-secondary-issue').removeClass('source-line-code-secondary-issue'); + renderIssue: function (issue) { + var issueView = new IssueView({ + el: '#issue-' + issue.get('key'), + model: issue + }); + this.issueViews.push(issueView); + issueView.render(); + }, + + addIssue: function (issue) { + var line = issue.get('line') || 0, + code = this.$('.source-line-code[data-line-number=' + line + ']'), + issueBox = '<div class="issue" id="issue-' + issue.get('key') + '" data-key="' + issue.get('key') + '">'; + code.addClass('has-issues'); + var issueList = code.find('.issue-list'); + if (issueList.length === 0) { + code.append('<div class="issue-list"></div>'); + issueList = code.find('.issue-list'); + } + issueList + .append(issueBox) + .removeClass('hidden'); + this.renderIssue(issue); + }, + + showIssuesForLine: function (line) { + this.$('.source-line-code[data-line-number="' + line + '"]').find('.issue-list').removeClass('hidden'); + var issues = this.issues.filter(function (issue) { + return (issue.get('line') === line) || (!issue.get('line') && !line); + }); + issues.forEach(this.renderIssue, this); + }, + + onIssuesSeverityChange: function () { + var that = this; + this.addIssuesPerLineMeta(this.issues); + this.$('.source-line-with-issues').each(function () { + var line = +$(this).data('line-number'), + row = _.findWhere(that.model.get('source'), { line: line }), + issue = _.first(row.issues); + $(this).html('<i class="icon-severity-' + issue.severity.toLowerCase() + '"></i>'); + }); + }, + + highlightUsages: function (e) { + var highlighted = $(e.currentTarget).is('.highlighted'), + key = e.currentTarget.className.split(/\s+/)[0]; + this.$('.sym.highlighted').removeClass('highlighted'); + if (!highlighted) { + this.$('.sym.' + key).addClass('highlighted'); + } + }, + + showSCMPopup: function (e) { + e.stopPropagation(); + $('body').click(); + var line = +$(e.currentTarget).data('line-number'), + row = _.findWhere(this.model.get('source'), { line: line }), + popup = new SCMPopupView({ + triggerEl: $(e.currentTarget), + model: new Backbone.Model(row) + }); + popup.render(); + }, + + showCoveragePopup: function (e) { + e.stopPropagation(); + $('body').click(); + this.clearTooltips(); + var line = $(e.currentTarget).data('line-number'), + row = _.findWhere(this.model.get('source'), { line: line }), + url = baseUrl + '/api/tests/list', + options = { + sourceFileUuid: this.model.id, + sourceFileLineNumber: line, + ps: 1000 + }; + return $.get(url, options).done(function (data) { + var popup = new CoveragePopupView({ + collection: new Backbone.Collection(data.tests), + row: row, + tests: $(e.currentTarget).data('tests'), + triggerEl: $(e.currentTarget) + }); + popup.render(); + }); + }, + + showDuplications: function (e) { + var that = this, + lineNumber = $(e.currentTarget).closest('.source-line').data('line-number'); + this.clearTooltips(); + this.requestDuplications().done(function () { + that.render(); + that.$el.addClass('source-duplications-expanded'); + + // immediately show dropdown popup if there is only one duplicated block + if (that.model.get('duplications').length === 1) { + var dupsBlock = that.$('.source-line[data-line-number=' + lineNumber + ']') + .find('.source-line-duplications-extra'); + dupsBlock.click(); + } + }); + }, + + showDuplicationPopup: function (e) { + e.stopPropagation(); + $('body').click(); + this.clearTooltips(); + var index = $(e.currentTarget).data('index'), + line = $(e.currentTarget).data('line-number'), + blocks = this.model.get('duplications')[index - 1].blocks, + inRemovedComponent = _.some(blocks, function (b) { + return b._ref == null; + }), + foundOne = false; + blocks = _.filter(blocks, function (b) { + var outOfBounds = b.from > line || b.from + b.size < line, + currentFile = b._ref === '1', + shouldDisplayForCurrentFile = outOfBounds || foundOne, + shouldDisplay = !currentFile || (currentFile && shouldDisplayForCurrentFile), + isOk = (b._ref != null) && shouldDisplay; + if (b._ref === '1' && !outOfBounds) { + foundOne = true; + } + return isOk; + }); + var popup = new DuplicationPopupView({ + triggerEl: $(e.currentTarget), + model: this.model, + inRemovedComponent: inRemovedComponent, + collection: new Backbone.Collection(blocks) + }); + popup.render(); + }, + + onLineIssuesClick: function (e) { + var line = $(e.currentTarget).data('line-number'), + issuesList = $(e.currentTarget).parent().find('.issue-list'), + areIssuesRendered = issuesList.find('.issue-inner').length > 0; + if (issuesList.is('.hidden')) { + if (areIssuesRendered) { + issuesList.removeClass('hidden'); + } else { + this.showIssuesForLine(line); + } + } else { + issuesList.addClass('hidden'); + } + }, + + showLineActionsPopup: function (e) { + e.stopPropagation(); + $('body').click(); + var that = this, + line = $(e.currentTarget).data('line-number'), + popup = new LineActionsPopupView({ + triggerEl: $(e.currentTarget), + model: this.model, + line: line, + row: $(e.currentTarget).closest('.source-line') + }); + popup.on('onManualIssueAdded', function (issue) { + that.addIssue(issue); + }); + popup.render(); + }, + + onLineNumberClick: function (e) { + var row = $(e.currentTarget).closest('.source-line'), + line = row.data('line-number'), + highlighted = row.is('.' + HIGHLIGHTED_ROW_CLASS); + if (!highlighted) { + this.highlightLine(line); + this.showLineActionsPopup(e); + } else { + this.removeHighlighting(); + } + }, + + removeHighlighting: function () { + this.highlightedLine = null; + this.$('.' + HIGHLIGHTED_ROW_CLASS).removeClass(HIGHLIGHTED_ROW_CLASS); + }, + + highlightLine: function (line) { + var row = this.$('.source-line[data-line-number=' + line + ']'); + this.removeHighlighting(); + this.highlightedLine = line; + row.addClass(HIGHLIGHTED_ROW_CLASS); + return this; + }, + + bindScrollEvents: function () { + var that = this; + this.$el.scrollParent().on('scroll.source-viewer', function () { + that.onScroll(); + }); + }, + + unbindScrollEvents: function () { + this.$el.scrollParent().off('scroll.source-viewer'); + }, + + onScroll: function () { + var p = this.$el.scrollParent(); + if (p.is(document)) { + p = $(window); + } + var pTopOffset = p.offset() != null ? p.offset().top : 0, + pPosition = p.scrollTop() + pTopOffset; + if (this.model.get('hasSourceBefore') && (pPosition <= this.ui.sourceBeforeSpinner.offset().top)) { + this.loadSourceBeforeThrottled(); + } + if (this.model.get('hasSourceAfter') && (pPosition + p.height() >= this.ui.sourceAfterSpinner.offset().top)) { + return this.loadSourceAfterThrottled(); + } + }, + + scrollToLine: function (line) { + var row = this.$('.source-line[data-line-number=' + line + ']'); + if (row.length > 0) { + var p = this.$el.scrollParent(); + if (p.is(document)) { + p = $(window); + } + var pTopOffset = p.offset() != null ? p.offset().top : 0, + pHeight = p.height(), + goal = row.offset().top - pHeight / 3 - pTopOffset; + p.scrollTop(goal); + } + return this; + }, + + scrollToFirstLine: function (line) { + var row = this.$('.source-line[data-line-number=' + line + ']'); + if (row.length > 0) { + var p = this.$el.scrollParent(); + if (p.is(document)) { + p = $(window); + } + var pTopOffset = p.offset() != null ? p.offset().top : 0, + goal = row.offset().top - pTopOffset; + p.scrollTop(goal); + } + return this; + }, + + scrollToLastLine: function (line) { + var row = this.$('.source-line[data-line-number=' + line + ']'); + if (row.length > 0) { + var p = this.$el.scrollParent(); + if (p.is(document)) { + p = $(window); + } + var pTopOffset = p.offset() != null ? p.offset().top : 0, + pHeight = p.height(), + goal = row.offset().top - pTopOffset - pHeight + row.height(); + p.scrollTop(goal); + } + return this; + }, + + loadSourceBefore: function () { + this.unbindScrollEvents(); + var that = this, + source = this.model.get('source'), + firstLine = _.first(source).line, + url = baseUrl + '/api/sources/lines', + options = { + uuid: this.model.id, + from: firstLine - this.LINES_AROUND, + to: firstLine - 1 + }; + return $.get(url, options).done(function (data) { + source = (data.sources || []).concat(source); + if (source.length > that.TOTAL_LINES_LIMIT + 1) { + source = source.slice(0, that.TOTAL_LINES_LIMIT); + that.model.set({ hasSourceAfter: true }); + } + if (source.length === 0 || (source.length > 0 && _.first(source).line === 1)) { + source.unshift({ line: 0 }); + } + source = source.map(function (row) { + return _.extend(row, { + utCoverageStatus: that.getUTCoverageStatus(row), + itCoverageStatus: that.getItCoverageStatus(row) + }); + }); + that.model.set({ + source: source, + hasUTCoverage: that.model.hasUTCoverage(source), + hasITCoverage: that.model.hasITCoverage(source), + hasSourceBefore: (data.sources.length === that.LINES_AROUND) && (_.first(source).line > 0) + }); + that.addIssuesPerLineMeta(that.issues); + if (that.model.has('duplications')) { + that.model.addDuplications(that.model.get('duplications')); + that.model.addMeta(that.model.get('duplicationsParsed')); + } + that.model.checkIfHasDuplications(); + that.render(); + that.scrollToFirstLine(firstLine); + if (that.model.get('hasSourceBefore') || that.model.get('hasSourceAfter')) { + that.bindScrollEvents(); + } + }); + }, + + loadSourceAfter: function () { + this.unbindScrollEvents(); + var that = this, + source = this.model.get('source'), + lastLine = _.last(source).line, + url = baseUrl + '/api/sources/lines', + options = { + uuid: this.model.id, + from: lastLine + 1, + to: lastLine + this.LINES_AROUND + }; + return $.get(url, options).done(function (data) { + source = source.concat(data.sources); + if (source.length > that.TOTAL_LINES_LIMIT + 1) { + source = source.slice(source.length - that.TOTAL_LINES_LIMIT); + that.model.set({ hasSourceBefore: true }); + } + source = source.map(function (row) { + return _.extend(row, { + utCoverageStatus: that.getUTCoverageStatus(row), + itCoverageStatus: that.getItCoverageStatus(row) + }); + }); + that.model.set({ + source: source, + hasUTCoverage: that.model.hasUTCoverage(source), + hasITCoverage: that.model.hasITCoverage(source), + hasSourceAfter: data.sources.length === that.LINES_AROUND + }); + that.addIssuesPerLineMeta(that.issues); + if (that.model.has('duplications')) { + that.model.addDuplications(that.model.get('duplications')); + that.model.addMeta(that.model.get('duplicationsParsed')); + } + that.model.checkIfHasDuplications(); + that.render(); + that.scrollToLastLine(lastLine); + if (that.model.get('hasSourceBefore') || that.model.get('hasSourceAfter')) { + that.bindScrollEvents(); + } + }).fail(function () { + that.model.set({ + hasSourceAfter: false + }); + that.render(); + if (that.model.get('hasSourceBefore') || that.model.get('hasSourceAfter')) { + that.bindScrollEvents(); + } + }); + }, + + filterLines: function (func) { + var lines = this.model.get('source'), + $lines = this.$('.source-line'); + this.model.set('filterLinesFunc', func); + lines.forEach(function (line, idx) { + var $line = $($lines[idx]), + filtered = func(line) && line.line > 0; + $line.toggleClass('source-line-shadowed', !filtered); + $line.toggleClass('source-line-filtered', filtered); + }); + }, + + filterLinesByDate: function (date, label) { + var sinceDate = moment(date).toDate(); + this.sinceLabel = label; + this.filterLines(function (line) { + var scmDate = moment(line.scmDate).toDate(); + return scmDate >= sinceDate; + }); + }, + + showFilteredTooltip: function (e) { + $(e.currentTarget).tooltip({ + container: 'body', + placement: 'right', + title: tp('source_viewer.tooltip.new_code', this.sinceLabel), + trigger: 'manual' + }).tooltip('show'); + }, + + hideFilteredTooltip: function (e) { + $(e.currentTarget).tooltip('destroy'); + }, + + toggleIssueLocations: function (issue) { + if (this.locationsShowFor === issue) { + this.hideIssueLocations(); + } else { + this.hideIssueLocations(); + this.showIssueLocations(issue); + } + }, + + showIssueLocations: function (issue) { + this.locationsShowFor = issue; + var primaryLocation = { + msg: issue.get('message'), + textRange: issue.get('textRange') + }, + _locations = [primaryLocation]; + issue.get('flows').forEach(function (flow) { + var flowLocationsCount = _.size(flow.locations); + var flowLocations = flow.locations.map(function (location, index) { + var _location = _.extend({}, location); + if (flowLocationsCount > 1) { + _.extend(_location, { index: flowLocationsCount - index }); } + return _location; }); - + _locations = [].concat(_locations, flowLocations); }); + _locations.forEach(this.showIssueLocation, this); + }, + + showIssueLocation: function (location, index) { + if (location && location.textRange) { + var line = location.textRange.startLine, + row = this.$('.source-line-code[data-line-number="' + line + '"]'); + + if (index > 0 && _.size(location.msg)) { + // render location marker only for + // secondary locations and execution flows + // and only if message is not empty + var renderedFlowLocation = this.renderIssueLocation(location); + row.find('.source-line-issue-locations').prepend(renderedFlowLocation); + } + + this.highlightIssueLocationInCode(location); + } + }, + + renderIssueLocation: function (location) { + location.msg = location.msg ? location.msg : ' '; + return this.issueLocationTemplate(location); + }, + + highlightIssueLocationInCode: function (location) { + for (var line = location.textRange.startLine; line <= location.textRange.endLine; line++) { + var row = this.$('.source-line-code[data-line-number="' + line + '"]'); + + // get location for the current line + var from = line === location.textRange.startLine ? location.textRange.startOffset : 0, + to = line === location.textRange.endLine ? location.textRange.endOffset : 999999, + _location = { from: from, to: to }; + + // mark issue location in the source code + var codeEl = row.find('.source-line-code-inner > pre'), + code = codeEl.html(), + newCode = highlightLocations(code, [_location], 'source-line-code-secondary-issue'); + codeEl.html(newCode); + } + }, + + hideIssueLocations: function () { + this.locationsShowFor = null; + this.$('.source-line-issue-locations').empty(); + this.$('.source-line-code-secondary-issue').removeClass('source-line-code-secondary-issue'); + } +}); diff --git a/server/sonar-web/src/main/js/components/source-viewer/measures-overlay.js b/server/sonar-web/src/main/js/components/source-viewer/measures-overlay.js index 29cbbe06a5b..7283eaa2a2e 100644 --- a/server/sonar-web/src/main/js/components/source-viewer/measures-overlay.js +++ b/server/sonar-web/src/main/js/components/source-viewer/measures-overlay.js @@ -1,231 +1,229 @@ -define([ - 'components/common/modals', - './templates' -], function (ModalView) { +import $ from 'jquery'; +import _ from 'underscore'; +import ModalView from 'components/common/modals'; +import './templates'; - var $ = jQuery; +export default ModalView.extend({ + template: Templates['source-viewer-measures'], + testsOrder: ['ERROR', 'FAILURE', 'OK', 'SKIPPED'], - return ModalView.extend({ - template: Templates['source-viewer-measures'], - testsOrder: ['ERROR', 'FAILURE', 'OK', 'SKIPPED'], - - initialize: function () { - var that = this, - requests = [this.requestMeasures(), this.requestIssues()]; - if (this.model.get('isUnitTest')) { - requests.push(this.requestTests()); - } - this.testsScroll = 0; - $.when.apply($, requests).done(function () { - that.render(); - }); - }, - - events: function () { - return _.extend(ModalView.prototype.events.apply(this, arguments), { - 'click .js-sort-tests-by-duration': 'sortTestsByDuration', - 'click .js-sort-tests-by-name': 'sortTestsByName', - 'click .js-sort-tests-by-status': 'sortTestsByStatus', - 'click .js-show-test': 'showTest', - 'click .js-show-all-measures': 'showAllMeasures' - }); - }, - - onRender: function () { - ModalView.prototype.onRender.apply(this, arguments); - this.$('.js-pie-chart').pieChart(); - this.$('.js-test-list').scrollTop(this.testsScroll); - }, - - getMetrics: function () { - var metrics = '', - url = baseUrl + '/api/metrics/search'; - $.ajax({ - url: url, - async: false, - data: { ps: 9999 } - }).done(function (data) { - metrics = _.filter(data.metrics, function (metric) { - return metric.type !== 'DATA' && !metric.hidden; - }); - metrics = _.sortBy(metrics, 'name'); + initialize: function () { + var that = this, + requests = [this.requestMeasures(), this.requestIssues()]; + if (this.model.get('isUnitTest')) { + requests.push(this.requestTests()); + } + this.testsScroll = 0; + $.when.apply($, requests).done(function () { + that.render(); + }); + }, + + events: function () { + return _.extend(ModalView.prototype.events.apply(this, arguments), { + 'click .js-sort-tests-by-duration': 'sortTestsByDuration', + 'click .js-sort-tests-by-name': 'sortTestsByName', + 'click .js-sort-tests-by-status': 'sortTestsByStatus', + 'click .js-show-test': 'showTest', + 'click .js-show-all-measures': 'showAllMeasures' + }); + }, + + onRender: function () { + ModalView.prototype.onRender.apply(this, arguments); + this.$('.js-pie-chart').pieChart(); + this.$('.js-test-list').scrollTop(this.testsScroll); + }, + + getMetrics: function () { + var metrics = '', + url = baseUrl + '/api/metrics/search'; + $.ajax({ + url: url, + async: false, + data: { ps: 9999 } + }).done(function (data) { + metrics = _.filter(data.metrics, function (metric) { + return metric.type !== 'DATA' && !metric.hidden; }); - return metrics; - }, + metrics = _.sortBy(metrics, 'name'); + }); + return metrics; + }, - calcAdditionalMeasures: function (measures) { - if (measures.lines_to_cover && measures.uncovered_lines) { - measures.covered_lines = measures.lines_to_cover - measures.uncovered_lines; - } - if (measures.conditions_to_cover && measures.uncovered_conditions) { - measures.covered_conditions = measures.conditions_to_cover - measures.uncovered_conditions; - } - if (measures.it_lines_to_cover && measures.it_uncovered_lines) { - measures.it_covered_lines = measures.it_lines_to_cover - measures.it_uncovered_lines; - } - if (measures.it_conditions_to_cover && measures.it_uncovered_conditions) { - measures.it_covered_conditions = measures.it_conditions_to_cover - measures.it_uncovered_conditions; - } - return measures; - }, - - - prepareMetrics: function (metrics) { - metrics = _.filter(metrics, function (metric) { - return metric.value != null; - }); - return _.sortBy( - _.map(_.pairs(_.groupBy(metrics, 'domain')), function (domain) { - return { - name: domain[0], - metrics: domain[1] - }; - }), - 'name' - ); - }, - - - requestMeasures: function () { - var that = this, - url = baseUrl + '/api/resources', - metrics = this.getMetrics(), - options = { - resource: this.model.key(), - metrics: _.pluck(metrics, 'key').join() + calcAdditionalMeasures: function (measures) { + if (measures.lines_to_cover && measures.uncovered_lines) { + measures.covered_lines = measures.lines_to_cover - measures.uncovered_lines; + } + if (measures.conditions_to_cover && measures.uncovered_conditions) { + measures.covered_conditions = measures.conditions_to_cover - measures.uncovered_conditions; + } + if (measures.it_lines_to_cover && measures.it_uncovered_lines) { + measures.it_covered_lines = measures.it_lines_to_cover - measures.it_uncovered_lines; + } + if (measures.it_conditions_to_cover && measures.it_uncovered_conditions) { + measures.it_covered_conditions = measures.it_conditions_to_cover - measures.it_uncovered_conditions; + } + return measures; + }, + + + prepareMetrics: function (metrics) { + metrics = _.filter(metrics, function (metric) { + return metric.value != null; + }); + return _.sortBy( + _.map(_.pairs(_.groupBy(metrics, 'domain')), function (domain) { + return { + name: domain[0], + metrics: domain[1] }; - return $.get(url, options).done(function (data) { - var measuresList = data[0].msr || [], - measures = that.model.get('measures') || {}; - measuresList.forEach(function (m) { - var metric = _.findWhere(metrics, { key: m.key }); - metric.value = m.frmt_val || m.data; - measures[m.key] = m.frmt_val || m.data; - measures[m.key + '_raw'] = m.val; - }); - measures = that.calcAdditionalMeasures(measures); - that.model.set({ - measures: measures, - measuresToDisplay: that.prepareMetrics(metrics) - }); + }), + 'name' + ); + }, + + + requestMeasures: function () { + var that = this, + url = baseUrl + '/api/resources', + metrics = this.getMetrics(), + options = { + resource: this.model.key(), + metrics: _.pluck(metrics, 'key').join() + }; + return $.get(url, options).done(function (data) { + var measuresList = data[0].msr || [], + measures = that.model.get('measures') || {}; + measuresList.forEach(function (m) { + var metric = _.findWhere(metrics, { key: m.key }); + metric.value = m.frmt_val || m.data; + measures[m.key] = m.frmt_val || m.data; + measures[m.key + '_raw'] = m.val; }); - }, - - requestIssues: function () { - var that = this, - url = baseUrl + '/api/issues/search', - options = { - componentUuids: this.model.id, - resolved: false, - ps: 1, - facets: 'severities,tags' - }; - return $.get(url, options).done(function (data) { - var issuesFacets = {}; - data.facets.forEach(function (facet) { - issuesFacets[facet.property] = facet.values; - }); - var severityOrder = ['BLOCKER', 'CRITICAL', 'MAJOR', 'MINOR', 'INFO'], - maxCountBySeverity = _.max(issuesFacets.severities, function (s) { - return s.count; - }).count, - maxCountByTag = _.max(issuesFacets.tags, function (s) { - return s.count; - }).count; - issuesFacets.severities = _.sortBy(issuesFacets.severities, function (s) { - return severityOrder.indexOf(s.val); - }); - that.model.set({ - issuesFacets: issuesFacets, - issuesCount: data.total, - maxCountBySeverity: maxCountBySeverity, - maxCountByTag: maxCountByTag - }); + measures = that.calcAdditionalMeasures(measures); + that.model.set({ + measures: measures, + measuresToDisplay: that.prepareMetrics(metrics) }); - }, - - requestTests: function () { - var that = this, - url = baseUrl + '/api/tests/list', - options = { testFileUuid: this.model.id }; - return $.get(url, options).done(function (data) { - that.model.set({ tests: data.tests }); - that.testSorting = 'status'; - that.testAsc = true; - that.sortTests(function (test) { - return '' + that.testsOrder.indexOf(test.status) + '_______' + test.name; - }); + }); + }, + + requestIssues: function () { + var that = this, + url = baseUrl + '/api/issues/search', + options = { + componentUuids: this.model.id, + resolved: false, + ps: 1, + facets: 'severities,tags' + }; + return $.get(url, options).done(function (data) { + var issuesFacets = {}; + data.facets.forEach(function (facet) { + issuesFacets[facet.property] = facet.values; }); - }, - - sortTests: function (condition) { - var tests = this.model.get('tests'); - if (_.isArray(tests)) { - tests = _.sortBy(tests, condition); - if (!this.testAsc) { - tests.reverse(); - } - this.model.set({ tests: tests }); - } - }, - - sortTestsByDuration: function () { - if (this.testSorting === 'duration') { - this.testAsc = !this.testAsc; - } - this.sortTests('durationInMs'); - this.testSorting = 'duration'; - this.render(); - }, - - sortTestsByName: function () { - if (this.testSorting === 'name') { - this.testAsc = !this.testAsc; - } - this.sortTests('name'); - this.testSorting = 'name'; - this.render(); - }, - - sortTestsByStatus: function () { - var that = this; - if (this.testSorting === 'status') { - this.testAsc = !this.testAsc; - } - this.sortTests(function (test) { - return '' + that.testsOrder.indexOf(test.status) + '_______' + test.name; + var severityOrder = ['BLOCKER', 'CRITICAL', 'MAJOR', 'MINOR', 'INFO'], + maxCountBySeverity = _.max(issuesFacets.severities, function (s) { + return s.count; + }).count, + maxCountByTag = _.max(issuesFacets.tags, function (s) { + return s.count; + }).count; + issuesFacets.severities = _.sortBy(issuesFacets.severities, function (s) { + return severityOrder.indexOf(s.val); }); - this.testSorting = 'status'; - this.render(); - }, - - showTest: function (e) { - var that = this, - testUuid = $(e.currentTarget).data('id'), - url = baseUrl + '/api/tests/covered_files', - options = { testUuid: testUuid }; - this.testsScroll = $(e.currentTarget).scrollParent().scrollTop(); - return $.get(url, options).done(function (data) { - that.coveredFiles = data.files; - that.selectedTest = _.findWhere(that.model.get('tests'), { testUuid: testUuid }); - that.render(); + that.model.set({ + issuesFacets: issuesFacets, + issuesCount: data.total, + maxCountBySeverity: maxCountBySeverity, + maxCountByTag: maxCountByTag }); - }, - - showAllMeasures: function () { - this.$('.js-all-measures').removeClass('hidden'); - this.$('.js-show-all-measures').remove(); - }, - - serializeData: function () { - return _.extend(ModalView.prototype.serializeData.apply(this, arguments), { - testSorting: this.testSorting, - selectedTest: this.selectedTest, - coveredFiles: this.coveredFiles || [] + }); + }, + + requestTests: function () { + var that = this, + url = baseUrl + '/api/tests/list', + options = { testFileUuid: this.model.id }; + return $.get(url, options).done(function (data) { + that.model.set({ tests: data.tests }); + that.testSorting = 'status'; + that.testAsc = true; + that.sortTests(function (test) { + return '' + that.testsOrder.indexOf(test.status) + '_______' + test.name; }); + }); + }, + + sortTests: function (condition) { + var tests = this.model.get('tests'); + if (_.isArray(tests)) { + tests = _.sortBy(tests, condition); + if (!this.testAsc) { + tests.reverse(); + } + this.model.set({ tests: tests }); } - }); + }, + sortTestsByDuration: function () { + if (this.testSorting === 'duration') { + this.testAsc = !this.testAsc; + } + this.sortTests('durationInMs'); + this.testSorting = 'duration'; + this.render(); + }, + + sortTestsByName: function () { + if (this.testSorting === 'name') { + this.testAsc = !this.testAsc; + } + this.sortTests('name'); + this.testSorting = 'name'; + this.render(); + }, + + sortTestsByStatus: function () { + var that = this; + if (this.testSorting === 'status') { + this.testAsc = !this.testAsc; + } + this.sortTests(function (test) { + return '' + that.testsOrder.indexOf(test.status) + '_______' + test.name; + }); + this.testSorting = 'status'; + this.render(); + }, + + showTest: function (e) { + var that = this, + testUuid = $(e.currentTarget).data('id'), + url = baseUrl + '/api/tests/covered_files', + options = { testUuid: testUuid }; + this.testsScroll = $(e.currentTarget).scrollParent().scrollTop(); + return $.get(url, options).done(function (data) { + that.coveredFiles = data.files; + that.selectedTest = _.findWhere(that.model.get('tests'), { testUuid: testUuid }); + that.render(); + }); + }, + + showAllMeasures: function () { + this.$('.js-all-measures').removeClass('hidden'); + this.$('.js-show-all-measures').remove(); + }, + + serializeData: function () { + return _.extend(ModalView.prototype.serializeData.apply(this, arguments), { + testSorting: this.testSorting, + selectedTest: this.selectedTest, + coveredFiles: this.coveredFiles || [] + }); + } }); + + diff --git a/server/sonar-web/src/main/js/components/source-viewer/more-actions.js b/server/sonar-web/src/main/js/components/source-viewer/more-actions.js index 9668ebf66a1..93704f062a7 100644 --- a/server/sonar-web/src/main/js/components/source-viewer/more-actions.js +++ b/server/sonar-web/src/main/js/components/source-viewer/more-actions.js @@ -1,55 +1,52 @@ -define([ - 'components/workspace/main', - './templates' -], function (Workspace) { - - var $ = jQuery; - - return Marionette.ItemView.extend({ - className: 'source-viewer-header-more-actions', - template: Templates['source-viewer-more-actions'], - - events: { - 'click .js-measures': 'showMeasures', - 'click .js-new-window': 'openNewWindow', - 'click .js-workspace': 'openInWorkspace', - 'click .js-raw-source': 'showRawSource' - }, - - onRender: function () { - var that = this; - $('body').on('click.component-viewer-more-actions', function () { - $('body').off('click.component-viewer-more-actions'); - that.destroy(); - }); - }, - - showMeasures: function () { - this.options.parent.showMeasures(); - }, - - openNewWindow: function () { - this.options.parent.getPermalink(); - }, - - openInWorkspace: function () { - var uuid = this.options.parent.model.id; - if (Workspace == null) { - Workspace = require('components/workspace/main'); - } - Workspace.openComponent({ uuid: uuid }); - }, - - showRawSource: function () { - this.options.parent.showRawSources(); - }, - - serializeData: function () { - var options = this.options.parent.options.viewer.options; - return _.extend(Marionette.ItemView.prototype.serializeData.apply(this, arguments), { - options: options - }); - } - }); - +import $ from 'jquery'; +import _ from 'underscore'; +import Marionette from 'backbone.marionette'; +import Workspace from 'components/workspace/main'; +import './templates'; + +export default Marionette.ItemView.extend({ + className: 'source-viewer-header-more-actions', + template: Templates['source-viewer-more-actions'], + + events: { + 'click .js-measures': 'showMeasures', + 'click .js-new-window': 'openNewWindow', + 'click .js-workspace': 'openInWorkspace', + 'click .js-raw-source': 'showRawSource' + }, + + onRender: function () { + var that = this; + $('body').on('click.component-viewer-more-actions', function () { + $('body').off('click.component-viewer-more-actions'); + that.destroy(); + }); + }, + + showMeasures: function () { + this.options.parent.showMeasures(); + }, + + openNewWindow: function () { + this.options.parent.getPermalink(); + }, + + openInWorkspace: function () { + var uuid = this.options.parent.model.id; + var RealWorkspace = Workspace.openComponent ? Workspace : require('components/workspace/main'); + RealWorkspace.openComponent({ uuid: uuid }); + }, + + showRawSource: function () { + this.options.parent.showRawSources(); + }, + + serializeData: function () { + var options = this.options.parent.options.viewer.options; + return _.extend(Marionette.ItemView.prototype.serializeData.apply(this, arguments), { + options: options + }); + } }); + + diff --git a/server/sonar-web/src/main/js/components/source-viewer/popups/coverage-popup.js b/server/sonar-web/src/main/js/components/source-viewer/popups/coverage-popup.js index da624d60deb..9e3e0993ec4 100644 --- a/server/sonar-web/src/main/js/components/source-viewer/popups/coverage-popup.js +++ b/server/sonar-web/src/main/js/components/source-viewer/popups/coverage-popup.js @@ -1,55 +1,51 @@ -define([ - 'components/common/popup', - 'components/workspace/main', - '../templates' -], function (Popup, Workspace) { +import $ from 'jquery'; +import _ from 'underscore'; +import Popup from 'components/common/popup'; +import Workspace from 'components/workspace/main'; +import '../templates'; - var $ = jQuery; +export default Popup.extend({ + template: Templates['source-viewer-coverage-popup'], - return Popup.extend({ - template: Templates['source-viewer-coverage-popup'], + events: { + 'click a[data-uuid]': 'goToFile' + }, - events: { - 'click a[data-uuid]': 'goToFile' - }, + onRender: function () { + Popup.prototype.onRender.apply(this, arguments); + this.$('.bubble-popup-container').isolatedScroll(); + }, - onRender: function () { - Popup.prototype.onRender.apply(this, arguments); - this.$('.bubble-popup-container').isolatedScroll(); - }, + goToFile: function (e) { + e.stopPropagation(); + var uuid = $(e.currentTarget).data('uuid'); + var RealWorkspace = Workspace.openComponent ? Workspace : require('components/workspace/main'); + RealWorkspace.openComponent({ uuid: uuid }); + }, - goToFile: function (e) { - e.stopPropagation(); - var uuid = $(e.currentTarget).data('uuid'); - if (Workspace == null) { - Workspace = require('components/workspace/main'); - } - Workspace.openComponent({ uuid: uuid }); - }, - - serializeData: function () { - var row = this.options.row || {}, - tests = _.groupBy(this.collection.toJSON(), 'fileUuid'), - testFiles = _.map(tests, function (testSet) { - var test = testSet[0]; - return { - file: { - uuid: test.fileUuid, - longName: test.fileLongName - }, - tests: testSet - }; - }); - _.extend(row, { - lineHits: row[this.options.tests + 'LineHits'], - conditions: row[this.options.tests + 'Conditions'], - coveredConditions: row[this.options.tests + 'CoveredConditions'] - }); - return { - testFiles: testFiles, - tests: this.options.tests, - row: row - }; - } - }); + serializeData: function () { + var row = this.options.row || {}, + tests = _.groupBy(this.collection.toJSON(), 'fileUuid'), + testFiles = _.map(tests, function (testSet) { + var test = testSet[0]; + return { + file: { + uuid: test.fileUuid, + longName: test.fileLongName + }, + tests: testSet + }; + }); + _.extend(row, { + lineHits: row[this.options.tests + 'LineHits'], + conditions: row[this.options.tests + 'Conditions'], + coveredConditions: row[this.options.tests + 'CoveredConditions'] + }); + return { + testFiles: testFiles, + tests: this.options.tests, + row: row + }; + } }); + diff --git a/server/sonar-web/src/main/js/components/source-viewer/popups/duplication-popup.js b/server/sonar-web/src/main/js/components/source-viewer/popups/duplication-popup.js index 00967315d34..4d62ee40eb0 100644 --- a/server/sonar-web/src/main/js/components/source-viewer/popups/duplication-popup.js +++ b/server/sonar-web/src/main/js/components/source-viewer/popups/duplication-popup.js @@ -1,49 +1,45 @@ -define([ - 'components/common/popup', - 'components/workspace/main', - '../templates' -], function (Popup, Workspace) { +import $ from 'jquery'; +import _ from 'underscore'; +import Popup from 'components/common/popup'; +import Workspace from 'components/workspace/main'; +import '../templates'; - var $ = jQuery; +export default Popup.extend({ + template: Templates['source-viewer-duplication-popup'], - return Popup.extend({ - template: Templates['source-viewer-duplication-popup'], + events: { + 'click a[data-uuid]': 'goToFile' + }, - events: { - 'click a[data-uuid]': 'goToFile' - }, + goToFile: function (e) { + e.stopPropagation(); + var uuid = $(e.currentTarget).data('uuid'), + line = $(e.currentTarget).data('line'); + var RealWorkspace = Workspace.openComponent ? Workspace : require('components/workspace/main'); + RealWorkspace.openComponent({ uuid: uuid, line: line }); + }, - goToFile: function (e) { - e.stopPropagation(); - var uuid = $(e.currentTarget).data('uuid'), - line = $(e.currentTarget).data('line'); - if (Workspace == null) { - Workspace = require('components/workspace/main'); - } - Workspace.openComponent({ uuid: uuid, line: line }); - }, - - serializeData: function () { - var that = this, - files = this.model.get('duplicationFiles'), - groupedBlocks = _.groupBy(this.collection.toJSON(), '_ref'), - duplications = _.map(groupedBlocks, function (blocks, fileRef) { - return { - blocks: blocks, - file: files[fileRef] - }; - }); - duplications = _.sortBy(duplications, function (d) { - var a = d.file.projectName !== that.model.get('projectName'), - b = d.file.subProjectName !== that.model.get('subProjectName'), - c = d.file.key !== that.model.get('key'); - return '' + a + b + c; - }); - return { - component: this.model.toJSON(), - duplications: duplications, - inRemovedComponent: this.options.inRemovedComponent - }; - } - }); + serializeData: function () { + var that = this, + files = this.model.get('duplicationFiles'), + groupedBlocks = _.groupBy(this.collection.toJSON(), '_ref'), + duplications = _.map(groupedBlocks, function (blocks, fileRef) { + return { + blocks: blocks, + file: files[fileRef] + }; + }); + duplications = _.sortBy(duplications, function (d) { + var a = d.file.projectName !== that.model.get('projectName'), + b = d.file.subProjectName !== that.model.get('subProjectName'), + c = d.file.key !== that.model.get('key'); + return '' + a + b + c; + }); + return { + component: this.model.toJSON(), + duplications: duplications, + inRemovedComponent: this.options.inRemovedComponent + }; + } }); + diff --git a/server/sonar-web/src/main/js/components/source-viewer/popups/line-actions-popup.js b/server/sonar-web/src/main/js/components/source-viewer/popups/line-actions-popup.js index 3a4e0b21b33..dc9be5637e0 100644 --- a/server/sonar-web/src/main/js/components/source-viewer/popups/line-actions-popup.js +++ b/server/sonar-web/src/main/js/components/source-viewer/popups/line-actions-popup.js @@ -1,39 +1,37 @@ -define([ - 'components/common/popup', - 'components/issue/manual-issue-view', - '../templates' -], function (Popup, ManualIssueView) { +import Popup from 'components/common/popup'; +import ManualIssueView from 'components/issue/manual-issue-view'; +import '../templates'; - return Popup.extend({ - template: Templates['source-viewer-line-options-popup'], +export default Popup.extend({ + template: Templates['source-viewer-line-options-popup'], - events: { - 'click .js-get-permalink': 'getPermalink', - 'click .js-add-manual-issue': 'addManualIssue' - }, + events: { + 'click .js-get-permalink': 'getPermalink', + 'click .js-add-manual-issue': 'addManualIssue' + }, - getPermalink: function (e) { - e.preventDefault(); - var url = baseUrl + '/component/index?id=' + - (encodeURIComponent(this.model.key())) + '&line=' + this.options.line, - windowParams = 'resizable=1,scrollbars=1,status=1'; - window.open(url, this.model.get('name'), windowParams); - }, + getPermalink: function (e) { + e.preventDefault(); + var url = baseUrl + '/component/index?id=' + + (encodeURIComponent(this.model.key())) + '&line=' + this.options.line, + windowParams = 'resizable=1,scrollbars=1,status=1'; + window.open(url, this.model.get('name'), windowParams); + }, - addManualIssue: function (e) { - e.preventDefault(); - var that = this, - line = this.options.line, - component = this.model.key(), - manualIssueView = new ManualIssueView({ - line: line, - component: component - }); - manualIssueView.render().$el.appendTo(this.options.row.find('.source-line-code')); - manualIssueView.on('add', function (issue) { - that.trigger('onManualIssueAdded', issue); - }); - } - }); + addManualIssue: function (e) { + e.preventDefault(); + var that = this, + line = this.options.line, + component = this.model.key(), + manualIssueView = new ManualIssueView({ + line: line, + component: component + }); + manualIssueView.render().$el.appendTo(this.options.row.find('.source-line-code')); + manualIssueView.on('add', function (issue) { + that.trigger('onManualIssueAdded', issue); + }); + } }); + diff --git a/server/sonar-web/src/main/js/components/source-viewer/popups/scm-popup.js b/server/sonar-web/src/main/js/components/source-viewer/popups/scm-popup.js index 3aa152de292..d229f2e9d57 100644 --- a/server/sonar-web/src/main/js/components/source-viewer/popups/scm-popup.js +++ b/server/sonar-web/src/main/js/components/source-viewer/popups/scm-popup.js @@ -1,22 +1,20 @@ -define([ - 'components/common/popup', - '../templates' -], function (Popup) { +import Popup from 'components/common/popup'; +import '../templates'; - return Popup.extend({ - template: Templates['source-viewer-scm-popup'], +export default Popup.extend({ + template: Templates['source-viewer-scm-popup'], - events: { - 'click': 'onClick' - }, + events: { + 'click': 'onClick' + }, - onRender: function () { - Popup.prototype.onRender.apply(this, arguments); - this.$('.bubble-popup-container').isolatedScroll(); - }, + onRender: function () { + Popup.prototype.onRender.apply(this, arguments); + this.$('.bubble-popup-container').isolatedScroll(); + }, - onClick: function (e) { - e.stopPropagation(); - } - }); + onClick: function (e) { + e.stopPropagation(); + } }); + diff --git a/server/sonar-web/src/main/js/components/source-viewer/source.js b/server/sonar-web/src/main/js/components/source-viewer/source.js index ea33cbaeeb2..f2578ef07fd 100644 --- a/server/sonar-web/src/main/js/components/source-viewer/source.js +++ b/server/sonar-web/src/main/js/components/source-viewer/source.js @@ -1,90 +1,91 @@ -define(function () { +import _ from 'underscore'; +import Backbone from 'backbone'; - return Backbone.Model.extend({ - idAttribute: 'uuid', +export default Backbone.Model.extend({ + idAttribute: 'uuid', - defaults: function () { - return { - exist: true, + defaults: function () { + return { + exist: true, - hasSource: false, - hasCoverage: false, - hasITCoverage: false, - hasDuplications: false, - hasSCM: false, + hasSource: false, + hasCoverage: false, + hasITCoverage: false, + hasDuplications: false, + hasSCM: false, - canSeeCode: true - }; - }, + canSeeCode: true + }; + }, - key: function () { - return this.get('key'); - }, + key: function () { + return this.get('key'); + }, - addMeta: function (meta) { - var source = this.get('source'), - metaIdx = 0, - metaLine = meta[metaIdx]; - source.forEach(function (line) { - while (metaLine != null && line.line > metaLine.line) { - metaLine = meta[++metaIdx]; - } - if (metaLine != null && line.line === metaLine.line) { - _.extend(line, metaLine); - metaLine = meta[++metaIdx]; - } - }); - this.set({ source: source }); - }, + addMeta: function (meta) { + var source = this.get('source'), + metaIdx = 0, + metaLine = meta[metaIdx]; + source.forEach(function (line) { + while (metaLine != null && line.line > metaLine.line) { + metaLine = meta[++metaIdx]; + } + if (metaLine != null && line.line === metaLine.line) { + _.extend(line, metaLine); + metaLine = meta[++metaIdx]; + } + }); + this.set({ source: source }); + }, - addDuplications: function (duplications) { - var source = this.get('source'); - if (source != null) { - source.forEach(function (line) { - var lineDuplications = []; - duplications.forEach(function (d, i) { - var duplicated = false; - d.blocks.forEach(function (b) { - if (b._ref === '1') { - var lineFrom = b.from, - lineTo = b.from + b.size - 1; - if (line.line >= lineFrom && line.line <= lineTo) { - duplicated = true; - } + addDuplications: function (duplications) { + var source = this.get('source'); + if (source != null) { + source.forEach(function (line) { + var lineDuplications = []; + duplications.forEach(function (d, i) { + var duplicated = false; + d.blocks.forEach(function (b) { + if (b._ref === '1') { + var lineFrom = b.from, + lineTo = b.from + b.size - 1; + if (line.line >= lineFrom && line.line <= lineTo) { + duplicated = true; } - }); - lineDuplications.push(duplicated ? i + 1 : false); + } }); - line.duplications = lineDuplications; - }); - } - this.set({ source: source }); - }, - - checkIfHasDuplications: function () { - var hasDuplications = false, - source = this.get('source'); - if (source != null) { - source.forEach(function (line) { - if (line.duplicated) { - hasDuplications = true; - } + lineDuplications.push(duplicated ? i + 1 : false); }); - } - this.set({ hasDuplications: hasDuplications }); - }, - - hasUTCoverage: function (source) { - return _.some(source, function (line) { - return line.utCoverageStatus != null; + line.duplications = lineDuplications; }); - }, + } + this.set({ source: source }); + }, - hasITCoverage: function (source) { - return _.some(source, function (line) { - return line.itCoverageStatus != null; + checkIfHasDuplications: function () { + var hasDuplications = false, + source = this.get('source'); + if (source != null) { + source.forEach(function (line) { + if (line.duplicated) { + hasDuplications = true; + } }); } - }); + this.set({ hasDuplications: hasDuplications }); + }, + + hasUTCoverage: function (source) { + return _.some(source, function (line) { + return line.utCoverageStatus != null; + }); + }, + hasITCoverage: function (source) { + return _.some(source, function (line) { + return line.itCoverageStatus != null; + }); + } }); + + diff --git a/server/sonar-web/src/main/js/components/workspace/main.js b/server/sonar-web/src/main/js/components/workspace/main.js index 648ed854f7c..3718625541e 100644 --- a/server/sonar-web/src/main/js/components/workspace/main.js +++ b/server/sonar-web/src/main/js/components/workspace/main.js @@ -1,131 +1,129 @@ -define([ - './models/item', - './models/items', - './views/items-view', - './views/viewer-view', - './views/rule-view' -], function (Item, Items, ItemsView, ViewerView, RuleView) { - - var $ = jQuery, - - instance = null, - - Workspace = function () { - if (instance != null) { - throw new Error('Cannot instantiate more than one Workspace, use Workspace.getInstance()'); - } - this.initialize(); - }; - - Workspace.prototype = { - initialize: function () { - var that = this; - - this.items = new Items(); - this.items.load(); - this.items.on('change', function () { - that.save(); - }); - - this.itemsView = new ItemsView({ collection: this.items }); - this.itemsView.render().$el.appendTo(document.body); - this.itemsView.on('click', function (model) { - that.open(model); - }); - }, - - save: function () { - this.items.save(); - }, - - addComponent: function (model) { - var m = this.items.add2(model); - this.save(); - return m; - }, - - open: function (options) { - var model = typeof options.toJSON === 'function' ? options : new Item(options); - if (!model.isValid()) { - throw new Error(model.validationError); +import $ from 'jquery'; +import _ from 'underscore'; +import Item from './models/item'; +import Items from './models/items'; +import ItemsView from './views/items-view'; +import ViewerView from './views/viewer-view'; +import RuleView from './views/rule-view'; + +var instance = null, + + Workspace = function () { + if (instance != null) { + throw new Error('Cannot instantiate more than one Workspace, use Workspace.getInstance()'); } - var m = this.addComponent(model); - if (m.isComponent()) { - this.showComponentViewer(m); - } - if (m.isRule()) { - this.showRule(m); - } - }, + this.initialize(); + }; + +Workspace.prototype = { + initialize: function () { + var that = this; + + this.items = new Items(); + this.items.load(); + this.items.on('change', function () { + that.save(); + }); + + this.itemsView = new ItemsView({ collection: this.items }); + this.itemsView.render().$el.appendTo(document.body); + this.itemsView.on('click', function (model) { + that.open(model); + }); + }, + + save: function () { + this.items.save(); + }, + + addComponent: function (model) { + var m = this.items.add2(model); + this.save(); + return m; + }, + + open: function (options) { + var model = typeof options.toJSON === 'function' ? options : new Item(options); + if (!model.isValid()) { + throw new Error(model.validationError); + } + var m = this.addComponent(model); + if (m.isComponent()) { + this.showComponentViewer(m); + } + if (m.isRule()) { + this.showRule(m); + } + }, - openComponent: function (options) { - return this.open(_.extend(options, { type: 'component' })); - }, + openComponent: function (options) { + return this.open(_.extend(options, { type: 'component' })); + }, - openRule: function (options) { - return this.open(_.extend(options, { type: 'rule' })); - }, + openRule: function (options) { + return this.open(_.extend(options, { type: 'rule' })); + }, - showViewer: function (Viewer, model) { - var that = this; - if (this.viewerView != null) { - this.viewerView.model.trigger('hideViewer'); - this.viewerView.destroy(); - } - $('html').addClass('with-workspace'); - model.trigger('showViewer'); - this.viewerView = new Viewer({ model: model }); - this.viewerView - .on('viewerMinimize', function () { - model.trigger('hideViewer'); - that.closeComponentViewer(); - }) - .on('viewerClose', function (m) { - that.closeComponentViewer(); - m.destroy(); - }); - this.viewerView.render().$el.appendTo(document.body); - }, - - showComponentViewer: function (model) { - this.showViewer(ViewerView, model); - }, - - closeComponentViewer: function () { - if (this.viewerView != null) { - this.viewerView.destroy(); - $('.with-workspace').removeClass('with-workspace'); - } - }, - - showRule: function (model) { - var that = this; - this.fetchRule(model) - .done(function () { - model.set({ exist: true }); - that.showViewer(RuleView, model); - }).fail(function () { - model.set({ exist: false }); - that.showViewer(RuleView, model); - }); - }, - - fetchRule: function (model) { - var url = baseUrl + '/api/rules/show', - options = { key: model.get('key') }; - return $.get(url, options).done(function (r) { - model.set(r.rule); - }); + showViewer: function (Viewer, model) { + var that = this; + if (this.viewerView != null) { + this.viewerView.model.trigger('hideViewer'); + this.viewerView.destroy(); } - }; - - Workspace.getInstance = function () { - if (instance == null) { - instance = new Workspace(); + $('html').addClass('with-workspace'); + model.trigger('showViewer'); + this.viewerView = new Viewer({ model: model }); + this.viewerView + .on('viewerMinimize', function () { + model.trigger('hideViewer'); + that.closeComponentViewer(); + }) + .on('viewerClose', function (m) { + that.closeComponentViewer(); + m.destroy(); + }); + this.viewerView.render().$el.appendTo(document.body); + }, + + showComponentViewer: function (model) { + this.showViewer(ViewerView, model); + }, + + closeComponentViewer: function () { + if (this.viewerView != null) { + this.viewerView.destroy(); + $('.with-workspace').removeClass('with-workspace'); } - return instance; - }; + }, + + showRule: function (model) { + var that = this; + this.fetchRule(model) + .done(function () { + model.set({ exist: true }); + that.showViewer(RuleView, model); + }).fail(function () { + model.set({ exist: false }); + that.showViewer(RuleView, model); + }); + }, + + fetchRule: function (model) { + var url = baseUrl + '/api/rules/show', + options = { key: model.get('key') }; + return $.get(url, options).done(function (r) { + model.set(r.rule); + }); + } +}; + +Workspace.getInstance = function () { + if (instance == null) { + instance = new Workspace(); + } + return instance; +}; + +export default Workspace.getInstance(); - return Workspace.getInstance(); -}); diff --git a/server/sonar-web/src/main/js/components/workspace/models/item.js b/server/sonar-web/src/main/js/components/workspace/models/item.js index 98d2e9a2ba7..b5ba9c0efec 100644 --- a/server/sonar-web/src/main/js/components/workspace/models/item.js +++ b/server/sonar-web/src/main/js/components/workspace/models/item.js @@ -1,31 +1,31 @@ -define(function () { +import Backbone from 'backbone'; - return Backbone.Model.extend({ +export default Backbone.Model.extend({ - validate: function () { - if (!this.has('type')) { - return 'type is missing'; - } - if (this.get('type') === 'component' && !this.has('uuid')) { - return 'uuid is missing'; - } - if (this.get('type') === 'rule' && !this.has('key')) { - return 'key is missing'; - } - }, + validate: function () { + if (!this.has('type')) { + return 'type is missing'; + } + if (this.get('type') === 'component' && !this.has('uuid')) { + return 'uuid is missing'; + } + if (this.get('type') === 'rule' && !this.has('key')) { + return 'key is missing'; + } + }, - isComponent: function () { - return this.get('type') === 'component'; - }, + isComponent: function () { + return this.get('type') === 'component'; + }, - isRule: function () { - return this.get('type') === 'rule'; - }, - - destroy: function (options) { - this.stopListening(); - this.trigger('destroy', this, this.collection, options); - } - }); + isRule: function () { + return this.get('type') === 'rule'; + }, + destroy: function (options) { + this.stopListening(); + this.trigger('destroy', this, this.collection, options); + } }); + + diff --git a/server/sonar-web/src/main/js/components/workspace/models/items.js b/server/sonar-web/src/main/js/components/workspace/models/items.js index 8325a7f558c..037e8e15e14 100644 --- a/server/sonar-web/src/main/js/components/workspace/models/items.js +++ b/server/sonar-web/src/main/js/components/workspace/models/items.js @@ -1,43 +1,44 @@ -define(['./item'], function (Item) { - - var STORAGE_KEY = 'sonarqube-workspace'; - - return Backbone.Collection.extend({ - model: Item, - - initialize: function () { - this.on('remove', this.save); - }, - - save: function () { - var dump = JSON.stringify(this.toJSON()); - window.localStorage.setItem(STORAGE_KEY, dump); - }, - - load: function () { - var dump = window.localStorage.getItem(STORAGE_KEY); - if (dump != null) { - try { - var parsed = JSON.parse(dump); - this.reset(parsed); - } catch (err) { - // fail silently - } +import Backbone from 'backbone'; +import Item from './item'; + +var STORAGE_KEY = 'sonarqube-workspace'; + +export default Backbone.Collection.extend({ + model: Item, + + initialize: function () { + this.on('remove', this.save); + }, + + save: function () { + var dump = JSON.stringify(this.toJSON()); + window.localStorage.setItem(STORAGE_KEY, dump); + }, + + load: function () { + var dump = window.localStorage.getItem(STORAGE_KEY); + if (dump != null) { + try { + var parsed = JSON.parse(dump); + this.reset(parsed); + } catch (err) { + // fail silently } - }, - - has: function (model) { - var forComponent = model.isComponent() && this.findWhere({ uuid: model.get('uuid') }) != null, - forRule = model.isRule() && this.findWhere({ key: model.get('key') }) != null; - return forComponent || forRule; - }, - - add2: function (model) { - var tryModel = model.isComponent() ? - this.findWhere({ uuid: model.get('uuid') }) : - this.findWhere({ key: model.get('key') }); - return tryModel != null ? tryModel : this.add(model); } - }); - + }, + + has: function (model) { + var forComponent = model.isComponent() && this.findWhere({ uuid: model.get('uuid') }) != null, + forRule = model.isRule() && this.findWhere({ key: model.get('key') }) != null; + return forComponent || forRule; + }, + + add2: function (model) { + var tryModel = model.isComponent() ? + this.findWhere({ uuid: model.get('uuid') }) : + this.findWhere({ key: model.get('key') }); + return tryModel != null ? tryModel : this.add(model); + } }); + + diff --git a/server/sonar-web/src/main/js/components/workspace/views/base-viewer-view.js b/server/sonar-web/src/main/js/components/workspace/views/base-viewer-view.js index b742ed8c646..4be16e1f992 100644 --- a/server/sonar-web/src/main/js/components/workspace/views/base-viewer-view.js +++ b/server/sonar-web/src/main/js/components/workspace/views/base-viewer-view.js @@ -1,38 +1,37 @@ -define([ - './viewer-header-view' -], function (HeaderView) { - - return Marionette.LayoutView.extend({ - className: 'workspace-viewer', - - modelEvents: { - 'destroy': 'destroy' - }, - - regions: { - headerRegion: '.workspace-viewer-header', - viewerRegion: '.workspace-viewer-container' - }, - - onRender: function () { - this.showHeader(); - this.$('.workspace-viewer-container').isolatedScroll(); - }, - - onViewerMinimize: function () { - this.trigger('viewerMinimize'); - }, - - onViewerClose: function () { - this.trigger('viewerClose', this.model); - }, - - showHeader: function () { - var headerView = new HeaderView({ model: this.model }); - this.listenTo(headerView, 'viewerMinimize', this.onViewerMinimize); - this.listenTo(headerView, 'viewerClose', this.onViewerClose); - this.headerRegion.show(headerView); - } - }); - +import Marionette from 'backbone.marionette'; +import HeaderView from './viewer-header-view'; + +export default Marionette.LayoutView.extend({ + className: 'workspace-viewer', + + modelEvents: { + 'destroy': 'destroy' + }, + + regions: { + headerRegion: '.workspace-viewer-header', + viewerRegion: '.workspace-viewer-container' + }, + + onRender: function () { + this.showHeader(); + this.$('.workspace-viewer-container').isolatedScroll(); + }, + + onViewerMinimize: function () { + this.trigger('viewerMinimize'); + }, + + onViewerClose: function () { + this.trigger('viewerClose', this.model); + }, + + showHeader: function () { + var headerView = new HeaderView({ model: this.model }); + this.listenTo(headerView, 'viewerMinimize', this.onViewerMinimize); + this.listenTo(headerView, 'viewerClose', this.onViewerClose); + this.headerRegion.show(headerView); + } }); + + diff --git a/server/sonar-web/src/main/js/components/workspace/views/item-view.js b/server/sonar-web/src/main/js/components/workspace/views/item-view.js index 3a9a9527755..c307e69916d 100644 --- a/server/sonar-web/src/main/js/components/workspace/views/item-view.js +++ b/server/sonar-web/src/main/js/components/workspace/views/item-view.js @@ -1,41 +1,40 @@ -define([ - '../templates' -], function () { - - return Marionette.ItemView.extend({ - tagName: 'li', - className: 'workspace-nav-item', - template: Templates['workspace-item'], - - modelEvents: { - 'change': 'render', - 'showViewer': 'onViewerShow', - 'hideViewer': 'onViewerHide' - }, - - events: { - 'click': 'onClick', - 'click .js-close': 'onCloseClick' - }, - - onClick: function (e) { - e.preventDefault(); - this.options.collectionView.trigger('click', this.model); - }, - - onCloseClick: function (e) { - e.preventDefault(); - e.stopPropagation(); - this.model.destroy(); - }, - - onViewerShow: function () { - this.$el.addClass('hidden'); - }, - - onViewerHide: function () { - this.$el.removeClass('hidden'); - } - }); - +import Marionette from 'backbone.marionette'; +import '../templates'; + +export default Marionette.ItemView.extend({ + tagName: 'li', + className: 'workspace-nav-item', + template: Templates['workspace-item'], + + modelEvents: { + 'change': 'render', + 'showViewer': 'onViewerShow', + 'hideViewer': 'onViewerHide' + }, + + events: { + 'click': 'onClick', + 'click .js-close': 'onCloseClick' + }, + + onClick: function (e) { + e.preventDefault(); + this.options.collectionView.trigger('click', this.model); + }, + + onCloseClick: function (e) { + e.preventDefault(); + e.stopPropagation(); + this.model.destroy(); + }, + + onViewerShow: function () { + this.$el.addClass('hidden'); + }, + + onViewerHide: function () { + this.$el.removeClass('hidden'); + } }); + + diff --git a/server/sonar-web/src/main/js/components/workspace/views/items-view.js b/server/sonar-web/src/main/js/components/workspace/views/items-view.js index 9341b986f22..c244ff9c450 100644 --- a/server/sonar-web/src/main/js/components/workspace/views/items-view.js +++ b/server/sonar-web/src/main/js/components/workspace/views/items-view.js @@ -1,17 +1,16 @@ -define([ - './item-view', - '../templates' -], function (ItemView) { +import Marionette from 'backbone.marionette'; +import ItemView from './item-view'; +import '../templates'; - return Marionette.CompositeView.extend({ - className: 'workspace-nav', - template: Templates['workspace-items'], - childViewContainer: '.workspace-nav-list', - childView: ItemView, - - childViewOptions: function () { - return { collectionView: this }; - } - }); +export default Marionette.CompositeView.extend({ + className: 'workspace-nav', + template: Templates['workspace-items'], + childViewContainer: '.workspace-nav-list', + childView: ItemView, + childViewOptions: function () { + return { collectionView: this }; + } }); + + diff --git a/server/sonar-web/src/main/js/components/workspace/views/rule-view.js b/server/sonar-web/src/main/js/components/workspace/views/rule-view.js index 9b918af2949..6b3fd957638 100644 --- a/server/sonar-web/src/main/js/components/workspace/views/rule-view.js +++ b/server/sonar-web/src/main/js/components/workspace/views/rule-view.js @@ -1,25 +1,25 @@ -define([ - './base-viewer-view', - '../templates' -], function (BaseView) { +import _ from 'underscore'; +import Marionette from 'backbone.marionette'; +import BaseView from './base-viewer-view'; +import '../templates'; - return BaseView.extend({ - template: Templates['workspace-rule'], +export default BaseView.extend({ + template: Templates['workspace-rule'], - onRender: function () { - BaseView.prototype.onRender.apply(this, arguments); - this.$('[data-toggle="tooltip"]').tooltip({ container: 'body' }); - }, + onRender: function () { + BaseView.prototype.onRender.apply(this, arguments); + this.$('[data-toggle="tooltip"]').tooltip({ container: 'body' }); + }, - onDestroy: function () { - this.$('[data-toggle="tooltip"]').tooltip('destroy'); - }, - - serializeData: function () { - return _.extend(Marionette.LayoutView.prototype.serializeData.apply(this, arguments), { - allTags: _.union(this.model.get('sysTags'), this.model.get('tags')) - }); - } - }); + onDestroy: function () { + this.$('[data-toggle="tooltip"]').tooltip('destroy'); + }, + serializeData: function () { + return _.extend(Marionette.LayoutView.prototype.serializeData.apply(this, arguments), { + allTags: _.union(this.model.get('sysTags'), this.model.get('tags')) + }); + } }); + + diff --git a/server/sonar-web/src/main/js/components/workspace/views/viewer-header-view.js b/server/sonar-web/src/main/js/components/workspace/views/viewer-header-view.js index 15f79a27636..b0c03b77edd 100644 --- a/server/sonar-web/src/main/js/components/workspace/views/viewer-header-view.js +++ b/server/sonar-web/src/main/js/components/workspace/views/viewer-header-view.js @@ -1,95 +1,94 @@ -define([ - '../templates' -], function () { - - var $ = jQuery; - - return Marionette.ItemView.extend({ - template: Templates['workspace-viewer-header'], - - modelEvents: { - 'change': 'render' - }, - - events: { - 'mousedown .js-resize': 'onResizeClick', - - 'click .js-minimize': 'onMinimizeClick', - 'click .js-full-screen': 'onFullScreenClick', - 'click .js-normal-size': 'onNormalSizeClick', - 'click .js-close': 'onCloseClick' - }, - - onRender: function () { - this.$('[data-toggle="tooltip"]').tooltip({ container: 'body' }); - this.$('.js-normal-size').addClass('hidden'); - }, - - onDestroy: function () { - this.$('[data-toggle="tooltip"]').tooltip('destroy'); - $('.tooltip').remove(); - }, - - onResizeClick: function (e) { - e.preventDefault(); - this.startResizing(e); - }, - - onMinimizeClick: function (e) { - e.preventDefault(); - this.trigger('viewerMinimize'); - }, - - onFullScreenClick: function (e) { - e.preventDefault(); - this.toFullScreen(); - }, - - onNormalSizeClick: function (e) { - e.preventDefault(); - this.toNormalSize(); - }, - - onCloseClick: function (e) { - e.preventDefault(); - this.trigger('viewerClose'); - }, - - startResizing: function (e) { - this.initialResizePosition = e.clientY; - this.initialResizeHeight = $('.workspace-viewer-container').height(); - var processResizing = _.bind(this.processResizing, this), - stopResizing = _.bind(this.stopResizing, this); - $('body') - .on('mousemove.workspace', processResizing) - .on('mouseup.workspace', stopResizing); - }, - - processResizing: function (e) { - var currentResizePosition = e.clientY, - resizeDelta = this.initialResizePosition - currentResizePosition, - height = this.initialResizeHeight + resizeDelta; - $('.workspace-viewer-container').height(height); - }, - - stopResizing: function () { - $('body') - .off('mousemove.workspace') - .off('mouseup.workspace'); - }, - - toFullScreen: function () { - this.$('.js-normal-size').removeClass('hidden'); - this.$('.js-full-screen').addClass('hidden'); - this.initialResizeHeight = $('.workspace-viewer-container').height(); - $('.workspace-viewer-container').height('9999px'); - }, - - toNormalSize: function () { - this.$('.js-normal-size').addClass('hidden'); - this.$('.js-full-screen').removeClass('hidden'); - $('.workspace-viewer-container').height(this.initialResizeHeight); - } - }); - +import $ from 'jquery'; +import _ from 'underscore'; +import Marionette from 'backbone.marionette'; +import '../templates'; + +export default Marionette.ItemView.extend({ + template: Templates['workspace-viewer-header'], + + modelEvents: { + 'change': 'render' + }, + + events: { + 'mousedown .js-resize': 'onResizeClick', + + 'click .js-minimize': 'onMinimizeClick', + 'click .js-full-screen': 'onFullScreenClick', + 'click .js-normal-size': 'onNormalSizeClick', + 'click .js-close': 'onCloseClick' + }, + + onRender: function () { + this.$('[data-toggle="tooltip"]').tooltip({ container: 'body' }); + this.$('.js-normal-size').addClass('hidden'); + }, + + onDestroy: function () { + this.$('[data-toggle="tooltip"]').tooltip('destroy'); + $('.tooltip').remove(); + }, + + onResizeClick: function (e) { + e.preventDefault(); + this.startResizing(e); + }, + + onMinimizeClick: function (e) { + e.preventDefault(); + this.trigger('viewerMinimize'); + }, + + onFullScreenClick: function (e) { + e.preventDefault(); + this.toFullScreen(); + }, + + onNormalSizeClick: function (e) { + e.preventDefault(); + this.toNormalSize(); + }, + + onCloseClick: function (e) { + e.preventDefault(); + this.trigger('viewerClose'); + }, + + startResizing: function (e) { + this.initialResizePosition = e.clientY; + this.initialResizeHeight = $('.workspace-viewer-container').height(); + var processResizing = _.bind(this.processResizing, this), + stopResizing = _.bind(this.stopResizing, this); + $('body') + .on('mousemove.workspace', processResizing) + .on('mouseup.workspace', stopResizing); + }, + + processResizing: function (e) { + var currentResizePosition = e.clientY, + resizeDelta = this.initialResizePosition - currentResizePosition, + height = this.initialResizeHeight + resizeDelta; + $('.workspace-viewer-container').height(height); + }, + + stopResizing: function () { + $('body') + .off('mousemove.workspace') + .off('mouseup.workspace'); + }, + + toFullScreen: function () { + this.$('.js-normal-size').removeClass('hidden'); + this.$('.js-full-screen').addClass('hidden'); + this.initialResizeHeight = $('.workspace-viewer-container').height(); + $('.workspace-viewer-container').height('9999px'); + }, + + toNormalSize: function () { + this.$('.js-normal-size').addClass('hidden'); + this.$('.js-full-screen').removeClass('hidden'); + $('.workspace-viewer-container').height(this.initialResizeHeight); + } }); + + diff --git a/server/sonar-web/src/main/js/components/workspace/views/viewer-view.js b/server/sonar-web/src/main/js/components/workspace/views/viewer-view.js index 207deaae575..c335411693e 100644 --- a/server/sonar-web/src/main/js/components/workspace/views/viewer-view.js +++ b/server/sonar-web/src/main/js/components/workspace/views/viewer-view.js @@ -1,37 +1,33 @@ -define([ - './base-viewer-view', - 'components/source-viewer/main', - '../templates' -], function (BaseView, SourceViewer) { +import BaseView from './base-viewer-view'; +import SourceViewer from 'components/source-viewer/main'; +import '../templates'; - return BaseView.extend({ - template: Templates['workspace-viewer'], +export default BaseView.extend({ + template: Templates['workspace-viewer'], - onRender: function () { - BaseView.prototype.onRender.apply(this, arguments); - this.showViewer(); - }, + onRender: function () { + BaseView.prototype.onRender.apply(this, arguments); + this.showViewer(); + }, - showViewer: function () { - if (SourceViewer == null) { - SourceViewer = require('components/source-viewer/main'); - } - var that = this, - viewer = new SourceViewer(), - options = this.model.toJSON(); - viewer.open(this.model.get('uuid'), { workspace: true }); - viewer.on('loaded', function () { - that.model.set({ - name: viewer.model.get('name'), - q: viewer.model.get('q') - }); - if (options.line != null) { - viewer.highlightLine(options.line); - viewer.scrollToLine(options.line); - } + showViewer: function () { + var RealSourceViewer = SourceViewer.on ? SourceViewer : require('components/source-viewer/main'); + var that = this, + viewer = new RealSourceViewer(), + options = this.model.toJSON(); + viewer.open(this.model.get('uuid'), { workspace: true }); + viewer.on('loaded', function () { + that.model.set({ + name: viewer.model.get('name'), + q: viewer.model.get('q') }); - this.viewerRegion.show(viewer); - } - }); - + if (options.line != null) { + viewer.highlightLine(options.line); + viewer.scrollToLine(options.line); + } + }); + this.viewerRegion.show(viewer); + } }); + + |