added svn:eol-style native property on /app files

git-svn-id: http://redmine.rubyforge.org/svn/trunk@333 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
Jean-Philippe Lang 2007-03-12 17:59:02 +00:00
parent 071f8e18d0
commit 027bf93849
180 changed files with 6362 additions and 6362 deletions

View File

@ -1,131 +1,131 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang # Copyright (C) 2006-2007 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class AccountController < ApplicationController class AccountController < ApplicationController
layout 'base' layout 'base'
helper :custom_fields helper :custom_fields
include CustomFieldsHelper include CustomFieldsHelper
# prevents login action to be filtered by check_if_login_required application scope filter # prevents login action to be filtered by check_if_login_required application scope filter
skip_before_filter :check_if_login_required, :only => [:login, :lost_password, :register] skip_before_filter :check_if_login_required, :only => [:login, :lost_password, :register]
before_filter :require_login, :only => :logout before_filter :require_login, :only => :logout
# Show user's account # Show user's account
def show def show
@user = User.find(params[:id]) @user = User.find(params[:id])
@custom_values = @user.custom_values.find(:all, :include => :custom_field) @custom_values = @user.custom_values.find(:all, :include => :custom_field)
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
render_404 render_404
end end
# Login request and validation # Login request and validation
def login def login
if request.get? if request.get?
# Logout user # Logout user
self.logged_in_user = nil self.logged_in_user = nil
else else
# Authenticate user # Authenticate user
user = User.try_to_login(params[:login], params[:password]) user = User.try_to_login(params[:login], params[:password])
if user if user
self.logged_in_user = user self.logged_in_user = user
redirect_back_or_default :controller => 'my', :action => 'page' redirect_back_or_default :controller => 'my', :action => 'page'
else else
flash.now[:notice] = l(:notice_account_invalid_creditentials) flash.now[:notice] = l(:notice_account_invalid_creditentials)
end end
end end
end end
# Log out current user and redirect to welcome page # Log out current user and redirect to welcome page
def logout def logout
self.logged_in_user = nil self.logged_in_user = nil
redirect_to :controller => 'welcome' redirect_to :controller => 'welcome'
end end
# Enable user to choose a new password # Enable user to choose a new password
def lost_password def lost_password
redirect_to :controller => 'welcome' and return unless Setting.lost_password? redirect_to :controller => 'welcome' and return unless Setting.lost_password?
if params[:token] if params[:token]
@token = Token.find_by_action_and_value("recovery", params[:token]) @token = Token.find_by_action_and_value("recovery", params[:token])
redirect_to :controller => 'welcome' and return unless @token and !@token.expired? redirect_to :controller => 'welcome' and return unless @token and !@token.expired?
@user = @token.user @user = @token.user
if request.post? if request.post?
@user.password, @user.password_confirmation = params[:new_password], params[:new_password_confirmation] @user.password, @user.password_confirmation = params[:new_password], params[:new_password_confirmation]
if @user.save if @user.save
@token.destroy @token.destroy
flash[:notice] = l(:notice_account_password_updated) flash[:notice] = l(:notice_account_password_updated)
redirect_to :action => 'login' redirect_to :action => 'login'
return return
end end
end end
render :template => "account/password_recovery" render :template => "account/password_recovery"
return return
else else
if request.post? if request.post?
user = User.find_by_mail(params[:mail]) user = User.find_by_mail(params[:mail])
# user not found in db # user not found in db
flash.now[:notice] = l(:notice_account_unknown_email) and return unless user flash.now[:notice] = l(:notice_account_unknown_email) and return unless user
# user uses an external authentification # user uses an external authentification
flash.now[:notice] = l(:notice_can_t_change_password) and return if user.auth_source_id flash.now[:notice] = l(:notice_can_t_change_password) and return if user.auth_source_id
# create a new token for password recovery # create a new token for password recovery
token = Token.new(:user => user, :action => "recovery") token = Token.new(:user => user, :action => "recovery")
if token.save if token.save
Mailer.deliver_lost_password(token) Mailer.deliver_lost_password(token)
flash[:notice] = l(:notice_account_lost_email_sent) flash[:notice] = l(:notice_account_lost_email_sent)
redirect_to :action => 'login' redirect_to :action => 'login'
return return
end end
end end
end end
end end
# User self-registration # User self-registration
def register def register
redirect_to :controller => 'welcome' and return unless Setting.self_registration? redirect_to :controller => 'welcome' and return unless Setting.self_registration?
if params[:token] if params[:token]
token = Token.find_by_action_and_value("register", params[:token]) token = Token.find_by_action_and_value("register", params[:token])
redirect_to :controller => 'welcome' and return unless token and !token.expired? redirect_to :controller => 'welcome' and return unless token and !token.expired?
user = token.user user = token.user
redirect_to :controller => 'welcome' and return unless user.status == User::STATUS_REGISTERED redirect_to :controller => 'welcome' and return unless user.status == User::STATUS_REGISTERED
user.status = User::STATUS_ACTIVE user.status = User::STATUS_ACTIVE
if user.save if user.save
token.destroy token.destroy
flash[:notice] = l(:notice_account_activated) flash[:notice] = l(:notice_account_activated)
redirect_to :action => 'login' redirect_to :action => 'login'
return return
end end
else else
if request.get? if request.get?
@user = User.new(:language => Setting.default_language) @user = User.new(:language => Setting.default_language)
@custom_values = UserCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @user) } @custom_values = UserCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @user) }
else else
@user = User.new(params[:user]) @user = User.new(params[:user])
@user.admin = false @user.admin = false
@user.login = params[:user][:login] @user.login = params[:user][:login]
@user.status = User::STATUS_REGISTERED @user.status = User::STATUS_REGISTERED
@user.password, @user.password_confirmation = params[:password], params[:password_confirmation] @user.password, @user.password_confirmation = params[:password], params[:password_confirmation]
@custom_values = UserCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @user, :value => params["custom_fields"][x.id.to_s]) } @custom_values = UserCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @user, :value => params["custom_fields"][x.id.to_s]) }
@user.custom_values = @custom_values @user.custom_values = @custom_values
token = Token.new(:user => @user, :action => "register") token = Token.new(:user => @user, :action => "register")
if @user.save and token.save if @user.save and token.save
Mailer.deliver_register(token) Mailer.deliver_register(token)
flash[:notice] = l(:notice_account_register_done) flash[:notice] = l(:notice_account_register_done)
redirect_to :controller => 'welcome' and return redirect_to :controller => 'welcome' and return
end end
end end
end end
end end
end end

View File

@ -1,56 +1,56 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class AdminController < ApplicationController class AdminController < ApplicationController
layout 'base' layout 'base'
before_filter :require_admin before_filter :require_admin
helper :sort helper :sort
include SortHelper include SortHelper
def index def index
end end
def projects def projects
sort_init 'name', 'asc' sort_init 'name', 'asc'
sort_update sort_update
@project_count = Project.count @project_count = Project.count
@project_pages = Paginator.new self, @project_count, @project_pages = Paginator.new self, @project_count,
15, 15,
params['page'] params['page']
@projects = Project.find :all, :order => sort_clause, @projects = Project.find :all, :order => sort_clause,
:limit => @project_pages.items_per_page, :limit => @project_pages.items_per_page,
:offset => @project_pages.current.offset :offset => @project_pages.current.offset
render :action => "projects", :layout => false if request.xhr? render :action => "projects", :layout => false if request.xhr?
end end
def mail_options def mail_options
@actions = Permission.find(:all, :conditions => ["mail_option=?", true]) || [] @actions = Permission.find(:all, :conditions => ["mail_option=?", true]) || []
if request.post? if request.post?
@actions.each { |a| @actions.each { |a|
a.mail_enabled = (params[:action_ids] || []).include? a.id.to_s a.mail_enabled = (params[:action_ids] || []).include? a.id.to_s
a.save a.save
} }
flash.now[:notice] = l(:notice_successful_update) flash.now[:notice] = l(:notice_successful_update)
end end
end end
def info def info
@db_adapter_name = ActiveRecord::Base.connection.adapter_name @db_adapter_name = ActiveRecord::Base.connection.adapter_name
end end
end end

View File

@ -1,109 +1,109 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang # Copyright (C) 2006-2007 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class ApplicationController < ActionController::Base class ApplicationController < ActionController::Base
before_filter :check_if_login_required, :set_localization before_filter :check_if_login_required, :set_localization
filter_parameter_logging :password filter_parameter_logging :password
def logged_in_user=(user) def logged_in_user=(user)
@logged_in_user = user @logged_in_user = user
session[:user_id] = (user ? user.id : nil) session[:user_id] = (user ? user.id : nil)
end end
def logged_in_user def logged_in_user
if session[:user_id] if session[:user_id]
@logged_in_user ||= User.find(session[:user_id]) @logged_in_user ||= User.find(session[:user_id])
else else
nil nil
end end
end end
def logged_in_user_membership def logged_in_user_membership
@user_membership ||= Member.find(:first, :conditions => ["user_id=? and project_id=?", self.logged_in_user.id, @project.id]) @user_membership ||= Member.find(:first, :conditions => ["user_id=? and project_id=?", self.logged_in_user.id, @project.id])
end end
# check if login is globally required to access the application # check if login is globally required to access the application
def check_if_login_required def check_if_login_required
require_login if Setting.login_required? require_login if Setting.login_required?
end end
def set_localization def set_localization
lang = begin lang = begin
if self.logged_in_user and self.logged_in_user.language and !self.logged_in_user.language.empty? and GLoc.valid_languages.include? self.logged_in_user.language.to_sym if self.logged_in_user and self.logged_in_user.language and !self.logged_in_user.language.empty? and GLoc.valid_languages.include? self.logged_in_user.language.to_sym
self.logged_in_user.language self.logged_in_user.language
elsif request.env['HTTP_ACCEPT_LANGUAGE'] elsif request.env['HTTP_ACCEPT_LANGUAGE']
accept_lang = parse_qvalues(request.env['HTTP_ACCEPT_LANGUAGE']).first.split('-').first accept_lang = parse_qvalues(request.env['HTTP_ACCEPT_LANGUAGE']).first.split('-').first
if accept_lang and !accept_lang.empty? and GLoc.valid_languages.include? accept_lang.to_sym if accept_lang and !accept_lang.empty? and GLoc.valid_languages.include? accept_lang.to_sym
accept_lang accept_lang
end end
end end
rescue rescue
nil nil
end || Setting.default_language end || Setting.default_language
set_language_if_valid(lang) set_language_if_valid(lang)
end end
def require_login def require_login
unless self.logged_in_user unless self.logged_in_user
store_location store_location
redirect_to :controller => "account", :action => "login" redirect_to :controller => "account", :action => "login"
return false return false
end end
true true
end end
def require_admin def require_admin
return unless require_login return unless require_login
unless self.logged_in_user.admin? unless self.logged_in_user.admin?
render :nothing => true, :status => 403 render :nothing => true, :status => 403
return false return false
end end
true true
end end
# authorizes the user for the requested action. # authorizes the user for the requested action.
def authorize(ctrl = params[:controller], action = params[:action]) def authorize(ctrl = params[:controller], action = params[:action])
# check if action is allowed on public projects # check if action is allowed on public projects
if @project.is_public? and Permission.allowed_to_public "%s/%s" % [ ctrl, action ] if @project.is_public? and Permission.allowed_to_public "%s/%s" % [ ctrl, action ]
return true return true
end end
# if action is not public, force login # if action is not public, force login
return unless require_login return unless require_login
# admin is always authorized # admin is always authorized
return true if self.logged_in_user.admin? return true if self.logged_in_user.admin?
# if not admin, check membership permission # if not admin, check membership permission
@user_membership ||= Member.find(:first, :conditions => ["user_id=? and project_id=?", self.logged_in_user.id, @project.id]) @user_membership ||= Member.find(:first, :conditions => ["user_id=? and project_id=?", self.logged_in_user.id, @project.id])
if @user_membership and Permission.allowed_to_role( "%s/%s" % [ ctrl, action ], @user_membership.role_id ) if @user_membership and Permission.allowed_to_role( "%s/%s" % [ ctrl, action ], @user_membership.role_id )
return true return true
end end
render :nothing => true, :status => 403 render :nothing => true, :status => 403
false false
end end
# make sure that the user is a member of the project (or admin) if project is private # make sure that the user is a member of the project (or admin) if project is private
# used as a before_filter for actions that do not require any particular permission on the project # used as a before_filter for actions that do not require any particular permission on the project
def check_project_privacy def check_project_privacy
return true if @project.is_public? return true if @project.is_public?
return false unless logged_in_user return false unless logged_in_user
return true if logged_in_user.admin? || logged_in_user_membership return true if logged_in_user.admin? || logged_in_user_membership
render :nothing => true, :status => 403 render :nothing => true, :status => 403
false false
end end
# store current uri in session. # store current uri in session.
# return to this location by calling redirect_back_or_default # return to this location by calling redirect_back_or_default
def store_location def store_location
@ -118,30 +118,30 @@ class ApplicationController < ActionController::Base
redirect_to session[:return_to_params] redirect_to session[:return_to_params]
session[:return_to_params] = nil session[:return_to_params] = nil
end end
end
def render_404
@html_title = "404"
render :template => "common/404", :layout => true, :status => 404
return false
end end
# qvalues http header parser def render_404
# code taken from webrick @html_title = "404"
def parse_qvalues(value) render :template => "common/404", :layout => true, :status => 404
tmp = [] return false
if value end
parts = value.split(/,\s*/)
parts.each {|part| # qvalues http header parser
if m = %r{^([^\s,]+?)(?:;\s*q=(\d+(?:\.\d+)?))?$}.match(part) # code taken from webrick
val = m[1] def parse_qvalues(value)
q = (m[2] or 1).to_f tmp = []
tmp.push([val, q]) if value
end parts = value.split(/,\s*/)
} parts.each {|part|
tmp = tmp.sort_by{|val, q| -q} if m = %r{^([^\s,]+?)(?:;\s*q=(\d+(?:\.\d+)?))?$}.match(part)
tmp.collect!{|val, q| val} val = m[1]
end q = (m[2] or 1).to_f
return tmp tmp.push([val, q])
end end
}
tmp = tmp.sort_by{|val, q| -q}
tmp.collect!{|val, q| val}
end
return tmp
end
end end

View File

@ -1,23 +1,23 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class CustomFieldsController < ApplicationController class CustomFieldsController < ApplicationController
layout 'base' layout 'base'
before_filter :require_admin before_filter :require_admin
def index def index
list list
@ -25,48 +25,48 @@ class CustomFieldsController < ApplicationController
end end
def list def list
@custom_fields_by_type = CustomField.find(:all).group_by {|f| f.type.to_s } @custom_fields_by_type = CustomField.find(:all).group_by {|f| f.type.to_s }
@tab = params[:tab] || 'IssueCustomField' @tab = params[:tab] || 'IssueCustomField'
render :action => "list", :layout => false if request.xhr? render :action => "list", :layout => false if request.xhr?
end end
def new def new
case params[:type] case params[:type]
when "IssueCustomField" when "IssueCustomField"
@custom_field = IssueCustomField.new(params[:custom_field]) @custom_field = IssueCustomField.new(params[:custom_field])
@custom_field.trackers = Tracker.find(params[:tracker_ids]) if params[:tracker_ids] @custom_field.trackers = Tracker.find(params[:tracker_ids]) if params[:tracker_ids]
when "UserCustomField" when "UserCustomField"
@custom_field = UserCustomField.new(params[:custom_field]) @custom_field = UserCustomField.new(params[:custom_field])
when "ProjectCustomField" when "ProjectCustomField"
@custom_field = ProjectCustomField.new(params[:custom_field]) @custom_field = ProjectCustomField.new(params[:custom_field])
else else
redirect_to :action => 'list' redirect_to :action => 'list'
return return
end end
if request.post? and @custom_field.save if request.post? and @custom_field.save
flash[:notice] = l(:notice_successful_create) flash[:notice] = l(:notice_successful_create)
redirect_to :action => 'list', :tab => @custom_field.type redirect_to :action => 'list', :tab => @custom_field.type
end end
@trackers = Tracker.find(:all, :order => 'position') @trackers = Tracker.find(:all, :order => 'position')
end end
def edit def edit
@custom_field = CustomField.find(params[:id]) @custom_field = CustomField.find(params[:id])
if request.post? and @custom_field.update_attributes(params[:custom_field]) if request.post? and @custom_field.update_attributes(params[:custom_field])
if @custom_field.is_a? IssueCustomField if @custom_field.is_a? IssueCustomField
@custom_field.trackers = params[:tracker_ids] ? Tracker.find(params[:tracker_ids]) : [] @custom_field.trackers = params[:tracker_ids] ? Tracker.find(params[:tracker_ids]) : []
end end
flash[:notice] = l(:notice_successful_update) flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'list', :tab => @custom_field.type redirect_to :action => 'list', :tab => @custom_field.type
end end
@trackers = Tracker.find(:all, :order => 'position') @trackers = Tracker.find(:all, :order => 'position')
end end
def destroy def destroy
@custom_field = CustomField.find(params[:id]).destroy @custom_field = CustomField.find(params[:id]).destroy
redirect_to :action => 'list', :tab => @custom_field.type redirect_to :action => 'list', :tab => @custom_field.type
rescue rescue
flash[:notice] = "Unable to delete custom field" flash[:notice] = "Unable to delete custom field"
redirect_to :action => 'list' redirect_to :action => 'list'
end end
end end

View File

@ -1,71 +1,71 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang # Copyright (C) 2006-2007 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class DocumentsController < ApplicationController
layout 'base'
before_filter :find_project, :authorize
def show class DocumentsController < ApplicationController
layout 'base'
before_filter :find_project, :authorize
def show
@attachments = @document.attachments.find(:all, :order => "created_on DESC") @attachments = @document.attachments.find(:all, :order => "created_on DESC")
end end
def edit def edit
@categories = Enumeration::get_values('DCAT') @categories = Enumeration::get_values('DCAT')
if request.post? and @document.update_attributes(params[:document]) if request.post? and @document.update_attributes(params[:document])
flash[:notice] = l(:notice_successful_update) flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'show', :id => @document redirect_to :action => 'show', :id => @document
end end
end end
def destroy def destroy
@document.destroy @document.destroy
redirect_to :controller => 'projects', :action => 'list_documents', :id => @project redirect_to :controller => 'projects', :action => 'list_documents', :id => @project
end
def download
@attachment = @document.attachments.find(params[:attachment_id])
@attachment.increment_download
send_file @attachment.diskfile, :filename => @attachment.filename
rescue
render_404
end
def add_attachment
# Save the attachments
@attachments = []
params[:attachments].each { |file|
next unless file.size > 0
a = Attachment.create(:container => @document, :file => file, :author => logged_in_user)
@attachments << a unless a.new_record?
} if params[:attachments] and params[:attachments].is_a? Array
Mailer.deliver_attachments_add(@attachments) if !@attachments.empty? and Permission.find_by_controller_and_action(params[:controller], params[:action]).mail_enabled?
redirect_to :action => 'show', :id => @document
end
def destroy_attachment
@document.attachments.find(params[:attachment_id]).destroy
redirect_to :action => 'show', :id => @document
end end
private def download
def find_project @attachment = @document.attachments.find(params[:attachment_id])
@document = Document.find(params[:id]) @attachment.increment_download
@project = @document.project send_file @attachment.diskfile, :filename => @attachment.filename
rescue ActiveRecord::RecordNotFound rescue
render_404 render_404
end
def add_attachment
# Save the attachments
@attachments = []
params[:attachments].each { |file|
next unless file.size > 0
a = Attachment.create(:container => @document, :file => file, :author => logged_in_user)
@attachments << a unless a.new_record?
} if params[:attachments] and params[:attachments].is_a? Array
Mailer.deliver_attachments_add(@attachments) if !@attachments.empty? and Permission.find_by_controller_and_action(params[:controller], params[:action]).mail_enabled?
redirect_to :action => 'show', :id => @document
end
def destroy_attachment
@document.attachments.find(params[:attachment_id]).destroy
redirect_to :action => 'show', :id => @document
end
private
def find_project
@document = Document.find(params[:id])
@project = @document.project
rescue ActiveRecord::RecordNotFound
render_404
end end
end end

View File

@ -1,23 +1,23 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class EnumerationsController < ApplicationController class EnumerationsController < ApplicationController
layout 'base' layout 'base'
before_filter :require_admin before_filter :require_admin
def index def index
list list
@ -60,11 +60,11 @@ class EnumerationsController < ApplicationController
end end
def destroy def destroy
Enumeration.find(params[:id]).destroy Enumeration.find(params[:id]).destroy
flash[:notice] = l(:notice_successful_delete) flash[:notice] = l(:notice_successful_delete)
redirect_to :action => 'list' redirect_to :action => 'list'
rescue rescue
flash[:notice] = "Unable to delete enumeration" flash[:notice] = "Unable to delete enumeration"
redirect_to :action => 'list' redirect_to :action => 'list'
end end
end end

View File

@ -1,47 +1,47 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class HelpController < ApplicationController class HelpController < ApplicationController
skip_before_filter :check_if_login_required skip_before_filter :check_if_login_required
before_filter :load_help_config before_filter :load_help_config
# displays help page for the requested controller/action # displays help page for the requested controller/action
def index def index
# select help page to display # select help page to display
if params[:ctrl] and @help_config['pages'][params[:ctrl]] if params[:ctrl] and @help_config['pages'][params[:ctrl]]
if params[:page] and @help_config['pages'][params[:ctrl]][params[:page]] if params[:page] and @help_config['pages'][params[:ctrl]][params[:page]]
template = @help_config['pages'][params[:ctrl]][params[:page]] template = @help_config['pages'][params[:ctrl]][params[:page]]
else else
template = @help_config['pages'][params[:ctrl]]['index'] template = @help_config['pages'][params[:ctrl]]['index']
end end
end end
# choose language according to available help translations # choose language according to available help translations
lang = (@help_config['langs'].include? current_language.to_s) ? current_language.to_s : @help_config['langs'].first lang = (@help_config['langs'].include? current_language.to_s) ? current_language.to_s : @help_config['langs'].first
if template if template
redirect_to "/manual/#{lang}/#{template}" redirect_to "/manual/#{lang}/#{template}"
else else
redirect_to "/manual/#{lang}/index.html" redirect_to "/manual/#{lang}/index.html"
end end
end end
private private
def load_help_config def load_help_config
@help_config = YAML::load(File.open("#{RAILS_ROOT}/config/help.yml")) @help_config = YAML::load(File.open("#{RAILS_ROOT}/config/help.yml"))
end end
end end

View File

@ -1,24 +1,24 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class IssueCategoriesController < ApplicationController class IssueCategoriesController < ApplicationController
layout 'base' layout 'base'
before_filter :find_project, :authorize before_filter :find_project, :authorize
def edit def edit
if request.post? and @category.update_attributes(params[:category]) if request.post? and @category.update_attributes(params[:category])
flash[:notice] = l(:notice_successful_update) flash[:notice] = l(:notice_successful_update)
@ -28,17 +28,17 @@ class IssueCategoriesController < ApplicationController
def destroy def destroy
@category.destroy @category.destroy
redirect_to :controller => 'projects', :action => 'settings', :tab => 'categories', :id => @project redirect_to :controller => 'projects', :action => 'settings', :tab => 'categories', :id => @project
rescue rescue
flash[:notice] = "Categorie can't be deleted" flash[:notice] = "Categorie can't be deleted"
redirect_to :controller => 'projects', :action => 'settings', :tab => 'categories', :id => @project redirect_to :controller => 'projects', :action => 'settings', :tab => 'categories', :id => @project
end end
private private
def find_project def find_project
@category = IssueCategory.find(params[:id]) @category = IssueCategory.find(params[:id])
@project = @category.project @project = @category.project
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
render_404 render_404
end end
end end

View File

@ -1,34 +1,34 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class IssueStatusesController < ApplicationController class IssueStatusesController < ApplicationController
layout 'base' layout 'base'
before_filter :require_admin before_filter :require_admin
verify :method => :post, :only => [ :destroy, :create, :update, :move ], verify :method => :post, :only => [ :destroy, :create, :update, :move ],
:redirect_to => { :action => :list } :redirect_to => { :action => :list }
def index def index
list list
render :action => 'list' unless request.xhr? render :action => 'list' unless request.xhr?
end end
def list def list
@issue_status_pages, @issue_statuses = paginate :issue_statuses, :per_page => 25, :order => "position" @issue_status_pages, @issue_statuses = paginate :issue_statuses, :per_page => 25, :order => "position"
render :action => "list", :layout => false if request.xhr? render :action => "list", :layout => false if request.xhr?
end end
@ -58,28 +58,28 @@ class IssueStatusesController < ApplicationController
else else
render :action => 'edit' render :action => 'edit'
end end
end end
def move def move
@issue_status = IssueStatus.find(params[:id]) @issue_status = IssueStatus.find(params[:id])
case params[:position] case params[:position]
when 'highest' when 'highest'
@issue_status.move_to_top @issue_status.move_to_top
when 'higher' when 'higher'
@issue_status.move_higher @issue_status.move_higher
when 'lower' when 'lower'
@issue_status.move_lower @issue_status.move_lower
when 'lowest' when 'lowest'
@issue_status.move_to_bottom @issue_status.move_to_bottom
end if params[:position] end if params[:position]
redirect_to :action => 'list' redirect_to :action => 'list'
end end
def destroy def destroy
IssueStatus.find(params[:id]).destroy IssueStatus.find(params[:id]).destroy
redirect_to :action => 'list' redirect_to :action => 'list'
rescue rescue
flash[:notice] = "Unable to delete issue status" flash[:notice] = "Unable to delete issue status"
redirect_to :action => 'list' redirect_to :action => 'list'
end end
end end

View File

@ -1,149 +1,149 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang # Copyright (C) 2006-2007 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class IssuesController < ApplicationController class IssuesController < ApplicationController
layout 'base', :except => :export_pdf layout 'base', :except => :export_pdf
before_filter :find_project, :authorize before_filter :find_project, :authorize
helper :custom_fields helper :custom_fields
include CustomFieldsHelper include CustomFieldsHelper
helper :ifpdf helper :ifpdf
include IfpdfHelper include IfpdfHelper
def show def show
@status_options = @issue.status.workflows.find(:all, :order => 'position', :include => :new_status, :conditions => ["role_id=? and tracker_id=?", self.logged_in_user.role_for_project(@project.id), @issue.tracker.id]).collect{ |w| w.new_status } if self.logged_in_user @status_options = @issue.status.workflows.find(:all, :order => 'position', :include => :new_status, :conditions => ["role_id=? and tracker_id=?", self.logged_in_user.role_for_project(@project.id), @issue.tracker.id]).collect{ |w| w.new_status } if self.logged_in_user
@custom_values = @issue.custom_values.find(:all, :include => :custom_field) @custom_values = @issue.custom_values.find(:all, :include => :custom_field)
@journals_count = @issue.journals.count @journals_count = @issue.journals.count
@journals = @issue.journals.find(:all, :include => [:user, :details], :limit => 15, :order => "journals.created_on desc") @journals = @issue.journals.find(:all, :include => [:user, :details], :limit => 15, :order => "journals.created_on desc")
end end
def history def history
@journals = @issue.journals.find(:all, :include => [:user, :details], :order => "journals.created_on desc") @journals = @issue.journals.find(:all, :include => [:user, :details], :order => "journals.created_on desc")
@journals_count = @journals.length @journals_count = @journals.length
end end
def export_pdf def export_pdf
@custom_values = @issue.custom_values.find(:all, :include => :custom_field) @custom_values = @issue.custom_values.find(:all, :include => :custom_field)
@options_for_rfpdf ||= {} @options_for_rfpdf ||= {}
@options_for_rfpdf[:file_name] = "#{@project.name}_#{@issue.long_id}.pdf" @options_for_rfpdf[:file_name] = "#{@project.name}_#{@issue.long_id}.pdf"
end end
def edit def edit
@priorities = Enumeration::get_values('IPRI') @priorities = Enumeration::get_values('IPRI')
if request.get? if request.get?
@custom_values = @project.custom_fields_for_issues(@issue.tracker).collect { |x| @issue.custom_values.find_by_custom_field_id(x.id) || CustomValue.new(:custom_field => x, :customized => @issue) } @custom_values = @project.custom_fields_for_issues(@issue.tracker).collect { |x| @issue.custom_values.find_by_custom_field_id(x.id) || CustomValue.new(:custom_field => x, :customized => @issue) }
else else
begin begin
@issue.init_journal(self.logged_in_user) @issue.init_journal(self.logged_in_user)
# Retrieve custom fields and values # Retrieve custom fields and values
@custom_values = @project.custom_fields_for_issues(@issue.tracker).collect { |x| CustomValue.new(:custom_field => x, :customized => @issue, :value => params["custom_fields"][x.id.to_s]) } @custom_values = @project.custom_fields_for_issues(@issue.tracker).collect { |x| CustomValue.new(:custom_field => x, :customized => @issue, :value => params["custom_fields"][x.id.to_s]) }
@issue.custom_values = @custom_values @issue.custom_values = @custom_values
@issue.attributes = params[:issue] @issue.attributes = params[:issue]
if @issue.save if @issue.save
flash[:notice] = l(:notice_successful_update) flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'show', :id => @issue redirect_to :action => 'show', :id => @issue
end end
rescue ActiveRecord::StaleObjectError rescue ActiveRecord::StaleObjectError
# Optimistic locking exception # Optimistic locking exception
flash[:notice] = l(:notice_locking_conflict) flash[:notice] = l(:notice_locking_conflict)
end end
end end
end end
def add_note def add_note
unless params[:notes].empty? unless params[:notes].empty?
journal = @issue.init_journal(self.logged_in_user, params[:notes]) journal = @issue.init_journal(self.logged_in_user, params[:notes])
#@history = @issue.histories.build(params[:history]) #@history = @issue.histories.build(params[:history])
#@history.author_id = self.logged_in_user.id if self.logged_in_user #@history.author_id = self.logged_in_user.id if self.logged_in_user
#@history.status = @issue.status #@history.status = @issue.status
if @issue.save if @issue.save
flash[:notice] = l(:notice_successful_update) flash[:notice] = l(:notice_successful_update)
Mailer.deliver_issue_edit(journal) if Permission.find_by_controller_and_action(params[:controller], params[:action]).mail_enabled? Mailer.deliver_issue_edit(journal) if Permission.find_by_controller_and_action(params[:controller], params[:action]).mail_enabled?
redirect_to :action => 'show', :id => @issue redirect_to :action => 'show', :id => @issue
return return
end end
end end
show show
render :action => 'show' render :action => 'show'
end end
def change_status def change_status
#@history = @issue.histories.build(params[:history]) #@history = @issue.histories.build(params[:history])
@status_options = @issue.status.workflows.find(:all, :order => 'position', :include => :new_status, :conditions => ["role_id=? and tracker_id=?", self.logged_in_user.role_for_project(@project.id), @issue.tracker.id]).collect{ |w| w.new_status } if self.logged_in_user @status_options = @issue.status.workflows.find(:all, :order => 'position', :include => :new_status, :conditions => ["role_id=? and tracker_id=?", self.logged_in_user.role_for_project(@project.id), @issue.tracker.id]).collect{ |w| w.new_status } if self.logged_in_user
@new_status = IssueStatus.find(params[:new_status_id]) @new_status = IssueStatus.find(params[:new_status_id])
if params[:confirm] if params[:confirm]
begin begin
#@history.author_id = self.logged_in_user.id if self.logged_in_user #@history.author_id = self.logged_in_user.id if self.logged_in_user
#@issue.status = @history.status #@issue.status = @history.status
#@issue.fixed_version_id = (params[:issue][:fixed_version_id]) #@issue.fixed_version_id = (params[:issue][:fixed_version_id])
#@issue.assigned_to_id = (params[:issue][:assigned_to_id]) #@issue.assigned_to_id = (params[:issue][:assigned_to_id])
#@issue.done_ratio = (params[:issue][:done_ratio]) #@issue.done_ratio = (params[:issue][:done_ratio])
#@issue.lock_version = (params[:issue][:lock_version]) #@issue.lock_version = (params[:issue][:lock_version])
journal = @issue.init_journal(self.logged_in_user, params[:notes]) journal = @issue.init_journal(self.logged_in_user, params[:notes])
@issue.status = @new_status @issue.status = @new_status
if @issue.update_attributes(params[:issue]) if @issue.update_attributes(params[:issue])
flash[:notice] = l(:notice_successful_update) flash[:notice] = l(:notice_successful_update)
Mailer.deliver_issue_edit(journal) if Permission.find_by_controller_and_action(params[:controller], params[:action]).mail_enabled? Mailer.deliver_issue_edit(journal) if Permission.find_by_controller_and_action(params[:controller], params[:action]).mail_enabled?
redirect_to :action => 'show', :id => @issue redirect_to :action => 'show', :id => @issue
end end
rescue ActiveRecord::StaleObjectError rescue ActiveRecord::StaleObjectError
# Optimistic locking exception # Optimistic locking exception
flash[:notice] = l(:notice_locking_conflict) flash[:notice] = l(:notice_locking_conflict)
end end
end end
@assignable_to = @project.members.find(:all, :include => :user).collect{ |m| m.user } @assignable_to = @project.members.find(:all, :include => :user).collect{ |m| m.user }
end end
def destroy def destroy
@issue.destroy @issue.destroy
redirect_to :controller => 'projects', :action => 'list_issues', :id => @project redirect_to :controller => 'projects', :action => 'list_issues', :id => @project
end end
def add_attachment def add_attachment
# Save the attachments # Save the attachments
@attachments = [] @attachments = []
params[:attachments].each { |file| params[:attachments].each { |file|
next unless file.size > 0 next unless file.size > 0
a = Attachment.create(:container => @issue, :file => file, :author => logged_in_user) a = Attachment.create(:container => @issue, :file => file, :author => logged_in_user)
@attachments << a unless a.new_record? @attachments << a unless a.new_record?
} if params[:attachments] and params[:attachments].is_a? Array } if params[:attachments] and params[:attachments].is_a? Array
Mailer.deliver_attachments_add(@attachments) if !@attachments.empty? and Permission.find_by_controller_and_action(params[:controller], params[:action]).mail_enabled? Mailer.deliver_attachments_add(@attachments) if !@attachments.empty? and Permission.find_by_controller_and_action(params[:controller], params[:action]).mail_enabled?
redirect_to :action => 'show', :id => @issue redirect_to :action => 'show', :id => @issue
end end
def destroy_attachment def destroy_attachment
@issue.attachments.find(params[:attachment_id]).destroy @issue.attachments.find(params[:attachment_id]).destroy
redirect_to :action => 'show', :id => @issue redirect_to :action => 'show', :id => @issue
end end
# Send the file in stream mode # Send the file in stream mode
def download def download
@attachment = @issue.attachments.find(params[:attachment_id]) @attachment = @issue.attachments.find(params[:attachment_id])
send_file @attachment.diskfile, :filename => @attachment.filename send_file @attachment.diskfile, :filename => @attachment.filename
rescue rescue
render_404 render_404
end end
private private
def find_project def find_project
@issue = Issue.find(params[:id], :include => [:project, :tracker, :status, :author, :priority, :category]) @issue = Issue.find(params[:id], :include => [:project, :tracker, :status, :author, :priority, :category])
@project = @issue.project @project = @issue.project
@html_title = "#{@project.name} - #{@issue.tracker.name} ##{@issue.id}" @html_title = "#{@project.name} - #{@issue.tracker.name} ##{@issue.id}"
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
render_404 render_404
end end
end end

View File

@ -1,42 +1,42 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class MembersController < ApplicationController class MembersController < ApplicationController
layout 'base' layout 'base'
before_filter :find_project, :authorize before_filter :find_project, :authorize
def edit def edit
if request.post? and @member.update_attributes(params[:member]) if request.post? and @member.update_attributes(params[:member])
flash[:notice] = l(:notice_successful_update) flash[:notice] = l(:notice_successful_update)
redirect_to :controller => 'projects', :action => 'settings', :tab => 'members', :id => @project redirect_to :controller => 'projects', :action => 'settings', :tab => 'members', :id => @project
end end
end end
def destroy def destroy
@member.destroy @member.destroy
flash[:notice] = l(:notice_successful_delete) flash[:notice] = l(:notice_successful_delete)
redirect_to :controller => 'projects', :action => 'settings', :tab => 'members', :id => @project redirect_to :controller => 'projects', :action => 'settings', :tab => 'members', :id => @project
end end
private private
def find_project def find_project
@member = Member.find(params[:id]) @member = Member.find(params[:id])
@project = @member.project @project = @member.project
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
render_404 render_404
end end
end end

View File

@ -1,23 +1,23 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class NewsController < ApplicationController class NewsController < ApplicationController
layout 'base' layout 'base'
before_filter :find_project, :authorize before_filter :find_project, :authorize
def show def show
end end
@ -27,34 +27,34 @@ class NewsController < ApplicationController
flash[:notice] = l(:notice_successful_update) flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'show', :id => @news redirect_to :action => 'show', :id => @news
end end
end
def add_comment
@comment = Comment.new(params[:comment])
@comment.author = logged_in_user
if @news.comments << @comment
flash[:notice] = l(:label_comment_added)
redirect_to :action => 'show', :id => @news
else
render :action => 'show'
end
end end
def destroy_comment def add_comment
@news.comments.find(params[:comment_id]).destroy @comment = Comment.new(params[:comment])
redirect_to :action => 'show', :id => @news @comment.author = logged_in_user
end if @news.comments << @comment
flash[:notice] = l(:label_comment_added)
redirect_to :action => 'show', :id => @news
else
render :action => 'show'
end
end
def destroy_comment
@news.comments.find(params[:comment_id]).destroy
redirect_to :action => 'show', :id => @news
end
def destroy def destroy
@news.destroy @news.destroy
redirect_to :controller => 'projects', :action => 'list_news', :id => @project redirect_to :controller => 'projects', :action => 'list_news', :id => @project
end end
private private
def find_project def find_project
@news = News.find(params[:id]) @news = News.find(params[:id])
@project = @news.project @project = @news.project
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
render_404 render_404
end end
end end

File diff suppressed because it is too large Load Diff

View File

@ -1,167 +1,167 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class ReportsController < ApplicationController class ReportsController < ApplicationController
layout 'base' layout 'base'
before_filter :find_project, :authorize before_filter :find_project, :authorize
def issue_report def issue_report
@statuses = IssueStatus.find(:all, :order => 'position') @statuses = IssueStatus.find(:all, :order => 'position')
case params[:detail] case params[:detail]
when "tracker" when "tracker"
@field = "tracker_id" @field = "tracker_id"
@rows = Tracker.find :all, :order => 'position' @rows = Tracker.find :all, :order => 'position'
@data = issues_by_tracker @data = issues_by_tracker
@report_title = l(:field_tracker) @report_title = l(:field_tracker)
render :template => "reports/issue_report_details" render :template => "reports/issue_report_details"
when "priority" when "priority"
@field = "priority_id" @field = "priority_id"
@rows = Enumeration::get_values('IPRI') @rows = Enumeration::get_values('IPRI')
@data = issues_by_priority @data = issues_by_priority
@report_title = l(:field_priority) @report_title = l(:field_priority)
render :template => "reports/issue_report_details" render :template => "reports/issue_report_details"
when "category" when "category"
@field = "category_id" @field = "category_id"
@rows = @project.issue_categories @rows = @project.issue_categories
@data = issues_by_category @data = issues_by_category
@report_title = l(:field_category) @report_title = l(:field_category)
render :template => "reports/issue_report_details" render :template => "reports/issue_report_details"
when "author" when "author"
@field = "author_id" @field = "author_id"
@rows = @project.members.collect { |m| m.user } @rows = @project.members.collect { |m| m.user }
@data = issues_by_author @data = issues_by_author
@report_title = l(:field_author) @report_title = l(:field_author)
render :template => "reports/issue_report_details" render :template => "reports/issue_report_details"
else else
@queries = @project.queries.find :all, :conditions => ["is_public=? or user_id=?", true, (logged_in_user ? logged_in_user.id : 0)] @queries = @project.queries.find :all, :conditions => ["is_public=? or user_id=?", true, (logged_in_user ? logged_in_user.id : 0)]
@trackers = Tracker.find(:all, :order => 'position') @trackers = Tracker.find(:all, :order => 'position')
@priorities = Enumeration::get_values('IPRI') @priorities = Enumeration::get_values('IPRI')
@categories = @project.issue_categories @categories = @project.issue_categories
@authors = @project.members.collect { |m| m.user } @authors = @project.members.collect { |m| m.user }
issues_by_tracker issues_by_tracker
issues_by_priority issues_by_priority
issues_by_category issues_by_category
issues_by_author issues_by_author
render :template => "reports/issue_report" render :template => "reports/issue_report"
end end
end end
def delays def delays
@trackers = Tracker.find(:all) @trackers = Tracker.find(:all)
if request.get? if request.get?
@selected_tracker_ids = @trackers.collect {|t| t.id.to_s } @selected_tracker_ids = @trackers.collect {|t| t.id.to_s }
else else
@selected_tracker_ids = params[:tracker_ids].collect { |id| id.to_i.to_s } if params[:tracker_ids] and params[:tracker_ids].is_a? Array @selected_tracker_ids = params[:tracker_ids].collect { |id| id.to_i.to_s } if params[:tracker_ids] and params[:tracker_ids].is_a? Array
end end
@selected_tracker_ids ||= [] @selected_tracker_ids ||= []
@raw = @raw =
ActiveRecord::Base.connection.select_all("SELECT datediff( a.created_on, b.created_on ) as delay, count(a.id) as total ActiveRecord::Base.connection.select_all("SELECT datediff( a.created_on, b.created_on ) as delay, count(a.id) as total
FROM issue_histories a, issue_histories b, issues i FROM issue_histories a, issue_histories b, issues i
WHERE a.status_id =5 WHERE a.status_id =5
AND a.issue_id = b.issue_id AND a.issue_id = b.issue_id
AND a.issue_id = i.id AND a.issue_id = i.id
AND i.tracker_id in (#{@selected_tracker_ids.join(',')}) AND i.tracker_id in (#{@selected_tracker_ids.join(',')})
AND b.id = ( AND b.id = (
SELECT min( c.id ) SELECT min( c.id )
FROM issue_histories c FROM issue_histories c
WHERE b.issue_id = c.issue_id ) WHERE b.issue_id = c.issue_id )
GROUP BY delay") unless @selected_tracker_ids.empty? GROUP BY delay") unless @selected_tracker_ids.empty?
@raw ||=[] @raw ||=[]
@x_from = 0 @x_from = 0
@x_to = 0 @x_to = 0
@y_from = 0 @y_from = 0
@y_to = 0 @y_to = 0
@sum_total = 0 @sum_total = 0
@sum_delay = 0 @sum_delay = 0
@raw.each do |r| @raw.each do |r|
@x_to = [r['delay'].to_i, @x_to].max @x_to = [r['delay'].to_i, @x_to].max
@y_to = [r['total'].to_i, @y_to].max @y_to = [r['total'].to_i, @y_to].max
@sum_total = @sum_total + r['total'].to_i @sum_total = @sum_total + r['total'].to_i
@sum_delay = @sum_delay + r['total'].to_i * r['delay'].to_i @sum_delay = @sum_delay + r['total'].to_i * r['delay'].to_i
end end
end end
private private
# Find project of id params[:id] # Find project of id params[:id]
def find_project def find_project
@project = Project.find(params[:id]) @project = Project.find(params[:id])
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
render_404 render_404
end end
def issues_by_tracker def issues_by_tracker
@issues_by_tracker ||= @issues_by_tracker ||=
ActiveRecord::Base.connection.select_all("select s.id as status_id, ActiveRecord::Base.connection.select_all("select s.id as status_id,
s.is_closed as closed, s.is_closed as closed,
t.id as tracker_id, t.id as tracker_id,
count(i.id) as total count(i.id) as total
from from
issues i, issue_statuses s, trackers t issues i, issue_statuses s, trackers t
where where
i.status_id=s.id i.status_id=s.id
and i.tracker_id=t.id and i.tracker_id=t.id
and i.project_id=#{@project.id} and i.project_id=#{@project.id}
group by s.id, s.is_closed, t.id") group by s.id, s.is_closed, t.id")
end end
def issues_by_priority def issues_by_priority
@issues_by_priority ||= @issues_by_priority ||=
ActiveRecord::Base.connection.select_all("select s.id as status_id, ActiveRecord::Base.connection.select_all("select s.id as status_id,
s.is_closed as closed, s.is_closed as closed,
p.id as priority_id, p.id as priority_id,
count(i.id) as total count(i.id) as total
from from
issues i, issue_statuses s, enumerations p issues i, issue_statuses s, enumerations p
where where
i.status_id=s.id i.status_id=s.id
and i.priority_id=p.id and i.priority_id=p.id
and i.project_id=#{@project.id} and i.project_id=#{@project.id}
group by s.id, s.is_closed, p.id") group by s.id, s.is_closed, p.id")
end end
def issues_by_category def issues_by_category
@issues_by_category ||= @issues_by_category ||=
ActiveRecord::Base.connection.select_all("select s.id as status_id, ActiveRecord::Base.connection.select_all("select s.id as status_id,
s.is_closed as closed, s.is_closed as closed,
c.id as category_id, c.id as category_id,
count(i.id) as total count(i.id) as total
from from
issues i, issue_statuses s, issue_categories c issues i, issue_statuses s, issue_categories c
where where
i.status_id=s.id i.status_id=s.id
and i.category_id=c.id and i.category_id=c.id
and i.project_id=#{@project.id} and i.project_id=#{@project.id}
group by s.id, s.is_closed, c.id") group by s.id, s.is_closed, c.id")
end end
def issues_by_author def issues_by_author
@issues_by_author ||= @issues_by_author ||=
ActiveRecord::Base.connection.select_all("select s.id as status_id, ActiveRecord::Base.connection.select_all("select s.id as status_id,
s.is_closed as closed, s.is_closed as closed,
a.id as author_id, a.id as author_id,
count(i.id) as total count(i.id) as total
from from
issues i, issue_statuses s, users a issues i, issue_statuses s, users a
where where
i.status_id=s.id i.status_id=s.id
and i.author_id=a.id and i.author_id=a.id
and i.project_id=#{@project.id} and i.project_id=#{@project.id}
group by s.id, s.is_closed, a.id") group by s.id, s.is_closed, a.id")
end end
end end

View File

@ -1,26 +1,26 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class RolesController < ApplicationController class RolesController < ApplicationController
layout 'base' layout 'base'
before_filter :require_admin before_filter :require_admin
verify :method => :post, :only => [ :destroy, :move ], verify :method => :post, :only => [ :destroy, :move ],
:redirect_to => { :action => :list } :redirect_to => { :action => :list }
def index def index
list list
@ -28,26 +28,26 @@ class RolesController < ApplicationController
end end
def list def list
@role_pages, @roles = paginate :roles, :per_page => 10, :order => "position" @role_pages, @roles = paginate :roles, :per_page => 10, :order => "position"
render :action => "list", :layout => false if request.xhr? render :action => "list", :layout => false if request.xhr?
end end
def new def new
@role = Role.new(params[:role]) @role = Role.new(params[:role])
if request.post? if request.post?
@role.permissions = Permission.find(params[:permission_ids]) if params[:permission_ids] @role.permissions = Permission.find(params[:permission_ids]) if params[:permission_ids]
if @role.save if @role.save
flash[:notice] = l(:notice_successful_create) flash[:notice] = l(:notice_successful_create)
redirect_to :action => 'list' redirect_to :action => 'list'
end end
end end
@permissions = Permission.find(:all, :conditions => ["is_public=?", false], :order => 'sort ASC') @permissions = Permission.find(:all, :conditions => ["is_public=?", false], :order => 'sort ASC')
end end
def edit def edit
@role = Role.find(params[:id]) @role = Role.find(params[:id])
if request.post? and @role.update_attributes(params[:role]) if request.post? and @role.update_attributes(params[:role])
@role.permissions = Permission.find(params[:permission_ids] || []) @role.permissions = Permission.find(params[:permission_ids] || [])
Permission.allowed_to_role_expired Permission.allowed_to_role_expired
flash[:notice] = l(:notice_successful_update) flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'list' redirect_to :action => 'list'
@ -56,47 +56,47 @@ class RolesController < ApplicationController
end end
def destroy def destroy
@role = Role.find(params[:id]) @role = Role.find(params[:id])
unless @role.members.empty? unless @role.members.empty?
flash[:notice] = 'Some members have this role. Can\'t delete it.' flash[:notice] = 'Some members have this role. Can\'t delete it.'
else else
@role.destroy @role.destroy
end end
redirect_to :action => 'list' redirect_to :action => 'list'
end end
def move def move
@role = Role.find(params[:id]) @role = Role.find(params[:id])
case params[:position] case params[:position]
when 'highest' when 'highest'
@role.move_to_top @role.move_to_top
when 'higher' when 'higher'
@role.move_higher @role.move_higher
when 'lower' when 'lower'
@role.move_lower @role.move_lower
when 'lowest' when 'lowest'
@role.move_to_bottom @role.move_to_bottom
end if params[:position] end if params[:position]
redirect_to :action => 'list' redirect_to :action => 'list'
end end
def workflow def workflow
@role = Role.find_by_id(params[:role_id]) @role = Role.find_by_id(params[:role_id])
@tracker = Tracker.find_by_id(params[:tracker_id]) @tracker = Tracker.find_by_id(params[:tracker_id])
if request.post? if request.post?
Workflow.destroy_all( ["role_id=? and tracker_id=?", @role.id, @tracker.id]) Workflow.destroy_all( ["role_id=? and tracker_id=?", @role.id, @tracker.id])
(params[:issue_status] || []).each { |old, news| (params[:issue_status] || []).each { |old, news|
news.each { |new| news.each { |new|
@role.workflows.build(:tracker_id => @tracker.id, :old_status_id => old, :new_status_id => new) @role.workflows.build(:tracker_id => @tracker.id, :old_status_id => old, :new_status_id => new)
} }
} }
if @role.save if @role.save
flash[:notice] = l(:notice_successful_update) flash[:notice] = l(:notice_successful_update)
end end
end end
@roles = Role.find(:all, :order => 'position') @roles = Role.find(:all, :order => 'position')
@trackers = Tracker.find(:all, :order => 'position') @trackers = Tracker.find(:all, :order => 'position')
@statuses = IssueStatus.find(:all, :include => :workflows, :order => 'position') @statuses = IssueStatus.find(:all, :include => :workflows, :order => 'position')
end end
end end

View File

@ -1,23 +1,23 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class TrackersController < ApplicationController class TrackersController < ApplicationController
layout 'base' layout 'base'
before_filter :require_admin before_filter :require_admin
def index def index
list list
@ -28,7 +28,7 @@ class TrackersController < ApplicationController
verify :method => :post, :only => [ :destroy, :move ], :redirect_to => { :action => :list } verify :method => :post, :only => [ :destroy, :move ], :redirect_to => { :action => :list }
def list def list
@tracker_pages, @trackers = paginate :trackers, :per_page => 10, :order => 'position' @tracker_pages, @trackers = paginate :trackers, :per_page => 10, :order => 'position'
render :action => "list", :layout => false if request.xhr? render :action => "list", :layout => false if request.xhr?
end end
@ -47,28 +47,28 @@ class TrackersController < ApplicationController
redirect_to :action => 'list' redirect_to :action => 'list'
end end
end end
def move def move
@tracker = Tracker.find(params[:id]) @tracker = Tracker.find(params[:id])
case params[:position] case params[:position]
when 'highest' when 'highest'
@tracker.move_to_top @tracker.move_to_top
when 'higher' when 'higher'
@tracker.move_higher @tracker.move_higher
when 'lower' when 'lower'
@tracker.move_lower @tracker.move_lower
when 'lowest' when 'lowest'
@tracker.move_to_bottom @tracker.move_to_bottom
end if params[:position] end if params[:position]
redirect_to :action => 'list' redirect_to :action => 'list'
end end
def destroy def destroy
@tracker = Tracker.find(params[:id]) @tracker = Tracker.find(params[:id])
unless @tracker.issues.empty? unless @tracker.issues.empty?
flash[:notice] = "This tracker contains issues and can\'t be deleted." flash[:notice] = "This tracker contains issues and can\'t be deleted."
else else
@tracker.destroy @tracker.destroy
end end
redirect_to :action => 'list' redirect_to :action => 'list'
end end

View File

@ -1,113 +1,113 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang # Copyright (C) 2006-2007 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class UsersController < ApplicationController class UsersController < ApplicationController
layout 'base' layout 'base'
before_filter :require_admin before_filter :require_admin
helper :sort helper :sort
include SortHelper include SortHelper
helper :custom_fields helper :custom_fields
include CustomFieldsHelper include CustomFieldsHelper
def index def index
list list
render :action => 'list' unless request.xhr? render :action => 'list' unless request.xhr?
end end
def list def list
sort_init 'login', 'asc' sort_init 'login', 'asc'
sort_update sort_update
@user_count = User.count @user_count = User.count
@user_pages = Paginator.new self, @user_count, @user_pages = Paginator.new self, @user_count,
15, 15,
params['page'] params['page']
@users = User.find :all,:order => sort_clause, @users = User.find :all,:order => sort_clause,
:limit => @user_pages.items_per_page, :limit => @user_pages.items_per_page,
:offset => @user_pages.current.offset :offset => @user_pages.current.offset
render :action => "list", :layout => false if request.xhr? render :action => "list", :layout => false if request.xhr?
end end
def add def add
if request.get? if request.get?
@user = User.new(:language => Setting.default_language) @user = User.new(:language => Setting.default_language)
@custom_values = UserCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @user) } @custom_values = UserCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @user) }
else else
@user = User.new(params[:user]) @user = User.new(params[:user])
@user.admin = params[:user][:admin] || false @user.admin = params[:user][:admin] || false
@user.login = params[:user][:login] @user.login = params[:user][:login]
@user.password, @user.password_confirmation = params[:password], params[:password_confirmation] unless @user.auth_source_id @user.password, @user.password_confirmation = params[:password], params[:password_confirmation] unless @user.auth_source_id
@custom_values = UserCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @user, :value => params["custom_fields"][x.id.to_s]) } @custom_values = UserCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @user, :value => params["custom_fields"][x.id.to_s]) }
@user.custom_values = @custom_values @user.custom_values = @custom_values
if @user.save if @user.save
flash[:notice] = l(:notice_successful_create) flash[:notice] = l(:notice_successful_create)
redirect_to :action => 'list' redirect_to :action => 'list'
end end
end end
@auth_sources = AuthSource.find(:all) @auth_sources = AuthSource.find(:all)
end end
def edit def edit
@user = User.find(params[:id]) @user = User.find(params[:id])
if request.get? if request.get?
@custom_values = UserCustomField.find(:all).collect { |x| @user.custom_values.find_by_custom_field_id(x.id) || CustomValue.new(:custom_field => x) } @custom_values = UserCustomField.find(:all).collect { |x| @user.custom_values.find_by_custom_field_id(x.id) || CustomValue.new(:custom_field => x) }
else else
@user.admin = params[:user][:admin] if params[:user][:admin] @user.admin = params[:user][:admin] if params[:user][:admin]
@user.login = params[:user][:login] if params[:user][:login] @user.login = params[:user][:login] if params[:user][:login]
@user.password, @user.password_confirmation = params[:password], params[:password_confirmation] unless params[:password].nil? or params[:password].empty? or @user.auth_source_id @user.password, @user.password_confirmation = params[:password], params[:password_confirmation] unless params[:password].nil? or params[:password].empty? or @user.auth_source_id
if params[:custom_fields] if params[:custom_fields]
@custom_values = UserCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @user, :value => params["custom_fields"][x.id.to_s]) } @custom_values = UserCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @user, :value => params["custom_fields"][x.id.to_s]) }
@user.custom_values = @custom_values @user.custom_values = @custom_values
end end
if @user.update_attributes(params[:user]) if @user.update_attributes(params[:user])
flash[:notice] = l(:notice_successful_update) flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'list' redirect_to :action => 'list'
end end
end end
@auth_sources = AuthSource.find(:all) @auth_sources = AuthSource.find(:all)
@roles = Role.find(:all, :order => 'position') @roles = Role.find(:all, :order => 'position')
@projects = Project.find(:all) - @user.projects @projects = Project.find(:all) - @user.projects
@membership ||= Member.new @membership ||= Member.new
end end
def edit_membership def edit_membership
@user = User.find(params[:id]) @user = User.find(params[:id])
@membership = params[:membership_id] ? Member.find(params[:membership_id]) : Member.new(:user => @user) @membership = params[:membership_id] ? Member.find(params[:membership_id]) : Member.new(:user => @user)
@membership.attributes = params[:membership] @membership.attributes = params[:membership]
if request.post? and @membership.save if request.post? and @membership.save
flash[:notice] = l(:notice_successful_update) flash[:notice] = l(:notice_successful_update)
end end
redirect_to :action => 'edit', :id => @user and return redirect_to :action => 'edit', :id => @user and return
end end
def destroy_membership def destroy_membership
@user = User.find(params[:id]) @user = User.find(params[:id])
if request.post? and Member.find(params[:membership_id]).destroy if request.post? and Member.find(params[:membership_id]).destroy
flash[:notice] = l(:notice_successful_update) flash[:notice] = l(:notice_successful_update)
end end
redirect_to :action => 'edit', :id => @user and return redirect_to :action => 'edit', :id => @user and return
end end
def destroy def destroy
User.find(params[:id]).destroy User.find(params[:id]).destroy
redirect_to :action => 'list'
rescue
flash[:notice] = "Unable to delete user"
redirect_to :action => 'list' redirect_to :action => 'list'
end rescue
flash[:notice] = "Unable to delete user"
redirect_to :action => 'list'
end
end end

View File

@ -1,23 +1,23 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class VersionsController < ApplicationController class VersionsController < ApplicationController
layout 'base' layout 'base'
before_filter :find_project, :authorize before_filter :find_project, :authorize
def edit def edit
if request.post? and @version.update_attributes(params[:version]) if request.post? and @version.update_attributes(params[:version])
@ -26,33 +26,33 @@ class VersionsController < ApplicationController
end end
end end
def destroy def destroy
@version.destroy @version.destroy
redirect_to :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project redirect_to :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project
rescue rescue
flash[:notice] = "Unable to delete version" flash[:notice] = "Unable to delete version"
redirect_to :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project redirect_to :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project
end end
def download def download
@attachment = @version.attachments.find(params[:attachment_id]) @attachment = @version.attachments.find(params[:attachment_id])
@attachment.increment_download @attachment.increment_download
send_file @attachment.diskfile, :filename => @attachment.filename send_file @attachment.diskfile, :filename => @attachment.filename
rescue rescue
render_404 render_404
end end
def destroy_file def destroy_file
@version.attachments.find(params[:attachment_id]).destroy @version.attachments.find(params[:attachment_id]).destroy
flash[:notice] = l(:notice_successful_delete) flash[:notice] = l(:notice_successful_delete)
redirect_to :controller => 'projects', :action => 'list_files', :id => @project redirect_to :controller => 'projects', :action => 'list_files', :id => @project
end end
private private
def find_project def find_project
@version = Version.find(params[:id]) @version = Version.find(params[:id])
@project = @version.project @project = @version.project
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
render_404 render_404
end end
end end

View File

@ -1,25 +1,25 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class WelcomeController < ApplicationController class WelcomeController < ApplicationController
layout 'base' layout 'base'
def index def index
@news = News.latest logged_in_user @news = News.latest logged_in_user
@projects = Project.latest logged_in_user @projects = Project.latest logged_in_user
end end
end end

View File

@ -1,19 +1,19 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module AccountHelper module AccountHelper
end end

View File

@ -1,19 +1,19 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module AdminHelper module AdminHelper
end end

View File

@ -1,229 +1,229 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang # Copyright (C) 2006-2007 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module ApplicationHelper module ApplicationHelper
# Return current logged in user or nil # Return current logged in user or nil
def loggedin? def loggedin?
@logged_in_user @logged_in_user
end end
# Return true if user is logged in and is admin, otherwise false # Return true if user is logged in and is admin, otherwise false
def admin_loggedin? def admin_loggedin?
@logged_in_user and @logged_in_user.admin? @logged_in_user and @logged_in_user.admin?
end end
# Return true if user is authorized for controller/action, otherwise false # Return true if user is authorized for controller/action, otherwise false
def authorize_for(controller, action) def authorize_for(controller, action)
# check if action is allowed on public projects # check if action is allowed on public projects
if @project.is_public? and Permission.allowed_to_public "%s/%s" % [ controller, action ] if @project.is_public? and Permission.allowed_to_public "%s/%s" % [ controller, action ]
return true return true
end end
# check if user is authorized # check if user is authorized
if @logged_in_user and (@logged_in_user.admin? or Permission.allowed_to_role( "%s/%s" % [ controller, action ], @logged_in_user.role_for_project(@project.id) ) ) if @logged_in_user and (@logged_in_user.admin? or Permission.allowed_to_role( "%s/%s" % [ controller, action ], @logged_in_user.role_for_project(@project.id) ) )
return true return true
end end
return false return false
end end
# Display a link if user is authorized # Display a link if user is authorized
def link_to_if_authorized(name, options = {}, html_options = nil, *parameters_for_method_reference) def link_to_if_authorized(name, options = {}, html_options = nil, *parameters_for_method_reference)
link_to(name, options, html_options, *parameters_for_method_reference) if authorize_for(options[:controller], options[:action]) link_to(name, options, html_options, *parameters_for_method_reference) if authorize_for(options[:controller], options[:action])
end end
# Display a link to user's account page # Display a link to user's account page
def link_to_user(user) def link_to_user(user)
link_to user.display_name, :controller => 'account', :action => 'show', :id => user link_to user.display_name, :controller => 'account', :action => 'show', :id => user
end end
def image_to_function(name, function, html_options = {}) def image_to_function(name, function, html_options = {})
html_options.symbolize_keys! html_options.symbolize_keys!
tag(:input, html_options.merge({ tag(:input, html_options.merge({
:type => "image", :src => image_path(name), :type => "image", :src => image_path(name),
:onclick => (html_options[:onclick] ? "#{html_options[:onclick]}; " : "") + "#{function};" :onclick => (html_options[:onclick] ? "#{html_options[:onclick]}; " : "") + "#{function};"
})) }))
end end
def format_date(date) def format_date(date)
l_date(date) if date l_date(date) if date
end end
def format_time(time) def format_time(time)
l_datetime((time.is_a? String) ? time.to_time : time) if time l_datetime((time.is_a? String) ? time.to_time : time) if time
end end
def day_name(day) def day_name(day)
l(:general_day_names).split(',')[day-1] l(:general_day_names).split(',')[day-1]
end end
def month_name(month) def month_name(month)
l(:actionview_datehelper_select_month_names).split(',')[month-1] l(:actionview_datehelper_select_month_names).split(',')[month-1]
end end
def pagination_links_full(paginator, options={}, html_options={}) def pagination_links_full(paginator, options={}, html_options={})
html = '' html = ''
html << link_to_remote(('&#171; ' + l(:label_previous)), html << link_to_remote(('&#171; ' + l(:label_previous)),
{:update => "content", :url => { :page => paginator.current.previous }}, {:update => "content", :url => { :page => paginator.current.previous }},
{:href => url_for(:action => 'list', :params => params.merge({:page => paginator.current.previous}))}) + ' ' if paginator.current.previous {:href => url_for(:action => 'list', :params => params.merge({:page => paginator.current.previous}))}) + ' ' if paginator.current.previous
html << (pagination_links_each(paginator, options) do |n| html << (pagination_links_each(paginator, options) do |n|
link_to_remote(n.to_s, link_to_remote(n.to_s,
{:url => {:action => 'list', :params => params.merge({:page => n})}, :update => 'content'}, {:url => {:action => 'list', :params => params.merge({:page => n})}, :update => 'content'},
{:href => url_for(:action => 'list', :params => params.merge({:page => n}))}) {:href => url_for(:action => 'list', :params => params.merge({:page => n}))})
end || '') end || '')
html << ' ' + link_to_remote((l(:label_next) + ' &#187;'), html << ' ' + link_to_remote((l(:label_next) + ' &#187;'),
{:update => "content", :url => { :page => paginator.current.next }}, {:update => "content", :url => { :page => paginator.current.next }},
{:href => url_for(:action => 'list', :params => params.merge({:page => paginator.current.next}))}) if paginator.current.next {:href => url_for(:action => 'list', :params => params.merge({:page => paginator.current.next}))}) if paginator.current.next
html html
end end
# textilize text according to system settings and RedCloth availability # textilize text according to system settings and RedCloth availability
def textilizable(text, options = {}) def textilizable(text, options = {})
# different methods for formatting wiki links # different methods for formatting wiki links
case options[:wiki_links] case options[:wiki_links]
when :local when :local
# used for local links to html files # used for local links to html files
format_wiki_link = Proc.new {|title| "#{title}.html" } format_wiki_link = Proc.new {|title| "#{title}.html" }
when :anchor when :anchor
# used for single-file wiki export # used for single-file wiki export
format_wiki_link = Proc.new {|title| "##{title}" } format_wiki_link = Proc.new {|title| "##{title}" }
else else
if @project if @project
format_wiki_link = Proc.new {|title| url_for :controller => 'wiki', :action => 'index', :id => @project, :page => title } format_wiki_link = Proc.new {|title| url_for :controller => 'wiki', :action => 'index', :id => @project, :page => title }
else else
format_wiki_link = Proc.new {|title| title } format_wiki_link = Proc.new {|title| title }
end end
end end
# turn wiki links into textile links: # turn wiki links into textile links:
# example: # example:
# [[link]] -> "link":link # [[link]] -> "link":link
# [[link|title]] -> "title":link # [[link|title]] -> "title":link
text = text.gsub(/\[\[([^\]\|]+)(\|([^\]\|]+))?\]\]/) {|m| "\"#{$3 || $1}\":" + format_wiki_link.call(Wiki.titleize($1)) } text = text.gsub(/\[\[([^\]\|]+)(\|([^\]\|]+))?\]\]/) {|m| "\"#{$3 || $1}\":" + format_wiki_link.call(Wiki.titleize($1)) }
# turn issue ids to textile links # turn issue ids to textile links
# example: # example:
# #52 -> "#52":/issues/show/52 # #52 -> "#52":/issues/show/52
text = text.gsub(/#(\d+)([\s\.\(\)\-,:;])/) {|m| "\"##{$1}\":" + url_for(:controller => 'issues', :action => 'show', :id => $1) + $2 } text = text.gsub(/#(\d+)([\s\.\(\)\-,:;])/) {|m| "\"##{$1}\":" + url_for(:controller => 'issues', :action => 'show', :id => $1) + $2 }
# turn revision ids to textile links (@project needed) # turn revision ids to textile links (@project needed)
# example: # example:
# r52 -> "r52":/repositories/revision/6?rev=52 (@project.id is 6) # r52 -> "r52":/repositories/revision/6?rev=52 (@project.id is 6)
text = text.gsub(/r(\d+)([\s\.\(\)\-,:;])/) {|m| "\"r#{$1}\":" + url_for(:controller => 'repositories', :action => 'revision', :id => @project.id, :rev => $1) + $2 } if @project text = text.gsub(/r(\d+)([\s\.\(\)\-,:;])/) {|m| "\"r#{$1}\":" + url_for(:controller => 'repositories', :action => 'revision', :id => @project.id, :rev => $1) + $2 } if @project
# finally textilize text # finally textilize text
text = (Setting.text_formatting == 'textile') && (ActionView::Helpers::TextHelper.method_defined? "textilize") ? auto_link(RedCloth.new(text, [:filter_html]).to_html) : simple_format(auto_link(h(text))) text = (Setting.text_formatting == 'textile') && (ActionView::Helpers::TextHelper.method_defined? "textilize") ? auto_link(RedCloth.new(text, [:filter_html]).to_html) : simple_format(auto_link(h(text)))
end end
def error_messages_for(object_name, options = {}) def error_messages_for(object_name, options = {})
options = options.symbolize_keys options = options.symbolize_keys
object = instance_variable_get("@#{object_name}") object = instance_variable_get("@#{object_name}")
if object && !object.errors.empty? if object && !object.errors.empty?
# build full_messages here with controller current language # build full_messages here with controller current language
full_messages = [] full_messages = []
object.errors.each do |attr, msg| object.errors.each do |attr, msg|
next if msg.nil? next if msg.nil?
msg = msg.first if msg.is_a? Array msg = msg.first if msg.is_a? Array
if attr == "base" if attr == "base"
full_messages << l(msg) full_messages << l(msg)
else else
full_messages << "&#171; " + (l_has_string?("field_" + attr) ? l("field_" + attr) : object.class.human_attribute_name(attr)) + " &#187; " + l(msg) unless attr == "custom_values" full_messages << "&#171; " + (l_has_string?("field_" + attr) ? l("field_" + attr) : object.class.human_attribute_name(attr)) + " &#187; " + l(msg) unless attr == "custom_values"
end end
end end
# retrieve custom values error messages # retrieve custom values error messages
if object.errors[:custom_values] if object.errors[:custom_values]
object.custom_values.each do |v| object.custom_values.each do |v|
v.errors.each do |attr, msg| v.errors.each do |attr, msg|
next if msg.nil? next if msg.nil?
msg = msg.first if msg.is_a? Array msg = msg.first if msg.is_a? Array
full_messages << "&#171; " + v.custom_field.name + " &#187; " + l(msg) full_messages << "&#171; " + v.custom_field.name + " &#187; " + l(msg)
end end
end end
end end
content_tag("div", content_tag("div",
content_tag( content_tag(
options[:header_tag] || "h2", lwr(:gui_validation_error, full_messages.length) + " :" options[:header_tag] || "h2", lwr(:gui_validation_error, full_messages.length) + " :"
) + ) +
content_tag("ul", full_messages.collect { |msg| content_tag("li", msg) }), content_tag("ul", full_messages.collect { |msg| content_tag("li", msg) }),
"id" => options[:id] || "errorExplanation", "class" => options[:class] || "errorExplanation" "id" => options[:id] || "errorExplanation", "class" => options[:class] || "errorExplanation"
) )
else else
"" ""
end end
end end
def lang_options_for_select(blank=true) def lang_options_for_select(blank=true)
(blank ? [["(auto)", ""]] : []) + (blank ? [["(auto)", ""]] : []) +
(GLoc.valid_languages.sort {|x,y| x.to_s <=> y.to_s }).collect {|lang| [ l_lang_name(lang.to_s, lang), lang.to_s]} (GLoc.valid_languages.sort {|x,y| x.to_s <=> y.to_s }).collect {|lang| [ l_lang_name(lang.to_s, lang), lang.to_s]}
end end
def label_tag_for(name, option_tags = nil, options = {}) def label_tag_for(name, option_tags = nil, options = {})
label_text = l(("field_"+field.to_s.gsub(/\_id$/, "")).to_sym) + (options.delete(:required) ? @template.content_tag("span", " *", :class => "required"): "") label_text = l(("field_"+field.to_s.gsub(/\_id$/, "")).to_sym) + (options.delete(:required) ? @template.content_tag("span", " *", :class => "required"): "")
content_tag("label", label_text) content_tag("label", label_text)
end end
def labelled_tabular_form_for(name, object, options, &proc) def labelled_tabular_form_for(name, object, options, &proc)
options[:html] ||= {} options[:html] ||= {}
options[:html].store :class, "tabular" options[:html].store :class, "tabular"
form_for(name, object, options.merge({ :builder => TabularFormBuilder, :lang => current_language}), &proc) form_for(name, object, options.merge({ :builder => TabularFormBuilder, :lang => current_language}), &proc)
end end
def check_all_links(form_name) def check_all_links(form_name)
link_to_function(l(:button_check_all), "checkAll('#{form_name}', true)") + link_to_function(l(:button_check_all), "checkAll('#{form_name}', true)") +
" | " + " | " +
link_to_function(l(:button_uncheck_all), "checkAll('#{form_name}', false)") link_to_function(l(:button_uncheck_all), "checkAll('#{form_name}', false)")
end end
def calendar_for(field_id) def calendar_for(field_id)
image_tag("calendar.png", {:id => "#{field_id}_trigger",:class => "calendar-trigger"}) + image_tag("calendar.png", {:id => "#{field_id}_trigger",:class => "calendar-trigger"}) +
javascript_tag("Calendar.setup({inputField : '#{field_id}', ifFormat : '%Y-%m-%d', button : '#{field_id}_trigger' });") javascript_tag("Calendar.setup({inputField : '#{field_id}', ifFormat : '%Y-%m-%d', button : '#{field_id}_trigger' });")
end end
end end
class TabularFormBuilder < ActionView::Helpers::FormBuilder class TabularFormBuilder < ActionView::Helpers::FormBuilder
include GLoc include GLoc
def initialize(object_name, object, template, options, proc) def initialize(object_name, object, template, options, proc)
set_language_if_valid options.delete(:lang) set_language_if_valid options.delete(:lang)
@object_name, @object, @template, @options, @proc = object_name, object, template, options, proc @object_name, @object, @template, @options, @proc = object_name, object, template, options, proc
end end
(field_helpers - %w(radio_button hidden_field) + %w(date_select)).each do |selector| (field_helpers - %w(radio_button hidden_field) + %w(date_select)).each do |selector|
src = <<-END_SRC src = <<-END_SRC
def #{selector}(field, options = {}) def #{selector}(field, options = {})
return super if options.delete :no_label return super if options.delete :no_label
label_text = l(("field_"+field.to_s.gsub(/\_id$/, "")).to_sym) + (options.delete(:required) ? @template.content_tag("span", " *", :class => "required"): "") label_text = l(("field_"+field.to_s.gsub(/\_id$/, "")).to_sym) + (options.delete(:required) ? @template.content_tag("span", " *", :class => "required"): "")
label = @template.content_tag("label", label_text, label = @template.content_tag("label", label_text,
:class => (@object && @object.errors[field] ? "error" : nil), :class => (@object && @object.errors[field] ? "error" : nil),
:for => (@object_name.to_s + "_" + field.to_s)) :for => (@object_name.to_s + "_" + field.to_s))
label + super label + super
end end
END_SRC END_SRC
class_eval src, __FILE__, __LINE__ class_eval src, __FILE__, __LINE__
end end
def select(field, choices, options = {}, html_options = {}) def select(field, choices, options = {}, html_options = {})
label_text = l(("field_"+field.to_s.gsub(/\_id$/, "")).to_sym) + (options.delete(:required) ? @template.content_tag("span", " *", :class => "required"): "") label_text = l(("field_"+field.to_s.gsub(/\_id$/, "")).to_sym) + (options.delete(:required) ? @template.content_tag("span", " *", :class => "required"): "")
label = @template.content_tag("label", label_text, label = @template.content_tag("label", label_text,
:class => (@object && @object.errors[field] ? "error" : nil), :class => (@object && @object.errors[field] ? "error" : nil),
:for => (@object_name.to_s + "_" + field.to_s)) :for => (@object_name.to_s + "_" + field.to_s))
label + super label + super
end end
end end

View File

@ -1,77 +1,77 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module CustomFieldsHelper module CustomFieldsHelper
# Return custom field html tag corresponding to its format # Return custom field html tag corresponding to its format
def custom_field_tag(custom_value) def custom_field_tag(custom_value)
custom_field = custom_value.custom_field custom_field = custom_value.custom_field
field_name = "custom_fields[#{custom_field.id}]" field_name = "custom_fields[#{custom_field.id}]"
field_id = "custom_fields_#{custom_field.id}" field_id = "custom_fields_#{custom_field.id}"
case custom_field.field_format case custom_field.field_format
when "string", "int" when "string", "int"
text_field 'custom_value', 'value', :name => field_name, :id => field_id text_field 'custom_value', 'value', :name => field_name, :id => field_id
when "date" when "date"
text_field('custom_value', 'value', :name => field_name, :id => field_id, :size => 10) + text_field('custom_value', 'value', :name => field_name, :id => field_id, :size => 10) +
calendar_for(field_id) calendar_for(field_id)
when "text" when "text"
text_area 'custom_value', 'value', :name => field_name, :id => field_id, :cols => 60, :rows => 3 text_area 'custom_value', 'value', :name => field_name, :id => field_id, :cols => 60, :rows => 3
when "bool" when "bool"
check_box 'custom_value', 'value', :name => field_name, :id => field_id check_box 'custom_value', 'value', :name => field_name, :id => field_id
when "list" when "list"
select 'custom_value', 'value', custom_field.possible_values, { :include_blank => true }, :name => field_name, :id => field_id select 'custom_value', 'value', custom_field.possible_values, { :include_blank => true }, :name => field_name, :id => field_id
end end
end end
# Return custom field label tag # Return custom field label tag
def custom_field_label_tag(custom_value) def custom_field_label_tag(custom_value)
content_tag "label", custom_value.custom_field.name + content_tag "label", custom_value.custom_field.name +
(custom_value.custom_field.is_required? ? " <span class=\"required\">*</span>" : ""), (custom_value.custom_field.is_required? ? " <span class=\"required\">*</span>" : ""),
:for => "custom_fields_#{custom_value.custom_field.id}", :for => "custom_fields_#{custom_value.custom_field.id}",
:class => (custom_value.errors.empty? ? nil : "error" ) :class => (custom_value.errors.empty? ? nil : "error" )
end end
# Return custom field tag with its label tag # Return custom field tag with its label tag
def custom_field_tag_with_label(custom_value) def custom_field_tag_with_label(custom_value)
custom_field_label_tag(custom_value) + custom_field_tag(custom_value) custom_field_label_tag(custom_value) + custom_field_tag(custom_value)
end end
# Return a string used to display a custom value # Return a string used to display a custom value
def show_value(custom_value) def show_value(custom_value)
return "" unless custom_value return "" unless custom_value
format_value(custom_value.value, custom_value.custom_field.field_format) format_value(custom_value.value, custom_value.custom_field.field_format)
end end
# Return a string used to display a custom value # Return a string used to display a custom value
def format_value(value, field_format) def format_value(value, field_format)
return "" unless value && !value.empty? return "" unless value && !value.empty?
case field_format case field_format
when "date" when "date"
begin; l_date(value.to_date); rescue; value end begin; l_date(value.to_date); rescue; value end
when "bool" when "bool"
l_YesNo(value == "1") l_YesNo(value == "1")
else else
value value
end end
end end
# Return an array of custom field formats which can be used in select_tag # Return an array of custom field formats which can be used in select_tag
def custom_field_formats_for_select def custom_field_formats_for_select
CustomField::FIELD_FORMATS.sort {|a,b| a[1][:order]<=>b[1][:order]}.collect { |k| [ l(k[1][:name]), k[0] ] } CustomField::FIELD_FORMATS.sort {|a,b| a[1][:order]<=>b[1][:order]}.collect { |k| [ l(k[1][:name]), k[0] ] }
end end
end end

View File

@ -1,19 +1,19 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module DocumentsHelper module DocumentsHelper
end end

View File

@ -1,19 +1,19 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module EnumerationsHelper module EnumerationsHelper
end end

View File

@ -1,19 +1,19 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module HelpHelper module HelpHelper
end end

View File

@ -1,70 +1,70 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require 'iconv' require 'iconv'
require 'rfpdf/chinese' require 'rfpdf/chinese'
module IfpdfHelper module IfpdfHelper
class IFPDF < FPDF class IFPDF < FPDF
include GLoc include GLoc
attr_accessor :footer_date attr_accessor :footer_date
def initialize(lang) def initialize(lang)
super() super()
set_language_if_valid lang set_language_if_valid lang
case current_language case current_language
when :ja when :ja
extend(PDF_Japanese) extend(PDF_Japanese)
AddSJISFont() AddSJISFont()
@font_for_content = 'SJIS' @font_for_content = 'SJIS'
@font_for_footer = 'SJIS' @font_for_footer = 'SJIS'
else else
@font_for_content = 'Arial' @font_for_content = 'Arial'
@font_for_footer = 'Helvetica' @font_for_footer = 'Helvetica'
end end
SetCreator("redMine #{Redmine::VERSION}") SetCreator("redMine #{Redmine::VERSION}")
SetFont(@font_for_content) SetFont(@font_for_content)
end end
def SetFontStyle(style, size) def SetFontStyle(style, size)
SetFont(@font_for_content, style, size) SetFont(@font_for_content, style, size)
end end
def Cell(w,h=0,txt='',border=0,ln=0,align='',fill=0,link='') def Cell(w,h=0,txt='',border=0,ln=0,align='',fill=0,link='')
@ic ||= Iconv.new(l(:general_pdf_encoding), 'UTF-8') @ic ||= Iconv.new(l(:general_pdf_encoding), 'UTF-8')
txt = begin txt = begin
@ic.iconv(txt) @ic.iconv(txt)
rescue rescue
txt txt
end end
super w,h,txt,border,ln,align,fill,link super w,h,txt,border,ln,align,fill,link
end end
def Footer def Footer
SetFont(@font_for_footer, 'I', 8) SetFont(@font_for_footer, 'I', 8)
SetY(-15) SetY(-15)
SetX(15) SetX(15)
Cell(0, 5, @footer_date, 0, 0, 'L') Cell(0, 5, @footer_date, 0, 0, 'L')
SetY(-15) SetY(-15)
SetX(-30) SetX(-30)
Cell(0, 5, PageNo().to_s + '/{nb}', 0, 0, 'C') Cell(0, 5, PageNo().to_s + '/{nb}', 0, 0, 'C')
end end
end end
end end

View File

@ -1,19 +1,19 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module IssueCategoriesHelper module IssueCategoriesHelper
end end

View File

@ -1,19 +1,19 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module IssueStatusesHelper module IssueStatusesHelper
end end

View File

@ -1,74 +1,74 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module IssuesHelper module IssuesHelper
def show_detail(detail, no_html=false) def show_detail(detail, no_html=false)
case detail.property case detail.property
when 'attr' when 'attr'
label = l(("field_" + detail.prop_key.to_s.gsub(/\_id$/, "")).to_sym) label = l(("field_" + detail.prop_key.to_s.gsub(/\_id$/, "")).to_sym)
case detail.prop_key case detail.prop_key
when 'due_date', 'start_date' when 'due_date', 'start_date'
value = format_date(detail.value.to_date) if detail.value value = format_date(detail.value.to_date) if detail.value
old_value = format_date(detail.old_value.to_date) if detail.old_value old_value = format_date(detail.old_value.to_date) if detail.old_value
when 'status_id' when 'status_id'
s = IssueStatus.find_by_id(detail.value) and value = s.name if detail.value s = IssueStatus.find_by_id(detail.value) and value = s.name if detail.value
s = IssueStatus.find_by_id(detail.old_value) and old_value = s.name if detail.old_value s = IssueStatus.find_by_id(detail.old_value) and old_value = s.name if detail.old_value
when 'assigned_to_id' when 'assigned_to_id'
u = User.find_by_id(detail.value) and value = u.name if detail.value u = User.find_by_id(detail.value) and value = u.name if detail.value
u = User.find_by_id(detail.old_value) and old_value = u.name if detail.old_value u = User.find_by_id(detail.old_value) and old_value = u.name if detail.old_value
when 'priority_id' when 'priority_id'
e = Enumeration.find_by_id(detail.value) and value = e.name if detail.value e = Enumeration.find_by_id(detail.value) and value = e.name if detail.value
e = Enumeration.find_by_id(detail.old_value) and old_value = e.name if detail.old_value e = Enumeration.find_by_id(detail.old_value) and old_value = e.name if detail.old_value
when 'category_id' when 'category_id'
c = IssueCategory.find_by_id(detail.value) and value = c.name if detail.value c = IssueCategory.find_by_id(detail.value) and value = c.name if detail.value
c = IssueCategory.find_by_id(detail.old_value) and old_value = c.name if detail.old_value c = IssueCategory.find_by_id(detail.old_value) and old_value = c.name if detail.old_value
when 'fixed_version_id' when 'fixed_version_id'
v = Version.find_by_id(detail.value) and value = v.name if detail.value v = Version.find_by_id(detail.value) and value = v.name if detail.value
v = Version.find_by_id(detail.old_value) and old_value = v.name if detail.old_value v = Version.find_by_id(detail.old_value) and old_value = v.name if detail.old_value
end end
when 'cf' when 'cf'
custom_field = CustomField.find_by_id(detail.prop_key) custom_field = CustomField.find_by_id(detail.prop_key)
if custom_field if custom_field
label = custom_field.name label = custom_field.name
value = format_value(detail.value, custom_field.field_format) if detail.value value = format_value(detail.value, custom_field.field_format) if detail.value
old_value = format_value(detail.old_value, custom_field.field_format) if detail.old_value old_value = format_value(detail.old_value, custom_field.field_format) if detail.old_value
end end
end end
label ||= detail.prop_key label ||= detail.prop_key
value ||= detail.value value ||= detail.value
old_value ||= detail.old_value old_value ||= detail.old_value
unless no_html unless no_html
label = content_tag('strong', label) label = content_tag('strong', label)
old_value = content_tag("i", h(old_value)) if detail.old_value old_value = content_tag("i", h(old_value)) if detail.old_value
old_value = content_tag("strike", old_value) if detail.old_value and (!detail.value or detail.value.empty?) old_value = content_tag("strike", old_value) if detail.old_value and (!detail.value or detail.value.empty?)
value = content_tag("i", h(value)) if value value = content_tag("i", h(value)) if value
end end
if detail.value and !detail.value.to_s.empty? if detail.value and !detail.value.to_s.empty?
if old_value if old_value
label + " " + l(:text_journal_changed, old_value, value) label + " " + l(:text_journal_changed, old_value, value)
else else
label + " " + l(:text_journal_set_to, value) label + " " + l(:text_journal_set_to, value)
end end
else else
label + " " + l(:text_journal_deleted) + " (#{old_value})" label + " " + l(:text_journal_deleted) + " (#{old_value})"
end end
end end
end end

View File

@ -1,19 +1,19 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module MembersHelper module MembersHelper
end end

View File

@ -1,19 +1,19 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module NewsHelper module NewsHelper
end end

View File

@ -1,29 +1,29 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module ProjectsHelper module ProjectsHelper
def highlight_tokens(text, tokens) def highlight_tokens(text, tokens)
return text unless tokens && !tokens.empty? return text unless tokens && !tokens.empty?
regexp = Regexp.new "(#{tokens.join('|')})", Regexp::IGNORECASE regexp = Regexp.new "(#{tokens.join('|')})", Regexp::IGNORECASE
result = '' result = ''
text.split(regexp).each_with_index do |words, i| text.split(regexp).each_with_index do |words, i|
result << (i.even? ? (words.length > 100 ? "#{words[0..44]} ... #{words[-45..-1]}" : words) : content_tag('span', words, :class => 'highlight')) result << (i.even? ? (words.length > 100 ? "#{words[0..44]} ... #{words[-45..-1]}" : words) : content_tag('span', words, :class => 'highlight'))
end end
result result
end end
end end

View File

@ -1,32 +1,32 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module ReportsHelper module ReportsHelper
def aggregate(data, criteria) def aggregate(data, criteria)
a = 0 a = 0
data.each { |row| data.each { |row|
match = 1 match = 1
criteria.each { |k, v| criteria.each { |k, v|
match = 0 unless row[k].to_s == v.to_s match = 0 unless row[k].to_s == v.to_s
} unless criteria.nil? } unless criteria.nil?
a = a + row["total"].to_i if match == 1 a = a + row["total"].to_i if match == 1
} unless data.nil? } unless data.nil?
a a
end end
end end

View File

@ -1,19 +1,19 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module RolesHelper module RolesHelper
end end

View File

@ -1,19 +1,19 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module TrackersHelper module TrackersHelper
end end

View File

@ -1,19 +1,19 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module UsersHelper module UsersHelper
end end

View File

@ -1,19 +1,19 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module VersionsHelper module VersionsHelper
end end

View File

@ -1,19 +1,19 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module WelcomeHelper module WelcomeHelper
end end

View File

@ -1,92 +1,92 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang # Copyright (C) 2006-2007 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require "digest/md5" require "digest/md5"
class Attachment < ActiveRecord::Base class Attachment < ActiveRecord::Base
belongs_to :container, :polymorphic => true belongs_to :container, :polymorphic => true
belongs_to :author, :class_name => "User", :foreign_key => "author_id" belongs_to :author, :class_name => "User", :foreign_key => "author_id"
validates_presence_of :container, :filename validates_presence_of :container, :filename
cattr_accessor :storage_path cattr_accessor :storage_path
@@storage_path = "#{RAILS_ROOT}/files" @@storage_path = "#{RAILS_ROOT}/files"
def validate def validate
errors.add_to_base :too_long if self.filesize > Setting.attachment_max_size.to_i.kilobytes errors.add_to_base :too_long if self.filesize > Setting.attachment_max_size.to_i.kilobytes
end end
def file=(incomming_file) def file=(incomming_file)
unless incomming_file.nil? unless incomming_file.nil?
@temp_file = incomming_file @temp_file = incomming_file
if @temp_file.size > 0 if @temp_file.size > 0
self.filename = sanitize_filename(@temp_file.original_filename) self.filename = sanitize_filename(@temp_file.original_filename)
self.disk_filename = DateTime.now.strftime("%y%m%d%H%M%S") + "_" + self.filename self.disk_filename = DateTime.now.strftime("%y%m%d%H%M%S") + "_" + self.filename
self.content_type = @temp_file.content_type self.content_type = @temp_file.content_type
self.filesize = @temp_file.size self.filesize = @temp_file.size
end end
end end
end end
def file def file
nil nil
end end
# Copy temp file to its final location # Copy temp file to its final location
def before_save def before_save
if @temp_file && (@temp_file.size > 0) if @temp_file && (@temp_file.size > 0)
logger.debug("saving '#{self.diskfile}'") logger.debug("saving '#{self.diskfile}'")
File.open(diskfile, "wb") do |f| File.open(diskfile, "wb") do |f|
f.write(@temp_file.read) f.write(@temp_file.read)
end end
self.digest = Digest::MD5.hexdigest(File.read(diskfile)) self.digest = Digest::MD5.hexdigest(File.read(diskfile))
end end
end end
# Deletes file on the disk # Deletes file on the disk
def after_destroy def after_destroy
if self.filename? if self.filename?
File.delete(diskfile) if File.exist?(diskfile) File.delete(diskfile) if File.exist?(diskfile)
end end
end end
# Returns file's location on disk # Returns file's location on disk
def diskfile def diskfile
"#{@@storage_path}/#{self.disk_filename}" "#{@@storage_path}/#{self.disk_filename}"
end end
def increment_download def increment_download
increment!(:downloads) increment!(:downloads)
end end
# returns last created projects # returns last created projects
def self.most_downloaded def self.most_downloaded
find(:all, :limit => 5, :order => "downloads DESC") find(:all, :limit => 5, :order => "downloads DESC")
end end
private private
def sanitize_filename(value) def sanitize_filename(value)
# get only the filename, not the whole path # get only the filename, not the whole path
just_filename = value.gsub(/^.*(\\|\/)/, '') just_filename = value.gsub(/^.*(\\|\/)/, '')
# NOTE: File.basename doesn't work right with Windows paths on Unix # NOTE: File.basename doesn't work right with Windows paths on Unix
# INCORRECT: just_filename = File.basename(value.gsub('\\\\', '/')) # INCORRECT: just_filename = File.basename(value.gsub('\\\\', '/'))
# Finally, replace all non alphanumeric, underscore or periods with underscore # Finally, replace all non alphanumeric, underscore or periods with underscore
@filename = just_filename.gsub(/[^\w\.\-]/,'_') @filename = just_filename.gsub(/[^\w\.\-]/,'_')
end end
end end

View File

@ -1,79 +1,79 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require 'net/ldap' require 'net/ldap'
require 'iconv' require 'iconv'
class AuthSourceLdap < AuthSource class AuthSourceLdap < AuthSource
validates_presence_of :host, :port, :attr_login validates_presence_of :host, :port, :attr_login
def after_initialize def after_initialize
self.port = 389 if self.port == 0 self.port = 389 if self.port == 0
end end
def authenticate(login, password) def authenticate(login, password)
attrs = [] attrs = []
# get user's DN # get user's DN
ldap_con = initialize_ldap_con(self.account, self.account_password) ldap_con = initialize_ldap_con(self.account, self.account_password)
login_filter = Net::LDAP::Filter.eq( self.attr_login, login ) login_filter = Net::LDAP::Filter.eq( self.attr_login, login )
object_filter = Net::LDAP::Filter.eq( "objectClass", "*" ) object_filter = Net::LDAP::Filter.eq( "objectClass", "*" )
dn = String.new dn = String.new
ldap_con.search( :base => self.base_dn, ldap_con.search( :base => self.base_dn,
:filter => object_filter & login_filter, :filter => object_filter & login_filter,
:attributes=> ['dn', self.attr_firstname, self.attr_lastname, self.attr_mail]) do |entry| :attributes=> ['dn', self.attr_firstname, self.attr_lastname, self.attr_mail]) do |entry|
dn = entry.dn dn = entry.dn
attrs = [:firstname => AuthSourceLdap.get_attr(entry, self.attr_firstname), attrs = [:firstname => AuthSourceLdap.get_attr(entry, self.attr_firstname),
:lastname => AuthSourceLdap.get_attr(entry, self.attr_lastname), :lastname => AuthSourceLdap.get_attr(entry, self.attr_lastname),
:mail => AuthSourceLdap.get_attr(entry, self.attr_mail), :mail => AuthSourceLdap.get_attr(entry, self.attr_mail),
:auth_source_id => self.id ] :auth_source_id => self.id ]
end end
return nil if dn.empty? return nil if dn.empty?
logger.debug "DN found for #{login}: #{dn}" if logger && logger.debug? logger.debug "DN found for #{login}: #{dn}" if logger && logger.debug?
# authenticate user # authenticate user
ldap_con = initialize_ldap_con(dn, password) ldap_con = initialize_ldap_con(dn, password)
return nil unless ldap_con.bind return nil unless ldap_con.bind
# return user's attributes # return user's attributes
logger.debug "Authentication successful for '#{login}'" if logger && logger.debug? logger.debug "Authentication successful for '#{login}'" if logger && logger.debug?
attrs attrs
rescue Net::LDAP::LdapError => text rescue Net::LDAP::LdapError => text
raise "LdapError: " + text raise "LdapError: " + text
end end
# test the connection to the LDAP # test the connection to the LDAP
def test_connection def test_connection
ldap_con = initialize_ldap_con(self.account, self.account_password) ldap_con = initialize_ldap_con(self.account, self.account_password)
ldap_con.open { } ldap_con.open { }
rescue Net::LDAP::LdapError => text rescue Net::LDAP::LdapError => text
raise "LdapError: " + text raise "LdapError: " + text
end end
def auth_method_name def auth_method_name
"LDAP" "LDAP"
end end
private private
def initialize_ldap_con(ldap_user, ldap_password) def initialize_ldap_con(ldap_user, ldap_password)
Net::LDAP.new( {:host => self.host, Net::LDAP.new( {:host => self.host,
:port => self.port, :port => self.port,
:auth => { :method => :simple, :username => Iconv.new('iso-8859-15', 'utf-8').iconv(ldap_user), :password => Iconv.new('iso-8859-15', 'utf-8').iconv(ldap_password) }} :auth => { :method => :simple, :username => Iconv.new('iso-8859-15', 'utf-8').iconv(ldap_user), :password => Iconv.new('iso-8859-15', 'utf-8').iconv(ldap_password) }}
) )
end end
def self.get_attr(entry, attr_name) def self.get_attr(entry, attr_name)
entry[attr_name].is_a?(Array) ? entry[attr_name].first : entry[attr_name] entry[attr_name].is_a?(Array) ? entry[attr_name].first : entry[attr_name]
end end
end end

View File

@ -1,60 +1,60 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class CustomField < ActiveRecord::Base class CustomField < ActiveRecord::Base
has_many :custom_values, :dependent => :delete_all has_many :custom_values, :dependent => :delete_all
serialize :possible_values serialize :possible_values
FIELD_FORMATS = { "string" => { :name => :label_string, :order => 1 }, FIELD_FORMATS = { "string" => { :name => :label_string, :order => 1 },
"text" => { :name => :label_text, :order => 2 }, "text" => { :name => :label_text, :order => 2 },
"int" => { :name => :label_integer, :order => 3 }, "int" => { :name => :label_integer, :order => 3 },
"list" => { :name => :label_list, :order => 4 }, "list" => { :name => :label_list, :order => 4 },
"date" => { :name => :label_date, :order => 5 }, "date" => { :name => :label_date, :order => 5 },
"bool" => { :name => :label_boolean, :order => 6 } "bool" => { :name => :label_boolean, :order => 6 }
}.freeze }.freeze
validates_presence_of :name, :field_format validates_presence_of :name, :field_format
validates_uniqueness_of :name validates_uniqueness_of :name
validates_format_of :name, :with => /^[\w\s\'\-]*$/i validates_format_of :name, :with => /^[\w\s\'\-]*$/i
validates_inclusion_of :field_format, :in => FIELD_FORMATS.keys validates_inclusion_of :field_format, :in => FIELD_FORMATS.keys
def initialize(attributes = nil) def initialize(attributes = nil)
super super
self.possible_values ||= [] self.possible_values ||= []
end
def before_validation
# remove empty values
self.possible_values = self.possible_values.collect{|v| v unless v.empty?}.compact
end
def validate
if self.field_format == "list"
errors.add(:possible_values, :activerecord_error_blank) if self.possible_values.nil? || self.possible_values.empty?
errors.add(:possible_values, :activerecord_error_invalid) unless self.possible_values.is_a? Array
end
end
# to move in project_custom_field
def self.for_all
find(:all, :conditions => ["is_for_all=?", true])
end
def type_name
nil
end end
end
def before_validation
# remove empty values
self.possible_values = self.possible_values.collect{|v| v unless v.empty?}.compact
end
def validate
if self.field_format == "list"
errors.add(:possible_values, :activerecord_error_blank) if self.possible_values.nil? || self.possible_values.empty?
errors.add(:possible_values, :activerecord_error_invalid) unless self.possible_values.is_a? Array
end
end
# to move in project_custom_field
def self.for_all
find(:all, :conditions => ["is_for_all=?", true])
end
def type_name
nil
end
end

View File

@ -1,38 +1,38 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class CustomValue < ActiveRecord::Base class CustomValue < ActiveRecord::Base
belongs_to :custom_field belongs_to :custom_field
belongs_to :customized, :polymorphic => true belongs_to :customized, :polymorphic => true
protected protected
def validate def validate
errors.add(:value, :activerecord_error_blank) and return if custom_field.is_required? and value.empty? errors.add(:value, :activerecord_error_blank) and return if custom_field.is_required? and value.empty?
errors.add(:value, :activerecord_error_invalid) unless custom_field.regexp.empty? or value =~ Regexp.new(custom_field.regexp) errors.add(:value, :activerecord_error_invalid) unless custom_field.regexp.empty? or value =~ Regexp.new(custom_field.regexp)
errors.add(:value, :activerecord_error_too_short) if custom_field.min_length > 0 and value.length < custom_field.min_length and value.length > 0 errors.add(:value, :activerecord_error_too_short) if custom_field.min_length > 0 and value.length < custom_field.min_length and value.length > 0
errors.add(:value, :activerecord_error_too_long) if custom_field.max_length > 0 and value.length > custom_field.max_length errors.add(:value, :activerecord_error_too_long) if custom_field.max_length > 0 and value.length > custom_field.max_length
case custom_field.field_format case custom_field.field_format
when "int" when "int"
errors.add(:value, :activerecord_error_not_a_number) unless value =~ /^[0-9]*$/ errors.add(:value, :activerecord_error_not_a_number) unless value =~ /^[0-9]*$/
when "date" when "date"
errors.add(:value, :activerecord_error_not_a_date) unless value =~ /^\d{4}-\d{2}-\d{2}$/ or value.empty? errors.add(:value, :activerecord_error_not_a_date) unless value =~ /^\d{4}-\d{2}-\d{2}$/ or value.empty?
when "list" when "list"
errors.add(:value, :activerecord_error_inclusion) unless custom_field.possible_values.include? value or value.empty? errors.add(:value, :activerecord_error_inclusion) unless custom_field.possible_values.include? value or value.empty?
end end
end end
end end

View File

@ -1,24 +1,24 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Document < ActiveRecord::Base class Document < ActiveRecord::Base
belongs_to :project belongs_to :project
belongs_to :category, :class_name => "Enumeration", :foreign_key => "category_id" belongs_to :category, :class_name => "Enumeration", :foreign_key => "category_id"
has_many :attachments, :as => :container, :dependent => :destroy has_many :attachments, :as => :container, :dependent => :destroy
validates_presence_of :project, :title, :category validates_presence_of :project, :title, :category
end end

View File

@ -1,47 +1,47 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Enumeration < ActiveRecord::Base class Enumeration < ActiveRecord::Base
before_destroy :check_integrity before_destroy :check_integrity
validates_presence_of :opt, :name validates_presence_of :opt, :name
validates_uniqueness_of :name, :scope => [:opt] validates_uniqueness_of :name, :scope => [:opt]
validates_format_of :name, :with => /^[\w\s\'\-]*$/i validates_format_of :name, :with => /^[\w\s\'\-]*$/i
OPTIONS = { OPTIONS = {
"IPRI" => :enumeration_issue_priorities, "IPRI" => :enumeration_issue_priorities,
"DCAT" => :enumeration_doc_categories "DCAT" => :enumeration_doc_categories
}.freeze }.freeze
def self.get_values(option) def self.get_values(option)
find(:all, :conditions => ['opt=?', option]) find(:all, :conditions => ['opt=?', option])
end end
def option_name def option_name
OPTIONS[self.opt] OPTIONS[self.opt]
end end
private private
def check_integrity def check_integrity
case self.opt case self.opt
when "IPRI" when "IPRI"
raise "Can't delete enumeration" if Issue.find(:first, :conditions => ["priority_id=?", self.id]) raise "Can't delete enumeration" if Issue.find(:first, :conditions => ["priority_id=?", self.id])
when "DCAT" when "DCAT"
raise "Can't delete enumeration" if Document.find(:first, :conditions => ["category_id=?", self.id]) raise "Can't delete enumeration" if Document.find(:first, :conditions => ["category_id=?", self.id])
end end
end end
end end

View File

@ -1,102 +1,102 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Issue < ActiveRecord::Base class Issue < ActiveRecord::Base
belongs_to :project belongs_to :project
belongs_to :tracker belongs_to :tracker
belongs_to :status, :class_name => 'IssueStatus', :foreign_key => 'status_id' belongs_to :status, :class_name => 'IssueStatus', :foreign_key => 'status_id'
belongs_to :author, :class_name => 'User', :foreign_key => 'author_id' belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
belongs_to :assigned_to, :class_name => 'User', :foreign_key => 'assigned_to_id' belongs_to :assigned_to, :class_name => 'User', :foreign_key => 'assigned_to_id'
belongs_to :fixed_version, :class_name => 'Version', :foreign_key => 'fixed_version_id' belongs_to :fixed_version, :class_name => 'Version', :foreign_key => 'fixed_version_id'
belongs_to :priority, :class_name => 'Enumeration', :foreign_key => 'priority_id' belongs_to :priority, :class_name => 'Enumeration', :foreign_key => 'priority_id'
belongs_to :category, :class_name => 'IssueCategory', :foreign_key => 'category_id' belongs_to :category, :class_name => 'IssueCategory', :foreign_key => 'category_id'
has_many :journals, :as => :journalized, :dependent => :destroy has_many :journals, :as => :journalized, :dependent => :destroy
has_many :attachments, :as => :container, :dependent => :destroy has_many :attachments, :as => :container, :dependent => :destroy
has_many :custom_values, :dependent => :delete_all, :as => :customized has_many :custom_values, :dependent => :delete_all, :as => :customized
has_many :custom_fields, :through => :custom_values has_many :custom_fields, :through => :custom_values
validates_presence_of :subject, :description, :priority, :tracker, :author, :status validates_presence_of :subject, :description, :priority, :tracker, :author, :status
validates_inclusion_of :done_ratio, :in => 0..100 validates_inclusion_of :done_ratio, :in => 0..100
validates_associated :custom_values, :on => :update validates_associated :custom_values, :on => :update
# set default status for new issues # set default status for new issues
def before_validation def before_validation
self.status = IssueStatus.default if new_record? self.status = IssueStatus.default if new_record?
end end
def validate def validate
if self.due_date.nil? && @attributes['due_date'] && !@attributes['due_date'].empty? if self.due_date.nil? && @attributes['due_date'] && !@attributes['due_date'].empty?
errors.add :due_date, :activerecord_error_not_a_date errors.add :due_date, :activerecord_error_not_a_date
end end
if self.due_date and self.start_date and self.due_date < self.start_date if self.due_date and self.start_date and self.due_date < self.start_date
errors.add :due_date, :activerecord_error_greater_than_start_date errors.add :due_date, :activerecord_error_greater_than_start_date
end end
end end
#def before_create #def before_create
# build_history # build_history
#end #end
def before_save def before_save
if @current_journal if @current_journal
# attributes changes # attributes changes
(Issue.column_names - %w(id description)).each {|c| (Issue.column_names - %w(id description)).each {|c|
@current_journal.details << JournalDetail.new(:property => 'attr', @current_journal.details << JournalDetail.new(:property => 'attr',
:prop_key => c, :prop_key => c,
:old_value => @issue_before_change.send(c), :old_value => @issue_before_change.send(c),
:value => send(c)) unless send(c)==@issue_before_change.send(c) :value => send(c)) unless send(c)==@issue_before_change.send(c)
} }
# custom fields changes # custom fields changes
custom_values.each {|c| custom_values.each {|c|
@current_journal.details << JournalDetail.new(:property => 'cf', @current_journal.details << JournalDetail.new(:property => 'cf',
:prop_key => c.custom_field_id, :prop_key => c.custom_field_id,
:old_value => @custom_values_before_change[c.custom_field_id], :old_value => @custom_values_before_change[c.custom_field_id],
:value => c.value) unless @custom_values_before_change[c.custom_field_id]==c.value :value => c.value) unless @custom_values_before_change[c.custom_field_id]==c.value
} }
@current_journal.save unless @current_journal.details.empty? and @current_journal.notes.empty? @current_journal.save unless @current_journal.details.empty? and @current_journal.notes.empty?
end end
end end
def long_id def long_id
"%05d" % self.id "%05d" % self.id
end end
def custom_value_for(custom_field) def custom_value_for(custom_field)
self.custom_values.each {|v| return v if v.custom_field_id == custom_field.id } self.custom_values.each {|v| return v if v.custom_field_id == custom_field.id }
return nil return nil
end end
def init_journal(user, notes = "") def init_journal(user, notes = "")
@current_journal ||= Journal.new(:journalized => self, :user => user, :notes => notes) @current_journal ||= Journal.new(:journalized => self, :user => user, :notes => notes)
@issue_before_change = self.clone @issue_before_change = self.clone
@custom_values_before_change = {} @custom_values_before_change = {}
self.custom_values.each {|c| @custom_values_before_change.store c.custom_field_id, c.value } self.custom_values.each {|c| @custom_values_before_change.store c.custom_field_id, c.value }
@current_journal @current_journal
end end
private private
# Creates an history for the issue # Creates an history for the issue
#def build_history #def build_history
# @history = self.histories.build # @history = self.histories.build
# @history.status = self.status # @history.status = self.status
# @history.author = self.author # @history.author = self.author
#end #end
end end

View File

@ -1,29 +1,29 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class IssueCategory < ActiveRecord::Base class IssueCategory < ActiveRecord::Base
before_destroy :check_integrity before_destroy :check_integrity
belongs_to :project belongs_to :project
validates_presence_of :name validates_presence_of :name
validates_uniqueness_of :name, :scope => [:project_id] validates_uniqueness_of :name, :scope => [:project_id]
private private
def check_integrity def check_integrity
raise "Can't delete category" if Issue.find(:first, :conditions => ["category_id=?", self.id]) raise "Can't delete category" if Issue.find(:first, :conditions => ["category_id=?", self.id])
end end
end end

View File

@ -1,27 +1,27 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class IssueCustomField < CustomField class IssueCustomField < CustomField
has_and_belongs_to_many :projects, :join_table => "custom_fields_projects", :foreign_key => "custom_field_id" has_and_belongs_to_many :projects, :join_table => "custom_fields_projects", :foreign_key => "custom_field_id"
has_and_belongs_to_many :trackers, :join_table => "custom_fields_trackers", :foreign_key => "custom_field_id" has_and_belongs_to_many :trackers, :join_table => "custom_fields_trackers", :foreign_key => "custom_field_id"
has_many :issues, :through => :issue_custom_values has_many :issues, :through => :issue_custom_values
def type_name def type_name
:label_issue_plural :label_issue_plural
end end
end end

View File

@ -1,24 +1,24 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class IssueHistory < ActiveRecord::Base class IssueHistory < ActiveRecord::Base
belongs_to :status, :class_name => 'IssueStatus', :foreign_key => 'status_id' belongs_to :status, :class_name => 'IssueStatus', :foreign_key => 'status_id'
belongs_to :author, :class_name => 'User', :foreign_key => 'author_id' belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
belongs_to :issue belongs_to :issue
validates_presence_of :status validates_presence_of :status
end end

View File

@ -1,51 +1,51 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class IssueStatus < ActiveRecord::Base class IssueStatus < ActiveRecord::Base
before_destroy :check_integrity before_destroy :check_integrity
has_many :workflows, :foreign_key => "old_status_id" has_many :workflows, :foreign_key => "old_status_id"
acts_as_list acts_as_list
validates_presence_of :name validates_presence_of :name
validates_uniqueness_of :name validates_uniqueness_of :name
validates_format_of :name, :with => /^[\w\s\'\-]*$/i validates_format_of :name, :with => /^[\w\s\'\-]*$/i
validates_length_of :html_color, :is => 6 validates_length_of :html_color, :is => 6
validates_format_of :html_color, :with => /^[a-f0-9]*$/i validates_format_of :html_color, :with => /^[a-f0-9]*$/i
def before_save def before_save
IssueStatus.update_all "is_default=#{connection.quoted_false}" if self.is_default? IssueStatus.update_all "is_default=#{connection.quoted_false}" if self.is_default?
end end
# Returns the default status for new issues # Returns the default status for new issues
def self.default def self.default
find(:first, :conditions =>["is_default=?", true]) find(:first, :conditions =>["is_default=?", true])
end end
# Returns an array of all statuses the given role can switch to # Returns an array of all statuses the given role can switch to
def new_statuses_allowed_to(role, tracker) def new_statuses_allowed_to(role, tracker)
statuses = [] statuses = []
for workflow in self.workflows for workflow in self.workflows
statuses << workflow.new_status if workflow.role_id == role.id and workflow.tracker_id == tracker.id statuses << workflow.new_status if workflow.role_id == role.id and workflow.tracker_id == tracker.id
end unless role.nil? or tracker.nil? end unless role.nil? or tracker.nil?
statuses statuses
end end
private private
def check_integrity def check_integrity
raise "Can't delete status" if Issue.find(:first, :conditions => ["status_id=?", self.id]) raise "Can't delete status" if Issue.find(:first, :conditions => ["status_id=?", self.id])
end end
end end

View File

@ -1,88 +1,88 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang # Copyright (C) 2006-2007 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Mailer < ActionMailer::Base class Mailer < ActionMailer::Base
helper IssuesHelper helper IssuesHelper
def issue_add(issue) def issue_add(issue)
set_language_if_valid(Setting.default_language) set_language_if_valid(Setting.default_language)
# Sends to all project members # Sends to all project members
@recipients = issue.project.members.collect { |m| m.user.mail if m.user.mail_notification }.compact @recipients = issue.project.members.collect { |m| m.user.mail if m.user.mail_notification }.compact
@from = Setting.mail_from @from = Setting.mail_from
@subject = "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] #{issue.status.name} - #{issue.subject}" @subject = "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] #{issue.status.name} - #{issue.subject}"
@body['issue'] = issue @body['issue'] = issue
end end
def issue_edit(journal) def issue_edit(journal)
set_language_if_valid(Setting.default_language) set_language_if_valid(Setting.default_language)
# Sends to all project members # Sends to all project members
issue = journal.journalized issue = journal.journalized
@recipients = issue.project.members.collect { |m| m.user.mail if m.user.mail_notification }.compact @recipients = issue.project.members.collect { |m| m.user.mail if m.user.mail_notification }.compact
@from = Setting.mail_from @from = Setting.mail_from
@subject = "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] #{issue.status.name} - #{issue.subject}" @subject = "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] #{issue.status.name} - #{issue.subject}"
@body['issue'] = issue @body['issue'] = issue
@body['journal']= journal @body['journal']= journal
end end
def document_add(document) def document_add(document)
set_language_if_valid(Setting.default_language) set_language_if_valid(Setting.default_language)
@recipients = document.project.users.collect { |u| u.mail if u.mail_notification }.compact @recipients = document.project.users.collect { |u| u.mail if u.mail_notification }.compact
@from = Setting.mail_from @from = Setting.mail_from
@subject = "[#{document.project.name}] #{l(:label_document_new)}: #{document.title}" @subject = "[#{document.project.name}] #{l(:label_document_new)}: #{document.title}"
@body['document'] = document @body['document'] = document
end end
def attachments_add(attachments) def attachments_add(attachments)
set_language_if_valid(Setting.default_language) set_language_if_valid(Setting.default_language)
container = attachments.first.container container = attachments.first.container
url = "http://#{Setting.host_name}/" url = "http://#{Setting.host_name}/"
added_to = "" added_to = ""
case container.class.to_s case container.class.to_s
when 'Version' when 'Version'
url << "projects/list_files/#{container.project_id}" url << "projects/list_files/#{container.project_id}"
added_to = "#{l(:label_version)}: #{container.name}" added_to = "#{l(:label_version)}: #{container.name}"
when 'Document' when 'Document'
url << "documents/show/#{container.id}" url << "documents/show/#{container.id}"
added_to = "#{l(:label_document)}: #{container.title}" added_to = "#{l(:label_document)}: #{container.title}"
when 'Issue' when 'Issue'
url << "issues/show/#{container.id}" url << "issues/show/#{container.id}"
added_to = "#{container.tracker.name} ##{container.id}: #{container.subject}" added_to = "#{container.tracker.name} ##{container.id}: #{container.subject}"
end end
@recipients = container.project.users.collect { |u| u.mail if u.mail_notification }.compact @recipients = container.project.users.collect { |u| u.mail if u.mail_notification }.compact
@from = Setting.mail_from @from = Setting.mail_from
@subject = "[#{container.project.name}] #{l(:label_attachment_new)}" @subject = "[#{container.project.name}] #{l(:label_attachment_new)}"
@body['attachments'] = attachments @body['attachments'] = attachments
@body['url'] = url @body['url'] = url
@body['added_to'] = added_to @body['added_to'] = added_to
end end
def lost_password(token) def lost_password(token)
set_language_if_valid(token.user.language) set_language_if_valid(token.user.language)
@recipients = token.user.mail @recipients = token.user.mail
@from = Setting.mail_from @from = Setting.mail_from
@subject = l(:mail_subject_lost_password) @subject = l(:mail_subject_lost_password)
@body['token'] = token @body['token'] = token
end end
def register(token) def register(token)
set_language_if_valid(token.user.language) set_language_if_valid(token.user.language)
@recipients = token.user.mail @recipients = token.user.mail
@from = Setting.mail_from @from = Setting.mail_from
@subject = l(:mail_subject_register) @subject = l(:mail_subject_register)
@body['token'] = token @body['token'] = token
end end
end end

View File

@ -1,29 +1,29 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Member < ActiveRecord::Base class Member < ActiveRecord::Base
belongs_to :user belongs_to :user
belongs_to :role belongs_to :role
belongs_to :project belongs_to :project
validates_presence_of :role, :user, :project validates_presence_of :role, :user, :project
validates_uniqueness_of :user_id, :scope => :project_id validates_uniqueness_of :user_id, :scope => :project_id
def name def name
self.user.display_name self.user.display_name
end end
end end

View File

@ -1,29 +1,29 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class News < ActiveRecord::Base class News < ActiveRecord::Base
belongs_to :project belongs_to :project
belongs_to :author, :class_name => 'User', :foreign_key => 'author_id' belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
has_many :comments, :as => :commented, :dependent => :delete_all, :order => "created_on" has_many :comments, :as => :commented, :dependent => :delete_all, :order => "created_on"
validates_presence_of :title, :description validates_presence_of :title, :description
# returns latest news for projects visible by user # returns latest news for projects visible by user
def self.latest(user=nil, count=5) def self.latest(user=nil, count=5)
find(:all, :limit => count, :conditions => Project.visible_by(user), :include => [ :author, :project ], :order => "news.created_on DESC") find(:all, :limit => count, :conditions => Project.visible_by(user), :include => [ :author, :project ], :order => "news.created_on DESC")
end end
end end

View File

@ -1,65 +1,65 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Permission < ActiveRecord::Base class Permission < ActiveRecord::Base
has_and_belongs_to_many :roles has_and_belongs_to_many :roles
validates_presence_of :controller, :action, :description validates_presence_of :controller, :action, :description
GROUPS = { GROUPS = {
100 => :label_project, 100 => :label_project,
200 => :label_member_plural, 200 => :label_member_plural,
300 => :label_version_plural, 300 => :label_version_plural,
400 => :label_issue_category_plural, 400 => :label_issue_category_plural,
600 => :label_query_plural, 600 => :label_query_plural,
1000 => :label_issue_plural, 1000 => :label_issue_plural,
1100 => :label_news_plural, 1100 => :label_news_plural,
1200 => :label_document_plural, 1200 => :label_document_plural,
1300 => :label_attachment_plural, 1300 => :label_attachment_plural,
1400 => :label_repository 1400 => :label_repository
}.freeze }.freeze
@@cached_perms_for_public = nil @@cached_perms_for_public = nil
@@cached_perms_for_roles = nil @@cached_perms_for_roles = nil
def name def name
self.controller + "/" + self.action self.controller + "/" + self.action
end end
def group_id def group_id
(self.sort / 100)*100 (self.sort / 100)*100
end end
def self.allowed_to_public(action) def self.allowed_to_public(action)
@@cached_perms_for_public ||= find(:all, :conditions => ["is_public=?", true]).collect {|p| "#{p.controller}/#{p.action}"} @@cached_perms_for_public ||= find(:all, :conditions => ["is_public=?", true]).collect {|p| "#{p.controller}/#{p.action}"}
@@cached_perms_for_public.include? action @@cached_perms_for_public.include? action
end end
def self.allowed_to_role(action, role) def self.allowed_to_role(action, role)
@@cached_perms_for_roles ||= @@cached_perms_for_roles ||=
begin begin
perms = {} perms = {}
find(:all, :include => :roles).each {|p| perms.store "#{p.controller}/#{p.action}", p.roles.collect {|r| r.id } } find(:all, :include => :roles).each {|p| perms.store "#{p.controller}/#{p.action}", p.roles.collect {|r| r.id } }
perms perms
end end
allowed_to_public(action) or (@@cached_perms_for_roles[action] and @@cached_perms_for_roles[action].include? role) allowed_to_public(action) or (@@cached_perms_for_roles[action] and @@cached_perms_for_roles[action].include? role)
end end
def self.allowed_to_role_expired def self.allowed_to_role_expired
@@cached_perms_for_roles = nil @@cached_perms_for_roles = nil
end end
end end

View File

@ -1,71 +1,71 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Project < ActiveRecord::Base class Project < ActiveRecord::Base
has_many :versions, :dependent => :destroy, :order => "versions.effective_date DESC, versions.name DESC" has_many :versions, :dependent => :destroy, :order => "versions.effective_date DESC, versions.name DESC"
has_many :members, :dependent => :delete_all, :include => :user, :conditions => "users.status=#{User::STATUS_ACTIVE}" has_many :members, :dependent => :delete_all, :include => :user, :conditions => "users.status=#{User::STATUS_ACTIVE}"
has_many :users, :through => :members has_many :users, :through => :members
has_many :custom_values, :dependent => :delete_all, :as => :customized has_many :custom_values, :dependent => :delete_all, :as => :customized
has_many :issues, :dependent => :destroy, :order => "issues.created_on DESC", :include => [:status, :tracker] has_many :issues, :dependent => :destroy, :order => "issues.created_on DESC", :include => [:status, :tracker]
has_many :queries, :dependent => :delete_all has_many :queries, :dependent => :delete_all
has_many :documents, :dependent => :destroy has_many :documents, :dependent => :destroy
has_many :news, :dependent => :delete_all, :include => :author has_many :news, :dependent => :delete_all, :include => :author
has_many :issue_categories, :dependent => :delete_all, :order => "issue_categories.name" has_many :issue_categories, :dependent => :delete_all, :order => "issue_categories.name"
has_one :repository, :dependent => :destroy has_one :repository, :dependent => :destroy
has_one :wiki, :dependent => :destroy has_one :wiki, :dependent => :destroy
has_and_belongs_to_many :custom_fields, :class_name => 'IssueCustomField', :join_table => 'custom_fields_projects', :association_foreign_key => 'custom_field_id' has_and_belongs_to_many :custom_fields, :class_name => 'IssueCustomField', :join_table => 'custom_fields_projects', :association_foreign_key => 'custom_field_id'
acts_as_tree :order => "name", :counter_cache => true acts_as_tree :order => "name", :counter_cache => true
validates_presence_of :name, :description validates_presence_of :name, :description
validates_uniqueness_of :name validates_uniqueness_of :name
validates_associated :custom_values, :on => :update validates_associated :custom_values, :on => :update
validates_associated :repository, :wiki validates_associated :repository, :wiki
validates_format_of :name, :with => /^[\w\s\'\-]*$/i validates_format_of :name, :with => /^[\w\s\'\-]*$/i
# returns latest created projects # returns latest created projects
# non public projects will be returned only if user is a member of those # non public projects will be returned only if user is a member of those
def self.latest(user=nil, count=5) def self.latest(user=nil, count=5)
find(:all, :limit => count, :conditions => visible_by(user), :order => "projects.created_on DESC") find(:all, :limit => count, :conditions => visible_by(user), :order => "projects.created_on DESC")
end end
def self.visible_by(user=nil) def self.visible_by(user=nil)
if user && !user.memberships.empty? if user && !user.memberships.empty?
return ["projects.is_public = ? or projects.id IN (#{user.memberships.collect{|m| m.project_id}.join(',')})", true] return ["projects.is_public = ? or projects.id IN (#{user.memberships.collect{|m| m.project_id}.join(',')})", true]
else else
return ["projects.is_public = ?", true] return ["projects.is_public = ?", true]
end end
end end
# Returns an array of all custom fields enabled for project issues # Returns an array of all custom fields enabled for project issues
# (explictly associated custom fields and custom fields enabled for all projects) # (explictly associated custom fields and custom fields enabled for all projects)
def custom_fields_for_issues(tracker) def custom_fields_for_issues(tracker)
tracker.custom_fields.find(:all, :include => :projects, tracker.custom_fields.find(:all, :include => :projects,
:conditions => ["is_for_all=? or project_id=?", true, self.id]) :conditions => ["is_for_all=? or project_id=?", true, self.id])
#(CustomField.for_all + custom_fields).uniq #(CustomField.for_all + custom_fields).uniq
end end
def all_custom_fields def all_custom_fields
@all_custom_fields ||= IssueCustomField.find(:all, :include => :projects, @all_custom_fields ||= IssueCustomField.find(:all, :include => :projects,
:conditions => ["is_for_all=? or project_id=?", true, self.id]) :conditions => ["is_for_all=? or project_id=?", true, self.id])
end end
protected protected
def validate def validate
errors.add(parent_id, " must be a root project") if parent and parent.parent 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 errors.add_to_base("A project with subprojects can't be a subproject") if parent and children.size > 0
end end
end end

View File

@ -1,22 +1,22 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class ProjectCustomField < CustomField class ProjectCustomField < CustomField
def type_name def type_name
:label_project_plural :label_project_plural
end end
end end

View File

@ -1,33 +1,33 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Role < ActiveRecord::Base class Role < ActiveRecord::Base
before_destroy :check_integrity before_destroy :check_integrity
has_and_belongs_to_many :permissions has_and_belongs_to_many :permissions
has_many :workflows, :dependent => :delete_all has_many :workflows, :dependent => :delete_all
has_many :members has_many :members
acts_as_list acts_as_list
validates_presence_of :name validates_presence_of :name
validates_uniqueness_of :name validates_uniqueness_of :name
validates_format_of :name, :with => /^[\w\s\'\-]*$/i validates_format_of :name, :with => /^[\w\s\'\-]*$/i
private private
def check_integrity def check_integrity
raise "Can't delete role" if Member.find(:first, :conditions =>["role_id=?", self.id]) raise "Can't delete role" if Member.find(:first, :conditions =>["role_id=?", self.id])
end end
end end

View File

@ -1,216 +1,216 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require 'rexml/document' require 'rexml/document'
module SvnRepos module SvnRepos
class CommandFailed < StandardError #:nodoc: class CommandFailed < StandardError #:nodoc:
end end
class Base class Base
def initialize(url, login=nil, password=nil) def initialize(url, login=nil, password=nil)
@url = url @url = url
@login = login if login && !login.empty? @login = login if login && !login.empty?
@password = (password || "") if @login @password = (password || "") if @login
end end
# Returns the entry identified by path and revision identifier # Returns the entry identified by path and revision identifier
# or nil if entry doesn't exist in the repository # or nil if entry doesn't exist in the repository
def entry(path=nil, identifier=nil) def entry(path=nil, identifier=nil)
e = entries(path, identifier) e = entries(path, identifier)
e ? e.first : nil e ? e.first : nil
end end
# Returns an Entries collection # Returns an Entries collection
# or nil if the given path doesn't exist in the repository # or nil if the given path doesn't exist in the repository
def entries(path=nil, identifier=nil) def entries(path=nil, identifier=nil)
path ||= '' path ||= ''
identifier = 'HEAD' unless identifier and identifier > 0 identifier = 'HEAD' unless identifier and identifier > 0
entries = Entries.new entries = Entries.new
cmd = "svn list --xml #{target(path)}@#{identifier}" cmd = "svn list --xml #{target(path)}@#{identifier}"
cmd << " --username #{@login} --password #{@password}" if @login cmd << " --username #{@login} --password #{@password}" if @login
shellout(cmd) do |io| shellout(cmd) do |io|
begin begin
doc = REXML::Document.new(io) doc = REXML::Document.new(io)
doc.elements.each("lists/list/entry") do |entry| doc.elements.each("lists/list/entry") do |entry|
entries << Entry.new({:name => entry.elements['name'].text, entries << Entry.new({:name => entry.elements['name'].text,
:path => ((path.empty? ? "" : "#{path}/") + entry.elements['name'].text), :path => ((path.empty? ? "" : "#{path}/") + entry.elements['name'].text),
:kind => entry.attributes['kind'], :kind => entry.attributes['kind'],
:size => (entry.elements['size'] and entry.elements['size'].text).to_i, :size => (entry.elements['size'] and entry.elements['size'].text).to_i,
:lastrev => Revision.new({ :lastrev => Revision.new({
:identifier => entry.elements['commit'].attributes['revision'], :identifier => entry.elements['commit'].attributes['revision'],
:time => Time.parse(entry.elements['commit'].elements['date'].text), :time => Time.parse(entry.elements['commit'].elements['date'].text),
:author => (entry.elements['commit'].elements['author'] ? entry.elements['commit'].elements['author'].text : "anonymous") :author => (entry.elements['commit'].elements['author'] ? entry.elements['commit'].elements['author'].text : "anonymous")
}) })
}) })
end end
rescue rescue
end end
end end
return nil if $? && $?.exitstatus != 0 return nil if $? && $?.exitstatus != 0
entries.sort_by_name entries.sort_by_name
rescue Errno::ENOENT => e rescue Errno::ENOENT => e
raise CommandFailed raise CommandFailed
end end
def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={}) def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={})
path ||= '' path ||= ''
identifier_from = 'HEAD' unless identifier_from and identifier_from.to_i > 0 identifier_from = 'HEAD' unless identifier_from and identifier_from.to_i > 0
identifier_to = 1 unless identifier_to and identifier_to.to_i > 0 identifier_to = 1 unless identifier_to and identifier_to.to_i > 0
revisions = Revisions.new revisions = Revisions.new
cmd = "svn log --xml -r #{identifier_from}:#{identifier_to}" cmd = "svn log --xml -r #{identifier_from}:#{identifier_to}"
cmd << " --username #{@login} --password #{@password}" if @login cmd << " --username #{@login} --password #{@password}" if @login
cmd << " --verbose " if options[:with_paths] cmd << " --verbose " if options[:with_paths]
cmd << target(path) cmd << target(path)
shellout(cmd) do |io| shellout(cmd) do |io|
begin begin
doc = REXML::Document.new(io) doc = REXML::Document.new(io)
doc.elements.each("log/logentry") do |logentry| doc.elements.each("log/logentry") do |logentry|
paths = [] paths = []
logentry.elements.each("paths/path") do |path| logentry.elements.each("paths/path") do |path|
paths << {:action => path.attributes['action'], paths << {:action => path.attributes['action'],
:path => path.text :path => path.text
} }
end end
paths.sort! { |x,y| x[:path] <=> y[:path] } paths.sort! { |x,y| x[:path] <=> y[:path] }
revisions << Revision.new({:identifier => logentry.attributes['revision'], revisions << Revision.new({:identifier => logentry.attributes['revision'],
:author => (logentry.elements['author'] ? logentry.elements['author'].text : "anonymous"), :author => (logentry.elements['author'] ? logentry.elements['author'].text : "anonymous"),
:time => Time.parse(logentry.elements['date'].text), :time => Time.parse(logentry.elements['date'].text),
:message => logentry.elements['msg'].text, :message => logentry.elements['msg'].text,
:paths => paths :paths => paths
}) })
end end
rescue rescue
end end
end end
return nil if $? && $?.exitstatus != 0 return nil if $? && $?.exitstatus != 0
revisions revisions
rescue Errno::ENOENT => e rescue Errno::ENOENT => e
raise CommandFailed raise CommandFailed
end end
def diff(path, identifier_from, identifier_to=nil) def diff(path, identifier_from, identifier_to=nil)
path ||= '' path ||= ''
if identifier_to and identifier_to.to_i > 0 if identifier_to and identifier_to.to_i > 0
identifier_to = identifier_to.to_i identifier_to = identifier_to.to_i
else else
identifier_to = identifier_from.to_i - 1 identifier_to = identifier_from.to_i - 1
end end
cmd = "svn diff -r " cmd = "svn diff -r "
cmd << "#{identifier_to}:" cmd << "#{identifier_to}:"
cmd << "#{identifier_from}" cmd << "#{identifier_from}"
cmd << "#{target(path)}@#{identifier_from}" cmd << "#{target(path)}@#{identifier_from}"
cmd << " --username #{@login} --password #{@password}" if @login cmd << " --username #{@login} --password #{@password}" if @login
diff = [] diff = []
shellout(cmd) do |io| shellout(cmd) do |io|
io.each_line do |line| io.each_line do |line|
diff << line diff << line
end end
end end
return nil if $? && $?.exitstatus != 0 return nil if $? && $?.exitstatus != 0
diff diff
rescue Errno::ENOENT => e rescue Errno::ENOENT => e
raise CommandFailed raise CommandFailed
end end
def cat(path, identifier=nil) def cat(path, identifier=nil)
identifier = (identifier and identifier.to_i > 0) ? identifier.to_i : "HEAD" identifier = (identifier and identifier.to_i > 0) ? identifier.to_i : "HEAD"
cmd = "svn cat #{target(path)}@#{identifier}" cmd = "svn cat #{target(path)}@#{identifier}"
cmd << " --username #{@login} --password #{@password}" if @login cmd << " --username #{@login} --password #{@password}" if @login
cat = nil cat = nil
shellout(cmd) do |io| shellout(cmd) do |io|
cat = io.read cat = io.read
end end
return nil if $? && $?.exitstatus != 0 return nil if $? && $?.exitstatus != 0
cat cat
rescue Errno::ENOENT => e rescue Errno::ENOENT => e
raise CommandFailed raise CommandFailed
end end
private private
def target(path) def target(path)
" \"" << "#{@url}/#{path}".gsub(/["'?<>\*]/, '') << "\"" " \"" << "#{@url}/#{path}".gsub(/["'?<>\*]/, '') << "\""
end end
def logger def logger
RAILS_DEFAULT_LOGGER RAILS_DEFAULT_LOGGER
end end
def shellout(cmd, &block) def shellout(cmd, &block)
logger.debug "Shelling out: #{cmd}" if logger && logger.debug? logger.debug "Shelling out: #{cmd}" if logger && logger.debug?
IO.popen(cmd, "r+") do |io| IO.popen(cmd, "r+") do |io|
io.close_write io.close_write
block.call(io) if block_given? block.call(io) if block_given?
end end
end end
end end
class Entries < Array class Entries < Array
def sort_by_name def sort_by_name
sort {|x,y| sort {|x,y|
if x.kind == y.kind if x.kind == y.kind
x.name <=> y.name x.name <=> y.name
else else
x.kind <=> y.kind x.kind <=> y.kind
end end
} }
end end
def revisions def revisions
revisions ||= Revisions.new(collect{|entry| entry.lastrev}) revisions ||= Revisions.new(collect{|entry| entry.lastrev})
end end
end end
class Entry class Entry
attr_accessor :name, :path, :kind, :size, :lastrev attr_accessor :name, :path, :kind, :size, :lastrev
def initialize(attributes={}) def initialize(attributes={})
self.name = attributes[:name] if attributes[:name] self.name = attributes[:name] if attributes[:name]
self.path = attributes[:path] if attributes[:path] self.path = attributes[:path] if attributes[:path]
self.kind = attributes[:kind] if attributes[:kind] self.kind = attributes[:kind] if attributes[:kind]
self.size = attributes[:size].to_i if attributes[:size] self.size = attributes[:size].to_i if attributes[:size]
self.lastrev = attributes[:lastrev] self.lastrev = attributes[:lastrev]
end end
def is_file? def is_file?
'file' == self.kind 'file' == self.kind
end end
def is_dir? def is_dir?
'dir' == self.kind 'dir' == self.kind
end end
end end
class Revisions < Array class Revisions < Array
def latest def latest
sort {|x,y| x.time <=> y.time}.last sort {|x,y| x.time <=> y.time}.last
end end
end end
class Revision class Revision
attr_accessor :identifier, :author, :time, :message, :paths attr_accessor :identifier, :author, :time, :message, :paths
def initialize(attributes={}) def initialize(attributes={})
self.identifier = attributes[:identifier] self.identifier = attributes[:identifier]
self.author = attributes[:author] self.author = attributes[:author]
self.time = attributes[:time] self.time = attributes[:time]
self.message = attributes[:message] || "" self.message = attributes[:message] || ""
self.paths = attributes[:paths] self.paths = attributes[:paths]
end end
end end
end end

View File

@ -1,33 +1,33 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Tracker < ActiveRecord::Base class Tracker < ActiveRecord::Base
before_destroy :check_integrity before_destroy :check_integrity
has_many :issues has_many :issues
has_many :workflows, :dependent => :delete_all has_many :workflows, :dependent => :delete_all
has_and_belongs_to_many :custom_fields, :class_name => 'IssueCustomField', :join_table => 'custom_fields_trackers', :association_foreign_key => 'custom_field_id' has_and_belongs_to_many :custom_fields, :class_name => 'IssueCustomField', :join_table => 'custom_fields_trackers', :association_foreign_key => 'custom_field_id'
acts_as_list acts_as_list
validates_presence_of :name validates_presence_of :name
validates_uniqueness_of :name validates_uniqueness_of :name
validates_format_of :name, :with => /^[\w\s\'\-]*$/i validates_format_of :name, :with => /^[\w\s\'\-]*$/i
private private
def check_integrity def check_integrity
raise "Can't delete tracker" if Issue.find(:first, :conditions => ["tracker_id=?", self.id]) raise "Can't delete tracker" if Issue.find(:first, :conditions => ["tracker_id=?", self.id])
end end
end end

View File

@ -1,142 +1,142 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang # Copyright (C) 2006-2007 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require "digest/sha1" require "digest/sha1"
class User < ActiveRecord::Base class User < ActiveRecord::Base
has_many :memberships, :class_name => 'Member', :include => [ :project, :role ], :dependent => :delete_all has_many :memberships, :class_name => 'Member', :include => [ :project, :role ], :dependent => :delete_all
has_many :projects, :through => :memberships has_many :projects, :through => :memberships
has_many :custom_values, :dependent => :delete_all, :as => :customized has_many :custom_values, :dependent => :delete_all, :as => :customized
has_one :preference, :dependent => :destroy, :class_name => 'UserPreference' has_one :preference, :dependent => :destroy, :class_name => 'UserPreference'
belongs_to :auth_source belongs_to :auth_source
attr_accessor :password, :password_confirmation attr_accessor :password, :password_confirmation
attr_accessor :last_before_login_on attr_accessor :last_before_login_on
# Prevents unauthorized assignments # Prevents unauthorized assignments
attr_protected :login, :admin, :password, :password_confirmation, :hashed_password attr_protected :login, :admin, :password, :password_confirmation, :hashed_password
validates_presence_of :login, :firstname, :lastname, :mail validates_presence_of :login, :firstname, :lastname, :mail
validates_uniqueness_of :login, :mail validates_uniqueness_of :login, :mail
# Login must contain lettres, numbers, underscores only # Login must contain lettres, numbers, underscores only
validates_format_of :firstname, :lastname, :with => /^[\w\s\'\-]*$/i validates_format_of :firstname, :lastname, :with => /^[\w\s\'\-]*$/i
validates_format_of :login, :with => /^[a-z0-9_\-@\.]+$/i validates_format_of :login, :with => /^[a-z0-9_\-@\.]+$/i
validates_format_of :mail, :with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i validates_format_of :mail, :with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i
# Password length between 4 and 12 # Password length between 4 and 12
validates_length_of :password, :in => 4..12, :allow_nil => true validates_length_of :password, :in => 4..12, :allow_nil => true
validates_confirmation_of :password, :allow_nil => true validates_confirmation_of :password, :allow_nil => true
validates_associated :custom_values, :on => :update validates_associated :custom_values, :on => :update
# Account statuses # Account statuses
STATUS_ACTIVE = 1 STATUS_ACTIVE = 1
STATUS_REGISTERED = 2 STATUS_REGISTERED = 2
STATUS_LOCKED = 3 STATUS_LOCKED = 3
def before_save def before_save
# update hashed_password if password was set # update hashed_password if password was set
self.hashed_password = User.hash_password(self.password) if self.password self.hashed_password = User.hash_password(self.password) if self.password
end end
def self.active def self.active
with_scope :find => { :conditions => [ "status = ?", STATUS_ACTIVE ] } do with_scope :find => { :conditions => [ "status = ?", STATUS_ACTIVE ] } do
yield yield
end end
end end
def self.find_active(*args) def self.find_active(*args)
active do active do
find(*args) find(*args)
end end
end end
# Returns the user that matches provided login and password, or nil # Returns the user that matches provided login and password, or nil
def self.try_to_login(login, password) def self.try_to_login(login, password)
user = find(:first, :conditions => ["login=?", login]) user = find(:first, :conditions => ["login=?", login])
if user if user
# user is already in local database # user is already in local database
return nil if !user.active? return nil if !user.active?
if user.auth_source if user.auth_source
# user has an external authentication method # user has an external authentication method
return nil unless user.auth_source.authenticate(login, password) return nil unless user.auth_source.authenticate(login, password)
else else
# authentication with local password # authentication with local password
return nil unless User.hash_password(password) == user.hashed_password return nil unless User.hash_password(password) == user.hashed_password
end end
else else
# user is not yet registered, try to authenticate with available sources # user is not yet registered, try to authenticate with available sources
attrs = AuthSource.authenticate(login, password) attrs = AuthSource.authenticate(login, password)
if attrs if attrs
onthefly = new(*attrs) onthefly = new(*attrs)
onthefly.login = login onthefly.login = login
onthefly.language = Setting.default_language onthefly.language = Setting.default_language
if onthefly.save if onthefly.save
user = find(:first, :conditions => ["login=?", login]) user = find(:first, :conditions => ["login=?", login])
logger.info("User '#{user.login}' created on the fly.") if logger logger.info("User '#{user.login}' created on the fly.") if logger
end end
end end
end end
user.update_attribute(:last_login_on, Time.now) if user user.update_attribute(:last_login_on, Time.now) if user
user user
rescue => text rescue => text
raise text raise text
end end
# Return user's full name for display # Return user's full name for display
def display_name def display_name
firstname + " " + lastname firstname + " " + lastname
end end
def name def name
display_name display_name
end end
def active? def active?
self.status == STATUS_ACTIVE self.status == STATUS_ACTIVE
end end
def registered? def registered?
self.status == STATUS_REGISTERED self.status == STATUS_REGISTERED
end end
def locked? def locked?
self.status == STATUS_LOCKED self.status == STATUS_LOCKED
end end
def check_password?(clear_password) def check_password?(clear_password)
User.hash_password(clear_password) == self.hashed_password User.hash_password(clear_password) == self.hashed_password
end end
def role_for_project(project_id) def role_for_project(project_id)
@role_for_projects ||= @role_for_projects ||=
begin begin
roles = {} roles = {}
self.memberships.each { |m| roles.store m.project_id, m.role_id } self.memberships.each { |m| roles.store m.project_id, m.role_id }
roles roles
end end
@role_for_projects[project_id] @role_for_projects[project_id]
end end
def pref def pref
self.preference ||= UserPreference.new(:user => self) self.preference ||= UserPreference.new(:user => self)
end end
private private
# Return password digest # Return password digest
def self.hash_password(clear_password) def self.hash_password(clear_password)
Digest::SHA1.hexdigest(clear_password || "") Digest::SHA1.hexdigest(clear_password || "")
end end
end end

View File

@ -1,23 +1,23 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class UserCustomField < CustomField class UserCustomField < CustomField
def type_name def type_name
:label_user_plural :label_user_plural
end end
end end

View File

@ -1,32 +1,32 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Version < ActiveRecord::Base class Version < ActiveRecord::Base
before_destroy :check_integrity before_destroy :check_integrity
belongs_to :project belongs_to :project
has_many :fixed_issues, :class_name => 'Issue', :foreign_key => 'fixed_version_id' has_many :fixed_issues, :class_name => 'Issue', :foreign_key => 'fixed_version_id'
has_many :attachments, :as => :container, :dependent => :destroy has_many :attachments, :as => :container, :dependent => :destroy
validates_presence_of :name validates_presence_of :name
validates_uniqueness_of :name, :scope => [:project_id] validates_uniqueness_of :name, :scope => [:project_id]
validates_format_of :effective_date, :with => /^\d{4}-\d{2}-\d{2}$/, :message => :activerecord_error_not_a_date validates_format_of :effective_date, :with => /^\d{4}-\d{2}-\d{2}$/, :message => :activerecord_error_not_a_date
private private
def check_integrity def check_integrity
raise "Can't delete version" if self.fixed_issues.find(:first) raise "Can't delete version" if self.fixed_issues.find(:first)
end end
end end

View File

@ -1,24 +1,24 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Workflow < ActiveRecord::Base class Workflow < ActiveRecord::Base
belongs_to :role belongs_to :role
belongs_to :old_status, :class_name => 'IssueStatus', :foreign_key => 'old_status_id' belongs_to :old_status, :class_name => 'IssueStatus', :foreign_key => 'old_status_id'
belongs_to :new_status, :class_name => 'IssueStatus', :foreign_key => 'new_status_id' belongs_to :new_status, :class_name => 'IssueStatus', :foreign_key => 'new_status_id'
validates_presence_of :role, :old_status, :new_status validates_presence_of :role, :old_status, :new_status
end end

View File

@ -1,24 +1,24 @@
<center> <center>
<div class="box login"> <div class="box login">
<h2 class="icon22 icon22-authent"><%=l(:label_please_login)%></h2> <h2 class="icon22 icon22-authent"><%=l(:label_please_login)%></h2>
<% form_tag({:action=> "login"}, :class => "tabular") do %>
<p><label for="login"><%=l(:field_login)%>:</label>
<%= text_field_tag 'login', nil, :size => 25 %></p>
<p><label for="password"><%=l(:field_password)%>:</label>
<%= password_field_tag 'password', nil, :size => 25 %></p>
<p><center><input type="submit" name="login" value="<%=l(:button_login)%> &#187;" class="primary" /></center>
<% end %>
<br>
<% links = []
links << link_to(l(:label_register), :action => 'register') if Setting.self_registration?
links << link_to(l(:label_password_lost), :action => 'lost_password') if Setting.lost_password?
%>
<%= links.join(" | ") %>
</p>
</div> <% form_tag({:action=> "login"}, :class => "tabular") do %>
<p><label for="login"><%=l(:field_login)%>:</label>
<%= text_field_tag 'login', nil, :size => 25 %></p>
<p><label for="password"><%=l(:field_password)%>:</label>
<%= password_field_tag 'password', nil, :size => 25 %></p>
<p><center><input type="submit" name="login" value="<%=l(:button_login)%> &#187;" class="primary" /></center>
<% end %>
<br>
<% links = []
links << link_to(l(:label_register), :action => 'register') if Setting.self_registration?
links << link_to(l(:label_password_lost), :action => 'lost_password') if Setting.lost_password?
%>
<%= links.join(" | ") %>
</p>
</div>
</center> </center>

View File

@ -1,14 +1,14 @@
<center> <center>
<div class="box login"> <div class="box login">
<h2><%=l(:label_password_lost)%></h2> <h2><%=l(:label_password_lost)%></h2>
<% form_tag({:action=> "lost_password"}, :class => "tabular") do %> <% form_tag({:action=> "lost_password"}, :class => "tabular") do %>
<p><label for="mail"><%=l(:field_mail)%> <span class="required">*</span></label> <p><label for="mail"><%=l(:field_mail)%> <span class="required">*</span></label>
<%= text_field_tag 'mail', nil, :size => 40 %></p> <%= text_field_tag 'mail', nil, :size => 40 %></p>
<p><center><%= submit_tag l(:button_submit) %></center></p> <p><center><%= submit_tag l(:button_submit) %></center></p>
<% end %> <% end %>
</div> </div>
</center> </center>

View File

@ -1,21 +1,21 @@
<center> <center>
<div class="box login"> <div class="box login">
<h2><%=l(:label_password_lost)%></h2> <h2><%=l(:label_password_lost)%></h2>
<p><%=l(:field_login)%>: <strong><%= @user.login %></strong><br /> <p><%=l(:field_login)%>: <strong><%= @user.login %></strong><br />
<%= error_messages_for 'user' %> <%= error_messages_for 'user' %>
<% form_tag({:token => @token.value}, :class => "tabular") do %> <% form_tag({:token => @token.value}, :class => "tabular") do %>
<p><label for="new_password"><%=l(:field_new_password)%> <span class="required">*</span></label> <p><label for="new_password"><%=l(:field_new_password)%> <span class="required">*</span></label>
<%= password_field_tag 'new_password', nil, :size => 25 %></p> <%= password_field_tag 'new_password', nil, :size => 25 %></p>
<p><label for="new_password_confirmation"><%=l(:field_password_confirmation)%> <span class="required">*</span></label> <p><label for="new_password_confirmation"><%=l(:field_password_confirmation)%> <span class="required">*</span></label>
<%= password_field_tag 'new_password_confirmation', nil, :size => 25 %></p> <%= password_field_tag 'new_password_confirmation', nil, :size => 25 %></p>
<p><center><%= submit_tag l(:button_save) %></center></p> <p><center><%= submit_tag l(:button_save) %></center></p>
<% end %> <% end %>
</div> </div>
</center> </center>

View File

@ -7,7 +7,7 @@
<!--[form:user]--> <!--[form:user]-->
<p><label for="user_login"><%=l(:field_login)%> <span class="required">*</span></label> <p><label for="user_login"><%=l(:field_login)%> <span class="required">*</span></label>
<%= text_field 'user', 'login', :size => 25 %></p> <%= text_field 'user', 'login', :size => 25 %></p>
<p><label for="password"><%=l(:field_password)%> <span class="required">*</span></label> <p><label for="password"><%=l(:field_password)%> <span class="required">*</span></label>
<%= password_field_tag 'password', nil, :size => 25 %></p> <%= password_field_tag 'password', nil, :size => 25 %></p>
@ -16,22 +16,22 @@
<p><label for="user_firstname"><%=l(:field_firstname)%> <span class="required">*</span></label> <p><label for="user_firstname"><%=l(:field_firstname)%> <span class="required">*</span></label>
<%= text_field 'user', 'firstname' %></p> <%= text_field 'user', 'firstname' %></p>
<p><label for="user_lastname"><%=l(:field_lastname)%> <span class="required">*</span></label> <p><label for="user_lastname"><%=l(:field_lastname)%> <span class="required">*</span></label>
<%= text_field 'user', 'lastname' %></p> <%= text_field 'user', 'lastname' %></p>
<p><label for="user_mail"><%=l(:field_mail)%> <span class="required">*</span></label> <p><label for="user_mail"><%=l(:field_mail)%> <span class="required">*</span></label>
<%= text_field 'user', 'mail' %></p> <%= text_field 'user', 'mail' %></p>
<p><label for="user_language"><%=l(:field_language)%></label> <p><label for="user_language"><%=l(:field_language)%></label>
<%= select("user", "language", lang_options_for_select) %></p> <%= select("user", "language", lang_options_for_select) %></p>
<% for @custom_value in @custom_values %> <% for @custom_value in @custom_values %>
<p><%= custom_field_tag_with_label @custom_value %></p> <p><%= custom_field_tag_with_label @custom_value %></p>
<% end %> <% end %>
<p><label for="user_mail_notification"><%=l(:field_mail_notification)%></label> <p><label for="user_mail_notification"><%=l(:field_mail_notification)%></label>
<%= check_box 'user', 'mail_notification' %></p> <%= check_box 'user', 'mail_notification' %></p>
<!--[eoform:user]--> <!--[eoform:user]-->
</div> </div>

View File

@ -1,26 +1,26 @@
<h2><%= @user.display_name %></h2> <h2><%= @user.display_name %></h2>
<p> <p>
<%= mail_to @user.mail unless @user.pref.hide_mail %> <%= mail_to @user.mail unless @user.pref.hide_mail %>
<ul> <ul>
<li><%=l(:label_registered_on)%>: <%= format_date(@user.created_on) %></li> <li><%=l(:label_registered_on)%>: <%= format_date(@user.created_on) %></li>
<% for custom_value in @custom_values %> <% for custom_value in @custom_values %>
<% if !custom_value.value.empty? %> <% if !custom_value.value.empty? %>
<li><%= custom_value.custom_field.name%>: <%=h show_value(custom_value) %></li> <li><%= custom_value.custom_field.name%>: <%=h show_value(custom_value) %></li>
<% end %> <% end %>
<% end %> <% end %>
</ul> </ul>
</p> </p>
<h3><%=l(:label_project_plural)%></h3> <h3><%=l(:label_project_plural)%></h3>
<p> <p>
<% for membership in @user.memberships %> <% for membership in @user.memberships %>
<%= membership.project.name %> (<%= membership.role.name %>, <%= format_date(membership.created_on) %>) <%= membership.project.name %> (<%= membership.role.name %>, <%= format_date(membership.created_on) %>)
<br /> <br />
<% end %> <% end %>
</p> </p>
<h3><%=l(:label_activity)%></h3> <h3><%=l(:label_activity)%></h3>
<p> <p>
<%=l(:label_reported_issues)%>: <%= Issue.count(["author_id=?", @user.id]) %> <%=l(:label_reported_issues)%>: <%= Issue.count(["author_id=?", @user.id]) %>
</p> </p>

View File

@ -1,45 +1,45 @@
<h2><%=l(:label_administration)%></h2> <h2><%=l(:label_administration)%></h2>
<p class="icon22 icon22-projects"> <p class="icon22 icon22-projects">
<%= link_to l(:label_project_plural), :controller => 'admin', :action => 'projects' %> | <%= link_to l(:label_project_plural), :controller => 'admin', :action => 'projects' %> |
<%= link_to l(:label_new), :controller => 'projects', :action => 'add' %> <%= link_to l(:label_new), :controller => 'projects', :action => 'add' %>
</p> </p>
<p class="icon22 icon22-users"> <p class="icon22 icon22-users">
<%= link_to l(:label_user_plural), :controller => 'users' %> | <%= link_to l(:label_user_plural), :controller => 'users' %> |
<%= link_to l(:label_new), :controller => 'users', :action => 'add' %> <%= link_to l(:label_new), :controller => 'users', :action => 'add' %>
</p> </p>
<p class="icon22 icon22-role"> <p class="icon22 icon22-role">
<%= link_to l(:label_role_and_permissions), :controller => 'roles' %> <%= link_to l(:label_role_and_permissions), :controller => 'roles' %>
</p> </p>
<p class="icon22 icon22-tracker"> <p class="icon22 icon22-tracker">
<%= link_to l(:label_tracker_plural), :controller => 'trackers' %> | <%= link_to l(:label_tracker_plural), :controller => 'trackers' %> |
<%= link_to l(:label_issue_status_plural), :controller => 'issue_statuses' %> | <%= link_to l(:label_issue_status_plural), :controller => 'issue_statuses' %> |
<%= link_to l(:label_workflow), :controller => 'roles', :action => 'workflow' %> <%= link_to l(:label_workflow), :controller => 'roles', :action => 'workflow' %>
</p> </p>
<p class="icon22 icon22-workflow"> <p class="icon22 icon22-workflow">
<%= link_to l(:label_custom_field_plural), :controller => 'custom_fields' %> <%= link_to l(:label_custom_field_plural), :controller => 'custom_fields' %>
</p> </p>
<p class="icon22 icon22-options"> <p class="icon22 icon22-options">
<%= link_to l(:label_enumerations), :controller => 'enumerations' %> <%= link_to l(:label_enumerations), :controller => 'enumerations' %>
</p> </p>
<p class="icon22 icon22-notifications"> <p class="icon22 icon22-notifications">
<%= link_to l(:field_mail_notification), :controller => 'admin', :action => 'mail_options' %> <%= link_to l(:field_mail_notification), :controller => 'admin', :action => 'mail_options' %>
</p> </p>
<p class="icon22 icon22-authent"> <p class="icon22 icon22-authent">
<%= link_to l(:label_authentication), :controller => 'auth_sources' %> <%= link_to l(:label_authentication), :controller => 'auth_sources' %>
</p> </p>
<p class="icon22 icon22-settings"> <p class="icon22 icon22-settings">
<%= link_to l(:label_settings), :controller => 'settings' %> <%= link_to l(:label_settings), :controller => 'settings' %>
</p> </p>
<p class="icon22 icon22-info"> <p class="icon22 icon22-info">
<%= link_to l(:label_information_plural), :controller => 'admin', :action => 'info' %> <%= link_to l(:label_information_plural), :controller => 'admin', :action => 'info' %>
</p> </p>

View File

@ -1,3 +1,3 @@
<h2><%=l(:label_information_plural)%></h2> <h2><%=l(:label_information_plural)%></h2>
<p><%=l(:field_version)%>: <strong>redMine <%= Redmine::VERSION %></strong> (<%= @db_adapter_name %>)</p> <p><%=l(:field_version)%>: <strong>redMine <%= Redmine::VERSION %></strong> (<%= @db_adapter_name %>)</p>

View File

@ -1,25 +1,25 @@
<h2><%=l(:field_mail_notification)%></h2> <h2><%=l(:field_mail_notification)%></h2>
<% form_tag ({:action => 'mail_options'}, :id => 'mail_options_form') do %> <% form_tag ({:action => 'mail_options'}, :id => 'mail_options_form') do %>
<div class="box"> <div class="box">
<p><%=l(:text_select_mail_notifications)%></p> <p><%=l(:text_select_mail_notifications)%></p>
<% actions = @actions.group_by {|p| p.group_id } %> <% actions = @actions.group_by {|p| p.group_id } %>
<% actions.keys.sort.each do |group_id| %> <% actions.keys.sort.each do |group_id| %>
<fieldset style="margin-top: 6px;"><legend><strong><%= l(Permission::GROUPS[group_id]) %></strong></legend> <fieldset style="margin-top: 6px;"><legend><strong><%= l(Permission::GROUPS[group_id]) %></strong></legend>
<% actions[group_id].each do |p| %> <% actions[group_id].each do |p| %>
<div style="width:170px;float:left;"><%= check_box_tag "action_ids[]", p.id, p.mail_enabled? %> <div style="width:170px;float:left;"><%= check_box_tag "action_ids[]", p.id, p.mail_enabled? %>
<%= l(p.description.to_sym) %> <%= l(p.description.to_sym) %>
</div> </div>
<% end %> <% end %>
<div class="clear"></div> <div class="clear"></div>
</fieldset> </fieldset>
<% end %> <% end %>
<br /> <br />
<p><%= check_all_links 'mail_options_form' %></p> <p><%= check_all_links 'mail_options_form' %></p>
</div> </div>
<%= submit_tag l(:button_save) %> <%= submit_tag l(:button_save) %>
<% end %> <% end %>

View File

@ -6,24 +6,24 @@
<table class="list"> <table class="list">
<thead><tr> <thead><tr>
<%= sort_header_tag('name', :caption => l(:label_project)) %> <%= sort_header_tag('name', :caption => l(:label_project)) %>
<th><%=l(:field_description)%></th> <th><%=l(:field_description)%></th>
<th><%=l(:field_is_public)%></th> <th><%=l(:field_is_public)%></th>
<th><%=l(:label_subproject_plural)%></th> <th><%=l(:label_subproject_plural)%></th>
<%= sort_header_tag('created_on', :caption => l(:field_created_on)) %> <%= sort_header_tag('created_on', :caption => l(:field_created_on)) %>
<th></th> <th></th>
</tr></thead> </tr></thead>
<tbody> <tbody>
<% for project in @projects %> <% for project in @projects %>
<tr class="<%= cycle("odd", "even") %>"> <tr class="<%= cycle("odd", "even") %>">
<td><%= link_to project.name, :controller => 'projects', :action => 'settings', :id => project %> <td><%= link_to project.name, :controller => 'projects', :action => 'settings', :id => project %>
<td><%=h project.description %> <td><%=h project.description %>
<td align="center"><%= image_tag 'true.png' if project.is_public? %> <td align="center"><%= image_tag 'true.png' if project.is_public? %>
<td align="center"><%= project.children.size %> <td align="center"><%= project.children.size %>
<td align="center"><%= format_date(project.created_on) %> <td align="center"><%= format_date(project.created_on) %>
<td align="center"> <td align="center">
<%= button_to l(:button_delete), { :controller => 'projects', :action => 'destroy', :id => project }, :class => "button-small" %> <%= button_to l(:button_delete), { :controller => 'projects', :action => 'destroy', :id => project }, :class => "button-small" %>
</td> </td>
</tr> </tr>
<% end %> <% end %>
</tbody> </tbody>

View File

@ -1,4 +1,4 @@
<h2>404</h2> <h2>404</h2>
<p><%= l(:notice_file_not_found) %></p> <p><%= l(:notice_file_not_found) %></p>
<p><a href="javascript:history.back()">Back</a></p> <p><a href="javascript:history.back()">Back</a></p>

View File

@ -57,30 +57,30 @@ function deleteValueField(e) {
<!--[form:custom_field]--> <!--[form:custom_field]-->
<div class="box"> <div class="box">
<p><%= f.text_field :name, :required => true %></p> <p><%= f.text_field :name, :required => true %></p>
<p><%= f.select :field_format, custom_field_formats_for_select, {}, :onchange => "toggle_custom_field_format();" %></p> <p><%= f.select :field_format, custom_field_formats_for_select, {}, :onchange => "toggle_custom_field_format();" %></p>
<p><label for="custom_field_min_length"><%=l(:label_min_max_length)%></label> <p><label for="custom_field_min_length"><%=l(:label_min_max_length)%></label>
<%= f.text_field :min_length, :size => 5, :no_label => true %> - <%= f.text_field :min_length, :size => 5, :no_label => true %> -
<%= f.text_field :max_length, :size => 5, :no_label => true %><br>(<%=l(:text_min_max_length_info)%>)</p> <%= f.text_field :max_length, :size => 5, :no_label => true %><br>(<%=l(:text_min_max_length_info)%>)</p>
<p><%= f.text_field :regexp, :size => 50 %><br>(<%=l(:text_regexp_info)%>)</p> <p><%= f.text_field :regexp, :size => 50 %><br>(<%=l(:text_regexp_info)%>)</p>
<p id="custom_field_possible_values"><label><%= l(:field_possible_values) %> <%= image_to_function "add.png", "addValueField();return false" %></label> <p id="custom_field_possible_values"><label><%= l(:field_possible_values) %> <%= image_to_function "add.png", "addValueField();return false" %></label>
<% (@custom_field.possible_values.to_a + [""]).each do |value| %> <% (@custom_field.possible_values.to_a + [""]).each do |value| %>
<span><%= text_field_tag 'custom_field[possible_values][]', value, :size => 30 %> <%= image_to_function "delete.png", "deleteValueField(this);return false" %><br /></span> <span><%= text_field_tag 'custom_field[possible_values][]', value, :size => 30 %> <%= image_to_function "delete.png", "deleteValueField(this);return false" %><br /></span>
<% end %> <% end %>
</p> </p>
</div> </div>
<%= javascript_tag "toggle_custom_field_format();" %> <%= javascript_tag "toggle_custom_field_format();" %>
<!--[eoform:custom_field]--> <!--[eoform:custom_field]-->
<div class="box"> <div class="box">
<% case @custom_field.type.to_s <% case @custom_field.type.to_s
when "IssueCustomField" %> when "IssueCustomField" %>
<fieldset><legend><%=l(:label_tracker_plural)%></legend> <fieldset><legend><%=l(:label_tracker_plural)%></legend>
<% for tracker in @trackers %> <% for tracker in @trackers %>
<%= check_box_tag "tracker_ids[]", tracker.id, (@custom_field.trackers.include? tracker) %> <%= tracker.name %> <%= check_box_tag "tracker_ids[]", tracker.id, (@custom_field.trackers.include? tracker) %> <%= tracker.name %>
<% end %> <% end %>
</fieldset> </fieldset>
&nbsp; &nbsp;
<p><%= f.check_box :is_required %></p> <p><%= f.check_box :is_required %></p>
<p><%= f.check_box :is_for_all %></p> <p><%= f.check_box :is_for_all %></p>

View File

@ -6,29 +6,29 @@
<li><%= link_to l(:label_project_plural), {}, :id=> "tab-ProjectCustomField", :onclick => "showTab('ProjectCustomField'); this.blur(); return false;" %></li> <li><%= link_to l(:label_project_plural), {}, :id=> "tab-ProjectCustomField", :onclick => "showTab('ProjectCustomField'); this.blur(); return false;" %></li>
<li><%= link_to l(:label_user_plural), {}, :id=> "tab-UserCustomField", :onclick => "showTab('UserCustomField'); this.blur(); return false;" %></li> <li><%= link_to l(:label_user_plural), {}, :id=> "tab-UserCustomField", :onclick => "showTab('UserCustomField'); this.blur(); return false;" %></li>
</ul> </ul>
</div> </div>
<% %w(IssueCustomField ProjectCustomField UserCustomField).each do |type| %> <% %w(IssueCustomField ProjectCustomField UserCustomField).each do |type| %>
<div id="tab-content-<%= type %>" class="tab-content"> <div id="tab-content-<%= type %>" class="tab-content">
<table class="list"> <table class="list">
<thead><tr> <thead><tr>
<th width="30%"><%=l(:field_name)%></th> <th width="30%"><%=l(:field_name)%></th>
<th><%=l(:field_field_format)%></th> <th><%=l(:field_field_format)%></th>
<th><%=l(:field_is_required)%></th> <th><%=l(:field_is_required)%></th>
<% if type == 'IssueCustomField' %> <% if type == 'IssueCustomField' %>
<th><%=l(:field_is_for_all)%></th> <th><%=l(:field_is_for_all)%></th>
<th><%=l(:label_used_by)%></th> <th><%=l(:label_used_by)%></th>
<% end %> <% end %>
<th width="10%"></th> <th width="10%"></th>
</tr></thead> </tr></thead>
<tbody> <tbody>
<% for custom_field in (@custom_fields_by_type[type] || []) %> <% for custom_field in (@custom_fields_by_type[type] || []) %>
<tr class="<%= cycle("odd", "even") %>"> <tr class="<%= cycle("odd", "even") %>">
<td><%= link_to custom_field.name, :action => 'edit', :id => custom_field %></td> <td><%= link_to custom_field.name, :action => 'edit', :id => custom_field %></td>
<td align="center"><%= l(CustomField::FIELD_FORMATS[custom_field.field_format][:name]) %></td> <td align="center"><%= l(CustomField::FIELD_FORMATS[custom_field.field_format][:name]) %></td>
<td align="center"><%= image_tag 'true.png' if custom_field.is_required? %></td> <td align="center"><%= image_tag 'true.png' if custom_field.is_required? %></td>
<% if type == 'IssueCustomField' %> <% if type == 'IssueCustomField' %>
<td align="center"><%= image_tag 'true.png' if custom_field.is_for_all? %></td> <td align="center"><%= image_tag 'true.png' if custom_field.is_for_all? %></td>
<td align="center"><%= custom_field.projects.count.to_s + ' ' + lwr(:label_project, custom_field.projects.count) if custom_field.is_a? IssueCustomField and !custom_field.is_for_all? %></td> <td align="center"><%= custom_field.projects.count.to_s + ' ' + lwr(:label_project, custom_field.projects.count) if custom_field.is_a? IssueCustomField and !custom_field.is_for_all? %></td>
<% end %> <% end %>
<td align="center"> <td align="center">

View File

@ -1,3 +1,3 @@
<p><%= link_to h(document.title), :controller => 'documents', :action => 'show', :id => document %><br /> <p><%= link_to h(document.title), :controller => 'documents', :action => 'show', :id => document %><br />
<% unless document.description.empty? %><%=h(truncate(document.description, 250)) %><br /><% end %> <% unless document.description.empty? %><%=h(truncate(document.description, 250)) %><br /><% end %>
<em><%= format_time(document.created_on) %></em></p> <em><%= format_time(document.created_on) %></em></p>

View File

@ -1,11 +1,11 @@
<%= error_messages_for 'document' %> <%= error_messages_for 'document' %>
<div class="box"> <div class="box">
<!--[form:document]--> <!--[form:document]-->
<p><label for="document_category_id"><%=l(:field_category)%></label> <p><label for="document_category_id"><%=l(:field_category)%></label>
<select name="document[category_id]"> <select name="document[category_id]">
<%= options_from_collection_for_select @categories, "id", "name", @document.category_id %> <%= options_from_collection_for_select @categories, "id", "name", @document.category_id %>
</select></p> </select></p>
<p><label for="document_title"><%=l(:field_title)%> <span class="required">*</span></label> <p><label for="document_title"><%=l(:field_title)%> <span class="required">*</span></label>
<%= text_field 'document', 'title', :size => 60 %></p> <%= text_field 'document', 'title', :size => 60 %></p>

View File

@ -1,37 +1,37 @@
<div class="contextual"> <div class="contextual">
<%= link_to_if_authorized l(:button_edit), {:controller => 'documents', :action => 'edit', :id => @document}, :class => 'icon icon-edit' %> <%= link_to_if_authorized l(:button_edit), {:controller => 'documents', :action => 'edit', :id => @document}, :class => 'icon icon-edit' %>
<%= link_to_if_authorized l(:button_delete), {:controller => 'documents', :action => 'destroy', :id => @document}, :confirm => l(:text_are_you_sure), :method => :post, :class => 'icon icon-del' %> <%= link_to_if_authorized l(:button_delete), {:controller => 'documents', :action => 'destroy', :id => @document}, :confirm => l(:text_are_you_sure), :method => :post, :class => 'icon icon-del' %>
</div> </div>
<h2><%= @document.title %></h2> <h2><%= @document.title %></h2>
<p><em><%= @document.category.name %><br /> <p><em><%= @document.category.name %><br />
<%= format_date @document.created_on %></em></p> <%= format_date @document.created_on %></em></p>
<%= textilizable @document.description %> <%= textilizable @document.description %>
<br /> <br />
<h3><%= l(:label_attachment_plural) %></h3> <h3><%= l(:label_attachment_plural) %></h3>
<ul class="documents"> <ul class="documents">
<% for attachment in @attachments %> <% for attachment in @attachments %>
<li> <li>
<div class="contextual"> <div class="contextual">
<%= link_to_if_authorized l(:button_delete), {:controller => 'documents', :action => 'destroy_attachment', :id => @document, :attachment_id => attachment}, :confirm => l(:text_are_you_sure), :method => :post, :class => 'icon icon-del' %> <%= link_to_if_authorized l(:button_delete), {:controller => 'documents', :action => 'destroy_attachment', :id => @document, :attachment_id => attachment}, :confirm => l(:text_are_you_sure), :method => :post, :class => 'icon icon-del' %>
</div> </div>
<%= link_to attachment.filename, :action => 'download', :id => @document, :attachment_id => attachment %> <%= link_to attachment.filename, :action => 'download', :id => @document, :attachment_id => attachment %>
(<%= number_to_human_size attachment.filesize %>)<br /> (<%= number_to_human_size attachment.filesize %>)<br />
<em><%= attachment.author.display_name %>, <%= format_date(attachment.created_on) %></em><br /> <em><%= attachment.author.display_name %>, <%= format_date(attachment.created_on) %></em><br />
<%= lwr(:label_download, attachment.downloads) %> <%= lwr(:label_download, attachment.downloads) %>
</li> </li>
<% end %>
</ul>
<br />
<% if authorize_for('documents', 'add_attachment') %>
<% form_tag ({ :controller => 'documents', :action => 'add_attachment', :id => @document }, :multipart => true, :class => "tabular") do %>
<p id="attachments_p"><label for="attachment_file"><%=l(:label_attachment)%>
<%= image_to_function "add.png", "addFileField();return false" %></label>
<%= file_field_tag 'attachments[]', :size => 30 %> <em>(<%= l(:label_max_size) %>: <%= number_to_human_size(Setting.attachment_max_size.to_i.kilobytes) %>)</em></p>
<%= submit_tag l(:button_add) %>
<% end %>
<% end %> <% end %>
</ul>
<br />
<% if authorize_for('documents', 'add_attachment') %>
<% form_tag ({ :controller => 'documents', :action => 'add_attachment', :id => @document }, :multipart => true, :class => "tabular") do %>
<p id="attachments_p"><label for="attachment_file"><%=l(:label_attachment)%>
<%= image_to_function "add.png", "addFileField();return false" %></label>
<%= file_field_tag 'attachments[]', :size => 30 %> <em>(<%= l(:label_max_size) %>: <%= number_to_human_size(Setting.attachment_max_size.to_i.kilobytes) %>)</em></p>
<%= submit_tag l(:button_add) %>
<% end %>
<% end %>

View File

@ -1,19 +1,19 @@
<h2><%=l(:label_enumerations)%></h2> <h2><%=l(:label_enumerations)%></h2>
&nbsp; &nbsp;
<% Enumeration::OPTIONS.each do |option, name| %> <% Enumeration::OPTIONS.each do |option, name| %>
<% if params[:opt]==option %> <% if params[:opt]==option %>
<h3><%= l(name) %></h3> <h3><%= l(name) %></h3>
<ul> <ul>
<% for value in Enumeration.find(:all, :conditions => ["opt = ?", option]) %> <% for value in Enumeration.find(:all, :conditions => ["opt = ?", option]) %>
<li><%= link_to value.name, :action => 'edit', :id => value %></li> <li><%= link_to value.name, :action => 'edit', :id => value %></li>
<% end %> <% end %>
</ul> </ul>
<p><%= link_to l(:label_enumeration_new), { :action => 'new', :opt => option }, :class => "icon icon-add" %></p>&nbsp; <p><%= link_to l(:label_enumeration_new), { :action => 'new', :opt => option }, :class => "icon icon-add" %></p>&nbsp;
<% else %> <% else %>
<h3><%= link_to l(name), :opt => option %></h3> <h3><%= link_to l(name), :opt => option %></h3>
<% end %> <% end %>
<% end %> <% end %>

View File

@ -6,13 +6,13 @@
<%= text_field 'issue_status', 'name' %></p> <%= text_field 'issue_status', 'name' %></p>
<p><label for="issue_status_is_closed"><%=l(:field_is_closed)%></label> <p><label for="issue_status_is_closed"><%=l(:field_is_closed)%></label>
<%= check_box 'issue_status', 'is_closed' %></p> <%= check_box 'issue_status', 'is_closed' %></p>
<p><label for="issue_status_is_default"><%=l(:field_is_default)%></label> <p><label for="issue_status_is_default"><%=l(:field_is_default)%></label>
<%= check_box 'issue_status', 'is_default' %></p> <%= check_box 'issue_status', 'is_default' %></p>
<p><label for="issue_status_html_color"><%=l(:field_html_color)%><span class="required"> *</span></label> <p><label for="issue_status_html_color"><%=l(:field_html_color)%><span class="required"> *</span></label>
#<%= text_field 'issue_status', 'html_color', :maxlength => 6 %></p> #<%= text_field 'issue_status', 'html_color', :maxlength => 6 %></p>
<!--[eoform:issue_status]--> <!--[eoform:issue_status]-->
</div> </div>

View File

@ -6,18 +6,18 @@
<table class="list"> <table class="list">
<thead><tr> <thead><tr>
<th><%=l(:field_status)%></th> <th><%=l(:field_status)%></th>
<th><%=l(:field_is_default)%></th> <th><%=l(:field_is_default)%></th>
<th><%=l(:field_is_closed)%></th> <th><%=l(:field_is_closed)%></th>
<th><%=l(:button_sort)%></th> <th><%=l(:button_sort)%></th>
<th></th> <th></th>
</tr></thead> </tr></thead>
<tbody> <tbody>
<% for status in @issue_statuses %> <% for status in @issue_statuses %>
<tr class="<%= cycle("odd", "even") %>"> <tr class="<%= cycle("odd", "even") %>">
<td><div class="square" style="background:#<%= status.html_color %>;"></div> <%= link_to status.name, :action => 'edit', :id => status %></td> <td><div class="square" style="background:#<%= status.html_color %>;"></div> <%= link_to status.name, :action => 'edit', :id => status %></td>
<td align="center"><%= image_tag 'true.png' if status.is_default? %></td> <td align="center"><%= image_tag 'true.png' if status.is_default? %></td>
<td align="center"><%= image_tag 'true.png' if status.is_closed? %></td> <td align="center"><%= image_tag 'true.png' if status.is_closed? %></td>
<td align="center"> <td align="center">
<%= link_to image_tag('2uparrow.png', :alt => l(:label_sort_highest)), {:action => 'move', :id => status, :position => 'highest'}, :method => :post, :title => l(:label_sort_highest) %> <%= link_to image_tag('2uparrow.png', :alt => l(:label_sort_highest)), {:action => 'move', :id => status, :position => 'highest'}, :method => :post, :title => l(:label_sort_highest) %>
<%= link_to image_tag('1uparrow.png', :alt => l(:label_sort_higher)), {:action => 'move', :id => status, :position => 'higher'}, :method => :post, :title => l(:label_sort_higher) %> - <%= link_to image_tag('1uparrow.png', :alt => l(:label_sort_higher)), {:action => 'move', :id => status, :position => 'higher'}, :method => :post, :title => l(:label_sort_higher) %> -
@ -25,11 +25,11 @@
<%= link_to image_tag('2downarrow.png', :alt => l(:label_sort_lowest)), {:action => 'move', :id => status, :position => 'lowest'}, :method => :post, :title => l(:label_sort_lowest) %> <%= link_to image_tag('2downarrow.png', :alt => l(:label_sort_lowest)), {:action => 'move', :id => status, :position => 'lowest'}, :method => :post, :title => l(:label_sort_lowest) %>
</td> </td>
<td align="center"> <td align="center">
<%= button_to l(:button_delete), { :action => 'destroy', :id => status }, :confirm => l(:text_are_you_sure), :class => "button-small" %> <%= button_to l(:button_delete), { :action => 'destroy', :id => status }, :confirm => l(:text_are_you_sure), :class => "button-small" %>
</td> </td>
</tr> </tr>
<% end %> <% end %>
</tbody> </tbody>
</table> </table>
<%= pagination_links_full @issue_status_pages %> <%= pagination_links_full @issue_status_pages %>

View File

@ -1,5 +1,5 @@
<% if authorize_for('projects', 'add_issue') %> <% if authorize_for('projects', 'add_issue') %>
<% form_tag({ :controller => 'projects', :action => 'add_issue', :id => @project }, :method => 'get') do %> <% form_tag({ :controller => 'projects', :action => 'add_issue', :id => @project }, :method => 'get') do %>
<%= l(:label_issue_new) %>: <%= select_tag 'tracker_id', ("<option></option>" + options_from_collection_for_select(trackers, 'id', 'name')), :onchange => "if (this.value!='') {this.form.submit();}" %> <%= l(:label_issue_new) %>: <%= select_tag 'tracker_id', ("<option></option>" + options_from_collection_for_select(trackers, 'id', 'name')), :onchange => "if (this.value!='') {this.form.submit();}" %>
<% end %> <% end %>
<% end %> <% end %>

View File

@ -1,11 +1,11 @@
<% for journal in journals %> <% for journal in journals %>
<h4><%= format_time(journal.created_on) %> - <%= journal.user.name %></h4> <h4><%= format_time(journal.created_on) %> - <%= journal.user.name %></h4>
<ul> <ul>
<% for detail in journal.details %> <% for detail in journal.details %>
<li><%= show_detail(detail) %></li> <li><%= show_detail(detail) %></li>
<% end %> <% end %>
</ul> </ul>
<% if journal.notes? %> <% if journal.notes? %>
<%= textilizable journal.notes %> <%= textilizable journal.notes %>
<% end %> <% end %>
<% end %> <% end %>

View File

@ -1,25 +1,25 @@
<% if issues.length > 0 %> <% if issues.length > 0 %>
<table class="list"> <table class="list">
<thead><tr> <thead><tr>
<th>#</th> <th>#</th>
<th><%=l(:field_tracker)%></th> <th><%=l(:field_tracker)%></th>
<th><%=l(:field_subject)%></th> <th><%=l(:field_subject)%></th>
</tr></thead> </tr></thead>
<tbody> <tbody>
<% for issue in issues %> <% for issue in issues %>
<tr class="<%= cycle("odd", "even") %>"> <tr class="<%= cycle("odd", "even") %>">
<th align="center"> <th align="center">
<%= link_to issue.id, :controller => 'issues', :action => 'show', :id => issue %> <%= link_to issue.id, :controller => 'issues', :action => 'show', :id => issue %>
</th> </th>
<td><p class="small"><%= issue.project.name %> - <%= issue.tracker.name %><br /> <td><p class="small"><%= issue.project.name %> - <%= issue.tracker.name %><br />
<%= issue.status.name %> - <%= format_time(issue.updated_on) %></p></td> <%= issue.status.name %> - <%= format_time(issue.updated_on) %></p></td>
<td> <td>
<p class="small"><%= link_to h(issue.subject), :controller => 'issues', :action => 'show', :id => issue %></p> <p class="small"><%= link_to h(issue.subject), :controller => 'issues', :action => 'show', :id => issue %></p>
</td> </td>
</tr> </tr>
<% end %> <% end %>
</tbody> </tbody>
</table> </table>
<% else %> <% else %>
<i><%=l(:label_no_data)%></i> <i><%=l(:label_no_data)%></i>
<% end %> <% end %>

View File

@ -1,6 +1,6 @@
<%= link_to "#{issue.tracker.name} ##{issue.id}", { :controller => 'issues', :action => 'show', :id => issue } %></strong>: <%=h issue.subject %><br /> <%= link_to "#{issue.tracker.name} ##{issue.id}", { :controller => 'issues', :action => 'show', :id => issue } %></strong>: <%=h issue.subject %><br />
<br /> <br />
<strong><%= l(:field_start_date) %></strong>: <%= format_date(issue.start_date) %><br /> <strong><%= l(:field_start_date) %></strong>: <%= format_date(issue.start_date) %><br />
<strong><%= l(:field_due_date) %></strong>: <%= format_date(issue.due_date) %><br /> <strong><%= l(:field_due_date) %></strong>: <%= format_date(issue.due_date) %><br />
<strong><%= l(:field_assigned_to) %></strong>: <%= issue.assigned_to ? issue.assigned_to.name : "-" %><br /> <strong><%= l(:field_assigned_to) %></strong>: <%= issue.assigned_to ? issue.assigned_to.name : "-" %><br />
<strong><%= l(:field_priority) %></strong>: <%= issue.priority.name %> <strong><%= l(:field_priority) %></strong>: <%= issue.priority.name %>

View File

@ -1,37 +1,37 @@
<h2><%=l(:label_issue)%> #<%= @issue.id %>: <%=h @issue.subject %></h2> <h2><%=l(:label_issue)%> #<%= @issue.id %>: <%=h @issue.subject %></h2>
<%= error_messages_for 'issue' %> <%= error_messages_for 'issue' %>
<% form_tag({:action => 'change_status', :id => @issue}, :class => "tabular") do %> <% form_tag({:action => 'change_status', :id => @issue}, :class => "tabular") do %>
<%= hidden_field_tag 'confirm', 1 %> <%= hidden_field_tag 'confirm', 1 %>
<%= hidden_field_tag 'new_status_id', @new_status.id %> <%= hidden_field_tag 'new_status_id', @new_status.id %>
<div class="box"> <div class="box">
<p><label><%=l(:label_issue_status_new)%></label> <%= @new_status.name %></p> <p><label><%=l(:label_issue_status_new)%></label> <%= @new_status.name %></p>
<p><label for="issue_assigned_to_id"><%=l(:field_assigned_to)%></label> <p><label for="issue_assigned_to_id"><%=l(:field_assigned_to)%></label>
<select name="issue[assigned_to_id]"> <select name="issue[assigned_to_id]">
<option value=""></option> <option value=""></option>
<%= options_from_collection_for_select @assignable_to, "id", "display_name", @issue.assigned_to_id %></p> <%= options_from_collection_for_select @assignable_to, "id", "display_name", @issue.assigned_to_id %></p>
</select></p> </select></p>
<p><label for="issue_done_ratio"><%=l(:field_done_ratio)%></label> <p><label for="issue_done_ratio"><%=l(:field_done_ratio)%></label>
<%= select("issue", "done_ratio", ((0..10).to_a.collect {|r| ["#{r*10} %", r*10] }) ) %> <%= select("issue", "done_ratio", ((0..10).to_a.collect {|r| ["#{r*10} %", r*10] }) ) %>
</select></p> </select></p>
<p><label for="issue_fixed_version"><%=l(:field_fixed_version)%></label> <p><label for="issue_fixed_version"><%=l(:field_fixed_version)%></label>
<select name="issue[fixed_version_id]"> <select name="issue[fixed_version_id]">
<option value="">--none--</option> <option value="">--none--</option>
<%= options_from_collection_for_select @issue.project.versions, "id", "name", @issue.fixed_version_id %> <%= options_from_collection_for_select @issue.project.versions, "id", "name", @issue.fixed_version_id %>
</select></p> </select></p>
<p><label for="notes"><%= l(:field_notes) %></label> <p><label for="notes"><%= l(:field_notes) %></label>
<%= text_area_tag 'notes', @notes, :cols => 60, :rows => 10, :class => 'wiki-edit' %></p> <%= text_area_tag 'notes', @notes, :cols => 60, :rows => 10, :class => 'wiki-edit' %></p>
</div> </div>
<%= hidden_field 'issue', 'lock_version' %> <%= hidden_field 'issue', 'lock_version' %>
<%= submit_tag l(:button_save) %> <%= submit_tag l(:button_save) %>
<% end %> <% end %>

View File

@ -1,6 +1,6 @@
<h3><%=l(:label_history)%></h3> <h3><%=l(:label_history)%></h3>
<div id="history"> <div id="history">
<%= render :partial => 'history', :locals => { :journals => @journals } %> <%= render :partial => 'history', :locals => { :journals => @journals } %>
</div> </div>
<br /> <br />
<p><%= link_to l(:button_back), :action => 'show', :id => @issue %></p> <p><%= link_to l(:button_back), :action => 'show', :id => @issue %></p>

View File

@ -1,111 +1,111 @@
<div class="contextual"> <div class="contextual">
<%= l(:label_export_to) %><%= link_to 'PDF', {:action => 'export_pdf', :id => @issue}, :class => 'icon icon-pdf' %> <%= l(:label_export_to) %><%= link_to 'PDF', {:action => 'export_pdf', :id => @issue}, :class => 'icon icon-pdf' %>
</div> </div>
<h2><%= @issue.tracker.name %> #<%= @issue.id %> - <%=h @issue.subject %></h2>
<div class="box"> <h2><%= @issue.tracker.name %> #<%= @issue.id %> - <%=h @issue.subject %></h2>
<table width="100%">
<tr> <div class="box">
<td style="width:15%"><b><%=l(:field_status)%> :</b></td><td style="width:35%"><%= @issue.status.name %></td> <table width="100%">
<td style="width:15%"><b><%=l(:field_priority)%> :</b></td><td style="width:35%"><%= @issue.priority.name %></td> <tr>
</tr> <td style="width:15%"><b><%=l(:field_status)%> :</b></td><td style="width:35%"><%= @issue.status.name %></td>
<tr> <td style="width:15%"><b><%=l(:field_priority)%> :</b></td><td style="width:35%"><%= @issue.priority.name %></td>
<td><b><%=l(:field_assigned_to)%> :</b></td><td><%= @issue.assigned_to ? @issue.assigned_to.name : "-" %></td> </tr>
<td><b><%=l(:field_category)%> :</b></td><td><%=h @issue.category ? @issue.category.name : "-" %></td> <tr>
</tr> <td><b><%=l(:field_assigned_to)%> :</b></td><td><%= @issue.assigned_to ? @issue.assigned_to.name : "-" %></td>
<tr> <td><b><%=l(:field_category)%> :</b></td><td><%=h @issue.category ? @issue.category.name : "-" %></td>
<td><b><%=l(:field_author)%> :</b></td><td><%= link_to_user @issue.author %></td> </tr>
<td><b><%=l(:field_start_date)%> :</b></td><td><%= format_date(@issue.start_date) %></td> <tr>
</tr> <td><b><%=l(:field_author)%> :</b></td><td><%= link_to_user @issue.author %></td>
<tr> <td><b><%=l(:field_start_date)%> :</b></td><td><%= format_date(@issue.start_date) %></td>
<td><b><%=l(:field_created_on)%> :</b></td><td><%= format_date(@issue.created_on) %></td> </tr>
<td><b><%=l(:field_due_date)%> :</b></td><td><%= format_date(@issue.due_date) %></td> <tr>
</tr> <td><b><%=l(:field_created_on)%> :</b></td><td><%= format_date(@issue.created_on) %></td>
<tr> <td><b><%=l(:field_due_date)%> :</b></td><td><%= format_date(@issue.due_date) %></td>
<td><b><%=l(:field_updated_on)%> :</b></td><td><%= format_date(@issue.updated_on) %></td> </tr>
<td><b><%=l(:field_done_ratio)%> :</b></td><td><%= @issue.done_ratio %> %</td> <tr>
</tr> <td><b><%=l(:field_updated_on)%> :</b></td><td><%= format_date(@issue.updated_on) %></td>
<tr> <td><b><%=l(:field_done_ratio)%> :</b></td><td><%= @issue.done_ratio %> %</td>
<td><b><%=l(:field_fixed_version)%> :</b></td><td><%= @issue.fixed_version ? @issue.fixed_version.name : "-" %></td> </tr>
<td></td><td></td> <tr>
</tr> <td><b><%=l(:field_fixed_version)%> :</b></td><td><%= @issue.fixed_version ? @issue.fixed_version.name : "-" %></td>
<tr> <td></td><td></td>
<% n = 0 </tr>
for custom_value in @custom_values %> <tr>
<td><b><%= custom_value.custom_field.name %> :</b></td><td><%=h show_value custom_value %></td> <% n = 0
<% n = n + 1 for custom_value in @custom_values %>
if (n > 1) <td><b><%= custom_value.custom_field.name %> :</b></td><td><%=h show_value custom_value %></td>
n = 0 %> <% n = n + 1
</tr><tr> if (n > 1)
<%end n = 0 %>
end %> </tr><tr>
</tr> <%end
</table> end %>
<hr /> </tr>
<br /> </table>
<hr />
<b><%=l(:field_description)%> :</b><br /><br /> <br />
<%= textilizable @issue.description %>
<br /> <b><%=l(:field_description)%> :</b><br /><br />
<%= textilizable @issue.description %>
<div class="contextual"> <br />
<%= link_to_if_authorized l(:button_edit), {:controller => 'issues', :action => 'edit', :id => @issue}, :class => 'icon icon-edit' %>
<%= link_to_if_authorized l(:button_move), {:controller => 'projects', :action => 'move_issues', :id => @project, "issue_ids[]" => @issue.id }, :class => 'icon icon-move' %> <div class="contextual">
<%= link_to_if_authorized l(:button_delete), {:controller => 'issues', :action => 'destroy', :id => @issue}, :confirm => l(:text_are_you_sure), :method => :post, :class => 'icon icon-del' %> <%= link_to_if_authorized l(:button_edit), {:controller => 'issues', :action => 'edit', :id => @issue}, :class => 'icon icon-edit' %>
</div> <%= link_to_if_authorized l(:button_move), {:controller => 'projects', :action => 'move_issues', :id => @project, "issue_ids[]" => @issue.id }, :class => 'icon icon-move' %>
<%= link_to_if_authorized l(:button_delete), {:controller => 'issues', :action => 'destroy', :id => @issue}, :confirm => l(:text_are_you_sure), :method => :post, :class => 'icon icon-del' %>
<% if authorize_for('issues', 'change_status') and @status_options and !@status_options.empty? %> </div>
<% form_tag ({:controller => 'issues', :action => 'change_status', :id => @issue}) do %>
<%=l(:label_change_status)%> : <% if authorize_for('issues', 'change_status') and @status_options and !@status_options.empty? %>
<select name="new_status_id"> <% form_tag ({:controller => 'issues', :action => 'change_status', :id => @issue}) do %>
<%= options_from_collection_for_select @status_options, "id", "name" %> <%=l(:label_change_status)%> :
</select> <select name="new_status_id">
<%= submit_tag l(:button_change) %> <%= options_from_collection_for_select @status_options, "id", "name" %>
<% end %> </select>
<% end %> <%= submit_tag l(:button_change) %>
&nbsp; <% end %>
</div>
<div id="history" class="box">
<h3><%=l(:label_history)%>
<% if @journals_count > @journals.length %>(<%= l(:label_last_changes, @journals.length) %>)<% end %></h3>
<%= render :partial => 'history', :locals => { :journals => @journals } %>
<% if @journals_count > @journals.length %>
<p><center><small><%= link_to l(:label_change_view_all), :action => 'history', :id => @issue %></small></center></p>
<% end %> <% end %>
</div> &nbsp;
</div>
<div class="box">
<h3><%=l(:label_attachment_plural)%></h3> <div id="history" class="box">
<table width="100%"> <h3><%=l(:label_history)%>
<% for attachment in @issue.attachments %> <% if @journals_count > @journals.length %>(<%= l(:label_last_changes, @journals.length) %>)<% end %></h3>
<tr> <%= render :partial => 'history', :locals => { :journals => @journals } %>
<td><%= link_to attachment.filename, { :action => 'download', :id => @issue, :attachment_id => attachment }, :class => 'icon icon-attachment' %> (<%= number_to_human_size(attachment.filesize) %>)</td> <% if @journals_count > @journals.length %>
<td><%= format_date(attachment.created_on) %></td> <p><center><small><%= link_to l(:label_change_view_all), :action => 'history', :id => @issue %></small></center></p>
<td><%= attachment.author.display_name %></td> <% end %>
<td><div class="contextual"><%= link_to_if_authorized l(:button_delete), {:controller => 'issues', :action => 'destroy_attachment', :id => @issue, :attachment_id => attachment }, :confirm => l(:text_are_you_sure), :method => :post, :class => 'icon icon-del' %></div></td> </div>
</tr>
<div class="box">
<h3><%=l(:label_attachment_plural)%></h3>
<table width="100%">
<% for attachment in @issue.attachments %>
<tr>
<td><%= link_to attachment.filename, { :action => 'download', :id => @issue, :attachment_id => attachment }, :class => 'icon icon-attachment' %> (<%= number_to_human_size(attachment.filesize) %>)</td>
<td><%= format_date(attachment.created_on) %></td>
<td><%= attachment.author.display_name %></td>
<td><div class="contextual"><%= link_to_if_authorized l(:button_delete), {:controller => 'issues', :action => 'destroy_attachment', :id => @issue, :attachment_id => attachment }, :confirm => l(:text_are_you_sure), :method => :post, :class => 'icon icon-del' %></div></td>
</tr>
<% end %>
</table>
<br />
<% if authorize_for('issues', 'add_attachment') %>
<% form_tag ({ :controller => 'issues', :action => 'add_attachment', :id => @issue }, :multipart => true, :class => "tabular") do %>
<p id="attachments_p"><label><%=l(:label_attachment_new)%>
<%= image_to_function "add.png", "addFileField();return false" %></label>
<%= file_field_tag 'attachments[]', :size => 30 %> <em>(<%= l(:label_max_size) %>: <%= number_to_human_size(Setting.attachment_max_size.to_i.kilobytes) %>)</em></p>
<%= submit_tag l(:button_add) %>
<% end %>
<% end %>
</div>
<% if authorize_for('issues', 'add_note') %>
<div class="box">
<h3><%= l(:label_add_note) %></h3>
<% form_tag ({:controller => 'issues', :action => 'add_note', :id => @issue}, :class => "tabular" ) do %>
<p><label for="notes"><%=l(:field_notes)%></label>
<%= text_area_tag 'notes', '', :cols => 60, :rows => 10, :class => 'wiki-edit' %></p>
<%= submit_tag l(:button_add) %>
<% end %>
</div>
<% end %> <% end %>
</table>
<br />
<% if authorize_for('issues', 'add_attachment') %>
<% form_tag ({ :controller => 'issues', :action => 'add_attachment', :id => @issue }, :multipart => true, :class => "tabular") do %>
<p id="attachments_p"><label><%=l(:label_attachment_new)%>
<%= image_to_function "add.png", "addFileField();return false" %></label>
<%= file_field_tag 'attachments[]', :size => 30 %> <em>(<%= l(:label_max_size) %>: <%= number_to_human_size(Setting.attachment_max_size.to_i.kilobytes) %>)</em></p>
<%= submit_tag l(:button_add) %>
<% end %>
<% end %>
</div>
<% if authorize_for('issues', 'add_note') %>
<div class="box">
<h3><%= l(:label_add_note) %></h3>
<% form_tag ({:controller => 'issues', :action => 'add_note', :id => @issue}, :class => "tabular" ) do %>
<p><label for="notes"><%=l(:field_notes)%></label>
<%= text_area_tag 'notes', '', :cols => 60, :rows => 10, :class => 'wiki-edit' %></p>
<%= submit_tag l(:button_add) %>
<% end %>
</div>
<% end %>

View File

@ -1,149 +1,149 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head> <head>
<title><%= Setting.app_title + (@html_title ? ": #{@html_title}" : "") %></title> <title><%= Setting.app_title + (@html_title ? ": #{@html_title}" : "") %></title>
<meta http-equiv="content-type" content="text/html; charset=utf-8" /> <meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta name="description" content="redMine" /> <meta name="description" content="redMine" />
<meta name="keywords" content="issue,bug,tracker" /> <meta name="keywords" content="issue,bug,tracker" />
<!--[if IE]> <!--[if IE]>
<style type="text/css"> <style type="text/css">
body {behavior: url(<%= stylesheet_path "csshover.htc" %>);} body {behavior: url(<%= stylesheet_path "csshover.htc" %>);}
</style> </style>
<![endif]--> <![endif]-->
<%= stylesheet_link_tag "application" %> <%= stylesheet_link_tag "application" %>
<%= stylesheet_link_tag "print", :media => "print" %> <%= stylesheet_link_tag "print", :media => "print" %>
<%= javascript_include_tag :defaults %> <%= javascript_include_tag :defaults %>
<%= javascript_include_tag 'menu' %> <%= javascript_include_tag 'menu' %>
<%= stylesheet_link_tag 'jstoolbar' %> <%= stylesheet_link_tag 'jstoolbar' %>
<!-- page specific tags --><%= yield :header_tags %> <!-- page specific tags --><%= yield :header_tags %>
</head> </head>
<body> <body>
<div id="container" > <div id="container" >
<div id="header"> <div id="header">
<div style="float: left;"> <div style="float: left;">
<h1><%= Setting.app_title %></h1> <h1><%= Setting.app_title %></h1>
<h2><%= Setting.app_subtitle %></h2> <h2><%= Setting.app_subtitle %></h2>
</div> </div>
<div style="float: right; padding-right: 1em; padding-top: 0.2em;"> <div style="float: right; padding-right: 1em; padding-top: 0.2em;">
<% if loggedin? %><small><%=l(:label_logged_as)%> <b><%= @logged_in_user.login %></b></small><% end %> <% if loggedin? %><small><%=l(:label_logged_as)%> <b><%= @logged_in_user.login %></b></small><% end %>
</div> </div>
</div> </div>
<div id="navigation"> <div id="navigation">
<ul> <ul>
<li><%= link_to l(:label_home), { :controller => 'welcome' }, :class => "icon icon-home" %></li> <li><%= link_to l(:label_home), { :controller => 'welcome' }, :class => "icon icon-home" %></li>
<li><%= link_to l(:label_my_page), { :controller => 'my', :action => 'page'}, :class => "icon icon-mypage" %></li> <li><%= link_to l(:label_my_page), { :controller => 'my', :action => 'page'}, :class => "icon icon-mypage" %></li>
<li><%= link_to l(:label_project_plural), { :controller => 'projects' }, :class => "icon icon-projects" %></li> <li><%= link_to l(:label_project_plural), { :controller => 'projects' }, :class => "icon icon-projects" %></li>
<% unless @project.nil? || @project.id.nil? %> <% unless @project.nil? || @project.id.nil? %>
<li class="submenu"><%= link_to @project.name, { :controller => 'projects', :action => 'show', :id => @project }, :class => "icon icon-projects", :onmouseover => "buttonMouseover(event, 'menuProject');" %></li> <li class="submenu"><%= link_to @project.name, { :controller => 'projects', :action => 'show', :id => @project }, :class => "icon icon-projects", :onmouseover => "buttonMouseover(event, 'menuProject');" %></li>
<% end %> <% end %>
<% if loggedin? %> <% if loggedin? %>
<li><%= link_to l(:label_my_account), { :controller => 'my', :action => 'account' }, :class => "icon icon-user" %></li> <li><%= link_to l(:label_my_account), { :controller => 'my', :action => 'account' }, :class => "icon icon-user" %></li>
<% end %> <% end %>
<% if admin_loggedin? %> <% if admin_loggedin? %>
<li class="submenu"><%= link_to l(:label_administration), { :controller => 'admin' }, :class => "icon icon-admin", :onmouseover => "buttonMouseover(event, 'menuAdmin');" %></li> <li class="submenu"><%= link_to l(:label_administration), { :controller => 'admin' }, :class => "icon icon-admin", :onmouseover => "buttonMouseover(event, 'menuAdmin');" %></li>
<% end %> <% end %>
<li class="right"><%= link_to l(:label_help), { :controller => 'help', :ctrl => params[:controller], :page => params[:action] }, :onclick => "window.open(this.href); return false;", :class => "icon icon-help" %></li> <li class="right"><%= link_to l(:label_help), { :controller => 'help', :ctrl => params[:controller], :page => params[:action] }, :onclick => "window.open(this.href); return false;", :class => "icon icon-help" %></li>
<% if loggedin? %> <% if loggedin? %>
<li class="right"><%= link_to l(:label_logout), { :controller => 'account', :action => 'logout' }, :class => "icon icon-user" %></li> <li class="right"><%= link_to l(:label_logout), { :controller => 'account', :action => 'logout' }, :class => "icon icon-user" %></li>
<% else %> <% else %>
<li class="right"><%= link_to l(:label_login), { :controller => 'account', :action => 'login' }, :class => "icon icon-user" %></li> <li class="right"><%= link_to l(:label_login), { :controller => 'account', :action => 'login' }, :class => "icon icon-user" %></li>
<% end %> <% end %>
</ul> </ul>
</div> </div>
<% if admin_loggedin? %> <% if admin_loggedin? %>
<div id="menuAdmin" class="menu" onmouseover="menuMouseover(event)"> <div id="menuAdmin" class="menu" onmouseover="menuMouseover(event)">
<a class="menuItem" href="<%= url_for :controller => 'admin', :action => 'projects' %>" onmouseover="menuItemMouseover(event,'menuProjects');"><span class="menuItemText"><%=l(:label_project_plural)%></span><span class="menuItemArrow">&#9654;</span></a> <a class="menuItem" href="<%= url_for :controller => 'admin', :action => 'projects' %>" onmouseover="menuItemMouseover(event,'menuProjects');"><span class="menuItemText"><%=l(:label_project_plural)%></span><span class="menuItemArrow">&#9654;</span></a>
<a class="menuItem" href="<%= url_for :controller => 'users' %>" onmouseover="menuItemMouseover(event,'menuUsers');"><span class="menuItemText"><%=l(:label_user_plural)%></span><span class="menuItemArrow">&#9654;</span></a> <a class="menuItem" href="<%= url_for :controller => 'users' %>" onmouseover="menuItemMouseover(event,'menuUsers');"><span class="menuItemText"><%=l(:label_user_plural)%></span><span class="menuItemArrow">&#9654;</span></a>
<%= link_to l(:label_role_and_permissions), {:controller => 'roles' }, :class => "menuItem" %> <%= link_to l(:label_role_and_permissions), {:controller => 'roles' }, :class => "menuItem" %>
<a class="menuItem" href="<%= url_for :controller => 'trackers' %>" onmouseover="menuItemMouseover(event,'menuTrackers');"><span class="menuItemText"><%=l(:label_tracker_plural)%></span><span class="menuItemArrow">&#9654;</span></a> <a class="menuItem" href="<%= url_for :controller => 'trackers' %>" onmouseover="menuItemMouseover(event,'menuTrackers');"><span class="menuItemText"><%=l(:label_tracker_plural)%></span><span class="menuItemArrow">&#9654;</span></a>
<%= link_to l(:label_custom_field_plural), {:controller => 'custom_fields' }, :class => "menuItem" %> <%= link_to l(:label_custom_field_plural), {:controller => 'custom_fields' }, :class => "menuItem" %>
<%= link_to l(:label_enumerations), {:controller => 'enumerations' }, :class => "menuItem" %> <%= link_to l(:label_enumerations), {:controller => 'enumerations' }, :class => "menuItem" %>
<%= link_to l(:field_mail_notification), {:controller => 'admin', :action => 'mail_options' }, :class => "menuItem" %> <%= link_to l(:field_mail_notification), {:controller => 'admin', :action => 'mail_options' }, :class => "menuItem" %>
<%= link_to l(:label_authentication), {:controller => 'auth_sources' }, :class => "menuItem" %> <%= link_to l(:label_authentication), {:controller => 'auth_sources' }, :class => "menuItem" %>
<%= link_to l(:label_settings), {:controller => 'settings' }, :class => "menuItem" %> <%= link_to l(:label_settings), {:controller => 'settings' }, :class => "menuItem" %>
<%= link_to l(:label_information_plural), {:controller => 'admin', :action => 'info' }, :class => "menuItem" %> <%= link_to l(:label_information_plural), {:controller => 'admin', :action => 'info' }, :class => "menuItem" %>
</div> </div>
<div id="menuTrackers" class="menu"> <div id="menuTrackers" class="menu">
<%= link_to l(:label_issue_status_plural), {:controller => 'issue_statuses' }, :class => "menuItem" %> <%= link_to l(:label_issue_status_plural), {:controller => 'issue_statuses' }, :class => "menuItem" %>
<%= link_to l(:label_workflow), {:controller => 'roles', :action => 'workflow' }, :class => "menuItem" %> <%= link_to l(:label_workflow), {:controller => 'roles', :action => 'workflow' }, :class => "menuItem" %>
</div> </div>
<div id="menuProjects" class="menu"><%= link_to l(:label_new), {:controller => 'projects', :action => 'add' }, :class => "menuItem" %></div> <div id="menuProjects" class="menu"><%= link_to l(:label_new), {:controller => 'projects', :action => 'add' }, :class => "menuItem" %></div>
<div id="menuUsers" class="menu"><%= link_to l(:label_new), {:controller => 'users', :action => 'add' }, :class => "menuItem" %></a></div> <div id="menuUsers" class="menu"><%= link_to l(:label_new), {:controller => 'users', :action => 'add' }, :class => "menuItem" %></a></div>
<% end %> <% end %>
<% unless @project.nil? || @project.id.nil? %> <% unless @project.nil? || @project.id.nil? %>
<div id="menuProject" class="menu" onmouseover="menuMouseover(event)"> <div id="menuProject" class="menu" onmouseover="menuMouseover(event)">
<%= link_to l(:label_calendar), {:controller => 'projects', :action => 'calendar', :id => @project }, :class => "menuItem" %> <%= link_to l(:label_calendar), {:controller => 'projects', :action => 'calendar', :id => @project }, :class => "menuItem" %>
<%= link_to l(:label_gantt), {:controller => 'projects', :action => 'gantt', :id => @project }, :class => "menuItem" %> <%= link_to l(:label_gantt), {:controller => 'projects', :action => 'gantt', :id => @project }, :class => "menuItem" %>
<%= link_to l(:label_issue_plural), {:controller => 'projects', :action => 'list_issues', :id => @project, :set_filter => 1 }, :class => "menuItem" %> <%= link_to l(:label_issue_plural), {:controller => 'projects', :action => 'list_issues', :id => @project, :set_filter => 1 }, :class => "menuItem" %>
<%= link_to l(:label_report_plural), {:controller => 'reports', :action => 'issue_report', :id => @project }, :class => "menuItem" %> <%= link_to l(:label_report_plural), {:controller => 'reports', :action => 'issue_report', :id => @project }, :class => "menuItem" %>
<%= link_to l(:label_activity), {:controller => 'projects', :action => 'activity', :id => @project }, :class => "menuItem" %> <%= link_to l(:label_activity), {:controller => 'projects', :action => 'activity', :id => @project }, :class => "menuItem" %>
<%= link_to l(:label_news_plural), {:controller => 'projects', :action => 'list_news', :id => @project }, :class => "menuItem" %> <%= link_to l(:label_news_plural), {:controller => 'projects', :action => 'list_news', :id => @project }, :class => "menuItem" %>
<%= link_to l(:label_change_log), {:controller => 'projects', :action => 'changelog', :id => @project }, :class => "menuItem" %> <%= link_to l(:label_change_log), {:controller => 'projects', :action => 'changelog', :id => @project }, :class => "menuItem" %>
<%= link_to l(:label_roadmap), {:controller => 'projects', :action => 'roadmap', :id => @project }, :class => "menuItem" %> <%= link_to l(:label_roadmap), {:controller => 'projects', :action => 'roadmap', :id => @project }, :class => "menuItem" %>
<%= link_to l(:label_document_plural), {:controller => 'projects', :action => 'list_documents', :id => @project }, :class => "menuItem" %> <%= link_to l(:label_document_plural), {:controller => 'projects', :action => 'list_documents', :id => @project }, :class => "menuItem" %>
<%= link_to l(:label_wiki), {:controller => 'wiki', :id => @project, :page => nil }, :class => "menuItem" if @project.wiki and !@project.wiki.new_record? %> <%= link_to l(:label_wiki), {:controller => 'wiki', :id => @project, :page => nil }, :class => "menuItem" if @project.wiki and !@project.wiki.new_record? %>
<%= link_to l(:label_member_plural), {:controller => 'projects', :action => 'list_members', :id => @project }, :class => "menuItem" %> <%= link_to l(:label_member_plural), {:controller => 'projects', :action => 'list_members', :id => @project }, :class => "menuItem" %>
<%= link_to l(:label_attachment_plural), {:controller => 'projects', :action => 'list_files', :id => @project }, :class => "menuItem" %> <%= link_to l(:label_attachment_plural), {:controller => 'projects', :action => 'list_files', :id => @project }, :class => "menuItem" %>
<%= link_to l(:label_search), {:controller => 'projects', :action => 'search', :id => @project }, :class => "menuItem" %> <%= link_to l(:label_search), {:controller => 'projects', :action => 'search', :id => @project }, :class => "menuItem" %>
<%= link_to l(:label_repository), {:controller => 'repositories', :action => 'show', :id => @project}, :class => "menuItem" if @project.repository and !@project.repository.new_record? %> <%= link_to l(:label_repository), {:controller => 'repositories', :action => 'show', :id => @project}, :class => "menuItem" if @project.repository and !@project.repository.new_record? %>
<%= link_to_if_authorized l(:label_settings), {:controller => 'projects', :action => 'settings', :id => @project }, :class => "menuItem" %> <%= link_to_if_authorized l(:label_settings), {:controller => 'projects', :action => 'settings', :id => @project }, :class => "menuItem" %>
</div> </div>
<% end %> <% end %>
<div id="subcontent"> <div id="subcontent">
<% unless @project.nil? || @project.id.nil? %> <% unless @project.nil? || @project.id.nil? %>
<h2><%= @project.name %></h2> <h2><%= @project.name %></h2>
<ul class="menublock"> <ul class="menublock">
<li><%= link_to l(:label_overview), :controller => 'projects', :action => 'show', :id => @project %></li> <li><%= link_to l(:label_overview), :controller => 'projects', :action => 'show', :id => @project %></li>
<li><%= link_to l(:label_calendar), :controller => 'projects', :action => 'calendar', :id => @project %></li> <li><%= link_to l(:label_calendar), :controller => 'projects', :action => 'calendar', :id => @project %></li>
<li><%= link_to l(:label_gantt), :controller => 'projects', :action => 'gantt', :id => @project %></li> <li><%= link_to l(:label_gantt), :controller => 'projects', :action => 'gantt', :id => @project %></li>
<li><%= link_to l(:label_issue_plural), :controller => 'projects', :action => 'list_issues', :id => @project, :set_filter => 1 %></li> <li><%= link_to l(:label_issue_plural), :controller => 'projects', :action => 'list_issues', :id => @project, :set_filter => 1 %></li>
<li><%= link_to l(:label_report_plural), :controller => 'reports', :action => 'issue_report', :id => @project %></li> <li><%= link_to l(:label_report_plural), :controller => 'reports', :action => 'issue_report', :id => @project %></li>
<li><%= link_to l(:label_activity), :controller => 'projects', :action => 'activity', :id => @project %></li> <li><%= link_to l(:label_activity), :controller => 'projects', :action => 'activity', :id => @project %></li>
<li><%= link_to l(:label_news_plural), :controller => 'projects', :action => 'list_news', :id => @project %></li> <li><%= link_to l(:label_news_plural), :controller => 'projects', :action => 'list_news', :id => @project %></li>
<li><%= link_to l(:label_change_log), :controller => 'projects', :action => 'changelog', :id => @project %></li> <li><%= link_to l(:label_change_log), :controller => 'projects', :action => 'changelog', :id => @project %></li>
<li><%= link_to l(:label_roadmap), :controller => 'projects', :action => 'roadmap', :id => @project %></li> <li><%= link_to l(:label_roadmap), :controller => 'projects', :action => 'roadmap', :id => @project %></li>
<li><%= link_to l(:label_document_plural), :controller => 'projects', :action => 'list_documents', :id => @project %></li> <li><%= link_to l(:label_document_plural), :controller => 'projects', :action => 'list_documents', :id => @project %></li>
<li><%= link_to l(:label_wiki), :controller => 'wiki', :id => @project, :page => nil if @project.wiki and !@project.wiki.new_record? %></li> <li><%= link_to l(:label_wiki), :controller => 'wiki', :id => @project, :page => nil if @project.wiki and !@project.wiki.new_record? %></li>
<li><%= link_to l(:label_member_plural), :controller => 'projects', :action => 'list_members', :id => @project %></li> <li><%= link_to l(:label_member_plural), :controller => 'projects', :action => 'list_members', :id => @project %></li>
<li><%= link_to l(:label_attachment_plural), :controller => 'projects', :action => 'list_files', :id => @project %></li> <li><%= link_to l(:label_attachment_plural), :controller => 'projects', :action => 'list_files', :id => @project %></li>
<li><%= link_to l(:label_search), :controller => 'projects', :action => 'search', :id => @project %></li> <li><%= link_to l(:label_search), :controller => 'projects', :action => 'search', :id => @project %></li>
<li><%= link_to l(:label_repository), :controller => 'repositories', :action => 'show', :id => @project if @project.repository and !@project.repository.new_record? %></li> <li><%= link_to l(:label_repository), :controller => 'repositories', :action => 'show', :id => @project if @project.repository and !@project.repository.new_record? %></li>
<li><%= link_to_if_authorized l(:label_settings), :controller => 'projects', :action => 'settings', :id => @project %></li> <li><%= link_to_if_authorized l(:label_settings), :controller => 'projects', :action => 'settings', :id => @project %></li>
</ul> </ul>
<% end %> <% end %>
<% if loggedin? and @logged_in_user.memberships.length > 0 %> <% if loggedin? and @logged_in_user.memberships.length > 0 %>
<h2><%=l(:label_my_projects) %></h2> <h2><%=l(:label_my_projects) %></h2>
<ul class="menublock"> <ul class="menublock">
<% for membership in @logged_in_user.memberships %> <% for membership in @logged_in_user.memberships %>
<li><%= link_to membership.project.name, :controller => 'projects', :action => 'show', :id => membership.project %></li> <li><%= link_to membership.project.name, :controller => 'projects', :action => 'show', :id => membership.project %></li>
<% end %> <% end %>
</ul> </ul>
<% end %> <% end %>
</div> </div>
<div id="content"> <div id="content">
<% if flash[:notice] %><p style="color: green"><%= flash[:notice] %></p><% end %> <% if flash[:notice] %><p style="color: green"><%= flash[:notice] %></p><% end %>
<%= @content_for_layout %> <%= @content_for_layout %>
</div> </div>
<div id="footer"> <div id="footer">
<p><a href="http://redmine.rubyforge.org/">redMine</a> <small><%= Redmine::VERSION %> &copy 2006-2007 Jean-Philippe Lang</small></p> <p><a href="http://redmine.rubyforge.org/">redMine</a> <small><%= Redmine::VERSION %> &copy 2006-2007 Jean-Philippe Lang</small></p>
</div> </div>
</div> </div>
</body> </body>
</html> </html>

View File

@ -1,7 +1,7 @@
<%=l(:label_issue)%> #<%= issue.id %> - <%= issue.subject %> <%=l(:label_issue)%> #<%= issue.id %> - <%= issue.subject %>
<%=l(:field_author)%>: <%= issue.author.display_name %> <%=l(:field_author)%>: <%= issue.author.display_name %>
<%=l(:field_status)%>: <%= issue.status.name %> <%=l(:field_status)%>: <%= issue.status.name %>
<%= issue.description %>
<%= issue.description %>
http://<%= Setting.host_name %>/issues/show/<%= issue.id %> http://<%= Setting.host_name %>/issues/show/<%= issue.id %>

View File

@ -1,6 +1,6 @@
<%= @added_to %> <%= @added_to %>
<%= @attachments.size %> files(s) added. <%= @attachments.size %> files(s) added.
<% @attachments.each do |attachment | %> <% @attachments.each do |attachment | %>
- <%= attachment.filename %><% end %> - <%= attachment.filename %><% end %>
<%= @url %> <%= @url %>

View File

@ -1,6 +1,6 @@
<%= @added_to %> <%= @added_to %>
<%= @attachments.size %> files(s) added. <%= @attachments.size %> files(s) added.
<% @attachments.each do |attachment | %> <% @attachments.each do |attachment | %>
- <%= attachment.filename %><% end %> - <%= attachment.filename %><% end %>
<%= @url %> <%= @url %>

View File

@ -1,6 +1,6 @@
<%= @added_to %> <%= @added_to %>
<%= @attachments.size %> files(s) added. <%= @attachments.size %> files(s) added.
<% @attachments.each do |attachment | %> <% @attachments.each do |attachment | %>
- <%= attachment.filename %><% end %> - <%= attachment.filename %><% end %>
<%= @url %> <%= @url %>

View File

@ -1,6 +1,6 @@
<%= @added_to %> <%= @added_to %>
<%= @attachments.size %> fichier(s) ajouté(s). <%= @attachments.size %> fichier(s) ajouté(s).
<% @attachments.each do |attachment | %> <% @attachments.each do |attachment | %>
- <%= attachment.filename %><% end %> - <%= attachment.filename %><% end %>
<%= @url %> <%= @url %>

View File

@ -1,6 +1,6 @@
<%= @added_to %> <%= @added_to %>
<%= @attachments.size %> ファイルが追加されました。 <%= @attachments.size %> ファイルが追加されました。
<% @attachments.each do |attachment | %> <% @attachments.each do |attachment | %>
- <%= attachment.filename %><% end %> - <%= attachment.filename %><% end %>
<%= @url %> <%= @url %>

View File

@ -1,4 +1,4 @@
A document has been added to <%= @document.project.name %> (<%= @document.category.name %>): A document has been added to <%= @document.project.name %> (<%= @document.category.name %>):
<%= l(:field_title) %>: <%= @document.title %> <%= l(:field_title) %>: <%= @document.title %>
http://<%= Setting.host_name %>/documents/show/<%= @document.id %> http://<%= Setting.host_name %>/documents/show/<%= @document.id %>

View File

@ -1,4 +1,4 @@
A document has been added to <%= @document.project.name %> (<%= @document.category.name %>): A document has been added to <%= @document.project.name %> (<%= @document.category.name %>):
<%= l(:field_title) %>: <%= @document.title %> <%= l(:field_title) %>: <%= @document.title %>
http://<%= Setting.host_name %>/documents/show/<%= @document.id %> http://<%= Setting.host_name %>/documents/show/<%= @document.id %>

View File

@ -1,4 +1,4 @@
A document has been added to <%= @document.project.name %> (<%= @document.category.name %>): A document has been added to <%= @document.project.name %> (<%= @document.category.name %>):
<%= l(:field_title) %>: <%= @document.title %> <%= l(:field_title) %>: <%= @document.title %>
http://<%= Setting.host_name %>/documents/show/<%= @document.id %> http://<%= Setting.host_name %>/documents/show/<%= @document.id %>

View File

@ -1,4 +1,4 @@
Un document a été ajouté à <%= @document.project.name %> (<%= @document.category.name %>): Un document a été ajouté à <%= @document.project.name %> (<%= @document.category.name %>):
<%= l(:field_title) %>: <%= @document.title %> <%= l(:field_title) %>: <%= @document.title %>
http://<%= Setting.host_name %>/documents/show/<%= @document.id %> http://<%= Setting.host_name %>/documents/show/<%= @document.id %>

View File

@ -1,4 +1,4 @@
文書が <%= @document.project.name %> (<%= @document.category.name %>) に追加されました: 文書が <%= @document.project.name %> (<%= @document.category.name %>) に追加されました:
<%= l(:field_title) %>: <%= @document.title %> <%= l(:field_title) %>: <%= @document.title %>
http://<%= Setting.host_name %>/documents/show/<%= @document.id %> http://<%= Setting.host_name %>/documents/show/<%= @document.id %>

Some files were not shown because too many files have changed in this diff Show More