diff --git a/.gitignore b/.gitignore
index 73b76dc34..ffa4a1bc7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,7 @@
*.swp
/config/database.yml
/config/configuration.yml
+/config/additional_environment.rb
/files/*
/log/*
/public/tmp/*
@@ -26,3 +27,4 @@ vendor/cache
/files
/public/images/avatars
/public/files
+/tags
diff --git a/Gemfile b/Gemfile
index 976184793..13b410d9d 100644
--- a/Gemfile
+++ b/Gemfile
@@ -6,6 +6,8 @@ unless RUBY_PLATFORM =~ /w32/
gem 'iconv'
end
+gem "mysql2", "= 0.3.18"
+gem 'redis-rails'
gem 'rubyzip'
gem 'delayed_job_active_record'#, :group => :production
gem 'daemons'
@@ -21,9 +23,6 @@ gem "builder", "3.0.0"
gem 'acts-as-taggable-on', '2.4.1'
gem 'spreadsheet'
gem 'ruby-ole'
-#gem 'email_verifier', path: 'lib/email_verifier'
-gem 'rufus-scheduler'
-#gem 'dalli', path: 'lib/dalli-2.7.2'
gem 'rails_kindeditor',path:'lib/rails_kindeditor'
group :development do
gem 'grape-swagger'
@@ -83,56 +82,13 @@ group :openid do
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.18", :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`
diff --git a/app/api/mobile/api.rb b/app/api/mobile/api.rb
index 4724b0bc0..a59b01776 100644
--- a/app/api/mobile/api.rb
+++ b/app/api/mobile/api.rb
@@ -1,49 +1,49 @@
-module Mobile
- require_relative 'middleware/error_handler'
- require_relative 'apis/auth'
- require_relative 'apis/users'
- require_relative 'apis/courses'
- require_relative 'apis/watches'
- require_relative 'apis/upgrade'
- require_relative 'apis/homeworks'
- require_relative 'apis/comments'
- class API < Grape::API
- version 'v1', using: :path
- format :json
- content_type :json, "application/json;charset=UTF-8"
- use Mobile::Middleware::ErrorHandler
-
- helpers do
- def logger
- API.logger
- end
-
- def authenticate!
- raise('Unauthorized. Invalid or expired token.') unless current_user
- end
-
- def current_user
- token = ApiKey.where(access_token: params[:token]).first
- if token && !token.expired?
- @current_user = User.find(token.user_id)
- else
- nil
- end
- end
- end
-
- mount Apis::Auth
- mount Apis::Users
- mount Apis::Courses
- mount Apis::Watches
- mount Apis::Upgrade
- mount Apis::Homeworks
- mount Apis::Comments
-
- #add_swagger_documentation ({api_version: 'v1', base_path: 'http://u06.shellinfo.cn/trustie/api'})
- #add_swagger_documentation ({api_version: 'v1', base_path: '/api'}) if Rails.env.development?
-
- end
-end
-
-
+module Mobile
+ require_relative 'middleware/error_handler'
+ require_relative 'apis/auth'
+ require_relative 'apis/users'
+ require_relative 'apis/courses'
+ require_relative 'apis/watches'
+ require_relative 'apis/upgrade'
+ require_relative 'apis/homeworks'
+ require_relative 'apis/comments'
+ class API < Grape::API
+ version 'v1', using: :path
+ format :json
+ content_type :json, "application/json;charset=UTF-8"
+ use Mobile::Middleware::ErrorHandler
+
+ helpers do
+ def logger
+ API.logger
+ end
+
+ def authenticate!
+ raise('Unauthorized. Invalid or expired token.') unless current_user
+ end
+
+ def current_user
+ token = ApiKey.where(access_token: params[:token]).first
+ if token && !token.expired?
+ @current_user = User.find(token.user_id)
+ else
+ nil
+ end
+ end
+ end
+
+ mount Apis::Auth
+ mount Apis::Users
+ mount Apis::Courses
+ mount Apis::Watches
+ mount Apis::Upgrade
+ mount Apis::Homeworks
+ mount Apis::Comments
+
+ #add_swagger_documentation ({api_version: 'v1', base_path: 'http://u06.shellinfo.cn/trustie/api'})
+ #add_swagger_documentation ({api_version: 'v1', base_path: '/api'}) if Rails.env.development?
+
+ end
+end
+
+
diff --git a/app/api/mobile/apis/courses.rb b/app/api/mobile/apis/courses.rb
index 08c7adf10..0d0c4651f 100644
--- a/app/api/mobile/apis/courses.rb
+++ b/app/api/mobile/apis/courses.rb
@@ -228,6 +228,32 @@ module Mobile
present :status, 0
end
+ desc '课程课件'
+ params do
+ requires :token, type: String
+ requires :course_id,type: Integer,desc: '课程id'
+ optional :name,type:String,desc:'课件名称可能包含的字符'
+ end
+ get ":course_id/attachments" do
+ cs = CoursesService.new
+ count = cs.course_attachments params
+ present :data, count, with: Mobile::Entities::Attachment
+ present :status, 0
+ end
+
+ desc '课程学生'
+ params do
+ requires :token,type:String
+ requires :course_id,type:Integer,desc: '课程id'
+ optional :name,type:String,desc:'学生的姓名或者昵称或者学号可能包含的字符'
+ end
+ get ":course_id/members" do
+ cs = CoursesService.new
+ count = cs.course_members params
+ present :data, count, with: Mobile::Entities::Member
+ present :status, 0
+ end
+
end
end
end
diff --git a/app/api/mobile/entities/attachment.rb b/app/api/mobile/entities/attachment.rb
index 510db89be..080b24558 100644
--- a/app/api/mobile/entities/attachment.rb
+++ b/app/api/mobile/entities/attachment.rb
@@ -16,8 +16,11 @@ module Mobile
end
end
end
+ attachment_expose :id
attachment_expose :filename
attachment_expose :description
+ attachment_expose :downloads
+ attachment_expose :quotes
end
end
end
\ No newline at end of file
diff --git a/app/api/mobile/entities/course.rb b/app/api/mobile/entities/course.rb
index 520f73384..50812b349 100644
--- a/app/api/mobile/entities/course.rb
+++ b/app/api/mobile/entities/course.rb
@@ -46,6 +46,7 @@ module Mobile
course_expose :term
course_expose :time
course_expose :updated_at
+ course_expose :course_student_num
expose :teacher, using: Mobile::Entities::User do |c, opt|
if c.is_a? ::Course
c.teacher
diff --git a/app/api/mobile/entities/member.rb b/app/api/mobile/entities/member.rb
new file mode 100644
index 000000000..837ec788a
--- /dev/null
+++ b/app/api/mobile/entities/member.rb
@@ -0,0 +1,33 @@
+module Mobile
+ module Entities
+ class Member < Grape::Entity
+ include ApplicationHelper
+ include ApiHelper
+ def self.member_expose(f)
+ expose f do |u,opt|
+ if u.is_a?(Hash) && u.key?(f)
+ u[f]
+ elsif u.is_a?(::Member)
+ if u.respond_to?(f)
+ u.send(f)
+ else
+ case f
+ when :student_id
+ u.user.user_extensions.student_id
+ end
+ end
+ end
+
+ end
+ end
+
+ expose :user, using: Mobile::Entities::User do |c, opt|
+ if c.is_a?(::Member)
+ c.user
+ end
+ end
+ member_expose :student_id
+ member_expose :score
+ end
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/account_controller.rb b/app/controllers/account_controller.rb
index f8d0f5dd1..22db3d5b4 100644
--- a/app/controllers/account_controller.rb
+++ b/app/controllers/account_controller.rb
@@ -332,7 +332,7 @@ class AccountController < ApplicationController
token = Token.create(:user => user, :action => 'autologin')
cookie_options = {
:value => token.value,
- :expires => 1.year.from_now,
+ :expires => 7.days.from_now,
:path => (Redmine::Configuration['autologin_cookie_path'] || '/'),
:secure => (Redmine::Configuration['autologin_cookie_secure'] ? true : false),
:httponly => true
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 47251cf85..741af2aee 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -894,7 +894,6 @@ class ApplicationController < ActionController::Base
set_autologin_cookie(user)
end
call_hook(:controller_account_success_authentication_after, {:user => user })
-
-
end
+
end
diff --git a/app/controllers/applied_project_controller.rb b/app/controllers/applied_project_controller.rb
index 8e70ed32c..b9824976b 100644
--- a/app/controllers/applied_project_controller.rb
+++ b/app/controllers/applied_project_controller.rb
@@ -1,59 +1,59 @@
-class AppliedProjectController < ApplicationController
-
- #申请加入项目
- def applied_join_project
- @user_id = params[:user_id]
- @project = Project.find_by_id(params[:project_id])
- if params[:project_join]
- if @project
- user = User.find @user_id
- if user.member_of?(@project)
- @status = 3
- else
- @applieds = AppliedProject.where("user_id = ? and project_id = ?", params[:user_id],params[:project_id])
- if @applieds.count == 0
- appliedproject = AppliedProject.create(:user_id => params[:user_id], :project_id => params[:project_id])
- Mailer.run.applied_project(appliedproject)
- @status = 2
- else
- @status = 1
- end
- end
- else
- @status = 0
- end
- respond_to do |format|
- format.js
- end
- return
- end
-
- @applieds = AppliedProject.where("user_id = ? and project_id = ?", params[:user_id],params[:project_id])
- if @applieds.count == 0
- appliedproject = AppliedProject.create(:user_id => params[:user_id], :project_id => params[:project_id])
- Mailer.run.applied_project(appliedproject)
- end
-
- #redirect_to project_path(params[:project_id])
- #redirect_to_referer_or {render :text => ( 'applied success.'), :layout => true}
- respond_to do |format|
- format.html { redirect_to_referer_or {render :text => (watching ? 'Watcher added.' : 'Watcher removed.'), :layout => true}}
- format.js { render :partial => 'set_applied'}
- end
- end
-
- #取消申请
- def unapplied_join_project
- @project = Project.find(params[:project_id])
- #@applied = AppliedProject.find(params[:id])
- #@applied.destroy
-
- AppliedProject.deleteappiled(params[:user_id], params[:project_id])
-
- respond_to do |format|
- format.html { redirect_to_referer_or {render :text => (watching ? 'Watcher added.' : 'Watcher removed.'), :layout => true}}
- format.js { render :partial => 'set_applied' }
- end
- end
-
-end
+class AppliedProjectController < ApplicationController
+
+ #申请加入项目
+ def applied_join_project
+ @user_id = params[:user_id]
+ @project = Project.find_by_id(params[:project_id])
+ if params[:project_join]
+ if @project
+ user = User.find @user_id
+ if user.member_of?(@project)
+ @status = 3
+ else
+ @applieds = AppliedProject.where("user_id = ? and project_id = ?", params[:user_id],params[:project_id])
+ if @applieds.count == 0
+ appliedproject = AppliedProject.create(:user_id => params[:user_id], :project_id => params[:project_id])
+ Mailer.run.applied_project(appliedproject)
+ @status = 2
+ else
+ @status = 1
+ end
+ end
+ else
+ @status = 0
+ end
+ respond_to do |format|
+ format.js
+ end
+ return
+ end
+
+ @applieds = AppliedProject.where("user_id = ? and project_id = ?", params[:user_id],params[:project_id])
+ if @applieds.count == 0
+ appliedproject = AppliedProject.create(:user_id => params[:user_id], :project_id => params[:project_id])
+ Mailer.run.applied_project(appliedproject)
+ end
+
+ #redirect_to project_path(params[:project_id])
+ #redirect_to_referer_or {render :text => ( 'applied success.'), :layout => true}
+ respond_to do |format|
+ format.html { redirect_to_referer_or {render :text => (watching ? 'Watcher added.' : 'Watcher removed.'), :layout => true}}
+ format.js { render :partial => 'set_applied'}
+ end
+ end
+
+ #取消申请
+ def unapplied_join_project
+ @project = Project.find(params[:project_id])
+ #@applied = AppliedProject.find(params[:id])
+ #@applied.destroy
+
+ AppliedProject.deleteappiled(params[:user_id], params[:project_id])
+
+ respond_to do |format|
+ format.html { redirect_to_referer_or {render :text => (watching ? 'Watcher added.' : 'Watcher removed.'), :layout => true}}
+ format.js { render :partial => 'set_applied' }
+ end
+ end
+
+end
diff --git a/app/controllers/bids_controller.rb b/app/controllers/bids_controller.rb
index d38846ea0..c98df27d3 100644
--- a/app/controllers/bids_controller.rb
+++ b/app/controllers/bids_controller.rb
@@ -490,7 +490,7 @@ class BidsController < ApplicationController
(SELECT stars FROM seems_rateable_rates WHERE rateable_type = 'HomeworkAttach' AND rateable_id = homework_attaches.id AND is_teacher_score = 1 AND stars IS NOT NULL ORDER BY updated_at DESC limit 0,1) AS t_score,
(SELECT AVG(stars) FROM seems_rateable_rates WHERE rateable_type = 'HomeworkAttach' AND rateable_id = homework_attaches.id AND is_teacher_score = 0) AS s_score
FROM homework_attaches WHERE bid_id = #{@bid.id} ORDER BY s_score DESC,created_at ASC) AS table1
- WHERE table1.t_score IS NULL OR table1.t_score = 0")
+ WHERE table1.t_score IS NULL")
@not_batch_homework = true
@cur_type = 1
else
@@ -506,7 +506,8 @@ class BidsController < ApplicationController
end
@cur_page = params[:page] || 1
- @homework_list = paginateHelper all_homework_list,10
+ # @homework_list = paginateHelper all_homework_list,10
+ @homework_list = all_homework_list
@jours_count = @bid.journals_for_messages.where('m_parent_id IS NULL').count
if params[:student_id].present?
@temp = []
@@ -792,7 +793,7 @@ class BidsController < ApplicationController
@bid.is_evaluation = params[:bid][:is_evaluation]
@bid.proportion = params[:bid][:proportion]
@bid.evaluation_num = params[:bid][:evaluation_num]
- @bid.open_anonymous_evaluation = params[:bid][:open_anonymous_evaluation]
+ params[:bid][:open_anonymous_evaluation] ? @bid.open_anonymous_evaluation = 1 : @bid.open_anonymous_evaluation = 0
@bid.reward_type = 3
# @bid.budget = params[:bid][:budget]
@bid.deadline = params[:bid][:deadline]
diff --git a/app/controllers/boards_controller.rb b/app/controllers/boards_controller.rb
index bdbbb8e37..f6ec09b2a 100644
--- a/app/controllers/boards_controller.rb
+++ b/app/controllers/boards_controller.rb
@@ -42,12 +42,19 @@ class BoardsController < ApplicationController
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
+ if @course.boards.empty?
+ @board = @course.boards.build
+ @board.name = " #{l(:label_borad_course) }"
+ @board.description = @course.name.to_s
+ @board.project_id = -1
+ if @board.save
+ @boards = @course.boards.includes(:last_message => :author).all
+ end
end
- render :layout => 'base_courses'
+ unless @course.boards.empty?
+ @board = @course.boards.first
+ end
+ show and return
else
render_403
end
@@ -65,7 +72,7 @@ class BoardsController < ApplicationController
'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_count = @board ? @board.topics.count : 0
if @project
@topic_pages = Paginator.new @topic_count, per_page_option, params['page']
@topics = @board.topics.
@@ -77,14 +84,13 @@ class BoardsController < ApplicationController
preload(:author, {:last_reply => :author}).
all
elsif @course
- board_topics = @board.topics.
- reorder("#{Message.table_name}.sticky DESC").
+ board_topics = @board ? @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
+ all : []
@topics = paginateHelper board_topics,10
end
diff --git a/app/controllers/courses_controller.rb b/app/controllers/courses_controller.rb
index c0e99d546..a1e547a84 100644
--- a/app/controllers/courses_controller.rb
+++ b/app/controllers/courses_controller.rb
@@ -191,8 +191,9 @@ class CoursesController < ApplicationController
results = searchmember_by_name(student_homework_score(@group.id,0,0,"desc"), q)
end
@is_remote = true
- @result_count = results.count
- @results = paginateHelper results, 10
+ #@result_count = results.count
+ #@results = paginateHelper results, 10
+ @results = results
@search_name = q
end
@@ -315,13 +316,15 @@ class CoursesController < ApplicationController
when '1'
@subPage_title = l :label_teacher_list
@all_members = searchTeacherAndAssistant(@course)
- @members = paginateHelper @all_members, 10
+ #@members = paginateHelper @all_members, 10
+ @members = @all_members
when '2'
@subPage_title = l :label_student_list
page = params[:page].nil? ? 0 : (params['page'].to_i - 1)
@all_members = student_homework_score(0,page, 10,"desc")
# @all_members = @course.members
- @members = paginateHelper_for_members @all_members, 10
+ # @members = paginateHelper_for_members @all_members, 10
+ @members = @all_members
end
respond_to do |format|
if params[:page]
@@ -705,7 +708,7 @@ class CoursesController < ApplicationController
#"show_course_journals_for_messages" => true,
"show_bids" => true,
"show_homeworks" => true,
- #"show_polls" => true
+ "show_polls" => true
}
@date_to ||= Date.today + 1
@date_from = (@date_to - @days) > @course.created_at.to_date ? (@date_to - @days) : @course.created_at.to_date
@@ -877,7 +880,7 @@ class CoursesController < ApplicationController
students_for_courses.course_id = #{@course.id} and members.user_id = students_for_courses.student_id AND
members.user_id NOT IN (SELECT homework_attaches.user_id FROM homework_attaches WHERE homework_attaches.bid_id in (SELECT bid_id FROM homework_for_courses WHERE course_id = #{@course.id} )
)
- GROUP BY members.user_id ORDER BY score #{score_sort_by} limit #{start_from}, #{nums}"
+ GROUP BY members.user_id ORDER BY score #{score_sort_by} " #limit #{start_from}, #{nums}"
end
else
diff --git a/app/controllers/files_controller.rb b/app/controllers/files_controller.rb
index 8b1c8ba32..69e7105aa 100644
--- a/app/controllers/files_controller.rb
+++ b/app/controllers/files_controller.rb
@@ -145,10 +145,14 @@ class FilesController < ApplicationController
ids += version.id.to_s
end
end
- resultSet = Attachment.where("((attachments.container_type = 'Project' And attachments.container_id = '#{project.id}') OR (container_type = 'Version' AND container_id IN (#{ids}))) 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
+ if ids.blank?
+ resultSet = Attachment.where("attachments.container_type = 'Project' And attachments.container_id = '#{project.id}' AND filename LIKE :like ", like: "%#{keywords}%").
+ reorder(sort)
+ else
+ resultSet = Attachment.where("((attachments.container_type = 'Project' And attachments.container_id = '#{project.id}') OR (container_type = 'Version' AND container_id IN (#{ids}))) AND filename LIKE :like ", like: "%#{keywords}%").
+ reorder(sort)
+ end
+ end
def find_public_attache keywords,sort = ""
# StoresController#search 将每条文件都查出来,再次进行判断过滤。---> resultSet.to_a.map
diff --git a/app/controllers/homework_attach_controller.rb b/app/controllers/homework_attach_controller.rb
index a589ce144..f6b044c63 100644
--- a/app/controllers/homework_attach_controller.rb
+++ b/app/controllers/homework_attach_controller.rb
@@ -51,7 +51,7 @@ class HomeworkAttachController < ApplicationController
order_by = "created_at #{direction}"
end
all_homework_list = HomeworkAttach.eager_load(:attachments,:user,:rate_averages).find_by_sql("SELECT * FROM (SELECT homework_attaches.*,
- (SELECT stars FROM seems_rateable_rates WHERE rateable_type = 'HomeworkAttach' AND rateable_id = homework_attaches.id AND is_teacher_score = 1 AND stars IS NOT NULL AND stars > 0 ORDER BY updated_at DESC limit 0,1) AS t_score,
+ (SELECT stars FROM seems_rateable_rates WHERE rateable_type = 'HomeworkAttach' AND rateable_id = homework_attaches.id AND is_teacher_score = 1 AND stars IS NOT NULL ORDER BY updated_at DESC limit 0,1) AS t_score,
(SELECT AVG(stars) FROM seems_rateable_rates WHERE rateable_type = 'HomeworkAttach' AND rateable_id = homework_attaches.id AND is_teacher_score = 0) AS s_score
FROM homework_attaches WHERE bid_id = #{@bid.id}
ORDER BY #{order_by}) AS table1
@@ -59,7 +59,8 @@ class HomeworkAttachController < ApplicationController
all_homework_list = search_homework_member(all_homework_list,@search_name.to_s.downcase) if @search_name
@cur_page = params[:page] || 1
@cur_type = 2
- @homework_list = paginateHelper all_homework_list,10
+ # @homework_list = paginateHelper all_homework_list,10
+ @homework_list = all_homework_list
@direction = direction == 'asc'? 'desc' : 'asc'
respond_to do |format|
format.js
@@ -93,7 +94,8 @@ class HomeworkAttachController < ApplicationController
all_homework_list = search_homework_member(all_homework_list,@search_name.to_s.downcase) if @search_name
@cur_page = params[:page] || 1
@cur_type = 3
- @homework_list = paginateHelper all_homework_list,10
+ # @homework_list = paginateHelper all_homework_list,10
+ @homework_list = all_homework_list
@direction = direction == 'asc'? 'desc' : 'asc'
respond_to do |format|
format.js
@@ -110,7 +112,8 @@ class HomeworkAttachController < ApplicationController
all_homework_list = get_student_batch_homework_list @bid,User.current
@cur_page = params[:page] || 1
@cur_type = 4
- @homework_list = paginateHelper all_homework_list,10
+ # @homework_list = paginateHelper all_homework_list,10
+ @homework_list = all_homework_list
respond_to do |format|
format.js
end
@@ -134,7 +137,8 @@ class HomeworkAttachController < ApplicationController
WHERE homework_attaches.bid_id = #{@bid.id} AND homework_users.user_id = #{User.current.id}")
end
@cur_page = params[:page] || 1
- @homework_list = paginateHelper all_homework_list,10
+ # @homework_list = paginateHelper all_homework_list,10
+ @homework_list = all_homework_list
respond_to do |format|
format.js
end
@@ -440,14 +444,16 @@ class HomeworkAttachController < ApplicationController
homework = @homework
is_teacher = @is_teacher ? 1 : 0
#保存评分@homework.rate(@m_score.to_i,User.current.id,:quality, (@is_teacher ? 1 : 0))
- if @m_score
+ @is_comprehensive_evaluation = @is_teacher ? 1 : (@is_anonymous_comments ? 2 : 3) #判断当前评论是老师评论?匿评?留言
+ if @is_teacher || @is_anonymous_comments
+ @m_score ||= 0
rate = @homework.rates(:quality).where(:rater_id => User.current.id, :is_teacher_score => is_teacher).first
if rate
rate.stars = @m_score
- rate.save!
else
- @homework.rates(:quality).new(:stars => @m_score, :rater_id => User.current.id, :is_teacher_score => is_teacher).save!
+ rate = @homework.rates(:quality).new(:stars => @m_score, :rater_id => User.current.id, :is_teacher_score => is_teacher)
end
+ rate.save!
if homework.is_teacher_score == 0
if is_teacher == 1
@@ -465,12 +471,26 @@ class HomeworkAttachController < ApplicationController
end
end
homework.save!
- end
+ end
#保存评论
- @is_comprehensive_evaluation = @is_teacher ? 1 : (@is_anonymous_comments ? 2 : 3) #判断当前评论是老师评论?匿评?留言
- if params[:new_form] && params[:new_form][:user_message] && params[:new_form][:user_message] != "" #有没有留言
- @homework.addjours User.current.id, params[:new_form][:user_message],0,@is_comprehensive_evaluation
+ if params[:new_form] && params[:new_form][:user_message] #有没有留言
+ jour = @homework.journals_for_messages.where("is_comprehensive_evaluation = 1 and user_id = #{User.current.id}").order("created_on DESC").first
+ if params[:new_form][:user_message] == ""
+ if @is_teacher
+ unless jour
+ jour = @homework.addjours User.current.id, "",0,@is_comprehensive_evaluation
+ end
+ end
+ else
+ jour = @homework.addjours User.current.id, params[:new_form][:user_message],0,@is_comprehensive_evaluation
+ end
+ end
+
+ if jour
+ jour.save_attachments(params[:attachments])
+ render_attachment_warning_if_needed(jour)
+ jour.save
end
@teacher_stars = @stars_reates.where("is_teacher_score = 1") #老师评分列表
@@ -483,7 +503,7 @@ class HomeworkAttachController < ApplicationController
get_not_batch_homework_list params[:cur_sort] || "s_socre",params[:cur_direction] || "desc",@homework.bid_id
elsif @cur_type == "2" #老师已批列表
@result_homework = HomeworkAttach.find_by_sql("SELECT homework_attaches.*,
- (SELECT stars FROM seems_rateable_rates WHERE rateable_type = 'HomeworkAttach' AND rateable_id = homework_attaches.id AND is_teacher_score = 1 AND stars IS NOT NULL AND stars > 0 ORDER BY updated_at DESC limit 0,1) AS t_score,
+ (SELECT stars FROM seems_rateable_rates WHERE rateable_type = 'HomeworkAttach' AND rateable_id = homework_attaches.id AND is_teacher_score = 1 AND stars IS NOT NULL ORDER BY updated_at DESC limit 0,1) AS t_score,
(SELECT AVG(stars) FROM seems_rateable_rates WHERE rateable_type = 'HomeworkAttach' AND rateable_id = homework_attaches.id AND is_teacher_score = 0) AS s_score
FROM homework_attaches WHERE id = #{@homework.id}").first
elsif @cur_type == "3" #全部作业列表
@@ -610,9 +630,10 @@ class HomeworkAttachController < ApplicationController
(SELECT AVG(stars) FROM seems_rateable_rates WHERE rateable_type = 'HomeworkAttach' AND rateable_id = homework_attaches.id AND is_teacher_score = 0) AS s_score
FROM homework_attaches WHERE bid_id = #{bid_id}
ORDER BY #{order_by}) AS table1
- WHERE table1.t_score IS NULL OR table1.t_score = 0 ")
+ WHERE table1.t_score IS NULL ")
@all_homework_list = search_homework_member(@all_homework_list,@search_name.to_s.downcase) if @search_name
- @homework_list = paginateHelper @all_homework_list,10
+ # @homework_list = paginateHelper @all_homework_list,10
+ @homework_list = @all_homework_list
end
#获取指定作业的所有成员
diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb
index 790718e5d..12ee4bc3b 100644
--- a/app/controllers/issues_controller.rb
+++ b/app/controllers/issues_controller.rb
@@ -75,7 +75,11 @@ class IssuesController < ApplicationController
else
@limit = 10#per_page_option
end
-
+ @assign_to_id = params[:assigned_to_id]
+ @author_id = params[:author_id]
+ @priority_id = params[:priority_id]
+ @status_id = params[:status_id]
+ @subject = params[:subject]
@issue_count = @query.issue_count
@issue_pages = Paginator.new @issue_count, @limit, params['page']
@offset ||= @issue_pages.offset
@@ -95,6 +99,7 @@ class IssuesController < ApplicationController
format.api {
Issue.load_visible_relations(@issues) if include_in_api_response?('relations')
}
+ # format.json { render :json => @issues.map { |issue| issue.to_json}} #:json => @issues.map { |issue| issue.to_json}
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') }
diff --git a/app/controllers/members_controller.rb b/app/controllers/members_controller.rb
index fc243741a..6271a6832 100644
--- a/app/controllers/members_controller.rb
+++ b/app/controllers/members_controller.rb
@@ -60,8 +60,12 @@ class MembersController < ApplicationController
user_ids.each do |user_id|
AppliedProject.deleteappiled(user_id, @project.id)
end
+ @succes_message = "拒绝成功"
end
end
+ respond_to do |format|
+ format.js
+ end
else
#modify by nwb
#更改课程成员逻辑
@@ -117,9 +121,14 @@ class MembersController < ApplicationController
format.html { redirect_to invite_members_project_url(@project) }
end
else
+ unless members.present? && members.all? {|m| m.valid? }
+ @project_error_message = members.empty? ? l(:label_user_role_null) :members.collect {|m| m.errors.full_messages}.flatten.uniq.join(', ')
+ else
+ @succes_message = "添加成功"
+ end
respond_to do |format|
format.html { redirect_to_settings_in_projects }
- format.js { @members = members; @applied_members = applied_members; }
+ format.js
format.api {
@member = members.first
if @member.valid?
@@ -184,6 +193,8 @@ class MembersController < ApplicationController
end # end of params[:refusal_button]
+
+
end
def update
diff --git a/app/controllers/messages_controller.rb b/app/controllers/messages_controller.rb
index 436418430..bab5dfb4c 100644
--- a/app/controllers/messages_controller.rb
+++ b/app/controllers/messages_controller.rb
@@ -93,7 +93,15 @@ class MessagesController < ApplicationController
end
call_hook(:controller_messages_new_after_save, { :params => params, :message => @message})
render_attachment_warning_if_needed(@message)
- redirect_to board_message_url(@board, @message)
+ if params[:is_board]
+ if @project
+ redirect_to project_boards_path(@project)
+ elsif @course
+ redirect_to course_boards_path(@course)
+ end
+ else
+ redirect_to board_message_url(@board, @message)
+ end
else
layout_file = @project ? 'base_projects' : 'base_courses'
render :action => 'new', :layout => layout_file
@@ -131,9 +139,16 @@ class MessagesController < ApplicationController
render_attachment_warning_if_needed(@reply)
else
#render file: 'messages#show', layout: 'base_courses'
+ end
+ if params[:is_board]
+ if @project
+ redirect_to project_boards_path(@project)
+ elsif @course
+ redirect_to course_boards_path(@course)
+ end
+ else
+ redirect_to board_message_url(@board, @topic, :r => @reply)
end
- redirect_to board_message_url(@board, @topic, :r => @reply)
-
end
# Edit a message
@@ -172,16 +187,20 @@ class MessagesController < ApplicationController
@message.destroy
# modify by nwb
if @project
- if @message.parent
- redirect_to board_message_url(@board, @message.parent, :r => r)
- else
+ if params[:is_board]
redirect_to project_boards_url(@project)
+ else
+ redirect_to board_message_url(@board, @topic, :r => @reply)
end
elsif @course
- if @message.parent
- redirect_to board_message_url(@board, @message.parent, :r => r)
+ if params[:is_board]
+ redirect_to course_boards_url(@course)
else
- redirect_to course_board_url(@course, @board)
+ if @message.parent
+ redirect_to board_message_url(@board, @message.parent, :r => r)
+ else
+ redirect_to course_board_url(@course, @board)
+ end
end
end
end
diff --git a/app/controllers/my_controller.rb b/app/controllers/my_controller.rb
index 7ff015fbc..d42a750a1 100644
--- a/app/controllers/my_controller.rb
+++ b/app/controllers/my_controller.rb
@@ -20,7 +20,7 @@ class MyController < ApplicationController
# edit
before_filter :auth_login1, :only => [:account]
#
- before_filter :require_login
+ before_filter :require_login, except: [:change_mail_notification]
helper :issues
helper :users
@@ -75,6 +75,19 @@ class MyController < ApplicationController
end
end
+ def change_mail_notification
+ token = params[:token]
+ user = try_to_autologin1
+ if user
+ user.mail_notification = params[:mail_notification]
+ user.save
+ flash[:notice] = l(:notice_mail_notification_updated)
+ redirect_to my_account_url
+ else
+ redirect_to signin_url
+ end
+ end
+
# Edit user's account
def account
@user = User.current
diff --git a/app/controllers/news_controller.rb b/app/controllers/news_controller.rb
index d41491349..f71a77ca7 100644
--- a/app/controllers/news_controller.rb
+++ b/app/controllers/news_controller.rb
@@ -152,6 +152,9 @@ class NewsController < ApplicationController
end
def edit
+ if @course
+ render :layout => "base_courses"
+ end
end
def update
diff --git a/app/controllers/poll_controller.rb b/app/controllers/poll_controller.rb
index b897d039a..32ec3dad2 100644
--- a/app/controllers/poll_controller.rb
+++ b/app/controllers/poll_controller.rb
@@ -29,7 +29,7 @@ class PollController < ApplicationController
end
#已提交问卷的用户不能再访问该界面
if has_commit_poll?(@poll.id,User.current.id) && (!User.current.admin?)
- render_403
+ redirect_to poll_index_url(:polls_type => "Course", :polls_group_id => @course.id)
else
@can_edit_poll = (!has_commit_poll?(@poll.id,User.current.id)) || User.current.admin?
@percent = get_percent(@poll,User.current)
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 8ed9fcfef..96807d2dc 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -27,15 +27,7 @@ class ProjectsController < ApplicationController
menu_item :feedback, :only => :feedback
menu_item :share, :only => :share
- before_filter :find_project, :except => [ :index, :search,:list, :new, :create, :copy, :statistics, :new_join,
- :course, :enterprise_course, :course_enterprise,:view_homework_attaches]
- before_filter :authorize, :only => [:show, :settings, :edit, :sort_project_members, :update, :modules, :close,
- :reopen,:view_homework_attaches,:course]
before_filter :find_project, :except => [ :index, :search,:list, :new, :create, :copy, :statistics, :new_join, :course, :enterprise_course, :course_enterprise,:view_homework_attaches,:join_project]
- # before_filter :authorize, :except => [:new_join, :new_homework, :homework, :statistics, :search, :watcherlist, :index, :list, :new, :create, :copy, :archive, :unarchive, :destroy, :member, :focus, :file,
- # :statistics, :feedback, :course, :enterprise_course, :course_enterprise, :project_respond, :share,
- # :show_projects_score, :issue_score_index, :news_score_index, :file_score_index, :code_submit_score_index, :projects_topic_score_index]
- #此条勿删 课程相关权限 ,:new_homework,:homework,:feedback,,:member
before_filter :authorize, :only => [:show, :settings, :edit, :sort_project_members, :update, :modules, :close, :reopen,:view_homework_attaches,:course]
before_filter :authorize_global, :only => [:new, :create,:view_homework_attaches]
before_filter :require_admin, :only => [ :copy, :archive, :unarchive, :destroy, :calendar]
@@ -181,6 +173,7 @@ class ProjectsController < ApplicationController
@project.safe_attributes = params[:project]
@project.organization_id = params[:organization_id]
@project.user_id = User.current.id
+ @project.project_new_type = 1
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
@@ -250,18 +243,13 @@ class ProjectsController < ApplicationController
# Author lizanle
# Description 项目动态展示方法,删除了不必要的代码
def show
-
- # 试图跳转到请求的按钮
- if params[:login]
- login = params[:login]
- login = login.sub(/%40/,'@')
- mail = params[:login]
- password = params[:password]
- us = UsersService.new
- user = us.register_auto(login,mail, password)
+ # params[:login]为邮箱邀请用户加入,主要功能:
+ # 1、自动注册
+ # 2、加入项目、创建角色
+ # 3、用户得分
+ if params[:email]
+ user = User.find_by_mail(params[:email].to_s)
Member.create(:role_ids => [4], :user_id => user.id,:project_id => @project.id)
- UserGrade.create(:user_id => user.id, :project_id => @project.id)
- User.current = user unless User.current.nil?
end
if params[:jump] && redirect_to_project_menu_item(@project, params[:jump])
return
@@ -331,14 +319,46 @@ class ProjectsController < ApplicationController
@member ||= @project.members.new
@trackers = Tracker.sorted.all
@wiki ||= @project.wiki
+ @select_tab = params[:tab]
+
+ # 处理从新建版本库返回来的错误信息
+ if !params[:repository_error_message].to_s.blank?
+ html = ""
+ errors = params[:repository_error_message].flatten
+ errors.each do |error|
+ # 版本库路径为空的错误信息不予提示
+ if(error!=l(:label_repository_path_not_null))
+ html << error << ";"
+ end
+ end
+ if params[:repository] == "pswd_is_null"
+ html << l(:label_password_not_null)
+ end
+ flash[:error] = html if !html.to_s.blank?
+ end
+ scm = params[:repository_scm] || (Redmine::Scm::Base.all & Setting.enabled_scm).first
+ @repository = Repository.factory(scm)
+ @repository.is_default = @project.repository.nil?
+ @repository.project = @project
+
end
+ # 两种情况:1、系统外用户;2、系统内用户 (通过邮件判定)
def send_mail_to_member
if !params[:mail].blank? && User.find_by_mail(params[:mail].to_s).nil?
email = params[:mail]
Mailer.run.send_invite_in_project(email, @project, User.current)
@is_zhuce =false
flash[:notice] = l(:notice_email_sent, :value => email)
+ elsif !User.find_by_mail(params[:mail].to_s).nil?
+ user = User.find_by_mail(params[:mail].to_s)
+ if !user.member_of?(@project)
+ email = params[:mail]
+ Mailer.run.request_member_to_project(email, @project, User.current)
+ flash[:notice] = l(:notice_email_sent, :value => email)
+ else
+ flash[:error] = l(:label_member_of_project, :value => email)
+ end
else
flash[:error] = l(:notice_registed_error, :value => email)
@is_zhuce = true
@@ -347,6 +367,7 @@ class ProjectsController < ApplicationController
format.html{redirect_to invite_members_by_mail_project_url(@project)}
end
end
+
#发送邮件邀请新用户
def invite_members_by_mail
if User.current.member_of?(@project) || User.current.admin?
@@ -379,7 +400,7 @@ class ProjectsController < ApplicationController
# include CoursesHelper
def member
## 有角色参数的才是课程,没有的就是项目
- @render_file = 'member_list'
+ @render_file = 'project_member_list'
# 判断是否课程
if @project.project_type == Project::ProjectType_course
@teachers= searchTeacherAndAssistant(@project)
@@ -455,22 +476,10 @@ class ProjectsController < ApplicationController
def update
@project.safe_attributes = params[:project]
@project.organization_id = params[:organization_id]
- #@project.dts_test = params[:project][:dts_test]
+ params[:project][:is_public] ? @project.is_public = 1 : @project.is_public = 0
+ params[:project][:hidden_repo] ? @project.hidden_repo = 1 : @project.hidden_repo = 0
if validate_parent_id && @project.save
- @course = Course.find_by_extra(@project.identifier)
- unless @course.nil?
- @course.password = params[:project][:course][:password]
- # added by bai
- @course.term = params[:term]
- @course.time = params[:time]
- @course.setup_time = params[:setup_time]
- @course.endup_time = params[:endup_time]
- @course.class_period = params[:class_period]
- # end
- @course.save
- end
@project.set_allowed_parent!(params[:project]['parent_id']) if params[:project].has_key?('parent_id')
-
if params[:project][:is_public] == '0'
project_status = ProjectStatus.find_by_project_id(@project.id)
project_status.destroy if project_status
@@ -618,6 +627,17 @@ class ProjectsController < ApplicationController
end
end
+ #朋友圈、科研组、开发组之间的切换
+ def change_project_type
+ @project.project_new_type = params[:project_type]
+ if @project.save
+ message = @project.project_new_type
+ else
+ message = "0"
+ end
+ render :json => message
+ end
+
private
def memberAccess
diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb
index 01e470c91..5fe953563 100644
--- a/app/controllers/repositories_controller.rb
+++ b/app/controllers/repositories_controller.rb
@@ -25,6 +25,7 @@ class ChangesetNotFound < Exception; end
class InvalidRevisionParam < Exception; end
class RepositoriesController < ApplicationController
+ include ApplicationHelper
menu_item :repository
menu_item :settings, :only => [:new, :create, :edit, :update, :destroy, :committers]
default_search_scope :changesets
@@ -122,7 +123,7 @@ update
if request.post? && @repository.save
redirect_to settings_project_url(@project, :tab => 'repositories')
else
- render :action => 'new'
+ redirect_to settings_project_url(@project, :tab => 'repositories')
end
else # 原逻辑
##xianbo
@@ -167,11 +168,12 @@ update
@repository.update_attributes(:login => User.current.login.to_s)
end
- redirect_to settings_project_url(@project, :tab => 'repositories')
- else if(@repository_tag)
- render :action => 'newrepo', :layout =>'base_projects'
+ redirect_to settings_project_url(@project, :tab => 'repositories',:repository_error_message=>@repository.errors.full_messages)
+ else if(@repository_tag.blank?)
+ #render :action => 'newrepo', :layout =>'base_projects'
+ redirect_to settings_project_url(@project, :tab => 'repositories',:repository => "pswd_is_null",:repository_error_message=>@repository.errors.full_messages)
else
- render :action => 'new', :layout =>'base_projects'
+ redirect_to settings_project_url(@project, :tab => 'repositories',:repository => @repository,:repository_error_message=>@repository.errors.full_messages)
end
end
@@ -234,24 +236,10 @@ update
end
def destroy
- @root_path=RepositoriesHelper::ROOT_PATH
- @repo_name=User.current.login.to_s+"_"+@repository.identifier.to_s
- @repository_name=User.current.login.to_s+"/"+@repository.identifier.to_s+".git"
- @middle=User.current.login.to_s+"_"+@repository.identifier.to_s+"-write:"
- @repository.destroy if request.delete?
+ DestroyRepositoryTask.new.destroy(User.current.id, @repository.id)
+ @repository.hidden = true
+ @repository.save
redirect_to settings_project_url(@project, :tab => 'repositories')
- if(@repository.type=="Repository::Git")
- logger.info "destory the repository value"+"root path"+@root_path+"repo_name"+@repo_name+
- "repository_name"+@repository_name+"user group"+@middle
- system "sed -i /"+@repo_name+"/{d} "+@root_path+"htdocs/user.passwd"
- system "sed -i /"+@middle+"/{d} "+@root_path+"htdocs/group.passwd"
- system "rm -r "+@root_path+"htdocs/"+@repository_name
- # if(@sed_user&&@sed_group&&@remove)
- # else
- # logger.info "An error occured when destory the repository"+"delete form passwd: \n"+
- # @sed_user+"delete from group"+@sed_group+"delete from file"+@remove
- # end
- end
end
def show
diff --git a/app/controllers/test_controller.rb b/app/controllers/test_controller.rb
index 22cf7d1d5..51ff293f1 100644
--- a/app/controllers/test_controller.rb
+++ b/app/controllers/test_controller.rb
@@ -57,5 +57,98 @@ class TestController < ApplicationController
attach.filename
end
+ def mailer()
+ raise unless Rails.env.development?
+ @user = User.find(params[:user_id])
+ send_for_user_activities(@user, Time.now,1)
+ render 'mailer/send_for_user_activities'
+ end
+ def send_for_user_activities(user, date_to, days)
+ date_from = date_to - days.days
+
+ subject = "[ #{user.show_name}#{l(:label_day_mail)}]"
+ @subject = " #{user.show_name}#{l(:label_day_mail)}"
+
+ date_from = "#{date_from} 17:59:59"
+ date_to = "#{date_to} 17:59:59"
+
+ # 生成token用于直接点击登录
+ @user = user
+ token = Token.new(:user =>user , :action => 'autologin')
+ token.save
+ @token = token
+
+ # 查询user参加的项目及课程
+ projects = user.projects
+ courses = user.courses
+ project_ids = projects.map{|project| project.id}.join(",")
+ course_ids = courses.map {|course| course.id}.join(",")
+
+ # 查询user的缺陷,包括发布的,跟踪的以及被指派的缺陷
+ sql = "select DISTINCT i.* from issues i, watchers w
+ where (i.assigned_to_id = #{user.id} or i.author_id = #{user.id}
+ or (w.watchable_type = 'Issue' and w.watchable_id = i.id and w.user_id = #{user.id}))
+ and (i.created_on between '#{date_from}' and '#{date_to}') order by i.created_on desc"
+ @issues = Issue.find_by_sql(sql)
+
+ # @bids 查询课程作业,包括老师发布的作业,以及user提交作业
+ # @attachments查询课程课件更新
+ @attachments ||= []
+
+ @bids ||= [] # 老师发布的作业
+
+ unless courses.first.nil?
+ count = courses.count
+ count = count - 1
+ for i in 0..count do
+ bids = courses[i].homeworks.where("bids.created_on between '#{date_from}' and '#{date_to}'").order("bids.created_on desc")
+ attachments = courses[i].attachments.where("attachments.created_on between '#{date_from}' and '#{date_to}'").order('attachments.created_on DESC')
+ @bids += bids if bids.count > 0
+ @attachments += attachments if attachments.count > 0
+ end
+ end
+ # user 提交的作业
+ @homeworks = HomeworkAttach.where("user_id=#{user.id} and (created_at between '#{date_from}' and '#{date_to}')").order("created_at desc")
+
+ # 查询user在课程。项目中发布的讨论帖子
+ messages = Message.find_by_sql("select DISTINCT * from messages where author_id = #{user.id} and (created_on between '#{date_from}' and '#{date_to}') order by created_on desc")
+ @course_messages ||= []
+ @project_messages ||= []
+ unless messages.first.nil?
+ messages.each do |msg|
+ if msg.project
+ @project_messages << msg
+ elsif msg.course
+ @course_messages << msg
+ end
+ end
+ end
+ # 查询user在课程中发布的通知,项目中发的新闻
+ @course_news = (course_ids && !course_ids.empty?) ? News.find_by_sql("select DISTINCT n.* from news n
+ where n.course_id in (#{course_ids})
+ and (created_on between '#{date_from}' and '#{date_to}') order by created_on desc") : []
+ @project_news = (project_ids && !project_ids.empty?) ? News.find_by_sql("select DISTINCT n.* from news n where n.project_id in (#{project_ids})
+ and (created_on between '#{date_from}' and '#{date_to}') order by created_on desc") : []
+
+ # 查询user在课程及个人中留言
+ @course_journal_messages = JournalsForMessage.find_by_sql("select DISTINCT * from journals_for_messages where
+ jour_type='Course' and user_id = #{user.id}
+ and (created_on between '#{date_from}' and '#{date_to}') order by created_on desc")
+ @user_journal_messages = user.journals_for_messages.where("m_parent_id IS NULL and (created_on between '#{date_from}' and '#{date_to}')").order('created_on DESC')
+
+
+ # 查询user新建贴吧或发布帖子
+ @forums = Forum.find_by_sql("select DISTINCT * from forums where creator_id = #{user.id} and (created_at between '#{date_from}' and '#{date_to}') order by created_at desc")
+ @memos = Memo.find_by_sql("select DISTINCT m.* from memos m, forums f where (m.author_id = #{user.id} or (m.forum_id = f.id and f.creator_id = #{user.id}))
+ and (m.created_at between '#{date_from}' and '#{date_to}') order by m.created_at desc")
+
+
+ has_content = [@issues,@homeworks,@course_messages,@project_messages,@course_news,@project_news,
+ @course_journal_messages,@user_journal_messages,@forums,@memos,@attachments,@bids].any? {|o|
+ !o.empty?
+ }
+ #有内容才发,没有不发
+ end
+
-end
\ No newline at end of file
+end
diff --git a/app/controllers/trackers_controller.rb b/app/controllers/trackers_controller.rb
index 01bc47a2f..64ad9c83a 100644
--- a/app/controllers/trackers_controller.rb
+++ b/app/controllers/trackers_controller.rb
@@ -38,12 +38,13 @@ class TrackersController < ApplicationController
@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
+ # 去掉原因,这块代码已经没有用到
+ # @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
diff --git a/app/controllers/versions_controller.rb b/app/controllers/versions_controller.rb
index 57f26103c..defc36868 100644
--- a/app/controllers/versions_controller.rb
+++ b/app/controllers/versions_controller.rb
@@ -85,13 +85,14 @@ class VersionsController < ApplicationController
end
def new
- @version = @project.versions.build
- @version.safe_attributes = params[:version]
-
- respond_to do |format|
- format.html
- format.js
- end
+ # @version = @project.versions.build
+ # @version.safe_attributes = params[:version]
+ #
+ # respond_to do |format|
+ # format.html
+ # format.js
+ # end
+ redirect_to settings_project_url(@project, :tab => 'versions')
end
def create
@@ -116,7 +117,8 @@ class VersionsController < ApplicationController
end
else
respond_to do |format|
- format.html { render :action => 'new' }
+ format.html { flash[:error] = @version.errors.full_messages.flatten.to_s
+ redirect_to settings_project_url(@project, :tab => 'versions') }
format.js { render :action => 'new' }
format.api { render_validation_errors(@version) }
end
@@ -136,7 +138,7 @@ class VersionsController < ApplicationController
respond_to do |format|
format.html {
flash[:notice] = l(:notice_successful_update)
- redirect_back_or_default settings_project_path(@project, :tab => 'versions')
+ redirect_to settings_project_path(@project, :tab => 'versions')
}
format.api { render_api_ok }
end
diff --git a/app/controllers/welcome_controller.rb b/app/controllers/welcome_controller.rb
index f35210f01..6e067fb83 100644
--- a/app/controllers/welcome_controller.rb
+++ b/app/controllers/welcome_controller.rb
@@ -58,12 +58,18 @@ class WelcomeController < ApplicationController
else
case @first_page.sort_type
when 0
+ @my_projects = find_my_projects
+ @other_projects = @my_projects.count < 9 ? find_miracle_project( 9 - @my_projects.count, 3,"score desc") : []
@projects = find_miracle_project(10, 3,"created_on desc")
#@projects = @projects_all.order("created_on desc")
when 1
+ @my_projects = find_my_projects
+ @other_projects = @my_projects.count < 9 ? find_miracle_project( 9 - @my_projects.count, 3,"score desc") : []
@projects = find_miracle_project(10, 3,"score desc")
#@projects = @projects_all.order("grade desc")
when 2
+ @my_projects = find_my_projects
+ @other_projects = @my_projects.count < 9 ? find_miracle_project( 9 - @my_projects.count, 3,"score desc") : []
@projects = find_miracle_project(10, 3,"watchers_count desc")
#@projects = @projects_all.order("watchers_count desc")
diff --git a/app/controllers/words_controller.rb b/app/controllers/words_controller.rb
index 680a13963..3d6772ea8 100644
--- a/app/controllers/words_controller.rb
+++ b/app/controllers/words_controller.rb
@@ -81,9 +81,10 @@ class WordsController < ApplicationController
@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
+ elsif @journal_destroyed.jour_type == "Course"
+ @course = Course.find @journal_destroyed.jour_id
+ @jours_count = @course.journals_for_messages.where('m_parent_id IS NULL').count
end
respond_to do |format|
format.js
diff --git a/app/controllers/zipdown_controller.rb b/app/controllers/zipdown_controller.rb
index df354f107..06d69f72e 100644
--- a/app/controllers/zipdown_controller.rb
+++ b/app/controllers/zipdown_controller.rb
@@ -188,6 +188,7 @@ class ZipdownController < ApplicationController
files_paths.each do |filename|
rename_file = File.basename(filename)
rename_file = filename_to_real( File.basename(filename)) if is_attachment
+
begin
zipfile.add(rename_file, filename)
rescue Exception => e
@@ -238,4 +239,4 @@ class ZipdownController < ApplicationController
attach = Attachment.find_by_disk_filename(name)
attach.filename
end
-end
\ No newline at end of file
+end
diff --git a/app/helpers/account_helper.rb b/app/helpers/account_helper.rb
index 445a1670e..7ad6fe65b 100644
--- a/app/helpers/account_helper.rb
+++ b/app/helpers/account_helper.rb
@@ -1,62 +1,62 @@
-# 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 AccountHelper
-
- def email_activation_register(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.run.register(token)
- #flash[:notice] = l(:notice_account_register_done)
- #render action: 'email_valid', locals: {:mail => user.mail}
- else
- yield if block_given?
- end
- user
- end
-
- def automatically_register(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
- user
- end
-
- def administrator_manually__register(user, &block)
- if user.save
- UserStatus.create(:user_id => user.id ,:changsets_count => 0, :watchers_count => 0)
- # Sends an email to the administrators
- Mailer.run.account_activation_request(user)
- #account_pending
- else
- yield if block_given?
- end
- user
- 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 AccountHelper
+
+ def email_activation_register(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.run.register(token)
+ #flash[:notice] = l(:notice_account_register_done)
+ #render action: 'email_valid', locals: {:mail => user.mail}
+ else
+ yield if block_given?
+ end
+ user
+ end
+
+ def automatically_register(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
+ user
+ end
+
+ def administrator_manually__register(user, &block)
+ if user.save
+ UserStatus.create(:user_id => user.id ,:changsets_count => 0, :watchers_count => 0)
+ # Sends an email to the administrators
+ Mailer.run.account_activation_request(user)
+ #account_pending
+ else
+ yield if block_given?
+ end
+ user
+ end
+
+end
diff --git a/app/helpers/activities_helper.rb b/app/helpers/activities_helper.rb
index 2f48ba87f..ede2ed78a 100644
--- a/app/helpers/activities_helper.rb
+++ b/app/helpers/activities_helper.rb
@@ -1,45 +1,45 @@
-# 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 ActivitiesHelper
- def sort_activity_events(events)
- events_by_group = events.group_by(&:event_group)
- sorted_events = []
- events.sort {|x, y| y.event_datetime <=> x.event_datetime}.each do |event|
- if group_events = events_by_group.delete(event.event_group)
- group_events.sort {|x, y| y.event_datetime <=> x.event_datetime}.each_with_index do |e, i|
- sorted_events << [e, i > 0] unless e.event_description.nil?
- end
- end
- end
- sorted_events
- end
- def sort_activity_events_course(events)
- events_by_group = events.group_by(&:event_group)
- sorted_events = []
- events.sort {|x, y| y.event_datetime <=> x.event_datetime}.each do |event|
- if group_events = events_by_group.delete(event.event_group)
- group_events.sort {|x, y| y.event_datetime <=> x.event_datetime}.each_with_index do |e, i|
- sorted_events << e unless e.event_description.nil?
- end
- end
- end
- sorted_events
- 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 ActivitiesHelper
+ def sort_activity_events(events)
+ events_by_group = events.group_by(&:event_group)
+ sorted_events = []
+ events.sort {|x, y| y.event_datetime <=> x.event_datetime}.each do |event|
+ if group_events = events_by_group.delete(event.event_group)
+ group_events.sort {|x, y| y.event_datetime <=> x.event_datetime}.each_with_index do |e, i|
+ sorted_events << [e, i > 0] unless e.event_description.nil?
+ end
+ end
+ end
+ sorted_events
+ end
+ def sort_activity_events_course(events)
+ events_by_group = events.group_by(&:event_group)
+ sorted_events = []
+ events.sort {|x, y| y.event_datetime <=> x.event_datetime}.each do |event|
+ if group_events = events_by_group.delete(event.event_group)
+ group_events.sort {|x, y| y.event_datetime <=> x.event_datetime}.each_with_index do |e, i|
+ sorted_events << e unless e.event_description.nil?
+ end
+ end
+ end
+ sorted_events
+ end
+end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 15c34c6ee..405dc72ed 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -81,7 +81,7 @@ module ApplicationHelper
def authorize_for(controller, action)
User.current.allowed_to?({:controller => controller, :action => action}, @project)
end
-
+
# add by nwb
def authorize_for_course(controller, action)
User.current.allowed_to?({:controller => controller, :action => action}, @course)
@@ -128,6 +128,24 @@ module ApplicationHelper
end
end
+ def link_to_isuue_user(user, options={})
+ if user.is_a?(User)
+ name = h(user.name(options[:format]))
+ link_to name, {:controller=> 'users', :action => 'show', id: user.id, host: Setting.user_domain}, :class => "pro_info_p"
+ else
+ h(user.to_s)
+ end
+ end
+
+ def link_to_settings_user(user, options={})
+ if user.is_a?(User)
+ name = h(user.name(options[:format]))
+ link_to name, {:controller=> 'users', :action => 'show', id: user.id, host: Setting.user_domain}, :class => "w90 c_orange fl"
+ else
+ h(user.to_s)
+ end
+ end
+
#重载上面方法,增加样式显示
def link_to_user_header user,canShowRealName=false,options={}
if user.is_a?(User)
@@ -170,6 +188,28 @@ module ApplicationHelper
s
end
+ def link_to_issue_version(issue, options={})
+ title = nil
+ subject = nil
+ text = options[:tracker] == false ? "##{issue.id}" : "#{issue.tracker} ##{issue.id}"
+ if options[:subject] == false
+ title = truncate(issue.subject, :length => 60)
+ else
+ subject = issue.subject
+ if options[:truncate]
+ subject = truncate(subject, :length => 60)
+ end
+ end
+ if issue.status_id == 5
+ s = link_to text, issue_path(issue), :class => "text_line_s", :title => title
+ else
+ s = link_to text, issue_path(issue), :class => "c_blue", :title => title
+ end
+ s << h(": #{subject}") if subject
+ s = h("#{issue.project} - ") + s if options[:project]
+ s
+ end
+
# Generates a link to an attachment.
# Options:
# * :text - Link text (default to attachment filename)
@@ -193,7 +233,7 @@ module ApplicationHelper
route_method = options.delete(:download) ? :download_named_attachment_path : :named_attachment_path
html_options = options.slice!(:only_path)
url = send(route_method, attachment, attachment.filename, options)
- url << "?token=#{token}" unless token.nil?
+ url << "?token=#{token}" unless token.nil?
link_to text, url, html_options
end
@@ -218,18 +258,18 @@ module ApplicationHelper
h(text),
{:controller => 'repositories', :action => 'revision', :id => repository.project, :repository_id => repository.identifier_param, :rev => rev},
:title => l(:label_revision_id, format_revision(revision))
- )
+ )
end
# Generates a link to a message
def link_to_message(message, options={}, html_options = nil)
link_to(
- truncate(message.subject, :length => 60),
- board_message_path(message.board_id, message.parent_id || message.id, {
- :r => (message.parent_id && message.id),
- :anchor => (message.parent_id ? "message-#{message.id}" : nil)
- }.merge(options)),
- html_options
+ truncate(message.subject, :length => 60),
+ board_message_path(message.board_id, message.parent_id || message.id, {
+ :r => (message.parent_id && message.id),
+ :anchor => (message.parent_id ? "message-#{message.id}" : nil)
+ }.merge(options)),
+ html_options
)
end
@@ -281,8 +321,23 @@ module ApplicationHelper
def thumbnail_tag(attachment)
link_to image_tag(thumbnail_path(attachment)),
- named_attachment_path(attachment, attachment.filename),
- :title => attachment.filename
+ named_attachment_path(attachment, attachment.filename),
+ :title => attachment.filename
+ end
+
+ def thumbnail_issue_tag(attachment)
+ imagesize = attachment.thumbnail(:size => "200*200")
+ imagepath = named_attachment_path(attachment, attachment.filename)
+ if imagesize
+ link_to image_tag(thumbnail_path(attachment), height: '73', width: '100', class: 'issue_attachment_picture'),
+ imagepath,
+ :title => attachment.filename
+
+ else
+ link_to image_tag(imagepath , height: '73', width: '100', class: 'issue_attachment_picture'),
+ imagepath,
+ :title => attachment.filename
+ end
end
# 图片缩略图链接
@@ -310,9 +365,9 @@ module ApplicationHelper
def image_to_function(name, function, html_options = {})
html_options.symbolize_keys!
tag(:input, html_options.merge({
- :type => "image", :src => image_path(name),
- :onclick => (html_options[:onclick] ? "#{html_options[:onclick]}; " : "") + "#{function};"
- }))
+ :type => "image", :src => image_path(name),
+ :onclick => (html_options[:onclick] ? "#{html_options[:onclick]}; " : "") + "#{function};"
+ }))
end
def format_activity_title(text)
@@ -330,9 +385,9 @@ module ApplicationHelper
def format_version_name(version)
if version.project == @project
- h(version)
+ h(truncate(version.name,:length=>20))
else
- h("#{version.project} - #{version}")
+ h("#{version.project} - #{truncate(version.name,:length=>20)}")
end
end
@@ -346,7 +401,7 @@ module ApplicationHelper
# The given collection may be a subset of the whole project tree
# (eg. some intermediate nodes are private and can not be seen)
#Modified by nie.
- def render_project_nested_lists(projects)
+ def render_project_nested_lists(projects)
s = ''
if projects.any?
ancestors = []
@@ -375,9 +430,9 @@ module ApplicationHelper
if project.try(:project_type) == Project::ProjectType_project
unless User.current.member_of?(@project)
- s << ""
- s << watcher_link(@project, User.current)#, ['whiteButton'])
- s << " "
+ s << ""
+ s << watcher_link(@project, User.current)#, ['whiteButton'])
+ s << " "
end
s << (render :partial => 'projects/project', :locals => {:project => project}).to_s
else
@@ -390,7 +445,7 @@ module ApplicationHelper
@project = original_project
end
s.html_safe
- end
+ end
def render_course_nested_lists(courses)
s = ''
@@ -425,7 +480,7 @@ module ApplicationHelper
end
- #added by young
+ #added by young
def render_project_nested_lists_new(projects)
s = ''
if projects.any?
@@ -454,7 +509,7 @@ module ApplicationHelper
end
s.html_safe
end
- #end
+ #end
def render_page_hierarchy(pages, node=nil, options={})
content = ''
if pages[node]
@@ -489,14 +544,22 @@ module ApplicationHelper
end
end
+ def render_project_settings_tabs(tabs)
+ if tabs.any?
+ render :partial => 'common/project_tab', :locals => {:tabs => tabs}
+ else
+ content_tag 'p', l(:label_no_data), :class => "nodata"
+ end
+ end
+
# Renders the project quick-jump box
def render_project_jump_box
return unless User.current.logged?
projects = User.current.memberships.collect(&:project).compact.select(&:active?).uniq
if projects.any?
options =
- ("#{ l(:label_jump_to_a_project) } " +
- '--- ').html_safe
+ ("#{ l(:label_jump_to_a_project) } " +
+ '--- ').html_safe
options << project_tree_options_for_select(projects, :selected => @project) do |p|
{ :value => project_path(:id => p, :jump => current_menu_item) }
@@ -547,6 +610,17 @@ module ApplicationHelper
s.html_safe
end
+ #缺陷追踪者列表复选框生成
+ def issue_watcher_check_box_tags_ex name, principals
+ s = ''
+ principals.each do |principal|
+ s << "
#{ check_box_tag name, principal.id, false, :id => nil } #{h link_to principal.userInfo, user_path( principal.id)} \n"
+ end
+ s.html_safe
+ end
+
+
+
#扩展的checkbox生成
def principals_check_box_tags_ex(name, principals)
s = ''
@@ -556,6 +630,15 @@ module ApplicationHelper
s.html_safe
end
+ # li标签checkbos扩展
+ def principals_check_box_tags_li(name, principals)
+ s = ''
+ principals.each do |principal|
+ s << "#{ check_box_tag name, principal.id, false, :id => nil } #{h link_to principal.userInfo, user_path( principal.id) } \n"
+ end
+ s.html_safe
+ end
+
#扩展的checkbox生成
def principals_radio_box_tags_ex(name, principals)
s = ''
@@ -666,24 +749,24 @@ module ApplicationHelper
link_to(image_tag('2uparrow.png', :alt => l(:label_sort_highest)),
url.merge({"#{name}[move_to]" => 'highest'}),
:method => method, :title => l(:label_sort_highest)) +
- link_to(image_tag('1uparrow.png', :alt => l(:label_sort_higher)),
- url.merge({"#{name}[move_to]" => 'higher'}),
- :method => method, :title => l(:label_sort_higher)) +
- link_to(image_tag('1downarrow.png', :alt => l(:label_sort_lower)),
- url.merge({"#{name}[move_to]" => 'lower'}),
- :method => method, :title => l(:label_sort_lower)) +
- link_to(image_tag('2downarrow.png', :alt => l(:label_sort_lowest)),
- url.merge({"#{name}[move_to]" => 'lowest'}),
- :method => method, :title => l(:label_sort_lowest))
+ link_to(image_tag('1uparrow.png', :alt => l(:label_sort_higher)),
+ url.merge({"#{name}[move_to]" => 'higher'}),
+ :method => method, :title => l(:label_sort_higher)) +
+ link_to(image_tag('1downarrow.png', :alt => l(:label_sort_lower)),
+ url.merge({"#{name}[move_to]" => 'lower'}),
+ :method => method, :title => l(:label_sort_lower)) +
+ link_to(image_tag('2downarrow.png', :alt => l(:label_sort_lowest)),
+ url.merge({"#{name}[move_to]" => 'lowest'}),
+ :method => method, :title => l(:label_sort_lowest))
end
def breadcrumb(*args)
elements = args.flatten
- elements.any? ? content_tag('p', (args.join(" \xc2\xbb ") + " \xc2\xbb ").html_safe, :class => 'breadcrumb') : nil
+ elements.any? ? content_tag('p', (args.join(" \xc2\xbb ") + " \xc2\xbb ").html_safe, :class => 'wiki_con_tit"') : nil
end
def other_formats_links(&block)
- concat(''.html_safe + l(:label_export_to))
+ concat('
'.html_safe + l(:label_export_to))
yield Redmine::Views::OtherFormatsBuilder.new(self)
concat('
'.html_safe)
end
@@ -758,15 +841,15 @@ module ApplicationHelper
def textilizable(*args)
options = args.last.is_a?(Hash) ? args.pop : {}
case args.size
- when 1
- obj = options[:object]
- text = args.shift
- when 2
- obj = args.shift
- attr = args.shift
- text = obj.send(attr).to_s
- else
- raise ArgumentError, 'invalid arguments to textilizable'
+ when 1
+ obj = options[:object]
+ text = args.shift
+ when 2
+ obj = args.shift
+ attr = args.shift
+ text = obj.send(attr).to_s
+ else
+ raise ArgumentError, 'invalid arguments to textilizable'
end
return '' if text.blank?
project = options[:project] || @project || (obj && obj.respond_to?(:project) ? obj.project : nil)
@@ -922,18 +1005,18 @@ module ApplicationHelper
# check if page exists
wiki_page = link_project.wiki.find_page(page)
url = if anchor.present? && wiki_page.present? && (obj.is_a?(WikiContent) || obj.is_a?(WikiContent::Version)) && obj.page == wiki_page
- "##{anchor}"
- else
- case options[:wiki_links]
- when :local; "#{page.present? ? Wiki.titleize(page) : ''}.html" + (anchor.present? ? "##{anchor}" : '')
- when :anchor; "##{page.present? ? Wiki.titleize(page) : title}" + (anchor.present? ? "_#{anchor}" : '') # used for single-file wiki export
- else
- wiki_page_id = page.present? ? Wiki.titleize(page) : nil
- parent = wiki_page.nil? && obj.is_a?(WikiContent) && obj.page && project == link_project ? obj.page.title : nil
- url_for(:only_path => only_path, :controller => 'wiki', :action => 'show', :project_id => link_project,
- :id => wiki_page_id, :version => nil, :anchor => anchor, :parent => parent)
- end
- end
+ "##{anchor}"
+ else
+ case options[:wiki_links]
+ when :local; "#{page.present? ? Wiki.titleize(page) : ''}.html" + (anchor.present? ? "##{anchor}" : '')
+ when :anchor; "##{page.present? ? Wiki.titleize(page) : title}" + (anchor.present? ? "_#{anchor}" : '') # used for single-file wiki export
+ else
+ wiki_page_id = page.present? ? Wiki.titleize(page) : nil
+ parent = wiki_page.nil? && obj.is_a?(WikiContent) && obj.page && project == link_project ? obj.page.title : nil
+ url_for(:only_path => only_path, :controller => 'wiki', :action => 'show', :project_id => link_project,
+ :id => wiki_page_id, :version => nil, :anchor => anchor, :parent => parent)
+ end
+ end
link_to(title.present? ? title.html_safe : h(page), url, :class => ('wiki-page' + (wiki_page ? '' : ' new')))
else
# project or wiki doesn't exist
@@ -1008,110 +1091,110 @@ module ApplicationHelper
# project.changesets.visible raises an SQL error because of a double join on repositories
if repository && (changeset = Changeset.visible.find_by_repository_id_and_revision(repository.id, identifier))
link = link_to(h("#{project_prefix}#{repo_prefix}r#{identifier}"), {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :repository_id => repository.identifier_param, :rev => changeset.revision},
- :class => 'changeset',
- :title => truncate_single_line(changeset.comments, :length => 100))
+ :class => 'changeset',
+ :title => truncate_single_line(changeset.comments, :length => 100))
end
end
elsif sep == '#'
oid = identifier.to_i
case prefix
- when nil
- if oid.to_s == identifier && issue = Issue.visible.find_by_id(oid, :include => :status)
- anchor = comment_id ? "note-#{comment_id}" : nil
- link = link_to("##{oid}", {:only_path => only_path, :controller => 'issues', :action => 'show', :id => oid, :anchor => anchor},
- :class => issue.css_classes,
- :title => "#{truncate(issue.subject, :length => 100)} (#{issue.status.name})")
- end
- when 'document'
- if document = Document.visible.find_by_id(oid)
- link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document},
- :class => 'document'
- end
- when 'version'
- if version = Version.visible.find_by_id(oid)
- link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version},
- :class => 'version'
- end
- when 'message'
- if message = Message.visible.find_by_id(oid, :include => :parent)
- link = link_to_message(message, {:only_path => only_path}, :class => 'message')
- end
- when 'forum'
- if board = Board.visible.find_by_id(oid)
- link = link_to h(board.name), {:only_path => only_path, :controller => 'boards', :action => 'show', :id => board, :project_id => board.project},
- :class => 'board'
- end
- when 'news'
- if news = News.visible.find_by_id(oid)
- link = link_to h(news.title), {:only_path => only_path, :controller => 'news', :action => 'show', :id => news},
- :class => 'news'
- end
- when 'project'
- if p = Project.visible.find_by_id(oid)
- link = link_to_project(p, {:only_path => only_path}, :class => 'project')
- end
+ when nil
+ if oid.to_s == identifier && issue = Issue.visible.find_by_id(oid, :include => :status)
+ anchor = comment_id ? "note-#{comment_id}" : nil
+ link = link_to("##{oid}", {:only_path => only_path, :controller => 'issues', :action => 'show', :id => oid, :anchor => anchor},
+ :class => issue.css_classes,
+ :title => "#{truncate(issue.subject, :length => 100)} (#{issue.status.name})")
+ end
+ when 'document'
+ if document = Document.visible.find_by_id(oid)
+ link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document},
+ :class => 'document'
+ end
+ when 'version'
+ if version = Version.visible.find_by_id(oid)
+ link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version},
+ :class => 'version'
+ end
+ when 'message'
+ if message = Message.visible.find_by_id(oid, :include => :parent)
+ link = link_to_message(message, {:only_path => only_path}, :class => 'message')
+ end
+ when 'forum'
+ if board = Board.visible.find_by_id(oid)
+ link = link_to h(board.name), {:only_path => only_path, :controller => 'boards', :action => 'show', :id => board, :project_id => board.project},
+ :class => 'board'
+ end
+ when 'news'
+ if news = News.visible.find_by_id(oid)
+ link = link_to h(news.title), {:only_path => only_path, :controller => 'news', :action => 'show', :id => news},
+ :class => 'news'
+ end
+ when 'project'
+ if p = Project.visible.find_by_id(oid)
+ link = link_to_project(p, {:only_path => only_path}, :class => 'project')
+ end
end
elsif sep == ':'
# removes the double quotes if any
name = identifier.gsub(%r{^"(.*)"$}, "\\1")
case prefix
- when 'document'
- if project && document = project.documents.visible.find_by_title(name)
- link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document},
- :class => 'document'
- end
- when 'version'
- if project && version = project.versions.visible.find_by_name(name)
- link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version},
- :class => 'version'
- end
- when 'forum'
- if project && board = project.boards.visible.find_by_name(name)
- link = link_to h(board.name), {:only_path => only_path, :controller => 'boards', :action => 'show', :id => board, :project_id => board.project},
- :class => 'board'
- end
- when 'news'
- if project && news = project.news.visible.find_by_title(name)
- link = link_to h(news.title), {:only_path => only_path, :controller => 'news', :action => 'show', :id => news},
- :class => 'news'
- end
- when 'commit', 'source', 'export'
- if project
- repository = nil
- if name =~ %r{^(([a-z0-9\-_]+)\|)(.+)$}
- repo_prefix, repo_identifier, name = $1, $2, $3
- repository = project.repositories.detect {|repo| repo.identifier == repo_identifier}
- else
- repository = project.repository
+ when 'document'
+ if project && document = project.documents.visible.find_by_title(name)
+ link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document},
+ :class => 'document'
+ end
+ when 'version'
+ if project && version = project.versions.visible.find_by_name(name)
+ link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version},
+ :class => 'version'
+ end
+ when 'forum'
+ if project && board = project.boards.visible.find_by_name(name)
+ link = link_to h(board.name), {:only_path => only_path, :controller => 'boards', :action => 'show', :id => board, :project_id => board.project},
+ :class => 'board'
+ end
+ when 'news'
+ if project && news = project.news.visible.find_by_title(name)
+ link = link_to h(news.title), {:only_path => only_path, :controller => 'news', :action => 'show', :id => news},
+ :class => 'news'
end
- if prefix == 'commit'
- if repository && (changeset = Changeset.visible.where("repository_id = ? AND scmid LIKE ?", repository.id, "#{name}%").first)
- link = link_to h("#{project_prefix}#{repo_prefix}#{name}"), {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :repository_id => repository.identifier_param, :rev => changeset.identifier},
- :class => 'changeset',
- :title => truncate_single_line(changeset.comments, :length => 100)
+ when 'commit', 'source', 'export'
+ if project
+ repository = nil
+ if name =~ %r{^(([a-z0-9\-_]+)\|)(.+)$}
+ repo_prefix, repo_identifier, name = $1, $2, $3
+ repository = project.repositories.detect {|repo| repo.identifier == repo_identifier}
+ else
+ repository = project.repository
end
- else
- if repository && User.current.allowed_to?(:browse_repository, project)
- name =~ %r{^[/\\]*(.*?)(@([^/\\@]+?))?(#(L\d+))?$}
- path, rev, anchor = $1, $3, $5
- link = link_to h("#{project_prefix}#{prefix}:#{repo_prefix}#{name}"), {:controller => 'repositories', :action => (prefix == 'export' ? 'raw' : 'entry'), :id => project, :repository_id => repository.identifier_param,
- :path => to_path_param(path),
- :rev => rev,
- :anchor => anchor},
- :class => (prefix == 'export' ? 'source download' : 'source')
+ if prefix == 'commit'
+ if repository && (changeset = Changeset.visible.where("repository_id = ? AND scmid LIKE ?", repository.id, "#{name}%").first)
+ link = link_to h("#{project_prefix}#{repo_prefix}#{name}"), {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :repository_id => repository.identifier_param, :rev => changeset.identifier},
+ :class => 'changeset',
+ :title => truncate_single_line(changeset.comments, :length => 100)
+ end
+ else
+ if repository && User.current.allowed_to?(:browse_repository, project)
+ name =~ %r{^[/\\]*(.*?)(@([^/\\@]+?))?(#(L\d+))?$}
+ path, rev, anchor = $1, $3, $5
+ link = link_to h("#{project_prefix}#{prefix}:#{repo_prefix}#{name}"), {:controller => 'repositories', :action => (prefix == 'export' ? 'raw' : 'entry'), :id => project, :repository_id => repository.identifier_param,
+ :path => to_path_param(path),
+ :rev => rev,
+ :anchor => anchor},
+ :class => (prefix == 'export' ? 'source download' : 'source')
+ end
end
+ repo_prefix = nil
+ end
+ when 'attachment'
+ attachments = options[:attachments] || (obj && obj.respond_to?(:attachments) ? obj.attachments : nil)
+ if attachments && attachment = Attachment.latest_attach(attachments, name)
+ link = link_to_attachment(attachment, :only_path => only_path, :download => true, :class => 'attachment')
+ end
+ when 'project'
+ if p = Project.visible.where("identifier = :s OR LOWER(name) = :s", :s => name.downcase).first
+ link = link_to_project(p, {:only_path => only_path}, :class => 'project')
end
- repo_prefix = nil
- end
- when 'attachment'
- attachments = options[:attachments] || (obj && obj.respond_to?(:attachments) ? obj.attachments : nil)
- if attachments && attachment = Attachment.latest_attach(attachments, name)
- link = link_to_attachment(attachment, :only_path => only_path, :download => true, :class => 'attachment')
- end
- when 'project'
- if p = Project.visible.where("identifier = :s OR LOWER(name) = :s", :s => name.downcase).first
- link = link_to_project(p, {:only_path => only_path}, :class => 'project')
- end
end
end
end
@@ -1128,9 +1211,9 @@ module ApplicationHelper
@current_section += 1
if @current_section > 1
content_tag('div',
- link_to(image_tag('edit.png'), options[:edit_section_links].merge(:section => @current_section)),
- :class => 'contextual',
- :title => l(:button_edit_section)) + heading.html_safe
+ link_to(image_tag('edit.png'), options[:edit_section_links].merge(:section => @current_section)),
+ :class => 'contextual',
+ :title => l(:button_edit_section)) + heading.html_safe
else
heading
end
@@ -1249,10 +1332,10 @@ module ApplicationHelper
# Same as Rails' simple_format helper without using paragraphs
def simple_format_without_paragraph(text)
text.to_s.
- gsub(/\r\n?/, "\n"). # \r\n and \r -> \n
- gsub(/\n\n+/, " "). # 2+ newline -> 2 br
- gsub(/([^\n]\n)(?=[^\n])/, '\1 '). # 1 newline -> br
- html_safe
+ gsub(/\r\n?/, "\n"). # \r\n and \r -> \n
+ gsub(/\n\n+/, " "). # 2+ newline -> 2 br
+ gsub(/([^\n]\n)(?=[^\n])/, '\1 '). # 1 newline -> br
+ html_safe
end
def wiki_simple_format_without_paragraph(text)
@@ -1267,7 +1350,7 @@ module ApplicationHelper
end
def lang_options_for_select(blank=true)
- { 'Chinese简体中文 '=> 'zh', :English => :en}
+ { 'Chinese简体中文 '=> 'zh', :English => :en}
end
def label_tag_for(name, option_tags = nil, options = {})
@@ -1334,9 +1417,31 @@ module ApplicationHelper
def delete_link(url, options={})
options = {
- :method => :delete,
- :data => {:confirm => l(:text_are_you_sure)},
- :class => 'icon icon-del'
+ :method => :delete,
+ :data => {:confirm => l(:text_are_you_sure)},
+ :class => 'icon icon-del'
+ }.merge(options)
+
+ link_to l(:button_delete), url, options
+ end
+
+ def delete_link_version(url, options={})
+ options = {
+ :method => :delete,
+ :data => {:confirm => l(:text_are_you_sure)},
+ :class => 'c_purple'
+ }.merge(options)
+
+ link_to l(:button_delete), url, options
+ end
+
+
+
+ def delete_new_link(url, options={})
+ options = {
+ :method => :delete,
+ :data => {:confirm => l(:text_are_you_sure)},
+ :class => "c_purple"
}.merge(options)
link_to l(:button_delete), url, options
@@ -1347,11 +1452,11 @@ module ApplicationHelper
:href => "#",
:onclick => %|submitPreview("#{escape_javascript url_for(url)}", "#{escape_javascript form}", "#{escape_javascript target}"); return false;|,
:accesskey => accesskey(:preview)
- }.merge(options)
+ }.merge(options)
end
def link_to_function(name, function, html_options={})
- content_tag(:a, name, {:href => '#', :onclick => "#{function}; return false;"}.merge(html_options))
+ content_tag(:a, name, {:href => '#', :onclick => "#{function}; return false;"}.merge(:class => " c_purple"))
end
# Helper to render JSON in views
@@ -1373,9 +1478,8 @@ module ApplicationHelper
end
def check_all_links(form_name)
- link_to_function(l(:button_check_all), "checkAll('#{form_name}', true)") +
- " | ".html_safe +
- link_to_function(l(:button_uncheck_all), "checkAll('#{form_name}', false)")
+ link_to_function(l(:button_check_all), "checkAll('#{form_name}', true)") + " ".html_safe + " | "+ " ".html_safe +
+ link_to_function(l(:button_uncheck_all), "checkAll('#{form_name}', false)")
end
def progress_bar(pcts, options={})
@@ -1386,12 +1490,12 @@ module ApplicationHelper
width = options[:width] || '100px;'
legend = options[:legend] || ''
content_tag('table',
- content_tag('tr',
- (pcts[0] > 0 ? content_tag('td', '', :style => "width: #{pcts[0]}%;", :class => 'closed') : ''.html_safe) +
- (pcts[1] > 0 ? content_tag('td', '', :style => "width: #{pcts[1]}%;", :class => 'done') : ''.html_safe) +
- (pcts[2] > 0 ? content_tag('td', '', :style => "width: #{pcts[2]}%;", :class => 'todo') : ''.html_safe)
- ), :class => 'progress', :style => "width: #{width};").html_safe +
- content_tag('p', legend, :class => 'percent').html_safe
+ content_tag('tr',
+ (pcts[0] > 0 ? content_tag('td', '', :style => "width: #{pcts[0]}%;", :class => 'closed') : ''.html_safe) +
+ (pcts[1] > 0 ? content_tag('td', '', :style => "width: #{pcts[1]}%;", :class => 'done') : ''.html_safe) +
+ (pcts[2] > 0 ? content_tag('td', '', :style => "width: #{pcts[2]}%;", :class => 'todo') : ''.html_safe)
+ ), :class => 'progress', :style => "width: #{width};").html_safe +
+ content_tag('p', legend, :class => 'percent').html_safe
end
def checked_image(checked=true)
@@ -1404,7 +1508,7 @@ module ApplicationHelper
unless @context_menu_included
content_for :header_tags do
javascript_include_tag('context_menu') +
- stylesheet_link_tag('context_menu')
+ stylesheet_link_tag('context_menu')
end
if l(:direction) == 'rtl'
content_for :header_tags do
@@ -1435,7 +1539,7 @@ module ApplicationHelper
tags = javascript_tag(
"var datepickerOptions={dateFormat: 'yy-mm-dd', firstDay: #{start_of_week}, " +
"showOn: 'button', buttonImageOnly: true, buttonImage: '" +
- path_to_image('/images/calendar.png') +
+ path_to_image('/images/public_icon.png') +
"', showButtonPanel: true, showWeek: true, showOtherMonths: true, selectOtherMonths: true};")
jquery_locale = l('jquery.locale', :default => current_language.to_s)
unless jquery_locale == 'en'
@@ -1457,7 +1561,7 @@ module ApplicationHelper
tags = javascript_tag(
"var datepickerOptions={dateFormat: 'yy-mm-dd',minDate: new Date(), firstDay: #{start_of_week}, " +
"showOn: 'button', buttonImageOnly: true, buttonImage: '" +
- path_to_image('/images/calendar.png') +
+ path_to_image('/images/public_icon.png') +
"', showButtonPanel: true, showWeek: true, showOtherMonths: true, selectOtherMonths: true, onClose: function(dateText, inst) {TimeClose(dateText,inst);}, beforeShow : function(input){TimeBeforeShow(input);} };")
jquery_locale = l('jquery.locale', :default => current_language.to_s)
unless jquery_locale == 'en'
@@ -1663,7 +1767,7 @@ module ApplicationHelper
end
s
end
-
+
def get_memo
@new_memo = Memo.new
#@new_memo.subject = "有什么想说的,尽管来咆哮吧~~"
@@ -1717,6 +1821,17 @@ module ApplicationHelper
candown
end
+ def project_type_link(text, value)
+ if value == 1
+ link_to " #{text}".html_safe,"javascript:void(0)" ,:onClick => "show_window();", :class => "pr_join_a",:id => "setting_project_type"
+ elsif value == 2
+ link_to " #{text}".html_safe,"javascript:void(0)" ,:onClick => "show_window();", :class => "pr_join_a",:id => "setting_project_type"
+ else
+ link_to " #{text}".html_safe,"javascript:void(0)" ,:onClick => "show_window();", :class => "pr_join_a",:id => "setting_project_type"
+ end
+
+ end
+
private
def wiki_helper
@@ -1746,11 +1861,11 @@ module ApplicationHelper
html << (content_tag "span", l(:label_no_current_watchers))
end
for user in User.watched_by(obj.id)
- html << (link_to image_tag(url_to_avatar(user), :class => "avatar"), user_path(user), :class => "avatar", :title => "#{user.name}")
- count = count + 1
- if count >= 12
- break
- end
+ html << (link_to image_tag(url_to_avatar(user), :class => "avatar"), user_path(user), :class => "avatar", :title => "#{user.name}")
+ count = count + 1
+ if count >= 12
+ break
+ end
end
html.html_safe
end
@@ -1776,13 +1891,13 @@ module ApplicationHelper
html.html_safe
end
- def show_bid_fans_picture(obj)
+ def show_bid_fans_picture(obj)
html = ''
if obj.watcher_users.count == 0
html << (content_tag "span", l(:label_project_no_follow))
else
obj.watcher_users.take(12).each do |user|
- html << (link_to image_tag(url_to_avatar(user), :class => "avatar"), user_path(user), :class => "avatar", :title => user.name)
+ html << (link_to image_tag(url_to_avatar(user), :class => "avatar"), user_path(user), :class => "avatar", :title => user.name)
end
end
html.html_safe
@@ -1817,7 +1932,7 @@ module ApplicationHelper
html.html_safe
end
- def show_contest_project(contest)
+ def show_contest_project(contest)
html = ''
if contest.projects.where('is_public = 1').count == 0
html << (content_tag "p", l(:label_no_bid_project), :class => "font_lighter")
@@ -1829,7 +1944,7 @@ module ApplicationHelper
html.html_safe
end
- def show_contest_softapplication(contest)
+ def show_contest_softapplication(contest)
html = ''
if contest.softapplications.where('is_public = 1').count == 0
html << (content_tag "p", l(:label_no_contest_softapplication), :class => "font_lighter")
@@ -1841,17 +1956,17 @@ module ApplicationHelper
html.html_safe
end
- def show_contest_fans_picture(obj)
+ def show_contest_fans_picture(obj)
html = ''
if obj.watcher_users.count == 0
html << (content_tag "span", l(:label_project_no_follow))
else
obj.watcher_users.take(12).each do |user|
- html << (link_to image_tag(url_to_avatar(user), :class => "avatar"), user_path(user), :class => "avatar", :title => user.name)
+ html << (link_to image_tag(url_to_avatar(user), :class => "avatar"), user_path(user), :class => "avatar", :title => user.name)
end
end
html.html_safe
- end
+ end
#display fans picture
def show_more_fans?(obj)
@@ -1868,13 +1983,13 @@ module ApplicationHelper
html << (content_tag "span", l(:label_no_current_fans))
else
obj.watcher_users.take(12).each do |user|
- html << (link_to image_tag(url_to_avatar(user), :class => "avatar"), user_path(user), :class => "avatar", :title => user.name)
+ html << (link_to image_tag(url_to_avatar(user), :class => "avatar"), user_path(user), :class => "avatar", :title => user.name)
end
end
html.html_safe
end
- # added by bai
+ # added by bai
def show_more_participate?(obj)
if obj.join_in_contests.count > 12
return true
@@ -1883,18 +1998,18 @@ module ApplicationHelper
end
end
- def show_participate_picture(obj)
+ def show_participate_picture(obj)
html = ''
count = 0
if obj.join_in_contests.count == 0
html << (content_tag "span", l(:label_no_current_participate))
end
for temp in obj.join_in_contests
- html << (link_to image_tag(url_to_avatar(temp.user), :class => "avatar"), user_path(temp.user), :class => "avatar", :title => "#{temp.user.name}")
- count = count + 1
- if count >= 12
- break
- end
+ html << (link_to image_tag(url_to_avatar(temp.user), :class => "avatar"), user_path(temp.user), :class => "avatar", :title => "#{temp.user.name}")
+ count = count + 1
+ if count >= 12
+ break
+ end
end
html.html_safe
end
@@ -1903,14 +2018,14 @@ module ApplicationHelper
# add by huang
def show_watcher_list(user)
- html = ''
- count = 0
+ html = ''
+ count = 0
for user in User.watched_by(user.id)
- html << (link_to image_tag(url_to_avatar(user), :class => "avatar"), user_path(user), :class => "avatar", :title => "#{user.name}")
- count = count + 1
- if count >= 12
- break
- end
+ html << (link_to image_tag(url_to_avatar(user), :class => "avatar"), user_path(user), :class => "avatar", :title => "#{user.name}")
+ count = count + 1
+ if count >= 12
+ break
+ end
end
html.html_safe
end
@@ -1928,14 +2043,14 @@ module ApplicationHelper
return true if bid.nil?
case bid.homework_type
- when Bid::HomeworkFile
- attaches = HomeworkAttach.where(bid_id: curb)
- attaches.map(&:user_id).include? cur
- when Bid::HomeworkProject
- attaches = BidingProject.where(user_id: User.current, bid_id: bid)
- attaches.count > 0 # > 0 则有提交记录
- else
- true
+ when Bid::HomeworkFile
+ attaches = HomeworkAttach.where(bid_id: curb)
+ attaches.map(&:user_id).include? cur
+ when Bid::HomeworkProject
+ attaches = BidingProject.where(user_id: User.current, bid_id: bid)
+ attaches.count > 0 # > 0 则有提交记录
+ else
+ true
end
end
@@ -1964,6 +2079,8 @@ module ApplicationHelper
forum_link = link_to l(:label_forum_all), {:controller => "forums", :action => "index"}
stores_link = link_to l(:label_stores_index), {:controller => 'stores', :action=> 'index'}
school_all_school_link = link_to l(:label_school_all), {:controller => 'school', :action => 'index'}
+ project_new_link = link_to l(:label_project_new), {:controller => 'projects', :action => 'new', :host => Setting.project_domain}
+ # project_mine_link = link_to l(:label_my_project), {:controller => 'users', :action => 'user_projects', :host => Setting.project_domain}
#@nav_dispaly_project_label
nav_list = Array.new
@@ -1976,6 +2093,8 @@ module ApplicationHelper
nav_list.push(main_contest_link) if @nav_dispaly_main_contest_label && @show_contest == 1 && visiable
nav_list.push(courses_link) if @nav_dispaly_course_label && @show_course == 1 && visiable
+ nav_list.push(project_new_link) if @nav_dispaly_project_label
+ # nav_list.push(project_mine_link) if @nav_dispaly_main_project_label
# nav_list.push(projects_link) if @nav_dispaly_project_label
#nav_list.push(users_link) if @nav_dispaly_user_label
# nav_list.push(contest_link) if @nav_dispaly_contest_label && @show_contest == 1
@@ -1995,12 +2114,12 @@ module ApplicationHelper
end
# def hadcommittedforcontest(curu)
- # message = JournalsForMessage.find_by_sql("select * from journals_for_messages where jour_type = 'Softapplication' ")
- # message.each do |createmessage|
- # if createmessage.user_id == curu
- # return true
- # end
- # end
+ # message = JournalsForMessage.find_by_sql("select * from journals_for_messages where jour_type = 'Softapplication' ")
+ # message.each do |createmessage|
+ # if createmessage.user_id == curu
+ # return true
+ # end
+ # end
# end
def footer_logo(ul_class=nil, li_class=nil)
@@ -2020,16 +2139,16 @@ module ApplicationHelper
def sort_homework_path(bid, sort, direction)
case self.action_name
- when 'show_courseEx'
- get_not_batch_homework_homework_attach_index_path(bid_id: bid.id, sort: sort, direction: 'asc')
- when 'get_not_batch_homework'
- get_not_batch_homework_homework_attach_index_path(bid_id: bid.id, sort: sort, direction: direction)
- when 'get_batch_homeworks'
- get_batch_homeworks_homework_attach_index_path(bid_id: bid.id, sort: sort, direction: direction)
- when 'get_homeworks'
- get_homeworks_homework_attach_index_path(bid_id: bid.id, sort: sort, direction: direction)
- else
- '#'
+ when 'show_courseEx'
+ get_not_batch_homework_homework_attach_index_path(bid_id: bid.id, sort: sort, direction: 'asc')
+ when 'get_not_batch_homework'
+ get_not_batch_homework_homework_attach_index_path(bid_id: bid.id, sort: sort, direction: direction)
+ when 'get_batch_homeworks'
+ get_batch_homeworks_homework_attach_index_path(bid_id: bid.id, sort: sort, direction: direction)
+ when 'get_homeworks'
+ get_homeworks_homework_attach_index_path(bid_id: bid.id, sort: sort, direction: direction)
+ else
+ '#'
end
end
diff --git a/app/helpers/attachments_helper.rb b/app/helpers/attachments_helper.rb
index 8843b1a76..be24629af 100644
--- a/app/helpers/attachments_helper.rb
+++ b/app/helpers/attachments_helper.rb
@@ -35,6 +35,16 @@ module AttachmentsHelper
end
end
+ def link_to_attachment_project(container, options = {})
+ options.assert_valid_keys(:author, :thumbnails)
+
+ if container.attachments.any?
+ options = {:deletable => container.attachments_deletable?, :author => true}.merge(options)
+ render :partial => 'attachments/project_file_links',
+ :locals => {:attachments => container.attachments, :options => options, :thumbnails => (options[:thumbnails] && Setting.thumbnails_enabled?)}
+ end
+ end
+
def link_to_attachments_course(container, options = {})
options.assert_valid_keys(:author, :thumbnails)
diff --git a/app/helpers/courses_helper.rb b/app/helpers/courses_helper.rb
index 2e06e3a43..801d98b0b 100644
--- a/app/helpers/courses_helper.rb
+++ b/app/helpers/courses_helper.rb
@@ -691,9 +691,11 @@ module CoursesHelper
#end
#poll_count
- #Poll.where(polls_group_id: @course_ids, polls_type: Course, polls_status: 2||3).where("published_at>?",date_from).each do |poll|
- # activities[poll.polls_group_id]+=1
- #end
+ # 动态目前只统计发布的问卷,关闭的问卷不在动态内显示
+ # Poll.where(polls_group_id: @course_ids, polls_type: Course, polls_status: 2||3).where("published_at>?",date_from).each do |poll|
+ Poll.where(polls_group_id: @course_ids, polls_type: Course, polls_status: 2||3).where("published_at>?",date_from).each do |poll|
+ activities[poll.polls_group_id]+=1
+ end
#end
diff --git a/app/helpers/files_helper.rb b/app/helpers/files_helper.rb
index d69f13a29..9a1765ddc 100644
--- a/app/helpers/files_helper.rb
+++ b/app/helpers/files_helper.rb
@@ -1,150 +1,150 @@
-# encoding: utf-8
-module FilesHelper
- include AttachmentsHelper
-
- def downloadAll containers
- paths = []
- files = []
- tmpfile = "tmp.zip"
-
- containers.each do |container|
- next if container.attachments.empty?
- if container.is_a?(Version);end
- container.attachments.each do |attachment|
- paths << attachment.diskfile
- file = attachment.diskfile
- # logger.error "[FilesHelper] downloadAll: #{e}"
- begin
- File.new(file, "r")
- rescue Exception => e
- logger.error e
- next
- end
- files << file
- # zip.add(file.path.dup.sub(directory, ''), file.path)
- end
- end
-
- zipfile_name = "archive.zip"
- if File.exists? File.open(zipfile_name, "w+")
- ff = File.open(zipfile_name, "w+")
- ff.close
- File.delete ff
- end
- Zip::ZipFile.open(zipfile_name, Zip::ZipFile::CREATE) do |zipfile|
- files.each do |filename|
- directory = File.dirname filename
- # Two arguments:
- # - The name of the file as it will appear in the archive
- # - The original file, including the path to find it
- dir = filename.sub(directory+"/", '')
- zipfile.add(dir, filename)
-
- end
- end
- File.new(zipfile_name,'w+')
- end
-
- #带勾选框的课程列表
- def courses_check_box_tags(name,courses,current_course,attachment)
- s = ''
- courses.each do |course|
- if !course_contains_attachment?(course,attachment) && is_course_teacher(User.current,course) && course_in_current_or_next_term(course)
- s << "#{ check_box_tag name, course.id, false, :id => nil } #{h course.name} [#{get_course_term course}] "
- end
- end
- s.html_safe
- end
-
- #带勾选框的项目列表
- def projects_check_box_tags(name,projects,current_project,attachment)
- s = ''
- projects.each do |project|
- if !project_contains_attachment?(project,attachment) && User.current.allowed_to?(:manage_files, project)
- s << "#{ check_box_tag name, project.id, false, :id => nil } #{h project.name} "
- 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 has_project? user,file
- result = false
- user.projects.each do |project|
- if !project_contains_attachment?(project,file) && User.current.allowed_to?(:manage_files, project)
- return true
- end
- end
- result
- end
-
- # 判断指定的资源时候符合类型
- def isTypeOk(attachment, type, contentType)
- result = false
- if type != 0
- if attachment.attachtype == type
- result = true
- end
- else
- result = true
- end
- if result
- if contentType != '0' && contentType != attachment.suffix_type
- result = false
- end
- end
- result
- end
-
- def visable_attachemnts attachments
- result = []
- attachments.each do |attachment|
- if attachment.is_public? ||
- (attachment.container_type == "Project" && User.current.member_of?(attachment.project)) ||
- (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 get_attachments_by_tag attachments,tag
- attachments.each do |attachment|
- attachment.tag_list.include?(tag)
- end
- end
-
- def visable_attachemnts_insite attachments,obj
- result = []
- if obj.is_a?(Course)
- attachments.each do |attachment|
- if attachment.is_public? || (attachment.container_type == "Course" && attachment.container_id == obj.id && User.current.member_of_course?(Course.find(attachment.container_id)))|| attachment.author_id == User.current.id
- result << attachment
- end
- end
- else if obj.is_a?(Project)
- attachments.each do |attachment|
- if attachment.is_public? || (attachment.container_type == "Project" && attachment.container_id == obj.id && User.current.member_of_course?(Project.find(attachment.container_id)))|| attachment.author_id == User.current.id
- result << attachment
- end
- end
- end
- end
- result
- end
-
-
-
+# encoding: utf-8
+module FilesHelper
+ include AttachmentsHelper
+
+ def downloadAll containers
+ paths = []
+ files = []
+ tmpfile = "tmp.zip"
+
+ containers.each do |container|
+ next if container.attachments.empty?
+ if container.is_a?(Version);end
+ container.attachments.each do |attachment|
+ paths << attachment.diskfile
+ file = attachment.diskfile
+ # logger.error "[FilesHelper] downloadAll: #{e}"
+ begin
+ File.new(file, "r")
+ rescue Exception => e
+ logger.error e
+ next
+ end
+ files << file
+ # zip.add(file.path.dup.sub(directory, ''), file.path)
+ end
+ end
+
+ zipfile_name = "archive.zip"
+ if File.exists? File.open(zipfile_name, "w+")
+ ff = File.open(zipfile_name, "w+")
+ ff.close
+ File.delete ff
+ end
+ Zip::ZipFile.open(zipfile_name, Zip::ZipFile::CREATE) do |zipfile|
+ files.each do |filename|
+ directory = File.dirname filename
+ # Two arguments:
+ # - The name of the file as it will appear in the archive
+ # - The original file, including the path to find it
+ dir = filename.sub(directory+"/", '')
+ zipfile.add(dir, filename)
+
+ end
+ end
+ File.new(zipfile_name,'w+')
+ end
+
+ #带勾选框的课程列表
+ def courses_check_box_tags(name,courses,current_course,attachment)
+ s = ''
+ courses.each do |course|
+ if !course_contains_attachment?(course,attachment) && is_course_teacher(User.current,course) && course_in_current_or_next_term(course)
+ s << "#{ check_box_tag name, course.id, false, :id => nil } #{h course.name} [#{get_course_term course}] "
+ end
+ end
+ s.html_safe
+ end
+
+ #带勾选框的项目列表
+ def projects_check_box_tags(name,projects,current_project,attachment)
+ s = ''
+ projects.each do |project|
+ if !project_contains_attachment?(project,attachment) && User.current.allowed_to?(:manage_files, project)
+ s << "#{ check_box_tag name, project.id, false, :id => nil } #{h project.name} "
+ 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 has_project? user,file
+ result = false
+ user.projects.each do |project|
+ if !project_contains_attachment?(project,file) && User.current.allowed_to?(:manage_files, project)
+ return true
+ end
+ end
+ result
+ end
+
+ # 判断指定的资源时候符合类型
+ def isTypeOk(attachment, type, contentType)
+ result = false
+ if type != 0
+ if attachment.attachtype == type
+ result = true
+ end
+ else
+ result = true
+ end
+ if result
+ if contentType != '0' && contentType != attachment.suffix_type
+ result = false
+ end
+ end
+ result
+ end
+
+ def visable_attachemnts attachments
+ result = []
+ attachments.each do |attachment|
+ if attachment.is_public? ||
+ (attachment.container_type == "Project" && User.current.member_of?(attachment.project)) ||
+ (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 get_attachments_by_tag attachments,tag
+ attachments.each do |attachment|
+ attachment.tag_list.include?(tag)
+ end
+ end
+
+ def visable_attachemnts_insite attachments,obj
+ result = []
+ if obj.is_a?(Course)
+ attachments.each do |attachment|
+ if attachment.is_public? || (attachment.container_type == "Course" && attachment.container_id == obj.id && User.current.member_of_course?(Course.find(attachment.container_id)))|| attachment.author_id == User.current.id
+ result << attachment
+ end
+ end
+ else if obj.is_a?(Project)
+ attachments.each do |attachment|
+ if attachment.is_public? || (attachment.container_type == "Project" && attachment.container_id == obj.id && User.current.member_of_course?(Project.find(attachment.container_id)))|| attachment.author_id == User.current.id
+ result << attachment
+ end
+ end
+ end
+ end
+ result
+ end
+
+
+
end
\ No newline at end of file
diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb
index 6a708051a..b72a191db 100644
--- a/app/helpers/issues_helper.rb
+++ b/app/helpers/issues_helper.rb
@@ -61,12 +61,38 @@ module IssuesHelper
#h("#{issue.tracker} ##{issue.id}")
# h("#{issue.tracker} #{issue.source_from}")
s = ''
- s << link_to(@issue.project.name, project_issues_path(@issue.project))
- s << " > #"
- s << @issue.project_index
+ s << link_to(@issue.project.name, project_issues_path(@issue.project), :class => "pro_page_top")
+ s << " > "
+ s << link_to("#" + @issue.project_index, project_issues_path(@issue.project), :class => "pro_page_top")
s.html_safe
end
+ #获取跟踪类型
+ #REDO:时间紧需要优化,两个方法可以综合成一个
+ def get_issue_type(value)
+ if value == "缺陷" || value == 1
+ class_type = "red_btn_cir ml10"
+ elsif value == "功能" || value == 2
+ class_type = "blue_btn_cir ml10"
+ elsif value == "支持" || value == 3
+ class_type = "green_btn_cir ml10"
+ else
+ class_type = "orange_btn_cir ml10"
+ end
+ end
+
+ def get_issue_typevalue(value)
+ if value == "缺陷" || value == 1
+ assign = "缺陷"
+ elsif value == "功能" || value == 2
+ assign = "功能"
+ elsif value == "支持" || value == 3
+ assign = "支持"
+ else
+ assign = "任务"
+ end
+ end
+
def render_issue_subject_with_tree(issue)
s = ''
ancestors = issue.root? ? [] : issue.ancestors.visible.all
@@ -314,17 +340,18 @@ module IssuesHelper
if detail.property == 'attachment' && !value.blank? && atta = Attachment.find_by_id(detail.prop_key)
# Link to the attachment if it has not been removed
if options[:token].nil?
- value = link_to_attachment(atta, :download => true, :only_path => options[:only_path])
+ value = atta.filename
else
- value = link_to_attachment(atta, :download => true, :only_path => options[:only_path], :token => options[:token])
- end
- if options[:only_path] != false && atta.is_text?
- value += link_to(
- image_tag('magnifier.png'),
- :controller => 'attachments', :action => 'show',
- :id => atta, :filename => atta.filename
- )
+ value = atta.filename
end
+ # 放大镜搜索功能
+ # if options[:only_path] != false && atta.is_text?
+ # value += link_to(
+ # image_tag('magnifier.png'),
+ # :controller => 'attachments', :action => 'show',
+ # :id => atta, :filename => atta.filename
+ # )
+ # end
else
value = content_tag("i", h(value)) if value
end
diff --git a/app/helpers/journals_helper.rb b/app/helpers/journals_helper.rb
index cfebb4d30..0eee08b6b 100644
--- a/app/helpers/journals_helper.rb
+++ b/app/helpers/journals_helper.rb
@@ -46,6 +46,26 @@ module JournalsHelper
content.html_safe
end
+ def render_links_easy(issue, journal, options={})
+ content = ''
+ editable = User.current.logged? && (User.current.allowed_to?(:edit_issue_notes, issue.project) || (journal.user == User.current && User.current.allowed_to?(:edit_own_issue_notes, issue.project)))
+ destroyable = User.current.logged? && ((journal.user == User.current) || (issue.author_id == User.current.id) || (User.current.admin == 1))
+ links = []
+ if !journal.notes.blank?
+ links << link_to(l(:button_quote),
+ {:controller => 'journals', :action => 'new', :id => issue.id, :journal_id => journal},
+ :remote => true,
+ :method => 'post',
+ :title => l(:button_quote)) if options[:reply_links]
+ if destroyable
+ links << link_to(l(:button_delete), { :controller => 'journals', :action => 'destroy', :id => journal, :format => 'js' },
+ :title => l(:button_delete))
+ end
+ end
+ content << content_tag('div', links.join(' ').html_safe, :class => 'contextual') unless links.empty?
+ content.html_safe
+ end
+
def render_notes (issue, journal, options={})
content = ''
editable = User.current.logged? && (User.current.allowed_to?(:edit_issue_notes, issue.project) || (journal.user == User.current && User.current.allowed_to?(:edit_own_issue_notes, issue.project)))
@@ -73,6 +93,35 @@ module JournalsHelper
content_tag('div', content.html_safe, :id => "journal-#{journal.id}-notes", :class => css_classes ,:style => "width:580px")
end
+ # 缺陷回复内容、引用内容
+ # Redo:后面需要统一扩展
+ def render_notes_issue (issue, journal, options={})
+ content = ''
+ editable = User.current.logged? && (User.current.allowed_to?(:edit_issue_notes, issue.project) || (journal.user == User.current && User.current.allowed_to?(:edit_own_issue_notes, issue.project)))
+ destroyable = User.current.logged? && ((journal.user == User.current) || (issue.author_id == User.current.id) || (User.current.admin == 1))
+ links = []
+ if !journal.notes.blank?
+ links << link_to(l(:button_quote),
+ {:controller => 'journals', :action => 'new', :id => issue.id, :journal_id => journal},
+ :remote => true,
+ :method => 'post',
+ :title => l(:button_quote)) if options[:reply_links]
+ links << link_to_in_place_notes_editor(l(:button_edit), "journal-#{journal.id}-notes",
+ { :controller => 'journals', :action => 'edit', :id => journal, :format => 'js' },
+ :title => l(:button_edit)) if editable
+ #Added by young
+ if destroyable
+ links << link_to(l(:button_delete), { :controller => 'journals', :action => 'destroy', :id => journal, :format => 'js' },
+ :title => l(:button_delete))
+ end
+ end
+ #content << content_tag('div', links.join(' ').html_safe, :class => 'contextual', :style => 'margin-top:-25px;') unless links.empty?
+ content << textilizable(journal, :notes)
+ css_classes = "wiki"
+ css_classes << " editable" if editable
+ content_tag('div', content.html_safe, :id => "journal-#{journal.id}-notes", :class => css_classes ,:style => "width:510px")
+ 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)
diff --git a/app/helpers/members_helper.rb b/app/helpers/members_helper.rb
index c8e8bd87b..06b154d36 100644
--- a/app/helpers/members_helper.rb
+++ b/app/helpers/members_helper.rb
@@ -1,96 +1,110 @@
-# 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 MembersHelper
- def render_principals_for_new_members(project)
- scope = Principal.active.sorted.not_member_of(project).like(params[:q])
- principal_count = scope.count
- principal_pages = Redmine::Pagination::Paginator.new principal_count, 10, params['page'] #by young
- principals = scope.offset(principal_pages.offset).limit(principal_pages.per_page).all
- s = content_tag('div', principals_check_box_tags_ex('membership[user_ids][]', principals), :id => 'principals')
- links = pagination_links_full(principal_pages, principal_count, :per_page_links => false) {|text, parameters, options|
- link_to text, autocomplete_project_memberships_path(project, parameters.merge(:q => params[:q], :format => 'js')), :remote => true
- }
- s + content_tag('div', content_tag('ul', links), :class => 'pagination_new')
- end
-
- #获取项目可邀请的成员列表
- def render_project_members project
- scope = Principal.active.sorted.not_member_of(project).like(params[:q])
- principals = paginateHelper scope,10
- s = content_tag('ul', project_member_check_box_tags_ex('membership[user_ids][]', principals), :class => 'mb5', :style => "margin-left: -40px;")
- links = pagination_links_full(@obj_pages, @obj_count, :per_page_links => false, :remote => false, :flag => true){|text, parameters, options|
- link_to text, autocomplete_project_memberships_path(project, parameters.merge(:q => params[:q],:flag => true, :format => 'js')), :remote => true
- }
- s + content_tag('ul', links,:class => 'wlist')
- end
-
- # add by nwb
- # 课程可添加的成员列表
- def render_principals_for_new_course_members(course)
- if params[:q] && params[:q] != ""
- scope = Principal.active.sorted.not_member_of_course(course).like(params[:q])
- else
- scope = []
- end
- principals = paginateHelper scope,10
- s = content_tag('ul', project_member_check_box_tags_ex('membership[user_ids][]', principals), :class => 'mb5', :id => 'principals')
-
- links = pagination_links_full(@obj_pages, @obj_count, :per_page_links => false, :remote => false, :flag => true) {|text, parameters, options|
- link_to text, autocomplete_course_memberships_path(course, parameters.merge(:q => params[:q], :format => 'js')), :remote => true
- }
-
- s + content_tag('ul', links,:class => 'wlist',:id => "course_member_pagination_links")
- end
-
-
- # 当前申请加入的成员名单
- def render_principals_for_applied_members(project)
- scope = project.applied_projects.map(&:user)
- principal_count = scope.count
- principal_pages = Redmine::Pagination::Paginator.new principal_count, 10, params['page']
- 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')
-
- links = pagination_links_full(principal_pages, principal_count, :per_page_links => false) {|text, parameters, options|
- link_to text, appliedproject_project_memberships_path(project, parameters.merge(:q => params[:q], :format => 'js')), :remote => true
- }
-
- s + content_tag('div', content_tag('ul', links), :class => 'applied_new')
- end
-
- private
- def paginateHelper obj, pre_size=20
- @obj_count = obj.count
- @obj_pages = Redmine::Pagination::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 MembersHelper
+ def render_principals_for_new_members(project)
+ scope = Principal.active.sorted.not_member_of(project).like(params[:q])
+ principal_count = scope.count
+ principal_pages = Redmine::Pagination::Paginator.new principal_count, 10, params['page'] #by young
+ principals = scope.offset(principal_pages.offset).limit(principal_pages.per_page).all
+ s = content_tag('div', principals_check_box_tags_ex('membership[user_ids][]', principals), :id => 'principals')
+ links = pagination_links_full(principal_pages, principal_count, :per_page_links => false) {|text, parameters, options|
+ link_to text, autocomplete_project_memberships_path(project, parameters.merge(:q => params[:q], :format => 'js')), :remote => true
+ }
+ s + content_tag('div', content_tag('ul', links), :class => 'pagination_new')
+ end
+
+ #获取项目可邀请的成员列表
+ def render_project_members project
+ if params[:q] && params[:q].lstrip.rstrip != ""
+ scope = Principal.active.sorted.not_member_of(project).like(params[:q])
+ else
+ scope = []
+ end
+ principals = paginateHelper scope,10
+ s = content_tag('ul', project_member_check_box_tags_ex('membership[user_ids][]', principals), :class => 'mb5')
+ links = pagination_links_full(@obj_pages, @obj_count, :per_page_links => false, :remote => false, :flag => true){|text, parameters, options|
+ link_to text, autocomplete_project_memberships_path(project, parameters.merge(:q => params[:q],:flag => true, :format => 'js')), :remote => true
+ }
+ s + content_tag('ul', links,:class => 'wlist', :id => "course_member_pagination_links" )
+ end
+
+ # add by nwb
+ # 课程可添加的成员列表
+ def render_principals_for_new_course_members(course)
+ if params[:q] && params[:q].lstrip.rstrip != ""
+ scope = Principal.active.sorted.not_member_of_course(course).like(params[:q])
+ else
+ scope = []
+ end
+ principals = paginateHelper scope,10
+ s = content_tag('ul', project_member_check_box_tags_ex('membership[user_ids][]', principals), :class => 'mb5', :id => 'principals')
+
+ links = pagination_links_full(@obj_pages, @obj_count, :per_page_links => false, :remote => false, :flag => true) {|text, parameters, options|
+ link_to text, autocomplete_course_memberships_path(course, parameters.merge(:q => params[:q], :format => 'js')), :remote => true
+ }
+
+ s + content_tag('ul', links,:class => 'wlist',:id => "course_member_pagination_links")
+ end
+
+ # 新申请加入项目成员列表
+ def render_principals_for_applied_members_new project
+ scope = project.applied_projects.map(&:user)
+ principals = paginateHelper scope,10
+ s = content_tag('ul', principals_check_box_tags_li('membership[user_ids][]', principals), :class => 'mb5')
+ links = pagination_links_full(@obj_pages, @obj_count, :per_page_links => false, :remote => false, :flag => true){|text, parameters, options|
+ link_to text, appliedproject_project_memberships_path(project, parameters.merge(:q => params[:q],:flag => true, :format => 'js')), :remote => true
+ }
+ s + content_tag('ul', links,:class => 'wlist', :id => "course_member_pagination_links" )
+ end
+
+ # 当前申请加入的成员名单
+ def render_principals_for_applied_members(project)
+ scope = project.applied_projects.map(&:user)
+ principal_count = scope.count
+ principal_pages = Redmine::Pagination::Paginator.new principal_count, 10, params['page']
+ 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')
+
+ links = pagination_links_full(principal_pages, principal_count, :per_page_links => false) {|text, parameters, options|
+ link_to text, appliedproject_project_memberships_path(project, parameters.merge(:q => params[:q], :format => 'js')), :remote => true
+ }
+
+ s + content_tag('div', content_tag('ul', links), :class => 'applied_new')
+ end
+
+ private
+ def paginateHelper obj, pre_size=20
+ @obj_count = obj.count
+ @obj_pages = Redmine::Pagination::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
diff --git a/app/helpers/owner_type_helper.rb b/app/helpers/owner_type_helper.rb
index 98f273bee..dd5dbbbac 100644
--- a/app/helpers/owner_type_helper.rb
+++ b/app/helpers/owner_type_helper.rb
@@ -1,9 +1,9 @@
-module OwnerTypeHelper
- MEMO = 1
- FORUM = 2
- MESSAGE = 3
- NEWS = 4
- COMMENT = 5
- BID = 6
- JOURNALSFORMESSAGE = 7
+module OwnerTypeHelper
+ MEMO = 1
+ FORUM = 2
+ MESSAGE = 3
+ NEWS = 4
+ COMMENT = 5
+ BID = 6
+ JOURNALSFORMESSAGE = 7
end
\ No newline at end of file
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index 3c1663fcb..508e58ba3 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -21,7 +21,12 @@ 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
+ link_to_if version.visible?, format_version_name(version), { :controller => 'versions', :action => 'show', :id => version }, :class => "c_blue02"
+ end
+
+ def link_to_version_show(version, options = {})
+ return '' unless version && version.is_a?(Version)
+ link_to_if version.visible?, format_version_name(version), { :controller => 'versions', :action => 'show', :id => version }, :class => " f16 fb c_dblue "
end
def project_settings_tabs
@@ -29,7 +34,7 @@ module ProjectsHelper
{: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 => '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},
@@ -386,4 +391,20 @@ module ProjectsHelper
end
type
end
+
+ #显示项目配置菜单
+ def show_project_memu user
+ if user.allowed_to?(:edit_project, @project)
+ result = "edit_project"
+ elsif user.allowed_to?(:select_project_modules, @project)
+ result = "select_project_modules"
+ elsif user.allowed_to?(:manage_members, @project)
+ result = "manage_members"
+ elsif user.allowed_to?(:manage_versions, @project)
+ result = "manage_versions"
+ elsif user.allowed_to?(:manage_repository, @project)
+ result = "manage_repository"
+ end
+ result
+ end
end
diff --git a/app/helpers/queries_helper.rb b/app/helpers/queries_helper.rb
index f36d2ea94..d9d910a66 100644
--- a/app/helpers/queries_helper.rb
+++ b/app/helpers/queries_helper.rb
@@ -243,26 +243,37 @@ module QueriesHelper
# Retrieve query from session or build a new query
def retrieve_query
- if !params[:query_id].blank?
- cond = "project_id IS NULL"
- cond << " OR project_id = #{@project.id}" if @project
- @query = IssueQuery.find(params[:query_id], :conditions => cond)
- raise ::Unauthorized unless @query.visible?
- @query.project = @project
- session[:query] = {:id => @query.id, :project_id => @query.project_id}
- sort_clear
- elsif api_request? || params[:set_filter] || session[:query].nil? || session[:query][:project_id] != (@project ? @project.id : nil)
+ # if !params[:query_id].blank?
+ # cond = "project_id IS NULL"
+ # cond << " OR project_id = #{@project.id}" if @project
+ # @query = IssueQuery.find(params[:query_id], :conditions => cond)
+ # raise ::Unauthorized unless @query.visible?
+ # @query.project = @project
+ # session[:query] = {:id => @query.id, :project_id => @query.project_id}
+ # sort_clear
+ # elsif api_request? || params[:set_filter] || session[:query].nil? || session[:query][:project_id] != (@project ? @project.id : nil)
# Give it a name, required to be valid
@query = IssueQuery.new(:name => "_")
@query.project = @project
+ params[:f] = %w(subject status_id priority_id author_id assigned_to_id) unless params[:status_id].nil?
+ params[:op] = {'subject' => "~" ,
+ 'status_id' => ( params[:status_id] == '0' ? "!":"=" ),
+ 'priority_id' => ( params[:priority_id] == '0' ? "!":"=" ),
+ 'author_id' => ( params[:author_id] == '0' ? "!":"=" ),
+ 'assigned_to_id' => ( params[:assigned_to_id] == '0' ? "!":"=" )} unless params[:status_id].nil?
+ params[:v] = {'subject' => [params[:subject]],
+ 'status_id' => [params[:status_id]],
+ 'priority_id' => [params[:priority_id]],
+ 'author_id' => [params[:author_id]],
+ 'assigned_to_id' => [params[:assigned_to_id]]} unless params[:status_id].nil?
@query.build_from_params(params)
- session[:query] = {:project_id => @query.project_id, :filters => @query.filters, :group_by => @query.group_by, :column_names => @query.column_names}
- else
- # retrieve from session
- @query = IssueQuery.find_by_id(session[:query][:id]) if session[:query][:id]
- @query ||= IssueQuery.new(:name => "_", :filters => session[:query][:filters], :group_by => session[:query][:group_by], :column_names => session[:query][:column_names])
- @query.project = @project
- end
+ #session[:query] = {:project_id => @query.project_id, :filters => @query.filters, :group_by => @query.group_by, :column_names => @query.column_names}
+ # else
+ # # retrieve from session
+ # @query = IssueQuery.find_by_id(session[:query][:id]) if session[:query][:id]
+ # @query ||= IssueQuery.new(:name => "_", :filters => session[:query][:filters], :group_by => session[:query][:group_by], :column_names => session[:query][:column_names])
+ # @query.project = @project
+ # end
end
def retrieve_query_from_session
diff --git a/app/helpers/repositories_helper.rb b/app/helpers/repositories_helper.rb
index 3c7123435..773560932 100644
--- a/app/helpers/repositories_helper.rb
+++ b/app/helpers/repositories_helper.rb
@@ -18,7 +18,11 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module RepositoriesHelper
- ROOT_PATH="/home/pdl/redmine-2.3.2-0/apache2/"
+ if Rails.env.development?
+ ROOT_PATH="/tmp/" if Rails.env.development?
+ else
+ ROOT_PATH="/home/pdl/redmine-2.3.2-0/apache2/"
+ end
PROJECT_PATH_CUT = 40
REPO_IP_ADDRESS = Setting.repository_domain
diff --git a/app/helpers/watchers_helper.rb b/app/helpers/watchers_helper.rb
index 7995d7e68..d3b2a49b1 100644
--- a/app/helpers/watchers_helper.rb
+++ b/app/helpers/watchers_helper.rb
@@ -42,7 +42,28 @@ module WatchersHelper
: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
+
+ def watcher_link_issue(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 ? 'talk_edit ' : 'talk_edit '].join(' ') << options[0].to_s) :
+ ([watcher_css(objects), watched ? 'talk_edit fr ' : 'talk_edit fr '].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
@@ -261,17 +282,36 @@ module WatchersHelper
content.present? ? content_tag('ul', content, :class => 'watchers') : content
end
+
+
+
+
+
+
+# 缺陷跟踪者列表复选框生成
def watchers_checkboxes(object, users, checked=nil)
if users.nil?
else
+ # 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"
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"
+ s = content_tag(:ul,
+ content_tag(:li, "#{check_box_tag 'issue[watcher_user_ids][]', user.id, c, :id => nil } #{h link_to user.userInfo, user_path( user.id)}".html_safe,
+ :id=>"issue_watcher_user_ids_#{user.id}",:style=>"float: left;width: 175px;margin: 0px 20px 10px 0px; overflow: hidden; line-height:1.6em;" ),
+ :class => "mb10 ml80")
end.join.html_safe
+
+ # scope = users.sort
+ # watchers = paginateHelper scope,10
+ # s = content_tag('ul', issue_watcher_check_box_tags_ex('issue[watcher_user_ids][]', watchers), :class => 'mb10 ml80')
+ # links = pagination_links_full(@obj_pages, @obj_count, :per_page_links => false, :remote => false, :flag => true){|text, parameters, options|
+ # link_to text, watchers_autocomplete_for_user_path(@users, parameters.merge(:q => params[:q],:format => 'js',:flag => 'ture')), :remote => true
+ # }
+ # s + content_tag('ul', links,:class => 'wlist', :style =>"float:left;margin-top:0px;")
end
end
@@ -304,8 +344,8 @@ module WatchersHelper
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),
- :style => "color: #fff; display:block;font-size:12px; padding: 0px 5px; margin-right: 10px; height: 20px; line-height: 22px; background: none repeat scroll 0% 0% #64BDD9; TES;padding-top:1px;" )
- end
+ :class => "pr_join_a_quit" )
+ end
#项目关注、取消关注
#REDO:项目样式确定后方法需要对CSS变量进行改进
@@ -321,7 +361,7 @@ module WatchersHelper
: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 => "project_watch_new" ,:id=>id
+ :class => "pr_join_a" ,:id=>id
end
#申请加入项目
@@ -339,7 +379,21 @@ module WatchersHelper
:user_id => user.id,
:project_id => project.id)
method = applied ? 'delete' : 'post'
- link_to text, url, :remote => true, :method => method , :class => "project_watch_new",:id => id
+ link_to text, url, :remote => true, :method => method , :class => "pr_join_a",:id => id
+ end
+
+ def paginateHelper obj, pre_size=20
+ @obj_count = obj.count
+ @obj_pages = Redmine::Pagination::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
diff --git a/app/helpers/welcome_helper.rb b/app/helpers/welcome_helper.rb
index f6e205e82..4800a949a 100644
--- a/app/helpers/welcome_helper.rb
+++ b/app/helpers/welcome_helper.rb
@@ -443,6 +443,10 @@ module WelcomeHelper
resultSet.take(limit)
end
+ def find_my_projects
+ my_projects = User.current.memberships.all(conditions: "projects.project_type = 0")
+ end
+
def sort_project_by_hot_rails project_type=0, order_by='score DESC', limit=15
# Project.find_by_sql("
# SELECT p.id, p.name, p.description, p.identifier, t.project_id
diff --git a/app/models/document.rb b/app/models/document.rb
index c8e5f8a24..6bfb4b8ff 100644
--- a/app/models/document.rb
+++ b/app/models/document.rb
@@ -1,95 +1,95 @@
-# 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 Document < ActiveRecord::Base
- include Redmine::SafeAttributes
- belongs_to :project
- belongs_to :user
- belongs_to :category, :class_name => "DocumentCategory", :foreign_key => "category_id"
- include UserScoreHelper
- after_save :be_user_score # user_score
- after_destroy :down_user_score
- acts_as_attachable :delete_permission => :delete_documents
- after_create :send_mail
- # 被ForgeActivity虚拟关联
- has_many :forge_acts, :class_name => 'ForgeActivity',:as =>:forge_act ,:dependent => :destroy
- # end
- acts_as_searchable :columns => ['title', "#{table_name}.description"], :include => :project
- acts_as_event :title => Proc.new {|o| "#{l(:label_document)}: #{o.title}"},
- #:author => Proc.new {|o| o.attachments.reorder("#{Attachment.table_name}.created_on ASC").first.try(:author) },
- :author => Proc.new {|o| User.find(o.user_id)},
- :url => Proc.new {|o| {:controller => 'documents', :action => 'show', :id => o.id}}
- acts_as_activity_provider :find_options => {:include => :project},
- :is_public => 'documents.is_public'
-
- validates_presence_of :project, :title, :category
- validates_length_of :title, :maximum => 60
- after_create :act_as_forge_activity
- scope :visible, lambda {|*args|
- includes(:project).where(Project.allowed_to_condition(args.shift || User.current, :view_documents, *args))
- }
-
- safe_attributes 'category_id', 'title', 'description','is_public'
-
- def visible?(user=User.current)
- !user.nil? && user.allowed_to?(:view_documents, project)
- end
-
- def has_right?(project,user=User.current)
- user.admin? || user.member_of?(project) || self.is_public==1
- end
-
- def initialize(attributes=nil, *args)
- super
- if new_record?
- self.category ||= DocumentCategory.default
- end
- end
-
- def updated_on
- unless @updated_on
- a = attachments.last
- @updated_on = (a && a.created_on) || created_on
- end
- @updated_on
- end
-
- # update user score
- def be_user_score
- UserScore.project(:push_document, self.user,self,{ document_id: self.id })
- update_document(self.user,1)
- update_document(self.user,2,self.project)
- end
-
- def down_user_score
- update_document(self.user,1)
- update_document(self.user,2,self.project)
- end
-
- # Time 2015-03-02 10:51:16
- # Author lizanle
- # Description 新创建的document要在公共表ForgeActivity中记录
- def act_as_forge_activity
- self.forge_acts << ForgeActivity.new(:user_id => self.user_id,
- :project_id => self.project_id)
- end
-
- def send_mail
- Mailer.run.document_added(self) if Setting.notified_events.include?('document_added')
- 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 Document < ActiveRecord::Base
+ include Redmine::SafeAttributes
+ belongs_to :project
+ belongs_to :user
+ belongs_to :category, :class_name => "DocumentCategory", :foreign_key => "category_id"
+ include UserScoreHelper
+ after_save :be_user_score # user_score
+ after_destroy :down_user_score
+ acts_as_attachable :delete_permission => :delete_documents
+ after_create :send_mail
+ # 被ForgeActivity虚拟关联
+ has_many :forge_acts, :class_name => 'ForgeActivity',:as =>:forge_act ,:dependent => :destroy
+ # end
+ acts_as_searchable :columns => ['title', "#{table_name}.description"], :include => :project
+ acts_as_event :title => Proc.new {|o| "#{l(:label_document)}: #{o.title}"},
+ #:author => Proc.new {|o| o.attachments.reorder("#{Attachment.table_name}.created_on ASC").first.try(:author) },
+ :author => Proc.new {|o| User.find(o.user_id)},
+ :url => Proc.new {|o| {:controller => 'documents', :action => 'show', :id => o.id}}
+ acts_as_activity_provider :find_options => {:include => :project},
+ :is_public => 'documents.is_public'
+
+ validates_presence_of :project, :title, :category
+ validates_length_of :title, :maximum => 60
+ after_create :act_as_forge_activity
+ scope :visible, lambda {|*args|
+ includes(:project).where(Project.allowed_to_condition(args.shift || User.current, :view_documents, *args))
+ }
+
+ safe_attributes 'category_id', 'title', 'description','is_public'
+
+ def visible?(user=User.current)
+ !user.nil? && user.allowed_to?(:view_documents, project)
+ end
+
+ def has_right?(project,user=User.current)
+ user.admin? || user.member_of?(project) || self.is_public==1
+ end
+
+ def initialize(attributes=nil, *args)
+ super
+ if new_record?
+ self.category ||= DocumentCategory.default
+ end
+ end
+
+ def updated_on
+ unless @updated_on
+ a = attachments.last
+ @updated_on = (a && a.created_on) || created_on
+ end
+ @updated_on
+ end
+
+ # update user score
+ def be_user_score
+ UserScore.project(:push_document, self.user,self,{ document_id: self.id })
+ update_document(self.user,1)
+ update_document(self.user,2,self.project)
+ end
+
+ def down_user_score
+ update_document(self.user,1)
+ update_document(self.user,2,self.project)
+ end
+
+ # Time 2015-03-02 10:51:16
+ # Author lizanle
+ # Description 新创建的document要在公共表ForgeActivity中记录
+ def act_as_forge_activity
+ self.forge_acts << ForgeActivity.new(:user_id => self.user_id,
+ :project_id => self.project_id)
+ end
+
+ def send_mail
+ Mailer.run.document_added(self) if Setting.notified_events.include?('document_added')
+ end
+
+end
diff --git a/app/models/forum.rb b/app/models/forum.rb
index 6db069a09..2af1abf9e 100644
--- a/app/models/forum.rb
+++ b/app/models/forum.rb
@@ -1,58 +1,58 @@
-class Forum < ActiveRecord::Base
- include Redmine::SafeAttributes
- include ApplicationHelper
- has_many_kindeditor_assets :assets, :dependent => :destroy
- has_many :topics, :class_name => 'Memo', :conditions => "#{Memo.table_name}.parent_id IS NULL", :order => "#{Memo.table_name}.created_at DESC", :dependent => :destroy
- has_many :memos, :dependent => :destroy, conditions: "parent_id IS NULL"
- belongs_to :creator, :class_name => "User", :foreign_key => 'creator_id'
- safe_attributes 'name',
- 'description',
- 'topic_count',
- 'memo_count',
- 'last_memo_id',
- 'creator_id',
- 'sticky',
- 'locked'
- validates_presence_of :name, :creator_id, :description
- validates_length_of :name, maximum: 50
- #validates_length_of :description, maximum: 255
- validates :name, :uniqueness => true
- after_destroy :delete_kindeditor_assets
- acts_as_taggable
- scope :by_join_date, order("created_at DESC")
- after_create :send_mail
- def reset_counters!
- self.class.reset_counters!(id)
- end
-
- def editable_by? user
- # user && user.logged? || (self.author == usr && usr.allowed_to?(:edit_own_messages, project))
- self.creator == user || user.admin?
- end
-
- def destroyable_by? user
- # user && user.logged? && Forum.find(self.forum_id).creator_id == user.id || user.admin?
- self.creator == user || user.admin?
- end
-
- def send_mail
- logger.debug "send mail for forum add."
- Mailer.run.forum_add(self) if Setting.notified_events.include?('forum_add')
- end
- # Updates topic_count, memo_count and last_memo_id attributes for +board_id+
- def self.reset_counters!(forum_id)
- forum_id = forum_id.to_i
- update_all("topic_count = (SELECT COUNT(*) FROM #{Memo.table_name} WHERE forum_id=#{forum_id} AND parent_id IS NULL)," +
- " memo_count = (SELECT COUNT(*) FROM #{Memo.table_name} WHERE forum_id=#{forum_id} AND parent_id IS NOT NULL)," +
- " last_memo_id = (SELECT MAX(id) FROM #{Memo.table_name} WHERE forum_id=#{forum_id})",
- ["id = ?", forum_id])
- end
-
- # Time 2015-03-26 15:50:54
- # Author lizanle
- # Description 删除论坛后删除对应的资源
- def delete_kindeditor_assets
- delete_kindeditor_assets_from_disk self.id,OwnerTypeHelper::FORUM
- end
-
-end
+class Forum < ActiveRecord::Base
+ include Redmine::SafeAttributes
+ include ApplicationHelper
+ has_many_kindeditor_assets :assets, :dependent => :destroy
+ has_many :topics, :class_name => 'Memo', :conditions => "#{Memo.table_name}.parent_id IS NULL", :order => "#{Memo.table_name}.created_at DESC", :dependent => :destroy
+ has_many :memos, :dependent => :destroy, conditions: "parent_id IS NULL"
+ belongs_to :creator, :class_name => "User", :foreign_key => 'creator_id'
+ safe_attributes 'name',
+ 'description',
+ 'topic_count',
+ 'memo_count',
+ 'last_memo_id',
+ 'creator_id',
+ 'sticky',
+ 'locked'
+ validates_presence_of :name, :creator_id, :description
+ validates_length_of :name, maximum: 50
+ #validates_length_of :description, maximum: 255
+ validates :name, :uniqueness => true
+ after_destroy :delete_kindeditor_assets
+ acts_as_taggable
+ scope :by_join_date, order("created_at DESC")
+ after_create :send_mail
+ def reset_counters!
+ self.class.reset_counters!(id)
+ end
+
+ def editable_by? user
+ # user && user.logged? || (self.author == usr && usr.allowed_to?(:edit_own_messages, project))
+ self.creator == user || user.admin?
+ end
+
+ def destroyable_by? user
+ # user && user.logged? && Forum.find(self.forum_id).creator_id == user.id || user.admin?
+ self.creator == user || user.admin?
+ end
+
+ def send_mail
+ logger.debug "send mail for forum add."
+ Mailer.run.forum_add(self) if Setting.notified_events.include?('forum_add')
+ end
+ # Updates topic_count, memo_count and last_memo_id attributes for +board_id+
+ def self.reset_counters!(forum_id)
+ forum_id = forum_id.to_i
+ update_all("topic_count = (SELECT COUNT(*) FROM #{Memo.table_name} WHERE forum_id=#{forum_id} AND parent_id IS NULL)," +
+ " memo_count = (SELECT COUNT(*) FROM #{Memo.table_name} WHERE forum_id=#{forum_id} AND parent_id IS NOT NULL)," +
+ " last_memo_id = (SELECT MAX(id) FROM #{Memo.table_name} WHERE forum_id=#{forum_id})",
+ ["id = ?", forum_id])
+ end
+
+ # Time 2015-03-26 15:50:54
+ # Author lizanle
+ # Description 删除论坛后删除对应的资源
+ def delete_kindeditor_assets
+ delete_kindeditor_assets_from_disk self.id,OwnerTypeHelper::FORUM
+ end
+
+end
diff --git a/app/models/issue_observer.rb b/app/models/issue_observer.rb
index 51f64c783..ea78349af 100644
--- a/app/models/issue_observer.rb
+++ b/app/models/issue_observer.rb
@@ -1,28 +1,28 @@
-# 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 IssueObserver < ActiveRecord::Observer
-
- def after_create(issue)
- # 将跟踪者与本项目的其他成员都设为收件方,并去重,不在进行抄送,
- recipients = issue.recipients - issue.watcher_recipients + issue.watcher_recipients
- recipients.each do |rec|
- Mailer.run.issue_add(issue,rec) if Setting.notified_events.include?('issue_added')
- 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 IssueObserver < ActiveRecord::Observer
+
+ def after_create(issue)
+ # 将跟踪者与本项目的其他成员都设为收件方,并去重,不在进行抄送,
+ recipients = issue.recipients - issue.watcher_recipients + issue.watcher_recipients
+ recipients.each do |rec|
+ Mailer.run.issue_add(issue,rec) if Setting.notified_events.include?('issue_added')
+ end
+
+ end
+end
diff --git a/app/models/issue_query.rb b/app/models/issue_query.rb
index c55143ca8..dba45cb43 100644
--- a/app/models/issue_query.rb
+++ b/app/models/issue_query.rb
@@ -310,7 +310,7 @@ class IssueQuery < Query
:order => options[:order],
:limit => options[:limit],
:offset => options[:offset]
- )
+ ).reverse
rescue ::ActiveRecord::StatementInvalid => e
raise StatementInvalid.new(e.message)
end
diff --git a/app/models/journal_observer.rb b/app/models/journal_observer.rb
index 1fca58f37..c5b0e496b 100644
--- a/app/models/journal_observer.rb
+++ b/app/models/journal_observer.rb
@@ -1,34 +1,34 @@
-# 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 JournalObserver < ActiveRecord::Observer
- def after_create(journal)
- if journal.notify? &&
- (Setting.notified_events.include?('issue_updated') ||
- (Setting.notified_events.include?('issue_note_added') && journal.notes.present?) ||
- (Setting.notified_events.include?('issue_status_updated') && journal.new_status.present?) ||
- (Setting.notified_events.include?('issue_priority_updated') && journal.new_value_for('priority_id').present?)
- )
- # 将跟踪者与本项目的其他成员都设为收件方,并去重,不在进行抄送,
- recipients = journal.recipients - journal.watcher_recipients + journal.watcher_recipients
- recipients.each do |rec|
-
- Mailer.run.issue_edit(journal,rec)
- end
- 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 JournalObserver < ActiveRecord::Observer
+ def after_create(journal)
+ if journal.notify? &&
+ (Setting.notified_events.include?('issue_updated') ||
+ (Setting.notified_events.include?('issue_note_added') && journal.notes.present?) ||
+ (Setting.notified_events.include?('issue_status_updated') && journal.new_status.present?) ||
+ (Setting.notified_events.include?('issue_priority_updated') && journal.new_value_for('priority_id').present?)
+ )
+ # 将跟踪者与本项目的其他成员都设为收件方,并去重,不在进行抄送,
+ recipients = journal.recipients - journal.watcher_recipients + journal.watcher_recipients
+ recipients.each do |rec|
+
+ Mailer.run.issue_edit(journal,rec)
+ end
+ end
+ end
+end
diff --git a/app/models/journals_for_message.rb b/app/models/journals_for_message.rb
index dda45965e..239a15881 100644
--- a/app/models/journals_for_message.rb
+++ b/app/models/journals_for_message.rb
@@ -1,175 +1,179 @@
-# fq
-# 数据库字段中带有m前缀和is_readed是二次开发添加,之前的字段基本复用
-# 注意reply_id 是提到人的id,不是留言id, Base中叫做 at_user
-class JournalsForMessage < ActiveRecord::Base
- include Redmine::SafeAttributes
- include UserScoreHelper
- include ApplicationHelper
- has_many_kindeditor_assets :assets, :dependent => :destroy
- safe_attributes "jour_type", # 留言所属类型
- "jour_id", # 留言所属类型的id
- "notes", # 留言内容
- "reply_id", # 留言被回复留言者的用户id(用户a回复了用户b,这是b的id,用以查询谁给b留言了)
- "status", # 留言是否被查看(弃用)
- "user_id", # 留言者的id
- "m_parent_id", # 留言信息的父留言id
- "is_readed", # 留言是否已读
- "m_reply_count", # 留言的回复数量
- "m_reply_id" # 回复某留言的留言id(a留言回复了b留言,这是b留言的id)
- "is_comprehensive_evaluation" # 1 教师评论、2 匿评、3 留言
- acts_as_tree :foreign_key => 'm_parent_id', :counter_cache => :m_reply_count, :order => "#{JournalsForMessage.table_name}.created_on ASC"
- after_destroy :delete_kindeditor_assets
- belongs_to :project,
- :foreign_key => 'jour_id',
- :conditions => "#{self.table_name}.jour_type = 'Project' "
- belongs_to :course,
- :foreign_key => 'jour_id'
-
-
- belongs_to :jour, :polymorphic => true
- belongs_to :user
- belongs_to :homework_attach
- belongs_to :at_user, :class_name => "User", :foreign_key => 'reply_id'
-
- acts_as_event :title => Proc.new {|o| "#{l(:label_my_message)}"},
- :datetime => Proc.new {|o| o.updated_on },
- :author => Proc.new {|o| o.user },
- :description => Proc.new{|o| o.notes },
- :type => Proc.new {|o| o.jour_type },
- :url => Proc.new {|o|
- if o.jour.kind_of? Project
- {:controller => 'projects', :action => 'feedback', :id => o.jour, :r => o.id, :anchor => "word_li_#{o.id}"}
- elsif o.jour.kind_of? Course
- {:controller => 'courses', :action => 'feedback', :id => o.jour, :r => o.id, :anchor => "word_li_#{o.id}"}
- end
- }
- acts_as_activity_provider :author_key => :user_id,
- :timestamp => "#{self.table_name}.updated_on",
- :find_options => {:include => :project }
-
- acts_as_activity_provider :type => 'course_journals_for_messages',
- :author_key => :user_id,
- :permission => :view_course_journals_for_messages,
- :timestamp => "#{self.table_name}.updated_on",
- :find_options => {:include => :course }
-
-
- has_many :acts, :class_name => 'Activity', :as => :act, :dependent => :destroy
-
- validates :notes, presence: true
- after_create :act_as_activity #huang
- after_create :reset_counters!
- after_destroy :reset_counters!
- after_save :be_user_score
- after_destroy :down_user_score
-
- # default_scope { where('m_parent_id IS NULL') }
-
- def self.create_by_user? user
- if user.anonymous?
- return false
- else
- return true
- end
- end
-
-
- def self.remove_by_user? user
- if( self.user == user ||
- ( self.jour.kind_of?(User) && self.jour== user )
- )
- true
- else
- false
- end
- end
-
- def self.delete_message(message_id)
- self.find(message_id).destroy
- # self.destroy_all "id = #{message_id}"
- end
-
- def reference_user
- User.find(reply_id)
- end
-
- def delete_by_user?user
- # 用户可删除自己的留言
- if self.user.id == user.id || user.admin?
- return true
- else
- return false
- end
- end
-
- def self.reference_message(user_id)
- @user = User.find(user_id)
- message = JournalsForMessage.find_by_sql("select * from journals_for_messages where reply_id = #{@user.id}
- or (jour_type = 'Bid' and jour_id in (select id from bids where author_id = #{@user.id}))")
- message
- end
-
- def act_as_activity
- if self.jour_type == 'Principal'
- unless self.user_id == self.jour.id && self.user_id != self.reply_id && self.reply_id != 0
- # self.acts << Activity.new(:user_id => self.user_id)
- self.acts << Activity.new(:user_id => self.jour_id)
- end
- elsif self.jour_type == 'Project'
- self.acts << Activity.new(:user_id => self.reply_id)
- elsif self.jour_type == 'Course'
- self.acts << Activity.new(:user_id => self.reply_id)
- else
- end
- end
-
- def reset_counters!
- self.class.reset_counters!(self)
- end
- def self.reset_counters! journals_for_messages
- # jfm_id = journals_for_messages.id.to_i
- count = find_all_by_m_parent_id(journals_for_messages.m_parent_id).count #(SELECT COUNT(*) FROM #{JournalsForMessage.table_name} WHERE m_parent_id = #{jfm_id} )
- update_all("m_reply_count = #{count.to_i}", ["id = ?", journals_for_messages.m_parent_id])
- end
-
- #如果是在项目中留言则返回该项目否则返回nil - zjc
- def project
- if self.jour_type == 'Project'
- Project.find(self.jour_id)
- else
- nil
- end
- end
-
- # 更新用户分数 -by zjc
- def be_user_score
- #新建了留言回复
- if self.reply_id != 0
- #协同得分加分
- UserScore.joint(:reply_message, self.user,User.find(self.reply_id),self, { journals_for_messages_id: self.id })
- update_replay_for_message(self.user,1)
- if self.jour_type == "Project"
- update_replay_for_message(self.user,2,self.jour)
- end
- end
- end
- # 更新用户分数 -by zjc
- def down_user_score
- #删除了留言回复
- if self.reply_id != 0
- #协同得分减分
- UserScore.joint(:reply_message_delete, self.user,User.find(self.reply_id), { journals_for_messages_id: self.id })
- update_replay_for_message(self.user,1)
- if self.jour_type == "Project"
- update_replay_for_message(self.user,2,self.jour)
- end
- end
- end
-
- # Time 2015-04-01 14:15:06
- # Author lizanle
- # Description 删除对应课程留言的图片资源
- def delete_kindeditor_assets
- delete_kindeditor_assets_from_disk self.id,7
- end
-end
+# fq
+# 数据库字段中带有m前缀和is_readed是二次开发添加,之前的字段基本复用
+# 注意reply_id 是提到人的id,不是留言id, Base中叫做 at_user
+class JournalsForMessage < ActiveRecord::Base
+ include Redmine::SafeAttributes
+ include UserScoreHelper
+ include ApplicationHelper
+ has_many_kindeditor_assets :assets, :dependent => :destroy
+ safe_attributes "jour_type", # 留言所属类型
+ "jour_id", # 留言所属类型的id
+ "notes", # 留言内容
+ "reply_id", # 留言被回复留言者的用户id(用户a回复了用户b,这是b的id,用以查询谁给b留言了)
+ "status", # 留言是否被查看(弃用)
+ "user_id", # 留言者的id
+ "m_parent_id", # 留言信息的父留言id
+ "is_readed", # 留言是否已读
+ "m_reply_count", # 留言的回复数量
+ "m_reply_id" # 回复某留言的留言id(a留言回复了b留言,这是b留言的id)
+ "is_comprehensive_evaluation" # 1 教师评论、2 匿评、3 留言
+ acts_as_tree :foreign_key => 'm_parent_id', :counter_cache => :m_reply_count, :order => "#{JournalsForMessage.table_name}.created_on ASC"
+ after_destroy :delete_kindeditor_assets
+ belongs_to :project,
+ :foreign_key => 'jour_id',
+ :conditions => "#{self.table_name}.jour_type = 'Project' "
+ belongs_to :course,
+ :foreign_key => 'jour_id'
+
+
+ belongs_to :jour, :polymorphic => true
+ belongs_to :user
+ belongs_to :homework_attach
+ belongs_to :at_user, :class_name => "User", :foreign_key => 'reply_id'
+
+ acts_as_event :title => Proc.new {|o| "#{l(:label_my_message)}"},
+ :datetime => Proc.new {|o| o.updated_on },
+ :author => Proc.new {|o| o.user },
+ :description => Proc.new{|o| o.notes },
+ :type => Proc.new {|o| o.jour_type },
+ :url => Proc.new {|o|
+ if o.jour.kind_of? Project
+ {:controller => 'projects', :action => 'feedback', :id => o.jour, :r => o.id, :anchor => "word_li_#{o.id}"}
+ elsif o.jour.kind_of? Course
+ {:controller => 'courses', :action => 'feedback', :id => o.jour, :r => o.id, :anchor => "word_li_#{o.id}"}
+ end
+ }
+ acts_as_activity_provider :author_key => :user_id,
+ :timestamp => "#{self.table_name}.updated_on",
+ :find_options => {:include => :project }
+
+ acts_as_activity_provider :type => 'course_journals_for_messages',
+ :author_key => :user_id,
+ :permission => :view_course_journals_for_messages,
+ :timestamp => "#{self.table_name}.updated_on",
+ :find_options => {:include => :course }
+ acts_as_attachable
+
+ has_many :acts, :class_name => 'Activity', :as => :act, :dependent => :destroy
+
+ validates :notes, presence: true, if: :is_homework_jour?
+ after_create :act_as_activity #huang
+ after_create :reset_counters!
+ after_destroy :reset_counters!
+ after_save :be_user_score
+ after_destroy :down_user_score
+
+ # default_scope { where('m_parent_id IS NULL') }
+
+ def self.create_by_user? user
+ if user.anonymous?
+ return false
+ else
+ return true
+ end
+ end
+
+
+ def self.remove_by_user? user
+ if( self.user == user ||
+ ( self.jour.kind_of?(User) && self.jour== user )
+ )
+ true
+ else
+ false
+ end
+ end
+
+ def self.delete_message(message_id)
+ self.find(message_id).destroy
+ # self.destroy_all "id = #{message_id}"
+ end
+
+ def is_homework_jour?
+ self.jour_type != "HomeworkAttach"
+ end
+
+ def reference_user
+ User.find(reply_id)
+ end
+
+ def delete_by_user?user
+ # 用户可删除自己的留言
+ if self.user.id == user.id || user.admin?
+ return true
+ else
+ return false
+ end
+ end
+
+ def self.reference_message(user_id)
+ @user = User.find(user_id)
+ message = JournalsForMessage.find_by_sql("select * from journals_for_messages where reply_id = #{@user.id}
+ or (jour_type = 'Bid' and jour_id in (select id from bids where author_id = #{@user.id}))")
+ message
+ end
+
+ def act_as_activity
+ if self.jour_type == 'Principal'
+ unless self.user_id == self.jour.id && self.user_id != self.reply_id && self.reply_id != 0
+ # self.acts << Activity.new(:user_id => self.user_id)
+ self.acts << Activity.new(:user_id => self.jour_id)
+ end
+ elsif self.jour_type == 'Project'
+ self.acts << Activity.new(:user_id => self.reply_id)
+ elsif self.jour_type == 'Course'
+ self.acts << Activity.new(:user_id => self.reply_id)
+ else
+ end
+ end
+
+ def reset_counters!
+ self.class.reset_counters!(self)
+ end
+ def self.reset_counters! journals_for_messages
+ # jfm_id = journals_for_messages.id.to_i
+ count = find_all_by_m_parent_id(journals_for_messages.m_parent_id).count #(SELECT COUNT(*) FROM #{JournalsForMessage.table_name} WHERE m_parent_id = #{jfm_id} )
+ update_all("m_reply_count = #{count.to_i}", ["id = ?", journals_for_messages.m_parent_id])
+ end
+
+ #如果是在项目中留言则返回该项目否则返回nil - zjc
+ def project
+ if self.jour_type == 'Project'
+ Project.find(self.jour_id)
+ else
+ nil
+ end
+ end
+
+ # 更新用户分数 -by zjc
+ def be_user_score
+ #新建了留言回复
+ if self.reply_id != 0
+ #协同得分加分
+ UserScore.joint(:reply_message, self.user,User.find(self.reply_id),self, { journals_for_messages_id: self.id })
+ update_replay_for_message(self.user,1)
+ if self.jour_type == "Project"
+ update_replay_for_message(self.user,2,self.jour)
+ end
+ end
+ end
+ # 更新用户分数 -by zjc
+ def down_user_score
+ #删除了留言回复
+ if self.reply_id != 0
+ #协同得分减分
+ UserScore.joint(:reply_message_delete, self.user,User.find(self.reply_id), { journals_for_messages_id: self.id })
+ update_replay_for_message(self.user,1)
+ if self.jour_type == "Project"
+ update_replay_for_message(self.user,2,self.jour)
+ end
+ end
+ end
+
+ # Time 2015-04-01 14:15:06
+ # Author lizanle
+ # Description 删除对应课程留言的图片资源
+ def delete_kindeditor_assets
+ delete_kindeditor_assets_from_disk self.id,7
+ end
+end
diff --git a/app/models/journals_for_message_observer.rb b/app/models/journals_for_message_observer.rb
index ee8e28b86..0db2e0043 100644
--- a/app/models/journals_for_message_observer.rb
+++ b/app/models/journals_for_message_observer.rb
@@ -1,7 +1,7 @@
-# Added by young
-class JournalsForMessageObserver < ActiveRecord::Observer
- def after_create(journals_for_message)
- Mailer.run.journals_for_message_add(User.current, journals_for_message)
- end
-end
-
+# Added by young
+class JournalsForMessageObserver < ActiveRecord::Observer
+ def after_create(journals_for_message)
+ Mailer.run.journals_for_message_add(User.current, journals_for_message)
+ end
+end
+
diff --git a/app/models/mail_handler.rb b/app/models/mail_handler.rb
index da1af66a8..bf268ad66 100644
--- a/app/models/mail_handler.rb
+++ b/app/models/mail_handler.rb
@@ -1,490 +1,490 @@
-# 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 MailHandler < ActionMailer::Base
- include ActionView::Helpers::SanitizeHelper
- include Redmine::I18n
-
- class UnauthorizedAction < StandardError; end
- class MissingInformation < StandardError; end
-
- attr_reader :email, :user
-
- def self.receive(email, options={})
- @@handler_options = options.dup
-
- @@handler_options[:issue] ||= {}
-
- if @@handler_options[:allow_override].is_a?(String)
- @@handler_options[:allow_override] = @@handler_options[:allow_override].split(',').collect(&:strip)
- end
- @@handler_options[:allow_override] ||= []
- # Project needs to be overridable if not specified
- @@handler_options[:allow_override] << 'project' unless @@handler_options[:issue].has_key?(:project)
- # Status overridable by default
- @@handler_options[:allow_override] << 'status' unless @@handler_options[:issue].has_key?(:status)
-
- @@handler_options[:no_account_notice] = (@@handler_options[:no_account_notice].to_s == '1')
- @@handler_options[:no_notification] = (@@handler_options[:no_notification].to_s == '1')
- @@handler_options[:no_permission_check] = (@@handler_options[:no_permission_check].to_s == '1')
-
- email.force_encoding('ASCII-8BIT') if email.respond_to?(:force_encoding)
- super(email)
- end
-
- def logger
- Rails.logger
- end
-
- cattr_accessor :ignored_emails_headers
- @@ignored_emails_headers = {
- 'X-Auto-Response-Suppress' => 'oof',
- 'Auto-Submitted' => /^auto-/
- }
-
- # Processes incoming emails
- # Returns the created object (eg. an issue, a message) or false
- def receive(email)
- @email = email
- sender_email = email.from.to_a.first.to_s.strip
- # Ignore emails received from the application emission address to avoid hell cycles
- if sender_email.downcase == Setting.mail_from.to_s.strip.downcase
- if logger && logger.info
- logger.info "MailHandler: ignoring email from Redmine emission address [#{sender_email}]"
- end
- return false
- end
- # Ignore auto generated emails
- self.class.ignored_emails_headers.each do |key, ignored_value|
- value = email.header[key]
- if value
- value = value.to_s.downcase
- if (ignored_value.is_a?(Regexp) && value.match(ignored_value)) || value == ignored_value
- if logger && logger.info
- logger.info "MailHandler: ignoring email with #{key}:#{value} header"
- end
- return false
- end
- end
- end
- @user = User.find_by_mail(sender_email) if sender_email.present?
- if @user && !@user.active?
- if logger && logger.info
- logger.info "MailHandler: ignoring email from non-active user [#{@user.login}]"
- end
- return false
- end
- if @user.nil?
- # Email was submitted by an unknown user
- case @@handler_options[:unknown_user]
- when 'accept'
- @user = User.anonymous
- when 'create'
- @user = create_user_from_email
- if @user
- if logger && logger.info
- logger.info "MailHandler: [#{@user.login}] account created"
- end
- add_user_to_group(@@handler_options[:default_group])
- unless @@handler_options[:no_account_notice]
- Mailer.run.account_information(@user, @user.password)
- end
- else
- if logger && logger.error
- logger.error "MailHandler: could not create account for [#{sender_email}]"
- end
- return false
- end
- else
- # Default behaviour, emails from unknown users are ignored
- if logger && logger.info
- logger.info "MailHandler: ignoring email from unknown user [#{sender_email}]"
- end
- return false
- end
- end
- User.current = @user
- dispatch
- end
-
- private
-
- MESSAGE_ID_RE = %r{^ e
- # TODO: send a email to the user
- logger.error e.message if logger
- false
- rescue MissingInformation => e
- logger.error "MailHandler: missing information from #{user}: #{e.message}" if logger
- false
- rescue UnauthorizedAction => e
- logger.error "MailHandler: unauthorized attempt from #{user}" if logger
- false
- end
-
- def dispatch_to_default
- receive_issue
- end
-
- # Creates a new issue
- def receive_issue
- project = target_project
- # check permission
- unless @@handler_options[:no_permission_check]
- raise UnauthorizedAction unless user.allowed_to?(:add_issues, project)
- end
-
- issue = Issue.new(:author => user, :project => project)
- issue.safe_attributes = issue_attributes_from_keywords(issue)
- issue.safe_attributes = {'custom_field_values' => custom_field_values_from_keywords(issue)}
- issue.subject = cleaned_up_subject
- if issue.subject.blank?
- issue.subject = '(no subject)'
- end
- issue.description = cleaned_up_text_body
-
- # add To and Cc as watchers before saving so the watchers can reply to Redmine
- add_watchers(issue)
- issue.save!
- add_attachments(issue)
- logger.info "MailHandler: issue ##{issue.id} created by #{user}" if logger && logger.info
- issue
- end
-
- # Adds a note to an existing issue
- def receive_issue_reply(issue_id, from_journal=nil)
- issue = Issue.find_by_id(issue_id)
- return unless issue
- # check permission
- unless @@handler_options[:no_permission_check]
- unless user.allowed_to?(:add_issue_notes, issue.project) ||
- user.allowed_to?(:edit_issues, issue.project)
- raise UnauthorizedAction
- end
- end
-
- # ignore CLI-supplied defaults for new issues
- @@handler_options[:issue].clear
-
- journal = issue.init_journal(user)
- if from_journal && from_journal.private_notes?
- # If the received email was a reply to a private note, make the added note private
- issue.private_notes = true
- end
- issue.safe_attributes = issue_attributes_from_keywords(issue)
- issue.safe_attributes = {'custom_field_values' => custom_field_values_from_keywords(issue)}
- journal.notes = cleaned_up_text_body
- add_attachments(issue)
- issue.save!
- if logger && logger.info
- logger.info "MailHandler: issue ##{issue.id} updated by #{user}"
- end
- journal
- end
-
- # Reply will be added to the issue
- def receive_journal_reply(journal_id)
- journal = Journal.find_by_id(journal_id)
- if journal && journal.journalized_type == 'Issue'
- receive_issue_reply(journal.journalized_id, journal)
- end
- end
-
- # Receives a reply to a forum message
- def receive_message_reply(message_id)
- message = Message.find_by_id(message_id)
- if message
- message = message.root
-
- unless @@handler_options[:no_permission_check]
- raise UnauthorizedAction unless user.allowed_to?(:add_messages, message.project)
- end
-
- if !message.locked?
- reply = Message.new(:subject => cleaned_up_subject.gsub(%r{^.*msg\d+\]}, '').strip,
- :content => cleaned_up_text_body)
- reply.author = user
- reply.board = message.board
- message.children << reply
- add_attachments(reply)
- reply
- else
- if logger && logger.info
- logger.info "MailHandler: ignoring reply from [#{sender_email}] to a locked topic"
- end
- end
- end
- end
-
- def add_attachments(obj)
- if email.attachments && email.attachments.any?
- email.attachments.each do |attachment|
- obj.attachments << Attachment.create(:container => obj,
- :file => attachment.decoded,
- :filename => attachment.filename,
- :author => user,
- :content_type => attachment.mime_type)
- end
- end
- end
-
- # Adds To and Cc as watchers of the given object if the sender has the
- # appropriate permission
- def add_watchers(obj)
- if user.allowed_to?("add_#{obj.class.name.underscore}_watchers".to_sym, obj.project)
- addresses = [email.to, email.cc].flatten.compact.uniq.collect {|a| a.strip.downcase}
- unless addresses.empty?
- watchers = User.active.where('LOWER(mail) IN (?)', addresses).all
- watchers.each {|w| obj.add_watcher(w)}
- end
- end
- end
-
- def get_keyword(attr, options={})
- @keywords ||= {}
- if @keywords.has_key?(attr)
- @keywords[attr]
- else
- @keywords[attr] = begin
- if (options[:override] || @@handler_options[:allow_override].include?(attr.to_s)) &&
- (v = extract_keyword!(plain_text_body, attr, options[:format]))
- v
- elsif !@@handler_options[:issue][attr].blank?
- @@handler_options[:issue][attr]
- end
- end
- end
- end
-
- # Destructively extracts the value for +attr+ in +text+
- # Returns nil if no matching keyword found
- def extract_keyword!(text, attr, format=nil)
- keys = [attr.to_s.humanize]
- if attr.is_a?(Symbol)
- if user && user.language.present?
- keys << l("field_#{attr}", :default => '', :locale => user.language)
- end
- if Setting.default_language.present?
- keys << l("field_#{attr}", :default => '', :locale => Setting.default_language)
- end
- end
- keys.reject! {|k| k.blank?}
- keys.collect! {|k| Regexp.escape(k)}
- format ||= '.+'
- keyword = nil
- regexp = /^(#{keys.join('|')})[ \t]*:[ \t]*(#{format})\s*$/i
- if m = text.match(regexp)
- keyword = m[2].strip
- text.gsub!(regexp, '')
- end
- keyword
- end
-
- def target_project
- # TODO: other ways to specify project:
- # * parse the email To field
- # * specific project (eg. Setting.mail_handler_target_project)
- target = Project.find_by_identifier(get_keyword(:project))
- raise MissingInformation.new('Unable to determine target project') if target.nil?
- target
- end
-
- # Returns a Hash of issue attributes extracted from keywords in the email body
- def issue_attributes_from_keywords(issue)
- assigned_to = (k = get_keyword(:assigned_to, :override => true)) && find_assignee_from_keyword(k, issue)
-
- attrs = {
- 'tracker_id' => (k = get_keyword(:tracker)) && issue.project.trackers.named(k).first.try(:id),
- 'status_id' => (k = get_keyword(:status)) && IssueStatus.named(k).first.try(:id),
- 'priority_id' => (k = get_keyword(:priority)) && IssuePriority.named(k).first.try(:id),
- 'category_id' => (k = get_keyword(:category)) && issue.project.issue_categories.named(k).first.try(:id),
- 'assigned_to_id' => assigned_to.try(:id),
- 'fixed_version_id' => (k = get_keyword(:fixed_version, :override => true)) &&
- issue.project.shared_versions.named(k).first.try(:id),
- 'start_date' => get_keyword(:start_date, :override => true, :format => '\d{4}-\d{2}-\d{2}'),
- 'due_date' => get_keyword(:due_date, :override => true, :format => '\d{4}-\d{2}-\d{2}'),
- 'estimated_hours' => get_keyword(:estimated_hours, :override => true),
- 'done_ratio' => get_keyword(:done_ratio, :override => true, :format => '(\d|10)?0')
- }.delete_if {|k, v| v.blank? }
-
- if issue.new_record? && attrs['tracker_id'].nil?
- attrs['tracker_id'] = issue.project.trackers.first.try(:id)
- end
-
- attrs
- end
-
- # Returns a Hash of issue custom field values extracted from keywords in the email body
- def custom_field_values_from_keywords(customized)
- customized.custom_field_values.inject({}) do |h, v|
- if keyword = get_keyword(v.custom_field.name, :override => true)
- h[v.custom_field.id.to_s] = v.custom_field.value_from_keyword(keyword, customized)
- end
- h
- end
- end
-
- # Returns the text/plain part of the email
- # If not found (eg. HTML-only email), returns the body with tags removed
- def plain_text_body
- return @plain_text_body unless @plain_text_body.nil?
-
- part = email.text_part || email.html_part || email
- @plain_text_body = Redmine::CodesetUtil.to_utf8(part.body.decoded, part.charset)
-
- # strip html tags and remove doctype directive
- @plain_text_body = strip_tags(@plain_text_body.strip)
- @plain_text_body.sub! %r{^$/)
- addr, name = m[2], m[1]
- end
- if addr.present?
- user = self.class.new_user_from_attributes(addr, name)
- if @@handler_options[:no_notification]
- user.mail_notification = 'none'
- end
- if user.save
- user
- else
- logger.error "MailHandler: failed to create User: #{user.errors.full_messages}" if logger
- nil
- end
- else
- logger.error "MailHandler: failed to create User: no FROM address found" if logger
- nil
- end
- end
-
- # Adds the newly created user to default group
- def add_user_to_group(default_group)
- if default_group.present?
- default_group.split(',').each do |group_name|
- if group = Group.named(group_name).first
- group.users << @user
- elsif logger
- logger.warn "MailHandler: could not add user to [#{group_name}], group not found"
- end
- end
- end
- end
-
- # Removes the email body of text after the truncation configurations.
- def cleanup_body(body)
- delimiters = Setting.mail_handler_body_delimiters.to_s.split(/[\r\n]+/).reject(&:blank?).map {|s| Regexp.escape(s)}
- unless delimiters.empty?
- regex = Regexp.new("^[> ]*(#{ delimiters.join('|') })\s*[\r\n].*", Regexp::MULTILINE)
- body = body.gsub(regex, '')
- end
- body.strip
- end
-
- def find_assignee_from_keyword(keyword, issue)
- keyword = keyword.to_s.downcase
- assignable = issue.assignable_users
- assignee = nil
- assignee ||= assignable.detect {|a|
- a.mail.to_s.downcase == keyword ||
- a.login.to_s.downcase == keyword
- }
- if assignee.nil? && keyword.match(/ /)
- firstname, lastname = *(keyword.split) # "First Last Throwaway"
- assignee ||= assignable.detect {|a|
- a.is_a?(User) && a.firstname.to_s.downcase == firstname &&
- a.lastname.to_s.downcase == lastname
- }
- end
- if assignee.nil?
- assignee ||= assignable.detect {|a| a.name.downcase == keyword}
- end
- assignee
- 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 MailHandler < ActionMailer::Base
+ include ActionView::Helpers::SanitizeHelper
+ include Redmine::I18n
+
+ class UnauthorizedAction < StandardError; end
+ class MissingInformation < StandardError; end
+
+ attr_reader :email, :user
+
+ def self.receive(email, options={})
+ @@handler_options = options.dup
+
+ @@handler_options[:issue] ||= {}
+
+ if @@handler_options[:allow_override].is_a?(String)
+ @@handler_options[:allow_override] = @@handler_options[:allow_override].split(',').collect(&:strip)
+ end
+ @@handler_options[:allow_override] ||= []
+ # Project needs to be overridable if not specified
+ @@handler_options[:allow_override] << 'project' unless @@handler_options[:issue].has_key?(:project)
+ # Status overridable by default
+ @@handler_options[:allow_override] << 'status' unless @@handler_options[:issue].has_key?(:status)
+
+ @@handler_options[:no_account_notice] = (@@handler_options[:no_account_notice].to_s == '1')
+ @@handler_options[:no_notification] = (@@handler_options[:no_notification].to_s == '1')
+ @@handler_options[:no_permission_check] = (@@handler_options[:no_permission_check].to_s == '1')
+
+ email.force_encoding('ASCII-8BIT') if email.respond_to?(:force_encoding)
+ super(email)
+ end
+
+ def logger
+ Rails.logger
+ end
+
+ cattr_accessor :ignored_emails_headers
+ @@ignored_emails_headers = {
+ 'X-Auto-Response-Suppress' => 'oof',
+ 'Auto-Submitted' => /^auto-/
+ }
+
+ # Processes incoming emails
+ # Returns the created object (eg. an issue, a message) or false
+ def receive(email)
+ @email = email
+ sender_email = email.from.to_a.first.to_s.strip
+ # Ignore emails received from the application emission address to avoid hell cycles
+ if sender_email.downcase == Setting.mail_from.to_s.strip.downcase
+ if logger && logger.info
+ logger.info "MailHandler: ignoring email from Redmine emission address [#{sender_email}]"
+ end
+ return false
+ end
+ # Ignore auto generated emails
+ self.class.ignored_emails_headers.each do |key, ignored_value|
+ value = email.header[key]
+ if value
+ value = value.to_s.downcase
+ if (ignored_value.is_a?(Regexp) && value.match(ignored_value)) || value == ignored_value
+ if logger && logger.info
+ logger.info "MailHandler: ignoring email with #{key}:#{value} header"
+ end
+ return false
+ end
+ end
+ end
+ @user = User.find_by_mail(sender_email) if sender_email.present?
+ if @user && !@user.active?
+ if logger && logger.info
+ logger.info "MailHandler: ignoring email from non-active user [#{@user.login}]"
+ end
+ return false
+ end
+ if @user.nil?
+ # Email was submitted by an unknown user
+ case @@handler_options[:unknown_user]
+ when 'accept'
+ @user = User.anonymous
+ when 'create'
+ @user = create_user_from_email
+ if @user
+ if logger && logger.info
+ logger.info "MailHandler: [#{@user.login}] account created"
+ end
+ add_user_to_group(@@handler_options[:default_group])
+ unless @@handler_options[:no_account_notice]
+ Mailer.run.account_information(@user, @user.password)
+ end
+ else
+ if logger && logger.error
+ logger.error "MailHandler: could not create account for [#{sender_email}]"
+ end
+ return false
+ end
+ else
+ # Default behaviour, emails from unknown users are ignored
+ if logger && logger.info
+ logger.info "MailHandler: ignoring email from unknown user [#{sender_email}]"
+ end
+ return false
+ end
+ end
+ User.current = @user
+ dispatch
+ end
+
+ private
+
+ MESSAGE_ID_RE = %r{^ e
+ # TODO: send a email to the user
+ logger.error e.message if logger
+ false
+ rescue MissingInformation => e
+ logger.error "MailHandler: missing information from #{user}: #{e.message}" if logger
+ false
+ rescue UnauthorizedAction => e
+ logger.error "MailHandler: unauthorized attempt from #{user}" if logger
+ false
+ end
+
+ def dispatch_to_default
+ receive_issue
+ end
+
+ # Creates a new issue
+ def receive_issue
+ project = target_project
+ # check permission
+ unless @@handler_options[:no_permission_check]
+ raise UnauthorizedAction unless user.allowed_to?(:add_issues, project)
+ end
+
+ issue = Issue.new(:author => user, :project => project)
+ issue.safe_attributes = issue_attributes_from_keywords(issue)
+ issue.safe_attributes = {'custom_field_values' => custom_field_values_from_keywords(issue)}
+ issue.subject = cleaned_up_subject
+ if issue.subject.blank?
+ issue.subject = '(no subject)'
+ end
+ issue.description = cleaned_up_text_body
+
+ # add To and Cc as watchers before saving so the watchers can reply to Redmine
+ add_watchers(issue)
+ issue.save!
+ add_attachments(issue)
+ logger.info "MailHandler: issue ##{issue.id} created by #{user}" if logger && logger.info
+ issue
+ end
+
+ # Adds a note to an existing issue
+ def receive_issue_reply(issue_id, from_journal=nil)
+ issue = Issue.find_by_id(issue_id)
+ return unless issue
+ # check permission
+ unless @@handler_options[:no_permission_check]
+ unless user.allowed_to?(:add_issue_notes, issue.project) ||
+ user.allowed_to?(:edit_issues, issue.project)
+ raise UnauthorizedAction
+ end
+ end
+
+ # ignore CLI-supplied defaults for new issues
+ @@handler_options[:issue].clear
+
+ journal = issue.init_journal(user)
+ if from_journal && from_journal.private_notes?
+ # If the received email was a reply to a private note, make the added note private
+ issue.private_notes = true
+ end
+ issue.safe_attributes = issue_attributes_from_keywords(issue)
+ issue.safe_attributes = {'custom_field_values' => custom_field_values_from_keywords(issue)}
+ journal.notes = cleaned_up_text_body
+ add_attachments(issue)
+ issue.save!
+ if logger && logger.info
+ logger.info "MailHandler: issue ##{issue.id} updated by #{user}"
+ end
+ journal
+ end
+
+ # Reply will be added to the issue
+ def receive_journal_reply(journal_id)
+ journal = Journal.find_by_id(journal_id)
+ if journal && journal.journalized_type == 'Issue'
+ receive_issue_reply(journal.journalized_id, journal)
+ end
+ end
+
+ # Receives a reply to a forum message
+ def receive_message_reply(message_id)
+ message = Message.find_by_id(message_id)
+ if message
+ message = message.root
+
+ unless @@handler_options[:no_permission_check]
+ raise UnauthorizedAction unless user.allowed_to?(:add_messages, message.project)
+ end
+
+ if !message.locked?
+ reply = Message.new(:subject => cleaned_up_subject.gsub(%r{^.*msg\d+\]}, '').strip,
+ :content => cleaned_up_text_body)
+ reply.author = user
+ reply.board = message.board
+ message.children << reply
+ add_attachments(reply)
+ reply
+ else
+ if logger && logger.info
+ logger.info "MailHandler: ignoring reply from [#{sender_email}] to a locked topic"
+ end
+ end
+ end
+ end
+
+ def add_attachments(obj)
+ if email.attachments && email.attachments.any?
+ email.attachments.each do |attachment|
+ obj.attachments << Attachment.create(:container => obj,
+ :file => attachment.decoded,
+ :filename => attachment.filename,
+ :author => user,
+ :content_type => attachment.mime_type)
+ end
+ end
+ end
+
+ # Adds To and Cc as watchers of the given object if the sender has the
+ # appropriate permission
+ def add_watchers(obj)
+ if user.allowed_to?("add_#{obj.class.name.underscore}_watchers".to_sym, obj.project)
+ addresses = [email.to, email.cc].flatten.compact.uniq.collect {|a| a.strip.downcase}
+ unless addresses.empty?
+ watchers = User.active.where('LOWER(mail) IN (?)', addresses).all
+ watchers.each {|w| obj.add_watcher(w)}
+ end
+ end
+ end
+
+ def get_keyword(attr, options={})
+ @keywords ||= {}
+ if @keywords.has_key?(attr)
+ @keywords[attr]
+ else
+ @keywords[attr] = begin
+ if (options[:override] || @@handler_options[:allow_override].include?(attr.to_s)) &&
+ (v = extract_keyword!(plain_text_body, attr, options[:format]))
+ v
+ elsif !@@handler_options[:issue][attr].blank?
+ @@handler_options[:issue][attr]
+ end
+ end
+ end
+ end
+
+ # Destructively extracts the value for +attr+ in +text+
+ # Returns nil if no matching keyword found
+ def extract_keyword!(text, attr, format=nil)
+ keys = [attr.to_s.humanize]
+ if attr.is_a?(Symbol)
+ if user && user.language.present?
+ keys << l("field_#{attr}", :default => '', :locale => user.language)
+ end
+ if Setting.default_language.present?
+ keys << l("field_#{attr}", :default => '', :locale => Setting.default_language)
+ end
+ end
+ keys.reject! {|k| k.blank?}
+ keys.collect! {|k| Regexp.escape(k)}
+ format ||= '.+'
+ keyword = nil
+ regexp = /^(#{keys.join('|')})[ \t]*:[ \t]*(#{format})\s*$/i
+ if m = text.match(regexp)
+ keyword = m[2].strip
+ text.gsub!(regexp, '')
+ end
+ keyword
+ end
+
+ def target_project
+ # TODO: other ways to specify project:
+ # * parse the email To field
+ # * specific project (eg. Setting.mail_handler_target_project)
+ target = Project.find_by_identifier(get_keyword(:project))
+ raise MissingInformation.new('Unable to determine target project') if target.nil?
+ target
+ end
+
+ # Returns a Hash of issue attributes extracted from keywords in the email body
+ def issue_attributes_from_keywords(issue)
+ assigned_to = (k = get_keyword(:assigned_to, :override => true)) && find_assignee_from_keyword(k, issue)
+
+ attrs = {
+ 'tracker_id' => (k = get_keyword(:tracker)) && issue.project.trackers.named(k).first.try(:id),
+ 'status_id' => (k = get_keyword(:status)) && IssueStatus.named(k).first.try(:id),
+ 'priority_id' => (k = get_keyword(:priority)) && IssuePriority.named(k).first.try(:id),
+ 'category_id' => (k = get_keyword(:category)) && issue.project.issue_categories.named(k).first.try(:id),
+ 'assigned_to_id' => assigned_to.try(:id),
+ 'fixed_version_id' => (k = get_keyword(:fixed_version, :override => true)) &&
+ issue.project.shared_versions.named(k).first.try(:id),
+ 'start_date' => get_keyword(:start_date, :override => true, :format => '\d{4}-\d{2}-\d{2}'),
+ 'due_date' => get_keyword(:due_date, :override => true, :format => '\d{4}-\d{2}-\d{2}'),
+ 'estimated_hours' => get_keyword(:estimated_hours, :override => true),
+ 'done_ratio' => get_keyword(:done_ratio, :override => true, :format => '(\d|10)?0')
+ }.delete_if {|k, v| v.blank? }
+
+ if issue.new_record? && attrs['tracker_id'].nil?
+ attrs['tracker_id'] = issue.project.trackers.first.try(:id)
+ end
+
+ attrs
+ end
+
+ # Returns a Hash of issue custom field values extracted from keywords in the email body
+ def custom_field_values_from_keywords(customized)
+ customized.custom_field_values.inject({}) do |h, v|
+ if keyword = get_keyword(v.custom_field.name, :override => true)
+ h[v.custom_field.id.to_s] = v.custom_field.value_from_keyword(keyword, customized)
+ end
+ h
+ end
+ end
+
+ # Returns the text/plain part of the email
+ # If not found (eg. HTML-only email), returns the body with tags removed
+ def plain_text_body
+ return @plain_text_body unless @plain_text_body.nil?
+
+ part = email.text_part || email.html_part || email
+ @plain_text_body = Redmine::CodesetUtil.to_utf8(part.body.decoded, part.charset)
+
+ # strip html tags and remove doctype directive
+ @plain_text_body = strip_tags(@plain_text_body.strip)
+ @plain_text_body.sub! %r{^$/)
+ addr, name = m[2], m[1]
+ end
+ if addr.present?
+ user = self.class.new_user_from_attributes(addr, name)
+ if @@handler_options[:no_notification]
+ user.mail_notification = 'none'
+ end
+ if user.save
+ user
+ else
+ logger.error "MailHandler: failed to create User: #{user.errors.full_messages}" if logger
+ nil
+ end
+ else
+ logger.error "MailHandler: failed to create User: no FROM address found" if logger
+ nil
+ end
+ end
+
+ # Adds the newly created user to default group
+ def add_user_to_group(default_group)
+ if default_group.present?
+ default_group.split(',').each do |group_name|
+ if group = Group.named(group_name).first
+ group.users << @user
+ elsif logger
+ logger.warn "MailHandler: could not add user to [#{group_name}], group not found"
+ end
+ end
+ end
+ end
+
+ # Removes the email body of text after the truncation configurations.
+ def cleanup_body(body)
+ delimiters = Setting.mail_handler_body_delimiters.to_s.split(/[\r\n]+/).reject(&:blank?).map {|s| Regexp.escape(s)}
+ unless delimiters.empty?
+ regex = Regexp.new("^[> ]*(#{ delimiters.join('|') })\s*[\r\n].*", Regexp::MULTILINE)
+ body = body.gsub(regex, '')
+ end
+ body.strip
+ end
+
+ def find_assignee_from_keyword(keyword, issue)
+ keyword = keyword.to_s.downcase
+ assignable = issue.assignable_users
+ assignee = nil
+ assignee ||= assignable.detect {|a|
+ a.mail.to_s.downcase == keyword ||
+ a.login.to_s.downcase == keyword
+ }
+ if assignee.nil? && keyword.match(/ /)
+ firstname, lastname = *(keyword.split) # "First Last Throwaway"
+ assignee ||= assignable.detect {|a|
+ a.is_a?(User) && a.firstname.to_s.downcase == firstname &&
+ a.lastname.to_s.downcase == lastname
+ }
+ end
+ if assignee.nil?
+ assignee ||= assignable.detect {|a| a.name.downcase == keyword}
+ end
+ assignee
+ end
+end
diff --git a/app/models/mailer.rb b/app/models/mailer.rb
index a6acb1635..7756b7e27 100644
--- a/app/models/mailer.rb
+++ b/app/models/mailer.rb
@@ -1,908 +1,931 @@
-# 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 Mailer < ActionMailer::Base
- layout 'mailer'
- helper :application
- helper :issues
- helper :custom_fields
-
- include Redmine::I18n
- include CoursesHelper
- def self.default_url_options
- { :host => Setting.host_name, :protocol => Setting.protocol }
- end
-
-
- class MailerProxy
- def initialize(cls)
- @target = cls
- end
- def method_missing(name, *args, &block)
- if Setting.delayjob_enabled && Object.const_defined?('Delayed')
- @target.delay.send(name, *args, &block)
- else
- @target.send(name, *args, &block).deliver
- end
- end
- end
-
- def self.run
- MailerProxy.new(self)
- end
-
- # author: alan
- # 发送邀请未注册用户加入项目邮件
- # 功能: 在加入项目的同时自动注册用户
- def send_invite_in_project(email, project, invitor)
- @email = email
- @subject = "#{invitor.name} #{l(:label_invite_project)} #{project.name} "
- @password = newpass(6)
- @project_url = url_for(:controller => 'projects', :action => 'show', :id => project.id,
- :password => @password, :login => email)
- mail :to => email, :subject => @subject
- end
-
- # author: alan
- # 根据用户选择发送个人日报或周报
- # 发送内容: 项目【缺陷,讨论区,新闻】,课程【通知,留言,新闻】, 贴吧, 个人留言
- def send_for_user_activities(user, date_to, days)
- date_from = date_to - days.days
-
- subject = "[ #{user.show_name} : #{l(:label_day_mail)}]"
- @subject = " #{user.show_name} : #{date_to} #{l(:label_day_mail)}"
-
- date_from = "#{date_from} 17:59:59"
- date_to = "#{date_to} 17:59:59"
-
- # 生成token用于直接点击登录
- @user = user
- token = Token.new(:user =>user , :action => 'autologin')
- token.save
- @token = token
-
- @user_url = url_for(my_account_url(user,:token => @token.value))
- # 查询user参加的项目及课程
- projects = user.projects
- courses = user.courses
- project_ids = projects.map{|project| project.id}.join(",")
- course_ids = courses.map {|course| course.id}.join(",")
-
- # 查询user的缺陷,包括发布的,跟踪的以及被指派的缺陷
- sql = "select DISTINCT i.* from issues i, watchers w
- where (i.assigned_to_id = #{user.id} or i.author_id = #{user.id}
- or (w.watchable_type = 'Issue' and w.watchable_id = i.id and w.user_id = #{user.id}))
- and (i.created_on between '#{date_from}' and '#{date_to}') order by i.created_on desc"
- @issues = Issue.find_by_sql(sql)
-
- # @bids 查询课程作业,包括老师发布的作业,以及user提交作业
- # @attachments查询课程课件更新
- @attachments ||= []
-
- @bids ||= [] # 老师发布的作业
-
- unless courses.first.nil?
- count = courses.count
- count = count - 1
- for i in 0..count do
- bids = courses[i].homeworks.where("bids.created_on between '#{date_from}' and '#{date_to}'").order("bids.created_on desc")
- attachments = courses[i].attachments.where("attachments.created_on between '#{date_from}' and '#{date_to}'").order('attachments.created_on DESC')
- @bids += bids if bids.count > 0
- @attachments += attachments if attachments.count > 0
- end
- end
- # user 提交的作业
- @homeworks = HomeworkAttach.where("user_id=#{user.id} and (created_at between '#{date_from}' and '#{date_to}')").order("created_at desc")
-
- # 查询user在课程。项目中发布的讨论帖子
- messages = Message.find_by_sql("select DISTINCT * from messages where author_id = #{user.id} and (created_on between '#{date_from}' and '#{date_to}') order by created_on desc")
- @course_messages ||= []
- @project_messages ||= []
- unless messages.first.nil?
- messages.each do |msg|
- if msg.project
- @project_messages << msg
- elsif msg.course
- @course_messages << msg
- end
- end
- end
- # 查询user在课程中发布的通知,项目中发的新闻
- @course_news = (course_ids && !course_ids.empty?) ? News.find_by_sql("select DISTINCT n.* from news n
- where n.course_id in (#{course_ids})
- and (created_on between '#{date_from}' and '#{date_to}') order by created_on desc") : []
- @project_news = (project_ids && !project_ids.empty?) ? News.find_by_sql("select DISTINCT n.* from news n where n.project_id in (#{project_ids})
- and (created_on between '#{date_from}' and '#{date_to}') order by created_on desc") : []
-
- # 查询user在课程及个人中留言
- @course_journal_messages = JournalsForMessage.find_by_sql("select DISTINCT * from journals_for_messages where
- jour_type='Course' and user_id = #{user.id}
- and (created_on between '#{date_from}' and '#{date_to}') order by created_on desc")
- @user_journal_messages = user.journals_for_messages.where("m_parent_id IS NULL and (created_on between '#{date_from}' and '#{date_to}')").order('created_on DESC')
-
-
- # 查询user新建贴吧或发布帖子
- @forums = Forum.find_by_sql("select DISTINCT * from forums where creator_id = #{user.id} and (created_at between '#{date_from}' and '#{date_to}') order by created_at desc")
- @memos = Memo.find_by_sql("select DISTINCT m.* from memos m, forums f where (m.author_id = #{user.id} or (m.forum_id = f.id and f.creator_id = #{user.id}))
- and (m.created_at between '#{date_from}' and '#{date_to}') order by m.created_at desc")
-
-
- has_content = [@issues,@homeworks,@course_messages,@project_messages,@course_news,@project_news,
- @course_journal_messages,@user_journal_messages,@forums,@memos,@attachments,@bids].any? {|o|
- !o.empty?
- }
- binding.pry if Rails.env.development?
- #有内容才发,没有不发
- mail :to => user.mail,:subject => subject if has_content
- end
-
- # 公共讨论区发帖、回帖添加邮件发送信息
- def forum_message_added(memo)
- @memo = memo
- redmine_headers 'Memo' => memo.id
- @forum = memo.forum
- @author = memo.author
- @forum_url = url_for(:controller => 'forums', :action => 'show', :id => @forum.id)
- @issue_author_url = url_for(user_activities_url(@author))
- recipients ||= []
- #将帖子创建者邮箱地址加入数组
- recipients << @forum.creator.mail
- #回复人邮箱地址加入数组
- recipients << @author.mail
- # cc = wiki_content.page.wiki.watcher_recipients - recipients
-
- @memo_url = url_for(forum_memo_url(@forum, (@memo.parent_id.nil? ? @memo : @memo.parent_id)))
- mail :to => recipients,
- :subject => "[ #{l(:label_message_plural)} : #{memo.subject} #{l(:label_memo_create_succ)}]",
- :filter => true
- end
- # Builds a Mail::Message object used to email recipients of the added journals for message.
-
- # 留言分为直接留言,和对留言人留言的回复
- # 字段说明在JournalsForMessage.rb
- # 直接留言后 reply_id,m_parent_id 为空,相对应的at_user取值为nil
-
- def journals_for_message_add(user, journals_for_message)
- @user = journals_for_message.user # 留言人
- @mail = journals_for_message.jour if journals_for_message.at_user.nil? # 留言
- @mail = journals_for_message.at_user if journals_for_message.at_user
- @message = journals_for_message.notes
- @title = "#@user #{t(:label_leave_your_message, :locale => 'zh')}"
- @issue_author_url = url_for(user_activities_url(@user))
- @url = case journals_for_message.jour.class.to_s.to_sym # 判断留言的对象所属类型
- when :Bid
- course_for_bid_url(journals_for_message.jour, anchor: "word_li_#{journals_for_message.id}")
- when :Project
- return -1 if journals_for_message.jour.project_type == Project::ProjectType_project
- project_feedback_url(journals_for_message.jour, anchor: "word_li_#{journals_for_message.id}")
- when :Course
- course_feedback_url(journals_for_message.jour, anchor: "word_li_#{journals_for_message.id}")
- when :Contest
- show_contest_contest_url(journals_for_message.jour, anchor: "word_li_#{journals_for_message.id}")
- when :User
- user_newfeedback_user_url(journals_for_message.jour, anchor: "word_li_#{journals_for_message.id}")
- else
- Rails.logger.error "[Builds a Mail::Message ERROR] journalsForMessage's jour is unkown type, journalsForMessage.id = #{journals_for_message.id}"
- return -1
- end
-
- # 验证用户的收取邮件的方式
- recipients ||= []
- recipients1 ||= []
- recipients1 = @mail.mail
- recipients = journals_for_message.jour.author.mail
-
- # modify by nwb
- #如果是直接留言并且留言对象是课程
- if !journals_for_message.at_user && journals_for_message.jour.class.to_s.to_sym == :Course
- course = journals_for_message.jour
- @author = journals_for_message.user
- #课程的教师
- @members = course_all_member journals_for_message.jour
- #收件人邮箱
- @recipients ||= []
- @members.each do |teacher|
- @recipients << teacher.user.mail
- end
- mail :to => @recipients,
- :subject => "#{l(:label_your_course)}#{journals_for_message.jour.name}#{l(:label_have_message)} ",
- :filter => true
- elsif journals_for_message.jour.class.to_s.to_sym == :Bid
- if !journals_for_message.jour.author.notify_about? journals_for_message
- return -1
- end
-
- mail :to => recipients, :subject => @title,:filter => true
- elsif journals_for_message.jour.class.to_s.to_sym == :Contest
- if !journals_for_message.jour.author.notify_about? journals_for_message
- return -1
- end
- mail :to => recipients, :subject => @title,:filter => true
- else
- mail :to => recipients1, :subject => @title,:filter => true
- end
-
-
- end
-
- # Builds a Mail::Message object used to email recipients of the added issue.
- #
- # Example:
- # issue_add(issue) => Mail::Message object
- # Mailer.issue_add(issue).deliver => sends an email to issue recipients
- def issue_add(issue, recipients)
- issue_id = issue.project_index
- redmine_headers 'Project' => issue.project.identifier,
- 'Issue-Id' => issue_id,
- 'Issue-Author' => issue.author.login
- redmine_headers 'Issue-Assignee' => issue.assigned_to.login if issue.assigned_to
- message_id issue
-
- @author = issue.author
- @issue = issue
- user = User.find_by_mail(recipients)
- token = Token.new(:user =>user , :action => 'autologin')
- token.save
- @token = token
- @issue_url = url_for(:controller => 'issues', :action => 'show', :id => issue.id, :token => @token.value)
-
- # edit
- @issue_author_url = url_for(user_activities_url(@author,:token => @token.value))
- @project_url = url_for(:controller => 'projects', :action => 'show', :id => issue.project_id, :token => @token.value)
-
- @user_url = url_for(my_account_url(user,:token => @token.value))
-
-
- subject = "[#{issue.project.name} - #{issue.tracker.name} ##{issue_id}] (#{issue.status.name}) #{issue.subject}"
- mail :to => recipients,
- :subject => subject,
- :filter => true
- end
- # issue.attachments.each do |attach|
- # attachments["#{attach.filename}"] = File.read("#{attach.disk_filename}")
- # end
- # cc = issue.watcher_recipients - recipients
- #mail.attachments['test'] = File.read("#{RAILS.root}/files/2015/01/150114094010_libegl.dll")
-
-
-
-
- # Builds a Mail::Message object used to email recipients of the edited issue.
- #
- # Example:
- # issue_edit(journal) => Mail::Message object
- # Mailer.issue_edit(journal).deliver => sends an email to issue recipients
- def issue_edit(journal,recipients)
- issue = journal.journalized.reload
- issue_id = issue.project_index
- redmine_headers 'Project' => issue.project.identifier,
- 'Issue-Id' => issue_id.to_s,
- 'Issue-Author' => issue.author.login
- redmine_headers 'Issue-Assignee' => issue.assigned_to.login if issue.assigned_to
- message_id journal
- references issue
- @author = journal.user
-
- user = User.find_by_mail(recipients)
-
- token = Token.new(:user =>user , :action => 'autologin')
- token.save
- @token = token
-
-
- # edit
- @issue_author_url = url_for(:controller => 'users', :action => 'show', :id => issue.author_id, :token => @token.value)
- @project_url = url_for(:controller => 'projects', :action => 'show', :id => issue.project_id, :token => @token.value)
- @user_url = url_for(my_account_url(user,:token => @token.value))
-
- @issue_url = url_for(:controller => 'issues', :action => 'show', :id => issue.id, :anchor => "change-#{journal.id}", :token => @token.value)
- s = "[#{issue.project.name} - #{issue.tracker.name} ##{issue_id}] "
- s << "(#{issue.status.name}) " if journal.new_value_for('status_id')
- s << issue.subject
- @issue = issue
- @journal = journal
- # @issue_url = url_for(:controller => 'issues', :action => 'show', :id => issue, :anchor => "change-#{journal.id}")
- mail :to => recipients,
- :subject => s,
- :filter => true
- end
-
- def self.deliver_mailer(to,cc, subject)
- mail :to => to,
- :cc => cc,
- :subject => subject
- end
-
- # 用户申请加入项目邮件通知
- def applied_project(applied)
- @project =applied.project
- redmine_headers 'Project' => @project,
- 'User' => applied.user
- @user = applied.user
- recipients = @project.manager_recipients
- s = l(:text_applied_project, :id => "##{@user.show_name}", :project => @project.name)
- @applied_url = url_for(:controller => 'projects', :action => 'settings', :id => @project.id,:tab=>'members')
- mail :to => recipients,
- :subject => s
- end
-
- def reminder(user, issues, days)
- set_language_if_valid user.language
- @issues = issues
- @days = days
- @issues_url = url_for(:controller => 'issues', :action => 'index',
- :set_filter => 1, :assigned_to_id => user.id,
- :sort => 'due_date:asc')
- mail :to => user.mail,
- :subject => l(:mail_subject_reminder, :count => issues.size, :days => days)
- end
-
- #缺陷到期邮件通知
- def issue_expire issue
- issue_id = issue.project_index
- redmine_headers 'Project' => issue.project.identifier,
- 'Issue-Id' => issue_id,
- 'Issue-Author' => issue.author.login
- redmine_headers 'Issue-Assignee' => issue.assigned_to.login if issue.assigned_to
- message_id issue
- @author = issue.author
- @issue = issue
- @issue_url = url_for(:controller => 'issues', :action => 'show', :id => issue.id)
- recipients = issue.recipients
- s = l(:text_issue_expire,:issue => "[#{issue.project.name} - #{issue.tracker.name} ##{issue_id}] (#{issue.status.name}) #{issue.subject}")
- mail :to => recipients,
- :subject => s
- #########################################################################################################
- #@issues = issues
- #s = l(:text_issue_expire,:issue => "[#{issue.project.name} - #{issue.tracker.name} ##{issue_id}] (#{issue.status.name}) #{issue.subject}")
- #puts s + "////" + issue.assigned_to.mail
- #@issues_url = url_for(:controller => 'issues', :action => 'show',:id => issue.id)
- #mail :to => issue.assigned_to.mail,
- # :subject => s
- #########################################################################################################
- #issue_id = issue.project_index
- #redmine_headers 'Project' => issue.project.identifier,
- # 'Issue-Id' => issue_id,
- # 'Issue-Author' => issue.author.login
- #redmine_headers 'Issue-Assignee' => issue.assigned_to.login if issue.assigned_to
- #message_id issue
- #@author = issue.author
- #@issue = issue
- #@issue_url = url_for(:controller => 'issues', :action => 'show', :id => issue)
- #recipients = issue.recipients
- #cc = issue.watcher_recipients - recipients
- #mail :to => recipients,
- # :cc => cc,
- # :subject => "[#{issue.project.name} - #{issue.tracker.name} ##{issue_id}] (#{issue.status.name}) #{issue.subject}"
- ######################################################################################################
- end
-
-
- # Builds a Mail::Message object used to email users belonging to the added document's project.
- #
- # Example:
- # document_added(document) => Mail::Message object
- # Mailer.document_added(document).deliver => sends an email to the document's project recipients
- def document_added(document)
- redmine_headers 'Project' => document.project.identifier
- @author = User.current
- @document = document
- @issue_author_url = url_for(user_activities_url(@author))
- @document_url = url_for(:controller => 'documents', :action => 'show', :id => document)
- mail :to => document.recipients,
- :subject => "[#{document.project.name}] #{l(:label_document_new)}: #{document.title}",
- :filter => true
- end
-
- # Builds a Mail::Message object used to email recipients of a project when an attachements are added.
- #
- # Example:
- # attachments_added(attachments) => Mail::Message object
- # Mailer.attachments_added(attachments).deliver => sends an email to the project's recipients
- def attachments_added(attachments)
- container = attachments.first.container
- added_to = ''
- added_to_url = ''
- @author = attachments.first.author
- @issue_author_url = url_for(user_activities_url(@author))
- case container.class.name
- when 'Project'
- added_to_url = url_for(:controller => 'files', :action => 'index', :project_id => container)
- added_to = "#{l(:label_project)}: #{container}"
- recipients = container.notified_users.select { |user| user.allowed_to?(:view_files, container) }.collect { |u| u.mail }
- when 'Course'
- added_to_url = url_for(:controller => 'files', :action => 'index', :course_id => container)
- added_to = "#{l(:label_course)}: #{container.name}"
- recipients = container.notified_users.select { |user| user.allowed_to?(:view_files, container) }.collect { |u| u.mail }
- when 'Version'
- added_to_url = url_for(:controller => 'files', :action => 'index', :project_id => container.project)
- added_to = "#{l(:label_version)}: #{container.name}"
- recipients = container.project.notified_users.select { |user| user.allowed_to?(:view_files, container.project) }.collect { |u| u.mail }
- when 'Document'
- added_to_url = url_for(:controller => 'documents', :action => 'show', :id => container.id)
- added_to = "#{l(:label_document)}: #{container.title}"
- recipients = container.recipients
- end
- if container.class.name == 'Course'
- redmine_headers 'Course' => container.id
- @attachments = attachments
- @added_to = added_to
- @added_to_url = added_to_url
- mail :to => recipients,
- :subject => "[#{container.name}] #{l(:label_attachment_new)}",
- :filter => true
- elsif container.class.name == 'Project'
- redmine_headers 'Project' => container.id
- @attachments = attachments
- @added_to = added_to
- @added_to_url = added_to_url
- mail :to => recipients,
- :subject => "[#{container.name}] #{l(:label_attachment_new)}",
- :filter => true
- else
- redmine_headers 'Project' => container.project.identifier
- @attachments = attachments
- @added_to = added_to
- @added_to_url = added_to_url
- mail :to => recipients,
- :subject => "[#{container.project.name}] #{l(:label_attachment_new)}",
- :filter => true
- end
- end
-
- # Builds a Mail::Message object used to email recipients of a news' project when a news item is added.
- #
- # Example:
- # news_added(news) => Mail::Message object
- # Mailer.news_added(news).deliver => sends an email to the news' project recipients
- def news_added(news)
-
- if news.project
- redmine_headers 'Project' => news.project.identifier
- @author = news.author
- @issue_author_url = url_for(user_activities_url(@author))
- message_id news
- @news = news
- @news_url = url_for(:controller => 'news', :action => 'show', :id => news)
- mail :to => news.recipients,
- :subject => "[#{news.project.name}] #{l(:label_news)}: #{news.title}",
- :filter => true
- elsif news.course
- redmine_headers 'Course' => news.course.id
- @author = news.author
- @issue_author_url = url_for(user_activities_url(@author))
- message_id news
- @news = news
- recipients = news.course.notified_users.select { |user| user.allowed_to?(:view_files, news.course) }.collect { |u| u.mail }
- @news_url = url_for(:controller => 'news', :action => 'show', :id => news)
- mail :to => recipients,
- :subject => "[#{news.course.name}] #{l(:label_news)}: #{news.title}",
- :filter => true
- end
- end
-
- # Builds a Mail::Message object used to email recipients of a news' project when a news comment is added.
- #
- # Example:
- # news_comment_added(comment) => Mail::Message object
- # Mailer.news_comment_added(comment) => sends an email to the news' project recipients
- def news_comment_added(comment)
- news = comment.commented
- if news.project
- redmine_headers 'Project' => news.project.identifier
- @author = comment.author
- @issue_author_url = url_for(user_activities_url(@author))
- message_id comment
- @news = news
- @comment = comment
- @news_url = url_for(:controller => 'news', :action => 'show', :id => news)
- mail :to => news.recipients,
- :cc => news.watcher_recipients,
- :subject => "Re: [#{news.project.name}] #{l(:label_news)}: #{news.title}",
- :filter => true
- elsif news.course
- redmine_headers 'Course' => news.course.id
- @author = comment.author
- @issue_author_url = url_for(user_activities_url(@author))
- message_id comment
- @news = news
- @comment = comment
- @news_url = url_for(:controller => 'news', :action => 'show', :id => news)
- recipients = news.course.notified_users.select { |user| user.allowed_to?(:view_files, news.course) }.collect { |u| u.mail }
-
- mail :to => recipients,
- :subject => "[#{news.course.name}] #{l(:label_news)}: #{news.title}",
- :filter => true
- end
- end
-
- # Builds a Mail::Message object used to email the recipients of the specified message that was posted.
- #
- # Example:
- # message_posted(message) => Mail::Message object
- # Mailer.message_posted(message).deliver => sends an email to the recipients
- def message_posted(message)
- if message.project
- redmine_headers 'Project' => message.project.identifier,
- 'Topic-Id' => (message.parent_id || message.id)
- @author = message.author
- @issue_author_url = url_for(user_activities_url(@author))
- message_id message
- references message.parent unless message.parent.nil?
- recipients = message.recipients
- cc = ((message.root.watcher_recipients + message.board.watcher_recipients).uniq - recipients)
- @message = message
- @message_url = url_for(message.event_url)
- mail :to => recipients,
- :cc => cc,
- :subject => "[#{message.board.project.name} - #{message.board.name} - msg#{message.root.id}] #{message.subject}",
- :filter => true
- elsif message.course
- redmine_headers 'Course' => message.course.id,
- 'Topic-Id' => (message.parent_id || message.id)
- @author = message.author
- @issue_author_url = url_for(user_activities_url(@author))
- message_id message
- references message.parent unless message.parent.nil?
- recipients = message.course.notified_users.select { |user| user.allowed_to?(:view_files, message.course) }.collect { |u| u.mail }
- cc = ((message.root.watcher_recipients + message.board.watcher_recipients).uniq - recipients)
- @message = message
- @message_url = url_for(message.event_url)
- mail :to => recipients,
- :cc => cc,
- :subject => "[#{message.board.course.name} - #{message.board.name} - msg#{message.root.id}] #{message.subject}",
- :filter => true
- end
- end
-
- # Builds a Mail::Message object used to email the recipients of a project of the specified wiki content was added.
- #
- # Example:
- # wiki_content_added(wiki_content) => Mail::Message object
- # Mailer.wiki_content_added(wiki_content).deliver => sends an email to the project's recipients
- def wiki_content_added(wiki_content)
- redmine_headers 'Project' => wiki_content.project.identifier,
- 'Wiki-Page-Id' => wiki_content.page.id
- @author = wiki_content.author
- message_id wiki_content
- recipients = wiki_content.recipients
- cc = wiki_content.page.wiki.watcher_recipients - recipients
- @wiki_content = wiki_content
- @wiki_content_url = url_for(:controller => 'wiki', :action => 'show',
- :project_id => wiki_content.project,
- :id => wiki_content.page.title)
- mail :to => recipients,
- :cc => cc,
- :subject => "[#{wiki_content.project.name}] #{l(:mail_subject_wiki_content_added, :id => wiki_content.page.pretty_title)}",
- :filter => true
- end
-
- # Builds a Mail::Message object used to email the recipients of a project of the specified wiki content was updated.
- #
- # Example:
- # wiki_content_updated(wiki_content) => Mail::Message object
- # Mailer.wiki_content_updated(wiki_content).deliver => sends an email to the project's recipients
- def wiki_content_updated(wiki_content)
- redmine_headers 'Project' => wiki_content.project.identifier,
- 'Wiki-Page-Id' => wiki_content.page.id
- @author = wiki_content.author
- message_id wiki_content
- recipients = wiki_content.recipients
- cc = wiki_content.page.wiki.watcher_recipients + wiki_content.page.watcher_recipients - recipients
- @wiki_content = wiki_content
- @wiki_content_url = url_for(:controller => 'wiki', :action => 'show',
- :project_id => wiki_content.project,
- :id => wiki_content.page.title)
- @wiki_diff_url = url_for(:controller => 'wiki', :action => 'diff',
- :project_id => wiki_content.project, :id => wiki_content.page.title,
- :version => wiki_content.version)
- mail :to => recipients,
- :cc => cc,
- :subject => "[#{wiki_content.project.name}] #{l(:mail_subject_wiki_content_updated, :id => wiki_content.page.pretty_title)}",
- :filter => true
- end
-
- # Builds a Mail::Message object used to email the specified user their account information.
- #
- # Example:
- # account_information(user, password) => Mail::Message object
- # Mailer.account_information(user, password).deliver => sends account information to the user
- def account_information(user, password)
- set_language_if_valid user.language
- @user = user
- @password = password
- @login_url = url_for(:controller => 'account', :action => 'login')
- mail :to => user.mail,
- :subject => l(:mail_subject_register, Setting.app_title)
- end
-
- # Builds a Mail::Message object used to email all active administrators of an account activation request.
- #
- # Example:
- # account_activation_request(user) => Mail::Message object
- # Mailer.account_activation_request(user).deliver => sends an email to all active administrators
- def account_activation_request(user)
- # Send the email to all active administrators
- recipients = User.active.where(:admin => true).all.collect { |u| u.mail }.compact
- @user = user
- @url = url_for(:controller => 'users', :action => 'index',
- :status => User::STATUS_REGISTERED,
- :sort_key => 'created_on', :sort_order => 'desc')
- mail :to => recipients,
- :subject => l(:mail_subject_account_activation_request, Setting.app_title)
- end
-
- # Builds a Mail::Message object used to email the specified user that their account was activated by an administrator.
- #
- # Example:
- # account_activated(user) => Mail::Message object
- # Mailer.account_activated(user).deliver => sends an email to the registered user
- def account_activated(user)
- set_language_if_valid user.language
- @user = user
- @login_url = url_for(:controller => 'account', :action => 'login')
- mail :to => user.mail,
- :subject => l(:mail_subject_register, Setting.app_title)
- end
-
- def lost_password(token)
- set_language_if_valid(token.user.language)
- @token = token
- @url = url_for(:controller => 'account', :action => 'lost_password', :token => token.value)
- mail :to => token.user.mail,
- :subject => l(:mail_subject_lost_password, Setting.app_title)
- end
-
- def register(token)
- set_language_if_valid(token.user.language)
- @token = token
- @url = url_for(:controller => 'account', :action => 'activate', :token => token.value)
- mail :to => token.user.mail,
- :subject => l(:mail_subject_register, Setting.app_title)
- end
-
- def test_email(user)
- set_language_if_valid(user.language)
- @url = url_for(:controller => 'welcome')
- mail :to => user.mail,
- :subject => 'forge test'
- end
-
- # Overrides default deliver! method to prevent from sending an email
- # with no recipient, cc or bcc
- def deliver!(mail = @mail)
- set_language_if_valid @initial_language
- return false if (recipients.nil? || recipients.empty?) &&
- (cc.nil? || cc.empty?) &&
- (bcc.nil? || bcc.empty?)
-
-
- # Log errors when raise_delivery_errors is set to false, Rails does not
- raise_errors = self.class.raise_delivery_errors
- self.class.raise_delivery_errors = true
- begin
- return super(mail)
- rescue Exception => e
- if raise_errors
- raise e
- elsif mylogger
- mylogger.error "The following error occured while sending email notification: \"#{e.message}\". Check your configuration in config/configuration.yml."
- end
- ensure
- self.class.raise_delivery_errors = raise_errors
- end
- end
-
- # Sends reminders to issue assignees
- # Available options:
- # * :days => how many days in the future to remind about (defaults to 7)
- # * :tracker => id of tracker for filtering issues (defaults to all trackers)
- # * :project => id or identifier of project to process (defaults to all projects)
- # * :users => array of user/group ids who should be reminded
- def self.reminders(options={})
- days = options[:days] || 7
- project = options[:project] ? Project.find(options[:project]) : nil
- tracker = options[:tracker] ? Tracker.find(options[:tracker]) : nil
- user_ids = options[:users]
-
- scope = Issue.open.where("#{Issue.table_name}.assigned_to_id IS NOT NULL" +
- " AND #{Project.table_name}.status = #{Project::STATUS_ACTIVE}" +
- " AND #{Issue.table_name}.due_date <= ?", days.day.from_now.to_date
- )
- scope = scope.where(:assigned_to_id => user_ids) if user_ids.present?
- scope = scope.where(:project_id => project.id) if project
- scope = scope.where(:tracker_id => tracker.id) if tracker
-
- issues_by_assignee = scope.includes(:status, :assigned_to, :project, :tracker).all.group_by(&:assigned_to)
- issues_by_assignee.keys.each do |assignee|
- if assignee.is_a?(Group)
- assignee.users.each do |user|
- issues_by_assignee[user] ||= []
- issues_by_assignee[user] += issues_by_assignee[assignee]
- end
- end
- end
-
- issues_by_assignee.each do |assignee, issues|
- reminder(assignee, issues, days).deliver if assignee.is_a?(User) && assignee.active?
- end
- end
-
- # Activates/desactivates email deliveries during +block+
- def self.with_deliveries(enabled = true, &block)
- was_enabled = ActionMailer::Base.perform_deliveries
- ActionMailer::Base.perform_deliveries = !!enabled
- yield
- ensure
- ActionMailer::Base.perform_deliveries = was_enabled
- end
-
- # Sends emails synchronously in the given block
- def self.with_synched_deliveries(&block)
- saved_method = ActionMailer::Base.delivery_method
- if m = saved_method.to_s.match(%r{^async_(.+)$})
- synched_method = m[1]
- ActionMailer::Base.delivery_method = synched_method.to_sym
- ActionMailer::Base.send "#{synched_method}_settings=", ActionMailer::Base.send("async_#{synched_method}_settings")
- end
- yield
- ensure
- ActionMailer::Base.delivery_method = saved_method
- end
-
- #过滤掉不是不合规则的收件人
- def filter(reps)
- r_reps = []
- if reps.is_a? Array
- reps.each do |r|
- u = User.find_by_mail(r)
- if u && u.mail_notification == 'all'
- r_reps << r
- end
- end
- elsif reps.is_a? String
- u = User.find_by_mail(reps)
- if u && u.mail_notification == 'all'
- r_reps << reps
- end
- end
- r_reps
- end
-
- def mail(headers={})
- headers.merge! 'X-Mailer' => 'Redmine',
- 'X-Redmine-Host' => Setting.host_name,
- 'X-Redmine-Site' => Setting.app_title,
- 'X-Auto-Response-Suppress' => 'OOF',
- 'Auto-Submitted' => 'auto-generated',
- 'From' => Setting.mail_from,
- 'List-Id' => "<#{Setting.mail_from.to_s.gsub('@', '.')}>"
-
- # Removes the author from the recipients and cc
- # if he doesn't want to receive notifications about what he does
- if @author && @author.logged? && @author.pref[:no_self_notified]
- headers[:to].delete(@author.mail) if headers[:to].is_a?(Array)
- headers[:cc].delete(@author.mail) if headers[:cc].is_a?(Array)
- end
-
- if headers[:filter]
- headers[:to] = filter(headers[:to])
- headers[:cc] = filter(headers[:cc])
- end
-
- if @author && @author.logged?
- redmine_headers 'Sender' => @author.login
- end
-
- # Blind carbon copy recipients
- if Setting.bcc_recipients?
- headers[:bcc] = [headers[:to], headers[:cc]].flatten.uniq.reject(&:blank?)
- headers[:to] = nil
- headers[:cc] = nil
- end
-
- if @message_id_object
- headers[:message_id] = "<#{self.class.message_id_for(@message_id_object)}>"
- end
- if @references_objects
- headers[:references] = @references_objects.collect {|o| "<#{self.class.message_id_for(o)}>"}.join(' ')
- end
-
- super headers do |format|
- format.text
- format.html unless Setting.plain_text_mail?
- end
-
- set_language_if_valid @initial_language
- end
-
- def initialize(*args)
- @initial_language = current_language
- set_language_if_valid Setting.default_language
- super
- end
-
- def self.deliver_mail(mail)
- return false if mail.to.blank? && mail.cc.blank? && mail.bcc.blank?
- Thread.new do
- super
- end
- end
-
- def self.method_missing(method, *args, &block)
- if m = method.to_s.match(%r{^deliver_(.+)$})
- ActiveSupport::Deprecation.warn "Mailer.deliver_#{m[1]}(*args) is deprecated. Use Mailer.#{m[1]}(*args).deliver instead."
- send(m[1], *args).deliver
- else
- super
- end
- end
-
-
-
- private
-
- # Appends a Redmine header field (name is prepended with 'X-Redmine-')
- def redmine_headers(h)
- h.each { |k,v| headers["X-Redmine-#{k}"] = v.to_s }
- end
-
- # Returns a predictable Message-Id for the given object
- def self.message_id_for(object)
- # id + timestamp should reduce the odds of a collision
- # as far as we don't send multiple emails for the same object
- timestamp = object.send(object.respond_to?(:created_on) ? :created_on : :updated_on)
- hash = "redmine.#{object.class.name.demodulize.underscore}-#{object.id}.#{timestamp.strftime("%Y%m%d%H%M%S")}"
- host = Setting.mail_from.to_s.gsub(%r{^.*@}, '')
- host = "#{::Socket.gethostname}.redmine" if host.empty?
- "#{hash}@#{host}"
- end
-
- def message_id(object)
- @message_id_object = object
- end
-
- def references(object)
- @references_objects ||= []
- @references_objects << object
- end
-
- def mylogger
- Rails.logger
- end
-
- def add_attachments(obj)
- if email.attachments && email.attachments.any?
- email.attachments.each do |attachment|
- obj.attachments << Attachment.create(:container => obj,
- :file => attachment.decoded,
- :filename => attachment.filename,
- :author => user,
- :content_type => attachment.mime_type)
- end
- end
- end
-
- # author: alan
- # 功能: 生成len位随机字符串
- def newpass(len)
- chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a
- newpass = ""
- 1.upto(len) { |i| newpass << chars[rand(chars.size-1)] }
- return newpass
- 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 Mailer < ActionMailer::Base
+ layout 'mailer'
+ helper :application
+ helper :issues
+ helper :custom_fields
+
+ include Redmine::I18n
+ include CoursesHelper
+ def self.default_url_options
+ { :host => Setting.host_name, :protocol => Setting.protocol }
+ end
+
+
+ class MailerProxy
+ def initialize(cls)
+ @target = cls
+ end
+ def method_missing(name, *args, &block)
+ if Setting.delayjob_enabled? && Object.const_defined?('Delayed')
+ @target.delay.send(name, *args, &block)
+ else
+ @target.send(name, *args, &block).deliver
+ end
+ end
+ end
+
+ def self.run
+ MailerProxy.new(self)
+ end
+
+ # author: alan
+ # 发送邀请未注册用户加入项目邮件
+ # 功能: 在加入项目的同时自动注册用户
+ def send_invite_in_project(email, project, invitor)
+ @email = email
+ @subject = "#{invitor.name} #{l(:label_invite_project)} #{project.name} "
+ @password = newpass(6)
+
+ login = email
+ login = login.sub(/%40/,'@')
+ us = UsersService.new
+ # 自动激活用户
+ user = us.register_auto(login, @email, @password)
+
+ Member.create(:role_ids => [4], :user_id => user.id,:project_id => project.id)
+ UserGrade.create(:user_id => user.id, :project_id => project.id)
+ User.current = user unless User.current.nil?
+ @user = user
+ @token = Token.get_token_from_user(user, 'autologin')
+ @project_url = url_for(:controller => 'projects', :action => 'show', :id => project.id,:user => user, :token => @token.value
+ )
+ mail :to => email, :subject => @subject
+ end
+
+ # 邀请已注册的用户加入项目
+ def request_member_to_project(email, project, invitor)
+ @subject = "#{invitor.name} #{l(:label_invite_project)}: #{project.name} "
+ user = User.find_by_mail(email.to_s)
+ @invitor_name = "#{invitor.name}"
+ @project_name = "#{project.name}"
+ @user = user
+ @token = Token.get_token_from_user(user, 'autologin')
+ @project_url = url_for(:controller => 'projects', :action => 'show', :id => project.id, :email => email, :token => @token.value)
+ mail :to => email, :subject => @subject
+ end
+
+ # author: alan
+ # 根据用户选择发送个人日报或周报
+ # 发送内容: 项目【缺陷,讨论区,新闻】,课程【通知,留言,新闻】, 贴吧, 个人留言
+ def send_for_user_activities(user, date_to, days)
+ date_from = date_to - days.days
+
+ subject = "[ #{user.show_name}#{l(:label_day_mail)}]"
+ @subject = " #{user.show_name}#{l(:label_day_mail)}"
+
+ date_from = "#{date_from} 17:59:59"
+ date_to = "#{date_to} 17:59:59"
+
+ # 生成token用于直接点击登录
+ @user = user
+ @token = Token.get_token_from_user(user, 'autologin')
+
+ # 查询user参加的项目及课程
+ projects = user.projects
+ courses = user.courses
+ project_ids = projects.map{|project| project.id}.join(",")
+ course_ids = courses.map {|course| course.id}.join(",")
+
+ # 查询user的缺陷,包括发布的,跟踪的以及被指派的缺陷
+ sql = "select DISTINCT i.* from issues i, watchers w
+ where (i.assigned_to_id = #{user.id} or i.author_id = #{user.id}
+ or (w.watchable_type = 'Issue' and w.watchable_id = i.id and w.user_id = #{user.id}))
+ and (i.created_on between '#{date_from}' and '#{date_to}') order by i.created_on desc"
+ @issues = Issue.find_by_sql(sql)
+
+ # @bids 查询课程作业,包括老师发布的作业,以及user提交作业
+ # @attachments查询课程课件更新
+ @attachments ||= []
+
+ @bids ||= [] # 老师发布的作业
+
+ unless courses.first.nil?
+ count = courses.count
+ count = count - 1
+ for i in 0..count do
+ bids = courses[i].homeworks.where("bids.created_on between '#{date_from}' and '#{date_to}'").order("bids.created_on desc")
+ attachments = courses[i].attachments.where("attachments.created_on between '#{date_from}' and '#{date_to}'").order('attachments.created_on DESC')
+ @bids += bids if bids.count > 0
+ @attachments += attachments if attachments.count > 0
+ end
+ end
+ # user 提交的作业
+ @homeworks = HomeworkAttach.where("user_id=#{user.id} and (created_at between '#{date_from}' and '#{date_to}')").order("created_at desc")
+
+ # 查询user在课程。项目中发布的讨论帖子
+ messages = Message.find_by_sql("select DISTINCT * from messages where author_id = #{user.id} and (created_on between '#{date_from}' and '#{date_to}') order by created_on desc")
+ @course_messages ||= []
+ @project_messages ||= []
+ unless messages.first.nil?
+ messages.each do |msg|
+ if msg.project
+ @project_messages << msg
+ elsif msg.course
+ @course_messages << msg
+ end
+ end
+ end
+ # 查询user在课程中发布的通知,项目中发的新闻
+ @course_news = (course_ids && !course_ids.empty?) ? News.find_by_sql("select DISTINCT n.* from news n
+ where n.course_id in (#{course_ids})
+ and (created_on between '#{date_from}' and '#{date_to}') order by created_on desc") : []
+ @project_news = (project_ids && !project_ids.empty?) ? News.find_by_sql("select DISTINCT n.* from news n where n.project_id in (#{project_ids})
+ and (created_on between '#{date_from}' and '#{date_to}') order by created_on desc") : []
+
+ # 查询user在课程及个人中留言
+ @course_journal_messages = JournalsForMessage.find_by_sql("select DISTINCT * from journals_for_messages where
+ jour_type='Course' and user_id = #{user.id}
+ and (created_on between '#{date_from}' and '#{date_to}') order by created_on desc")
+ @user_journal_messages = user.journals_for_messages.where("m_parent_id IS NULL and (created_on between '#{date_from}' and '#{date_to}')").order('created_on DESC')
+
+
+ # 查询user新建贴吧或发布帖子
+ @forums = Forum.find_by_sql("select DISTINCT * from forums where creator_id = #{user.id} and (created_at between '#{date_from}' and '#{date_to}') order by created_at desc")
+ @memos = Memo.find_by_sql("select DISTINCT m.* from memos m, forums f where (m.author_id = #{user.id} or (m.forum_id = f.id and f.creator_id = #{user.id}))
+ and (m.created_at between '#{date_from}' and '#{date_to}') order by m.created_at desc")
+
+
+ has_content = [@issues,@homeworks,@course_messages,@project_messages,@course_news,@project_news,
+ @course_journal_messages,@user_journal_messages,@forums,@memos,@attachments,@bids].any? {|o|
+ !o.empty?
+ }
+ mylogger.debug "Sent activity mail : #{user.mail} - #{has_content}"
+ #有内容才发,没有不发
+ mail :to => user.mail,:subject => subject if has_content
+ end
+
+ # 公共讨论区发帖、回帖添加邮件发送信息
+ def forum_message_added(memo)
+ @memo = memo
+ redmine_headers 'Memo' => memo.id
+ @forum = memo.forum
+ @author = memo.author
+ @forum_url = url_for(:controller => 'forums', :action => 'show', :id => @forum.id)
+ @issue_author_url = url_for(user_activities_url(@author))
+ recipients ||= []
+ #将帖子创建者邮箱地址加入数组
+ recipients << @forum.creator.mail
+ #回复人邮箱地址加入数组
+ recipients << @author.mail
+ # cc = wiki_content.page.wiki.watcher_recipients - recipients
+
+ @memo_url = url_for(forum_memo_url(@forum, (@memo.parent_id.nil? ? @memo : @memo.parent_id)))
+ mail :to => recipients,
+ :subject => "[ #{l(:label_message_plural)} : #{memo.subject} #{l(:label_memo_create_succ)}]",
+ :filter => true
+ end
+ # Builds a Mail::Message object used to email recipients of the added journals for message.
+
+ # 留言分为直接留言,和对留言人留言的回复
+ # 字段说明在JournalsForMessage.rb
+ # 直接留言后 reply_id,m_parent_id 为空,相对应的at_user取值为nil
+
+ def journals_for_message_add(user, journals_for_message)
+ @user = journals_for_message.user # 留言人
+ @mail = journals_for_message.jour if journals_for_message.at_user.nil? # 留言
+ @mail = journals_for_message.at_user if journals_for_message.at_user
+ @message = journals_for_message.notes
+ @title = "#@user #{t(:label_leave_your_message, :locale => 'zh')}"
+ @issue_author_url = url_for(user_activities_url(@user))
+ @url = case journals_for_message.jour.class.to_s.to_sym # 判断留言的对象所属类型
+ when :Bid
+ course_for_bid_url(journals_for_message.jour, anchor: "word_li_#{journals_for_message.id}")
+ when :Project
+ return -1 if journals_for_message.jour.project_type == Project::ProjectType_project
+ project_feedback_url(journals_for_message.jour, anchor: "word_li_#{journals_for_message.id}")
+ when :Course
+ course_feedback_url(journals_for_message.jour, anchor: "word_li_#{journals_for_message.id}")
+ when :Contest
+ show_contest_contest_url(journals_for_message.jour, anchor: "word_li_#{journals_for_message.id}")
+ when :User
+ user_newfeedback_user_url(journals_for_message.jour, anchor: "word_li_#{journals_for_message.id}")
+ else
+ Rails.logger.error "[Builds a Mail::Message ERROR] journalsForMessage's jour is unkown type, journalsForMessage.id = #{journals_for_message.id}"
+ return -1
+ end
+
+ # 验证用户的收取邮件的方式
+ recipients ||= []
+ recipients1 ||= []
+ recipients1 = @mail.mail
+ recipients = journals_for_message.jour.author.mail
+
+ # modify by nwb
+ #如果是直接留言并且留言对象是课程
+ if !journals_for_message.at_user && journals_for_message.jour.class.to_s.to_sym == :Course
+ course = journals_for_message.jour
+ @author = journals_for_message.user
+ #课程的教师
+ @members = course_all_member journals_for_message.jour
+ #收件人邮箱
+ @recipients ||= []
+ @members.each do |teacher|
+ @recipients << teacher.user.mail
+ end
+ mail :to => @recipients,
+ :subject => "#{l(:label_your_course)}#{journals_for_message.jour.name}#{l(:label_have_message)} ",
+ :filter => true
+ elsif journals_for_message.jour.class.to_s.to_sym == :Bid
+ if !journals_for_message.jour.author.notify_about? journals_for_message
+ return -1
+ end
+
+ mail :to => recipients, :subject => @title,:filter => true
+ elsif journals_for_message.jour.class.to_s.to_sym == :Contest
+ if !journals_for_message.jour.author.notify_about? journals_for_message
+ return -1
+ end
+ mail :to => recipients, :subject => @title,:filter => true
+ else
+ mail :to => recipients1, :subject => @title,:filter => true
+ end
+
+
+ end
+
+ # Builds a Mail::Message object used to email recipients of the added issue.
+ #
+ # Example:
+ # issue_add(issue) => Mail::Message object
+ # Mailer.issue_add(issue).deliver => sends an email to issue recipients
+ def issue_add(issue, recipients)
+ issue_id = issue.project_index
+ redmine_headers 'Project' => issue.project.identifier,
+ 'Issue-Id' => issue_id,
+ 'Issue-Author' => issue.author.login
+ redmine_headers 'Issue-Assignee' => issue.assigned_to.login if issue.assigned_to
+ message_id issue
+
+ @author = issue.author
+ @issue = issue
+ user = User.find_by_mail(recipients)
+ @user = user
+ @token = Token.get_token_from_user(user, 'autologin')
+ @issue_url = url_for(:controller => 'issues', :action => 'show', :id => issue.id, :token => @token.value)
+
+ # edit
+ @issue_author_url = url_for(user_activities_url(@author,:token => @token.value))
+ @project_url = url_for(:controller => 'projects', :action => 'show', :id => issue.project_id, :token => @token.value)
+
+ @user_url = url_for(my_account_url(user,:token => @token.value))
+
+
+ subject = "[#{issue.project.name} - #{issue.tracker.name} ##{issue_id}] (#{issue.status.name}) #{issue.subject}"
+ mail :to => recipients,
+ :subject => subject,
+ :filter => true
+ end
+ # issue.attachments.each do |attach|
+ # attachments["#{attach.filename}"] = File.read("#{attach.disk_filename}")
+ # end
+ # cc = issue.watcher_recipients - recipients
+ #mail.attachments['test'] = File.read("#{RAILS.root}/files/2015/01/150114094010_libegl.dll")
+
+
+
+
+ # Builds a Mail::Message object used to email recipients of the edited issue.
+ #
+ # Example:
+ # issue_edit(journal) => Mail::Message object
+ # Mailer.issue_edit(journal).deliver => sends an email to issue recipients
+ def issue_edit(journal,recipients)
+ issue = journal.journalized.reload
+ issue_id = issue.project_index
+ redmine_headers 'Project' => issue.project.identifier,
+ 'Issue-Id' => issue_id.to_s,
+ 'Issue-Author' => issue.author.login
+ redmine_headers 'Issue-Assignee' => issue.assigned_to.login if issue.assigned_to
+ message_id journal
+ references issue
+ @author = journal.user
+
+ user = User.find_by_mail(recipients)
+ @user = user
+ @token = Token.get_token_from_user(user, 'autologin')
+
+
+ # edit
+ @issue_author_url = url_for(:controller => 'users', :action => 'show', :id => issue.author_id, :token => @token.value)
+ @project_url = url_for(:controller => 'projects', :action => 'show', :id => issue.project_id, :token => @token.value)
+ @user_url = url_for(my_account_url(user,:token => @token.value))
+
+ @issue_url = url_for(:controller => 'issues', :action => 'show', :id => issue.id, :anchor => "change-#{journal.id}", :token => @token.value)
+ s = "[#{issue.project.name} - #{issue.tracker.name} ##{issue_id}] "
+ s << "(#{issue.status.name}) " if journal.new_value_for('status_id')
+ s << issue.subject
+ @issue = issue
+ @journal = journal
+ # @issue_url = url_for(:controller => 'issues', :action => 'show', :id => issue, :anchor => "change-#{journal.id}")
+ mail :to => recipients,
+ :subject => s,
+ :filter => true
+ end
+
+ def self.deliver_mailer(to,cc, subject)
+ mail :to => to,
+ :cc => cc,
+ :subject => subject
+ end
+
+ # 用户申请加入项目邮件通知
+ def applied_project(applied)
+ @project =applied.project
+ redmine_headers 'Project' => @project,
+ 'User' => applied.user
+ @user = applied.user
+ recipients = @project.manager_recipients
+ s = l(:text_applied_project, :id => "##{@user.show_name}", :project => @project.name)
+ @applied_url = url_for(:controller => 'projects', :action => 'settings', :id => @project.id,:tab=>'members')
+ mail :to => recipients,
+ :subject => s
+ end
+
+ def reminder(user, issues, days)
+ set_language_if_valid user.language
+ @issues = issues
+ @days = days
+ @issues_url = url_for(:controller => 'issues', :action => 'index',
+ :set_filter => 1, :assigned_to_id => user.id,
+ :sort => 'due_date:asc')
+ mail :to => user.mail,
+ :subject => l(:mail_subject_reminder, :count => issues.size, :days => days)
+ end
+
+ #缺陷到期邮件通知
+ def issue_expire issue
+ issue_id = issue.project_index
+ redmine_headers 'Project' => issue.project.identifier,
+ 'Issue-Id' => issue_id,
+ 'Issue-Author' => issue.author.login
+ redmine_headers 'Issue-Assignee' => issue.assigned_to.login if issue.assigned_to
+ message_id issue
+ @author = issue.author
+ @issue = issue
+ @issue_url = url_for(:controller => 'issues', :action => 'show', :id => issue.id)
+ recipients = issue.recipients
+ s = l(:text_issue_expire,:issue => "[#{issue.project.name} - #{issue.tracker.name} ##{issue_id}] (#{issue.status.name}) #{issue.subject}")
+ mail :to => recipients,
+ :subject => s
+ #########################################################################################################
+ #@issues = issues
+ #s = l(:text_issue_expire,:issue => "[#{issue.project.name} - #{issue.tracker.name} ##{issue_id}] (#{issue.status.name}) #{issue.subject}")
+ #puts s + "////" + issue.assigned_to.mail
+ #@issues_url = url_for(:controller => 'issues', :action => 'show',:id => issue.id)
+ #mail :to => issue.assigned_to.mail,
+ # :subject => s
+ #########################################################################################################
+ #issue_id = issue.project_index
+ #redmine_headers 'Project' => issue.project.identifier,
+ # 'Issue-Id' => issue_id,
+ # 'Issue-Author' => issue.author.login
+ #redmine_headers 'Issue-Assignee' => issue.assigned_to.login if issue.assigned_to
+ #message_id issue
+ #@author = issue.author
+ #@issue = issue
+ #@issue_url = url_for(:controller => 'issues', :action => 'show', :id => issue)
+ #recipients = issue.recipients
+ #cc = issue.watcher_recipients - recipients
+ #mail :to => recipients,
+ # :cc => cc,
+ # :subject => "[#{issue.project.name} - #{issue.tracker.name} ##{issue_id}] (#{issue.status.name}) #{issue.subject}"
+ ######################################################################################################
+ end
+
+
+ # Builds a Mail::Message object used to email users belonging to the added document's project.
+ #
+ # Example:
+ # document_added(document) => Mail::Message object
+ # Mailer.document_added(document).deliver => sends an email to the document's project recipients
+ def document_added(document)
+ redmine_headers 'Project' => document.project.identifier
+ @author = User.current
+ @document = document
+ @issue_author_url = url_for(user_activities_url(@author))
+ @document_url = url_for(:controller => 'documents', :action => 'show', :id => document)
+ mail :to => document.recipients,
+ :subject => "[#{document.project.name}] #{l(:label_document_new)}: #{document.title}",
+ :filter => true
+ end
+
+ # Builds a Mail::Message object used to email recipients of a project when an attachements are added.
+ #
+ # Example:
+ # attachments_added(attachments) => Mail::Message object
+ # Mailer.attachments_added(attachments).deliver => sends an email to the project's recipients
+ def attachments_added(attachments)
+ container = attachments.first.container
+ added_to = ''
+ added_to_url = ''
+ @author = attachments.first.author
+ @issue_author_url = url_for(user_activities_url(@author))
+ case container.class.name
+ when 'Project'
+ added_to_url = url_for(:controller => 'files', :action => 'index', :project_id => container)
+ added_to = "#{l(:label_project)}: #{container}"
+ recipients = container.notified_users.select { |user| user.allowed_to?(:view_files, container) }.collect { |u| u.mail }
+ when 'Course'
+ added_to_url = url_for(:controller => 'files', :action => 'index', :course_id => container)
+ added_to = "#{l(:label_course)}: #{container.name}"
+ recipients = container.notified_users.select { |user| user.allowed_to?(:view_files, container) }.collect { |u| u.mail }
+ when 'Version'
+ added_to_url = url_for(:controller => 'files', :action => 'index', :project_id => container.project)
+ added_to = "#{l(:label_version)}: #{container.name}"
+ recipients = container.project.notified_users.select { |user| user.allowed_to?(:view_files, container.project) }.collect { |u| u.mail }
+ when 'Document'
+ added_to_url = url_for(:controller => 'documents', :action => 'show', :id => container.id)
+ added_to = "#{l(:label_document)}: #{container.title}"
+ recipients = container.recipients
+ end
+ if container.class.name == 'Course'
+ redmine_headers 'Course' => container.id
+ @attachments = attachments
+ @added_to = added_to
+ @added_to_url = added_to_url
+ mail :to => recipients,
+ :subject => "[#{container.name}] #{l(:label_attachment_new)}",
+ :filter => true
+ elsif container.class.name == 'Project'
+ redmine_headers 'Project' => container.id
+ @attachments = attachments
+ @added_to = added_to
+ @added_to_url = added_to_url
+ mail :to => recipients,
+ :subject => "[#{container.name}] #{l(:label_attachment_new)}",
+ :filter => true
+ else
+ redmine_headers 'Project' => container.project.identifier
+ @attachments = attachments
+ @added_to = added_to
+ @added_to_url = added_to_url
+ mail :to => recipients,
+ :subject => "[#{container.project.name}] #{l(:label_attachment_new)}",
+ :filter => true
+ end
+ end
+
+ # Builds a Mail::Message object used to email recipients of a news' project when a news item is added.
+ #
+ # Example:
+ # news_added(news) => Mail::Message object
+ # Mailer.news_added(news).deliver => sends an email to the news' project recipients
+ def news_added(news)
+
+ if news.project
+ redmine_headers 'Project' => news.project.identifier
+ @author = news.author
+ @issue_author_url = url_for(user_activities_url(@author))
+ message_id news
+ @news = news
+ @news_url = url_for(:controller => 'news', :action => 'show', :id => news)
+ mail :to => news.recipients,
+ :subject => "[#{news.project.name}] #{l(:label_news)}: #{news.title}",
+ :filter => true
+ elsif news.course
+ redmine_headers 'Course' => news.course.id
+ @author = news.author
+ @issue_author_url = url_for(user_activities_url(@author))
+ message_id news
+ @news = news
+ recipients = news.course.notified_users.select { |user| user.allowed_to?(:view_files, news.course) }.collect { |u| u.mail }
+ @news_url = url_for(:controller => 'news', :action => 'show', :id => news)
+ mail :to => recipients,
+ :subject => "[#{news.course.name}] #{l(:label_news)}: #{news.title}",
+ :filter => true
+ end
+ end
+
+ # Builds a Mail::Message object used to email recipients of a news' project when a news comment is added.
+ #
+ # Example:
+ # news_comment_added(comment) => Mail::Message object
+ # Mailer.news_comment_added(comment) => sends an email to the news' project recipients
+ def news_comment_added(comment)
+ news = comment.commented
+ if news.project
+ redmine_headers 'Project' => news.project.identifier
+ @author = comment.author
+ @issue_author_url = url_for(user_activities_url(@author))
+ message_id comment
+ @news = news
+ @comment = comment
+ @news_url = url_for(:controller => 'news', :action => 'show', :id => news)
+ mail :to => news.recipients,
+ :cc => news.watcher_recipients,
+ :subject => "Re: [#{news.project.name}] #{l(:label_news)}: #{news.title}",
+ :filter => true
+ elsif news.course
+ redmine_headers 'Course' => news.course.id
+ @author = comment.author
+ @issue_author_url = url_for(user_activities_url(@author))
+ message_id comment
+ @news = news
+ @comment = comment
+ @news_url = url_for(:controller => 'news', :action => 'show', :id => news)
+ recipients = news.course.notified_users.select { |user| user.allowed_to?(:view_files, news.course) }.collect { |u| u.mail }
+
+ mail :to => recipients,
+ :subject => "[#{news.course.name}] #{l(:label_news)}: #{news.title}",
+ :filter => true
+ end
+ end
+
+ # Builds a Mail::Message object used to email the recipients of the specified message that was posted.
+ #
+ # Example:
+ # message_posted(message) => Mail::Message object
+ # Mailer.message_posted(message).deliver => sends an email to the recipients
+ def message_posted(message)
+ if message.project
+ redmine_headers 'Project' => message.project.identifier,
+ 'Topic-Id' => (message.parent_id || message.id)
+ @author = message.author
+ @issue_author_url = url_for(user_activities_url(@author))
+ message_id message
+ references message.parent unless message.parent.nil?
+ recipients = message.recipients
+ cc = ((message.root.watcher_recipients + message.board.watcher_recipients).uniq - recipients)
+ @message = message
+ @message_url = url_for(message.event_url)
+ mail :to => recipients,
+ :cc => cc,
+ :subject => "[#{message.board.project.name} - #{message.board.name} - msg#{message.root.id}] #{message.subject}",
+ :filter => true
+ elsif message.course
+ redmine_headers 'Course' => message.course.id,
+ 'Topic-Id' => (message.parent_id || message.id)
+ @author = message.author
+ @issue_author_url = url_for(user_activities_url(@author))
+ message_id message
+ references message.parent unless message.parent.nil?
+ recipients = message.course.notified_users.select { |user| user.allowed_to?(:view_files, message.course) }.collect { |u| u.mail }
+ cc = ((message.root.watcher_recipients + message.board.watcher_recipients).uniq - recipients)
+ @message = message
+ @message_url = url_for(message.event_url)
+ mail :to => recipients,
+ :cc => cc,
+ :subject => "[#{message.board.course.name} - #{message.board.name} - msg#{message.root.id}] #{message.subject}",
+ :filter => true
+ end
+ end
+
+ # Builds a Mail::Message object used to email the recipients of a project of the specified wiki content was added.
+ #
+ # Example:
+ # wiki_content_added(wiki_content) => Mail::Message object
+ # Mailer.wiki_content_added(wiki_content).deliver => sends an email to the project's recipients
+ def wiki_content_added(wiki_content)
+ redmine_headers 'Project' => wiki_content.project.identifier,
+ 'Wiki-Page-Id' => wiki_content.page.id
+ @author = wiki_content.author
+ message_id wiki_content
+ recipients = wiki_content.recipients
+ cc = wiki_content.page.wiki.watcher_recipients - recipients
+ @wiki_content = wiki_content
+ @wiki_content_url = url_for(:controller => 'wiki', :action => 'show',
+ :project_id => wiki_content.project,
+ :id => wiki_content.page.title)
+ mail :to => recipients,
+ :cc => cc,
+ :subject => "[#{wiki_content.project.name}] #{l(:mail_subject_wiki_content_added, :id => wiki_content.page.pretty_title)}",
+ :filter => true
+ end
+
+ # Builds a Mail::Message object used to email the recipients of a project of the specified wiki content was updated.
+ #
+ # Example:
+ # wiki_content_updated(wiki_content) => Mail::Message object
+ # Mailer.wiki_content_updated(wiki_content).deliver => sends an email to the project's recipients
+ def wiki_content_updated(wiki_content)
+ redmine_headers 'Project' => wiki_content.project.identifier,
+ 'Wiki-Page-Id' => wiki_content.page.id
+ @author = wiki_content.author
+ message_id wiki_content
+ recipients = wiki_content.recipients
+ cc = wiki_content.page.wiki.watcher_recipients + wiki_content.page.watcher_recipients - recipients
+ @wiki_content = wiki_content
+ @wiki_content_url = url_for(:controller => 'wiki', :action => 'show',
+ :project_id => wiki_content.project,
+ :id => wiki_content.page.title)
+ @wiki_diff_url = url_for(:controller => 'wiki', :action => 'diff',
+ :project_id => wiki_content.project, :id => wiki_content.page.title,
+ :version => wiki_content.version)
+ mail :to => recipients,
+ :cc => cc,
+ :subject => "[#{wiki_content.project.name}] #{l(:mail_subject_wiki_content_updated, :id => wiki_content.page.pretty_title)}",
+ :filter => true
+ end
+
+ # Builds a Mail::Message object used to email the specified user their account information.
+ #
+ # Example:
+ # account_information(user, password) => Mail::Message object
+ # Mailer.account_information(user, password).deliver => sends account information to the user
+ def account_information(user, password)
+ set_language_if_valid user.language
+ @user = user
+ @password = password
+ @login_url = url_for(:controller => 'account', :action => 'login')
+ mail :to => user.mail,
+ :subject => l(:mail_subject_register, Setting.app_title)
+ end
+
+ # Builds a Mail::Message object used to email all active administrators of an account activation request.
+ #
+ # Example:
+ # account_activation_request(user) => Mail::Message object
+ # Mailer.account_activation_request(user).deliver => sends an email to all active administrators
+ def account_activation_request(user)
+ # Send the email to all active administrators
+ recipients = User.active.where(:admin => true).all.collect { |u| u.mail }.compact
+ @user = user
+ @url = url_for(:controller => 'users', :action => 'index',
+ :status => User::STATUS_REGISTERED,
+ :sort_key => 'created_on', :sort_order => 'desc')
+ mail :to => recipients,
+ :subject => l(:mail_subject_account_activation_request, Setting.app_title)
+ end
+
+ # Builds a Mail::Message object used to email the specified user that their account was activated by an administrator.
+ #
+ # Example:
+ # account_activated(user) => Mail::Message object
+ # Mailer.account_activated(user).deliver => sends an email to the registered user
+ def account_activated(user)
+ set_language_if_valid user.language
+ @user = user
+ @login_url = url_for(:controller => 'account', :action => 'login')
+ mail :to => user.mail,
+ :subject => l(:mail_subject_register, Setting.app_title)
+ end
+
+ def lost_password(token)
+ set_language_if_valid(token.user.language)
+ @token = token
+ @url = url_for(:controller => 'account', :action => 'lost_password', :token => token.value)
+ mail :to => token.user.mail,
+ :subject => l(:mail_subject_lost_password, Setting.app_title)
+ end
+
+ def register(token)
+ set_language_if_valid(token.user.language)
+ @token = token
+ @url = url_for(:controller => 'account', :action => 'activate', :token => token.value)
+ mail :to => token.user.mail,
+ :subject => l(:mail_subject_register, Setting.app_title)
+ end
+
+ def test_email(user)
+ set_language_if_valid(user.language)
+ @url = url_for(:controller => 'welcome')
+ mail :to => user.mail,
+ :subject => 'forge test'
+ end
+
+ # Overrides default deliver! method to prevent from sending an email
+ # with no recipient, cc or bcc
+ def deliver!(mail = @mail)
+ set_language_if_valid @initial_language
+ return false if (recipients.nil? || recipients.empty?) &&
+ (cc.nil? || cc.empty?) &&
+ (bcc.nil? || bcc.empty?)
+
+
+ # Log errors when raise_delivery_errors is set to false, Rails does not
+ raise_errors = self.class.raise_delivery_errors
+ self.class.raise_delivery_errors = true
+ begin
+ return super(mail)
+ rescue Exception => e
+ if raise_errors
+ raise e
+ elsif mylogger
+ mylogger.error "The following error occured while sending email notification: \"#{e.message}\". Check your configuration in config/configuration.yml."
+ end
+ ensure
+ self.class.raise_delivery_errors = raise_errors
+ end
+ end
+
+ # Sends reminders to issue assignees
+ # Available options:
+ # * :days => how many days in the future to remind about (defaults to 7)
+ # * :tracker => id of tracker for filtering issues (defaults to all trackers)
+ # * :project => id or identifier of project to process (defaults to all projects)
+ # * :users => array of user/group ids who should be reminded
+ def self.reminders(options={})
+ days = options[:days] || 7
+ project = options[:project] ? Project.find(options[:project]) : nil
+ tracker = options[:tracker] ? Tracker.find(options[:tracker]) : nil
+ user_ids = options[:users]
+
+ scope = Issue.open.where("#{Issue.table_name}.assigned_to_id IS NOT NULL" +
+ " AND #{Project.table_name}.status = #{Project::STATUS_ACTIVE}" +
+ " AND #{Issue.table_name}.due_date <= ?", days.day.from_now.to_date
+ )
+ scope = scope.where(:assigned_to_id => user_ids) if user_ids.present?
+ scope = scope.where(:project_id => project.id) if project
+ scope = scope.where(:tracker_id => tracker.id) if tracker
+
+ issues_by_assignee = scope.includes(:status, :assigned_to, :project, :tracker).all.group_by(&:assigned_to)
+ issues_by_assignee.keys.each do |assignee|
+ if assignee.is_a?(Group)
+ assignee.users.each do |user|
+ issues_by_assignee[user] ||= []
+ issues_by_assignee[user] += issues_by_assignee[assignee]
+ end
+ end
+ end
+
+ issues_by_assignee.each do |assignee, issues|
+ reminder(assignee, issues, days).deliver if assignee.is_a?(User) && assignee.active?
+ end
+ end
+
+ # Activates/desactivates email deliveries during +block+
+ def self.with_deliveries(enabled = true, &block)
+ was_enabled = ActionMailer::Base.perform_deliveries
+ ActionMailer::Base.perform_deliveries = !!enabled
+ yield
+ ensure
+ ActionMailer::Base.perform_deliveries = was_enabled
+ end
+
+ # Sends emails synchronously in the given block
+ def self.with_synched_deliveries(&block)
+ saved_method = ActionMailer::Base.delivery_method
+ if m = saved_method.to_s.match(%r{^async_(.+)$})
+ synched_method = m[1]
+ ActionMailer::Base.delivery_method = synched_method.to_sym
+ ActionMailer::Base.send "#{synched_method}_settings=", ActionMailer::Base.send("async_#{synched_method}_settings")
+ end
+ yield
+ ensure
+ ActionMailer::Base.delivery_method = saved_method
+ end
+
+ #过滤掉不是不合规则的收件人
+ def filter(reps)
+ r_reps = []
+ if reps.is_a? Array
+ reps.each do |r|
+ u = User.find_by_mail(r)
+ if u && u.mail_notification == 'all'
+ r_reps << r
+ end
+ end
+ elsif reps.is_a? String
+ u = User.find_by_mail(reps)
+ if u && u.mail_notification == 'all'
+ r_reps << reps
+ end
+ end
+ r_reps
+ end
+
+ def mail(headers={})
+ headers.merge! 'X-Mailer' => 'Redmine',
+ 'X-Redmine-Host' => Setting.host_name,
+ 'X-Redmine-Site' => Setting.app_title,
+ 'X-Auto-Response-Suppress' => 'OOF',
+ 'Auto-Submitted' => 'auto-generated',
+ 'From' => Setting.mail_from,
+ 'List-Id' => "<#{Setting.mail_from.to_s.gsub('@', '.')}>"
+
+ # Removes the author from the recipients and cc
+ # if he doesn't want to receive notifications about what he does
+ if @author && @author.logged? && @author.pref[:no_self_notified]
+ headers[:to].delete(@author.mail) if headers[:to].is_a?(Array)
+ headers[:cc].delete(@author.mail) if headers[:cc].is_a?(Array)
+ end
+
+ if headers[:filter]
+ headers[:to] = filter(headers[:to])
+ headers[:cc] = filter(headers[:cc])
+ end
+
+ if @author && @author.logged?
+ redmine_headers 'Sender' => @author.login
+ end
+
+ # Blind carbon copy recipients
+ if Setting.bcc_recipients?
+ headers[:bcc] = [headers[:to], headers[:cc]].flatten.uniq.reject(&:blank?)
+ headers[:to] = nil
+ headers[:cc] = nil
+ end
+
+ if @message_id_object
+ headers[:message_id] = "<#{self.class.message_id_for(@message_id_object)}>"
+ end
+ if @references_objects
+ headers[:references] = @references_objects.collect {|o| "<#{self.class.message_id_for(o)}>"}.join(' ')
+ end
+
+ set_language_if_valid @initial_language
+ m = super headers do |format|
+ format.text
+ format.html unless Setting.plain_text_mail?
+ end
+ mylogger.debug "Sent a mail from #{m.from} to [#{m.to},#{m.cc}, #{m.bcc if Setting.bcc_recipients?}] subject: #{m.subject}"
+ m
+ end
+
+ def initialize(*args)
+ @initial_language = current_language
+ set_language_if_valid Setting.default_language
+ super
+ end
+
+ def self.deliver_mail(mail)
+ return false if mail.to.blank? && mail.cc.blank? && mail.bcc.blank?
+ Thread.new do
+ super
+ end
+ end
+
+ def self.method_missing(method, *args, &block)
+ if m = method.to_s.match(%r{^deliver_(.+)$})
+ ActiveSupport::Deprecation.warn "Mailer.deliver_#{m[1]}(*args) is deprecated. Use Mailer.#{m[1]}(*args).deliver instead."
+ send(m[1], *args).deliver
+ else
+ super
+ end
+ end
+
+
+
+ private
+
+ # Appends a Redmine header field (name is prepended with 'X-Redmine-')
+ def redmine_headers(h)
+ h.each { |k,v| headers["X-Redmine-#{k}"] = v.to_s }
+ end
+
+ # Returns a predictable Message-Id for the given object
+ def self.message_id_for(object)
+ # id + timestamp should reduce the odds of a collision
+ # as far as we don't send multiple emails for the same object
+ timestamp = object.send(object.respond_to?(:created_on) ? :created_on : :updated_on)
+ hash = "redmine.#{object.class.name.demodulize.underscore}-#{object.id}.#{timestamp.strftime("%Y%m%d%H%M%S")}"
+ host = Setting.mail_from.to_s.gsub(%r{^.*@}, '')
+ host = "#{::Socket.gethostname}.redmine" if host.empty?
+ "#{hash}@#{host}"
+ end
+
+ def message_id(object)
+ @message_id_object = object
+ end
+
+ def references(object)
+ @references_objects ||= []
+ @references_objects << object
+ end
+
+ def mylogger
+ if Setting.delayjob_enabled?
+ Delayed::Worker.logger
+ else
+ Rails.logger
+ end
+ end
+
+ def add_attachments(obj)
+ if email.attachments && email.attachments.any?
+ email.attachments.each do |attachment|
+ obj.attachments << Attachment.create(:container => obj,
+ :file => attachment.decoded,
+ :filename => attachment.filename,
+ :author => user,
+ :content_type => attachment.mime_type)
+ end
+ end
+ end
+
+ # author: alan
+ # 功能: 生成len位随机字符串
+ def newpass(len)
+ chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a
+ newpass = ""
+ 1.upto(len) { |i| newpass << chars[rand(chars.size-1)] }
+ return newpass
+ end
+end
diff --git a/app/models/memo.rb b/app/models/memo.rb
index 191d4f978..2831effe3 100644
--- a/app/models/memo.rb
+++ b/app/models/memo.rb
@@ -1,179 +1,179 @@
-class Memo < ActiveRecord::Base
- include Redmine::SafeAttributes
- include UserScoreHelper
- include ApplicationHelper
- belongs_to :forum
- has_many_kindeditor_assets :assets, :dependent => :destroy
- belongs_to :author, :class_name => "User", :foreign_key => 'author_id'
- validates_presence_of :author_id, :forum_id, :subject,:content
- # 若是主题帖,则内容可以是空
- #validates :content, presence: true, if: Proc.new{|o| !o.parent_id.nil? }
- validates_length_of :subject, maximum: 50
- #validates_length_of :content, maximum: 3072
- validate :cannot_reply_to_locked_topic, :on => :create
-
- acts_as_tree :counter_cache => :replies_count, :order => "#{Memo.table_name}.created_at ASC"
- acts_as_attachable
- has_many :user_score_details, :class_name => 'UserScoreDetails',:as => :score_changeable_obj
- has_many :praise_tread, as: :praise_tread_object, dependent: :destroy
- belongs_to :last_reply, :class_name => 'Memo', :foreign_key => 'last_reply_id'
- # acts_as_searchable :column => ['subject', 'content'],
- # #:include => { :forum => :p}
- # #:project_key => "#{Forum.table_name}.project_id"
- # :date_column => "#{table_name}.created_at"
- acts_as_event :title => Proc.new {|o| "#{o.forum.name}: #{o.subject}"},
- :datetime => :updated_at,
- # :datetime => :created_at,
- :description => :content,
- :author => :author,
- :type => Proc.new {|o| o.parent_id.nil? ? 'Memo' : 'Reply'},
- :url => Proc.new {|o| {:controller => 'memos', :action => 'show', :forum_id => o.forum_id}.merge(o.parent_id.nil? ? {:id => o.id} : {:id => o.parent_id, :r => o.id, :anchor => "reply-#{o.id}"})}
- acts_as_activity_provider :author_key => :author_id,
- :func => 'memos',
- :timestamp => 'created_at'
- # :find_options => {:type => 'memos'}
- # acts_as_watchable
-
- safe_attributes "author_id",
- "subject",
- "content",
- "forum_id",
- "last_memo_id",
- "lock",
- "sticky",
- "parent_id",
- "replies_count"
-
- after_create :add_author_as_watcher, :reset_counters!, :send_mail
- # after_update :update_memos_forum
- after_destroy :reset_counters!,:delete_kindeditor_assets#,:down_user_score -- 公共区发帖暂不计入得分
- # after_create :send_notification
- # after_save :plusParentAndForum
- # after_destroy :minusParentAndForum
- #before_save :be_user_score
- # scope :visible, lambda { |*args|
- # includes(:forum => ).where()
- # }
-
- def send_mail
- Mailer.run.forum_message_added(self) if Setting.notified_events.include?('forum_message_added')
- end
-
- def cannot_reply_to_locked_topic
- errors.add :base, l(:label_memo_locked) if root.locked? && self != root
- end
-
- # def update_memos_forum
- # if forum_id_changed?
- # Message.update_all({:board_id => board_id}, ["id = ? OR parent_id = ?", root.id, root.id ])
- # Forum.reset_counters!(forum_id_was)
- # Forum.reset_counters!(forum_id)
- # end
- # end
-
- def reset_counters!
- if parent && parent.id
- Memo.update_all({:last_reply_id => parent.children.maximum(:id)}, {:id => parent.id})
- parent.update_attribute(:updated_at, Time.now)
- end
- forum.reset_counters!
- end
-
- def sticky?
- sticky == 1
- end
-
- def replies
- Memo.where("parent_id = ?", id)
- end
-
- def locked?
- self.lock
- end
-
- def editable_by? user
- # user && user.logged? || (self.author == usr && usr.allowed_to?(:edit_own_messages, project))
- user.admin? || self.author == user
- end
-
- def destroyable_by? user
- (user && self.author == user) || user.admin?
- #self.author == user || user.admin?
- end
-
- def deleted_attach_able_by? user
- (user && user.logged? && (self.author == user) ) || user.admin?
- end
-
- private
-
- def add_author_as_watcher
- Watcher.create(:watchable => self.root, :user => author)
- end
-
- def send_notification
- if Setting.notified_events.include?('message_posted')
- Mailer.run.message_posted(self)
- end
- end
-
- def plusParentAndForum
- @forum = Forum.find(self.forum_id)
- @forum.memo_count = @forum.memo_count.to_int + 1
- @forum.last_memo_id = self.id
- if self.parent_id
- @parent_memo = Memo.find_by_id(self.parent_id)
- @parent_memo.last_reply_id = self
- @parent_memo.replies_count = @parent_memo.replies_count.to_int + 1
- @parent_memo.save
- else
- @forum.topic_count = @forum.topic_count.to_int + 1
- end
- @forum.save
- end
-
- def minusParentAndForum
- @forum = Forum.find(self.forum_id)
- @forum.memo_count = @forum.memo_count.to_int - 1
- @forum.memo_count = 0 if @forum.memo_count.to_int < 0
- # @forum.last_memo_id = Memo.reorder('created_at ASC').find_all_by_forum_id(self.forum_id).last.id
- if self.parent_id
- @parent_memo = Memo.find_by_id(self.parent_id)
- # @parent_memo.last_reply_id = Memo.reorder('created_at ASC').find_all_by_parent_id(self.parent_id).last.id
- @parent_memo.replies_count = @parent_memo.replies_count.to_int - 1
- @parent_memo.replies_count = 0 if @parent_memo.replies_count.to_int < 0
- @parent_memo.save
- else
- @forum.topic_count = @forum.topic_count.to_int - 1
- @forum.topic_count = 0 if @forum.topic_count.to_int < 0
- end
- @forum.save
- end
-
- #更新用户分数 -by zjc
- def be_user_score
- #新建memo且无parent的为发帖
- if self.parent_id.nil?
- UserScore.joint(:post_message, User.current,nil,self ,{ memo_id: self.id })
- update_memo_number(User.current,1)
-
- #新建memo且有parent的为回帖
- elsif !self.parent_id.nil?
- UserScore.joint(:reply_posting, User.current,self.parent.author,self, { memo_id: self.id })
- update_replay_for_memo(User.current,1)
- end
- end
-
- #被删除时更新用户分数
- def down_user_score
- update_memo_number(User.current,1)
- update_replay_for_memo(User.current,1)
- end
-
- # Time 2015-03-26 15:20:24
- # Author lizanle
- # Description 从硬盘上删除资源
- def delete_kindeditor_assets
- delete_kindeditor_assets_from_disk self.id,OwnerTypeHelper::MEMO
- end
-end
+class Memo < ActiveRecord::Base
+ include Redmine::SafeAttributes
+ include UserScoreHelper
+ include ApplicationHelper
+ belongs_to :forum
+ has_many_kindeditor_assets :assets, :dependent => :destroy
+ belongs_to :author, :class_name => "User", :foreign_key => 'author_id'
+ validates_presence_of :author_id, :forum_id, :subject,:content
+ # 若是主题帖,则内容可以是空
+ #validates :content, presence: true, if: Proc.new{|o| !o.parent_id.nil? }
+ validates_length_of :subject, maximum: 50
+ #validates_length_of :content, maximum: 3072
+ validate :cannot_reply_to_locked_topic, :on => :create
+
+ acts_as_tree :counter_cache => :replies_count, :order => "#{Memo.table_name}.created_at ASC"
+ acts_as_attachable
+ has_many :user_score_details, :class_name => 'UserScoreDetails',:as => :score_changeable_obj
+ has_many :praise_tread, as: :praise_tread_object, dependent: :destroy
+ belongs_to :last_reply, :class_name => 'Memo', :foreign_key => 'last_reply_id'
+ # acts_as_searchable :column => ['subject', 'content'],
+ # #:include => { :forum => :p}
+ # #:project_key => "#{Forum.table_name}.project_id"
+ # :date_column => "#{table_name}.created_at"
+ acts_as_event :title => Proc.new {|o| "#{o.forum.name}: #{o.subject}"},
+ :datetime => :updated_at,
+ # :datetime => :created_at,
+ :description => :content,
+ :author => :author,
+ :type => Proc.new {|o| o.parent_id.nil? ? 'Memo' : 'Reply'},
+ :url => Proc.new {|o| {:controller => 'memos', :action => 'show', :forum_id => o.forum_id}.merge(o.parent_id.nil? ? {:id => o.id} : {:id => o.parent_id, :r => o.id, :anchor => "reply-#{o.id}"})}
+ acts_as_activity_provider :author_key => :author_id,
+ :func => 'memos',
+ :timestamp => 'created_at'
+ # :find_options => {:type => 'memos'}
+ # acts_as_watchable
+
+ safe_attributes "author_id",
+ "subject",
+ "content",
+ "forum_id",
+ "last_memo_id",
+ "lock",
+ "sticky",
+ "parent_id",
+ "replies_count"
+
+ after_create :add_author_as_watcher, :reset_counters!, :send_mail
+ # after_update :update_memos_forum
+ after_destroy :reset_counters!,:delete_kindeditor_assets#,:down_user_score -- 公共区发帖暂不计入得分
+ # after_create :send_notification
+ # after_save :plusParentAndForum
+ # after_destroy :minusParentAndForum
+ #before_save :be_user_score
+ # scope :visible, lambda { |*args|
+ # includes(:forum => ).where()
+ # }
+
+ def send_mail
+ Mailer.run.forum_message_added(self) if Setting.notified_events.include?('forum_message_added')
+ end
+
+ def cannot_reply_to_locked_topic
+ errors.add :base, l(:label_memo_locked) if root.locked? && self != root
+ end
+
+ # def update_memos_forum
+ # if forum_id_changed?
+ # Message.update_all({:board_id => board_id}, ["id = ? OR parent_id = ?", root.id, root.id ])
+ # Forum.reset_counters!(forum_id_was)
+ # Forum.reset_counters!(forum_id)
+ # end
+ # end
+
+ def reset_counters!
+ if parent && parent.id
+ Memo.update_all({:last_reply_id => parent.children.maximum(:id)}, {:id => parent.id})
+ parent.update_attribute(:updated_at, Time.now)
+ end
+ forum.reset_counters!
+ end
+
+ def sticky?
+ sticky == 1
+ end
+
+ def replies
+ Memo.where("parent_id = ?", id)
+ end
+
+ def locked?
+ self.lock
+ end
+
+ def editable_by? user
+ # user && user.logged? || (self.author == usr && usr.allowed_to?(:edit_own_messages, project))
+ user.admin? || self.author == user
+ end
+
+ def destroyable_by? user
+ (user && self.author == user) || user.admin?
+ #self.author == user || user.admin?
+ end
+
+ def deleted_attach_able_by? user
+ (user && user.logged? && (self.author == user) ) || user.admin?
+ end
+
+ private
+
+ def add_author_as_watcher
+ Watcher.create(:watchable => self.root, :user => author)
+ end
+
+ def send_notification
+ if Setting.notified_events.include?('message_posted')
+ Mailer.run.message_posted(self)
+ end
+ end
+
+ def plusParentAndForum
+ @forum = Forum.find(self.forum_id)
+ @forum.memo_count = @forum.memo_count.to_int + 1
+ @forum.last_memo_id = self.id
+ if self.parent_id
+ @parent_memo = Memo.find_by_id(self.parent_id)
+ @parent_memo.last_reply_id = self
+ @parent_memo.replies_count = @parent_memo.replies_count.to_int + 1
+ @parent_memo.save
+ else
+ @forum.topic_count = @forum.topic_count.to_int + 1
+ end
+ @forum.save
+ end
+
+ def minusParentAndForum
+ @forum = Forum.find(self.forum_id)
+ @forum.memo_count = @forum.memo_count.to_int - 1
+ @forum.memo_count = 0 if @forum.memo_count.to_int < 0
+ # @forum.last_memo_id = Memo.reorder('created_at ASC').find_all_by_forum_id(self.forum_id).last.id
+ if self.parent_id
+ @parent_memo = Memo.find_by_id(self.parent_id)
+ # @parent_memo.last_reply_id = Memo.reorder('created_at ASC').find_all_by_parent_id(self.parent_id).last.id
+ @parent_memo.replies_count = @parent_memo.replies_count.to_int - 1
+ @parent_memo.replies_count = 0 if @parent_memo.replies_count.to_int < 0
+ @parent_memo.save
+ else
+ @forum.topic_count = @forum.topic_count.to_int - 1
+ @forum.topic_count = 0 if @forum.topic_count.to_int < 0
+ end
+ @forum.save
+ end
+
+ #更新用户分数 -by zjc
+ def be_user_score
+ #新建memo且无parent的为发帖
+ if self.parent_id.nil?
+ UserScore.joint(:post_message, User.current,nil,self ,{ memo_id: self.id })
+ update_memo_number(User.current,1)
+
+ #新建memo且有parent的为回帖
+ elsif !self.parent_id.nil?
+ UserScore.joint(:reply_posting, User.current,self.parent.author,self, { memo_id: self.id })
+ update_replay_for_memo(User.current,1)
+ end
+ end
+
+ #被删除时更新用户分数
+ def down_user_score
+ update_memo_number(User.current,1)
+ update_replay_for_memo(User.current,1)
+ end
+
+ # Time 2015-03-26 15:20:24
+ # Author lizanle
+ # Description 从硬盘上删除资源
+ def delete_kindeditor_assets
+ delete_kindeditor_assets_from_disk self.id,OwnerTypeHelper::MEMO
+ end
+end
diff --git a/app/models/message.rb b/app/models/message.rb
index 669495b45..bbf62b5dc 100644
--- a/app/models/message.rb
+++ b/app/models/message.rb
@@ -1,221 +1,221 @@
-# 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 Message < ActiveRecord::Base
- include Redmine::SafeAttributes
- include UserScoreHelper
- include ApplicationHelper
- has_many_kindeditor_assets :assets, :dependent => :destroy
- belongs_to :board
- belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
- has_many :praise_tread, as: :praise_tread_object, dependent: :destroy
-
- acts_as_tree :counter_cache => :replies_count, :order => "#{Message.table_name}.created_on ASC"
- acts_as_attachable
- belongs_to :last_reply, :class_name => 'Message', :foreign_key => 'last_reply_id'
-
- # added by fq
- has_many :acts, :class_name => 'Activity', :as => :act, :dependent => :destroy
- # 被ForgeActivity虚拟关联
- has_many :forge_acts, :class_name => 'ForgeActivity',:as =>:forge_act ,:dependent => :destroy
- # end
-
- acts_as_searchable :columns => ['subject', 'content'],
- :include => {:board => :project},
- :project_key => "#{Board.table_name}.project_id",
- :date_column => "#{table_name}.created_on"
- acts_as_searchable :columns => ['subject', 'content'],
- :include => {:board => :course},
- :course_key => "#{Board.table_name}.course_id",
- :date_column => "#{table_name}.created_at"
- acts_as_event :title => Proc.new {|o| "#{o.board.name}: #{o.subject}"},
- :description => :content,
- :datetime => :updated_on,
- # :datetime => "#{Message.table_name}.created_on",
- :group => :parent,
- :type => Proc.new {|o| o.parent_id.nil? ? 'message' : 'reply'},
- :url => Proc.new {|o| {:controller => 'messages', :action => 'show', :board_id => o.board_id}.merge(o.parent_id.nil? ? {:id => o.id} :
- {:id => o.parent_id, :r => o.id, :anchor => "message-#{o.id}"})}
-
- acts_as_activity_provider :find_options => {:include => [{:board => :project}, :author]},
- :author_key => :author_id
- acts_as_activity_provider :find_options => {:include => [{:board => :course}, :author]},
- :type => 'course_messages',
- :author_key => :author_id
- acts_as_watchable
-
- validates_presence_of :board, :subject, :content
- validates_length_of :subject, :maximum => 255
- validate :cannot_reply_to_locked_topic, :on => :create
-
- after_create :add_author_as_watcher, :reset_counters!
- after_update :update_messages_board
- after_destroy :reset_counters!,:down_user_score,:delete_kindeditor_assets
-
- after_create :act_as_activity,:be_user_score,:act_as_forge_activity, :send_mail
- #before_save :be_user_score
-
- scope :visible, lambda {|*args|
- includes(:board => :project).where(Project.allowed_to_condition(args.shift || User.current, :view_messages, *args))
- }
-
- scope :course_visible, lambda {|*args|
- includes(:board => :course).where(Course.allowed_to_condition(args.shift || User.current, :view_course_messages, *args))
- }
-
-
- safe_attributes 'subject', 'content'
- safe_attributes 'board_id','locked', 'sticky',
- :if => lambda {|message, user|
- if message.project
- user.allowed_to?(:edit_messages, message.project)
- else
- user.allowed_to?(:edit_messages, message.course)
- end
- }
-
- def visible?(user=User.current)
- if project
- !user.nil? && user.allowed_to?(:view_messages, project)
- elsif course
- !user.nil? && user.allowed_to?(:view_messages, course)
- end
- end
-
- def cannot_reply_to_locked_topic
- # Can not reply to a locked topic
- errors.add :base, 'Topic is locked' if root.locked? && self != root
- end
-
- def update_messages_board
- if board_id_changed?
- Message.update_all({:board_id => board_id}, ["id = ? OR parent_id = ?", root.id, root.id])
- Board.reset_counters!(board_id_was)
- Board.reset_counters!(board_id)
- end
- end
-
- def reset_counters!
- if parent && parent.id
- Message.update_all({:last_reply_id => parent.children.maximum(:id)}, {:id => parent.id})
- end
- board.reset_counters!
- end
-
- def sticky=(arg)
- write_attribute :sticky, (arg == true || arg.to_s == '1' ? 1 : 0)
- end
-
- def sticky?
- sticky == 1
- end
-
- def project
- board.project
- end
-
- def course
- board.course
- end
-
- def course_editable_by?(usr)
- usr && usr.logged? && (usr.allowed_to?(:edit_messages, course) || (self.author == usr && usr.allowed_to?(:edit_own_messages, course)))
- end
-
- def course_destroyable_by?(usr)
- usr && usr.logged? && (usr.allowed_to?(:delete_messages, course) || (self.author == usr && usr.allowed_to?(:delete_own_messages, course)))
- end
-
- def editable_by?(usr)
- usr && usr.logged? && (usr.allowed_to?(:edit_messages, project) || (self.author == usr && usr.allowed_to?(:edit_own_messages, project)))
- end
-
- def destroyable_by?(usr)
- usr && usr.logged? && (usr.allowed_to?(:delete_messages, project) || (self.author == usr && usr.allowed_to?(:delete_own_messages, project)))
- end
-
- private
-
- def add_author_as_watcher
- Watcher.create(:watchable => self.root, :user => author)
- end
-
- # fq
- def act_as_activity
- self.acts << Activity.new(:user_id => self.author_id)
- end
- # end
-
- # Time 2015-02-27 14:32:25
- # Author lizanle
- # Description
- def act_as_forge_activity
- # 如果project为空,那么就是课程相关的消息
- if !self.board.project.nil?
- self.forge_acts << ForgeActivity.new(:user_id => self.author_id,
- :project_id => self.board.project.id)
- end
- end
-
- #更新用户分数 -by zjc
- def be_user_score
- #新建message且无parent的为发帖
-
- if self.parent_id.nil? && !self.board.project.nil?
- UserScore.joint(:post_message, self.author,nil,self, { message_id: self.id })
- update_memo_number(self.author,1)
- if self.board.project_id != -1
- update_memo_number(self.author,2,self.board.project)
- end
- #新建message且有parent的为回帖
- elsif !self.parent_id.nil? && !self.board.project.nil?
- UserScore.joint(:reply_posting, self.author,self.parent.author,self, { message_id: self.id })
- update_replay_for_memo(self.author,1)
- if self.board.project_id != -1
- update_replay_for_memo(self.author,2,self.board.project)
- end
- end
- end
-
- #减少用户分数
- def down_user_score
- if self.parent_id.nil? && !self.board.project.nil?
- UserScore.joint(:delete_message, self.author,nil,self, { message_id: self.id })
- update_memo_number(User.current,1)
- if self.board.project_id != -1
- update_memo_number(self.author,2,self.board.project)
- end
- elsif !self.parent_id.nil? && !self.board.project.nil?
- UserScore.joint(:reply_deleting, self.author,self.parent.author,self, { message_id: self.id })
- update_replay_for_memo(User.current,1)
- if self.board.project_id != -1
- update_replay_for_memo(self.author,2,self.board.project)
- end
- end
- end
-
- def send_mail
- Mailer.run.message_posted(self) if Setting.notified_events.include?('message_posted')
- end
-
- # Time 2015-03-31 09:15:06
- # Author lizanle
- # Description 删除对应消息的图片资源
- def delete_kindeditor_assets
- delete_kindeditor_assets_from_disk self.id,OwnerTypeHelper::MESSAGE
- 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 Message < ActiveRecord::Base
+ include Redmine::SafeAttributes
+ include UserScoreHelper
+ include ApplicationHelper
+ has_many_kindeditor_assets :assets, :dependent => :destroy
+ belongs_to :board
+ belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
+ has_many :praise_tread, as: :praise_tread_object, dependent: :destroy
+
+ acts_as_tree :counter_cache => :replies_count, :order => "#{Message.table_name}.created_on ASC"
+ acts_as_attachable
+ belongs_to :last_reply, :class_name => 'Message', :foreign_key => 'last_reply_id'
+
+ # added by fq
+ has_many :acts, :class_name => 'Activity', :as => :act, :dependent => :destroy
+ # 被ForgeActivity虚拟关联
+ has_many :forge_acts, :class_name => 'ForgeActivity',:as =>:forge_act ,:dependent => :destroy
+ # end
+
+ acts_as_searchable :columns => ['subject', 'content'],
+ :include => {:board => :project},
+ :project_key => "#{Board.table_name}.project_id",
+ :date_column => "#{table_name}.created_on"
+ acts_as_searchable :columns => ['subject', 'content'],
+ :include => {:board => :course},
+ :course_key => "#{Board.table_name}.course_id",
+ :date_column => "#{table_name}.created_at"
+ acts_as_event :title => Proc.new {|o| "#{o.board.name}: #{o.subject}"},
+ :description => :content,
+ :datetime => :updated_on,
+ # :datetime => "#{Message.table_name}.created_on",
+ :group => :parent,
+ :type => Proc.new {|o| o.parent_id.nil? ? 'message' : 'reply'},
+ :url => Proc.new {|o| {:controller => 'messages', :action => 'show', :board_id => o.board_id}.merge(o.parent_id.nil? ? {:id => o.id} :
+ {:id => o.parent_id, :r => o.id, :anchor => "message-#{o.id}"})}
+
+ acts_as_activity_provider :find_options => {:include => [{:board => :project}, :author]},
+ :author_key => :author_id
+ acts_as_activity_provider :find_options => {:include => [{:board => :course}, :author]},
+ :type => 'course_messages',
+ :author_key => :author_id
+ acts_as_watchable
+
+ validates_presence_of :board, :subject, :content
+ validates_length_of :subject, :maximum => 255
+ validate :cannot_reply_to_locked_topic, :on => :create
+
+ after_create :add_author_as_watcher, :reset_counters!
+ after_update :update_messages_board
+ after_destroy :reset_counters!,:down_user_score,:delete_kindeditor_assets
+
+ after_create :act_as_activity,:be_user_score,:act_as_forge_activity, :send_mail
+ #before_save :be_user_score
+
+ scope :visible, lambda {|*args|
+ includes(:board => :project).where(Project.allowed_to_condition(args.shift || User.current, :view_messages, *args))
+ }
+
+ scope :course_visible, lambda {|*args|
+ includes(:board => :course).where(Course.allowed_to_condition(args.shift || User.current, :view_course_messages, *args))
+ }
+
+
+ safe_attributes 'subject', 'content'
+ safe_attributes 'board_id','locked', 'sticky',
+ :if => lambda {|message, user|
+ if message.project
+ user.allowed_to?(:edit_messages, message.project)
+ else
+ user.allowed_to?(:edit_messages, message.course)
+ end
+ }
+
+ def visible?(user=User.current)
+ if project
+ !user.nil? && user.allowed_to?(:view_messages, project)
+ elsif course
+ !user.nil? && user.allowed_to?(:view_messages, course)
+ end
+ end
+
+ def cannot_reply_to_locked_topic
+ # Can not reply to a locked topic
+ errors.add :base, 'Topic is locked' if root.locked? && self != root
+ end
+
+ def update_messages_board
+ if board_id_changed?
+ Message.update_all({:board_id => board_id}, ["id = ? OR parent_id = ?", root.id, root.id])
+ Board.reset_counters!(board_id_was)
+ Board.reset_counters!(board_id)
+ end
+ end
+
+ def reset_counters!
+ if parent && parent.id
+ Message.update_all({:last_reply_id => parent.children.maximum(:id)}, {:id => parent.id})
+ end
+ board.reset_counters!
+ end
+
+ def sticky=(arg)
+ write_attribute :sticky, (arg == true || arg.to_s == '1' ? 1 : 0)
+ end
+
+ def sticky?
+ sticky == 1
+ end
+
+ def project
+ board.project
+ end
+
+ def course
+ board.course
+ end
+
+ def course_editable_by?(usr)
+ usr && usr.logged? && (usr.allowed_to?(:edit_messages, course) || (self.author == usr && usr.allowed_to?(:edit_own_messages, course)))
+ end
+
+ def course_destroyable_by?(usr)
+ usr && usr.logged? && (usr.allowed_to?(:delete_messages, course) || (self.author == usr && usr.allowed_to?(:delete_own_messages, course)))
+ end
+
+ def editable_by?(usr)
+ usr && usr.logged? && (usr.allowed_to?(:edit_messages, project) || (self.author == usr && usr.allowed_to?(:edit_own_messages, project)))
+ end
+
+ def destroyable_by?(usr)
+ usr && usr.logged? && (usr.allowed_to?(:delete_messages, project) || (self.author == usr && usr.allowed_to?(:delete_own_messages, project)))
+ end
+
+ private
+
+ def add_author_as_watcher
+ Watcher.create(:watchable => self.root, :user => author)
+ end
+
+ # fq
+ def act_as_activity
+ self.acts << Activity.new(:user_id => self.author_id)
+ end
+ # end
+
+ # Time 2015-02-27 14:32:25
+ # Author lizanle
+ # Description
+ def act_as_forge_activity
+ # 如果project为空,那么就是课程相关的消息
+ if !self.board.project.nil?
+ self.forge_acts << ForgeActivity.new(:user_id => self.author_id,
+ :project_id => self.board.project.id)
+ end
+ end
+
+ #更新用户分数 -by zjc
+ def be_user_score
+ #新建message且无parent的为发帖
+
+ if self.parent_id.nil? && !self.board.project.nil?
+ UserScore.joint(:post_message, self.author,nil,self, { message_id: self.id })
+ update_memo_number(self.author,1)
+ if self.board.project_id != -1
+ update_memo_number(self.author,2,self.board.project)
+ end
+ #新建message且有parent的为回帖
+ elsif !self.parent_id.nil? && !self.board.project.nil?
+ UserScore.joint(:reply_posting, self.author,self.parent.author,self, { message_id: self.id })
+ update_replay_for_memo(self.author,1)
+ if self.board.project_id != -1
+ update_replay_for_memo(self.author,2,self.board.project)
+ end
+ end
+ end
+
+ #减少用户分数
+ def down_user_score
+ if self.parent_id.nil? && !self.board.project.nil?
+ UserScore.joint(:delete_message, self.author,nil,self, { message_id: self.id })
+ update_memo_number(User.current,1)
+ if self.board.project_id != -1
+ update_memo_number(self.author,2,self.board.project)
+ end
+ elsif !self.parent_id.nil? && !self.board.project.nil?
+ UserScore.joint(:reply_deleting, self.author,self.parent.author,self, { message_id: self.id })
+ update_replay_for_memo(User.current,1)
+ if self.board.project_id != -1
+ update_replay_for_memo(self.author,2,self.board.project)
+ end
+ end
+ end
+
+ def send_mail
+ Mailer.run.message_posted(self) if Setting.notified_events.include?('message_posted')
+ end
+
+ # Time 2015-03-31 09:15:06
+ # Author lizanle
+ # Description 删除对应消息的图片资源
+ def delete_kindeditor_assets
+ delete_kindeditor_assets_from_disk self.id,OwnerTypeHelper::MESSAGE
+ end
+end
diff --git a/app/models/news.rb b/app/models/news.rb
index de3ad35b0..7e809cbfd 100644
--- a/app/models/news.rb
+++ b/app/models/news.rb
@@ -1,120 +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 News < ActiveRecord::Base
- include Redmine::SafeAttributes
- belongs_to :project
- include ApplicationHelper
- has_many_kindeditor_assets :assets, :dependent => :destroy
- #added by nwb
- belongs_to :course
- belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
- has_many :comments, :as => :commented, :dependent => :delete_all, :order => "created_on"
- # fq
- has_many :acts, :class_name => 'Activity', :as => :act, :dependent => :destroy
- # 被ForgeActivity虚拟关联
- has_many :forge_acts, :class_name => 'ForgeActivity',:as =>:forge_act ,:dependent => :destroy
- # end
-
- validates_presence_of :title, :description
- validates_length_of :title, :maximum => 60
- validates_length_of :summary, :maximum => 255
- validates_length_of :description, :maximum => 10000
-
- acts_as_attachable :delete_permission => :manage_news
- acts_as_searchable :columns => ['title', 'summary', "#{table_name}.description"], :include => :project
- acts_as_event :url => Proc.new {|o| {:controller => 'news', :action => 'show', :id => o.id}}
- acts_as_activity_provider :find_options => {:include => [:project, :author]},
- :author_key => :author_id
- #added by nwb
- #课程新闻独立于项目
- acts_as_activity_provider :type => 'course_news',
- :find_options => {:include => [:course, :author]},
- :author_key => :author_id
- acts_as_watchable
-
- after_create :act_as_activity,:act_as_forge_activity,:add_author_as_watcher, :send_mail
-
- after_destroy :delete_kindeditor_assets
-
- scope :visible, lambda {|*args|
- includes(:project).where(Project.allowed_to_condition(args.shift || User.current, :view_news, *args))
- }
-
- scope :course_visible, lambda {|*args|
- includes(:course).where(Course.allowed_to_condition(args.shift || User.current, :view_course_news, *args))
- }
- safe_attributes 'title', 'summary', 'description'
-
- def visible?(user=User.current)
- !user.nil? && user.allowed_to?(:view_news, project)
- end
-
- # Returns true if the news can be commented by user
- def commentable?(user=User.current)
- user.allowed_to?(:comment_news, project)
- end
-
- def recipients
- project.users.select {|user| user.notify_about?(self)}.map(&:mail)
- end
-
- # returns latest news for projects visible by user
- def self.latest(user = User.current, count = 5)
- visible(user).includes([:author, :project]).order("#{News.table_name}.created_on DESC").limit(count).all
- end
-
- # 新闻的短描述信息
- def short_description(length = 255)
- description.gsub(/<\/?.*?>/,"").html_safe if description
- #description.gsub(/^(.{#{length}}[^\n\r]*).*$/m, '\1...').strip if description
- #description
- end
-
- private
-
- def add_author_as_watcher
- Watcher.create(:watchable => self, :user => author)
- end
- ## fq
- def act_as_activity
- self.acts << Activity.new(:user_id => self.author_id)
- end
-
- # Time 2015-02-27 15:48:17
- # Author lizanle
- # Description 公用表中也要记录
- def act_as_forge_activity
- # 如果是project为空,那么是课程相关的,不需要保存
- if !self.project.nil?
- self.forge_acts << ForgeActivity.new(:user_id => self.author_id,
- :project_id => self.project.id)
- end
- end
-
- # Time 2015-03-31 13:50:54
- # Author lizanle
- # Description 删除news后删除对应的资源
- def delete_kindeditor_assets
- delete_kindeditor_assets_from_disk self.id,OwnerTypeHelper::NEWS
- end
-
- def send_mail
- Mailer.run.news_added(self) if Setting.notified_events.include?('news_added')
- 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 News < ActiveRecord::Base
+ include Redmine::SafeAttributes
+ belongs_to :project
+ include ApplicationHelper
+ has_many_kindeditor_assets :assets, :dependent => :destroy
+ #added by nwb
+ belongs_to :course
+ belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
+ has_many :comments, :as => :commented, :dependent => :delete_all, :order => "created_on"
+ # fq
+ has_many :acts, :class_name => 'Activity', :as => :act, :dependent => :destroy
+ # 被ForgeActivity虚拟关联
+ has_many :forge_acts, :class_name => 'ForgeActivity',:as =>:forge_act ,:dependent => :destroy
+ # end
+
+ validates_presence_of :title, :description
+ validates_length_of :title, :maximum => 60
+ validates_length_of :summary, :maximum => 255
+ validates_length_of :description, :maximum => 10000
+
+ acts_as_attachable :delete_permission => :manage_news
+ acts_as_searchable :columns => ['title', 'summary', "#{table_name}.description"], :include => :project
+ acts_as_event :url => Proc.new {|o| {:controller => 'news', :action => 'show', :id => o.id}}
+ acts_as_activity_provider :find_options => {:include => [:project, :author]},
+ :author_key => :author_id
+ #added by nwb
+ #课程新闻独立于项目
+ acts_as_activity_provider :type => 'course_news',
+ :find_options => {:include => [:course, :author]},
+ :author_key => :author_id
+ acts_as_watchable
+
+ after_create :act_as_activity,:act_as_forge_activity,:add_author_as_watcher, :send_mail
+
+ after_destroy :delete_kindeditor_assets
+
+ scope :visible, lambda {|*args|
+ includes(:project).where(Project.allowed_to_condition(args.shift || User.current, :view_news, *args))
+ }
+
+ scope :course_visible, lambda {|*args|
+ includes(:course).where(Course.allowed_to_condition(args.shift || User.current, :view_course_news, *args))
+ }
+ safe_attributes 'title', 'summary', 'description'
+
+ def visible?(user=User.current)
+ !user.nil? && user.allowed_to?(:view_news, project)
+ end
+
+ # Returns true if the news can be commented by user
+ def commentable?(user=User.current)
+ user.allowed_to?(:comment_news, project)
+ end
+
+ def recipients
+ project.users.select {|user| user.notify_about?(self)}.map(&:mail)
+ end
+
+ # returns latest news for projects visible by user
+ def self.latest(user = User.current, count = 5)
+ visible(user).includes([:author, :project]).order("#{News.table_name}.created_on DESC").limit(count).all
+ end
+
+ # 新闻的短描述信息
+ def short_description(length = 255)
+ description.gsub(/<\/?.*?>/,"").html_safe if description
+ #description.gsub(/^(.{#{length}}[^\n\r]*).*$/m, '\1...').strip if description
+ #description
+ end
+
+ private
+
+ def add_author_as_watcher
+ Watcher.create(:watchable => self, :user => author)
+ end
+ ## fq
+ def act_as_activity
+ self.acts << Activity.new(:user_id => self.author_id)
+ end
+
+ # Time 2015-02-27 15:48:17
+ # Author lizanle
+ # Description 公用表中也要记录
+ def act_as_forge_activity
+ # 如果是project为空,那么是课程相关的,不需要保存
+ if !self.project.nil?
+ self.forge_acts << ForgeActivity.new(:user_id => self.author_id,
+ :project_id => self.project.id)
+ end
+ end
+
+ # Time 2015-03-31 13:50:54
+ # Author lizanle
+ # Description 删除news后删除对应的资源
+ def delete_kindeditor_assets
+ delete_kindeditor_assets_from_disk self.id,OwnerTypeHelper::NEWS
+ end
+
+ def send_mail
+ Mailer.run.news_added(self) if Setting.notified_events.include?('news_added')
+ end
+
+end
diff --git a/app/models/poll.rb b/app/models/poll.rb
index 943c08b51..64e9df79a 100644
--- a/app/models/poll.rb
+++ b/app/models/poll.rb
@@ -7,22 +7,24 @@ class Poll < ActiveRecord::Base
has_many :poll_users, :dependent => :destroy
has_many :users, :through => :poll_users #该文件被哪些用户提交答案过
# 添加课程的poll动态
-# has_many :acts, :class_name => 'Activity', :as => :act, :dependent => :destroy
-# after_create :act_as_activity
+ has_many :acts, :class_name => 'Activity', :as => :act, :dependent => :destroy
+ after_create :act_as_activity
-# acts_as_event :title => Proc.new {|o| "#{l(:label_my_message)} ##{o.id}: #{o.name}" },
-# :description => :description,
-# :author => :author,
-# :url => Proc.new {|o| {:controller => 'poll', :action => 'show', :id => o.id}}
+ acts_as_event :title => Proc.new {|o| "#{l(:label_course_poll)}: #{o.polls_name}" },
+ :description => :polls_description,
+ :datetime => :published_at,
+ :author => :user,
+ :url => Proc.new {|o| {:controller => 'poll', :action => 'show', :id => o.id}}
-# acts_as_activity_provider :type => 'polls',
-# :permission => :view_course_polls,
- #:find_options => {:include => [:course, :author]},
- #:timestamp => "#{self.table_name}.published_at",
-# :author_key => :author_id
+ acts_as_activity_provider :type => 'polls',
+ #:permission => :view_course_polls,
+ :find_options => {:select => "#{Poll.table_name}.*",
+ :joins => "LEFT JOIN #{Course.table_name} ON ( #{Poll.table_name}.polls_type='Course' AND #{Poll.table_name}.polls_status= 2 AND #{Poll.table_name}.polls_group_id = #{Course.table_name}.id )"},
+ :timestamp => "#{self.table_name}.published_at",
+ :author_key => :user_id
-# def act_as_activity
-# self.acts << Activity.new(:user_id => self.user_id)
-# end
+ def act_as_activity
+ self.acts << Activity.new(:user_id => self.user_id)
+ end
end
diff --git a/app/models/principal.rb b/app/models/principal.rb
index dfec5b911..0f0746f78 100644
--- a/app/models/principal.rb
+++ b/app/models/principal.rb
@@ -19,6 +19,7 @@ class Principal < ActiveRecord::Base
self.table_name = "#{table_name_prefix}users#{table_name_suffix}"
# Account statuses
+ # 0 全部;1 活动的; 2 已注册; 3 锁定
STATUS_ANONYMOUS = 0
STATUS_ACTIVE = 1
STATUS_REGISTERED = 2
diff --git a/app/models/project.rb b/app/models/project.rb
index 07854822e..f257058ea 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -51,7 +51,7 @@ class Project < ActiveRecord::Base
has_many :issue_categories, :dependent => :delete_all, :order => "#{IssueCategory.table_name}.name"
has_many :boards, :dependent => :destroy, :order => "position ASC"
has_one :repository, :conditions => ["is_default = ?", true]
- has_many :repositories, :dependent => :destroy
+ has_many :repositories, :dependent => :destroy, conditions: "hidden=false"
has_many :changesets, :through => :repository
#added by xianbo for delete biding_project
has_many :biding_projects, :dependent => :destroy
diff --git a/app/models/relative_memo.rb b/app/models/relative_memo.rb
index 181aa89f6..07767c7d6 100644
--- a/app/models/relative_memo.rb
+++ b/app/models/relative_memo.rb
@@ -1,199 +1,199 @@
-class RelativeMemo < ActiveRecord::Base
- # attr_accessible :title, :body
- include Redmine::SafeAttributes
- belongs_to :open_source_project, :class_name => "OpenSourceProject", :foreign_key => 'osp_id'
- belongs_to :author, :class_name => "User", :foreign_key => 'author_id'
-
- has_many :tags, :through => :project_tags, :class_name => 'Tag'
- has_many :project_tags, :class_name => 'ProjectTags'
-
- has_many :relation_topics, :class_name => 'RelativeMemoToOpenSourceProject'
-
- has_many :no_uses, :as => :no_use, :dependent => :delete_all
-
- has_many :bugs_to_osp, :class_name => 'BugToOsp', :foreign_key => 'relative_memo_id', :dependent => :destroy
-
-
- acts_as_taggable
-
- validates_presence_of :subject
- #validates :content, presence: true
- # validates_length_of :subject, maximum: 50
- #validates_length_of :content, maximum: 3072
- validate :cannot_reply_to_locked_topic, :on => :create
- validates_uniqueness_of :osp_id, :scope => [:subject, :content]
-
- acts_as_tree :counter_cache => :replies_count, :order => "#{RelativeMemo.table_name}.created_at ASC"
- acts_as_attachable
- belongs_to :last_reply, :class_name => 'RelativeMemo', :foreign_key => 'last_reply_id'
- # acts_as_searchable :column => ['subject', 'content'],
- # #:include => { :forum => :p}
- # #:project_key => "#{Forum.table_name}.project_id"
- # :date_column => "#{table_name}.created_at"
-
- # acts_as_event :title => Proc.new {|o| "#{o.forum.name}: #{o.subject}"},
- # :datetime => :updated_at,
- # # :datetime => :created_at,
- # :description => :content,
- # :author => :author,
- # :type => Proc.new {|o| o.parent_id.nil? ? 'Memo' : 'Reply'},
- # :url => Proc.new {|o| {:controller => 'memos', :action => 'show', :forum_id => o.forum_id}.merge(o.parent_id.nil? ? {:id => o.id} : {:id => o.parent_id, :r => o.id, :anchor => "reply-#{o.id}"})}
- # acts_as_activity_provider :author_key => :author_id,
- # :func => 'memos',
- # :timestamp => 'created_at'
-
- # :find_options => {:type => 'memos'}
- # acts_as_watchable
-
- safe_attributes "author_id",
- "subject",
- "content",
- "osp_id",
- "last_memo_id",
- "lock",
- "sticky",
- "parent_id",
- "replies_count",
- "is_quote"
-
- after_create :add_author_as_watcher, :reset_counters!
- # after_update :update_memos_forum
- after_destroy :reset_counters!
- # after_create :send_notification
- # after_save :plusParentAndForum
- # after_destroy :minusParentAndForum
-
- # scope :visible, lambda { |*args|
- # includes(:forum => ).where()
- # }
-
- def cannot_reply_to_locked_topic
- errors.add :base, l(:label_memo_locked) if root.locked? && self != root
- end
-
- def short_content(length = 25)
- str = "^(.{,#{length}})[^\n\r]*.*$"
- content.gsub(Regexp.new(str), '\1...').strip if content
- end
-
- # def update_memos_forum
- # if forum_id_changed?
- # Message.update_all({:board_id => board_id}, ["id = ? OR parent_id = ?", root.id, root.id ])
- # Forum.reset_counters!(forum_id_was)
- # Forum.reset_counters!(forum_id)
- # end
- # end
-
-
- scope :no_use_for, lambda { |user_id|
- { :include => :no_uses,
- :conditions => ["#{NoUse.table_name}.user_id = ?", user_id] }
- }
-
- # 获取帖子的回复
- def replies
- memos = RelativeMemo.where("parent_id = ?", id)
- end
-
- def no_use_for?(user)
- self.no_uses.each do |no_use|
- if no_use.user_id == user.id
- return true
- end
- end
- false
- end
-
- def set_no_use(user, flag=true)
- flag ? set_filter(user) : remove_filter(user)
- end
-
- def set_filter(user)
- self.no_uses << NoUse.new(:user => user)
- end
-
- def remove_filter(user)
- return nil unless user && user.is_a?(User)
- NoUse.delete_all "no_use_type = '#{self.class}' AND no_use_id = #{self.id} AND user_id = #{user.id}"
- end
-
- def reset_counters!
- if parent && parent.id
- RelativeMemo.update_all({:last_reply_id => parent.children.maximum(:id)}, {:id => parent.id})
- parent.update_attribute(:updated_at, Time.now)
- end
- # forum.reset_counters!
- end
-
- def sticky?
- sticky == 1
- end
-
- def replies
- RelativeMemo.where("parent_id = ?", id)
- end
-
- def locked?
- self.lock
- end
-
- def editable_by? user
- # user && user.logged? || (self.author == usr && usr.allowed_to?(:edit_own_messages, project))
- user.admin?
- end
-
- # def destroyable_by? user
- # (user && user.logged? && (Forum.find(self.forum_id).creator_id == user.id) ) || user.admin?
- # #self.author == user || user.admin?
- # end
-
- def deleted_attach_able_by? user
- (user && user.logged? && (self.author == user) ) || user.admin?
- end
-
- private
-
- def add_author_as_watcher
- Watcher.create(:watchable => self.root, :user => author)
- end
-
- def send_notification
- if Setting.notified_events.include?('message_posted')
- Mailer.run.message_posted(self)
- end
- end
-
- # def plusParentAndForum
- # @forum = Forum.find(self.forum_id)
- # @forum.memo_count = @forum.memo_count.to_int + 1
- # @forum.last_memo_id = self.id
- # if self.parent_id
- # @parent_memo = Memo.find_by_id(self.parent_id)
- # @parent_memo.last_reply_id = self
- # @parent_memo.replies_count = @parent_memo.replies_count.to_int + 1
- # @parent_memo.save
- # else
- # @forum.topic_count = @forum.topic_count.to_int + 1
- # end
- # @forum.save
- # end
-
- # def minusParentAndForum
- # @forum = Forum.find(self.forum_id)
- # @forum.memo_count = @forum.memo_count.to_int - 1
- # @forum.memo_count = 0 if @forum.memo_count.to_int < 0
- # # @forum.last_memo_id = Memo.reorder('created_at ASC').find_all_by_forum_id(self.forum_id).last.id
- # if self.parent_id
- # @parent_memo = Memo.find_by_id(self.parent_id)
- # # @parent_memo.last_reply_id = Memo.reorder('created_at ASC').find_all_by_parent_id(self.parent_id).last.id
- # @parent_memo.replies_count = @parent_memo.replies_count.to_int - 1
- # @parent_memo.replies_count = 0 if @parent_memo.replies_count.to_int < 0
- # @parent_memo.save
- # else
- # @forum.topic_count = @forum.topic_count.to_int - 1
- # @forum.topic_count = 0 if @forum.topic_count.to_int < 0
- # end
- # @forum.save
- # end
-end
-
+class RelativeMemo < ActiveRecord::Base
+ # attr_accessible :title, :body
+ include Redmine::SafeAttributes
+ belongs_to :open_source_project, :class_name => "OpenSourceProject", :foreign_key => 'osp_id'
+ belongs_to :author, :class_name => "User", :foreign_key => 'author_id'
+
+ has_many :tags, :through => :project_tags, :class_name => 'Tag'
+ has_many :project_tags, :class_name => 'ProjectTags'
+
+ has_many :relation_topics, :class_name => 'RelativeMemoToOpenSourceProject'
+
+ has_many :no_uses, :as => :no_use, :dependent => :delete_all
+
+ has_many :bugs_to_osp, :class_name => 'BugToOsp', :foreign_key => 'relative_memo_id', :dependent => :destroy
+
+
+ acts_as_taggable
+
+ validates_presence_of :subject
+ #validates :content, presence: true
+ # validates_length_of :subject, maximum: 50
+ #validates_length_of :content, maximum: 3072
+ validate :cannot_reply_to_locked_topic, :on => :create
+ validates_uniqueness_of :osp_id, :scope => [:subject, :content]
+
+ acts_as_tree :counter_cache => :replies_count, :order => "#{RelativeMemo.table_name}.created_at ASC"
+ acts_as_attachable
+ belongs_to :last_reply, :class_name => 'RelativeMemo', :foreign_key => 'last_reply_id'
+ # acts_as_searchable :column => ['subject', 'content'],
+ # #:include => { :forum => :p}
+ # #:project_key => "#{Forum.table_name}.project_id"
+ # :date_column => "#{table_name}.created_at"
+
+ # acts_as_event :title => Proc.new {|o| "#{o.forum.name}: #{o.subject}"},
+ # :datetime => :updated_at,
+ # # :datetime => :created_at,
+ # :description => :content,
+ # :author => :author,
+ # :type => Proc.new {|o| o.parent_id.nil? ? 'Memo' : 'Reply'},
+ # :url => Proc.new {|o| {:controller => 'memos', :action => 'show', :forum_id => o.forum_id}.merge(o.parent_id.nil? ? {:id => o.id} : {:id => o.parent_id, :r => o.id, :anchor => "reply-#{o.id}"})}
+ # acts_as_activity_provider :author_key => :author_id,
+ # :func => 'memos',
+ # :timestamp => 'created_at'
+
+ # :find_options => {:type => 'memos'}
+ # acts_as_watchable
+
+ safe_attributes "author_id",
+ "subject",
+ "content",
+ "osp_id",
+ "last_memo_id",
+ "lock",
+ "sticky",
+ "parent_id",
+ "replies_count",
+ "is_quote"
+
+ after_create :add_author_as_watcher, :reset_counters!
+ # after_update :update_memos_forum
+ after_destroy :reset_counters!
+ # after_create :send_notification
+ # after_save :plusParentAndForum
+ # after_destroy :minusParentAndForum
+
+ # scope :visible, lambda { |*args|
+ # includes(:forum => ).where()
+ # }
+
+ def cannot_reply_to_locked_topic
+ errors.add :base, l(:label_memo_locked) if root.locked? && self != root
+ end
+
+ def short_content(length = 25)
+ str = "^(.{,#{length}})[^\n\r]*.*$"
+ content.gsub(Regexp.new(str), '\1...').strip if content
+ end
+
+ # def update_memos_forum
+ # if forum_id_changed?
+ # Message.update_all({:board_id => board_id}, ["id = ? OR parent_id = ?", root.id, root.id ])
+ # Forum.reset_counters!(forum_id_was)
+ # Forum.reset_counters!(forum_id)
+ # end
+ # end
+
+
+ scope :no_use_for, lambda { |user_id|
+ { :include => :no_uses,
+ :conditions => ["#{NoUse.table_name}.user_id = ?", user_id] }
+ }
+
+ # 获取帖子的回复
+ def replies
+ memos = RelativeMemo.where("parent_id = ?", id)
+ end
+
+ def no_use_for?(user)
+ self.no_uses.each do |no_use|
+ if no_use.user_id == user.id
+ return true
+ end
+ end
+ false
+ end
+
+ def set_no_use(user, flag=true)
+ flag ? set_filter(user) : remove_filter(user)
+ end
+
+ def set_filter(user)
+ self.no_uses << NoUse.new(:user => user)
+ end
+
+ def remove_filter(user)
+ return nil unless user && user.is_a?(User)
+ NoUse.delete_all "no_use_type = '#{self.class}' AND no_use_id = #{self.id} AND user_id = #{user.id}"
+ end
+
+ def reset_counters!
+ if parent && parent.id
+ RelativeMemo.update_all({:last_reply_id => parent.children.maximum(:id)}, {:id => parent.id})
+ parent.update_attribute(:updated_at, Time.now)
+ end
+ # forum.reset_counters!
+ end
+
+ def sticky?
+ sticky == 1
+ end
+
+ def replies
+ RelativeMemo.where("parent_id = ?", id)
+ end
+
+ def locked?
+ self.lock
+ end
+
+ def editable_by? user
+ # user && user.logged? || (self.author == usr && usr.allowed_to?(:edit_own_messages, project))
+ user.admin?
+ end
+
+ # def destroyable_by? user
+ # (user && user.logged? && (Forum.find(self.forum_id).creator_id == user.id) ) || user.admin?
+ # #self.author == user || user.admin?
+ # end
+
+ def deleted_attach_able_by? user
+ (user && user.logged? && (self.author == user) ) || user.admin?
+ end
+
+ private
+
+ def add_author_as_watcher
+ Watcher.create(:watchable => self.root, :user => author)
+ end
+
+ def send_notification
+ if Setting.notified_events.include?('message_posted')
+ Mailer.run.message_posted(self)
+ end
+ end
+
+ # def plusParentAndForum
+ # @forum = Forum.find(self.forum_id)
+ # @forum.memo_count = @forum.memo_count.to_int + 1
+ # @forum.last_memo_id = self.id
+ # if self.parent_id
+ # @parent_memo = Memo.find_by_id(self.parent_id)
+ # @parent_memo.last_reply_id = self
+ # @parent_memo.replies_count = @parent_memo.replies_count.to_int + 1
+ # @parent_memo.save
+ # else
+ # @forum.topic_count = @forum.topic_count.to_int + 1
+ # end
+ # @forum.save
+ # end
+
+ # def minusParentAndForum
+ # @forum = Forum.find(self.forum_id)
+ # @forum.memo_count = @forum.memo_count.to_int - 1
+ # @forum.memo_count = 0 if @forum.memo_count.to_int < 0
+ # # @forum.last_memo_id = Memo.reorder('created_at ASC').find_all_by_forum_id(self.forum_id).last.id
+ # if self.parent_id
+ # @parent_memo = Memo.find_by_id(self.parent_id)
+ # # @parent_memo.last_reply_id = Memo.reorder('created_at ASC').find_all_by_parent_id(self.parent_id).last.id
+ # @parent_memo.replies_count = @parent_memo.replies_count.to_int - 1
+ # @parent_memo.replies_count = 0 if @parent_memo.replies_count.to_int < 0
+ # @parent_memo.save
+ # else
+ # @forum.topic_count = @forum.topic_count.to_int - 1
+ # @forum.topic_count = 0 if @forum.topic_count.to_int < 0
+ # end
+ # @forum.save
+ # end
+end
+
diff --git a/app/models/token.rb b/app/models/token.rb
index 3131bce8d..c89ff30bc 100644
--- a/app/models/token.rb
+++ b/app/models/token.rb
@@ -27,6 +27,14 @@ class Token < ActiveRecord::Base
self.value = Token.generate_token_value
end
+ def self.get_token_from_user(user, action)
+ token = Token.where(:action => action, :user_id => user).first
+ unless token
+ token = Token.create(user: user, action: action)
+ end
+ token
+ end
+
# Return true if token has expired
def expired?
return Time.now > self.created_on + @@validity_time
diff --git a/app/models/wiki_content_observer.rb b/app/models/wiki_content_observer.rb
index 6e13d1a8a..3ded4da86 100644
--- a/app/models/wiki_content_observer.rb
+++ b/app/models/wiki_content_observer.rb
@@ -1,28 +1,28 @@
-# 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 WikiContentObserver < ActiveRecord::Observer
- def after_create(wiki_content)
- Mailer.run.wiki_content_added(wiki_content) if Setting.notified_events.include?('wiki_content_added')
- end
-
- def after_update(wiki_content)
- if wiki_content.text_changed?
- Mailer.run.wiki_content_updated(wiki_content) if Setting.notified_events.include?('wiki_content_updated')
- 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 WikiContentObserver < ActiveRecord::Observer
+ def after_create(wiki_content)
+ Mailer.run.wiki_content_added(wiki_content) if Setting.notified_events.include?('wiki_content_added')
+ end
+
+ def after_update(wiki_content)
+ if wiki_content.text_changed?
+ Mailer.run.wiki_content_updated(wiki_content) if Setting.notified_events.include?('wiki_content_updated')
+ end
+ end
+end
diff --git a/app/models/zip_pack.rb b/app/models/zip_pack.rb
index e2d03f363..df6ad593f 100644
--- a/app/models/zip_pack.rb
+++ b/app/models/zip_pack.rb
@@ -1,18 +1,18 @@
-class ZipPack < ActiveRecord::Base
- # attr_accessible :title, :body
-
- def self.packed?(bid_id, user_id, digests)
- zip_pack = ZipPack.where(homework_id: bid_id, user_id: user_id).first
- return false unless zip_pack && zip_pack.digests == digests
- zip_pack
- end
-
- def file_valid?
- return false unless File.exist?(self.file_path)
- Trustie::Utils.digest(self.file_path) == self.file_digest
- end
-
- def digests
- self.file_digests.split(',').sort
- end
-end
+class ZipPack < ActiveRecord::Base
+ # attr_accessible :title, :body
+
+ def self.packed?(bid_id, user_id, digests)
+ zip_pack = ZipPack.where(homework_id: bid_id, user_id: user_id).first
+ return false unless zip_pack && zip_pack.digests == digests
+ zip_pack
+ end
+
+ def file_valid?
+ return false unless File.exist?(self.file_path)
+ Trustie::Utils.digest(self.file_path) == self.file_digest
+ end
+
+ def digests
+ self.file_digests.split(',').sort
+ end
+end
diff --git a/app/services/courses_service.rb b/app/services/courses_service.rb
index e91883bee..22249b953 100644
--- a/app/services/courses_service.rb
+++ b/app/services/courses_service.rb
@@ -86,7 +86,7 @@ class CoursesService
gender = m.user.user_extensions.gender.nil? ? 0 : m.user.user_extensions.gender
work_unit = get_user_work_unit m.user
location = get_user_location m.user
- users << {:id => m.user.id, :img_url => img_url, :nickname => m.user.login, :gender => gender, :work_unit => work_unit, :mail => m.user.mail, :location => location, :brief_introduction => m.user.user_extensions.brief_introduction}
+ users << {:id => m.user.id, :img_url => img_url, :nickname => m.user.login, :gender => gender, :work_unit => work_unit, :mail => m.user.mail, :location => location, :brief_introduction => m.user.user_extensions.brief_introduction,:realname=>m.user.realname}
end
users
end
@@ -169,7 +169,7 @@ class CoursesService
unless (course.is_public == 1 || current_user.member_of_course?(course) || current_user.admin?)
raise '403'
end
- {:course => course,:work_unit => work_unit, :img_url => url_to_avatar(course),:current_user_is_member => current_user.member_of_course?(course),:current_user_is_teacher => is_course_teacher(current_user,course)}
+ {:course => course,:work_unit => work_unit, :img_url => url_to_avatar(course),:current_user_is_member => current_user.member_of_course?(course),:current_user_is_teacher => is_course_teacher(current_user,course),:course_student_num => course ? course.student.count.to_s : 0}
end
#创建课程
@@ -428,7 +428,53 @@ class CoursesService
result
end
+ # 课程课件
+ def course_attachments params
+ result = []
+ @course = Course.find(params[:course_id])
+ @attachments = @course.attachments.order("created_on desc")
+ if !params[:name].nil? && params[:name] != ""
+ @attachments.each do |atta|
+ result << {:filename => atta.filename,
+ :description => atta.description,
+ :downloads => atta.downloads,
+ :quotes => atta.quotes.nil? ? 0 :atta.quotes } if atta.filename.include?(params[:name])
+
+ end
+ else
+ @attachments.each do |atta|
+ result << {:filename => atta.filename,
+ :description => atta.description,
+ :downloads => atta.downloads,
+ :quotes => atta.quotes.nil? ? 0 :atta.quotes }
+
+ end
+ end
+ result
+ end
+
+ # 课程学生列表
+ def course_members params
+ @all_members = searchmember_by_name(student_homework_score(0,params[:course_id], 10,"desc"),params[:name])
+ end
+
private
+ def searchmember_by_name members, name
+ #searchPeopleByRoles(project, StudentRoles)
+ mems = []
+ if name != ""
+ name = name.to_s.downcase
+ members.each do |m|
+ username = m.user[:lastname].to_s.downcase + m.user[:firstname].to_s.downcase
+ if(m.user[:login].to_s.downcase.include?(name) || m.user.user_extensions[:student_id].to_s.downcase.include?(name) || username.include?(name))
+ mems << m
+ end
+ end
+ else
+ mems = members
+ end
+ mems
+ end
def show_homework_info course,bid,current_user,is_course_teacher
author_real_name = bid.author.lastname + bid.author.firstname
many_times = course.homeworks.index(bid) + 1
@@ -465,5 +511,52 @@ class CoursesService
end
+ def student_homework_score(groupid,course_id, nums, score_sort_by)
+ #teachers = find_course_teachers(@course)
+ #start_from = start_from * nums
+ sql_select = ""
+ if groupid == 0
+ if nums == 0
+ sql_select = "SELECT members.*, SUM(homework_attaches.score) as score FROM members, homework_attaches
+ WHERE members.course_id = #{course_id} AND members.user_id in (SELECT students_for_courses.student_id FROM students_for_courses WHERE course_id = #{course_id}) AND members.user_id = homework_attaches.user_id
+ AND homework_attaches.bid_id in (SELECT bid_id FROM homework_for_courses WHERE course_id = #{course_id}) GROUP BY members.user_id
+ UNION all
+ SELECT members.*, 0 as score FROM members,homework_attaches,students_for_courses WHERE members.course_id = #{course_id} AND
+ students_for_courses.course_id = #{course_id} and members.user_id = students_for_courses.student_id AND
+ members.user_id NOT IN (SELECT homework_attaches.user_id FROM homework_attaches WHERE homework_attaches.bid_id in (SELECT bid_id FROM homework_for_courses WHERE course_id = #{course_id} )
+ )
+ GROUP BY members.user_id ORDER BY score #{score_sort_by}"
+ else
+ sql_select = "SELECT members.*, SUM(homework_attaches.score) as score FROM members, homework_attaches
+ WHERE members.course_id = #{course_id} AND members.user_id in (SELECT students_for_courses.student_id FROM students_for_courses WHERE course_id = #{course_id}) AND members.user_id = homework_attaches.user_id
+ AND homework_attaches.bid_id in (SELECT bid_id FROM homework_for_courses WHERE course_id = #{course_id}) GROUP BY members.user_id
+ UNION all
+ SELECT members.*, 0 as score FROM members,homework_attaches,students_for_courses WHERE members.course_id = #{course_id} AND
+ students_for_courses.course_id = #{course_id} and members.user_id = students_for_courses.student_id AND
+ members.user_id NOT IN (SELECT homework_attaches.user_id FROM homework_attaches WHERE homework_attaches.bid_id in (SELECT bid_id FROM homework_for_courses WHERE course_id = #{course_id} )
+ )
+ GROUP BY members.user_id ORDER BY score #{score_sort_by} " #limit #{start_from}, #{nums}"
+
+ end
+ else
+ sql_select = "SELECT members.*, SUM(homework_attaches.score) as score FROM members, homework_attaches
+ WHERE members.course_id = #{course_id} AND members.user_id in (SELECT students_for_courses.student_id FROM students_for_courses WHERE course_id = #{course_id}) AND members.user_id = homework_attaches.user_id
+ and members.course_group_id = #{groupid} AND homework_attaches.bid_id in (SELECT bid_id FROM homework_for_courses WHERE course_id = #{course_id})
+ GROUP BY members.user_id
+ UNION all
+ SELECT members.*, 0 as score FROM members,homework_attaches,students_for_courses WHERE members.course_id = #{course_id}
+ and members.course_group_id = #{groupid} AND
+ students_for_courses.course_id = #{course_id} and members.user_id = students_for_courses.student_id AND
+ members.user_id NOT IN (SELECT homework_attaches.user_id FROM homework_attaches WHERE homework_attaches.bid_id in (SELECT bid_id FROM homework_for_courses WHERE course_id = #{course_id} )
+ )
+ GROUP BY members.user_id ORDER BY score #{score_sort_by}"
+ end
+ sql = ActiveRecord::Base.connection()
+ homework_scores = Member.find_by_sql(sql_select)
+ sql.close()
+
+ homework_scores
+ end
+
end
\ No newline at end of file
diff --git a/app/services/users_service.rb b/app/services/users_service.rb
index c1f716fd1..3a92bf8f1 100644
--- a/app/services/users_service.rb
+++ b/app/services/users_service.rb
@@ -44,12 +44,14 @@ class UsersService
#location = get_user_location @user
#{:id => @user.id, :img_url => img_url, :nickname => @user.login, :gender => gender, :work_unit => work_unit, :mail => @user.mail, :location => location, :brief_introduction => @user.user_extensions.brief_introduction}
end
+
+ # 自动注册功能 FOR:邮件邀请
def register_auto(login,mail,password)
@user = User.new
@user.admin = false
@user.register
@user.login = login
- @user.mail =mail
+ @user.mail = mail
password_confirmation = password
should_confirmation_password = true
if !password.blank? && !password_confirmation.blank? && should_confirmation_password
@@ -59,9 +61,7 @@ class UsersService
else
@user.password = ""
end
-
@user = automatically_register(@user)
-
if @user.id != nil
ue = @user.user_extensions ||= UserExtensions.new
ue.user_id = @user.id
@@ -69,6 +69,7 @@ class UsersService
end
@user
end
+
#显示用户
#id用户id
def show_user(params)
diff --git a/app/tasks/destroy_repository_task.rb b/app/tasks/destroy_repository_task.rb
new file mode 100644
index 000000000..3e434422e
--- /dev/null
+++ b/app/tasks/destroy_repository_task.rb
@@ -0,0 +1,25 @@
+#coding=utf-8
+#
+
+class DestroyRepositoryTask
+ def destroy(user_id, rep_id)
+ user = User.find(user_id)
+ repository = Repository.find(rep_id)
+
+ Rails.logger.info "start delete repository #{user} #{repository}"
+ @root_path=RepositoriesHelper::ROOT_PATH
+ @repo_name=user.login.to_s+"_"+repository.identifier.to_s
+ @repository_name=user.login.to_s+"/"+repository.identifier.to_s+".git"
+ @middle=user.login.to_s+"_"+repository.identifier.to_s+"-write:"
+ repository.destroy
+ if(repository.type=="Repository::Git")
+ Rails.logger.info "destory the repository value"+"root path"+@root_path+"repo_name"+@repo_name+
+ "repository_name"+@repository_name+"user group"+@middle
+ system "sed -i /"+@repo_name+"/{d} "+@root_path+"htdocs/user.passwd"
+ system "sed -i /"+@middle+"/{d} "+@root_path+"htdocs/group.passwd"
+ system "rm -r "+@root_path+"htdocs/"+@repository_name
+ end
+ end
+
+ handle_asynchronously :destroy,:queue => 'repository'
+end
diff --git a/app/views/account/login.html.erb b/app/views/account/login.html.erb
index 4175282b3..bb289eb03 100644
--- a/app/views/account/login.html.erb
+++ b/app/views/account/login.html.erb
@@ -68,7 +68,7 @@
<% if Setting.autologin? %>
- <%= check_box_tag 'autologin', 1, false, :tabindex => 4 %>
+ <%= check_box_tag 'autologin', 1, true, :tabindex => 4 %>
<%= l(:label_stay_logged_in) %>
<% end %>
diff --git a/app/views/attachments/_form.html.erb b/app/views/attachments/_form.html.erb
index 18586e809..2e8800617 100644
--- a/app/views/attachments/_form.html.erb
+++ b/app/views/attachments/_form.html.erb
@@ -1,11 +1,12 @@
+
<% if defined?(container) && container && container.saved_attachments %>
<% container.attachments.each_with_index do |attachment, i| %>
- <%= text_field_tag("attachments[p#{i}][filename]", attachment.filename, :class => 'filename readonly', :readonly=>'readonly')%>
- <%= text_field_tag("attachments[p#{i}][description]", attachment.description, :maxlength => 254, :placeholder => l(:label_optional_description), :class => 'description', :style=>"display: inline-block;") %>
- <%= l(:field_is_public)%>:
- <%= check_box_tag("attachments[p#{i}][is_public_checkbox]", attachment.is_public,attachment.is_public == 1 ? true : false,:class => 'is_public')%>
+ <%= text_field_tag("attachments[p#{i}][filename]", attachment.filename, :class => 'filename readonly', :readonly => 'readonly') %>
+ <%= text_field_tag("attachments[p#{i}][description]", attachment.description, :maxlength => 254, :placeholder => l(:label_optional_description), :class => 'description', :style => "display: inline-block;") %>
+ <%= l(:field_is_public) %>:
+ <%= check_box_tag("attachments[p#{i}][is_public_checkbox]", attachment.is_public, attachment.is_public == 1 ? true : false, :class => 'is_public') %>
<%= if attachment.id.nil?
#待补充代码
else
@@ -17,48 +18,56 @@
<%= hidden_field_tag "attachments[p#{i}][token]", "#{attachment.token}" %>
<% end %>
+ <% container.saved_attachments.each_with_index do |attachment, i| %>
+
+ <%= text_field_tag("attachments[p#{i}][filename]", attachment.filename, :class => 'filename readonly', :readonly => 'readonly') %>
+ <%= text_field_tag("attachments[p#{i}][description]", attachment.description, :maxlength => 254, :placeholder => l(:label_optional_description), :class => 'description', :style => "display: inline-block;") %>
+ <%= l(:field_is_public) %>:
+ <%= check_box_tag("attachments[p#{i}][is_public_checkbox]", attachment.is_public, attachment.is_public == 1 ? true : false, :class => 'is_public') %>
+ <%= if attachment.id.nil?
+ #待补充代码
+ else
+ link_to(' '.html_safe, attachment_path(attachment, :attachment_id => "p#{i}", :format => 'js'), :method => 'delete', :remote => true, :class => 'remove-upload')
+ end
+ %>
+ <%#= render :partial => 'tags/tag', :locals => {:obj => attachment, :object_flag => "6"} %>
+ <%= hidden_field_tag "attachments[p#{i}][token]", "#{attachment.token}" %>
+
+ <% end %>
<% end %>
-
-<% project = project %>
-
+ <% project = project %>
+
<%#= button_tag "浏览", :type=>"button", :onclick=>"CompatibleSend();" %>
- <%= button_tag l(:button_browse), :type=>"button", :onclick=>"_file.click()",:onmouseover => 'this.focus()', :style => ie8? ? 'display:none' : '' %>
+ <%= button_tag "文件浏览", :type=>"button", :onclick=>"$('#_file').click();",:onmouseover => 'this.focus()',:class => 'sub_btn' %>
<%= file_field_tag 'attachments[dummy][file]',
- :id => '_file',
- :class => 'file_selector',
- :multiple => true,
- :onchange => 'addInputFiles(this);',
- :style => ie8? ? '' : 'display:none',
- :data => {
- :max_file_size => Setting.attachment_max_size.to_i.kilobytes,
- :max_file_size_message => l(:error_attachment_too_big, :max_size => number_to_human_size(Setting.attachment_max_size.to_i.kilobytes)),
- :max_concurrent_uploads => Redmine::Configuration['max_concurrent_ajax_uploads'].to_i,
- :upload_path => uploads_path(:format => 'js',:project =>project),
- :description_placeholder => l(:label_optional_description),
- :field_is_public => l(:field_is_public),
- :are_you_sure => l(:text_are_you_sure),
- :file_count => l(:label_file_count),
- :delete_all_files => l(:text_are_you_sure_all)
- } %>
+ :id => '_file',
+ :class => 'file_selector',
+ :multiple => true,
+ :onchange => 'addInputFiles(this);',
+ :style => ie8? ? '' : 'display:none',
+ :data => {
+ :max_file_size => Setting.attachment_max_size.to_i.kilobytes,
+ :max_file_size_message => l(:error_attachment_too_big, :max_size => number_to_human_size(Setting.attachment_max_size.to_i.kilobytes)),
+ :max_concurrent_uploads => Redmine::Configuration['max_concurrent_ajax_uploads'].to_i,
+ :upload_path => uploads_path(:format => 'js', :project => project),
+ :description_placeholder => l(:label_optional_description),
+ :field_is_public => l(:field_is_public),
+ :are_you_sure => l(:text_are_you_sure),
+ :file_count => l(:label_file_count),
+ :delete_all_files => l(:text_are_you_sure_all)
+ } %>
- <%= l(:label_no_file_uploaded)%>
+ <%= l(:label_no_file_uploaded) %>
(<%= l(:label_max_size) %>:
<%= number_to_human_size(Setting.attachment_max_size.to_i.kilobytes) %>)
-<% content_for :header_tags do %>
- <%= javascript_include_tag 'attachments' %>
-<% end %>
-
+ <% content_for :header_tags do %>
+ <%= javascript_include_tag 'attachments' %>
+ <% end %>
+
diff --git a/app/views/attachments/_form_project.html.erb b/app/views/attachments/_form_project.html.erb
new file mode 100644
index 000000000..9778d3242
--- /dev/null
+++ b/app/views/attachments/_form_project.html.erb
@@ -0,0 +1,67 @@
+
+<% if defined?(container) && container && container.saved_attachments %>
+ <% if isReply %>
+ <% container.saved_attachments.each_with_index do |attachment, i| %>
+
+ <%= text_field_tag("attachments[p#{i}][filename]", attachment.filename, :class => 'filename readonly', :readonly=>'readonly')%>
+ <%= text_field_tag("attachments[p#{i}][description]", attachment.description, :maxlength => 255, :placeholder => l(:label_optional_description), :class => 'description', :style=>"display: inline-block;") +
+ link_to(' '.html_safe, attachment_path(attachment, :attachment_id => "p#{i}", :format => 'js'), :method => 'delete', :remote => true, :class => 'remove-upload') %>
+ <%#= render :partial => 'tags/tag', :locals => {:obj => attachment, :object_flag => "6"} %>
+ <%= l(:field_is_public)%>:
+ <%= check_box_tag("attachments[p#{i}][is_public_checkbox]", attachment.is_public,attachment.is_public == 1 ? true : false, :class => 'is_public')%>
+ <%= hidden_field_tag "attachments[p#{i}][token]", "#{attachment.token}" %>
+
+ <% end %>
+ <% else %>
+ <% container.attachments.each_with_index do |attachment, i| %>
+
+ <%= text_field_tag("attachments[p#{i}][filename]", attachment.filename, :class => 'filename readonly', :readonly=>'readonly')%>
+ <%= text_field_tag("attachments[p#{i}][description]", attachment.description, :maxlength => 255, :placeholder => l(:label_optional_description), :class => 'description', :style=>"display: inline-block;") +
+ link_to(' '.html_safe, attachment_path(attachment, :attachment_id => "p#{i}", :format => 'js'), :method => 'delete', :remote => true, :class => 'remove-upload') %>
+ <%#= render :partial => 'tags/tag', :locals => {:obj => attachment, :object_flag => "6"} %>
+ <%= l(:field_is_public)%>:
+ <%= check_box_tag("attachments[p#{i}][is_public_checkbox]", attachment.is_public,attachment.is_public == 1 ? true : false, :class => 'is_public')%>
+ <%= hidden_field_tag "attachments[p#{i}][token]", "#{attachment.token}" %>
+
+ <% end %>
+ <% end %>
+<% end %>
+
+
+
+<%#= button_tag "浏览", :type=>"button", :onclick=>"CompatibleSend();" %>
+
+ <%= button_tag "文件浏览", :type=>"button", :onclick=>"_file.click()", :class =>"sub_btn",:style => ie8? ? 'display:none' : '' %>
+ <%= file_field_tag 'attachments[dummy][file]',
+ :id => '_file',
+ :class => 'file_selector',
+ :multiple => true,
+ :onchange => 'addInputFiles(this);',
+ :style => 'display:none',
+ :data => {
+ :max_file_size => Setting.attachment_max_size.to_i.kilobytes,
+ :max_file_size_message => l(:error_attachment_too_big, :max_size => number_to_human_size(Setting.attachment_max_size.to_i.kilobytes)),
+ :max_concurrent_uploads => Redmine::Configuration['max_concurrent_ajax_uploads'].to_i,
+ :upload_path => uploads_path(:format => 'js'),
+ :description_placeholder => l(:label_optional_description),
+ :field_is_public => l(:field_is_public),
+ :are_you_sure => l(:text_are_you_sure),
+ :file_count => l(:label_file_count),
+ :delete_all_files => l(:text_are_you_sure_all)
+ } %>
+ <%= l(:label_no_file_uploaded)%>
+(<%= l(:label_max_size) %>: <%= number_to_human_size(Setting.attachment_max_size.to_i.kilobytes) %>)
+
+
+<% content_for :header_tags do %>
+ <%= javascript_include_tag 'attachments' %>
+<% end %>
+
+
diff --git a/app/views/attachments/_homework_jour_link.html.erb b/app/views/attachments/_homework_jour_link.html.erb
new file mode 100644
index 000000000..e0efa211c
--- /dev/null
+++ b/app/views/attachments/_homework_jour_link.html.erb
@@ -0,0 +1,18 @@
+
+ <% for attachment in attachments %>
+
+ <%= link_to_short_attachment attachment, :class => 'link_file', :download => true, :length => 100 -%>
+
+ <% if attachment.is_text? %>
+
+ <%= link_to image_tag('magnifier.png'),
+ {:controller => 'attachments',
+ :action => 'show',
+ :id => attachment,
+ :filename => attachment.filename},
+ :target => "_blank"%>
+
+ <% end %>
+
+ <% end %>
+
diff --git a/app/views/attachments/_links.html.erb b/app/views/attachments/_links.html.erb
index 02c7ba4dc..c3ec2b9f0 100644
--- a/app/views/attachments/_links.html.erb
+++ b/app/views/attachments/_links.html.erb
@@ -60,7 +60,7 @@
<% if defined?(thumbnails) && thumbnails %>
<% images = attachments.select(&:thumbnailable?) %>
<% if images.any? %>
-
+
<% images.each do |attachment| %>
<%= thumbnail_tag(attachment) %>
<% end %>
diff --git a/app/views/attachments/_project_file_links.html.erb b/app/views/attachments/_project_file_links.html.erb
new file mode 100644
index 000000000..a18d819da
--- /dev/null
+++ b/app/views/attachments/_project_file_links.html.erb
@@ -0,0 +1,99 @@
+
+
+
+ <% is_float ||= false %>
+ <% for attachment in attachments %>
+
+ <%if is_float%>
+
+ <% end%>
+
+ <% if options[:length] %>
+ <%= link_to_short_attachment attachment, :class => ' link_file_board', :download => true,:length => options[:length] -%>
+ <% else %>
+ <%= link_to_short_attachment attachment, :class => ' link_file_board', :download => true -%>
+ <% end %>
+
+ <%if is_float%>
+
+ <% end%>
+
+ <% if attachment.is_text? %>
+ <%= link_to image_tag('magnifier.png'),
+ :controller => 'attachments',
+ :action => 'show',
+ :id => attachment,
+ :filename => attachment.filename%>
+ <% end %>
+
+ <%= h(truncate(" - #{attachment.description}", length: options[:length] ? options[:length]:15, omission: '...')) unless attachment.description.blank? %>
+
+
(
+ <%= number_to_human_size attachment.filesize %>)
+
+ <% if options[:deletable] %>
+ <% if attachment.container_type == 'HomeworkAttach' %>
+ <%= link_to image_tag('delete.png'), {:controller => 'attachments', :action => 'delete_homework', :id => attachment.id},
+ :data => {:confirm => l(:text_are_you_sure)},
+ :method => :delete,
+ :class => 'delete delete-homework-icon',
+ :remote => true,
+ :title => l(:button_delete) %>
+ <% else %>
+ <%= link_to image_tag('delete.png'), attachment_path(attachment),
+ :data => {:confirm => l(:text_are_you_sure)},
+ :method => :delete,
+ :class => 'delete',
+ #:remote => true,
+ #:id => "attachments_" + attachment.id.to_s,
+ :title => l(:button_delete) %>
+ <% end %>
+ <% end %>
+ <% if options[:wrap] %>
+
+
+ <% end %>
+ <% if options[:author] %>
+
+ <%= link_to h(truncate(attachment.author.name, length: 10, omission: '...')),user_path(attachment.author),:class => "c_orange" %>,
+ <%= format_time(attachment.created_on) %>
+
+ <% end %>
+
+ <% end %>
+
+ <% if defined?(thumbnails) && thumbnails %>
+ <% images = attachments.select(&:thumbnailable?) %>
+ <% if images.any? %>
+ <% images.each do |attachment| %>
+
<%= thumbnail_issue_tag(attachment) %>
+ <% end %>
+ <% end %>
+ <% end %>
+
+
diff --git a/app/views/avatar/_avatar_form.html.erb b/app/views/avatar/_avatar_form.html.erb
index 6f9b9c7b1..56f1f130e 100644
--- a/app/views/avatar/_avatar_form.html.erb
+++ b/app/views/avatar/_avatar_form.html.erb
@@ -46,7 +46,7 @@
<%= link_to l(:button_delete_file),{:controller => :avatar,:action => :delete_image,:remote=>true,:source_type=> source.class,:source_id=>source.id},:confirm => l(:text_are_you_sure), :method => :post, :class => "btn_addPic", :style => "text-decoration:none;" %>
<%= l(:button_upload_photo) %>
-
+
<%= file_field_tag 'avatar[image]',
@@ -68,6 +68,7 @@
:source_id => source.id.to_s
} %>
+
<% content_for :header_tags do %>
<%= javascript_include_tag 'avatars' %>
diff --git a/app/views/avatar/_avatar_preview.html.erb b/app/views/avatar/_avatar_preview.html.erb
new file mode 100644
index 000000000..f7a014c64
--- /dev/null
+++ b/app/views/avatar/_avatar_preview.html.erb
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
diff --git a/app/views/avatar/_new_avatar_form.html.erb b/app/views/avatar/_new_avatar_form.html.erb
index 8ca08c766..e341bc83a 100644
--- a/app/views/avatar/_new_avatar_form.html.erb
+++ b/app/views/avatar/_new_avatar_form.html.erb
@@ -2,10 +2,10 @@
<%= image_tag(url_to_avatar(source), id: "avatar_image", :width =>"60", :height =>"60",:alt=>"上传图片")%>
<%#= link_to l(:button_delete_file),{:controller => :avatar,:action => :delete_image,:remote=>true,:source_type=> source.class,:source_id=>source.id},:confirm => l(:text_are_you_sure), :method => :post, :class => "upbtn fl" %>
-
上传图片
+
<%= l(:button_upload_photo) %>
<%= file_field_tag 'avatar[image]',
:id => nil,
- :class => 'upload_file ',
+ :class => 'upload_file',
:size => "1",
:multiple => false,
:onchange => 'addInputAvatar(this);',
diff --git a/app/views/bids/_alert_anonyoms.html.erb b/app/views/bids/_alert_anonyoms.html.erb
index 2f1c443f4..4da6e0a10 100644
--- a/app/views/bids/_alert_anonyoms.html.erb
+++ b/app/views/bids/_alert_anonyoms.html.erb
@@ -66,10 +66,10 @@
<% end %>
diff --git a/app/views/bids/_homework.html.erb b/app/views/bids/_homework.html.erb
index a7a703c05..c3a6cc9d0 100644
--- a/app/views/bids/_homework.html.erb
+++ b/app/views/bids/_homework.html.erb
@@ -1,16 +1,5 @@
<%= render_flash_messages %>
diff --git a/app/views/bids/_homework_list.html.erb b/app/views/bids/_homework_list.html.erb
index c0ae219a5..f11d9d3af 100644
--- a/app/views/bids/_homework_list.html.erb
+++ b/app/views/bids/_homework_list.html.erb
@@ -57,7 +57,6 @@
<%= render :partial => 'homework_attach/homeworks_list',
:locals => {:homeworks => @homework_list,
- :homework_count => @obj_count,
:remote => false,
:not_batch_homework => @not_batch_homework,:is_student_batch_homework => @is_student_batch_homework}%>
diff --git a/app/views/bids/_new_homework_form.html.erb b/app/views/bids/_new_homework_form.html.erb
index aeb9a5c41..7a5f628f9 100644
--- a/app/views/bids/_new_homework_form.html.erb
+++ b/app/views/bids/_new_homework_form.html.erb
@@ -1,53 +1,54 @@
-<%= stylesheet_link_tag 'jquery/jquery-ui-1.9.2', :media => 'all' %>
-<%= error_messages_for 'bid' %>
-<%= hidden_field_tag 'course_id', @course.id %>
-
-
<%= l(:label_course_homework_new)%>
-
-
-
-
- * <%= l(:field_name)%> :
-
-
-
-
- <%= l(:field_quote)%> :
-
- <% if edit_mode %>
- <%= f.kindeditor :description,:width=>'91%',:editor_id => 'bid_description_editor',:owner_id => bid.id,:owner_type =>OwnerTypeHelper::BID %>
- <% else %>
- <%= hidden_field_tag :asset_id,params[:asset_id],:required => false,:style => 'display:none' %>
- <%= f.kindeditor :description,:width=>'91%',:editor_id => 'bid_description_editor' %>
- <% end %>
-
-
-
- * <%= l(:label_limit_time)%> :
-
- <%= calendar_for('bid_deadline')%>
-
-
- <%= l(:label_open_anonymous_evaluation)%> :
- >
-
-
-
- * <%= l(:field_evaluation_num)%> :
-
- <%= l(:label_evaluation_description)%>
-
-
-
- <%= l(:label_attachment_plural) %> :
- <%= render :partial => 'attachments/new_form', :locals => {:container => bid} %>
-
-
-
- <%= l(:button_create)%>
- <%= link_to l(:button_cancel), homework_course_path(@course), :class => "blue_btn grey_btn fl c_white"%>
-
-
-
-
-
+<%= stylesheet_link_tag 'jquery/jquery-ui-1.9.2', :media => 'all' %>
+<%= error_messages_for 'bid' %>
+<%= hidden_field_tag 'course_id', @course.id %>
+
+
<%= l(:label_course_homework_new)%>
+
+
+
+
+ * <%= l(:field_name)%> :
+
+
+
+
+ <%= l(:field_quote)%> :
+
+ <% if edit_mode %>
+ <%= f.kindeditor :description,:width=>'91%',:editor_id => 'bid_description_editor',:owner_id => bid.id,:owner_type =>OwnerTypeHelper::BID %>
+ <% else %>
+ <%= hidden_field_tag :asset_id,params[:asset_id],:required => false,:style => 'display:none' %>
+ <%= f.kindeditor :description,:width=>'91%',:editor_id => 'bid_description_editor' %>
+ <% end %>
+
+
+
+ * <%= l(:label_limit_time)%> :
+
+ <%= calendar_for('bid_deadline')%>
+
+
+
+ <%= l(:label_open_anonymous_evaluation)%> :
+ >
+
+
+
+ * <%= l(:field_evaluation_num)%> :
+
+ <%= l(:label_evaluation_description)%>
+
+
+
+ <%= l(:label_attachment_plural) %> :
+ <%= render :partial => 'attachments/new_form', :locals => {:container => bid} %>
+
+
+
+ <%= l(:button_create)%>
+ <%= link_to l(:button_cancel), homework_course_path(@course), :class => "blue_btn grey_btn fl c_white"%>
+
+
+
+
+
diff --git a/app/views/bids/alert_anonymous_comment.js.erb b/app/views/bids/alert_anonymous_comment.js.erb
index 5cb4018a6..66c36e223 100644
--- a/app/views/bids/alert_anonymous_comment.js.erb
+++ b/app/views/bids/alert_anonymous_comment.js.erb
@@ -1,6 +1,6 @@
$('#ajax-modal').html('<%= escape_javascript(render :partial => 'alert_anonyoms', locals: { bid: @bid, totle_size:@totle_size, cur_size:@cur_size, percent:@percent}) %>');
showModal('ajax-modal', '500px');
-$('#ajax-modal').css('height','180px');
+//$('#ajax-modal').css('height','180px');
$('#ajax-modal').siblings().remove();
$('#ajax-modal').before("
" +
" ");
diff --git a/app/views/boards/_course_new.html.erb b/app/views/boards/_course_new.html.erb
new file mode 100644
index 000000000..94ba51529
--- /dev/null
+++ b/app/views/boards/_course_new.html.erb
@@ -0,0 +1,9 @@
+<%= form_for @message, :url =>{:controller=>'messages',:action => 'new', :board_id => @board.id, :is_board => 'true'}, :html => {:multipart => true, :id => 'message-form'} do |f| %>
+
+ <%= render :partial => 'form_course', :locals => {:f => f} %>
+
+ <%= link_to l(:button_cancel), course_boards_path(@course), :class => 'grey_btn fr ml10' %>
+ <%= l(:button_submit)%>
+
+
+<% end %>
diff --git a/app/views/boards/_course_show.html.erb b/app/views/boards/_course_show.html.erb
index ed2c20448..8f2cddc48 100644
--- a/app/views/boards/_course_show.html.erb
+++ b/app/views/boards/_course_show.html.erb
@@ -1,28 +1,26 @@
-
- <% if User.current.logged? %>
-
- <%= link_to h(@board.name), course_board_path(@course, @board) %>
- <%= l(:label_message_new) %>
-
-
- <%= form_for @message, :url => new_board_message_path(@board), :html => {:multipart => false, :id => 'message-form'} do |f| %>
- <%= render :partial => 'messages/form_course', :locals => {:f => f} %>
-
- <%= l(:button_submit)%>
- <%= link_to l(:button_cancel), "javascript:void(0)", :onclick => '$("#add-message").hide(); return false;' ,:class => 'ButtonColor m3p10' %>
-
- <% end %>
-
- <% end %>
-
+
-
<%= l(:label_board_plural) %>
-
+
+ <% if User.current.language == "zh"%>
+ <%= h @board.name %>
+ <% else %>
+ <%= l(:project_module_boards) %>
+ <% end %>
+
+
<%= l(:label_message_new) %>
+
+
+
+
+
+
+
+ <%= render :partial => 'course_new' %>
+
+
<% if !User.current.logged?%>
@@ -31,38 +29,125 @@
<% end %>
-
-
- <%= l(:label_totle) %>
- <%= @topic_count %>
- <%= l(:label_course_momes_count) %>
-
- <%= link_to l(:label_message_new),
- new_board_message_path(@board),
- :class => 'problem_new_btn fl c_dorange' if User.current.logged? %>
-
-
+
<% if @topics.any? %>
<% @topics.each do |topic| %>
-
- <%= link_to image_tag(url_to_avatar(topic.author), :width=>"32",:height=>"32"), user_path(topic.author),:class => 'problem_pic talk_pic fl' %>
-
- <%= link_to h(topic.subject.truncate(40,ommision:'...')), board_message_path(@board, topic),title: topic.subject.to_s,:class => "problem_tit fl fb c_dblue" %>
- <% if topic.sticky? %>
-
置顶
+
+ <%= link_to image_tag(url_to_avatar(topic.author), :width=>"42",:height=>"42"), user_path(topic.author),:class =>'talkmain_pic fl' %>
+
+ <% author = topic.author.to_s + ":" %>
+ <%= link_to author, user_path(topic.author), :class =>"talkmain_name fl " %>
+
<%= h(topic.subject) %>
+ <% if topic.sticky? %>
+
<%= l(:label_board_sticky)%>
+ <% end %>
+
+
+
+
+
+ <%= topic.content %>
+
+
[展开]
+
+
+
+
+ <%= l(:label_activity_time)%>: <%= format_time topic.created_on %>
+
+ <%= toggle_link l(:button_reply), "reply" + topic.id.to_s, :focus => 'message_content',:class => ' c_dblue fr' %>
+
+
+
+
+ <% reply = Message.new(:subject => "RE: #{@message.subject}")%>
+ <% if !topic.locked? && authorize_for('messages', 'reply') %>
+
+
+
+ <%= form_for reply, :as => :reply, :url => {:controller=>'messages',:action => 'reply', :id => topic.id, :board_id => topic.board_id, :is_board => 'true'}, :html => {:multipart => true, :id => 'message_form' + topic.id.to_s} do |f| %>
+
+ <%= render :partial => 'form_project', :locals => {:f => f, :replying => true} %>
+
<%= l(:label_memo_create)%>
+ <% end %>
+
+
<% end %>
-
-
由<%= link_to topic.author,user_path(topic.author),:class => "problem_name" %>添加于<%= format_time(topic.created_on) %>
-
- <%=link_to (l(:label_reply) + topic.replies_count.to_s), board_message_path(@board, topic),:class => "talk_btn fr c_white" %>
+ <% replies_all = topic.children.
+ includes(:author, :attachments, {:board => :project}).
+ reorder("#{Message.table_name}.created_on DESC").offset(2).
+ all %>
+ <% replies_show = topic.children.
+ includes(:author, :attachments, {:board => :project}).
+ reorder("#{Message.table_name}.created_on DESC").limit(2).
+ all %>
+ <% unless replies_show.empty? %>
+ <% reply_count = 0 %>
+
+
+ <% replies_show.each do |message| %>
+
+
+ <%= link_to image_tag(url_to_avatar(message.author), :width => '34',:height => '34'), user_path(message.author), :class =>'Msg_pic' %>
+
+ <%= link_to_user_header message.author,false,:class => 'fl c_orange ' %>
+
+
<%= textAreailizable message,:content,:attachments => message.attachments %>
+
+
+
<%= format_time(message.created_on) %>
+ <%= link_to(
+
+ l(:button_delete),
+ {:controller => 'messages', :action => 'destroy', :id => message.id, :board_id => message.board_id, :is_board => 'true'},
+ :method => :post,
+ :data => {:confirm => l(:text_are_you_sure)},
+ :title => l(:button_delete),
+ :class => ' c_dblue fr'
+ ) if message.course_destroyable_by?(User.current) %>
+
+
+
+
+ <% end %>
+
+
+
+
+ <% replies_all.each do |message| %>
-
-
+
+ <%= link_to image_tag(url_to_avatar(message.author), :width => '34',:height => '34'), user_path(message.author), :class =>'Msg_pic' %>
+
+ <%= link_to_user_header message.author,false,:class => 'fl c_orange ' %>
+
+
<%= textAreailizable message,:content,:attachments => message.attachments %>
+
+
+
<%= format_time(message.created_on) %>
+ <%= link_to(
+
+ l(:button_delete),
+ {:controller => 'messages', :action => 'destroy', :id => message.id, :board_id => message.board_id, :is_board => 'true'},
+ :method => :post,
+ :data => {:confirm => l(:text_are_you_sure)},
+ :title => l(:button_delete),
+ :class => ' c_dblue fr'
+ ) if message.course_destroyable_by?(User.current) %>
+
+
+
+
+ <% end %>
+
+
+
+
+ <% end %>
+
<% end %>
<% else %>
-
- <%= l(:label_no_data) %>
-
+
<%= l(:label_no_data) %>
<% end %>
<%= pagination_links_full @obj_pages, @obj_count, :per_page_links => false, :remote => false, :flag => true%>
diff --git a/app/views/boards/_form.html.erb b/app/views/boards/_form.html.erb
index c1ab085cf..47ae0672d 100644
--- a/app/views/boards/_form.html.erb
+++ b/app/views/boards/_form.html.erb
@@ -13,3 +13,18 @@
<% end %>
+
+
+
+
+ <%= link_to h(topic.subject), board_message_path(@board, topic), title:topic.subject.to_s, :class =>"problem_tit fl" %>
+ <% if topic.sticky? %>
+
<%= l(:label_board_sticky)%>
+ <% end %>
+
+ <%= l(:label_post_by)%><%= link_to topic.author, user_path(topic.author), :class =>"problem_name" %>
+ <%= l(:label_post_by_time)%><%= format_time topic.created_on %>
+
+
<%= link_to (l(:label_short_reply) + " "+topic.replies_count.to_s), board_message_path(@board, topic), :style =>"color:#fff;line-height: 18px;" %>
+
+
\ No newline at end of file
diff --git a/app/views/boards/_form_course.html.erb b/app/views/boards/_form_course.html.erb
new file mode 100644
index 000000000..5cd2d8a2f
--- /dev/null
+++ b/app/views/boards/_form_course.html.erb
@@ -0,0 +1,60 @@
+<%= error_messages_for 'message' %>
+<% replying ||= false %>
+<% extra_option = replying ? { readonly: true} : { maxlength: 200 } %>
+<% if replying %>
+
+ * <%= l(:field_subject) %> :
+
+ <%= f.text_field :subject, { size: 60, id: "message_subject",:class=>"talk_input w585" }.merge(extra_option) %>
+
+
+
+
+<% else %>
+
+ * <%= l(:field_subject) %> :
+
+
+ <%= f.text_field :subject, { size: 60, id: "message_subject", onkeyup: "regexSubject();",:class=>"talk_input w585" }.merge(extra_option) %>
+
+
+
+<% end %>
+
+ <% unless replying %>
+ <% if @message.safe_attribute? 'sticky' %>
+ <%= f.check_box :sticky %>
+ <%= label_tag 'message_sticky', l(:label_board_sticky) %>
+ <% end %>
+ <% if @message.safe_attribute? 'locked' %>
+ <%= f.check_box :locked %>
+ <%= label_tag 'message_locked', l(:label_board_locked) %>
+ <% end %>
+ <% end %>
+
+
+
+
+ <% unless replying %>
+ * <%= l(:field_description) %> :
+ <% end %>
+ <%= text_area :quote,:quote,:style => 'display:none' %>
+ <% if replying%>
+ <%= f.text_area :content, :class => 'talk_text fl', :id => 'message_content', :onkeyup => "regexContent();", :maxlength => 5000,:placeholder => "最多3000个汉字(或6000个英文字符)", :style=>"width: 575px;" %>
+ <% else %>
+ <%= f.text_area :content, :class => 'talk_text fl', :id => 'message_content', :onkeyup => "regexContent();", :maxlength => 5000,:placeholder => "最多3000个汉字(或6000个英文字符)" %>
+ <% end %>
+
+
+
+
+
+ <% unless replying %>
+
+ <%= render :partial => 'attachments/form_course', :locals => {:container => @message,:isReply => @isReply} %>
+
+ <% end %>
+
+
+
+
\ No newline at end of file
diff --git a/app/views/boards/_form_project.html.erb b/app/views/boards/_form_project.html.erb
new file mode 100644
index 000000000..b42cabbeb
--- /dev/null
+++ b/app/views/boards/_form_project.html.erb
@@ -0,0 +1,60 @@
+<%= error_messages_for 'message' %>
+<% replying ||= false %>
+<% extra_option = replying ? { readonly: true} : { maxlength: 200 } %>
+<% if replying %>
+
+ * <%= l(:field_subject) %> :
+
+ <%= f.text_field :subject, { size: 60, id: "message_subject",:class=>"talk_input w585" }.merge(extra_option) %>
+
+
+
+
+<% else %>
+
+ * <%= l(:field_subject) %> :
+
+
+ <%= f.text_field :subject, { size: 60, id: "message_subject", onkeyup: "regexSubject();",:class=>"talk_input w585" }.merge(extra_option) %>
+
+
+
+<% end %>
+
+ <% unless replying %>
+ <% if @message.safe_attribute? 'sticky' %>
+ <%= f.check_box :sticky %>
+ <%= label_tag 'message_sticky', l(:label_board_sticky) %>
+ <% end %>
+ <% if @message.safe_attribute? 'locked' %>
+ <%= f.check_box :locked %>
+ <%= label_tag 'message_locked', l(:label_board_locked) %>
+ <% end %>
+ <% end %>
+
+
+
+
+ <% unless replying %>
+ * <%= l(:field_description) %> :
+ <% end %>
+ <%= text_area :quote,:quote,:style => 'display:none' %>
+ <% if replying%>
+ <%= f.text_area :content, :class => 'talk_text fl', :id => 'message_content', :onkeyup => "regexContent();", :maxlength => 5000,:placeholder => "最多3000个汉字(或6000个英文字符)", :style=>"width: 575px;" %>
+ <% else %>
+ <%= f.text_area :content, :class => 'talk_text fl', :id => 'message_content', :onkeyup => "regexContent();", :maxlength => 5000,:placeholder => "最多3000个汉字(或6000个英文字符)" %>
+ <% end %>
+
+
+
+
+
+<% unless replying %>
+
+ <%= render :partial => 'attachments/form_project', :locals => {:container => @message,:isReply => @isReply} %>
+
+ <% end %>
+
+
+
+
\ No newline at end of file
diff --git a/app/views/boards/_project_new_topic.html.erb b/app/views/boards/_project_new_topic.html.erb
new file mode 100644
index 000000000..371007a72
--- /dev/null
+++ b/app/views/boards/_project_new_topic.html.erb
@@ -0,0 +1,9 @@
+<%= form_for @message, :url =>{:controller=>'messages',:action => 'new', :board_id => @board.id, :is_board => 'true'}, :html => {:multipart => true, :id => 'message-form'} do |f| %>
+
+ <%= render :partial => 'form_project', :locals => {:f => f} %>
+
+ <%= link_to l(:button_cancel), project_boards_path(@project), :class => 'grey_btn fr ml10' %>
+ <%= l(:button_submit)%>
+
+
+<% end %>
\ No newline at end of file
diff --git a/app/views/boards/_project_show.html.erb b/app/views/boards/_project_show.html.erb
index 765cb2a65..ef2591b30 100644
--- a/app/views/boards/_project_show.html.erb
+++ b/app/views/boards/_project_show.html.erb
@@ -1,100 +1,198 @@
-
-
- <% if User.current.logged? %>
-
-
<%= l(:project_module_boards_post) %>
-
- <%= form_for @message, :url => new_board_message_path(@board), :html => {:multipart => true, :id => 'message-form'} do |f| %>
- <%= render :partial => 'messages/form', :locals => {:f => f} %>
-
- <%= l(:button_submit)%>
- <%= link_to l(:button_cancel), "#", :onclick => '$("#add-message").hide(); return false;', :class => 'ButtonColor m3p10' %>
-
- <% end %>
-
- <% end %>
+
+
+ <% if User.current.language == "zh"%>
+ <%= h @board.name %>
+ <% else %>
+ <%= l(:project_module_boards) %>
+ <% end %>
+
+
+
<%= l(:label_message_new) %>
+
<% if !User.current.logged? %>
-
- <% if @project.project_type == 1 %>
- <%= l(:label_user_login_course_board) %>
- <% else %>
- <%= l(:label_user_login_project_board) %>
- <% end %>
- <%= link_to l(:label_user_login_new), signin_path %>
-
+
+ <%= l(:label_user_login_project_board) %>
+ <%= link_to l(:label_user_login_new), signin_path, :class => "c_blue ml5" %>
<% end %>
-
-
-
-
- <% if User.current.language == "zh"%>
- <%= h @board.name %>
- <% else %>
- <%= l(:project_module_boards) %>
- <% end %>
-
-
-
-
<%= l(:label_project_board_count , :count => @topic_count)%>
- <% if @project.enabled_modules.where("name = 'boards'").count > 0 && User.current.member_of?(@project) %>
-
<%= link_to l(:project_module_boards_post), new_board_message_path(@board),
- :class => 'problem_new_btn fl',
- :onclick => 'showAndScrollTo("add-message", "message_subject"); return false;' if User.current.logged? %>
- <% end %>
-
-
+
+
+
+
+
+ <%= render :partial => 'project_new_topic' %>
+
+
+
- <% if @topics.any? %>
- <% @topics.each do |topic| %>
-
-
- <%= link_to image_tag(url_to_avatar(topic.author), :class => "problem_pic talk_pic fl"), user_path(topic.author) %>
-
-
-
-
<%= link_to h(topic.subject), board_message_path(@board, topic), title:topic.subject.to_s, :class =>"problem_tit fl" %>
+
+<% if @topics.any? %>
+ <% @topics.each do |topic| %>
+
+ <%= link_to image_tag(url_to_avatar(topic.author), :width=>"42",:height=>"42"), user_path(topic.author),:class =>'talkmain_pic fl' %>
+
+ <% author = topic.author.to_s + ":" %>
+ <%= link_to author, user_path(topic.author), :class =>"talkmain_name fl " %>
+
<%= h(topic.subject) %>
<% if topic.sticky? %>
-
<%= l(:label_board_sticky)%>
+
<%= l(:label_board_sticky)%>
<% end %>
-
-
- <%= l(:label_post_by)%><%= link_to topic.author, user_path(topic.author), :class =>"problem_name" %>
- <%= l(:label_post_by_time)%><%= format_time topic.created_on %>
-
+
+
+
+
+ <%= topic.content %>
+
+ [展开]
+
+
+
+
+
+
+
+
+ <%= l(:label_activity_time)%>: <%= format_time topic.created_on %>
-
<%= link_to (l(:label_short_reply) + " "+topic.replies_count.to_s), board_message_path(@board, topic), :style =>"color:#fff;line-height: 18px;" %>
+ <%= toggle_link l(:button_reply), "reply" + topic.id.to_s, :focus => 'message_content',:class => ' c_dblue fr' %>
+
- <% end %>
-
- <%= pagination_links_full @topic_pages, @topic_count, :per_page_links => false, :remote => false, :flag => true %>
-
+
+ <% reply = Message.new(:subject => "RE: #{@message.subject}")%>
+ <% if !topic.locked? && authorize_for('messages', 'reply') %>
+
+
+
+ <%= form_for reply, :as => :reply, :url => {:controller=>'messages',:action => 'reply', :id => topic.id, :board_id => topic.board_id, :is_board => 'true'}, :html => {:multipart => true, :id => 'message_form' + topic.id.to_s} do |f| %>
+
+ <%= render :partial => 'form_project', :locals => {:f => f, :replying => true} %>
+
<%= l(:label_memo_create)%>
+ <% end %>
+
+
+ <% end %>
+ <% replies_all = topic.children.
+ includes(:author, :attachments, {:board => :project}).
+ reorder("#{Message.table_name}.created_on DESC").offset(2).
+ all %>
+ <% replies_show = topic.children.
+ includes(:author, :attachments, {:board => :project}).
+ reorder("#{Message.table_name}.created_on DESC").limit(2).
+ all %>
+ <% unless replies_show.empty? %>
+ <% reply_count = 0 %>
+
+
+ <% replies_show.each do |message| %>
+
+
+ <%= link_to image_tag(url_to_avatar(message.author), :width => '34',:height => '34'), user_path(message.author), :class =>'Msg_pic' %>
+
+ <%= link_to_user_header message.author,false,:class => 'fl c_orange ' %>
+
+
<%= textAreailizable message,:content,:attachments => message.attachments %>
+
+
+
<%= format_time(message.created_on) %>
+ <%= link_to(
+
+ l(:button_delete),
+ {:controller => 'messages', :action => 'destroy', :id => message.id, :board_id => message.board_id, :is_board => 'true'},
+ :method => :post,
+ :data => {:confirm => l(:text_are_you_sure)},
+ :title => l(:button_delete),
+ :class => ' c_dblue fr'
+ ) if message.course_destroyable_by?(User.current) %>
+
+
+
+
+ <% end %>
+
+
+
+
+ <% replies_all.each do |message| %>
+
+
+ <%= link_to image_tag(url_to_avatar(message.author), :width => '34',:height => '34'), user_path(message.author), :class =>'Msg_pic' %>
+
+ <%= link_to_user_header message.author,false,:class => 'fl c_orange ' %>
+
+
<%= textAreailizable message,:content,:attachments => message.attachments %>
+
+
+
<%= format_time(message.created_on) %>
+ <%= link_to(
+
+ l(:button_delete),
+ {:controller => 'messages', :action => 'destroy', :id => message.id, :board_id => message.board_id, :is_board => 'true'},
+ :method => :post,
+ :data => {:confirm => l(:text_are_you_sure)},
+ :title => l(:button_delete),
+ :class => ' c_dblue fr'
+ ) if message.course_destroyable_by?(User.current) %>
+
+
+
+
+ <% end %>
+
+
+
+
+ <% end %>
+
+ <% end %>
<% else %>
<%= l(:label_no_data) %>
<% end %>
-
-
-
+
+ <%= pagination_links_full @topic_pages, @topic_count, :per_page_links => false, :remote => false, :flag => true %>
+
+
-<% other_formats_links do |f| %>
- <%= f.link_to 'Atom', :url => {:key => User.current.rss_key} %>
-<% end %>
+<%# other_formats_links do |f| %>
+ <%#= f.link_to 'Atom', :url => {:key => User.current.rss_key} %>
+<%# end %>
<% html_title @board.name %>
<% content_for :header_tags do %>
<%= auto_discovery_link_tag(:atom, {:format => 'atom', :key => User.current.rss_key}, :title => "#{@project}: #{@board}") %>
<% end %>
+
+
\ No newline at end of file
diff --git a/app/views/boards/show.html.erb b/app/views/boards/show.html.erb
index 81d1288fd..3b810a4b2 100644
--- a/app/views/boards/show.html.erb
+++ b/app/views/boards/show.html.erb
@@ -1,6 +1,109 @@
-
-<% if @project %>
- <%= render :partial => 'project_show', locals: {project: @project} %>
-<% elsif @course %>
- <%= render :partial => 'course_show', locals: {course: @course} %>
-<% end %>
+
+
+
+<% if @project %>
+ <%= render :partial => 'project_show', locals: {project: @project} %>
+<% elsif @course %>
+ <%= render :partial => 'course_show', locals: {course: @course} %>
+<% end %>
diff --git a/app/views/common/_project_tab.html.erb b/app/views/common/_project_tab.html.erb
new file mode 100644
index 000000000..95ac48c59
--- /dev/null
+++ b/app/views/common/_project_tab.html.erb
@@ -0,0 +1,28 @@
+<% selected_tab = params[:tab] ? params[:tab].to_s : tabs.first[:name] %>
+
+
+
+ <% tabs.each do |tab| -%>
+ <%= link_to l(tab[:label]), { :tab => tab[:name] },
+ :id => "tab-#{tab[:name]}",
+ :class => (tab[:name] != selected_tab ? 'hwork_normaltab' : 'hwork_hovertab'),
+ :onclick => "showTab('#{tab[:name]}'); this.blur(); return false;" %>
+ <% end -%>
+
+
+
+
+
+
+<% tabs.each do |tab| -%>
+ <%= content_tag('div', render(:partial => tab[:partial], :locals => {:tab => tab} ),
+ :id => "tab-content-#{tab[:name]}",
+ :style => (tab[:name] != selected_tab ? 'display:none' : nil),
+ :class => 'hwork_normaltab') %>
+<% end -%>
diff --git a/app/views/contests/_form_contest.html.erb b/app/views/contests/_form_contest.html.erb
index ec993fae8..344d69571 100644
--- a/app/views/contests/_form_contest.html.erb
+++ b/app/views/contests/_form_contest.html.erb
@@ -67,7 +67,7 @@
<%= f.text_field :deadline,
:required => true,
:size => 60,
- :style => "width:150px;",
+ :style => "width:150px;float:left;",
:readonly => true,
:placeholder => "#{l(:label_deadline)}"
%>
diff --git a/app/views/courses/_course.html.erb b/app/views/courses/_course.html.erb
index 8974c3089..755dd63b0 100644
--- a/app/views/courses/_course.html.erb
+++ b/app/views/courses/_course.html.erb
@@ -58,14 +58,14 @@
<%= content_tag('span', "#{garble @course.members.count}", :class => "info") %>
<%= content_tag('span', l(:label_x_member, :count => memberCount(@course))) %>
-
+
<%= content_tag('span', link_to("#{@course_activity_count[@course.id]}", course_path(@course)), :class => "info") %>
<%= content_tag('span', l(:label_x_activity, :count => @course_activity_count[@course.id])) %>
-
+
<% if(course_endTime_timeout? @course) %>
@@ -79,16 +79,6 @@
-
- <%= content_tag "span","#{l(:label_duration_time)}:", :class => "course-font"%>
- <%= get_course_term @course %>
-
-
-
- <%= content_tag "span", "#{l(:label_course_brief_introduction)}:", :class => "course-font" %>
- <%= content_tag "div", course.short_description, :class => "brief_introduction", :title => course.short_description %>
-
-
-
- <%= pagination_links_full @obj_pages, @obj_count, :per_page_links => false, :remote => @is_remote, :flag => true%>
-
+
<% else%>
<%= l(:label_no_data) %>
diff --git a/app/views/courses/_searchmembers.html.erb b/app/views/courses/_searchmembers.html.erb
index c6b577c8d..1956f34c4 100644
--- a/app/views/courses/_searchmembers.html.erb
+++ b/app/views/courses/_searchmembers.html.erb
@@ -1,5 +1,5 @@
<%= form_tag( searchmembers_course_path(@course), method: 'get',:class => "f_l",:remote=>true,:id => "search_student") do %>
- <%= text_field_tag 'name', params[:name], name: "name", :class => 'st_search_input', :placeholder => '输入学生姓名、学号进行搜索'%>
+ <%= text_field_tag 'name', params[:name], name: "name", :class => 'st_search_input', :placeholder => '输入学生昵称、姓名、学号进行搜索'%>
<% if @group %>
<%= hidden_field "search_group_id", params[:search_group_id],:value => "#{@group.id}", name: 'search_group_id' %>
diff --git a/app/views/courses/_show_member_score.html.erb b/app/views/courses/_show_member_score.html.erb
index 0f962da81..bb080b57b 100644
--- a/app/views/courses/_show_member_score.html.erb
+++ b/app/views/courses/_show_member_score.html.erb
@@ -27,15 +27,15 @@
/***弹框***/
- #popbox_tscore{width:480px;position:absolute;z-index:100;left:50%;top:50%;margin:-215px 0 0 -300px; background:#fff; -moz-border-radius:5px; -webkit-border-radius:5px; border-radius:5px; box-shadow:0px 0px 8px #194a81; overflow:auto;}
- .alert .close02{width:26px;height:26px;overflow:hidden;position:absolute;top:-10px;right:-490px;background:url(images/close.png) no-repeat;cursor:pointer;}
- .tscore_con h2{ display:block; background:#eaeaea; font-size:14px; color:#343333; height:31px; width: auto; margin-top:25px; padding-left:20px; padding-top:5px;}
+ /*#popbox_tscore{width:480px;position:absolute;z-index:100;left:50%;top:50%;margin:-215px 0 0 -300px; background:#fff; -moz-border-radius:5px; -webkit-border-radius:5px; border-radius:5px; box-shadow:0px 0px 8px #194a81; overflow:auto;}*/
+ /*.alert .close02{width:26px;height:26px;overflow:hidden;position:absolute;top:-10px;right:-490px;background:url(images/close.png) no-repeat;cursor:pointer;}*/
+ .tscore_con h2{ display:block; background:#eaeaea; font-size:14px; color:#343333; height:31px; width: auto; text-align: center; padding-top:5px;}
.tscore_box{ width:350px; margin:15px auto;}
.tscore_box li{ height:25px;}
-
+
<%= @member_score.user.name %> 历次作业积分
作业名称 得分
diff --git a/app/views/courses/new_homework.html.erb b/app/views/courses/new_homework.html.erb
index ac26c2f29..9ec73d519 100644
--- a/app/views/courses/new_homework.html.erb
+++ b/app/views/courses/new_homework.html.erb
@@ -1,4 +1,4 @@
-<%= javascript_include_tag "/assets/kindeditor/kindeditor" %>
-<%= labelled_form_for @homework, :html => { :multipart => true }, :url => {:controller => 'bids', :action => 'create_homework',:course_id => "#{params[:id] || params[:course_id]}"} do |f| %>
- <%= render :partial => 'bids/new_homework_form', :locals => { :bid => @homework,:bid_id => "new_bid",:f => f,:edit_mode => false } %>
+<%= javascript_include_tag "/assets/kindeditor/kindeditor" %>
+<%= labelled_form_for @homework, :html => { :multipart => true }, :url => {:controller => 'bids', :action => 'create_homework',:course_id => "#{params[:id] || params[:course_id]}"} do |f| %>
+ <%= render :partial => 'bids/new_homework_form', :locals => { :bid => @homework,:bid_id => "new_bid",:f => f,:edit_mode => false } %>
<% end %>
\ No newline at end of file
diff --git a/app/views/courses/settings.html.erb b/app/views/courses/settings.html.erb
index e68be7141..69ce4f5dc 100644
--- a/app/views/courses/settings.html.erb
+++ b/app/views/courses/settings.html.erb
@@ -1,92 +1,92 @@
-
-
<%= l(:label_course_modify_settings)%>
-
-
-
-
-
-
-
- <%= form_tag({:controller => 'courses', :action => 'search_member'},:id => "course_member_search_form", :method => :get, :class => "search_form_course",:remote => true) do %>
-
- <%= text_field_tag 'name', params[:name], :placeholder => "昵称、学号、姓名搜索", :class => "search_text fl" %>
-
- <%= l(:label_search)%>
-
-
-
- <% end %>
-
-
-
- <%= render :partial => "course_members" %>
-
-
-
+
+
<%= l(:label_course_modify_settings)%>
+
+
+
+
+
+
+
+ <%= form_tag(search_member_course_path,:id => "course_member_search_form", :method => :get, :class => "search_form_course",:remote => true) do %>
+
+ <%= text_field_tag 'name', params[:name], :placeholder => "昵称、学号、姓名搜索", :class => "search_text fl" %>
+
+ <%= l(:label_search)%>
+
+
+
+ <% end %>
+
+
+
+ <%= render :partial => "course_members" %>
+
+
+
\ No newline at end of file
diff --git a/app/views/courses/show_member_score.js.erb b/app/views/courses/show_member_score.js.erb
index fe8d52a2b..87e728901 100644
--- a/app/views/courses/show_member_score.js.erb
+++ b/app/views/courses/show_member_score.js.erb
@@ -1,3 +1,13 @@
+//$('#ajax-modal').html('<%#= escape_javascript(render :partial => 'courses/show_member_score', :locals => {:member => @member_score}) %>');
+//showModal('ajax-modal', '400px');
+//$('#ajax-modal').addClass('new-watcher');
+
$('#ajax-modal').html('<%= escape_javascript(render :partial => 'courses/show_member_score', :locals => {:member => @member_score}) %>');
showModal('ajax-modal', '400px');
-$('#ajax-modal').addClass('new-watcher');
+//$('#ajax-modal').css('height','569px');
+$('#ajax-modal').siblings().remove();
+$('#ajax-modal').before("" +
+" ");
+//$('#ajax-modal').parent().removeClass();
+$('#ajax-modal').parent().css("top","30%").css("left","40%").css("position","fixed");
+$('#ajax-modal').parent().addClass("new-watcher");
diff --git a/app/views/files/_course_file.html.erb b/app/views/files/_course_file.html.erb
index 7b2acd875..1769b1a45 100644
--- a/app/views/files/_course_file.html.erb
+++ b/app/views/files/_course_file.html.erb
@@ -62,11 +62,11 @@
上传:
- 课件 |
- 软件 |
- 媒体 |
- 代码 |
- 其他
+ 课件 |
+ 软件 |
+ 媒体 |
+ 代码 |
+ 其他
<% end %>
diff --git a/app/views/files/_project_file_list.html.erb b/app/views/files/_project_file_list.html.erb
index c7e0cec29..3dd5134d7 100644
--- a/app/views/files/_project_file_list.html.erb
+++ b/app/views/files/_project_file_list.html.erb
@@ -24,9 +24,9 @@
<%= link_to(l(:label_slected_to_other_project),quote_resource_show_project_project_file_path(project,file),:class => "f_l re_select",:remote => true) if has_project?(User.current,file) %>
<% if manage_allowed && file.container_id == project.id && file.container_type == "Project" %>
-
- <%= link_to (file.is_public? ? "公开":"私有"), update_file_dense_attachments_path(:attachmentid=>file.id,:newtype=>(file.is_public? ? 0:1)),:remote=>true,:class=>"f_l re_open",:method => :post %>
-
+
+ <%= link_to (file.is_public? ? "公开":"私有"), update_file_dense_attachments_path(:attachmentid=>file.id,:newtype=>(file.is_public? ? 0:1)),:remote=>true,:class=>"f_l re_open",:method => :post %>
+
<% else %>
<% end %>
@@ -45,8 +45,8 @@
- <%= render :partial => 'tags/tag_new', :locals => {:obj => file, :object_flag => "10"} %>
- <%= render :partial => 'tags/tag_add', :locals => {:obj => file, :object_flag => "10"} %>
+ <%= render :partial => 'tags/tag_new', :locals => {:obj => file, :object_flag => "6"} %>
+ <%= render :partial => 'tags/tag_add', :locals => {:obj => file, :object_flag => "6"} %>
diff --git a/app/views/files/_project_file_new.html.erb b/app/views/files/_project_file_new.html.erb
index 89088a295..1e217f991 100644
--- a/app/views/files/_project_file_new.html.erb
+++ b/app/views/files/_project_file_new.html.erb
@@ -1,8 +1,3 @@
-
-
-
<%= l(:lable_file_sharingarea) %>
-
-
- <% if @issue.safe_attribute?('done_ratio') && @issue.leaf? && Issue.use_field_for_done_ratio? %>
-
<%= f.select :done_ratio, ((0..10).to_a.collect {|r| ["#{r*10} %", r*10] }), {:required => @issue.required_attribute?('done_ratio')},
- {:onchange => "PrecentChange(this.value)"} %>
- <% end %>
-
-
-
-
-
-<% if @issue.safe_attribute? 'custom_field_values' %>
-<%= render :partial => 'issues/form_custom_fields' %>
-<% end %>
+
+
+ <%= l(:label_change_properties) %>
+
+
+ * <%= l(:field_status) %>:
+ <% if @issue.safe_attribute?('status_id') && @allowed_statuses.present? %>
+ <%= f.select :status_id,
+ (@allowed_statuses.collect { |p| [p.name, p.id] }),
+ {:no_label => true},
+ # ajax 刷新
+ #:onchange => "updateIssueFrom('#{escape_javascript project_issue_form_path(@project, :id => @issue, :format => 'js')}')",
+ :class => "w150" %>
+ <% else %>
+ <%= h(@issue.status.name) %>
+ <% end %>
+
+
+
+ * <%= l(:field_priority) %>:
+ <% if @issue.safe_attribute? 'priority_id' %>
+ <%= f.select :priority_id,
+ (@priorities.collect { |p| [p.name, p.id] }),
+ {:required => true, :no_label => true}, :disabled => !@issue.leaf?,
+ :class => "w150" %>
+ <% end %>
+
+
+
+
+ <%= l(:field_assigned_to) %>:
+ <% if @issue.safe_attribute? 'assigned_to_id' %>
+ <%= f.select :assigned_to_id, principals_options_for_select(@issue.assignable_users, @issue.assigned_to),
+ {:required => @issue.required_attribute?('assigned_to_id'), :no_label => true},
+ :class => "w150" %>
+ <% end %>
+
+
+
+ <% if @issue.safe_attribute?('fixed_version_id') && @issue.assignable_versions.any? %>
+ <%= l(:field_fixed_version) %>:
+ <%= f.select :fixed_version_id, version_options_for_select(@issue.assignable_versions, @issue.fixed_version),
+ {:include_blank => true, :required => @issue.required_attribute?('fixed_version_id'), :no_label => true},
+ :class => "w150" %>
+ <%#= link_to(image_tag('add.png', :style => 'vertical-align: middle;'),
+ new_project_version_path(@issue.project),
+ :remote => true,
+ :method => 'get',
+ :title => l(:label_version_new),
+ :tabindex => 200) if User.current.allowed_to?(:manage_versions, @issue.project) %>
+ <%= link_to "", new_project_version_path(@issue.project), :class => "pic_add mt5 ml5 " %>
+
+ <% end %>
+
+
+
+
+
+
+ <%= l(:field_start_date) %>:
+ <% if @issue.safe_attribute? 'start_date' %>
+ <%= f.text_field :start_date,
+ :size => 22,
+ :disabled => !@issue.leaf?,
+ :no_label => true,
+ :required => @issue.required_attribute?('start_date') %>
+ <%= calendar_for('issue_start_date', 'start_date') if @issue.leaf? %>
+ <% end %>
+
+
+
+ <%= l(:field_due_date) %>:
+ <% if @issue.safe_attribute? 'due_date' %>
+ <%= f.text_field :due_date, :size => 22,
+ :disabled => !@issue.leaf?,
+ :no_label => true,
+ :required => @issue.required_attribute?('due_date') %>
+ <%= calendar_for('issue_due_date', 'start_date') if @issue.leaf? %>
+ <% end %>
+
+
+
+ <%= l(:field_estimated_hours) %>:
+ <% if @issue.safe_attribute? 'estimated_hours' %>
+ <%= f.text_field :estimated_hours, :size => 22,
+ :disabled => !@issue.leaf?,
+ :no_label => true,
+ :required => @issue.required_attribute?('estimated_hours') %>
+ <%= l(:field_hours) %>
+ <% end %>
+
+
+ % 完成 :
+ <% if @issue.safe_attribute?('done_ratio') && @issue.leaf? && Issue.use_field_for_done_ratio? %>
+ <%= f.select :done_ratio, ((0..10).to_a.collect { |r| ["#{r*10} %", r*10] }),
+ {:required => @issue.required_attribute?('done_ratio'), :no_label => true},
+ :onchange => "PrecentChange(this.value)",
+ :class => "w150" %>
+ <% end %>
+
+
+
+
+
+
+
+
+
+ <% if @issue.safe_attribute? 'custom_field_values' %>
+ <%= render :partial => 'issues/form_custom_fields' %>
+ <% end %>
<% end %>
diff --git a/app/views/issues/_edit.html.erb b/app/views/issues/_edit.html.erb
index 8037bee01..e4c1290aa 100644
--- a/app/views/issues/_edit.html.erb
+++ b/app/views/issues/_edit.html.erb
@@ -1,51 +1,43 @@
<%= labelled_form_for @issue, :html => {:id => 'issue-form', :multipart => true} do |f| %>
<%= error_messages_for 'issue', 'time_entry' %>
<%= render :partial => 'conflict' if @conflict %>
-
+
<% if @edit_allowed || !@allowed_statuses.empty? %>
-
<%= l(:label_change_properties) %>
-
- <%= render :partial => 'form', :locals => {:f => f} %>
+
+ <%= render :partial => 'form', :locals => {:f => f} %>
+
+
+
+
-
- <% end %>
-
<%= l(:field_notes) %>
- <%= f.text_area :notes, :cols => 60, :rows => 10, :class => 'wiki-edit', :no_label => true %>
- <%= wikitoolbar_for 'issue_notes' %>
+ <% end %>
- <% if @issue.safe_attribute? 'private_notes' %>
- <%= f.check_box :private_notes, :no_label => true %> <%= l(:field_private_notes) %>
+
+
+ <% if @journals.present? %>
+
+ <%= render :partial => 'history', :locals => {:issue => @issue, :journals => @journals} %>
+
<% end %>
-
- <%= call_hook(:view_issues_edit_notes_bottom, { :issue => @issue, :notes => @notes, :form => f }) %>
+ 回复
+ <%= f.text_area :notes, :style => "width:99%;", :rows => "5", :no_label => true %>
+
+
+
- <%= l(:label_attachment_plural) %>
- <%= render :partial => 'attachments/form', :locals => {:container => @issue} %>
-
+ <%= call_hook(:view_issues_edit_notes_bottom, {:issue => @issue, :notes => @notes, :form => f}) %>
+
-
-
- <%= l(:label_issue_watchers) %>
-
- <%= watchers_checkboxes(@issue, @available_watchers) %>
-
-
- <%= link_to l(:label_search_for_watchers),
- {:controller => 'watchers', :action => 'new', :project_id => @issue.project},
- :remote => true,
- :method => 'get' %>
-
-
-
-
+
+
+
<%= f.hidden_field :lock_version %>
<%= hidden_field_tag 'last_journal_id', params[:last_journal_id] || @issue.last_journal_id %>
- <%= hidden_field_tag 'reference_user_id', params[:reference_user_id]%>
- <%= submit_tag l(:button_submit) %>
- <%= preview_link preview_edit_issue_path(:project_id => @project, :id => @issue), 'issue-form' %>
+ <%= hidden_field_tag 'reference_user_id', params[:reference_user_id] %>
<% end %>
diff --git a/app/views/issues/_form.html.erb b/app/views/issues/_form.html.erb
index fb2fa9e55..4cd370adc 100644
--- a/app/views/issues/_form.html.erb
+++ b/app/views/issues/_form.html.erb
@@ -1,65 +1,116 @@
-
<%= labelled_fields_for :issue, @issue do |f| %>
-<%= call_hook(:view_issues_form_details_top, { :issue => @issue, :form => f }) %>
+ <%= call_hook(:view_issues_form_details_top, {:issue => @issue, :form => f}) %>
+
+
+
+ <% if @issue.safe_attribute? 'tracker_id' %>
+ * 类型 :
+ <%= f.select :tracker_id,
+ @issue.project.trackers.collect { |t| [t.name, t.id] },
+ {:required => true, :no_label => true},
+ :onchange => "updateIssueFrom('#{escape_javascript project_issue_form_path(@project, :id => @issue, :format => 'js')}')",
+ :class => "w90"
+ %>
+ <% end %>
+
+
+ <% if @issue.safe_attribute? 'is_private' %>
+ <%= f.check_box :is_private, :no_label => true, :class => "ml30" %>
+ <%= l(:field_is_private) %>
+ <%= l(:field_is_private_tips)%>
+ <% end %>
+
+
+
+
+ <%#= f.select :project_id, project_tree_options_for_select(@issue.allowed_target_projects, :selected => @issue.project), {:required => true},
+ :onchange => "updateIssueFrom('#{escape_javascript project_issue_form_path(@project, :id => @issue, :format => 'js')}')" %>
+
+
+
+ <% if @issue.safe_attribute? 'subject' %>
+ * 主题 :
+ <%= f.text_field :subject,
+ :class => "w583",
+ :maxlength => 255,
+ :style => "font-size:small",
+ :no_label => true
+ %>
+
+ <%= javascript_tag do %>
+ observeAutocompleteField('issue_subject',
+ '<%= escape_javascript auto_complete_issues_path(:project_id => @project, :scope => (Setting.cross_project_issue_relations? ? 'all' : nil)) %>',
+ { select: function(event, ui) {
+ $('input#issue_subject').val(ui.item.value);
+ }
+ });
+ <% end %>
-<% if @issue.safe_attribute? 'is_private' %>
-
- <%= f.check_box :is_private, :no_label => true %><%= l(:field_is_private) %>
-
-<% end %>
-
-<% if @issue.safe_attribute? 'project_id' %>
-<%= f.select :project_id, project_tree_options_for_select(@issue.allowed_target_projects, :selected => @issue.project), {:required => true},
- :onchange => "updateIssueFrom('#{escape_javascript project_issue_form_path(@project, :id => @issue, :format => 'js')}')" %>
-<% end %>
-
-<% if @issue.safe_attribute? 'tracker_id' %>
-<%= f.select :tracker_id, @issue.project.trackers.collect {|t| [t.name, t.id]}, {:required => true},
- :onchange => "updateIssueFrom('#{escape_javascript project_issue_form_path(@project, :id => @issue, :format => 'js')}')" %>
-
-<% end %>
-
-
-<% if @issue.safe_attribute? 'subject' %>
-<%= f.text_field :subject, :size => 80, :maxlength => 255, :required => true, :style => "font-size:small" %>
-
-<%= javascript_tag do %>
- observeAutocompleteField('issue_subject', '<%= escape_javascript auto_complete_issues_path(:project_id => @project,:scope => (Setting.cross_project_issue_relations? ? 'all' : nil)) %>',
- { select: function(event, ui) {
- $('input#issue_subject').val(ui.item.value);
- }
- });
-<% end %>
-
-<% end %>
-
-<% if @issue.safe_attribute? 'description' %>
-
- <%= f.label_for_field :description, :required => @issue.required_attribute?('description') %>
- <%= link_to_function image_tag('edit.png'), '$(this).hide(); $("#issue_description_and_toolbar").show()' unless @issue.new_record? %>
- <%= content_tag 'span', :id => "issue_description_and_toolbar", :style => (@issue.new_record? ? nil : 'display:none') do %>
- <%= f.text_area :description,
- :cols => 60,
- :rows => (@issue.description.blank? ? 10 : [[10, @issue.description.length / 50].max, 100].min),
- :accesskey => accesskey(:edit),
- :class => 'wiki-edit',
- :style => "font-size:small;width:520px;",
- :no_label => true %>
- <% end %>
-
-<%= wikitoolbar_for 'issue_description' %>
-<% end %>
+ <% end %>
+
+
-
- <%= render :partial => 'issues/attributes' %>
-
+
+ <% if @issue.safe_attribute? 'description' %>
+ 描述 :
+ <%= f.label_for_field :description, :required => @issue.required_attribute?('description'), :no_label => true, :class => "label" %>
+ <%= link_to_function image_tag('edit.png'), '$(this).hide(); $("#issue_description_and_toolbar").show()' unless @issue.new_record? %>
+ <%= content_tag 'span', :id => "issue_description_and_toolbar", :style => (@issue.new_record? ? nil : 'display:none') do %>
+ <%= f.text_area :description,
+ :rows => (@issue.description.blank? ? 10 : [[10, @issue.description.length / 50].max, 100].min),
+ :accesskey => accesskey(:edit),
+ :class => "w583",
+ :no_label => true %>
+ <% end %>
-<%= call_hook(:view_issues_form_details_bottom, { :issue => @issue, :form => f }) %>
+ <%= wikitoolbar_for 'issue_description' %>
+ <% end %>
+
+
+
+
+
+ <% if @copy_from && @copy_from.attachments.any? %>
+
+
+
+
+ <% end %>
+ <% if @copy_from && !@copy_from.leaf? %>
+
+ <%= l(:label_copy_subtasks) %>
+ <%= check_box_tag 'copy_subtasks', '1', @copy_subtasks %>
+
+ <% end %>
+
+
+
+
+ <%= l(:label_attachment_plural) %>:
+ <%= render :partial => 'attachments/form', :locals => {:container => @issue} %>
+
+
+
+ <%= render :partial => 'issues/attributes' %>
+
+
+
+
+
+
+ <%#= link_to "",
+# {:controller => 'watchers', :action => 'new', :project_id => @issue.project},
+# :remote => true,
+# :method => 'get',
+ :class => "pic_sch mt5 ml5" %>
+
+ <%#= javascript_tag "observeSearchfield('user_search', 'users_for_watcher', '#{ escape_javascript watchers_autocomplete_for_user_path(:user => @available_watchers, :format => 'js', :flag => 'ture') }')" %>
+
+
+
+
+
+
+ <%= call_hook(:view_issues_form_details_bottom, {:issue => @issue, :form => f}) %>
<% end %>
diff --git a/app/views/issues/_history.html.erb b/app/views/issues/_history.html.erb
index 9823e30b7..b0f1ad38d 100644
--- a/app/views/issues/_history.html.erb
+++ b/app/views/issues/_history.html.erb
@@ -1,43 +1,33 @@
<% reply_links = authorize_for('issues', 'edit') -%>
-<% for journal in journals %>
-
+<% journals.reverse.each do |journal| %>
-
-
- <%= image_tag(url_to_avatar(journal.user), :class => "avatar") %>
-
-
-
-
- <%= authoring journal.created_on, journal.user, :label => :label_updated_time_by %>
- <%= render_links(issue, journal, :reply_links => reply_links) unless journal.notes.blank? %>
-
-
-
-
-
- <% if journal.details.any? %>
- <% details_to_strings(journal.details).each do |string| %>
-
- <%= string %>
- <% end %>
- <% end %>
- <%= render_notes(issue, journal, :reply_links => reply_links) unless journal.notes.blank? %>
-
-
-
- <%= format_time journal.created_on %>
-
-
-
-
-
+
+
+
+
+
<%= journal.user %> <%= format_time journal.created_on %>
+
+
+ <% if journal.details.any? %>
+ <% details_to_strings(journal.details).each do |string| %>
+
<%= string %>
+ <% end %>
+ <% end %>
+
+
+
+
+
+
<%= render_notes_issue(issue, journal, :reply_links => reply_links) unless journal.notes.blank? %>
+
+
+
+
-
-<%= call_hook(:view_issues_history_journal_bottom, { :journal => journal }) %>
+ <%= call_hook(:view_issues_history_journal_bottom, { :journal => journal }) %>
<% end %>
<% heads_for_wiki_formatter if User.current.allowed_to?(:edit_issue_notes, issue.project) || User.current.allowed_to?(:edit_own_issue_notes, issue.project) %>
diff --git a/app/views/issues/_list.html.erb b/app/views/issues/_list.html.erb
index 4519b6047..f1b5a319d 100644
--- a/app/views/issues/_list.html.erb
+++ b/app/views/issues/_list.html.erb
@@ -1,69 +1,35 @@
-