##// END OF EJS Templates
My page - Spent time: configurable number of days to display (#8761)....
Jean-Philippe Lang -
r15560:db5bd2b2de47
parent child
Show More
@@ -0,0 +1,3
1 <% @updated_blocks.each do |block| %>
2 $("#block-<%= block %>").html("<%= escape_javascript render_block_content(block.to_s, @user) %>");
3 <% end %>
@@ -130,6 +130,17 class MyController < ApplicationController
130 redirect_to my_account_path
130 redirect_to my_account_path
131 end
131 end
132
132
133 def update_page
134 @user = User.current
135 block_settings = params[:settings] || {}
136
137 block_settings.each do |block, settings|
138 @user.pref.update_block_settings(block, settings)
139 end
140 @user.pref.save
141 @updated_blocks = block_settings.keys
142 end
143
133 # User's page layout configuration
144 # User's page layout configuration
134 def page_layout
145 def page_layout
135 @user = User.current
146 @user = User.current
@@ -45,8 +45,9 module MyHelper
45 return
45 return
46 end
46 end
47
47
48 settings = user.pref.my_page_settings(block)
48 begin
49 begin
49 render(:partial => "my/blocks/#{block}", :locals => {:user => user})
50 render(:partial => "my/blocks/#{block}", :locals => {:user => user, :settings => settings})
50 rescue ActionView::MissingTemplate
51 rescue ActionView::MissingTemplate
51 Rails.logger.warn("Template missing for block \"#{block}\" found in #{user.login} (id=#{user.id}) preferences")
52 Rails.logger.warn("Template missing for block \"#{block}\" found in #{user.login} (id=#{user.id}) preferences")
52 return nil
53 return nil
@@ -107,13 +108,18 module MyHelper
107 to_a
108 to_a
108 end
109 end
109
110
110 def timelog_items
111 def timelog_items(settings)
111 TimeEntry.
112 days = settings[:days].to_i
112 where("#{TimeEntry.table_name}.user_id = ? AND #{TimeEntry.table_name}.spent_on BETWEEN ? AND ?", User.current.id, User.current.today - 6, User.current.today).
113 days = 7 if days < 1 || days > 365
114
115 entries = TimeEntry.
116 where("#{TimeEntry.table_name}.user_id = ? AND #{TimeEntry.table_name}.spent_on BETWEEN ? AND ?", User.current.id, User.current.today - (days - 1), User.current.today).
113 joins(:activity, :project).
117 joins(:activity, :project).
114 references(:issue => [:tracker, :status]).
118 references(:issue => [:tracker, :status]).
115 includes(:issue => [:tracker, :status]).
119 includes(:issue => [:tracker, :status]).
116 order("#{TimeEntry.table_name}.spent_on DESC, #{Project.table_name}.name ASC, #{Tracker.table_name}.position ASC, #{Issue.table_name}.id ASC").
120 order("#{TimeEntry.table_name}.spent_on DESC, #{Project.table_name}.name ASC, #{Tracker.table_name}.position ASC, #{Issue.table_name}.id ASC").
117 to_a
121 to_a
122
123 return entries, days
118 end
124 end
119 end
125 end
@@ -91,6 +91,19 class UserPreference < ActiveRecord::Base
91 self[:my_page_layout] = arg
91 self[:my_page_layout] = arg
92 end
92 end
93
93
94 def my_page_settings(block=nil)
95 s = self[:my_page_settings] ||= {}
96 if block
97 s[block] ||= {}
98 else
99 s
100 end
101 end
102
103 def my_page_settings=(arg)
104 self[:my_page_settings] = arg
105 end
106
94 def remove_block(block)
107 def remove_block(block)
95 block = block.to_s.underscore
108 block = block.to_s.underscore
96 %w(top left right).each do |f|
109 %w(top left right).each do |f|
@@ -108,4 +121,9 class UserPreference < ActiveRecord::Base
108 my_page_layout['top'] ||= []
121 my_page_layout['top'] ||= []
109 my_page_layout['top'].unshift(block)
122 my_page_layout['top'].unshift(block)
110 end
123 end
124
125 def update_block_settings(block, settings)
126 block_settings = my_page_settings(block).merge(settings.symbolize_keys)
127 my_page_settings[block] = block_settings
128 end
111 end
129 end
@@ -1,18 +1,37
1 <%
1 <%
2 entries = timelog_items
2 entries, days = timelog_items(settings)
3 entries_by_day = entries.group_by(&:spent_on)
3 entries_by_day = entries.group_by(&:spent_on)
4 %>
4 %>
5 <% if User.current.allowed_to?(:log_time, nil, :global => true) %>
5
6 <div class="contextual">
6 <div class="contextual">
7 <%= link_to l(:button_log_time), new_time_entry_path, :class => "icon icon-add" %>
7 <%= link_to l(:button_log_time), new_time_entry_path, :class => "icon icon-add" if User.current.allowed_to?(:log_time, nil, :global => true) %>
8 <%= link_to_function l(:label_options), "$('#timelog-settings').toggle();", :class => 'icon-only icon-settings' %>
8 </div>
9 </div>
9 <% end %>
10
10
11 <h3>
11 <h3>
12 <%= link_to l(:label_spent_time), time_entries_path(:user_id => 'me') %>
12 <%= link_to l(:label_spent_time), time_entries_path(:user_id => 'me') %>
13 (<%= l(:label_last_n_days, 7) %>: <%= l_hours_short entries.sum(&:hours) %>)
13 (<%= l(:label_last_n_days, days) %>: <%= l_hours_short entries.sum(&:hours) %>)
14 </h3>
14 </h3>
15
15
16
17 <div id="timelog-settings" style="display:none;">
18 <%= form_tag({}, :remote => true) do %>
19 <div class="box">
20 <p>
21 <label>
22 <%= l(:button_show) %>:
23 <%= text_field_tag 'settings[timelog][days]', days, :size => 6 %>
24 <%= l(:label_day_plural) %>
25 </label>
26 </p>
27 </div>
28 <p>
29 <%= submit_tag l(:button_save) %>
30 <%= link_to_function l(:button_cancel), "$('#timelog-settings').toggle();" %>
31 </p>
32 <% end %>
33 </div>
34
16 <% if entries.any? %>
35 <% if entries.any? %>
17 <%= form_tag({}, :data => {:cm_url => time_entries_context_menu_path}) do %>
36 <%= form_tag({}, :data => {:cm_url => time_entries_context_menu_path}) do %>
18 <table class="list time-entries">
37 <table class="list time-entries">
@@ -74,6 +74,7 Rails.application.routes.draw do
74 match 'my/account', :controller => 'my', :action => 'account', :via => [:get, :post]
74 match 'my/account', :controller => 'my', :action => 'account', :via => [:get, :post]
75 match 'my/account/destroy', :controller => 'my', :action => 'destroy', :via => [:get, :post]
75 match 'my/account/destroy', :controller => 'my', :action => 'destroy', :via => [:get, :post]
76 match 'my/page', :controller => 'my', :action => 'page', :via => :get
76 match 'my/page', :controller => 'my', :action => 'page', :via => :get
77 post 'my/page', :to => 'my#update_page'
77 match 'my', :controller => 'my', :action => 'index', :via => :get # Redirects to my/page
78 match 'my', :controller => 'my', :action => 'index', :via => :get # Redirects to my/page
78 get 'my/api_key', :to => 'my#show_api_key', :as => 'my_api_key'
79 get 'my/api_key', :to => 'my#show_api_key', :as => 'my_api_key'
79 post 'my/api_key', :to => 'my#reset_api_key'
80 post 'my/api_key', :to => 'my#reset_api_key'
@@ -1218,6 +1218,7 div.wiki img {vertical-align:middle; max-width:100%;}
1218 .icon-list { background-image: url(../images/text_list_bullets.png); }
1218 .icon-list { background-image: url(../images/text_list_bullets.png); }
1219 .icon-close { background-image: url(../images/close.png); }
1219 .icon-close { background-image: url(../images/close.png); }
1220 .icon-close:hover { background-image: url(../images/close_hl.png); }
1220 .icon-close:hover { background-image: url(../images/close_hl.png); }
1221 .icon-settings { background-image: url(../images/changeset.png); }
1221
1222
1222 .icon-file { background-image: url(../images/files/default.png); }
1223 .icon-file { background-image: url(../images/files/default.png); }
1223 .icon-file.text-plain { background-image: url(../images/files/text.png); }
1224 .icon-file.text-plain { background-image: url(../images/files/text.png); }
@@ -1242,7 +1243,7 div.wiki img {vertical-align:middle; max-width:100%;}
1242 .sort-handle.ajax-loading { background-image: url(../images/loading.gif); }
1243 .sort-handle.ajax-loading { background-image: url(../images/loading.gif); }
1243 tr.ui-sortable-helper { border:1px solid #e4e4e4; }
1244 tr.ui-sortable-helper { border:1px solid #e4e4e4; }
1244
1245
1245 .contextual>.icon:not(:first-child), .buttons>.icon:not(:first-child) { margin-left: 5px; }
1246 .contextual>*:not(:first-child), .buttons>.icon:not(:first-child) { margin-left: 5px; }
1246
1247
1247 img.gravatar {
1248 img.gravatar {
1248 vertical-align: middle;
1249 vertical-align: middle;
@@ -221,6 +221,18 class MyControllerTest < Redmine::ControllerTest
221 end
221 end
222 end
222 end
223
223
224 def test_update_page_with_blank_preferences
225 user = User.generate!(:language => 'en')
226 @request.session[:user_id] = user.id
227
228 xhr :post, :update_page, :settings => {'timelog' => {'days' => '14'}}
229 assert_response :success
230 assert_include '$("#block-timelog").html(', response.body
231 assert_include '14 days', response.body
232
233 assert_equal({:days => "14"}, user.reload.pref.my_page_settings('timelog'))
234 end
235
224 def test_page_layout
236 def test_page_layout
225 get :page_layout
237 get :page_layout
226 assert_response :success
238 assert_response :success
@@ -26,6 +26,7 class RoutingMyTest < Redmine::RoutingTest
26 should_route 'POST /my/account/destroy' => 'my#destroy'
26 should_route 'POST /my/account/destroy' => 'my#destroy'
27
27
28 should_route 'GET /my/page' => 'my#page'
28 should_route 'GET /my/page' => 'my#page'
29 should_route 'POST /my/page' => 'my#update_page'
29 should_route 'GET /my' => 'my#index'
30 should_route 'GET /my' => 'my#index'
30
31
31 should_route 'GET /my/api_key' => 'my#show_api_key'
32 should_route 'GET /my/api_key' => 'my#show_api_key'
General Comments 0
You need to be logged in to leave comments. Login now