##// END OF EJS Templates
Search engines now supports pagination....
Jean-Philippe Lang -
r755:a96421019f3a
parent child
Show More
@@ -0,0 +1,2
1 require File.dirname(__FILE__) + '/lib/acts_as_searchable'
2 ActiveRecord::Base.send(:include, Redmine::Acts::Searchable)
@@ -0,0 +1,89
1 # redMine - project management software
2 # Copyright (C) 2006-2007 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 module Redmine
19 module Acts
20 module Searchable
21 def self.included(base)
22 base.extend ClassMethods
23 end
24
25 module ClassMethods
26 def acts_as_searchable(options = {})
27 return if self.included_modules.include?(Redmine::Acts::Searchable::InstanceMethods)
28
29 cattr_accessor :searchable_options
30 self.searchable_options = options
31
32 if searchable_options[:columns].nil?
33 raise 'No searchable column defined.'
34 elsif !searchable_options[:columns].is_a?(Array)
35 searchable_options[:columns] = [] << searchable_options[:columns]
36 end
37
38 if searchable_options[:project_key]
39 elsif column_names.include?('project_id')
40 searchable_options[:project_key] = "#{table_name}.project_id"
41 else
42 raise 'No project key defined.'
43 end
44
45 if searchable_options[:date_column]
46 elsif column_names.include?('created_on')
47 searchable_options[:date_column] = "#{table_name}.created_on"
48 else
49 raise 'No date column defined defined.'
50 end
51
52 send :include, Redmine::Acts::Searchable::InstanceMethods
53 end
54 end
55
56 module InstanceMethods
57 def self.included(base)
58 base.extend ClassMethods
59 end
60
61 module ClassMethods
62 def search(tokens, all_tokens, project, options={})
63 tokens = [] << tokens unless tokens.is_a?(Array)
64 find_options = {:include => searchable_options[:include]}
65 find_options[:limit] = options[:limit] if options[:limit]
66 find_options[:order] = "#{searchable_options[:date_column]} " + (options[:before] ? 'DESC' : 'ASC')
67
68 sql = ([ '(' + searchable_options[:columns].collect {|column| "(LOWER(#{column}) LIKE ?)"}.join(' OR ') + ')' ] * tokens.size).join(all_tokens ? ' AND ' : ' OR ')
69 if options[:offset]
70 sql = "(#{sql}) AND (#{searchable_options[:date_column]} " + (options[:before] ? '<' : '>') + "'#{connection.quoted_date(options[:offset])}')"
71 end
72 find_options[:conditions] = [sql, * (tokens * searchable_options[:columns].size).sort]
73
74 results = with_scope(:find => {:conditions => ["#{searchable_options[:project_key]} = ?", project.id]}) do
75 find(:all, find_options)
76 end
77 if searchable_options[:with]
78 searchable_options[:with].each do |model, assoc|
79 results += model.to_s.camelcase.constantize.search(tokens, all_tokens, project, options).collect {|r| r.send assoc}
80 end
81 results.uniq!
82 end
83 results
84 end
85 end
86 end
87 end
88 end
89 end
@@ -1,97 +1,104
1 1 # redMine - project management software
2 2 # Copyright (C) 2006 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
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 class SearchController < ApplicationController
19 19 layout 'base'
20 20
21 21 helper :messages
22 22 include MessagesHelper
23 23
24 24 def index
25 25 @question = params[:q] || ""
26 26 @question.strip!
27 27 @all_words = params[:all_words] || (params[:submit] ? false : true)
28 28
29 offset = nil
30 begin; offset = params[:offset].to_time if params[:offset]; rescue; end
31
29 32 # quick jump to an issue
30 33 if @question.match(/^#?(\d+)$/) && Issue.find_by_id($1, :include => :project, :conditions => Project.visible_by(logged_in_user))
31 34 redirect_to :controller => "issues", :action => "show", :id => $1
32 35 return
33 36 end
34 37
35 38 if params[:id]
36 39 find_project
37 40 return unless check_project_privacy
38 41 end
39 42
40 43 if @project
41 @object_types = %w(projects issues changesets news documents wiki_pages messages)
42 @object_types.delete('wiki_pages') unless @project.wiki
43 @object_types.delete('changesets') unless @project.repository
44 44 # only show what the user is allowed to view
45 @object_types = %w(issues news documents changesets wiki_pages messages)
45 46 @object_types = @object_types.select {|o| User.current.allowed_to?("view_#{o}".to_sym, @project)}
46 47
47 48 @scope = @object_types.select {|t| params[t]}
48 # default objects to search if none is specified in parameters
49 49 @scope = @object_types if @scope.empty?
50 50 else
51 51 @object_types = @scope = %w(projects)
52 52 end
53 53
54 54 # tokens must be at least 3 character long
55 55 @tokens = @question.split.uniq.select {|w| w.length > 2 }
56 56
57 57 if !@tokens.empty?
58 58 # no more than 5 tokens to search for
59 59 @tokens.slice! 5..-1 if @tokens.size > 5
60 60 # strings used in sql like statement
61 61 like_tokens = @tokens.collect {|w| "%#{w.downcase}%"}
62 62 operator = @all_words ? " AND " : " OR "
63 limit = 10
64 63 @results = []
64 limit = 10
65 65 if @project
66 @results += @project.issues.find(:all, :limit => limit, :include => :author, :conditions => [ (["(LOWER(subject) like ? OR LOWER(description) like ?)"] * like_tokens.size).join(operator), * (like_tokens * 2).sort] ) if @scope.include? 'issues'
67 Journal.with_scope :find => {:conditions => ["#{Issue.table_name}.project_id = ?", @project.id]} do
68 @results += Journal.find(:all, :include => :issue, :limit => limit, :conditions => [ (["(LOWER(notes) like ? OR LOWER(notes) like ?)"] * like_tokens.size).join(operator), * (like_tokens * 2).sort] ).collect(&:issue) if @scope.include? 'issues'
66 @scope.each do |s|
67 @results += s.singularize.camelcase.constantize.search(like_tokens, @all_words, @project,
68 :limit => (limit+1), :offset => offset, :before => params[:previous].nil?)
69 69 end
70 @results.uniq!
71 @results += @project.news.find(:all, :limit => limit, :conditions => [ (["(LOWER(title) like ? OR LOWER(description) like ?)"] * like_tokens.size).join(operator), * (like_tokens * 2).sort], :include => :author ) if @scope.include? 'news'
72 @results += @project.documents.find(:all, :limit => limit, :conditions => [ (["(LOWER(title) like ? OR LOWER(description) like ?)"] * like_tokens.size).join(operator), * (like_tokens * 2).sort] ) if @scope.include? 'documents'
73 @results += @project.wiki.pages.find(:all, :limit => limit, :include => :content, :conditions => [ (["(LOWER(title) like ? OR LOWER(text) like ?)"] * like_tokens.size).join(operator), * (like_tokens * 2).sort] ) if @project.wiki && @scope.include?('wiki_pages')
74 @results += @project.repository.changesets.find(:all, :limit => limit, :conditions => [ (["(LOWER(comments) like ?)"] * like_tokens.size).join(operator), * (like_tokens).sort] ) if @project.repository && @scope.include?('changesets')
75 Message.with_scope :find => {:conditions => ["#{Board.table_name}.project_id = ?", @project.id]} do
76 @results += Message.find(:all, :include => :board, :limit => limit, :conditions => [ (["(LOWER(subject) like ? OR LOWER(content) like ?)"] * like_tokens.size).join(operator), * (like_tokens * 2).sort] ) if @scope.include? 'messages'
70 @results = @results.sort {|a,b| b.event_datetime <=> a.event_datetime}
71 if params[:previous].nil?
72 @pagination_previous_date = @results[0].event_datetime if offset && @results[0]
73 if @results.size > limit
74 @pagination_next_date = @results[limit-1].event_datetime
75 @results = @results[0, limit]
76 end
77 else
78 @pagination_next_date = @results[-1].event_datetime if offset && @results[-1]
79 if @results.size > limit
80 @pagination_previous_date = @results[-(limit)].event_datetime
81 @results = @results[-(limit), limit]
82 end
77 83 end
78 84 else
79 85 Project.with_scope(:find => {:conditions => Project.visible_by(logged_in_user)}) do
80 86 @results += Project.find(:all, :limit => limit, :conditions => [ (["(LOWER(name) like ? OR LOWER(description) like ?)"] * like_tokens.size).join(operator), * (like_tokens * 2).sort] ) if @scope.include? 'projects'
81 87 end
82 88 # if only one project is found, user is redirected to its overview
83 89 redirect_to :controller => 'projects', :action => 'show', :id => @results.first and return if @results.size == 1
84 90 end
85 91 @question = @tokens.join(" ")
86 92 else
87 93 @question = ""
88 94 end
95 render :layout => false if request.xhr?
89 96 end
90 97
91 98 private
92 99 def find_project
93 100 @project = Project.find(params[:id])
94 101 rescue ActiveRecord::RecordNotFound
95 102 render_404
96 103 end
97 104 end
@@ -1,33 +1,33
1 1 # redMine - project management software
2 2 # Copyright (C) 2006-2007 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
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 module SearchHelper
19 19 def highlight_tokens(text, tokens)
20 return text unless tokens && !tokens.empty?
20 return text unless text && tokens && !tokens.empty?
21 21 regexp = Regexp.new "(#{tokens.join('|')})", Regexp::IGNORECASE
22 22 result = ''
23 23 text.split(regexp).each_with_index do |words, i|
24 24 if result.length > 1200
25 25 # maximum length of the preview reached
26 26 result << '...'
27 27 break
28 28 end
29 29 result << (i.even? ? h(words.length > 100 ? "#{words[0..44]} ... #{words[-45..-1]}" : words) : content_tag('span', h(words), :class => 'highlight'))
30 30 end
31 31 result
32 32 end
33 33 end
@@ -1,79 +1,84
1 1 # redMine - project management software
2 2 # Copyright (C) 2006-2007 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
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 class Changeset < ActiveRecord::Base
19 19 belongs_to :repository
20 20 has_many :changes, :dependent => :delete_all
21 21 has_and_belongs_to_many :issues
22 22
23 23 acts_as_event :title => Proc.new {|o| "#{l(:label_revision)} #{o.revision}" + (o.comments.blank? ? '' : (': ' + o.comments))},
24 24 :description => :comments,
25 25 :datetime => :committed_on,
26 26 :author => :committer,
27 27 :url => Proc.new {|o| {:controller => 'repositories', :action => 'revision', :id => o.repository.project_id, :rev => o.revision}}
28
29 acts_as_searchable :columns => 'comments',
30 :include => :repository,
31 :project_key => "#{Repository.table_name}.project_id",
32 :date_column => 'committed_on'
28 33
29 34 validates_presence_of :repository_id, :revision, :committed_on, :commit_date
30 35 validates_numericality_of :revision, :only_integer => true
31 36 validates_uniqueness_of :revision, :scope => :repository_id
32 37 validates_uniqueness_of :scmid, :scope => :repository_id, :allow_nil => true
33 38
34 39 def comments=(comment)
35 40 write_attribute(:comments, comment.strip)
36 41 end
37 42
38 43 def committed_on=(date)
39 44 self.commit_date = date
40 45 super
41 46 end
42 47
43 48 def after_create
44 49 scan_comment_for_issue_ids
45 50 end
46 51
47 52 def scan_comment_for_issue_ids
48 53 return if comments.blank?
49 54 # keywords used to reference issues
50 55 ref_keywords = Setting.commit_ref_keywords.downcase.split(",")
51 56 # keywords used to fix issues
52 57 fix_keywords = Setting.commit_fix_keywords.downcase.split(",")
53 58 # status applied
54 59 fix_status = IssueStatus.find_by_id(Setting.commit_fix_status_id)
55 60
56 61 kw_regexp = (ref_keywords + fix_keywords).collect{|kw| Regexp.escape(kw.strip)}.join("|")
57 62 return if kw_regexp.blank?
58 63
59 64 # remove any associated issues
60 65 self.issues.clear
61 66
62 67 comments.scan(Regexp.new("(#{kw_regexp})[\s:]+(([\s,;&]*#?\\d+)+)", Regexp::IGNORECASE)).each do |match|
63 68 action = match[0]
64 69 target_issue_ids = match[1].scan(/\d+/)
65 70 target_issues = repository.project.issues.find_all_by_id(target_issue_ids)
66 71 if fix_status && fix_keywords.include?(action.downcase)
67 72 # update status of issues
68 73 logger.debug "Issues fixed by changeset #{self.revision}: #{issue_ids.join(', ')}." if logger && logger.debug?
69 74 target_issues.each do |issue|
70 75 # don't change the status is the issue is already closed
71 76 next if issue.status.is_closed?
72 77 issue.status = fix_status
73 78 issue.save
74 79 end
75 80 end
76 81 self.issues << target_issues
77 82 end
78 83 end
79 84 end
@@ -1,27 +1,29
1 1 # redMine - project management software
2 2 # Copyright (C) 2006 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
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 class Document < ActiveRecord::Base
19 19 belongs_to :project
20 20 belongs_to :category, :class_name => "Enumeration", :foreign_key => "category_id"
21 21 has_many :attachments, :as => :container, :dependent => :destroy
22 22
23 acts_as_event :url => Proc.new {|o| {:controller => 'documents', :action => 'show', :id => o.id}}
23 acts_as_searchable :columns => ['title', 'description']
24 acts_as_event :title => Proc.new {|o| "#{l(:label_document)}: #{o.title}"},
25 :url => Proc.new {|o| {:controller => 'documents', :action => 'show', :id => o.id}}
24 26
25 27 validates_presence_of :project, :title, :category
26 28 validates_length_of :title, :maximum => 60
27 29 end
@@ -1,169 +1,170
1 1 # redMine - project management software
2 2 # Copyright (C) 2006-2007 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
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 class Issue < ActiveRecord::Base
19 19 belongs_to :project
20 20 belongs_to :tracker
21 21 belongs_to :status, :class_name => 'IssueStatus', :foreign_key => 'status_id'
22 22 belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
23 23 belongs_to :assigned_to, :class_name => 'User', :foreign_key => 'assigned_to_id'
24 24 belongs_to :fixed_version, :class_name => 'Version', :foreign_key => 'fixed_version_id'
25 25 belongs_to :priority, :class_name => 'Enumeration', :foreign_key => 'priority_id'
26 26 belongs_to :category, :class_name => 'IssueCategory', :foreign_key => 'category_id'
27 27
28 28 has_many :journals, :as => :journalized, :dependent => :destroy
29 29 has_many :attachments, :as => :container, :dependent => :destroy
30 30 has_many :time_entries, :dependent => :nullify
31 31 has_many :custom_values, :dependent => :delete_all, :as => :customized
32 32 has_many :custom_fields, :through => :custom_values
33 33 has_and_belongs_to_many :changesets, :order => "revision ASC"
34 34
35 35 has_many :relations_from, :class_name => 'IssueRelation', :foreign_key => 'issue_from_id', :dependent => :delete_all
36 36 has_many :relations_to, :class_name => 'IssueRelation', :foreign_key => 'issue_to_id', :dependent => :delete_all
37 37
38 38 acts_as_watchable
39 acts_as_searchable :columns => ['subject', 'description'], :with => {:journal => :issue}
39 40 acts_as_event :title => Proc.new {|o| "#{o.tracker.name} ##{o.id}: #{o.subject}"},
40 :url => Proc.new {|o| {:controller => 'issues', :action => 'show', :id => o.id}}
41 :url => Proc.new {|o| {:controller => 'issues', :action => 'show', :id => o.id}}
41 42
42 43 validates_presence_of :subject, :description, :priority, :tracker, :author, :status
43 44 validates_length_of :subject, :maximum => 255
44 45 validates_inclusion_of :done_ratio, :in => 0..100
45 46 validates_numericality_of :estimated_hours, :allow_nil => true
46 47 validates_associated :custom_values, :on => :update
47 48
48 49 # set default status for new issues
49 50 def before_validation
50 51 self.status = IssueStatus.default if status.nil?
51 52 end
52 53
53 54 def validate
54 55 if self.due_date.nil? && @attributes['due_date'] && !@attributes['due_date'].empty?
55 56 errors.add :due_date, :activerecord_error_not_a_date
56 57 end
57 58
58 59 if self.due_date and self.start_date and self.due_date < self.start_date
59 60 errors.add :due_date, :activerecord_error_greater_than_start_date
60 61 end
61 62
62 63 if start_date && soonest_start && start_date < soonest_start
63 64 errors.add :start_date, :activerecord_error_invalid
64 65 end
65 66
66 67 # validate assignment
67 68 if assigned_to && !assignable_users.include?(assigned_to)
68 69 errors.add :assigned_to_id, :activerecord_error_invalid
69 70 end
70 71 end
71 72
72 73 def before_create
73 74 # default assignment based on category
74 75 if assigned_to.nil? && category && category.assigned_to
75 76 self.assigned_to = category.assigned_to
76 77 end
77 78 end
78 79
79 80 def before_save
80 81 if @current_journal
81 82 # attributes changes
82 83 (Issue.column_names - %w(id description)).each {|c|
83 84 @current_journal.details << JournalDetail.new(:property => 'attr',
84 85 :prop_key => c,
85 86 :old_value => @issue_before_change.send(c),
86 87 :value => send(c)) unless send(c)==@issue_before_change.send(c)
87 88 }
88 89 # custom fields changes
89 90 custom_values.each {|c|
90 91 next if (@custom_values_before_change[c.custom_field_id]==c.value ||
91 92 (@custom_values_before_change[c.custom_field_id].blank? && c.value.blank?))
92 93 @current_journal.details << JournalDetail.new(:property => 'cf',
93 94 :prop_key => c.custom_field_id,
94 95 :old_value => @custom_values_before_change[c.custom_field_id],
95 96 :value => c.value)
96 97 }
97 98 @current_journal.save unless @current_journal.details.empty? and @current_journal.notes.empty?
98 99 end
99 100 end
100 101
101 102 def after_save
102 103 # Update start/due dates of following issues
103 104 relations_from.each(&:set_issue_to_dates)
104 105
105 106 # Close duplicates if the issue was closed
106 107 if @issue_before_change && !@issue_before_change.closed? && self.closed?
107 108 duplicates.each do |duplicate|
108 109 # Don't re-close it if it's already closed
109 110 next if duplicate.closed?
110 111 # Same user and notes
111 112 duplicate.init_journal(@current_journal.user, @current_journal.notes)
112 113 duplicate.update_attribute :status, self.status
113 114 end
114 115 end
115 116 end
116 117
117 118 def custom_value_for(custom_field)
118 119 self.custom_values.each {|v| return v if v.custom_field_id == custom_field.id }
119 120 return nil
120 121 end
121 122
122 123 def init_journal(user, notes = "")
123 124 @current_journal ||= Journal.new(:journalized => self, :user => user, :notes => notes)
124 125 @issue_before_change = self.clone
125 126 @custom_values_before_change = {}
126 127 self.custom_values.each {|c| @custom_values_before_change.store c.custom_field_id, c.value }
127 128 @current_journal
128 129 end
129 130
130 131 # Return true if the issue is closed, otherwise false
131 132 def closed?
132 133 self.status.is_closed?
133 134 end
134 135
135 136 # Users the issue can be assigned to
136 137 def assignable_users
137 138 project.members.select {|m| m.role.assignable?}.collect {|m| m.user}
138 139 end
139 140
140 141 def spent_hours
141 142 @spent_hours ||= time_entries.sum(:hours) || 0
142 143 end
143 144
144 145 def relations
145 146 (relations_from + relations_to).sort
146 147 end
147 148
148 149 def all_dependent_issues
149 150 dependencies = []
150 151 relations_from.each do |relation|
151 152 dependencies << relation.issue_to
152 153 dependencies += relation.issue_to.all_dependent_issues
153 154 end
154 155 dependencies
155 156 end
156 157
157 158 # Returns an array of the duplicate issues
158 159 def duplicates
159 160 relations.select {|r| r.relation_type == IssueRelation::TYPE_DUPLICATES}.collect {|r| r.other_issue(self)}
160 161 end
161 162
162 163 def duration
163 164 (start_date && due_date) ? due_date - start_date : 0
164 165 end
165 166
166 167 def soonest_start
167 168 @soonest_start ||= relations_to.collect{|relation| relation.successor_soonest_start}.compact.min
168 169 end
169 170 end
@@ -1,26 +1,31
1 1 # redMine - project management software
2 2 # Copyright (C) 2006 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
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 class Journal < ActiveRecord::Base
19 19 belongs_to :journalized, :polymorphic => true
20 20 # added as a quick fix to allow eager loading of the polymorphic association
21 21 # since always associated to an issue, for now
22 22 belongs_to :issue, :foreign_key => :journalized_id
23 23
24 24 belongs_to :user
25 25 has_many :details, :class_name => "JournalDetail", :dependent => :delete_all
26
27 acts_as_searchable :columns => 'notes',
28 :include => :issue,
29 :project_key => "#{Issue.table_name}.project_id",
30 :date_column => "#{Issue.table_name}.created_on"
26 31 end
@@ -1,41 +1,46
1 1 # redMine - project management software
2 2 # Copyright (C) 2006-2007 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
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 class Message < ActiveRecord::Base
19 19 belongs_to :board
20 20 belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
21 21 acts_as_tree :counter_cache => :replies_count, :order => "#{Message.table_name}.created_on ASC"
22 22 has_many :attachments, :as => :container, :dependent => :destroy
23 23 belongs_to :last_reply, :class_name => 'Message', :foreign_key => 'last_reply_id'
24 24
25 acts_as_searchable :columns => ['subject', 'content'], :include => :board, :project_key => "project_id"
26 acts_as_event :title => Proc.new {|o| "#{o.board.name}: #{o.subject}"},
27 :description => :content,
28 :url => Proc.new {|o| {:controller => 'messages', :action => 'show', :board_id => o.board_id, :id => o.id}}
29
25 30 validates_presence_of :subject, :content
26 31 validates_length_of :subject, :maximum => 255
27 32
28 33 def after_create
29 34 board.update_attribute(:last_message_id, self.id)
30 35 board.increment! :messages_count
31 36 if parent
32 37 parent.reload.update_attribute(:last_reply_id, self.id)
33 38 else
34 39 board.increment! :topics_count
35 40 end
36 41 end
37 42
38 43 def project
39 44 board.project
40 45 end
41 46 end
@@ -1,33 +1,34
1 1 # redMine - project management software
2 2 # Copyright (C) 2006 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
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 class News < ActiveRecord::Base
19 19 belongs_to :project
20 20 belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
21 21 has_many :comments, :as => :commented, :dependent => :delete_all, :order => "created_on"
22 22
23 23 validates_presence_of :title, :description
24 24 validates_length_of :title, :maximum => 60
25 25 validates_length_of :summary, :maximum => 255
26 26
27 acts_as_searchable :columns => ['title', 'description']
27 28 acts_as_event :url => Proc.new {|o| {:controller => 'news', :action => 'show', :id => o.id}}
28 29
29 30 # returns latest news for projects visible by user
30 31 def self.latest(user=nil, count=5)
31 32 find(:all, :limit => count, :conditions => Project.visible_by(user), :include => [ :author, :project ], :order => "#{News.table_name}.created_on DESC")
32 33 end
33 34 end
@@ -1,164 +1,168
1 1 # redMine - project management software
2 2 # Copyright (C) 2006 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
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 class Project < ActiveRecord::Base
19 19 # Project statuses
20 20 STATUS_ACTIVE = 1
21 21 STATUS_ARCHIVED = 9
22 22
23 23 has_many :members, :dependent => :delete_all, :include => :user, :conditions => "#{User.table_name}.status=#{User::STATUS_ACTIVE}"
24 24 has_many :users, :through => :members
25 25 has_many :custom_values, :dependent => :delete_all, :as => :customized
26 26 has_many :enabled_modules, :dependent => :delete_all
27 27 has_many :issues, :dependent => :destroy, :order => "#{Issue.table_name}.created_on DESC", :include => [:status, :tracker]
28 28 has_many :issue_changes, :through => :issues, :source => :journals
29 29 has_many :versions, :dependent => :destroy, :order => "#{Version.table_name}.effective_date DESC, #{Version.table_name}.name DESC"
30 30 has_many :time_entries, :dependent => :delete_all
31 31 has_many :queries, :dependent => :delete_all
32 32 has_many :documents, :dependent => :destroy
33 33 has_many :news, :dependent => :delete_all, :include => :author
34 34 has_many :issue_categories, :dependent => :delete_all, :order => "#{IssueCategory.table_name}.name"
35 35 has_many :boards, :order => "position ASC"
36 36 has_one :repository, :dependent => :destroy
37 37 has_many :changesets, :through => :repository
38 38 has_one :wiki, :dependent => :destroy
39 39 has_and_belongs_to_many :custom_fields, :class_name => 'IssueCustomField', :join_table => "#{table_name_prefix}custom_fields_projects#{table_name_suffix}", :association_foreign_key => 'custom_field_id'
40 40 acts_as_tree :order => "name", :counter_cache => true
41
41
42 acts_as_searchable :columns => ['name', 'description'], :project_key => 'id'
43 acts_as_event :title => Proc.new {|o| "#{l(:label_project)}: #{o.name}"},
44 :url => Proc.new {|o| {:controller => 'projects', :action => 'show', :id => o.id}}
45
42 46 attr_protected :status, :enabled_module_names
43 47
44 48 validates_presence_of :name, :description, :identifier
45 49 validates_uniqueness_of :name, :identifier
46 50 validates_associated :custom_values, :on => :update
47 51 validates_associated :repository, :wiki
48 52 validates_length_of :name, :maximum => 30
49 53 validates_format_of :name, :with => /^[\w\s\'\-]*$/i
50 54 validates_length_of :description, :maximum => 255
51 55 validates_length_of :homepage, :maximum => 60
52 56 validates_length_of :identifier, :in => 3..12
53 57 validates_format_of :identifier, :with => /^[a-z0-9\-]*$/
54 58
55 59 def identifier=(identifier)
56 60 super unless identifier_frozen?
57 61 end
58 62
59 63 def identifier_frozen?
60 64 errors[:identifier].nil? && !(new_record? || identifier.blank?)
61 65 end
62 66
63 67 def issues_with_subprojects(include_subprojects=false)
64 68 conditions = nil
65 69 if include_subprojects && !active_children.empty?
66 70 ids = [id] + active_children.collect {|c| c.id}
67 71 conditions = ["#{Issue.table_name}.project_id IN (#{ids.join(',')})"]
68 72 end
69 73 conditions ||= ["#{Issue.table_name}.project_id = ?", id]
70 74 Issue.with_scope :find => { :conditions => conditions } do
71 75 yield
72 76 end
73 77 end
74 78
75 79 # returns latest created projects
76 80 # non public projects will be returned only if user is a member of those
77 81 def self.latest(user=nil, count=5)
78 82 find(:all, :limit => count, :conditions => visible_by(user), :order => "created_on DESC")
79 83 end
80 84
81 85 def self.visible_by(user=nil)
82 86 if user && user.admin?
83 87 return "#{Project.table_name}.status=#{Project::STATUS_ACTIVE}"
84 88 elsif user && user.memberships.any?
85 89 return "#{Project.table_name}.status=#{Project::STATUS_ACTIVE} AND (#{Project.table_name}.is_public = #{connection.quoted_true} or #{Project.table_name}.id IN (#{user.memberships.collect{|m| m.project_id}.join(',')}))"
86 90 else
87 91 return "#{Project.table_name}.status=#{Project::STATUS_ACTIVE} AND #{Project.table_name}.is_public = #{connection.quoted_true}"
88 92 end
89 93 end
90 94
91 95 def active?
92 96 self.status == STATUS_ACTIVE
93 97 end
94 98
95 99 def archive
96 100 # Archive subprojects if any
97 101 children.each do |subproject|
98 102 subproject.archive
99 103 end
100 104 update_attribute :status, STATUS_ARCHIVED
101 105 end
102 106
103 107 def unarchive
104 108 return false if parent && !parent.active?
105 109 update_attribute :status, STATUS_ACTIVE
106 110 end
107 111
108 112 def active_children
109 113 children.select {|child| child.active?}
110 114 end
111 115
112 116 # Returns an array of all custom fields enabled for project issues
113 117 # (explictly associated custom fields and custom fields enabled for all projects)
114 118 def custom_fields_for_issues(tracker)
115 119 all_custom_fields.select {|c| tracker.custom_fields.include? c }
116 120 end
117 121
118 122 def all_custom_fields
119 123 @all_custom_fields ||= (IssueCustomField.for_all + custom_fields).uniq
120 124 end
121 125
122 126 def <=>(project)
123 127 name <=> project.name
124 128 end
125 129
126 130 def allows_to?(action)
127 131 if action.is_a? Hash
128 132 allowed_actions.include? "#{action[:controller]}/#{action[:action]}"
129 133 else
130 134 allowed_permissions.include? action
131 135 end
132 136 end
133 137
134 138 def module_enabled?(module_name)
135 139 module_name = module_name.to_s
136 140 enabled_modules.detect {|m| m.name == module_name}
137 141 end
138 142
139 143 def enabled_module_names=(module_names)
140 144 enabled_modules.clear
141 145 module_names = [] unless module_names && module_names.is_a?(Array)
142 146 module_names.each do |name|
143 147 enabled_modules << EnabledModule.new(:name => name.to_s)
144 148 end
145 149 end
146 150
147 151 protected
148 152 def validate
149 153 errors.add(parent_id, " must be a root project") if parent and parent.parent
150 154 errors.add_to_base("A project with subprojects can't be a subproject") if parent and children.size > 0
151 155 end
152 156
153 157 private
154 158 def allowed_permissions
155 159 @allowed_permissions ||= begin
156 160 module_names = enabled_modules.collect {|m| m.name}
157 161 Redmine::AccessControl.modules_permissions(module_names).collect {|p| p.name}
158 162 end
159 163 end
160 164
161 165 def allowed_actions
162 166 @actions_allowed ||= allowed_permissions.inject([]) { |actions, permission| actions += Redmine::AccessControl.allowed_actions(permission) }.flatten
163 167 end
164 168 end
@@ -1,102 +1,115
1 1 # redMine - project management software
2 2 # Copyright (C) 2006-2007 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
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 require 'diff'
19 19
20 20 class WikiPage < ActiveRecord::Base
21 21 belongs_to :wiki
22 22 has_one :content, :class_name => 'WikiContent', :foreign_key => 'page_id', :dependent => :destroy
23 23 has_many :attachments, :as => :container, :dependent => :destroy
24
24
25 acts_as_event :title => Proc.new {|o| "#{l(:label_wiki)}: #{o.title}"},
26 :description => :text,
27 :datetime => :created_on,
28 :url => Proc.new {|o| {:controller => 'wiki', :id => o.wiki.project_id, :page => o.title}}
29
30 acts_as_searchable :columns => ['title', 'text'],
31 :include => [:wiki, :content],
32 :project_key => "#{Wiki.table_name}.project_id"
33
25 34 attr_accessor :redirect_existing_links
26 35
27 36 validates_presence_of :title
28 37 validates_format_of :title, :with => /^[^,\.\/\?\;\|\s]*$/
29 38 validates_uniqueness_of :title, :scope => :wiki_id, :case_sensitive => false
30 39 validates_associated :content
31 40
32 41 def title=(value)
33 42 value = Wiki.titleize(value)
34 43 @previous_title = read_attribute(:title) if @previous_title.blank?
35 44 write_attribute(:title, value)
36 45 end
37 46
38 47 def before_save
39 48 self.title = Wiki.titleize(title)
40 49 # Manage redirects if the title has changed
41 50 if !@previous_title.blank? && (@previous_title != title) && !new_record?
42 51 # Update redirects that point to the old title
43 52 wiki.redirects.find_all_by_redirects_to(@previous_title).each do |r|
44 53 r.redirects_to = title
45 54 r.title == r.redirects_to ? r.destroy : r.save
46 55 end
47 56 # Remove redirects for the new title
48 57 wiki.redirects.find_all_by_title(title).each(&:destroy)
49 58 # Create a redirect to the new title
50 59 wiki.redirects << WikiRedirect.new(:title => @previous_title, :redirects_to => title) unless redirect_existing_links == "0"
51 60 @previous_title = nil
52 61 end
53 62 end
54 63
55 64 def before_destroy
56 65 # Remove redirects to this page
57 66 wiki.redirects.find_all_by_redirects_to(title).each(&:destroy)
58 67 end
59 68
60 69 def pretty_title
61 70 WikiPage.pretty_title(title)
62 71 end
63 72
64 73 def content_for_version(version=nil)
65 74 result = content.versions.find_by_version(version.to_i) if version
66 75 result ||= content
67 76 result
68 77 end
69 78
70 79 def diff(version_to=nil, version_from=nil)
71 80 version_to = version_to ? version_to.to_i : self.content.version
72 81 version_from = version_from ? version_from.to_i : version_to - 1
73 82 version_to, version_from = version_from, version_to unless version_from < version_to
74 83
75 84 content_to = content.versions.find_by_version(version_to)
76 85 content_from = content.versions.find_by_version(version_from)
77 86
78 87 (content_to && content_from) ? WikiDiff.new(content_to, content_from) : nil
79 88 end
80 89
81 90 def self.pretty_title(str)
82 91 (str && str.is_a?(String)) ? str.tr('_', ' ') : str
83 92 end
84 93
85 94 def project
86 95 wiki.project
87 96 end
97
98 def text
99 content.text if content
100 end
88 101 end
89 102
90 103 class WikiDiff
91 104 attr_reader :diff, :words, :content_to, :content_from
92 105
93 106 def initialize(content_to, content_from)
94 107 @content_to = content_to
95 108 @content_from = content_from
96 109 @words = content_to.text.split(/(\s+)/)
97 110 @words = @words.select {|word| word != ' '}
98 111 words_from = content_from.text.split(/(\s+)/)
99 112 words_from = words_from.select {|word| word != ' '}
100 113 @diff = words_from.diff @words
101 114 end
102 115 end
@@ -1,53 +1,41
1 1 <h2><%= l(:label_search) %></h2>
2 2
3 3 <div class="box">
4 4 <% form_tag({}, :method => :get) do %>
5 5 <p><%= text_field_tag 'q', @question, :size => 30, :id => 'search-input' %>
6 6 <%= javascript_tag "Field.focus('search-input')" %>
7 7
8 8 <% @object_types.each do |t| %>
9 9 <label><%= check_box_tag t, 1, @scope.include?(t) %> <%= l("label_#{t.singularize}_plural")%></label>
10 10 <% end %>
11 11 <br />
12 12 <%= check_box_tag 'all_words', 1, @all_words %> <%= l(:label_all_words) %></p>
13 13 <%= submit_tag l(:button_submit), :name => 'submit' %>
14 14 <% end %>
15 15 </div>
16 16
17 17 <% if @results %>
18 <h3><%= lwr(:label_result, @results.length) %></h3>
18 <h3><%= l(:label_result_plural) %></h3>
19 19 <ul>
20 20 <% @results.each do |e| %>
21 <li><p>
22 <% if e.is_a? Project %>
23 <%= link_to highlight_tokens(h(e.name), @tokens), :controller => 'projects', :action => 'show', :id => e %><br />
24 <%= highlight_tokens(e.description, @tokens) %>
25 <% elsif e.is_a? Issue %>
26 <%= link_to_issue e %>: <%= highlight_tokens(h(e.subject), @tokens) %><br />
27 <%= highlight_tokens(e.description, @tokens) %><br />
28 <i><%= e.author.name %>, <%= format_time(e.created_on) %></i>
29 <% elsif e.is_a? News %>
30 <%=l(:label_news)%>: <%= link_to highlight_tokens(h(e.title), @tokens), :controller => 'news', :action => 'show', :id => e %><br />
31 <%= highlight_tokens(e.description, @tokens) %><br />
32 <i><%= e.author.name %>, <%= format_time(e.created_on) %></i>
33 <% elsif e.is_a? Document %>
34 <%=l(:label_document)%>: <%= link_to highlight_tokens(h(e.title), @tokens), :controller => 'documents', :action => 'show', :id => e %><br />
35 <%= highlight_tokens(e.description, @tokens) %><br />
36 <i><%= format_time(e.created_on) %></i>
37 <% elsif e.is_a? WikiPage %>
38 <%=l(:label_wiki)%>: <%= link_to highlight_tokens(h(e.pretty_title), @tokens), :controller => 'wiki', :action => 'index', :id => @project, :page => e.title %><br />
39 <%= highlight_tokens(e.content.text, @tokens) %><br />
40 <i><%= e.content.author ? e.content.author.name : "Anonymous" %>, <%= format_time(e.content.updated_on) %></i>
41 <% elsif e.is_a? Changeset %>
42 <%=l(:label_revision)%> <%= link_to h(e.revision), :controller => 'repositories', :action => 'revision', :id => @project, :rev => e.revision %><br />
43 <%= highlight_tokens(e.comments, @tokens) %><br />
44 <em><%= e.committer.blank? ? e.committer : "Anonymous" %>, <%= format_time(e.committed_on) %></em>
45 <% elsif e.is_a? Message %>
46 <%=h e.board.name %>: <%= link_to_message e %><br />
47 <%= highlight_tokens(e.content, @tokens) %><br />
48 <em><%= e.author ? e.author.name : "Anonymous" %>, <%= format_time(e.created_on) %></em>
49 <% end %>
50 </p></li>
21 <li><p><%= link_to highlight_tokens(truncate(e.event_title, 255), @tokens), e.event_url %><br />
22 <%= highlight_tokens(e.event_description, @tokens) %><br />
23 <span class="author"><%= format_time(e.event_datetime) %></span></p></li>
51 24 <% end %>
52 25 </ul>
53 26 <% end %>
27
28 <p><center>
29 <% if @pagination_previous_date %>
30 <%= link_to_remote ('&#171; ' + l(:label_previous)),
31 {:update => :content,
32 :url => params.merge(:previous => 1, :offset => @pagination_previous_date.strftime("%Y%m%d%H%M%S"))
33 }, :href => url_for(params.merge(:previous => 1, :offset => @pagination_previous_date.strftime("%Y%m%d%H%M%S"))) %>&nbsp;
34 <% end %>
35 <% if @pagination_next_date %>
36 <%= link_to_remote (l(:label_next) + ' &#187;'),
37 {:update => :content,
38 :url => params.merge(:previous => nil, :offset => @pagination_next_date.strftime("%Y%m%d%H%M%S"))
39 }, :href => url_for(params.merge(:previous => nil, :offset => @pagination_next_date.strftime("%Y%m%d%H%M%S"))) %>
40 <% end %>
41 </center></p>
@@ -1,91 +1,93
1 1 # Be sure to restart your web server when you modify this file.
2 2
3 3 # Uncomment below to force Rails into production mode when
4 4 # you don't control web/app server and can't set it the proper way
5 5 # ENV['RAILS_ENV'] ||= 'production'
6 6
7 7 # Bootstrap the Rails environment, frameworks, and default configuration
8 8 require File.join(File.dirname(__FILE__), 'boot')
9 9
10 10 Rails::Initializer.run do |config|
11 11 # Settings in config/environments/* take precedence those specified here
12 12
13 13 # Skip frameworks you're not going to use
14 14 # config.frameworks -= [ :action_web_service, :action_mailer ]
15 15
16 16 # Add additional load paths for sweepers
17 17 config.load_paths += %W( #{RAILS_ROOT}/app/sweepers )
18
19 config.plugin_paths = ['lib/plugins', 'vendor/plugins']
18 20
19 21 # Force all environments to use the same logger level
20 22 # (by default production uses :info, the others :debug)
21 23 # config.log_level = :debug
22 24
23 25 # Use the database for sessions instead of the file system
24 26 # (create the session table with 'rake create_sessions_table')
25 27 # config.action_controller.session_store = :active_record_store
26 28
27 29 # Enable page/fragment caching by setting a file-based store
28 30 # (remember to create the caching directory and make it readable to the application)
29 31 # config.action_controller.fragment_cache_store = :file_store, "#{RAILS_ROOT}/cache"
30 32
31 33 # Activate observers that should always be running
32 34 # config.active_record.observers = :cacher, :garbage_collector
33 35 config.active_record.observers = :message_observer
34 36
35 37 # Make Active Record use UTC-base instead of local time
36 38 # config.active_record.default_timezone = :utc
37 39
38 40 # Use Active Record's schema dumper instead of SQL when creating the test database
39 41 # (enables use of different database adapters for development and test environments)
40 42 # config.active_record.schema_format = :ruby
41 43
42 44 # See Rails::Configuration for more options
43 45
44 46 # SMTP server configuration
45 47 config.action_mailer.smtp_settings = {
46 48 :address => "127.0.0.1",
47 49 :port => 25,
48 50 :domain => "somenet.foo",
49 51 :authentication => :login,
50 52 :user_name => "redmine",
51 53 :password => "redmine",
52 54 }
53 55
54 56 config.action_mailer.perform_deliveries = true
55 57
56 58 # Tell ActionMailer not to deliver emails to the real world.
57 59 # The :test delivery method accumulates sent emails in the
58 60 # ActionMailer::Base.deliveries array.
59 61 #config.action_mailer.delivery_method = :test
60 62 config.action_mailer.delivery_method = :smtp
61 63
62 64 # Uncomment this line if the engines plugin is installed.
63 65 # This will ensure that engines is loaded first.
64 66 # config.plugins = ["engines", "*"]
65 67 end
66 68
67 69 ActiveRecord::Errors.default_error_messages = {
68 70 :inclusion => "activerecord_error_inclusion",
69 71 :exclusion => "activerecord_error_exclusion",
70 72 :invalid => "activerecord_error_invalid",
71 73 :confirmation => "activerecord_error_confirmation",
72 74 :accepted => "activerecord_error_accepted",
73 75 :empty => "activerecord_error_empty",
74 76 :blank => "activerecord_error_blank",
75 77 :too_long => "activerecord_error_too_long",
76 78 :too_short => "activerecord_error_too_short",
77 79 :wrong_length => "activerecord_error_wrong_length",
78 80 :taken => "activerecord_error_taken",
79 81 :not_a_number => "activerecord_error_not_a_number"
80 82 }
81 83
82 84 ActionView::Base.field_error_proc = Proc.new{ |html_tag, instance| "#{html_tag}" }
83 85
84 86 GLoc.set_config :default_language => :en
85 87 GLoc.clear_strings
86 88 GLoc.set_kcode
87 89 GLoc.load_localized_strings
88 90 GLoc.set_config(:raise_string_not_found_errors => false)
89 91
90 92 require 'redmine'
91 93
@@ -1,513 +1,512
1 1 _gloc_rule_default: '|n| n==1 ? "" : "_plural" '
2 2
3 3 actionview_datehelper_select_day_prefix:
4 4 actionview_datehelper_select_month_names: January,February,March,April,May,June,July,August,September,October,November,December
5 5 actionview_datehelper_select_month_names_abbr: Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec
6 6 actionview_datehelper_select_month_prefix:
7 7 actionview_datehelper_select_year_prefix:
8 8 actionview_datehelper_time_in_words_day: 1 day
9 9 actionview_datehelper_time_in_words_day_plural: %d days
10 10 actionview_datehelper_time_in_words_hour_about: about an hour
11 11 actionview_datehelper_time_in_words_hour_about_plural: about %d hours
12 12 actionview_datehelper_time_in_words_hour_about_single: about an hour
13 13 actionview_datehelper_time_in_words_minute: 1 minute
14 14 actionview_datehelper_time_in_words_minute_half: half a minute
15 15 actionview_datehelper_time_in_words_minute_less_than: less than a minute
16 16 actionview_datehelper_time_in_words_minute_plural: %d minutes
17 17 actionview_datehelper_time_in_words_minute_single: 1 minute
18 18 actionview_datehelper_time_in_words_second_less_than: less than a second
19 19 actionview_datehelper_time_in_words_second_less_than_plural: less than %d seconds
20 20 actionview_instancetag_blank_option: Please select
21 21
22 22 activerecord_error_inclusion: is not included in the list
23 23 activerecord_error_exclusion: is reserved
24 24 activerecord_error_invalid: is invalid
25 25 activerecord_error_confirmation: doesn't match confirmation
26 26 activerecord_error_accepted: must be accepted
27 27 activerecord_error_empty: can't be empty
28 28 activerecord_error_blank: can't be blank
29 29 activerecord_error_too_long: is too long
30 30 activerecord_error_too_short: is too short
31 31 activerecord_error_wrong_length: is the wrong length
32 32 activerecord_error_taken: has already been taken
33 33 activerecord_error_not_a_number: is not a number
34 34 activerecord_error_not_a_date: is not a valid date
35 35 activerecord_error_greater_than_start_date: must be greater than start date
36 36 activerecord_error_not_same_project: doesn't belong to the same project
37 37 activerecord_error_circular_dependency: This relation would create a circular dependency
38 38
39 39 general_fmt_age: %d yr
40 40 general_fmt_age_plural: %d yrs
41 41 general_fmt_date: %%m/%%d/%%Y
42 42 general_fmt_datetime: %%m/%%d/%%Y %%I:%%M %%p
43 43 general_fmt_datetime_short: %%b %%d, %%I:%%M %%p
44 44 general_fmt_time: %%I:%%M %%p
45 45 general_text_No: 'No'
46 46 general_text_Yes: 'Yes'
47 47 general_text_no: 'no'
48 48 general_text_yes: 'yes'
49 49 general_lang_name: 'English'
50 50 general_csv_separator: ','
51 51 general_csv_encoding: ISO-8859-1
52 52 general_pdf_encoding: ISO-8859-1
53 53 general_day_names: Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday
54 54
55 55 notice_account_updated: Account was successfully updated.
56 56 notice_account_invalid_creditentials: Invalid user or password
57 57 notice_account_password_updated: Password was successfully updated.
58 58 notice_account_wrong_password: Wrong password
59 59 notice_account_register_done: Account was successfully created. To activate your account, click on the link that was emailed to you.
60 60 notice_account_unknown_email: Unknown user.
61 61 notice_can_t_change_password: This account uses an external authentication source. Impossible to change the password.
62 62 notice_account_lost_email_sent: An email with instructions to choose a new password has been sent to you.
63 63 notice_account_activated: Your account has been activated. You can now log in.
64 64 notice_successful_create: Successful creation.
65 65 notice_successful_update: Successful update.
66 66 notice_successful_delete: Successful deletion.
67 67 notice_successful_connection: Successful connection.
68 68 notice_file_not_found: The page you were trying to access doesn't exist or has been removed.
69 69 notice_locking_conflict: Data have been updated by another user.
70 70 notice_scm_error: Entry and/or revision doesn't exist in the repository.
71 71 notice_not_authorized: You are not authorized to access this page.
72 72 notice_email_sent: An email was sent to %s
73 73 notice_email_error: An error occurred while sending mail (%s)
74 74 notice_feeds_access_key_reseted: Your RSS access key was reseted.
75 75
76 76 mail_subject_lost_password: Your redMine password
77 77 mail_subject_register: redMine account activation
78 78
79 79 gui_validation_error: 1 error
80 80 gui_validation_error_plural: %d errors
81 81
82 82 field_name: Name
83 83 field_description: Description
84 84 field_summary: Summary
85 85 field_is_required: Required
86 86 field_firstname: Firstname
87 87 field_lastname: Lastname
88 88 field_mail: Email
89 89 field_filename: File
90 90 field_filesize: Size
91 91 field_downloads: Downloads
92 92 field_author: Author
93 93 field_created_on: Created
94 94 field_updated_on: Updated
95 95 field_field_format: Format
96 96 field_is_for_all: For all projects
97 97 field_possible_values: Possible values
98 98 field_regexp: Regular expression
99 99 field_min_length: Minimum length
100 100 field_max_length: Maximum length
101 101 field_value: Value
102 102 field_category: Category
103 103 field_title: Title
104 104 field_project: Project
105 105 field_issue: Issue
106 106 field_status: Status
107 107 field_notes: Notes
108 108 field_is_closed: Issue closed
109 109 field_is_default: Default status
110 110 field_html_color: Color
111 111 field_tracker: Tracker
112 112 field_subject: Subject
113 113 field_due_date: Due date
114 114 field_assigned_to: Assigned to
115 115 field_priority: Priority
116 116 field_fixed_version: Fixed version
117 117 field_user: User
118 118 field_role: Role
119 119 field_homepage: Homepage
120 120 field_is_public: Public
121 121 field_parent: Subproject of
122 122 field_is_in_chlog: Issues displayed in changelog
123 123 field_is_in_roadmap: Issues displayed in roadmap
124 124 field_login: Login
125 125 field_mail_notification: Mail notifications
126 126 field_admin: Administrator
127 127 field_last_login_on: Last connection
128 128 field_language: Language
129 129 field_effective_date: Date
130 130 field_password: Password
131 131 field_new_password: New password
132 132 field_password_confirmation: Confirmation
133 133 field_version: Version
134 134 field_type: Type
135 135 field_host: Host
136 136 field_port: Port
137 137 field_account: Account
138 138 field_base_dn: Base DN
139 139 field_attr_login: Login attribute
140 140 field_attr_firstname: Firstname attribute
141 141 field_attr_lastname: Lastname attribute
142 142 field_attr_mail: Email attribute
143 143 field_onthefly: On-the-fly user creation
144 144 field_start_date: Start
145 145 field_done_ratio: %% Done
146 146 field_auth_source: Authentication mode
147 147 field_hide_mail: Hide my email address
148 148 field_comments: Comment
149 149 field_url: URL
150 150 field_start_page: Start page
151 151 field_subproject: Subproject
152 152 field_hours: Hours
153 153 field_activity: Activity
154 154 field_spent_on: Date
155 155 field_identifier: Identifier
156 156 field_is_filter: Used as a filter
157 157 field_issue_to_id: Related issue
158 158 field_delay: Delay
159 159 field_assignable: Issues can be assigned to this role
160 160 field_redirect_existing_links: Redirect existing links
161 161 field_estimated_hours: Estimated time
162 162
163 163 setting_app_title: Application title
164 164 setting_app_subtitle: Application subtitle
165 165 setting_welcome_text: Welcome text
166 166 setting_default_language: Default language
167 167 setting_login_required: Authent. required
168 168 setting_self_registration: Self-registration enabled
169 169 setting_attachment_max_size: Attachment max. size
170 170 setting_issues_export_limit: Issues export limit
171 171 setting_mail_from: Emission mail address
172 172 setting_host_name: Host name
173 173 setting_text_formatting: Text formatting
174 174 setting_wiki_compression: Wiki history compression
175 175 setting_feeds_limit: Feed content limit
176 176 setting_autofetch_changesets: Autofetch commits
177 177 setting_sys_api_enabled: Enable WS for repository management
178 178 setting_commit_ref_keywords: Referencing keywords
179 179 setting_commit_fix_keywords: Fixing keywords
180 180 setting_autologin: Autologin
181 181 setting_date_format: Date format
182 182 setting_cross_project_issue_relations: Allow cross-project issue relations
183 183
184 184 label_user: User
185 185 label_user_plural: Users
186 186 label_user_new: New user
187 187 label_project: Project
188 188 label_project_new: New project
189 189 label_project_plural: Projects
190 190 label_project_all: All Projects
191 191 label_project_latest: Latest projects
192 192 label_issue: Issue
193 193 label_issue_new: New issue
194 194 label_issue_plural: Issues
195 195 label_issue_view_all: View all issues
196 196 label_document: Document
197 197 label_document_new: New document
198 198 label_document_plural: Documents
199 199 label_role: Role
200 200 label_role_plural: Roles
201 201 label_role_new: New role
202 202 label_role_and_permissions: Roles and permissions
203 203 label_member: Member
204 204 label_member_new: New member
205 205 label_member_plural: Members
206 206 label_tracker: Tracker
207 207 label_tracker_plural: Trackers
208 208 label_tracker_new: New tracker
209 209 label_workflow: Workflow
210 210 label_issue_status: Issue status
211 211 label_issue_status_plural: Issue statuses
212 212 label_issue_status_new: New status
213 213 label_issue_category: Issue category
214 214 label_issue_category_plural: Issue categories
215 215 label_issue_category_new: New category
216 216 label_custom_field: Custom field
217 217 label_custom_field_plural: Custom fields
218 218 label_custom_field_new: New custom field
219 219 label_enumerations: Enumerations
220 220 label_enumeration_new: New value
221 221 label_information: Information
222 222 label_information_plural: Information
223 223 label_please_login: Please login
224 224 label_register: Register
225 225 label_password_lost: Lost password
226 226 label_home: Home
227 227 label_my_page: My page
228 228 label_my_account: My account
229 229 label_my_projects: My projects
230 230 label_administration: Administration
231 231 label_login: Sign in
232 232 label_logout: Sign out
233 233 label_help: Help
234 234 label_reported_issues: Reported issues
235 235 label_assigned_to_me_issues: Issues assigned to me
236 236 label_last_login: Last connection
237 237 label_last_updates: Last updated
238 238 label_last_updates_plural: %d last updated
239 239 label_registered_on: Registered on
240 240 label_activity: Activity
241 241 label_new: New
242 242 label_logged_as: Logged as
243 243 label_environment: Environment
244 244 label_authentication: Authentication
245 245 label_auth_source: Authentication mode
246 246 label_auth_source_new: New authentication mode
247 247 label_auth_source_plural: Authentication modes
248 248 label_subproject_plural: Subprojects
249 249 label_min_max_length: Min - Max length
250 250 label_list: List
251 251 label_date: Date
252 252 label_integer: Integer
253 253 label_boolean: Boolean
254 254 label_string: Text
255 255 label_text: Long text
256 256 label_attribute: Attribute
257 257 label_attribute_plural: Attributes
258 258 label_download: %d Download
259 259 label_download_plural: %d Downloads
260 260 label_no_data: No data to display
261 261 label_change_status: Change status
262 262 label_history: History
263 263 label_attachment: File
264 264 label_attachment_new: New file
265 265 label_attachment_delete: Delete file
266 266 label_attachment_plural: Files
267 267 label_report: Report
268 268 label_report_plural: Reports
269 269 label_news: News
270 270 label_news_new: Add news
271 271 label_news_plural: News
272 272 label_news_latest: Latest news
273 273 label_news_view_all: View all news
274 274 label_change_log: Change log
275 275 label_settings: Settings
276 276 label_overview: Overview
277 277 label_version: Version
278 278 label_version_new: New version
279 279 label_version_plural: Versions
280 280 label_confirmation: Confirmation
281 281 label_export_to: Export to
282 282 label_read: Read...
283 283 label_public_projects: Public projects
284 284 label_open_issues: open
285 285 label_open_issues_plural: open
286 286 label_closed_issues: closed
287 287 label_closed_issues_plural: closed
288 288 label_total: Total
289 289 label_permissions: Permissions
290 290 label_current_status: Current status
291 291 label_new_statuses_allowed: New statuses allowed
292 292 label_all: all
293 293 label_none: none
294 294 label_next: Next
295 295 label_previous: Previous
296 296 label_used_by: Used by
297 297 label_details: Details
298 298 label_add_note: Add a note
299 299 label_per_page: Per page
300 300 label_calendar: Calendar
301 301 label_months_from: months from
302 302 label_gantt: Gantt
303 303 label_internal: Internal
304 304 label_last_changes: last %d changes
305 305 label_change_view_all: View all changes
306 306 label_personalize_page: Personalize this page
307 307 label_comment: Comment
308 308 label_comment_plural: Comments
309 309 label_comment_add: Add a comment
310 310 label_comment_added: Comment added
311 311 label_comment_delete: Delete comments
312 312 label_query: Custom query
313 313 label_query_plural: Custom queries
314 314 label_query_new: New query
315 315 label_filter_add: Add filter
316 316 label_filter_plural: Filters
317 317 label_equals: is
318 318 label_not_equals: is not
319 319 label_in_less_than: in less than
320 320 label_in_more_than: in more than
321 321 label_in: in
322 322 label_today: today
323 323 label_this_week: this week
324 324 label_less_than_ago: less than days ago
325 325 label_more_than_ago: more than days ago
326 326 label_ago: days ago
327 327 label_contains: contains
328 328 label_not_contains: doesn't contain
329 329 label_day_plural: days
330 330 label_repository: Repository
331 331 label_browse: Browse
332 332 label_modification: %d change
333 333 label_modification_plural: %d changes
334 334 label_revision: Revision
335 335 label_revision_plural: Revisions
336 336 label_added: added
337 337 label_modified: modified
338 338 label_deleted: deleted
339 339 label_latest_revision: Latest revision
340 340 label_latest_revision_plural: Latest revisions
341 341 label_view_revisions: View revisions
342 342 label_max_size: Maximum size
343 343 label_on: 'on'
344 344 label_sort_highest: Move to top
345 345 label_sort_higher: Move up
346 346 label_sort_lower: Move down
347 347 label_sort_lowest: Move to bottom
348 348 label_roadmap: Roadmap
349 349 label_roadmap_due_in: Due in
350 350 label_roadmap_overdue: %s late
351 351 label_roadmap_no_issues: No issues for this version
352 352 label_search: Search
353 label_result: %d result
354 label_result_plural: %d results
353 label_result_plural: Results
355 354 label_all_words: All words
356 355 label_wiki: Wiki
357 356 label_wiki_edit: Wiki edit
358 357 label_wiki_edit_plural: Wiki edits
359 358 label_wiki_page: Wiki page
360 359 label_wiki_page_plural: Wiki pages
361 360 label_page_index: Index
362 361 label_current_version: Current version
363 362 label_preview: Preview
364 363 label_feed_plural: Feeds
365 364 label_changes_details: Details of all changes
366 365 label_issue_tracking: Issue tracking
367 366 label_spent_time: Spent time
368 367 label_f_hour: %.2f hour
369 368 label_f_hour_plural: %.2f hours
370 369 label_time_tracking: Time tracking
371 370 label_change_plural: Changes
372 371 label_statistics: Statistics
373 372 label_commits_per_month: Commits per month
374 373 label_commits_per_author: Commits per author
375 374 label_view_diff: View differences
376 375 label_diff_inline: inline
377 376 label_diff_side_by_side: side by side
378 377 label_options: Options
379 378 label_copy_workflow_from: Copy workflow from
380 379 label_permissions_report: Permissions report
381 380 label_watched_issues: Watched issues
382 381 label_related_issues: Related issues
383 382 label_applied_status: Applied status
384 383 label_loading: Loading...
385 384 label_relation_new: New relation
386 385 label_relation_delete: Delete relation
387 386 label_relates_to: related to
388 387 label_duplicates: duplicates
389 388 label_blocks: blocks
390 389 label_blocked_by: blocked by
391 390 label_precedes: precedes
392 391 label_follows: follows
393 392 label_end_to_start: end to start
394 393 label_end_to_end: end to end
395 394 label_start_to_start: start to start
396 395 label_start_to_end: start to end
397 396 label_stay_logged_in: Stay logged in
398 397 label_disabled: disabled
399 398 label_show_completed_versions: Show completed versions
400 399 label_me: me
401 400 label_board: Forum
402 401 label_board_new: New forum
403 402 label_board_plural: Forums
404 403 label_topic_plural: Topics
405 404 label_message_plural: Messages
406 405 label_message_last: Last message
407 406 label_message_new: New message
408 407 label_reply_plural: Replies
409 408 label_send_information: Send account information to the user
410 409 label_year: Year
411 410 label_month: Month
412 411 label_week: Week
413 412 label_date_from: From
414 413 label_date_to: To
415 414 label_language_based: Language based
416 415 label_sort_by: Sort by "%s"
417 416 label_send_test_email: Send a test email
418 417 label_feeds_access_key_created_on: RSS access key created %s ago
419 418 label_module_plural: Modules
420 419 label_added_time_by: Added by %s %s ago
421 420 label_updated_time: Updated %s ago
422 421 label_jump_to_a_project: Jump to a project...
423 422 label_file_plural: Files
424 423 label_changeset_plural: Changesets
425 424
426 425 button_login: Login
427 426 button_submit: Submit
428 427 button_save: Save
429 428 button_check_all: Check all
430 429 button_uncheck_all: Uncheck all
431 430 button_delete: Delete
432 431 button_create: Create
433 432 button_test: Test
434 433 button_edit: Edit
435 434 button_add: Add
436 435 button_change: Change
437 436 button_apply: Apply
438 437 button_clear: Clear
439 438 button_lock: Lock
440 439 button_unlock: Unlock
441 440 button_download: Download
442 441 button_list: List
443 442 button_view: View
444 443 button_move: Move
445 444 button_back: Back
446 445 button_cancel: Cancel
447 446 button_activate: Activate
448 447 button_sort: Sort
449 448 button_log_time: Log time
450 449 button_rollback: Rollback to this version
451 450 button_watch: Watch
452 451 button_unwatch: Unwatch
453 452 button_reply: Reply
454 453 button_archive: Archive
455 454 button_unarchive: Unarchive
456 455 button_reset: Reset
457 456 button_rename: Rename
458 457
459 458 status_active: active
460 459 status_registered: registered
461 460 status_locked: locked
462 461
463 462 text_select_mail_notifications: Select actions for which mail notifications should be sent.
464 463 text_regexp_info: eg. ^[A-Z0-9]+$
465 464 text_min_max_length_info: 0 means no restriction
466 465 text_project_destroy_confirmation: Are you sure you want to delete this project and all related data ?
467 466 text_workflow_edit: Select a role and a tracker to edit the workflow
468 467 text_are_you_sure: Are you sure ?
469 468 text_journal_changed: changed from %s to %s
470 469 text_journal_set_to: set to %s
471 470 text_journal_deleted: deleted
472 471 text_tip_task_begin_day: task beginning this day
473 472 text_tip_task_end_day: task ending this day
474 473 text_tip_task_begin_end_day: task beginning and ending this day
475 474 text_project_identifier_info: 'Lower case letters (a-z), numbers and dashes allowed.<br />Once saved, the identifier can not be changed.'
476 475 text_caracters_maximum: %d characters maximum.
477 476 text_length_between: Length between %d and %d characters.
478 477 text_tracker_no_workflow: No workflow defined for this tracker
479 478 text_unallowed_characters: Unallowed characters
480 479 text_comma_separated: Multiple values allowed (comma separated).
481 480 text_issues_ref_in_commit_messages: Referencing and fixing issues in commit messages
482 481 text_issue_added: Issue %s has been reported.
483 482 text_issue_updated: Issue %s has been updated.
484 483 text_wiki_destroy_confirmation: Are you sure you want to delete this wiki and all its content ?
485 484 text_issue_category_destroy_question: Some issues (%d) are assigned to this category. What do you want to do ?
486 485 text_issue_category_destroy_assignments: Remove category assignments
487 486 text_issue_category_reassign_to: Reassing issues to this category
488 487
489 488 default_role_manager: Manager
490 489 default_role_developper: Developer
491 490 default_role_reporter: Reporter
492 491 default_tracker_bug: Bug
493 492 default_tracker_feature: Feature
494 493 default_tracker_support: Support
495 494 default_issue_status_new: New
496 495 default_issue_status_assigned: Assigned
497 496 default_issue_status_resolved: Resolved
498 497 default_issue_status_feedback: Feedback
499 498 default_issue_status_closed: Closed
500 499 default_issue_status_rejected: Rejected
501 500 default_doc_category_user: User documentation
502 501 default_doc_category_tech: Technical documentation
503 502 default_priority_low: Low
504 503 default_priority_normal: Normal
505 504 default_priority_high: High
506 505 default_priority_urgent: Urgent
507 506 default_priority_immediate: Immediate
508 507 default_activity_design: Design
509 508 default_activity_development: Development
510 509
511 510 enumeration_issue_priorities: Issue priorities
512 511 enumeration_doc_categories: Document categories
513 512 enumeration_activities: Activities (time tracking)
@@ -1,513 +1,512
1 1 _gloc_rule_default: '|n| n==1 ? "" : "_plural" '
2 2
3 3 actionview_datehelper_select_day_prefix:
4 4 actionview_datehelper_select_month_names: Janvier,FΓ©vrier,Mars,Avril,Mai,Juin,Juillet,AoΓ»t,Septembre,Octobre,Novembre,DΓ©cembre
5 5 actionview_datehelper_select_month_names_abbr: Jan,FΓ©v,Mars,Avril,Mai,Juin,Juil,AoΓ»t,Sept,Oct,Nov,DΓ©c
6 6 actionview_datehelper_select_month_prefix:
7 7 actionview_datehelper_select_year_prefix:
8 8 actionview_datehelper_time_in_words_day: 1 jour
9 9 actionview_datehelper_time_in_words_day_plural: %d jours
10 10 actionview_datehelper_time_in_words_hour_about: environ une heure
11 11 actionview_datehelper_time_in_words_hour_about_plural: environ %d heures
12 12 actionview_datehelper_time_in_words_hour_about_single: environ une heure
13 13 actionview_datehelper_time_in_words_minute: 1 minute
14 14 actionview_datehelper_time_in_words_minute_half: 30 secondes
15 15 actionview_datehelper_time_in_words_minute_less_than: moins d'une minute
16 16 actionview_datehelper_time_in_words_minute_plural: %d minutes
17 17 actionview_datehelper_time_in_words_minute_single: 1 minute
18 18 actionview_datehelper_time_in_words_second_less_than: moins d'une seconde
19 19 actionview_datehelper_time_in_words_second_less_than_plural: moins de %d secondes
20 20 actionview_instancetag_blank_option: Choisir
21 21
22 22 activerecord_error_inclusion: n'est pas inclus dans la liste
23 23 activerecord_error_exclusion: est reservΓ©
24 24 activerecord_error_invalid: est invalide
25 25 activerecord_error_confirmation: ne correspond pas Γ  la confirmation
26 26 activerecord_error_accepted: doit Γͺtre acceptΓ©
27 27 activerecord_error_empty: doit Γͺtre renseignΓ©
28 28 activerecord_error_blank: doit Γͺtre renseignΓ©
29 29 activerecord_error_too_long: est trop long
30 30 activerecord_error_too_short: est trop court
31 31 activerecord_error_wrong_length: n'est pas de la bonne longueur
32 32 activerecord_error_taken: est dΓ©jΓ  utilisΓ©
33 33 activerecord_error_not_a_number: n'est pas un nombre
34 34 activerecord_error_not_a_date: n'est pas une date valide
35 35 activerecord_error_greater_than_start_date: doit Γͺtre postΓ©rieur Γ  la date de dΓ©but
36 36 activerecord_error_not_same_project: n'appartient pas au mΓͺme projet
37 37 activerecord_error_circular_dependency: Cette relation crΓ©erait une dΓ©pendance circulaire
38 38
39 39 general_fmt_age: %d an
40 40 general_fmt_age_plural: %d ans
41 41 general_fmt_date: %%d/%%m/%%Y
42 42 general_fmt_datetime: %%d/%%m/%%Y %%H:%%M
43 43 general_fmt_datetime_short: %%d/%%m %%H:%%M
44 44 general_fmt_time: %%H:%%M
45 45 general_text_No: 'Non'
46 46 general_text_Yes: 'Oui'
47 47 general_text_no: 'non'
48 48 general_text_yes: 'oui'
49 49 general_lang_name: 'FranΓ§ais'
50 50 general_csv_separator: ';'
51 51 general_csv_encoding: ISO-8859-1
52 52 general_pdf_encoding: ISO-8859-1
53 53 general_day_names: Lundi,Mardi,Mercredi,Jeudi,Vendredi,Samedi,Dimanche
54 54
55 55 notice_account_updated: Le compte a été mis à jour avec succès.
56 56 notice_account_invalid_creditentials: Identifiant ou mot de passe invalide.
57 57 notice_account_password_updated: Mot de passe mis à jour avec succès.
58 58 notice_account_wrong_password: Mot de passe incorrect
59 59 notice_account_register_done: Un message contenant les instructions pour activer votre compte vous a Γ©tΓ© envoyΓ©.
60 60 notice_account_unknown_email: Aucun compte ne correspond Γ  cette adresse.
61 61 notice_can_t_change_password: Ce compte utilise une authentification externe. Impossible de changer le mot de passe.
62 62 notice_account_lost_email_sent: Un message contenant les instructions pour choisir un nouveau mot de passe vous a Γ©tΓ© envoyΓ©.
63 63 notice_account_activated: Votre compte a Γ©tΓ© activΓ©. Vous pouvez Γ  prΓ©sent vous connecter.
64 64 notice_successful_create: Création effectuée avec succès.
65 65 notice_successful_update: Mise à jour effectuée avec succès.
66 66 notice_successful_delete: Suppression effectuée avec succès.
67 67 notice_successful_connection: Connection rΓ©ussie.
68 68 notice_file_not_found: "La page Γ  laquelle vous souhaitez accΓ©der n'existe pas ou a Γ©tΓ© supprimΓ©e."
69 69 notice_locking_conflict: Les donnΓ©es ont Γ©tΓ© mises Γ  jour par un autre utilisateur. Mise Γ  jour impossible.
70 70 notice_scm_error: "L'entrΓ©e et/ou la rΓ©vision demandΓ©e n'existe pas dans le dΓ©pΓ΄t."
71 71 notice_not_authorized: "Vous n'Γͺtes pas autorisΓ©s Γ  accΓ©der Γ  cette page."
72 72 notice_email_sent: "Un email a Γ©tΓ© envoyΓ© Γ  %s"
73 73 notice_email_error: "Erreur lors de l'envoi de l'email (%s)"
74 74 notice_feeds_access_key_reseted: Votre clé d'accès aux flux RSS a été réinitialisée.
75 75
76 76 mail_subject_lost_password: Votre mot de passe redMine
77 77 mail_subject_register: Activation de votre compte redMine
78 78
79 79 gui_validation_error: 1 erreur
80 80 gui_validation_error_plural: %d erreurs
81 81
82 82 field_name: Nom
83 83 field_description: Description
84 84 field_summary: RΓ©sumΓ©
85 85 field_is_required: Obligatoire
86 86 field_firstname: PrΓ©nom
87 87 field_lastname: Nom
88 88 field_mail: Email
89 89 field_filename: Fichier
90 90 field_filesize: Taille
91 91 field_downloads: TΓ©lΓ©chargements
92 92 field_author: Auteur
93 93 field_created_on: Créé
94 94 field_updated_on: Mis Γ  jour
95 95 field_field_format: Format
96 96 field_is_for_all: Pour tous les projets
97 97 field_possible_values: Valeurs possibles
98 98 field_regexp: Expression régulière
99 99 field_min_length: Longueur minimum
100 100 field_max_length: Longueur maximum
101 101 field_value: Valeur
102 102 field_category: CatΓ©gorie
103 103 field_title: Titre
104 104 field_project: Projet
105 105 field_issue: Demande
106 106 field_status: Statut
107 107 field_notes: Notes
108 108 field_is_closed: Demande fermΓ©e
109 109 field_is_default: Statut par dΓ©faut
110 110 field_html_color: Couleur
111 111 field_tracker: Tracker
112 112 field_subject: Sujet
113 113 field_due_date: Date d'Γ©chΓ©ance
114 114 field_assigned_to: AssignΓ© Γ 
115 115 field_priority: PrioritΓ©
116 116 field_fixed_version: Version corrigΓ©e
117 117 field_user: Utilisateur
118 118 field_role: RΓ΄le
119 119 field_homepage: Site web
120 120 field_is_public: Public
121 121 field_parent: Sous-projet de
122 122 field_is_in_chlog: Demandes affichΓ©es dans l'historique
123 123 field_is_in_roadmap: Demandes affichΓ©es dans la roadmap
124 124 field_login: Identifiant
125 125 field_mail_notification: Notifications par mail
126 126 field_admin: Administrateur
127 127 field_last_login_on: Dernière connexion
128 128 field_language: Langue
129 129 field_effective_date: Date
130 130 field_password: Mot de passe
131 131 field_new_password: Nouveau mot de passe
132 132 field_password_confirmation: Confirmation
133 133 field_version: Version
134 134 field_type: Type
135 135 field_host: HΓ΄te
136 136 field_port: Port
137 137 field_account: Compte
138 138 field_base_dn: Base DN
139 139 field_attr_login: Attribut Identifiant
140 140 field_attr_firstname: Attribut PrΓ©nom
141 141 field_attr_lastname: Attribut Nom
142 142 field_attr_mail: Attribut Email
143 143 field_onthefly: CrΓ©ation des utilisateurs Γ  la volΓ©e
144 144 field_start_date: DΓ©but
145 145 field_done_ratio: %% RΓ©alisΓ©
146 146 field_auth_source: Mode d'authentification
147 147 field_hide_mail: Cacher mon adresse mail
148 148 field_comments: Commentaire
149 149 field_url: URL
150 150 field_start_page: Page de dΓ©marrage
151 151 field_subproject: Sous-projet
152 152 field_hours: Heures
153 153 field_activity: ActivitΓ©
154 154 field_spent_on: Date
155 155 field_identifier: Identifiant
156 156 field_is_filter: UtilisΓ© comme filtre
157 157 field_issue_to_id: Demande liΓ©e
158 158 field_delay: Retard
159 159 field_assignable: Demandes assignables Γ  ce rΓ΄le
160 160 field_redirect_existing_links: Rediriger les liens existants
161 161 field_estimated_hours: Temps estimΓ©
162 162
163 163 setting_app_title: Titre de l'application
164 164 setting_app_subtitle: Sous-titre de l'application
165 165 setting_welcome_text: Texte d'accueil
166 166 setting_default_language: Langue par dΓ©faut
167 167 setting_login_required: Authentif. obligatoire
168 168 setting_self_registration: Enregistrement autorisΓ©
169 169 setting_attachment_max_size: Taille max des fichiers
170 170 setting_issues_export_limit: Limite export demandes
171 171 setting_mail_from: Adresse d'Γ©mission
172 172 setting_host_name: Nom d'hΓ΄te
173 173 setting_text_formatting: Formatage du texte
174 174 setting_wiki_compression: Compression historique wiki
175 175 setting_feeds_limit: Limite du contenu des flux RSS
176 176 setting_autofetch_changesets: RΓ©cupΓ©ration auto. des commits
177 177 setting_sys_api_enabled: Activer les WS pour la gestion des dΓ©pΓ΄ts
178 178 setting_commit_ref_keywords: Mot-clΓ©s de rΓ©fΓ©rencement
179 179 setting_commit_fix_keywords: Mot-clΓ©s de rΓ©solution
180 180 setting_autologin: Autologin
181 181 setting_date_format: Format de date
182 182 setting_cross_project_issue_relations: Autoriser les relations entre demandes de diffΓ©rents projets
183 183
184 184 label_user: Utilisateur
185 185 label_user_plural: Utilisateurs
186 186 label_user_new: Nouvel utilisateur
187 187 label_project: Projet
188 188 label_project_new: Nouveau projet
189 189 label_project_plural: Projets
190 190 label_project_all: Tous les projets
191 191 label_project_latest: Derniers projets
192 192 label_issue: Demande
193 193 label_issue_new: Nouvelle demande
194 194 label_issue_plural: Demandes
195 195 label_issue_view_all: Voir toutes les demandes
196 196 label_document: Document
197 197 label_document_new: Nouveau document
198 198 label_document_plural: Documents
199 199 label_role: RΓ΄le
200 200 label_role_plural: RΓ΄les
201 201 label_role_new: Nouveau rΓ΄le
202 202 label_role_and_permissions: RΓ΄les et permissions
203 203 label_member: Membre
204 204 label_member_new: Nouveau membre
205 205 label_member_plural: Membres
206 206 label_tracker: Tracker
207 207 label_tracker_plural: Trackers
208 208 label_tracker_new: Nouveau tracker
209 209 label_workflow: Workflow
210 210 label_issue_status: Statut de demandes
211 211 label_issue_status_plural: Statuts de demandes
212 212 label_issue_status_new: Nouveau statut
213 213 label_issue_category: CatΓ©gorie de demandes
214 214 label_issue_category_plural: CatΓ©gories de demandes
215 215 label_issue_category_new: Nouvelle catΓ©gorie
216 216 label_custom_field: Champ personnalisΓ©
217 217 label_custom_field_plural: Champs personnalisΓ©s
218 218 label_custom_field_new: Nouveau champ personnalisΓ©
219 219 label_enumerations: Listes de valeurs
220 220 label_enumeration_new: Nouvelle valeur
221 221 label_information: Information
222 222 label_information_plural: Informations
223 223 label_please_login: Identification
224 224 label_register: S'enregistrer
225 225 label_password_lost: Mot de passe perdu
226 226 label_home: Accueil
227 227 label_my_page: Ma page
228 228 label_my_account: Mon compte
229 229 label_my_projects: Mes projets
230 230 label_administration: Administration
231 231 label_login: Connexion
232 232 label_logout: DΓ©connexion
233 233 label_help: Aide
234 234 label_reported_issues: Demandes soumises
235 235 label_assigned_to_me_issues: Demandes qui me sont assignΓ©es
236 236 label_last_login: Dernière connexion
237 237 label_last_updates: Dernière mise à jour
238 238 label_last_updates_plural: %d dernières mises à jour
239 239 label_registered_on: Inscrit le
240 240 label_activity: ActivitΓ©
241 241 label_new: Nouveau
242 242 label_logged_as: ConnectΓ© en tant que
243 243 label_environment: Environnement
244 244 label_authentication: Authentification
245 245 label_auth_source: Mode d'authentification
246 246 label_auth_source_new: Nouveau mode d'authentification
247 247 label_auth_source_plural: Modes d'authentification
248 248 label_subproject_plural: Sous-projets
249 249 label_min_max_length: Longueurs mini - maxi
250 250 label_list: Liste
251 251 label_date: Date
252 252 label_integer: Entier
253 253 label_boolean: BoolΓ©en
254 254 label_string: Texte
255 255 label_text: Texte long
256 256 label_attribute: Attribut
257 257 label_attribute_plural: Attributs
258 258 label_download: %d TΓ©lΓ©chargement
259 259 label_download_plural: %d TΓ©lΓ©chargements
260 260 label_no_data: Aucune donnΓ©e Γ  afficher
261 261 label_change_status: Changer le statut
262 262 label_history: Historique
263 263 label_attachment: Fichier
264 264 label_attachment_new: Nouveau fichier
265 265 label_attachment_delete: Supprimer le fichier
266 266 label_attachment_plural: Fichiers
267 267 label_report: Rapport
268 268 label_report_plural: Rapports
269 269 label_news: Annonce
270 270 label_news_new: Nouvelle annonce
271 271 label_news_plural: Annonces
272 272 label_news_latest: Dernières annonces
273 273 label_news_view_all: Voir toutes les annonces
274 274 label_change_log: Historique
275 275 label_settings: Configuration
276 276 label_overview: AperΓ§u
277 277 label_version: Version
278 278 label_version_new: Nouvelle version
279 279 label_version_plural: Versions
280 280 label_confirmation: Confirmation
281 281 label_export_to: Exporter en
282 282 label_read: Lire...
283 283 label_public_projects: Projets publics
284 284 label_open_issues: ouvert
285 285 label_open_issues_plural: ouverts
286 286 label_closed_issues: fermΓ©
287 287 label_closed_issues_plural: fermΓ©s
288 288 label_total: Total
289 289 label_permissions: Permissions
290 290 label_current_status: Statut actuel
291 291 label_new_statuses_allowed: Nouveaux statuts autorisΓ©s
292 292 label_all: tous
293 293 label_none: aucun
294 294 label_next: Suivant
295 295 label_previous: PrΓ©cΓ©dent
296 296 label_used_by: UtilisΓ© par
297 297 label_details: DΓ©tails
298 298 label_add_note: Ajouter une note
299 299 label_per_page: Par page
300 300 label_calendar: Calendrier
301 301 label_months_from: mois depuis
302 302 label_gantt: Gantt
303 303 label_internal: Interne
304 304 label_last_changes: %d derniers changements
305 305 label_change_view_all: Voir tous les changements
306 306 label_personalize_page: Personnaliser cette page
307 307 label_comment: Commentaire
308 308 label_comment_plural: Commentaires
309 309 label_comment_add: Ajouter un commentaire
310 310 label_comment_added: Commentaire ajoutΓ©
311 311 label_comment_delete: Supprimer les commentaires
312 312 label_query: Rapport personnalisΓ©
313 313 label_query_plural: Rapports personnalisΓ©s
314 314 label_query_new: Nouveau rapport
315 315 label_filter_add: Ajouter le filtre
316 316 label_filter_plural: Filtres
317 317 label_equals: Γ©gal
318 318 label_not_equals: diffΓ©rent
319 319 label_in_less_than: dans moins de
320 320 label_in_more_than: dans plus de
321 321 label_in: dans
322 322 label_today: aujourd'hui
323 323 label_this_week: cette semaine
324 324 label_less_than_ago: il y a moins de
325 325 label_more_than_ago: il y a plus de
326 326 label_ago: il y a
327 327 label_contains: contient
328 328 label_not_contains: ne contient pas
329 329 label_day_plural: jours
330 330 label_repository: DΓ©pΓ΄t
331 331 label_browse: Parcourir
332 332 label_modification: %d modification
333 333 label_modification_plural: %d modifications
334 334 label_revision: RΓ©vision
335 335 label_revision_plural: RΓ©visions
336 336 label_added: ajoutΓ©
337 337 label_modified: modifiΓ©
338 338 label_deleted: supprimΓ©
339 339 label_latest_revision: Dernière révision
340 340 label_latest_revision_plural: Dernières révisions
341 341 label_view_revisions: Voir les rΓ©visions
342 342 label_max_size: Taille maximale
343 343 label_on: sur
344 344 label_sort_highest: Remonter en premier
345 345 label_sort_higher: Remonter
346 346 label_sort_lower: Descendre
347 347 label_sort_lowest: Descendre en dernier
348 348 label_roadmap: Roadmap
349 349 label_roadmap_due_in: EchΓ©ance dans
350 350 label_roadmap_overdue: En retard de %s
351 351 label_roadmap_no_issues: Aucune demande pour cette version
352 352 label_search: Recherche
353 label_result: %d rΓ©sultat
354 label_result_plural: %d rΓ©sultats
353 label_result_plural: RΓ©sultats
355 354 label_all_words: Tous les mots
356 355 label_wiki: Wiki
357 356 label_wiki_edit: RΓ©vision wiki
358 357 label_wiki_edit_plural: RΓ©visions wiki
359 358 label_wiki_page: Page wiki
360 359 label_wiki_page_plural: Pages wiki
361 360 label_page_index: Index
362 361 label_current_version: Version actuelle
363 362 label_preview: PrΓ©visualisation
364 363 label_feed_plural: Flux RSS
365 364 label_changes_details: DΓ©tails de tous les changements
366 365 label_issue_tracking: Suivi des demandes
367 366 label_spent_time: Temps passΓ©
368 367 label_f_hour: %.2f heure
369 368 label_f_hour_plural: %.2f heures
370 369 label_time_tracking: Suivi du temps
371 370 label_change_plural: Changements
372 371 label_statistics: Statistiques
373 372 label_commits_per_month: Commits par mois
374 373 label_commits_per_author: Commits par auteur
375 374 label_view_diff: Voir les diffΓ©rences
376 375 label_diff_inline: en ligne
377 376 label_diff_side_by_side: cΓ΄te Γ  cΓ΄te
378 377 label_options: Options
379 378 label_copy_workflow_from: Copier le workflow de
380 379 label_permissions_report: Synthèse des permissions
381 380 label_watched_issues: Demandes surveillΓ©es
382 381 label_related_issues: Demandes liΓ©es
383 382 label_applied_status: Statut appliquΓ©
384 383 label_loading: Chargement...
385 384 label_relation_new: Nouvelle relation
386 385 label_relation_delete: Supprimer la relation
387 386 label_relates_to: liΓ© Γ 
388 387 label_duplicates: doublon de
389 388 label_blocks: bloque
390 389 label_blocked_by: bloquΓ© par
391 390 label_precedes: précède
392 391 label_follows: suit
393 392 label_end_to_start: fin Γ  dΓ©but
394 393 label_end_to_end: fin Γ  fin
395 394 label_start_to_start: dΓ©but Γ  dΓ©but
396 395 label_start_to_end: dΓ©but Γ  fin
397 396 label_stay_logged_in: Rester connectΓ©
398 397 label_disabled: dΓ©sactivΓ©
399 398 label_show_completed_versions: Voire les versions passΓ©es
400 399 label_me: moi
401 400 label_board: Forum
402 401 label_board_new: Nouveau forum
403 402 label_board_plural: Forums
404 403 label_topic_plural: Discussions
405 404 label_message_plural: Messages
406 405 label_message_last: Dernier message
407 406 label_message_new: Nouveau message
408 407 label_reply_plural: RΓ©ponses
409 408 label_send_information: Envoyer les informations Γ  l'utilisateur
410 409 label_year: AnnΓ©e
411 410 label_month: Mois
412 411 label_week: Semaine
413 412 label_date_from: Du
414 413 label_date_to: Au
415 414 label_language_based: BasΓ© sur la langue
416 415 label_sort_by: Trier par "%s"
417 416 label_send_test_email: Envoyer un email de test
418 417 label_feeds_access_key_created_on: Clé d'accès RSS créée il y a %s
419 418 label_module_plural: Modules
420 419 label_added_time_by: AjoutΓ© par %s il y a %s
421 420 label_updated_time: Mis Γ  jour il y a %s
422 421 label_jump_to_a_project: Aller Γ  un projet...
423 422 label_file_plural: Fichiers
424 423 label_changeset_plural: RΓ©visions
425 424
426 425 button_login: Connexion
427 426 button_submit: Soumettre
428 427 button_save: Sauvegarder
429 428 button_check_all: Tout cocher
430 429 button_uncheck_all: Tout dΓ©cocher
431 430 button_delete: Supprimer
432 431 button_create: CrΓ©er
433 432 button_test: Tester
434 433 button_edit: Modifier
435 434 button_add: Ajouter
436 435 button_change: Changer
437 436 button_apply: Appliquer
438 437 button_clear: Effacer
439 438 button_lock: Verrouiller
440 439 button_unlock: DΓ©verrouiller
441 440 button_download: TΓ©lΓ©charger
442 441 button_list: Lister
443 442 button_view: Voir
444 443 button_move: DΓ©placer
445 444 button_back: Retour
446 445 button_cancel: Annuler
447 446 button_activate: Activer
448 447 button_sort: Trier
449 448 button_log_time: Saisir temps
450 449 button_rollback: Revenir Γ  cette version
451 450 button_watch: Surveiller
452 451 button_unwatch: Ne plus surveiller
453 452 button_reply: RΓ©pondre
454 453 button_archive: Archiver
455 454 button_unarchive: DΓ©sarchiver
456 455 button_reset: RΓ©initialiser
457 456 button_rename: Renommer
458 457
459 458 status_active: actif
460 459 status_registered: enregistrΓ©
461 460 status_locked: vΓ©rouillΓ©
462 461
463 462 text_select_mail_notifications: SΓ©lectionner les actions pour lesquelles la notification par mail doit Γͺtre activΓ©e.
464 463 text_regexp_info: ex. ^[A-Z0-9]+$
465 464 text_min_max_length_info: 0 pour aucune restriction
466 465 text_project_destroy_confirmation: Etes-vous sΓ»r de vouloir supprimer ce projet et tout ce qui lui est rattachΓ© ?
467 466 text_workflow_edit: SΓ©lectionner un tracker et un rΓ΄le pour Γ©diter le workflow
468 467 text_are_you_sure: Etes-vous sΓ»r ?
469 468 text_journal_changed: changΓ© de %s Γ  %s
470 469 text_journal_set_to: mis Γ  %s
471 470 text_journal_deleted: supprimΓ©
472 471 text_tip_task_begin_day: tΓ’che commenΓ§ant ce jour
473 472 text_tip_task_end_day: tΓ’che finissant ce jour
474 473 text_tip_task_begin_end_day: tΓ’che commenΓ§ant et finissant ce jour
475 474 text_project_identifier_info: 'Lettres minuscules (a-z), chiffres et tirets autorisΓ©s.<br />Un fois sauvegardΓ©, l''identifiant ne pourra plus Γͺtre modifiΓ©.'
476 475 text_caracters_maximum: %d caractères maximum.
477 476 text_length_between: Longueur comprise entre %d et %d caractères.
478 477 text_tracker_no_workflow: Aucun worflow n'est dΓ©fini pour ce tracker
479 478 text_unallowed_characters: Caractères non autorisés
480 479 text_comma_separated: Plusieurs valeurs possibles (sΓ©parΓ©es par des virgules).
481 480 text_issues_ref_in_commit_messages: RΓ©fΓ©rencement et rΓ©solution des demandes dans les commentaires de commits
482 481 text_issue_added: La demande %s a Γ©tΓ© soumise.
483 482 text_issue_updated: La demande %s a Γ©tΓ© mise Γ  jour.
484 483 text_wiki_destroy_confirmation: Etes-vous sΓ»r de vouloir supprimer ce wiki et tout son contenu ?
485 484 text_issue_category_destroy_question: Des demandes (%d) sont affectΓ©es Γ  cette catΓ©gories. Que voulez-vous faire ?
486 485 text_issue_category_destroy_assignments: N'affecter les demandes Γ  aucune autre catΓ©gorie
487 486 text_issue_category_reassign_to: RΓ©affecter les demandes Γ  cette catΓ©gorie
488 487
489 488 default_role_manager: Manager
490 489 default_role_developper: DΓ©veloppeur
491 490 default_role_reporter: Rapporteur
492 491 default_tracker_bug: Anomalie
493 492 default_tracker_feature: Evolution
494 493 default_tracker_support: Assistance
495 494 default_issue_status_new: Nouveau
496 495 default_issue_status_assigned: AssignΓ©
497 496 default_issue_status_resolved: RΓ©solu
498 497 default_issue_status_feedback: Commentaire
499 498 default_issue_status_closed: FermΓ©
500 499 default_issue_status_rejected: RejetΓ©
501 500 default_doc_category_user: Documentation utilisateur
502 501 default_doc_category_tech: Documentation technique
503 502 default_priority_low: Bas
504 503 default_priority_normal: Normal
505 504 default_priority_high: Haut
506 505 default_priority_urgent: Urgent
507 506 default_priority_immediate: ImmΓ©diat
508 507 default_activity_design: Conception
509 508 default_activity_development: DΓ©veloppement
510 509
511 510 enumeration_issue_priorities: PrioritΓ©s des demandes
512 511 enumeration_doc_categories: CatΓ©gories des documents
513 512 enumeration_activities: ActivitΓ©s (suivi du temps)
1 NO CONTENT: file renamed from lib/redmine/acts_as_event/init.rb to lib/plugins/acts_as_event/init.rb
1 NO CONTENT: file renamed from lib/redmine/acts_as_event/lib/acts_as_event.rb to lib/plugins/acts_as_event/lib/acts_as_event.rb
1 NO CONTENT: file renamed from lib/redmine/acts_as_watchable/init.rb to lib/plugins/acts_as_watchable/init.rb
1 NO CONTENT: file renamed from lib/redmine/acts_as_watchable/lib/acts_as_watchable.rb to lib/plugins/acts_as_watchable/lib/acts_as_watchable.rb
@@ -1,103 +1,101
1 1 require 'redmine/access_control'
2 2 require 'redmine/menu_manager'
3 3 require 'redmine/mime_type'
4 require 'redmine/acts_as_watchable/init'
5 require 'redmine/acts_as_event/init'
6 4 require 'redmine/plugin'
7 5
8 6 begin
9 7 require_library_or_gem 'RMagick' unless Object.const_defined?(:Magick)
10 8 rescue LoadError
11 9 # RMagick is not available
12 10 end
13 11
14 12 REDMINE_SUPPORTED_SCM = %w( Subversion Darcs Mercurial Cvs )
15 13
16 14 # Permissions
17 15 Redmine::AccessControl.map do |map|
18 16 map.permission :view_project, {:projects => [:show, :activity, :feeds]}, :public => true
19 17 map.permission :search_project, {:search => :index}, :public => true
20 18 map.permission :edit_project, {:projects => [:settings, :edit]}, :require => :member
21 19 map.permission :select_project_modules, {:projects => :modules}, :require => :member
22 20 map.permission :manage_members, {:projects => :settings, :members => [:new, :edit, :destroy]}, :require => :member
23 21 map.permission :manage_versions, {:projects => [:settings, :add_version], :versions => [:edit, :destroy]}, :require => :member
24 22
25 23 map.project_module :issue_tracking do |map|
26 24 # Issue categories
27 25 map.permission :manage_categories, {:projects => [:settings, :add_issue_category], :issue_categories => [:edit, :destroy]}, :require => :member
28 26 # Issues
29 27 map.permission :view_issues, {:projects => [:list_issues, :export_issues_csv, :export_issues_pdf, :changelog, :roadmap],
30 28 :issues => [:show, :export_pdf],
31 29 :queries => :index,
32 30 :reports => :issue_report}, :public => true
33 31 map.permission :add_issues, {:projects => :add_issue}, :require => :loggedin
34 32 map.permission :edit_issues, {:issues => [:edit, :destroy_attachment]}, :require => :loggedin
35 33 map.permission :manage_issue_relations, {:issue_relations => [:new, :destroy]}, :require => :loggedin
36 34 map.permission :add_issue_notes, {:issues => :add_note}, :require => :loggedin
37 35 map.permission :change_issue_status, {:issues => :change_status}, :require => :loggedin
38 36 map.permission :move_issues, {:projects => :move_issues}, :require => :loggedin
39 37 map.permission :delete_issues, {:issues => :destroy}, :require => :member
40 38 # Queries
41 39 map.permission :manage_pulic_queries, {:queries => [:new, :edit, :destroy]}, :require => :member
42 40 map.permission :save_queries, {:queries => [:new, :edit, :destroy]}, :require => :loggedin
43 41 # Gantt & calendar
44 42 map.permission :view_gantt, :projects => :gantt
45 43 map.permission :view_calendar, :projects => :calendar
46 44 end
47 45
48 46 map.project_module :time_tracking do |map|
49 47 map.permission :log_time, {:timelog => :edit}, :require => :loggedin
50 48 map.permission :view_time_entries, :timelog => [:details, :report]
51 49 end
52 50
53 51 map.project_module :news do |map|
54 52 map.permission :manage_news, {:projects => :add_news, :news => [:edit, :destroy, :destroy_comment]}, :require => :member
55 53 map.permission :view_news, {:projects => :list_news, :news => :show}, :public => true
56 54 map.permission :comment_news, {:news => :add_comment}, :require => :loggedin
57 55 end
58 56
59 57 map.project_module :documents do |map|
60 58 map.permission :manage_documents, {:projects => :add_document, :documents => [:edit, :destroy, :add_attachment, :destroy_attachment]}, :require => :loggedin
61 59 map.permission :view_documents, :projects => :list_documents, :documents => [:show, :download]
62 60 end
63 61
64 62 map.project_module :files do |map|
65 63 map.permission :manage_files, {:projects => :add_file, :versions => :destroy_file}, :require => :loggedin
66 64 map.permission :view_files, :projects => :list_files, :versions => :download
67 65 end
68 66
69 67 map.project_module :wiki do |map|
70 68 map.permission :manage_wiki, {:wikis => [:edit, :destroy]}, :require => :member
71 69 map.permission :rename_wiki_pages, {:wiki => :rename}, :require => :member
72 70 map.permission :delete_wiki_pages, {:wiki => :destroy}, :require => :member
73 71 map.permission :view_wiki_pages, :wiki => [:index, :history, :diff, :special]
74 72 map.permission :edit_wiki_pages, :wiki => [:edit, :preview, :add_attachment, :destroy_attachment]
75 73 end
76 74
77 75 map.project_module :repository do |map|
78 76 map.permission :manage_repository, :repositories => [:edit, :destroy]
79 77 map.permission :browse_repository, :repositories => [:show, :browse, :entry, :changes, :diff, :stats, :graph]
80 78 map.permission :view_changesets, :repositories => [:show, :revisions, :revision]
81 79 end
82 80
83 81 map.project_module :boards do |map|
84 82 map.permission :manage_boards, {:boards => [:new, :edit, :destroy]}, :require => :member
85 83 map.permission :view_messages, {:boards => [:index, :show], :messages => [:show]}, :public => true
86 84 map.permission :add_messages, {:messages => [:new, :reply]}, :require => :loggedin
87 85 end
88 86 end
89 87
90 88 # Project menu configuration
91 89 Redmine::MenuManager.map :project_menu do |menu|
92 90 menu.push :label_overview, :controller => 'projects', :action => 'show'
93 91 menu.push :label_activity, :controller => 'projects', :action => 'activity'
94 92 menu.push :label_roadmap, :controller => 'projects', :action => 'roadmap'
95 93 menu.push :label_issue_plural, :controller => 'projects', :action => 'list_issues'
96 94 menu.push :label_news_plural, :controller => 'projects', :action => 'list_news'
97 95 menu.push :label_document_plural, :controller => 'projects', :action => 'list_documents'
98 96 menu.push :label_wiki, { :controller => 'wiki', :action => 'index', :page => nil }, :if => Proc.new { |p| p.wiki && !p.wiki.new_record? }
99 97 menu.push :label_board_plural, { :controller => 'boards', :action => 'index', :id => nil }, :param => :project_id, :if => Proc.new { |p| p.boards.any? }
100 98 menu.push :label_attachment_plural, :controller => 'projects', :action => 'list_files'
101 99 menu.push :label_repository, { :controller => 'repositories', :action => 'show' }, :if => Proc.new { |p| p.repository && !p.repository.new_record? }
102 100 menu.push :label_settings, :controller => 'projects', :action => 'settings'
103 101 end
@@ -1,49 +1,49
1 1 require File.dirname(__FILE__) + '/../test_helper'
2 2 require 'search_controller'
3 3
4 4 # Re-raise errors caught by the controller.
5 5 class SearchController; def rescue_action(e) raise e end; end
6 6
7 7 class SearchControllerTest < Test::Unit::TestCase
8 8 fixtures :projects, :issues
9 9
10 10 def setup
11 11 @controller = SearchController.new
12 12 @request = ActionController::TestRequest.new
13 13 @response = ActionController::TestResponse.new
14 14 User.current = nil
15 15 end
16 16
17 17 def test_search_for_projects
18 18 get :index
19 19 assert_response :success
20 20 assert_template 'index'
21 21
22 22 get :index, :q => "cook"
23 23 assert_response :success
24 24 assert_template 'index'
25 25 assert assigns(:results).include?(Project.find(1))
26 26 end
27 27
28 28 def test_search_in_project
29 29 get :index, :id => 1
30 30 assert_response :success
31 31 assert_template 'index'
32 32 assert_not_nil assigns(:project)
33 33
34 get :index, :id => 1, :q => "can", :scope => ["issues", "news", "documents"]
34 get :index, :id => 1, :q => "can"
35 35 assert_response :success
36 36 assert_template 'index'
37 37 end
38 38
39 39 def test_quick_jump_to_issue
40 40 # issue of a public project
41 41 get :index, :q => "3"
42 42 assert_redirected_to 'issues/show/3'
43 43
44 44 # issue of a private project
45 45 get :index, :q => "4"
46 46 assert_response :success
47 47 assert_template 'index'
48 48 end
49 49 end
General Comments 0
You need to be logged in to leave comments. Login now