Defect #2660 » documents.diff
app/views/issues/show.rhtml | ||
---|---|---|
23 | 23 |
<td style="width:15%" class="start-date"><b><%=l(:field_start_date)%>:</b></td><td style="width:35%"><%= format_date(@issue.start_date) %></td> |
24 | 24 |
</tr> |
25 | 25 |
<tr> |
26 |
<td class="priority"><b><%=l(:field_priority)%>:</b></td><td class="priority priority-<%= @issue.priority.name %>"><%= @issue.priority.name %></td>
|
|
26 |
<td class="priority"><b><%=l(:field_priority)%>:</b></td><td class="priority"><%= @issue.priority.name %></td> |
|
27 | 27 |
<td class="due-date"><b><%=l(:field_due_date)%>:</b></td><td class="due-date"><%= format_date(@issue.due_date) %></td> |
28 | 28 |
</tr> |
29 | 29 |
<tr> |
30 |
- |
app/controllers/issues_controller.rb | ||
---|---|---|
187 | 187 | |
188 | 188 |
if (@time_entry.hours.nil? || @time_entry.valid?) && @issue.save |
189 | 189 |
# Log spend time |
190 |
if current_role.allowed_to?(:log_time)
|
|
190 |
if User.current.allowed_to?(:log_time, @project)
|
|
191 | 191 |
@time_entry.save |
192 | 192 |
end |
193 | 193 |
if !journal.new_record? |
194 |
- |
app/views/mailer/layout.text.html.rhtml | ||
---|---|---|
6 | 6 |
font-size: 0.8em; |
7 | 7 |
color:#484848; |
8 | 8 |
} |
9 |
h1 { |
|
10 |
font-family: "Trebuchet MS", Verdana, sans-serif; |
|
11 |
font-size: 1.2em; |
|
12 |
margin: 0px; |
|
13 |
} |
|
14 |
a, a:link, a:visited { |
|
15 |
color: #2A5685; |
|
16 |
} |
|
17 |
a:hover, a:active { |
|
18 |
color: #c61a1a; |
|
19 |
} |
|
9 |
h1, h2, h3 { font-family: "Trebuchet MS", Verdana, sans-serif; margin: 0px; } |
|
10 |
h1 { font-size: 1.2em; } |
|
11 |
h2, h3 { font-size: 1.1em; } |
|
12 |
a, a:link, a:visited { color: #2A5685;} |
|
13 |
a:hover, a:active { color: #c61a1a; } |
|
14 |
a.wiki-anchor { display: none; } |
|
20 | 15 |
hr { |
21 | 16 |
width: 100%; |
22 | 17 |
height: 1px; |
23 |
- |
db/migrate/20090214190337_add_watchers_user_id_type_index.rb | ||
---|---|---|
1 |
class AddWatchersUserIdTypeIndex < ActiveRecord::Migration |
|
2 |
def self.up |
|
3 |
add_index :watchers, [:user_id, :watchable_type], :name => :watchers_user_id_type |
|
4 |
end |
|
5 | ||
6 |
def self.down |
|
7 |
remove_index :watchers, :name => :watchers_user_id_type |
|
8 |
end |
|
9 |
end |
|
0 |
- |
app/views/issues/show.rhtml | ||
---|---|---|
19 | 19 | |
20 | 20 |
<table width="100%"> |
21 | 21 |
<tr> |
22 |
<td style="width:15%" class="status"><b><%=l(:field_status)%>:</b></td><td style="width:35%" class="status status-<%= @issue.status.name %>"><%= @issue.status.name %></td>
|
|
22 |
<td style="width:15%" class="status"><b><%=l(:field_status)%>:</b></td><td style="width:35%" class="status"><%= @issue.status.name %></td> |
|
23 | 23 |
<td style="width:15%" class="start-date"><b><%=l(:field_start_date)%>:</b></td><td style="width:35%"><%= format_date(@issue.start_date) %></td> |
24 | 24 |
</tr> |
25 | 25 |
<tr> |
26 |
- |
doc/CHANGELOG | ||
---|---|---|
1 | 1 |
== Redmine changelog |
2 | 2 | |
3 | 3 |
Redmine - project management software |
4 |
Copyright (C) 2006-2008 Jean-Philippe Lang
|
|
4 |
Copyright (C) 2006-2009 Jean-Philippe Lang
|
|
5 | 5 |
http://www.redmine.org/ |
6 | 6 | |
7 | 7 | |
8 |
== v0.8.1 |
|
8 |
== 2009-02-15 v0.8.1
|
|
9 | 9 | |
10 | 10 |
* Select watchers on new issue form |
11 |
* Issue description is no longer a required field |
|
11 | 12 |
* Files module: ability to add files without version |
13 |
* Jump to the current tab when using the project quick-jump combo |
|
14 |
* Display a warning if some attachments were not saved |
|
15 |
* Import custom fields values from emails on issue creation |
|
12 | 16 |
* Show view/annotate/download links on entry and annotate views |
17 |
* Admin Info Screen: Display if plugin assets directory is writable |
|
18 |
* Adds a 'Create and continue' button on the new issue form |
|
19 |
* IMAP: add options to move received emails |
|
20 |
* Do not show Category field when categories are not defined |
|
21 |
* Lower the project identifier limit to a minimum of two characters |
|
22 |
* Add "closed" html class to closed entries in issue list |
|
23 |
* Fixed: broken redirect URL on login failure |
|
13 | 24 |
* Fixed: Deleted files are shown when using Darcs |
25 |
* Fixed: Darcs adapter works on Win32 only |
|
26 |
* Fixed: syntax highlight doesn't appear in new ticket preview |
|
27 |
* Fixed: email notification for changes I make still occurs when running Repository.fetch_changesets |
|
28 |
* Fixed: no error is raised when entering invalid hours on the issue update form |
|
29 |
* Fixed: Details time log report CSV export doesn't honour date format from settings |
|
30 |
* Fixed: invalid css classes on issue details |
|
31 |
* Fixed: Trac importer creates duplicate custom values |
|
32 |
* Fixed: inline attached image should not match partial filename |
|
14 | 33 | |
15 | 34 | |
16 | 35 |
== 2008-12-30 v0.8.0 |
17 |
- |
app/controllers/documents_controller.rb | ||
---|---|---|
54 | 54 |
end |
55 | 55 |
|
56 | 56 |
def edit |
57 |
@categories = Enumeration::get_values('DCAT')
|
|
57 |
@categories = Enumeration.document_categories
|
|
58 | 58 |
if request.post? and @document.update_attributes(params[:document]) |
59 | 59 |
flash[:notice] = l(:notice_successful_update) |
60 | 60 |
redirect_to :action => 'show', :id => @document |
app/controllers/enumerations_controller.rb | ||
---|---|---|
85 | 85 |
redirect_to :action => 'index' |
86 | 86 |
end |
87 | 87 |
end |
88 |
@enumerations = Enumeration.get_values(@enumeration.opt) - [@enumeration]
|
|
88 |
@enumerations = Enumeration.values(@enumeration.opt) - [@enumeration] |
|
89 | 89 |
#rescue |
90 | 90 |
# flash[:error] = 'Unable to delete enumeration' |
91 | 91 |
# redirect_to :action => 'index' |
app/controllers/issues_controller.rb | ||
---|---|---|
100 | 100 |
@journals.reverse! if User.current.wants_comments_in_reverse_order? |
101 | 101 |
@allowed_statuses = @issue.new_statuses_allowed_to(User.current) |
102 | 102 |
@edit_allowed = User.current.allowed_to?(:edit_issues, @project) |
103 |
@priorities = Enumeration::get_values('IPRI')
|
|
103 |
@priorities = Enumeration.priorities
|
|
104 | 104 |
@time_entry = TimeEntry.new |
105 | 105 |
respond_to do |format| |
106 | 106 |
format.html { render :template => 'issues/show.rhtml' } |
... | ... | |
153 | 153 |
return |
154 | 154 |
end |
155 | 155 |
end |
156 |
@priorities = Enumeration::get_values('IPRI')
|
|
156 |
@priorities = Enumeration.priorities
|
|
157 | 157 |
render :layout => !request.xhr? |
158 | 158 |
end |
159 | 159 |
|
... | ... | |
163 | 163 |
|
164 | 164 |
def edit |
165 | 165 |
@allowed_statuses = @issue.new_statuses_allowed_to(User.current) |
166 |
@priorities = Enumeration::get_values('IPRI')
|
|
166 |
@priorities = Enumeration.priorities
|
|
167 | 167 |
@edit_allowed = User.current.allowed_to?(:edit_issues, @project) |
168 | 168 |
@time_entry = TimeEntry.new |
169 | 169 |
|
... | ... | |
403 | 403 |
@assignables << @issue.assigned_to if @issue && @issue.assigned_to && !@assignables.include?(@issue.assigned_to) |
404 | 404 |
end |
405 | 405 |
|
406 |
@priorities = Enumeration.get_values('IPRI').reverse
|
|
406 |
@priorities = Enumeration.priorities.reverse
|
|
407 | 407 |
@statuses = IssueStatus.find(:all, :order => 'position') |
408 | 408 |
@back = request.env['HTTP_REFERER'] |
409 | 409 |
|
app/controllers/reports_controller.rb | ||
---|---|---|
37 | 37 |
render :template => "reports/issue_report_details" |
38 | 38 |
when "priority" |
39 | 39 |
@field = "priority_id" |
40 |
@rows = Enumeration::get_values('IPRI')
|
|
40 |
@rows = Enumeration.priorities
|
|
41 | 41 |
@data = issues_by_priority |
42 | 42 |
@report_title = l(:field_priority) |
43 | 43 |
render :template => "reports/issue_report_details" |
... | ... | |
68 | 68 |
else |
69 | 69 |
@trackers = @project.trackers |
70 | 70 |
@versions = @project.versions.sort |
71 |
@priorities = Enumeration::get_values('IPRI')
|
|
71 |
@priorities = Enumeration.priorities
|
|
72 | 72 |
@categories = @project.issue_categories |
73 | 73 |
@assignees = @project.members.collect { |m| m.user } |
74 | 74 |
@authors = @project.members.collect { |m| m.user } |
app/helpers/timelog_helper.rb | ||
---|---|---|
27 | 27 |
end |
28 | 28 |
|
29 | 29 |
def activity_collection_for_select_options |
30 |
activities = Enumeration::get_values('ACTI')
|
|
30 |
activities = Enumeration.activities
|
|
31 | 31 |
collection = [] |
32 | 32 |
collection << [ "--- #{l(:actionview_instancetag_blank_option)} ---", '' ] unless activities.detect(&:is_default) |
33 | 33 |
activities.each { |a| collection << [a.name, a.id] } |
app/models/document.rb | ||
---|---|---|
31 | 31 |
|
32 | 32 |
def after_initialize |
33 | 33 |
if new_record? |
34 |
self.category ||= Enumeration.default('DCAT')
|
|
34 |
self.category ||= Enumeration.document_categories.default
|
|
35 | 35 |
end |
36 | 36 |
end |
37 | 37 |
end |
app/models/enumeration.rb | ||
---|---|---|
26 | 26 | |
27 | 27 |
# Single table inheritance would be an option |
28 | 28 |
OPTIONS = { |
29 |
"IPRI" => {:label => :enumeration_issue_priorities, :model => Issue, :foreign_key => :priority_id}, |
|
30 |
"DCAT" => {:label => :enumeration_doc_categories, :model => Document, :foreign_key => :category_id}, |
|
31 |
"ACTI" => {:label => :enumeration_activities, :model => TimeEntry, :foreign_key => :activity_id} |
|
29 |
"IPRI" => {:label => :enumeration_issue_priorities, :model => Issue, :foreign_key => :priority_id, :scope => :priorities},
|
|
30 |
"DCAT" => {:label => :enumeration_doc_categories, :model => Document, :foreign_key => :category_id, :scope => :document_categories},
|
|
31 |
"ACTI" => {:label => :enumeration_activities, :model => TimeEntry, :foreign_key => :activity_id, :scope => :activities}
|
|
32 | 32 |
}.freeze |
33 | 33 |
|
34 |
def self.get_values(option) |
|
35 |
find(:all, :conditions => {:opt => option}, :order => 'position') |
|
34 |
# Creates a named scope for each type of value. The scope has a +default+ method |
|
35 |
# that returns the default value, or nil if no value is set as default. |
|
36 |
# Example: |
|
37 |
# Enumeration.priorities |
|
38 |
# Enumeration.priorities.default |
|
39 |
OPTIONS.each do |k, v| |
|
40 |
next unless v[:scope] |
|
41 |
named_scope v[:scope], :conditions => { :opt => k }, :order => 'position' do |
|
42 |
def default |
|
43 |
find(:first, :conditions => { :is_default => true }) |
|
44 |
end |
|
45 |
end |
|
36 | 46 |
end |
37 | 47 |
|
38 |
def self.default(option) |
|
39 |
find(:first, :conditions => {:opt => option, :is_default => true}, :order => 'position') |
|
48 |
named_scope :values, lambda {|opt| { :conditions => { :opt => opt }, :order => 'position' } } do |
|
49 |
def default |
|
50 |
find(:first, :conditions => { :is_default => true }) |
|
51 |
end |
|
40 | 52 |
end |
41 | 53 | |
42 | 54 |
def option_name |
app/models/issue.rb | ||
---|---|---|
63 | 63 |
if new_record? |
64 | 64 |
# set default values for new records only |
65 | 65 |
self.status ||= IssueStatus.default |
66 |
self.priority ||= Enumeration.default('IPRI')
|
|
66 |
self.priority ||= Enumeration.priorities.default
|
|
67 | 67 |
end |
68 | 68 |
end |
69 | 69 |
|
app/models/time_entry.rb | ||
---|---|---|
37 | 37 | |
38 | 38 |
def after_initialize |
39 | 39 |
if new_record? && self.activity.nil? |
40 |
if default_activity = Enumeration.default('ACTI')
|
|
40 |
if default_activity = Enumeration.activities.default
|
|
41 | 41 |
self.activity_id = default_activity.id |
42 | 42 |
end |
43 | 43 |
end |
app/views/documents/_form.rhtml | ||
---|---|---|
2 | 2 |
<div class="box"> |
3 | 3 |
<!--[form:document]--> |
4 | 4 |
<p><label for="document_category_id"><%=l(:field_category)%></label> |
5 |
<%= select('document', 'category_id', Enumeration.get_values('DCAT').collect {|c| [c.name, c.id]}) %></p>
|
|
5 |
<%= select('document', 'category_id', Enumeration.document_categories.collect {|c| [c.name, c.id]}) %></p>
|
|
6 | 6 | |
7 | 7 |
<p><label for="document_title"><%=l(:field_title)%> <span class="required">*</span></label> |
8 | 8 |
<%= text_field 'document', 'title', :size => 60 %></p> |
app/views/enumerations/list.rhtml | ||
---|---|---|
3 | 3 |
<% Enumeration::OPTIONS.each do |option, params| %> |
4 | 4 |
<h3><%= l(params[:label]) %></h3> |
5 | 5 | |
6 |
<% enumerations = Enumeration.get_values(option) %>
|
|
6 |
<% enumerations = Enumeration.values(option) %> |
|
7 | 7 |
<% if enumerations.any? %> |
8 | 8 |
<table class="list"> |
9 | 9 |
<% enumerations.each do |enumeration| %> |
app/views/issues/bulk_edit.rhtml | ||
---|---|---|
13 | 13 |
<%= select_tag('status_id', "<option value=\"\">#{l(:label_no_change_option)}</option>" + options_from_collection_for_select(@available_statuses, :id, :name)) %></label> |
14 | 14 |
<% end %> |
15 | 15 |
<label><%= l(:field_priority) %>: |
16 |
<%= select_tag('priority_id', "<option value=\"\">#{l(:label_no_change_option)}</option>" + options_from_collection_for_select(Enumeration.get_values('IPRI'), :id, :name)) %></label>
|
|
16 |
<%= select_tag('priority_id', "<option value=\"\">#{l(:label_no_change_option)}</option>" + options_from_collection_for_select(Enumeration.priorities, :id, :name)) %></label>
|
|
17 | 17 |
<label><%= l(:field_category) %>: |
18 | 18 |
<%= select_tag('category_id', content_tag('option', l(:label_no_change_option), :value => '') + |
19 | 19 |
content_tag('option', l(:label_none), :value => 'none') + |
lib/tasks/migrate_from_mantis.rake | ||
---|---|---|
40 | 40 |
90 => closed_status # closed |
41 | 41 |
} |
42 | 42 |
|
43 |
priorities = Enumeration.get_values('IPRI')
|
|
43 |
priorities = Enumeration.priorities
|
|
44 | 44 |
DEFAULT_PRIORITY = priorities[2] |
45 | 45 |
PRIORITY_MAPPING = {10 => priorities[1], # none |
46 | 46 |
20 => priorities[1], # low |
lib/tasks/migrate_from_trac.rake | ||
---|---|---|
37 | 37 |
'closed' => closed_status |
38 | 38 |
} |
39 | 39 | |
40 |
priorities = Enumeration.get_values('IPRI')
|
|
40 |
priorities = Enumeration.priorities
|
|
41 | 41 |
DEFAULT_PRIORITY = priorities[0] |
42 | 42 |
PRIORITY_MAPPING = {'lowest' => priorities[0], |
43 | 43 |
'low' => priorities[0], |
test/functional/issues_controller_test.rb | ||
---|---|---|
640 | 640 |
:id => 1, |
641 | 641 |
:issue => { :status_id => 2, :assigned_to_id => 3 }, |
642 | 642 |
:notes => 'Assigned to dlopper', |
643 |
:time_entry => { :hours => '', :comments => '', :activity_id => Enumeration.get_values('ACTI').first }
|
|
643 |
:time_entry => { :hours => '', :comments => '', :activity_id => Enumeration.activities.first }
|
|
644 | 644 |
end |
645 | 645 |
assert_redirected_to :action => 'show', :id => '1' |
646 | 646 |
issue.reload |
... | ... | |
676 | 676 |
post :edit, |
677 | 677 |
:id => 1, |
678 | 678 |
:notes => '2.5 hours added', |
679 |
:time_entry => { :hours => '2.5', :comments => '', :activity_id => Enumeration.get_values('ACTI').first }
|
|
679 |
:time_entry => { :hours => '2.5', :comments => '', :activity_id => Enumeration.activities.first }
|
|
680 | 680 |
end |
681 | 681 |
assert_redirected_to :action => 'show', :id => '1' |
682 | 682 |
|
test/unit/enumeration_test.rb | ||
---|---|---|
38 | 38 |
end |
39 | 39 |
|
40 | 40 |
def test_default |
41 |
e = Enumeration.default('IPRI')
|
|
41 |
e = Enumeration.priorities.default
|
|
42 | 42 |
assert e.is_a?(Enumeration) |
43 | 43 |
assert e.is_default? |
44 | 44 |
assert_equal 'Normal', e.name |
... | ... | |
47 | 47 |
def test_create |
48 | 48 |
e = Enumeration.new(:opt => 'IPRI', :name => 'Very urgent', :is_default => false) |
49 | 49 |
assert e.save |
50 |
assert_equal 'Normal', Enumeration.default('IPRI').name
|
|
50 |
assert_equal 'Normal', Enumeration.priorities.default.name
|
|
51 | 51 |
end |
52 | 52 |
|
53 | 53 |
def test_create_as_default |
54 | 54 |
e = Enumeration.new(:opt => 'IPRI', :name => 'Very urgent', :is_default => true) |
55 | 55 |
assert e.save |
56 |
assert_equal e, Enumeration.default('IPRI')
|
|
56 |
assert_equal e, Enumeration.priorities.default
|
|
57 | 57 |
end |
58 | 58 |
|
59 | 59 |
def test_update_default |
60 |
e = Enumeration.default('IPRI')
|
|
60 |
e = Enumeration.priorities.default
|
|
61 | 61 |
e.update_attributes(:name => 'Changed', :is_default => true) |
62 |
assert_equal e, Enumeration.default('IPRI')
|
|
62 |
assert_equal e, Enumeration.priorities.default
|
|
63 | 63 |
end |
64 | 64 |
|
65 | 65 |
def test_update_default_to_non_default |
66 |
e = Enumeration.default('IPRI')
|
|
66 |
e = Enumeration.priorities.default
|
|
67 | 67 |
e.update_attributes(:name => 'Changed', :is_default => false) |
68 |
assert_nil Enumeration.default('IPRI')
|
|
68 |
assert_nil Enumeration.priorities.default
|
|
69 | 69 |
end |
70 | 70 |
|
71 | 71 |
def test_change_default |
72 | 72 |
e = Enumeration.find_by_name('Urgent') |
73 | 73 |
e.update_attributes(:name => 'Urgent', :is_default => true) |
74 |
assert_equal e, Enumeration.default('IPRI')
|
|
74 |
assert_equal e, Enumeration.priorities.default
|
|
75 | 75 |
end |
76 | 76 |
|
77 | 77 |
def test_destroy_with_reassign |
test/unit/issue_test.rb | ||
---|---|---|
27 | 27 |
:time_entries |
28 | 28 | |
29 | 29 |
def test_create |
30 |
issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3, :status_id => 1, :priority => Enumeration.get_values('IPRI').first, :subject => 'test_create', :description => 'IssueTest#test_create', :estimated_hours => '1:30')
|
|
30 |
issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3, :status_id => 1, :priority => Enumeration.priorities.first, :subject => 'test_create', :description => 'IssueTest#test_create', :estimated_hours => '1:30')
|
|
31 | 31 |
assert issue.save |
32 | 32 |
issue.reload |
33 | 33 |
assert_equal 1.5, issue.estimated_hours |
34 | 34 |
end |
35 | 35 |
|
36 | 36 |
def test_create_minimal |
37 |
issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3, :status_id => 1, :priority => Enumeration.get_values('IPRI').first, :subject => 'test_create')
|
|
37 |
issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3, :status_id => 1, :priority => Enumeration.priorities.first, :subject => 'test_create')
|
|
38 | 38 |
assert issue.save |
39 | 39 |
assert issue.description.nil? |
40 | 40 |
end |
... | ... | |
110 | 110 |
end |
111 | 111 |
|
112 | 112 |
def test_category_based_assignment |
113 |
issue = Issue.create(:project_id => 1, :tracker_id => 1, :author_id => 3, :status_id => 1, :priority => Enumeration.get_values('IPRI').first, :subject => 'Assignment test', :description => 'Assignment test', :category_id => 1)
|
|
113 |
issue = Issue.create(:project_id => 1, :tracker_id => 1, :author_id => 3, :status_id => 1, :priority => Enumeration.priorities.first, :subject => 'Assignment test', :description => 'Assignment test', :category_id => 1)
|
|
114 | 114 |
assert_equal IssueCategory.find(1).assigned_to, issue.assigned_to |
115 | 115 |
end |
116 | 116 |
|
... | ... | |
126 | 126 |
|
127 | 127 |
def test_should_close_duplicates |
128 | 128 |
# Create 3 issues |
129 |
issue1 = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :priority => Enumeration.get_values('IPRI').first, :subject => 'Duplicates test', :description => 'Duplicates test')
|
|
129 |
issue1 = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :priority => Enumeration.priorities.first, :subject => 'Duplicates test', :description => 'Duplicates test')
|
|
130 | 130 |
assert issue1.save |
131 | 131 |
issue2 = issue1.clone |
132 | 132 |
assert issue2.save |
... | ... | |
153 | 153 |
|
154 | 154 |
def test_should_not_close_duplicated_issue |
155 | 155 |
# Create 3 issues |
156 |
issue1 = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :priority => Enumeration.get_values('IPRI').first, :subject => 'Duplicates test', :description => 'Duplicates test')
|
|
156 |
issue1 = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :priority => Enumeration.priorities.first, :subject => 'Duplicates test', :description => 'Duplicates test')
|
|
157 | 157 |
assert issue1.save |
158 | 158 |
issue2 = issue1.clone |
159 | 159 |
assert issue2.save |
160 |
- |
app/models/project.rb | ||
---|---|---|
287 | 287 |
end |
288 | 288 |
|
289 | 289 |
def enabled_module_names=(module_names) |
290 |
enabled_modules.clear |
|
291 |
module_names = [] unless module_names && module_names.is_a?(Array) |
|
292 |
module_names.each do |name| |
|
293 |
enabled_modules << EnabledModule.new(:name => name.to_s) |
|
290 |
if module_names && module_names.is_a?(Array) |
|
291 |
module_names = module_names.collect(&:to_s) |
|
292 |
# remove disabled modules |
|
293 |
enabled_modules.each {|mod| mod.destroy unless module_names.include?(mod.name)} |
|
294 |
# add new modules |
|
295 |
module_names.each {|name| enabled_modules << EnabledModule.new(:name => name)} |
|
296 |
else |
|
297 |
enabled_modules.clear |
|
294 | 298 |
end |
295 | 299 |
end |
296 | 300 |
|
test/unit/project_test.rb | ||
---|---|---|
18 | 18 |
require File.dirname(__FILE__) + '/../test_helper' |
19 | 19 |
|
20 | 20 |
class ProjectTest < Test::Unit::TestCase |
21 |
fixtures :projects, :issues, :issue_statuses, :journals, :journal_details, :users, :members, :roles, :projects_trackers, :trackers, :boards |
|
21 |
fixtures :projects, :enabled_modules, |
|
22 |
:issues, :issue_statuses, :journals, :journal_details, |
|
23 |
:users, :members, :roles, :projects_trackers, :trackers, :boards |
|
22 | 24 |
|
23 | 25 |
def setup |
24 | 26 |
@ecookbook = Project.find(1) |
... | ... | |
218 | 220 |
Project.delete_all |
219 | 221 |
assert_nil Project.next_identifier |
220 | 222 |
end |
223 |
|
|
224 |
def test_enabled_module_names_should_not_recreate_enabled_modules |
|
225 |
project = Project.find(1) |
|
226 |
# Remove one module |
|
227 |
modules = project.enabled_modules.slice(0..-2) |
|
228 |
assert modules.any? |
|
229 |
assert_difference 'EnabledModule.count', -1 do |
|
230 |
project.enabled_module_names = modules.collect(&:name) |
|
231 |
end |
|
232 |
project.reload |
|
233 |
# Ids should be preserved |
|
234 |
assert_equal project.enabled_module_ids.sort, modules.collect(&:id).sort |
|
235 |
end |
|
221 | 236 |
end |
222 |
- |
app/models/enabled_module.rb | ||
---|---|---|
1 |
# redMine - project management software
|
|
2 |
# Copyright (C) 2006-2007 Jean-Philippe Lang
|
|
1 |
# Redmine - project management software
|
|
2 |
# Copyright (C) 2006-2009 Jean-Philippe Lang
|
|
3 | 3 |
# |
4 | 4 |
# This program is free software; you can redistribute it and/or |
5 | 5 |
# modify it under the terms of the GNU General Public License |
... | ... | |
20 | 20 |
|
21 | 21 |
validates_presence_of :name |
22 | 22 |
validates_uniqueness_of :name, :scope => :project_id |
23 |
|
|
24 |
after_create :module_enabled |
|
25 |
|
|
26 |
private |
|
27 |
|
|
28 |
# after_create callback used to do things when a module is enabled |
|
29 |
def module_enabled |
|
30 |
case name |
|
31 |
when 'wiki' |
|
32 |
# Create a wiki with a default start page |
|
33 |
if project && project.wiki.nil? |
|
34 |
Wiki.create(:project => project, :start_page => 'Wiki') |
|
35 |
end |
|
36 |
end |
|
37 |
end |
|
23 | 38 |
end |
test/unit/enabled_module_test.rb | ||
---|---|---|
1 |
# Redmine - project management software |
|
2 |
# Copyright (C) 2006-2009 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 |
require File.dirname(__FILE__) + '/../test_helper' |
|
19 | ||
20 |
class EnabledModuleTest < Test::Unit::TestCase |
|
21 |
fixtures :projects, :wikis |
|
22 |
|
|
23 |
def test_enabling_wiki_should_create_a_wiki |
|
24 |
CustomField.delete_all |
|
25 |
project = Project.create!(:name => 'Project with wiki', :identifier => 'wikiproject') |
|
26 |
assert_nil project.wiki |
|
27 |
project.enabled_module_names = ['wiki'] |
|
28 |
project.reload |
|
29 |
assert_not_nil project.wiki |
|
30 |
assert_equal 'Wiki', project.wiki.start_page |
|
31 |
end |
|
32 |
|
|
33 |
def test_reenabling_wiki_should_not_create_another_wiki |
|
34 |
project = Project.find(1) |
|
35 |
assert_not_nil project.wiki |
|
36 |
project.enabled_module_names = [] |
|
37 |
project.reload |
|
38 |
assert_no_difference 'Wiki.count' do |
|
39 |
project.enabled_module_names = ['wiki'] |
|
40 |
end |
|
41 |
assert_not_nil project.wiki |
|
42 |
end |
|
43 |
end |
|
0 |
- |
app/views/custom_fields/_form.rhtml | ||
---|---|---|
54 | 54 | |
55 | 55 |
<div class="box"> |
56 | 56 |
<p><%= f.text_field :name, :required => true %></p> |
57 |
<p><%= f.select :field_format, custom_field_formats_for_select, {}, :onchange => "toggle_custom_field_format();" %></p> |
|
57 |
<p><%= f.select :field_format, custom_field_formats_for_select, {}, :onchange => "toggle_custom_field_format();", |
|
58 |
:disabled => !@custom_field.new_record? %></p> |
|
58 | 59 |
<p><label for="custom_field_min_length"><%=l(:label_min_max_length)%></label> |
59 | 60 |
<%= f.text_field :min_length, :size => 5, :no_label => true %> - |
60 | 61 |
<%= f.text_field :max_length, :size => 5, :no_label => true %><br>(<%=l(:text_min_max_length_info)%>)</p> |
61 |
- |
app/models/user.rb | ||
---|---|---|
81 | 81 |
end |
82 | 82 |
|
83 | 83 |
def identity_url=(url) |
84 |
begin |
|
85 |
self.write_attribute(:identity_url, OpenIdAuthentication.normalize_identifier(url)) |
|
86 |
rescue InvalidOpenId |
|
87 |
# Invlaid url, don't save |
|
84 |
if url.blank? |
|
85 |
write_attribute(:identity_url, '') |
|
86 |
else |
|
87 |
begin |
|
88 |
write_attribute(:identity_url, OpenIdAuthentication.normalize_identifier(url)) |
|
89 |
rescue OpenIdAuthentication::InvalidOpenId |
|
90 |
# Invlaid url, don't save |
|
91 |
end |
|
88 | 92 |
end |
89 | 93 |
self.read_attribute(:identity_url) |
90 | 94 |
end |
test/unit/user_test.rb | ||
---|---|---|
204 | 204 |
u = User.new( :identity_url => 'example.com' ) |
205 | 205 |
assert_equal normalized_open_id_url, u.identity_url |
206 | 206 |
end |
207 |
|
|
208 |
def test_setting_blank_identity_url |
|
209 |
u = User.new( :identity_url => 'example.com' ) |
|
210 |
u.identity_url = '' |
|
211 |
assert u.identity_url.blank? |
|
212 |
end |
|
213 |
|
|
214 |
def test_setting_invalid_identity_url |
|
215 |
u = User.new( :identity_url => 'this is not an openid url' ) |
|
216 |
assert u.identity_url.blank? |
|
217 |
end |
|
207 | 218 |
|
208 | 219 |
else |
209 | 220 |
puts "Skipping openid tests." |
210 |
- |
extra/svn/reposman.rb | ||
---|---|---|
26 | 26 |
# allow user to browse the repository within |
27 | 27 |
# Redmine even for private project. If you want to share repositories |
28 | 28 |
# through Redmine.pm, you need to use the apache owner. |
29 |
# -g, --group=GROUP group of the repository. (default: root) |
|
29 | 30 |
# --scm=SCM the kind of SCM repository you want to create (and register) in |
30 | 31 |
# Redmine (default: Subversion). reposman is able to create Git |
31 | 32 |
# and Subversion repositories. For all other kind (Bazaar, |
... | ... | |
60 | 61 |
require 'find' |
61 | 62 |
require 'etc' |
62 | 63 | |
63 |
Version = "1.2"
|
|
64 |
Version = "1.3"
|
|
64 | 65 |
SUPPORTED_SCM = %w( Subversion Darcs Mercurial Bazaar Git Filesystem ) |
65 | 66 | |
66 | 67 |
opts = GetoptLong.new( |
67 | 68 |
['--svn-dir', '-s', GetoptLong::REQUIRED_ARGUMENT], |
68 | 69 |
['--redmine-host', '-r', GetoptLong::REQUIRED_ARGUMENT], |
69 | 70 |
['--owner', '-o', GetoptLong::REQUIRED_ARGUMENT], |
71 |
['--group', '-g', GetoptLong::REQUIRED_ARGUMENT], |
|
70 | 72 |
['--url', '-u', GetoptLong::REQUIRED_ARGUMENT], |
71 | 73 |
['--command' , '-c', GetoptLong::REQUIRED_ARGUMENT], |
72 | 74 |
['--scm', GetoptLong::REQUIRED_ARGUMENT], |
... | ... | |
83 | 85 |
$redmine_host = '' |
84 | 86 |
$repos_base = '' |
85 | 87 |
$svn_owner = 'root' |
88 |
$svn_group = 'root' |
|
86 | 89 |
$use_groupid = true |
87 | 90 |
$svn_url = false |
88 | 91 |
$test = false |
... | ... | |
125 | 128 |
when '--svn-dir'; $repos_base = arg.dup |
126 | 129 |
when '--redmine-host'; $redmine_host = arg.dup |
127 | 130 |
when '--owner'; $svn_owner = arg.dup; $use_groupid = false; |
131 |
when '--group'; $svn_group = arg.dup; $use_groupid = false; |
|
128 | 132 |
when '--url'; $svn_url = arg.dup |
129 | 133 |
when '--scm'; $scm = arg.dup.capitalize; log("Invalid SCM: #{$scm}", :exit => true) unless SUPPORTED_SCM.include?($scm) |
130 | 134 |
when '--command'; $command = arg.dup |
... | ... | |
195 | 199 |
if RUBY_PLATFORM =~ /mswin/ |
196 | 200 |
yield if block_given? |
197 | 201 |
else |
198 |
uid, gid = Etc.getpwnam($svn_owner).uid, ($use_groupid ? Etc.getgrnam(project.identifier).gid : 0)
|
|
202 |
uid, gid = Etc.getpwnam($svn_owner).uid, ($use_groupid ? Etc.getgrnam(project.identifier).gid : Etc.getgrnam($svn_group).gid)
|
|
199 | 203 |
right = project.is_public ? 0775 : 0770 |
200 | 204 |
yield if block_given? |
201 | 205 |
Find.find(repos_path) do |f| |
202 |
- |
lang/ru.yml | ||
---|---|---|
729 | 729 |
text_user_wrote: '%s написал(а):' |
730 | 730 |
text_wiki_destroy_confirmation: Вы уверены, что хотите удалить данную Wiki и все ее содержимое? |
731 | 731 |
text_workflow_edit: Выберите роль и трекер для редактирования последовательности состояний |
732 | ||
733 | 732 |
text_plugin_assets_writable: Каталог для плагинов доступен по записи |
734 | 733 |
warning_attachments_not_saved: "%d файл(ов) невозможно сохранить." |
735 | 734 |
button_create_and_continue: Создать и продолжить |
736 | 735 |
text_custom_field_possible_values_info: 'По одному значению в каждой строке' |
737 | 736 |
label_display: Отображение |
738 | 737 |
field_editable: Редактируемый |
739 | ||
740 |
setting_repository_log_display_limit: Maximum number of revisions displayed on file log |
|
738 |
setting_repository_log_display_limit: Максимальное количество отображаемых ревизий в журнале файлов |
|
741 | 739 |
field_identity_url: OpenID URL |
742 |
setting_openid: Allow OpenID login and registration |
|
743 |
label_login_with_open_id_option: or login with OpenID |
|
744 |
field_watcher: Watcher |
|
740 |
setting_openid: Разрешать вход и регистрацию под логином OpenID |
|
741 |
label_login_with_open_id_option: или войти с помощью OpenID |
|
742 |
field_watcher: Наблюдатель |
|
743 |
lang/zh-tw.yml | ||
---|---|---|
147 | 147 |
field_admin: 管理者 |
148 | 148 |
field_last_login_on: 最近連線日期 |
149 | 149 |
field_language: 語系 |
150 |
field_identity_url: OpenID 網址 |
|
150 | 151 |
field_effective_date: 日期 |
151 | 152 |
field_password: 目前密碼 |
152 | 153 |
field_new_password: 新密碼 |
... | ... | |
187 | 188 |
field_comments_sorting: 註解排序 |
188 | 189 |
field_parent_title: 父頁面 |
189 | 190 |
field_editable: 可編輯 |
191 |
field_watcher: 觀察者 |
|
190 | 192 | |
191 | 193 |
setting_app_title: 標題 |
192 | 194 |
setting_app_subtitle: 副標題 |
... | ... | |
228 | 230 |
setting_gravatar_enabled: 啟用 Gravatar 全球認證大頭像 |
229 | 231 |
setting_diff_max_lines_displayed: 差異顯示行數之最大值 |
230 | 232 |
setting_repository_log_display_limit: 版次顯示數目之最大值 |
233 |
setting_openid: 允許使用 OpenID 登入與註冊 |
|
231 | 234 | |
232 | 235 |
permission_edit_project: 編輯專案 |
233 | 236 |
permission_select_project_modules: 選擇專案模組 |
... | ... | |
332 | 335 |
label_information_plural: 資訊 |
333 | 336 |
label_please_login: 請先登入 |
334 | 337 |
label_register: 註冊 |
338 |
label_login_with_open_id_option: 或使用 OpenID 登入 |
|
335 | 339 |
label_password_lost: 遺失密碼 |
336 | 340 |
label_home: 網站首頁 |
337 | 341 |
label_my_page: 帳戶首頁 |
... | ... | |
706 | 710 |
enumeration_issue_priorities: 項目優先權 |
707 | 711 |
enumeration_doc_categories: 文件分類 |
708 | 712 |
enumeration_activities: 活動 (時間追蹤) |
709 |
field_identity_url: OpenID URL |
|
710 |
setting_openid: Allow OpenID login and registration |
|
711 |
label_login_with_open_id_option: or login with OpenID |
|
712 |
field_watcher: Watcher |
lang/zh.yml | ||
---|---|---|
147 | 147 |
field_admin: 管理员 |
148 | 148 |
field_last_login_on: 最后登录 |
149 | 149 |
field_language: 语言 |
150 |
field_identity_url: OpenID URL |
|
150 | 151 |
field_effective_date: 日期 |
151 | 152 |
field_password: 密码 |
152 | 153 |
field_new_password: 新密码 |
... | ... | |
187 | 188 |
field_comments_sorting: 显示注释 |
188 | 189 |
field_parent_title: 上级页面 |
189 | 190 |
field_editable: 可编辑 |
191 |
field_watcher: 跟踪者 |
|
190 | 192 | |
191 | 193 |
setting_app_title: 应用程序标题 |
192 | 194 |
setting_app_subtitle: 应用程序子标题 |
... | ... | |
228 | 230 |
setting_gravatar_enabled: 使用Gravatar用户头像 |
229 | 231 |
setting_diff_max_lines_displayed: 查看差别页面上显示的最大行数 |
230 | 232 |
setting_repository_log_display_limit: 在文件变更记录页面上显示的最大修订版本数量 |
233 |
setting_openid: 允许使用OpenID登录和注册 |
|
231 | 234 | |
232 | 235 |
permission_edit_project: 编辑项目 |
233 | 236 |
permission_select_project_modules: 选择项目模块 |
... | ... | |
332 | 335 |
label_information_plural: 信息 |
333 | 336 |
label_please_login: 请登录 |
334 | 337 |
label_register: 注册 |
338 |
label_login_with_open_id_option: 或使用OpenID登录 |
|
335 | 339 |
label_password_lost: 忘记密码 |
336 | 340 |
label_home: 主页 |
337 | 341 |
label_my_page: 我的工作台 |
... | ... | |
562 | 566 |
label_search_titles_only: 仅在标题中搜索 |
563 | 567 |
label_user_mail_option_all: "收取我的项目的所有通知" |
564 | 568 |
label_user_mail_option_selected: "收取选中项目的所有通知..." |
565 |
label_user_mail_option_none: "只收取我跟踪或参与的项目的通知"
|
|
569 |
label_user_mail_option_none: "只收取我跟踪或参与的事情的通知"
|
|
566 | 570 |
label_user_mail_no_self_notified: "不要发送对我自己提交的修改的通知" |
567 | 571 |
label_registration_activation_by_email: 通过邮件认证激活帐号 |
568 | 572 |
label_registration_manual_activation: 手动激活帐号 |
... | ... | |
706 | 710 |
enumeration_issue_priorities: 问题优先级 |
707 | 711 |
enumeration_doc_categories: 文档类别 |
708 | 712 |
enumeration_activities: 活动(时间跟踪) |
709 |
field_identity_url: OpenID URL |
|
710 |
setting_openid: Allow OpenID login and registration |
|
711 |
label_login_with_open_id_option: or login with OpenID |
|
712 |
field_watcher: Watcher |
|
713 |
- |
lang/hu.yml | ||
---|---|---|
705 | 705 |
field_editable: Szerkeszthető |
706 | 706 |
setting_repository_log_display_limit: Maximum hány revízió jelenjen meg a fájl logban |
707 | 707 |
field_identity_url: OpenID URL |
708 |
setting_openid: Allow OpenID login and registration |
|
709 |
label_login_with_open_id_option: or login with OpenID |
|
710 |
field_watcher: Watcher |
|
708 |
setting_openid: OpenID bejelentkezés és regisztráció engedélyezése |
|
709 |
label_login_with_open_id_option: vagy bejelentkezés OpenID használatával |
|
710 |
field_watcher: Megfigyelő |
lang/pl.yml | ||
---|---|---|
40 | 40 |
activerecord_error_not_a_date: nie jest prawidłową datą |
41 | 41 |
activerecord_error_not_a_number: nie jest numerem |
42 | 42 |
activerecord_error_not_same_project: nie należy do tego samego projektu |
43 |
activerecord_error_taken: jest już wybrane
|
|
43 |
activerecord_error_taken: jest już zajęte
|
|
44 | 44 |
activerecord_error_too_long: jest za długie |
45 | 45 |
activerecord_error_too_short: jest za krótkie |
46 | 46 |
activerecord_error_wrong_length: ma złą długość |
... | ... | |
654 | 654 |
setting_plain_text_mail: tylko tekst (bez HTML) |
655 | 655 |
setting_protocol: Protokoł |
656 | 656 |
setting_repositories_encodings: Kodowanie repozytoriów |
657 |
setting_self_registration: Własna rejestracja umożliwiona
|
|
657 |
setting_self_registration: Samodzielna rejestracja użtytkowników
|
|
658 | 658 |
setting_sequential_project_identifiers: Generuj sekwencyjne identyfikatory projektów |
659 | 659 |
setting_sys_api_enabled: Włączenie WS do zarządzania repozytorium |
660 | 660 |
setting_text_formatting: Formatowanie tekstu |
... | ... | |
716 | 716 |
text_diff_truncated: '... Ten plik różnic został przycięty ponieważ jest zbyt długi.' |
717 | 717 |
setting_diff_max_lines_displayed: Maksymalna liczba linii różnicy do pokazania |
718 | 718 |
text_plugin_assets_writable: Zapisywalny katalog zasobów wtyczek |
719 |
warning_attachments_not_saved: "%d file(s) could not be saved." |
|
720 |
field_editable: Editable |
|
721 |
label_display: Display |
|
722 |
button_create_and_continue: Create and continue |
|
723 |
text_custom_field_possible_values_info: 'One line for each value' |
|
724 |
setting_repository_log_display_limit: Maximum number of revisions displayed on file log |
|
725 |
field_identity_url: OpenID URL |
|
726 |
setting_openid: Allow OpenID login and registration |
|
727 |
label_login_with_open_id_option: or login with OpenID |
|
728 |
field_watcher: Watcher |
|
719 |
warning_attachments_not_saved: "%d załącznik(ów) nie zostało zapisanych." |
|
720 |
field_editable: Edytowalne |
|
721 |
label_display: Wygląd |
|
722 |
button_create_and_continue: Stwórz i dodaj kolejne |
|
723 |
text_custom_field_possible_values_info: 'Każda wartość w osobnej linii' |
|
724 |
setting_repository_log_display_limit: Maksymalna liczba rewizji wyświetlanych w logu pliku |
|
725 |
field_identity_url: Identyfikator OpenID (URL) |
|
726 |
setting_openid: Logowanie i rejestracja przy użyciu OpenID |
|
727 |
label_login_with_open_id_option: albo użyj OpenID |
|
728 |
field_watcher: Obserwator |
lang/pt-br.yml | ||
---|---|---|
694 | 694 |
permission_edit_own_messages: Editar próprias mensagens |
695 | 695 |
permission_delete_own_messages: Excluir próprias mensagens |
696 | 696 |
label_user_activity: "Atividade de %s" |
697 |
label_updated_time_by: Atualizado por %s à %s
|
|
697 |
label_updated_time_by: Atualizado por %s há %s
|
|
698 | 698 |
text_diff_truncated: '... Este diff foi truncado porque excede o tamanho máximo que pode ser exibido.' |
699 | 699 |
setting_diff_max_lines_displayed: Número máximo de linhas exibidas no diff |
700 | 700 |
text_plugin_assets_writable: Diretório de plugins gravável |
lang/sv.yml | ||
---|---|---|
63 | 63 |
notice_can_t_change_password: Detta konto använder en extern autentiseringskälla. Det går inte att byta lösenord. |
64 | 64 |
notice_account_lost_email_sent: Ett mail med instruktioner om hur man väljer ett nytt lösenord har skickats till dig. |
65 | 65 |
notice_account_activated: Ditt konto har blivit aktiverat. Du kan nu logga in. |
66 |
notice_successful_create: Skapandet lyckades.
|
|
66 |
notice_successful_create: Skapades korrekt.
|
|
67 | 67 |
notice_successful_update: Uppdatering lyckades. |
68 | 68 |
notice_successful_delete: Borttagning lyckades. |
69 | 69 |
notice_successful_connection: Uppkoppling lyckades. |
... | ... | |
80 | 80 |
notice_unable_delete_version: Denna version var inte möjlig att ta bort. |
81 | 81 | |
82 | 82 |
error_can_t_load_default_data: "Standardkonfiguration gick inte att läsa in: %s" |
83 |
error_scm_not_found: "Inlägg och/eller revision finns inte i detta repository."
|
|
84 |
error_scm_command_failed: "Ett fel inträffade vid försök att nå repositoryt: %s"
|
|
83 |
error_scm_not_found: "Inlägg och/eller revision finns inte i detta versionsarkiv."
|
|
84 |
error_scm_command_failed: "Ett fel inträffade vid försök att nå versionsarkivet: %s"
|
|
85 | 85 |
error_scm_annotate: "Inlägget existerar inte eller kan inte kommenteras." |
86 | 86 |
error_issue_not_found_in_project: 'Ärendet hittades inte eller så tillhör det inte detta projekt' |
87 | 87 | |
... | ... | |
147 | 147 |
field_admin: Administratör |
148 | 148 |
field_last_login_on: Senaste inloggning |
149 | 149 |
field_language: Språk |
150 |
field_identity_url: OpenID URL |
|
150 | 151 |
field_effective_date: Datum |
151 | 152 |
field_password: Lösenord |
152 | 153 |
field_new_password: Nytt lösenord |
... | ... | |
187 | 188 |
field_comments_sorting: Visa kommentarer |
188 | 189 |
field_parent_title: Föräldersida |
189 | 190 |
field_editable: Redigerbar |
191 |
field_watcher: Bevakare |
|
190 | 192 | |
191 | 193 |
setting_app_title: Applikationsrubrik |
192 | 194 |
setting_app_subtitle: Applikationsunderrubrik |
... | ... | |
196 | 198 |
setting_self_registration: Självregistrering |
197 | 199 |
setting_attachment_max_size: Maxstorlek på bilaga |
198 | 200 |
setting_issues_export_limit: Exportgräns för ärenden |
199 |
setting_mail_from: Mailavsändare
|
|
201 |
setting_mail_from: Avsändare
|
|
200 | 202 |
setting_bcc_recipients: Hemlig kopia (bcc) till mottagare |
201 | 203 |
setting_plain_text_mail: Oformaterad text i mail (ingen HTML) |
202 | 204 |
setting_host_name: Värddatornamn |
... | ... | |
205 | 207 |
setting_feeds_limit: Innehållsgräns för Feed |
206 | 208 |
setting_default_projects_public: Nya projekt är publika som standard |
207 | 209 |
setting_autofetch_changesets: Automatisk hämtning av commits |
208 |
setting_sys_api_enabled: Aktivera WS för repository-hantering
|
|
210 |
setting_sys_api_enabled: Aktivera WS för versionsarkivhantering
|
|
209 | 211 |
setting_commit_ref_keywords: Referens-nyckelord |
210 | 212 |
setting_commit_fix_keywords: Fix-nyckelord |
211 | 213 |
setting_autologin: Automatisk inloggning |
... | ... | |
213 | 215 |
setting_time_format: Tidsformat |
214 | 216 |
setting_cross_project_issue_relations: Tillåt ärenderelationer mellan projekt |
215 | 217 |
setting_issue_list_default_columns: Standardkolumner i ärendelistan |
216 |
setting_repositories_encodings: Teckenuppsättningar för repositoriy
|
|
218 |
setting_repositories_encodings: Teckenuppsättningar för versionsarkiv
|
|
217 | 219 |
setting_commit_logs_encoding: Teckenuppsättning för commit-meddelanden |
218 |
setting_emails_footer: Mailsignatur
|
|
220 |
setting_emails_footer: Signatur
|
|
219 | 221 |
setting_protocol: Protokoll |
220 | 222 |
setting_per_page_options: Alternativ, objekt per sida |
221 | 223 |
setting_user_format: Visningsformat för användare |
... | ... | |
228 | 230 |
setting_gravatar_enabled: Använd Gravatar-avatarer |
229 | 231 |
setting_diff_max_lines_displayed: Maximalt antal synliga rader i diff |
230 | 232 |
setting_repository_log_display_limit: Maximalt antal revisioner i filloggen |
233 |
setting_openid: Tillåt inloggning och registrering med OpenID |
|
231 | 234 | |
232 | 235 |
permission_edit_project: Ändra projekt |
233 | 236 |
permission_select_project_modules: Välja projektmoduler |
... | ... | |
238 | 241 |
permission_edit_issues: Ändra ärende |
239 | 242 |
permission_manage_issue_relations: Hantera ärenderelationer |
240 | 243 |
permission_add_issue_notes: Lägga till notering |
241 |
permission_edit_issue_notes: Ändra noteringar |
|
242 |
permission_edit_own_issue_notes: Ändra egna noteringar |
|
244 |
permission_edit_issue_notes: Ändra ärendenoteringar
|
|
245 |
permission_edit_own_issue_notes: Ändra egna ärendenoteringar
|
|
243 | 246 |
permission_move_issues: Flytta ärenden |
244 | 247 |
permission_delete_issues: Ta bort ärenden |
245 | 248 |
permission_manage_public_queries: Hantera publika frågor |
... | ... | |
250 | 253 |
permission_add_issue_watchers: Lägga till bevakare |
251 | 254 |
permission_log_time: Logga spenderad tid |
252 | 255 |
permission_view_time_entries: Visa spenderad tid |
253 |
permission_edit_time_entries: Ändra tidloggar |
|
254 |
permission_edit_own_time_entries: Ändra egna tidloggar |
|
256 |
permission_edit_time_entries: Ändra tidloggningar
|
|
257 |
permission_edit_own_time_entries: Ändra egna tidloggningar
|
|
255 | 258 |
permission_manage_news: Hantera nyheter |
256 | 259 |
permission_comment_news: Kommentera nyheter |
257 | 260 |
permission_manage_documents: Hantera dokument |
... | ... | |
266 | 269 |
permission_edit_wiki_pages: Ändra wikisidor |
267 | 270 |
permission_delete_wiki_pages_attachments: Ta bort bilagor |
268 | 271 |
permission_protect_wiki_pages: Skydda wikisidor |
269 |
permission_manage_repository: Hantera repository
|
|
270 |
permission_browse_repository: Bläddra i repository
|
|
272 |
permission_manage_repository: Hantera versionsarkiv
|
|
273 |
permission_browse_repository: Bläddra i versionsarkiv
|
|
271 | 274 |
permission_view_changesets: Visa changesets |
272 |
permission_commit_access: Commit-tillgång
|
|
275 |
permission_commit_access: Commit-åtkomst
|
|
273 | 276 |
permission_manage_boards: Hantera forum |
274 | 277 |
permission_view_messages: Visa meddelanden |
275 | 278 |
permission_add_messages: Lägg till meddelanden |
... | ... | |
283 | 286 |
project_module_documents: Dokument |
284 | 287 |
project_module_files: Filer |
285 | 288 |
project_module_wiki: Wiki |
286 |
project_module_repository: Repository
|
|
289 |
project_module_repository: Versionsarkiv
|
|
287 | 290 |
project_module_boards: Forum |
288 | 291 | |
289 | 292 |
label_user: Användare |
... | ... | |
317 | 320 |
label_tracker_new: Ny ärendetyp |
318 | 321 |
label_workflow: Arbetsflöde |
319 | 322 |
label_issue_status: Ärendestatus |
320 |
label_issue_status_plural: Ärendestatusar
|
|
323 |
label_issue_status_plural: Ärendestatus |
|
321 | 324 |
label_issue_status_new: Ny status |
322 | 325 |
label_issue_category: Ärendekategori |
323 | 326 |
label_issue_category_plural: Ärendekategorier |
... | ... | |
325 | 328 |
label_custom_field: Användardefinerat fält |
326 | 329 |
label_custom_field_plural: Användardefinerade fält |
327 | 330 |
label_custom_field_new: Nytt användardefinerat fält |
328 |
label_enumerations: Enumerationer
|
|
331 |
label_enumerations: Uppräkningar
|
|
329 | 332 |
label_enumeration_new: Nytt värde |
330 | 333 |
label_information: Information |
331 | 334 |
label_information_plural: Information |
332 | 335 |
label_please_login: Var god logga in |
333 | 336 |
label_register: Registrera |
337 |
label_login_with_open_id_option: eller logga in med OpenID |
|
334 | 338 |
label_password_lost: Glömt lösenord |
335 | 339 |
label_home: Hem |
336 | 340 |
label_my_page: Min sida |
... | ... | |
403 | 407 |
label_total: Total |
404 | 408 |
label_permissions: Behörigheter |
405 | 409 |
label_current_status: Nuvarande status |
406 |
label_new_statuses_allowed: Nya statusar tillåtna
|
|
410 |
label_new_statuses_allowed: Nya tillåtna statusvärden
|
|
407 | 411 |
label_all: alla |
408 | 412 |
label_none: ingen |
409 | 413 |
label_nobody: ingen |
... | ... | |
451 | 455 |
label_contains: innehåller |
452 | 456 |
label_not_contains: innehåller inte |
453 | 457 |
label_day_plural: dagar |
454 |
label_repository: Repository
|
|
455 |
label_repository_plural: Repositorys
|
|
458 |
label_repository: Versionsarkiv
|
|
459 |
label_repository_plural: Versionsarkiv
|
|
456 | 460 |
label_browse: Bläddra |
457 | 461 |
label_modification: %d ändring |
458 | 462 |
label_modification_plural: %d ändringar |
... | ... | |
562 | 566 |
label_user_mail_option_all: "För alla händelser i mina projekt" |
563 | 567 |
label_user_mail_option_selected: "För alla händelser i markerade projekt..." |
564 | 568 |
label_user_mail_option_none: "Endast för saker jag bevakar eller är involverad i" |
565 |
label_user_mail_no_self_notified: "Jag vill inte bli notifierad om ändringar som jag har gjort"
|
|
569 |
label_user_mail_no_self_notified: "Jag vill inte bli underrättad om ändringar som jag har gjort"
|
|
566 | 570 |
label_registration_activation_by_email: kontoaktivering med mail |
567 | 571 |
label_registration_manual_activation: manuell kontoaktivering |
568 | 572 |
label_registration_automatic_activation: automatisk kontoaktivering |
... | ... | |
658 | 662 |
text_issue_category_destroy_question: Några ärenden (%d) är tilldelade till denna kategori. Vad vill du göra ? |
659 | 663 |
text_issue_category_destroy_assignments: Ta bort kategoritilldelningar |
660 | 664 |
text_issue_category_reassign_to: Återtilldela ärenden till denna kategori |
661 |
text_user_mail_option: "För omarkerade projekt kommer du bara få notifieringar om saker du bevakar eller är inblandad i (T.ex. ärenden du skapat eller tilldelats)."
|
|
662 |
text_no_configuration_data: "Roller, ärendetyper, ärendestatusar och arbetsflöden har inte konfigurerats ännu.\nDet rekommenderas att läsa in standardkonfigurationen. Du kommer att kunna göra ändringar efter att den blivit inläst."
|
|
665 |
text_user_mail_option: "För omarkerade projekt kommer du bara bli underrättad om saker du bevakar eller är inblandad i (T.ex. ärenden du skapat eller tilldelats)."
|
|
666 |
text_no_configuration_data: "Roller, ärendetyper, ärendestatus och arbetsflöden har inte konfigurerats ännu.\nDet rekommenderas att läsa in standardkonfigurationen. Du kommer att kunna göra ändringar efter att den blivit inläst." |
|
663 | 667 |
text_load_default_configuration: Läs in standardkonfiguration |
664 | 668 |
text_status_changed_by_changeset: Tilldelad i changeset %s. |
665 | 669 |
text_issues_destroy_confirmation: 'Är du säker på att du vill radera markerade ärende(n) ?' |
666 | 670 |
text_select_project_modules: 'Välj vilka moduler som ska vara aktiva för projektet:' |
667 | 671 |
text_default_administrator_account_changed: Standardadministratörens konto ändrat |
668 |
text_file_repository_writable: Foldern för bifogade filer är skrivbar
|
|
669 |
text_plugin_assets_writable: Foldern för plug-ins är skrivbar
|
|
672 |
text_file_repository_writable: Arkivet för bifogade filer är skrivbar
|
|
673 |
text_plugin_assets_writable: Arkivet för plug-ins är skrivbar
|
|
670 | 674 |
text_rmagick_available: RMagick tillgängligt (valfritt) |
671 | 675 |
text_destroy_time_entries_question: %.02f timmar har rapporterats på ärendena du är på väg att ta bort. Vad vill du göra ? |
672 | 676 |
text_destroy_time_entries: Ta bort rapporterade timmar |
... | ... | |
675 | 679 |
text_user_wrote: '%s skrev:' |
676 | 680 |
text_enumeration_destroy_question: '%d objekt är tilldelade till detta värde.' |
677 | 681 |
text_enumeration_category_reassign_to: 'Återtilldela till detta värde:' |
678 |
text_email_delivery_not_configured: "Mailfunktionen har inte konfigurerats, och notifieringar är inaktiverade.\nKonfigurera din SMTP-server i config/email.yml och starta om applikationen för att aktivera dem."
|
|
679 |
text_repository_usernames_mapping: "Välj eller uppdatera den Redmine-användare som är mappad till varje användarnamn i repository-loggen.\nAnvändare med samma användarnamn eller emailadress i både Redmine och repositoryt mappas automatiskt."
|
|
682 |
text_email_delivery_not_configured: "Mailfunktionen har inte konfigurerats, och notifieringar via mail kan därför inte skickas.\nKonfigurera din SMTP-server i config/email.yml och starta om applikationen för att aktivera dem."
|
|
683 |
text_repository_usernames_mapping: "Välj eller uppdatera den Redmine-användare som är mappad till varje användarnamn i versionarkivloggen.\nAnvändare med samma användarnamn eller emailadress i både Redmine och versionsarkivet mappas automatiskt."
|
|
680 | 684 |
text_diff_truncated: '... Denna diff har förminskats eftersom den överskrider den maximala storlek som kan visas.' |
681 | 685 |
text_custom_field_possible_values_info: 'En rad för varje värde' |
682 | 686 | |
... | ... | |
705 | 709 |
enumeration_issue_priorities: Ärendeprioriteter |
706 | 710 |
enumeration_doc_categories: Dokumentkategorier |
707 | 711 |
enumeration_activities: Aktiviteter (tidsuppföljning) |
708 |
field_identity_url: OpenID URL |
|
709 |
setting_openid: Allow OpenID login and registration |
|
710 |
label_login_with_open_id_option: or login with OpenID |
|
711 |
field_watcher: Watcher |
|
712 |
- |
app/models/project.rb | ||
---|---|---|
62 | 62 |
validates_length_of :homepage, :maximum => 255 |
63 | 63 |
validates_length_of :identifier, :in => 2..20 |
64 | 64 |
validates_format_of :identifier, :with => /^[a-z0-9\-]*$/ |
65 |
|
|
65 |
validates_each :identifier do |record, attr, value| |
|
66 |
record.errors.add attr, 'Identifiers cannot be named Documents' if value.downcase.strip == 'documents' |
|
67 |
end |
|
68 |
|
|
66 | 69 |
before_destroy :delete_all_members |
67 | 70 | |
68 | 71 |
named_scope :has_module, lambda { |mod| { :conditions => ["#{Project.table_name}.id IN (SELECT em.project_id FROM #{EnabledModule.table_name} em WHERE em.name=?)", mod.to_s] } } |
test/unit/project_test.rb | ||
---|---|---|
47 | 47 |
assert_equal "activerecord_error_blank", @ecookbook.errors.on(:name) |
48 | 48 |
end |
49 | 49 |
|
50 |
def test_validate_documents_identifier |
|
51 |
project = Project.new(:name => "documents", :identifier => "documents") |
|
52 |
assert !project.save |
|
53 |
assert_equal 2, project.errors.count |
|
54 |
project = Project.new(:name => "documents", :identifier => " dOcuMents ") |
|
55 |
assert !project.save |
|
56 |
assert_equal 3, project.errors.count |
|
57 |
end |
|
58 |
|
|
50 | 59 |
def test_archive |
51 | 60 |
user = @ecookbook.members.first.user |
52 | 61 |
@ecookbook.archive |