Conflicts:
	public/stylesheets/application.css
	public/stylesheets/scm.css
	test/fixtures/activities.yml
	test/fixtures/course_infos.yml
	test/fixtures/course_statuses.yml
	test/fixtures/schools.yml
	test/fixtures/user_extensions.yml
	test/functional/applied_project_controller_test.rb
	test/functional/apply_project_masters_controller_test.rb
	test/functional/attachment_type_edit_controller_test.rb
	test/functional/contestnotifications_controller_test.rb
	test/functional/forums_controller_test.rb
	test/functional/memos_controller_test.rb
	test/functional/no_uses_controller_test.rb
	test/functional/notificationcomments_controller_test.rb
	test/functional/open_source_projects_controller_test.rb
	test/functional/softapplications_controller_test.rb
	test/functional/test_controller_test.rb
	test/functional/web_footer_companies_controller_test.rb
	test/unit/attachmentstype_test.rb
	test/unit/contest_notification_test.rb
	test/unit/contesting_softapplication_test.rb
	test/unit/contestnotification_test.rb
	test/unit/course_group_test.rb
	test/unit/course_infos_test.rb
	test/unit/course_status_test.rb
	test/unit/forum_test.rb
	test/unit/helpers/applied_project_helper_test.rb
	test/unit/helpers/apply_project_masters_helper_test.rb
	test/unit/helpers/attachment_type_edit_helper_test.rb
	test/unit/helpers/contestnotifications_helper_test.rb
	test/unit/helpers/courses_helper_test.rb
	test/unit/helpers/forums_helper_test.rb
	test/unit/helpers/memos_helper_test.rb
	test/unit/helpers/no_uses_helper_test.rb
	test/unit/helpers/notificationcomments_helper_test.rb
	test/unit/helpers/open_source_projects_helper_test.rb
	test/unit/helpers/school_helper_test.rb
	test/unit/helpers/softapplications_helper_test.rb
	test/unit/helpers/stores_helper_test.rb
	test/unit/helpers/test_helper_test.rb
	test/unit/helpers/zipdown_helper_test.rb
	test/unit/join_in_contest_test.rb
	test/unit/journal_reply_test.rb
	test/unit/memo_test.rb
	test/unit/no_use_test.rb
	test/unit/notificationcomments_test.rb
	test/unit/open_source_project_test.rb
	test/unit/option_number_test.rb
	test/unit/project_score_test.rb
	test/unit/relative_memo_test.rb
	test/unit/school_test.rb
	test/unit/softapplication_test.rb
	test/unit/user_score_details_test.rb
	test/unit/web_footer_company_test.rb
	test/unit/web_footer_oranizer_test.rb
dev_dingxu
alanlong 11 years ago
commit 4c56bb3e4d

16
.gitignore vendored

@ -1,16 +0,0 @@
*.swp
/.project
/.idea
/.bundle
*.swp
/config/database.yml
/files/*
/log/*
/tmp/*
.gitignore
/public/images/avatars/*
/Gemfile
/Gemfile.lock
/db/schema.rb
/Gemfile.lock
/lib/plugins/acts_as_versioned/test/debug.log

@ -1,125 +1,136 @@
source 'https://rubygems.org'
unless RUBY_PLATFORM =~ /w32/
# unix-like only
gem 'iconv'
gem 'rubyzip'
gem 'zip-zip'
end
gem 'seems_rateable', path: 'lib/seems_rateable'
gem "rails", "3.2.13"
gem "jquery-rails", "~> 2.0.2"
gem "i18n", "~> 0.6.0"
gem "coderay", "~> 1.0.6"
gem "fastercsv", "~> 1.5.0", :platforms => [:mri_18, :mingw_18, :jruby]
gem "builder", "3.0.0"
gem 'acts-as-taggable-on', '2.4.1'
group :development do
gem 'better_errors', path: 'lib/better_errors'
gem 'rack-mini-profiler', path: 'lib/rack-mini-profiler'
if ENV['PRY']
gem 'pry'
gem 'pry-nav'
end
end
group :test do
# shoulda的版本做了改动
#gem "shoulda", "~> 3.3.2"
gem "shoulda", "> 3.3.2"
gem "mocha", "~> 0.13.3"
gem 'capybara', '~> 2.0.0'
gem 'nokogiri', '< 1.6.0'
end
# Gems used only for assets and not required
# in production environments by default.
group :assets do
gem 'sass-rails', '~> 3.2.3'
gem 'coffee-rails', '~> 3.2.1'
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
gem 'therubyracer', :platforms => :ruby
gem 'uglifier', '>= 1.0.3'
end
# Optional gem for LDAP authentication
group :ldap do
gem "net-ldap", "~> 0.3.1"
end
platforms :mri, :mingw do
group :rmagick do
# RMagick 2 supports ruby 1.9
# RMagick 1 would be fine for ruby 1.8 but Bundler does not support
# different requirements for the same gem on different platforms
gem "rmagick", ">= 2.0.0"
end
end
# Optional gem for OpenID authentication
group :openid do
gem "ruby-openid", "~> 2.1.4", :require => "openid"
gem "rack-openid"
end
# Optional gem for exporting the gantt to a PNG file, not supported with jruby
platforms :jruby do
# jruby-openssl is bundled with JRuby 1.7.0
gem "jruby-openssl" if Object.const_defined?(:JRUBY_VERSION) && JRUBY_VERSION < '1.7.0'
gem "activerecord-jdbc-adapter", "1.2.5"
end
# Include database gems for the adapters found in the database
# configuration file
require 'erb'
require 'yaml'
database_file = File.join(File.dirname(__FILE__), "config/database.yml")
if File.exist?(database_file)
database_config = YAML::load(ERB.new(IO.read(database_file)).result)
adapters = database_config.values.map {|c| c['adapter']}.compact.uniq
if adapters.any?
adapters.each do |adapter|
case adapter
when 'mysql2'
gem "mysql2", "= 0.3.11", :platforms => [:mri, :mingw]
gem "activerecord-jdbcmysql-adapter", :platforms => :jruby
when 'mysql'
gem "mysql", "~> 2.8.1", :platforms => [:mri, :mingw]
gem "activerecord-jdbcmysql-adapter", :platforms => :jruby
when /postgresql/
gem "pg", ">= 0.11.0", :platforms => [:mri, :mingw]
gem "activerecord-jdbcpostgresql-adapter", :platforms => :jruby
when /sqlite3/
gem "sqlite3", :platforms => [:mri, :mingw]
gem "activerecord-jdbcsqlite3-adapter", :platforms => :jruby
when /sqlserver/
gem "tiny_tds", "~> 0.5.1", :platforms => [:mri, :mingw]
gem "activerecord-sqlserver-adapter", :platforms => [:mri, :mingw]
else
warn("Unknown database adapter `#{adapter}` found in config/database.yml, use Gemfile.local to load your own database gems")
end
end
else
warn("No adapter found in config/database.yml, please configure it first")
end
else
warn("Please configure your config/database.yml first")
end
local_gemfile = File.join(File.dirname(__FILE__), "Gemfile.local")
if File.exists?(local_gemfile)
puts "Loading Gemfile.local ..." if $DEBUG # `ruby -d` or `bundle -v`
instance_eval File.read(local_gemfile)
end
# Load plugins' Gemfiles
Dir.glob File.expand_path("../plugins/*/Gemfile", __FILE__) do |file|
puts "Loading #{file} ..." if $DEBUG # `ruby -d` or `bundle -v`
instance_eval File.read(file)
end
source 'http://ruby.taobao.org'
#source 'http://ruby.sdutlinux.org/'
unless RUBY_PLATFORM =~ /w32/
# unix-like only
gem 'iconv'
gem 'rubyzip'
gem 'zip-zip'
end
gem 'seems_rateable', path: 'lib/seems_rateable'
gem "rails", "3.2.13"
gem "jquery-rails", "~> 2.0.2"
gem "i18n", "~> 0.6.0"
gem "coderay", "~> 1.0.6"
gem "fastercsv", "~> 1.5.0", :platforms => [:mri_18, :mingw_18, :jruby]
gem "builder", "3.0.0"
gem 'acts-as-taggable-on', '2.4.1'
gem 'spreadsheet'
gem 'ruby-ole'
group :development do
gem 'better_errors', path: 'lib/better_errors'
gem 'rack-mini-profiler', path: 'lib/rack-mini-profiler'
end
group :test do
gem "shoulda", "~> 3.5.0"
gem "mocha", "~> 1.1.0"
gem 'capybara', '~> 2.4.1'
gem 'nokogiri', '~> 1.6.3'
gem 'factory_girl', '~> 4.4.0'
gem 'selenium-webdriver', '~> 2.42.0'
platforms :mri, :mingw do
group :rmagick do
# RMagick 2 supports ruby 1.9
# RMagick 1 would be fine for ruby 1.8 but Bundler does not support
# different requirements for the same gem on different platforms
gem "rmagick", ">= 2.0.0"
end
end
end
group :development, :test do
gem "guard-rails", '~> 0.5.3'
gem 'spork-testunit', '~> 0.0.8'
gem 'guard-spork', '~> 1.5.1'
gem 'guard-test', '~> 1.0.0'
gem 'ruby-prof', '~> 0.15.1' unless RUBY_PLATFORM =~ /w32/
gem 'pry'
gem 'pry-nav'
end
# Gems used only for assets and not required
# in production environments by default.
group :assets do
gem 'sass-rails', '~> 3.2.3'
gem 'coffee-rails', '~> 3.2.1'
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
gem 'therubyracer', :platforms => :ruby
gem 'uglifier', '>= 1.0.3'
end
# Optional gem for LDAP authentication
group :ldap do
gem "net-ldap", "~> 0.3.1"
end
# Optional gem for OpenID authentication
group :openid do
gem "ruby-openid", "~> 2.1.4", :require => "openid"
gem "rack-openid"
end
# Optional gem for exporting the gantt to a PNG file, not supported with jruby
platforms :jruby do
# jruby-openssl is bundled with JRuby 1.7.0
gem "jruby-openssl" if Object.const_defined?(:JRUBY_VERSION) && JRUBY_VERSION < '1.7.0'
gem "activerecord-jdbc-adapter", "1.2.5"
end
# Include database gems for the adapters found in the database
# configuration file
require 'erb'
require 'yaml'
database_file = File.join(File.dirname(__FILE__), "config/database.yml")
if File.exist?(database_file)
database_config = YAML::load(ERB.new(IO.read(database_file)).result)
adapters = database_config.values.map {|c| c['adapter']}.compact.uniq
if adapters.any?
adapters.each do |adapter|
case adapter
when 'mysql2'
gem "mysql2", "= 0.3.11", :platforms => [:mri, :mingw]
gem "activerecord-jdbcmysql-adapter", :platforms => :jruby
when 'mysql'
gem "mysql", "~> 2.8.1", :platforms => [:mri, :mingw]
gem "activerecord-jdbcmysql-adapter", :platforms => :jruby
when /postgresql/
gem "pg", ">= 0.11.0", :platforms => [:mri, :mingw]
gem "activerecord-jdbcpostgresql-adapter", :platforms => :jruby
when /sqlite3/
gem "sqlite3", :platforms => [:mri, :mingw]
gem "activerecord-jdbcsqlite3-adapter", :platforms => :jruby
when /sqlserver/
gem "tiny_tds", "~> 0.5.1", :platforms => [:mri, :mingw]
gem "activerecord-sqlserver-adapter", :platforms => [:mri, :mingw]
else
warn("Unknown database adapter `#{adapter}` found in config/database.yml, use Gemfile.local to load your own database gems")
end
end
else
warn("No adapter found in config/database.yml, please configure it first")
end
else
warn("Please configure your config/database.yml first")
end
local_gemfile = File.join(File.dirname(__FILE__), "Gemfile.local")
if File.exists?(local_gemfile)
puts "Loading Gemfile.local ..." if $DEBUG # `ruby -d` or `bundle -v`
instance_eval File.read(local_gemfile)
end
# Load plugins' Gemfiles
Dir.glob File.expand_path("../plugins/*/Gemfile", __FILE__) do |file|
puts "Loading #{file} ..." if $DEBUG # `ruby -d` or `bundle -v`
instance_eval File.read(file)
end

@ -1,188 +0,0 @@
PATH
remote: lib/better_errors
specs:
better_errors (1.1.0)
coderay (>= 1.0.0)
erubis (>= 2.6.6)
PATH
remote: lib/rack-mini-profiler
specs:
rack-mini-profiler (0.9.1)
rack (>= 1.1.3)
PATH
remote: lib/seems_rateable
specs:
seems_rateable (1.0.13)
jquery-rails
rails
GEM
remote: https://rubygems.org/
specs:
actionmailer (3.2.13)
actionpack (= 3.2.13)
mail (~> 2.5.3)
actionpack (3.2.13)
activemodel (= 3.2.13)
activesupport (= 3.2.13)
builder (~> 3.0.0)
erubis (~> 2.7.0)
journey (~> 1.0.4)
rack (~> 1.4.5)
rack-cache (~> 1.2)
rack-test (~> 0.6.1)
sprockets (~> 2.2.1)
activemodel (3.2.13)
activesupport (= 3.2.13)
builder (~> 3.0.0)
activerecord (3.2.13)
activemodel (= 3.2.13)
activesupport (= 3.2.13)
arel (~> 3.0.2)
tzinfo (~> 0.3.29)
activeresource (3.2.13)
activemodel (= 3.2.13)
activesupport (= 3.2.13)
activesupport (3.2.13)
i18n (= 0.6.1)
multi_json (~> 1.0)
acts-as-taggable-on (2.4.1)
rails (>= 3, < 5)
arel (3.0.2)
builder (3.0.0)
capybara (2.0.3)
mime-types (>= 1.16)
nokogiri (>= 1.3.3)
rack (>= 1.0.0)
rack-test (>= 0.5.4)
selenium-webdriver (~> 2.0)
xpath (~> 1.0.0)
childprocess (0.5.3)
ffi (~> 1.0, >= 1.0.11)
coderay (1.0.9)
coffee-rails (3.2.2)
coffee-script (>= 2.2.0)
railties (~> 3.2.0)
coffee-script (2.2.0)
coffee-script-source
execjs
coffee-script-source (1.7.0)
erubis (2.7.0)
execjs (2.0.2)
fastercsv (1.5.0)
ffi (1.9.3-x86-mingw32)
hike (1.2.3)
i18n (0.6.1)
journey (1.0.4)
jquery-rails (2.0.3)
railties (>= 3.1.0, < 5.0)
thor (~> 0.14)
json (1.8.0)
mail (2.5.4)
mime-types (~> 1.16)
treetop (~> 1.4.8)
metaclass (0.0.4)
mime-types (1.23)
mocha (0.13.3)
metaclass (~> 0.0.1)
multi_json (1.7.6)
mysql2 (0.3.11-x86-mingw32)
net-ldap (0.3.1)
nokogiri (1.5.11-x86-mingw32)
polyglot (0.3.3)
rack (1.4.5)
rack-cache (1.2)
rack (>= 0.4)
rack-openid (1.3.1)
rack (>= 1.1.0)
ruby-openid (>= 2.1.8)
rack-ssl (1.3.3)
rack
rack-test (0.6.2)
rack (>= 1.0)
rails (3.2.13)
actionmailer (= 3.2.13)
actionpack (= 3.2.13)
activerecord (= 3.2.13)
activeresource (= 3.2.13)
activesupport (= 3.2.13)
bundler (~> 1.0)
railties (= 3.2.13)
railties (3.2.13)
actionpack (= 3.2.13)
activesupport (= 3.2.13)
rack-ssl (~> 1.3.2)
rake (>= 0.8.7)
rdoc (~> 3.4)
thor (>= 0.14.6, < 2.0)
rake (10.3.2)
rdoc (3.12.2)
json (~> 1.4)
rmagick (2.13.2)
ruby-openid (2.1.8)
rubyzip (1.1.4)
sass (3.2.14)
sass-rails (3.2.6)
railties (~> 3.2.0)
sass (>= 3.1.10)
tilt (~> 1.3)
selenium-webdriver (2.42.0)
childprocess (>= 0.5.0)
multi_json (~> 1.0)
rubyzip (~> 1.0)
websocket (~> 1.0.4)
shoulda (3.5.0)
shoulda-context (~> 1.0, >= 1.0.1)
shoulda-matchers (>= 1.4.1, < 3.0)
shoulda-context (1.2.1)
shoulda-matchers (2.6.1)
activesupport (>= 3.0.0)
sprockets (2.2.2)
hike (~> 1.2)
multi_json (~> 1.0)
rack (~> 1.0)
tilt (~> 1.1, != 1.3.0)
thor (0.18.1)
tilt (1.4.1)
treetop (1.4.14)
polyglot
polyglot (>= 0.3.1)
tzinfo (0.3.37)
uglifier (2.4.0)
execjs (>= 0.3.0)
json (>= 1.8.0)
websocket (1.0.7)
xpath (1.0.0)
nokogiri (~> 1.3)
PLATFORMS
x86-mingw32
DEPENDENCIES
activerecord-jdbc-adapter (= 1.2.5)
activerecord-jdbcmysql-adapter
acts-as-taggable-on (= 2.4.1)
better_errors!
builder (= 3.0.0)
capybara (~> 2.0.0)
coderay (~> 1.0.6)
coffee-rails (~> 3.2.1)
fastercsv (~> 1.5.0)
i18n (~> 0.6.0)
jquery-rails (~> 2.0.2)
mocha (~> 0.13.3)
mysql2 (= 0.3.11)
net-ldap (~> 0.3.1)
nokogiri (< 1.6.0)
rack-mini-profiler!
rack-openid
rails (= 3.2.13)
rmagick (>= 2.0.0)
ruby-openid (~> 2.1.4)
sass-rails (~> 3.2.3)
seems_rateable!
shoulda (> 3.3.2)
therubyracer
uglifier (>= 1.0.3)

@ -0,0 +1,40 @@
# More info at https://github.com/guard/guard#readme
# guard 'rails' do
# watch('Gemfile.lock')
# watch(%r{^(config|lib)/.*})
# end
#
guard 'spork', :test_unit => true, :test_unit_env => {'RAILS_ENV' => 'test'}, :wait => 60 do
watch(%r{app/models/.+\.rb})
watch('config/application.rb')
watch('config/environment.rb')
watch('config/environments/test.rb')
watch(%r{^config/initializers/.+\.rb$})
watch('Gemfile.lock')
watch('spec/spec_helper.rb') { :rspec }
watch('test/test_helper.rb') { :test_unit }
watch(%r{features/support/}) { :cucumber }
end
guard :test, :drb => true, :all_after_pass => false, :all_on_start => false do
watch(%r{^test/.+_test\.rb$})
watch('test/test_helper.rb') { 'test' }
# Non-rails
watch(%r{^lib/(.+)\.rb$}) { |m| "test/#{m[1]}_test.rb" }
# Rails 4
# watch(%r{^app/(.+)\.rb}) { |m| "test/#{m[1]}_test.rb" }
# watch(%r{^app/controllers/application_controller\.rb}) { 'test/controllers' }
# watch(%r{^app/controllers/(.+)_controller\.rb}) { |m| "test/integration/#{m[1]}_test.rb" }
# watch(%r{^app/views/(.+)_mailer/.+}) { |m| "test/mailers/#{m[1]}_mailer_test.rb" }
# watch(%r{^lib/(.+)\.rb}) { |m| "test/lib/#{m[1]}_test.rb" }
# Rails < 4
watch(%r{^app/models/(.+)\.rb$}) { |m| "test/unit/#{m[1]}_test.rb" }
watch(%r{^app/controllers/(.+)\.rb$}) { |m| "test/functional/#{m[1]}_test.rb" }
watch(%r{^app/views/(.+)/.+\.erb$}) { |m| "test/functional/#{m[1]}_controller_test.rb" }
watch(%r{^app/views/.+$}) { 'test/integration' }
watch('app/controllers/application_controller.rb') { ['test/functional', 'test/integration'] }
end

@ -1,53 +1,99 @@
patch:
用户姓名的部分根据issues#655。
为了修改方便
alias
方法 之前显示 调整之后
name firstname+lastname login
nickname xxx login
realname xxx firstname+lastname
User model经过修改已经完全集成了user_extensions的功能
例如
user.gender=1
user.save
user_extensions字段会自动保存
不必要每次user.user_extensions.xxx以及判断是否为空
================================================================================
app/models/setting.rb :165
# fixed domain url in development. tantantan's bug
if Rails.env.development?
methods.map do |m|
define_singleton_method m do; nil; end if m.to_s =~ /([a-zA-Z]+_domain)$/
end
end
程序部分链接中制定了subdomain参数使链接在二级域名中来回跳转。
为了开发方便使之功能在development模式下失效。
# => nyan
================================================================================
app/controller/projects_controller.rb ===> projects#fake
fake filter: 修改了传到页面中的Count后缀的数量
改为正确的数量删掉fake过滤器即可
================================================================================
#导航栏匹配域名显示和改变
app\helper\application_helper.rb
# rewrite navigation
app\views\layouts\_base_header.html.erb
# reset navigation by domain name and url through regular match
================================================================================
#首页根据域名匹配进入不同的页面
app\controller\welcome_controller.rb
def entry_select_user
if request.original_url.match(/user\.trustie\.net/)
redirect_to(:controller => "users", :action => "index")
return 0
end
end
================================================================================
================================================================================
0606新坑
user_scores表结构有问题需要运行
bundle exec rake db:migrate:down VERSION=20140410021724
bundle exec rake db:migrate:up VERSION=20140410021724
===================================[2014-04-09]=================================
kw: 域名, 二级域名, subdomain, forge, course, contest
域名跳转forge/course/contest这几个设置在settings.yml中
但是跳转在development模式下会导致无法开发
app/models/setting.rb :165
# fixed domain url in development. tantantan's bug
if Rails.env.development?
methods.map do |m|
define_singleton_method m do; nil; end if m.to_s =~ /([a-zA-Z]+_domain)$/
end
end
程序部分链接中制定了subdomain参数使链接在二级域名中来回跳转。
为了开发方便使之功能在development模式下失效。
===================================[2014-04-09]=================================
kw: 菜单, 导航栏, layout
网页上方的导航条没有用Redmine::MenuManager
MenuManager的样式无法定制菜单显示条件if中的proc执行行为没有了解
#导航栏匹配域名显示和改变
app\helper\application_helper.rb
render_dynamic_nav 方法中利用变量可以设置在layout中具体显示哪些条目
app\views\layouts\_base_header.html.erb
需要显示的条目由具体的实例变量设置在各个layout中
===================================[2014-04-09]=================================
kw: home_path, 首页, 跳转, 二级域名, welcome
#首页根据域名匹配进入不同的页面
app\controller\welcome_controller.rb
#entry_select 放射设置二级域名所显示的首页
===================================[2014-06-06]=================================
kw: user_scores
user_scores表结构有问题需要运行
bundle exec rake db:migrate:down VERSION=20140410021724
bundle exec rake db:migrate:up VERSION=20140410021724
===================================[2014-07-08]=================================
kw: CKEditor, 富文本, 编辑器
CKEditor插件加载方法
1.把插件文件夹拷入plugins文件夹确保文件夹名为redmine_ckeditor
2.运行 bundle install --without development test
3.运行 rake redmine:plugins:migrate RAILS_ENV=production
4.启动服务器
5.配置CKEditor插件(Administration > Plugins > Configure)
6.把文本格式 (Administration > Settings > General > Text formatting)改为CKEditor
注意一定要先配置CKEditor插件再见文本格式更改不然数据库不会生成对应记录会报错。。
===================================[2014-07-19]=================================
kw: 首页, 定制, forge, course, contest, 排序
若遇到首页定制报错问题请尝试如下操作
如果运行迁移文件有报错与sort_type相关
先运行 bundle exec rake db:migrate:down version=20140716021202 bundle exec rake db:migrate:up version=20140716021202
在按如下步骤执行,未报与之相关的则直接按如下步骤执行
1.运行 bundle exec rake db:migrate:down version=20140719080032
2.运行 bundle exec rake db:migrate:up version=20140719080032
===================================[2014-07-30]=================================
kw: 首页, 定制, forge, course, contest, 排序image_width
undefined image_width 问题
bundle exec rake db:migrate:down version=20140725062302
bundle exec rake db:migrate:up version=20140725062302
=================================[2014-07-19]=====================================
kw: Mysql2::Error,存储过程,CALL sp_project_status_cursor();
bundle exec rake db:migrate:down version=20130828004955
bundle exec rake db:migrate:up version=20130828004955
=================================[2014-08-13]====================================
kw:配置支持的图片格式
默认支持如下格式:"bmp,jpeg,jpg,png,gif"
可在configuration.yml中修改格式pic_types: "bmp,jpeg,jpg,png,gif"(注意pic_types若前面有#号需去掉)
配置完成后重启服务
=================================[2014-08-16]====================================
kw:数据迁移project_scores表已存在
bundle exec rake db:migrate:down VERSION=20140811022947
bundle exec rake db:migrate:up VERSION=20140811022947
bundle exec rake db:migrate
bundle exec rake project_score:calculate
=================================[2014-10-17]====================================
kw:数据迁移web_footer_oranizers表已存在
bundle exec rake db:migrate:down VERSION=20141013014908
bundle exec rake db:migrate:up VERSION=20141013014908
bundle exec rake db:migrate
kw:数据迁移web_footer_companies表已存在
bundle exec rake db:migrate:down VERSION=20141013023400
bundle exec rake db:migrate:up VERSION=20141013023400
bundle exec rake db:migrate

@ -1,375 +1,390 @@
# Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class AccountController < ApplicationController
helper :custom_fields
include CustomFieldsHelper
# prevents login action to be filtered by check_if_login_required application scope filter
skip_before_filter :check_if_login_required
# Login request and validation
def login
if request.get?
if User.current.logged?
redirect_to home_url
end
else
authenticate_user
end
rescue AuthSourceException => e
logger.error "An error occured when authenticating #{params[:username]}: #{e.message}"
render_error :message => e.message
end
# Log out current user and redirect to welcome page
def logout
if User.current.anonymous?
redirect_to home_url
elsif request.post?
logout_user
redirect_to home_url
end
# display the logout form
end
# Lets user choose a new password
def lost_password
(redirect_to(home_url); return) unless Setting.lost_password?
if params[:token]
@token = Token.find_token("recovery", params[:token].to_s)
if @token.nil? || @token.expired?
redirect_to home_url
return
end
@user = @token.user
unless @user && @user.active?
redirect_to home_url
return
end
if request.post?
@user.password, @user.password_confirmation = params[:new_password], params[:new_password_confirmation]
if @user.save
@token.destroy
flash[:notice] = l(:notice_account_password_updated)
redirect_to signin_path
return
end
end
render :template => "account/password_recovery"
return
else
if request.post?
user = User.find_by_mail(params[:mail].to_s)
# user not found or not active
unless user && user.active?
flash.now[:error] = l(:notice_account_unknown_email)
return
end
# user cannot change its password
unless user.change_password_allowed?
flash.now[:error] = l(:notice_can_t_change_password)
return
end
# create a new token for password recovery
token = Token.new(:user => user, :action => "recovery")
if token.save
Thread.new do
Mailer.lost_password(token).deliver
end
flash[:notice] = l(:notice_account_lost_email_sent)
redirect_to signin_path
return
end
end
end
end
# User self-registration
def register
# @root_path="/home/pdl/redmine-2.3.2-0/apache2/"
#
(redirect_to(home_url); return) unless Setting.self_registration? || session[:auth_source_registration]
if request.get?
session[:auth_source_registration] = nil
@user = User.new(:language => current_language.to_s)
else
user_params = params[:user] || {}
@user = User.new
@user.safe_attributes = user_params
if params[:identity] == "2" # 2 企业
@user.firstname = params[:enterprise_name]
@user.lastname = l(:field_enterprise)
end
@user.admin = false
@user.register
if session[:auth_source_registration]
@user.activate
@user.login = session[:auth_source_registration][:login]
@user.auth_source_id = session[:auth_source_registration][:auth_source_id]
if @user.save
session[:auth_source_registration] = nil
self.logged_user = @user
flash[:notice] = l(:notice_account_activated)
redirect_to my_account_path
end
else
@user.login = params[:user][:login]
unless user_params[:identity_url].present? && user_params[:password].blank? && user_params[:password_confirmation].blank?
@user.password, @user.password_confirmation = user_params[:password], user_params[:password_confirmation]
end
case Setting.self_registration
when '1'
register_by_email_activation(@user)
when '3'
register_automatically(@user)
else
register_manually_by_administrator(@user)
end
#added by bai
if @user.id != nil
ue = @user.user_extensions ||= UserExtensions.new
#ue = UserExtensions.create(:identity => params[:identity].to_i,:technical_title => params[:technical_title], :gender => params[:gender].to_i, :user_id => @user.id, :student_id => )
ue.identity = params[:identity].to_i
ue.technical_title = params[:technical_title]
ue.gender = params[:gender].to_i
ue.user_id = @user.id
ue.student_id = params[:no]
ue.location = params[:province] if params[:province] != nil
ue.location_city = params[:city] if params[:city] != nil
ue.save
end
end
end
end
# Token based account activation
def activate
(redirect_to(home_url); return) unless Setting.self_registration? && params[:token].present?
token = Token.find_token('register', params[:token].to_s)
(redirect_to(home_url); return) unless token and !token.expired?
user = token.user
(redirect_to(home_url); return) unless user.registered?
user.activate
if user.save
token.destroy
flash[:notice] = l(:notice_account_activated)
end
redirect_to signin_path
end
def valid_ajax
req = Hash.new(false)
req[:message] = ''
valid_attr = params[:valid]
valid_value = params[:value]
faker = User.new
if valid_attr.eql?('login')
faker.login = valid_value
faker.valid?
req[:valid] = faker.errors[:login].blank?
req[:message] = faker.errors[:login]
end
if valid_attr.eql?('mail')
faker.mail = valid_value
faker.valid?
req[:valid] = faker.errors[:mail].blank?
req[:message] = faker.errors[:mail]
end
req[:message] = l(:modal_valid_passing) if req[:message].blank?
render :json => req
end
private
def authenticate_user
if Setting.openid? && using_open_id?
open_id_authenticate(params[:openid_url])
else
password_authentication
end
end
def password_authentication
user = User.try_to_login(params[:username], params[:password])
if user.nil?
invalid_credentials
elsif user.status == 2
invalid_credentials_new
elsif user.new_record?
onthefly_creation_failed(user, {:login => user.login, :auth_source_id => user.auth_source_id })
else
# Valid user
successful_authentication(user)
end
end
def open_id_authenticate(openid_url)
back_url = signin_url(:autologin => params[:autologin])
authenticate_with_open_id(openid_url, :required => [:nickname, :fullname, :email], :return_to => back_url, :method => :post) do |result, identity_url, registration|
if result.successful?
user = User.find_or_initialize_by_identity_url(identity_url)
if user.new_record?
# Self-registration off
(redirect_to(home_url); return) unless Setting.self_registration?
# Create on the fly
user.login = registration['nickname'] unless registration['nickname'].nil?
user.mail = registration['email'] unless registration['email'].nil?
user.firstname, user.lastname = registration['fullname'].split(' ') unless registration['fullname'].nil?
user.random_password
user.register
case Setting.self_registration
when '1'
register_by_email_activation(user) do
onthefly_creation_failed(user)
end
when '3'
register_automatically(user) do
onthefly_creation_failed(user)
end
else
register_manually_by_administrator(user) do
onthefly_creation_failed(user)
end
end
else
# Existing record
if user.active?
successful_authentication(user)
else
account_pending
end
end
end
end
end
def successful_authentication(user)
logger.info "Successful authentication for '#{user.login}' from #{request.remote_ip} at #{Time.now.utc}"
# Valid user
self.logged_user = user
# generate a key and set cookie if autologin
if params[:autologin] && Setting.autologin?
set_autologin_cookie(user)
end
call_hook(:controller_account_success_authentication_after, {:user => user })
code = /\d*/
#根据home_url生产正则表达式
eval("code = " + "/^" + home_url.gsub(/\//,"\\\/") + "\\\/*(welcome)?\\\/*(\\\/index\\\/*.*)?\$/")
if code=~params[:back_url]
redirect_to user_activities_path(user)
else
#by young
#redirect_back_or_default my_page_path
redirect_back_or_default User.current
#redirect_to User.current
end
end
def set_autologin_cookie(user)
token = Token.create(:user => user, :action => 'autologin')
cookie_options = {
:value => token.value,
:expires => 1.year.from_now,
:path => (Redmine::Configuration['autologin_cookie_path'] || '/'),
:secure => (Redmine::Configuration['autologin_cookie_secure'] ? true : false),
:httponly => true
}
cookies[autologin_cookie_name] = cookie_options
end
# Onthefly creation failed, display the registration form to fill/fix attributes
def onthefly_creation_failed(user, auth_source_options = { })
@user = user
session[:auth_source_registration] = auth_source_options unless auth_source_options.empty?
render :action => 'register'
end
def invalid_credentials
logger.warn "Failed login for '#{params[:username]}' from #{request.remote_ip} at #{Time.now.utc}"
flash.now[:error] = l(:notice_account_invalid_creditentials)
end
def invalid_credentials_new
logger.warn "Failed login for '#{params[:username]}' from #{request.remote_ip} at #{Time.now.utc}"
flash.now[:error] = l(:notice_account_invalid_creditentials_new)
end
# Register a user for email activation.
#
# Pass a block for behavior when a user fails to save
def register_by_email_activation(user, &block)
token = Token.new(:user => user, :action => "register")
if user.save and token.save
UserStatus.create(:user_id => user.id, :changsets_count => 0, :watchers_count => 0)
Mailer.register(token).deliver
flash[:notice] = l(:notice_account_register_done)
redirect_to signin_path
else
yield if block_given?
end
end
# Automatically register a user
#
# Pass a block for behavior when a user fails to save
def register_automatically(user, &block)
# Automatic activation
user.activate
user.last_login_on = Time.now
if user.save
UserStatus.create(:user_id => user.id, :changsets_count => 0, :watchers_count => 0)
self.logged_user = user
flash[:notice] = l(:notice_account_activated)
redirect_to my_account_path
else
yield if block_given?
end
end
# Manual activation by the administrator
#
# Pass a block for behavior when a user fails to save
def register_manually_by_administrator(user, &block)
if user.save
UserStatus.create(:user_id => user.id ,:changsets_count => 0, :watchers_count => 0)
# Sends an email to the administrators
Mailer.account_activation_request(user).deliver
account_pending
else
yield if block_given?
end
end
def account_pending
flash[:notice] = l(:notice_account_pending)
redirect_to signin_path
end
end
# Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class AccountController < ApplicationController
helper :custom_fields
include CustomFieldsHelper
# prevents login action to be filtered by check_if_login_required application scope filter
skip_before_filter :check_if_login_required
# Login request and validation
def login
if request.get?
if User.current.logged?
redirect_to home_url
end
else
authenticate_user
end
rescue AuthSourceException => e
logger.error "An error occured when authenticating #{params[:username]}: #{e.message}"
render_error :message => e.message
end
# Log out current user and redirect to welcome page
def logout
if User.current.anonymous?
redirect_to home_url
elsif request.post?
logout_user
redirect_to home_url
end
# display the logout form
end
# Lets user choose a new password
def lost_password
(redirect_to(home_url); return) unless Setting.lost_password?
if params[:token]
@token = Token.find_token("recovery", params[:token].to_s)
if @token.nil? || @token.expired?
redirect_to home_url
return
end
@user = @token.user
unless @user && @user.active?
redirect_to home_url
return
end
if request.post?
@user.password, @user.password_confirmation = params[:new_password], params[:new_password_confirmation]
if @user.save
@token.destroy
flash[:notice] = l(:notice_account_password_updated)
redirect_to signin_url
return
end
end
render :template => "account/password_recovery"
return
else
if request.post?
user = User.find_by_mail(params[:mail].to_s)
# user not found or not active
unless user && user.active?
flash.now[:error] = l(:notice_account_unknown_email)
return
end
# user cannot change its password
unless user.change_password_allowed?
flash.now[:error] = l(:notice_can_t_change_password)
return
end
# create a new token for password recovery
token = Token.new(:user => user, :action => "recovery")
if token.save
Thread.new do
Mailer.lost_password(token).deliver
end
flash[:notice] = l(:notice_account_lost_email_sent)
redirect_to signin_url
return
end
end
end
end
# User self-registration
def register
(redirect_to(home_url); return) unless Setting.self_registration? || session[:auth_source_registration]
if request.get?
session[:auth_source_registration] = nil
@user = User.new(:language => current_language.to_s)
else
user_params = params[:user] || {}
if session[:auth_source_registration]
@user.activate
@user.login = session[:auth_source_registration][:login]
@user.auth_source_id = session[:auth_source_registration][:auth_source_id]
if @user.save
session[:auth_source_registration] = nil
self.logged_user = @user
flash[:notice] = l(:notice_account_activated)
redirect_to my_account_path
end
else
create_and_save_user params[:user][:login],user_params[:password],user_params[:mail],user_params[:password_confirmation],true
end
end
if params[:identity] == "2"
@user.firstname = firstname_code
@user.lastname = lastname_code
end
end
#should_confirmation_password是否验证密码
def create_and_save_user login,password,email,password_confirmation,should_confirmation_password
@user = User.new
@user.admin = false
@user.register
@user.login = login
@user.mail = email
if should_confirmation_password && !password.blank? && !password_confirmation.blank?
@user.password,@user.password_confirmation = password,password_confirmation
elsif !should_confirmation_password && !password.blank?
@user.password = password
else
@user.password = ""
end
case Setting.self_registration
when '1'
register_by_email_activation(@user)
when '3'
register_automatically(@user)
else
register_manually_by_administrator(@user)
end
if @user.id != nil
ue = @user.user_extensions ||= UserExtensions.new
ue.user_id = @user.id
ue.save
end
@user
end
# Token based account activation
def activate
(redirect_to(home_url); return) unless Setting.self_registration? && params[:token].present?
token = Token.find_token('register', params[:token].to_s)
(redirect_to(home_url); return) unless token and !token.expired?
user = token.user
(redirect_to(home_url); return) unless user.registered?
user.activate
if user.save
token.destroy
flash[:notice] = l(:notice_account_activated)
end
redirect_to signin_url
end
def valid_ajax
req = Hash.new(false)
req[:message] = ''
valid_attr = params[:valid]
valid_value = params[:value]
faker = User.new
if valid_attr.eql?('login')
faker.login = valid_value
faker.valid?
req[:valid] = faker.errors[:login].blank?
req[:message] = faker.errors[:login]
end
if valid_attr.eql?('mail')
faker.mail = valid_value
faker.valid?
req[:valid] = faker.errors[:mail].blank?
req[:message] = faker.errors[:mail]
end
req[:message] = l(:modal_valid_passing) if req[:message].blank?
render :json => req
end
def email_valid
end
def resendmail
user = User.find(params[:user]) if params[:user]
token = Token.new(:user => user, :action => "register")
if token.save
Mailer.register(token).deliver
else
yield if block_given?
end
end
private
def authenticate_user
if Setting.openid? && using_open_id?
open_id_authenticate(params[:openid_url])
else
password_authentication
end
end
def password_authentication
user, last_login_on = User.try_to_login(params[:username], params[:password])
if user.nil?
invalid_credentials
elsif user.status == 2
invalid_credentials_new
elsif user.new_record?
onthefly_creation_failed(user, {:login => user.login, :auth_source_id => user.auth_source_id })
else
# Valid user
successful_authentication(user, last_login_on)
end
end
def open_id_authenticate(openid_url)
back_url = signin_url(:autologin => params[:autologin])
authenticate_with_open_id(openid_url, :required => [:nickname, :fullname, :email], :return_to => back_url, :method => :post) do |result, identity_url, registration|
if result.successful?
user = User.find_or_initialize_by_identity_url(identity_url)
if user.new_record?
# Self-registration off
(redirect_to(home_url); return) unless Setting.self_registration?
# Create on the fly
user.login = registration['nickname'] unless registration['nickname'].nil?
user.mail = registration['email'] unless registration['email'].nil?
user.firstname, user.lastname = registration['fullname'].split(' ') unless registration['fullname'].nil?
user.random_password
user.register
case Setting.self_registration
when '1'
register_by_email_activation(user) do
onthefly_creation_failed(user)
end
when '3'
register_automatically(user) do
onthefly_creation_failed(user)
end
else
register_manually_by_administrator(user) do
onthefly_creation_failed(user)
end
end
else
# Existing record
if user.active?
successful_authentication(user)
else
account_pending
end
end
end
end
end
def successful_authentication(user, last_login_on)
logger.info "Successful authentication for '#{user.login}' from #{request.remote_ip} at #{Time.now.utc}"
# Valid user
self.logged_user = user
# generate a key and set cookie if autologin
if params[:autologin] && Setting.autologin?
set_autologin_cookie(user)
end
call_hook(:controller_account_success_authentication_after, {:user => user })
code = /\d*/
#根据home_url生产正则表达式
eval("code = " + "/^" + home_url.gsub(/\//,"\\\/") + "\\\/*(welcome)?\\\/*(\\\/index\\\/*.*)?\$/")
if code=~params[:back_url] && last_login_on != ''
redirect_to user_activities_path(user)
else
if last_login_on == ''
redirect_to my_account_url
else
#by young
#redirect_back_or_default my_page_path
redirect_back_or_default User.current
#redirect_to my_account_url
#redirect_to User.current
end
end
end
def set_autologin_cookie(user)
token = Token.create(:user => user, :action => 'autologin')
cookie_options = {
:value => token.value,
:expires => 1.year.from_now,
:path => (Redmine::Configuration['autologin_cookie_path'] || '/'),
:secure => (Redmine::Configuration['autologin_cookie_secure'] ? true : false),
:httponly => true
}
cookies[autologin_cookie_name] = cookie_options
end
# Onthefly creation failed, display the registration form to fill/fix attributes
def onthefly_creation_failed(user, auth_source_options = { })
@user = user
session[:auth_source_registration] = auth_source_options unless auth_source_options.empty?
render :action => 'register'
end
def invalid_credentials
logger.warn "Failed login for '#{params[:username]}' from #{request.remote_ip} at #{Time.now.utc}"
flash.now[:error] = l(:notice_account_invalid_creditentials)
end
def invalid_credentials_new
logger.warn "Failed login for '#{params[:username]}' from #{request.remote_ip} at #{Time.now.utc}"
flash.now[:error] = l(:notice_account_invalid_creditentials_new)
end
# Register a user for email activation.
#
# Pass a block for behavior when a user fails to save
def register_by_email_activation(user, &block)
token = Token.new(:user => user, :action => "register")
if user.save and token.save
UserStatus.create(:user_id => user.id, :changsets_count => 0, :watchers_count => 0)
Mailer.register(token).deliver
flash[:notice] = l(:notice_account_register_done)
render action: 'email_valid', locals: {:mail => user.mail}
else
yield if block_given?
end
end
# Automatically register a user
#
# Pass a block for behavior when a user fails to save
def register_automatically(user, &block)
# Automatic activation
user.activate
user.last_login_on = Time.now
if user.save
UserStatus.create(:user_id => user.id, :changsets_count => 0, :watchers_count => 0)
self.logged_user = user
flash[:notice] = l(:notice_account_activated)
redirect_to my_account_url
else
yield if block_given?
end
end
# Manual activation by the administrator
#
# Pass a block for behavior when a user fails to save
def register_manually_by_administrator(user, &block)
if user.save
UserStatus.create(:user_id => user.id ,:changsets_count => 0, :watchers_count => 0)
# Sends an email to the administrators
Mailer.account_activation_request(user).deliver
account_pending
else
yield if block_given?
end
end
def account_pending
flash[:notice] = l(:notice_account_pending)
redirect_to signin_url
end
end

@ -20,7 +20,7 @@ class ActivitiesController < ApplicationController
before_filter :find_optional_project, :index
accept_rss_auth :index
helper :Watchers
helper :project_score
def index
@days = Setting.activity_days_default.to_i

@ -1,237 +1,286 @@
# Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class AdminController < ApplicationController
layout 'admin'
menu_item :projects, :only => :projects
menu_item :plugins, :only => :plugins
menu_item :info, :only => :info
before_filter :require_admin
helper :sort
helper :Users
include SortHelper
def index
@no_configuration_data = Redmine::DefaultData::Loader::no_data?
end
def projects
@status = params[:status] || 1
scope = Project.status(@status).order('lft')
scope = scope.like(params[:name]) if params[:name].present?
@projects = scope.all
render :action => "projects", :layout => false if request.xhr?
end
def users
@project_type = params[:project_type]
role = params[:role]
sort_init 'login', 'asc'
sort_update %w(login firstname lastname mail admin created_on last_login_on)
case params[:format]
when 'xml', 'json'
@offset, @limit = api_offset_and_limit({:limit => 15})
else
@limit = 15#per_page_option
end
@status = params[:status] || 1
has = {
"show_changesets" => true
}
# @count = Redmine::Activity::Fetcher.new(User.current, :author => @user).scope_select {|t| !has["show_#{t}"].nil?}.events(nil, nil).count
scope = UserStatus.visible
case role
when 'teacher'
scope = UserStatus.teacher
when 'student'
scope = UserStatus.student
else
end
scope = scope.in_group(params[:group_id]) if params[:group_id].present?
# scope.each do |user|
# UserStatus.create(:changesets_count => user.changesets.count, :watchers_count => user.watcher_users.count, :user_id => user.id)
# end
@user_count = scope.count
@user_pages = Paginator.new @user_count, @limit, params['page']
#@offset ||= @user_pages.offset
#@users = scope.order(sort_clause).limit(@limit).offset(@offset).all
@user_base_tag = params[:id] ? 'base_users':'base'
if params[:user_sort_type].present?
case params[:user_sort_type]
when '0'
@offset ||= @user_pages.reverse_offset
unless @offset == 0
@users_statuses = scope.offset(@offset).limit(@limit).all.reverse
else
limit = @user_count % @limit
if limit == 0
limit = @limit
end
@users_statuses = scope.offset(@offset).limit(limit).all.reverse
end
@s_type = 0
# @projects = @projects.sort {|x,y| y.created_on <=> x.created_on }
# @projects = @projects[@offset, @limit]
when '1'
@offset ||= @user_pages.reverse_offset
unless @offset == 0
@users_statuses = scope.reorder('grade').offset(@offset).limit(@limit).all.reverse
else
limit = @user_count % @limit
if limit == 0
limit = @limit
end
@users_statuses = scope.reorder('grade').offset(@offset).limit(limit).all.reverse
end
@s_type = 1
#sort {|x,y| y.user_status.changesets_count <=> x.user_status.changesets_count}
#@users = @users[@offset, @limit]
when '2'
@offset ||= @user_pages.reverse_offset
unless @offset == 0
@users_statuses = scope.reorder('watchers_count').offset(@offset).limit(@limit).all.reverse
else
limit = @user_count % @limit
if limit == 0
limit = @limit
end
@users_statuses = scope.reorder('watchers_count').offset(@offset).limit(limit).all.reverse
end
@s_type = 2
#@users = @users[@offset, @limit]
end
else
@offset ||= @user_pages.reverse_offset
unless @offset == 0
@users_statuses = scope.reorder('grade').offset(@offset).limit(@limit).all.reverse
else
limit = @user_count % @limit
if limit == 0
limit = @limit
end
@users_statuses = scope.reorder('grade').offset(@offset).limit(limit).all.reverse
end
@s_type = 1
# @projects = @projects.sort {|x,y| y.created_on <=> x.created_on }
# @projects = @projects[@offset, @limit]
end
@users = []
@users_statuses.each do |obj|
@users << User.find_by_id("#{obj.user_id}")
end
respond_to do |format|
format.html {
@groups = Group.all.sort
}
format.api
end
end
def plugins
@plugins = Redmine::Plugin.all
end
# Loads the default configuration
# (roles, trackers, statuses, workflow, enumerations)
def default_configuration
if request.post?
begin
Redmine::DefaultData::Loader::load(params[:lang])
flash[:notice] = l(:notice_default_data_loaded)
rescue Exception => e
flash[:error] = l(:error_can_t_load_default_data, e.message)
end
end
redirect_to admin_path
end
def test_email
raise_delivery_errors = ActionMailer::Base.raise_delivery_errors
# Force ActionMailer to raise delivery errors so we can catch it
ActionMailer::Base.raise_delivery_errors = true
begin
@test = Mailer.test_email(User.current).deliver
flash[:notice] = l(:notice_email_sent, User.current.mail)
rescue Exception => e
flash[:error] = l(:notice_email_error, e.message)
end
ActionMailer::Base.raise_delivery_errors = raise_delivery_errors
redirect_to settings_path(:tab => 'notifications')
end
def info
@db_adapter_name = ActiveRecord::Base.connection.adapter_name
@checklist = [
[:text_default_administrator_account_changed, User.default_admin_account_changed?],
[:text_file_repository_writable, File.writable?(Attachment.storage_path)],
[:text_plugin_assets_writable, File.writable?(Redmine::Plugin.public_directory)],
[:text_rmagick_available, Object.const_defined?(:Magick)]
]
end
#管理功能用户列表的搜索
def search
sort_init 'login', 'asc'
sort_update %w(login firstname lastname mail admin created_on last_login_on)
case params[:format]
when 'xml', 'json'
@offset, @limit = api_offset_and_limit({:limit => 15})
else
@limit = 15#per_page_option
end
@status = params[:status] || 1
has = {
"show_changesets" => true
}
scope = User.logged.status(@status)
scope = scope.like(params[:name]) if params[:name].present?
@user_count = scope.count
@user_pages = Paginator.new @user_count, @limit, params['page']
@user_base_tag = params[:id] ? 'base_users':'base'
@offset ||= @user_pages.reverse_offset
unless @offset == 0
@users = scope.offset(@offset).limit(@limit).all.reverse
else
limit = @user_count % @limit
if limit == 0
limit = @limit
end
@users = scope.offset(@offset).limit(limit).all.reverse
end
respond_to do |format|
format.html {
@groups = Group.all.sort
}
format.api
end
end
end
# Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class AdminController < ApplicationController
layout 'admin'
menu_item :projects, :only => :projects
menu_item :plugins, :only => :plugins
menu_item :info, :only => :info
before_filter :require_admin
helper :sort
helper :Users
helper :Settings
include SortHelper
def index
@no_configuration_data = Redmine::DefaultData::Loader::no_data?
end
def projects
@status = params[:status] || 1
scope = Project.status(@status).order('lft')
scope = scope.like(params[:name]) if params[:name].present?
@projects = scope.where(project_type: Project::ProjectType_project).all
render :action => "projects", :layout => false if request.xhr?
end
def users
sort_init 'login', 'asc'
sort_update %w(login firstname lastname mail admin created_on last_login_on)
case params[:format]
when 'xml', 'json'
@offset, @limit = api_offset_and_limit({:limit => 15})
else
@limit = 15#per_page_option
end
@status = params[:status] || 1
scope = User.logged.status(@status)
scope = User.like(params[:name]) if params[:name].present?
scope = scope.in_group(params[:group_id]) if params[:group_id].present?
@user_count = scope.count
@user_pages = Paginator.new @user_count, @limit, params['page']
@offset ||= @user_pages.offset
@users = scope.order(sort_clause).limit(@limit).offset(@offset).all
respond_to do |format|
format.html {
@groups = Group.all.sort
}
format.api
end
end
def plugins
@plugins = Redmine::Plugin.all
end
# Loads the default configuration
# (roles, trackers, statuses, workflow, enumerations)
def default_configuration
if request.post?
begin
Redmine::DefaultData::Loader::load(params[:lang])
flash[:notice] = l(:notice_default_data_loaded)
rescue Exception => e
flash[:error] = l(:error_can_t_load_default_data, e.message)
end
end
redirect_to admin_url
end
def test_email
raise_delivery_errors = ActionMailer::Base.raise_delivery_errors
# Force ActionMailer to raise delivery errors so we can catch it
ActionMailer::Base.raise_delivery_errors = true
begin
@test = Mailer.test_email(User.current).deliver
flash[:notice] = l(:notice_email_sent, User.current.mail)
rescue Exception => e
flash[:error] = l(:notice_email_error, e.message)
end
ActionMailer::Base.raise_delivery_errors = raise_delivery_errors
redirect_to settings_url(:tab => 'notifications')
end
def info
@db_adapter_name = ActiveRecord::Base.connection.adapter_name
@checklist = [
[:text_default_administrator_account_changed, User.default_admin_account_changed?],
[:text_file_repository_writable, File.writable?(Attachment.storage_path)],
[:text_plugin_assets_writable, File.writable?(Redmine::Plugin.public_directory)],
[:text_rmagick_available, Object.const_defined?(:Magick)]
]
end
#管理功能用户列表的搜索
def search
sort_init 'login', 'asc'
sort_update %w(login firstname lastname mail admin created_on last_login_on)
case params[:format]
when 'xml', 'json'
@offset, @limit = api_offset_and_limit({:limit => 15})
else
@limit = 15#per_page_option
end
@status = params[:status] || 1
scope = User.logged.status(@status)
scope = scope.like(params[:name],params[:search_by][:id]) if params[:name].present?
@user_count = scope.count
@user_pages = Paginator.new @user_count, @limit, params['page']
@user_base_tag = params[:id] ? 'base_users':'base'
@users = scope.offset(@user_pages.offset).limit(@user_pages.per_page)
respond_to do |format|
format.html {
@groups = Group.all.sort
}
format.api
end
end
#首页定制
def first_page_made
if request.get?
@first_page = FirstPage.find_by_page_type('project')
elsif request.post?
@first_page = FirstPage.find_by_page_type('project')
@first_page.web_title = params[:web_title]
@first_page.description = params[:first_page][:description]
#@first_page.title = params[:title]
@first_page.image_width = params[:image_width]
@first_page.image_height = params[:image_height]
@first_page.sort_type = params[:sort_type]
@first_page.show_course = params[:show_course]
@first_page.show_contest = params[:show_contest]
if @first_page.save
respond_to do |format|
flash[:notice] = l(:notice_successful_update)
format.html {
redirect_to first_page_made_url
}
format.api { render_api_ok }
#format.json { render json: @first_page, status: :created, location: @first_page }
end
else
respond_to do |format|
flash.now[:error] = "#{l :label_first_page_create_fail}: #{@first_page.errors.full_messages[0]}"
format.html {
render :action => 'first_page_made'
}
format.api { render_validation_errors(@first_page) }
#format.json { render json: @first_page.errors, status: :unprocessable_entity }
end
end
end
end
def course_page_made
if request.get?
@course_page = FirstPage.find_by_page_type('course')
@first_page = FirstPage.find_by_page_type('project')
elsif request.post?
@first_page = FirstPage.find_by_page_type('project')
@course_page = FirstPage.find_by_page_type('course')
@first_page.web_title = params[:web_title]
@course_page.web_title = params[:web_title]
@course_page.title = params[:course_title]
@course_page.image_width = params[:image_width]
@course_page.image_height = params[:image_height]
@course_page.description = params[:course_description]
if @first_page.save && @course_page.save
respond_to do |format|
format.html {
flash[:notice] = l(:notice_successful_update)
redirect_to course_page_made_url
}
format.api { render_api_ok }
end
else
respond_to do |format|
flash.now[:error] = "#{l :label_first_page_create_fail}: #{@first_page.errors.full_messages[0]}\n\t#{@course_page.errors.full_messages[0]}"
#flash.now[:error] = "#{l :label_first_page_create_fail}: #{@course_page.errors.full_messages[0]}"
format.html {
render :action => 'course_page_made'
}
format.api { render_validation_errors(@first_page) }
format.api { render_validation_errors(@course_page) }
end
end
end
end
def contest_page_made
if request.get?
@contest_page = FirstPage.find_by_page_type('contest')
@first_page = FirstPage.find_by_page_type('project')
elsif request.post?
@first_page = FirstPage.find_by_page_type('project')
@contest_page = FirstPage.find_by_page_type('contest')
@first_page.web_title = params[:web_title]
@contest_page.web_title = params[:web_title]
@contest_page.title = params[:contest_title]
@contest_page.image_width = params[:image_width]
@contest_page.image_height = params[:image_height]
@contest_page.description = params[:contest_description]
if @first_page.save && @contest_page.save
respond_to do |format|
format.html {
flash[:notice] = l(:notice_successful_update)
redirect_to contest_page_made_url
}
format.api { render_api_ok }
end
else
respond_to do |format|
flash.now[:error] = "#{l :label_first_page_create_fail}: #{@first_page.errors.full_messages[0]}\n\t#{@contest_page.errors.full_messages[0]}\n\t#{@notification.errors.full_messages[0]}"
format.html {
render :action => 'contest_page_made'
}
format.api { render_validation_errors(@first_page) }
format.api { render_validation_errors(@contest_page) }
end
end
end
end
def web_footer_made
if request.get?
@organizer = WebFooterOranizer.first
@first_page = FirstPage.find_by_page_type('project')
#@notification = ContestNotification.all.first;
elsif request.post?
@first_page = FirstPage.find_by_page_type('project')
@first_page.web_title = params[:web_title]
@organizer = WebFooterOranizer.first
if @organizer.nil?
@organizer = WebFooterOranizer.new
end
@organizer.name = params[:organizer_name]
@organizer.description = params[:web_footer_oranizer][:description]
if @first_page.save && @organizer.save
respond_to do |format|
format.html {
flash[:notice] = l(:notice_successful_update)
redirect_to web_footer_made_url
}
format.api { render_api_ok }
end
else
respond_to do |format|
flash.now[:error] = "#{l :label_first_page_create_fail}: #{@first_page.errors.full_messages[0]}\n\t#{@organizer.errors.full_messages[0]}}"
format.html {
render :action => 'web_footer_made'
}
format.api { render_validation_errors(@first_page) }
format.api { render_validation_errors(@contest_page) }
end
end
end
end
end

@ -41,6 +41,8 @@ class ApplicationController < ActionController::Base
cookies.delete(autologin_cookie_name)
end
before_filter :find_first_page
before_filter :find_web_footer
before_filter :session_expiration, :user_setup, :check_if_login_required, :set_localization
before_filter :user_agent
@ -122,7 +124,7 @@ class ApplicationController < ActionController::Base
else
# HTTP Basic, either username/password or API key/random
authenticate_with_http_basic do |username, password|
user = User.try_to_login(username, password) || User.find_by_api_key(username)
user = User.try_to_login(username, password)[0] || User.find_by_api_key(username)
end
end
# Switch user if requested by an admin user
@ -207,8 +209,8 @@ class ApplicationController < ActionController::Base
url = url_for(:controller => params[:controller], :action => params[:action], :id => params[:id], :project_id => params[:project_id])
end
respond_to do |format|
format.html { redirect_to :controller => "account", :action => "login", :back_url => url }
format.atom { redirect_to :controller => "account", :action => "login", :back_url => url }
format.html { redirect_to signin_url }
format.atom { redirect_to signin_url }
format.xml { head :unauthorized, 'WWW-Authenticate' => 'Basic realm="Redmine API"' }
format.js { head :unauthorized, 'WWW-Authenticate' => 'Basic realm="Redmine API"' }
format.json { head :unauthorized, 'WWW-Authenticate' => 'Basic realm="Redmine API"' }
@ -233,6 +235,21 @@ class ApplicationController < ActionController::Base
# Authorize the user for the requested action
def authorize(ctrl = params[:controller], action = params[:action], global = false)
#modify by NWB
allowed = authorize_allowed(params[:controller], params[:action],global)
if allowed
true
else
if @project && @project.archived?
render_403 :message => :notice_not_authorized_archived_project
else
deny_access
end
end
end
def authorize_allowed(ctrl = params[:controller], action = params[:action], global = false)
#modify by NWB
if @project
allowed = User.current.allowed_to?({:controller => ctrl, :action => action}, @project || @projects, :global => global)
@ -241,6 +258,25 @@ class ApplicationController < ActionController::Base
else
allowed = User.current.allowed_to?({:controller => ctrl, :action => action}, @project || @projects, :global => global)
end
allowed
end
def authorize_attachment_download(ctrl = params[:controller], action = params[:action], global = false)
case @attachment.container_type
when "Memo"
allowed = User.current.allowed_to?(:memos_attachments_download,nil,:global => true)
when "Message"
if @project
allowed = User.current.allowed_to?(:projects_attachments_download,@project,:global => false)
elsif @course
allowed = User.current.allowed_to?(:course_attachments_download, @course, :global => false)
end
when "contest"
return true
when "Course"
allowed = User.current.allowed_to?(:course_attachments_download, @course, :global => false)
else
return true
end
if allowed
true
@ -470,26 +506,33 @@ class ApplicationController < ActionController::Base
def render_403(options={})
@project = nil
render_error({:message => :notice_not_authorized, :status => 403}.merge(options))
render_error({:message => :notice_not_authorized, :status => 403}.merge(options),'common/403')
#render :template => 'common/403'
return false
end
def render_404(options={})
render_error({:message => :notice_file_not_found, :status => 404}.merge(options))
render_error({:message => :notice_file_not_found, :status => 404}.merge(options),'common/404')
#render :template => 'common/404'
return false
end
# Renders an error response
def render_error(arg)
def render_error(arg,template = 'common/error')
arg = {:message => arg} unless arg.is_a?(Hash)
@message = arg[:message]
@lay = arg[:layout]
@message = l(@message) if @message.is_a?(Symbol)
@status = arg[:status] || 500
respond_to do |format|
format.html {
render :template => 'common/error', :layout => use_layout, :status => @status
if @lay
render :template => template, :layout => @lay,:status => @status
else
render :template => template, :layout => use_layout, :status => @status
end
}
format.any { head @status }
end
@ -519,7 +562,7 @@ class ApplicationController < ActionController::Base
#
# @return [boolean, string] name of the layout to use or false for no layout
def use_layout
request.xhr? ? false : 'base'
request.xhr? ? false : 'users_base'
end
def invalid_authenticity_token
@ -715,4 +758,35 @@ class ApplicationController < ActionController::Base
raise RuntimeError, 'unknow type, Please input you type into this helper.'
end
end
def paginateHelper_for_members obj, pre_size=10
@obj_count = StudentsForCourse.find_by_sql("select count(id) as mem_count from students_for_courses where course_id = #{@course.id}")[0][:mem_count].to_s.to_i
@obj_pages = Paginator.new @obj_count, pre_size, params['page']
if obj.kind_of? ActiveRecord::Base or obj.kind_of? ActiveRecord::Relation
obj.limit(@obj_pages.per_page).offset(0)
elsif obj.kind_of? Array
obj[0, @obj_pages.per_page]
else
logger.error "[ApplicationController] Error : application_controller#paginateHelper ===> unknow category: #{obj.class}"
raise RuntimeError, 'unknow type, Please input you type into this helper.'
end
end
#查找首页相关信息
def find_first_page
@first_page = FirstPage.find_by_page_type('project')
if @first_page.nil?
@first_page = FirstPage.new
@first_page.page_type = 'project'
@first_page.description = ""
@first_page.save()
end
@show_course = @first_page.show_course
@show_contest = @first_page.show_contest
end
def find_web_footer
@organizer = WebFooterOranizer.first
@companies = WebFooterCompany.all
end
end

@ -6,7 +6,8 @@ class AppliedProjectController < ApplicationController
@project = Project.find(params[:project_id])
@applieds = AppliedProject.where("user_id = ? and project_id = ?", params[:user_id],params[:project_id])
if @applieds.count == 0
AppliedProject.create(:user_id => params[:user_id], :project_id => params[:project_id])
appliedproject = AppliedProject.create(:user_id => params[:user_id], :project_id => params[:project_id])
Mailer.applied_project(appliedproject).deliver
end
#redirect_to project_path(params[:project_id])

@ -1,294 +1,465 @@
# Redmine - project management software
# Copyright (C) 2006-2013 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 AttachmentsController < ApplicationController
before_filter :find_project, :only => [:show, :download, :thumbnail, :destroy, :delete_homework]#, :except => [:upload, :autocomplete]
before_filter :file_readable, :read_authorize, :only => [:show, :thumbnail]#Modified by young
before_filter :delete_authorize, :only => :destroy
before_filter :authorize_global, :only => :upload
before_filter :login_without_softapplication, only: [:download]
accept_api_auth :show, :download, :upload
def show
respond_to do |format|
format.html {
if @attachment.is_diff?
@diff = File.new(@attachment.diskfile, "rb").read
@diff_type = params[:type] || User.current.pref[:diff_type] || '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
render :action => 'diff'
elsif @attachment.is_text? && @attachment.filesize <= Setting.file_max_size_displayed.to_i.kilobyte
@content = File.new(@attachment.diskfile, "rb").read
render :action => 'file'
else
download
end
}
format.api
end
end
def download
if true || @attachment.container.is_a?(Version) || @attachment.container.is_a?(Project)
@attachment.increment_download
end
if stale?(:etag => @attachment.digest)
# images are sent inline
send_file @attachment.diskfile, :filename => filename_for_content_disposition(@attachment.filename),
:type => detect_content_type(@attachment),
:disposition => (@attachment.image? ? 'inline' : 'attachment')
end
rescue => e
redirect_to "http://" + (Setting.host_name.to_s) +"/file_not_found.html"
end
#更新资源文件类型
def updateType
@attachment = Attachment.find(params[:attachmentid])
if @attachment != nil
@attachment.attachtype = params[:newtype]
@attachment.save
render :text =>'success'
else
render :text=>'error'
end
end
def thumbnail
if @attachment.thumbnailable? && thumbnail = @attachment.thumbnail(:size => params[:size])
if stale?(:etag => thumbnail)
send_file thumbnail,
:filename => filename_for_content_disposition(@attachment.filename),
:type => detect_content_type(@attachment),
:disposition => 'inline'
end
else
# No thumbnail for the attachment or thumbnail could not be created
render :nothing => true, :status => 404
end
end
def upload
# Make sure that API users get used to set this content type
# as it won't trigger Rails' automatic parsing of the request body for parameters
unless request.content_type == 'application/octet-stream'
render :nothing => true, :status => 406
return
end
@attachment = Attachment.new(:file => request.raw_post)
@attachment.author = User.current
@attachment.filename = params[:filename].presence || Redmine::Utils.random_hex(16)
saved = @attachment.save
respond_to do |format|
format.js
format.api {
if saved
render :action => 'upload', :status => :created
else
render_validation_errors(@attachment)
end
}
end
end
def destroy
if @attachment.container.respond_to?(:init_journal)
@attachment.container.init_journal(User.current)
end
if @attachment.container
# Make sure association callbacks are called
@attachment.container.attachments.delete(@attachment)
else
@attachment.destroy
end
respond_to do |format|
# modify by nwb
if @attachment.container_type == 'Course'
if @course.nil?
format.html { redirect_to_referer_or forum_memo_path(@attachment.container.forum, @attachment.container) }
else
format.html { redirect_to_referer_or course_path(@course) }
end
else
if @project.nil?
format.html { redirect_to_referer_or forum_memo_path(@attachment.container.forum, @attachment.container) }
else
format.html { redirect_to_referer_or project_path(@project) }
end
end
format.js
end
end
def delete_homework
@bid = @attachment.container.bid
# Make sure association callbacks are called
container = @attachment.container
@attachment.container.attachments.delete(@attachment)
#if container.attachments.empty?
#container.delete
#end
respond_to do |format|
format.html { redirect_to_referer_or respond_path(@bid) }
format.js
end
end
def autocomplete
# modify by nwb
if params[:project_id]
@project = Project.find_by_id(params[:project_id])
elsif params[:course_id]
@course = Course.find_by_id(params[:course_id])
end
respond_to do |format|
format.js
end
end
def add_exist_file_to_project
classname = params[:class_name]
class_id = params[:class_id]
attachments = params[:attachment][:attach]
obj = Object.const_get(classname).find_by_id(class_id)
attachments.collect do |attach_id|
ori = Attachment.find_by_id(attach_id)
next if ori.blank?
attach_copied_obj = ori.copy
attach_copied_obj.tag_list.add(ori.tag_list) # tag关联
attach_copied_obj.container = obj
attach_copied_obj.created_on = Time.now
attach_copied_obj.author_id = User.current.id
@obj = obj
@save_flag = attach_copied_obj.save
@save_message = attach_copied_obj.errors.full_messages
end
respond_to do |format|
format.js
end
rescue NoMethodError
@save_flag = false
@save_message = [] << l(:error_attachment_empty)
respond_to do |format|
format.js
end
end
def add_exist_file_to_course
class_id = params[:class_id]
attachments = params[:attachment][:attach]
obj = Course.find_by_id(class_id)
attachments.collect do |attach_id|
ori = Attachment.find_by_id(attach_id)
next if ori.blank?
attach_copied_obj = ori.copy
attach_copied_obj.tag_list.add(ori.tag_list) # tag关联
attach_copied_obj.container = obj
attach_copied_obj.created_on = Time.now
attach_copied_obj.author_id = User.current.id
@obj = obj
@save_flag = attach_copied_obj.save
@save_message = attach_copied_obj.errors.full_messages
end
respond_to do |format|
format.js
end
rescue NoMethodError
@save_flag = false
@save_message = [] << l(:error_attachment_empty)
respond_to do |format|
format.js
end
end
private
def find_project
@attachment = Attachment.find(params[:id])
# Show 404 if the filename in the url is wrong
# modify by nwb
raise ActiveRecord::RecordNotFound if params[:filename] && params[:filename] != @attachment.filename
if @attachment.container_type == 'Course'
@course = @attachment.course
else
unless @attachment.container_type == 'Bid' || @attachment.container_type == 'HomeworkAttach' || @attachment.container_type == 'Memo' || @attachment.container_type == 'Softapplication'
@project = @attachment.project
end
end
rescue ActiveRecord::RecordNotFound
render_404
end
# Checks that the file exists and is readable
def file_readable
if @attachment.readable?
true
else
logger.error "Cannot send attachment, #{@attachment.diskfile} does not exist or is unreadable."
render_404
end
end
def read_authorize
if @attachment.container_type == "HomeworkAttach" || @attachment.container_type == 'Bid'
true
#User.current.allowed_to?(:view_homework_attaches, @attachment.project) ? true : deny_access
else
@attachment.visible? ? true : deny_access
end
end
def delete_authorize
@attachment.deletable? ? true : deny_access
end
def detect_content_type(attachment)
content_type = attachment.content_type
if content_type.blank?
content_type = Redmine::MimeType.of(attachment.filename)
end
content_type.to_s
end
def login_without_softapplication
referer = request.headers['Referer']
require_login unless referer =~ /softapplication/
end
def renderTag
@attachmentNew = Attachment.find(params[:attchmentId])
respond_to do |format|
format.js
end
end
end
# Redmine - project management software
# Copyright (C) 2006-2013 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 AttachmentsController < ApplicationController
layout "users_base"
before_filter :find_project, :only => [:show, :download, :thumbnail, :destroy, :delete_homework]#, :except => [:upload, :autocomplete]
before_filter :file_readable, :read_authorize, :only => [:show, :thumbnail]#Modified by young
before_filter :delete_authorize, :only => :destroy
before_filter :authorize_global, :only => :upload
before_filter :authorize_attachment_download, :only => :download
#before_filter :login_without_softapplication, only: [:download]
accept_api_auth :show, :download, :upload
require 'iconv'
include AttachmentsHelper
def show
respond_to do |format|
format.html {
if @attachment.is_diff?
@diff = File.new(@attachment.diskfile, "rb").read
@diff_type = params[:type] || User.current.pref[:diff_type] || '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
render :action => 'diff'
elsif @attachment.is_text? && @attachment.filesize <= Setting.file_max_size_displayed.to_i.kilobyte
@content = File.new(@attachment.diskfile, "rb").read
# 编码为非 UTF-8先进行间接转码
# 部分unicode编码不直接支持转为 UTF-8
# modify by nwb
if @content.encoding.name != 'UTF-8'
@content = @content.force_encoding('GBK')
@content = @content.encode('UTF-8')
end
render :action => 'file'
else
download
end
}
format.api
end
rescue Encoding::InvalidByteSequenceError => e
render :action => 'file'
end
def download
# modify by nwb
# 下载添加权限设置
candown = false
if @attachment.container.class.to_s != "HomeworkAttach" && (@attachment.container.has_attribute?(:project) || @attachment.container.has_attribute?(:project_id)) && @attachment.container.project
project = @attachment.container.project
candown= User.current.member_of?(project) || (project.is_public && @attachment.is_public == 1)
elsif @attachment.container.is_a?(Project)
project = @attachment.container
candown= User.current.member_of?(project) || (project.is_public && @attachment.is_public == 1)
elsif (@attachment.container.has_attribute?(:board) || @attachment.container.has_attribute?(:board_id)) && @attachment.container.board &&
@attachment.container.board.project
project = @attachment.container.board.project
candown = User.current.member_of?(project) || (project.is_public && @attachment.is_public == 1)
elsif (@attachment.container.has_attribute?(:course) ||@attachment.container.has_attribute?(:course_id) ) && @attachment.container.course
course = @attachment.container.course
candown = User.current.member_of_course?(course) || (course.is_public==1 && @attachment.is_public == 1)
elsif @attachment.container.is_a?(Course)
course = @attachment.container
candown= User.current.member_of_course?(course) || (course.is_public==1 && @attachment.is_public == 1)
elsif (@attachment.container.has_attribute?(:board) || @attachment.container.has_attribute?(:board_id)) && @attachment.container.board &&
@attachment.container.board.course
course = @attachment.container.board.course
candown= User.current.member_of_course?(course) || (course.is_public==1 && @attachment.is_public == 1)
elsif @attachment.container.class.to_s=="HomeworkAttach" && @attachment.container.bid.reward_type == 3
candown = true
elsif @attachment.container_type == "Bid" && @attachment.container && @attachment.container.courses.first
course = @attachment.container.courses.first
candown = User.current.member_of_course?(course) || (course.is_public == 1 && @attachment.is_public == 1)
else
candown = @attachment.is_public == 1
end
if candown || User.current.admin? || User.current.id == @attachment.author_id
@attachment.increment_download
if stale?(:etag => @attachment.digest)
# images are sent inline
send_file @attachment.diskfile, :filename => filename_for_content_disposition(@attachment.filename),
:type => detect_content_type(@attachment),
:disposition => (@attachment.image? ? 'inline' : 'attachment')
end
else
render_403 :message => :notice_not_authorized
end
rescue => e
redirect_to "http://" + (Setting.host_name.to_s) +"/file_not_found.html"
end
#更新资源文件类型
def updateType
@attachment = Attachment.find(params[:attachmentid])
if @attachment != nil
@attachment.attachtype = params[:newtype]
@attachment.save
render :text =>'success'
else
render :text=>'error'
end
end
# 更新文件密级
def updateFileDense
@attachment = Attachment.find(params[:attachmentid])
if @attachment != nil
filedense = params[:newtype].to_s
# d = Iconv.conv("unicodebig","utf-8",filedense)
if filedense == "%E5%85%AC%E5%BC%80" #l(:field_is_public)
@attachment.is_public = 1
else
@attachment.is_public = 0
end
@attachment.save
@newfiledense = filedense
end
respond_to do |format|
format.js
end
end
def update_file_dense
@attachment = Attachment.find(params[:attachmentid])
if @attachment != nil
filedense = params[:newtype].to_s
if filedense == "1"
@attachment.is_public = 1
else
@attachment.is_public = 0
end
@attachment.save
@newfiledense = filedense
end
respond_to do |format|
format.js
end
end
def thumbnail
if @attachment.thumbnailable? && thumbnail = @attachment.thumbnail(:size => params[:size])
if stale?(:etag => thumbnail)
send_file thumbnail,
:filename => filename_for_content_disposition(@attachment.filename),
:type => detect_content_type(@attachment),
:disposition => 'inline'
end
else
# No thumbnail for the attachment or thumbnail could not be created
render :nothing => true, :status => 404
end
end
def upload
# Make sure that API users get used to set this content type
# as it won't trigger Rails' automatic parsing of the request body for parameters
unless request.content_type == 'application/octet-stream'
render :nothing => true, :status => 406
return
end
@attachment = Attachment.new(:file => request.raw_post)
@attachment.author = User.current
@attachment.filename = params[:filename].presence || Redmine::Utils.random_hex(16)
saved = @attachment.save
respond_to do |format|
format.js
format.api {
if saved
render :action => 'upload', :status => :created
else
render_validation_errors(@attachment)
end
}
end
end
def destroy
if @attachment.container.respond_to?(:init_journal)
@attachment.container.init_journal(User.current)
end
if @attachment.container
@attachment.container.attachments.delete(@attachment)
else
@attachment.destroy
end
respond_to do |format|
if !@attachment.container.nil? &&
(@attachment.container.is_a?(Course) || ((@attachment.container.has_attribute?(:course) || @attachment.container.has_attribute?(:course_id) ) &&
@attachment.container.course ) || ((@attachment.container.has_attribute?(:board) || @attachment.container.has_attribute?(:board_id)) &&
@attachment.container.board && @attachment.container.board.course ) )
if @attachment.container.is_a?(News)
format.html { redirect_to_referer_or news_path(@attachment.container) }
elsif @attachment.container.is_a?(Message)
format.html { redirect_to_referer_or new_board_message_path(@attachment.container) }
elsif @course.nil?
format.html { redirect_to_referer_or forum_memo_path(@attachment.container.forum, @attachment.container) }
else
format.html { redirect_to_referer_or course_path(@course) }
end
elsif !@attachment.container.nil? && @attachment.container.is_a?(Softapplication)
format.html { redirect_to_referer_or softapplications_path(@attachment.container) }
elsif !@attachment.container.nil? && @attachment.container.is_a?(Bid)
format.html { redirect_to_referer_or respond_path(@attachment.container) }
else
if @project.nil?
format.html { redirect_to_referer_or forum_memo_path(@attachment.container.forum, @attachment.container) }
else
format.html { redirect_to_referer_or project_path(@project) }
end
end
format.js
end
end
def delete_homework
@bid = @attachment.container.bid
# Make sure association callbacks are called
container = @attachment.container
@attachment.container.attachments.delete(@attachment)
#if container.attachments.empty?
#container.delete
#end
respond_to do |format|
format.html { redirect_to_referer_or respond_path(@bid) }
format.js
end
end
#删除竞赛作品的附件
def delete_softapplications
@attachment = Attachment.find params[:id]
@softapplication = @attachment.container if @attachment!=nil
@attachment.container.attachments.delete(@attachment) if @attachment!=nil
respond_to do |format|
format.html { redirect_to_referer_or edit_softapplication_path(@softapplication) }
#format.js
end
end
def autocomplete
# modify by nwb
if params[:project_id]
@project = Project.find_by_id(params[:project_id])
elsif params[:course_id]
@course = Course.find_by_id(params[:course_id])
end
respond_to do |format|
format.js
end
end
def add_exist_file_to_project
classname = params[:class_name]
class_id = params[:class_id]
attachments = params[:attachment][:attach]
obj = Object.const_get(classname).find_by_id(class_id)
attachments.collect do |attach_id|
ori = Attachment.find_by_id(attach_id)
next if ori.blank?
attach_copied_obj = ori.copy
attach_copied_obj.tag_list.add(ori.tag_list) # tag关联
attach_copied_obj.container = obj
attach_copied_obj.created_on = Time.now
attach_copied_obj.author_id = User.current.id
if attach_copied_obj.attachtype == nil
attach_copied_obj.attachtype = 1
end
@obj = obj
@save_flag = attach_copied_obj.save
@save_message = attach_copied_obj.errors.full_messages
end
respond_to do |format|
format.js
end
rescue NoMethodError
@save_flag = false
@save_message = [] << l(:error_attachment_empty)
respond_to do |format|
format.js
end
end
def add_exist_file_to_course
class_id = params[:class_id]
attachments = params[:attachment][:attach]
obj = Course.find_by_id(class_id)
attachments.collect do |attach_id|
ori = Attachment.find_by_id(attach_id)
next if ori.blank?
attach_copied_obj = ori.copy
attach_copied_obj.tag_list.add(ori.tag_list) # tag关联
attach_copied_obj.container = obj
attach_copied_obj.created_on = Time.now
attach_copied_obj.author_id = User.current.id
if attach_copied_obj.attachtype == nil
attach_copied_obj.attachtype = 4
end
@obj = obj
@save_flag = attach_copied_obj.save
@save_message = attach_copied_obj.errors.full_messages
end
respond_to do |format|
format.js
end
rescue NoMethodError
@save_flag = false
@save_message = [] << l(:error_attachment_empty)
respond_to do |format|
format.js
end
end
def add_exist_file_to_courses
file = Attachment.find(params[:file_id])
courses = params[:courses][:course]
@message = ""
courses.each do |course|
c = Course.find(course);
if course_contains_attachment?(c,file)
if @message && @message == ""
@message += l(:label_course_prompt) + c.name + l(:label_contain_resource) + file.filename + l(:label_quote_resource_failed)
next
else
@message += "<br/>" + l(:label_course_prompt) + c.name + l(:label_contain_resource) + file.filename + l(:label_quote_resource_failed)
next
end
end
attach_copied_obj = file.copy
attach_copied_obj.tag_list.add(file.tag_list) # tag关联
attach_copied_obj.container = c
attach_copied_obj.created_on = Time.now
attach_copied_obj.author_id = User.current.id
attach_copied_obj.copy_from = file.copy_from.nil? ? file.id : file.copy_from
if attach_copied_obj.attachtype == nil
attach_copied_obj.attachtype = 4
end
@obj = c
@save_flag = attach_copied_obj.save
@save_message = attach_copied_obj.errors.full_messages
update_quotes attach_copied_obj
end
respond_to do |format|
format.js
end
rescue NoMethodError
@save_flag = false
@save_message = [] << l(:label_course_empty_select)
respond_to do |format|
format.js
end
end
def update_quotes attachment
if attachment.copy_from
attachments = Attachment.find_by_sql("select * from attachments where copy_from = #{attachment.copy_from} or id = #{attachment.copy_from}")
else
attachments = Attachment.find_by_sql("select * from attachments where copy_from = #{attachment.id} or id = #{attachment.copy_from}")
end
attachment.quotes = get_qute_number attachment
attachment.save
attachments.each do |att|
att.quotes = attachment.quotes
att.save
end
end
private
def find_project
@attachment = Attachment.find(params[:id])
# Show 404 if the filename in the url is wrong
# modify by nwb
raise ActiveRecord::RecordNotFound if params[:filename] && params[:filename] != @attachment.filename
if @attachment.container_type == 'Course'
@course = @attachment.course
elsif !@attachment.container.nil? && (@attachment.container.has_attribute?(:course) || @attachment.container.has_attribute?(:course_id)) && @attachment.container.course
@course = @attachment.container.course
elsif !@attachment.container.nil? && ((@attachment.container.has_attribute?(:board) || @attachment.container.has_attribute?(:board_id)) && @attachment.container.board &&
@attachment.container.board.course)
@course = @attachment.container.board.course
else
unless @attachment.container_type == 'Bid' || @attachment.container_type == 'HomeworkAttach' || @attachment.container_type == 'Memo' || @attachment.container_type == 'Softapplication'
@project = @attachment.project
end
end
rescue ActiveRecord::RecordNotFound
render_404
end
# Checks that the file exists and is readable
def file_readable
if @attachment.readable?
true
else
logger.error "Cannot send attachment, #{@attachment.diskfile} does not exist or is unreadable."
render_404
end
end
def read_authorize
if @attachment.container_type == "HomeworkAttach" || @attachment.container_type == 'Bid'
true
#User.current.allowed_to?(:view_homework_attaches, @attachment.project) ? true : deny_access
else
@attachment.visible? ? true : deny_access
end
end
def delete_authorize
@attachment.deletable? ? true : deny_access
end
def detect_content_type(attachment)
content_type = attachment.content_type
if content_type.blank?
content_type = Redmine::MimeType.of(attachment.filename)
end
content_type.to_s
end
def login_without_softapplication
referer = request.headers['Referer']
require_login unless referer =~ /softapplication/ || @attachment.container_type == "Memo"
end
def renderTag
@attachmentNew = Attachment.find(params[:attchmentId])
respond_to do |format|
format.js
end
end
end

@ -1,96 +1,96 @@
# Redmine - project management software
# Copyright (C) 2006-2013 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 AuthSourcesController < ApplicationController
layout 'admin'
menu_item :ldap_authentication
before_filter :require_admin
before_filter :find_auth_source, :only => [:edit, :update, :test_connection, :destroy]
def index
@auth_source_pages, @auth_sources = paginate AuthSource, :per_page => 25
end
def new
klass_name = params[:type] || 'AuthSourceLdap'
@auth_source = AuthSource.new_subclass_instance(klass_name, params[:auth_source])
render_404 unless @auth_source
end
def create
@auth_source = AuthSource.new_subclass_instance(params[:type], params[:auth_source])
if @auth_source.save
flash[:notice] = l(:notice_successful_create)
redirect_to auth_sources_path
else
render :action => 'new'
end
end
def edit
end
def update
if @auth_source.update_attributes(params[:auth_source])
flash[:notice] = l(:notice_successful_update)
redirect_to auth_sources_path
else
render :action => 'edit'
end
end
def test_connection
begin
@auth_source.test_connection
flash[:notice] = l(:notice_successful_connection)
rescue Exception => e
flash[:error] = l(:error_unable_to_connect, e.message)
end
redirect_to auth_sources_path
end
def destroy
unless @auth_source.users.exists?
@auth_source.destroy
flash[:notice] = l(:notice_successful_delete)
end
redirect_to auth_sources_path
end
def autocomplete_for_new_user
results = AuthSource.search(params[:term])
render :json => results.map {|result| {
'value' => result[:login],
'label' => "#{result[:login]} (#{result[:firstname]} #{result[:lastname]})",
'login' => result[:login].to_s,
'firstname' => result[:firstname].to_s,
'lastname' => result[:lastname].to_s,
'mail' => result[:mail].to_s,
'auth_source_id' => result[:auth_source_id].to_s
}}
end
private
def find_auth_source
@auth_source = AuthSource.find(params[:id])
rescue ActiveRecord::RecordNotFound
render_404
end
end
# Redmine - project management software
# Copyright (C) 2006-2013 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 AuthSourcesController < ApplicationController
layout 'admin'
menu_item :ldap_authentication
before_filter :require_admin
before_filter :find_auth_source, :only => [:edit, :update, :test_connection, :destroy]
def index
@auth_source_pages, @auth_sources = paginate AuthSource, :per_page => 25
end
def new
klass_name = params[:type] || 'AuthSourceLdap'
@auth_source = AuthSource.new_subclass_instance(klass_name, params[:auth_source])
render_404 unless @auth_source
end
def create
@auth_source = AuthSource.new_subclass_instance(params[:type], params[:auth_source])
if @auth_source.save
flash[:notice] = l(:notice_successful_create)
redirect_to auth_sources_url
else
render :action => 'new'
end
end
def edit
end
def update
if @auth_source.update_attributes(params[:auth_source])
flash[:notice] = l(:notice_successful_update)
redirect_to auth_sources_url
else
render :action => 'edit'
end
end
def test_connection
begin
@auth_source.test_connection
flash[:notice] = l(:notice_successful_connection)
rescue Exception => e
flash[:error] = l(:error_unable_to_connect, e.message)
end
redirect_to auth_sources_url
end
def destroy
unless @auth_source.users.exists?
@auth_source.destroy
flash[:notice] = l(:notice_successful_delete)
end
redirect_to auth_sources_url
end
def autocomplete_for_new_user
results = AuthSource.search(params[:term])
render :json => results.map {|result| {
'value' => result[:login],
'label' => "#{result[:login]} (#{result[:firstname]} #{result[:lastname]})",
'login' => result[:login].to_s,
'firstname' => result[:firstname].to_s,
'lastname' => result[:lastname].to_s,
'mail' => result[:mail].to_s,
'auth_source_id' => result[:auth_source_id].to_s
}}
end
private
def find_auth_source
@auth_source = AuthSource.find(params[:id])
rescue ActiveRecord::RecordNotFound
render_404
end
end

@ -29,7 +29,11 @@ class AutoCompletesController < ApplicationController
@issues += scope.where("LOWER(#{Issue.table_name}.subject) LIKE LOWER(?)", "%#{q}%").order("#{Issue.table_name}.id DESC").limit(10).all
@issues.compact!
end
render :layout => false
#render :layout => false
render :json => @issues.map {|issue| {
'value' => issue[:subject]
}}
end

@ -2,7 +2,7 @@ class AvatarController < ApplicationController
#before_filter :set_cache_buster
include AvatarHelper
include AvatarHelper
def upload
# Make sure that API users get used to set this content type
@ -28,6 +28,13 @@ class AvatarController < ApplicationController
if @temp_file && (@temp_file.size > 0)
diskfile=disk_filename(@source_type,@source_id)
@urlfile='/' << File.join("images","avatars",avatar_directory(@source_type),avatar_filename(@source_id,@image_file))
# 用户头像上传时进行特别处理
if @source_type == 'User'
diskfile += "temp"
@urlfile += "temp"
end
logger.info("Saving avatar '#{diskfile}' (#{@temp_file.size} bytes)")
path = File.dirname(diskfile)
unless File.directory?(path)
@ -55,17 +62,20 @@ class AvatarController < ApplicationController
# saved = @avatar.save
begin
f = Magick::ImageList.new(diskfile)
width = 300.0
proportion = (width/f[0].columns)
height = (f[0].rows*proportion)
f.resize_to_fill!(width,height)
# f.scale!(width,height)
f.write(diskfile)
# gif格式不再做大小处理
if f.format != 'GIF'
width = 300.0
proportion = (width/f[0].columns)
height = (f[0].rows*proportion)
f.resize_to_fill!(width,height)
f.write(diskfile)
end
rescue Exception => e
logger.error "[Error] avatar : avatar_controller#upload ===> #{e}"
end
respond_to do |format|
format.js
format.api {
@ -77,6 +87,49 @@ class AvatarController < ApplicationController
}
end
end
#add by zjc
#删除图片
def delete_image
@source_type = params[:source_type]
@source_id = params[:source_id]
@source = nil #eval(@source_type).find(@source_id)
c = Object.const_get(@source_type)
if c.respond_to?(:find)
@source = c.find(@source_id)
end
diskfile=disk_filename(@source_type,@source_id)
unless diskfile.nil? || diskfile == ""
path = File.dirname(diskfile)
if File.directory?(path) && File.exist?(diskfile)
# 用户头像进行特别处理
if @source_type == 'User'
diskfile1 = diskfile + 'temp'
File.open(diskfile1, "wb") do |f|
buffer = "DELETE"
f.write(buffer)
end
else
File.delete(diskfile)
end
end
end
rescue e do
logger.info e.message
end
respond_to do |format|
format.js
format.api {
if saved
render :action => 'upload', :status => :created
else
render_validation_errors(@avatar)
end
}
end
end
private

File diff suppressed because it is too large Load Diff

@ -1,147 +1,157 @@
# Redmine - project management software
# Copyright (C) 2006-2013 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 BoardsController < ApplicationController
layout 'base_projects'#by young
default_search_scope :messages
before_filter :find_project_by_project_id, :find_board_if_available
before_filter :authorize, :except => [:new, :show, :create, :index]
accept_rss_auth :index, :show
helper :sort
include SortHelper
helper :watchers
def index
#modify by nwb
if @project
@boards = @project.boards.includes(:last_message => :author).all
@boards = [] << @boards[0] if @boards.any?
if @boards.size == 1
@board = @boards.first
show and return
end
render :layout => false if request.xhr?
elsif @course
@boards = @course.boards.includes(:last_message => :author).all
@boards = [] << @boards[0] if @boards.any?
if @boards.size == 1
@board = @boards.first
show and return
end
render :layout => 'base_courses'
end
end
def show
respond_to do |format|
format.html {
sort_init 'updated_on', 'desc'
sort_update 'created_on' => "#{Message.table_name}.created_on",
'replies' => "#{Message.table_name}.replies_count",
'updated_on' => "COALESCE(last_replies_messages.created_on, #{Message.table_name}.created_on)"
@topic_count = @board.topics.count
@topic_pages = Paginator.new @topic_count, per_page_option, params['page']
@topics = @board.topics.
reorder("#{Message.table_name}.sticky DESC").
includes(:last_reply).
limit(@topic_pages.per_page).
offset(@topic_pages.offset).
order(sort_clause).
preload(:author, {:last_reply => :author}).
all
@message = Message.new(:board => @board)
#modify by nwb
if @project
render :action => 'show', :layout => !request.xhr?
elsif @course
render :action => 'show', :layout => 'base_courses'
end
}
format.atom {
@messages = @board.messages.
reorder('created_on DESC').
includes(:author, :board).
limit(Setting.feeds_limit.to_i).
all
if @project
render_feed(@messages, :title => "#{@project}: #{@board}")
elsif @course
render_feed(@messages, :title => "#{@course}: #{@board}")
end
}
end
end
def new
@board = @project.boards.build
@board.safe_attributes = params[:board]
if @project.project_type == 1
render :layout => 'base_courses'
end
end
def create
@board = @project.boards.build
@board.safe_attributes = params[:board]
if @board.save
flash[:notice] = l(:notice_successful_create)
#Modified by young
#redirect_to_settings_in_projects
redirect_to project_board_path(@project, @board)
#Ended by young
else
render :action => 'new'
end
end
def edit
if @project.project_type == 1
render :layout => 'base_courses'
end
end
def update
@board.safe_attributes = params[:board]
if @board.save
redirect_to_settings_in_projects
else
render :action => 'edit'
end
end
def destroy
@board.destroy
redirect_to_settings_in_projects
end
private
def redirect_to_settings_in_projects
redirect_to settings_project_path(@project, :tab => 'boards')
end
def find_board_if_available
@board = @project.boards.find(params[:id]) if params[:id]
rescue ActiveRecord::RecordNotFound
render_404
end
end
# Redmine - project management software
# Copyright (C) 2006-2013 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 BoardsController < ApplicationController
layout 'base_projects'#by young
default_search_scope :messages
before_filter :find_project_by_project_id, :find_board_if_available
before_filter :authorize, :except => [:new, :show, :create, :index]
accept_rss_auth :index, :show
helper :sort
include SortHelper
helper :watchers
helper :project_score
def index
#modify by nwb
if @project
@boards = @project.boards.includes(:last_message => :author).all
@boards = [] << @boards[0] if @boards.any?
if @boards.size == 1
@board = @boards.first
show and return
end
render :layout => false if request.xhr?
elsif @course
if (User.current.admin? || @course.is_public == 1 || (@course.is_public == 0 && User.current.member_of_course?(@course)))
@boards = @course.boards.includes(:last_message => :author).all
@boards = [] << @boards[0] if @boards.any?
if @boards.size == 1
@board = @boards.first
show and return
end
render :layout => 'base_courses'
else
render_403
end
end
end
def show
respond_to do |format|
format.html {
sort_init 'updated_on', 'desc'
sort_update 'created_on' => "#{Message.table_name}.created_on",
'replies' => "#{Message.table_name}.replies_count",
'updated_on' => "COALESCE(last_replies_messages.created_on, #{Message.table_name}.created_on)"
@topic_count = @board.topics.count
@topic_pages = Paginator.new @topic_count, per_page_option, params['page']
@topics = @board.topics.
reorder("#{Message.table_name}.sticky DESC").
includes(:last_reply).
limit(@topic_pages.per_page).
offset(@topic_pages.offset).
order(sort_clause).
preload(:author, {:last_reply => :author}).
all
@message = Message.new(:board => @board)
#modify by nwb
if @project
render :action => 'show', :layout => 'base_projects'
elsif @course
render :action => 'show', :layout => 'base_courses'
end
}
format.atom {
@messages = @board.messages.
reorder('created_on DESC').
includes(:author, :board).
limit(Setting.feeds_limit.to_i).
all
if @project
render_feed(@messages, :title => "#{@project}: #{@board}")
elsif @course
render_feed(@messages, :title => "#{@course}: #{@board}")
end
}
end
end
def new
@board = @project.boards.build
@board.safe_attributes = params[:board]
if @project.project_type == 1
render :layout => 'base_courses'
end
end
def create
@board = @project.boards.build
@board.safe_attributes = params[:board]
if @board.save
flash[:notice] = l(:notice_successful_create)
#Modified by young
#redirect_to_settings_in_projects
redirect_to project_board_url(@project, @board)
#Ended by young
else
render :action => 'new'
end
end
def edit
if @project.project_type == 1
render :layout => 'base_courses'
end
end
def update
@board.safe_attributes = params[:board]
if @board.save
redirect_to_settings_in_projects
else
render :action => 'edit'
end
end
def destroy
@board.destroy
redirect_to_settings_in_projects
end
private
def redirect_to_settings_in_projects
redirect_to settings_project_url(@project, :tab => 'boards')
end
def find_board_if_available
if @project
@board = @project.boards.find(params[:id]) if params[:id]
elsif @course
@board = @course.boards.find(params[:id]) if params[:id]
end
rescue ActiveRecord::RecordNotFound
render_404
end
end

@ -27,6 +27,7 @@ class CalendarsController < ApplicationController
include QueriesHelper
helper :sort
include SortHelper
helper :project_score
def show
if params[:year] and params[:year].to_i > 1900

@ -1,55 +1,55 @@
# Redmine - project management software
# Copyright (C) 2006-2013 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 CommentsController < ApplicationController
default_search_scope :news
model_object News
before_filter :find_model_object
before_filter :find_project_from_association
before_filter :authorize
def create
raise Unauthorized unless @news.commentable?
@comment = Comment.new
@comment.safe_attributes = params[:comment]
@comment.author = User.current
if @news.comments << @comment
flash[:notice] = l(:label_comment_added)
end
redirect_to news_path(@news)
end
def destroy
@news.comments.find(params[:comment_id]).destroy
redirect_to news_path(@news)
end
private
# ApplicationController's find_model_object sets it based on the controller
# name so it needs to be overriden and set to @news instead
def find_model_object
super
@news = @object
@comment = nil
@news
end
end
# Redmine - project management software
# Copyright (C) 2006-2013 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 CommentsController < ApplicationController
default_search_scope :news
model_object News
before_filter :find_model_object
before_filter :find_project_from_association
before_filter :authorize
def create
raise Unauthorized unless @news.commentable?
@comment = Comment.new
@comment.safe_attributes = params[:comment]
@comment.author = User.current
if @news.comments << @comment
flash[:notice] = l(:label_comment_added)
end
redirect_to news_url(@news)
end
def destroy
@news.comments.find(params[:comment_id]).destroy
redirect_to news_url(@news)
end
private
# ApplicationController's find_model_object sets it based on the controller
# name so it needs to be overriden and set to @news instead
def find_model_object
super
@news = @object
@comment = nil
@news
end
end

@ -0,0 +1,6 @@
class ContestNotificationController < ApplicationController
layout 'contest_base'
def show
@notification = ContestNotification.find(params[:id])
end
end

@ -1,187 +1,187 @@
class ContestnotificationsController < ApplicationController
# GET /contestnotifications
# GET /contestnotifications.json
layout 'base_newcontest'
default_search_scope :contestnotifications
model_object Contestnotification
# before_filter :find_model_object, :except => [:new, :create, :index]
# before_filter :find_contest_from_association, :except => [:new, :create, :index]
before_filter :find_contest_by_contest_id, :only => [:new, :create]
before_filter :find_contest
before_filter :find_author
# before_filter :authorize, :except => [:index]
before_filter :find_optional_contest, :only => [:index]
accept_rss_auth :index
accept_api_auth :index
before_filter :access_edit_destroy, only: [:edit ,:update, :destroy]
def find_author
@user = @contest.author
render_404 if @user.nil?
end
def find_contest
@contest = Contest.find(params[:contest_id])
render_404 if @contest.nil?
end
def index
# @contestnotifications = Contestnotification.all
#
# respond_to do |format|
# format.html # index.html.erb
# format.json { render json: @contestnotifications }
# end
### begin ###
case params[:format]
when 'xml', 'json'
@offset, @limit = api_offset_and_limit
else
@limit = 10
end
scope = @contest ? @contest.contestnotifications.visible : Contestnotifications.visible
@contestnotifications_count = scope.count
@contestnotifications_pages = Paginator.new @contestnotifications_count, @limit, params['page']
@offset ||= @contestnotifications_pages.offset
@contestnotificationss = scope.all(:include => [:author, :contest],
:order => "#{Contestnotification.table_name}.created_at DESC",
:offset => @offset,
:limit => @limit)
respond_to do |format|
format.html {
@contestnotification = Contestnotification.new # for adding news inline
render :layout => 'base_newcontest'
}
format.api
format.atom { render_feed(@contestnotificationss, :title => (@contest ? @contest.name : Setting.app_title) + ": #{l(:label_contest_notification)}") }
end
### end ###
end
# GET /contestnotifications/1
# GET /contestnotifications/1.json
def show
@contestnotification = Contestnotification.find(params[:id])
#
# respond_to do |format|
# format.html # show.html.erb
# format.json { render json: @contestnotification }
# end
@notificationcomments = @contestnotification.notificationcomments
@notificationcomments.reverse! if User.current.wants_notificationcomments_in_reverse_order?
render :layout => 'base_newcontest'
end
# GET /contestnotifications/new
# GET /contestnotifications/new.json
def new
# @contestnotification = Contestnotification.new
#
# respond_to do |format|
# format.html # new.html.erb
# format.json { render json: @contestnotification }
# end
@contestnotification = Contestnotification.new(:contest => @contest, :author => User.current)
render :layout => 'base_newcontest'
end
# GET /contestnotifications/1/edit
def edit
@contestnotification = Contestnotification.find(params[:id])
end
# POST /contestnotifications
# POST /contestnotifications.json
def create
# @contestnotification = Contestnotification.new(params[:contestnotification])
#
# respond_to do |format|
# if @contestnotification.save
# format.html { redirect_to @contestnotification, notice: 'Contestnotification was successfully created.' }
# format.json { render json: @contestnotification, status: :created, location: @contestnotification }
# else
# format.html { render action: "new" }
# format.json { render json: @contestnotification.errors, status: :unprocessable_entity }
# end
# end
@contestnotification = Contestnotification.new(:contest => @contest, :author => User.current)
@contestnotification.safe_attributes = params[:contestnotification]
@contestnotification.save_attachments(params[:attachments])
if @contestnotification.save
render_attachment_warning_if_needed(@contestnotification)
flash[:notice] = l(:notice_successful_create)
redirect_to contest_contestnotifications_path(@contest)
else
layout_file = 'base_newcontest'
render :action => 'new', :layout => layout_file
end
end
# PUT /contestnotifications/1
# PUT /contestnotifications/1.json
def update
# @contestnotification = Contestnotification.find(params[:id])
#
# respond_to do |format|
# if @contestnotification.update_attributes(params[:contestnotification])
# format.html { redirect_to @contestnotification, notice: 'Contestnotification was successfully updated.' }
# format.json { head :no_content }
# else
# format.html { render action: "edit" }
# format.json { render json: @contestnotification.errors, status: :unprocessable_entity }
# end
# end
@contestnotification = Contestnotification.find(params[:id])
@contestnotification.safe_attributes = params[:contestnotification]
@contestnotification.save_attachments(params[:attachments])
if @contestnotification.save
render_attachment_warning_if_needed(@contestnotification)
flash[:notice] = l(:notice_successful_update)
redirect_to contest_contestnotification_path(@contestnotification.contest, @contestnotification)
else
render :action => 'edit'
end
end
# DELETE /contestnotifications/1
# DELETE /contestnotifications/1.json
def destroy
# @contestnotification = Contestnotification.find(params[:id])
# @contestnotification.destroy
#
# respond_to do |format|
# format.html { redirect_to contestnotifications_url }
# format.json { head :no_content }
# end
@contestnotification = Contestnotification.find(params[:id])
@contestnotification.destroy
redirect_to contest_contestnotifications_path(@contest)
end
private
def find_optional_contest
return true unless params[:id]
@contest = Contest.find(params[:id])
# authorize
rescue ActiveRecord::RecordNotFound
render_404
end
def access_edit_destroy
if (User.current.admin? && User.current.logged? )||(User.current == @contest.author && User.current.logged?)
return true
else
render_403
end
end
end
class ContestnotificationsController < ApplicationController
# GET /contestnotifications
# GET /contestnotifications.json
layout 'base_newcontest'
default_search_scope :contestnotifications
model_object Contestnotification
# before_filter :find_model_object, :except => [:new, :create, :index]
# before_filter :find_contest_from_association, :except => [:new, :create, :index]
before_filter :find_contest_by_contest_id, :only => [:new, :create]
before_filter :find_contest
before_filter :find_author
# before_filter :authorize, :except => [:index]
before_filter :find_optional_contest, :only => [:index]
accept_rss_auth :index
accept_api_auth :index
before_filter :access_edit_destroy, only: [:edit ,:update, :destroy]
def find_author
@user = @contest.author
render_404 if @user.nil?
end
def find_contest
@contest = Contest.find(params[:contest_id])
render_404 if @contest.nil?
end
def index
# @contestnotifications = Contestnotification.all
#
# respond_to do |format|
# format.html # index.html.erb
# format.json { render json: @contestnotifications }
# end
### begin ###
case params[:format]
when 'xml', 'json'
@offset, @limit = api_offset_and_limit
else
@limit = 10
end
scope = @contest ? @contest.contestnotifications.visible : Contestnotifications.visible
@contestnotifications_count = scope.count
@contestnotifications_pages = Paginator.new @contestnotifications_count, @limit, params['page']
@offset ||= @contestnotifications_pages.offset
@contestnotificationss = scope.all(:include => [:author, :contest],
:order => "#{Contestnotification.table_name}.created_at DESC",
:offset => @offset,
:limit => @limit)
respond_to do |format|
format.html {
@contestnotification = Contestnotification.new # for adding news inline
render :layout => 'base_newcontest'
}
format.api
format.atom { render_feed(@contestnotificationss, :title => (@contest ? @contest.name : Setting.app_title) + ": #{l(:label_contest_notification)}") }
end
### end ###
end
# GET /contestnotifications/1
# GET /contestnotifications/1.json
def show
@contestnotification = Contestnotification.find(params[:id])
#
# respond_to do |format|
# format.html # show.html.erb
# format.json { render json: @contestnotification }
# end
@notificationcomments = @contestnotification.notificationcomments
@notificationcomments.reverse! if User.current.wants_notificationcomments_in_reverse_order?
render :layout => 'base_newcontest'
end
# GET /contestnotifications/new
# GET /contestnotifications/new.json
def new
# @contestnotification = Contestnotification.new
#
# respond_to do |format|
# format.html # new.html.erb
# format.json { render json: @contestnotification }
# end
@contestnotification = Contestnotification.new(:contest => @contest, :author => User.current)
render :layout => 'base_newcontest'
end
# GET /contestnotifications/1/edit
def edit
@contestnotification = Contestnotification.find(params[:id])
end
# POST /contestnotifications
# POST /contestnotifications.json
def create
# @contestnotification = Contestnotification.new(params[:contestnotification])
#
# respond_to do |format|
# if @contestnotification.save
# format.html { redirect_to @contestnotification, notice: 'Contestnotification was successfully created.' }
# format.json { render json: @contestnotification, status: :created, location: @contestnotification }
# else
# format.html { render action: "new" }
# format.json { render json: @contestnotification.errors, status: :unprocessable_entity }
# end
# end
@contestnotification = Contestnotification.new(:contest => @contest, :author => User.current)
@contestnotification.safe_attributes = params[:contestnotification]
@contestnotification.save_attachments(params[:attachments])
if @contestnotification.save
render_attachment_warning_if_needed(@contestnotification)
flash[:notice] = l(:notice_successful_create)
redirect_to contest_contestnotifications_url(@contest)
else
layout_file = 'base_newcontest'
render :action => 'new', :layout => layout_file
end
end
# PUT /contestnotifications/1
# PUT /contestnotifications/1.json
def update
# @contestnotification = Contestnotification.find(params[:id])
#
# respond_to do |format|
# if @contestnotification.update_attributes(params[:contestnotification])
# format.html { redirect_to @contestnotification, notice: 'Contestnotification was successfully updated.' }
# format.json { head :no_content }
# else
# format.html { render action: "edit" }
# format.json { render json: @contestnotification.errors, status: :unprocessable_entity }
# end
# end
@contestnotification = Contestnotification.find(params[:id])
@contestnotification.safe_attributes = params[:contestnotification]
@contestnotification.save_attachments(params[:attachments])
if @contestnotification.save
render_attachment_warning_if_needed(@contestnotification)
flash[:notice] = l(:notice_successful_update)
redirect_to contest_contestnotification_url(@contestnotification.contest, @contestnotification)
else
render :action => 'edit'
end
end
# DELETE /contestnotifications/1
# DELETE /contestnotifications/1.json
def destroy
# @contestnotification = Contestnotification.find(params[:id])
# @contestnotification.destroy
#
# respond_to do |format|
# format.html { redirect_to contestnotifications_url }
# format.json { head :no_content }
# end
@contestnotification = Contestnotification.find(params[:id])
@contestnotification.destroy
redirect_to contest_contestnotifications_url(@contest)
end
private
def find_optional_contest
return true unless params[:id]
@contest = Contest.find(params[:id])
# authorize
rescue ActiveRecord::RecordNotFound
render_404
end
def access_edit_destroy
if (User.current.admin? && User.current.logged? )||(User.current == @contest.author && User.current.logged?)
return true
else
render_403
end
end
end

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,81 +1,81 @@
# Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class CustomFieldsController < ApplicationController
layout 'admin'
before_filter :require_admin
before_filter :build_new_custom_field, :only => [:new, :create]
before_filter :find_custom_field, :only => [:edit, :update, :destroy]
def index
@custom_fields_by_type = CustomField.all.group_by {|f| f.class.name }
@tab = params[:tab] || 'IssueCustomField'
end
def new
end
def create
if @custom_field.save
flash[:notice] = l(:notice_successful_create)
call_hook(:controller_custom_fields_new_after_save, :params => params, :custom_field => @custom_field)
redirect_to custom_fields_path(:tab => @custom_field.class.name)
else
render :action => 'new'
end
end
def edit
end
def update
if @custom_field.update_attributes(params[:custom_field])
flash[:notice] = l(:notice_successful_update)
call_hook(:controller_custom_fields_edit_after_save, :params => params, :custom_field => @custom_field)
redirect_to custom_fields_path(:tab => @custom_field.class.name)
else
render :action => 'edit'
end
end
def destroy
begin
@custom_field.destroy
rescue
flash[:error] = l(:error_can_not_delete_custom_field)
end
redirect_to custom_fields_path(:tab => @custom_field.class.name)
end
private
def build_new_custom_field
@custom_field = CustomField.new_subclass_instance(params[:type], params[:custom_field])
if @custom_field.nil?
render_404
else
@custom_field.default_value = nil
end
end
def find_custom_field
@custom_field = CustomField.find(params[:id])
rescue ActiveRecord::RecordNotFound
render_404
end
end
# Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class CustomFieldsController < ApplicationController
layout 'admin'
before_filter :require_admin
before_filter :build_new_custom_field, :only => [:new, :create]
before_filter :find_custom_field, :only => [:edit, :update, :destroy]
def index
@custom_fields_by_type = CustomField.all.group_by {|f| f.class.name }
@tab = params[:tab] || 'IssueCustomField'
end
def new
end
def create
if @custom_field.save
flash[:notice] = l(:notice_successful_create)
call_hook(:controller_custom_fields_new_after_save, :params => params, :custom_field => @custom_field)
redirect_to custom_fields_url(:tab => @custom_field.class.name)
else
render :action => 'new'
end
end
def edit
end
def update
if @custom_field.update_attributes(params[:custom_field])
flash[:notice] = l(:notice_successful_update)
call_hook(:controller_custom_fields_edit_after_save, :params => params, :custom_field => @custom_field)
redirect_to custom_fields_url(:tab => @custom_field.class.name)
else
render :action => 'edit'
end
end
def destroy
begin
@custom_field.destroy
rescue
flash[:error] = l(:error_can_not_delete_custom_field)
end
redirect_to custom_fields_url(:tab => @custom_field.class.name)
end
private
def build_new_custom_field
@custom_field = CustomField.new_subclass_instance(params[:type], params[:custom_field])
if @custom_field.nil?
render_404
else
@custom_field.default_value = nil
end
end
def find_custom_field
@custom_field = CustomField.find(params[:id])
rescue ActiveRecord::RecordNotFound
render_404
end
end

@ -1,103 +1,120 @@
# Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class DocumentsController < ApplicationController
layout 'base_projects'#by young
default_search_scope :documents
model_object Document
before_filter :find_project_by_project_id, :only => [:index, :new, :create]
before_filter :find_model_object, :except => [:index, :new, :create]
before_filter :find_project_from_association, :except => [:index, :new, :create]
before_filter :authorize , :except => [:index]#Added by young
helper :attachments
def index
@sort_by = %w(category date title author).include?(params[:sort_by]) ? params[:sort_by] : 'category'
documents = @project.documents.includes(:attachments, :category).all
case @sort_by
when 'date'
@grouped = documents.group_by {|d| d.updated_on.to_date }
when 'title'
@grouped = documents.group_by {|d| d.title.first.upcase}
when 'author'
@grouped = documents.select{|d| d.attachments.any?}.group_by {|d| d.attachments.last.author}
else
@grouped = documents.group_by(&:category)
end
@document = @project.documents.build
if @project.project_type == 1
render :layout => 'base_courses'
else
render :layout => false if request.xhr?
end
end
def show
@attachments = @document.attachments.all
if @project.project_type ==1
render :action => 'show', :layout => 'base_courses'
end
end
def new
@document = @project.documents.build
@document.safe_attributes = params[:document]
end
def create
@document = @project.documents.build
@document.safe_attributes = params[:document]
@document.user = User.current
@document.save_attachments(params[:attachments])
if @document.save
render_attachment_warning_if_needed(@document)
flash[:notice] = l(:notice_successful_create)
redirect_to project_documents_path(@project)
else
render :action => 'new'
end
end
def edit
end
def update
@document.safe_attributes = params[:document]
if request.put? and @document.save
flash[:notice] = l(:notice_successful_update)
redirect_to document_path(@document)
else
render :action => 'edit'
end
end
def destroy
@document.destroy if request.delete?
redirect_to project_documents_path(@project)
end
def add_attachment
attachments = Attachment.attach_files(@document, params[:attachments])
render_attachment_warning_if_needed(@document)
if attachments.present? && attachments[:files].present? && Setting.notified_events.include?('document_added')
Mailer.attachments_added(attachments[:files]).deliver
end
redirect_to document_path(@document)
end
end
# Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class DocumentsController < ApplicationController
layout 'base_projects'#by young
default_search_scope :documents
model_object Document
before_filter :find_project_by_project_id, :only => [:index, :new, :create]
before_filter :find_model_object, :except => [:index, :new, :create]
before_filter :find_project_from_association, :except => [:index, :new, :create]
before_filter :authorize , :except => [:index]#Added by young
before_filter :authorize_document
helper :attachments
helper :project_score
def index
@sort_by = %w(category date title author).include?(params[:sort_by]) ? params[:sort_by] : 'category'
temp = @project.documents.includes(:attachments, :category).all
documents = []
temp.each do |doc|
if doc.has_right?(@project)
documents << doc
end
end
case @sort_by
when 'date'
@grouped = documents.group_by {|d| d.updated_on.to_date }
when 'title'
@grouped = documents.group_by {|d| d.title.first.upcase}
when 'author'
# @grouped = documents.select{|d| d.attachments.any?}.group_by {|d| d.attachments.last.author}
@grouped = documents.group_by(&:user)
else
@grouped = documents.group_by(&:category)
end
@document = @project.documents.build
if @project.project_type == 1
render :layout => 'base_courses'
else
render :layout => false if request.xhr?
end
end
def show
@attachments = @document.attachments.all
if @project.project_type ==1
render :action => 'show', :layout => 'base_courses'
end
end
def new
@document = @project.documents.build
@document.safe_attributes = params[:document]
end
def create
@document = @project.documents.build
@document.safe_attributes = params[:document]
@document.user = User.current
@document.save_attachments(params[:attachments])
if @document.save
render_attachment_warning_if_needed(@document)
flash[:notice] = l(:notice_successful_create)
redirect_to project_documents_url(@project)
else
render :action => 'new'
end
end
def edit
end
def update
@document.safe_attributes = params[:document]
if request.put? and @document.save
flash[:notice] = l(:notice_successful_update)
redirect_to document_url(@document)
else
render :action => 'edit'
end
end
def destroy
@document.destroy if request.delete?
redirect_to project_documents_url(@project)
end
def add_attachment
attachments = Attachment.attach_files(@document, params[:attachments])
render_attachment_warning_if_needed(@document)
if attachments.present? && attachments[:files].present? && Setting.notified_events.include?('document_added')
Mailer.attachments_added(attachments[:files]).deliver
end
redirect_to document_url(@document)
end
# 权限判断
# add by nwb
def authorize_document
if !(User.current.admin? || User.current.member_of?(@project) || @document == nil || (@document != nil && @document.is_public==1))
render_403 :message => :notice_not_authorized
end
end
end

@ -1,98 +1,98 @@
# Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class EnumerationsController < ApplicationController
layout 'admin'
before_filter :require_admin, :except => :index
before_filter :require_admin_or_api_request, :only => :index
before_filter :build_new_enumeration, :only => [:new, :create]
before_filter :find_enumeration, :only => [:edit, :update, :destroy]
accept_api_auth :index
helper :custom_fields
def index
respond_to do |format|
format.html
format.api {
@klass = Enumeration.get_subclass(params[:type])
if @klass
@enumerations = @klass.shared.sorted.all
else
render_404
end
}
end
end
def new
end
def create
if request.post? && @enumeration.save
flash[:notice] = l(:notice_successful_create)
redirect_to enumerations_path
else
render :action => 'new'
end
end
def edit
end
def update
if request.put? && @enumeration.update_attributes(params[:enumeration])
flash[:notice] = l(:notice_successful_update)
redirect_to enumerations_path
else
render :action => 'edit'
end
end
def destroy
if !@enumeration.in_use?
# No associated objects
@enumeration.destroy
redirect_to enumerations_path
return
elsif params[:reassign_to_id]
if reassign_to = @enumeration.class.find_by_id(params[:reassign_to_id])
@enumeration.destroy(reassign_to)
redirect_to enumerations_path
return
end
end
@enumerations = @enumeration.class.all - [@enumeration]
end
private
def build_new_enumeration
class_name = params[:enumeration] && params[:enumeration][:type] || params[:type]
@enumeration = Enumeration.new_subclass_instance(class_name, params[:enumeration])
if @enumeration.nil?
render_404
end
end
def find_enumeration
@enumeration = Enumeration.find(params[:id])
rescue ActiveRecord::RecordNotFound
render_404
end
end
# Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class EnumerationsController < ApplicationController
layout 'admin'
before_filter :require_admin, :except => :index
before_filter :require_admin_or_api_request, :only => :index
before_filter :build_new_enumeration, :only => [:new, :create]
before_filter :find_enumeration, :only => [:edit, :update, :destroy]
accept_api_auth :index
helper :custom_fields
def index
respond_to do |format|
format.html
format.api {
@klass = Enumeration.get_subclass(params[:type])
if @klass
@enumerations = @klass.shared.sorted.all
else
render_404
end
}
end
end
def new
end
def create
if request.post? && @enumeration.save
flash[:notice] = l(:notice_successful_create)
redirect_to enumerations_url
else
render :action => 'new'
end
end
def edit
end
def update
if request.put? && @enumeration.update_attributes(params[:enumeration])
flash[:notice] = l(:notice_successful_update)
redirect_to enumerations_url
else
render :action => 'edit'
end
end
def destroy
if !@enumeration.in_use?
# No associated objects
@enumeration.destroy
redirect_to enumerations_url
return
elsif params[:reassign_to_id]
if reassign_to = @enumeration.class.find_by_id(params[:reassign_to_id])
@enumeration.destroy(reassign_to)
redirect_to enumerations_url
return
end
end
@enumerations = @enumeration.class.all - [@enumeration]
end
private
def build_new_enumeration
class_name = params[:enumeration] && params[:enumeration][:type] || params[:type]
@enumeration = Enumeration.new_subclass_instance(class_name, params[:enumeration])
if @enumeration.nil?
render_404
end
end
def find_enumeration
@enumeration = Enumeration.find(params[:id])
rescue ActiveRecord::RecordNotFound
render_404
end
end

@ -1,189 +1,412 @@
# Redmine - project management software
# Copyright (C) 2006-2013 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 FilesController < ApplicationController
layout 'base_projects'#by young
menu_item :files
before_filter :find_project_by_project_id#, :except => [:getattachtype]
before_filter :authorize, :except => [:getattachtype]
helper :sort
include SortHelper
def index
#sort_init 'filename', 'asc'
sort_init 'created_on', 'desc'
sort_update 'created_on' => "#{Attachment.table_name}.created_on",
'filename' => "#{Attachment.table_name}.filename",
'size' => "#{Attachment.table_name}.filesize",
'downloads' => "#{Attachment.table_name}.downloads"
if params[:project_id]
@isproject = true
@containers = [ Project.includes(:attachments).reorder("#{Attachment.table_name}.created_on DESC").find(@project.id)]
@containers += @project.versions.includes(:attachments).reorder("#{Attachment.table_name}.created_on DESC").all.sort
render :layout => !request.xhr?
elsif params[:course_id]
@isproject = false
@containers = [ Course.includes(:attachments).reorder("#{Attachment.table_name}.created_on DESC").find(@course.id)]
render :layout => 'base_courses'
end
end
def new
@versions = @project.versions.sort
@course_tag = @project.project_type
if @project.project_type == 1
render :layout => 'base_courses'
end
end
def create
if params[:add_tag]
@addTag=true
#render :back
tag_saveEx
#render :text =>"success"
respond_to do |format|
format.js
end
else
#modify by nwb
if @project
@addTag=false
container = (params[:version_id].blank? ? @project : @project.versions.find_by_id(params[:version_id]))
attachments = Attachment.attach_filesex(container, params[:attachments], params[:attachment_type])
render_attachment_warning_if_needed(container)
if !attachments.empty? && !attachments[:files].blank? && Setting.notified_events.include?('file_added')
Mailer.attachments_added(attachments[:files]).deliver
end
# TODO: 临时用 nyan
sort_init 'created_on', 'desc'
sort_update 'created_on' => "#{Attachment.table_name}.created_on",
'filename' => "#{Attachment.table_name}.filename",
'size' => "#{Attachment.table_name}.filesize",
'downloads' => "#{Attachment.table_name}.downloads"
@containers = [Project.includes(:attachments).reorder("#{Attachment.table_name}.created_on DESC").find(@project.id)] #modify by Long Jun
@containers += @project.versions.includes(:attachments).reorder("#{Attachment.table_name}.created_on DESC").all.sort
@attachtype = 0
@contenttype = 0
respond_to do |format|
format.js
format.html {
redirect_to project_files_path(@project)
}
end
elsif @course
@addTag=false
attachments = Attachment.attach_filesex(@course, params[:attachments], params[:attachment_type])
if !attachments.empty? && !attachments[:files].blank? && Setting.notified_events.include?('file_added')
Mailer.attachments_added(attachments[:files]).deliver
end
# TODO: 临时用 nyan
sort_init 'created_on', 'desc'
sort_update 'created_on' => "#{Attachment.table_name}.created_on",
'filename' => "#{Attachment.table_name}.filename",
'size' => "#{Attachment.table_name}.filesize",
'downloads' => "#{Attachment.table_name}.downloads"
@containers = [Course.includes(:attachments).reorder("#{Attachment.table_name}.created_on DESC").find(@course.id)]
@attachtype = 0
@contenttype = 0
respond_to do |format|
format.js
format.html {
redirect_to course_files_path(@course)
}
end
end
end
end
def tag_saveEx
@tags = params[:tag_name][:name]
@obj_id = params[:object_id]
@obj_flag = params[:object_flag]
case @obj_flag
when '1' then
@obj = User.find_by_id(@obj_id)
when '2' then
@obj = Project.find_by_id(@obj_id)
when '3' then
@obj = Issue.find_by_id(@obj_id)
when '4' then
@obj = Bid.find_by_id(@obj_id)
when '5' then
@obj = Forum.find_by_id(@obj_id)
when '6'
@obj = Attachment.find_by_id(@obj_id)
when '7' then
@obj = Contest.find_by_id(@obj_id)
when '8'
@obj = OpenSourceProject.find_by_id(@obj_id)
when '9'
@obj = Course.find_by_id(@obj_id)
else
@obj = nil
end
unless @obj.nil?
@obj.tag_list.add(@tags.split(","))
else
return
end
if @obj.save
## 执行成功的操作。
else
#捕获异常
end
end
# 返回制定资源类型的资源列表
# added by nwb
def getattachtype
sort_init 'created_on', 'desc'
sort_update 'created_on' => "#{Attachment.table_name}.created_on",
'filename' => "#{Attachment.table_name}.filename",
'size' => "#{Attachment.table_name}.filesize",
'downloads' => "#{Attachment.table_name}.downloads"
if @project
@containers = [ Project.includes(:attachments).reorder("#{Attachment.table_name}.created_on DESC").find(@project.id)]
@containers += @project.versions.includes(:attachments).reorder("#{Attachment.table_name}.created_on DESC").all.sort
elsif @course
@containers = [ Course.includes(:attachments).reorder("#{Attachment.table_name}.created_on DESC").find(@course.id)]
end
@attachtype = params[:type].to_i
@contenttype = params[:contentType].to_s
respond_to do |format|
format.js
end
end
end
# Redmine - project management software
# Copyright (C) 2006-2013 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 FilesController < ApplicationController
layout 'base_projects' #by young
menu_item :files
before_filter :find_project_by_project_id#, :except => [:getattachtype]
before_filter :authorize, :except => [:getattachtype,:quote_resource_show,:search]
helper :sort
include SortHelper
include FilesHelper
helper :project_score
include CoursesHelper
def show_attachments obj
@attachments = []
obj.each do |container|
@attachments += container.attachments
end
@all_attachments = visable_attachemnts(@attachments)
@limit = 10
@feedback_count = @all_attachments.count
@feedback_pages = Paginator.new @feedback_count, @limit, params['page']
@offset ||= @feedback_pages.offset
@curse_attachments_all = @all_attachments[@offset, @limit]
@curse_attachments = paginateHelper @all_attachments,10
end
def search
sort = ""
@sort = ""
@order = ""
@is_remote = true
if params[:sort]
order_by = params[:sort].split(":")
@sort = order_by[0]
if order_by.count > 1
@order = order_by[1]
end
sort = "#{@sort} #{@order}"
end
begin
q = "%#{params[:name].strip}%"
#(redirect_to stores_url, :notice => l(:label_sumbit_empty);return) if params[:name].blank?
if params[:insite]
@result = find_public_attache q,sort
@result = visable_attachemnts_insite @result,@course
@searched_attach = paginateHelper @result,10
else
@result = find_course_attache q,@course,sort
@result = visable_attachemnts @result
@searched_attach = paginateHelper @result,10
end
#rescue Exception => e
# #render 'stores'
# redirect_to search_course_files_url
end
end
def find_course_attache keywords,course,sort = ""
if sort == ""
sort = "created_on DESC"
end
resultSet = Attachment.where("attachments.container_type = 'Course' And attachments.container_id = '#{course.id}' AND filename LIKE :like ", like: "%#{keywords}%").
reorder(sort)
#resultSet = Attachment.find_by_sql("SELECT `attachments`.* FROM `attachments` LEFT OUTER JOIN `homework_attaches` ON `attachments`.container_type = 'HomeworkAttach' AND `attachments`.container_id = `homework_attaches`.id LEFT OUTER JOIN `homework_for_courses` ON `homework_attaches`.bid_id = `homework_for_courses`.bid_id LEFT OUTER JOIN `homework_for_courses` AS H_C ON `attachments`.container_type = 'Bid' AND `attachments`.container_id = H_C.bid_id WHERE (`homework_for_courses`.course_id = 117 OR H_C.course_id = 117 OR (`attachments`.container_type = 'Course' AND `attachments`.container_id = 117)) AND `attachments`.filename LIKE '%#{keywords}%'").reorder("created_on DESC")
end
def find_public_attache keywords,sort = ""
# StoresController#search 将每条文件都查出来,再次进行判断过滤。---> resultSet.to_a.map
# 此时内容不多速度还可但文件增长每条判断多则进行3-4次表连接。
# 现在还木有思路 药丸
if sort == ""
sort = "created_on DESC"
end
resultSet = Attachment.where("attachments.container_type IS NOT NULL AND attachments.copy_from IS NULL AND filename LIKE :like ", like: "%#{keywords}%").
reorder(sort)
end
def index
#sort_init 'filename', 'asc'
sort_init 'created_on', 'desc'
sort_update 'created_on' => "#{Attachment.table_name}.created_on",
'filename' => "#{Attachment.table_name}.filename",
'size' => "#{Attachment.table_name}.filesize",
'downloads' => "#{Attachment.table_name}.downloads"
sort = ""
@sort = ""
@order = ""
@is_remote = false
if params[:project_id]
@isproject = true
if params[:sort]
params[:sort].split(",").each do |sort_type|
order_by = sort_type.split(":")
case order_by[0]
when "filename"
attribute = "filename"
when "size"
attribute = "filesize"
when "attach_type"
attribute = "attachtype"
when "content_type"
attribute = "created_on"
when "field_file_dense"
attribute = "is_public"
when "downloads"
attribute = "downloads"
when "created_on"
attribute = "created_on"
end
if order_by.count == 1
sort += "#{Attachment.table_name}.#{attribute} asc " if attribute
elsif order_by.count == 2
sort += "#{Attachment.table_name}.#{attribute} #{order_by[1]} " if attribute && order_by[1]
end
if sort_type != params[:sort].split(",").last
sort += ","
end
end
end
@containers = [ Project.includes(:attachments).reorder(sort).find(@project.id)]
@containers += @project.versions.includes(:attachments).reorder(sort).all
show_attachments @containers
render :layout => !request.xhr?
elsif params[:course_id]
@isproject = false
if params[:sort]
params[:sort].split(",").each do |sort_type|
order_by = sort_type.split(":")
case order_by[0]
when "filename"
attribute = "filename"
when "size"
attribute = "filesize"
when "attach_type"
attribute = "attachtype"
when "content_type"
attribute = "created_on"
when "field_file_dense"
attribute = "is_public"
when "downloads"
attribute = "downloads"
when "created_on"
attribute = "created_on"
when "quotes"
attribute = "quotes"
end
@sort = order_by[0]
@order = order_by[1]
if order_by.count == 1 && attribute
sort += "#{Attachment.table_name}.#{attribute} asc "
if sort_type != params[:sort].split(",").last
sort += ","
end
elsif order_by.count == 2 && order_by[1]
sort += "#{Attachment.table_name}.#{attribute} #{order_by[1]} "
if sort_type != params[:sort].split(",").last
sort += ","
end
end
end
end
@containers = [ Course.includes(:attachments).reorder(sort).find(@course.id)]
show_attachments @containers
render :layout => 'base_courses'
end
end
def quote_resource_show
@file = Attachment.find(params[:id])
@can_quote = attachment_candown @file
end
def new
@versions = @project.versions.sort
@course_tag = @project.project_type
if @project.project_type == 1
render :layout => 'base_courses'
end
end
def create
if params[:add_tag]
@addTag=true
#render :back
tag_saveEx
#render :text =>"success"
respond_to do |format|
format.js
end
else
#modify by nwb
if @project
@addTag=false
container = (params[:version_id].blank? ? @project : @project.versions.find_by_id(params[:version_id]))
attachments = Attachment.attach_filesex(container, params[:attachments], params[:attachment_type])
render_attachment_warning_if_needed(container)
if !attachments.empty? && !attachments[:files].blank? && Setting.notified_events.include?('file_added')
Mailer.attachments_added(attachments[:files]).deliver
end
# TODO: 临时用 nyan
sort_init 'created_on', 'desc'
sort_update 'created_on' => "#{Attachment.table_name}.created_on",
'filename' => "#{Attachment.table_name}.filename",
'size' => "#{Attachment.table_name}.filesize",
'downloads' => "#{Attachment.table_name}.downloads"
@containers = [Project.includes(:attachments).reorder("#{Attachment.table_name}.created_on DESC").find(@project.id)] #modify by Long Jun
@containers += @project.versions.includes(:attachments).reorder("#{Attachment.table_name}.created_on DESC").all.sort
show_attachments @containers
@attachtype = 0
@contenttype = 0
respond_to do |format|
format.js
format.html {
redirect_to project_files_url(@project)
}
end
elsif @course
@addTag=false
attachments = Attachment.attach_filesex(@course, params[:attachments], params[:attachment_type])
if !attachments.empty? && !attachments[:files].blank? && Setting.notified_events.include?('file_added')
Mailer.attachments_added(attachments[:files]).deliver
end
# TODO: 临时用 nyan
sort_init 'created_on', 'desc'
sort_update 'created_on' => "#{Attachment.table_name}.created_on",
'filename' => "#{Attachment.table_name}.filename",
'size' => "#{Attachment.table_name}.filesize",
'downloads' => "#{Attachment.table_name}.downloads"
@containers = [Course.includes(:attachments).reorder("#{Attachment.table_name}.created_on DESC").find(@course.id)]
show_attachments @containers
@attachtype = 0
@contenttype = 0
respond_to do |format|
format.js
format.html {
redirect_to course_files_url(@course)
}
end
end
end
end
def tag_saveEx
@tags = params[:tag_name][:name]
@obj_id = params[:object_id]
@obj_flag = params[:object_flag]
case @obj_flag
when '1' then
@obj = User.find_by_id(@obj_id)
when '2' then
@obj = Project.find_by_id(@obj_id)
when '3' then
@obj = Issue.find_by_id(@obj_id)
when '4' then
@obj = Bid.find_by_id(@obj_id)
when '5' then
@obj = Forum.find_by_id(@obj_id)
when '6'
@obj = Attachment.find_by_id(@obj_id)
when '7' then
@obj = Contest.find_by_id(@obj_id)
when '8'
@obj = OpenSourceProject.find_by_id(@obj_id)
when '9'
@obj = Course.find_by_id(@obj_id)
else
@obj = nil
end
unless @obj.nil?
@obj.tag_list.add(@tags.split(","))
else
return
end
if @obj.save
## 执行成功的操作。
else
#捕获异常
end
end
# 返回指定资源类型的资源列表
# added by nwb
def getattachtype
sort_init 'created_on', 'desc'
sort_update 'created_on' => "#{Attachment.table_name}.created_on",
'filename' => "#{Attachment.table_name}.filename",
'size' => "#{Attachment.table_name}.filesize",
'downloads' => "#{Attachment.table_name}.downloads"
sort=''
if params[:sort]
params[:sort].split(",").each do |sort_type|
order_by = sort_type.split(":")
case order_by[0]
when "filename"
attribute = "filename"
when "size"
attribute = "filesize"
when "attach_type"
attribute = "attachtype"
when "content_type"
attribute = "created_on"
when "field_file_dense"
attribute = "is_public"
when "downloads"
attribute = "downloads"
when "created_on"
attribute = "created_on"
end
if order_by.count == 1
sort += "#{Attachment.table_name}.#{attribute} asc "
elsif order_by.count == 2
sort += "#{Attachment.table_name}.#{attribute} #{order_by[1]} "
end
if sort_type != params[:sort].split(",").last
sort += ","
end
end
end
if @project
@isproject = true
@containers = [ Project.includes(:attachments).reorder("#{Attachment.table_name}.created_on DESC").find(@project.id)]
@containers += @project.versions.includes(:attachments).reorder(sort).all
show_attachments @containers
@attachtype = params[:type].to_i
@contenttype = params[:contentType].to_s
respond_to do |format|
format.js
format.html {
render :layout => 'base_projects'
}
end
elsif @course
@isproject = false
@containers = [ Course.includes(:attachments).reorder(sort).find(@course.id)]
show_attachments @containers
@attachtype = params[:type].to_i
@contenttype = params[:contentType].to_s
# render layout: 'base_courses'
respond_to do |format|
format.js
format.html {
render :layout => 'base_courses'
}
end
else
show_attachments @containers
@attachtype = params[:type].to_i
@contenttype = params[:contentType].to_s
respond_to do |format|
format.js
format.html
end
end
end
end

@ -1,225 +1,232 @@
# added by fq
class ForumsController < ApplicationController
# GET /forums
# GET /forums.json
before_filter :find_forum_if_available
before_filter :authenticate_user_edit, :only => [:edit, :update]
before_filter :authenticate_user_destroy, :only => [:destroy]
before_filter :require_login, :only => [:new, :create]
helper :sort
include SortHelper
PageLimit = 20
def create_memo
@memo = Memo.new(params[:memo])
@memo.forum_id = @forum.id
@memo.author_id = User.current.id
@memo.save_attachments(params[:attachments] || (params[:memo] && params[:memo][:uploads]))
respond_to do |format|
if @memo.save
format.html { redirect_to (forum_memo_path(@forum, (@memo.parent_id.nil? ? @memo : @memo.parent_id))), notice: "#{l :label_memo_create_succ}" }
format.json { render json: @memo, status: :created, location: @memo }
else
sort_init 'updated_at', 'desc'
sort_update 'created_at' => "#{Memo.table_name}.created_at",
'replies' => "#{Memo.table_name}.replies_count",
'updated_at' => "COALESCE (last_replies_memos.created_at, #{Memo.table_name}.created_at)"
@topic_count = @forum.topics.count
@topic_pages = Paginator.new @topic_count, per_page_option, params['page']
@memos = @forum.topics.
reorder("#{Memo.table_name}.sticky DESC").
includes(:last_reply).
limit(@topic_pages.per_page).
offset(@topic_pages.offset).
order(sort_clause).
preload(:author, {:last_reply => :author}).
all
flash.now[:error] = "#{l :label_memo_create_fail}: #{@memo.errors.full_messages[0]}"
# back_error_page = @memo.parent_id.nil? ? forum_path(@forum) : forum_memo_path(@forum, @memo.parent_id)
format.html { render action: :show, layout: 'base_forums' }#, error: "#{l :label_memo_create_fail}: #{@memo.errors.full_messages[0]}" }
format.json { render json: @memo.errors, status: :unprocessable_entity }
end
end
end
def index
@offset, @limit = api_offset_and_limit({:limit => 10})
@forums_all = Forum.all
@forums_count = @forums_all.count
@forums_pages = Paginator.new @forums_count, @limit, params['page']
@offset ||= @forums_pages.offset
# @forums = @forums_all.offset(@offset).limit(@limit).all
@forums = Forum.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: @forums }
end
end
# GET /forums/1
# GET /forums/1.json
def show
sort_init 'updated_at', 'desc'
sort_update 'created_at' => "#{Memo.table_name}.created_at",
'replies' => "#{Memo.table_name}.replies_count",
'updated_at' => "COALESCE (last_replies_memos.created_at, #{Memo.table_name}.created_at)"
@memo = Memo.new(:forum => @forum)
@topic_count = @forum.topics.count
@topic_pages = Paginator.new @topic_count, per_page_option, params['page']
@memos = @forum.topics.
reorder("#{Memo.table_name}.sticky DESC").
includes(:last_reply).
limit(@topic_pages.per_page).
offset(@topic_pages.offset).
order(sort_clause).
preload(:author, {:last_reply => :author}).
all
# @offset, @limit = api_offset_and_limit({:limit => 10})
# @forum = Forum.find(params[:id])
# @memos_all = @forum.topics
# @topic_count = @memos_all.count
# @topic_pages = Paginator.new @topic_count, @limit, params['page']
# @offset ||= @topic_pages.offset
# @memos = @memos_all.offset(@offset).limit(@limit).all
respond_to do |format|
format.html {
render :layout => 'base_forums'
}# show.html.erb
format.json { render json: @forum }
end
end
# GET /forums/new
# GET /forums/new.json
def new
@forum = Forum.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: @forum }
end
end
# GET /forums/1/edit
def edit
@forum = Forum.find(params[:id])
end
# POST /forums
# POST /forums.json
def create
@forum = Forum.new(params[:forum])
@forum.creator_id = User.current.id
respond_to do |format|
if @forum.save
format.html { redirect_to @forum, notice: l(:label_forum_create_succ) }
format.json { render json: @forum, status: :created, location: @forum }
else
flash.now[:error] = "#{l :label_forum_create_fail}: #{@forum.errors.full_messages[0]}"
format.html { render action: "new" }
format.json { render json: @forum.errors, status: :unprocessable_entity }
end
end
end
# PUT /forums/1
# PUT /forums/1.json
def update
@forum = Forum.find(params[:id])
respond_to do |format|
if @forum.update_attributes(params[:forum])
format.html { redirect_to @forum, notice: 'Forum was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: @forum.errors, status: :unprocessable_entity }
end
end
end
# DELETE /forums/1
# DELETE /forums/1.json
def destroy
@forum = Forum.find(params[:id])
@forum.destroy
respond_to do |format|
format.html { redirect_to forums_url }
format.json { head :no_content }
end
end
def search_forum
# @forums = paginateHelper Forum.where("name LIKE '%#{params[:name]}%'")
name = params[:name]
(redirect_to forums_path, :notice => l(:label_sumbit_empty);return) if name.blank?
@offset, @limit = api_offset_and_limit({:limit => 10})
@forums_all = Forum.where("name LIKE '%#{params[:name]}%'")
@forums_count = @forums_all.count
@forums_pages = Paginator.new @forums_count, @limit, params['page']
@offset ||= @forums_pages.offset
@forums = @forums_all.offset(@offset).limit(@limit).all
respond_to do |format|
format.html {
render 'index'
}
format.json { render json: @forums }
end
end
def search_memo
limit = PageLimit
@memo = Memo.new
@offset, @limit = api_offset_and_limit({:limit => limit})
@forum = Forum.find(params[:id])
@memos_all = @forum.topics.where("subject LIKE '%#{params[:name]}%'")
@topic_count = @memos_all.count
@topic_pages = Paginator.new @topic_count, @limit, params['page']
@offset ||= @topic_pages.offset
@memos = @memos_all.offset(@offset).limit(@limit).all
respond_to do |format|
format.html {
render 'show', :layout => 'base_forums'
}
format.json { render json: @forum }
end
end
private
def find_forum_if_available
@forum = Forum.find(params[:id]) if params[:id]
rescue ActiveRecord::RecordNotFound
render_404
nil
end
def authenticate_user_edit
find_forum_if_available
render_403 unless @forum.editable_by? User.current
end
def authenticate_user_destroy
find_forum_if_available
render_403 unless @forum.destroyable_by? User.current
end
# added by fq
class ForumsController < ApplicationController
layout "users_base"
# GET /forums
# GET /forums.json
before_filter :find_forum_if_available
before_filter :authenticate_user_edit, :only => [:edit, :update]
before_filter :authenticate_user_destroy, :only => [:destroy]
before_filter :require_login, :only => [:new, :create]
helper :sort
include SortHelper
PageLimit = 20
def create_memo
@memo = Memo.new(params[:memo])
@memo.forum_id = @forum.id
@memo.author_id = User.current.id
@memo.save_attachments(params[:attachments] || (params[:memo] && params[:memo][:uploads]))
respond_to do |format|
if @memo.save
format.html { redirect_to (forum_memo_url(@forum, (@memo.parent_id.nil? ? @memo : @memo.parent_id))), notice: "#{l :label_memo_create_succ}" }
format.json { render json: @memo, status: :created, location: @memo }
else
sort_init 'updated_at', 'desc'
sort_update 'created_at' => "#{Memo.table_name}.created_at",
'replies' => "#{Memo.table_name}.replies_count",
'updated_at' => "COALESCE (last_replies_memos.created_at, #{Memo.table_name}.created_at)"
@topic_count = @forum.topics.count
@topic_pages = Paginator.new @topic_count, per_page_option, params['page']
@memos = @forum.topics.
reorder("#{Memo.table_name}.sticky DESC").
includes(:last_reply).
limit(@topic_pages.per_page).
offset(@topic_pages.offset).
order(sort_clause).
preload(:author, {:last_reply => :author}).
all
flash.now[:error] = "#{l :label_memo_create_fail}: #{@memo.errors.full_messages[0]}"
# back_error_page = @memo.parent_id.nil? ? forum_path(@forum) : forum_memo_path(@forum, @memo.parent_id)
format.html { render action: :show, layout: 'base_forums' }#, error: "#{l :label_memo_create_fail}: #{@memo.errors.full_messages[0]}" }
format.json { render json: @memo.errors, status: :unprocessable_entity }
end
end
end
def index
@offset, @limit = api_offset_and_limit({:limit => 10})
@forums_all = Forum.reorder("sticky DESC")
@forums_count = @forums_all.count
@forums_pages = Paginator.new @forums_count, @limit, params['page']
@offset ||= @forums_pages.offset
@forums = @forums_all.offset(@offset).limit(@limit).all
#@forums = Forum.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: @forums }
end
end
# GET /forums/1
# GET /forums/1.json
def show
sort_init 'updated_at', 'desc'
sort_update 'created_at' => "#{Memo.table_name}.created_at",
'replies' => "#{Memo.table_name}.replies_count",
'updated_at' => "COALESCE (last_replies_memos.created_at, #{Memo.table_name}.created_at)"
@memo = Memo.new(:forum => @forum)
@topic_count = @forum.topics.count
@topic_pages = Paginator.new @topic_count, per_page_option, params['page']
@memos = @forum.topics.
reorder("#{Memo.table_name}.sticky DESC").
includes(:last_reply).
limit(@topic_pages.per_page).
offset(@topic_pages.offset).
order(sort_clause).
preload(:author, {:last_reply => :author}).
all
# @offset, @limit = api_offset_and_limit({:limit => 10})
# @forum = Forum.find(params[:id])
# @memos_all = @forum.topics
# @topic_count = @memos_all.count
# @topic_pages = Paginator.new @topic_count, @limit, params['page']
# @offset ||= @topic_pages.offset
# @memos = @memos_all.offset(@offset).limit(@limit).all
respond_to do |format|
format.html {
render :layout => 'base_forums'
}# show.html.erb
format.json { render json: @forum }
end
end
# GET /forums/new
# GET /forums/new.json
def new
@forum = Forum.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: @forum }
end
end
# GET /forums/1/edit
def edit
@forum = Forum.find(params[:id])
end
# POST /forums
# POST /forums.json
def create
@forum = Forum.new(params[:forum])
@forum.creator_id = User.current.id
respond_to do |format|
if @forum.save
format.html { redirect_to @forum, notice: l(:label_forum_create_succ) }
format.json { render json: @forum, status: :created, location: @forum }
else
flash.now[:error] = "#{l :label_forum_create_fail}: #{@forum.errors.full_messages[0]}"
format.html { render action: "new" }
format.json { render json: @forum.errors, status: :unprocessable_entity }
end
end
end
# PUT /forums/1
# PUT /forums/1.json
def update
@forum = Forum.find(params[:id])
respond_to do |format|
if @forum.update_attributes(params[:forum])
format.html { redirect_to @forum, notice: l(:label_forum_update_succ) }
format.json { head :no_content }
else
flash.now[:error] = "#{l :label_forum_update_fail}: #{@forum.errors.full_messages[0]}"
format.html { render action: "edit" }
format.json { render json: @forum.errors, status: :unprocessable_entity }
end
end
end
# DELETE /forums/1
# DELETE /forums/1.json
def destroy
@forum = Forum.find(params[:id])
@forum.destroy
respond_to do |format|
format.html { redirect_to forums_url }
format.json { head :no_content }
end
end
def search_forum
# @forums = paginateHelper Forum.where("name LIKE '%#{params[:name]}%'")
q = "%#{params[:name].strip}%"
(redirect_to forums_url, :notice => l(:label_sumbit_empty);return) if params[:name].blank?
@offset, @limit = api_offset_and_limit({:limit => 10})
@forums_all = Forum.where("name LIKE ?", q)
@forums_count = @forums_all.count
@forums_pages = Paginator.new @forums_count, @limit, params['page']
@offset ||= @forums_pages.offset
@forums = @forums_all.offset(@offset).limit(@limit).all
respond_to do |format|
format.html {
render 'index'
}
format.json { render json: @forums }
end
end
def search_memo
q = "%#{params[:name].strip}%"
limit = PageLimit
@memo = Memo.new
@offset, @limit = api_offset_and_limit({:limit => limit})
@forum = Forum.find(params[:id])
@memos_all = @forum.topics.where("subject LIKE ?", q)
@topic_count = @memos_all.count
@topic_pages = Paginator.new @topic_count, @limit, params['page']
@offset ||= @topic_pages.offset
@memos = @memos_all.offset(@offset).limit(@limit).all
respond_to do |format|
format.html {
render 'show', :layout => 'base_forums'
}
format.json { render json: @forum }
end
end
private
def find_forum_if_available
@forum = Forum.find(params[:id]) if params[:id]
rescue ActiveRecord::RecordNotFound
render_404
nil
end
def authenticate_user_edit
find_forum_if_available
render_403 unless @forum.editable_by? User.current
end
def authenticate_user_destroy
find_forum_if_available
render_403 unless @forum.destroyable_by? User.current
end
end

@ -29,6 +29,7 @@ class GanttsController < ApplicationController
helper :sort
include SortHelper
include Redmine::Export::PDF
helper :project_score
def show
@gantt = Redmine::Helpers::Gantt.new(params)

@ -1,5 +1,6 @@
#added by baiyu
class GitUsageController < ApplicationController
layout "project_base"
def ch_usage
end

@ -1,141 +1,141 @@
# Redmine - project management software
# Copyright (C) 2006-2013 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 GroupsController < ApplicationController
layout 'admin'
before_filter :require_admin
before_filter :find_group, :except => [:index, :new, :create]
accept_api_auth :index, :show, :create, :update, :destroy, :add_users, :remove_user
helper :custom_fields
def index
@groups = Group.sorted.all
respond_to do |format|
format.html
format.api
end
end
def show
respond_to do |format|
format.html
format.api
end
end
def new
@group = Group.new
end
def create
@group = Group.new
@group.safe_attributes = params[:group]
respond_to do |format|
if @group.save
format.html {
flash[:notice] = l(:notice_successful_create)
redirect_to(params[:continue] ? new_group_path : groups_path)
}
format.api { render :action => 'show', :status => :created, :location => group_url(@group) }
else
format.html { render :action => "new" }
format.api { render_validation_errors(@group) }
end
end
end
def edit
end
def update
@group.safe_attributes = params[:group]
respond_to do |format|
if @group.save
flash[:notice] = l(:notice_successful_update)
format.html { redirect_to(groups_path) }
format.api { render_api_ok }
else
format.html { render :action => "edit" }
format.api { render_validation_errors(@group) }
end
end
end
def destroy
@group.destroy
respond_to do |format|
format.html { redirect_to(groups_path) }
format.api { render_api_ok }
end
end
def add_users
@users = User.find_all_by_id(params[:user_id] || params[:user_ids])
@group.users << @users if request.post?
respond_to do |format|
format.html { redirect_to edit_group_path(@group, :tab => 'users') }
format.js
format.api { render_api_ok }
end
end
def remove_user
@group.users.delete(User.find(params[:user_id])) if request.delete?
respond_to do |format|
format.html { redirect_to edit_group_path(@group, :tab => 'users') }
format.js
format.api { render_api_ok }
end
end
def autocomplete_for_user
respond_to do |format|
format.js
end
end
def edit_membership
@membership = Member.edit_membership(params[:membership_id], params[:membership], @group)
@membership.save if request.post?
respond_to do |format|
format.html { redirect_to edit_group_path(@group, :tab => 'memberships') }
format.js
end
end
def destroy_membership
Member.find(params[:membership_id]).destroy if request.post?
respond_to do |format|
format.html { redirect_to edit_group_path(@group, :tab => 'memberships') }
format.js
end
end
private
def find_group
@group = Group.find(params[:id])
rescue ActiveRecord::RecordNotFound
render_404
end
end
# Redmine - project management software
# Copyright (C) 2006-2013 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 GroupsController < ApplicationController
layout 'admin'
before_filter :require_admin
before_filter :find_group, :except => [:index, :new, :create]
accept_api_auth :index, :show, :create, :update, :destroy, :add_users, :remove_user
helper :custom_fields
def index
@groups = Group.sorted.all
respond_to do |format|
format.html
format.api
end
end
def show
respond_to do |format|
format.html
format.api
end
end
def new
@group = Group.new
end
def create
@group = Group.new
@group.safe_attributes = params[:group]
respond_to do |format|
if @group.save
format.html {
flash[:notice] = l(:notice_successful_create)
redirect_to(params[:continue] ? new_group_url : groups_url)
}
format.api { render :action => 'show', :status => :created, :location => group_url(@group) }
else
format.html { render :action => "new" }
format.api { render_validation_errors(@group) }
end
end
end
def edit
end
def update
@group.safe_attributes = params[:group]
respond_to do |format|
if @group.save
flash[:notice] = l(:notice_successful_update)
format.html { redirect_to(groups_url) }
format.api { render_api_ok }
else
format.html { render :action => "edit" }
format.api { render_validation_errors(@group) }
end
end
end
def destroy
@group.destroy
respond_to do |format|
format.html { redirect_to(groups_url) }
format.api { render_api_ok }
end
end
def add_users
@users = User.find_all_by_id(params[:user_id] || params[:user_ids])
@group.users << @users if request.post?
respond_to do |format|
format.html { redirect_to edit_group_url(@group, :tab => 'users') }
format.js
format.api { render_api_ok }
end
end
def remove_user
@group.users.delete(User.find(params[:user_id])) if request.delete?
respond_to do |format|
format.html { redirect_to edit_group_url(@group, :tab => 'users') }
format.js
format.api { render_api_ok }
end
end
def autocomplete_for_user
respond_to do |format|
format.js
end
end
def edit_membership
@membership = Member.edit_membership(params[:membership_id], params[:membership], @group)
@membership.save if request.post?
respond_to do |format|
format.html { redirect_to edit_group_url(@group, :tab => 'memberships') }
format.js
end
end
def destroy_membership
Member.find(params[:membership_id]).destroy if request.post?
respond_to do |format|
format.html { redirect_to edit_group_url(@group, :tab => 'memberships') }
format.js
end
end
private
def find_group
@group = Group.find(params[:id])
rescue ActiveRecord::RecordNotFound
render_404
end
end

File diff suppressed because it is too large Load Diff

@ -1,129 +1,132 @@
# Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class IssueCategoriesController < ApplicationController
menu_item :settings
model_object IssueCategory
before_filter :find_model_object, :except => [:index, :new, :create]
#before_filter :find_model_object_contest, :except => [:index, :new, :create]
before_filter :find_project_from_association, :except => [:index, :new, :create]
before_filter :find_project_by_project_id, :only => [:index, :new, :create]
before_filter :authorize
accept_api_auth :index, :show, :create, :update, :destroy
def index
respond_to do |format|
format.html { redirect_to_settings_in_projects }
format.api { @categories = @project.issue_categories.all }
end
end
def show
respond_to do |format|
format.html { redirect_to_settings_in_projects }
format.api
end
end
def new
@category = @project.issue_categories.build
@category.safe_attributes = params[:issue_category]
respond_to do |format|
format.html{render :layout => 'base_projects'}# by young
format.js
end
end
def create
@category = @project.issue_categories.build
@category.safe_attributes = params[:issue_category]
if @category.save
respond_to do |format|
format.html do
flash[:notice] = l(:notice_successful_create)
redirect_to_settings_in_projects
end
format.js
format.api { render :action => 'show', :status => :created, :location => issue_category_path(@category) }
end
else
respond_to do |format|
format.html { render :action => 'new'}
format.js { render :action => 'new'}
format.api { render_validation_errors(@category) }
end
end
end
def edit
end
def update
@category.safe_attributes = params[:issue_category]
if @category.save
respond_to do |format|
format.html {
flash[:notice] = l(:notice_successful_update)
redirect_to_settings_in_projects
}
format.api { render_api_ok }
end
else
respond_to do |format|
format.html { render :action => 'edit' }
format.api { render_validation_errors(@category) }
end
end
end
def destroy
@issue_count = @category.issues.size
if @issue_count == 0 || params[:todo] || api_request?
reassign_to = nil
if params[:reassign_to_id] && (params[:todo] == 'reassign' || params[:todo].blank?)
reassign_to = @project.issue_categories.find_by_id(params[:reassign_to_id])
end
@category.destroy(reassign_to)
respond_to do |format|
format.html { redirect_to_settings_in_projects }
format.api { render_api_ok }
end
return
end
@categories = @project.issue_categories - [@category]
end
private
def redirect_to_settings_in_projects
redirect_to settings_project_path(@project, :tab => 'categories')
end
# Wrap ApplicationController's find_model_object method to set
# @category instead of just @issue_category
def find_model_object
super
@category = @object
end
def find_model_object_contest
super
@category = @object
end
end
# Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class IssueCategoriesController < ApplicationController
layout "project_base"
menu_item :settings
model_object IssueCategory
before_filter :find_model_object, :except => [:index, :new, :create]
#before_filter :find_model_object_contest, :except => [:index, :new, :create]
before_filter :find_project_from_association, :except => [:index, :new, :create]
before_filter :find_project_by_project_id, :only => [:index, :new, :create]
before_filter :authorize
accept_api_auth :index, :show, :create, :update, :destroy
helper :project_score
def index
respond_to do |format|
format.html { redirect_to_settings_in_projects }
format.api { @categories = @project.issue_categories.all }
end
end
def show
respond_to do |format|
format.html { redirect_to_settings_in_projects }
format.api
end
end
def new
@category = @project.issue_categories.build
@category.safe_attributes = params[:issue_category]
respond_to do |format|
format.html{render :layout => 'base_projects'}# by young
format.js
end
end
def create
@category = @project.issue_categories.build
@category.safe_attributes = params[:issue_category]
if @category.save
respond_to do |format|
format.html do
flash[:notice] = l(:notice_successful_create)
redirect_to_settings_in_projects
end
format.js
format.api { render :action => 'show', :status => :created, :location => issue_category_path(@category) }
end
else
respond_to do |format|
format.html { render :action => 'new'}
format.js { render :action => 'new'}
format.api { render_validation_errors(@category) }
end
end
end
def edit
end
def update
@category.safe_attributes = params[:issue_category]
if @category.save
respond_to do |format|
format.html {
flash[:notice] = l(:notice_successful_update)
redirect_to_settings_in_projects
}
format.api { render_api_ok }
end
else
respond_to do |format|
format.html { render :action => 'edit' }
format.api { render_validation_errors(@category) }
end
end
end
def destroy
@issue_count = @category.issues.size
if @issue_count == 0 || params[:todo] || api_request?
reassign_to = nil
if params[:reassign_to_id] && (params[:todo] == 'reassign' || params[:todo].blank?)
reassign_to = @project.issue_categories.find_by_id(params[:reassign_to_id])
end
@category.destroy(reassign_to)
respond_to do |format|
format.html { redirect_to_settings_in_projects }
format.api { render_api_ok }
end
return
end
@categories = @project.issue_categories - [@category]
end
private
def redirect_to_settings_in_projects
redirect_to settings_project_url(@project, :tab => 'categories')
end
# Wrap ApplicationController's find_model_object method to set
# @category instead of just @issue_category
def find_model_object
super
@category = @object
end
def find_model_object_contest
super
@category = @object
end
end

@ -1,88 +1,88 @@
# Redmine - project management software
# Copyright (C) 2006-2013 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 IssueRelationsController < ApplicationController
before_filter :find_issue, :find_project_from_association, :authorize, :only => [:index, :create]
before_filter :find_relation, :except => [:index, :create]
accept_api_auth :index, :show, :create, :destroy
def index
@relations = @issue.relations
respond_to do |format|
format.html { render :nothing => true }
format.api
end
end
def show
raise Unauthorized unless @relation.visible?
respond_to do |format|
format.html { render :nothing => true }
format.api
end
end
def create
@relation = IssueRelation.new(params[:relation])
@relation.issue_from = @issue
if params[:relation] && m = params[:relation][:issue_to_id].to_s.strip.match(/^#?(\d+)$/)
@relation.issue_to = Issue.visible.find_by_id(m[1].to_i)
end
saved = @relation.save
respond_to do |format|
format.html { redirect_to issue_path(@issue) }
format.js {
@relations = @issue.reload.relations.select {|r| r.other_issue(@issue) && r.other_issue(@issue).visible? }
}
format.api {
if saved
render :action => 'show', :status => :created, :location => relation_url(@relation)
else
render_validation_errors(@relation)
end
}
end
end
def destroy
raise Unauthorized unless @relation.deletable?
@relation.destroy
respond_to do |format|
format.html { redirect_to issue_path(@relation.issue_from) }
format.js
format.api { render_api_ok }
end
end
private
def find_issue
@issue = @object = Issue.find(params[:issue_id])
rescue ActiveRecord::RecordNotFound
render_404
end
def find_relation
@relation = IssueRelation.find(params[:id])
rescue ActiveRecord::RecordNotFound
render_404
end
end
# Redmine - project management software
# Copyright (C) 2006-2013 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 IssueRelationsController < ApplicationController
before_filter :find_issue, :find_project_from_association, :authorize, :only => [:index, :create]
before_filter :find_relation, :except => [:index, :create]
accept_api_auth :index, :show, :create, :destroy
def index
@relations = @issue.relations
respond_to do |format|
format.html { render :nothing => true }
format.api
end
end
def show
raise Unauthorized unless @relation.visible?
respond_to do |format|
format.html { render :nothing => true }
format.api
end
end
def create
@relation = IssueRelation.new(params[:relation])
@relation.issue_from = @issue
if params[:relation] && m = params[:relation][:issue_to_id].to_s.strip.match(/^#?(\d+)$/)
@relation.issue_to = Issue.visible.find_by_id(m[1].to_i)
end
saved = @relation.save
respond_to do |format|
format.html { redirect_to issue_url(@issue) }
format.js {
@relations = @issue.reload.relations.select {|r| r.other_issue(@issue) && r.other_issue(@issue).visible? }
}
format.api {
if saved
render :action => 'show', :status => :created, :location => relation_url(@relation)
else
render_validation_errors(@relation)
end
}
end
end
def destroy
raise Unauthorized unless @relation.deletable?
@relation.destroy
respond_to do |format|
format.html { redirect_to issue_url(@relation.issue_from) }
format.js
format.api { render_api_ok }
end
end
private
def find_issue
@issue = @object = Issue.find(params[:issue_id])
rescue ActiveRecord::RecordNotFound
render_404
end
def find_relation
@relation = IssueRelation.find(params[:id])
rescue ActiveRecord::RecordNotFound
render_404
end
end

@ -1,81 +1,81 @@
# Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class IssueStatusesController < ApplicationController
layout 'admin'
before_filter :require_admin, :except => :index
before_filter :require_admin_or_api_request, :only => :index
accept_api_auth :index
def index
respond_to do |format|
format.html {
@issue_status_pages, @issue_statuses = paginate IssueStatus.sorted, :per_page => 25
render :action => "index", :layout => false if request.xhr?
}
format.api {
@issue_statuses = IssueStatus.all(:order => 'position')
}
end
end
def new
@issue_status = IssueStatus.new
end
def create
@issue_status = IssueStatus.new(params[:issue_status])
if request.post? && @issue_status.save
flash[:notice] = l(:notice_successful_create)
redirect_to issue_statuses_path
else
render :action => 'new'
end
end
def edit
@issue_status = IssueStatus.find(params[:id])
end
def update
@issue_status = IssueStatus.find(params[:id])
if request.put? && @issue_status.update_attributes(params[:issue_status])
flash[:notice] = l(:notice_successful_update)
redirect_to issue_statuses_path
else
render :action => 'edit'
end
end
def destroy
IssueStatus.find(params[:id]).destroy
redirect_to issue_statuses_path
rescue
flash[:error] = l(:error_unable_delete_issue_status)
redirect_to issue_statuses_path
end
def update_issue_done_ratio
if request.post? && IssueStatus.update_issue_done_ratios
flash[:notice] = l(:notice_issue_done_ratios_updated)
else
flash[:error] = l(:error_issue_done_ratios_not_updated)
end
redirect_to issue_statuses_path
end
end
# Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class IssueStatusesController < ApplicationController
layout 'admin'
before_filter :require_admin, :except => :index
before_filter :require_admin_or_api_request, :only => :index
accept_api_auth :index
def index
respond_to do |format|
format.html {
@issue_status_pages, @issue_statuses = paginate IssueStatus.sorted, :per_page => 25
render :action => "index", :layout => false if request.xhr?
}
format.api {
@issue_statuses = IssueStatus.all(:order => 'position')
}
end
end
def new
@issue_status = IssueStatus.new
end
def create
@issue_status = IssueStatus.new(params[:issue_status])
if request.post? && @issue_status.save
flash[:notice] = l(:notice_successful_create)
redirect_to issue_statuses_url
else
render :action => 'new'
end
end
def edit
@issue_status = IssueStatus.find(params[:id])
end
def update
@issue_status = IssueStatus.find(params[:id])
if request.put? && @issue_status.update_attributes(params[:issue_status])
flash[:notice] = l(:notice_successful_update)
redirect_to issue_statuses_url
else
render :action => 'edit'
end
end
def destroy
IssueStatus.find(params[:id]).destroy
redirect_to issue_statuses_url
rescue
flash[:error] = l(:error_unable_delete_issue_status)
redirect_to issue_statuses_url
end
def update_issue_done_ratio
if request.post? && IssueStatus.update_issue_done_ratios
flash[:notice] = l(:notice_issue_done_ratios_updated)
else
flash[:error] = l(:error_issue_done_ratios_not_updated)
end
redirect_to issue_statuses_url
end
end

@ -1,451 +1,480 @@
# Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class IssuesController < ApplicationController
layout 'base_projects'#Added by young
menu_item :new_issue, :only => [:new, :create]
default_search_scope :issues
before_filter :find_issue, :only => [:show, :edit, :update]
before_filter :find_issues, :only => [:bulk_edit, :bulk_update, :destroy]
before_filter :find_project, :only => [:new, :create, :update_form]
before_filter :authorize, :except => [:index]
before_filter :find_optional_project, :only => [:index]
before_filter :check_for_default_issue_status, :only => [:new, :create]
before_filter :build_new_issue_from_params, :only => [:new, :create, :update_form]
accept_rss_auth :index, :show
accept_api_auth :index, :show, :create, :update, :destroy
rescue_from Query::StatementInvalid, :with => :query_statement_invalid
helper :journals
helper :projects
include ProjectsHelper
helper :custom_fields
include CustomFieldsHelper
helper :issue_relations
include IssueRelationsHelper
helper :watchers
include WatchersHelper
helper :attachments
include AttachmentsHelper
helper :queries
include QueriesHelper
helper :repositories
include RepositoriesHelper
helper :sort
include SortHelper
include IssuesHelper
helper :timelog
include Redmine::Export::PDF
def index
retrieve_query
sort_init(@query.sort_criteria.empty? ? [['id', 'desc']] : @query.sort_criteria)
sort_update(@query.sortable_columns)
@query.sort_criteria = sort_criteria.to_a
@project_base_tag = (params[:project_id] || @issue.project) ? 'base_projects':'base'#by young
if @query.valid?
case params[:format]
when 'csv', 'pdf'
@limit = 10#Setting.issues_export_limit.to_i
when 'atom'
@limit = 10#Setting.feeds_limit.to_i
when 'xml', 'json'
@offset, @limit = api_offset_and_limit({:limit => 10})
else
@limit = 10#per_page_option
end
@issue_count = @query.issue_count
@issue_pages = Paginator.new @issue_count, @limit, params['page']
@offset ||= @issue_pages.offset
@issues = @query.issues(:include => [:assigned_to, :tracker, :priority, :category, :fixed_version],
:order => sort_clause,
:offset => @offset,
:limit => @limit)
@issue_count_by_group = @query.issue_count_by_group
respond_to do |format|
format.html { render :template => 'issues/index', :layout => @project_base_tag }#by young
format.api {
Issue.load_visible_relations(@issues) if include_in_api_response?('relations')
}
format.atom { render_feed(@issues, :title => "#{@project || Setting.app_title}: #{l(:label_issue_plural)}") }
format.csv { send_data(query_to_csv(@issues, @query, params), :type => 'text/csv; header=present', :filename => 'issues.csv') }
format.pdf { send_data(issues_to_pdf(@issues, @project, @query), :type => 'application/pdf', :filename => 'issues.pdf') }
end
else
respond_to do |format|
format.html { render(:template => 'issues/index', :layout => @project_base_tag) }#by young
format.any(:atom, :csv, :pdf) { render(:nothing => true) }
format.api { render_validation_errors(@query) }
end
end
rescue ActiveRecord::RecordNotFound
render_404
end
def show
@journals = @issue.journals.includes(:user, :details).reorder("#{Journal.table_name}.id ASC").all
@journals.each_with_index {|j,i| j.indice = i+1}
@journals.reject!(&:private_notes?) unless User.current.allowed_to?(:view_private_notes, @issue.project)
@journals.reverse! if User.current.wants_comments_in_reverse_order?
@changesets = @issue.changesets.visible.all
@changesets.reverse! if User.current.wants_comments_in_reverse_order?
@relations = @issue.relations.select {|r| r.other_issue(@issue) && r.other_issue(@issue).visible? }
@allowed_statuses = @issue.new_statuses_allowed_to(User.current)
@edit_allowed = User.current.allowed_to?(:edit_issues, @project)
@priorities = IssuePriority.active
@time_entry = TimeEntry.new(:issue => @issue, :project => @issue.project)
@project_base_tag = (params[:project_id] || @issue.project) ? 'base_projects':'base'#by young
respond_to do |format|
format.html {
retrieve_previous_and_next_issue_ids
render :template => 'issues/show', :layout => @project_base_tag#by young
}
format.api
format.atom { render :template => 'journals/index', :layout => false, :content_type => 'application/atom+xml' }
format.pdf {
pdf = issue_to_pdf(@issue, :journals => @journals)
send_data(pdf, :type => 'application/pdf', :filename => "#{@project.identifier}-#{@issue.id}.pdf")
}
end
end
# Add a new issue
# The new issue will be created from an existing one if copy_from parameter is given
def new
respond_to do |format|
format.html { render :action => 'new', :layout => 'base_projects' }
end
end
def create
call_hook(:controller_issues_new_before_save, { :params => params, :issue => @issue })
@issue.save_attachments(params[:attachments] || (params[:issue] && params[:issue][:uploads]))
if @issue.save
call_hook(:controller_issues_new_after_save, { :params => params, :issue => @issue})
respond_to do |format|
format.html {
render_attachment_warning_if_needed(@issue)
flash[:notice] = l(:notice_issue_successful_create, :id => view_context.link_to("#{@issue.source_from}", issue_path(@issue), :title => @issue.subject))
#flash[:notice] = l(:notice_issue_successful_create, :id => view_context.link_to("##{@issue.id}", issue_path(@issue), :title => @issue.subject))
if params[:continue]
attrs = {:tracker_id => @issue.tracker, :parent_issue_id => @issue.parent_issue_id}.reject {|k,v| v.nil?}
redirect_to new_project_issue_path(@issue.project, :issue => attrs)
else
redirect_to issue_path(@issue)
end
}
format.api { render :action => 'show', :status => :created, :location => issue_url(@issue) }
end
return
else
respond_to do |format|
format.html { render :action => 'new' }
format.api { render_validation_errors(@issue) }
end
end
end
def edit
return unless update_issue_from_params
respond_to do |format|
format.html {render :layout => 'base_projects' }#added by young
format.xml { }
end
end
def update
return unless update_issue_from_params
@issue.save_attachments(params[:attachments] || (params[:issue] && params[:issue][:uploads]))
saved = false
begin
saved = @issue.save_issue_with_child_records(params, @time_entry)
rescue ActiveRecord::StaleObjectError
@conflict = true
if params[:last_journal_id]
@conflict_journals = @issue.journals_after(params[:last_journal_id]).all
@conflict_journals.reject!(&:private_notes?) unless User.current.allowed_to?(:view_private_notes, @issue.project)
end
end
if saved
render_attachment_warning_if_needed(@issue)
reply_id = params[:reference_user_id].to_i
if reply_id > 0
JournalReply.add_reply(@issue.current_journal.id, reply_id, User.current.id)
end
flash[:notice] = l(:notice_successful_update) unless @issue.current_journal.new_record?
respond_to do |format|
format.html { redirect_back_or_default issue_path(@issue) }
format.api { render_api_ok }
end
else
respond_to do |format|
format.html { render :action => 'edit' }
format.api { render_validation_errors(@issue) }
end
end
end
# Updates the issue form when changing the project, status or tracker
# on issue creation/update
def update_form
end
# Bulk edit/copy a set of issues
def bulk_edit
@issues.sort!
@copy = params[:copy].present?
@notes = params[:notes]
if User.current.allowed_to?(:move_issues, @projects)
@allowed_projects = Issue.allowed_target_projects_on_move
if params[:issue]
@target_project = @allowed_projects.detect {|p| p.id.to_s == params[:issue][:project_id].to_s}
if @target_project
target_projects = [@target_project]
end
end
end
target_projects ||= @projects
if @copy
@available_statuses = [IssueStatus.default]
else
@available_statuses = @issues.map(&:new_statuses_allowed_to).reduce(:&)
end
@custom_fields = target_projects.map{|p|p.all_issue_custom_fields}.reduce(:&)
@assignables = target_projects.map(&:assignable_users).reduce(:&)
@trackers = target_projects.map(&:trackers).reduce(:&)
@versions = target_projects.map {|p| p.shared_versions.open}.reduce(:&)
@categories = target_projects.map {|p| p.issue_categories}.reduce(:&)
if @copy
@attachments_present = @issues.detect {|i| i.attachments.any?}.present?
@subtasks_present = @issues.detect {|i| !i.leaf?}.present?
end
@safe_attributes = @issues.map(&:safe_attribute_names).reduce(:&)
render :layout => false if request.xhr?
end
def bulk_update
@issues.sort!
@copy = params[:copy].present?
attributes = parse_params_for_bulk_issue_attributes(params)
unsaved_issue_ids = []
moved_issues = []
if @copy && params[:copy_subtasks].present?
# Descendant issues will be copied with the parent task
# Don't copy them twice
@issues.reject! {|issue| @issues.detect {|other| issue.is_descendant_of?(other)}}
end
@issues.each do |issue|
issue.reload
if @copy
issue = issue.copy({},
:attachments => params[:copy_attachments].present?,
:subtasks => params[:copy_subtasks].present?
)
end
journal = issue.init_journal(User.current, params[:notes])
issue.safe_attributes = attributes
call_hook(:controller_issues_bulk_edit_before_save, { :params => params, :issue => issue })
if issue.save
moved_issues << issue
else
# Keep unsaved issue ids to display them in flash error
unsaved_issue_ids << issue.id
end
end
set_flash_from_bulk_issue_save(@issues, unsaved_issue_ids)
if params[:follow]
if @issues.size == 1 && moved_issues.size == 1
redirect_to issue_path(moved_issues.first)
elsif moved_issues.map(&:project).uniq.size == 1
redirect_to project_issues_path(moved_issues.map(&:project).first)
end
else
redirect_back_or_default _project_issues_path(@project)
end
end
def destroy
@hours = TimeEntry.sum(:hours, :conditions => ['issue_id IN (?)', @issues]).to_f
if @hours > 0
case params[:todo]
when 'destroy'
# nothing to do
when 'nullify'
TimeEntry.update_all('issue_id = NULL', ['issue_id IN (?)', @issues])
when 'reassign'
reassign_to = @project.issues.find_by_id(params[:reassign_to_id])
if reassign_to.nil?
flash.now[:error] = l(:error_issue_not_found_in_project)
return
else
TimeEntry.update_all("issue_id = #{reassign_to.id}", ['issue_id IN (?)', @issues])
end
else
# display the destroy form if it's a user request
return unless api_request?
end
end
@issues.each do |issue|
begin
issue.reload.destroy
rescue ::ActiveRecord::RecordNotFound # raised by #reload if issue no longer exists
# nothing to do, issue was already deleted (eg. by a parent)
end
end
respond_to do |format|
format.html { redirect_back_or_default _project_issues_path(@project) }
format.api { render_api_ok }
end
end
private
def find_project
project_id = params[:project_id] || (params[:issue] && params[:issue][:project_id])
@project = Project.find(project_id)
rescue ActiveRecord::RecordNotFound
render_404
end
def retrieve_previous_and_next_issue_ids
retrieve_query_from_session
if @query
sort_init(@query.sort_criteria.empty? ? [['id', 'desc']] : @query.sort_criteria)
sort_update(@query.sortable_columns, 'issues_index_sort')
limit = 500
issue_ids = @query.issue_ids(:order => sort_clause, :limit => (limit + 1), :include => [:assigned_to, :tracker, :priority, :category, :fixed_version])
if (idx = issue_ids.index(@issue.id)) && idx < limit
if issue_ids.size < 500
@issue_position = idx + 1
@issue_count = issue_ids.size
end
@prev_issue_id = issue_ids[idx - 1] if idx > 0
@next_issue_id = issue_ids[idx + 1] if idx < (issue_ids.size - 1)
end
end
end
# Used by #edit and #update to set some common instance variables
# from the params
# TODO: Refactor, not everything in here is needed by #edit
def update_issue_from_params
@edit_allowed = User.current.allowed_to?(:edit_issues, @project)
@time_entry = TimeEntry.new(:issue => @issue, :project => @issue.project)
@time_entry.attributes = params[:time_entry]
@issue.init_journal(User.current)
issue_attributes = params[:issue]
if issue_attributes && params[:conflict_resolution]
case params[:conflict_resolution]
when 'overwrite'
issue_attributes = issue_attributes.dup
issue_attributes.delete(:lock_version)
when 'add_notes'
issue_attributes = issue_attributes.slice(:notes)
when 'cancel'
redirect_to issue_path(@issue)
return false
end
end
@issue.safe_attributes = issue_attributes
@priorities = IssuePriority.active
@allowed_statuses = @issue.new_statuses_allowed_to(User.current)
true
end
# TODO: Refactor, lots of extra code in here
# TODO: Changing tracker on an existing issue should not trigger this
def build_new_issue_from_params
if params[:id].blank?
@issue = Issue.new
if params[:copy_from]
begin
@copy_from = Issue.visible.find(params[:copy_from])
@copy_attachments = params[:copy_attachments].present? || request.get?
@copy_subtasks = params[:copy_subtasks].present? || request.get?
@issue.copy_from(@copy_from, :attachments => @copy_attachments, :subtasks => @copy_subtasks)
rescue ActiveRecord::RecordNotFound
render_404
return
end
end
@issue.project = @project
else
@issue = @project.issues.visible.find(params[:id])
end
@issue.project = @project
@issue.author ||= User.current
# Tracker must be set before custom field values
@issue.tracker ||= @project.trackers.find((params[:issue] && params[:issue][:tracker_id]) || params[:tracker_id] || :first)
if @issue.tracker.nil?
render_error l(:error_no_tracker_in_project)
return false
end
@issue.start_date ||= Date.today if Setting.default_issue_start_date_to_creation_date?
@issue.safe_attributes = params[:issue]
@priorities = IssuePriority.active
@allowed_statuses = @issue.new_statuses_allowed_to(User.current, true)
@available_watchers = (@issue.project.users.sort + @issue.watcher_users).uniq
end
def check_for_default_issue_status
if IssueStatus.default.nil?
render_error l(:error_no_default_issue_status)
return false
end
end
def parse_params_for_bulk_issue_attributes(params)
attributes = (params[:issue] || {}).reject {|k,v| v.blank?}
attributes.keys.each {|k| attributes[k] = '' if attributes[k] == 'none'}
if custom = attributes[:custom_field_values]
custom.reject! {|k,v| v.blank?}
custom.keys.each do |k|
if custom[k].is_a?(Array)
custom[k] << '' if custom[k].delete('__none__')
else
custom[k] = '' if custom[k] == '__none__'
end
end
end
attributes
end
end
# Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class IssuesController < ApplicationController
layout 'base_projects'#Added by young
default_search_scope :issues
before_filter :find_issue, :only => [:show, :edit, :update]
before_filter :find_issues, :only => [:bulk_edit, :bulk_update, :destroy]
before_filter :find_project, :only => [:new, :create, :update_form]
before_filter :authorize, :except => [:index]
before_filter :find_optional_project, :only => [:index]
before_filter :check_for_default_issue_status, :only => [:new, :create]
before_filter :build_new_issue_from_params, :only => [:new, :create, :update_form]
accept_rss_auth :index, :show
accept_api_auth :index, :show, :create, :update, :destroy
rescue_from Query::StatementInvalid, :with => :query_statement_invalid
helper :journals
helper :projects
include ProjectsHelper
helper :custom_fields
include CustomFieldsHelper
helper :issue_relations
include IssueRelationsHelper
helper :watchers
include WatchersHelper
helper :attachments
include AttachmentsHelper
helper :queries
include QueriesHelper
helper :repositories
include RepositoriesHelper
helper :sort
include SortHelper
include IssuesHelper
helper :timelog
include Redmine::Export::PDF
helper :project_score
def index
retrieve_query
sort_init(@query.sort_criteria.empty? ? [['id', 'desc']] : @query.sort_criteria)
sort_update(@query.sortable_columns)
@query.sort_criteria = sort_criteria.to_a
@project_base_tag = (params[:project_id] || @issue.project) ? 'base_projects':'base'
if @query.valid?
case params[:format]
when 'csv', 'pdf'
@limit = 10#Setting.issues_export_limit.to_i
when 'atom'
@limit = 10#Setting.feeds_limit.to_i
when 'xml', 'json'
@offset, @limit = api_offset_and_limit({:limit => 10})
else
@limit = 10#per_page_option
end
@issue_count = @query.issue_count
@issue_pages = Paginator.new @issue_count, @limit, params['page']
@offset ||= @issue_pages.offset
@issues = @query.issues(:include => [:assigned_to, :tracker, :priority, :category, :fixed_version],
:order => sort_clause,
:offset => @offset,
:limit => @limit)
@issue_count_by_group = @query.issue_count_by_group
respond_to do |format|
format.html { render :template => 'issues/index', :layout => @project_base_tag }#by young
format.api {
Issue.load_visible_relations(@issues) if include_in_api_response?('relations')
}
format.atom { render_feed(@issues, :title => "#{@project || Setting.app_title}: #{l(:label_issue_plural)}") }
format.csv { send_data(query_to_csv(@issues, @query, params), :type => 'text/csv; header=present', :filename => 'issues.csv') }
format.pdf { send_data(issues_to_pdf(@issues, @project, @query), :type => 'application/pdf', :filename => 'issues.pdf') }
end
else
respond_to do |format|
format.html { render(:template => 'issues/index', :layout => @project_base_tag) }#by young
format.any(:atom, :csv, :pdf) { render(:nothing => true) }
format.api { render_validation_errors(@query) }
end
end
rescue ActiveRecord::RecordNotFound
render_404
end
def show
@journals = @issue.journals.includes(:user, :details).reorder("#{Journal.table_name}.id ASC").all
@journals.each_with_index {|j,i| j.indice = i+1}
@journals.reject!(&:private_notes?) unless User.current.allowed_to?(:view_private_notes, @issue.project)
@journals.reverse! if User.current.wants_comments_in_reverse_order?
@changesets = @issue.changesets.visible.all
@changesets.reverse! if User.current.wants_comments_in_reverse_order?
@relations = @issue.relations.select {|r| r.other_issue(@issue) && r.other_issue(@issue).visible? }
@allowed_statuses = @issue.new_statuses_allowed_to(User.current)
@edit_allowed = User.current.allowed_to?(:edit_issues, @project)
@priorities = IssuePriority.active
@time_entry = TimeEntry.new(:issue => @issue, :project => @issue.project)
@project_base_tag = (params[:project_id] || @issue.project) ? 'base_projects':'base'#by young
@available_watchers = (@issue.project.users.sort + @issue.watcher_users).uniq
respond_to do |format|
format.html {
retrieve_previous_and_next_issue_ids
render :template => 'issues/show', :layout => @project_base_tag#by young
}
format.api
format.atom { render :template => 'journals/index', :layout => false, :content_type => 'application/atom+xml' }
format.pdf {
pdf = issue_to_pdf(@issue, :journals => @journals)
send_data(pdf, :type => 'application/pdf', :filename => "#{@project.identifier}-#{@issue.id}.pdf")
}
end
end
# Add a new issue
# The new issue will be created from an existing one if copy_from parameter is given
def new
respond_to do |format|
format.html { render :action => 'new', :layout => 'base_projects' }
end
end
def create
call_hook(:controller_issues_new_before_save, { :params => params, :issue => @issue })
@issue.save_attachments(params[:attachments] || (params[:issue] && params[:issue][:uploads]))
if @issue.save
call_hook(:controller_issues_new_after_save, { :params => params, :issue => @issue})
respond_to do |format|
format.html {
render_attachment_warning_if_needed(@issue)
flash[:notice] = l(:notice_issue_successful_create, :id => view_context.link_to("#{@issue.source_from}", issue_path(@issue), :title => @issue.subject))
#flash[:notice] = l(:notice_issue_successful_create, :id => view_context.link_to("##{@issue.id}", issue_path(@issue), :title => @issue.subject))
if params[:continue]
attrs = {:tracker_id => @issue.tracker, :parent_issue_id => @issue.parent_issue_id}.reject {|k,v| v.nil?}
redirect_to new_project_issue_url(@issue.project, :issue => attrs)
else
redirect_to issue_url(@issue)
end
}
format.api { render :action => 'show', :status => :created, :location => issue_url(@issue) }
end
return
else
respond_to do |format|
format.html { render :action => 'new' }
format.api { render_validation_errors(@issue) }
end
end
end
def edit
return unless update_issue_from_params
respond_to do |format|
format.html {render :layout => 'base_projects' }#added by young
format.xml { }
end
end
def update
return unless update_issue_from_params
@issue.save_attachments(params[:attachments] || (params[:issue] && params[:issue][:uploads]))
saved = false
begin
saved = @issue.save_issue_with_child_records(params, @time_entry)
rescue ActiveRecord::StaleObjectError
@conflict = true
if params[:last_journal_id]
@conflict_journals = @issue.journals_after(params[:last_journal_id]).all
@conflict_journals.reject!(&:private_notes?) unless User.current.allowed_to?(:view_private_notes, @issue.project)
end
end
if saved
#修改界面增加跟踪者
watcherlist = @issue.watcher_users
select_users = []
if params[:issue]
if params[:issue][:watcher_user_ids]
params[:issue][:watcher_user_ids].each do |user_id|
select_users << User.find(user_id)
end
end
end
select_users.each do |user|
if watcherlist.include? user
else
@issue.add_watcher user
end
end
watcherlist.each do |user|
if select_users.include? user
else
@issue.remove_watcher user
end
end
render_attachment_warning_if_needed(@issue)
reply_id = params[:reference_user_id].to_i
if reply_id > 0
JournalReply.add_reply(@issue.current_journal.id, reply_id, User.current.id)
end
flash[:notice] = l(:notice_successful_update) unless @issue.current_journal.new_record?
respond_to do |format|
format.html { redirect_back_or_default issue_path(@issue) }
format.api { render_api_ok }
end
else
respond_to do |format|
format.html { render :action => 'edit' }
format.api { render_validation_errors(@issue) }
end
end
end
# Updates the issue form when changing the project, status or tracker
# on issue creation/update
def update_form
end
# Bulk edit/copy a set of issues
def bulk_edit
@issues.sort!
@copy = params[:copy].present?
@notes = params[:notes]
if User.current.allowed_to?(:move_issues, @projects)
@allowed_projects = Issue.allowed_target_projects_on_move
if params[:issue]
@target_project = @allowed_projects.detect {|p| p.id.to_s == params[:issue][:project_id].to_s}
if @target_project
target_projects = [@target_project]
end
end
end
target_projects ||= @projects
if @copy
@available_statuses = [IssueStatus.default]
else
@available_statuses = @issues.map(&:new_statuses_allowed_to).reduce(:&)
end
@custom_fields = target_projects.map{|p|p.all_issue_custom_fields}.reduce(:&)
@assignables = target_projects.map(&:assignable_users).reduce(:&)
@trackers = target_projects.map(&:trackers).reduce(:&)
@versions = target_projects.map {|p| p.shared_versions.open}.reduce(:&)
@categories = target_projects.map {|p| p.issue_categories}.reduce(:&)
if @copy
@attachments_present = @issues.detect {|i| i.attachments.any?}.present?
@subtasks_present = @issues.detect {|i| !i.leaf?}.present?
end
@safe_attributes = @issues.map(&:safe_attribute_names).reduce(:&)
render :layout => false if request.xhr?
end
def bulk_update
@issues.sort!
@copy = params[:copy].present?
attributes = parse_params_for_bulk_issue_attributes(params)
unsaved_issue_ids = []
moved_issues = []
if @copy && params[:copy_subtasks].present?
# Descendant issues will be copied with the parent task
# Don't copy them twice
@issues.reject! {|issue| @issues.detect {|other| issue.is_descendant_of?(other)}}
end
@issues.each do |issue|
issue.reload
if @copy
issue = issue.copy({},
:attachments => params[:copy_attachments].present?,
:subtasks => params[:copy_subtasks].present?
)
end
journal = issue.init_journal(User.current, params[:notes])
issue.safe_attributes = attributes
call_hook(:controller_issues_bulk_edit_before_save, { :params => params, :issue => issue })
if issue.save
moved_issues << issue
else
# Keep unsaved issue ids to display them in flash error
unsaved_issue_ids << issue.id
end
end
set_flash_from_bulk_issue_save(@issues, unsaved_issue_ids)
if params[:follow]
if @issues.size == 1 && moved_issues.size == 1
redirect_to issue_url(moved_issues.first)
elsif moved_issues.map(&:project).uniq.size == 1
redirect_to project_issues_url(moved_issues.map(&:project).first)
end
else
redirect_back_or_default _project_issues_path(@project)
end
end
def destroy
@hours = TimeEntry.sum(:hours, :conditions => ['issue_id IN (?)', @issues]).to_f
if @hours > 0
case params[:todo]
when 'destroy'
# nothing to do
when 'nullify'
TimeEntry.update_all('issue_id = NULL', ['issue_id IN (?)', @issues])
when 'reassign'
reassign_to = @project.issues.find_by_id(params[:reassign_to_id])
if reassign_to.nil?
flash.now[:error] = l(:error_issue_not_found_in_project)
return
else
TimeEntry.update_all("issue_id = #{reassign_to.id}", ['issue_id IN (?)', @issues])
end
else
# display the destroy form if it's a user request
return unless api_request?
end
end
@issues.each do |issue|
begin
issue.reload.destroy
rescue ::ActiveRecord::RecordNotFound # raised by #reload if issue no longer exists
# nothing to do, issue was already deleted (eg. by a parent)
end
end
respond_to do |format|
format.html { redirect_back_or_default _project_issues_path(@project) }
format.api { render_api_ok }
end
end
private
def find_project
project_id = params[:project_id] || (params[:issue] && params[:issue][:project_id])
@project = Project.find(project_id)
rescue ActiveRecord::RecordNotFound
render_404
end
def retrieve_previous_and_next_issue_ids
retrieve_query_from_session
if @query
sort_init(@query.sort_criteria.empty? ? [['id', 'desc']] : @query.sort_criteria)
sort_update(@query.sortable_columns, 'issues_index_sort')
limit = 500
issue_ids = @query.issue_ids(:order => sort_clause, :limit => (limit + 1), :include => [:assigned_to, :tracker, :priority, :category, :fixed_version])
if (idx = issue_ids.index(@issue.id)) && idx < limit
if issue_ids.size < 500
@issue_position = idx + 1
@issue_count = issue_ids.size
end
@prev_issue_id = issue_ids[idx - 1] if idx > 0
@next_issue_id = issue_ids[idx + 1] if idx < (issue_ids.size - 1)
end
end
end
# Used by #edit and #update to set some common instance variables
# from the params
# TODO: Refactor, not everything in here is needed by #edit
def update_issue_from_params
@edit_allowed = User.current.allowed_to?(:edit_issues, @project)
@time_entry = TimeEntry.new(:issue => @issue, :project => @issue.project)
@time_entry.attributes = params[:time_entry]
@issue.init_journal(User.current)
issue_attributes = params[:issue]
if issue_attributes && params[:conflict_resolution]
case params[:conflict_resolution]
when 'overwrite'
issue_attributes = issue_attributes.dup
issue_attributes.delete(:lock_version)
when 'add_notes'
issue_attributes = issue_attributes.slice(:notes)
when 'cancel'
redirect_to issue_url(@issue)
return false
end
end
@issue.safe_attributes = issue_attributes
@priorities = IssuePriority.active
@allowed_statuses = @issue.new_statuses_allowed_to(User.current)
true
end
# TODO: Refactor, lots of extra code in here
# TODO: Changing tracker on an existing issue should not trigger this
def build_new_issue_from_params
if params[:id].blank?
@issue = Issue.new
if params[:copy_from]
begin
@copy_from = Issue.visible.find(params[:copy_from])
@copy_attachments = params[:copy_attachments].present? || request.get?
@copy_subtasks = params[:copy_subtasks].present? || request.get?
@issue.copy_from(@copy_from, :attachments => @copy_attachments, :subtasks => @copy_subtasks)
rescue ActiveRecord::RecordNotFound
render_404
return
end
end
@issue.project = @project
else
@issue = @project.issues.visible.find(params[:id])
end
@issue.project = @project
@issue.author ||= User.current
# Tracker must be set before custom field values
@issue.tracker ||= @project.trackers.find((params[:issue] && params[:issue][:tracker_id]) || params[:tracker_id] || :first)
if @issue.tracker.nil?
render_error l(:error_no_tracker_in_project)
return false
end
@issue.start_date ||= Date.today if Setting.default_issue_start_date_to_creation_date?
@issue.safe_attributes = params[:issue]
@priorities = IssuePriority.active
@allowed_statuses = @issue.new_statuses_allowed_to(User.current, true)
@available_watchers = (@issue.project.users.sort + @issue.watcher_users).uniq
end
def check_for_default_issue_status
if IssueStatus.default.nil?
render_error l(:error_no_default_issue_status)
return false
end
end
def parse_params_for_bulk_issue_attributes(params)
attributes = (params[:issue] || {}).reject {|k,v| v.blank?}
attributes.keys.each {|k| attributes[k] = '' if attributes[k] == 'none'}
if custom = attributes[:custom_field_values]
custom.reject! {|k,v| v.blank?}
custom.keys.each do |k|
if custom[k].is_a?(Array)
custom[k] << '' if custom[k].delete('__none__')
else
custom[k] = '' if custom[k] == '__none__'
end
end
end
attributes
end
end

@ -1,112 +1,117 @@
# Redmine - project management software
# Copyright (C) 2006-2013 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 JournalsController < ApplicationController
before_filter :find_journal, :only => [:edit, :diff, :destroy]
before_filter :find_issue, :only => [:new]
before_filter :find_optional_project, :only => [:index]
before_filter :authorize, :only => [:new, :edit, :diff]
accept_rss_auth :index
menu_item :issues
helper :issues
helper :custom_fields
helper :queries
include QueriesHelper
helper :sort
include SortHelper
def index
retrieve_query
sort_init 'id', 'desc'
sort_update(@query.sortable_columns)
if @query.valid?
@journals = @query.journals(:order => "#{Journal.table_name}.created_on DESC",
:limit => 25)
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'
rescue ActiveRecord::RecordNotFound
render_404
end
def diff
@issue = @journal.issue
if params[:detail_id].present?
@detail = @journal.details.find_by_id(params[:detail_id])
else
@detail = @journal.details.detect {|d| d.prop_key == 'description'}
end
(render_404; return false) unless @issue && @detail
@diff = Redmine::Helpers::Diff.new(@detail.value, @detail.old_value)
end
def new
@journal = Journal.visible.find(params[:journal_id]) if params[:journal_id]
if @journal
user = @journal.user
text = @journal.notes
else
user = @issue.author
text = @issue.description
end
# Replaces pre blocks with [...]
text = text.to_s.strip.gsub(%r{<pre>((.|\s)*?)</pre>}m, '[...]')
@content = "> #{ll(Setting.default_language, :text_user_wrote, user)}\n> "
@content << text.gsub(/(\r?\n|\r\n?)/, "\n> ") + "\n\n"
@id = user.id
rescue ActiveRecord::RecordNotFound
render_404
end
def edit
(render_403; return false) unless @journal.editable_by?(User.current)
if request.post?
@journal.update_attributes(:notes => params[:notes]) if params[:notes]
@journal.destroy if @journal.details.empty? && @journal.notes.blank?
call_hook(:controller_journals_edit_post, { :journal => @journal, :params => params})
respond_to do |format|
format.html { redirect_to issue_path(@journal.journalized) }
format.js { render :action => 'update' }
end
else
respond_to do |format|
format.html {
# TODO: implement non-JS journal update
render :nothing => true
}
format.js
end
end
end
# Delete a journals added by young
def destroy
@journal.destroy
redirect_to issue_path(@journal.journalized)
end
private
def find_journal
@journal = Journal.visible.find(params[:id])
@project = @journal.journalized.project
rescue ActiveRecord::RecordNotFound
render_404
end
end
# Redmine - project management software
# Copyright (C) 2006-2013 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 JournalsController < ApplicationController
before_filter :find_journal, :only => [:edit, :diff, :destroy]
before_filter :find_issue, :only => [:new]
before_filter :find_optional_project, :only => [:index]
before_filter :authorize, :only => [:new, :edit, :diff]
accept_rss_auth :index
menu_item :issues
helper :issues
helper :custom_fields
helper :queries
include QueriesHelper
helper :sort
include SortHelper
def index
retrieve_query
sort_init 'id', 'desc'
sort_update(@query.sortable_columns)
if @query.valid?
@journals = @query.journals(:order => "#{Journal.table_name}.created_on DESC",
:limit => 25)
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'
rescue ActiveRecord::RecordNotFound
render_404
end
def diff
@issue = @journal.issue
if params[:detail_id].present?
@detail = @journal.details.find_by_id(params[:detail_id])
else
@detail = @journal.details.detect {|d| d.prop_key == 'description'}
end
(render_404; return false) unless @issue && @detail
@diff = Redmine::Helpers::Diff.new(@detail.value, @detail.old_value)
respond_to do |format|
format.html {
render :layout => 'project_base'
}
end
end
def new
@journal = Journal.visible.find(params[:journal_id]) if params[:journal_id]
if @journal
user = @journal.user
text = @journal.notes
else
user = @issue.author
text = @issue.description
end
# Replaces pre blocks with [...]
text = text.to_s.strip.gsub(%r{<pre>((.|\s)*?)</pre>}m, '[...]')
@content = "> #{ll(Setting.default_language, :text_user_wrote, user)}\n> "
@content << text.gsub(/(\r?\n|\r\n?)/, "\n> ") + "\n\n"
@id = user.id
rescue ActiveRecord::RecordNotFound
render_404
end
def edit
(render_403; return false) unless @journal.editable_by?(User.current)
if request.post?
@journal.update_attributes(:notes => params[:notes]) if params[:notes]
@journal.destroy if @journal.details.empty? && @journal.notes.blank?
call_hook(:controller_journals_edit_post, { :journal => @journal, :params => params})
respond_to do |format|
format.html { redirect_to issue_url(@journal.journalized) }
format.js { render :action => 'update' }
end
else
respond_to do |format|
format.html {
# TODO: implement non-JS journal update
render :nothing => true
}
format.js
end
end
end
# Delete a journals added by young
def destroy
@journal.destroy
redirect_to issue_url(@journal.journalized)
end
private
def find_journal
@journal = Journal.visible.find(params[:id])
@project = @journal.journalized.project
rescue ActiveRecord::RecordNotFound
render_404
end
end

@ -1,293 +1,327 @@
# Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class MembersController < ApplicationController
model_object Member
before_filter :find_model_object, :except => [:index, :create, :autocomplete]
#before_filter :find_model_object_contest, :except => [:index, :create, :autocomplete]
before_filter :find_project_from_association, :except => [:index, :create, :autocomplete]
before_filter :find_project_by_project_id, :only => [:index, :create, :autocomplete]
before_filter :authorize
accept_api_auth :index, :show, :create, :update, :destroy
def index
@offset, @limit = api_offset_and_limit
@member_count = @project.member_principals.count
@member_pages = Paginator.new @member_count, @limit, params['page']
@offset ||= @member_pages.offset
@members = @project.member_principals.all(
:order => "#{Member.table_name}.id",
:limit => @limit,
:offset => @offset
)
respond_to do |format|
format.html { head 406 }
format.api
end
end
def show
respond_to do |format|
format.html { head 406 }
format.api
end
end
def create
if params[:refusal_button]
members = []
applied_members = true
if params[:membership]
if params[:membership][:user_ids]
attrs = params[:membership].dup
user_ids = attrs.delete(:user_ids)
user_ids.each do |user_id|
AppliedProject.deleteappiled(user_id, @project.id)
end
end
end
else
#modify by nwb
#更改课程成员逻辑
applied_members = false
members = []
user_grades = []
if @project
project_info = []
if params[:membership]
if params[:membership][:user_ids]
attrs = params[:membership].dup
user_ids = attrs.delete(:user_ids)
user_ids.each do |user_id|
members << Member.new(:role_ids => params[:membership][:role_ids], :user_id => user_id)
user_grades << UserGrade.new(:user_id => user_id, :project_id => @project.id)
## added by nie
if (params[:membership][:role_ids] && params[:membership][:role_ids][0] == "3")
project_info << ProjectInfo.new(:user_id => user_id, :project_id => @project.id)
# ProjectInfo.create(:name => "test", :user_id => 123)
end
## end
end
else
members << Member.new(:role_ids => params[:membership][:role_ids], :user_id => params[:membership][:user_id])
user_grades << UserGrade.new(:user_id => params[:membership][:user_id], :project_id => @project.id)
## added by nie
if (params[:membership][:role_ids] && params[:membership][:role_ids][0] == "3")
project_info << ProjectInfo.new(:project_id => @project.id, :user_id => params[:membership][:user_id])
end
## end
end
@project.members << members
# added by nie
@project.project_infos << project_info
@project.user_grades << user_grades
# end
end
if members.present? && members.all? { |m| m.valid? }
members.each do |member|
AppliedProject.deleteappiled(member.user_id, @project.id)
end
end
respond_to do |format|
format.html { redirect_to_settings_in_projects }
format.js { @members = members; @applied_members = applied_members; }
format.api {
@member = members.first
if @member.valid?
render :action => 'show', :status => :created, :location => membership_url(@member)
else
render_validation_errors(@member)
end
}
end
elsif @course
course_info = []
if params[:membership]
if params[:membership][:user_ids]
attrs = params[:membership].dup
user_ids = attrs.delete(:user_ids)
user_ids.each do |user_id|
members << Member.new(:role_ids => params[:membership][:role_ids], :user_id => user_id)
#user_grades << UserGrade.new(:user_id => user_id, :course_id => @course.id)
if (params[:membership][:role_ids] && params[:membership][:role_ids][0] == "3")
course_info << CourseInfo.new(:user_id => user_id, :course_id => @course.id)
end
end
else
members << Member.new(:role_ids => params[:membership][:role_ids], :user_id => params[:membership][:user_id])
if (params[:membership][:role_ids] && params[:membership][:role_ids][0] == "3")
course_info << CourseInfo.new(:course_id => @course.id, :user_id => params[:membership][:user_id])
end
end
@course.members << members
@course.course_infos << course_info
end
respond_to do |format|
format.html { redirect_to_settings_in_courses }
format.js { @members = members; @applied_members = applied_members; }
format.api {
@member = members.first
if @member.valid?
render :action => 'show', :status => :created, :location => membership_url(@member)
else
render_validation_errors(@member)
end
}
end
end # end of if @project
end # end of params[:refusal_button]
end
def update
#modify by nwb
#增加对课程成员修改的支持
if @project
if params[:membership]
@member.role_ids = params[:membership][:role_ids]
#added by nie
if (params[:membership][:role_ids] && params[:membership][:role_ids][0] == "3")
@projectInfo = ProjectInfo.new(:user_id => @member.user_id, :project_id => @project.id)
@projectInfo.save
else
user_admin = ProjectInfo.where("user_id = ? and project_id = ?", @member.user_id, @project.id)
if user_admin.size > 0
user_admin.each do |user|
user.destroy
end
end
end
end
saved = @member.save
respond_to do |format|
format.html { redirect_to_settings_in_projects }
format.js
format.api {
if saved
render_api_ok
else
render_validation_errors(@member)
end
}
end
elsif @course
if params[:membership]
@member.role_ids = params[:membership][:role_ids]
if (params[:membership][:role_ids] && params[:membership][:role_ids][0] == "3")
@courseInfo = CourseInfos.new(:user_id => @member.user_id, :course_id => @course.id)
@courseInfo.save
else
user_admin = CourseInfos.where("user_id = ? and course_id = ?", @member.user_id, @course.id)
if user_admin.size > 0
user_admin.each do |user|
user.destroy
end
end
end
end
saved = @member.save
respond_to do |format|
format.html { redirect_to_settings_in_courses }
format.js
format.api {
if saved
render_api_ok
else
render_validation_errors(@member)
end
}
end
end
end
def destroy
#modify by nwb
#课程成员删除修改
if @project
if request.delete? && @member.deletable?
@member.destroy
# end
user_admin = ProjectInfo.where("user_id = ? and project_id = ?", @member.user_id, @project.id)
if user_admin.size > 0
user_admin.each do |user|
user.destroy
end
end
user_grade = UserGrade.where("user_id = ? and project_id = ?", @member.user_id, @project.id)
if user_grade.size > 0
user_grade.each do |grade|
grade.destroy
end
end
end
respond_to do |format|
format.html { redirect_to_settings_in_projects }
format.js
format.api {
if @member.destroyed?
render_api_ok
else
head :unprocessable_entity
end
}
end
elsif @course
if request.delete? && @member.deletable?
@member.destroy
user_admin = CourseInfos.where("user_id = ? and course_id = ?", @member.user_id, @course.id)
if user_admin.size > 0
user_admin.each do |user|
user.destroy
end
end
end
respond_to do |format|
format.html { redirect_to_settings_in_courses }
format.js
format.api {
if @member.destroyed?
render_api_ok
else
head :unprocessable_entity
end
}
end
end
end
def autocomplete
respond_to do |format|
format.js
end
end
private
def redirect_to_settings_in_projects
redirect_to settings_project_path(@project, :tab => 'members')
end
def redirect_to_settings_in_courses
redirect_to settings_course_path(@course, :tab => 'members')
end
end
# -*coding:utf-8 -*-
# Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class MembersController < ApplicationController
model_object Member
before_filter :find_model_object, :except => [:index, :create, :autocomplete]
#before_filter :find_model_object_contest, :except => [:index, :create, :autocomplete]
before_filter :find_project_from_association, :except => [:index, :create, :autocomplete]
before_filter :find_project_by_project_id, :only => [:index, :create, :autocomplete]
before_filter :authorize
accept_api_auth :index, :show, :create, :update, :destroy
def index
@offset, @limit = api_offset_and_limit
@member_count = @project.member_principals.count
@member_pages = Paginator.new @member_count, @limit, params['page']
@offset ||= @member_pages.offset
@members = @project.member_principals.all(
:order => "#{Member.table_name}.id",
:limit => @limit,
:offset => @offset
)
respond_to do |format|
format.html { head 406 }
format.api
end
end
def show
respond_to do |format|
format.html { head 406 }
format.api
end
end
def create
if params[:refusal_button]
members = []
applied_members = true
if params[:membership]
if params[:membership][:user_ids]
attrs = params[:membership].dup
user_ids = attrs.delete(:user_ids)
user_ids.each do |user_id|
AppliedProject.deleteappiled(user_id, @project.id)
end
end
end
else
#modify by nwb
#更改课程成员逻辑
applied_members = false
members = []
user_grades = []
if @project
project_info = []
if params[:membership]
if params[:membership][:user_ids]
attrs = params[:membership].dup
user_ids = attrs.delete(:user_ids)
user_ids.each do |user_id|
members << Member.new(:role_ids => params[:membership][:role_ids], :user_id => user_id)
user_grades << UserGrade.new(:user_id => user_id, :project_id => @project.id)
## added by nie
if (params[:membership][:role_ids])
role = Role.find(params[:membership][:role_ids][0])
project_info << ProjectInfo.new(:user_id => user_id, :project_id => @project.id) if role.allowed_to?(:is_manager)
# ProjectInfo.create(:name => "test", :user_id => 123)
end
## end
end
else
members << Member.new(:role_ids => params[:membership][:role_ids], :user_id => params[:membership][:user_id])
user_grades << UserGrade.new(:user_id => params[:membership][:user_id], :project_id => @project.id)
## added by nie
if (params[:membership][:role_ids])
role = Role.find(params[:membership][:role_ids][0])
project_info << ProjectInfo.new(:project_id => @project.id, :user_id => params[:membership][:user_id]) if role.allowed_to?(:is_manager)
end
## end
end
@project.members << members
# added by nie
@project.project_infos << project_info
@project.user_grades << user_grades
# end
end
if members.present? && members.all? { |m| m.valid? }
members.each do |member|
AppliedProject.deleteappiled(member.user_id, @project.id)
end
end
respond_to do |format|
format.html { redirect_to_settings_in_projects }
format.js { @members = members; @applied_members = applied_members; }
format.api {
@member = members.first
if @member.valid?
render :action => 'show', :status => :created, :location => membership_url(@member)
else
render_validation_errors(@member)
end
}
end
elsif @course
course_info = []
if params[:membership]
if params[:membership][:user_ids]
attrs = params[:membership].dup
user_ids = attrs.delete(:user_ids)
user_ids.each do |user_id|
member = Member.new(:role_ids => params[:membership][:role_ids], :user_id => user_id)
role = Role.find_by_id(params[:membership][:role_ids])
# 这里的判断只能通过角色名,可以弄成常量
if role.name == "学生" || role.name == "Student"
StudentsForCourse.create(:student_id => user_id, :course_id =>@course.id)
end
members << member
#user_grades << UserGrade.new(:user_id => user_id, :course_id => @course.id)
if (params[:membership][:role_ids])
role = Role.find(params[:membership][:role_ids][0])
course_info << CourseInfo.new(:user_id => user_id, :course_id => @course.id) if role.allowed_to?(:is_manager)
end
end
else
members << Member.new(:role_ids => params[:membership][:role_ids], :user_id => params[:membership][:user_id])
if (params[:membership][:role_ids])
role = Role.find(params[:membership][:role_ids][0])
course_info << CourseInfo.new(:course_id => @course.id, :user_id => params[:membership][:user_id]) if role.allowed_to?(:is_manager)
end
end
@course.members << members
@course.course_infos << course_info
end
respond_to do |format|
format.html { redirect_to_settings_in_courses }
format.js { @members = members; @applied_members = applied_members; }
format.api {
@member = members.first
if @member.valid?
render :action => 'show', :status => :created, :location => membership_url(@member)
else
render_validation_errors(@member)
end
}
end
end # end of if @project
end # end of params[:refusal_button]
end
def update
#modify by nwb
#增加对课程成员修改的支持
if @project
if params[:membership]
@member.role_ids = params[:membership][:role_ids]
#added by nie
if (params[:membership][:role_ids])
role = Role.find(params[:membership][:role_ids][0])
if role.allowed_to?(:is_manager)
@projectInfo = ProjectInfo.new(:user_id => @member.user_id, :project_id => @project.id)
@projectInfo.save
else
user_admin = ProjectInfo.where("user_id = ? and project_id = ?", @member.user_id, @project.id)
if user_admin.size > 0
user_admin.each do |user|
user.destroy
end
end
end
end
end
saved = @member.save
respond_to do |format|
format.html { redirect_to_settings_in_projects }
format.js
format.api {
if saved
render_api_ok
else
render_validation_errors(@member)
end
}
end
elsif @course
if params[:membership]
@member.role_ids = params[:membership][:role_ids]
if (params[:membership][:role_ids])
role = Role.find(params[:membership][:role_ids][0])
# 这里的判断只能通过角色名,可以弄成常量
if role.name == "学生" || role.name == "Student"
StudentsForCourse.create(:student_id => @member.user_id, :course_id =>@course.id)
else
joined = StudentsForCourse.where('student_id = ? and course_id = ?', @member.user_id,@course.id)
joined.each do |join|
join.delete
end
@member.course_group_id = 0
end
if role.allowed_to?(:is_manager)
@courseInfo = CourseInfos.new(:user_id => @member.user_id, :course_id => @course.id)
@courseInfo.save
else
user_admin = CourseInfos.where("user_id = ? and course_id = ?", @member.user_id, @course.id)
if user_admin.size > 0
user_admin.each do |user|
user.destroy
end
end
end
end
end
saved = @member.save
respond_to do |format|
format.html { redirect_to_settings_in_courses }
format.js
format.api {
if saved
render_api_ok
else
render_validation_errors(@member)
end
}
end
end
end
def destroy
#modify by nwb
#课程成员删除修改
if @project
if request.delete? && @member.deletable?
@member.destroy
# end
user_admin = ProjectInfo.where("user_id = ? and project_id = ?", @member.user_id, @project.id)
if user_admin.size > 0
user_admin.each do |user|
user.destroy
end
end
user_grade = UserGrade.where("user_id = ? and project_id = ?", @member.user_id, @project.id)
if user_grade.size > 0
user_grade.each do |grade|
grade.destroy
end
end
end
respond_to do |format|
format.html { redirect_to_settings_in_projects }
format.js
format.api {
if @member.destroyed?
render_api_ok
else
head :unprocessable_entity
end
}
end
elsif @course
if request.delete? && @member.deletable?
@member.destroy
user_admin = CourseInfos.where("user_id = ? and course_id = ?", @member.user_id, @course.id)
if user_admin.size > 0
user_admin.each do |user|
user.destroy
end
end
joined = StudentsForCourse.where('student_id = ? and course_id = ?', @member.user_id,@course.id)
joined.each do |join|
join.delete
end
end
respond_to do |format|
format.html { redirect_to_settings_in_courses }
format.js
format.api {
if @member.destroyed?
render_api_ok
else
head :unprocessable_entity
end
}
end
end
end
def autocomplete
respond_to do |format|
format.js
end
end
private
def redirect_to_settings_in_projects
redirect_to settings_project_url(@project, :tab => 'members')
end
def redirect_to_settings_in_courses
redirect_to settings_course_url(@course, :tab => 'members')
end
end

@ -1,190 +1,207 @@
class MemosController < ApplicationController
default_search_scope :memos
before_filter :find_forum, :only => [:new, :create, :preview]
before_filter :find_attachments, :only => [:preview]
before_filter :find_memo, :except => [:new, :create, :preview]
before_filter :authenticate_user_edit, :only => [:edit, :update]
before_filter :authenticate_user_destroy, :only => [:destroy]
before_filter :require_login, :only => [:new, :create]
helper :attachments
include AttachmentsHelper
layout 'base_memos'
def quote
@subject = @memo.subject
@subject = "RE: #{@subject}" unless @subject.starts_with?('RE:')
@content = "#{ll(Setting.default_language, :text_user_wrote, @memo.author)} <br/> &nbsp; "
@content << @memo.content.to_s.strip.gsub(%r{<pre>((.|\s)*?)</pre>}m, '[...]').gsub(/(\r?\n|\r\n?)/, "\n") + "</blockquote>\n\n<br/>"
@content = "<blockquote>" << @content
end
def new
@memo = Memo.new
@memo.forum_id = @forum.id
respond_to do |format|
format.html {
render action: :new ,layout: 'base'
}
format.json { render json: @memo }
end
end
def create
@memo = Memo.new(params[:memo])
@memo.forum_id = params[:forum_id]
@memo.author_id = User.current.id
@memo.save_attachments(params[:attachments] || (params[:memo] && params[:memo][:uploads]))
respond_to do |format|
if @memo.save
format.html { redirect_to back_memo_url, notice: "#{l :label_memo_create_succ}" }
format.json { render json: @memo, status: :created, location: @memo }
else
flash[:error] = "#{l :label_memo_create_fail}: #{@memo.errors.full_messages[0]}"
# back_error_page = @memo.parent_id.nil? ? forum_path(@forum) : forum_memo_path(@forum, @memo.parent_id)
pre_count = REPLIES_PER_PAGE
@memo_new = @memo.dup
@memo = @memo.root # 取出楼主防止输入帖子id让回复作为主贴显示
unless @memo.new_record?
@memo.update_column(:viewed_count, (@memo.viewed_count.to_i + 1))
end
page = params[:page]
if params[:r] && page.nil?
offset = @memo.children.where("#{Memo.table_name}.id < ?", params[:r].to_i).count
page = 1 + offset / pre_count
else
end
@reply_count = @memo.children.count
@reply_pages = Paginator.new @reply_count, pre_count, page
@replies = @memo.children.
includes(:author, :attachments).
reorder("#{Memo.table_name}.created_at ASC").
limit(@reply_pages.per_page).
offset(@reply_pages.offset).
all
if @memo.new_record?
format.html { redirect_to back_url, error: "#{l :label_memo_create_fail}: #{@memo.errors.full_messages[0]}" }
else
format.html { render action: :show }#, error: "#{l :label_memo_create_fail}: #{@memo.errors.full_messages[0]}" }
# format.html { redirect_to back_memo_or_forum_url}#, error: "#{l :label_memo_create_fail}: #{@memo.errors.full_messages[0]}" }
format.json { render json: @memo.errors, status: :unprocessable_entity }
end
end
end
end
REPLIES_PER_PAGE = 20 unless const_defined?(:REPLIES_PER_PAGE)
def show
pre_count = REPLIES_PER_PAGE
@memo = @memo.root # 取出楼主防止输入帖子id让回复作为主贴显示
@memo.update_column(:viewed_count, (@memo.viewed_count.to_i + 1))
page = params[:page]
if params[:r] && page.nil?
offset = @memo.children.where("#{Memo.table_name}.id < ?", params[:r].to_i).count
page = 1 + offset / pre_count
else
end
@reply_count = @memo.children.count
@reply_pages = Paginator.new @reply_count, pre_count, page
@replies = @memo.children.
includes(:author, :attachments).
reorder("#{Memo.table_name}.created_at DESC").
limit(@reply_pages.per_page).
offset(@reply_pages.offset).
all
@memo_new = Memo.new
# @memo = Memo.find_by_id(params[:id])
# @forum = Forum.find(params[:forum_id])
# @replies = @memo.replies
# @mome_new = Memo.new
respond_to do |format|
format.html # show.html.erb
format.json { render json: @memo }
format.xml { render xml: @memo }
end
end
def edit
@replying = false
end
def update
respond_to do |format|
if( @memo.update_column(:subject, params[:memo][:subject]) &&
@memo.update_column(:content, params[:memo][:content]) &&
@memo.update_column(:sticky, params[:memo][:sticky]) &&
@memo.update_column(:lock, params[:memo][:lock]))
@memo.save_attachments(params[:attachments] || (params[:memo] && params[:memo][:uploads]))
# @memo.root.update_attribute(:updated_at, @memo.updated_at)
format.html {redirect_to back_memo_url, notice: "#{l :label_memo_create_succ}"}
else
format.html { render action: "edit" }
format.json { render json: @person.errors, status: :unprocessable_entity }
end
end
end
def destroy
@memo.destroy
respond_to do |format|
# format.html { redirect_to @back_url }
format.html { redirect_to back_memo_or_forum_url }
format.json { head :no_content }
end
end
private
def find_memo
return unless find_forum
#@memo = @forum.memos.find(params[:id])
@memo = Memo.find(params[:id])
rescue ActiveRecord::RecordNotFound
render_404
nil
end
def find_forum
@forum = Forum.find(params[:forum_id])
rescue ActiveRecord::RecordNotFound
render_404
nil
end
def authenticate_user_edit
find_memo
render_403 unless @memo.editable_by? User.current
end
def authenticate_user_destroy
find_memo
render_403 unless @memo.destroyable_by? User.current
end
def back_memo_url
forum_memo_path(@forum, (@memo.parent_id.nil? ? @memo : @memo.parent_id))
end
def back_memo_or_forum_url
@memo.parent_id.nil? ? forum_url(@forum) : forum_memo_url(@forum, @memo.parent_id)
end
end
class MemosController < ApplicationController
default_search_scope :memos
before_filter :find_forum, :only => [:new, :create, :preview]
before_filter :find_attachments, :only => [:preview]
before_filter :find_memo, :except => [:new, :create, :preview]
before_filter :authenticate_user_edit, :only => [:edit, :update]
before_filter :authenticate_user_destroy, :only => [:destroy]
before_filter :require_login, :only => [:new, :create]
helper :attachments
include AttachmentsHelper
include ApplicationHelper
layout 'base_memos'
def quote
@subject = @memo.subject
@subject = "RE: #{@subject}" unless @subject.starts_with?('RE:')
@content = "#{ll(Setting.default_language, :text_user_wrote, @memo.author)} <br/> &nbsp; "
@content << @memo.content.to_s.strip.gsub(%r{<pre>((.|\s)*?)</pre>}m, '[...]').gsub(/(\r?\n|\r\n?)/, "\n") + "</blockquote>\n\n<br/>"
@content = "<blockquote style='word-break: break-all;word-wrap: break-word;'>" << @content
#@content = "> #{ll(Setting.default_language, :text_user_wrote, @memo.author)}\n> "
#@content << @memo.content.to_s.strip.gsub(%r{<pre>((.|\s)*?)</pre>}m, '[...]').gsub(/(\r?\n|\r\n?)/, "\n> ") + "\n\n"
#@content_html = textilizable(@content)
@temp = Memo.new
@temp.content = @content
end
def new
@memo = Memo.new
@memo.forum_id = @forum.id
respond_to do |format|
format.html {
render action: :new ,layout: 'base'
}
format.json { render json: @memo }
end
end
def create
if params[:quote].nil?
@quote = ""
else
@quote = params[:quote]
end
#unless params[:quote].nil?
# @quote = params[:quote][:quote]
#end
@memo = Memo.new(params[:memo])
@memo.forum_id = params[:forum_id]
@memo.author_id = User.current.id
@memo.save_attachments(params[:attachments] || (params[:memo] && params[:memo][:uploads]))
@memo.content = @quote + @memo.content
respond_to do |format|
if @memo.save
format.html { redirect_to back_memo_url, notice: "#{l :label_memo_create_succ}" }
format.json { render json: @memo, status: :created, location: @memo }
else
flash.now[:error] = "#{l :label_memo_create_fail}: #{@memo.errors.full_messages[0]}"
# back_error_page = @memo.parent_id.nil? ? forum_path(@forum) : forum_memo_path(@forum, @memo.parent_id)
pre_count = REPLIES_PER_PAGE
@memo_new = @memo.dup
@memo = @memo.root # 取出楼主防止输入帖子id让回复作为主贴显示
unless @memo.new_record?
@memo.update_column(:viewed_count, (@memo.viewed_count.to_i + 1))
end
page = params[:page]
if params[:r] && page.nil?
offset = @memo.children.where("#{Memo.table_name}.id < ?", params[:r].to_i).count
page = 1 + offset / pre_count
else
end
@reply_count = @memo.children.count
@reply_pages = Paginator.new @reply_count, pre_count, page
@replies = @memo.children.
includes(:author, :attachments).
reorder("#{Memo.table_name}.created_at DESC").
limit(@reply_pages.per_page).
offset(@reply_pages.offset).
all
if @memo.new_record?
format.html { render :new,:layout=>'base'}
else
format.html { render action: :show }
format.json { render json: @memo.errors, status: :unprocessable_entity }
end
end
end
end
REPLIES_PER_PAGE = 20 unless const_defined?(:REPLIES_PER_PAGE)
def show
pre_count = REPLIES_PER_PAGE
@memo = @memo.root # 取出楼主防止输入帖子id让回复作为主贴显示
@memo.update_column(:viewed_count, (@memo.viewed_count.to_i + 1))
page = params[:page]
if params[:r] && page.nil?
offset = @memo.children.where("#{Memo.table_name}.id < ?", params[:r].to_i).count
page = 1 + offset / pre_count
else
end
@reply_count = @memo.children.count
@reply_pages = Paginator.new @reply_count, pre_count, page
@replies = @memo.children.
includes(:author, :attachments).
reorder("#{Memo.table_name}.created_at DESC").
limit(@reply_pages.per_page).
offset(@reply_pages.offset).
all
@memo_new = Memo.new
# @memo = Memo.find_by_id(params[:id])
# @forum = Forum.find(params[:forum_id])
# @replies = @memo.replies
# @mome_new = Memo.new
respond_to do |format|
format.html # show.html.erb
format.json { render json: @memo }
format.xml { render xml: @memo }
end
end
def edit
@replying = false
end
def update
respond_to do |format|
if( @memo.update_column(:subject, params[:memo][:subject]) &&
@memo.update_column(:content, params[:memo][:content]) &&
@memo.update_column(:sticky, params[:memo][:sticky]) &&
@memo.update_column(:lock, params[:memo][:lock]))
@memo.save_attachments(params[:attachments] || (params[:memo] && params[:memo][:uploads]))
@memo.save
# @memo.root.update_attribute(:updated_at, @memo.updated_at)
format.html {redirect_to back_memo_url, notice: "#{l :label_memo_create_succ}"}
else
format.html { render action: "edit" }
format.json { render json: @person.errors, status: :unprocessable_entity }
end
end
end
def destroy
@memo.destroy
respond_to do |format|
# format.html { redirect_to @back_url }
format.html { redirect_to back_memo_or_forum_url }
format.json { head :no_content }
end
end
private
def find_memo
return unless find_forum
#@memo = @forum.memos.find(params[:id])
@memo = Memo.find(params[:id])
rescue ActiveRecord::RecordNotFound
render_404
nil
end
def find_forum
@forum = Forum.find(params[:forum_id])
rescue ActiveRecord::RecordNotFound
render_404
nil
end
def authenticate_user_edit
find_memo
render_403 unless @memo.editable_by? User.current
end
def authenticate_user_destroy
find_memo
render_403 unless @memo.destroyable_by? User.current
end
def back_memo_url
forum_memo_path(@forum, (@memo.parent_id.nil? ? @memo : @memo.parent_id))
end
def back_memo_or_forum_url
@memo.parent_id.nil? ? forum_url(@forum) : forum_memo_url(@forum, @memo.parent_id)
end
end

@ -1,159 +1,202 @@
# Redmine - project management software
# Copyright (C) 2006-2013 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 MessagesController < ApplicationController
menu_item :boards
default_search_scope :messages
before_filter :find_board, :only => [:new, :preview]
before_filter :find_attachments, :only => [:preview]
before_filter :find_message, :except => [:new, :preview]
before_filter :authorize, :except => [:preview, :edit, :destroy, :new]
helper :boards
helper :watchers
helper :attachments
include AttachmentsHelper
REPLIES_PER_PAGE = 25 unless const_defined?(:REPLIES_PER_PAGE)
# Show a topic and its replies
def show
page = params[:page]
# Find the page of the requested reply
if params[:r] && page.nil?
offset = @topic.children.count(:conditions => ["#{Message.table_name}.id < ?", params[:r].to_i])
page = 1 + offset / REPLIES_PER_PAGE
end
@reply_count = @topic.children.count
@reply_pages = Paginator.new @reply_count, REPLIES_PER_PAGE, page
@replies = @topic.children.
includes(:author, :attachments, {:board => :project}).
reorder("#{Message.table_name}.created_on DESC").
limit(@reply_pages.per_page).
offset(@reply_pages.offset).
all
@reply = Message.new(:subject => "RE: #{@message.subject}")
if @course
render :action => "show", :layout => "base_courses"#by young
else
render :action => "show", :layout => "base_projects"#by young
end
end
# Create a new topic
def new
@message = Message.new
@message.author = User.current
@message.board = @board
@message.safe_attributes = params[:message]
if request.post?
@message.save_attachments(params[:attachments])
if @message.save
call_hook(:controller_messages_new_after_save, { :params => params, :message => @message})
render_attachment_warning_if_needed(@message)
redirect_to board_message_path(@board, @message)
else
layout_file = @project ? 'base_projects' : 'base_courses'
render :action => 'new', :layout => layout_file
end
end
end
# Reply to a topic
def reply
@reply = Message.new
@reply.author = User.current
@reply.board = @board
@reply.safe_attributes = params[:reply]
@topic.children << @reply
@topic.update_attribute(:updated_on, Time.now)
if !@reply.new_record?
call_hook(:controller_messages_reply_after_save, { :params => params, :message => @reply})
attachments = Attachment.attach_files(@reply, params[:attachments])
render_attachment_warning_if_needed(@reply)
else
#render file: 'messages#show', layout: 'base_courses'
end
redirect_to board_message_path(@board, @topic, :r => @reply)
end
# Edit a message
def edit
(render_403; return false) unless @message.editable_by?(User.current)
@message.safe_attributes = params[:message]
if request.post? && @message.save
attachments = Attachment.attach_files(@message, params[:attachments])
render_attachment_warning_if_needed(@message)
flash[:notice] = l(:notice_successful_update)
@message.reload
redirect_to board_message_path(@message.board, @message.root, :r => (@message.parent_id && @message.id))
end
end
# Delete a messages
def destroy
(render_403; return false) unless @message.destroyable_by?(User.current)
r = @message.to_param
@message.destroy
if @message.parent
redirect_to board_message_path(@board, @message.parent, :r => r)
else
redirect_to project_board_path(@project, @board)
end
end
def quote
@subject = @message.subject
@subject = "RE: #{@subject}" unless @subject.starts_with?('RE:')
@content = "> #{ll(Setting.default_language, :text_user_wrote, @message.author)}\n> "
@content << @message.content.to_s.strip.gsub(%r{<pre>((.|\s)*?)</pre>}m, '[...]').gsub(/(\r?\n|\r\n?)/, "\n> ") + "\n\n"
end
def preview
message = @board.messages.find_by_id(params[:id])
@text = (params[:message] || params[:reply])[:content]
@previewed = message
render :partial => 'common/preview'
end
private
def find_message
return unless find_board
@message = @board.messages.find(params[:id], :include => :parent)
@topic = @message.root
rescue ActiveRecord::RecordNotFound
render_404
end
def find_board
#modify by nwb
@board = Board.find(params[:board_id])
if @board.project_id != -1 && @board.project_id != nil
@project = @board.project
elsif @board.course_id
@course = @board.course
end
rescue ActiveRecord::RecordNotFound
render_404
nil
end
end
# Redmine - project management software
# Copyright (C) 2006-2013 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 MessagesController < ApplicationController
include ApplicationHelper
menu_item :boards
default_search_scope :messages
before_filter :find_board, :only => [:new, :preview,:edit]
before_filter :find_attachments, :only => [:preview]
before_filter :find_message, :except => [:new, :preview]
before_filter :authorize, :except => [:preview, :edit, :destroy, :new]
helper :boards
helper :watchers
helper :attachments
include AttachmentsHelper
helper :project_score
REPLIES_PER_PAGE = 25 unless const_defined?(:REPLIES_PER_PAGE)
# Show a topic and its replies
def show
@isReply = true
page = params[:page]
# Find the page of the requested reply
if params[:r] && page.nil?
offset = @topic.children.count(:conditions => ["#{Message.table_name}.id < ?", params[:r].to_i])
page = 1 + offset / REPLIES_PER_PAGE
end
@reply_count = @topic.children.count
@reply_pages = Paginator.new @reply_count, REPLIES_PER_PAGE, page
@replies = @topic.children.
includes(:author, :attachments, {:board => :project}).
reorder("#{Message.table_name}.created_on DESC").
limit(@reply_pages.per_page).
offset(@reply_pages.offset).
all
@reply = Message.new(:subject => "RE: #{@message.subject}")
if @course
render :action => "show", :layout => "base_courses"#by young
else
render :action => "show", :layout => "base_projects"#by young
end
end
# Create a new topic
def new
@message = Message.new
@message.author = User.current
@message.board = @board
@message.safe_attributes = params[:message]
if request.post?
@message.save_attachments(params[:attachments])
if @message.save
call_hook(:controller_messages_new_after_save, { :params => params, :message => @message})
render_attachment_warning_if_needed(@message)
redirect_to board_message_url(@board, @message)
else
layout_file = @project ? 'base_projects' : 'base_courses'
render :action => 'new', :layout => layout_file
end
end
end
# Reply to a topic
def reply
if params[:reply][:content] == ""
(redirect_to board_message_url(@board, @topic, :r => @reply), :notice => l(:label_reply_empty);return)
end
@quote = params[:quote][:quote]
@reply = Message.new
@reply.author = User.current
@reply.board = @board
@reply.safe_attributes = params[:reply]
@reply.content = @quote + @reply.content
@topic.children << @reply
#@topic.update_attribute(:updated_on, Time.now)
if !@reply.new_record?
call_hook(:controller_messages_reply_after_save, { :params => params, :message => @reply})
attachments = Attachment.attach_files(@reply, params[:attachments])
render_attachment_warning_if_needed(@reply)
else
#render file: 'messages#show', layout: 'base_courses'
end
redirect_to board_message_url(@board, @topic, :r => @reply)
end
# Edit a message
def edit
@isReply = false
if @project
(render_403; return false) unless @message.editable_by?(User.current)
else
(render_403; return false) unless @message.course_editable_by?(User.current)
end
@message.safe_attributes = params[:message]
if request.post? && @message.save
attachments = Attachment.attach_files(@message, params[:attachments])
render_attachment_warning_if_needed(@message)
flash[:notice] = l(:notice_successful_update)
@message.reload
redirect_to board_message_url(@message.board, @message.root, :r => (@message.parent_id && @message.id))
elsif request.get?
respond_to do |format|
format.html {
layout_file = @project ? 'base_projects' : 'base_courses'
render :layout => layout_file
}
end
end
end
# Delete a messages
def destroy
if @project
(render_403; return false) unless @message.destroyable_by?(User.current)
else
(render_403; return false) unless @message.course_destroyable_by?(User.current)
end
r = @message.to_param
@message.destroy
# modify by nwb
if @project
if @message.parent
redirect_to board_message_url(@board, @message.parent, :r => r)
else
redirect_to project_boards_url(@project)
end
elsif @course
if @message.parent
redirect_to board_message_url(@board, @message.parent, :r => r)
else
redirect_to course_board_url(@course, @board)
end
end
end
def quote
@subject = @message.subject
@subject = "RE: #{@subject}" unless @subject.starts_with?('RE:')
@content = "> #{ll(Setting.default_language, :text_user_wrote, @message.author)}\n> "
@temp = Message.new
#@temp.content = "> #{ll(Setting.default_language, :text_user_wrote, @message.author)}> "
@content << @message.content.to_s.strip.gsub(%r{<pre>((.|\s)*?)</pre>}m, '[...]').gsub(/(\r?\n|\r\n?)/, "\n> ") + "\n\n"
@content_html = textilizable(@content)
@temp.content = @content_html
#@content = "#{ll(Setting.default_language, :text_user_wrote, @message.author)} <br/> &nbsp; "
#@content << @message.content.to_s.strip.gsub(%r{<pre>((.|\s)*?)</pre>}m, '[...]').gsub(/(\r?\n|\r\n?)/, "\n") + "</blockquote>\n\n<br/>"
#@content = "<blockquote>" << @content
#@temp = Message.new
#@temp.content = @content
end
def preview
message = @board.messages.find_by_id(params[:id])
@text = (params[:message] || params[:reply])[:content]
@previewed = message
render :partial => 'common/preview'
end
private
def find_message
return unless find_board
@message = @board.messages.find(params[:id], :include => :parent)
@topic = @message.root
rescue ActiveRecord::RecordNotFound
render_404
end
def find_board
#modify by nwb
@board = Board.find(params[:board_id])
if @board.project_id != -1 && @board.project_id != nil
@project = @board.project
elsif @board.course_id
@course = @board.course
end
rescue ActiveRecord::RecordNotFound
render_404
nil
end
end

@ -1,217 +1,286 @@
# Redmine - project management software
# Copyright (C) 2006-2013 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 MyController < ApplicationController
before_filter :require_login
helper :issues
helper :users
helper :custom_fields
BLOCKS = { 'issuesassignedtome' => :label_assigned_to_me_issues,
'issuesreportedbyme' => :label_reported_issues,
'issueswatched' => :label_watched_issues,
'news' => :label_news_latest,
'calendar' => :label_calendar,
'documents' => :label_document_plural,
'timelog' => :label_spent_time
}.merge(Redmine::Views::MyPage::Block.additional_blocks).freeze
DEFAULT_LAYOUT = { 'left' => ['issuesassignedtome'],
'right' => ['issuesreportedbyme']
}.freeze
def index
page
render :action => 'page'
end
# Show user's page
def page
@user = User.current
@blocks = @user.pref[:my_page_layout] || DEFAULT_LAYOUT
end
# Edit user's account
def account
@user = User.current
@pref = @user.pref
if request.post?
@user.safe_attributes = params[:user]
@user.pref.attributes = params[:pref]
@user.pref[:no_self_notified] = (params[:no_self_notified] == '1')
@user.login = params[:login]
unless @user.user_extensions.nil?
if @user.user_extensions.identity == 2
@user.firstname = params[:enterprise_name]
end
end
@se = @user.extensions
@se.school_id = params[:occupation] if params[:occupation]
@se.gender = params[:gender]
@se.location = params[:province] if params[:province]
@se.location_city = params[:city] if params[:city]
@se.identity = params[:identity].to_i if params[:identity]
@se.technical_title = params[:technical_title] if params[:technical_title]
@se.student_id = params[:no] if params[:no]
if @user.save && @se.save
@user.pref.save
@user.notified_project_ids = (@user.mail_notification == 'selected' ? params[:notified_project_ids] : [])
set_language_if_valid @user.language
flash[:notice] = l(:notice_account_updated)
redirect_to user_path(@user)
return
else
@user
end
end
end
# Destroys user's account
def destroy
@user = User.current
unless @user.own_account_deletable?
redirect_to my_account_path
return
end
if request.post? && params[:confirm]
@user.destroy
if @user.destroyed?
logout_user
flash[:notice] = l(:notice_account_deleted)
end
redirect_to home_path
end
end
# Manage user's password
def password
@user = User.current
unless @user.change_password_allowed?
flash[:error] = l(:notice_can_t_change_password)
redirect_to my_account_path
return
end
if request.post?
if @user.check_password?(params[:password])
@user.password, @user.password_confirmation = params[:new_password], params[:new_password_confirmation]
if @user.save
flash[:notice] = l(:notice_account_password_updated)
redirect_to my_account_path
end
else
flash[:error] = l(:notice_account_wrong_password)
end
end
end
# Create a new feeds key
def reset_rss_key
if request.post?
if User.current.rss_token
User.current.rss_token.destroy
User.current.reload
end
User.current.rss_key
flash[:notice] = l(:notice_feeds_access_key_reseted)
end
redirect_to my_account_path
end
# Create a new API key
def reset_api_key
if request.post?
if User.current.api_token
User.current.api_token.destroy
User.current.reload
end
User.current.api_key
flash[:notice] = l(:notice_api_access_key_reseted)
end
redirect_to my_account_path
end
# User's page layout configuration
def page_layout
@user = User.current
@blocks = @user.pref[:my_page_layout] || DEFAULT_LAYOUT.dup
@block_options = []
BLOCKS.each do |k, v|
unless %w(top left right).detect {|f| (@blocks[f] ||= []).include?(k)}
@block_options << [l("my.blocks.#{v}", :default => [v, v.to_s.humanize]), k.dasherize]
end
end
end
# Add a block to user's page
# The block is added on top of the page
# params[:block] : id of the block to add
def add_block
block = params[:block].to_s.underscore
if block.present? && BLOCKS.key?(block)
@user = User.current
layout = @user.pref[:my_page_layout] || {}
# remove if already present in a group
%w(top left right).each {|f| (layout[f] ||= []).delete block }
# add it on top
layout['top'].unshift block
@user.pref[:my_page_layout] = layout
@user.pref.save
end
redirect_to my_page_layout_path
end
# Remove a block to user's page
# params[:block] : id of the block to remove
def remove_block
block = params[:block].to_s.underscore
@user = User.current
# remove block in all groups
layout = @user.pref[:my_page_layout] || {}
%w(top left right).each {|f| (layout[f] ||= []).delete block }
@user.pref[:my_page_layout] = layout
@user.pref.save
redirect_to my_page_layout_path
end
# Change blocks order on user's page
# params[:group] : group to order (top, left or right)
# params[:list-(top|left|right)] : array of block ids of the group
def order_blocks
group = params[:group]
@user = User.current
if group.is_a?(String)
group_items = (params["blocks"] || []).collect(&:underscore)
group_items.each {|s| s.sub!(/^block_/, '')}
if group_items and group_items.is_a? Array
layout = @user.pref[:my_page_layout] || {}
# remove group blocks if they are presents in other groups
%w(top left right).each {|f|
layout[f] = (layout[f] || []) - group_items
}
layout[group] = group_items
@user.pref[:my_page_layout] = layout
@user.pref.save
end
end
render :nothing => true
end
end
# Redmine - project management software
# Copyright (C) 2006-2013 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 MyController < ApplicationController
layout "users_base"
before_filter :require_login
helper :issues
helper :users
helper :custom_fields
BLOCKS = { 'issuesassignedtome' => :label_assigned_to_me_issues,
'issuesreportedbyme' => :label_reported_issues,
'issueswatched' => :label_watched_issues,
'news' => :label_news_latest,
'calendar' => :label_calendar,
'documents' => :label_document_plural,
'timelog' => :label_spent_time
}.merge(Redmine::Views::MyPage::Block.additional_blocks).freeze
DEFAULT_LAYOUT = { 'left' => ['issuesassignedtome'],
'right' => ['issuesreportedbyme']
}.freeze
def index
page
render :action => 'page'
end
# Show user's page
def page
@user = User.current
@Issues= Issue.visible.open.
where(:assigned_to_id => ([User.current.id] + User.current.group_ids))
@limit = 10
@feedback_count = @Issues.count
@feedback_pages = Paginator.new @feedback_count, @limit, params['page']
@offset ||= @feedback_pages.offset
@curse_attachments = @Issues[@offset, @limit]
@blocks = @user.pref[:my_page_layout] || DEFAULT_LAYOUT
end
def page2
@limit = 10
@user = User.current
@Issues= Issue.visible.open.
where(:assigned_to_id => ([User.current.id] + User.current.group_ids))
@feedback_count = @Issues.count
@feedback_pages = Paginator.new @feedback_count, @limit, params['page']
@offset ||= @feedback_pages.offset
@curse_attachments = @Issues[@offset, @limit]
@state = false
@blocks = @user.pref[:my_page_layout] || DEFAULT_LAYOUT
respond_to do |format|
format.js
end
end
# Edit user's account
def account
@user = User.current
lg=@user.login
@pref = @user.pref
diskfile = disk_filename('User', @user.id)
diskfile1 = diskfile + 'temp'
if request.post?
@user.safe_attributes = params[:user]
@user.pref.attributes = params[:pref]
@user.pref[:no_self_notified] = (params[:no_self_notified] == '1')
@user.login = params[:login]
unless @user.user_extensions.nil?
if @user.user_extensions.identity == 2
@user.firstname = params[:enterprise_name]
end
end
@se = @user.extensions
if params[:occupation].to_i.to_s == params[:occupation]
@se.school_id = params[:occupation]
else
@se.occupation = params[:occupation]
end
@se.gender = params[:gender]
@se.location = params[:province] if params[:province]
@se.location_city = params[:city] if params[:city]
@se.identity = params[:identity].to_i if params[:identity]
@se.technical_title = params[:technical_title] if params[:technical_title]
@se.student_id = params[:no] if params[:no]
if @user.save && @se.save
# 头像保存
if File.exist?(diskfile1)
if File.exist?(diskfile)
File.delete(diskfile)
end
File.open(diskfile1, "rb") do |f|
buffer = f.read(10)
if buffer != "DELETE"
File.open(diskfile1, "rb") do |f1|
File.open(diskfile, "wb") do |f|
buffer = ""
while (buffer = f1.read(8192))
f.write(buffer)
end
end
end
# File.rename(diskfile + 'temp',diskfile);
end
end
end
# 确保文件被删除
if File.exist?(diskfile1)
File.delete(diskfile1)
end
@user.pref.save
@user.notified_project_ids = (@user.mail_notification == 'selected' ? params[:notified_project_ids] : [])
set_language_if_valid @user.language
flash[:notice] = l(:notice_account_updated)
redirect_to user_url(@user)
return
else
# 确保文件被删除
if File.exist?(diskfile1)
File.delete(diskfile1)
end
@user.login = lg
end
else
# 确保文件被删除
if File.exist?(diskfile1)
File.delete(diskfile1)
end
end
end
# Destroys user's account
def destroy
@user = User.current
unless @user.own_account_deletable?
redirect_to my_account_url
return
end
if request.post? && params[:confirm]
@user.destroy
if @user.destroyed?
logout_user
flash.now[:notice] = l(:notice_account_deleted)
end
redirect_to home_url
end
end
# Manage user's password
def password
@user = User.current
unless @user.change_password_allowed?
flash.now[:error] = l(:notice_can_t_change_password)
redirect_to my_account_url
return
end
if request.post?
if @user.check_password?(params[:password])
@user.password, @user.password_confirmation = params[:new_password], params[:new_password_confirmation]
if @user.save
flash.now[:notice] = l(:notice_account_password_updated)
redirect_to my_account_url
end
else
flash.now[:error] = l(:notice_account_wrong_password)
end
end
end
# Create a new feeds key
def reset_rss_key
if request.post?
if User.current.rss_token
User.current.rss_token.destroy
User.current.reload
end
User.current.rss_key
flash[:notice] = l(:notice_feeds_access_key_reseted)
end
redirect_to my_account_url
end
# Create a new API key
def reset_api_key
if request.post?
if User.current.api_token
User.current.api_token.destroy
User.current.reload
end
User.current.api_key
flash[:notice] = l(:notice_api_access_key_reseted)
end
redirect_to my_account_url
end
# User's page layout configuration
def page_layout
@user = User.current
@blocks = @user.pref[:my_page_layout] || DEFAULT_LAYOUT.dup
@block_options = []
BLOCKS.each do |k, v|
unless %w(top left right).detect {|f| (@blocks[f] ||= []).include?(k)}
@block_options << [l("my.blocks.#{v}", :default => [v, v.to_s.humanize]), k.dasherize]
end
end
end
# Add a block to user's page
# The block is added on top of the page
# params[:block] : id of the block to add
def add_block
block = params[:block].to_s.underscore
if block.present? && BLOCKS.key?(block)
@user = User.current
layout = @user.pref[:my_page_layout] || {}
# remove if already present in a group
%w(top left right).each {|f| (layout[f] ||= []).delete block }
# add it on top
layout['top'].unshift block
@user.pref[:my_page_layout] = layout
@user.pref.save
end
redirect_to my_page_layout_url
end
# Remove a block to user's page
# params[:block] : id of the block to remove
def remove_block
block = params[:block].to_s.underscore
@user = User.current
# remove block in all groups
layout = @user.pref[:my_page_layout] || {}
%w(top left right).each {|f| (layout[f] ||= []).delete block }
@user.pref[:my_page_layout] = layout
@user.pref.save
redirect_to my_page_layout_url
end
# Change blocks order on user's page
# params[:group] : group to order (top, left or right)
# params[:list-(top|left|right)] : array of block ids of the group
def order_blocks
group = params[:group]
@user = User.current
if group.is_a?(String)
group_items = (params["blocks"] || []).collect(&:underscore)
group_items.each {|s| s.sub!(/^block_/, '')}
if group_items and group_items.is_a? Array
layout = @user.pref[:my_page_layout] || {}
# remove group blocks if they are presents in other groups
%w(top left right).each {|f|
layout[f] = (layout[f] || []) - group_items
}
layout[group] = group_items
@user.pref[:my_page_layout] = layout
@user.pref.save
end
end
render :nothing => true
end
end

@ -1,172 +1,180 @@
# Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class NewsController < ApplicationController
layout 'base_projects'# by young
default_search_scope :news
model_object News
before_filter :find_model_object, :except => [:new, :create, :index]
before_filter :find_project_from_association, :except => [:new, :create, :index]
before_filter :find_project_by_project_id, :only => [:new, :create]
before_filter :authorize, :except => [:index]
before_filter :find_optional_project, :only => :index
accept_rss_auth :index
accept_api_auth :index
helper :watchers
helper :attachments
def index
case params[:format]
when 'xml', 'json'
@offset, @limit = api_offset_and_limit
else
@limit = 10
end
# modify by nwb
if params[:course_id] && @course==nil
@course = Course.find(params[:course_id])
end
if @project
scope = @project ? @project.news.visible : News.visible
@news_count = scope.count
@news_pages = Paginator.new @news_count, @limit, params['page']
@offset ||= @news_pages.offset
@newss = scope.all(:include => [:author, :project],
:order => "#{News.table_name}.created_on DESC",
:offset => @offset,
:limit => @limit)
respond_to do |format|
format.html {
@news = News.new # for adding news inline
# huang
render :layout => false if request.xhr?
}
format.api
format.atom { render_feed(@newss, :title => (@project ? @project.name : Setting.app_title) + ": #{l(:label_news_plural)}") }
end
elsif @course
scope = @course ? @course.news.course_visible : News.course_visible
@news_count = scope.count
@news_pages = Paginator.new @news_count, @limit, params['page']
@offset ||= @news_pages.offset
@newss = scope.all(:include => [:author, :course],
:order => "#{News.table_name}.created_on DESC",
:offset => @offset,
:limit => @limit)
respond_to do |format|
format.html {
@news = News.new
render :layout => 'base_courses'
}
format.api
format.atom { render_feed(@newss, :title => (@course ? @course.name : Setting.app_title) + ": #{l(:label_news_plural)}") }
end
end
end
def show
@comments = @news.comments
@comments.reverse! if User.current.wants_comments_in_reverse_order?
#modify by nwb
if @news.course_id
@course = Course.find(@news.course_id)
if @course
render :layout => 'base_courses'
end
end
end
def new
@news = News.new(:project => @project, :author => User.current)
@course_tag = @project.project_type
if @course_tag
render :layout => 'base_courses'
end
end
def create
#modify by nwb
if @project
@news = News.new(:project => @project, :author => User.current)
@news.safe_attributes = params[:news]
@news.save_attachments(params[:attachments])
if @news.save
render_attachment_warning_if_needed(@news)
flash[:notice] = l(:notice_successful_create)
redirect_to project_news_index_path(@project)
else
layout_file = @project ? 'base_projects' : 'base_courses'
render :action => 'new', :layout => layout_file
end
elsif @course
@news = News.new(:course => @course, :author => User.current)
@news.safe_attributes = params[:news]
@news.save_attachments(params[:attachments])
if @news.save
render_attachment_warning_if_needed(@news)
flash[:notice] = l(:notice_successful_create)
redirect_to course_news_index_path(@course)
else
layout_file = 'base_courses'
render :action => 'new', :layout => layout_file
end
end
end
def edit
end
def update
@news.safe_attributes = params[:news]
@news.save_attachments(params[:attachments])
if @news.save
render_attachment_warning_if_needed(@news)
flash[:notice] = l(:notice_successful_update)
redirect_to news_path(@news)
else
render :action => 'edit'
end
end
def destroy
@news.destroy
# modify by nwb
if @project
redirect_to project_news_index_path(@project)
elsif @course
redirect_to course_news_index_path(@course)
end
end
private
def find_optional_project
return true unless params[:project_id]
@project = Project.find(params[:project_id])
authorize
rescue ActiveRecord::RecordNotFound
render_404
end
end
# Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class NewsController < ApplicationController
layout 'base_projects'# by young
default_search_scope :news
model_object News
before_filter :find_model_object, :except => [:new, :create, :index]
before_filter :find_project_from_association, :except => [:new, :create, :index]
before_filter :find_project_by_project_id, :only => [:new, :create]
before_filter :authorize, :except => [:index]
before_filter :find_optional_project, :only => :index
accept_rss_auth :index
accept_api_auth :index
helper :watchers
helper :attachments
helper :project_score
def index
case params[:format]
when 'xml', 'json'
@offset, @limit = api_offset_and_limit
else
@limit = 10
end
# modify by nwb
if params[:course_id] && @course==nil
@course = Course.find(params[:course_id])
end
if @project
scope = @project ? @project.news.visible : News.visible
@news_count = scope.count
@news_pages = Paginator.new @news_count, @limit, params['page']
@offset ||= @news_pages.offset
@newss = scope.all(:include => [:author, :project],
:order => "#{News.table_name}.created_on DESC",
:offset => @offset,
:limit => @limit)
respond_to do |format|
format.html {
@news = News.new # for adding news inline
# huang
render :layout => false if request.xhr?
}
format.api
format.atom { render_feed(@newss, :title => (@project ? @project.name : Setting.app_title) + ": #{l(:label_news_plural)}") }
end
elsif @course
if (User.current.admin? || @course.is_public == 1 || (@course.is_public == 0 && User.current.member_of_course?(@course)))
scope = @course ? @course.news.course_visible : News.course_visible
@news_count = scope.count
@news_pages = Paginator.new @news_count, @limit, params['page']
@offset ||= @news_pages.offset
@newss = scope.all(:include => [:author, :course],
:order => "#{News.table_name}.created_on DESC",
:offset => @offset,
:limit => @limit)
respond_to do |format|
format.html {
@news = News.new
render :layout => 'base_courses'
}
format.api
format.atom { render_feed(@newss, :title => (@course ? @course.name : Setting.app_title) + ": #{l(:label_news_plural)}") }
end
else
render_403
end
end
end
def show
@comments = @news.comments
@comments.reverse! if User.current.wants_comments_in_reverse_order?
#modify by nwb
if @news.course_id
@course = Course.find(@news.course_id)
if @course
render :layout => 'base_courses'
end
end
end
def new
#modify by nwb
if @project
@news = News.new(:project => @project, :author => User.current)
elsif @course
@news = News.new(:course => @course, :author => User.current)
render :layout => 'base_courses'
end
end
def create
#modify by nwb
if @project
@news = News.new(:project => @project, :author => User.current)
@news.safe_attributes = params[:news]
@news.save_attachments(params[:attachments])
if @news.save
render_attachment_warning_if_needed(@news)
flash[:notice] = l(:notice_successful_create)
redirect_to project_news_index_url(@project)
else
layout_file = @project ? 'base_projects' : 'base_courses'
render :action => 'new', :layout => layout_file
end
elsif @course
@news = News.new(:course => @course, :author => User.current)
@news.safe_attributes = params[:news]
@news.save_attachments(params[:attachments])
if @news.save
render_attachment_warning_if_needed(@news)
flash[:notice] = l(:notice_successful_create)
redirect_to course_news_index_url(@course)
else
layout_file = 'base_courses'
render :action => 'new', :layout => layout_file
end
end
end
def edit
end
def update
@news.safe_attributes = params[:news]
@news.save_attachments(params[:attachments])
if @news.save
render_attachment_warning_if_needed(@news)
flash[:notice] = l(:notice_successful_update)
redirect_to news_url(@news)
else
#flash[:error] = l(:notice_successful_update)
redirect_to news_url(@news)
end
end
def destroy
@news.destroy
# modify by nwb
if @project
redirect_to project_news_index_url(@project)
elsif @course
redirect_to course_news_index_url(@course)
end
end
private
def find_optional_project
return true unless params[:project_id]
@project = Project.find(params[:project_id])
authorize
rescue ActiveRecord::RecordNotFound
render_404
end
end

@ -1,27 +1,36 @@
class NotificationcommentsController < ApplicationController
# default_search_scope :contestnotifications
# model_object Contestnotifications
# before_filter :authorize
def create
#raise Unauthorized unless @contestnotifications.notificationcommentable?
@contest = Contest.find(params[:contest_id])
@contestnotification = Contestnotification.find(params[:contestnotification_id])
# @notificaioncomment = Notificationcomment.new
# @notificaioncomment.safe_attributes = params[:notificationcomment]
# @notificaioncomment.author = User.current
comment = @contestnotification.notificationcomments.new(params[:notificationcomment].merge(author_id: User.current.id))
if comment.save
flash[:notice] = l(:label_comment_added)
end
redirect_to contest_contestnotification_path(@contest, @contestnotification)
end
def destroy
@contestnotifications.notificaioncomments.find(params[:notificaioncomment_id]).destroy
redirect_to contest_contestnotification_path(@contestnotifications)
end
end
class NotificationcommentsController < ApplicationController
def show
end
# default_search_scope :contestnotifications
# model_object Contestnotifications
# before_filter :authorize
def create
#raise Unauthorized unless @contestnotifications.notificationcommentable?
@contest = Contest.find(params[:contest_id])
@contestnotification = Contestnotification.find(params[:contestnotification_id])
# @notificaioncomment = Notificationcomment.new
# @notificaioncomment.safe_attributes = params[:notificationcomment]
# @notificaioncomment.author = User.current
comment = @contestnotification.notificationcomments.new(params[:notificationcomment].merge(author_id: User.current.id))
if comment.save
flash[:notice] = l(:label_comment_added)
end
redirect_to contest_contestnotification_url(@contest, @contestnotification)
end
def destroy
@contest = Contest.find(params[:contest_id])
@contestnotification = Contestnotification.find(params[:contestnotification_id])
notificaioncomments = Notificationcomment.find(params[:id])
notificaioncomments.destroy if notificaioncomments
#@contestnotifications = notificaioncomments.Contestnotification
#@contest = @contestnotifications.contest
#@contestnotifications.notificaioncomments.find(params[:notificaioncomment_id]).destroy
redirect_to contest_contestnotification_url(@contest,@contestnotification)
end
end

@ -1,262 +1,262 @@
class OpenSourceProjectsController < ApplicationController
before_filter :find_osp, :only => [:master_apply, :accept_master_apply, :refuse_master_apply]
before_filter :require_master, :only => [:master_apply, :accept_master_apply, :refuse_master_apply]
helper :sort
include SortHelper
helper :apply_project_masters
include ApplyProjectMastersHelper
helper :no_uses
include NoUsesHelper
# GET /open_source_projects
# GET /open_source_projects.json
def index
@app_dir = params[:app_dir]
@language = params[:language]
@created_at = params[:created_at]
per_page_option = 10
@open_source_projects = OpenSourceProject.filter(@app_dir, @language, @created_at)
@open_source_projects = @open_source_projects.like(params[:name]) if params[:name].present?
@os_project_count = @open_source_projects.count
@os_project_pages = Paginator.new @os_project_count, per_page_option, params['page']
@open_source_projects = @open_source_projects.offset(@os_project_pages.offset).limit(@os_project_pages.per_page)
@bugs = BugToOsp.order('created_at desc').limit(8)
# @open_source_projects = OpenSourceProject.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: @open_source_projects }
end
end
def master_apply
@apply = @open_source_project.apply_tips
@applicants = @open_source_project.applicants
respond_to do |format|
format.html {
render :layout => "base_opensource_p"
}
format.json { render json: @open_source_project }
end
end
# GET /open_source_projects/1
# GET /open_source_projects/1.json
def show
@open_source_project = OpenSourceProject.find(params[:id])
sort_init 'updated_at', 'desc'
sort_update 'created_at' => "#{RelativeMemo.table_name}.created_at",
'replies' => "#{RelativeMemo.table_name}.replies_count",
'updated_at' => "COALESCE (last_replies_relative_memos.created_at, #{RelativeMemo.table_name}.created_at)"
@memo = RelativeMemo.new(:open_source_project => @open_source_project)
@topic_count = @open_source_project.topics.count
@topic_pages = Paginator.new @topic_count, 10, params['page']
@memos = @open_source_project.topics.
reorder("#{RelativeMemo.table_name}.sticky DESC").
includes(:last_reply).
limit(@topic_pages.per_page).
offset(@topic_pages.offset).
order(sort_clause).
all
@bugs = @open_source_project.bugs.limit(6)
respond_to do |format|
format.html {
render :layout => "base_opensource_p"
}
format.json { render json: @open_source_project }
end
end
def allbug
@bugs = BugToOsp.visible
@bug_count = @bugs.count
@bug_pages = Paginator.new @bug_count, per_page_option, params['page']
@bugs = @bugs.includes(:bug).reorder("#{RelativeMemo.table_name}.created_at DESC").limit(@bug_pages.per_page).offset(@bug_pages.offset).all
respond_to do |format|
format.html
format.json { render json: @open_source_project }
end
end
def search
end
def showbug
@open_source_project = OpenSourceProject.find(params[:id])
sort_init 'updated_at', 'desc'
sort_update 'created_at' => "#{RelativeMemo.table_name}.created_at",
'replies' => "#{RelativeMemo.table_name}.replies_count",
'updated_at' => "COALESCE (last_replies_relative_memos.created_at, #{RelativeMemo.table_name}.created_at)"
@memo = RelativeMemo.new(:open_source_project => @open_source_project)
@topic_count = @open_source_project.bugs.count
@topic_pages = Paginator.new @topic_count, per_page_option, params['page']
@memos = @open_source_project.bugs.
reorder("#{RelativeMemo.table_name}.sticky DESC").
includes(:last_reply).
limit(@topic_pages.per_page).
offset(@topic_pages.offset).
order(sort_clause).
all
respond_to do |format|
format.html {
render :layout => "base_opensource_p"
}
format.json { render json: @open_source_project }
end
end
# added by yiang 暴力添加,请绕道
def showmemo
@open_source_project = OpenSourceProject.find(params[:id])
sort_init 'updated_at', 'desc'
sort_update 'created_at' => "#{RelativeMemo.table_name}.created_at",
'replies' => "#{RelativeMemo.table_name}.replies_count",
'updated_at' => "COALESCE (last_replies_relative_memos.created_at, #{RelativeMemo.table_name}.created_at)"
@memo = RelativeMemo.new(:open_source_project => @open_source_project)
@topic_count = @open_source_project.topics.count
@topic_pages = Paginator.new @topic_count, per_page_option, params['page']
@memos = @open_source_project.topics.
reorder("#{RelativeMemo.table_name}.sticky DESC").
includes(:last_reply).
limit(@topic_pages.per_page).
offset(@topic_pages.offset).
order(sort_clause).
all
respond_to do |format|
format.html {
render :layout => "base_opensource_p"
}
format.json { render json: @open_source_project }
end
end
# GET /open_source_projects/new
# GET /open_source_projects/new.json
def new
@open_source_project = OpenSourceProject.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: @open_source_project }
end
end
# GET /open_source_projects/1/edit
def edit
@open_source_project = OpenSourceProject.find(params[:id])
end
# POST /open_source_projects
# POST /open_source_projects.json
def create
@open_source_project = OpenSourceProject.new(params[:open_source_project])
respond_to do |format|
if @open_source_project.save
format.html { redirect_to @open_source_project, notice: 'Open source project was successfully created.' }
format.json { render json: @open_source_project, status: :created, location: @open_source_project }
else
format.html { render action: "new" }
format.json { render json: @open_source_project.errors, status: :unprocessable_entity }
end
end
end
# PUT /open_source_projects/1
# PUT /open_source_projects/1.json
def update
@open_source_project = OpenSourceProject.find(params[:id])
respond_to do |format|
if @open_source_project.update_attributes(params[:open_source_project])
format.html { redirect_to @open_source_project, notice: 'Open source project was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: @open_source_project.errors, status: :unprocessable_entity }
end
end
end
# DELETE /open_source_projects/1
# DELETE /open_source_projects/1.json
def destroy
@open_source_project = OpenSourceProject.find(params[:id])
@open_source_project.destroy
respond_to do |format|
format.html { redirect_to open_source_projects_url }
format.json { head :no_content }
end
end
def remove_condition
@app_dir = params[:app_dir]
@language = params[:language]
@created_at = params[:created_at]
redirect_to open_source_projects_path(:app_dir => @app_dir, :language => @language, :created_at => @created_at, :name => params[:name])
end
def search
# per_page_option = 10
#
# @open_source_projects = OpenSourceProject.filter(@app_dir, @language, @created_at)
# @open_source_projects = @open_source_projects.like(params[:name]) if params[:name].present?
#
# @os_project_count = @open_source_projects.count
# @os_project_pages = Paginator.new @os_project_count, per_page_option, params['page']
#
# @open_source_projects = @open_source_projects.offset(@os_project_pages.offset).limit(@os_project_pages.per_page)
redirect_to open_source_projects_path(:name => params[:name])
end
def refuse_master_apply
@apply = ApplyProjectMaster.where("user_id = ? and apply_id = ? and apply_type = 'OpenSourceProject'", params[:user_id], @open_source_project.id)
@apply.first.destory
redirect_to master_apply_open_source_project_path
end
def accept_master_apply
@apply = ApplyProjectMaster.where("user_id = ? and apply_id = ? and apply_type = 'OpenSourceProject'", params[:user_id], @open_source_project.id)
if @apply.count == 1
@apply.first.update_attributes(:status => 2)
end
redirect_to master_apply_open_source_project_path
end
private
def require_master
render_403 unless @open_source_project.admin?(User.current)
end
def find_osp
@open_source_project = OpenSourceProject.find(params[:id])
render_404 unless @open_source_project.present?
end
end
class OpenSourceProjectsController < ApplicationController
before_filter :find_osp, :only => [:master_apply, :accept_master_apply, :refuse_master_apply]
before_filter :require_master, :only => [:master_apply, :accept_master_apply, :refuse_master_apply]
helper :sort
include SortHelper
helper :apply_project_masters
include ApplyProjectMastersHelper
helper :no_uses
include NoUsesHelper
# GET /open_source_projects
# GET /open_source_projects.json
def index
@app_dir = params[:app_dir]
@language = params[:language]
@created_at = params[:created_at]
per_page_option = 10
@open_source_projects = OpenSourceProject.filter(@app_dir, @language, @created_at)
@open_source_projects = @open_source_projects.like(params[:name]) if params[:name].present?
@os_project_count = @open_source_projects.count
@os_project_pages = Paginator.new @os_project_count, per_page_option, params['page']
@open_source_projects = @open_source_projects.offset(@os_project_pages.offset).limit(@os_project_pages.per_page)
@bugs = BugToOsp.order('created_at desc').limit(8)
# @open_source_projects = OpenSourceProject.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: @open_source_projects }
end
end
def master_apply
@apply = @open_source_project.apply_tips
@applicants = @open_source_project.applicants
respond_to do |format|
format.html {
render :layout => "base_opensource_p"
}
format.json { render json: @open_source_project }
end
end
# GET /open_source_projects/1
# GET /open_source_projects/1.json
def show
@open_source_project = OpenSourceProject.find(params[:id])
sort_init 'updated_at', 'desc'
sort_update 'created_at' => "#{RelativeMemo.table_name}.created_at",
'replies' => "#{RelativeMemo.table_name}.replies_count",
'updated_at' => "COALESCE (last_replies_relative_memos.created_at, #{RelativeMemo.table_name}.created_at)"
@memo = RelativeMemo.new(:open_source_project => @open_source_project)
@topic_count = @open_source_project.topics.count
@topic_pages = Paginator.new @topic_count, 10, params['page']
@memos = @open_source_project.topics.
reorder("#{RelativeMemo.table_name}.sticky DESC").
includes(:last_reply).
limit(@topic_pages.per_page).
offset(@topic_pages.offset).
order(sort_clause).
all
@bugs = @open_source_project.bugs.limit(6)
respond_to do |format|
format.html {
render :layout => "base_opensource_p"
}
format.json { render json: @open_source_project }
end
end
def allbug
@bugs = BugToOsp.visible
@bug_count = @bugs.count
@bug_pages = Paginator.new @bug_count, per_page_option, params['page']
@bugs = @bugs.includes(:bug).reorder("#{RelativeMemo.table_name}.created_at DESC").limit(@bug_pages.per_page).offset(@bug_pages.offset).all
respond_to do |format|
format.html
format.json { render json: @open_source_project }
end
end
def search
end
def showbug
@open_source_project = OpenSourceProject.find(params[:id])
sort_init 'updated_at', 'desc'
sort_update 'created_at' => "#{RelativeMemo.table_name}.created_at",
'replies' => "#{RelativeMemo.table_name}.replies_count",
'updated_at' => "COALESCE (last_replies_relative_memos.created_at, #{RelativeMemo.table_name}.created_at)"
@memo = RelativeMemo.new(:open_source_project => @open_source_project)
@topic_count = @open_source_project.bugs.count
@topic_pages = Paginator.new @topic_count, per_page_option, params['page']
@memos = @open_source_project.bugs.
reorder("#{RelativeMemo.table_name}.sticky DESC").
includes(:last_reply).
limit(@topic_pages.per_page).
offset(@topic_pages.offset).
order(sort_clause).
all
respond_to do |format|
format.html {
render :layout => "base_opensource_p"
}
format.json { render json: @open_source_project }
end
end
# added by yiang 暴力添加,请绕道
def showmemo
@open_source_project = OpenSourceProject.find(params[:id])
sort_init 'updated_at', 'desc'
sort_update 'created_at' => "#{RelativeMemo.table_name}.created_at",
'replies' => "#{RelativeMemo.table_name}.replies_count",
'updated_at' => "COALESCE (last_replies_relative_memos.created_at, #{RelativeMemo.table_name}.created_at)"
@memo = RelativeMemo.new(:open_source_project => @open_source_project)
@topic_count = @open_source_project.topics.count
@topic_pages = Paginator.new @topic_count, per_page_option, params['page']
@memos = @open_source_project.topics.
reorder("#{RelativeMemo.table_name}.sticky DESC").
includes(:last_reply).
limit(@topic_pages.per_page).
offset(@topic_pages.offset).
order(sort_clause).
all
respond_to do |format|
format.html {
render :layout => "base_opensource_p"
}
format.json { render json: @open_source_project }
end
end
# GET /open_source_projects/new
# GET /open_source_projects/new.json
def new
@open_source_project = OpenSourceProject.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: @open_source_project }
end
end
# GET /open_source_projects/1/edit
def edit
@open_source_project = OpenSourceProject.find(params[:id])
end
# POST /open_source_projects
# POST /open_source_projects.json
def create
@open_source_project = OpenSourceProject.new(params[:open_source_project])
respond_to do |format|
if @open_source_project.save
format.html { redirect_to @open_source_project, notice: 'Open source project was successfully created.' }
format.json { render json: @open_source_project, status: :created, location: @open_source_project }
else
format.html { render action: "new" }
format.json { render json: @open_source_project.errors, status: :unprocessable_entity }
end
end
end
# PUT /open_source_projects/1
# PUT /open_source_projects/1.json
def update
@open_source_project = OpenSourceProject.find(params[:id])
respond_to do |format|
if @open_source_project.update_attributes(params[:open_source_project])
format.html { redirect_to @open_source_project, notice: 'Open source project was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: @open_source_project.errors, status: :unprocessable_entity }
end
end
end
# DELETE /open_source_projects/1
# DELETE /open_source_projects/1.json
def destroy
@open_source_project = OpenSourceProject.find(params[:id])
@open_source_project.destroy
respond_to do |format|
format.html { redirect_to open_source_projects_url }
format.json { head :no_content }
end
end
def remove_condition
@app_dir = params[:app_dir]
@language = params[:language]
@created_at = params[:created_at]
redirect_to open_source_projects_url(:app_dir => @app_dir, :language => @language, :created_at => @created_at, :name => params[:name])
end
def search
# per_page_option = 10
#
# @open_source_projects = OpenSourceProject.filter(@app_dir, @language, @created_at)
# @open_source_projects = @open_source_projects.like(params[:name]) if params[:name].present?
#
# @os_project_count = @open_source_projects.count
# @os_project_pages = Paginator.new @os_project_count, per_page_option, params['page']
#
# @open_source_projects = @open_source_projects.offset(@os_project_pages.offset).limit(@os_project_pages.per_page)
redirect_to open_source_projects_url(:name => params[:name])
end
def refuse_master_apply
@apply = ApplyProjectMaster.where("user_id = ? and apply_id = ? and apply_type = 'OpenSourceProject'", params[:user_id], @open_source_project.id)
@apply.first.destory
redirect_to master_apply_open_source_project_url
end
def accept_master_apply
@apply = ApplyProjectMaster.where("user_id = ? and apply_id = ? and apply_type = 'OpenSourceProject'", params[:user_id], @open_source_project.id)
if @apply.count == 1
@apply.first.update_attributes(:status => 2)
end
redirect_to master_apply_open_source_project_url
end
private
def require_master
render_403 unless @open_source_project.admin?(User.current)
end
def find_osp
@open_source_project = OpenSourceProject.find(params[:id])
render_404 unless @open_source_project.present?
end
end

@ -16,11 +16,10 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class PreviewsController < ApplicationController
before_filter :find_project, :find_attachments, :find_contest, except: [:contestnotification]
before_filter :find_project, :find_attachments, except: :contestnotification
def issue
@issue = @project.issues.find_by_id(params[:id]) unless params[:id].blank?
@issue = @contest.issues.find_by_id(params[:id]) unless params[:id].blank?
if @issue
@description = params[:issue] && params[:issue][:description]
if @description && @description.gsub(/(\r?\n|\n\r?)/, "\n") == @issue.description.to_s.gsub(/(\r?\n|\n\r?)/, "\n")
@ -65,12 +64,4 @@ class PreviewsController < ApplicationController
render :partial => 'common/preview'
end
private
def find_contest
contest_id = (params[:issue] && params[:issue][:contest_id]) || params[:contest_id]
@contest = Contest.find(contest_id)
rescue ActiveRecord::RecordNotFound
render_404
end
end

@ -1,42 +1,42 @@
# Redmine - project management software
# Copyright (C) 2006-2013 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 ProjectEnumerationsController < ApplicationController
before_filter :find_project_by_project_id
before_filter :authorize
def update
if request.put? && params[:enumerations]
Project.transaction do
params[:enumerations].each do |id, activity|
@project.update_or_create_time_entry_activity(id, activity)
end
end
flash[:notice] = l(:notice_successful_update)
end
redirect_to settings_project_path(@project, :tab => 'activities')
end
def destroy
@project.time_entry_activities.each do |time_entry_activity|
time_entry_activity.destroy(time_entry_activity.parent)
end
flash[:notice] = l(:notice_successful_update)
redirect_to settings_project_path(@project, :tab => 'activities')
end
end
# Redmine - project management software
# Copyright (C) 2006-2013 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 ProjectEnumerationsController < ApplicationController
before_filter :find_project_by_project_id
before_filter :authorize
def update
if request.put? && params[:enumerations]
Project.transaction do
params[:enumerations].each do |id, activity|
@project.update_or_create_time_entry_activity(id, activity)
end
end
flash[:notice] = l(:notice_successful_update)
end
redirect_to settings_project_url(@project, :tab => 'activities')
end
def destroy
@project.time_entry_activities.each do |time_entry_activity|
time_entry_activity.destroy(time_entry_activity.parent)
end
flash[:notice] = l(:notice_successful_update)
redirect_to settings_project_url(@project, :tab => 'activities')
end
end

@ -42,7 +42,7 @@ class ProjectsController < ApplicationController
before_filter :authorize_global, :only => [:new, :create,:view_homework_attaches]
before_filter :require_admin, :only => [ :copy, :archive, :unarchive, :destroy, :calendar]
before_filter :file, :statistics, :watcherlist
before_filter :find_project_repository, :only => [:show]
#before_filter :find_project_repository, :only => [:show]
# 除非项目内人员,不可查看成员, TODO: 完了写报表里去
before_filter :memberAccess, only: :member
@ -75,6 +75,8 @@ class ProjectsController < ApplicationController
helper :watchers
# helper :watcherlist
helper :words
helper :project_score
helper :user_score
### added by william
include ActsAsTaggableOn::TagsHelper
@ -103,12 +105,15 @@ class ProjectsController < ApplicationController
end
def index
render_404
#调用存储过程更新提交次数
#ActiveRecord::Base.connection.execute("CALL sp_project_status_cursor();")
#Modified by nie
@project_type = params[:project_type].to_i
per_page_option = 10
@projects_all = Project.active.visible.
joins("LEFT JOIN #{ProjectStatus.table_name} ON #{Project.table_name}.id = #{ProjectStatus.table_name}.project_id").
joins("LEFT JOIN #{ProjectStatus.table_name} ON #{Project.table_name}.id = #{ProjectStatus.table_name}.project_id").joins("LEFT JOIN #{ProjectScore.table_name} ON #{Project.table_name}.id = #{ProjectScore.table_name}.project_id").
where("#{Project.table_name}.project_type = ? ", Project::ProjectType_project)
@project_count = @projects_all.count
@ -131,7 +136,7 @@ class ProjectsController < ApplicationController
@projects = @projects_all.order("created_on desc")
@s_type = 0
when '1'
@projects = @projects_all.order("grade desc")
@projects = @projects_all.order("score desc")
@s_type = 1
when '2'
@projects = @projects_all.order("watchers_count desc")
@ -145,14 +150,15 @@ class ProjectsController < ApplicationController
@projects = @projects[@project_pages.offset, @project_pages.per_page]
else
@projects = @projects = @projects_all.order("grade desc")
@projects = @projects = @projects_all.order("score desc")
@s_type = 1
end
@projects = @projects.offset(@project_pages.offset).limit(@project_pages.per_page)
respond_to do |format|
format.html {
render :layout => 'base'
format.html {
# render :layout => 'base'
# scope = Project
# unless params[:closed]
# scope = scope.active
@ -398,21 +404,35 @@ class ProjectsController < ApplicationController
#Ended by young
def feedback
page = params[:page]
@page = params[:page]
@page = @page.to_i
# Find the page of the requested reply
@jours = @project.journals_for_messages.where('m_parent_id IS NULL').order('created_on DESC')
@limit = 10
if params[:r] && page.nil?
offset = @jours.count(:conditions => ["#{JournalsForMessage.table_name}.id > ?", params[:r].to_i])
page = 1 + offset / @limit
offset = @jours.count(:conditions => ["#{JournalsForMessage.table_name}.id > ?", params[:r].to_i])
page = 1 + offset / @limit
if params[:r] && @page.nil?
@page = page
end
@feedback_count = @jours.count
@feedback_pages = Paginator.new @feedback_count, @limit, page
@offset ||= @feedback_pages.offset
@jour = @jours[@offset, @limit]
puts @page
if @page < 0
@page = 1
end
if @page > page
@page = page
end
#@feedback_count = @jours.count
#@feedback_pages = Paginator.new @feedback_count, @limit, @page
#@offset ||= @feedback_pages.offset
@jour = paginateHelper @jours,10
@state = false
@base_courses_tag = @project.project_type
respond_to do |format|
format.html{render :layout => 'base_courses' if @base_courses_tag==1}
format.api
@ -448,24 +468,10 @@ class ProjectsController < ApplicationController
end
def new
@project_type = params[:project_type] ||= params[:course]
@issue_custom_fields = IssueCustomField.sorted.all
@trackers = Tracker.sorted.all
case @project_type
when '0' # Project
@project = Project.new
@project.safe_attributes = params[:project]
when '1' # Course
@project = Project.new
@project.safe_attributes = params[:project]
@course_tag = params[:course]
@course = Course.new
@course.safe_attributes = params[:course]
else # default Project
@project = Project.new
@project.safe_attributes = params[:project]
end
@trackers = Tracker.sorted.all
@project = Project.new
@project.safe_attributes = params[:project]
render :layout => 'base'
end
@ -478,127 +484,44 @@ class ProjectsController < ApplicationController
end
end
def create
@course_tag = params[:project][:project_type]
if(@course_tag=="1")
if User.current.user_extensions.identity#.include?(UserExtensions::TEACHER,UserExtensions::DEVELOPER)
@course = Course.new
@course.extra='course' + DateTime.parse(Time.now.to_s).strftime('%Y-%m-%d_%H-%M-%S').to_s
@course.safe_attributes = params[:project][:course]
@course.tea_id = User.current.id
# added by bai
@course.term = params[:term]
@course.time = params[:time]
#@course.school_id = params[:occupation]
@course.school_id = User.current.user_extensions.school_id
@course.setup_time = params[:setup_time]
@course.endup_time = params[:endup_time]
@course.class_period = params[:class_period]
end
end
def create
@issue_custom_fields = IssueCustomField.sorted.all
@trackers = Tracker.sorted.all
@project = Project.new
@project.user_id = User.current.id
@project.safe_attributes = params[:project]
if @course_tag == '1'
@project.identifier = @course.extra
end
if @course_tag == '1'
if User.current.user_extensions.identity == 0
if@course.save
if validate_parent_id && @project.save
@project.set_allowed_parent!(params[:project]['parent_id']) if params[:project].has_key?('parent_id')
# Add current user as a project member if he is not admin
unless User.current.admin?
r = Role.givable.find_by_id(Setting.new_project_user_role_id.to_i) || Role.givable.first
m = Member.new(:user => User.current, :roles => [r])
project = ProjectInfo.new(:user_id => User.current.id, :project_id => @project.id)
user_grades = UserGrade.create(:user_id => User.current.id, :project_id => @project.id)
if params[:project][:is_public] == '1'
project_status = ProjectStatus.create(:project_id => @project.id, :watchers_count => 0, :changesets_count => 0, :grade => 0, :project_type => @course_tag)
end
@project.members << m
@project.project_infos << project
end
respond_to do |format|
format.html {
flash[:notice] = l(:notice_successful_create)
if params[:continue]
attrs = {:parent_id => @project.parent_id}.reject {|k,v| v.nil?}
redirect_to new_project_path(attrs, :course => '0')
#Added by young
elsif params[:course_continue]
redirect_to new_project_path(:course => '1')
#Ended by young
else
redirect_to settings_project_path(@project,:project_type => 1)
end
}
format.api { render :action => 'show', :status => :created, :location => url_for(:controller => 'projects', :action => 'show', :id => @project.id) }
end
else
@course.destroy
respond_to do |format|
format.html { render :action => 'new', :layout => 'base'}#Added by young
format.api { render_validation_errors(@project) }
end
end
else
if validate_parent_id && @project.save
@project.delete
respond_to do |format|
format.html { render :action => 'new', :layout => 'base'}#Added by young
format.api { render_validation_errors(@project) }
end
if validate_parent_id && @project.save
@project.set_allowed_parent!(params[:project]['parent_id']) if params[:project].has_key?('parent_id')
# Add current user as a project member if he is not admin
#unless User.current.admin?
r = Role.givable.find_by_id(Setting.new_project_user_role_id.to_i) || Role.givable.first
m = Member.new(:user => User.current, :roles => [r])
project_info = ProjectInfo.new(:user_id => User.current.id, :project_id => @project.id)
user_grades = UserGrade.create(:user_id => User.current.id, :project_id => @project.id)
Rails.logger.debug "UserGrade created: #{user_grades.to_json}"
#if params[:project][:is_public] == '1'
project_status = ProjectStatus.create(:project_id => @project.id, :watchers_count => 0, :changesets_count => 0, :project_type => @project.project_type,:grade => 0)
Rails.logger.debug "ProjectStatus created: #{project_status.to_json}"
#end
@project.members << m
@project.project_infos << project_info
#end
respond_to do |format|
format.html {
flash[:notice] = l(:notice_successful_create)
if params[:continue]
attrs = {:parent_id => @project.parent_id}.reject {|k,v| v.nil?}
redirect_to new_project_url(attrs, :course => '0')
else
respond_to do |format|
format.html { render :action => 'new', :layout => 'base'}#Added by young
format.api { render_validation_errors(@project) }
end
redirect_to settings_project_url(@project)
end
end
}
format.api { render :action => 'show', :status => :created, :location => url_for(:controller => 'projects', :action => 'show', :id => @project.id) }
end
else
if validate_parent_id && @project.save
@project.set_allowed_parent!(params[:project]['parent_id']) if params[:project].has_key?('parent_id')
# Add current user as a project member if he is not admin
unless User.current.admin?
r = Role.givable.find_by_id(Setting.new_project_user_role_id.to_i) || Role.givable.first
m = Member.new(:user => User.current, :roles => [r])
project = ProjectInfo.new(:user_id => User.current.id, :project_id => @project.id)
user_grades = UserGrade.create(:user_id => User.current.id, :project_id => @project.id)
if params[:project][:is_public] == '1' || @course_tag=="1"
project_status = ProjectStatus.create(:project_id => @project.id, :watchers_count => 0, :changesets_count => 0, :project_type => @project.project_type)
end
@project.members << m
@project.project_infos << project
end
respond_to do |format|
format.html {
flash[:notice] = l(:notice_successful_create)
if params[:continue]
attrs = {:parent_id => @project.parent_id}.reject {|k,v| v.nil?}
redirect_to new_project_path(attrs, :course => '0')
#Added by young
elsif params[:course_continue]
redirect_to new_project_path(:course => '1')
#Ended by young
else
redirect_to settings_project_path(@project)
end
}
format.api { render :action => 'show', :status => :created, :location => url_for(:controller => 'projects', :action => 'show', :id => @project.id) }
end
else
respond_to do |format|
format.html { render :action => 'new', :layout => 'base'}#Added by young
format.api { render_validation_errors(@project) }
end
end
respond_to do |format|
format.html { render :action => 'new', :layout => 'base'}#Added by young
format.api { render_validation_errors(@project) }
end
end
end
@ -616,13 +539,13 @@ class ProjectsController < ApplicationController
if validate_parent_id && @project.copy(@source_project, :only => params[:only])
@project.set_allowed_parent!(params[:project]['parent_id']) if params[:project].has_key?('parent_id')
flash[:notice] = l(:notice_successful_create)
redirect_to settings_project_path(@project)
redirect_to settings_project_url(@project)
elsif !@project.new_record?
# Project was created
# But some objects were not copied due to validation failures
# (eg. issues from disabled trackers)
# TODO: inform about that
redirect_to settings_project_path(@project)
redirect_to settings_project_url(@project)
end
end
end
@ -633,7 +556,6 @@ class ProjectsController < ApplicationController
# Show @project
def show
@project_type = params[:project_type]
# try to redirect to the requested menu item
@ -672,6 +594,7 @@ class ProjectsController < ApplicationController
"show_news" => true,
"show_bids" => true,
"show_contests" => true,
"show_wiki_edits"=>true,
"show_journals_for_messages" => true
}
@date_to ||= Date.today + 1
@ -685,8 +608,14 @@ class ProjectsController < ApplicationController
@activity.scope_select {|t| !has["show_#{t}"].nil?}
# logger.debug "=========================================#{@activity.scope}"
# @activity.scope = (@author.nil? ? :default : :all) if @activity.scope.empty?
#Added by young
events = @activity.events(@date_from, @date_to)
# modify by nwb
# 添加私密性判断
if User.current.member_of?(@project)|| User.current.admin?
events = @activity.events(@date_from, @date_to)
else
events = @activity.events(@date_from, @date_to, :is_public => 1)
end
@offset, @limit = api_offset_and_limit({:limit => 10})
@events_count = events.count
@ -717,8 +646,8 @@ class ProjectsController < ApplicationController
@canShowRealName = isCourseTeacher(User.current.id)
end
#勿删 real_name action为虚拟的该方法并不存在用来辅助判断真名权限
#勿删 @canShowRealName = User.current.allowed_to?({:controller => "projects", :action => "real_name"}, @project || @projects, :global => false)
# real_name action为虚拟的该方法并不存在用来辅助判断真名权限
# @canShowRealName = User.current.allowed_to?({:controller => "projects", :action => "real_name"}, @project || @projects, :global => false)
respond_to do |format|
format.html{render :layout => 'base_courses' if @base_courses_tag==1}
format.api
@ -734,7 +663,7 @@ class ProjectsController < ApplicationController
#Added by young
# @course_tag = params[:course]
# if @course_tag == '1'
@course = Course.find_by_extra(@project.identifier)
#@course = Course.find_by_extra(@project.identifier)
# if @project.project_type == 1
# render :layout => 'base_courses'
# else
@ -769,8 +698,8 @@ class ProjectsController < ApplicationController
else # @project.project_type == Project::ProjectType_project
roles = Role.find_all_givable
@subPage_title = l :label_member_list
@members = @project.member_principals.includes(:roles, :principal).all
@members = sort_project_members(@project, @members)
@members = @project.member_principals.includes(:roles, :principal).joins("LEFT JOIN #{OptionNumber.table_name} ON #{OptionNumber.table_name}.user_id = #{Member.table_name}.user_id and #{OptionNumber.table_name}.score_type = 2 AND #{Member.table_name}.project_id = #{OptionNumber.table_name}.project_id").order("#{OptionNumber.table_name}.total_score DESC").all
#@members = sort_project_members(@project, @members)
@applied_members = appied_project_members(@project, @members)
end
@members = paginateHelper @members
@ -826,6 +755,7 @@ class ProjectsController < ApplicationController
def update
@project.safe_attributes = params[:project]
#@project.dts_test = params[:project][:dts_test]
if validate_parent_id && @project.save
@course = Course.find_by_extra(@project.identifier)
unless @course.nil?
@ -851,7 +781,7 @@ class ProjectsController < ApplicationController
respond_to do |format|
format.html {
flash[:notice] = l(:notice_successful_update)
redirect_to settings_project_path(@project,:course => @project.project_type)
redirect_to settings_project_url(@project,:course => @project.project_type)
}
format.api { render_api_ok }
end
@ -869,7 +799,7 @@ class ProjectsController < ApplicationController
def modules
@project.enabled_module_names = params[:enabled_module_names]
flash[:notice] = l(:notice_successful_update)
redirect_to settings_project_path(@project, :tab => 'modules')
redirect_to settings_project_url(@project, :tab => 'modules')
end
def archive
@ -878,22 +808,22 @@ class ProjectsController < ApplicationController
flash[:error] = l(:error_can_not_archive_project)
end
end
redirect_to admin_projects_path(:status => params[:status])
redirect_to admin_projects_url(:status => params[:status])
end
def unarchive
@project.unarchive if request.post? && !@project.active?
redirect_to admin_projects_path(:status => params[:status])
redirect_to admin_projects_url(:status => params[:status])
end
def close
@project.close
redirect_to project_path(@project)
redirect_to project_url(@project)
end
def reopen
@project.reopen
redirect_to project_path(@project)
redirect_to project_url(@project)
end
# Delete @project
@ -902,19 +832,21 @@ class ProjectsController < ApplicationController
if api_request? || params[:confirm]
@project_to_destroy.destroy
respond_to do |format|
format.html { redirect_to admin_projects_path }
format.html { redirect_to admin_projects_url }
format.api { render_api_ok }
end
else
render :layout => "base"
render :layout => "project_base"
end
# hide project in layout
@project = nil
end
# added by bai
def show_projects_score
render :layout => false
respond_to do |format|
format.html { render :layout => "project_base"}
format.js
end
end
def issue_score_index
@ -966,6 +898,18 @@ class ProjectsController < ApplicationController
end
end
def exit_project
@project = Project.find params[:id]
if User.current.login?
members = Member.where(:user_id => User.current.id, :project_id=>params[:id]).first
if members != nil && members.roles.first.to_s != "Manager"
members.destroy
end
respond_to do |format|
format.js
end
end
end
private
def memberAccess
@ -1112,4 +1056,5 @@ class ProjectsController < ApplicationController
end
#gcmend
end

@ -1,106 +1,106 @@
# Redmine - project management software
# Copyright (C) 2006-2013 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 QueriesController < ApplicationController
menu_item :issues
before_filter :find_query, :except => [:new, :create, :index]
before_filter :find_optional_project, :only => [:new, :create]
accept_api_auth :index
include QueriesHelper
def index
case params[:format]
when 'xml', 'json'
@offset, @limit = api_offset_and_limit
else
@limit = per_page_option
end
@query_count = IssueQuery.visible.count
@query_pages = Paginator.new @query_count, @limit, params['page']
@queries = IssueQuery.visible.all(:limit => @limit, :offset => @offset, :order => "#{Query.table_name}.name")
respond_to do |format|
format.api
end
end
def new
@query = IssueQuery.new
@query.user = User.current
@query.project = @project
@query.is_public = false unless User.current.allowed_to?(:manage_public_queries, @project) || User.current.admin?
@query.build_from_params(params)
end
def create
@query = IssueQuery.new(params[:query])
@query.user = User.current
@query.project = params[:query_is_for_all] ? nil : @project
@query.is_public = false unless User.current.allowed_to?(:manage_public_queries, @project) || User.current.admin?
@query.build_from_params(params)
@query.column_names = nil if params[:default_columns]
if @query.save
flash[:notice] = l(:notice_successful_create)
redirect_to _project_issues_path(@project, :query_id => @query)
else
render :action => 'new', :layout => !request.xhr?
end
end
def edit
end
def update
@query.attributes = params[:query]
@query.project = nil if params[:query_is_for_all]
@query.is_public = false unless User.current.allowed_to?(:manage_public_queries, @project) || User.current.admin?
@query.build_from_params(params)
@query.column_names = nil if params[:default_columns]
if @query.save
flash[:notice] = l(:notice_successful_update)
redirect_to _project_issues_path(@project, :query_id => @query)
else
render :action => 'edit'
end
end
def destroy
@query.destroy
redirect_to _project_issues_path(@project, :set_filter => 1)
end
private
def find_query
@query = IssueQuery.find(params[:id])
@project = @query.project
render_403 unless @query.editable_by?(User.current)
rescue ActiveRecord::RecordNotFound
render_404
end
def find_optional_project
@project = Project.find(params[:project_id]) if params[:project_id]
render_403 unless User.current.allowed_to?(:save_queries, @project, :global => true)
rescue ActiveRecord::RecordNotFound
render_404
end
end
# Redmine - project management software
# Copyright (C) 2006-2013 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 QueriesController < ApplicationController
menu_item :issues
before_filter :find_query, :except => [:new, :create, :index]
before_filter :find_optional_project, :only => [:new, :create]
accept_api_auth :index
include QueriesHelper
def index
case params[:format]
when 'xml', 'json'
@offset, @limit = api_offset_and_limit
else
@limit = per_page_option
end
@query_count = IssueQuery.visible.count
@query_pages = Paginator.new @query_count, @limit, params['page']
@queries = IssueQuery.visible.all(:limit => @limit, :offset => @offset, :order => "#{Query.table_name}.name")
respond_to do |format|
format.api
end
end
def new
@query = IssueQuery.new
@query.user = User.current
@query.project = @project
@query.is_public = false unless User.current.allowed_to?(:manage_public_queries, @project) || User.current.admin?
@query.build_from_params(params)
end
def create
@query = IssueQuery.new(params[:query])
@query.user = User.current
@query.project = params[:query_is_for_all] ? nil : @project
@query.is_public = false unless User.current.allowed_to?(:manage_public_queries, @project) || User.current.admin?
@query.build_from_params(params)
@query.column_names = nil if params[:default_columns]
if @query.save
flash[:notice] = l(:notice_successful_create)
redirect_to _project_issues_url(@project, :query_id => @query)
else
render :action => 'new', :layout => !request.xhr?
end
end
def edit
end
def update
@query.attributes = params[:query]
@query.project = nil if params[:query_is_for_all]
@query.is_public = false unless User.current.allowed_to?(:manage_public_queries, @project) || User.current.admin?
@query.build_from_params(params)
@query.column_names = nil if params[:default_columns]
if @query.save
flash[:notice] = l(:notice_successful_update)
redirect_to _project_issues_url(@project, :query_id => @query)
else
render :action => 'edit'
end
end
def destroy
@query.destroy
redirect_to _project_issues_url(@project, :set_filter => 1)
end
private
def find_query
@query = IssueQuery.find(params[:id])
@project = @query.project
render_403 unless @query.editable_by?(User.current)
rescue ActiveRecord::RecordNotFound
render_404
end
def find_optional_project
@project = Project.find(params[:project_id]) if params[:project_id]
render_403 unless User.current.allowed_to?(:save_queries, @project, :global => true)
rescue ActiveRecord::RecordNotFound
render_404
end
end

File diff suppressed because it is too large Load Diff

@ -1,108 +1,108 @@
# Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class RolesController < ApplicationController
layout 'admin'
before_filter :require_admin, :except => [:index, :show]
before_filter :require_admin_or_api_request, :only => [:index, :show]
before_filter :find_role, :only => [:show, :edit, :update, :destroy]
accept_api_auth :index, :show
def index
respond_to do |format|
format.html {
@role_pages, @roles = paginate Role.sorted, :per_page => 25
render :action => "index", :layout => false if request.xhr?
}
format.api {
@roles = Role.givable.all
}
end
end
def show
respond_to do |format|
format.api
end
end
def new
# Prefills the form with 'Non member' role permissions by default
@role = Role.new(params[:role] || {:permissions => Role.non_member.permissions})
if params[:copy].present? && @copy_from = Role.find_by_id(params[:copy])
@role.copy_from(@copy_from)
end
@roles = Role.sorted.all
end
def create
@role = Role.new(params[:role])
if request.post? && @role.save
# workflow copy
if !params[:copy_workflow_from].blank? && (copy_from = Role.find_by_id(params[:copy_workflow_from]))
@role.workflow_rules.copy(copy_from)
end
flash[:notice] = l(:notice_successful_create)
redirect_to roles_path
else
@roles = Role.sorted.all
render :action => 'new'
end
end
def edit
end
def update
if request.put? and @role.update_attributes(params[:role])
flash[:notice] = l(:notice_successful_update)
redirect_to roles_path
else
render :action => 'edit'
end
end
def destroy
@role.destroy
redirect_to roles_path
rescue
flash[:error] = l(:error_can_not_remove_role)
redirect_to roles_path
end
def permissions
@roles = Role.sorted.all
@permissions = Redmine::AccessControl.permissions.select { |p| !p.public? }
if request.post?
@roles.each do |role|
role.permissions = params[:permissions][role.id.to_s]
role.save
end
flash[:notice] = l(:notice_successful_update)
redirect_to roles_path
end
end
private
def find_role
@role = Role.find(params[:id])
rescue ActiveRecord::RecordNotFound
render_404
end
end
# Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class RolesController < ApplicationController
layout 'admin'
before_filter :require_admin, :except => [:index, :show]
before_filter :require_admin_or_api_request, :only => [:index, :show]
before_filter :find_role, :only => [:show, :edit, :update, :destroy]
accept_api_auth :index, :show
def index
respond_to do |format|
format.html {
@role_pages, @roles = paginate Role.sorted, :per_page => 25
render :action => "index", :layout => false if request.xhr?
}
format.api {
@roles = Role.givable.all
}
end
end
def show
respond_to do |format|
format.api
end
end
def new
# Prefills the form with 'Non member' role permissions by default
@role = Role.new(params[:role] || {:permissions => Role.non_member.permissions})
if params[:copy].present? && @copy_from = Role.find_by_id(params[:copy])
@role.copy_from(@copy_from)
end
@roles = Role.sorted.all
end
def create
@role = Role.new(params[:role])
if request.post? && @role.save
# workflow copy
if !params[:copy_workflow_from].blank? && (copy_from = Role.find_by_id(params[:copy_workflow_from]))
@role.workflow_rules.copy(copy_from)
end
flash[:notice] = l(:notice_successful_create)
redirect_to roles_url
else
@roles = Role.sorted.all
render :action => 'new'
end
end
def edit
end
def update
if request.put? and @role.update_attributes(params[:role])
flash[:notice] = l(:notice_successful_update)
redirect_to roles_url
else
render :action => 'edit'
end
end
def destroy
@role.destroy
redirect_to roles_url
rescue
flash[:error] = l(:error_can_not_remove_role)
redirect_to roles_url
end
def permissions
@roles = Role.sorted.all
@permissions = Redmine::AccessControl.permissions.select { |p| !p.public? }
if request.post?
@roles.each do |role|
role.permissions = params[:permissions][role.id.to_s]
role.save
end
flash[:notice] = l(:notice_successful_update)
redirect_to roles_url
end
end
private
def find_role
@role = Role.find(params[:id])
rescue ActiveRecord::RecordNotFound
render_404
end
end

@ -1,5 +1,5 @@
class SchoolController < ApplicationController
layout 'course_base'
before_filter :require_admin, :only => :upload_logo
def upload
@ -58,7 +58,7 @@ class SchoolController < ApplicationController
options_s = ""
school.each do |s|
options_s << "<li style = 'width: 33%; float: left'><a id=#{s.id} onclick='test(this.id, this.text)'>#{s.name}</a></li>"
options_s << "<li style = 'width: 33%; float: left'><a style='cursor: pointer;' id=#{s.id} onclick='test(this.id, this.text)'>#{s.name}</a></li>"
end
res = Hash.new
@ -78,7 +78,7 @@ class SchoolController < ApplicationController
@school.each do |s|
#options << "<option value=#{s.id}>#{s.name}</option>"
options << "<li style = 'width: 33%; float: left'><a id=#{s.id} onclick='test(this.id, this.text)'>#{s.name}</a></li>"
options << "<li style = 'width: 33%; float: left'><a style='cursor: pointer;' id=#{s.id} onclick='test(this.id, this.text)'>#{s.name}</a></li>"
end
@ -91,23 +91,25 @@ class SchoolController < ApplicationController
options = ""
@school.each do |s|
options << "<li style = 'width: 33%; float: left'><a id=#{s.id} onclick='test(this.id)'>#{s.name}</a></li>"
options << "<li style = 'width: 33%; float: left'><a style='cursor: pointer;' id=#{s.id} onclick='test(this.id)'>#{s.name}</a></li>"
end
render :text => options
end
def search_school
if params[:province].nil? or params[:province] == "0"
@school = School.where("name LIKE '%"+params[:key_word]+"%'");
else
@school = School.where("province = ? AND name LIKE '%"+params[:key_word]+"%'", params[:province]);
end
q = "%#{params[:key_word].strip}%"
@school = School.where("name LIKE ?", q)
@school = @school.where("province = ?", params[:province]) if (params[:province] != '0' )
options = ""
@school.each do |s|
options << "<li style = 'width: 33%; float: left'> <a id=#{s.id} onclick='test(this.id)'>#{s.name}</a></li>"
options << "<li style = 'width: 33%; float: left'> <a style='cursor: pointer;' id=#{s.id} onclick='test(this.id)'>#{s.name}</a></li>"
end
render :text => options
options = "<div class='flash error' id='flash_error'>#{l(:label_school_not_fount)}</div>" if options.blank?
render :text => options
end
end

@ -1,111 +1,111 @@
# Redmine - project management software
# Copyright (C) 2006-2013 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 SearchController < ApplicationController
before_filter :find_optional_project
def index
@question = params[:q] || ""
@question.strip!
@all_words = params[:all_words] ? params[:all_words].present? : true
@titles_only = params[:titles_only] ? params[:titles_only].present? : false
projects_to_search =
case params[:scope]
when 'all'
nil
when 'my_projects'
User.current.memberships.collect(&:project)
when 'subprojects'
@project ? (@project.self_and_descendants.active.all) : nil
else
@project
end
offset = nil
begin; offset = params[:offset].to_time if params[:offset]; rescue; end
# quick jump to an issue
if (m = @question.match(/^#?(\d+)$/)) && (issue = Issue.visible.find_by_id(m[1].to_i))
redirect_to issue_path(issue)
return
end
@object_types = Redmine::Search.available_search_types.dup
if projects_to_search.is_a? Project
# don't search projects
@object_types.delete('projects')
# only show what the user is allowed to view
@object_types = @object_types.select {|o| User.current.allowed_to?("view_#{o}".to_sym, projects_to_search)}
end
@scope = @object_types.select {|t| params[t]}
@scope = @object_types if @scope.empty?
# 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 2 characters long
@tokens = @tokens.uniq.select {|w| w.length > 1 }
if !@tokens.empty?
# no more than 5 tokens to search for
@tokens.slice! 5..-1 if @tokens.size > 5
@results = []
@results_by_type = Hash.new {|h,k| h[k] = 0}
limit = 10
@scope.each do |s|
r, c = s.singularize.camelcase.constantize.search(@tokens, projects_to_search,
:all_words => @all_words,
:titles_only => @titles_only,
:limit => (limit+1),
:offset => offset,
:before => params[:previous].nil?)
@results += r
@results_by_type[s] += c
end
@results = @results.sort {|a,b| b.event_datetime <=> a.event_datetime}
if params[:previous].nil?
@pagination_previous_date = @results[0].event_datetime if offset && @results[0]
if @results.size > limit
@pagination_next_date = @results[limit-1].event_datetime
@results = @results[0, limit]
end
else
@pagination_next_date = @results[-1].event_datetime if offset && @results[-1]
if @results.size > limit
@pagination_previous_date = @results[-(limit)].event_datetime
@results = @results[-(limit), limit]
end
end
else
@question = ""
end
render :layout => false if request.xhr?
end
private
def find_optional_project
return true unless params[:id]
@project = Project.find(params[:id])
check_project_privacy
rescue ActiveRecord::RecordNotFound
render_404
end
end
# Redmine - project management software
# Copyright (C) 2006-2013 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 SearchController < ApplicationController
before_filter :find_optional_project
def index
@question = params[:q] || ""
@question.strip!
@all_words = params[:all_words] ? params[:all_words].present? : true
@titles_only = params[:titles_only] ? params[:titles_only].present? : false
projects_to_search =
case params[:scope]
when 'all'
nil
when 'my_projects'
User.current.memberships.collect(&:project)
when 'subprojects'
@project ? (@project.self_and_descendants.active.all) : nil
else
@project
end
offset = nil
begin; offset = params[:offset].to_time if params[:offset]; rescue; end
# quick jump to an issue
if (m = @question.match(/^#?(\d+)$/)) && (issue = Issue.visible.find_by_id(m[1].to_i))
redirect_to issue_url(issue)
return
end
@object_types = Redmine::Search.available_search_types.dup
if projects_to_search.is_a? Project
# don't search projects
@object_types.delete('projects')
# only show what the user is allowed to view
@object_types = @object_types.select {|o| User.current.allowed_to?("view_#{o}".to_sym, projects_to_search)}
end
@scope = @object_types.select {|t| params[t]}
@scope = @object_types if @scope.empty?
# 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 2 characters long
@tokens = @tokens.uniq.select {|w| w.length > 1 }
if !@tokens.empty?
# no more than 5 tokens to search for
@tokens.slice! 5..-1 if @tokens.size > 5
@results = []
@results_by_type = Hash.new {|h,k| h[k] = 0}
limit = 10
@scope.each do |s|
r, c = s.singularize.camelcase.constantize.search(@tokens, projects_to_search,
:all_words => @all_words,
:titles_only => @titles_only,
:limit => (limit+1),
:offset => offset,
:before => params[:previous].nil?)
@results += r
@results_by_type[s] += c
end
@results = @results.sort {|a,b| b.event_datetime <=> a.event_datetime}
if params[:previous].nil?
@pagination_previous_date = @results[0].event_datetime if offset && @results[0]
if @results.size > limit
@pagination_next_date = @results[limit-1].event_datetime
@results = @results[0, limit]
end
else
@pagination_next_date = @results[-1].event_datetime if offset && @results[-1]
if @results.size > limit
@pagination_previous_date = @results[-(limit)].event_datetime
@results = @results[-(limit), limit]
end
end
else
@question = ""
end
render :layout => false if request.xhr?
end
private
def find_optional_project
return true unless params[:id]
@project = Project.find(params[:id])
check_project_privacy
rescue ActiveRecord::RecordNotFound
render_404
end
end

@ -1,73 +1,73 @@
# Redmine - project management software
# Copyright (C) 2006-2013 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 SettingsController < ApplicationController
layout 'admin'
menu_item :plugins, :only => :plugin
helper :queries
before_filter :require_admin
def index
edit
render :action => 'edit'
end
def edit
@notifiables = Redmine::Notifiable.all
if request.post? && params[:settings] && params[:settings].is_a?(Hash)
settings = (params[:settings] || {}).dup.symbolize_keys
settings.each do |name, value|
# remove blank values in array settings
value.delete_if {|v| v.blank? } if value.is_a?(Array)
Setting[name] = value
end
flash[:notice] = l(:notice_successful_update)
redirect_to settings_path(:tab => params[:tab])
else
@options = {}
user_format = User::USER_FORMATS.collect{|key, value| [key, value[:setting_order]]}.sort{|a, b| a[1] <=> b[1]}
@options[:user_format] = user_format.collect{|f| [User.current.name(f[0]), f[0].to_s]}
@deliveries = ActionMailer::Base.perform_deliveries
@guessed_host_and_path = request.host_with_port.dup
@guessed_host_and_path << ('/'+ Redmine::Utils.relative_url_root.gsub(%r{^\/}, '')) unless Redmine::Utils.relative_url_root.blank?
Redmine::Themes.rescan
end
end
def plugin
@plugin = Redmine::Plugin.find(params[:id])
unless @plugin.configurable?
render_404
return
end
if request.post?
Setting.send "plugin_#{@plugin.id}=", params[:settings]
flash[:notice] = l(:notice_successful_update)
redirect_to plugin_settings_path(@plugin)
else
@partial = @plugin.settings[:partial]
@settings = Setting.send "plugin_#{@plugin.id}"
end
rescue Redmine::PluginNotFound
render_404
end
end
# Redmine - project management software
# Copyright (C) 2006-2013 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 SettingsController < ApplicationController
layout 'admin'
menu_item :plugins, :only => :plugin
helper :queries
before_filter :require_admin
def index
edit
render :action => 'edit'
end
def edit
@notifiables = Redmine::Notifiable.all
if request.post? && params[:settings] && params[:settings].is_a?(Hash)
settings = (params[:settings] || {}).dup.symbolize_keys
settings.each do |name, value|
# remove blank values in array settings
value.delete_if {|v| v.blank? } if value.is_a?(Array)
Setting[name] = value
end
flash[:notice] = l(:notice_successful_update)
redirect_to settings_url(:tab => params[:tab])
else
@options = {}
user_format = User::USER_FORMATS.collect{|key, value| [key, value[:setting_order]]}.sort{|a, b| a[1] <=> b[1]}
@options[:user_format] = user_format.collect{|f| [User.current.name(f[0]), f[0].to_s]}
@deliveries = ActionMailer::Base.perform_deliveries
@guessed_host_and_path = request.host_with_port.dup
@guessed_host_and_path << ('/'+ Redmine::Utils.relative_url_root.gsub(%r{^\/}, '')) unless Redmine::Utils.relative_url_root.blank?
Redmine::Themes.rescan
end
end
def plugin
@plugin = Redmine::Plugin.find(params[:id])
unless @plugin.configurable?
render_404
return
end
if request.post?
Setting.send "plugin_#{@plugin.id}=", params[:settings]
flash[:notice] = l(:notice_successful_update)
redirect_to plugin_settings_url(@plugin)
else
@partial = @plugin.settings[:partial]
@settings = Setting.send "plugin_#{@plugin.id}"
end
rescue Redmine::PluginNotFound
render_404
end
end

@ -1,322 +1,356 @@
class SoftapplicationsController < ApplicationController
before_filter :find_softapplication, only: [:edit, :update, :destroy]
before_filter :editable, only: [:edit, :update]
before_filter :destroyable, only: :destroy
# GET /softapplications
# GET /softapplications.json
def index
@softapplications = Softapplication.all
#new added fenyefunction
@limit = 5
@softapplication_count = @softapplications.count
@softapplication_pages = Paginator.new @softapplication_count, @limit, params['page']
@offset ||= @softapplication_pages.offset
#@softapplications = @softapplications[@offset,@limit]
#new added end
#new added sort
if params[:softapplication_sort_type].present?
case params[:softapplication_sort_type]
when '0'
@softapplications = @softapplications[@offset, @limit]
@s_state = 0
when '1'
@softapplications = @softapplications.sort { |x, y| y[:created_at] <=> x[:created_at]}[@offset, @limit]
@s_state = 1
end
else
@softapplications = @softapplications.sort { |x, y| y[:created_at] <=> x[:created_at]}[@offset, @limit]
@s_state = 1
end
#new added end
respond_to do |format|
format.html # index.html.erb
format.json { render json: @softapplications }
end
end
# GET /softapplications/1
# GET /softapplications/1.json
def percent_of(num, percent)
num.to_f / percent.to_f * 100.0
end
def show
@softapplication = Softapplication.find(params[:id])
@project = @softapplication.project
# 打分统计
stars_reates = @softapplication.
rates(:quality)
stars_reates_count = stars_reates.count == 0 ? 1 : stars_reates.count
stars_status = stars_reates.select("stars, count(*) as scount").
group("stars")
@stars_status_map = Hash.new(0.0)
stars_status.each do |star_status|
percent = percent_of(star_status.scount, stars_reates_count).to_f
percent_m = format("%.2f", percent)
@stars_status_map["star#{star_status.stars.to_i}".to_sym] =
percent_m.to_s + "%"
end
@jours = @softapplication.journals_for_messages.order('created_on DESC')
@image_results = []
@softapplication.attachments.each do |f|
f.image? ? @image_results << f : @image_results
end
@app_items = []
@softapplication.attachments.each do |f|
f.pack? ? @app_items << f : @app_items
end
@limit = 10
@feedback_count = @jours.count
@feedback_pages = Paginator.new @feedback_count, @limit, params['page']
@offset ||= @feedback_pages.offset
@jour = @jours[@offset, @limit]
@state = false
respond_to do |format|
format.html # show.html.erb
format.json { render json: @softapplication }
end
end
# GET /softapplications/new
# GET /softapplications/new.json
def new
@softapplication = Softapplication.new
#添加当前用户创建过的项目作为托管项目(下拉项目列表)
project = Project.find(params[:user_id])
#end
respond_to do |format|
format.html # new.html.erb
format.json { render json: @softapplication }
end
end
# GET /softapplications/1/edit
def edit
@softapplication = Softapplication.find(params[:id])
@membership = User.current.memberships.all(:conditions => Project.visible_condition(User.current))
@option = []
# @contesting_project_count = @contesting_project_all.count
# @contesting_project_pages = Paginator.new @contesting_project_count, per_page_option, params['page']
@membership.each do |membership|
unless(membership.project.project_type==1)
#membership.member_roles.each{|role|
# if(role.role_id == 3)
# @option << membership.project
# end
#}
#拥有编辑项目权限的可操作该项目
if User.current.allowed_to?({:controller => "projects", :action => "edit"}, membership.project, :global => false)
@option << membership.project
end
end
end
end
# POST /softapplications
# POST /softapplications.json
# def create
# @softapplication = Softapplication.new(params[:softapplication])
# @softapplication.user = User.current
# @softapplication.save_attachments(params[:attachments])
# respond_to do |format|
# if @softapplication.save
# format.js
# format.html { redirect_to @softapplication, notice: 'Softapplication was successfully created.' }
# # format.json { render json: @softapplication, status: :created, location: @softapplication }
# else
# format.js { render status: 406 }
# format.html { render action: "new" }
# # format.json { render json: @softapplication.errors, status: :unprocessable_entity }
# end
# end
# end
#new changed created function
def create
@softapplication = Softapplication.new(params[:softapplication])
@softapplication.user = User.current
#@softapplication.deposit_project = params[:project]
@softapplication.project = Project.find_by_id(params[:project])
@softapplication.save_attachments(params[:attachments])
respond_to do |format|
if @softapplication.save
ContestingSoftapplication.create(:contest_id => params[:contest_id], :softapplication_id => @softapplication.id)
#ProjectingSoftapplication.create_softapplication_projecting(:project_id => params[:project_id], :softapplication_id => @softapplication.id)
#ProjectingSoftapplication.create_softapplication_projecting(@project.id, softapplication.id)
format.html { redirect_to show_attendingcontest_contest_path(:id => params[:contest_id]), notice: l(:notice_attendingcontest_work_successfully_created) }
# format.json { render json: @softapplication, status: :created, location: @softapplication }
else
format.js { render status: 406 }
format.html { render action: "new" }
# format.json { render json: @softapplication.errors, status: :unprocessable_entity }
end
end
#关联新建的参赛作品
# @contesting_softapplication = paginateHelper @contest.contesting_softapplications
end
# PUT /softapplications/1
# PUT /softapplications/1.json
def update
# @softapplication = Softapplication.find(params[:id])
@softapplication.attachments.map{|attach| attach.destroy }
@softapplication.save_attachments(params[:attachments])
#@softapplication.deposit_project = params[:project]
@softapplication.project = Project.find_by_id(params[:project])
respond_to do |format|
if @softapplication.update_attributes(params[:softapplication])
format.html { redirect_to @softapplication, notice: l(:notice_softapplication_was_successfully_updated) }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: @softapplication.errors, status: :unprocessable_entity }
end
end
end
def add_attach
@softapplication = Softapplication.find(params[:id])
@softapplication.save_attachments(params[:attachments])
end
# DELETE /softapplications/1
# DELETE /softapplications/1.json
def destroy
# @softapplication = Softapplication.find(params[:id])
@softapplication.destroy
respond_to do |format|
format.html { redirect_to home_path }
format.json { head :no_content }
end
end
#应用评价涉及到的方法
def new_message
@jour = JournalsForMessage.find(params[:journal_id]) if params[:journal_id]
if @jour
user = @jour.user
text = @jour.notes
else
user = @softapplication.user
text = @softapplication.description
end
text = text.to_s.strip.gsub(%r{<pre>((.|\s)*?)</pre>}m, '[...]')
@content = "> #{ll(User.current.language, :text_user_wrote, user)}\n> "
@content << text.gsub(/(\r?\n|\r\n?)/, "\n> ") + "\n\n"
@id = user.id
rescue ActiveRecord::RecordNotFound
render_404
end
#新建评价
def create_message
if params[:reference_content]
message = params[:softapplication_message][:message] + "\n" + params[:reference_content]
else
message = params[:softapplication_message][:message]
end
refer_user_id = params[:softapplication_message][:reference_user_id].to_i
@softapplication = Softapplication.find(params[:id])
@softapplication.add_jour(User.current, message, refer_user_id)
@user = @softapplication.user
@jours = @softapplication.journals_for_messages.where('m_parent_id IS NULL').order('created_on DESC')
@limit = 10
@feedback_count = @jours.count
@feedback_pages = Paginator.new @feedback_count, @limit, params['page']
@offset ||= @feedback_pages.offset
@jour = @jours[@offset, @limit]
#@softapplication.set_commit(@feedback_count)
respond_to do |format|
format.js
end
end
##删除评价
def destroy_message
@user = @softapplication.user
if User.current.admin? || User.current.id == @user.id
JournalsForMessage.delete_message(params[:object_id])
end
@jours = @softapplication.journals_for_messages.reverse
@limit = 10
@feedback_count = @jours.count
@feedback_pages = Paginator.new @feedback_count, @limit, params['page']
@offset ||= @feedback_pages.offset
@jour = @jours[@offset, @limit]
@softapplication.set_commit(@feedback_count)
respond_to do |format|
format.js
end
end
#
def more
@jour = @softapplication.journals_for_messages
@jour.each_with_index {|j,i| j.indice = i+1}
@state = true
respond_to do |format|
format.html { redirect_to :back }
format.js
#format.api { render_api_ok }
end
end
#
def back
@jour = @softapplication.journals_for_messages
@jour.each_with_index {|j,i| j.indice = i+1}
@state = false
respond_to do |format|
format.html { redirect_to :back }
format.js
#format.api { render_api_ok }
end
end
private
def find_softapplication
@softapplication = Softapplication.find_by_id(params[:id])
end
def editable
unless @softapplication.editable_by? User.current
render_403
return false
end
end
def destroyable
unless @softapplication.destroyable_by? User.current
render_403
return false
end
end
end
class SoftapplicationsController < ApplicationController
layout "contest_base"
before_filter :find_softapplication, only: [:edit, :update, :destroy]
before_filter :editable, only: [:edit, :update]
before_filter :destroyable, only: :destroy
# GET /softapplications
# GET /softapplications.json
def index
@softapplications = Softapplication.all
#new added fenyefunction
@limit = 5
@softapplication_count = @softapplications.count
@softapplication_pages = Paginator.new @softapplication_count, @limit, params['page']
@offset ||= @softapplication_pages.offset
#@softapplications = @softapplications[@offset,@limit]
#new added end
#new added sort
if params[:softapplication_sort_type].present?
case params[:softapplication_sort_type]
when '0'
@softapplications = @softapplications[@offset, @limit]
@s_state = 0
when '1'
@softapplications = @softapplications.sort { |x, y| y[:created_at] <=> x[:created_at]}[@offset, @limit]
@s_state = 1
end
else
@softapplications = @softapplications.sort { |x, y| y[:created_at] <=> x[:created_at]}[@offset, @limit]
@s_state = 1
end
#new added end
respond_to do |format|
format.html # index.html.erb
format.json { render json: @softapplications }
end
end
# GET /softapplications/1
# GET /softapplications/1.json
def percent_of(num, percent)
num.to_f / percent.to_f * 100.0
end
def show
@softapplication = Softapplication.find(params[:id])
#@project = @softapplication.project
# 打分统计
stars_reates = @softapplication.
rates(:quality)
stars_reates_count = stars_reates.count == 0 ? 1 : stars_reates.count
stars_status = stars_reates.select("stars, count(*) as scount").
group("stars")
@stars_status_map = Hash.new(0)
stars_status.each do |star_status|
percent = percent_of(star_status.scount, stars_reates_count).to_f
people = star_status.scount.to_i
@stars_status_map["star#{star_status.stars.to_i}".to_sym] =
people.to_s
end
@jours = @softapplication.journals_for_messages.order('created_on DESC')
@image_results = []
@softapplication.attachments.each do |f|
f.image? ? @image_results << f : @image_results
end
@app_items = []
@softapplication.attachments.each do |f|
f.pack? ? @app_items << f : @app_items
end
@limit = 10
@feedback_count = @jours.count
@feedback_pages = Paginator.new @feedback_count, @limit, params['page']
@offset ||= @feedback_pages.offset
@jour = @jours[@offset, @limit]
@state = false
respond_to do |format|
format.html # show.html.erb
format.json { render json: @softapplication }
end
end
# GET /softapplications/new
# GET /softapplications/new.json
def new
@softapplication = Softapplication.new
#添加当前用户创建过的项目作为托管项目(下拉项目列表)
project = Project.find(params[:user_id])
#end
respond_to do |format|
format.html # new.html.erb
format.json { render json: @softapplication }
end
end
# GET /softapplications/1/edit
def edit
@softapplication = Softapplication.find(params[:id])
@membership = User.current.memberships.all(:conditions => Project.visible_condition(User.current))
@option = []
# @contesting_project_count = @contesting_project_all.count
# @contesting_project_pages = Paginator.new @contesting_project_count, per_page_option, params['page']
@membership.each do |membership|
unless(membership.project.project_type==1)
#拥有编辑项目权限的可操作该项目
if User.current.allowed_to?(:quote_project,membership.project)
@option << membership.project
end
end
end
end
# POST /softapplications
# POST /softapplications.json
# def create
# @softapplication = Softapplication.new(params[:softapplication])
# @softapplication.user = User.current
# @softapplication.save_attachments(params[:attachments])
# respond_to do |format|
# if @softapplication.save
# format.js
# format.html { redirect_to @softapplication, notice: 'Softapplication was successfully created.' }
# # format.json { render json: @softapplication, status: :created, location: @softapplication }
# else
# format.js { render status: 406 }
# format.html { render action: "new" }
# # format.json { render json: @softapplication.errors, status: :unprocessable_entity }
# end
# end
# end
#new changed created function
def create
#options = params[:softapplication]
#options[:app_type_name] = params[:other_input] if options[:app_type_name] == "其他" && params[:other_input]
@softapplication = Softapplication.new(params[:softapplication])
@softapplication.user = User.current
#@softapplication.deposit_project = params[:project]
@softapplication.project = Project.find_by_id(params[:project])
@softapplication.app_type_name = params[:other_input] if params[:other_input] != ""
@softapplication.save_attachments(params[:attachments])
respond_to do |format|
if @softapplication.save
ContestingSoftapplication.create(:contest_id => params[:contest_id], :softapplication_id => @softapplication.id)
#ProjectingSoftapplication.create_softapplication_projecting(:project_id => params[:project_id], :softapplication_id => @softapplication.id)
#ProjectingSoftapplication.create_softapplication_projecting(@project.id, softapplication.id)
format.html { redirect_to show_attendingcontest_contest_url(:id => params[:contest_id]), notice: l(:notice_attendingcontest_work_successfully_created) }
# format.json { render json: @softapplication, status: :created, location: @softapplication }
else
#format.js { render status: 406 }
format.html { render action: "contests/show_attendingcontest" }
# format.json { render json: @softapplication.errors, status: :unprocessable_entity }
end
end
#关联新建的参赛作品
# @contesting_softapplication = paginateHelper @contest.contesting_softapplications
end
# PUT /softapplications/1
# PUT /softapplications/1.json
def update
# @softapplication = Softapplication.find(params[:id])
#@softapplication.attachments.map{|attach| attach.destroy }
@softapplication.save_attachments(params[:attachments]) if params[:attachments]
#@softapplication.deposit_project = params[:project]
@softapplication.project = Project.find_by_id(params[:project])
@softapplication.name = params[:softapplication][:name]
@softapplication.android_min_version_available = params[:softapplication][:android_min_version_available]
@softapplication.app_type_name = params[:other_input] == "" ? params[:softapplication][:app_type_name] : params[:other_input]
@softapplication.description = params[:softapplication][:description]
@softapplication.application_developers = params[:softapplication][:application_developers]
#@softapplication.app_type_name = params[:other_input] if params[:other_input] != ""
respond_to do |format|
#if @softapplication.update_attributes(params[:softapplication])
if @softapplication.save
format.html { redirect_to @softapplication, notice: l(:notice_softapplication_was_successfully_updated) }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: @softapplication.errors, status: :unprocessable_entity }
end
end
end
def add_attach
@softapplication = Softapplication.find(params[:id])
@softapplication.save_attachments(params[:attachments])
end
# DELETE /softapplications/1
# DELETE /softapplications/1.json
def destroy
# @softapplication = Softapplication.find(params[:id])
@softapplication.destroy
respond_to do |format|
format.html { redirect_to home_url }
format.json { head :no_content }
end
end
#应用评价涉及到的方法
def new_message
@jour = JournalsForMessage.find(params[:journal_id]) if params[:journal_id]
if @jour
user = @jour.user
text = @jour.notes
else
user = @softapplication.user
text = @softapplication.description
end
text = text.to_s.strip.gsub(%r{<pre>((.|\s)*?)</pre>}m, '[...]')
@content = "> #{ll(User.current.language, :text_user_wrote, user)}\n> "
@content << text.gsub(/(\r?\n|\r\n?)/, "\n> ") + "\n\n"
@id = user.id
rescue ActiveRecord::RecordNotFound
render_404
end
#新建评价
def create_message
if params[:reference_content]
message = params[:softapplication_message][:message] + "\n" + params[:reference_content]
else
message = params[:softapplication_message][:message]
end
refer_user_id = params[:softapplication_message][:reference_user_id].to_i
@softapplication = Softapplication.find(params[:id])
@softapplication.add_jour(User.current, message, refer_user_id)
@user = @softapplication.user
@jours = @softapplication.journals_for_messages.where('m_parent_id IS NULL').order('created_on DESC')
@limit = 10
@feedback_count = @jours.count
@feedback_pages = Paginator.new @feedback_count, @limit, params['page']
@offset ||= @feedback_pages.offset
@jour = @jours[@offset, @limit]
#@softapplication.set_commit(@feedback_count)
respond_to do |format|
format.js
end
end
##删除评价
def destroy_message
@user = @softapplication.user
if User.current.admin? || User.current.id == @user.id
JournalsForMessage.delete_message(params[:object_id])
end
@jours = @softapplication.journals_for_messages.reverse
@limit = 10
@feedback_count = @jours.count
@feedback_pages = Paginator.new @feedback_count, @limit, params['page']
@offset ||= @feedback_pages.offset
@jour = @jours[@offset, @limit]
@softapplication.set_commit(@feedback_count)
respond_to do |format|
format.js
end
end
#
def more
@jour = @softapplication.journals_for_messages
@jour.each_with_index {|j,i| j.indice = i+1}
@state = true
respond_to do |format|
format.html { redirect_to :back }
format.js
#format.api { render_api_ok }
end
end
#
def back
@jour = @softapplication.journals_for_messages
@jour.each_with_index {|j,i| j.indice = i+1}
@state = false
respond_to do |format|
format.html { redirect_to :back }
format.js
#format.api { render_api_ok }
end
end
def search
@softapplications = Softapplication.where("name like '%#{params[:name]}%'")
#new added fenyefunction
@limit = 5
@softapplication_count = @softapplications.count
@softapplication_pages = Paginator.new @softapplication_count, @limit, params['page']
@offset ||= @softapplication_pages.offset
#new added sort
if params[:softapplication_sort_type].present?
case params[:softapplication_sort_type]
when '0'
@softapplications = @softapplications[@offset, @limit]
@s_state = 0
when '1'
@softapplications = @softapplications.sort { |x, y| y[:created_at] <=> x[:created_at]}[@offset, @limit]
@s_state = 1
end
else
@softapplications = @softapplications.sort { |x, y| y[:created_at] <=> x[:created_at]}[@offset, @limit]
@s_state = 1
end
#new added end
respond_to do |format|
format.html
end
end
private
def find_softapplication
@softapplication = Softapplication.find_by_id(params[:id])
end
def editable
unless @softapplication.editable_by? User.current
render_403
return false
end
end
def destroyable
unless @softapplication.destroyable_by? User.current
render_403
return false
end
end
end

@ -5,12 +5,18 @@ class StoresController < ApplicationController
layout 'base_stores'
def search
name = params[:name] ||= ''
(redirect_to stores_path, :notice => l(:label_sumbit_empty);return) if name.blank?
begin
q = "%#{params[:name].strip}%"
(redirect_to stores_url, :notice => l(:label_sumbit_empty);return) if params[:name].blank?
result = find_public_attache name
result = find_public_attache q
@searched_attach = paginateHelper result
@result_all_count = result.count;
rescue Exception => e
#render 'stores'
redirect_to stores_url
end
end
def find_public_attache keywords
@ -23,14 +29,14 @@ class StoresController < ApplicationController
result = resultSet.to_a.dup
resultSet.to_a.map { |res|
if(res.container.nil? ||
(res.container.class.to_s=="Project" && res.container.is_public == false) ||
(res.container.has_attribute?(:project) && res.container.project.is_public == false) ||
(res.container.class.to_s=="HomeworkAttach" && res.container.bid.reward_type == 3) ||
false
)
result.delete(res)
end
if(res.container.nil? ||
(res.container.class.to_s=="Project" && res.container.is_public == false) ||
(res.container.has_attribute?(:project) && res.container.project.is_public == false) ||
(res.container.class.to_s=="HomeworkAttach" && res.container.bid.reward_type == 3) ||
false
) || (res.container.is_a?(Course) && res.container.is_public == 0)
result.delete(res)
end
}
result
end
@ -38,7 +44,9 @@ class StoresController < ApplicationController
LIMIT = 12 unless const_defined?(:LIMIT)
def index
@projects_attach = project_classification(0).take(LIMIT)
@courses_attach = project_classification(1).take(LIMIT)
@courses_attach = Attachment.includes(:course).where("courses.is_public = 1").
where(container_type: 'Course').
limit(LIMIT)
# @projects_attach = Attachment.includes(:project).where("projects.project_type=? AND projects.is_public = ?", 0, 1).
# reorder("#{Attachment.table_name}.downloads DESC").
# limit(LIMIT)

@ -14,13 +14,14 @@ class TagsController < ApplicationController
include AttachmentsHelper
include ContestsHelper
include ActsAsTaggableOn::TagsHelper
include TagsHelper
helper :projects
helper :courses
include TagsHelper
helper :tags
include OpenSourceProjectsHelper
before_filter :require_admin,:only => [:delete,:show_all]
before_filter :require_login,:only => [:tag_save]
# $selected_tags = Array.new
# $related_tags = Array.new
@ -71,8 +72,8 @@ class TagsController < ApplicationController
@projects_results,
@issues_results,
@bids_results,
@forums_results,
attachments_results,
@forums_results,
@attachments_results,
@contests_results,
@courses_results,
@open_source_projects_results= refresh_results(@obj_id,@obj_flag,@selected_tags)
@ -107,8 +108,8 @@ class TagsController < ApplicationController
@projects_results,
@issues_results,
@bids_results,
@forums_results,
attachments_results,
@forums_results,
@attachments_results,
@contests_results,
@courses_results,
@open_source_projects_results= refresh_results(@obj_id,@show_flag)
@ -130,8 +131,8 @@ class TagsController < ApplicationController
@projects_results,
@issues_results,
@bids_results,
@forums_results,
attachments_results,
@forums_results,
@attachments_results,
@contests_results,
@courses_results,
@open_source_projects_results= refresh_results(@obj_id,@show_flag)
@ -188,6 +189,83 @@ class TagsController < ApplicationController
# end
end
end
# 只删除某个对象的该tag
def remove_tag_new
@obj = nil
@object_flag = nil
if request.get?
# 获取传过来的tag_id taggable_id 和 taggable_type,通过2者确定要删除tag的对象
@tag_name = params[:tag_name]
@tag_id = (ActsAsTaggableOn::Tag.find_by_name(@tag_name)).id
@taggable_id = params[:taggable_id] # 当做参数传时对象会变成字符串
@taggable_type = numbers_to_object_type(params[:taggable_type])
@obj = get_object(@taggable_id,params[:taggable_type])
@object_flag = params[:taggable_type]
# if can_remove_tag?(User.current,@taggable_id,@taggable_type)
@taggings = ActsAsTaggableOn::Tagging.find_by_tag_id_and_taggable_id_and_taggable_type(@tag_id,@taggable_id,@taggable_type)
unless @taggings.nil?
@taggings.delete
end
# 是否还有其他记录 引用了 tag_id
@tagging = ActsAsTaggableOn::Tagging.find_by_tag_id(@tag_id)
# 如果taggings表中记录已经不存在 那么检查tags表 作删除动作
if @tagging.nil?
@tag = ActsAsTaggableOn::Tag.find_by_id(@tag_id)
@tag.delete unless @tag.nil?
end
# end
end
end
def tag_save
@tags = params[:tag_for_save][:name]
@obj_id = params[:tag_for_save][:object_id]
@obj_flag = params[:tag_for_save][:object_flag]
case @obj_flag
when '1' then
@obj = User.find_by_id(@obj_id)
when '2' then
@obj = Project.find_by_id(@obj_id)
when '3' then
@obj = Issue.find_by_id(@obj_id)
when '4' then
@obj = Bid.find_by_id(@obj_id)
when '5' then
@obj = Forum.find_by_id(@obj_id)
when '6'
@obj = Attachment.find_by_id(@obj_id)
when '7' then
@obj = Contest.find_by_id(@obj_id)
when '8'
@obj = OpenSourceProject.find_by_id(@obj_id)
when '9'
@obj = Course.find_by_id(@obj_id)
else
@obj = nil
end
unless @obj.nil?
@obj.tag_list.add(@tags.split(","))
else
return
end
if @obj.save
logger.debug "#{__FILE__}:#{__LINE__} ===> #{@obj.to_json}"
else
logger.error "#{__FILE__}:#{__LINE__} ===> #{@obj.errors.try(:full_messages)}"
end
respond_to do |format|
format.js
format.html
end
end
private
# 这里用来刷新搜索结果的区域
@ -199,7 +277,7 @@ class TagsController < ApplicationController
@bids_results = nil
@contests_results = nil
@forums_results = nil
attachments_results = nil
@attachments_results = nil
@open_source_projects_results = nil
@obj_pages = nil
@obj = nil
@ -228,8 +306,9 @@ class TagsController < ApplicationController
# modifed by Long Jun
# this is used to find the attachments that came from the same project and tagged with the same tag.
@result = get_attachments_by_project_tag(selected_tags, @obj)
@obj_pages, attachments_results, @results_count = for_pagination(@result)
#@result = get_attachments_by_project_tag(selected_tags, @obj)
@result = get_attachments_by_tag(selected_tags)
@obj_pages, @attachments_results, @results_count = for_pagination(@result)
when '7'
@obj = Contest.find_by_id(obj_id)
@obj_pages,@contests_results,@results_count = for_pagination(get_contests_by_tag(selected_tags))
@ -249,8 +328,8 @@ class TagsController < ApplicationController
@projects_results,
@issues_results,
@bids_results,
@forums_results,
attachments_results,
@forums_results,
@attachments_results,
@contests_results,
@courses_results,
@open_source_projects_results]
@ -307,5 +386,7 @@ class TagsController < ApplicationController
return
end
end
end

@ -26,7 +26,7 @@ class TestController < ApplicationController
end
def courselist
@courses = Project.course_entities
@courses = paginateHelper Course.includes(:homeworks).all, 10
end
def ziping files_path

@ -1,315 +1,315 @@
# Redmine - project management software
# Copyright (C) 2006-2013 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 TimelogController < ApplicationController
layout 'base_projects'#added by young
menu_item :issues
before_filter :find_project_for_new_time_entry, :only => [:create]
before_filter :find_time_entry, :only => [:show, :edit, :update]
before_filter :find_time_entries, :only => [:bulk_edit, :bulk_update, :destroy]
before_filter :authorize, :except => [:new, :index, :report]
before_filter :find_optional_project, :only => [:index, :report]
before_filter :find_optional_project_for_new_time_entry, :only => [:new]
before_filter :authorize_global, :only => [:new, :index, :report]
accept_rss_auth :index
accept_api_auth :index, :show, :create, :update, :destroy
rescue_from Query::StatementInvalid, :with => :query_statement_invalid
helper :sort
include SortHelper
helper :issues
include TimelogHelper
helper :custom_fields
include CustomFieldsHelper
helper :queries
include QueriesHelper
def index
@query = TimeEntryQuery.build_from_params(params, :project => @project, :name => '_')
scope = time_entry_scope
sort_init(@query.sort_criteria.empty? ? [['spent_on', 'desc']] : @query.sort_criteria)
sort_update(@query.sortable_columns)
respond_to do |format|
format.html {
# Paginate results
@entry_count = scope.count
@entry_pages = Paginator.new @entry_count, per_page_option, params['page']
@entries = scope.all(
:include => [:project, :activity, :user, {:issue => :tracker}],
:order => sort_clause,
:limit => @entry_pages.per_page,
:offset => @entry_pages.offset
)
@total_hours = scope.sum(:hours).to_f
render :layout => !request.xhr?
}
format.api {
@entry_count = scope.count
@offset, @limit = api_offset_and_limit
@entries = scope.all(
:include => [:project, :activity, :user, {:issue => :tracker}],
:order => sort_clause,
:limit => @limit,
:offset => @offset
)
}
format.atom {
entries = scope.all(
:include => [:project, :activity, :user, {:issue => :tracker}],
:order => "#{TimeEntry.table_name}.created_on DESC",
:limit => Setting.feeds_limit.to_i
)
render_feed(entries, :title => l(:label_spent_time))
}
format.csv {
# Export all entries
@entries = scope.all(
:include => [:project, :activity, :user, {:issue => [:tracker, :assigned_to, :priority]}],
:order => sort_clause
)
send_data(query_to_csv(@entries, @query, params), :type => 'text/csv; header=present', :filename => 'timelog.csv')
}
end
end
def report
@query = TimeEntryQuery.build_from_params(params, :project => @project, :name => '_')
scope = time_entry_scope
@report = Redmine::Helpers::TimeReport.new(@project, @issue, params[:criteria], params[:columns], scope)
respond_to do |format|
format.html { render :layout => !request.xhr? }
format.csv { send_data(report_to_csv(@report), :type => 'text/csv; header=present', :filename => 'timelog.csv') }
end
end
def show
respond_to do |format|
# TODO: Implement html response
format.html { render :nothing => true, :status => 406 }
format.api
end
end
def new
@time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :user => User.current, :spent_on => User.current.today)
@time_entry.safe_attributes = params[:time_entry]
end
def create
@time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :user => User.current, :spent_on => User.current.today)
@time_entry.safe_attributes = params[:time_entry]
call_hook(:controller_timelog_edit_before_save, { :params => params, :time_entry => @time_entry })
if @time_entry.save
respond_to do |format|
format.html {
flash[:notice] = l(:notice_successful_create)
if params[:continue]
if params[:project_id]
options = {
:time_entry => {:issue_id => @time_entry.issue_id, :activity_id => @time_entry.activity_id},
:back_url => params[:back_url]
}
if @time_entry.issue
redirect_to new_project_issue_time_entry_path(@time_entry.project, @time_entry.issue, options)
else
redirect_to new_project_time_entry_path(@time_entry.project, options)
end
else
options = {
:time_entry => {:project_id => @time_entry.project_id, :issue_id => @time_entry.issue_id, :activity_id => @time_entry.activity_id},
:back_url => params[:back_url]
}
redirect_to new_time_entry_path(options)
end
else
redirect_back_or_default project_time_entries_path(@time_entry.project)
end
}
format.api { render :action => 'show', :status => :created, :location => time_entry_url(@time_entry) }
end
else
respond_to do |format|
format.html { render :action => 'new' }
format.api { render_validation_errors(@time_entry) }
end
end
end
def edit
@time_entry.safe_attributes = params[:time_entry]
end
def update
@time_entry.safe_attributes = params[:time_entry]
call_hook(:controller_timelog_edit_before_save, { :params => params, :time_entry => @time_entry })
if @time_entry.save
respond_to do |format|
format.html {
flash[:notice] = l(:notice_successful_update)
redirect_back_or_default project_time_entries_path(@time_entry.project)
}
format.api { render_api_ok }
end
else
respond_to do |format|
format.html { render :action => 'edit' }
format.api { render_validation_errors(@time_entry) }
end
end
end
def bulk_edit
@available_activities = TimeEntryActivity.shared.active
@custom_fields = TimeEntry.first.available_custom_fields
end
def bulk_update
attributes = parse_params_for_bulk_time_entry_attributes(params)
unsaved_time_entry_ids = []
@time_entries.each do |time_entry|
time_entry.reload
time_entry.safe_attributes = attributes
call_hook(:controller_time_entries_bulk_edit_before_save, { :params => params, :time_entry => time_entry })
unless time_entry.save
# Keep unsaved time_entry ids to display them in flash error
unsaved_time_entry_ids << time_entry.id
end
end
set_flash_from_bulk_time_entry_save(@time_entries, unsaved_time_entry_ids)
redirect_back_or_default project_time_entries_path(@projects.first)
end
def destroy
destroyed = TimeEntry.transaction do
@time_entries.each do |t|
unless t.destroy && t.destroyed?
raise ActiveRecord::Rollback
end
end
end
respond_to do |format|
format.html {
if destroyed
flash[:notice] = l(:notice_successful_delete)
else
flash[:error] = l(:notice_unable_delete_time_entry)
end
redirect_back_or_default project_time_entries_path(@projects.first)
}
format.api {
if destroyed
render_api_ok
else
render_validation_errors(@time_entries)
end
}
end
end
private
def find_time_entry
@time_entry = TimeEntry.find(params[:id])
unless @time_entry.editable_by?(User.current)
render_403
return false
end
@project = @time_entry.project
rescue ActiveRecord::RecordNotFound
render_404
end
def find_time_entries
@time_entries = TimeEntry.find_all_by_id(params[:id] || params[:ids])
raise ActiveRecord::RecordNotFound if @time_entries.empty?
@projects = @time_entries.collect(&:project).compact.uniq
@project = @projects.first if @projects.size == 1
rescue ActiveRecord::RecordNotFound
render_404
end
def set_flash_from_bulk_time_entry_save(time_entries, unsaved_time_entry_ids)
if unsaved_time_entry_ids.empty?
flash[:notice] = l(:notice_successful_update) unless time_entries.empty?
else
flash[:error] = l(:notice_failed_to_save_time_entries,
:count => unsaved_time_entry_ids.size,
:total => time_entries.size,
:ids => '#' + unsaved_time_entry_ids.join(', #'))
end
end
def find_optional_project_for_new_time_entry
if (project_id = (params[:project_id] || params[:time_entry] && params[:time_entry][:project_id])).present?
@project = Project.find(project_id)
end
if (issue_id = (params[:issue_id] || params[:time_entry] && params[:time_entry][:issue_id])).present?
@issue = Issue.find(issue_id)
@project ||= @issue.project
end
rescue ActiveRecord::RecordNotFound
render_404
end
def find_project_for_new_time_entry
find_optional_project_for_new_time_entry
if @project.nil?
render_404
end
end
def find_optional_project
if !params[:issue_id].blank?
@issue = Issue.find(params[:issue_id])
@project = @issue.project
elsif !params[:project_id].blank?
@project = Project.find(params[:project_id])
end
end
# Returns the TimeEntry scope for index and report actions
def time_entry_scope
scope = TimeEntry.visible.where(@query.statement)
if @issue
scope = scope.on_issue(@issue)
elsif @project
scope = scope.on_project(@project, Setting.display_subprojects_issues?)
end
scope
end
def parse_params_for_bulk_time_entry_attributes(params)
attributes = (params[:time_entry] || {}).reject {|k,v| v.blank?}
attributes.keys.each {|k| attributes[k] = '' if attributes[k] == 'none'}
attributes[:custom_field_values].reject! {|k,v| v.blank?} if attributes[:custom_field_values]
attributes
end
end
# Redmine - project management software
# Copyright (C) 2006-2013 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 TimelogController < ApplicationController
layout 'base_projects'#added by young
menu_item :issues
before_filter :find_project_for_new_time_entry, :only => [:create]
before_filter :find_time_entry, :only => [:show, :edit, :update]
before_filter :find_time_entries, :only => [:bulk_edit, :bulk_update, :destroy]
before_filter :authorize, :except => [:new, :index, :report]
before_filter :find_optional_project, :only => [:index, :report]
before_filter :find_optional_project_for_new_time_entry, :only => [:new]
before_filter :authorize_global, :only => [:new, :index, :report]
accept_rss_auth :index
accept_api_auth :index, :show, :create, :update, :destroy
rescue_from Query::StatementInvalid, :with => :query_statement_invalid
helper :sort
include SortHelper
helper :issues
include TimelogHelper
helper :custom_fields
include CustomFieldsHelper
helper :queries
include QueriesHelper
def index
@query = TimeEntryQuery.build_from_params(params, :project => @project, :name => '_')
scope = time_entry_scope
sort_init(@query.sort_criteria.empty? ? [['spent_on', 'desc']] : @query.sort_criteria)
sort_update(@query.sortable_columns)
respond_to do |format|
format.html {
# Paginate results
@entry_count = scope.count
@entry_pages = Paginator.new @entry_count, per_page_option, params['page']
@entries = scope.all(
:include => [:project, :activity, :user, {:issue => :tracker}],
:order => sort_clause,
:limit => @entry_pages.per_page,
:offset => @entry_pages.offset
)
@total_hours = scope.sum(:hours).to_f
render :layout => !request.xhr?
}
format.api {
@entry_count = scope.count
@offset, @limit = api_offset_and_limit
@entries = scope.all(
:include => [:project, :activity, :user, {:issue => :tracker}],
:order => sort_clause,
:limit => @limit,
:offset => @offset
)
}
format.atom {
entries = scope.all(
:include => [:project, :activity, :user, {:issue => :tracker}],
:order => "#{TimeEntry.table_name}.created_on DESC",
:limit => Setting.feeds_limit.to_i
)
render_feed(entries, :title => l(:label_spent_time))
}
format.csv {
# Export all entries
@entries = scope.all(
:include => [:project, :activity, :user, {:issue => [:tracker, :assigned_to, :priority]}],
:order => sort_clause
)
send_data(query_to_csv(@entries, @query, params), :type => 'text/csv; header=present', :filename => 'timelog.csv')
}
end
end
def report
@query = TimeEntryQuery.build_from_params(params, :project => @project, :name => '_')
scope = time_entry_scope
@report = Redmine::Helpers::TimeReport.new(@project, @issue, params[:criteria], params[:columns], scope)
respond_to do |format|
format.html { render :layout => !request.xhr? }
format.csv { send_data(report_to_csv(@report), :type => 'text/csv; header=present', :filename => 'timelog.csv') }
end
end
def show
respond_to do |format|
# TODO: Implement html response
format.html { render :nothing => true, :status => 406 }
format.api
end
end
def new
@time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :user => User.current, :spent_on => User.current.today)
@time_entry.safe_attributes = params[:time_entry]
end
def create
@time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :user => User.current, :spent_on => User.current.today)
@time_entry.safe_attributes = params[:time_entry]
call_hook(:controller_timelog_edit_before_save, { :params => params, :time_entry => @time_entry })
if @time_entry.save
respond_to do |format|
format.html {
flash[:notice] = l(:notice_successful_create)
if params[:continue]
if params[:project_id]
options = {
:time_entry => {:issue_id => @time_entry.issue_id, :activity_id => @time_entry.activity_id},
:back_url => params[:back_url]
}
if @time_entry.issue
redirect_to new_project_issue_time_entry_url(@time_entry.project, @time_entry.issue, options)
else
redirect_to new_project_time_entry_url(@time_entry.project, options)
end
else
options = {
:time_entry => {:project_id => @time_entry.project_id, :issue_id => @time_entry.issue_id, :activity_id => @time_entry.activity_id},
:back_url => params[:back_url]
}
redirect_to new_time_entry_url(options)
end
else
redirect_back_or_default project_time_entries_path(@time_entry.project)
end
}
format.api { render :action => 'show', :status => :created, :location => time_entry_url(@time_entry) }
end
else
respond_to do |format|
format.html { render :action => 'new' }
format.api { render_validation_errors(@time_entry) }
end
end
end
def edit
@time_entry.safe_attributes = params[:time_entry]
end
def update
@time_entry.safe_attributes = params[:time_entry]
call_hook(:controller_timelog_edit_before_save, { :params => params, :time_entry => @time_entry })
if @time_entry.save
respond_to do |format|
format.html {
flash[:notice] = l(:notice_successful_update)
redirect_back_or_default project_time_entries_path(@time_entry.project)
}
format.api { render_api_ok }
end
else
respond_to do |format|
format.html { render :action => 'edit' }
format.api { render_validation_errors(@time_entry) }
end
end
end
def bulk_edit
@available_activities = TimeEntryActivity.shared.active
@custom_fields = TimeEntry.first.available_custom_fields
end
def bulk_update
attributes = parse_params_for_bulk_time_entry_attributes(params)
unsaved_time_entry_ids = []
@time_entries.each do |time_entry|
time_entry.reload
time_entry.safe_attributes = attributes
call_hook(:controller_time_entries_bulk_edit_before_save, { :params => params, :time_entry => time_entry })
unless time_entry.save
# Keep unsaved time_entry ids to display them in flash error
unsaved_time_entry_ids << time_entry.id
end
end
set_flash_from_bulk_time_entry_save(@time_entries, unsaved_time_entry_ids)
redirect_back_or_default project_time_entries_path(@projects.first)
end
def destroy
destroyed = TimeEntry.transaction do
@time_entries.each do |t|
unless t.destroy && t.destroyed?
raise ActiveRecord::Rollback
end
end
end
respond_to do |format|
format.html {
if destroyed
flash[:notice] = l(:notice_successful_delete)
else
flash[:error] = l(:notice_unable_delete_time_entry)
end
redirect_back_or_default project_time_entries_path(@projects.first)
}
format.api {
if destroyed
render_api_ok
else
render_validation_errors(@time_entries)
end
}
end
end
private
def find_time_entry
@time_entry = TimeEntry.find(params[:id])
unless @time_entry.editable_by?(User.current)
render_403
return false
end
@project = @time_entry.project
rescue ActiveRecord::RecordNotFound
render_404
end
def find_time_entries
@time_entries = TimeEntry.find_all_by_id(params[:id] || params[:ids])
raise ActiveRecord::RecordNotFound if @time_entries.empty?
@projects = @time_entries.collect(&:project).compact.uniq
@project = @projects.first if @projects.size == 1
rescue ActiveRecord::RecordNotFound
render_404
end
def set_flash_from_bulk_time_entry_save(time_entries, unsaved_time_entry_ids)
if unsaved_time_entry_ids.empty?
flash[:notice] = l(:notice_successful_update) unless time_entries.empty?
else
flash[:error] = l(:notice_failed_to_save_time_entries,
:count => unsaved_time_entry_ids.size,
:total => time_entries.size,
:ids => '#' + unsaved_time_entry_ids.join(', #'))
end
end
def find_optional_project_for_new_time_entry
if (project_id = (params[:project_id] || params[:time_entry] && params[:time_entry][:project_id])).present?
@project = Project.find(project_id)
end
if (issue_id = (params[:issue_id] || params[:time_entry] && params[:time_entry][:issue_id])).present?
@issue = Issue.find(issue_id)
@project ||= @issue.project
end
rescue ActiveRecord::RecordNotFound
render_404
end
def find_project_for_new_time_entry
find_optional_project_for_new_time_entry
if @project.nil?
render_404
end
end
def find_optional_project
if !params[:issue_id].blank?
@issue = Issue.find(params[:issue_id])
@project = @issue.project
elsif !params[:project_id].blank?
@project = Project.find(params[:project_id])
end
end
# Returns the TimeEntry scope for index and report actions
def time_entry_scope
scope = TimeEntry.visible.where(@query.statement)
if @issue
scope = scope.on_issue(@issue)
elsif @project
scope = scope.on_project(@project, Setting.display_subprojects_issues?)
end
scope
end
def parse_params_for_bulk_time_entry_attributes(params)
attributes = (params[:time_entry] || {}).reject {|k,v| v.blank?}
attributes.keys.each {|k| attributes[k] = '' if attributes[k] == 'none'}
attributes[:custom_field_values].reject! {|k,v| v.blank?} if attributes[:custom_field_values]
attributes
end
end

@ -1,101 +1,108 @@
# Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class TrackersController < ApplicationController
layout 'admin'
before_filter :require_admin, :except => :index
before_filter :require_admin_or_api_request, :only => :index
accept_api_auth :index
def index
respond_to do |format|
format.html {
@tracker_pages, @trackers = paginate Tracker.sorted, :per_page => 25
render :action => "index", :layout => false if request.xhr?
}
format.api {
@trackers = Tracker.sorted.all
}
end
end
def new
@tracker ||= Tracker.new(params[:tracker])
@trackers = Tracker.sorted.all
@projects = Project.all
end
def create
@tracker = Tracker.new(params[:tracker])
if @tracker.save
# workflow copy
if !params[:copy_workflow_from].blank? && (copy_from = Tracker.find_by_id(params[:copy_workflow_from]))
@tracker.workflow_rules.copy(copy_from)
end
flash[:notice] = l(:notice_successful_create)
redirect_to trackers_path
return
end
new
render :action => 'new'
end
def edit
@tracker ||= Tracker.find(params[:id])
@projects = Project.all
end
def update
@tracker = Tracker.find(params[:id])
if @tracker.update_attributes(params[:tracker])
flash[:notice] = l(:notice_successful_update)
redirect_to trackers_path
return
end
edit
render :action => 'edit'
end
def destroy
@tracker = Tracker.find(params[:id])
unless @tracker.issues.empty?
flash[:error] = l(:error_can_not_delete_tracker)
else
@tracker.destroy
end
redirect_to trackers_path
end
def fields
if request.post? && params[:trackers]
params[:trackers].each do |tracker_id, tracker_params|
tracker = Tracker.find_by_id(tracker_id)
if tracker
tracker.core_fields = tracker_params[:core_fields]
tracker.custom_field_ids = tracker_params[:custom_field_ids]
tracker.save
end
end
flash[:notice] = l(:notice_successful_update)
redirect_to fields_trackers_path
return
end
@trackers = Tracker.sorted.all
@custom_fields = IssueCustomField.all.sort
end
end
# Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class TrackersController < ApplicationController
layout 'admin'
helper "project_score"
before_filter :require_admin, :except => :index
before_filter :require_admin_or_api_request, :only => :index
accept_api_auth :index
include CoursesHelper
def index
respond_to do |format|
format.html {
@tracker_pages, @trackers = paginate Tracker.sorted, :per_page => 25
render :action => "index", :layout => false if request.xhr?
}
format.api {
@trackers = Tracker.sorted.all
}
end
end
def new
@tracker ||= Tracker.new(params[:tracker])
@trackers = Tracker.sorted.all
@projects = Project.where("project_type = #{Project::ProjectType_project}").all
@courses = Course.all
@course_activity_count=Hash.new
@courses.each do |course|
@course_activity_count[course.id]=0
end
@course_activity_count=get_course_activity @courses,@course_activity_count
end
def create
@tracker = Tracker.new(params[:tracker])
if @tracker.save
# workflow copy
if !params[:copy_workflow_from].blank? && (copy_from = Tracker.find_by_id(params[:copy_workflow_from]))
@tracker.workflow_rules.copy(copy_from)
end
flash[:notice] = l(:notice_successful_create)
redirect_to trackers_url
return
end
new
render :action => 'new'
end
def edit
@tracker ||= Tracker.find(params[:id])
@projects = Project.where("project_type = #{Project::ProjectType_project}").all
@courses = Course.all
end
def update
@tracker = Tracker.find(params[:id])
if @tracker.update_attributes(params[:tracker])
flash[:notice] = l(:notice_successful_update)
redirect_to trackers_url
return
end
edit
render :action => 'edit'
end
def destroy
@tracker = Tracker.find(params[:id])
unless @tracker.issues.empty?
flash[:error] = l(:error_can_not_delete_tracker)
else
@tracker.destroy
end
redirect_to trackers_url
end
def fields
if request.post? && params[:trackers]
params[:trackers].each do |tracker_id, tracker_params|
tracker = Tracker.find_by_id(tracker_id)
if tracker
tracker.core_fields = tracker_params[:core_fields]
tracker.custom_field_ids = tracker_params[:custom_field_ids]
tracker.save
end
end
flash[:notice] = l(:notice_successful_update)
redirect_to fields_trackers_url
return
end
@trackers = Tracker.sorted.all
@custom_fields = IssueCustomField.all.sort
end
end

File diff suppressed because it is too large Load Diff

@ -1,199 +1,200 @@
# Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class VersionsController < ApplicationController
layout "base_projects"
menu_item :roadmap
model_object Version
before_filter :find_model_object, :except => [:index, :new, :create, :close_completed]
#before_filter :find_model_object_contest, :except => [:index, :new, :create]
before_filter :find_project_from_association, :except => [:index, :new, :create, :close_completed]
before_filter :find_project_by_project_id, :only => [:index, :new, :create, :close_completed]
before_filter :authorize
accept_api_auth :index, :show, :create, :update, :destroy
helper :custom_fields
helper :projects
def index
respond_to do |format|
format.html {
@trackers = @project.trackers.sorted.all
retrieve_selected_tracker_ids(@trackers, @trackers.select {|t| t.is_in_roadmap?})
@with_subprojects = params[:with_subprojects].nil? ? Setting.display_subprojects_issues? : (params[:with_subprojects] == '1')
project_ids = @with_subprojects ? @project.self_and_descendants.collect(&:id) : [@project.id]
@versions = @project.shared_versions || []
@versions += @project.rolled_up_versions.visible if @with_subprojects
#added by young
@versions = @versions.uniq.reverse#Modified by young
unless params[:completed]
@completed_versions = @versions.select {|version| version.closed? || version.completed? }
@versions -= @completed_versions
end
@offset, @limit = api_offset_and_limit({:limit => 4})
@versions_count = @versions.count
@versions_pages = Paginator.new @versions_count, @limit, params['page']
@offset ||= @versions_pages.offset
@versions = @versions.slice(@offset, @limit)
#end by young
@issues_by_version = {}
if @selected_tracker_ids.any? && @versions.any?
issues = Issue.visible.all(
:include => [:project, :status, :tracker, :priority, :fixed_version],
:conditions => {:tracker_id => @selected_tracker_ids, :project_id => project_ids, :fixed_version_id => @versions.map(&:id)},
:order => "#{Project.table_name}.lft, #{Tracker.table_name}.position, #{Issue.table_name}.id"
)
@issues_by_version = issues.group_by(&:fixed_version)
end
@versions.reject! {|version| !project_ids.include?(version.project_id) && @issues_by_version[version].blank?}
}
format.api {
@versions = @project.shared_versions.all
}
end
end
def show
respond_to do |format|
format.html {
@issues = @version.fixed_issues.visible.
includes(:status, :tracker, :priority).
reorder("#{Tracker.table_name}.position, #{Issue.table_name}.id").
all
}
format.api
end
end
def new
@version = @project.versions.build
@version.safe_attributes = params[:version]
respond_to do |format|
format.html
format.js
end
end
def create
@version = @project.versions.build
if params[:version]
attributes = params[:version].dup
attributes.delete('sharing') unless attributes.nil? || @version.allowed_sharings.include?(attributes['sharing'])
@version.safe_attributes = attributes
end
if request.post?
if @version.save
respond_to do |format|
format.html do
flash[:notice] = l(:notice_successful_create)
redirect_back_or_default settings_project_path(@project, :tab => 'versions')
end
format.js
format.api do
render :action => 'show', :status => :created, :location => version_url(@version)
end
end
else
respond_to do |format|
format.html { render :action => 'new' }
format.js { render :action => 'new' }
format.api { render_validation_errors(@version) }
end
end
end
end
def edit
end
def update
if request.put? && params[:version]
attributes = params[:version].dup
attributes.delete('sharing') unless @version.allowed_sharings.include?(attributes['sharing'])
@version.safe_attributes = attributes
if @version.save
respond_to do |format|
format.html {
flash[:notice] = l(:notice_successful_update)
redirect_back_or_default settings_project_path(@project, :tab => 'versions')
}
format.api { render_api_ok }
end
else
respond_to do |format|
format.html { render :action => 'edit' }
format.api { render_validation_errors(@version) }
end
end
end
end
def close_completed
if request.put?
@project.close_completed_versions
end
redirect_to settings_project_path(@project, :tab => 'versions')
end
def close_completed_contest
if request.put?
@contest.close_completed_versions
end
redirect_to settings_contest_path(@contest, :tab => 'versions')
end
def destroy
if @version.fixed_issues.empty?
@version.destroy
respond_to do |format|
format.html { redirect_back_or_default settings_project_path(@project, :tab => 'versions') }
format.api { render_api_ok }
end
else
respond_to do |format|
format.html {
flash[:error] = l(:notice_unable_delete_version)
redirect_to settings_project_path(@project, :tab => 'versions')
}
format.api { head :unprocessable_entity }
end
end
end
def status_by
respond_to do |format|
format.html { render :action => 'show' }
format.js
end
end
private
def retrieve_selected_tracker_ids(selectable_trackers, default_trackers=nil)
if ids = params[:tracker_ids]
@selected_tracker_ids = (ids.is_a? Array) ? ids.collect { |id| id.to_i.to_s } : ids.split('/').collect { |id| id.to_i.to_s }
else
@selected_tracker_ids = (selectable_trackers).collect {|t| t.id.to_s }
end
end
end
# Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class VersionsController < ApplicationController
layout "base_projects"
menu_item :roadmap
model_object Version
before_filter :find_model_object, :except => [:index, :new, :create, :close_completed]
#before_filter :find_model_object_contest, :except => [:index, :new, :create]
before_filter :find_project_from_association, :except => [:index, :new, :create, :close_completed]
before_filter :find_project_by_project_id, :only => [:index, :new, :create, :close_completed]
before_filter :authorize
accept_api_auth :index, :show, :create, :update, :destroy
helper :custom_fields
helper :projects
helper :project_score
def index
respond_to do |format|
format.html {
@trackers = @project.trackers.sorted.all
retrieve_selected_tracker_ids(@trackers, @trackers.select {|t| t.is_in_roadmap?})
@with_subprojects = params[:with_subprojects].nil? ? Setting.display_subprojects_issues? : (params[:with_subprojects] == '1')
project_ids = @with_subprojects ? @project.self_and_descendants.collect(&:id) : [@project.id]
@versions = @project.shared_versions || []
@versions += @project.rolled_up_versions.visible if @with_subprojects
#added by young
@versions = @versions.uniq.reverse#Modified by young
unless params[:completed]
@completed_versions = @versions.select {|version| version.closed? || version.completed? }
@versions -= @completed_versions
end
@offset, @limit = api_offset_and_limit({:limit => 4})
@versions_count = @versions.count
@versions_pages = Paginator.new @versions_count, @limit, params['page']
@offset ||= @versions_pages.offset
@versions = @versions.slice(@offset, @limit)
#end by young
@issues_by_version = {}
if @selected_tracker_ids.any? && @versions.any?
issues = Issue.visible.all(
:include => [:project, :status, :tracker, :priority, :fixed_version],
:conditions => {:tracker_id => @selected_tracker_ids, :project_id => project_ids, :fixed_version_id => @versions.map(&:id)},
:order => "#{Project.table_name}.lft, #{Tracker.table_name}.position, #{Issue.table_name}.id"
)
@issues_by_version = issues.group_by(&:fixed_version)
end
@versions.reject! {|version| !project_ids.include?(version.project_id) && @issues_by_version[version].blank?}
}
format.api {
@versions = @project.shared_versions.all
}
end
end
def show
respond_to do |format|
format.html {
@issues = @version.fixed_issues.visible.
includes(:status, :tracker, :priority).
reorder("#{Tracker.table_name}.position, #{Issue.table_name}.id").
all
}
format.api
end
end
def new
@version = @project.versions.build
@version.safe_attributes = params[:version]
respond_to do |format|
format.html
format.js
end
end
def create
@version = @project.versions.build
if params[:version]
attributes = params[:version].dup
attributes.delete('sharing') unless attributes.nil? || @version.allowed_sharings.include?(attributes['sharing'])
@version.safe_attributes = attributes
end
if request.post?
if @version.save
respond_to do |format|
format.html do
flash[:notice] = l(:notice_successful_create)
redirect_to settings_project_url(@project, :tab => 'versions')
end
format.js
format.api do
render :action => 'show', :status => :created, :location => version_url(@version)
end
end
else
respond_to do |format|
format.html { render :action => 'new' }
format.js { render :action => 'new' }
format.api { render_validation_errors(@version) }
end
end
end
end
def edit
end
def update
if request.put? && params[:version]
attributes = params[:version].dup
attributes.delete('sharing') unless @version.allowed_sharings.include?(attributes['sharing'])
@version.safe_attributes = attributes
if @version.save
respond_to do |format|
format.html {
flash[:notice] = l(:notice_successful_update)
redirect_back_or_default settings_project_path(@project, :tab => 'versions')
}
format.api { render_api_ok }
end
else
respond_to do |format|
format.html { render :action => 'edit' }
format.api { render_validation_errors(@version) }
end
end
end
end
def close_completed
if request.put?
@project.close_completed_versions
end
redirect_to settings_project_url(@project, :tab => 'versions')
end
def close_completed_contest
if request.put?
@contest.close_completed_versions
end
redirect_to settings_contest_url(@contest, :tab => 'versions')
end
def destroy
if @version.fixed_issues.empty?
@version.destroy
respond_to do |format|
format.html { redirect_back_or_default settings_project_path(@project, :tab => 'versions') }
format.api { render_api_ok }
end
else
respond_to do |format|
format.html {
flash[:error] = l(:notice_unable_delete_version)
redirect_to settings_project_url(@project, :tab => 'versions')
}
format.api { head :unprocessable_entity }
end
end
end
def status_by
respond_to do |format|
format.html { render :action => 'show' }
format.js
end
end
private
def retrieve_selected_tracker_ids(selectable_trackers, default_trackers=nil)
if ids = params[:tracker_ids]
@selected_tracker_ids = (ids.is_a? Array) ? ids.collect { |id| id.to_i.to_s } : ids.split('/').collect { |id| id.to_i.to_s }
else
@selected_tracker_ids = (selectable_trackers).collect {|t| t.id.to_s }
end
end
end

@ -0,0 +1,52 @@
class WebFooterCompaniesController < ApplicationController
layout 'admin'
menu_item :projects, :only => :projects
menu_item :plugins, :only => :plugins
menu_item :info, :only => :info
before_filter :require_admin
def index
@companys = WebFooterCompany.all
end
def new
@company ||= WebFooterCompany.new
end
def create
@company = WebFooterCompany.new(params[:web_footer_company])
if @company.save
flash[:notice] = l(:notice_successful_create)
redirect_to web_footer_companies_url
else
flash[:error] = "#{l :web_footer_company_create_fail}: #{@company.errors.full_messages[0]}"
respond_to do |format|
format.html { render :action => 'new'}
format.api { render_validation_errors(@company) }
end
end
end
def destroy
@company = WebFooterCompany.find(params[:id])
@company.destroy
redirect_to web_footer_companies_url
end
def edit
@company = WebFooterCompany.find(params[:id])
end
def update
@company = WebFooterCompany.find(params[:id])
if @company.update_attributes(params[:web_footer_company])
flash[:notice] = l(:notice_successful_update)
redirect_to web_footer_companies_url
else
flash[:error] = "#{l :web_footer_company_update_fail}: #{@company.errors.full_messages[0]}"
render :action => 'edit'
end
end
end

@ -1,160 +1,230 @@
# Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class WelcomeController < ApplicationController
caches_action :robots
# before_filter :fake, :only => [:index, :course]
before_filter :entry_select, :only => [:index]
def index
end
def robots
@projects = Project.all_public.active
render :layout => false, :content_type => 'text/plain'
end
def course
if params[:school_id]
@school_id = params[:school_id]
elsif User.current.logged? && User.current.user_extensions.school
@school_id = User.current.user_extensions.school.try(:id)
end
@logoLink ||= logolink()
end
def logolink()
id = params[:school_id]
logo_link = ""
if id.nil? and User.current.user_extensions.school.nil?
logo_link = '/images/transparent.png'
else
if id == "0"
logo_link = '/images/transparent.png'
else
if id.nil?
if School.find(User.current.user_extensions.school.id).logo_link.nil?
logo_link = '/images/transparent.png'
else
logo_link = School.find(User.current.user_extensions.school.id).logo_link
end
else
logo_link = School.find(id).logo_link
end
end
end
return logo_link
end
def contest
end
def search
search_condition = params[:q]
search_type = params[:search_type].to_sym unless search_condition.blank?
respond_to do |format|
format.html{
case search_type
when :projects
redirect_to projects_search_path(:name => search_condition,
:project_type => Project::ProjectType_project)
when :courses
redirect_to courses_search_path(:name => search_condition)
when :users
redirect_to users_search_path(:name => search_condition)
when :users_teacher
redirect_to users_search_path(:name => search_condition, :role => :teacher)
when :users_student
redirect_to users_search_path(:name => search_condition, :role => :student)
else
#redirect_to home_path, :alert => l(:label_sumbit_empty)
(redirect_to home_path, :notice => l(:label_sumbit_empty);return) #if params[:name].blank?
end
}
end
end
private
def entry_select
url = request.original_url
if url.include?("course.trustie.net")
course
render :course
return 0
elsif url.include?("contest.trustie.net")
contest
render :contest
return 0
elsif url.include?("user.trustie.net")
redirect_to(:controller => "users", :action => "index")
end
end
# 判断网站的入口,是课程 course 则跳过index去渲染 course 方法
def entry_select_course
if request.original_url.match(/course\.trustie\.net/)
(course() and render :course and return 0)
end
end
def entry_select_contest
if request.original_url.match(/contest\.trustie\.net/)
contest
render :contest
return 0
end
end
def entry_select_user
if request.original_url.match(/user\.trustie\.net$/)
redirect_to(:controller => "users", :action => "index")
return 0
end
end
# def render(*args)
# _fake if @fake_filter
# super
# end
# private
# def fake
# @fake_filter = true
# end
# # 骗子方法
# def _fake
# instance_variables.map { |variable|
# if variable.to_s =~ /Count$/
# self.instance_variable_set(variable.to_sym,
# ("1" + (self.instance_variable_get(variable.to_sym).to_s)).to_i)
# end
# }
# end
end
# Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class WelcomeController < ApplicationController
include ApplicationHelper
include WelcomeHelper
helper :project_score
caches_action :robots
before_filter :find_first_page, :only => [:index]
# before_filter :fake, :only => [:index, :course]
before_filter :entry_select, :only => [:index]
def index
if @first_page.nil? || @first_page.sort_type.nil?
@projects = find_miracle_project(10, 3,"score desc")
else
case @first_page.sort_type
when 0
@projects = find_miracle_project(10, 3,"created_on desc")
#@projects = @projects_all.order("created_on desc")
when 1
@projects = find_miracle_project(10, 3,"score desc")
#@projects = @projects_all.order("grade desc")
when 2
@projects = find_miracle_project(10, 3,"watchers_count desc")
#@projects = @projects_all.order("watchers_count desc")
#gcm
#when '3'
#@projects=desc_sort_course_by_avtivity(@project_activity_count_array,@project_all_array)
# @projects=handle_project @projects_all,@project_activity_count
# @s_type = 3
# @projects = @projects[@project_pages.offset, @project_pages.per_page]
else
@projects = @projects_all.order("score desc")
end
end
end
def robots
@projects = Project.all_public.active
render :layout => false, :content_type => 'text/plain'
end
def course
@course_page = FirstPage.find_by_page_type('course')
@school_id = params[:school_id] || User.current.user_extensions.school.try(:id)
@logoLink ||= logolink()
##3-8月份为查找春季课程9-2月份为查找秋季课程
#month_now = Time.now.strftime("%m").to_i
#year_now = Time.new.strftime("%Y").to_i
#(month_now >= 3 && month_now < 9) ? course_term = l(:label_spring) : course_term = l(:label_autumn)
##year_now -= 1 if year_now < 3
#@school_id.nil? ? @cur_school_course = [] : @cur_school_course = find_miracle_course(10,7,@school_id, year_now, course_term)
##未登录或者当前学校未开设课程
#if @cur_school_course.empty?
# @has_course = false
# User.current.logged? ? course_count = 9 : course_count = 10
# @cur_school_course += find_all_new_hot_course(course_count, @school_id, year_now, course_term)
# while @cur_school_course.count < 9 do
# if course_term == l(:label_spring)
# course_term = l(:label_autumn)
# year_now -= 1
# else
# course_term = l(:label_spring)
# end
# @cur_school_course += find_all_new_hot_course((10-@cur_school_course.count), nil, year_now, course_term)
# end
#else
# if @cur_school_course.count < 9
# @has_course = false
# @cur_school_course += find_all_new_hot_course(9-@cur_school_course.count, @school_id, year_now, course_term)
# if @cur_school_course.count < 9
# if course_term == l(:label_spring)
# course_term = l(:label_autumn)
# year_now -= 1
# else
# course_term = l(:label_spring)
# end
# @cur_school_course += find_all_new_hot_course(9-@cur_school_course.count, nil, year_now, course_term)
# end
# else
# @has_course = true
# end
#end
end
def logolink()
@course_page = FirstPage.find_by_page_type('course')
logo = get_avatar?(@course_page)
id = params[:school_id]
logo_link = ""
if id.nil? && (User.current.user_extensions.nil? || User.current.user_extensions.school.nil?)
if logo
logo_link = url_to_avatar(@course_page)
else
logo_link = '/images/transparent.png'
end
else
if id == "0"
if logo
logo_link = url_to_avatar(@course_page)
else
logo_link = '/images/transparent.png'
end
else
if id.nil?
if School.find(User.current.user_extensions.school.id).logo_link.nil?
logo_link = '/images/transparent.png'
else
logo_link = School.find(User.current.user_extensions.school.id).logo_link
end
else
logo_link = School.find(id).logo_link
end
end
end
return logo_link
end
def contest
@contest_page = FirstPage.find_by_page_type('contest')
@contest_notifications = Contestnotification.order("created_at desc").limit(5)
end
def search
search_condition = params[:q]
search_type = params[:search_type].to_sym unless search_condition.blank?
search_by = params[:search_by]
if search_type.nil? && params[:contests_search] && params[:name] != ""
search_type = :contests
search_condition = params[:name]
end
respond_to do |format|
format.html{
case search_type
when :projects
redirect_to projects_search_url(:name => search_condition,
:project_type => Project::ProjectType_project)
when :courses
redirect_to courses_search_url(:name => search_condition)
when :contests
redirect_to contests_url(:name => search_condition)
when :users
redirect_to users_search_url(:name => search_condition,:search_by => search_by)
when :users_teacher
redirect_to users_search_url(:name => search_condition, :search_by => search_by, :role => :teacher)
when :users_student
redirect_to users_search_url(:name => search_condition, :search_by => search_by, :role => :student)
else
#redirect_to home_path, :alert => l(:label_sumbit_empty)
(redirect_to home_url, :notice => l(:label_sumbit_empty);return) #if params[:name].blank?
end
}
end
end
private
# 判断网站的入口,是课程 course 则跳过index去渲染 course 方法
def entry_select
url = request.original_url.gsub('/','')
if url.include?(Setting.host_course.gsub('/',''))
if @first_page.show_course == 1
course
render :course
else
render_404
end
return 0
elsif url.include?(Setting.host_contest.gsub('/',''))
if @first_page.show_contest == 1
contest
render :contest
else
render_404
end
return 0
elsif url.include?(Setting.host_user.gsub('/',''))
#redirect_to(:controller => "users", :action => "index")
end
end
# def render(*args)
# _fake if @fake_filter
# super
# end
# private
# def fake
# @fake_filter = true
# end
# # 骗子方法
# def _fake
# instance_variables.map { |variable|
# if variable.to_s =~ /Count$/
# self.instance_variable_set(variable.to_sym,
# ("1" + (self.instance_variable_get(variable.to_sym).to_s)).to_i)
# end
# }
# end
end

@ -1,357 +1,358 @@
# Redmine - project management software
# Copyright (C) 2006-2013 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 'diff'
# The WikiController follows the Rails REST controller pattern but with
# a few differences
#
# * index - shows a list of WikiPages grouped by page or date
# * new - not used
# * create - not used
# * show - will also show the form for creating a new wiki page
# * edit - used to edit an existing or new page
# * update - used to save a wiki page update to the database, including new pages
# * destroy - normal
#
# Other member and collection methods are also used
#
# TODO: still being worked on
class WikiController < ApplicationController
layout 'base_projects'#by young
default_search_scope :wiki_pages
before_filter :find_wiki, :authorize
before_filter :find_existing_or_new_page, :only => [:show, :edit, :update]
before_filter :find_existing_page, :only => [:rename, :protect, :history, :diff, :annotate, :add_attachment, :destroy, :destroy_version]
accept_api_auth :index, :show, :update, :destroy
before_filter :find_attachments, :only => [:preview]
helper :attachments
include AttachmentsHelper
helper :watchers
include Redmine::Export::PDF
# List of pages, sorted alphabetically and by parent (hierarchy)
def index
load_pages_for_index
respond_to do |format|
format.html {
@pages_by_parent_id = @pages.group_by(&:parent_id)
}
format.api
end
end
# List of page, by last update
def date_index
load_pages_for_index
@pages_by_date = @pages.group_by {|p| p.updated_on.to_date}
end
# display a page (in editing mode if it doesn't exist)
def show
if @page.new_record?
if User.current.allowed_to?(:edit_wiki_pages, @project) && editable? && !api_request?
edit
render :action => 'edit'
else
render_404
end
return
end
if params[:version] && !User.current.allowed_to?(:view_wiki_edits, @project)
deny_access
return
end
@content = @page.content_for_version(params[:version])
if User.current.allowed_to?(:export_wiki_pages, @project)
if params[:format] == 'pdf'
send_data(wiki_page_to_pdf(@page, @project), :type => 'application/pdf', :filename => "#{@page.title}.pdf")
return
elsif params[:format] == 'html'
export = render_to_string :action => 'export', :layout => false
send_data(export, :type => 'text/html', :filename => "#{@page.title}.html")
return
elsif params[:format] == 'txt'
send_data(@content.text, :type => 'text/plain', :filename => "#{@page.title}.txt")
return
end
end
@editable = editable?
@sections_editable = @editable && User.current.allowed_to?(:edit_wiki_pages, @page.project) &&
@content.current_version? &&
Redmine::WikiFormatting.supports_section_edit?
respond_to do |format|
format.html
format.api
end
end
# edit an existing page or a new one
def edit
return render_403 unless editable?
if @page.new_record?
@page.content = WikiContent.new(:page => @page)
if params[:parent].present?
@page.parent = @page.wiki.find_page(params[:parent].to_s)
end
end
@content = @page.content_for_version(params[:version])
@content.text = initial_page_content(@page) if @content.text.blank?
# don't keep previous comment
@content.comments = nil
# To prevent StaleObjectError exception when reverting to a previous version
@content.version = @page.content.version
@text = @content.text
if params[:section].present? && Redmine::WikiFormatting.supports_section_edit?
@section = params[:section].to_i
@text, @section_hash = Redmine::WikiFormatting.formatter.new(@text).get_section(@section)
render_404 if @text.blank?
end
end
# Creates a new page or updates an existing one
def update
return render_403 unless editable?
was_new_page = @page.new_record?
@page.content = WikiContent.new(:page => @page) if @page.new_record?
@page.safe_attributes = params[:wiki_page]
@content = @page.content
content_params = params[:content]
if content_params.nil? && params[:wiki_page].is_a?(Hash)
content_params = params[:wiki_page].slice(:text, :comments, :version)
end
content_params ||= {}
@content.comments = content_params[:comments]
@text = content_params[:text]
if params[:section].present? && Redmine::WikiFormatting.supports_section_edit?
@section = params[:section].to_i
@section_hash = params[:section_hash]
@content.text = Redmine::WikiFormatting.formatter.new(@content.text).update_section(params[:section].to_i, @text, @section_hash)
else
@content.version = content_params[:version] if content_params[:version]
@content.text = @text
end
@content.author = User.current
if @page.save_with_content
attachments = Attachment.attach_files(@page, params[:attachments])
render_attachment_warning_if_needed(@page)
call_hook(:controller_wiki_edit_after_save, { :params => params, :page => @page})
respond_to do |format|
format.html { redirect_to project_wiki_page_path(@project, @page.title) }
format.api {
if was_new_page
render :action => 'show', :status => :created, :location => project_wiki_page_path(@project, @page.title)
else
render_api_ok
end
}
end
else
respond_to do |format|
format.html { render :action => 'edit' }
format.api { render_validation_errors(@content) }
end
end
rescue ActiveRecord::StaleObjectError, Redmine::WikiFormatting::StaleSectionError
# Optimistic locking exception
respond_to do |format|
format.html {
flash.now[:error] = l(:notice_locking_conflict)
render :action => 'edit'
}
format.api { render_api_head :conflict }
end
rescue ActiveRecord::RecordNotSaved
respond_to do |format|
format.html { render :action => 'edit' }
format.api { render_validation_errors(@content) }
end
end
# rename a page
def rename
return render_403 unless editable?
@page.redirect_existing_links = true
# used to display the *original* title if some AR validation errors occur
@original_title = @page.pretty_title
if request.post? && @page.update_attributes(params[:wiki_page])
flash[:notice] = l(:notice_successful_update)
redirect_to project_wiki_page_path(@project, @page.title)
end
end
def protect
@page.update_attribute :protected, params[:protected]
redirect_to project_wiki_page_path(@project, @page.title)
end
# show page history
def history
@version_count = @page.content.versions.count
@version_pages = Paginator.new @version_count, per_page_option, params['page']
# don't load text
@versions = @page.content.versions.
select("id, author_id, comments, updated_on, version").
reorder('version DESC').
limit(@version_pages.per_page + 1).
offset(@version_pages.offset).
all
render :layout => false if request.xhr?
end
def diff
@diff = @page.diff(params[:version], params[:version_from])
render_404 unless @diff
end
def annotate
@annotate = @page.annotate(params[:version])
render_404 unless @annotate
end
# Removes a wiki page and its history
# Children can be either set as root pages, removed or reassigned to another parent page
def destroy
return render_403 unless editable?
@descendants_count = @page.descendants.size
if @descendants_count > 0
case params[:todo]
when 'nullify'
# Nothing to do
when 'destroy'
# Removes all its descendants
@page.descendants.each(&:destroy)
when 'reassign'
# Reassign children to another parent page
reassign_to = @wiki.pages.find_by_id(params[:reassign_to_id].to_i)
return unless reassign_to
@page.children.each do |child|
child.update_attribute(:parent, reassign_to)
end
else
@reassignable_to = @wiki.pages - @page.self_and_descendants
# display the destroy form if it's a user request
return unless api_request?
end
end
@page.destroy
respond_to do |format|
format.html { redirect_to project_wiki_index_path(@project) }
format.api { render_api_ok }
end
end
def destroy_version
return render_403 unless editable?
@content = @page.content_for_version(params[:version])
@content.destroy
redirect_to_referer_or history_project_wiki_page_path(@project, @page.title)
end
# Export wiki to a single pdf or html file
def export
@pages = @wiki.pages.all(:order => 'title', :include => [:content, {:attachments => :author}])
respond_to do |format|
format.html {
export = render_to_string :action => 'export_multiple', :layout => false
send_data(export, :type => 'text/html', :filename => "wiki.html")
}
format.pdf {
send_data(wiki_pages_to_pdf(@pages, @project), :type => 'application/pdf', :filename => "#{@project.identifier}.pdf")
}
end
end
def preview
page = @wiki.find_page(params[:id])
# page is nil when previewing a new page
return render_403 unless page.nil? || editable?(page)
if page
@attachments += page.attachments
@previewed = page.content
end
@text = params[:content][:text]
render :partial => 'common/preview'
end
def add_attachment
return render_403 unless editable?
attachments = Attachment.attach_files(@page, params[:attachments])
render_attachment_warning_if_needed(@page)
redirect_to :action => 'show', :id => @page.title, :project_id => @project
end
private
def find_wiki
@project = Project.find(params[:project_id])
@wiki = @project.wiki
render_404 unless @wiki
rescue ActiveRecord::RecordNotFound
render_404
end
# Finds the requested page or a new page if it doesn't exist
def find_existing_or_new_page
@page = @wiki.find_or_new_page(params[:id])
if @wiki.page_found_with_redirect?
redirect_to params.update(:id => @page.title)
end
end
# Finds the requested page and returns a 404 error if it doesn't exist
def find_existing_page
@page = @wiki.find_page(params[:id])
if @page.nil?
render_404
return
end
if @wiki.page_found_with_redirect?
redirect_to params.update(:id => @page.title)
end
end
# Returns true if the current user is allowed to edit the page, otherwise false
def editable?(page = @page)
page.editable_by?(User.current)
end
# Returns the default content of a new wiki page
def initial_page_content(page)
helper = Redmine::WikiFormatting.helper_for(Setting.text_formatting)
extend helper unless self.instance_of?(helper)
helper.instance_method(:initial_page_content).bind(self).call(page)
end
def load_pages_for_index
@pages = @wiki.pages.with_updated_on.reorder("#{WikiPage.table_name}.title").includes(:wiki => :project).includes(:parent).all
end
end
# Redmine - project management software
# Copyright (C) 2006-2013 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 'diff'
# The WikiController follows the Rails REST controller pattern but with
# a few differences
#
# * index - shows a list of WikiPages grouped by page or date
# * new - not used
# * create - not used
# * show - will also show the form for creating a new wiki page
# * edit - used to edit an existing or new page
# * update - used to save a wiki page update to the database, including new pages
# * destroy - normal
#
# Other member and collection methods are also used
#
# TODO: still being worked on
class WikiController < ApplicationController
layout 'base_projects'#by young
default_search_scope :wiki_pages
before_filter :find_wiki, :authorize
before_filter :find_existing_or_new_page, :only => [:show, :edit, :update]
before_filter :find_existing_page, :only => [:rename, :protect, :history, :diff, :annotate, :add_attachment, :destroy, :destroy_version]
accept_api_auth :index, :show, :update, :destroy
before_filter :find_attachments, :only => [:preview]
helper :attachments
include AttachmentsHelper
helper :watchers
include Redmine::Export::PDF
helper :project_score
# List of pages, sorted alphabetically and by parent (hierarchy)
def index
load_pages_for_index
respond_to do |format|
format.html {
@pages_by_parent_id = @pages.group_by(&:parent_id)
}
format.api
end
end
# List of page, by last update
def date_index
load_pages_for_index
@pages_by_date = @pages.group_by {|p| p.updated_on.to_date}
end
# display a page (in editing mode if it doesn't exist)
def show
if @page.new_record?
if User.current.allowed_to?(:edit_wiki_pages, @project) && editable? && !api_request?
edit
render :action => 'edit'
else
render_404
end
return
end
if params[:version] && !User.current.allowed_to?(:view_wiki_edits, @project)
deny_access
return
end
@content = @page.content_for_version(params[:version])
if User.current.allowed_to?(:export_wiki_pages, @project)
if params[:format] == 'pdf'
send_data(wiki_page_to_pdf(@page, @project), :type => 'application/pdf', :filename => "#{@page.title}.pdf")
return
elsif params[:format] == 'html'
export = render_to_string :action => 'export', :layout => false
send_data(export, :type => 'text/html', :filename => "#{@page.title}.html")
return
elsif params[:format] == 'txt'
send_data(@content.text, :type => 'text/plain', :filename => "#{@page.title}.txt")
return
end
end
@editable = editable?
@sections_editable = @editable && User.current.allowed_to?(:edit_wiki_pages, @page.project) &&
@content.current_version? &&
Redmine::WikiFormatting.supports_section_edit?
respond_to do |format|
format.html
format.api
end
end
# edit an existing page or a new one
def edit
return render_403 unless editable?
if @page.new_record?
@page.content = WikiContent.new(:page => @page)
if params[:parent].present?
@page.parent = @page.wiki.find_page(params[:parent].to_s)
end
end
@content = @page.content_for_version(params[:version])
@content.text = initial_page_content(@page) if @content.text.blank?
# don't keep previous comment
@content.comments = nil
# To prevent StaleObjectError exception when reverting to a previous version
@content.version = @page.content.version
@text = @content.text
if params[:section].present? && Redmine::WikiFormatting.supports_section_edit?
@section = params[:section].to_i
@text, @section_hash = Redmine::WikiFormatting.formatter.new(@text).get_section(@section)
render_404 if @text.blank?
end
end
# Creates a new page or updates an existing one
def update
return render_403 unless editable?
was_new_page = @page.new_record?
@page.content = WikiContent.new(:page => @page) if @page.new_record?
@page.safe_attributes = params[:wiki_page]
@content = @page.content
content_params = params[:content]
if content_params.nil? && params[:wiki_page].is_a?(Hash)
content_params = params[:wiki_page].slice(:text, :comments, :version)
end
content_params ||= {}
@content.comments = content_params[:comments]
@text = content_params[:text]
if params[:section].present? && Redmine::WikiFormatting.supports_section_edit?
@section = params[:section].to_i
@section_hash = params[:section_hash]
@content.text = Redmine::WikiFormatting.formatter.new(@content.text).update_section(params[:section].to_i, @text, @section_hash)
else
@content.version = content_params[:version] if content_params[:version]
@content.text = @text
end
@content.author = User.current
if @page.save_with_content
attachments = Attachment.attach_files(@page, params[:attachments])
render_attachment_warning_if_needed(@page)
call_hook(:controller_wiki_edit_after_save, { :params => params, :page => @page})
respond_to do |format|
format.html { redirect_to project_wiki_page_url(@project, @page.title) }
format.api {
if was_new_page
render :action => 'show', :status => :created, :location => project_wiki_page_path(@project, @page.title)
else
render_api_ok
end
}
end
else
respond_to do |format|
format.html { render :action => 'edit' }
format.api { render_validation_errors(@content) }
end
end
rescue ActiveRecord::StaleObjectError, Redmine::WikiFormatting::StaleSectionError
# Optimistic locking exception
respond_to do |format|
format.html {
flash.now[:error] = l(:notice_locking_conflict)
render :action => 'edit'
}
format.api { render_api_head :conflict }
end
rescue ActiveRecord::RecordNotSaved
respond_to do |format|
format.html { render :action => 'edit' }
format.api { render_validation_errors(@content) }
end
end
# rename a page
def rename
return render_403 unless editable?
@page.redirect_existing_links = true
# used to display the *original* title if some AR validation errors occur
@original_title = @page.pretty_title
if request.post? && @page.update_attributes(params[:wiki_page])
flash[:notice] = l(:notice_successful_update)
redirect_to project_wiki_page_url(@project, @page.title)
end
end
def protect
@page.update_attribute :protected, params[:protected]
redirect_to project_wiki_page_url(@project, @page.title)
end
# show page history
def history
@version_count = @page.content.versions.count
@version_pages = Paginator.new @version_count, per_page_option, params['page']
# don't load text
@versions = @page.content.versions.
select("id, author_id, comments, updated_on, version").
reorder('version DESC').
limit(@version_pages.per_page + 1).
offset(@version_pages.offset).
all
render :layout => false if request.xhr?
end
def diff
@diff = @page.diff(params[:version], params[:version_from])
render_404 unless @diff
end
def annotate
@annotate = @page.annotate(params[:version])
render_404 unless @annotate
end
# Removes a wiki page and its history
# Children can be either set as root pages, removed or reassigned to another parent page
def destroy
return render_403 unless editable?
@descendants_count = @page.descendants.size
if @descendants_count > 0
case params[:todo]
when 'nullify'
# Nothing to do
when 'destroy'
# Removes all its descendants
@page.descendants.each(&:destroy)
when 'reassign'
# Reassign children to another parent page
reassign_to = @wiki.pages.find_by_id(params[:reassign_to_id].to_i)
return unless reassign_to
@page.children.each do |child|
child.update_attribute(:parent, reassign_to)
end
else
@reassignable_to = @wiki.pages - @page.self_and_descendants
# display the destroy form if it's a user request
return unless api_request?
end
end
@page.destroy
respond_to do |format|
format.html { redirect_to project_wiki_index_url(@project) }
format.api { render_api_ok }
end
end
def destroy_version
return render_403 unless editable?
@content = @page.content_for_version(params[:version])
@content.destroy
redirect_to_referer_or history_project_wiki_page_url(@project, @page.title)
end
# Export wiki to a single pdf or html file
def export
@pages = @wiki.pages.all(:order => 'title', :include => [:content, {:attachments => :author}])
respond_to do |format|
format.html {
export = render_to_string :action => 'export_multiple', :layout => false
send_data(export, :type => 'text/html', :filename => "wiki.html")
}
format.pdf {
send_data(wiki_pages_to_pdf(@pages, @project), :type => 'application/pdf', :filename => "#{@project.identifier}.pdf")
}
end
end
def preview
page = @wiki.find_page(params[:id])
# page is nil when previewing a new page
return render_403 unless page.nil? || editable?(page)
if page
@attachments += page.attachments
@previewed = page.content
end
@text = params[:content][:text]
render :partial => 'common/preview'
end
def add_attachment
return render_403 unless editable?
attachments = Attachment.attach_files(@page, params[:attachments])
render_attachment_warning_if_needed(@page)
redirect_to :action => 'show', :id => @page.title, :project_id => @project
end
private
def find_wiki
@project = Project.find(params[:project_id])
@wiki = @project.wiki
render_404 unless @wiki
rescue ActiveRecord::RecordNotFound
render_404
end
# Finds the requested page or a new page if it doesn't exist
def find_existing_or_new_page
@page = @wiki.find_or_new_page(params[:id])
if @wiki.page_found_with_redirect?
redirect_to params.update(:id => @page.title)
end
end
# Finds the requested page and returns a 404 error if it doesn't exist
def find_existing_page
@page = @wiki.find_page(params[:id])
if @page.nil?
render_404
return
end
if @wiki.page_found_with_redirect?
redirect_to params.update(:id => @page.title)
end
end
# Returns true if the current user is allowed to edit the page, otherwise false
def editable?(page = @page)
page.editable_by?(User.current)
end
# Returns the default content of a new wiki page
def initial_page_content(page)
helper = Redmine::WikiFormatting.helper_for(Setting.text_formatting)
extend helper unless self.instance_of?(helper)
helper.instance_method(:initial_page_content).bind(self).call(page)
end
def load_pages_for_index
@pages = @wiki.pages.with_updated_on.reorder("#{WikiPage.table_name}.title").includes(:wiki => :project).includes(:parent).all
end
end

@ -1,36 +1,36 @@
# Redmine - project management software
# Copyright (C) 2006-2013 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 WikisController < ApplicationController
menu_item :settings
before_filter :find_project, :authorize
# Create or update a project's wiki
def edit
@wiki = @project.wiki || Wiki.new(:project => @project)
@wiki.safe_attributes = params[:wiki]
@wiki.save if request.post?
end
# Delete a project's wiki
def destroy
if request.post? && params[:confirm] && @project.wiki
@project.wiki.destroy
redirect_to settings_project_path(@project, :tab => 'wiki')
end
end
end
# Redmine - project management software
# Copyright (C) 2006-2013 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 WikisController < ApplicationController
menu_item :settings
before_filter :find_project, :authorize
# Create or update a project's wiki
def edit
@wiki = @project.wiki || Wiki.new(:project => @project)
@wiki.safe_attributes = params[:wiki]
@wiki.save if request.post?
end
# Delete a project's wiki
def destroy
if request.post? && params[:confirm] && @project.wiki
@project.wiki.destroy
redirect_to settings_project_url(@project, :tab => 'wiki')
end
end
end

@ -1,247 +1,287 @@
# encoding: utf-8
#####leave message fq
class WordsController < ApplicationController
before_filter :find_user, :only => [:new, :create, :destroy, :more, :back]
def create
if params[:new_form][:user_message].size>0
unless params[:user_id].nil?
if params[:reference_content]
message = params[:new_form][:user_message] + "\n" + params[:reference_content]
else
message = params[:new_form][:user_message]
end
refer_user_id = params[:new_form][:reference_user_id].to_i
@user.add_jour(User.current, message, refer_user_id)
unless refer_user_id == 0 || refer_user_id == User.current.id
User.find(refer_user_id).add_jour(User.current, message, refer_user_id)
end
@user.count_new_jour
# if a_message.size > 5
# @message = a_message[-5, 5]
# else
# @message = a_message
# end
# @message_count = a_message.count
end
end
@jours = @user.journals_for_messages.where('m_parent_id IS NULL').reverse
@limit = 10
@feedback_count = @jours.count
@feedback_pages = Paginator.new @feedback_count, @limit, params['page']
@offset ||= @feedback_pages.offset
@jour = @jours[@offset, @limit]
respond_to do |format|
# format.html { redirect_to_referer_or {render :text => 'Watcher added.', :layout => true}}
format.js
#format.api { render_api_ok }
end
end
def create_reply
# 这里是创建回复所使用的方法,此方法只针对回复,每一个新的留言并不在此方法管理范围内。
# 由于多个地方用到了留言而之前的表设计也有jour_type/jour_id这类信息
# 所以在方法 add_reply_adapter 中判断所有调用此方法的来源页面,
# 为了保证兼容以往所有的代码,保证以往的方法可以调用,在返回页面中都做了各式各样的判断。
# 页面保证 render new_respond/journal_reply
# 修改 add_reply_adapter 中可以确保留言创建成功
# 删除留言功能要调用destroy也记得在destroy.js中修改
# deny api. api useless
parent_id = params[:reference_id]
author_id = User.current.id
reply_user_id = params[:reference_user_id]
reply_id = params[:reference_message_id] # 暂时不实现
content = params[:user_notes]
options = {:user_id => author_id,
:status => true,
:m_parent_id => parent_id,
:m_reply_id => reply_id,
:reply_id => reply_user_id,
:notes => content,
:is_readed => false}
@jfm = add_reply_adapter options
respond_to do |format|
# format.html {
# if @jfm.errors.empty?
# flash.now.notice = l(:label_feedback_success)
# else
# flash.now.errors = l(:label_feedback_fail)
# end
# render 'test/index'
# }
format.js{
@save_succ = true if @jfm.errors.empty?
}
end
end
def destroy
@journal_destroyed = JournalsForMessage.delete_message(params[:object_id])
respond_to do |format|
format.js
#format.api { render_api_ok }
end
end
def new
@jour = JournalsForMessage.find(params[:journal_id]) if params[:journal_id]
if @jour
user = @jour.user
text = @jour.notes
else
user = @user
text = []
end
# Replaces pre blocks with [...]
text = text.to_s.strip.gsub(%r{<pre>((.|\s)*?)</pre>}m, '[...]')
@content = "> #{ll(User.current.language, :text_user_wrote, user)}\n> "
@content << text.gsub(/(\r?\n|\r\n?)/, "\n> ") + "\n\n"
# @content << text.gsub(/(\r?\n|\r\n?)/, "\n> ") + "\n\n"
# @content = "> #{ll(Setting.default_language, :text_user_wrote, user)}\n> "
@id = user.id
rescue ActiveRecord::RecordNotFound
render_404
end
def more
@jours = @user.journals_for_messages.reverse
@limit = 10
@feedback_count = @jours.count
@feedback_pages = Paginator.new @feedback_count, @limit, params['page']
@offset ||= @feedback_pages.offset
@jour = @jours[@offset, @limit]
@state = true
respond_to do |format|
format.html { redirect_to :back }
format.js
#format.api { render_api_ok }
end
end
def back
@jours = @user.journals_for_messages.reverse
@limit = 10
@feedback_count = @jours.count
@feedback_pages = Paginator.new @feedback_count, @limit, params['page']
@offset ||= @feedback_pages.offset
@jour = @jours[@offset, @limit]
@state = false
respond_to do |format|
format.html { redirect_to :back }
format.js
#format.api { render_api_ok }
end
end
def add_project_respond
user = User.current
message = params[:new_form][:project_message]
Project.add_jour(user, message)
redirect_to project_feedback_path('trustie')
# redirect_to signin_path
end
def leave_project_message
user = User.current
message = params[:new_form][:project_message]
feedback = Project.add_new_jour(user, message, params[:id])
if(feedback.errors.empty?)
redirect_to project_feedback_path(params[:id]), notice: l(:label_feedback_success)
else
flash[:error] = feedback.errors.full_messages[0]
redirect_to project_feedback_path(params[:id])
end
end
# add by nwb
def leave_course_message
user = User.current
message = params[:new_form][:course_message]
feedback = Course.add_new_jour(user, message, params[:id])
if(feedback.errors.empty?)
redirect_to course_feedback_path(params[:id]), notice: l(:label_feedback_success)
else
flash[:error] = feedback.errors.full_messages[0]
redirect_to course_feedback_path(params[:id])
end
end
def add_brief_introdution
user = User.current
message = params[:new_form][:user_introduction]
UserExtensions.introduction(user, message)
redirect_to user_path(user.id)
end
private
def find_user
if params[:user_id]
@user = User.find(params[:user_id])
end
rescue
render_404
end
def obj_distinguish_url_origin
#modify by nwb
#添加对课程留言的支持
referer = request.headers["Referer"]
obj_id = referer.match(%r(/([0-9]{1,})(/|$)))[1]
if referer.match(/project/)
obj = Project.find_by_id(obj_id)
elsif referer.match(/course/)
obj = Course.find_by_id(obj_id)
elsif referer.match(/user/)
obj = User.find_by_id(obj_id)
elsif ( referer.match(/bids/) || referer.match(/calls/) )
obj = Bid.find_by_id(obj_id)
elsif ( referer.match(/contests/) || referer.match(/contests/) ) #new added
obj = Contest.find_by_id(obj_id)
elsif ( referer.match(/softapplications/) || referer.match(/softapplications/) ) #new added
obj = Softapplication.find_by_id(obj_id)
elsif ( referer.match(/homework_attach/) || referer.match(/homework_attach/) ) #new added
obj = HomeworkAttach.find_by_id(obj_id)
else
raise 'create reply obj unknow type.'
end
obj
end
def add_reply_adapter options
#modify by nwb
#添加对课程留言的支持
obj = obj_distinguish_url_origin
if obj.kind_of? User
obj.add_jour(nil, nil, nil, options)
elsif obj.kind_of? Project
Project.add_new_jour(nil, nil, obj.id, options)
elsif obj.kind_of? Course
Course.add_new_jour(nil, nil, obj.id, options)
elsif obj.kind_of? Bid
obj.add_jour(nil, nil, nil, options)
elsif obj.kind_of? Contest
obj.add_jour(nil, nil, obj.id, options) #new added
elsif obj.kind_of? Softapplication
obj.add_jour(nil, nil, obj.id, options) #new added
elsif obj.kind_of? HomeworkAttach
obj.add_jour(nil, nil, obj.id, options) #new added
else
raise 'create reply obj unknow type.'
end
end
#######end of message
end
# encoding: utf-8
#####leave message fq
class WordsController < ApplicationController
before_filter :find_user, :only => [:new, :create, :destroy, :more, :back]
def create
if params[:new_form][:user_message].size>0
unless params[:user_id].nil?
if params[:reference_content]
message = params[:new_form][:user_message] + "\n" + params[:reference_content]
else
message = params[:new_form][:user_message]
end
refer_user_id = params[:new_form][:reference_user_id].to_i
@user.add_jour(User.current, message, refer_user_id)
unless refer_user_id == 0 || refer_user_id == User.current.id
User.find(refer_user_id).add_jour(User.current, message, refer_user_id)
end
@user.count_new_jour
# if a_message.size > 5
# @message = a_message[-5, 5]
# else
# @message = a_message
# end
# @message_count = a_message.count
end
end
@jours = @user.journals_for_messages.where('m_parent_id IS NULL').reverse
@jour = paginateHelper @jours,10
respond_to do |format|
# format.html { redirect_to_referer_or {render :text => 'Watcher added.', :layout => true}}
format.js
#format.api { render_api_ok }
end
end
def create_reply
# 这里是创建回复所使用的方法,此方法只针对回复,每一个新的留言并不在此方法管理范围内。
# 由于多个地方用到了留言而之前的表设计也有jour_type/jour_id这类信息
# 所以在方法 add_reply_adapter 中判断所有调用此方法的来源页面,
# 为了保证兼容以往所有的代码,保证以往的方法可以调用,在返回页面中都做了各式各样的判断。
# 页面保证 render new_respond/journal_reply
# 修改 add_reply_adapter 中可以确保留言创建成功
# 删除留言功能要调用destroy也记得在destroy.js中修改
# deny api. api useless
parent_id = params[:reference_id]
author_id = User.current.id
reply_user_id = params[:reference_user_id]
reply_id = params[:reference_message_id] # 暂时不实现
content = params[:user_notes]
@show_name = params[:show_name] == "true"
options = {:user_id => author_id,
:status => true,
:m_parent_id => parent_id,
:m_reply_id => reply_id,
:reply_id => reply_user_id,
:notes => content,
:is_readed => false}
@jfm = add_reply_adapter options
respond_to do |format|
# format.html {
# if @jfm.errors.empty?
# flash.now.notice = l(:label_feedback_success)
# else
# flash.now.errors = l(:label_feedback_fail)
# end
# render 'test/index'
# }
format.js{
@save_succ = true if @jfm.errors.empty?
}
end
end
def destroy
@journal_destroyed = JournalsForMessage.delete_message(params[:object_id])
if @journal_destroyed.jour_type == "Bid"
@bid = Bid.find(@journal_destroyed.jour_id)
end
if @bid
@jours_count = @bid.journals_for_messages.where('m_parent_id IS NULL').count
end
respond_to do |format|
format.js
#format.api { render_api_ok }
end
end
def destroyJournal
@journalP=JournalsForMessage.find(params[:object_id])
@journalP.destroy
@page = params[:page]
@page = @page.to_i
@project = Project.find params[:project_id]
# Find the page of the requested reply
@jours = @project.journals_for_messages.where('m_parent_id IS NULL').order('created_on DESC')
@limit = 10
offset = @jours.count(:conditions => ["#{JournalsForMessage.table_name}.id > ?", params[:r].to_i])
page = 1 + offset / @limit
if params[:r] && @page.nil?
@page = page
end
if @page < 0
@page = 1
end
if @page > page
@page = page
end
@feedback_count = @jours.count
@feedback_pages = Paginator.new @feedback_count, @limit, @page
@offset ||= @feedback_pages.offset
@jour = @jours[@offset, @limit]
@state = false
@base_courses_tag = @project.project_type
respond_to do |format|
format.js
end
end
def new
@jour = JournalsForMessage.find(params[:journal_id]) if params[:journal_id]
if @jour
user = @jour.user
text = @jour.notes
else
user = @user
text = []
end
# Replaces pre blocks with [...]
text = text.to_s.strip.gsub(%r{<pre>((.|\s)*?)</pre>}m, '[...]')
@content = "> #{ll(User.current.language, :text_user_wrote, user)}\n> "
@content << text.gsub(/(\r?\n|\r\n?)/, "\n> ") + "\n\n"
# @content << text.gsub(/(\r?\n|\r\n?)/, "\n> ") + "\n\n"
# @content = "> #{ll(Setting.default_language, :text_user_wrote, user)}\n> "
@id = user.id
rescue ActiveRecord::RecordNotFound
render_404
end
def more
@jours = @user.journals_for_messages.reverse
@limit = 10
@feedback_count = @jours.count
@feedback_pages = Paginator.new @feedback_count, @limit, params['page']
@offset ||= @feedback_pages.offset
@jour = @jours[@offset, @limit]
@state = true
respond_to do |format|
format.html { redirect_to :back }
format.js
#format.api { render_api_ok }
end
end
def back
@jours = @user.journals_for_messages.reverse
@limit = 10
@feedback_count = @jours.count
@feedback_pages = Paginator.new @feedback_count, @limit, params['page']
@offset ||= @feedback_pages.offset
@jour = @jours[@offset, @limit]
@state = false
respond_to do |format|
format.html { redirect_to :back }
format.js
#format.api { render_api_ok }
end
end
def add_project_respond
user = User.current
message = params[:new_form][:project_message]
Project.add_jour(user, message)
redirect_to project_feedback_url('trustie')
# redirect_to signin_path
end
def leave_project_message
user = User.current
message = params[:new_form][:project_message]
feedback = Project.add_new_jour(user, message, params[:id])
if(feedback.errors.empty?)
redirect_to project_feedback_url(params[:id]), notice: l(:label_feedback_success)
else
flash[:error] = feedback.errors.full_messages[0]
redirect_to project_feedback_url(params[:id])
end
end
# add by nwb
def leave_course_message
user = User.current
message = params[:new_form][:course_message]
feedback = Course.add_new_jour(user, message, params[:id])
if(feedback.errors.empty?)
redirect_to course_feedback_url(params[:id]), notice: l(:label_feedback_success)
else
flash[:error] = feedback.errors.full_messages[0]
redirect_to course_feedback_url(params[:id])
end
end
def add_brief_introdution
user = User.current
message = params[:new_form][:user_introduction]
UserExtensions.introduction(user, message)
redirect_to user_url(user.id)
end
private
def find_user
if params[:user_id]
@user = User.find(params[:user_id])
end
rescue
render_404
end
def obj_distinguish_url_origin
#modify by nwb
#添加对课程留言的支持
referer = request.headers["Referer"]
#referer = "http://forge.trustie.net/words/create_reply"
obj_id = referer.match(%r(/([0-9]{1,})(/|\?|$)))[1]
if referer.match(/project/)
obj = Project.find_by_id(obj_id)
elsif referer.match(/user/)
obj = User.find_by_id(obj_id)
elsif ( referer.match(/bids/) || referer.match(/calls/) )
obj = Bid.find_by_id(obj_id)
elsif ( referer.match(/contests/) || referer.match(/contests/) ) #new added
obj = Contest.find_by_id(obj_id)
elsif ( referer.match(/softapplications/) || referer.match(/softapplications/) ) #new added
obj = Softapplication.find_by_id(obj_id)
elsif ( referer.match(/homework_attach/) || referer.match(/homework_attach/) ) #new added
obj = HomeworkAttach.find_by_id(obj_id)
elsif referer.match(/course/)
obj = Course.find_by_id(obj_id)
else
#raise "create reply obj unknow type.#{referer}"
end
obj
end
def add_reply_adapter options
#modify by nwb
#添加对课程留言的支持
#留言回复应该不关系其所属的Class而关心的是其所属的父留言
obj = obj_distinguish_url_origin || User.find_by_id(2)
if obj.kind_of? User
obj.add_jour(nil, nil, nil, options)
elsif obj.kind_of? Project
Project.add_new_jour(nil, nil, obj.id, options)
elsif obj.kind_of? Course
Course.add_new_jour(nil, nil, obj.id, options)
elsif obj.kind_of? Bid
obj.add_jour(nil, nil, nil, options)
elsif obj.kind_of? Contest
obj.add_jour(nil, nil, obj.id, options) #new added
elsif obj.kind_of? Softapplication
obj.add_jour(nil, nil, obj.id, options) #new added
elsif obj.kind_of? HomeworkAttach
obj.add_jour(nil, nil, obj.id, options) #new added
else
raise "create reply obj unknow type.#{obj.class}"
end
end
#######end of message
end

@ -1,128 +1,128 @@
# Redmine - project management software
# Copyright (C) 2006-2013 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 WorkflowsController < ApplicationController
layout 'admin'
before_filter :require_admin, :find_roles, :find_trackers
def index
@workflow_counts = WorkflowTransition.count_by_tracker_and_role
end
def edit
@role = Role.find_by_id(params[:role_id]) if params[:role_id]
@tracker = Tracker.find_by_id(params[:tracker_id]) if params[:tracker_id]
if request.post?
WorkflowTransition.destroy_all( ["role_id=? and tracker_id=?", @role.id, @tracker.id])
(params[:issue_status] || []).each { |status_id, transitions|
transitions.each { |new_status_id, options|
author = options.is_a?(Array) && options.include?('author') && !options.include?('always')
assignee = options.is_a?(Array) && options.include?('assignee') && !options.include?('always')
WorkflowTransition.create(:role_id => @role.id, :tracker_id => @tracker.id, :old_status_id => status_id, :new_status_id => new_status_id, :author => author, :assignee => assignee)
}
}
if @role.save
redirect_to workflows_edit_path(:role_id => @role, :tracker_id => @tracker, :used_statuses_only => params[:used_statuses_only])
return
end
end
@used_statuses_only = (params[:used_statuses_only] == '0' ? false : true)
if @tracker && @used_statuses_only && @tracker.issue_statuses.any?
@statuses = @tracker.issue_statuses
end
@statuses ||= IssueStatus.sorted.all
if @tracker && @role && @statuses.any?
workflows = WorkflowTransition.where(:role_id => @role.id, :tracker_id => @tracker.id).all
@workflows = {}
@workflows['always'] = workflows.select {|w| !w.author && !w.assignee}
@workflows['author'] = workflows.select {|w| w.author}
@workflows['assignee'] = workflows.select {|w| w.assignee}
end
end
def permissions
@role = Role.find_by_id(params[:role_id]) if params[:role_id]
@tracker = Tracker.find_by_id(params[:tracker_id]) if params[:tracker_id]
if request.post? && @role && @tracker
WorkflowPermission.replace_permissions(@tracker, @role, params[:permissions] || {})
redirect_to workflows_permissions_path(:role_id => @role, :tracker_id => @tracker, :used_statuses_only => params[:used_statuses_only])
return
end
@used_statuses_only = (params[:used_statuses_only] == '0' ? false : true)
if @tracker && @used_statuses_only && @tracker.issue_statuses.any?
@statuses = @tracker.issue_statuses
end
@statuses ||= IssueStatus.sorted.all
if @role && @tracker
@fields = (Tracker::CORE_FIELDS_ALL - @tracker.disabled_core_fields).map {|field| [field, l("field_"+field.sub(/_id$/, ''))]}
@custom_fields = @tracker.custom_fields
@permissions = WorkflowPermission.where(:tracker_id => @tracker.id, :role_id => @role.id).all.inject({}) do |h, w|
h[w.old_status_id] ||= {}
h[w.old_status_id][w.field_name] = w.rule
h
end
@statuses.each {|status| @permissions[status.id] ||= {}}
end
end
def copy
if params[:source_tracker_id].blank? || params[:source_tracker_id] == 'any'
@source_tracker = nil
else
@source_tracker = Tracker.find_by_id(params[:source_tracker_id].to_i)
end
if params[:source_role_id].blank? || params[:source_role_id] == 'any'
@source_role = nil
else
@source_role = Role.find_by_id(params[:source_role_id].to_i)
end
@target_trackers = params[:target_tracker_ids].blank? ? nil : Tracker.find_all_by_id(params[:target_tracker_ids])
@target_roles = params[:target_role_ids].blank? ? nil : Role.find_all_by_id(params[:target_role_ids])
if request.post?
if params[:source_tracker_id].blank? || params[:source_role_id].blank? || (@source_tracker.nil? && @source_role.nil?)
flash.now[:error] = l(:error_workflow_copy_source)
elsif @target_trackers.blank? || @target_roles.blank?
flash.now[:error] = l(:error_workflow_copy_target)
else
WorkflowRule.copy(@source_tracker, @source_role, @target_trackers, @target_roles)
flash[:notice] = l(:notice_successful_update)
redirect_to workflows_copy_path(:source_tracker_id => @source_tracker, :source_role_id => @source_role)
end
end
end
private
def find_roles
@roles = Role.sorted.all
end
def find_trackers
@trackers = Tracker.sorted.all
end
end
# Redmine - project management software
# Copyright (C) 2006-2013 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 WorkflowsController < ApplicationController
layout 'admin'
before_filter :require_admin, :find_roles, :find_trackers
def index
@workflow_counts = WorkflowTransition.count_by_tracker_and_role
end
def edit
@role = Role.find_by_id(params[:role_id]) if params[:role_id]
@tracker = Tracker.find_by_id(params[:tracker_id]) if params[:tracker_id]
if request.post?
WorkflowTransition.destroy_all( ["role_id=? and tracker_id=?", @role.id, @tracker.id])
(params[:issue_status] || []).each { |status_id, transitions|
transitions.each { |new_status_id, options|
author = options.is_a?(Array) && options.include?('author') && !options.include?('always')
assignee = options.is_a?(Array) && options.include?('assignee') && !options.include?('always')
WorkflowTransition.create(:role_id => @role.id, :tracker_id => @tracker.id, :old_status_id => status_id, :new_status_id => new_status_id, :author => author, :assignee => assignee)
}
}
if @role.save
redirect_to workflows_edit_url(:role_id => @role, :tracker_id => @tracker, :used_statuses_only => params[:used_statuses_only])
return
end
end
@used_statuses_only = (params[:used_statuses_only] == '0' ? false : true)
if @tracker && @used_statuses_only && @tracker.issue_statuses.any?
@statuses = @tracker.issue_statuses
end
@statuses ||= IssueStatus.sorted.all
if @tracker && @role && @statuses.any?
workflows = WorkflowTransition.where(:role_id => @role.id, :tracker_id => @tracker.id).all
@workflows = {}
@workflows['always'] = workflows.select {|w| !w.author && !w.assignee}
@workflows['author'] = workflows.select {|w| w.author}
@workflows['assignee'] = workflows.select {|w| w.assignee}
end
end
def permissions
@role = Role.find_by_id(params[:role_id]) if params[:role_id]
@tracker = Tracker.find_by_id(params[:tracker_id]) if params[:tracker_id]
if request.post? && @role && @tracker
WorkflowPermission.replace_permissions(@tracker, @role, params[:permissions] || {})
redirect_to workflows_permissions_url(:role_id => @role, :tracker_id => @tracker, :used_statuses_only => params[:used_statuses_only])
return
end
@used_statuses_only = (params[:used_statuses_only] == '0' ? false : true)
if @tracker && @used_statuses_only && @tracker.issue_statuses.any?
@statuses = @tracker.issue_statuses
end
@statuses ||= IssueStatus.sorted.all
if @role && @tracker
@fields = (Tracker::CORE_FIELDS_ALL - @tracker.disabled_core_fields).map {|field| [field, l("field_"+field.sub(/_id$/, ''))]}
@custom_fields = @tracker.custom_fields
@permissions = WorkflowPermission.where(:tracker_id => @tracker.id, :role_id => @role.id).all.inject({}) do |h, w|
h[w.old_status_id] ||= {}
h[w.old_status_id][w.field_name] = w.rule
h
end
@statuses.each {|status| @permissions[status.id] ||= {}}
end
end
def copy
if params[:source_tracker_id].blank? || params[:source_tracker_id] == 'any'
@source_tracker = nil
else
@source_tracker = Tracker.find_by_id(params[:source_tracker_id].to_i)
end
if params[:source_role_id].blank? || params[:source_role_id] == 'any'
@source_role = nil
else
@source_role = Role.find_by_id(params[:source_role_id].to_i)
end
@target_trackers = params[:target_tracker_ids].blank? ? nil : Tracker.find_all_by_id(params[:target_tracker_ids])
@target_roles = params[:target_role_ids].blank? ? nil : Role.find_all_by_id(params[:target_role_ids])
if request.post?
if params[:source_tracker_id].blank? || params[:source_role_id].blank? || (@source_tracker.nil? && @source_role.nil?)
flash.now[:error] = l(:error_workflow_copy_source)
elsif @target_trackers.blank? || @target_roles.blank?
flash.now[:error] = l(:error_workflow_copy_target)
else
WorkflowRule.copy(@source_tracker, @source_role, @target_trackers, @target_roles)
flash[:notice] = l(:notice_successful_update)
redirect_to workflows_copy_url(:source_tracker_id => @source_tracker, :source_role_id => @source_role)
end
end
end
private
def find_roles
@roles = Role.sorted.all
end
def find_trackers
@trackers = Tracker.sorted.all
end
end

@ -1,154 +1,122 @@
class ZipdownController < ApplicationController
#查找项目(课程)
before_filter :find_project_by_bid_id, :only => [:assort]
#检查权限
#勿删 before_filter :authorize, :only => [:assort,:download_user_homework]
SAVE_FOLDER = "#{Rails.root}/files"
OUTPUT_FOLDER = "#{Rails.root}/tmp/archiveZip"
#通过作业Id找到项目课程
def find_project_by_bid_id
obj_class = params[:obj_class]
obj_id = params[:obj_id]
obj = obj_class.constantize.find(obj_id)
case obj.class.to_s.to_sym
when :Bid
@project = obj.courses[0]
end
end
def assort
obj_class = params[:obj_class]
obj_id = params[:obj_id]
obj = obj_class.constantize.find(obj_id)
zipfile = nil
case obj.class.to_s.to_sym
when :Bid
zipfile = zip_bid obj
else
logger.error "[ZipDown#assort] ===> #{obj.class.to_s.to_sym} unKown !!"
end
send_file zipfile, :filename => obj.name+".zip", :type => detect_content_type(zipfile) if zipfile
#rescue NameError, ActiveRecord::RecordNotFound => e
#logger.error "[ZipDown] ===> #{e}"
#@error = e
end
#下载某一学生的作业的所有文件
def download_user_homework
homework = HomeworkAttach.find params[:homework]
if homework != nil && (User.current.admin? || User.current.member_of_course?(homework.bid.courses.first))
zipfile = zip_homework_by_user homework
send_file zipfile, :filename => homework.name+".zip", :type => detect_content_type(zipfile) if zipfile
else
render_403 :message => :notice_not_authorized
end
end
private
def zip_user_bid(bid,user_id)
# Todo: User Access Controll
homeattaches = bid.homeworks.where("user_id = ?",user_id)
# 得到每一个人所有文件打包的zip文件
# 并将每一个人的zip打包为一个并返回路径
user_zip_paths = homeattaches.map do |homeattach|
zip_homework_by_user homeattach
end
#zipping "#{Time.now.to_i}_#{bid.name}.zip", user_zip_paths, OUTPUT_FOLDER
user_zip_paths
end
def zip_bid(bid)
# Todo: User Access Controll
homeattaches = bid.homeworks
# 得到每一个人所有文件打包的zip文件
# 并将每一个人的zip打包为一个并返回路径
user_zip_paths = homeattaches.map do |homeattach|
zip_homework_by_user homeattach
end
zipping "#{Time.now.to_i}_#{bid.name}.zip", user_zip_paths, OUTPUT_FOLDER
#@paths = homeworks_attach_path
#zipfile = ziping homeworks_attach_path
#send_file zipfile, :filename => bid.name,
# :type => detect_content_type(zipfile)
#rescue Errno::ENOENT => e
# logger.error "[Errno::ENOENT] ===> #{e}"
# @error = e
end
def zip_homework_by_user(homeattach)
homeworks_attach_path = []
# 需要将所有homework.attachments遍历加入zip
# 并且返回zip路径
user_attaches_paths = homeattach.attachments.each do |attach|
#length = attach.storage_path.length
homeworks_attach_path << attach.diskfile#.to_s.slice((length+1)..-1)
end
zipping "#{homeattach.user.name.to_s}_#{Time.now.to_i}.zip", homeworks_attach_path, OUTPUT_FOLDER, true
#user_attaches_paths
end
def zipping(zip_name_refer, files_paths, output_path, is_attachment=false)
# 输入待打包的文件列表已经打包文件定位到ouput_path
ic = Iconv.new('GBK//IGNORE', 'UTF-8//IGNORE')
input_filename = files_paths
rename_zipfile = zip_name_refer ||= "archive_#{Time.now.to_i}.zip"
zipfile_name = "#{output_path}/#{rename_zipfile}"
Dir.mkdir(File.dirname(zipfile_name)) unless File.exist?(File.dirname(zipfile_name))
Zip::File.open(zipfile_name, Zip::File::CREATE) do |zipfile|
input_filename.each do |filename|
rename_file = Time.now.to_i.to_s+ ic.iconv( (File.basename(filename)) ).to_s
rename_file = ic.iconv( filename_to_real( File.basename(filename))).to_s if is_attachment
zipfile.add(rename_file, filename)
end
zipfile.get_output_stream('ReadMe') do |os|
os.write 'Homeworks'
end
end
zipfile_name
rescue Errno => e
logger.error "[zipdown#zipping] ===> #{e}"
@error = e
end
#def ziping files_path
# ic = Iconv.new('GBK//IGNORE', 'UTF-8//IGNORE')
# folder = SaveFolder
# input_filename = files_path
# zipfile_name = "#{OutputFolder}/archive_#{Time.now.to_i}.zip"
#
# Dir.mkdir(File.dirname(zipfile_name)) unless File.exist?(File.dirname(zipfile_name))
# Zip::File.open(zipfile_name, Zip::File::CREATE) do |zipfile|
# input_filename.each do |filename|
# zipfile.add(ic.iconv(filename_to_real(File.basename(filename))), folder + '/' + filename)
# end
# zipfile.get_output_stream("ReadMe") { |os|
# os.write "Homeworks"
# }
# end
# zipfile_name
#rescue Errno => e
# logger.error "[zipdown#zipping] ===> #{e}"
# @error = e
#end
def detect_content_type(name)
content_type = Redmine::MimeType.of(name)
content_type.to_s
end
def filename_to_real(name)
attach = Attachment.find_by_disk_filename(name)
attach.filename
end
end
require 'zip'
class ZipdownController < ApplicationController
#查找项目(课程)
before_filter :find_project_by_bid_id, :only => [:assort]
#检查权限
#勿删 before_filter :authorize, :only => [:assort,:download_user_homework]
SAVE_FOLDER = "#{Rails.root}/files"
OUTPUT_FOLDER = "#{Rails.root}/tmp/archiveZip"
#通过作业Id找到项目课程
def find_project_by_bid_id
obj_class = params[:obj_class]
obj_id = params[:obj_id]
obj = obj_class.constantize.find(obj_id)
case obj.class.to_s.to_sym
when :Bid
@project = obj.courses[0]
end
end
def assort
if params[:obj_class] == "Bid"
bid = Bid.find params[:obj_id]
file_count = 0
bid.homeworks.map { |homework| file_count += homework.attachments.count}
if file_count > 0
zipfile = zip_bid bid
else
render file: 'public/no_file_found.html'
end
else
logger.error "[ZipDown#assort] ===> #{params[:obj_class]} unKown !!"
end
send_file zipfile, :filename => bid.name + ".zip", :type => detect_content_type(zipfile) if zipfile
rescue Exception => e
render file: 'public/no_file_found.html'
end
#下载某一学生的作业的所有文件
def download_user_homework
homework = HomeworkAttach.find params[:homework]
if User.current.admin? || User.current.member_of_course?(homework.bid.courses.first)
if homework != nil
unless homework.attachments.empty?
zipfile = zip_homework_by_user homework
send_file zipfile, :filename => ((homework.user.user_extensions.nil? || homework.user.user_extensions.student_id.nil?) ? "" : homework.user.user_extensions.student_id) +
"_" + (homework.user.lastname.nil? ? "" : homework.user.lastname) + (homework.user.firstname.nil? ? "" : homework.user.firstname) +
"_" + homework.name + ".zip", :type => detect_content_type(zipfile) if(zipfile)
else
render file: 'public/no_file_found.html'
end
else
render file: 'public/file_not_found.html'
end
else
render_403
end
rescue => e
render file: 'public/file_not_found.html'
end
private
def zip_bid(bid)
# Todo: User Access Controll
bid_homework_path = []
bid.homeworks.each do |homeattach|
unless homeattach.attachments.empty?
bid_homework_path << zip_homework_by_user(homeattach)
end
end
zipping "#{Time.now.to_i}_#{bid.name}.zip", bid_homework_path, OUTPUT_FOLDER
end
def zip_homework_by_user(homeattach)
homeworks_attach_path = []
# 需要将所有homework.attachments遍历加入zip
# 并且返回zip路径
homeattach.attachments.each do |attach|
homeworks_attach_path << attach.diskfile#.to_s.slice((length+1)..-1)
end
zipping("#{homeattach.user.lastname}#{homeattach.user.firstname}_#{((homeattach.user.user_extensions.nil? || homeattach.user.user_extensions.student_id.nil?) ? "" : homeattach.user.user_extensions.student_id)}_#{Time.now.to_i.to_s}.zip", homeworks_attach_path, OUTPUT_FOLDER, true)
end
def zipping(zip_name_refer, files_paths, output_path, is_attachment=false)
# 输入待打包的文件列表已经打包文件定位到ouput_path
ic = Iconv.new('GBK//IGNORE', 'UTF-8//IGNORE')
input_filename = files_paths
rename_zipfile = zip_name_refer ||= "#{Time.now.to_i.to_s}.zip"
zipfile_name = "#{output_path}/#{rename_zipfile}"
Dir.mkdir(File.dirname(zipfile_name)) unless File.exist?(File.dirname(zipfile_name))
Zip::File.open(zipfile_name, Zip::File::CREATE) do |zipfile|
input_filename.each do |filename|
rename_file = ic.iconv( (File.basename(filename)) ).to_s
rename_file = ic.iconv( filename_to_real( File.basename(filename))).to_s if is_attachment
zipfile.add(rename_file, filename)
end
#zipfile.get_output_stream('ReadMe') do |os|
# os.write 'Homeworks'
#end
end
zipfile_name
rescue Errno => e
logger.error "[zipdown#zipping] ===> #{e}"
@error = e
end
def detect_content_type(name)
content_type = Redmine::MimeType.of(name)
content_type.to_s
end
def filename_to_real(name)
attach = Attachment.find_by_disk_filename(name)
attach.filename
end
end

File diff suppressed because it is too large Load Diff

@ -1,206 +1,243 @@
# encoding: utf-8
#
# Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module AttachmentsHelper
# Displays view/delete links to the attachments of the given object
# Options:
# :author -- author names are not displayed if set to false
# :thumbails -- display thumbnails if enabled in settings
def link_to_attachments(container, options = {})
options.assert_valid_keys(:author, :thumbnails)
if container.attachments.any?
options = {:deletable => container.attachments_deletable?, :author => true}.merge(options)
render :partial => 'attachments/links',
:locals => {:attachments => container.attachments, :options => options, :thumbnails => (options[:thumbnails] && Setting.thumbnails_enabled?)}
end
end
def attach_delete(project)
if User.current.logged? && (User.current.admin? || (!Member.where('user_id = ? and project_id = ?', User.current.id, project.bid.courses.first.id).first.nil? && (Member.where('user_id = ? and project_id = ?', User.current.id, project.bid.courses.first.id).first.roles&Role.where('id = ? or id = ?', 3, 7)).size >0) || project.user_id == User.current.id)
true
else
false
end
end
def render_api_attachment(attachment, api)
api.attachment do
api.id attachment.id
api.filename attachment.filename
api.filesize attachment.filesize
api.content_type attachment.content_type
api.description attachment.description
api.content_url url_for(:controller => 'attachments', :action => 'download', :id => attachment, :filename => attachment.filename, :only_path => false)
api.author(:id => attachment.author.id, :name => attachment.author.name) if attachment.author
api.created_on attachment.created_on
end
end
def link_to_memo_attachments(container, options = {})
options.assert_valid_keys(:author, :thumbnails)
if container.attachments.any?
options = {:deletable => deletable?(container), :author => true}.merge(options)
render :partial => 'attachments/links',
:locals => {:attachments => container.attachments, :options => options, :thumbnails => (options[:thumbnails] && Setting.thumbnails_enabled?)}
end
end
private
def deletable? container, user=User.current
User.current.logged? && (container.author == user || user.admin?)
end
# this method is used to get all projects that tagged one tag
# added by william
def get_attachments_by_tag(tag_name)
Attachment.tagged_with(tag_name).order('created_on desc')
end
# this method is used to get all attachments that from one project and tagged one tag
# added by Long Jun
def get_attachments_by_project_tag(tag_name, obj)
@project_id =nil
if obj.container_type == 'Version'
@project_id = Version.find(obj.container_id).project_id
elsif obj.container_type == 'Project'
@project_id = obj.container_id
end
Attachment.tagged_with(tag_name).order('created_on desc').where("(container_id = :project_id and container_type = 'Project') or
(container_id in (select id from versions where project_id =:project_id) and container_type = 'Version')", {:project_id => @project_id})
end
def render_attachments_for_new_project(project, limit=nil)
# 查询条件
params[:q] ||= ""
filename_condition = params[:q].strip
attachAll = Attachment.scoped
# 当前项目所有资源
# attachments = Attachment.find_all_by_container_type_and_container_id(project.class, project.id)
# attachments = Attachment.where("container_type = '#{project.class}' and container_id = #{project.id}")
# 除去当前项目的所有资源
nobelong_attach = Attachment.where("!(container_type = '#{project.class}' and container_id = #{project.id})") unless project.blank?
# 搜索域确定
domain = project.nil? ? attachAll : nobelong_attach
# 搜索到的资源
searched_attach = domain.where("filename LIKE :like ", like:"%#{filename_condition}%").limit(limit).order('created_on desc')
searched_attach = private_filter searched_attach
searched_attach = paginateHelper(searched_attach, 10)
s = content_tag('div', attachments_check_box_tags('attachment[attach][]', searched_attach), :id => 'attachments')
links = pagination_links_full(@obj_pages, @obj_count, :per_page_links => false) {|text, parameters, options|
link_to text, attachments_autocomplete_path( parameters.merge(:project_id=>project.id,:q => params[:q], :format => 'js')), :remote => true }
return s + content_tag('div', content_tag('ul', links), :class => 'pagination')
# ================================================================================================
# attach_count = searched_attach.count
# attach_pages = Redmine::Pagination::Paginator.new attach_count, 10, params['page'] #by young
# attachs = searched_attach.offset(attach_pages.offset).limit(attach_pages.per_page).all
# s = content_tag('div', attachments_check_box_tags('attachment[attach][]', attachs), :id => 'attachments')
# links = pagination_links_full(attach_pages, attach_count, :per_page_links => false) {|text, parameters, options|
# link_to text, attachments_autocomplete_path( parameters.merge(:q => params[:q], :format => 'js')), :remote => true }
# return s + content_tag('div', content_tag('ul', links), :class => 'pagination')
# return searched_attach.to_json
end
# add by nwb
def render_attachments_for_new_course(course, limit=nil)
# 查询条件
params[:q] ||= ""
filename_condition = params[:q].strip
attachAll = Attachment.scoped
# 除去当前课程的所有资源
nobelong_attach = Attachment.where("!(container_type = '#{course.class}' and container_id = #{course.id})") unless course.blank?
# 搜索域确定
domain = course.nil? ? attachAll : nobelong_attach
# 搜索到的资源
searched_attach = domain.where("filename LIKE :like ", like:"%#{filename_condition}%").limit(limit).order('created_on desc')
searched_attach = private_filter searched_attach
searched_attach = paginateHelper(searched_attach, 10)
#testattach = Attachment.public_attachments
s = content_tag('div', attachments_check_box_tags('attachment[attach][]', searched_attach), :id => 'attachments')
links = pagination_links_full(@obj_pages, @obj_count, :per_page_links => false) {|text, parameters, options|
link_to text, attachments_autocomplete_path( parameters.merge(:course_id=>course.id,:q => params[:q], :format => 'js')), :remote => true }
return s + content_tag('div', content_tag('ul', links), :class => 'pagination')
end
def attachments_check_box_tags(name, attachs)
s = ''
attachs.each do |attach|
s << "<label>#{ check_box_tag name, attach.id, false, :id => nil } #{h attach.filename}</label><br/>"
end
s.html_safe
end
def private_filter resultSet
result = resultSet.to_a.dup
# modify by nwb
#添加对课程资源文件的判断
resultSet.map { |res|
if(res.container.nil? ||
(res.container.class.to_s=="Project" && res.container.is_public == false) ||
(res.container.has_attribute?(:project) && res.container.project && res.container.project.is_public == false) ||
(res.container.class.to_s=="HomeworkAttach" && res.container.bid.reward_type == 3) ||
(res.container.class.to_s=="Course" && res.container.is_public == false) ||
(res.container.has_attribute?(:course) && res.container.course && res.container.course.is_public == false)
)
result.delete(res)
end
}
result
end
include Redmine::Pagination
def paginateHelper obj, pre_size=10
@obj_count = obj.count
@obj_pages = Paginator.new @obj_count, pre_size, params['page']
if obj.kind_of? ActiveRecord::Base or obj.kind_of? ActiveRecord::Relation
obj.limit(@obj_pages.per_page).offset(@obj_pages.offset)
elsif obj.kind_of? Array
obj[@obj_pages.offset, @obj_pages.per_page]
else
logger.error "[ApplicationController] Error : application_controller#paginateHelper ===> unknow category: #{obj.class}"
raise RuntimeError, 'unknow type, Please input you type into this helper.'
end
end
end
# encoding: utf-8
#
# Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module AttachmentsHelper
# Displays view/delete links to the attachments of the given object
# Options:
# :author -- author names are not displayed if set to false
# :thumbails -- display thumbnails if enabled in settings
include Redmine::Pagination
def link_to_attachments(container, options = {})
options.assert_valid_keys(:author, :thumbnails)
if container.attachments.any?
options = {:deletable => container.attachments_deletable?, :author => true}.merge(options)
render :partial => 'attachments/links',
:locals => {:attachments => container.attachments, :options => options, :thumbnails => (options[:thumbnails] && Setting.thumbnails_enabled?)}
end
end
def attach_delete(project)
if User.current.logged? && (User.current.admin? || (!Member.where('user_id = ? and project_id = ?', User.current.id, project.bid.courses.first.id).first.nil? && (Member.where('user_id = ? and project_id = ?', User.current.id, project.bid.courses.first.id).first.roles&Role.where('id = ? or id = ?', 3, 7)).size >0) || project.user_id == User.current.id)
true
else
false
end
end
def render_api_attachment(attachment, api)
api.attachment do
api.id attachment.id
api.filename attachment.filename
api.filesize attachment.filesize
api.content_type attachment.content_type
api.description attachment.description
api.content_url url_for(:controller => 'attachments', :action => 'download', :id => attachment, :filename => attachment.filename, :only_path => false)
api.author(:id => attachment.author.id, :name => attachment.author.name) if attachment.author
api.created_on attachment.created_on
end
end
def link_to_memo_attachments(container, options = {})
options.assert_valid_keys(:author, :thumbnails)
if container.attachments.any?
options = {:deletable => deletable?(container), :author => true}.merge(options)
render :partial => 'attachments/links',
:locals => {:attachments => container.attachments, :options => options, :thumbnails => (options[:thumbnails] && Setting.thumbnails_enabled?)}
end
end
def course_contains_attachment? course,attachment
course.attachments.each do |att|
if att.id == attachment.id || (!att.copy_from.nil? && !attachment.copy_from.nil? && att.copy_from == attachment.copy_from) || att.copy_from == attachment.id || att.id == attachment.copy_from
return true
end
end
false
end
def get_qute_number attachment
if attachment.copy_from
result = Attachment.find_by_sql("select count(*) as number from attachments where copy_from = #{attachment.copy_from}")
else
result = Attachment.find_by_sql("select count(*) as number from attachments where copy_from = #{attachment.id}")
end
if result.nil? || result.count <= 0
return 0
else
return result[0].number
end
end
private
def deletable? container, user=User.current
User.current.logged? && (container.author == user || user.admin?)
end
# this method is used to get all projects that tagged one tag
# added by william
def get_attachments_by_tag(tag_name)
Attachment.tagged_with(tag_name).order('created_on desc')
end
# this method is used to get all attachments that from one project and tagged one tag
# added by Long Jun
def get_attachments_by_project_tag(tag_name, obj)
@project_id =nil
if obj.container_type == 'Version'
@project_id = Version.find(obj.container_id).project_id
elsif obj.container_type == 'Project'
@project_id = obj.container_id
end
attachments = Attachment.tagged_with(tag_name).order('created_on desc').where("(container_id = :project_id and container_type = 'Project') or
(container_id in (select id from versions where project_id =:project_id) and container_type = 'Version')", {:project_id => @project_id})
return attachments
end
def render_attachments_for_new_project(project, limit=nil)
# 查询条件
params[:q] ||= ""
filename_condition = params[:q].strip
attachAll = Attachment.scoped
# 当前项目所有资源
# attachments = Attachment.find_all_by_container_type_and_container_id(project.class, project.id)
# attachments = Attachment.where("container_type = '#{project.class}' and container_id = #{project.id}")
# 除去当前项目的所有资源
nobelong_attach = Attachment.where("!(container_type = '#{project.class}' and container_id = #{project.id})") unless project.blank?
# 搜索域确定
domain = project.nil? ? attachAll : nobelong_attach
# 搜索到的资源
searched_attach = domain.where("is_public=1 and filename LIKE :like ", like:"%#{filename_condition}%").limit(limit).order('created_on desc')
#searched_attach = private_filter searched_attach
searched_attach = paginateHelper(searched_attach, 10)
s = content_tag('div', attachments_check_box_tags('attachment[attach][]', searched_attach), :id => 'attachments')
links = pagination_links_full(@obj_pages, @obj_count, :per_page_links => false) {|text, parameters, options|
link_to text, attachments_autocomplete_path( parameters.merge(:project_id=>project.id,:q => params[:q], :format => 'js')), :remote => true }
return s + content_tag('div', content_tag('ul', links), :class => 'pagination')
# ================================================================================================
# attach_count = searched_attach.count
# attach_pages = Redmine::Pagination::Paginator.new attach_count, 10, params['page'] #by young
# attachs = searched_attach.offset(attach_pages.offset).limit(attach_pages.per_page).all
# s = content_tag('div', attachments_check_box_tags('attachment[attach][]', attachs), :id => 'attachments')
# links = pagination_links_full(attach_pages, attach_count, :per_page_links => false) {|text, parameters, options|
# link_to text, attachments_autocomplete_path( parameters.merge(:q => params[:q], :format => 'js')), :remote => true }
# return s + content_tag('div', content_tag('ul', links), :class => 'pagination')
# return searched_attach.to_json
end
# add by nwb
def render_attachments_for_new_course(course, limit=nil)
# 查询条件
params[:q] ||= ""
filename_condition = params[:q].strip
#attachAll = Attachment.where("author_id = #{User.current.id}")
#
## 除去当前课程的所有资源
#nobelong_attach =
# 搜索域确定
course.nil? ?
domain=Attachment.where("author_id = #{User.current.id}")
:
domain=Attachment.where("author_id = #{User.current.id} and container_type = 'Course' and container_id <> #{course.id}") unless course.blank?
# 搜索到的资源
searched_attach = domain.where("filename LIKE :like ", like:"%#{filename_condition}%").limit(limit).order('created_on desc')
#searched_attach = private_filter searched_attach
searched_attach = paginateHelper(searched_attach, 10)
#testattach = Attachment.public_attachments
s = content_tag('div', attachments_check_box_tags('attachment[attach][]', searched_attach), :id => 'attachments')
links = pagination_links_full(@obj_pages, @obj_count, :per_page_links => false) {|text, parameters, options|
link_to text, attachments_autocomplete_path( parameters.merge(:course_id=>course.id,:q => params[:q], :format => 'js')), :remote => true }
return s + content_tag('div', content_tag('ul', links), :class => 'pagination')
end
def attachments_check_box_tags(name, attachs)
s = ''
attachs.each do |attach|
s << "<label>#{ check_box_tag name, attach.id, false, :id => nil } #{h attach.filename}</label><br/>"
end
s.html_safe
end
# Modified by Longjun
# 有参数的方法要加()
def private_filter(resultSet)
result = resultSet.to_a.dup
# modify by nwb
#添加对课程资源文件的判断
resultSet.map { |res|
if(res.container.nil? ||
(res.container.class.to_s=="Project" && res.container.is_public == false) ||
(res.container.has_attribute?(:project) && res.container.project && res.container.project.is_public == false) ||
(res.container.class.to_s=="HomeworkAttach" && res.container.bid.reward_type == 3) ||
(res.container.class.to_s=="Course" && res.container.is_public == false) ||
(res.container.has_attribute?(:course) && res.container.course && res.container.course.is_public == false)
)
result.delete(res)
end
}
result
end
# Modified by Longjun
# include 应放在class/model 的开始处
# include Redmine::Pagination
# end
def paginateHelper (obj, pre_size=10)
@obj_count = obj.count
@obj_pages = Paginator.new @obj_count, pre_size, params['page']
if obj.kind_of? ActiveRecord::Base or obj.kind_of? ActiveRecord::Relation
obj.limit(@obj_pages.per_page).offset(@obj_pages.offset)
elsif obj.kind_of? Array
obj[@obj_pages.offset, @obj_pages.per_page]
else
logger.error "[ApplicationController] Error : application_controller#paginateHelper ===> unknow category: #{obj.class}"
raise RuntimeError, 'unknow type, Please input you type into this helper.'
end
end
end

@ -38,7 +38,7 @@ module AvatarHelper
avatar_image(source)
else
File.join(relative_path,avatar_directory(source.class),'0')
end
end
end
def get_avatar?(source)

@ -1,184 +0,0 @@
#enconding:utf-8
# fq
module BidsHelper
def render_notes(bid, journal, options={})
content = ''
removable = User.current == journal.user || User.current == bid.author
links = []
if !journal.notes.blank?
links << link_to(image_tag('comment.png'),
{:controller => 'bids', :action => 'new', :id => bid, :journal_id => journal},
:remote => true,
:method => 'post',
:title => l(:button_quote)) if options[:reply_links]
if removable
url = {:controller => 'bids',
:action => 'destroy',
:object_id => journal,
:id => bid}
links << ' '
links << link_to(image_tag('delete.png'), url,
:remote => true, :method => 'delete', :class => "delete", :title => l(:button_delete))
end
end
content << content_tag('div', links.join(' ').html_safe, :class => 'contextual') unless links.empty?
content << textilizable(journal.notes)
css_classes = "wiki"
content_tag('div', content.html_safe, :id => "journal-#{journal.id}-notes", :class => css_classes)
end
def link_to_in_place_notes_editor(text, field_id, url, options={})
onclick = "$.ajax({url: '#{url_for(url)}', type: 'get'}); return false;"
link_to text, '#', options.merge(:onclick => onclick)
end
# this method is used to get all projects that tagged one tag
# added by william
def get_bids_by_tag(tag_name)
Bid.tagged_with(tag_name).order('updated_on desc')
end
#added by huang
def sort_bid_enterprise(state, project_type)
content = ''.html_safe
case state
when 0
content << content_tag('li', link_to(l(:label_sort_by_active), calls_path(:bid_sort_type => '1', :project_type => project_type)))
content << content_tag('li', link_to(l(:label_sort_by_time), calls_path(:bid_sort_type => '0', :project_type => project_type), :class=>"selected"), :class=>"selected")
when 1
content << content_tag('li', link_to(l(:label_sort_by_active), calls_path(:bid_sort_type => '1', :project_type => project_type), :class=>"selected"), :class=>"selected")
content << content_tag('li', link_to(l(:label_sort_by_time), calls_path(:bid_sort_type => '0', :project_type => project_type)))
end
content = content_tag('ul', content)
content_tag('div', content, :class => "tabs_enterprise")
end
#end
def sort_bid(state, project_type)
content = ''.html_safe
case state
when 0
content << content_tag('li', link_to(l(:label_sort_by_active), calls_path(:bid_sort_type => '1', :project_type => project_type)))
content << content_tag('li', link_to(l(:label_sort_by_time), calls_path(:bid_sort_type => '0', :project_type => project_type), :class=>"selected"), :class=>"selected")
when 1
content << content_tag('li', link_to(l(:label_sort_by_active), calls_path(:bid_sort_type => '1', :project_type => project_type), :class=>"selected"), :class=>"selected")
content << content_tag('li', link_to(l(:label_sort_by_time), calls_path(:bid_sort_type => '0', :project_type => project_type)))
end
content = content_tag('ul', content)
content_tag('div', content, :class => "tabs")
end
#huang
def sort_contest(state)
content = ''.html_safe
case state
when 0
content << content_tag('li', link_to(l(:label_sort_by_active), contest_path(:contest_sort_type => '1')))
content << content_tag('li', link_to(l(:label_sort_by_time), contest_path(:contest_sort_type => '0'), :class=>"selected"), :class=>"selected")
when 1
content << content_tag('li', link_to(l(:label_sort_by_active), contest_path(:contest_sort_type => '1'), :class=>"selected"), :class=>"selected")
content << content_tag('li', link_to(l(:label_sort_by_time), contest_path(:contest_sort_type => '0')))
end
content = content_tag('ul', content)
content_tag('div', content, :class => "tabs")
end
#end
def course_options_for_select(courses)
# <option value = '0'>#{l(:label_choose_reward)}</option>
html = ''
courses.each do |course|
html << "<option value = #{course.id}>"
html << course.name
html << "</option>"
end
html.html_safe
end
# used to get the reward and handle the value which can be used to display in views
# added by william
def get_prize(b_project)
b_project.get_reward
end
def count_bid_project
bids = Bid.where('parent_id = ?', @bid.id)
@projects = []
for bid in bids
@projects += bid.biding_projects
end
@projects.count
end
def count_bid_user
bids = Bid.where('parent_id = ?', @bid.id)
@users = []
for bid in bids
for project in bid.projects
@users += project.users
end
end
@users.count
end
# 查看学号
def im_watching_student_id? bid
people = []
people << bid.author
case bid.reward_type # 天煞的bid分了三用途里面各种hasmany还不定能用
when Bid::Enterprise
when Bid::Contest
bid.join_in_contests.each do |jic|
people << jic.user
end
when Bid::Homework
# people += bid.courses.first.users.to_a
people += searchTeacherAndAssistant(bid.courses.first).to_a
else
raise 'bids_helper: unknow bid type' # 出了错看这里!不知道的抛异常,省的找不到出错的地方!
end
people.include?(User.current)
end
# 当前用户是否加入了此课程(包括教师)
def is_cur_course_user? bid
people = []
#people << bid.author
course = bid.courses.first
course.members.each do |member|
people << member.user
end
people.include?(User.current)
end
<<<<<<< HEAD
=======
#当前用户是不是指定课程的学生
def is_cur_course_student? course
people = []
course.members.each do |member|
if [5,10].include? member.roles.first.id
people << member.user
end
end
people.include?(User.current)
end
>>>>>>> 8c33cf0afb89556112710759615cbd88bb0326f2
# def select_option_helper option
# tmp = Hash.new
# option.each do |project|
# tmp[project.name] = project.identifier
# end
# tmp
# end
def can_delete_project_homework bind_project,current_user
current_user.id == bind_project.user.id || current_user.admin
end
end

@ -43,16 +43,16 @@ module ContestsHelper
def sort_contest_enterprise(state, project_type)
content = ''.html_safe
case state
when 0
content << content_tag('li', link_to(l(:label_sort_by_active), calls_path(:contest_sort_type => '1', :project_type => project_type)))
content << content_tag('li', link_to(l(:label_sort_by_time), calls_path(:contest_sort_type => '0', :project_type => project_type), :class=>"selected"), :class=>"selected")
when 1
content << content_tag('li', link_to(l(:label_sort_by_active), calls_path(:contest_sort_type => '1', :project_type => project_type), :class=>"selected"), :class=>"selected")
content << content_tag('li', link_to(l(:label_sort_by_time), calls_path(:contest_sort_type => '0', :project_type => project_type)))
end
content = content_tag('ul', content)
content_tag('div', content, :class => "tabs_enterprise")
when 0
content << content_tag('li', link_to(l(:label_sort_by_active), calls_path(:contest_sort_type => '1', :project_type => project_type)))
content << content_tag('li', link_to(l(:label_sort_by_time), calls_path(:contest_sort_type => '0', :project_type => project_type), :class=>"selected"), :class=>"selected")
when 1
content << content_tag('li', link_to(l(:label_sort_by_active), calls_path(:contest_sort_type => '1', :project_type => project_type), :class=>"selected"), :class=>"selected")
content << content_tag('li', link_to(l(:label_sort_by_time), calls_path(:contest_sort_type => '0', :project_type => project_type)))
end
content = content_tag('ul', content)
content_tag('div', content, :class => "tabs_enterprise")
end
#end
@ -100,7 +100,10 @@ module ContestsHelper
def count_contest_project
contests = Contest.find(:id)
@projects = []
for contest in contests
# Modified by longjun
# for contest in contests
contests.each do |contest|
# end longjun
@projects += contest.contesting_projects
end
@projects.count
@ -109,7 +112,10 @@ module ContestsHelper
def count_contest_softapplication
contests = Contest.find(:id)
@softapplications = []
for contest in contests
# Modified by alan
# for contest in contests
contests.each do |contest|
# end alan
@softapplications += contest.contesting_softapplications
end
@projects.count
@ -119,19 +125,29 @@ module ContestsHelper
def count_contest_user
contests = Contest.find(:id)
@users = []
for contest in contests
for project in contest.projects
# Modified by alan
# for contest in contests
contests.each do |contest|
contest.projects.each do |project|
@users += project.users
end
end
# end alan
@users.count
end
def count_contest_softapplication_user
contests = Contest.find(:id)
@users = []
for contest in contests
for project in contest.softapplications
# Modified by alan
# for contest in contests
contests.each do |contest|
contest.projects.each do |softapplications|
# for project in contest.softapplications
@users += softapplication.users
end
end
@ -173,6 +189,18 @@ module ContestsHelper
end
tmp
end
#作品分类下拉框
def work_type_opttion
type = []
#work_types = WorksCategory.all
WorksCategory.all.each do |work_type|
option = []
option << work_type.category
option << work_type.category
type << option
end
type
end
end

@ -1,391 +1,604 @@
# encoding: utf-8
## This helper be included in applicationHelper
module CoursesHelper
=begin
1. define TeacherRoles, StudentRoles
2. define count function
3. define search by roles
4. define search member function
=end
TeacherRoles = [3, 4, 7, 9]
StudentRoles = [5, 10]
AllPeople = StudentRoles+TeacherRoles
## return people count
# 返回x项目成员数量即roles表中定义的所有成员
def projectCount project
searchCountByRoles project, AllPeople
end
# 返回教师数量即roles表中定义的Manager
def teacherCount project
searchCountByRoles project, TeacherRoles
# or
# searchTeacherAndAssistant(project).count
end
# 返回学生数量即roles表中定义的Reporter
def studentCount project
searchCountByRoles project,StudentRoles
# or
# searchStudent(project).count
end
# 判断用户是否是课程的管理员
# add by nwb
def is_course_manager?(user_id,course_id)
@result = false
@user_id = CourseInfo.find_by_course_id(course_id)
if @user_id == user.id
@result = true
end
return @result
end
# 返回课程设置界面
def course_settings_tabs
tabs = [{:name => 'info', :action => :edit_course, :partial => 'courses/edit', :label => :label_information_plural},
{:name => 'members', :action => :manage_members, :partial => 'courses/settings/members', :label => :label_member_plural}
]
tabs.select { |tab| User.current.allowed_to?(tab[:action], @course) }
end
#是否启动互评下拉框
def is_evaluation_option
type = []
option1 = []
option2 = []
option1 << l(:lable_start_mutual_evaluation)
option1 << 1
option2 << l(:lable_close_mutual_evaluation)
option2 << 2
type << option1
type << option2
end
# garble count 混淆数量
# alias projectCountOrigin projectCount
# def projectCount project
# count = projectCountOrigin project
# garble count
# end
def homework_type_option
type = []
option1 = []
option2 = []
option1 << l(:label_task_submit_form_accessory)
option1 << 1
option2 << l(:label_task_submit_form_project)
option2 << 2
type << option1
type << option2
end
def proportion_option
type = []
i = 0
while i <= 100
option = []
option << i.to_s + "%"
option << i
type << option
i = i + 10
end
type
end
alias teacherCountOrigin teacherCount
def teacherCount project
count = teacherCountOrigin project
garble count
end
alias studentCountOrigin studentCount
def studentCount course
count = studentCountOrigin course
garble count
end
def eventToLanguageCourse event_type, course
case event_type
when "issue-note"
l :label_issue
when "issue"
l :label_issue
when "attachment"
l :label_attachment
when "news"
l :label_notification
else
""
end
end
def garble count
count = count.round( 1-count.to_s.size ).to_i
return count.to_s if count.to_s.size.eql?(1)
count.to_s << '+'
end
# =====================================================================================
# return people list
def searchTeacherAndAssistant project
searchPeopleByRoles(project, TeacherRoles)
end
def searchStudent project
searchPeopleByRoles(project, StudentRoles)
end
# =====================================================================================
def searchCountByRoles project, roles_id
members = searchPeopleByRoles project, roles_id
members.count
end
def searchPeopleByRoles project, roles_id
members = []
begin
members = project.members.joins(:member_roles).where("member_roles.role_id IN (:role_id)", {:role_id => roles_id})
rescue Exception => e
logger.error "[CoursesHelper] ===> #{e}"
end
members
end
def sort_courses(state)
content = ''.html_safe
case state
when 0
content << content_tag('li', link_to(l(:label_sort_by_active), courses_path(:courses_sort_type => '1')))
content << content_tag('li', link_to(l(:label_sort_by_influence), courses_path(:courses_sort_type => '2')))
content << content_tag('li', link_to(l(:label_sort_by_time), courses_path(:courses_sort_type => '0'), :class=>"selected"), :class=>"selected")
when 1
content << content_tag('li', link_to(l(:label_sort_by_active), courses_path(:courses_sort_type => '1'), :class=>"selected"), :class=>"selected")
content << content_tag('li', link_to(l(:label_sort_by_influence), courses_path(:courses_sort_type => '2')))
content << content_tag('li', link_to(l(:label_sort_by_time), courses_path(:courses_sort_type => '0')))
when 2
content << content_tag('li', link_to(l(:label_sort_by_active), courses_path(:courses_sort_type => '1')))
content << content_tag('li', link_to(l(:label_sort_by_influence), courses_path(:courses_sort_type => '2'), :class=>"selected"), :class=>"selected")
content << content_tag('li', link_to(l(:label_sort_by_time), courses_path(:courses_sort_type => '0')))
end
content = content_tag('ul', content)
content_tag('div', content, :class => "tabs")
end
def render_course_hierarchy(courses)
render_course_nested_lists(courses) do |course|
s = link_to_course(course, {}, :class => "#{course.css_classes} #{User.current.member_of?(course) ? 'my-course' : nil}").html_safe
s
end
end
#useless
def searchMembersByRole project, role_id
members = []
begin
members = project.members.joins(:member_roles).where("member_roles.role_id = :role_id", {:role_id => role_id })
rescue Exception => e
logger.error "[CoursesHelper] ===> #{e}"
end
members
end
def sort_course(state, school_id)
content = ''.html_safe
case state
when 0
content << content_tag('li', link_to(l(:label_sort_by_time), courses_path(:course_sort_type => '0'), :school_id => school_id, :class=>"selected"), :class=>"selected")
content << content_tag('li', link_to(l(:label_sort_by_active), courses_path(:course_sort_type => '1', :school_id => school_id)))
content << content_tag('li', link_to(l(:label_sort_by_activity), courses_path(:course_sort_type => '3', :school_id => school_id)))
when 1
content << content_tag('li', link_to(l(:label_sort_by_time), courses_path(:course_sort_type => '0', :school_id => school_id)))
content << content_tag('li', link_to(l(:label_sort_by_active), courses_path(:course_sort_type => '1', :school_id => school_id), :class=>"selected"), :class=>"selected")
content << content_tag('li', link_to(l(:label_sort_by_activity), courses_path(:course_sort_type => '3', :school_id => school_id)))
when 2
content << content_tag('li', link_to(l(:label_sort_by_time), courses_path(:course_sort_type => '0', :school_id => school_id)))
content << content_tag('li', link_to(l(:label_sort_by_active), courses_path(:course_sort_type => '1', :school_id => school_id)))
content << content_tag('li', link_to(l(:label_sort_by_activity), courses_path(:course_sort_type => '3', :school_id => school_id)))
#gcm
when 3
content << content_tag('li', link_to(l(:label_sort_by_time), courses_path(:course_sort_type => '0', :school_id => school_id)))
content << content_tag('li', link_to(l(:label_sort_by_active), courses_path(:course_sort_type => '1', :school_id => school_id)))
content << content_tag('li', link_to(l(:label_sort_by_activity), courses_path(:course_sort_type => '3', :school_id => school_id), :class=>"selected"), :class=>"selected")
end
#gcmend
content = content_tag('ul', content)
content_tag('div', content, :class => "tabs")
end
def findCourseTime project
str = ""
begin
@course = Course.find_by_extra(@project.identifier)
date_format = l(:zh_date)[:formats][:default]
if @course
str = DateTime.parse(@course.setup_time.to_s).strftime("#{date_format}").to_s unless @course.setup_time.blank?
str << '-' unless @course.setup_time.blank?
str << DateTime.parse(@course.endup_time.to_s).strftime("#{date_format}").to_s unless @course.endup_time.blank?
end
rescue Exception => e
logger.error "[CoursesHelper] ===> #{e}"
end
str
end
# added by nwb
def get_course_term course
str = ( course.try(:time).to_s << '.' << course.try(:term).to_s )
str[0..-4]
end
def members_to_user_ids members
people = []
members.each { |member|
people << member.user_id
}
people
end
# 截至到2014-03-17 这个是最终的判断课程是否过期的方法
def course_endTime_timeout? course
end_time_str = course.try(:endup_time)
begin
cTime = Time.parse(end_time_str.to_s)
rescue TypeError,ArgumentError
cTime = Time.parse("3000-01-01")
end
now = Time.now
now > cTime
end
def find_by_extra_from_project extra
Course.find_by_extra(try(extra))
end
#判断制定用户是不是当前课程的老师
def is_course_teacher (user,course)
course.members.joins(:member_roles).where("member_roles.role_id IN (:role_id) and members.user_id = #{user.id}", {:role_id => TeacherRoles}).count != 0
#修改为根据用户是否有发布任务的权限来判断用户是否是课程的老师
#is_teacher = false
#@membership = user.memberships.all(:conditions => Project.visible_condition(User.current))
#@membership.each do |membership|
# unless(membership.project.project_type==0)
# if user.allowed_to?({:controller => "projects", :action => "new_homework"}, membership.project, :global => false)
# is_teacher = true
# end
# end
#end
#is_teacher
end
#当前用户是不是指定课程的学生
def is_cur_course_student course
course.members.joins(:member_roles).where("member_roles.role_id IN (:role_id) and members.user_id = #{User.current.id}", {:role_id => StudentRoles}).count != 0
#修改:能新建占位且不能新建任务的角色判定为学生
#is_student = false
#@membership = User.current.memberships.all(:conditions => Project.visible_condition(User.current))
#@membership.each do |membership|
# unless(membership.project.project_type==0)
# if !User.current.allowed_to?({:controller => "projects", :action => "new_homework"}, membership.project, :global => false) && User.current.allowed_to?({:controller => "homework_attach", :action => "new"}, membership.project, :global => false)
# is_student = true
# end
# end
#end
#is_student
end
#获取当前用户在指定作业下提交的作业的集合
def cur_user_homework_for_bid bid
cur_user_homework = HomeworkAttach.where("user_id = ? and bid_id = ?",User.current,bid.id)
cur_user_homework
end
#判断当前用户对指定作业是否已经评价过
def has_evaluation? homework
seem_count = homework.rates(:quality).where("rater_id = ?",User.current).count
seem_count > 0
end
#获取指定作业的所有成员
def users_for_homework homework
homework.nil? ? [] : (homework.users + [homework.user])
end
#获取指定作业的最终评分
#最终评分 = 学生评分的平均分 * 0.4 +教师评分 * 0.6
def score_for_homework homework
if homework.bid.is_evaluation == 1 || homework.bid.is_evaluation == nil
return format("%.2f",(homework.bid.proportion * 1.0 / 100) * (teacher_score_for_homework(homework).to_f) + (1 - homework.bid.proportion * 1.0 / 100) * (student_score_for_homework(homework).to_f))
else
return teacher_score_for_homework homework
end
end
#获取作业的互评得分
def student_score_for_homework homework
member = searchPeopleByRoles(homework.bid.courses.first,TeacherRoles).first
student_stars = homework.rates(:quality).where("rater_id <> #{member.user_id}").select("stars")
student_stars_count = 0
student_stars.each do |star|
student_stars_count = student_stars_count + star.stars
end
return format("%.2f",student_stars_count / (student_stars.count == 0 ? 1 : student_stars.count))
end
#获取作业的教师评分
def teacher_score_for_homework homework
member = searchPeopleByRoles(homework.bid.courses.first,TeacherRoles).first
teacher_stars = homework.rates(:quality).where("rater_id = #{member.user_id}").select("stars").first
return format("%.2f",teacher_stars == nil ? 0 : teacher_stars.stars)
end
#获取指定项目的得分
def project_score project
issue_count = project.issues.count
issue_journal_count = project.issue_changes.count
issue_score = issue_count * 0.2
issue_journal_score = issue_journal_count * 0.1
finall_issue_score = issue_score + issue_journal_score
new_count = project.news.count
new_score = new_count * 0.1
finall_new_score = new_score
document_count = project.documents.count
file_score = document_count * 0.1
finall_file_score = file_score
changeset_count = project.changesets.count
code_submit_score = changeset_count * 0.3
finall_code_submit_score = code_submit_score
board_message_count = 0
project.boards.each do |board|
board_message_count += board.messages_count
end
topic_score = board_message_count * 0.1
#finall_topic_score = topic_score
finall_project_score = finall_issue_score + finall_new_score + finall_file_score + finall_code_submit_score + topic_score
format("%.2f",finall_project_score)
end
#获取指定作业的参与人员
#返回结果:张三、李四、王五
def homework_user_of_homework homework,is_teacher
homework_users = ""
homework.users.each do |user|
homework_users = homework_users + (is_teacher ? user.realname : user.name)
if user != homework.users.last
homework_users = homework_users + ""
end
end
return homework_users
end
def get_courses_by_tag(tag_name)
Course.tagged_with(tag_name).order('updated_at desc')
end
end
# encoding: utf-8
## This helper be included in applicationHelper
module CoursesHelper
=begin
1. define TeacherRoles, StudentRoles
2. define count function
3. define search by roles
4. define search member function
=end
#TeacherRoles = [3, 4, 7, 9]
#StudentRoles = [5, 10]
#AllPeople = StudentRoles+TeacherRoles
## return people count
# 返回x项目成员数量即roles表中定义的所有成员
def projectCount project
#searchCountByRoles project, AllPeople
project.members.count
end
# 返回教师数量即roles表中定义的Manager
def teacherCount project
searchTeacherAndAssistant(project).count
# or
# searchTeacherAndAssistant(project).count
end
# 返回学生数量即roles表中定义的Reporter
#def studentCount project
# searchStudent(project).count
# or
# searchStudent(project).count
# end
# 判断用户是否是课程的管理员
# add by nwb
def is_course_manager?(user_id,course_id)
@result = false
@user_id = CourseInfo.find_by_course_id(course_id)
if @user_id == user.id
@result = true
end
return @result
end
# 返回课程设置界面
def course_settings_tabs
tabs = [{:name => 'info', :action => :edit_course, :partial => 'courses/edit', :label => :label_information_plural},
{:name => 'members', :action => :manage_members, :partial => 'courses/settings/members', :label => :label_member_plural}
]
tabs.select { |tab| User.current.allowed_to?(tab[:action], @course) }
end
#是否启动互评下拉框
def is_evaluation_option
type = []
option1 = []
option2 = []
option1 << l(:lable_start_mutual_evaluation)
option1 << 1
option2 << l(:lable_close_mutual_evaluation)
option2 << 2
type << option1
type << option2
end
# garble count 混淆数量
# alias projectCountOrigin projectCount
# def projectCount project
# count = projectCountOrigin project
# garble count
# end
def homework_type_option
type = []
option1 = []
option2 = []
option1 << l(:label_task_submit_form_accessory)
option1 << 1
option2 << l(:label_task_submit_form_project)
option2 << 2
type << option1
type << option2
end
def proportion_option
type = []
i = 0
while i <= 100
option = []
option << i.to_s + "%"
option << i
type << option
i = i + 10
end
type
end
#alias teacherCountOrigin teacherCount
#def teacherCount project
# count = teacherCountOrigin project
# garble count
#end
# 注意:此方法有问题,速度慢且结果不准
# alias studentCountOrigin studentCount
#def studentCount course
# count = studentCountOrigin course
#garble count
# end
# 学生人数计算
# add by nwb
def studentCount course
searchStudent(course).count.to_s#course.student.count
end
#课程成员数计算
def memberCount course
count = searchStudent(course).count + searchTeacherAndAssistant(course).count
count.to_s
end
def eventToLanguageCourse event_type, course
case event_type
when "issue-note"
l :label_issue
when "issue"
l :label_issue
when "attachment"
l :label_attachment
when "news"
l :label_notification
else
""
end
end
def garble count
count = count.round( 1-count.to_s.size ).to_i
return count.to_s if count.to_s.size.eql?(1)
count.to_s << '+'
end
# =====================================================================================
# return people list
def searchTeacherAndAssistant project
#searchPeopleByRoles(project, TeacherRoles)
members = []
project.members.each do |m|
members << m if m && m.user && m.user.allowed_to?(:as_teacher,project)
end
members
end
def search_student_in_group(project, course_group_id)
#searchPeopleByRoles(project, StudentRoles)
members = []
project.members.each do |m|
members << m if m && m.user && m.user.allowed_to?(:as_student,project)
end
members
end
def searchStudent project
#searchPeopleByRoles(project, StudentRoles)
members = []
project.members.each do |m|
if m && m.user && m.user.allowed_to?(:as_student,project)
members << m
end
end
members
end
def searchStudent_by_name project, name
#searchPeopleByRoles(project, StudentRoles)
members = []
project.members.each do |m|
if m && m.user && m.user.allowed_to?(:as_student,project)
username = m.user[:lastname].to_s + m.user[:firstname].to_s
if(m.user[:login].to_s.include?(name) || m.user.user_extensions[:student_id].to_s.include?(name) || username.include?(name))
members << m
end
end
end
members
end
def searchmember_by_name members, name
#searchPeopleByRoles(project, StudentRoles)
mems = []
if name != ""
members.each do |m|
username = m.user[:lastname].to_s + m.user[:firstname].to_s
if(m.user[:login].to_s.include?(name) || m.user.user_extensions[:student_id].to_s.include?(name) || username.include?(name))
mems << m
end
end
else
mems = members
end
mems
end
def searchgroupmember_by_name members, name, group
#searchPeopleByRoles(project, StudentRoles)
mems = []
if name != ""
members.each do |m|
if m.course_group_id == group.id
username = m.user[:lastname].to_s + m.user[:firstname].to_s
if(m.user[:login].to_s.include?(name) || m.user.user_extensions[:student_id].to_s.include?(name) || username.include?(name))
mems << m
end
end
end
else
mems = members
end
mems
end
def searchgroupstudent_by_name(group, project, name)
members = []
group.members.each do |m|
if m && m.user && m.user.allowed_to?(:as_student,project)
username = m.user[:lastname].to_s + m.user[:firstname].to_s
if(m.user[:login].to_s.include?(name) || m.user.user_extensions[:student_id].to_s.include?(name) || username.include?(name))
members << m
end
end
end
members
end
def searchStudent_by_group group, project
#searchPeopleByRoles(project, StudentRoles)
members = []
group.members.each do |m|
members << m if m && m.user && m.user.allowed_to?(:as_student,project)
end
members
end
# =====================================================================================
#def searchCountByRoles project, roles_id
# members = searchPeopleByRoles project, roles_id
# members.count
#end
#def searchPeopleByRoles project, roles_id
# members = []
# begin
# members = project.members.joins(:member_roles).where("member_roles.role_id IN (:role_id)", {:role_id => roles_id})
# rescue Exception => e
# logger.error "[CoursesHelper] ===> #{e}"
# end
# members
#end
def sort_courses(state)
content = ''.html_safe
case state
when 0
content << content_tag('li', link_to(l(:label_sort_by_active), courses_path(:courses_sort_type => '1')))
content << content_tag('li', link_to(l(:label_sort_by_influence), courses_path(:courses_sort_type => '2')))
content << content_tag('li', link_to(l(:label_sort_by_time), courses_path(:courses_sort_type => '0'), :class=>"selected"), :class=>"selected")
when 1
content << content_tag('li', link_to(l(:label_sort_by_active), courses_path(:courses_sort_type => '1'), :class=>"selected"), :class=>"selected")
content << content_tag('li', link_to(l(:label_sort_by_influence), courses_path(:courses_sort_type => '2')))
content << content_tag('li', link_to(l(:label_sort_by_time), courses_path(:courses_sort_type => '0')))
when 2
content << content_tag('li', link_to(l(:label_sort_by_active), courses_path(:courses_sort_type => '1')))
content << content_tag('li', link_to(l(:label_sort_by_influence), courses_path(:courses_sort_type => '2'), :class=>"selected"), :class=>"selected")
content << content_tag('li', link_to(l(:label_sort_by_time), courses_path(:courses_sort_type => '0')))
end
content = content_tag('ul', content)
content_tag('div', content, :class => "tabs")
end
def render_course_hierarchy(courses)
render_course_nested_lists(courses) do |course|
s = link_to_course(course, {}, :class => "#{course.css_classes} #{User.current.member_of_course?(course) ? 'my-course' : nil}").html_safe
s
end
end
#useless
#def searchMembersByRole project, role_id
# members = []
# begin
# members = project.members.joins(:member_roles).where("member_roles.role_id = :role_id", {:role_id => role_id })
# rescue Exception => e
# logger.error "[CoursesHelper] ===> #{e}"
# end
# members
#end
def sort_course(state, school_id)
content = ''.html_safe
case state
when 0
content << content_tag('li', link_to(l(:label_sort_by_time), courses_path(:course_sort_type => '0'), :school_id => school_id, :class=>"selected"), :class=>"selected")
content << content_tag('li', link_to(l(:label_sort_by_active), courses_path(:course_sort_type => '1', :school_id => school_id)))
content << content_tag('li', link_to(l(:label_sort_by_activity), courses_path(:course_sort_type => '3', :school_id => school_id)))
when 1
content << content_tag('li', link_to(l(:label_sort_by_time), courses_path(:course_sort_type => '0', :school_id => school_id)))
content << content_tag('li', link_to(l(:label_sort_by_active), courses_path(:course_sort_type => '1', :school_id => school_id), :class=>"selected"), :class=>"selected")
content << content_tag('li', link_to(l(:label_sort_by_activity), courses_path(:course_sort_type => '3', :school_id => school_id)))
when 2
content << content_tag('li', link_to(l(:label_sort_by_time), courses_path(:course_sort_type => '0', :school_id => school_id)))
content << content_tag('li', link_to(l(:label_sort_by_active), courses_path(:course_sort_type => '1', :school_id => school_id)))
content << content_tag('li', link_to(l(:label_sort_by_activity), courses_path(:course_sort_type => '3', :school_id => school_id)))
#gcm
when 3
content << content_tag('li', link_to(l(:label_sort_by_time), courses_path(:course_sort_type => '0', :school_id => school_id)))
content << content_tag('li', link_to(l(:label_sort_by_active), courses_path(:course_sort_type => '1', :school_id => school_id)))
content << content_tag('li', link_to(l(:label_sort_by_activity), courses_path(:course_sort_type => '3', :school_id => school_id), :class=>"selected"), :class=>"selected")
end
#gcmend
content = content_tag('ul', content)
content_tag('div', content, :class => "tabs")
end
def findCourseTime project
str = ""
begin
@course = Course.find_by_extra(@project.identifier)
date_format = l(:zh_date)[:formats][:default]
if @course
str = DateTime.parse(@course.setup_time.to_s).strftime("#{date_format}").to_s unless @course.setup_time.blank?
str << '-' unless @course.setup_time.blank?
str << DateTime.parse(@course.endup_time.to_s).strftime("#{date_format}").to_s unless @course.endup_time.blank?
end
rescue Exception => e
logger.error "[CoursesHelper] ===> #{e}"
end
str
end
# added by nwb
def get_course_term course
str = ( course.try(:time).to_s << '.' << course.try(:term).to_s )
str[0..-4]
end
def members_to_user_ids members
people = []
members.each { |member|
people << member.user_id
}
people
end
# 截至到2014-03-17 这个是最终的判断课程是否过期的方法
def course_endTime_timeout? course
end_time_str = course.try(:endup_time)
begin
cTime = Time.parse(end_time_str.to_s)
rescue TypeError,ArgumentError
cTime = Time.parse("3000-01-01")
end
now = Time.now
now > cTime
end
def find_by_extra_from_project extra
Course.find_by_extra(try(extra))
end
#判断指定用户是不是当前课程的老师
def is_course_teacher (user,course)
#course.members.joins(:member_roles).where("member_roles.role_id IN (:role_id) and members.user_id = #{user.id}", {:role_id => TeacherRoles}).count != 0
user.allowed_to?(:as_teacher,course)
#修改为根据用户是否有发布任务的权限来判断用户是否是课程的老师
#is_teacher = false
#@membership = user.memberships.all(:conditions => Project.visible_condition(User.current))
#@membership.each do |membership|
# unless(membership.project.project_type==0)
# if user.allowed_to?({:controller => "projects", :action => "new_homework"}, membership.project, :global => false)
# is_teacher = true
# end
# end
#end
#is_teacher
end
#当前用户是不是指定课程的学生
def is_cur_course_student course
#course.members.joins(:member_roles).where("member_roles.role_id IN (:role_id) and members.user_id = #{User.current.id}", {:role_id => StudentRoles}).count != 0
User.current.logged? && User.current.member_of_course?(course) && !(User.current.allowed_to?(:as_teacher,course))
#修改:能新建占位且不能新建任务的角色判定为学生
#is_student = false
#@membership = User.current.memberships.all(:conditions => Project.visible_condition(User.current))
#@membership.each do |membership|
# unless(membership.project.project_type==0)
# if !User.current.allowed_to?({:controller => "projects", :action => "new_homework"}, membership.project, :global => false) && User.current.allowed_to?({:controller => "homework_attach", :action => "new"}, membership.project, :global => false)
# is_student = true
# end
# end
#end
#is_student
end
#获取当前用户在指定作业下提交的作业的集合
def cur_user_homework_for_bid bid
bid.homeworks.where("user_id = ?",User.current)
end
#判断当前用户对指定作业是否已经评价过
def has_evaluation? homework
seem_count = homework.rates(:quality).where("rater_id = ?",User.current).count
seem_count > 0
end
#获取指定作业的所有成员
def users_for_homework homework
homework.nil? ? [] : (homework.users + [homework.user])
end
#获取指定作业的最终评分
#最终评分 = 学生评分的平均分 * 0.4 +教师评分 * 0.6
def score_for_homework homework
if homework.bid.is_evaluation == 1 || homework.bid.is_evaluation == nil
return format("%.2f",(homework.bid.proportion * 1.0 / 100) * (teacher_score_for_homework(homework).to_f) + (1 - homework.bid.proportion * 1.0 / 100) * (student_score_for_homework(homework).to_f))
else
return teacher_score_for_homework homework
end
end
def score_for_homework_new homework
if teacher_score_for_homework(homework) != 0
return teacher_score_for_homework homework
else
return student_score_for_homework homework
end
end
#获取作业的互评得分
def student_score_for_homework homework
#member = searchTeacherAndAssistant(homework.bid.courses.first).first#searchPeopleByRoles(homework.bid.courses.first,TeacherRoles).first
#if member.nil?
# return "0.00"
#end
#student_stars = homework.rates(:quality).where("rater_id <> #{member.user_id}").select("stars")
members = searchStudent(homework.bid.courses.first)
user_ids = []
members.each do |user|
user_ids << user.user_id
end
student_stars = homework.rates(:quality).where("rater_id in (:user_ids)",{:user_ids => user_ids}).select("stars")
student_stars_count = 0
student_stars.each do |star|
student_stars_count = student_stars_count + star.stars
end
return format("%.2f",student_stars_count / (student_stars.count == 0 ? 1 : student_stars.count))
end
#获取作业的教师评分
#多个教师只获取一份教师评分
def teacher_score_for_homework homework
members = searchTeacherAndAssistant(homework.bid.courses.first)
teacher_ids = []
members.each do |user|
teacher_ids << user.user_id
end
teacher_stars = homework.rates(:quality).where("rater_id in (:teacher_ids)",{:teacher_ids => teacher_ids}).select("stars")
teacher_stars_count = 0
teacher_stars.each do |star|
teacher_stars_count = teacher_stars_count + star.stars
end
return format("%.2f",teacher_stars.count > 0 ? teacher_stars_count/teacher_stars.count : 0)
end
#获取指定项目的得分
def project_score project
issue_count = project.issues.count
issue_journal_count = project.issue_changes.count
issue_score = issue_count * 0.2
issue_journal_score = issue_journal_count * 0.1
finall_issue_score = issue_score + issue_journal_score
new_count = project.news.count
new_score = new_count * 0.1
finall_new_score = new_score
document_count = project.documents.count
file_score = document_count * 0.1
finall_file_score = file_score
changeset_count = project.changesets.count
code_submit_score = changeset_count * 0.3
finall_code_submit_score = code_submit_score
board_message_count = 0
project.boards.each do |board|
board_message_count += board.messages_count
end
topic_score = board_message_count * 0.1
#finall_topic_score = topic_score
finall_project_score = finall_issue_score + finall_new_score + finall_file_score + finall_code_submit_score + topic_score
format("%.2f",finall_project_score)
end
#获取指定作业的参与人员
#返回结果:张三、李四、王五
def homework_user_of_homework homework,is_teacher
homework_users = ""
homework.users.each do |user|
homework_users = homework_users + (is_teacher ? (user.lastname + user.firstname) : user.login)
if user != homework.users.last
homework_users = homework_users + ""
end
end
return homework_users
end
def get_courses_by_tag(tag_name)
Course.tagged_with(tag_name).order('updated_at desc')
end
#课程实践年份下拉框
def course_time_option year
type = []
now_year = year.nil? ? Time.now.year : (Time.now.year <= year ? Time.now.year : year)
for i in (now_year..now_year + 10)
option = []
option << i
option << i
type << option
end
type
end
#课程课时下拉框
def course_term_option
type = []
option1 = []
option1 << l(:label_spring)
option1 << l(:label_spring)
option2 = []
option2 << l(:label_autumn)
option2 << l(:label_autumn)
type << option1
type << option2
type
end
def cur_course_term
month = Time.now.month
if month >= 9 || month < 3
term = "秋季学期"
else
term = "春季学期"
end
term
end
def course_in_current_or_next_term course
is_current_term = false
is_next_term = false
if course.time == Time.now.year && course.term == cur_course_term
is_current_term = true
end
if cur_course_term == "秋季学期" && course.time == (Time.now.year + 1) && course.term == "春季学期"
is_next_term = true
elsif cur_course_term == "春季学期" && course.time == Time.now.year && course.term == "秋季学期"
is_next_term = true
end
is_current_term || is_next_term
end
#获取课程动态
def get_course_activity courses, activities
@course_ids=activities.keys()
days = Setting.activity_days_default.to_i
date_to ||= Date.today + 1
date_from = date_to - days-1.years
#file_count
Attachment.where(container_id: @course_ids, container_type: Course).where("created_on>?", date_from).each do |attachment|
activities[attachment.container_id]+=1
end
#message_count
Board.where(course_id: @course_ids).each do |board|
# activities[board.course_id]+=1
activities[board.course_id]+=board.messages.where("updated_on>?", date_from).count
end
#news
News.where(course_id: @course_ids).where("created_on>?",date_from).each do |news|
activities[news.course_id]+=1
end
# 动态数 + 1 ( 某某创建了该课程 )
activities.each_pair { |key, value| activities[key] = value + 1 }
return activities
end
end

@ -1,5 +1,6 @@
# encoding: utf-8
module FilesHelper
include AttachmentsHelper
def downloadAll containers
paths = []
@ -44,6 +45,27 @@ module FilesHelper
File.new(zipfile_name,'w+')
end
def courses_check_box_tags(name,courses,current_course,attachment)
s = ''
courses.each do |course|
if !(attachment.container_type && attachment.container_id == course.id) && is_course_teacher(User.current,course) && course_in_current_or_next_term(course)
s << "<label>#{ check_box_tag name, course.id, false, :id => nil } #{h course.name}</label>&nbsp;[#{get_course_term course}]<br/>"
end
end
s.html_safe
end
#判断用户是否拥有不包含当前资源的课程,需用户在该课程中角色为教师且该课程属于当前学期或下一学期
def has_course? user,file
result = false
user.courses.each do |course|
if !course_contains_attachment?(course,file) && is_course_teacher(User.current,course) && course_in_current_or_next_term(course)
return true
end
end
result
end
# 判断指定的资源时候符合类型
def isTypeOk(attachment, type, contentType)
result = false
@ -62,5 +84,71 @@ module FilesHelper
result
end
def visable_attachemnts attachments
result = []
attachments.each do |attachment|
if attachment.is_public? || (attachment.container_type == "Course" && User.current.member_of_course?(Course.find(attachment.container_id)))|| attachment.author_id == User.current.id
result << attachment
end
end
result
end
def visable_attachemnts_incourse attachments
result = []
attachments.each do |attachment|
if attachment.is_public? || (attachment.author.member_of_course?(Course.find(attachment.container_id)))|| attachment.author_id == User.current.id
result << attachment
end
end
result
end
def visable_attachemnts_insite attachments,course
result = []
attachments.each do |attachment|
if attachment.is_public? || (attachment.container_type == "Course" && attachment.container_id == course.id && User.current.member_of_course?(Course.find(attachment.container_id)))|| attachment.author_id == User.current.id
result << attachment
end
end
result
end
def attachment_candown attachment
candown = false
if attachment.container
if attachment.container.class.to_s != "HomeworkAttach" && (attachment.container.has_attribute?(:project) || attachment.container.has_attribute?(:project_id)) && attachment.container.project
project = attachment.container.project
candown= User.current.member_of?(project) || (project.is_public && attachment.is_public == 1)
elsif attachment.container.is_a?(Project)
project = attachment.container
candown= User.current.member_of?(project) || (project.is_public && attachment.is_public == 1)
elsif (attachment.container.has_attribute?(:board) || attachment.container.has_attribute?(:board_id)) && attachment.container.board &&
attachment.container.board.project
project = attachment.container.board.project
candown = User.current.member_of?(project) || (project.is_public && attachment.is_public == 1)
elsif (attachment.container.has_attribute?(:course) ||attachment.container.has_attribute?(:course_id) ) && attachment.container.course
course = attachment.container.course
candown = User.current.member_of_course?(course) || (course.is_public==1 && attachment.is_public == 1)
elsif attachment.container.is_a?(Course)
course = attachment.container
candown= User.current.member_of_course?(course) || (course.is_public==1 && attachment.is_public == 1)
elsif (attachment.container.has_attribute?(:board) || attachment.container.has_attribute?(:board_id)) && attachment.container.board &&
attachment.container.board.course
course = attachment.container.board.course
candown= User.current.member_of_course?(course) || (course.is_public==1 && attachment.is_public == 1)
elsif attachment.container.class.to_s=="HomeworkAttach" && attachment.container.bid.reward_type == 3
candown = true
elsif attachment.container_type == "Bid" && attachment.container && attachment.container.courses
course = attachment.container.courses.first
candown = User.current.member_of_course?(attachment.container.courses.first) || (course.is_public == 1 && attachment.is_public == 1)
else
candown = (attachment.is_public == 1 || attachment.is_public == true)
end
end
candown
end
end

@ -0,0 +1,247 @@
# Gitlab5.3 API操作接口
# Add by nwb
# 暂时没支持SSH
# 接口通过HTTP协议与服务器交互理论上只要能安装gitlab的操作系统本接口都能支持
# 本机的测试环境是Ubuntu 12.04
module GitlabHelper
# gitlab版本库数据本地保存的根目录
ROOT_PATH="/home/git/repositories/"
PROJECT_PATH_CUT = 40
# gitlab版本库所在服务器
# 注意REPO_IP_ADDRESS必须以http://开头暂时只支持HTTP协议未支持SSH
#REPO_IP_ADDRESS = "http://" + Setting.repository_domain
REPO_IP_ADDRESS = "http://192.168.137.100"
GITLAB_API = "/api/v3"
# 用户在项目中的权限级别
GUEST = 10
REPORTER = 20
DEVELOPER = 30
MASTER = 40
# gitlab的登录验证信息
# add by nwb
def self.gitlab_token=(token)
Thread.current[:gitlab_token] = token
end
# gitlab的登录验证信息
# add by nwb
def self.gitlab_token
Thread.current[:gitlab_token] ||= nil
end
# 登录gitlab
# add by nwb
def login_gitlab(email,password)
url = REPO_IP_ADDRESS + GITLAB_API + "/session"
uri = URI.parse(url)
data = {email:email, password:password}
begin
res = Net::HTTP.post_form(uri, data)
if res.code == '201'
temp = ActiveSupport::JSON.decode(res.body)
GitlabHelper.gitlab_token= temp['private_token']
return true
else
return false
end
rescue =>err
return false
end
end
# 创建项目
# add by nwb
def create_project(project_name)
url = REPO_IP_ADDRESS + GITLAB_API + "/projects"
uri = URI.parse(url)
data = {name:project_name, private_token:GitlabHelper.gitlab_token}
begin
res = Net::HTTP.post_form(uri, data)
if res.code == '201'
temp = ActiveSupport::JSON.decode(res.body)
#新创建项目的版本库地址
respo = temp['http_url_to_repo']
respo['http://localhost'] = REPO_IP_ADDRESS
# 新创建项目的web地址
webaddress = temp['web_url']
webaddress['http://localhost'] = REPO_IP_ADDRESS
return true
else
return false
end
rescue =>err
return false
end
end
# 为指定用户创建版本库
# project_name版本库名称 user_id:Gitlab版本库中的用户编号
# add by nwb
def create_project_for_user(project_name,user_id)
url = REPO_IP_ADDRESS + GITLAB_API + "/projects/user/" + user_id
uri = URI.parse(url)
data = {user_id:user_id, name:project_name,private_token:GitlabHelper.gitlab_token}
begin
res = Net::HTTP.post_form(uri, data)
if res.code == '201'
temp = ActiveSupport::JSON.decode(res.body)
#新创建项目的版本库地址
respo = temp['http_url_to_repo']
respo['http://localhost'] = REPO_IP_ADDRESS
# 新创建项目的web地址
webaddress = temp['web_url']
webaddress['http://localhost'] = REPO_IP_ADDRESS
return true
else
return false
end
rescue =>err
return false
end
end
# 创建用户
# loginname登录名称(版本库路径包含) name用户姓名
# add by nwb
def create_user (loginname,name,password,email)
url = REPO_IP_ADDRESS + GITLAB_API + "/users"
uri = URI.parse(url)
data = {email:email,password:password,username:loginname, name:name, private_token:GitlabHelper.gitlab_token}
begin
res = Net::HTTP.post_form(uri, data)
if res.code == '201'
temp = ActiveSupport::JSON.decode(res.body)
#新创建的gitlab用户编号(需保存)
user_id = temp['id']
return true
else
return false
end
rescue =>err
return false
end
end
# 删除用户
# user_id:用户在gitlab中的id
# add by nwb
def delete_user(user_id)
url = REPO_IP_ADDRESS + GITLAB_API + "/users/" + user_id
uri = URI.parse(url)
data = {id:user_id,private_token:GitlabHelper.gitlab_token}
http = Net::HTTP.new uri.host, uri.port
begin
req = Net::HTTP::Delete.new(uri.request_uri)
req.form_data = data
res= http.start { |http| http.request req }
if res.code == '200'
temp = ActiveSupport::JSON.decode(res.body)
# 删除成功对应更新trustie用户的gitlab用户编号
return true
else
return false
end
rescue =>err
return false
end
end
# 给用户添加一个可操作的项目
# 若用户已在该项目中,权限级别取新权限与现有权限的最大值
# project_id:项目在gitlab中的id user_id:用户在gitlab中的id
# access_level为用户在项目中的权限级别对应如下
#GUEST = 10
#REPORTER = 20
#DEVELOPER = 30
#MASTER = 40
# add by nwb
def add_user_to_project(project_id,user_id,access_level)
url = REPO_IP_ADDRESS + GITLAB_API + "/projects/" + project_id +"/members"
uri = URI.parse(url)
data = {id:project_id,user_id:user_id,access_level:access_level, private_token:GitlabHelper.gitlab_token}
begin
res = Net::HTTP.post_form(uri, data)
if res.code == '201'
temp = ActiveSupport::JSON.decode(res.body)
return true
else
return false
end
rescue =>err
return false
end
end
# 从项目中删除用户
# project_id:项目在gitlab中的ids user_id:用户在gitlab中的id
# add by nwb
def delete_user_from_project(project_id,user_id)
url = REPO_IP_ADDRESS + GITLAB_API + "/projects/" + project_id +"/members/" + user_id
uri = URI.parse(url)
data = {id:project_id,user_id:user_id,private_token:GitlabHelper.gitlab_token}
http = Net::HTTP.new uri.host, uri.port
begin
req = Net::HTTP::Delete.new(uri.request_uri)
req.form_data = data
res= http.start { |http| http.request req }
if res.code == '200'
temp = ActiveSupport::JSON.decode(res.body)
return true
else
return false
end
rescue =>err
return false
end
end
# 发送post消息
# add by nwb
def post(url, params)
uri = URI.parse(url)
http = Net::HTTP.new(uri.host, uri.port)
if uri.scheme == 'https'
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
http.use_ssl = true
end
begin
request = Net::HTTP::Post.new(uri.request_uri)
request['Content-Type'] = 'application/json;charset=utf-8'
request['User-Agent'] = 'Mozilla/5.0 (Windows NT 5.1; rv:29.0) Gecko/20100101 Firefox/29.0'
request['X-ACL-TOKEN'] = 'xxx_token'
#request.set_form_data(params)
request.body = params.to_json
response = http.start { |http| http.request(request) }
return JSON.parse response.body
rescue =>err
return nil
end
end
# 发送get消息
# add by nwb
def get(url, params)
uri = URI.parse(url)
uri.query = URI.encode_www_form(params)
http = Net::HTTP.new uri.host, uri.port
if uri.scheme == 'https'
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
http.use_ssl = true
end
begin
request = Net::HTTP::Get.new uri.request_uri
request['Content-Type'] = 'application/json;charset=utf-8'
request['User-Agent'] = 'Mozilla/5.0 (Windows NT 5.1; rv:29.0) Gecko/20100101 Firefox/29.0'
request['X-ACL-TOKEN'] = 'xxx_token'
response = http.start { |http| http.request request }
return JSON.parse response.body
rescue =>err
return nil
end
end
end

@ -60,7 +60,7 @@ module HomeworkAttachHelper
memberships = User.current.memberships.all(:conditions => cond)
projects = memberships.map(&:project)
not_have_project = []
not_have_project << "<<NULL>>"
not_have_project << Setting.please_chose
not_have_project << 0
type = []
type << not_have_project
@ -74,4 +74,49 @@ module HomeworkAttachHelper
end
type
end
#判断指定用户是不是已经赞过该作业
def is_praise_homework user_id, obj_id
PraiseTread.where("user_id = #{user_id} AND praise_tread_object_id = #{obj_id} AND praise_tread_object_type = 'HomeworkAttach'").empty?
end
#获取赞的总数
def praise_homework_count obj_id
PraiseTread.where("praise_tread_object_id = #{obj_id} AND praise_tread_object_type = 'HomeworkAttach'").count
end
#获取用户对作业的评分
def get_homework_score user, homework
temp = HomeworkAttach.find_by_sql("SELECT stars FROM seems_rateable_rates WHERE rateable_type = 'HomeworkAttach' AND rateable_id = #{homework.id} AND rater_id = #{user.id}").first
@m_score = temp.nil? ? 0:temp.stars.to_i
end
#获取评分对应的评论
def get_homework_review homework,is_teacher,user
homework.journals_for_messages.where("is_comprehensive_evaluation = #{is_teacher ? 1 : 2} and user_id = #{user.id}").order("created_on DESC").first
end
def convert_array array
ary = "("
if array.nil? || array.count == 0
return "()"
end
array.length.times do |i|
if i == array.length - 1
ary += array[i].id.to_s + ")"
else
if !(array[i].nil? || array[i].id.nil? || array[i].id.to_s == "")
ary += array[i].id.to_s + ","
end
end
end
#array.each do |member|
# if member == array.last
# ary += member.id.to_s + ")"
# else
# ary += member.id.to_s + ","
# end
#end
ary
end
end

@ -73,7 +73,7 @@ module IssuesHelper
ancestors.each do |ancestor|
s << '<div>' + content_tag('p', link_to_issue(ancestor, :project => (issue.project_id != ancestor.project_id)))
end
s << '<div>'
s << '<div style="word-wrap: break-word; word-break: normal;">'
subject = h(issue.subject)
if issue.is_private?
subject = content_tag('span', l(:field_is_private), :class => 'private') + ' ' + subject
@ -227,6 +227,7 @@ module IssuesHelper
strings = []
values_by_field = {}
details.each do |detail|
if detail.property == 'cf'
field_id = detail.prop_key
field = CustomField.find_by_id(field_id)
@ -242,6 +243,7 @@ module IssuesHelper
end
end
strings << show_detail(detail, no_html, options)
end
values_by_field.each do |field_id, changes|
detail = JournalDetail.new(:property => 'cf', :prop_key => field_id)
@ -326,7 +328,7 @@ module IssuesHelper
if detail.property == 'attr' && detail.prop_key == 'description'
s = l(:text_journal_changed_no_detail, :label => label)
unless no_html
diff_link = link_to 'diff',
diff_link = link_to l(:label_diff),
{:controller => 'journals', :action => 'diff', :id => detail.journal_id,
:detail_id => detail.id, :only_path => options[:only_path]},
:title => l(:label_view_diff)

@ -0,0 +1,27 @@
module LoggerHelper
#输出日志
def OutLogger
#日志输出级别
#Rails.logger.level = Logger::INFO
if(!File.exist?("database"))
Dir.mkdir("database")
end
if(!File.exist?("database/get"))
Dir.mkdir("database/get")
end
if(!File.exist?("database/sql"))
Dir.mkdir("database/sql")
end
if(!File.exist?("database/controller"))
Dir.mkdir("database/controller")
end
Rails.logger = Logger.new("database/get/#{Date.today.to_s}.log", "daily")
ActiveRecord::Base.logger = Logger.new("database/sql/#{Date.today.to_s}.log", "daily")
ActionController::Base.logger = Logger.new("database/controller/#{Date.today.to_s}.log", "daily")
end
end

@ -31,6 +31,7 @@ module MembersHelper
}
s + content_tag('div', content_tag('ul', links), :class => 'pagination_new')
end
# add by nwb
@ -53,10 +54,13 @@ module MembersHelper
# 当前申请加入的成员名单
def render_principals_for_applied_members(project)
scope = Principal.active.sorted.applied_members(project).like(params[:q])
scope = project.applied_projects.map(&:user)
principal_count = scope.count
principal_pages = Redmine::Pagination::Paginator.new principal_count, 10, params['page']
principals = scope.offset(principal_pages.offset).limit(principal_pages.per_page).all
offset ||= principal_pages.offset
principals = scope[offset, 10]
#principals = scope.offset(principal_pages.offset).limit(principal_pages.per_page).all
#principals = ApplicationController.new.paginateHelper scope,10
s = content_tag('div', principals_check_box_tags_ex('membership[user_ids][]', principals), :id => 'principals')

@ -0,0 +1,122 @@
# encoding: utf-8
module ProjectScoreHelper
#缺陷数量
def issue_num project
project.issues.count
end
#缺陷留言数量
def issue_journal_num project
project.issue_changes.count
end
#新闻数量
def news_num project
project.news.count
end
#文档数量
def documents_num project
project.documents.count
end
#代码提交数量
def changesets_num project
project.changesets.count
end
#讨论区帖子数量
def board_message_num project
board_message_count = 0
project.boards.each do |board|
board_message_count += board.messages_count
end
board_message_count
end
#缺陷得分
def issue_score project
i_num = issue_num project
i_j_num = issue_journal_num project
i_num * 4 + i_j_num
end
# 新闻得分
def news_score project
n_num = news_num project
n_num
end
#文档得分
def documents_score project
d_num = documents_num(project)
d_num * 4
end
#代码提交得分
def changesets_score project
c_num = changesets_num project
c_num * 4
end
#讨论区帖子得分
def board_message_score project
b_m_num = board_message_num project
b_m_num * 2
end
#计算项目得分
def project_scores project
result = (issue_score project) + (news_score project) + (documents_score project) + (changesets_score project) + (board_message_score project)
pss = ProjectScore.where("project_id = '#{project.id}'")
if pss.nil? || pss.count == 0
ps = ProjectScore.new
ps.issue_num = issue_num(project)
ps.board_message_num = board_message_num(project)
ps.changeset_num = changesets_num(project)
ps.documents_num = documents_num(project)
ps.issue_journal_num = issue_journal_num(project)
ps.news_num = news_num(project)
ps.score = result
ps.project = project
ps.save
else
ps = pss.first
ps.issue_num = issue_num(project)
ps.board_message_num = board_message_num(project)
ps.changeset_num = changesets_num(project)
ps.documents_num = documents_num(project)
ps.issue_journal_num = issue_journal_num(project)
ps.news_num = news_num(project)
ps.score = result
ps.save
end
result
end
#读取项目得分
def red_project_scores project
grade = 0
pss = ProjectScore.where("project_id = '#{project.id}'")
if pss.nil? || pss.count == 0
grade
else
ps = pss.first
grade = ps.score
grade
end
end
def get_project_score project
pss = ProjectScore.where("project_id = '#{project.id}'")
ps = nil
if pss.nil? || pss.count == 0
ps = nil
else
ps = pss.first
end
ps
end
end

@ -1,342 +1,378 @@
# encoding: utf-8
#
# Redmine - project management software
# Copyright (C) 2006-2013 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.
include AvatarHelper
module ProjectsHelper
def link_to_version(version, options = {})
return '' unless version && version.is_a?(Version)
link_to_if version.visible?, format_version_name(version), { :controller => 'versions', :action => 'show', :id => version }, options
end
def project_settings_tabs
tabs = [{:name => 'info', :action => :edit_project, :partial => 'projects/edit', :label => :label_information_plural},
{:name => 'modules', :action => :select_project_modules, :partial => 'projects/settings/modules', :label => :label_module_plural},
{:name => 'members', :action => :manage_members, :partial => 'projects/settings/members', :label => :label_member_plural},
{:name => 'versions', :action => :manage_versions, :partial => 'projects/settings/versions', :label => :label_version_plural},
{:name => 'categories', :action => :manage_categories, :partial => 'projects/settings/issue_categories', :label => :label_issue_category_plural},
# {:name => 'wiki', :action => :manage_wiki, :partial => 'projects/settings/wiki', :label => :label_wiki},
{:name => 'repositories', :action => :manage_repository, :partial => 'projects/settings/repositories', :label => :label_repository_plural},
#{:name => 'boards', :action => :manage_boards, :partial => 'projects/settings/boards', :label => :label_board_plural},
{:name => 'activities', :action => :manage_project_activities, :partial => 'projects/settings/activities', :label => :enumeration_activities}
]
tabs.select {|tab| User.current.allowed_to?(tab[:action], @project)}
end
# added bu huang
def sort_project_enterprise(state, project_type)
content = ''.html_safe
case state
when 0
content << content_tag('li', link_to(l(:label_sort_by_active), projects_path(:project_sort_type => '1', :project_type => project_type)))
content << content_tag('li', link_to(l(:label_sort_by_influence), projects_path(:project_sort_type => '2', :project_type => project_type)))
content << content_tag('li', link_to(l(:label_sort_by_time), projects_path(:project_sort_type => '0', :project_type => project_type), :class=>"selected"), :class=>"selected")
when 1
content << content_tag('li', link_to(l(:label_sort_by_active), projects_path(:project_sort_type => '1', :project_type => project_type), :class=>"selected"), :class=>"selected")
content << content_tag('li', link_to(l(:label_sort_by_influence), projects_path(:project_sort_type => '2', :project_type => project_type)))
content << content_tag('li', link_to(l(:label_sort_by_time), projects_path(:project_sort_type => '0', :project_type => project_type)))
when 2
content << content_tag('li', link_to(l(:label_sort_by_active), projects_path(:project_sort_type => '1', :project_type => project_type)))
content << content_tag('li', link_to(l(:label_sort_by_influence), projects_path(:project_sort_type => '2', :project_type => project_type), :class=>"selected"), :class=>"selected")
content << content_tag('li', link_to(l(:label_sort_by_time), projects_path(:project_sort_type => '0', :project_type => project_type)))
end
content = content_tag('ul', content)
content_tag('div', content, :class => "tabs_enterprise")
end
def sort_course(state, project_type, school_id)
content = ''.html_safe
case state
when 0
content << content_tag('li', link_to(l(:label_sort_by_time), course_path(:project_sort_type => '0', :project_type => project_type), :school_id => school_id, :class=>"selected"), :class=>"selected")
content << content_tag('li', link_to(l(:label_sort_by_active), course_path(:project_sort_type => '1', :project_type => project_type, :school_id => school_id)))
# content << content_tag('li', link_to(l(:label_sort_by_influence), course_path(:project_sort_type => '2', :project_type => project_type)))
content << content_tag('li', link_to(l(:label_sort_by_activity), course_path(:project_sort_type => '3', :project_type => project_type, :school_id => school_id)))
when 1
content << content_tag('li', link_to(l(:label_sort_by_time), course_path(:project_sort_type => '0', :project_type => project_type, :school_id => school_id)))
content << content_tag('li', link_to(l(:label_sort_by_active), course_path(:project_sort_type => '1', :project_type => project_type, :school_id => school_id), :class=>"selected"), :class=>"selected")
# content << content_tag('li', link_to(l(:label_sort_by_influence), course_path(:project_sort_type => '2', :project_type => project_type)))
content << content_tag('li', link_to(l(:label_sort_by_activity), course_path(:project_sort_type => '3', :project_type => project_type, :school_id => school_id)))
when 2
content << content_tag('li', link_to(l(:label_sort_by_time), course_path(:project_sort_type => '0', :project_type => project_type, :school_id => school_id)))
content << content_tag('li', link_to(l(:label_sort_by_active), course_path(:project_sort_type => '1', :project_type => project_type, :school_id => school_id)))
# content << content_tag('li', link_to(l(:label_sort_by_influence), course_path(:project_sort_type => '2', :project_type => project_type), :class=>"selected"), :class=>"selected")
content << content_tag('li', link_to(l(:label_sort_by_activity), course_path(:project_sort_type => '3', :project_type => project_type, :school_id => school_id)))
#gcm
when 3
content << content_tag('li', link_to(l(:label_sort_by_time), course_path(:project_sort_type => '0', :project_type => project_type, :school_id => school_id)))
content << content_tag('li', link_to(l(:label_sort_by_active), course_path(:project_sort_type => '1', :project_type => project_type, :school_id => school_id)))
# content << content_tag('li', link_to(l(:label_sort_by_influence), course_path(:project_sort_type => '2', :project_type => project_type)))
content << content_tag('li', link_to(l(:label_sort_by_activity), course_path(:project_sort_type => '3', :project_type => project_type, :school_id => school_id), :class=>"selected"), :class=>"selected")
end
#gcmend
content = content_tag('ul', content)
content_tag('div', content, :class => "tabs")
end
# end
def sort_project(state, project_type)
content = ''.html_safe
case state
when 0
content << content_tag('li', link_to(l(:label_sort_by_active), projects_path(:project_sort_type => '1', :project_type => project_type)))
content << content_tag('li', link_to(l(:label_sort_by_influence), projects_path(:project_sort_type => '2', :project_type => project_type)))
content << content_tag('li', link_to(l(:label_sort_by_time), projects_path(:project_sort_type => '0', :project_type => project_type), :class=>"selected"), :class=>"selected")
when 1
content << content_tag('li', link_to(l(:label_sort_by_active), projects_path(:project_sort_type => '1', :project_type => project_type), :class=>"selected"), :class=>"selected")
content << content_tag('li', link_to(l(:label_sort_by_influence), projects_path(:project_sort_type => '2', :project_type => project_type)))
content << content_tag('li', link_to(l(:label_sort_by_time), projects_path(:project_sort_type => '0', :project_type => project_type)))
when 2
content << content_tag('li', link_to(l(:label_sort_by_active), projects_path(:project_sort_type => '1', :project_type => project_type)))
content << content_tag('li', link_to(l(:label_sort_by_influence), projects_path(:project_sort_type => '2', :project_type => project_type), :class=>"selected"), :class=>"selected")
content << content_tag('li', link_to(l(:label_sort_by_time), projects_path(:project_sort_type => '0', :project_type => project_type)))
end
content = content_tag('ul', content)
content_tag('div', content, :class => "tabs")
end
# def sort_course(state, project_type)
# content = ''.html_safe
# case state
# when 0
#
# content << content_tag('li', link_to(l(:label_sort_by_active), course_path(:project_sort_type => '1', :project_type => project_type)))
# content << content_tag('li', link_to(l(:label_sort_by_influence), course_path(:project_sort_type => '2', :project_type => project_type)))
# content << content_tag('li', link_to(l(:label_sort_by_time), course_path(:project_sort_type => '0', :project_type => project_type), :class=>"selected"), :class=>"selected")
# when 1
#
# content << content_tag('li', link_to(l(:label_sort_by_active), course_path(:project_sort_type => '1', :project_type => project_type), :class=>"selected"), :class=>"selected")
# content << content_tag('li', link_to(l(:label_sort_by_influence), course_path(:project_sort_type => '2', :project_type => project_type)))
# content << content_tag('li', link_to(l(:label_sort_by_time), course_path(:project_sort_type => '0', :project_type => project_type)))
# when 2
# content << content_tag('li', link_to(l(:label_sort_by_active), course_path(:project_sort_type => '1', :project_type => project_type)))
# content << content_tag('li', link_to(l(:label_sort_by_influence), course_path(:project_sort_type => '2', :project_type => project_type), :class=>"selected"), :class=>"selected")
# content << content_tag('li', link_to(l(:label_sort_by_time), course_path(:project_sort_type => '0', :project_type => project_type)))
# end
# content = content_tag('ul', content)
# content_tag('div', content, :class => "tabs")
# end
#Added by young
def course_settings_tabs
tabs = [{:name => 'info', :action => :edit_project, :partial => 'projects/edit', :label => :label_information_plural, :course=>'1'},
#{:name => 'boards', :action => :manage_boards, :partial => 'projects/settings/boards', :label => :label_board_plural, :project_type => 1},
# {:name => 'repositories', :action => :manage_repository, :partial => 'projects/settings/repositories', :label => :label_repository_plural},
{:name => 'members', :action => :manage_members, :partial => 'projects/settings/members', :label => :label_member_plural}
]
tabs.select {|tab| User.current.allowed_to?(tab[:action], @project)}
end
#Ended by young
def parent_project_select_tag(project)
selected = project.parent
# retrieve the requested parent project
parent_id = (params[:project] && params[:project][:parent_id]) || params[:parent_id]
if parent_id
selected = (parent_id.blank? ? nil : Project.find(parent_id))
end
options = ''
options << "<option value=''></option>" if project.allowed_parents.include?(nil)
options << project_tree_options_for_select(project.allowed_parents.compact, :selected => selected)
content_tag('select', options.html_safe, :name => 'project[parent_id]', :id => 'project_parent_id')
end
# Renders the projects index
def render_project_hierarchy(projects)
render_project_nested_lists(projects) do |project|
#Modified by young
if (project.try(:project_type) == Project::ProjectType_course )
s = link_to_project(project, {}, :class => "#{project.css_classes} #{User.current.member_of?(project) ? 'my-project' : nil}").html_safe
else
s = link_to_project(project, {}, :class => "#{project.css_classes} #{User.current.member_of?(project) ? 'my-project' : nil}")
end
#Ended by young
if project.description.present?
#Delete by nie.
# s << content_tag('td', textilizable(project.short_description, :project => project), :class => 'wiki description')
end
s
end
end
# Returns a set of options for a select field, grouped by project.
def version_options_for_select(versions, selected=nil)
grouped = Hash.new {|h,k| h[k] = []}
versions.each do |version|
grouped[version.project.name] << [version.name, version.id]
end
if grouped.keys.size > 1
grouped_options_for_select(grouped, selected && selected.id)
else
options_for_select((grouped.values.first || []), selected && selected.id)
end
end
def format_version_sharing(sharing)
sharing = 'none' unless Version::VERSION_SHARINGS.include?(sharing)
l("label_version_sharing_#{sharing}")
end
# this method is used to get all projects that tagged one tag
# added by william
def get_projects_by_tag(tag_name)
Project.tagged_with(tag_name).order('updated_on desc')
end
# added by fq
def homework_type_option
type = []
option1 = []
option2 = []
option1 << l(:label_task_submit_form_accessory)
option1 << 1
option2 << l(:label_task_submit_form_project)
option2 << 2
type << option1
type << option2
end
#是否启动互评下拉框
def is_evaluation_option
type = []
option1 = []
option2 = []
option1 << l(:lable_start_mutual_evaluation)
option1 << 1
option2 << l(:lable_close_mutual_evaluation)
option2 << 2
type << option1
type << option2
end
# 用来判断用户是否是项目的管理员
# added by william
def is_manager?(user_id,project_id)
@result = false
@user_id = ProjectInfo.find_by_project_id(project_id)
if @user_id == user.id
@result = true
end
return @result
end
# 将动态中类型转换为可读的字符串
def eventToLanguage event_type
case event_type
when "issue-note"
l :label_issue
when "issue"
l :label_issue
when "attachment"
l :label_attachment
when "news"
l :label_news
else
""
end
end
def eventToLanguageCourse event_type, project
case event_type
when "issue-note"
l :label_issue
when "issue"
l :label_issue
when "attachment"
l :label_attachment
when "news"
project.project_type == 1 ? (l :label_notification) : (l :label_news)
else
""
end
end
def rolesToLanguage rolesArray
rolesArray = ([] << rolesArray) unless rolesArray.is_a?(Array)
rolesArray.map{ |roleName|
case roleName.to_sym
when :Manager
l :default_role_manager
when :Developer
l :default_role_developer
when :Reporter
l :default_role_reporter
else
'Unkown'
end
}
end
def sort_project_by_hot
return sort_project_by_hot_rails
@projects_status = ProjectStatus.visible.where("project_statuses.project_type <> ? or project_statuses.project_type is null", 1)
@projects_status = @projects_status.reorder('grade').all.reverse
@projects = []
@projects_status.each do |obj|
break if(@projects_status[10] == obj)
@projects << Project.visible.find_by_id("#{obj.project_id}")#where('id=:id', id: obj.project_id)
end
@projects
rescue NoMethodError => e
logger.error "Logger.Error [ProjectsHelper] ===> #sort_project_by_hot, NoMethodError: #{e}"
[]
end
def sort_project_by_hot_rails
# @projects_status = ProjectStatus.visible.where("project_statuses.project_type <> ? or project_statuses.project_type is null", 1)
# @projects_status = @projects_status.reorder('grade').all.reverse
# Project.joins(@projects_status).limit(10)
limit = 10
#Project.find_by_sql("SELECT * FROM projects RIGHT OUTER JOIN (SELECT * FROM project_statuses ORDER BY grade DESC LIMIT #{limit} ) AS t ON projects.id = t.project_id ")
Project.find_by_sql("
SELECT p.id, p.name, p.description, p.identifier, t.project_id
FROM projects AS p RIGHT OUTER JOIN (
SELECT project_id,grade FROM project_statuses
WHERE project_type = 0 ORDER BY grade DESC LIMIT #{limit} ) AS t ON p.id = t.project_id ")
end
# 判断课程是否结束,快别用,这个定日子的方法有问题
def course_timeout? project
return true if (project.nil? && project.course_extra.nil?)
courses_year = project.course_extra.time
current_year = Time.now.year
if(courses_year >= current_year)
return false
elsif( (courses_year < current_year) && (Time.now.month < 3) )
return false
else
return true
end
end
end
# encoding: utf-8
#
# Redmine - project management software
# Copyright (C) 2006-2013 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.
include AvatarHelper
module ProjectsHelper
def link_to_version(version, options = {})
return '' unless version && version.is_a?(Version)
link_to_if version.visible?, format_version_name(version), { :controller => 'versions', :action => 'show', :id => version }, options
end
def project_settings_tabs
tabs = [{:name => 'info', :action => :edit_project, :partial => 'projects/edit', :label => :label_information_plural},
{:name => 'modules', :action => :select_project_modules, :partial => 'projects/settings/modules', :label => :label_module_plural},
{:name => 'members', :action => :manage_members, :partial => 'projects/settings/members', :label => :label_member_plural},
{:name => 'versions', :action => :manage_versions, :partial => 'projects/settings/versions', :label => :label_version_plural},
{:name => 'categories', :action => :manage_categories, :partial => 'projects/settings/issue_categories', :label => :label_issue_category_plural},
# {:name => 'wiki', :action => :manage_wiki, :partial => 'projects/settings/wiki', :label => :label_wiki},
{:name => 'repositories', :action => :manage_repository, :partial => 'projects/settings/repositories', :label => :label_repository_plural},
#{:name => 'boards', :action => :manage_boards, :partial => 'projects/settings/boards', :label => :label_board_plural},
{:name => 'activities', :action => :manage_project_activities, :partial => 'projects/settings/activities', :label => :enumeration_activities}
]
tabs.select {|tab| User.current.allowed_to?(tab[:action], @project)}
end
# added bu huang
def sort_project_enterprise(state, project_type)
content = ''.html_safe
case state
when 0
content << content_tag('li', link_to(l(:label_sort_by_active), projects_path(:project_sort_type => '1', :project_type => project_type)))
content << content_tag('li', link_to(l(:label_sort_by_influence), projects_path(:project_sort_type => '2', :project_type => project_type)))
content << content_tag('li', link_to(l(:label_sort_by_time), projects_path(:project_sort_type => '0', :project_type => project_type), :class=>"selected"), :class=>"selected")
when 1
content << content_tag('li', link_to(l(:label_sort_by_active), projects_path(:project_sort_type => '1', :project_type => project_type), :class=>"selected"), :class=>"selected")
content << content_tag('li', link_to(l(:label_sort_by_influence), projects_path(:project_sort_type => '2', :project_type => project_type)))
content << content_tag('li', link_to(l(:label_sort_by_time), projects_path(:project_sort_type => '0', :project_type => project_type)))
when 2
content << content_tag('li', link_to(l(:label_sort_by_active), projects_path(:project_sort_type => '1', :project_type => project_type)))
content << content_tag('li', link_to(l(:label_sort_by_influence), projects_path(:project_sort_type => '2', :project_type => project_type), :class=>"selected"), :class=>"selected")
content << content_tag('li', link_to(l(:label_sort_by_time), projects_path(:project_sort_type => '0', :project_type => project_type)))
end
content = content_tag('ul', content)
content_tag('div', content, :class => "tabs_enterprise")
end
def sort_course(state, project_type, school_id)
content = ''.html_safe
case state
when 0
content << content_tag('li', link_to(l(:label_sort_by_time), course_path(:project_sort_type => '0', :project_type => project_type), :school_id => school_id, :class=>"selected"), :class=>"selected")
content << content_tag('li', link_to(l(:label_sort_by_active), course_path(:project_sort_type => '1', :project_type => project_type, :school_id => school_id)))
# content << content_tag('li', link_to(l(:label_sort_by_influence), course_path(:project_sort_type => '2', :project_type => project_type)))
content << content_tag('li', link_to(l(:label_sort_by_activity), course_path(:project_sort_type => '3', :project_type => project_type, :school_id => school_id)))
when 1
content << content_tag('li', link_to(l(:label_sort_by_time), course_path(:project_sort_type => '0', :project_type => project_type, :school_id => school_id)))
content << content_tag('li', link_to(l(:label_sort_by_active), course_path(:project_sort_type => '1', :project_type => project_type, :school_id => school_id), :class=>"selected"), :class=>"selected")
# content << content_tag('li', link_to(l(:label_sort_by_influence), course_path(:project_sort_type => '2', :project_type => project_type)))
content << content_tag('li', link_to(l(:label_sort_by_activity), course_path(:project_sort_type => '3', :project_type => project_type, :school_id => school_id)))
when 2
content << content_tag('li', link_to(l(:label_sort_by_time), course_path(:project_sort_type => '0', :project_type => project_type, :school_id => school_id)))
content << content_tag('li', link_to(l(:label_sort_by_active), course_path(:project_sort_type => '1', :project_type => project_type, :school_id => school_id)))
# content << content_tag('li', link_to(l(:label_sort_by_influence), course_path(:project_sort_type => '2', :project_type => project_type), :class=>"selected"), :class=>"selected")
content << content_tag('li', link_to(l(:label_sort_by_activity), course_path(:project_sort_type => '3', :project_type => project_type, :school_id => school_id)))
#gcm
when 3
content << content_tag('li', link_to(l(:label_sort_by_time), course_path(:project_sort_type => '0', :project_type => project_type, :school_id => school_id)))
content << content_tag('li', link_to(l(:label_sort_by_active), course_path(:project_sort_type => '1', :project_type => project_type, :school_id => school_id)))
# content << content_tag('li', link_to(l(:label_sort_by_influence), course_path(:project_sort_type => '2', :project_type => project_type)))
content << content_tag('li', link_to(l(:label_sort_by_activity), course_path(:project_sort_type => '3', :project_type => project_type, :school_id => school_id), :class=>"selected"), :class=>"selected")
end
#gcmend
content = content_tag('ul', content)
content_tag('div', content, :class => "tabs")
end
# end
def sort_project(state, project_type)
content = ''.html_safe
case state
when 0
content << content_tag('li', link_to(l(:label_sort_by_active), projects_path(:project_sort_type => '1', :project_type => project_type)))
content << content_tag('li', link_to(l(:label_sort_by_influence), projects_path(:project_sort_type => '2', :project_type => project_type)))
content << content_tag('li', link_to(l(:label_sort_by_time), projects_path(:project_sort_type => '0', :project_type => project_type), :class=>"selected"), :class=>"selected")
when 1
content << content_tag('li', link_to(l(:label_sort_by_active), projects_path(:project_sort_type => '1', :project_type => project_type), :class=>"selected"), :class=>"selected")
content << content_tag('li', link_to(l(:label_sort_by_influence), projects_path(:project_sort_type => '2', :project_type => project_type)))
content << content_tag('li', link_to(l(:label_sort_by_time), projects_path(:project_sort_type => '0', :project_type => project_type)))
when 2
content << content_tag('li', link_to(l(:label_sort_by_active), projects_path(:project_sort_type => '1', :project_type => project_type)))
content << content_tag('li', link_to(l(:label_sort_by_influence), projects_path(:project_sort_type => '2', :project_type => project_type), :class=>"selected"), :class=>"selected")
content << content_tag('li', link_to(l(:label_sort_by_time), projects_path(:project_sort_type => '0', :project_type => project_type)))
end
content = content_tag('ul', content)
content_tag('div', content, :class => "tabs")
end
# def sort_course(state, project_type)
# content = ''.html_safe
# case state
# when 0
#
# content << content_tag('li', link_to(l(:label_sort_by_active), course_path(:project_sort_type => '1', :project_type => project_type)))
# content << content_tag('li', link_to(l(:label_sort_by_influence), course_path(:project_sort_type => '2', :project_type => project_type)))
# content << content_tag('li', link_to(l(:label_sort_by_time), course_path(:project_sort_type => '0', :project_type => project_type), :class=>"selected"), :class=>"selected")
# when 1
#
# content << content_tag('li', link_to(l(:label_sort_by_active), course_path(:project_sort_type => '1', :project_type => project_type), :class=>"selected"), :class=>"selected")
# content << content_tag('li', link_to(l(:label_sort_by_influence), course_path(:project_sort_type => '2', :project_type => project_type)))
# content << content_tag('li', link_to(l(:label_sort_by_time), course_path(:project_sort_type => '0', :project_type => project_type)))
# when 2
# content << content_tag('li', link_to(l(:label_sort_by_active), course_path(:project_sort_type => '1', :project_type => project_type)))
# content << content_tag('li', link_to(l(:label_sort_by_influence), course_path(:project_sort_type => '2', :project_type => project_type), :class=>"selected"), :class=>"selected")
# content << content_tag('li', link_to(l(:label_sort_by_time), course_path(:project_sort_type => '0', :project_type => project_type)))
# end
# content = content_tag('ul', content)
# content_tag('div', content, :class => "tabs")
# end
# Added by young
def course_settings_tabs
tabs = [{:name => 'info', :action => :edit_project, :partial => 'projects/edit', :label => :label_information_plural, :course=>'1'},
#{:name => 'boards', :action => :manage_boards, :partial => 'projects/settings/boards', :label => :label_board_plural, :project_type => 1},
# {:name => 'repositories', :action => :manage_repository, :partial => 'projects/settings/repositories', :label => :label_repository_plural},
{:name => 'members', :action => :manage_members, :partial => 'projects/settings/members', :label => :label_member_plural}
]
tabs.select {|tab| User.current.allowed_to?(tab[:action], @project)}
end
# Ended by young
def parent_project_select_tag(project)
selected = project.parent
# retrieve the requested parent project
parent_id = (params[:project] && params[:project][:parent_id]) || params[:parent_id]
if parent_id
selected = (parent_id.blank? ? nil : Project.find(parent_id))
end
options = ''
options << "<option value=''></option>" if project.allowed_parents.include?(nil)
options << project_tree_options_for_select(project.allowed_parents.compact, :selected => selected)
content_tag('select', options.html_safe, :name => 'project[parent_id]', :id => 'project_parent_id')
end
# Renders the projects index
def render_project_hierarchy(projects)
render_project_nested_lists(projects) do |project|
#Modified by young
if project.try(:project_type) == Project::ProjectType_course
# modified by longjun
# never use unless and else
# unless project.is_public == 1
if project.is_public != 1
s = "<span class='private_project'>#{l(:label_private)}</span>".html_safe
else
s = "".html_safe
end
# end longjun
# modified by Longjun
s += link_to_project(project, {},
:class => "#{project.css_classes} #{User.current.member_of?(project) ? 'my-project' : nil}").html_safe
# end longjun
else
# modified by longjun
# unless project.is_public
if !project.is_public
# end longjun
s = "<span class='private_project'>#{l(:label_private)}</span>".html_safe
else
s = "".html_safe
end
# modified by longjun
s += link_to_project(project, {},
:class => "#{project.css_classes} #{User.current.member_of?(project) ? 'my-project' : nil}")
# end longjun
end
#Ended by young
if project.description.present?
#Delete by nie.
# s << content_tag('td', textilizable(project.short_description, :project => project), :class => 'wiki description')
end
s
end
end
# Returns a set of options for a select field, grouped by project.
def version_options_for_select(versions, selected=nil)
grouped = Hash.new {|h,k| h[k] = []}
versions.each do |version|
grouped[version.project.name] << [version.name, version.id]
end
if grouped.keys.size > 1
grouped_options_for_select(grouped, selected && selected.id)
else
options_for_select((grouped.values.first || []), selected && selected.id)
end
end
def format_version_sharing(sharing)
sharing = 'none' unless Version::VERSION_SHARINGS.include?(sharing)
l("label_version_sharing_#{sharing}")
end
# this method is used to get all projects that tagged one tag
# added by william
def get_projects_by_tag(tag_name)
Project.tagged_with(tag_name).order('updated_on desc')
end
# added by fq
def homework_type_option
type = []
option1 = []
option2 = []
option1 << l(:label_task_submit_form_accessory)
option1 << 1
option2 << l(:label_task_submit_form_project)
option2 << 2
type << option1
type << option2
end
#是否启动互评下拉框
def is_evaluation_option
type = []
option1 = []
option2 = []
option1 << l(:lable_start_mutual_evaluation)
option1 << 1
option2 << l(:lable_close_mutual_evaluation)
option2 << 2
type << option1
type << option2
end
# 用来判断用户是否是项目的管理员
# added by william
def is_manager?(user_id,project_id)
@result = false
@user_id = ProjectInfo.find_by_project_id(project_id)
# modified by longjun
# if @user_id == user.id
# @result = true
# end
@result = true if @user_id = user.id
# end longjun
return @result
end
# 将动态中类型转换为可读的字符串
def eventToLanguage event_type
case event_type
when "issue-note"
l :label_issue
when "issue"
l :label_issue
when "attachment"
l :label_attachment
when "news"
l :label_news
else
""
end
end
def eventToLanguageCourse event_type, project
case event_type
when "issue-note"
l :label_issue
when "issue"
l :label_issue
when "attachment"
l :label_attachment
when "news"
project.project_type == 1 ? (l :label_notification) : (l :label_news)
else
""
end
end
def rolesToLanguage rolesArray
rolesArray = ([] << rolesArray) unless rolesArray.is_a?(Array)
rolesArray.map{ |roleName|
case roleName.to_sym
when :Manager
l :default_role_manager
when :Developer
l :default_role_developer
when :Reporter
l :default_role_reporter
else
'Unkown'
end
}
end
def sort_project_by_hot
return sort_project_by_hot_rails
@projects_status = ProjectStatus.visible.where("project_statuses.project_type <> ? or project_statuses.project_type is null", 1)
@projects_status = @projects_status.reorder('grade').all.reverse
@projects = []
@projects_status.each do |obj|
break if(@projects_status[10] == obj)
@projects << Project.visible.find_by_id("#{obj.project_id}")#where('id=:id', id: obj.project_id)
end
@projects
rescue NoMethodError => e
logger.error "Logger.Error [ProjectsHelper] ===> #sort_project_by_hot, NoMethodError: #{e}"
[]
end
def sort_project_by_hot_rails
# @projects_status = ProjectStatus.visible.where("project_statuses.project_type <> ? or project_statuses.project_type is null", 1)
# @projects_status = @projects_status.reorder('grade').all.reverse
# Project.joins(@projects_status).limit(10)
limit = 10
#Project.find_by_sql("SELECT * FROM projects RIGHT OUTER JOIN (SELECT * FROM project_statuses ORDER BY grade DESC LIMIT #{limit} ) AS t ON projects.id = t.project_id ")
Project.find_by_sql("
SELECT p.id, p.name, p.description, p.identifier, t.project_id
FROM projects AS p RIGHT OUTER JOIN (
SELECT project_id,grade FROM project_statuses
WHERE project_type = 0 ORDER BY grade DESC LIMIT #{limit} ) AS t ON p.id = t.project_id ")
end
# 判断课程是否结束,快别用,这个定日子的方法有问题
def course_timeout? project
return true if (project.nil? && project.course_extra.nil?)
courses_year = project.course_extra.time
current_year = Time.now.year
if courses_year >= current_year
return false
elsif (courses_year < current_year) && (Time.now.month < 3)
return false
else
return true
end
end
def find_project_repository project
unless project.repositories.nil?
project.repositories.each do |repository|
repository.fetch_changesets if Setting.autofetch_changesets?
end
end
end
end

@ -20,7 +20,7 @@
module RepositoriesHelper
ROOT_PATH="/home/pdl/redmine-2.3.2-0/apache2/"
PROJECT_PATH_CUT = 40
REPO_IP_ADDRESS = "repository.trustie.net"
REPO_IP_ADDRESS = Setting.repository_domain
def format_revision(revision)
if revision.respond_to? :format_identifier

@ -4,13 +4,8 @@ def options_from_select_project(user)
@option = []
@membership.each do |membership|
unless(membership.project.project_type==1)
#membership.member_roles.each{|role|
# if(role.role_id == 3)
# @option << membership.project
# end
#}
#拥有编辑项目权限的可操作该项目
if user.allowed_to?({:controller => "projects", :action => "edit"}, membership.project, :global => false)
#可被用户引用的项目
if user.allowed_to?(:quote_project, membership.project)
@option << membership.project
end
end

@ -13,6 +13,19 @@ module SoftapplicationsHelper
content = content_tag('ul', content)
content_tag('div', content, :class => "tabs")
end
#作品分类下拉框
def work_type_opttion
type = []
#work_types = WorksCategory.all
WorksCategory.all.each do |work_type|
option = []
option << work_type.category
option << work_type.category
type << option
end
type
end
# def select_option_helper option
# tmp = Hash.new

@ -16,6 +16,8 @@ module StoresHelper
news_path(container)
when 'Project'
project_files_path(container)
when 'Course'
course_files_path(container)
when 'Version'
# version_path(container)
project_files_path(container.project)
@ -37,15 +39,23 @@ module StoresHelper
WORD_LIMIT = 100
def come_from_local attachment
container = attachment.container
case container.class.to_s
when 'Message'
# '项目 > zzz > 论坛 > 帖子xxx'
# topic_str = container.project.project_type == 0 ? l(:label_board) : l(:label_new_course)
topic_list = link_to l(:label_board), project_boards_path(container.project)
topic_item = link_to container.subject.truncate(WORD_LIMIT, omission: '...'), board_message_path(container.board, container), title: container.subject
project_link(container.project).push(topic_list, topic_item)
course = container.course
project = container.project
if course.nil? # container is belongs to Project
topic_list = link_to l(:label_board), project_boards_path(container.project)
topic_item = link_to container.subject.truncate(WORD_LIMIT, omission: '...'), board_message_path(container.board, container), title: container.subject
project_link(container.project).push(topic_list, topic_item)
else # container is belongs to Course
topic_list = link_to l(:label_course_news), course_boards_path(course)
topic_item = link_to container.try(:subject).to_s.truncate(WORD_LIMIT, omission: '...'), board_message_path(container.board, container), title: container.subject
project_link(course).push(topic_list, topic_item)
end
when 'Issue'
# '项目 > zzz > 缺陷 > 问题xxx'
issue_list = link_to l(:label_project_issues), project_issues_path(container.project)
@ -58,15 +68,26 @@ module StoresHelper
project_link(container.project).push(doc_list, doc_item)
when 'News'
# '课程 > zzz > 新闻 > 新闻xxx'
news_str = container.project.project_type == 0 ? l(:label_news) : l(:label_course_news)
news_list = link_to news_str, project_news_index_path(container.project)
news_item = link_to container.title.truncate(WORD_LIMIT, omission: '...'), news_path(container), title: container.title
project_link(container.project).push(news_list, news_item)
course = container.course
project = container.project
if course.nil? # container is belongs to Project
news_list = link_to l(:label_news), project_news_index_path(container.project)
news_item = link_to container.title.truncate(WORD_LIMIT, omission: '...'), news_path(container), title: container.title
project_link(container.project).push(news_list, news_item)
else # container is belongs to Course
news_list = link_to l(:label_course_news), course_news_index_path(course)
news_item = link_to container.title.truncate(WORD_LIMIT, omission: '...'), news_path(container), title: container.title
project_link(course).push(news_list, news_item)
end
when 'Project'
# '项目 > zzz '
file_str = container.project.project_type == 0 ? l(:project_module_files) : l(:label_course_file)
files_list = link_to file_str, project_files_path(container.project)
project_link(container).push(files_list)
when 'Course'
files_list = link_to l(:label_course_file), course_files_path(container)
project_link(container).push(files_list)
when 'Version'
# '项目 > zzz > 里程碑 > xxx'
ver_list = link_to l(:label_roadmap), project_roadmap_path(container.project)
@ -91,7 +112,8 @@ module StoresHelper
# '竞赛 > xxx '
bid_link(container)
else
Rails.logger.error "ERROR: attachment type unkown"
Rails.logger.error "ERROR: attachment type unkown. file:#{__FILE__}, line:#{__LINE__}"
Rails.logger.error "#{container.class.to_s}"
[link_to('unkown', '')]
end
rescue ActionController::RoutingError => e
@ -99,20 +121,6 @@ module StoresHelper
[link_to('unkown', '')]
end
def project_link project
if project.nil?
Rails.logger.error "ERROR: attachment type unkown #project_link project.nil?"
return [link_to('unkown', '')]
end
project_list = nil
if project.project_type == 0
project_list = link_to l(:label_project_plural), projects_path
else
project_list = link_to l(:label_new_course), course_path
end
project_item = link_to project.to_s, project_path(project)
[project_list, project_item]
end
def bid_link bid
bid_list = nil
@ -129,12 +137,36 @@ module StoresHelper
Rails.logger.error "ERROR: attachment type unkown #bid_link/when 3"
return [link_to('unkown', '#')]
end
bid_list = link_to l(:label_homework), project_homework_path(bid.courses.first)
bid_item = link_to bid.name, respond_path(bid)
bid_list = link_to l(:label_homework), homework_course_path(bid.courses.first)
bid_item = link_to bid.name, course_for_bid_path(bid)
return project_link(bid.courses.first).push(bid_list, bid_item)
else
xxx
end
[bid_list, bid_item]
end
def project_link project
if project.nil?
Rails.logger.error "ERROR: attachment type unkown #project_link project.nil? file: #{__FILE__}, line: #{__LINE__}"
return [link_to('unkown', '')]
end
project_list = nil
klass = project.class.to_s
case klass
when "Project"
project_list = "<lable>#{l(:label_project_plural)}</lable>"
project_item = link_to project.to_s, project_path(project)
[project_list, project_item]
when "Course"
course_list = "<lable>#{l(:label_new_course)}</lable>"
course_item = link_to project.name, course_path(project)
[course_list, course_item]
else
Rails.logger.error "[StoresHelper]: #{klass} ======================================="
[]
end
end
end

@ -12,6 +12,8 @@ module TagsHelper
@obj = Issue.find_by_id(obj_id)
when '4'
@obj = Bid.find_by_id(obj_id)
when '5'
@obj = Forum.find_by_id(obj_id)
when '6'
@obj = Attachment.find_by_id(obj_id)
when '7'
@ -44,6 +46,8 @@ module TagsHelper
if user.id == obj_id
@result = true
end
when '5'
@result = is_forum_manager?(user.id,obj_id)
when '7'
if user.id == obj_id
@result = true
@ -56,6 +60,17 @@ module TagsHelper
end
# 判断用户是否是贴吧的管理员
# add by chenmin
def is_forum_manager?(user_id,forum_id)
@result = false
@user_id = Forum.find(forum_id).creator_id;
if @user_id == user.id
@result = true
end
return @result
end
def tagname_val
("#tag_name_name").value
end

@ -228,16 +228,10 @@ module UserScoreHelper
isManager = 0
members = Member.where('user_id = ?', user.id)
members.each do |m|
#roles = m.member_roles
#roles.each do |r|
# if r.role_id == 3
# isManager = 1
# end
#end
@membership = m.memberships.all(:conditions => Project.visible_condition(User.current))
@membership.each do |membership|
#拥有编辑项目权限的可操作该项目
if m.allowed_to?({:controller => "projects", :action => "edit"}, membership.project, :global => false)
if m.allowed_to?(:is_manager, membership.project, :global => false)
isManager = 1
end
end
@ -342,8 +336,619 @@ module UserScoreHelper
user.user_score.update_attributes(:collaboration => collaboration, :influence => influence, :skill => skill,
:activity => activity, :file => file, :issue => issue, :level => level)
end
#========================================================================================================
#个人得分统计
#========================================================================================================
#type 1个人得分、2个人在项目project中的得分
def get_option_number(user,type,project=nil)
if project.nil?
option_number = OptionNumber.where("user_id = '#{user.id}' and score_type = '#{type}'");
else
option_number = OptionNumber.where("user_id = '#{user.id}' and score_type = '#{type}' and project_id = '#{project.id}'");
end
result = nil
if option_number.nil? || option_number.count == 0
result = OptionNumber.new
result.user_id = user.id
result.memo = 0
result.messages_for_issues = 0
result.issues_status = 0
result.replay_for_message = 0
result.replay_for_memo = 0
result.follow = 0
result.tread = 0
result.praise_by_one = 0
result.praise_by_two = 0
result.praise_by_three = 0
result.tread_by_one = 0
result.tread_by_two = 0
result.tread_by_three = 0
result.changeset = 0
result.document = 0
result.attachment = 0
result.issue_done_ratio = 0
result.post_issue = 0
result.total_score = 0
result.score_type =type
unless project.nil?
result.project_id = project.id
end
else
result = option_number.first
end
result
end
def get_option_num_by_id(user_id,type,project_id=nil)
if project_id.nil?
option_number = OptionNumber.where("user_id = '#{user_id}' and score_type = '#{type}'");
else
option_number = OptionNumber.where("user_id = '#{user_id}' and score_type = '#{type}' and project_id = '#{project_id}'");
end
result = nil
if option_number.nil? || option_number.count == 0
result = OptionNumber.new
result.user_id = user_id
result.memo = 0
result.messages_for_issues = 0
result.issues_status = 0
result.replay_for_message = 0
result.replay_for_memo = 0
result.follow = 0
result.tread = 0
result.praise_by_one = 0
result.praise_by_two = 0
result.praise_by_three = 0
result.tread_by_one = 0
result.tread_by_two = 0
result.tread_by_three = 0
result.changeset = 0
result.document = 0
result.attachment = 0
result.issue_done_ratio = 0
result.post_issue = 0
result.total_score = 0
result.score_type =type
unless project_id.nil?
result.project_id = project_id
end
else
result = option_number.first
end
result
end
#更新分数
def update_score(option_number)
option_number.total_score = collaboration(option_number) + influence(option_number) + skill(option_number) + active(option_number)
if option_number.total_score < 0
option_number.total_score = 0
end
option_number.save
option_number.total_score
end
#协同得分
def collaboration(option_number)
option_number.memo * 2 + option_number.messages_for_issues + option_number.issues_status + option_number.replay_for_message + option_number.replay_for_memo
end
#影响力得分
def influence(option_number)
option_number.follow * 2
end
#技术得分
def skill(option_number)
option_number.praise_by_one * 4 + option_number.praise_by_two * 6 + option_number.praise_by_three * 8 - option_number.tread * 2 - option_number.tread_by_one * 2 - option_number.tread_by_two * 4 - option_number.tread_by_three * 6
end
#项目贡献得分
def active(option_number)
option_number.changeset * 4 + option_number.document * 4 + option_number.attachment * 4 + option_number.issue_done_ratio * 2 + option_number.post_issue * 4
end
#更新发帖数
def update_memo_number(user,type,project=nil)
option_number = get_option_number(user,type,project)
option_number.memo = memo_num(user,project)#Message.includes(:author).where("parent_id IS NULL and author_id = '#{user.id}'").all.count + Memo.includes(:author).where("parent_id IS NULL and author_id = '#{user.id}'").all.count
update_score(option_number)
end
#发帖数
def memo_num(user,project=nil)
if project.nil?
#Message.includes(:author).joins(:board).where("#{Message.table_name}.parent_id IS NULL and #{Message.table_name}.author_id = '#{user.id}' and #{Board.table_name}.project_id != -1").all.count #+ Memo.includes(:author).where("parent_id IS NULL and author_id = '#{user.id}'").all.count
users = Message.find_by_sql("SELECT COUNT(*) as m_count FROM `messages` JOIN `boards` ON boards.project_id != -1 AND messages.board_id = boards.id
WHERE messages.parent_id IS NULL AND messages.author_id = #{user.id}")
result = 0
users.each do |user|
result = user.m_count
end
result
#user.messages.where("parent_id IS NULL").count
else
#Message.includes(:author).joins(:board).where("#{Message.table_name}.parent_id IS NULL and #{Message.table_name}.author_id = '#{user.id}' and #{Board.table_name}.project_id = #{project.id}").all.count
users = Message.find_by_sql("SELECT COUNT(*) as m_count FROM `messages` JOIN `boards` ON boards.project_id = '#{project.id}' AND messages.board_id = boards.id
WHERE messages.parent_id IS NULL AND messages.author_id = #{user.id}")
result = 0
users.each do |user|
result = user.m_count
end
result
end
end
def memo_score(user,project=nil)
if project.nil?
User.find_by_sql("SELECT `users`.id,(SELECT COUNT(*) * 2 FROM `messages` JOIN `boards` ON boards.project_id != -1 AND messages.board_id = boards.id
WHERE messages.parent_id IS NULL AND messages.author_id = `users`.id) AS m_count
FROM `users` where id = #{user.id}")
else
User.find_by_sql("SELECT `users`.id,(SELECT COUNT(*) * 2 FROM `messages` JOIN `boards` ON boards.project_id = '#{project.id}' AND messages.board_id = boards.id
WHERE messages.parent_id IS NULL AND messages.author_id = `users`.id) AS m_count
FROM `users` where id = #{user.id}")
end
end
#更新对缺陷留言数
def update_messges_for_issue(user,type,project=nil)
option_number = get_option_number(user,type,project)
option_number.messages_for_issues = messges_for_issue_num(user,project)#Journal.includes(:user).where("user_id = '#{user.id}' and notes != '' and notes is not null").all.count
update_score(option_number)
end
def messges_for_issue_num(user,project=nil)
if project.nil?
#Journal.includes(:user).where("user_id = '#{user.id}' and notes is not null and notes != ''").all.count
users = Journal.find_by_sql("SELECT COUNT(*) as m_count FROM journals WHERE journals.user_id = #{user.id} AND journals.notes IS NOT NULL AND journals.notes != ''")
result = 0
if users.count > 0
result = users.first.m_count
end
result
else
#Journal.includes(:user).joins(:issue).where("#{Journal.table_name}.user_id = '#{user.id}' and #{Issue.table_name}.project_id = '#{project.id}' and #{Journal.table_name}.notes != '' and #{Journal.table_name}.notes is not null").all.count
users = Journal.find_by_sql("SELECT COUNT(*) as m_count FROM journals join issues on #{Journal.table_name}.journalized_type = 'Issue' and #{Journal.table_name}.journalized_id = #{Issue.table_name}.id WHERE journals.user_id = #{user.id} AND journals.notes IS NOT NULL AND journals.notes != ''and #{Issue.table_name}.project_id = '#{project.id}'")
result = 0
if users.count > 0
result = users.first.m_count
end
result
end
end
def messges_for_issue_score(user,project=nil)
if project.nil?
User.find_by_sql("SELECT users.id,(SELECT COUNT(*) FROM journals WHERE journals.user_id = users.id AND journals.notes IS NOT NULL AND journals.notes != '') AS m_score FROM users where id = #{user.id}")
else
User.find_by_sql("SELECT users.id,(SELECT COUNT(*) FROM journals join issues on #{Journal.table_name}.journalized_type = 'Issue' and #{Journal.table_name}.journalized_id = #{Issue.table_name}.id WHERE journals.user_id = users.id AND journals.notes IS NOT NULL AND journals.notes != ''and #{Issue.table_name}.project_id = '#{project.id}') AS m_score FROM users where id = #{user.id}")
end
end
#更新更改缺陷状态状态次数
def update_issues_status(user,type,project=nil)
option_number = get_option_number(user,type,project)
option_number.issues_status = issues_status_num(user,project)#Journal.joins(:details, :user).where("#{JournalDetail.table_name}.prop_key = 'status_id' and #{User.table_name}.id = '#{user.id}'").count
update_score(option_number)
end
def issues_status_num(user,project=nil)
if project.nil?
#Journal.joins(:details, :user).where("#{JournalDetail.table_name}.prop_key = 'status_id' and #{User.table_name}.id = '#{user.id}'").count
users = Journal.find_by_sql("SELECT COUNT(*) as m_count FROM journals JOIN journal_details on journals.id = journal_details.journal_id WHERE journal_details.prop_key = 'status_id' and journals.user_id = #{user.id}")
result = 0
if users.count > 0
result = users.first.m_count
end
result
else
#Journal.joins(:issue,:details,:user).where("#{Issue.table_name}.project_id = '#{project.id}' and #{JournalDetail.table_name}.prop_key = 'status_id' and #{User.table_name}.id = '#{user.id}'").count
users = Journal.find_by_sql("SELECT COUNT(*) as m_count FROM journals JOIN journal_details on journals.id = journal_details.journal_id JOIN issues ON issues.id = journals.journalized_id and journalized_type = 'Issue' WHERE journal_details.prop_key = 'status_id' and journals.user_id = #{user.id} and issues.project_id = '#{project.id}'")
result = 0
if users.count > 0
result = users.first.m_count
end
result
end
end
def issues_status_score(user,project=nil)
if project.nil?
#Journal.joins(:details, :user).where("#{JournalDetail.table_name}.prop_key = 'status_id' and #{User.table_name}.id = '#{user.id}'").count
User.find_by_sql("SELECT users.id,(SELECT COUNT(*) FROM journals JOIN journal_details on journals.id = journal_details.journal_id WHERE journal_details.prop_key = 'status_id' and journals.user_id = users.id) AS m_count FROM users WHERE users.id = '#{user.id}'")
else
#Journal.joins(:issue,:details,:user).where("#{Issue.table_name}.project_id = '#{project.id}' and #{JournalDetail.table_name}.prop_key = 'status_id' and #{User.table_name}.id = '#{user.id}'").count
User.find_by_sql("SELECT users.id,(SELECT COUNT(*) FROM journals JOIN journal_details on journals.id = journal_details.journal_id JOIN issues ON issues.id = journals.journalized_id and journalized_type = 'Issue' WHERE journal_details.prop_key = 'status_id' and journals.user_id = users.id and issues.project_id = '#{project.id}') AS m_count FROM users WHERE users.id = '#{user.id}'")
end
end
#更新对留言的回复数量
def update_replay_for_message(user,type,project=nil)
option_number = get_option_number(user,type,project)
option_number.replay_for_message = replay_for_message_num(user,project)#JournalsForMessage.includes(:user).where("m_parent_id IS NOT NULL and user_id = #{user.id}").count
update_score(option_number)
end
def replay_for_message_num(user,project=nil)
if project.nil?
#JournalsForMessage.includes(:user).where("m_parent_id IS NOT NULL and user_id = #{user.id} and jour_type = 'Project'").count
users = JournalsForMessage.find_by_sql("SELECT COUNT(*) as m_count From #{JournalsForMessage.table_name} WHERE m_parent_id IS NOT NULL and user_id = #{user.id} and jour_type = 'Project'")
result = 0
if users.count > 0
result = users.first.m_count
end
result
else
#JournalsForMessage.includes(:user).where("m_parent_id IS NOT NULL and user_id = #{user.id} and jour_type = 'Project' and jour_id = '#{project.id}'").count
users = JournalsForMessage.find_by_sql("SELECT COUNT(*) as m_count From #{JournalsForMessage.table_name} WHERE m_parent_id IS NOT NULL and user_id = #{user.id} and jour_type = 'Project' and jour_id = '#{project.id}'")
result = 0
if users.count > 0
result = users.first.m_count
end
result
end
end
def replay_for_message_score(user,project=nil)
if project.nil?
User.find_by_sql("SELECT users.id,(SELECT COUNT(*) From journals_for_messages WHERE m_parent_id IS NOT NULL and user_id = users.id and jour_type = 'Project') as m_score FROM users WHERE users.id = '#{user.id}'")
else
User.find_by_sql("SELECT users.id,(SELECT COUNT(*) From journals_for_messages WHERE m_parent_id IS NOT NULL and user_id = users.id and jour_type = 'Project' and jour_id = '#{project.id}') as m_score FROM users WHERE users.id = '#{user.id}'")
end
end
#更新对帖子的回复数量
def update_replay_for_memo(user,type,project=nil)
option_number = get_option_number(user,type,project)
option_number.replay_for_memo = replay_for_memo_num(user,project)#Message.includes(:author).where("parent_id IS NOT NULL and author_id = #{user.id}").all.count #+ Memo.includes(:author).where("parent_id IS NOT NULL and author_id = #{user.id}").all.count
update_score(option_number)
end
def replay_for_memo_num(user,project=nil)
if project.nil?
#Message.includes(:author).joins(:board).where("#{Message.table_name}.parent_id IS NOT NULL and #{Message.table_name}.author_id = '#{user.id}' and #{Board.table_name}.project_id != -1").all.count
users = Message.find_by_sql("SELECT COUNT(*) as m_count FROM messages JOIN boards on messages.board_id = boards.id WHERE messages.parent_id IS NOT NULL AND messages.author_id = #{user.id} AND boards.project_id != -1")
result = 0
if users.count > 0
result = users.first.m_count
end
result
else
#Message.includes(:author).joins(:board).where("#{Message.table_name}.parent_id IS NOT NULL and #{Message.table_name}.author_id = '#{user.id}' and #{Board.table_name}.project_id = #{project.id}").all.count
users = Message.find_by_sql("SELECT COUNT(*) as m_count FROM messages JOIN boards on messages.board_id = boards.id WHERE messages.parent_id IS NOT NULL AND messages.author_id = #{user.id} AND boards.project_id = #{project.id}")
result = 0
if users.count > 0
result = users.first.m_count
end
result
end
end
def replay_for_memo_score(user,project=nil)
if project.nil?
User.find_by_sql("SELECT users.id,(SELECT COUNT(*) FROM messages JOIN boards on messages.board_id = boards.id WHERE messages.parent_id IS NOT NULL AND messages.author_id = users.id AND boards.project_id != -1) FROM users WHERE users.id = #{user.id}")
else
User.find_by_sql("SELECT users.id,(SELECT COUNT(*) FROM messages JOIN boards on messages.board_id = boards.id WHERE messages.parent_id IS NOT NULL AND messages.author_id = users.id AND boards.project_id = #{project.id}) FROM users WHERE users.id = #{user.id}")
end
end
#更新被关注的人数
def update_follow(user,type)
option_number = get_option_number(user,type)
option_number.follow = follow_num(user)#Watcher.includes(:watchable).where("watchable_type = 'Principal' and watchable_id = '#{user.id}'").count
update_score(option_number)
end
def follow_num(user)
#Watcher.includes(:watchable).where("watchable_type = 'Principal' and watchable_id = '#{user.id}'").count
users = Watcher.find_by_sql("SELECT COUNT(*) as m_count FROM #{Watcher.table_name} WHERE watchable_type = 'Principal' and watchable_id = #{user.id}")
result = 0
if users.count > 0
result = users.first.m_count
end
result
end
def follow_score(user)
User.find_by_sql("SELECT users.id, (SELECT COUNT(*) * 2 FROM #{Watcher.table_name} WHERE watchable_type = 'Principal' and watchable_id = users.id) FROM users WHERE users.id = '#{user.id}'")
end
#更新帖子踩各项数量
def update_tread(user,type,project=nil)
option_number = get_option_number(user,type,project)
tread_nums = tread_num(user,project)
option_number.tread = tread_nums[:tread]
option_number.tread_by_one = tread_nums[:tead_by_one]
option_number.tread_by_two = tread_nums[:tread_by_two]
option_number.tread_by_three = tread_nums[:tread_by_three]
update_score(option_number)
end
def tread_num(user,project=nil)
if project.nil?
result0 = PraiseTread.where("praise_tread_object_type IN ( 'Issue','Message') and praise_or_tread = 0 and user_id = '#{user.id}'").all.count
pts = PraiseTread.where("praise_tread_object_type IN ( 'Issue','Message') and praise_or_tread = 0").all
result = []
result1 = []
result2 = []
pts.each do |pt|
obj = PraiseTread.find_object_by_type_and_id(pt.praise_tread_object_type, pt.praise_tread_object_id)
if obj.nil?
next
end
target_user = obj.author
level = UserLevels.get_level(pt.user)#pt.user.get_level
#project = pt.project
if level == 1 && target_user.id == user.id
result << pt
elsif level == 2 && target_user.id == user.id
result1 << pt
elsif level == 3 && target_user.id == user.id
result2 << pt
end
end
{:tread=>result0,:tead_by_one => result.count,:tread_by_two => result1.count,:tread_by_three =>result2.count}
else
result0 = PraiseTread.where("praise_tread_object_type IN ( 'Issue','Message') and praise_or_tread = 0 and user_id = '#{user.id}'").all.count
pts = PraiseTread.where("praise_tread_object_type IN ( 'Issue','Message') and praise_or_tread = 0").all
result = []
result1 = []
result2 = []
pts.each do |pt|
obj = PraiseTread.find_object_by_type_and_id(pt.praise_tread_object_type, pt.praise_tread_object_id)
if obj.nil? || (pt.praise_tread_object_type == "Issue" && obj.project.nil?) || (pt.praise_tread_object_type == "Message" && obj.board.nil?) || (pt.praise_tread_object_type == "Message" && obj.board.project.nil?)
next
end
if !(pt.praise_tread_object_type == "Issue" && obj.project.id == project.id) && !(pt.praise_tread_object_type == "Message" && obj.board.project.id == project.id)
next
end
target_user = obj.author
level = UserLevels.get_level(pt.user)#pt.user.get_level
#project = pt.project
if level == 1 && target_user.id == user.id
result << pt
elsif level == 2 && target_user.id == user.id
result1 << pt
elsif level == 3 && target_user.id == user.id
result2 << pt
end
end
{:tread=>result0,:tead_by_one => result.count,:tread_by_two => result1.count,:tread_by_three =>result2.count}
end
end
#更新帖子顶数量
def update_praise(user,type,project=nil)
option_number = get_option_number(user,type,project)
praise_nums = praise_num(user,project)
option_number.praise_by_one = praise_nums[:praise_by_one]
option_number.praise_by_two = praise_nums[:praise_by_two]
option_number.praise_by_three = praise_nums[:praise_by_three]
update_score(option_number)
end
def praise_num(user,project=nil)
if !project.nil?
pts = PraiseTread.where("praise_tread_object_type IN ( 'Issue','Message') and praise_or_tread = 1").all
result = []
result1 = []
result2 = []
pts.each do |pt|
obj = PraiseTread.find_object_by_type_and_id(pt.praise_tread_object_type, pt.praise_tread_object_id)
if obj.nil? || (pt.praise_tread_object_type == "Issue" && obj.project.nil?) || (pt.praise_tread_object_type == "Message" && obj.board.nil?) || (pt.praise_tread_object_type == "Message" && obj.board.project.nil?)
next
end
if !(pt.praise_tread_object_type == "Issue" && obj.project.id == project.id) && !(pt.praise_tread_object_type == "Message" && obj.board.project.id == project.id)
next
end
target_user = obj.author
level = UserLevels.get_level(pt.user)#pt.user.get_level
#project = pt.project
if level == 1 && target_user.id == user.id
result << pt
elsif level == 2 && target_user.id == user.id
result1 << pt
elsif level == 3 && target_user.id == user.id
result2 << pt
end
end
{:praise_by_one => result.count,:praise_by_two => result1.count,:praise_by_three => result2.count}
else
pts = PraiseTread.where("praise_tread_object_type IN ( 'Issue','Message') and praise_or_tread = 1").all
result = []
result1 = []
result2 = []
pts.each do |pt|
obj = PraiseTread.find_object_by_type_and_id(pt.praise_tread_object_type, pt.praise_tread_object_id)
if obj.nil?
next
end
#if obj.project.id == -1
# next
#end
target_user = obj.author
level = UserLevels.get_level(pt.user)#pt.user.get_level
project = pt.project
if level == 1 && target_user.id == user.id
result << pt
elsif level == 2 && target_user.id == user.id
result1 << pt
elsif level == 3 && target_user.id == user.id
result2 << pt
end
end
{:praise_by_one => result.count,:praise_by_two => result1.count,:praise_by_three => result2.count}
end
end
#更新提交代码次数
def update_changeset(user,type,project=nil)
option_number = get_option_number(user,type,project)
option_number.changeset = changeset_num(user,project)#Changeset.includes(:user).where("user_id = '#{user.id}'").all.count
update_score(option_number)
end
def changeset_num(user,project=nil)
if project.nil?
#Changeset.includes(:user).where("user_id = '#{user.id}'").all.count
users = Changeset.find_by_sql("SELECT COUNT(*) as m_count FROM #{Changeset.table_name} WHERE user_id = #{user.id}")
result = 0
if users.count > 0
result = users.first.m_count
end
result
else
#Changeset.includes(:user).joins(:repository).where("#{Changeset.table_name}.user_id = '#{user.id}' and #{Repository.table_name}.project_id = #{project.id}").all.count
users = Changeset.find_by_sql("SELECT COUNT(*) as m_count FROM #{Changeset.table_name} JOIN #{Repository.table_name} ON #{Changeset.table_name}.repository_id = #{Repository.table_name}.id WHERE #{Changeset.table_name}.user_id = #{user.id} and #{Repository.table_name}.project_id = #{project.id}")
result = 0
if users.count > 0
result = users.first.m_count
end
result
end
end
#更新文档提交次数
def update_document(user,type,project=nil)
option_number = get_option_number(user,type,project)
option_number.document = document_num(user,project)#Document.includes(:user).where("user_id = '#{user.id}'").all.count
update_score(option_number)
end
def document_num(user,project=nil)
if project.nil?
#Document.includes(:user).where("user_id = '#{user.id}'").all.count
users = Document.find_by_sql("SELECT COUNT(*) as m_count FROM #{Document.table_name} WHERE #{Document.table_name}.user_id = #{user.id}")
result = 0
if users.count > 0
result = users.first.m_count
end
result
else
#Document.includes(:user,:project).where("user_id = '#{user.id}' and project_id = '#{project.id}'").all.count
users = Document.find_by_sql("SELECT COUNT(*) as m_count FROM #{Document.table_name} WHERE #{Document.table_name}.user_id = #{user.id} and #{Document.table_name}.project_id = '#{project.id}'")
result = 0
if users.count > 0
result = users.first.m_count
end
result
end
end
#更新附件提交数量
def update_attachment(user,type,project=nil)
option_number = get_option_number(user,type,project)
option_number.attachment = attachment_num(user,project)#Attachment.includes(:author).where("author_id = '#{user.id}'").all.count
update_score(option_number)
end
def attachment_num(user,project=nil)
if project.nil?
#Attachment.includes(:author,:container).where("author_id = '#{user.id}' and container_type = 'Project'").all.count
users = Attachment.find_by_sql("SELECT COUNT(*) as m_count FROM #{Attachment.table_name} WHERE author_id = '#{user.id}' and container_type = 'Project'")
result = 0
if users.count > 0
result = users.first.m_count
end
result
else
#Attachment.includes(:author,:container).where("author_id = '#{user.id}' and container_type = 'Project' and container_id = #{project.id}").all.count
users = Attachment.find_by_sql("SELECT COUNT(*) as m_count FROM #{Attachment.table_name} WHERE author_id = '#{user.id}' and container_type = 'Project' and container_id = #{project.id}")
result = 0
if users.count > 0
result = users.first.m_count
end
result
end
end
#更新缺陷完成度次数
def update_issue_done_ratio(user,type,project=nil)
option_number = get_option_number(user,type,project)
option_number.issue_done_ratio = issue_done_ratio_num(user,project) #Journal.joins(:details, :user).where("#{JournalDetail.table_name}.prop_key = 'done_ratio' and #{User.table_name}.id = '#{user.id}'").count
update_score(option_number)
end
def issue_done_ratio_num(user,project=nil)
if project.nil?
#Journal.joins(:details, :user).where("#{JournalDetail.table_name}.prop_key = 'done_ratio' and #{User.table_name}.id = '#{user.id}'").count
users = Journal.find_by_sql("SELECT COUNT(*) as m_count FROM #{Journal.table_name} JOIN #{JournalDetail.table_name} ON #{JournalDetail.table_name}.journal_id = #{Journal.table_name}.id WHERE #{JournalDetail.table_name}.prop_key = 'done_ratio' and #{Journal.table_name}.user_id = #{user.id}")
result = 0
if users.count > 0
result = users.first.m_count
end
result
else
#Journal.joins(:issue,:details,:user).where("#{Issue.table_name}.project_id = '#{project.id}' and #{JournalDetail.table_name}.prop_key = 'done_ratio' and #{User.table_name}.id = '#{user.id}'").count
users = Journal.find_by_sql("SELECT COUNT(*) as m_count FROM #{Journal.table_name} JOIN #{JournalDetail.table_name} ON #{JournalDetail.table_name}.journal_id = #{Journal.table_name}.id JOIN issues ON issues.id = journals.journalized_id and journalized_type = 'Issue' WHERE #{JournalDetail.table_name}.prop_key = 'done_ratio' and #{Journal.table_name}.user_id = #{user.id} and #{Issue.table_name}.project_id = '#{project.id}'")
result = 0
if users.count > 0
result = users.first.m_count
end
result
end
end
#更新发布缺陷次数
def update_post_issue(user,type,project=nil)
option_number = get_option_number(user,type,project)
option_number.post_issue = post_issue_num(user,project) #Issue.includes(:author).where("author_id = '#{user.id}'").all.count
update_score(option_number)
end
def post_issue_num(user,project=nil)
if project.nil?
#Issue.includes(:author).where("author_id = '#{user.id}'").all.count
users = Issue.find_by_sql("SELECT COUNT(*) as m_count FROM #{Issue.table_name} WHERE author_id = #{user.id}")
result = 0
if users.count > 0
result = users.first.m_count
end
result
else
#Issue.includes(:author).where("author_id = '#{user.id}' and project_id = '#{project.id}'").all.count
users = Issue.find_by_sql("SELECT COUNT(*) as m_count FROM #{Issue.table_name} WHERE author_id = #{user.id} and project_id = '#{project.id}'")
result = 0
if users.count > 0
result = users.first.m_count
end
result
end
end
#读取项目成员得分
def read_user_project_scores(user,project)
option_num = get_option_number(user,2,project)
option_num.total_score
end
def user_scores(user,type,project=nil)
ooption_num = get_option_number(user,type,project)
update_memo_number(user,type,project)
update_messges_for_issue(user,type,project)
update_issues_status(user,type,project)
update_replay_for_message(user,type,project)
update_replay_for_memo(user,type,project)
update_tread(user,type,project)
update_praise(user,type,project)
update_changeset(user,type,project)
update_document(user,type,project)
update_attachment(user,type,project)
update_issue_done_ratio(user,type,project)
update_post_issue(user,type,project)
if project.nil?
update_follow(user,type)
end
update_score(ooption_num)
ooption_num
end
end

@ -258,4 +258,24 @@ module UsersHelper
end
return result
end
#获取用户参与的公开的课程列表
def user_public_course_list user
membership = user.coursememberships.all#@user.coursememberships.all(:conditions => Course.visible_condition(User.current))
membership.sort! {|older, newer| newer.created_on <=> older.created_on }
memberships = []
membership.collect { |e|
memberships.push(e)
}
## 判断课程是否过期 [需封装]
memberships_doing = []
memberships_done = []
memberships.map { |e|
if course_endTime_timeout?(e.course)
memberships_done.push e
else
memberships_doing.push e
end
}
end
end

@ -1,249 +1,288 @@
# encoding: utf-8
#
# Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module WatchersHelper
def watcher_tag(object, user, options={})
ActiveSupport::Deprecation.warn "#watcher_tag is deprecated and will be removed in Redmine 3.0. Use #watcher_link instead."
watcher_link(object, user)
end
###################modified by liuping, nyan
def watcher_link(objects, user, options=[])
return '' unless user && user.logged?
objects = Array.wrap(objects)
watched = objects.any? {|object| object.watched_by?(user)}
@watch_flag = (objects.first.instance_of?(User) or objects.first.instance_of?(Project) or objects.first.instance_of?(Contest) or (objects.first.instance_of?(Bid)))
css = @watch_flag ? ([watcher_css(objects), watched ? 'icon ' : 'icon '].join(' ') << options[0].to_s) :
([watcher_css(objects), watched ? 'icon icon-fav ' : 'icon icon-fav-off '].join(' ') << options[0].to_s)
text = @watch_flag ?
(watched ? l(:button_unfollow) : l(:button_follow)) : (watched ? l(:button_unwatch) : l(:button_watch))
url = watch_path(
:object_type => objects.first.class.to_s.underscore,
:object_id => (objects.size == 1 ? objects.first.id : objects.map(&:id).sort)
)
method = watched ? 'delete' : 'post'
link_to text, url, :remote => true, :method => method, :class => css
end
############## added by linchun
def new_watcher_link(objects, user, options=[])
return '' unless user && user.logged?
objects = Array.wrap(objects)
watched = objects.any? {|object| object.watched_by?(user)}
@watch_flag = (objects.first.instance_of?(User) or objects.first.instance_of?(Project) or (objects.first.instance_of?(Contest)))
css = @watch_flag ? ([watcher_css(objects), watched ? 'icon ' : 'icon '].join(' ') << options[0].to_s) :
([watcher_css(objects), watched ? 'icon icon-fav ' : 'icon icon-fav-off '].join(' ') << options[0].to_s)
text = @watch_flag ?
(watched ? l(:button_unfollow) : l(:button_follow)) : (watched ? l(:button_unwatch) : l(:button_watch))
url = watch_path(
:object_type => objects.first.class.to_s.underscore,
:object_id => (objects.size == 1 ? objects.first.id : objects.map(&:id).sort)
)
method = watched ? 'delete' : 'post'
link_to text, url, :remote => true, :method => method, :class => css
end
# add by nwb
# 关注课程
def new_course_watcher_link(objects, user, options=[])
return '' unless user && user.logged?
objects = Array.wrap(objects)
watched = objects.any? {|object| object.watched_by?(user)}
@watch_flag = (objects.first.instance_of?(User) or objects.first.instance_of?(Project) or (objects.first.instance_of?(Contest)))
css = @watch_flag ? ([watcher_css(objects), watched ? 'icon ' : 'icon '].join(' ') << options[0].to_s) :
([watcher_css(objects), watched ? 'icon icon-fav ' : 'icon icon-fav-off '].join(' ') << options[0].to_s)
text = @watch_flag ?
(watched ? l(:button_unfollow) : l(:button_follow)) : (watched ? l(:button_unwatch) : l(:button_watch))
url = watch_path(
:object_type => objects.first.class.to_s.underscore,
:object_id => (objects.size == 1 ? objects.first.id : objects.map(&:id).sort)
)
method = watched ? 'delete' : 'post'
link_to text, url, :remote => true, :method => method, :class => css
end
# added by fq, modify nyan
# Somebody may use option params
def join_in_course(course, user, options=[])
return '' unless user && user.logged?
# modify by nwb
# 主讲教师不允许退出课程
return '' if user.id == course.tea_id
joined = user.member_of_course?(course)
text = joined ? l(:label_exit_course) : l(:label_join_course)
url_t = join_path(:object_id => course.id)
url_f = try_join_path(:object_id => course.id)
method = joined ? 'delete' : 'post'
if joined
link_to text, url_t, :remote => true, :method => method, :id => "#{course.id}", :confirm => l(:text_are_you_sure_out), :class => []+options
else
link_to text, url_f, :remote => true, :method => method, :id => "#{course.id}", :class => []+options
end
end
# 用户是否允许加入课程判断
# add by nwb
def join_in_course_for_list(course, user, options=[])
return '' unless user && user.logged?
# modify by nwb
# 主讲教师不允许退出课程
return '' if user.id == course.tea_id
joined = user.member_of_course?(course)
text = joined ? l(:label_exit_course) : l(:label_join_course)
url_t = join_path(:object_id => course.id)
url_f = try_join_path(:object_id => course.id)
method = joined ? 'delete' : 'post'
if joined
link_to text, url_t, :remote => true, :method => method, :id => "#{course.id}", :confirm => l(:text_are_you_sure_out), :class => []+options
else
link_to text, url_f, :remote => true, :method => method, :id => "#{course.id}", :class => []+options
end
end
#added by bai
def join_in_contest(bid, user, options=[])
if bid.reward_type == 2
return '' unless user && user.logged?
joined = user.join_in_contest?(bid)
text = joined ? l(:label_exit_contest) : l(:label_join_contest)
url_t = join_in_contest_path(:id => bid.id)
url_f = try_join_in_contest_path(:id => bid.id)
# url = join_in_contest_path(:id => bid.id)
method = joined ? 'delete' : 'post'
if joined
link_to text, url_t, :remote => true, :method => method, :id => "#{bid.id}", :confirm => l(:text_are_you_sure_out), :class => []+options
else
link_to text, url_f, :remote => true, :method => method, :id => "#{bid.id}", :class => []+options
end
end
end
##new add by linchun
def join_in_contest(contest, user, options=[])
return '' unless user && user.logged?
joined = user.join_in_contest?(contest)
text = joined ? l(:label_exit_contest) : l(:label_join_contest)
url_t = join_in_contest_path(:id => contest.id)
url_f = try_join_in_contest_path(:id => contest.id)
# url = join_in_contest_path(:id => contest.id)
method = joined ? 'delete' : 'post'
if joined
link_to text, url_t, :remote => true, :method => method, :id => "#{contest.id}", :confirm => l(:text_are_you_sure_out), :class => []+options
else
link_to text, url_f, :remote => true, :method => method, :id => "#{contest.id}", :class => []+options
end
end
# liuwanwei 的需求, 新竞赛
# 新路由命名为 competition
def join_in_competition(competition, user)
return '' unless user && user.logged?
joined = JoinInCompetition.where('competition_id = ? AND user_id = ?', competition.id, user.id).count>0
text = joined ? l(:label_exit_contest) : l(:label_join_contest)
url_f = new_join_contests_path(:id => competition.id)
url_t = unjoin_in_contest_contests_path(:id => competition.id)
method = joined ? 'delete' : 'post'
if joined
# 退出竞赛用
link_to text, url_t, :remote => true, :method => method, :id => "#{competition.id}", :confirm => l(:text_are_you_sure_out)
else
# 加入竞赛用
link_to text, url_f, :remote => true, :method => method, :id => "#{competition.id}"
end
end
# Returns the css class used to identify watch links for a given +object+
def watcher_css(objects)
objects = Array.wrap(objects)
id = (objects.size == 1 ? objects.first.id : 'bulk')
"#{objects.first.class.to_s.underscore}-#{id}-watcher"
end
# Returns a comma separated list of users watching the given object
def watchers_list(object)
remove_allowed = User.current.allowed_to?("delete_#{object.class.name.underscore}_watchers".to_sym, object.project)
content = ''.html_safe
lis = object.watcher_users.collect do |user|
s = ''.html_safe
s << avatar(user, :size => "16").to_s
s << link_to_user(user, :class => 'user')
if remove_allowed
url = {:controller => 'watchers',
:action => 'destroy',
:object_type => object.class.to_s.underscore,
:object_id => object.id,
:user_id => user}
s << ' '
s << link_to(image_tag('delete.png'), url,
:remote => true, :method => 'delete', :class => "delete")
end
content << content_tag('li', s, :class => "user-#{user.id}")
end
content.present? ? content_tag('ul', content, :class => 'watchers') : content
end
def watchers_checkboxes(object, users, checked=nil)
users.map do |user|
c = checked.nil? ? object.watched_by?(user) : checked
tag = check_box_tag 'issue[watcher_user_ids][]', user.id, c, :id => nil
content_tag 'label', "#{tag} #{h(user)}".html_safe,
:id => "issue_watcher_user_ids_#{user.id}",
:class => "floating"
end.join.html_safe
end
def applied_css(project)
id = project.id
"#{project.class.to_s.underscore}-#{id}-applied"
end
def applied_link(project, user, options=[])
return '' unless user && user.logged?
applied = project.applied_projects.find_by_user_id(user.id)
text = applied ? l(:label_unapply_project) : l(:label_apply_project)
@applied_flag = project.instance_of?(Project)
css = @applied_flag ? ([applied_css(project), applied ? 'icon ' : 'icon '].join(' ') << options[0].to_s) :
([applied_css(project), applied ? 'icon icon-applied ' : 'icon icon-applied-off '].join(' ') << options[0].to_s)
if applied
appliedid = applied.id
end
url = appliedproject_path(
:id=>appliedid,
:user_id => user.id,
:project_id => project.id
)
method = applied ? 'delete' : 'post'
link_to text, url, :remote => true, :method => method ,:class=>css
end
end
# encoding: utf-8
#
# Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module WatchersHelper
def watcher_tag(object, user, options={})
ActiveSupport::Deprecation.warn "#watcher_tag is deprecated and will be removed in Redmine 3.0. Use #watcher_link instead."
watcher_link(object, user)
end
###################modified by liuping, nyan
def watcher_link(objects, user, options=[])
return '' unless user && user.logged?
objects = Array.wrap(objects)
watched = objects.any? {|object| object.watched_by?(user)}
@watch_flag = (objects.first.instance_of?(User) or objects.first.instance_of?(Project) or objects.first.instance_of?(Contest) or (objects.first.instance_of?(Bid)))
css = @watch_flag ? ([watcher_css(objects), watched ? 'icon ' : 'icon '].join(' ') << options[0].to_s) :
([watcher_css(objects), watched ? 'icon icon-fav ' : 'icon icon-fav-off '].join(' ') << options[0].to_s)
text = @watch_flag ?
(watched ? l(:button_unfollow) : l(:button_follow)) : (watched ? l(:button_unwatch) : l(:button_watch))
url = watch_path(
:object_type => objects.first.class.to_s.underscore,
:object_id => (objects.size == 1 ? objects.first.id : objects.map(&:id).sort)
)
method = watched ? 'delete' : 'post'
link_to text, url, :remote => true, :method => method, :class => css
end
############## added by linchun
def new_watcher_link(objects, user, options=[])
return '' unless user && user.logged?
objects = Array.wrap(objects)
watched = objects.any? {|object| object.watched_by?(user)}
@watch_flag = (objects.first.instance_of?(User) or objects.first.instance_of?(Project) or (objects.first.instance_of?(Contest)))
css = @watch_flag ? ([watcher_css(objects), watched ? 'icon ' : 'icon '].join(' ') << options[0].to_s) :
([watcher_css(objects), watched ? 'icon icon-fav ' : 'icon icon-fav-off '].join(' ') << options[0].to_s)
text = @watch_flag ?
(watched ? l(:button_unfollow) : l(:button_follow)) : (watched ? l(:button_unwatch) : l(:button_watch))
url = watch_path(
:object_type => objects.first.class.to_s.underscore,
:object_id => (objects.size == 1 ? objects.first.id : objects.map(&:id).sort)
)
method = watched ? 'delete' : 'post'
link_to text, url, :remote => true, :method => method, :class => css, :onclick => "location.reload()"
end
# add by nwb
# 关注课程
def new_course_watcher_link(objects, user, options=[])
return '' unless user && user.logged?
objects = Array.wrap(objects)
watched = objects.any? {|object| object.watched_by?(user)}
@watch_flag = (objects.first.instance_of?(User) or objects.first.instance_of?(Project) or (objects.first.instance_of?(Contest)))
css = @watch_flag ? ([watcher_css(objects), watched ? 'icon ' : 'icon '].join(' ') << options[0].to_s) :
([watcher_css(objects), watched ? 'icon icon-fav ' : 'icon icon-fav-off '].join(' ') << options[0].to_s)
text = @watch_flag ?
(watched ? l(:button_unfollow) : l(:button_follow)) : (watched ? l(:button_unwatch) : l(:button_watch))
url = watch_path(
:object_type => objects.first.class.to_s.underscore,
:object_id => (objects.size == 1 ? objects.first.id : objects.map(&:id).sort)
)
method = watched ? 'delete' : 'post'
link_to text, url, :remote => true, :method => method, :class => css
end
# added by fq, modify nyan
# Somebody may use option params
def join_in_course(course, user, options=[])
return '' unless user && user.logged?
# modify by nwb
# 主讲教师不允许退出课程
return '' if user.id == course.tea_id
joined = course.members.map{|m| m.user}.include? user
text = joined ? l(:label_exit_course) : l(:label_new_join)
url = joined ? join_path(:object_id => course.id) : try_join_path(:object_id => course.id)
method = joined ? 'delete' : 'post'
if joined
link_to text, url, :remote => true, :method => method, :id => "#{course.id}", :confirm => l(:text_are_you_sure_out), :class => []+options
else
link_to text, url, :remote => true, :method => method, :id => "#{course.id}", :class => []+options
end
end
def join_in_course_group(coursegroups,group, user, options=[])
return '' unless user && user.logged?
@isjoin = false
coursegroups.each do |g|
g.members.each do |mem|
if mem.user_id == user.id
@isjoin = true
end
end
end
url_t = join_group_path(:object_id => group.id)
url_f = join_group_path(:object_id => group.id)
if @isjoin == true
joined = user.member_of_course_group?(group)
text = l(:label_exit_group)
if joined
link_to text, {:controller => "courses", :action => "join_group", :object_id => "#{group.id}"},
:remote => true, :method => 'delete',
:id => "#{group.id}", :style => "padding: 8px 8px 4px; ",
:confirm => l(:text_are_you_sure_out_group), :class => 'group_in'
end
else
text = l(:label_new_join_group)
form_tag({:controller => "courses", :action => "join_group", :object_id => "#{group.id}"}, :remote => true, :method => 'post') do
submit_tag text, class: "group_in", style: "width: 43px;height: 21px;"
end
end
end
# 用户是否允许加入课程判断
# add by nwb
def join_in_course_for_list(course, user, options=[])
return '' unless user && user.logged?
# modify by nwb
# 主讲教师不允许退出课程
return '' if user.id == course.tea_id
joined = user.member_of_course?(course)
text = joined ? l(:label_exit_course) : l(:label_join_course)
url_t = join_path(:object_id => course.id)
url_f = try_join_path(:object_id => course.id)
method = joined ? 'delete' : 'post'
if joined
link_to text, url_t, :remote => true, :method => method, :id => "#{course.id}", :confirm => l(:text_are_you_sure_out), :class => []+options
else
link_to text, url_f, :remote => true, :method => method, :id => "#{course.id}", :class => []+options
end
end
#added by bai
def join_in_contest(bid, user, options=[])
if bid.reward_type == 2
return '' unless user && user.logged?
joined = user.join_in_contest?(bid)
text = joined ? l(:label_exit_contest) : l(:label_join_contest)
url_t = join_in_contest_path(:id => bid.id)
url_f = try_join_in_contest_path(:id => bid.id)
# url = join_in_contest_path(:id => bid.id)
method = joined ? 'delete' : 'post'
if joined
link_to text, url_t, :remote => true, :method => method, :id => "#{bid.id}", :confirm => l(:text_are_you_sure_out), :class => []+options
else
link_to text, url_f, :remote => true, :method => method, :id => "#{bid.id}", :class => []+options
end
end
end
##new add by linchun
def join_in_contest(contest, user, options=[])
return '' unless user && user.logged?
joined = user.join_in_contest?(contest)
text = joined ? l(:label_exit_contest) : l(:label_join_contest)
url_t = join_in_contest_path(:id => contest.id)
url_f = try_join_in_contest_path(:id => contest.id)
# url = join_in_contest_path(:id => contest.id)
method = joined ? 'delete' : 'post'
if joined
link_to text, url_t, :remote => true, :method => method, :id => "#{contest.id}", :confirm => l(:text_are_you_sure_out), :class => []+options
else
link_to text, url_f, :remote => true, :method => method, :id => "#{contest.id}", :class => []+options
end
end
# liuwanwei 的需求, 新竞赛
# 新路由命名为 competition
def join_in_competition(competition, user)
return '' unless user && user.logged?
joined = JoinInCompetition.where('competition_id = ? AND user_id = ?', competition.id, user.id).count>0
text = joined ? l(:label_exit_contest) : l(:label_join_contest)
url_f = new_join_contests_path(:id => competition.id)
url_t = unjoin_in_contest_contests_path(:id => competition.id)
method = joined ? 'delete' : 'post'
if joined
# 退出竞赛用
link_to text, url_t, :remote => true, :method => method, :id => "#{competition.id}", :confirm => l(:text_are_you_sure_out)
else
# 加入竞赛用
link_to text, url_f, :remote => true, :method => method, :id => "#{competition.id}"
end
end
# Returns the css class used to identify watch links for a given +object+
def watcher_css(objects)
objects = Array.wrap(objects)
id = (objects.size == 1 ? objects.first.id : 'bulk')
"#{objects.first.class.to_s.underscore}-#{id}-watcher"
end
# Returns a comma separated list of users watching the given object
def watchers_list(object)
remove_allowed = User.current.allowed_to?("delete_#{object.class.name.underscore}_watchers".to_sym, object.project)
content = ''.html_safe
lis = object.watcher_users.collect do |user|
s = ''.html_safe
s << avatar(user, :size => "16").to_s
s << link_to_user(user, :class => 'user')
if remove_allowed
url = {:controller => 'watchers',
:action => 'destroy',
:object_type => object.class.to_s.underscore,
:object_id => object.id,
:user_id => user}
s << ' '
s << link_to(image_tag('delete.png'), url,
:remote => true, :method => 'delete', :class => "delete")
end
content << content_tag('li', s, :class => "user-#{user.id}")
end
content.present? ? content_tag('ul', content, :class => 'watchers') : content
end
def watchers_checkboxes(object, users, checked=nil)
if users.nil?
else
users.map do |user|
c = checked.nil? ? object.watched_by?(user) : checked
tag = check_box_tag 'issue[watcher_user_ids][]', user.id, c, :id => nil
content_tag 'label', "#{tag} #{h(user)}".html_safe,
:id => "issue_watcher_user_ids_#{user.id}",
:class => "floating"
end.join.html_safe
end
end
def applied_css(project)
id = project.id
"#{project.class.to_s.underscore}-#{id}-applied"
end
def applied_link(project, user, options=[])
return '' unless user && user.logged?
applied = project.applied_projects.find_by_user_id(user.id)
text = applied ? l(:label_unapply_project) : l(:label_apply_project)
@applied_flag = project.instance_of?(Project)
css = @applied_flag ? ([applied_css(project), applied ? 'icon ' : 'icon '].join(' ') << options[0].to_s) :
([applied_css(project), applied ? 'icon icon-applied ' : 'icon icon-applied-off '].join(' ') << options[0].to_s)
if applied
appliedid = applied.id
end
url = appliedproject_path(
:id=>appliedid,
:user_id => user.id,
:project_id => project.id
)
method = applied ? 'delete' : 'post'
link_to text, url, :remote => true, :method => method ,:class=>css
end
def exit_project_link(project)
link_to(l(:label_exit_project),exit_cur_project_path(project.id),
:remote => true, :confirm => l(:lable_sure_exit_project) )
end
end

File diff suppressed because it is too large Load Diff

@ -40,4 +40,14 @@ module WikiHelper
link_to(h(parent.pretty_title), {:controller => 'wiki', :action => 'show', :id => parent.title, :project_id => parent.project, :version => nil})
})
end
def wiki_content_format wiki
text = wiki.text.html_safe
text = parse_non_pre_blocks(text, wiki, text) do |text|
[:parse_inline_attachments, :parse_wiki_links, :parse_redmine_links].each do |method_name|
send method_name, text, project, wiki, attr, only_path, options
end
end
text
end
end

@ -1,7 +1,8 @@
class Activity < ActiveRecord::Base
attr_accessible :act_id, :act_type, :user_id
belongs_to :act, :polymorphic => true
belongs_to :user
validates_presence_of :act_id, :act_type, :user_id
end
class Activity < ActiveRecord::Base
attr_accessible :act_id, :act_type, :user_id
belongs_to :act, :polymorphic => true
belongs_to :user
validates :act_id, presence: true
validates :act_type, presence: true
validates :user_id, presence: true
end

File diff suppressed because it is too large Load Diff

@ -1,92 +1,90 @@
# Redmine - project management software
# Copyright (C) 2006-2013 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.
# Generic exception for when the AuthSource can not be reached
# (eg. can not connect to the LDAP)
class AuthSourceException < Exception; end
class AuthSourceTimeoutException < AuthSourceException; end
class AuthSource < ActiveRecord::Base
include Redmine::SubclassFactory
include Redmine::Ciphering
has_many :users
validates_presence_of :name
validates_uniqueness_of :name
validates_length_of :name, :maximum => 60
def authenticate(login, password)
end
def test_connection
end
def auth_method_name
"Abstract"
end
def account_password
read_ciphered_attribute(:account_password)
end
def account_password=(arg)
write_ciphered_attribute(:account_password, arg)
end
def searchable?
false
end
def self.search(q)
results = []
AuthSource.all.each do |source|
begin
if source.searchable?
results += source.search(q)
end
rescue AuthSourceException => e
logger.error "Error while searching users in #{source.name}: #{e.message}"
end
end
results
end
def allow_password_changes?
self.class.allow_password_changes?
end
# Does this auth source backend allow password changes?
def self.allow_password_changes?
false
end
# Try to authenticate a user not yet registered against available sources
def self.authenticate(login, password)
AuthSource.where(:onthefly_register => true).all.each do |source|
begin
logger.debug "Authenticating '#{login}' against '#{source.name}'" if logger && logger.debug?
attrs = source.authenticate(login, password)
rescue => e
logger.error "Error during authentication: #{e.message}"
attrs = nil
end
return attrs if attrs
end
return nil
end
end
# Redmine - project management software
# Copyright (C) 2006-2013 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.
# Generic exception for when the AuthSource can not be reached
# (eg. can not connect to the LDAP)
class AuthSourceException < Exception; end
class AuthSourceTimeoutException < AuthSourceException; end
class AuthSource < ActiveRecord::Base
include Redmine::SubclassFactory
include Redmine::Ciphering
has_many :users
validates :name, presence: true, uniqueness: true, length: {maximum: 60}
def authenticate(login, password)
end
def test_connection
end
def auth_method_name
"Abstract"
end
def account_password
read_ciphered_attribute(:account_password)
end
def account_password=(arg)
write_ciphered_attribute(:account_password, arg)
end
def searchable?
false
end
def self.search(q)
results = []
AuthSource.all.each do |source|
begin
if source.searchable?
results += source.search(q)
end
rescue AuthSourceException => e
logger.error "Error while searching users in #{source.name}: #{e.message}"
end
end
results
end
def allow_password_changes?
self.class.allow_password_changes?
end
# Does this auth source backend allow password changes?
def self.allow_password_changes?
false
end
# Try to authenticate a user not yet registered against available sources
def self.authenticate(login, password)
AuthSource.where(:onthefly_register => true).all.each do |source|
begin
logger.debug "Authenticating '#{login}' against '#{source.name}'" if logger && logger.debug?
attrs = source.authenticate(login, password)
rescue => e
logger.error "Error during authentication: #{e.message}"
attrs = nil
end
return attrs if attrs
end
return nil
end
end

@ -1,200 +1,206 @@
# Redmine - project management software
# Copyright (C) 2006-2013 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 'net/ldap'
require 'net/ldap/dn'
require 'timeout'
class AuthSourceLdap < AuthSource
validates_presence_of :host, :port, :attr_login
validates_length_of :name, :host, :maximum => 60, :allow_nil => true
validates_length_of :account, :account_password, :base_dn, :filter, :maximum => 255, :allow_blank => true
validates_length_of :attr_login, :attr_firstname, :attr_lastname, :attr_mail, :maximum => 30, :allow_nil => true
validates_numericality_of :port, :only_integer => true
validates_numericality_of :timeout, :only_integer => true, :allow_blank => true
validate :validate_filter
before_validation :strip_ldap_attributes
def initialize(attributes=nil, *args)
super
self.port = 389 if self.port == 0
end
def authenticate(login, password)
return nil if login.blank? || password.blank?
with_timeout do
attrs = get_user_dn(login, password)
if attrs && attrs[:dn] && authenticate_dn(attrs[:dn], password)
logger.debug "Authentication successful for '#{login}'" if logger && logger.debug?
return attrs.except(:dn)
end
end
rescue Net::LDAP::LdapError => e
raise AuthSourceException.new(e.message)
end
# test the connection to the LDAP
def test_connection
with_timeout do
ldap_con = initialize_ldap_con(self.account, self.account_password)
ldap_con.open { }
end
rescue Net::LDAP::LdapError => e
raise AuthSourceException.new(e.message)
end
def auth_method_name
"LDAP"
end
# Returns true if this source can be searched for users
def searchable?
!account.to_s.include?("$login") && %w(login firstname lastname mail).all? {|a| send("attr_#{a}?")}
end
# Searches the source for users and returns an array of results
def search(q)
q = q.to_s.strip
return [] unless searchable? && q.present?
results = []
search_filter = base_filter & Net::LDAP::Filter.begins(self.attr_login, q)
ldap_con = initialize_ldap_con(self.account, self.account_password)
ldap_con.search(:base => self.base_dn,
:filter => search_filter,
:attributes => ['dn', self.attr_login, self.attr_firstname, self.attr_lastname, self.attr_mail],
:size => 10) do |entry|
attrs = get_user_attributes_from_ldap_entry(entry)
attrs[:login] = AuthSourceLdap.get_attr(entry, self.attr_login)
results << attrs
end
results
rescue Net::LDAP::LdapError => e
raise AuthSourceException.new(e.message)
end
private
def with_timeout(&block)
timeout = self.timeout
timeout = 20 unless timeout && timeout > 0
Timeout.timeout(timeout) do
return yield
end
rescue Timeout::Error => e
raise AuthSourceTimeoutException.new(e.message)
end
def ldap_filter
if filter.present?
Net::LDAP::Filter.construct(filter)
end
rescue Net::LDAP::LdapError
nil
end
def base_filter
filter = Net::LDAP::Filter.eq("objectClass", "*")
if f = ldap_filter
filter = filter & f
end
filter
end
def validate_filter
if filter.present? && ldap_filter.nil?
errors.add(:filter, :invalid)
end
end
def strip_ldap_attributes
[:attr_login, :attr_firstname, :attr_lastname, :attr_mail].each do |attr|
write_attribute(attr, read_attribute(attr).strip) unless read_attribute(attr).nil?
end
end
def initialize_ldap_con(ldap_user, ldap_password)
options = { :host => self.host,
:port => self.port,
:encryption => (self.tls ? :simple_tls : nil)
}
options.merge!(:auth => { :method => :simple, :username => ldap_user, :password => ldap_password }) unless ldap_user.blank? && ldap_password.blank?
Net::LDAP.new options
end
def get_user_attributes_from_ldap_entry(entry)
{
:dn => entry.dn,
:firstname => AuthSourceLdap.get_attr(entry, self.attr_firstname),
:lastname => AuthSourceLdap.get_attr(entry, self.attr_lastname),
:mail => AuthSourceLdap.get_attr(entry, self.attr_mail),
:auth_source_id => self.id
}
end
# Return the attributes needed for the LDAP search. It will only
# include the user attributes if on-the-fly registration is enabled
def search_attributes
if onthefly_register?
['dn', self.attr_firstname, self.attr_lastname, self.attr_mail]
else
['dn']
end
end
# Check if a DN (user record) authenticates with the password
def authenticate_dn(dn, password)
if dn.present? && password.present?
initialize_ldap_con(dn, password).bind
end
end
# Get the user's dn and any attributes for them, given their login
def get_user_dn(login, password)
ldap_con = nil
if self.account && self.account.include?("$login")
ldap_con = initialize_ldap_con(self.account.sub("$login", Net::LDAP::DN.escape(login)), password)
else
ldap_con = initialize_ldap_con(self.account, self.account_password)
end
attrs = {}
search_filter = base_filter & Net::LDAP::Filter.eq(self.attr_login, login)
ldap_con.search( :base => self.base_dn,
:filter => search_filter,
:attributes=> search_attributes) do |entry|
if onthefly_register?
attrs = get_user_attributes_from_ldap_entry(entry)
else
attrs = {:dn => entry.dn}
end
logger.debug "DN found for #{login}: #{attrs[:dn]}" if logger && logger.debug?
end
attrs
end
def self.get_attr(entry, attr_name)
if !attr_name.blank?
entry[attr_name].is_a?(Array) ? entry[attr_name].first : entry[attr_name]
end
end
end
# Redmine - project management software
# Copyright (C) 2006-2013 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 'net/ldap'
require 'net/ldap/dn'
require 'timeout'
class AuthSourceLdap < AuthSource
validates :host, presence: true, length: {maximum: 60, allow_nil: true}
validates :port, presence: true, numericality: {only_integer: true}
validates :attr_login, presence: true
validates :name, length: {maximum: 60, allow_nil: true}
validates :account, length: {maximum: 255, allow_blank: true}
validates :account_password, length: {maximum: 255, allow_blank: true}
validates :base_dn, length: {maximum: 255, allow_blank: true}
validates :filter, length: {maximum: 255, allow_blank: true}
validates :attr_login, length: {maximum: 30, allow_nil: true}
validates :attr_firstname, length: {maximum: 30, allow_nil: true}
validates :attr_lastname, length: {maximum: 30, allow_nil: true}
validates :attr_mail, length: {maximum: 30, allow_nil: true}
validates :timeout, numericality: { only_integer: true, allow_blank: true}
validate :validate_filter
before_validation :strip_ldap_attributes
def initialize(attributes=nil, *args)
super
self.port = 389 if self.port == 0
end
def authenticate(login, password)
return nil if login.blank? || password.blank?
with_timeout do
attrs = get_user_dn(login, password)
if attrs && attrs[:dn] && authenticate_dn(attrs[:dn], password)
logger.debug "Authentication successful for '#{login}'" if logger && logger.debug?
return attrs.except(:dn)
end
end
rescue Net::LDAP::LdapError => e
raise AuthSourceException.new(e.message)
end
# test the connection to the LDAP
def test_connection
with_timeout do
ldap_con = initialize_ldap_con(self.account, self.account_password)
ldap_con.open { }
end
rescue Net::LDAP::LdapError => e
raise AuthSourceException.new(e.message)
end
def auth_method_name
"LDAP"
end
# Returns true if this source can be searched for users
def searchable?
!account.to_s.include?("$login") && %w(login firstname lastname mail).all? {|a| send("attr_#{a}?")}
end
# Searches the source for users and returns an array of results
def search(q)
q = q.to_s.strip
return [] unless searchable? && q.present?
results = []
search_filter = base_filter & Net::LDAP::Filter.begins(self.attr_login, q)
ldap_con = initialize_ldap_con(self.account, self.account_password)
ldap_con.search(:base => self.base_dn,
:filter => search_filter,
:attributes => ['dn', self.attr_login, self.attr_firstname, self.attr_lastname, self.attr_mail],
:size => 10) do |entry|
attrs = get_user_attributes_from_ldap_entry(entry)
attrs[:login] = AuthSourceLdap.get_attr(entry, self.attr_login)
results << attrs
end
results
rescue Net::LDAP::LdapError => e
raise AuthSourceException.new(e.message)
end
private
def with_timeout(&block)
timeout = self.timeout
timeout = 20 unless timeout && timeout > 0
Timeout.timeout(timeout) do
return yield
end
rescue Timeout::Error => e
raise AuthSourceTimeoutException.new(e.message)
end
def ldap_filter
if filter.present?
Net::LDAP::Filter.construct(filter)
end
rescue Net::LDAP::LdapError
nil
end
def base_filter
filter = Net::LDAP::Filter.eq("objectClass", "*")
if f = ldap_filter
filter = filter & f
end
filter
end
def validate_filter
if filter.present? && ldap_filter.nil?
errors.add(:filter, :invalid)
end
end
def strip_ldap_attributes
[:attr_login, :attr_firstname, :attr_lastname, :attr_mail].each do |attr|
write_attribute(attr, read_attribute(attr).strip) unless read_attribute(attr).nil?
end
end
def initialize_ldap_con(ldap_user, ldap_password)
options = { :host => self.host,
:port => self.port,
:encryption => (self.tls ? :simple_tls : nil)
}
options.merge!(:auth => { :method => :simple, :username => ldap_user, :password => ldap_password }) unless ldap_user.blank? && ldap_password.blank?
Net::LDAP.new options
end
def get_user_attributes_from_ldap_entry(entry)
{
:dn => entry.dn,
:firstname => AuthSourceLdap.get_attr(entry, self.attr_firstname),
:lastname => AuthSourceLdap.get_attr(entry, self.attr_lastname),
:mail => AuthSourceLdap.get_attr(entry, self.attr_mail),
:auth_source_id => self.id
}
end
# Return the attributes needed for the LDAP search. It will only
# include the user attributes if on-the-fly registration is enabled
def search_attributes
if onthefly_register?
['dn', self.attr_firstname, self.attr_lastname, self.attr_mail]
else
['dn']
end
end
# Check if a DN (user record) authenticates with the password
def authenticate_dn(dn, password)
if dn.present? && password.present?
initialize_ldap_con(dn, password).bind
end
end
# Get the user's dn and any attributes for them, given their login
def get_user_dn(login, password)
ldap_con = nil
if self.account && self.account.include?("$login")
ldap_con = initialize_ldap_con(self.account.sub("$login", Net::LDAP::DN.escape(login)), password)
else
ldap_con = initialize_ldap_con(self.account, self.account_password)
end
attrs = {}
search_filter = base_filter & Net::LDAP::Filter.eq(self.attr_login, login)
ldap_con.search( :base => self.base_dn,
:filter => search_filter,
:attributes=> search_attributes) do |entry|
if onthefly_register?
attrs = get_user_attributes_from_ldap_entry(entry)
else
attrs = {:dn => entry.dn}
end
logger.debug "DN found for #{login}: #{attrs[:dn]}" if logger && logger.debug?
end
attrs
end
def self.get_attr(entry, attr_name)
if !attr_name.blank?
entry[attr_name].is_a?(Array) ? entry[attr_name].first : entry[attr_name]
end
end
end

@ -28,6 +28,7 @@ class Bid < ActiveRecord::Base
has_many :homework_for_courses, :dependent => :destroy
has_many :courses, :through => :homework_for_courses, :source => :course
has_many :homeworks, :class_name => 'HomeworkAttach', :dependent => :destroy
has_many :homework_evaluations, :through => :homeworks
has_many :join_in_contests, :dependent => :destroy
has_many :praise_tread, as: :praise_tread_object, dependent: :destroy
# has_many :fork_homework, :class_name => 'Bid', :conditions => "#{Bid.table_name}.parent_id = #{id}"
@ -36,17 +37,15 @@ class Bid < ActiveRecord::Base
acts_as_attachable
NAME_LENGTH_LIMIT = 60
DESCRIPTION_LENGTH_LIMIT = 250
validates_length_of :name, :maximum => NAME_LENGTH_LIMIT
validates_length_of :description, :maximum => DESCRIPTION_LENGTH_LIMIT
validates_presence_of :author_id, :name, :deadline
# validates_presence_of :deadline, :message => 'test'
# validates_format_of :deadline, :with =>
validates_format_of :deadline, :with => /^[\d]{4}[-][\d]{1,2}[-][\d]{1,2}$/
validates_format_of :budget, :with => /^(\d+)$|^(\d+).([0-9]{2})|^(\d+).([0-9]{1})$/,
:if => Proc.new { |p| p.reward_type == 1 }
validates_format_of :budget, :with => /^(\d+)$|^(\d+).([0-9]{1})$/, :if => Proc.new { |p| p.reward_type == 3 }
DESCRIPTION_LENGTH_LIMIT = 3000
validates :name, length: {maximum: NAME_LENGTH_LIMIT}, presence: true
validates :description, length: {maximum: DESCRIPTION_LENGTH_LIMIT}
validates :author_id, presence: true
validates :deadline, presence: true, format: {:with => /^[\d]{4}[-][\d]{1,2}[-][\d]{1,2}$/}
validates :name, length: {maximum: NAME_LENGTH_LIMIT}
validates :budget, format: { with: ->(p) { if p.reward_type == 1 then /^(\d+)$|^(\d+).([0-9]{2})|^(\d+).([0-9]{1})$/
elsif p.reward_type == 3 then /^(\d+)$|^(\d+).([0-9]{1})$/ end } }
validate :validate_user
validate :validate_reward_type
after_create :act_as_activity

@ -1,59 +1,59 @@
## fq
class BidingProject < ActiveRecord::Base
attr_accessible :bid_id, :project_id, :user_id, :description,:reward
belongs_to :bid
belongs_to :project
belongs_to :user
DESCRIPTION_LENGTH_LIMIT = 500
validates_length_of :description, :maximum => DESCRIPTION_LENGTH_LIMIT
validates_presence_of :user_id, :bid_id, :project_id
validate :validate_user
validate :validate_bid
validate :validate_project
validates_uniqueness_of :bid_id, :scope => :project_id
def self.cerate_bidding(bid_id, project_id, description = nil)
self.create(:user_id => User.current.id, :bid_id => bid_id,
:project_id => project_id, :description => description)
end
# used to update the reward ,the value varies from 0,1,2,3,4,5
# added by william
def update_reward(which)
self.update_attribute(:reward,which)
end
# return the reward,the value is a type of string
# added by william
def get_reward
self.reward
end
def cancel_bidding
unless self.nil?
if User.current.id == self.user_id
self.destroy
end
end
end
private
def validate_user
errors.add :user_id, :invalid if user.nil? || !user.active?
end
def validate_bid
errors.add :bid_id, :invalid if bid.nil?
end
def validate_project
errors.add :project_id, :invalid if project.nil?
end
end
## fq
class BidingProject < ActiveRecord::Base
attr_accessible :bid_id, :project_id, :user_id, :description,:reward
belongs_to :bid
belongs_to :project
belongs_to :user
DESCRIPTION_LENGTH_LIMIT = 500
validates :description, length: {maximum: DESCRIPTION_LENGTH_LIMIT}
validates :user_id, presence: true
validates :bid_id, presence: true, :uniqueness => { :scope => :project_id}
validates :project_id, presence: true
validate :validate_user
validate :validate_bid
validate :validate_project
def self.cerate_bidding(bid_id, project_id, description = nil)
self.create(:user_id => User.current.id, :bid_id => bid_id,
:project_id => project_id, :description => description)
end
# used to update the reward ,the value varies from 0,1,2,3,4,5
# added by william
def update_reward(which)
self.update_attribute(:reward,which)
end
# return the reward,the value is a type of string
# added by william
def get_reward
self.reward
end
def cancel_bidding
unless self.nil?
if User.current.id == self.user_id
self.destroy
end
end
end
private
def validate_user
errors.add :user_id, :invalid if user.nil? || !user.active?
end
def validate_bid
errors.add :bid_id, :invalid if bid.nil?
end
def validate_project
errors.add :project_id, :invalid if project.nil?
end
end

@ -1,91 +1,90 @@
# Redmine - project management software
# Copyright (C) 2006-2013 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 Board < ActiveRecord::Base
include Redmine::SafeAttributes
belongs_to :project
belongs_to :course
has_many :topics, :class_name => 'Message', :conditions => "#{Message.table_name}.parent_id IS NULL", :order => "#{Message.table_name}.created_on DESC"
has_many :messages, :dependent => :destroy, :order => "#{Message.table_name}.created_on DESC"
belongs_to :last_message, :class_name => 'Message', :foreign_key => :last_message_id
acts_as_tree :dependent => :nullify
acts_as_list :scope => '(project_id = #{project_id} AND parent_id #{parent_id ? "= #{parent_id}" : "IS NULL"})'
acts_as_watchable
validates_presence_of :name, :description
validates_length_of :name, :maximum => 30
validates_length_of :description, :maximum => 255
validate :validate_board
scope :visible, lambda {|*args|
includes(:project).where(Project.allowed_to_condition(args.shift || User.current, :view_messages, *args))
}
safe_attributes 'name', 'description', 'parent_id', 'move_to'
def visible?(user=User.current)
!user.nil? && user.allowed_to?(:view_messages, project)
end
def reload(*args)
@valid_parents = nil
super
end
def to_s
name
end
def valid_parents
@valid_parents ||= project.boards - self_and_descendants
end
def reset_counters!
self.class.reset_counters!(id)
end
# Updates topics_count, messages_count and last_message_id attributes for +board_id+
def self.reset_counters!(board_id)
board_id = board_id.to_i
update_all("topics_count = (SELECT COUNT(*) FROM #{Message.table_name} WHERE board_id=#{board_id} AND parent_id IS NULL)," +
" messages_count = (SELECT COUNT(*) FROM #{Message.table_name} WHERE board_id=#{board_id})," +
" last_message_id = (SELECT MAX(id) FROM #{Message.table_name} WHERE board_id=#{board_id})",
["id = ?", board_id])
end
def self.board_tree(boards, parent_id=nil, level=0)
tree = []
boards.select {|board| board.parent_id == parent_id}.sort_by(&:position).each do |board|
tree << [board, level]
tree += board_tree(boards, board.id, level+1)
end
if block_given?
tree.each do |board, level|
yield board, level
end
end
tree
end
protected
def validate_board
if parent_id && parent_id_changed?
errors.add(:parent_id, :invalid) unless valid_parents.include?(parent)
end
end
end
# Redmine - project management software
# Copyright (C) 2006-2013 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 Board < ActiveRecord::Base
include Redmine::SafeAttributes
belongs_to :project
belongs_to :course
has_many :topics, :class_name => 'Message', :conditions => "#{Message.table_name}.parent_id IS NULL", :order => "#{Message.table_name}.created_on DESC"
has_many :messages, :dependent => :destroy, :order => "#{Message.table_name}.created_on DESC"
belongs_to :last_message, :class_name => 'Message', :foreign_key => :last_message_id
acts_as_tree :dependent => :nullify
acts_as_list :scope => '(project_id = #{project_id} AND parent_id #{parent_id ? "= #{parent_id}" : "IS NULL"})'
acts_as_watchable
validates :name, presence: true, length: {maximum: 30}
validates :description, presence: true, length: {maximum: 255}
validate :validate_board
scope :visible, lambda {|*args|
includes(:project).where(Project.allowed_to_condition(args.shift || User.current, :view_messages, *args))
}
safe_attributes 'name', 'description', 'parent_id', 'move_to'
def visible?(user=User.current)
!user.nil? && user.allowed_to?(:view_messages, project)
end
def reload(*args)
@valid_parents = nil
super
end
def to_s
name
end
def valid_parents
@valid_parents ||= project.boards - self_and_descendants
end
def reset_counters!
self.class.reset_counters!(id)
end
# Updates topics_count, messages_count and last_message_id attributes for +board_id+
def self.reset_counters!(board_id)
board_id = board_id.to_i
update_all("topics_count = (SELECT COUNT(*) FROM #{Message.table_name} WHERE board_id=#{board_id} AND parent_id IS NULL)," +
" messages_count = (SELECT COUNT(*) FROM #{Message.table_name} WHERE board_id=#{board_id})," +
" last_message_id = (SELECT MAX(id) FROM #{Message.table_name} WHERE board_id=#{board_id})",
["id = ?", board_id])
end
def self.board_tree(boards, parent_id=nil, level=0)
tree = []
boards.select {|board| board.parent_id == parent_id}.sort_by(&:position).each do |board|
tree << [board, level]
tree += board_tree(boards, board.id, level+1)
end
if block_given?
tree.each do |board, level|
yield board, level
end
end
tree
end
protected
def validate_board
if parent_id && parent_id_changed?
errors.add(:parent_id, :invalid) unless valid_parents.include?(parent)
end
end
end

@ -1,12 +1,11 @@
class BugToOsp < ActiveRecord::Base
# attr_accessible :title, :body
belongs_to :open_source_project, :foreign_key => "osp_id"
belongs_to :bug, :class_name => 'RelativeMemo', :foreign_key => "relative_memo_id"
validates_presence_of :osp_id, :relative_memo_id
scope :visible, lambda {|*args|
nil
}
end
class BugToOsp < ActiveRecord::Base
# attr_accessible :title, :body
belongs_to :open_source_project, :foreign_key => "osp_id"
belongs_to :bug, :class_name => 'RelativeMemo', :foreign_key => "relative_memo_id"
validates :osp_id, presence: true
validates :relative_memo_id, presence: true
scope :visible, lambda {|*args|
nil
}
end

@ -1,37 +1,39 @@
# Redmine - project management software
# Copyright (C) 2006-2013 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 Change < ActiveRecord::Base
belongs_to :changeset
validates_presence_of :changeset_id, :action, :path
before_save :init_path
before_validation :replace_invalid_utf8_of_path
def relative_path
changeset.repository.relative_path(path)
end
def replace_invalid_utf8_of_path
self.path = Redmine::CodesetUtil.replace_invalid_utf8(self.path)
self.from_path = Redmine::CodesetUtil.replace_invalid_utf8(self.from_path)
end
def init_path
self.path ||= ""
end
end
# Redmine - project management software
# Copyright (C) 2006-2013 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 Change < ActiveRecord::Base
belongs_to :changeset
validates :changeset_id, presence: true
validates :action, presence: true
validates :path, presence: true
before_save :init_path
before_validation :replace_invalid_utf8_of_path
def relative_path
changeset.repository.relative_path(path)
end
def replace_invalid_utf8_of_path
self.path = Redmine::CodesetUtil.replace_invalid_utf8(self.path)
self.from_path = Redmine::CodesetUtil.replace_invalid_utf8(self.from_path)
end
def init_path
self.path ||= ""
end
end

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

Loading…
Cancel
Save