Compare commits

..
1 Commits
Author SHA1 Message Date
Jean-Philippe Lang 3fa3b14afe tagged version 0.6.0
git-svn-id: http://redmine.rubyforge.org/svn/tags/0.6.0@884 e93f8b46-1217-0410-a6f0-8f06a7374b81
2007-11-04 14:05:15 +00:00
337 changed files with 1706 additions and 14602 deletions
+25 -47
View File
@@ -21,7 +21,7 @@ class AccountController < ApplicationController
include CustomFieldsHelper include CustomFieldsHelper
# prevents login action to be filtered by check_if_login_required application scope filter # prevents login action to be filtered by check_if_login_required application scope filter
skip_before_filter :check_if_login_required, :only => [:login, :lost_password, :register, :activate] skip_before_filter :check_if_login_required, :only => [:login, :lost_password, :register]
# Show user's account # Show user's account
def show def show
@@ -106,62 +106,40 @@ class AccountController < ApplicationController
# User self-registration # User self-registration
def register def register
redirect_to(home_url) && return unless Setting.self_registration? redirect_to(home_url) && return unless Setting.self_registration?
if request.get? if params[:token]
@user = User.new(:language => Setting.default_language) token = Token.find_by_action_and_value("register", params[:token])
@custom_values = UserCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @user) } redirect_to(home_url) && return unless token and !token.expired?
user = token.user
redirect_to(home_url) && return unless user.status == User::STATUS_REGISTERED
user.status = User::STATUS_ACTIVE
if user.save
token.destroy
flash[:notice] = l(:notice_account_activated)
redirect_to :action => 'login'
return
end
else else
@user = User.new(params[:user]) if request.get?
@user.admin = false @user = User.new(:language => Setting.default_language)
@user.login = params[:user][:login] @custom_values = UserCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @user) }
@user.status = User::STATUS_REGISTERED else
@user.password, @user.password_confirmation = params[:password], params[:password_confirmation] @user = User.new(params[:user])
@custom_values = UserCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, @user.admin = false
:customized => @user, @user.login = params[:user][:login]
:value => (params["custom_fields"] ? params["custom_fields"][x.id.to_s] : nil)) } @user.status = User::STATUS_REGISTERED
@user.custom_values = @custom_values @user.password, @user.password_confirmation = params[:password], params[:password_confirmation]
case Setting.self_registration @custom_values = UserCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @user, :value => params["custom_fields"][x.id.to_s]) }
when '1' @user.custom_values = @custom_values
# Email activation
token = Token.new(:user => @user, :action => "register") token = Token.new(:user => @user, :action => "register")
if @user.save and token.save if @user.save and token.save
Mailer.deliver_register(token) Mailer.deliver_register(token)
flash[:notice] = l(:notice_account_register_done) flash[:notice] = l(:notice_account_register_done)
redirect_to :action => 'login' redirect_to :controller => 'account', :action => 'login'
end
when '3'
# Automatic activation
@user.status = User::STATUS_ACTIVE
if @user.save
flash[:notice] = l(:notice_account_activated)
redirect_to :action => 'login'
end
else
# Manual activation by the administrator
if @user.save
# Sends an email to the administrators
Mailer.deliver_account_activation_request(@user)
flash[:notice] = l(:notice_account_pending)
redirect_to :action => 'login'
end end
end end
end end
end end
# Token based account activation
def activate
redirect_to(home_url) && return unless Setting.self_registration? && params[:token]
token = Token.find_by_action_and_value('register', params[:token])
redirect_to(home_url) && return unless token and !token.expired?
user = token.user
redirect_to(home_url) && return unless user.status == User::STATUS_REGISTERED
user.status = User::STATUS_ACTIVE
if user.save
token.destroy
flash[:notice] = l(:notice_account_activated)
end
redirect_to :action => 'login'
end
private private
def logged_user=(user) def logged_user=(user)
if user && user.is_a?(User) if user && user.is_a?(User)
+2 -3
View File
@@ -48,9 +48,8 @@ class AdminController < ApplicationController
def mail_options def mail_options
@notifiables = %w(issue_added issue_updated news_added document_added file_added message_posted) @notifiables = %w(issue_added issue_updated news_added document_added file_added message_posted)
if request.post? if request.post?
settings = (params[:settings] || {}).dup.symbolize_keys Setting.notified_events = (params[:notified_events] || [])
settings[:notified_events] ||= [] Setting.emails_footer = params[:emails_footer] if params[:emails_footer]
settings.each { |name, value| Setting[name] = value }
flash[:notice] = l(:notice_successful_update) flash[:notice] = l(:notice_successful_update)
redirect_to :controller => 'admin', :action => 'mail_options' redirect_to :controller => 'admin', :action => 'mail_options'
end end
+4 -13
View File
@@ -23,6 +23,10 @@ class ApplicationController < ActionController::Base
require_dependency "repository/#{scm.underscore}" require_dependency "repository/#{scm.underscore}"
end end
def logged_in_user
User.current.logged? ? User.current : nil
end
def current_role def current_role
@current_role ||= User.current.role_for_project(@project) @current_role ||= User.current.role_for_project(@project)
end end
@@ -145,19 +149,6 @@ class ApplicationController < ActionController::Base
self.class.read_inheritable_attribute('accept_key_auth_actions') || [] self.class.read_inheritable_attribute('accept_key_auth_actions') || []
end end
# TODO: move to model
def attach_files(obj, files)
attachments = []
if files && files.is_a?(Array)
files.each do |file|
next unless file.size > 0
a = Attachment.create(:container => obj, :file => file, :author => User.current)
attachments << a unless a.new_record?
end
end
attachments
end
# qvalues http header parser # qvalues http header parser
# code taken from webrick # code taken from webrick
def parse_qvalues(value) def parse_qvalues(value)
+3 -2
View File
@@ -32,6 +32,7 @@ class BoardsController < ApplicationController
if @boards.size == 1 if @boards.size == 1
@board = @boards.first @board = @boards.first
show show
render :action => 'show'
end end
end end
@@ -41,11 +42,11 @@ class BoardsController < ApplicationController
@topic_count = @board.topics.count @topic_count = @board.topics.count
@topic_pages = Paginator.new self, @topic_count, 25, params['page'] @topic_pages = Paginator.new self, @topic_count, 25, params['page']
@topics = @board.topics.find :all, :order => "#{Message.table_name}.sticky DESC, #{sort_clause}", @topics = @board.topics.find :all, :order => sort_clause,
:include => [:author, {:last_reply => :author}], :include => [:author, {:last_reply => :author}],
:limit => @topic_pages.items_per_page, :limit => @topic_pages.items_per_page,
:offset => @topic_pages.current.offset :offset => @topic_pages.current.offset
render :action => 'show', :layout => !request.xhr? render :action => 'show', :layout => false if request.xhr?
end end
verify :method => :post, :only => [ :destroy ], :redirect_to => { :action => :index } verify :method => :post, :only => [ :destroy ], :redirect_to => { :action => :index }
+3 -18
View File
@@ -45,7 +45,7 @@ class CustomFieldsController < ApplicationController
end end
if request.post? and @custom_field.save if request.post? and @custom_field.save
flash[:notice] = l(:notice_successful_create) flash[:notice] = l(:notice_successful_create)
redirect_to :action => 'list', :tab => @custom_field.class.name redirect_to :action => 'list', :tab => @custom_field.type
end end
@trackers = Tracker.find(:all, :order => 'position') @trackers = Tracker.find(:all, :order => 'position')
end end
@@ -57,29 +57,14 @@ class CustomFieldsController < ApplicationController
@custom_field.trackers = params[:tracker_ids] ? Tracker.find(params[:tracker_ids]) : [] @custom_field.trackers = params[:tracker_ids] ? Tracker.find(params[:tracker_ids]) : []
end end
flash[:notice] = l(:notice_successful_update) flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'list', :tab => @custom_field.class.name redirect_to :action => 'list', :tab => @custom_field.type
end end
@trackers = Tracker.find(:all, :order => 'position') @trackers = Tracker.find(:all, :order => 'position')
end end
def move
@custom_field = CustomField.find(params[:id])
case params[:position]
when 'highest'
@custom_field.move_to_top
when 'higher'
@custom_field.move_higher
when 'lower'
@custom_field.move_lower
when 'lowest'
@custom_field.move_to_bottom
end if params[:position]
redirect_to :action => 'list', :tab => @custom_field.class.name
end
def destroy def destroy
@custom_field = CustomField.find(params[:id]).destroy @custom_field = CustomField.find(params[:id]).destroy
redirect_to :action => 'list', :tab => @custom_field.class.name redirect_to :action => 'list', :tab => @custom_field.type
rescue rescue
flash[:error] = "Unable to delete custom field" flash[:error] = "Unable to delete custom field"
redirect_to :action => 'list' redirect_to :action => 'list'
+9 -3
View File
@@ -39,14 +39,20 @@ class DocumentsController < ApplicationController
def download def download
@attachment = @document.attachments.find(params[:attachment_id]) @attachment = @document.attachments.find(params[:attachment_id])
@attachment.increment_download @attachment.increment_download
send_file @attachment.diskfile, :filename => @attachment.filename, :type => @attachment.content_type send_file @attachment.diskfile, :filename => @attachment.filename
rescue rescue
render_404 render_404
end end
def add_attachment def add_attachment
attachments = attach_files(@document, params[:attachments]) # Save the attachments
Mailer.deliver_attachments_added(attachments) if !attachments.empty? && Setting.notified_events.include?('document_added') @attachments = []
params[:attachments].each { |file|
next unless file.size > 0
a = Attachment.create(:container => @document, :file => file, :author => logged_in_user)
@attachments << a unless a.new_record?
} if params[:attachments] and params[:attachments].is_a? Array
Mailer.deliver_attachments_added(@attachments) if !@attachments.empty? && Setting.notified_events.include?('document_added')
redirect_to :action => 'show', :id => @document redirect_to :action => 'show', :id => @document
end end
+98
View File
@@ -0,0 +1,98 @@
# redMine - project management software
# Copyright (C) 2006-2007 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 FeedsController < ApplicationController
before_filter :find_scope
session :off
helper :issues
include IssuesHelper
helper :custom_fields
include CustomFieldsHelper
# news feeds
def news
News.with_scope(:find => @find_options) do
@news = News.find :all, :order => "#{News.table_name}.created_on DESC", :include => [ :author, :project ]
end
headers["Content-Type"] = "application/rss+xml"
render :action => 'news_atom' if 'atom' == params[:format]
end
# issue feeds
def issues
if @project && params[:query_id]
query = Query.find(params[:query_id])
query.executed_by = @user
# ignore query if it's not valid
query = nil unless query.valid?
# override with query conditions
@find_options[:conditions] = query.statement if query.valid? and @project == query.project
end
Issue.with_scope(:find => @find_options) do
@issues = Issue.find :all, :include => [:project, :author, :tracker, :status],
:order => "#{Issue.table_name}.created_on DESC"
end
@title = (@project ? @project.name : Setting.app_title) + ": " + (query ? query.name : l(:label_reported_issues))
headers["Content-Type"] = "application/rss+xml"
render :action => 'issues_atom' if 'atom' == params[:format]
end
# issue changes feeds
def history
if @project && params[:query_id]
query = Query.find(params[:query_id])
query.executed_by = @user
# ignore query if it's not valid
query = nil unless query.valid?
# override with query conditions
@find_options[:conditions] = query.statement if query.valid? and @project == query.project
end
Journal.with_scope(:find => @find_options) do
@journals = Journal.find :all, :include => [ :details, :user, {:issue => [:project, :author, :tracker, :status]} ],
:order => "#{Journal.table_name}.created_on DESC"
end
@title = (@project ? @project.name : Setting.app_title) + ": " + (query ? query.name : l(:label_changes_details))
headers["Content-Type"] = "application/rss+xml"
render :action => 'history_atom' if 'atom' == params[:format]
end
private
# override for feeds specific authentication
def check_if_login_required
@user = User.find_by_rss_key(params[:key])
render(:nothing => true, :status => 403) and return false if !@user && Setting.login_required?
end
def find_scope
if params[:project_id]
# project feed
# check if project is public or if the user is a member
@project = Project.find(params[:project_id])
render(:nothing => true, :status => 403) and return false unless @project.is_public? || (@user && @user.role_for_project(@project))
scope = ["#{Project.table_name}.id=?", params[:project_id].to_i]
else
# global feed
scope = ["#{Project.table_name}.is_public=?", true]
end
@find_options = {:conditions => scope, :limit => Setting.feeds_limit.to_i}
return true
end
end
+53 -75
View File
@@ -16,10 +16,9 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class IssuesController < ApplicationController class IssuesController < ApplicationController
layout 'base' layout 'base', :except => :export_pdf
before_filter :find_project, :authorize, :except => [:index, :changes, :preview] before_filter :find_project, :authorize, :except => [:index, :preview]
before_filter :find_optional_project, :only => [:index, :changes] accept_key_auth :index
accept_key_auth :index, :changes
cache_sweeper :issue_sweeper, :only => [ :edit, :change_status, :destroy ] cache_sweeper :issue_sweeper, :only => [ :edit, :change_status, :destroy ]
@@ -38,65 +37,47 @@ class IssuesController < ApplicationController
helper :queries helper :queries
helper :sort helper :sort
include SortHelper include SortHelper
include IssuesHelper
def index def index
sort_init "#{Issue.table_name}.id", "desc" sort_init "#{Issue.table_name}.id", "desc"
sort_update sort_update
retrieve_query retrieve_query
if @query.valid? if @query.valid?
limit = %w(pdf csv).include?(params[:format]) ? Setting.issues_export_limit.to_i : 25
@issue_count = Issue.count(:include => [:status, :project], :conditions => @query.statement) @issue_count = Issue.count(:include => [:status, :project], :conditions => @query.statement)
@issue_pages = Paginator.new self, @issue_count, limit, params['page'] @issue_pages = Paginator.new self, @issue_count, 25, params['page']
@issues = Issue.find :all, :order => sort_clause, @issues = Issue.find :all, :order => sort_clause,
:include => [ :assigned_to, :status, :tracker, :project, :priority, :category, :fixed_version ], :include => [ :assigned_to, :status, :tracker, :project, :priority, :category ],
:conditions => @query.statement, :conditions => @query.statement,
:limit => limit, :limit => @issue_pages.items_per_page,
:offset => @issue_pages.current.offset :offset => @issue_pages.current.offset
respond_to do |format|
format.html { render :template => 'issues/index.rhtml', :layout => !request.xhr? }
format.atom { render_feed(@issues, :title => l(:label_issue_plural)) }
format.csv { send_data(issues_to_csv(@issues, @project).read, :type => 'text/csv; header=present', :filename => 'export.csv') }
format.pdf { send_data(render(:template => 'issues/index.rfpdf', :layout => false), :type => 'application/pdf', :filename => 'export.pdf') }
end
else
# Send html if the query is not valid
render(:template => 'issues/index.rhtml', :layout => !request.xhr?)
end end
end respond_to do |format|
format.html { render :layout => false if request.xhr? }
def changes format.atom { render_feed(@issues, :title => l(:label_issue_plural)) }
sort_init "#{Issue.table_name}.id", "desc"
sort_update
retrieve_query
if @query.valid?
@changes = Journal.find :all, :include => [ :details, :user, {:issue => [:project, :author, :tracker, :status]} ],
:conditions => @query.statement,
:limit => 25,
:order => "#{Journal.table_name}.created_on DESC"
end end
@title = (@project ? @project.name : Setting.app_title) + ": " + (@query.new_record? ? l(:label_changes_details) : @query.name)
render :layout => false, :content_type => 'application/atom+xml'
end end
def show def show
@custom_values = @issue.custom_values.find(:all, :include => :custom_field, :order => "#{CustomField.table_name}.position") @custom_values = @issue.custom_values.find(:all, :include => :custom_field)
@journals = @issue.journals.find(:all, :include => [:user, :details], :order => "#{Journal.table_name}.created_on ASC") @journals = @issue.journals.find(:all, :include => [:user, :details], :order => "#{Journal.table_name}.created_on ASC")
@status_options = @issue.status.find_new_statuses_allowed_to(User.current.role_for_project(@project), @issue.tracker)
respond_to do |format| if params[:format]=='pdf'
format.html { render :template => 'issues/show.rhtml' } @options_for_rfpdf ||= {}
format.pdf { send_data(render(:template => 'issues/show.rfpdf', :layout => false), :type => 'application/pdf', :filename => "#{@project.identifier}-#{@issue.id}.pdf") } @options_for_rfpdf[:file_name] = "#{@project.identifier}-#{@issue.id}.pdf"
render :template => 'issues/show.rfpdf', :layout => false
else
@status_options = @issue.status.find_new_statuses_allowed_to(logged_in_user.role_for_project(@project), @issue.tracker) if logged_in_user
render :template => 'issues/show.rhtml'
end end
end end
def edit def edit
@priorities = Enumeration::get_values('IPRI') @priorities = Enumeration::get_values('IPRI')
@custom_values = []
if request.get? if request.get?
@custom_values = @project.custom_fields_for_issues(@issue.tracker).collect { |x| @issue.custom_values.find_by_custom_field_id(x.id) || CustomValue.new(:custom_field => x, :customized => @issue) } @custom_values = @project.custom_fields_for_issues(@issue.tracker).collect { |x| @issue.custom_values.find_by_custom_field_id(x.id) || CustomValue.new(:custom_field => x, :customized => @issue) }
else else
begin begin
@issue.init_journal(User.current) @issue.init_journal(self.logged_in_user)
# Retrieve custom fields and values # Retrieve custom fields and values
if params["custom_fields"] if params["custom_fields"]
@custom_values = @project.custom_fields_for_issues(@issue.tracker).collect { |x| CustomValue.new(:custom_field => x, :customized => @issue, :value => params["custom_fields"][x.id.to_s]) } @custom_values = @project.custom_fields_for_issues(@issue.tracker).collect { |x| CustomValue.new(:custom_field => x, :customized => @issue, :value => params["custom_fields"][x.id.to_s]) }
@@ -116,8 +97,13 @@ class IssuesController < ApplicationController
def add_note def add_note
journal = @issue.init_journal(User.current, params[:notes]) journal = @issue.init_journal(User.current, params[:notes])
attachments = attach_files(@issue, params[:attachments]) params[:attachments].each { |file|
attachments.each {|a| journal.details << JournalDetail.new(:property => 'attachment', :prop_key => a.id, :value => a.filename)} next unless file.size > 0
a = Attachment.create(:container => @issue, :file => file, :author => logged_in_user)
journal.details << JournalDetail.new(:property => 'attachment',
:prop_key => a.id,
:value => a.filename) unless a.new_record?
} if params[:attachments] and params[:attachments].is_a? Array
if journal.save if journal.save
flash[:notice] = l(:notice_successful_update) flash[:notice] = l(:notice_successful_update)
Mailer.deliver_issue_edit(journal) if Setting.notified_events.include?('issue_updated') Mailer.deliver_issue_edit(journal) if Setting.notified_events.include?('issue_updated')
@@ -128,18 +114,25 @@ class IssuesController < ApplicationController
end end
def change_status def change_status
@status_options = @issue.status.find_new_statuses_allowed_to(User.current.role_for_project(@project), @issue.tracker) @status_options = @issue.status.find_new_statuses_allowed_to(logged_in_user.role_for_project(@project), @issue.tracker) if logged_in_user
@new_status = IssueStatus.find(params[:new_status_id]) @new_status = IssueStatus.find(params[:new_status_id])
if params[:confirm] if params[:confirm]
begin begin
journal = @issue.init_journal(User.current, params[:notes]) journal = @issue.init_journal(self.logged_in_user, params[:notes])
@issue.status = @new_status @issue.status = @new_status
if @issue.update_attributes(params[:issue]) if @issue.update_attributes(params[:issue])
attachments = attach_files(@issue, params[:attachments]) # Save attachments
attachments.each {|a| journal.details << JournalDetail.new(:property => 'attachment', :prop_key => a.id, :value => a.filename)} params[:attachments].each { |file|
next unless file.size > 0
a = Attachment.create(:container => @issue, :file => file, :author => logged_in_user)
journal.details << JournalDetail.new(:property => 'attachment',
:prop_key => a.id,
:value => a.filename) unless a.new_record?
} if params[:attachments] and params[:attachments].is_a? Array
# Log time # Log time
if current_role.allowed_to?(:log_time) if current_role.allowed_to?(:log_time)
@time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :user => User.current, :spent_on => Date.today) @time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :user => logged_in_user, :spent_on => Date.today)
@time_entry.attributes = params[:time_entry] @time_entry.attributes = params[:time_entry]
@time_entry.save @time_entry.save
end end
@@ -159,13 +152,13 @@ class IssuesController < ApplicationController
def destroy def destroy
@issue.destroy @issue.destroy
redirect_to :action => 'index', :project_id => @project redirect_to :controller => 'projects', :action => 'list_issues', :id => @project
end end
def destroy_attachment def destroy_attachment
a = @issue.attachments.find(params[:attachment_id]) a = @issue.attachments.find(params[:attachment_id])
a.destroy a.destroy
journal = @issue.init_journal(User.current) journal = @issue.init_journal(self.logged_in_user)
journal.details << JournalDetail.new(:property => 'attachment', journal.details << JournalDetail.new(:property => 'attachment',
:prop_key => a.id, :prop_key => a.id,
:old_value => a.filename) :old_value => a.filename)
@@ -183,7 +176,6 @@ class IssuesController < ApplicationController
:change_status => User.current.allowed_to?(:change_issue_status, @project), :change_status => User.current.allowed_to?(:change_issue_status, @project),
:add => User.current.allowed_to?(:add_issues, @project), :add => User.current.allowed_to?(:add_issues, @project),
:move => User.current.allowed_to?(:move_issues, @project), :move => User.current.allowed_to?(:move_issues, @project),
:copy => (@project.trackers.include?(@issue.tracker) && User.current.allowed_to?(:add_issues, @project)),
:delete => User.current.allowed_to?(:delete_issues, @project)} :delete => User.current.allowed_to?(:delete_issues, @project)}
render :layout => false render :layout => false
end end
@@ -203,37 +195,23 @@ private
render_404 render_404
end end
def find_optional_project
return true unless params[:project_id]
@project = Project.find(params[:project_id])
authorize
rescue ActiveRecord::RecordNotFound
render_404
end
# Retrieve query from session or build a new query # Retrieve query from session or build a new query
def retrieve_query def retrieve_query
if params[:query_id] if params[:set_filter] or !session[:query] or session[:query].project_id
@query = Query.find(params[:query_id], :conditions => {:project_id => (@project ? @project.id : nil)}) # Give it a name, required to be valid
@query = Query.new(:name => "_", :executed_by => logged_in_user)
if params[:fields] and params[:fields].is_a? Array
params[:fields].each do |field|
@query.add_filter(field, params[:operators][field], params[:values][field])
end
else
@query.available_filters.keys.each do |field|
@query.add_short_filter(field, params[field]) if params[field]
end
end
session[:query] = @query session[:query] = @query
else else
if params[:set_filter] or !session[:query] or session[:query].project != @project @query = session[:query]
# Give it a name, required to be valid
@query = Query.new(:name => "_")
@query.project = @project
if params[:fields] and params[:fields].is_a? Array
params[:fields].each do |field|
@query.add_filter(field, params[:operators][field], params[:values][field])
end
else
@query.available_filters.keys.each do |field|
@query.add_short_filter(field, params[field]) if params[field]
end
end
session[:query] = @query
else
@query = session[:query]
end
end end
end end
end end
+11 -48
View File
@@ -17,81 +17,44 @@
class MessagesController < ApplicationController class MessagesController < ApplicationController
layout 'base' layout 'base'
before_filter :find_board, :only => :new before_filter :find_project, :authorize
before_filter :find_message, :except => :new
before_filter :authorize
verify :method => :post, :only => [ :reply, :destroy ], :redirect_to => { :action => :show } verify :method => :post, :only => [ :reply, :destroy ], :redirect_to => { :action => :show }
helper :attachments helper :attachments
include AttachmentsHelper include AttachmentsHelper
# Show a topic and its replies
def show def show
@reply = Message.new(:subject => "RE: #{@message.subject}") @reply = Message.new(:subject => "RE: #{@message.subject}")
render :action => "show", :layout => false if request.xhr? render :action => "show", :layout => false if request.xhr?
end end
# Create a new topic
def new def new
@message = Message.new(params[:message]) @message = Message.new(params[:message])
@message.author = User.current @message.author = logged_in_user
@message.board = @board @message.board = @board
if params[:message] && User.current.allowed_to?(:edit_messages, @project)
@message.locked = params[:message]['locked']
@message.sticky = params[:message]['sticky']
end
if request.post? && @message.save if request.post? && @message.save
attach_files(@message, params[:attachments]) params[:attachments].each { |file|
next unless file.size > 0
Attachment.create(:container => @message, :file => file, :author => logged_in_user)
} if params[:attachments] and params[:attachments].is_a? Array
redirect_to :action => 'show', :id => @message redirect_to :action => 'show', :id => @message
end end
end end
# Reply to a topic
def reply def reply
@reply = Message.new(params[:reply]) @reply = Message.new(params[:reply])
@reply.author = User.current @reply.author = logged_in_user
@reply.board = @board @reply.board = @board
@topic.children << @reply @message.children << @reply
if !@reply.new_record? redirect_to :action => 'show', :id => @message
attach_files(@reply, params[:attachments])
end
redirect_to :action => 'show', :id => @topic
end
# Edit a message
def edit
if params[:message] && User.current.allowed_to?(:edit_messages, @project)
@message.locked = params[:message]['locked']
@message.sticky = params[:message]['sticky']
end
if request.post? && @message.update_attributes(params[:message])
attach_files(@message, params[:attachments])
flash[:notice] = l(:notice_successful_update)
redirect_to :action => 'show', :id => @topic
end
end
# Delete a messages
def destroy
@message.destroy
redirect_to @message.parent.nil? ?
{ :controller => 'boards', :action => 'show', :project_id => @project, :id => @board } :
{ :action => 'show', :id => @message.parent }
end end
private private
def find_message def find_project
find_board
@message = @board.messages.find(params[:id], :include => :parent)
@topic = @message.root
rescue ActiveRecord::RecordNotFound
render_404
end
def find_board
@board = Board.find(params[:board_id], :include => :project) @board = Board.find(params[:board_id], :include => :project)
@project = @board.project @project = @board.project
@message = @board.topics.find(params[:id]) if params[:id]
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
render_404 render_404
end end
+5 -6
View File
@@ -44,7 +44,7 @@ class MyController < ApplicationController
# Show user's page # Show user's page
def page def page
@user = User.current @user = self.logged_in_user
@blocks = @user.pref[:my_page_layout] || DEFAULT_LAYOUT @blocks = @user.pref[:my_page_layout] || DEFAULT_LAYOUT
end end
@@ -56,7 +56,6 @@ class MyController < ApplicationController
@user.attributes = params[:user] @user.attributes = params[:user]
@user.mail_notification = (params[:notification_option] == 'all') @user.mail_notification = (params[:notification_option] == 'all')
@user.pref.attributes = params[:pref] @user.pref.attributes = params[:pref]
@user.pref[:no_self_notified] = (params[:no_self_notified] == '1')
if @user.save if @user.save
@user.pref.save @user.pref.save
@user.notified_project_ids = (params[:notification_option] == 'selected' ? params[:notified_project_ids] : []) @user.notified_project_ids = (params[:notification_option] == 'selected' ? params[:notified_project_ids] : [])
@@ -76,7 +75,7 @@ class MyController < ApplicationController
# Manage user's password # Manage user's password
def password def password
@user = User.current @user = self.logged_in_user
flash[:error] = l(:notice_can_t_change_password) and redirect_to :action => 'account' and return if @user.auth_source_id flash[:error] = l(:notice_can_t_change_password) and redirect_to :action => 'account' and return if @user.auth_source_id
if request.post? if request.post?
if @user.check_password?(params[:password]) if @user.check_password?(params[:password])
@@ -102,7 +101,7 @@ class MyController < ApplicationController
# User's page layout configuration # User's page layout configuration
def page_layout def page_layout
@user = User.current @user = self.logged_in_user
@blocks = @user.pref[:my_page_layout] || DEFAULT_LAYOUT.dup @blocks = @user.pref[:my_page_layout] || DEFAULT_LAYOUT.dup
session[:page_layout] = @blocks session[:page_layout] = @blocks
%w(top left right).each {|f| session[:page_layout][f] ||= [] } %w(top left right).each {|f| session[:page_layout][f] ||= [] }
@@ -116,7 +115,7 @@ class MyController < ApplicationController
def add_block def add_block
block = params[:block] block = params[:block]
render(:nothing => true) and return unless block && (BLOCKS.keys.include? block) render(:nothing => true) and return unless block && (BLOCKS.keys.include? block)
@user = User.current @user = self.logged_in_user
# remove if already present in a group # remove if already present in a group
%w(top left right).each {|f| (session[:page_layout][f] ||= []).delete block } %w(top left right).each {|f| (session[:page_layout][f] ||= []).delete block }
# add it on top # add it on top
@@ -151,7 +150,7 @@ class MyController < ApplicationController
# Save user's page layout # Save user's page layout
def page_layout_save def page_layout_save
@user = User.current @user = self.logged_in_user
@user.pref[:my_page_layout] = session[:page_layout] if session[:page_layout] @user.pref[:my_page_layout] = session[:page_layout] if session[:page_layout]
@user.pref.save @user.pref.save
session[:page_layout] = nil session[:page_layout] = nil
+3 -25
View File
@@ -17,21 +17,7 @@
class NewsController < ApplicationController class NewsController < ApplicationController
layout 'base' layout 'base'
before_filter :find_project, :authorize, :except => :index before_filter :find_project, :authorize
before_filter :find_optional_project, :only => :index
accept_key_auth :index
def index
@news_pages, @newss = paginate :news,
:per_page => 10,
:conditions => (@project ? {:project_id => @project.id} : Project.visible_by(User.current)),
:include => [:author, :project],
:order => "#{News.table_name}.created_on DESC"
respond_to do |format|
format.html { render :layout => false if request.xhr? }
format.atom { render_feed(@newss, :title => (@project ? @project.name : Setting.app_title) + ": #{l(:label_news_plural)}") }
end
end
def show def show
end end
@@ -45,7 +31,7 @@ class NewsController < ApplicationController
def add_comment def add_comment
@comment = Comment.new(params[:comment]) @comment = Comment.new(params[:comment])
@comment.author = User.current @comment.author = logged_in_user
if @news.comments << @comment if @news.comments << @comment
flash[:notice] = l(:label_comment_added) flash[:notice] = l(:label_comment_added)
redirect_to :action => 'show', :id => @news redirect_to :action => 'show', :id => @news
@@ -61,7 +47,7 @@ class NewsController < ApplicationController
def destroy def destroy
@news.destroy @news.destroy
redirect_to :action => 'index', :project_id => @project redirect_to :controller => 'projects', :action => 'list_news', :id => @project
end end
private private
@@ -71,12 +57,4 @@ private
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
render_404 render_404
end end
def find_optional_project
return true unless params[:project_id]
@project = Project.find(params[:project_id])
authorize
rescue ActiveRecord::RecordNotFound
render_404
end
end end
+205 -64
View File
@@ -15,6 +15,8 @@
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require 'csv'
class ProjectsController < ApplicationController class ProjectsController < ApplicationController
layout 'base' layout 'base'
before_filter :find_project, :except => [ :index, :list, :add ] before_filter :find_project, :except => [ :index, :list, :add ]
@@ -48,7 +50,7 @@ class ProjectsController < ApplicationController
# Lists visible projects # Lists visible projects
def list def list
projects = Project.find :all, projects = Project.find :all,
:conditions => Project.visible_by(User.current), :conditions => Project.visible_by(logged_in_user),
:include => :parent :include => :parent
@project_tree = projects.group_by {|p| p.parent || p} @project_tree = projects.group_by {|p| p.parent || p}
@project_tree.each_key {|p| @project_tree[p] -= [p]} @project_tree.each_key {|p| @project_tree[p] -= [p]}
@@ -56,19 +58,15 @@ class ProjectsController < ApplicationController
# Add a new project # Add a new project
def add def add
@custom_fields = IssueCustomField.find(:all, :order => "#{CustomField.table_name}.position") @custom_fields = IssueCustomField.find(:all)
@trackers = Tracker.all @root_projects = Project.find(:all, :conditions => "parent_id IS NULL AND status = #{Project::STATUS_ACTIVE}")
@root_projects = Project.find(:all,
:conditions => "parent_id IS NULL AND status = #{Project::STATUS_ACTIVE}",
:order => 'name')
@project = Project.new(params[:project]) @project = Project.new(params[:project])
@project.enabled_module_names = Redmine::AccessControl.available_project_modules @project.enabled_module_names = Redmine::AccessControl.available_project_modules
if request.get? if request.get?
@custom_values = ProjectCustomField.find(:all, :order => "#{CustomField.table_name}.position").collect { |x| CustomValue.new(:custom_field => x, :customized => @project) } @custom_values = ProjectCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @project) }
@project.trackers = Tracker.all
else else
@project.custom_fields = CustomField.find(params[:custom_field_ids]) if params[:custom_field_ids] @project.custom_fields = CustomField.find(params[:custom_field_ids]) if params[:custom_field_ids]
@custom_values = ProjectCustomField.find(:all, :order => "#{CustomField.table_name}.position").collect { |x| CustomValue.new(:custom_field => x, :customized => @project, :value => (params[:custom_fields] ? params["custom_fields"][x.id.to_s] : nil)) } @custom_values = ProjectCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @project, :value => (params[:custom_fields] ? params["custom_fields"][x.id.to_s] : nil)) }
@project.custom_values = @custom_values @project.custom_values = @custom_values
if @project.save if @project.save
@project.enabled_module_names = params[:enabled_modules] @project.enabled_module_names = params[:enabled_modules]
@@ -80,11 +78,11 @@ class ProjectsController < ApplicationController
# Show @project # Show @project
def show def show
@custom_values = @project.custom_values.find(:all, :include => :custom_field, :order => "#{CustomField.table_name}.position") @custom_values = @project.custom_values.find(:all, :include => :custom_field)
@members_by_role = @project.members.find(:all, :include => [:user, :role], :order => 'position').group_by {|m| m.role} @members_by_role = @project.members.find(:all, :include => [:user, :role], :order => 'position').group_by {|m| m.role}
@subprojects = @project.active_children @subprojects = @project.active_children
@news = @project.news.find(:all, :limit => 5, :include => [ :author, :project ], :order => "#{News.table_name}.created_on DESC") @news = @project.news.find(:all, :limit => 5, :include => [ :author, :project ], :order => "#{News.table_name}.created_on DESC")
@trackers = @project.trackers @trackers = Tracker.find(:all, :order => 'position')
@open_issues_by_tracker = Issue.count(:group => :tracker, :joins => "INNER JOIN #{IssueStatus.table_name} ON #{IssueStatus.table_name}.id = #{Issue.table_name}.status_id", :conditions => ["project_id=? and #{IssueStatus.table_name}.is_closed=?", @project.id, false]) @open_issues_by_tracker = Issue.count(:group => :tracker, :joins => "INNER JOIN #{IssueStatus.table_name} ON #{IssueStatus.table_name}.id = #{Issue.table_name}.status_id", :conditions => ["project_id=? and #{IssueStatus.table_name}.is_closed=?", @project.id, false])
@total_issues_by_tracker = Issue.count(:group => :tracker, :conditions => ["project_id=?", @project.id]) @total_issues_by_tracker = Issue.count(:group => :tracker, :conditions => ["project_id=?", @project.id])
@total_hours = @project.time_entries.sum(:hours) @total_hours = @project.time_entries.sum(:hours)
@@ -92,14 +90,11 @@ class ProjectsController < ApplicationController
end end
def settings def settings
@root_projects = Project.find(:all, @root_projects = Project::find(:all, :conditions => ["parent_id IS NULL AND status = #{Project::STATUS_ACTIVE} AND id <> ?", @project.id])
:conditions => ["parent_id IS NULL AND status = #{Project::STATUS_ACTIVE} AND id <> ?", @project.id],
:order => 'name')
@custom_fields = IssueCustomField.find(:all) @custom_fields = IssueCustomField.find(:all)
@issue_category ||= IssueCategory.new @issue_category ||= IssueCategory.new
@member ||= @project.members.new @member ||= @project.members.new
@trackers = Tracker.all @custom_values ||= ProjectCustomField.find(:all).collect { |x| @project.custom_values.find_by_custom_field_id(x.id) || CustomValue.new(:custom_field => x) }
@custom_values ||= ProjectCustomField.find(:all, :order => "#{CustomField.table_name}.position").collect { |x| @project.custom_values.find_by_custom_field_id(x.id) || CustomValue.new(:custom_field => x) }
@repository ||= @project.repository @repository ||= @project.repository
@wiki ||= @project.wiki @wiki ||= @project.wiki
end end
@@ -109,7 +104,7 @@ class ProjectsController < ApplicationController
if request.post? if request.post?
@project.custom_fields = IssueCustomField.find(params[:custom_field_ids]) if params[:custom_field_ids] @project.custom_fields = IssueCustomField.find(params[:custom_field_ids]) if params[:custom_field_ids]
if params[:custom_fields] if params[:custom_fields]
@custom_values = ProjectCustomField.find(:all, :order => "#{CustomField.table_name}.position").collect { |x| CustomValue.new(:custom_field => x, :customized => @project, :value => params["custom_fields"][x.id.to_s]) } @custom_values = ProjectCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @project, :value => params["custom_fields"][x.id.to_s]) }
@project.custom_values = @custom_values @project.custom_values = @custom_values
end end
@project.attributes = params[:project] @project.attributes = params[:project]
@@ -181,7 +176,10 @@ class ProjectsController < ApplicationController
def add_document def add_document
@document = @project.documents.build(params[:document]) @document = @project.documents.build(params[:document])
if request.post? and @document.save if request.post? and @document.save
attach_files(@document, params[:attachments]) # Save the attachments
params[:attachments].each { |a|
Attachment.create(:container => @document, :file => a, :author => logged_in_user) unless a.size == 0
} if params[:attachments] and params[:attachments].is_a? Array
flash[:notice] = l(:notice_successful_create) flash[:notice] = l(:notice_successful_create)
Mailer.deliver_document_added(@document) if Setting.notified_events.include?('document_added') Mailer.deliver_document_added(@document) if Setting.notified_events.include?('document_added')
redirect_to :action => 'list_documents', :id => @project redirect_to :action => 'list_documents', :id => @project
@@ -211,7 +209,7 @@ class ProjectsController < ApplicationController
@issue = params[:copy_from] ? Issue.new.copy_from(params[:copy_from]) : Issue.new(params[:issue]) @issue = params[:copy_from] ? Issue.new.copy_from(params[:copy_from]) : Issue.new(params[:issue])
@issue.project = @project @issue.project = @project
@issue.author = User.current @issue.author = User.current
@issue.tracker ||= @project.trackers.find(params[:tracker_id]) @issue.tracker ||= Tracker.find(params[:tracker_id])
default_status = IssueStatus.default default_status = IssueStatus.default
unless default_status unless default_status
@@ -220,7 +218,7 @@ class ProjectsController < ApplicationController
return return
end end
@issue.status = default_status @issue.status = default_status
@allowed_statuses = ([default_status] + default_status.find_new_statuses_allowed_to(User.current.role_for_project(@project), @issue.tracker)) @allowed_statuses = ([default_status] + default_status.find_new_statuses_allowed_to(logged_in_user.role_for_project(@project), @issue.tracker))if logged_in_user
if request.get? if request.get?
@issue.start_date ||= Date.today @issue.start_date ||= Date.today
@@ -234,16 +232,124 @@ class ProjectsController < ApplicationController
@custom_values = @project.custom_fields_for_issues(@issue.tracker).collect { |x| CustomValue.new(:custom_field => x, :customized => @issue, :value => params["custom_fields"][x.id.to_s]) } @custom_values = @project.custom_fields_for_issues(@issue.tracker).collect { |x| CustomValue.new(:custom_field => x, :customized => @issue, :value => params["custom_fields"][x.id.to_s]) }
@issue.custom_values = @custom_values @issue.custom_values = @custom_values
if @issue.save if @issue.save
attach_files(@issue, params[:attachments]) if params[:attachments] && params[:attachments].is_a?(Array)
# Save attachments
params[:attachments].each {|a| Attachment.create(:container => @issue, :file => a, :author => User.current) unless a.size == 0}
end
flash[:notice] = l(:notice_successful_create) flash[:notice] = l(:notice_successful_create)
Mailer.deliver_issue_add(@issue) if Setting.notified_events.include?('issue_added') Mailer.deliver_issue_add(@issue) if Setting.notified_events.include?('issue_added')
redirect_to :controller => 'issues', :action => 'index', :project_id => @project redirect_to :action => 'list_issues', :id => @project
return return
end end
end end
@priorities = Enumeration::get_values('IPRI') @priorities = Enumeration::get_values('IPRI')
end end
# Show filtered/sorted issues list of @project
def list_issues
sort_init "#{Issue.table_name}.id", "desc"
sort_update
retrieve_query
@results_per_page_options = [ 15, 25, 50, 100 ]
if params[:per_page] and @results_per_page_options.include? params[:per_page].to_i
@results_per_page = params[:per_page].to_i
session[:results_per_page] = @results_per_page
else
@results_per_page = session[:results_per_page] || 25
end
if @query.valid?
@issue_count = Issue.count(:include => [:status, :project], :conditions => @query.statement)
@issue_pages = Paginator.new self, @issue_count, @results_per_page, params['page']
@issues = Issue.find :all, :order => sort_clause,
:include => [ :assigned_to, :status, :tracker, :project, :priority, :category ],
:conditions => @query.statement,
:limit => @issue_pages.items_per_page,
:offset => @issue_pages.current.offset
end
render :layout => false if request.xhr?
end
# Export filtered/sorted issues list to CSV
def export_issues_csv
sort_init "#{Issue.table_name}.id", "desc"
sort_update
retrieve_query
render :action => 'list_issues' and return unless @query.valid?
@issues = Issue.find :all, :order => sort_clause,
:include => [ :assigned_to, :author, :status, :tracker, :priority, :project, {:custom_values => :custom_field} ],
:conditions => @query.statement,
:limit => Setting.issues_export_limit.to_i
ic = Iconv.new(l(:general_csv_encoding), 'UTF-8')
export = StringIO.new
CSV::Writer.generate(export, l(:general_csv_separator)) do |csv|
# csv header fields
headers = [ "#", l(:field_status),
l(:field_project),
l(:field_tracker),
l(:field_priority),
l(:field_subject),
l(:field_assigned_to),
l(:field_author),
l(:field_start_date),
l(:field_due_date),
l(:field_done_ratio),
l(:field_created_on),
l(:field_updated_on)
]
for custom_field in @project.all_custom_fields
headers << custom_field.name
end
csv << headers.collect {|c| begin; ic.iconv(c.to_s); rescue; c.to_s; end }
# csv lines
@issues.each do |issue|
fields = [issue.id, issue.status.name,
issue.project.name,
issue.tracker.name,
issue.priority.name,
issue.subject,
(issue.assigned_to ? issue.assigned_to.name : ""),
issue.author.name,
issue.start_date ? l_date(issue.start_date) : nil,
issue.due_date ? l_date(issue.due_date) : nil,
issue.done_ratio,
l_datetime(issue.created_on),
l_datetime(issue.updated_on)
]
for custom_field in @project.all_custom_fields
fields << (show_value issue.custom_value_for(custom_field))
end
csv << fields.collect {|c| begin; ic.iconv(c.to_s); rescue; c.to_s; end }
end
end
export.rewind
send_data(export.read, :type => 'text/csv; header=present', :filename => 'export.csv')
end
# Export filtered/sorted issues to PDF
def export_issues_pdf
sort_init "#{Issue.table_name}.id", "desc"
sort_update
retrieve_query
render :action => 'list_issues' and return unless @query.valid?
@issues = Issue.find :all, :order => sort_clause,
:include => [ :author, :status, :tracker, :priority, :project ],
:conditions => @query.statement,
:limit => Setting.issues_export_limit.to_i
@options_for_rfpdf ||= {}
@options_for_rfpdf[:file_name] = "export.pdf"
render :layout => false
end
# Bulk edit issues # Bulk edit issues
def bulk_edit_issues def bulk_edit_issues
if request.post? if request.post?
@@ -277,7 +383,7 @@ class ProjectsController < ApplicationController
else else
flash[:error] = l(:notice_failed_to_save_issues, unsaved_issue_ids.size, issues.size, '#' + unsaved_issue_ids.join(', #')) flash[:error] = l(:notice_failed_to_save_issues, unsaved_issue_ids.size, issues.size, '#' + unsaved_issue_ids.join(', #'))
end end
redirect_to :controller => 'issues', :action => 'index', :project_id => @project redirect_to :action => 'list_issues', :id => @project
return return
end end
if current_role && User.current.allowed_to?(:change_issue_status, @project) if current_role && User.current.allowed_to?(:change_issue_status, @project)
@@ -293,54 +399,70 @@ class ProjectsController < ApplicationController
def move_issues def move_issues
@issues = @project.issues.find(params[:issue_ids]) if params[:issue_ids] @issues = @project.issues.find(params[:issue_ids]) if params[:issue_ids]
redirect_to :controller => 'issues', :action => 'index', :project_id => @project and return unless @issues redirect_to :action => 'list_issues', :id => @project and return unless @issues
@projects = [] @projects = []
# find projects to which the user is allowed to move the issue # find projects to which the user is allowed to move the issue
if User.current.admin? User.current.memberships.each {|m| @projects << m.project if m.role.allowed_to?(:controller => 'projects', :action => 'move_issues')}
# admin is allowed to move issues to any active (visible) project # issue can be moved to any tracker
@projects = Project.find(:all, :conditions => Project.visible_by(User.current), :order => 'name') @trackers = Tracker.find(:all)
else if request.post? and params[:new_project_id] and params[:new_tracker_id]
User.current.memberships.each {|m| @projects << m.project if m.role.allowed_to?(:move_issues)} new_project = Project.find_by_id(params[:new_project_id])
end new_tracker = Tracker.find_by_id(params[:new_tracker_id])
@target_project = @projects.detect {|p| p.id.to_s == params[:new_project_id]} if params[:new_project_id] @issues.each do |i|
@target_project ||= @project if new_project && i.project_id != new_project.id
@trackers = @target_project.trackers # issue is moved to another project
if request.post? i.category = nil
new_tracker = params[:new_tracker_id].blank? ? nil : @target_project.trackers.find_by_id(params[:new_tracker_id]) i.fixed_version = nil
unsaved_issue_ids = [] # delete issue relations
@issues.each do |issue| i.relations_from.clear
unsaved_issue_ids << issue.id unless issue.move_to(@target_project, new_tracker) i.relations_to.clear
i.project = new_project
end
if new_tracker
i.tracker = new_tracker
end
i.save
end end
if unsaved_issue_ids.empty? flash[:notice] = l(:notice_successful_update)
flash[:notice] = l(:notice_successful_update) unless @issues.empty? redirect_to :action => 'list_issues', :id => @project
else
flash[:error] = l(:notice_failed_to_save_issues, unsaved_issue_ids.size, @issues.size, '#' + unsaved_issue_ids.join(', #'))
end
redirect_to :controller => 'issues', :action => 'index', :project_id => @project
return
end end
render :layout => false if request.xhr?
end end
# Add a news to @project # Add a news to @project
def add_news def add_news
@news = News.new(:project => @project, :author => User.current) @news = News.new(:project => @project)
if request.post? if request.post?
@news.attributes = params[:news] @news.attributes = params[:news]
@news.author_id = self.logged_in_user.id if self.logged_in_user
if @news.save if @news.save
flash[:notice] = l(:notice_successful_create) flash[:notice] = l(:notice_successful_create)
Mailer.deliver_news_added(@news) if Setting.notified_events.include?('news_added') Mailer.deliver_news_added(@news) if Setting.notified_events.include?('news_added')
redirect_to :controller => 'news', :action => 'index', :project_id => @project redirect_to :action => 'list_news', :id => @project
end end
end end
end end
# Show news list of @project
def list_news
@news_pages, @newss = paginate :news, :per_page => 10, :conditions => ["project_id=?", @project.id], :include => :author, :order => "#{News.table_name}.created_on DESC"
respond_to do |format|
format.html { render :layout => false if request.xhr? }
format.atom { render_feed(@newss, :title => "#{@project.name}: #{l(:label_news_plural)}") }
end
end
def add_file def add_file
if request.post? if request.post?
@version = @project.versions.find_by_id(params[:version_id]) @version = @project.versions.find_by_id(params[:version_id])
attachments = attach_files(@issue, params[:attachments]) # Save the attachments
Mailer.deliver_attachments_added(attachments) if !attachments.empty? && Setting.notified_events.include?('file_added') @attachments = []
params[:attachments].each { |file|
next unless file.size > 0
a = Attachment.create(:container => @version, :file => file, :author => logged_in_user)
@attachments << a unless a.new_record?
} if params[:attachments] and params[:attachments].is_a? Array
Mailer.deliver_attachments_added(@attachments) if !@attachments.empty? && Setting.notified_events.include?('file_added')
redirect_to :controller => 'projects', :action => 'list_files', :id => @project redirect_to :controller => 'projects', :action => 'list_files', :id => @project
end end
@versions = @project.versions.sort @versions = @project.versions.sort
@@ -352,13 +474,13 @@ class ProjectsController < ApplicationController
# Show changelog for @project # Show changelog for @project
def changelog def changelog
@trackers = @project.trackers.find(:all, :conditions => ["is_in_chlog=?", true], :order => 'position') @trackers = Tracker.find(:all, :conditions => ["is_in_chlog=?", true], :order => 'position')
retrieve_selected_tracker_ids(@trackers) retrieve_selected_tracker_ids(@trackers)
@versions = @project.versions.sort @versions = @project.versions.sort
end end
def roadmap def roadmap
@trackers = @project.trackers.find(:all, :conditions => ["is_in_roadmap=?", true]) @trackers = Tracker.find(:all, :conditions => ["is_in_roadmap=?", true], :order => 'position')
retrieve_selected_tracker_ids(@trackers) retrieve_selected_tracker_ids(@trackers)
@versions = @project.versions.sort @versions = @project.versions.sort
@versions = @versions.select {|v| !v.completed? } unless params[:completed] @versions = @versions.select {|v| !v.completed? } unless params[:completed]
@@ -385,22 +507,20 @@ class ProjectsController < ApplicationController
@date_to = @date_from >> 1 @date_to = @date_from >> 1
end end
@event_types = %w(issues news files documents changesets wiki_pages messages) @event_types = %w(issues news files documents wiki_pages changesets)
@event_types.delete('wiki_pages') unless @project.wiki @event_types.delete('wiki_pages') unless @project.wiki
@event_types.delete('changesets') unless @project.repository @event_types.delete('changesets') unless @project.repository
@event_types.delete('messages') unless @project.boards.any?
# only show what the user is allowed to view # only show what the user is allowed to view
@event_types = @event_types.select {|o| User.current.allowed_to?("view_#{o}".to_sym, @project)} @event_types = @event_types.select {|o| User.current.allowed_to?("view_#{o}".to_sym, @project)}
@scope = @event_types.select {|t| params["show_#{t}"]} @scope = @event_types.select {|t| params["show_#{t}"]}
# default events if none is specified in parameters # default events if none is specified in parameters
@scope = (@event_types - %w(wiki_pages messages))if @scope.empty? @scope = (@event_types - %w(wiki_pages))if @scope.empty?
@events = [] @events = []
if @scope.include?('issues') if @scope.include?('issues')
@events += @project.issues.find(:all, :include => [:author, :tracker], :conditions => ["#{Issue.table_name}.created_on>=? and #{Issue.table_name}.created_on<=?", @date_from, @date_to] ) @events += @project.issues.find(:all, :include => [:author, :tracker], :conditions => ["#{Issue.table_name}.created_on>=? and #{Issue.table_name}.created_on<=?", @date_from, @date_to] )
@events += @project.issues_status_changes(@date_from, @date_to)
end end
if @scope.include?('news') if @scope.include?('news')
@@ -430,13 +550,7 @@ class ProjectsController < ApplicationController
end end
if @scope.include?('changesets') if @scope.include?('changesets')
@events += Changeset.find(:all, :include => :repository, :conditions => ["#{Repository.table_name}.project_id = ? AND #{Changeset.table_name}.committed_on BETWEEN ? AND ?", @project.id, @date_from, @date_to]) @events += @project.repository.changesets.find(:all, :conditions => ["#{Changeset.table_name}.committed_on BETWEEN ? AND ?", @date_from, @date_to])
end
if @scope.include?('messages')
@events += Message.find(:all,
:include => [:board, :author],
:conditions => ["#{Board.table_name}.project_id=? AND #{Message.table_name}.parent_id IS NULL AND #{Message.table_name}.created_on BETWEEN ? AND ?", @project.id, @date_from, @date_to])
end end
@events_by_day = @events.group_by(&:event_date) @events_by_day = @events.group_by(&:event_date)
@@ -545,4 +659,31 @@ private
@selected_tracker_ids = selectable_trackers.collect {|t| t.id.to_s } @selected_tracker_ids = selectable_trackers.collect {|t| t.id.to_s }
end end
end end
# Retrieve query from session or build a new query
def retrieve_query
if params[:query_id]
@query = @project.queries.find(params[:query_id])
@query.executed_by = logged_in_user
session[:query] = @query
else
if params[:set_filter] or !session[:query] or session[:query].project_id != @project.id
# Give it a name, required to be valid
@query = Query.new(:name => "_", :executed_by => logged_in_user)
@query.project = @project
if params[:fields] and params[:fields].is_a? Array
params[:fields].each do |field|
@query.add_filter(field, params[:operators][field], params[:values][field])
end
else
@query.available_filters.keys.each do |field|
@query.add_short_filter(field, params[field]) if params[field]
end
end
session[:query] = @query
else
@query = session[:query]
end
end
end
end end
+7 -5
View File
@@ -22,13 +22,14 @@ class QueriesController < ApplicationController
def index def index
@queries = @project.queries.find(:all, @queries = @project.queries.find(:all,
:order => "name ASC", :order => "name ASC",
:conditions => ["is_public = ? or user_id = ?", true, (User.current.logged? ? User.current.id : 0)]) :conditions => ["is_public = ? or user_id = ?", true, (logged_in_user ? logged_in_user.id : 0)])
end end
def new def new
@query = Query.new(params[:query]) @query = Query.new(params[:query])
@query.project = @project @query.project = @project
@query.user = User.current @query.user = logged_in_user
@query.executed_by = logged_in_user
@query.is_public = false unless current_role.allowed_to?(:manage_public_queries) @query.is_public = false unless current_role.allowed_to?(:manage_public_queries)
@query.column_names = nil if params[:default_columns] @query.column_names = nil if params[:default_columns]
@@ -38,7 +39,7 @@ class QueriesController < ApplicationController
if request.post? && params[:confirm] && @query.save if request.post? && params[:confirm] && @query.save
flash[:notice] = l(:notice_successful_create) flash[:notice] = l(:notice_successful_create)
redirect_to :controller => 'issues', :action => 'index', :project_id => @project, :query_id => @query redirect_to :controller => 'projects', :action => 'list_issues', :id => @project, :query_id => @query
return return
end end
render :layout => false if request.xhr? render :layout => false if request.xhr?
@@ -56,7 +57,7 @@ class QueriesController < ApplicationController
if @query.save if @query.save
flash[:notice] = l(:notice_successful_update) flash[:notice] = l(:notice_successful_update)
redirect_to :controller => 'issues', :action => 'index', :project_id => @project, :query_id => @query redirect_to :controller => 'projects', :action => 'list_issues', :id => @project, :query_id => @query
end end
end end
end end
@@ -70,8 +71,9 @@ private
def find_project def find_project
if params[:id] if params[:id]
@query = Query.find(params[:id]) @query = Query.find(params[:id])
@query.executed_by = logged_in_user
@project = @query.project @project = @query.project
render_403 unless @query.editable_by?(User.current) render_403 unless @query.editable_by?(logged_in_user)
else else
@project = Project.find(params[:project_id]) @project = Project.find(params[:project_id])
end end
+2 -2
View File
@@ -25,7 +25,7 @@ class ReportsController < ApplicationController
case params[:detail] case params[:detail]
when "tracker" when "tracker"
@field = "tracker_id" @field = "tracker_id"
@rows = @project.trackers @rows = Tracker.find :all, :order => 'position'
@data = issues_by_tracker @data = issues_by_tracker
@report_title = l(:field_tracker) @report_title = l(:field_tracker)
render :template => "reports/issue_report_details" render :template => "reports/issue_report_details"
@@ -60,7 +60,7 @@ class ReportsController < ApplicationController
@report_title = l(:field_subproject) @report_title = l(:field_subproject)
render :template => "reports/issue_report_details" render :template => "reports/issue_report_details"
else else
@trackers = @project.trackers @trackers = Tracker.find(:all, :order => 'position')
@versions = @project.versions.sort @versions = @project.versions.sort
@priorities = Enumeration::get_values('IPRI') @priorities = Enumeration::get_values('IPRI')
@categories = @project.issue_categories @categories = @project.issue_categories
+3 -26
View File
@@ -19,9 +19,6 @@ require 'SVG/Graph/Bar'
require 'SVG/Graph/BarHorizontal' require 'SVG/Graph/BarHorizontal'
require 'digest/sha1' require 'digest/sha1'
class ChangesetNotFound < Exception
end
class RepositoriesController < ApplicationController class RepositoriesController < ApplicationController
layout 'base' layout 'base'
before_filter :find_repository, :except => :edit before_filter :find_repository, :except => :edit
@@ -92,44 +89,24 @@ class RepositoriesController < ApplicationController
show_error and return unless @content show_error and return unless @content
if 'raw' == params[:format] if 'raw' == params[:format]
send_data @content, :filename => @path.split('/').last send_data @content, :filename => @path.split('/').last
else
# Prevent empty lines when displaying a file with Windows style eol
@content.gsub!("\r\n", "\n")
end end
end end
def annotate
@annotate = @repository.scm.annotate(@path, @rev)
show_error and return if @annotate.nil? || @annotate.empty?
end
def revision def revision
@changeset = @repository.changesets.find_by_revision(@rev) @changeset = @repository.changesets.find_by_revision(@rev)
raise ChangesetNotFound unless @changeset show_error and return unless @changeset
@changes_count = @changeset.changes.size @changes_count = @changeset.changes.size
@changes_pages = Paginator.new self, @changes_count, 150, params['page'] @changes_pages = Paginator.new self, @changes_count, 150, params['page']
@changes = @changeset.changes.find(:all, @changes = @changeset.changes.find(:all,
:limit => @changes_pages.items_per_page, :limit => @changes_pages.items_per_page,
:offset => @changes_pages.current.offset) :offset => @changes_pages.current.offset)
respond_to do |format| render :action => "revision", :layout => false if request.xhr?
format.html
format.js {render :layout => false}
end
rescue ChangesetNotFound
show_error
end end
def diff def diff
@rev_to = params[:rev_to] ? params[:rev_to].to_i : (@rev - 1) @rev_to = params[:rev_to] ? params[:rev_to].to_i : (@rev - 1)
@diff_type = params[:type] || User.current.pref[:diff_type] || 'inline' @diff_type = ('sbs' == params[:type]) ? 'sbs' : 'inline'
@diff_type = 'inline' unless %w(inline sbs).include?(@diff_type)
# Save diff type as user preference
if User.current.logged? && @diff_type != User.current.pref[:diff_type]
User.current.pref[:diff_type] = @diff_type
User.current.preference.save
end
@cache_key = "repositories/diff/#{@repository.id}/" + Digest::MD5.hexdigest("#{@path}-#{@rev}-#{@rev_to}-#{@diff_type}") @cache_key = "repositories/diff/#{@repository.id}/" + Digest::MD5.hexdigest("#{@path}-#{@rev}-#{@rev_to}-#{@diff_type}")
unless read_fragment(@cache_key) unless read_fragment(@cache_key)
+2 -3
View File
@@ -33,8 +33,7 @@ class RolesController < ApplicationController
end end
def new def new
# Prefills the form with 'Non member' role permissions @role = Role.new(params[:role])
@role = Role.new(params[:role] || {:permissions => Role.non_member.permissions})
if request.post? && @role.save if request.post? && @role.save
flash[:notice] = l(:notice_successful_create) flash[:notice] = l(:notice_successful_create)
redirect_to :action => 'list' redirect_to :action => 'list'
@@ -94,7 +93,7 @@ class RolesController < ApplicationController
end end
@roles = Role.find(:all, :order => 'builtin, position') @roles = Role.find(:all, :order => 'builtin, position')
@trackers = Tracker.find(:all, :order => 'position') @trackers = Tracker.find(:all, :order => 'position')
@statuses = IssueStatus.find(:all, :order => 'position') @statuses = IssueStatus.find(:all, :include => :workflows, :order => 'position')
end end
def report def report
+6 -9
View File
@@ -31,7 +31,7 @@ class SearchController < ApplicationController
begin; offset = params[:offset].to_time if params[:offset]; rescue; end begin; offset = params[:offset].to_time if params[:offset]; rescue; end
# quick jump to an issue # quick jump to an issue
if @question.match(/^#?(\d+)$/) && Issue.find_by_id($1, :include => :project, :conditions => Project.visible_by(User.current)) if @question.match(/^#?(\d+)$/) && Issue.find_by_id($1, :include => :project, :conditions => Project.visible_by(logged_in_user))
redirect_to :controller => "issues", :action => "show", :id => $1 redirect_to :controller => "issues", :action => "show", :id => $1
return return
end end
@@ -52,11 +52,8 @@ class SearchController < ApplicationController
@object_types = @scope = %w(projects) @object_types = @scope = %w(projects)
end end
# extract tokens from the question
# eg. hello "bye bye" => ["hello", "bye bye"]
@tokens = @question.scan(%r{((\s|^)"[\s\w]+"(\s|$)|\S+)}).collect {|m| m.first.gsub(%r{(^\s*"\s*|\s*"\s*$)}, '')}
# tokens must be at least 3 character long # tokens must be at least 3 character long
@tokens = @tokens.uniq.select {|w| w.length > 2 } @tokens = @question.split.uniq.select {|w| w.length > 2 }
if !@tokens.empty? if !@tokens.empty?
# no more than 5 tokens to search for # no more than 5 tokens to search for
@@ -90,13 +87,13 @@ class SearchController < ApplicationController
end end
else else
operator = @all_words ? ' AND ' : ' OR ' operator = @all_words ? ' AND ' : ' OR '
@results += Project.find(:all, Project.with_scope(:find => {:conditions => Project.visible_by(logged_in_user)}) do
:limit => limit, @results += Project.find(:all, :limit => limit, :conditions => [ (["(LOWER(name) like ? OR LOWER(description) like ?)"] * like_tokens.size).join(operator), * (like_tokens * 2).sort] ) if @scope.include? 'projects'
:conditions => [ (["(#{Project.visible_by(User.current)}) AND (LOWER(name) like ? OR LOWER(description) like ?)"] * like_tokens.size).join(operator), * (like_tokens * 2).sort] end
) if @scope.include? 'projects'
# if only one project is found, user is redirected to its overview # if only one project is found, user is redirected to its overview
redirect_to :controller => 'projects', :action => 'show', :id => @results.first and return if @results.size == 1 redirect_to :controller => 'projects', :action => 'show', :id => @results.first and return if @results.size == 1
end end
@question = @tokens.join(" ")
else else
@question = "" @question = ""
end end
+4 -4
View File
@@ -54,7 +54,7 @@ class TimelogController < ApplicationController
begin; @date_to = params[:date_to].to_date; rescue; end begin; @date_to = params[:date_to].to_date; rescue; end
end end
@date_from ||= Date.civil(Date.today.year, 1, 1) @date_from ||= Date.civil(Date.today.year, 1, 1)
@date_to ||= (Date.civil(Date.today.year, Date.today.month, 1) >> 1) - 1 @date_to ||= Date.civil(Date.today.year, Date.today.month+1, 1) - 1
unless @criterias.empty? unless @criterias.empty?
sql_select = @criterias.collect{|criteria| @available_criterias[criteria][:sql] + " AS " + criteria}.join(', ') sql_select = @criterias.collect{|criteria| @available_criterias[criteria][:sql] + " AS " + criteria}.join(', ')
@@ -107,15 +107,15 @@ class TimelogController < ApplicationController
@entries = (@issue ? @issue : @project).time_entries.find(:all, :include => [:activity, :user, {:issue => [:tracker, :assigned_to, :priority]}], :order => sort_clause) @entries = (@issue ? @issue : @project).time_entries.find(:all, :include => [:activity, :user, {:issue => [:tracker, :assigned_to, :priority]}], :order => sort_clause)
@total_hours = @entries.inject(0) { |sum,entry| sum + entry.hours } @total_hours = @entries.inject(0) { |sum,entry| sum + entry.hours }
@owner_id = User.current.id @owner_id = logged_in_user ? logged_in_user.id : 0
send_csv and return if 'csv' == params[:export] send_csv and return if 'csv' == params[:export]
render :action => 'details', :layout => false if request.xhr? render :action => 'details', :layout => false if request.xhr?
end end
def edit def edit
render_404 and return if @time_entry && @time_entry.user != User.current render_404 and return if @time_entry && @time_entry.user != logged_in_user
@time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :user => User.current, :spent_on => Date.today) @time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :user => logged_in_user, :spent_on => Date.today)
@time_entry.attributes = params[:time_entry] @time_entry.attributes = params[:time_entry]
if request.post? and @time_entry.save if request.post? and @time_entry.save
flash[:notice] = l(:notice_successful_update) flash[:notice] = l(:notice_successful_update)
+2 -4
View File
@@ -37,10 +37,8 @@ class TrackersController < ApplicationController
if request.post? and @tracker.save if request.post? and @tracker.save
# workflow copy # workflow copy
if !params[:copy_workflow_from].blank? && (copy_from = Tracker.find_by_id(params[:copy_workflow_from])) if !params[:copy_workflow_from].blank? && (copy_from = Tracker.find_by_id(params[:copy_workflow_from]))
Workflow.transaction do copy_from.workflows.each do |w|
copy_from.workflows.find(:all, :include => [:role, :old_status, :new_status]).each do |w| @tracker.workflows << w.clone
Workflow.create(:tracker_id => @tracker.id, :role => w.role, :old_status => w.old_status, :new_status => w.new_status)
end
end end
end end
flash[:notice] = l(:notice_successful_create) flash[:notice] = l(:notice_successful_create)
+12 -4
View File
@@ -52,13 +52,13 @@ class UsersController < ApplicationController
def add def add
if request.get? if request.get?
@user = User.new(:language => Setting.default_language) @user = User.new(:language => Setting.default_language)
@custom_values = UserCustomField.find(:all, :order => "#{CustomField.table_name}.position").collect { |x| CustomValue.new(:custom_field => x, :customized => @user) } @custom_values = UserCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @user) }
else else
@user = User.new(params[:user]) @user = User.new(params[:user])
@user.admin = params[:user][:admin] || false @user.admin = params[:user][:admin] || false
@user.login = params[:user][:login] @user.login = params[:user][:login]
@user.password, @user.password_confirmation = params[:password], params[:password_confirmation] unless @user.auth_source_id @user.password, @user.password_confirmation = params[:password], params[:password_confirmation] unless @user.auth_source_id
@custom_values = UserCustomField.find(:all, :order => "#{CustomField.table_name}.position").collect { |x| CustomValue.new(:custom_field => x, :customized => @user, :value => (params[:custom_fields] ? params["custom_fields"][x.id.to_s] : nil)) } @custom_values = UserCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @user, :value => (params[:custom_fields] ? params["custom_fields"][x.id.to_s] : nil)) }
@user.custom_values = @custom_values @user.custom_values = @custom_values
if @user.save if @user.save
Mailer.deliver_account_information(@user, params[:password]) if params[:send_information] Mailer.deliver_account_information(@user, params[:password]) if params[:send_information]
@@ -72,13 +72,13 @@ class UsersController < ApplicationController
def edit def edit
@user = User.find(params[:id]) @user = User.find(params[:id])
if request.get? if request.get?
@custom_values = UserCustomField.find(:all, :order => "#{CustomField.table_name}.position").collect { |x| @user.custom_values.find_by_custom_field_id(x.id) || CustomValue.new(:custom_field => x) } @custom_values = UserCustomField.find(:all).collect { |x| @user.custom_values.find_by_custom_field_id(x.id) || CustomValue.new(:custom_field => x) }
else else
@user.admin = params[:user][:admin] if params[:user][:admin] @user.admin = params[:user][:admin] if params[:user][:admin]
@user.login = params[:user][:login] if params[:user][:login] @user.login = params[:user][:login] if params[:user][:login]
@user.password, @user.password_confirmation = params[:password], params[:password_confirmation] unless params[:password].nil? or params[:password].empty? or @user.auth_source_id @user.password, @user.password_confirmation = params[:password], params[:password_confirmation] unless params[:password].nil? or params[:password].empty? or @user.auth_source_id
if params[:custom_fields] if params[:custom_fields]
@custom_values = UserCustomField.find(:all, :order => "#{CustomField.table_name}.position").collect { |x| CustomValue.new(:custom_field => x, :customized => @user, :value => params["custom_fields"][x.id.to_s]) } @custom_values = UserCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @user, :value => params["custom_fields"][x.id.to_s]) }
@user.custom_values = @custom_values @user.custom_values = @custom_values
end end
if @user.update_attributes(params[:user]) if @user.update_attributes(params[:user])
@@ -109,4 +109,12 @@ class UsersController < ApplicationController
end end
redirect_to :action => 'edit', :id => @user and return redirect_to :action => 'edit', :id => @user and return
end end
def destroy
User.find(params[:id]).destroy
redirect_to :action => 'list'
rescue
flash[:error] = "Unable to delete user"
redirect_to :action => 'list'
end
end end
+1 -11
View File
@@ -21,9 +21,6 @@ class VersionsController < ApplicationController
cache_sweeper :version_sweeper, :only => [ :edit, :destroy ] cache_sweeper :version_sweeper, :only => [ :edit, :destroy ]
def show
end
def edit def edit
if request.post? and @version.update_attributes(params[:version]) if request.post? and @version.update_attributes(params[:version])
flash[:notice] = l(:notice_successful_update) flash[:notice] = l(:notice_successful_update)
@@ -42,7 +39,7 @@ class VersionsController < ApplicationController
def download def download
@attachment = @version.attachments.find(params[:attachment_id]) @attachment = @version.attachments.find(params[:attachment_id])
@attachment.increment_download @attachment.increment_download
send_file @attachment.diskfile, :filename => @attachment.filename, :type => @attachment.content_type send_file @attachment.diskfile, :filename => @attachment.filename
rescue rescue
render_404 render_404
end end
@@ -53,13 +50,6 @@ class VersionsController < ApplicationController
redirect_to :controller => 'projects', :action => 'list_files', :id => @project redirect_to :controller => 'projects', :action => 'list_files', :id => @project
end end
def status_by
respond_to do |format|
format.html { render :action => 'show' }
format.js { render(:update) {|page| page.replace_html 'status_by', render_issue_status_by(@version, params[:status_by])} }
end
end
private private
def find_project def find_project
@version = Version.find(params[:id]) @version = Version.find(params[:id])
+2 -2
View File
@@ -19,7 +19,7 @@ class WelcomeController < ApplicationController
layout 'base' layout 'base'
def index def index
@news = News.latest User.current @news = News.latest logged_in_user
@projects = Project.latest User.current @projects = Project.latest logged_in_user
end end
end end
+6 -2
View File
@@ -69,7 +69,7 @@ class WikiController < ApplicationController
#@content.text = params[:content][:text] #@content.text = params[:content][:text]
#@content.comments = params[:content][:comments] #@content.comments = params[:content][:comments]
@content.attributes = params[:content] @content.attributes = params[:content]
@content.author = User.current @content.author = logged_in_user
# if page is new @page.save will also save content, but not if page isn't a new record # if page is new @page.save will also save content, but not if page isn't a new record
if (@page.new_record? ? @page.save : @content.save) if (@page.new_record? ? @page.save : @content.save)
redirect_to :action => 'index', :id => @project, :page => @page.title redirect_to :action => 'index', :id => @project, :page => @page.title
@@ -154,7 +154,11 @@ class WikiController < ApplicationController
def add_attachment def add_attachment
@page = @wiki.find_page(params[:page]) @page = @wiki.find_page(params[:page])
attach_files(@page, params[:attachments]) # Save the attachments
params[:attachments].each { |file|
next unless file.size > 0
a = Attachment.create(:container => @page, :file => file, :author => logged_in_user)
} if params[:attachments] and params[:attachments].is_a? Array
redirect_to :action => 'index', :page => @page.title redirect_to :action => 'index', :page => @page.title
end end
+1 -1
View File
@@ -23,7 +23,7 @@ class WikisController < ApplicationController
def edit def edit
@wiki = @project.wiki || Wiki.new(:project => @project) @wiki = @project.wiki || Wiki.new(:project => @project)
@wiki.attributes = params[:wiki] @wiki.attributes = params[:wiki]
@wiki.save if request.post? @wiki.save if @request.post?
render(:update) {|page| page.replace_html "tab-content-wiki", :partial => 'projects/settings/wiki'} render(:update) {|page| page.replace_html "tab-content-wiki", :partial => 'projects/settings/wiki'}
end end
+13 -51
View File
@@ -16,7 +16,6 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module ApplicationHelper module ApplicationHelper
include Redmine::WikiFormatting::Macros::Definitions
def current_role def current_role
@current_role ||= User.current.role_for_project(@project) @current_role ||= User.current.role_for_project(@project)
@@ -34,7 +33,7 @@ module ApplicationHelper
# Display a link to user's account page # Display a link to user's account page
def link_to_user(user) def link_to_user(user)
user ? link_to(user, :controller => 'account', :action => 'show', :id => user) : 'Anonymous' link_to user.name, :controller => 'account', :action => 'show', :id => user
end end
def link_to_issue(issue) def link_to_issue(issue)
@@ -71,28 +70,20 @@ module ApplicationHelper
def format_date(date) def format_date(date)
return nil unless date return nil unless date
# "Setting.date_format.size < 2" is a temporary fix (content of date_format setting changed) @date_format ||= (Setting.date_format.to_i == 0 ? l(:general_fmt_date) : "%Y-%m-%d")
@date_format ||= (Setting.date_format.blank? || Setting.date_format.size < 2 ? l(:general_fmt_date) : Setting.date_format)
date.strftime(@date_format) date.strftime(@date_format)
end end
def format_time(time, include_date = true) def format_time(time)
return nil unless time return nil unless time
@date_format_setting ||= Setting.date_format.to_i
time = time.to_time if time.is_a?(String) time = time.to_time if time.is_a?(String)
zone = User.current.time_zone @date_format_setting == 0 ? l_datetime(time) : (time.strftime("%Y-%m-%d") + ' ' + l_time(time))
if time.utc?
local = zone ? zone.adjust(time) : time.getlocal
else
local = zone ? zone.adjust(time.getutc) : time
end
@date_format ||= (Setting.date_format.blank? || Setting.date_format.size < 2 ? l(:general_fmt_date) : Setting.date_format)
@time_format ||= (Setting.time_format.blank? ? l(:general_fmt_time) : Setting.time_format)
include_date ? local.strftime("#{@date_format} #{@time_format}") : local.strftime(@time_format)
end end
def authoring(created, author) def authoring(created, author)
time_tag = content_tag('acronym', distance_of_time_in_words(Time.now, created), :title => format_time(created)) time_tag = content_tag('acronym', distance_of_time_in_words(Time.now, created), :title => format_time(created))
l(:label_added_time_by, author || 'Anonymous', time_tag) l(:label_added_time_by, author.name, time_tag)
end end
def day_name(day) def day_name(day)
@@ -139,28 +130,15 @@ module ApplicationHelper
:preview => 'r', :preview => 'r',
:quick_search => 'f', :quick_search => 'f',
:search => '4', :search => '4',
}.freeze unless const_defined?(:ACCESSKEYS) }.freeze
def accesskey(s) def accesskey(s)
ACCESSKEYS[s] ACCESSKEYS[s]
end end
# Formats text according to system settings. # format text according to system settings
# 2 ways to call this method: def textilizable(text, options = {})
# * with a String: textilizable(text, options) return "" if text.blank?
# * with an object and one of its attribute: textilizable(issue, :description, options)
def textilizable(*args)
options = args.last.is_a?(Hash) ? args.pop : {}
case args.size
when 1
obj = nil
text = args.shift || ''
when 2
obj = args.shift
text = obj.send(args.shift)
else
raise ArgumentError, 'invalid arguments to textilizable'
end
# when using an image link, try to use an attachment, if possible # when using an image link, try to use an attachment, if possible
attachments = options[:attachments] attachments = options[:attachments]
@@ -180,8 +158,7 @@ module ApplicationHelper
end end
text = (Setting.text_formatting == 'textile') ? text = (Setting.text_formatting == 'textile') ?
Redmine::WikiFormatting.to_html(text) { |macro, args| exec_macro(macro, obj, args) } : Redmine::WikiFormatting.to_html(text) : simple_format(auto_link(h(text)))
simple_format(auto_link(h(text)))
# different methods for formatting wiki links # different methods for formatting wiki links
case options[:wiki_links] case options[:wiki_links]
@@ -231,7 +208,7 @@ module ApplicationHelper
# example: # example:
# #52 -> <a href="/issues/show/52">#52</a> # #52 -> <a href="/issues/show/52">#52</a>
# r52 -> <a href="/repositories/revision/6?rev=52">r52</a> (project.id is 6) # r52 -> <a href="/repositories/revision/6?rev=52">r52</a> (project.id is 6)
text = text.gsub(%r{([\s\(,-^])(#|r)(\d+)(?=[[:punct:]]|\s|<|$)}) do |m| text = text.gsub(%r{([\s,-^])(#|r)(\d+)(?=[[:punct:]]|\s|<|$)}) do |m|
leading, otype, oid = $1, $2, $3 leading, otype, oid = $1, $2, $3
link = nil link = nil
if otype == 'r' if otype == 'r'
@@ -299,7 +276,7 @@ module ApplicationHelper
def lang_options_for_select(blank=true) def lang_options_for_select(blank=true)
(blank ? [["(auto)", ""]] : []) + (blank ? [["(auto)", ""]] : []) +
GLoc.valid_languages.collect{|lang| [ ll(lang.to_s, :general_lang_name), lang.to_s]}.sort{|x,y| x.last <=> y.last } GLoc.valid_languages.collect{|lang| [ ll(lang.to_s, :general_lang_name), lang.to_s]}.sort{|x,y| x.first <=> y.first }
end end
def label_tag_for(name, option_tags = nil, options = {}) def label_tag_for(name, option_tags = nil, options = {})
@@ -319,21 +296,6 @@ module ApplicationHelper
link_to_function(l(:button_uncheck_all), "checkAll('#{form_name}', false)") link_to_function(l(:button_uncheck_all), "checkAll('#{form_name}', false)")
end end
def progress_bar(pcts, options={})
pcts = [pcts, pcts] unless pcts.is_a?(Array)
pcts[1] = pcts[1] - pcts[0]
pcts << (100 - pcts[1] - pcts[0])
width = options[:width] || '100px;'
legend = options[:legend] || ''
content_tag('table',
content_tag('tr',
(pcts[0] > 0 ? content_tag('td', '', :width => "#{pcts[0].floor}%;", :class => 'closed') : '') +
(pcts[1] > 0 ? content_tag('td', '', :width => "#{pcts[1].floor}%;", :class => 'done') : '') +
(pcts[2] > 0 ? content_tag('td', '', :width => "#{pcts[2].floor}%;", :class => 'todo') : '')
), :class => 'progress', :style => "width: #{width};") +
content_tag('p', legend, :class => 'pourcent')
end
def context_menu_link(name, url, options={}) def context_menu_link(name, url, options={})
options[:class] ||= '' options[:class] ||= ''
if options.delete(:selected) if options.delete(:selected)
@@ -1,5 +1,5 @@
# redMine - project management software # redMine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang # Copyright (C) 2006 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
@@ -15,25 +15,5 @@
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.dirname(__FILE__) + '/../test_helper' module FeedsHelper
class JournalTest < Test::Unit::TestCase
fixtures :issues, :issue_statuses, :journals, :journal_details
def setup
@journal = Journal.find 1
end
def test_journalized_is_an_issue
issue = @journal.issue
assert_kind_of Issue, issue
assert_equal 1, issue.id
end
def test_new_status
status = @journal.new_status
assert_not_nil status
assert_kind_of IssueStatus, status
assert_equal 2, status.id
end
end end
-55
View File
@@ -15,10 +15,7 @@
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require 'csv'
module IssuesHelper module IssuesHelper
include ApplicationHelper
def render_issue_tooltip(issue) def render_issue_tooltip(issue)
@cached_label_start_date ||= l(:field_start_date) @cached_label_start_date ||= l(:field_start_date)
@@ -104,56 +101,4 @@ module IssuesHelper
end end
end end
end end
def issues_to_csv(issues, project = nil)
ic = Iconv.new(l(:general_csv_encoding), 'UTF-8')
export = StringIO.new
CSV::Writer.generate(export, l(:general_csv_separator)) do |csv|
# csv header fields
headers = [ "#",
l(:field_status),
l(:field_project),
l(:field_tracker),
l(:field_priority),
l(:field_subject),
l(:field_assigned_to),
l(:field_category),
l(:field_fixed_version),
l(:field_author),
l(:field_start_date),
l(:field_due_date),
l(:field_done_ratio),
l(:field_created_on),
l(:field_updated_on)
]
# Export project custom fields if project is given
# otherwise export custom fields marked as "For all projects"
custom_fields = project.nil? ? IssueCustomField.for_all : project.all_custom_fields
custom_fields.each {|f| headers << f.name}
csv << headers.collect {|c| begin; ic.iconv(c.to_s); rescue; c.to_s; end }
# csv lines
issues.each do |issue|
fields = [issue.id,
issue.status.name,
issue.project.name,
issue.tracker.name,
issue.priority.name,
issue.subject,
issue.assigned_to,
issue.category,
issue.fixed_version,
issue.author.name,
format_date(issue.start_date),
format_date(issue.due_date),
issue.done_ratio,
format_time(issue.created_on),
format_time(issue.updated_on)
]
custom_fields.each {|f| fields << show_value(issue.custom_value_for(f)) }
csv << fields.collect {|c| begin; ic.iconv(c.to_s); rescue; c.to_s; end }
end
end
export.rewind
export
end
end end
+3 -3
View File
@@ -179,9 +179,9 @@ module ProjectsHelper
end end
# today red line # today red line
if Date.today >= date_from and Date.today <= date_to if Date.today >= @date_from and Date.today <= @date_to
gc.stroke('red') gc.stroke('red')
x = (Date.today-date_from+1)*zoom + subject_width x = (Date.today-@date_from+1)*zoom + subject_width
gc.line(x, headers_heigth, x, headers_heigth + g_height-1) gc.line(x, headers_heigth, x, headers_heigth + g_height-1)
end end
@@ -190,7 +190,7 @@ module ProjectsHelper
end if Object.const_defined?(:Magick) end if Object.const_defined?(:Magick)
def new_issue_selector def new_issue_selector
trackers = @project.trackers trackers = Tracker.find(:all, :order => 'position')
# can't use form tag inside helper # can't use form tag inside helper
content_tag('form', content_tag('form',
select_tag('tracker_id', '<option></option>' + options_from_collection_for_select(trackers, 'id', 'name'), :onchange => "if (this.value != '') {this.form.submit()}"), select_tag('tracker_id', '<option></option>' + options_from_collection_for_select(trackers, 'id', 'name'), :onchange => "if (this.value != '') {this.form.submit()}"),
+14 -20
View File
@@ -22,30 +22,24 @@ module QueriesHelper
end end
def column_header(column) def column_header(column)
column.sortable ? sort_header_tag(column.sortable, :caption => column.caption) : content_tag('th', column.caption) if column.sortable
sort_header_tag(column.sortable, :caption => l("field_#{column.name}"))
else
content_tag('th', l("field_#{column.name}"))
end
end end
def column_content(column, issue) def column_content(column, issue)
if column.is_a?(QueryCustomFieldColumn) value = issue.send(column.name)
cv = issue.custom_values.detect {|v| v.custom_field_id == column.custom_field.id} if value.is_a?(Date)
show_value(cv) format_date(value)
elsif value.is_a?(Time)
format_time(value)
elsif column.name == :subject
((@project.nil? || @project != issue.project) ? "#{issue.project.name} - " : '') +
link_to(h(value), :controller => 'issues', :action => 'show', :id => issue)
else else
value = issue.send(column.name) h(value)
if value.is_a?(Date)
format_date(value)
elsif value.is_a?(Time)
format_time(value)
else
case column.name
when :subject
h((@project.nil? || @project != issue.project) ? "#{issue.project.name} - " : '') +
link_to(h(value), :controller => 'issues', :action => 'show', :id => issue)
when :done_ratio
progress_bar(value, :width => '80px')
else
h(value)
end
end
end end
end end
end end
+1 -8
View File
@@ -62,10 +62,7 @@ module RepositoriesHelper
content_tag('p', form.text_field(:url, :size => 60, :required => true, :disabled => (repository && !repository.root_url.blank?)) + content_tag('p', form.text_field(:url, :size => 60, :required => true, :disabled => (repository && !repository.root_url.blank?)) +
'<br />(http://, https://, svn://, file:///)') + '<br />(http://, https://, svn://, file:///)') +
content_tag('p', form.text_field(:login, :size => 30)) + content_tag('p', form.text_field(:login, :size => 30)) +
content_tag('p', form.password_field(:password, :size => 30, :name => 'ignore', content_tag('p', form.password_field(:password, :size => 30))
:value => ((repository.new_record? || repository.password.blank?) ? '' : ('x'*15)),
:onfocus => "this.value=''; this.name='repository[password]';",
:onchange => "this.name='repository[password]';"))
end end
def darcs_field_tags(form, repository) def darcs_field_tags(form, repository)
@@ -80,8 +77,4 @@ module RepositoriesHelper
content_tag('p', form.text_field(:root_url, :label => 'CVSROOT', :size => 60, :required => true, :disabled => !repository.new_record?)) + content_tag('p', form.text_field(:root_url, :label => 'CVSROOT', :size => 60, :required => true, :disabled => !repository.new_record?)) +
content_tag('p', form.text_field(:url, :label => 'Module', :size => 30, :required => true, :disabled => !repository.new_record?)) content_tag('p', form.text_field(:url, :label => 'Module', :size => 30, :required => true, :disabled => !repository.new_record?))
end end
def bazaar_field_tags(form, repository)
content_tag('p', form.text_field(:url, :label => 'Root directory', :size => 60, :required => true, :disabled => (repository && !repository.new_record?)))
end
end end
-28
View File
@@ -16,32 +16,4 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module VersionsHelper module VersionsHelper
STATUS_BY_CRITERIAS = %w(category tracker priority author assigned_to)
def render_issue_status_by(version, criteria)
criteria ||= 'category'
raise 'Unknown criteria' unless STATUS_BY_CRITERIAS.include?(criteria)
h = Hash.new {|k,v| k[v] = [0, 0]}
begin
# Total issue count
Issue.count(:group => criteria,
:conditions => ["#{Issue.table_name}.fixed_version_id = ?", version.id]).each {|c,s| h[c][0] = s}
# Open issues count
Issue.count(:group => criteria,
:include => :status,
:conditions => ["#{Issue.table_name}.fixed_version_id = ? AND #{IssueStatus.table_name}.is_closed = ?", version.id, false]).each {|c,s| h[c][1] = s}
rescue ActiveRecord::RecordNotFound
# When grouping by an association, Rails throws this exception if there's no result (bug)
end
counts = h.keys.compact.sort.collect {|k| {:group => k, :total => h[k][0], :open => h[k][1], :closed => (h[k][0] - h[k][1])}}
max = counts.collect {|c| c[:total]}.max
render :partial => 'issue_counts', :locals => {:version => version, :criteria => criteria, :counts => counts, :max => max}
end
def status_by_options_for_select(value)
options_for_select(STATUS_BY_CRITERIAS.collect {|criteria| [l("field_#{criteria}".to_sym), criteria]}, value)
end
end end
+7 -2
View File
@@ -21,7 +21,7 @@ class Attachment < ActiveRecord::Base
belongs_to :container, :polymorphic => true belongs_to :container, :polymorphic => true
belongs_to :author, :class_name => "User", :foreign_key => "author_id" belongs_to :author, :class_name => "User", :foreign_key => "author_id"
validates_presence_of :container, :filename, :author validates_presence_of :container, :filename
validates_length_of :filename, :maximum => 255 validates_length_of :filename, :maximum => 255
validates_length_of :disk_filename, :maximum => 255 validates_length_of :disk_filename, :maximum => 255
@@ -83,8 +83,13 @@ class Attachment < ActiveRecord::Base
increment!(:downloads) increment!(:downloads)
end end
# returns last created projects
def self.most_downloaded
find(:all, :limit => 5, :order => "downloads DESC")
end
def project def project
container.project container.is_a?(Project) ? container : container.project
end end
def image? def image?
-4
View File
@@ -20,10 +20,6 @@ class AuthSource < ActiveRecord::Base
validates_presence_of :name validates_presence_of :name
validates_uniqueness_of :name validates_uniqueness_of :name
validates_length_of :name, :host, :maximum => 60
validates_length_of :account_password, :maximum => 60, :allow_nil => true
validates_length_of :account, :base_dn, :maximum => 255
validates_length_of :attr_login, :attr_firstname, :attr_lastname, :attr_mail, :maximum => 30
def authenticate(login, password) def authenticate(login, password)
end end
-19
View File
@@ -63,14 +63,6 @@ class Changeset < ActiveRecord::Base
return if kw_regexp.blank? return if kw_regexp.blank?
referenced_issues = [] referenced_issues = []
if ref_keywords.delete('*')
# find any issue ID in the comments
target_issue_ids = []
comments.scan(%r{([\s\(,-^])#(\d+)(?=[[:punct:]]|\s|<|$)}).each { |m| target_issue_ids << m[1] }
referenced_issues += repository.project.issues.find_all_by_id(target_issue_ids)
end
comments.scan(Regexp.new("(#{kw_regexp})[\s:]+(([\s,;&]*#?\\d+)+)", Regexp::IGNORECASE)).each do |match| comments.scan(Regexp.new("(#{kw_regexp})[\s:]+(([\s,;&]*#?\\d+)+)", Regexp::IGNORECASE)).each do |match|
action = match[0] action = match[0]
target_issue_ids = match[1].scan(/\d+/) target_issue_ids = match[1].scan(/\d+/)
@@ -88,17 +80,6 @@ class Changeset < ActiveRecord::Base
end end
referenced_issues += target_issues referenced_issues += target_issues
end end
self.issues = referenced_issues.uniq self.issues = referenced_issues.uniq
end end
# Returns the previous changeset
def previous
@previous ||= Changeset.find(:first, :conditions => ['revision < ? AND repository_id = ?', self.revision, self.repository_id], :order => 'revision DESC')
end
# Returns the next changeset
def next
@next ||= Changeset.find(:first, :conditions => ['revision > ? AND repository_id = ?', self.revision, self.repository_id], :order => 'revision ASC')
end
end end
-8
View File
@@ -17,7 +17,6 @@
class CustomField < ActiveRecord::Base class CustomField < ActiveRecord::Base
has_many :custom_values, :dependent => :delete_all has_many :custom_values, :dependent => :delete_all
acts_as_list :scope => 'type = \'#{self.class}\''
serialize :possible_values serialize :possible_values
FIELD_FORMATS = { "string" => { :name => :label_string, :order => 1 }, FIELD_FORMATS = { "string" => { :name => :label_string, :order => 1 },
@@ -43,9 +42,6 @@ class CustomField < ActiveRecord::Base
def before_validation def before_validation
# remove empty values # remove empty values
self.possible_values = self.possible_values.collect{|v| v unless v.empty?}.compact self.possible_values = self.possible_values.collect{|v| v unless v.empty?}.compact
# make sure these fields are not searchable
self.searchable = false if %w(int float date bool).include?(field_format)
true
end end
def validate def validate
@@ -55,10 +51,6 @@ class CustomField < ActiveRecord::Base
end end
end end
def <=>(field)
position <=> field.position
end
# to move in project_custom_field # to move in project_custom_field
def self.for_all def self.for_all
find(:all, :conditions => ["is_for_all=?", true]) find(:all, :conditions => ["is_for_all=?", true])
+2 -2
View File
@@ -31,9 +31,9 @@ protected
when 'float' when 'float'
begin; !value.blank? && Kernel.Float(value); rescue; errors.add(:value, :activerecord_error_invalid) end begin; !value.blank? && Kernel.Float(value); rescue; errors.add(:value, :activerecord_error_invalid) end
when 'date' when 'date'
errors.add(:value, :activerecord_error_not_a_date) unless value =~ /^\d{4}-\d{2}-\d{2}$/ or value.blank? errors.add(:value, :activerecord_error_not_a_date) unless value =~ /^\d{4}-\d{2}-\d{2}$/ or value.empty?
when 'list' when 'list'
errors.add(:value, :activerecord_error_inclusion) unless custom_field.possible_values.include?(value) or value.blank? errors.add(:value, :activerecord_error_inclusion) unless custom_field.possible_values.include? value or value.empty?
end end
end end
end end
-1
View File
@@ -22,7 +22,6 @@ class Document < ActiveRecord::Base
acts_as_searchable :columns => ['title', 'description'] acts_as_searchable :columns => ['title', 'description']
acts_as_event :title => Proc.new {|o| "#{l(:label_document)}: #{o.title}"}, acts_as_event :title => Proc.new {|o| "#{l(:label_document)}: #{o.title}"},
:author => Proc.new {|o| (a = o.attachments.find(:first, :order => "#{Attachment.table_name}.created_on ASC")) ? a.author : nil },
:url => Proc.new {|o| {:controller => 'documents', :action => 'show', :id => o.id}} :url => Proc.new {|o| {:controller => 'documents', :action => 'show', :id => o.id}}
validates_presence_of :project, :title, :category validates_presence_of :project, :title, :category
+1 -31
View File
@@ -40,7 +40,7 @@ class Issue < ActiveRecord::Base
acts_as_event :title => Proc.new {|o| "#{o.tracker.name} ##{o.id}: #{o.subject}"}, acts_as_event :title => Proc.new {|o| "#{o.tracker.name} ##{o.id}: #{o.subject}"},
:url => Proc.new {|o| {:controller => 'issues', :action => 'show', :id => o.id}} :url => Proc.new {|o| {:controller => 'issues', :action => 'show', :id => o.id}}
validates_presence_of :subject, :description, :priority, :project, :tracker, :author, :status validates_presence_of :subject, :description, :priority, :tracker, :author, :status
validates_length_of :subject, :maximum => 255 validates_length_of :subject, :maximum => 255
validates_inclusion_of :done_ratio, :in => 0..100 validates_inclusion_of :done_ratio, :in => 0..100
validates_numericality_of :estimated_hours, :allow_nil => true validates_numericality_of :estimated_hours, :allow_nil => true
@@ -61,32 +61,6 @@ class Issue < ActiveRecord::Base
self self
end end
# Move an issue to a new project and tracker
def move_to(new_project, new_tracker = nil)
transaction do
if new_project && project_id != new_project.id
# delete issue relations
self.relations_from.clear
self.relations_to.clear
# issue is moved to another project
self.category = nil
self.fixed_version = nil
self.project = new_project
end
if new_tracker
self.tracker = new_tracker
end
if save
# Manually update project_id on related time entries
TimeEntry.update_all("project_id = #{new_project.id}", {:issue_id => id})
else
rollback_db_transaction
return false
end
end
return true
end
def priority_id=(pid) def priority_id=(pid)
self.priority = nil self.priority = nil
write_attribute(:priority_id, pid) write_attribute(:priority_id, pid)
@@ -106,10 +80,6 @@ class Issue < ActiveRecord::Base
end end
end end
def validate_on_create
errors.add :tracker_id, :activerecord_error_invalid unless project.trackers.include?(tracker)
end
def before_create def before_create
# default assignment based on category # default assignment based on category
if assigned_to.nil? && category && category.assigned_to if assigned_to.nil? && category && category.assigned_to
-4
View File
@@ -35,9 +35,5 @@ class IssueCategory < ActiveRecord::Base
destroy_without_reassign destroy_without_reassign
end end
def <=>(category)
name <=> category.name
end
def to_s; name end def to_s; name end
end end
-11
View File
@@ -29,19 +29,8 @@ class Journal < ActiveRecord::Base
:project_key => "#{Issue.table_name}.project_id", :project_key => "#{Issue.table_name}.project_id",
:date_column => "#{Issue.table_name}.created_on" :date_column => "#{Issue.table_name}.created_on"
acts_as_event :title => Proc.new {|o| "#{o.issue.tracker.name} ##{o.issue.id}: #{o.issue.subject}" + ((s = o.new_status) ? " (#{s})" : '') },
:description => :notes,
:author => :user,
:url => Proc.new {|o| {:controller => 'issues', :action => 'show', :id => o.issue.id}}
def save def save
# Do not save an empty journal # Do not save an empty journal
(details.empty? && notes.blank?) ? false : super (details.empty? && notes.blank?) ? false : super
end end
# Returns the new status if the journal contains a status change, otherwise nil
def new_status
c = details.detect {|detail| detail.prop_key == 'status_id'}
(c && c.value) ? IssueStatus.find_by_id(c.value.to_i) : nil
end
end end
+2 -32
View File
@@ -89,14 +89,6 @@ class Mailer < ActionMailer::Base
:login_url => url_for(:controller => 'account', :action => 'login') :login_url => url_for(:controller => 'account', :action => 'login')
end end
def account_activation_request(user)
# Send the email to all active administrators
recipients User.find_active(:all, :conditions => {:admin => true}).collect { |u| u.mail }.compact
subject l(:mail_subject_account_activation_request)
body :user => user,
:url => url_for(:controller => 'users', :action => 'index', :status => User::STATUS_REGISTERED, :sort_key => 'created_on', :sort_order => 'desc')
end
def lost_password(token) def lost_password(token)
set_language_if_valid(token.user.language) set_language_if_valid(token.user.language)
recipients token.user.mail recipients token.user.mail
@@ -110,7 +102,7 @@ class Mailer < ActionMailer::Base
recipients token.user.mail recipients token.user.mail
subject l(:mail_subject_register) subject l(:mail_subject_register)
body :token => token, body :token => token,
:url => url_for(:controller => 'account', :action => 'activate', :token => token.value) :url => url_for(:controller => 'account', :action => 'register', :token => token.value)
end end
def test(user) def test(user)
@@ -129,32 +121,10 @@ class Mailer < ActionMailer::Base
default_url_options[:protocol] = Setting.protocol default_url_options[:protocol] = Setting.protocol
end end
# Overrides the create_mail method
def create_mail
# Removes the current user from the recipients and cc
# if he doesn't want to receive notifications about what he does
if User.current.pref[:no_self_notified]
recipients.delete(User.current.mail) if recipients
cc.delete(User.current.mail) if cc
end
# Blind carbon copy recipients
if Setting.bcc_recipients?
bcc([recipients, cc].flatten.compact.uniq)
recipients []
cc []
end
super
end
# Renders a message with the corresponding layout # Renders a message with the corresponding layout
def render_message(method_name, body) def render_message(method_name, body)
layout = method_name.match(%r{text\.html\.(rhtml|rxml)}) ? 'layout.text.html.rhtml' : 'layout.text.plain.rhtml' layout = method_name.match(%r{text\.html\.(rhtml|rxml)}) ? 'layout.text.html.rhtml' : 'layout.text.plain.rhtml'
body[:content_for_layout] = render(:file => method_name, :body => body) body[:content_for_layout] = render(:file => method_name, :body => body)
ActionView::Base.new(template_root, body, self).render(:file => "mailer/#{layout}") ActionView::Base.new(File.join(template_root, 'mailer'), body, self).render(:file => layout)
end end
# Makes partial rendering work with Rails 1.2 (retro-compatibility)
def self.controller_path
''
end unless respond_to?('controller_path')
end end
-18
View File
@@ -30,15 +30,9 @@ class Message < ActiveRecord::Base
:description => :content, :description => :content,
:url => Proc.new {|o| {:controller => 'messages', :action => 'show', :board_id => o.board_id, :id => o.id}} :url => Proc.new {|o| {:controller => 'messages', :action => 'show', :board_id => o.board_id, :id => o.id}}
attr_protected :locked, :sticky
validates_presence_of :subject, :content validates_presence_of :subject, :content
validates_length_of :subject, :maximum => 255 validates_length_of :subject, :maximum => 255
def validate_on_create
# Can not reply to a locked topic
errors.add_to_base 'Topic is locked' if root.locked?
end
def after_create def after_create
board.update_attribute(:last_message_id, self.id) board.update_attribute(:last_message_id, self.id)
board.increment! :messages_count board.increment! :messages_count
@@ -49,18 +43,6 @@ class Message < ActiveRecord::Base
end end
end end
def after_destroy
# The following line is required so that the previous counter
# updates (due to children removal) are not overwritten
board.reload
board.decrement! :messages_count
board.decrement! :topics_count unless parent
end
def sticky?
sticky == 1
end
def project def project
board.project board.project
end end
+7 -31
View File
@@ -20,11 +20,10 @@ class Project < ActiveRecord::Base
STATUS_ACTIVE = 1 STATUS_ACTIVE = 1
STATUS_ARCHIVED = 9 STATUS_ARCHIVED = 9
has_many :members, :include => :user, :conditions => "#{User.table_name}.status=#{User::STATUS_ACTIVE}" has_many :members, :dependent => :delete_all, :include => :user, :conditions => "#{User.table_name}.status=#{User::STATUS_ACTIVE}"
has_many :users, :through => :members has_many :users, :through => :members
has_many :custom_values, :dependent => :delete_all, :as => :customized has_many :custom_values, :dependent => :delete_all, :as => :customized
has_many :enabled_modules, :dependent => :delete_all has_many :enabled_modules, :dependent => :delete_all
has_and_belongs_to_many :trackers, :order => "#{Tracker.table_name}.position"
has_many :issues, :dependent => :destroy, :order => "#{Issue.table_name}.created_on DESC", :include => [:status, :tracker] has_many :issues, :dependent => :destroy, :order => "#{Issue.table_name}.created_on DESC", :include => [:status, :tracker]
has_many :issue_changes, :through => :issues, :source => :journals has_many :issue_changes, :through => :issues, :source => :journals
has_many :versions, :dependent => :destroy, :order => "#{Version.table_name}.effective_date DESC, #{Version.table_name}.name DESC" has_many :versions, :dependent => :destroy, :order => "#{Version.table_name}.effective_date DESC, #{Version.table_name}.name DESC"
@@ -37,13 +36,7 @@ class Project < ActiveRecord::Base
has_one :repository, :dependent => :destroy has_one :repository, :dependent => :destroy
has_many :changesets, :through => :repository has_many :changesets, :through => :repository
has_one :wiki, :dependent => :destroy has_one :wiki, :dependent => :destroy
# Custom field for the project issues has_and_belongs_to_many :custom_fields, :class_name => 'IssueCustomField', :join_table => "#{table_name_prefix}custom_fields_projects#{table_name_suffix}", :association_foreign_key => 'custom_field_id'
has_and_belongs_to_many :custom_fields,
:class_name => 'IssueCustomField',
:order => "#{CustomField.table_name}.position",
:join_table => "#{table_name_prefix}custom_fields_projects#{table_name_suffix}",
:association_foreign_key => 'custom_field_id'
acts_as_tree :order => "name", :counter_cache => true acts_as_tree :order => "name", :counter_cache => true
acts_as_searchable :columns => ['name', 'description'], :project_key => 'id' acts_as_searchable :columns => ['name', 'description'], :project_key => 'id'
@@ -57,13 +50,12 @@ class Project < ActiveRecord::Base
validates_associated :custom_values, :on => :update validates_associated :custom_values, :on => :update
validates_associated :repository, :wiki validates_associated :repository, :wiki
validates_length_of :name, :maximum => 30 validates_length_of :name, :maximum => 30
validates_format_of :name, :with => /^[\w\s\'\-]*$/i
validates_length_of :description, :maximum => 255 validates_length_of :description, :maximum => 255
validates_length_of :homepage, :maximum => 60 validates_length_of :homepage, :maximum => 60
validates_length_of :identifier, :in => 3..20 validates_length_of :identifier, :in => 3..12
validates_format_of :identifier, :with => /^[a-z0-9\-]*$/ validates_format_of :identifier, :with => /^[a-z0-9\-]*$/
before_destroy :delete_all_members
def identifier=(identifier) def identifier=(identifier)
super unless identifier_frozen? super unless identifier_frozen?
end end
@@ -79,22 +71,11 @@ class Project < ActiveRecord::Base
conditions = ["#{Issue.table_name}.project_id IN (#{ids.join(',')})"] conditions = ["#{Issue.table_name}.project_id IN (#{ids.join(',')})"]
end end
conditions ||= ["#{Issue.table_name}.project_id = ?", id] conditions ||= ["#{Issue.table_name}.project_id = ?", id]
# Quick and dirty fix for Rails 2 compatibility Issue.with_scope :find => { :conditions => conditions } do
Issue.send(:with_scope, :find => { :conditions => conditions }) do
yield yield
end end
end end
# Return all issues status changes for the project between the 2 given dates
def issues_status_changes(from, to)
Journal.find(:all, :include => [:issue, :details, :user],
:conditions => ["#{Journal.table_name}.journalized_type = 'Issue'" +
" AND #{Issue.table_name}.project_id = ?" +
" AND #{JournalDetail.table_name}.prop_key = 'status_id'" +
" AND #{Journal.table_name}.created_on BETWEEN ? AND ?",
id, from, to+1])
end
# returns latest created projects # returns latest created projects
# non public projects will be returned only if user is a member of those # non public projects will be returned only if user is a member of those
def self.latest(user=nil, count=5) def self.latest(user=nil, count=5)
@@ -132,14 +113,9 @@ class Project < ActiveRecord::Base
children.select {|child| child.active?} children.select {|child| child.active?}
end end
# Deletes all project's members
def delete_all_members
Member.delete_all(['project_id = ?', id])
end
# Users issues can be assigned to # Users issues can be assigned to
def assignable_users def assignable_users
members.select {|m| m.role.assignable?}.collect {|m| m.user}.sort members.select {|m| m.role.assignable?}.collect {|m| m.user}
end end
# Returns the mail adresses of users that should be always notified on project events # Returns the mail adresses of users that should be always notified on project events
@@ -158,7 +134,7 @@ class Project < ActiveRecord::Base
end end
def <=>(project) def <=>(project)
name.downcase <=> project.name.downcase name <=> project.name
end end
def allows_to?(action) def allows_to?(action)
+16 -38
View File
@@ -17,34 +17,13 @@
class QueryColumn class QueryColumn
attr_accessor :name, :sortable attr_accessor :name, :sortable
include GLoc
def initialize(name, options={}) def initialize(name, options={})
self.name = name self.name = name
self.sortable = options[:sortable] self.sortable = options[:sortable]
end end
def caption def default?; default end
set_language_if_valid(User.current.language)
l("field_#{name}")
end
end
class QueryCustomFieldColumn < QueryColumn
def initialize(custom_field)
self.name = "cf_#{custom_field.id}".to_sym
self.sortable = false
@cf = custom_field
end
def caption
@cf.name
end
def custom_field
@cf
end
end end
class Query < ActiveRecord::Base class Query < ActiveRecord::Base
@@ -54,6 +33,7 @@ class Query < ActiveRecord::Base
serialize :column_names serialize :column_names
attr_protected :project, :user attr_protected :project, :user
attr_accessor :executed_by
validates_presence_of :name, :on => :save validates_presence_of :name, :on => :save
validates_length_of :name, :maximum => 255 validates_length_of :name, :maximum => 255
@@ -99,7 +79,6 @@ class Query < ActiveRecord::Base
QueryColumn.new(:assigned_to, :sortable => "#{User.table_name}.lastname"), QueryColumn.new(:assigned_to, :sortable => "#{User.table_name}.lastname"),
QueryColumn.new(:updated_on, :sortable => "#{Issue.table_name}.updated_on"), QueryColumn.new(:updated_on, :sortable => "#{Issue.table_name}.updated_on"),
QueryColumn.new(:category, :sortable => "#{IssueCategory.table_name}.name"), QueryColumn.new(:category, :sortable => "#{IssueCategory.table_name}.name"),
QueryColumn.new(:fixed_version),
QueryColumn.new(:start_date, :sortable => "#{Issue.table_name}.start_date"), QueryColumn.new(:start_date, :sortable => "#{Issue.table_name}.start_date"),
QueryColumn.new(:due_date, :sortable => "#{Issue.table_name}.due_date"), QueryColumn.new(:due_date, :sortable => "#{Issue.table_name}.due_date"),
QueryColumn.new(:estimated_hours, :sortable => "#{Issue.table_name}.estimated_hours"), QueryColumn.new(:estimated_hours, :sortable => "#{Issue.table_name}.estimated_hours"),
@@ -111,7 +90,11 @@ class Query < ActiveRecord::Base
def initialize(attributes = nil) def initialize(attributes = nil)
super attributes super attributes
self.filters ||= { 'status_id' => {:operator => "o", :values => [""]} } self.filters ||= { 'status_id' => {:operator => "o", :values => [""]} }
set_language_if_valid(User.current.language) end
def executed_by=(user)
@executed_by = user
set_language_if_valid(user.language) if user
end end
def validate def validate
@@ -143,12 +126,12 @@ class Query < ActiveRecord::Base
"done_ratio" => { :type => :integer, :order => 13 }} "done_ratio" => { :type => :integer, :order => 13 }}
user_values = [] user_values = []
user_values << ["<< #{l(:label_me)} >>", "me"] if User.current.logged?
if project if project
user_values += project.users.sort.collect{|s| [s.name, s.id.to_s] } user_values += project.users.collect{|s| [s.name, s.id.to_s] }
else elsif executed_by
user_values << ["<< #{l(:label_me)} >>", "me"] if executed_by
# members of the user's projects # members of the user's projects
user_values += User.current.projects.collect(&:users).flatten.uniq.sort.collect{|s| [s.name, s.id.to_s] } user_values += executed_by.projects.collect(&:users).flatten.uniq.sort.collect{|s| [s.name, s.id.to_s] }
end end
@available_filters["assigned_to_id"] = { :type => :list_optional, :order => 4, :values => user_values } unless user_values.empty? @available_filters["assigned_to_id"] = { :type => :list_optional, :order => 4, :values => user_values } unless user_values.empty?
@available_filters["author_id"] = { :type => :list, :order => 5, :values => user_values } unless user_values.empty? @available_filters["author_id"] = { :type => :list, :order => 5, :values => user_values } unless user_values.empty?
@@ -162,6 +145,8 @@ class Query < ActiveRecord::Base
end end
@project.all_custom_fields.select(&:is_filter?).each do |field| @project.all_custom_fields.select(&:is_filter?).each do |field|
case field.field_format case field.field_format
when "string", "int"
options = { :type => :string, :order => 20 }
when "text" when "text"
options = { :type => :text, :order => 20 } options = { :type => :text, :order => 20 }
when "list" when "list"
@@ -170,8 +155,6 @@ class Query < ActiveRecord::Base
options = { :type => :date, :order => 20 } options = { :type => :date, :order => 20 }
when "bool" when "bool"
options = { :type => :list, :values => [[l(:general_text_yes), "1"], [l(:general_text_no), "0"]], :order => 20 } options = { :type => :list, :values => [[l(:general_text_yes), "1"], [l(:general_text_no), "0"]], :order => 20 }
else
options = { :type => :string, :order => 20 }
end end
@available_filters["cf_#{field.id}"] = options.merge({ :name => field.name }) @available_filters["cf_#{field.id}"] = options.merge({ :name => field.name })
end end
@@ -220,12 +203,7 @@ class Query < ActiveRecord::Base
end end
def available_columns def available_columns
return @available_columns if @available_columns cols = Query.available_columns
@available_columns = Query.available_columns
@available_columns += (project ?
project.custom_fields :
IssueCustomField.find(:all, :conditions => {:is_for_all => true})
).collect {|cf| QueryCustomFieldColumn.new(cf) }
end end
def columns def columns
@@ -265,7 +243,7 @@ class Query < ActiveRecord::Base
elsif project elsif project
clause << "#{Issue.table_name}.project_id=%d" % project.id clause << "#{Issue.table_name}.project_id=%d" % project.id
else else
clause << Project.visible_by(User.current) clause << Project.visible_by(executed_by)
end end
# filters clauses # filters clauses
@@ -290,7 +268,7 @@ class Query < ActiveRecord::Base
# "me" value subsitution # "me" value subsitution
if %w(assigned_to_id author_id).include?(field) if %w(assigned_to_id author_id).include?(field)
v.push(User.current.logged? ? User.current.id.to_s : "0") if v.delete("me") v.push(executed_by ? executed_by.id.to_s : "0") if v.delete("me")
end end
case operator_for field case operator_for field
-4
View File
@@ -34,10 +34,6 @@ class Repository < ActiveRecord::Base
scm.supports_cat? scm.supports_cat?
end end
def supports_annotate?
scm.supports_annotate?
end
def entries(path=nil, identifier=nil) def entries(path=nil, identifier=nil)
scm.entries(path, identifier) scm.entries(path, identifier)
end end
-86
View File
@@ -1,86 +0,0 @@
# redMine - project management software
# Copyright (C) 2006-2007 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 'redmine/scm/adapters/bazaar_adapter'
class Repository::Bazaar < Repository
attr_protected :root_url
validates_presence_of :url
def scm_adapter
Redmine::Scm::Adapters::BazaarAdapter
end
def self.scm_name
'Bazaar'
end
def entries(path=nil, identifier=nil)
entries = scm.entries(path, identifier)
if entries
entries.each do |e|
next if e.lastrev.revision.blank?
c = Change.find(:first,
:include => :changeset,
:conditions => ["#{Change.table_name}.revision = ? and #{Changeset.table_name}.repository_id = ?", e.lastrev.revision, id],
:order => "#{Changeset.table_name}.revision DESC")
if c
e.lastrev.identifier = c.changeset.revision
e.lastrev.name = c.changeset.revision
e.lastrev.author = c.changeset.committer
end
end
end
end
def fetch_changesets
scm_info = scm.info
if scm_info
# latest revision found in database
db_revision = latest_changeset ? latest_changeset.revision : 0
# latest revision in the repository
scm_revision = scm_info.lastrev.identifier.to_i
if db_revision < scm_revision
logger.debug "Fetching changesets for repository #{url}" if logger && logger.debug?
identifier_from = db_revision + 1
while (identifier_from <= scm_revision)
# loads changesets by batches of 200
identifier_to = [identifier_from + 199, scm_revision].min
revisions = scm.revisions('', identifier_to, identifier_from, :with_paths => true)
transaction do
revisions.reverse_each do |revision|
changeset = Changeset.create(:repository => self,
:revision => revision.identifier,
:committer => revision.author,
:committed_on => revision.time,
:scmid => revision.scmid,
:comments => revision.message)
revision.paths.each do |change|
Change.create(:changeset => changeset,
:action => change[:action],
:path => change[:path],
:revision => change[:revision])
end
end
end unless revisions.nil?
identifier_from = identifier_to + 1
end
end
end
end
end
-17
View File
@@ -17,23 +17,6 @@
class Setting < ActiveRecord::Base class Setting < ActiveRecord::Base
DATE_FORMATS = [
'%Y-%m-%d',
'%d/%m/%Y',
'%d.%m.%Y',
'%d-%m-%Y',
'%m/%d/%Y',
'%d %b %Y',
'%d %B %Y',
'%b %d, %Y',
'%B %d, %Y'
]
TIME_FORMATS = [
'%H:%M',
'%I:%M %p'
]
cattr_accessor :available_settings cattr_accessor :available_settings
@@available_settings = YAML::load(File.open("#{RAILS_ROOT}/config/settings.yml")) @@available_settings = YAML::load(File.open("#{RAILS_ROOT}/config/settings.yml"))
Redmine::Plugin.registered_plugins.each do |id, plugin| Redmine::Plugin.registered_plugins.each do |id, plugin|
-8
View File
@@ -29,14 +29,6 @@ class Tracker < ActiveRecord::Base
def to_s; name end def to_s; name end
def <=>(tracker)
name <=> tracker.name
end
def self.all
find(:all, :order => 'position')
end
private private
def check_integrity def check_integrity
raise "Can't delete tracker" if Issue.find(:first, :conditions => ["tracker_id=?", self.id]) raise "Can't delete tracker" if Issue.find(:first, :conditions => ["tracker_id=?", self.id])
+22 -39
View File
@@ -19,7 +19,6 @@ require "digest/sha1"
class User < ActiveRecord::Base class User < ActiveRecord::Base
# Account statuses # Account statuses
STATUS_ANONYMOUS = 0
STATUS_ACTIVE = 1 STATUS_ACTIVE = 1
STATUS_REGISTERED = 2 STATUS_REGISTERED = 2
STATUS_LOCKED = 3 STATUS_LOCKED = 3
@@ -37,16 +36,17 @@ class User < ActiveRecord::Base
# Prevents unauthorized assignments # Prevents unauthorized assignments
attr_protected :login, :admin, :password, :password_confirmation, :hashed_password attr_protected :login, :admin, :password, :password_confirmation, :hashed_password
validates_presence_of :login, :firstname, :lastname, :mail, :if => Proc.new { |user| !user.is_a?(AnonymousUser) } validates_presence_of :login, :firstname, :lastname, :mail
validates_uniqueness_of :login, :mail validates_uniqueness_of :login, :mail
# Login must contain lettres, numbers, underscores only # Login must contain lettres, numbers, underscores only
validates_format_of :login, :with => /^[a-z0-9_\-@\.]*$/i validates_format_of :login, :with => /^[a-z0-9_\-@\.]+$/i
validates_length_of :login, :maximum => 30 validates_length_of :login, :maximum => 30
validates_format_of :firstname, :lastname, :with => /^[\w\s\'\-]*$/i validates_format_of :firstname, :lastname, :with => /^[\w\s\'\-]*$/i
validates_length_of :firstname, :lastname, :maximum => 30 validates_length_of :firstname, :lastname, :maximum => 30
validates_format_of :mail, :with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i, :allow_nil => true validates_format_of :mail, :with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i
validates_length_of :mail, :maximum => 60, :allow_nil => true validates_length_of :mail, :maximum => 60
validates_length_of :password, :minimum => 4, :allow_nil => true # Password length between 4 and 12
validates_length_of :password, :in => 4..12, :allow_nil => true
validates_confirmation_of :password, :allow_nil => true validates_confirmation_of :password, :allow_nil => true
validates_associated :custom_values, :on => :update validates_associated :custom_values, :on => :update
@@ -130,10 +130,6 @@ class User < ActiveRecord::Base
self.preference ||= UserPreference.new(:user => self) self.preference ||= UserPreference.new(:user => self)
end end
def time_zone
self.pref.time_zone.nil? ? nil : TimeZone[self.pref.time_zone]
end
# Return user's RSS key (a 40 chars long string), used to access feeds # Return user's RSS key (a 40 chars long string), used to access feeds
def rss_key def rss_key
token = self.rss_token || Token.create(:user => self, :action => 'feeds') token = self.rss_token || Token.create(:user => self, :action => 'feeds')
@@ -163,7 +159,7 @@ class User < ActiveRecord::Base
end end
def <=>(user) def <=>(user)
user.nil? ? -1 : (lastname == user.lastname ? firstname <=> user.firstname : lastname <=> user.lastname) lastname == user.lastname ? firstname <=> user.firstname : lastname <=> user.lastname
end end
def to_s def to_s
@@ -178,16 +174,14 @@ class User < ActiveRecord::Base
def role_for_project(project) def role_for_project(project)
# No role on archived projects # No role on archived projects
return nil unless project && project.active? return nil unless project && project.active?
if logged? # Find project membership
# Find project membership membership = memberships.detect {|m| m.project_id == project.id}
membership = memberships.detect {|m| m.project_id == project.id} if membership
if membership membership.role
membership.role elsif logged?
else Role.non_member
@role_non_member ||= Role.non_member
end
else else
@role_anonymous ||= Role.anonymous Role.anonymous
end end
end end
@@ -218,17 +212,11 @@ class User < ActiveRecord::Base
end end
def self.current def self.current
@current_user ||= User.anonymous @current_user ||= AnonymousUser.new
end end
def self.anonymous def self.anonymous
return @anonymous_user if @anonymous_user AnonymousUser.new
anonymous_user = AnonymousUser.find(:first)
if anonymous_user.nil?
anonymous_user = AnonymousUser.create(:lastname => 'Anonymous', :firstname => '', :mail => '', :login => '', :status => 0)
raise 'Unable to create the anonymous user.' if anonymous_user.new_record?
end
@anonymous_user = anonymous_user
end end
private private
@@ -239,17 +227,12 @@ private
end end
class AnonymousUser < User class AnonymousUser < User
def logged?
def validate_on_create false
# There should be only one AnonymousUser in the database
errors.add_to_base 'An anonymous user already exists.' if AnonymousUser.find(:first)
end end
# Overrides a few properties # Anonymous user has no RSS key
def logged?; false end def rss_key
def admin; false end nil
def name; 'Anonymous' end end
def mail; nil end
def time_zone; nil end
def rss_key; nil end
end end
-18
View File
@@ -39,24 +39,6 @@ class Version < ActiveRecord::Base
effective_date && (effective_date <= Date.today) && (open_issues_count == 0) effective_date && (effective_date <= Date.today) && (open_issues_count == 0)
end end
def completed_pourcent
if fixed_issues.count == 0
0
elsif open_issues_count == 0
100
else
(closed_issues_count * 100 + Issue.sum('done_ratio', :include => 'status', :conditions => ["fixed_version_id = ? AND is_closed = ?", id, false]).to_f) / fixed_issues.count
end
end
def closed_pourcent
if fixed_issues.count == 0
0
else
closed_issues_count * 100.0 / fixed_issues.count
end
end
# Returns true if the version is overdue: due date reached and some open issues # Returns true if the version is overdue: due date reached and some open issues
def overdue? def overdue?
effective_date && (effective_date < Date.today) && (open_issues_count > 0) effective_date && (effective_date < Date.today) && (open_issues_count > 0)
+2 -2
View File
@@ -25,8 +25,8 @@ class WikiContent < ActiveRecord::Base
acts_as_versioned acts_as_versioned
class Version class Version
belongs_to :page, :class_name => '::WikiPage', :foreign_key => 'page_id' belongs_to :page, :class_name => 'WikiPage', :foreign_key => 'page_id'
belongs_to :author, :class_name => '::User', :foreign_key => 'author_id' belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
attr_protected :data attr_protected :data
acts_as_event :title => Proc.new {|o| "#{l(:label_wiki_edit)}: #{o.page.title} (##{o.version})"}, acts_as_event :title => Proc.new {|o| "#{l(:label_wiki_edit)}: #{o.page.title} (##{o.version})"},
+1 -1
View File
@@ -6,7 +6,7 @@
<div class="box tabular"> <div class="box tabular">
<p><label for="new_password"><%=l(:field_new_password)%> <span class="required">*</span></label> <p><label for="new_password"><%=l(:field_new_password)%> <span class="required">*</span></label>
<%= password_field_tag 'new_password', nil, :size => 25 %><br /> <%= password_field_tag 'new_password', nil, :size => 25 %><br />
<em><%= l(:text_caracters_minimum, 4) %></em></p> <em><%= l(:text_length_between, 4, 12) %></em></p>
<p><label for="new_password_confirmation"><%=l(:field_password_confirmation)%> <span class="required">*</span></label> <p><label for="new_password_confirmation"><%=l(:field_password_confirmation)%> <span class="required">*</span></label>
<%= password_field_tag 'new_password_confirmation', nil, :size => 25 %></p> <%= password_field_tag 'new_password_confirmation', nil, :size => 25 %></p>
+4 -2
View File
@@ -9,8 +9,7 @@
<%= text_field 'user', 'login', :size => 25 %></p> <%= text_field 'user', 'login', :size => 25 %></p>
<p><label for="password"><%=l(:field_password)%> <span class="required">*</span></label> <p><label for="password"><%=l(:field_password)%> <span class="required">*</span></label>
<%= password_field_tag 'password', nil, :size => 25 %><br /> <%= password_field_tag 'password', nil, :size => 25 %></p>
<em><%= l(:text_caracters_minimum, 4) %></em></p>
<p><label for="password_confirmation"><%=l(:field_password_confirmation)%> <span class="required">*</span></label> <p><label for="password_confirmation"><%=l(:field_password_confirmation)%> <span class="required">*</span></label>
<%= password_field_tag 'password_confirmation', nil, :size => 25 %></p> <%= password_field_tag 'password_confirmation', nil, :size => 25 %></p>
@@ -30,6 +29,9 @@
<% for @custom_value in @custom_values %> <% for @custom_value in @custom_values %>
<p><%= custom_field_tag_with_label @custom_value %></p> <p><%= custom_field_tag_with_label @custom_value %></p>
<% end %> <% end %>
<p><label for="user_mail_notification"><%=l(:field_mail_notification)%></label>
<%= check_box 'user', 'mail_notification' %></p>
<!--[eoform:user]--> <!--[eoform:user]-->
</div> </div>
-2
View File
@@ -43,5 +43,3 @@
<p class="icon22 icon22-info"> <p class="icon22 icon22-info">
<%= link_to l(:label_information_plural), :controller => 'admin', :action => 'info' %> <%= link_to l(:label_information_plural), :controller => 'admin', :action => 'info' %>
</p> </p>
<% set_html_title l(:label_administration) -%>
+1 -3
View File
@@ -12,7 +12,7 @@
&nbsp; &nbsp;
<h3 class="icon22 icon22-plugin">Plugins</h3> <h3 class="icon22 icon22-plugin">Plugins</h3>
<table class="list"> <table class="list">
<% @plugins.keys.sort {|x,y| x.to_s <=> y.to_s}.each do |plugin| %> <% @plugins.keys.sort.each do |plugin| %>
<tr class="<%= cycle('odd', 'even') %>"> <tr class="<%= cycle('odd', 'even') %>">
<td><%=h @plugins[plugin].name %></td> <td><%=h @plugins[plugin].name %></td>
<td><%=h @plugins[plugin].description %></td> <td><%=h @plugins[plugin].description %></td>
@@ -23,5 +23,3 @@
<% end %> <% end %>
</table> </table>
<% end %> <% end %>
<% set_html_title(l(:label_information_plural)) -%>
+2 -13
View File
@@ -6,28 +6,17 @@
<% form_tag({:action => 'mail_options'}, :id => 'mail-options-form') do %> <% form_tag({:action => 'mail_options'}, :id => 'mail-options-form') do %>
<fieldset class="box tabular settings"><legend><%=l(:label_settings)%></legend>
<p><label><%= l(:setting_mail_from) %></label>
<%= text_field_tag 'settings[mail_from]', Setting.mail_from, :size => 60 %></p>
<p><label><%= l(:setting_bcc_recipients) %></label>
<%= check_box_tag 'settings[bcc_recipients]', 1, Setting.bcc_recipients? %>
<%= hidden_field_tag 'settings[bcc_recipients]', 0 %></p>
</fieldset>
<fieldset class="box"><legend><%=l(:text_select_mail_notifications)%></legend> <fieldset class="box"><legend><%=l(:text_select_mail_notifications)%></legend>
<% @notifiables.each do |notifiable| %> <% @notifiables.each do |notifiable| %>
<label><%= check_box_tag 'settings[notified_events][]', notifiable, Setting.notified_events.include?(notifiable) %> <label><%= check_box_tag "notified_events[]", notifiable, Setting.notified_events.include?(notifiable) %>
<%= notifiable.humanize %></label><br /> <%= notifiable.humanize %></label><br />
<% end %> <% end %>
<p><%= check_all_links('mail-options-form') %></p> <p><%= check_all_links('mail-options-form') %></p>
</fieldset> </fieldset>
<fieldset class="box"><legend><%= l(:setting_emails_footer) %></legend> <fieldset class="box"><legend><%= l(:setting_emails_footer) %></legend>
<%= text_area_tag 'settings[emails_footer]', Setting.emails_footer, :class => 'wiki-edit', :rows => 5 %> <%= text_area_tag 'emails_footer', Setting.emails_footer, :class => 'wiki-edit', :rows => 5 %>
</fieldset> </fieldset>
<%= submit_tag l(:button_save) %> <%= submit_tag l(:button_save) %>
<% end %> <% end %>
<% set_html_title(l(:field_mail_notification)) -%>
+1 -3
View File
@@ -26,7 +26,7 @@
<tbody> <tbody>
<% for project in @projects %> <% for project in @projects %>
<tr class="<%= cycle("odd", "even") %>"> <tr class="<%= cycle("odd", "even") %>">
<td><%= project.active? ? link_to(h(project.name), :controller => 'projects', :action => 'settings', :id => project) : h(project.name) %> <td><%= project.active? ? link_to(project.name, :controller => 'projects', :action => 'settings', :id => project) : h(project.name) %>
<td><%= textilizable project.description, :project => project %> <td><%= textilizable project.description, :project => project %>
<td align="center"><%= image_tag 'true.png' if project.is_public? %> <td align="center"><%= image_tag 'true.png' if project.is_public? %>
<td align="center"><%= project.children.size %> <td align="center"><%= project.children.size %>
@@ -47,5 +47,3 @@
<p><%= pagination_links_full @project_pages, :status => @status %> <p><%= pagination_links_full @project_pages, :status => @status %>
[ <%= @project_pages.current.first_item %> - <%= @project_pages.current.last_item %> / <%= @project_count %> ]</p> [ <%= @project_pages.current.first_item %> - <%= @project_pages.current.last_item %> / <%= @project_count %> ]</p>
<% set_html_title l(:label_project_plural) -%>
+1 -4
View File
@@ -15,10 +15,7 @@
<%= text_field 'auth_source', 'account' %></p> <%= text_field 'auth_source', 'account' %></p>
<p><label for="auth_source_account_password"><%=l(:field_password)%></label> <p><label for="auth_source_account_password"><%=l(:field_password)%></label>
<%= password_field 'auth_source', 'account_password', :name => 'ignore', <%= password_field 'auth_source', 'account_password' %></p>
:value => ((@auth_source.new_record? || @auth_source.account_password.blank?) ? '' : ('x'*15)),
:onfocus => "this.value=''; this.name='auth_source[account_password]';",
:onchange => "this.name='auth_source[account_password]';" %></p>
<p><label for="auth_source_base_dn"><%=l(:field_base_dn)%> <span class="required">*</span></label> <p><label for="auth_source_base_dn"><%=l(:field_base_dn)%> <span class="required">*</span></label>
<%= text_field 'auth_source', 'base_dn', :size => 60 %></p> <%= text_field 'auth_source', 'base_dn', :size => 60 %></p>
+1 -1
View File
@@ -19,7 +19,7 @@
<td> <td>
<small> <small>
<% if board.last_message %> <% if board.last_message %>
<%= authoring board.last_message.created_on, board.last_message.author %><br /> <%= board.last_message.author.name %>, <%= format_time(board.last_message.created_on) %><br />
<%= link_to_message board.last_message %> <%= link_to_message board.last_message %>
<% end %> <% end %>
</small> </small>
+10 -8
View File
@@ -18,7 +18,7 @@
<h2><%=h @board.name %></h2> <h2><%=h @board.name %></h2>
<% if @topics.any? %> <% if @topics.any? %>
<table class="list messages"> <table class="list">
<thead><tr> <thead><tr>
<th><%= l(:field_subject) %></th> <th><%= l(:field_subject) %></th>
<th><%= l(:field_author) %></th> <th><%= l(:field_author) %></th>
@@ -28,16 +28,18 @@
</tr></thead> </tr></thead>
<tbody> <tbody>
<% @topics.each do |topic| %> <% @topics.each do |topic| %>
<tr class="message <%= cycle 'odd', 'even' %> <%= topic.sticky? ? 'sticky' : '' %> <%= topic.locked? ? 'locked' : '' %>"> <tr class="<%= cycle 'odd', 'even' %>">
<td class="subject"><%= link_to h(topic.subject), { :controller => 'messages', :action => 'show', :board_id => @board, :id => topic }, :class => 'icon' %></td> <td><%= link_to h(topic.subject), :controller => 'messages', :action => 'show', :board_id => @board, :id => topic %></td>
<td class="author" align="center"><%= topic.author %></td> <td align="center"><%= link_to_user topic.author %></td>
<td class="created_on" align="center"><%= format_time(topic.created_on) %></td> <td align="center"><%= format_time(topic.created_on) %></td>
<td class="replies" align="center"><%= topic.replies_count %></td> <td align="center"><%= topic.replies_count %></td>
<td class="last_message"> <td>
<small>
<% if topic.last_reply %> <% if topic.last_reply %>
<%= authoring topic.last_reply.created_on, topic.last_reply.author %><br /> <%= topic.last_reply.author.name %>, <%= format_time(topic.last_reply.created_on) %><br />
<%= link_to_message topic.last_reply %> <%= link_to_message topic.last_reply %>
<% end %> <% end %>
</small>
</td> </td>
</tr> </tr>
<% end %> <% end %>
+4 -13
View File
@@ -7,32 +7,21 @@ function toggle_custom_field_format() {
p_length = $("custom_field_min_length"); p_length = $("custom_field_min_length");
p_regexp = $("custom_field_regexp"); p_regexp = $("custom_field_regexp");
p_values = $("custom_field_possible_values"); p_values = $("custom_field_possible_values");
p_searchable = $("custom_field_searchable");
switch (format.value) { switch (format.value) {
case "list": case "list":
Element.hide(p_length.parentNode); Element.hide(p_length.parentNode);
Element.hide(p_regexp.parentNode); Element.hide(p_regexp.parentNode);
Element.show(p_searchable.parentNode);
Element.show(p_values); Element.show(p_values);
break; break;
case "date": case "date":
case "bool": case "bool":
Element.hide(p_length.parentNode); Element.hide(p_length.parentNode);
Element.hide(p_regexp.parentNode); Element.hide(p_regexp.parentNode);
Element.hide(p_searchable.parentNode);
Element.hide(p_values);
break;
case "float":
case "int":
Element.show(p_length.parentNode);
Element.show(p_regexp.parentNode);
Element.hide(p_searchable.parentNode);
Element.hide(p_values); Element.hide(p_values);
break; break;
default: default:
Element.show(p_length.parentNode); Element.show(p_length.parentNode);
Element.show(p_regexp.parentNode); Element.show(p_regexp.parentNode);
Element.show(p_searchable.parentNode);
Element.hide(p_values); Element.hide(p_values);
break; break;
} }
@@ -58,6 +47,7 @@ function deleteValueField(e) {
//]]> //]]>
</script> </script>
<!--[form:custom_field]-->
<div class="box"> <div class="box">
<p><%= f.text_field :name, :required => true %></p> <p><%= f.text_field :name, :required => true %></p>
<p><%= f.select :field_format, custom_field_formats_for_select, {}, :onchange => "toggle_custom_field_format();" %></p> <p><%= f.select :field_format, custom_field_formats_for_select, {}, :onchange => "toggle_custom_field_format();" %></p>
@@ -69,8 +59,11 @@ function deleteValueField(e) {
<% (@custom_field.possible_values.to_a + [""]).each do |value| %> <% (@custom_field.possible_values.to_a + [""]).each do |value| %>
<span><%= text_field_tag 'custom_field[possible_values][]', value, :size => 30 %> <%= image_to_function "delete.png", "deleteValueField(this);return false" %><br /></span> <span><%= text_field_tag 'custom_field[possible_values][]', value, :size => 30 %> <%= image_to_function "delete.png", "deleteValueField(this);return false" %><br /></span>
<% end %> <% end %>
</p> </p>
</div> </div>
<%= javascript_tag "toggle_custom_field_format();" %>
<!--[eoform:custom_field]-->
<div class="box"> <div class="box">
<% case @custom_field.type.to_s <% case @custom_field.type.to_s
@@ -85,7 +78,6 @@ when "IssueCustomField" %>
<p><%= f.check_box :is_required %></p> <p><%= f.check_box :is_required %></p>
<p><%= f.check_box :is_for_all %></p> <p><%= f.check_box :is_for_all %></p>
<p><%= f.check_box :is_filter %></p> <p><%= f.check_box :is_filter %></p>
<p><%= f.check_box :searchable %></p>
<% when "UserCustomField" %> <% when "UserCustomField" %>
<p><%= f.check_box :is_required %></p> <p><%= f.check_box :is_required %></p>
@@ -95,4 +87,3 @@ when "IssueCustomField" %>
<% end %> <% end %>
</div> </div>
<%= javascript_tag "toggle_custom_field_format();" %>
+1 -10
View File
@@ -19,11 +19,10 @@
<th><%=l(:field_is_for_all)%></th> <th><%=l(:field_is_for_all)%></th>
<th><%=l(:label_used_by)%></th> <th><%=l(:label_used_by)%></th>
<% end %> <% end %>
<th><%=l(:button_sort)%></th>
<th width="10%"></th> <th width="10%"></th>
</tr></thead> </tr></thead>
<tbody> <tbody>
<% for custom_field in (@custom_fields_by_type[type] || []).sort %> <% for custom_field in (@custom_fields_by_type[type] || []) %>
<tr class="<%= cycle("odd", "even") %>"> <tr class="<%= cycle("odd", "even") %>">
<td><%= link_to custom_field.name, :action => 'edit', :id => custom_field %></td> <td><%= link_to custom_field.name, :action => 'edit', :id => custom_field %></td>
<td align="center"><%= l(CustomField::FIELD_FORMATS[custom_field.field_format][:name]) %></td> <td align="center"><%= l(CustomField::FIELD_FORMATS[custom_field.field_format][:name]) %></td>
@@ -32,12 +31,6 @@
<td align="center"><%= image_tag 'true.png' if custom_field.is_for_all? %></td> <td align="center"><%= image_tag 'true.png' if custom_field.is_for_all? %></td>
<td align="center"><%= custom_field.projects.count.to_s + ' ' + lwr(:label_project, custom_field.projects.count) if custom_field.is_a? IssueCustomField and !custom_field.is_for_all? %></td> <td align="center"><%= custom_field.projects.count.to_s + ' ' + lwr(:label_project, custom_field.projects.count) if custom_field.is_a? IssueCustomField and !custom_field.is_for_all? %></td>
<% end %> <% end %>
<td align="center" style="width:15%;">
<%= link_to image_tag('2uparrow.png', :alt => l(:label_sort_highest)), {:action => 'move', :id => custom_field, :position => 'highest'}, :method => :post, :title => l(:label_sort_highest) %>
<%= link_to image_tag('1uparrow.png', :alt => l(:label_sort_higher)), {:action => 'move', :id => custom_field, :position => 'higher'}, :method => :post, :title => l(:label_sort_higher) %> -
<%= link_to image_tag('1downarrow.png', :alt => l(:label_sort_lower)), {:action => 'move', :id => custom_field, :position => 'lower'}, :method => :post, :title => l(:label_sort_lower) %>
<%= link_to image_tag('2downarrow.png', :alt => l(:label_sort_lowest)), {:action => 'move', :id => custom_field, :position => 'lowest'}, :method => :post, :title => l(:label_sort_lowest) %>
</td>
<td align="center"> <td align="center">
<%= button_to l(:button_delete), { :action => 'destroy', :id => custom_field }, :confirm => l(:text_are_you_sure), :class => "button-small" %> <%= button_to l(:button_delete), { :action => 'destroy', :id => custom_field }, :confirm => l(:text_are_you_sure), :class => "button-small" %>
</td> </td>
@@ -51,5 +44,3 @@
<% end %> <% end %>
<%= javascript_tag "showTab('#{@tab}');" %> <%= javascript_tag "showTab('#{@tab}');" %>
<% set_html_title(l(:label_custom_field_plural)) -%>
+2 -4
View File
@@ -3,9 +3,9 @@
<%= link_to_if_authorized l(:button_delete), {:controller => 'documents', :action => 'destroy', :id => @document}, :confirm => l(:text_are_you_sure), :method => :post, :class => 'icon icon-del' %> <%= link_to_if_authorized l(:button_delete), {:controller => 'documents', :action => 'destroy', :id => @document}, :confirm => l(:text_are_you_sure), :method => :post, :class => 'icon icon-del' %>
</div> </div>
<h2><%=h @document.title %></h2> <h2><%= @document.title %></h2>
<p><em><%=h @document.category.name %><br /> <p><em><%= @document.category.name %><br />
<%= format_date @document.created_on %></em></p> <%= format_date @document.created_on %></em></p>
<%= textilizable @document.description, :attachments => @document.attachments %> <%= textilizable @document.description, :attachments => @document.attachments %>
<br /> <br />
@@ -34,5 +34,3 @@
<%= submit_tag l(:button_add) %> <%= submit_tag l(:button_add) %>
<% end %> <% end %>
<% end %> <% end %>
<% set_html_title h(@document.title) -%>
-2
View File
@@ -24,5 +24,3 @@
<p><%= link_to l(:label_enumeration_new), { :action => 'new', :opt => option } %></p> <p><%= link_to l(:label_enumeration_new), { :action => 'new', :opt => option } %></p>
<% end %> <% end %>
<% set_html_title(l(:label_enumerations)) -%>
+28
View File
@@ -0,0 +1,28 @@
xml.instruct!
xml.rss "version" => "2.0", "xmlns:dc" => "http://purl.org/dc/elements/1.1/" do
xml.channel do
xml.title @title
xml.link url_for(:controller => 'welcome', :only_path => false)
xml.pubDate CGI.rfc1123_date(@journals.first ? @journals.first.created_on : Time.now)
xml.description l(:label_changes_details)
@journals.each do |journal|
issue = journal.issue
xml.item do
xml.title "#{issue.project.name} - #{issue.tracker.name} ##{issue.id}: #{issue.subject}"
url = url_for(:controller => 'issues' , :action => 'show', :id => issue, :only_path => false)
xml.link url
xml.description do
xml.text! h(journal.notes)
xml.text! "<ul>"
journal.details.each do |detail|
xml.text! "<li>" + show_detail(detail, false) + "</li>"
end
xml.text! "</ul>"
end
xml.pubDate CGI.rfc1123_date(journal.created_on)
xml.guid url
xml.author h(journal.user.name)
end
end
end
end
@@ -4,26 +4,24 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom" do
xml.link "rel" => "self", "href" => url_for(:controller => 'feeds', :action => 'history', :format => 'atom', :only_path => false) xml.link "rel" => "self", "href" => url_for(:controller => 'feeds', :action => 'history', :format => 'atom', :only_path => false)
xml.link "rel" => "alternate", "href" => url_for(:controller => 'welcome', :only_path => false) xml.link "rel" => "alternate", "href" => url_for(:controller => 'welcome', :only_path => false)
xml.id url_for(:controller => 'welcome', :only_path => false) xml.id url_for(:controller => 'welcome', :only_path => false)
xml.updated((@changes.first ? @changes.first.event_datetime : Time.now).xmlschema) xml.updated CGI.rfc1123_date(@journals.first.created_on) if @journals.any?
xml.author { xml.name "#{Setting.app_title}" } xml.author { xml.name "#{Setting.app_title}" }
@changes.each do |change| @journals.each do |journal|
issue = change.issue issue = journal.issue
xml.entry do xml.entry do
xml.title "#{issue.project.name} - #{issue.tracker.name} ##{issue.id}: #{issue.subject}" xml.title "#{issue.project.name} - #{issue.tracker.name} ##{issue.id}: #{issue.subject}"
xml.link "rel" => "alternate", "href" => url_for(:controller => 'issues' , :action => 'show', :id => issue, :only_path => false) xml.link "rel" => "alternate", "href" => url_for(:controller => 'issues' , :action => 'show', :id => issue, :only_path => false)
xml.id url_for(:controller => 'issues' , :action => 'show', :id => issue, :journal_id => change, :only_path => false) xml.id url_for(:controller => 'issues' , :action => 'show', :id => issue, :only_path => false)
xml.updated change.created_on.xmlschema xml.updated CGI.rfc1123_date(journal.created_on)
xml.author do xml.author { xml.name journal.user.name }
xml.name change.user.name xml.summary journal.notes
xml.email(change.user.mail)
end
xml.content "type" => "html" do xml.content "type" => "html" do
xml.text! '<ul>' xml.text! journal.notes if journal.notes
change.details.each do |detail| xml.text! "<ul>"
xml.text! '<li>' + show_detail(detail, false) + '</li>' journal.details.each do |detail|
xml.text! "<li>" + show_detail(detail, false) + "</li>"
end end
xml.text! '</ul>' xml.text! "</ul>"
xml.text! textilizable(change.notes) unless change.notes.blank?
end end
end end
end end
+20
View File
@@ -0,0 +1,20 @@
xml.instruct!
xml.rss "version" => "2.0", "xmlns:dc" => "http://purl.org/dc/elements/1.1/" do
xml.channel do
xml.title @title
xml.link url_for(:controller => 'welcome', :only_path => false)
xml.pubDate CGI.rfc1123_date(@issues.first ? @issues.first.created_on : Time.now)
xml.description l(:label_reported_issues)
@issues.each do |issue|
xml.item do
xml.title "#{issue.project.name} - #{issue.tracker.name} ##{issue.id}: #{issue.subject}"
url = url_for(:controller => 'issues' , :action => 'show', :id => issue, :only_path => false)
xml.link url
xml.description h(issue.description)
xml.pubDate CGI.rfc1123_date(issue.created_on)
xml.guid url
xml.author h(issue.author.name)
end
end
end
end
+22
View File
@@ -0,0 +1,22 @@
xml.instruct!
xml.feed "xmlns" => "http://www.w3.org/2005/Atom" do
xml.title @title
xml.link "rel" => "self", "href" => url_for(:controller => 'feeds', :action => 'issues', :format => 'atom', :only_path => false)
xml.link "rel" => "alternate", "href" => url_for(:controller => 'welcome', :only_path => false)
xml.id url_for(:controller => 'welcome', :only_path => false)
xml.updated CGI.rfc1123_date(@issues.first.updated_on) if @issues.any?
xml.author { xml.name "#{Setting.app_title}" }
@issues.each do |issue|
xml.entry do
xml.title "#{issue.project.name} - #{issue.tracker.name} ##{issue.id}: #{issue.subject}"
xml.link "rel" => "alternate", "href" => url_for(:controller => 'issues' , :action => 'show', :id => issue, :only_path => false)
xml.id url_for(:controller => 'issues' , :action => 'show', :id => issue, :only_path => false)
xml.updated CGI.rfc1123_date(issue.updated_on)
xml.author { xml.name issue.author.name }
xml.summary issue.description
xml.content "type" => "html" do
xml.text! issue.description
end
end
end
end
+20
View File
@@ -0,0 +1,20 @@
xml.instruct!
xml.rss "version" => "2.0", "xmlns:dc" => "http://purl.org/dc/elements/1.1/" do
xml.channel do
xml.title "#{Setting.app_title}: #{l(:label_news_latest)}"
xml.link url_for(:controller => 'welcome', :only_path => false)
xml.pubDate CGI.rfc1123_date(@news.first ? @news.first.created_on : Time.now)
xml.description l(:label_news_latest)
@news.each do |news|
xml.item do
xml.title "#{news.project.name}: #{news.title}"
news_url = url_for(:controller => 'news' , :action => 'show', :id => news, :only_path => false)
xml.link news_url
xml.description h(news.summary)
xml.pubDate CGI.rfc1123_date(news.created_on)
xml.guid news_url
xml.author h(news.author.name)
end
end
end
end
+22
View File
@@ -0,0 +1,22 @@
xml.instruct!
xml.feed "xmlns" => "http://www.w3.org/2005/Atom" do
xml.title "#{Setting.app_title}: #{l(:label_news_latest)}"
xml.link "rel" => "self", "href" => url_for(:controller => 'feeds', :action => 'news', :format => 'atom', :only_path => false)
xml.link "rel" => "alternate", "href" => url_for(:controller => 'welcome', :only_path => false)
xml.id url_for(:controller => 'welcome', :only_path => false)
xml.updated CGI.rfc1123_date(@news.first.created_on) if @news.any?
xml.author { xml.name "#{Setting.app_title}" }
@news.each do |news|
xml.entry do
xml.title news.title
xml.link "rel" => "alternate", "href" => url_for(:controller => 'news' , :action => 'show', :id => news, :only_path => false)
xml.id url_for(:controller => 'news' , :action => 'show', :id => news, :only_path => false)
xml.updated CGI.rfc1123_date(news.created_on)
xml.author { xml.name news.author.name }
xml.summary h(news.summary)
xml.content "type" => "html" do
xml.text! news.description
end
end
end
end
-2
View File
@@ -33,5 +33,3 @@
</table> </table>
<%= pagination_links_full @issue_status_pages %> <%= pagination_links_full @issue_status_pages %>
<% set_html_title(l(:label_issue_status_plural)) -%>
+5 -5
View File
@@ -7,14 +7,14 @@
</tr></thead> </tr></thead>
<tbody> <tbody>
<% for issue in issues %> <% for issue in issues %>
<tr id="issue-<%= issue.id %>" class="issue hascontextmenu <%= cycle('odd', 'even') %> <%= "status-#{issue.status.position} priority-#{issue.priority.position}" %>"> <tr class="<%= cycle("odd", "even") %> <%= "status-#{issue.status.position} priority-#{issue.priority.position}" %>">
<td class="id"> <td class="id">
<%= link_to issue.id, :controller => 'issues', :action => 'show', :id => issue %> <%= link_to issue.id, :controller => 'issues', :action => 'show', :id => issue %>
</td> </td>
<td><%=h issue.project.name %> - <%= issue.tracker.name %><br /> <td><p class="small"><%= issue.project.name %> - <%= issue.tracker.name %><br />
<%= issue.status.name %> - <%= format_time(issue.updated_on) %></td> <%= issue.status.name %> - <%= format_time(issue.updated_on) %></p></td>
<td class="subject"> <td>
<%= link_to h(issue.subject), :controller => 'issues', :action => 'show', :id => issue %> <p class="small"><%= link_to h(issue.subject), :controller => 'issues', :action => 'show', :id => issue %></p>
</td> </td>
</tr> </tr>
<% end %> <% end %>
+3 -3
View File
@@ -1,10 +1,10 @@
<% if authorize_for('projects', 'add_issue') && @project.trackers.any? %> <% if authorize_for('projects', 'add_issue') %>
<h3><%= l(:label_issue_new) %></h3> <h3><%= l(:label_issue_new) %></h3>
<%= l(:label_tracker) %>: <%= new_issue_selector %> <%= l(:label_tracker) %>: <%= new_issue_selector %>
<% end %> <% end %>
<h3><%= l(:label_issue_plural) %></h3> <h3><%= l(:label_issue_plural) %></h3>
<%= link_to l(:label_issue_view_all), { :controller => 'issues', :action => 'index', :project_id => @project, :set_filter => 1 } %><br /> <%= link_to l(:label_issue_view_all), :controller => 'projects', :action => 'list_issues', :id => @project, :set_filter => 1 %><br />
<%= link_to l(:field_summary), :controller => 'reports', :action => 'issue_report', :id => @project %><br /> <%= link_to l(:field_summary), :controller => 'reports', :action => 'issue_report', :id => @project %><br />
<%= link_to l(:label_change_log), :controller => 'projects', :action => 'changelog', :id => @project %> <%= link_to l(:label_change_log), :controller => 'projects', :action => 'changelog', :id => @project %>
@@ -14,5 +14,5 @@
:order => "name ASC", :order => "name ASC",
:conditions => ["is_public = ? or user_id = ?", true, (User.current.logged? ? User.current.id : 0)]) :conditions => ["is_public = ? or user_id = ?", true, (User.current.logged? ? User.current.id : 0)])
queries.each do |query| %> queries.each do |query| %>
<%= link_to query.name, :controller => 'issues', :action => 'index', :project_id => @project, :query_id => query %><br /> <%= link_to query.name, :controller => 'projects', :action => 'list_issues', :id => @project, :query_id => query %><br />
<% end %> <% end %>
+2
View File
@@ -29,9 +29,11 @@
<p><label for="notes"><%= l(:field_notes) %></label> <p><label for="notes"><%= l(:field_notes) %></label>
<%= text_area_tag 'notes', @notes, :cols => 60, :rows => 10, :class => 'wiki-edit' %></p> <%= text_area_tag 'notes', @notes, :cols => 60, :rows => 10, :class => 'wiki-edit' %></p>
<% if authorize_for('issues', 'add_attachment') %>
<p id="attachments_p"><label><%=l(:label_attachment_new)%> <p id="attachments_p"><label><%=l(:label_attachment_new)%>
<%= image_to_function "add.png", "addFileField();return false" %></label> <%= image_to_function "add.png", "addFileField();return false" %></label>
<%= file_field_tag 'attachments[]', :size => 30 %> <em>(<%= l(:label_max_size) %>: <%= number_to_human_size(Setting.attachment_max_size.to_i.kilobytes) %>)</em></p> <%= file_field_tag 'attachments[]', :size => 30 %> <em>(<%= l(:label_max_size) %>: <%= number_to_human_size(Setting.attachment_max_size.to_i.kilobytes) %>)</em></p>
<% end %>
</div> </div>
<%= submit_tag l(:button_save) %> <%= submit_tag l(:button_save) %>
+2 -2
View File
@@ -1,4 +1,4 @@
<% back_to = url_for(:controller => 'issues', :action => 'index', :project_id => @project) %> <% back_to = url_for(:controller => 'projects', :action => 'list_issues', :id => @project) %>
<ul> <ul>
<li><%= context_menu_link l(:button_edit), {:controller => 'issues', :action => 'edit', :id => @issue}, <li><%= context_menu_link l(:button_edit), {:controller => 'issues', :action => 'edit', :id => @issue},
:class => 'icon-edit', :disabled => !@can[:edit] %></li> :class => 'icon-edit', :disabled => !@can[:edit] %></li>
@@ -32,7 +32,7 @@
</ul> </ul>
</li> </li>
<li><%= context_menu_link l(:button_copy), {:controller => 'projects', :action => 'add_issue', :id => @project, :copy_from => @issue}, <li><%= context_menu_link l(:button_copy), {:controller => 'projects', :action => 'add_issue', :id => @project, :copy_from => @issue},
:class => 'icon-copy', :disabled => !@can[:copy] %></li> :class => 'icon-copy', :disabled => !@can[:add] %></li>
<li><%= context_menu_link l(:button_move), {:controller => 'projects', :action => 'move_issues', :id => @project, "issue_ids[]" => @issue.id }, <li><%= context_menu_link l(:button_move), {:controller => 'projects', :action => 'move_issues', :id => @project, "issue_ids[]" => @issue.id },
:class => 'icon-move', :disabled => !@can[:move] %> :class => 'icon-move', :disabled => !@can[:move] %>
<li><%= context_menu_link l(:button_delete), {:controller => 'issues', :action => 'destroy', :id => @issue}, <li><%= context_menu_link l(:button_delete), {:controller => 'issues', :action => 'destroy', :id => @issue},
+21 -59
View File
@@ -1,73 +1,35 @@
<% if @query.new_record? %> <h2><%=l(:label_issue_plural)%></h2>
<h2><%=l(:label_issue_plural)%></h2>
<% set_html_title l(:label_issue_plural) %>
<% form_tag({ :controller => 'queries', :action => 'new' }, :id => 'query_form') do %> <% form_tag({}, :id => 'query_form') do %>
<%= hidden_field_tag('project_id', @project.id) if @project %> <%= render :partial => 'queries/filters', :locals => {:query => @query} %>
<%= render :partial => 'queries/filters', :locals => {:query => @query} %>
<div class="contextual">
<%= link_to_remote l(:button_apply),
{ :url => { :set_filter => 1 },
:update => "content",
:with => "Form.serialize('query_form')"
}, :class => 'icon icon-checked' %>
<%= link_to_remote l(:button_clear),
{ :url => { :set_filter => 1 },
:update => "content",
}, :class => 'icon icon-reload' %>
<% if current_role && current_role.allowed_to?(:save_queries) %>
<%= link_to l(:button_save), {}, :onclick => "$('query_form').submit(); return false;", :class => 'icon icon-save' %>
<% end %>
</div>
<br />
&nbsp;
<% end %>
<% else %>
<div class="contextual">
<% if @query.editable_by?(User.current) %>
<%= link_to l(:button_edit), {:controller => 'queries', :action => 'edit', :id => @query}, :class => 'icon icon-edit' %>
<%= link_to l(:button_delete), {:controller => 'queries', :action => 'destroy', :id => @query}, :confirm => l(:text_are_you_sure), :method => :post, :class => 'icon icon-del' %>
<% end %>
</div>
<h2><%= @query.name %></h2>
<div id="query_form"></div>
<% set_html_title @query.name %>
<% end %> <% end %>
<div class="contextual">
<%= link_to_remote l(:button_apply),
{ :url => { :set_filter => 1 },
:update => "content",
:with => "Form.serialize('query_form')"
}, :class => 'icon icon-edit' %>
<%= link_to_remote l(:button_clear),
{ :url => { :set_filter => 1 },
:update => "content",
}, :class => 'icon icon-reload' %>
</div>
<br />&nbsp;
<%= error_messages_for 'query' %> <%= error_messages_for 'query' %>
<% if @query.valid? %> <% if @query.valid? %>
<% if @issues.empty? %> <% if @issues.empty? %>
<p class="nodata"><%= l(:label_no_data) %></p> <p><i><%= l(:label_no_data) %></i></p>
<% else %> <% else %>
<% form_tag({:controller => 'projects', :action => 'bulk_edit_issues', :id => @project}, :id => 'issues_form', :onsubmit => "if (!checkBulkEdit(this)) {alert('#{l(:notice_no_issue_selected)}'); return false;}" ) do %> &nbsp;
<%= render :partial => 'issues/list', :locals => {:issues => @issues, :query => @query} %> <%= render :partial => 'issues/list', :locals => {:issues => @issues, :query => @query} %>
<div class="contextual">
<%= l(:label_export_to) %>
<%= link_to 'CSV', {:format => 'csv'}, :class => 'icon icon-csv' %>,
<%= link_to 'PDF', {:format => 'pdf'}, :class => 'icon icon-pdf' %>
</div>
<p><%= pagination_links_full @issue_pages %> <p><%= pagination_links_full @issue_pages %>
[ <%= @issue_pages.current.first_item %> - <%= @issue_pages.current.last_item %> / <%= @issue_count %> ]</p> [ <%= @issue_pages.current.first_item %> - <%= @issue_pages.current.last_item %> / <%= @issue_count %> ]</p>
<% end %> <% end %>
<% end %> <% end %>
<% end %>
<% content_for :sidebar do %>
<%= render :partial => 'issues/sidebar' %>
<% end if @project%>
<% content_for :header_tags do %> <% content_for :header_tags do %>
<%= auto_discovery_link_tag(:atom, {:query_id => @query, :format => 'atom', :page => nil, :key => User.current.rss_key}, :title => l(:label_issue_plural)) %> <%= auto_discovery_link_tag(:atom, params.merge({:format => 'atom', :page => nil, :key => User.current.rss_key})) %>
<%= auto_discovery_link_tag(:atom, {:action => 'changes', :query_id => @query, :format => 'atom', :page => nil, :key => User.current.rss_key}, :title => l(:label_changes_details)) %>
<%= javascript_include_tag 'calendar/calendar' %>
<%= javascript_include_tag "calendar/lang/calendar-#{current_language}.js" %>
<%= javascript_include_tag 'calendar/calendar-setup' %>
<%= stylesheet_link_tag 'calendar' %>
<%= javascript_include_tag 'context_menu' %>
<%= stylesheet_link_tag 'context_menu' %>
<% end %> <% end %>
<div id="context-menu" style="display: none;"></div>
<%= javascript_tag 'new ContextMenu({})' %>
+3 -3
View File
@@ -10,7 +10,7 @@
<h2><%= @issue.tracker.name %> #<%= @issue.id %></h2> <h2><%= @issue.tracker.name %> #<%= @issue.id %></h2>
<div class="issue <%= "status-#{@issue.status.position} priority-#{@issue.priority.position}" %>"> <div class="issue">
<h3><%=h @issue.subject %></h3> <h3><%=h @issue.subject %></h3>
<p class="author"> <p class="author">
<%= authoring @issue.created_on, @issue.author %>. <%= authoring @issue.created_on, @issue.author %>.
@@ -28,7 +28,7 @@
</tr> </tr>
<tr> <tr>
<td><b><%=l(:field_assigned_to)%> :</b></td><td><%= @issue.assigned_to ? link_to_user(@issue.assigned_to) : "-" %></td> <td><b><%=l(:field_assigned_to)%> :</b></td><td><%= @issue.assigned_to ? link_to_user(@issue.assigned_to) : "-" %></td>
<td><b><%=l(:field_done_ratio)%> :</b></td><td><%= progress_bar @issue.done_ratio, :width => '80px', :legend => "#{@issue.done_ratio}%" %></td> <td><b><%=l(:field_done_ratio)%> :</b></td><td><%= @issue.done_ratio %> %</td>
</tr> </tr>
<tr> <tr>
<td><b><%=l(:field_category)%> :</b></td><td><%=h @issue.category ? @issue.category.name : "-" %></td> <td><b><%=l(:field_category)%> :</b></td><td><%=h @issue.category ? @issue.category.name : "-" %></td>
@@ -64,7 +64,7 @@ end %>
<% end %> <% end %>
<p><strong><%=l(:field_description)%></strong></p> <p><strong><%=l(:field_description)%></strong></p>
<%= textilizable @issue, :description, :attachments => @issue.attachments %> <%= textilizable @issue.description, :attachments => @issue.attachments %>
<% if @issue.attachments.any? %> <% if @issue.attachments.any? %>
<%= link_to_attachments @issue.attachments, :delete_url => (authorize_for('issues', 'destroy_attachment') ? {:controller => 'issues', :action => 'destroy_attachment', :id => @issue} : nil) %> <%= link_to_attachments @issue.attachments, :delete_url => (authorize_for('issues', 'destroy_attachment') ? {:controller => 'issues', :action => 'destroy_attachment', :id => @issue} : nil) %>
+2 -2
View File
@@ -3,10 +3,10 @@
<option selected><%= l(:label_jump_to_a_project) %></option> <option selected><%= l(:label_jump_to_a_project) %></option>
<option disabled>---</option> <option disabled>---</option>
<% user_projects_by_root.keys.sort.each do |root| %> <% user_projects_by_root.keys.sort.each do |root| %>
<%= content_tag('option', h(root.name), :value => url_for(:controller => 'projects', :action => 'show', :id => root)) %> <%= content_tag('option', root.name, :value => url_for(:controller => 'projects', :action => 'show', :id => root)) %>
<% user_projects_by_root[root].sort.each do |project| %> <% user_projects_by_root[root].sort.each do |project| %>
<% next if project == root %> <% next if project == root %>
<%= content_tag('option', ('&#187; ' + h(project.name)), :value => url_for(:controller => 'projects', :action => 'show', :id => project)) %> <%= content_tag('option', ('&#187; ' + project.name), :value => url_for(:controller => 'projects', :action => 'show', :id => project)) %>
<% end %> <% end %>
<% end %> <% end %>
</select> </select>
+9 -9
View File
@@ -22,18 +22,18 @@
<div id="account"> <div id="account">
<% if User.current.logged? %> <% if User.current.logged? %>
<%=l(:label_logged_as)%> <%= User.current.login %> - <%=l(:label_logged_as)%> <%= User.current.login %> -
<%= link_to l(:label_my_account), { :controller => 'my', :action => 'account' }, :class => 'myaccount' %> <%= link_to l(:label_my_account), { :controller => 'my', :action => 'account' } %>
<%= link_to l(:label_logout), { :controller => 'account', :action => 'logout' }, :class => 'logout' %> <%= link_to l(:label_logout), { :controller => 'account', :action => 'logout' } %>
<% else %> <% else %>
<%= link_to l(:label_login), { :controller => 'account', :action => 'login' }, :class => 'signin' %> <%= link_to l(:label_login), { :controller => 'account', :action => 'login' } %>
<%= link_to(l(:label_register), { :controller => 'account',:action => 'register' }, :class => 'register') if Setting.self_registration? %> <%= link_to(l(:label_register), :controller => 'account',:action => 'register') if Setting.self_registration? %>
<% end %> <% end %>
</div> </div>
<%= link_to l(:label_home), home_url, :class => 'home' %> <%= link_to l(:label_home), home_url %>
<%= link_to l(:label_my_page), { :controller => 'my', :action => 'page'}, :class => 'mypage' if User.current.logged? %> <%= link_to l(:label_my_page), { :controller => 'my', :action => 'page'} if User.current.logged? %>
<%= link_to l(:label_project_plural), { :controller => 'projects' }, :class => 'projects' %> <%= link_to l(:label_project_plural), { :controller => 'projects' } %>
<%= link_to l(:label_administration), { :controller => 'admin' }, :class => 'admin' if User.current.admin? %> <%= link_to l(:label_administration), { :controller => 'admin' } if User.current.admin? %>
<%= link_to l(:label_help), Redmine::Info.help_url, :class => 'help' %> <%= link_to l(:label_help), Redmine::Info.help_url %>
</div> </div>
<div id="header"> <div id="header">
@@ -1,2 +0,0 @@
<p><%= l(:mail_body_account_activation_request, @user.login) %></p>
<p><%= link_to @url, @url %></p>
@@ -1,2 +0,0 @@
<%= l(:mail_body_account_activation_request, @user.login) %>
<%= @url %>
+1 -1
View File
@@ -1,3 +1,3 @@
<%= l(:text_issue_added, "##{@issue.id}") %> <%= l(:text_issue_added, "##{@issue.id}") %>
<hr /> <hr />
<%= render :partial => "issue_text_html", :locals => { :issue => @issue, :issue_url => @issue_url } %> <%= render :file => "_issue_text_html", :use_full_path => true, :locals => { :issue => @issue, :issue_url => @issue_url } %>
+1 -1
View File
@@ -1,3 +1,3 @@
<%= l(:text_issue_added, "##{@issue.id}") %> <%= l(:text_issue_added, "##{@issue.id}") %>
---------------------------------------- ----------------------------------------
<%= render :partial => "issue_text_plain", :locals => { :issue => @issue, :issue_url => @issue_url } %> <%= render :file => "_issue_text_plain", :use_full_path => true, :locals => { :issue => @issue, :issue_url => @issue_url } %>
+1 -1
View File
@@ -7,4 +7,4 @@
</ul> </ul>
<%= textilizable(@journal.notes) %> <%= textilizable(@journal.notes) %>
<hr /> <hr />
<%= render :partial => "issue_text_html", :locals => { :issue => @issue, :issue_url => @issue_url } %> <%= render :file => "_issue_text_html", :use_full_path => true, :locals => { :issue => @issue, :issue_url => @issue_url } %>
+1 -1
View File
@@ -5,4 +5,4 @@
<% end %> <% end %>
<%= @journal.notes if @journal.notes? %> <%= @journal.notes if @journal.notes? %>
---------------------------------------- ----------------------------------------
<%= render :partial => "issue_text_plain", :locals => { :issue => @issue, :issue_url => @issue_url } %> <%= render :file => "_issue_text_plain", :use_full_path => true, :locals => { :issue => @issue, :issue_url => @issue_url } %>
@@ -1,4 +1,4 @@
<h1><%=h @message.board.project.name %> - <%=h @message.board.name %>: <%= link_to @message.subject, @message_url %></h1> <h1><%=h @message.board.project.name %> - <%=h @message.board.name %>: <%= link_to @message.subject, @message_url %></h1>
<em><%= @message.author %></em> <em><%= @message.author.name %></em>
<%= textilizable @message.content %> <%= textilizable @message.content %>
@@ -1,4 +1,4 @@
<%= @message_url %> <%= @message_url %>
<%= @message.author %> <%= @message.author.name %>
<%= @message.content %> <%= @message.content %>
+2 -9
View File
@@ -3,19 +3,12 @@
<div class="box"> <div class="box">
<!--[form:message]--> <!--[form:message]-->
<p><label><%= l(:field_subject) %></label><br /> <p><label><%= l(:field_subject) %></label><br />
<%= f.text_field :subject, :required => true, :size => 120 %> <%= f.text_field :subject, :required => true, :size => 120 %></p>
<% if User.current.allowed_to?(:edit_messages, @project) %> <p><%= f.text_area :content, :required => true, :cols => 80, :rows => 15, :class => 'wiki-edit' %></p>
<label><%= f.check_box :sticky %> Sticky</label>
<label><%= f.check_box :locked %> Locked</label>
<% end %>
</p>
<p><%= f.text_area :content, :required => true, :cols => 80, :rows => 15, :class => 'wiki-edit', :id => 'message_content' %></p>
<%= wikitoolbar_for 'message_content' %> <%= wikitoolbar_for 'message_content' %>
<!--[eoform:message]--> <!--[eoform:message]-->
<span class="tabular"> <span class="tabular">
<%= render :partial => 'attachments/form' %> <%= render :partial => 'attachments/form' %>
</span>
</div> </div>
-6
View File
@@ -1,6 +0,0 @@
<h2><%= link_to h(@board.name), :controller => 'boards', :action => 'show', :project_id => @project, :id => @board %> &#187; <%=h @message.subject %></h2>
<% form_for :message, @message, :url => {:action => 'edit'}, :html => {:multipart => true} do |f| %>
<%= render :partial => 'form', :locals => {:f => f} %>
<%= submit_tag l(:button_save) %>
<% end %>
+13 -25
View File
@@ -1,39 +1,27 @@
<div class="contextual"> <h2><%= link_to h(@board.name), :controller => 'boards', :action => 'show', :project_id => @project, :id => @board %> &#187; <%=h @message.subject %></h2>
<%= link_to_if_authorized l(:button_edit), {:action => 'edit', :id => @topic}, :class => 'icon icon-edit' %>
<%= link_to_if_authorized l(:button_delete), {:action => 'destroy', :id => @topic}, :method => :post, :confirm => l(:text_are_you_sure), :class => 'icon icon-del' %>
</div>
<h2><%= link_to h(@board.name), :controller => 'boards', :action => 'show', :project_id => @project, :id => @board %> &#187; <%=h @topic.subject %></h2> <p><span class="author"><%= authoring @message.created_on, @message.author %></span></p>
<div class="message">
<p><span class="author"><%= authoring @topic.created_on, @topic.author %></span></p>
<div class="wiki"> <div class="wiki">
<%= textilizable(@topic.content, :attachments => @topic.attachments) %> <%= textilizable(@message.content, :attachments => @message.attachments) %>
</div>
<%= link_to_attachments @topic.attachments, :no_author => true %>
</div> </div>
<%= link_to_attachments @message.attachments, :no_author => true %>
<br /> <br />
<h3 class="icon22 icon22-comment"><%= l(:label_reply_plural) %></h3> <h3 class="icon22 icon22-comment"><%= l(:label_reply_plural) %></h3>
<% @topic.children.each do |message| %> <% @message.children.each do |message| %>
<a name="<%= "message-#{message.id}" %>"></a> <a name="<%= "message-#{message.id}" %>"></a>
<div class="contextual"> <h4><%=h message.subject %> - <%= message.author.name %>, <%= format_time(message.created_on) %></h4>
<%= link_to_if_authorized l(:button_edit), {:action => 'edit', :id => message}, :class => 'icon icon-edit' %>
<%= link_to_if_authorized l(:button_delete), {:action => 'destroy', :id => message}, :method => :post, :confirm => l(:text_are_you_sure), :class => 'icon icon-del' %>
</div>
<div class="message reply">
<h4><%=h message.subject %> - <%= authoring message.created_on, message.author %></h4>
<div class="wiki"><%= textilizable message.content %></div> <div class="wiki"><%= textilizable message.content %></div>
<%= link_to_attachments message.attachments, :no_author => true %>
</div>
<% end %> <% end %>
<% if !@topic.locked? && authorize_for('messages', 'reply') %> <% if authorize_for('messages', 'reply') %>
<p><%= toggle_link l(:button_reply), "reply", :focus => 'message_content' %></p> <p><%= toggle_link l(:button_reply), "reply", :focus => "reply_content" %></p>
<div id="reply" style="display:none;"> <div id="reply" style="display:none;">
<% form_for :reply, @reply, :url => {:action => 'reply', :id => @topic}, :html => {:multipart => true} do |f| %> <%= error_messages_for 'message' %>
<%= render :partial => 'form', :locals => {:f => f} %> <% form_for :reply, @reply, :url => {:action => 'reply', :id => @message} do |f| %>
<%= submit_tag l(:button_submit) %> <p><%= f.text_field :subject, :required => true, :size => 60 %></p>
<p><%= f.text_area :content, :required => true, :cols => 80, :rows => 10 %></p>
<p><%= submit_tag l(:button_submit) %></p>
<% end %> <% end %>
</div> </div>
<% end %> <% end %>
+2 -9
View File
@@ -4,10 +4,7 @@
<h2><%=l(:label_my_account)%></h2> <h2><%=l(:label_my_account)%></h2>
<%= error_messages_for 'user' %> <%= error_messages_for 'user' %>
<% form_for :user, @user, :url => { :action => "account" }, <% form_for :user, @user, :url => { :action => "account" }, :builder => TabularFormBuilder, :lang => current_language do |f| %>
:builder => TabularFormBuilder,
:lang => current_language,
:html => { :id => 'my_account_form' } do |f| %>
<div class="splitcontentleft"> <div class="splitcontentleft">
<h3><%=l(:label_information_plural)%></h3> <h3><%=l(:label_information_plural)%></h3>
<div class="box tabular"> <div class="box tabular">
@@ -17,7 +14,6 @@
<p><%= f.select :language, lang_options_for_select %></p> <p><%= f.select :language, lang_options_for_select %></p>
<% fields_for :pref, @user.pref, :builder => TabularFormBuilder, :lang => current_language do |pref_fields| %> <% fields_for :pref, @user.pref, :builder => TabularFormBuilder, :lang => current_language do |pref_fields| %>
<p><%= pref_fields.select :time_zone, TimeZone.all.collect {|z| [ z.to_s, z.name ]}, :include_blank => true %></p>
<p><%= pref_fields.check_box :hide_mail %></p> <p><%= pref_fields.check_box :hide_mail %></p>
<% end %> <% end %>
</div> </div>
@@ -32,11 +28,10 @@
:onchange => 'if ($("notification_option").value == "selected") {Element.show("notified-projects")} else {Element.hide("notified-projects")}' %> :onchange => 'if ($("notification_option").value == "selected") {Element.show("notified-projects")} else {Element.hide("notified-projects")}' %>
<% content_tag 'div', :id => 'notified-projects', :style => (@notification_option == 'selected' ? '' : 'display:none;') do %> <% content_tag 'div', :id => 'notified-projects', :style => (@notification_option == 'selected' ? '' : 'display:none;') do %>
<p><% User.current.projects.each do |project| %> <p><% User.current.projects.each do |project| %>
<label><%= check_box_tag 'notified_project_ids[]', project.id, @user.notified_projects_ids.include?(project.id) %> <%=h project.name %></label><br /> <label><%= check_box_tag 'notified_project_ids[]', project.id, @user.notified_projects_ids.include?(project.id) %> <%= project.name %></label><br />
<% end %></p> <% end %></p>
<p><em><%= l(:text_user_mail_option) %></em></p> <p><em><%= l(:text_user_mail_option) %></em></p>
<% end %> <% end %>
<p><label><%= check_box_tag 'no_self_notified', 1, @user.pref[:no_self_notified] %> <%= l(:label_user_mail_no_self_notified) %></label></p>
</div> </div>
</div> </div>
<% end %> <% end %>
@@ -44,5 +39,3 @@
<% content_for :sidebar do %> <% content_for :sidebar do %>
<%= render :partial => 'sidebar' %> <%= render :partial => 'sidebar' %>
<% end %> <% end %>
<% set_html_title l(:label_my_account) -%>
-9
View File
@@ -31,12 +31,3 @@
<% end if @blocks['right'] %> <% end if @blocks['right'] %>
</div> </div>
<% content_for :header_tags do %>
<%= javascript_include_tag 'context_menu' %>
<%= stylesheet_link_tag 'context_menu' %>
<% end %>
<div id="context-menu" style="display: none;"></div>
<%= javascript_tag 'new ContextMenu({})' %>
<% set_html_title l(:label_my_page) -%>
+1 -1
View File
@@ -9,7 +9,7 @@
<p><label for="new_password"><%=l(:field_new_password)%> <span class="required">*</span></label> <p><label for="new_password"><%=l(:field_new_password)%> <span class="required">*</span></label>
<%= password_field_tag 'new_password', nil, :size => 25 %><br /> <%= password_field_tag 'new_password', nil, :size => 25 %><br />
<em><%= l(:text_caracters_minimum, 4) %></em></p> <em><%= l(:text_length_between, 4, 12) %></em></p>
<p><label for="new_password_confirmation"><%=l(:field_password_confirmation)%> <span class="required">*</span></label> <p><label for="new_password_confirmation"><%=l(:field_password_confirmation)%> <span class="required">*</span></label>
<%= password_field_tag 'new_password_confirmation', nil, :size => 25 %></p> <%= password_field_tag 'new_password_confirmation', nil, :size => 25 %></p>
+3 -6
View File
@@ -26,21 +26,18 @@
<h3 class="icon22 icon22-comment"><%= l(:label_comment_plural) %></h3> <h3 class="icon22 icon22-comment"><%= l(:label_comment_plural) %></h3>
<% @news.comments.each do |comment| %> <% @news.comments.each do |comment| %>
<% next if comment.new_record? %> <% next if comment.new_record? %>
<h4><%= authoring comment.created_on, comment.author %></h4> <h4><%= format_time(comment.created_on) %> - <%= comment.author.name %></h4>
<div class="contextual"> <div class="contextual">
<%= link_to_if_authorized l(:button_delete), {:controller => 'news', :action => 'destroy_comment', :id => @news, :comment_id => comment}, :confirm => l(:text_are_you_sure), :method => :post, :class => 'icon icon-del' %> <%= link_to_if_authorized l(:button_delete), {:controller => 'news', :action => 'destroy_comment', :id => @news, :comment_id => comment}, :confirm => l(:text_are_you_sure), :method => :post, :class => 'icon icon-del' %>
</div> </div>
<%= textilizable(comment.comments) %> <%= simple_format(auto_link(h comment.comments))%>
<% end if @news.comments_count > 0 %> <% end if @news.comments_count > 0 %>
</div> </div>
<% if authorize_for 'news', 'add_comment' %> <% if authorize_for 'news', 'add_comment' %>
<p><%= toggle_link l(:label_comment_add), "add_comment_form", :focus => "comment_comments" %></p> <p><%= toggle_link l(:label_comment_add), "add_comment_form", :focus => "comment_comments" %></p>
<% form_tag({:action => 'add_comment', :id => @news}, :id => "add_comment_form", :style => "display:none;") do %> <% form_tag({:action => 'add_comment', :id => @news}, :id => "add_comment_form", :style => "display:none;") do %>
<%= text_area 'comment', 'comments', :cols => 80, :rows => 15, :class => 'wiki-edit' %> <%= text_area 'comment', 'comments', :cols => 60, :rows => 6 %>
<%= wikitoolbar_for 'comment_comments' %>
<p><%= submit_tag l(:button_add) %></p> <p><%= submit_tag l(:button_add) %></p>
<% end %> <% end %>
<% end %> <% end %>
<% set_html_title(h(@news.title)) -%>
+4 -20
View File
@@ -9,7 +9,7 @@
<% end %> <% end %>
<p><%= f.text_area :description, :required => true, :cols => 60, :rows => 5 %><em><%= l(:text_caracters_maximum, 255) %></em></p> <p><%= f.text_area :description, :required => true, :cols => 60, :rows => 5 %><em><%= l(:text_caracters_maximum, 255) %></em></p>
<p><%= f.text_field :identifier, :required => true, :disabled => @project.identifier_frozen? %><br /><em><%= l(:text_length_between, 3, 20) %> <%= l(:text_project_identifier_info) unless @project.identifier_frozen? %></em></p> <p><%= f.text_field :identifier, :required => true, :size => 15, :disabled => @project.identifier_frozen? %><br /><em><%= l(:text_length_between, 3, 12) %> <%= l(:text_project_identifier_info) unless @project.identifier_frozen? %></em></p>
<p><%= f.text_field :homepage, :size => 40 %></p> <p><%= f.text_field :homepage, :size => 40 %></p>
<p><%= f.check_box :is_public %></p> <p><%= f.check_box :is_public %></p>
<%= wikitoolbar_for 'project_description' %> <%= wikitoolbar_for 'project_description' %>
@@ -17,32 +17,16 @@
<% for @custom_value in @custom_values %> <% for @custom_value in @custom_values %>
<p><%= custom_field_tag_with_label @custom_value %></p> <p><%= custom_field_tag_with_label @custom_value %></p>
<% end %> <% end %>
</div>
<% unless @trackers.empty? %>
<fieldset class="box"><legend><%=l(:label_tracker_plural)%></legend>
<% @trackers.each do |tracker| %>
<label class="floating">
<%= check_box_tag 'project[tracker_ids][]', tracker.id, @project.trackers.include?(tracker) %>
<%= tracker %>
</label>
<% end %>
<%= hidden_field_tag 'project[tracker_ids][]', '' %>
</fieldset>
<% end %>
<% unless @custom_fields.empty? %> <% unless @custom_fields.empty? %>
<fieldset class="box"><legend><%=l(:label_custom_field_plural)%></legend> <p><label><%=l(:label_custom_field_plural)%></label>
<% for custom_field in @custom_fields %> <% for custom_field in @custom_fields %>
<label class="floating">
<%= check_box_tag "custom_field_ids[]", custom_field.id, ((@project.custom_fields.include? custom_field) or custom_field.is_for_all?), (custom_field.is_for_all? ? {:disabled => "disabled"} : {}) %> <%= check_box_tag "custom_field_ids[]", custom_field.id, ((@project.custom_fields.include? custom_field) or custom_field.is_for_all?), (custom_field.is_for_all? ? {:disabled => "disabled"} : {}) %>
<%= custom_field.name %> <%= custom_field.name %>
</label> <% end %></p>
<% end %>
</fieldset>
<% end %> <% end %>
<!--[eoform:project]--> <!--[eoform:project]-->
</div>
<% content_for :header_tags do %> <% content_for :header_tags do %>
<%= javascript_include_tag 'calendar/calendar' %> <%= javascript_include_tag 'calendar/calendar' %>
+2 -4
View File
@@ -4,9 +4,9 @@
<h3><%= day_name(day.cwday) %> <%= day.day %></h3> <h3><%= day_name(day.cwday) %> <%= day.day %></h3>
<ul> <ul>
<% @events_by_day[day].sort {|x,y| y.event_datetime <=> x.event_datetime }.each do |e| %> <% @events_by_day[day].sort {|x,y| y.event_datetime <=> x.event_datetime }.each do |e| %>
<li><p><%= format_time(e.event_datetime, false) %> <%= link_to truncate(e.event_title, 100), e.event_url %><br /> <li><p><%= e.event_datetime.strftime("%H:%M") %> <%= link_to truncate(e.event_title, 100), e.event_url %><br />
<% unless e.event_description.blank? %><em><%= truncate(e.event_description, 500) %></em><br /><% end %> <% unless e.event_description.blank? %><em><%= truncate(e.event_description, 500) %></em><br /><% end %>
<span class="author"><%= e.event_author if e.respond_to?(:event_author) %></span></p></li> <span class="author"><%= e.event_author if e.respond_to?(:author) %></span></p></li>
<% end %> <% end %>
</ul> </ul>
<% end %> <% end %>
@@ -39,5 +39,3 @@
<p><%= submit_tag l(:button_apply), :class => 'button-small' %></p> <p><%= submit_tag l(:button_apply), :class => 'button-small' %></p>
<% end %> <% end %>
<% end %> <% end %>
<% set_html_title l(:label_activity) -%>
+6 -6
View File
@@ -3,13 +3,13 @@
<% labelled_tabular_form_for :project, @project, :url => { :action => "add" } do |f| %> <% labelled_tabular_form_for :project, @project, :url => { :action => "add" } do |f| %>
<%= render :partial => 'form', :locals => { :f => f } %> <%= render :partial => 'form', :locals => { :f => f } %>
<fieldset class="box"><legend><%= l(:label_module_plural) %></legend> <div class="box">
<p><label><%= l(:label_module_plural) %></label>
<% Redmine::AccessControl.available_project_modules.each do |m| %> <% Redmine::AccessControl.available_project_modules.each do |m| %>
<label class="floating"> <%= check_box_tag 'enabled_modules[]', m, @project.module_enabled?(m) %> <%= m.to_s.humanize %>
<%= check_box_tag 'enabled_modules[]', m, @project.module_enabled?(m) %> <%= m.to_s.humanize %> <% end %></p>
</label> </div>
<% end %>
</fieldset>
<%= submit_tag l(:button_save) %> <%= submit_tag l(:button_save) %>
<% end %> <% end %>
-2
View File
@@ -38,5 +38,3 @@
<p><%= submit_tag l(:button_apply), :class => 'button-small' %></p> <p><%= submit_tag l(:button_apply), :class => 'button-small' %></p>
<% end %> <% end %>
<% end %> <% end %>
<% set_html_title l(:label_calendar) -%>
+1 -1
View File
@@ -1,7 +1,7 @@
<h2><%=l(:label_confirmation)%></h2> <h2><%=l(:label_confirmation)%></h2>
<div class="box"> <div class="box">
<center> <center>
<p><strong><%=h @project_to_destroy.name %></strong><br /> <p><strong><%= @project_to_destroy.name %></strong><br />
<%=l(:text_project_destroy_confirmation)%></p> <%=l(:text_project_destroy_confirmation)%></p>
<p> <p>
@@ -1,6 +1,5 @@
<% pdf=IfpdfHelper::IFPDF.new(current_language) <% pdf=IfpdfHelper::IFPDF.new(current_language)
title = @project ? "#{@project.name} - #{l(:label_issue_plural)}" : "#{l(:label_issue_plural)}" pdf.SetTitle("#{@project.name} - #{l(:label_issue_plural)}")
pdf.SetTitle(title)
pdf.AliasNbPages pdf.AliasNbPages
pdf.footer_date = format_date(Date.today) pdf.footer_date = format_date(Date.today)
pdf.AddPage("L") pdf.AddPage("L")
@@ -10,7 +9,7 @@
# title # title
# #
pdf.SetFontStyle('B',11) pdf.SetFontStyle('B',11)
pdf.Cell(190,10, title) pdf.Cell(190,10, "#{@project.name} - #{l(:label_issue_plural)}")
pdf.Ln pdf.Ln
# #
@@ -22,7 +21,7 @@
pdf.Cell(30, row_height, l(:field_tracker), 0, 0, 'L', 1) pdf.Cell(30, row_height, l(:field_tracker), 0, 0, 'L', 1)
pdf.Cell(30, row_height, l(:field_status), 0, 0, 'L', 1) pdf.Cell(30, row_height, l(:field_status), 0, 0, 'L', 1)
pdf.Cell(30, row_height, l(:field_priority), 0, 0, 'L', 1) pdf.Cell(30, row_height, l(:field_priority), 0, 0, 'L', 1)
pdf.Cell(40, row_height, l(:field_assigned_to), 0, 0, 'L', 1) pdf.Cell(40, row_height, l(:field_author), 0, 0, 'L', 1)
pdf.Cell(25, row_height, l(:field_updated_on), 0, 0, 'L', 1) pdf.Cell(25, row_height, l(:field_updated_on), 0, 0, 'L', 1)
pdf.Cell(0, row_height, l(:field_subject), 0, 0, 'L', 1) pdf.Cell(0, row_height, l(:field_subject), 0, 0, 'L', 1)
pdf.Line(10, pdf.GetY, 287, pdf.GetY) pdf.Line(10, pdf.GetY, 287, pdf.GetY)
@@ -40,7 +39,7 @@
pdf.Cell(30, row_height, issue.tracker.name, 0, 0, 'L', 1) pdf.Cell(30, row_height, issue.tracker.name, 0, 0, 'L', 1)
pdf.Cell(30, row_height, issue.status.name, 0, 0, 'L', 1) pdf.Cell(30, row_height, issue.status.name, 0, 0, 'L', 1)
pdf.Cell(30, row_height, issue.priority.name, 0, 0, 'L', 1) pdf.Cell(30, row_height, issue.priority.name, 0, 0, 'L', 1)
pdf.Cell(40, row_height, issue.assigned_to ? issue.assigned_to.name : '', 0, 0, 'L', 1) pdf.Cell(40, row_height, issue.author.name, 0, 0, 'L', 1)
pdf.Cell(25, row_height, format_date(issue.updated_on), 0, 0, 'L', 1) pdf.Cell(25, row_height, format_date(issue.updated_on), 0, 0, 'L', 1)
pdf.MultiCell(0, row_height, (@project == issue.project ? issue.subject : "#{issue.project.name} - #{issue.subject}")) pdf.MultiCell(0, row_height, (@project == issue.project ? issue.subject : "#{issue.project.name} - #{issue.subject}"))
pdf.Line(10, pdf.GetY, 287, pdf.GetY) pdf.Line(10, pdf.GetY, 287, pdf.GetY)

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