##// END OF EJS Templates
Display status change before subject of issue on the activity view otherwise it may be truncated....
Display status change before subject of issue on the activity view otherwise it may be truncated. git-svn-id: http://redmine.rubyforge.org/svn/trunk@1505 e93f8b46-1217-0410-a6f0-8f06a7374b81

File last commit:

r1459:39216f327c63
r1491:2e8b2d5e1312
Show More
project.rb
262 lines | 9.9 KiB | text/x-ruby | RubyLexer
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Project < ActiveRecord::Base
Jean-Philippe Lang
Added the ability to archive projects:...
r546 # Project statuses
STATUS_ACTIVE = 1
STATUS_ARCHIVED = 9
Jean-Philippe Lang
Merged Rails 2.0 compatibility changes....
r962 has_many :members, :include => :user, :conditions => "#{User.table_name}.status=#{User::STATUS_ACTIVE}"
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 has_many :users, :through => :members
has_many :custom_values, :dependent => :delete_all, :as => :customized
Jean-Philippe Lang
Added project module concept....
r714 has_many :enabled_modules, :dependent => :delete_all
Jean-Philippe Lang
Added per-project tracker selection. Trackers can be selected on project settings....
r907 has_and_belongs_to_many :trackers, :order => "#{Tracker.table_name}.position"
Jean-Philippe Lang
fixed #9308 table_name pre/suffix support...
r334 has_many :issues, :dependent => :destroy, :order => "#{Issue.table_name}.created_on DESC", :include => [:status, :tracker]
Jean-Philippe Lang
Activity view improvements:...
r640 has_many :issue_changes, :through => :issues, :source => :journals
Jean-Philippe Lang
Fixed an error when trying to delete a project (versions/issues dependency)...
r571 has_many :versions, :dependent => :destroy, :order => "#{Version.table_name}.effective_date DESC, #{Version.table_name}.name DESC"
Jean-Philippe Lang
Simple time tracking functionality added. Time can be logged at issue or project level....
r365 has_many :time_entries, :dependent => :delete_all
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 has_many :queries, :dependent => :delete_all
has_many :documents, :dependent => :destroy
has_many :news, :dependent => :delete_all, :include => :author
Jean-Philippe Lang
fixed #9308 table_name pre/suffix support...
r334 has_many :issue_categories, :dependent => :delete_all, :order => "#{IssueCategory.table_name}.name"
Jean-Philippe Lang
Fixed: Boards are not deleted when project is deleted (closes #963)....
r1301 has_many :boards, :dependent => :destroy, :order => "position ASC"
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 has_one :repository, :dependent => :destroy
Jean-Philippe Lang
Improved Redmine links:...
r703 has_many :changesets, :through => :repository
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 has_one :wiki, :dependent => :destroy
Jean-Philippe Lang
Custom fields can now be reordered....
r888 # Custom field for the project issues
has_and_belongs_to_many :custom_fields,
:class_name => 'IssueCustomField',
:order => "#{CustomField.table_name}.position",
:join_table => "#{table_name_prefix}custom_fields_projects#{table_name_suffix}",
:association_foreign_key => 'custom_field_id'
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 acts_as_tree :order => "name", :counter_cache => true
Jean-Philippe Lang
Search engines now supports pagination....
r755
Jean-Philippe Lang
Ability to search all projects or the projects the user belongs to (#791)....
r1420 acts_as_searchable :columns => ['name', 'description'], :project_key => 'id', :permission => nil
Jean-Philippe Lang
Search engines now supports pagination....
r755 acts_as_event :title => Proc.new {|o| "#{l(:label_project)}: #{o.name}"},
:url => Proc.new {|o| {:controller => 'projects', :action => 'show', :id => o.id}}
Jean-Philippe Lang
Added project module concept....
r714 attr_protected :status, :enabled_module_names
Jean-Philippe Lang
Added the ability to archive projects:...
r546
Jean-Philippe Lang
Unlimited and optional project description. The project list will show truncated descriptions only (the first fews lines)....
r1074 validates_presence_of :name, :identifier
Jean-Philippe Lang
Initial commit for svn repository management and access control:...
r393 validates_uniqueness_of :name, :identifier
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 validates_associated :custom_values, :on => :update
validates_associated :repository, :wiki
Jean-Philippe Lang
Added some attributes length validations....
r397 validates_length_of :name, :maximum => 30
Jean-Philippe Lang
Change projects homepage limit to 255 chars (#663, #1095)....
r1443 validates_length_of :homepage, :maximum => 255
Jean-Philippe Lang
Project name format limitation removed (name can now contain any character)....
r936 validates_length_of :identifier, :in => 3..20
Jean-Philippe Lang
Initial commit for svn repository management and access control:...
r393 validates_format_of :identifier, :with => /^[a-z0-9\-]*$/
Jean-Philippe Lang
Merged Rails 2.0 compatibility changes....
r962 before_destroy :delete_all_members
Jean-Philippe Lang
Initial commit for svn repository management and access control:...
r393 def identifier=(identifier)
super unless identifier_frozen?
end
def identifier_frozen?
errors[:identifier].nil? && !(new_record? || identifier.blank?)
end
Jean-Philippe Lang
Added the ability to include subprojects issues on calendar & gantt (options box)...
r395 def issues_with_subprojects(include_subprojects=false)
conditions = nil
Jean-Philippe Lang
Fixed: Calendar and Gantt show private subprojects even if current user is not a member of them (#1217)....
r1416 if include_subprojects
ids = [id] + child_ids
conditions = ["#{Project.table_name}.id IN (#{ids.join(',')}) AND #{Project.visible_by}"]
Jean-Philippe Lang
Added the ability to include subprojects issues on calendar & gantt (options box)...
r395 end
Jean-Philippe Lang
Include subprojects versions on calendar and gantt (#1116)....
r1349 conditions ||= ["#{Project.table_name}.id = ?", id]
Jean-Philippe Lang
Fixed: calendar and gantt broken with Rails 2.0...
r969 # Quick and dirty fix for Rails 2 compatibility
Issue.send(:with_scope, :find => { :conditions => conditions }) do
Jean-Philippe Lang
Include subprojects versions on calendar and gantt (#1116)....
r1349 Version.send(:with_scope, :find => { :conditions => conditions }) do
yield
end
Jean-Philippe Lang
Added the ability to include subprojects issues on calendar & gantt (options box)...
r395 end
end
Jean-Philippe Lang
Added issues status changes on the activity view (initial patch by Cyril Mougel)....
r879
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 # returns latest created projects
# non public projects will be returned only if user is a member of those
def self.latest(user=nil, count=5)
Jean-Philippe Lang
fixed #9308 table_name pre/suffix support...
r334 find(:all, :limit => count, :conditions => visible_by(user), :order => "created_on DESC")
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 end
def self.visible_by(user=nil)
Jean-Philippe Lang
Fixed: Calendar and Gantt show private subprojects even if current user is not a member of them (#1217)....
r1416 user ||= User.current
Jean-Philippe Lang
Projects menu item now shows the list of public projects and projects for which the user is a member (marked with a star)....
r457 if user && user.admin?
Jean-Philippe Lang
Added a cross-project issue list. It displays the issues of all the projects visible by the user....
r673 return "#{Project.table_name}.status=#{Project::STATUS_ACTIVE}"
Jean-Philippe Lang
Fixed an error on welcome screen for users with no membership...
r566 elsif user && user.memberships.any?
Jean-Philippe Lang
Added a cross-project issue list. It displays the issues of all the projects visible by the user....
r673 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(',')}))"
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 else
Jean-Philippe Lang
Added a cross-project issue list. It displays the issues of all the projects visible by the user....
r673 return "#{Project.table_name}.status=#{Project::STATUS_ACTIVE} AND #{Project.table_name}.is_public = #{connection.quoted_true}"
Jean-Philippe Lang
Added the ability to archive projects:...
r546 end
end
Jean-Philippe Lang
Activity enhancements:...
r1213 def self.allowed_to_condition(user, permission, options={})
Jean-Philippe Lang
Propagates time tracking to the parent project (closes #433). Time report enhancements....
r1162 statements = []
Jean-Philippe Lang
Activity enhancements:...
r1213 base_statement = "#{Project.table_name}.status=#{Project::STATUS_ACTIVE}"
if options[:project]
project_statement = "#{Project.table_name}.id = #{options[:project].id}"
project_statement << " OR #{Project.table_name}.parent_id = #{options[:project].id}" if options[:with_subprojects]
base_statement = "(#{project_statement}) AND (#{base_statement})"
end
Jean-Philippe Lang
Propagates time tracking to the parent project (closes #433). Time report enhancements....
r1162 if user.admin?
# no restriction
elsif user.logged?
statements << "#{Project.table_name}.is_public = #{connection.quoted_true}" if Role.non_member.allowed_to?(permission)
allowed_project_ids = user.memberships.select {|m| m.role.allowed_to?(permission)}.collect {|m| m.project_id}
Jean-Philippe Lang
Fixed #759: Can not view a project without View time entries permission (broken by r1176)....
r1170 statements << "#{Project.table_name}.id IN (#{allowed_project_ids.join(',')})" if allowed_project_ids.any?
Jean-Philippe Lang
Activity enhancements:...
r1213 elsif Role.anonymous.allowed_to?(permission)
# anonymous user allowed on public project
statements << "#{Project.table_name}.is_public = #{connection.quoted_true}"
Jean-Philippe Lang
Propagates time tracking to the parent project (closes #433). Time report enhancements....
r1162 else
Jean-Philippe Lang
Activity enhancements:...
r1213 # anonymous user is not authorized
statements << "1=0"
Jean-Philippe Lang
Propagates time tracking to the parent project (closes #433). Time report enhancements....
r1162 end
Jean-Philippe Lang
Activity enhancements:...
r1213 statements.empty? ? base_statement : "((#{base_statement}) AND (#{statements.join(' OR ')}))"
Jean-Philippe Lang
Propagates time tracking to the parent project (closes #433). Time report enhancements....
r1162 end
Jean-Philippe Lang
If 'Display subprojects issues on main projects' is set to false:...
r1283 def project_condition(with_subprojects)
cond = "#{Project.table_name}.id = #{id}"
cond = "(#{cond} OR #{Project.table_name}.parent_id = #{id})" if with_subprojects
cond
end
Jean-Philippe Lang
Project identifier is now used in URLs (instead of project id)....
r994 def self.find(*args)
if args.first && args.first.is_a?(String) && !args.first.match(/^\d*$/)
project = find_by_identifier(*args)
raise ActiveRecord::RecordNotFound, "Couldn't find Project with identifier=#{args.first}" if project.nil?
project
else
super
end
end
def to_param
Jean-Philippe Lang
Fixed: can not access old projects created with a numeric identifier (#1322)....
r1459 # id is used for projects with a numeric identifier (compatibility)
@to_param ||= (identifier.to_s =~ %r{^\d*$} ? id : identifier)
Jean-Philippe Lang
Project identifier is now used in URLs (instead of project id)....
r994 end
Jean-Philippe Lang
Added the ability to archive projects:...
r546 def active?
self.status == STATUS_ACTIVE
end
def archive
# Archive subprojects if any
children.each do |subproject|
subproject.archive
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 end
Jean-Philippe Lang
Added the ability to archive projects:...
r546 update_attribute :status, STATUS_ARCHIVED
end
def unarchive
return false if parent && !parent.active?
update_attribute :status, STATUS_ACTIVE
end
def active_children
children.select {|child| child.active?}
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 end
Jean-Philippe Lang
On the calendar, the gantt and in the Tracker filter on the issue list, only active trackers of the project (and its sub projects) can be selected....
r1057 # Returns an array of the trackers used by the project and its sub projects
def rolled_up_trackers
@rolled_up_trackers ||=
Tracker.find(:all, :include => :projects,
:select => "DISTINCT #{Tracker.table_name}.*",
:conditions => ["#{Project.table_name}.id = ? OR #{Project.table_name}.parent_id = ?", id, id],
:order => "#{Tracker.table_name}.position")
end
Jean-Philippe Lang
Merged Rails 2.0 compatibility changes....
r962 # Deletes all project's members
def delete_all_members
Member.delete_all(['project_id = ?', id])
end
Jean-Philippe Lang
Added 'Bulk edit' functionality....
r806 # Users issues can be assigned to
def assignable_users
Jean-Philippe Lang
'Assigned to' drop down list is now sorted by user's lastname....
r926 members.select {|m| m.role.assignable?}.collect {|m| m.user}.sort
Jean-Philippe Lang
Added 'Bulk edit' functionality....
r806 end
Jean-Philippe Lang
More flexible mail notifications settings at user level. A user has now 3 options:...
r842 # Returns the mail adresses of users that should be always notified on project events
def recipients
members.select {|m| m.mail_notification? || m.user.mail_notification?}.collect {|m| m.user.mail}
end
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 # Returns an array of all custom fields enabled for project issues
# (explictly associated custom fields and custom fields enabled for all projects)
def custom_fields_for_issues(tracker)
Jean-Philippe Lang
fixed #9308 table_name pre/suffix support...
r334 all_custom_fields.select {|c| tracker.custom_fields.include? c }
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 end
def all_custom_fields
Jean-Philippe Lang
fixed #9308 table_name pre/suffix support...
r334 @all_custom_fields ||= (IssueCustomField.for_all + custom_fields).uniq
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 end
Jean-Philippe Lang
Subprojects are now grouped by projects in the 'Projects' top navigation drop-down menu....
r692
Jean-Philippe Lang
Ability to search all projects or the projects the user belongs to (#791)....
r1420 def project
self
end
Jean-Philippe Lang
Subprojects are now grouped by projects in the 'Projects' top navigation drop-down menu....
r692 def <=>(project)
Jean-Philippe Lang
* Added time zone support: users can select their time zone on their account view....
r904 name.downcase <=> project.name.downcase
Jean-Philippe Lang
Subprojects are now grouped by projects in the 'Projects' top navigation drop-down menu....
r692 end
Jean-Philippe Lang
Added project module concept....
r714
Jean-Philippe Lang
Unlimited and optional project description. The project list will show truncated descriptions only (the first fews lines)....
r1074 def to_s
name
end
# Returns a short description of the projects (first lines)
def short_description(length = 255)
description.gsub(/^(.{#{length}}[^\n]*).*$/m, '\1').strip if description
end
Jean-Philippe Lang
Added project module concept....
r714 def allows_to?(action)
if action.is_a? Hash
allowed_actions.include? "#{action[:controller]}/#{action[:action]}"
else
allowed_permissions.include? action
end
end
def module_enabled?(module_name)
module_name = module_name.to_s
enabled_modules.detect {|m| m.name == module_name}
end
def enabled_module_names=(module_names)
enabled_modules.clear
module_names = [] unless module_names && module_names.is_a?(Array)
module_names.each do |name|
enabled_modules << EnabledModule.new(:name => name.to_s)
end
end
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330
protected
def validate
errors.add(parent_id, " must be a root project") if parent and parent.parent
errors.add_to_base("A project with subprojects can't be a subproject") if parent and children.size > 0
Jean-Philippe Lang
Do not authorize project identifier with numbers only (would be interpreted as the project id in urls)....
r1094 errors.add(:identifier, :activerecord_error_invalid) if !identifier.blank? && identifier.match(/^\d*$/)
Jean-Philippe Lang
v0.2.0...
r5 end
Jean-Philippe Lang
Added project module concept....
r714
private
def allowed_permissions
@allowed_permissions ||= begin
module_names = enabled_modules.collect {|m| m.name}
Redmine::AccessControl.modules_permissions(module_names).collect {|p| p.name}
end
end
def allowed_actions
@actions_allowed ||= allowed_permissions.inject([]) { |actions, permission| actions += Redmine::AccessControl.allowed_actions(permission) }.flatten
end
Jean-Philippe Lang
Initial commit...
r2 end