git-svn-id: http://redmine.rubyforge.org/svn/trunk@4 e93f8b46-1217-0410-a6f0-8f06a7374b81tags/0.2.0
@@ -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' |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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(('« ' + _('Previous') ), { :page => paginator.current.previous }) + ' ' if paginator.current.previous | |||
html << (pagination_links(paginator, options, html_options) || '') | |||
html << ' ' + link_to((_('Next') + ' »'), { :page => paginator.current.next }) if paginator.current.next | |||
html | |||
end | |||
end |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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&sort_key=id">Id</a> | |||
# <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) | |||
' ' * n | |||
end | |||
# Return capitalized title. | |||
def titleize(title) | |||
title.split.map {|w| w.capitalize }.join(' ') | |||
end | |||
end |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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' %> »" class="primary" /></p> | |||
<%= end_form_tag %> | |||
</div> |
@@ -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> | |||
| |||
<%= 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> | |||
| |||
<%= 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> |
@@ -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> |
@@ -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> |
@@ -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> |
@@ -0,0 +1,4 @@ | |||
<h2><%=_('Information')%></h2> | |||
<%=_('Version')%>: <%= RDM_APP_NAME %> <%= RDM_APP_VERSION %><br /> | |||
<%=_('Database')%>: <%= @adapter_name %> |
@@ -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 %> |
@@ -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 ('« ' + _('Previous')), { :page => @project_pages.current.previous } if @project_pages.current.previous %> | |||
<%= pagination_links(@project_pages) %> | |||
<%= link_to (_('Next') + ' »'), { :page => @project_pages.current.next } if @project_pages.current.next %> | |||
<br /> | |||
<%= link_to ('» ' + _('New project')), :controller => 'projects', :action => 'add' %> |
@@ -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]--> | |||
@@ -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 %> |
@@ -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 ('« ' + _('Previous')), { :page => @custom_field_pages.current.previous } if @custom_field_pages.current.previous %> | |||
<%= link_to (_('Next') + ' »'), { :page => @custom_field_pages.current.next } if @custom_field_pages.current.next %> | |||
<br /> | |||
<%= link_to ('» ' + _('New custom field')), :action => 'new' %> |
@@ -0,0 +1,7 @@ | |||
<h2><%=_('New custom field')%></h2> | |||
<%= start_form_tag :action => 'new' %> | |||
<%= render :partial => 'form' %> | |||
<%= submit_tag _('Create') %> | |||
<%= end_form_tag %> | |||
@@ -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]--> | |||
@@ -0,0 +1,8 @@ | |||
<h2><%=_('Document')%></h2> | |||
<%= start_form_tag :action => 'edit', :id => @document %> | |||
<%= render :partial => 'form' %> | |||
<%= submit_tag _('Save') %> | |||
<%= end_form_tag %> | |||
@@ -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 %> | |||
@@ -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]--> | |||
@@ -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 %> |
@@ -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 ('» ' + _('New')), :action => 'new', :opt => option[1] %></li> | |||
</ul> | |||
<% else %> | |||
<p><%= image_tag 'dir' %> <%= link_to _(option[0]), :opt => option[1] %></p> | |||
<% end %> | |||
<% end %> | |||
@@ -0,0 +1,6 @@ | |||
<h2><%=_('New enumeration')%></h2> | |||
<%= start_form_tag :action => 'create' %> | |||
<%= render :partial => 'form' %> | |||
<%= submit_tag _('Create') %> | |||
<%= end_form_tag %> |
@@ -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]--> | |||
@@ -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 %> |
@@ -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]--> | |||
@@ -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 %> |
@@ -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 %>"> </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 '» ' + _('New issue status'), :action => 'new' %> |
@@ -0,0 +1,6 @@ | |||
<h2><%=_('New issue status')%></h2> | |||
<%= start_form_tag :action => 'create' %> | |||
<%= render :partial => 'form' %> | |||
<%= submit_tag _('Create') %> | |||
<%= end_form_tag %> |
@@ -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 %> |
@@ -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 %> |
@@ -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 %> |
@@ -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 %> | |||
| |||
<% 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 %> | |||
| |||
<% end %> | |||
<% if authorize_for('issues', 'destroy') %> | |||
<%= start_form_tag ({:controller => 'issues', :action => 'destroy', :id => @issue} ) %> | |||
<%= submit_tag _ "Delete" %> | |||
<%= end_form_tag %> | |||
| |||
<% 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> | |||
@@ -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> |
@@ -0,0 +1,6 @@ | |||
<%=_('Issue')%> #<%= issue.id %> - <%= issue.subject %> | |||
<%=_('Author')%>: <%= issue.author.display_name %> | |||
<%= issue.descr %> | |||
http://<%= RDM_HOST_NAME %>/issues/show/<%= issue.id %> |
@@ -0,0 +1,3 @@ | |||
Issue #<%= @issue.id %> has been reported. | |||
---------------------------------------- | |||
<%= render :file => "_issue", :use_full_path => true, :locals => { :issue => @issue } %> |
@@ -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 } %> |
@@ -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]--> | |||
@@ -0,0 +1,6 @@ | |||
<h2><%=_('News')%></h2> | |||
<%= start_form_tag :action => 'edit', :id => @news %> | |||
<%= render :partial => 'form' %> | |||
<%= submit_tag _('Save') %> | |||
<%= end_form_tag %> |
@@ -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 %> | |||
@@ -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]--> |
@@ -0,0 +1,7 @@ | |||
<h2><%=_('New project')%></h2> | |||
<%= start_form_tag :action => 'add' %> | |||
<%= render :partial => 'form' %> | |||
<%= submit_tag _('Create') %> | |||
<%= end_form_tag %> | |||
@@ -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 %> | |||