Project

General

Profile

Feature #20458 » 20458.patch

Takenori TAKAKI, 2022-09-15 03:56

View differences:

app/controllers/activities_controller.rb
32 32
    @date_to ||= User.current.today + 1
33 33
    @date_from = @date_to - @days
34 34
    @with_subprojects = params[:with_subprojects].nil? ? Setting.display_subprojects_issues? : (params[:with_subprojects] == '1')
35
    if params[:user_id].present?
36
      @author = User.visible.active.find(params[:user_id])
35
    @authors = []
36
    if params[:user_ids].present?
37
      @authors = User.visible.active.where(:id => params[:user_ids])
38
      raise ActiveRecord::RecordNotFound if @authors.empty?
37 39
    end
38 40

  
39 41
    @activity = Redmine::Activity::Fetcher.new(User.current, :project => @project,
40 42
                                                             :with_subprojects => @with_subprojects,
41
                                                             :author => @author)
43
                                                             :authors => @authors)
42 44
    pref = User.current.pref
43 45
    @activity.scope_select {|t| !params["show_#{t}"].nil?}
44 46
    if @activity.scope.present?
......
47 49
        pref.save
48 50
      end
49 51
    else
50
      if @author.nil?
52
      if @authors.empty?
51 53
        scope = pref.activity_scope & @activity.event_types
52 54
        @activity.scope = scope.present? ? scope : :default
53 55
      else
......
62 64
        @activity.events(@date_from, @date_to)
63 65
      end
64 66

  
65
    if events.empty? || stale?(:etag => [@activity.scope, @date_to, @date_from, @with_subprojects, @author, events.first, events.size, User.current, current_language])
67
    if events.empty? || stale?(:etag => [@activity.scope, @date_to, @date_from, @with_subprojects, @authors.first, @authors.size, events.first, events.size, User.current, current_language])
66 68
      respond_to do |format|
67 69
        format.html do
68 70
          @events_by_day = events.group_by {|event| User.current.time_to_date(event.event_datetime)}
......
70 72
        end
71 73
        format.atom do
72 74
          title = l(:label_activity)
73
          if @author
74
            title = @author.name
75
          if @authors.any?
76
            title = @authors.map(&:name).join(", ")
75 77
          elsif @activity.scope.size == 1
76 78
            title = l("label_#{@activity.scope.first.singularize}_plural")
77 79
          end
app/views/activities/index.html.erb
1
<h2><%= @author.nil? ? l(:label_activity) : l(:label_user_activity, link_to_user(@author)).html_safe %></h2>
1
<h2><%= @authors.empty? ? l(:label_activity) : l(:label_user_activity, @authors.map{|a| link_to_user(a)}.join(',')).html_safe %></h2>
2 2

  
3 3
<p class="subtitle"><%= l(:label_date_from_to, :start => format_date(@date_to - @days), :end => format_date(@date_to-1)) %></p>
4 4

  
......
38 38
</p>
39 39
<p>
40 40
  <%= l(:label_user) %>
41
  <%= select_tag('user_id', activity_authors_options_for_select(@project, params[:user_id]), include_blank: true) %>
41
  <%= select_tag('user_ids[]', activity_authors_options_for_select(@project, params[:user_ids]), include_blank: true, multiple: (params[:user_ids]&.count.to_i > 1)) %>
42
  <span class="toggle-multiselect icon-only"></span>
42 43
</p>
43 44
<ul>
44 45
<% @activity.event_types.each do |t| %>
......
46 47
    <%= check_box_tag "show_#{t}", 1, @activity.scope.include?(t) %>
47 48
    <label for="show_<%=t%>">
48 49
      <%= link_to(l("label_#{t.singularize}_plural"),
49
                  {"show_#{t}" => 1, :user_id => params[:user_id], :from => params[:from]})%>
50
                  {"show_#{t}" => 1, :user_ids => params[:user_ids], :from => params[:from]})%>
50 51
    </label>
51 52
  </li>
52 53
<% end %>
......
59 60
<% end %>
60 61
<% end %>
61 62

  
62
<% html_title(l(:label_activity), @author) -%>
63
<% html_title(l(:label_activity), @authors) -%>
lib/redmine/activity/fetcher.rb
24 24
      attr_reader :user, :project, :scope
25 25

  
26 26
      def initialize(user, options={})
27
        options.assert_valid_keys(:project, :with_subprojects, :author)
27
        options.assert_valid_keys(:project, :with_subprojects, :author, :authors)
28 28
        @user = user
29 29
        @project = options[:project]
30 30
        @options = options
......
87 87
      def events(from = nil, to = nil, options={})
88 88
        e = []
89 89
        @options[:limit] = options[:limit]
90
        authors = [[@options[:author]], @options[:authors]].flatten.compact
90 91

  
91 92
        @scope.each do |event_type|
92 93
          constantized_providers(event_type).each do |provider|
93
            e += provider.find_events(event_type, @user, from, to, @options)
94
            if authors.any?
95
              e += authors.map { |author| provider.find_events(event_type, @user, from, to, @options.merge(:author => author)) }.flatten
96
            else
97
              e += provider.find_events(event_type, @user, from, to, @options)
98
            end
94 99
          end
95 100
        end
96 101

  
public/javascripts/application.js
1025 1025
  $('#content').on('change', 'input[data-disables], input[data-enables], input[data-shows]', toggleDisabledOnChange);
1026 1026
  toggleDisabledInit();
1027 1027

  
1028
  $('#content').on('click', '.toggle-multiselect', function() {
1028
  $('#content, #sidebar').on('click', '.toggle-multiselect', function() {
1029 1029
    toggleMultiSelect($(this).siblings('select'));
1030 1030
    $(this).toggleClass('icon-toggle-plus icon-toggle-minus');
1031 1031
  });
test/functional/activities_controller_test.rb
82 82
    get(
83 83
      :index,
84 84
      :params => {
85
        :user_id => 2
85
        :user_ids => [2, 3]
86 86
      }
87 87
    )
88 88
    assert_response :success
89 89

  
90
    assert_select 'h2 a[href="/users/2"]', :text => 'John Smith'
91
    assert_select '#sidebar select#user_id option[value="2"][selected=selected]'
90
    { 2 => 'John Smith', 3 => 'Dave Lopper' }.each do |user_id, user_name|
91
      assert_select "h2 a[href='/users/#{user_id}']", :text => user_name
92
      assert_select "#sidebar select#user_ids_ option[value='#{user_id}'][selected=selected]"
93
    end
92 94

  
93 95
    i1 = Issue.find(1)
94 96
    d1 = User.find(1).time_to_date(i1.created_on)
......
101 103
    get(
102 104
      :index,
103 105
      :params => {
104
        :user_id => 299
106
        :user_ids => [299]
105 107
      }
106 108
    )
107 109
    assert_response 404
......
113 115

  
114 116
    @request.session[:user_id] = nil
115 117
    get :index, :params => {
116
      :user_id => user.id
118
      :user_ids => [user.id]
117 119
    }
118 120

  
119 121
    assert_response 404
......
199 201
    get(
200 202
      :index,
201 203
      :params => {
202
        :user_id => 2,
204
        :user_ids => [2, 3],
203 205
        :format => 'atom'
204 206
      }
205 207
    )
206 208
    assert_response :success
207
    assert_select 'title', :text => "Redmine: #{User.find(2).name}"
209
    assert_select 'title', :text => "Redmine: #{User.find(2).name}, #{User.find(3).name}"
208 210
  end
209 211

  
210 212
  def test_index_atom_feed_with_subprojects
(3-3/3)