@@ -0,0 +1,22 | |||||
|
1 | # redMine - project management software | |||
|
2 | # Copyright (C) 2006 Jean-Philippe Lang | |||
|
3 | # | |||
|
4 | # This program is free software; you can redistribute it and/or | |||
|
5 | # modify it under the terms of the GNU General Public License | |||
|
6 | # as published by the Free Software Foundation; either version 2 | |||
|
7 | # of the License, or (at your option) any later version. | |||
|
8 | # | |||
|
9 | # This program is distributed in the hope that it will be useful, | |||
|
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
|
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
|
12 | # GNU General Public License for more details. | |||
|
13 | # | |||
|
14 | # You should have received a copy of the GNU General Public License | |||
|
15 | # along with this program; if not, write to the Free Software | |||
|
16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
|
17 | ||||
|
18 | class Journal < ActiveRecord::Base | |||
|
19 | belongs_to :journalized, :polymorphic => true | |||
|
20 | belongs_to :user | |||
|
21 | has_many :details, :class_name => "JournalDetail", :dependent => true | |||
|
22 | end |
@@ -0,0 +1,20 | |||||
|
1 | # redMine - project management software | |||
|
2 | # Copyright (C) 2006 Jean-Philippe Lang | |||
|
3 | # | |||
|
4 | # This program is free software; you can redistribute it and/or | |||
|
5 | # modify it under the terms of the GNU General Public License | |||
|
6 | # as published by the Free Software Foundation; either version 2 | |||
|
7 | # of the License, or (at your option) any later version. | |||
|
8 | # | |||
|
9 | # This program is distributed in the hope that it will be useful, | |||
|
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
|
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
|
12 | # GNU General Public License for more details. | |||
|
13 | # | |||
|
14 | # You should have received a copy of the GNU General Public License | |||
|
15 | # along with this program; if not, write to the Free Software | |||
|
16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
|
17 | ||||
|
18 | class JournalDetail < ActiveRecord::Base | |||
|
19 | belongs_to :journal | |||
|
20 | end |
@@ -0,0 +1,11 | |||||
|
1 | <% for journal in journals %> | |||
|
2 | <h4><%= format_time(journal.created_on) %> - <%= journal.user.name %></h4> | |||
|
3 | <ul> | |||
|
4 | <% for detail in journal.details %> | |||
|
5 | <li><%= show_detail(detail) %></li> | |||
|
6 | <% end %> | |||
|
7 | </ul> | |||
|
8 | <% if journal.notes? %> | |||
|
9 | <%= simple_format auto_link journal.notes %> | |||
|
10 | <% end %> | |||
|
11 | <% end %> |
@@ -0,0 +1,6 | |||||
|
1 | <h3><%=l(:label_history)%></h3> | |||
|
2 | <div id="history"> | |||
|
3 | <%= render :partial => 'history', :locals => { :journals => @journals } %> | |||
|
4 | </div> | |||
|
5 | <br /> | |||
|
6 | <p><%= link_to l(:button_back), :action => 'show', :id => @issue %></p> No newline at end of file |
@@ -0,0 +1,8 | |||||
|
1 | Issue #<%= @issue.id %> has been updated. | |||
|
2 | <%= @journal.user.name %> | |||
|
3 | <% for detail in @journal.details %> | |||
|
4 | <%= show_detail(detail) %> | |||
|
5 | <% end %> | |||
|
6 | <%= @journal.notes if @journal.notes? %> | |||
|
7 | ---------------------------------------- | |||
|
8 | <%= render :file => "_issue", :use_full_path => true, :locals => { :issue => @issue } %> No newline at end of file |
@@ -0,0 +1,8 | |||||
|
1 | Issue #<%= @issue.id %> has been updated. | |||
|
2 | <%= @journal.user.name %> | |||
|
3 | <% for detail in @journal.details %> | |||
|
4 | <%= show_detail(detail) %> | |||
|
5 | <% end %> | |||
|
6 | <%= @journal.notes if @journal.notes? %> | |||
|
7 | ---------------------------------------- | |||
|
8 | <%= render :file => "_issue", :use_full_path => true, :locals => { :issue => @issue } %> No newline at end of file |
@@ -0,0 +1,8 | |||||
|
1 | Issue #<%= @issue.id %> has been updated. | |||
|
2 | <%= @journal.user.name %> | |||
|
3 | <% for detail in @journal.details %> | |||
|
4 | <%= show_detail(detail) %> | |||
|
5 | <% end %> | |||
|
6 | <%= @journal.notes if @journal.notes? %> | |||
|
7 | ---------------------------------------- | |||
|
8 | <%= render :file => "_issue", :use_full_path => true, :locals => { :issue => @issue } %> No newline at end of file |
@@ -0,0 +1,8 | |||||
|
1 | La demande #<%= @issue.id %> a été mise à jour. | |||
|
2 | <%= @journal.user.name %> - <%= format_date(@journal.created_on) %> | |||
|
3 | <% for detail in @journal.details %> | |||
|
4 | <%= show_detail(detail) %> | |||
|
5 | <% end %> | |||
|
6 | <%= journal.notes if journal.notes? %> | |||
|
7 | ---------------------------------------- | |||
|
8 | <%= render :file => "_issue", :use_full_path => true, :locals => { :issue => @issue } %> No newline at end of file |
@@ -0,0 +1,54 | |||||
|
1 | class CreateJournals < ActiveRecord::Migration | |||
|
2 | ||||
|
3 | # model removed, but needed for data migration | |||
|
4 | class IssueHistory < ActiveRecord::Base; belongs_to :issue; end | |||
|
5 | ||||
|
6 | def self.up | |||
|
7 | create_table :journals, :force => true do |t| | |||
|
8 | t.column "journalized_id", :integer, :default => 0, :null => false | |||
|
9 | t.column "journalized_type", :string, :limit => 30, :default => "", :null => false | |||
|
10 | t.column "user_id", :integer, :default => 0, :null => false | |||
|
11 | t.column "notes", :text | |||
|
12 | t.column "created_on", :datetime, :null => false | |||
|
13 | end | |||
|
14 | create_table :journal_details, :force => true do |t| | |||
|
15 | t.column "journal_id", :integer, :default => 0, :null => false | |||
|
16 | t.column "property", :string, :limit => 30, :default => "", :null => false | |||
|
17 | t.column "prop_key", :string, :limit => 30, :default => "", :null => false | |||
|
18 | t.column "old_value", :string | |||
|
19 | t.column "value", :string | |||
|
20 | end | |||
|
21 | ||||
|
22 | # indexes | |||
|
23 | add_index "journals", ["journalized_id", "journalized_type"], :name => "journals_journalized_id" | |||
|
24 | add_index "journal_details", ["journal_id"], :name => "journal_details_journal_id" | |||
|
25 | ||||
|
26 | Permission.create :controller => "issues", :action => "history", :description => "label_history", :sort => 1006, :is_public => true, :mail_option => 0, :mail_enabled => 0 | |||
|
27 | ||||
|
28 | # data migration | |||
|
29 | IssueHistory.find(:all, :include => :issue).each {|h| | |||
|
30 | j = Journal.new(:journalized => h.issue, :user_id => h.author_id, :notes => h.notes, :created_on => h.created_on) | |||
|
31 | j.details << JournalDetail.new(:property => 'attr', :prop_key => 'status_id', :value => h.status_id) | |||
|
32 | j.save | |||
|
33 | } | |||
|
34 | ||||
|
35 | drop_table :issue_histories | |||
|
36 | end | |||
|
37 | ||||
|
38 | def self.down | |||
|
39 | drop_table :journal_details | |||
|
40 | drop_table :journals | |||
|
41 | ||||
|
42 | create_table "issue_histories", :force => true do |t| | |||
|
43 | t.column "issue_id", :integer, :default => 0, :null => false | |||
|
44 | t.column "status_id", :integer, :default => 0, :null => false | |||
|
45 | t.column "author_id", :integer, :default => 0, :null => false | |||
|
46 | t.column "notes", :text, :default => "" | |||
|
47 | t.column "created_on", :timestamp | |||
|
48 | end | |||
|
49 | ||||
|
50 | add_index "issue_histories", ["issue_id"], :name => "issue_histories_issue_id" | |||
|
51 | ||||
|
52 | Permission.find(:first, :conditions => ["controller=? and action=?", 'issues', 'history']).destroy | |||
|
53 | end | |||
|
54 | end |
@@ -41,7 +41,7 class ApplicationController < ActionController::Base | |||||
41 | if self.logged_in_user and self.logged_in_user.language and !self.logged_in_user.language.empty? and GLoc.valid_languages.include? self.logged_in_user.language.to_sym |
|
41 | if self.logged_in_user and self.logged_in_user.language and !self.logged_in_user.language.empty? and GLoc.valid_languages.include? self.logged_in_user.language.to_sym | |
42 | self.logged_in_user.language |
|
42 | self.logged_in_user.language | |
43 | elsif request.env['HTTP_ACCEPT_LANGUAGE'] |
|
43 | elsif request.env['HTTP_ACCEPT_LANGUAGE'] | |
44 |
accept_lang = |
|
44 | accept_lang = parse_qvalues(request.env['HTTP_ACCEPT_LANGUAGE']).first.split('-').first | |
45 | if accept_lang and !accept_lang.empty? and GLoc.valid_languages.include? accept_lang.to_sym |
|
45 | if accept_lang and !accept_lang.empty? and GLoc.valid_languages.include? accept_lang.to_sym | |
46 | accept_lang |
|
46 | accept_lang | |
47 | end |
|
47 | end | |
@@ -104,4 +104,23 class ApplicationController < ActionController::Base | |||||
104 | session[:return_to] = nil |
|
104 | session[:return_to] = nil | |
105 | end |
|
105 | end | |
106 | end |
|
106 | end | |
|
107 | ||||
|
108 | # qvalues http header parser | |||
|
109 | # code taken from webrick | |||
|
110 | def parse_qvalues(value) | |||
|
111 | tmp = [] | |||
|
112 | if value | |||
|
113 | parts = value.split(/,\s*/) | |||
|
114 | parts.each {|part| | |||
|
115 | if m = %r{^([^\s,]+?)(?:;\s*q=(\d+(?:\.\d+)?))?$}.match(part) | |||
|
116 | val = m[1] | |||
|
117 | q = (m[2] or 1).to_f | |||
|
118 | tmp.push([val, q]) | |||
|
119 | end | |||
|
120 | } | |||
|
121 | tmp = tmp.sort_by{|val, q| -q} | |||
|
122 | tmp.collect!{|val, q| val} | |||
|
123 | end | |||
|
124 | return tmp | |||
|
125 | end | |||
107 | end No newline at end of file |
|
126 | end |
@@ -27,6 +27,13 class IssuesController < ApplicationController | |||||
27 | def show |
|
27 | def show | |
28 | @status_options = @issue.status.workflows.find(:all, :include => :new_status, :conditions => ["role_id=? and tracker_id=?", self.logged_in_user.role_for_project(@project.id), @issue.tracker.id]).collect{ |w| w.new_status } if self.logged_in_user |
|
28 | @status_options = @issue.status.workflows.find(:all, :include => :new_status, :conditions => ["role_id=? and tracker_id=?", self.logged_in_user.role_for_project(@project.id), @issue.tracker.id]).collect{ |w| w.new_status } if self.logged_in_user | |
29 | @custom_values = @issue.custom_values.find(:all, :include => :custom_field) |
|
29 | @custom_values = @issue.custom_values.find(:all, :include => :custom_field) | |
|
30 | @journals_count = @issue.journals.count | |||
|
31 | @journals = @issue.journals.find(:all, :include => [:user, :details], :limit => 15, :order => "journals.created_on desc") | |||
|
32 | end | |||
|
33 | ||||
|
34 | def history | |||
|
35 | @journals = @issue.journals.find(:all, :include => [:user, :details], :order => "journals.created_on desc") | |||
|
36 | @journals_count = @journals.length | |||
30 | end |
|
37 | end | |
31 |
|
38 | |||
32 | def export_pdf |
|
39 | def export_pdf | |
@@ -41,6 +48,7 class IssuesController < ApplicationController | |||||
41 | @custom_values = @project.custom_fields_for_issues(@issue.tracker).collect { |x| @issue.custom_values.find_by_custom_field_id(x.id) || CustomValue.new(:custom_field => x, :customized => @issue) } |
|
48 | @custom_values = @project.custom_fields_for_issues(@issue.tracker).collect { |x| @issue.custom_values.find_by_custom_field_id(x.id) || CustomValue.new(:custom_field => x, :customized => @issue) } | |
42 | else |
|
49 | else | |
43 | begin |
|
50 | begin | |
|
51 | @issue.init_journal(self.logged_in_user) | |||
44 | # Retrieve custom fields and values |
|
52 | # Retrieve custom fields and values | |
45 | @custom_values = @project.custom_fields_for_issues(@issue.tracker).collect { |x| CustomValue.new(:custom_field => x, :customized => @issue, :value => params["custom_fields"][x.id.to_s]) } |
|
53 | @custom_values = @project.custom_fields_for_issues(@issue.tracker).collect { |x| CustomValue.new(:custom_field => x, :customized => @issue, :value => params["custom_fields"][x.id.to_s]) } | |
46 | @issue.custom_values = @custom_values |
|
54 | @issue.custom_values = @custom_values | |
@@ -57,13 +65,14 class IssuesController < ApplicationController | |||||
57 | end |
|
65 | end | |
58 |
|
66 | |||
59 | def add_note |
|
67 | def add_note | |
60 |
unless params |
|
68 | unless params[:notes].empty? | |
61 | @history = @issue.histories.build(params[:history]) |
|
69 | journal = @issue.init_journal(self.logged_in_user, params[:notes]) | |
62 | @history.author_id = self.logged_in_user.id if self.logged_in_user |
|
70 | #@history = @issue.histories.build(params[:history]) | |
63 | @history.status = @issue.status |
|
71 | #@history.author_id = self.logged_in_user.id if self.logged_in_user | |
64 |
|
|
72 | #@history.status = @issue.status | |
|
73 | if @issue.save | |||
65 | flash[:notice] = l(:notice_successful_update) |
|
74 | flash[:notice] = l(:notice_successful_update) | |
66 |
Mailer.deliver_issue_ |
|
75 | Mailer.deliver_issue_edit(journal) if Permission.find_by_controller_and_action(@params[:controller], @params[:action]).mail_enabled? | |
67 | redirect_to :action => 'show', :id => @issue |
|
76 | redirect_to :action => 'show', :id => @issue | |
68 | return |
|
77 | return | |
69 | end |
|
78 | end | |
@@ -73,17 +82,20 class IssuesController < ApplicationController | |||||
73 | end |
|
82 | end | |
74 |
|
83 | |||
75 | def change_status |
|
84 | def change_status | |
76 | @history = @issue.histories.build(params[:history]) |
|
85 | #@history = @issue.histories.build(params[:history]) | |
77 | @status_options = @issue.status.workflows.find(:all, :conditions => ["role_id=? and tracker_id=?", self.logged_in_user.role_for_project(@project.id), @issue.tracker.id]).collect{ |w| w.new_status } if self.logged_in_user |
|
86 | @status_options = @issue.status.workflows.find(:all, :conditions => ["role_id=? and tracker_id=?", self.logged_in_user.role_for_project(@project.id), @issue.tracker.id]).collect{ |w| w.new_status } if self.logged_in_user | |
|
87 | @new_status = IssueStatus.find(params[:new_status_id]) | |||
78 | if params[:confirm] |
|
88 | if params[:confirm] | |
79 | begin |
|
89 | begin | |
80 | @history.author_id = self.logged_in_user.id if self.logged_in_user |
|
90 | #@history.author_id = self.logged_in_user.id if self.logged_in_user | |
81 | @issue.status = @history.status |
|
91 | #@issue.status = @history.status | |
82 | @issue.fixed_version_id = (params[:issue][:fixed_version_id]) |
|
92 | #@issue.fixed_version_id = (params[:issue][:fixed_version_id]) | |
83 | @issue.assigned_to_id = (params[:issue][:assigned_to_id]) |
|
93 | #@issue.assigned_to_id = (params[:issue][:assigned_to_id]) | |
84 | @issue.done_ratio = (params[:issue][:done_ratio]) |
|
94 | #@issue.done_ratio = (params[:issue][:done_ratio]) | |
85 | @issue.lock_version = (params[:issue][:lock_version]) |
|
95 | #@issue.lock_version = (params[:issue][:lock_version]) | |
86 | if @issue.save |
|
96 | @issue.init_journal(self.logged_in_user, params[:notes]) | |
|
97 | @issue.status = @new_status | |||
|
98 | if @issue.update_attributes(params[:issue]) | |||
87 | flash[:notice] = l(:notice_successful_update) |
|
99 | flash[:notice] = l(:notice_successful_update) | |
88 | Mailer.deliver_issue_change_status(@issue) if Permission.find_by_controller_and_action(@params[:controller], @params[:action]).mail_enabled? |
|
100 | Mailer.deliver_issue_change_status(@issue) if Permission.find_by_controller_and_action(@params[:controller], @params[:action]).mail_enabled? | |
89 | redirect_to :action => 'show', :id => @issue |
|
101 | redirect_to :action => 'show', :id => @issue |
@@ -28,6 +28,7 class ProjectsController < ApplicationController | |||||
28 | include CustomFieldsHelper |
|
28 | include CustomFieldsHelper | |
29 | helper :ifpdf |
|
29 | helper :ifpdf | |
30 | include IfpdfHelper |
|
30 | include IfpdfHelper | |
|
31 | helper IssuesHelper | |||
31 |
|
32 | |||
32 | def index |
|
33 | def index | |
33 | list |
|
34 | list |
@@ -81,7 +81,7 module ApplicationHelper | |||||
81 | end |
|
81 | end | |
82 |
|
82 | |||
83 | def textilizable(text) |
|
83 | def textilizable(text) | |
84 |
$RDM_TEXTILE_DISABLED ? text : |
|
84 | $RDM_TEXTILE_DISABLED ? text : RedCloth.new(text).to_html | |
85 | end |
|
85 | end | |
86 |
|
86 | |||
87 | def error_messages_for(object_name, options = {}) |
|
87 | def error_messages_for(object_name, options = {}) |
@@ -54,14 +54,19 module CustomFieldsHelper | |||||
54 | # Return a string used to display a custom value |
|
54 | # Return a string used to display a custom value | |
55 | def show_value(custom_value) |
|
55 | def show_value(custom_value) | |
56 | return "" unless custom_value |
|
56 | return "" unless custom_value | |
|
57 | format_value(custom_value.value, custom_value.custom_field.field_format) | |||
|
58 | end | |||
57 |
|
|
59 | ||
58 | case custom_value.custom_field.field_format |
|
60 | # Return a string used to display a custom value | |
|
61 | def format_value(value, field_format) | |||
|
62 | return "" unless value | |||
|
63 | case field_format | |||
59 | when "date" |
|
64 | when "date" | |
60 |
|
|
65 | value.empty? ? "" : l_date(value.to_date) | |
61 | when "bool" |
|
66 | when "bool" | |
62 |
l_YesNo( |
|
67 | l_YesNo(value == "1") | |
63 | else |
|
68 | else | |
64 |
|
|
69 | value | |
65 |
end |
|
70 | end | |
66 | end |
|
71 | end | |
67 |
|
72 |
@@ -25,12 +25,12 module IfpdfHelper | |||||
25 |
|
25 | |||
26 | def Cell(w,h=0,txt='',border=0,ln=0,align='',fill=0,link='') |
|
26 | def Cell(w,h=0,txt='',border=0,ln=0,align='',fill=0,link='') | |
27 | @ic ||= Iconv.new('ISO-8859-1', 'UTF-8') |
|
27 | @ic ||= Iconv.new('ISO-8859-1', 'UTF-8') | |
28 | super w,h,@ic.iconv(txt),border,ln,align,fill,link |
|
28 | txt = begin | |
|
29 | @ic.iconv(txt) | |||
|
30 | rescue | |||
|
31 | txt | |||
29 | end |
|
32 | end | |
30 |
|
33 | super w,h,txt,border,ln,align,fill,link | ||
31 | def MultiCell(w,h,txt,border=0,align='J',fill=0) |
|
|||
32 | @ic ||= Iconv.new('ISO-8859-1', 'UTF-8') |
|
|||
33 | super w,h,txt,border,align,fill |
|
|||
34 | end |
|
34 | end | |
35 |
|
35 | |||
36 | def Footer |
|
36 | def Footer |
@@ -16,4 +16,59 | |||||
16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |
17 |
|
17 | |||
18 | module IssuesHelper |
|
18 | module IssuesHelper | |
|
19 | ||||
|
20 | def show_detail(detail, no_html=false) | |||
|
21 | case detail.property | |||
|
22 | when 'attr' | |||
|
23 | label = l(("field_" + detail.prop_key.to_s.gsub(/\_id$/, "")).to_sym) | |||
|
24 | case detail.prop_key | |||
|
25 | when 'due_date', 'start_date' | |||
|
26 | value = format_date(detail.value.to_date) if detail.value | |||
|
27 | old_value = format_date(detail.old_value.to_date) if detail.old_value | |||
|
28 | when 'status_id' | |||
|
29 | s = IssueStatus.find_by_id(detail.value) and value = s.name if detail.value | |||
|
30 | s = IssueStatus.find_by_id(detail.old_value) and old_value = s.name if detail.old_value | |||
|
31 | when 'assigned_to_id' | |||
|
32 | u = User.find_by_id(detail.value) and value = u.name if detail.value | |||
|
33 | u = User.find_by_id(detail.old_value) and old_value = u.name if detail.old_value | |||
|
34 | when 'priority_id' | |||
|
35 | e = Enumeration.find_by_id(detail.value) and value = e.name if detail.value | |||
|
36 | e = Enumeration.find_by_id(detail.old_value) and old_value = e.name if detail.old_value | |||
|
37 | when 'category_id' | |||
|
38 | c = IssueCategory.find_by_id(detail.value) and value = c.name if detail.value | |||
|
39 | c = IssueCategory.find_by_id(detail.old_value) and old_value = c.name if detail.old_value | |||
|
40 | when 'fixed_version_id' | |||
|
41 | v = Version.find_by_id(detail.value) and value = v.name if detail.value | |||
|
42 | v = Version.find_by_id(detail.old_value) and old_value = v.name if detail.old_value | |||
|
43 | end | |||
|
44 | when 'cf' | |||
|
45 | custom_field = CustomField.find_by_id(detail.prop_key) | |||
|
46 | if custom_field | |||
|
47 | label = custom_field.name | |||
|
48 | value = format_value(detail.value, custom_field.field_format) if detail.value | |||
|
49 | old_value = format_value(detail.old_value, custom_field.field_format) if detail.old_value | |||
|
50 | end | |||
|
51 | end | |||
|
52 | ||||
|
53 | label ||= detail.prop_key | |||
|
54 | value ||= detail.value | |||
|
55 | old_value ||= detail.old_value | |||
|
56 | ||||
|
57 | unless no_html | |||
|
58 | label = content_tag('strong', label) | |||
|
59 | old_value = content_tag("i", old_value) if old_value | |||
|
60 | old_value = content_tag("strike", old_value) if old_value and !value | |||
|
61 | value = content_tag("i", value) if value | |||
|
62 | end | |||
|
63 | ||||
|
64 | if value | |||
|
65 | if old_value | |||
|
66 | label + " " + l(:text_journal_changed, old_value, value) | |||
|
67 | else | |||
|
68 | label + " " + l(:text_journal_set_to, value) | |||
|
69 | end | |||
|
70 | else | |||
|
71 | label + " " + l(:text_journal_deleted) + " (#{old_value})" | |||
|
72 | end | |||
|
73 | end | |||
19 | end |
|
74 | end |
@@ -26,7 +26,8 class Issue < ActiveRecord::Base | |||||
26 | belongs_to :priority, :class_name => 'Enumeration', :foreign_key => 'priority_id' |
|
26 | belongs_to :priority, :class_name => 'Enumeration', :foreign_key => 'priority_id' | |
27 | belongs_to :category, :class_name => 'IssueCategory', :foreign_key => 'category_id' |
|
27 | belongs_to :category, :class_name => 'IssueCategory', :foreign_key => 'category_id' | |
28 |
|
28 | |||
29 | has_many :histories, :class_name => 'IssueHistory', :dependent => true, :order => "issue_histories.created_on DESC", :include => :status |
|
29 | #has_many :histories, :class_name => 'IssueHistory', :dependent => true, :order => "issue_histories.created_on DESC", :include => :status | |
|
30 | has_many :journals, :as => :journalized, :dependent => true | |||
30 | has_many :attachments, :as => :container, :dependent => true |
|
31 | has_many :attachments, :as => :container, :dependent => true | |
31 |
|
32 | |||
32 | has_many :custom_values, :dependent => true, :as => :customized |
|
33 | has_many :custom_values, :dependent => true, :as => :customized | |
@@ -51,8 +52,28 class Issue < ActiveRecord::Base | |||||
51 | end |
|
52 | end | |
52 | end |
|
53 | end | |
53 |
|
54 | |||
54 | def before_create |
|
55 | #def before_create | |
55 | build_history |
|
56 | # build_history | |
|
57 | #end | |||
|
58 | ||||
|
59 | def before_save | |||
|
60 | if @current_journal | |||
|
61 | # attributes changes | |||
|
62 | (Issue.column_names - %w(id description)).each {|c| | |||
|
63 | @current_journal.details << JournalDetail.new(:property => 'attr', | |||
|
64 | :prop_key => c, | |||
|
65 | :old_value => @issue_before_change.send(c), | |||
|
66 | :value => send(c)) unless send(c)==@issue_before_change.send(c) | |||
|
67 | } | |||
|
68 | # custom fields changes | |||
|
69 | custom_values.each {|c| | |||
|
70 | @current_journal.details << JournalDetail.new(:property => 'cf', | |||
|
71 | :prop_key => c.custom_field_id, | |||
|
72 | :old_value => @custom_values_before_change[c.custom_field_id], | |||
|
73 | :value => c.value) unless @custom_values_before_change[c.custom_field_id]==c.value | |||
|
74 | } | |||
|
75 | @current_journal.save unless @current_journal.details.empty? and @current_journal.notes.empty? | |||
|
76 | end | |||
56 | end |
|
77 | end | |
57 |
|
78 | |||
58 | def long_id |
|
79 | def long_id | |
@@ -64,11 +85,19 class Issue < ActiveRecord::Base | |||||
64 | return nil |
|
85 | return nil | |
65 | end |
|
86 | end | |
66 |
|
87 | |||
|
88 | def init_journal(user, notes = "") | |||
|
89 | @current_journal ||= Journal.new(:journalized => self, :user => user, :notes => notes) | |||
|
90 | @issue_before_change = self.clone | |||
|
91 | @custom_values_before_change = {} | |||
|
92 | self.custom_values.each {|c| @custom_values_before_change.store c.custom_field_id, c.value } | |||
|
93 | @current_journal | |||
|
94 | end | |||
|
95 | ||||
67 | private |
|
96 | private | |
68 | # Creates an history for the issue |
|
97 | # Creates an history for the issue | |
69 | def build_history |
|
98 | #def build_history | |
70 | @history = self.histories.build |
|
99 | # @history = self.histories.build | |
71 | @history.status = self.status |
|
100 | # @history.status = self.status | |
72 | @history.author = self.author |
|
101 | # @history.author = self.author | |
73 | end |
|
102 | #end | |
74 | end |
|
103 | end |
@@ -17,7 +17,7 | |||||
17 |
|
17 | |||
18 | class Mailer < ActionMailer::Base |
|
18 | class Mailer < ActionMailer::Base | |
19 |
|
19 | |||
20 |
def issue_ |
|
20 | def issue_add(issue) | |
21 | # Sends to all project members |
|
21 | # Sends to all project members | |
22 | @recipients = issue.project.members.collect { |m| m.user.mail if m.user.mail_notification } |
|
22 | @recipients = issue.project.members.collect { |m| m.user.mail if m.user.mail_notification } | |
23 | @from = $RDM_MAIL_FROM |
|
23 | @from = $RDM_MAIL_FROM | |
@@ -25,20 +25,14 class Mailer < ActionMailer::Base | |||||
25 | @body['issue'] = issue |
|
25 | @body['issue'] = issue | |
26 | end |
|
26 | end | |
27 |
|
27 | |||
28 | def issue_add(issue) |
|
28 | def issue_edit(journal) | |
29 | # Sends to all project members |
|
29 | # Sends to all project members | |
|
30 | issue = journal.journalized | |||
30 | @recipients = issue.project.members.collect { |m| m.user.mail if m.user.mail_notification } |
|
31 | @recipients = issue.project.members.collect { |m| m.user.mail if m.user.mail_notification } | |
31 | @from = $RDM_MAIL_FROM |
|
32 | @from = $RDM_MAIL_FROM | |
32 | @subject = "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] #{issue.status.name} - #{issue.subject}" |
|
33 | @subject = "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] #{issue.status.name} - #{issue.subject}" | |
33 | @body['issue'] = issue |
|
34 | @body['issue'] = issue | |
34 | end |
|
35 | @body['journal']= journal | |
35 |
|
||||
36 | def issue_add_note(history) |
|
|||
37 | # Sends to all project members |
|
|||
38 | @recipients = history.issue.project.members.collect { |m| m.user.mail if m.user.mail_notification } |
|
|||
39 | @from = $RDM_MAIL_FROM |
|
|||
40 | @subject = "[#{history.issue.project.name} - #{history.issue.tracker.name} ##{history.issue.id}] #{history.issue.status.name} - #{history.issue.subject}" |
|
|||
41 | @body['history'] = history |
|
|||
42 | end |
|
36 | end | |
43 |
|
37 | |||
44 | def lost_password(token) |
|
38 | def lost_password(token) |
@@ -66,20 +66,25 | |||||
66 | pdf.Line(pdf.GetX, pdf.GetY, 170, pdf.GetY) |
|
66 | pdf.Line(pdf.GetX, pdf.GetY, 170, pdf.GetY) | |
67 |
|
67 | |||
68 | pdf.Ln |
|
68 | pdf.Ln | |
|
69 | ||||
69 | pdf.SetFont('Arial','B',9) |
|
70 | pdf.SetFont('Arial','B',9) | |
70 | pdf.Cell(190,5, l(:label_history),"B") |
|
71 | pdf.Cell(190,5, l(:label_history), "B") | |
71 | pdf.Ln |
|
72 | pdf.Ln | |
72 |
for |
|
73 | for journal in issue.journals.find(:all, :include => :user, :order => "journals.created_on desc") | |
73 |
|
|
74 | pdf.SetFont('Arial','B',8) | |
74 | pdf.Cell(100,5, history.status.name) |
|
75 | pdf.Cell(190,5, format_time(journal.created_on) + " - " + journal.user.name) | |
75 | pdf.SetFont('Arial','',8) |
|
76 | pdf.Ln | |
76 | pdf.Cell(20,5, format_date(history.created_on)) |
|
77 | pdf.SetFont('Arial','I',8) | |
77 | pdf.Cell(70,5, history.author.name,0,0,"R") |
|
78 | for detail in journal.details | |
78 | pdf.SetFont('Arial','',8) |
|
79 | pdf.Cell(190,5, "- " + show_detail(detail, true)) | |
79 |
|
|
80 | pdf.Ln | |
80 | pdf.Cell(10,4, "") and pdf.MultiCell(180,4, history.notes) if history.notes? |
|
81 | end | |
|
82 | if journal.notes? | |||
|
83 | pdf.SetFont('Arial','',8) | |||
|
84 | pdf.MultiCell(190,5, journal.notes) | |||
81 | end |
|
85 | end | |
82 |
|
|
86 | pdf.Ln | |
|
87 | end | |||
83 |
|
88 | |||
84 | pdf.SetFont('Arial','B',9) |
|
89 | pdf.SetFont('Arial','B',9) | |
85 | pdf.Cell(190,5, l(:label_attachment_plural), "B") |
|
90 | pdf.Cell(190,5, l(:label_attachment_plural), "B") | |
@@ -87,8 +92,8 | |||||
87 | for attachment in issue.attachments |
|
92 | for attachment in issue.attachments | |
88 | pdf.SetFont('Arial','',8) |
|
93 | pdf.SetFont('Arial','',8) | |
89 | pdf.Cell(80,5, attachment.filename) |
|
94 | pdf.Cell(80,5, attachment.filename) | |
90 | pdf.Cell(20,5, human_size(attachment.filesize)) |
|
95 | pdf.Cell(20,5, human_size(attachment.filesize),0,0,"R") | |
91 | pdf.Cell(20,5, format_date(attachment.created_on)) |
|
96 | pdf.Cell(20,5, format_date(attachment.created_on),0,0,"R") | |
92 | pdf.Cell(70,5, attachment.author.name,0,0,"R") |
|
97 | pdf.Cell(70,5, attachment.author.name,0,0,"R") | |
93 | pdf.Ln |
|
98 | pdf.Ln | |
94 | end |
|
99 | end |
@@ -1,13 +1,13 | |||||
1 | <h2><%=l(:label_issue)%> #<%= @issue.id %>: <%= @issue.subject %></h2> |
|
1 | <h2><%=l(:label_issue)%> #<%= @issue.id %>: <%= @issue.subject %></h2> | |
2 |
|
2 | |||
3 |
<%= error_messages_for ' |
|
3 | <%= error_messages_for 'issue' %> | |
4 | <%= start_form_tag({:action => 'change_status', :id => @issue}, :class => "tabular") %> |
|
4 | <%= start_form_tag({:action => 'change_status', :id => @issue}, :class => "tabular") %> | |
5 |
|
5 | |||
6 | <%= hidden_field_tag 'confirm', 1 %> |
|
6 | <%= hidden_field_tag 'confirm', 1 %> | |
7 |
<%= hidden_field ' |
|
7 | <%= hidden_field_tag 'new_status_id', @new_status.id %> | |
8 |
|
8 | |||
9 | <div class="box"> |
|
9 | <div class="box"> | |
10 |
<p><label><%=l(:label_issue_status_new)%></label> <%= @ |
|
10 | <p><label><%=l(:label_issue_status_new)%></label> <%= @new_status.name %></p> | |
11 |
|
11 | |||
12 | <p><label for="issue_assigned_to_id"><%=l(:field_assigned_to)%></label> |
|
12 | <p><label for="issue_assigned_to_id"><%=l(:field_assigned_to)%></label> | |
13 | <select name="issue[assigned_to_id]"> |
|
13 | <select name="issue[assigned_to_id]"> | |
@@ -27,8 +27,9 | |||||
27 | <%= options_from_collection_for_select @issue.project.versions, "id", "name", @issue.fixed_version_id %> |
|
27 | <%= options_from_collection_for_select @issue.project.versions, "id", "name", @issue.fixed_version_id %> | |
28 | </select></p> |
|
28 | </select></p> | |
29 |
|
29 | |||
30 |
<p><label for=" |
|
30 | <p><label for="notes"><%= l(:field_notes) %></label> | |
31 |
<%= text_area ' |
|
31 | <%= text_area_tag 'notes', @notes, :cols => 60, :rows => 10 %></p> | |
|
32 | ||||
32 | </div> |
|
33 | </div> | |
33 |
|
34 | |||
34 | <%= hidden_field 'issue', 'lock_version' %> |
|
35 | <%= hidden_field 'issue', 'lock_version' %> |
@@ -19,7 +19,7 | |||||
19 |
|
19 | |||
20 | <div class="clear"> |
|
20 | <div class="clear"> | |
21 | <p><%= f.text_field :subject, :size => 80, :required => true %></p> |
|
21 | <p><%= f.text_field :subject, :size => 80, :required => true %></p> | |
22 | <p><%= f.text_area :description, :cols => 60, :rows => 10, :required => true %></p> |
|
22 | <p><%= f.text_area :description, :cols => 60, :rows => [[10, @issue.description.length / 50].max, 100].min, :required => true %></p> | |
23 |
|
23 | |||
24 | <% for @custom_value in @custom_values %> |
|
24 | <% for @custom_value in @custom_values %> | |
25 | <p><%= custom_field_tag_with_label @custom_value %></p> |
|
25 | <p><%= custom_field_tag_with_label @custom_value %></p> |
@@ -44,8 +44,8 end %> | |||||
44 |
|
44 | |||
45 | <b><%=l(:field_description)%> :</b><br /><br /> |
|
45 | <b><%=l(:field_description)%> :</b><br /><br /> | |
46 | <%= textilizable @issue.description %> |
|
46 | <%= textilizable @issue.description %> | |
47 |
|
47 | <br /> | ||
48 | <p> |
|
48 | <div style="float:left;"> | |
49 | <% if authorize_for('issues', 'edit') %> |
|
49 | <% if authorize_for('issues', 'edit') %> | |
50 | <%= start_form_tag ({:controller => 'issues', :action => 'edit', :id => @issue}, :method => "get" ) %> |
|
50 | <%= start_form_tag ({:controller => 'issues', :action => 'edit', :id => @issue}, :method => "get" ) %> | |
51 | <%= submit_tag l(:button_edit) %> |
|
51 | <%= submit_tag l(:button_edit) %> | |
@@ -56,7 +56,7 end %> | |||||
56 | <% if authorize_for('issues', 'change_status') and @status_options and !@status_options.empty? %> |
|
56 | <% if authorize_for('issues', 'change_status') and @status_options and !@status_options.empty? %> | |
57 | <%= start_form_tag ({:controller => 'issues', :action => 'change_status', :id => @issue}) %> |
|
57 | <%= start_form_tag ({:controller => 'issues', :action => 'change_status', :id => @issue}) %> | |
58 | <%=l(:label_change_status)%> : |
|
58 | <%=l(:label_change_status)%> : | |
59 |
<select name=" |
|
59 | <select name="new_status_id"> | |
60 | <%= options_from_collection_for_select @status_options, "id", "name" %> |
|
60 | <%= options_from_collection_for_select @status_options, "id", "name" %> | |
61 | </select> |
|
61 | </select> | |
62 | <%= submit_tag l(:button_change) %> |
|
62 | <%= submit_tag l(:button_change) %> | |
@@ -71,30 +71,25 end %> | |||||
71 | <%= end_form_tag %> |
|
71 | <%= end_form_tag %> | |
72 | |
|
72 | | |
73 | <% end %> |
|
73 | <% end %> | |
74 |
|
74 | </div> | ||
|
75 | <div style="float:right;"> | |||
75 | <% if authorize_for('issues', 'destroy') %> |
|
76 | <% if authorize_for('issues', 'destroy') %> | |
76 | <%= start_form_tag ({:controller => 'issues', :action => 'destroy', :id => @issue} ) %> |
|
77 | <%= start_form_tag ({:controller => 'issues', :action => 'destroy', :id => @issue} ) %> | |
77 | <%= submit_tag l(:button_delete) %> |
|
78 | <%= submit_tag l(:button_delete) %> | |
78 | <%= end_form_tag %> |
|
79 | <%= end_form_tag %> | |
79 | |
|
80 | | |
80 | <% end %> |
|
81 | <% end %> | |
81 |
</ |
|
82 | </div> | |
|
83 | <div class="clear"></div> | |||
82 | </div> |
|
84 | </div> | |
83 |
|
85 | |||
84 | <div class="box"> |
|
86 | <div id="history" class="box"> | |
85 |
<h3><%=l(:label_history)%> |
|
87 | <h3><%=l(:label_history)%> | |
86 | <table width="100%"> |
|
88 | <% if @journals_count > @journals.length %>(<%= l(:label_last_changes, @journals.length) %>)<% end %></h3> | |
87 | <% for history in @issue.histories.find(:all, :include => [:author, :status]) %> |
|
89 | <%= render :partial => 'history', :locals => { :journals => @journals } %> | |
88 | <tr> |
|
90 | <% if @journals_count > @journals.length %> | |
89 | <td><%= format_date(history.created_on) %></td> |
|
91 | <p><center><small>[ <%= link_to l(:label_change_view_all), :action => 'history', :id => @issue %> ]</small></center></p> | |
90 | <td><%= history.author.display_name %></td> |
|
|||
91 | <td><b><%= history.status.name %></b></td> |
|
|||
92 | </tr> |
|
|||
93 | <% if history.notes? %> |
|
|||
94 | <tr><td colspan=3><%= simple_format auto_link history.notes %></td></tr> |
|
|||
95 | <% end %> |
|
92 | <% end %> | |
96 | <% end %> |
|
|||
97 | </table> |
|
|||
98 | </div> |
|
93 | </div> | |
99 |
|
94 | |||
100 | <div class="box"> |
|
95 | <div class="box"> | |
@@ -130,8 +125,8 end %> | |||||
130 | <div class="box"> |
|
125 | <div class="box"> | |
131 | <h3><%= l(:label_add_note) %></h3> |
|
126 | <h3><%= l(:label_add_note) %></h3> | |
132 | <%= start_form_tag ({:controller => 'issues', :action => 'add_note', :id => @issue}, :class => "tabular" ) %> |
|
127 | <%= start_form_tag ({:controller => 'issues', :action => 'add_note', :id => @issue}, :class => "tabular" ) %> | |
133 |
<p><label for=" |
|
128 | <p><label for="notes"><%=l(:field_notes)%></label> | |
134 |
<%= text_area ' |
|
129 | <%= text_area_tag 'notes', '', :cols => 60, :rows => 10 %></p> | |
135 | <%= submit_tag l(:button_add) %> |
|
130 | <%= submit_tag l(:button_add) %> | |
136 | <%= end_form_tag %> |
|
131 | <%= end_form_tag %> | |
137 | </div> |
|
132 | </div> |
@@ -133,7 +133,7 var menu_contenu=' \ | |||||
133 | <div id="footer"> |
|
133 | <div id="footer"> | |
134 | <p> |
|
134 | <p> | |
135 | <%= auto_link $RDM_FOOTER_SIG %> | |
|
135 | <%= auto_link $RDM_FOOTER_SIG %> | | |
136 | <a href="http://redmine.org/" target="_new"><%= RDM_APP_NAME %></a> <%= RDM_APP_VERSION %> |
|
136 | <a href="http://redmine.rubyforge.org/" target="_new"><%= RDM_APP_NAME %></a> <%= RDM_APP_VERSION %> | |
137 | </p> |
|
137 | </p> | |
138 | </div> |
|
138 | </div> | |
139 |
|
139 |
@@ -7,6 +7,7 http://redmine.org/ | |||||
7 |
|
7 | |||
8 | == xx/xx/2006 v0.x.x |
|
8 | == xx/xx/2006 v0.x.x | |
9 |
|
9 | |||
|
10 | * improved issues change history | |||
10 | * new functionality: move an issue to another project or tracker |
|
11 | * new functionality: move an issue to another project or tracker | |
11 | * new functionality: add a note to an issue |
|
12 | * new functionality: add a note to an issue | |
12 | * new report: project activity |
|
13 | * new report: project activity |
@@ -256,6 +256,8 label_calendar: Kalender | |||||
256 | label_months_from: Monate von |
|
256 | label_months_from: Monate von | |
257 | label_gantt_chart: Gantt Diagramm |
|
257 | label_gantt_chart: Gantt Diagramm | |
258 | label_internal: Intern |
|
258 | label_internal: Intern | |
|
259 | label_last_changes: %d änderungen des Letzten | |||
|
260 | label_change_view_all: Alle änderungen ansehen | |||
259 |
|
261 | |||
260 | button_login: Einloggen |
|
262 | button_login: Einloggen | |
261 | button_submit: Einreichen |
|
263 | button_submit: Einreichen | |
@@ -285,6 +287,9 text_possible_values_info: Werte trennten sich mit | | |||||
285 | text_project_destroy_confirmation: Sind sie sicher, daß sie das Projekt löschen wollen ? |
|
287 | text_project_destroy_confirmation: Sind sie sicher, daß sie das Projekt löschen wollen ? | |
286 | text_workflow_edit: Auswahl Workflow zum Bearbeiten |
|
288 | text_workflow_edit: Auswahl Workflow zum Bearbeiten | |
287 | text_are_you_sure: Sind sie sicher ? |
|
289 | text_are_you_sure: Sind sie sicher ? | |
|
290 | text_journal_changed: geändert von %s zu %s | |||
|
291 | text_journal_set_to: gestellt zu %s | |||
|
292 | text_journal_deleted: gelöscht | |||
288 |
|
293 | |||
289 | default_role_manager: Manager |
|
294 | default_role_manager: Manager | |
290 | default_role_developper: Developer |
|
295 | default_role_developper: Developer |
@@ -256,6 +256,8 label_calendar: Calendar | |||||
256 | label_months_from: months from |
|
256 | label_months_from: months from | |
257 | label_gantt_chart: Gantt chart |
|
257 | label_gantt_chart: Gantt chart | |
258 | label_internal: Internal |
|
258 | label_internal: Internal | |
|
259 | label_last_changes: last %d changes | |||
|
260 | label_change_view_all: View all changes | |||
259 |
|
261 | |||
260 | button_login: Login |
|
262 | button_login: Login | |
261 | button_submit: Submit |
|
263 | button_submit: Submit | |
@@ -285,6 +287,9 text_possible_values_info: values separated with | | |||||
285 | text_project_destroy_confirmation: Are you sure you want to delete this project and all related data ? |
|
287 | text_project_destroy_confirmation: Are you sure you want to delete this project and all related data ? | |
286 | text_workflow_edit: Select a role and a tracker to edit the workflow |
|
288 | text_workflow_edit: Select a role and a tracker to edit the workflow | |
287 | text_are_you_sure: Are you sure ? |
|
289 | text_are_you_sure: Are you sure ? | |
|
290 | text_journal_changed: changed from %s to %s | |||
|
291 | text_journal_set_to: set to %s | |||
|
292 | text_journal_deleted: deleted | |||
288 |
|
293 | |||
289 | default_role_manager: Manager |
|
294 | default_role_manager: Manager | |
290 | default_role_developper: Developer |
|
295 | default_role_developper: Developer |
@@ -256,6 +256,8 label_calendar: Calendario | |||||
256 | label_months_from: meses de |
|
256 | label_months_from: meses de | |
257 | label_gantt_chart: Diagrama de Gantt |
|
257 | label_gantt_chart: Diagrama de Gantt | |
258 | label_internal: Interno |
|
258 | label_internal: Interno | |
|
259 | label_last_changes: %d cambios del último | |||
|
260 | label_change_view_all: Ver todos los cambios | |||
259 |
|
261 | |||
260 | button_login: Conexión |
|
262 | button_login: Conexión | |
261 | button_submit: Someter |
|
263 | button_submit: Someter | |
@@ -285,6 +287,9 text_possible_values_info: Los valores se separaron con | | |||||
285 | text_project_destroy_confirmation: ¿ Estás seguro de querer eliminar el proyecto ? |
|
287 | text_project_destroy_confirmation: ¿ Estás seguro de querer eliminar el proyecto ? | |
286 | text_workflow_edit: Seleccionar un workflow para actualizar |
|
288 | text_workflow_edit: Seleccionar un workflow para actualizar | |
287 | text_are_you_sure: ¿ Estás seguro ? |
|
289 | text_are_you_sure: ¿ Estás seguro ? | |
|
290 | text_journal_changed: cambiado de %s a %s | |||
|
291 | text_journal_set_to: fijado a %s | |||
|
292 | text_journal_deleted: suprimido | |||
288 |
|
293 | |||
289 | default_role_manager: Manager |
|
294 | default_role_manager: Manager | |
290 | default_role_developper: Desarrollador |
|
295 | default_role_developper: Desarrollador |
@@ -257,6 +257,8 label_calendar: Calendrier | |||||
257 | label_months_from: mois depuis |
|
257 | label_months_from: mois depuis | |
258 | label_gantt_chart: Diagramme de Gantt |
|
258 | label_gantt_chart: Diagramme de Gantt | |
259 | label_internal: Interne |
|
259 | label_internal: Interne | |
|
260 | label_last_changes: %d derniers changements | |||
|
261 | label_change_view_all: Voir tous les changements | |||
260 |
|
262 | |||
261 | button_login: Connexion |
|
263 | button_login: Connexion | |
262 | button_submit: Soumettre |
|
264 | button_submit: Soumettre | |
@@ -286,6 +288,9 text_possible_values_info: valeurs séparées par | | |||||
286 | text_project_destroy_confirmation: Etes-vous sûr de vouloir supprimer ce projet et tout ce qui lui est rattaché ? |
|
288 | text_project_destroy_confirmation: Etes-vous sûr de vouloir supprimer ce projet et tout ce qui lui est rattaché ? | |
287 | text_workflow_edit: Sélectionner un tracker et un rôle pour éditer le workflow |
|
289 | text_workflow_edit: Sélectionner un tracker et un rôle pour éditer le workflow | |
288 | text_are_you_sure: Etes-vous sûr ? |
|
290 | text_are_you_sure: Etes-vous sûr ? | |
|
291 | text_journal_changed: changé de %s à %s | |||
|
292 | text_journal_set_to: mis à %s | |||
|
293 | text_journal_deleted: supprimé | |||
289 |
|
294 | |||
290 | default_role_manager: Manager |
|
295 | default_role_manager: Manager | |
291 | default_role_developper: Développeur |
|
296 | default_role_developper: Développeur |
@@ -186,10 +186,6 form { | |||||
186 |
|
186 | |||
187 | .noborder { |
|
187 | .noborder { | |
188 | border:0px; |
|
188 | border:0px; | |
189 | Exception exceptions.AssertionError: <exceptions.AssertionError instance at 0xb7c0b20c> in <bound |
|
|||
190 | method SubversionRepository.__del__ of <vclib.svn.SubversionRepository instance at 0xb7c1252c>> |
|
|||
191 | ignored |
|
|||
192 |
|
||||
193 | background-color:#fff; |
|
189 | background-color:#fff; | |
194 | width:100%; |
|
190 | width:100%; | |
195 | } |
|
191 | } | |
@@ -292,7 +288,7 table.calenderTable td { | |||||
292 | border:1px solid #578bb8; |
|
288 | border:1px solid #578bb8; | |
293 | } |
|
289 | } | |
294 |
|
290 | |||
295 |
hr { border:none; border-bottom: dotted |
|
291 | hr { border:none; border-bottom: dotted 1px #c0c0c0; } | |
296 |
|
292 | |||
297 |
|
293 | |||
298 | /**************** Sidebar styles ****************/ |
|
294 | /**************** Sidebar styles ****************/ | |
@@ -409,6 +405,17 img.calendar-trigger { | |||||
409 | margin-left: 4px; |
|
405 | margin-left: 4px; | |
410 | } |
|
406 | } | |
411 |
|
407 | |||
|
408 | #history h4 { | |||
|
409 | font-size: 1em; | |||
|
410 | margin-bottom: 12px; | |||
|
411 | margin-top: 20px; | |||
|
412 | font-weight: normal; | |||
|
413 | border-bottom: dotted 1px #c0c0c0; | |||
|
414 | } | |||
|
415 | ||||
|
416 | #history p { | |||
|
417 | margin-left: 34px; | |||
|
418 | } | |||
412 |
|
419 | |||
413 | /***** CSS FORM ******/ |
|
420 | /***** CSS FORM ******/ | |
414 | .tabular p{ |
|
421 | .tabular p{ |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
General Comments 0
You need to be logged in to leave comments.
Login now