diff --git a/app/controllers/queries_controller.rb b/app/controllers/queries_controller.rb index 089121708..d60ea899d 100644 --- a/app/controllers/queries_controller.rb +++ b/app/controllers/queries_controller.rb @@ -133,6 +133,7 @@ class QueriesController < ApplicationController @query.column_names = nil if params[:default_columns] @query.sort_criteria = (params[:query] && params[:query][:sort_criteria]) || @query.sort_criteria @query.name = params[:query] && params[:query][:name] + @query.description = params[:query] && params[:query][:description] if User.current.allowed_to?(:manage_public_queries, @query.project) || User.current.admin? @query.visibility = (params[:query] && params[:query][:visibility]) || Query::VISIBILITY_PRIVATE @query.role_ids = params[:query] && params[:query][:role_ids] diff --git a/app/helpers/queries_helper.rb b/app/helpers/queries_helper.rb index 92459ae00..a4fcca186 100644 --- a/app/helpers/queries_helper.rb +++ b/app/helpers/queries_helper.rb @@ -502,7 +502,8 @@ module QueriesHelper content_tag('li', link_to(query.name, url_params.merge(:query_id => query), - :class => css) + + :class => css, + :title => query.description) + clear_link.html_safe) end.join("\n").html_safe, :class => 'queries' diff --git a/app/models/query.rb b/app/models/query.rb index 65aba26bd..2b82b1b7a 100644 --- a/app/models/query.rb +++ b/app/models/query.rb @@ -262,6 +262,7 @@ class Query < ApplicationRecord validates_presence_of :name validates_length_of :name, :maximum => 255 + validates_length_of :description, :maximum => 255 validates :visibility, :inclusion => {:in => [VISIBILITY_PUBLIC, VISIBILITY_ROLES, VISIBILITY_PRIVATE]} validate :validate_query_filters validate do |query| diff --git a/app/views/admin/projects.html.erb b/app/views/admin/projects.html.erb index e6805453a..cbbc8fffd 100644 --- a/app/views/admin/projects.html.erb +++ b/app/views/admin/projects.html.erb @@ -3,6 +3,7 @@

<%= @query.new_record? ? l(:label_project_plural) : @query.name %>

+<%= @query.persisted? && @query.description.present? ? content_tag('p', @query.description) : '' %> <%= form_tag(admin_projects_path(@project, nil), :method => :get, :id => 'query_form') do %> <%= hidden_field_tag 'admin_projects', '1' %> diff --git a/app/views/calendars/show.html.erb b/app/views/calendars/show.html.erb index d3d00a427..10592e916 100644 --- a/app/views/calendars/show.html.erb +++ b/app/views/calendars/show.html.erb @@ -1,4 +1,5 @@

<%= @query.new_record? ? l(:label_calendar) : @query.name %>

+<%= @query.persisted? && @query.description.present? ? content_tag('p', @query.description) : '' %> <%= form_tag({:controller => 'calendars', :action => 'show', :project_id => @project}, :method => :get, :id => 'query_form') do %> diff --git a/app/views/gantts/show.html.erb b/app/views/gantts/show.html.erb index 43e430311..62e5bf705 100644 --- a/app/views/gantts/show.html.erb +++ b/app/views/gantts/show.html.erb @@ -3,6 +3,7 @@

<%= @query.new_record? ? l(:label_gantt) : @query.name %>

+<%= @query.persisted? && @query.description.present? ? content_tag('p', @query.description) : '' %> <%= form_tag({:controller => 'gantts', :action => 'show', :project_id => @project, :month => params[:month], diff --git a/app/views/issues/index.html.erb b/app/views/issues/index.html.erb index 997a64e55..d4eaf8943 100644 --- a/app/views/issues/index.html.erb +++ b/app/views/issues/index.html.erb @@ -19,6 +19,7 @@

<%= @query.new_record? ? l(:label_issue_plural) : @query.name %>

<% html_title(@query.new_record? ? l(:label_issue_plural) : @query.name) %> +<%= @query.persisted? && @query.description.present? ? content_tag('p', @query.description) : '' %> <%= form_tag(_project_issues_path(@project), :method => :get, :id => 'query_form') do %> <%= render :partial => 'queries/query_form' %> diff --git a/app/views/projects/index.html.erb b/app/views/projects/index.html.erb index 3bd665640..436a3b8b7 100644 --- a/app/views/projects/index.html.erb +++ b/app/views/projects/index.html.erb @@ -5,6 +5,7 @@

<%= @query.new_record? ? l(:label_project_plural) : @query.name %>

+<%= @query.persisted? && @query.description.present? ? content_tag('p', @query.description) : '' %> <%= form_tag(projects_path(@project, nil), :method => :get, :id => 'query_form') do %> <%= render :partial => 'queries/query_form' %> diff --git a/app/views/queries/_form.html.erb b/app/views/queries/_form.html.erb index 5f4fa3490..27391e8ef 100644 --- a/app/views/queries/_form.html.erb +++ b/app/views/queries/_form.html.erb @@ -8,6 +8,8 @@

<%= text_field 'query', 'name', :size => 80 %>

+

+<%= text_field 'query', 'description', :size => 80 %>

<% if User.current.admin? || User.current.allowed_to?(:manage_public_queries, @query.project) %> diff --git a/app/views/timelog/index.html.erb b/app/views/timelog/index.html.erb index a045e4743..0b2a72988 100644 --- a/app/views/timelog/index.html.erb +++ b/app/views/timelog/index.html.erb @@ -14,6 +14,7 @@

<%= @query.new_record? ? l(:label_spent_time) : @query.name %>

+<%= @query.persisted? && @query.description.present? ? content_tag('p', @query.description) : '' %> <%= form_tag(_time_entries_path(@project, nil), :method => :get, :id => 'query_form') do %> <%= render :partial => 'date_range' %> diff --git a/app/views/users/index.html.erb b/app/views/users/index.html.erb index d609bfd78..021c11cb6 100644 --- a/app/views/users/index.html.erb +++ b/app/views/users/index.html.erb @@ -8,6 +8,7 @@

<%= @query.new_record? ? l(:label_user_plural) : @query.name %>

+<%= @query.persisted? && @query.description.present? ? content_tag('p', @query.description) : '' %> <%= form_tag(users_path, method: :get, id: 'query_form') do %> <%= render partial: 'queries/query_form' %> diff --git a/db/migrate/20240213101801_add_queries_description.rb b/db/migrate/20240213101801_add_queries_description.rb new file mode 100644 index 000000000..5755731c9 --- /dev/null +++ b/db/migrate/20240213101801_add_queries_description.rb @@ -0,0 +1,9 @@ +class AddQueriesDescription < ActiveRecord::Migration[6.1] + def up + add_column :queries, :description, :string, :after => :name + end + + def down + remove_column :queries, :description + end +end diff --git a/test/fixtures/queries.yml b/test/fixtures/queries.yml index 6b3bb0193..cc0ea220f 100644 --- a/test/fixtures/queries.yml +++ b/test/fixtures/queries.yml @@ -5,6 +5,7 @@ queries_001: project_id: 1 visibility: 2 name: Multiple custom fields query + description: Description for Multiple custom fields query filters: | --- cf_1: @@ -28,6 +29,7 @@ queries_002: project_id: 1 visibility: 0 name: Private query for cookbook + description: Description for Private query for cookbook filters: | --- tracker_id: @@ -47,6 +49,7 @@ queries_003: project_id: visibility: 0 name: Private query for all projects + description: Description for Private query for all projects filters: | --- tracker_id: @@ -62,6 +65,7 @@ queries_004: project_id: visibility: 2 name: Public query for all projects + description: Description for Public query for all projects filters: | --- tracker_id: @@ -77,6 +81,7 @@ queries_005: project_id: visibility: 2 name: Open issues by priority and tracker + description: Description for Oepn issues by priority and tracker filters: | --- status_id: @@ -98,6 +103,7 @@ queries_006: project_id: visibility: 2 name: Open issues grouped by tracker + description: Description for Open issues grouped by tracker filters: | --- status_id: @@ -118,6 +124,7 @@ queries_007: project_id: 2 visibility: 2 name: Public query for project 2 + description: Description for Public query for project 2 filters: | --- tracker_id: @@ -133,6 +140,7 @@ queries_008: project_id: 2 visibility: 0 name: Private query for project 2 + description: Description for Private query for project 2 filters: | --- tracker_id: @@ -148,6 +156,7 @@ queries_009: project_id: visibility: 2 name: Open issues grouped by list custom field + description: Description for Open issues grouped by list custom field filters: | --- status_id: @@ -168,6 +177,7 @@ queries_010: project_id: 1 visibility: 2 name: My spent time + description: Description for My spent time filters: | --- user_id: @@ -187,6 +197,7 @@ queries_011: type: ProjectQuery visibility: 2 name: Projects as list + description: Description for Projects as list filters: | --- id: @@ -205,6 +216,7 @@ queries_012: type: ProjectQuery visibility: 1 name: My bookmarks + description: Description for My bookmarks filters: | --- id: diff --git a/test/functional/calendars_controller_test.rb b/test/functional/calendars_controller_test.rb index b6dcbdf01..32e586e85 100644 --- a/test/functional/calendars_controller_test.rb +++ b/test/functional/calendars_controller_test.rb @@ -155,15 +155,16 @@ class CalendarsControllerTest < Redmine::ControllerTest end def test_show_should_run_custom_queries - @query = IssueQuery.create!(:name => 'Calendar Query', :visibility => IssueQuery::VISIBILITY_PUBLIC) + query = IssueQuery.create!(:name => 'Calendar Query', :description => 'Description for Calendar Query', :visibility => IssueQuery::VISIBILITY_PUBLIC) get( :show, :params => { - :query_id => @query.id + :query_id => query.id } ) assert_response :success - assert_select 'h2', :text => 'Calendar Query' + assert_select 'h2', :text => query.name + assert_select '#sidebar a.query.selected[title=?]', query.description, :text => query.name end def test_cross_project_calendar diff --git a/test/functional/gantts_controller_test.rb b/test/functional/gantts_controller_test.rb index b3a68c483..f3e3656ec 100644 --- a/test/functional/gantts_controller_test.rb +++ b/test/functional/gantts_controller_test.rb @@ -118,6 +118,19 @@ class GanttsControllerTest < Redmine::ControllerTest assert_response :success end + def test_show_should_run_custom_query + query = IssueQuery.create!(:name => 'Gantt Query', :description => 'Description for Gantt Query', :visibility => IssueQuery::VISIBILITY_PUBLIC) + get( + :show, + :params => { + :query_id => query.id + } + ) + assert_response :success + assert_select 'h2', :text => query.name + assert_select '#sidebar a.query.selected[title=?]', query.description, :text => query.name + end + def test_gantt_should_work_cross_project get :show assert_response :success diff --git a/test/functional/issues_controller_test.rb b/test/functional/issues_controller_test.rb index ee477dffa..43eaa08c6 100644 --- a/test/functional/issues_controller_test.rb +++ b/test/functional/issues_controller_test.rb @@ -359,7 +359,8 @@ class IssuesControllerTest < Redmine::ControllerTest assert_select 'a.query.selected', 1 # assert link properties assert_select( - 'a.query.selected[href=?]', + 'a.query.selected[title=?][href=?]', + 'Description for Oepn issues by priority and tracker', '/projects/ecookbook/issues?query_id=5', :text => "Open issues by priority and tracker" ) diff --git a/test/functional/projects_controller_test.rb b/test/functional/projects_controller_test.rb index 0ac0ecc36..d236206a1 100644 --- a/test/functional/projects_controller_test.rb +++ b/test/functional/projects_controller_test.rb @@ -252,6 +252,14 @@ class ProjectsControllerTest < Redmine::ControllerTest assert_select ".total-for-cf-#{field.id} span.value", :text => '9' end + def test_index_with_query + query = ProjectQuery.find(11) + get :index, :params => { :query_id => query.id } + assert_response :success + assert_select 'h2', :text => query.name + assert_select '#sidebar a.query.selected[title=?]', query.description, :text => query.name + end + def test_index_should_retrieve_default_query query = ProjectQuery.find(11) ProjectQuery.stubs(:default).returns query @@ -260,6 +268,7 @@ class ProjectsControllerTest < Redmine::ControllerTest @request.session[:user_id] = user_id get :index assert_select 'h2', text: query.name + assert_select '#sidebar a.query.selected[title=?]', query.description, :text => query.name end end diff --git a/test/functional/queries_controller_test.rb b/test/functional/queries_controller_test.rb index 0d15c4087..137ef9a35 100644 --- a/test/functional/queries_controller_test.rb +++ b/test/functional/queries_controller_test.rb @@ -328,6 +328,25 @@ class QueriesControllerTest < Redmine::ControllerTest assert_equal [['due_date', 'desc'], ['tracker', 'asc']], query.sort_criteria end + def test_create_with_description + @request.session[:user_id] = 2 + assert_difference '::Query.count', 1 do + post( + :create, + :params => { + :project_id => 'ecookbook', + :query => { + :name => 'test_new_with_description', :description => 'Description for test_new_with_description' + } + } + ) + end + q = Query.find_by_name("test_new_with_description") + assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook', :query_id => q + + assert_equal 'Description for test_new_with_description', q.description + end + def test_create_with_failure @request.session[:user_id] = 2 assert_no_difference '::Query.count' do @@ -659,6 +678,14 @@ class QueriesControllerTest < Redmine::ControllerTest end end + def test_edit_description + @request.session[:user_id] = 1 + get(:edit, :params => {:id => 5}) + assert_response :success + + assert_select 'input[name="query[description]"][value=?]', 'Description for Oepn issues by priority and tracker' + end + def test_edit_invalid_query @request.session[:user_id] = 2 get(:edit, :params => {:id => 99}) @@ -744,6 +771,23 @@ class QueriesControllerTest < Redmine::ControllerTest assert Query.find_by_name('test_project_query_updated') end + def test_update_description + @request.session[:user_id] = 1 + q = Query.find(5) + put( + :update, + :params => { + :id => q.id, + :query => { + :name => q.name, + :description => 'query description updated' + } + } + ) + assert_redirected_to :controller => 'issues', :action => 'index', :query_id => q.id + assert_equal 'query description updated', Query.find(5).description + end + def test_update_with_failure @request.session[:user_id] = 1 put( diff --git a/test/functional/timelog_controller_test.rb b/test/functional/timelog_controller_test.rb index 7e50952f5..b00b41b79 100644 --- a/test/functional/timelog_controller_test.rb +++ b/test/functional/timelog_controller_test.rb @@ -1682,14 +1682,14 @@ class TimelogControllerTest < Redmine::ControllerTest end def test_index_with_query - query = TimeEntryQuery.new(:project_id => 1, :name => 'Time Entry Query', :visibility => 2) + query = TimeEntryQuery.new(:project_id => 1, :name => 'Time Entry Query', :description => 'Description for Time Entry Query', :visibility => 2) query.save! @request.session[:user_id] = 2 get :index, :params => {:project_id => 'ecookbook', :query_id => query.id} assert_response :success assert_select 'h2', :text => query.name - assert_select '#sidebar a.selected', :text => query.name + assert_select '#sidebar a.query.selected[title=?]', query.description, :text => query.name end def test_index_atom_feed diff --git a/test/functional/users_controller_test.rb b/test/functional/users_controller_test.rb index e452371ff..b2814ee50 100644 --- a/test/functional/users_controller_test.rb +++ b/test/functional/users_controller_test.rb @@ -189,6 +189,15 @@ class UsersControllerTest < Redmine::ControllerTest assert_select 'tr#user-1', 1 end + def test_index_with_query + query = UserQuery.create!(:name => 'My User Query', :description => 'Description for My User Query', :visibility => UserQuery::VISIBILITY_PUBLIC) + get :index, :params => { :query_id => query.id } + assert_response :success + + assert_select 'h2', :text => query.name + assert_select '#sidebar a.query.selected[title=?]', query.description, :text => query.name + end + def test_index_csv with_settings :default_language => 'en' do user = User.logged.status(1).first