Project

General

Profile

Defect #2660 » documents.diff

Austen Ito, 2009-02-19 10:47

View differences:

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  %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
    (1-1/1)