Commit 5ceb0673 authored by jplang's avatar jplang
Browse files

Makes spent time queries savable (#14790).

git-svn-id: https://svn.redmine.org/redmine/trunk@15639 e93f8b46-1217-0410-a6f0-8f06a7374b81
parent 9b23beaa
...@@ -60,7 +60,7 @@ class QueriesController < ApplicationController ...@@ -60,7 +60,7 @@ class QueriesController < ApplicationController
if @query.save if @query.save
flash[:notice] = l(:notice_successful_create) flash[:notice] = l(:notice_successful_create)
redirect_to_issues(:query_id => @query) redirect_to_items(:query_id => @query)
else else
render :action => 'new', :layout => !request.xhr? render :action => 'new', :layout => !request.xhr?
end end
...@@ -74,7 +74,7 @@ class QueriesController < ApplicationController ...@@ -74,7 +74,7 @@ class QueriesController < ApplicationController
if @query.save if @query.save
flash[:notice] = l(:notice_successful_update) flash[:notice] = l(:notice_successful_update)
redirect_to_issues(:query_id => @query) redirect_to_items(:query_id => @query)
else else
render :action => 'edit' render :action => 'edit'
end end
...@@ -82,7 +82,7 @@ class QueriesController < ApplicationController ...@@ -82,7 +82,7 @@ class QueriesController < ApplicationController
def destroy def destroy
@query.destroy @query.destroy
redirect_to_issues(:set_filter => 1) redirect_to_items(:set_filter => 1)
end end
private private
...@@ -117,7 +117,12 @@ class QueriesController < ApplicationController ...@@ -117,7 +117,12 @@ class QueriesController < ApplicationController
@query @query
end end
def redirect_to_issues(options) def redirect_to_items(options)
method = "redirect_to_#{@query.class.name.underscore}"
send method, options
end
def redirect_to_issue_query(options)
if params[:gantt] if params[:gantt]
if @project if @project
redirect_to project_gantt_path(@project, options) redirect_to project_gantt_path(@project, options)
...@@ -129,6 +134,10 @@ class QueriesController < ApplicationController ...@@ -129,6 +134,10 @@ class QueriesController < ApplicationController
end end
end end
def redirect_to_time_entry_query(options)
redirect_to _time_entries_path(@project, nil, options)
end
# Returns the Query subclass, IssueQuery by default # Returns the Query subclass, IssueQuery by default
# for compatibility with previous behaviour # for compatibility with previous behaviour
def query_class def query_class
......
...@@ -40,8 +40,7 @@ class TimelogController < ApplicationController ...@@ -40,8 +40,7 @@ class TimelogController < ApplicationController
include QueriesHelper include QueriesHelper
def index def index
@query = TimeEntryQuery.build_from_params(params, :project => @project, :name => '_') retrieve_time_entry_query
sort_init(@query.sort_criteria.empty? ? [['spent_on', 'desc']] : @query.sort_criteria) sort_init(@query.sort_criteria.empty? ? [['spent_on', 'desc']] : @query.sort_criteria)
sort_update(@query.sortable_columns) sort_update(@query.sortable_columns)
scope = time_entry_scope(:order => sort_clause). scope = time_entry_scope(:order => sort_clause).
...@@ -75,7 +74,7 @@ class TimelogController < ApplicationController ...@@ -75,7 +74,7 @@ class TimelogController < ApplicationController
end end
def report def report
@query = TimeEntryQuery.build_from_params(params, :project => @project, :name => '_') retrieve_time_entry_query
scope = time_entry_scope scope = time_entry_scope
@report = Redmine::Helpers::TimeReport.new(@project, @issue, params[:criteria], params[:columns], scope) @report = Redmine::Helpers::TimeReport.new(@project, @issue, params[:criteria], params[:columns], scope)
...@@ -271,4 +270,8 @@ private ...@@ -271,4 +270,8 @@ private
end end
scope scope
end end
def retrieve_time_entry_query
retrieve_query(TimeEntryQuery, false)
end
end end
...@@ -204,26 +204,27 @@ module QueriesHelper ...@@ -204,26 +204,27 @@ module QueriesHelper
end end
# Retrieve query from session or build a new query # Retrieve query from session or build a new query
def retrieve_query def retrieve_query(klass=IssueQuery, use_session=true)
if !params[:query_id].blank? session_key = klass.name.underscore.to_sym
if params[:query_id].present?
cond = "project_id IS NULL" cond = "project_id IS NULL"
cond << " OR project_id = #{@project.id}" if @project cond << " OR project_id = #{@project.id}" if @project
@query = IssueQuery.where(cond).find(params[:query_id]) @query = klass.where(cond).find(params[:query_id])
raise ::Unauthorized unless @query.visible? raise ::Unauthorized unless @query.visible?
@query.project = @project @query.project = @project
session[:query] = {:id => @query.id, :project_id => @query.project_id} session[session_key] = {:id => @query.id, :project_id => @query.project_id} if use_session
sort_clear sort_clear
elsif api_request? || params[:set_filter] || session[:query].nil? || session[:query][:project_id] != (@project ? @project.id : nil) elsif api_request? || params[:set_filter] || !use_session || session[session_key].nil? || session[session_key][:project_id] != (@project ? @project.id : nil)
# Give it a name, required to be valid # Give it a name, required to be valid
@query = IssueQuery.new(:name => "_") @query = klass.new(:name => "_", :project => @project)
@query.project = @project
@query.build_from_params(params) @query.build_from_params(params)
session[:query] = {:project_id => @query.project_id, :filters => @query.filters, :group_by => @query.group_by, :column_names => @query.column_names, :totalable_names => @query.totalable_names} session[session_key] = {:project_id => @query.project_id, :filters => @query.filters, :group_by => @query.group_by, :column_names => @query.column_names, :totalable_names => @query.totalable_names} if use_session
else else
# retrieve from session # retrieve from session
@query = nil @query = nil
@query = IssueQuery.find_by_id(session[:query][:id]) if session[:query][:id] @query = klass.find_by_id(session[session_key][:id]) if session[session_key][:id]
@query ||= IssueQuery.new(:name => "_", :filters => session[:query][:filters], :group_by => session[:query][:group_by], :column_names => session[:query][:column_names], :totalable_names => session[:query][:totalable_names]) @query ||= klass.new(:name => "_", :filters => session[session_key][:filters], :group_by => session[session_key][:group_by], :column_names => session[session_key][:column_names], :totalable_names => session[session_key][:totalable_names])
@query.project = @project @query.project = @project
end end
end end
......
<h2><%= l(:label_query_new) %></h2> <h2><%= l(:label_query_new) %></h2>
<%= form_tag(@project ? project_queries_path(@project) : queries_path, :id => "query-form") do %> <%= form_tag(@project ? project_queries_path(@project) : queries_path, :id => "query-form") do %>
<%= hidden_field_tag 'type', @query.class.name %>
<%= render :partial => 'form', :locals => {:query => @query} %> <%= render :partial => 'form', :locals => {:query => @query} %>
<%= submit_tag l(:button_save) %> <%= submit_tag l(:button_save) %>
<% end %> <% end %>
<div id="query_form_with_buttons" class="hide-when-print"> <div id="query_form_with_buttons" class="hide-when-print">
<%= hidden_field_tag 'set_filter', '1' %>
<div id="query_form_content"> <div id="query_form_content">
<fieldset id="filters" class="collapsible <%= @query.new_record? ? "" : "collapsed" %>"> <fieldset id="filters" class="collapsible <%= @query.new_record? ? "" : "collapsed" %>">
<legend onclick="toggleFieldset(this);"><%= l(:label_filter_plural) %></legend> <legend onclick="toggleFieldset(this);"><%= l(:label_filter_plural) %></legend>
...@@ -22,11 +23,25 @@ ...@@ -22,11 +23,25 @@
<p class="buttons"> <p class="buttons">
<%= link_to_function l(:button_apply), '$("#query_form").submit()', :class => 'icon icon-checked' %> <%= link_to_function l(:button_apply), '$("#query_form").submit()', :class => 'icon icon-checked' %>
<%= link_to l(:button_clear), {:project_id => @project, :issue_id => @issue}, :class => 'icon icon-reload' %> <%= link_to l(:button_clear), {:project_id => @project, :issue_id => @issue}, :class => 'icon icon-reload' %>
<% if @query.new_record? %>
<% if User.current.allowed_to?(:save_queries, @project, :global => true) %>
<%= link_to_function l(:button_save),
"$('#query_form').attr('action', '#{ @project ? new_project_query_path(@project) : new_query_path }').submit()",
:class => 'icon icon-save' %>
<% end %>
<% else %>
<% if @query.editable_by?(User.current) %>
<%= link_to l(:button_edit), edit_query_path(@query), :class => 'icon icon-edit' %>
<%= delete_link query_path(@query) %>
<% end %>
<% end %>
</p> </p>
<%= hidden_field_tag 'type', 'TimeEntryQuery' %>
</div> </div>
<div class="tabs hide-when-print"> <div class="tabs hide-when-print">
<% query_params = params.slice(:f, :op, :v, :sort) %> <% query_params = params.slice(:f, :op, :v, :sort, :query_id) %>
<ul> <ul>
<li><%= link_to(l(:label_details), _time_entries_path(@project, @issue, query_params), <li><%= link_to(l(:label_details), _time_entries_path(@project, @issue, query_params),
:class => (action_name == 'index' ? 'selected' : nil)) %></li> :class => (action_name == 'index' ? 'selected' : nil)) %></li>
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
<%= render_timelog_breadcrumb %> <%= render_timelog_breadcrumb %>
<h2><%= l(:label_spent_time) %></h2> <h2><%= @query.new_record? ? l(:label_spent_time) : @query.name %></h2>
<%= form_tag(params.slice(:project_id, :issue_id), :method => :get, :id => 'query_form') do %> <%= form_tag(params.slice(:project_id, :issue_id), :method => :get, :id => 'query_form') do %>
<%= render :partial => 'date_range' %> <%= render :partial => 'date_range' %>
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
</div> </div>
<% end %> <% end %>
<% html_title l(:label_spent_time), l(:label_details) %> <% html_title(@query.new_record? ? l(:label_spent_time) : @query.name, l(:label_details)) %>
<% content_for :header_tags do %> <% content_for :header_tags do %>
<%= auto_discovery_link_tag(:atom, {:issue_id => @issue, :format => 'atom', :key => User.current.rss_key}, :title => l(:label_spent_time)) %> <%= auto_discovery_link_tag(:atom, {:issue_id => @issue, :format => 'atom', :key => User.current.rss_key}, :title => l(:label_spent_time)) %>
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
<%= render_timelog_breadcrumb %> <%= render_timelog_breadcrumb %>
<h2><%= l(:label_spent_time) %></h2> <h2><%= @query.new_record? ? l(:label_spent_time) : @query.name %></h2>
<%= form_tag(params.slice(:project_id, :issue_id), :method => :get, :id => 'query_form') do %> <%= form_tag(params.slice(:project_id, :issue_id), :method => :get, :id => 'query_form') do %>
<% @report.criteria.each do |criterion| %> <% @report.criteria.each do |criterion| %>
...@@ -70,5 +70,5 @@ ...@@ -70,5 +70,5 @@
<% end %> <% end %>
<% end %> <% end %>
<% html_title l(:label_spent_time), l(:label_report) %> <% html_title(@query.new_record? ? l(:label_spent_time) : @query.name, l(:label_report)) %>
...@@ -806,7 +806,7 @@ module Redmine ...@@ -806,7 +806,7 @@ module Redmine
scope = object.project.shared_versions scope = object.project.shared_versions
filtered_versions_options(custom_field, scope, all_statuses) filtered_versions_options(custom_field, scope, all_statuses)
elsif object.nil? elsif object.nil?
scope = Version.visible.where(:sharing => 'system') scope = ::Version.visible.where(:sharing => 'system')
filtered_versions_options(custom_field, scope, all_statuses) filtered_versions_options(custom_field, scope, all_statuses)
else else
[] []
......
...@@ -399,9 +399,9 @@ class IssuesControllerTest < ActionController::TestCase ...@@ -399,9 +399,9 @@ class IssuesControllerTest < ActionController::TestCase
def test_index_with_query_id_and_project_id_should_set_session_query def test_index_with_query_id_and_project_id_should_set_session_query
get :index, :project_id => 1, :query_id => 4 get :index, :project_id => 1, :query_id => 4
assert_response :success assert_response :success
assert_kind_of Hash, session[:query] assert_kind_of Hash, session[:issue_query]
assert_equal 4, session[:query][:id] assert_equal 4, session[:issue_query][:id]
assert_equal 1, session[:query][:project_id] assert_equal 1, session[:issue_query][:project_id]
end end
def test_index_with_invalid_query_id_should_respond_404 def test_index_with_invalid_query_id_should_respond_404
...@@ -411,7 +411,7 @@ class IssuesControllerTest < ActionController::TestCase ...@@ -411,7 +411,7 @@ class IssuesControllerTest < ActionController::TestCase
def test_index_with_cross_project_query_in_session_should_show_project_issues def test_index_with_cross_project_query_in_session_should_show_project_issues
q = IssueQuery.create!(:name => "test", :user_id => 2, :visibility => IssueQuery::VISIBILITY_PRIVATE, :project => nil) q = IssueQuery.create!(:name => "test", :user_id => 2, :visibility => IssueQuery::VISIBILITY_PRIVATE, :project => nil)
@request.session[:query] = {:id => q.id, :project_id => 1} @request.session[:issue_query] = {:id => q.id, :project_id => 1}
with_settings :display_subprojects_issues => '0' do with_settings :display_subprojects_issues => '0' do
get :index, :project_id => 1 get :index, :project_id => 1
...@@ -832,9 +832,9 @@ class IssuesControllerTest < ActionController::TestCase ...@@ -832,9 +832,9 @@ class IssuesControllerTest < ActionController::TestCase
assert_equal columns, query.column_names.map(&:to_s) assert_equal columns, query.column_names.map(&:to_s)
# columns should be stored in session # columns should be stored in session
assert_kind_of Hash, session[:query] assert_kind_of Hash, session[:issue_query]
assert_kind_of Array, session[:query][:column_names] assert_kind_of Array, session[:issue_query][:column_names]
assert_equal columns, session[:query][:column_names].map(&:to_s) assert_equal columns, session[:issue_query][:column_names].map(&:to_s)
# ensure only these columns are kept in the selected columns list # ensure only these columns are kept in the selected columns list
assert_select 'select#selected_columns option' do assert_select 'select#selected_columns option' do
......
...@@ -58,6 +58,13 @@ class QueriesControllerTest < ActionController::TestCase ...@@ -58,6 +58,13 @@ class QueriesControllerTest < ActionController::TestCase
assert_response 404 assert_response 404
end end
def test_new_time_entry_query
@request.session[:user_id] = 2
get :new, :project_id => 1, :type => 'TimeEntryQuery'
assert_response :success
assert_select 'input[name=type][value=?]', 'TimeEntryQuery'
end
def test_create_project_public_query def test_create_project_public_query
@request.session[:user_id] = 2 @request.session[:user_id] = 2
post :create, post :create,
...@@ -263,6 +270,26 @@ class QueriesControllerTest < ActionController::TestCase ...@@ -263,6 +270,26 @@ class QueriesControllerTest < ActionController::TestCase
assert_equal Query::VISIBILITY_PUBLIC, query.visibility assert_equal Query::VISIBILITY_PUBLIC, query.visibility
end end
def test_create_project_public_time_entry_query
@request.session[:user_id] = 2
q = new_record(TimeEntryQuery) do
post :create,
:project_id => 'ecookbook',
:type => 'TimeEntryQuery',
:default_columns => '1',
:f => ["spent_on"],
:op => {"spent_on" => "="},
:v => { "spent_on" => ["2016-07-14"]},
:query => {"name" => "test_new_project_public_query", "visibility" => "2"}
end
assert_redirected_to :controller => 'timelog', :action => 'index', :project_id => 'ecookbook', :query_id => q.id
assert q.is_public?
assert q.has_default_columns?
assert q.valid?
end
def test_edit_global_public_query def test_edit_global_public_query
@request.session[:user_id] = 1 @request.session[:user_id] = 1
get :edit, :id => 4 get :edit, :id => 4
......
...@@ -759,6 +759,16 @@ class TimelogControllerTest < ActionController::TestCase ...@@ -759,6 +759,16 @@ class TimelogControllerTest < ActionController::TestCase
assert_equal values.sort, values assert_equal values.sort, values
end end
def test_index_with_query
query = TimeEntryQuery.new(:project_id => 1, :name => 'Time Entry Query', :visibility => 2)
query.save!
@request.session[:user_id] = 2
get :index, :project_id => 'ecookbook', :query_id => query.id
assert_response :success
assert_select 'h2', :text => query.name
end
def test_index_atom_feed def test_index_atom_feed
get :index, :project_id => 1, :format => 'atom' get :index, :project_id => 1, :format => 'atom'
assert_response :success assert_response :success
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment