Conflicts:
	app/views/boards/_project_show.html.erb
	public/javascripts/course.js

处理冲突
修改项目动态分页
项目到航天中添加“新建项目”
dev_repository_hjq
huang 10 years ago
commit 12eaac5683

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

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

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

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

@ -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
@ -29,6 +30,10 @@ class CommentsController < ApplicationController
@comment.safe_attributes = params[:comment] @comment.safe_attributes = 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
@ -680,26 +681,49 @@ 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_bids" => true,
"show_course_journals_for_messages" => true, "show_course_journals_for_messages" => true,
"show_bids" => true,
"show_homeworks" => true "show_homeworks" => 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?
@ -708,13 +732,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

@ -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]
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
@ -78,6 +79,39 @@ class FilesController < ApplicationController
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 +121,26 @@ 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
resultSet = Attachment.where("((attachments.container_type = 'Project' And attachments.container_id = '#{project.id}') OR (container_type = 'Version' AND container_id IN (#{ids}))) AND filename LIKE :like ", like: "%#{keywords}%").
reorder(sort)
#resultSet = Attachment.find_by_sql("SELECT `attachments`.* FROM `attachments` LEFT OUTER JOIN `homework_attaches` ON `attachments`.container_type = 'HomeworkAttach' AND `attachments`.container_id = `homework_attaches`.id LEFT OUTER JOIN `homework_for_courses` ON `homework_attaches`.bid_id = `homework_for_courses`.bid_id LEFT OUTER JOIN `homework_for_courses` AS H_C ON `attachments`.container_type = 'Bid' AND `attachments`.container_id = H_C.bid_id WHERE (`homework_for_courses`.course_id = 117 OR H_C.course_id = 117 OR (`attachments`.container_type = 'Course' AND `attachments`.container_id = 117)) AND `attachments`.filename LIKE '%#{keywords}%'").reorder("created_on DESC")
end
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 +186,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 +248,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,6 +265,8 @@ 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)]
@ -215,6 +283,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 +314,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 +343,7 @@ 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 end
# TODO: 临时用 nyan # TODO: 临时用 nyan

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

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

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

@ -336,7 +336,7 @@ class ProjectsController < ApplicationController
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)
else else

@ -131,7 +131,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 +147,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,}"
@ -243,8 +243,8 @@ update
if(@repository.type=="Repository::Git") if(@repository.type=="Repository::Git")
logger.info "destory the repository value"+"root path"+@root_path+"repo_name"+@repo_name+ logger.info "destory the repository value"+"root path"+@root_path+"repo_name"+@repo_name+
"repository_name"+@repository_name+"user group"+@middle "repository_name"+@repository_name+"user group"+@middle
system "sed -i /"+@repo_name+"/{d} "+@root_path+"user.passwd" system "sed -i /"+@repo_name+"/{d} "+@root_path+"htdocs/user.passwd"
system "sed -i /"+@middle+"/{d} "+@root_path+"group.passwd" system "sed -i /"+@middle+"/{d} "+@root_path+"htdocs/group.passwd"
system "rm -r "+@root_path+"htdocs/"+@repository_name system "rm -r "+@root_path+"htdocs/"+@repository_name
# if(@sed_user&&@sed_group&&@remove) # if(@sed_user&&@sed_group&&@remove)
# else # else

@ -553,7 +553,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 +620,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|

@ -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
@ -209,6 +209,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,7 +5,7 @@ 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 def download
@ -16,9 +16,11 @@ class ZipdownController < ApplicationController
end end
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
@ -56,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
@ -88,85 +90,116 @@ 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
zips = split_pack_files(bid_homework_path, Setting.pack_attachment_max_size.to_i*1024) homework_id = bid.id
x = 0 user_id = bid.author_id
zips.each { |o| out_file = find_or_pack(homework_id, user_id, digests.sort){
x += 1 zipping("#{Time.now.to_i}_#{bid.name}.zip",
file = zipping "#{Time.now.to_i}_#{bid.name}_#{x}.zip", o[:files], OUTPUT_FOLDER bid_homework_path, OUTPUT_FOLDER)
o[:real_file] = file
o[:file] = File.basename(file)
o[:size] = (File.size(file) / 1024.0 / 1024.0).round(2)
} }
# 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')
rename_zipfile = zip_name_refer ||= "#{Time.now.to_i.to_s}.zip" out_file = ZipPack.packed?(homework_id, user_id, digests.sort)
zipfile_name = "#{output_path}/#{rename_zipfile}"
Dir.mkdir(File.dirname(zipfile_name)) unless File.exist?(File.dirname(zipfile_name)) unless out_file && out_file.file_valid?
file = yield
ZipPack.where(homework_id: homework_id,
user_id: user_id).delete_all
unless is_attachment out_file = ZipPack.create(homework_id: homework_id,
#都是zip合并没必要再费力压缩了 user_id: user_id,
Zip.default_compression = Zlib::NO_COMPRESSION file_digest: Trustie::Utils.digest(file),
file_path: file,
pack_size: File.size(file),
file_digests: digests.join(',')
)
else else
Zip.default_compression = Zlib::DEFAULT_COMPRESSION out_file.pack_times = out_file.pack_times + 1
out_file.save
end 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"
zipfile_name = "#{output_path}/#{rename_zipfile}"
Dir.mkdir(File.dirname(zipfile_name)) unless File.exist?(File.dirname(zipfile_name))
Zip::File.open(zipfile_name, Zip::File::CREATE) do |zipfile| Zip::File.open(zipfile_name, Zip::File::CREATE) do |zipfile|
files_paths.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
# 合理分配文件打包 # 合理分配文件打包

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

@ -53,6 +53,10 @@ module ApplicationHelper
# Author lizanle # Author lizanle
# Description after save后需要进行资源记录的更新 # Description after save后需要进行资源记录的更新
# owner_type = 1 对应的是 memo # owner_type = 1 对应的是 memo
# owner_type = 2 对应的是forum
# owner_type = 3 对应的是message
# owner_type = 4 对应的是news
# owner_type = 5 对应的是comment
def update_kindeditor_assets_owner ids,owner_id,owner_type def update_kindeditor_assets_owner ids,owner_id,owner_type
ids.each do |id| ids.each do |id|
asset = Kindeditor::Asset.find(id.to_i) asset = Kindeditor::Asset.find(id.to_i)
@ -1676,6 +1680,42 @@ module ApplicationHelper
courses_doing courses_doing
end end
def attachment_candown attachment
candown = false
if attachment.container
if attachment.container.class.to_s != "HomeworkAttach" && (attachment.container.has_attribute?(:project) || attachment.container.has_attribute?(:project_id)) && attachment.container.project
project = attachment.container.project
candown= User.current.member_of?(project) || (project.is_public && attachment.is_public == 1)
elsif attachment.container.is_a?(Project)
project = attachment.container
candown= User.current.member_of?(project) || (project.is_public && attachment.is_public == 1)
elsif (attachment.container.has_attribute?(:board) || attachment.container.has_attribute?(:board_id)) && attachment.container.board &&
attachment.container.board.project
project = attachment.container.board.project
candown = User.current.member_of?(project) || (project.is_public && attachment.is_public == 1)
elsif (attachment.container.has_attribute?(:course) ||attachment.container.has_attribute?(:course_id) ) && attachment.container.course
course = attachment.container.course
candown = User.current.member_of_course?(course) || (course.is_public==1 && attachment.is_public == 1)
elsif attachment.container.is_a?(Course)
course = attachment.container
candown= User.current.member_of_course?(course) || (course.is_public==1 && attachment.is_public == 1)
elsif (attachment.container.has_attribute?(:board) || attachment.container.has_attribute?(:board_id)) && attachment.container.board &&
attachment.container.board.course
course = attachment.container.board.course
candown= User.current.member_of_course?(course) || (course.is_public==1 && attachment.is_public == 1)
elsif attachment.container.class.to_s=="HomeworkAttach" && attachment.container.bid.reward_type == 3
candown = true
elsif attachment.container_type == "Bid" && attachment.container && attachment.container.courses
course = attachment.container.courses.first
candown = User.current.member_of_course?(attachment.container.courses.first) || (course.is_public == 1 && attachment.is_public == 1)
else
candown = (attachment.is_public == 1 || attachment.is_public == true)
end
end
candown
end
private private
def wiki_helper def wiki_helper

@ -87,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
@ -95,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

@ -632,7 +632,7 @@ module CoursesHelper
#获取课程动态 #获取课程动态
def get_course_activity courses, activities def get_course_activity courses, activities
@course_ids=activities.keys() @course_ids=activities.keys()
@bid_ids = []
days = Setting.activity_days_default.to_i days = Setting.activity_days_default.to_i
date_to ||= Date.today + 1 date_to ||= Date.today + 1
date_from = date_to - days-1.years date_from = date_to - days-1.years
@ -653,8 +653,27 @@ module CoursesHelper
activities[news.course_id]+=1 activities[news.course_id]+=1
end end
#feedbackc_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|
# @bid_ids<<homework.bid_id
# activities[homework.bid_id]+=Bid.where(id: @bid_ids).where("created_on>?",date_from).count
#end
#@bid_ids.each do |bid_id|
# activities[] +=Bid.where(id: bid_id ).where("created_on>?",date_from).count
#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
end end
@ -736,4 +755,14 @@ 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
result = []
course.attachments.each do |attachment|
if attachment.is_public? || User.current.member_of_course?(course)
result << attachment
end
end
result
end
end end

@ -1,157 +1,144 @@
# 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>"
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 visable_attachemnts_insite attachments,obj
project = attachment.container.project result = []
candown= User.current.member_of?(project) || (project.is_public && attachment.is_public == 1) if obj.is_a?(Course)
elsif attachment.container.is_a?(Project) attachments.each do |attachment|
project = attachment.container 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
candown= User.current.member_of?(project) || (project.is_public && attachment.is_public == 1) result << attachment
elsif (attachment.container.has_attribute?(:board) || attachment.container.has_attribute?(:board_id)) && attachment.container.board && end
attachment.container.board.project end
project = attachment.container.board.project else if obj.is_a?(Project)
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 == "Project" && attachment.container_id == obj.id && User.current.member_of_course?(Project.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 end
candown= User.current.member_of_course?(course) || (course.is_public==1 && attachment.is_public == 1) end
elsif (attachment.container.has_attribute?(:board) || attachment.container.has_attribute?(:board_id)) && attachment.container.board && result
attachment.container.board.course end
course = attachment.container.board.course
candown= User.current.member_of_course?(course) || (course.is_public==1 && attachment.is_public == 1)
elsif attachment.container.class.to_s=="HomeworkAttach" && attachment.container.bid.reward_type == 3
candown = true
elsif attachment.container_type == "Bid" && attachment.container && attachment.container.courses
course = attachment.container.courses.first
candown = User.current.member_of_course?(attachment.container.courses.first) || (course.is_public == 1 && attachment.is_public == 1)
else
candown = (attachment.is_public == 1 || attachment.is_public == true)
end
end
candown
end
end end

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

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

@ -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,174 @@
# 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,
:timestamp => "#{self.table_name}.updated_on",
:find_options => {:include => :course }
has_many :acts, :class_name => 'Activity', :as => :act, :dependent => :destroy
validates :notes, presence: true has_many :acts, :class_name => 'Activity', :as => :act, :dependent => :destroy
after_create :act_as_activity #huang
after_create :reset_counters! validates :notes, presence: true
after_destroy :reset_counters! after_create :act_as_activity #huang
after_save :be_user_score after_create :reset_counters!
after_destroy :down_user_score after_destroy :reset_counters!
after_save :be_user_score
# default_scope { where('m_parent_id IS NULL') } after_destroy :down_user_score
def self.create_by_user? user # default_scope { where('m_parent_id IS NULL') }
if user.anonymous?
return false def self.create_by_user? user
else if user.anonymous?
return true return false
end else
end return true
end
end
def self.remove_by_user? user
if( self.user == user ||
( self.jour.kind_of?(User) && self.jour== user ) def self.remove_by_user? user
) if( self.user == user ||
true ( self.jour.kind_of?(User) && self.jour== user )
else )
false true
end else
end false
end
def self.delete_message(message_id) end
self.find(message_id).destroy
# self.destroy_all "id = #{message_id}" def self.delete_message(message_id)
end self.find(message_id).destroy
# self.destroy_all "id = #{message_id}"
def reference_user end
User.find(reply_id)
end def reference_user
User.find(reply_id)
def delete_by_user?user end
# 用户可删除自己的留言
if self.user.id == user.id || user.admin? def delete_by_user?user
return true # 用户可删除自己的留言
else if self.user.id == user.id || user.admin?
return false return true
end else
end return false
end
def self.reference_message(user_id) end
@user = User.find(user_id)
message = JournalsForMessage.find_by_sql("select * from journals_for_messages where reply_id = #{@user.id} def self.reference_message(user_id)
or (jour_type = 'Bid' and jour_id in (select id from bids where author_id = #{@user.id}))") @user = User.find(user_id)
message message = JournalsForMessage.find_by_sql("select * from journals_for_messages where reply_id = #{@user.id}
end or (jour_type = 'Bid' and jour_id in (select id from bids where author_id = #{@user.id}))")
message
def act_as_activity end
if self.jour_type == 'Principal'
unless self.user_id == self.jour.id && self.user_id != self.reply_id && self.reply_id != 0 def act_as_activity
# self.acts << Activity.new(:user_id => self.user_id) if self.jour_type == 'Principal'
self.acts << Activity.new(:user_id => self.jour_id) unless self.user_id == self.jour.id && self.user_id != self.reply_id && self.reply_id != 0
end # self.acts << Activity.new(:user_id => self.user_id)
elsif self.jour_type == 'Project' self.acts << Activity.new(:user_id => self.jour_id)
self.acts << Activity.new(:user_id => self.reply_id) end
elsif self.jour_type == 'Course' elsif self.jour_type == 'Project'
self.acts << Activity.new(:user_id => self.reply_id) self.acts << Activity.new(:user_id => self.reply_id)
else elsif self.jour_type == 'Course'
end self.acts << Activity.new(:user_id => self.reply_id)
end else
end
def reset_counters! end
self.class.reset_counters!(self)
end def reset_counters!
def self.reset_counters! journals_for_messages self.class.reset_counters!(self)
# 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} ) def self.reset_counters! journals_for_messages
update_all("m_reply_count = #{count.to_i}", ["id = ?", journals_for_messages.m_parent_id]) # 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} )
update_all("m_reply_count = #{count.to_i}", ["id = ?", journals_for_messages.m_parent_id])
#如果是在项目中留言则返回该项目否则返回nil - zjc end
def project
if self.jour_type == 'Project' #如果是在项目中留言则返回该项目否则返回nil - zjc
Project.find(self.jour_id) def project
else if self.jour_type == 'Project'
nil Project.find(self.jour_id)
end else
end nil
end
# 更新用户分数 -by zjc end
def be_user_score
#新建了留言回复 # 更新用户分数 -by zjc
if self.reply_id != 0 def be_user_score
#协同得分加分 #新建了留言回复
UserScore.joint(:reply_message, self.user,User.find(self.reply_id),self, { journals_for_messages_id: self.id }) if self.reply_id != 0
update_replay_for_message(self.user,1) #协同得分加分
if self.jour_type == "Project" UserScore.joint(:reply_message, self.user,User.find(self.reply_id),self, { journals_for_messages_id: self.id })
update_replay_for_message(self.user,2,self.jour) update_replay_for_message(self.user,1)
end if self.jour_type == "Project"
end update_replay_for_message(self.user,2,self.jour)
end end
# 更新用户分数 -by zjc end
def down_user_score end
#删除了留言回复 # 更新用户分数 -by zjc
if self.reply_id != 0 def down_user_score
#协同得分减分 #删除了留言回复
UserScore.joint(:reply_message_delete, self.user,User.find(self.reply_id), { journals_for_messages_id: self.id }) if self.reply_id != 0
update_replay_for_message(self.user,1) #协同得分减分
if self.jour_type == "Project" UserScore.joint(:reply_message_delete, self.user,User.find(self.reply_id), { journals_for_messages_id: self.id })
update_replay_for_message(self.user,2,self.jour) update_replay_for_message(self.user,1)
end if self.jour_type == "Project"
end update_replay_for_message(self.user,2,self.jour)
end end
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

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

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

@ -194,6 +194,8 @@ class CoursesService
@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]
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

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

@ -95,9 +95,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

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

@ -22,8 +22,8 @@
<%= link_to "留言", get_homework_jours_homework_attach_index_path(:bid_id => @bid.id), {:remote => true}%> <%= link_to "留言", get_homework_jours_homework_attach_index_path(:bid_id => @bid.id), {:remote => true}%>
(<span id="jours_count" class="c_red f_12"><%= @jours_count %></span>) (<span id="jours_count" class="c_red f_12"><%= @jours_count %></span>)
</li> </li>
<li> <li><%= link_to "作品打包下载", zipdown_assort_path(obj_class: @bid.class, obj_id: @bid, format: :json),
<%#= link_to "作品打包下载", zipdown_assort_path(obj_class: @bid.class, obj_id: @bid), class: "tb_all" unless @bid.homeworks.empty? %> remote: true, class: "tb_all" unless @bid.homeworks.empty? %>
</li> </li>
</ul> </ul>
<% else %> <% else %>

@ -1,47 +1,53 @@
<%= stylesheet_link_tag 'jquery/jquery-ui-1.9.2', :media => 'all' %> <%= stylesheet_link_tag 'jquery/jquery-ui-1.9.2', :media => 'all' %>
<%= error_messages_for 'bid' %> <%= error_messages_for 'bid' %>
<%= hidden_field_tag 'course_id', @course.id %> <%= hidden_field_tag 'course_id', @course.id %>
<div class="project_r_h"> <div class="project_r_h">
<h2 class="project_h2"><%= l(:label_course_homework_new)%></h2> <h2 class="project_h2"><%= l(:label_course_homework_new)%></h2>
</div> </div>
<div class="hwork_new"> <div class="hwork_new">
<ul> <ul>
<li class="ml45"> <li class="ml45">
<label><span class="c_red">*</span>&nbsp;<%= l(:field_name)%>&nbsp;&nbsp;</label> <label><span class="c_red">*</span>&nbsp;<%= l(:field_name)%>&nbsp;&nbsp;</label>
<input type="text" name="bid[name]" id="bid_name" class="hwork_input" maxlength="<%= Bid::NAME_LENGTH_LIMIT%>" onkeyup="regex_bid_name();" value="<%= bid.name%>" > <input type="text" name="bid[name]" id="bid_name" class="hwork_input" maxlength="<%= Bid::NAME_LENGTH_LIMIT%>" onkeyup="regex_bid_name();" value="<%= bid.name%>" >
<p id="bid_name_span" class="c_red" style="padding-left: 55px;"></p> <p id="bid_name_span" class="c_red" style="padding-left: 55px;"></p>
</li> </li>
<li class="ml45"> <li class="ml45">
<label class="fl" >&nbsp;&nbsp;<%= l(:field_quote)%>&nbsp;&nbsp;</label> <label class="fl" >&nbsp;&nbsp;<%= l(:field_quote)%>&nbsp;&nbsp;</label>
<textarea name="bid[description]" placeholder="最多3000个汉字(或6000个英文字符)" class="hwork_text fl"><%= bid.description%></textarea> <!--<textarea name="bid[description]" placeholder="最多3000个汉字(或6000个英文字符)" class="hwork_text fl"></textarea>-->
</li> <% if edit_mode %>
<div class="cl"></div> <%= f.kindeditor :description,:width=>'91%',:editor_id => 'bid_description_editor',:owner_id => bid.id,:owner_type =>OwnerTypeHelper::BID %>
<li class="ml21"> <% else %>
<label><span class="c_red">*</span>&nbsp;<%= l(:label_limit_time)%>&nbsp;&nbsp;</label> <%= hidden_field_tag :asset_id,params[:asset_id],:required => false,:style => 'display:none' %>
<input type="text" name="bid[deadline]" id="bid_deadline" class="hwork_input02" onchange="regexDeadLine();" readonly="readonly" value="<%= bid.deadline%>" > <%= f.kindeditor :description,:width=>'91%',:editor_id => 'bid_description_editor' %>
<%= calendar_for('bid_deadline')%> <% end %>
</li> </li>
<li class=" mb5 ml30"> <div class="cl"></div>
<label ><%= l(:label_open_anonymous_evaluation)%>&nbsp;&nbsp;</label> <li class="ml21">
<input type="checkbox" name="bid[open_anonymous_evaluation]" id="bid_open_anonymous_evaluation" <%= bid.open_anonymous_evaluation == 1 ? 'checked' : ''%> > <label><span class="c_red">*</span>&nbsp;<%= l(:label_limit_time)%>&nbsp;&nbsp;</label>
<div class="cl"></div> <input type="text" name="bid[deadline]" id="bid_deadline" class="hwork_input02" onchange="regexDeadLine();" readonly="readonly" value="<%= bid.deadline%>" >
</li> <%= calendar_for('bid_deadline')%>
<li class="ml9" id="bid_evaluation_num_li" style="display: <%= bid.open_anonymous_evaluation == 1 ? 'block' : 'none'%>;"> </li>
<label><span class="c_red">*</span>&nbsp;<%= l(:field_evaluation_num)%>&nbsp;&nbsp;</label> <li class=" mb5 ml30">
<input type="text" name="bid[evaluation_num]" id="bid_evaluation_num" class="hwork_input02" onkeyup="regex_evaluation_num();" value="<%= bid.evaluation_num%>"> <label ><%= l(:label_open_anonymous_evaluation)%>&nbsp;&nbsp;</label>
<span><%= l(:label_evaluation_description)%></span> <input type="checkbox" name="bid[open_anonymous_evaluation]" id="bid_open_anonymous_evaluation" <%= bid.open_anonymous_evaluation == 1 ? 'checked' : ''%> >
<p id="bid_evaluation_num_span" class="c_red" style="padding-left: 90px;"></p> <div class="cl"></div>
</li> </li>
<li class="ml45"> <li class="ml9" id="bid_evaluation_num_li" style="display: <%= bid.open_anonymous_evaluation == 1 ? 'block' : 'none'%>;">
<label class="fl">&nbsp;&nbsp;<%= l(:label_attachment_plural) %>&nbsp;&nbsp;</label> <label><span class="c_red">*</span>&nbsp;<%= l(:field_evaluation_num)%>&nbsp;&nbsp;</label>
<%= render :partial => 'attachments/new_form', :locals => {:container => bid} %> <input type="text" name="bid[evaluation_num]" id="bid_evaluation_num" class="hwork_input02" onkeyup="regex_evaluation_num();" value="<%= bid.evaluation_num%>">
<div class="cl"></div> <span><%= l(:label_evaluation_description)%></span>
</li> <p id="bid_evaluation_num_span" class="c_red" style="padding-left: 90px;"></p>
<li class=" ml90" > </li>
<a class="blue_btn fl c_white" onclick="submit_new_bid('<%= bid_id%>');" href="#"><%= l(:button_create)%></a> <li class="ml45">
<%= link_to l(:button_cancel), homework_course_path(@course), :class => "blue_btn grey_btn fl c_white"%> <label class="fl">&nbsp;&nbsp;<%= l(:label_attachment_plural) %>&nbsp;&nbsp;</label>
<div class="cl"></div> <%= render :partial => 'attachments/new_form', :locals => {:container => bid} %>
</li> <div class="cl"></div>
</ul> </li>
</div> <li class=" ml90" >
<div class="cl"></div> <a class="blue_btn fl c_white" onclick="submit_new_bid('<%= bid_id%>');" href="#"><%= l(:button_create)%></a>
<%= link_to l(:button_cancel), homework_course_path(@course), :class => "blue_btn grey_btn fl c_white"%>
<div class="cl"></div>
</li>
</ul>
</div>
<div class="cl"></div>

@ -1,3 +1,4 @@
<%= javascript_include_tag "/assets/kindeditor/kindeditor" %>
<%= labelled_form_for @bid do |f| %> <%= labelled_form_for @bid do |f| %>
<%= render :partial => 'new_homework_form', :locals => { :bid => @bid, :bid_id => "edit_bid_#{@bid.id}"} %> <%= render :partial => 'new_homework_form', :locals => { :bid => @bid, :bid_id => "edit_bid_#{@bid.id}",:f=>f,:edit_mode => true} %>
<% end %> <% end %>

@ -1,5 +1,6 @@
<% if @project %>
<%= render :partial => 'project_show', locals: {project: @project} %> <% if @project %>
<% elsif @course %> <%= render :partial => 'project_show', locals: {project: @project} %>
<%= render :partial => 'course_show', locals: {course: @course} %> <% elsif @course %>
<% end %> <%= render :partial => 'course_show', locals: {course: @course} %>
<% end %>

@ -1,28 +1,29 @@
<%= javascript_include_tag "/assets/kindeditor/kindeditor" %>
<div class="msg_box" id='leave-message'> <div class="msg_box" id='leave-message'>
<%# reply_allow = JournalsForMessage.create_by_user? User.current %> <%# reply_allow = JournalsForMessage.create_by_user? User.current %>
<h4><%= l(:label_leave_message) %></h4> <h4><%= l(:label_leave_message) %></h4>
<% if !User.current.logged?%> <% if !User.current.logged?%>
<div style="font-size: 14px;margin:20px;"> <div style="font-size: 14px;margin:20px;">
<%= l(:label_user_login_tips) %> <%= l(:label_user_login_tips) %>
<%= link_to l(:label_user_login_new), signin_path %> <%= link_to l(:label_user_login_new), signin_path %>
<hr/> <hr/>
</div> </div>
<% else %> <% else %>
<%= form_for('new_form', :method => :post, <%= form_for('new_form', :method => :post,
:url => {:controller => 'words', :action => 'leave_course_message'}) do |f|%> :url => {:controller => 'words', :action => 'leave_course_message'},:html => {:id=>'leave_message_form'}) do |f|%>
<%= f.text_area 'course_message',:id => "leave_meassge",:style => "resize: none;", <%= hidden_field_tag :asset_id,params[:asset_id],:required => false,:style => 'display:none' %>
:placeholder => "#{l(:label_welcome_my_respond)}",:maxlength => 250%> <%= f.kindeditor 'course_message',:editor_id => 'leave_message_editor',:input_html=>{:id => "leave_meassge",:style => "resize: none;",
<a href="#" class="grey_btn fr ml10">取&nbsp;&nbsp;消</a> :placeholder => "#{l(:label_welcome_my_respond)}",:maxlength => 250}%>
<a href="#" onclick='$("#leave_meassge").parent().submit();' class="blue_btn fr"> <%= l(:button_leave_meassge)%></a> <a href="#" class="grey_btn fr ml10">取&nbsp;&nbsp;消</a>
<% end %> <a href="#" onclick='leave_message_editor.sync();$("#leave_message_form").submit();' class="blue_btn fr"> <%= l(:button_leave_meassge)%></a>
<% end %> <% end %>
</div> <% end %>
</div>
<div id="history">
<%= render :partial => 'history',:locals => { :contest => @contest, :journals => @jour, :state => false} %> <div id="history">
</div> <%= render :partial => 'history',:locals => { :contest => @contest, :journals => @jour, :state => false} %>
<ul class="wlist"> </div>
<%= pagination_links_full @obj_pages, @obj_count, :per_page_links => false, :remote => false, :flag => true%> <ul class="wlist">
<%= pagination_links_full @obj_pages, @obj_count, :per_page_links => false, :remote => false, :flag => true%>
</ul> </ul>

@ -32,7 +32,7 @@
</script> </script>
<div id="bid_description_<%= bid.id%>" class="news_description mt5"> <div id="bid_description_<%= bid.id%>" class="news_description mt5">
<div id="bid_description_<%= bid.id%>_content"> <div id="bid_description_<%= bid.id%>_content">
<%= textilizable bid, :description %> <%= textAreailizable bid, :description %>
</div> </div>
</div> </div>
<div class="news_foot c_red" id="bid_show_more_des_button<%= bid.id%>" onclick="bid_show_more_des(<%= bid.id%>);" style="cursor:pointer;display: none;"> <div class="news_foot c_red" id="bid_show_more_des_button<%= bid.id%>" onclick="bid_show_more_des(<%= bid.id%>);" style="cursor:pointer;display: none;">

@ -1,3 +1,16 @@
<script src="/jquery.min.js"></script>
<script type="text/javascript" src="/javascripts/iPass.packed.js"></script>
<script type="text/javascript">
$(document).ready(function(){
// to enable iPass plugin
$("input[type=password]").iPass();
// for the demo
$("#psw_btn").click(function() {
alert("密码: "+$("#course_course_password").val());
})
});
</script>
<div class="project_r_h02"> <div class="project_r_h02">
<h2 class="project_h2"><%= l(:permission_new_course)%></h2> <h2 class="project_h2"><%= l(:permission_new_course)%></h2>
</div> </div>
@ -24,7 +37,8 @@
<div class="cl"></div> <div class="cl"></div>
<li class="ml45 mb10"> <li class="ml45 mb10">
<label><span class="c_red">*</span>&nbsp;<%= l(:label_new_course_password)%>&nbsp;&nbsp;</label> <label><span class="c_red">*</span>&nbsp;<%= l(:label_new_course_password)%>&nbsp;&nbsp;</label>
<input type="text" name="course[password]" id="course_course_password" class="hwork_input02" > <input type="password" name="course[password]" id="course_course_password" class="hwork_input02" >
<a id="psw_btn" class="">显示明码</a>
<div class="cl"></div> <div class="cl"></div>
<span class=" ml80 c_orange">学生或其他成员申请加入课程时候需要使用该口令,该口令可以由老师在课堂上公布。</span> <span class=" ml80 c_orange">学生或其他成员申请加入课程时候需要使用该口令,该口令可以由老师在课堂上公布。</span>
</li> </li>
@ -35,7 +49,7 @@
</li> </li>
<li class=" mb5 ml80"> <li class=" mb5 ml80">
<label >公开&nbsp;&nbsp;</label> <label >公开&nbsp;&nbsp;</label>
<input checked="checked" id="course_is_public" name="course[is_public]" type="checkbox" value="1"> <input id="course_is_public" name="course[is_public]" type="checkbox" value="1">
<span class="c_grey">(打钩为公开,不打钩则不公开,若不公开,仅课程成员可见该课程。)</span> <span class="c_grey">(打钩为公开,不打钩则不公开,若不公开,仅课程成员可见该课程。)</span>
<div class="cl"></div> <div class="cl"></div>
</li> </li>

@ -1,3 +1,4 @@
<%= labelled_form_for @homework, :url => {:controller => 'bids', :action => 'create_homework',:course_id => "#{params[:id] || params[:course_id]}"} do |f| %> <%= javascript_include_tag "/assets/kindeditor/kindeditor" %>
<%= render :partial => 'bids/new_homework_form', :locals => { :bid => @homework,:bid_id => "new_bid" } %> <%= labelled_form_for @homework, :url => {:controller => 'bids', :action => 'create_homework',:course_id => "#{params[:id] || params[:course_id]}"} do |f| %>
<%= render :partial => 'bids/new_homework_form', :locals => { :bid => @homework,:bid_id => "new_bid",:f => f,:edit_mode => false } %>
<% end %> <% end %>

@ -12,12 +12,13 @@
<div class="problem_txt fl mt5"> <div class="problem_txt fl mt5">
<%= link_to_user_header(e.event_author,false,:class => 'problem_name c_orange fl') if e.respond_to?(:event_author) %> <%= link_to_user_header(e.event_author,false,:class => 'problem_name c_orange fl') if e.respond_to?(:event_author) %>
<%= link_to_user_header("(#{e.event_author})", @canShowRealName,:class => 'problem_name c_orange fl') if @canShowRealName && e.respond_to?(:event_author) %> <%= link_to_user_header("(#{e.event_author})", @canShowRealName,:class => 'problem_name c_orange fl') if @canShowRealName && e.respond_to?(:event_author) %>
<span class="fl"> &nbsp;</span>
<span class="fl"> <%= l(:label_new_activity) %></span> <span class="fl"> <%= l(:label_new_activity) %></span>
<%= link_to "#{eventToLanguageCourse(e.event_type, @course)}: "<< format_activity_title(e.event_title), (e.event_type.eql?("attachment")&&e.container.kind_of?(Course)) ? course_files_path(e.container) : e.event_url,:class => "problem_tit c_dblue fl fb"%> <%= link_to "#{eventToLanguageCourse(e.event_type, @course)} "<< format_activity_title(e.event_title), (e.event_type.eql?("attachment")&&e.container.kind_of?(Course)) ? course_files_path(e.container) : e.event_url,:class => "problem_tit c_dblue fl fb"%>
<br /> <br />
<p class="mt5 break_word"><%= e.event_description %> <p class="mt5 break_word"><%= e.event_description %>
<br /> <br />
<%= l :label_activity_time %> <%= format_activity_day(day) %><%= format_time(e.event_datetime, false) %> <%= l :label_activity_time %> <%= format_activity_day(day) %>&nbsp;<%= format_time(e.event_datetime, false) %>
</p> </p>
</div> </div>
<div class="cl"></div> <div class="cl"></div>
@ -25,7 +26,7 @@
<% end%> <% end%>
<% end%> <% end%>
<% end%> <% end%>
<% if @obj_pages.next_page.nil? %>
<div class="problem_main"> <div class="problem_main">
<a class="problem_pic fl"> <a class="problem_pic fl">
<%= image_tag(url_to_avatar(@user), :width => "42", :height => "42") %> <%= image_tag(url_to_avatar(@user), :width => "42", :height => "42") %>
@ -43,7 +44,7 @@
</div> </div>
<div class="cl"></div> <div class="cl"></div>
</div><!--课程动态 end--> </div><!--课程动态 end-->
<% end%>
<ul class="wlist"> <ul class="wlist">
<%= pagination_links_full @obj_pages, @obj_count, :per_page_links => false, :remote => false, :flag => true%> <%= pagination_links_full @obj_pages, @obj_count, :per_page_links => false, :remote => false, :flag => true%>
</ul> </ul>

@ -1,25 +0,0 @@
<h1 style="">文章列表</h1>
<div>
<table border="1px solid !important" >
<% @discuss_demo_list.each do |e| %>
<tr align="left" height="20">
<td width="30%" ><%= truncate(e.title,:length => 50) %></td>
<td align="center" width="60%">
<%= truncate(e.body,:length => 50) %> &nbsp;
</td>
<td style=" margin-right: 1" width="10%">
<%= link_to '查看文章',{:controller => 'discuss_demos',:action => 'show',:id=>e.id} %>
</td>
<td>
&nbsp;&nbsp;
<%= link_to '删除文章',discuss_demo_path(e.id), :method => :delete,:confirm => l(:text_are_you_sure) %>
</td>
</tr>
<tr height="20"></tr>
<tr height="20"></tr>
<% end %>
</table>
<% paginate @discuss_demo_list %>
<%= link_to '新建文章',new_discuss_demo_path %>
</div>

@ -1,7 +0,0 @@
<%= javascript_include_tag src='/assets/kindeditor/kindeditor' %>
<h1>新建文章</h1>
<%= form_for @discuss_demo,:url => {:controller => 'discuss_demos',:action => "show",:id =>@discuss_demo.id, :method => :put} do |f| %>
<%= f.text_field :title %>
<%= f.kindeditor :body ,:owner_id => @discuss_demo.id%>
<%= f.submit :value=> '提交' %>
<% end %>

@ -1,3 +0,0 @@
<h1><%= @discuss_demo.title %></h1>
<%= textAreailizable @discuss_demo.body %>
<%=link_to "返回首页",discuss_demos_path %>

@ -55,7 +55,7 @@
<div class="cl"></div> <div class="cl"></div>
<div class="re_con" id="course_list"> <div class="re_con" id="course_list">
<%= render :partial => 'course_list',:locals => {course: @course,all_attachments: @all_attachments,sort:@sort,order:@order,curse_attachments:@curse_attachments} %> <%= render :partial => 'course_list',:locals => {course: @course,all_attachments: @all_attachments,sort:@sort,order:@order,curse_attachments:@obj_attachments} %>
</div><!---re_con end--> </div><!---re_con end-->
</div> </div>

@ -15,7 +15,8 @@
</div> </div>
<div class="cl"></div> <div class="cl"></div>
<div class="for_img_thumbnails"> <div class="for_img_thumbnails">
<% curse_attachments.each do |file| %> <% curse_attachments.sort.reverse.each do |file| %>
<% if file.is_public? || User.current.member_of_course?(course) %>
<div class="re_con_box"> <div class="re_con_box">
<div class=""> <div class="">
<%= link_to_attachment file, :download => true,:text => truncate(file.filename,length: 35, omission: '...'), :title => file.filename+"\n"+file.description.to_s, :style => "overflow: hidden; white-space: nowrap;text-overflow: ellipsis;",:class => "c_dblue f_14 f_b f_l" %> <%= link_to_attachment file, :download => true,:text => truncate(file.filename,length: 35, omission: '...'), :title => file.filename+"\n"+file.description.to_s, :style => "overflow: hidden; white-space: nowrap;text-overflow: ellipsis;",:class => "c_dblue f_14 f_b f_l" %>
@ -50,6 +51,9 @@
</div> </div>
<div class="cl"></div> <div class="cl"></div>
</div><!---re_con_box end--> </div><!---re_con_box end-->
<% else %>
<div class="re_con_box"><span class='fr mr10 pr_join_span '><%= file.filename %>是私有资源</span></div>
<% end %>
<% end %> <% end %>
</div> </div>
<ul class="wlist"> <ul class="wlist">

@ -0,0 +1,58 @@
<div class="re_con_top">
<p class="f_l c_blue f_b f_14">共有&nbsp;<%= all_attachments.count%>&nbsp;个资源</p>
<p class="f_r" style="color: #808080">
<% if order == "asc" %>
按&nbsp;<%= link_to "时间",params.merge(:sort=>"created_on:desc"),:class => "f_b c_grey",:remote => @is_remote %><%= render partial: 'arrow_show',locals: { sort: sort,order:order,current:"created_on"} %>&nbsp;/&nbsp;
<%= link_to "下载次数",params.merge(:sort=>"downloads:desc"),:class => "f_b c_grey",:remote => @is_remote %><%= render partial: 'arrow_show',locals: { sort: sort,order:order,current:"downloads"} %>&nbsp;/&nbsp;
<%= link_to "引用次数",params.merge(:sort=>"quotes:desc"),:class => "f_b c_grey",:remote => @is_remote %><%= render partial: 'arrow_show',locals: { sort: sort,order:order,current:"quotes"} %>&nbsp;排序
<% else %>
按&nbsp;<%= link_to "时间",params.merge(:sort=>"created_on:asc"),:class => "f_b c_grey" ,:remote => @is_remote %><%= render partial: 'arrow_show',locals: { sort: sort,order:order,current:"created_on"} %>&nbsp;/&nbsp;
<%= link_to "下载次数",params.merge(:sort=>"downloads:asc"),:class => "f_b c_grey",:remote => @is_remote %><%= render partial: 'arrow_show',locals: { sort: sort,order:order,current:"downloads"} %>&nbsp; /&nbsp;
<%= link_to "引用次数",params.merge(:sort=>"quotes:asc"),:class => "f_b c_grey",:remote => @is_remote %><%= render partial: 'arrow_show',locals: { sort: sort,order:order,current:"quotes"} %>&nbsp;排序
<% end %>
</p>
</div>
<div class="cl"></div>
<div class="for_img_thumbnails">
<% project_attachments.each do |file| %>
<div class="re_con_box">
<div class="">
<%= link_to_attachment file, :download => true,:text => truncate(file.filename,length: 35, omission: '...'), :title => file.filename+"\n"+file.description.to_s, :style => "overflow: hidden; white-space: nowrap;text-overflow: ellipsis;",:class => "c_dblue f_14 f_b f_l" %>
<% if User.current.logged? %>
<% if (manage_allowed || file.author_id == User.current.id) && project_contains_attachment?(project,file) %>
<%= link_to(l(:label_slected_to_other_project),quote_resource_show_project_project_file_path(project,file),:class => "f_l re_select",:remote => true) if has_project?(User.current,file) %>
<% if manage_allowed && file.container_id == project.id && file.container_type == "Project" %>
<span id="is_public_<%= file.id %>">
<%= link_to (file.is_public? ? "公开":"私有"), update_file_dense_attachments_path(:attachmentid=>file.id,:newtype=>(file.is_public? ? 0:1)),:remote=>true,:class=>"f_l re_open",:method => :post %>
</span>
<% else %>
<!-- <#%= link_to (file.is_public? ? "公开":"私有"),"javascript:void(0)",:class=>"f_l re_open" %> -->
<% end %>
<% else %>
<%= link_to(l(:label_slected_to_project),quote_resource_show_project_project_file_path(project,file),:class => "f_l re_select",:remote => true) if has_project?(User.current,file) %>
<% end %>
<% else %>
<% end %>
</div>
<div class="cl"></div>
<div class="">
<p class="f_l c_grey02 font">文件大小:<%= number_to_human_size(file.filesize) %></p>
<%= link_to( l(:button_delete), attachment_path(file),
:data => {:confirm => l(:text_are_you_sure)}, :method => :delete,:class => "f_r re_de") if manage_allowed && file.container_id == project.id && file.container_type == "Project"%>
<p class="f_r c_grey02" ><%= time_tag(file.created_on).html_safe %><%= l(:label_bids_published_ago) %>&nbsp;&nbsp;|&nbsp;&nbsp;下载<%= file.downloads %>&nbsp;&nbsp;|&nbsp;&nbsp;引用<%= file.quotes.nil? ? 0:file.quotes %> </p>
</div>
<div class="cl"></div>
<div class="tag_h">
<%= render :partial => 'tags/tag_new', :locals => {:obj => file, :object_flag => "10"} %>
<%= render :partial => 'tags/tag_add', :locals => {:obj => file, :object_flag => "10"} %>
</div>
<div class="cl"></div>
</div><!---re_con_box end-->
<% end %>
</div>
<ul class="wlist">
<%= pagination_links_full @obj_pages, @obj_count, :per_page_links => false, :remote => @is_remote, :flag => true%>
</ul>
<div class="cl"></div>

@ -0,0 +1,65 @@
<div class="project_r_h">
<h2 class="project_h2"><%= l(:lable_file_sharingarea) %></h2>
</div>
<!--<%#= stylesheet_link_tag 'resource', :media => 'all' %> -->
<script>
function show_upload()
{
$('#ajax-modal').html('<%= escape_javascript(render :partial => 'upload_show_project',:locals => {:project => project}) %>');
showModal('ajax-modal', '513px');
$('#ajax-modal').siblings().remove();
$('#ajax-modal').before("<span style='float: right;cursor:pointer;padding-left: 513px;'><a href='javascript:void(0)' onclick='closeModal()'><img src='/images/bid/close.png' width='26px' height='26px' /></a></span>")
$('#ajax-modal').parent().css("top","").css("left","");
$('#ajax-modal').parent().addClass("popbox_polls");
}
function closeModal()
{
hideModal($("#popbox_upload"));
}
function presscss(id)
{
if(id == "incourse")
{
$('#incourse').attr("class", "re_schbtn b_dblue");
$('#insite').attr("class", "re_schbtn b_lblue");
}
else
{
$('#incourse').attr("class", "re_schbtn b_lblue");
$('#insite').attr("class", "re_schbtn b_dblue");
}
}
function buttoncss()
{
$('#incourse').attr("class", "re_schbtn b_lblue");
$('#insite').attr("class", "re_schbtn b_lblue");
}
</script>
<div class="container">
<div class="resource"><!--资源库内容开始--->
<div class="re_top">
<%= form_tag( search_project_project_files_path(@project), method: 'get',:class => "re_search f_l",:remote=>true) do %>
<%= text_field_tag 'name', params[:name], name: "name", :class => 're_schbox',:style=>"padding: 0px"%>
<%= submit_tag "课内搜索", :class => "re_schbtn b_lblue",:name => "incourse",:id => "incourse", :onmouseover => "presscss('incourse')",:onmouseout =>"buttoncss()" %>
<%= submit_tag "全站搜索", :class => "re_schbtn b_lblue",:name => "insite",:id => "insite",:onmouseover => "presscss('insite')",:onmouseout =>"buttoncss()" %>
<% end %>
<% manage_allowed = User.current.allowed_to?(:manage_files, @project) %>
<% if manage_allowed %> <!-- show_window('light','fade','20%','35%')-->
<a href="javascript:void(0)" class="re_fabu f_r b_lblue" onclick="show_upload();">上传资源</a>
<% end %>
</div><!---re_top end-->
<div class="cl"></div>
<div class="re_con" id="course_list">
<%= render :partial => 'project_file_list',:locals => {project: @project,all_attachments: @all_attachments,sort:@sort,order:@order,project_attachments:@obj_attachments,:manage_allowed => manage_allowed} %>
</div><!---re_con end-->
</div>
</div>
<% html_title(l(:label_attachment_plural)) -%>

@ -24,8 +24,8 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<% if @curse_attachments != nil %> <% if @obj_attachments != nil %>
<% @curse_attachments.each do |file| %> <% @obj_attachments.each do |file| %>
<%if file.is_public == 0 && !User.current.member_of?(@project)%> <%if file.is_public == 0 && !User.current.member_of?(@project)%>
<%next%> <%next%>
<%end%> <%end%>

@ -0,0 +1,31 @@
<div id="popbox_upload" style="margin-top: -30px;margin-left: -20px;margin-right: -10px;">
<div class="upload_con">
<h2>将此课件引入我的资源库</h2>
<% if error == '403' %>
<div class="upload_box">
<div style="color: red;">您没有权限引用此资源</div>
</div>
<% else %>
<div class="upload_box">
<div id="error_show" style="color: red;"></div>
<%= form_tag attach_relations_path,
method: :post,
remote: true,
id: "relation_file_form" do %>
<%= hidden_field_tag(:file_id, file.id) %>
<%= content_tag('div', projects_check_box_tags('projects[project][]', User.current.projects,project,file), :id => 'projects')%>
<a id="submit_quote" href="javascript:void(0)" class="blue_btn fl c_white" onclick="submit_quote();">引&nbsp;&nbsp;用</a><a href="javascript:void(0)" class="blue_btn grey_btn fl c_white" onclick="closeModal();">取&nbsp;&nbsp;消</a>
<% end -%>
</div>
<% end %>
</div>
</div>
<script>
function submit_quote()
{
$('#submit_quote').parent().submit();
}
</script>

@ -0,0 +1,29 @@
<div id="popbox_upload" class="box_h3 mb10" style="margin-top: -30px">
<div class="upload_con">
<h2><%= l(:label_upload_files)%></h2>
<div class="upload_box">
<%= error_messages_for 'attachment' %>
<div id="network_issue" style="color: red; display: none;"><%= l(:label_file_upload_error_messages)%></div>
<%= form_tag(project_files_path(project), :multipart => true,:remote => !ie8?,:name=>"upload_form") do %>
<!-- <label style="margin-top:3px;"><#%= l(:label_file_upload)%></label> -->
<%= render :partial => 'attachement_list',:locals => {:project => project} %>
<div class="cl"></div>
<a href="javascript:void(0);" class=" fr grey_btn mr40" onclick="closeModal();"><%= l(:button_cancel)%></a>
<a id="submit_resource" href="javascript:void(0);" class="blue_btn fr" onclick="submit_resource();"><%= l(:button_confirm)%></a>
<% end %>
</div>
</div>
<% content_for :header_tags do %>
<%= javascript_include_tag 'attachments' %>
<% end %>
</div>
<script>
function submit_resource()
{
$('#submit_resource').parent().submit();
}
</script>

@ -1,35 +1,33 @@
<%if @addTag%> <% if @addTag%>
<% if @obj_flag == '3'%> <% if @obj_flag == '3'%>
$('#tags_show_issue').html('<%= escape_javascript(render :partial => 'tags/tag_name',
$('#tags_show_issue').html('<%= escape_javascript(render :partial => 'tags/tag_name',
:locals => {:obj => @obj,:non_list_all => false,:object_flag => @obj_flag}) %>'); :locals => {:obj => @obj,:non_list_all => false,:object_flag => @obj_flag}) %>');
//$('#put-tag-form-issue').hide(); //$('#put-tag-form-issue').hide();
$('#name-issue').val(""); $('#name-issue').val("");
<% elsif @obj_flag == '6'%> <% elsif @obj_flag == '6'%>
$("#tags_show-<%=@obj.class%>-<%=@obj.id%>").empty(); $("#tags_show-<%=@obj.class%>-<%=@obj.id%>").empty();
$("#tags_show-<%=@obj.class%>-<%=@obj.id%>").html('<%= escape_javascript(render :partial => 'tags/tag_name', $("#tags_show-<%=@obj.class%>-<%=@obj.id%>").html('<%= escape_javascript(render :partial => 'tags/tag_name',
:locals => {:obj => @obj,:non_list_all => false,:object_flag => @obj_flag}) %>'); :locals => {:obj => @obj,:non_list_all => false,:object_flag => @obj_flag}) %>');
$("#put-tag-form- <%=@obj.class%>- <%=@obj.id%>").hide(); $("#put-tag-form- <%=@obj.class%>- <%=@obj.id%>").hide();
$("#put-tag-form-<%=@obj.class%>-<%=@obj.id%> #name").val(""); $("#put-tag-form-<%=@obj.class%>-<%=@obj.id%> #name").val("");
<% else %> <% else %>
$('#tags_show').html('<%= escape_javascript(render :partial => 'tags/tag_name',
$('#tags_show').html('<%= escape_javascript(render :partial => 'tags/tag_name',
:locals => {:obj => @obj,:non_list_all => false,:object_flag => @obj_flag}) %>'); :locals => {:obj => @obj,:non_list_all => false,:object_flag => @obj_flag}) %>');
$('#tags_show').html('<%=render_attachments_tag_save(@project, nil)%>'); $('#tags_show').html('<%=render_attachments_tag_save(@project, nil)%>');
$('#put-tag-form #name').val(""); $('#put-tag-form #name').val("");
//$('#put-tag-form').hide(); //$('#put-tag-form').hide();
<% end %> <% end %>
<%else%> <% else %>
$("#attachments_fields").children().remove(); $("#attachments_fields").children().remove();
$("#upload_file_count").text("未上传文件"); $("#upload_file_count").text("未上传文件");
$('#upload_file_div').slideToggle('slow'); $('#upload_file_div').slideToggle('slow');
<%if @project%> <% if @project%>
$("#all_browse_div").html('<%= j(render partial: "show_all_attachment")%>'); closeModal();
<%elsif @course%> $("#resource_list").html('<%= j(render partial: "project_file_new" ,locals: {project: @project}) %>');
$("#all_browse_div").html('<%= j(render partial: "course_show_all_attachment")%>'); <%elsif @course%>
closeModal(); closeModal();
$("#resource_list").html('<%= j(render partial: "course_file" ,locals: {course: @course}) %>'); $("#resource_list").html('<%= j(render partial: "course_file" ,locals: {course: @course}) %>');
<%end%> <% end %>
<% end %> <% end %>
$(document).ready(img_thumbnails); $(document).ready(img_thumbnails);

@ -0,0 +1,11 @@
<% if @can_quote %>
$('#ajax-modal').html('<%= escape_javascript(render :partial => 'show_quote_resource_project',:locals => {:project => @project,:file => @file,:error => ''}) %>');
<% else %>
$('#ajax-modal').html('<%= escape_javascript(render :partial => 'show_quote_resource_project',:locals => {:project => @project,:file => @file,:error => '403'}) %>');
<% end %>
showModal('ajax-modal', '513px');
$('#ajax-modal').siblings().remove();
$('#ajax-modal').before("<span style='float: right;cursor:pointer;padding-left: 513px;'><a href='javascript:void(0)' onclick='closeModal()'><img src='/images/bid/close.png' width='26px' height='26px' /></a></span>");
$('#ajax-modal').parent().css("top","").css("left","");
$('#ajax-modal').parent().addClass("popbox_polls");

@ -0,0 +1 @@
$("#course_list").html("<%= escape_javascript(render :partial => 'project_file_list',:locals => {project: @project,all_attachments: @result,sort:@sort,order:@order,project_attachments:@searched_attach,:manage_allowed => User.current.allowed_to?(:manage_files, @project)})%>");

@ -1,114 +1,114 @@
<% bid = homework.bid%> <% bid = homework.bid%>
<li class="pic_head" style="line-height: 1.2;"> <li class="pic_head" style="line-height: 1.2;">
<% if is_student_batch_homework %> <% if is_student_batch_homework %>
<!-- 学生匿评 不现实姓名、头像,以及相关的连接 --> <!-- 学生匿评 不现实姓名、头像,以及相关的连接 -->
<a><%= image_tag(url_to_avatar("匿名"), :width => "40", :height => "40")%></a> <a><%= image_tag(url_to_avatar("匿名"), :width => "40", :height => "40")%></a>
<a>匿名</a> <a>匿名</a>
<% else %> <% else %>
<%= link_to image_tag(url_to_avatar(homework.user), :width => "40", :height => "40"), user_path(homework.user) %> <%= link_to image_tag(url_to_avatar(homework.user), :width => "40", :height => "40"), user_path(homework.user) %>
<span> <span>
<% user_realname = homework.user.lastname.to_s + homework.user.firstname.to_s %> <% user_realname = homework.user.lastname.to_s + homework.user.firstname.to_s %>
<% user_name = is_teacher ? (user_realname.empty? ? homework.user.login : user_realname) : homework.user.login %> <% user_name = is_teacher ? (user_realname.empty? ? homework.user.login : user_realname) : homework.user.login %>
<%= link_to user_name, user_path(homework.user), :title => user_name %> <%= link_to user_name, user_path(homework.user), :title => user_name %>
</span> </span>
<% end %> <% end %>
</li> </li>
<li class="wname"> <li class="wname">
<% if homework.name == nil || homework.name == "" %> <% if homework.name == nil || homework.name == "" %>
<% homework_filename = homework.user.name + "提交的作业" %> <% homework_filename = homework.user.name + "提交的作业" %>
<% else %> <% else %>
<% homework_filename = homework.name %> <% homework_filename = homework.name %>
<% end %> <% end %>
<%= link_to homework_filename , homework_attach_path(homework,:cur_page => @cur_page,:cur_type => @cur_type,:cur_sort => @cur_sort, :cur_direction => @cur_direction), :title => homework_filename, :remote => true%> <%= link_to homework_filename , homework_attach_path(homework,:cur_page => @cur_page,:cur_type => @cur_type,:cur_sort => @cur_sort, :cur_direction => @cur_direction), :title => homework_filename, :remote => true%>
<span class="c_grey "> <span class="c_grey ">
提交时间: 提交时间:
<%= format_time homework.created_at%> <%= format_time homework.created_at%>
</span> </span>
</li> </li>
<li class="wdown"> <li class="wdown">
<%#= link_to "(#{homework.attachments.count.to_s}个附件)", "javascript:"%> <%= link_to "(#{homework.attachments.count.to_s}个附件)", zipdown_download_user_homework_path(:homework => homework)%>
</li> </li>
<li class="wscore"> <li class="wscore">
<% unless is_student_batch_homework %> <% unless is_student_batch_homework %>
<%= l(:label_teacher_score)%>: <%= l(:label_teacher_score)%>:
<span class="c_red"> <span class="c_red">
<%= (homework.t_score.nil? || (homework.t_score && homework.t_score.to_i == 0)) ? l(:label_without_score) : format("%.2f",homework.t_score)%> <%= (homework.t_score.nil? || (homework.t_score && homework.t_score.to_i == 0)) ? l(:label_without_score) : format("%.2f",homework.t_score)%>
</span> </span>
&nbsp;&nbsp; &nbsp;&nbsp;
<% end %> <% end %>
</li> </li>
<li class="wscore"> <li class="wscore">
<%= is_student_batch_homework ? l(:label_my_score) : l(:label_student_score)%>: <%= is_student_batch_homework ? l(:label_my_score) : l(:label_student_score)%>:
<span class="c_red"> <span class="c_red">
<%= is_student_batch_homework ? (homework.m_score.nil? ? l(:label_without_score) : format("%.2f",homework.m_score)) : (homework.s_score.nil? ? l(:label_without_score) : format("%.2f",homework.s_score))%> <%= is_student_batch_homework ? (homework.m_score.nil? ? l(:label_without_score) : format("%.2f",homework.m_score)) : (homework.s_score.nil? ? l(:label_without_score) : format("%.2f",homework.s_score))%>
</span> </span>
</li> </li>
<% if is_teacher %> <% if is_teacher %>
<!-- 是老师,所有列表正常显示 --> <!-- 是老师,所有列表正常显示 -->
<li class="wping"> <li class="wping">
<%= link_to l(:label_work_rating),homework_attach_path(homework,:cur_page => @cur_page,:cur_type => @cur_type,:cur_sort => @cur_sort, :cur_direction => @cur_direction),:remote => true %> <%= link_to l(:label_work_rating),homework_attach_path(homework,:cur_page => @cur_page,:cur_type => @cur_type,:cur_sort => @cur_sort, :cur_direction => @cur_direction),:remote => true %>
<% if Time.parse(bid.deadline.to_s).strftime("%Y-%m-%d") < Time.parse(homework.created_at.to_s).strftime("%Y-%m-%d") %> <% if Time.parse(bid.deadline.to_s).strftime("%Y-%m-%d") < Time.parse(homework.created_at.to_s).strftime("%Y-%m-%d") %>
<span class="c_red">&nbsp;&nbsp;迟交!</span> <span class="c_red">&nbsp;&nbsp;迟交!</span>
<% end %> <% end %>
</li> </li>
<% else %> <% else %>
<!-- 是学生 --> <!-- 是学生 -->
<% if is_my_homework %> <% if is_my_homework %>
<!-- 我的作品,在未开启匿评和未使用匿评,显示为编辑和删除 --> <!-- 我的作品,在未开启匿评和未使用匿评,显示为编辑和删除 -->
<% if bid.comment_status == 0 || bid.open_anonymous_evaluation == 0 %> <% if bid.comment_status == 0 || bid.open_anonymous_evaluation == 0 %>
<li class="wmine"> <li class="wmine">
<%= link_to l(:button_edit), edit_homework_attach_path(homework) %> <%= link_to l(:button_edit), edit_homework_attach_path(homework) %>
<% if homework.user == User.current || User.current.admin? %> <% if homework.user == User.current || User.current.admin? %>
<!-- 作业创建者显示删除作业 --> <!-- 作业创建者显示删除作业 -->
<%= link_to(l(:label_bid_respond_delete), homework, <%= link_to(l(:label_bid_respond_delete), homework,
method: :delete, :confirm => l(:text_are_you_sure), :remote => true ) %> method: :delete, :confirm => l(:text_are_you_sure), :remote => true ) %>
<% else %> <% else %>
<!-- 作业参与者显示退出作业 --> <!-- 作业参与者显示退出作业 -->
<%= link_to l(:label_logout), destory_homework_users_homework_attach_path(homework,:user_id=>User.current.id), <%= link_to l(:label_logout), destory_homework_users_homework_attach_path(homework,:user_id=>User.current.id),
:remote => true, :confirm => l(:label_sure_exit_homework) %> :remote => true, :confirm => l(:label_sure_exit_homework) %>
<% end %> <% end %>
</li> </li>
<% else %> <% else %>
<li class="wmine" title="只有开启匿评之前才能修改和删除作业哦!"> <li class="wmine" title="只有开启匿评之前才能修改和删除作业哦!">
<a style="color:#8e8e8e;"><%= l(:button_edit) %></a> <a style="color:#8e8e8e;"><%= l(:button_edit) %></a>
<% if homework.user == User.current || User.current.admin? %> <% if homework.user == User.current || User.current.admin? %>
<!-- 作业创建者显示删除作业 --> <!-- 作业创建者显示删除作业 -->
<a style="color:#8e8e8e;"> <a style="color:#8e8e8e;">
<%=l(:label_bid_respond_delete)%> <%=l(:label_bid_respond_delete)%>
</a> </a>
<% else %> <% else %>
<!-- 作业参与者显示退出作业 --> <!-- 作业参与者显示退出作业 -->
<a style="color:#8e8e8e;"> <a style="color:#8e8e8e;">
<%=l(:label_logout) %> <%=l(:label_logout) %>
</a> </a>
<% end %> <% end %>
</li> </li>
<% end %> <% end %>
<% elsif is_student_batch_homework%> <% elsif is_student_batch_homework%>
<!-- 学生匿评列表 --> <!-- 学生匿评列表 -->
<% if bid.comment_status == 1 %> <% if bid.comment_status == 1 %>
<!-- 处于开启匿评阶段,可以正常评分 --> <!-- 处于开启匿评阶段,可以正常评分 -->
<li class="wping"> <li class="wping">
<%= link_to l(:label_anonymous_comments),homework_attach_path(homework,:cur_page => @cur_page,:cur_type => @cur_type),:remote => true %> <%= link_to l(:label_anonymous_comments),homework_attach_path(homework,:cur_page => @cur_page,:cur_type => @cur_type),:remote => true %>
<% if Time.parse(bid.deadline.to_s).strftime("%Y-%m-%d") < Time.parse(homework.created_at.to_s).strftime("%Y-%m-%d") %> <% if Time.parse(bid.deadline.to_s).strftime("%Y-%m-%d") < Time.parse(homework.created_at.to_s).strftime("%Y-%m-%d") %>
<span class="c_red">&nbsp;&nbsp;迟交!</span> <span class="c_red">&nbsp;&nbsp;迟交!</span>
<% end %> <% end %>
</li> </li>
<% elsif bid.comment_status == 2%> <% elsif bid.comment_status == 2%>
<!-- 处于匿评已关闭阶段,不容许评分 --> <!-- 处于匿评已关闭阶段,不容许评分 -->
<li class="wping" title="关闭匿评后不可继续评分"> <li class="wping" title="关闭匿评后不可继续评分">
<a style="background:#8e8e8e;"> <a style="background:#8e8e8e;">
<%= l(:label_anonymous_comments) %> <%= l(:label_anonymous_comments) %>
</a> </a>
<% if Time.parse(bid.deadline.to_s).strftime("%Y-%m-%d") < Time.parse(homework.created_at.to_s).strftime("%Y-%m-%d") %> <% if Time.parse(bid.deadline.to_s).strftime("%Y-%m-%d") < Time.parse(homework.created_at.to_s).strftime("%Y-%m-%d") %>
<span class="c_red">&nbsp;&nbsp;迟交!</span> <span class="c_red">&nbsp;&nbsp;迟交!</span>
<% end %> <% end %>
</li> </li>
<% end %> <% end %>
<% else %> <% else %>
<!-- 学生众评列表,显示为点赞 --> <!-- 学生众评列表,显示为点赞 -->
<li class="wzan" id="homeworl_praise_li_<%= homework.id%>"> <li class="wzan" id="homeworl_praise_li_<%= homework.id%>">
<%= render :partial => "homework_attach/homework_praise", locals: {:homework => homework} %> <%= render :partial => "homework_attach/homework_praise", locals: {:homework => homework} %>
</li> </li>
<% end %> <% end %>
<% end %> <% end %>

@ -6,6 +6,7 @@
per_page: number of items to fetch per page per_page: number of items to fetch per page
remote: data-remote remote: data-remote
-%> -%>
<li>
<%= link_to_unless current_page.first?, l('views.pagination.first').html_safe, url, :remote => remote %> <%= link_to_unless current_page.first?, l('views.pagination.first').html_safe, url, :remote => remote, :class => 'next c_blue' %>
</li>

@ -5,6 +5,6 @@
per_page: number of items to fetch per page per_page: number of items to fetch per page
remote: data-remote remote: data-remote
-%> -%>
<span class="spacer"> <li>
<%= raw(t 'views.pagination.truncate') %> <%= link_to raw(t 'views.pagination.truncate'),:class=>'c_blue' %>
</span> </li>

@ -6,6 +6,6 @@
per_page: number of items to fetch per page per_page: number of items to fetch per page
remote: data-remote remote: data-remote
-%> -%>
<li>
<%= link_to_unless current_page.last?, t('views.pagination.next').html_safe, url, :rel => 'next', :remote => remote %> <%= link_to_unless current_page.last?, t('views.pagination.next').html_safe, url, :rel => 'next', :remote => remote, :class => "next c_blue" %>
</li>

@ -8,6 +8,6 @@
remote: data-remote remote: data-remote
<%= link_to_unless page.current?, page, url, {:remote => remote, :rel => page.next? ? 'next' : page.prev? ? 'prev' : nil} <%= link_to_unless page.current?, page, url, {:remote => remote, :rel => page.next? ? 'next' : page.prev? ? 'prev' : nil}
-%> -%>
<li class='<%= page.current? ? "wlist_select" : "" %>'>
<%= link_to page, url, page.current? ? {:remote => remote,:class => 'current-page', :rel => page.next? ? 'next' : page.prev? ? 'prev' : nil} : {:remote => remote, :rel => page.next? ? 'next' : page.prev? ? 'prev' : nil} %> <%= link_to page, url, page.current? ? {:remote => remote,:class => 'current-page c_white', :rel => page.next? ? 'next' : page.prev? ? 'prev' : nil} : {:remote => remote,:class => 'page c_blue', :rel => page.next? ? 'next' : page.prev? ? 'prev' : nil} %>
</li>

@ -7,8 +7,8 @@
paginator: the paginator that renders the pagination tags inside paginator: the paginator that renders the pagination tags inside
-%> -%>
<%= paginator.render do -%> <%= paginator.render do -%>
<div id="paginator" class="pagination"> <ul id="paginator" class="wlist">
<%= first_page_tag unless current_page.first? %> <%#= first_page_tag unless current_page.first? %>
<%= prev_page_tag unless current_page.first? %> <%= prev_page_tag unless current_page.first? %>
<% each_page do |page| -%> <% each_page do |page| -%>
<% if page.left_outer? || page.right_outer? || page.inside_window? -%> <% if page.left_outer? || page.right_outer? || page.inside_window? -%>
@ -18,6 +18,6 @@
<% end -%> <% end -%>
<% end -%> <% end -%>
<%= next_page_tag unless current_page.last? %> <%= next_page_tag unless current_page.last? %>
<%= last_page_tag unless current_page.last? %> <!--<%#= last_page_tag unless current_page.last? %>-->
</div> </ul>
<% end -%> <% end -%>

@ -6,6 +6,7 @@
per_page: number of items to fetch per page per_page: number of items to fetch per page
remote: data-remote remote: data-remote
-%> -%>
<li >
<%= link_to_unless current_page.first?, t('views.pagination.previous').html_safe, url, :rel => 'prev', :remote => remote %> <%= link_to_unless current_page.first?, t('views.pagination.previous').html_safe, url, :rel => 'prev', :remote => remote ,:class=>"previous c_blue"%>
</li>

@ -1,6 +1,7 @@
<% course_model %> <% course_model %>
<% teacher_num = teacherCount(@course) %> <% teacher_num = teacherCount(@course) %>
<% student_num = studentCount(@course) %> <% student_num = studentCount(@course) %>
<% course_file_num = visable_attachemnts_incourse(@course).count%>
<% is_teacher = User.current.logged? && (User.current.admin? || User.current.allowed_to?(:as_teacher,@course)) %> <% is_teacher = User.current.logged? && (User.current.admin? || User.current.allowed_to?(:as_teacher,@course)) %>
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
@ -47,7 +48,7 @@
</div> </div>
<div class="search fl"> <div class="search fl">
<%= form_tag({:controller => 'courses', :action => 'search'},:id => "course_search_form", :method => :get, :class => "search_form") do %> <%= form_tag({:controller => 'courses', :action => 'search'},:id => "course_search_form", :method => :get, :class => "search_form") do %>
<%= text_field_tag 'name', params[:name], :placeholder => "课程名称", :class => "search_text fl", :onkeyup => "regexName('#{l(:label_search_conditions_not_null)}');" %> <%= text_field_tag 'name', params[:name], :placeholder => l(:label_course_name), :class => "search_text fl", :onkeyup => "regexName('#{l(:label_search_conditions_not_null)}');" %>
<a href="#" onclick="submitSerch('<%= l(:label_search_conditions_not_null) %>');" class="search_btn fl f14 c_white" > <a href="#" onclick="submitSerch('<%= l(:label_search_conditions_not_null) %>');" class="search_btn fl f14 c_white" >
<%= l(:label_search)%> <%= l(:label_search)%>
</a> </a>
@ -94,7 +95,7 @@
<span>|&nbsp;</span> <span>|&nbsp;</span>
<%= l(:label_account_identity_student)%><%= course_student_link student_num %> <%= l(:label_account_identity_student)%><%= course_student_link student_num %>
<span>|&nbsp;</span> <span>|&nbsp;</span>
<%= l(:project_module_attachments)%><%= link_to @course.attachments.count, course_files_path(@course), :class => 'info_foot_num c_blue' %></div> <%= l(:project_module_attachments)%><%= link_to course_file_num, course_files_path(@course), :class => 'info_foot_num c_blue' %></div>
<div class="cl"></div> <div class="cl"></div>
</div><!--课程信息 end--> </div><!--课程信息 end-->
<div class="info_box"> <div class="info_box">
@ -125,7 +126,9 @@
<%= link_to( "+#{l(:label_course_news_new)}", new_course_news_path(@course), :class => 'subnav_green c_white') if is_teacher %> <%= link_to( "+#{l(:label_course_news_new)}", new_course_news_path(@course), :class => 'subnav_green c_white') if is_teacher %>
</div> </div>
<div class="subNav"> <div class="subNav">
<%= link_to l(:label_course_file), course_files_path(@course), :class => "f14 c_blue02" %><%= link_to "(#{@course.attachments.count})", course_files_path(@course), :class => "subnav_num c_orange" %><%= link_to( "+#{l(:label_upload_files)}", course_files_path(@course), :class => 'subnav_green ml95 c_white') if is_teacher %> <%= link_to l(:label_course_file), course_files_path(@course), :class => "f14 c_blue02" %>
<%= link_to "(#{course_file_num})", course_files_path(@course), :class => "subnav_num c_orange" %>
<%= link_to( "+#{l(:label_upload_files)}", course_files_path(@course), :class => 'subnav_green ml95 c_white') if is_teacher %>
</div> </div>
<div class="subNav"> <div class="subNav">
<%= link_to l(:label_course_board), course_boards_path(@course), :class => "f14 c_blue02" %> <%= link_to l(:label_course_board), course_boards_path(@course), :class => "f14 c_blue02" %>

@ -1,373 +1,373 @@
<div class="content"> <div class="content">
<h4 class="wmail_h4" style="color:#474646; font-size:14px; margin-bottom:5px;" > <h4 class="wmail_h4" style="color:#474646; font-size:14px; margin-bottom:5px;" >
<%= @subject %> <%= @subject %>
</h4> </h4>
<% if @attachments.first || @course_news.first || @bids.first || <% if @attachments.first || @course_news.first || @bids.first ||
@homeworks.first || @course_journal_messages.first|| @course_messages.first %> @homeworks.first || @course_journal_messages.first|| @course_messages.first %>
<div class="wmail_main" style="padding:20px 10px 0px;"> <div class="wmail_main" style="padding:20px 10px 0px;">
<h2 class="wmail_h2" style="color:#15bccf; "><%= l(:label_course_overview)%></h2> <h2 class="wmail_h2" style="color:#15bccf; "><%= l(:label_course_overview)%></h2>
<% unless @course_news.first.nil? %> <% unless @course_news.first.nil? %>
<ul class="wmail_ul" style=" list-style-type:none;clear: both;margin-left:10px; border-bottom:1px dashed #cfcfcf; padding-bottom:15px; width:720px; margin-bottom:15px;"> <ul class="wmail_ul" style=" list-style-type:none;clear: both;margin-left:10px; border-bottom:1px dashed #cfcfcf; padding-bottom:15px; width:720px; margin-bottom:15px;">
<h4 class="wmail_h4" style="color:#474646; font-size:14px; margin-bottom:5px;" > <h4 class="wmail_h4" style="color:#474646; font-size:14px; margin-bottom:5px;" >
<%= l(:label_course_news) %> <%= l(:label_course_news) %>
<span class="wmail_num" style="color:#fe3f0c; margin-left:5px; font-weight:normal;">(<%= @course_news.count %>)</span> <span class="wmail_num" style="color:#fe3f0c; margin-left:5px; font-weight:normal;">(<%= @course_news.count %>)</span>
</h4> </h4>
<% @course_news.each do |course_new|%> <% @course_news.each do |course_new|%>
<li style="clear: both; list-style: none;"> <li style="clear: both; list-style: none;">
<span class="wmail_dis" style="float:left; color:#000000; margin-right:5px;">▪</span> <span class="wmail_dis" style="float:left; color:#000000; margin-right:5px;">▪</span>
<span class="wmail_b" style="color:#1b55a7; font-weight:bold; float:left;">[</span> <span class="wmail_b" style="color:#1b55a7; font-weight:bold; float:left;">[</span>
<%= link_to truncate(course_new.course.name,length: 30,omission: '...'), course_url(course_new.course, :token => @token.value), <%= link_to truncate(course_new.course.name,length: 30,omission: '...'), course_url(course_new.course, :token => @token.value),
:class=> "wmail_column", :class=> "wmail_column",
:style=> " font-weight: bold; display:block; float:left; color:#1b55a7;overflow:hidden; white-space: nowrap; text-overflow:ellipsis;" %> :style=> " font-weight: bold; display:block; float:left; color:#1b55a7;overflow:hidden; white-space: nowrap; text-overflow:ellipsis;" %>
<span class="wmail_b" style="color:#1b55a7; font-weight:bold; float:left;">]</span> <span class="wmail_b" style="color:#1b55a7; font-weight:bold; float:left;">]</span>
<%= link_to course_new.author, user_activities_url(course_new.author,:token => @token.value), :class => "wmail_name", <%= link_to course_new.author, user_activities_url(course_new.author,:token => @token.value), :class => "wmail_name",
:style => "color:#fe5722; float:left;display:block; margin-right:5px; margin-left:5px; overflow:hidden; white-space: nowrap; text-overflow:ellipsis;"%> :style => "color:#fe5722; float:left;display:block; margin-right:5px; margin-left:5px; overflow:hidden; white-space: nowrap; text-overflow:ellipsis;"%>
<span class="wmail_txt" style="float:left; margin-right:5px;color:#6e6e6e;"><%= l(:label_project_notice) %></span> <span class="wmail_txt" style="float:left; margin-right:5px;color:#6e6e6e;"><%= l(:label_project_notice) %></span>
<%= link_to truncate(course_new.title,length: 30,omission: '...'), news_url(course_new,:token => @token.value), <%= link_to truncate(course_new.title,length: 30,omission: '...'), news_url(course_new,:token => @token.value),
:class => 'wmail_info', :class => 'wmail_info',
:style => "color:#5a5a5a; float:left; margin-right:5px; display:block;color:#1b55a7;overflow:hidden; white-space: nowrap; text-overflow:ellipsis;" :style => "color:#5a5a5a; float:left; margin-right:5px; display:block;color:#1b55a7;overflow:hidden; white-space: nowrap; text-overflow:ellipsis;"
%> %>
<span class="wmail_date" style="color:#6e6e6e; float:right;display:block; margin-left:10px;"><%= format_time(course_new.created_on) %></span> <span class="wmail_date" style="color:#6e6e6e; float:right;display:block; margin-left:10px;"><%= format_time(course_new.created_on) %></span>
</li> </li>
<% end %> <% end %>
<div class="cl"></div> <div class="cl"></div>
</ul><!--课程动态 end--> </ul><!--课程动态 end-->
<% end %> <% end %>
<% if !@bids.first.nil? || !@homeworks.first.nil? %> <% if !@bids.first.nil? || !@homeworks.first.nil? %>
<ul class="wmail_ul" style="clear: both;margin-left:10px; border-bottom:1px dashed #cfcfcf; padding-bottom:15px; width:720px; margin-bottom:15px;"> <ul class="wmail_ul" style="clear: both;margin-left:10px; border-bottom:1px dashed #cfcfcf; padding-bottom:15px; width:720px; margin-bottom:15px;">
<h4 class="wmail_h4" style="color:#474646; font-size:14px; margin-bottom:5px;"><%= l(:label_homework_overview) %><span class="wmail_num" style="color:#fe3f0c; margin-left:5px; font-weight:normal;">(<%= @bids.count %>)</span></h4> <h4 class="wmail_h4" style="color:#474646; font-size:14px; margin-bottom:5px;"><%= l(:label_homework_overview) %><span class="wmail_num" style="color:#fe3f0c; margin-left:5px; font-weight:normal;">(<%= @bids.count %>)</span></h4>
<% unless @bids.first.nil?%> <% unless @bids.first.nil?%>
<% @bids.each do |bid| %> <% @bids.each do |bid| %>
<li style="clear: both; list-style: none;"> <li style="clear: both; list-style: none;">
<span class="wmail_dis" style="float:left; color:#000000; margin-right:5px;">▪</span> <span class="wmail_dis" style="float:left; color:#000000; margin-right:5px;">▪</span>
<span class="wmail_b" style="color:#1b55a7; font-weight:bold; float:left;">[</span> <span class="wmail_b" style="color:#1b55a7; font-weight:bold; float:left;">[</span>
<%= link_to truncate(bid.courses.first.name,length: 30,omission: '...'), course_url(bid.courses.first, :token => @token.value), <%= link_to truncate(bid.courses.first.name,length: 30,omission: '...'), course_url(bid.courses.first, :token => @token.value),
:class=> "wmail_column", :class=> "wmail_column",
:style=> " font-weight: bold; display:block; float:left; color:#1b55a7;overflow:hidden; white-space: nowrap; text-overflow:ellipsis;" %> :style=> " font-weight: bold; display:block; float:left; color:#1b55a7;overflow:hidden; white-space: nowrap; text-overflow:ellipsis;" %>
<span class="wmail_b" style="color:#1b55a7; font-weight:bold; float:left;">]</span> <span class="wmail_b" style="color:#1b55a7; font-weight:bold; float:left;">]</span>
<%= link_to bid.author, user_activities_url(bid.author,:token => @token.value), :class => "wmail_name", <%= link_to bid.author, user_activities_url(bid.author,:token => @token.value), :class => "wmail_name",
:style => "color:#fe5722; float:left;display:block; margin-right:5px; margin-left:5px; overflow:hidden; white-space: nowrap; text-overflow:ellipsis;"%> :style => "color:#fe5722; float:left;display:block; margin-right:5px; margin-left:5px; overflow:hidden; white-space: nowrap; text-overflow:ellipsis;"%>
<span class="wmail_txt" style="float:left; margin-right:5px;color:#6e6e6e;"><%= l(:label_course_homework) %></span> <span class="wmail_txt" style="float:left; margin-right:5px;color:#6e6e6e;"><%= l(:label_course_homework) %></span>
<%= link_to truncate(bid.name,length: 30,omission: '...'), course_for_bid_url(:id => bid.id,:token => @token.value), <%= link_to truncate(bid.name,length: 30,omission: '...'), course_for_bid_url(:id => bid.id,:token => @token.value),
:class => 'wmail_info', :class => 'wmail_info',
:style => "color:#5a5a5a; float:left; margin-right:5px; display:block;color:#1b55a7;overflow:hidden; white-space: nowrap; text-overflow:ellipsis;" :style => "color:#5a5a5a; float:left; margin-right:5px; display:block;color:#1b55a7;overflow:hidden; white-space: nowrap; text-overflow:ellipsis;"
%> %>
<span class="wmail_date" style="color:#6e6e6e; float:right;display:block; margin-left:10px;"><%= format_time(bid.created_on) %></span> <span class="wmail_date" style="color:#6e6e6e; float:right;display:block; margin-left:10px;"><%= format_time(bid.created_on) %></span>
</li> </li>
<% end %> <% end %>
<% end %> <% end %>
<% unless @homeworks.first.nil? %> <% unless @homeworks.first.nil? %>
<% @homeworks.each do |homework| %> <% @homeworks.each do |homework| %>
<li style="clear: both; list-style: none;"> <li style="clear: both; list-style: none;">
<span class="wmail_dis" style="float:left; color:#000000; margin-right:5px;">▪</span> <span class="wmail_dis" style="float:left; color:#000000; margin-right:5px;">▪</span>
<span class="wmail_b" style="color:#1b55a7; font-weight:bold; float:left;">[</span> <span class="wmail_b" style="color:#1b55a7; font-weight:bold; float:left;">[</span>
<%= link_to truncate(homework.bid.courses.first.name,length: 30,omission: '...'), course_url(homework.bid.courses.first, :token => @token.value), <%= link_to truncate(homework.bid.courses.first.name,length: 30,omission: '...'), course_url(homework.bid.courses.first, :token => @token.value),
:class=> "wmail_column", :class=> "wmail_column",
:style=> " font-weight: bold; display:block; float:left; color:#1b55a7;overflow:hidden; white-space: nowrap; text-overflow:ellipsis;" %> :style=> " font-weight: bold; display:block; float:left; color:#1b55a7;overflow:hidden; white-space: nowrap; text-overflow:ellipsis;" %>
<span class="wmail_b" style="color:#1b55a7; font-weight:bold; float:left;">]</span> <span class="wmail_b" style="color:#1b55a7; font-weight:bold; float:left;">]</span>
<%= link_to homework.user, user_activities_url(homework.user,:token => @token.value), :class => "wmail_name", <%= link_to homework.user, user_activities_url(homework.user,:token => @token.value), :class => "wmail_name",
:style => "color:#fe5722; float:left;display:block; margin-right:5px; margin-left:5px; overflow:hidden; white-space: nowrap; text-overflow:ellipsis;"%> :style => "color:#fe5722; float:left;display:block; margin-right:5px; margin-left:5px; overflow:hidden; white-space: nowrap; text-overflow:ellipsis;"%>
<span class="wmail_txt" style="float:left; margin-right:5px;color:#6e6e6e;"><%= l(:label_course_submit_homework) %></span> <span class="wmail_txt" style="float:left; margin-right:5px;color:#6e6e6e;"><%= l(:label_course_submit_homework) %></span>
<%= link_to truncate(homework.name,length: 30,omission: '...'), course_for_bid_url(:id => homework.bid.id,:token => @token.value), <%= link_to truncate(homework.name,length: 30,omission: '...'), course_for_bid_url(:id => homework.bid.id,:token => @token.value),
:class => 'wmail_info', :class => 'wmail_info',
:style => "color:#5a5a5a; float:left; margin-right:5px; display:block;color:#1b55a7;overflow:hidden; white-space: nowrap; text-overflow:ellipsis;" :style => "color:#5a5a5a; float:left; margin-right:5px; display:block;color:#1b55a7;overflow:hidden; white-space: nowrap; text-overflow:ellipsis;"
%> %>
<span class="wmail_date" style="color:#6e6e6e; float:right;display:block; margin-left:10px;"><%= format_time(homework.created_on) %></span> <span class="wmail_date" style="color:#6e6e6e; float:right;display:block; margin-left:10px;"><%= format_time(homework.created_at) %></span>
</li> </li>
<% end %> <% end %>
<% end %> <% end %>
<div class="cl"></div> <div class="cl"></div>
</ul><!--作业动态 end--> </ul><!--作业动态 end-->
<% end %> <% end %>
<% unless @course_journal_messages.first.nil? %> <% unless @course_journal_messages.first.nil? %>
<ul class="wmail_ul" style="clear: both;margin-left:10px; border-bottom:1px dashed #cfcfcf; padding-bottom:15px; width:720px; margin-bottom:15px;"> <ul class="wmail_ul" style="clear: both;margin-left:10px; border-bottom:1px dashed #cfcfcf; padding-bottom:15px; width:720px; margin-bottom:15px;">
<h4 class="wmail_h4" style="color:#474646; font-size:14px; margin-bottom:5px;" > <h4 class="wmail_h4" style="color:#474646; font-size:14px; margin-bottom:5px;" >
<%= l(:view_course_journals_for_messages) %> <%= l(:view_course_journals_for_messages) %>
<span class="wmail_num" style="color:#fe3f0c; margin-left:5px; font-weight:normal;">(<%= @course_journal_messages.count %>)</span> <span class="wmail_num" style="color:#fe3f0c; margin-left:5px; font-weight:normal;">(<%= @course_journal_messages.count %>)</span>
</h4> </h4>
<% @course_journal_messages.each do |course_journal_message|%> <% @course_journal_messages.each do |course_journal_message|%>
<li style="clear: both; list-style: none;"> <li style="clear: both; list-style: none;">
<span class="wmail_dis" style="float:left; color:#000000; margin-right:5px;">▪</span> <span class="wmail_dis" style="float:left; color:#000000; margin-right:5px;">▪</span>
<span class="wmail_b" style="color:#1b55a7; font-weight:bold; float:left;">[</span> <span class="wmail_b" style="color:#1b55a7; font-weight:bold; float:left;">[</span>
<%= link_to truncate(course_journal_message.course.name,length: 30,omission: '...'), course_url(course_journal_message.course, :token => @token.value), <%= link_to truncate(course_journal_message.course.name,length: 30,omission: '...'), course_url(course_journal_message.course, :token => @token.value),
:class=> "wmail_column", :class=> "wmail_column",
:style=> " font-weight: bold; display:block; float:left; color:#1b55a7;overflow:hidden; white-space: nowrap; text-overflow:ellipsis;" %> :style=> " font-weight: bold; display:block; float:left; color:#1b55a7;overflow:hidden; white-space: nowrap; text-overflow:ellipsis;" %>
<span class="wmail_b" style="color:#1b55a7; font-weight:bold; float:left;">]</span> <span class="wmail_b" style="color:#1b55a7; font-weight:bold; float:left;">]</span>
<%= link_to course_journal_message.user, user_activities_url(course_journal_message.user,:token => @token.value), :class => "wmail_name", <%= link_to course_journal_message.user, user_activities_url(course_journal_message.user,:token => @token.value), :class => "wmail_name",
:style => "color:#fe5722; float:left;display:block; margin-right:5px; margin-left:5px; overflow:hidden; white-space: nowrap; text-overflow:ellipsis;"%> :style => "color:#fe5722; float:left;display:block; margin-right:5px; margin-left:5px; overflow:hidden; white-space: nowrap; text-overflow:ellipsis;"%>
<span class="wmail_txt" style="float:left; margin-right:5px;color:#6e6e6e;"><%= l(:label_send_course_journals_for_messages) %></span> <span class="wmail_txt" style="float:left; margin-right:5px;color:#6e6e6e;"><%= l(:label_send_course_journals_for_messages) %></span>
<%= link_to truncate(course_journal_message.notes,length: 30,omission: '...'), course_feedback_url(course_journal_message.course,:token => @token.value), <%= link_to truncate(course_journal_message.notes,length: 30,omission: '...'), course_feedback_url(course_journal_message.course,:token => @token.value),
:class => 'wmail_info', :class => 'wmail_info',
:style => "color:#5a5a5a; float:left; margin-right:5px; display:block;color:#1b55a7;overflow:hidden; white-space: nowrap; text-overflow:ellipsis;" :style => "color:#5a5a5a; float:left; margin-right:5px; display:block;color:#1b55a7;overflow:hidden; white-space: nowrap; text-overflow:ellipsis;"
%> %>
<span class="wmail_date" style="color:#6e6e6e; float:right;display:block; margin-left:10px;"><%= format_time(course_journal_message.created_on) %></span> <span class="wmail_date" style="color:#6e6e6e; float:right;display:block; margin-left:10px;"><%= format_time(course_journal_message.created_on) %></span>
</li> </li>
<% end %> <% end %>
<div class="cl"></div> <div class="cl"></div>
</ul><!--课程留言 end--> </ul><!--课程留言 end-->
<% end %> <% end %>
<% unless @course_messages.first.nil? %> <% unless @course_messages.first.nil? %>
<ul class="wmail_ul" style="margin-left:10px; border-bottom:1px dashed #cfcfcf; padding-bottom:15px; width:720px; margin-bottom:15px;"> <ul class="wmail_ul" style="margin-left:10px; border-bottom:1px dashed #cfcfcf; padding-bottom:15px; width:720px; margin-bottom:15px;">
<h4 class="wmail_h4" style="color:#474646; font-size:14px; margin-bottom:5px;" > <h4 class="wmail_h4" style="color:#474646; font-size:14px; margin-bottom:5px;" >
<%= l(:view_borad_course) %> <%= l(:view_borad_course) %>
<span class="wmail_num" style="color:#fe3f0c; margin-left:5px; font-weight:normal;">(<%= @course_journal_messages.count %>)</span> <span class="wmail_num" style="color:#fe3f0c; margin-left:5px; font-weight:normal;">(<%= @course_journal_messages.count %>)</span>
</h4> </h4>
<% @course_messages.each do |course_message|%> <% @course_messages.each do |course_message|%>
<li style="clear: both; list-style: none;"> <li style="clear: both; list-style: none;">
<span class="wmail_dis" style="float:left; color:#000000; margin-right:5px;">▪</span> <span class="wmail_dis" style="float:left; color:#000000; margin-right:5px;">▪</span>
<span class="wmail_b" style="color:#1b55a7; font-weight:bold; float:left;">[</span> <span class="wmail_b" style="color:#1b55a7; font-weight:bold; float:left;">[</span>
<%= link_to truncate(course_message.course.name,length: 30,omission: '...'), course_url(course_message.course.id, :token => @token.value), <%= link_to truncate(course_message.course.name,length: 30,omission: '...'), course_url(course_message.course.id, :token => @token.value),
:class=> "wmail_column", :class=> "wmail_column",
:style=> " font-weight: bold; display:block; float:left; color:#1b55a7;overflow:hidden; white-space: nowrap; text-overflow:ellipsis;" %> :style=> " font-weight: bold; display:block; float:left; color:#1b55a7;overflow:hidden; white-space: nowrap; text-overflow:ellipsis;" %>
<span class="wmail_b" style="color:#1b55a7; font-weight:bold; float:left;">]</span> <span class="wmail_b" style="color:#1b55a7; font-weight:bold; float:left;">]</span>
<%= link_to course_message.author, user_activities_url(course_message.author,:token => @token.value), :class => "wmail_name", <%= link_to course_message.author, user_activities_url(course_message.author,:token => @token.value), :class => "wmail_name",
:style => "color:#fe5722; float:left;display:block; margin-right:5px; margin-left:5px; overflow:hidden; white-space: nowrap; text-overflow:ellipsis;"%> :style => "color:#fe5722; float:left;display:block; margin-right:5px; margin-left:5px; overflow:hidden; white-space: nowrap; text-overflow:ellipsis;"%>
<span class="wmail_txt" style="float:left; margin-right:5px;color:#6e6e6e;"><%= l(:label_send_course_messages) %></span> <span class="wmail_txt" style="float:left; margin-right:5px;color:#6e6e6e;"><%= l(:label_send_course_messages) %></span>
<%= link_to truncate(course_message.subject,length: 30,omission: '...'),board_message_url(course_message, :board_id => course_message.board_id,:token => @token.value), <%= link_to truncate(course_message.subject,length: 30,omission: '...'),board_message_url(course_message, :board_id => course_message.board_id,:token => @token.value),
:class => 'wmail_info', :class => 'wmail_info',
:style => "color:#5a5a5a; float:left; margin-right:5px; display:block;color:#1b55a7;overflow:hidden; white-space: nowrap; text-overflow:ellipsis;" :style => "color:#5a5a5a; float:left; margin-right:5px; display:block;color:#1b55a7;overflow:hidden; white-space: nowrap; text-overflow:ellipsis;"
%> %>
<span class="wmail_date" style="color:#6e6e6e; float:right;display:block; margin-left:10px;"><%= format_time(course_message.created_on) %></span> <span class="wmail_date" style="color:#6e6e6e; float:right;display:block; margin-left:10px;"><%= format_time(course_message.created_on) %></span>
</li> </li>
<% end %> <% end %>
<div class="cl"></div> <div class="cl"></div>
</ul><!--课程讨论 end--> </ul><!--课程讨论 end-->
<% end %> <% end %>
<% unless @attachments.first.nil? %> <% unless @attachments.first.nil? %>
<ul class="wmail_ul" style="margin-left:10px; border-bottom:1px dashed #cfcfcf; padding-bottom:15px; width:720px; margin-bottom:15px;"> <ul class="wmail_ul" style="margin-left:10px; border-bottom:1px dashed #cfcfcf; padding-bottom:15px; width:720px; margin-bottom:15px;">
<h4 class="wmail_h4" style="color:#474646; font-size:14px; margin-bottom:5px;" > <h4 class="wmail_h4" style="color:#474646; font-size:14px; margin-bottom:5px;" >
<%= l(:label_course_attendingcontestwork_download) %> <%= l(:label_course_attendingcontestwork_download) %>
<span class="wmail_num" style="color:#fe3f0c; margin-left:5px; font-weight:normal;">(<%= @attachments.count %>)</span> <span class="wmail_num" style="color:#fe3f0c; margin-left:5px; font-weight:normal;">(<%= @attachments.count %>)</span>
</h4> </h4>
<% @attachments.each do |attachment|%> <% @attachments.each do |attachment|%>
<li style="clear: both; list-style: none;"> <li style="clear: both; list-style: none;">
<span class="wmail_dis" style="float:left; color:#000000; margin-right:5px;">▪</span> <span class="wmail_dis" style="float:left; color:#000000; margin-right:5px;">▪</span>
<span class="wmail_b" style="color:#1b55a7; font-weight:bold; float:left;">[</span> <span class="wmail_b" style="color:#1b55a7; font-weight:bold; float:left;">[</span>
<%= link_to truncate(attachment.course.name,length: 30,omission: '...'), course_url(attachment.course, :token => @token.value), <%= link_to truncate(attachment.course.name,length: 30,omission: '...'), course_url(attachment.course, :token => @token.value),
:class=> "wmail_column", :class=> "wmail_column",
:style=> " font-weight: bold; display:block; float:left; color:#1b55a7;overflow:hidden; white-space: nowrap; text-overflow:ellipsis;" %> :style=> " font-weight: bold; display:block; float:left; color:#1b55a7;overflow:hidden; white-space: nowrap; text-overflow:ellipsis;" %>
<span class="wmail_b" style="color:#1b55a7; font-weight:bold; float:left;">]</span> <span class="wmail_b" style="color:#1b55a7; font-weight:bold; float:left;">]</span>
<%= link_to attachment.author, user_activities_url(attachment.author,:token => @token.value), :class => "wmail_name", <%= link_to attachment.author, user_activities_url(attachment.author,:token => @token.value), :class => "wmail_name",
:style => "color:#fe5722; float:left;display:block; margin-right:5px; margin-left:5px; overflow:hidden; white-space: nowrap; text-overflow:ellipsis;"%> :style => "color:#fe5722; float:left;display:block; margin-right:5px; margin-left:5px; overflow:hidden; white-space: nowrap; text-overflow:ellipsis;"%>
<span class="wmail_txt" style="float:left; margin-right:5px;color:#6e6e6e;"><%= l(:label_course_file_upload) %></span> <span class="wmail_txt" style="float:left; margin-right:5px;color:#6e6e6e;"><%= l(:label_course_file_upload) %></span>
<%= link_to truncate(attachment.filename,length: 30,omission: '...'),course_files_url(attachment.course,:token => @token.value), <%= link_to truncate(attachment.filename,length: 30,omission: '...'),course_files_url(attachment.course,:token => @token.value),
:class => 'wmail_info', :class => 'wmail_info',
:style => "color:#5a5a5a; float:left; margin-right:5px; display:block;color:#1b55a7;overflow:hidden; white-space: nowrap; text-overflow:ellipsis;" :style => "color:#5a5a5a; float:left; margin-right:5px; display:block;color:#1b55a7;overflow:hidden; white-space: nowrap; text-overflow:ellipsis;"
%> %>
<span class="wmail_date" style="color:#6e6e6e; float:right;display:block; margin-left:10px;"><%= format_time(attachment.created_on) %></span> <span class="wmail_date" style="color:#6e6e6e; float:right;display:block; margin-left:10px;"><%= format_time(attachment.created_on) %></span>
</li> </li>
<% end %> <% end %>
<div class="cl"></div> <div class="cl"></div>
</ul><!--课件下载 end--> </ul><!--课件下载 end-->
<% end %> <% end %>
</div><!--课程动态 end--> </div><!--课程动态 end-->
<% end %> <% end %>
<% if @issues.first || @project_messages.first %> <% if @issues.first || @project_messages.first %>
<div class="wmail_main" style="padding:20px 10px 0px;"> <div class="wmail_main" style="padding:20px 10px 0px;">
<h2 class="wmail_h2" style="color:#15bccf; "><%= l(:label_project_overview_new)%></h2> <h2 class="wmail_h2" style="color:#15bccf; "><%= l(:label_project_overview_new)%></h2>
<% unless @issues.first.nil? %> <% unless @issues.first.nil? %>
<ul class="wmail_ul" style="margin-left:10px; border-bottom:1px dashed #cfcfcf; padding-bottom:15px; width:720px; margin-bottom:15px;"> <ul class="wmail_ul" style="margin-left:10px; border-bottom:1px dashed #cfcfcf; padding-bottom:15px; width:720px; margin-bottom:15px;">
<h4 class="wmail_h4" style="color:#474646; font-size:14px; margin-bottom:5px;" > <h4 class="wmail_h4" style="color:#474646; font-size:14px; margin-bottom:5px;" >
<%= l(:label_issue_tracking) %> <%= l(:label_issue_tracking) %>
<span class="wmail_num" style="color:#fe3f0c; margin-left:5px; font-weight:normal;">(<%= @issues.count %>)</span> <span class="wmail_num" style="color:#fe3f0c; margin-left:5px; font-weight:normal;">(<%= @issues.count %>)</span>
</h4> </h4>
<% @issues.each do |issue|%> <% @issues.each do |issue|%>
<li style="clear: both; list-style: none;"> <li style="clear: both; list-style: none;">
<span class="wmail_dis" style="float:left; color:#000000; margin-right:5px;">▪</span> <span class="wmail_dis" style="float:left; color:#000000; margin-right:5px;">▪</span>
<span class="wmail_b" style="color:#1b55a7; font-weight:bold; float:left;">[</span> <span class="wmail_b" style="color:#1b55a7; font-weight:bold; float:left;">[</span>
<%= link_to truncate(issue.project.name,length: 30,omission: '...'), project_url(issue.project, :token => @token.value), <%= link_to truncate(issue.project.name,length: 30,omission: '...'), project_url(issue.project, :token => @token.value),
:class=> "wmail_column", :class=> "wmail_column",
:style=> " font-weight: bold; display:block; float:left; color:#1b55a7;overflow:hidden; white-space: nowrap; text-overflow:ellipsis;" %> :style=> " font-weight: bold; display:block; float:left; color:#1b55a7;overflow:hidden; white-space: nowrap; text-overflow:ellipsis;" %>
<span class="wmail_b" style="color:#1b55a7; font-weight:bold; float:left;">]</span> <span class="wmail_b" style="color:#1b55a7; font-weight:bold; float:left;">]</span>
<%= link_to issue.author, user_activities_url(issue.author,:token => @token.value), :class => "wmail_name", <%= link_to issue.author, user_activities_url(issue.author,:token => @token.value), :class => "wmail_name",
:style => "color:#fe5722; float:left;display:block; margin-right:5px; margin-left:5px; overflow:hidden; white-space: nowrap; text-overflow:ellipsis;"%> :style => "color:#fe5722; float:left;display:block; margin-right:5px; margin-left:5px; overflow:hidden; white-space: nowrap; text-overflow:ellipsis;"%>
<span class="wmail_txt" style="float:left; margin-right:5px;color:#6e6e6e;"><%= l(:label_project_issue) %></span> <span class="wmail_txt" style="float:left; margin-right:5px;color:#6e6e6e;"><%= l(:label_project_issue) %></span>
<%= link_to truncate(issue.subject,length: 30,omission: '...'),issue_url(issue, :token => @token.value), <%= link_to truncate(issue.subject,length: 30,omission: '...'),issue_url(issue, :token => @token.value),
:class => 'wmail_info', :class => 'wmail_info',
:style => "color:#5a5a5a; float:left; margin-right:5px; display:block;color:#1b55a7;overflow:hidden; white-space: nowrap; text-overflow:ellipsis;" :style => "color:#5a5a5a; float:left; margin-right:5px; display:block;color:#1b55a7;overflow:hidden; white-space: nowrap; text-overflow:ellipsis;"
%> %>
<span class="wmail_date" style="color:#6e6e6e; float:right;display:block; margin-left:10px;"><%= format_time(issue.created_on) %></span> <span class="wmail_date" style="color:#6e6e6e; float:right;display:block; margin-left:10px;"><%= format_time(issue.created_on) %></span>
</li> </li>
<% end %> <% end %>
<div class="cl"></div> <div class="cl"></div>
</ul><!--问题跟踪 end--> </ul><!--问题跟踪 end-->
<% end %> <% end %>
<% unless @project_messages.first.nil? %> <% unless @project_messages.first.nil? %>
<ul class="wmail_ul" style="margin-left:10px; border-bottom:1px dashed #cfcfcf; padding-bottom:15px; width:720px; margin-bottom:15px;"> <ul class="wmail_ul" style="margin-left:10px; border-bottom:1px dashed #cfcfcf; padding-bottom:15px; width:720px; margin-bottom:15px;">
<h4 class="wmail_h4" style="color:#474646; font-size:14px; margin-bottom:5px;" > <h4 class="wmail_h4" style="color:#474646; font-size:14px; margin-bottom:5px;" >
<%= l(:project_moule_boards_show) %> <%= l(:project_moule_boards_show) %>
<span class="wmail_num" style="color:#fe3f0c; margin-left:5px; font-weight:normal;">(<%= @project_messages.count %>)</span> <span class="wmail_num" style="color:#fe3f0c; margin-left:5px; font-weight:normal;">(<%= @project_messages.count %>)</span>
</h4> </h4>
<% @project_messages.each do |project_message|%> <% @project_messages.each do |project_message|%>
<li style="clear: both; list-style: none;"> <li style="clear: both; list-style: none;">
<span class="wmail_dis" style="float:left; color:#000000; margin-right:5px;">▪</span> <span class="wmail_dis" style="float:left; color:#000000; margin-right:5px;">▪</span>
<span class="wmail_b" style="color:#1b55a7; font-weight:bold; float:left;">[</span> <span class="wmail_b" style="color:#1b55a7; font-weight:bold; float:left;">[</span>
<%= link_to truncate(project_message.project.name,length: 30,omission: '...'), project_url(project_message.project, :token => @token.value), <%= link_to truncate(project_message.project.name,length: 30,omission: '...'), project_url(project_message.project, :token => @token.value),
:class=> "wmail_column", :class=> "wmail_column",
:style=> " font-weight: bold; display:block; float:left; color:#1b55a7;overflow:hidden; white-space: nowrap; text-overflow:ellipsis;" %> :style=> " font-weight: bold; display:block; float:left; color:#1b55a7;overflow:hidden; white-space: nowrap; text-overflow:ellipsis;" %>
<span class="wmail_b" style="color:#1b55a7; font-weight:bold; float:left;">]</span> <span class="wmail_b" style="color:#1b55a7; font-weight:bold; float:left;">]</span>
<%= link_to project_message.author, user_activities_url(project_message.author,:token => @token.value), :class => "wmail_name", <%= link_to project_message.author, user_activities_url(project_message.author,:token => @token.value), :class => "wmail_name",
:style => "color:#fe5722; float:left;display:block; margin-right:5px; margin-left:5px; overflow:hidden; white-space: nowrap; text-overflow:ellipsis;"%> :style => "color:#fe5722; float:left;display:block; margin-right:5px; margin-left:5px; overflow:hidden; white-space: nowrap; text-overflow:ellipsis;"%>
<span class="wmail_txt" style="float:left; margin-right:5px;color:#6e6e6e;"><%= l(:label_send_course_messages) %></span> <span class="wmail_txt" style="float:left; margin-right:5px;color:#6e6e6e;"><%= l(:label_send_course_messages) %></span>
<%= link_to truncate(project_message.subject,length: 30,omission: '...'),board_message_url(project_message, :board_id => project_message.board_id,:token => @token.value), <%= link_to truncate(project_message.subject,length: 30,omission: '...'),board_message_url(project_message, :board_id => project_message.board_id,:token => @token.value),
:class => 'wmail_info', :class => 'wmail_info',
:style => "color:#5a5a5a; float:left; margin-right:5px; display:block;color:#1b55a7;overflow:hidden; white-space: nowrap; text-overflow:ellipsis;" :style => "color:#5a5a5a; float:left; margin-right:5px; display:block;color:#1b55a7;overflow:hidden; white-space: nowrap; text-overflow:ellipsis;"
%> %>
<span class="wmail_date" style="color:#6e6e6e; float:right;display:block; margin-left:10px;"><%= format_time(project_message.created_on) %></span> <span class="wmail_date" style="color:#6e6e6e; float:right;display:block; margin-left:10px;"><%= format_time(project_message.created_on) %></span>
</li> </li>
<% end %> <% end %>
<div class="cl"></div> <div class="cl"></div>
</ul><!--项目论坛 end--> </ul><!--项目论坛 end-->
<% end %> <% end %>
</div><!--项目动态 end--> </div><!--项目动态 end-->
<% end %> <% end %>
<% unless @user_journal_messages.first.nil? %> <% unless @user_journal_messages.first.nil? %>
<div class="wmail_main" style="padding:20px 10px 0px;"> <div class="wmail_main" style="padding:20px 10px 0px;">
<h2 class="wmail_h2" style="color:#15bccf; "><%= l(:label_activities) %></h2> <h2 class="wmail_h2" style="color:#15bccf; "><%= l(:label_activities) %></h2>
<ul class="wmail_ul" style="margin-left:10px; border-bottom:1px dashed #cfcfcf; padding-bottom:15px; width:720px; margin-bottom:15px;"> <ul class="wmail_ul" style="margin-left:10px; border-bottom:1px dashed #cfcfcf; padding-bottom:15px; width:720px; margin-bottom:15px;">
<h4 class="wmail_h4" style="color:#474646; font-size:14px; margin-bottom:5px;" > <h4 class="wmail_h4" style="color:#474646; font-size:14px; margin-bottom:5px;" >
<%= l(:label_user_message) %> <%= l(:label_user_message) %>
<span class="wmail_num" style="color:#fe3f0c; margin-left:5px; font-weight:normal;">(<%= @user_journal_messages.count %>)</span> <span class="wmail_num" style="color:#fe3f0c; margin-left:5px; font-weight:normal;">(<%= @user_journal_messages.count %>)</span>
</h4> </h4>
<% @user_journal_messages.each do |user_journal_message|%> <% @user_journal_messages.each do |user_journal_message|%>
<li style="clear: both; list-style: none;"> <li style="clear: both; list-style: none;">
<span class="wmail_dis" style="float:left; color:#000000; margin-right:5px;">▪</span> <span class="wmail_dis" style="float:left; color:#000000; margin-right:5px;">▪</span>
<%= link_to user_journal_message.user, user_activities_url(user_journal_message.user,:token => @token.value), <%= link_to user_journal_message.user, user_activities_url(user_journal_message.user,:token => @token.value),
:class => "wmail_name", :class => "wmail_name",
:style => "color:#fe5722; float:left;display:block; margin-right:5px; margin-left:5px; overflow:hidden; white-space: nowrap; text-overflow:ellipsis;" %> :style => "color:#fe5722; float:left;display:block; margin-right:5px; margin-left:5px; overflow:hidden; white-space: nowrap; text-overflow:ellipsis;" %>
<span class="wmail_txt" style="float:left; margin-right:5px;color:#6e6e6e;"><%= l(:label_show_your_message) %></span> <span class="wmail_txt" style="float:left; margin-right:5px;color:#6e6e6e;"><%= l(:label_show_your_message) %></span>
<%= link_to truncate(user_journal_message.notes,length: 30,omission: '...'),feedback_url(@user,:token => @token.value), <%= link_to truncate(user_journal_message.notes,length: 30,omission: '...'),feedback_url(@user,:token => @token.value),
:class => 'wmail_info', :class => 'wmail_info',
:style => "color:#5a5a5a; float:left; margin-right:5px; display:block;color:#1b55a7;overflow:hidden; white-space: nowrap; text-overflow:ellipsis;" :style => "color:#5a5a5a; float:left; margin-right:5px; display:block;color:#1b55a7;overflow:hidden; white-space: nowrap; text-overflow:ellipsis;"
%> %>
<span class="wmail_date" style="color:#6e6e6e; float:right;display:block; margin-left:10px;"><%= format_time(user_journal_message.created_on) %></span></li> <span class="wmail_date" style="color:#6e6e6e; float:right;display:block; margin-left:10px;"><%= format_time(user_journal_message.created_on) %></span></li>
<% end %> <% end %>
<div class="cl"></div> <div class="cl"></div>
</ul><!--课程动态 end--> </ul><!--课程动态 end-->
</div><!--个人动态 end--> </div><!--个人动态 end-->
<% end %> <% end %>
<% if @forums.first || @memos.first %> <% if @forums.first || @memos.first %>
<div class="wmail_main" style="padding:20px 10px 0px;"> <div class="wmail_main" style="padding:20px 10px 0px;">
<h2 class="wmail_h2" style="color:#15bccf; "><%= l(:lable_bar_active) %></h2> <h2 class="wmail_h2" style="color:#15bccf; "><%= l(:lable_bar_active) %></h2>
<% unless @forums.first.nil? %> <% unless @forums.first.nil? %>
<ul class="wmail_ul" style="margin-left:10px; border-bottom:1px dashed #cfcfcf; padding-bottom:15px; width:720px; margin-bottom:15px;"> <ul class="wmail_ul" style="margin-left:10px; border-bottom:1px dashed #cfcfcf; padding-bottom:15px; width:720px; margin-bottom:15px;">
<h4 class="wmail_h4" style="color:#474646; font-size:14px; margin-bottom:5px;" > <h4 class="wmail_h4" style="color:#474646; font-size:14px; margin-bottom:5px;" >
<%= l(:label_user_forum) %> <%= l(:label_user_forum) %>
<span class="wmail_num" style="color:#fe3f0c; margin-left:5px; font-weight:normal;">(<%= @forums.count %>)</span> <span class="wmail_num" style="color:#fe3f0c; margin-left:5px; font-weight:normal;">(<%= @forums.count %>)</span>
</h4> </h4>
<% @forums.each do |forum|%> <% @forums.each do |forum|%>
<li style="clear: both; list-style: none;"> <li style="clear: both; list-style: none;">
<span class="wmail_dis" style="float:left; color:#000000; margin-right:5px;">▪</span> <span class="wmail_dis" style="float:left; color:#000000; margin-right:5px;">▪</span>
<%= link_to forum.creator, user_activities_url(forum.creator,:token => @token.value), <%= link_to forum.creator, user_activities_url(forum.creator,:token => @token.value),
:class => "wmail_name", :class => "wmail_name",
:style => "color:#fe5722; float:left;display:block; margin-right:5px; margin-left:5px; overflow:hidden; white-space: nowrap; text-overflow:ellipsis;" %> :style => "color:#fe5722; float:left;display:block; margin-right:5px; margin-left:5px; overflow:hidden; white-space: nowrap; text-overflow:ellipsis;" %>
<span class="wmail_txt" style="float:left; margin-right:5px;color:#6e6e6e;"><%= l(:label_forum_new) %></span> <span class="wmail_txt" style="float:left; margin-right:5px;color:#6e6e6e;"><%= l(:label_forum_new) %></span>
<%= link_to truncate(forum.name,length: 30,omission: '...'),forum_url(forum,:token => @token.value), <%= link_to truncate(forum.name,length: 30,omission: '...'),forum_url(forum,:token => @token.value),
:class => 'wmail_info', :class => 'wmail_info',
:style => "color:#5a5a5a; float:left; margin-right:5px; display:block;color:#1b55a7;overflow:hidden; white-space: nowrap; text-overflow:ellipsis;" :style => "color:#5a5a5a; float:left; margin-right:5px; display:block;color:#1b55a7;overflow:hidden; white-space: nowrap; text-overflow:ellipsis;"
%> %>
<span class="wmail_date" style="color:#6e6e6e; float:right;display:block; margin-left:10px;"><%= format_time(forum.created_at) %></span></li> <span class="wmail_date" style="color:#6e6e6e; float:right;display:block; margin-left:10px;"><%= format_time(forum.created_at) %></span></li>
<% end %> <% end %>
<div class="cl"></div> <div class="cl"></div>
</ul><!-- 新建贴吧 end--> </ul><!-- 新建贴吧 end-->
<% end %> <% end %>
<% unless @memos.first.nil? %> <% unless @memos.first.nil? %>
<ul class="wmail_ul" style="margin-left:10px; border-bottom:1px dashed #cfcfcf; padding-bottom:15px; width:720px; margin-bottom:15px;"> <ul class="wmail_ul" style="margin-left:10px; border-bottom:1px dashed #cfcfcf; padding-bottom:15px; width:720px; margin-bottom:15px;">
<h4 class="wmail_h4" style="color:#474646; font-size:14px; margin-bottom:5px;" > <h4 class="wmail_h4" style="color:#474646; font-size:14px; margin-bottom:5px;" >
<%= l(:label_user_message_forum) %> <%= l(:label_user_message_forum) %>
<span class="wmail_num" style="color:#fe3f0c; margin-left:5px; font-weight:normal;">(<%= @memos.count %>)</span> <span class="wmail_num" style="color:#fe3f0c; margin-left:5px; font-weight:normal;">(<%= @memos.count %>)</span>
</h4> </h4>
<% @memos.each do |memo|%> <% @memos.each do |memo|%>
<li style="clear: both; list-style: none;"> <li style="clear: both; list-style: none;">
<span class="wmail_dis" style="float:left; color:#000000; margin-right:5px;">▪</span> <span class="wmail_dis" style="float:left; color:#000000; margin-right:5px;">▪</span>
<%= link_to memo.author, user_activities_url(memo.author,:token => @token.value), <%= link_to memo.author, user_activities_url(memo.author,:token => @token.value),
:class => "wmail_name", :class => "wmail_name",
:style => "color:#fe5722; float:left;display:block; margin-right:5px; margin-left:5px; overflow:hidden; white-space: nowrap; text-overflow:ellipsis;" %> :style => "color:#fe5722; float:left;display:block; margin-right:5px; margin-left:5px; overflow:hidden; white-space: nowrap; text-overflow:ellipsis;" %>
<span class="wmail_txt" style="float:left; margin-right:5px;color:#6e6e6e;"><%= memo.parent_id.nil? ? l(:label_memo_new_from_forum) : l(:label_reply) %></span> <span class="wmail_txt" style="float:left; margin-right:5px;color:#6e6e6e;"><%= memo.parent_id.nil? ? l(:label_memo_new_from_forum) : l(:label_reply) %></span>
<%= link_to truncate(memo.subject,length: 30,omission: '...'),forum_memo_url(memo.forum, (memo.parent_id.nil? ? memo : memo.parent_id)), <%= link_to truncate(memo.subject,length: 30,omission: '...'),forum_memo_url(memo.forum, (memo.parent_id.nil? ? memo : memo.parent_id)),
:class => 'wmail_info', :class => 'wmail_info',
:style => "color:#5a5a5a; float:left; margin-right:5px; display:block;color:#1b55a7;overflow:hidden; white-space: nowrap; text-overflow:ellipsis;" :style => "color:#5a5a5a; float:left; margin-right:5px; display:block;color:#1b55a7;overflow:hidden; white-space: nowrap; text-overflow:ellipsis;"
%> %>
<span class="wmail_date" style="color:#6e6e6e; float:right;display:block; margin-left:10px;"><%= format_time(memo.created_at) %></span></li> <span class="wmail_date" style="color:#6e6e6e; float:right;display:block; margin-left:10px;"><%= format_time(memo.created_at) %></span></li>
<% end %> <% end %>
<div class="cl"></div> <div class="cl"></div>
</ul><!-- 新建贴吧 end--> </ul><!-- 新建贴吧 end-->
<% end %> <% end %>
</div><!--贴吧动态 end--> </div><!--贴吧动态 end-->
<% end %> <% end %>
<div class="wmail_foot" style="margin-top:20px;color:#2775d2; margin-left:10px;"> <div class="wmail_foot" style="margin-top:20px;color:#2775d2; margin-left:10px;">
<%= link_to l(:mail_footer), @user_url, :style => "margin-top:20px;color:#2775d2; margin-left:10px;" %> <%= link_to l(:mail_footer), @user_url, :style => "margin-top:20px;color:#2775d2; margin-left:10px;" %>
</div> </div>
</div> </div>

@ -1,3 +1,34 @@
<script type="text/javascript">
// var flag = false;
// jQuery(document).ready(function($) {
// transpotUrl('#content');
// });
// function submit_message_replay()
// {
// regexContent();//onkeyup传给kindeditor用不上了所以只能放在这里
// if(flag)
// {
// message_content_editor.sync();//提交内容之前要sync不然服务器端取不到值
// $("#message_form").submit();
// }
// }
// function regexContent()
// {
// var content = message_content_editor.html();//$.trim($("#message_content").val());
// if(content.length ==0)
// {
// $("#message_content_span").text("<%= l(:label_reply_empty) %>");
// $("#message_content_span").css('color','#ff0000');
// flag = false;
// }
// else
// {
// $("#message_content_span").text("<%= l(:label_field_correct) %>");
// $("#message_content_span").css('color','#008000');
// flag = true;
// }
// }
</script>
<div class="project_r_h"> <div class="project_r_h">
<h2 class="project_h2"><%= l(:label_board) %></h2> <h2 class="project_h2"><%= l(:label_board) %></h2>
</div> </div>
@ -24,7 +55,7 @@
:class => 'talk_edit fr' :class => 'talk_edit fr'
) if @message.course_destroyable_by?(User.current) %> ) if @message.course_destroyable_by?(User.current) %>
<div class="cl"></div> <div class="cl"></div>
<div class="talk_info mb10"><%= textilizable(@topic, :content) %></div> <div class="talk_info mb10"><%= textAreailizable(@topic, :content) %></div>
<div class="talk_info mb10"><%= link_to_attachments_course @topic, :author => false %></div> <div class="talk_info mb10"><%= link_to_attachments_course @topic, :author => false %></div>
<!-- <a href="#" class=" link_file ml60">附件爱覅俄方if.zip(27.5kB)</a>--> <!-- <a href="#" class=" link_file ml60">附件爱覅俄方if.zip(27.5kB)</a>-->
<div class="cl"></div> <div class="cl"></div>
@ -52,7 +83,7 @@
<%= link_to_user_header message.author,false,:class => 'c_blue fb fl mb10 ' %> <%= link_to_user_header message.author,false,:class => 'c_blue fb fl mb10 ' %>
<span class="c_grey fr"><%= format_time(message.created_on) %></span> <span class="c_grey fr"><%= format_time(message.created_on) %></span>
<div class="cl"></div> <div class="cl"></div>
<p><%= textilizable message,:content,:attachments => message.attachments %></p> <p><%= textAreailizable message,:content,:attachments => message.attachments %></p>
<%= link_to_attachments_course message, :author => false %> <%= link_to_attachments_course message, :author => false %>
</div> </div>
<div class="ping_disfoot"> <div class="ping_disfoot">
@ -87,7 +118,7 @@
<div id="reply" style="display:none;"> <div id="reply" style="display:none;">
<%= form_for @reply, :as => :reply, :url => {:action => 'reply', :id => @topic}, :html => {:multipart => true, :id => 'message_form'} do |f| %> <%= form_for @reply, :as => :reply, :url => {:action => 'reply', :id => @topic}, :html => {:multipart => true, :id => 'message_form'} do |f| %>
<%= render :partial => 'form_course', :locals => {:f => f, :replying => true} %> <%= render :partial => 'form_course', :locals => {:f => f, :replying => true} %>
<a href="#" onclick="submit_message_replay();"class="blue_btn fl c_white" style="margin-left: 50px;"><%= l(:button_submit)%></a> <%= link_to l(:button_submit),"#",:onclick => 'course_board_submit_message_replay();' ,:class => "blue_btn fl c_white" ,:style=>"margin-left: 50px;"%>
<% end %> <% end %>
<div id="preview" class="wiki"></div> <div id="preview" class="wiki"></div>
</div> </div>
@ -97,32 +128,3 @@
</ul> </ul>
<% html_title @topic.subject %> <% html_title @topic.subject %>
<script type="text/javascript">
var flag = false;
jQuery(document).ready(function($) {
transpotUrl('#content');
});
function submit_message_replay()
{
if(flag)
{
$("#message_form").submit();
}
}
function regexContent()
{
var content = $.trim($("#message_content").val());
if(content.length ==0)
{
$("#message_content_span").text("<%= l(:label_reply_empty) %>");
$("#message_content_span").css('color','#ff0000');
flag = false;
}
else
{
$("#message_content_span").text("<%= l(:label_field_correct) %>");
$("#message_content_span").css('color','#008000');
flag = true;
}
}
</script>

@ -1,3 +1,4 @@
<%= javascript_include_tag "/assets/kindeditor/kindeditor" %>
<%= error_messages_for 'message' %> <%= error_messages_for 'message' %>
<% replying ||= false %> <% replying ||= false %>
<% extra_option = replying ? { readonly: true} : { maxlength: 200 } %> <% extra_option = replying ? { readonly: true} : { maxlength: 200 } %>
@ -28,7 +29,25 @@
<div id="message_quote" class="wiki" style="width: 100%;word-break: break-all;word-wrap: break-word;"></div> <div id="message_quote" class="wiki" style="width: 100%;word-break: break-all;word-wrap: break-word;"></div>
<label class="fl" ><span class="c_red">*</span>&nbsp;<%= l(:field_description) %>&nbsp;&nbsp;</label> <label class="fl" ><span class="c_red">*</span>&nbsp;<%= l(:field_description) %>&nbsp;&nbsp;</label>
<%= text_area :quote,:quote,:style => 'display:none' %> <%= text_area :quote,:quote,:style => 'display:none' %>
<%= f.text_area :content, :class => 'talk_text fl', :id => 'message_content', :onkeyup => "regexContent();", :maxlength => 5000,:placeholder => "最多3000个汉字(或6000个英文字符)" %> <%= hidden_field_tag :asset_id,params[:asset_id],:required => false,:style => 'display:none' %>
<% if replying %>
<%= f.kindeditor :content, :editor_id => 'message_content_editor',
:width => '89%',
:height => 300,
:input_html => { :id => 'message_content',
:class => 'talk_text fl',
:maxlength => 5000 }%>
<% else %>
<%= f.kindeditor :content, :editor_id => 'message_content_editor',
:owner_id => @message.nil? ? 0: @message.id,
:owner_type => OwnerTypeHelper::MESSAGE,
:width => '91%',
:height => 300,
:class => 'talk_text fl',
:input_html => { :id => 'message_content',
:class => 'talk_text fl',
:maxlength => 5000 }%>
<% end %>
<div class="cl"></div> <div class="cl"></div>
<p id="message_content_span" class="ml55"></p> <p id="message_content_span" class="ml55"></p>
</li> </li>

@ -1,12 +1,21 @@
<%= javascript_include_tag "/assets/kindeditor/kindeditor" %>
<li class="ml45"> <li class="ml45">
<label><span class="c_red">*</span>&nbsp;<%= l(:field_title) %>&nbsp;&nbsp;</label> <label><span class="c_red">*</span>&nbsp;<%= l(:field_title) %>&nbsp;&nbsp;</label>
<input type="text" name="news[title]" class="hwork_input" id="news_title" size="60" onkeyup="regexTitle();" maxlength="60" placeholder="60个字符以内" value="<%= is_new ? '' : @news.title %>"> <input type="text" name="news[title]" class="hwork_input" id="news_title" size="60" onkeyup="regexTitle();" maxlength="60" placeholder="60个字符以内" value="<%= is_new ? '' : @news.title %>">
<p id="title_notice_span" class="ml55"></p> <p id="title_notice_span" class="ml55"></p>
</li> </li>
<li class="ml45"> <li class="ml45">
<label class="fl" ><span class="c_red">*</span>&nbsp;<%= l(:field_description) %>&nbsp;&nbsp;</label> <% if is_new %>
<textarea id="news_description" name="news[description]" placeholder="最多3000个汉字(或6000个英文字符)" class="hwork_text fl" onkeyup="regexDescription();" maxlength="6000"><%= is_new ? '' : @news.description %></textarea> <%= hidden_field_tag :asset_id,params[:asset_id],:required => false,:style => 'display:none' %>
<p id="description_notice_span" class="ml55"></p> <label class="fl" ><span class="c_red">*</span>&nbsp;<%= l(:field_description) %>&nbsp;&nbsp;</label>
<%= f.kindeditor :description,:width=>'91%',:editor_id=>'news_description_editor' %>
<p id="description_notice_span" class="ml55"></p>
<% else %>
<label class="fl" ><span class="c_red">*</span>&nbsp;<%= l(:field_description) %>&nbsp;&nbsp;</label>
<%= f.kindeditor :description,:width=>'91%',:editor_id=>'news_description_editor',:owner_id => @news.id,:owner_type => OwnerTypeHelper::NEWS %>
<p id="description_notice_span" class="ml55"></p>
<% end %>
</li> </li>
<div class="cl"></div> <div class="cl"></div>
<li class="ml45"> <li class="ml45">
@ -19,7 +28,7 @@
<%= link_to l(:button_create), "#", :onclick => 'submitNews();', :onmouseover => 'submitFocus(this);', :class => 'blue_btn fl c_white' %> <%= link_to l(:button_create), "#", :onclick => 'submitNews();', :onmouseover => 'submitFocus(this);', :class => 'blue_btn fl c_white' %>
<%= link_to l(:button_cancel), course_news_index_path(@course), :onclick => '$("#add-news").hide()', :class => 'blue_btn grey_btn fl c_white' %> <%= link_to l(:button_cancel), course_news_index_path(@course), :onclick => '$("#add-news").hide()', :class => 'blue_btn grey_btn fl c_white' %>
<% else %> <% else %>
<%= link_to l(:button_save), "#", :onclick => 'submitNews();',:onmouseover => 'this.focus()',:class => 'blue_btn fl c_white' %> <%= link_to l(:button_save), "#", :onclick => "submitNews();",:onmouseover => 'this.focus()',:class => 'blue_btn fl c_white' %>
<%= link_to l(:button_cancel), "#", :onclick => '$("#edit-news").hide(); return false;',:class => 'blue_btn grey_btn fl c_white' %> <%= link_to l(:button_cancel), "#", :onclick => '$("#edit-news").hide(); return false;',:class => 'blue_btn grey_btn fl c_white' %>
<% end %> <% end %>
<div class="cl"></div> <div class="cl"></div>

@ -51,7 +51,7 @@
<%= link_to_user_header(news.author,false,{:class=> 'problem_name c_orange fl'}) if news.respond_to?(:author) %> <%= link_to_user_header(news.author,false,{:class=> 'problem_name c_orange fl'}) if news.respond_to?(:author) %>
<span class="fl"> <%= l(:label_release_news) %></span><%= link_to h(news.title), news_path(news),:class => 'problem_tit fl fb c_dblue' %><br /> <span class="fl"> <%= l(:label_release_news) %></span><%= link_to h(news.title), news_path(news),:class => 'problem_tit fl fb c_dblue' %><br />
<div class="cl mb5"></div> <div class="cl mb5"></div>
<p id="news_description_<%= news.id %>" class="news_description mt5"><%= news.description %><br /> <%= l(:label_create_time) %> <%= format_time(news.created_on) %></p> <p id="news_description_<%= news.id %>" class="news_description mt5"><%= textAreailizable news.description %><br /> <%= l(:label_create_time) %> <%= format_time(news.created_on) %></p>
<div class="news_foot" style="display: none;" onclick="news_show_more_des(<%= news.id %>);" id="news_foot_<%= news.id %>"><%= l(:label_expend_information) %> <span class="g-arr-down"><img src="/images/jiantou.jpg" width="12" height="6" /></span></div> <div class="news_foot" style="display: none;" onclick="news_show_more_des(<%= news.id %>);" id="news_foot_<%= news.id %>"><%= l(:label_expend_information) %> <span class="g-arr-down"><img src="/images/jiantou.jpg" width="12" height="6" /></span></div>
</div> </div>
<div class="cl"></div> <div class="cl"></div>

@ -44,6 +44,7 @@
function submitNews() function submitNews()
{ {
news_description_editor.sync();
if(regexTitle() && regexDescription()) if(regexTitle() && regexDescription())
{ {
$("#news-form").submit(); $("#news-form").submit();
@ -51,6 +52,7 @@
} }
function submitComment() function submitComment()
{ {
comment_editor.sync();
$("#add_comment_form").submit(); $("#add_comment_form").submit();
} }
function clearMessage() function clearMessage()
@ -58,7 +60,7 @@
$("#comment_comments").val(""); $("#comment_comments").val("");
} }
</script> </script>
<%= javascript_include_tag "/assets/kindeditor/kindeditor" %>
<div class="project_r_h"> <div class="project_r_h">
<h2 class="project_h2"><%= l(:label_course_news) %></h2> <h2 class="project_h2"><%= l(:label_course_news) %></h2>
</div> </div>
@ -84,7 +86,7 @@
:onclick => '$("#edit-news").show(); return false;') if User.current.allowed_to?(:manage_news, @course) %> :onclick => '$("#edit-news").show(); return false;') if User.current.allowed_to?(:manage_news, @course) %>
<%= delete_link(news_path(@news),:class => 'talk_edit fr') if User.current.allowed_to?(:manage_news, @course) %> <%= delete_link(news_path(@news),:class => 'talk_edit fr') if User.current.allowed_to?(:manage_news, @course) %>
<div class="cl"></div> <div class="cl"></div>
<div class="mb5"><%= textilizable(@news, :description) %><br /> <%= l(:label_create_time) %> <%= format_time(@news.created_on) %></div> <div class="mb5"><%= textAreailizable(@news, :description) %><br /> <%= l(:label_create_time) %> <%= format_time(@news.created_on) %></div>
<%= link_to_attachments_course @news %> <%= link_to_attachments_course @news %>
<!--<a href="#" class=" link_file">附件爱覅俄方if.zip(27.5kB)</a> --> <!--<a href="#" class=" link_file">附件爱覅俄方if.zip(27.5kB)</a> -->
</div> </div>
@ -95,8 +97,9 @@
<div class="msg_box"> <div class="msg_box">
<h4><%= l(:label_comment_add) %></h4> <h4><%= l(:label_comment_add) %></h4>
<%= form_tag({:controller => 'comments', :action => 'create', :id => @news}, :id => "add_comment_form") do %> <%= form_tag({:controller => 'comments', :action => 'create', :id => @news}, :id => "add_comment_form") do %>
<div class="box"> <div class="box" >
<%= text_area 'comment', 'comments', :placeholder=>"最多250个字"%> <%= hidden_field_tag :asset_id,params[:asset_id],:required => false,:style => 'display:none' %>
<%= kindeditor_tag :comment, '',:height=>'100',:editor_id =>'comment_editor', :placeholder=>"最多250个字"%>
</div> </div>
<p> <p>
<a href="#" class="grey_btn fr ml10" onclick="clearMessage();"><%= l(:label_cancel_with_space) %></a> <a href="#" class="grey_btn fr ml10" onclick="clearMessage();"><%= l(:label_cancel_with_space) %></a>
@ -106,6 +109,7 @@
<% end %> <% end %>
</div> </div>
<% end %> <% end %>
<% comments = @comments.reverse %> <% comments = @comments.reverse %>
<% comments.each do |comment| %> <% comments.each do |comment| %>
<% next if comment.new_record? %> <% next if comment.new_record? %>
@ -115,7 +119,7 @@
<div class="ping_distop"> <div class="ping_distop">
<%= link_to_user_header(comment.author,false,:class => 'c_blue fb fl mb10 ') if comment.respond_to?(:author) %><span class="c_grey fr"><%= format_time(comment.created_on) %></span> <%= link_to_user_header(comment.author,false,:class => 'c_blue fb fl mb10 ') if comment.respond_to?(:author) %><span class="c_grey fr"><%= format_time(comment.created_on) %></span>
<div class="cl"></div> <div class="cl"></div>
<p><%= textilizable(comment.comments) %></p> <p><%= textAreailizable(comment.comments) %></p>
</div> </div>
<div class="ping_disfoot"><%= link_to_if_authorized_course image_tag('delete.png'), {:controller => 'comments', :action => 'destroy', :id => @news, :comment_id => comment}, <div class="ping_disfoot"><%= link_to_if_authorized_course image_tag('delete.png'), {:controller => 'comments', :action => 'destroy', :id => @news, :comment_id => comment},
:data => {:confirm => l(:text_are_you_sure)}, :method => :delete, :title => l(:button_delete) %> :data => {:confirm => l(:text_are_you_sure)}, :method => :delete, :title => l(:button_delete) %>

@ -130,4 +130,4 @@
<% end %> <% end %>
<% end %> <% end %>
<% end %> <% end %>
<%= paginate @events_pages, :left => 3, :right => 3%> <%= paginate @events_pages, :left => 3, :right => 3 %>

@ -1,78 +1,77 @@
require File.expand_path('../boot', __FILE__) require File.expand_path('../boot', __FILE__)
require 'rails/all' require 'rails/all'
require 'sprockets/railtie' require 'sprockets/railtie'
if defined?(Bundler) if defined?(Bundler)
# If you precompile assets before deploying to production, use this line # If you precompile assets before deploying to production, use this line
Bundler.require(*Rails.groups(:assets => %w(development test))) Bundler.require(*Rails.groups(:assets => %w(development test)))
# If you want your assets lazily compiled in production, use this line # If you want your assets lazily compiled in production, use this line
# Bundler.require(:default, :assets, Rails.env) # Bundler.require(:default, :assets, Rails.env)
end end
module RedmineApp module RedmineApp
class Application < Rails::Application class Application < Rails::Application
# Settings in config/environments/* take precedence over those specified here. # Settings in config/environments/* take precedence over those specified here.
# Application configuration should go into files in config/initializers # Application configuration should go into files in config/initializers
# -- all .rb files in that directory are automatically loaded. # -- all .rb files in that directory are automatically loaded.
#verifier if email is real #verifier if email is real
config.generators do |g| config.generators do |g|
g.test_framework :rspec, g.test_framework :rspec,
fixtures: true, fixtures: true,
view_specs: false, view_specs: false,
helper_specs: false, helper_specs: false,
routing_specs: false, routing_specs: false,
controller_specs: true, controller_specs: true,
request_specs: false request_specs: false
g.fixture_replacement :factory_girl, dir: "spec/factories" g.fixture_replacement :factory_girl, dir: "spec/factories"
end end
# Custom directories with classes and modules you want to be autoloadable. # Custom directories with classes and modules you want to be autoloadable.
config.autoload_paths += %W(#{config.root}/lib) config.autoload_paths += %W(#{config.root}/lib)
# Only load the plugins named here, in the order given (default is alphabetical). # Only load the plugins named here, in the order given (default is alphabetical).
# :all can be used as a placeholder for all plugins not explicitly named. # :all can be used as a placeholder for all plugins not explicitly named.
# config.plugins = [ :exception_notification, :ssl_requirement, :all ] # config.plugins = [ :exception_notification, :ssl_requirement, :all ]
# Activate observers that should always be running. # Activate observers that should always be running.
config.active_record.observers = :journals_for_message_observer, :message_observer, :issue_observer, :journal_observer, :news_observer, config.active_record.observers = :journals_for_message_observer, :issue_observer, :journal_observer, :wiki_content_observer
:document_observer, :wiki_content_observer, :comment_observer, :forum_observer, :memo_observer
config.active_record.store_full_sti_class = true
config.active_record.store_full_sti_class = true config.active_record.default_timezone = :local
config.active_record.default_timezone = :local
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. # config.time_zone = 'Central Time (US & Canada)'
# config.time_zone = 'Central Time (US & Canada)'
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] # config.i18n.default_locale = :de
# config.i18n.default_locale = :de
# Configure the default encoding used in templates for Ruby 1.9.
# Configure the default encoding used in templates for Ruby 1.9. config.encoding = "utf-8"
config.encoding = "utf-8"
# Configure sensitive parameters which will be filtered from the log file.
# Configure sensitive parameters which will be filtered from the log file. config.filter_parameters += [:password]
config.filter_parameters += [:password]
# Enable the asset pipeline
# Enable the asset pipeline config.assets.enabled = false
config.assets.enabled = false
# Version of your assets, change this if you want to expire all your assets
# Version of your assets, change this if you want to expire all your assets config.assets.version = '1.0'
config.assets.version = '1.0'
config.action_mailer.perform_deliveries = false
config.action_mailer.perform_deliveries = false
# Do not include all helpers
# Do not include all helpers config.action_controller.include_all_helpers = false
config.action_controller.include_all_helpers = false
config.session_store :cookie_store, :key => '_redmine_session'
config.session_store :cookie_store, :key => '_redmine_session'
if File.exists?(File.join(File.dirname(__FILE__), 'additional_environment.rb'))
if File.exists?(File.join(File.dirname(__FILE__), 'additional_environment.rb')) instance_eval File.read(File.join(File.dirname(__FILE__), 'additional_environment.rb'))
instance_eval File.read(File.join(File.dirname(__FILE__), 'additional_environment.rb')) end
end
end
end end
end

@ -1,212 +1,209 @@
# = Redmine configuration file # = Redmine configuration file
# #
# Each environment has it's own configuration options. If you are only # Each environment has it's own configuration options. If you are only
# running in production, only the production block needs to be configured. # running in production, only the production block needs to be configured.
# Environment specific configuration options override the default ones. # Environment specific configuration options override the default ones.
# #
# Note that this file needs to be a valid YAML file. # Note that this file needs to be a valid YAML file.
# DO NOT USE TABS! Use 2 spaces instead of tabs for identation. # DO NOT USE TABS! Use 2 spaces instead of tabs for identation.
# #
# == Outgoing email settings (email_delivery setting) # == Outgoing email settings (email_delivery setting)
# #
# === Common configurations # === Common configurations
# #
# ==== Sendmail command # ==== Sendmail command
# #
# production: # production:
# email_delivery: # email_delivery:
# delivery_method: :sendmail # delivery_method: :sendmail
# #
# ==== Simple SMTP server at localhost # ==== Simple SMTP server at localhost
# #
# production: # production:
# email_delivery: # email_delivery:
# delivery_method: :smtp # delivery_method: :smtp
# smtp_settings: # smtp_settings:
# address: smtp.163.com # address: smtp.163.com
# port: 25 # port: 25
# #
# ==== SMTP server at example.com using LOGIN authentication and checking HELO for foo.com # ==== SMTP server at example.com using LOGIN authentication and checking HELO for foo.com
# #
# production: # production:
# email_delivery: # email_delivery:
# delivery_method: :smtp # delivery_method: :smtp
# smtp_settings: # smtp_settings:
# address: smtp.gmail.com # address: smtp.gmail.com
# port: 587 # port: 587
# authentication: :login # authentication: :login
# domain: 'foo.com' # domain: 'foo.com'
# user_name: senluowanxiangt@gmail.com # user_name: senluowanxiangt@gmail.com
# password: 1913TXBja # password: 1913TXBja
# #
# ==== SMTP server at example.com using PLAIN authentication # ==== SMTP server at example.com using PLAIN authentication
# #
# production: # production:
# email_delivery: # email_delivery:
# delivery_method: :smtp # delivery_method: :smtp
# smtp_settings: # smtp_settings:
# address: smtp.gmail.com # address: smtp.gmail.com
# port: 587 # port: 587
# authentication: :plain # authentication: :plain
# domain: 'example.com' # domain: 'example.com'
# user_name: senluowanxiangt@gmail.com # user_name: senluowanxiangt@gmail.com
# password: 1913TXBja # password: 1913TXBja
# #
# ==== SMTP server at using TLS (GMail) # ==== SMTP server at using TLS (GMail)
# #
# This might require some additional configuration. See the guides at: # This might require some additional configuration. See the guides at:
# http://www.redmine.org/projects/redmine/wiki/EmailConfiguration # http://www.redmine.org/projects/redmine/wiki/EmailConfiguration
# #
# production: # production:
# email_delivery: # email_delivery:
# delivery_method: :smtp # delivery_method: :smtp
# smtp_settings: # smtp_settings:
# enable_starttls_auto: true # enable_starttls_auto: true
# address: smtp.gmail.com # address: smtp.gmail.com
# port: 587 # port: 587
# domain: "smtp.gmail.com" # 'your.domain.com' for GoogleApps # domain: "smtp.gmail.com" # 'your.domain.com' for GoogleApps
# authentication: :plain # authentication: :plain
# user_name: senluowanxiangt@gmail.com # user_name: senluowanxiangt@gmail.com
# password: 1913TXBja # password: 1913TXBja
# #
# #
# === More configuration options # === More configuration options
# #
# See the "Configuration options" at the following website for a list of the # See the "Configuration options" at the following website for a list of the
# full options allowed: # full options allowed:
# #
# http://wiki.rubyonrails.org/rails/pages/HowToSendEmailsWithActionMailer # http://wiki.rubyonrails.org/rails/pages/HowToSendEmailsWithActionMailer
# default configuration options for all environments # default configuration options for all environments
default: default:
# Outgoing emails configuration (see examples above) # Outgoing emails configuration (see examples above)
email_delivery: email_delivery:
delivery_method: :smtp delivery_method: :smtp
smtp_settings: smtp_settings:
address: smtp.126.com
port: 25
domain: smtp.126.com
address: smtp.126.com authentication: :plain
port: 25 user_name: "alanlong9278@126.com"
domain: smtp.126.com password: 'alanlong8788786'
authentication: :plain
user_name: "alanlong9278@126.com" # Absolute path to the directory where attachments are stored.
password: 'alanlong8788786' # The default is the 'files' directory in your Redmine instance.
# Your Redmine instance needs to have write permission on this
# Absolute path to the directory where attachments are stored. # directory.
# The default is the 'files' directory in your Redmine instance. # Examples:
# Your Redmine instance needs to have write permission on this # attachments_storage_path: /var/redmine/files
# directory. # attachments_storage_path: D:/redmine/files
# Examples: attachments_storage_path:
# attachments_storage_path: /var/redmine/files
# attachments_storage_path: D:/redmine/files # Configuration of the autologin cookie.
attachments_storage_path: # autologin_cookie_name: the name of the cookie (default: autologin)
# autologin_cookie_path: the cookie path (default: /)
# Configuration of the autologin cookie. # autologin_cookie_secure: true sets the cookie secure flag (default: false)
# autologin_cookie_name: the name of the cookie (default: autologin) autologin_cookie_name:
# autologin_cookie_path: the cookie path (default: /) autologin_cookie_path:
# autologin_cookie_secure: true sets the cookie secure flag (default: false) autologin_cookie_secure:
autologin_cookie_name:
autologin_cookie_path: # Configuration of SCM executable command.
autologin_cookie_secure: #
# Absolute path (e.g. /usr/local/bin/hg) or command name (e.g. hg.exe, bzr.exe)
# Configuration of SCM executable command. # On Windows + CRuby, *.cmd, *.bat (e.g. hg.cmd, bzr.bat) does not work.
# #
# Absolute path (e.g. /usr/local/bin/hg) or command name (e.g. hg.exe, bzr.exe) # On Windows + JRuby 1.6.2, path which contains spaces does not work.
# On Windows + CRuby, *.cmd, *.bat (e.g. hg.cmd, bzr.bat) does not work. # For example, "C:\Program Files\TortoiseHg\hg.exe".
# # If you want to this feature, you need to install to the path which does not contains spaces.
# On Windows + JRuby 1.6.2, path which contains spaces does not work. # For example, "C:\TortoiseHg\hg.exe".
# For example, "C:\Program Files\TortoiseHg\hg.exe". #
# If you want to this feature, you need to install to the path which does not contains spaces. # Examples:
# For example, "C:\TortoiseHg\hg.exe". # scm_subversion_command: svn # (default: svn)
# # scm_mercurial_command: C:\Program Files\TortoiseHg\hg.exe # (default: hg)
# Examples: # scm_git_command: /usr/local/bin/git # (default: git)
# scm_subversion_command: svn # (default: svn) # scm_cvs_command: cvs # (default: cvs)
# scm_mercurial_command: C:\Program Files\TortoiseHg\hg.exe # (default: hg) # scm_bazaar_command: bzr.exe # (default: bzr)
# scm_git_command: /usr/local/bin/git # (default: git) # scm_darcs_command: darcs-1.0.9-i386-linux # (default: darcs)
# scm_cvs_command: cvs # (default: cvs) #
# scm_bazaar_command: bzr.exe # (default: bzr) scm_subversion_command:
# scm_darcs_command: darcs-1.0.9-i386-linux # (default: darcs) scm_mercurial_command:
# scm_git_command:
scm_subversion_command: scm_cvs_command:
scm_mercurial_command: scm_bazaar_command:
scm_git_command: scm_darcs_command:
scm_cvs_command:
scm_bazaar_command: # Absolute path to the SCM commands errors (stderr) log file.
scm_darcs_command: # The default is to log in the 'log' directory of your Redmine instance.
# Example:
# Absolute path to the SCM commands errors (stderr) log file. # scm_stderr_log_file: /var/log/redmine_scm_stderr.log
# The default is to log in the 'log' directory of your Redmine instance. scm_stderr_log_file:
# Example:
# scm_stderr_log_file: /var/log/redmine_scm_stderr.log # Key used to encrypt sensitive data in the database (SCM and LDAP passwords).
scm_stderr_log_file: # If you don't want to enable data encryption, just leave it blank.
# WARNING: losing/changing this key will make encrypted data unreadable.
# Key used to encrypt sensitive data in the database (SCM and LDAP passwords). #
# If you don't want to enable data encryption, just leave it blank. # If you want to encrypt existing passwords in your database:
# WARNING: losing/changing this key will make encrypted data unreadable. # * set the cipher key here in your configuration file
# # * encrypt data using 'rake db:encrypt RAILS_ENV=production'
# If you want to encrypt existing passwords in your database: #
# * set the cipher key here in your configuration file # If you have encrypted data and want to change this key, you have to:
# * encrypt data using 'rake db:encrypt RAILS_ENV=production' # * decrypt data using 'rake db:decrypt RAILS_ENV=production' first
# # * change the cipher key here in your configuration file
# If you have encrypted data and want to change this key, you have to: # * encrypt data using 'rake db:encrypt RAILS_ENV=production'
# * decrypt data using 'rake db:decrypt RAILS_ENV=production' first database_cipher_key:
# * change the cipher key here in your configuration file
# * encrypt data using 'rake db:encrypt RAILS_ENV=production' # Set this to false to disable plugins' assets mirroring on startup.
database_cipher_key: # You can use `rake redmine:plugins:assets` to manually mirror assets
# to public/plugin_assets when you install/upgrade a Redmine plugin.
# Set this to false to disable plugins' assets mirroring on startup. #
# You can use `rake redmine:plugins:assets` to manually mirror assets #mirror_plugins_assets_on_startup: false
# to public/plugin_assets when you install/upgrade a Redmine plugin.
# # Your secret key for verifying cookie session data integrity. If you
#mirror_plugins_assets_on_startup: false # change this key, all old sessions will become invalid! Make sure the
# secret is at least 30 characters and all random, no regular words or
# Your secret key for verifying cookie session data integrity. If you # you'll be exposed to dictionary attacks.
# change this key, all old sessions will become invalid! Make sure the #
# secret is at least 30 characters and all random, no regular words or # If you have a load-balancing Redmine cluster, you have to use the
# you'll be exposed to dictionary attacks. # same secret token on each machine.
# #secret_token: 'change it to a long random string'
# If you have a load-balancing Redmine cluster, you have to use the
# same secret token on each machine. # Absolute path (e.g. /usr/bin/convert, c:/im/convert.exe) to
#secret_token: 'change it to a long random string' # the ImageMagick's `convert` binary. Used to generate attachment thumbnails.
imagemagick_convert_command: '/home/pdl/redmine-2.3.2-0/common/bin/convert'
# Absolute path (e.g. /usr/bin/convert, c:/im/convert.exe) to
# the ImageMagick's `convert` binary. Used to generate attachment thumbnails. # Configuration of RMagcik font.
imagemagick_convert_command: '/home/pdl/redmine-2.3.2-0/common/bin/convert' #
# Redmine uses RMagcik in order to export gantt png.
# Configuration of RMagcik font. # You don't need this setting if you don't install RMagcik.
# #
# Redmine uses RMagcik in order to export gantt png. # In CJK (Chinese, Japanese and Korean),
# You don't need this setting if you don't install RMagcik. # in order to show CJK characters correctly,
# # you need to set this configuration.
# In CJK (Chinese, Japanese and Korean), #
# in order to show CJK characters correctly, # Because there is no standard font across platforms in CJK,
# you need to set this configuration. # you need to set a font installed in your server.
# #
# Because there is no standard font across platforms in CJK, # This setting is not necessary in non CJK.
# you need to set a font installed in your server. #
# # Examples for Japanese:
# This setting is not necessary in non CJK. # Windows:
# # rmagick_font_path: C:\windows\fonts\msgothic.ttc
# Examples for Japanese: # Linux:
# Windows: # rmagick_font_path: /usr/share/fonts/ipa-mincho/ipam.ttf
# rmagick_font_path: C:\windows\fonts\msgothic.ttc #
# Linux: rmagick_font_path:
# rmagick_font_path: /usr/share/fonts/ipa-mincho/ipam.ttf
# # Maximum number of simultaneous AJAX uploads
rmagick_font_path: #max_concurrent_ajax_uploads: 2
#pic_types: "bmp,jpeg,jpg,png,gif"
# Maximum number of simultaneous AJAX uploads
#max_concurrent_ajax_uploads: 2 # specific configuration options for production environment
#pic_types: "bmp,jpeg,jpg,png,gif" # that overrides the default ones
production:
# specific configuration options for production environment # CJK support
# that overrides the default ones rmagick_font_path: /usr/share/fonts/ipa-mincho/ipam.ttf
production:
# CJK support # specific configuration options for development environment
rmagick_font_path: /usr/share/fonts/ipa-mincho/ipam.ttf # that overrides the default ones
development:
# specific configuration options for development environment
# that overrides the default ones
development:

@ -1,15 +1,16 @@
I18n.default_locale = 'en' I18n.default_locale = 'en'
I18n.backend = Redmine::I18n::Backend.new I18n.backend = Redmine::I18n::Backend.new
require 'redmine' require 'redmine'
require 'trustie'
# Load the secret token from the Redmine configuration file
secret = Redmine::Configuration['secret_token'] # Load the secret token from the Redmine configuration file
if secret.present? secret = Redmine::Configuration['secret_token']
RedmineApp::Application.config.secret_token = secret if secret.present?
end RedmineApp::Application.config.secret_token = secret
end
Redmine::Plugin.load
unless Redmine::Configuration['mirror_plugins_assets_on_startup'] == false Redmine::Plugin.load
Redmine::Plugin.mirror_assets unless Redmine::Configuration['mirror_plugins_assets_on_startup'] == false
end Redmine::Plugin.mirror_assets
end

@ -1,27 +1,15 @@
#!/usr/bin/env ruby #coding=utf-8
require 'rubygems'
require 'rufus-scheduler' ## 移入crontab
#users = User.where("mail_notification = 'week' or mail_notification = 'day'") # scheduler = Rufus::Scheduler.new
#
scheduler = Rufus::Scheduler.new # #每天18:00发送当天的邮件汇总
scheduler.cron('0 0 * * 1') do # scheduler.cron('0 18 * * *') do
users = User.where("mail_notification = 'week'") # users = User.where(mail_notification: 'day')
users.each do |user| # users.each do |user|
#Rails.logger.info "send mail to #{user.show_name}(#{user.mail}) at #{Time.now}" # mailer = Mailer.send_for_user_activities(user, Date.today, 1)
Thread.start do # mailer.deliver if mailer
Mailer.send_for_user_activities(user, Date.today, 7).deliver # end
end # end
end
end
scheduler.cron('0 0 * * *') do
users = User.where("mail_notification = 'day'")
users.each do |user|
#Rails.logger.info "send mail to #{user.show_name}(#{user.mail}) at #{Time.now}"
Thread.start do
Mailer.send_for_user_activities(user, Date.today, 1).deliver
end
end
end

@ -1,22 +0,0 @@
# Time 2015-01-30 17:02:41
# Author lizanle
# Description 打开redmine\ruby\lib\ruby\gems\1.9.1\gems\actionpack-3.2.13\lib\action_view\helpers\UrlHelper重写link_to_unless方法
# 如果是当前页则给当前页添加样式class=>'current-page'
module ActionView
# = Action View URL Helpers
module Helpers #:nodoc:
# Provides a set of methods for making links and getting URLs that
# depend on the routing subsystem (see ActionDispatch::Routing).
# This allows you to use the same format for links in views
# and controllers.
module UrlHelper
def link_to_unless(condition, name, options = {}, html_options = {}, &block)
if condition
link_to(name, options, html_options.merge(:class => 'current-page'))
else
link_to(name, options, html_options)
end
end
end
end
end

@ -184,6 +184,11 @@ en:
label_anonymous: Anonymous #作业和留言 模块 label_anonymous: Anonymous #作业和留言 模块
text_are_you_sure: Are you sure? #js 提示 text_are_you_sure: Are you sure? #js 提示
text_are_you_sure_out: 你确定要退出该课程吗?
text_are_you_sure_out_group: 你确定要退出该分班吗?
label_no_data: No data to display label_no_data: No data to display
# 项目、课程、用户公用 # 项目、课程、用户公用

@ -187,7 +187,8 @@ zh:
text_are_you_sure: 您确定要删除吗? #js 提示 text_are_you_sure: 您确定要删除吗? #js 提示
text_are_you_sure_out: 你确定要退出该课程吗?
text_are_you_sure_out_group: 你确定要退出该分班吗?
label_no_data: 没有任何数据可供显示 label_no_data: 没有任何数据可供显示

@ -4,7 +4,7 @@ en:
# 托管平台主页 > 底部承办单位 # 托管平台主页 > 底部承办单位
label_hosted_by: Organizer label_hosted_organization: Organizer
label_hosted_by: National Key Laboratory for Parallel and Distributed Processing, NUDT label_hosted_by: National Key Laboratory for Parallel and Distributed Processing, NUDT
label_sponsor: Department of Computer Science and Technology, NUDT label_sponsor: Department of Computer Science and Technology, NUDT
label_co_organizer_NUDT: College of Computer, NUDT label_co_organizer_NUDT: College of Computer, NUDT

@ -6,10 +6,13 @@ en:
# #
# 课程公共标签 # 课程公共标签
# #
label_course_join_student: 加入课程 label_course_join_student: Join a course
label_course_new: 新建课程 label_course_exit_student: Exit a course
label_course_new: New course
label_homework: 课程作业 label_course_name: Course name
label_homework: Task
label_course_news: 课程通知 label_course_news: 课程通知
label_main_teacher: 主讲教师 label_main_teacher: 主讲教师
label_course_term: 开课学期 label_course_term: 开课学期

@ -13,6 +13,7 @@ zh:
label_course_join_student: 加入课程 label_course_join_student: 加入课程
label_course_exit_student: 退出课程 label_course_exit_student: 退出课程
label_course_new: 新建课程 label_course_new: 新建课程
label_course_name: 课程名称
label_homework: 课程作业 label_homework: 课程作业
label_course_news: 课程通知 label_course_news: 课程通知

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

Loading…
Cancel
Save