# HG changeset patch # User Chris Cannam # Date 1290601208 0 # Node ID 371eac10df0bde6981a9636dbfbfdd3230a66488 # Parent 09b1d4349da3dde58657fd526967edf711801c2b# Parent 97333e644a2c3a80067929d23c0fe3079c9f4b3b * Merge from "cannam" branch. This includes update to Redmine trunk, plus welcome/tip-of-the-day from luisf branch. diff -r 09b1d4349da3 -r 371eac10df0b .svn/all-wcprops --- a/.svn/all-wcprops Thu Oct 21 11:19:14 2010 +0100 +++ b/.svn/all-wcprops Wed Nov 24 12:20:08 2010 +0000 @@ -1,7 +1,7 @@ K 25 svn:wc:ra_dav:version-url V 24 -/svn/!svn/ver/4173/trunk +/svn/!svn/ver/4411/trunk END Rakefile K 25 diff -r 09b1d4349da3 -r 371eac10df0b .svn/entries --- a/.svn/entries Thu Oct 21 11:19:14 2010 +0100 +++ b/.svn/entries Wed Nov 24 12:20:08 2010 +0000 @@ -1,15 +1,15 @@ 10 dir -4173 +4411 http://redmine.rubyforge.org/svn/trunk http://redmine.rubyforge.org/svn -2010-09-23T16:23:39.070168Z -4173 -winterheart +2010-11-17T18:27:38.712585Z +4411 +jplang has-props diff -r 09b1d4349da3 -r 371eac10df0b app/.svn/all-wcprops --- a/app/.svn/all-wcprops Thu Oct 21 11:19:14 2010 +0100 +++ b/app/.svn/all-wcprops Wed Nov 24 12:20:08 2010 +0000 @@ -1,5 +1,5 @@ K 25 svn:wc:ra_dav:version-url V 28 -/svn/!svn/ver/4172/trunk/app +/svn/!svn/ver/4411/trunk/app END diff -r 09b1d4349da3 -r 371eac10df0b app/.svn/entries --- a/app/.svn/entries Thu Oct 21 11:19:14 2010 +0100 +++ b/app/.svn/entries Wed Nov 24 12:20:08 2010 +0000 @@ -1,15 +1,15 @@ 10 dir -4173 +4411 http://redmine.rubyforge.org/svn/trunk/app http://redmine.rubyforge.org/svn -2010-09-23T15:20:19.085385Z -4172 -edavis10 +2010-11-17T18:27:38.712585Z +4411 +jplang diff -r 09b1d4349da3 -r 371eac10df0b app/controllers/.svn/all-wcprops --- a/app/controllers/.svn/all-wcprops Thu Oct 21 11:19:14 2010 +0100 +++ b/app/controllers/.svn/all-wcprops Wed Nov 24 12:20:08 2010 +0000 @@ -1,13 +1,13 @@ K 25 svn:wc:ra_dav:version-url V 40 -/svn/!svn/ver/4172/trunk/app/controllers +/svn/!svn/ver/4411/trunk/app/controllers END issues_controller.rb K 25 svn:wc:ra_dav:version-url V 61 -/svn/!svn/ver/4083/trunk/app/controllers/issues_controller.rb +/svn/!svn/ver/4411/trunk/app/controllers/issues_controller.rb END queries_controller.rb K 25 @@ -43,7 +43,7 @@ K 25 svn:wc:ra_dav:version-url V 57 -/svn/!svn/ver/3745/trunk/app/controllers/my_controller.rb +/svn/!svn/ver/4224/trunk/app/controllers/my_controller.rb END comments_controller.rb K 25 @@ -67,7 +67,7 @@ K 25 svn:wc:ra_dav:version-url V 68 -/svn/!svn/ver/4059/trunk/app/controllers/context_menus_controller.rb +/svn/!svn/ver/4242/trunk/app/controllers/context_menus_controller.rb END journals_controller.rb K 25 @@ -81,6 +81,12 @@ V 64 /svn/!svn/ver/3536/trunk/app/controllers/workflows_controller.rb END +time_entry_reports_controller.rb +K 25 +svn:wc:ra_dav:version-url +V 73 +/svn/!svn/ver/4232/trunk/app/controllers/time_entry_reports_controller.rb +END reports_controller.rb K 25 svn:wc:ra_dav:version-url @@ -93,53 +99,53 @@ V 75 /svn/!svn/ver/4075/trunk/app/controllers/project_enumerations_controller.rb END +settings_controller.rb +K 25 +svn:wc:ra_dav:version-url +V 63 +/svn/!svn/ver/4220/trunk/app/controllers/settings_controller.rb +END +timelog_controller.rb +K 25 +svn:wc:ra_dav:version-url +V 62 +/svn/!svn/ver/4410/trunk/app/controllers/timelog_controller.rb +END custom_fields_controller.rb K 25 svn:wc:ra_dav:version-url V 68 /svn/!svn/ver/3627/trunk/app/controllers/custom_fields_controller.rb END -timelog_controller.rb +users_controller.rb K 25 svn:wc:ra_dav:version-url -V 62 -/svn/!svn/ver/4087/trunk/app/controllers/timelog_controller.rb -END -settings_controller.rb -K 25 -svn:wc:ra_dav:version-url -V 63 -/svn/!svn/ver/3176/trunk/app/controllers/settings_controller.rb +V 60 +/svn/!svn/ver/4382/trunk/app/controllers/users_controller.rb END issue_moves_controller.rb K 25 svn:wc:ra_dav:version-url V 66 -/svn/!svn/ver/3940/trunk/app/controllers/issue_moves_controller.rb -END -users_controller.rb -K 25 -svn:wc:ra_dav:version-url -V 60 -/svn/!svn/ver/4066/trunk/app/controllers/users_controller.rb +/svn/!svn/ver/4292/trunk/app/controllers/issue_moves_controller.rb END files_controller.rb K 25 svn:wc:ra_dav:version-url V 60 -/svn/!svn/ver/4085/trunk/app/controllers/files_controller.rb +/svn/!svn/ver/4177/trunk/app/controllers/files_controller.rb END application_controller.rb K 25 svn:wc:ra_dav:version-url V 66 -/svn/!svn/ver/4075/trunk/app/controllers/application_controller.rb +/svn/!svn/ver/4286/trunk/app/controllers/application_controller.rb END -previews_controller.rb +ldap_auth_sources_controller.rb K 25 svn:wc:ra_dav:version-url -V 63 -/svn/!svn/ver/3946/trunk/app/controllers/previews_controller.rb +V 72 +/svn/!svn/ver/3744/trunk/app/controllers/ldap_auth_sources_controller.rb END auth_sources_controller.rb K 25 @@ -147,11 +153,11 @@ V 67 /svn/!svn/ver/3744/trunk/app/controllers/auth_sources_controller.rb END -ldap_auth_sources_controller.rb +previews_controller.rb K 25 svn:wc:ra_dav:version-url -V 72 -/svn/!svn/ver/3744/trunk/app/controllers/ldap_auth_sources_controller.rb +V 63 +/svn/!svn/ver/4174/trunk/app/controllers/previews_controller.rb END search_controller.rb K 25 @@ -165,18 +171,18 @@ V 63 /svn/!svn/ver/3528/trunk/app/controllers/messages_controller.rb END -versions_controller.rb -K 25 -svn:wc:ra_dav:version-url -V 63 -/svn/!svn/ver/4097/trunk/app/controllers/versions_controller.rb -END issue_relations_controller.rb K 25 svn:wc:ra_dav:version-url V 70 /svn/!svn/ver/3591/trunk/app/controllers/issue_relations_controller.rb END +versions_controller.rb +K 25 +svn:wc:ra_dav:version-url +V 63 +/svn/!svn/ver/4354/trunk/app/controllers/versions_controller.rb +END boards_controller.rb K 25 svn:wc:ra_dav:version-url @@ -193,7 +199,7 @@ K 25 svn:wc:ra_dav:version-url V 59 -/svn/!svn/ver/4172/trunk/app/controllers/news_controller.rb +/svn/!svn/ver/4174/trunk/app/controllers/news_controller.rb END trackers_controller.rb K 25 @@ -241,7 +247,7 @@ K 25 svn:wc:ra_dav:version-url V 63 -/svn/!svn/ver/4070/trunk/app/controllers/projects_controller.rb +/svn/!svn/ver/4397/trunk/app/controllers/projects_controller.rb END account_controller.rb K 25 @@ -253,7 +259,7 @@ K 25 svn:wc:ra_dav:version-url V 64 -/svn/!svn/ver/4041/trunk/app/controllers/calendars_controller.rb +/svn/!svn/ver/4388/trunk/app/controllers/calendars_controller.rb END issue_categories_controller.rb K 25 @@ -265,7 +271,7 @@ K 25 svn:wc:ra_dav:version-url V 61 -/svn/!svn/ver/4072/trunk/app/controllers/gantts_controller.rb +/svn/!svn/ver/4388/trunk/app/controllers/gantts_controller.rb END documents_controller.rb K 25 @@ -277,7 +283,7 @@ K 25 svn:wc:ra_dav:version-url V 59 -/svn/!svn/ver/3632/trunk/app/controllers/wiki_controller.rb +/svn/!svn/ver/4303/trunk/app/controllers/wiki_controller.rb END activities_controller.rb K 25 diff -r 09b1d4349da3 -r 371eac10df0b app/controllers/.svn/entries --- a/app/controllers/.svn/entries Thu Oct 21 11:19:14 2010 +0100 +++ b/app/controllers/.svn/entries Wed Nov 24 12:20:08 2010 +0000 @@ -1,15 +1,15 @@ 10 dir -4173 +4411 http://redmine.rubyforge.org/svn/trunk/app/controllers http://redmine.rubyforge.org/svn -2010-09-23T15:20:19.085385Z -4172 -edavis10 +2010-11-17T18:27:38.712585Z +4411 +jplang @@ -32,11 +32,11 @@ -2010-09-24T12:48:26.271687Z -611e226f9845a33fb6fe28700968e7de -2010-09-11T20:21:27.018967Z -4083 -jbbarth +2010-11-19T13:04:46.996826Z +e6c77385e49176b593367b44e7b33f3e +2010-11-17T18:27:38.712585Z +4411 +jplang has-props @@ -58,7 +58,7 @@ -13034 +12834 queries_controller.rb file @@ -236,10 +236,10 @@ -2010-09-23T14:37:44.395735Z -b178015d27e341adaa871e3800e94401 -2010-05-23T03:16:37.499264Z -3745 +2010-11-19T13:04:46.996826Z +b465d7aeca2d6b4cc11159ae9bc7349e +2010-09-28T22:13:11.637219Z +4224 edavis10 has-props @@ -262,7 +262,7 @@ -6422 +6021 comments_controller.rb file @@ -372,10 +372,10 @@ -2010-09-24T12:48:26.271687Z -8e09032afd0db141012e59a0f689b687 -2010-09-03T21:43:07.906158Z -4059 +2010-11-19T13:04:46.996826Z +2db29b69c3f0130e470a0a11dfc1f28b +2010-10-08T03:09:51.863032Z +4242 jbbarth @@ -398,7 +398,7 @@ -1647 +1821 journals_controller.rb file @@ -468,6 +468,40 @@ 3346 +time_entry_reports_controller.rb +file + + + + +2010-11-19T13:04:46.996826Z +dadcb57d89dc3c90c5fa099b143c07f8 +2010-10-05T16:07:17.015270Z +4232 +edavis10 + + + + + + + + + + + + + + + + + + + + + +9308 + reports_controller.rb file @@ -536,16 +570,16 @@ 856 -settings_controller.rb +timelog_controller.rb file -2010-09-23T14:37:44.399747Z -b7f5a5cb777aa2418a71520c164da11a -2009-12-17T18:21:02.630202Z -3176 +2010-11-19T13:04:46.996826Z +7984019db8d0beb1d7ff158390d4ad68 +2010-11-16T20:27:45.364396Z +4410 jplang has-props @@ -568,7 +602,7 @@ -2337 +8623 custom_fields_controller.rb file @@ -604,16 +638,16 @@ 2373 -timelog_controller.rb +settings_controller.rb file -2010-09-24T12:48:26.271687Z -7e5890e22da346ff06debe33cc4bf34d -2010-09-14T19:02:25.847894Z -4087 +2010-11-19T13:04:46.996826Z +4328cabdf111342d147b245bc61bb75e +2010-09-28T20:19:55.214366Z +4220 edavis10 has-props @@ -636,7 +670,41 @@ -14320 +2239 + +issue_moves_controller.rb +file + + + + +2010-11-19T13:04:47.000764Z +cacd6ffe0ce299e2ede9d45b7ef8af42 +2010-10-25T18:44:46.868009Z +4292 +edavis10 + + + + + + + + + + + + + + + + + + + + + +2441 users_controller.rb file @@ -644,11 +712,11 @@ -2010-09-24T12:48:26.275788Z -df36e1f9ccb5879ba3aa7b34592c18cf -2010-09-06T01:02:52.851079Z -4066 -edavis10 +2010-11-19T13:04:47.000764Z +3af0a81ba74621dc21d877a579b39d9c +2010-11-07T14:15:01.891476Z +4382 +jplang has-props @@ -670,41 +738,7 @@ -5977 - -issue_moves_controller.rb -file - - - - -2010-09-23T14:37:44.395735Z -41a4ff4e0c4fab3e134a9bfa8136323a -2010-08-13T14:59:04.653474Z -3940 -edavis10 - - - - - - - - - - - - - - - - - - - - - -2290 +7565 files_controller.rb file @@ -712,33 +746,33 @@ -2010-09-24T12:48:26.275788Z -120cefe7fd45eda6957c2e633ceab0fb -2010-09-14T16:24:07.840869Z -4085 -edavis10 - - - - - - - - - - - - - - - - - - - - - -1258 +2010-11-19T13:04:47.000764Z +f0246e8f8dde5ea7b93e4dc2162181fc +2010-09-26T08:07:41.604064Z +4177 +jplang + + + + + + + + + + + + + + + + + + + + + +1289 application_controller.rb file @@ -746,67 +780,67 @@ -2010-09-24T12:48:26.275788Z -e93fc4710d9abbef72273a22b174eb27 -2010-09-10T16:00:49.687515Z -4075 +2010-11-19T13:04:47.000764Z +8f7d4c9d306ae9d59ea0e064466454d1 +2010-10-23T11:07:04.019894Z +4286 +jplang +has-props + + + + + + + + + + + + + + + + + + + + +13669 + +previews_controller.rb +file + + + + +2010-11-19T13:04:47.000764Z +c5ae4fae18159e70fd81c2487bb1daa1 +2010-09-24T16:26:46.819682Z +4174 edavis10 -has-props - - - - - - - - - - - - - - - - - - - - -13486 - -ldap_auth_sources_controller.rb -file - - - - -2010-09-23T14:37:44.395735Z -5f7b9cb2e9c8a60db58ea0833cf481c5 -2010-05-23T03:16:31.304135Z -3744 -edavis10 - - - - - - - - - - - - - - - - - - - - - -917 + + + + + + + + + + + + + + + + + + + + + +957 auth_sources_controller.rb file @@ -842,16 +876,16 @@ 2542 -previews_controller.rb +ldap_auth_sources_controller.rb file 2010-09-23T14:37:44.395735Z -1407f3993f625a9fa14fa0e208c3df4f -2010-08-18T15:01:35.032314Z -3946 +5f7b9cb2e9c8a60db58ea0833cf481c5 +2010-05-23T03:16:31.304135Z +3744 edavis10 @@ -874,7 +908,7 @@ -835 +917 search_controller.rb file @@ -944,6 +978,40 @@ 5824 +versions_controller.rb +file + + + + +2010-11-19T13:04:47.000764Z +a98fb262a20669600a85c0f72202c5e6 +2010-11-01T13:13:32.982466Z +4354 +jplang +has-props + + + + + + + + + + + + + + + + + + + + +6241 + issue_relations_controller.rb file @@ -978,40 +1046,6 @@ 2220 -versions_controller.rb -file - - - - -2010-09-24T12:48:26.275788Z -9cc19ecc2f9e1ad458f27cdbcd450970 -2010-09-17T15:55:08.377083Z -4097 -edavis10 -has-props - - - - - - - - - - - - - - - - - - - - -6136 - boards_controller.rb file @@ -1086,10 +1120,10 @@ -2010-09-24T12:48:26.275788Z -dd877e070cf218909dccfc0c67658914 -2010-09-23T15:20:19.085385Z -4172 +2010-11-19T13:04:47.000764Z +d9e36fcf69f18973b274648b7b70dccf +2010-09-24T16:26:46.819682Z +4174 edavis10 has-props @@ -1112,7 +1146,7 @@ -3388 +3221 trackers_controller.rb file @@ -1358,11 +1392,11 @@ -2010-09-24T12:48:26.275788Z -7a9d61829d2ebbcab2524e763a28235b -2010-09-08T16:01:51.939478Z -4070 -edavis10 +2010-11-19T13:04:47.000764Z +b0f584d53a742f6c89b157030f9d6a8d +2010-11-13T10:05:43.644565Z +4397 +jplang has-props @@ -1384,7 +1418,7 @@ -9973 +10011 account_controller.rb file @@ -1426,33 +1460,33 @@ -2010-09-24T12:48:26.275788Z -cac7d6c5cbe1f559c89a3f41e79ea4b5 -2010-08-26T16:36:59.817467Z -4041 -edavis10 - - - - - - - - - - - - - - - - - - - - - -1354 +2010-11-19T13:04:47.000764Z +0be20cab6d5ea49f428a90cf3afef3e3 +2010-11-07T22:38:10.728638Z +4388 +jplang + + + + + + + + + + + + + + + + + + + + + +1390 issue_categories_controller.rb file @@ -1494,11 +1528,11 @@ -2010-09-24T12:48:26.275788Z +2010-11-19T13:04:47.000764Z 81dbee1745da99b9ea499f3fbe1d3944 -2010-09-10T03:09:02.311267Z -4072 -edavis10 +2010-11-07T22:38:10.728638Z +4388 +jplang @@ -1562,11 +1596,11 @@ -2010-09-23T14:37:44.403745Z -cb709bfbd3ba20cd9e7245a9575a720d -2010-04-11T12:56:18.077630Z -3632 -jplang +2010-11-19T13:04:47.004764Z +0af823002ab9c7e8f59b3d12cf6267e9 +2010-10-28T21:25:38.778234Z +4303 +edavis10 has-props @@ -1588,7 +1622,7 @@ -9211 +10145 activities_controller.rb file diff -r 09b1d4349da3 -r 371eac10df0b app/controllers/.svn/text-base/application_controller.rb.svn-base --- a/app/controllers/.svn/text-base/application_controller.rb.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/controllers/.svn/text-base/application_controller.rb.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -153,8 +153,16 @@ # Authorize the user for the requested action def authorize(ctrl = params[:controller], action = params[:action], global = false) - allowed = User.current.allowed_to?({:controller => ctrl, :action => action}, @project, :global => global) - allowed ? true : deny_access + allowed = User.current.allowed_to?({:controller => ctrl, :action => action}, @project || @projects, :global => global) + if allowed + true + else + if @project && @project.archived? + render_403 :message => :notice_not_authorized_archived_project + else + deny_access + end + end end # Authorize the user for the requested action outside a project @@ -213,16 +221,19 @@ def find_issues @issues = Issue.find_all_by_id(params[:id] || params[:ids]) raise ActiveRecord::RecordNotFound if @issues.empty? - projects = @issues.collect(&:project).compact.uniq - if projects.size == 1 - @project = projects.first - else + @projects = @issues.collect(&:project).compact.uniq + @project = @projects.first if @projects.size == 1 + rescue ActiveRecord::RecordNotFound + render_404 + end + + # Check if project is unique before bulk operations + def check_project_uniqueness + unless @project # TODO: let users bulk edit/move/destroy issues from different projects render_error 'Can not bulk edit/move/destroy issues from different projects' return false end - rescue ActiveRecord::RecordNotFound - render_404 end # make sure that the user is a member of the project (or admin) if project is private @@ -262,39 +273,33 @@ redirect_to default end - def render_403 + def render_403(options={}) @project = nil - respond_to do |format| - format.html { render :template => "common/403", :layout => use_layout, :status => 403 } - format.atom { head 403 } - format.xml { head 403 } - format.js { head 403 } - format.json { head 403 } - end + render_error({:message => :notice_not_authorized, :status => 403}.merge(options)) return false end - def render_404 - respond_to do |format| - format.html { render :template => "common/404", :layout => use_layout, :status => 404 } - format.atom { head 404 } - format.xml { head 404 } - format.js { head 404 } - format.json { head 404 } - end + def render_404(options={}) + render_error({:message => :notice_file_not_found, :status => 404}.merge(options)) return false end - def render_error(msg) + # Renders an error response + def render_error(arg) + arg = {:message => arg} unless arg.is_a?(Hash) + + @message = arg[:message] + @message = l(@message) if @message.is_a?(Symbol) + @status = arg[:status] || 500 + respond_to do |format| - format.html { - flash.now[:error] = msg - render :text => '', :layout => use_layout, :status => 500 + format.html { + render :template => 'common/error', :layout => use_layout, :status => @status } - format.atom { head 500 } - format.xml { head 500 } - format.js { head 500 } - format.json { head 500 } + format.atom { head @status } + format.xml { head @status } + format.js { head @status } + format.json { head @status } end end diff -r 09b1d4349da3 -r 371eac10df0b app/controllers/.svn/text-base/calendars_controller.rb.svn-base --- a/app/controllers/.svn/text-base/calendars_controller.rb.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/controllers/.svn/text-base/calendars_controller.rb.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -8,6 +8,8 @@ helper :projects helper :queries include QueriesHelper + helper :sort + include SortHelper def show if params[:year] and params[:year].to_i > 1900 diff -r 09b1d4349da3 -r 371eac10df0b app/controllers/.svn/text-base/context_menus_controller.rb.svn-base --- a/app/controllers/.svn/text-base/context_menus_controller.rb.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/controllers/.svn/text-base/context_menus_controller.rb.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -16,17 +16,21 @@ @projects = @issues.collect(&:project).compact.uniq @project = @projects.first if @projects.size == 1 - @can = {:edit => (@project && User.current.allowed_to?(:edit_issues, @project)), + @can = {:edit => User.current.allowed_to?(:edit_issues, @projects), :log_time => (@project && User.current.allowed_to?(:log_time, @project)), - :update => (@project && (User.current.allowed_to?(:edit_issues, @project) || (User.current.allowed_to?(:change_status, @project) && @allowed_statuses && !@allowed_statuses.empty?))), + :update => (User.current.allowed_to?(:edit_issues, @projects) || (User.current.allowed_to?(:change_status, @projects) && !@allowed_statuses.blank?)), :move => (@project && User.current.allowed_to?(:move_issues, @project)), :copy => (@issue && @project.trackers.include?(@issue.tracker) && User.current.allowed_to?(:add_issues, @project)), - :delete => (@project && User.current.allowed_to?(:delete_issues, @project)) + :delete => User.current.allowed_to?(:delete_issues, @projects) } if @project @assignables = @project.assignable_users @assignables << @issue.assigned_to if @issue && @issue.assigned_to && !@assignables.include?(@issue.assigned_to) @trackers = @project.trackers + else + #when multiple projects, we only keep the intersection of each set + @assignables = @projects.map(&:assignable_users).inject{|memo,a| memo & a} + @trackers = @projects.map(&:trackers).inject{|memo,t| memo & t} end @priorities = IssuePriority.all.reverse diff -r 09b1d4349da3 -r 371eac10df0b app/controllers/.svn/text-base/files_controller.rb.svn-base --- a/app/controllers/.svn/text-base/files_controller.rb.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/controllers/.svn/text-base/files_controller.rb.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -28,7 +28,7 @@ attachments = Attachment.attach_files(container, params[:attachments]) render_attachment_warning_if_needed(container) - if !attachments.empty? && Setting.notified_events.include?('file_added') + if !attachments.empty? && !attachments[:files].blank? && Setting.notified_events.include?('file_added') Mailer.deliver_attachments_added(attachments[:files]) end redirect_to project_files_path(@project) diff -r 09b1d4349da3 -r 371eac10df0b app/controllers/.svn/text-base/issue_moves_controller.rb.svn-base --- a/app/controllers/.svn/text-base/issue_moves_controller.rb.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/controllers/.svn/text-base/issue_moves_controller.rb.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -1,6 +1,6 @@ class IssueMovesController < ApplicationController default_search_scope :issues - before_filter :find_issues + before_filter :find_issues, :check_project_uniqueness before_filter :authorize def new @@ -18,6 +18,7 @@ @issues.each do |issue| issue.reload issue.init_journal(User.current) + issue.current_journal.notes = @notes if @notes.present? call_hook(:controller_issues_move_before_save, { :params => params, :issue => issue, :target_project => @target_project, :copy => !!@copy }) if r = issue.move_to_project(@target_project, new_tracker, {:copy => @copy, :attributes => extract_changed_attributes_for_move(params)}) moved_issues << r @@ -50,11 +51,13 @@ @target_project ||= @project @trackers = @target_project.trackers @available_statuses = Workflow.available_statuses(@project) + @notes = params[:notes] + @notes ||= '' end def extract_changed_attributes_for_move(params) changed_attributes = {} - [:assigned_to_id, :status_id, :start_date, :due_date].each do |valid_attribute| + [:assigned_to_id, :status_id, :start_date, :due_date, :priority_id].each do |valid_attribute| unless params[valid_attribute].blank? changed_attributes[valid_attribute] = (params[valid_attribute] == 'none' ? nil : params[valid_attribute]) end diff -r 09b1d4349da3 -r 371eac10df0b app/controllers/.svn/text-base/issues_controller.rb.svn-base --- a/app/controllers/.svn/text-base/issues_controller.rb.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/controllers/.svn/text-base/issues_controller.rb.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -21,12 +21,13 @@ before_filter :find_issue, :only => [:show, :edit, :update] before_filter :find_issues, :only => [:bulk_edit, :bulk_update, :move, :perform_move, :destroy] + before_filter :check_project_uniqueness, :only => [:move, :perform_move] before_filter :find_project, :only => [:new, :create] before_filter :authorize, :except => [:index] before_filter :find_optional_project, :only => [:index] before_filter :check_for_default_issue_status, :only => [:new, :create] before_filter :build_new_issue_from_params, :only => [:new, :create] - accept_key_auth :index, :show + accept_key_auth :index, :show, :create, :update, :destroy rescue_from Query::StatementInvalid, :with => :query_statement_invalid @@ -149,11 +150,7 @@ end end end - - # Attributes that can be updated on workflow transition (without :edit permission) - # TODO: make it configurable (at least per role) - UPDATABLE_ATTRS_ON_TRANSITION = %w(status_id assigned_to_id fixed_version_id done_ratio) unless const_defined?(:UPDATABLE_ATTRS_ON_TRANSITION) - + def edit update_issue_from_params @@ -193,8 +190,10 @@ # Bulk edit a set of issues def bulk_edit @issues.sort! - @available_statuses = Workflow.available_statuses(@project) - @custom_fields = @project.all_issue_custom_fields + @available_statuses = @projects.map{|p|Workflow.available_statuses(p)}.inject{|memo,w|memo & w} + @custom_fields = @projects.map{|p|p.all_issue_custom_fields}.inject{|memo,c|memo & c} + @assignables = @projects.map(&:assignable_users).inject{|memo,a| memo & a} + @trackers = @projects.map(&:trackers).inject{|memo,t| memo & t} end def bulk_update @@ -241,7 +240,7 @@ end @issues.each(&:destroy) respond_to do |format| - format.html { redirect_to :action => 'index', :project_id => @project } + format.html { redirect_back_or_default(:action => 'index', :project_id => @project) } format.xml { head :ok } format.json { head :ok } end @@ -270,20 +269,15 @@ @priorities = IssuePriority.all @edit_allowed = User.current.allowed_to?(:edit_issues, @project) @time_entry = TimeEntry.new + @time_entry.attributes = params[:time_entry] @notes = params[:notes] || (params[:issue].present? ? params[:issue][:notes] : nil) @issue.init_journal(User.current, @notes) - # User can change issue attributes only if he has :edit permission or if a workflow transition is allowed - if (@edit_allowed || !@allowed_statuses.empty?) && params[:issue] - attrs = params[:issue].dup - attrs.delete_if {|k,v| !UPDATABLE_ATTRS_ON_TRANSITION.include?(k) } unless @edit_allowed - attrs.delete(:status_id) unless @allowed_statuses.detect {|s| s.id.to_s == attrs[:status_id].to_s} - @issue.safe_attributes = attrs - end - + @issue.safe_attributes = params[:issue] end # TODO: Refactor, lots of extra code in here + # TODO: Changing tracker on an existing issue should not trigger this def build_new_issue_from_params if params[:id].blank? @issue = Issue.new @@ -300,12 +294,14 @@ render_error l(:error_no_tracker_in_project) return false end + @issue.start_date ||= Date.today if params[:issue].is_a?(Hash) @issue.safe_attributes = params[:issue] - @issue.watcher_user_ids = params[:issue]['watcher_user_ids'] if User.current.allowed_to?(:add_issue_watchers, @project) + if User.current.allowed_to?(:add_issue_watchers, @project) && @issue.new_record? + @issue.watcher_user_ids = params[:issue]['watcher_user_ids'] + end end @issue.author = User.current - @issue.start_date ||= Date.today @priorities = IssuePriority.all @allowed_statuses = @issue.new_statuses_allowed_to(User.current, true) end diff -r 09b1d4349da3 -r 371eac10df0b app/controllers/.svn/text-base/my_controller.rb.svn-base --- a/app/controllers/.svn/text-base/my_controller.rb.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/controllers/.svn/text-base/my_controller.rb.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -54,7 +54,7 @@ @pref = @user.pref if request.post? @user.attributes = params[:user] - @user.mail_notification = (params[:notification_option] == 'all') + @user.mail_notification = params[:notification_option] || 'only_my_events' @user.pref.attributes = params[:pref] @user.pref[:no_self_notified] = (params[:no_self_notified] == '1') if @user.save @@ -66,12 +66,8 @@ return end end - @notification_options = [[l(:label_user_mail_option_all), 'all'], - [l(:label_user_mail_option_none), 'none']] - # Only users that belong to more than 1 project can select projects for which they are notified - # Note that @user.membership.size would fail since AR ignores :include association option when doing a count - @notification_options.insert 1, [l(:label_user_mail_option_selected), 'selected'] if @user.memberships.length > 1 - @notification_option = @user.mail_notification? ? 'all' : (@user.notified_projects_ids.empty? ? 'none' : 'selected') + @notification_options = @user.valid_notification_options + @notification_option = @user.mail_notification #? ? 'all' : (@user.notified_projects_ids.empty? ? 'none' : 'selected') end # Manage user's password diff -r 09b1d4349da3 -r 371eac10df0b app/controllers/.svn/text-base/news_controller.rb.svn-base --- a/app/controllers/.svn/text-base/news_controller.rb.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/controllers/.svn/text-base/news_controller.rb.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -18,10 +18,10 @@ class NewsController < ApplicationController default_search_scope :news model_object News - before_filter :find_model_object, :except => [:new, :create, :index, :preview] - before_filter :find_project_from_association, :except => [:new, :create, :index, :preview] - before_filter :find_project, :only => [:new, :create, :preview] - before_filter :authorize, :except => [:index, :preview] + before_filter :find_model_object, :except => [:new, :create, :index] + before_filter :find_project_from_association, :except => [:new, :create, :index] + before_filter :find_project, :only => [:new, :create] + before_filter :authorize, :except => [:index] before_filter :find_optional_project, :only => :index accept_key_auth :index @@ -78,11 +78,6 @@ redirect_to :action => 'index', :project_id => @project end - def preview - @text = (params[:news] ? params[:news][:description] : nil) - render :partial => 'common/preview' - end - private def find_project @project = Project.find(params[:project_id]) diff -r 09b1d4349da3 -r 371eac10df0b app/controllers/.svn/text-base/previews_controller.rb.svn-base --- a/app/controllers/.svn/text-base/previews_controller.rb.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/controllers/.svn/text-base/previews_controller.rb.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -16,6 +16,11 @@ render :layout => false end + def news + @text = (params[:news] ? params[:news][:description] : nil) + render :partial => 'common/preview' + end + private def find_project diff -r 09b1d4349da3 -r 371eac10df0b app/controllers/.svn/text-base/projects_controller.rb.svn-base --- a/app/controllers/.svn/text-base/projects_controller.rb.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/controllers/.svn/text-base/projects_controller.rb.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -93,7 +93,7 @@ flash[:notice] = l(:notice_successful_create) redirect_to :controller => 'projects', :action => 'settings', :id => @project } - format.xml { head :created, :location => url_for(:controller => 'projects', :action => 'show', :id => @project.id) } + format.xml { render :action => 'show', :status => :created, :location => url_for(:controller => 'projects', :action => 'show', :id => @project.id) } end else respond_to do |format| @@ -125,13 +125,13 @@ if validate_parent_id && @project.copy(@source_project, :only => params[:only]) @project.set_allowed_parent!(params[:project]['parent_id']) if params[:project].has_key?('parent_id') flash[:notice] = l(:notice_successful_create) - redirect_to :controller => 'admin', :action => 'projects' + redirect_to :controller => 'projects', :action => 'settings' elsif !@project.new_record? # Project was created # But some objects were not copied due to validation failures # (eg. issues from disabled trackers) # TODO: inform about that - redirect_to :controller => 'admin', :action => 'projects' + redirect_to :controller => 'projects', :action => 'settings' end end end diff -r 09b1d4349da3 -r 371eac10df0b app/controllers/.svn/text-base/settings_controller.rb.svn-base --- a/app/controllers/.svn/text-base/settings_controller.rb.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/controllers/.svn/text-base/settings_controller.rb.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -26,7 +26,7 @@ end def edit - @notifiables = %w(issue_added issue_updated news_added document_added file_added message_posted wiki_content_added wiki_content_updated) + @notifiables = Redmine::Notifiable.all if request.post? && params[:settings] && params[:settings].is_a?(Hash) settings = (params[:settings] || {}).dup.symbolize_keys settings.each do |name, value| diff -r 09b1d4349da3 -r 371eac10df0b app/controllers/.svn/text-base/time_entry_reports_controller.rb.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/controllers/.svn/text-base/time_entry_reports_controller.rb.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -0,0 +1,209 @@ +class TimeEntryReportsController < ApplicationController + menu_item :issues + before_filter :find_optional_project + before_filter :load_available_criterias + + helper :sort + include SortHelper + helper :issues + helper :timelog + include TimelogHelper + helper :custom_fields + include CustomFieldsHelper + + def report + @criterias = params[:criterias] || [] + @criterias = @criterias.select{|criteria| @available_criterias.has_key? criteria} + @criterias.uniq! + @criterias = @criterias[0,3] + + @columns = (params[:columns] && %w(year month week day).include?(params[:columns])) ? params[:columns] : 'month' + + retrieve_date_range + + unless @criterias.empty? + sql_select = @criterias.collect{|criteria| @available_criterias[criteria][:sql] + " AS " + criteria}.join(', ') + sql_group_by = @criterias.collect{|criteria| @available_criterias[criteria][:sql]}.join(', ') + sql_condition = '' + + if @project.nil? + sql_condition = Project.allowed_to_condition(User.current, :view_time_entries) + elsif @issue.nil? + sql_condition = @project.project_condition(Setting.display_subprojects_issues?) + else + sql_condition = "#{Issue.table_name}.root_id = #{@issue.root_id} AND #{Issue.table_name}.lft >= #{@issue.lft} AND #{Issue.table_name}.rgt <= #{@issue.rgt}" + end + + sql = "SELECT #{sql_select}, tyear, tmonth, tweek, spent_on, SUM(hours) AS hours" + sql << " FROM #{TimeEntry.table_name}" + sql << time_report_joins + sql << " WHERE" + sql << " (%s) AND" % sql_condition + sql << " (spent_on BETWEEN '%s' AND '%s')" % [ActiveRecord::Base.connection.quoted_date(@from), ActiveRecord::Base.connection.quoted_date(@to)] + sql << " GROUP BY #{sql_group_by}, tyear, tmonth, tweek, spent_on" + + @hours = ActiveRecord::Base.connection.select_all(sql) + + @hours.each do |row| + case @columns + when 'year' + row['year'] = row['tyear'] + when 'month' + row['month'] = "#{row['tyear']}-#{row['tmonth']}" + when 'week' + row['week'] = "#{row['tyear']}-#{row['tweek']}" + when 'day' + row['day'] = "#{row['spent_on']}" + end + end + + @total_hours = @hours.inject(0) {|s,k| s = s + k['hours'].to_f} + + @periods = [] + # Date#at_beginning_of_ not supported in Rails 1.2.x + date_from = @from.to_time + # 100 columns max + while date_from <= @to.to_time && @periods.length < 100 + case @columns + when 'year' + @periods << "#{date_from.year}" + date_from = (date_from + 1.year).at_beginning_of_year + when 'month' + @periods << "#{date_from.year}-#{date_from.month}" + date_from = (date_from + 1.month).at_beginning_of_month + when 'week' + @periods << "#{date_from.year}-#{date_from.to_date.cweek}" + date_from = (date_from + 7.day).at_beginning_of_week + when 'day' + @periods << "#{date_from.to_date}" + date_from = date_from + 1.day + end + end + end + + respond_to do |format| + format.html { render :layout => !request.xhr? } + format.csv { send_data(report_to_csv(@criterias, @periods, @hours), :type => 'text/csv; header=present', :filename => 'timelog.csv') } + end + end + + private + + # TODO: duplicated in TimelogController + def find_optional_project + if !params[:issue_id].blank? + @issue = Issue.find(params[:issue_id]) + @project = @issue.project + elsif !params[:project_id].blank? + @project = Project.find(params[:project_id]) + end + deny_access unless User.current.allowed_to?(:view_time_entries, @project, :global => true) + end + + # Retrieves the date range based on predefined ranges or specific from/to param dates + # TODO: duplicated in TimelogController + def retrieve_date_range + @free_period = false + @from, @to = nil, nil + + if params[:period_type] == '1' || (params[:period_type].nil? && !params[:period].nil?) + case params[:period].to_s + when 'today' + @from = @to = Date.today + when 'yesterday' + @from = @to = Date.today - 1 + when 'current_week' + @from = Date.today - (Date.today.cwday - 1)%7 + @to = @from + 6 + when 'last_week' + @from = Date.today - 7 - (Date.today.cwday - 1)%7 + @to = @from + 6 + when '7_days' + @from = Date.today - 7 + @to = Date.today + when 'current_month' + @from = Date.civil(Date.today.year, Date.today.month, 1) + @to = (@from >> 1) - 1 + when 'last_month' + @from = Date.civil(Date.today.year, Date.today.month, 1) << 1 + @to = (@from >> 1) - 1 + when '30_days' + @from = Date.today - 30 + @to = Date.today + when 'current_year' + @from = Date.civil(Date.today.year, 1, 1) + @to = Date.civil(Date.today.year, 12, 31) + end + elsif params[:period_type] == '2' || (params[:period_type].nil? && (!params[:from].nil? || !params[:to].nil?)) + begin; @from = params[:from].to_s.to_date unless params[:from].blank?; rescue; end + begin; @to = params[:to].to_s.to_date unless params[:to].blank?; rescue; end + @free_period = true + else + # default + end + + @from, @to = @to, @from if @from && @to && @from > @to + @from ||= (TimeEntry.earilest_date_for_project(@project) || Date.today) + @to ||= (TimeEntry.latest_date_for_project(@project) || Date.today) + end + + def load_available_criterias + @available_criterias = { 'project' => {:sql => "#{TimeEntry.table_name}.project_id", + :klass => Project, + :label => :label_project}, + 'version' => {:sql => "#{Issue.table_name}.fixed_version_id", + :klass => Version, + :label => :label_version}, + 'category' => {:sql => "#{Issue.table_name}.category_id", + :klass => IssueCategory, + :label => :field_category}, + 'member' => {:sql => "#{TimeEntry.table_name}.user_id", + :klass => User, + :label => :label_member}, + 'tracker' => {:sql => "#{Issue.table_name}.tracker_id", + :klass => Tracker, + :label => :label_tracker}, + 'activity' => {:sql => "#{TimeEntry.table_name}.activity_id", + :klass => TimeEntryActivity, + :label => :label_activity}, + 'issue' => {:sql => "#{TimeEntry.table_name}.issue_id", + :klass => Issue, + :label => :label_issue} + } + + # Add list and boolean custom fields as available criterias + custom_fields = (@project.nil? ? IssueCustomField.for_all : @project.all_issue_custom_fields) + custom_fields.select {|cf| %w(list bool).include? cf.field_format }.each do |cf| + @available_criterias["cf_#{cf.id}"] = {:sql => "(SELECT c.value FROM #{CustomValue.table_name} c WHERE c.custom_field_id = #{cf.id} AND c.customized_type = 'Issue' AND c.customized_id = #{Issue.table_name}.id)", + :format => cf.field_format, + :label => cf.name} + end if @project + + # Add list and boolean time entry custom fields + TimeEntryCustomField.find(:all).select {|cf| %w(list bool).include? cf.field_format }.each do |cf| + @available_criterias["cf_#{cf.id}"] = {:sql => "(SELECT c.value FROM #{CustomValue.table_name} c WHERE c.custom_field_id = #{cf.id} AND c.customized_type = 'TimeEntry' AND c.customized_id = #{TimeEntry.table_name}.id)", + :format => cf.field_format, + :label => cf.name} + end + + # Add list and boolean time entry activity custom fields + TimeEntryActivityCustomField.find(:all).select {|cf| %w(list bool).include? cf.field_format }.each do |cf| + @available_criterias["cf_#{cf.id}"] = {:sql => "(SELECT c.value FROM #{CustomValue.table_name} c WHERE c.custom_field_id = #{cf.id} AND c.customized_type = 'Enumeration' AND c.customized_id = #{TimeEntry.table_name}.activity_id)", + :format => cf.field_format, + :label => cf.name} + end + + call_hook(:controller_timelog_available_criterias, { :available_criterias => @available_criterias, :project => @project }) + @available_criterias + end + + def time_report_joins + sql = '' + sql << " LEFT JOIN #{Issue.table_name} ON #{TimeEntry.table_name}.issue_id = #{Issue.table_name}.id" + sql << " LEFT JOIN #{Project.table_name} ON #{TimeEntry.table_name}.project_id = #{Project.table_name}.id" + # TODO: rename hook + call_hook(:controller_timelog_time_report_joins, {:sql => sql} ) + sql + end + +end diff -r 09b1d4349da3 -r 371eac10df0b app/controllers/.svn/text-base/timelog_controller.rb.svn-base --- a/app/controllers/.svn/text-base/timelog_controller.rb.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/controllers/.svn/text-base/timelog_controller.rb.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -17,12 +17,11 @@ class TimelogController < ApplicationController menu_item :issues - before_filter :find_project, :authorize, :only => [:edit, :destroy] - before_filter :find_optional_project, :only => [:report, :details] - before_filter :load_available_criterias, :only => [:report] + before_filter :find_project, :only => [:new, :create] + before_filter :find_time_entry, :only => [:edit, :update, :destroy] + before_filter :authorize, :except => [:index] + before_filter :find_optional_project, :only => [:index] - verify :method => :post, :only => :destroy, :redirect_to => { :action => :details } - helper :sort include SortHelper helper :issues @@ -30,83 +29,7 @@ helper :custom_fields include CustomFieldsHelper - def report - @criterias = params[:criterias] || [] - @criterias = @criterias.select{|criteria| @available_criterias.has_key? criteria} - @criterias.uniq! - @criterias = @criterias[0,3] - - @columns = (params[:columns] && %w(year month week day).include?(params[:columns])) ? params[:columns] : 'month' - - retrieve_date_range - - unless @criterias.empty? - sql_select = @criterias.collect{|criteria| @available_criterias[criteria][:sql] + " AS " + criteria}.join(', ') - sql_group_by = @criterias.collect{|criteria| @available_criterias[criteria][:sql]}.join(', ') - sql_condition = '' - - if @project.nil? - sql_condition = Project.allowed_to_condition(User.current, :view_time_entries) - elsif @issue.nil? - sql_condition = @project.project_condition(Setting.display_subprojects_issues?) - else - sql_condition = "#{Issue.table_name}.root_id = #{@issue.root_id} AND #{Issue.table_name}.lft >= #{@issue.lft} AND #{Issue.table_name}.rgt <= #{@issue.rgt}" - end - - sql = "SELECT #{sql_select}, tyear, tmonth, tweek, spent_on, SUM(hours) AS hours" - sql << " FROM #{TimeEntry.table_name}" - sql << time_report_joins - sql << " WHERE" - sql << " (%s) AND" % sql_condition - sql << " (spent_on BETWEEN '%s' AND '%s')" % [ActiveRecord::Base.connection.quoted_date(@from), ActiveRecord::Base.connection.quoted_date(@to)] - sql << " GROUP BY #{sql_group_by}, tyear, tmonth, tweek, spent_on" - - @hours = ActiveRecord::Base.connection.select_all(sql) - - @hours.each do |row| - case @columns - when 'year' - row['year'] = row['tyear'] - when 'month' - row['month'] = "#{row['tyear']}-#{row['tmonth']}" - when 'week' - row['week'] = "#{row['tyear']}-#{row['tweek']}" - when 'day' - row['day'] = "#{row['spent_on']}" - end - end - - @total_hours = @hours.inject(0) {|s,k| s = s + k['hours'].to_f} - - @periods = [] - # Date#at_beginning_of_ not supported in Rails 1.2.x - date_from = @from.to_time - # 100 columns max - while date_from <= @to.to_time && @periods.length < 100 - case @columns - when 'year' - @periods << "#{date_from.year}" - date_from = (date_from + 1.year).at_beginning_of_year - when 'month' - @periods << "#{date_from.year}-#{date_from.month}" - date_from = (date_from + 1.month).at_beginning_of_month - when 'week' - @periods << "#{date_from.year}-#{date_from.to_date.cweek}" - date_from = (date_from + 7.day).at_beginning_of_week - when 'day' - @periods << "#{date_from.to_date}" - date_from = date_from + 1.day - end - end - end - - respond_to do |format| - format.html { render :layout => !request.xhr? } - format.csv { send_data(report_to_csv(@criterias, @periods, @hours), :type => 'text/csv; header=present', :filename => 'timelog.csv') } - end - end - - def details + def index sort_init 'spent_on', 'desc' sort_update 'spent_on' => 'spent_on', 'user' => 'user_id', @@ -162,24 +85,52 @@ end end end - - def edit - (render_403; return) if @time_entry && !@time_entry.editable_by?(User.current) + + def new + @time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :user => User.current, :spent_on => User.current.today) + @time_entry.attributes = params[:time_entry] + + call_hook(:controller_timelog_edit_before_save, { :params => params, :time_entry => @time_entry }) + render :action => 'edit' + end + + verify :method => :post, :only => :create, :render => {:nothing => true, :status => :method_not_allowed } + def create @time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :user => User.current, :spent_on => User.current.today) @time_entry.attributes = params[:time_entry] call_hook(:controller_timelog_edit_before_save, { :params => params, :time_entry => @time_entry }) - if request.post? and @time_entry.save + if @time_entry.save flash[:notice] = l(:notice_successful_update) - redirect_back_or_default :action => 'details', :project_id => @time_entry.project - return + redirect_back_or_default :action => 'index', :project_id => @time_entry.project + else + render :action => 'edit' end end + def edit + @time_entry.attributes = params[:time_entry] + + call_hook(:controller_timelog_edit_before_save, { :params => params, :time_entry => @time_entry }) + end + + verify :method => :put, :only => :update, :render => {:nothing => true, :status => :method_not_allowed } + def update + @time_entry.attributes = params[:time_entry] + + call_hook(:controller_timelog_edit_before_save, { :params => params, :time_entry => @time_entry }) + + if @time_entry.save + flash[:notice] = l(:notice_successful_update) + redirect_back_or_default :action => 'index', :project_id => @time_entry.project + else + render :action => 'edit' + end + end + + verify :method => :delete, :only => :destroy, :render => {:nothing => true, :status => :method_not_allowed } def destroy - (render_404; return) unless @time_entry - (render_403; return) unless @time_entry.editable_by?(User.current) if @time_entry.destroy && @time_entry.destroyed? flash[:notice] = l(:notice_successful_delete) else @@ -187,15 +138,23 @@ end redirect_to :back rescue ::ActionController::RedirectBackError - redirect_to :action => 'details', :project_id => @time_entry.project + redirect_to :action => 'index', :project_id => @time_entry.project end private + def find_time_entry + @time_entry = TimeEntry.find(params[:id]) + unless @time_entry.editable_by?(User.current) + render_403 + return false + end + @project = @time_entry.project + rescue ActiveRecord::RecordNotFound + render_404 + end + def find_project - if params[:id] - @time_entry = TimeEntry.find(params[:id]) - @project = @time_entry.project - elsif params[:issue_id] + if params[:issue_id] @issue = Issue.find(params[:issue_id]) @project = @issue.project elsif params[:project_id] @@ -264,61 +223,4 @@ @to ||= (TimeEntry.latest_date_for_project(@project) || Date.today) end - def load_available_criterias - @available_criterias = { 'project' => {:sql => "#{TimeEntry.table_name}.project_id", - :klass => Project, - :label => :label_project}, - 'version' => {:sql => "#{Issue.table_name}.fixed_version_id", - :klass => Version, - :label => :label_version}, - 'category' => {:sql => "#{Issue.table_name}.category_id", - :klass => IssueCategory, - :label => :field_category}, - 'member' => {:sql => "#{TimeEntry.table_name}.user_id", - :klass => User, - :label => :label_member}, - 'tracker' => {:sql => "#{Issue.table_name}.tracker_id", - :klass => Tracker, - :label => :label_tracker}, - 'activity' => {:sql => "#{TimeEntry.table_name}.activity_id", - :klass => TimeEntryActivity, - :label => :label_activity}, - 'issue' => {:sql => "#{TimeEntry.table_name}.issue_id", - :klass => Issue, - :label => :label_issue} - } - - # Add list and boolean custom fields as available criterias - custom_fields = (@project.nil? ? IssueCustomField.for_all : @project.all_issue_custom_fields) - custom_fields.select {|cf| %w(list bool).include? cf.field_format }.each do |cf| - @available_criterias["cf_#{cf.id}"] = {:sql => "(SELECT c.value FROM #{CustomValue.table_name} c WHERE c.custom_field_id = #{cf.id} AND c.customized_type = 'Issue' AND c.customized_id = #{Issue.table_name}.id)", - :format => cf.field_format, - :label => cf.name} - end if @project - - # Add list and boolean time entry custom fields - TimeEntryCustomField.find(:all).select {|cf| %w(list bool).include? cf.field_format }.each do |cf| - @available_criterias["cf_#{cf.id}"] = {:sql => "(SELECT c.value FROM #{CustomValue.table_name} c WHERE c.custom_field_id = #{cf.id} AND c.customized_type = 'TimeEntry' AND c.customized_id = #{TimeEntry.table_name}.id)", - :format => cf.field_format, - :label => cf.name} - end - - # Add list and boolean time entry activity custom fields - TimeEntryActivityCustomField.find(:all).select {|cf| %w(list bool).include? cf.field_format }.each do |cf| - @available_criterias["cf_#{cf.id}"] = {:sql => "(SELECT c.value FROM #{CustomValue.table_name} c WHERE c.custom_field_id = #{cf.id} AND c.customized_type = 'Enumeration' AND c.customized_id = #{TimeEntry.table_name}.activity_id)", - :format => cf.field_format, - :label => cf.name} - end - - call_hook(:controller_timelog_available_criterias, { :available_criterias => @available_criterias, :project => @project }) - @available_criterias - end - - def time_report_joins - sql = '' - sql << " LEFT JOIN #{Issue.table_name} ON #{TimeEntry.table_name}.issue_id = #{Issue.table_name}.id" - sql << " LEFT JOIN #{Project.table_name} ON #{TimeEntry.table_name}.project_id = #{Project.table_name}.id" - call_hook(:controller_timelog_time_report_joins, {:sql => sql} ) - sql - end end diff -r 09b1d4349da3 -r 371eac10df0b app/controllers/.svn/text-base/users_controller.rb.svn-base --- a/app/controllers/.svn/text-base/users_controller.rb.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/controllers/.svn/text-base/users_controller.rb.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -51,7 +51,6 @@ def show @user = User.find(params[:id]) - @custom_values = @user.custom_values # show projects based on current user visibility @memberships = @user.memberships.all(:conditions => Project.visible_by(User.current)) @@ -71,53 +70,96 @@ render_404 end - def add - if request.get? - @user = User.new(:language => Setting.default_language) + def new + @notification_options = User::MAIL_NOTIFICATION_OPTIONS + @notification_option = Setting.default_notification_option + + @user = User.new(:language => Setting.default_language) + @auth_sources = AuthSource.find(:all) + end + + verify :method => :post, :only => :create, :render => {:nothing => true, :status => :method_not_allowed } + def create + @notification_options = User::MAIL_NOTIFICATION_OPTIONS + @notification_option = Setting.default_notification_option + + @user = User.new(params[:user]) + @user.admin = params[:user][:admin] || false + @user.login = params[:user][:login] + @user.password, @user.password_confirmation = params[:password], params[:password_confirmation] unless @user.auth_source_id + + # TODO: Similar to My#account + @user.mail_notification = params[:notification_option] || 'only_my_events' + @user.pref.attributes = params[:pref] + @user.pref[:no_self_notified] = (params[:no_self_notified] == '1') + + if @user.save + @user.pref.save + @user.notified_project_ids = (params[:notification_option] == 'selected' ? params[:notified_project_ids] : []) + + Mailer.deliver_account_information(@user, params[:password]) if params[:send_information] + flash[:notice] = l(:notice_successful_create) + redirect_to(params[:continue] ? {:controller => 'users', :action => 'new'} : + {:controller => 'users', :action => 'edit', :id => @user}) + return else - @user = User.new(params[:user]) - @user.admin = params[:user][:admin] || false - @user.login = params[:user][:login] - @user.password, @user.password_confirmation = params[:password], params[:password_confirmation] unless @user.auth_source_id - if @user.save - Mailer.deliver_account_information(@user, params[:password]) if params[:send_information] - flash[:notice] = l(:notice_successful_create) - redirect_to(params[:continue] ? {:controller => 'users', :action => 'add'} : - {:controller => 'users', :action => 'edit', :id => @user}) - return - end + @auth_sources = AuthSource.find(:all) + @notification_option = @user.mail_notification + + render :action => 'new' end - @auth_sources = AuthSource.find(:all) end def edit @user = User.find(params[:id]) - if request.post? - @user.admin = params[:user][:admin] if params[:user][:admin] - @user.login = params[:user][:login] if params[:user][:login] - if params[:password].present? && (@user.auth_source_id.nil? || params[:user][:auth_source_id].blank?) - @user.password, @user.password_confirmation = params[:password], params[:password_confirmation] - end - @user.group_ids = params[:user][:group_ids] if params[:user][:group_ids] - @user.attributes = params[:user] - # Was the account actived ? (do it before User#save clears the change) - was_activated = (@user.status_change == [User::STATUS_REGISTERED, User::STATUS_ACTIVE]) - if @user.save - if was_activated - Mailer.deliver_account_activated(@user) - elsif @user.active? && params[:send_information] && !params[:password].blank? && @user.auth_source_id.nil? - Mailer.deliver_account_information(@user, params[:password]) - end - flash[:notice] = l(:notice_successful_update) - redirect_to :back - end - end + @notification_options = @user.valid_notification_options + @notification_option = @user.mail_notification + @auth_sources = AuthSource.find(:all) @membership ||= Member.new + end + + verify :method => :put, :only => :update, :render => {:nothing => true, :status => :method_not_allowed } + def update + @user = User.find(params[:id]) + @notification_options = @user.valid_notification_options + @notification_option = @user.mail_notification + + @user.admin = params[:user][:admin] if params[:user][:admin] + @user.login = params[:user][:login] if params[:user][:login] + if params[:password].present? && (@user.auth_source_id.nil? || params[:user][:auth_source_id].blank?) + @user.password, @user.password_confirmation = params[:password], params[:password_confirmation] + end + @user.group_ids = params[:user][:group_ids] if params[:user][:group_ids] + @user.attributes = params[:user] + # Was the account actived ? (do it before User#save clears the change) + was_activated = (@user.status_change == [User::STATUS_REGISTERED, User::STATUS_ACTIVE]) + # TODO: Similar to My#account + @user.mail_notification = params[:notification_option] || 'only_my_events' + @user.pref.attributes = params[:pref] + @user.pref[:no_self_notified] = (params[:no_self_notified] == '1') + + if @user.save + @user.pref.save + @user.notified_project_ids = (params[:notification_option] == 'selected' ? params[:notified_project_ids] : []) + + if was_activated + Mailer.deliver_account_activated(@user) + elsif @user.active? && params[:send_information] && !params[:password].blank? && @user.auth_source_id.nil? + Mailer.deliver_account_information(@user, params[:password]) + end + flash[:notice] = l(:notice_successful_update) + redirect_to :back + else + @auth_sources = AuthSource.find(:all) + @membership ||= Member.new + + render :action => :edit + end rescue ::ActionController::RedirectBackError redirect_to :controller => 'users', :action => 'edit', :id => @user end - + def edit_membership @user = User.find(params[:id]) @membership = Member.edit_membership(params[:membership_id], params[:membership], @user) diff -r 09b1d4349da3 -r 371eac10df0b app/controllers/.svn/text-base/versions_controller.rb.svn-base --- a/app/controllers/.svn/text-base/versions_controller.rb.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/controllers/.svn/text-base/versions_controller.rb.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -109,6 +109,10 @@ if @version.update_attributes(attributes) flash[:notice] = l(:notice_successful_update) redirect_to :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project + else + respond_to do |format| + format.html { render :action => 'edit' } + end end end end diff -r 09b1d4349da3 -r 371eac10df0b app/controllers/.svn/text-base/wiki_controller.rb.svn-base --- a/app/controllers/.svn/text-base/wiki_controller.rb.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/controllers/.svn/text-base/wiki_controller.rb.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -17,20 +17,39 @@ require 'diff' +# The WikiController follows the Rails REST controller pattern but with +# a few differences +# +# * index - shows a list of WikiPages grouped by page or date +# * new - not used +# * create - not used +# * show - will also show the form for creating a new wiki page +# * edit - used to edit an existing or new page +# * update - used to save a wiki page update to the database, including new pages +# * destroy - normal +# +# Other member and collection methods are also used +# +# TODO: still being worked on class WikiController < ApplicationController default_search_scope :wiki_pages before_filter :find_wiki, :authorize before_filter :find_existing_page, :only => [:rename, :protect, :history, :diff, :annotate, :add_attachment, :destroy] - verify :method => :post, :only => [:destroy, :protect], :redirect_to => { :action => :index } + verify :method => :post, :only => [:protect], :redirect_to => { :action => :show } helper :attachments include AttachmentsHelper helper :watchers - + + # List of pages, sorted alphabetically and by parent (hierarchy) + def index + load_pages_grouped_by_date_without_content + end + # display a page (in editing mode if it doesn't exist) - def index - page_title = params[:page] + def show + page_title = params[:id] @page = @wiki.find_or_new_page(page_title) if @page.new_record? if User.current.allowed_to?(:edit_wiki_pages, @project) && editable? @@ -63,7 +82,7 @@ # edit an existing page or a new one def edit - @page = @wiki.find_or_new_page(params[:page]) + @page = @wiki.find_or_new_page(params[:id]) return render_403 unless editable? @page.content = WikiContent.new(:page => @page) if @page.new_record? @@ -71,34 +90,48 @@ @content.text = initial_page_content(@page) if @content.text.blank? # don't keep previous comment @content.comments = nil - if request.get? - # To prevent StaleObjectError exception when reverting to a previous version - @content.version = @page.content.version - else - if !@page.new_record? && @content.text == params[:content][:text] - attachments = Attachment.attach_files(@page, params[:attachments]) - render_attachment_warning_if_needed(@page) - # don't save if text wasn't changed - redirect_to :action => 'index', :id => @project, :page => @page.title - return - end - #@content.text = params[:content][:text] - #@content.comments = params[:content][:comments] - @content.attributes = params[:content] - @content.author = User.current - # if page is new @page.save will also save content, but not if page isn't a new record - if (@page.new_record? ? @page.save : @content.save) - attachments = Attachment.attach_files(@page, params[:attachments]) - render_attachment_warning_if_needed(@page) - call_hook(:controller_wiki_edit_after_save, { :params => params, :page => @page}) - redirect_to :action => 'index', :id => @project, :page => @page.title - end - end + + # To prevent StaleObjectError exception when reverting to a previous version + @content.version = @page.content.version rescue ActiveRecord::StaleObjectError # Optimistic locking exception flash[:error] = l(:notice_locking_conflict) end - + + verify :method => :put, :only => :update, :render => {:nothing => true, :status => :method_not_allowed } + # Creates a new page or updates an existing one + def update + @page = @wiki.find_or_new_page(params[:id]) + return render_403 unless editable? + @page.content = WikiContent.new(:page => @page) if @page.new_record? + + @content = @page.content_for_version(params[:version]) + @content.text = initial_page_content(@page) if @content.text.blank? + # don't keep previous comment + @content.comments = nil + + if !@page.new_record? && params[:content].present? && @content.text == params[:content][:text] + attachments = Attachment.attach_files(@page, params[:attachments]) + render_attachment_warning_if_needed(@page) + # don't save if text wasn't changed + redirect_to :action => 'show', :project_id => @project, :id => @page.title + return + end + @content.attributes = params[:content] + @content.author = User.current + # if page is new @page.save will also save content, but not if page isn't a new record + if (@page.new_record? ? @page.save : @content.save) + attachments = Attachment.attach_files(@page, params[:attachments]) + render_attachment_warning_if_needed(@page) + call_hook(:controller_wiki_edit_after_save, { :params => params, :page => @page}) + redirect_to :action => 'show', :project_id => @project, :id => @page.title + end + + rescue ActiveRecord::StaleObjectError + # Optimistic locking exception + flash[:error] = l(:notice_locking_conflict) + end + # rename a page def rename return render_403 unless editable? @@ -107,13 +140,13 @@ @original_title = @page.pretty_title if request.post? && @page.update_attributes(params[:wiki_page]) flash[:notice] = l(:notice_successful_update) - redirect_to :action => 'index', :id => @project, :page => @page.title + redirect_to :action => 'show', :project_id => @project, :id => @page.title end end def protect @page.update_attribute :protected, params[:protected] - redirect_to :action => 'index', :id => @project, :page => @page.title + redirect_to :action => 'show', :project_id => @project, :id => @page.title end # show page history @@ -139,7 +172,8 @@ @annotate = @page.annotate(params[:version]) render_404 unless @annotate end - + + verify :method => :delete, :only => [:destroy], :redirect_to => { :action => :show } # Removes a wiki page and its history # Children can be either set as root pages, removed or reassigned to another parent page def destroy @@ -166,41 +200,26 @@ end end @page.destroy - redirect_to :action => 'special', :id => @project, :page => 'Page_index' + redirect_to :action => 'index', :project_id => @project end - # display special pages - def special - page_title = params[:page].downcase - case page_title - # show pages index, sorted by title - when 'page_index', 'date_index' - # eager load information about last updates, without loading text - @pages = @wiki.pages.find :all, :select => "#{WikiPage.table_name}.*, #{WikiContent.table_name}.updated_on", - :joins => "LEFT JOIN #{WikiContent.table_name} ON #{WikiContent.table_name}.page_id = #{WikiPage.table_name}.id", - :order => 'title' - @pages_by_date = @pages.group_by {|p| p.updated_on.to_date} - @pages_by_parent_id = @pages.group_by(&:parent_id) - # export wiki to a single html file - when 'export' - if User.current.allowed_to?(:export_wiki_pages, @project) - @pages = @wiki.pages.find :all, :order => 'title' - export = render_to_string :action => 'export_multiple', :layout => false - send_data(export, :type => 'text/html', :filename => "wiki.html") - else - redirect_to :action => 'index', :id => @project, :page => nil - end - return + # Export wiki to a single html file + def export + if User.current.allowed_to?(:export_wiki_pages, @project) + @pages = @wiki.pages.find :all, :order => 'title' + export = render_to_string :action => 'export_multiple', :layout => false + send_data(export, :type => 'text/html', :filename => "wiki.html") else - # requested special page doesn't exist, redirect to default page - redirect_to :action => 'index', :id => @project, :page => nil - return + redirect_to :action => 'show', :project_id => @project, :id => nil end - render :action => "special_#{page_title}" + end + + def date_index + load_pages_grouped_by_date_without_content end def preview - page = @wiki.find_page(params[:page]) + page = @wiki.find_page(params[:id]) # page is nil when previewing a new page return render_403 unless page.nil? || editable?(page) if page @@ -215,13 +234,13 @@ return render_403 unless editable? attachments = Attachment.attach_files(@page, params[:attachments]) render_attachment_warning_if_needed(@page) - redirect_to :action => 'index', :page => @page.title + redirect_to :action => 'show', :id => @page.title, :project_id => @project end private def find_wiki - @project = Project.find(params[:id]) + @project = Project.find(params[:project_id]) @wiki = @project.wiki render_404 unless @wiki rescue ActiveRecord::RecordNotFound @@ -230,7 +249,7 @@ # Finds the requested page and returns a 404 error if it doesn't exist def find_existing_page - @page = @wiki.find_page(params[:page]) + @page = @wiki.find_page(params[:id]) render_404 if @page.nil? end @@ -245,4 +264,14 @@ extend helper unless self.instance_of?(helper) helper.instance_method(:initial_page_content).bind(self).call(page) end + + # eager load information about last updates, without loading text + def load_pages_grouped_by_date_without_content + @pages = @wiki.pages.find :all, :select => "#{WikiPage.table_name}.*, #{WikiContent.table_name}.updated_on", + :joins => "LEFT JOIN #{WikiContent.table_name} ON #{WikiContent.table_name}.page_id = #{WikiPage.table_name}.id", + :order => 'title' + @pages_by_date = @pages.group_by {|p| p.updated_on.to_date} + @pages_by_parent_id = @pages.group_by(&:parent_id) + end + end diff -r 09b1d4349da3 -r 371eac10df0b app/controllers/application_controller.rb --- a/app/controllers/application_controller.rb Thu Oct 21 11:19:14 2010 +0100 +++ b/app/controllers/application_controller.rb Wed Nov 24 12:20:08 2010 +0000 @@ -153,8 +153,16 @@ # Authorize the user for the requested action def authorize(ctrl = params[:controller], action = params[:action], global = false) - allowed = User.current.allowed_to?({:controller => ctrl, :action => action}, @project, :global => global) - allowed ? true : deny_access + allowed = User.current.allowed_to?({:controller => ctrl, :action => action}, @project || @projects, :global => global) + if allowed + true + else + if @project && @project.archived? + render_403 :message => :notice_not_authorized_archived_project + else + deny_access + end + end end # Authorize the user for the requested action outside a project @@ -213,16 +221,19 @@ def find_issues @issues = Issue.find_all_by_id(params[:id] || params[:ids]) raise ActiveRecord::RecordNotFound if @issues.empty? - projects = @issues.collect(&:project).compact.uniq - if projects.size == 1 - @project = projects.first - else + @projects = @issues.collect(&:project).compact.uniq + @project = @projects.first if @projects.size == 1 + rescue ActiveRecord::RecordNotFound + render_404 + end + + # Check if project is unique before bulk operations + def check_project_uniqueness + unless @project # TODO: let users bulk edit/move/destroy issues from different projects render_error 'Can not bulk edit/move/destroy issues from different projects' return false end - rescue ActiveRecord::RecordNotFound - render_404 end # make sure that the user is a member of the project (or admin) if project is private @@ -262,39 +273,33 @@ redirect_to default end - def render_403 + def render_403(options={}) @project = nil - respond_to do |format| - format.html { render :template => "common/403", :layout => use_layout, :status => 403 } - format.atom { head 403 } - format.xml { head 403 } - format.js { head 403 } - format.json { head 403 } - end + render_error({:message => :notice_not_authorized, :status => 403}.merge(options)) return false end - def render_404 - respond_to do |format| - format.html { render :template => "common/404", :layout => use_layout, :status => 404 } - format.atom { head 404 } - format.xml { head 404 } - format.js { head 404 } - format.json { head 404 } - end + def render_404(options={}) + render_error({:message => :notice_file_not_found, :status => 404}.merge(options)) return false end - def render_error(msg) + # Renders an error response + def render_error(arg) + arg = {:message => arg} unless arg.is_a?(Hash) + + @message = arg[:message] + @message = l(@message) if @message.is_a?(Symbol) + @status = arg[:status] || 500 + respond_to do |format| - format.html { - flash.now[:error] = msg - render :text => '', :layout => use_layout, :status => 500 + format.html { + render :template => 'common/error', :layout => use_layout, :status => @status } - format.atom { head 500 } - format.xml { head 500 } - format.js { head 500 } - format.json { head 500 } + format.atom { head @status } + format.xml { head @status } + format.js { head @status } + format.json { head @status } end end diff -r 09b1d4349da3 -r 371eac10df0b app/controllers/calendars_controller.rb --- a/app/controllers/calendars_controller.rb Thu Oct 21 11:19:14 2010 +0100 +++ b/app/controllers/calendars_controller.rb Wed Nov 24 12:20:08 2010 +0000 @@ -8,6 +8,8 @@ helper :projects helper :queries include QueriesHelper + helper :sort + include SortHelper def show if params[:year] and params[:year].to_i > 1900 diff -r 09b1d4349da3 -r 371eac10df0b app/controllers/context_menus_controller.rb --- a/app/controllers/context_menus_controller.rb Thu Oct 21 11:19:14 2010 +0100 +++ b/app/controllers/context_menus_controller.rb Wed Nov 24 12:20:08 2010 +0000 @@ -16,17 +16,21 @@ @projects = @issues.collect(&:project).compact.uniq @project = @projects.first if @projects.size == 1 - @can = {:edit => (@project && User.current.allowed_to?(:edit_issues, @project)), + @can = {:edit => User.current.allowed_to?(:edit_issues, @projects), :log_time => (@project && User.current.allowed_to?(:log_time, @project)), - :update => (@project && (User.current.allowed_to?(:edit_issues, @project) || (User.current.allowed_to?(:change_status, @project) && @allowed_statuses && !@allowed_statuses.empty?))), + :update => (User.current.allowed_to?(:edit_issues, @projects) || (User.current.allowed_to?(:change_status, @projects) && !@allowed_statuses.blank?)), :move => (@project && User.current.allowed_to?(:move_issues, @project)), :copy => (@issue && @project.trackers.include?(@issue.tracker) && User.current.allowed_to?(:add_issues, @project)), - :delete => (@project && User.current.allowed_to?(:delete_issues, @project)) + :delete => User.current.allowed_to?(:delete_issues, @projects) } if @project @assignables = @project.assignable_users @assignables << @issue.assigned_to if @issue && @issue.assigned_to && !@assignables.include?(@issue.assigned_to) @trackers = @project.trackers + else + #when multiple projects, we only keep the intersection of each set + @assignables = @projects.map(&:assignable_users).inject{|memo,a| memo & a} + @trackers = @projects.map(&:trackers).inject{|memo,t| memo & t} end @priorities = IssuePriority.all.reverse diff -r 09b1d4349da3 -r 371eac10df0b app/controllers/files_controller.rb --- a/app/controllers/files_controller.rb Thu Oct 21 11:19:14 2010 +0100 +++ b/app/controllers/files_controller.rb Wed Nov 24 12:20:08 2010 +0000 @@ -28,7 +28,7 @@ attachments = Attachment.attach_files(container, params[:attachments]) render_attachment_warning_if_needed(container) - if !attachments.empty? && Setting.notified_events.include?('file_added') + if !attachments.empty? && !attachments[:files].blank? && Setting.notified_events.include?('file_added') Mailer.deliver_attachments_added(attachments[:files]) end redirect_to project_files_path(@project) diff -r 09b1d4349da3 -r 371eac10df0b app/controllers/issue_moves_controller.rb --- a/app/controllers/issue_moves_controller.rb Thu Oct 21 11:19:14 2010 +0100 +++ b/app/controllers/issue_moves_controller.rb Wed Nov 24 12:20:08 2010 +0000 @@ -1,6 +1,6 @@ class IssueMovesController < ApplicationController default_search_scope :issues - before_filter :find_issues + before_filter :find_issues, :check_project_uniqueness before_filter :authorize def new @@ -18,6 +18,7 @@ @issues.each do |issue| issue.reload issue.init_journal(User.current) + issue.current_journal.notes = @notes if @notes.present? call_hook(:controller_issues_move_before_save, { :params => params, :issue => issue, :target_project => @target_project, :copy => !!@copy }) if r = issue.move_to_project(@target_project, new_tracker, {:copy => @copy, :attributes => extract_changed_attributes_for_move(params)}) moved_issues << r @@ -50,11 +51,13 @@ @target_project ||= @project @trackers = @target_project.trackers @available_statuses = Workflow.available_statuses(@project) + @notes = params[:notes] + @notes ||= '' end def extract_changed_attributes_for_move(params) changed_attributes = {} - [:assigned_to_id, :status_id, :start_date, :due_date].each do |valid_attribute| + [:assigned_to_id, :status_id, :start_date, :due_date, :priority_id].each do |valid_attribute| unless params[valid_attribute].blank? changed_attributes[valid_attribute] = (params[valid_attribute] == 'none' ? nil : params[valid_attribute]) end diff -r 09b1d4349da3 -r 371eac10df0b app/controllers/issues_controller.rb --- a/app/controllers/issues_controller.rb Thu Oct 21 11:19:14 2010 +0100 +++ b/app/controllers/issues_controller.rb Wed Nov 24 12:20:08 2010 +0000 @@ -21,12 +21,13 @@ before_filter :find_issue, :only => [:show, :edit, :update] before_filter :find_issues, :only => [:bulk_edit, :bulk_update, :move, :perform_move, :destroy] + before_filter :check_project_uniqueness, :only => [:move, :perform_move] before_filter :find_project, :only => [:new, :create] before_filter :authorize, :except => [:index] before_filter :find_optional_project, :only => [:index] before_filter :check_for_default_issue_status, :only => [:new, :create] before_filter :build_new_issue_from_params, :only => [:new, :create] - accept_key_auth :index, :show + accept_key_auth :index, :show, :create, :update, :destroy rescue_from Query::StatementInvalid, :with => :query_statement_invalid @@ -149,11 +150,7 @@ end end end - - # Attributes that can be updated on workflow transition (without :edit permission) - # TODO: make it configurable (at least per role) - UPDATABLE_ATTRS_ON_TRANSITION = %w(status_id assigned_to_id fixed_version_id done_ratio) unless const_defined?(:UPDATABLE_ATTRS_ON_TRANSITION) - + def edit update_issue_from_params @@ -193,8 +190,10 @@ # Bulk edit a set of issues def bulk_edit @issues.sort! - @available_statuses = Workflow.available_statuses(@project) - @custom_fields = @project.all_issue_custom_fields + @available_statuses = @projects.map{|p|Workflow.available_statuses(p)}.inject{|memo,w|memo & w} + @custom_fields = @projects.map{|p|p.all_issue_custom_fields}.inject{|memo,c|memo & c} + @assignables = @projects.map(&:assignable_users).inject{|memo,a| memo & a} + @trackers = @projects.map(&:trackers).inject{|memo,t| memo & t} end def bulk_update @@ -241,7 +240,7 @@ end @issues.each(&:destroy) respond_to do |format| - format.html { redirect_to :action => 'index', :project_id => @project } + format.html { redirect_back_or_default(:action => 'index', :project_id => @project) } format.xml { head :ok } format.json { head :ok } end @@ -270,20 +269,15 @@ @priorities = IssuePriority.all @edit_allowed = User.current.allowed_to?(:edit_issues, @project) @time_entry = TimeEntry.new + @time_entry.attributes = params[:time_entry] @notes = params[:notes] || (params[:issue].present? ? params[:issue][:notes] : nil) @issue.init_journal(User.current, @notes) - # User can change issue attributes only if he has :edit permission or if a workflow transition is allowed - if (@edit_allowed || !@allowed_statuses.empty?) && params[:issue] - attrs = params[:issue].dup - attrs.delete_if {|k,v| !UPDATABLE_ATTRS_ON_TRANSITION.include?(k) } unless @edit_allowed - attrs.delete(:status_id) unless @allowed_statuses.detect {|s| s.id.to_s == attrs[:status_id].to_s} - @issue.safe_attributes = attrs - end - + @issue.safe_attributes = params[:issue] end # TODO: Refactor, lots of extra code in here + # TODO: Changing tracker on an existing issue should not trigger this def build_new_issue_from_params if params[:id].blank? @issue = Issue.new @@ -300,12 +294,14 @@ render_error l(:error_no_tracker_in_project) return false end + @issue.start_date ||= Date.today if params[:issue].is_a?(Hash) @issue.safe_attributes = params[:issue] - @issue.watcher_user_ids = params[:issue]['watcher_user_ids'] if User.current.allowed_to?(:add_issue_watchers, @project) + if User.current.allowed_to?(:add_issue_watchers, @project) && @issue.new_record? + @issue.watcher_user_ids = params[:issue]['watcher_user_ids'] + end end @issue.author = User.current - @issue.start_date ||= Date.today @priorities = IssuePriority.all @allowed_statuses = @issue.new_statuses_allowed_to(User.current, true) end diff -r 09b1d4349da3 -r 371eac10df0b app/controllers/my_controller.rb --- a/app/controllers/my_controller.rb Thu Oct 21 11:19:14 2010 +0100 +++ b/app/controllers/my_controller.rb Wed Nov 24 12:20:08 2010 +0000 @@ -54,7 +54,7 @@ @pref = @user.pref if request.post? @user.attributes = params[:user] - @user.mail_notification = (params[:notification_option] == 'all') + @user.mail_notification = params[:notification_option] || 'only_my_events' @user.pref.attributes = params[:pref] @user.pref[:no_self_notified] = (params[:no_self_notified] == '1') if @user.save @@ -66,12 +66,8 @@ return end end - @notification_options = [[l(:label_user_mail_option_all), 'all'], - [l(:label_user_mail_option_none), 'none']] - # Only users that belong to more than 1 project can select projects for which they are notified - # Note that @user.membership.size would fail since AR ignores :include association option when doing a count - @notification_options.insert 1, [l(:label_user_mail_option_selected), 'selected'] if @user.memberships.length > 1 - @notification_option = @user.mail_notification? ? 'all' : (@user.notified_projects_ids.empty? ? 'none' : 'selected') + @notification_options = @user.valid_notification_options + @notification_option = @user.mail_notification #? ? 'all' : (@user.notified_projects_ids.empty? ? 'none' : 'selected') end # Manage user's password diff -r 09b1d4349da3 -r 371eac10df0b app/controllers/news_controller.rb --- a/app/controllers/news_controller.rb Thu Oct 21 11:19:14 2010 +0100 +++ b/app/controllers/news_controller.rb Wed Nov 24 12:20:08 2010 +0000 @@ -18,10 +18,10 @@ class NewsController < ApplicationController default_search_scope :news model_object News - before_filter :find_model_object, :except => [:new, :create, :index, :preview] - before_filter :find_project_from_association, :except => [:new, :create, :index, :preview] - before_filter :find_project, :only => [:new, :create, :preview] - before_filter :authorize, :except => [:index, :preview] + before_filter :find_model_object, :except => [:new, :create, :index] + before_filter :find_project_from_association, :except => [:new, :create, :index] + before_filter :find_project, :only => [:new, :create] + before_filter :authorize, :except => [:index] before_filter :find_optional_project, :only => :index accept_key_auth :index @@ -78,11 +78,6 @@ redirect_to :action => 'index', :project_id => @project end - def preview - @text = (params[:news] ? params[:news][:description] : nil) - render :partial => 'common/preview' - end - private def find_project @project = Project.find(params[:project_id]) diff -r 09b1d4349da3 -r 371eac10df0b app/controllers/previews_controller.rb --- a/app/controllers/previews_controller.rb Thu Oct 21 11:19:14 2010 +0100 +++ b/app/controllers/previews_controller.rb Wed Nov 24 12:20:08 2010 +0000 @@ -16,6 +16,11 @@ render :layout => false end + def news + @text = (params[:news] ? params[:news][:description] : nil) + render :partial => 'common/preview' + end + private def find_project diff -r 09b1d4349da3 -r 371eac10df0b app/controllers/projects_controller.rb --- a/app/controllers/projects_controller.rb Thu Oct 21 11:19:14 2010 +0100 +++ b/app/controllers/projects_controller.rb Wed Nov 24 12:20:08 2010 +0000 @@ -93,7 +93,7 @@ flash[:notice] = l(:notice_successful_create) redirect_to :controller => 'projects', :action => 'settings', :id => @project } - format.xml { head :created, :location => url_for(:controller => 'projects', :action => 'show', :id => @project.id) } + format.xml { render :action => 'show', :status => :created, :location => url_for(:controller => 'projects', :action => 'show', :id => @project.id) } end else respond_to do |format| @@ -125,13 +125,13 @@ if validate_parent_id && @project.copy(@source_project, :only => params[:only]) @project.set_allowed_parent!(params[:project]['parent_id']) if params[:project].has_key?('parent_id') flash[:notice] = l(:notice_successful_create) - redirect_to :controller => 'admin', :action => 'projects' + redirect_to :controller => 'projects', :action => 'settings' elsif !@project.new_record? # Project was created # But some objects were not copied due to validation failures # (eg. issues from disabled trackers) # TODO: inform about that - redirect_to :controller => 'admin', :action => 'projects' + redirect_to :controller => 'projects', :action => 'settings' end end end diff -r 09b1d4349da3 -r 371eac10df0b app/controllers/settings_controller.rb --- a/app/controllers/settings_controller.rb Thu Oct 21 11:19:14 2010 +0100 +++ b/app/controllers/settings_controller.rb Wed Nov 24 12:20:08 2010 +0000 @@ -26,7 +26,7 @@ end def edit - @notifiables = %w(issue_added issue_updated news_added document_added file_added message_posted wiki_content_added wiki_content_updated) + @notifiables = Redmine::Notifiable.all if request.post? && params[:settings] && params[:settings].is_a?(Hash) settings = (params[:settings] || {}).dup.symbolize_keys settings.each do |name, value| diff -r 09b1d4349da3 -r 371eac10df0b app/controllers/time_entry_reports_controller.rb --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/controllers/time_entry_reports_controller.rb Wed Nov 24 12:20:08 2010 +0000 @@ -0,0 +1,209 @@ +class TimeEntryReportsController < ApplicationController + menu_item :issues + before_filter :find_optional_project + before_filter :load_available_criterias + + helper :sort + include SortHelper + helper :issues + helper :timelog + include TimelogHelper + helper :custom_fields + include CustomFieldsHelper + + def report + @criterias = params[:criterias] || [] + @criterias = @criterias.select{|criteria| @available_criterias.has_key? criteria} + @criterias.uniq! + @criterias = @criterias[0,3] + + @columns = (params[:columns] && %w(year month week day).include?(params[:columns])) ? params[:columns] : 'month' + + retrieve_date_range + + unless @criterias.empty? + sql_select = @criterias.collect{|criteria| @available_criterias[criteria][:sql] + " AS " + criteria}.join(', ') + sql_group_by = @criterias.collect{|criteria| @available_criterias[criteria][:sql]}.join(', ') + sql_condition = '' + + if @project.nil? + sql_condition = Project.allowed_to_condition(User.current, :view_time_entries) + elsif @issue.nil? + sql_condition = @project.project_condition(Setting.display_subprojects_issues?) + else + sql_condition = "#{Issue.table_name}.root_id = #{@issue.root_id} AND #{Issue.table_name}.lft >= #{@issue.lft} AND #{Issue.table_name}.rgt <= #{@issue.rgt}" + end + + sql = "SELECT #{sql_select}, tyear, tmonth, tweek, spent_on, SUM(hours) AS hours" + sql << " FROM #{TimeEntry.table_name}" + sql << time_report_joins + sql << " WHERE" + sql << " (%s) AND" % sql_condition + sql << " (spent_on BETWEEN '%s' AND '%s')" % [ActiveRecord::Base.connection.quoted_date(@from), ActiveRecord::Base.connection.quoted_date(@to)] + sql << " GROUP BY #{sql_group_by}, tyear, tmonth, tweek, spent_on" + + @hours = ActiveRecord::Base.connection.select_all(sql) + + @hours.each do |row| + case @columns + when 'year' + row['year'] = row['tyear'] + when 'month' + row['month'] = "#{row['tyear']}-#{row['tmonth']}" + when 'week' + row['week'] = "#{row['tyear']}-#{row['tweek']}" + when 'day' + row['day'] = "#{row['spent_on']}" + end + end + + @total_hours = @hours.inject(0) {|s,k| s = s + k['hours'].to_f} + + @periods = [] + # Date#at_beginning_of_ not supported in Rails 1.2.x + date_from = @from.to_time + # 100 columns max + while date_from <= @to.to_time && @periods.length < 100 + case @columns + when 'year' + @periods << "#{date_from.year}" + date_from = (date_from + 1.year).at_beginning_of_year + when 'month' + @periods << "#{date_from.year}-#{date_from.month}" + date_from = (date_from + 1.month).at_beginning_of_month + when 'week' + @periods << "#{date_from.year}-#{date_from.to_date.cweek}" + date_from = (date_from + 7.day).at_beginning_of_week + when 'day' + @periods << "#{date_from.to_date}" + date_from = date_from + 1.day + end + end + end + + respond_to do |format| + format.html { render :layout => !request.xhr? } + format.csv { send_data(report_to_csv(@criterias, @periods, @hours), :type => 'text/csv; header=present', :filename => 'timelog.csv') } + end + end + + private + + # TODO: duplicated in TimelogController + def find_optional_project + if !params[:issue_id].blank? + @issue = Issue.find(params[:issue_id]) + @project = @issue.project + elsif !params[:project_id].blank? + @project = Project.find(params[:project_id]) + end + deny_access unless User.current.allowed_to?(:view_time_entries, @project, :global => true) + end + + # Retrieves the date range based on predefined ranges or specific from/to param dates + # TODO: duplicated in TimelogController + def retrieve_date_range + @free_period = false + @from, @to = nil, nil + + if params[:period_type] == '1' || (params[:period_type].nil? && !params[:period].nil?) + case params[:period].to_s + when 'today' + @from = @to = Date.today + when 'yesterday' + @from = @to = Date.today - 1 + when 'current_week' + @from = Date.today - (Date.today.cwday - 1)%7 + @to = @from + 6 + when 'last_week' + @from = Date.today - 7 - (Date.today.cwday - 1)%7 + @to = @from + 6 + when '7_days' + @from = Date.today - 7 + @to = Date.today + when 'current_month' + @from = Date.civil(Date.today.year, Date.today.month, 1) + @to = (@from >> 1) - 1 + when 'last_month' + @from = Date.civil(Date.today.year, Date.today.month, 1) << 1 + @to = (@from >> 1) - 1 + when '30_days' + @from = Date.today - 30 + @to = Date.today + when 'current_year' + @from = Date.civil(Date.today.year, 1, 1) + @to = Date.civil(Date.today.year, 12, 31) + end + elsif params[:period_type] == '2' || (params[:period_type].nil? && (!params[:from].nil? || !params[:to].nil?)) + begin; @from = params[:from].to_s.to_date unless params[:from].blank?; rescue; end + begin; @to = params[:to].to_s.to_date unless params[:to].blank?; rescue; end + @free_period = true + else + # default + end + + @from, @to = @to, @from if @from && @to && @from > @to + @from ||= (TimeEntry.earilest_date_for_project(@project) || Date.today) + @to ||= (TimeEntry.latest_date_for_project(@project) || Date.today) + end + + def load_available_criterias + @available_criterias = { 'project' => {:sql => "#{TimeEntry.table_name}.project_id", + :klass => Project, + :label => :label_project}, + 'version' => {:sql => "#{Issue.table_name}.fixed_version_id", + :klass => Version, + :label => :label_version}, + 'category' => {:sql => "#{Issue.table_name}.category_id", + :klass => IssueCategory, + :label => :field_category}, + 'member' => {:sql => "#{TimeEntry.table_name}.user_id", + :klass => User, + :label => :label_member}, + 'tracker' => {:sql => "#{Issue.table_name}.tracker_id", + :klass => Tracker, + :label => :label_tracker}, + 'activity' => {:sql => "#{TimeEntry.table_name}.activity_id", + :klass => TimeEntryActivity, + :label => :label_activity}, + 'issue' => {:sql => "#{TimeEntry.table_name}.issue_id", + :klass => Issue, + :label => :label_issue} + } + + # Add list and boolean custom fields as available criterias + custom_fields = (@project.nil? ? IssueCustomField.for_all : @project.all_issue_custom_fields) + custom_fields.select {|cf| %w(list bool).include? cf.field_format }.each do |cf| + @available_criterias["cf_#{cf.id}"] = {:sql => "(SELECT c.value FROM #{CustomValue.table_name} c WHERE c.custom_field_id = #{cf.id} AND c.customized_type = 'Issue' AND c.customized_id = #{Issue.table_name}.id)", + :format => cf.field_format, + :label => cf.name} + end if @project + + # Add list and boolean time entry custom fields + TimeEntryCustomField.find(:all).select {|cf| %w(list bool).include? cf.field_format }.each do |cf| + @available_criterias["cf_#{cf.id}"] = {:sql => "(SELECT c.value FROM #{CustomValue.table_name} c WHERE c.custom_field_id = #{cf.id} AND c.customized_type = 'TimeEntry' AND c.customized_id = #{TimeEntry.table_name}.id)", + :format => cf.field_format, + :label => cf.name} + end + + # Add list and boolean time entry activity custom fields + TimeEntryActivityCustomField.find(:all).select {|cf| %w(list bool).include? cf.field_format }.each do |cf| + @available_criterias["cf_#{cf.id}"] = {:sql => "(SELECT c.value FROM #{CustomValue.table_name} c WHERE c.custom_field_id = #{cf.id} AND c.customized_type = 'Enumeration' AND c.customized_id = #{TimeEntry.table_name}.activity_id)", + :format => cf.field_format, + :label => cf.name} + end + + call_hook(:controller_timelog_available_criterias, { :available_criterias => @available_criterias, :project => @project }) + @available_criterias + end + + def time_report_joins + sql = '' + sql << " LEFT JOIN #{Issue.table_name} ON #{TimeEntry.table_name}.issue_id = #{Issue.table_name}.id" + sql << " LEFT JOIN #{Project.table_name} ON #{TimeEntry.table_name}.project_id = #{Project.table_name}.id" + # TODO: rename hook + call_hook(:controller_timelog_time_report_joins, {:sql => sql} ) + sql + end + +end diff -r 09b1d4349da3 -r 371eac10df0b app/controllers/timelog_controller.rb --- a/app/controllers/timelog_controller.rb Thu Oct 21 11:19:14 2010 +0100 +++ b/app/controllers/timelog_controller.rb Wed Nov 24 12:20:08 2010 +0000 @@ -17,12 +17,11 @@ class TimelogController < ApplicationController menu_item :issues - before_filter :find_project, :authorize, :only => [:edit, :destroy] - before_filter :find_optional_project, :only => [:report, :details] - before_filter :load_available_criterias, :only => [:report] + before_filter :find_project, :only => [:new, :create] + before_filter :find_time_entry, :only => [:edit, :update, :destroy] + before_filter :authorize, :except => [:index] + before_filter :find_optional_project, :only => [:index] - verify :method => :post, :only => :destroy, :redirect_to => { :action => :details } - helper :sort include SortHelper helper :issues @@ -30,83 +29,7 @@ helper :custom_fields include CustomFieldsHelper - def report - @criterias = params[:criterias] || [] - @criterias = @criterias.select{|criteria| @available_criterias.has_key? criteria} - @criterias.uniq! - @criterias = @criterias[0,3] - - @columns = (params[:columns] && %w(year month week day).include?(params[:columns])) ? params[:columns] : 'month' - - retrieve_date_range - - unless @criterias.empty? - sql_select = @criterias.collect{|criteria| @available_criterias[criteria][:sql] + " AS " + criteria}.join(', ') - sql_group_by = @criterias.collect{|criteria| @available_criterias[criteria][:sql]}.join(', ') - sql_condition = '' - - if @project.nil? - sql_condition = Project.allowed_to_condition(User.current, :view_time_entries) - elsif @issue.nil? - sql_condition = @project.project_condition(Setting.display_subprojects_issues?) - else - sql_condition = "#{Issue.table_name}.root_id = #{@issue.root_id} AND #{Issue.table_name}.lft >= #{@issue.lft} AND #{Issue.table_name}.rgt <= #{@issue.rgt}" - end - - sql = "SELECT #{sql_select}, tyear, tmonth, tweek, spent_on, SUM(hours) AS hours" - sql << " FROM #{TimeEntry.table_name}" - sql << time_report_joins - sql << " WHERE" - sql << " (%s) AND" % sql_condition - sql << " (spent_on BETWEEN '%s' AND '%s')" % [ActiveRecord::Base.connection.quoted_date(@from), ActiveRecord::Base.connection.quoted_date(@to)] - sql << " GROUP BY #{sql_group_by}, tyear, tmonth, tweek, spent_on" - - @hours = ActiveRecord::Base.connection.select_all(sql) - - @hours.each do |row| - case @columns - when 'year' - row['year'] = row['tyear'] - when 'month' - row['month'] = "#{row['tyear']}-#{row['tmonth']}" - when 'week' - row['week'] = "#{row['tyear']}-#{row['tweek']}" - when 'day' - row['day'] = "#{row['spent_on']}" - end - end - - @total_hours = @hours.inject(0) {|s,k| s = s + k['hours'].to_f} - - @periods = [] - # Date#at_beginning_of_ not supported in Rails 1.2.x - date_from = @from.to_time - # 100 columns max - while date_from <= @to.to_time && @periods.length < 100 - case @columns - when 'year' - @periods << "#{date_from.year}" - date_from = (date_from + 1.year).at_beginning_of_year - when 'month' - @periods << "#{date_from.year}-#{date_from.month}" - date_from = (date_from + 1.month).at_beginning_of_month - when 'week' - @periods << "#{date_from.year}-#{date_from.to_date.cweek}" - date_from = (date_from + 7.day).at_beginning_of_week - when 'day' - @periods << "#{date_from.to_date}" - date_from = date_from + 1.day - end - end - end - - respond_to do |format| - format.html { render :layout => !request.xhr? } - format.csv { send_data(report_to_csv(@criterias, @periods, @hours), :type => 'text/csv; header=present', :filename => 'timelog.csv') } - end - end - - def details + def index sort_init 'spent_on', 'desc' sort_update 'spent_on' => 'spent_on', 'user' => 'user_id', @@ -162,24 +85,52 @@ end end end - - def edit - (render_403; return) if @time_entry && !@time_entry.editable_by?(User.current) + + def new + @time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :user => User.current, :spent_on => User.current.today) + @time_entry.attributes = params[:time_entry] + + call_hook(:controller_timelog_edit_before_save, { :params => params, :time_entry => @time_entry }) + render :action => 'edit' + end + + verify :method => :post, :only => :create, :render => {:nothing => true, :status => :method_not_allowed } + def create @time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :user => User.current, :spent_on => User.current.today) @time_entry.attributes = params[:time_entry] call_hook(:controller_timelog_edit_before_save, { :params => params, :time_entry => @time_entry }) - if request.post? and @time_entry.save + if @time_entry.save flash[:notice] = l(:notice_successful_update) - redirect_back_or_default :action => 'details', :project_id => @time_entry.project - return + redirect_back_or_default :action => 'index', :project_id => @time_entry.project + else + render :action => 'edit' end end + def edit + @time_entry.attributes = params[:time_entry] + + call_hook(:controller_timelog_edit_before_save, { :params => params, :time_entry => @time_entry }) + end + + verify :method => :put, :only => :update, :render => {:nothing => true, :status => :method_not_allowed } + def update + @time_entry.attributes = params[:time_entry] + + call_hook(:controller_timelog_edit_before_save, { :params => params, :time_entry => @time_entry }) + + if @time_entry.save + flash[:notice] = l(:notice_successful_update) + redirect_back_or_default :action => 'index', :project_id => @time_entry.project + else + render :action => 'edit' + end + end + + verify :method => :delete, :only => :destroy, :render => {:nothing => true, :status => :method_not_allowed } def destroy - (render_404; return) unless @time_entry - (render_403; return) unless @time_entry.editable_by?(User.current) if @time_entry.destroy && @time_entry.destroyed? flash[:notice] = l(:notice_successful_delete) else @@ -187,15 +138,23 @@ end redirect_to :back rescue ::ActionController::RedirectBackError - redirect_to :action => 'details', :project_id => @time_entry.project + redirect_to :action => 'index', :project_id => @time_entry.project end private + def find_time_entry + @time_entry = TimeEntry.find(params[:id]) + unless @time_entry.editable_by?(User.current) + render_403 + return false + end + @project = @time_entry.project + rescue ActiveRecord::RecordNotFound + render_404 + end + def find_project - if params[:id] - @time_entry = TimeEntry.find(params[:id]) - @project = @time_entry.project - elsif params[:issue_id] + if params[:issue_id] @issue = Issue.find(params[:issue_id]) @project = @issue.project elsif params[:project_id] @@ -264,61 +223,4 @@ @to ||= (TimeEntry.latest_date_for_project(@project) || Date.today) end - def load_available_criterias - @available_criterias = { 'project' => {:sql => "#{TimeEntry.table_name}.project_id", - :klass => Project, - :label => :label_project}, - 'version' => {:sql => "#{Issue.table_name}.fixed_version_id", - :klass => Version, - :label => :label_version}, - 'category' => {:sql => "#{Issue.table_name}.category_id", - :klass => IssueCategory, - :label => :field_category}, - 'member' => {:sql => "#{TimeEntry.table_name}.user_id", - :klass => User, - :label => :label_member}, - 'tracker' => {:sql => "#{Issue.table_name}.tracker_id", - :klass => Tracker, - :label => :label_tracker}, - 'activity' => {:sql => "#{TimeEntry.table_name}.activity_id", - :klass => TimeEntryActivity, - :label => :label_activity}, - 'issue' => {:sql => "#{TimeEntry.table_name}.issue_id", - :klass => Issue, - :label => :label_issue} - } - - # Add list and boolean custom fields as available criterias - custom_fields = (@project.nil? ? IssueCustomField.for_all : @project.all_issue_custom_fields) - custom_fields.select {|cf| %w(list bool).include? cf.field_format }.each do |cf| - @available_criterias["cf_#{cf.id}"] = {:sql => "(SELECT c.value FROM #{CustomValue.table_name} c WHERE c.custom_field_id = #{cf.id} AND c.customized_type = 'Issue' AND c.customized_id = #{Issue.table_name}.id)", - :format => cf.field_format, - :label => cf.name} - end if @project - - # Add list and boolean time entry custom fields - TimeEntryCustomField.find(:all).select {|cf| %w(list bool).include? cf.field_format }.each do |cf| - @available_criterias["cf_#{cf.id}"] = {:sql => "(SELECT c.value FROM #{CustomValue.table_name} c WHERE c.custom_field_id = #{cf.id} AND c.customized_type = 'TimeEntry' AND c.customized_id = #{TimeEntry.table_name}.id)", - :format => cf.field_format, - :label => cf.name} - end - - # Add list and boolean time entry activity custom fields - TimeEntryActivityCustomField.find(:all).select {|cf| %w(list bool).include? cf.field_format }.each do |cf| - @available_criterias["cf_#{cf.id}"] = {:sql => "(SELECT c.value FROM #{CustomValue.table_name} c WHERE c.custom_field_id = #{cf.id} AND c.customized_type = 'Enumeration' AND c.customized_id = #{TimeEntry.table_name}.activity_id)", - :format => cf.field_format, - :label => cf.name} - end - - call_hook(:controller_timelog_available_criterias, { :available_criterias => @available_criterias, :project => @project }) - @available_criterias - end - - def time_report_joins - sql = '' - sql << " LEFT JOIN #{Issue.table_name} ON #{TimeEntry.table_name}.issue_id = #{Issue.table_name}.id" - sql << " LEFT JOIN #{Project.table_name} ON #{TimeEntry.table_name}.project_id = #{Project.table_name}.id" - call_hook(:controller_timelog_time_report_joins, {:sql => sql} ) - sql - end end diff -r 09b1d4349da3 -r 371eac10df0b app/controllers/users_controller.rb --- a/app/controllers/users_controller.rb Thu Oct 21 11:19:14 2010 +0100 +++ b/app/controllers/users_controller.rb Wed Nov 24 12:20:08 2010 +0000 @@ -51,7 +51,6 @@ def show @user = User.find(params[:id]) - @custom_values = @user.custom_values # show projects based on current user visibility @memberships = @user.memberships.all(:conditions => Project.visible_by(User.current)) @@ -71,53 +70,96 @@ render_404 end - def add - if request.get? - @user = User.new(:language => Setting.default_language) + def new + @notification_options = User::MAIL_NOTIFICATION_OPTIONS + @notification_option = Setting.default_notification_option + + @user = User.new(:language => Setting.default_language) + @auth_sources = AuthSource.find(:all) + end + + verify :method => :post, :only => :create, :render => {:nothing => true, :status => :method_not_allowed } + def create + @notification_options = User::MAIL_NOTIFICATION_OPTIONS + @notification_option = Setting.default_notification_option + + @user = User.new(params[:user]) + @user.admin = params[:user][:admin] || false + @user.login = params[:user][:login] + @user.password, @user.password_confirmation = params[:password], params[:password_confirmation] unless @user.auth_source_id + + # TODO: Similar to My#account + @user.mail_notification = params[:notification_option] || 'only_my_events' + @user.pref.attributes = params[:pref] + @user.pref[:no_self_notified] = (params[:no_self_notified] == '1') + + if @user.save + @user.pref.save + @user.notified_project_ids = (params[:notification_option] == 'selected' ? params[:notified_project_ids] : []) + + Mailer.deliver_account_information(@user, params[:password]) if params[:send_information] + flash[:notice] = l(:notice_successful_create) + redirect_to(params[:continue] ? {:controller => 'users', :action => 'new'} : + {:controller => 'users', :action => 'edit', :id => @user}) + return else - @user = User.new(params[:user]) - @user.admin = params[:user][:admin] || false - @user.login = params[:user][:login] - @user.password, @user.password_confirmation = params[:password], params[:password_confirmation] unless @user.auth_source_id - if @user.save - Mailer.deliver_account_information(@user, params[:password]) if params[:send_information] - flash[:notice] = l(:notice_successful_create) - redirect_to(params[:continue] ? {:controller => 'users', :action => 'add'} : - {:controller => 'users', :action => 'edit', :id => @user}) - return - end + @auth_sources = AuthSource.find(:all) + @notification_option = @user.mail_notification + + render :action => 'new' end - @auth_sources = AuthSource.find(:all) end def edit @user = User.find(params[:id]) - if request.post? - @user.admin = params[:user][:admin] if params[:user][:admin] - @user.login = params[:user][:login] if params[:user][:login] - if params[:password].present? && (@user.auth_source_id.nil? || params[:user][:auth_source_id].blank?) - @user.password, @user.password_confirmation = params[:password], params[:password_confirmation] - end - @user.group_ids = params[:user][:group_ids] if params[:user][:group_ids] - @user.attributes = params[:user] - # Was the account actived ? (do it before User#save clears the change) - was_activated = (@user.status_change == [User::STATUS_REGISTERED, User::STATUS_ACTIVE]) - if @user.save - if was_activated - Mailer.deliver_account_activated(@user) - elsif @user.active? && params[:send_information] && !params[:password].blank? && @user.auth_source_id.nil? - Mailer.deliver_account_information(@user, params[:password]) - end - flash[:notice] = l(:notice_successful_update) - redirect_to :back - end - end + @notification_options = @user.valid_notification_options + @notification_option = @user.mail_notification + @auth_sources = AuthSource.find(:all) @membership ||= Member.new + end + + verify :method => :put, :only => :update, :render => {:nothing => true, :status => :method_not_allowed } + def update + @user = User.find(params[:id]) + @notification_options = @user.valid_notification_options + @notification_option = @user.mail_notification + + @user.admin = params[:user][:admin] if params[:user][:admin] + @user.login = params[:user][:login] if params[:user][:login] + if params[:password].present? && (@user.auth_source_id.nil? || params[:user][:auth_source_id].blank?) + @user.password, @user.password_confirmation = params[:password], params[:password_confirmation] + end + @user.group_ids = params[:user][:group_ids] if params[:user][:group_ids] + @user.attributes = params[:user] + # Was the account actived ? (do it before User#save clears the change) + was_activated = (@user.status_change == [User::STATUS_REGISTERED, User::STATUS_ACTIVE]) + # TODO: Similar to My#account + @user.mail_notification = params[:notification_option] || 'only_my_events' + @user.pref.attributes = params[:pref] + @user.pref[:no_self_notified] = (params[:no_self_notified] == '1') + + if @user.save + @user.pref.save + @user.notified_project_ids = (params[:notification_option] == 'selected' ? params[:notified_project_ids] : []) + + if was_activated + Mailer.deliver_account_activated(@user) + elsif @user.active? && params[:send_information] && !params[:password].blank? && @user.auth_source_id.nil? + Mailer.deliver_account_information(@user, params[:password]) + end + flash[:notice] = l(:notice_successful_update) + redirect_to :back + else + @auth_sources = AuthSource.find(:all) + @membership ||= Member.new + + render :action => :edit + end rescue ::ActionController::RedirectBackError redirect_to :controller => 'users', :action => 'edit', :id => @user end - + def edit_membership @user = User.find(params[:id]) @membership = Member.edit_membership(params[:membership_id], params[:membership], @user) diff -r 09b1d4349da3 -r 371eac10df0b app/controllers/versions_controller.rb --- a/app/controllers/versions_controller.rb Thu Oct 21 11:19:14 2010 +0100 +++ b/app/controllers/versions_controller.rb Wed Nov 24 12:20:08 2010 +0000 @@ -109,6 +109,10 @@ if @version.update_attributes(attributes) flash[:notice] = l(:notice_successful_update) redirect_to :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project + else + respond_to do |format| + format.html { render :action => 'edit' } + end end end end diff -r 09b1d4349da3 -r 371eac10df0b app/controllers/welcome_controller.rb --- a/app/controllers/welcome_controller.rb Thu Oct 21 11:19:14 2010 +0100 +++ b/app/controllers/welcome_controller.rb Wed Nov 24 12:20:08 2010 +0000 @@ -21,6 +21,14 @@ def index @news = News.latest User.current @projects = Project.latest User.current + + # tests if user is logged in to gfenerate the tips of the day list + if User.current.logged? + @tipsoftheday = Setting.tipoftheday_text + else + @tipsoftheday = '' + end + end def robots diff -r 09b1d4349da3 -r 371eac10df0b app/controllers/wiki_controller.rb --- a/app/controllers/wiki_controller.rb Thu Oct 21 11:19:14 2010 +0100 +++ b/app/controllers/wiki_controller.rb Wed Nov 24 12:20:08 2010 +0000 @@ -17,20 +17,39 @@ require 'diff' +# The WikiController follows the Rails REST controller pattern but with +# a few differences +# +# * index - shows a list of WikiPages grouped by page or date +# * new - not used +# * create - not used +# * show - will also show the form for creating a new wiki page +# * edit - used to edit an existing or new page +# * update - used to save a wiki page update to the database, including new pages +# * destroy - normal +# +# Other member and collection methods are also used +# +# TODO: still being worked on class WikiController < ApplicationController default_search_scope :wiki_pages before_filter :find_wiki, :authorize before_filter :find_existing_page, :only => [:rename, :protect, :history, :diff, :annotate, :add_attachment, :destroy] - verify :method => :post, :only => [:destroy, :protect], :redirect_to => { :action => :index } + verify :method => :post, :only => [:protect], :redirect_to => { :action => :show } helper :attachments include AttachmentsHelper helper :watchers - + + # List of pages, sorted alphabetically and by parent (hierarchy) + def index + load_pages_grouped_by_date_without_content + end + # display a page (in editing mode if it doesn't exist) - def index - page_title = params[:page] + def show + page_title = params[:id] @page = @wiki.find_or_new_page(page_title) if @page.new_record? if User.current.allowed_to?(:edit_wiki_pages, @project) && editable? @@ -63,7 +82,7 @@ # edit an existing page or a new one def edit - @page = @wiki.find_or_new_page(params[:page]) + @page = @wiki.find_or_new_page(params[:id]) return render_403 unless editable? @page.content = WikiContent.new(:page => @page) if @page.new_record? @@ -71,34 +90,48 @@ @content.text = initial_page_content(@page) if @content.text.blank? # don't keep previous comment @content.comments = nil - if request.get? - # To prevent StaleObjectError exception when reverting to a previous version - @content.version = @page.content.version - else - if !@page.new_record? && @content.text == params[:content][:text] - attachments = Attachment.attach_files(@page, params[:attachments]) - render_attachment_warning_if_needed(@page) - # don't save if text wasn't changed - redirect_to :action => 'index', :id => @project, :page => @page.title - return - end - #@content.text = params[:content][:text] - #@content.comments = params[:content][:comments] - @content.attributes = params[:content] - @content.author = User.current - # if page is new @page.save will also save content, but not if page isn't a new record - if (@page.new_record? ? @page.save : @content.save) - attachments = Attachment.attach_files(@page, params[:attachments]) - render_attachment_warning_if_needed(@page) - call_hook(:controller_wiki_edit_after_save, { :params => params, :page => @page}) - redirect_to :action => 'index', :id => @project, :page => @page.title - end - end + + # To prevent StaleObjectError exception when reverting to a previous version + @content.version = @page.content.version rescue ActiveRecord::StaleObjectError # Optimistic locking exception flash[:error] = l(:notice_locking_conflict) end - + + verify :method => :put, :only => :update, :render => {:nothing => true, :status => :method_not_allowed } + # Creates a new page or updates an existing one + def update + @page = @wiki.find_or_new_page(params[:id]) + return render_403 unless editable? + @page.content = WikiContent.new(:page => @page) if @page.new_record? + + @content = @page.content_for_version(params[:version]) + @content.text = initial_page_content(@page) if @content.text.blank? + # don't keep previous comment + @content.comments = nil + + if !@page.new_record? && params[:content].present? && @content.text == params[:content][:text] + attachments = Attachment.attach_files(@page, params[:attachments]) + render_attachment_warning_if_needed(@page) + # don't save if text wasn't changed + redirect_to :action => 'show', :project_id => @project, :id => @page.title + return + end + @content.attributes = params[:content] + @content.author = User.current + # if page is new @page.save will also save content, but not if page isn't a new record + if (@page.new_record? ? @page.save : @content.save) + attachments = Attachment.attach_files(@page, params[:attachments]) + render_attachment_warning_if_needed(@page) + call_hook(:controller_wiki_edit_after_save, { :params => params, :page => @page}) + redirect_to :action => 'show', :project_id => @project, :id => @page.title + end + + rescue ActiveRecord::StaleObjectError + # Optimistic locking exception + flash[:error] = l(:notice_locking_conflict) + end + # rename a page def rename return render_403 unless editable? @@ -107,13 +140,13 @@ @original_title = @page.pretty_title if request.post? && @page.update_attributes(params[:wiki_page]) flash[:notice] = l(:notice_successful_update) - redirect_to :action => 'index', :id => @project, :page => @page.title + redirect_to :action => 'show', :project_id => @project, :id => @page.title end end def protect @page.update_attribute :protected, params[:protected] - redirect_to :action => 'index', :id => @project, :page => @page.title + redirect_to :action => 'show', :project_id => @project, :id => @page.title end # show page history @@ -139,7 +172,8 @@ @annotate = @page.annotate(params[:version]) render_404 unless @annotate end - + + verify :method => :delete, :only => [:destroy], :redirect_to => { :action => :show } # Removes a wiki page and its history # Children can be either set as root pages, removed or reassigned to another parent page def destroy @@ -166,41 +200,26 @@ end end @page.destroy - redirect_to :action => 'special', :id => @project, :page => 'Page_index' + redirect_to :action => 'index', :project_id => @project end - # display special pages - def special - page_title = params[:page].downcase - case page_title - # show pages index, sorted by title - when 'page_index', 'date_index' - # eager load information about last updates, without loading text - @pages = @wiki.pages.find :all, :select => "#{WikiPage.table_name}.*, #{WikiContent.table_name}.updated_on", - :joins => "LEFT JOIN #{WikiContent.table_name} ON #{WikiContent.table_name}.page_id = #{WikiPage.table_name}.id", - :order => 'title' - @pages_by_date = @pages.group_by {|p| p.updated_on.to_date} - @pages_by_parent_id = @pages.group_by(&:parent_id) - # export wiki to a single html file - when 'export' - if User.current.allowed_to?(:export_wiki_pages, @project) - @pages = @wiki.pages.find :all, :order => 'title' - export = render_to_string :action => 'export_multiple', :layout => false - send_data(export, :type => 'text/html', :filename => "wiki.html") - else - redirect_to :action => 'index', :id => @project, :page => nil - end - return + # Export wiki to a single html file + def export + if User.current.allowed_to?(:export_wiki_pages, @project) + @pages = @wiki.pages.find :all, :order => 'title' + export = render_to_string :action => 'export_multiple', :layout => false + send_data(export, :type => 'text/html', :filename => "wiki.html") else - # requested special page doesn't exist, redirect to default page - redirect_to :action => 'index', :id => @project, :page => nil - return + redirect_to :action => 'show', :project_id => @project, :id => nil end - render :action => "special_#{page_title}" + end + + def date_index + load_pages_grouped_by_date_without_content end def preview - page = @wiki.find_page(params[:page]) + page = @wiki.find_page(params[:id]) # page is nil when previewing a new page return render_403 unless page.nil? || editable?(page) if page @@ -215,13 +234,13 @@ return render_403 unless editable? attachments = Attachment.attach_files(@page, params[:attachments]) render_attachment_warning_if_needed(@page) - redirect_to :action => 'index', :page => @page.title + redirect_to :action => 'show', :id => @page.title, :project_id => @project end private def find_wiki - @project = Project.find(params[:id]) + @project = Project.find(params[:project_id]) @wiki = @project.wiki render_404 unless @wiki rescue ActiveRecord::RecordNotFound @@ -230,7 +249,7 @@ # Finds the requested page and returns a 404 error if it doesn't exist def find_existing_page - @page = @wiki.find_page(params[:page]) + @page = @wiki.find_page(params[:id]) render_404 if @page.nil? end @@ -245,4 +264,14 @@ extend helper unless self.instance_of?(helper) helper.instance_method(:initial_page_content).bind(self).call(page) end + + # eager load information about last updates, without loading text + def load_pages_grouped_by_date_without_content + @pages = @wiki.pages.find :all, :select => "#{WikiPage.table_name}.*, #{WikiContent.table_name}.updated_on", + :joins => "LEFT JOIN #{WikiContent.table_name} ON #{WikiContent.table_name}.page_id = #{WikiPage.table_name}.id", + :order => 'title' + @pages_by_date = @pages.group_by {|p| p.updated_on.to_date} + @pages_by_parent_id = @pages.group_by(&:parent_id) + end + end diff -r 09b1d4349da3 -r 371eac10df0b app/helpers/.svn/all-wcprops --- a/app/helpers/.svn/all-wcprops Thu Oct 21 11:19:14 2010 +0100 +++ b/app/helpers/.svn/all-wcprops Wed Nov 24 12:20:08 2010 +0000 @@ -1,7 +1,7 @@ K 25 svn:wc:ra_dav:version-url V 36 -/svn/!svn/ver/4166/trunk/app/helpers +/svn/!svn/ver/4391/trunk/app/helpers END trackers_helper.rb K 25 @@ -79,7 +79,7 @@ K 25 svn:wc:ra_dav:version-url V 51 -/svn/!svn/ver/2794/trunk/app/helpers/wiki_helper.rb +/svn/!svn/ver/4375/trunk/app/helpers/wiki_helper.rb END enumerations_helper.rb K 25 @@ -91,19 +91,19 @@ K 25 svn:wc:ra_dav:version-url V 53 -/svn/!svn/ver/4166/trunk/app/helpers/issues_helper.rb +/svn/!svn/ver/4281/trunk/app/helpers/issues_helper.rb +END +gantt_helper.rb +K 25 +svn:wc:ra_dav:version-url +V 52 +/svn/!svn/ver/4283/trunk/app/helpers/gantt_helper.rb END queries_helper.rb K 25 svn:wc:ra_dav:version-url V 54 -/svn/!svn/ver/3924/trunk/app/helpers/queries_helper.rb -END -gantt_helper.rb -K 25 -svn:wc:ra_dav:version-url -V 52 -/svn/!svn/ver/4072/trunk/app/helpers/gantt_helper.rb +/svn/!svn/ver/4387/trunk/app/helpers/queries_helper.rb END mail_handler_helper.rb K 25 @@ -135,41 +135,47 @@ V 53 /svn/!svn/ver/333/trunk/app/helpers/welcome_helper.rb END +workflows_helper.rb +K 25 +svn:wc:ra_dav:version-url +V 56 +/svn/!svn/ver/1914/trunk/app/helpers/workflows_helper.rb +END journals_helper.rb K 25 svn:wc:ra_dav:version-url V 55 /svn/!svn/ver/4062/trunk/app/helpers/journals_helper.rb END -workflows_helper.rb -K 25 -svn:wc:ra_dav:version-url -V 56 -/svn/!svn/ver/1914/trunk/app/helpers/workflows_helper.rb -END reports_helper.rb K 25 svn:wc:ra_dav:version-url V 53 /svn/!svn/ver/629/trunk/app/helpers/reports_helper.rb END +custom_fields_helper.rb +K 25 +svn:wc:ra_dav:version-url +V 60 +/svn/!svn/ver/3675/trunk/app/helpers/custom_fields_helper.rb +END +settings_helper.rb +K 25 +svn:wc:ra_dav:version-url +V 55 +/svn/!svn/ver/4222/trunk/app/helpers/settings_helper.rb +END timelog_helper.rb K 25 svn:wc:ra_dav:version-url V 54 /svn/!svn/ver/3708/trunk/app/helpers/timelog_helper.rb END -settings_helper.rb +users_helper.rb K 25 svn:wc:ra_dav:version-url -V 55 -/svn/!svn/ver/3222/trunk/app/helpers/settings_helper.rb -END -custom_fields_helper.rb -K 25 -svn:wc:ra_dav:version-url -V 60 -/svn/!svn/ver/3675/trunk/app/helpers/custom_fields_helper.rb +V 52 +/svn/!svn/ver/4230/trunk/app/helpers/users_helper.rb END issue_moves_helper.rb K 25 @@ -177,17 +183,11 @@ V 58 /svn/!svn/ver/3936/trunk/app/helpers/issue_moves_helper.rb END -users_helper.rb -K 25 -svn:wc:ra_dav:version-url -V 52 -/svn/!svn/ver/3237/trunk/app/helpers/users_helper.rb -END application_helper.rb K 25 svn:wc:ra_dav:version-url V 58 -/svn/!svn/ver/4103/trunk/app/helpers/application_helper.rb +/svn/!svn/ver/4391/trunk/app/helpers/application_helper.rb END auth_sources_helper.rb K 25 @@ -199,7 +199,7 @@ K 25 svn:wc:ra_dav:version-url V 53 -/svn/!svn/ver/2822/trunk/app/helpers/search_helper.rb +/svn/!svn/ver/4353/trunk/app/helpers/search_helper.rb END messages_helper.rb K 25 diff -r 09b1d4349da3 -r 371eac10df0b app/helpers/.svn/entries --- a/app/helpers/.svn/entries Thu Oct 21 11:19:14 2010 +0100 +++ b/app/helpers/.svn/entries Wed Nov 24 12:20:08 2010 +0000 @@ -1,15 +1,15 @@ 10 dir -4173 +4411 http://redmine.rubyforge.org/svn/trunk/app/helpers http://redmine.rubyforge.org/svn -2010-09-20T18:50:14.663319Z -4166 -edavis10 +2010-11-11T13:39:14.764400Z +4391 +jplang @@ -440,10 +440,10 @@ -2010-09-23T14:37:44.431779Z -aee0a578b4bbfe95d2ede93a418824a6 -2009-06-28T11:55:49.957729Z -2794 +2010-11-19T13:04:46.900732Z +3e6762604b5e9a201b7a7bb2edc1f78f +2010-11-06T14:30:32.528294Z +4375 jplang has-props @@ -466,7 +466,7 @@ -2307 +2297 enumerations_helper.rb file @@ -508,11 +508,11 @@ -2010-09-24T12:48:25.903794Z -f45b693d0286eacc66fde223d7306002 -2010-09-20T18:50:14.663319Z -4166 -edavis10 +2010-11-19T13:04:46.900732Z +b5569bf5b4ba507a522f4e371505ae0c +2010-10-22T22:29:32.969473Z +4281 +jplang has-props @@ -534,7 +534,41 @@ -11249 +10075 + +gantt_helper.rb +file + + + + +2010-11-19T13:04:46.900732Z +dfac5226f31c3c232d7dcc9416172071 +2010-10-23T09:08:55.877887Z +4283 +jplang + + + + + + + + + + + + + + + + + + + + + +1988 queries_helper.rb file @@ -542,11 +576,11 @@ -2010-09-23T14:37:44.427784Z -403463e02373d20faf0ed8988cfae033 -2010-08-08T07:07:20.961363Z -3924 -jbbarth +2010-11-19T13:04:46.900732Z +6b997d023cc081b101be1949eb18f893 +2010-11-07T15:38:51.908839Z +4387 +jplang has-props @@ -568,41 +602,7 @@ -3785 - -gantt_helper.rb -file - - - - -2010-09-24T12:48:25.903794Z -bed98c36b12ec59c120d8da45f1511e0 -2010-09-10T03:09:02.311267Z -4072 -edavis10 - - - - - - - - - - - - - - - - - - - - - -1027 +3722 mail_handler_helper.rb file @@ -774,6 +774,40 @@ 817 +workflows_helper.rb +file + + + + +2010-09-23T14:37:44.431779Z +4f7bcbe149363ecb18080e3ce6c3f761 +2008-09-28T12:03:17.584169Z +1914 +jplang +has-props + + + + + + + + + + + + + + + + + + + + +824 + journals_helper.rb file @@ -808,40 +842,6 @@ 2266 -workflows_helper.rb -file - - - - -2010-09-23T14:37:44.431779Z -4f7bcbe149363ecb18080e3ce6c3f761 -2008-09-28T12:03:17.584169Z -1914 -jplang -has-props - - - - - - - - - - - - - - - - - - - - -824 - reports_helper.rb file @@ -876,6 +876,74 @@ 1265 +custom_fields_helper.rb +file + + + + +2010-09-23T14:37:44.423776Z +97753365c8eb76a948d7417d5db31079 +2010-04-16T15:34:05.970144Z +3675 +edavis10 +has-props + + + + + + + + + + + + + + + + + + + + +5322 + +settings_helper.rb +file + + + + +2010-11-19T13:04:46.900732Z +868d0dc19e332ae2c817321637a8e31f +2010-09-28T21:09:06.467392Z +4222 +edavis10 +has-props + + + + + + + + + + + + + + + + + + + + +3858 + timelog_helper.rb file @@ -910,108 +978,6 @@ 6636 -settings_helper.rb -file - - - - -2010-09-23T14:37:44.431779Z -72a1f70b395a94a9efae4d1046d5df2b -2009-12-23T17:56:39.685148Z -3222 -jplang -has-props - - - - - - - - - - - - - - - - - - - - -3350 - -custom_fields_helper.rb -file - - - - -2010-09-23T14:37:44.423776Z -97753365c8eb76a948d7417d5db31079 -2010-04-16T15:34:05.970144Z -3675 -edavis10 -has-props - - - - - - - - - - - - - - - - - - - - -5322 - -users_helper.rb -file - - - - -2010-09-23T14:37:44.431779Z -051113e44a01776675b1a38144a5fb8c -2009-12-24T16:14:15.868995Z -3237 -jplang -has-props - - - - - - - - - - - - - - - - - - - - -2645 - issue_moves_helper.rb file @@ -1046,17 +1012,51 @@ 28 +users_helper.rb +file + + + + +2010-11-19T13:04:46.900732Z +01b097606863e1e2938e7222d07fc2b7 +2010-09-30T18:22:46.611444Z +4230 +edavis10 +has-props + + + + + + + + + + + + + + + + + + + + +2644 + application_helper.rb file -2010-09-24T12:48:25.903794Z -fed6be9c1540dab50fb9e194984395b3 -2010-09-20T02:55:14.397976Z -4103 -edavis10 +2010-11-19T13:04:46.900732Z +a9ac6edf6104b93a669ba1b0705f4fc6 +2010-11-11T13:39:14.764400Z +4391 +jplang has-props @@ -1078,7 +1078,7 @@ -33297 +34105 auth_sources_helper.rb file @@ -1120,10 +1120,10 @@ -2010-09-23T14:37:44.431779Z -da0566fb2a355566f38723e4a11d1aab -2009-07-18T09:46:20.387008Z -2822 +2010-11-19T13:04:46.900732Z +dedb3c62af67e076703aa2f60c97fb2b +2010-11-01T12:55:15.292443Z +4353 jplang has-props @@ -1146,7 +1146,7 @@ -2639 +2668 messages_helper.rb file diff -r 09b1d4349da3 -r 371eac10df0b app/helpers/.svn/text-base/application_helper.rb.svn-base --- a/app/helpers/.svn/text-base/application_helper.rb.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/helpers/.svn/text-base/application_helper.rb.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -1,5 +1,5 @@ -# redMine - project management software -# Copyright (C) 2006-2007 Jean-Philippe Lang +# Redmine - project management software +# Copyright (C) 2006-2010 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -34,25 +34,11 @@ # Display a link if user is authorized # # @param [String] name Anchor text (passed to link_to) - # @param [Hash, String] options Hash params or url for the link target (passed to link_to). - # This will checked by authorize_for to see if the user is authorized + # @param [Hash] options Hash params. This will checked by authorize_for to see if the user is authorized # @param [optional, Hash] html_options Options passed to link_to # @param [optional, Hash] parameters_for_method_reference Extra parameters for link_to def link_to_if_authorized(name, options = {}, html_options = nil, *parameters_for_method_reference) - if options.is_a?(String) - begin - route = ActionController::Routing::Routes.recognize_path(options.gsub(/\?.*/,''), :method => options[:method] || :get) - link_controller = route[:controller] - link_action = route[:action] - rescue ActionController::RoutingError # Parse failed, not a route - link_controller, link_action = nil, nil - end - else - link_controller = options[:controller] || params[:controller] - link_action = options[:action] - end - - link_to(name, options, html_options, *parameters_for_method_reference) if authorize_for(link_controller, link_action) + link_to(name, options, html_options, *parameters_for_method_reference) if authorize_for(options[:controller] || params[:controller], options[:action]) end # Display a link to remote if user is authorized @@ -121,11 +107,6 @@ link_to(text, {:controller => 'repositories', :action => 'revision', :id => project, :rev => revision}, :title => l(:label_revision_id, revision)) end - - def link_to_project(project, options={}) - options[:class] ||= 'project' - link_to(h(project), {:controller => 'projects', :action => 'show', :id => project}, :class => options[:class]) - end # Generates a link to a project if active # Examples: @@ -196,7 +177,7 @@ content << "' + end + end + end # Same as Rails' simple_format helper without using paragraphs def simple_format_without_paragraph(text) diff -r 09b1d4349da3 -r 371eac10df0b app/helpers/.svn/text-base/gantt_helper.rb.svn-base --- a/app/helpers/.svn/text-base/gantt_helper.rb.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/helpers/.svn/text-base/gantt_helper.rb.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -16,6 +16,31 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. module GanttHelper + + def gantt_zoom_link(gantt, in_or_out) + case in_or_out + when :in + if gantt.zoom < 4 + link_to_remote(l(:text_zoom_in), + {:url => gantt.params.merge(:zoom => (gantt.zoom+1)), :method => :get, :update => 'content'}, + {:href => url_for(gantt.params.merge(:zoom => (gantt.zoom+1))), + :class => 'icon icon-zoom-in'}) + else + content_tag('span', l(:text_zoom_in), :class => 'icon icon-zoom-in') + end + + when :out + if gantt.zoom > 1 + link_to_remote(l(:text_zoom_out), + {:url => gantt.params.merge(:zoom => (gantt.zoom-1)), :method => :get, :update => 'content'}, + {:href => url_for(gantt.params.merge(:zoom => (gantt.zoom-1))), + :class => 'icon icon-zoom-out'}) + else + content_tag('span', l(:text_zoom_out), :class => 'icon icon-zoom-out') + end + end + end + def number_of_issues_on_versions(gantt) versions = gantt.events.collect {|event| (event.is_a? Version) ? event : nil}.compact diff -r 09b1d4349da3 -r 371eac10df0b app/helpers/.svn/text-base/issues_helper.rb.svn-base --- a/app/helpers/.svn/text-base/issues_helper.rb.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/helpers/.svn/text-base/issues_helper.rb.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -246,30 +246,4 @@ end export end - - def gantt_zoom_link(gantt, in_or_out) - img_attributes = {:style => 'height:1.4em; width:1.4em; margin-left: 3px;'} # em for accessibility - - case in_or_out - when :in - if gantt.zoom < 4 - link_to_remote(l(:text_zoom_in) + image_tag('zoom_in.png', img_attributes.merge(:alt => l(:text_zoom_in))), - {:url => gantt.params.merge(:zoom => (gantt.zoom+1)), :method => :get, :update => 'content'}, - {:href => url_for(gantt.params.merge(:zoom => (gantt.zoom+1)))}) - else - l(:text_zoom_in) + - image_tag('zoom_in_g.png', img_attributes.merge(:alt => l(:text_zoom_in))) - end - - when :out - if gantt.zoom > 1 - link_to_remote(l(:text_zoom_out) + image_tag('zoom_out.png', img_attributes.merge(:alt => l(:text_zoom_out))), - {:url => gantt.params.merge(:zoom => (gantt.zoom-1)), :method => :get, :update => 'content'}, - {:href => url_for(gantt.params.merge(:zoom => (gantt.zoom-1)))}) - else - l(:text_zoom_out) + - image_tag('zoom_out_g.png', img_attributes.merge(:alt => l(:text_zoom_out))) - end - end - end end diff -r 09b1d4349da3 -r 371eac10df0b app/helpers/.svn/text-base/queries_helper.rb.svn-base --- a/app/helpers/.svn/text-base/queries_helper.rb.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/helpers/.svn/text-base/queries_helper.rb.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -78,10 +78,9 @@ # Give it a name, required to be valid @query = Query.new(:name => "_") @query.project = @project - if params[:fields] and params[:fields].is_a? Array - params[:fields].each do |field| - @query.add_filter(field, params[:operators][field], params[:values][field]) - end + if params[:fields] + @query.filters = {} + @query.add_filters(params[:fields], params[:operators], params[:values]) else @query.available_filters.keys.each do |field| @query.add_short_filter(field, params[field]) if params[field] diff -r 09b1d4349da3 -r 371eac10df0b app/helpers/.svn/text-base/search_helper.rb.svn-base --- a/app/helpers/.svn/text-base/search_helper.rb.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/helpers/.svn/text-base/search_helper.rb.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -39,7 +39,7 @@ end def type_label(t) - l("label_#{t.singularize}_plural") + l("label_#{t.singularize}_plural", :default => t.to_s.humanize) end def project_select_tag diff -r 09b1d4349da3 -r 371eac10df0b app/helpers/.svn/text-base/settings_helper.rb.svn-base --- a/app/helpers/.svn/text-base/settings_helper.rb.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/helpers/.svn/text-base/settings_helper.rb.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -71,4 +71,14 @@ label = options.delete(:label) label != false ? content_tag("label", l(label || "setting_#{setting}")) : '' end + + # Renders a notification field for a Redmine::Notifiable option + def notification_field(notifiable) + return content_tag(:label, + check_box_tag('settings[notified_events][]', + notifiable.name, + Setting.notified_events.include?(notifiable.name)) + + l_or_humanize(notifiable.name, :prefix => 'label_'), + :class => notifiable.parent.present? ? "parent" : '') + end end diff -r 09b1d4349da3 -r 371eac10df0b app/helpers/.svn/text-base/users_helper.rb.svn-base --- a/app/helpers/.svn/text-base/users_helper.rb.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/helpers/.svn/text-base/users_helper.rb.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -34,14 +34,14 @@ end def change_status_link(user) - url = {:controller => 'users', :action => 'edit', :id => user, :page => params[:page], :status => params[:status], :tab => nil} + url = {:controller => 'users', :action => 'update', :id => user, :page => params[:page], :status => params[:status], :tab => nil} if user.locked? - link_to l(:button_unlock), url.merge(:user => {:status => User::STATUS_ACTIVE}), :method => :post, :class => 'icon icon-unlock' + link_to l(:button_unlock), url.merge(:user => {:status => User::STATUS_ACTIVE}), :method => :put, :class => 'icon icon-unlock' elsif user.registered? - link_to l(:button_activate), url.merge(:user => {:status => User::STATUS_ACTIVE}), :method => :post, :class => 'icon icon-unlock' + link_to l(:button_activate), url.merge(:user => {:status => User::STATUS_ACTIVE}), :method => :put, :class => 'icon icon-unlock' elsif user != User.current - link_to l(:button_lock), url.merge(:user => {:status => User::STATUS_LOCKED}), :method => :post, :class => 'icon icon-lock' + link_to l(:button_lock), url.merge(:user => {:status => User::STATUS_LOCKED}), :method => :put, :class => 'icon icon-lock' end end diff -r 09b1d4349da3 -r 371eac10df0b app/helpers/.svn/text-base/wiki_helper.rb.svn-base --- a/app/helpers/.svn/text-base/wiki_helper.rb.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/helpers/.svn/text-base/wiki_helper.rb.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -24,7 +24,7 @@ attrs << " selected='selected'" if selected == page indent = (level > 0) ? (' ' * level * 2 + '» ') : nil - s << "\n" + + s << "\n" + wiki_page_options_for_select(pages, selected, page, level + 1) end s diff -r 09b1d4349da3 -r 371eac10df0b app/helpers/application_helper.rb --- a/app/helpers/application_helper.rb Thu Oct 21 11:19:14 2010 +0100 +++ b/app/helpers/application_helper.rb Wed Nov 24 12:20:08 2010 +0000 @@ -1,5 +1,5 @@ -# redMine - project management software -# Copyright (C) 2006-2007 Jean-Philippe Lang +# Redmine - project management software +# Copyright (C) 2006-2010 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -34,25 +34,11 @@ # Display a link if user is authorized # # @param [String] name Anchor text (passed to link_to) - # @param [Hash, String] options Hash params or url for the link target (passed to link_to). - # This will checked by authorize_for to see if the user is authorized + # @param [Hash] options Hash params. This will checked by authorize_for to see if the user is authorized # @param [optional, Hash] html_options Options passed to link_to # @param [optional, Hash] parameters_for_method_reference Extra parameters for link_to def link_to_if_authorized(name, options = {}, html_options = nil, *parameters_for_method_reference) - if options.is_a?(String) - begin - route = ActionController::Routing::Routes.recognize_path(options.gsub(/\?.*/,''), :method => options[:method] || :get) - link_controller = route[:controller] - link_action = route[:action] - rescue ActionController::RoutingError # Parse failed, not a route - link_controller, link_action = nil, nil - end - else - link_controller = options[:controller] || params[:controller] - link_action = options[:action] - end - - link_to(name, options, html_options, *parameters_for_method_reference) if authorize_for(link_controller, link_action) + link_to(name, options, html_options, *parameters_for_method_reference) if authorize_for(options[:controller] || params[:controller], options[:action]) end # Display a link to remote if user is authorized @@ -123,11 +109,6 @@ link_to(text, {:controller => 'repositories', :action => 'revision', :id => project, :rev => rev}, :title => l(:label_revision_id, format_revision(revision))) end - - def link_to_project(project, options={}) - options[:class] ||= 'project' - link_to(h(project), {:controller => 'projects', :action => 'show', :id => project}, :class => options[:class]) - end # Generates a link to a project if active # Examples: @@ -198,7 +179,7 @@ content << "' + end + end + end # Same as Rails' simple_format helper without using paragraphs def simple_format_without_paragraph(text) diff -r 09b1d4349da3 -r 371eac10df0b app/helpers/gantt_helper.rb --- a/app/helpers/gantt_helper.rb Thu Oct 21 11:19:14 2010 +0100 +++ b/app/helpers/gantt_helper.rb Wed Nov 24 12:20:08 2010 +0000 @@ -16,6 +16,31 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. module GanttHelper + + def gantt_zoom_link(gantt, in_or_out) + case in_or_out + when :in + if gantt.zoom < 4 + link_to_remote(l(:text_zoom_in), + {:url => gantt.params.merge(:zoom => (gantt.zoom+1)), :method => :get, :update => 'content'}, + {:href => url_for(gantt.params.merge(:zoom => (gantt.zoom+1))), + :class => 'icon icon-zoom-in'}) + else + content_tag('span', l(:text_zoom_in), :class => 'icon icon-zoom-in') + end + + when :out + if gantt.zoom > 1 + link_to_remote(l(:text_zoom_out), + {:url => gantt.params.merge(:zoom => (gantt.zoom-1)), :method => :get, :update => 'content'}, + {:href => url_for(gantt.params.merge(:zoom => (gantt.zoom-1))), + :class => 'icon icon-zoom-out'}) + else + content_tag('span', l(:text_zoom_out), :class => 'icon icon-zoom-out') + end + end + end + def number_of_issues_on_versions(gantt) versions = gantt.events.collect {|event| (event.is_a? Version) ? event : nil}.compact diff -r 09b1d4349da3 -r 371eac10df0b app/helpers/issues_helper.rb --- a/app/helpers/issues_helper.rb Thu Oct 21 11:19:14 2010 +0100 +++ b/app/helpers/issues_helper.rb Wed Nov 24 12:20:08 2010 +0000 @@ -246,30 +246,4 @@ end export end - - def gantt_zoom_link(gantt, in_or_out) - img_attributes = {:style => 'height:1.4em; width:1.4em; margin-left: 3px;'} # em for accessibility - - case in_or_out - when :in - if gantt.zoom < 4 - link_to_remote(l(:text_zoom_in) + image_tag('zoom_in.png', img_attributes.merge(:alt => l(:text_zoom_in))), - {:url => gantt.params.merge(:zoom => (gantt.zoom+1)), :method => :get, :update => 'content'}, - {:href => url_for(gantt.params.merge(:zoom => (gantt.zoom+1)))}) - else - l(:text_zoom_in) + - image_tag('zoom_in_g.png', img_attributes.merge(:alt => l(:text_zoom_in))) - end - - when :out - if gantt.zoom > 1 - link_to_remote(l(:text_zoom_out) + image_tag('zoom_out.png', img_attributes.merge(:alt => l(:text_zoom_out))), - {:url => gantt.params.merge(:zoom => (gantt.zoom-1)), :method => :get, :update => 'content'}, - {:href => url_for(gantt.params.merge(:zoom => (gantt.zoom-1)))}) - else - l(:text_zoom_out) + - image_tag('zoom_out_g.png', img_attributes.merge(:alt => l(:text_zoom_out))) - end - end - end end diff -r 09b1d4349da3 -r 371eac10df0b app/helpers/queries_helper.rb --- a/app/helpers/queries_helper.rb Thu Oct 21 11:19:14 2010 +0100 +++ b/app/helpers/queries_helper.rb Wed Nov 24 12:20:08 2010 +0000 @@ -78,10 +78,9 @@ # Give it a name, required to be valid @query = Query.new(:name => "_") @query.project = @project - if params[:fields] and params[:fields].is_a? Array - params[:fields].each do |field| - @query.add_filter(field, params[:operators][field], params[:values][field]) - end + if params[:fields] + @query.filters = {} + @query.add_filters(params[:fields], params[:operators], params[:values]) else @query.available_filters.keys.each do |field| @query.add_short_filter(field, params[field]) if params[field] diff -r 09b1d4349da3 -r 371eac10df0b app/helpers/search_helper.rb --- a/app/helpers/search_helper.rb Thu Oct 21 11:19:14 2010 +0100 +++ b/app/helpers/search_helper.rb Wed Nov 24 12:20:08 2010 +0000 @@ -39,7 +39,7 @@ end def type_label(t) - l("label_#{t.singularize}_plural") + l("label_#{t.singularize}_plural", :default => t.to_s.humanize) end def project_select_tag diff -r 09b1d4349da3 -r 371eac10df0b app/helpers/settings_helper.rb --- a/app/helpers/settings_helper.rb Thu Oct 21 11:19:14 2010 +0100 +++ b/app/helpers/settings_helper.rb Wed Nov 24 12:20:08 2010 +0000 @@ -71,4 +71,14 @@ label = options.delete(:label) label != false ? content_tag("label", l(label || "setting_#{setting}")) : '' end + + # Renders a notification field for a Redmine::Notifiable option + def notification_field(notifiable) + return content_tag(:label, + check_box_tag('settings[notified_events][]', + notifiable.name, + Setting.notified_events.include?(notifiable.name)) + + l_or_humanize(notifiable.name, :prefix => 'label_'), + :class => notifiable.parent.present? ? "parent" : '') + end end diff -r 09b1d4349da3 -r 371eac10df0b app/helpers/users_helper.rb --- a/app/helpers/users_helper.rb Thu Oct 21 11:19:14 2010 +0100 +++ b/app/helpers/users_helper.rb Wed Nov 24 12:20:08 2010 +0000 @@ -34,14 +34,14 @@ end def change_status_link(user) - url = {:controller => 'users', :action => 'edit', :id => user, :page => params[:page], :status => params[:status], :tab => nil} + url = {:controller => 'users', :action => 'update', :id => user, :page => params[:page], :status => params[:status], :tab => nil} if user.locked? - link_to l(:button_unlock), url.merge(:user => {:status => User::STATUS_ACTIVE}), :method => :post, :class => 'icon icon-unlock' + link_to l(:button_unlock), url.merge(:user => {:status => User::STATUS_ACTIVE}), :method => :put, :class => 'icon icon-unlock' elsif user.registered? - link_to l(:button_activate), url.merge(:user => {:status => User::STATUS_ACTIVE}), :method => :post, :class => 'icon icon-unlock' + link_to l(:button_activate), url.merge(:user => {:status => User::STATUS_ACTIVE}), :method => :put, :class => 'icon icon-unlock' elsif user != User.current - link_to l(:button_lock), url.merge(:user => {:status => User::STATUS_LOCKED}), :method => :post, :class => 'icon icon-lock' + link_to l(:button_lock), url.merge(:user => {:status => User::STATUS_LOCKED}), :method => :put, :class => 'icon icon-lock' end end diff -r 09b1d4349da3 -r 371eac10df0b app/helpers/wiki_helper.rb --- a/app/helpers/wiki_helper.rb Thu Oct 21 11:19:14 2010 +0100 +++ b/app/helpers/wiki_helper.rb Wed Nov 24 12:20:08 2010 +0000 @@ -24,7 +24,7 @@ attrs << " selected='selected'" if selected == page indent = (level > 0) ? (' ' * level * 2 + '» ') : nil - s << "\n" + + s << "\n" + wiki_page_options_for_select(pages, selected, page, level + 1) end s diff -r 09b1d4349da3 -r 371eac10df0b app/models/.svn/all-wcprops --- a/app/models/.svn/all-wcprops Thu Oct 21 11:19:14 2010 +0100 +++ b/app/models/.svn/all-wcprops Wed Nov 24 12:20:08 2010 +0000 @@ -1,7 +1,7 @@ K 25 svn:wc:ra_dav:version-url V 35 -/svn/!svn/ver/4167/trunk/app/models +/svn/!svn/ver/4404/trunk/app/models END document.rb K 25 @@ -13,7 +13,7 @@ K 25 svn:wc:ra_dav:version-url V 51 -/svn/!svn/ver/3801/trunk/app/models/mail_handler.rb +/svn/!svn/ver/4404/trunk/app/models/mail_handler.rb END repository.rb K 25 @@ -25,7 +25,7 @@ K 25 svn:wc:ra_dav:version-url V 49 -/svn/!svn/ver/4087/trunk/app/models/time_entry.rb +/svn/!svn/ver/4277/trunk/app/models/time_entry.rb END token.rb K 25 @@ -37,7 +37,7 @@ K 25 svn:wc:ra_dav:version-url V 55 -/svn/!svn/ver/2637/trunk/app/models/journal_observer.rb +/svn/!svn/ver/4221/trunk/app/models/journal_observer.rb END auth_source_ldap.rb K 25 @@ -81,6 +81,12 @@ V 50 /svn/!svn/ver/3240/trunk/app/models/enumeration.rb END +issue.rb +K 25 +svn:wc:ra_dav:version-url +V 44 +/svn/!svn/ver/4394/trunk/app/models/issue.rb +END time_entry_activity_custom_field.rb K 25 svn:wc:ra_dav:version-url @@ -93,12 +99,6 @@ V 50 /svn/!svn/ver/3250/trunk/app/models/member_role.rb END -issue.rb -K 25 -svn:wc:ra_dav:version-url -V 44 -/svn/!svn/ver/4105/trunk/app/models/issue.rb -END issue_priority.rb K 25 svn:wc:ra_dav:version-url @@ -111,23 +111,17 @@ V 55 /svn/!svn/ver/3169/trunk/app/models/message_observer.rb END -wiki_content.rb -K 25 -svn:wc:ra_dav:version-url -V 51 -/svn/!svn/ver/3632/trunk/app/models/wiki_content.rb -END watcher.rb K 25 svn:wc:ra_dav:version-url V 46 /svn/!svn/ver/3167/trunk/app/models/watcher.rb END -wiki_page.rb +wiki_content.rb K 25 svn:wc:ra_dav:version-url -V 48 -/svn/!svn/ver/3632/trunk/app/models/wiki_page.rb +V 51 +/svn/!svn/ver/4296/trunk/app/models/wiki_content.rb END enabled_module.rb K 25 @@ -135,6 +129,12 @@ V 53 /svn/!svn/ver/2970/trunk/app/models/enabled_module.rb END +wiki_page.rb +K 25 +svn:wc:ra_dav:version-url +V 48 +/svn/!svn/ver/4296/trunk/app/models/wiki_page.rb +END comment.rb K 25 svn:wc:ra_dav:version-url @@ -151,7 +151,7 @@ K 25 svn:wc:ra_dav:version-url V 44 -/svn/!svn/ver/4079/trunk/app/models/query.rb +/svn/!svn/ver/4387/trunk/app/models/query.rb END member.rb K 25 @@ -169,7 +169,13 @@ K 25 svn:wc:ra_dav:version-url V 45 -/svn/!svn/ver/4167/trunk/app/models/mailer.rb +/svn/!svn/ver/4373/trunk/app/models/mailer.rb +END +journal.rb +K 25 +svn:wc:ra_dav:version-url +V 46 +/svn/!svn/ver/4062/trunk/app/models/journal.rb END workflow.rb K 25 @@ -177,12 +183,6 @@ V 47 /svn/!svn/ver/3709/trunk/app/models/workflow.rb END -journal.rb -K 25 -svn:wc:ra_dav:version-url -V 46 -/svn/!svn/ver/4062/trunk/app/models/journal.rb -END user_custom_field.rb K 25 svn:wc:ra_dav:version-url @@ -211,7 +211,7 @@ K 25 svn:wc:ra_dav:version-url V 43 -/svn/!svn/ver/4164/trunk/app/models/user.rb +/svn/!svn/ver/4234/trunk/app/models/user.rb END auth_source.rb K 25 @@ -343,13 +343,13 @@ K 25 svn:wc:ra_dav:version-url V 51 -/svn/!svn/ver/3077/trunk/app/models/custom_value.rb +/svn/!svn/ver/4382/trunk/app/models/custom_value.rb END project.rb K 25 svn:wc:ra_dav:version-url V 46 -/svn/!svn/ver/4087/trunk/app/models/project.rb +/svn/!svn/ver/4402/trunk/app/models/project.rb END document_category.rb K 25 diff -r 09b1d4349da3 -r 371eac10df0b app/models/.svn/entries --- a/app/models/.svn/entries Thu Oct 21 11:19:14 2010 +0100 +++ b/app/models/.svn/entries Wed Nov 24 12:20:08 2010 +0000 @@ -1,15 +1,15 @@ 10 dir -4173 +4411 http://redmine.rubyforge.org/svn/trunk/app/models http://redmine.rubyforge.org/svn -2010-09-20T23:17:51.402972Z -4167 -edavis10 +2010-11-14T13:48:01.671461Z +4404 +jplang @@ -69,11 +69,11 @@ -2010-09-23T14:37:44.475780Z -009baaf8ec2c62e225d84f9dc9898a23 -2010-06-20T16:22:36.211973Z -3801 -edavis10 +2010-11-19T13:04:46.952746Z +dd4785525bab24b6791967d66ffe6cb9 +2010-11-14T13:48:01.671461Z +4404 +jplang has-props @@ -95,7 +95,7 @@ -12708 +13455 repository.rb file @@ -137,33 +137,33 @@ -2010-09-24T12:48:25.923798Z -005148fc17a331f651990b8784f70a3e -2010-09-14T19:02:25.847894Z +2010-11-19T13:04:46.956816Z +aa2cc7da3c19ce52813f08949e6cefec +2010-10-22T20:40:11.668687Z +4277 +jplang +has-props + + + + + + + + + + + + + + + + + + + + 4087 -edavis10 -has-props - - - - - - - - - - - - - - - - - - - - -4089 token.rb file @@ -205,10 +205,10 @@ -2010-09-23T14:37:44.475780Z -0c8188293bba080a074aeb40a86e49f7 -2009-03-28T00:38:57.780983Z -2637 +2010-11-19T13:04:46.956816Z +7d895b3a013ce8f4e63dd4e7aab7eb20 +2010-09-28T20:20:00.843023Z +4221 edavis10 has-props @@ -231,7 +231,7 @@ -974 +1302 auth_source_ldap.rb file @@ -471,16 +471,16 @@ 3856 -issue.rb +time_entry_activity_custom_field.rb file -2010-09-24T12:48:25.923798Z -d169fc23e9a8686dba8f414b92e0fe26 -2010-09-20T02:55:26.436604Z -4105 +2010-09-23T14:37:44.487730Z +d5549b2847a255d4bdd7185a670988b5 +2009-10-21T22:35:03.091600Z +2952 edavis10 has-props @@ -503,7 +503,7 @@ -31528 +896 member_role.rb file @@ -539,17 +539,17 @@ 2011 -time_entry_activity_custom_field.rb +issue.rb file -2010-09-23T14:37:44.487730Z -d5549b2847a255d4bdd7185a670988b5 -2009-10-21T22:35:03.091600Z -2952 -edavis10 +2010-11-19T13:04:46.956816Z +35d32fdd4b71df26207f71005d93580e +2010-11-12T11:34:53.754717Z +4394 +jplang has-props @@ -571,7 +571,7 @@ -896 +32352 issue_priority.rb file @@ -641,6 +641,40 @@ 979 +wiki_content.rb +file + + + + +2010-11-19T13:04:46.956816Z +3cac6a9c934a472fcbdf99cd00e5bfbb +2010-10-27T16:27:06.240747Z +4296 +edavis10 +has-props + + + + + + + + + + + + + + + + + + + + +4480 + watcher.rb file @@ -675,17 +709,17 @@ 2093 -wiki_content.rb +wiki_page.rb file -2010-09-23T14:37:44.491776Z -2ce4521051866ff5f654f8a8bddfc824 -2010-04-11T12:56:18.077630Z -3632 -jplang +2010-11-19T13:04:46.956816Z +a45da72d99c7bc05ce93eb86205942e5 +2010-10-27T16:27:06.240747Z +4296 +edavis10 has-props @@ -707,7 +741,7 @@ -4458 +6720 enabled_module.rb file @@ -743,40 +777,6 @@ 1296 -wiki_page.rb -file - - - - -2010-09-23T14:37:44.491776Z -e6b3c8e83cb441a021358acf5d246d21 -2010-04-11T12:56:18.077630Z -3632 -jplang -has-props - - - - - - - - - - - - - - - - - - - - -6697 - comment.rb file @@ -851,11 +851,11 @@ -2010-09-24T12:48:25.923798Z -1cbc803eff5cf06cb8f3f133e5e7bed2 -2010-09-10T19:53:57.028875Z -4079 -edavis10 +2010-11-19T13:04:46.956816Z +ab1aeac4c9dd4c6ff846a281927b515a +2010-11-07T15:38:51.908839Z +4387 +jplang has-props @@ -877,7 +877,7 @@ -26050 +26148 member.rb file @@ -953,11 +953,11 @@ -2010-09-24T12:48:25.923798Z -46fe26aa1e0c5f59bdc2eab01a1c88e0 -2010-09-20T23:17:51.402972Z -4167 -edavis10 +2010-11-19T13:04:46.956816Z +1c4b2494e527ab830998b06f67b18f52 +2010-11-06T13:23:23.456511Z +4373 +jplang has-props @@ -979,7 +979,41 @@ -18478 +18490 + +workflow.rb +file + + + + +2010-09-23T14:37:44.491776Z +4561dfcb12b3fa066a9516c59a9eef94 +2010-04-30T12:19:51.238583Z +3709 +jplang +has-props + + + + + + + + + + + + + + + + + + + + +4028 journal.rb file @@ -1015,40 +1049,6 @@ 3214 -workflow.rb -file - - - - -2010-09-23T14:37:44.491776Z -4561dfcb12b3fa066a9516c59a9eef94 -2010-04-30T12:19:51.238583Z -3709 -jplang -has-props - - - - - - - - - - - - - - - - - - - - -4028 - user_custom_field.rb file @@ -1191,11 +1191,11 @@ -2010-09-24T12:48:25.927735Z -911221c7bce8ea7ed20a36477f72d457 -2010-09-20T16:38:00.519430Z -4164 -edavis10 +2010-11-19T13:04:46.956816Z +de9dd6a174b66d7a7f16a699f1f1698f +2010-10-06T05:08:38.847540Z +4234 +jbbarth has-props @@ -1217,7 +1217,7 @@ -13260 +15699 auth_source.rb file @@ -1939,10 +1939,10 @@ -2010-09-23T14:37:44.471831Z -2fdf508dceb97028a97b4fee91368d92 -2009-11-20T12:57:52.379950Z -3077 +2010-11-19T13:04:46.960863Z +6938d61d0f9e1fc190bb1d0e6c05546e +2010-11-07T14:15:01.891476Z +4382 jplang has-props @@ -1965,7 +1965,7 @@ -2374 +2424 project.rb file @@ -1973,11 +1973,11 @@ -2010-09-24T12:48:25.927735Z -fc2bd6fba523135882690f2d4b218277 -2010-09-14T19:02:25.847894Z -4087 -edavis10 +2010-11-19T13:04:46.960863Z +87ee5ad7f6983a739700f40cff0d65ae +2010-11-14T12:33:14.198318Z +4402 +jplang has-props @@ -1999,7 +1999,7 @@ -29540 +30070 document_category.rb file diff -r 09b1d4349da3 -r 371eac10df0b app/models/.svn/text-base/custom_value.rb.svn-base --- a/app/models/.svn/text-base/custom_value.rb.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/models/.svn/text-base/custom_value.rb.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -34,6 +34,10 @@ custom_field.editable? end + def visible? + custom_field.visible? + end + def required? custom_field.is_required? end diff -r 09b1d4349da3 -r 371eac10df0b app/models/.svn/text-base/issue.rb.svn-base --- a/app/models/.svn/text-base/issue.rb.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/models/.svn/text-base/issue.rb.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -86,8 +86,8 @@ } before_create :default_assign - before_save :reschedule_following_issues, :close_duplicates, :update_done_ratio_from_issue_status - after_save :update_nested_set_attributes, :update_parent_attributes, :create_journal + before_save :close_duplicates, :update_done_ratio_from_issue_status + after_save :reschedule_following_issues, :update_nested_set_attributes, :update_parent_attributes, :create_journal after_destroy :destroy_children after_destroy :update_parent_attributes @@ -233,14 +233,35 @@ lock_version ) unless const_defined?(:SAFE_ATTRIBUTES) + SAFE_ATTRIBUTES_ON_TRANSITION = %w( + status_id + assigned_to_id + fixed_version_id + done_ratio + ) unless const_defined?(:SAFE_ATTRIBUTES_ON_TRANSITION) + # Safely sets attributes # Should be called from controllers instead of #attributes= # attr_accessible is too rough because we still want things like # Issue.new(:project => foo) to work # TODO: move workflow/permission checks from controllers to here def safe_attributes=(attrs, user=User.current) - return if attrs.nil? - attrs = attrs.reject {|k,v| !SAFE_ATTRIBUTES.include?(k)} + return unless attrs.is_a?(Hash) + + # User can change issue attributes only if he has :edit permission or if a workflow transition is allowed + if new_record? || user.allowed_to?(:edit_issues, project) + attrs = attrs.reject {|k,v| !SAFE_ATTRIBUTES.include?(k)} + elsif new_statuses_allowed_to(user).any? + attrs = attrs.reject {|k,v| !SAFE_ATTRIBUTES_ON_TRANSITION.include?(k)} + else + return + end + + # Tracker must be set before since new_statuses_allowed_to depends on it. + if t = attrs.delete('tracker_id') + self.tracker_id = t + end + if attrs['status_id'] unless new_statuses_allowed_to(user).collect(&:id).include?(attrs['status_id'].to_i) attrs.delete('status_id') @@ -263,7 +284,7 @@ end def done_ratio - if Issue.use_status_for_done_ratio? && status && status.default_done_ratio? + if Issue.use_status_for_done_ratio? && status && status.default_done_ratio status.default_done_ratio else read_attribute(:done_ratio) @@ -326,7 +347,7 @@ # Set the done_ratio using the status if that setting is set. This will keep the done_ratios # even if the user turns off the setting later def update_done_ratio_from_issue_status - if Issue.use_status_for_done_ratio? && status && status.default_done_ratio? + if Issue.use_status_for_done_ratio? && status && status.default_done_ratio self.done_ratio = status.default_done_ratio end end @@ -390,7 +411,9 @@ # Users the issue can be assigned to def assignable_users - project.assignable_users + users = project.assignable_users + users << author if author + users.uniq.sort end # Versions that the issue can be assigned to @@ -415,9 +438,10 @@ # Returns the mail adresses of users that should be notified def recipients notified = project.notified_users - # Author and assignee are always notified unless they have been locked - notified << author if author && author.active? - notified << assigned_to if assigned_to && assigned_to.active? + # Author and assignee are always notified unless they have been + # locked or don't want to be notified + notified << author if author && author.active? && author.notify_about?(self) + notified << assigned_to if assigned_to && assigned_to.active? && assigned_to.notify_about?(self) notified.uniq! # Remove users that can not view the issue notified.reject! {|user| !visible?(user)} @@ -714,7 +738,7 @@ end # done ratio = weighted average ratio of leaves - unless Issue.use_status_for_done_ratio? && p.status && p.status.default_done_ratio? + unless Issue.use_status_for_done_ratio? && p.status && p.status.default_done_ratio leaves_count = p.leaves.count if leaves_count > 0 average = p.leaves.average(:estimated_hours).to_f diff -r 09b1d4349da3 -r 371eac10df0b app/models/.svn/text-base/journal_observer.rb.svn-base --- a/app/models/.svn/text-base/journal_observer.rb.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/models/.svn/text-base/journal_observer.rb.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -17,6 +17,11 @@ class JournalObserver < ActiveRecord::Observer def after_create(journal) - Mailer.deliver_issue_edit(journal) if Setting.notified_events.include?('issue_updated') + if Setting.notified_events.include?('issue_updated') || + (Setting.notified_events.include?('issue_note_added') && journal.notes.present?) || + (Setting.notified_events.include?('issue_status_updated') && journal.new_status.present?) || + (Setting.notified_events.include?('issue_priority_updated') && journal.new_value_for('priority_id').present?) + Mailer.deliver_issue_edit(journal) + end end end diff -r 09b1d4349da3 -r 371eac10df0b app/models/.svn/text-base/mail_handler.rb.svn-base --- a/app/models/.svn/text-base/mail_handler.rb.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/models/.svn/text-base/mail_handler.rb.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -17,6 +17,7 @@ class MailHandler < ActionMailer::Base include ActionView::Helpers::SanitizeHelper + include Redmine::I18n class UnauthorizedAction < StandardError; end class MissingInformation < StandardError; end @@ -116,36 +117,20 @@ # Creates a new issue def receive_issue project = target_project - tracker = (get_keyword(:tracker) && project.trackers.find_by_name(get_keyword(:tracker))) || project.trackers.find(:first) - category = (get_keyword(:category) && project.issue_categories.find_by_name(get_keyword(:category))) - priority = (get_keyword(:priority) && IssuePriority.find_by_name(get_keyword(:priority))) - status = (get_keyword(:status) && IssueStatus.find_by_name(get_keyword(:status))) - assigned_to = (get_keyword(:assigned_to, :override => true) && find_user_from_keyword(get_keyword(:assigned_to, :override => true))) - due_date = get_keyword(:due_date, :override => true) - start_date = get_keyword(:start_date, :override => true) - # check permission unless @@handler_options[:no_permission_check] raise UnauthorizedAction unless user.allowed_to?(:add_issues, project) end - issue = Issue.new(:author => user, :project => project, :tracker => tracker, :category => category, :priority => priority, :due_date => due_date, :start_date => start_date, :assigned_to => assigned_to) - # check workflow - if status && issue.new_statuses_allowed_to(user).include?(status) - issue.status = status - end - issue.subject = email.subject.chomp[0,255] + issue = Issue.new(:author => user, :project => project) + issue.safe_attributes = issue_attributes_from_keywords(issue) + issue.safe_attributes = {'custom_field_values' => custom_field_values_from_keywords(issue)} + issue.subject = email.subject.to_s.chomp[0,255] if issue.subject.blank? issue.subject = '(no subject)' end - # custom fields - issue.custom_field_values = issue.available_custom_fields.inject({}) do |h, c| - if value = get_keyword(c.name, :override => true) - h[c.id] = value - end - h - end issue.description = cleaned_up_text_body + # add To and Cc as watchers before saving so the watchers can reply to Redmine add_watchers(issue) issue.save! @@ -154,41 +139,19 @@ issue end - def target_project - # TODO: other ways to specify project: - # * parse the email To field - # * specific project (eg. Setting.mail_handler_target_project) - target = Project.find_by_identifier(get_keyword(:project)) - raise MissingInformation.new('Unable to determine target project') if target.nil? - target - end - # Adds a note to an existing issue def receive_issue_reply(issue_id) - status = (get_keyword(:status) && IssueStatus.find_by_name(get_keyword(:status))) - due_date = get_keyword(:due_date, :override => true) - start_date = get_keyword(:start_date, :override => true) - assigned_to = (get_keyword(:assigned_to, :override => true) && find_user_from_keyword(get_keyword(:assigned_to, :override => true))) - issue = Issue.find_by_id(issue_id) return unless issue # check permission unless @@handler_options[:no_permission_check] raise UnauthorizedAction unless user.allowed_to?(:add_issue_notes, issue.project) || user.allowed_to?(:edit_issues, issue.project) - raise UnauthorizedAction unless status.nil? || user.allowed_to?(:edit_issues, issue.project) end - - # add the note + journal = issue.init_journal(user, cleaned_up_text_body) + issue.safe_attributes = issue_attributes_from_keywords(issue) + issue.safe_attributes = {'custom_field_values' => custom_field_values_from_keywords(issue)} add_attachments(issue) - # check workflow - if status && issue.new_statuses_allowed_to(user).include?(status) - issue.status = status - end - issue.start_date = start_date if start_date - issue.due_date = due_date if due_date - issue.assigned_to = assigned_to if assigned_to - issue.save! logger.info "MailHandler: issue ##{issue.id} updated by #{user}" if logger && logger.info journal @@ -255,8 +218,8 @@ @keywords[attr] else @keywords[attr] = begin - if (options[:override] || @@handler_options[:allow_override].include?(attr.to_s)) && plain_text_body.gsub!(/^#{attr.to_s.humanize}[ \t]*:[ \t]*(.+)\s*$/i, '') - $1.strip + if (options[:override] || @@handler_options[:allow_override].include?(attr.to_s)) && (v = extract_keyword!(plain_text_body, attr, options[:format])) + v elsif !@@handler_options[:issue][attr].blank? @@handler_options[:issue][attr] end @@ -264,6 +227,59 @@ end end + # Destructively extracts the value for +attr+ in +text+ + # Returns nil if no matching keyword found + def extract_keyword!(text, attr, format=nil) + keys = [attr.to_s.humanize] + if attr.is_a?(Symbol) + keys << l("field_#{attr}", :default => '', :locale => user.language) if user + keys << l("field_#{attr}", :default => '', :locale => Setting.default_language) + end + keys.reject! {|k| k.blank?} + keys.collect! {|k| Regexp.escape(k)} + format ||= '.+' + text.gsub!(/^(#{keys.join('|')})[ \t]*:[ \t]*(#{format})\s*$/i, '') + $2 && $2.strip + end + + def target_project + # TODO: other ways to specify project: + # * parse the email To field + # * specific project (eg. Setting.mail_handler_target_project) + target = Project.find_by_identifier(get_keyword(:project)) + raise MissingInformation.new('Unable to determine target project') if target.nil? + target + end + + # Returns a Hash of issue attributes extracted from keywords in the email body + def issue_attributes_from_keywords(issue) + assigned_to = (k = get_keyword(:assigned_to, :override => true)) && find_user_from_keyword(k) + assigned_to = nil if assigned_to && !issue.assignable_users.include?(assigned_to) + + { + 'tracker_id' => ((k = get_keyword(:tracker)) && issue.project.trackers.find_by_name(k).try(:id)) || issue.project.trackers.find(:first).try(:id), + 'status_id' => (k = get_keyword(:status)) && IssueStatus.find_by_name(k).try(:id), + 'priority_id' => (k = get_keyword(:priority)) && IssuePriority.find_by_name(k).try(:id), + 'category_id' => (k = get_keyword(:category)) && issue.project.issue_categories.find_by_name(k).try(:id), + 'assigned_to_id' => assigned_to.try(:id), + 'fixed_version_id' => (k = get_keyword(:fixed_version, :override => true)) && issue.project.shared_versions.find_by_name(k).try(:id), + 'start_date' => get_keyword(:start_date, :override => true, :format => '\d{4}-\d{2}-\d{2}'), + 'due_date' => get_keyword(:due_date, :override => true, :format => '\d{4}-\d{2}-\d{2}'), + 'estimated_hours' => get_keyword(:estimated_hours, :override => true), + 'done_ratio' => get_keyword(:done_ratio, :override => true, :format => '(\d|10)?0') + }.delete_if {|k, v| v.blank? } + end + + # Returns a Hash of issue custom field values extracted from keywords in the email body + def custom_field_values_from_keywords(customized) + customized.custom_field_values.inject({}) do |h, v| + if value = get_keyword(v.custom_field.name, :override => true) + h[v.custom_field.id.to_s] = value + end + h + end + end + # Returns the text/plain part of the email # If not found (eg. HTML-only email), returns the body with tags removed def plain_text_body @@ -318,7 +334,7 @@ def cleanup_body(body) delimiters = Setting.mail_handler_body_delimiters.to_s.split(/[\r\n]+/).reject(&:blank?).map {|s| Regexp.escape(s)} unless delimiters.empty? - regex = Regexp.new("^(#{ delimiters.join('|') })\s*[\r\n].*", Regexp::MULTILINE) + regex = Regexp.new("^[> ]*(#{ delimiters.join('|') })\s*[\r\n].*", Regexp::MULTILINE) body = body.gsub(regex, '') end body.strip diff -r 09b1d4349da3 -r 371eac10df0b app/models/.svn/text-base/mailer.rb.svn-base --- a/app/models/.svn/text-base/mailer.rb.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/models/.svn/text-base/mailer.rb.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -178,9 +178,9 @@ message_id wiki_content recipients wiki_content.recipients cc(wiki_content.page.wiki.watcher_recipients - recipients) - subject "[#{wiki_content.project.name}] #{l(:mail_subject_wiki_content_added, :page => wiki_content.page.pretty_title)}" + subject "[#{wiki_content.project.name}] #{l(:mail_subject_wiki_content_added, :id => wiki_content.page.pretty_title)}" body :wiki_content => wiki_content, - :wiki_content_url => url_for(:controller => 'wiki', :action => 'index', :id => wiki_content.project, :page => wiki_content.page.title) + :wiki_content_url => url_for(:controller => 'wiki', :action => 'show', :project_id => wiki_content.project, :id => wiki_content.page.title) render_multipart('wiki_content_added', body) end @@ -195,10 +195,10 @@ message_id wiki_content recipients wiki_content.recipients cc(wiki_content.page.wiki.watcher_recipients + wiki_content.page.watcher_recipients - recipients) - subject "[#{wiki_content.project.name}] #{l(:mail_subject_wiki_content_updated, :page => wiki_content.page.pretty_title)}" + subject "[#{wiki_content.project.name}] #{l(:mail_subject_wiki_content_updated, :id => wiki_content.page.pretty_title)}" body :wiki_content => wiki_content, - :wiki_content_url => url_for(:controller => 'wiki', :action => 'index', :id => wiki_content.project, :page => wiki_content.page.title), - :wiki_diff_url => url_for(:controller => 'wiki', :action => 'diff', :id => wiki_content.project, :page => wiki_content.page.title, :version => wiki_content.version) + :wiki_content_url => url_for(:controller => 'wiki', :action => 'show', :project_id => wiki_content.project, :id => wiki_content.page.title), + :wiki_diff_url => url_for(:controller => 'wiki', :action => 'diff', :project_id => wiki_content.project, :id => wiki_content.page.title, :version => wiki_content.version) render_multipart('wiki_content_updated', body) end diff -r 09b1d4349da3 -r 371eac10df0b app/models/.svn/text-base/project.rb.svn-base --- a/app/models/.svn/text-base/project.rb.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/models/.svn/text-base/project.rb.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -20,6 +20,9 @@ STATUS_ACTIVE = 1 STATUS_ARCHIVED = 9 + # Maximum length for project identifiers + IDENTIFIER_MAX_LENGTH = 100 + # Specific overidden Activities has_many :time_entry_activities has_many :members, :include => [:user, :roles], :conditions => "#{User.table_name}.type='User' AND #{User.table_name}.status=#{User::STATUS_ACTIVE}" @@ -64,11 +67,11 @@ attr_protected :status, :enabled_module_names validates_presence_of :name, :identifier - validates_uniqueness_of :name, :identifier + validates_uniqueness_of :identifier validates_associated :repository, :wiki - validates_length_of :name, :maximum => 30 + validates_length_of :name, :maximum => 255 validates_length_of :homepage, :maximum => 255 - validates_length_of :identifier, :in => 1..20 + validates_length_of :identifier, :in => 1..IDENTIFIER_MAX_LENGTH # donwcase letters, digits, dashes but not digits only validates_format_of :identifier, :with => /^(?!\d+$)[a-z0-9\-]*$/, :if => Proc.new { |p| p.identifier_changed? } # reserved words @@ -220,6 +223,10 @@ self.status == STATUS_ACTIVE end + def archived? + self.status == STATUS_ARCHIVED + end + # Archives the project and its descendants def archive # Check that there is no issue of a non descendant project that is assigned @@ -382,12 +389,13 @@ # Returns the mail adresses of users that should be always notified on project events def recipients - members.select {|m| m.mail_notification? || m.user.mail_notification?}.collect {|m| m.user.mail} + notified_users.collect {|user| user.mail} end # Returns the users that should be notified on project events def notified_users - members.select {|m| m.mail_notification? || m.user.mail_notification?}.collect {|m| m.user} + # TODO: User part should be extracted to User#notify_about? + members.select {|m| m.mail_notification? || m.user.mail_notification == 'all'}.collect {|m| m.user} end # Returns an array of all custom fields enabled for project issues @@ -564,6 +572,18 @@ return nil end end + + # Yields the given block for each project with its level in the tree + def self.project_tree(projects, &block) + ancestors = [] + projects.sort_by(&:lft).each do |project| + while (ancestors.any? && !project.is_descendant_of?(ancestors.last)) + ancestors.pop + end + yield project, ancestors.size + ancestors << project + end + end private diff -r 09b1d4349da3 -r 371eac10df0b app/models/.svn/text-base/query.rb.svn-base --- a/app/models/.svn/text-base/query.rb.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/models/.svn/text-base/query.rb.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -196,10 +196,10 @@ @available_filters["assigned_to_id"] = { :type => :list_optional, :order => 4, :values => user_values } unless user_values.empty? @available_filters["author_id"] = { :type => :list, :order => 5, :values => user_values } unless user_values.empty? - group_values = Group.all.collect {|g| [g.name, g.id] } + group_values = Group.all.collect {|g| [g.name, g.id.to_s] } @available_filters["member_of_group"] = { :type => :list_optional, :order => 6, :values => group_values } unless group_values.empty? - role_values = Role.givable.collect {|r| [r.name, r.id] } + role_values = Role.givable.collect {|r| [r.name, r.id.to_s] } @available_filters["assigned_to_role"] = { :type => :list_optional, :order => 7, :values => role_values } unless role_values.empty? if User.current.logged? @@ -258,8 +258,10 @@ # Add multiple filters using +add_filter+ def add_filters(fields, operators, values) - fields.each do |field| - add_filter(field, operators[field], values[field]) + if fields.is_a?(Array) && operators.is_a?(Hash) && values.is_a?(Hash) + fields.each do |field| + add_filter(field, operators[field], values[field]) + end end end diff -r 09b1d4349da3 -r 371eac10df0b app/models/.svn/text-base/time_entry.rb.svn-base --- a/app/models/.svn/text-base/time_entry.rb.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/models/.svn/text-base/time_entry.rb.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -27,7 +27,7 @@ acts_as_customizable acts_as_event :title => Proc.new {|o| "#{l_hours(o.hours)} (#{(o.issue || o.project).event_title})"}, - :url => Proc.new {|o| {:controller => 'timelog', :action => 'details', :project_id => o.project, :issue_id => o.issue}}, + :url => Proc.new {|o| {:controller => 'timelog', :action => 'index', :project_id => o.project, :issue_id => o.issue}}, :author => :user, :description => :comments diff -r 09b1d4349da3 -r 371eac10df0b app/models/.svn/text-base/user.rb.svn-base --- a/app/models/.svn/text-base/user.rb.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/models/.svn/text-base/user.rb.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -33,6 +33,15 @@ :username => '#{login}' } + MAIL_NOTIFICATION_OPTIONS = [ + [:all, :label_user_mail_option_all], + [:selected, :label_user_mail_option_selected], + [:none, :label_user_mail_option_none], + [:only_my_events, :label_user_mail_option_only_my_events], + [:only_assigned, :label_user_mail_option_only_assigned], + [:only_owner, :label_user_mail_option_only_owner] + ] + has_and_belongs_to_many :groups, :after_add => Proc.new {|user, group| group.user_added(user)}, :after_remove => Proc.new {|user, group| group.user_removed(user)} has_many :issue_categories, :foreign_key => 'assigned_to_id', :dependent => :nullify @@ -65,7 +74,7 @@ validates_confirmation_of :password, :allow_nil => true def before_create - self.mail_notification = false + self.mail_notification = Setting.default_notification_option if self.mail_notification.blank? true end @@ -250,6 +259,17 @@ notified_projects_ids end + # Only users that belong to more than 1 project can select projects for which they are notified + def valid_notification_options + # Note that @user.membership.size would fail since AR ignores + # :include association option when doing a count + if memberships.length < 1 + MAIL_NOTIFICATION_OPTIONS.delete_if {|option| option.first == :selected} + else + MAIL_NOTIFICATION_OPTIONS + end + end + # Find a user account by matching the exact login and then a case-insensitive # version. Exact matches will be given priority. def self.find_by_login(login) @@ -324,23 +344,35 @@ !roles_for_project(project).detect {|role| role.member?}.nil? end - # Return true if the user is allowed to do the specified action on project - # action can be: + # Return true if the user is allowed to do the specified action on a specific context + # Action can be: # * a parameter-like Hash (eg. :controller => 'projects', :action => 'edit') # * a permission Symbol (eg. :edit_project) - def allowed_to?(action, project, options={}) - if project + # Context can be: + # * a project : returns true if user is allowed to do the specified action on this project + # * a group of projects : returns true if user is allowed on every project + # * nil with options[:global] set : check if user has at least one role allowed for this action, + # or falls back to Non Member / Anonymous permissions depending if the user is logged + def allowed_to?(action, context, options={}) + if context && context.is_a?(Project) # No action allowed on archived projects - return false unless project.active? + return false unless context.active? # No action allowed on disabled modules - return false unless project.allows_to?(action) + return false unless context.allows_to?(action) # Admin users are authorized for anything else return true if admin? - roles = roles_for_project(project) + roles = roles_for_project(context) return false unless roles - roles.detect {|role| (project.is_public? || role.member?) && role.allowed_to?(action)} + roles.detect {|role| (context.is_public? || role.member?) && role.allowed_to?(action)} + elsif context && context.is_a?(Array) + # Authorize if user is authorized on every element of the array + context.map do |project| + allowed_to?(action,project,options) + end.inject do |memo,allowed| + memo && allowed + end elsif options[:global] # Admin users are always authorized return true if admin? @@ -359,6 +391,41 @@ allowed_to?(action, nil, options.reverse_merge(:global => true)) end + # Utility method to help check if a user should be notified about an + # event. + # + # TODO: only supports Issue events currently + def notify_about?(object) + case mail_notification.to_sym + when :all + true + when :selected + # Handled by the Project + when :none + false + when :only_my_events + if object.is_a?(Issue) && (object.author == self || object.assigned_to == self) + true + else + false + end + when :only_assigned + if object.is_a?(Issue) && object.assigned_to == self + true + else + false + end + when :only_owner + if object.is_a?(Issue) && object.author == self + true + else + false + end + else + false + end + end + def self.current=(user) @current_user = user end diff -r 09b1d4349da3 -r 371eac10df0b app/models/.svn/text-base/wiki_content.rb.svn-base --- a/app/models/.svn/text-base/wiki_content.rb.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/models/.svn/text-base/wiki_content.rb.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -54,7 +54,7 @@ :description => :comments, :datetime => :updated_on, :type => 'wiki-page', - :url => Proc.new {|o| {:controller => 'wiki', :id => o.page.wiki.project_id, :page => o.page.title, :version => o.version}} + :url => Proc.new {|o| {:controller => 'wiki', :action => 'show', :project_id => o.page.wiki.project, :id => o.page.title, :version => o.version}} acts_as_activity_provider :type => 'wiki_edits', :timestamp => "#{WikiContent.versioned_table_name}.updated_on", diff -r 09b1d4349da3 -r 371eac10df0b app/models/.svn/text-base/wiki_page.rb.svn-base --- a/app/models/.svn/text-base/wiki_page.rb.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/models/.svn/text-base/wiki_page.rb.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -28,7 +28,7 @@ acts_as_event :title => Proc.new {|o| "#{l(:label_wiki)}: #{o.title}"}, :description => :text, :datetime => :created_on, - :url => Proc.new {|o| {:controller => 'wiki', :id => o.wiki.project, :page => o.title}} + :url => Proc.new {|o| {:controller => 'wiki', :action => 'show', :project_id => o.wiki.project, :id => o.title}} acts_as_searchable :columns => ['title', 'text'], :include => [{:wiki => :project}, :content], @@ -139,7 +139,7 @@ parent_page = t.blank? ? nil : self.wiki.find_page(t) self.parent = parent_page end - + protected def validate diff -r 09b1d4349da3 -r 371eac10df0b app/models/custom_value.rb --- a/app/models/custom_value.rb Thu Oct 21 11:19:14 2010 +0100 +++ b/app/models/custom_value.rb Wed Nov 24 12:20:08 2010 +0000 @@ -34,6 +34,10 @@ custom_field.editable? end + def visible? + custom_field.visible? + end + def required? custom_field.is_required? end diff -r 09b1d4349da3 -r 371eac10df0b app/models/issue.rb --- a/app/models/issue.rb Thu Oct 21 11:19:14 2010 +0100 +++ b/app/models/issue.rb Wed Nov 24 12:20:08 2010 +0000 @@ -86,8 +86,8 @@ } before_create :default_assign - before_save :reschedule_following_issues, :close_duplicates, :update_done_ratio_from_issue_status - after_save :update_nested_set_attributes, :update_parent_attributes, :create_journal + before_save :close_duplicates, :update_done_ratio_from_issue_status + after_save :reschedule_following_issues, :update_nested_set_attributes, :update_parent_attributes, :create_journal after_destroy :destroy_children after_destroy :update_parent_attributes @@ -233,14 +233,35 @@ lock_version ) unless const_defined?(:SAFE_ATTRIBUTES) + SAFE_ATTRIBUTES_ON_TRANSITION = %w( + status_id + assigned_to_id + fixed_version_id + done_ratio + ) unless const_defined?(:SAFE_ATTRIBUTES_ON_TRANSITION) + # Safely sets attributes # Should be called from controllers instead of #attributes= # attr_accessible is too rough because we still want things like # Issue.new(:project => foo) to work # TODO: move workflow/permission checks from controllers to here def safe_attributes=(attrs, user=User.current) - return if attrs.nil? - attrs = attrs.reject {|k,v| !SAFE_ATTRIBUTES.include?(k)} + return unless attrs.is_a?(Hash) + + # User can change issue attributes only if he has :edit permission or if a workflow transition is allowed + if new_record? || user.allowed_to?(:edit_issues, project) + attrs = attrs.reject {|k,v| !SAFE_ATTRIBUTES.include?(k)} + elsif new_statuses_allowed_to(user).any? + attrs = attrs.reject {|k,v| !SAFE_ATTRIBUTES_ON_TRANSITION.include?(k)} + else + return + end + + # Tracker must be set before since new_statuses_allowed_to depends on it. + if t = attrs.delete('tracker_id') + self.tracker_id = t + end + if attrs['status_id'] unless new_statuses_allowed_to(user).collect(&:id).include?(attrs['status_id'].to_i) attrs.delete('status_id') @@ -263,7 +284,7 @@ end def done_ratio - if Issue.use_status_for_done_ratio? && status && status.default_done_ratio? + if Issue.use_status_for_done_ratio? && status && status.default_done_ratio status.default_done_ratio else read_attribute(:done_ratio) @@ -326,7 +347,7 @@ # Set the done_ratio using the status if that setting is set. This will keep the done_ratios # even if the user turns off the setting later def update_done_ratio_from_issue_status - if Issue.use_status_for_done_ratio? && status && status.default_done_ratio? + if Issue.use_status_for_done_ratio? && status && status.default_done_ratio self.done_ratio = status.default_done_ratio end end @@ -390,7 +411,9 @@ # Users the issue can be assigned to def assignable_users - project.assignable_users + users = project.assignable_users + users << author if author + users.uniq.sort end # Versions that the issue can be assigned to @@ -415,9 +438,10 @@ # Returns the mail adresses of users that should be notified def recipients notified = project.notified_users - # Author and assignee are always notified unless they have been locked - notified << author if author && author.active? - notified << assigned_to if assigned_to && assigned_to.active? + # Author and assignee are always notified unless they have been + # locked or don't want to be notified + notified << author if author && author.active? && author.notify_about?(self) + notified << assigned_to if assigned_to && assigned_to.active? && assigned_to.notify_about?(self) notified.uniq! # Remove users that can not view the issue notified.reject! {|user| !visible?(user)} @@ -714,7 +738,7 @@ end # done ratio = weighted average ratio of leaves - unless Issue.use_status_for_done_ratio? && p.status && p.status.default_done_ratio? + unless Issue.use_status_for_done_ratio? && p.status && p.status.default_done_ratio leaves_count = p.leaves.count if leaves_count > 0 average = p.leaves.average(:estimated_hours).to_f diff -r 09b1d4349da3 -r 371eac10df0b app/models/journal_observer.rb --- a/app/models/journal_observer.rb Thu Oct 21 11:19:14 2010 +0100 +++ b/app/models/journal_observer.rb Wed Nov 24 12:20:08 2010 +0000 @@ -17,6 +17,11 @@ class JournalObserver < ActiveRecord::Observer def after_create(journal) - Mailer.deliver_issue_edit(journal) if Setting.notified_events.include?('issue_updated') + if Setting.notified_events.include?('issue_updated') || + (Setting.notified_events.include?('issue_note_added') && journal.notes.present?) || + (Setting.notified_events.include?('issue_status_updated') && journal.new_status.present?) || + (Setting.notified_events.include?('issue_priority_updated') && journal.new_value_for('priority_id').present?) + Mailer.deliver_issue_edit(journal) + end end end diff -r 09b1d4349da3 -r 371eac10df0b app/models/mail_handler.rb --- a/app/models/mail_handler.rb Thu Oct 21 11:19:14 2010 +0100 +++ b/app/models/mail_handler.rb Wed Nov 24 12:20:08 2010 +0000 @@ -17,6 +17,7 @@ class MailHandler < ActionMailer::Base include ActionView::Helpers::SanitizeHelper + include Redmine::I18n class UnauthorizedAction < StandardError; end class MissingInformation < StandardError; end @@ -116,36 +117,20 @@ # Creates a new issue def receive_issue project = target_project - tracker = (get_keyword(:tracker) && project.trackers.find_by_name(get_keyword(:tracker))) || project.trackers.find(:first) - category = (get_keyword(:category) && project.issue_categories.find_by_name(get_keyword(:category))) - priority = (get_keyword(:priority) && IssuePriority.find_by_name(get_keyword(:priority))) - status = (get_keyword(:status) && IssueStatus.find_by_name(get_keyword(:status))) - assigned_to = (get_keyword(:assigned_to, :override => true) && find_user_from_keyword(get_keyword(:assigned_to, :override => true))) - due_date = get_keyword(:due_date, :override => true) - start_date = get_keyword(:start_date, :override => true) - # check permission unless @@handler_options[:no_permission_check] raise UnauthorizedAction unless user.allowed_to?(:add_issues, project) end - issue = Issue.new(:author => user, :project => project, :tracker => tracker, :category => category, :priority => priority, :due_date => due_date, :start_date => start_date, :assigned_to => assigned_to) - # check workflow - if status && issue.new_statuses_allowed_to(user).include?(status) - issue.status = status - end - issue.subject = email.subject.chomp[0,255] + issue = Issue.new(:author => user, :project => project) + issue.safe_attributes = issue_attributes_from_keywords(issue) + issue.safe_attributes = {'custom_field_values' => custom_field_values_from_keywords(issue)} + issue.subject = email.subject.to_s.chomp[0,255] if issue.subject.blank? issue.subject = '(no subject)' end - # custom fields - issue.custom_field_values = issue.available_custom_fields.inject({}) do |h, c| - if value = get_keyword(c.name, :override => true) - h[c.id] = value - end - h - end issue.description = cleaned_up_text_body + # add To and Cc as watchers before saving so the watchers can reply to Redmine add_watchers(issue) issue.save! @@ -154,41 +139,19 @@ issue end - def target_project - # TODO: other ways to specify project: - # * parse the email To field - # * specific project (eg. Setting.mail_handler_target_project) - target = Project.find_by_identifier(get_keyword(:project)) - raise MissingInformation.new('Unable to determine target project') if target.nil? - target - end - # Adds a note to an existing issue def receive_issue_reply(issue_id) - status = (get_keyword(:status) && IssueStatus.find_by_name(get_keyword(:status))) - due_date = get_keyword(:due_date, :override => true) - start_date = get_keyword(:start_date, :override => true) - assigned_to = (get_keyword(:assigned_to, :override => true) && find_user_from_keyword(get_keyword(:assigned_to, :override => true))) - issue = Issue.find_by_id(issue_id) return unless issue # check permission unless @@handler_options[:no_permission_check] raise UnauthorizedAction unless user.allowed_to?(:add_issue_notes, issue.project) || user.allowed_to?(:edit_issues, issue.project) - raise UnauthorizedAction unless status.nil? || user.allowed_to?(:edit_issues, issue.project) end - - # add the note + journal = issue.init_journal(user, cleaned_up_text_body) + issue.safe_attributes = issue_attributes_from_keywords(issue) + issue.safe_attributes = {'custom_field_values' => custom_field_values_from_keywords(issue)} add_attachments(issue) - # check workflow - if status && issue.new_statuses_allowed_to(user).include?(status) - issue.status = status - end - issue.start_date = start_date if start_date - issue.due_date = due_date if due_date - issue.assigned_to = assigned_to if assigned_to - issue.save! logger.info "MailHandler: issue ##{issue.id} updated by #{user}" if logger && logger.info journal @@ -255,8 +218,8 @@ @keywords[attr] else @keywords[attr] = begin - if (options[:override] || @@handler_options[:allow_override].include?(attr.to_s)) && plain_text_body.gsub!(/^#{attr.to_s.humanize}[ \t]*:[ \t]*(.+)\s*$/i, '') - $1.strip + if (options[:override] || @@handler_options[:allow_override].include?(attr.to_s)) && (v = extract_keyword!(plain_text_body, attr, options[:format])) + v elsif !@@handler_options[:issue][attr].blank? @@handler_options[:issue][attr] end @@ -264,6 +227,59 @@ end end + # Destructively extracts the value for +attr+ in +text+ + # Returns nil if no matching keyword found + def extract_keyword!(text, attr, format=nil) + keys = [attr.to_s.humanize] + if attr.is_a?(Symbol) + keys << l("field_#{attr}", :default => '', :locale => user.language) if user + keys << l("field_#{attr}", :default => '', :locale => Setting.default_language) + end + keys.reject! {|k| k.blank?} + keys.collect! {|k| Regexp.escape(k)} + format ||= '.+' + text.gsub!(/^(#{keys.join('|')})[ \t]*:[ \t]*(#{format})\s*$/i, '') + $2 && $2.strip + end + + def target_project + # TODO: other ways to specify project: + # * parse the email To field + # * specific project (eg. Setting.mail_handler_target_project) + target = Project.find_by_identifier(get_keyword(:project)) + raise MissingInformation.new('Unable to determine target project') if target.nil? + target + end + + # Returns a Hash of issue attributes extracted from keywords in the email body + def issue_attributes_from_keywords(issue) + assigned_to = (k = get_keyword(:assigned_to, :override => true)) && find_user_from_keyword(k) + assigned_to = nil if assigned_to && !issue.assignable_users.include?(assigned_to) + + { + 'tracker_id' => ((k = get_keyword(:tracker)) && issue.project.trackers.find_by_name(k).try(:id)) || issue.project.trackers.find(:first).try(:id), + 'status_id' => (k = get_keyword(:status)) && IssueStatus.find_by_name(k).try(:id), + 'priority_id' => (k = get_keyword(:priority)) && IssuePriority.find_by_name(k).try(:id), + 'category_id' => (k = get_keyword(:category)) && issue.project.issue_categories.find_by_name(k).try(:id), + 'assigned_to_id' => assigned_to.try(:id), + 'fixed_version_id' => (k = get_keyword(:fixed_version, :override => true)) && issue.project.shared_versions.find_by_name(k).try(:id), + 'start_date' => get_keyword(:start_date, :override => true, :format => '\d{4}-\d{2}-\d{2}'), + 'due_date' => get_keyword(:due_date, :override => true, :format => '\d{4}-\d{2}-\d{2}'), + 'estimated_hours' => get_keyword(:estimated_hours, :override => true), + 'done_ratio' => get_keyword(:done_ratio, :override => true, :format => '(\d|10)?0') + }.delete_if {|k, v| v.blank? } + end + + # Returns a Hash of issue custom field values extracted from keywords in the email body + def custom_field_values_from_keywords(customized) + customized.custom_field_values.inject({}) do |h, v| + if value = get_keyword(v.custom_field.name, :override => true) + h[v.custom_field.id.to_s] = value + end + h + end + end + # Returns the text/plain part of the email # If not found (eg. HTML-only email), returns the body with tags removed def plain_text_body @@ -318,7 +334,7 @@ def cleanup_body(body) delimiters = Setting.mail_handler_body_delimiters.to_s.split(/[\r\n]+/).reject(&:blank?).map {|s| Regexp.escape(s)} unless delimiters.empty? - regex = Regexp.new("^(#{ delimiters.join('|') })\s*[\r\n].*", Regexp::MULTILINE) + regex = Regexp.new("^[> ]*(#{ delimiters.join('|') })\s*[\r\n].*", Regexp::MULTILINE) body = body.gsub(regex, '') end body.strip diff -r 09b1d4349da3 -r 371eac10df0b app/models/mailer.rb --- a/app/models/mailer.rb Thu Oct 21 11:19:14 2010 +0100 +++ b/app/models/mailer.rb Wed Nov 24 12:20:08 2010 +0000 @@ -178,9 +178,9 @@ message_id wiki_content recipients wiki_content.recipients cc(wiki_content.page.wiki.watcher_recipients - recipients) - subject "[#{wiki_content.project.name}] #{l(:mail_subject_wiki_content_added, :page => wiki_content.page.pretty_title)}" + subject "[#{wiki_content.project.name}] #{l(:mail_subject_wiki_content_added, :id => wiki_content.page.pretty_title)}" body :wiki_content => wiki_content, - :wiki_content_url => url_for(:controller => 'wiki', :action => 'index', :id => wiki_content.project, :page => wiki_content.page.title) + :wiki_content_url => url_for(:controller => 'wiki', :action => 'show', :project_id => wiki_content.project, :id => wiki_content.page.title) render_multipart('wiki_content_added', body) end @@ -195,10 +195,10 @@ message_id wiki_content recipients wiki_content.recipients cc(wiki_content.page.wiki.watcher_recipients + wiki_content.page.watcher_recipients - recipients) - subject "[#{wiki_content.project.name}] #{l(:mail_subject_wiki_content_updated, :page => wiki_content.page.pretty_title)}" + subject "[#{wiki_content.project.name}] #{l(:mail_subject_wiki_content_updated, :id => wiki_content.page.pretty_title)}" body :wiki_content => wiki_content, - :wiki_content_url => url_for(:controller => 'wiki', :action => 'index', :id => wiki_content.project, :page => wiki_content.page.title), - :wiki_diff_url => url_for(:controller => 'wiki', :action => 'diff', :id => wiki_content.project, :page => wiki_content.page.title, :version => wiki_content.version) + :wiki_content_url => url_for(:controller => 'wiki', :action => 'show', :project_id => wiki_content.project, :id => wiki_content.page.title), + :wiki_diff_url => url_for(:controller => 'wiki', :action => 'diff', :project_id => wiki_content.project, :id => wiki_content.page.title, :version => wiki_content.version) render_multipart('wiki_content_updated', body) end diff -r 09b1d4349da3 -r 371eac10df0b app/models/project.rb --- a/app/models/project.rb Thu Oct 21 11:19:14 2010 +0100 +++ b/app/models/project.rb Wed Nov 24 12:20:08 2010 +0000 @@ -20,6 +20,9 @@ STATUS_ACTIVE = 1 STATUS_ARCHIVED = 9 + # Maximum length for project identifiers + IDENTIFIER_MAX_LENGTH = 100 + # Specific overidden Activities has_many :time_entry_activities has_many :members, :include => [:user, :roles], :conditions => "#{User.table_name}.type='User' AND #{User.table_name}.status=#{User::STATUS_ACTIVE}" @@ -64,11 +67,11 @@ attr_protected :status, :enabled_module_names validates_presence_of :name, :identifier - validates_uniqueness_of :name, :identifier + validates_uniqueness_of :identifier validates_associated :repository, :wiki - validates_length_of :name, :maximum => 30 + validates_length_of :name, :maximum => 255 validates_length_of :homepage, :maximum => 255 - validates_length_of :identifier, :in => 1..20 + validates_length_of :identifier, :in => 1..IDENTIFIER_MAX_LENGTH # donwcase letters, digits, dashes but not digits only validates_format_of :identifier, :with => /^(?!\d+$)[a-z0-9\-]*$/, :if => Proc.new { |p| p.identifier_changed? } # reserved words @@ -220,6 +223,10 @@ self.status == STATUS_ACTIVE end + def archived? + self.status == STATUS_ARCHIVED + end + # Archives the project and its descendants def archive # Check that there is no issue of a non descendant project that is assigned @@ -382,12 +389,13 @@ # Returns the mail adresses of users that should be always notified on project events def recipients - members.select {|m| m.mail_notification? || m.user.mail_notification?}.collect {|m| m.user.mail} + notified_users.collect {|user| user.mail} end # Returns the users that should be notified on project events def notified_users - members.select {|m| m.mail_notification? || m.user.mail_notification?}.collect {|m| m.user} + # TODO: User part should be extracted to User#notify_about? + members.select {|m| m.mail_notification? || m.user.mail_notification == 'all'}.collect {|m| m.user} end # Returns an array of all custom fields enabled for project issues @@ -564,6 +572,18 @@ return nil end end + + # Yields the given block for each project with its level in the tree + def self.project_tree(projects, &block) + ancestors = [] + projects.sort_by(&:lft).each do |project| + while (ancestors.any? && !project.is_descendant_of?(ancestors.last)) + ancestors.pop + end + yield project, ancestors.size + ancestors << project + end + end private diff -r 09b1d4349da3 -r 371eac10df0b app/models/query.rb --- a/app/models/query.rb Thu Oct 21 11:19:14 2010 +0100 +++ b/app/models/query.rb Wed Nov 24 12:20:08 2010 +0000 @@ -196,10 +196,10 @@ @available_filters["assigned_to_id"] = { :type => :list_optional, :order => 4, :values => user_values } unless user_values.empty? @available_filters["author_id"] = { :type => :list, :order => 5, :values => user_values } unless user_values.empty? - group_values = Group.all.collect {|g| [g.name, g.id] } + group_values = Group.all.collect {|g| [g.name, g.id.to_s] } @available_filters["member_of_group"] = { :type => :list_optional, :order => 6, :values => group_values } unless group_values.empty? - role_values = Role.givable.collect {|r| [r.name, r.id] } + role_values = Role.givable.collect {|r| [r.name, r.id.to_s] } @available_filters["assigned_to_role"] = { :type => :list_optional, :order => 7, :values => role_values } unless role_values.empty? if User.current.logged? @@ -258,8 +258,10 @@ # Add multiple filters using +add_filter+ def add_filters(fields, operators, values) - fields.each do |field| - add_filter(field, operators[field], values[field]) + if fields.is_a?(Array) && operators.is_a?(Hash) && values.is_a?(Hash) + fields.each do |field| + add_filter(field, operators[field], values[field]) + end end end diff -r 09b1d4349da3 -r 371eac10df0b app/models/repository/.svn/entries --- a/app/models/repository/.svn/entries Thu Oct 21 11:19:14 2010 +0100 +++ b/app/models/repository/.svn/entries Wed Nov 24 12:20:08 2010 +0000 @@ -1,7 +1,7 @@ 10 dir -4173 +4411 http://redmine.rubyforge.org/svn/trunk/app/models/repository http://redmine.rubyforge.org/svn diff -r 09b1d4349da3 -r 371eac10df0b app/models/time_entry.rb --- a/app/models/time_entry.rb Thu Oct 21 11:19:14 2010 +0100 +++ b/app/models/time_entry.rb Wed Nov 24 12:20:08 2010 +0000 @@ -27,7 +27,7 @@ acts_as_customizable acts_as_event :title => Proc.new {|o| "#{l_hours(o.hours)} (#{(o.issue || o.project).event_title})"}, - :url => Proc.new {|o| {:controller => 'timelog', :action => 'details', :project_id => o.project, :issue_id => o.issue}}, + :url => Proc.new {|o| {:controller => 'timelog', :action => 'index', :project_id => o.project, :issue_id => o.issue}}, :author => :user, :description => :comments diff -r 09b1d4349da3 -r 371eac10df0b app/models/user.rb --- a/app/models/user.rb Thu Oct 21 11:19:14 2010 +0100 +++ b/app/models/user.rb Wed Nov 24 12:20:08 2010 +0000 @@ -33,6 +33,15 @@ :username => '#{login}' } + MAIL_NOTIFICATION_OPTIONS = [ + [:all, :label_user_mail_option_all], + [:selected, :label_user_mail_option_selected], + [:none, :label_user_mail_option_none], + [:only_my_events, :label_user_mail_option_only_my_events], + [:only_assigned, :label_user_mail_option_only_assigned], + [:only_owner, :label_user_mail_option_only_owner] + ] + has_and_belongs_to_many :groups, :after_add => Proc.new {|user, group| group.user_added(user)}, :after_remove => Proc.new {|user, group| group.user_removed(user)} has_many :issue_categories, :foreign_key => 'assigned_to_id', :dependent => :nullify @@ -65,7 +74,7 @@ validates_confirmation_of :password, :allow_nil => true def before_create - self.mail_notification = false + self.mail_notification = Setting.default_notification_option if self.mail_notification.blank? true end @@ -250,6 +259,17 @@ notified_projects_ids end + # Only users that belong to more than 1 project can select projects for which they are notified + def valid_notification_options + # Note that @user.membership.size would fail since AR ignores + # :include association option when doing a count + if memberships.length < 1 + MAIL_NOTIFICATION_OPTIONS.delete_if {|option| option.first == :selected} + else + MAIL_NOTIFICATION_OPTIONS + end + end + # Find a user account by matching the exact login and then a case-insensitive # version. Exact matches will be given priority. def self.find_by_login(login) @@ -324,23 +344,35 @@ !roles_for_project(project).detect {|role| role.member?}.nil? end - # Return true if the user is allowed to do the specified action on project - # action can be: + # Return true if the user is allowed to do the specified action on a specific context + # Action can be: # * a parameter-like Hash (eg. :controller => 'projects', :action => 'edit') # * a permission Symbol (eg. :edit_project) - def allowed_to?(action, project, options={}) - if project + # Context can be: + # * a project : returns true if user is allowed to do the specified action on this project + # * a group of projects : returns true if user is allowed on every project + # * nil with options[:global] set : check if user has at least one role allowed for this action, + # or falls back to Non Member / Anonymous permissions depending if the user is logged + def allowed_to?(action, context, options={}) + if context && context.is_a?(Project) # No action allowed on archived projects - return false unless project.active? + return false unless context.active? # No action allowed on disabled modules - return false unless project.allows_to?(action) + return false unless context.allows_to?(action) # Admin users are authorized for anything else return true if admin? - roles = roles_for_project(project) + roles = roles_for_project(context) return false unless roles - roles.detect {|role| (project.is_public? || role.member?) && role.allowed_to?(action)} + roles.detect {|role| (context.is_public? || role.member?) && role.allowed_to?(action)} + elsif context && context.is_a?(Array) + # Authorize if user is authorized on every element of the array + context.map do |project| + allowed_to?(action,project,options) + end.inject do |memo,allowed| + memo && allowed + end elsif options[:global] # Admin users are always authorized return true if admin? @@ -359,6 +391,41 @@ allowed_to?(action, nil, options.reverse_merge(:global => true)) end + # Utility method to help check if a user should be notified about an + # event. + # + # TODO: only supports Issue events currently + def notify_about?(object) + case mail_notification.to_sym + when :all + true + when :selected + # Handled by the Project + when :none + false + when :only_my_events + if object.is_a?(Issue) && (object.author == self || object.assigned_to == self) + true + else + false + end + when :only_assigned + if object.is_a?(Issue) && object.assigned_to == self + true + else + false + end + when :only_owner + if object.is_a?(Issue) && object.author == self + true + else + false + end + else + false + end + end + def self.current=(user) @current_user = user end diff -r 09b1d4349da3 -r 371eac10df0b app/models/wiki_content.rb --- a/app/models/wiki_content.rb Thu Oct 21 11:19:14 2010 +0100 +++ b/app/models/wiki_content.rb Wed Nov 24 12:20:08 2010 +0000 @@ -54,7 +54,7 @@ :description => :comments, :datetime => :updated_on, :type => 'wiki-page', - :url => Proc.new {|o| {:controller => 'wiki', :id => o.page.wiki.project_id, :page => o.page.title, :version => o.version}} + :url => Proc.new {|o| {:controller => 'wiki', :action => 'show', :project_id => o.page.wiki.project, :id => o.page.title, :version => o.version}} acts_as_activity_provider :type => 'wiki_edits', :timestamp => "#{WikiContent.versioned_table_name}.updated_on", diff -r 09b1d4349da3 -r 371eac10df0b app/models/wiki_page.rb --- a/app/models/wiki_page.rb Thu Oct 21 11:19:14 2010 +0100 +++ b/app/models/wiki_page.rb Wed Nov 24 12:20:08 2010 +0000 @@ -28,7 +28,7 @@ acts_as_event :title => Proc.new {|o| "#{l(:label_wiki)}: #{o.title}"}, :description => :text, :datetime => :created_on, - :url => Proc.new {|o| {:controller => 'wiki', :id => o.wiki.project, :page => o.title}} + :url => Proc.new {|o| {:controller => 'wiki', :action => 'show', :project_id => o.wiki.project, :id => o.title}} acts_as_searchable :columns => ['title', 'text'], :include => [{:wiki => :project}, :content], @@ -139,7 +139,7 @@ parent_page = t.blank? ? nil : self.wiki.find_page(t) self.parent = parent_page end - + protected def validate diff -r 09b1d4349da3 -r 371eac10df0b app/sweepers/.svn/entries --- a/app/sweepers/.svn/entries Thu Oct 21 11:19:14 2010 +0100 +++ b/app/sweepers/.svn/entries Wed Nov 24 12:20:08 2010 +0000 @@ -1,7 +1,7 @@ 10 dir -4173 +4411 http://redmine.rubyforge.org/svn/trunk/app/sweepers http://redmine.rubyforge.org/svn diff -r 09b1d4349da3 -r 371eac10df0b app/views/.svn/all-wcprops --- a/app/views/.svn/all-wcprops Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/.svn/all-wcprops Wed Nov 24 12:20:08 2010 +0000 @@ -1,5 +1,5 @@ K 25 svn:wc:ra_dav:version-url V 34 -/svn/!svn/ver/4172/trunk/app/views +/svn/!svn/ver/4409/trunk/app/views END diff -r 09b1d4349da3 -r 371eac10df0b app/views/.svn/entries --- a/app/views/.svn/entries Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/.svn/entries Wed Nov 24 12:20:08 2010 +0000 @@ -1,15 +1,15 @@ 10 dir -4173 +4411 http://redmine.rubyforge.org/svn/trunk/app/views http://redmine.rubyforge.org/svn -2010-09-23T15:20:19.085385Z -4172 -edavis10 +2010-11-16T19:49:08.085592Z +4409 +jplang @@ -50,6 +50,9 @@ workflows dir +time_entry_reports +dir + reports dir @@ -74,13 +77,13 @@ files dir -previews +ldap_auth_sources dir auth_sources dir -ldap_auth_sources +previews dir search @@ -89,10 +92,10 @@ messages dir -versions +issue_relations dir -issue_relations +versions dir mailer diff -r 09b1d4349da3 -r 371eac10df0b app/views/account/.svn/entries --- a/app/views/account/.svn/entries Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/account/.svn/entries Wed Nov 24 12:20:08 2010 +0000 @@ -1,7 +1,7 @@ 10 dir -4173 +4411 http://redmine.rubyforge.org/svn/trunk/app/views/account http://redmine.rubyforge.org/svn diff -r 09b1d4349da3 -r 371eac10df0b app/views/activities/.svn/entries --- a/app/views/activities/.svn/entries Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/activities/.svn/entries Wed Nov 24 12:20:08 2010 +0000 @@ -1,7 +1,7 @@ 10 dir -4173 +4411 http://redmine.rubyforge.org/svn/trunk/app/views/activities http://redmine.rubyforge.org/svn diff -r 09b1d4349da3 -r 371eac10df0b app/views/admin/.svn/all-wcprops --- a/app/views/admin/.svn/all-wcprops Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/admin/.svn/all-wcprops Wed Nov 24 12:20:08 2010 +0000 @@ -1,7 +1,7 @@ K 25 svn:wc:ra_dav:version-url V 40 -/svn/!svn/ver/4080/trunk/app/views/admin +/svn/!svn/ver/4271/trunk/app/views/admin END info.rhtml K 25 @@ -37,5 +37,5 @@ K 25 svn:wc:ra_dav:version-url V 55 -/svn/!svn/ver/4080/trunk/app/views/admin/projects.rhtml +/svn/!svn/ver/4271/trunk/app/views/admin/projects.rhtml END diff -r 09b1d4349da3 -r 371eac10df0b app/views/admin/.svn/entries --- a/app/views/admin/.svn/entries Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/admin/.svn/entries Wed Nov 24 12:20:08 2010 +0000 @@ -1,15 +1,15 @@ 10 dir -4173 +4411 http://redmine.rubyforge.org/svn/trunk/app/views/admin http://redmine.rubyforge.org/svn -2010-09-10T23:07:10.817821Z -4080 -edavis10 +2010-10-22T15:11:04.321155Z +4271 +jplang @@ -202,11 +202,11 @@ -2010-09-24T12:48:28.359820Z -5ed19629dda93ba07ab4e356099d19c4 -2010-09-10T23:07:10.817821Z -4080 -edavis10 +2010-11-19T13:04:49.448967Z +9aaefdc17951db18479f38fb0db73ea7 +2010-10-22T15:11:04.321155Z +4271 +jplang has-props @@ -228,5 +228,5 @@ -2198 +2136 diff -r 09b1d4349da3 -r 371eac10df0b app/views/admin/.svn/text-base/projects.rhtml.svn-base --- a/app/views/admin/.svn/text-base/projects.rhtml.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/admin/.svn/text-base/projects.rhtml.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -19,7 +19,6 @@ - @@ -27,8 +26,7 @@ <% project_tree(@projects) do |project, level| %> <%= project.css_classes %> <%= level > 0 ? "idnt idnt-#{level}" : nil %>"> - - + <% if User.current.allowed_to?(:view_time_entries, @project) %> - + <% end %> @@ -44,18 +44,19 @@ <%= render_custom_fields_rows(@issue) %> <%= call_hook(:view_issues_show_details_bottom, :issue => @issue) %>
<%=l(:label_project)%><%=l(:field_description)%> <%=l(:field_is_public)%> <%=l(:field_created_on)%>
<%= link_to_project(project, :action => 'settings') %><%= textilizable project.short_description, :project => project %><%= link_to_project(project, {:action => 'settings'}, :title => project.short_description) %> <%= checked_image project.is_public? %> <%= format_date(project.created_on) %> diff -r 09b1d4349da3 -r 371eac10df0b app/views/admin/projects.rhtml --- a/app/views/admin/projects.rhtml Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/admin/projects.rhtml Wed Nov 24 12:20:08 2010 +0000 @@ -19,7 +19,6 @@ - @@ -27,8 +26,7 @@ <% project_tree(@projects) do |project, level| %> <%= project.css_classes %> <%= level > 0 ? "idnt idnt-#{level}" : nil %>"> - - + <% if User.current.allowed_to?(:view_time_entries, @project) %> - + <% end %> @@ -44,18 +44,19 @@ <%= render_custom_fields_rows(@issue) %> <%= call_hook(:view_issues_show_details_bottom, :issue => @issue) %>
<%=l(:label_project)%><%=l(:field_description)%> <%=l(:field_is_public)%> <%=l(:field_created_on)%>
<%= link_to_project(project, :action => 'settings') %><%= textilizable project.short_description, :project => project %><%= link_to_project(project, {:action => 'settings'}, :title => project.short_description) %> <%= checked_image project.is_public? %> <%= format_date(project.created_on) %> diff -r 09b1d4349da3 -r 371eac10df0b app/views/attachments/.svn/entries --- a/app/views/attachments/.svn/entries Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/attachments/.svn/entries Wed Nov 24 12:20:08 2010 +0000 @@ -1,7 +1,7 @@ 10 dir -4173 +4411 http://redmine.rubyforge.org/svn/trunk/app/views/attachments http://redmine.rubyforge.org/svn diff -r 09b1d4349da3 -r 371eac10df0b app/views/auth_sources/.svn/entries --- a/app/views/auth_sources/.svn/entries Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/auth_sources/.svn/entries Wed Nov 24 12:20:08 2010 +0000 @@ -1,7 +1,7 @@ 10 dir -4173 +4411 http://redmine.rubyforge.org/svn/trunk/app/views/auth_sources http://redmine.rubyforge.org/svn diff -r 09b1d4349da3 -r 371eac10df0b app/views/auto_completes/.svn/entries --- a/app/views/auto_completes/.svn/entries Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/auto_completes/.svn/entries Wed Nov 24 12:20:08 2010 +0000 @@ -1,7 +1,7 @@ 10 dir -4173 +4411 http://redmine.rubyforge.org/svn/trunk/app/views/auto_completes http://redmine.rubyforge.org/svn diff -r 09b1d4349da3 -r 371eac10df0b app/views/boards/.svn/entries --- a/app/views/boards/.svn/entries Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/boards/.svn/entries Wed Nov 24 12:20:08 2010 +0000 @@ -1,7 +1,7 @@ 10 dir -4173 +4411 http://redmine.rubyforge.org/svn/trunk/app/views/boards http://redmine.rubyforge.org/svn diff -r 09b1d4349da3 -r 371eac10df0b app/views/calendars/.svn/all-wcprops --- a/app/views/calendars/.svn/all-wcprops Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/calendars/.svn/all-wcprops Wed Nov 24 12:20:08 2010 +0000 @@ -1,11 +1,11 @@ K 25 svn:wc:ra_dav:version-url V 44 -/svn/!svn/ver/4045/trunk/app/views/calendars +/svn/!svn/ver/4238/trunk/app/views/calendars END show.html.erb K 25 svn:wc:ra_dav:version-url V 58 -/svn/!svn/ver/4045/trunk/app/views/calendars/show.html.erb +/svn/!svn/ver/4238/trunk/app/views/calendars/show.html.erb END diff -r 09b1d4349da3 -r 371eac10df0b app/views/calendars/.svn/entries --- a/app/views/calendars/.svn/entries Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/calendars/.svn/entries Wed Nov 24 12:20:08 2010 +0000 @@ -1,15 +1,15 @@ 10 dir -4173 +4411 http://redmine.rubyforge.org/svn/trunk/app/views/calendars http://redmine.rubyforge.org/svn -2010-08-26T16:37:21.560510Z -4045 -edavis10 +2010-10-07T15:26:53.500793Z +4238 +winterheart @@ -32,11 +32,11 @@ -2010-09-24T12:48:28.963902Z -a8b2469aff09bc51d836f40717281a44 -2010-08-26T16:37:21.560510Z -4045 -edavis10 +2010-11-19T13:04:49.472856Z +d47ece5d0e0ff017f3f1b5ce4b776ba0 +2010-10-07T15:26:53.500793Z +4238 +winterheart has-props @@ -58,5 +58,5 @@ -1880 +1946 diff -r 09b1d4349da3 -r 371eac10df0b app/views/calendars/.svn/text-base/show.html.erb.svn-base --- a/app/views/calendars/.svn/text-base/show.html.erb.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/calendars/.svn/text-base/show.html.erb.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -26,7 +26,8 @@ }, :class => 'icon icon-checked' %> <%= link_to_remote l(:button_clear), - { :url => { :set_filter => (@query.new_record? ? 1 : nil) }, + { :url => { :project_id => @project, :set_filter => (@query.new_record? ? 1 : nil) }, + :method => :put, :update => "content", }, :class => 'icon icon-reload' if @query.new_record? %>

@@ -37,9 +38,9 @@ <%= render :partial => 'common/calendar', :locals => {:calendar => @calendar} %>

- <%= l(:text_tip_task_begin_day) %> - <%= l(:text_tip_task_end_day) %> - <%= l(:text_tip_task_begin_end_day) %> + <%= l(:text_tip_issue_begin_day) %> + <%= l(:text_tip_issue_end_day) %> + <%= l(:text_tip_issue_begin_end_day) %>

<% end %> diff -r 09b1d4349da3 -r 371eac10df0b app/views/calendars/show.html.erb --- a/app/views/calendars/show.html.erb Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/calendars/show.html.erb Wed Nov 24 12:20:08 2010 +0000 @@ -26,7 +26,8 @@ }, :class => 'icon icon-checked' %> <%= link_to_remote l(:button_clear), - { :url => { :set_filter => (@query.new_record? ? 1 : nil) }, + { :url => { :project_id => @project, :set_filter => (@query.new_record? ? 1 : nil) }, + :method => :put, :update => "content", }, :class => 'icon icon-reload' if @query.new_record? %>

@@ -37,9 +38,9 @@ <%= render :partial => 'common/calendar', :locals => {:calendar => @calendar} %>

- <%= l(:text_tip_task_begin_day) %> - <%= l(:text_tip_task_end_day) %> - <%= l(:text_tip_task_begin_end_day) %> + <%= l(:text_tip_issue_begin_day) %> + <%= l(:text_tip_issue_end_day) %> + <%= l(:text_tip_issue_begin_end_day) %>

<% end %> diff -r 09b1d4349da3 -r 371eac10df0b app/views/common/.svn/all-wcprops --- a/app/views/common/.svn/all-wcprops Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/common/.svn/all-wcprops Wed Nov 24 12:20:08 2010 +0000 @@ -1,7 +1,7 @@ K 25 svn:wc:ra_dav:version-url V 41 -/svn/!svn/ver/3790/trunk/app/views/common +/svn/!svn/ver/4286/trunk/app/views/common END _file.rhtml K 25 @@ -15,24 +15,18 @@ V 56 /svn/!svn/ver/2768/trunk/app/views/common/feed.atom.rxml END +error.html.erb +K 25 +svn:wc:ra_dav:version-url +V 56 +/svn/!svn/ver/4286/trunk/app/views/common/error.html.erb +END _preview.rhtml K 25 svn:wc:ra_dav:version-url V 56 /svn/!svn/ver/1699/trunk/app/views/common/_preview.rhtml END -403.rhtml -K 25 -svn:wc:ra_dav:version-url -V 51 -/svn/!svn/ver/1032/trunk/app/views/common/403.rhtml -END -404.rhtml -K 25 -svn:wc:ra_dav:version-url -V 51 -/svn/!svn/ver/1032/trunk/app/views/common/404.rhtml -END _diff.rhtml K 25 svn:wc:ra_dav:version-url diff -r 09b1d4349da3 -r 371eac10df0b app/views/common/.svn/entries --- a/app/views/common/.svn/entries Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/common/.svn/entries Wed Nov 24 12:20:08 2010 +0000 @@ -1,15 +1,15 @@ 10 dir -4173 +4411 http://redmine.rubyforge.org/svn/trunk/app/views/common http://redmine.rubyforge.org/svn -2010-06-19T22:52:15.523619Z -3790 -edavis10 +2010-10-23T11:07:04.019894Z +4286 +jplang @@ -94,6 +94,40 @@ 1410 +error.html.erb +file + + + + +2010-11-19T13:04:49.456921Z +882dace2c9ea129616067a2052cebef4 +2010-10-23T11:07:04.019894Z +4286 +jplang + + + + + + + + + + + + + + + + + + + + + +156 + _preview.rhtml file @@ -128,74 +162,6 @@ 160 -403.rhtml -file - - - - -2010-09-23T14:37:44.523788Z -6d702bd53ba3e3fb3b1849b20ea05932 -2008-01-02T22:41:53.166620Z -1032 -jplang -has-props - - - - - - - - - - - - - - - - - - - - -130 - -404.rhtml -file - - - - -2010-09-23T14:37:44.523788Z -c6f0413a62e887c7638111e882e33d20 -2008-01-02T22:41:53.166620Z -1032 -jplang -has-props - - - - - - - - - - - - - - - - - - - - -130 - _diff.rhtml file diff -r 09b1d4349da3 -r 371eac10df0b app/views/common/.svn/prop-base/403.rhtml.svn-base --- a/app/views/common/.svn/prop-base/403.rhtml.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -K 13 -svn:eol-style -V 6 -native -END diff -r 09b1d4349da3 -r 371eac10df0b app/views/common/.svn/prop-base/404.rhtml.svn-base --- a/app/views/common/.svn/prop-base/404.rhtml.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -K 13 -svn:eol-style -V 6 -native -END diff -r 09b1d4349da3 -r 371eac10df0b app/views/common/.svn/text-base/403.rhtml.svn-base --- a/app/views/common/.svn/text-base/403.rhtml.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -

403

- -

<%= l(:notice_not_authorized) %>

-

Back

- -<% html_title '403' %> diff -r 09b1d4349da3 -r 371eac10df0b app/views/common/.svn/text-base/404.rhtml.svn-base --- a/app/views/common/.svn/text-base/404.rhtml.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -

404

- -

<%= l(:notice_file_not_found) %>

-

Back

- -<% html_title '404' %> diff -r 09b1d4349da3 -r 371eac10df0b app/views/common/.svn/text-base/error.html.erb.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/views/common/.svn/text-base/error.html.erb.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -0,0 +1,6 @@ +

<%=h @status %>

+ +

<%=h @message %>

+

Back

+ +<% html_title @status %> diff -r 09b1d4349da3 -r 371eac10df0b app/views/common/403.rhtml --- a/app/views/common/403.rhtml Thu Oct 21 11:19:14 2010 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -

403

- -

<%= l(:notice_not_authorized) %>

-

Back

- -<% html_title '403' %> diff -r 09b1d4349da3 -r 371eac10df0b app/views/common/404.rhtml --- a/app/views/common/404.rhtml Thu Oct 21 11:19:14 2010 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -

404

- -

<%= l(:notice_file_not_found) %>

-

Back

- -<% html_title '404' %> diff -r 09b1d4349da3 -r 371eac10df0b app/views/common/error.html.erb --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/views/common/error.html.erb Wed Nov 24 12:20:08 2010 +0000 @@ -0,0 +1,6 @@ +

<%=h @status %>

+ +

<%=h @message %>

+

Back

+ +<% html_title @status %> diff -r 09b1d4349da3 -r 371eac10df0b app/views/context_menus/.svn/all-wcprops --- a/app/views/context_menus/.svn/all-wcprops Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/context_menus/.svn/all-wcprops Wed Nov 24 12:20:08 2010 +0000 @@ -1,11 +1,11 @@ K 25 svn:wc:ra_dav:version-url V 48 -/svn/!svn/ver/4059/trunk/app/views/context_menus +/svn/!svn/ver/4409/trunk/app/views/context_menus END issues.html.erb K 25 svn:wc:ra_dav:version-url V 64 -/svn/!svn/ver/4059/trunk/app/views/context_menus/issues.html.erb +/svn/!svn/ver/4409/trunk/app/views/context_menus/issues.html.erb END diff -r 09b1d4349da3 -r 371eac10df0b app/views/context_menus/.svn/entries --- a/app/views/context_menus/.svn/entries Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/context_menus/.svn/entries Wed Nov 24 12:20:08 2010 +0000 @@ -1,15 +1,15 @@ 10 dir -4173 +4411 http://redmine.rubyforge.org/svn/trunk/app/views/context_menus http://redmine.rubyforge.org/svn -2010-09-03T21:43:07.906158Z -4059 -jbbarth +2010-11-16T19:49:08.085592Z +4409 +jplang @@ -32,11 +32,11 @@ -2010-09-24T12:48:26.291820Z -8cf639a9f676637f0825ccf06013495c -2010-09-03T21:43:07.906158Z -4059 -jbbarth +2010-11-19T13:04:47.016806Z +1a873e0d09f011b6b274e955460d35a1 +2010-11-16T19:49:08.085592Z +4409 +jplang has-props @@ -58,5 +58,5 @@ -6709 +6698 diff -r 09b1d4349da3 -r 371eac10df0b app/views/context_menus/.svn/text-base/issues.html.erb.svn-base --- a/app/views/context_menus/.svn/text-base/issues.html.erb.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/context_menus/.svn/text-base/issues.html.erb.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -9,7 +9,7 @@ :class => 'icon-edit', :disabled => !@can[:edit] %> <% end %> - <% unless @allowed_statuses.empty? %> + <% if @allowed_statuses.present? %>
  • <%= l(:field_status) %>
      @@ -33,7 +33,6 @@ <% end %> - <% if @projects.size == 1 %>
    • <%= l(:field_priority) %>
        @@ -43,8 +42,8 @@ <% end -%>
    • - <% end %> + <% #TODO: allow editing versions when multiple projects %> <% unless @project.nil? || @project.shared_versions.open.empty? -%>
    • <%= l(:field_fixed_version) %> @@ -58,7 +57,7 @@
  • <% end %> - <% unless @assignables.nil? || @assignables.empty? -%> + <% if @assignables.present? -%>
  • <%= l(:field_assigned_to) %>
      @@ -85,7 +84,7 @@ <% end -%> - <% if Issue.use_field_for_done_ratio? && @projects.size == 1 %> + <% if Issue.use_field_for_done_ratio? %>
    • <%= l(:field_done_ratio) %>
        @@ -99,7 +98,7 @@ <% if !@issue.nil? %> <% if @can[:log_time] -%> -
      • <%= context_menu_link l(:button_log_time), {:controller => 'timelog', :action => 'edit', :issue_id => @issue}, +
      • <%= context_menu_link l(:button_log_time), {:controller => 'timelog', :action => 'new', :issue_id => @issue}, :class => 'icon-time-add' %>
      • <% end %> <% if User.current.logged? %> @@ -115,7 +114,7 @@ :class => 'icon-copy', :disabled => !@can[:move] %>
      • <%= context_menu_link l(:button_move), new_issue_move_path(:ids => @issues.collect(&:id)), :class => 'icon-move', :disabled => !@can[:move] %>
      • -
      • <%= context_menu_link l(:button_delete), {:controller => 'issues', :action => 'destroy', :ids => @issues.collect(&:id)}, +
      • <%= context_menu_link l(:button_delete), {:controller => 'issues', :action => 'destroy', :ids => @issues.collect(&:id), :back_url => @back}, :method => :post, :confirm => l(:text_issues_destroy_confirmation), :class => 'icon-del', :disabled => !@can[:delete] %>
      • <%= call_hook(:view_issues_context_menu_end, {:issues => @issues, :can => @can, :back => @back }) %> diff -r 09b1d4349da3 -r 371eac10df0b app/views/context_menus/issues.html.erb --- a/app/views/context_menus/issues.html.erb Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/context_menus/issues.html.erb Wed Nov 24 12:20:08 2010 +0000 @@ -9,7 +9,7 @@ :class => 'icon-edit', :disabled => !@can[:edit] %> <% end %> - <% unless @allowed_statuses.empty? %> + <% if @allowed_statuses.present? %>
      • <%= l(:field_status) %>
          @@ -33,7 +33,6 @@ <% end %> - <% if @projects.size == 1 %>
        • <%= l(:field_priority) %>
            @@ -43,8 +42,8 @@ <% end -%>
        • - <% end %> + <% #TODO: allow editing versions when multiple projects %> <% unless @project.nil? || @project.shared_versions.open.empty? -%>
        • <%= l(:field_fixed_version) %> @@ -58,7 +57,7 @@
      • <% end %> - <% unless @assignables.nil? || @assignables.empty? -%> + <% if @assignables.present? -%>
      • <%= l(:field_assigned_to) %>
          @@ -85,7 +84,7 @@ <% end -%> - <% if Issue.use_field_for_done_ratio? && @projects.size == 1 %> + <% if Issue.use_field_for_done_ratio? %>
        • <%= l(:field_done_ratio) %>
            @@ -99,7 +98,7 @@ <% if !@issue.nil? %> <% if @can[:log_time] -%> -
          • <%= context_menu_link l(:button_log_time), {:controller => 'timelog', :action => 'edit', :issue_id => @issue}, +
          • <%= context_menu_link l(:button_log_time), {:controller => 'timelog', :action => 'new', :issue_id => @issue}, :class => 'icon-time-add' %>
          • <% end %> <% if User.current.logged? %> @@ -115,7 +114,7 @@ :class => 'icon-copy', :disabled => !@can[:move] %>
          • <%= context_menu_link l(:button_move), new_issue_move_path(:ids => @issues.collect(&:id)), :class => 'icon-move', :disabled => !@can[:move] %>
          • -
          • <%= context_menu_link l(:button_delete), {:controller => 'issues', :action => 'destroy', :ids => @issues.collect(&:id)}, +
          • <%= context_menu_link l(:button_delete), {:controller => 'issues', :action => 'destroy', :ids => @issues.collect(&:id), :back_url => @back}, :method => :post, :confirm => l(:text_issues_destroy_confirmation), :class => 'icon-del', :disabled => !@can[:delete] %>
          • <%= call_hook(:view_issues_context_menu_end, {:issues => @issues, :can => @can, :back => @back }) %> diff -r 09b1d4349da3 -r 371eac10df0b app/views/custom_fields/.svn/all-wcprops --- a/app/views/custom_fields/.svn/all-wcprops Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/custom_fields/.svn/all-wcprops Wed Nov 24 12:20:08 2010 +0000 @@ -1,13 +1,13 @@ K 25 svn:wc:ra_dav:version-url V 48 -/svn/!svn/ver/3672/trunk/app/views/custom_fields +/svn/!svn/ver/4382/trunk/app/views/custom_fields END _form.rhtml K 25 svn:wc:ra_dav:version-url V 60 -/svn/!svn/ver/3510/trunk/app/views/custom_fields/_form.rhtml +/svn/!svn/ver/4382/trunk/app/views/custom_fields/_form.rhtml END edit.rhtml K 25 diff -r 09b1d4349da3 -r 371eac10df0b app/views/custom_fields/.svn/entries --- a/app/views/custom_fields/.svn/entries Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/custom_fields/.svn/entries Wed Nov 24 12:20:08 2010 +0000 @@ -1,15 +1,15 @@ 10 dir -4173 +4411 http://redmine.rubyforge.org/svn/trunk/app/views/custom_fields http://redmine.rubyforge.org/svn -2010-04-16T15:33:49.924704Z -3672 -edavis10 +2010-11-07T14:15:01.891476Z +4382 +jplang @@ -32,10 +32,10 @@ -2010-09-23T14:37:44.527783Z -4a422eb0f307906a5015134deef6e66a -2010-02-28T10:55:24.417498Z -3510 +2010-11-19T13:04:48.192856Z +7c1accc3dd22bd872e2e9b6a7f02a5c2 +2010-11-07T14:15:01.891476Z +4382 jplang has-props @@ -58,7 +58,7 @@ -3882 +3960 edit.rhtml file diff -r 09b1d4349da3 -r 371eac10df0b app/views/custom_fields/.svn/text-base/_form.rhtml.svn-base --- a/app/views/custom_fields/.svn/text-base/_form.rhtml.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/custom_fields/.svn/text-base/_form.rhtml.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -86,10 +86,12 @@ <% when "UserCustomField" %>

            <%= f.check_box :is_required %>

            +

            <%= f.check_box :visible %>

            <%= f.check_box :editable %>

            <% when "ProjectCustomField" %>

            <%= f.check_box :is_required %>

            +

            <%= f.check_box :visible %>

            <%= f.check_box :searchable %>

            <% when "TimeEntryCustomField" %> diff -r 09b1d4349da3 -r 371eac10df0b app/views/custom_fields/_form.rhtml --- a/app/views/custom_fields/_form.rhtml Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/custom_fields/_form.rhtml Wed Nov 24 12:20:08 2010 +0000 @@ -86,10 +86,12 @@ <% when "UserCustomField" %>

            <%= f.check_box :is_required %>

            +

            <%= f.check_box :visible %>

            <%= f.check_box :editable %>

            <% when "ProjectCustomField" %>

            <%= f.check_box :is_required %>

            +

            <%= f.check_box :visible %>

            <%= f.check_box :searchable %>

            <% when "TimeEntryCustomField" %> diff -r 09b1d4349da3 -r 371eac10df0b app/views/documents/.svn/entries --- a/app/views/documents/.svn/entries Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/documents/.svn/entries Wed Nov 24 12:20:08 2010 +0000 @@ -1,7 +1,7 @@ 10 dir -4173 +4411 http://redmine.rubyforge.org/svn/trunk/app/views/documents http://redmine.rubyforge.org/svn diff -r 09b1d4349da3 -r 371eac10df0b app/views/enumerations/.svn/entries --- a/app/views/enumerations/.svn/entries Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/enumerations/.svn/entries Wed Nov 24 12:20:08 2010 +0000 @@ -1,7 +1,7 @@ 10 dir -4173 +4411 http://redmine.rubyforge.org/svn/trunk/app/views/enumerations http://redmine.rubyforge.org/svn diff -r 09b1d4349da3 -r 371eac10df0b app/views/files/.svn/all-wcprops --- a/app/views/files/.svn/all-wcprops Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/files/.svn/all-wcprops Wed Nov 24 12:20:08 2010 +0000 @@ -1,13 +1,13 @@ K 25 svn:wc:ra_dav:version-url V 40 -/svn/!svn/ver/4085/trunk/app/views/files +/svn/!svn/ver/4268/trunk/app/views/files END index.html.erb K 25 svn:wc:ra_dav:version-url V 55 -/svn/!svn/ver/4085/trunk/app/views/files/index.html.erb +/svn/!svn/ver/4268/trunk/app/views/files/index.html.erb END new.html.erb K 25 diff -r 09b1d4349da3 -r 371eac10df0b app/views/files/.svn/entries --- a/app/views/files/.svn/entries Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/files/.svn/entries Wed Nov 24 12:20:08 2010 +0000 @@ -1,15 +1,15 @@ 10 dir -4173 +4411 http://redmine.rubyforge.org/svn/trunk/app/views/files http://redmine.rubyforge.org/svn -2010-09-14T16:24:07.840869Z -4085 -edavis10 +2010-10-22T14:45:02.987126Z +4268 +jplang @@ -32,11 +32,11 @@ -2010-09-24T12:48:27.722352Z -178f4ae5a5527ba5ab517e9e5685d670 -2010-09-14T16:24:07.840869Z -4085 -edavis10 +2010-11-19T13:04:49.392852Z +05986f09d13424caeb68601c7c9ff16b +2010-10-22T14:45:02.987126Z +4268 +jplang has-props @@ -58,7 +58,7 @@ -1838 +1878 new.html.erb file diff -r 09b1d4349da3 -r 371eac10df0b app/views/files/.svn/text-base/index.html.erb.svn-base --- a/app/views/files/.svn/text-base/index.html.erb.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/files/.svn/text-base/index.html.erb.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -1,5 +1,5 @@
            -<%= link_to_if_authorized l(:label_attachment_new), new_project_file_path(@project), :class => 'icon icon-add' %> +<%= link_to(l(:label_attachment_new), new_project_file_path(@project), :class => 'icon icon-add') if User.current.allowed_to?(:manage_files, @project) %>

            <%=l(:label_attachment_plural)%>

            diff -r 09b1d4349da3 -r 371eac10df0b app/views/files/index.html.erb --- a/app/views/files/index.html.erb Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/files/index.html.erb Wed Nov 24 12:20:08 2010 +0000 @@ -1,5 +1,5 @@
            -<%= link_to_if_authorized l(:label_attachment_new), new_project_file_path(@project), :class => 'icon icon-add' %> +<%= link_to(l(:label_attachment_new), new_project_file_path(@project), :class => 'icon icon-add') if User.current.allowed_to?(:manage_files, @project) %>

            <%=l(:label_attachment_plural)%>

            diff -r 09b1d4349da3 -r 371eac10df0b app/views/gantts/.svn/all-wcprops --- a/app/views/gantts/.svn/all-wcprops Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/gantts/.svn/all-wcprops Wed Nov 24 12:20:08 2010 +0000 @@ -1,11 +1,11 @@ K 25 svn:wc:ra_dav:version-url V 41 -/svn/!svn/ver/4074/trunk/app/views/gantts +/svn/!svn/ver/4283/trunk/app/views/gantts END show.html.erb K 25 svn:wc:ra_dav:version-url V 55 -/svn/!svn/ver/4074/trunk/app/views/gantts/show.html.erb +/svn/!svn/ver/4283/trunk/app/views/gantts/show.html.erb END diff -r 09b1d4349da3 -r 371eac10df0b app/views/gantts/.svn/entries --- a/app/views/gantts/.svn/entries Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/gantts/.svn/entries Wed Nov 24 12:20:08 2010 +0000 @@ -1,15 +1,15 @@ 10 dir -4173 +4411 http://redmine.rubyforge.org/svn/trunk/app/views/gantts http://redmine.rubyforge.org/svn -2010-09-10T03:09:18.467829Z -4074 -edavis10 +2010-10-23T09:08:55.877887Z +4283 +jplang @@ -32,11 +32,11 @@ -2010-09-24T12:48:28.971835Z -821f1ef595aacb4d32e9a449742c4d67 -2010-09-10T03:09:18.467829Z -4074 -edavis10 +2010-11-19T13:04:49.480864Z +e0ed1c5fd05cd8c8f3f930c443564ebc +2010-10-23T09:08:55.877887Z +4283 +jplang has-props @@ -58,5 +58,5 @@ -6152 +6213 diff -r 09b1d4349da3 -r 371eac10df0b app/views/gantts/.svn/text-base/show.html.erb.svn-base --- a/app/views/gantts/.svn/text-base/show.html.erb.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/gantts/.svn/text-base/show.html.erb.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -10,7 +10,7 @@ -

            +

            <%= gantt_zoom_link(@gantt, :in) %> <%= gantt_zoom_link(@gantt, :out) %>

            @@ -29,7 +29,8 @@ }, :class => 'icon icon-checked' %> <%= link_to_remote l(:button_clear), - { :url => { :set_filter => (@query.new_record? ? 1 : nil) }, + { :url => { :project_id => @project, :set_filter => (@query.new_record? ? 1 : nil) }, + :method => :put, :update => "content", }, :class => 'icon icon-reload' if @query.new_record? %>

            diff -r 09b1d4349da3 -r 371eac10df0b app/views/gantts/show.html.erb --- a/app/views/gantts/show.html.erb Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/gantts/show.html.erb Wed Nov 24 12:20:08 2010 +0000 @@ -10,7 +10,7 @@ -

            +

            <%= gantt_zoom_link(@gantt, :in) %> <%= gantt_zoom_link(@gantt, :out) %>

            @@ -29,7 +29,8 @@ }, :class => 'icon icon-checked' %> <%= link_to_remote l(:button_clear), - { :url => { :set_filter => (@query.new_record? ? 1 : nil) }, + { :url => { :project_id => @project, :set_filter => (@query.new_record? ? 1 : nil) }, + :method => :put, :update => "content", }, :class => 'icon icon-reload' if @query.new_record? %>

            diff -r 09b1d4349da3 -r 371eac10df0b app/views/groups/.svn/all-wcprops --- a/app/views/groups/.svn/all-wcprops Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/groups/.svn/all-wcprops Wed Nov 24 12:20:08 2010 +0000 @@ -1,7 +1,7 @@ K 25 svn:wc:ra_dav:version-url V 41 -/svn/!svn/ver/3734/trunk/app/views/groups +/svn/!svn/ver/4312/trunk/app/views/groups END autocomplete_for_user.html.erb K 25 @@ -43,7 +43,7 @@ K 25 svn:wc:ra_dav:version-url V 57 -/svn/!svn/ver/3734/trunk/app/views/groups/_users.html.erb +/svn/!svn/ver/4312/trunk/app/views/groups/_users.html.erb END show.html.erb K 25 diff -r 09b1d4349da3 -r 371eac10df0b app/views/groups/.svn/entries --- a/app/views/groups/.svn/entries Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/groups/.svn/entries Wed Nov 24 12:20:08 2010 +0000 @@ -1,15 +1,15 @@ 10 dir -4173 +4411 http://redmine.rubyforge.org/svn/trunk/app/views/groups http://redmine.rubyforge.org/svn -2010-05-09T11:19:15.980195Z -3734 -jplang +2010-10-30T16:47:33.260585Z +4312 +jbbarth @@ -236,11 +236,11 @@ -2010-09-23T14:37:44.547775Z -eff82d54d4b9afef8e057bce83a79055 -2010-05-09T11:19:15.980195Z -3734 -jplang +2010-11-19T13:04:49.444940Z +7738dc0db4c4ad48e82613829c1e991a +2010-10-30T16:47:33.260585Z +4312 +jbbarth has-props @@ -262,7 +262,7 @@ -1572 +1625 show.html.erb file diff -r 09b1d4349da3 -r 371eac10df0b app/views/groups/.svn/text-base/_users.html.erb.svn-base --- a/app/views/groups/.svn/text-base/_users.html.erb.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/groups/.svn/text-base/_users.html.erb.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -29,7 +29,7 @@ <% remote_form_for(:group, @group, :url => {:controller => 'groups', :action => 'add_users', :id => @group}, :method => :post) do |f| %>
            <%=l(:label_user_new)%> -

            <%= text_field_tag 'user_search', nil %>

            +

            <%= label_tag "user_search", l(:label_user_search) %><%= text_field_tag 'user_search', nil %>

            <%= observe_field(:user_search, :frequency => 0.5, :update => :users, diff -r 09b1d4349da3 -r 371eac10df0b app/views/groups/_users.html.erb --- a/app/views/groups/_users.html.erb Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/groups/_users.html.erb Wed Nov 24 12:20:08 2010 +0000 @@ -29,7 +29,7 @@ <% remote_form_for(:group, @group, :url => {:controller => 'groups', :action => 'add_users', :id => @group}, :method => :post) do |f| %>
            <%=l(:label_user_new)%> -

            <%= text_field_tag 'user_search', nil %>

            +

            <%= label_tag "user_search", l(:label_user_search) %><%= text_field_tag 'user_search', nil %>

            <%= observe_field(:user_search, :frequency => 0.5, :update => :users, diff -r 09b1d4349da3 -r 371eac10df0b app/views/issue_categories/.svn/all-wcprops --- a/app/views/issue_categories/.svn/all-wcprops Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/issue_categories/.svn/all-wcprops Wed Nov 24 12:20:08 2010 +0000 @@ -1,7 +1,7 @@ K 25 svn:wc:ra_dav:version-url V 51 -/svn/!svn/ver/3549/trunk/app/views/issue_categories +/svn/!svn/ver/4385/trunk/app/views/issue_categories END new.html.erb K 25 @@ -12,8 +12,8 @@ _form.rhtml K 25 svn:wc:ra_dav:version-url -V 62 -/svn/!svn/ver/577/trunk/app/views/issue_categories/_form.rhtml +V 63 +/svn/!svn/ver/4385/trunk/app/views/issue_categories/_form.rhtml END edit.rhtml K 25 diff -r 09b1d4349da3 -r 371eac10df0b app/views/issue_categories/.svn/entries --- a/app/views/issue_categories/.svn/entries Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/issue_categories/.svn/entries Wed Nov 24 12:20:08 2010 +0000 @@ -1,14 +1,14 @@ 10 dir -4173 +4411 http://redmine.rubyforge.org/svn/trunk/app/views/issue_categories http://redmine.rubyforge.org/svn -2010-03-06T18:43:00.594668Z -3549 +2010-11-07T14:56:12.614499Z +4385 jplang @@ -66,10 +66,10 @@ -2010-09-23T14:37:44.551784Z -18eb89247454858a8ee0d9ffe9f0e8f6 -2007-06-29T17:21:37.739022Z -577 +2010-11-19T13:04:49.476971Z +e0d28729320423a7b8fcb6309b58de9a +2010-11-07T14:56:12.614499Z +4385 jplang has-props @@ -92,7 +92,7 @@ -235 +240 edit.rhtml file diff -r 09b1d4349da3 -r 371eac10df0b app/views/issue_categories/.svn/text-base/_form.rhtml.svn-base --- a/app/views/issue_categories/.svn/text-base/_form.rhtml.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/issue_categories/.svn/text-base/_form.rhtml.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -2,5 +2,5 @@

            <%= f.text_field :name, :size => 30, :required => true %>

            -

            <%= f.select :assigned_to_id, @project.users.collect{|u| [u.name, u.id]}, :include_blank => true %>

            +

            <%= f.select :assigned_to_id, @project.users.sort.collect{|u| [u.name, u.id]}, :include_blank => true %>

            diff -r 09b1d4349da3 -r 371eac10df0b app/views/issue_categories/_form.rhtml --- a/app/views/issue_categories/_form.rhtml Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/issue_categories/_form.rhtml Wed Nov 24 12:20:08 2010 +0000 @@ -2,5 +2,5 @@

            <%= f.text_field :name, :size => 30, :required => true %>

            -

            <%= f.select :assigned_to_id, @project.users.collect{|u| [u.name, u.id]}, :include_blank => true %>

            +

            <%= f.select :assigned_to_id, @project.users.sort.collect{|u| [u.name, u.id]}, :include_blank => true %>

            diff -r 09b1d4349da3 -r 371eac10df0b app/views/issue_moves/.svn/all-wcprops --- a/app/views/issue_moves/.svn/all-wcprops Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/issue_moves/.svn/all-wcprops Wed Nov 24 12:20:08 2010 +0000 @@ -1,11 +1,11 @@ K 25 svn:wc:ra_dav:version-url V 46 -/svn/!svn/ver/3936/trunk/app/views/issue_moves +/svn/!svn/ver/4292/trunk/app/views/issue_moves END new.rhtml K 25 svn:wc:ra_dav:version-url V 56 -/svn/!svn/ver/3936/trunk/app/views/issue_moves/new.rhtml +/svn/!svn/ver/4292/trunk/app/views/issue_moves/new.rhtml END diff -r 09b1d4349da3 -r 371eac10df0b app/views/issue_moves/.svn/entries --- a/app/views/issue_moves/.svn/entries Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/issue_moves/.svn/entries Wed Nov 24 12:20:08 2010 +0000 @@ -1,14 +1,14 @@ 10 dir -4173 +4411 http://redmine.rubyforge.org/svn/trunk/app/views/issue_moves http://redmine.rubyforge.org/svn -2010-08-11T14:42:10.119704Z -3936 +2010-10-25T18:44:46.868009Z +4292 edavis10 @@ -32,10 +32,10 @@ -2010-09-23T14:37:44.555783Z -75404bb56747fe4f58e979b3452af027 -2010-08-11T14:42:10.119704Z -3936 +2010-11-19T13:04:48.788846Z +1ad6c5f00ec9a5a7509125da416b0b07 +2010-10-25T18:44:46.868009Z +4292 edavis10 has-props @@ -58,5 +58,5 @@ -2304 +2701 diff -r 09b1d4349da3 -r 371eac10df0b app/views/issue_moves/.svn/text-base/new.rhtml.svn-base --- a/app/views/issue_moves/.svn/text-base/new.rhtml.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/issue_moves/.svn/text-base/new.rhtml.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -34,6 +34,11 @@

            + + <%= select_tag('priority_id', "" + options_from_collection_for_select(IssuePriority.all, :id, :name)) %> +

            + +

            <%= text_field_tag 'start_date', '', :size => 10 %><%= calendar_for('start_date') %>

            @@ -43,6 +48,11 @@ <%= text_field_tag 'due_date', '', :size => 10 %><%= calendar_for('due_date') %>

            +
            <%= l(:field_notes) %> +<%= text_area_tag 'notes', @notes, :cols => 60, :rows => 10, :class => 'wiki-edit' %> +<%= wikitoolbar_for 'notes' %> +
            + <%= call_hook(:view_issues_move_bottom, :issues => @issues, :target_project => @target_project, :copy => !!@copy) %> diff -r 09b1d4349da3 -r 371eac10df0b app/views/issue_moves/new.rhtml --- a/app/views/issue_moves/new.rhtml Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/issue_moves/new.rhtml Wed Nov 24 12:20:08 2010 +0000 @@ -34,6 +34,11 @@

            + + <%= select_tag('priority_id', "" + options_from_collection_for_select(IssuePriority.all, :id, :name)) %> +

            + +

            <%= text_field_tag 'start_date', '', :size => 10 %><%= calendar_for('start_date') %>

            @@ -43,6 +48,11 @@ <%= text_field_tag 'due_date', '', :size => 10 %><%= calendar_for('due_date') %>

            +
            <%= l(:field_notes) %> +<%= text_area_tag 'notes', @notes, :cols => 60, :rows => 10, :class => 'wiki-edit' %> +<%= wikitoolbar_for 'notes' %> +
            + <%= call_hook(:view_issues_move_bottom, :issues => @issues, :target_project => @target_project, :copy => !!@copy) %> diff -r 09b1d4349da3 -r 371eac10df0b app/views/issue_relations/.svn/entries --- a/app/views/issue_relations/.svn/entries Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/issue_relations/.svn/entries Wed Nov 24 12:20:08 2010 +0000 @@ -1,7 +1,7 @@ 10 dir -4173 +4411 http://redmine.rubyforge.org/svn/trunk/app/views/issue_relations http://redmine.rubyforge.org/svn diff -r 09b1d4349da3 -r 371eac10df0b app/views/issue_statuses/.svn/entries --- a/app/views/issue_statuses/.svn/entries Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/issue_statuses/.svn/entries Wed Nov 24 12:20:08 2010 +0000 @@ -1,7 +1,7 @@ 10 dir -4173 +4411 http://redmine.rubyforge.org/svn/trunk/app/views/issue_statuses http://redmine.rubyforge.org/svn diff -r 09b1d4349da3 -r 371eac10df0b app/views/issues/.svn/all-wcprops --- a/app/views/issues/.svn/all-wcprops Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/issues/.svn/all-wcprops Wed Nov 24 12:20:08 2010 +0000 @@ -1,7 +1,7 @@ K 25 svn:wc:ra_dav:version-url V 41 -/svn/!svn/ver/4165/trunk/app/views/issues +/svn/!svn/ver/4311/trunk/app/views/issues END _relations.rhtml K 25 @@ -9,29 +9,29 @@ V 58 /svn/!svn/ver/4065/trunk/app/views/issues/_relations.rhtml END -_action_menu.rhtml -K 25 -svn:wc:ra_dav:version-url -V 60 -/svn/!svn/ver/4105/trunk/app/views/issues/_action_menu.rhtml -END _history.rhtml K 25 svn:wc:ra_dav:version-url V 56 /svn/!svn/ver/4062/trunk/app/views/issues/_history.rhtml END -_form.rhtml +_action_menu.rhtml K 25 svn:wc:ra_dav:version-url -V 53 -/svn/!svn/ver/4165/trunk/app/views/issues/_form.rhtml +V 60 +/svn/!svn/ver/4258/trunk/app/views/issues/_action_menu.rhtml END bulk_edit.rhtml K 25 svn:wc:ra_dav:version-url V 57 -/svn/!svn/ver/4037/trunk/app/views/issues/bulk_edit.rhtml +/svn/!svn/ver/4242/trunk/app/views/issues/bulk_edit.rhtml +END +_form.rhtml +K 25 +svn:wc:ra_dav:version-url +V 53 +/svn/!svn/ver/4311/trunk/app/views/issues/_form.rhtml END _form_update.rhtml K 25 @@ -73,7 +73,7 @@ K 25 svn:wc:ra_dav:version-url V 52 -/svn/!svn/ver/4014/trunk/app/views/issues/show.rhtml +/svn/!svn/ver/4264/trunk/app/views/issues/show.rhtml END _form_custom_fields.rhtml K 25 @@ -81,18 +81,18 @@ V 67 /svn/!svn/ver/2827/trunk/app/views/issues/_form_custom_fields.rhtml END +_list_simple.rhtml +K 25 +svn:wc:ra_dav:version-url +V 60 +/svn/!svn/ver/3924/trunk/app/views/issues/_list_simple.rhtml +END _changesets.rhtml K 25 svn:wc:ra_dav:version-url V 59 /svn/!svn/ver/3898/trunk/app/views/issues/_changesets.rhtml END -_list_simple.rhtml -K 25 -svn:wc:ra_dav:version-url -V 60 -/svn/!svn/ver/3924/trunk/app/views/issues/_list_simple.rhtml -END _edit.rhtml K 25 svn:wc:ra_dav:version-url @@ -121,5 +121,5 @@ K 25 svn:wc:ra_dav:version-url V 51 -/svn/!svn/ver/3946/trunk/app/views/issues/new.rhtml +/svn/!svn/ver/4311/trunk/app/views/issues/new.rhtml END diff -r 09b1d4349da3 -r 371eac10df0b app/views/issues/.svn/entries --- a/app/views/issues/.svn/entries Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/issues/.svn/entries Wed Nov 24 12:20:08 2010 +0000 @@ -1,15 +1,15 @@ 10 dir -4173 +4411 http://redmine.rubyforge.org/svn/trunk/app/views/issues http://redmine.rubyforge.org/svn -2010-09-20T18:50:09.519311Z -4165 -edavis10 +2010-10-30T16:15:31.867344Z +4311 +jbbarth @@ -60,6 +60,40 @@ 1816 +_action_menu.rhtml +file + + + + +2010-11-19T13:04:50.824922Z +74c6e939ebb113c49a367fff0f463f63 +2010-10-15T23:11:05.712143Z +4258 +edavis10 + + + + + + + + + + + + + + + + + + + + + +1285 + _history.rhtml file @@ -94,17 +128,18 @@ 859 -_action_menu.rhtml +_form.rhtml file -2010-09-24T12:48:29.596042Z -d39cbd8da926ba1c0912674a25e0bbae -2010-09-20T02:55:26.436604Z -4105 -edavis10 +2010-11-19T13:04:50.824922Z +7c3d2a41291eabbd1c7e28139be69e49 +2010-10-30T16:15:31.867344Z +4311 +jbbarth +has-props @@ -125,8 +160,7 @@ - -1228 +2033 bulk_edit.rhtml file @@ -134,11 +168,11 @@ -2010-09-23T14:37:44.571741Z -2118a1220c381352190040dc4b80e7d4 -2010-08-24T15:27:12.793586Z -4037 -edavis10 +2010-11-19T13:04:50.824922Z +b60c0aee0477249fc72d3206e30a8a07 +2010-10-08T03:09:51.863032Z +4242 +jbbarth has-props @@ -160,41 +194,7 @@ -3344 - -_form.rhtml -file - - - - -2010-09-24T12:48:29.596042Z -c95e7aec098a5197f699f7ff5d9cfea5 -2010-09-20T18:50:09.519311Z -4165 -edavis10 -has-props - - - - - - - - - - - - - - - - - - - - -2034 +3438 _form_update.rhtml file @@ -406,11 +406,11 @@ -2010-09-23T14:37:44.575742Z -81fcfef3bb688e30577916647e05f02a -2010-08-22T19:12:21.015911Z -4014 -edavis10 +2010-11-19T13:04:50.824922Z +1f2adc49d35b7299cebfc9aff8152908 +2010-10-19T19:26:07.436051Z +4264 +jplang has-props @@ -432,7 +432,7 @@ -5394 +5399 _form_custom_fields.rhtml file @@ -468,6 +468,40 @@ 353 +_changesets.rhtml +file + + + + +2010-09-23T14:37:44.571741Z +4c03735a361a24cc60a70975502bace7 +2010-07-29T15:48:53.812065Z +3898 +winterheart +has-props + + + + + + + + + + + + + + + + + + + + +509 + _list_simple.rhtml file @@ -502,40 +536,6 @@ 989 -_changesets.rhtml -file - - - - -2010-09-23T14:37:44.571741Z -4c03735a361a24cc60a70975502bace7 -2010-07-29T15:48:53.812065Z -3898 -winterheart -has-props - - - - - - - - - - - - - - - - - - - - -509 - _edit.rhtml file @@ -678,11 +678,11 @@ -2010-09-23T14:37:44.575742Z -c1a3c605c3eed0e46487a4455acefad7 -2010-08-18T15:01:35.032314Z -3946 -edavis10 +2010-11-19T13:04:50.824922Z +9889d4cce0dfd6d224e85fc1f489c623 +2010-10-30T16:15:31.867344Z +4311 +jbbarth has-props @@ -704,5 +704,5 @@ -1118 +1154 diff -r 09b1d4349da3 -r 371eac10df0b app/views/issues/.svn/text-base/_action_menu.rhtml.svn-base --- a/app/views/issues/.svn/text-base/_action_menu.rhtml.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/issues/.svn/text-base/_action_menu.rhtml.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -1,10 +1,10 @@
            <%= link_to_if_authorized(l(:button_update), {:controller => 'issues', :action => 'edit', :id => @issue }, :onclick => 'showAndScrollTo("update", "notes"); return false;', :class => 'icon icon-edit', :accesskey => accesskey(:edit)) %> -<%= link_to_if_authorized l(:button_log_time), {:controller => 'timelog', :action => 'edit', :issue_id => @issue}, :class => 'icon icon-time-add' %> +<%= link_to_if_authorized l(:button_log_time), {:controller => 'timelog', :action => 'new', :issue_id => @issue}, :class => 'icon icon-time-add' %> <% replace_watcher ||= 'watcher' %> <%= watcher_tag(@issue, User.current, {:id => replace_watcher, :replace => ['watcher','watcher2']}) %> <%= link_to_if_authorized l(:button_duplicate), {:controller => 'issues', :action => 'new', :project_id => @project, :copy_from => @issue }, :class => 'icon icon-duplicate' %> -<%= link_to_if_authorized l(:button_copy), new_issue_move_path(:id => @issue, :copy_options => {:copy => 't'}), :class => 'icon icon-copy' %> -<%= link_to_if_authorized l(:button_move), new_issue_move_path(:id => @issue), :class => 'icon icon-move' %> +<%= link_to_if_authorized l(:button_copy), {:controller => 'issue_moves', :action => 'new', :id => @issue, :copy_options => {:copy => 't'}}, :class => 'icon icon-copy' %> +<%= link_to_if_authorized l(:button_move), {:controller => 'issue_moves', :action => 'new', :id => @issue}, :class => 'icon icon-move' %> <%= link_to_if_authorized l(:button_delete), {:controller => 'issues', :action => 'destroy', :id => @issue}, :confirm => (@issue.leaf? ? l(:text_are_you_sure) : l(:text_are_you_sure_with_children)), :method => :post, :class => 'icon icon-del' %>
            diff -r 09b1d4349da3 -r 371eac10df0b app/views/issues/.svn/text-base/_form.rhtml.svn-base --- a/app/views/issues/.svn/text-base/_form.rhtml.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/issues/.svn/text-base/_form.rhtml.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -8,8 +8,8 @@

            <%= f.text_field :subject, :size => 80, :required => true %>

            -<% unless (@issue.new_record? && @issue.parent_issue_id.nil?) || !User.current.allowed_to?(:manage_subtasks, @project) %> -

            <%= f.text_field :parent_issue_id, :size => 10 %>

            +<% if User.current.allowed_to?(:manage_subtasks, @project) %> +

            <%= f.text_field :parent_issue_id, :size => 10 %>

            <%= javascript_tag "observeParentIssueField('#{auto_complete_issues_path(:id => @issue, :project_id => @project) }')" %> <% end %> @@ -26,11 +26,11 @@ <% if @issue.new_record? %> -

            <%= label_tag('attachments[1][file]', l(:label_attachment_plural))%><%= render :partial => 'attachments/form' %>

            +

            <%= label_tag('attachments[1][file]', l(:label_attachment_plural))%><%= render :partial => 'attachments/form' %>

            <% end %> <% if @issue.new_record? && User.current.allowed_to?(:add_issue_watchers, @project) -%> -

            +

            <% @issue.project.users.sort.each do |user| -%> <% end -%> diff -r 09b1d4349da3 -r 371eac10df0b app/views/issues/.svn/text-base/bulk_edit.rhtml.svn-base --- a/app/views/issues/.svn/text-base/bulk_edit.rhtml.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/issues/.svn/text-base/bulk_edit.rhtml.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -11,7 +11,7 @@

            - <%= select_tag('issue[tracker_id]', "" + options_from_collection_for_select(@project.trackers, :id, :name)) %> + <%= select_tag('issue[tracker_id]', "" + options_from_collection_for_select(@trackers, :id, :name)) %>

            <% if @available_statuses.any? %>

            @@ -27,20 +27,25 @@ <%= select_tag('issue[assigned_to_id]', content_tag('option', l(:label_no_change_option), :value => '') + content_tag('option', l(:label_nobody), :value => 'none') + - options_from_collection_for_select(@project.assignable_users, :id, :name)) %> + options_from_collection_for_select(@assignables, :id, :name)) %>

            +<% if @project %>

            <%= select_tag('issue[category_id]', content_tag('option', l(:label_no_change_option), :value => '') + content_tag('option', l(:label_none), :value => 'none') + options_from_collection_for_select(@project.issue_categories, :id, :name)) %>

            +<% end %> +<% #TODO: allow editing versions when multiple projects %> +<% if @project %>

            <%= select_tag('issue[fixed_version_id]', content_tag('option', l(:label_no_change_option), :value => '') + content_tag('option', l(:label_none), :value => 'none') + version_options_for_select(@project.shared_versions.open)) %>

            +<% end %> <% @custom_fields.each do |custom_field| %>

            <%= custom_field_tag_for_bulk_edit('issue', custom_field) %>

            diff -r 09b1d4349da3 -r 371eac10df0b app/views/issues/.svn/text-base/new.rhtml.svn-base --- a/app/views/issues/.svn/text-base/new.rhtml.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/issues/.svn/text-base/new.rhtml.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -1,7 +1,7 @@

            <%=l(:label_issue_new)%>

            <% labelled_tabular_form_for :issue, @issue, :url => {:controller => 'issues', :action => 'create', :project_id => @project}, - :html => {:multipart => true, :id => 'issue-form'} do |f| %> + :html => {:multipart => true, :id => 'issue-form', :class => 'tabular new-issue-form'} do |f| %> <%= error_messages_for 'issue' %>
            <%= render :partial => 'issues/form', :locals => {:f => f} %> diff -r 09b1d4349da3 -r 371eac10df0b app/views/issues/.svn/text-base/show.rhtml.svn-base --- a/app/views/issues/.svn/text-base/show.rhtml.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/issues/.svn/text-base/show.rhtml.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -32,7 +32,7 @@
  • <%=l(:field_category)%>:<%=h @issue.category ? @issue.category.name : "-" %><%=l(:label_spent_time)%>:<%= @issue.spent_hours > 0 ? (link_to l_hours(@issue.spent_hours), {:controller => 'timelog', :action => 'details', :project_id => @project, :issue_id => @issue}) : "-" %><%= @issue.spent_hours > 0 ? (link_to l_hours(@issue.spent_hours), {:controller => 'timelog', :action => 'index', :project_id => @project, :issue_id => @issue}) : "-" %>
    + +<% if @issue.description? || @issue.attachments.any? -%>
    -
    -<%= link_to_remote_if_authorized(l(:button_quote), { :url => {:action => 'reply', :id => @issue} }, :class => 'icon icon-comment') unless @issue.description.blank? %> +<%= link_to_remote_if_authorized(l(:button_quote), { :url => {:action => 'reply', :id => @issue} }, :class => 'icon icon-comment') if @issue.description? %>
    -

    <%=l(:field_description)%>

    <%= textilizable @issue, :description, :attachments => @issue.attachments %>
    <%= link_to_attachments @issue %> +<% end -%> <%= call_hook(:view_issues_show_description_bottom, :issue => @issue) %> diff -r 09b1d4349da3 -r 371eac10df0b app/views/issues/_action_menu.rhtml --- a/app/views/issues/_action_menu.rhtml Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/issues/_action_menu.rhtml Wed Nov 24 12:20:08 2010 +0000 @@ -1,10 +1,10 @@
    <%= link_to_if_authorized(l(:button_update), {:controller => 'issues', :action => 'edit', :id => @issue }, :onclick => 'showAndScrollTo("update", "notes"); return false;', :class => 'icon icon-edit', :accesskey => accesskey(:edit)) %> -<%= link_to_if_authorized l(:button_log_time), {:controller => 'timelog', :action => 'edit', :issue_id => @issue}, :class => 'icon icon-time-add' %> +<%= link_to_if_authorized l(:button_log_time), {:controller => 'timelog', :action => 'new', :issue_id => @issue}, :class => 'icon icon-time-add' %> <% replace_watcher ||= 'watcher' %> <%= watcher_tag(@issue, User.current, {:id => replace_watcher, :replace => ['watcher','watcher2']}) %> <%= link_to_if_authorized l(:button_duplicate), {:controller => 'issues', :action => 'new', :project_id => @project, :copy_from => @issue }, :class => 'icon icon-duplicate' %> -<%= link_to_if_authorized l(:button_copy), new_issue_move_path(:id => @issue, :copy_options => {:copy => 't'}), :class => 'icon icon-copy' %> -<%= link_to_if_authorized l(:button_move), new_issue_move_path(:id => @issue), :class => 'icon icon-move' %> +<%= link_to_if_authorized l(:button_copy), {:controller => 'issue_moves', :action => 'new', :id => @issue, :copy_options => {:copy => 't'}}, :class => 'icon icon-copy' %> +<%= link_to_if_authorized l(:button_move), {:controller => 'issue_moves', :action => 'new', :id => @issue}, :class => 'icon icon-move' %> <%= link_to_if_authorized l(:button_delete), {:controller => 'issues', :action => 'destroy', :id => @issue}, :confirm => (@issue.leaf? ? l(:text_are_you_sure) : l(:text_are_you_sure_with_children)), :method => :post, :class => 'icon icon-del' %>
    diff -r 09b1d4349da3 -r 371eac10df0b app/views/issues/_form.rhtml --- a/app/views/issues/_form.rhtml Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/issues/_form.rhtml Wed Nov 24 12:20:08 2010 +0000 @@ -8,8 +8,8 @@

    <%= f.text_field :subject, :size => 80, :required => true %>

    -<% unless (@issue.new_record? && @issue.parent_issue_id.nil?) || !User.current.allowed_to?(:manage_subtasks, @project) %> -

    <%= f.text_field :parent_issue_id, :size => 10 %>

    +<% if User.current.allowed_to?(:manage_subtasks, @project) %> +

    <%= f.text_field :parent_issue_id, :size => 10 %>

    <%= javascript_tag "observeParentIssueField('#{auto_complete_issues_path(:id => @issue, :project_id => @project) }')" %> <% end %> @@ -26,11 +26,11 @@ <% if @issue.new_record? %> -

    <%= label_tag('attachments[1][file]', l(:label_attachment_plural))%><%= render :partial => 'attachments/form' %>

    +

    <%= label_tag('attachments[1][file]', l(:label_attachment_plural))%><%= render :partial => 'attachments/form' %>

    <% end %> <% if @issue.new_record? && User.current.allowed_to?(:add_issue_watchers, @project) -%> -

    +

    <% @issue.project.users.sort.each do |user| -%> <% end -%> diff -r 09b1d4349da3 -r 371eac10df0b app/views/issues/bulk_edit.rhtml --- a/app/views/issues/bulk_edit.rhtml Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/issues/bulk_edit.rhtml Wed Nov 24 12:20:08 2010 +0000 @@ -11,7 +11,7 @@

    - <%= select_tag('issue[tracker_id]', "" + options_from_collection_for_select(@project.trackers, :id, :name)) %> + <%= select_tag('issue[tracker_id]', "" + options_from_collection_for_select(@trackers, :id, :name)) %>

    <% if @available_statuses.any? %>

    @@ -27,20 +27,25 @@ <%= select_tag('issue[assigned_to_id]', content_tag('option', l(:label_no_change_option), :value => '') + content_tag('option', l(:label_nobody), :value => 'none') + - options_from_collection_for_select(@project.assignable_users, :id, :name)) %> + options_from_collection_for_select(@assignables, :id, :name)) %>

    +<% if @project %>

    <%= select_tag('issue[category_id]', content_tag('option', l(:label_no_change_option), :value => '') + content_tag('option', l(:label_none), :value => 'none') + options_from_collection_for_select(@project.issue_categories, :id, :name)) %>

    +<% end %> +<% #TODO: allow editing versions when multiple projects %> +<% if @project %>

    <%= select_tag('issue[fixed_version_id]', content_tag('option', l(:label_no_change_option), :value => '') + content_tag('option', l(:label_none), :value => 'none') + version_options_for_select(@project.shared_versions.open)) %>

    +<% end %> <% @custom_fields.each do |custom_field| %>

    <%= custom_field_tag_for_bulk_edit('issue', custom_field) %>

    diff -r 09b1d4349da3 -r 371eac10df0b app/views/issues/new.rhtml --- a/app/views/issues/new.rhtml Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/issues/new.rhtml Wed Nov 24 12:20:08 2010 +0000 @@ -1,7 +1,7 @@

    <%=l(:label_issue_new)%>

    <% labelled_tabular_form_for :issue, @issue, :url => {:controller => 'issues', :action => 'create', :project_id => @project}, - :html => {:multipart => true, :id => 'issue-form'} do |f| %> + :html => {:multipart => true, :id => 'issue-form', :class => 'tabular new-issue-form'} do |f| %> <%= error_messages_for 'issue' %>
    <%= render :partial => 'issues/form', :locals => {:f => f} %> diff -r 09b1d4349da3 -r 371eac10df0b app/views/issues/show.rhtml --- a/app/views/issues/show.rhtml Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/issues/show.rhtml Wed Nov 24 12:20:08 2010 +0000 @@ -32,7 +32,7 @@
    <%=l(:field_category)%>:<%=h @issue.category ? @issue.category.name : "-" %><%=l(:label_spent_time)%>:<%= @issue.spent_hours > 0 ? (link_to l_hours(@issue.spent_hours), {:controller => 'timelog', :action => 'details', :project_id => @project, :issue_id => @issue}) : "-" %><%= @issue.spent_hours > 0 ? (link_to l_hours(@issue.spent_hours), {:controller => 'timelog', :action => 'index', :project_id => @project, :issue_id => @issue}) : "-" %>
    + +<% if @issue.description? || @issue.attachments.any? -%>
    -
    -<%= link_to_remote_if_authorized(l(:button_quote), { :url => {:action => 'reply', :id => @issue} }, :class => 'icon icon-comment') unless @issue.description.blank? %> +<%= link_to_remote_if_authorized(l(:button_quote), { :url => {:action => 'reply', :id => @issue} }, :class => 'icon icon-comment') if @issue.description? %>
    -

    <%=l(:field_description)%>

    <%= textilizable @issue, :description, :attachments => @issue.attachments %>
    <%= link_to_attachments @issue %> +<% end -%> <%= call_hook(:view_issues_show_description_bottom, :issue => @issue) %> diff -r 09b1d4349da3 -r 371eac10df0b app/views/journals/.svn/entries --- a/app/views/journals/.svn/entries Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/journals/.svn/entries Wed Nov 24 12:20:08 2010 +0000 @@ -1,7 +1,7 @@ 10 dir -4173 +4411 http://redmine.rubyforge.org/svn/trunk/app/views/journals http://redmine.rubyforge.org/svn diff -r 09b1d4349da3 -r 371eac10df0b app/views/layouts/.svn/all-wcprops --- a/app/views/layouts/.svn/all-wcprops Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/layouts/.svn/all-wcprops Wed Nov 24 12:20:08 2010 +0000 @@ -1,7 +1,7 @@ K 25 svn:wc:ra_dav:version-url V 42 -/svn/!svn/ver/4005/trunk/app/views/layouts +/svn/!svn/ver/4362/trunk/app/views/layouts END base.rhtml K 25 @@ -13,13 +13,13 @@ K 25 svn:wc:ra_dav:version-url V 64 -/svn/!svn/ver/2887/trunk/app/views/layouts/mailer.text.plain.erb +/svn/!svn/ver/4362/trunk/app/views/layouts/mailer.text.plain.erb END mailer.text.html.erb K 25 svn:wc:ra_dav:version-url V 63 -/svn/!svn/ver/2887/trunk/app/views/layouts/mailer.text.html.erb +/svn/!svn/ver/4362/trunk/app/views/layouts/mailer.text.html.erb END admin.rhtml K 25 diff -r 09b1d4349da3 -r 371eac10df0b app/views/layouts/.svn/entries --- a/app/views/layouts/.svn/entries Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/layouts/.svn/entries Wed Nov 24 12:20:08 2010 +0000 @@ -1,15 +1,15 @@ 10 dir -4173 +4411 http://redmine.rubyforge.org/svn/trunk/app/views/layouts http://redmine.rubyforge.org/svn -2010-08-19T16:57:44.231882Z -4005 -winterheart +2010-11-02T19:00:36.834304Z +4362 +edavis10 @@ -66,10 +66,10 @@ -2010-09-23T14:37:44.583752Z -9631cc13a2471d1bdde52f4d8cee6f18 -2009-09-13T17:14:35.707881Z -2887 +2010-11-19T13:04:48.184855Z +490231bbc42932a0f9e1735a94d06260 +2010-11-02T19:00:36.834304Z +4362 edavis10 has-props @@ -92,7 +92,7 @@ -46 +75 mailer.text.html.erb file @@ -100,10 +100,10 @@ -2010-09-23T14:37:44.583752Z -bd4792711b615ebda6bb50b1f1158f0c -2009-09-13T17:14:35.707881Z -2887 +2010-11-19T13:04:48.184855Z +5073a425d4e7896c725996f9cf35f74b +2010-11-02T19:00:36.834304Z +4362 edavis10 has-props @@ -126,7 +126,7 @@ -646 +761 admin.rhtml file diff -r 09b1d4349da3 -r 371eac10df0b app/views/layouts/.svn/text-base/mailer.text.html.erb.svn-base --- a/app/views/layouts/.svn/text-base/mailer.text.html.erb.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/layouts/.svn/text-base/mailer.text.html.erb.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -25,6 +25,7 @@ +<%= Redmine::WikiFormatting.to_html(Setting.text_formatting, Setting.emails_header) %> <%= yield %>
    <%= Redmine::WikiFormatting.to_html(Setting.text_formatting, Setting.emails_footer) %> diff -r 09b1d4349da3 -r 371eac10df0b app/views/layouts/.svn/text-base/mailer.text.plain.erb.svn-base --- a/app/views/layouts/.svn/text-base/mailer.text.plain.erb.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/layouts/.svn/text-base/mailer.text.plain.erb.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -1,3 +1,4 @@ +<%= Setting.emails_header %> <%= yield %> -- <%= Setting.emails_footer %> diff -r 09b1d4349da3 -r 371eac10df0b app/views/layouts/mailer.text.html.erb --- a/app/views/layouts/mailer.text.html.erb Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/layouts/mailer.text.html.erb Wed Nov 24 12:20:08 2010 +0000 @@ -25,6 +25,7 @@ +<%= Redmine::WikiFormatting.to_html(Setting.text_formatting, Setting.emails_header) %> <%= yield %>
    <%= Redmine::WikiFormatting.to_html(Setting.text_formatting, Setting.emails_footer) %> diff -r 09b1d4349da3 -r 371eac10df0b app/views/layouts/mailer.text.plain.erb --- a/app/views/layouts/mailer.text.plain.erb Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/layouts/mailer.text.plain.erb Wed Nov 24 12:20:08 2010 +0000 @@ -1,3 +1,4 @@ +<%= Setting.emails_header %> <%= yield %> -- <%= Setting.emails_footer %> diff -r 09b1d4349da3 -r 371eac10df0b app/views/ldap_auth_sources/.svn/entries --- a/app/views/ldap_auth_sources/.svn/entries Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/ldap_auth_sources/.svn/entries Wed Nov 24 12:20:08 2010 +0000 @@ -1,7 +1,7 @@ 10 dir -4173 +4411 http://redmine.rubyforge.org/svn/trunk/app/views/ldap_auth_sources http://redmine.rubyforge.org/svn diff -r 09b1d4349da3 -r 371eac10df0b app/views/mailer/.svn/all-wcprops --- a/app/views/mailer/.svn/all-wcprops Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/mailer/.svn/all-wcprops Wed Nov 24 12:20:08 2010 +0000 @@ -1,13 +1,13 @@ K 25 svn:wc:ra_dav:version-url V 41 -/svn/!svn/ver/3452/trunk/app/views/mailer +/svn/!svn/ver/4296/trunk/app/views/mailer END wiki_content_added.text.plain.rhtml K 25 svn:wc:ra_dav:version-url V 77 -/svn/!svn/ver/2749/trunk/app/views/mailer/wiki_content_added.text.plain.rhtml +/svn/!svn/ver/4296/trunk/app/views/mailer/wiki_content_added.text.plain.rhtml END account_activated.text.plain.rhtml K 25 @@ -79,7 +79,7 @@ K 25 svn:wc:ra_dav:version-url V 76 -/svn/!svn/ver/2749/trunk/app/views/mailer/wiki_content_added.text.html.rhtml +/svn/!svn/ver/4296/trunk/app/views/mailer/wiki_content_added.text.html.rhtml END test.text.plain.rhtml K 25 @@ -117,18 +117,18 @@ V 64 /svn/!svn/ver/3452/trunk/app/views/mailer/_issue_text_html.rhtml END +attachments_added.text.html.rhtml +K 25 +svn:wc:ra_dav:version-url +V 75 +/svn/!svn/ver/3452/trunk/app/views/mailer/attachments_added.text.html.rhtml +END news_added.text.plain.rhtml K 25 svn:wc:ra_dav:version-url V 68 /svn/!svn/ver/877/trunk/app/views/mailer/news_added.text.plain.rhtml END -attachments_added.text.html.rhtml -K 25 -svn:wc:ra_dav:version-url -V 75 -/svn/!svn/ver/3452/trunk/app/views/mailer/attachments_added.text.html.rhtml -END news_added.text.html.rhtml K 25 svn:wc:ra_dav:version-url @@ -141,41 +141,35 @@ V 72 /svn/!svn/ver/877/trunk/app/views/mailer/document_added.text.plain.rhtml END +issue_add.text.plain.rhtml +K 25 +svn:wc:ra_dav:version-url +V 68 +/svn/!svn/ver/2493/trunk/app/views/mailer/issue_add.text.plain.rhtml +END document_added.text.html.rhtml K 25 svn:wc:ra_dav:version-url V 72 /svn/!svn/ver/3452/trunk/app/views/mailer/document_added.text.html.rhtml END -issue_add.text.plain.rhtml -K 25 -svn:wc:ra_dav:version-url -V 68 -/svn/!svn/ver/2493/trunk/app/views/mailer/issue_add.text.plain.rhtml -END account_information.text.plain.rhtml K 25 svn:wc:ra_dav:version-url V 77 /svn/!svn/ver/877/trunk/app/views/mailer/account_information.text.plain.rhtml END -message_posted.text.plain.rhtml -K 25 -svn:wc:ra_dav:version-url -V 72 -/svn/!svn/ver/932/trunk/app/views/mailer/message_posted.text.plain.rhtml -END account_information.text.html.rhtml K 25 svn:wc:ra_dav:version-url V 77 /svn/!svn/ver/3452/trunk/app/views/mailer/account_information.text.html.rhtml END -wiki_content_updated.text.plain.rhtml +message_posted.text.plain.rhtml K 25 svn:wc:ra_dav:version-url -V 79 -/svn/!svn/ver/2749/trunk/app/views/mailer/wiki_content_updated.text.plain.rhtml +V 72 +/svn/!svn/ver/932/trunk/app/views/mailer/message_posted.text.plain.rhtml END lost_password.text.plain.rhtml K 25 @@ -183,11 +177,17 @@ V 72 /svn/!svn/ver/1683/trunk/app/views/mailer/lost_password.text.plain.rhtml END +wiki_content_updated.text.plain.rhtml +K 25 +svn:wc:ra_dav:version-url +V 79 +/svn/!svn/ver/4296/trunk/app/views/mailer/wiki_content_updated.text.plain.rhtml +END wiki_content_updated.text.html.rhtml K 25 svn:wc:ra_dav:version-url V 78 -/svn/!svn/ver/2749/trunk/app/views/mailer/wiki_content_updated.text.html.rhtml +/svn/!svn/ver/4296/trunk/app/views/mailer/wiki_content_updated.text.html.rhtml END lost_password.text.html.rhtml K 25 diff -r 09b1d4349da3 -r 371eac10df0b app/views/mailer/.svn/entries --- a/app/views/mailer/.svn/entries Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/mailer/.svn/entries Wed Nov 24 12:20:08 2010 +0000 @@ -1,15 +1,15 @@ 10 dir -4173 +4411 http://redmine.rubyforge.org/svn/trunk/app/views/mailer http://redmine.rubyforge.org/svn -2010-02-18T19:13:38.135448Z -3452 -jplang +2010-10-27T16:27:06.240747Z +4296 +edavis10 @@ -32,11 +32,11 @@ -2010-09-23T14:37:44.607738Z -882607e6f82c2c4e7db74136ee974a5b -2009-05-17T09:55:13.601447Z -2749 -jplang +2010-11-19T13:04:49.420968Z +1729c597befa0c9411266eb9d1c5b577 +2010-10-27T16:27:06.240747Z +4296 +edavis10 has-props @@ -58,7 +58,7 @@ -197 +195 account_activated.text.plain.rhtml file @@ -440,11 +440,11 @@ -2010-09-23T14:37:44.607738Z -21acbb8688d350bccc49d0b9f0fa7964 -2009-05-17T09:55:13.601447Z -2749 -jplang +2010-11-19T13:04:49.420968Z +37e05984b98664e4b97c26b51196f9ab +2010-10-27T16:27:06.240747Z +4296 +edavis10 has-props @@ -466,7 +466,7 @@ -225 +223 test.text.plain.rhtml file @@ -672,6 +672,40 @@ 629 +attachments_added.text.html.rhtml +file + + + + +2010-09-23T14:37:44.603754Z +db9ef17343824d59b7a19db7036ee2f1 +2010-02-18T19:13:38.135448Z +3452 +jplang +has-props + + + + + + + + + + + + + + + + + + + + +144 + news_added.text.plain.rhtml file @@ -706,40 +740,6 @@ 87 -attachments_added.text.html.rhtml -file - - - - -2010-09-23T14:37:44.603754Z -db9ef17343824d59b7a19db7036ee2f1 -2010-02-18T19:13:38.135448Z -3452 -jplang -has-props - - - - - - - - - - - - - - - - - - - - -144 - news_added.text.html.rhtml file @@ -808,6 +808,40 @@ 107 +issue_add.text.plain.rhtml +file + + + + +2010-09-23T14:37:44.603754Z +52a0f774acd5b7aeeb3768de943af901 +2009-02-21T11:04:50.579477Z +2493 +jplang +has-props + + + + + + + + + + + + + + + + + + + + +224 + document_added.text.html.rhtml file @@ -842,40 +876,6 @@ 163 -issue_add.text.plain.rhtml -file - - - - -2010-09-23T14:37:44.603754Z -52a0f774acd5b7aeeb3768de943af901 -2009-02-21T11:04:50.579477Z -2493 -jplang -has-props - - - - - - - - - - - - - - - - - - - - -224 - account_information.text.plain.rhtml file @@ -910,6 +910,40 @@ 295 +account_information.text.html.rhtml +file + + + + +2010-09-23T14:37:44.603754Z +e7e91d7f18dd1547cfebafdf4822a18f +2010-02-18T19:13:38.135448Z +3452 +jplang +has-props + + + + + + + + + + + + + + + + + + + + +368 + message_posted.text.plain.rhtml file @@ -944,74 +978,6 @@ 68 -account_information.text.html.rhtml -file - - - - -2010-09-23T14:37:44.603754Z -e7e91d7f18dd1547cfebafdf4822a18f -2010-02-18T19:13:38.135448Z -3452 -jplang -has-props - - - - - - - - - - - - - - - - - - - - -368 - -wiki_content_updated.text.plain.rhtml -file - - - - -2010-09-23T14:37:44.607738Z -801160f7633227c04b4a3a8c249feeff -2009-05-17T09:55:13.601447Z -2749 -jplang -has-props - - - - - - - - - - - - - - - - - - - - -290 - lost_password.text.plain.rhtml file @@ -1046,6 +1012,40 @@ 97 +wiki_content_updated.text.plain.rhtml +file + + + + +2010-11-19T13:04:49.420968Z +0cb005c22ad144fdbe29238b0080f28b +2010-10-27T16:27:06.240747Z +4296 +edavis10 +has-props + + + + + + + + + + + + + + + + + + + + +288 + lost_password.text.html.rhtml file @@ -1086,11 +1086,11 @@ -2010-09-23T14:37:44.607738Z -f7cca2b19b22b64036fdba45803b6805 -2009-05-17T09:55:13.601447Z -2749 -jplang +2010-11-19T13:04:49.420968Z +f35cf0d09dd393a255db2d428a3d30f0 +2010-10-27T16:27:06.240747Z +4296 +edavis10 has-props @@ -1112,5 +1112,5 @@ -320 +318 diff -r 09b1d4349da3 -r 371eac10df0b app/views/mailer/.svn/text-base/wiki_content_added.text.html.rhtml.svn-base --- a/app/views/mailer/.svn/text-base/wiki_content_added.text.html.rhtml.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/mailer/.svn/text-base/wiki_content_added.text.html.rhtml.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -1,3 +1,3 @@ -

    <%= l(:mail_body_wiki_content_added, :page => link_to(h(@wiki_content.page.pretty_title), @wiki_content_url), +

    <%= l(:mail_body_wiki_content_added, :id => link_to(h(@wiki_content.page.pretty_title), @wiki_content_url), :author => h(@wiki_content.author)) %>
    <%=h @wiki_content.comments %>

    diff -r 09b1d4349da3 -r 371eac10df0b app/views/mailer/.svn/text-base/wiki_content_added.text.plain.rhtml.svn-base --- a/app/views/mailer/.svn/text-base/wiki_content_added.text.plain.rhtml.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/mailer/.svn/text-base/wiki_content_added.text.plain.rhtml.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -1,4 +1,4 @@ -<%= l(:mail_body_wiki_content_added, :page => h(@wiki_content.page.pretty_title), +<%= l(:mail_body_wiki_content_added, :id => h(@wiki_content.page.pretty_title), :author => h(@wiki_content.author)) %> <%= @wiki_content.comments %> diff -r 09b1d4349da3 -r 371eac10df0b app/views/mailer/.svn/text-base/wiki_content_updated.text.html.rhtml.svn-base --- a/app/views/mailer/.svn/text-base/wiki_content_updated.text.html.rhtml.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/mailer/.svn/text-base/wiki_content_updated.text.html.rhtml.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -1,4 +1,4 @@ -

    <%= l(:mail_body_wiki_content_updated, :page => link_to(h(@wiki_content.page.pretty_title), @wiki_content_url), +

    <%= l(:mail_body_wiki_content_updated, :id => link_to(h(@wiki_content.page.pretty_title), @wiki_content_url), :author => h(@wiki_content.author)) %>
    <%=h @wiki_content.comments %>

    diff -r 09b1d4349da3 -r 371eac10df0b app/views/mailer/.svn/text-base/wiki_content_updated.text.plain.rhtml.svn-base --- a/app/views/mailer/.svn/text-base/wiki_content_updated.text.plain.rhtml.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/mailer/.svn/text-base/wiki_content_updated.text.plain.rhtml.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -1,4 +1,4 @@ -<%= l(:mail_body_wiki_content_updated, :page => h(@wiki_content.page.pretty_title), +<%= l(:mail_body_wiki_content_updated, :id => h(@wiki_content.page.pretty_title), :author => h(@wiki_content.author)) %> <%= @wiki_content.comments %> diff -r 09b1d4349da3 -r 371eac10df0b app/views/mailer/wiki_content_added.text.html.rhtml --- a/app/views/mailer/wiki_content_added.text.html.rhtml Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/mailer/wiki_content_added.text.html.rhtml Wed Nov 24 12:20:08 2010 +0000 @@ -1,3 +1,3 @@ -

    <%= l(:mail_body_wiki_content_added, :page => link_to(h(@wiki_content.page.pretty_title), @wiki_content_url), +

    <%= l(:mail_body_wiki_content_added, :id => link_to(h(@wiki_content.page.pretty_title), @wiki_content_url), :author => h(@wiki_content.author)) %>
    <%=h @wiki_content.comments %>

    diff -r 09b1d4349da3 -r 371eac10df0b app/views/mailer/wiki_content_added.text.plain.rhtml --- a/app/views/mailer/wiki_content_added.text.plain.rhtml Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/mailer/wiki_content_added.text.plain.rhtml Wed Nov 24 12:20:08 2010 +0000 @@ -1,4 +1,4 @@ -<%= l(:mail_body_wiki_content_added, :page => h(@wiki_content.page.pretty_title), +<%= l(:mail_body_wiki_content_added, :id => h(@wiki_content.page.pretty_title), :author => h(@wiki_content.author)) %> <%= @wiki_content.comments %> diff -r 09b1d4349da3 -r 371eac10df0b app/views/mailer/wiki_content_updated.text.html.rhtml --- a/app/views/mailer/wiki_content_updated.text.html.rhtml Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/mailer/wiki_content_updated.text.html.rhtml Wed Nov 24 12:20:08 2010 +0000 @@ -1,4 +1,4 @@ -

    <%= l(:mail_body_wiki_content_updated, :page => link_to(h(@wiki_content.page.pretty_title), @wiki_content_url), +

    <%= l(:mail_body_wiki_content_updated, :id => link_to(h(@wiki_content.page.pretty_title), @wiki_content_url), :author => h(@wiki_content.author)) %>
    <%=h @wiki_content.comments %>

    diff -r 09b1d4349da3 -r 371eac10df0b app/views/mailer/wiki_content_updated.text.plain.rhtml --- a/app/views/mailer/wiki_content_updated.text.plain.rhtml Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/mailer/wiki_content_updated.text.plain.rhtml Wed Nov 24 12:20:08 2010 +0000 @@ -1,4 +1,4 @@ -<%= l(:mail_body_wiki_content_updated, :page => h(@wiki_content.page.pretty_title), +<%= l(:mail_body_wiki_content_updated, :id => h(@wiki_content.page.pretty_title), :author => h(@wiki_content.author)) %> <%= @wiki_content.comments %> diff -r 09b1d4349da3 -r 371eac10df0b app/views/members/.svn/entries --- a/app/views/members/.svn/entries Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/members/.svn/entries Wed Nov 24 12:20:08 2010 +0000 @@ -1,7 +1,7 @@ 10 dir -4173 +4411 http://redmine.rubyforge.org/svn/trunk/app/views/members http://redmine.rubyforge.org/svn diff -r 09b1d4349da3 -r 371eac10df0b app/views/messages/.svn/entries --- a/app/views/messages/.svn/entries Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/messages/.svn/entries Wed Nov 24 12:20:08 2010 +0000 @@ -1,7 +1,7 @@ 10 dir -4173 +4411 http://redmine.rubyforge.org/svn/trunk/app/views/messages http://redmine.rubyforge.org/svn diff -r 09b1d4349da3 -r 371eac10df0b app/views/my/.svn/all-wcprops --- a/app/views/my/.svn/all-wcprops Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/my/.svn/all-wcprops Wed Nov 24 12:20:08 2010 +0000 @@ -1,13 +1,13 @@ K 25 svn:wc:ra_dav:version-url V 37 -/svn/!svn/ver/3775/trunk/app/views/my +/svn/!svn/ver/4380/trunk/app/views/my END account.rhtml K 25 svn:wc:ra_dav:version-url V 51 -/svn/!svn/ver/3745/trunk/app/views/my/account.rhtml +/svn/!svn/ver/4223/trunk/app/views/my/account.rhtml END page.rhtml K 25 @@ -37,5 +37,5 @@ K 25 svn:wc:ra_dav:version-url V 55 -/svn/!svn/ver/3755/trunk/app/views/my/page_layout.rhtml +/svn/!svn/ver/4380/trunk/app/views/my/page_layout.rhtml END diff -r 09b1d4349da3 -r 371eac10df0b app/views/my/.svn/entries --- a/app/views/my/.svn/entries Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/my/.svn/entries Wed Nov 24 12:20:08 2010 +0000 @@ -1,15 +1,15 @@ 10 dir -4173 +4411 http://redmine.rubyforge.org/svn/trunk/app/views/my http://redmine.rubyforge.org/svn -2010-06-19T16:50:13.340830Z -3775 -edavis10 +2010-11-07T12:36:19.797484Z +4380 +jplang @@ -32,10 +32,10 @@ -2010-09-23T14:37:44.619750Z -4fb90e7d5633e4ec24100c38acdad03d -2010-05-23T03:16:37.499264Z -3745 +2010-11-19T13:04:47.012855Z +746c4ac2d5bc111d91747aa0b0c54a5a +2010-09-28T22:13:06.534232Z +4223 edavis10 has-props @@ -58,7 +58,7 @@ -2730 +1561 page.rhtml file @@ -205,11 +205,11 @@ -2010-09-23T14:37:44.623783Z -c1260ac20d704693b8748cef7b7c58f9 -2010-05-26T21:52:03.637924Z -3755 -edavis10 +2010-11-19T13:04:47.012855Z +afbc3db612a251e1fcb34498f27c50b8 +2010-11-07T12:36:19.797484Z +4380 +jplang has-props @@ -231,5 +231,5 @@ -4115 +4274 diff -r 09b1d4349da3 -r 371eac10df0b app/views/my/.svn/text-base/account.rhtml.svn-base --- a/app/views/my/.svn/text-base/account.rhtml.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/my/.svn/text-base/account.rhtml.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -32,24 +32,12 @@

    <%=l(:field_mail_notification)%>

    -<%= select_tag 'notification_option', options_for_select(@notification_options, @notification_option), - :onchange => 'if ($("notification_option").value == "selected") {Element.show("notified-projects")} else {Element.hide("notified-projects")}' %> -<% content_tag 'div', :id => 'notified-projects', :style => (@notification_option == 'selected' ? '' : 'display:none;') do %> -

    <% User.current.projects.each do |project| %> -
    -<% end %>

    -

    <%= l(:text_user_mail_option) %>

    -<% end %> -

    +<%= render :partial => 'users/mail_notifications' %>

    <%=l(:label_preferences)%>

    -<% fields_for :pref, @user.pref, :builder => TabularFormBuilder, :lang => current_language do |pref_fields| %> -

    <%= pref_fields.check_box :hide_mail %>

    -

    <%= pref_fields.select :time_zone, ActiveSupport::TimeZone.all.collect {|z| [ z.to_s, z.name ]}, :include_blank => true %>

    -

    <%= pref_fields.select :comments_sorting, [[l(:label_chronological_order), 'asc'], [l(:label_reverse_chronological_order), 'desc']] %>

    -<% end %> +<%= render :partial => 'users/preferences' %>
    diff -r 09b1d4349da3 -r 371eac10df0b app/views/my/.svn/text-base/page_layout.rhtml.svn-base --- a/app/views/my/.svn/text-base/page_layout.rhtml.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/my/.svn/text-base/page_layout.rhtml.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -5,9 +5,9 @@ Sortable.destroy('list-left'); Sortable.destroy('list-right'); - Sortable.create("list-top", {constraint:false, containment:['list-top','list-left','list-right'], dropOnEmpty:true, handle:'handle', onUpdate:function(){new Ajax.Request('/my/order_blocks?group=top', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize("list-top")})}, only:'mypage-box', tag:'div'}) - Sortable.create("list-left", {constraint:false, containment:['list-top','list-left','list-right'], dropOnEmpty:true, handle:'handle', onUpdate:function(){new Ajax.Request('/my/order_blocks?group=left', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize("list-left")})}, only:'mypage-box', tag:'div'}) - Sortable.create("list-right", {constraint:false, containment:['list-top','list-left','list-right'], dropOnEmpty:true, handle:'handle', onUpdate:function(){new Ajax.Request('/my/order_blocks?group=right', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize("list-right")})}, only:'mypage-box', tag:'div'}) + Sortable.create("list-top", {constraint:false, containment:['list-top','list-left','list-right'], dropOnEmpty:true, handle:'handle', onUpdate:function(){new Ajax.Request('<%= url_for(:controller => 'my', :action => 'order_blocks', :group => 'top') %>', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize("list-top")})}, only:'mypage-box', tag:'div'}) + Sortable.create("list-left", {constraint:false, containment:['list-top','list-left','list-right'], dropOnEmpty:true, handle:'handle', onUpdate:function(){new Ajax.Request('<%= url_for(:controller => 'my', :action => 'order_blocks', :group => 'left') %>', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize("list-left")})}, only:'mypage-box', tag:'div'}) + Sortable.create("list-right", {constraint:false, containment:['list-top','list-left','list-right'], dropOnEmpty:true, handle:'handle', onUpdate:function(){new Ajax.Request('<%= url_for(:controller => 'my', :action => 'order_blocks', :group => 'right') %>', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize("list-right")})}, only:'mypage-box', tag:'div'}) } function updateSelect() { diff -r 09b1d4349da3 -r 371eac10df0b app/views/my/account.rhtml --- a/app/views/my/account.rhtml Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/my/account.rhtml Wed Nov 24 12:20:08 2010 +0000 @@ -32,24 +32,12 @@

    <%=l(:field_mail_notification)%>

    -<%= select_tag 'notification_option', options_for_select(@notification_options, @notification_option), - :onchange => 'if ($("notification_option").value == "selected") {Element.show("notified-projects")} else {Element.hide("notified-projects")}' %> -<% content_tag 'div', :id => 'notified-projects', :style => (@notification_option == 'selected' ? '' : 'display:none;') do %> -

    <% User.current.projects.each do |project| %> -
    -<% end %>

    -

    <%= l(:text_user_mail_option) %>

    -<% end %> -

    +<%= render :partial => 'users/mail_notifications' %>

    <%=l(:label_preferences)%>

    -<% fields_for :pref, @user.pref, :builder => TabularFormBuilder, :lang => current_language do |pref_fields| %> -

    <%= pref_fields.check_box :hide_mail %>

    -

    <%= pref_fields.select :time_zone, ActiveSupport::TimeZone.all.collect {|z| [ z.to_s, z.name ]}, :include_blank => true %>

    -

    <%= pref_fields.select :comments_sorting, [[l(:label_chronological_order), 'asc'], [l(:label_reverse_chronological_order), 'desc']] %>

    -<% end %> +<%= render :partial => 'users/preferences' %>
    diff -r 09b1d4349da3 -r 371eac10df0b app/views/my/blocks/.svn/all-wcprops --- a/app/views/my/blocks/.svn/all-wcprops Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/my/blocks/.svn/all-wcprops Wed Nov 24 12:20:08 2010 +0000 @@ -1,7 +1,7 @@ K 25 svn:wc:ra_dav:version-url V 44 -/svn/!svn/ver/3734/trunk/app/views/my/blocks +/svn/!svn/ver/4259/trunk/app/views/my/blocks END _issueswatched.rhtml K 25 @@ -31,7 +31,7 @@ K 25 svn:wc:ra_dav:version-url V 59 -/svn/!svn/ver/3734/trunk/app/views/my/blocks/_timelog.rhtml +/svn/!svn/ver/4259/trunk/app/views/my/blocks/_timelog.rhtml END _documents.rhtml K 25 diff -r 09b1d4349da3 -r 371eac10df0b app/views/my/blocks/.svn/entries --- a/app/views/my/blocks/.svn/entries Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/my/blocks/.svn/entries Wed Nov 24 12:20:08 2010 +0000 @@ -1,15 +1,15 @@ 10 dir -4173 +4411 http://redmine.rubyforge.org/svn/trunk/app/views/my/blocks http://redmine.rubyforge.org/svn -2010-05-09T11:19:15.980195Z -3734 -jplang +2010-10-15T23:37:01.382819Z +4259 +edavis10 @@ -168,11 +168,11 @@ -2010-09-23T14:37:44.623783Z -4dfff03583b1da52a7f2fb8d20398928 -2010-05-09T11:19:15.980195Z -3734 -jplang +2010-11-19T13:04:47.008792Z +2ba11e15a7f15f88fe061979d921b59d +2010-10-15T23:37:01.382819Z +4259 +edavis10 has-props @@ -194,7 +194,7 @@ -2282 +2284 _documents.rhtml file diff -r 09b1d4349da3 -r 371eac10df0b app/views/my/blocks/.svn/text-base/_timelog.rhtml.svn-base --- a/app/views/my/blocks/.svn/text-base/_timelog.rhtml.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/my/blocks/.svn/text-base/_timelog.rhtml.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -40,7 +40,7 @@ :title => l(:button_edit) %> <%= link_to image_tag('delete.png'), {:controller => 'timelog', :action => 'destroy', :id => entry}, :confirm => l(:text_are_you_sure), - :method => :post, + :method => :delete, :title => l(:button_delete) %> <% end -%> diff -r 09b1d4349da3 -r 371eac10df0b app/views/my/blocks/_timelog.rhtml --- a/app/views/my/blocks/_timelog.rhtml Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/my/blocks/_timelog.rhtml Wed Nov 24 12:20:08 2010 +0000 @@ -40,7 +40,7 @@ :title => l(:button_edit) %> <%= link_to image_tag('delete.png'), {:controller => 'timelog', :action => 'destroy', :id => entry}, :confirm => l(:text_are_you_sure), - :method => :post, + :method => :delete, :title => l(:button_delete) %> <% end -%> diff -r 09b1d4349da3 -r 371eac10df0b app/views/my/page_layout.rhtml --- a/app/views/my/page_layout.rhtml Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/my/page_layout.rhtml Wed Nov 24 12:20:08 2010 +0000 @@ -5,9 +5,9 @@ Sortable.destroy('list-left'); Sortable.destroy('list-right'); - Sortable.create("list-top", {constraint:false, containment:['list-top','list-left','list-right'], dropOnEmpty:true, handle:'handle', onUpdate:function(){new Ajax.Request('/my/order_blocks?group=top', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize("list-top")})}, only:'mypage-box', tag:'div'}) - Sortable.create("list-left", {constraint:false, containment:['list-top','list-left','list-right'], dropOnEmpty:true, handle:'handle', onUpdate:function(){new Ajax.Request('/my/order_blocks?group=left', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize("list-left")})}, only:'mypage-box', tag:'div'}) - Sortable.create("list-right", {constraint:false, containment:['list-top','list-left','list-right'], dropOnEmpty:true, handle:'handle', onUpdate:function(){new Ajax.Request('/my/order_blocks?group=right', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize("list-right")})}, only:'mypage-box', tag:'div'}) + Sortable.create("list-top", {constraint:false, containment:['list-top','list-left','list-right'], dropOnEmpty:true, handle:'handle', onUpdate:function(){new Ajax.Request('<%= url_for(:controller => 'my', :action => 'order_blocks', :group => 'top') %>', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize("list-top")})}, only:'mypage-box', tag:'div'}) + Sortable.create("list-left", {constraint:false, containment:['list-top','list-left','list-right'], dropOnEmpty:true, handle:'handle', onUpdate:function(){new Ajax.Request('<%= url_for(:controller => 'my', :action => 'order_blocks', :group => 'left') %>', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize("list-left")})}, only:'mypage-box', tag:'div'}) + Sortable.create("list-right", {constraint:false, containment:['list-top','list-left','list-right'], dropOnEmpty:true, handle:'handle', onUpdate:function(){new Ajax.Request('<%= url_for(:controller => 'my', :action => 'order_blocks', :group => 'right') %>', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize("list-right")})}, only:'mypage-box', tag:'div'}) } function updateSelect() { diff -r 09b1d4349da3 -r 371eac10df0b app/views/news/.svn/all-wcprops --- a/app/views/news/.svn/all-wcprops Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/news/.svn/all-wcprops Wed Nov 24 12:20:08 2010 +0000 @@ -1,19 +1,19 @@ K 25 svn:wc:ra_dav:version-url V 39 -/svn/!svn/ver/4172/trunk/app/views/news +/svn/!svn/ver/4267/trunk/app/views/news END _news.rhtml K 25 svn:wc:ra_dav:version-url V 51 -/svn/!svn/ver/3924/trunk/app/views/news/_news.rhtml +/svn/!svn/ver/4214/trunk/app/views/news/_news.rhtml END show.rhtml K 25 svn:wc:ra_dav:version-url V 50 -/svn/!svn/ver/4172/trunk/app/views/news/show.rhtml +/svn/!svn/ver/4214/trunk/app/views/news/show.rhtml END _form.rhtml K 25 @@ -25,17 +25,17 @@ K 25 svn:wc:ra_dav:version-url V 50 -/svn/!svn/ver/4168/trunk/app/views/news/edit.rhtml +/svn/!svn/ver/4214/trunk/app/views/news/edit.rhtml END index.rhtml K 25 svn:wc:ra_dav:version-url V 51 -/svn/!svn/ver/4163/trunk/app/views/news/index.rhtml +/svn/!svn/ver/4267/trunk/app/views/news/index.rhtml END new.rhtml K 25 svn:wc:ra_dav:version-url V 49 -/svn/!svn/ver/4163/trunk/app/views/news/new.rhtml +/svn/!svn/ver/4214/trunk/app/views/news/new.rhtml END diff -r 09b1d4349da3 -r 371eac10df0b app/views/news/.svn/entries --- a/app/views/news/.svn/entries Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/news/.svn/entries Wed Nov 24 12:20:08 2010 +0000 @@ -1,15 +1,15 @@ 10 dir -4173 +4411 http://redmine.rubyforge.org/svn/trunk/app/views/news http://redmine.rubyforge.org/svn -2010-09-23T15:20:19.085385Z -4172 -edavis10 +2010-10-22T14:42:38.351679Z +4267 +jplang @@ -32,11 +32,11 @@ -2010-09-23T14:37:44.627781Z -8a95983c16121228642f685334a98b43 -2010-08-08T07:07:20.961363Z -3924 -jbbarth +2010-11-19T13:04:49.428894Z +2501c1cef884fd4a56abb3a4e736825f +2010-09-27T16:51:12.033537Z +4214 +edavis10 has-props @@ -58,7 +58,7 @@ -422 +384 show.rhtml file @@ -66,10 +66,10 @@ -2010-09-24T12:48:28.335892Z -fb4ed9638d6d3f708b140d2ccbc013de -2010-09-23T15:20:19.085385Z -4172 +2010-11-19T13:04:49.428894Z +c21730c749ee8533fadff9abbea6ffd8 +2010-09-27T16:51:12.033537Z +4214 edavis10 has-props @@ -92,7 +92,7 @@ -3025 +2897 _form.rhtml file @@ -134,10 +134,10 @@ -2010-09-24T12:48:28.335892Z -03cd635f1021f3f088155b7106062d98 -2010-09-21T15:20:37.706826Z -4168 +2010-11-19T13:04:49.432892Z +dd2c968c6b42916bff9b9e5de055e007 +2010-09-27T16:51:12.033537Z +4214 edavis10 has-props @@ -160,7 +160,7 @@ -771 +733 index.rhtml file @@ -168,11 +168,11 @@ -2010-09-24T12:48:28.335892Z -22895814fee421f0a7e4654059ede065 -2010-09-20T15:13:48.212792Z -4163 -edavis10 +2010-11-19T13:04:49.432892Z +764ec3719917039d0cac3d375ec819c4 +2010-10-22T14:42:38.351679Z +4267 +jplang has-props @@ -194,7 +194,7 @@ -2260 +2114 new.rhtml file @@ -202,10 +202,10 @@ -2010-09-24T12:48:28.335892Z -834dc30ca0d2f96a37f2ef2a60d9aaf9 -2010-09-20T15:13:48.212792Z -4163 +2010-11-19T13:04:49.432892Z +1e7f24dd1dc6a117b245a76174e4c8ae +2010-09-27T16:51:12.033537Z +4214 edavis10 has-props @@ -228,5 +228,5 @@ -733 +664 diff -r 09b1d4349da3 -r 371eac10df0b app/views/news/.svn/text-base/_news.rhtml.svn-base --- a/app/views/news/.svn/text-base/_news.rhtml.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/news/.svn/text-base/_news.rhtml.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -1,5 +1,5 @@

    <%= link_to_project(news.project) + ': ' unless @project %> -<%= link_to h(news.title), :controller => 'news', :action => 'show', :id => news %> +<%= link_to h(news.title), news_path(news) %> <%= "(#{l(:label_x_comments, :count => news.comments_count)})" if news.comments_count > 0 %>
    <% unless news.summary.blank? %><%=h news.summary %>
    <% end %> diff -r 09b1d4349da3 -r 371eac10df0b app/views/news/.svn/text-base/edit.rhtml.svn-base --- a/app/views/news/.svn/text-base/edit.rhtml.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/news/.svn/text-base/edit.rhtml.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -1,12 +1,12 @@

    <%=l(:label_news)%>

    -<% labelled_tabular_form_for :news, @news, :url => { :action => "update" }, +<% labelled_tabular_form_for :news, @news, :url => news_path(@news), :html => { :id => 'news-form', :method => :put } do |f| %> <%= render :partial => 'form', :locals => { :f => f } %> <%= submit_tag l(:button_save) %> <%= link_to_remote l(:label_preview), - { :url => { :controller => 'news', :action => 'preview', :project_id => @project }, - :method => 'post', + { :url => preview_news_path(:project_id => @project), + :method => 'get', :update => 'preview', :with => "Form.serialize('news-form')" }, :accesskey => accesskey(:preview) %> diff -r 09b1d4349da3 -r 371eac10df0b app/views/news/.svn/text-base/index.rhtml.svn-base --- a/app/views/news/.svn/text-base/index.rhtml.svn-base Thu Oct 21 11:19:14 2010 +0100 +++ b/app/views/news/.svn/text-base/index.rhtml.svn-base Wed Nov 24 12:20:08 2010 +0000 @@ -1,19 +1,19 @@
    -<%= link_to_if_authorized(l(:label_news_new), - {:controller => 'news', :action => 'new', :project_id => @project}, - :class => 'icon icon-add', - :onclick => 'Element.show("add-news"); Form.Element.focus("news_title"); return false;') if @project %> +<%= link_to(l(:label_news_new), + new_project_news_path(@project), + :class => 'icon icon-add', + :onclick => 'Element.show("add-news"); Form.Element.focus("news_title"); return false;') if @project && User.current.allowed_to?(:manage_news, @project) %>