From ecf1abd2abfc95257cc9bb22f1e4db3c505d6d5d Mon Sep 17 00:00:00 2001 From: Simon Brandhof Date: Sun, 25 Nov 2012 19:40:40 +0100 Subject: [PATCH] SONAR-3825 favourite measure filters --- .../sonar/core/persistence/DatabaseUtils.java | 1 + .../core/persistence/DatabaseVersion.java | 2 +- .../org/sonar/core/persistence/rows-h2.sql | 1 + .../org/sonar/core/persistence/schema-h2.ddl | 11 +- .../app/controllers/favourites_controller.rb | 14 +- .../app/controllers/measures_controller.rb | 34 ++++ .../WEB-INF/app/helpers/measures_helper.rb | 12 ++ .../WEB-INF/app/models/measure_filter.rb | 2 + .../app/models/measure_filter_favourite.rb | 23 +++ .../main/webapp/WEB-INF/app/models/user.rb | 20 ++- .../app/views/measures/manage.html.erb | 154 +++++++++++++----- .../app/views/measures/search.html.erb | 6 +- .../358_create_measure_filter_favourites.rb | 34 ++++ 13 files changed, 252 insertions(+), 62 deletions(-) create mode 100644 sonar-server/src/main/webapp/WEB-INF/app/models/measure_filter_favourite.rb create mode 100644 sonar-server/src/main/webapp/WEB-INF/db/migrate/358_create_measure_filter_favourites.rb diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseUtils.java b/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseUtils.java index c8d1d3f41da..dff45f0fe94 100644 --- a/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseUtils.java +++ b/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseUtils.java @@ -67,6 +67,7 @@ public final class DatabaseUtils { "manual_measures", "measure_data", "measure_filters", + "measure_filter_favourites", "metrics", "notifications", "projects", diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java b/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java index dbf65739635..02c2f840137 100644 --- a/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java +++ b/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java @@ -32,7 +32,7 @@ import java.util.List; */ public class DatabaseVersion implements BatchComponent, ServerComponent { - public static final int LAST_VERSION = 357; + public static final int LAST_VERSION = 358; public static enum Status { UP_TO_DATE, REQUIRES_UPGRADE, REQUIRES_DOWNGRADE, FRESH_INSTALL diff --git a/sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql b/sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql index a932334fdce..a46a8fdb1b9 100644 --- a/sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql +++ b/sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql @@ -185,6 +185,7 @@ INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('354'); INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('355'); INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('356'); INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('357'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('358'); INSERT INTO USERS(ID, LOGIN, NAME, EMAIL, CRYPTED_PASSWORD, SALT, CREATED_AT, UPDATED_AT, REMEMBER_TOKEN, REMEMBER_TOKEN_EXPIRES_AT) VALUES (1, 'admin', 'Administrator', '', 'a373a0e667abb2604c1fd571eb4ad47fe8cc0878', '48bc4b0d93179b5103fd3885ea9119498e9d161b', '2011-09-26 22:27:48.0', '2011-09-26 22:27:48.0', null, null); ALTER TABLE USERS ALTER COLUMN ID RESTART WITH 2; diff --git a/sonar-core/src/main/resources/org/sonar/core/persistence/schema-h2.ddl b/sonar-core/src/main/resources/org/sonar/core/persistence/schema-h2.ddl index 98e7e586b04..576451a88a2 100644 --- a/sonar-core/src/main/resources/org/sonar/core/persistence/schema-h2.ddl +++ b/sonar-core/src/main/resources/org/sonar/core/persistence/schema-h2.ddl @@ -525,6 +525,13 @@ CREATE TABLE "MEASURE_FILTERS" ( "UPDATED_AT" TIMESTAMP ); +CREATE TABLE "MEASURE_FILTER_FAVOURITES" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "USER_ID" INTEGER NOT NULL, + "MEASURE_FILTER_ID" INTEGER NOT NULL, + "CREATED_AT" TIMESTAMP +); + -- ---------------------------------------------- -- DDL Statements for indexes -- ---------------------------------------------- @@ -631,4 +638,6 @@ CREATE INDEX "SEMAPHORE_NAMES" ON "SEMAPHORES" ("NAME"); CREATE UNIQUE INDEX "UNIQ_AUTHOR_LOGINS" ON "AUTHORS" ("LOGIN"); -CREATE INDEX "MEASURE_FILTERS_NAME" ON "MEASURE_FILTERS" ("NAME"); \ No newline at end of file +CREATE INDEX "MEASURE_FILTERS_NAME" ON "MEASURE_FILTERS" ("NAME"); + +CREATE INDEX "MEASURE_FILTER_FAVS_USERID" ON "MEASURE_FILTER_FAVOURITES" ("USER_ID"); \ No newline at end of file diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/favourites_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/favourites_controller.rb index a529ac6d273..1d2283c5e39 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/favourites_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/favourites_controller.rb @@ -25,21 +25,21 @@ class FavouritesController < ApplicationController favourite_id=params[:id] if current_user.favourite?(favourite_id) current_user.delete_favourite(favourite_id) - @style='notfav' - @tooltip='Click to add to favourites' + style='notfav' + tooltip='Click to add to favourites' else current_user.add_favourite(favourite_id) - @style='fav' - @tooltip='Click to remove from favourites' + style='fav' + tooltip='Click to remove from favourites' end star_id=params[:elt] render :update do |page| page.element.removeClassName(star_id, 'notfav') page.element.removeClassName(star_id, 'fav') - page.element.addClassName(star_id, @style) - page.element.writeAttribute(star_id, 'alt', @tooltip) - page.element.writeAttribute(star_id, 'title', @tooltip) + page.element.addClassName(star_id, style) + page.element.writeAttribute(star_id, 'alt', tooltip) + page.element.writeAttribute(star_id, 'title', tooltip) end end diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/measures_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/measures_controller.rb index ab33a006d21..40d74b6f14e 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/measures_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/measures_controller.rb @@ -21,6 +21,7 @@ class MeasuresController < ApplicationController SECTION=Navigation::SECTION_HOME + # GET /measures/index def index @filter = MeasureFilter.new render :action => 'search' @@ -37,6 +38,7 @@ class MeasuresController < ApplicationController end # Load existing filter + # GET /measures/filter/ def filter require_parameters :id @@ -61,17 +63,20 @@ class MeasuresController < ApplicationController verify_post_request access_denied unless logged_in? + add_to_favourites=false if params[:id].present? @filter = find_filter(params[:id]) else @filter = MeasureFilter.new @filter.user_id=current_user.id + add_to_favourites=true end @filter.name=params[:name] @filter.description=params[:description] @filter.shared=(params[:shared]=='true') @filter.data=URI.unescape(params[:data]) if @filter.save + current_user.favourited_measure_filters<<@filter render :text => @filter.id.to_s, :status => 200 else render :partial => 'measures/save_form', :status => 400 @@ -81,14 +86,21 @@ class MeasuresController < ApplicationController # GET /measures/manage def manage access_denied unless logged_in? + @shared_filters = MeasureFilter.find(:all, + :include => :user, + :conditions => ['shared=? and user_id<>?', true, current_user.id]) + @fav_filter_ids = current_user.measure_filter_favourites.map { |fav| fav.measure_filter_id } + Api::Utils.insensitive_sort!(@shared_filters) { |elt| elt.name } end + # GET /measures/edit_form/ def edit_form require_parameters :id @filter = find_filter(params[:id]) render :partial => 'measures/edit_form' end + # POST /measures/edit/?name=&description=&shared= def edit verify_post_request access_denied unless logged_in? @@ -106,6 +118,7 @@ class MeasuresController < ApplicationController end end + # POST /measures/delete/ def delete verify_post_request access_denied unless logged_in? @@ -116,6 +129,26 @@ class MeasuresController < ApplicationController redirect_to :action => 'manage' end + # POST /measures/toggle_fav/ + def toggle_fav + access_denied unless logged_in? + verify_ajax_request + require_parameters :id + + favourites = MeasureFilterFavourite.find(:all, + :conditions => ['user_id=? and measure_filter_id=?', current_user.id, params[:id]]) + if favourites.empty? + filter = find_filter(params[:id]) + current_user.favourited_measure_filters< is_favourite.to_s, :status => 200 + end + private def find_filter(id) filter = MeasureFilter.find(id) @@ -126,4 +159,5 @@ class MeasuresController < ApplicationController def owner?(filter) current_user && filter.user_id==current_user.id end + end diff --git a/sonar-server/src/main/webapp/WEB-INF/app/helpers/measures_helper.rb b/sonar-server/src/main/webapp/WEB-INF/app/helpers/measures_helper.rb index 77f3593f123..8986cbf5d93 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/helpers/measures_helper.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/helpers/measures_helper.rb @@ -61,4 +61,16 @@ module MeasuresHelper html end end + + def measure_filter_star(filter, is_favourite) + if is_favourite + style='fav' + title=message('click_to_remove_from_favourites') + else + style='notfav' + title=message('click_to_add_to_favourites') + end + + "" + end end diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/measure_filter.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/measure_filter.rb index e123375ea17..087b92b61db 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/models/measure_filter.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/models/measure_filter.rb @@ -137,6 +137,8 @@ class MeasureFilter < ActiveRecord::Base attr_reader :base_result, :results belongs_to :user + has_many :measure_filter_favourites, :dependent => :delete_all + validates_presence_of :name, :message => Api::Utils.message('measure_filter.missing_name') validates_length_of :name, :maximum => 100, :message => Api::Utils.message('measure_filter.name_too_long') validates_length_of :description, :allow_nil => true, :maximum => 4000 diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/measure_filter_favourite.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/measure_filter_favourite.rb new file mode 100644 index 00000000000..8bfd80e9be1 --- /dev/null +++ b/sonar-server/src/main/webapp/WEB-INF/app/models/measure_filter_favourite.rb @@ -0,0 +1,23 @@ +# +# Sonar, entreprise quality control tool. +# Copyright (C) 2008-2012 SonarSource +# mailto:contact AT sonarsource DOT com +# +# Sonar is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 3 of the License, or (at your option) any later version. +# +# Sonar is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with Sonar; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 +# +class MeasureFilterFavourite < ActiveRecord::Base + belongs_to :user + belongs_to :measure_filter +end \ No newline at end of file diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/user.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/user.rb index ea4fdeb8030..5be2a51c417 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/models/user.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/models/user.rb @@ -30,7 +30,13 @@ class User < ActiveRecord::Base has_many :filters, :dependent => :destroy has_many :active_dashboards, :dependent => :destroy, :order => 'order_index' has_many :dashboards, :dependent => :destroy - has_many :measure_filters, :class_name => 'MeasureFilter', :dependent => :destroy + has_many :measure_filters, :class_name => 'MeasureFilter', :dependent => :delete_all + + # measure filters that are marked as favourites + has_many :favourited_measure_filters, :class_name => 'MeasureFilter', :through => :measure_filter_favourites, :source => :measure_filter + + # the join table MEASURE_FILTER_FAVOURITES + has_many :measure_filter_favourites, :class_name => 'MeasureFilterFavourite', :dependent => :delete_all include Authentication include Authentication::ByPassword @@ -91,11 +97,13 @@ class User < ActiveRecord::Base # do not validate user, for example when user created via SSO has no password self.save(false) - self.user_roles.each { |role| role.delete } - self.properties.each { |prop| prop.delete } - self.filters.each { |f| f.destroy } - self.dashboards.each { |d| d.destroy } - self.active_dashboards.each { |ad| ad.destroy } + self.user_roles.clear + self.properties.clear + self.filters.clear + self.dashboards.clear + self.active_dashboards.clear + self.measure_filter_favourites.clear + self.measure_filters.clear end # SONAR-3258 diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/measures/manage.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/measures/manage.html.erb index 33f46b05630..695bd565d8b 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/measures/manage.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/measures/manage.html.erb @@ -1,47 +1,113 @@ -
- - - - - - +<% content_for :script do %> + +<% end %> + +

My Measure Filters

+
<%= message('name') -%><%= message('sharing') -%><%= message('operations') -%>
+ + + + + + + + + + <% if current_user.measure_filters.empty? %> + + - - - <% if current_user.measure_filters.empty? %> - - + <% else %> + <% current_user.measure_filters.each do |filter| %> + + + + + - <% else %> - <% current_user.measure_filters.each do |filter| %> - - - - - - <% end %> <% end %> - -
<%= message('name') -%><%= message('sharing') -%><%= message('operations') -%>
<%= message('filters.no_filters') -%>
<%= message('filters.no_filters') -%>
+ <%= measure_filter_star(filter, @fav_filter_ids.include?(filter.id)) -%> + + <%= link_to h(filter.name), :action => 'filter', :id => filter.id -%> + <% if filter.description %> +
<%= h filter.description -%>
+ <% end %> +
+ <% if filter.shared %> + Shared with all users + <% else %> + Private + <% end %> + + <%= message('edit') -%> +   + <%= link_to_action message('delete'), "#{ApplicationController.root_context}/measures/delete/#{filter.id}", + :class => 'link-action link-red', + :id => "delete_#{filter.name.parameterize}", + :confirm_button => message('delete'), + :confirm_title => 'measure_filters.delete_confirm_title', + :confirm_msg => 'measure_filters.are_you_sure_want_delete_filter_x', + :confirm_msg_params => [filter.name] -%> +
- <%= link_to h(filter.name), :action => 'filter', :id => filter.id -%> - <% if filter.description %> -
<%= h filter.description -%>
- <% end %> -
- <% if filter.shared %> - Shared with all users - <% else %> - Private - <% end %> - - <%= message('edit') -%> -   - <%= link_to_action message('delete'), "#{ApplicationController.root_context}/measures/delete/#{filter.id}", - :class => 'link-action link-red', - :id => "delete_#{filter.name.parameterize}", - :confirm_button => message('delete'), - :confirm_title => 'measure_filters.delete_confirm_title', - :confirm_msg => 'measure_filters.are_you_sure_want_delete_filter_x', - :confirm_msg_params => [filter.name] -%> -
-
+ <% end %> + + + +
+ +

Shared Measure Filters

+ + + + + + + + + + <% if @shared_filters.empty? %> + + + + <% else %> + <% @shared_filters.each do |filter| %> + + + + + + + <% end %> + <% end %> + +
<%= message('name') -%><%= message('shared_by') -%>
<%= message('filters.no_filters') -%>
+ <%= measure_filter_star(filter, @fav_filter_ids.include?(filter.id)) -%> + + <%= link_to h(filter.name), :action => 'filter', :id => filter.id -%> + <% if filter.description %> +
<%= h filter.description -%>
+ <% end %> +
+ <%= h filter.user.name -%> +
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/measures/search.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/measures/search.html.erb index 90fc6f7d804..deb3d90ab37 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/measures/search.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/measures/search.html.erb @@ -100,7 +100,7 @@ - Reset + New search @@ -111,12 +111,13 @@ <% if logged_in? %>
    - <% current_user.measure_filters.each do |my_filter| %> + <% current_user.favourited_measure_filters.each do |my_filter| %>
  • <%= h my_filter.name -%>
  • <% end %>
+ Manage <% end %> @@ -147,6 +148,5 @@ <% end %> -

\ No newline at end of file diff --git a/sonar-server/src/main/webapp/WEB-INF/db/migrate/358_create_measure_filter_favourites.rb b/sonar-server/src/main/webapp/WEB-INF/db/migrate/358_create_measure_filter_favourites.rb new file mode 100644 index 00000000000..1d8433c8074 --- /dev/null +++ b/sonar-server/src/main/webapp/WEB-INF/db/migrate/358_create_measure_filter_favourites.rb @@ -0,0 +1,34 @@ +# +# Sonar, entreprise quality control tool. +# Copyright (C) 2008-2012 SonarSource +# mailto:contact AT sonarsource DOT com +# +# Sonar is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 3 of the License, or (at your option) any later version. +# +# Sonar is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with Sonar; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 +# + +# +# Sonar 3.4 +# +class CreateMeasureFilterFavourites < ActiveRecord::Migration + def self.up + create_table 'measure_filter_favourites' do |t| + t.column 'user_id', :integer, :null => false + t.column 'measure_filter_id', :integer, :null => false + t.column 'created_at', :datetime + end + add_index 'measure_filter_favourites', 'user_id', :name => 'measure_filter_favs_userid' + end +end + -- 2.39.5