Feature #5458 » 5458-use_time_in_issue_start_and_due_date_2.3_stable.diff
app/helpers/application_helper.rb Fri May 31 17:49:32 2013 +0200 | ||
---|---|---|
298 | 298 |
end |
299 | 299 |
end |
300 | 300 | |
301 |
def time_select_tag( name, stime ) |
|
302 |
out = '' |
|
303 |
time = stime.to_time(:utc) |
|
304 |
if time.nil? |
|
305 |
time = Date.today.to_time(:local) |
|
306 |
end |
|
307 |
time = time.in_time_zone(Time.zone.name) |
|
308 |
out << select_tag( |
|
309 |
"#{name}[hour]", |
|
310 |
options_for_select( (0..24).map{|i| [i,i] }, time.hour ), |
|
311 |
:style => 'min-width: 10px;max-width: 50px;' |
|
312 |
) |
|
313 |
out << ':' |
|
314 |
out << select_tag( |
|
315 |
"#{name}[minute]", |
|
316 |
options_for_select( (0..12).map{|i| [i*5,i*5] }, (time.min/5).round*5 ), |
|
317 |
:style => 'min-width: 10px;max-width: 50px;' |
|
318 |
) |
|
319 |
out << 'h' |
|
320 |
out |
|
321 |
end |
|
322 | ||
301 | 323 |
def project_tree_options_for_select(projects, options = {}) |
302 | 324 |
s = '' |
303 | 325 |
project_tree(projects) do |project, level| |
app/helpers/queries_helper.rb Fri May 31 17:49:32 2013 +0200 | ||
---|---|---|
100 | 100 |
h(value) |
101 | 101 |
end |
102 | 102 |
when 'Time' |
103 |
format_time(value) |
|
103 |
if ( column.name == :start_date or column.name == :due_date ) and |
|
104 |
( !issue.project.use_datetime_for_issues or value.strftime('%H%M')=='0000' ) |
|
105 |
format_date(value) |
|
106 |
else |
|
107 |
format_time(value) |
|
108 |
end |
|
104 | 109 |
when 'Date' |
105 | 110 |
format_date(value) |
106 | 111 |
when 'Fixnum' |
app/models/issue.rb Fri May 31 17:49:32 2013 +0200 | ||
---|---|---|
61 | 61 |
DONE_RATIO_OPTIONS = %w(issue_field issue_status) |
62 | 62 | |
63 | 63 |
attr_reader :current_journal |
64 |
attr_accessor :start_time |
|
65 |
attr_accessor :due_time |
|
66 | ||
64 | 67 |
delegate :notes, :notes=, :private_notes, :private_notes=, :to => :current_journal, :allow_nil => true |
65 | 68 | |
66 | 69 |
validates_presence_of :subject, :priority, :project, :tracker, :author, :status |
... | ... | |
68 | 71 |
validates_length_of :subject, :maximum => 255 |
69 | 72 |
validates_inclusion_of :done_ratio, :in => 0..100 |
70 | 73 |
validates :estimated_hours, :numericality => {:greater_than_or_equal_to => 0, :allow_nil => true, :message => :invalid} |
71 |
validates :start_date, :date => true |
|
72 |
validates :due_date, :date => true |
|
74 |
#validates :start_date, :date => true
|
|
75 |
#validates :due_date, :date => true
|
|
73 | 76 |
validate :validate_issue, :validate_required_fields |
74 | 77 | |
75 | 78 |
scope :visible, lambda {|*args| |
... | ... | |
90 | 93 |
ids.any? ? where(:fixed_version_id => ids) : where('1=0') |
91 | 94 |
} |
92 | 95 | |
93 |
before_create :default_assign |
|
94 |
before_save :close_duplicates, :update_done_ratio_from_issue_status, :force_updated_on_change, :update_closed_on |
|
96 |
before_create :default_assign, :add_start_and_due_time
|
|
97 |
before_save :close_duplicates, :update_done_ratio_from_issue_status, :force_updated_on_change, :update_closed_on, :add_start_and_due_time
|
|
95 | 98 |
after_save {|issue| issue.send :after_project_change if !issue.id_changed? && issue.project_id_changed?} |
96 | 99 |
after_save :reschedule_following_issues, :update_nested_set_attributes, :update_parent_attributes, :create_journal |
97 | 100 |
# Should be after_create but would be called before previous after_save callbacks |
... | ... | |
361 | 364 |
'subject', |
362 | 365 |
'description', |
363 | 366 |
'start_date', |
367 |
'start_time', |
|
364 | 368 |
'due_date', |
369 |
'due_time', |
|
365 | 370 |
'done_ratio', |
366 | 371 |
'estimated_hours', |
367 | 372 |
'custom_field_values', |
... | ... | |
1302 | 1307 |
end |
1303 | 1308 |
end |
1304 | 1309 | |
1310 |
# Callback on start and due time |
|
1311 |
def add_start_and_due_time |
|
1312 |
if project.use_datetime_for_issues |
|
1313 |
if st=start_time and sd=start_date |
|
1314 |
if st['hour'].to_i > 0 or st['minute'].to_i > 0 |
|
1315 |
self.start_date = Time.parse( "#{sd.year}.#{sd.month}.#{sd.day} #{st['hour']}:#{st['minute']}:00" ) |
|
1316 |
end |
|
1317 |
end |
|
1318 |
if dt=due_time and dd=due_date |
|
1319 |
if dt['hour'].to_i > 0 or dt['minute'].to_i > 0 |
|
1320 |
self.due_date = Time.parse( "#{dd.year}.#{dd.month}.#{dd.day} #{dt['hour']}:#{dt['minute']}:00" ) |
|
1321 |
end |
|
1322 |
end |
|
1323 |
end |
|
1324 |
end |
|
1325 | ||
1305 | 1326 |
# Default assignment based on category |
1306 | 1327 |
def default_assign |
1307 | 1328 |
if assigned_to.nil? && category && category.assigned_to |
app/models/project.rb Fri May 31 17:49:32 2013 +0200 | ||
---|---|---|
650 | 650 |
'description', |
651 | 651 |
'homepage', |
652 | 652 |
'is_public', |
653 |
'use_datetime_for_issues', |
|
653 | 654 |
'identifier', |
654 | 655 |
'custom_field_values', |
655 | 656 |
'custom_fields', |
app/views/issues/_attributes.html.erb Fri May 31 17:49:32 2013 +0200 | ||
---|---|---|
47 | 47 |
<% end %> |
48 | 48 | |
49 | 49 |
<% if @issue.safe_attribute? 'start_date' %> |
50 |
<p><%= f.text_field :start_date, :size => 10, :disabled => !@issue.leaf?, :required => @issue.required_attribute?('start_date') %><%= calendar_for('issue_start_date') if @issue.leaf? %></p> |
|
50 |
<p> |
|
51 |
<%= f.text_field :start_date, :size => 10, :disabled => !@issue.leaf?, :required => @issue.required_attribute?('start_date') %> |
|
52 |
<%= calendar_for('issue_start_date') if @issue.leaf? %> <br /> |
|
53 |
<%== time_select_tag( "issue[start_time]", @issue.start_date.to_s ) if @project.use_datetime_for_issues %> |
|
54 |
</p> |
|
51 | 55 |
<% end %> |
52 | 56 | |
53 | 57 |
<% if @issue.safe_attribute? 'due_date' %> |
54 |
<p><%= f.text_field :due_date, :size => 10, :disabled => !@issue.leaf?, :required => @issue.required_attribute?('due_date') %><%= calendar_for('issue_due_date') if @issue.leaf? %></p> |
|
58 |
<p><%= f.text_field :due_date, :size => 10, :disabled => !@issue.leaf?, :required => @issue.required_attribute?('due_date') %> |
|
59 |
<%= calendar_for('issue_due_date') if @issue.leaf? %> <br /> |
|
60 |
<%== time_select_tag( "issue[due_time]", @issue.due_date.to_s ) if @project.use_datetime_for_issues %> |
|
61 |
</p> |
|
55 | 62 |
<% end %> |
56 | 63 | |
57 | 64 |
<% if @issue.safe_attribute? 'estimated_hours' %> |
app/views/issues/show.html.erb Fri May 31 17:49:32 2013 +0200 | ||
---|---|---|
47 | 47 |
end |
48 | 48 | |
49 | 49 |
unless @issue.disabled_core_fields.include?('start_date') |
50 |
rows.right l(:field_start_date), format_date(@issue.start_date), :class => 'start-date'
|
|
50 |
rows.right l(:field_start_date), (@project.use_datetime_for_issues ? format_time(@issue.start_date) : format_date(@issue.start_date)), :class => 'start-date'
|
|
51 | 51 |
end |
52 | 52 |
unless @issue.disabled_core_fields.include?('due_date') |
53 |
rows.right l(:field_due_date), format_date(@issue.due_date), :class => 'due-date'
|
|
53 |
rows.right l(:field_due_date), (@project.use_datetime_for_issues ? format_time(@issue.due_date) : format_date(@issue.due_date)), :class => 'due-date'
|
|
54 | 54 |
end |
55 | 55 |
unless @issue.disabled_core_fields.include?('done_ratio') |
56 | 56 |
rows.right l(:field_done_ratio), progress_bar(@issue.done_ratio, :width => '80px', :legend => "#{@issue.done_ratio}%"), :class => 'progress' |
app/views/projects/_form.html.erb Fri May 31 17:49:32 2013 +0200 | ||
---|---|---|
11 | 11 |
<% end %></p> |
12 | 12 |
<p><%= f.text_field :homepage, :size => 60 %></p> |
13 | 13 |
<p><%= f.check_box :is_public %></p> |
14 |
<p><%= f.check_box :use_datetime_for_issues %></p> |
|
14 | 15 | |
15 | 16 |
<% unless @project.allowed_parents.compact.empty? %> |
16 | 17 |
<p><%= label(:project, :parent_id, l(:field_parent)) %><%= parent_project_select_tag(@project) %></p> |
config/locales/cs.yml Fri May 31 17:49:32 2013 +0200 | ||
---|---|---|
311 | 311 |
field_assigned_to_role: Role přiřaditele |
312 | 312 |
field_text: Textové pole |
313 | 313 |
field_visible: Viditelný |
314 | ||
314 |
field_use_datetime_for_issues: Použít u tiketů také čas |
|
315 | 315 |
setting_app_title: Název aplikace |
316 | 316 |
setting_app_subtitle: Podtitulek aplikace |
317 | 317 |
setting_welcome_text: Uvítací text |
config/locales/en-GB.yml Fri May 31 17:49:32 2013 +0200 | ||
---|---|---|
311 | 311 |
field_assigned_to_role: "Assignee's role" |
312 | 312 |
field_text: Text field |
313 | 313 |
field_visible: Visible |
314 |
field_use_datetime_for_issues: Use time in tickets too |
|
314 | 315 |
field_warn_on_leaving_unsaved: "Warn me when leaving a page with unsaved text" |
315 | 316 | |
316 | 317 |
setting_app_title: Application title |
config/locales/en.yml Fri May 31 17:49:32 2013 +0200 | ||
---|---|---|
314 | 314 |
field_assigned_to_role: "Assignee's role" |
315 | 315 |
field_text: Text field |
316 | 316 |
field_visible: Visible |
317 |
field_use_datetime_for_issues: Use time in tickets too |
|
317 | 318 |
field_warn_on_leaving_unsaved: "Warn me when leaving a page with unsaved text" |
318 | 319 |
field_issues_visibility: Issues visibility |
319 | 320 |
field_is_private: Private |
db/migrate/20130531174459_add_time_to_issue_start_date_and_issue_due_date.rb Fri May 31 17:49:32 2013 +0200 | ||
---|---|---|
1 |
class AddTimeToIssueStartDateAndIssueDueDate < ActiveRecord::Migration |
|
2 |
def self.up |
|
3 |
change_column :issues, :start_date, :datetime |
|
4 |
change_column :issues, :due_date, :datetime |
|
5 |
end |
|
6 |
|
|
7 |
def self.down |
|
8 |
change_column :issues, :start_date, :date |
|
9 |
change_column :issues, :due_date, :date |
|
10 |
end |
|
11 |
end |
db/migrate/20130531174549_add_use_datetime_for_issues_to_projects.rb Fri May 31 17:49:32 2013 +0200 | ||
---|---|---|
1 |
class AddUseDatetimeForIssuesToProjects < ActiveRecord::Migration |
|
2 | ||
3 |
def self.up |
|
4 |
add_column :projects, :use_datetime_for_issues, :boolean, :default => false |
|
5 |
end |
|
6 | ||
7 |
def self.down |
|
8 |
remove_column :projects, :use_datetime_for_issues |
|
9 |
end |
|
10 | ||
11 |
end |
lib/redmine/utils.rb Wed Jun 05 15:41:36 2013 +0200 | ||
---|---|---|
60 | 60 |
weeks = days / 7 |
61 | 61 |
result = weeks * (7 - non_working_week_days.size) |
62 | 62 |
days_left = days - weeks * 7 |
63 |
start_cwday = from.cwday |
|
63 |
start_cwday = from.to_date.cwday
|
|
64 | 64 |
days_left.times do |i| |
65 | 65 |
unless non_working_week_days.include?(((start_cwday + i - 1) % 7) + 1) |
66 | 66 |
result += 1 |
... | ... | |
78 | 78 |
weeks = working_days / (7 - non_working_week_days.size) |
79 | 79 |
result = weeks * 7 |
80 | 80 |
days_left = working_days - weeks * (7 - non_working_week_days.size) |
81 |
cwday = date.cwday |
|
81 |
cwday = date.to_date.cwday
|
|
82 | 82 |
while days_left > 0 |
83 | 83 |
cwday += 1 |
84 | 84 |
unless non_working_week_days.include?(((cwday - 1) % 7) + 1) |
... | ... | |
94 | 94 | |
95 | 95 |
# Returns the date of the first day on or after the given date that is a working day |
96 | 96 |
def next_working_date(date) |
97 |
cwday = date.cwday |
|
97 |
cwday = date.to_date.cwday
|
|
98 | 98 |
days = 0 |
99 | 99 |
while non_working_week_days.include?(((cwday + days - 1) % 7) + 1) |
100 | 100 |
days += 1 |