Merge branch 'szzh' into sw_new_course

sw_new_course
sw 10 years ago
commit 8073ca42b3

5
.gitignore vendored

@ -5,6 +5,7 @@
*.swp *.swp
/config/database.yml /config/database.yml
/config/configuration.yml /config/configuration.yml
/config/additional_environment.rb
/files/* /files/*
/log/* /log/*
/public/tmp/* /public/tmp/*
@ -23,3 +24,7 @@
public/api_doc/ public/api_doc/
/.metadata /.metadata
vendor/cache vendor/cache
/files
/public/images/avatars
/public/files
/tags

@ -4,10 +4,13 @@ source 'http://ruby.taobao.org'
unless RUBY_PLATFORM =~ /w32/ unless RUBY_PLATFORM =~ /w32/
# unix-like only # unix-like only
gem 'iconv' gem 'iconv'
gem 'rubyzip'
gem 'zip-zip'
end end
gem "mysql2", "= 0.3.18"
gem 'redis-rails'
gem 'rubyzip'
gem 'delayed_job_active_record'#, :group => :production
gem 'daemons'
gem 'grape', '~> 0.9.0' gem 'grape', '~> 0.9.0'
gem 'grape-entity' gem 'grape-entity'
gem 'seems_rateable', '~> 1.0.13' gem 'seems_rateable', '~> 1.0.13'
@ -20,9 +23,6 @@ gem "builder", "3.0.0"
gem 'acts-as-taggable-on', '2.4.1' gem 'acts-as-taggable-on', '2.4.1'
gem 'spreadsheet' gem 'spreadsheet'
gem 'ruby-ole' 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' gem 'rails_kindeditor',path:'lib/rails_kindeditor'
group :development do group :development do
gem 'grape-swagger' gem 'grape-swagger'
@ -58,8 +58,6 @@ group :test do
#end #end
end end
# gem 'rspec-rails' , '2.13.1'
# gem 'guard-rspec','2.5.0'
# Gems used only for assets and not required # Gems used only for assets and not required
# in production environments by default. # in production environments by default.
group :assets do group :assets do
@ -84,56 +82,13 @@ group :openid do
gem "rack-openid" gem "rack-openid"
end 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") database_file = File.join(File.dirname(__FILE__), "config/database.yml")
if File.exist?(database_file) 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 else
warn("Please configure your config/database.yml first") warn("Please configure your config/database.yml first")
end 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 # Load plugins' Gemfiles
Dir.glob File.expand_path("../plugins/*/Gemfile", __FILE__) do |file| Dir.glob File.expand_path("../plugins/*/Gemfile", __FILE__) do |file|
puts "Loading #{file} ..." if $DEBUG # `ruby -d` or `bundle -v` puts "Loading #{file} ..." if $DEBUG # `ruby -d` or `bundle -v`

@ -1,49 +1,49 @@
module Mobile module Mobile
require_relative 'middleware/error_handler' require_relative 'middleware/error_handler'
require_relative 'apis/auth' require_relative 'apis/auth'
require_relative 'apis/users' require_relative 'apis/users'
require_relative 'apis/courses' require_relative 'apis/courses'
require_relative 'apis/watches' require_relative 'apis/watches'
require_relative 'apis/upgrade' require_relative 'apis/upgrade'
require_relative 'apis/homeworks' require_relative 'apis/homeworks'
require_relative 'apis/comments' require_relative 'apis/comments'
class API < Grape::API class API < Grape::API
version 'v1', using: :path version 'v1', using: :path
format :json format :json
content_type :json, "application/json;charset=UTF-8" content_type :json, "application/json;charset=UTF-8"
use Mobile::Middleware::ErrorHandler use Mobile::Middleware::ErrorHandler
helpers do helpers do
def logger def logger
API.logger API.logger
end end
def authenticate! def authenticate!
raise('Unauthorized. Invalid or expired token.') unless current_user raise('Unauthorized. Invalid or expired token.') unless current_user
end end
def current_user def current_user
token = ApiKey.where(access_token: params[:token]).first token = ApiKey.where(access_token: params[:token]).first
if token && !token.expired? if token && !token.expired?
@current_user = User.find(token.user_id) @current_user = User.find(token.user_id)
else else
nil nil
end end
end end
end end
mount Apis::Auth mount Apis::Auth
mount Apis::Users mount Apis::Users
mount Apis::Courses mount Apis::Courses
mount Apis::Watches mount Apis::Watches
mount Apis::Upgrade mount Apis::Upgrade
mount Apis::Homeworks mount Apis::Homeworks
mount Apis::Comments 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: 'http://u06.shellinfo.cn/trustie/api'})
#add_swagger_documentation ({api_version: 'v1', base_path: '/api'}) if Rails.env.development? #add_swagger_documentation ({api_version: 'v1', base_path: '/api'}) if Rails.env.development?
end end
end end

@ -26,7 +26,7 @@ module Mobile
present :data, {token: key.access_token, user: api_user}, using: Entities::Auth present :data, {token: key.access_token, user: api_user}, using: Entities::Auth
present :status, 0 present :status, 0
else else
raise 'Unauthorized.' raise "无效的用户名或密码"
end end
end end

@ -80,7 +80,7 @@ module Mobile
end end
post do post do
cs_params = { cs_params = {
memo: {:subject => params[:subject],:content => '该贴来自手机App意见反馈'}, memo: {:subject => '该贴来自手机App意见反馈' ,:content => params[:subject]},
} }
cs = CommentService.new cs = CommentService.new
memo,message = cs.create_feedback cs_params, current_user memo,message = cs.create_feedback cs_params, current_user

@ -80,6 +80,10 @@ module Mobile
class_period: params[:class_period] class_period: params[:class_period]
} }
course = ::Course.find(params[:course_id]) course = ::Course.find(params[:course_id])
# 如果没有传密码过来,那就把原来的密码给上,不然会不更新
if params[:password].nil? || params[:password].blank?
cs_params[:course][:password] = course[:password]
end
cs.edit_course_authorize(current_user,course) cs.edit_course_authorize(current_user,course)
course = cs.edit_course(cs_params, course,current_user) course = cs.edit_course(cs_params, course,current_user)
present :data, course, with: Mobile::Entities::Course present :data, course, with: Mobile::Entities::Course
@ -224,6 +228,32 @@ module Mobile
present :status, 0 present :status, 0
end 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 end
end end

@ -14,7 +14,7 @@ module Mobile
us = UsersService.new us = UsersService.new
user = us.register params.merge(:password_confirmation => params[:password], user = us.register params.merge(:password_confirmation => params[:password],
:should_confirmation_password => true) :should_confirmation_password => true)
raise "register failed #{user.errors.full_messages}" if user.new_record? raise "该邮箱已经被注册过了" if user.new_record?
present :data, user, with: Mobile::Entities::User present :data, user, with: Mobile::Entities::User
present :status, 0 present :status, 0

@ -16,8 +16,11 @@ module Mobile
end end
end end
end end
attachment_expose :id
attachment_expose :filename attachment_expose :filename
attachment_expose :description attachment_expose :description
attachment_expose :downloads
attachment_expose :quotes
end end
end end
end end

@ -46,6 +46,7 @@ module Mobile
course_expose :term course_expose :term
course_expose :time course_expose :time
course_expose :updated_at course_expose :updated_at
course_expose :course_student_num
expose :teacher, using: Mobile::Entities::User do |c, opt| expose :teacher, using: Mobile::Entities::User do |c, opt|
if c.is_a? ::Course if c.is_a? ::Course
c.teacher c.teacher
@ -58,6 +59,7 @@ module Mobile
end end
course_expose :current_user_is_member course_expose :current_user_is_member
course_expose :current_user_is_teacher course_expose :current_user_is_teacher
course_expose :work_unit
end end
end end
end end

@ -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

@ -15,13 +15,13 @@ module Mobile
when :img_url when :img_url
url_to_avatar(u) url_to_avatar(u)
when :gender when :gender
u.user_extensions.gender.nil? ? 0 : u.user_extensions.gender u.nil? || u.user_extensions.nil? || u.user_extensions.gender.nil? ? 0 : u.user_extensions.gender
when :work_unit when :work_unit
get_user_work_unit u get_user_work_unit u
when :location when :location
get_user_location u get_user_location u
when :brief_introduction when :brief_introduction
u.user_extensions.brief_introduction u.nil? || u.user_extensions.nil? ? "" : u.user_extensions.brief_introduction
end end
end end
end end
@ -34,6 +34,8 @@ module Mobile
user_expose :img_url user_expose :img_url
#昵称 #昵称
expose :nickname expose :nickname
#真名
expose :realname
#性别 #性别
user_expose :gender user_expose :gender
#我的二维码 #我的二维码

@ -88,9 +88,7 @@ class AccountController < ApplicationController
# create a new token for password recovery # create a new token for password recovery
token = Token.new(:user => user, :action => "recovery") token = Token.new(:user => user, :action => "recovery")
if token.save if token.save
Thread.new do Mailer.run.lost_password(token)
Mailer.lost_password(token).deliver
end
flash[:notice] = l(:notice_account_lost_email_sent) flash[:notice] = l(:notice_account_lost_email_sent)
redirect_to signin_url redirect_to signin_url
return return
@ -228,7 +226,7 @@ class AccountController < ApplicationController
user = User.find(params[:user]) if params[:user] user = User.find(params[:user]) if params[:user]
token = Token.new(:user => user, :action => "register") token = Token.new(:user => user, :action => "register")
if token.save if token.save
Mailer.register(token).deliver Mailer.run.register(token)
else else
yield if block_given? yield if block_given?
@ -334,7 +332,7 @@ class AccountController < ApplicationController
token = Token.create(:user => user, :action => 'autologin') token = Token.create(:user => user, :action => 'autologin')
cookie_options = { cookie_options = {
:value => token.value, :value => token.value,
:expires => 1.year.from_now, :expires => 7.days.from_now,
:path => (Redmine::Configuration['autologin_cookie_path'] || '/'), :path => (Redmine::Configuration['autologin_cookie_path'] || '/'),
:secure => (Redmine::Configuration['autologin_cookie_secure'] ? true : false), :secure => (Redmine::Configuration['autologin_cookie_secure'] ? true : false),
:httponly => true :httponly => true
@ -366,7 +364,7 @@ class AccountController < ApplicationController
token = Token.new(:user => user, :action => "register") token = Token.new(:user => user, :action => "register")
if user.save and token.save if user.save and token.save
UserStatus.create(:user_id => user.id, :changsets_count => 0, :watchers_count => 0) UserStatus.create(:user_id => user.id, :changsets_count => 0, :watchers_count => 0)
Mailer.register(token).deliver Mailer.run.register(token)
flash[:notice] = l(:notice_account_register_done) flash[:notice] = l(:notice_account_register_done)
@ -401,7 +399,7 @@ class AccountController < ApplicationController
if user.save if user.save
UserStatus.create(:user_id => user.id ,:changsets_count => 0, :watchers_count => 0) UserStatus.create(:user_id => user.id ,:changsets_count => 0, :watchers_count => 0)
# Sends an email to the administrators # Sends an email to the administrators
Mailer.account_activation_request(user).deliver Mailer.run.account_activation_request(user)
account_pending account_pending
else else
yield if block_given? yield if block_given?

@ -894,7 +894,6 @@ class ApplicationController < ActionController::Base
set_autologin_cookie(user) set_autologin_cookie(user)
end end
call_hook(:controller_account_success_authentication_after, {:user => user }) call_hook(:controller_account_success_authentication_after, {:user => user })
end end
end end

@ -1,59 +1,59 @@
class AppliedProjectController < ApplicationController class AppliedProjectController < ApplicationController
#申请加入项目 #申请加入项目
def applied_join_project def applied_join_project
@user_id = params[:user_id] @user_id = params[:user_id]
@project = Project.find_by_id(params[:project_id]) @project = Project.find_by_id(params[:project_id])
if params[:project_join] if params[:project_join]
if @project if @project
user = User.find @user_id user = User.find @user_id
if user.member_of?(@project) if user.member_of?(@project)
@status = 3 @status = 3
else else
@applieds = AppliedProject.where("user_id = ? and project_id = ?", params[:user_id],params[:project_id]) @applieds = AppliedProject.where("user_id = ? and project_id = ?", params[:user_id],params[:project_id])
if @applieds.count == 0 if @applieds.count == 0
appliedproject = AppliedProject.create(:user_id => params[:user_id], :project_id => params[:project_id]) appliedproject = AppliedProject.create(:user_id => params[:user_id], :project_id => params[:project_id])
Mailer.applied_project(appliedproject).deliver Mailer.run.applied_project(appliedproject)
@status = 2 @status = 2
else else
@status = 1 @status = 1
end end
end end
else else
@status = 0 @status = 0
end end
respond_to do |format| respond_to do |format|
format.js format.js
end end
return return
end end
@applieds = AppliedProject.where("user_id = ? and project_id = ?", params[:user_id],params[:project_id]) @applieds = AppliedProject.where("user_id = ? and project_id = ?", params[:user_id],params[:project_id])
if @applieds.count == 0 if @applieds.count == 0
appliedproject = AppliedProject.create(:user_id => params[:user_id], :project_id => params[:project_id]) appliedproject = AppliedProject.create(:user_id => params[:user_id], :project_id => params[:project_id])
Mailer.applied_project(appliedproject).deliver Mailer.run.applied_project(appliedproject)
end end
#redirect_to project_path(params[:project_id]) #redirect_to project_path(params[:project_id])
#redirect_to_referer_or {render :text => ( 'applied success.'), :layout => true} #redirect_to_referer_or {render :text => ( 'applied success.'), :layout => true}
respond_to do |format| respond_to do |format|
format.html { redirect_to_referer_or {render :text => (watching ? 'Watcher added.' : 'Watcher removed.'), :layout => true}} format.html { redirect_to_referer_or {render :text => (watching ? 'Watcher added.' : 'Watcher removed.'), :layout => true}}
format.js { render :partial => 'set_applied'} format.js { render :partial => 'set_applied'}
end end
end end
#取消申请 #取消申请
def unapplied_join_project def unapplied_join_project
@project = Project.find(params[:project_id]) @project = Project.find(params[:project_id])
#@applied = AppliedProject.find(params[:id]) #@applied = AppliedProject.find(params[:id])
#@applied.destroy #@applied.destroy
AppliedProject.deleteappiled(params[:user_id], params[:project_id]) AppliedProject.deleteappiled(params[:user_id], params[:project_id])
respond_to do |format| respond_to do |format|
format.html { redirect_to_referer_or {render :text => (watching ? 'Watcher added.' : 'Watcher removed.'), :layout => true}} format.html { redirect_to_referer_or {render :text => (watching ? 'Watcher added.' : 'Watcher removed.'), :layout => true}}
format.js { render :partial => 'set_applied' } format.js { render :partial => 'set_applied' }
end end
end end
end end

@ -27,7 +27,7 @@ class AttachmentsController < ApplicationController
accept_api_auth :show, :download, :upload accept_api_auth :show, :download, :upload
require 'iconv' require 'iconv'
include AttachmentsHelper include AttachmentsHelper
include ApplicationHelper
def show def show
respond_to do |format| respond_to do |format|
@ -65,36 +65,7 @@ class AttachmentsController < ApplicationController
def download def download
# modify by nwb # modify by nwb
# 下载添加权限设置 # 下载添加权限设置
candown = false candown = attachment_candown @attachment
if @attachment.container.class.to_s != "HomeworkAttach" && (@attachment.container.has_attribute?(:project) || @attachment.container.has_attribute?(:project_id)) && @attachment.container.project
project = @attachment.container.project
candown= User.current.member_of?(project) || (project.is_public && @attachment.is_public == 1)
elsif @attachment.container.is_a?(Project)
project = @attachment.container
candown= User.current.member_of?(project) || (project.is_public && @attachment.is_public == 1)
elsif (@attachment.container.has_attribute?(:board) || @attachment.container.has_attribute?(:board_id)) && @attachment.container.board &&
@attachment.container.board.project
project = @attachment.container.board.project
candown = User.current.member_of?(project) || (project.is_public && @attachment.is_public == 1)
elsif (@attachment.container.has_attribute?(:course) ||@attachment.container.has_attribute?(:course_id) ) && @attachment.container.course
course = @attachment.container.course
candown = User.current.member_of_course?(course) || (course.is_public==1 && @attachment.is_public == 1)
elsif @attachment.container.is_a?(Course)
course = @attachment.container
candown= User.current.member_of_course?(course) || (course.is_public==1 && @attachment.is_public == 1)
elsif (@attachment.container.has_attribute?(:board) || @attachment.container.has_attribute?(:board_id)) && @attachment.container.board &&
@attachment.container.board.course
course = @attachment.container.board.course
candown= User.current.member_of_course?(course) || (course.is_public==1 && @attachment.is_public == 1)
elsif @attachment.container.class.to_s=="HomeworkAttach" && @attachment.container.bid.reward_type == 3
candown = true
elsif @attachment.container_type == "Bid" && @attachment.container && @attachment.container.courses.first
course = @attachment.container.courses.first
candown = User.current.member_of_course?(course) || (course.is_public == 1 && @attachment.is_public == 1)
else
candown = @attachment.is_public == 1
end
if candown || User.current.admin? || User.current.id == @attachment.author_id if candown || User.current.admin? || User.current.id == @attachment.author_id
@attachment.increment_download @attachment.increment_download
if stale?(:etag => @attachment.digest) if stale?(:etag => @attachment.digest)
@ -108,7 +79,7 @@ class AttachmentsController < ApplicationController
end end
rescue => e rescue => e
redirect_to "http://" + (Setting.host_name.to_s) +"/file_not_found.html" redirect_to "http: //" + (Setting.host_name.to_s) +"/file_not_found.html"
end end
#更新资源文件类型 #更新资源文件类型
@ -349,6 +320,46 @@ class AttachmentsController < ApplicationController
end end
end end
def add_exist_file_to_projects
file = Attachment.find(params[:file_id])
projects = params[:projects][:project]
@message = ""
projects.each do |project|
c = Project.find(project);
if project_contains_attachment?(c,file)
if @message && @message == ""
@message += l(:label_project_prompt) + c.name + l(:label_contain_resource) + file.filename + l(:label_quote_resource_failed)
next
else
@message += "<br/>" + l(:label_project_prompt) + c.name + l(:label_contain_resource) + file.filename + l(:label_quote_resource_failed)
next
end
end
attach_copied_obj = file.copy
attach_copied_obj.tag_list.add(file.tag_list) # tag关联
attach_copied_obj.container = c
attach_copied_obj.created_on = Time.now
attach_copied_obj.author_id = User.current.id
attach_copied_obj.copy_from = file.copy_from.nil? ? file.id : file.copy_from
if attach_copied_obj.attachtype == nil
attach_copied_obj.attachtype = 4
end
@obj = c
@save_flag = attach_copied_obj.save
@save_message = attach_copied_obj.errors.full_messages
update_quotes attach_copied_obj
end
respond_to do |format|
format.js
end
rescue NoMethodError
@save_flag = false
@save_message = [] << l(:label_course_empty_select)
respond_to do |format|
format.js
end
end
def add_exist_file_to_courses def add_exist_file_to_courses
file = Attachment.find(params[:file_id]) file = Attachment.find(params[:file_id])
courses = params[:courses][:course] courses = params[:courses][:course]

@ -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 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 (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 FROM homework_attaches WHERE bid_id = #{@bid.id} ORDER BY s_score DESC,created_at ASC) AS table1
WHERE table1.t_score IS NULL") WHERE table1.t_score IS NULL OR table1.t_score = 0")
@not_batch_homework = true @not_batch_homework = true
@cur_type = 1 @cur_type = 1
else else
@ -506,7 +506,8 @@ class BidsController < ApplicationController
end end
@cur_page = params[:page] || 1 @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 @jours_count = @bid.journals_for_messages.where('m_parent_id IS NULL').count
if params[:student_id].present? if params[:student_id].present?
@temp = [] @temp = []
@ -792,7 +793,7 @@ class BidsController < ApplicationController
@bid.is_evaluation = params[:bid][:is_evaluation] @bid.is_evaluation = params[:bid][:is_evaluation]
@bid.proportion = params[:bid][:proportion] @bid.proportion = params[:bid][:proportion]
@bid.evaluation_num = params[:bid][:evaluation_num] @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.reward_type = 3
# @bid.budget = params[:bid][:budget] # @bid.budget = params[:bid][:budget]
@bid.deadline = params[:bid][:deadline] @bid.deadline = params[:bid][:deadline]
@ -1035,11 +1036,12 @@ class BidsController < ApplicationController
def alert_anonymous_comment def alert_anonymous_comment
@bid = Bid.find params[:id] @bid = Bid.find params[:id]
@course = @bid.courses.first @course = @bid.courses.first
@cur_size = 0
@totle_size = 0
if @bid.comment_status == 0 if @bid.comment_status == 0
@totle_size = searchStudent(@course).size @totle_size = searchStudent(@course).size
@cur_size = @bid.homeworks.size @cur_size = @bid.homeworks.size
elsif @bid.comment_status == 1 elsif @bid.comment_status == 1
@totle_size = 0
@bid.homeworks.map { |homework| @totle_size += homework.homework_evaluations.count} @bid.homeworks.map { |homework| @totle_size += homework.homework_evaluations.count}
@cur_size = 0 @cur_size = 0
@bid.homeworks.map { |homework| @cur_size += homework.rates(:quality).where("seems_rateable_rates.is_teacher_score = 0").count} @bid.homeworks.map { |homework| @cur_size += homework.rates(:quality).where("seems_rateable_rates.is_teacher_score = 0").count}

@ -42,12 +42,19 @@ class BoardsController < ApplicationController
elsif @course elsif @course
if (User.current.admin? || @course.is_public == 1 || (@course.is_public == 0 && User.current.member_of_course?(@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 = @course.boards.includes(:last_message => :author).all
@boards = [] << @boards[0] if @boards.any? if @course.boards.empty?
if @boards.size == 1 @board = @course.boards.build
@board = @boards.first @board.name = " #{l(:label_borad_course) }"
show and return @board.description = @course.name.to_s
@board.project_id = -1
if @board.save
@boards = @course.boards.includes(:last_message => :author).all
end
end end
render :layout => 'base_courses' unless @course.boards.empty?
@board = @course.boards.first
end
show and return
else else
render_403 render_403
end end
@ -65,7 +72,7 @@ class BoardsController < ApplicationController
'replies' => "#{Message.table_name}.replies_count", 'replies' => "#{Message.table_name}.replies_count",
'updated_on' => "COALESCE(last_replies_messages.created_on, #{Message.table_name}.created_on)" '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 if @project
@topic_pages = Paginator.new @topic_count, per_page_option, params['page'] @topic_pages = Paginator.new @topic_count, per_page_option, params['page']
@topics = @board.topics. @topics = @board.topics.
@ -77,14 +84,13 @@ class BoardsController < ApplicationController
preload(:author, {:last_reply => :author}). preload(:author, {:last_reply => :author}).
all all
elsif @course elsif @course
board_topics = @board.topics. board_topics = @board ? @board.topics.reorder("#{Message.table_name}.sticky DESC").
reorder("#{Message.table_name}.sticky DESC").
includes(:last_reply). includes(:last_reply).
# limit(@topic_pages.per_page). # limit(@topic_pages.per_page).
# offset(@topic_pages.offset). # offset(@topic_pages.offset).
order(sort_clause). order(sort_clause).
preload(:author, {:last_reply => :author}). preload(:author, {:last_reply => :author}).
all all : []
@topics = paginateHelper board_topics,10 @topics = paginateHelper board_topics,10
end end

@ -17,6 +17,7 @@
class CommentsController < ApplicationController class CommentsController < ApplicationController
default_search_scope :news default_search_scope :news
include ApplicationHelper
model_object News model_object News
before_filter :find_model_object before_filter :find_model_object
before_filter :find_project_from_association before_filter :find_project_from_association
@ -26,9 +27,13 @@ class CommentsController < ApplicationController
raise Unauthorized unless @news.commentable? raise Unauthorized unless @news.commentable?
@comment = Comment.new @comment = Comment.new
@comment.safe_attributes = params[:comment] @project ? @comment.comments = params[:comment][:comments] : @comment.comments = params[:comment]
@comment.author = User.current @comment.author = User.current
if @news.comments << @comment if @news.comments << @comment
if params[:asset_id]
ids = params[:asset_id].split(',')
update_kindeditor_assets_owner ids,@comment.id,OwnerTypeHelper::COMMENT
end
flash[:notice] = l(:label_comment_added) flash[:notice] = l(:label_comment_added)
end end

@ -1,6 +1,7 @@
class CoursesController < ApplicationController class CoursesController < ApplicationController
layout 'base_courses' # layout 'base_courses'
include CoursesHelper include CoursesHelper
include ActivitiesHelper
helper :activities helper :activities
helper :members helper :members
helper :words helper :words
@ -30,19 +31,19 @@ class CoursesController < ApplicationController
def join def join
if User.current.logged? if User.current.logged?
cs = CoursesService.new cs = CoursesService.new
join = cs.join_course params,User.current user = User.current
join = cs.join_course params,user
@state = join[:state] @state = join[:state]
course = join[:course] course = join[:course]
else else
@state = 5 #未登录 @state = 5 #未登录
end end
respond_to do |format| respond_to do |format|
format.js { render :partial => 'set_join', :locals => {:user => User.current, :course => course, :object_id => params[:object_id]} } format.js { render :partial => 'set_join', :locals => {:user => user, :course => course, :object_id => params[:object_id]} }
end end
rescue Exception => e rescue Exception => e
@state = 4 #已经加入了课程 @state = 4 #已经加入了课程
respond_to do |format| respond_to do |format|
# format.html { redirect_to_referer_or {render :text => (watching ? 'Watcher added.' : 'Watcher removed.'), :layout => true}}
format.js { render :partial => 'set_join', :locals => {:user => User.current, :course => nil, :object_id => nil} } format.js { render :partial => 'set_join', :locals => {:user => User.current, :course => nil, :object_id => nil} }
end end
end end
@ -72,6 +73,7 @@ class CoursesController < ApplicationController
if @course.errors.full_messages.count <= 0 if @course.errors.full_messages.count <= 0
respond_to do |format| respond_to do |format|
format.html { format.html {
# render :layout => 'base_courses'
flash[:notice] = l(:notice_successful_update) flash[:notice] = l(:notice_successful_update)
redirect_to settings_course_url(@course) redirect_to settings_course_url(@course)
} }
@ -81,7 +83,7 @@ class CoursesController < ApplicationController
respond_to do |format| respond_to do |format|
format.html { format.html {
settings settings
render :action => 'settings' redirect_to settings_course_url(@course)
} }
format.api { render_validation_errors(@course) } format.api { render_validation_errors(@course) }
end end
@ -189,8 +191,9 @@ class CoursesController < ApplicationController
results = searchmember_by_name(student_homework_score(@group.id,0,0,"desc"), q) results = searchmember_by_name(student_homework_score(@group.id,0,0,"desc"), q)
end end
@is_remote = true @is_remote = true
@result_count = results.count #@result_count = results.count
@results = paginateHelper results, 10 #@results = paginateHelper results, 10
@results = results
@search_name = q @search_name = q
end end
@ -313,16 +316,19 @@ class CoursesController < ApplicationController
when '1' when '1'
@subPage_title = l :label_teacher_list @subPage_title = l :label_teacher_list
@all_members = searchTeacherAndAssistant(@course) @all_members = searchTeacherAndAssistant(@course)
@members = paginateHelper @all_members, 10 #@members = paginateHelper @all_members, 10
@members = @all_members
when '2' when '2'
@subPage_title = l :label_student_list @subPage_title = l :label_student_list
page = params[:page].nil? ? 0 : (params['page'].to_i - 1) page = params[:page].nil? ? 0 : (params['page'].to_i - 1)
@all_members = student_homework_score(0,page, 10,"desc") @all_members = student_homework_score(0,page, 10,"desc")
# @all_members = @course.members # @all_members = @course.members
@members = paginateHelper_for_members @all_members, 10 # @members = paginateHelper_for_members @all_members, 10
@members = @all_members
end end
respond_to do |format| respond_to do |format|
if params[:page] if params[:page]
format.html {render :layout => 'base_courses'}
format.js format.js
else else
format.html {render :layout => 'base_courses'} format.html {render :layout => 'base_courses'}
@ -402,23 +408,46 @@ class CoursesController < ApplicationController
@issue_category ||= IssueCategory.new @issue_category ||= IssueCategory.new
@member ||= @course.members.new @member ||= @course.members.new
@trackers = Tracker.sorted.all @trackers = Tracker.sorted.all
@roles = Role.givable.all[3..5]
@members = @course.member_principals.includes(:roles, :principal).all.sort
respond_to do |format|
format.html { render :layout => 'base_courses' }
format.api { render_validation_errors(@course) }
end
else else
render_403 render_403
end end
end end
def search_member
if User.current.allowed_to?(:as_teacher,@course) || User.current.admin
q = "#{params[:name].strip}"
@roles = Role.givable.all[3..5]
if q.nil? || q == ""
@members = @course.member_principals.includes(:roles, :principal).all.sort
else
@members = searchmember_by_name(@course.member_principals.includes(:roles, :principal).all.sort,q)
end
else
render_403
end
end
def create def create
cs = CoursesService.new cs = CoursesService.new
@course = cs.create_course(params,User.current)[:course] @course = cs.create_course(params,User.current)[:course]
if @course.new_record? if @course.new_record?
respond_to do |format| respond_to do |format|
format.html { render :action => 'new', :layout => 'base' } #Added by young format.html { render :action => 'new', :layout => 'new_base' } #Added by young
format.api { render_validation_errors(@course) } format.api { render_validation_errors(@course) }
end end
else else
respond_to do |format| respond_to do |format|
format.html { format.html {
# render :layout => 'base_courses'
flash[:notice] = l(:notice_successful_create) flash[:notice] = l(:notice_successful_create)
if params[:continue] if params[:continue]
redirect_to new_course_url(attrs, :course => '0') redirect_to new_course_url(attrs, :course => '0')
@ -482,7 +511,7 @@ class CoursesController < ApplicationController
respond_to do |format| respond_to do |format|
format.html { format.html {
render :layout => 'base' render :layout => 'new_base'
} }
format.api { format.api {
} }
@ -676,26 +705,50 @@ class CoursesController < ApplicationController
"show_course_files" => true, "show_course_files" => true,
"show_course_news" => true, "show_course_news" => true,
"show_course_messages" => true, "show_course_messages" => true,
#"show_course_journals_for_messages" => true,
"show_bids" => true, "show_bids" => true,
"show_course_journals_for_messages" => true, "show_homeworks" => true,
"show_homeworks" => true "show_polls" => true
} }
@date_to ||= Date.today + 1 @date_to ||= Date.today + 1
@date_from = (@date_to - @days) > @course.created_at.to_date ? (@date_to - @days) : @course.created_at.to_date @date_from = (@date_to - @days) > @course.created_at.to_date ? (@date_to - @days) : @course.created_at.to_date
@author = (params[:user_id].blank? ? nil : User.active.find(params[:user_id])) @author = (params[:user_id].blank? ? nil : User.active.find(params[:user_id]))
@author ||= @course.teacher if @author.nil?
# 决定显示所用用户或单个用户活动 # 显示老师和助教的活动
@activity = Redmine::Activity::Fetcher.new(User.current, :course => @course, # @authors = searchTeacherAndAssistant(@course)
:with_subprojects => false, @authors = course_all_member(@course)
:author => @author) events = []
@activity.scope_select {|t| has["show_#{t}"]} @authors.each do |author|
# modify by nwb @activity = Redmine::Activity::Fetcher.new(User.current, :course => @course,
# 添加私密性判断 :with_subprojects => false,
if User.current.member_of_course?(@course)|| User.current.admin? :author => author.user)
events = @activity.events(@days, @course.created_at)
@activity.scope_select {|t| has["show_#{t}"]}
# modify by nwb
# 添加私密性判断
if User.current.member_of_course?(@course)|| User.current.admin?
events += @activity.events(@days, @course.created_at)
else
events += @activity.events(@days, @course.created_at, :is_public => 1)
end
end
else else
events = @activity.events(@days, @course.created_at, :is_public => 1) # @author = @course.teacher
@activity = Redmine::Activity::Fetcher.new(User.current, :course => @course,
:with_subprojects => false,
:author => @author)
@activity.scope_select {|t| has["show_#{t}"]}
# modify by nwb
# 添加私密性判断
if User.current.member_of_course?(@course)|| User.current.admin?
events = @activity.events(@days, @course.created_at)
else
events = @activity.events(@days, @course.created_at, :is_public => 1)
end
end end
# 无新动态时,显示老动态 # 无新动态时,显示老动态
if events.count == 0 if events.count == 0
if User.current.member_of_course?(@course)|| User.current.admin? if User.current.member_of_course?(@course)|| User.current.admin?
@ -704,13 +757,17 @@ class CoursesController < ApplicationController
events = @activity.events(:is_public => 1) events = @activity.events(:is_public => 1)
end end
end end
events = paginateHelper events,10
@events_by_day = events.group_by {|event| User.current.time_to_date(event.event_datetime)}
# documents
@sort_by = %w(category date title author).include?(params[:sort_by]) ? params[:sort_by] : 'category' @sort_by = %w(category date title author).include?(params[:sort_by]) ? params[:sort_by] : 'category'
if(User.find_by_id(CourseInfos.find_by_course_id(@course.id).try(:user_id))) if(User.find_by_id(CourseInfos.find_by_course_id(@course.id).try(:user_id)))
@user = User.find_by_id(CourseInfos.find_by_course_id(@course.id).user_id) @user = User.find_by_id(CourseInfos.find_by_course_id(@course.id).user_id)
end end
sorted_events = sort_activity_events_course(events)
events = paginateHelper sorted_events,10
@events_by_day = events.group_by {|event| User.current.time_to_date(event.event_datetime)}
# documents
respond_to do |format| respond_to do |format|
format.html{render :layout => 'base_courses'} format.html{render :layout => 'base_courses'}
format.api format.api
@ -823,7 +880,7 @@ class CoursesController < ApplicationController
students_for_courses.course_id = #{@course.id} and members.user_id = students_for_courses.student_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} ) 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 end
else else

@ -1,42 +0,0 @@
class DiscussDemosController < ApplicationController
def index
@discuss_demo_list = DiscussDemo.where("body is not null").order("created_at desc").page(params[:page] || 1).per(10)
end
def new
@discuss_demo = DiscussDemo.create
@discuss_demo.save!
@discuss_demo
end
def create
end
def update
@discuss_demo = DiscussDemo.find(params[:id])
@discuss_demo.update_attributes(:title => params[:discuss_demo][:title],:body => params[:discuss_demo][:body])
redirect_to :controller=> 'discuss_demos',:action => 'show',:id => params[:id]
end
def delete
end
def destroy
asset = Kindeditor::Asset.find_by_owner_id(params[:id])
if !asset.nil?
filepath = File.join(Rails.root,"public","files","uploads",
asset[:created_at].to_s.gsub("+0800","").to_datetime.strftime("%Y%m").to_s,
asset[:asset].to_s)
File.delete(filepath) if File.exist?filepath
end
DiscussDemo.destroy(params[:id])
redirect_to :controller=> 'discuss_demos',:action => 'index'
end
def show
@discuss_demo = DiscussDemo.find(params[:id])
end
end

@ -110,7 +110,7 @@ class DocumentsController < ApplicationController
render_attachment_warning_if_needed(@document) render_attachment_warning_if_needed(@document)
if attachments.present? && attachments[:files].present? && Setting.notified_events.include?('document_added') if attachments.present? && attachments[:files].present? && Setting.notified_events.include?('document_added')
Mailer.attachments_added(attachments[:files]).deliver Mailer.run.attachments_added(attachments[:files])
end end
redirect_to document_url(@document) redirect_to document_url(@document)
end end

@ -23,13 +23,14 @@ class FilesController < ApplicationController
before_filter :auth_login1, :only => [:index] before_filter :auth_login1, :only => [:index]
before_filter :logged_user_by_apptoken,:only => [:index] before_filter :logged_user_by_apptoken,:only => [:index]
before_filter :find_project_by_project_id#, :except => [:getattachtype] before_filter :find_project_by_project_id#, :except => [:getattachtype]
before_filter :authorize, :except => [:getattachtype,:quote_resource_show,:search] before_filter :authorize, :except => [:getattachtype,:quote_resource_show,:search,:search_project,:quote_resource_show_project,:search_tag_attachment]
helper :sort helper :sort
include SortHelper include SortHelper
include FilesHelper include FilesHelper
helper :project_score helper :project_score
include CoursesHelper include CoursesHelper
include ApplicationHelper
def show_attachments obj def show_attachments obj
@attachments = [] @attachments = []
@ -41,8 +42,8 @@ class FilesController < ApplicationController
@feedback_count = @all_attachments.count @feedback_count = @all_attachments.count
@feedback_pages = Paginator.new @feedback_count, @limit, params['page'] @feedback_pages = Paginator.new @feedback_count, @limit, params['page']
@offset ||= @feedback_pages.offset @offset ||= @feedback_pages.offset
@curse_attachments_all = @all_attachments[@offset, @limit] #@curse_attachments_all = @all_attachments[@offset, @limit]
@curse_attachments = paginateHelper @all_attachments,10 @obj_attachments = paginateHelper @all_attachments,10
end end
def search def search
@ -50,6 +51,7 @@ class FilesController < ApplicationController
@sort = "" @sort = ""
@order = "" @order = ""
@is_remote = true @is_remote = true
@q = params[:name].strip
if params[:sort] if params[:sort]
order_by = params[:sort].split(":") order_by = params[:sort].split(":")
@sort = order_by[0] @sort = order_by[0]
@ -59,25 +61,66 @@ class FilesController < ApplicationController
sort = "#{@sort} #{@order}" sort = "#{@sort} #{@order}"
end end
# show_attachments [@course]
begin begin
q = "%#{params[:name].strip}%" q = "%#{params[:name].strip}%"
#(redirect_to stores_url, :notice => l(:label_sumbit_empty);return) if params[:name].blank? #(redirect_to stores_url, :notice => l(:label_sumbit_empty);return) if params[:name].blank?
if params[:insite] if params[:insite]
@result = find_public_attache q,sort if q == "%%"
@result = visable_attachemnts_insite @result,@course @result = []
@searched_attach = paginateHelper @result,10 @searched_attach = paginateHelper @result,10
else
@result = find_public_attache q,sort
@result = visable_attachemnts_insite @result,@course
@searched_attach = paginateHelper @result,10
end
else else
@result = find_course_attache q,@course,sort @result = find_course_attache q,@course,sort
@result = visable_attachemnts @result @result = visable_attachemnts @result
@searched_attach = paginateHelper @result,10 @searched_attach = paginateHelper @result,10
end
@tag_list = get_course_tag_list @course
end
#rescue Exception => e #rescue Exception => e
# #render 'stores' # #render 'stores'
# redirect_to search_course_files_url # redirect_to search_course_files_url
end end
end end
def search_project
sort = ""
@sort = ""
@order = ""
@is_remote = true
if params[:sort]
order_by = params[:sort].split(":")
@sort = order_by[0]
if order_by.count > 1
@order = order_by[1]
end
sort = "#{@sort} #{@order}"
end
begin
q = "%#{params[:name].strip}%"
#(redirect_to stores_url, :notice => l(:label_sumbit_empty);return) if params[:name].blank?
if params[:insite]
@result = find_public_attache q,sort
@result = visable_attachemnts_insite @result,@project
@searched_attach = paginateHelper @result,10
else
@result = find_project_attache q,@project,sort
@result = visable_attachemnts @result
@searched_attach = paginateHelper @result,10
end
#rescue Exception => e
# #render 'stores'
# redirect_to search_course_files_url
end
end
def find_course_attache keywords,course,sort = "" def find_course_attache keywords,course,sort = ""
if sort == "" if sort == ""
sort = "created_on DESC" sort = "created_on DESC"
@ -87,6 +130,30 @@ class FilesController < ApplicationController
#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") #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 end
def find_project_attache keywords,project,sort = ""
if sort == ""
sort = "created_on DESC"
end
ids = ""
len = 0
count = project.versions.count
project.versions.each do |version|
len = len + 1
if len != count
ids += version.id.to_s + ','
else
ids += version.id.to_s
end
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 = "" def find_public_attache keywords,sort = ""
# StoresController#search 将每条文件都查出来,再次进行判断过滤。---> resultSet.to_a.map # StoresController#search 将每条文件都查出来,再次进行判断过滤。---> resultSet.to_a.map
# 此时内容不多速度还可但文件增长每条判断多则进行3-4次表连接。 # 此时内容不多速度还可但文件增长每条判断多则进行3-4次表连接。
@ -132,17 +199,27 @@ class FilesController < ApplicationController
attribute = "downloads" attribute = "downloads"
when "created_on" when "created_on"
attribute = "created_on" attribute = "created_on"
when "quotes"
attribute = "quotes"
else
attribute = "created_on"
end end
@sort = order_by[0]
if order_by.count == 1 @order = order_by[1]
sort += "#{Attachment.table_name}.#{attribute} asc " if attribute if order_by.count == 1 && attribute
elsif order_by.count == 2 sort += "#{Attachment.table_name}.#{attribute} asc "
sort += "#{Attachment.table_name}.#{attribute} #{order_by[1]} " if attribute && order_by[1] if sort_type != params[:sort].split(",").last
end sort += ","
if sort_type != params[:sort].split(",").last end
sort += "," elsif order_by.count == 2 && order_by[1]
sort += "#{Attachment.table_name}.#{attribute} #{order_by[1]} "
if sort_type != params[:sort].split(",").last
sort += ","
end
end end
end end
else
sort = "#{Attachment.table_name}.created_on desc"
end end
@containers = [ Project.includes(:attachments).find(@project.id)] @containers = [ Project.includes(:attachments).find(@project.id)]
@ -184,6 +261,8 @@ class FilesController < ApplicationController
attribute = "created_on" attribute = "created_on"
when "quotes" when "quotes"
attribute = "quotes" attribute = "quotes"
else
attribute = "created_on"
end end
@sort = order_by[0] @sort = order_by[0]
@order = order_by[1] @order = order_by[1]
@ -199,12 +278,16 @@ class FilesController < ApplicationController
end end
end end
end end
else
sort = "#{Attachment.table_name}.created_on desc"
end end
@containers = [ Course.includes(:attachments).reorder(sort).find(@course.id)] @containers = [ Course.includes(:attachments).reorder(sort).find(@course.id)]
show_attachments @containers show_attachments @containers
@tag_list = attachment_tag_list @all_attachments
render :layout => 'base_courses' render :layout => 'base_courses'
end end
@ -215,6 +298,11 @@ class FilesController < ApplicationController
@can_quote = attachment_candown @file @can_quote = attachment_candown @file
end end
def quote_resource_show_project
@file = Attachment.find(params[:id])
@can_quote = attachment_candown @file
end
def new def new
@versions = @project.versions.sort @versions = @project.versions.sort
@course_tag = @project.project_type @course_tag = @project.project_type
@ -241,7 +329,7 @@ class FilesController < ApplicationController
render_attachment_warning_if_needed(container) render_attachment_warning_if_needed(container)
if !attachments.empty? && !attachments[:files].blank? && Setting.notified_events.include?('file_added') if !attachments.empty? && !attachments[:files].blank? && Setting.notified_events.include?('file_added')
Mailer.attachments_added(attachments[:files]).deliver Mailer.run.attachments_added(attachments[:files])
end end
# TODO: 临时用 nyan # TODO: 临时用 nyan
@ -270,7 +358,28 @@ class FilesController < ApplicationController
attachments = Attachment.attach_filesex(@course, params[:attachments], params[:attachment_type]) attachments = Attachment.attach_filesex(@course, params[:attachments], params[:attachment_type])
if !attachments.empty? && !attachments[:files].blank? && Setting.notified_events.include?('file_added') if !attachments.empty? && !attachments[:files].blank? && Setting.notified_events.include?('file_added')
Mailer.attachments_added(attachments[:files]).deliver Mailer.run.attachments_added(attachments[:files])
end
if params[:course_attachment_type] && params[:course_attachment_type] != "5"
case params[:course_attachment_type]
when "1"
tag_name = l(:label_courseware)
when "2"
tag_name = l(:label_software)
when "3"
tag_name = l(:label_media)
when "4"
tag_name = l(:label_code)
else
tag_name = ""
end
if !attachments.empty? && attachments[:files] && tag_name != ""
attachments[:files].each do |attachment|
attachment.tag_list.add(tag_name)
attachment.save
end
end
end end
# TODO: 临时用 nyan # TODO: 临时用 nyan
@ -283,6 +392,7 @@ class FilesController < ApplicationController
@containers = [Course.includes(:attachments).reorder("#{Attachment.table_name}.created_on DESC").find(@course.id)] @containers = [Course.includes(:attachments).reorder("#{Attachment.table_name}.created_on DESC").find(@course.id)]
show_attachments @containers show_attachments @containers
@tag_list = attachment_tag_list @all_attachments
@attachtype = 0 @attachtype = 0
@contenttype = 0 @contenttype = 0
@ -416,8 +526,31 @@ class FilesController < ApplicationController
format.html format.html
end end
end end
end
#查找指定TAG的按条件过滤的资源列表只有课程内搜索有此功能
def search_tag_attachment
@q,@tag_name,@order = params[:q],params[:tag_name]
@is_remote = true
if params[:sort]
order_by = params[:sort].split(":")
@sort = order_by[0]
if order_by.count > 1
@order = order_by[1]
end
sort = "#{@sort} #{@order}"
end
q = "%#{@q.strip}%"
@result = find_course_attache q,@course,sort
@result = visable_attachemnts @result
@result = @result.select{|attachment| attachment.tag_list.include?(@tag_name)}
@searched_attach = paginateHelper @result,10
@tag_list = get_course_tag_list @course
respond_to do |format|
format.js
# format.html
end
end end
end end

@ -63,8 +63,10 @@ class ForumsController < ApplicationController
respond_to do |format| respond_to do |format|
if @memo.save if @memo.save
ids = params[:asset_id].split(',') if params[:asset_id]
update_kindeditor_assets_owner ids ,@memo.id,1 ids = params[:asset_id].split(',')
update_kindeditor_assets_owner ids ,@memo.id,OwnerTypeHelper::MEMO
end
#end #end
format.html { redirect_to (forum_memo_url(@forum, (@memo.parent_id.nil? ? @memo : @memo.parent_id))), notice: "#{l :label_memo_create_succ}" } format.html { redirect_to (forum_memo_url(@forum, (@memo.parent_id.nil? ? @memo : @memo.parent_id))), notice: "#{l :label_memo_create_succ}" }
format.json { render json: @memo, status: :created, location: @memo } format.json { render json: @memo, status: :created, location: @memo }
@ -170,8 +172,10 @@ class ForumsController < ApplicationController
# Author lizanle # Author lizanle
# Description after save后需要进行资源记录的更新 # Description after save后需要进行资源记录的更新
# owner_type = 2 对应的是 forum # owner_type = 2 对应的是 forum
ids = params[:asset_id].split(',') if params[:asset_id]
update_kindeditor_assets_owner ids ,@forum.id,2 ids = params[:asset_id].split(',')
update_kindeditor_assets_owner ids ,@forum.id,OwnerTypeHelper::FORUM
end
#end #end
respond_to do |format| respond_to do |format|

@ -22,6 +22,7 @@ class HomeworkAttachController < ApplicationController
#获取未批作业列表 #获取未批作业列表
def get_not_batch_homework def get_not_batch_homework
@not_batch_homework = true @not_batch_homework = true
@search_name = params[:name]
sort, direction = params[:sort] || "s_socre", params[:direction] || "desc" sort, direction = params[:sort] || "s_socre", params[:direction] || "desc"
get_not_batch_homework_list sort,direction, @bid.id get_not_batch_homework_list sort,direction, @bid.id
@cur_page = params[:page] || 1 @cur_page = params[:page] || 1
@ -39,6 +40,7 @@ class HomeworkAttachController < ApplicationController
#获取已评作业列表 #获取已评作业列表
def get_batch_homeworks def get_batch_homeworks
@search_name = params[:name]
sort, direction = params[:sort] || "s_socre", params[:direction] || "desc" sort, direction = params[:sort] || "s_socre", params[:direction] || "desc"
@is_batch_homeworks = true @is_batch_homeworks = true
if sort == 't_socre' if sort == 't_socre'
@ -49,14 +51,16 @@ class HomeworkAttachController < ApplicationController
order_by = "created_at #{direction}" order_by = "created_at #{direction}"
end end
all_homework_list = HomeworkAttach.eager_load(:attachments,:user,:rate_averages).find_by_sql("SELECT * FROM (SELECT homework_attaches.*, 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 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 AND stars > 0 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 (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} FROM homework_attaches WHERE bid_id = #{@bid.id}
ORDER BY #{order_by}) AS table1 ORDER BY #{order_by}) AS table1
WHERE table1.t_score IS NOT NULL") WHERE table1.t_score IS NOT NULL")
all_homework_list = search_homework_member(all_homework_list,@search_name.to_s.downcase) if @search_name
@cur_page = params[:page] || 1 @cur_page = params[:page] || 1
@cur_type = 2 @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' @direction = direction == 'asc'? 'desc' : 'asc'
respond_to do |format| respond_to do |format|
format.js format.js
@ -72,6 +76,7 @@ class HomeworkAttachController < ApplicationController
#获取所有作业列表 #获取所有作业列表
def get_homeworks def get_homeworks
@is_all_homeworks = true @is_all_homeworks = true
@search_name = params[:name]
sort, direction = params[:sort] || "s_socre", params[:direction] || "desc" sort, direction = params[:sort] || "s_socre", params[:direction] || "desc"
if sort == 't_socre' if sort == 't_socre'
order_by = "t_score #{direction}" order_by = "t_score #{direction}"
@ -85,9 +90,12 @@ 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 (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} FROM homework_attaches WHERE bid_id = #{@bid.id}
ORDER BY #{order_by}") ORDER BY #{order_by}")
all_homework_list = search_homework_member(all_homework_list,@search_name.to_s.downcase) if @search_name
@cur_page = params[:page] || 1 @cur_page = params[:page] || 1
@cur_type = 3 @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' @direction = direction == 'asc'? 'desc' : 'asc'
respond_to do |format| respond_to do |format|
format.js format.js
@ -104,7 +112,8 @@ class HomeworkAttachController < ApplicationController
all_homework_list = get_student_batch_homework_list @bid,User.current all_homework_list = get_student_batch_homework_list @bid,User.current
@cur_page = params[:page] || 1 @cur_page = params[:page] || 1
@cur_type = 4 @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| respond_to do |format|
format.js format.js
end end
@ -128,7 +137,8 @@ class HomeworkAttachController < ApplicationController
WHERE homework_attaches.bid_id = #{@bid.id} AND homework_users.user_id = #{User.current.id}") WHERE homework_attaches.bid_id = #{@bid.id} AND homework_users.user_id = #{User.current.id}")
end end
@cur_page = params[:page] || 1 @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| respond_to do |format|
format.js format.js
end end
@ -308,7 +318,7 @@ class HomeworkAttachController < ApplicationController
def edit def edit
bid = @homework.bid bid = @homework.bid
if (bid.comment_status == 0 || bid.open_anonymous_evaluation == 0) && (User.current.admin? || User.current.member_of_course?(bid.courses.first)) if (bid.comment_status == 0 || bid.open_anonymous_evaluation == 0 || bid.comment_status == 2) && (User.current.admin? || User.current.member_of_course?(bid.courses.first))
get_homework_member @homework get_homework_member @homework
else else
render_403 :message => :notice_not_authorized render_403 :message => :notice_not_authorized
@ -341,7 +351,7 @@ class HomeworkAttachController < ApplicationController
def destroy def destroy
bid = @homework.bid bid = @homework.bid
if (bid.comment_status == 0 || bid.open_anonymous_evaluation == 0) && (User.current.admin? || User.current == @homework.user) if (bid.comment_status == 0 || bid.open_anonymous_evaluation == 0 || bid.comment_status == 0) && (User.current.admin? || User.current == @homework.user)
if @homework.destroy if @homework.destroy
#respond_to do |format| #respond_to do |format|
# format.html { redirect_to course_for_bid_url @homework.bid } # format.html { redirect_to course_for_bid_url @homework.bid }
@ -434,14 +444,15 @@ class HomeworkAttachController < ApplicationController
homework = @homework homework = @homework
is_teacher = @is_teacher ? 1 : 0 is_teacher = @is_teacher ? 1 : 0
#保存评分@homework.rate(@m_score.to_i,User.current.id,:quality, (@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 @m_score && (@is_teacher || @is_anonymous_comments)
rate = @homework.rates(:quality).where(:rater_id => User.current.id, :is_teacher_score => is_teacher).first rate = @homework.rates(:quality).where(:rater_id => User.current.id, :is_teacher_score => is_teacher).first
if rate if rate
rate.stars = @m_score rate.stars = @m_score
rate.save!
else 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 end
rate.save!
if homework.is_teacher_score == 0 if homework.is_teacher_score == 0
if is_teacher == 1 if is_teacher == 1
@ -459,12 +470,26 @@ class HomeworkAttachController < ApplicationController
end end
end end
homework.save! homework.save!
end end
#保存评论 #保存评论
@is_comprehensive_evaluation = @is_teacher ? 1 : (@is_anonymous_comments ? 2 : 3) #判断当前评论是老师评论?匿评?留言 if params[:new_form] && params[:new_form][:user_message] #有没有留言
if params[:new_form] && params[:new_form][:user_message] && 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
@homework.addjours User.current.id, params[:new_form][:user_message],0,@is_comprehensive_evaluation 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 end
@teacher_stars = @stars_reates.where("is_teacher_score = 1") #老师评分列表 @teacher_stars = @stars_reates.where("is_teacher_score = 1") #老师评分列表
@ -477,7 +502,7 @@ class HomeworkAttachController < ApplicationController
get_not_batch_homework_list params[:cur_sort] || "s_socre",params[:cur_direction] || "desc",@homework.bid_id get_not_batch_homework_list params[:cur_sort] || "s_socre",params[:cur_direction] || "desc",@homework.bid_id
elsif @cur_type == "2" #老师已批列表 elsif @cur_type == "2" #老师已批列表
@result_homework = HomeworkAttach.find_by_sql("SELECT homework_attaches.*, @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 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 AND stars > 0 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 (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 FROM homework_attaches WHERE id = #{@homework.id}").first
elsif @cur_type == "3" #全部作业列表 elsif @cur_type == "3" #全部作业列表
@ -538,6 +563,14 @@ class HomeworkAttachController < ApplicationController
end end
private private
#根据条件过滤作业结果
def search_homework_member homeworks,name
select_homework = homeworks.select{ |homework|
homework.user[:login].to_s.downcase.include?(name) || homework.user.user_extensions[:student_id].to_s.downcase.include?(name) || (homework.user[:lastname].to_s.downcase + homework.user[:firstname].to_s.downcase).include?(name)
}
select_homework
end
#验证是否显示课程 #验证是否显示课程
def can_show_course def can_show_course
@first_page = FirstPage.find_by_page_type('project') @first_page = FirstPage.find_by_page_type('project')
@ -596,8 +629,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 (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} FROM homework_attaches WHERE bid_id = #{bid_id}
ORDER BY #{order_by}) AS table1 ORDER BY #{order_by}) AS table1
WHERE table1.t_score IS NULL") WHERE table1.t_score IS NULL OR table1.t_score = 0 ")
@homework_list = paginateHelper @all_homework_list,10 @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 = @all_homework_list
end end
#获取指定作业的所有成员 #获取指定作业的所有成员

@ -95,6 +95,7 @@ class IssuesController < ApplicationController
format.api { format.api {
Issue.load_visible_relations(@issues) if include_in_api_response?('relations') 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.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.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') } format.pdf { send_data(issues_to_pdf(@issues, @project, @query), :type => 'application/pdf', :filename => 'issues.pdf') }

@ -60,8 +60,12 @@ class MembersController < ApplicationController
user_ids.each do |user_id| user_ids.each do |user_id|
AppliedProject.deleteappiled(user_id, @project.id) AppliedProject.deleteappiled(user_id, @project.id)
end end
@succes_message = "拒绝成功"
end end
end end
respond_to do |format|
format.js
end
else else
#modify by nwb #modify by nwb
#更改课程成员逻辑 #更改课程成员逻辑
@ -117,9 +121,14 @@ class MembersController < ApplicationController
format.html { redirect_to invite_members_project_url(@project) } format.html { redirect_to invite_members_project_url(@project) }
end end
else 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| respond_to do |format|
format.html { redirect_to_settings_in_projects } format.html { redirect_to_settings_in_projects }
format.js { @members = members; @applied_members = applied_members; } format.js
format.api { format.api {
@member = members.first @member = members.first
if @member.valid? if @member.valid?
@ -133,6 +142,9 @@ class MembersController < ApplicationController
elsif @course elsif @course
course_info = [] course_info = []
if params[:membership] if params[:membership]
@create_member_error_messages = "角色不能留空" unless params[:membership][:role_ids]
@create_member_error_messages = "用户不能留空" unless params[:membership][:user_ids]
if params[:membership][:user_ids] if params[:membership][:user_ids]
attrs = params[:membership].dup attrs = params[:membership].dup
user_ids = attrs.delete(:user_ids) user_ids = attrs.delete(:user_ids)
@ -140,7 +152,7 @@ class MembersController < ApplicationController
member = Member.new(:role_ids => params[:membership][:role_ids], :user_id => user_id) member = Member.new(:role_ids => params[:membership][:role_ids], :user_id => user_id)
role = Role.find_by_id(params[:membership][:role_ids]) role = Role.find_by_id(params[:membership][:role_ids])
# 这里的判断只能通过角色名,可以弄成常量 # 这里的判断只能通过角色名,可以弄成常量
if role.name == "学生" || role.name == "Student" if role && (role.name == "学生" || role.name == "Student")
StudentsForCourse.create(:student_id => user_id, :course_id =>@course.id) StudentsForCourse.create(:student_id => user_id, :course_id =>@course.id)
end end
members << member members << member
@ -159,6 +171,11 @@ class MembersController < ApplicationController
end end
@course.members << members @course.members << members
@course.course_infos << course_info @course.course_infos << course_info
@roles = Role.givable.all[3..5]
members = @course.member_principals.includes(:roles, :principal).all.sort
else
@create_member_error_messages = l(:label_user_role_null)
end end
respond_to do |format| respond_to do |format|
format.html { redirect_to_settings_in_courses } format.html { redirect_to_settings_in_courses }
@ -176,6 +193,8 @@ class MembersController < ApplicationController
end # end of params[:refusal_button] end # end of params[:refusal_button]
end end
def update def update
@ -242,6 +261,9 @@ class MembersController < ApplicationController
end end
end end
end end
@roles = Role.givable.all[3..5]
@members = @course.member_principals.includes(:roles, :principal).all.sort
@member = @course.members.new
end end
saved = @member.save saved = @member.save
@ -304,7 +326,8 @@ class MembersController < ApplicationController
joined.each do |join| joined.each do |join|
join.delete join.delete
end end
@roles = Role.givable.all[3..5]
@members = @course.member_principals.includes(:roles, :principal).all.sort
end end
respond_to do |format| respond_to do |format|
format.html { redirect_to_settings_in_courses } format.html { redirect_to_settings_in_courses }

@ -86,6 +86,11 @@ class MessagesController < ApplicationController
if request.post? if request.post?
@message.save_attachments(params[:attachments]) @message.save_attachments(params[:attachments])
if @message.save if @message.save
# 更新kindeditor上传的图片资源所有者
if params[:asset_id]
ids = params[:asset_id].split(',')
update_kindeditor_assets_owner ids,@message.id,OwnerTypeHelper::MESSAGE
end
call_hook(:controller_messages_new_after_save, { :params => params, :message => @message}) call_hook(:controller_messages_new_after_save, { :params => params, :message => @message})
render_attachment_warning_if_needed(@message) render_attachment_warning_if_needed(@message)
redirect_to board_message_url(@board, @message) redirect_to board_message_url(@board, @message)
@ -117,6 +122,10 @@ class MessagesController < ApplicationController
@topic.children << @reply @topic.children << @reply
#@topic.update_attribute(:updated_on, Time.now) #@topic.update_attribute(:updated_on, Time.now)
if !@reply.new_record? if !@reply.new_record?
if params[:asset_id]
ids = params[:asset_id].split(',')
update_kindeditor_assets_owner ids,@reply.id,OwnerTypeHelper::MESSAGE
end
call_hook(:controller_messages_reply_after_save, { :params => params, :message => @reply}) call_hook(:controller_messages_reply_after_save, { :params => params, :message => @reply})
attachments = Attachment.attach_files(@reply, params[:attachments]) attachments = Attachment.attach_files(@reply, params[:attachments])
render_attachment_warning_if_needed(@reply) render_attachment_warning_if_needed(@reply)
@ -183,16 +192,7 @@ class MessagesController < ApplicationController
@content = "> #{ll(Setting.default_language, :text_user_wrote, @message.author)}\n> " @content = "> #{ll(Setting.default_language, :text_user_wrote, @message.author)}\n> "
@temp = Message.new @temp = Message.new
#@temp.content = "> #{ll(Setting.default_language, :text_user_wrote, @message.author)}> " @temp.content = "<blockquote>#{ll(Setting.default_language, :text_user_wrote, @message.author)} <br/>#{@message.content.html_safe}</blockquote>".html_safe
@content << @message.content.to_s.strip.gsub(%r{<pre>((.|\s)*?)</pre>}m, '[...]').gsub(/(\r?\n|\r\n?)/, "\n> ") + "\n\n"
@content_html = textilizable(@content)
@temp.content = @content_html
#@content = "#{ll(Setting.default_language, :text_user_wrote, @message.author)} <br/> &nbsp; "
#@content << @message.content.to_s.strip.gsub(%r{<pre>((.|\s)*?)</pre>}m, '[...]').gsub(/(\r?\n|\r\n?)/, "\n") + "</blockquote>\n\n<br/>"
#@content = "<blockquote>" << @content
#@temp = Message.new
#@temp.content = @content
end end
def preview def preview

@ -20,7 +20,7 @@ class MyController < ApplicationController
# edit # edit
before_filter :auth_login1, :only => [:account] before_filter :auth_login1, :only => [:account]
# #
before_filter :require_login before_filter :require_login, except: [:change_mail_notification]
helper :issues helper :issues
helper :users helper :users
@ -75,6 +75,19 @@ class MyController < ApplicationController
end end
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 # Edit user's account
def account def account
@user = User.current @user = User.current

@ -17,6 +17,7 @@
class NewsController < ApplicationController class NewsController < ApplicationController
layout 'base_projects'# by young layout 'base_projects'# by young
include ApplicationHelper
before_filter :authorize1, :only => [:show] before_filter :authorize1, :only => [:show]
default_search_scope :news default_search_scope :news
model_object News model_object News
@ -136,6 +137,10 @@ class NewsController < ApplicationController
@news.safe_attributes = params[:news] @news.safe_attributes = params[:news]
@news.save_attachments(params[:attachments]) @news.save_attachments(params[:attachments])
if @news.save if @news.save
if params[:asset_id]
ids = params[:asset_id].split(',')
update_kindeditor_assets_owner ids,@news.id,OwnerTypeHelper::NEWS
end
render_attachment_warning_if_needed(@news) render_attachment_warning_if_needed(@news)
flash[:notice] = l(:notice_successful_create) flash[:notice] = l(:notice_successful_create)
redirect_to course_news_index_url(@course) redirect_to course_news_index_url(@course)
@ -147,6 +152,9 @@ class NewsController < ApplicationController
end end
def edit def edit
if @course
render :layout => "base_courses"
end
end end
def update def update

@ -29,7 +29,7 @@ class PollController < ApplicationController
end end
#已提交问卷的用户不能再访问该界面 #已提交问卷的用户不能再访问该界面
if has_commit_poll?(@poll.id,User.current.id) && (!User.current.admin?) 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 else
@can_edit_poll = (!has_commit_poll?(@poll.id,User.current.id)) || User.current.admin? @can_edit_poll = (!has_commit_poll?(@poll.id,User.current.id)) || User.current.admin?
@percent = get_percent(@poll,User.current) @percent = get_percent(@poll,User.current)

@ -27,15 +27,7 @@ class ProjectsController < ApplicationController
menu_item :feedback, :only => :feedback menu_item :feedback, :only => :feedback
menu_item :share, :only => :share 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 :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, :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 :authorize_global, :only => [:new, :create,:view_homework_attaches]
before_filter :require_admin, :only => [ :copy, :archive, :unarchive, :destroy, :calendar] before_filter :require_admin, :only => [ :copy, :archive, :unarchive, :destroy, :calendar]
@ -181,6 +173,7 @@ class ProjectsController < ApplicationController
@project.safe_attributes = params[:project] @project.safe_attributes = params[:project]
@project.organization_id = params[:organization_id] @project.organization_id = params[:organization_id]
@project.user_id = User.current.id @project.user_id = User.current.id
@project.project_new_type = 1
if validate_parent_id && @project.save if validate_parent_id && @project.save
@project.set_allowed_parent!(params[:project]['parent_id']) if params[:project].has_key?('parent_id') @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 # Add current user as a project member if he is not admin
@ -250,18 +243,13 @@ class ProjectsController < ApplicationController
# Author lizanle # Author lizanle
# Description 项目动态展示方法,删除了不必要的代码 # Description 项目动态展示方法,删除了不必要的代码
def show def show
# params[:login]为邮箱邀请用户加入,主要功能:
# 试图跳转到请求的按钮 # 1、自动注册
if params[:login] # 2、加入项目、创建角色
login = params[:login] # 3、用户得分
login = login.sub(/%40/,'@') if params[:email]
mail = params[:login] user = User.find_by_mail(params[:email].to_s)
password = params[:password]
us = UsersService.new
user = us.register_auto(login,mail, password)
Member.create(:role_ids => [4], :user_id => user.id,:project_id => @project.id) 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 end
if params[:jump] && redirect_to_project_menu_item(@project, params[:jump]) if params[:jump] && redirect_to_project_menu_item(@project, params[:jump])
return return
@ -331,14 +319,46 @@ class ProjectsController < ApplicationController
@member ||= @project.members.new @member ||= @project.members.new
@trackers = Tracker.sorted.all @trackers = Tracker.sorted.all
@wiki ||= @project.wiki @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 end
# 两种情况1、系统外用户2、系统内用户 (通过邮件判定)
def send_mail_to_member def send_mail_to_member
if !params[:mail].blank? && User.find_by_mail(params[:mail].to_s).nil? if !params[:mail].blank? && User.find_by_mail(params[:mail].to_s).nil?
email = params[:mail] email = params[:mail]
Mailer.send_invite_in_project(email, @project, User.current).deliver Mailer.run.send_invite_in_project(email, @project, User.current)
@is_zhuce =false @is_zhuce =false
flash[:notice] = l(:notice_email_sent, :value => email) 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 else
flash[:error] = l(:notice_registed_error, :value => email) flash[:error] = l(:notice_registed_error, :value => email)
@is_zhuce = true @is_zhuce = true
@ -347,6 +367,7 @@ class ProjectsController < ApplicationController
format.html{redirect_to invite_members_by_mail_project_url(@project)} format.html{redirect_to invite_members_by_mail_project_url(@project)}
end end
end end
#发送邮件邀请新用户 #发送邮件邀请新用户
def invite_members_by_mail def invite_members_by_mail
if User.current.member_of?(@project) || User.current.admin? if User.current.member_of?(@project) || User.current.admin?
@ -379,7 +400,7 @@ class ProjectsController < ApplicationController
# include CoursesHelper # include CoursesHelper
def member def member
## 有角色参数的才是课程,没有的就是项目 ## 有角色参数的才是课程,没有的就是项目
@render_file = 'member_list' @render_file = 'project_member_list'
# 判断是否课程 # 判断是否课程
if @project.project_type == Project::ProjectType_course if @project.project_type == Project::ProjectType_course
@teachers= searchTeacherAndAssistant(@project) @teachers= searchTeacherAndAssistant(@project)
@ -455,22 +476,10 @@ class ProjectsController < ApplicationController
def update def update
@project.safe_attributes = params[:project] @project.safe_attributes = params[:project]
@project.organization_id = params[:organization_id] @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 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') @project.set_allowed_parent!(params[:project]['parent_id']) if params[:project].has_key?('parent_id')
if params[:project][:is_public] == '0' if params[:project][:is_public] == '0'
project_status = ProjectStatus.find_by_project_id(@project.id) project_status = ProjectStatus.find_by_project_id(@project.id)
project_status.destroy if project_status project_status.destroy if project_status
@ -618,6 +627,17 @@ class ProjectsController < ApplicationController
end end
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 private
def memberAccess def memberAccess

@ -25,6 +25,7 @@ class ChangesetNotFound < Exception; end
class InvalidRevisionParam < Exception; end class InvalidRevisionParam < Exception; end
class RepositoriesController < ApplicationController class RepositoriesController < ApplicationController
include ApplicationHelper
menu_item :repository menu_item :repository
menu_item :settings, :only => [:new, :create, :edit, :update, :destroy, :committers] menu_item :settings, :only => [:new, :create, :edit, :update, :destroy, :committers]
default_search_scope :changesets default_search_scope :changesets
@ -122,7 +123,7 @@ update
if request.post? && @repository.save if request.post? && @repository.save
redirect_to settings_project_url(@project, :tab => 'repositories') redirect_to settings_project_url(@project, :tab => 'repositories')
else else
render :action => 'new' redirect_to settings_project_url(@project, :tab => 'repositories')
end end
else # 原逻辑 else # 原逻辑
##xianbo ##xianbo
@ -131,7 +132,7 @@ update
@project_path=@root_path+"htdocs/"+@repository_name @project_path=@root_path+"htdocs/"+@repository_name
@repository_tag=params[:repository][:upassword] || params[:repository][:password] @repository_tag=params[:repository][:upassword] || params[:repository][:password]
@repo_name=User.current.login.to_s+"_"+params[:repository][:identifier] @repo_name=User.current.login.to_s+"_"+params[:repository][:identifier]
logger.info "htpasswd -mb "+@root_path+"user.passwd "+@repo_name+": "+@repository_tag logger.info "htpasswd -mb "+@root_path+"htdocs/user.passwd "+@repo_name+": "+@repository_tag
logger.info "the value of create repository"+@root_path+": "+@repository_name+": "+@project_path+": "+@repo_name logger.info "the value of create repository"+@root_path+": "+@repository_name+": "+@project_path+": "+@repo_name
attrs = pickup_extra_info attrs = pickup_extra_info
if((@repository_tag!="")&&params[:repository_scm]=="Git") if((@repository_tag!="")&&params[:repository_scm]=="Git")
@ -147,9 +148,9 @@ update
@repository.project = @project @repository.project = @project
if request.post? && @repository.save if request.post? && @repository.save
if(params[:repository_scm]=="Git") if(params[:repository_scm]=="Git")
system "htpasswd -mb "+@root_path+"user.passwd "+@repo_name+" "+@repository_tag system "htpasswd -mb "+@root_path+"htdocs/user.passwd "+@repo_name+" "+@repository_tag
system "echo -e '"+@repo_name+"-write:"+ system "echo -e '"+@repo_name+"-write:"+
" "+@repo_name+"' >> "+@root_path+"group.passwd" " "+@repo_name+"' >> "+@root_path+"htdocs/group.passwd"
system "mkdir "+@root_path+"htdocs/"+User.current.login.to_s system "mkdir "+@root_path+"htdocs/"+User.current.login.to_s
system "git init --bare "+@project_path system "git init --bare "+@project_path
system "mv "+@project_path+"/hooks/post-update{.sample,}" system "mv "+@project_path+"/hooks/post-update{.sample,}"
@ -167,11 +168,12 @@ update
@repository.update_attributes(:login => User.current.login.to_s) @repository.update_attributes(:login => User.current.login.to_s)
end end
redirect_to settings_project_url(@project, :tab => 'repositories') redirect_to settings_project_url(@project, :tab => 'repositories',:repository_error_message=>@repository.errors.full_messages)
else if(@repository_tag) else if(@repository_tag.blank?)
render :action => 'newrepo', :layout =>'base_projects' #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 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
end end
@ -234,24 +236,10 @@ update
end end
def destroy def destroy
@root_path=RepositoriesHelper::ROOT_PATH DestroyRepositoryTask.new.destroy(User.current.id, @repository.id)
@repo_name=User.current.login.to_s+"_"+@repository.identifier.to_s @repository.hidden = true
@repository_name=User.current.login.to_s+"/"+@repository.identifier.to_s+".git" @repository.save
@middle=User.current.login.to_s+"_"+@repository.identifier.to_s+"-write:"
@repository.destroy if request.delete?
redirect_to settings_project_url(@project, :tab => 'repositories') 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+"user.passwd"
system "sed -i /"+@middle+"/{d} "+@root_path+"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 end
def show def show

@ -29,6 +29,9 @@ class SettingsController < ApplicationController
end end
def edit def edit
hidden_non_project = Setting.find_by_name("hidden_non_project")
@text = (hidden_non_project && hidden_non_project.value == "0") ? l(:label_show_non_project) : l(:label_hidden_non_project)
@notifiables = Redmine::Notifiable.all @notifiables = Redmine::Notifiable.all
if request.post? && params[:settings] && params[:settings].is_a?(Hash) if request.post? && params[:settings] && params[:settings].is_a?(Hash)
settings = (params[:settings] || {}).dup.symbolize_keys settings = (params[:settings] || {}).dup.symbolize_keys
@ -70,4 +73,20 @@ class SettingsController < ApplicationController
rescue Redmine::PluginNotFound rescue Redmine::PluginNotFound
render_404 render_404
end end
#隐藏/显示非项目信息
def hidden_non_project
@notifiable = Setting.find_by_name("hidden_non_project")
if @notifiable
@notifiable.value == "1" ? @notifiable.value = 0 : @notifiable.value = 1
@notifiable.save
else
@notifiable = Setting.new()
@notifiable.name = "hidden_non_project"
@notifiable.value = 0
@notifiable.save
end
redirect_to settings_url
end
end end

@ -220,11 +220,18 @@ class TagsController < ApplicationController
@tag = ActsAsTaggableOn::Tag.find_by_id(@tag_id) @tag = ActsAsTaggableOn::Tag.find_by_id(@tag_id)
@tag.delete unless @tag.nil? @tag.delete unless @tag.nil?
end end
if @obj && @object_flag == '6' && @obj.container.kind_of?(Course)
@course = @obj.container
@tag_list = get_course_tag_list @course
@select_tag_name = params[:select_tag_name]
end
# end # end
end end
end end
def tag_save def tag_save
@select_tag_name = params[:tag_for_save][:tag_name]
@tags = params[:tag_for_save][:name] @tags = params[:tag_for_save][:name]
@obj_id = params[:tag_for_save][:object_id] @obj_id = params[:tag_for_save][:object_id]
@obj_flag = params[:tag_for_save][:object_flag] @obj_flag = params[:tag_for_save][:object_flag]
@ -263,6 +270,10 @@ class TagsController < ApplicationController
else else
logger.error "#{__FILE__}:#{__LINE__} ===> #{@obj.errors.try(:full_messages)}" logger.error "#{__FILE__}:#{__LINE__} ===> #{@obj.errors.try(:full_messages)}"
end end
if @obj && @obj_flag == '6' && @obj.container.kind_of?(Course)
@course = @obj.container
@tag_list = @tag_list = get_course_tag_list @course
end
respond_to do |format| respond_to do |format|
format.js format.js
format.html format.html

@ -57,5 +57,98 @@ class TestController < ApplicationController
attach.filename attach.filename
end 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 end

@ -438,13 +438,84 @@ class UsersController < ApplicationController
# Description 所有动态 # Description 所有动态
where_condition = nil; where_condition = nil;
# where_condition = "act_type <> 'JournalsForMessage'" # where_condition = "act_type <> 'JournalsForMessage'"
user_ids = []
if @user == User.current if @user == User.current
watcher = User.watched_by(@user) watcher = User.watched_by(@user)
watcher.push(User.current) watcher.push(User.current)
activity = Activity.where(where_condition).where('user_id in (?)', watcher).order('id desc') user_ids = watcher.map{|x| x.id}
else else
activity = Activity.where(where_condition).where('user_id = ?', @user.id).order('id desc') user_ids << @user.id
end end
activity = Activity.where(where_condition).where(user_id: user_ids).order('id desc')
permission = !User.current.admin?
if permission
#Issue
act_ids = activity.where(act_type: 'Issue').select('act_id').map{|x| x.act_id}
project_ids = Issue.where(id: act_ids).select('distinct project_id').map{|x| x.project_id}
p_ids = []
Project.where(id: project_ids).each do |x|
p_ids << x.id unless x.visible?(User.current)
end
ids = []
ids << Issue.where(id: act_ids, project_id: p_ids).map{|x| x.id}
#Bid
act_ids = activity.where(act_type: 'Bid').select('act_id').map{|x| x.act_id}
course_ids = HomeworkForCourse.where(bid_id: act_ids).select('distinct course_id').map{|x| x.course_id}
c_ids = []
Course.where(id: course_ids).each do |x|
c_ids << x.id unless x.is_public !=0 && User.current.member_of_course?(x)
end
ids << HomeworkForCourse.where(bid_id: act_ids, course_id: c_ids).map{|x| x.id}
#Journal
act_ids = activity.where(act_type: 'Journal').select('act_id').map{|x| x.act_id}
project_ids = Journal.where(id:act_ids, journalized_type: 'Project').select('distinct journalized_id').map{|x| x.journalized_id}
p_ids = []
Project.where(id: project_ids).each do |x|
p_ids << x.id unless x.visible?(User.current)
end
ids << Journal.where(id: act_ids, journalized_id: p_ids, journalized_type: 'Project').map{|x| x.id}
#News
act_ids = activity.where(act_type: 'News').select('act_id').map{|x| x.act_id}
project_ids = News.where(id: act_ids).select('distinct project_id').map{|x| x.project_id}
p_ids = []
Project.where(id: project_ids).each do |x|
p_ids << x.id unless x.visible?(User.current)
end
ids << News.where(id: act_ids, project_id: p_ids).map{|x| x.id}
project_ids = News.where(id: act_ids).select('distinct course_id').map{|x| x.course_id}
c_ids = []
Course.where(id: project_ids).each do |x|
c_ids << x.id unless x.is_public !=0 && User.current.member_of_course?(x)
end
ids << News.where(id: act_ids, course_id: p_ids).map{|x| x.id}
#Message
act_ids = activity.where(act_type: 'Message').select('act_id').map{|x| x.act_id}
board_ids = Message.where(id: act_ids).select('distinct board_id').map{|x| x.board_id}
project_ids = Board.where(id: board_ids).select('distinct project_id').map{|x| x.project_id}
p_ids = []
Project.where(id: project_ids).each do |x|
p_ids << x.id unless x.visible?(User.current)
end
ids << Message.where(id: act_ids, board_id: p_ids).map{|x| x.id}
project_ids = Board.where(id: board_ids).select('distinct course_id').map{|x| x.course_id}
c_ids = []
Course.where(id: project_ids).each do |x|
c_ids << x.id unless x.is_public !=0 && User.current.member_of_course?(x)
end
ids << Message.where(id: act_ids, board_id: c_ids).map{|x| x.id}
logger.debug "filter ids #{ids}"
activity = activity.where('act_id not in (?)', ids.flatten ).order('id desc') unless ids.flatten.empty?
end
# activity = activity.reject { |e| # activity = activity.reject { |e|
# e.act.nil? || # e.act.nil? ||
# (!User.current.admin? && !e.act.nil? # (!User.current.admin? && !e.act.nil?
@ -454,14 +525,11 @@ class UsersController < ApplicationController
# (e.act_type == "News" && ((!e.act.project.nil? && !e.act.project.visible?(User.current)) || (!e.act.course.nil? && e.act.course.is_public == 0 && !User.current.member_of_course?(e.act.course)))) || # (e.act_type == "News" && ((!e.act.project.nil? && !e.act.project.visible?(User.current)) || (!e.act.course.nil? && e.act.course.is_public == 0 && !User.current.member_of_course?(e.act.course)))) ||
# (e.act_type == "Message" && !e.act.board.nil? && ((!e.act.board.project.nil? && !e.act.board.project.visible?(User.current)) || (!e.act.board.course.nil? && e.act.board.course.is_public == 0 && !User.current.member_of_course?(e.act.board.course)))))) # (e.act_type == "Message" && !e.act.board.nil? && ((!e.act.board.project.nil? && !e.act.board.project.visible?(User.current)) || (!e.act.board.course.nil? && e.act.board.course.is_public == 0 && !User.current.member_of_course?(e.act.board.course))))))
# } # }
#
@activity_count = activity.count @activity_count = activity.count
@activity_pages = Paginator.new @activity_count, pre_count, params['page'] @activity_pages = Paginator.new @activity_count, pre_count, params['page']
@activity = activity.slice(@activity_pages.offset,@activity_pages.per_page) @activity = activity.slice(@activity_pages.offset,@activity_pages.per_page)
# @activity = @activity.reject { |e|
# ((e.act_type=="Issue") && ( !e.act.visible?(User.current))) ||
# ((e.act_type == "Journal") && (!e.act.project.visible?(User.current))) ||
# ((e.act_type == "Bid") && ((!User.current.member_of_course?(e.act.courses.first) || !User.current.admin?)))
# }
@state = 0 @state = 0
end end
@ -553,7 +621,7 @@ class UsersController < ApplicationController
@user.pref.save @user.pref.save
@user.notified_project_ids = (@user.mail_notification == 'selected' ? params[:notified_project_ids] : []) @user.notified_project_ids = (@user.mail_notification == 'selected' ? params[:notified_project_ids] : [])
Mailer.account_information(@user, params[:user][:password]).deliver if params[:send_information] Mailer.run.account_information(@user, params[:user][:password]) if params[:send_information]
respond_to do |format| respond_to do |format|
format.html { format.html {
@ -620,9 +688,9 @@ class UsersController < ApplicationController
@user.notified_project_ids = (@user.mail_notification == 'selected' ? params[:notified_project_ids] : []) @user.notified_project_ids = (@user.mail_notification == 'selected' ? params[:notified_project_ids] : [])
if was_activated if was_activated
Mailer.account_activated(@user).deliver Mailer.run.account_activated(@user)
elsif @user.active? && params[:send_information] && !params[:user][:password].blank? && @user.auth_source_id.nil? elsif @user.active? && params[:send_information] && !params[:user][:password].blank? && @user.auth_source_id.nil?
Mailer.account_information(@user, params[:user][:password]).deliver Mailer.run.account_information(@user, params[:user][:password])
end end
respond_to do |format| respond_to do |format|

@ -85,13 +85,14 @@ class VersionsController < ApplicationController
end end
def new def new
@version = @project.versions.build # @version = @project.versions.build
@version.safe_attributes = params[:version] # @version.safe_attributes = params[:version]
#
respond_to do |format| # respond_to do |format|
format.html # format.html
format.js # format.js
end # end
redirect_to settings_project_url(@project, :tab => 'versions')
end end
def create def create
@ -116,7 +117,8 @@ class VersionsController < ApplicationController
end end
else else
respond_to do |format| 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.js { render :action => 'new' }
format.api { render_validation_errors(@version) } format.api { render_validation_errors(@version) }
end end
@ -136,7 +138,7 @@ class VersionsController < ApplicationController
respond_to do |format| respond_to do |format|
format.html { format.html {
flash[:notice] = l(:notice_successful_update) 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 } format.api { render_api_ok }
end end

@ -58,12 +58,18 @@ class WelcomeController < ApplicationController
else else
case @first_page.sort_type case @first_page.sort_type
when 0 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 = find_miracle_project(10, 3,"created_on desc")
#@projects = @projects_all.order("created_on desc") #@projects = @projects_all.order("created_on desc")
when 1 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 = find_miracle_project(10, 3,"score desc")
#@projects = @projects_all.order("grade desc") #@projects = @projects_all.order("grade desc")
when 2 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 = find_miracle_project(10, 3,"watchers_count desc")
#@projects = @projects_all.order("watchers_count desc") #@projects = @projects_all.order("watchers_count desc")

@ -1,7 +1,7 @@
# encoding: utf-8 # encoding: utf-8
#####leave message fq #####leave message fq
class WordsController < ApplicationController class WordsController < ApplicationController
include ApplicationHelper
before_filter :find_user, :only => [:new, :create, :destroy, :more, :back] before_filter :find_user, :only => [:new, :create, :destroy, :more, :back]
def create def create
if params[:new_form][:user_message].size>0 if params[:new_form][:user_message].size>0
@ -81,9 +81,10 @@ class WordsController < ApplicationController
@journal_destroyed = JournalsForMessage.delete_message(params[:object_id]) @journal_destroyed = JournalsForMessage.delete_message(params[:object_id])
if @journal_destroyed.jour_type == "Bid" if @journal_destroyed.jour_type == "Bid"
@bid = Bid.find(@journal_destroyed.jour_id) @bid = Bid.find(@journal_destroyed.jour_id)
end
if @bid
@jours_count = @bid.journals_for_messages.where('m_parent_id IS NULL').count @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 end
respond_to do |format| respond_to do |format|
format.js format.js
@ -209,6 +210,10 @@ class WordsController < ApplicationController
message = params[:new_form][:course_message] message = params[:new_form][:course_message]
feedback = Course.add_new_jour(user, message, params[:id]) feedback = Course.add_new_jour(user, message, params[:id])
if(feedback.errors.empty?) if(feedback.errors.empty?)
if params[:asset_id]
ids = params[:asset_id].split(',')
update_kindeditor_assets_owner ids,feedback[:id],OwnerTypeHelper::JOURNALSFORMESSAGE
end
redirect_to course_feedback_url(params[:id]), notice: l(:label_feedback_success) redirect_to course_feedback_url(params[:id]), notice: l(:label_feedback_success)
else else
flash[:error] = feedback.errors.full_messages[0] flash[:error] = feedback.errors.full_messages[0]

@ -5,24 +5,48 @@ class ZipdownController < ApplicationController
#检查权限 #检查权限
#勿删 before_filter :authorize, :only => [:assort,:download_user_homework] #勿删 before_filter :authorize, :only => [:assort,:download_user_homework]
SAVE_FOLDER = "#{Rails.root}/files" SAVE_FOLDER = "#{Rails.root}/files"
OUTPUT_FOLDER = "#{Rails.root}/tmp/archiveZip" OUTPUT_FOLDER = "#{Rails.root}/files/archiveZip"
#统一下载功能
def download
begin
send_file "#{OUTPUT_FOLDER}/#{params[:file]}", :filename => params[:filename], :type => detect_content_type(params[:file])
rescue => e
render file: 'public/no_file_found.html'
end
end
#一个作业下所有文件打包下载只有admin和课程老师有权限
def assort def assort
if params[:obj_class] == "Bid" if params[:obj_class] == "Bid"
bid = Bid.find params[:obj_id] bid = Bid.find params[:obj_id]
render_403 if User.current.allowed_to?(:as_teacher,bid.courses.first)
file_count = 0 file_count = 0
bid.homeworks.map { |homework| file_count += homework.attachments.count} bid.homeworks.map { |homework| file_count += homework.attachments.count}
if file_count > 0 if file_count > 0
zipfile = zip_bid bid zipfile = zip_bid bid
else else
render file: 'public/no_file_found.html' render file: 'public/no_file_found.html'
return
end end
else else
logger.error "[ZipDown#assort] ===> #{params[:obj_class]} unKown !!" logger.error "[ZipDown#assort] ===> #{params[:obj_class]} unKown !!"
end end
send_file zipfile, :filename => bid.name + ".zip", :type => detect_content_type(zipfile) if zipfile
# if zipfile
# if zipfile.length > 1
# @mut_down_files = zipfile #zipfile.each{|x| File.basename(x)}
# else
# send_file zipfile.first[:real_file], :filename => bid.name + ".zip", :type => detect_content_type(zipfile.first[:real_file])
# return
# end
# end
respond_to do |format|
format.json {
render json: zipfile.to_json
}
end
#rescue Exception => e #rescue Exception => e
# render file: 'public/no_file_found.html' # render file: 'public/no_file_found.html'
end end
@ -34,9 +58,9 @@ class ZipdownController < ApplicationController
if homework != nil if homework != nil
unless homework.attachments.empty? unless homework.attachments.empty?
zipfile = zip_homework_by_user homework zipfile = zip_homework_by_user homework
send_file zipfile, :filename => ((homework.user.user_extensions.nil? || homework.user.user_extensions.student_id.nil?) ? "" : homework.user.user_extensions.student_id) + send_file zipfile.file_path, :filename => ((homework.user.user_extensions.nil? || homework.user.user_extensions.student_id.nil?) ? "" : homework.user.user_extensions.student_id) +
"_" + (homework.user.lastname.nil? ? "" : homework.user.lastname) + (homework.user.firstname.nil? ? "" : homework.user.firstname) + "_" + (homework.user.lastname.nil? ? "" : homework.user.lastname) + (homework.user.firstname.nil? ? "" : homework.user.firstname) +
"_" + homework.name + ".zip", :type => detect_content_type(zipfile) if(zipfile) "_" + homework.name + ".zip", :type => detect_content_type(zipfile.file_path) if(zipfile)
else else
render file: 'public/no_file_found.html' render file: 'public/no_file_found.html'
end end
@ -66,68 +90,146 @@ class ZipdownController < ApplicationController
def zip_bid(bid) def zip_bid(bid)
# Todo: User Access Controll # Todo: User Access Controll
bid_homework_path = [] bid_homework_path = []
digests = []
bid.homeworks.each do |homeattach| bid.homeworks.each do |homeattach|
unless homeattach.attachments.empty? unless homeattach.attachments.empty?
bid_homework_path << zip_homework_by_user(homeattach) out_file = zip_homework_by_user(homeattach)
bid_homework_path << out_file.file_path
digests << out_file.file_digest
end end
end end
zipping "#{Time.now.to_i}_#{bid.name}.zip", bid_homework_path, OUTPUT_FOLDER
homework_id = bid.id
user_id = bid.author_id
out_file = find_or_pack(homework_id, user_id, digests.sort){
zipping("#{Time.now.to_i}_#{bid.name}.zip",
bid_homework_path, OUTPUT_FOLDER)
}
# zips = split_pack_files(bid_homework_path, Setting.pack_attachment_max_size.to_i*1024)
# x = 0
#
#
# zips.each { |o|
# x += 1
# file = zipping "#{Time.now.to_i}_#{bid.name}_#{x}.zip", o[:files], OUTPUT_FOLDER
# o[:real_file] = file
# o[:file] = File.basename(file)
# o[:size] = (File.size(file) / 1024.0 / 1024.0).round(2)
# }
[{files:[out_file.file_path], count: 1, index: 1,
real_file: out_file.file_path, file: File.basename(out_file.file_path),
size:(out_file.pack_size / 1024.0 / 1024.0).round(2)
}]
end end
def zip_homework_by_user(homeattach) def zip_homework_by_user(homework_attach)
homeworks_attach_path = [] homeworks_attach_path = []
not_exist_file = [] not_exist_file = []
# 需要将所有homework.attachments遍历加入zip # 需要将所有homework.attachments遍历加入zip
# 并且返回zip路径
homeattach.attachments.each do |attach|
digests = []
homework_attach.attachments.each do |attach|
if File.exist?(attach.diskfile) if File.exist?(attach.diskfile)
homeworks_attach_path << attach.diskfile homeworks_attach_path << attach.diskfile
digests << attach.digest
else else
not_exist_file << attach.filename not_exist_file << attach.filename
digests << 'not_exist_file'
end end
end end
zipping("#{homeattach.user.lastname}#{homeattach.user.firstname}_#{((homeattach.user.user_extensions.nil? || homeattach.user.user_extensions.student_id.nil?) ? "" : homeattach.user.user_extensions.student_id)}_#{Time.now.to_i.to_s}.zip", homeworks_attach_path, OUTPUT_FOLDER, true, not_exist_file)
out_file = find_or_pack(homework_attach.bid_id, homework_attach.user_id, digests.sort){
zipping("#{homework_attach.user.lastname}#{homework_attach.user.firstname}_#{((homework_attach.user.user_extensions.nil? || homework_attach.user.user_extensions.student_id.nil?) ? "" : homework_attach.user.user_extensions.student_id)}_#{Time.now.to_i.to_s}.zip",
homeworks_attach_path, OUTPUT_FOLDER, true, not_exist_file)
}
end end
def zipping(zip_name_refer, files_paths, output_path, is_attachment=false, not_exist_file=[]) def find_or_pack(homework_id, user_id, digests)
# 输入待打包的文件列表已经打包文件定位到ouput_path raise "please given a pack block" unless block_given?
ic = Iconv.new('GBK//IGNORE', 'UTF-8//IGNORE')
input_filename = files_paths out_file = ZipPack.packed?(homework_id, user_id, digests.sort)
unless out_file && out_file.file_valid?
file = yield
ZipPack.where(homework_id: homework_id,
user_id: user_id).delete_all
out_file = ZipPack.create(homework_id: homework_id,
user_id: user_id,
file_digest: Trustie::Utils.digest(file),
file_path: file,
pack_size: File.size(file),
file_digests: digests.join(',')
)
else
out_file.pack_times = out_file.pack_times + 1
out_file.save
end
out_file
end
def zipping(zip_name_refer, files_paths, output_path, is_attachment=false, not_exist_file=[])
rename_zipfile = zip_name_refer ||= "#{Time.now.to_i.to_s}.zip" rename_zipfile = zip_name_refer ||= "#{Time.now.to_i.to_s}.zip"
zipfile_name = "#{output_path}/#{rename_zipfile}" zipfile_name = "#{output_path}/#{rename_zipfile}"
Dir.mkdir(File.dirname(zipfile_name)) unless File.exist?(File.dirname(zipfile_name)) Dir.mkdir(File.dirname(zipfile_name)) unless File.exist?(File.dirname(zipfile_name))
Zip::File.open(zipfile_name, Zip::File::CREATE) do |zipfile| Zip::File.open(zipfile_name, Zip::File::CREATE) do |zipfile|
input_filename.each do |filename| files_paths.each do |filename|
flag = true rename_file = File.basename(filename)
index = 1 rename_file = filename_to_real( File.basename(filename)) if is_attachment
rename_file = ic.iconv( (File.basename(filename)) ).to_s
rename_file = ic.iconv( filename_to_real( File.basename(filename))).to_s if is_attachment
begin begin
zipfile.add(rename_file, filename) zipfile.add(rename_file, filename)
flag = false
rescue Exception => e rescue Exception => e
zipfile.get_output_stream('FILE_NOTICE.txt') do |os| zipfile.get_output_stream('FILE_NOTICE.txt'){|os| os.write l(:label_file_exist)}
os.write l(:label_file_exist)
end
next next
end end
end end
unless not_exist_file.empty? unless not_exist_file.empty?
zipfile.get_output_stream('FILE_LOST.txt') do |os| zipfile.get_output_stream('FILE_LOST.txt'){|os| os.write l(:label_file_lost) + not_exist_file.join(',').to_s}
os.write l(:label_file_lost) + not_exist_file.join(',').to_s
end
end end
end end
zipfile_name zipfile_name
#rescue Errno => e
# logger.error "[zipdown#zipping] ===> #{e}"
# @error = e
end end
# 合理分配文件打包
# 如果小于 pack_attachment_max_size, 则返回单个文件
# 反之则切分为多个文件组返回
def split_pack_files(files, pack_attachment_max_size)
max_size = 0
last_files = []
ret_files = []
files.each_with_index do |f,i|
if (max_size += File.size(f)) > pack_attachment_max_size
max_size = 0
if last_files.empty? #如果单个文件超过大小,也将此文件作为一组
ret_files << {files: [f], count: 1, index: ret_files.count+1}
last_files.clear
else
ret_files << {files:last_files, count: last_files.count, index: ret_files.count+1}
last_files.clear
redo
end
else
last_files << f
end
end
ret_files << {files:last_files, count: last_files.count, index: ret_files.count+1} unless last_files.empty?
ret_files
end
def detect_content_type(name) def detect_content_type(name)
content_type = Redmine::MimeType.of(name) content_type = Redmine::MimeType.of(name)
content_type.to_s content_type.to_s
@ -137,4 +239,4 @@ class ZipdownController < ApplicationController
attach = Attachment.find_by_disk_filename(name) attach = Attachment.find_by_disk_filename(name)
attach.filename attach.filename
end end
end end

@ -1,62 +1,62 @@
# encoding: utf-8 # encoding: utf-8
# #
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang # Copyright (C) 2006-2013 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module AccountHelper module AccountHelper
def email_activation_register(user, &block) def email_activation_register(user, &block)
token = Token.new(:user => user, :action => "register") token = Token.new(:user => user, :action => "register")
if user.save and token.save if user.save and token.save
UserStatus.create(:user_id => user.id, :changsets_count => 0, :watchers_count => 0) UserStatus.create(:user_id => user.id, :changsets_count => 0, :watchers_count => 0)
Mailer.register(token).deliver Mailer.run.register(token)
#flash[:notice] = l(:notice_account_register_done) #flash[:notice] = l(:notice_account_register_done)
#render action: 'email_valid', locals: {:mail => user.mail} #render action: 'email_valid', locals: {:mail => user.mail}
else else
yield if block_given? yield if block_given?
end end
user user
end end
def automatically_register(user, &block) def automatically_register(user, &block)
# Automatic activation # Automatic activation
user.activate user.activate
user.last_login_on = Time.now user.last_login_on = Time.now
if user.save if user.save
UserStatus.create(:user_id => user.id, :changsets_count => 0, :watchers_count => 0) UserStatus.create(:user_id => user.id, :changsets_count => 0, :watchers_count => 0)
#self.logged_user = user #self.logged_user = user
#flash[:notice] = l(:notice_account_activated) #flash[:notice] = l(:notice_account_activated)
#redirect_to my_account_url #redirect_to my_account_url
else else
yield if block_given? yield if block_given?
end end
user user
end end
def administrator_manually__register(user, &block) def administrator_manually__register(user, &block)
if user.save if user.save
UserStatus.create(:user_id => user.id ,:changsets_count => 0, :watchers_count => 0) UserStatus.create(:user_id => user.id ,:changsets_count => 0, :watchers_count => 0)
# Sends an email to the administrators # Sends an email to the administrators
Mailer.account_activation_request(user).deliver Mailer.run.account_activation_request(user)
#account_pending #account_pending
else else
yield if block_given? yield if block_given?
end end
user user
end end
end end

@ -1,33 +1,45 @@
# encoding: utf-8 # encoding: utf-8
# #
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang # Copyright (C) 2006-2013 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module ActivitiesHelper module ActivitiesHelper
def sort_activity_events(events) def sort_activity_events(events)
events_by_group = events.group_by(&:event_group) events_by_group = events.group_by(&:event_group)
sorted_events = [] sorted_events = []
events.sort {|x, y| y.event_datetime <=> x.event_datetime}.each do |event| events.sort {|x, y| y.event_datetime <=> x.event_datetime}.each do |event|
if group_events = events_by_group.delete(event.event_group) 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| 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? sorted_events << [e, i > 0] unless e.event_description.nil?
end end
end end
end end
sorted_events sorted_events
end end
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

File diff suppressed because it is too large Load Diff

@ -35,6 +35,16 @@ module AttachmentsHelper
end end
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 = {}) def link_to_attachments_course(container, options = {})
options.assert_valid_keys(:author, :thumbnails) options.assert_valid_keys(:author, :thumbnails)
@ -77,6 +87,7 @@ module AttachmentsHelper
end end
end end
#判断课程course中是否包含课件attachmentcourse中引用了attachment也算作包含
def course_contains_attachment? course,attachment def course_contains_attachment? course,attachment
course.attachments.each do |att| course.attachments.each do |att|
if att.id == attachment.id || (!att.copy_from.nil? && !attachment.copy_from.nil? && att.copy_from == attachment.copy_from) || att.copy_from == attachment.id || att.id == attachment.copy_from if att.id == attachment.id || (!att.copy_from.nil? && !attachment.copy_from.nil? && att.copy_from == attachment.copy_from) || att.copy_from == attachment.id || att.id == attachment.copy_from
@ -85,6 +96,15 @@ module AttachmentsHelper
end end
false false
end end
#判断项目project中是否包含课件attachmentproject中引用了attachment也算作包含
def project_contains_attachment? project,attachment
project.attachments.each do |att|
if att.id == attachment.id || (!att.copy_from.nil? && !attachment.copy_from.nil? && att.copy_from == attachment.copy_from) || att.copy_from == attachment.id || att.id == attachment.copy_from
return true
end
end
false
end
def get_qute_number attachment def get_qute_number attachment
if attachment.copy_from if attachment.copy_from

@ -20,7 +20,7 @@ module CoursesHelper
# 返回教师数量即roles表中定义的Manager # 返回教师数量即roles表中定义的Manager
def teacherCount project def teacherCount project
project.members.count - studentCount(project).to_i project ? project.members.count - studentCount(project).to_i : 0
# or # or
# searchTeacherAndAssistant(project).count # searchTeacherAndAssistant(project).count
end end
@ -52,7 +52,7 @@ module CoursesHelper
end end
def course_poll_count def course_poll_count
Poll.where("polls_type = 'Course' and polls_group_id = #{@course.id}").count Poll.where("polls_type = 'Course' and polls_group_id = #{@course.id} and polls_status in (2,3)").count
end end
def course_feedback_count def course_feedback_count
@ -152,7 +152,7 @@ module CoursesHelper
# 学生人数计算 # 学生人数计算
# add by nwb # add by nwb
def studentCount course def studentCount course
course.student.count.to_s#course.student.count course ? course.student.count.to_s : 0#course.student.count
end end
#课程成员数计算 #课程成员数计算
@ -233,10 +233,10 @@ module CoursesHelper
#searchPeopleByRoles(project, StudentRoles) #searchPeopleByRoles(project, StudentRoles)
mems = [] mems = []
if name != "" if name != ""
name = name.to_s.downcase
members.each do |m| members.each do |m|
username = m.user[:lastname].to_s.downcase + m.user[:firstname].to_s.downcase
username = m.user[:lastname].to_s + m.user[:firstname].to_s if(m.user[:login].to_s.downcase.include?(name) || m.user.user_extensions[:student_id].to_s.downcase.include?(name) || username.include?(name))
if(m.user[:login].to_s.include?(name) || m.user.user_extensions[:student_id].to_s.include?(name) || username.include?(name))
mems << m mems << m
end end
end end
@ -632,27 +632,73 @@ module CoursesHelper
#获取课程动态 #获取课程动态
def get_course_activity courses, activities def get_course_activity courses, activities
@course_ids=activities.keys() @course_ids=activities.keys()
days = Setting.activity_days_default.to_i days = Setting.activity_days_default.to_i
date_to ||= Date.today + 1 #原来课程动态计算当期时间前(一年+一月)的动态
date_from = date_to - days-1.years # date_to ||= Date.today + 1
# #date_from = date_to - days-1.years
date_from = @course.created_at.to_date-days
#file_count #file_count
Attachment.where(container_id: @course_ids, container_type: Course).where("created_on>?", date_from).each do |attachment| Attachment.where(container_id: @course_ids, container_type: Course).where("created_on>?", date_from).each do |attachment|
if attachment.is_public? || User.current.member_of_course?(@course) || User.current.admin?
activities[attachment.container_id]+=1 activities[attachment.container_id]+=1
else
activities[attachment.container_id]
end
end end
#message_count
#Board.where(course_id: @course_ids).each do |board|
# activities[board.course_id]+=board.messages.where("updated_on>?", date_from).count
#end
#message_count #message_count
Board.where(course_id: @course_ids).each do |board| Board.where(course_id: @course_ids).each do |board|
# activities[board.course_id]+=1 countmessage = 0
activities[board.course_id]+=board.messages.where("updated_on>?", date_from).count # 课程人员退出课程后,之前在讨论区回帖不计入课程动态统计
board.messages.where("updated_on>?", date_from).each do |message|
if message.author.member_of_course?(@course)
countmessage+=1
end
end
activities[board.course_id]+=countmessage
end end
#news #news
News.where(course_id: @course_ids).where("created_on>?",date_from).each do |news| News.where(course_id: @course_ids).where("created_on>?",date_from).each do |news|
if news.author.member_of_course?(@course)
activities[news.course_id]+=1 activities[news.course_id]+=1
end
end
#feedback_count 留言目前有问题留待下一步处理
#JournalsForMessage.where(jour_id: @course_ids, jour_type: Course).each do |jourformess|
# activities[jourformess.jour_id]+=1
#end
#homework_count
HomeworkForCourse.where(course_id: @course_ids).each do |homework|
countbid=0
# @bid_ids<<homework.bid_id
Bid.where(id: homework.bid_id).where("created_on>?",date_from).each do |bid|
countbid+=1
end
activities[homework.course_id]+=countbid
end end
#@bid_ids.each do |bid_id|
# activities[] +=Bid.where(id: bid_id ).where("created_on>?",date_from).count
#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|
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
# 动态数 + 1 ( 某某创建了该课程 ) # 动态数 + 1 ( 某某创建了该课程 )
activities.each_pair { |key, value| activities[key] = value + 1 } activities.each_pair { |key, value| activities[key] = value + 1 }
return activities return activities
@ -677,7 +723,7 @@ module CoursesHelper
#加入课程、退出课程按钮 #加入课程、退出课程按钮
def join_in_course_header(course, user, options=[]) def join_in_course_header(course, user, options=[])
if user.logged? if user.logged?
joined = user.member_of_course? course joined = course.members.map{|member| member.user_id}.include? user.id
text = joined ? ("<em class='pr_arrow'></em>".html_safe + l(:label_course_exit_student)) : ("<em class='pr_add'></em>".html_safe + l(:label_course_join_student)) text = joined ? ("<em class='pr_arrow'></em>".html_safe + l(:label_course_exit_student)) : ("<em class='pr_add'></em>".html_safe + l(:label_course_join_student))
url = joined ? join_path(:object_id => course.id) : try_join_path(:object_id => course.id) url = joined ? join_path(:object_id => course.id) : try_join_path(:object_id => course.id)
method = joined ? 'delete' : 'post' method = joined ? 'delete' : 'post'
@ -718,7 +764,11 @@ module CoursesHelper
if user_homework && user_homework.empty? if user_homework && user_homework.empty?
link_to l(:label_commit_homework), new_exercise_book_path(bid),:class => 'fr mr10 work_edit' link_to l(:label_commit_homework), new_exercise_book_path(bid),:class => 'fr mr10 work_edit'
else else
"<span class='fr mr10 pr_join_span '>作业已交</span>".html_safe if bid.comment_status == 1 && bid.open_anonymous_evaluation == 1
"<span class='fr mr10 pr_join_span ' title='已开启匿评不能修改作品'>#{l(:label_edit_homework)}</span>".html_safe
else
link_to l(:label_edit_homework), edit_homework_attach_path(user_homework.first.id),:class => 'fr mr10 work_edit'
end
end end
end end
@ -736,4 +786,15 @@ module CoursesHelper
"<span class='fr mr10 pr_join_span '>未启用匿评</span>".html_safe "<span class='fr mr10 pr_join_span '>未启用匿评</span>".html_safe
end end
end end
def visable_attachemnts_incourse course
return[] unless course
result = []
course.attachments.each do |attachment|
if attachment.is_public? || User.current.member_of_course?(course) || User.current.admin?
result << attachment
end
end
result
end
end end

@ -1,157 +1,150 @@
# encoding: utf-8 # encoding: utf-8
module FilesHelper module FilesHelper
include AttachmentsHelper include AttachmentsHelper
def downloadAll containers def downloadAll containers
paths = [] paths = []
files = [] files = []
tmpfile = "tmp.zip" tmpfile = "tmp.zip"
containers.each do |container| containers.each do |container|
next if container.attachments.empty? next if container.attachments.empty?
if container.is_a?(Version);end if container.is_a?(Version);end
container.attachments.each do |attachment| container.attachments.each do |attachment|
paths << attachment.diskfile paths << attachment.diskfile
file = attachment.diskfile file = attachment.diskfile
# logger.error "[FilesHelper] downloadAll: #{e}" # logger.error "[FilesHelper] downloadAll: #{e}"
begin begin
File.new(file, "r") File.new(file, "r")
rescue Exception => e rescue Exception => e
logger.error e logger.error e
next next
end end
files << file files << file
# zip.add(file.path.dup.sub(directory, ''), file.path) # zip.add(file.path.dup.sub(directory, ''), file.path)
end end
end end
zipfile_name = "archive.zip" zipfile_name = "archive.zip"
if File.exists? File.open(zipfile_name, "w+") if File.exists? File.open(zipfile_name, "w+")
ff = File.open(zipfile_name, "w+") ff = File.open(zipfile_name, "w+")
ff.close ff.close
File.delete ff File.delete ff
end end
Zip::ZipFile.open(zipfile_name, Zip::ZipFile::CREATE) do |zipfile| Zip::ZipFile.open(zipfile_name, Zip::ZipFile::CREATE) do |zipfile|
files.each do |filename| files.each do |filename|
directory = File.dirname filename directory = File.dirname filename
# Two arguments: # Two arguments:
# - The name of the file as it will appear in the archive # - The name of the file as it will appear in the archive
# - The original file, including the path to find it # - The original file, including the path to find it
dir = filename.sub(directory+"/", '') dir = filename.sub(directory+"/", '')
zipfile.add(dir, filename) zipfile.add(dir, filename)
end end
end end
File.new(zipfile_name,'w+') File.new(zipfile_name,'w+')
end end
def courses_check_box_tags(name,courses,current_course,attachment) #带勾选框的课程列表
s = '' def courses_check_box_tags(name,courses,current_course,attachment)
courses.each do |course| s = ''
if !course_contains_attachment?(course,attachment) && is_course_teacher(User.current,course) && course_in_current_or_next_term(course) courses.each do |course|
s << "<label>#{ check_box_tag name, course.id, false, :id => nil } #{h course.name}</label>&nbsp;[#{get_course_term course}]<br/>" if !course_contains_attachment?(course,attachment) && is_course_teacher(User.current,course) && course_in_current_or_next_term(course)
end s << "<label>#{ check_box_tag name, course.id, false, :id => nil } #{h course.name}</label>&nbsp;[#{get_course_term course}]<br/>"
end end
s.html_safe end
end s.html_safe
end
#判断用户是否拥有不包含当前资源的课程,需用户在该课程中角色为教师且该课程属于当前学期或下一学期
def has_course? user,file #带勾选框的项目列表
result = false def projects_check_box_tags(name,projects,current_project,attachment)
user.courses.each do |course| s = ''
if !course_contains_attachment?(course,file) && is_course_teacher(User.current,course) && course_in_current_or_next_term(course) projects.each do |project|
return true if !project_contains_attachment?(project,attachment) && User.current.allowed_to?(:manage_files, project)
end s << "<label>#{ check_box_tag name, project.id, false, :id => nil } #{h project.name}</label><br/>"
end end
result end
end s.html_safe
end
# 判断指定的资源时候符合类型
def isTypeOk(attachment, type, contentType) #判断用户是否拥有不包含当前资源的课程,需用户在该课程中角色为教师且该课程属于当前学期或下一学期
result = false def has_course? user,file
if type != 0 result = false
if attachment.attachtype == type user.courses.each do |course|
result = true if !course_contains_attachment?(course,file) && is_course_teacher(User.current,course) && course_in_current_or_next_term(course)
end return true
else end
result = true end
end result
if result end
if contentType != '0' && contentType != attachment.suffix_type
result = false #判断用户是否拥有不包含当前资源的项目,需用户在该项目中有资源管理相关资源
end def has_project? user,file
end result = false
result user.projects.each do |project|
end if !project_contains_attachment?(project,file) && User.current.allowed_to?(:manage_files, project)
return true
def visable_attachemnts attachments end
result = [] end
attachments.each do |attachment| result
if attachment.is_public? || end
(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 def isTypeOk(attachment, type, contentType)
result << attachment result = false
end if type != 0
end if attachment.attachtype == type
result result = true
end end
else
def visable_attachemnts_incourse attachments result = true
result = [] end
attachments.each do |attachment| if result
if attachment.is_public? || (attachment.author.member_of_course?(Course.find(attachment.container_id)))|| attachment.author_id == User.current.id if contentType != '0' && contentType != attachment.suffix_type
result << attachment result = false
end end
end end
result result
end end
def visable_attachemnts_insite attachments,course def visable_attachemnts attachments
result = [] result = []
attachments.each do |attachment| attachments.each do |attachment|
if attachment.is_public? || (attachment.container_type == "Course" && attachment.container_id == course.id && User.current.member_of_course?(Course.find(attachment.container_id)))|| attachment.author_id == User.current.id if attachment.is_public? ||
result << attachment (attachment.container_type == "Project" && User.current.member_of?(attachment.project)) ||
end (attachment.container_type == "Course" && User.current.member_of_course?(Course.find(attachment.container_id)))||
end attachment.author_id == User.current.id
result result << attachment
end end
end
def attachment_candown attachment result
candown = false end
if attachment.container
if attachment.container.class.to_s != "HomeworkAttach" && (attachment.container.has_attribute?(:project) || attachment.container.has_attribute?(:project_id)) && attachment.container.project def get_attachments_by_tag attachments,tag
project = attachment.container.project attachments.each do |attachment|
candown= User.current.member_of?(project) || (project.is_public && attachment.is_public == 1) attachment.tag_list.include?(tag)
elsif attachment.container.is_a?(Project) end
project = attachment.container end
candown= User.current.member_of?(project) || (project.is_public && attachment.is_public == 1)
elsif (attachment.container.has_attribute?(:board) || attachment.container.has_attribute?(:board_id)) && attachment.container.board && def visable_attachemnts_insite attachments,obj
attachment.container.board.project result = []
project = attachment.container.board.project if obj.is_a?(Course)
candown = User.current.member_of?(project) || (project.is_public && attachment.is_public == 1) attachments.each do |attachment|
elsif (attachment.container.has_attribute?(:course) ||attachment.container.has_attribute?(:course_id) ) && attachment.container.course 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
course = attachment.container.course result << attachment
candown = User.current.member_of_course?(course) || (course.is_public==1 && attachment.is_public == 1) end
elsif attachment.container.is_a?(Course) end
course = attachment.container else if obj.is_a?(Project)
candown= User.current.member_of_course?(course) || (course.is_public==1 && attachment.is_public == 1) attachments.each do |attachment|
elsif (attachment.container.has_attribute?(:board) || attachment.container.has_attribute?(:board_id)) && attachment.container.board && 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
attachment.container.board.course result << attachment
course = attachment.container.board.course end
candown= User.current.member_of_course?(course) || (course.is_public==1 && attachment.is_public == 1) end
elsif attachment.container.class.to_s=="HomeworkAttach" && attachment.container.bid.reward_type == 3 end
candown = true end
elsif attachment.container_type == "Bid" && attachment.container && attachment.container.courses result
course = attachment.container.courses.first end
candown = User.current.member_of_course?(attachment.container.courses.first) || (course.is_public == 1 && attachment.is_public == 1)
else
candown = (attachment.is_public == 1 || attachment.is_public == true)
end
end
candown
end
end end

@ -61,12 +61,38 @@ module IssuesHelper
#h("#{issue.tracker} ##{issue.id}") #h("#{issue.tracker} ##{issue.id}")
# h("#{issue.tracker} #{issue.source_from}") # h("#{issue.tracker} #{issue.source_from}")
s = '' s = ''
s << link_to(@issue.project.name, project_issues_path(@issue.project)) s << link_to(@issue.project.name, project_issues_path(@issue.project), :class => "pro_page_top")
s << " > #" s << " > "
s << @issue.project_index s << link_to("#" + @issue.project_index, project_issues_path(@issue.project), :class => "pro_page_top")
s.html_safe s.html_safe
end 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) def render_issue_subject_with_tree(issue)
s = '' s = ''
ancestors = issue.root? ? [] : issue.ancestors.visible.all 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) if detail.property == 'attachment' && !value.blank? && atta = Attachment.find_by_id(detail.prop_key)
# Link to the attachment if it has not been removed # Link to the attachment if it has not been removed
if options[:token].nil? if options[:token].nil?
value = link_to_attachment(atta, :download => true, :only_path => options[:only_path]) value = atta.filename
else else
value = link_to_attachment(atta, :download => true, :only_path => options[:only_path], :token => options[:token]) 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 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 else
value = content_tag("i", h(value)) if value value = content_tag("i", h(value)) if value
end end

@ -46,6 +46,26 @@ module JournalsHelper
content.html_safe content.html_safe
end 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={}) def render_notes (issue, journal, options={})
content = '' 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))) 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") content_tag('div', content.html_safe, :id => "journal-#{journal.id}-notes", :class => css_classes ,:style => "width:580px")
end 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={}) def link_to_in_place_notes_editor(text, field_id, url, options={})
onclick = "$.ajax({url: '#{url_for(url)}', type: 'get'}); return false;" onclick = "$.ajax({url: '#{url_for(url)}', type: 'get'}); return false;"
link_to text, '#', options.merge(:onclick => onclick) link_to text, '#', options.merge(:onclick => onclick)

@ -1,95 +1,110 @@
# encoding: utf-8 # encoding: utf-8
# #
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang # Copyright (C) 2006-2013 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module MembersHelper module MembersHelper
def render_principals_for_new_members(project) def render_principals_for_new_members(project)
scope = Principal.active.sorted.not_member_of(project).like(params[:q]) scope = Principal.active.sorted.not_member_of(project).like(params[:q])
principal_count = scope.count principal_count = scope.count
principal_pages = Redmine::Pagination::Paginator.new principal_count, 10, params['page'] #by young 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 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') 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| 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 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') s + content_tag('div', content_tag('ul', links), :class => 'pagination_new')
end end
#获取项目可邀请的成员列表 #获取项目可邀请的成员列表
def render_project_members project def render_project_members project
scope = Principal.active.sorted.not_member_of(project).like(params[:q]) if params[:q] && params[:q].lstrip.rstrip != ""
principals = paginateHelper scope,10 scope = Principal.active.sorted.not_member_of(project).like(params[:q])
s = content_tag('ul', project_member_check_box_tags_ex('membership[user_ids][]', principals), :class => 'mb5', :style => "margin-left: -40px;") else
links = pagination_links_full(@obj_pages, @obj_count, :per_page_links => false, :remote => false, :flag => true){|text, parameters, options| scope = []
link_to text, autocomplete_project_memberships_path(project, parameters.merge(:q => params[:q],:flag => true, :format => 'js')), :remote => true end
} principals = paginateHelper scope,10
s + content_tag('ul', links,:class => 'wlist') s = content_tag('ul', project_member_check_box_tags_ex('membership[user_ids][]', principals), :class => 'mb5')
end 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
# add by nwb }
# 课程可添加的成员列表 s + content_tag('ul', links,:class => 'wlist', :id => "course_member_pagination_links" )
def render_principals_for_new_course_members(course) end
scope = Principal.active.sorted.not_member_of_course(course).like(params[:q])
principal_count = scope.count # add by nwb
principal_pages = Redmine::Pagination::Paginator.new principal_count, 10, params['page'] # 课程可添加的成员列表
principals = scope.offset(principal_pages.offset).limit(principal_pages.per_page).all def render_principals_for_new_course_members(course)
if params[:q] && params[:q].lstrip.rstrip != ""
s = content_tag('div', principals_check_box_tags_ex('membership[user_ids][]', principals), :id => 'principals') scope = Principal.active.sorted.not_member_of_course(course).like(params[:q])
else
links = pagination_links_full(principal_pages, principal_count, :per_page_links => false) {|text, parameters, options| scope = []
link_to text, autocomplete_course_memberships_path(course, parameters.merge(:q => params[:q], :format => 'js')), :remote => true end
} principals = paginateHelper scope,10
s = content_tag('ul', project_member_check_box_tags_ex('membership[user_ids][]', principals), :class => 'mb5', :id => 'principals')
s + content_tag('div', content_tag('ul', links), :class => 'pagination_new')
end 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
}
# 当前申请加入的成员名单
def render_principals_for_applied_members(project) s + content_tag('ul', links,:class => 'wlist',:id => "course_member_pagination_links")
scope = project.applied_projects.map(&:user) end
principal_count = scope.count
principal_pages = Redmine::Pagination::Paginator.new principal_count, 10, params['page'] # 新申请加入项目成员列表
offset ||= principal_pages.offset def render_principals_for_applied_members_new project
principals = scope[offset, 10] scope = project.applied_projects.map(&:user)
#principals = scope.offset(principal_pages.offset).limit(principal_pages.per_page).all principals = paginateHelper scope,10
#principals = ApplicationController.new.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|
s = content_tag('div', principals_check_box_tags_ex('membership[user_ids][]', principals), :id => 'principals') link_to text, appliedproject_project_memberships_path(project, parameters.merge(:q => params[:q],:flag => true, :format => 'js')), :remote => true
}
links = pagination_links_full(principal_pages, principal_count, :per_page_links => false) {|text, parameters, options| s + content_tag('ul', links,:class => 'wlist', :id => "course_member_pagination_links" )
link_to text, appliedproject_project_memberships_path(project, parameters.merge(:q => params[:q], :format => 'js')), :remote => true end
}
# 当前申请加入的成员名单
s + content_tag('div', content_tag('ul', links), :class => 'applied_new') def render_principals_for_applied_members(project)
end scope = project.applied_projects.map(&:user)
principal_count = scope.count
private principal_pages = Redmine::Pagination::Paginator.new principal_count, 10, params['page']
def paginateHelper obj, pre_size=20 offset ||= principal_pages.offset
@obj_count = obj.count principals = scope[offset, 10]
@obj_pages = Redmine::Pagination::Paginator.new @obj_count, pre_size, params['page'] #principals = scope.offset(principal_pages.offset).limit(principal_pages.per_page).all
if obj.kind_of? ActiveRecord::Base or obj.kind_of? ActiveRecord::Relation #principals = ApplicationController.new.paginateHelper scope,10
obj.limit(@obj_pages.per_page).offset(@obj_pages.offset)
elsif obj.kind_of? Array s = content_tag('div', principals_check_box_tags_ex('membership[user_ids][]', principals), :id => 'principals')
obj[@obj_pages.offset, @obj_pages.per_page]
else links = pagination_links_full(principal_pages, principal_count, :per_page_links => false) {|text, parameters, options|
logger.error "[ApplicationController] Error : application_controller#paginateHelper ===> unknow category: #{obj.class}" link_to text, appliedproject_project_memberships_path(project, parameters.merge(:q => params[:q], :format => 'js')), :remote => true
raise RuntimeError, 'unknow type, Please input you type into this helper.' }
end
end s + content_tag('div', content_tag('ul', links), :class => 'applied_new')
end
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

@ -0,0 +1,9 @@
module OwnerTypeHelper
MEMO = 1
FORUM = 2
MESSAGE = 3
NEWS = 4
COMMENT = 5
BID = 6
JOURNALSFORMESSAGE = 7
end

@ -21,7 +21,12 @@ include AvatarHelper
module ProjectsHelper module ProjectsHelper
def link_to_version(version, options = {}) def link_to_version(version, options = {})
return '' unless version && version.is_a?(Version) 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 end
def project_settings_tabs 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 => '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 => '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 => '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 => '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 => 'repositories', :action => :manage_repository, :partial => 'projects/settings/repositories', :label => :label_repository_plural},
#{:name => 'boards', :action => :manage_boards, :partial => 'projects/settings/boards', :label => :label_board_plural}, #{:name => 'boards', :action => :manage_boards, :partial => 'projects/settings/boards', :label => :label_board_plural},
@ -386,4 +391,20 @@ module ProjectsHelper
end end
type type
end 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 end

@ -255,8 +255,19 @@ module QueriesHelper
# Give it a name, required to be valid # Give it a name, required to be valid
@query = IssueQuery.new(:name => "_") @query = IssueQuery.new(:name => "_")
@query.project = @project @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) @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} #session[:query] = {:project_id => @query.project_id, :filters => @query.filters, :group_by => @query.group_by, :column_names => @query.column_names}
else else
# retrieve from session # retrieve from session
@query = IssueQuery.find_by_id(session[:query][:id]) if session[:query][:id] @query = IssueQuery.find_by_id(session[:query][:id]) if session[:query][:id]

@ -18,7 +18,11 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module RepositoriesHelper 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 PROJECT_PATH_CUT = 40
REPO_IP_ADDRESS = Setting.repository_domain REPO_IP_ADDRESS = Setting.repository_domain

@ -278,4 +278,29 @@ module UsersHelper
end end
} }
end end
#获取用户留言相关的连接
def user_jour_feed_back_url active
if active.act_type == "JournalsForMessage"
jour = JournalsForMessage.find active.act_id
if jour
case jour.jour_type
when "Principal"
link_to(l(:label_goto), user_newfeedback_user_path(jour.jour_id))
when "Project"
link_to(l(:label_goto), project_feedback_path(jour.jour_id))
when "Bid"
link_to(l(:label_goto), course_for_bid_path(jour.jour_id))
when "Course"
link_to(l(:label_goto), course_feedback_path(jour.jour_id))
when "Contest"
link_to(l(:label_goto), show_contest_contest_path(jour.jour_id))
when "Softapplication"
link_to(l(:label_goto), softapplication_path(jour.jour_id))
when "HomeworkAttach"
link_to(l(:label_goto), course_for_bid_path(jour.jour_id))
end
end
end
end
end end

@ -42,7 +42,28 @@ module WatchersHelper
:object_id => (objects.size == 1 ? objects.first.id : objects.map(&:id).sort) :object_id => (objects.size == 1 ? objects.first.id : objects.map(&:id).sort)
) )
method = watched ? 'delete' : 'post' 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 link_to text, url, :remote => true, :method => method, :class => css
end end
@ -155,7 +176,7 @@ module WatchersHelper
else else
text = l(:label_new_join_group) text = l(:label_new_join_group)
form_tag({:controller => "courses", :action => "join_group", :object_id => "#{group.id}"}, :remote => true, :method => 'post') do form_tag({:controller => "courses", :action => "join_group", :object_id => "#{group.id}"}, :remote => true, :method => 'post') do
submit_tag text, class: "group_in", style: "width: 43px;height: 21px;" submit_tag text, class: "group_in", style: "width: 90px;height: 21px;"
end end
end end
end end
@ -261,17 +282,36 @@ module WatchersHelper
content.present? ? content_tag('ul', content, :class => 'watchers') : content content.present? ? content_tag('ul', content, :class => 'watchers') : content
end end
# 缺陷跟踪者列表复选框生成
def watchers_checkboxes(object, users, checked=nil) def watchers_checkboxes(object, users, checked=nil)
if users.nil? if users.nil?
else 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| users.map do |user|
c = checked.nil? ? object.watched_by?(user) : checked c = checked.nil? ? object.watched_by?(user) : checked
tag = check_box_tag 'issue[watcher_user_ids][]', user.id, c, :id => nil s = content_tag(:ul,
content_tag 'label', "#{tag} #{h(user)}".html_safe, 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}", :id=>"issue_watcher_user_ids_#{user.id}",:style=>"float: left;width: 175px;margin: 0px 20px 10px 0px; overflow: hidden; line-height:1.6em;" ),
:class => "floating" :class => "mb10 ml80")
end.join.html_safe 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
end end
@ -304,8 +344,8 @@ module WatchersHelper
def exit_project_link(project) def exit_project_link(project)
link_to(l(:label_exit_project),exit_cur_project_path(project.id), link_to(l(:label_exit_project),exit_cur_project_path(project.id),
:remote => true, :confirm => l(:lable_sure_exit_project), :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;" ) :class => "pr_join_a_quit" )
end end
#项目关注、取消关注 #项目关注、取消关注
#REDO:项目样式确定后方法需要对CSS变量进行改进 #REDO:项目样式确定后方法需要对CSS变量进行改进
@ -321,7 +361,7 @@ module WatchersHelper
:object_id => (objects.size == 1 ? objects.first.id : objects.map(&:id).sort)) :object_id => (objects.size == 1 ? objects.first.id : objects.map(&:id).sort))
method = watched ? 'delete' : 'post' method = watched ? 'delete' : 'post'
link_to text, url, :remote => true, :method => method, link_to text, url, :remote => true, :method => method,
:class => "project_watch_new" ,:id=>id :class => "pr_join_a" ,:id=>id
end end
#申请加入项目 #申请加入项目
@ -339,7 +379,21 @@ module WatchersHelper
:user_id => user.id, :user_id => user.id,
:project_id => project.id) :project_id => project.id)
method = applied ? 'delete' : 'post' 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
end end

@ -443,6 +443,10 @@ module WelcomeHelper
resultSet.take(limit) resultSet.take(limit)
end 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 def sort_project_by_hot_rails project_type=0, order_by='score DESC', limit=15
# Project.find_by_sql(" # Project.find_by_sql("
# SELECT p.id, p.name, p.description, p.identifier, t.project_id # SELECT p.id, p.name, p.description, p.identifier, t.project_id

@ -17,7 +17,8 @@ class Bid < ActiveRecord::Base
HomeworkProject = 2 HomeworkProject = 2
attr_accessible :author_id, :budget, :deadline, :name, :description, :homework_type, :password attr_accessible :author_id, :budget, :deadline, :name, :description, :homework_type, :password
include Redmine::SafeAttributes include Redmine::SafeAttributes
include ApplicationHelper
has_many_kindeditor_assets :assets, :dependent => :destroy
belongs_to :author, :class_name => 'User', :foreign_key => :author_id belongs_to :author, :class_name => 'User', :foreign_key => :author_id
belongs_to :course belongs_to :course
has_many :biding_projects, :dependent => :destroy has_many :biding_projects, :dependent => :destroy
@ -47,7 +48,7 @@ class Bid < ActiveRecord::Base
validate :validate_user validate :validate_user
validate :validate_reward_type validate :validate_reward_type
after_create :act_as_activity after_create :act_as_activity
after_destroy :delete_kindeditor_assets
scope :visible, lambda {|*args| scope :visible, lambda {|*args|
nil nil
} }
@ -157,5 +158,10 @@ class Bid < ActiveRecord::Base
end end
end end
# Time 2015-04-01 14:19:06
# Author lizanle
# Description 删除对应课程通知的图片资源
def delete_kindeditor_assets
delete_kindeditor_assets_from_disk self.id,OwnerTypeHelper::BID
end
end end

@ -17,8 +17,25 @@
class Comment < ActiveRecord::Base class Comment < ActiveRecord::Base
include Redmine::SafeAttributes include Redmine::SafeAttributes
include ApplicationHelper
has_many_kindeditor_assets :assets, :dependent => :destroy
belongs_to :commented, :polymorphic => true, :counter_cache => true belongs_to :commented, :polymorphic => true, :counter_cache => true
belongs_to :author, :class_name => 'User', :foreign_key => 'author_id' belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
validates_presence_of :commented, :author, :comments validates_presence_of :commented, :author, :comments
safe_attributes 'comments' safe_attributes 'comments'
after_create :send_mail
def send_mail
if self.commented.is_a?(News) && Setting.notified_events.include?('news_comment_added')
Mailer.run.news_comment_added(self)
end
end
after_destroy :delete_kindeditor_assets
# Time 2015-03-31 09:15:06
# Author lizanle
# Description 删除对应评论的图片资源
def delete_kindeditor_assets
delete_kindeditor_assets_from_disk self.id,OwnerTypeHelper::COMMENT
end
end end

@ -1,27 +0,0 @@
# 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 CommentObserver < ActiveRecord::Observer
def after_create(comment)
if comment.commented.is_a?(News) && Setting.notified_events.include?('news_comment_added')
##by senluo
thread3=Thread.new do
Mailer.news_comment_added(comment).deliver
end
end
end
end

@ -1,4 +0,0 @@
class DiscussDemo < ActiveRecord::Base
attr_accessible :title, :body
has_many_kindeditor_assets :assets, :dependent => :destroy
end

@ -1,90 +1,95 @@
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang # Copyright (C) 2006-2013 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Document < ActiveRecord::Base class Document < ActiveRecord::Base
include Redmine::SafeAttributes include Redmine::SafeAttributes
belongs_to :project belongs_to :project
belongs_to :user belongs_to :user
belongs_to :category, :class_name => "DocumentCategory", :foreign_key => "category_id" belongs_to :category, :class_name => "DocumentCategory", :foreign_key => "category_id"
include UserScoreHelper include UserScoreHelper
after_save :be_user_score # user_score after_save :be_user_score # user_score
after_destroy :down_user_score after_destroy :down_user_score
acts_as_attachable :delete_permission => :delete_documents acts_as_attachable :delete_permission => :delete_documents
# 被ForgeActivity虚拟关联 after_create :send_mail
has_many :forge_acts, :class_name => 'ForgeActivity',:as =>:forge_act ,:dependent => :destroy # 被ForgeActivity虚拟关联
# end has_many :forge_acts, :class_name => 'ForgeActivity',:as =>:forge_act ,:dependent => :destroy
acts_as_searchable :columns => ['title', "#{table_name}.description"], :include => :project # end
acts_as_event :title => Proc.new {|o| "#{l(:label_document)}: #{o.title}"}, acts_as_searchable :columns => ['title', "#{table_name}.description"], :include => :project
#:author => Proc.new {|o| o.attachments.reorder("#{Attachment.table_name}.created_on ASC").first.try(:author) }, acts_as_event :title => Proc.new {|o| "#{l(:label_document)}: #{o.title}"},
:author => Proc.new {|o| User.find(o.user_id)}, #:author => Proc.new {|o| o.attachments.reorder("#{Attachment.table_name}.created_on ASC").first.try(:author) },
:url => Proc.new {|o| {:controller => 'documents', :action => 'show', :id => o.id}} :author => Proc.new {|o| User.find(o.user_id)},
acts_as_activity_provider :find_options => {:include => :project}, :url => Proc.new {|o| {:controller => 'documents', :action => 'show', :id => o.id}}
:is_public => 'documents.is_public' 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 validates_presence_of :project, :title, :category
after_create :act_as_forge_activity validates_length_of :title, :maximum => 60
scope :visible, lambda {|*args| after_create :act_as_forge_activity
includes(:project).where(Project.allowed_to_condition(args.shift || User.current, :view_documents, *args)) 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'
safe_attributes 'category_id', 'title', 'description','is_public'
def visible?(user=User.current)
!user.nil? && user.allowed_to?(:view_documents, project) def visible?(user=User.current)
end !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 def has_right?(project,user=User.current)
end user.admin? || user.member_of?(project) || self.is_public==1
end
def initialize(attributes=nil, *args)
super def initialize(attributes=nil, *args)
if new_record? super
self.category ||= DocumentCategory.default if new_record?
end self.category ||= DocumentCategory.default
end end
end
def updated_on
unless @updated_on def updated_on
a = attachments.last unless @updated_on
@updated_on = (a && a.created_on) || created_on a = attachments.last
end @updated_on = (a && a.created_on) || created_on
@updated_on end
end @updated_on
end
# update user score
def be_user_score # update user score
UserScore.project(:push_document, self.user,self,{ document_id: self.id }) def be_user_score
update_document(self.user,1) UserScore.project(:push_document, self.user,self,{ document_id: self.id })
update_document(self.user,2,self.project) update_document(self.user,1)
end update_document(self.user,2,self.project)
end
def down_user_score
update_document(self.user,1) def down_user_score
update_document(self.user,2,self.project) update_document(self.user,1)
end update_document(self.user,2,self.project)
end
# Time 2015-03-02 10:51:16
# Author lizanle # Time 2015-03-02 10:51:16
# Description 新创建的document要在公共表ForgeActivity中记录 # Author lizanle
def act_as_forge_activity # Description 新创建的document要在公共表ForgeActivity中记录
self.forge_acts << ForgeActivity.new(:user_id => self.user_id, def act_as_forge_activity
:project_id => self.project_id) self.forge_acts << ForgeActivity.new(:user_id => self.user_id,
end :project_id => self.project_id)
end
end
def send_mail
Mailer.run.document_added(self) if Setting.notified_events.include?('document_added')
end
end

@ -1,25 +0,0 @@
# 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 DocumentObserver < ActiveRecord::Observer
def after_create(document)
##by senluo
thread2=Thread.new do
Mailer.document_added(document).deliver if Setting.notified_events.include?('document_added')
end
end
end

@ -1,59 +1,58 @@
class Forum < ActiveRecord::Base class Forum < ActiveRecord::Base
include Redmine::SafeAttributes include Redmine::SafeAttributes
include ApplicationHelper include ApplicationHelper
has_many_kindeditor_assets :assets, :dependent => :destroy 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 :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" has_many :memos, :dependent => :destroy, conditions: "parent_id IS NULL"
belongs_to :creator, :class_name => "User", :foreign_key => 'creator_id' belongs_to :creator, :class_name => "User", :foreign_key => 'creator_id'
safe_attributes 'name', safe_attributes 'name',
'description', 'description',
'topic_count', 'topic_count',
'memo_count', 'memo_count',
'last_memo_id', 'last_memo_id',
'creator_id', 'creator_id',
'sticky', 'sticky',
'locked' 'locked'
validates_presence_of :name, :creator_id, :description validates_presence_of :name, :creator_id, :description
validates_length_of :name, maximum: 50 validates_length_of :name, maximum: 50
#validates_length_of :description, maximum: 255 #validates_length_of :description, maximum: 255
validates :name, :uniqueness => true validates :name, :uniqueness => true
after_destroy :delete_kindeditor_assets after_destroy :delete_kindeditor_assets
acts_as_taggable acts_as_taggable
scope :by_join_date, order("created_at DESC") scope :by_join_date, order("created_at DESC")
#after_create :send_email after_create :send_mail
def reset_counters! def reset_counters!
self.class.reset_counters!(id) self.class.reset_counters!(id)
end end
def editable_by? user def editable_by? user
# user && user.logged? || (self.author == usr && usr.allowed_to?(:edit_own_messages, project)) # user && user.logged? || (self.author == usr && usr.allowed_to?(:edit_own_messages, project))
self.creator == user || user.admin? self.creator == user || user.admin?
end end
def destroyable_by? user def destroyable_by? user
# user && user.logged? && Forum.find(self.forum_id).creator_id == user.id || user.admin? # user && user.logged? && Forum.find(self.forum_id).creator_id == user.id || user.admin?
self.creator == user || user.admin? self.creator == user || user.admin?
end end
def send_email def send_mail
Thread.start do logger.debug "send mail for forum add."
Mailer.forum_add(self).deliver if Setting.notified_events.include?('forum_add') Mailer.run.forum_add(self) if Setting.notified_events.include?('forum_add')
end end
end # Updates topic_count, memo_count and last_memo_id attributes for +board_id+
# Updates topic_count, memo_count and last_memo_id attributes for +board_id+ def self.reset_counters!(forum_id)
def self.reset_counters!(forum_id) forum_id = forum_id.to_i
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)," +
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)," +
" 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})",
" last_memo_id = (SELECT MAX(id) FROM #{Memo.table_name} WHERE forum_id=#{forum_id})", ["id = ?", forum_id])
["id = ?", forum_id]) end
end
# Time 2015-03-26 15:50:54
# Time 2015-03-26 15:50:54 # Author lizanle
# Author lizanle # Description 删除论坛后删除对应的资源
# Description 删除论坛后删除对应的资源 def delete_kindeditor_assets
def delete_kindeditor_assets delete_kindeditor_assets_from_disk self.id,OwnerTypeHelper::FORUM
delete_kindeditor_assets_from_disk self.id,2 end
end
end
end

@ -1,8 +0,0 @@
class ForumObserver < ActiveRecord::Observer
# def after_create(forum)
# Thread.start do
# Mailer.forum_add(forum).deliver if Setting.notified_events.include?('forum_add')
# end
#
# end
end

@ -1,30 +1,28 @@
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang # Copyright (C) 2006-2013 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class IssueObserver < ActiveRecord::Observer class IssueObserver < ActiveRecord::Observer
def after_create(issue) def after_create(issue)
Thread.start do # 将跟踪者与本项目的其他成员都设为收件方,并去重,不在进行抄送,
# 将跟踪者与本项目的其他成员都设为收件方,并去重,不在进行抄送, recipients = issue.recipients - issue.watcher_recipients + issue.watcher_recipients
recipients = issue.recipients - issue.watcher_recipients + issue.watcher_recipients recipients.each do |rec|
recipients.each do |rec| Mailer.run.issue_add(issue,rec) if Setting.notified_events.include?('issue_added')
Mailer.issue_add(issue,rec).deliver if Setting.notified_events.include?('issue_added') end
end
end end
end
end
end

@ -310,7 +310,7 @@ class IssueQuery < Query
:order => options[:order], :order => options[:order],
:limit => options[:limit], :limit => options[:limit],
:offset => options[:offset] :offset => options[:offset]
) ).reverse
rescue ::ActiveRecord::StatementInvalid => e rescue ::ActiveRecord::StatementInvalid => e
raise StatementInvalid.new(e.message) raise StatementInvalid.new(e.message)
end end

@ -1,36 +1,34 @@
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang # Copyright (C) 2006-2013 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class JournalObserver < ActiveRecord::Observer class JournalObserver < ActiveRecord::Observer
def after_create(journal) def after_create(journal)
if journal.notify? && if journal.notify? &&
(Setting.notified_events.include?('issue_updated') || (Setting.notified_events.include?('issue_updated') ||
(Setting.notified_events.include?('issue_note_added') && journal.notes.present?) || (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_status_updated') && journal.new_status.present?) ||
(Setting.notified_events.include?('issue_priority_updated') && journal.new_value_for('priority_id').present?) (Setting.notified_events.include?('issue_priority_updated') && journal.new_value_for('priority_id').present?)
) )
Thread.start do # 将跟踪者与本项目的其他成员都设为收件方,并去重,不在进行抄送,
# 将跟踪者与本项目的其他成员都设为收件方,并去重,不在进行抄送, recipients = journal.recipients - journal.watcher_recipients + journal.watcher_recipients
recipients = journal.recipients - journal.watcher_recipients + journal.watcher_recipients recipients.each do |rec|
recipients.each do |rec|
Mailer.run.issue_edit(journal,rec)
Mailer.issue_edit(journal,rec).deliver end
end end
end end
end end
end
end

@ -1,167 +1,179 @@
# fq # fq
# 数据库字段中带有m前缀和is_readed是二次开发添加之前的字段基本复用 # 数据库字段中带有m前缀和is_readed是二次开发添加之前的字段基本复用
# 注意reply_id 是提到人的id不是留言id, Base中叫做 at_user # 注意reply_id 是提到人的id不是留言id, Base中叫做 at_user
class JournalsForMessage < ActiveRecord::Base class JournalsForMessage < ActiveRecord::Base
include Redmine::SafeAttributes include Redmine::SafeAttributes
include UserScoreHelper include UserScoreHelper
safe_attributes "jour_type", # 留言所属类型 include ApplicationHelper
"jour_id", # 留言所属类型的id has_many_kindeditor_assets :assets, :dependent => :destroy
"notes", # 留言内容 safe_attributes "jour_type", # 留言所属类型
"reply_id", # 留言被回复留言者的用户id(用户a回复了用户b这是b的id用以查询谁给b留言了) "jour_id", # 留言所属类型的id
"status", # 留言是否被查看(弃用) "notes", # 留言内容
"user_id", # 留言者的id "reply_id", # 留言被回复留言者的用户id(用户a回复了用户b这是b的id用以查询谁给b留言了)
"m_parent_id", # 留言信息的父留言id "status", # 留言是否被查看(弃用)
"is_readed", # 留言是否已读 "user_id", # 留言者的id
"m_reply_count", # 留言的回复数量 "m_parent_id", # 留言信息的父留言id
"m_reply_id" # 回复某留言的留言id(a留言回复了b留言这是b留言的id) "is_readed", # 留言是否已读
"is_comprehensive_evaluation" # 1 教师评论、2 匿评、3 留言 "m_reply_count", # 留言的回复数量
acts_as_tree :foreign_key => 'm_parent_id', :counter_cache => :m_reply_count, :order => "#{JournalsForMessage.table_name}.created_on ASC" "m_reply_id" # 回复某留言的留言id(a留言回复了b留言这是b留言的id)
"is_comprehensive_evaluation" # 1 教师评论、2 匿评、3 留言
belongs_to :project, acts_as_tree :foreign_key => 'm_parent_id', :counter_cache => :m_reply_count, :order => "#{JournalsForMessage.table_name}.created_on ASC"
:foreign_key => 'jour_id', after_destroy :delete_kindeditor_assets
:conditions => "#{self.table_name}.jour_type = 'Project' " belongs_to :project,
belongs_to :course, :foreign_key => 'jour_id',
: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 :jour, :polymorphic => true
belongs_to :at_user, :class_name => "User", :foreign_key => 'reply_id' belongs_to :user
belongs_to :homework_attach
acts_as_event :title => Proc.new {|o| "#{l(:label_my_message)}"}, belongs_to :at_user, :class_name => "User", :foreign_key => 'reply_id'
:datetime => Proc.new {|o| o.updated_on },
:author => Proc.new {|o| o.user }, acts_as_event :title => Proc.new {|o| "#{l(:label_my_message)}"},
:description => Proc.new{|o| o.notes }, :datetime => Proc.new {|o| o.updated_on },
:type => Proc.new {|o| o.jour_type }, :author => Proc.new {|o| o.user },
:url => Proc.new {|o| :description => Proc.new{|o| o.notes },
if o.jour.kind_of? Project :type => Proc.new {|o| o.jour_type },
{:controller => 'projects', :action => 'feedback', :id => o.jour, :r => o.id, :anchor => "word_li_#{o.id}"} :url => Proc.new {|o|
elsif o.jour.kind_of? Course if o.jour.kind_of? Project
{:controller => 'courses', :action => 'feedback', :id => o.jour, :r => o.id, :anchor => "word_li_#{o.id}"} {:controller => 'projects', :action => 'feedback', :id => o.jour, :r => o.id, :anchor => "word_li_#{o.id}"}
end elsif o.jour.kind_of? Course
} {:controller => 'courses', :action => 'feedback', :id => o.jour, :r => o.id, :anchor => "word_li_#{o.id}"}
acts_as_activity_provider :author_key => :user_id, end
:timestamp => "#{self.table_name}.updated_on", }
:find_options => {:include => :project } acts_as_activity_provider :author_key => :user_id,
:timestamp => "#{self.table_name}.updated_on",
acts_as_activity_provider :type => 'course_journals_for_messages', :find_options => {:include => :project }
:author_key => :user_id,
:timestamp => "#{self.table_name}.updated_on", acts_as_activity_provider :type => 'course_journals_for_messages',
:find_options => {:include => :course } :author_key => :user_id,
:permission => :view_course_journals_for_messages,
:timestamp => "#{self.table_name}.updated_on",
has_many :acts, :class_name => 'Activity', :as => :act, :dependent => :destroy :find_options => {:include => :course }
acts_as_attachable
validates :notes, presence: true
after_create :act_as_activity #huang has_many :acts, :class_name => 'Activity', :as => :act, :dependent => :destroy
after_create :reset_counters!
after_destroy :reset_counters! validates :notes, presence: true, if: :is_homework_jour?
after_save :be_user_score after_create :act_as_activity #huang
after_destroy :down_user_score after_create :reset_counters!
after_destroy :reset_counters!
# default_scope { where('m_parent_id IS NULL') } after_save :be_user_score
after_destroy :down_user_score
def self.create_by_user? user
if user.anonymous? # default_scope { where('m_parent_id IS NULL') }
return false
else def self.create_by_user? user
return true if user.anonymous?
end return false
end else
return true
end
def self.remove_by_user? user end
if( self.user == user ||
( self.jour.kind_of?(User) && self.jour== user )
) def self.remove_by_user? user
true if( self.user == user ||
else ( self.jour.kind_of?(User) && self.jour== user )
false )
end true
end else
false
def self.delete_message(message_id) end
self.find(message_id).destroy end
# self.destroy_all "id = #{message_id}"
end def self.delete_message(message_id)
self.find(message_id).destroy
def reference_user # self.destroy_all "id = #{message_id}"
User.find(reply_id) end
end
def is_homework_jour?
def delete_by_user?user self.jour_type != "HomeworkAttach"
# 用户可删除自己的留言 end
if self.user.id == user.id || user.admin?
return true def reference_user
else User.find(reply_id)
return false end
end
end def delete_by_user?user
# 用户可删除自己的留言
def self.reference_message(user_id) if self.user.id == user.id || user.admin?
@user = User.find(user_id) return true
message = JournalsForMessage.find_by_sql("select * from journals_for_messages where reply_id = #{@user.id} else
or (jour_type = 'Bid' and jour_id in (select id from bids where author_id = #{@user.id}))") return false
message end
end end
def act_as_activity def self.reference_message(user_id)
if self.jour_type == 'Principal' @user = User.find(user_id)
unless self.user_id == self.jour.id && self.user_id != self.reply_id && self.reply_id != 0 message = JournalsForMessage.find_by_sql("select * from journals_for_messages where reply_id = #{@user.id}
# self.acts << Activity.new(:user_id => self.user_id) or (jour_type = 'Bid' and jour_id in (select id from bids where author_id = #{@user.id}))")
self.acts << Activity.new(:user_id => self.jour_id) message
end end
elsif self.jour_type == 'Project'
self.acts << Activity.new(:user_id => self.reply_id) def act_as_activity
elsif self.jour_type == 'Course' if self.jour_type == 'Principal'
self.acts << Activity.new(:user_id => self.reply_id) unless self.user_id == self.jour.id && self.user_id != self.reply_id && self.reply_id != 0
else # self.acts << Activity.new(:user_id => self.user_id)
end self.acts << Activity.new(:user_id => self.jour_id)
end end
elsif self.jour_type == 'Project'
def reset_counters! self.acts << Activity.new(:user_id => self.reply_id)
self.class.reset_counters!(self) elsif self.jour_type == 'Course'
end self.acts << Activity.new(:user_id => self.reply_id)
def self.reset_counters! journals_for_messages else
# jfm_id = journals_for_messages.id.to_i end
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} ) end
update_all("m_reply_count = #{count.to_i}", ["id = ?", journals_for_messages.m_parent_id])
end def reset_counters!
self.class.reset_counters!(self)
#如果是在项目中留言则返回该项目否则返回nil - zjc end
def project def self.reset_counters! journals_for_messages
if self.jour_type == 'Project' # jfm_id = journals_for_messages.id.to_i
Project.find(self.jour_id) 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} )
else update_all("m_reply_count = #{count.to_i}", ["id = ?", journals_for_messages.m_parent_id])
nil end
end
end #如果是在项目中留言则返回该项目否则返回nil - zjc
def project
# 更新用户分数 -by zjc if self.jour_type == 'Project'
def be_user_score Project.find(self.jour_id)
#新建了留言回复 else
if self.reply_id != 0 nil
#协同得分加分 end
UserScore.joint(:reply_message, self.user,User.find(self.reply_id),self, { journals_for_messages_id: self.id }) end
update_replay_for_message(self.user,1)
if self.jour_type == "Project" # 更新用户分数 -by zjc
update_replay_for_message(self.user,2,self.jour) def be_user_score
end #新建了留言回复
end if self.reply_id != 0
end #协同得分加分
# 更新用户分数 -by zjc UserScore.joint(:reply_message, self.user,User.find(self.reply_id),self, { journals_for_messages_id: self.id })
def down_user_score update_replay_for_message(self.user,1)
#删除了留言回复 if self.jour_type == "Project"
if self.reply_id != 0 update_replay_for_message(self.user,2,self.jour)
#协同得分减分 end
UserScore.joint(:reply_message_delete, self.user,User.find(self.reply_id), { journals_for_messages_id: self.id }) end
update_replay_for_message(self.user,1) end
if self.jour_type == "Project" # 更新用户分数 -by zjc
update_replay_for_message(self.user,2,self.jour) def down_user_score
end #删除了留言回复
end if self.reply_id != 0
end #协同得分减分
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)
end 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

@ -1,9 +1,7 @@
# Added by young # Added by young
class JournalsForMessageObserver < ActiveRecord::Observer class JournalsForMessageObserver < ActiveRecord::Observer
def after_create(journals_for_message) def after_create(journals_for_message)
thread1 = Thread.start do Mailer.run.journals_for_message_add(User.current, journals_for_message)
Mailer.journals_for_message_add(User.current, journals_for_message).deliver end
end end
end
end

@ -1,490 +1,490 @@
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang # Copyright (C) 2006-2013 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class MailHandler < ActionMailer::Base class MailHandler < ActionMailer::Base
include ActionView::Helpers::SanitizeHelper include ActionView::Helpers::SanitizeHelper
include Redmine::I18n include Redmine::I18n
class UnauthorizedAction < StandardError; end class UnauthorizedAction < StandardError; end
class MissingInformation < StandardError; end class MissingInformation < StandardError; end
attr_reader :email, :user attr_reader :email, :user
def self.receive(email, options={}) def self.receive(email, options={})
@@handler_options = options.dup @@handler_options = options.dup
@@handler_options[:issue] ||= {} @@handler_options[:issue] ||= {}
if @@handler_options[:allow_override].is_a?(String) if @@handler_options[:allow_override].is_a?(String)
@@handler_options[:allow_override] = @@handler_options[:allow_override].split(',').collect(&:strip) @@handler_options[:allow_override] = @@handler_options[:allow_override].split(',').collect(&:strip)
end end
@@handler_options[:allow_override] ||= [] @@handler_options[:allow_override] ||= []
# Project needs to be overridable if not specified # Project needs to be overridable if not specified
@@handler_options[:allow_override] << 'project' unless @@handler_options[:issue].has_key?(:project) @@handler_options[:allow_override] << 'project' unless @@handler_options[:issue].has_key?(:project)
# Status overridable by default # Status overridable by default
@@handler_options[:allow_override] << 'status' unless @@handler_options[:issue].has_key?(:status) @@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_account_notice] = (@@handler_options[:no_account_notice].to_s == '1')
@@handler_options[:no_notification] = (@@handler_options[:no_notification].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') @@handler_options[:no_permission_check] = (@@handler_options[:no_permission_check].to_s == '1')
email.force_encoding('ASCII-8BIT') if email.respond_to?(:force_encoding) email.force_encoding('ASCII-8BIT') if email.respond_to?(:force_encoding)
super(email) super(email)
end end
def logger def logger
Rails.logger Rails.logger
end end
cattr_accessor :ignored_emails_headers cattr_accessor :ignored_emails_headers
@@ignored_emails_headers = { @@ignored_emails_headers = {
'X-Auto-Response-Suppress' => 'oof', 'X-Auto-Response-Suppress' => 'oof',
'Auto-Submitted' => /^auto-/ 'Auto-Submitted' => /^auto-/
} }
# Processes incoming emails # Processes incoming emails
# Returns the created object (eg. an issue, a message) or false # Returns the created object (eg. an issue, a message) or false
def receive(email) def receive(email)
@email = email @email = email
sender_email = email.from.to_a.first.to_s.strip sender_email = email.from.to_a.first.to_s.strip
# Ignore emails received from the application emission address to avoid hell cycles # Ignore emails received from the application emission address to avoid hell cycles
if sender_email.downcase == Setting.mail_from.to_s.strip.downcase if sender_email.downcase == Setting.mail_from.to_s.strip.downcase
if logger && logger.info if logger && logger.info
logger.info "MailHandler: ignoring email from Redmine emission address [#{sender_email}]" logger.info "MailHandler: ignoring email from Redmine emission address [#{sender_email}]"
end end
return false return false
end end
# Ignore auto generated emails # Ignore auto generated emails
self.class.ignored_emails_headers.each do |key, ignored_value| self.class.ignored_emails_headers.each do |key, ignored_value|
value = email.header[key] value = email.header[key]
if value if value
value = value.to_s.downcase value = value.to_s.downcase
if (ignored_value.is_a?(Regexp) && value.match(ignored_value)) || value == ignored_value if (ignored_value.is_a?(Regexp) && value.match(ignored_value)) || value == ignored_value
if logger && logger.info if logger && logger.info
logger.info "MailHandler: ignoring email with #{key}:#{value} header" logger.info "MailHandler: ignoring email with #{key}:#{value} header"
end end
return false return false
end end
end end
end end
@user = User.find_by_mail(sender_email) if sender_email.present? @user = User.find_by_mail(sender_email) if sender_email.present?
if @user && !@user.active? if @user && !@user.active?
if logger && logger.info if logger && logger.info
logger.info "MailHandler: ignoring email from non-active user [#{@user.login}]" logger.info "MailHandler: ignoring email from non-active user [#{@user.login}]"
end end
return false return false
end end
if @user.nil? if @user.nil?
# Email was submitted by an unknown user # Email was submitted by an unknown user
case @@handler_options[:unknown_user] case @@handler_options[:unknown_user]
when 'accept' when 'accept'
@user = User.anonymous @user = User.anonymous
when 'create' when 'create'
@user = create_user_from_email @user = create_user_from_email
if @user if @user
if logger && logger.info if logger && logger.info
logger.info "MailHandler: [#{@user.login}] account created" logger.info "MailHandler: [#{@user.login}] account created"
end end
add_user_to_group(@@handler_options[:default_group]) add_user_to_group(@@handler_options[:default_group])
unless @@handler_options[:no_account_notice] unless @@handler_options[:no_account_notice]
Mailer.account_information(@user, @user.password).deliver Mailer.run.account_information(@user, @user.password)
end end
else else
if logger && logger.error if logger && logger.error
logger.error "MailHandler: could not create account for [#{sender_email}]" logger.error "MailHandler: could not create account for [#{sender_email}]"
end end
return false return false
end end
else else
# Default behaviour, emails from unknown users are ignored # Default behaviour, emails from unknown users are ignored
if logger && logger.info if logger && logger.info
logger.info "MailHandler: ignoring email from unknown user [#{sender_email}]" logger.info "MailHandler: ignoring email from unknown user [#{sender_email}]"
end end
return false return false
end end
end end
User.current = @user User.current = @user
dispatch dispatch
end end
private private
MESSAGE_ID_RE = %r{^<?redmine\.([a-z0-9_]+)\-(\d+)\.\d+@} MESSAGE_ID_RE = %r{^<?redmine\.([a-z0-9_]+)\-(\d+)\.\d+@}
ISSUE_REPLY_SUBJECT_RE = %r{\[[^\]]*#(\d+)\]} ISSUE_REPLY_SUBJECT_RE = %r{\[[^\]]*#(\d+)\]}
MESSAGE_REPLY_SUBJECT_RE = %r{\[[^\]]*msg(\d+)\]} MESSAGE_REPLY_SUBJECT_RE = %r{\[[^\]]*msg(\d+)\]}
def dispatch def dispatch
headers = [email.in_reply_to, email.references].flatten.compact headers = [email.in_reply_to, email.references].flatten.compact
subject = email.subject.to_s subject = email.subject.to_s
if headers.detect {|h| h.to_s =~ MESSAGE_ID_RE} if headers.detect {|h| h.to_s =~ MESSAGE_ID_RE}
klass, object_id = $1, $2.to_i klass, object_id = $1, $2.to_i
method_name = "receive_#{klass}_reply" method_name = "receive_#{klass}_reply"
if self.class.private_instance_methods.collect(&:to_s).include?(method_name) if self.class.private_instance_methods.collect(&:to_s).include?(method_name)
send method_name, object_id send method_name, object_id
else else
# ignoring it # ignoring it
end end
elsif m = subject.match(ISSUE_REPLY_SUBJECT_RE) elsif m = subject.match(ISSUE_REPLY_SUBJECT_RE)
receive_issue_reply(m[1].to_i) receive_issue_reply(m[1].to_i)
elsif m = subject.match(MESSAGE_REPLY_SUBJECT_RE) elsif m = subject.match(MESSAGE_REPLY_SUBJECT_RE)
receive_message_reply(m[1].to_i) receive_message_reply(m[1].to_i)
else else
dispatch_to_default dispatch_to_default
end end
rescue ActiveRecord::RecordInvalid => e rescue ActiveRecord::RecordInvalid => e
# TODO: send a email to the user # TODO: send a email to the user
logger.error e.message if logger logger.error e.message if logger
false false
rescue MissingInformation => e rescue MissingInformation => e
logger.error "MailHandler: missing information from #{user}: #{e.message}" if logger logger.error "MailHandler: missing information from #{user}: #{e.message}" if logger
false false
rescue UnauthorizedAction => e rescue UnauthorizedAction => e
logger.error "MailHandler: unauthorized attempt from #{user}" if logger logger.error "MailHandler: unauthorized attempt from #{user}" if logger
false false
end end
def dispatch_to_default def dispatch_to_default
receive_issue receive_issue
end end
# Creates a new issue # Creates a new issue
def receive_issue def receive_issue
project = target_project project = target_project
# check permission # check permission
unless @@handler_options[:no_permission_check] unless @@handler_options[:no_permission_check]
raise UnauthorizedAction unless user.allowed_to?(:add_issues, project) raise UnauthorizedAction unless user.allowed_to?(:add_issues, project)
end end
issue = Issue.new(:author => user, :project => project) issue = Issue.new(:author => user, :project => project)
issue.safe_attributes = issue_attributes_from_keywords(issue) issue.safe_attributes = issue_attributes_from_keywords(issue)
issue.safe_attributes = {'custom_field_values' => custom_field_values_from_keywords(issue)} issue.safe_attributes = {'custom_field_values' => custom_field_values_from_keywords(issue)}
issue.subject = cleaned_up_subject issue.subject = cleaned_up_subject
if issue.subject.blank? if issue.subject.blank?
issue.subject = '(no subject)' issue.subject = '(no subject)'
end end
issue.description = cleaned_up_text_body issue.description = cleaned_up_text_body
# add To and Cc as watchers before saving so the watchers can reply to Redmine # add To and Cc as watchers before saving so the watchers can reply to Redmine
add_watchers(issue) add_watchers(issue)
issue.save! issue.save!
add_attachments(issue) add_attachments(issue)
logger.info "MailHandler: issue ##{issue.id} created by #{user}" if logger && logger.info logger.info "MailHandler: issue ##{issue.id} created by #{user}" if logger && logger.info
issue issue
end end
# Adds a note to an existing issue # Adds a note to an existing issue
def receive_issue_reply(issue_id, from_journal=nil) def receive_issue_reply(issue_id, from_journal=nil)
issue = Issue.find_by_id(issue_id) issue = Issue.find_by_id(issue_id)
return unless issue return unless issue
# check permission # check permission
unless @@handler_options[:no_permission_check] unless @@handler_options[:no_permission_check]
unless user.allowed_to?(:add_issue_notes, issue.project) || unless user.allowed_to?(:add_issue_notes, issue.project) ||
user.allowed_to?(:edit_issues, issue.project) user.allowed_to?(:edit_issues, issue.project)
raise UnauthorizedAction raise UnauthorizedAction
end end
end end
# ignore CLI-supplied defaults for new issues # ignore CLI-supplied defaults for new issues
@@handler_options[:issue].clear @@handler_options[:issue].clear
journal = issue.init_journal(user) journal = issue.init_journal(user)
if from_journal && from_journal.private_notes? if from_journal && from_journal.private_notes?
# If the received email was a reply to a private note, make the added note private # If the received email was a reply to a private note, make the added note private
issue.private_notes = true issue.private_notes = true
end end
issue.safe_attributes = issue_attributes_from_keywords(issue) issue.safe_attributes = issue_attributes_from_keywords(issue)
issue.safe_attributes = {'custom_field_values' => custom_field_values_from_keywords(issue)} issue.safe_attributes = {'custom_field_values' => custom_field_values_from_keywords(issue)}
journal.notes = cleaned_up_text_body journal.notes = cleaned_up_text_body
add_attachments(issue) add_attachments(issue)
issue.save! issue.save!
if logger && logger.info if logger && logger.info
logger.info "MailHandler: issue ##{issue.id} updated by #{user}" logger.info "MailHandler: issue ##{issue.id} updated by #{user}"
end end
journal journal
end end
# Reply will be added to the issue # Reply will be added to the issue
def receive_journal_reply(journal_id) def receive_journal_reply(journal_id)
journal = Journal.find_by_id(journal_id) journal = Journal.find_by_id(journal_id)
if journal && journal.journalized_type == 'Issue' if journal && journal.journalized_type == 'Issue'
receive_issue_reply(journal.journalized_id, journal) receive_issue_reply(journal.journalized_id, journal)
end end
end end
# Receives a reply to a forum message # Receives a reply to a forum message
def receive_message_reply(message_id) def receive_message_reply(message_id)
message = Message.find_by_id(message_id) message = Message.find_by_id(message_id)
if message if message
message = message.root message = message.root
unless @@handler_options[:no_permission_check] unless @@handler_options[:no_permission_check]
raise UnauthorizedAction unless user.allowed_to?(:add_messages, message.project) raise UnauthorizedAction unless user.allowed_to?(:add_messages, message.project)
end end
if !message.locked? if !message.locked?
reply = Message.new(:subject => cleaned_up_subject.gsub(%r{^.*msg\d+\]}, '').strip, reply = Message.new(:subject => cleaned_up_subject.gsub(%r{^.*msg\d+\]}, '').strip,
:content => cleaned_up_text_body) :content => cleaned_up_text_body)
reply.author = user reply.author = user
reply.board = message.board reply.board = message.board
message.children << reply message.children << reply
add_attachments(reply) add_attachments(reply)
reply reply
else else
if logger && logger.info if logger && logger.info
logger.info "MailHandler: ignoring reply from [#{sender_email}] to a locked topic" logger.info "MailHandler: ignoring reply from [#{sender_email}] to a locked topic"
end end
end end
end end
end end
def add_attachments(obj) def add_attachments(obj)
if email.attachments && email.attachments.any? if email.attachments && email.attachments.any?
email.attachments.each do |attachment| email.attachments.each do |attachment|
obj.attachments << Attachment.create(:container => obj, obj.attachments << Attachment.create(:container => obj,
:file => attachment.decoded, :file => attachment.decoded,
:filename => attachment.filename, :filename => attachment.filename,
:author => user, :author => user,
:content_type => attachment.mime_type) :content_type => attachment.mime_type)
end end
end end
end end
# Adds To and Cc as watchers of the given object if the sender has the # Adds To and Cc as watchers of the given object if the sender has the
# appropriate permission # appropriate permission
def add_watchers(obj) def add_watchers(obj)
if user.allowed_to?("add_#{obj.class.name.underscore}_watchers".to_sym, obj.project) 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} addresses = [email.to, email.cc].flatten.compact.uniq.collect {|a| a.strip.downcase}
unless addresses.empty? unless addresses.empty?
watchers = User.active.where('LOWER(mail) IN (?)', addresses).all watchers = User.active.where('LOWER(mail) IN (?)', addresses).all
watchers.each {|w| obj.add_watcher(w)} watchers.each {|w| obj.add_watcher(w)}
end end
end end
end end
def get_keyword(attr, options={}) def get_keyword(attr, options={})
@keywords ||= {} @keywords ||= {}
if @keywords.has_key?(attr) if @keywords.has_key?(attr)
@keywords[attr] @keywords[attr]
else else
@keywords[attr] = begin @keywords[attr] = begin
if (options[:override] || @@handler_options[:allow_override].include?(attr.to_s)) && if (options[:override] || @@handler_options[:allow_override].include?(attr.to_s)) &&
(v = extract_keyword!(plain_text_body, attr, options[:format])) (v = extract_keyword!(plain_text_body, attr, options[:format]))
v v
elsif !@@handler_options[:issue][attr].blank? elsif !@@handler_options[:issue][attr].blank?
@@handler_options[:issue][attr] @@handler_options[:issue][attr]
end end
end end
end end
end end
# Destructively extracts the value for +attr+ in +text+ # Destructively extracts the value for +attr+ in +text+
# Returns nil if no matching keyword found # Returns nil if no matching keyword found
def extract_keyword!(text, attr, format=nil) def extract_keyword!(text, attr, format=nil)
keys = [attr.to_s.humanize] keys = [attr.to_s.humanize]
if attr.is_a?(Symbol) if attr.is_a?(Symbol)
if user && user.language.present? if user && user.language.present?
keys << l("field_#{attr}", :default => '', :locale => user.language) keys << l("field_#{attr}", :default => '', :locale => user.language)
end end
if Setting.default_language.present? if Setting.default_language.present?
keys << l("field_#{attr}", :default => '', :locale => Setting.default_language) keys << l("field_#{attr}", :default => '', :locale => Setting.default_language)
end end
end end
keys.reject! {|k| k.blank?} keys.reject! {|k| k.blank?}
keys.collect! {|k| Regexp.escape(k)} keys.collect! {|k| Regexp.escape(k)}
format ||= '.+' format ||= '.+'
keyword = nil keyword = nil
regexp = /^(#{keys.join('|')})[ \t]*:[ \t]*(#{format})\s*$/i regexp = /^(#{keys.join('|')})[ \t]*:[ \t]*(#{format})\s*$/i
if m = text.match(regexp) if m = text.match(regexp)
keyword = m[2].strip keyword = m[2].strip
text.gsub!(regexp, '') text.gsub!(regexp, '')
end end
keyword keyword
end end
def target_project def target_project
# TODO: other ways to specify project: # TODO: other ways to specify project:
# * parse the email To field # * parse the email To field
# * specific project (eg. Setting.mail_handler_target_project) # * specific project (eg. Setting.mail_handler_target_project)
target = Project.find_by_identifier(get_keyword(:project)) target = Project.find_by_identifier(get_keyword(:project))
raise MissingInformation.new('Unable to determine target project') if target.nil? raise MissingInformation.new('Unable to determine target project') if target.nil?
target target
end end
# Returns a Hash of issue attributes extracted from keywords in the email body # Returns a Hash of issue attributes extracted from keywords in the email body
def issue_attributes_from_keywords(issue) def issue_attributes_from_keywords(issue)
assigned_to = (k = get_keyword(:assigned_to, :override => true)) && find_assignee_from_keyword(k, issue) assigned_to = (k = get_keyword(:assigned_to, :override => true)) && find_assignee_from_keyword(k, issue)
attrs = { attrs = {
'tracker_id' => (k = get_keyword(:tracker)) && issue.project.trackers.named(k).first.try(:id), '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), 'status_id' => (k = get_keyword(:status)) && IssueStatus.named(k).first.try(:id),
'priority_id' => (k = get_keyword(:priority)) && IssuePriority.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), 'category_id' => (k = get_keyword(:category)) && issue.project.issue_categories.named(k).first.try(:id),
'assigned_to_id' => assigned_to.try(:id), 'assigned_to_id' => assigned_to.try(:id),
'fixed_version_id' => (k = get_keyword(:fixed_version, :override => true)) && 'fixed_version_id' => (k = get_keyword(:fixed_version, :override => true)) &&
issue.project.shared_versions.named(k).first.try(:id), issue.project.shared_versions.named(k).first.try(:id),
'start_date' => get_keyword(:start_date, :override => true, :format => '\d{4}-\d{2}-\d{2}'), '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}'), 'due_date' => get_keyword(:due_date, :override => true, :format => '\d{4}-\d{2}-\d{2}'),
'estimated_hours' => get_keyword(:estimated_hours, :override => true), 'estimated_hours' => get_keyword(:estimated_hours, :override => true),
'done_ratio' => get_keyword(:done_ratio, :override => true, :format => '(\d|10)?0') 'done_ratio' => get_keyword(:done_ratio, :override => true, :format => '(\d|10)?0')
}.delete_if {|k, v| v.blank? } }.delete_if {|k, v| v.blank? }
if issue.new_record? && attrs['tracker_id'].nil? if issue.new_record? && attrs['tracker_id'].nil?
attrs['tracker_id'] = issue.project.trackers.first.try(:id) attrs['tracker_id'] = issue.project.trackers.first.try(:id)
end end
attrs attrs
end end
# Returns a Hash of issue custom field values extracted from keywords in the email body # Returns a Hash of issue custom field values extracted from keywords in the email body
def custom_field_values_from_keywords(customized) def custom_field_values_from_keywords(customized)
customized.custom_field_values.inject({}) do |h, v| customized.custom_field_values.inject({}) do |h, v|
if keyword = get_keyword(v.custom_field.name, :override => true) 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) h[v.custom_field.id.to_s] = v.custom_field.value_from_keyword(keyword, customized)
end end
h h
end end
end end
# Returns the text/plain part of the email # Returns the text/plain part of the email
# If not found (eg. HTML-only email), returns the body with tags removed # If not found (eg. HTML-only email), returns the body with tags removed
def plain_text_body def plain_text_body
return @plain_text_body unless @plain_text_body.nil? return @plain_text_body unless @plain_text_body.nil?
part = email.text_part || email.html_part || email part = email.text_part || email.html_part || email
@plain_text_body = Redmine::CodesetUtil.to_utf8(part.body.decoded, part.charset) @plain_text_body = Redmine::CodesetUtil.to_utf8(part.body.decoded, part.charset)
# strip html tags and remove doctype directive # strip html tags and remove doctype directive
@plain_text_body = strip_tags(@plain_text_body.strip) @plain_text_body = strip_tags(@plain_text_body.strip)
@plain_text_body.sub! %r{^<!DOCTYPE .*$}, '' @plain_text_body.sub! %r{^<!DOCTYPE .*$}, ''
@plain_text_body @plain_text_body
end end
def cleaned_up_text_body def cleaned_up_text_body
cleanup_body(plain_text_body) cleanup_body(plain_text_body)
end end
def cleaned_up_subject def cleaned_up_subject
subject = email.subject.to_s subject = email.subject.to_s
subject.strip[0,255] subject.strip[0,255]
end end
def self.full_sanitizer def self.full_sanitizer
@full_sanitizer ||= HTML::FullSanitizer.new @full_sanitizer ||= HTML::FullSanitizer.new
end end
def self.assign_string_attribute_with_limit(object, attribute, value, limit=nil) def self.assign_string_attribute_with_limit(object, attribute, value, limit=nil)
limit ||= object.class.columns_hash[attribute.to_s].limit || 255 limit ||= object.class.columns_hash[attribute.to_s].limit || 255
value = value.to_s.slice(0, limit) value = value.to_s.slice(0, limit)
object.send("#{attribute}=", value) object.send("#{attribute}=", value)
end end
# Returns a User from an email address and a full name # Returns a User from an email address and a full name
def self.new_user_from_attributes(email_address, fullname=nil) def self.new_user_from_attributes(email_address, fullname=nil)
user = User.new user = User.new
# Truncating the email address would result in an invalid format # Truncating the email address would result in an invalid format
user.mail = email_address user.mail = email_address
assign_string_attribute_with_limit(user, 'login', email_address, User::LOGIN_LENGTH_LIMIT) assign_string_attribute_with_limit(user, 'login', email_address, User::LOGIN_LENGTH_LIMIT)
names = fullname.blank? ? email_address.gsub(/@.*$/, '').split('.') : fullname.split names = fullname.blank? ? email_address.gsub(/@.*$/, '').split('.') : fullname.split
assign_string_attribute_with_limit(user, 'firstname', names.shift, 30) assign_string_attribute_with_limit(user, 'firstname', names.shift, 30)
assign_string_attribute_with_limit(user, 'lastname', names.join(' '), 30) assign_string_attribute_with_limit(user, 'lastname', names.join(' '), 30)
user.lastname = '-' if user.lastname.blank? user.lastname = '-' if user.lastname.blank?
password_length = [Setting.password_min_length.to_i, 10].max password_length = [Setting.password_min_length.to_i, 10].max
user.password = Redmine::Utils.random_hex(password_length / 2 + 1) user.password = Redmine::Utils.random_hex(password_length / 2 + 1)
user.language = Setting.default_language user.language = Setting.default_language
user.mail_notification = 'only_my_events' user.mail_notification = 'only_my_events'
unless user.valid? unless user.valid?
user.login = "user#{Redmine::Utils.random_hex(6)}" unless user.errors[:login].blank? user.login = "user#{Redmine::Utils.random_hex(6)}" unless user.errors[:login].blank?
user.firstname = "-" unless user.errors[:firstname].blank? user.firstname = "-" unless user.errors[:firstname].blank?
(puts user.errors[:lastname];user.lastname = "-") unless user.errors[:lastname].blank? (puts user.errors[:lastname];user.lastname = "-") unless user.errors[:lastname].blank?
end end
user user
end end
# Creates a User for the +email+ sender # Creates a User for the +email+ sender
# Returns the user or nil if it could not be created # Returns the user or nil if it could not be created
def create_user_from_email def create_user_from_email
from = email.header['from'].to_s from = email.header['from'].to_s
addr, name = from, nil addr, name = from, nil
if m = from.match(/^"?(.+?)"?\s+<(.+@.+)>$/) if m = from.match(/^"?(.+?)"?\s+<(.+@.+)>$/)
addr, name = m[2], m[1] addr, name = m[2], m[1]
end end
if addr.present? if addr.present?
user = self.class.new_user_from_attributes(addr, name) user = self.class.new_user_from_attributes(addr, name)
if @@handler_options[:no_notification] if @@handler_options[:no_notification]
user.mail_notification = 'none' user.mail_notification = 'none'
end end
if user.save if user.save
user user
else else
logger.error "MailHandler: failed to create User: #{user.errors.full_messages}" if logger logger.error "MailHandler: failed to create User: #{user.errors.full_messages}" if logger
nil nil
end end
else else
logger.error "MailHandler: failed to create User: no FROM address found" if logger logger.error "MailHandler: failed to create User: no FROM address found" if logger
nil nil
end end
end end
# Adds the newly created user to default group # Adds the newly created user to default group
def add_user_to_group(default_group) def add_user_to_group(default_group)
if default_group.present? if default_group.present?
default_group.split(',').each do |group_name| default_group.split(',').each do |group_name|
if group = Group.named(group_name).first if group = Group.named(group_name).first
group.users << @user group.users << @user
elsif logger elsif logger
logger.warn "MailHandler: could not add user to [#{group_name}], group not found" logger.warn "MailHandler: could not add user to [#{group_name}], group not found"
end end
end end
end end
end end
# Removes the email body of text after the truncation configurations. # Removes the email body of text after the truncation configurations.
def cleanup_body(body) def cleanup_body(body)
delimiters = Setting.mail_handler_body_delimiters.to_s.split(/[\r\n]+/).reject(&:blank?).map {|s| Regexp.escape(s)} delimiters = Setting.mail_handler_body_delimiters.to_s.split(/[\r\n]+/).reject(&:blank?).map {|s| Regexp.escape(s)}
unless delimiters.empty? unless delimiters.empty?
regex = Regexp.new("^[> ]*(#{ delimiters.join('|') })\s*[\r\n].*", Regexp::MULTILINE) regex = Regexp.new("^[> ]*(#{ delimiters.join('|') })\s*[\r\n].*", Regexp::MULTILINE)
body = body.gsub(regex, '') body = body.gsub(regex, '')
end end
body.strip body.strip
end end
def find_assignee_from_keyword(keyword, issue) def find_assignee_from_keyword(keyword, issue)
keyword = keyword.to_s.downcase keyword = keyword.to_s.downcase
assignable = issue.assignable_users assignable = issue.assignable_users
assignee = nil assignee = nil
assignee ||= assignable.detect {|a| assignee ||= assignable.detect {|a|
a.mail.to_s.downcase == keyword || a.mail.to_s.downcase == keyword ||
a.login.to_s.downcase == keyword a.login.to_s.downcase == keyword
} }
if assignee.nil? && keyword.match(/ /) if assignee.nil? && keyword.match(/ /)
firstname, lastname = *(keyword.split) # "First Last Throwaway" firstname, lastname = *(keyword.split) # "First Last Throwaway"
assignee ||= assignable.detect {|a| assignee ||= assignable.detect {|a|
a.is_a?(User) && a.firstname.to_s.downcase == firstname && a.is_a?(User) && a.firstname.to_s.downcase == firstname &&
a.lastname.to_s.downcase == lastname a.lastname.to_s.downcase == lastname
} }
end end
if assignee.nil? if assignee.nil?
assignee ||= assignable.detect {|a| a.name.downcase == keyword} assignee ||= assignable.detect {|a| a.name.downcase == keyword}
end end
assignee assignee
end end
end end

File diff suppressed because it is too large Load Diff

@ -1,181 +1,179 @@
class Memo < ActiveRecord::Base class Memo < ActiveRecord::Base
include Redmine::SafeAttributes include Redmine::SafeAttributes
include UserScoreHelper include UserScoreHelper
include ApplicationHelper include ApplicationHelper
belongs_to :forum belongs_to :forum
has_many_kindeditor_assets :assets, :dependent => :destroy has_many_kindeditor_assets :assets, :dependent => :destroy
belongs_to :author, :class_name => "User", :foreign_key => 'author_id' belongs_to :author, :class_name => "User", :foreign_key => 'author_id'
validates_presence_of :author_id, :forum_id, :subject,:content validates_presence_of :author_id, :forum_id, :subject,:content
# 若是主题帖,则内容可以是空 # 若是主题帖,则内容可以是空
#validates :content, presence: true, if: Proc.new{|o| !o.parent_id.nil? } #validates :content, presence: true, if: Proc.new{|o| !o.parent_id.nil? }
validates_length_of :subject, maximum: 50 validates_length_of :subject, maximum: 50
#validates_length_of :content, maximum: 3072 #validates_length_of :content, maximum: 3072
validate :cannot_reply_to_locked_topic, :on => :create validate :cannot_reply_to_locked_topic, :on => :create
acts_as_tree :counter_cache => :replies_count, :order => "#{Memo.table_name}.created_at ASC" acts_as_tree :counter_cache => :replies_count, :order => "#{Memo.table_name}.created_at ASC"
acts_as_attachable acts_as_attachable
has_many :user_score_details, :class_name => 'UserScoreDetails',:as => :score_changeable_obj has_many :user_score_details, :class_name => 'UserScoreDetails',:as => :score_changeable_obj
has_many :praise_tread, as: :praise_tread_object, dependent: :destroy has_many :praise_tread, as: :praise_tread_object, dependent: :destroy
belongs_to :last_reply, :class_name => 'Memo', :foreign_key => 'last_reply_id' belongs_to :last_reply, :class_name => 'Memo', :foreign_key => 'last_reply_id'
# acts_as_searchable :column => ['subject', 'content'], # acts_as_searchable :column => ['subject', 'content'],
# #:include => { :forum => :p} # #:include => { :forum => :p}
# #:project_key => "#{Forum.table_name}.project_id" # #:project_key => "#{Forum.table_name}.project_id"
# :date_column => "#{table_name}.created_at" # :date_column => "#{table_name}.created_at"
acts_as_event :title => Proc.new {|o| "#{o.forum.name}: #{o.subject}"}, acts_as_event :title => Proc.new {|o| "#{o.forum.name}: #{o.subject}"},
:datetime => :updated_at, :datetime => :updated_at,
# :datetime => :created_at, # :datetime => :created_at,
:description => :content, :description => :content,
:author => :author, :author => :author,
:type => Proc.new {|o| o.parent_id.nil? ? 'Memo' : 'Reply'}, :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}"})} :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, acts_as_activity_provider :author_key => :author_id,
:func => 'memos', :func => 'memos',
:timestamp => 'created_at' :timestamp => 'created_at'
# :find_options => {:type => 'memos'} # :find_options => {:type => 'memos'}
# acts_as_watchable # acts_as_watchable
safe_attributes "author_id", safe_attributes "author_id",
"subject", "subject",
"content", "content",
"forum_id", "forum_id",
"last_memo_id", "last_memo_id",
"lock", "lock",
"sticky", "sticky",
"parent_id", "parent_id",
"replies_count" "replies_count"
after_create :add_author_as_watcher, :reset_counters!, :sendmail after_create :add_author_as_watcher, :reset_counters!, :send_mail
# after_update :update_memos_forum # after_update :update_memos_forum
after_destroy :reset_counters!,:delete_kindeditor_assets#,:down_user_score -- 公共区发帖暂不计入得分 after_destroy :reset_counters!,:delete_kindeditor_assets#,:down_user_score -- 公共区发帖暂不计入得分
# after_create :send_notification # after_create :send_notification
# after_save :plusParentAndForum # after_save :plusParentAndForum
# after_destroy :minusParentAndForum # after_destroy :minusParentAndForum
#before_save :be_user_score #before_save :be_user_score
# scope :visible, lambda { |*args| # scope :visible, lambda { |*args|
# includes(:forum => ).where() # includes(:forum => ).where()
# } # }
def sendmail def send_mail
thread1=Thread.new do Mailer.run.forum_message_added(self) if Setting.notified_events.include?('forum_message_added')
Mailer.forum_message_added(self).deliver if Setting.notified_events.include?('forum_message_added') end
end
end def cannot_reply_to_locked_topic
errors.add :base, l(:label_memo_locked) if root.locked? && self != root
def cannot_reply_to_locked_topic end
errors.add :base, l(:label_memo_locked) if root.locked? && self != root
end # def update_memos_forum
# if forum_id_changed?
# def update_memos_forum # Message.update_all({:board_id => board_id}, ["id = ? OR parent_id = ?", root.id, root.id ])
# if forum_id_changed? # Forum.reset_counters!(forum_id_was)
# Message.update_all({:board_id => board_id}, ["id = ? OR parent_id = ?", root.id, root.id ]) # Forum.reset_counters!(forum_id)
# Forum.reset_counters!(forum_id_was) # end
# Forum.reset_counters!(forum_id) # end
# end
# end def reset_counters!
if parent && parent.id
def reset_counters! Memo.update_all({:last_reply_id => parent.children.maximum(:id)}, {:id => parent.id})
if parent && parent.id parent.update_attribute(:updated_at, Time.now)
Memo.update_all({:last_reply_id => parent.children.maximum(:id)}, {:id => parent.id}) end
parent.update_attribute(:updated_at, Time.now) forum.reset_counters!
end end
forum.reset_counters!
end def sticky?
sticky == 1
def sticky? end
sticky == 1
end def replies
Memo.where("parent_id = ?", id)
def replies end
Memo.where("parent_id = ?", id)
end def locked?
self.lock
def locked? end
self.lock
end def editable_by? user
# user && user.logged? || (self.author == usr && usr.allowed_to?(:edit_own_messages, project))
def editable_by? user user.admin? || self.author == user
# user && user.logged? || (self.author == usr && usr.allowed_to?(:edit_own_messages, project)) end
user.admin? || self.author == user
end def destroyable_by? user
(user && self.author == user) || user.admin?
def destroyable_by? user #self.author == user || user.admin?
(user && self.author == user) || user.admin? end
#self.author == user || user.admin?
end def deleted_attach_able_by? user
(user && user.logged? && (self.author == user) ) || user.admin?
def deleted_attach_able_by? user end
(user && user.logged? && (self.author == user) ) || user.admin?
end private
private def add_author_as_watcher
Watcher.create(:watchable => self.root, :user => author)
def add_author_as_watcher end
Watcher.create(:watchable => self.root, :user => author)
end def send_notification
if Setting.notified_events.include?('message_posted')
def send_notification Mailer.run.message_posted(self)
if Setting.notified_events.include?('message_posted') end
Mailer.message_posted(self).deliver end
end
end def plusParentAndForum
@forum = Forum.find(self.forum_id)
def plusParentAndForum @forum.memo_count = @forum.memo_count.to_int + 1
@forum = Forum.find(self.forum_id) @forum.last_memo_id = self.id
@forum.memo_count = @forum.memo_count.to_int + 1 if self.parent_id
@forum.last_memo_id = self.id @parent_memo = Memo.find_by_id(self.parent_id)
if self.parent_id @parent_memo.last_reply_id = self
@parent_memo = Memo.find_by_id(self.parent_id) @parent_memo.replies_count = @parent_memo.replies_count.to_int + 1
@parent_memo.last_reply_id = self @parent_memo.save
@parent_memo.replies_count = @parent_memo.replies_count.to_int + 1 else
@parent_memo.save @forum.topic_count = @forum.topic_count.to_int + 1
else end
@forum.topic_count = @forum.topic_count.to_int + 1 @forum.save
end end
@forum.save
end def minusParentAndForum
@forum = Forum.find(self.forum_id)
def minusParentAndForum @forum.memo_count = @forum.memo_count.to_int - 1
@forum = Forum.find(self.forum_id) @forum.memo_count = 0 if @forum.memo_count.to_int < 0
@forum.memo_count = @forum.memo_count.to_int - 1 # @forum.last_memo_id = Memo.reorder('created_at ASC').find_all_by_forum_id(self.forum_id).last.id
@forum.memo_count = 0 if @forum.memo_count.to_int < 0 if self.parent_id
# @forum.last_memo_id = Memo.reorder('created_at ASC').find_all_by_forum_id(self.forum_id).last.id @parent_memo = Memo.find_by_id(self.parent_id)
if 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 = Memo.find_by_id(self.parent_id) @parent_memo.replies_count = @parent_memo.replies_count.to_int - 1
# @parent_memo.last_reply_id = Memo.reorder('created_at ASC').find_all_by_parent_id(self.parent_id).last.id @parent_memo.replies_count = 0 if @parent_memo.replies_count.to_int < 0
@parent_memo.replies_count = @parent_memo.replies_count.to_int - 1 @parent_memo.save
@parent_memo.replies_count = 0 if @parent_memo.replies_count.to_int < 0 else
@parent_memo.save @forum.topic_count = @forum.topic_count.to_int - 1
else @forum.topic_count = 0 if @forum.topic_count.to_int < 0
@forum.topic_count = @forum.topic_count.to_int - 1 end
@forum.topic_count = 0 if @forum.topic_count.to_int < 0 @forum.save
end end
@forum.save
end #更新用户分数 -by zjc
def be_user_score
#更新用户分数 -by zjc #新建memo且无parent的为发帖
def be_user_score if self.parent_id.nil?
#新建memo且无parent的为发帖 UserScore.joint(:post_message, User.current,nil,self ,{ memo_id: self.id })
if self.parent_id.nil? update_memo_number(User.current,1)
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?
#新建memo且有parent的为回帖 UserScore.joint(:reply_posting, User.current,self.parent.author,self, { memo_id: self.id })
elsif !self.parent_id.nil? update_replay_for_memo(User.current,1)
UserScore.joint(:reply_posting, User.current,self.parent.author,self, { memo_id: self.id }) end
update_replay_for_memo(User.current,1) end
end
end #被删除时更新用户分数
def down_user_score
#被删除时更新用户分数 update_memo_number(User.current,1)
def down_user_score update_replay_for_memo(User.current,1)
update_memo_number(User.current,1) end
update_replay_for_memo(User.current,1)
end # Time 2015-03-26 15:20:24
# Author lizanle
# Time 2015-03-26 15:20:24 # Description 从硬盘上删除资源
# Author lizanle def delete_kindeditor_assets
# Description 从硬盘上删除资源 delete_kindeditor_assets_from_disk self.id,OwnerTypeHelper::MEMO
def delete_kindeditor_assets end
delete_kindeditor_assets_from_disk self.id,1 end
end
end

@ -1,8 +0,0 @@
class MemoObserver < ActiveRecord::Observer
def after_create(memo)
thread1=Thread.new do
Mailer.forum_message_added(memo).deliver if Setting.notified_events.include?('forum_message_added')
end
end
end

@ -1,212 +1,221 @@
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang # Copyright (C) 2006-2013 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Message < ActiveRecord::Base class Message < ActiveRecord::Base
include Redmine::SafeAttributes include Redmine::SafeAttributes
include UserScoreHelper include UserScoreHelper
belongs_to :board include ApplicationHelper
belongs_to :author, :class_name => 'User', :foreign_key => 'author_id' has_many_kindeditor_assets :assets, :dependent => :destroy
has_many :praise_tread, as: :praise_tread_object, dependent: :destroy belongs_to :board
belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
acts_as_tree :counter_cache => :replies_count, :order => "#{Message.table_name}.created_on ASC" has_many :praise_tread, as: :praise_tread_object, dependent: :destroy
acts_as_attachable
belongs_to :last_reply, :class_name => 'Message', :foreign_key => 'last_reply_id' acts_as_tree :counter_cache => :replies_count, :order => "#{Message.table_name}.created_on ASC"
acts_as_attachable
# added by fq belongs_to :last_reply, :class_name => 'Message', :foreign_key => 'last_reply_id'
has_many :acts, :class_name => 'Activity', :as => :act, :dependent => :destroy
# 被ForgeActivity虚拟关联 # added by fq
has_many :forge_acts, :class_name => 'ForgeActivity',:as =>:forge_act ,:dependent => :destroy has_many :acts, :class_name => 'Activity', :as => :act, :dependent => :destroy
# end # 被ForgeActivity虚拟关联
has_many :forge_acts, :class_name => 'ForgeActivity',:as =>:forge_act ,:dependent => :destroy
acts_as_searchable :columns => ['subject', 'content'], # end
:include => {:board => :project},
:project_key => "#{Board.table_name}.project_id", acts_as_searchable :columns => ['subject', 'content'],
:date_column => "#{table_name}.created_on" :include => {:board => :project},
acts_as_searchable :columns => ['subject', 'content'], :project_key => "#{Board.table_name}.project_id",
:include => {:board => :course}, :date_column => "#{table_name}.created_on"
:course_key => "#{Board.table_name}.course_id", acts_as_searchable :columns => ['subject', 'content'],
:date_column => "#{table_name}.created_at" :include => {:board => :course},
acts_as_event :title => Proc.new {|o| "#{o.board.name}: #{o.subject}"}, :course_key => "#{Board.table_name}.course_id",
:description => :content, :date_column => "#{table_name}.created_at"
:datetime => :updated_on, acts_as_event :title => Proc.new {|o| "#{o.board.name}: #{o.subject}"},
# :datetime => "#{Message.table_name}.created_on", :description => :content,
:group => :parent, :datetime => :updated_on,
:type => Proc.new {|o| o.parent_id.nil? ? 'message' : 'reply'}, # :datetime => "#{Message.table_name}.created_on",
:url => Proc.new {|o| {:controller => 'messages', :action => 'show', :board_id => o.board_id}.merge(o.parent_id.nil? ? {:id => o.id} : :group => :parent,
{:id => o.parent_id, :r => o.id, :anchor => "message-#{o.id}"})} :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} :
acts_as_activity_provider :find_options => {:include => [{:board => :project}, :author]}, {:id => o.parent_id, :r => o.id, :anchor => "message-#{o.id}"})}
:author_key => :author_id
acts_as_activity_provider :find_options => {:include => [{:board => :course}, :author]}, acts_as_activity_provider :find_options => {:include => [{:board => :project}, :author]},
:type => 'course_messages', :author_key => :author_id
:author_key => :author_id acts_as_activity_provider :find_options => {:include => [{:board => :course}, :author]},
acts_as_watchable :type => 'course_messages',
:author_key => :author_id
validates_presence_of :board, :subject, :content acts_as_watchable
validates_length_of :subject, :maximum => 255
validate :cannot_reply_to_locked_topic, :on => :create validates_presence_of :board, :subject, :content
validates_length_of :subject, :maximum => 255
after_create :add_author_as_watcher, :reset_counters! validate :cannot_reply_to_locked_topic, :on => :create
after_update :update_messages_board
after_destroy :reset_counters!,:down_user_score after_create :add_author_as_watcher, :reset_counters!
after_update :update_messages_board
# fq after_destroy :reset_counters!,:down_user_score,:delete_kindeditor_assets
after_create :act_as_activity,:be_user_score,:act_as_forge_activity
#before_save :be_user_score after_create :act_as_activity,:be_user_score,:act_as_forge_activity, :send_mail
# end #before_save :be_user_score
scope :visible, lambda {|*args| scope :visible, lambda {|*args|
includes(:board => :project).where(Project.allowed_to_condition(args.shift || User.current, :view_messages, *args)) includes(:board => :project).where(Project.allowed_to_condition(args.shift || User.current, :view_messages, *args))
} }
scope :course_visible, lambda {|*args| scope :course_visible, lambda {|*args|
includes(:board => :course).where(Course.allowed_to_condition(args.shift || User.current, :view_course_messages, *args)) includes(:board => :course).where(Course.allowed_to_condition(args.shift || User.current, :view_course_messages, *args))
} }
safe_attributes 'subject', 'content' safe_attributes 'subject', 'content'
safe_attributes 'board_id','locked', 'sticky', safe_attributes 'board_id','locked', 'sticky',
:if => lambda {|message, user| :if => lambda {|message, user|
if message.project if message.project
user.allowed_to?(:edit_messages, message.project) user.allowed_to?(:edit_messages, message.project)
else else
user.allowed_to?(:edit_messages, message.course) user.allowed_to?(:edit_messages, message.course)
end end
} }
def visible?(user=User.current) def visible?(user=User.current)
if project if project
!user.nil? && user.allowed_to?(:view_messages, project) !user.nil? && user.allowed_to?(:view_messages, project)
elsif course elsif course
!user.nil? && user.allowed_to?(:view_messages, course) !user.nil? && user.allowed_to?(:view_messages, course)
end end
end end
def cannot_reply_to_locked_topic def cannot_reply_to_locked_topic
# Can not reply to a locked topic # Can not reply to a locked topic
errors.add :base, 'Topic is locked' if root.locked? && self != root errors.add :base, 'Topic is locked' if root.locked? && self != root
end end
def update_messages_board def update_messages_board
if board_id_changed? if board_id_changed?
Message.update_all({:board_id => board_id}, ["id = ? OR parent_id = ?", root.id, root.id]) 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_was)
Board.reset_counters!(board_id) Board.reset_counters!(board_id)
end end
end end
def reset_counters! def reset_counters!
if parent && parent.id if parent && parent.id
Message.update_all({:last_reply_id => parent.children.maximum(:id)}, {:id => parent.id}) Message.update_all({:last_reply_id => parent.children.maximum(:id)}, {:id => parent.id})
end end
board.reset_counters! board.reset_counters!
end end
def sticky=(arg) def sticky=(arg)
write_attribute :sticky, (arg == true || arg.to_s == '1' ? 1 : 0) write_attribute :sticky, (arg == true || arg.to_s == '1' ? 1 : 0)
end end
def sticky? def sticky?
sticky == 1 sticky == 1
end end
def project def project
board.project board.project
end end
def course def course
board.course board.course
end end
def course_editable_by?(usr) def course_editable_by?(usr)
usr && usr.logged? && (usr.allowed_to?(:edit_messages, course) || (self.author == usr && usr.allowed_to?(:edit_own_messages, course))) usr && usr.logged? && (usr.allowed_to?(:edit_messages, course) || (self.author == usr && usr.allowed_to?(:edit_own_messages, course)))
end end
def course_destroyable_by?(usr) def course_destroyable_by?(usr)
usr && usr.logged? && (usr.allowed_to?(:delete_messages, course) || (self.author == usr && usr.allowed_to?(:delete_own_messages, course))) usr && usr.logged? && (usr.allowed_to?(:delete_messages, course) || (self.author == usr && usr.allowed_to?(:delete_own_messages, course)))
end end
def editable_by?(usr) def editable_by?(usr)
usr && usr.logged? && (usr.allowed_to?(:edit_messages, project) || (self.author == usr && usr.allowed_to?(:edit_own_messages, project))) usr && usr.logged? && (usr.allowed_to?(:edit_messages, project) || (self.author == usr && usr.allowed_to?(:edit_own_messages, project)))
end end
def destroyable_by?(usr) def destroyable_by?(usr)
usr && usr.logged? && (usr.allowed_to?(:delete_messages, project) || (self.author == usr && usr.allowed_to?(:delete_own_messages, project))) usr && usr.logged? && (usr.allowed_to?(:delete_messages, project) || (self.author == usr && usr.allowed_to?(:delete_own_messages, project)))
end end
private private
def add_author_as_watcher def add_author_as_watcher
Watcher.create(:watchable => self.root, :user => author) Watcher.create(:watchable => self.root, :user => author)
end end
# fq # fq
def act_as_activity def act_as_activity
self.acts << Activity.new(:user_id => self.author_id) self.acts << Activity.new(:user_id => self.author_id)
end end
# end # end
# Time 2015-02-27 14:32:25 # Time 2015-02-27 14:32:25
# Author lizanle # Author lizanle
# Description # Description
def act_as_forge_activity def act_as_forge_activity
# 如果project为空那么就是课程相关的消息 # 如果project为空那么就是课程相关的消息
if !self.board.project.nil? if !self.board.project.nil?
self.forge_acts << ForgeActivity.new(:user_id => self.author_id, self.forge_acts << ForgeActivity.new(:user_id => self.author_id,
:project_id => self.board.project.id) :project_id => self.board.project.id)
end end
end end
#更新用户分数 -by zjc #更新用户分数 -by zjc
def be_user_score def be_user_score
#新建message且无parent的为发帖 #新建message且无parent的为发帖
if self.parent_id.nil? && !self.board.project.nil? if self.parent_id.nil? && !self.board.project.nil?
UserScore.joint(:post_message, self.author,nil,self, { message_id: self.id }) UserScore.joint(:post_message, self.author,nil,self, { message_id: self.id })
update_memo_number(self.author,1) update_memo_number(self.author,1)
if self.board.project_id != -1 if self.board.project_id != -1
update_memo_number(self.author,2,self.board.project) update_memo_number(self.author,2,self.board.project)
end end
#新建message且有parent的为回帖 #新建message且有parent的为回帖
elsif !self.parent_id.nil? && !self.board.project.nil? elsif !self.parent_id.nil? && !self.board.project.nil?
UserScore.joint(:reply_posting, self.author,self.parent.author,self, { message_id: self.id }) UserScore.joint(:reply_posting, self.author,self.parent.author,self, { message_id: self.id })
update_replay_for_memo(self.author,1) update_replay_for_memo(self.author,1)
if self.board.project_id != -1 if self.board.project_id != -1
update_replay_for_memo(self.author,2,self.board.project) update_replay_for_memo(self.author,2,self.board.project)
end end
end end
end end
#减少用户分数 #减少用户分数
def down_user_score def down_user_score
if self.parent_id.nil? && !self.board.project.nil? if self.parent_id.nil? && !self.board.project.nil?
UserScore.joint(:delete_message, self.author,nil,self, { message_id: self.id }) UserScore.joint(:delete_message, self.author,nil,self, { message_id: self.id })
update_memo_number(User.current,1) update_memo_number(User.current,1)
if self.board.project_id != -1 if self.board.project_id != -1
update_memo_number(self.author,2,self.board.project) update_memo_number(self.author,2,self.board.project)
end end
elsif !self.parent_id.nil? && !self.board.project.nil? elsif !self.parent_id.nil? && !self.board.project.nil?
UserScore.joint(:reply_deleting, self.author,self.parent.author,self, { message_id: self.id }) UserScore.joint(:reply_deleting, self.author,self.parent.author,self, { message_id: self.id })
update_replay_for_memo(User.current,1) update_replay_for_memo(User.current,1)
if self.board.project_id != -1 if self.board.project_id != -1
update_replay_for_memo(self.author,2,self.board.project) update_replay_for_memo(self.author,2,self.board.project)
end end
end end
end end
def send_mail
end 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

@ -1,25 +0,0 @@
# 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 MessageObserver < ActiveRecord::Observer
def after_create(message)
##by senluo
thread5=Thread.new do
Mailer.message_posted(message).deliver if Setting.notified_events.include?('message_posted')
end
end
end

@ -1,108 +1,120 @@
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang # Copyright (C) 2006-2013 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class News < ActiveRecord::Base class News < ActiveRecord::Base
include Redmine::SafeAttributes include Redmine::SafeAttributes
belongs_to :project belongs_to :project
#added by nwb include ApplicationHelper
belongs_to :course has_many_kindeditor_assets :assets, :dependent => :destroy
belongs_to :author, :class_name => 'User', :foreign_key => 'author_id' #added by nwb
has_many :comments, :as => :commented, :dependent => :delete_all, :order => "created_on" belongs_to :course
# fq belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
has_many :acts, :class_name => 'Activity', :as => :act, :dependent => :destroy has_many :comments, :as => :commented, :dependent => :delete_all, :order => "created_on"
# 被ForgeActivity虚拟关联 # fq
has_many :forge_acts, :class_name => 'ForgeActivity',:as =>:forge_act ,:dependent => :destroy has_many :acts, :class_name => 'Activity', :as => :act, :dependent => :destroy
# end # 被ForgeActivity虚拟关联
has_many :forge_acts, :class_name => 'ForgeActivity',:as =>:forge_act ,:dependent => :destroy
validates_presence_of :title, :description # end
validates_length_of :title, :maximum => 60
validates_length_of :summary, :maximum => 255 validates_presence_of :title, :description
validates_length_of :description, :maximum => 10000 validates_length_of :title, :maximum => 60
validates_length_of :summary, :maximum => 255
acts_as_attachable :delete_permission => :manage_news validates_length_of :description, :maximum => 10000
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_attachable :delete_permission => :manage_news
acts_as_activity_provider :find_options => {:include => [:project, :author]}, acts_as_searchable :columns => ['title', 'summary', "#{table_name}.description"], :include => :project
:author_key => :author_id acts_as_event :url => Proc.new {|o| {:controller => 'news', :action => 'show', :id => o.id}}
#added by nwb acts_as_activity_provider :find_options => {:include => [:project, :author]},
#课程新闻独立于项目 :author_key => :author_id
acts_as_activity_provider :type => 'course_news', #added by nwb
:find_options => {:include => [:course, :author]}, #课程新闻独立于项目
:author_key => :author_id acts_as_activity_provider :type => 'course_news',
acts_as_watchable :find_options => {:include => [:course, :author]},
:author_key => :author_id
after_create :add_author_as_watcher acts_as_watchable
# fq
after_create :act_as_activity,:act_as_forge_activity after_create :act_as_activity,:act_as_forge_activity,:add_author_as_watcher, :send_mail
# end
after_destroy :delete_kindeditor_assets
scope :visible, lambda {|*args|
includes(:project).where(Project.allowed_to_condition(args.shift || User.current, :view_news, *args)) 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)) 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' }
safe_attributes 'title', 'summary', 'description'
def visible?(user=User.current)
!user.nil? && user.allowed_to?(:view_news, project) def visible?(user=User.current)
end !user.nil? && user.allowed_to?(:view_news, project)
end
# Returns true if the news can be commented by user
def commentable?(user=User.current) # Returns true if the news can be commented by user
user.allowed_to?(:comment_news, project) def commentable?(user=User.current)
end user.allowed_to?(:comment_news, project)
end
def recipients
project.users.select {|user| user.notify_about?(self)}.map(&:mail) def recipients
end 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) # returns latest news for projects visible by user
visible(user).includes([:author, :project]).order("#{News.table_name}.created_on DESC").limit(count).all def self.latest(user = User.current, count = 5)
end 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 def short_description(length = 255)
#description.gsub(/^(.{#{length}}[^\n\r]*).*$/m, '\1...').strip if description description.gsub(/<\/?.*?>/,"").html_safe if description
#description #description.gsub(/^(.{#{length}}[^\n\r]*).*$/m, '\1...').strip if description
end #description
end
private
private
def add_author_as_watcher
Watcher.create(:watchable => self, :user => author) def add_author_as_watcher
end Watcher.create(:watchable => self, :user => author)
## fq end
def act_as_activity ## fq
self.acts << Activity.new(:user_id => self.author_id) def act_as_activity
end self.acts << Activity.new(:user_id => self.author_id)
end
# Time 2015-02-27 15:48:17
# Author lizanle # Time 2015-02-27 15:48:17
# Description 公用表中也要记录 # Author lizanle
def act_as_forge_activity # Description 公用表中也要记录
# 如果是project为空那么是课程相关的不需要保存 def act_as_forge_activity
if !self.project.nil? # 如果是project为空那么是课程相关的不需要保存
self.forge_acts << ForgeActivity.new(:user_id => self.author_id, if !self.project.nil?
:project_id => self.project.id) self.forge_acts << ForgeActivity.new(:user_id => self.author_id,
end :project_id => self.project.id)
end end
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

@ -1,25 +0,0 @@
# 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 NewsObserver < ActiveRecord::Observer
def after_create(news)
##by senluo
thread6=Thread.new do
Mailer.news_added(news).deliver if Setting.notified_events.include?('news_added')
end
end
end

@ -6,4 +6,25 @@ class Poll < ActiveRecord::Base
has_many :poll_questions, :dependent => :destroy,:order => "#{PollQuestion.table_name}.question_number" has_many :poll_questions, :dependent => :destroy,:order => "#{PollQuestion.table_name}.question_number"
has_many :poll_users, :dependent => :destroy has_many :poll_users, :dependent => :destroy
has_many :users, :through => :poll_users #该文件被哪些用户提交答案过 has_many :users, :through => :poll_users #该文件被哪些用户提交答案过
# 添加课程的poll动态
has_many :acts, :class_name => 'Activity', :as => :act, :dependent => :destroy
after_create :act_as_activity
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 => {: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
end end

@ -19,6 +19,7 @@ class Principal < ActiveRecord::Base
self.table_name = "#{table_name_prefix}users#{table_name_suffix}" self.table_name = "#{table_name_prefix}users#{table_name_suffix}"
# Account statuses # Account statuses
# 0 全部1 活动的; 2 已注册; 3 锁定
STATUS_ANONYMOUS = 0 STATUS_ANONYMOUS = 0
STATUS_ACTIVE = 1 STATUS_ACTIVE = 1
STATUS_REGISTERED = 2 STATUS_REGISTERED = 2
@ -42,7 +43,8 @@ class Principal < ActiveRecord::Base
where({}) where({})
else else
pattern = "%#{q}%" pattern = "%#{q}%"
sql = %w(login firstname lastname mail).map {|column| "LOWER(#{table_name}.#{column}) LIKE LOWER(:p)"}.join(" OR ") # sql = %w(login firstname lastname mail).map {|column| "LOWER(#{table_name}.#{column}) LIKE LOWER(:p)"}.join(" OR ")
sql= "LOWER(concat(lastname,firstname)) LIKE LOWER(:p) or LOWER(login) LIKE LOWER(:p) or LOWER(mail) LIKE LOWER(:p)"
params = {:p => pattern} params = {:p => pattern}
if q =~ /^(.+)\s+(.+)$/ if q =~ /^(.+)\s+(.+)$/
a, b = "#{$1}%", "#{$2}%" a, b = "#{$1}%", "#{$2}%"

@ -51,7 +51,7 @@ class Project < ActiveRecord::Base
has_many :issue_categories, :dependent => :delete_all, :order => "#{IssueCategory.table_name}.name" has_many :issue_categories, :dependent => :delete_all, :order => "#{IssueCategory.table_name}.name"
has_many :boards, :dependent => :destroy, :order => "position ASC" has_many :boards, :dependent => :destroy, :order => "position ASC"
has_one :repository, :conditions => ["is_default = ?", true] 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 has_many :changesets, :through => :repository
#added by xianbo for delete biding_project #added by xianbo for delete biding_project
has_many :biding_projects, :dependent => :destroy has_many :biding_projects, :dependent => :destroy

@ -1,199 +1,199 @@
class RelativeMemo < ActiveRecord::Base class RelativeMemo < ActiveRecord::Base
# attr_accessible :title, :body # attr_accessible :title, :body
include Redmine::SafeAttributes include Redmine::SafeAttributes
belongs_to :open_source_project, :class_name => "OpenSourceProject", :foreign_key => 'osp_id' belongs_to :open_source_project, :class_name => "OpenSourceProject", :foreign_key => 'osp_id'
belongs_to :author, :class_name => "User", :foreign_key => 'author_id' belongs_to :author, :class_name => "User", :foreign_key => 'author_id'
has_many :tags, :through => :project_tags, :class_name => 'Tag' has_many :tags, :through => :project_tags, :class_name => 'Tag'
has_many :project_tags, :class_name => 'ProjectTags' has_many :project_tags, :class_name => 'ProjectTags'
has_many :relation_topics, :class_name => 'RelativeMemoToOpenSourceProject' has_many :relation_topics, :class_name => 'RelativeMemoToOpenSourceProject'
has_many :no_uses, :as => :no_use, :dependent => :delete_all 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 has_many :bugs_to_osp, :class_name => 'BugToOsp', :foreign_key => 'relative_memo_id', :dependent => :destroy
acts_as_taggable acts_as_taggable
validates_presence_of :subject validates_presence_of :subject
#validates :content, presence: true #validates :content, presence: true
# validates_length_of :subject, maximum: 50 # validates_length_of :subject, maximum: 50
#validates_length_of :content, maximum: 3072 #validates_length_of :content, maximum: 3072
validate :cannot_reply_to_locked_topic, :on => :create validate :cannot_reply_to_locked_topic, :on => :create
validates_uniqueness_of :osp_id, :scope => [:subject, :content] validates_uniqueness_of :osp_id, :scope => [:subject, :content]
acts_as_tree :counter_cache => :replies_count, :order => "#{RelativeMemo.table_name}.created_at ASC" acts_as_tree :counter_cache => :replies_count, :order => "#{RelativeMemo.table_name}.created_at ASC"
acts_as_attachable acts_as_attachable
belongs_to :last_reply, :class_name => 'RelativeMemo', :foreign_key => 'last_reply_id' belongs_to :last_reply, :class_name => 'RelativeMemo', :foreign_key => 'last_reply_id'
# acts_as_searchable :column => ['subject', 'content'], # acts_as_searchable :column => ['subject', 'content'],
# #:include => { :forum => :p} # #:include => { :forum => :p}
# #:project_key => "#{Forum.table_name}.project_id" # #:project_key => "#{Forum.table_name}.project_id"
# :date_column => "#{table_name}.created_at" # :date_column => "#{table_name}.created_at"
# acts_as_event :title => Proc.new {|o| "#{o.forum.name}: #{o.subject}"}, # acts_as_event :title => Proc.new {|o| "#{o.forum.name}: #{o.subject}"},
# :datetime => :updated_at, # :datetime => :updated_at,
# # :datetime => :created_at, # # :datetime => :created_at,
# :description => :content, # :description => :content,
# :author => :author, # :author => :author,
# :type => Proc.new {|o| o.parent_id.nil? ? 'Memo' : 'Reply'}, # :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}"})} # :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, # acts_as_activity_provider :author_key => :author_id,
# :func => 'memos', # :func => 'memos',
# :timestamp => 'created_at' # :timestamp => 'created_at'
# :find_options => {:type => 'memos'} # :find_options => {:type => 'memos'}
# acts_as_watchable # acts_as_watchable
safe_attributes "author_id", safe_attributes "author_id",
"subject", "subject",
"content", "content",
"osp_id", "osp_id",
"last_memo_id", "last_memo_id",
"lock", "lock",
"sticky", "sticky",
"parent_id", "parent_id",
"replies_count", "replies_count",
"is_quote" "is_quote"
after_create :add_author_as_watcher, :reset_counters! after_create :add_author_as_watcher, :reset_counters!
# after_update :update_memos_forum # after_update :update_memos_forum
after_destroy :reset_counters! after_destroy :reset_counters!
# after_create :send_notification # after_create :send_notification
# after_save :plusParentAndForum # after_save :plusParentAndForum
# after_destroy :minusParentAndForum # after_destroy :minusParentAndForum
# scope :visible, lambda { |*args| # scope :visible, lambda { |*args|
# includes(:forum => ).where() # includes(:forum => ).where()
# } # }
def cannot_reply_to_locked_topic def cannot_reply_to_locked_topic
errors.add :base, l(:label_memo_locked) if root.locked? && self != root errors.add :base, l(:label_memo_locked) if root.locked? && self != root
end end
def short_content(length = 25) def short_content(length = 25)
str = "^(.{,#{length}})[^\n\r]*.*$" str = "^(.{,#{length}})[^\n\r]*.*$"
content.gsub(Regexp.new(str), '\1...').strip if content content.gsub(Regexp.new(str), '\1...').strip if content
end end
# def update_memos_forum # def update_memos_forum
# if forum_id_changed? # if forum_id_changed?
# Message.update_all({:board_id => board_id}, ["id = ? OR parent_id = ?", root.id, root.id ]) # 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_was)
# Forum.reset_counters!(forum_id) # Forum.reset_counters!(forum_id)
# end # end
# end # end
scope :no_use_for, lambda { |user_id| scope :no_use_for, lambda { |user_id|
{ :include => :no_uses, { :include => :no_uses,
:conditions => ["#{NoUse.table_name}.user_id = ?", user_id] } :conditions => ["#{NoUse.table_name}.user_id = ?", user_id] }
} }
# 获取帖子的回复 # 获取帖子的回复
def replies def replies
memos = RelativeMemo.where("parent_id = ?", id) memos = RelativeMemo.where("parent_id = ?", id)
end end
def no_use_for?(user) def no_use_for?(user)
self.no_uses.each do |no_use| self.no_uses.each do |no_use|
if no_use.user_id == user.id if no_use.user_id == user.id
return true return true
end end
end end
false false
end end
def set_no_use(user, flag=true) def set_no_use(user, flag=true)
flag ? set_filter(user) : remove_filter(user) flag ? set_filter(user) : remove_filter(user)
end end
def set_filter(user) def set_filter(user)
self.no_uses << NoUse.new(:user => user) self.no_uses << NoUse.new(:user => user)
end end
def remove_filter(user) def remove_filter(user)
return nil unless user && user.is_a?(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}" NoUse.delete_all "no_use_type = '#{self.class}' AND no_use_id = #{self.id} AND user_id = #{user.id}"
end end
def reset_counters! def reset_counters!
if parent && parent.id if parent && parent.id
RelativeMemo.update_all({:last_reply_id => parent.children.maximum(:id)}, {:id => parent.id}) RelativeMemo.update_all({:last_reply_id => parent.children.maximum(:id)}, {:id => parent.id})
parent.update_attribute(:updated_at, Time.now) parent.update_attribute(:updated_at, Time.now)
end end
# forum.reset_counters! # forum.reset_counters!
end end
def sticky? def sticky?
sticky == 1 sticky == 1
end end
def replies def replies
RelativeMemo.where("parent_id = ?", id) RelativeMemo.where("parent_id = ?", id)
end end
def locked? def locked?
self.lock self.lock
end end
def editable_by? user def editable_by? user
# user && user.logged? || (self.author == usr && usr.allowed_to?(:edit_own_messages, project)) # user && user.logged? || (self.author == usr && usr.allowed_to?(:edit_own_messages, project))
user.admin? user.admin?
end end
# def destroyable_by? user # def destroyable_by? user
# (user && user.logged? && (Forum.find(self.forum_id).creator_id == user.id) ) || user.admin? # (user && user.logged? && (Forum.find(self.forum_id).creator_id == user.id) ) || user.admin?
# #self.author == user || user.admin? # #self.author == user || user.admin?
# end # end
def deleted_attach_able_by? user def deleted_attach_able_by? user
(user && user.logged? && (self.author == user) ) || user.admin? (user && user.logged? && (self.author == user) ) || user.admin?
end end
private private
def add_author_as_watcher def add_author_as_watcher
Watcher.create(:watchable => self.root, :user => author) Watcher.create(:watchable => self.root, :user => author)
end end
def send_notification def send_notification
if Setting.notified_events.include?('message_posted') if Setting.notified_events.include?('message_posted')
Mailer.message_posted(self).deliver Mailer.run.message_posted(self)
end end
end end
# def plusParentAndForum # def plusParentAndForum
# @forum = Forum.find(self.forum_id) # @forum = Forum.find(self.forum_id)
# @forum.memo_count = @forum.memo_count.to_int + 1 # @forum.memo_count = @forum.memo_count.to_int + 1
# @forum.last_memo_id = self.id # @forum.last_memo_id = self.id
# if self.parent_id # if self.parent_id
# @parent_memo = Memo.find_by_id(self.parent_id) # @parent_memo = Memo.find_by_id(self.parent_id)
# @parent_memo.last_reply_id = self # @parent_memo.last_reply_id = self
# @parent_memo.replies_count = @parent_memo.replies_count.to_int + 1 # @parent_memo.replies_count = @parent_memo.replies_count.to_int + 1
# @parent_memo.save # @parent_memo.save
# else # else
# @forum.topic_count = @forum.topic_count.to_int + 1 # @forum.topic_count = @forum.topic_count.to_int + 1
# end # end
# @forum.save # @forum.save
# end # end
# def minusParentAndForum # def minusParentAndForum
# @forum = Forum.find(self.forum_id) # @forum = Forum.find(self.forum_id)
# @forum.memo_count = @forum.memo_count.to_int - 1 # @forum.memo_count = @forum.memo_count.to_int - 1
# @forum.memo_count = 0 if @forum.memo_count.to_int < 0 # @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 # # @forum.last_memo_id = Memo.reorder('created_at ASC').find_all_by_forum_id(self.forum_id).last.id
# if self.parent_id # if self.parent_id
# @parent_memo = Memo.find_by_id(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.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 = @parent_memo.replies_count.to_int - 1
# @parent_memo.replies_count = 0 if @parent_memo.replies_count.to_int < 0 # @parent_memo.replies_count = 0 if @parent_memo.replies_count.to_int < 0
# @parent_memo.save # @parent_memo.save
# else # else
# @forum.topic_count = @forum.topic_count.to_int - 1 # @forum.topic_count = @forum.topic_count.to_int - 1
# @forum.topic_count = 0 if @forum.topic_count.to_int < 0 # @forum.topic_count = 0 if @forum.topic_count.to_int < 0
# end # end
# @forum.save # @forum.save
# end # end
end end

@ -27,6 +27,14 @@ class Token < ActiveRecord::Base
self.value = Token.generate_token_value self.value = Token.generate_token_value
end 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 # Return true if token has expired
def expired? def expired?
return Time.now > self.created_on + @@validity_time return Time.now > self.created_on + @@validity_time

File diff suppressed because it is too large Load Diff

@ -1,34 +1,28 @@
# Redmine - project management software # Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang # Copyright (C) 2006-2013 Jean-Philippe Lang
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class WikiContentObserver < ActiveRecord::Observer class WikiContentObserver < ActiveRecord::Observer
def after_create(wiki_content) def after_create(wiki_content)
##by senluo Mailer.run.wiki_content_added(wiki_content) if Setting.notified_events.include?('wiki_content_added')
thread7=Thread.new do end
Mailer.wiki_content_added(wiki_content).deliver if Setting.notified_events.include?('wiki_content_added')
end def after_update(wiki_content)
end if wiki_content.text_changed?
Mailer.run.wiki_content_updated(wiki_content) if Setting.notified_events.include?('wiki_content_updated')
def after_update(wiki_content) end
if wiki_content.text_changed? end
##by senluo end
thread8=Thread.new do
Mailer.wiki_content_updated(wiki_content).deliver if Setting.notified_events.include?('wiki_content_updated')
end
end
end
end

@ -0,0 +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

@ -40,9 +40,9 @@ class CoursesService
end end
@courses = courses_all.visible(current_user) @courses = courses_all.visible(current_user)
if params[:name].present? if params[:name].present?
@courses_all = @courses.like(params[:name]) @courses_all = @courses.like(params[:name]).order("created_at desc")
else else
@courses_all = @courses; @courses_all = @courses.order("created_at desc");
end end
@courses_all @courses_all
course_list = [] course_list = []
@ -161,10 +161,15 @@ class CoursesService
#显示课程 #显示课程
def show_course(params,current_user) def show_course(params,current_user)
course = Course.find(params[:id]) course = Course.find(params[:id])
if course.school
work_unit = course.school.name
else
work_unit = get_user_work_unit course.teacher
end
unless (course.is_public == 1 || current_user.member_of_course?(course) || current_user.admin?) unless (course.is_public == 1 || current_user.member_of_course?(course) || current_user.admin?)
raise '403' raise '403'
end end
{:course => course,: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 end
#创建课程 #创建课程
@ -193,7 +198,9 @@ class CoursesService
@course.school_id = current_user.user_extensions.school_id @course.school_id = current_user.user_extensions.school_id
@course.setup_time = params[:setup_time] @course.setup_time = params[:setup_time]
@course.endup_time = params[:endup_time] @course.endup_time = params[:endup_time]
@course.class_period = params[:class_period] @course.class_period = params[:class_period].to_i
params[:course][:is_public] ? @course.is_public = 1 : @course.is_public = 0
params[:course][:open_student] ? @course.open_student = 1 : @course.open_student = 0
end end
@issue_custom_fields = IssueCustomField.sorted.all @issue_custom_fields = IssueCustomField.sorted.all
@ -238,7 +245,7 @@ class CoursesService
#course.safe_attributes = params[:course] #course.safe_attributes = params[:course]
course.time = params[:time] course.time = params[:time]
course.term = params[:term] course.term = params[:term]
course.class_period = params[:class_period] course.class_period = params[:class_period].to_i
params[:course][:is_public] ? course.is_public = 1 : course.is_public = 0 params[:course][:is_public] ? course.is_public = 1 : course.is_public = 0
params[:course][:open_student] ? course.open_student = 1 : course.open_student = 0 params[:course][:open_student] ? course.open_student = 1 : course.open_student = 0
if course.save if course.save
@ -338,7 +345,7 @@ class CoursesService
def course_dynamic(params,current_user) def course_dynamic(params,current_user)
@user = User.find(params[:id]) @user = User.find(params[:id])
if !current_user.admin? && !@user.active? if current_user.nil? && !current_user.admin? && !@user.active?
raise '404' raise '404'
return return
end end
@ -371,6 +378,16 @@ class CoursesService
unless latest_bid.nil? unless latest_bid.nil?
latest_course_dynamics << {:type => 4,:time => latest_bid.updated_on,:message => l(:label_recently_updated_homework,:locale => get_user_language(current_user))} latest_course_dynamics << {:type => 4,:time => latest_bid.updated_on,:message => l(:label_recently_updated_homework,:locale => get_user_language(current_user))}
end end
# Time 2015-04-07 14:58:30
# Author lizanle
# Description 添加课程创建动态
if(User.find_by_id(CourseInfos.find_by_course_id(course.id).try(:user_id)))
create_user_name = User.find_by_id(CourseInfos.find_by_course_id(course.id).user_id).realname
latest_course_dynamics << {:type => 5,:time => course.created_at,:message =>l(:label_recently,:locale => get_user_language(current_user)) << create_user_name << l(:label_creat,:locale => get_user_language(current_user))}
end
#每个作业中的最新留言 #每个作业中的最新留言
messages = [] messages = []
course.homeworks.each do |bid| course.homeworks.each do |bid|
@ -411,13 +428,59 @@ class CoursesService
result result
end 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 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 def show_homework_info course,bid,current_user,is_course_teacher
author_real_name = bid.author.lastname + bid.author.firstname author_real_name = bid.author.lastname + bid.author.firstname
many_times = course.homeworks.index(bid) + 1 many_times = course.homeworks.index(bid) + 1
name = bid.name name = bid.name
homework_count = bid.homeworks.count #已提交的作业数量 homework_count = bid.homeworks.count #已提交的作业数量
student_questions_count = bid.commit.nil? ? 0 : bid.commit student_questions_count = bid.journals_for_messages.where('m_parent_id IS NULL').count
description = bid.description description = bid.description
#if is_course_teacher(User.current, course) && @bid.open_anonymous_evaluation == 1 && @bid.homeworks.count >= 2 #if is_course_teacher(User.current, course) && @bid.open_anonymous_evaluation == 1 && @bid.homeworks.count >= 2
state = bid.comment_status state = bid.comment_status
@ -437,7 +500,7 @@ class CoursesService
many_times = course.homeworks.index(bid) + 1 many_times = course.homeworks.index(bid) + 1
name = bid.name name = bid.name
homework_count = bid.homeworks.count #已提交的作业数量 homework_count = bid.homeworks.count #已提交的作业数量
student_questions_count = bid.commit.nil? ? 0 : bid.commit student_questions_count = bid.journals_for_messages.where('m_parent_id IS NULL').count
description = bid.description description = bid.description
#if is_course_teacher(User.current, course) && @bid.open_anonymous_evaluation == 1 && @bid.homeworks.count >= 2 #if is_course_teacher(User.current, course) && @bid.open_anonymous_evaluation == 1 && @bid.homeworks.count >= 2
state = bid.comment_status state = bid.comment_status
@ -448,5 +511,52 @@ class CoursesService
end 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 end

@ -20,7 +20,7 @@ class HomeworkService
many_times = course.homeworks.index(@bid) + 1 many_times = course.homeworks.index(@bid) + 1
name = @bid.name name = @bid.name
homework_count = @bid.homeworks.count #已提交的作业数量 homework_count = @bid.homeworks.count #已提交的作业数量
student_questions_count = @bid.commit.nil? ? 0 : @bid.commit student_questions_count = @bid.journals_for_messages.where('m_parent_id IS NULL').count
description = @bid.description description = @bid.description
#if is_course_teacher(User.current, course) && @bid.open_anonymous_evaluation == 1 && @bid.homeworks.count >= 2 #if is_course_teacher(User.current, course) && @bid.open_anonymous_evaluation == 1 && @bid.homeworks.count >= 2
state = @bid.comment_status state = @bid.comment_status
@ -282,7 +282,7 @@ class HomeworkService
many_times = course.homeworks.index(@bid) + 1 many_times = course.homeworks.index(@bid) + 1
name = @bid.name name = @bid.name
homework_count = @bid.homeworks.count #已提交的作业数量 homework_count = @bid.homeworks.count #已提交的作业数量
student_questions_count = @bid.commit.nil? ? 0 : @bid.commit student_questions_count = @bid.journals_for_messages.where('m_parent_id IS NULL').count
description = @bid.description description = @bid.description
#if is_course_teacher(User.current, course) && @bid.open_anonymous_evaluation == 1 && @bid.homeworks.count >= 2 #if is_course_teacher(User.current, course) && @bid.open_anonymous_evaluation == 1 && @bid.homeworks.count >= 2
state = @bid.comment_status state = @bid.comment_status

@ -44,12 +44,14 @@ class UsersService
#location = get_user_location @user #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} #{: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 end
# 自动注册功能 FOR邮件邀请
def register_auto(login,mail,password) def register_auto(login,mail,password)
@user = User.new @user = User.new
@user.admin = false @user.admin = false
@user.register @user.register
@user.login = login @user.login = login
@user.mail =mail @user.mail = mail
password_confirmation = password password_confirmation = password
should_confirmation_password = true should_confirmation_password = true
if !password.blank? && !password_confirmation.blank? && should_confirmation_password if !password.blank? && !password_confirmation.blank? && should_confirmation_password
@ -59,9 +61,7 @@ class UsersService
else else
@user.password = "" @user.password = ""
end end
@user = automatically_register(@user) @user = automatically_register(@user)
if @user.id != nil if @user.id != nil
ue = @user.user_extensions ||= UserExtensions.new ue = @user.user_extensions ||= UserExtensions.new
ue.user_id = @user.id ue.user_id = @user.id
@ -69,6 +69,7 @@ class UsersService
end end
@user @user
end end
#显示用户 #显示用户
#id用户id #id用户id
def show_user(params) def show_user(params)
@ -77,7 +78,7 @@ class UsersService
gender = @user.user_extensions.gender.nil? ? 0 : @user.user_extensions.gender gender = @user.user_extensions.gender.nil? ? 0 : @user.user_extensions.gender
work_unit = get_user_work_unit @user work_unit = get_user_work_unit @user
location = get_user_location @user 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} {:id => @user.id, :img_url => img_url,:realname => @user.realname, :nickname => @user.login, :gender => gender, :work_unit => work_unit, :mail => @user.mail, :location => location, :brief_introduction => @user.user_extensions.brief_introduction}
end end
#忘记密码 #忘记密码
@ -95,9 +96,7 @@ class UsersService
# create a new token for password recovery # create a new token for password recovery
token = Token.new(:user => user, :action => "recovery") token = Token.new(:user => user, :action => "recovery")
if token.save if token.save
Thread.new do Mailer.run.lost_password(token)
Mailer.lost_password(token).deliver
end
return l(:notice_account_lost_email_sent,:locale => user.language) return l(:notice_account_lost_email_sent,:locale => user.language)
end end
end end
@ -194,20 +193,22 @@ class UsersService
#raise @current_user.errors.full_message #raise @current_user.errors.full_message
#return @current_user #return @current_user
else else
raise 'wrong password' raise l(:notice_account_wrong_password,:locale => 'zh')
end end
@current_user @current_user
end end
#搜索用户 #搜索用户
def search_user params def search_user params
@status = params[:status] || 1 status = params[:status] || 1
has = { has = {
"show_changesets" => true "show_changesets" => true
} }
scope = User.logged.status(@status) scope = User.logged.status(status)
@search_by = params[:search_by] ? params[:search_by] : "0" watcher = User.watched_by(params[:user_id])
scope = scope.like(params[:name],@search_by) if params[:name].present? watcher.push(params[:user_id])
search_by = params[:search_by] ? params[:search_by] : "0"
scope = scope.where("id not in (?)",watcher).like(params[:name],search_by) if params[:name].present?
scope scope
end end

@ -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

@ -68,7 +68,7 @@
<td align="left"> <td align="left">
<% if Setting.autologin? %> <% if Setting.autologin? %>
<label for="autologin"> <label for="autologin">
<%= check_box_tag 'autologin', 1, false, :tabindex => 4 %> <%= check_box_tag 'autologin', 1, true, :tabindex => 4 %>
<%= l(:label_stay_logged_in) %> <%= l(:label_stay_logged_in) %>
</label> </label>
<% end %> <% end %>

@ -1,11 +1,11 @@
<% if @status == 0%> <% if @status == 0%>
alert("您申请的项目不存在"); alert("<%= l('project.join.tips.notexist') %>");
<% elsif @status == 1%> <% elsif @status == 1%>
alert("请勿重复申请加入该项目"); alert("<%= l('project.join.tips.repeat') %>");
<% elsif @status == 2%> <% elsif @status == 2%>
alert("申请成功"); alert("<%= l('project.join.tips.success') %>");
<% elsif @status == 3%> <% elsif @status == 3%>
alert("您已加入该项目"); alert("<%= l('project.join.tips.has') %>");
<%else%> <%else%>
alert("申请失败"); alert("<%= l('project.join.tips.fail') %>");
<%end%> <%end%>

@ -1,11 +1,12 @@
<div class="fl">
<span id="attachments_fields" xmlns="http://www.w3.org/1999/html"> <span id="attachments_fields" xmlns="http://www.w3.org/1999/html">
<% if defined?(container) && container && container.saved_attachments %> <% if defined?(container) && container && container.saved_attachments %>
<% container.attachments.each_with_index do |attachment, i| %> <% container.attachments.each_with_index do |attachment, i| %>
<span id="attachments_p<%= i %>" class="attachment"> <span id="attachments_p<%= i %>" class="attachment">
<%= text_field_tag("attachments[p#{i}][filename]", attachment.filename, :class => 'filename readonly', :readonly=>'readonly')%> <%= 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;") %> <%= text_field_tag("attachments[p#{i}][description]", attachment.description, :maxlength => 254, :placeholder => l(:label_optional_description), :class => 'description', :style => "display: inline-block;") %>
<span class="ispublic-label"><%= l(:field_is_public)%>:</span> <span class="ispublic-label"><%= l(:field_is_public) %>:</span>
<%= check_box_tag("attachments[p#{i}][is_public_checkbox]", attachment.is_public,attachment.is_public == 1 ? true : false,:class => '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? <%= if attachment.id.nil?
#待补充代码 #待补充代码
else else
@ -19,15 +20,15 @@
<% end %> <% end %>
<% container.saved_attachments.each_with_index do |attachment, i| %> <% container.saved_attachments.each_with_index do |attachment, i| %>
<span id="attachments_p<%= i %>" class="attachment"> <span id="attachments_p<%= i %>" class="attachment">
<%= text_field_tag("attachments[p#{i}][filename]", attachment.filename, :class => 'filename readonly', :readonly=>'readonly')%> <%= 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;") %> <%= text_field_tag("attachments[p#{i}][description]", attachment.description, :maxlength => 254, :placeholder => l(:label_optional_description), :class => 'description', :style => "display: inline-block;") %>
<span class="ispublic-label"><%= l(:field_is_public)%>:</span> <span class="ispublic-label"><%= l(:field_is_public) %>:</span>
<%= check_box_tag("attachments[p#{i}][is_public_checkbox]", attachment.is_public,attachment.is_public == 1 ? true : false,:class => '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? <%= if attachment.id.nil?
#待补充代码 #待补充代码
else else
link_to('&nbsp;'.html_safe, attachment_path(attachment, :attachment_id => "p#{i}", :format => 'js'), :method => 'delete', :remote => true, :class => 'remove-upload') link_to('&nbsp;'.html_safe, attachment_path(attachment, :attachment_id => "p#{i}", :format => 'js'), :method => 'delete', :remote => true, :class => 'remove-upload')
end end
%> %>
<%#= render :partial => 'tags/tag', :locals => {:obj => attachment, :object_flag => "6"} %> <%#= render :partial => 'tags/tag', :locals => {:obj => attachment, :object_flag => "6"} %>
@ -36,45 +37,37 @@
<% end %> <% end %>
<% end %> <% end %>
</span> </span>
<script type='text/javascript'> <% project = project %>
// function CompatibleSend() <span class="add_attachment" style="font-weight:normal;">
// {
// var obj=document.getElementById("_file");
// var file= $(obj).clone();
// file.click();
// }
</script>
<% project = project %>
<span class="add_attachment" style="font-weight:normal;">
<%#= button_tag "浏览", :type=>"button", :onclick=>"CompatibleSend();" %> <%#= button_tag "浏览", :type=>"button", :onclick=>"CompatibleSend();" %>
<!--%= link_to image_tag(),"javascript:void(0)", :onclick => "_file.click()"%--> <!--%= link_to image_tag(),"javascript:void(0)", :onclick => "_file.click()"%-->
<%= 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]', <%= file_field_tag 'attachments[dummy][file]',
:id => '_file', :id => '_file',
:class => 'file_selector', :class => 'file_selector',
:multiple => true, :multiple => true,
:onchange => 'addInputFiles(this);', :onchange => 'addInputFiles(this);',
:style => ie8? ? '' : 'display:none', :style => ie8? ? '' : 'display:none',
:data => { :data => {
:max_file_size => Setting.attachment_max_size.to_i.kilobytes, :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_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, :max_concurrent_uploads => Redmine::Configuration['max_concurrent_ajax_uploads'].to_i,
:upload_path => uploads_path(:format => 'js',:project =>project), :upload_path => uploads_path(:format => 'js', :project => project),
:description_placeholder => l(:label_optional_description), :description_placeholder => l(:label_optional_description),
:field_is_public => l(:field_is_public), :field_is_public => l(:field_is_public),
:are_you_sure => l(:text_are_you_sure), :are_you_sure => l(:text_are_you_sure),
:file_count => l(:label_file_count), :file_count => l(:label_file_count),
:delete_all_files => l(:text_are_you_sure_all) :delete_all_files => l(:text_are_you_sure_all)
} %> } %>
<span id="upload_file_count"> <span id="upload_file_count">
<%= l(:label_no_file_uploaded)%> <%= l(:label_no_file_uploaded) %>
</span> </span>
(<%= l(:label_max_size) %>: (<%= l(:label_max_size) %>:
<%= number_to_human_size(Setting.attachment_max_size.to_i.kilobytes) %>) <%= number_to_human_size(Setting.attachment_max_size.to_i.kilobytes) %>)
</span> </span>
<% content_for :header_tags do %> <% content_for :header_tags do %>
<%= javascript_include_tag 'attachments' %> <%= javascript_include_tag 'attachments' %>
<% end %> <% end %>
</div>

@ -38,7 +38,7 @@
<span class="add_attachment"> <span class="add_attachment">
<%#= button_tag "浏览", :type=>"button", :onclick=>"CompatibleSend();" %> <%#= button_tag "浏览", :type=>"button", :onclick=>"CompatibleSend();" %>
<!--%= link_to image_tag(),"javascript:void(0)", :onclick => "_file.click()"%--> <!--%= link_to image_tag(),"javascript:void(0)", :onclick => "_file.click()"%-->
<%= button_tag "浏览", :type=>"button", :onclick=>"_file.click()",:class =>"sub_btn",:style => ie8? ? 'display:none' : '' %> <%= button_tag "#{l(:button_browse)}", :type=>"button", :onclick=>"_file.click()",:class =>"sub_btn",:style => ie8? ? 'display:none' : '' %>
<%= file_field_tag 'attachments[dummy][file]', <%= file_field_tag 'attachments[dummy][file]',
:id => '_file', :id => '_file',
:class => 'file_selector', :class => 'file_selector',

@ -0,0 +1,67 @@
<span id="attachments_fields" xmlns="http://www.w3.org/1999/html">
<% if defined?(container) && container && container.saved_attachments %>
<% if isReply %>
<% container.saved_attachments.each_with_index do |attachment, i| %>
<span id="attachments_p<%= i %>" class="sub_btn">
<%= 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('&nbsp;'.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"} %>
<span class="ispublic-label"><%= l(:field_is_public)%>:</span>
<%= 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}" %>
</span>
<% end %>
<% else %>
<% container.attachments.each_with_index do |attachment, i| %>
<span id="attachments_p<%= i %>" class="attachment">
<%= 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('&nbsp;'.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"} %>
<span class="ispublic-label"><%= l(:field_is_public)%>:</span>
<%= 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}" %>
</span>
<% end %>
<% end %>
<% end %>
</span>
<script type='text/javascript'>
// function CompatibleSend()
// {
// var obj=document.getElementById("_file");
// var file= $(obj).clone();
// file.click();
// }
</script>
<span class="add_attachment">
<%#= button_tag "浏览", :type=>"button", :onclick=>"CompatibleSend();" %>
<!--%= link_to image_tag(),"javascript:void(0)", :onclick => "_file.click()"%-->
<%= 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)
} %>
<span id="upload_file_count" :class="c_grey"><%= l(:label_no_file_uploaded)%></span>
(<%= l(:label_max_size) %>: <%= number_to_human_size(Setting.attachment_max_size.to_i.kilobytes) %>)
</span>
<% content_for :header_tags do %>
<%= javascript_include_tag 'attachments' %>
<% end %>

@ -0,0 +1,18 @@
<div style="font-weight:normal;">
<% for attachment in attachments %>
<div title="<%= attachment.filename%>" id = "attachment_" style="max-width: 300px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;float: left;">
<%= link_to_short_attachment attachment, :class => 'link_file', :download => true, :length => 100 -%>
</div>
<% if attachment.is_text? %>
<div style="float: left;">
<%= link_to image_tag('magnifier.png'),
{:controller => 'attachments',
:action => 'show',
:id => attachment,
:filename => attachment.filename},
:target => "_blank"%>
</div>
<% end %>
<br>
<% end %>
</div>

@ -9,7 +9,7 @@
<% if options[:length] %> <% if options[:length] %>
<%= link_to_short_attachment attachment, :class => 'icon icon-attachment', :download => true,:length => options[:length] -%> <%= link_to_short_attachment attachment, :class => 'icon icon-attachment', :download => true,:length => options[:length] -%>
<% else %> <% else %>
<%= link_to_short_attachment attachment, :class => 'icon icon-attachment', :download => true -%> <%= link_to_short_attachment attachment, :class => 'icon icon-attachment', :download => true, :length => 32 -%>
<% end %> <% end %>
</span> </span>
<%if is_float%> <%if is_float%>
@ -26,9 +26,7 @@
<span title="<%= attachment.description%>"> <span title="<%= attachment.description%>">
<%= h(truncate(" - #{attachment.description}", length: options[:length] ? options[:length]:15, omission: '...')) unless attachment.description.blank? %> <%= h(truncate(" - #{attachment.description}", length: options[:length] ? options[:length]:15, omission: '...')) unless attachment.description.blank? %>
</span> </span>
<span class="size">( <span class="size">(<%= number_to_human_size attachment.filesize , :precision => 0 %>)</span>
<%= number_to_human_size attachment.filesize %>)
</span>
<% if options[:deletable] %> <% if options[:deletable] %>
<% if attachment.container_type == 'HomeworkAttach' %> <% if attachment.container_type == 'HomeworkAttach' %>
<%= link_to image_tag('delete.png'), {:controller => 'attachments', :action => 'delete_homework', :id => attachment.id}, <%= link_to image_tag('delete.png'), {:controller => 'attachments', :action => 'delete_homework', :id => attachment.id},
@ -62,7 +60,7 @@
<% if defined?(thumbnails) && thumbnails %> <% if defined?(thumbnails) && thumbnails %>
<% images = attachments.select(&:thumbnailable?) %> <% images = attachments.select(&:thumbnailable?) %>
<% if images.any? %> <% if images.any? %>
<div class="thumbnails"> <div class="pro_pic mb10" width="100" height="73">
<% images.each do |attachment| %> <% images.each do |attachment| %>
<div><%= thumbnail_tag(attachment) %></div> <div><%= thumbnail_tag(attachment) %></div>
<% end %> <% end %>

@ -25,13 +25,13 @@
</span> </span>
<% project = project %> <% project = project %>
<span class="add_attachment" style="font-weight:normal;"> <span class="add_attachment" style="font-weight:normal;">
<%= button_tag "文件浏览", :type=>"button", :onclick=>"_file.click()",:onmouseover => 'this.focus()',:class => 'sub_btn' %> <%= button_tag l(:button_browse), :type=>"button", :onclick=>"_file.click()",:onmouseover => 'this.focus()',:class => 'sub_btn', :style => ie8? ? 'display:none' : '' %>
<%= file_field_tag 'attachments[dummy][file]', <%= file_field_tag 'attachments[dummy][file]',
:id => '_file', :id => '_file',
:class => 'file_selector', :class => ie8? ? '' : 'file_selector',
:multiple => true, :multiple => true,
:onchange => 'addInputFiles(this);', :onchange => 'addInputFiles(this);',
:style => 'display:none', :style => ie8? ? '' : 'display:none',
:data => { :data => {
:max_file_size => Setting.attachment_max_size.to_i.kilobytes, :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_file_size_message => l(:error_attachment_too_big, :max_size => number_to_human_size(Setting.attachment_max_size.to_i.kilobytes)),

@ -0,0 +1,99 @@
<script type="text/javascript">
jQuery(window).load(function () {
jQuery(".issue_attachment_picture").each(function () {
DrawImage(this, 100, 73);
});
});
function DrawImage(ImgD, FitWidth, FitHeight) {
var image = new Image();
image.src = ImgD.src;
if (image.width > 100 || image.height > 73)
{
rateWidth = image.width / 100;
rateHeight = image.height / 73;
if (rateWidth > rateHeight) {
ImgD.width = 100;
ImgD.height = Math.round(image.height/rateWidth);
}
else
{
ImgD.width = Math.round(image.width/rateHeight);
ImgD.height = 73;
}
}
}
</script>
<div class="attachments" style="font-weight:normal;">
<% is_float ||= false %>
<% for attachment in attachments %>
<p style="width: 100%;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;">
<%if is_float%>
<div style="max-width:55%;white-space: nowrap; overflow: hidden; text-overflow: ellipsis;float: left;">
<% end%>
<span title="<%= attachment.filename %>" id = "attachment_">
<% 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 %>
</span>
<%if is_float%>
</div>
<% end%>
<% if attachment.is_text? %>
<%= link_to image_tag('magnifier.png'),
:controller => 'attachments',
:action => 'show',
:id => attachment,
:filename => attachment.filename%>
<% end %>
<span title="<%= attachment.description%>">
<%= h(truncate(" - #{attachment.description}", length: options[:length] ? options[:length]:15, omission: '...')) unless attachment.description.blank? %>
</span>
<span class="size">(
<%= number_to_human_size attachment.filesize %>)
</span>
<% 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] %>
<br/>
&nbsp;
<% end %>
<% if options[:author] %>
<span class="author" title="<%= attachment.author%>">
<%= link_to h(truncate(attachment.author.name, length: 10, omission: '...')),user_path(attachment.author),:class => "c_orange" %>,
<%= format_time(attachment.created_on) %>
</span>
<% end %>
</p>
<% end %>
<div class="thumbnails">
<% if defined?(thumbnails) && thumbnails %>
<% images = attachments.select(&:thumbnailable?) %>
<% if images.any? %>
<% images.each do |attachment| %>
<div class="pro_pic fl " width="100" height="73"><%= thumbnail_issue_tag(attachment) %></div>
<% end %>
<% end %>
<% end %>
</div>
</div>

@ -0,0 +1,7 @@
<% if !@save_flag && @save_message %>
$("#error_show").html("<%= @save_message.join(', ') %>");
<% elsif @message && @message != "" %>
$("#error_show").html("<%= @message.html_safe %>");
<% else %>
closeModal();
<% end %>

@ -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;" %> <%= 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;" %>
<a href="javascript:void(0);" class="btn_addPic" style="text-decoration:none;"> <a href="javascript:void(0);" class="btn_addPic" style="text-decoration:none;">
<span><%= l(:button_upload_photo) %></span> <span><%= l(:button_upload_photo) %></span>
</a> </a>
<!-- :accept => 'image/png,image/gif,image/jpeg', --> <!-- :accept => 'image/png,image/gif,image/jpeg', -->
<span class="add_avatar" style="margin-left: -55px;width: 70px"> <span class="add_avatar" style="margin-left: -55px;width: 70px">
<%= file_field_tag 'avatar[image]', <%= file_field_tag 'avatar[image]',
@ -68,6 +68,7 @@
:source_id => source.id.to_s :source_id => source.id.to_s
} %> } %>
</span> </span>
</div> </div>
<% content_for :header_tags do %> <% content_for :header_tags do %>
<%= javascript_include_tag 'avatars' %> <%= javascript_include_tag 'avatars' %>

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

Loading…
Cancel
Save