Initial commit

git-svn-id: http://redmine.rubyforge.org/svn/trunk@4 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
Jean-Philippe Lang 2006-06-28 18:11:03 +00:00
parent 73e0b8f8b3
commit 6b7650e2f0
284 changed files with 12752 additions and 0 deletions

10
redmine/Rakefile Normal file
View File

@ -0,0 +1,10 @@
# Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/switchtower.rake, and they will automatically be available to Rake.
require(File.join(File.dirname(__FILE__), 'config', 'boot'))
require 'rake'
require 'rake/testtask'
require 'rake/rdoctask'
require 'tasks/rails'

View File

@ -0,0 +1,83 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class AccountController < ApplicationController
layout 'base'
# prevents login action to be filtered by check_if_login_required application scope filter
skip_before_filter :check_if_login_required, :only => :login
before_filter :require_login, :except => [:show, :login]
def show
@user = User.find(params[:id])
end
# Login request and validation
def login
if request.get?
session[:user] = nil
@user = User.new
else
@user = User.new(params[:user])
logged_in_user = @user.try_to_login
if logged_in_user
session[:user] = logged_in_user
redirect_back_or_default :controller => 'account', :action => 'my_page'
else
flash[:notice] = _('Invalid user/password')
end
end
end
# Log out current user and redirect to welcome page
def logout
session[:user] = nil
redirect_to(:controller => '')
end
def my_page
@user = session[:user]
@reported_issues = Issue.find(:all, :conditions => ["author_id=?", @user.id], :limit => 10, :include => [ :status, :project, :tracker ], :order => 'issues.updated_on DESC')
@assigned_issues = Issue.find(:all, :conditions => ["assigned_to_id=?", @user.id], :limit => 10, :include => [ :status, :project, :tracker ], :order => 'issues.updated_on DESC')
end
# Edit current user's account
def my_account
@user = User.find(session[:user].id)
if request.post? and @user.update_attributes(@params[:user])
flash[:notice] = 'Account was successfully updated.'
session[:user] = @user
set_localization
end
end
# Change current user's password
def change_password
@user = User.find(session[:user].id)
if @user.check_password?(@params[:old_password])
if @params[:new_password] == @params[:new_password_confirmation]
if @user.change_password(@params[:old_password], @params[:new_password])
flash[:notice] = 'Password was successfully updated.'
end
else
flash[:notice] = 'Password confirmation doesn\'t match!'
end
else
flash[:notice] = 'Wrong password'
end
render :action => 'my_account'
end
end

View File

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

View File

@ -0,0 +1,86 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class ApplicationController < ActionController::Base
before_filter :check_if_login_required, :set_localization
# check if login is globally required to access the application
def check_if_login_required
require_login if RDM_LOGIN_REQUIRED
end
def set_localization
Localization.lang = session[:user].nil? ? RDM_DEFAULT_LANG : (session[:user].language || RDM_DEFAULT_LANG)
end
def require_login
unless session[:user]
store_location
redirect_to(:controller => "account", :action => "login")
end
end
def require_admin
if session[:user].nil?
store_location
redirect_to(:controller => "account", :action => "login")
else
unless session[:user].admin?
flash[:notice] = "Acces not allowed"
redirect_to(:controller => "projects", :action => "list")
end
end
end
# authorizes the user for the requested action.
def authorize
# check if action is allowed on public projects
if @project.public? and Permission.allowed_to_public "%s/%s" % [ @params[:controller], @params[:action] ]
return true
end
# if user is not logged in, he is redirect to login form
unless session[:user]
store_location
redirect_to(:controller => "account", :action => "login")
return false
end
# check if user is authorized
if session[:user].admin? or Permission.allowed_to_role( "%s/%s" % [ @params[:controller], @params[:action] ], session[:user].role_for_project(@project.id) )
return true
end
flash[:notice] = "Acces denied"
redirect_to(:controller => "")
return false
end
# store current uri in the session.
# we can return to this location by calling redirect_back_or_default
def store_location
session[:return_to] = @request.request_uri
end
# move to the last store_location call or to the passed default one
def redirect_back_or_default(default)
if session[:return_to].nil?
redirect_to default
else
redirect_to_url session[:return_to]
session[:return_to] = nil
end
end
end

View File

@ -0,0 +1,58 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class CustomFieldsController < ApplicationController
layout 'base'
before_filter :require_admin
def index
list
render :action => 'list'
end
def list
@custom_field_pages, @custom_fields = paginate :custom_fields, :per_page => 10
end
def new
if request.get?
@custom_field = CustomField.new
else
@custom_field = CustomField.new(params[:custom_field])
if @custom_field.save
flash[:notice] = 'CustomField was successfully created.'
redirect_to :action => 'list'
end
end
end
def edit
@custom_field = CustomField.find(params[:id])
if request.post? and @custom_field.update_attributes(params[:custom_field])
flash[:notice] = 'CustomField was successfully updated.'
redirect_to :action => 'list'
end
end
def destroy
CustomField.find(params[:id]).destroy
redirect_to :action => 'list'
rescue
flash[:notice] = "Unable to delete custom field"
redirect_to :action => 'list'
end
end

View File

@ -0,0 +1,65 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class DocumentsController < ApplicationController
layout 'base'
before_filter :find_project, :authorize
def show
end
def edit
@categories = Enumeration::get_values('DCAT')
if request.post? and @document.update_attributes(params[:document])
flash[:notice] = 'Document was successfully updated.'
redirect_to :action => 'show', :id => @document
end
end
def destroy
@document.destroy
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
end
def add_attachment
# Save the attachment
if params[:attachment][:file].size > 0
@attachment = @document.attachments.build(params[:attachment])
@attachment.author_id = session[:user].id unless session[:user].nil?
@attachment.save
end
render :action => 'show'
end
def destroy_attachment
@document.attachments.find(params[:attachment_id]).destroy
render :action => 'show'
end
private
def find_project
@document = Document.find(params[:id])
@project = @document.project
end
end

View File

@ -0,0 +1,69 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class EnumerationsController < ApplicationController
layout 'base'
before_filter :require_admin
def index
list
render :action => 'list'
end
# GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
verify :method => :post, :only => [ :destroy, :create, :update ],
:redirect_to => { :action => :list }
def list
end
def new
@enumeration = Enumeration.new(:opt => params[:opt])
end
def create
@enumeration = Enumeration.new(params[:enumeration])
if @enumeration.save
flash[:notice] = 'Enumeration was successfully created.'
redirect_to :action => 'list', :opt => @enumeration.opt
else
render :action => 'new'
end
end
def edit
@enumeration = Enumeration.find(params[:id])
end
def update
@enumeration = Enumeration.find(params[:id])
if @enumeration.update_attributes(params[:enumeration])
flash[:notice] = 'Enumeration was successfully updated.'
redirect_to :action => 'list', :opt => @enumeration.opt
else
render :action => 'edit'
end
end
def destroy
Enumeration.find(params[:id]).destroy
redirect_to :action => 'list'
rescue
flash[:notice] = "Unable to delete enumeration"
redirect_to :action => 'list'
end
end

View File

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

View File

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

View File

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

View File

@ -0,0 +1,102 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class IssuesController < ApplicationController
layout 'base'
before_filter :find_project, :authorize
helper :custom_fields
include CustomFieldsHelper
def show
@status_options = @issue.status.workflows.find(:all, :conditions => ["role_id=? and tracker_id=?", session[:user].role_for_project(@project.id), @issue.tracker.id]).collect{ |w| w.new_status } if session[:user]
end
def edit
@trackers = Tracker.find(:all)
@priorities = Enumeration::get_values('IPRI')
if request.get?
@custom_values = @project.custom_fields_for_issues.collect { |x| @issue.custom_values.find_by_custom_field_id(x.id) || CustomValue.new(:custom_field => x) }
else
# Retrieve custom fields and values
@custom_values = @project.custom_fields_for_issues.collect { |x| CustomValue.new(:custom_field => x, :value => params["custom_fields"][x.id.to_s]) }
@issue.custom_values = @custom_values
if @issue.update_attributes(params[:issue])
flash[:notice] = 'Issue was successfully updated.'
redirect_to :action => 'show', :id => @issue
end
end
end
def change_status
@history = @issue.histories.build(params[:history])
@status_options = @issue.status.workflows.find(:all, :conditions => ["role_id=? and tracker_id=?", session[:user].role_for_project(@project.id), @issue.tracker.id]).collect{ |w| w.new_status } if session[:user]
if params[:confirm]
unless session[:user].nil?
@history.author = session[:user]
end
if @history.save
@issue.status = @history.status
@issue.fixed_version_id = (params[:issue][:fixed_version_id])
@issue.assigned_to_id = (params[:issue][:assigned_to_id])
if @issue.save
flash[:notice] = 'Issue was successfully updated.'
Mailer.deliver_issue_change_status(@issue) if Permission.find_by_controller_and_action(@params[:controller], @params[:action]).mail_enabled?
redirect_to :action => 'show', :id => @issue
end
end
end
@assignable_to = @project.members.find(:all, :include => :user).collect{ |m| m.user }
end
def destroy
@issue.destroy
redirect_to :controller => 'projects', :action => 'list_issues', :id => @project
end
def add_attachment
# Save the attachment
if params[:attachment][:file].size > 0
@attachment = @issue.attachments.build(params[:attachment])
@attachment.author_id = session[:user].id unless session[:user].nil?
@attachment.save
end
redirect_to :action => 'show', :id => @issue
end
def destroy_attachment
@issue.attachments.find(params[:attachment_id]).destroy
redirect_to :action => 'show', :id => @issue
end
# Send the file in stream mode
def download
@attachment = @issue.attachments.find(params[:attachment_id])
send_file @attachment.diskfile, :filename => @attachment.filename
end
private
def find_project
@issue = Issue.find(params[:id])
@project = @issue.project
end
end

View File

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

View File

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

View File

@ -0,0 +1,260 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class ProjectsController < ApplicationController
layout 'base'
before_filter :find_project, :authorize, :except => [ :index, :list, :add ]
before_filter :require_admin, :only => [ :add, :destroy ]
helper :sort
include SortHelper
helper :search_filter
include SearchFilterHelper
helper :custom_fields
include CustomFieldsHelper
def index
list
render :action => 'list'
end
# Lists public projects
def list
sort_init 'projects.name', 'asc'
sort_update
@project_count = Project.count(["public=?", true])
@project_pages = Paginator.new self, @project_count,
15,
@params['page']
@projects = Project.find :all, :order => sort_clause,
:conditions => ["public=?", true],
:limit => @project_pages.items_per_page,
:offset => @project_pages.current.offset
end
# Add a new project
def add
@custom_fields = CustomField::find_all
@project = Project.new(params[:project])
if request.post?
@project.custom_fields = CustomField.find(@params[:custom_field_ids]) if @params[:custom_field_ids]
if @project.save
flash[:notice] = 'Project was successfully created.'
redirect_to :controller => 'admin', :action => 'projects'
end
end
end
# Show @project
def show
@members = @project.members.find(:all, :include => [:user, :role])
end
def settings
@custom_fields = CustomField::find_all
@issue_category ||= IssueCategory.new
@member ||= @project.members.new
@roles = Role.find_all
@users = User.find_all - @project.members.find(:all, :include => :user).collect{|m| m.user }
end
# Edit @project
def edit
if request.post?
@project.custom_fields = CustomField.find(@params[:custom_field_ids]) if @params[:custom_field_ids]
if @project.update_attributes(params[:project])
flash[:notice] = 'Project was successfully updated.'
redirect_to :action => 'settings', :id => @project
else
settings
render :action => 'settings'
end
end
end
# Delete @project
def destroy
if request.post? and params[:confirm]
@project.destroy
redirect_to :controller => 'admin', :action => 'projects'
end
end
# Add a new issue category to @project
def add_issue_category
if request.post?
@issue_category = @project.issue_categories.build(params[:issue_category])
if @issue_category.save
redirect_to :action => 'settings', :id => @project
else
settings
render :action => 'settings'
end
end
end
# Add a new version to @project
def add_version
@version = @project.versions.build(params[:version])
if request.post? and @version.save
redirect_to :action => 'settings', :id => @project
end
end
# Add a new member to @project
def add_member
@member = @project.members.build(params[:member])
if request.post?
if @member.save
flash[:notice] = 'Member was successfully added.'
redirect_to :action => 'settings', :id => @project
else
settings
render :action => 'settings'
end
end
end
# Show members list of @project
def list_members
@members = @project.members
end
# Add a new document to @project
def add_document
@categories = Enumeration::get_values('DCAT')
@document = @project.documents.build(params[:document])
if request.post?
# Save the attachment
if params[:attachment][:file].size > 0
@attachment = @document.attachments.build(params[:attachment])
@attachment.author_id = session[:user].id unless session[:user].nil?
end
if @document.save
redirect_to :action => 'list_documents', :id => @project
end
end
end
# Show documents list of @project
def list_documents
@documents = @project.documents
end
# Add a new issue to @project
def add_issue
@trackers = Tracker.find(:all)
@priorities = Enumeration::get_values('IPRI')
if request.get?
@issue = @project.issues.build
@custom_values = @project.custom_fields_for_issues.collect { |x| CustomValue.new(:custom_field => x) }
else
# Create the issue and set the author
@issue = @project.issues.build(params[:issue])
@issue.author = session[:user] unless session[:user].nil?
# Create the document if a file was sent
if params[:attachment][:file].size > 0
@attachment = @issue.attachments.build(params[:attachment])
@attachment.author_id = session[:user].id unless session[:user].nil?
end
@custom_values = @project.custom_fields_for_issues.collect { |x| CustomValue.new(:custom_field => x, :value => params["custom_fields"][x.id.to_s]) }
@issue.custom_values = @custom_values
if @issue.save
flash[:notice] = "Issue was successfully added."
Mailer.deliver_issue_add(@issue) if Permission.find_by_controller_and_action(@params[:controller], @params[:action]).mail_enabled?
redirect_to :action => 'list_issues', :id => @project
end
end
end
# Show issues list of @project
def list_issues
sort_init 'issues.id', 'desc'
sort_update
search_filter_criteria 'issues.tracker_id', :values => "Tracker.find(:all)"
search_filter_criteria 'issues.priority_id', :values => "Enumeration.find(:all, :conditions => ['opt=?','IPRI'])"
search_filter_criteria 'issues.category_id', :values => "@project.issue_categories"
search_filter_criteria 'issues.status_id', :values => "IssueStatus.find(:all)"
search_filter_criteria 'issues.author_id', :values => "User.find(:all)", :label => "display_name"
search_filter_update if params[:set_filter] or request.post?
@issue_count = @project.issues.count(search_filter_clause)
@issue_pages = Paginator.new self, @issue_count,
15,
@params['page']
@issues = @project.issues.find :all, :order => sort_clause,
:include => [ :author, :status, :tracker ],
:conditions => search_filter_clause,
:limit => @issue_pages.items_per_page,
:offset => @issue_pages.current.offset
end
# Add a news to @project
def add_news
@news = @project.news.build(params[:news])
if request.post?
@news.author = session[:user] unless session[:user].nil?
if @news.save
redirect_to :action => 'list_news', :id => @project
end
end
end
# Show news list of @project
def list_news
@news_pages, @news = paginate :news, :per_page => 10, :conditions => ["project_id=?", @project.id], :include => :author, :order => "news.created_on DESC"
end
def add_file
if request.post?
# Save the attachment
if params[:attachment][:file].size > 0
@attachment = @project.versions.find(params[:version_id]).attachments.build(params[:attachment])
@attachment.author_id = session[:user].id unless session[:user].nil?
if @attachment.save
redirect_to :controller => 'projects', :action => 'list_files', :id => @project
end
end
end
@versions = @project.versions
end
def list_files
@versions = @project.versions
end
# Show changelog of @project
def changelog
@fixed_issues = @project.issues.find(:all,
:include => [ :fixed_version, :status, :tracker ],
:conditions => [ "issue_statuses.is_closed=? and trackers.is_in_chlog=? and issues.fixed_version_id is not null", true, true]
)
end
private
# Find project of id params[:id]
# if not found, redirect to project list
# used as a before_filter
def find_project
@project = Project.find(params[:id])
rescue
flash[:notice] = 'Project not found.'
redirect_to :action => 'list'
end
end

View File

@ -0,0 +1,71 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class ReportsController < ApplicationController
layout 'base'
before_filter :find_project, :authorize
def issue_report
@statuses = IssueStatus.find_all
@trackers = Tracker.find_all
@issues_by_tracker =
ActiveRecord::Base.connection.select_all("select s.id as status_id,
s.is_closed as closed,
t.id as tracker_id,
count(i.id) as total
from
issues i, issue_statuses s, trackers t
where
i.status_id=s.id
and i.tracker_id=t.id
and i.project_id=#{@project.id}
group by s.id, t.id")
@priorities = Enumeration::get_values('IPRI')
@issues_by_priority =
ActiveRecord::Base.connection.select_all("select s.id as status_id,
s.is_closed as closed,
p.id as priority_id,
count(i.id) as total
from
issues i, issue_statuses s, enumerations p
where
i.status_id=s.id
and i.priority_id=p.id
and i.project_id=#{@project.id}
group by s.id, p.id")
@categories = @project.issue_categories
@issues_by_category =
ActiveRecord::Base.connection.select_all("select s.id as status_id,
s.is_closed as closed,
c.id as category_id,
count(i.id) as total
from
issues i, issue_statuses s, issue_categories c
where
i.status_id=s.id
and i.category_id=c.id
and i.project_id=#{@project.id}
group by s.id, c.id")
end
private
# Find project of id params[:id]
def find_project
@project = Project.find(params[:id])
end
end

View File

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

View File

@ -0,0 +1,60 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class TrackersController < ApplicationController
layout 'base'
before_filter :require_admin
def index
list
render :action => 'list'
end
# GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
verify :method => :post, :only => [ :destroy ], :redirect_to => { :action => :list }
def list
@tracker_pages, @trackers = paginate :trackers, :per_page => 10
end
def new
@tracker = Tracker.new(params[:tracker])
if request.post? and @tracker.save
flash[:notice] = 'Tracker was successfully created.'
redirect_to :action => 'list'
end
end
def edit
@tracker = Tracker.find(params[:id])
if request.post? and @tracker.update_attributes(params[:tracker])
flash[:notice] = 'Tracker was successfully updated.'
redirect_to :action => 'list'
end
end
def destroy
@tracker = Tracker.find(params[:id])
unless @tracker.issues.empty?
flash[:notice] = "This tracker contains issues and can\'t be deleted."
else
@tracker.destroy
end
redirect_to :action => 'list'
end
end

View File

@ -0,0 +1,73 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class UsersController < ApplicationController
layout 'base'
before_filter :require_admin
helper :sort
include SortHelper
def index
list
render :action => 'list'
end
def list
sort_init 'users.login', 'asc'
sort_update
@user_count = User.count
@user_pages = Paginator.new self, @user_count,
15,
@params['page']
@users = User.find :all, :order => sort_clause,
:limit => @user_pages.items_per_page,
:offset => @user_pages.current.offset
end
def add
if request.get?
@user = User.new
else
@user = User.new(params[:user])
@user.admin = params[:user][:admin]
if @user.save
flash[:notice] = 'User was successfully created.'
redirect_to :action => 'list'
end
end
end
def edit
@user = User.find(params[:id])
if request.post?
@user.admin = params[:user][:admin] if params[:user][:admin]
if @user.update_attributes(params[:user])
flash[:notice] = 'User was successfully updated.'
redirect_to :action => 'list'
end
end
end
def destroy
User.find(params[:id]).destroy
redirect_to :action => 'list'
rescue
flash[:notice] = "Unable to delete user"
redirect_to :action => 'list'
end
end

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,65 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module ApplicationHelper
def loggedin?
session[:user]
end
def admin_loggedin?
session[:user] && session[:user].admin
end
def authorize_for(controller, action)
# check if action is allowed on public projects
if @project.public? and Permission.allowed_to_public "%s/%s" % [ controller, action ]
return true
end
# check if user is authorized
if session[:user] and (session[:user].admin? or Permission.allowed_to_role( "%s/%s" % [ controller, action ], session[:user].role_for_project(@project.id) ) )
return true
end
return false
end
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])
end
# Display a link to user's account page
def link_to_user(user)
link_to user.display_name, :controller => 'account', :action => 'show', :id => user
end
def format_date(date)
_('(date)', date) if date
end
def format_time(time)
_('(time)', time) if time
end
def pagination_links_full(paginator, options={}, html_options={})
html =''
html << link_to(('&#171; ' + _('Previous') ), { :page => paginator.current.previous }) + ' ' if paginator.current.previous
html << (pagination_links(paginator, options, html_options) || '')
html << ' ' + link_to((_('Next') + ' &#187;'), { :page => paginator.current.next }) if paginator.current.next
html
end
end

View File

@ -0,0 +1,36 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module CustomFieldsHelper
def custom_field_tag(custom_value)
custom_field = custom_value.custom_field
field_name = "custom_fields[#{custom_field.id}]"
case custom_field.typ
when 0 .. 2
text_field_tag field_name, custom_value.value
when 3
check_box field_name
when 4
select_tag field_name,
options_for_select(custom_field.possible_values.split('|'),
custom_value.value)
end
end
end

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,55 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module SearchFilterHelper
def search_filter_criteria(field, options = {})
session[:search_filter] ||= {}
session[:search_filter][field] ||= options
# session[:search_filter][field][:values] = options[:values] unless options[:values].nil?
# session[:search_filter][field][:label] = options[:label] unless options[:label].nil?
end
def search_filter_update
session[:search_filter].each_key {|field| session[:search_filter][field][:value] = params[field] }
#@search_filter[:value] = params[@search_filter[:field]]
end
def search_filter_clause
clause = "1=1"
session[:search_filter].each {|field, criteria| clause = clause + " AND " + field + "='" + session[:search_filter][field][:value] + "'" unless session[:search_filter][field][:value].nil? || session[:search_filter][field][:value].empty? }
clause
#@search_filter[:field] + "='" + @search_filter[:value] + "'" unless @search_filter[:value].nil? || @search_filter[:value].empty?
end
def search_filter_tag(field)
option_values = []
#values = eval @search_filter[:values_expr]
option_values = eval session[:search_filter][field][:values]
content_tag("select",
content_tag("option", "[All]", :value => "") +
options_from_collection_for_select(option_values,
"id",
session[:search_filter][field][:label] || "name",
session[:search_filter][field][:value].to_i
),
:name => field
)
end
end

View File

@ -0,0 +1,157 @@
# Helpers to sort tables using clickable column headers.
#
# Author: Stuart Rackham <srackham@methods.co.nz>, March 2005.
# License: This source code is released under the MIT license.
#
# - Consecutive clicks toggle the column's sort order.
# - Sort state is maintained by a session hash entry.
# - Icon image identifies sort column and state.
# - Typically used in conjunction with the Pagination module.
#
# Example code snippets:
#
# Controller:
#
# helper :sort
# include SortHelper
#
# def list
# sort_init 'last_name'
# sort_update
# @items = Contact.find_all nil, sort_clause
# end
#
# Controller (using Pagination module):
#
# helper :sort
# include SortHelper
#
# def list
# sort_init 'last_name'
# sort_update
# @contact_pages, @items = paginate :contacts,
# :order_by => sort_clause,
# :per_page => 10
# end
#
# View (table header in list.rhtml):
#
# <thead>
# <tr>
# <%= sort_header_tag('id', :title => 'Sort by contact ID') %>
# <%= sort_header_tag('last_name', :caption => 'Name') %>
# <%= sort_header_tag('phone') %>
# <%= sort_header_tag('address', :width => 200) %>
# </tr>
# </thead>
#
# - The ascending and descending sort icon images are sort_asc.png and
# sort_desc.png and reside in the application's images directory.
# - Introduces instance variables: @sort_name, @sort_default.
# - Introduces params :sort_key and :sort_order.
#
module SortHelper
# Initializes the default sort column (default_key) and sort order
# (default_order).
#
# - default_key is a column attribute name.
# - default_order is 'asc' or 'desc'.
# - name is the name of the session hash entry that stores the sort state,
# defaults to '<controller_name>_sort'.
#
def sort_init(default_key, default_order='asc', name=nil)
@sort_name = name || @params[:controller] + @params[:action] + '_sort'
@sort_default = {:key => default_key, :order => default_order}
end
# Updates the sort state. Call this in the controller prior to calling
# sort_clause.
#
def sort_update()
if @params[:sort_key]
sort = {:key => @params[:sort_key], :order => @params[:sort_order]}
elsif @session[@sort_name]
sort = @session[@sort_name] # Previous sort.
else
sort = @sort_default
end
@session[@sort_name] = sort
end
# Returns an SQL sort clause corresponding to the current sort state.
# Use this to sort the controller's table items collection.
#
def sort_clause()
@session[@sort_name][:key] + ' ' + @session[@sort_name][:order]
end
# Returns a link which sorts by the named column.
#
# - column is the name of an attribute in the sorted record collection.
# - The optional caption explicitly specifies the displayed link text.
# - A sort icon image is positioned to the right of the sort link.
#
def sort_link(column, caption=nil)
key, order = @session[@sort_name][:key], @session[@sort_name][:order]
if key == column
if order.downcase == 'asc'
icon = 'sort_asc'
order = 'desc'
else
icon = 'sort_desc'
order = 'asc'
end
else
icon = nil
order = 'desc' # changed for desc order by default
end
caption = titleize(Inflector::humanize(column)) unless caption
params = {:params => {:sort_key => column, :sort_order => order}}
link_to(caption, params) + (icon ? nbsp(2) + image_tag(icon) : '')
end
# Returns a table header <th> tag with a sort link for the named column
# attribute.
#
# Options:
# :caption The displayed link name (defaults to titleized column name).
# :title The tag's 'title' attribute (defaults to 'Sort by :caption').
#
# Other options hash entries generate additional table header tag attributes.
#
# Example:
#
# <%= sort_header_tag('id', :title => 'Sort by contact ID', :width => 40) %>
#
# Renders:
#
# <th title="Sort by contact ID" width="40">
# <a href="/contact/list?sort_order=desc&amp;sort_key=id">Id</a>
# &nbsp;&nbsp;<img alt="Sort_asc" src="/images/sort_asc.png" />
# </th>
#
def sort_header_tag(column, options = {})
if options[:caption]
caption = options[:caption]
options.delete(:caption)
else
caption = titleize(Inflector::humanize(column))
end
options[:title]= "Sort by #{caption}" unless options[:title]
content_tag('th', sort_link(column, caption), options)
end
private
# Return n non-breaking spaces.
def nbsp(n)
'&nbsp;' * n
end
# Return capitalized title.
def titleize(title)
title.split.map {|w| w.capitalize }.join(' ')
end
end

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,38 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class CustomField < ActiveRecord::Base
has_and_belongs_to_many :projects
has_many :custom_values, :dependent => true
has_many :issues, :through => :issue_custom_values
validates_presence_of :name, :typ
validates_uniqueness_of :name
TYPES = [
[ "Integer", 0 ],
[ "String", 1 ],
[ "Date", 2 ],
[ "Boolean", 3 ],
[ "List", 4 ]
].freeze
def self.for_all
find(:all, :conditions => ["is_for_all=?", true])
end
end

View File

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

View File

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

View File

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

View File

@ -0,0 +1,55 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Issue < ActiveRecord::Base
belongs_to :project
belongs_to :tracker
belongs_to :status, :class_name => 'IssueStatus', :foreign_key => 'status_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 :fixed_version, :class_name => 'Version', :foreign_key => 'fixed_version_id'
belongs_to :priority, :class_name => 'Enumeration', :foreign_key => 'priority_id'
belongs_to :category, :class_name => 'IssueCategory', :foreign_key => 'category_id'
has_many :histories, :class_name => 'IssueHistory', :dependent => true, :order => "issue_histories.created_on DESC", :include => :status
has_many :attachments, :as => :container, :dependent => true
has_many :custom_values, :dependent => true
has_many :custom_fields, :through => :custom_values
validates_presence_of :subject, :descr, :priority, :tracker, :author
# set default status for new issues
def before_create
self.status = IssueStatus.default
build_history
end
def long_id
"%05d" % self.id
end
private
# Creates an history for the issue
def build_history
@history = self.histories.build
@history.status = self.status
@history.author = self.author
end
end

View File

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

View File

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

View File

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

View File

@ -0,0 +1,36 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Mailer < ActionMailer::Base
def issue_change_status(issue)
# Sends to all project members
@recipients = issue.project.members.collect { |m| m.user.mail if m.user.mail_notification }
@from = 'redmine@somenet.foo'
@subject = "Issue ##{issue.id} has been updated"
@body['issue'] = issue
end
def issue_add(issue)
# Sends to all project members
@recipients = issue.project.members.collect { |m| m.user.mail if m.user.mail_notification }
@from = 'redmine@somenet.foo'
@subject = "Issue ##{issue.id} has been reported"
@body['issue'] = issue
end
end

View File

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

View File

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

View File

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

View File

@ -0,0 +1,44 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Project < ActiveRecord::Base
has_many :versions, :dependent => true, :order => "versions.date DESC"
has_many :members, :dependent => true
has_many :issues, :dependent => true, :order => "issues.created_on DESC", :include => :status
has_many :documents, :dependent => true
has_many :news, :dependent => true, :order => "news.created_on DESC", :include => :author
has_many :issue_categories, :dependent => true
has_and_belongs_to_many :custom_fields
validates_presence_of :name, :descr
# returns 5 last created projects
def self.latest
find(:all, :limit => 5, :order => "created_on DESC")
end
# Returns current version of the project
def current_version
versions.find(:first, :conditions => [ "date <= ?", Date.today ], :order => "date DESC, id DESC")
end
# Returns an array of all custom fields enabled for project issues
# (explictly associated custom fields and custom fields enabled for all projects)
def custom_fields_for_issues
(CustomField.for_all + custom_fields).uniq
end
end

View File

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

View File

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

View File

@ -0,0 +1,89 @@
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require "digest/sha1"
class User < ActiveRecord::Base
has_many :memberships, :class_name => 'Member', :include => [ :project, :role ], :dependent => true
attr_accessor :password
attr_accessor :last_before_login_on
# Prevents unauthorized assignments
attr_protected :admin
validates_presence_of :login, :firstname, :lastname, :mail
validates_uniqueness_of :login, :mail
# Login must contain lettres, numbers, underscores only
validates_format_of :login, :with => /^[a-z0-9_]+$/i
validates_format_of :mail, :with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i
def before_create
self.hashed_password = User.hash_password(self.password)
end
def after_create
@password = nil
end
# Returns the user that matches user's login and password
def try_to_login
@user = User.login(self.login, self.password)
unless @user.nil?
@user.last_before_login_on = @user.last_login_on
@user.update_attribute(:last_login_on, DateTime.now)
end
@user
end
# Return user's full name for display
def display_name
firstname + " " + lastname #+ (self.admin ? " (Admin)" : "" )
end
# Returns the user that matches the given login and password
def self.login(login, password)
hashed_password = hash_password(password || "")
find(:first,
:conditions => ["login = ? and hashed_password = ? and locked = ?", login, hashed_password, false])
end
def check_password?(clear_password)
User.hash_password(clear_password) == self.hashed_password
end
def change_password(current_password, new_password)
self.hashed_password = User.hash_password(new_password)
save
end
def role_for_project(project_id)
@role_for_projects ||=
begin
roles = {}
self.memberships.each { |m| roles.store m.project_id, m.role_id }
roles
end
@role_for_projects[project_id]
end
private
# Return password digest
def self.hash_password(clear_password)
Digest::SHA1.hexdigest(clear_password)
end
end

View File

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

View File

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

View File

@ -0,0 +1,13 @@
<div class="box">
<h2><%=_ 'Please login' %></h2>
<%= start_form_tag :action=> "login" %>
<p><label for="user_login"><%=_ 'Login' %>:</label><br/>
<input type="text" name="user[login]" id="user_login" size="30" /></p>
<p><label for="user_password"><%=_ 'Password' %>:</label><br/>
<input type="password" name="user[password]" id="user_password" size="30"/></p>
<p><input type="submit" name="login" value="<%=_ 'Log in' %> &#187;" class="primary" /></p>
<%= end_form_tag %>
</div>

View File

@ -0,0 +1,54 @@
<h2><%=_('My account')%></h2>
<p><%=_('Login')%>: <strong><%= @user.login %></strong><br />
<%=_('Created on')%>: <%= format_time(@user.created_on) %>,
<%=_('Last update')%>: <%= format_time(@user.updated_on) %></p>
<div class="splitcontentleft">
<div class="box">
<h3><%=_('Information')%></h3>
&nbsp;
<%= start_form_tag :action => 'my_account' %>
<%= error_messages_for 'user' %>
<!--[form:user]-->
<p><label for="user_firstname"><%=_('Firstname')%> <span class="required">*</span></label><br/>
<%= text_field 'user', 'firstname' %></p>
<p><label for="user_lastname"><%=_('Lastname')%> <span class="required">*</span></label><br/>
<%= text_field 'user', 'lastname' %></p>
<p><label for="user_mail"><%=_('Mail')%> <span class="required">*</span></label><br/>
<%= text_field 'user', 'mail' %></p>
<p><label for="user_language"><%=_('Language')%></label><br/>
<%= select("user", "language", Localization.langs) %></p>
<!--[eoform:user]-->
<p><%= check_box 'user', 'mail_notification' %> <label for="user_mail_notification"><%=_('Mail notifications')%></label></p>
<center><%= submit_tag _('Save') %></center>
<%= end_form_tag %>
</div>
</div>
<div class="splitcontentright">
<div class="box">
<h3><%=_('Password')%></h3>
&nbsp;
<%= start_form_tag :action => 'change_password' %>
<p><label for="old_password"><%=_('Password')%> <span class="required">*</span></label><br/>
<%= password_field_tag 'old_password' %></p>
<p><label for="new_password"><%=_('New password')%> <span class="required">*</span></label><br/>
<%= password_field_tag 'new_password' %></p>
<p><label for="new_password_confirmation"><%=_('Confirmation')%> <span class="required">*</span></label><br/>
<%= password_field_tag 'new_password_confirmation' %></p>
<center><%= submit_tag _('Save') %></center>
<%= end_form_tag %>
</div>
</div>

View File

@ -0,0 +1,19 @@
<h2><%=_('My page') %></h2>
<p>
<%=_('Welcome')%> <b><%= @user.firstname %></b><br />
<% unless @user.last_before_login_on.nil? %>
<%=_('Last login')%>: <%= format_time(@user.last_before_login_on) %>
<% end %>
</p>
<div class="splitcontentleft">
<h3><%=_('Reported issues')%></h3>
<%= render :partial => 'issues/list_simple', :locals => { :issues => @reported_issues } %>
<%= "<p>(Last #{@reported_issues.length} updated)</p>" if @reported_issues.length > 0 %>
</div>
<div class="splitcontentright">
<h3><%=_('Assigned to me')%></h3>
<%= render :partial => 'issues/list_simple', :locals => { :issues => @assigned_issues } %>
<%= "<p>(Last #{@assigned_issues.length} updated)</p>" if @assigned_issues.length > 0 %>
</div>

View File

@ -0,0 +1,19 @@
<h2><%= @user.display_name %></h2>
<p>
<%= mail_to @user.mail %><br />
<%=_('Registered on')%>: <%= format_date(@user.created_on) %>
</p>
<h3><%=_('Projects')%></h3>
<p>
<% for membership in @user.memberships %>
<%= membership.project.name %> (<%= membership.role.name %>, <%= format_date(membership.created_on) %>)
<br />
<% end %>
</p>
<h3><%=_('Activity')%></h3>
<p>
<%=_('Reported issues')%>: <%= Issue.count( [ "author_id=?", @user.id]) %>
</p>

View File

@ -0,0 +1,45 @@
<h2><%=_('Administration')%></h2>
<p>
<%= image_tag "projects" %>
<%= link_to _('Projects'), :controller => 'admin', :action => 'projects' %> |
<%= link_to _('New'), :controller => 'projects', :action => 'add' %>
</p>
<p>
<%= image_tag "users" %>
<%= link_to _('Users'), :controller => 'users' %> |
<%= link_to _('New'), :controller => 'users', :action => 'add' %>
</p>
<p>
<%= image_tag "role" %>
<%= link_to _('Roles and permissions'), :controller => 'roles' %>
</p>
<p>
<%= image_tag "tracker" %>
<%= link_to _('Trackers'), :controller => 'trackers' %> |
<%= link_to _('Custom fields'), :controller => 'custom_fields' %>
</p>
<p>
<%= image_tag "workflow" %>
<%= link_to _('Issue Statuses'), :controller => 'issue_statuses' %> |
<%= link_to _('Workflow'), :controller => 'roles', :action => 'workflow' %>
</p>
<p>
<%= image_tag "options" %>
<%= link_to _('Enumerations'), :controller => 'enumerations' %>
</p>
<p>
<%= image_tag "mailer" %>
<%= link_to _('Mail notifications'), :controller => 'admin', :action => 'mail_options' %>
</p>
<p>
<%= image_tag "help" %>
<%= link_to _('Information'), :controller => 'admin', :action => 'info' %>
</p>

View File

@ -0,0 +1,4 @@
<h2><%=_('Information')%></h2>
<%=_('Version')%>: <%= RDM_APP_NAME %> <%= RDM_APP_VERSION %><br />
<%=_('Database')%>: <%= @adapter_name %>

View File

@ -0,0 +1,16 @@
<h2><%=_('Mail notifications')%></h2>
<p><%=_('Select actions for which mail notification should be enabled.')%></p>
<%= start_form_tag ({}, :id => 'mail_options_form')%>
<% for action in @actions %>
<%= check_box_tag "action_ids[]", action.id, action.mail_enabled? %>
<%= action.descr %><br />
<% end %>
<br />
<p>
<a href="javascript:checkAll('mail_options_form', true)"><%=_('Check all')%></a> |
<a href="javascript:checkAll('mail_options_form', false)"><%=_('Uncheck all')%></a>
</p>
<%= submit_tag _('Save') %>
<%= end_form_tag %>

View File

@ -0,0 +1,35 @@
<h2><%=_('Projects')%></h2>
<table width="100%" cellspacing="1" cellpadding="2" class="listTableContent">
<tr class="ListHead">
<%= sort_header_tag('projects.name', :caption => _('Project')) %>
<th><%=_('Description')%></th>
<th><%=_('Public')%></th>
<%= sort_header_tag('projects.created_on', :caption => _('Created on')) %>
<th></th>
</tr>
<% odd_or_even = 1
for project in @projects
odd_or_even = 1 - odd_or_even %>
<tr class="ListLine<%= odd_or_even %>">
<td><%= link_to project.name, :controller => 'projects', :action => 'settings', :id => project %>
<td><%= project.descr %>
<td align="center"><%= image_tag 'true' if project.public? %>
<td align="center"><%= format_date(project.created_on) %>
<td align="center">
<%= start_form_tag({:controller => 'projects', :action => 'destroy', :id => project}) %>
<%= submit_tag _('Delete'), :class => "button-small" %>
<%= end_form_tag %>
</td>
</tr>
<% end %>
</table>
<%= link_to ('&#171; ' + _('Previous')), { :page => @project_pages.current.previous } if @project_pages.current.previous %>
<%= pagination_links(@project_pages) %>
<%= link_to (_('Next') + ' &#187;'), { :page => @project_pages.current.next } if @project_pages.current.next %>
<br />
<%= link_to ('&#187; ' + _('New project')), :controller => 'projects', :action => 'add' %>

View File

@ -0,0 +1,26 @@
<%= error_messages_for 'custom_field' %>
<!--[form:custom_field]-->
<p><label for="custom_field_name"><%=_('Name')%></label><br/>
<%= text_field 'custom_field', 'name' %></p>
<p><label for="custom_field_typ"><%=_('Type')%></label><br/>
<%= select("custom_field", "typ", CustomField::TYPES) %></p>
<p><%= check_box 'custom_field', 'is_required' %>
<label for="custom_field_is_required"><%=_('Required')%></label></p>
<p><%= check_box 'custom_field', 'is_for_all' %>
<label for="custom_field_is_for_all"><%=_('For all projects')%></label></p>
<p><label for="custom_field_min_length"><%=_('Min - max length')%></label> (<%=_('0 means no restriction')%>)<br/>
<%= text_field 'custom_field', 'min_length', :size => 5 %> -
<%= text_field 'custom_field', 'max_length', :size => 5 %></p>
<p><label for="custom_field_regexp"><%=_('Regular expression pattern')%></label> (eg. ^[A-Z0-9]+$)<br/>
<%= text_field 'custom_field', 'regexp', :size => 50 %></p>
<p><label for="custom_field_possible_values"><%=_('Possible values')%></label> (separator: |)<br/>
<%= text_area 'custom_field', 'possible_values', :rows => 5, :cols => 60 %></p>
<!--[eoform:custom_field]-->

View File

@ -0,0 +1,6 @@
<h2><%=_('Custom field')%></h2>
<%= start_form_tag :action => 'edit', :id => @custom_field %>
<%= render :partial => 'form' %>
<%= submit_tag _('Save') %>
<%= end_form_tag %>

View File

@ -0,0 +1,32 @@
<h2><%=_('Custom fields')%></h2>
<table border="0" cellspacing="1" cellpadding="2" class="listTableContent">
<tr class="ListHead">
<th><%=_('Name')%></th>
<th><%=_('Type')%></th>
<th><%=_('Required')%></th>
<th><%=_('For all projects')%></th>
<th><%=_('Used by')%></th>
<th></th>
</tr>
<% for custom_field in @custom_fields %>
<tr style="background-color:#CEE1ED">
<td><%= link_to custom_field.name, :action => 'edit', :id => custom_field %></td>
<td align="center"><%= CustomField::TYPES[custom_field.typ][0] %></td>
<td align="center"><%= image_tag 'true' if custom_field.is_required? %></td>
<td align="center"><%= image_tag 'true' if custom_field.is_for_all? %></td>
<td align="center"><%= custom_field.projects.count.to_s + ' ' + _('Project') + '(s)' unless custom_field.is_for_all? %></td>
<td align="center">
<%= start_form_tag :action => 'destroy', :id => custom_field %>
<%= submit_tag _('Delete'), :class => "button-small" %>
<%= end_form_tag %> </td>
</tr>
<% end %>
</table>
<%= link_to ('&#171; ' + _('Previous')), { :page => @custom_field_pages.current.previous } if @custom_field_pages.current.previous %>
<%= link_to (_('Next') + ' &#187;'), { :page => @custom_field_pages.current.next } if @custom_field_pages.current.next %>
<br />
<%= link_to ('&#187; ' + _('New custom field')), :action => 'new' %>

View File

@ -0,0 +1,7 @@
<h2><%=_('New custom field')%></h2>
<%= start_form_tag :action => 'new' %>
<%= render :partial => 'form' %>
<%= submit_tag _('Create') %>
<%= end_form_tag %>

View File

@ -0,0 +1,15 @@
<%= error_messages_for 'document' %>
<!--[form:document]-->
<p><label for="document_category_id"><%=_('Category')%></label><br />
<select name="document[category_id]">
<%= options_from_collection_for_select @categories, "id", "name",@document.category_id %>
</select></p>
<p><label for="document_title"><%=_('Title')%> <span class="required">*</span></label><br />
<%= text_field 'document', 'title', :size => 60 %></p>
<p><label for="document_descr"><%=_('Description')%> <span class="required">*</span></label><br />
<%= text_area 'document', 'descr', :cols => 60, :rows => 5 %></p>
<!--[eoform:document]-->

View File

@ -0,0 +1,8 @@
<h2><%=_('Document')%></h2>
<%= start_form_tag :action => 'edit', :id => @document %>
<%= render :partial => 'form' %>
<%= submit_tag _('Save') %>
<%= end_form_tag %>

View File

@ -0,0 +1,45 @@
<h2><%= @document.title %></h2>
<strong><%=_('Description')%>:</strong> <%= @document.descr %><br />
<strong><%=_('Category')%>:</strong> <%= @document.category.name %><br />
<br />
<% if authorize_for('documents', 'edit') %>
<%= start_form_tag ({ :controller => 'documents', :action => 'edit', :id => @document }, :method => 'get' ) %>
<%= submit_tag _('Edit') %>
<%= end_form_tag %>
<% end %>
<% if authorize_for('documents', 'destroy') %>
<%= start_form_tag ({ :controller => 'documents', :action => 'destroy', :id => @document } ) %>
<%= submit_tag _('Delete') %>
<%= end_form_tag %>
<% end %>
<br /><br />
<table border="0" cellspacing="1" cellpadding="2" width="100%">
<% for attachment in @document.attachments %>
<tr style="background-color:#CEE1ED">
<td><%= link_to attachment.filename, :action => 'download', :id => @document, :attachment_id => attachment %></td>
<td align="center"><%= format_date(attachment.created_on) %></td>
<td align="center"><%= attachment.author.display_name %></td>
<td><%= human_size(attachment.size) %><br /><%= attachment.downloads %> <%=_('download')%>(s)</td>
<% if authorize_for('documents', 'destroy_attachment') %>
<td align="center">
<%= start_form_tag :action => 'destroy_attachment', :id => @document, :attachment_id => attachment %>
<%= submit_tag _('Delete'), :class => "button-small" %>
<%= end_form_tag %>
</tr>
<% end %>
<% end %>
</table>
<br />
<% if authorize_for('documents', 'add_attachment') %>
<%= start_form_tag ({ :controller => 'documents', :action => 'add_attachment', :id => @document }, :multipart => true) %>
<%=_('Add file')%><br /><%= file_field 'attachment', 'file' %>
<%= submit_tag _('Add') %>
<%= end_form_tag %>
<% end %>

View File

@ -0,0 +1,9 @@
<%= error_messages_for 'enumeration' %>
<!--[form:optvalue]-->
<%= hidden_field 'enumeration', 'opt' %>
<p><label for="enumeration_name"><%=_('Name')%></label><br/>
<%= text_field 'enumeration', 'name' %></p>
<!--[eoform:optvalue]-->

View File

@ -0,0 +1,10 @@
<h2><%=_('Enumerations')%></h2>
<%= start_form_tag :action => 'update', :id => @enumeration %>
<%= render :partial => 'form' %>
<%= submit_tag _('Save') %>
<%= end_form_tag %>
<%= start_form_tag :action => 'destroy', :id => @enumeration %>
<%= submit_tag _('Delete') %>
<%= end_form_tag %>

View File

@ -0,0 +1,22 @@
<h2><%=_('Enumerations')%></h2>
<% for option in Enumeration::OPTIONS %>
<% if @params[:opt]==option[1] %>
<p><%= image_tag 'dir_open' %> <b><%=_ option[0] %></b></p>
<ul>
<% for value in Enumeration::find(:all, :conditions => [ "opt = ?", option[1]]) %>
<li><%= link_to value.name, :action => 'edit', :id => value %></li>
<% end %>
</ul>
<ul>
<li><%= link_to ('&#187; ' + _('New')), :action => 'new', :opt => option[1] %></li>
</ul>
<% else %>
<p><%= image_tag 'dir' %> <%= link_to _(option[0]), :opt => option[1] %></p>
<% end %>
<% end %>

View File

@ -0,0 +1,6 @@
<h2><%=_('New enumeration')%></h2>
<%= start_form_tag :action => 'create' %>
<%= render :partial => 'form' %>
<%= submit_tag _('Create') %>
<%= end_form_tag %>

View File

@ -0,0 +1,7 @@
<%= error_messages_for 'issue_category' %>
<!--[form:issue_category]-->
<p><label for="issue_category_name"><%=_('Name')%></label><br/>
<%= text_field 'issue_category', 'name' %></p>
<!--[eoform:issue_category]-->

View File

@ -0,0 +1,6 @@
<h2>Editing issue category</h2>
<%= start_form_tag :action => 'edit', :id => @category %>
<%= render :partial => 'form' %>
<%= submit_tag _('Save') %>
<%= end_form_tag %>

View File

@ -0,0 +1,17 @@
<%= error_messages_for 'issue_status' %>
<!--[form:issue_status]-->
<p><label for="issue_status_name"><%=_('Name')%></label><br/>
<%= text_field 'issue_status', 'name' %></p>
<p><%= check_box 'issue_status', 'is_closed' %>
<label for="issue_status_is_closed"><%=_('Issue closed')%></label></p>
<p><%= check_box 'issue_status', 'is_default' %>
<label for="issue_status_is_default"><%=_('Default status')%></label></p>
<p><label for="issue_status_html_color"><%=_('Color')%></label>
#<%= text_field 'issue_status', 'html_color', :size => 6 %></p>
<!--[eoform:issue_status]-->

View File

@ -0,0 +1,6 @@
<h2><%=_('Issue status')%></h2>
<%= start_form_tag :action => 'update', :id => @issue_status %>
<%= render :partial => 'form' %>
<%= submit_tag _('Save') %>
<%= end_form_tag %>

View File

@ -0,0 +1,30 @@
<h2><%=_('Issue statuses')%></h2>
<table border="0" cellspacing="1" cellpadding="2" class="listTableContent">
<tr class="ListHead">
<th><%=_('Status')%></th>
<th><%=_('Default status')%></th>
<th><%=_('Issue closed')%></th>
<th><%=_('Color')%></th>
<th></th>
</tr>
<% for status in @issue_statuses %>
<tr style="background-color:#CEE1ED">
<td><%= link_to status.name, :action => 'edit', :id => status %></td>
<td align="center"><%= image_tag 'true' if status.is_default %></td>
<td align="center"><%= image_tag 'true' if status.is_closed %></td>
<td bgcolor="#<%= status.html_color %>">&nbsp</td>
<td align="center">
<%= start_form_tag :action => 'destroy', :id => status %>
<%= submit_tag _('Delete'), :class => "button-small" %>
<%= end_form_tag %>
</td>
</tr>
<% end %>
</table>
<%= pagination_links_full @issue_status_pages %>
<br />
<%= link_to '&#187; ' + _('New issue status'), :action => 'new' %>

View File

@ -0,0 +1,6 @@
<h2><%=_('New issue status')%></h2>
<%= start_form_tag :action => 'create' %>
<%= render :partial => 'form' %>
<%= submit_tag _('Create') %>
<%= end_form_tag %>

View File

@ -0,0 +1,28 @@
<% if issues.length > 0 %>
<table cellspacing="0" cellpadding="1" width="100%" border="0" class="listTable">
<tr><td>
<table width="100%" border="0" cellspacing="1" cellpadding="2" class="listTableContent">
<tr class="ListHead">
<th>#</th>
<th><%=_('Tracker')%></th>
<th><%=_('Subject')%></th>
</tr>
<% for issue in issues %>
<tr bgcolor="#<%= issue.status.html_color %>">
<td align="center">
<%= link_to issue.id, :controller => 'issues', :action => 'show', :id => issue %><br />
</td>
<td><p class="small"><%= issue.project.name %> - <%= issue.tracker.name %><br />
<%= issue.status.name %> - <%= format_time(issue.updated_on) %></p></td>
<td>
<p class="small"><%= link_to issue.subject, :controller => 'issues', :action => 'show', :id => issue %></p>
</td>
</tr>
<% end %>
</table>
</td>
</tr>
</table>
<% else %>
<%=_('No issue')%>
<% end %>

View File

@ -0,0 +1,29 @@
<h2><%=_('Issue')%> #<%= @issue.id %>: <%= @issue.subject %></h2>
<%= error_messages_for 'history' %>
<%= start_form_tag :action => 'change_status', :id => @issue %>
<%= hidden_field_tag 'confirm', 1 %>
<%= hidden_field 'history', 'status_id' %>
<p><%=_('New status')%>: <b><%= @history.status.name %></b></p>
<div>
<p><label for="issue_assigned_to_id"><%=_('Assigned to')%></label><br/>
<select name="issue[assigned_to_id]">
<option value=""></option>
<%= options_from_collection_for_select @assignable_to, "id", "display_name", @issue.assigned_to_id %></p>
</select></p>
</div>
<p><label for="issue_fixed_version"><%=_('Fixed in version')%></label><br/>
<select name="issue[fixed_version_id]">
<option value="">--none--</option>
<%= options_from_collection_for_select @issue.project.versions, "id", "name", @issue.fixed_version_id %>
</select></p>
<p><label for="history_notes"><%=_('Notes')%></label><br />
<%= text_area 'history', 'notes', :cols => 60, :rows => 10 %></p>
<%= submit_tag _('Save') %>
<%= end_form_tag %>

View File

@ -0,0 +1,62 @@
<h2><%=_('Issue')%> #<%= @issue.id %></h2>
<%= error_messages_for 'issue' %>
<%= start_form_tag :action => 'edit', :id => @issue %>
<!--[form:issue]-->
<p><%=_('Status')%>: <b><%= @issue.status.name %></b></p>
<div style="float:left;margin-right:10px;">
<p><label for="issue_tracker_id"><%=_('Tracker')%> <span class="required">*</span></label><br/>
<select name="issue[tracker_id]">
<%= options_from_collection_for_select @trackers, "id", "name", @issue.tracker_id %></p>
</select></p>
</div>
<div style="float:left;margin-right:10px;">
<p><label for="issue_priority_id"><%=_('Priority')%> <span class="required">*</span></label><br/>
<select name="issue[priority_id]">
<%= options_from_collection_for_select @priorities, "id", "name", @issue.priority_id %></p>
</select></p>
</div>
<div style="float:left;margin-right:10px;">
<p><label for="issue_assigned_to_id"><%=_('Assigned to')%></label><br/>
<select name="issue[assigned_to_id]">
<option value=""></option>
<%= options_from_collection_for_select @issue.project.members, "user_id", "name", @issue.assigned_to_id %></p>
</select></p>
</div>
<div>
<p><label for="issue_category_id"><%=_('Category')%></label><br/>
<select name="issue[category_id]">
<option value=""></option>
<%= options_from_collection_for_select @project.issue_categories, "id", "name", @issue.category_id %></p>
</select></p>
</div>
<p><label for="issue_subject"><%=_('Subject')%></label><span class="required">*</span><br/>
<%= text_field 'issue', 'subject', :size => 60 %></p>
<p><label for="issue_descr"><%=_('Description')%></label><span class="required">*</span><br/>
<%= text_area 'issue', 'descr', :cols => 60, :rows => 10 %></p>
<% for custom_value in @custom_values %>
<p><%= content_tag "label", custom_value.custom_field.name %>
<% if custom_value.custom_field.is_required? %><span class="required">*</span><% end %>
<br />
<%= custom_field_tag custom_value %></p>
<% end %>
<p><label for="issue_fixed_version"><%=_('Fixed in version')%></label><br/>
<select name="issue[fixed_version_id]">
<option value="">--none--</option>
<%= options_from_collection_for_select @project.versions, "id", "name", @issue.fixed_version_id %>
</select></p>
<!--[eoform:issue]-->
<center><%= submit_tag _('Save') %></center>
<%= end_form_tag %>

View File

@ -0,0 +1,90 @@
<h2><%=_('Issue')%> #<%= @issue.id %> - <%= @issue.subject %></h2>
<div class="box">
<p><b><%=_('Tracker')%>:</b> <%= @issue.tracker.name %></p>
<p><b><%=_('Priority')%>:</b> <%= @issue.priority.name %></p>
<p><b><%=_('Category')%>:</b> <%= @issue.category.name unless @issue.category_id.nil? %></p>
<p><b><%=_('Status')%>:</b> <%= @issue.status.name %></p>
<p><b><%=_('Author')%>:</b> <%= @issue.author.display_name %></p>
<p><b><%=_('Assigned to')%>:</b> <%= @issue.assigned_to.display_name unless @issue.assigned_to.nil? %></p>
<p><b><%=_('Subject')%>:</b> <%= @issue.subject %></p>
<p><b><%=_('Description')%>:</b> <%= @issue.descr %></p>
<p><b><%=_('Created on')%>:</b> <%= format_date(@issue.created_on) %></p>
<% if authorize_for('issues', 'edit') %>
<%= start_form_tag ({:controller => 'issues', :action => 'edit', :id => @issue}, :method => "get" ) %>
<%= submit_tag _('Edit') %>
<%= end_form_tag %>
&nbsp;&nbsp;
<% end %>
<% if authorize_for('issues', 'change_status') and @status_options and !@status_options.empty? %>
<%= start_form_tag ({:controller => 'issues', :action => 'change_status', :id => @issue}) %>
<label for="history_status_id"><%=_('Change status')%>:</label>
<select name="history[status_id]">
<%= options_from_collection_for_select @status_options, "id", "name" %>
</select>
<%= submit_tag _ "Update..." %>
<%= end_form_tag %>
&nbsp;&nbsp;
<% end %>
<% if authorize_for('issues', 'destroy') %>
<%= start_form_tag ({:controller => 'issues', :action => 'destroy', :id => @issue} ) %>
<%= submit_tag _ "Delete" %>
<%= end_form_tag %>
&nbsp;&nbsp;
<% end %>
</div>
<div class="splitcontentleft">
<div class="box">
<h3><%=_('History')%></h3>
<table width="100%">
<% for history in @issue.histories.find(:all, :include => :author) %>
<tr>
<td><%= format_date(history.created_on) %></td>
<td><%= history.author.display_name %></td>
<td><b><%= history.status.name %></b></td>
</tr>
<% if history.notes? %>
<tr><td colspan=3><div class="notes"><%= history.notes %></td></tr>
<% end %>
<% end %>
</table>
</div>
</div>
<div class="splitcontentright">
<div class="box">
<h3><%=_('Attachments')%></h3>
<table width="100%">
<% for attachment in @issue.attachments %>
<tr>
<td><%= link_to attachment.filename, :action => 'download', :id => @issue, :attachment_id => attachment %> (<%= human_size(attachment.size) %>)</td>
<td><%= format_date(attachment.created_on) %></td>
<td><%= attachment.author.display_name %></td>
<% if authorize_for('issues', 'destroy_attachment') %>
<td>
<%= start_form_tag :action => 'destroy_attachment', :id => @issue, :attachment_id => attachment %>
<%= submit_tag _('Delete'), :class => "button-small" %>
<%= end_form_tag %>
</td>
<% end %>
</tr>
<% end %>
</table>
<br />
<% if authorize_for('issues', 'add_attachment') %>
<%= start_form_tag ({ :controller => 'issues', :action => 'add_attachment', :id => @issue }, :multipart => true) %>
<%=_('Add file')%>: <%= file_field 'attachment', 'file' %>
<%= submit_tag _('Add') %>
<%= end_form_tag %>
<% end %>
</div>
</div>

View File

@ -0,0 +1,89 @@
<!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">
<head>
<title>redMine</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta name="description" content="redMine" />
<meta name="keywords" content="issue,bug,tracker" />
<%= stylesheet_link_tag "application" %>
<%= stylesheet_link_tag "rails" %>
<%= javascript_include_tag :defaults %>
</head>
<body>
<div id="container" >
<div id="header">
<div style="float: left;">
<h1><%= RDM_APP_NAME %></h1>
<h2>Project management</h2>
</div>
<div style="float: right; padding-right: 1em; padding-top: 0.2em;">
<% unless session[:user].nil? %><small><%=_('Logged as')%> <b><%= session[:user].login %></b></small><% end %>
</div>
</div>
<div id="navigation">
<ul>
<li class="selected"><%= link_to _('Home'), { :controller => '' }, :class => "picHome" %></li>
<li><%= link_to _('My page'), { :controller => 'account', :action => 'my_page'}, :class => "picUserPage" %></li>
<li><%= link_to _('Projects'), { :controller => 'projects' }, :class => "picProject" %></li>
<% unless session[:user].nil? %>
<li><%= link_to _('My account'), { :controller => 'account', :action => 'my_account' }, :class => "picUser" %></li>
<% end %>
<% if admin_loggedin? %>
<li><%= link_to _('Administration'), { :controller => 'admin' }, :class => "picAdmin" %></li>
<% end %>
<li class="right"><%= link_to _('Help'), { :controller => 'help', :ctrl => @params[:controller], :page => @params[:action] }, :target => "new", :class => "picHelp" %></li>
<% if session[:user].nil? %>
<li class="right"><%= link_to _('Log in'), { :controller => 'account', :action => 'login' }, :class => "picUser" %></li>
<% else %>
<li class="right"><%= link_to _('Logout'), { :controller => 'account', :action => 'logout' }, :class => "picUser" %></li>
<% end %>
</ul>
</div>
<div id="subcontent">
<% unless @project.nil? || @project.id.nil? %>
<h2><%= @project.name %></h2>
<ul class="menublock">
<li><%= link_to _('Overview'), :controller => 'projects', :action => 'show', :id => @project %></li>
<li><%= link_to _('Issues'), :controller => 'projects', :action => 'list_issues', :id => @project %></li>
<li><%= link_to _('Reports'), :controller => 'reports', :action => 'issue_report', :id => @project %></li>
<li><%= link_to _('News'), :controller => 'projects', :action => 'list_news', :id => @project %></li>
<li><%= link_to _('Change log'), :controller => 'projects', :action => 'changelog', :id => @project %></li>
<li><%= link_to _('Documents'), :controller => 'projects', :action => 'list_documents', :id => @project %></li>
<li><%= link_to _('Members'), :controller => 'projects', :action => 'list_members', :id => @project %></li>
<li><%= link_to _('Files'), :controller => 'projects', :action => 'list_files', :id => @project %></li>
<li><%= link_to_if_authorized _('Settings'), :controller => 'projects', :action => 'settings', :id => @project %></li>
</ul>
<% end %>
<% unless session[:user].nil? %>
<h2><%=_('My projects') %></h2>
<ul class="menublock">
<% for membership in session[:user].memberships %>
<li><%= link_to membership.project.name, :controller => 'projects', :action => 'show', :id => membership.project %></li>
<% end %>
</ul>
<% end %>
</div>
<div id="content">
<% if flash[:notice] %><p style="color: green"><%= flash[:notice] %></p><% end %>
<%= @content_for_layout %>
</div>
<div id="footer">
<p><a href="http://redmine.sourceforge.net/" target="_new"><%= RDM_APP_NAME %></a> <%= RDM_APP_VERSION %></p>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,6 @@
<%=_('Issue')%> #<%= issue.id %> - <%= issue.subject %>
<%=_('Author')%>: <%= issue.author.display_name %>
<%= issue.descr %>
http://<%= RDM_HOST_NAME %>/issues/show/<%= issue.id %>

View File

@ -0,0 +1,3 @@
Issue #<%= @issue.id %> has been reported.
----------------------------------------
<%= render :file => "_issue", :use_full_path => true, :locals => { :issue => @issue } %>

View File

@ -0,0 +1,3 @@
Issue #<%= @issue.id %> has been updated to "<%= @issue.status.name %>" status.
----------------------------------------
<%= render :file => "_issue", :use_full_path => true, :locals => { :issue => @issue } %>

View File

@ -0,0 +1,13 @@
<%= error_messages_for 'news' %>
<!--[form:news]-->
<p><label for="news_title"><%=_('Title')%></label> <span class="required">*</span><br/>
<%= text_field 'news', 'title', :size => 60 %></p>
<p><label for="news_shortdescr"><%=_('Summary')%> <span class="required">*</span></label><br/>
<%= text_area 'news', 'shortdescr', :cols => 60, :rows => 2 %></p>
<p><label for="news_descr"><%=_('Description')%> <span class="required">*</span></label><br/>
<%= text_area 'news', 'descr', :cols => 60, :rows => 10 %></p>
<!--[eoform:news]-->

View File

@ -0,0 +1,6 @@
<h2><%=_('News')%></h2>
<%= start_form_tag :action => 'edit', :id => @news %>
<%= render :partial => 'form' %>
<%= submit_tag _('Save') %>
<%= end_form_tag %>

View File

@ -0,0 +1,10 @@
<h2><%= @news.title %></h2>
<p>
<b><%=_('Summary')%></b>: <%= @news.shortdescr %><br />
<b><%=_('By')%></b>: <%= @news.author.display_name %><br />
<b><%=_('Date')%></b>: <%= format_time(@news.created_on) %>
</p>
<%= @news.descr %>

View File

@ -0,0 +1,28 @@
<%= error_messages_for 'project' %>
<!--[form:project]-->
<p><label for="project_name"><%=_('Name')%> <span class="required">*</span></label><br/>
<%= text_field 'project', 'name' %></p>
<p><label for="project_descr"><%=_('Description')%> <span class="required">*</span></label><br/>
<%= text_field 'project', 'descr', :size => 60 %></p>
<p><label for="project_homepage"><%=_('Homepage')%></label><br/>
<%= text_field 'project', 'homepage', :size => 40 %></p>
<p><%= check_box 'project', 'public' %>
<label for="project_public"><%=_('Public')%></label></p>
<fieldset><legend><%=_('Custom fields')%></legend>
<% for custom_field in @custom_fields %>
<input type="checkbox"
name="custom_field_ids[]"
value="<%= custom_field.id %>"
<%if @project.custom_fields.include? custom_field%>checked="checked"<%end%>
> <%= custom_field.name %>
<% end %></fieldset>
<br />
<!--[eoform:project]-->

View File

@ -0,0 +1,7 @@
<h2><%=_('New project')%></h2>
<%= start_form_tag :action => 'add' %>
<%= render :partial => 'form' %>
<%= submit_tag _('Create') %>
<%= end_form_tag %>

View File

@ -0,0 +1,26 @@
<h2><%=_('New document')%></h2>
<%= error_messages_for 'document' %>
<%= start_form_tag( { :action => 'add_document', :id => @project }, :multipart => true) %>
<!--[form:document]-->
<p><label for="document_category_id"><%=_('Category')%></label><br />
<select name="document[category_id]">
<%= options_from_collection_for_select @categories, "id", "name",@document.category_id %>
</select></p>
<p><label for="document_title"><%=_('Title')%> <span class="required">*</span></label><br />
<%= text_field 'document', 'title', :size => 60 %></p>
<p><label for="document_descr"><%=_('Description')%> <span class="required">*</span></label><br />
<%= text_area 'document', 'descr', :cols => 60, :rows => 5 %></p>
<p><label for="attachment_file"><%=_('File')%></label><br/>
<%= file_field 'attachment', 'file' %></p>
<!--[eoform:document]-->
<%= submit_tag _('Create') %>
<%= end_form_tag %>

View File

@ -0,0 +1,13 @@
<h2><%=_('New file')%></h2>
<%= start_form_tag ({ :action => 'add_file', :project => @project }, :multipart => true) %>
<p><label for="version_id"><%=_('Version')%></label><br />
<select name="version_id">
<%= options_from_collection_for_select @versions, "id", "name" %>
</select></p>
<p><b><%=_('File')%><b><br /><%= file_field 'attachment', 'file' %></p>
<br/>
<%= submit_tag _('Add') %>
<%= end_form_tag %>

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