##// END OF EJS Templates
Moves blocks definition to Redmine::MyPage....
Jean-Philippe Lang -
r15548:8b86d5158e50
parent child
Show More
@@ -1,211 +1,192
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2016 Jean-Philippe Lang
2 # Copyright (C) 2006-2016 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 class MyController < ApplicationController
18 class MyController < ApplicationController
19 before_action :require_login
19 before_action :require_login
20 # let user change user's password when user has to
20 # let user change user's password when user has to
21 skip_before_action :check_password_change, :only => :password
21 skip_before_action :check_password_change, :only => :password
22
22
23 require_sudo_mode :account, only: :post
23 require_sudo_mode :account, only: :post
24 require_sudo_mode :reset_rss_key, :reset_api_key, :show_api_key, :destroy
24 require_sudo_mode :reset_rss_key, :reset_api_key, :show_api_key, :destroy
25
25
26 helper :issues
26 helper :issues
27 helper :users
27 helper :users
28 helper :custom_fields
28 helper :custom_fields
29
29
30 BLOCKS = { 'issuesassignedtome' => :label_assigned_to_me_issues,
31 'issuesreportedbyme' => :label_reported_issues,
32 'issueswatched' => :label_watched_issues,
33 'news' => :label_news_latest,
34 'calendar' => :label_calendar,
35 'documents' => :label_document_plural,
36 'timelog' => :label_spent_time
37 }.merge(Redmine::Views::MyPage::Block.additional_blocks).freeze
38
39 DEFAULT_LAYOUT = { 'left' => ['issuesassignedtome'],
40 'right' => ['issuesreportedbyme']
41 }.freeze
42
43 def index
30 def index
44 page
31 page
45 render :action => 'page'
32 render :action => 'page'
46 end
33 end
47
34
48 # Show user's page
35 # Show user's page
49 def page
36 def page
50 @user = User.current
37 @user = User.current
51 @blocks = @user.pref[:my_page_layout] || DEFAULT_LAYOUT
38 @blocks = @user.pref.my_page_layout
52 end
39 end
53
40
54 # Edit user's account
41 # Edit user's account
55 def account
42 def account
56 @user = User.current
43 @user = User.current
57 @pref = @user.pref
44 @pref = @user.pref
58 if request.post?
45 if request.post?
59 @user.safe_attributes = params[:user]
46 @user.safe_attributes = params[:user]
60 @user.pref.safe_attributes = params[:pref]
47 @user.pref.safe_attributes = params[:pref]
61 if @user.save
48 if @user.save
62 @user.pref.save
49 @user.pref.save
63 set_language_if_valid @user.language
50 set_language_if_valid @user.language
64 flash[:notice] = l(:notice_account_updated)
51 flash[:notice] = l(:notice_account_updated)
65 redirect_to my_account_path
52 redirect_to my_account_path
66 return
53 return
67 end
54 end
68 end
55 end
69 end
56 end
70
57
71 # Destroys user's account
58 # Destroys user's account
72 def destroy
59 def destroy
73 @user = User.current
60 @user = User.current
74 unless @user.own_account_deletable?
61 unless @user.own_account_deletable?
75 redirect_to my_account_path
62 redirect_to my_account_path
76 return
63 return
77 end
64 end
78
65
79 if request.post? && params[:confirm]
66 if request.post? && params[:confirm]
80 @user.destroy
67 @user.destroy
81 if @user.destroyed?
68 if @user.destroyed?
82 logout_user
69 logout_user
83 flash[:notice] = l(:notice_account_deleted)
70 flash[:notice] = l(:notice_account_deleted)
84 end
71 end
85 redirect_to home_path
72 redirect_to home_path
86 end
73 end
87 end
74 end
88
75
89 # Manage user's password
76 # Manage user's password
90 def password
77 def password
91 @user = User.current
78 @user = User.current
92 unless @user.change_password_allowed?
79 unless @user.change_password_allowed?
93 flash[:error] = l(:notice_can_t_change_password)
80 flash[:error] = l(:notice_can_t_change_password)
94 redirect_to my_account_path
81 redirect_to my_account_path
95 return
82 return
96 end
83 end
97 if request.post?
84 if request.post?
98 if !@user.check_password?(params[:password])
85 if !@user.check_password?(params[:password])
99 flash.now[:error] = l(:notice_account_wrong_password)
86 flash.now[:error] = l(:notice_account_wrong_password)
100 elsif params[:password] == params[:new_password]
87 elsif params[:password] == params[:new_password]
101 flash.now[:error] = l(:notice_new_password_must_be_different)
88 flash.now[:error] = l(:notice_new_password_must_be_different)
102 else
89 else
103 @user.password, @user.password_confirmation = params[:new_password], params[:new_password_confirmation]
90 @user.password, @user.password_confirmation = params[:new_password], params[:new_password_confirmation]
104 @user.must_change_passwd = false
91 @user.must_change_passwd = false
105 if @user.save
92 if @user.save
106 # The session token was destroyed by the password change, generate a new one
93 # The session token was destroyed by the password change, generate a new one
107 session[:tk] = @user.generate_session_token
94 session[:tk] = @user.generate_session_token
108 Mailer.password_updated(@user)
95 Mailer.password_updated(@user)
109 flash[:notice] = l(:notice_account_password_updated)
96 flash[:notice] = l(:notice_account_password_updated)
110 redirect_to my_account_path
97 redirect_to my_account_path
111 end
98 end
112 end
99 end
113 end
100 end
114 end
101 end
115
102
116 # Create a new feeds key
103 # Create a new feeds key
117 def reset_rss_key
104 def reset_rss_key
118 if request.post?
105 if request.post?
119 if User.current.rss_token
106 if User.current.rss_token
120 User.current.rss_token.destroy
107 User.current.rss_token.destroy
121 User.current.reload
108 User.current.reload
122 end
109 end
123 User.current.rss_key
110 User.current.rss_key
124 flash[:notice] = l(:notice_feeds_access_key_reseted)
111 flash[:notice] = l(:notice_feeds_access_key_reseted)
125 end
112 end
126 redirect_to my_account_path
113 redirect_to my_account_path
127 end
114 end
128
115
129 def show_api_key
116 def show_api_key
130 @user = User.current
117 @user = User.current
131 end
118 end
132
119
133 # Create a new API key
120 # Create a new API key
134 def reset_api_key
121 def reset_api_key
135 if request.post?
122 if request.post?
136 if User.current.api_token
123 if User.current.api_token
137 User.current.api_token.destroy
124 User.current.api_token.destroy
138 User.current.reload
125 User.current.reload
139 end
126 end
140 User.current.api_key
127 User.current.api_key
141 flash[:notice] = l(:notice_api_access_key_reseted)
128 flash[:notice] = l(:notice_api_access_key_reseted)
142 end
129 end
143 redirect_to my_account_path
130 redirect_to my_account_path
144 end
131 end
145
132
146 # User's page layout configuration
133 # User's page layout configuration
147 def page_layout
134 def page_layout
148 @user = User.current
135 @user = User.current
149 @blocks = @user.pref[:my_page_layout] || DEFAULT_LAYOUT.dup
136 @blocks = @user.pref.my_page_layout
150 @block_options = []
151 BLOCKS.each do |k, v|
152 unless @blocks.values.flatten.include?(k)
153 @block_options << [l("my.blocks.#{v}", :default => [v, v.to_s.humanize]), k.dasherize]
154 end
155 end
156 end
137 end
157
138
158 # Add a block to user's page
139 # Add a block to user's page
159 # The block is added on top of the page
140 # The block is added on top of the page
160 # params[:block] : id of the block to add
141 # params[:block] : id of the block to add
161 def add_block
142 def add_block
162 block = params[:block].to_s.underscore
143 block = params[:block].to_s.underscore
163 if block.present? && BLOCKS.key?(block)
144 if block.present? && Redmine::MyPage.blocks.key?(block)
164 @user = User.current
145 @user = User.current
165 layout = @user.pref[:my_page_layout] || {}
146 layout = @user.pref.my_page_layout
166 # remove if already present in a group
147 # remove if already present in a group
167 %w(top left right).each {|f| (layout[f] ||= []).delete block }
148 %w(top left right).each {|f| (layout[f] ||= []).delete block }
168 # add it on top
149 # add it on top
169 layout['top'].unshift block
150 layout['top'].unshift block
170 @user.pref[:my_page_layout] = layout
151 @user.pref.my_page_layout = layout
171 @user.pref.save
152 @user.pref.save
172 end
153 end
173 redirect_to my_page_layout_path
154 redirect_to my_page_layout_path
174 end
155 end
175
156
176 # Remove a block to user's page
157 # Remove a block to user's page
177 # params[:block] : id of the block to remove
158 # params[:block] : id of the block to remove
178 def remove_block
159 def remove_block
179 block = params[:block].to_s.underscore
160 block = params[:block].to_s.underscore
180 @user = User.current
161 @user = User.current
181 # remove block in all groups
162 # remove block in all groups
182 layout = @user.pref[:my_page_layout] || {}
163 layout = @user.pref.my_page_layout
183 %w(top left right).each {|f| (layout[f] ||= []).delete block }
164 %w(top left right).each {|f| (layout[f] ||= []).delete block }
184 @user.pref[:my_page_layout] = layout
165 @user.pref.my_page_layout = layout
185 @user.pref.save
166 @user.pref.save
186 redirect_to my_page_layout_path
167 redirect_to my_page_layout_path
187 end
168 end
188
169
189 # Change blocks order on user's page
170 # Change blocks order on user's page
190 # params[:group] : group to order (top, left or right)
171 # params[:group] : group to order (top, left or right)
191 # params[:list-(top|left|right)] : array of block ids of the group
172 # params[:list-(top|left|right)] : array of block ids of the group
192 def order_blocks
173 def order_blocks
193 group = params[:group]
174 group = params[:group]
194 @user = User.current
175 @user = User.current
195 if group.is_a?(String)
176 if group.is_a?(String)
196 group_items = (params["blocks"] || []).collect(&:underscore)
177 group_items = (params["blocks"] || []).collect(&:underscore)
197 group_items.each {|s| s.sub!(/^block_/, '')}
178 group_items.each {|s| s.sub!(/^block_/, '')}
198 if group_items and group_items.is_a? Array
179 if group_items and group_items.is_a? Array
199 layout = @user.pref[:my_page_layout] || {}
180 layout = @user.pref.my_page_layout
200 # remove group blocks if they are presents in other groups
181 # remove group blocks if they are presents in other groups
201 %w(top left right).each {|f|
182 %w(top left right).each {|f|
202 layout[f] = (layout[f] || []) - group_items
183 layout[f] = (layout[f] || []) - group_items
203 }
184 }
204 layout[group] = group_items
185 layout[group] = group_items
205 @user.pref[:my_page_layout] = layout
186 @user.pref.my_page_layout = layout
206 @user.pref.save
187 @user.pref.save
207 end
188 end
208 end
189 end
209 head 200
190 head 200
210 end
191 end
211 end
192 end
@@ -1,110 +1,119
1 # encoding: utf-8
1 # encoding: utf-8
2 #
2 #
3 # Redmine - project management software
3 # Redmine - project management software
4 # Copyright (C) 2006-2016 Jean-Philippe Lang
4 # Copyright (C) 2006-2016 Jean-Philippe Lang
5 #
5 #
6 # This program is free software; you can redistribute it and/or
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; either version 2
8 # as published by the Free Software Foundation; either version 2
9 # of the License, or (at your option) any later version.
9 # of the License, or (at your option) any later version.
10 #
10 #
11 # This program is distributed in the hope that it will be useful,
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
14 # GNU General Public License for more details.
15 #
15 #
16 # You should have received a copy of the GNU General Public License
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
19
20 module MyHelper
20 module MyHelper
21 # Renders the blocks
21 # Renders the blocks
22 def render_blocks(blocks, user, options={})
22 def render_blocks(blocks, user, options={})
23 s = ''.html_safe
23 s = ''.html_safe
24
24
25 if blocks.present?
25 if blocks.present?
26 blocks.each do |block|
26 blocks.each do |block|
27 content = render_block_content(block, user)
27 content = render_block_content(block, user)
28 if content.present?
28 if content.present?
29 if options[:edit]
29 if options[:edit]
30 close = link_to(l(:button_delete), {:action => "remove_block", :block => block}, :method => 'post', :class => "icon-only icon-close")
30 close = link_to(l(:button_delete), {:action => "remove_block", :block => block}, :method => 'post', :class => "icon-only icon-close")
31 content = close + content_tag('div', content, :class => 'handle')
31 content = close + content_tag('div', content, :class => 'handle')
32 end
32 end
33
33
34 s << content_tag('div', content, :class => "mypage-box", :id => "block-#{block}")
34 s << content_tag('div', content, :class => "mypage-box", :id => "block-#{block}")
35 end
35 end
36 end
36 end
37 end
37 end
38 s
38 s
39 end
39 end
40
40
41 # Renders a single block content
41 # Renders a single block content
42 def render_block_content(block, user)
42 def render_block_content(block, user)
43 unless MyController::BLOCKS.keys.include?(block)
43 unless Redmine::MyPage.blocks.key?(block)
44 Rails.logger.warn("Unknown block \"#{block}\" found in #{user.login} (id=#{user.id}) preferences")
44 Rails.logger.warn("Unknown block \"#{block}\" found in #{user.login} (id=#{user.id}) preferences")
45 return
45 return
46 end
46 end
47
47
48 begin
48 begin
49 render(:partial => "my/blocks/#{block}", :locals => {:user => user})
49 render(:partial => "my/blocks/#{block}", :locals => {:user => user})
50 rescue ActionView::MissingTemplate
50 rescue ActionView::MissingTemplate
51 Rails.logger.warn("Template missing for block \"#{block}\" found in #{user.login} (id=#{user.id}) preferences")
51 Rails.logger.warn("Template missing for block \"#{block}\" found in #{user.login} (id=#{user.id}) preferences")
52 return nil
52 return nil
53 end
53 end
54 end
54 end
55
55
56 def block_select_tag(user)
57 disabled = user.pref.my_page_layout.values.flatten
58 options = content_tag('option')
59 Redmine::MyPage.block_options.each do |label, block|
60 options << content_tag('option', label, :value => block, :disabled => disabled.include?(block))
61 end
62 content_tag('select', options, :id => "block-select")
63 end
64
56 def calendar_items(startdt, enddt)
65 def calendar_items(startdt, enddt)
57 Issue.visible.
66 Issue.visible.
58 where(:project_id => User.current.projects.map(&:id)).
67 where(:project_id => User.current.projects.map(&:id)).
59 where("(start_date>=? and start_date<=?) or (due_date>=? and due_date<=?)", startdt, enddt, startdt, enddt).
68 where("(start_date>=? and start_date<=?) or (due_date>=? and due_date<=?)", startdt, enddt, startdt, enddt).
60 includes(:project, :tracker, :priority, :assigned_to).
69 includes(:project, :tracker, :priority, :assigned_to).
61 references(:project, :tracker, :priority, :assigned_to).
70 references(:project, :tracker, :priority, :assigned_to).
62 to_a
71 to_a
63 end
72 end
64
73
65 def documents_items
74 def documents_items
66 Document.visible.order("#{Document.table_name}.created_on DESC").limit(10).to_a
75 Document.visible.order("#{Document.table_name}.created_on DESC").limit(10).to_a
67 end
76 end
68
77
69 def issuesassignedtome_items
78 def issuesassignedtome_items
70 Issue.visible.open.
79 Issue.visible.open.
71 assigned_to(User.current).
80 assigned_to(User.current).
72 limit(10).
81 limit(10).
73 includes(:status, :project, :tracker, :priority).
82 includes(:status, :project, :tracker, :priority).
74 references(:status, :project, :tracker, :priority).
83 references(:status, :project, :tracker, :priority).
75 order("#{IssuePriority.table_name}.position DESC, #{Issue.table_name}.updated_on DESC")
84 order("#{IssuePriority.table_name}.position DESC, #{Issue.table_name}.updated_on DESC")
76 end
85 end
77
86
78 def issuesreportedbyme_items
87 def issuesreportedbyme_items
79 Issue.visible.open.
88 Issue.visible.open.
80 where(:author_id => User.current.id).
89 where(:author_id => User.current.id).
81 limit(10).
90 limit(10).
82 includes(:status, :project, :tracker).
91 includes(:status, :project, :tracker).
83 references(:status, :project, :tracker).
92 references(:status, :project, :tracker).
84 order("#{Issue.table_name}.updated_on DESC")
93 order("#{Issue.table_name}.updated_on DESC")
85 end
94 end
86
95
87 def issueswatched_items
96 def issueswatched_items
88 Issue.visible.open.on_active_project.watched_by(User.current.id).recently_updated.limit(10)
97 Issue.visible.open.on_active_project.watched_by(User.current.id).recently_updated.limit(10)
89 end
98 end
90
99
91 def news_items
100 def news_items
92 News.visible.
101 News.visible.
93 where(:project_id => User.current.projects.map(&:id)).
102 where(:project_id => User.current.projects.map(&:id)).
94 limit(10).
103 limit(10).
95 includes(:project, :author).
104 includes(:project, :author).
96 references(:project, :author).
105 references(:project, :author).
97 order("#{News.table_name}.created_on DESC").
106 order("#{News.table_name}.created_on DESC").
98 to_a
107 to_a
99 end
108 end
100
109
101 def timelog_items
110 def timelog_items
102 TimeEntry.
111 TimeEntry.
103 where("#{TimeEntry.table_name}.user_id = ? AND #{TimeEntry.table_name}.spent_on BETWEEN ? AND ?", User.current.id, User.current.today - 6, User.current.today).
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).
104 joins(:activity, :project).
113 joins(:activity, :project).
105 references(:issue => [:tracker, :status]).
114 references(:issue => [:tracker, :status]).
106 includes(:issue => [:tracker, :status]).
115 includes(:issue => [:tracker, :status]).
107 order("#{TimeEntry.table_name}.spent_on DESC, #{Project.table_name}.name ASC, #{Tracker.table_name}.position ASC, #{Issue.table_name}.id ASC").
116 order("#{TimeEntry.table_name}.spent_on DESC, #{Project.table_name}.name ASC, #{Tracker.table_name}.position ASC, #{Issue.table_name}.id ASC").
108 to_a
117 to_a
109 end
118 end
110 end
119 end
@@ -1,85 +1,93
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2016 Jean-Philippe Lang
2 # Copyright (C) 2006-2016 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 class UserPreference < ActiveRecord::Base
18 class UserPreference < ActiveRecord::Base
19 include Redmine::SafeAttributes
19 include Redmine::SafeAttributes
20
20
21 belongs_to :user
21 belongs_to :user
22 serialize :others
22 serialize :others
23
23
24 attr_protected :others, :user_id
24 attr_protected :others, :user_id
25
25
26 before_save :set_others_hash
26 before_save :set_others_hash
27
27
28 safe_attributes 'hide_mail',
28 safe_attributes 'hide_mail',
29 'time_zone',
29 'time_zone',
30 'comments_sorting',
30 'comments_sorting',
31 'warn_on_leaving_unsaved',
31 'warn_on_leaving_unsaved',
32 'no_self_notified',
32 'no_self_notified',
33 'textarea_font'
33 'textarea_font'
34
34
35 TEXTAREA_FONT_OPTIONS = ['monospace', 'proportional']
35 TEXTAREA_FONT_OPTIONS = ['monospace', 'proportional']
36
36
37 def initialize(attributes=nil, *args)
37 def initialize(attributes=nil, *args)
38 super
38 super
39 if new_record? && !(attributes && attributes.key?(:hide_mail))
39 if new_record? && !(attributes && attributes.key?(:hide_mail))
40 self.hide_mail = Setting.default_users_hide_mail?
40 self.hide_mail = Setting.default_users_hide_mail?
41 end
41 end
42 if new_record? && !(attributes && attributes.key?(:no_self_notified))
42 if new_record? && !(attributes && attributes.key?(:no_self_notified))
43 self.no_self_notified = true
43 self.no_self_notified = true
44 end
44 end
45 self.others ||= {}
45 self.others ||= {}
46 end
46 end
47
47
48 def set_others_hash
48 def set_others_hash
49 self.others ||= {}
49 self.others ||= {}
50 end
50 end
51
51
52 def [](attr_name)
52 def [](attr_name)
53 if has_attribute? attr_name
53 if has_attribute? attr_name
54 super
54 super
55 else
55 else
56 others ? others[attr_name] : nil
56 others ? others[attr_name] : nil
57 end
57 end
58 end
58 end
59
59
60 def []=(attr_name, value)
60 def []=(attr_name, value)
61 if has_attribute? attr_name
61 if has_attribute? attr_name
62 super
62 super
63 else
63 else
64 h = (read_attribute(:others) || {}).dup
64 h = (read_attribute(:others) || {}).dup
65 h.update(attr_name => value)
65 h.update(attr_name => value)
66 write_attribute(:others, h)
66 write_attribute(:others, h)
67 value
67 value
68 end
68 end
69 end
69 end
70
70
71 def comments_sorting; self[:comments_sorting] end
71 def comments_sorting; self[:comments_sorting] end
72 def comments_sorting=(order); self[:comments_sorting]=order end
72 def comments_sorting=(order); self[:comments_sorting]=order end
73
73
74 def warn_on_leaving_unsaved; self[:warn_on_leaving_unsaved] || '1'; end
74 def warn_on_leaving_unsaved; self[:warn_on_leaving_unsaved] || '1'; end
75 def warn_on_leaving_unsaved=(value); self[:warn_on_leaving_unsaved]=value; end
75 def warn_on_leaving_unsaved=(value); self[:warn_on_leaving_unsaved]=value; end
76
76
77 def no_self_notified; (self[:no_self_notified] == true || self[:no_self_notified] == '1'); end
77 def no_self_notified; (self[:no_self_notified] == true || self[:no_self_notified] == '1'); end
78 def no_self_notified=(value); self[:no_self_notified]=value; end
78 def no_self_notified=(value); self[:no_self_notified]=value; end
79
79
80 def activity_scope; Array(self[:activity_scope]) ; end
80 def activity_scope; Array(self[:activity_scope]) ; end
81 def activity_scope=(value); self[:activity_scope]=value ; end
81 def activity_scope=(value); self[:activity_scope]=value ; end
82
82
83 def textarea_font; self[:textarea_font] end
83 def textarea_font; self[:textarea_font] end
84 def textarea_font=(value); self[:textarea_font]=value; end
84 def textarea_font=(value); self[:textarea_font]=value; end
85
86 def my_page_layout
87 self[:my_page_layout] ||= Redmine::MyPage.default_layout.deep_dup
88 end
89
90 def my_page_layout=(arg)
91 self[:my_page_layout] = arg
92 end
85 end
93 end
@@ -1,32 +1,29
1 <div class="contextual">
1 <div class="contextual">
2 <% if @block_options.present? %>
2
3 <%= form_tag({:action => "add_block"}, :id => "block-form") do %>
3 <%= form_tag({:action => "add_block"}, :id => "block-form") do %>
4 <%= label_tag('block-select', l(:label_my_page_block)) %>:
4 <%= label_tag('block-select', l(:label_my_page_block)) %>:
5 <%= select_tag 'block',
5 <%= block_select_tag(@user) %>
6 content_tag('option') + options_for_select(@block_options),
7 :id => "block-select" %>
8 <%= link_to l(:button_add), '#', :onclick => '$("#block-form").submit()', :class => 'icon icon-add' %>
6 <%= link_to l(:button_add), '#', :onclick => '$("#block-form").submit()', :class => 'icon icon-add' %>
9 <% end %>
7 <% end %>
10 <% end %>
11 <%= link_to l(:button_back), {:action => 'page'}, :class => 'icon icon-cancel' %>
8 <%= link_to l(:button_back), {:action => 'page'}, :class => 'icon icon-cancel' %>
12 </div>
9 </div>
13
10
14 <h2><%=l(:label_my_page)%></h2>
11 <h2><%=l(:label_my_page)%></h2>
15
12
16 <div id="list-top" class="block-receiver">
13 <div id="list-top" class="block-receiver">
17 <%= render_blocks(@blocks['top'], @user, :edit => true) %>
14 <%= render_blocks(@blocks['top'], @user, :edit => true) %>
18 </div>
15 </div>
19
16
20 <div id="list-left" class="splitcontentleft block-receiver">
17 <div id="list-left" class="splitcontentleft block-receiver">
21 <%= render_blocks(@blocks['left'], @user, :edit => true) %>
18 <%= render_blocks(@blocks['left'], @user, :edit => true) %>
22 </div>
19 </div>
23
20
24 <div id="list-right" class="splitcontentright block-receiver">
21 <div id="list-right" class="splitcontentright block-receiver">
25 <%= render_blocks(@blocks['right'], @user, :edit => true) %>
22 <%= render_blocks(@blocks['right'], @user, :edit => true) %>
26 </div>
23 </div>
27
24
28 <%= javascript_tag "initMyPageSortable('top', '#{ escape_javascript url_for(:action => "order_blocks", :group => "top") }');" %>
25 <%= javascript_tag "initMyPageSortable('top', '#{ escape_javascript url_for(:action => "order_blocks", :group => "top") }');" %>
29 <%= javascript_tag "initMyPageSortable('left', '#{ escape_javascript url_for(:action => "order_blocks", :group => "left") }');" %>
26 <%= javascript_tag "initMyPageSortable('left', '#{ escape_javascript url_for(:action => "order_blocks", :group => "left") }');" %>
30 <%= javascript_tag "initMyPageSortable('right', '#{ escape_javascript url_for(:action => "order_blocks", :group => "right") }');" %>
27 <%= javascript_tag "initMyPageSortable('right', '#{ escape_javascript url_for(:action => "order_blocks", :group => "right") }');" %>
31
28
32 <% html_title(l(:label_my_page)) -%>
29 <% html_title(l(:label_my_page)) -%>
@@ -1,32 +1,62
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2016 Jean-Philippe Lang
2 # Copyright (C) 2006-2016 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 module Redmine
18 module Redmine
19 module Views
20 module MyPage
19 module MyPage
21 module Block
20 include Redmine::I18n
21
22 CORE_BLOCKS = {
23 'issuesassignedtome' => :label_assigned_to_me_issues,
24 'issuesreportedbyme' => :label_reported_issues,
25 'issueswatched' => :label_watched_issues,
26 'news' => :label_news_latest,
27 'calendar' => :label_calendar,
28 'documents' => :label_document_plural,
29 'timelog' => :label_spent_time
30 }
31
32 # Returns the available blocks
33 def self.blocks
34 CORE_BLOCKS.merge(additional_blocks).freeze
35 end
36
37 def self.block_options
38 options = []
39 blocks.each do |k, v|
40 options << [l("my.blocks.#{v}", :default => [v, v.to_s.humanize]), k.dasherize]
41 end
42 options
43 end
44
45 # Returns the additional blocks that are defined by plugin partials
22 def self.additional_blocks
46 def self.additional_blocks
23 @@additional_blocks ||= Dir.glob("#{Redmine::Plugin.directory}/*/app/views/my/blocks/_*.{rhtml,erb}").inject({}) do |h,file|
47 @@additional_blocks ||= Dir.glob("#{Redmine::Plugin.directory}/*/app/views/my/blocks/_*.{rhtml,erb}").inject({}) do |h,file|
24 name = File.basename(file).split('.').first.gsub(/^_/, '')
48 name = File.basename(file).split('.').first.gsub(/^_/, '')
25 h[name] = name.to_sym
49 h[name] = name.to_sym
26 h
50 h
27 end
51 end
28 end
52 end
29 end
53
54 # Returns the default layout for My Page
55 def self.default_layout
56 {
57 'left' => ['issuesassignedtome'],
58 'right' => ['issuesreportedbyme']
59 }
30 end
60 end
31 end
61 end
32 end
62 end
@@ -1,295 +1,295
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2016 Jean-Philippe Lang
2 # Copyright (C) 2006-2016 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 require File.expand_path('../../test_helper', __FILE__)
18 require File.expand_path('../../test_helper', __FILE__)
19
19
20 class MyControllerTest < Redmine::ControllerTest
20 class MyControllerTest < Redmine::ControllerTest
21 fixtures :users, :email_addresses, :user_preferences, :roles, :projects, :members, :member_roles,
21 fixtures :users, :email_addresses, :user_preferences, :roles, :projects, :members, :member_roles,
22 :issues, :issue_statuses, :trackers, :enumerations, :custom_fields, :auth_sources
22 :issues, :issue_statuses, :trackers, :enumerations, :custom_fields, :auth_sources
23
23
24 def setup
24 def setup
25 @request.session[:user_id] = 2
25 @request.session[:user_id] = 2
26 end
26 end
27
27
28 def test_index
28 def test_index
29 get :index
29 get :index
30 assert_response :success
30 assert_response :success
31 assert_select 'h2', 'My page'
31 assert_select 'h2', 'My page'
32 end
32 end
33
33
34 def test_page
34 def test_page
35 get :page
35 get :page
36 assert_response :success
36 assert_response :success
37 assert_select 'h2', 'My page'
37 assert_select 'h2', 'My page'
38 end
38 end
39
39
40 def test_page_with_timelog_block
40 def test_page_with_timelog_block
41 preferences = User.find(2).pref
41 preferences = User.find(2).pref
42 preferences[:my_page_layout] = {'top' => ['timelog']}
42 preferences[:my_page_layout] = {'top' => ['timelog']}
43 preferences.save!
43 preferences.save!
44 TimeEntry.create!(:user => User.find(2), :spent_on => Date.yesterday, :issue_id => 1, :hours => 2.5, :activity_id => 10)
44 TimeEntry.create!(:user => User.find(2), :spent_on => Date.yesterday, :issue_id => 1, :hours => 2.5, :activity_id => 10)
45
45
46 get :page
46 get :page
47 assert_response :success
47 assert_response :success
48 assert_select 'tr.time-entry' do
48 assert_select 'tr.time-entry' do
49 assert_select 'td.subject a[href="/issues/1"]'
49 assert_select 'td.subject a[href="/issues/1"]'
50 assert_select 'td.hours', :text => '2.50'
50 assert_select 'td.hours', :text => '2.50'
51 end
51 end
52 end
52 end
53
53
54 def test_page_with_all_blocks
54 def test_page_with_all_blocks
55 blocks = MyController::BLOCKS.keys
55 blocks = Redmine::MyPage.blocks.keys
56 preferences = User.find(2).pref
56 preferences = User.find(2).pref
57 preferences[:my_page_layout] = {'top' => blocks}
57 preferences[:my_page_layout] = {'top' => blocks}
58 preferences.save!
58 preferences.save!
59
59
60 get :page
60 get :page
61 assert_response :success
61 assert_response :success
62 assert_select 'div.mypage-box', blocks.size
62 assert_select 'div.mypage-box', blocks.size
63 end
63 end
64
64
65 def test_my_account_should_show_editable_custom_fields
65 def test_my_account_should_show_editable_custom_fields
66 get :account
66 get :account
67 assert_response :success
67 assert_response :success
68 assert_select 'input[name=?]', 'user[custom_field_values][4]'
68 assert_select 'input[name=?]', 'user[custom_field_values][4]'
69 end
69 end
70
70
71 def test_my_account_should_not_show_non_editable_custom_fields
71 def test_my_account_should_not_show_non_editable_custom_fields
72 UserCustomField.find(4).update_attribute :editable, false
72 UserCustomField.find(4).update_attribute :editable, false
73
73
74 get :account
74 get :account
75 assert_response :success
75 assert_response :success
76 assert_select 'input[name=?]', 'user[custom_field_values][4]', 0
76 assert_select 'input[name=?]', 'user[custom_field_values][4]', 0
77 end
77 end
78
78
79 def test_my_account_should_show_language_select
79 def test_my_account_should_show_language_select
80 get :account
80 get :account
81 assert_response :success
81 assert_response :success
82 assert_select 'select[name=?]', 'user[language]'
82 assert_select 'select[name=?]', 'user[language]'
83 end
83 end
84
84
85 def test_my_account_should_not_show_language_select_with_force_default_language_for_loggedin
85 def test_my_account_should_not_show_language_select_with_force_default_language_for_loggedin
86 with_settings :force_default_language_for_loggedin => '1' do
86 with_settings :force_default_language_for_loggedin => '1' do
87 get :account
87 get :account
88 assert_response :success
88 assert_response :success
89 assert_select 'select[name=?]', 'user[language]', 0
89 assert_select 'select[name=?]', 'user[language]', 0
90 end
90 end
91 end
91 end
92
92
93 def test_update_account
93 def test_update_account
94 post :account,
94 post :account,
95 :user => {
95 :user => {
96 :firstname => "Joe",
96 :firstname => "Joe",
97 :login => "root",
97 :login => "root",
98 :admin => 1,
98 :admin => 1,
99 :group_ids => ['10'],
99 :group_ids => ['10'],
100 :custom_field_values => {"4" => "0100562500"}
100 :custom_field_values => {"4" => "0100562500"}
101 }
101 }
102
102
103 assert_redirected_to '/my/account'
103 assert_redirected_to '/my/account'
104 user = User.find(2)
104 user = User.find(2)
105 assert_equal "Joe", user.firstname
105 assert_equal "Joe", user.firstname
106 assert_equal "jsmith", user.login
106 assert_equal "jsmith", user.login
107 assert_equal "0100562500", user.custom_value_for(4).value
107 assert_equal "0100562500", user.custom_value_for(4).value
108 # ignored
108 # ignored
109 assert !user.admin?
109 assert !user.admin?
110 assert user.groups.empty?
110 assert user.groups.empty?
111 end
111 end
112
112
113 def test_update_account_should_send_security_notification
113 def test_update_account_should_send_security_notification
114 ActionMailer::Base.deliveries.clear
114 ActionMailer::Base.deliveries.clear
115 post :account,
115 post :account,
116 :user => {
116 :user => {
117 :mail => 'foobar@example.com'
117 :mail => 'foobar@example.com'
118 }
118 }
119
119
120 assert_not_nil (mail = ActionMailer::Base.deliveries.last)
120 assert_not_nil (mail = ActionMailer::Base.deliveries.last)
121 assert_mail_body_match '0.0.0.0', mail
121 assert_mail_body_match '0.0.0.0', mail
122 assert_mail_body_match I18n.t(:mail_body_security_notification_change_to, field: I18n.t(:field_mail), value: 'foobar@example.com'), mail
122 assert_mail_body_match I18n.t(:mail_body_security_notification_change_to, field: I18n.t(:field_mail), value: 'foobar@example.com'), mail
123 assert_select_email do
123 assert_select_email do
124 assert_select 'a[href^=?]', 'http://localhost:3000/my/account', :text => 'My account'
124 assert_select 'a[href^=?]', 'http://localhost:3000/my/account', :text => 'My account'
125 end
125 end
126 # The old email address should be notified about the change for security purposes
126 # The old email address should be notified about the change for security purposes
127 assert [mail.bcc, mail.cc].flatten.include?(User.find(2).mail)
127 assert [mail.bcc, mail.cc].flatten.include?(User.find(2).mail)
128 assert [mail.bcc, mail.cc].flatten.include?('foobar@example.com')
128 assert [mail.bcc, mail.cc].flatten.include?('foobar@example.com')
129 end
129 end
130
130
131 def test_my_account_should_show_destroy_link
131 def test_my_account_should_show_destroy_link
132 get :account
132 get :account
133 assert_select 'a[href="/my/account/destroy"]'
133 assert_select 'a[href="/my/account/destroy"]'
134 end
134 end
135
135
136 def test_get_destroy_should_display_the_destroy_confirmation
136 def test_get_destroy_should_display_the_destroy_confirmation
137 get :destroy
137 get :destroy
138 assert_response :success
138 assert_response :success
139 assert_select 'form[action="/my/account/destroy"]' do
139 assert_select 'form[action="/my/account/destroy"]' do
140 assert_select 'input[name=confirm]'
140 assert_select 'input[name=confirm]'
141 end
141 end
142 end
142 end
143
143
144 def test_post_destroy_without_confirmation_should_not_destroy_account
144 def test_post_destroy_without_confirmation_should_not_destroy_account
145 assert_no_difference 'User.count' do
145 assert_no_difference 'User.count' do
146 post :destroy
146 post :destroy
147 end
147 end
148 assert_response :success
148 assert_response :success
149 end
149 end
150
150
151 def test_post_destroy_without_confirmation_should_destroy_account
151 def test_post_destroy_without_confirmation_should_destroy_account
152 assert_difference 'User.count', -1 do
152 assert_difference 'User.count', -1 do
153 post :destroy, :confirm => '1'
153 post :destroy, :confirm => '1'
154 end
154 end
155 assert_redirected_to '/'
155 assert_redirected_to '/'
156 assert_match /deleted/i, flash[:notice]
156 assert_match /deleted/i, flash[:notice]
157 end
157 end
158
158
159 def test_post_destroy_with_unsubscribe_not_allowed_should_not_destroy_account
159 def test_post_destroy_with_unsubscribe_not_allowed_should_not_destroy_account
160 User.any_instance.stubs(:own_account_deletable?).returns(false)
160 User.any_instance.stubs(:own_account_deletable?).returns(false)
161
161
162 assert_no_difference 'User.count' do
162 assert_no_difference 'User.count' do
163 post :destroy, :confirm => '1'
163 post :destroy, :confirm => '1'
164 end
164 end
165 assert_redirected_to '/my/account'
165 assert_redirected_to '/my/account'
166 end
166 end
167
167
168 def test_change_password
168 def test_change_password
169 get :password
169 get :password
170 assert_response :success
170 assert_response :success
171 assert_select 'input[type=password][name=password]'
171 assert_select 'input[type=password][name=password]'
172 assert_select 'input[type=password][name=new_password]'
172 assert_select 'input[type=password][name=new_password]'
173 assert_select 'input[type=password][name=new_password_confirmation]'
173 assert_select 'input[type=password][name=new_password_confirmation]'
174 end
174 end
175
175
176 def test_update_password
176 def test_update_password
177 post :password, :password => 'jsmith',
177 post :password, :password => 'jsmith',
178 :new_password => 'secret123',
178 :new_password => 'secret123',
179 :new_password_confirmation => 'secret123'
179 :new_password_confirmation => 'secret123'
180 assert_redirected_to '/my/account'
180 assert_redirected_to '/my/account'
181 assert User.try_to_login('jsmith', 'secret123')
181 assert User.try_to_login('jsmith', 'secret123')
182 end
182 end
183
183
184 def test_update_password_with_non_matching_confirmation
184 def test_update_password_with_non_matching_confirmation
185 post :password, :password => 'jsmith',
185 post :password, :password => 'jsmith',
186 :new_password => 'secret123',
186 :new_password => 'secret123',
187 :new_password_confirmation => 'secret1234'
187 :new_password_confirmation => 'secret1234'
188 assert_response :success
188 assert_response :success
189 assert_select_error /Password doesn.*t match confirmation/
189 assert_select_error /Password doesn.*t match confirmation/
190 assert User.try_to_login('jsmith', 'jsmith')
190 assert User.try_to_login('jsmith', 'jsmith')
191 end
191 end
192
192
193 def test_update_password_with_wrong_password
193 def test_update_password_with_wrong_password
194 # wrong password
194 # wrong password
195 post :password, :password => 'wrongpassword',
195 post :password, :password => 'wrongpassword',
196 :new_password => 'secret123',
196 :new_password => 'secret123',
197 :new_password_confirmation => 'secret123'
197 :new_password_confirmation => 'secret123'
198 assert_response :success
198 assert_response :success
199 assert_equal 'Wrong password', flash[:error]
199 assert_equal 'Wrong password', flash[:error]
200 assert User.try_to_login('jsmith', 'jsmith')
200 assert User.try_to_login('jsmith', 'jsmith')
201 end
201 end
202
202
203 def test_change_password_should_redirect_if_user_cannot_change_its_password
203 def test_change_password_should_redirect_if_user_cannot_change_its_password
204 User.find(2).update_attribute(:auth_source_id, 1)
204 User.find(2).update_attribute(:auth_source_id, 1)
205
205
206 get :password
206 get :password
207 assert_not_nil flash[:error]
207 assert_not_nil flash[:error]
208 assert_redirected_to '/my/account'
208 assert_redirected_to '/my/account'
209 end
209 end
210
210
211 def test_update_password_should_send_security_notification
211 def test_update_password_should_send_security_notification
212 ActionMailer::Base.deliveries.clear
212 ActionMailer::Base.deliveries.clear
213 post :password, :password => 'jsmith',
213 post :password, :password => 'jsmith',
214 :new_password => 'secret123',
214 :new_password => 'secret123',
215 :new_password_confirmation => 'secret123'
215 :new_password_confirmation => 'secret123'
216
216
217 assert_not_nil (mail = ActionMailer::Base.deliveries.last)
217 assert_not_nil (mail = ActionMailer::Base.deliveries.last)
218 assert_mail_body_no_match 'secret123', mail # just to be sure: pw should never be sent!
218 assert_mail_body_no_match 'secret123', mail # just to be sure: pw should never be sent!
219 assert_select_email do
219 assert_select_email do
220 assert_select 'a[href^=?]', 'http://localhost:3000/my/password', :text => 'Change password'
220 assert_select 'a[href^=?]', 'http://localhost:3000/my/password', :text => 'Change password'
221 end
221 end
222 end
222 end
223
223
224 def test_page_layout
224 def test_page_layout
225 get :page_layout
225 get :page_layout
226 assert_response :success
226 assert_response :success
227 end
227 end
228
228
229 def test_add_block
229 def test_add_block
230 post :add_block, :block => 'issuesreportedbyme'
230 post :add_block, :block => 'issuesreportedbyme'
231 assert_redirected_to '/my/page_layout'
231 assert_redirected_to '/my/page_layout'
232 assert User.find(2).pref[:my_page_layout]['top'].include?('issuesreportedbyme')
232 assert User.find(2).pref[:my_page_layout]['top'].include?('issuesreportedbyme')
233 end
233 end
234
234
235 def test_add_invalid_block_should_redirect
235 def test_add_invalid_block_should_redirect
236 post :add_block, :block => 'invalid'
236 post :add_block, :block => 'invalid'
237 assert_redirected_to '/my/page_layout'
237 assert_redirected_to '/my/page_layout'
238 end
238 end
239
239
240 def test_remove_block
240 def test_remove_block
241 post :remove_block, :block => 'issuesassignedtome'
241 post :remove_block, :block => 'issuesassignedtome'
242 assert_redirected_to '/my/page_layout'
242 assert_redirected_to '/my/page_layout'
243 assert !User.find(2).pref[:my_page_layout].values.flatten.include?('issuesassignedtome')
243 assert !User.find(2).pref[:my_page_layout].values.flatten.include?('issuesassignedtome')
244 end
244 end
245
245
246 def test_order_blocks
246 def test_order_blocks
247 xhr :post, :order_blocks, :group => 'left', 'blocks' => ['documents', 'calendar', 'latestnews']
247 xhr :post, :order_blocks, :group => 'left', 'blocks' => ['documents', 'calendar', 'latestnews']
248 assert_response :success
248 assert_response :success
249 assert_equal ['documents', 'calendar', 'latestnews'], User.find(2).pref[:my_page_layout]['left']
249 assert_equal ['documents', 'calendar', 'latestnews'], User.find(2).pref[:my_page_layout]['left']
250 end
250 end
251
251
252 def test_reset_rss_key_with_existing_key
252 def test_reset_rss_key_with_existing_key
253 @previous_token_value = User.find(2).rss_key # Will generate one if it's missing
253 @previous_token_value = User.find(2).rss_key # Will generate one if it's missing
254 post :reset_rss_key
254 post :reset_rss_key
255
255
256 assert_not_equal @previous_token_value, User.find(2).rss_key
256 assert_not_equal @previous_token_value, User.find(2).rss_key
257 assert User.find(2).rss_token
257 assert User.find(2).rss_token
258 assert_match /reset/, flash[:notice]
258 assert_match /reset/, flash[:notice]
259 assert_redirected_to '/my/account'
259 assert_redirected_to '/my/account'
260 end
260 end
261
261
262 def test_reset_rss_key_without_existing_key
262 def test_reset_rss_key_without_existing_key
263 assert_nil User.find(2).rss_token
263 assert_nil User.find(2).rss_token
264 post :reset_rss_key
264 post :reset_rss_key
265
265
266 assert User.find(2).rss_token
266 assert User.find(2).rss_token
267 assert_match /reset/, flash[:notice]
267 assert_match /reset/, flash[:notice]
268 assert_redirected_to '/my/account'
268 assert_redirected_to '/my/account'
269 end
269 end
270
270
271 def test_show_api_key
271 def test_show_api_key
272 get :show_api_key
272 get :show_api_key
273 assert_response :success
273 assert_response :success
274 assert_select 'pre', User.find(2).api_key
274 assert_select 'pre', User.find(2).api_key
275 end
275 end
276
276
277 def test_reset_api_key_with_existing_key
277 def test_reset_api_key_with_existing_key
278 @previous_token_value = User.find(2).api_key # Will generate one if it's missing
278 @previous_token_value = User.find(2).api_key # Will generate one if it's missing
279 post :reset_api_key
279 post :reset_api_key
280
280
281 assert_not_equal @previous_token_value, User.find(2).api_key
281 assert_not_equal @previous_token_value, User.find(2).api_key
282 assert User.find(2).api_token
282 assert User.find(2).api_token
283 assert_match /reset/, flash[:notice]
283 assert_match /reset/, flash[:notice]
284 assert_redirected_to '/my/account'
284 assert_redirected_to '/my/account'
285 end
285 end
286
286
287 def test_reset_api_key_without_existing_key
287 def test_reset_api_key_without_existing_key
288 assert_nil User.find(2).api_token
288 assert_nil User.find(2).api_token
289 post :reset_api_key
289 post :reset_api_key
290
290
291 assert User.find(2).api_token
291 assert User.find(2).api_token
292 assert_match /reset/, flash[:notice]
292 assert_match /reset/, flash[:notice]
293 assert_redirected_to '/my/account'
293 assert_redirected_to '/my/account'
294 end
294 end
295 end
295 end
General Comments 0
You need to be logged in to leave comments. Login now