diff --git a/Gemfile b/Gemfile index 02dff5995..44d8c428d 100644 --- a/Gemfile +++ b/Gemfile @@ -51,7 +51,6 @@ gem 'meta-tags', '~> 1.2.5', :require => 'meta_tags' gem "haml-rails", '~> 0.3.4' gem 'jquery-rails', '~> 2.0.2' gem 'ruby-haml-js', '~> 0.0.3' -gem 'rails-backbone', '~> 0.7.2' gem 'rack-throttle' gem 'rest-client', '~> 1.6.6' @@ -60,6 +59,7 @@ gem 'attr_encrypted', '1.2.1' gem "gemoji", "~> 1.2.1", require: 'emoji/railtie' # AngularJS related stuff +gem 'underscore-rails' gem 'angularjs-rails' gem 'ng-rails-csrf' gem 'momentjs-rails' diff --git a/Gemfile.lock b/Gemfile.lock index cac3b44ec..ec77c2116 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -114,7 +114,6 @@ GEM warden (~> 1.2.1) diff-display (0.0.1) diff-lcs (1.1.3) - ejs (1.0.0) encryptor (1.1.3) erubis (2.7.0) escape_utils (0.2.4) @@ -274,10 +273,6 @@ GEM activesupport (= 3.2.13) bundler (~> 1.0) railties (= 3.2.13) - rails-backbone (0.7.2) - coffee-script (~> 2.2.0) - ejs (~> 1.0.0) - railties (>= 3.1.0) rails3-generators (1.0.0) railties (>= 3.0.0) rails3-jquery-autocomplete (1.0.11) @@ -407,6 +402,7 @@ GEM uglifier (1.2.7) execjs (>= 0.3.0) multi_json (~> 1.3) + underscore-rails (1.5.1) unicorn (4.3.1) kgio (~> 2.6) rack @@ -477,7 +473,6 @@ DEPENDENCIES pg (~> 0.14.0) rack-throttle rails (= 3.2.13) - rails-backbone (~> 0.7.2) rails3-generators rails3-jquery-autocomplete (~> 1.0.7) rake @@ -504,6 +499,7 @@ DEPENDENCIES trinidad (~> 1.0.2) turbo-sprockets-rails3 uglifier (~> 1.2.4) + underscore-rails unicorn (~> 4.3.1) whenever (~> 0.7.3) wikicloth diff --git a/app/assets/javascripts/angularjs/controllers/build_list_controller.js.erb b/app/assets/javascripts/angularjs/controllers/build_list_controller.js.erb new file mode 100644 index 000000000..948cce184 --- /dev/null +++ b/app/assets/javascripts/angularjs/controllers/build_list_controller.js.erb @@ -0,0 +1,42 @@ +RosaABF.controller('BuildListController', ['$scope', '$http', function($scope, $http) { + + $scope.advisoriable_types = <%=BuildList::RELEASE_UPDATE_TYPES%>; + + $scope.build_list = {}; + $scope.attach_advisory = 'no'; + // Statuses: advisory_not_found, server_error, continue_input + $scope.search_status = 'continue_input'; + $scope.term = ''; + $scope.advisory = null; + + + $scope.search = function() { + var params = {query: $scope.term, bl_type: $scope.build_list.update_type, format: 'json'}; + $http.get(Routes.search_advisories_path(params)).success(function(results) { + $scope.search_status = 'continue_input'; + $scope.advisory = results; + $('#attach_advisory').find('.advisory_id').val($scope.advisory.advisory_id); + }).error(function(data, status, headers, config) { + $scope.search_status = status == 404 ? 'advisory_not_found' : 'server_error'; + $scope.advisory = null; + $('#attach_advisory').find('.advisory_id').val(''); + });; + + } + + $scope.updateTypeChanged = function() { + if (_.contains($scope.advisoriable_types, $scope.build_list.update_type)) { + if ($scope.advisory || $scope.term.length > 0) { $scope.search(); } + } else { + $scope.attach_advisory = 'no'; + } + } + + $scope.attachAdvisoryChanged = function() { + if (!_.contains($scope.advisoriable_types, $scope.build_list.update_type)) { + $scope.build_list.update_type = $scope.advisoriable_types[0]; + } + $('#build_list_update_type .nonadvisoriable').attr('disabled', ($scope.attach_advisory != 'no')); + } + +}]); \ No newline at end of file diff --git a/app/assets/javascripts/angularjs/controllers/collaborators_controller.js.erb b/app/assets/javascripts/angularjs/controllers/collaborators_controller.js.erb new file mode 100644 index 000000000..bb43b5803 --- /dev/null +++ b/app/assets/javascripts/angularjs/controllers/collaborators_controller.js.erb @@ -0,0 +1,65 @@ +RosaABF.controller('CollaboratorsController', ['$scope', 'ApiCollaborator', function($scope, ApiCollaborator) { + + $scope.def_role = "<%=Relation::ROLES.first%>"; + + $scope.popup = $('#add_collaborator_form .users-search-popup'); + $scope.owner = $('#owner_name').val(); + $scope.project = $('#project_name').val(); + $scope.resource = ApiCollaborator.resource; + $scope.collaborators = []; + + $scope.new_collaborators = []; + + $scope.initNewCollaborator = function(c) { + if (c) { + c.term = c.actor_name; + c.collaborator.role = $scope.def_role; + } else { + c = {collaborator: {role: $scope.def_role}}; + } + $scope.new_collaborator = c; + } + $scope.initNewCollaborator(); + + $scope.getCollaborators = function() { + $scope.collaborators = $scope.resource.query({owner: $scope.owner, project: $scope.project}); + } + $scope.getCollaborators(); + + $scope.update = function(collaborator) { + collaborator.$update(); + } + + $scope.deleteCollaborators = function() { + var collaborators = []; + _.each($scope.collaborators, function(collaborator){ + if(collaborator.removed) { + collaborator.$delete(); + } else { + collaborators.push(collaborator); + } + $scope.collaborators = collaborators; + }); + } + + $scope.search = function() { + if ($scope.new_collaborator.term.length > 2) { + $scope.new_collaborators = $scope.resource.find( + {owner: $scope.owner, project: $scope.project, term: $scope.new_collaborator.term}); + $scope.popup.show(); + } + } + + $scope.select = function(c) { + $scope.initNewCollaborator(c); + $scope.popup.hide(); + } + + $scope.add = function() { + $scope.new_collaborator.$save(function() { + $scope.collaborators.push($scope.new_collaborator); + $scope.initNewCollaborator(); + }); + } + +}]); \ No newline at end of file diff --git a/app/assets/javascripts/angularjs/services/collaborator.js b/app/assets/javascripts/angularjs/services/collaborator.js new file mode 100644 index 000000000..c1d1198cb --- /dev/null +++ b/app/assets/javascripts/angularjs/services/collaborator.js @@ -0,0 +1,26 @@ +RosaABF.factory('ApiCollaborator', ['$resource', function($resource) { + + var CollaboratorResource = $resource( + '/:owner/:project/collaborators/:id?format=json', + { + owner: '@project.owner_uname', + project: '@project.name', + id: '@id' + }, + { + update: { + method: 'PUT', + isArray : false + }, + find: { + url: '/:owner/:project/collaborators/find.json', + method: 'GET', + isArray : true + } + } + ); + + return { + resource : CollaboratorResource + } +}]); \ No newline at end of file diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index c662d0421..da4b48c1a 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -9,10 +9,6 @@ //= require_tree ./lib //= require underscore -//= require backbone -//= require backbone_rails_sync -//= require backbone_datalink -//= require backbone/rosa //= require js-routes // require angular diff --git a/app/assets/javascripts/backbone/additionals.js.erb b/app/assets/javascripts/backbone/additionals.js.erb deleted file mode 100644 index 36cd3700a..000000000 --- a/app/assets/javascripts/backbone/additionals.js.erb +++ /dev/null @@ -1 +0,0 @@ -Rosa.bootstrapedData.ROLES = <%= Relation::ROLES.to_json %>; diff --git a/app/assets/javascripts/backbone/models/.gitkeep b/app/assets/javascripts/backbone/models/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/app/assets/javascripts/backbone/models/advisory.js b/app/assets/javascripts/backbone/models/advisory.js deleted file mode 100644 index 74e15fb21..000000000 --- a/app/assets/javascripts/backbone/models/advisory.js +++ /dev/null @@ -1,96 +0,0 @@ -Rosa.Models.Advisory = Backbone.Model.extend({ - defaults: { - id: null, - description: null, - references: null, - update_type: null, - found: false - }, - - initialize: function() { - _.bindAll(this, 'findByAdvisoryID'); - - this.url = '/advisories'; - }, - - findByAdvisoryID: function(id, bl_type, options) { - var self = this; - - var urlError = function() { - throw new Error("A 'url' property or function must be specified"); - }; - - var typeError = function() { - throw new Error("A 'bl_type' must be 'security' or 'bugfix'"); - }; - - var idError = function() { - throw new Error("A 'id' must be a string at least 4 characters long"); - }; - - if ( (typeof(id) != "string") || (id.length < 4) ) { - idError(); - } - - if ( (bl_type == undefined) || (bl_type == null) || ((bl_type != 'security') && (bl_type != 'bugfix')) ) { - typeError(); - } - - options |= {}; - var data = _.extend({ - query: id, - bl_type: bl_type - }, {}); - - var params = _.extend({ - type: 'GET', - dataType: 'json', - beforeSend: function( xhr ) { - var token = $('meta[name="csrf-token"]').attr('content'); - if (token) xhr.setRequestHeader('X-CSRF-Token', token); - - self.trigger('search:start'); - } - }, options); - - if (!params.url) { - params.url = ((_.isFunction(this.url) ? this.url() : this.url) + '/search') || urlError(); - } - - params.data = data; - - var complete = options.complete; - params.complete = function(jqXHR, textStatus) { - //console.log(jqXHR); - - switch (jqXHR.status) { - case 200: - self.set(_.extend({ - found: true - }, JSON.parse(jqXHR.responseText)), {silent: true}); - self.trigger('search:end'); - break - - case 404: - self.set(self.defaults, {silent: true}); - self.trigger('search:end'); - break - - default: - self.set(self.defaults, {silent: true}); - self.trigger('search:failed'); - } - - if (complete) complete(jqXHR, textStatus); - } - - $.ajax(params); - - return this; - - } -}); - -Rosa.Collections.AdvisoriesCollection = Backbone.Collection.extend({ - model: Rosa.Models.Advisory -}); diff --git a/app/assets/javascripts/backbone/models/collaborator.js b/app/assets/javascripts/backbone/models/collaborator.js deleted file mode 100644 index e203bbf36..000000000 --- a/app/assets/javascripts/backbone/models/collaborator.js +++ /dev/null @@ -1,97 +0,0 @@ -Rosa.Models.Collaborator = Backbone.Model.extend({ - paramRoot: 'collaborator', - - defaults: { - id: null, - actor_id: null, - actor_name: null, - actor_type: null, - avatar: null, - actor_path: null, - project_id: null, - role: null, - removed: false - }, - - changeRole: function(r) { - var self = this; - this._prevState = this.get('role'); - this.save({role: r}, - {wait: true, - success: function(model, response) { - self.trigger('sync_success'); - }, - error: function(model, response) { - model.set({role: model._prevState}); - self.trigger('sync_failed'); - } - }); - return this; - }, - setRole: function(r) { - this.set({ role: r }); - return this; - }, - toggleRemoved: function() { - if (this.get('removed') === false) { - this.set({removed: true}); - } else { - this.set({removed: false}); - } - return this; - } -}); - -Rosa.Collections.CollaboratorsCollection = Backbone.Collection.extend({ - model: Rosa.Models.Collaborator, - - initialize: function(coll, opts) { - if (opts === undefined || opts['url'] === undefined) { - this.url = window.location.pathname; - } else { - this.url = opts['url']; - } - this.on('change:removed change:id add', this.sort, this); - }, - comparator: function(m) { - var res = '' - if (m.get('removed') === true) { - res = 0; - } else if (m.isNew()) { - res = 1; - } else { res = 2 } - return res + m.get('actor_name'); - }, - - removeMarked: function() { - var marked = this.where({removed: true}); - marked.forEach(function(el) { - el.destroy({wait: true, silent: true}); - }); - }, - - saveAndAdd: function(model) { - - model.urlRoot = this.url; - var self = this; - model.save({}, { - wait: true, - success: function(m) { - self.add(m.toJSON()); - } - }); - }, - - filterByName: function(term, options) { - if (term == "") return this; - console.log(term); - - var pattern = new RegExp(term, "i"); - - return _(this.filter(function(data) { - console.log(data.get("actor_name")); - console.log(pattern.test(data.get("actor_name"))); - return pattern.test(data.get("actor_name")); - })); - } -}); diff --git a/app/assets/javascripts/backbone/rosa.js b/app/assets/javascripts/backbone/rosa.js deleted file mode 100644 index 9ed5f3096..000000000 --- a/app/assets/javascripts/backbone/rosa.js +++ /dev/null @@ -1,15 +0,0 @@ -//= require_self -//= require ./additionals -//= require_tree ./templates -//= require_tree ./models -//= require_tree ./views -//= require_tree ./routers - -window.Rosa = { - Models: {}, - Collections: {}, - Routers: {}, - Views: {}, - - bootstrapedData: {} -} diff --git a/app/assets/javascripts/backbone/routers/.gitkeep b/app/assets/javascripts/backbone/routers/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/app/assets/javascripts/backbone/routers/build_lists_advisories_router.js b/app/assets/javascripts/backbone/routers/build_lists_advisories_router.js deleted file mode 100644 index 950db332d..000000000 --- a/app/assets/javascripts/backbone/routers/build_lists_advisories_router.js +++ /dev/null @@ -1,9 +0,0 @@ -Rosa.Routers.BuildListsAdvisoriesRouter = Backbone.Router.extend({ - routes: {}, - - initialize: function() { - this.advisoriesView = new Rosa.Views.BuildListAdvisoriesView({ model: new Rosa.Models.Advisory() }); - - this.advisoriesView.render(); - } -}); diff --git a/app/assets/javascripts/backbone/routers/collaborators_router.js b/app/assets/javascripts/backbone/routers/collaborators_router.js deleted file mode 100644 index b3f12ed69..000000000 --- a/app/assets/javascripts/backbone/routers/collaborators_router.js +++ /dev/null @@ -1,15 +0,0 @@ -Rosa.Routers.CollaboratorsRouter = Backbone.Router.extend({ - routes: {}, - - initialize: function() { - this.collaboratorsCollection = new Rosa.Collections.CollaboratorsCollection(Rosa.bootstrapedData.collaborators, { url: window.location.pathname }); - this.searchCollection = new Rosa.Collections.CollaboratorsCollection(null, { url: window.location.pathname + '/find' }); - this.tableView = new Rosa.Views.CollaboratorsView({ collection: this.collaboratorsCollection }); - this.addView = new Rosa.Views.AddCollaboratorView({ collection: this.searchCollection }); - - this.addView.on('collaborator_prepared', this.collaboratorsCollection.saveAndAdd, this.collaboratorsCollection); - - this.tableView.render(); - this.addView.render(); - } -}); diff --git a/app/assets/javascripts/backbone/templates/.gitkeep b/app/assets/javascripts/backbone/templates/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/app/assets/javascripts/backbone/templates/collaborators/collaborator.jst.hamljs b/app/assets/javascripts/backbone/templates/collaborators/collaborator.jst.hamljs deleted file mode 100644 index b1ad6b5c2..000000000 --- a/app/assets/javascripts/backbone/templates/collaborators/collaborator.jst.hamljs +++ /dev/null @@ -1,39 +0,0 @@ -%td - %span#niceCheckbox1.nicecheck-main{ style: "background-position: 0px 0px; " } - - if (removed === true) { - %input{ type: 'checkbox', checked: 'checked' } - - } else { - %input{ type: 'checkbox' } - - } - -%td - .img - %img{ src: avatar, alt: 'avatar' } - .forimg - %a{ href: actor_path } - = actor_name - -- var ROLES = Rosa.bootstrapedData.ROLES; - -- for (var i = 0; i < ROLES.length; i++) { -%td - .radio - - var radio_id = id + '_' + ROLES[i]; - - var radio_type = 'role[' + id + ']'; - - if (ROLES[i] === role) { - - if ( removed ) { - %input.niceRadio{type: 'radio', value: ROLES[i], id: radio_id, name: radio_type, disabled: 'disabled', checked: 'checked'} - - } else { - %input.niceRadio{type: 'radio', value: ROLES[i], id: radio_id, name: radio_type, checked: 'checked'} - - }; - - } else { - - if ( removed ) { - %input.niceRadio{type: 'radio', value: ROLES[i], id: radio_id, name: radio_type, disabled: 'disabled' } - - } else { - %input.niceRadio{type: 'radio', value: ROLES[i], id: radio_id, name: radio_type } - - }; - - } - .forradio - %label{ for: radio_id } - = ROLES[i] -- } diff --git a/app/assets/javascripts/backbone/templates/collaborators/searched_collaborator.jst.hamljs b/app/assets/javascripts/backbone/templates/collaborators/searched_collaborator.jst.hamljs deleted file mode 100644 index 7b8a3e86f..000000000 --- a/app/assets/javascripts/backbone/templates/collaborators/searched_collaborator.jst.hamljs +++ /dev/null @@ -1,7 +0,0 @@ -%a - .collaborator - .img - %img{width: '16px', src: avatar, alt: 'avatar'} - .name - = actor_name - .both diff --git a/app/assets/javascripts/backbone/templates/shared/autocomplete_result_empty.jst.hamljs b/app/assets/javascripts/backbone/templates/shared/autocomplete_result_empty.jst.hamljs deleted file mode 100644 index 8ed5f5d10..000000000 --- a/app/assets/javascripts/backbone/templates/shared/autocomplete_result_empty.jst.hamljs +++ /dev/null @@ -1,3 +0,0 @@ -%li.empty_result - %span - Nothing found diff --git a/app/assets/javascripts/backbone/views/.gitkeep b/app/assets/javascripts/backbone/views/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/app/assets/javascripts/backbone/views/add_collaborator_view.js b/app/assets/javascripts/backbone/views/add_collaborator_view.js deleted file mode 100644 index bdddba49f..000000000 --- a/app/assets/javascripts/backbone/views/add_collaborator_view.js +++ /dev/null @@ -1,92 +0,0 @@ -Rosa.Views.AddCollaboratorView = Backbone.View.extend({ - result_empty: JST['backbone/templates/shared/autocomplete_result_empty'], - - events: { - 'click #add_collaborator_button': 'addCollaborator' - }, - - initialize: function() { - _.bindAll(this, 'getData', 'renderAll', 'onFocus', 'selectItem', 'addCollaborator'); - - this.$el = $('#add_collaborator_form'); - this.$_search_input = this.$('#collaborator_name'); - this.$_image = this.$('.admin-search.withimage img'); - this.$_role = this.$('#role'); - - this.ac = this.$_search_input.autocomplete({ - minLength: 1, - source: this.getData, - focus: this.onFocus, - select: this.selectItem - }); - this.ac.data("autocomplete")._renderItem = this.addOne; - this.ac.data("autocomplete")._renderMenu = this.renderAll; - }, - - render: function() { - return this; - }, - - getData: function(request, response) { - var self = this; - var res = this.collection.fetch({ - data: {term: request.term}, - wait: true, - success: function(collection) { - self.$_image.hide(); - if (collection.length !== 0) { - response(collection.models); - } else { - response([{result_empty: true}]); - } - } - }); - }, - - addOne: function(ul, item) { - var v = new Rosa.Views.SearchedCollaboratorView({ model: item }); - return v.render().$el.appendTo(ul); - }, - - renderAll: function( ul, items ) { - var self = this; - if (items[0]['result_empty'] !== undefined && items[0]['result_empty'] === true) { - ul.removeClass('has_results').append(this.result_empty()); - } else { - ul.addClass('has_results'); - _.each( items, function( item ) { - self.addOne( ul, item ); - }); - var factor = (items.length > 10) ? 10 : items.length; - ul.height(ul.children('li').first() * factor); - } - }, - - onFocus: function( event, ui ) { - this.$_search_input.val(ui.item.get('actor_name')); - return false; - }, - - selectItem: function( event, ui ) { - var model = ui.item; - this.$_image.attr('src', model.get('avatar')).show(); - - this.__selected_item = model; - return false; - }, - - addCollaborator: function(e) { - e.preventDefault(); - var model = this.__selected_item; - - if ( model !== undefined ) { - model.setRole(this.$_role.val()); - this.trigger('collaborator_prepared', model); - this.__selected_item = undefined; - this.$_image.hide(); - this.$_search_input.val(''); - } - return false; - } - -}); diff --git a/app/assets/javascripts/backbone/views/build_list_advisories_view.js b/app/assets/javascripts/backbone/views/build_list_advisories_view.js deleted file mode 100644 index 0b950150f..000000000 --- a/app/assets/javascripts/backbone/views/build_list_advisories_view.js +++ /dev/null @@ -1,215 +0,0 @@ -Rosa.Views.BuildListAdvisoriesView = Backbone.View.extend({ - initialize: function() { - _.bindAll(this, 'showAdvisory', 'showPreview', 'showForm', - 'showSearch', 'hideAll', 'displayStatus', 'processSearch', - 'showInTypeSelect', 'typeSelectChange'); - - this.$el = $('#advisory_block'); - this._$type_select = $('#build_list_update_type'); - this._$publish_button = $('input[type="submit"][name="publish"]'); - - this._$form = this.$('#new_advisory_form'); - this._$preview = this.$('#advisory_preview'); - - this._$search = this.$('#advisory_search_block'); - this._$search_field = this.$('#advisory_search'); - this._$not_found = this.$('#advisory_search_block > .advisory_not_found'); - this._$server_error = this.$('#advisory_search_block > .server_error'); - this._$continue_input = this.$('#advisory_search_block > .continue_input'); - this._search_timer = null; - - this._$selector = this.$('#attach_advisory'); - - this._state_vars = {}; - this._state_vars = _.extend({ - checked_update_type: this._$type_select.val(), - header_text: this._$preview.children('h3').html() - }, this.state_vars); - - this._$selector.on('change', this.showAdvisory); - this._$search_field.on('input keyup', this.processSearch); - - this._$type_select.on('change', this.typeSelectChange); - - this.model.on('search:start', function() { - this._$publish_button.prop({disabled: true}); - }, this); - this.model.on('search:end', this.showPreview, this); - this.model.on('search:failed', this.handleSearchError, this); - }, - - showAdvisory: function(ev) { - this._$publish_button.prop({disabled: false}); - switch (this._$selector.val()) { - case 'no': - this.hideAll(); - this.showInTypeSelect('all'); - break - case 'new': - this.showForm(); - this.showInTypeSelect('advisoriable'); - break - default: - this.showSearch(); - this.showInTypeSelect('advisoriable'); - this._$publish_button.prop({disabled: true}); - } - }, - - typeSelectChange: function(ev) { - switch (this._$selector.val()) { - case 'no': - this._state_vars.checked_update_type = this._$selector.val(); - break - case 'new': - break - default: - this._$search_field.trigger('input'); - } - }, - - showInTypeSelect: function(type) { - var children = this._$type_select.children('option'); - if (type != 'all') { - var visible_ch = children.filter('.' + type); - var sel = children.filter(':selected'); - - children.prop('disabled', true); - visible_ch.prop('disabled', false); - if (sel.prop('disabled')) { - sel.prop('selected', false); - visible_ch.first().prop('selected', true); - } - } else { - children.prop('disabled', false).prop('selected', false); - children.filter('option[value="' + this._state_vars.checked_update_type + '"]').prop('selected', true); - } - }, - - processSearch: function(ev) { - if (ev.type == "keyup") { - if (ev.keyCode != 13) { - return - } else { - ev.preventDefault(); - } - } - - var TIMER_INTERVAL = 500; - - var self = this; - - var timerCallback = function() { - if (self._$search_field.val().length > 3) { - // real search - self.model.findByAdvisoryID(self._$search_field.val(), self._$type_select.val()); - } else { - // hide preview if nothing to show - if (self._$preview.is(':visible')) { - self._$preview.slideUp(); - } - self.displayStatus('found'); - } - }; - - if (this.model.get('advisory_id') == this._$search_field.val()) { - this.showPreview(); - return; - } - // timeout before real AJAX request - clearTimeout(this._search_timer); - this._search_timer = setTimeout(timerCallback, TIMER_INTERVAL); - }, - - showPreview: function(id) { - this._$publish_button.prop({disabled: false}); - if (this._$form.is(':visible')) { - this._$form.slideUp(); - } - var prev = this._$preview; - var adv = this.model; - if (adv.get('found')) { - this._$selector.children('option.advisory_id').val(adv.get('advisory_id')); - - prev.children('h3').html(this._state_vars.header_text + ' ' + adv.get('advisory_id')); - prev.children('.descr').html(adv.get('description')); - prev.children('.refs').html(adv.get('references')); - if (!this._$preview.is(':visible')) { - this._$preview.slideDown(); - } - this.displayStatus('found'); - } else { - if (this._$preview.is(':visible')) { - this._$preview.slideUp(); - } - this._$publish_button.prop({disabled: true}); - this.displayStatus('not_found'); - this._$selector.children('option.advisory_id').val(''); - } - }, - - showForm: function() { - if (this._$preview.is(':visible')) { - this._$preview.slideUp(); - } - if (this._$search.is(':visible')) { - this._$search.slideUp(); - } - if (!this._$form.is(':visible')) { - this._$form.slideDown(); - } - }, - - showSearch: function() { - if (this._$form.is(':visible')) { - this._$form.slideUp(); - } - if (!this._$search.is(':visible')) { - this._$search.slideDown(); - this._$search_field.trigger('input'); - } - }, - - handleSearchError: function() { - this._$publish_button.prop({disabled: true}); - this.displayStatus('error'); - if (this._$preview.is(':visible')) { - this._$preview.slideUp(); - } - if (this._$form.is(':visible')) { - this._$form.slideUp(); - } - }, - - hideAll: function() { - if (this._$preview.is(':visible')) { - this._$preview.slideUp(); - } - if (this._$search.is(':visible')) { - this._$search.slideUp(); - } - if (this._$form.is(':visible')) { - this._$form.slideUp(); - } - }, - - displayStatus: function(st) { - var ELEMS = { - 'found': this._$continue_input, - 'not_found': this._$not_found, - 'error': this._$server_error - }; - - this._$continue_input.hide(); - this._$not_found.hide(); - this._$server_error.hide(); - - ELEMS[st].show(); - }, - - render: function() { - this.showAdvisory(); - return this; - } - -}); diff --git a/app/assets/javascripts/backbone/views/collaborator_view.js b/app/assets/javascripts/backbone/views/collaborator_view.js deleted file mode 100644 index c785baa0e..000000000 --- a/app/assets/javascripts/backbone/views/collaborator_view.js +++ /dev/null @@ -1,69 +0,0 @@ -Rosa.Views.CollaboratorView = Backbone.View.extend({ - template: JST['backbone/templates/collaborators/collaborator'], - tagName: 'tr', - className: 'regular', - - events: { - 'change input[type="radio"]': 'changeRole', - 'change input[type="checkbox"]': 'toggleRemoved' - }, - - initialize: function() { - this.$el.attr('id', 'admin-table-members-row' + this.options.model.get('id') + this.options.model.get('actor_type')); - this.model.on('change', this.render, this); - this.model.on('destroy', this.hide, this); - this.model.on('sync_failed', this.syncError, this); - this.model.on('sync_success', this.syncSuccess, this); - }, - - render: function() { - if (this.model.get('removed')) { - this.$el.addClass('removed'); - } else { - this.$el.removeClass('removed'); - }; - this.$el.html(this.template(this.model.toJSON())); - return this; - }, - - changeRole: function(e) { - this.$('input[type="radio"]').attr('disabled', 'disabled'); - this.model.changeRole(e.target.value); - }, - - toggleRemoved: function(e) { - this.model.toggleRemoved(); - }, - - hide: function() { - this.remove(); - }, - - syncError: function() { - var self = this; - this.$el.addClass('sync_error'); - this.$('td').animate({ - 'background-color': '#FFFFFF' - }, { - duration: 800, - easing: 'easeInCirc', - complete: function() { - self.$el.removeClass('sync_error'); - } - }); - }, - - syncSuccess: function() { - var self = this; - this.$el.addClass('sync_success'); - this.$('td').animate({ - 'background-color': '#FFFFFF' - }, { - duration: 800, - easing: 'easeInCirc', - complete: function() { - self.$el.removeClass('sync_success'); - } - }); - } -}); diff --git a/app/assets/javascripts/backbone/views/collaborators_view.js b/app/assets/javascripts/backbone/views/collaborators_view.js deleted file mode 100644 index cf6aafe84..000000000 --- a/app/assets/javascripts/backbone/views/collaborators_view.js +++ /dev/null @@ -1,57 +0,0 @@ -Rosa.Views.CollaboratorsView = Backbone.View.extend({ - initialize: function() { - _.bindAll(this, 'deleterClick', 'processFilter', 'addOne'); - this.setupDeleter(); - this.setupFilter(); - this.$el = $('#collaborators > tbody'); - this.collection.on('reset', this.render, this); - this.collection.on('add', this.clearFilter, this); - }, - - addOne: function(collaborator) { - var cView = new Rosa.Views.CollaboratorView({ model: collaborator }); - this.$el.append(cView.render().$el); - }, - - render: function() { - this.clearFilter(); - this.$el.empty(); - this.collection.forEach(this.addOne, this); - this._$deleter.show(); - return this; - }, - - renderList: function(list) { - this.$el.empty(); - - list.each(this.addOne); - return this; - }, - - setupDeleter: function() { - this._$deleter = $('#collaborators_deleter'); - this._$deleter.on('click.deleter', this.deleterClick); - this._$deleter.attr('title', 'Remove selected rows'); - }, - - deleterClick: function() { - this.collection.removeMarked(); - }, - - setupFilter: function() { - this._$filter = $('#collaborators thead input[type="text"]'); - this._$filter.on('keyup', this.processFilter); - this.clearFilter(); - }, - - clearFilter: function() { - this._$filter.val(''); - }, - - processFilter: function() { - var term = this._$filter.val(); - var list = this.collection.filterByName(term, {excludeRemoved: true}); - console.log(list); - this.renderList(list); - } -}); diff --git a/app/assets/javascripts/backbone/views/project_modify_view.js b/app/assets/javascripts/backbone/views/project_modify_view.js deleted file mode 100644 index 2c11de294..000000000 --- a/app/assets/javascripts/backbone/views/project_modify_view.js +++ /dev/null @@ -1,30 +0,0 @@ -Rosa.Views.ProjectModifyView = Backbone.View.extend({ - initialize: function() { - _.bindAll(this, 'checkboxClick'); - - this.$checkbox_wrapper = $('#niceCheckbox1'); - this._$checkbox = this.$checkbox_wrapper.children('#project_is_package').first(); - this.$maintainer_form = $('#maintainer_form'); - this.$publish_form = $('#publish_form'); - this._$publish_checkbox = this.$publish_form.find('#project_publish_i686_into_x86_64').first(); - - this.$checkbox_wrapper.on('click', this.checkboxClick); - }, - - checkboxClick: function() { - if (this._$checkbox.is(':checked')) { - this.$maintainer_form.slideDown(); - this.$publish_form.slideDown(); - } else { - this.$maintainer_form.slideUp(); - this.$publish_form.slideUp(); - if (this._$publish_checkbox.is(':checked')) { - changeCheck(this.$publish_form.find('.niceCheck-main')); - } - } - }, - - render: function() { - this.checkboxClick(); - } -}); diff --git a/app/assets/javascripts/backbone/views/searched_collaborator_view.js b/app/assets/javascripts/backbone/views/searched_collaborator_view.js deleted file mode 100644 index 05911be42..000000000 --- a/app/assets/javascripts/backbone/views/searched_collaborator_view.js +++ /dev/null @@ -1,12 +0,0 @@ -Rosa.Views.SearchedCollaboratorView = Backbone.View.extend({ - template: JST['backbone/templates/collaborators/searched_collaborator'], - tagName: 'li', - className: 'item', - - render: function() { - this.$el.empty(); - this.$el.data( "item.autocomplete", this.model ) - .append(this.template(this.model.toJSON())); - return this; - } -}) diff --git a/app/assets/javascripts/extra/tracker.js b/app/assets/javascripts/extra/tracker.js index 7acee8c69..66346cb27 100644 --- a/app/assets/javascripts/extra/tracker.js +++ b/app/assets/javascripts/extra/tracker.js @@ -129,8 +129,8 @@ $(document).ready(function() { return false; }); - $('#assigned-popup .header .icon-remove-circle').live('click', function() { - $('#assigned-popup').hide(); + $('.users-search-popup .header .icon-remove-circle').live('click', function() { + $('.users-search-popup').hide(); }); $('#assigned-container .icon-share').live('click', function() { diff --git a/app/assets/stylesheets/design/custom.scss b/app/assets/stylesheets/design/custom.scss index 273fc2f77..b0b613893 100644 --- a/app/assets/stylesheets/design/custom.scss +++ b/app/assets/stylesheets/design/custom.scss @@ -894,12 +894,11 @@ ul.ui-autocomplete.has_results { float: left; padding-top: 6px; } -#add_collaborator_form div.img { - width: 25px; - height: 25px; -} - -#add_collaborator_form div.img img { +#collaborators { + .img, img { + width: 25px; + height: 25px; + } } #add_collaborator_form .admin-role .lineForm { @@ -1011,12 +1010,12 @@ form.mass_build input[type="checkbox"] { height: 11px; } -div#new_advisory_form, +/*div#new_advisory_form, div#advisory_preview, div#advisory_search_block, div#advisory_search_block div.info { display: none; -} +}*/ div#advisory_search_block { padding-bottom: 15px; @@ -1964,7 +1963,7 @@ article .activity .top { } } -#assigned-popup { +.users-search-popup { z-index: 1001; position: absolute; margin: 5px 0 0 130px; @@ -1998,7 +1997,7 @@ article .activity .top { .edit_assignee { display: none; } - #manage_issue_users_list { + .list { overflow-y: auto; overflow-x: hidden; max-height: 280px; diff --git a/app/controllers/advisories_controller.rb b/app/controllers/advisories_controller.rb index b10afb889..208aa1723 100644 --- a/app/controllers/advisories_controller.rb +++ b/app/controllers/advisories_controller.rb @@ -21,9 +21,13 @@ class AdvisoriesController < ApplicationController def search @advisory = Advisory.by_update_type(params[:bl_type]).search_by_id(params[:query]).first - raise ActiveRecord::RecordNotFound.new('Not Found') if @advisory.nil? - respond_to do |format| - format.json { render @advisory } + if @advisory.nil? + render :nothing => true, :status => 404 + else + # respond_to do |format| + # format.json { render @advisory } + # end + render @advisory end end end diff --git a/app/controllers/projects/collaborators_controller.rb b/app/controllers/projects/collaborators_controller.rb index f0432b4fd..4e0faa81f 100644 --- a/app/controllers/projects/collaborators_controller.rb +++ b/app/controllers/projects/collaborators_controller.rb @@ -14,12 +14,6 @@ class Projects::CollaboratorsController < Projects::BaseController respond_with @collaborators end - def show - end - - def new - end - def find users = User.not_member_of(@project) groups = Group.not_member_of(@project) @@ -33,9 +27,6 @@ class Projects::CollaboratorsController < Projects::BaseController end end - def edit - end - def create @collaborator = Collaborator.new(params[:collaborator]) @collaborator.project = @project diff --git a/app/views/projects/build_lists/show.html.haml b/app/views/projects/build_lists/show.html.haml index 0850cf043..f8e8c6f8b 100644 --- a/app/views/projects/build_lists/show.html.haml +++ b/app/views/projects/build_lists/show.html.haml @@ -4,216 +4,213 @@ %p= @build_list.human_status %p= @build_list.updated_at .both -=form_for @build_list, :url => publish_build_list_path(@build_list), :html => { :class => :form } do |f| - %h3= t("layout.build_lists.main_data") - .leftlist= t("activerecord.attributes.build_list.container_path") - .rightlist - - if @build_list.container_published? - -url = container_url - = link_to url, url - - elsif @build_list.container_publish? - = t("layout.build_lists.creating") - .both - - .leftlist= t("activerecord.attributes.build_list.id") - .rightlist= @build_list.id - .both - .leftlist= t("activerecord.attributes.build_list.user") - .rightlist - = link_to @build_list.user.try(:fullname), @build_list.user - .both - .leftlist= t("activerecord.attributes.build_list.publisher") - .rightlist - = link_to @build_list.publisher.try(:fullname), @build_list.publisher if @build_list.publisher - .both - .leftlist= t("activerecord.attributes.build_list.build_for_platform") - .rightlist - - bfp = @build_list.build_for_platform - - if bfp.present? - = link_to(bfp.name, bfp) - - else - = t("layout.build_lists.platform_deleted") - .both - .leftlist= t("activerecord.attributes.build_list.save_to_repository") - .rightlist - = link_to "#{@build_list.save_to_platform.name}/#{@build_list.save_to_repository.name}", [@build_list.save_to_platform, @build_list.save_to_repository] - .both - .leftlist= t("activerecord.attributes.build_list.include_repos") - .rightlist= (@build_list.include_repos||[]).map{|r| Repository.find(r).name}.join(', ') - .both - .leftlist= t("activerecord.attributes.build_list.update_type") - .rightlist - - if can?(:publish, @build_list) - = f.select :update_type, options_for_select(build_list_classified_update_types, @build_list.update_type) - - else - = @build_list.update_type - .both - .leftlist= t("activerecord.attributes.build_list.auto_publish") - .rightlist= t("layout.#{@build_list.auto_publish}_") - .both - .leftlist= t("activerecord.attributes.build_list.auto_create_container") - .rightlist= t("layout.#{@build_list.auto_create_container?}_") - .both - .leftlist= t("activerecord.attributes.build_list.project_version") - .rightlist= link_to @build_list.project_version, tree_path(@build_list.project, @build_list.project_version) - .both - .leftlist= t("diff") - .rightlist= build_list_version_link(@build_list, true) - .both - .leftlist= t("activerecord.attributes.build_list.arch") - .rightlist= @build_list.arch.name - .both - .leftlist= t("activerecord.attributes.build_list.updated_at") - .rightlist= @build_list.updated_at - .both - .leftlist= t("activerecord.attributes.build_list.is_circle") - .rightlist= t("layout.#{@build_list.is_circle?}_") - .both - .leftlist= t("activerecord.attributes.build_list.new_core") - .rightlist= t("layout.#{@build_list.new_core?}_") - .both - - - if @build_list.extra_build_lists.present? || @build_list.extra_repositories.present? - .leftlist= t("activerecord.attributes.build_list.extra_repos") +%div{'ng-controller' => 'BuildListController'} + =form_for @build_list, :url => publish_build_list_path(@build_list), :html => { :class => :form } do |f| + %h3= t("layout.build_lists.main_data") + .leftlist= t("activerecord.attributes.build_list.container_path") .rightlist - - Repository.where(:id => @build_list.extra_repositories).each do |repo| - %p= link_to "#{repo.platform.name}/#{repo.name}", [repo.platform, repo] - - BuildList.where(:id => @build_list.extra_build_lists).each do |bl| - %p= link_to "#{bl.id} (#{bl.project.name} - #{bl.arch.name})", bl + - if @build_list.container_published? + -url = container_url + = link_to url, url + - elsif @build_list.container_publish? + = t("layout.build_lists.creating") .both - - if @build_list.mass_build_id.present? - .leftlist= t("activerecord.attributes.mass_build_id") - .rightlist= link_to @build_list.mass_build.name, platform_mass_builds_path(@build_list.save_to_platform) + .leftlist= t("activerecord.attributes.build_list.id") + .rightlist= @build_list.id .both - - - - if @build_list.advisory.present? - .leftlist= t("layout.build_lists.attached_advisory") - .rightlist= link_to @build_list.advisory.advisory_id, advisory_path(@build_list.advisory) - .both - - if !@build_list.in_work? && @build_list.started_at - %br - .leftlist - .rightlist= @build_list.human_duration - .both - - if @build_list.in_work? - %br - .leftlist + .leftlist= t("activerecord.attributes.build_list.user") .rightlist - = "#{@build_list.human_current_duration} / #{@build_list.human_average_build_time}" + = link_to @build_list.user.try(:fullname), @build_list.user + .both + .leftlist= t("activerecord.attributes.build_list.publisher") + .rightlist + = link_to @build_list.publisher.try(:fullname), @build_list.publisher if @build_list.publisher + .both + .leftlist= t("activerecord.attributes.build_list.build_for_platform") + .rightlist + - bfp = @build_list.build_for_platform + - if bfp.present? + = link_to(bfp.name, bfp) + - else + = t("layout.build_lists.platform_deleted") + .both + .leftlist= t("activerecord.attributes.build_list.save_to_repository") + .rightlist + = link_to "#{@build_list.save_to_platform.name}/#{@build_list.save_to_repository.name}", [@build_list.save_to_platform, @build_list.save_to_repository] + .both + .leftlist= t("activerecord.attributes.build_list.include_repos") + .rightlist= (@build_list.include_repos||[]).map{|r| Repository.find(r).name}.join(', ') + .both + .leftlist= t("activerecord.attributes.build_list.update_type") + .rightlist{'ng-init' => "build_list.update_type = '#{@build_list.update_type}'"} + - if can?(:publish, @build_list) + = f.select :update_type, options_for_select(build_list_classified_update_types, @build_list.update_type), {}, 'ng-model' => 'build_list.update_type', 'ng-change' => 'updateTypeChanged()' + - else + = @build_list.update_type + .both + .leftlist= t("activerecord.attributes.build_list.auto_publish") + .rightlist= t("layout.#{@build_list.auto_publish}_") + .both + .leftlist= t("activerecord.attributes.build_list.auto_create_container") + .rightlist= t("layout.#{@build_list.auto_create_container?}_") + .both + .leftlist= t("activerecord.attributes.build_list.project_version") + .rightlist= link_to @build_list.project_version, tree_path(@build_list.project, @build_list.project_version) + .both + .leftlist= t("diff") + .rightlist= build_list_version_link(@build_list, true) + .both + .leftlist= t("activerecord.attributes.build_list.arch") + .rightlist= @build_list.arch.name + .both + .leftlist= t("activerecord.attributes.build_list.updated_at") + .rightlist= @build_list.updated_at + .both + .leftlist= t("activerecord.attributes.build_list.is_circle") + .rightlist= t("layout.#{@build_list.is_circle?}_") + .both + .leftlist= t("activerecord.attributes.build_list.new_core") + .rightlist= t("layout.#{@build_list.new_core?}_") .both - - if @build_list.can_cancel? && can?(:cancel, @build_list) - = link_to t("layout.build_lists.cancel"), cancel_build_list_path(@build_list), - :method => :put, :confirm => t("layout.confirm"), :class => 'button' - - - if @build_list.save_to_platform.released && @build_list.advisory.nil? && can?(:publish, @build_list) - #advisory_block - .leftlist= label_tag :attach_advisory, t("layout.build_lists.attached_advisory") + - if @build_list.extra_build_lists.present? || @build_list.extra_repositories.present? + .leftlist= t("activerecord.attributes.build_list.extra_repos") .rightlist - = select_tag :attach_advisory, advisories_select_options(@advisories) - %p.hint_text= t("layout.advisories.publication_info", :update_types => BuildList::RELEASE_UPDATE_TYPES.join(', ')) + - Repository.where(:id => @build_list.extra_repositories).each do |repo| + %p= link_to "#{repo.platform.name}/#{repo.name}", [repo.platform, repo] + - BuildList.where(:id => @build_list.extra_build_lists).each do |bl| + %p= link_to "#{bl.id} (#{bl.project.name} - #{bl.arch.name})", bl .both - #advisory_search_block - %h3= t("layout.advisories.search_by_id") - .leftlist= label_tag :advisory_search, t("layout.advisories.search_hint") + - if @build_list.mass_build_id.present? + .leftlist= t("activerecord.attributes.mass_build_id") + .rightlist= link_to @build_list.mass_build.name, platform_mass_builds_path(@build_list.save_to_platform) + .both + + + - if @build_list.advisory.present? + .leftlist= t("layout.build_lists.attached_advisory") + .rightlist= link_to @build_list.advisory.advisory_id, advisory_path(@build_list.advisory) + .both + - if !@build_list.in_work? && @build_list.started_at + %br + .leftlist + .rightlist= @build_list.human_duration + .both + - if @build_list.in_work? + %br + .leftlist + .rightlist + = "#{@build_list.human_current_duration} / #{@build_list.human_average_build_time}" + .both + + - if @build_list.can_cancel? && can?(:cancel, @build_list) + = link_to t("layout.build_lists.cancel"), cancel_build_list_path(@build_list), + :method => :put, :confirm => t("layout.confirm"), :class => 'button' + + - if @build_list.save_to_platform.released && @build_list.advisory.nil? && can?(:publish, @build_list) + #advisory_block + .leftlist= label_tag :attach_advisory, t("layout.build_lists.attached_advisory") .rightlist - %input#advisory_search{:type => 'text'} - %p.hint_text= t("layout.advisories.advisory_id_info", :advisory_format => advisory_id_for_hint) - .both - - %w(advisory_not_found server_error continue_input).each do |el| - .info{:class => el} - %p= t("layout.advisories.banners.#{el}") - - #new_advisory_form - = f.fields_for @build_list.build_advisory do |f| - = render :partial => 'advisories/form', :locals => {:f => f} - - #advisory_preview - %h3= t("activerecord.models.advisory") << ' ' - - .leftlist= t("activerecord.attributes.advisory.description") - .rightlist.descr   + = select_tag :attach_advisory, advisories_select_options(@advisories), 'ng-model' => 'attach_advisory', 'ng-change' => 'attachAdvisoryChanged()' + %p.hint_text= t("layout.advisories.publication_info", :update_types => BuildList::RELEASE_UPDATE_TYPES.join(', ')) .both - .leftlist= t("activerecord.attributes.advisory.references") - .rightlist.refs   - .both - :javascript - $(function() { - var r = new Rosa.Routers.BuildListsAdvisoriesRouter(); - }); + #advisory_search_block{'ng-show' => 'attach_advisory != "no" && attach_advisory != "new"'} + %h3= t("layout.advisories.search_by_id") + .leftlist= label_tag :advisory_search, t("layout.advisories.search_hint") + .rightlist + %input#advisory_search{:type => 'text', 'ng-model' => 'term', 'ng-keyup' => 'search()'} + %p.hint_text= t("layout.advisories.advisory_id_info", :advisory_format => advisory_id_for_hint) + .both + - I18n.t('layout.advisories.banners').keys.each do |key| + .info{:class => key, 'ng-show' => "search_status == '#{key}'"} + %p= t("layout.advisories.banners.#{key}") - - if @build_list.build_started? - = render 'shared/log', { :build_started => true, :get_log_path => log_build_list_path(@build_list) } + #new_advisory_form{'ng-show' => 'attach_advisory == "new"'} + = f.fields_for @build_list.build_advisory do |f| + = render :partial => 'advisories/form', :locals => {:f => f} - - unless @build_list.extra_build_lists_published? - .flash_notify - .alert.alert-error= t('layout.build_lists.publish_with_extra_fail') - .both + #advisory_preview{'ng-show' => 'attach_advisory != "no" && attach_advisory != "new"'} + %h3= t('activerecord.models.advisory') << ' {{advisory.advisory_id}}' - - if can?(:publish, @build_list) - - if @build_list.build_published? - = submit_tag t("layout.publish_again"), :confirm => t("layout.publish_again_warning"), :name => 'publish' - - elsif can_publish_in_future?(@build_list) && @build_list.extra_build_lists_published? - - confirm = @build_list.tests_failed? ? t('layout.build_lists.tests_failed') : t('layout.confirm') - = submit_tag t("layout.publish"), :confirm => confirm, :name => 'publish' - - if @build_list.can_reject_publish? && can?(:reject_publish, @build_list) - = link_to t('layout.reject_publish'), reject_publish_build_list_path(@build_list), - :method => :put, :confirm => t("layout.confirm"), :class => 'button reject_publish' - - if @build_list.can_create_container? && can?(:create_container, @build_list) - = link_to t("layout.build_lists.create_container"), create_container_build_list_path(@build_list), - :method => :put, :confirm => t("layout.confirm"), :class => 'button create_container' - - if can? :create, @build_list - = link_to t('layout.build_lists.recreate_build_list'), new_project_build_list_path(@build_list.project, :build_list_id => @build_list.id), :class => 'button' + .leftlist= t('activerecord.attributes.advisory.description') + .rightlist.descr {{advisory.description}} + .both -.hr -%h3= t("layout.build_lists.items_header") -- if @item_groups.blank? - %h4.nomargin= t("layout.build_lists.no_items_data") -- @item_groups.each_with_index do |group, level| - - group.each do |item| - %h4.nomargin= "#{item.name} ##{level}" + .leftlist= t('activerecord.attributes.advisory.references') + .rightlist.refs {{advisory.references}} + .both + + - if @build_list.build_started? + = render 'shared/log', { :build_started => true, :get_log_path => log_build_list_path(@build_list) } + + - unless @build_list.extra_build_lists_published? + .flash_notify + .alert.alert-error= t('layout.build_lists.publish_with_extra_fail') + .both + + - if can?(:publish, @build_list) + - if @build_list.build_published? + = submit_tag t("layout.publish_again"), :confirm => t("layout.publish_again_warning"), :name => 'publish' + - elsif can_publish_in_future?(@build_list) && @build_list.extra_build_lists_published? + - confirm = @build_list.tests_failed? ? t('layout.build_lists.tests_failed') : t('layout.confirm') + = submit_tag t("layout.publish"), :confirm => confirm, :name => 'publish' + - if @build_list.can_reject_publish? && can?(:reject_publish, @build_list) + = link_to t('layout.reject_publish'), reject_publish_build_list_path(@build_list), + :method => :put, :confirm => t("layout.confirm"), :class => 'button reject_publish' + - if @build_list.can_create_container? && can?(:create_container, @build_list) + = link_to t("layout.build_lists.create_container"), create_container_build_list_path(@build_list), + :method => :put, :confirm => t("layout.confirm"), :class => 'button create_container' + - if can? :create, @build_list + = link_to t('layout.build_lists.recreate_build_list'), new_project_build_list_path(@build_list.project, :build_list_id => @build_list.id), :class => 'button' + + .hr + %h3= t("layout.build_lists.items_header") + - if @item_groups.blank? + %h4.nomargin= t("layout.build_lists.no_items_data") + - @item_groups.each_with_index do |group, level| + - group.each do |item| + %h4.nomargin= "#{item.name} ##{level}" + %table.tablesorter.width565{:cellpadding => "0", :cellspacing => "0"} + %thead + %tr + %th= t("activerecord.attributes.build_list/item.name") + %th= t("activerecord.attributes.build_list/item.version") + %th= t("activerecord.attributes.build_list/item.status") + %tbody + %tr{:class => build_list_item_status_color(item.status)} + %td= item.name + %td= build_list_item_version_link item + %td= item.human_status + .both + + - if @build_list.packages.present? + .hr + %h3= t("layout.build_lists.packages_header") %table.tablesorter.width565{:cellpadding => "0", :cellspacing => "0"} %thead %tr - %th= t("activerecord.attributes.build_list/item.name") - %th= t("activerecord.attributes.build_list/item.version") - %th= t("activerecord.attributes.build_list/item.status") + %th= t("activerecord.attributes.build_list/package.fullname") + %th= t("activerecord.attributes.build_list/package.name") + %th= t("activerecord.attributes.build_list/package.version") + %th= t("activerecord.attributes.build_list/package.release") %tbody - %tr{:class => build_list_item_status_color(item.status)} - %td= item.name - %td= build_list_item_version_link item - %td= item.human_status -.both + - @build_list.packages.each do |package| + %tr + - if package.sha1.present? + %td= link_to package.fullname, "#{APP_CONFIG['file_store_url']}/api/v1/file_stores/#{package.sha1}" + - else + %td= package.fullname + %td= package.name + %td= package.version + %td= package.release + .both -- if @build_list.packages.present? - .hr - %h3= t("layout.build_lists.packages_header") - %table.tablesorter.width565{:cellpadding => "0", :cellspacing => "0"} - %thead - %tr - %th= t("activerecord.attributes.build_list/package.fullname") - %th= t("activerecord.attributes.build_list/package.name") - %th= t("activerecord.attributes.build_list/package.version") - %th= t("activerecord.attributes.build_list/package.release") - %tbody - - @build_list.packages.each do |package| - %tr - - if package.sha1.present? - %td= link_to package.fullname, "#{APP_CONFIG['file_store_url']}/api/v1/file_stores/#{package.sha1}" - - else - %td= package.fullname - %td= package.name - %td= package.version - %td= package.release - .both - -- if @build_list.new_core? - .hr - = render 'platforms/product_build_lists/results', :subject => @build_list + - if @build_list.new_core? + .hr + = render 'platforms/product_build_lists/results', :subject => @build_list :javascript $('article .all').addClass('bigpadding'); diff --git a/app/views/projects/collaborators/_collaborator.json.jbuilder b/app/views/projects/collaborators/_collaborator.json.jbuilder index f1d105a32..55790d266 100644 --- a/app/views/projects/collaborators/_collaborator.json.jbuilder +++ b/app/views/projects/collaborators/_collaborator.json.jbuilder @@ -1,10 +1,9 @@ -json.id collaborator.id - -json.actor_id collaborator.actor_id -json.actor_name collaborator.actor_name -json.actor_type collaborator.actor_type +json.(collaborator, :id, :actor_name) +json.collaborator do # attr_accessible for AngularJS + json.(collaborator, :role, :actor_id, :actor_type, :project_id) +end +json.project do + json.(collaborator.project, :name, :owner_uname) +end json.avatar avatar_url(collaborator.actor) -json.actor_path participant_path(collaborator.actor) - -json.project_id collaborator.project_id -json.role collaborator.role +json.actor_path participant_path(collaborator.actor) \ No newline at end of file diff --git a/app/views/projects/collaborators/_collaborators.json.jbuilder b/app/views/projects/collaborators/_collaborators.json.jbuilder index 9e8d099a2..f7fba1505 100644 --- a/app/views/projects/collaborators/_collaborators.json.jbuilder +++ b/app/views/projects/collaborators/_collaborators.json.jbuilder @@ -1,12 +1,3 @@ -json.array!(collaborators) do |json, cb| - json.id cb.id - - json.actor_id cb.actor_id - json.actor_name cb.actor_name - json.actor_type cb.actor_type - json.avatar avatar_url(cb.actor) - json.actor_path participant_path(cb.actor) - - json.project_id cb.project_id - json.role cb.role +json.array!(collaborators) do |collaborator| + json.partial! 'projects/collaborators/collaborator', :collaborator => collaborator end diff --git a/app/views/projects/collaborators/index.html.haml b/app/views/projects/collaborators/index.html.haml index 7b9a468ae..6e633abab 100644 --- a/app/views/projects/collaborators/index.html.haml +++ b/app/views/projects/collaborators/index.html.haml @@ -5,40 +5,70 @@ %a{:name => 'users'} %h3= t("layout.users.list_header") -#add_collaborator_form - .admin-search.withimage - .img - %img{ :alt => 'avatar', :src => '', :style => 'display: none;' } - = text_field_tag :collaborator_name, nil +#collaborators{'ng-controller' => 'CollaboratorsController'} + = hidden_field_tag :owner_name, @project.try(:owner).try(:uname) + = hidden_field_tag :project_name, @project.try(:name) + + #add_collaborator_form + .admin-search.withimage + .img + %img{:alt => 'avatar', 'ng-src' => '{{new_collaborator.avatar}}', 'ng-show' => 'new_collaborator.avatar'} + = text_field_tag :collaborator_name, nil, 'ng-model' => 'new_collaborator.term', 'ng-keyup' => 'search()' + + .admin-role + .lineForm + = select_tag 'role', options_for_collaborators_roles_select, 'ng-model' => 'new_collaborator.collaborator.role' + .admin-add + %a.button{:rel => 'nofollow', :href => '', 'ng-click' => 'add()'} + = t('layout.add') .both - .admin-role - .lineForm - = select_tag 'role', options_for_collaborators_roles_select - .admin-add - %a{:id => 'add_collaborator_button', :class => 'button', :rel => 'nofollow', :href => 'javascript:void(0)'} - = t('layout.add') - .both -%table#collaborators.tablesorter{:cellpadding => "0", :cellspacing => "0"} - %thead - %tr - %th.centered - %span#collaborators_deleter.hidden - %span.delete    - %th - = t("layout.collaborators.members") - %th{:colspan => "3"} - = t("layout.collaborators.roles") - %tr.search - %th{:colspan => "5"} - %input{ :type => "text", :placeholder => "#{ t('layout.filter_by_name') }"} - %tbody -%br + .users-search-popup + .header + .title= t('layout.issues.search_user') + %span.icon-remove-circle + .list + .people{'ng-repeat' => 'c in new_collaborators', 'ng-click' => 'select(c)'} + .avatar + %img{width: '16px', 'ng-src' => '{{c.avatar}}', alt: 'avatar'} + .name {{c.actor_name}} + .both + + .nothing{'ng-hide' => 'new_collaborators.length > 0'}= t('layout.issues.nothing_to_show') + .both + .both -.both + %table.tablesorter{:cellpadding => "0", :cellspacing => "0"} + %thead + %tr + %th.centered + %span.delete{'ng-click' => 'deleteCollaborators()'}    + %th + = t("layout.collaborators.members") + %th{:colspan => "3"} + = t("layout.collaborators.roles") + %tr.search + %th{:colspan => "5"} + %input{:type => "text", :placeholder => "#{t('layout.filter_by_name')}", 'ng-model' => 'query.actor_name'} -:javascript - $(function() { - Rosa.bootstrapedData.collaborators = #{ render 'collaborators.json.jbuilder', :collaborators => @collaborators }; - r = new Rosa.Routers.CollaboratorsRouter(); - }); + %tbody + %tr{'ng-repeat' => 'c in collaborators | filter:query'} + %td + %input{:type => 'checkbox', 'ng-model' => 'c.removed' } + %td + .img + %img{'ng-src' => '{{c.avatar}}', alt: 'avatar' } + .forimg + %a{'ng-href' => '{{c.actor_path}}'} {{c.actor_name}} + + - Relation::ROLES.each do |role| + %td + .radio + %input{:type => 'radio', 'ng-model' => 'c.collaborator.role', :value => role, 'ng-click' => 'update(c)'} + .forradio + %label= t("layout.collaborators.role_names.#{role}") + + + %br + + .both \ No newline at end of file diff --git a/app/views/projects/issues/_assigned_popup.html.haml b/app/views/projects/issues/_assigned_popup.html.haml index 8f31e036e..51d06bf7a 100644 --- a/app/views/projects/issues/_assigned_popup.html.haml +++ b/app/views/projects/issues/_assigned_popup.html.haml @@ -1,4 +1,4 @@ -#assigned-popup +#assigned-popup.users-search-popup .header .title= t('layout.issues.assign_someone') %span.icon-remove-circle @@ -10,5 +10,5 @@ - unless [:new, :create].include?(action_name.to_sym) = form_for :issue, :url => [@project, @issue], :method => :put, :html => { :class => 'edit_assignee issue'} do |f| = hidden_field_tag "user-default_assignee", nil, :name => 'issue[assignee_id]' - #manage_issue_users_list + .list = render 'projects/issues/search_collaborators' \ No newline at end of file diff --git a/app/views/projects/projects/_form.html.haml b/app/views/projects/projects/_form.html.haml index 18585238c..b1cb51535 100644 --- a/app/views/projects/projects/_form.html.haml +++ b/app/views/projects/projects/_form.html.haml @@ -1,79 +1,82 @@ - act = controller.action_name.to_sym -- if [:new, :create].include? act - .leftlist= f.label :name - .rightlist= f.text_field :name, :class => 'text_field', :disabled => f.object.try(:persisted?) +%div{'ng-controller' => 'ProjectFromController'} + - if [:new, :create].include? act + .leftlist= f.label :name + .rightlist= f.text_field :name, :class => 'text_field', :disabled => f.object.try(:persisted?) + .both + .leftlist= f.label :description + .rightlist= f.text_area :description, :class => 'text_field', :cols => 80 .both -.leftlist= f.label :description -.rightlist= f.text_area :description, :class => 'text_field', :cols => 80 -.both -- if [:new, :create].include? act - .leftlist= f.label :owner - .rightlist - = label_tag t("activerecord.attributes.project.who_owns.me") - - if Group.can_own_project(current_user).count > 0 - = radio_button_tag :who_owns, 'me', @who_owns == :me #{}.merge( (@who_owns == :me) ? {:checked => 'checked'} : {} ) - = label_tag t("activerecord.attributes.project.who_owns.group") - = radio_button_tag :who_owns, 'group', @who_owns == :group #{}.merge( (@who_owns == :group) ? {:checked => 'checked'} : {} ) - -# TODO: Make our own select_box helper with new design, blackjack and bitches! - = select_tag :owner_id, options_from_collection_for_select( Group.can_own_project(current_user), :id, :name ) - - else - = hidden_field_tag :who_owns, :me - .both - -.leftlist= f.label :visibility -.rightlist - =# f.select :visibility, Project::VISIBILITIES - - Project::VISIBILITIES.each do |visibility| - = f.radio_button :visibility, visibility, :class => 'niceRadio' - - if visibility == 'open' - = image_tag("unlock.png") - - else - = image_tag("lock.png") - = t("activerecord.attributes.project.visibilities.#{visibility}") -.both -.leftlist - \  -.rightlist - .check - %span#niceCheckbox1.niceCheck-main= f.check_box :is_package - .forcheck= f.label :is_package - .both - - unless [:new, :create].include? act - #publish_form{:class => @project.publish_i686_into_x86_64 ? '' : 'hidden'} - .check - %span.niceCheck-main= f.check_box :publish_i686_into_x86_64 - .forcheck= f.label :publish_i686_into_x86_64 - .both - -.both -- if [:edit, :update].include? act - .leftlist= f.label :default_branch - .rightlist - = f.select :default_branch, - options_from_collection_for_select( @project.repo.branches, - :name, :name, @project.default_branch), - :class => 'sel80', :id => 'branch_selector' - .both - #maintainer_form{:class => @project.is_package ? '' : 'hidden'} - = f.hidden_field :maintainer_id, :value => @project.maintainer_id - .leftlist - = f.label :maintainer + - if [:new, :create].include? act + .leftlist= f.label :owner .rightlist - -# TODO: Maybe use something like Chosen with filter and prepopulated - -# list of potential maintainers? - = autocomplete_field_tag :maintainer_name, @project.maintainer.fullname, - autocomplete_maintainers_path(@project.owner, @project), - :id_element => '#project_maintainer_id', - :placeholder => @project.maintainer.fullname -- if [:new, :create].include? act - .leftlist= f.label :srpm - .rightlist= f.file_field :srpm, :class => 'file_field' + = label_tag t("activerecord.attributes.project.who_owns.me") + - if Group.can_own_project(current_user).count > 0 + = radio_button_tag :who_owns, 'me', @who_owns == :me #{}.merge( (@who_owns == :me) ? {:checked => 'checked'} : {} ) + = label_tag t("activerecord.attributes.project.who_owns.group") + = radio_button_tag :who_owns, 'group', @who_owns == :group #{}.merge( (@who_owns == :group) ? {:checked => 'checked'} : {} ) + -# TODO: Make our own select_box helper with new design, blackjack and bitches! + = select_tag :owner_id, options_from_collection_for_select( Group.can_own_project(current_user), :id, :name ) + - else + = hidden_field_tag :who_owns, :me + .both + + .leftlist= f.label :visibility + .rightlist + =# f.select :visibility, Project::VISIBILITIES + - Project::VISIBILITIES.each do |visibility| + = f.radio_button :visibility, visibility, :class => 'niceRadio' + - if visibility == 'open' + = image_tag("unlock.png") + - else + = image_tag("lock.png") + = t("activerecord.attributes.project.visibilities.#{visibility}") .both -.leftlist - \  -.rightlist= submit_tag t('layout.save'), :class => 'button', :data => {'disable-with' => t('layout.saving')} -.both + .leftlist + \  + .rightlist + .check= f.check_box :is_package, 'ng-model' => 'project.is_package', 'ng-change' => 'project.publish_i686_into_x86_64 = false' + .forcheck= f.label :is_package + .both + - unless [:new, :create].include? act + #publish_form{'ng-show' => 'project.is_package'} + .check= f.check_box :publish_i686_into_x86_64, 'ng-model' => 'project.publish_i686_into_x86_64' + .forcheck= f.label :publish_i686_into_x86_64 + .both + + .both + - if [:edit, :update].include? act + .leftlist= f.label :default_branch + .rightlist + = f.select :default_branch, + options_from_collection_for_select( @project.repo.branches, + :name, :name, @project.default_branch), + :class => 'sel80', :id => 'branch_selector' + .both + #maintainer_form{'ng-show' => 'project.is_package'} + = f.hidden_field :maintainer_id, :value => @project.maintainer_id + .leftlist + = f.label :maintainer + .rightlist + -# TODO: Maybe use something like Chosen with filter and prepopulated + -# list of potential maintainers? + = autocomplete_field_tag :maintainer_name, @project.maintainer.fullname, + autocomplete_maintainers_path(@project.owner, @project), + :id_element => '#project_maintainer_id', + :placeholder => @project.maintainer.fullname + - if [:new, :create].include? act + .leftlist= f.label :srpm + .rightlist= f.file_field :srpm, :class => 'file_field' + .both + .leftlist + \  + .rightlist= submit_tag t('layout.save'), :class => 'button', :data => {'disable-with' => t('layout.saving')} + .both + :javascript - $(function() { - ( new Rosa.Views.ProjectModifyView ).render(); - }); + RosaABF.controller('ProjectFromController', ['$scope', function($scope) { + $scope.project = { + is_package: #{@project.is_package}, + publish_i686_into_x86_64: #{@project.publish_i686_into_x86_64} + } + }]); \ No newline at end of file