Merge branch 'szzh' of http://repository.trustie.net/xianbo/trustie2 into szzh
Conflicts: app/views/boards/_project_show.html.erb public/javascripts/course.js 处理冲突 修改项目动态分页 项目到航天中添加“新建项目”
This commit is contained in:
commit
12eaac5683
279
Gemfile
279
Gemfile
|
@ -1,139 +1,140 @@
|
|||
source 'http://ruby.taobao.org'
|
||||
#source 'http://ruby.sdutlinux.org/'
|
||||
|
||||
unless RUBY_PLATFORM =~ /w32/
|
||||
# unix-like only
|
||||
gem 'iconv'
|
||||
gem 'rubyzip'
|
||||
gem 'zip-zip'
|
||||
end
|
||||
|
||||
gem 'grape', '~> 0.9.0'
|
||||
gem 'grape-entity'
|
||||
gem 'seems_rateable', '~> 1.0.13'
|
||||
gem "rails", "3.2.13"
|
||||
gem "jquery-rails", "~> 2.0.2"
|
||||
gem "i18n", "~> 0.6.0"
|
||||
gem 'coderay', '~> 1.1.0'
|
||||
gem "fastercsv", "~> 1.5.0", :platforms => [:mri_18, :mingw_18, :jruby]
|
||||
gem "builder", "3.0.0"
|
||||
gem 'acts-as-taggable-on', '2.4.1'
|
||||
gem 'spreadsheet'
|
||||
gem 'ruby-ole'
|
||||
#gem 'email_verifier', path: 'lib/email_verifier'
|
||||
gem 'rufus-scheduler'
|
||||
#gem 'dalli', path: 'lib/dalli-2.7.2'
|
||||
gem 'rails_kindeditor',path:'lib/rails_kindeditor'
|
||||
group :development do
|
||||
gem 'grape-swagger'
|
||||
#gem 'grape-swagger-ui', git: 'https://github.com/guange2015/grape-swagger-ui.git'
|
||||
gem 'puma' if RbConfig::CONFIG['host_os'] =~ /linux/
|
||||
gem 'pry-rails'
|
||||
if RUBY_VERSION >= '2.0.0'
|
||||
gem 'pry-byebug'
|
||||
else
|
||||
# gem 'pry-debugger'
|
||||
end
|
||||
gem 'pry-stack_explorer'
|
||||
gem 'better_errors', '~> 1.1.0'
|
||||
gem 'rack-mini-profiler', '~> 0.9.3'
|
||||
end
|
||||
|
||||
group :test do
|
||||
gem "shoulda", "~> 3.5.0"
|
||||
gem "mocha", "~> 1.1.0"
|
||||
gem 'capybara', '~> 2.4.1'
|
||||
gem 'nokogiri', '~> 1.6.3'
|
||||
gem 'factory_girl', '~> 4.4.0'
|
||||
gem 'selenium-webdriver', '~> 2.42.0'
|
||||
|
||||
gem "faker"
|
||||
# platforms :mri, :mingw do
|
||||
# group :rmagick do
|
||||
# # RMagick 2 supports ruby 1.9
|
||||
# # RMagick 1 would be fine for ruby 1.8 but Bundler does not support
|
||||
# # different requirements for the same gem on different platforms
|
||||
# gem "rmagick", ">= 2.0.0"
|
||||
# end
|
||||
#end
|
||||
end
|
||||
|
||||
# Gems used only for assets and not required
|
||||
# in production environments by default.
|
||||
group :assets do
|
||||
gem 'sass-rails', '~> 3.2.3'
|
||||
gem 'coffee-rails', '~> 3.2.1'
|
||||
|
||||
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
|
||||
gem 'therubyracer', :platforms => :ruby
|
||||
|
||||
gem 'uglifier', '>= 1.0.3'
|
||||
end
|
||||
|
||||
# Optional gem for LDAP authentication
|
||||
group :ldap do
|
||||
gem "net-ldap", "~> 0.3.1"
|
||||
end
|
||||
|
||||
|
||||
# Optional gem for OpenID authentication
|
||||
group :openid do
|
||||
gem "ruby-openid", "~> 2.1.4", :require => "openid"
|
||||
gem "rack-openid"
|
||||
end
|
||||
|
||||
# Optional gem for exporting the gantt to a PNG file, not supported with jruby
|
||||
platforms :jruby do
|
||||
# jruby-openssl is bundled with JRuby 1.7.0
|
||||
gem "jruby-openssl" if Object.const_defined?(:JRUBY_VERSION) && JRUBY_VERSION < '1.7.0'
|
||||
gem "activerecord-jdbc-adapter", "1.2.5"
|
||||
end
|
||||
|
||||
# Include database gems for the adapters found in the database
|
||||
# configuration file
|
||||
require 'erb'
|
||||
require 'yaml'
|
||||
database_file = File.join(File.dirname(__FILE__), "config/database.yml")
|
||||
if File.exist?(database_file)
|
||||
database_config = YAML::load(ERB.new(IO.read(database_file)).result)
|
||||
adapters = database_config.values.map {|c| c['adapter']}.compact.uniq
|
||||
if adapters.any?
|
||||
adapters.each do |adapter|
|
||||
case adapter
|
||||
when 'mysql2'
|
||||
gem "mysql2", "= 0.3.18", :platforms => [:mri, :mingw]
|
||||
gem "activerecord-jdbcmysql-adapter", :platforms => :jruby
|
||||
when 'mysql'
|
||||
gem "mysql", "~> 2.8.1", :platforms => [:mri, :mingw]
|
||||
gem "activerecord-jdbcmysql-adapter", :platforms => :jruby
|
||||
when /postgresql/
|
||||
gem "pg", ">= 0.11.0", :platforms => [:mri, :mingw]
|
||||
gem "activerecord-jdbcpostgresql-adapter", :platforms => :jruby
|
||||
when /sqlite3/
|
||||
gem "sqlite3", :platforms => [:mri, :mingw]
|
||||
gem "activerecord-jdbcsqlite3-adapter", :platforms => :jruby
|
||||
when /sqlserver/
|
||||
gem "tiny_tds", "~> 0.5.1", :platforms => [:mri, :mingw]
|
||||
gem "activerecord-sqlserver-adapter", :platforms => [:mri, :mingw]
|
||||
else
|
||||
warn("Unknown database adapter `#{adapter}` found in config/database.yml, use Gemfile.local to load your own database gems")
|
||||
end
|
||||
end
|
||||
else
|
||||
warn("No adapter found in config/database.yml, please configure it first")
|
||||
end
|
||||
else
|
||||
warn("Please configure your config/database.yml first")
|
||||
end
|
||||
|
||||
local_gemfile = File.join(File.dirname(__FILE__), "Gemfile.local")
|
||||
if File.exists?(local_gemfile)
|
||||
puts "Loading Gemfile.local ..." if $DEBUG # `ruby -d` or `bundle -v`
|
||||
instance_eval File.read(local_gemfile)
|
||||
end
|
||||
|
||||
# Load plugins' Gemfiles
|
||||
Dir.glob File.expand_path("../plugins/*/Gemfile", __FILE__) do |file|
|
||||
puts "Loading #{file} ..." if $DEBUG # `ruby -d` or `bundle -v`
|
||||
instance_eval File.read(file)
|
||||
end
|
||||
source 'http://ruby.taobao.org'
|
||||
#source 'http://ruby.sdutlinux.org/'
|
||||
|
||||
unless RUBY_PLATFORM =~ /w32/
|
||||
# unix-like only
|
||||
gem 'iconv'
|
||||
end
|
||||
|
||||
gem 'rubyzip'
|
||||
gem 'delayed_job_active_record'#, :group => :production
|
||||
gem 'daemons'
|
||||
gem 'grape', '~> 0.9.0'
|
||||
gem 'grape-entity'
|
||||
gem 'seems_rateable', '~> 1.0.13'
|
||||
gem "rails", "3.2.13"
|
||||
gem "jquery-rails", "~> 2.0.2"
|
||||
gem "i18n", "~> 0.6.0"
|
||||
gem 'coderay', '~> 1.1.0'
|
||||
gem "fastercsv", "~> 1.5.0", :platforms => [:mri_18, :mingw_18, :jruby]
|
||||
gem "builder", "3.0.0"
|
||||
gem 'acts-as-taggable-on', '2.4.1'
|
||||
gem 'spreadsheet'
|
||||
gem 'ruby-ole'
|
||||
#gem 'email_verifier', path: 'lib/email_verifier'
|
||||
gem 'rufus-scheduler'
|
||||
#gem 'dalli', path: 'lib/dalli-2.7.2'
|
||||
gem 'rails_kindeditor',path:'lib/rails_kindeditor'
|
||||
group :development do
|
||||
gem 'grape-swagger'
|
||||
#gem 'grape-swagger-ui', git: 'https://github.com/guange2015/grape-swagger-ui.git'
|
||||
gem 'puma' if RbConfig::CONFIG['host_os'] =~ /linux/
|
||||
gem 'pry-rails'
|
||||
if RUBY_VERSION >= '2.0.0'
|
||||
gem 'pry-byebug'
|
||||
else
|
||||
# gem 'pry-debugger'
|
||||
end
|
||||
gem 'pry-stack_explorer'
|
||||
gem 'better_errors', '~> 1.1.0'
|
||||
gem 'rack-mini-profiler', '~> 0.9.3'
|
||||
end
|
||||
|
||||
group :test do
|
||||
gem "shoulda", "~> 3.5.0"
|
||||
gem "mocha", "~> 1.1.0"
|
||||
gem 'capybara', '~> 2.4.1'
|
||||
gem 'nokogiri', '~> 1.6.3'
|
||||
gem 'factory_girl', '~> 4.4.0'
|
||||
gem 'selenium-webdriver', '~> 2.42.0'
|
||||
|
||||
gem "faker"
|
||||
# platforms :mri, :mingw do
|
||||
# group :rmagick do
|
||||
# # RMagick 2 supports ruby 1.9
|
||||
# # RMagick 1 would be fine for ruby 1.8 but Bundler does not support
|
||||
# # different requirements for the same gem on different platforms
|
||||
# gem "rmagick", ">= 2.0.0"
|
||||
# end
|
||||
#end
|
||||
end
|
||||
|
||||
# Gems used only for assets and not required
|
||||
# in production environments by default.
|
||||
group :assets do
|
||||
gem 'sass-rails', '~> 3.2.3'
|
||||
gem 'coffee-rails', '~> 3.2.1'
|
||||
|
||||
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
|
||||
gem 'therubyracer', :platforms => :ruby
|
||||
|
||||
gem 'uglifier', '>= 1.0.3'
|
||||
end
|
||||
|
||||
# Optional gem for LDAP authentication
|
||||
group :ldap do
|
||||
gem "net-ldap", "~> 0.3.1"
|
||||
end
|
||||
|
||||
|
||||
# Optional gem for OpenID authentication
|
||||
group :openid do
|
||||
gem "ruby-openid", "~> 2.1.4", :require => "openid"
|
||||
gem "rack-openid"
|
||||
end
|
||||
|
||||
# Optional gem for exporting the gantt to a PNG file, not supported with jruby
|
||||
platforms :jruby do
|
||||
# jruby-openssl is bundled with JRuby 1.7.0
|
||||
gem "jruby-openssl" if Object.const_defined?(:JRUBY_VERSION) && JRUBY_VERSION < '1.7.0'
|
||||
gem "activerecord-jdbc-adapter", "1.2.5"
|
||||
end
|
||||
|
||||
# Include database gems for the adapters found in the database
|
||||
# configuration file
|
||||
require 'erb'
|
||||
require 'yaml'
|
||||
database_file = File.join(File.dirname(__FILE__), "config/database.yml")
|
||||
if File.exist?(database_file)
|
||||
database_config = YAML::load(ERB.new(IO.read(database_file)).result)
|
||||
adapters = database_config.values.map {|c| c['adapter']}.compact.uniq
|
||||
if adapters.any?
|
||||
adapters.each do |adapter|
|
||||
case adapter
|
||||
when 'mysql2'
|
||||
gem "mysql2", "= 0.3.18", :platforms => [:mri, :mingw]
|
||||
gem "activerecord-jdbcmysql-adapter", :platforms => :jruby
|
||||
when 'mysql'
|
||||
gem "mysql", "~> 2.8.1", :platforms => [:mri, :mingw]
|
||||
gem "activerecord-jdbcmysql-adapter", :platforms => :jruby
|
||||
when /postgresql/
|
||||
gem "pg", ">= 0.11.0", :platforms => [:mri, :mingw]
|
||||
gem "activerecord-jdbcpostgresql-adapter", :platforms => :jruby
|
||||
when /sqlite3/
|
||||
gem "sqlite3", :platforms => [:mri, :mingw]
|
||||
gem "activerecord-jdbcsqlite3-adapter", :platforms => :jruby
|
||||
when /sqlserver/
|
||||
gem "tiny_tds", "~> 0.5.1", :platforms => [:mri, :mingw]
|
||||
gem "activerecord-sqlserver-adapter", :platforms => [:mri, :mingw]
|
||||
else
|
||||
warn("Unknown database adapter `#{adapter}` found in config/database.yml, use Gemfile.local to load your own database gems")
|
||||
end
|
||||
end
|
||||
else
|
||||
warn("No adapter found in config/database.yml, please configure it first")
|
||||
end
|
||||
else
|
||||
warn("Please configure your config/database.yml first")
|
||||
end
|
||||
|
||||
local_gemfile = File.join(File.dirname(__FILE__), "Gemfile.local")
|
||||
if File.exists?(local_gemfile)
|
||||
puts "Loading Gemfile.local ..." if $DEBUG # `ruby -d` or `bundle -v`
|
||||
instance_eval File.read(local_gemfile)
|
||||
end
|
||||
|
||||
# Load plugins' Gemfiles
|
||||
Dir.glob File.expand_path("../plugins/*/Gemfile", __FILE__) do |file|
|
||||
puts "Loading #{file} ..." if $DEBUG # `ruby -d` or `bundle -v`
|
||||
instance_eval File.read(file)
|
||||
end
|
||||
|
|
|
@ -1,49 +1,49 @@
|
|||
module Mobile
|
||||
require_relative 'middleware/error_handler'
|
||||
require_relative 'apis/auth'
|
||||
require_relative 'apis/users'
|
||||
require_relative 'apis/courses'
|
||||
require_relative 'apis/watches'
|
||||
require_relative 'apis/upgrade'
|
||||
require_relative 'apis/homeworks'
|
||||
require_relative 'apis/comments'
|
||||
class API < Grape::API
|
||||
version 'v1', using: :path
|
||||
format :json
|
||||
content_type :json, "application/json;charset=UTF-8"
|
||||
use Mobile::Middleware::ErrorHandler
|
||||
|
||||
helpers do
|
||||
def logger
|
||||
API.logger
|
||||
end
|
||||
|
||||
def authenticate!
|
||||
raise('Unauthorized. Invalid or expired token.') unless current_user
|
||||
end
|
||||
|
||||
def current_user
|
||||
token = ApiKey.where(access_token: params[:token]).first
|
||||
if token && !token.expired?
|
||||
@current_user = User.find(token.user_id)
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
mount Apis::Auth
|
||||
mount Apis::Users
|
||||
mount Apis::Courses
|
||||
mount Apis::Watches
|
||||
mount Apis::Upgrade
|
||||
mount Apis::Homeworks
|
||||
mount Apis::Comments
|
||||
|
||||
#add_swagger_documentation ({api_version: 'v1', base_path: 'http://u06.shellinfo.cn/trustie/api'})
|
||||
#add_swagger_documentation ({api_version: 'v1', base_path: '/api'}) if Rails.env.development?
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module Mobile
|
||||
require_relative 'middleware/error_handler'
|
||||
require_relative 'apis/auth'
|
||||
require_relative 'apis/users'
|
||||
require_relative 'apis/courses'
|
||||
require_relative 'apis/watches'
|
||||
require_relative 'apis/upgrade'
|
||||
require_relative 'apis/homeworks'
|
||||
require_relative 'apis/comments'
|
||||
class API < Grape::API
|
||||
version 'v1', using: :path
|
||||
format :json
|
||||
content_type :json, "application/json;charset=UTF-8"
|
||||
use Mobile::Middleware::ErrorHandler
|
||||
|
||||
helpers do
|
||||
def logger
|
||||
API.logger
|
||||
end
|
||||
|
||||
def authenticate!
|
||||
raise('Unauthorized. Invalid or expired token.') unless current_user
|
||||
end
|
||||
|
||||
def current_user
|
||||
token = ApiKey.where(access_token: params[:token]).first
|
||||
if token && !token.expired?
|
||||
@current_user = User.find(token.user_id)
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
mount Apis::Auth
|
||||
mount Apis::Users
|
||||
mount Apis::Courses
|
||||
mount Apis::Watches
|
||||
mount Apis::Upgrade
|
||||
mount Apis::Homeworks
|
||||
mount Apis::Comments
|
||||
|
||||
#add_swagger_documentation ({api_version: 'v1', base_path: 'http://u06.shellinfo.cn/trustie/api'})
|
||||
#add_swagger_documentation ({api_version: 'v1', base_path: '/api'}) if Rails.env.development?
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
|
|
@ -88,9 +88,7 @@ class AccountController < ApplicationController
|
|||
# create a new token for password recovery
|
||||
token = Token.new(:user => user, :action => "recovery")
|
||||
if token.save
|
||||
Thread.new do
|
||||
Mailer.lost_password(token).deliver
|
||||
end
|
||||
Mailer.run.lost_password(token)
|
||||
flash[:notice] = l(:notice_account_lost_email_sent)
|
||||
redirect_to signin_url
|
||||
return
|
||||
|
@ -228,7 +226,7 @@ class AccountController < ApplicationController
|
|||
user = User.find(params[:user]) if params[:user]
|
||||
token = Token.new(:user => user, :action => "register")
|
||||
if token.save
|
||||
Mailer.register(token).deliver
|
||||
Mailer.run.register(token)
|
||||
|
||||
else
|
||||
yield if block_given?
|
||||
|
@ -366,7 +364,7 @@ class AccountController < ApplicationController
|
|||
token = Token.new(:user => user, :action => "register")
|
||||
if user.save and token.save
|
||||
UserStatus.create(:user_id => user.id, :changsets_count => 0, :watchers_count => 0)
|
||||
Mailer.register(token).deliver
|
||||
Mailer.run.register(token)
|
||||
|
||||
|
||||
flash[:notice] = l(:notice_account_register_done)
|
||||
|
@ -401,7 +399,7 @@ class AccountController < ApplicationController
|
|||
if user.save
|
||||
UserStatus.create(:user_id => user.id ,:changsets_count => 0, :watchers_count => 0)
|
||||
# Sends an email to the administrators
|
||||
Mailer.account_activation_request(user).deliver
|
||||
Mailer.run.account_activation_request(user)
|
||||
account_pending
|
||||
else
|
||||
yield if block_given?
|
||||
|
|
|
@ -1,59 +1,59 @@
|
|||
class AppliedProjectController < ApplicationController
|
||||
|
||||
#申请加入项目
|
||||
def applied_join_project
|
||||
@user_id = params[:user_id]
|
||||
@project = Project.find_by_id(params[:project_id])
|
||||
if params[:project_join]
|
||||
if @project
|
||||
user = User.find @user_id
|
||||
if user.member_of?(@project)
|
||||
@status = 3
|
||||
else
|
||||
@applieds = AppliedProject.where("user_id = ? and project_id = ?", params[:user_id],params[:project_id])
|
||||
if @applieds.count == 0
|
||||
appliedproject = AppliedProject.create(:user_id => params[:user_id], :project_id => params[:project_id])
|
||||
Mailer.applied_project(appliedproject).deliver
|
||||
@status = 2
|
||||
else
|
||||
@status = 1
|
||||
end
|
||||
end
|
||||
else
|
||||
@status = 0
|
||||
end
|
||||
respond_to do |format|
|
||||
format.js
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
@applieds = AppliedProject.where("user_id = ? and project_id = ?", params[:user_id],params[:project_id])
|
||||
if @applieds.count == 0
|
||||
appliedproject = AppliedProject.create(:user_id => params[:user_id], :project_id => params[:project_id])
|
||||
Mailer.applied_project(appliedproject).deliver
|
||||
end
|
||||
|
||||
#redirect_to project_path(params[:project_id])
|
||||
#redirect_to_referer_or {render :text => ( 'applied success.'), :layout => true}
|
||||
respond_to do |format|
|
||||
format.html { redirect_to_referer_or {render :text => (watching ? 'Watcher added.' : 'Watcher removed.'), :layout => true}}
|
||||
format.js { render :partial => 'set_applied'}
|
||||
end
|
||||
end
|
||||
|
||||
#取消申请
|
||||
def unapplied_join_project
|
||||
@project = Project.find(params[:project_id])
|
||||
#@applied = AppliedProject.find(params[:id])
|
||||
#@applied.destroy
|
||||
|
||||
AppliedProject.deleteappiled(params[:user_id], params[:project_id])
|
||||
|
||||
respond_to do |format|
|
||||
format.html { redirect_to_referer_or {render :text => (watching ? 'Watcher added.' : 'Watcher removed.'), :layout => true}}
|
||||
format.js { render :partial => 'set_applied' }
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
class AppliedProjectController < ApplicationController
|
||||
|
||||
#申请加入项目
|
||||
def applied_join_project
|
||||
@user_id = params[:user_id]
|
||||
@project = Project.find_by_id(params[:project_id])
|
||||
if params[:project_join]
|
||||
if @project
|
||||
user = User.find @user_id
|
||||
if user.member_of?(@project)
|
||||
@status = 3
|
||||
else
|
||||
@applieds = AppliedProject.where("user_id = ? and project_id = ?", params[:user_id],params[:project_id])
|
||||
if @applieds.count == 0
|
||||
appliedproject = AppliedProject.create(:user_id => params[:user_id], :project_id => params[:project_id])
|
||||
Mailer.run.applied_project(appliedproject)
|
||||
@status = 2
|
||||
else
|
||||
@status = 1
|
||||
end
|
||||
end
|
||||
else
|
||||
@status = 0
|
||||
end
|
||||
respond_to do |format|
|
||||
format.js
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
@applieds = AppliedProject.where("user_id = ? and project_id = ?", params[:user_id],params[:project_id])
|
||||
if @applieds.count == 0
|
||||
appliedproject = AppliedProject.create(:user_id => params[:user_id], :project_id => params[:project_id])
|
||||
Mailer.run.applied_project(appliedproject)
|
||||
end
|
||||
|
||||
#redirect_to project_path(params[:project_id])
|
||||
#redirect_to_referer_or {render :text => ( 'applied success.'), :layout => true}
|
||||
respond_to do |format|
|
||||
format.html { redirect_to_referer_or {render :text => (watching ? 'Watcher added.' : 'Watcher removed.'), :layout => true}}
|
||||
format.js { render :partial => 'set_applied'}
|
||||
end
|
||||
end
|
||||
|
||||
#取消申请
|
||||
def unapplied_join_project
|
||||
@project = Project.find(params[:project_id])
|
||||
#@applied = AppliedProject.find(params[:id])
|
||||
#@applied.destroy
|
||||
|
||||
AppliedProject.deleteappiled(params[:user_id], params[:project_id])
|
||||
|
||||
respond_to do |format|
|
||||
format.html { redirect_to_referer_or {render :text => (watching ? 'Watcher added.' : 'Watcher removed.'), :layout => true}}
|
||||
format.js { render :partial => 'set_applied' }
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -27,7 +27,7 @@ class AttachmentsController < ApplicationController
|
|||
accept_api_auth :show, :download, :upload
|
||||
require 'iconv'
|
||||
include AttachmentsHelper
|
||||
|
||||
include ApplicationHelper
|
||||
|
||||
def show
|
||||
respond_to do |format|
|
||||
|
@ -65,36 +65,7 @@ class AttachmentsController < ApplicationController
|
|||
def download
|
||||
# modify by nwb
|
||||
# 下载添加权限设置
|
||||
candown = false
|
||||
if @attachment.container.class.to_s != "HomeworkAttach" && (@attachment.container.has_attribute?(:project) || @attachment.container.has_attribute?(:project_id)) && @attachment.container.project
|
||||
project = @attachment.container.project
|
||||
candown= User.current.member_of?(project) || (project.is_public && @attachment.is_public == 1)
|
||||
elsif @attachment.container.is_a?(Project)
|
||||
project = @attachment.container
|
||||
candown= User.current.member_of?(project) || (project.is_public && @attachment.is_public == 1)
|
||||
elsif (@attachment.container.has_attribute?(:board) || @attachment.container.has_attribute?(:board_id)) && @attachment.container.board &&
|
||||
@attachment.container.board.project
|
||||
project = @attachment.container.board.project
|
||||
candown = User.current.member_of?(project) || (project.is_public && @attachment.is_public == 1)
|
||||
elsif (@attachment.container.has_attribute?(:course) ||@attachment.container.has_attribute?(:course_id) ) && @attachment.container.course
|
||||
course = @attachment.container.course
|
||||
candown = User.current.member_of_course?(course) || (course.is_public==1 && @attachment.is_public == 1)
|
||||
elsif @attachment.container.is_a?(Course)
|
||||
course = @attachment.container
|
||||
candown= User.current.member_of_course?(course) || (course.is_public==1 && @attachment.is_public == 1)
|
||||
elsif (@attachment.container.has_attribute?(:board) || @attachment.container.has_attribute?(:board_id)) && @attachment.container.board &&
|
||||
@attachment.container.board.course
|
||||
course = @attachment.container.board.course
|
||||
candown= User.current.member_of_course?(course) || (course.is_public==1 && @attachment.is_public == 1)
|
||||
elsif @attachment.container.class.to_s=="HomeworkAttach" && @attachment.container.bid.reward_type == 3
|
||||
candown = true
|
||||
elsif @attachment.container_type == "Bid" && @attachment.container && @attachment.container.courses.first
|
||||
course = @attachment.container.courses.first
|
||||
candown = User.current.member_of_course?(course) || (course.is_public == 1 && @attachment.is_public == 1)
|
||||
else
|
||||
|
||||
candown = @attachment.is_public == 1
|
||||
end
|
||||
candown = attachment_candown @attachment
|
||||
if candown || User.current.admin? || User.current.id == @attachment.author_id
|
||||
@attachment.increment_download
|
||||
if stale?(:etag => @attachment.digest)
|
||||
|
@ -349,6 +320,46 @@ class AttachmentsController < ApplicationController
|
|||
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
|
||||
file = Attachment.find(params[:file_id])
|
||||
courses = params[:courses][:course]
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
class CommentsController < ApplicationController
|
||||
default_search_scope :news
|
||||
include ApplicationHelper
|
||||
model_object News
|
||||
before_filter :find_model_object
|
||||
before_filter :find_project_from_association
|
||||
|
@ -29,6 +30,10 @@ class CommentsController < ApplicationController
|
|||
@comment.safe_attributes = params[:comment]
|
||||
@comment.author = User.current
|
||||
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)
|
||||
end
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
class CoursesController < ApplicationController
|
||||
layout 'base_courses'
|
||||
include CoursesHelper
|
||||
include ActivitiesHelper
|
||||
helper :activities
|
||||
helper :members
|
||||
helper :words
|
||||
|
@ -680,26 +681,49 @@ class CoursesController < ApplicationController
|
|||
"show_course_files" => true,
|
||||
"show_course_news" => true,
|
||||
"show_course_messages" => true,
|
||||
"show_bids" => true,
|
||||
"show_course_journals_for_messages" => true,
|
||||
"show_bids" => true,
|
||||
"show_homeworks" => true
|
||||
}
|
||||
@date_to ||= Date.today + 1
|
||||
@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 ||= @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)
|
||||
if @author.nil?
|
||||
# 显示老师和助教的活动
|
||||
# @authors = searchTeacherAndAssistant(@course)
|
||||
@authors = course_all_member(@course)
|
||||
events = []
|
||||
@authors.each do |author|
|
||||
@activity = Redmine::Activity::Fetcher.new(User.current, :course => @course,
|
||||
:with_subprojects => false,
|
||||
:author => author.user)
|
||||
|
||||
@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
|
||||
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
|
||||
|
||||
# 无新动态时,显示老动态
|
||||
if events.count == 0
|
||||
if User.current.member_of_course?(@course)|| User.current.admin?
|
||||
|
@ -708,13 +732,17 @@ class CoursesController < ApplicationController
|
|||
events = @activity.events(:is_public => 1)
|
||||
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'
|
||||
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)
|
||||
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|
|
||||
format.html{render :layout => 'base_courses'}
|
||||
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)
|
||||
|
||||
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
|
||||
redirect_to document_url(@document)
|
||||
end
|
||||
|
|
|
@ -23,13 +23,14 @@ class FilesController < ApplicationController
|
|||
before_filter :auth_login1, :only => [:index]
|
||||
before_filter :logged_user_by_apptoken,:only => [:index]
|
||||
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
|
||||
include SortHelper
|
||||
include FilesHelper
|
||||
helper :project_score
|
||||
include CoursesHelper
|
||||
include ApplicationHelper
|
||||
|
||||
def show_attachments obj
|
||||
@attachments = []
|
||||
|
@ -41,8 +42,8 @@ class FilesController < ApplicationController
|
|||
@feedback_count = @all_attachments.count
|
||||
@feedback_pages = Paginator.new @feedback_count, @limit, params['page']
|
||||
@offset ||= @feedback_pages.offset
|
||||
@curse_attachments_all = @all_attachments[@offset, @limit]
|
||||
@curse_attachments = paginateHelper @all_attachments,10
|
||||
#@curse_attachments_all = @all_attachments[@offset, @limit]
|
||||
@obj_attachments = paginateHelper @all_attachments,10
|
||||
end
|
||||
|
||||
def search
|
||||
|
@ -78,6 +79,39 @@ class FilesController < ApplicationController
|
|||
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 = ""
|
||||
if sort == ""
|
||||
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")
|
||||
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 = ""
|
||||
# StoresController#search 将每条文件都查出来,再次进行判断过滤。---> resultSet.to_a.map
|
||||
# 此时内容不多速度还可,但文件增长,每条判断多则进行3-4次表连接。
|
||||
|
@ -132,17 +186,27 @@ class FilesController < ApplicationController
|
|||
attribute = "downloads"
|
||||
when "created_on"
|
||||
attribute = "created_on"
|
||||
when "quotes"
|
||||
attribute = "quotes"
|
||||
else
|
||||
attribute = "created_on"
|
||||
end
|
||||
|
||||
if order_by.count == 1
|
||||
sort += "#{Attachment.table_name}.#{attribute} asc " if attribute
|
||||
elsif order_by.count == 2
|
||||
sort += "#{Attachment.table_name}.#{attribute} #{order_by[1]} " if attribute && order_by[1]
|
||||
end
|
||||
if sort_type != params[:sort].split(",").last
|
||||
sort += ","
|
||||
@sort = order_by[0]
|
||||
@order = order_by[1]
|
||||
if order_by.count == 1 && attribute
|
||||
sort += "#{Attachment.table_name}.#{attribute} asc "
|
||||
if sort_type != params[:sort].split(",").last
|
||||
sort += ","
|
||||
end
|
||||
elsif order_by.count == 2 && order_by[1]
|
||||
sort += "#{Attachment.table_name}.#{attribute} #{order_by[1]} "
|
||||
if sort_type != params[:sort].split(",").last
|
||||
sort += ","
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
sort = "#{Attachment.table_name}.created_on desc"
|
||||
end
|
||||
|
||||
@containers = [ Project.includes(:attachments).find(@project.id)]
|
||||
|
@ -184,6 +248,8 @@ class FilesController < ApplicationController
|
|||
attribute = "created_on"
|
||||
when "quotes"
|
||||
attribute = "quotes"
|
||||
else
|
||||
attribute = "created_on"
|
||||
end
|
||||
@sort = order_by[0]
|
||||
@order = order_by[1]
|
||||
|
@ -199,6 +265,8 @@ class FilesController < ApplicationController
|
|||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
sort = "#{Attachment.table_name}.created_on desc"
|
||||
end
|
||||
|
||||
@containers = [ Course.includes(:attachments).reorder(sort).find(@course.id)]
|
||||
|
@ -215,6 +283,11 @@ class FilesController < ApplicationController
|
|||
@can_quote = attachment_candown @file
|
||||
end
|
||||
|
||||
def quote_resource_show_project
|
||||
@file = Attachment.find(params[:id])
|
||||
@can_quote = attachment_candown @file
|
||||
end
|
||||
|
||||
def new
|
||||
@versions = @project.versions.sort
|
||||
@course_tag = @project.project_type
|
||||
|
@ -241,7 +314,7 @@ class FilesController < ApplicationController
|
|||
render_attachment_warning_if_needed(container)
|
||||
|
||||
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
|
||||
|
||||
# TODO: 临时用 nyan
|
||||
|
@ -270,7 +343,7 @@ class FilesController < ApplicationController
|
|||
attachments = Attachment.attach_filesex(@course, params[:attachments], params[:attachment_type])
|
||||
|
||||
if !attachments.empty? && !attachments[:files].blank? && Setting.notified_events.include?('file_added')
|
||||
Mailer.attachments_added(attachments[:files]).deliver
|
||||
Mailer.run.attachments_added(attachments[:files])
|
||||
end
|
||||
|
||||
# TODO: 临时用 nyan
|
||||
|
|
|
@ -63,8 +63,10 @@ class ForumsController < ApplicationController
|
|||
|
||||
respond_to do |format|
|
||||
if @memo.save
|
||||
ids = params[:asset_id].split(',')
|
||||
update_kindeditor_assets_owner ids ,@memo.id,1
|
||||
if params[:asset_id]
|
||||
ids = params[:asset_id].split(',')
|
||||
update_kindeditor_assets_owner ids ,@memo.id,OwnerTypeHelper::MEMO
|
||||
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.json { render json: @memo, status: :created, location: @memo }
|
||||
|
@ -170,8 +172,10 @@ class ForumsController < ApplicationController
|
|||
# Author lizanle
|
||||
# Description after save后需要进行资源记录的更新
|
||||
# owner_type = 2 对应的是 forum
|
||||
ids = params[:asset_id].split(',')
|
||||
update_kindeditor_assets_owner ids ,@forum.id,2
|
||||
if params[:asset_id]
|
||||
ids = params[:asset_id].split(',')
|
||||
update_kindeditor_assets_owner ids ,@forum.id,OwnerTypeHelper::FORUM
|
||||
end
|
||||
#end
|
||||
respond_to do |format|
|
||||
|
||||
|
|
|
@ -86,6 +86,11 @@ class MessagesController < ApplicationController
|
|||
if request.post?
|
||||
@message.save_attachments(params[:attachments])
|
||||
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})
|
||||
render_attachment_warning_if_needed(@message)
|
||||
redirect_to board_message_url(@board, @message)
|
||||
|
@ -117,6 +122,10 @@ class MessagesController < ApplicationController
|
|||
@topic.children << @reply
|
||||
#@topic.update_attribute(:updated_on, Time.now)
|
||||
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})
|
||||
attachments = Attachment.attach_files(@reply, params[:attachments])
|
||||
render_attachment_warning_if_needed(@reply)
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
class NewsController < ApplicationController
|
||||
layout 'base_projects'# by young
|
||||
include ApplicationHelper
|
||||
before_filter :authorize1, :only => [:show]
|
||||
default_search_scope :news
|
||||
model_object News
|
||||
|
@ -136,6 +137,10 @@ class NewsController < ApplicationController
|
|||
@news.safe_attributes = params[:news]
|
||||
@news.save_attachments(params[:attachments])
|
||||
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)
|
||||
flash[:notice] = l(:notice_successful_create)
|
||||
redirect_to course_news_index_url(@course)
|
||||
|
|
|
@ -336,7 +336,7 @@ class ProjectsController < ApplicationController
|
|||
def send_mail_to_member
|
||||
if !params[:mail].blank? && User.find_by_mail(params[:mail].to_s).nil?
|
||||
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
|
||||
flash[:notice] = l(:notice_email_sent, :value => email)
|
||||
else
|
||||
|
|
|
@ -131,7 +131,7 @@ update
|
|||
@project_path=@root_path+"htdocs/"+@repository_name
|
||||
@repository_tag=params[:repository][:upassword] || params[:repository][:password]
|
||||
@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
|
||||
attrs = pickup_extra_info
|
||||
if((@repository_tag!="")&¶ms[:repository_scm]=="Git")
|
||||
|
@ -147,9 +147,9 @@ update
|
|||
@repository.project = @project
|
||||
if request.post? && @repository.save
|
||||
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:"+
|
||||
" "+@repo_name+"' >> "+@root_path+"group.passwd"
|
||||
" "+@repo_name+"' >> "+@root_path+"htdocs/group.passwd"
|
||||
system "mkdir "+@root_path+"htdocs/"+User.current.login.to_s
|
||||
system "git init --bare "+@project_path
|
||||
system "mv "+@project_path+"/hooks/post-update{.sample,}"
|
||||
|
@ -243,8 +243,8 @@ update
|
|||
if(@repository.type=="Repository::Git")
|
||||
logger.info "destory the repository value"+"root path"+@root_path+"repo_name"+@repo_name+
|
||||
"repository_name"+@repository_name+"user group"+@middle
|
||||
system "sed -i /"+@repo_name+"/{d} "+@root_path+"user.passwd"
|
||||
system "sed -i /"+@middle+"/{d} "+@root_path+"group.passwd"
|
||||
system "sed -i /"+@repo_name+"/{d} "+@root_path+"htdocs/user.passwd"
|
||||
system "sed -i /"+@middle+"/{d} "+@root_path+"htdocs/group.passwd"
|
||||
system "rm -r "+@root_path+"htdocs/"+@repository_name
|
||||
# if(@sed_user&&@sed_group&&@remove)
|
||||
# else
|
||||
|
|
|
@ -553,7 +553,7 @@ class UsersController < ApplicationController
|
|||
@user.pref.save
|
||||
@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|
|
||||
format.html {
|
||||
|
@ -620,9 +620,9 @@ class UsersController < ApplicationController
|
|||
@user.notified_project_ids = (@user.mail_notification == 'selected' ? params[:notified_project_ids] : [])
|
||||
|
||||
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?
|
||||
Mailer.account_information(@user, params[:user][:password]).deliver
|
||||
Mailer.run.account_information(@user, params[:user][:password])
|
||||
end
|
||||
|
||||
respond_to do |format|
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# encoding: utf-8
|
||||
#####leave message fq
|
||||
class WordsController < ApplicationController
|
||||
|
||||
include ApplicationHelper
|
||||
before_filter :find_user, :only => [:new, :create, :destroy, :more, :back]
|
||||
def create
|
||||
if params[:new_form][:user_message].size>0
|
||||
|
@ -209,6 +209,10 @@ class WordsController < ApplicationController
|
|||
message = params[:new_form][:course_message]
|
||||
feedback = Course.add_new_jour(user, message, params[:id])
|
||||
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)
|
||||
else
|
||||
flash[:error] = feedback.errors.full_messages[0]
|
||||
|
|
|
@ -5,7 +5,7 @@ class ZipdownController < ApplicationController
|
|||
#检查权限
|
||||
#勿删 before_filter :authorize, :only => [:assort,:download_user_homework]
|
||||
SAVE_FOLDER = "#{Rails.root}/files"
|
||||
OUTPUT_FOLDER = "#{Rails.root}/tmp/archiveZip"
|
||||
OUTPUT_FOLDER = "#{Rails.root}/files/archiveZip"
|
||||
|
||||
#统一下载功能
|
||||
def download
|
||||
|
@ -16,9 +16,11 @@ class ZipdownController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
#一个作业下所有文件打包下载,只有admin和课程老师有权限
|
||||
def assort
|
||||
if params[:obj_class] == "Bid"
|
||||
bid = Bid.find params[:obj_id]
|
||||
render_403 if User.current.allowed_to?(:as_teacher,bid.courses.first)
|
||||
file_count = 0
|
||||
bid.homeworks.map { |homework| file_count += homework.attachments.count}
|
||||
if file_count > 0
|
||||
|
@ -56,9 +58,9 @@ class ZipdownController < ApplicationController
|
|||
if homework != nil
|
||||
unless homework.attachments.empty?
|
||||
zipfile = zip_homework_by_user homework
|
||||
send_file zipfile, :filename => ((homework.user.user_extensions.nil? || homework.user.user_extensions.student_id.nil?) ? "" : homework.user.user_extensions.student_id) +
|
||||
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.name + ".zip", :type => detect_content_type(zipfile) if(zipfile)
|
||||
"_" + homework.name + ".zip", :type => detect_content_type(zipfile.file_path) if(zipfile)
|
||||
else
|
||||
render file: 'public/no_file_found.html'
|
||||
end
|
||||
|
@ -88,85 +90,116 @@ class ZipdownController < ApplicationController
|
|||
def zip_bid(bid)
|
||||
# Todo: User Access Controll
|
||||
bid_homework_path = []
|
||||
digests = []
|
||||
bid.homeworks.each do |homeattach|
|
||||
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
|
||||
|
||||
zips = split_pack_files(bid_homework_path, Setting.pack_attachment_max_size.to_i*1024)
|
||||
x = 0
|
||||
homework_id = bid.id
|
||||
user_id = bid.author_id
|
||||
|
||||
|
||||
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)
|
||||
out_file = find_or_pack(homework_id, user_id, digests.sort){
|
||||
zipping("#{Time.now.to_i}_#{bid.name}.zip",
|
||||
bid_homework_path, OUTPUT_FOLDER)
|
||||
}
|
||||
|
||||
|
||||
# zips = split_pack_files(bid_homework_path, Setting.pack_attachment_max_size.to_i*1024)
|
||||
# x = 0
|
||||
#
|
||||
#
|
||||
# zips.each { |o|
|
||||
# x += 1
|
||||
# file = zipping "#{Time.now.to_i}_#{bid.name}_#{x}.zip", o[:files], OUTPUT_FOLDER
|
||||
# o[:real_file] = file
|
||||
# o[:file] = File.basename(file)
|
||||
# o[:size] = (File.size(file) / 1024.0 / 1024.0).round(2)
|
||||
# }
|
||||
|
||||
[{files:[out_file.file_path], count: 1, index: 1,
|
||||
real_file: out_file.file_path, file: File.basename(out_file.file_path),
|
||||
size:(out_file.pack_size / 1024.0 / 1024.0).round(2)
|
||||
}]
|
||||
end
|
||||
|
||||
def zip_homework_by_user(homework_attach)
|
||||
homeworks_attach_path = []
|
||||
not_exist_file = []
|
||||
# 需要将所有homework.attachments遍历加入zip
|
||||
|
||||
|
||||
digests = []
|
||||
homework_attach.attachments.each do |attach|
|
||||
if File.exist?(attach.diskfile)
|
||||
homeworks_attach_path << attach.diskfile
|
||||
digests << attach.digest
|
||||
else
|
||||
not_exist_file << attach.filename
|
||||
digests << 'not_exist_file'
|
||||
end
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
def zip_homework_by_user(homeattach)
|
||||
homeworks_attach_path = []
|
||||
not_exist_file = []
|
||||
# 需要将所有homework.attachments遍历加入zip
|
||||
# 并且返回zip路径
|
||||
homeattach.attachments.each do |attach|
|
||||
if File.exist?(attach.diskfile)
|
||||
homeworks_attach_path << attach.diskfile
|
||||
else
|
||||
not_exist_file << attach.filename
|
||||
end
|
||||
|
||||
def find_or_pack(homework_id, user_id, digests)
|
||||
raise "please given a pack block" unless block_given?
|
||||
|
||||
out_file = ZipPack.packed?(homework_id, user_id, digests.sort)
|
||||
|
||||
unless out_file && out_file.file_valid?
|
||||
file = yield
|
||||
|
||||
ZipPack.where(homework_id: homework_id,
|
||||
user_id: user_id).delete_all
|
||||
|
||||
out_file = ZipPack.create(homework_id: homework_id,
|
||||
user_id: user_id,
|
||||
file_digest: Trustie::Utils.digest(file),
|
||||
file_path: file,
|
||||
pack_size: File.size(file),
|
||||
file_digests: digests.join(',')
|
||||
)
|
||||
else
|
||||
out_file.pack_times = out_file.pack_times + 1
|
||||
out_file.save
|
||||
end
|
||||
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
|
||||
end
|
||||
|
||||
|
||||
def zipping(zip_name_refer, files_paths, output_path, is_attachment=false, not_exist_file=[])
|
||||
# 输入待打包的文件列表,已经打包文件定位到ouput_path
|
||||
ic = Iconv.new('GBK//IGNORE', 'UTF-8//IGNORE')
|
||||
|
||||
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))
|
||||
|
||||
unless is_attachment
|
||||
#都是zip合并,没必要再费力压缩了
|
||||
Zip.default_compression = Zlib::NO_COMPRESSION
|
||||
else
|
||||
Zip.default_compression = Zlib::DEFAULT_COMPRESSION
|
||||
end
|
||||
|
||||
Zip::File.open(zipfile_name, Zip::File::CREATE) do |zipfile|
|
||||
files_paths.each do |filename|
|
||||
flag = true
|
||||
index = 1
|
||||
rename_file = ic.iconv( (File.basename(filename)) ).to_s
|
||||
rename_file = ic.iconv( filename_to_real( File.basename(filename))).to_s if is_attachment
|
||||
|
||||
rename_file = File.basename(filename)
|
||||
rename_file = filename_to_real( File.basename(filename)) if is_attachment
|
||||
begin
|
||||
zipfile.add(rename_file, filename)
|
||||
flag = false
|
||||
rescue Exception => e
|
||||
zipfile.get_output_stream('FILE_NOTICE.txt') do |os|
|
||||
os.write l(:label_file_exist)
|
||||
end
|
||||
zipfile.get_output_stream('FILE_NOTICE.txt'){|os| os.write l(:label_file_exist)}
|
||||
next
|
||||
end
|
||||
end
|
||||
unless not_exist_file.empty?
|
||||
zipfile.get_output_stream('FILE_LOST.txt') do |os|
|
||||
os.write l(:label_file_lost) + not_exist_file.join(',').to_s
|
||||
end
|
||||
zipfile.get_output_stream('FILE_LOST.txt'){|os| os.write l(:label_file_lost) + not_exist_file.join(',').to_s}
|
||||
end
|
||||
end
|
||||
zipfile_name
|
||||
#rescue Errno => e
|
||||
# logger.error "[zipdown#zipping] ===> #{e}"
|
||||
# @error = e
|
||||
end
|
||||
|
||||
# 合理分配文件打包
|
||||
|
|
|
@ -1,62 +1,62 @@
|
|||
# encoding: utf-8
|
||||
#
|
||||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
module AccountHelper
|
||||
|
||||
def email_activation_register(user, &block)
|
||||
token = Token.new(:user => user, :action => "register")
|
||||
if user.save and token.save
|
||||
UserStatus.create(:user_id => user.id, :changsets_count => 0, :watchers_count => 0)
|
||||
Mailer.register(token).deliver
|
||||
#flash[:notice] = l(:notice_account_register_done)
|
||||
#render action: 'email_valid', locals: {:mail => user.mail}
|
||||
else
|
||||
yield if block_given?
|
||||
end
|
||||
user
|
||||
end
|
||||
|
||||
def automatically_register(user, &block)
|
||||
# Automatic activation
|
||||
user.activate
|
||||
user.last_login_on = Time.now
|
||||
if user.save
|
||||
UserStatus.create(:user_id => user.id, :changsets_count => 0, :watchers_count => 0)
|
||||
#self.logged_user = user
|
||||
#flash[:notice] = l(:notice_account_activated)
|
||||
#redirect_to my_account_url
|
||||
else
|
||||
yield if block_given?
|
||||
end
|
||||
user
|
||||
end
|
||||
|
||||
def administrator_manually__register(user, &block)
|
||||
if user.save
|
||||
UserStatus.create(:user_id => user.id ,:changsets_count => 0, :watchers_count => 0)
|
||||
# Sends an email to the administrators
|
||||
Mailer.account_activation_request(user).deliver
|
||||
#account_pending
|
||||
else
|
||||
yield if block_given?
|
||||
end
|
||||
user
|
||||
end
|
||||
|
||||
end
|
||||
# encoding: utf-8
|
||||
#
|
||||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
module AccountHelper
|
||||
|
||||
def email_activation_register(user, &block)
|
||||
token = Token.new(:user => user, :action => "register")
|
||||
if user.save and token.save
|
||||
UserStatus.create(:user_id => user.id, :changsets_count => 0, :watchers_count => 0)
|
||||
Mailer.run.register(token)
|
||||
#flash[:notice] = l(:notice_account_register_done)
|
||||
#render action: 'email_valid', locals: {:mail => user.mail}
|
||||
else
|
||||
yield if block_given?
|
||||
end
|
||||
user
|
||||
end
|
||||
|
||||
def automatically_register(user, &block)
|
||||
# Automatic activation
|
||||
user.activate
|
||||
user.last_login_on = Time.now
|
||||
if user.save
|
||||
UserStatus.create(:user_id => user.id, :changsets_count => 0, :watchers_count => 0)
|
||||
#self.logged_user = user
|
||||
#flash[:notice] = l(:notice_account_activated)
|
||||
#redirect_to my_account_url
|
||||
else
|
||||
yield if block_given?
|
||||
end
|
||||
user
|
||||
end
|
||||
|
||||
def administrator_manually__register(user, &block)
|
||||
if user.save
|
||||
UserStatus.create(:user_id => user.id ,:changsets_count => 0, :watchers_count => 0)
|
||||
# Sends an email to the administrators
|
||||
Mailer.run.account_activation_request(user)
|
||||
#account_pending
|
||||
else
|
||||
yield if block_given?
|
||||
end
|
||||
user
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -1,33 +1,45 @@
|
|||
# encoding: utf-8
|
||||
#
|
||||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
module ActivitiesHelper
|
||||
def sort_activity_events(events)
|
||||
events_by_group = events.group_by(&:event_group)
|
||||
sorted_events = []
|
||||
events.sort {|x, y| y.event_datetime <=> x.event_datetime}.each do |event|
|
||||
if group_events = events_by_group.delete(event.event_group)
|
||||
group_events.sort {|x, y| y.event_datetime <=> x.event_datetime}.each_with_index do |e, i|
|
||||
sorted_events << [e, i > 0] unless e.event_description.nil?
|
||||
end
|
||||
end
|
||||
end
|
||||
sorted_events
|
||||
end
|
||||
end
|
||||
# encoding: utf-8
|
||||
#
|
||||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
module ActivitiesHelper
|
||||
def sort_activity_events(events)
|
||||
events_by_group = events.group_by(&:event_group)
|
||||
sorted_events = []
|
||||
events.sort {|x, y| y.event_datetime <=> x.event_datetime}.each do |event|
|
||||
if group_events = events_by_group.delete(event.event_group)
|
||||
group_events.sort {|x, y| y.event_datetime <=> x.event_datetime}.each_with_index do |e, i|
|
||||
sorted_events << [e, i > 0] unless e.event_description.nil?
|
||||
end
|
||||
end
|
||||
end
|
||||
sorted_events
|
||||
end
|
||||
def sort_activity_events_course(events)
|
||||
events_by_group = events.group_by(&:event_group)
|
||||
sorted_events = []
|
||||
events.sort {|x, y| y.event_datetime <=> x.event_datetime}.each do |event|
|
||||
if group_events = events_by_group.delete(event.event_group)
|
||||
group_events.sort {|x, y| y.event_datetime <=> x.event_datetime}.each_with_index do |e, i|
|
||||
sorted_events << e unless e.event_description.nil?
|
||||
end
|
||||
end
|
||||
end
|
||||
sorted_events
|
||||
end
|
||||
end
|
||||
|
|
|
@ -53,6 +53,10 @@ module ApplicationHelper
|
|||
# Author lizanle
|
||||
# Description after save后需要进行资源记录的更新
|
||||
# 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
|
||||
ids.each do |id|
|
||||
asset = Kindeditor::Asset.find(id.to_i)
|
||||
|
@ -1676,6 +1680,42 @@ module ApplicationHelper
|
|||
courses_doing
|
||||
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
|
||||
|
||||
def wiki_helper
|
||||
|
|
|
@ -87,6 +87,7 @@ module AttachmentsHelper
|
|||
end
|
||||
end
|
||||
|
||||
#判断课程course中是否包含课件attachment,course中引用了attachment也算作包含
|
||||
def course_contains_attachment? course,attachment
|
||||
course.attachments.each do |att|
|
||||
if att.id == attachment.id || (!att.copy_from.nil? && !attachment.copy_from.nil? && att.copy_from == attachment.copy_from) || att.copy_from == attachment.id || att.id == attachment.copy_from
|
||||
|
@ -95,6 +96,15 @@ module AttachmentsHelper
|
|||
end
|
||||
false
|
||||
end
|
||||
#判断项目project中是否包含课件attachment,project中引用了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
|
||||
if attachment.copy_from
|
||||
|
|
|
@ -632,7 +632,7 @@ module CoursesHelper
|
|||
#获取课程动态
|
||||
def get_course_activity courses, activities
|
||||
@course_ids=activities.keys()
|
||||
|
||||
@bid_ids = []
|
||||
days = Setting.activity_days_default.to_i
|
||||
date_to ||= Date.today + 1
|
||||
date_from = date_to - days-1.years
|
||||
|
@ -653,8 +653,27 @@ module CoursesHelper
|
|||
activities[news.course_id]+=1
|
||||
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 ( 某某创建了该课程 )
|
||||
activities.each_pair { |key, value| activities[key] = value + 1 }
|
||||
# activities.each_pair { |key, value| activities[key] = value + 1 }
|
||||
return activities
|
||||
end
|
||||
|
||||
|
@ -736,4 +755,14 @@ module CoursesHelper
|
|||
"<span class='fr mr10 pr_join_span '>未启用匿评</span>".html_safe
|
||||
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
|
||||
|
|
|
@ -1,157 +1,144 @@
|
|||
# encoding: utf-8
|
||||
module FilesHelper
|
||||
include AttachmentsHelper
|
||||
|
||||
def downloadAll containers
|
||||
paths = []
|
||||
files = []
|
||||
tmpfile = "tmp.zip"
|
||||
|
||||
containers.each do |container|
|
||||
next if container.attachments.empty?
|
||||
if container.is_a?(Version);end
|
||||
container.attachments.each do |attachment|
|
||||
paths << attachment.diskfile
|
||||
file = attachment.diskfile
|
||||
# logger.error "[FilesHelper] downloadAll: #{e}"
|
||||
begin
|
||||
File.new(file, "r")
|
||||
rescue Exception => e
|
||||
logger.error e
|
||||
next
|
||||
end
|
||||
files << file
|
||||
# zip.add(file.path.dup.sub(directory, ''), file.path)
|
||||
end
|
||||
end
|
||||
|
||||
zipfile_name = "archive.zip"
|
||||
if File.exists? File.open(zipfile_name, "w+")
|
||||
ff = File.open(zipfile_name, "w+")
|
||||
ff.close
|
||||
File.delete ff
|
||||
end
|
||||
Zip::ZipFile.open(zipfile_name, Zip::ZipFile::CREATE) do |zipfile|
|
||||
files.each do |filename|
|
||||
directory = File.dirname filename
|
||||
# Two arguments:
|
||||
# - The name of the file as it will appear in the archive
|
||||
# - The original file, including the path to find it
|
||||
dir = filename.sub(directory+"/", '')
|
||||
zipfile.add(dir, filename)
|
||||
|
||||
end
|
||||
end
|
||||
File.new(zipfile_name,'w+')
|
||||
end
|
||||
|
||||
def courses_check_box_tags(name,courses,current_course,attachment)
|
||||
s = ''
|
||||
courses.each do |course|
|
||||
if !course_contains_attachment?(course,attachment) && is_course_teacher(User.current,course) && course_in_current_or_next_term(course)
|
||||
s << "<label>#{ check_box_tag name, course.id, false, :id => nil } #{h course.name}</label> [#{get_course_term course}]<br/>"
|
||||
end
|
||||
end
|
||||
s.html_safe
|
||||
end
|
||||
|
||||
#判断用户是否拥有不包含当前资源的课程,需用户在该课程中角色为教师且该课程属于当前学期或下一学期
|
||||
def has_course? user,file
|
||||
result = false
|
||||
user.courses.each do |course|
|
||||
if !course_contains_attachment?(course,file) && is_course_teacher(User.current,course) && course_in_current_or_next_term(course)
|
||||
return true
|
||||
end
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
# 判断指定的资源时候符合类型
|
||||
def isTypeOk(attachment, type, contentType)
|
||||
result = false
|
||||
if type != 0
|
||||
if attachment.attachtype == type
|
||||
result = true
|
||||
end
|
||||
else
|
||||
result = true
|
||||
end
|
||||
if result
|
||||
if contentType != '0' && contentType != attachment.suffix_type
|
||||
result = false
|
||||
end
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
def visable_attachemnts attachments
|
||||
result = []
|
||||
attachments.each do |attachment|
|
||||
if attachment.is_public? ||
|
||||
(attachment.container_type == "Project" && User.current.member_of?(attachment.project)) ||
|
||||
(attachment.container_type == "Course" && User.current.member_of_course?(Course.find(attachment.container_id)))||
|
||||
attachment.author_id == User.current.id
|
||||
result << attachment
|
||||
end
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
def visable_attachemnts_incourse attachments
|
||||
result = []
|
||||
attachments.each do |attachment|
|
||||
if attachment.is_public? || (attachment.author.member_of_course?(Course.find(attachment.container_id)))|| attachment.author_id == User.current.id
|
||||
result << attachment
|
||||
end
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
def visable_attachemnts_insite attachments,course
|
||||
result = []
|
||||
attachments.each do |attachment|
|
||||
if attachment.is_public? || (attachment.container_type == "Course" && attachment.container_id == course.id && User.current.member_of_course?(Course.find(attachment.container_id)))|| attachment.author_id == User.current.id
|
||||
result << attachment
|
||||
end
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
def attachment_candown attachment
|
||||
candown = false
|
||||
if attachment.container
|
||||
if attachment.container.class.to_s != "HomeworkAttach" && (attachment.container.has_attribute?(:project) || attachment.container.has_attribute?(:project_id)) && attachment.container.project
|
||||
project = attachment.container.project
|
||||
candown= User.current.member_of?(project) || (project.is_public && attachment.is_public == 1)
|
||||
elsif attachment.container.is_a?(Project)
|
||||
project = attachment.container
|
||||
candown= User.current.member_of?(project) || (project.is_public && attachment.is_public == 1)
|
||||
elsif (attachment.container.has_attribute?(:board) || attachment.container.has_attribute?(:board_id)) && attachment.container.board &&
|
||||
attachment.container.board.project
|
||||
project = attachment.container.board.project
|
||||
candown = User.current.member_of?(project) || (project.is_public && attachment.is_public == 1)
|
||||
elsif (attachment.container.has_attribute?(:course) ||attachment.container.has_attribute?(:course_id) ) && attachment.container.course
|
||||
course = attachment.container.course
|
||||
candown = User.current.member_of_course?(course) || (course.is_public==1 && attachment.is_public == 1)
|
||||
elsif attachment.container.is_a?(Course)
|
||||
course = attachment.container
|
||||
candown= User.current.member_of_course?(course) || (course.is_public==1 && attachment.is_public == 1)
|
||||
elsif (attachment.container.has_attribute?(:board) || attachment.container.has_attribute?(:board_id)) && attachment.container.board &&
|
||||
attachment.container.board.course
|
||||
course = attachment.container.board.course
|
||||
candown= User.current.member_of_course?(course) || (course.is_public==1 && attachment.is_public == 1)
|
||||
elsif attachment.container.class.to_s=="HomeworkAttach" && attachment.container.bid.reward_type == 3
|
||||
candown = true
|
||||
elsif attachment.container_type == "Bid" && attachment.container && attachment.container.courses
|
||||
course = attachment.container.courses.first
|
||||
candown = User.current.member_of_course?(attachment.container.courses.first) || (course.is_public == 1 && attachment.is_public == 1)
|
||||
else
|
||||
candown = (attachment.is_public == 1 || attachment.is_public == true)
|
||||
end
|
||||
end
|
||||
candown
|
||||
end
|
||||
|
||||
|
||||
|
||||
# encoding: utf-8
|
||||
module FilesHelper
|
||||
include AttachmentsHelper
|
||||
|
||||
def downloadAll containers
|
||||
paths = []
|
||||
files = []
|
||||
tmpfile = "tmp.zip"
|
||||
|
||||
containers.each do |container|
|
||||
next if container.attachments.empty?
|
||||
if container.is_a?(Version);end
|
||||
container.attachments.each do |attachment|
|
||||
paths << attachment.diskfile
|
||||
file = attachment.diskfile
|
||||
# logger.error "[FilesHelper] downloadAll: #{e}"
|
||||
begin
|
||||
File.new(file, "r")
|
||||
rescue Exception => e
|
||||
logger.error e
|
||||
next
|
||||
end
|
||||
files << file
|
||||
# zip.add(file.path.dup.sub(directory, ''), file.path)
|
||||
end
|
||||
end
|
||||
|
||||
zipfile_name = "archive.zip"
|
||||
if File.exists? File.open(zipfile_name, "w+")
|
||||
ff = File.open(zipfile_name, "w+")
|
||||
ff.close
|
||||
File.delete ff
|
||||
end
|
||||
Zip::ZipFile.open(zipfile_name, Zip::ZipFile::CREATE) do |zipfile|
|
||||
files.each do |filename|
|
||||
directory = File.dirname filename
|
||||
# Two arguments:
|
||||
# - The name of the file as it will appear in the archive
|
||||
# - The original file, including the path to find it
|
||||
dir = filename.sub(directory+"/", '')
|
||||
zipfile.add(dir, filename)
|
||||
|
||||
end
|
||||
end
|
||||
File.new(zipfile_name,'w+')
|
||||
end
|
||||
|
||||
#带勾选框的课程列表
|
||||
def courses_check_box_tags(name,courses,current_course,attachment)
|
||||
s = ''
|
||||
courses.each do |course|
|
||||
if !course_contains_attachment?(course,attachment) && is_course_teacher(User.current,course) && course_in_current_or_next_term(course)
|
||||
s << "<label>#{ check_box_tag name, course.id, false, :id => nil } #{h course.name}</label> [#{get_course_term course}]<br/>"
|
||||
end
|
||||
end
|
||||
s.html_safe
|
||||
end
|
||||
|
||||
#带勾选框的项目列表
|
||||
def projects_check_box_tags(name,projects,current_project,attachment)
|
||||
s = ''
|
||||
projects.each do |project|
|
||||
if !project_contains_attachment?(project,attachment) && User.current.allowed_to?(:manage_files, project)
|
||||
s << "<label>#{ check_box_tag name, project.id, false, :id => nil } #{h project.name}</label>"
|
||||
end
|
||||
end
|
||||
s.html_safe
|
||||
end
|
||||
|
||||
#判断用户是否拥有不包含当前资源的课程,需用户在该课程中角色为教师且该课程属于当前学期或下一学期
|
||||
def has_course? user,file
|
||||
result = false
|
||||
user.courses.each do |course|
|
||||
if !course_contains_attachment?(course,file) && is_course_teacher(User.current,course) && course_in_current_or_next_term(course)
|
||||
return true
|
||||
end
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
#判断用户是否拥有不包含当前资源的项目,需用户在该项目中有资源管理相关资源
|
||||
def has_project? user,file
|
||||
result = false
|
||||
user.projects.each do |project|
|
||||
if !project_contains_attachment?(project,file) && User.current.allowed_to?(:manage_files, project)
|
||||
return true
|
||||
end
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
# 判断指定的资源时候符合类型
|
||||
def isTypeOk(attachment, type, contentType)
|
||||
result = false
|
||||
if type != 0
|
||||
if attachment.attachtype == type
|
||||
result = true
|
||||
end
|
||||
else
|
||||
result = true
|
||||
end
|
||||
if result
|
||||
if contentType != '0' && contentType != attachment.suffix_type
|
||||
result = false
|
||||
end
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
def visable_attachemnts attachments
|
||||
result = []
|
||||
attachments.each do |attachment|
|
||||
if attachment.is_public? ||
|
||||
(attachment.container_type == "Project" && User.current.member_of?(attachment.project)) ||
|
||||
(attachment.container_type == "Course" && User.current.member_of_course?(Course.find(attachment.container_id)))||
|
||||
attachment.author_id == User.current.id
|
||||
result << attachment
|
||||
end
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
def visable_attachemnts_insite attachments,obj
|
||||
result = []
|
||||
if obj.is_a?(Course)
|
||||
attachments.each do |attachment|
|
||||
if attachment.is_public? || (attachment.container_type == "Course" && attachment.container_id == obj.id && User.current.member_of_course?(Course.find(attachment.container_id)))|| attachment.author_id == User.current.id
|
||||
result << attachment
|
||||
end
|
||||
end
|
||||
else if obj.is_a?(Project)
|
||||
attachments.each do |attachment|
|
||||
if attachment.is_public? || (attachment.container_type == "Project" && attachment.container_id == obj.id && User.current.member_of_course?(Project.find(attachment.container_id)))|| attachment.author_id == User.current.id
|
||||
result << attachment
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
|
||||
|
||||
end
|
|
@ -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
|
||||
attr_accessible :author_id, :budget, :deadline, :name, :description, :homework_type, :password
|
||||
include Redmine::SafeAttributes
|
||||
|
||||
include ApplicationHelper
|
||||
has_many_kindeditor_assets :assets, :dependent => :destroy
|
||||
belongs_to :author, :class_name => 'User', :foreign_key => :author_id
|
||||
belongs_to :course
|
||||
has_many :biding_projects, :dependent => :destroy
|
||||
|
@ -47,7 +48,7 @@ class Bid < ActiveRecord::Base
|
|||
validate :validate_user
|
||||
validate :validate_reward_type
|
||||
after_create :act_as_activity
|
||||
|
||||
after_destroy :delete_kindeditor_assets
|
||||
scope :visible, lambda {|*args|
|
||||
nil
|
||||
}
|
||||
|
@ -157,5 +158,10 @@ class Bid < ActiveRecord::Base
|
|||
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
|
||||
|
|
|
@ -17,8 +17,25 @@
|
|||
|
||||
class Comment < ActiveRecord::Base
|
||||
include Redmine::SafeAttributes
|
||||
include ApplicationHelper
|
||||
has_many_kindeditor_assets :assets, :dependent => :destroy
|
||||
belongs_to :commented, :polymorphic => true, :counter_cache => true
|
||||
belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
|
||||
validates_presence_of :commented, :author, :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
|
||||
|
|
|
@ -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
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
class Document < ActiveRecord::Base
|
||||
include Redmine::SafeAttributes
|
||||
belongs_to :project
|
||||
belongs_to :user
|
||||
belongs_to :category, :class_name => "DocumentCategory", :foreign_key => "category_id"
|
||||
include UserScoreHelper
|
||||
after_save :be_user_score # user_score
|
||||
after_destroy :down_user_score
|
||||
acts_as_attachable :delete_permission => :delete_documents
|
||||
# 被ForgeActivity虚拟关联
|
||||
has_many :forge_acts, :class_name => 'ForgeActivity',:as =>:forge_act ,:dependent => :destroy
|
||||
# end
|
||||
acts_as_searchable :columns => ['title', "#{table_name}.description"], :include => :project
|
||||
acts_as_event :title => Proc.new {|o| "#{l(:label_document)}: #{o.title}"},
|
||||
#:author => Proc.new {|o| o.attachments.reorder("#{Attachment.table_name}.created_on ASC").first.try(:author) },
|
||||
:author => Proc.new {|o| User.find(o.user_id)},
|
||||
:url => Proc.new {|o| {:controller => 'documents', :action => 'show', :id => o.id}}
|
||||
acts_as_activity_provider :find_options => {:include => :project},
|
||||
:is_public => 'documents.is_public'
|
||||
|
||||
validates_presence_of :project, :title, :category
|
||||
validates_length_of :title, :maximum => 60
|
||||
after_create :act_as_forge_activity
|
||||
scope :visible, lambda {|*args|
|
||||
includes(:project).where(Project.allowed_to_condition(args.shift || User.current, :view_documents, *args))
|
||||
}
|
||||
|
||||
safe_attributes 'category_id', 'title', 'description','is_public'
|
||||
|
||||
def visible?(user=User.current)
|
||||
!user.nil? && user.allowed_to?(:view_documents, project)
|
||||
end
|
||||
|
||||
def has_right?(project,user=User.current)
|
||||
user.admin? || user.member_of?(project) || self.is_public==1
|
||||
end
|
||||
|
||||
def initialize(attributes=nil, *args)
|
||||
super
|
||||
if new_record?
|
||||
self.category ||= DocumentCategory.default
|
||||
end
|
||||
end
|
||||
|
||||
def updated_on
|
||||
unless @updated_on
|
||||
a = attachments.last
|
||||
@updated_on = (a && a.created_on) || created_on
|
||||
end
|
||||
@updated_on
|
||||
end
|
||||
|
||||
# update user score
|
||||
def be_user_score
|
||||
UserScore.project(:push_document, self.user,self,{ document_id: self.id })
|
||||
update_document(self.user,1)
|
||||
update_document(self.user,2,self.project)
|
||||
end
|
||||
|
||||
def down_user_score
|
||||
update_document(self.user,1)
|
||||
update_document(self.user,2,self.project)
|
||||
end
|
||||
|
||||
# Time 2015-03-02 10:51:16
|
||||
# Author lizanle
|
||||
# Description 新创建的document要在公共表ForgeActivity中记录
|
||||
def act_as_forge_activity
|
||||
self.forge_acts << ForgeActivity.new(:user_id => self.user_id,
|
||||
:project_id => self.project_id)
|
||||
end
|
||||
|
||||
end
|
||||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
class Document < ActiveRecord::Base
|
||||
include Redmine::SafeAttributes
|
||||
belongs_to :project
|
||||
belongs_to :user
|
||||
belongs_to :category, :class_name => "DocumentCategory", :foreign_key => "category_id"
|
||||
include UserScoreHelper
|
||||
after_save :be_user_score # user_score
|
||||
after_destroy :down_user_score
|
||||
acts_as_attachable :delete_permission => :delete_documents
|
||||
after_create :send_mail
|
||||
# 被ForgeActivity虚拟关联
|
||||
has_many :forge_acts, :class_name => 'ForgeActivity',:as =>:forge_act ,:dependent => :destroy
|
||||
# end
|
||||
acts_as_searchable :columns => ['title', "#{table_name}.description"], :include => :project
|
||||
acts_as_event :title => Proc.new {|o| "#{l(:label_document)}: #{o.title}"},
|
||||
#:author => Proc.new {|o| o.attachments.reorder("#{Attachment.table_name}.created_on ASC").first.try(:author) },
|
||||
:author => Proc.new {|o| User.find(o.user_id)},
|
||||
:url => Proc.new {|o| {:controller => 'documents', :action => 'show', :id => o.id}}
|
||||
acts_as_activity_provider :find_options => {:include => :project},
|
||||
:is_public => 'documents.is_public'
|
||||
|
||||
validates_presence_of :project, :title, :category
|
||||
validates_length_of :title, :maximum => 60
|
||||
after_create :act_as_forge_activity
|
||||
scope :visible, lambda {|*args|
|
||||
includes(:project).where(Project.allowed_to_condition(args.shift || User.current, :view_documents, *args))
|
||||
}
|
||||
|
||||
safe_attributes 'category_id', 'title', 'description','is_public'
|
||||
|
||||
def visible?(user=User.current)
|
||||
!user.nil? && user.allowed_to?(:view_documents, project)
|
||||
end
|
||||
|
||||
def has_right?(project,user=User.current)
|
||||
user.admin? || user.member_of?(project) || self.is_public==1
|
||||
end
|
||||
|
||||
def initialize(attributes=nil, *args)
|
||||
super
|
||||
if new_record?
|
||||
self.category ||= DocumentCategory.default
|
||||
end
|
||||
end
|
||||
|
||||
def updated_on
|
||||
unless @updated_on
|
||||
a = attachments.last
|
||||
@updated_on = (a && a.created_on) || created_on
|
||||
end
|
||||
@updated_on
|
||||
end
|
||||
|
||||
# update user score
|
||||
def be_user_score
|
||||
UserScore.project(:push_document, self.user,self,{ document_id: self.id })
|
||||
update_document(self.user,1)
|
||||
update_document(self.user,2,self.project)
|
||||
end
|
||||
|
||||
def down_user_score
|
||||
update_document(self.user,1)
|
||||
update_document(self.user,2,self.project)
|
||||
end
|
||||
|
||||
# Time 2015-03-02 10:51:16
|
||||
# Author lizanle
|
||||
# Description 新创建的document要在公共表ForgeActivity中记录
|
||||
def act_as_forge_activity
|
||||
self.forge_acts << ForgeActivity.new(:user_id => self.user_id,
|
||||
:project_id => self.project_id)
|
||||
end
|
||||
|
||||
def send_mail
|
||||
Mailer.run.document_added(self) if Setting.notified_events.include?('document_added')
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -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
|
||||
include Redmine::SafeAttributes
|
||||
include ApplicationHelper
|
||||
has_many_kindeditor_assets :assets, :dependent => :destroy
|
||||
has_many :topics, :class_name => 'Memo', :conditions => "#{Memo.table_name}.parent_id IS NULL", :order => "#{Memo.table_name}.created_at DESC", :dependent => :destroy
|
||||
has_many :memos, :dependent => :destroy, conditions: "parent_id IS NULL"
|
||||
belongs_to :creator, :class_name => "User", :foreign_key => 'creator_id'
|
||||
safe_attributes 'name',
|
||||
'description',
|
||||
'topic_count',
|
||||
'memo_count',
|
||||
'last_memo_id',
|
||||
'creator_id',
|
||||
'sticky',
|
||||
'locked'
|
||||
validates_presence_of :name, :creator_id, :description
|
||||
validates_length_of :name, maximum: 50
|
||||
#validates_length_of :description, maximum: 255
|
||||
validates :name, :uniqueness => true
|
||||
after_destroy :delete_kindeditor_assets
|
||||
acts_as_taggable
|
||||
scope :by_join_date, order("created_at DESC")
|
||||
#after_create :send_email
|
||||
def reset_counters!
|
||||
self.class.reset_counters!(id)
|
||||
end
|
||||
|
||||
def editable_by? user
|
||||
# user && user.logged? || (self.author == usr && usr.allowed_to?(:edit_own_messages, project))
|
||||
self.creator == user || user.admin?
|
||||
end
|
||||
|
||||
def destroyable_by? user
|
||||
# user && user.logged? && Forum.find(self.forum_id).creator_id == user.id || user.admin?
|
||||
self.creator == user || user.admin?
|
||||
end
|
||||
|
||||
def send_email
|
||||
Thread.start do
|
||||
Mailer.forum_add(self).deliver if Setting.notified_events.include?('forum_add')
|
||||
end
|
||||
end
|
||||
# Updates topic_count, memo_count and last_memo_id attributes for +board_id+
|
||||
def self.reset_counters!(forum_id)
|
||||
forum_id = forum_id.to_i
|
||||
update_all("topic_count = (SELECT COUNT(*) FROM #{Memo.table_name} WHERE forum_id=#{forum_id} AND parent_id IS NULL)," +
|
||||
" memo_count = (SELECT COUNT(*) FROM #{Memo.table_name} WHERE forum_id=#{forum_id} AND parent_id IS NOT NULL)," +
|
||||
" last_memo_id = (SELECT MAX(id) FROM #{Memo.table_name} WHERE forum_id=#{forum_id})",
|
||||
["id = ?", forum_id])
|
||||
end
|
||||
|
||||
# Time 2015-03-26 15:50:54
|
||||
# Author lizanle
|
||||
# Description 删除论坛后删除对应的资源
|
||||
def delete_kindeditor_assets
|
||||
delete_kindeditor_assets_from_disk self.id,2
|
||||
end
|
||||
|
||||
end
|
||||
class Forum < ActiveRecord::Base
|
||||
include Redmine::SafeAttributes
|
||||
include ApplicationHelper
|
||||
has_many_kindeditor_assets :assets, :dependent => :destroy
|
||||
has_many :topics, :class_name => 'Memo', :conditions => "#{Memo.table_name}.parent_id IS NULL", :order => "#{Memo.table_name}.created_at DESC", :dependent => :destroy
|
||||
has_many :memos, :dependent => :destroy, conditions: "parent_id IS NULL"
|
||||
belongs_to :creator, :class_name => "User", :foreign_key => 'creator_id'
|
||||
safe_attributes 'name',
|
||||
'description',
|
||||
'topic_count',
|
||||
'memo_count',
|
||||
'last_memo_id',
|
||||
'creator_id',
|
||||
'sticky',
|
||||
'locked'
|
||||
validates_presence_of :name, :creator_id, :description
|
||||
validates_length_of :name, maximum: 50
|
||||
#validates_length_of :description, maximum: 255
|
||||
validates :name, :uniqueness => true
|
||||
after_destroy :delete_kindeditor_assets
|
||||
acts_as_taggable
|
||||
scope :by_join_date, order("created_at DESC")
|
||||
after_create :send_mail
|
||||
def reset_counters!
|
||||
self.class.reset_counters!(id)
|
||||
end
|
||||
|
||||
def editable_by? user
|
||||
# user && user.logged? || (self.author == usr && usr.allowed_to?(:edit_own_messages, project))
|
||||
self.creator == user || user.admin?
|
||||
end
|
||||
|
||||
def destroyable_by? user
|
||||
# user && user.logged? && Forum.find(self.forum_id).creator_id == user.id || user.admin?
|
||||
self.creator == user || user.admin?
|
||||
end
|
||||
|
||||
def send_mail
|
||||
logger.debug "send mail for forum add."
|
||||
Mailer.run.forum_add(self) if Setting.notified_events.include?('forum_add')
|
||||
end
|
||||
# Updates topic_count, memo_count and last_memo_id attributes for +board_id+
|
||||
def self.reset_counters!(forum_id)
|
||||
forum_id = forum_id.to_i
|
||||
update_all("topic_count = (SELECT COUNT(*) FROM #{Memo.table_name} WHERE forum_id=#{forum_id} AND parent_id IS NULL)," +
|
||||
" memo_count = (SELECT COUNT(*) FROM #{Memo.table_name} WHERE forum_id=#{forum_id} AND parent_id IS NOT NULL)," +
|
||||
" last_memo_id = (SELECT MAX(id) FROM #{Memo.table_name} WHERE forum_id=#{forum_id})",
|
||||
["id = ?", forum_id])
|
||||
end
|
||||
|
||||
# Time 2015-03-26 15:50:54
|
||||
# Author lizanle
|
||||
# Description 删除论坛后删除对应的资源
|
||||
def delete_kindeditor_assets
|
||||
delete_kindeditor_assets_from_disk self.id,OwnerTypeHelper::FORUM
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -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
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
class IssueObserver < ActiveRecord::Observer
|
||||
|
||||
def after_create(issue)
|
||||
Thread.start do
|
||||
# 将跟踪者与本项目的其他成员都设为收件方,并去重,不在进行抄送,
|
||||
recipients = issue.recipients - issue.watcher_recipients + issue.watcher_recipients
|
||||
recipients.each do |rec|
|
||||
Mailer.issue_add(issue,rec).deliver if Setting.notified_events.include?('issue_added')
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
class IssueObserver < ActiveRecord::Observer
|
||||
|
||||
def after_create(issue)
|
||||
# 将跟踪者与本项目的其他成员都设为收件方,并去重,不在进行抄送,
|
||||
recipients = issue.recipients - issue.watcher_recipients + issue.watcher_recipients
|
||||
recipients.each do |rec|
|
||||
Mailer.run.issue_add(issue,rec) if Setting.notified_events.include?('issue_added')
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,36 +1,34 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
class JournalObserver < ActiveRecord::Observer
|
||||
def after_create(journal)
|
||||
if journal.notify? &&
|
||||
(Setting.notified_events.include?('issue_updated') ||
|
||||
(Setting.notified_events.include?('issue_note_added') && journal.notes.present?) ||
|
||||
(Setting.notified_events.include?('issue_status_updated') && journal.new_status.present?) ||
|
||||
(Setting.notified_events.include?('issue_priority_updated') && journal.new_value_for('priority_id').present?)
|
||||
)
|
||||
Thread.start do
|
||||
# 将跟踪者与本项目的其他成员都设为收件方,并去重,不在进行抄送,
|
||||
recipients = journal.recipients - journal.watcher_recipients + journal.watcher_recipients
|
||||
recipients.each do |rec|
|
||||
|
||||
Mailer.issue_edit(journal,rec).deliver
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
class JournalObserver < ActiveRecord::Observer
|
||||
def after_create(journal)
|
||||
if journal.notify? &&
|
||||
(Setting.notified_events.include?('issue_updated') ||
|
||||
(Setting.notified_events.include?('issue_note_added') && journal.notes.present?) ||
|
||||
(Setting.notified_events.include?('issue_status_updated') && journal.new_status.present?) ||
|
||||
(Setting.notified_events.include?('issue_priority_updated') && journal.new_value_for('priority_id').present?)
|
||||
)
|
||||
# 将跟踪者与本项目的其他成员都设为收件方,并去重,不在进行抄送,
|
||||
recipients = journal.recipients - journal.watcher_recipients + journal.watcher_recipients
|
||||
recipients.each do |rec|
|
||||
|
||||
Mailer.run.issue_edit(journal,rec)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,167 +1,174 @@
|
|||
# fq
|
||||
# 数据库字段中带有m前缀和is_readed是二次开发添加,之前的字段基本复用
|
||||
# 注意reply_id 是提到人的id,不是留言id, Base中叫做 at_user
|
||||
class JournalsForMessage < ActiveRecord::Base
|
||||
include Redmine::SafeAttributes
|
||||
include UserScoreHelper
|
||||
safe_attributes "jour_type", # 留言所属类型
|
||||
"jour_id", # 留言所属类型的id
|
||||
"notes", # 留言内容
|
||||
"reply_id", # 留言被回复留言者的用户id(用户a回复了用户b,这是b的id,用以查询谁给b留言了)
|
||||
"status", # 留言是否被查看(弃用)
|
||||
"user_id", # 留言者的id
|
||||
"m_parent_id", # 留言信息的父留言id
|
||||
"is_readed", # 留言是否已读
|
||||
"m_reply_count", # 留言的回复数量
|
||||
"m_reply_id" # 回复某留言的留言id(a留言回复了b留言,这是b留言的id)
|
||||
"is_comprehensive_evaluation" # 1 教师评论、2 匿评、3 留言
|
||||
acts_as_tree :foreign_key => 'm_parent_id', :counter_cache => :m_reply_count, :order => "#{JournalsForMessage.table_name}.created_on ASC"
|
||||
|
||||
belongs_to :project,
|
||||
:foreign_key => 'jour_id',
|
||||
:conditions => "#{self.table_name}.jour_type = 'Project' "
|
||||
belongs_to :course,
|
||||
:foreign_key => 'jour_id'
|
||||
|
||||
|
||||
belongs_to :jour, :polymorphic => true
|
||||
belongs_to :user
|
||||
belongs_to :homework_attach
|
||||
belongs_to :at_user, :class_name => "User", :foreign_key => 'reply_id'
|
||||
|
||||
acts_as_event :title => Proc.new {|o| "#{l(:label_my_message)}"},
|
||||
:datetime => Proc.new {|o| o.updated_on },
|
||||
:author => Proc.new {|o| o.user },
|
||||
:description => Proc.new{|o| o.notes },
|
||||
:type => Proc.new {|o| o.jour_type },
|
||||
:url => Proc.new {|o|
|
||||
if o.jour.kind_of? Project
|
||||
{:controller => 'projects', :action => 'feedback', :id => o.jour, :r => o.id, :anchor => "word_li_#{o.id}"}
|
||||
elsif o.jour.kind_of? Course
|
||||
{:controller => 'courses', :action => 'feedback', :id => o.jour, :r => o.id, :anchor => "word_li_#{o.id}"}
|
||||
end
|
||||
}
|
||||
acts_as_activity_provider :author_key => :user_id,
|
||||
:timestamp => "#{self.table_name}.updated_on",
|
||||
:find_options => {:include => :project }
|
||||
|
||||
acts_as_activity_provider :type => 'course_journals_for_messages',
|
||||
:author_key => :user_id,
|
||||
:timestamp => "#{self.table_name}.updated_on",
|
||||
:find_options => {:include => :course }
|
||||
|
||||
|
||||
has_many :acts, :class_name => 'Activity', :as => :act, :dependent => :destroy
|
||||
|
||||
validates :notes, presence: true
|
||||
after_create :act_as_activity #huang
|
||||
after_create :reset_counters!
|
||||
after_destroy :reset_counters!
|
||||
after_save :be_user_score
|
||||
after_destroy :down_user_score
|
||||
|
||||
# default_scope { where('m_parent_id IS NULL') }
|
||||
|
||||
def self.create_by_user? user
|
||||
if user.anonymous?
|
||||
return false
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def self.remove_by_user? user
|
||||
if( self.user == user ||
|
||||
( self.jour.kind_of?(User) && self.jour== user )
|
||||
)
|
||||
true
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
def self.delete_message(message_id)
|
||||
self.find(message_id).destroy
|
||||
# self.destroy_all "id = #{message_id}"
|
||||
end
|
||||
|
||||
def reference_user
|
||||
User.find(reply_id)
|
||||
end
|
||||
|
||||
def delete_by_user?user
|
||||
# 用户可删除自己的留言
|
||||
if self.user.id == user.id || user.admin?
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
def self.reference_message(user_id)
|
||||
@user = User.find(user_id)
|
||||
message = JournalsForMessage.find_by_sql("select * from journals_for_messages where reply_id = #{@user.id}
|
||||
or (jour_type = 'Bid' and jour_id in (select id from bids where author_id = #{@user.id}))")
|
||||
message
|
||||
end
|
||||
|
||||
def act_as_activity
|
||||
if self.jour_type == 'Principal'
|
||||
unless self.user_id == self.jour.id && self.user_id != self.reply_id && self.reply_id != 0
|
||||
# self.acts << Activity.new(:user_id => self.user_id)
|
||||
self.acts << Activity.new(:user_id => self.jour_id)
|
||||
end
|
||||
elsif self.jour_type == 'Project'
|
||||
self.acts << Activity.new(:user_id => self.reply_id)
|
||||
elsif self.jour_type == 'Course'
|
||||
self.acts << Activity.new(:user_id => self.reply_id)
|
||||
else
|
||||
end
|
||||
end
|
||||
|
||||
def reset_counters!
|
||||
self.class.reset_counters!(self)
|
||||
end
|
||||
def self.reset_counters! journals_for_messages
|
||||
# jfm_id = journals_for_messages.id.to_i
|
||||
count = find_all_by_m_parent_id(journals_for_messages.m_parent_id).count #(SELECT COUNT(*) FROM #{JournalsForMessage.table_name} WHERE m_parent_id = #{jfm_id} )
|
||||
update_all("m_reply_count = #{count.to_i}", ["id = ?", journals_for_messages.m_parent_id])
|
||||
end
|
||||
|
||||
#如果是在项目中留言则返回该项目否则返回nil - zjc
|
||||
def project
|
||||
if self.jour_type == 'Project'
|
||||
Project.find(self.jour_id)
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
# 更新用户分数 -by zjc
|
||||
def be_user_score
|
||||
#新建了留言回复
|
||||
if self.reply_id != 0
|
||||
#协同得分加分
|
||||
UserScore.joint(:reply_message, self.user,User.find(self.reply_id),self, { journals_for_messages_id: self.id })
|
||||
update_replay_for_message(self.user,1)
|
||||
if self.jour_type == "Project"
|
||||
update_replay_for_message(self.user,2,self.jour)
|
||||
end
|
||||
end
|
||||
end
|
||||
# 更新用户分数 -by zjc
|
||||
def down_user_score
|
||||
#删除了留言回复
|
||||
if self.reply_id != 0
|
||||
#协同得分减分
|
||||
UserScore.joint(:reply_message_delete, self.user,User.find(self.reply_id), { journals_for_messages_id: self.id })
|
||||
update_replay_for_message(self.user,1)
|
||||
if self.jour_type == "Project"
|
||||
update_replay_for_message(self.user,2,self.jour)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
# fq
|
||||
# 数据库字段中带有m前缀和is_readed是二次开发添加,之前的字段基本复用
|
||||
# 注意reply_id 是提到人的id,不是留言id, Base中叫做 at_user
|
||||
class JournalsForMessage < ActiveRecord::Base
|
||||
include Redmine::SafeAttributes
|
||||
include UserScoreHelper
|
||||
include ApplicationHelper
|
||||
has_many_kindeditor_assets :assets, :dependent => :destroy
|
||||
safe_attributes "jour_type", # 留言所属类型
|
||||
"jour_id", # 留言所属类型的id
|
||||
"notes", # 留言内容
|
||||
"reply_id", # 留言被回复留言者的用户id(用户a回复了用户b,这是b的id,用以查询谁给b留言了)
|
||||
"status", # 留言是否被查看(弃用)
|
||||
"user_id", # 留言者的id
|
||||
"m_parent_id", # 留言信息的父留言id
|
||||
"is_readed", # 留言是否已读
|
||||
"m_reply_count", # 留言的回复数量
|
||||
"m_reply_id" # 回复某留言的留言id(a留言回复了b留言,这是b留言的id)
|
||||
"is_comprehensive_evaluation" # 1 教师评论、2 匿评、3 留言
|
||||
acts_as_tree :foreign_key => 'm_parent_id', :counter_cache => :m_reply_count, :order => "#{JournalsForMessage.table_name}.created_on ASC"
|
||||
after_destroy :delete_kindeditor_assets
|
||||
belongs_to :project,
|
||||
:foreign_key => 'jour_id',
|
||||
:conditions => "#{self.table_name}.jour_type = 'Project' "
|
||||
belongs_to :course,
|
||||
:foreign_key => 'jour_id'
|
||||
|
||||
|
||||
belongs_to :jour, :polymorphic => true
|
||||
belongs_to :user
|
||||
belongs_to :homework_attach
|
||||
belongs_to :at_user, :class_name => "User", :foreign_key => 'reply_id'
|
||||
|
||||
acts_as_event :title => Proc.new {|o| "#{l(:label_my_message)}"},
|
||||
:datetime => Proc.new {|o| o.updated_on },
|
||||
:author => Proc.new {|o| o.user },
|
||||
:description => Proc.new{|o| o.notes },
|
||||
:type => Proc.new {|o| o.jour_type },
|
||||
:url => Proc.new {|o|
|
||||
if o.jour.kind_of? Project
|
||||
{:controller => 'projects', :action => 'feedback', :id => o.jour, :r => o.id, :anchor => "word_li_#{o.id}"}
|
||||
elsif o.jour.kind_of? Course
|
||||
{:controller => 'courses', :action => 'feedback', :id => o.jour, :r => o.id, :anchor => "word_li_#{o.id}"}
|
||||
end
|
||||
}
|
||||
acts_as_activity_provider :author_key => :user_id,
|
||||
:timestamp => "#{self.table_name}.updated_on",
|
||||
:find_options => {:include => :project }
|
||||
|
||||
acts_as_activity_provider :type => 'course_journals_for_messages',
|
||||
:author_key => :user_id,
|
||||
:timestamp => "#{self.table_name}.updated_on",
|
||||
:find_options => {:include => :course }
|
||||
|
||||
|
||||
has_many :acts, :class_name => 'Activity', :as => :act, :dependent => :destroy
|
||||
|
||||
validates :notes, presence: true
|
||||
after_create :act_as_activity #huang
|
||||
after_create :reset_counters!
|
||||
after_destroy :reset_counters!
|
||||
after_save :be_user_score
|
||||
after_destroy :down_user_score
|
||||
|
||||
# default_scope { where('m_parent_id IS NULL') }
|
||||
|
||||
def self.create_by_user? user
|
||||
if user.anonymous?
|
||||
return false
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def self.remove_by_user? user
|
||||
if( self.user == user ||
|
||||
( self.jour.kind_of?(User) && self.jour== user )
|
||||
)
|
||||
true
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
def self.delete_message(message_id)
|
||||
self.find(message_id).destroy
|
||||
# self.destroy_all "id = #{message_id}"
|
||||
end
|
||||
|
||||
def reference_user
|
||||
User.find(reply_id)
|
||||
end
|
||||
|
||||
def delete_by_user?user
|
||||
# 用户可删除自己的留言
|
||||
if self.user.id == user.id || user.admin?
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
def self.reference_message(user_id)
|
||||
@user = User.find(user_id)
|
||||
message = JournalsForMessage.find_by_sql("select * from journals_for_messages where reply_id = #{@user.id}
|
||||
or (jour_type = 'Bid' and jour_id in (select id from bids where author_id = #{@user.id}))")
|
||||
message
|
||||
end
|
||||
|
||||
def act_as_activity
|
||||
if self.jour_type == 'Principal'
|
||||
unless self.user_id == self.jour.id && self.user_id != self.reply_id && self.reply_id != 0
|
||||
# self.acts << Activity.new(:user_id => self.user_id)
|
||||
self.acts << Activity.new(:user_id => self.jour_id)
|
||||
end
|
||||
elsif self.jour_type == 'Project'
|
||||
self.acts << Activity.new(:user_id => self.reply_id)
|
||||
elsif self.jour_type == 'Course'
|
||||
self.acts << Activity.new(:user_id => self.reply_id)
|
||||
else
|
||||
end
|
||||
end
|
||||
|
||||
def reset_counters!
|
||||
self.class.reset_counters!(self)
|
||||
end
|
||||
def self.reset_counters! journals_for_messages
|
||||
# jfm_id = journals_for_messages.id.to_i
|
||||
count = find_all_by_m_parent_id(journals_for_messages.m_parent_id).count #(SELECT COUNT(*) FROM #{JournalsForMessage.table_name} WHERE m_parent_id = #{jfm_id} )
|
||||
update_all("m_reply_count = #{count.to_i}", ["id = ?", journals_for_messages.m_parent_id])
|
||||
end
|
||||
|
||||
#如果是在项目中留言则返回该项目否则返回nil - zjc
|
||||
def project
|
||||
if self.jour_type == 'Project'
|
||||
Project.find(self.jour_id)
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
# 更新用户分数 -by zjc
|
||||
def be_user_score
|
||||
#新建了留言回复
|
||||
if self.reply_id != 0
|
||||
#协同得分加分
|
||||
UserScore.joint(:reply_message, self.user,User.find(self.reply_id),self, { journals_for_messages_id: self.id })
|
||||
update_replay_for_message(self.user,1)
|
||||
if self.jour_type == "Project"
|
||||
update_replay_for_message(self.user,2,self.jour)
|
||||
end
|
||||
end
|
||||
end
|
||||
# 更新用户分数 -by zjc
|
||||
def down_user_score
|
||||
#删除了留言回复
|
||||
if self.reply_id != 0
|
||||
#协同得分减分
|
||||
UserScore.joint(:reply_message_delete, self.user,User.find(self.reply_id), { journals_for_messages_id: self.id })
|
||||
update_replay_for_message(self.user,1)
|
||||
if self.jour_type == "Project"
|
||||
update_replay_for_message(self.user,2,self.jour)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Time 2015-04-01 14:15:06
|
||||
# Author lizanle
|
||||
# Description 删除对应课程留言的图片资源
|
||||
def delete_kindeditor_assets
|
||||
delete_kindeditor_assets_from_disk self.id,7
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
# Added by young
|
||||
class JournalsForMessageObserver < ActiveRecord::Observer
|
||||
def after_create(journals_for_message)
|
||||
thread1 = Thread.start do
|
||||
Mailer.journals_for_message_add(User.current, journals_for_message).deliver
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Added by young
|
||||
class JournalsForMessageObserver < ActiveRecord::Observer
|
||||
def after_create(journals_for_message)
|
||||
Mailer.run.journals_for_message_add(User.current, journals_for_message)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,490 +1,490 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
class MailHandler < ActionMailer::Base
|
||||
include ActionView::Helpers::SanitizeHelper
|
||||
include Redmine::I18n
|
||||
|
||||
class UnauthorizedAction < StandardError; end
|
||||
class MissingInformation < StandardError; end
|
||||
|
||||
attr_reader :email, :user
|
||||
|
||||
def self.receive(email, options={})
|
||||
@@handler_options = options.dup
|
||||
|
||||
@@handler_options[:issue] ||= {}
|
||||
|
||||
if @@handler_options[:allow_override].is_a?(String)
|
||||
@@handler_options[:allow_override] = @@handler_options[:allow_override].split(',').collect(&:strip)
|
||||
end
|
||||
@@handler_options[:allow_override] ||= []
|
||||
# Project needs to be overridable if not specified
|
||||
@@handler_options[:allow_override] << 'project' unless @@handler_options[:issue].has_key?(:project)
|
||||
# Status overridable by default
|
||||
@@handler_options[:allow_override] << 'status' unless @@handler_options[:issue].has_key?(:status)
|
||||
|
||||
@@handler_options[:no_account_notice] = (@@handler_options[:no_account_notice].to_s == '1')
|
||||
@@handler_options[:no_notification] = (@@handler_options[:no_notification].to_s == '1')
|
||||
@@handler_options[:no_permission_check] = (@@handler_options[:no_permission_check].to_s == '1')
|
||||
|
||||
email.force_encoding('ASCII-8BIT') if email.respond_to?(:force_encoding)
|
||||
super(email)
|
||||
end
|
||||
|
||||
def logger
|
||||
Rails.logger
|
||||
end
|
||||
|
||||
cattr_accessor :ignored_emails_headers
|
||||
@@ignored_emails_headers = {
|
||||
'X-Auto-Response-Suppress' => 'oof',
|
||||
'Auto-Submitted' => /^auto-/
|
||||
}
|
||||
|
||||
# Processes incoming emails
|
||||
# Returns the created object (eg. an issue, a message) or false
|
||||
def receive(email)
|
||||
@email = email
|
||||
sender_email = email.from.to_a.first.to_s.strip
|
||||
# Ignore emails received from the application emission address to avoid hell cycles
|
||||
if sender_email.downcase == Setting.mail_from.to_s.strip.downcase
|
||||
if logger && logger.info
|
||||
logger.info "MailHandler: ignoring email from Redmine emission address [#{sender_email}]"
|
||||
end
|
||||
return false
|
||||
end
|
||||
# Ignore auto generated emails
|
||||
self.class.ignored_emails_headers.each do |key, ignored_value|
|
||||
value = email.header[key]
|
||||
if value
|
||||
value = value.to_s.downcase
|
||||
if (ignored_value.is_a?(Regexp) && value.match(ignored_value)) || value == ignored_value
|
||||
if logger && logger.info
|
||||
logger.info "MailHandler: ignoring email with #{key}:#{value} header"
|
||||
end
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
@user = User.find_by_mail(sender_email) if sender_email.present?
|
||||
if @user && !@user.active?
|
||||
if logger && logger.info
|
||||
logger.info "MailHandler: ignoring email from non-active user [#{@user.login}]"
|
||||
end
|
||||
return false
|
||||
end
|
||||
if @user.nil?
|
||||
# Email was submitted by an unknown user
|
||||
case @@handler_options[:unknown_user]
|
||||
when 'accept'
|
||||
@user = User.anonymous
|
||||
when 'create'
|
||||
@user = create_user_from_email
|
||||
if @user
|
||||
if logger && logger.info
|
||||
logger.info "MailHandler: [#{@user.login}] account created"
|
||||
end
|
||||
add_user_to_group(@@handler_options[:default_group])
|
||||
unless @@handler_options[:no_account_notice]
|
||||
Mailer.account_information(@user, @user.password).deliver
|
||||
end
|
||||
else
|
||||
if logger && logger.error
|
||||
logger.error "MailHandler: could not create account for [#{sender_email}]"
|
||||
end
|
||||
return false
|
||||
end
|
||||
else
|
||||
# Default behaviour, emails from unknown users are ignored
|
||||
if logger && logger.info
|
||||
logger.info "MailHandler: ignoring email from unknown user [#{sender_email}]"
|
||||
end
|
||||
return false
|
||||
end
|
||||
end
|
||||
User.current = @user
|
||||
dispatch
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
MESSAGE_ID_RE = %r{^<?redmine\.([a-z0-9_]+)\-(\d+)\.\d+@}
|
||||
ISSUE_REPLY_SUBJECT_RE = %r{\[[^\]]*#(\d+)\]}
|
||||
MESSAGE_REPLY_SUBJECT_RE = %r{\[[^\]]*msg(\d+)\]}
|
||||
|
||||
def dispatch
|
||||
headers = [email.in_reply_to, email.references].flatten.compact
|
||||
subject = email.subject.to_s
|
||||
if headers.detect {|h| h.to_s =~ MESSAGE_ID_RE}
|
||||
klass, object_id = $1, $2.to_i
|
||||
method_name = "receive_#{klass}_reply"
|
||||
if self.class.private_instance_methods.collect(&:to_s).include?(method_name)
|
||||
send method_name, object_id
|
||||
else
|
||||
# ignoring it
|
||||
end
|
||||
elsif m = subject.match(ISSUE_REPLY_SUBJECT_RE)
|
||||
receive_issue_reply(m[1].to_i)
|
||||
elsif m = subject.match(MESSAGE_REPLY_SUBJECT_RE)
|
||||
receive_message_reply(m[1].to_i)
|
||||
else
|
||||
dispatch_to_default
|
||||
end
|
||||
rescue ActiveRecord::RecordInvalid => e
|
||||
# TODO: send a email to the user
|
||||
logger.error e.message if logger
|
||||
false
|
||||
rescue MissingInformation => e
|
||||
logger.error "MailHandler: missing information from #{user}: #{e.message}" if logger
|
||||
false
|
||||
rescue UnauthorizedAction => e
|
||||
logger.error "MailHandler: unauthorized attempt from #{user}" if logger
|
||||
false
|
||||
end
|
||||
|
||||
def dispatch_to_default
|
||||
receive_issue
|
||||
end
|
||||
|
||||
# Creates a new issue
|
||||
def receive_issue
|
||||
project = target_project
|
||||
# check permission
|
||||
unless @@handler_options[:no_permission_check]
|
||||
raise UnauthorizedAction unless user.allowed_to?(:add_issues, project)
|
||||
end
|
||||
|
||||
issue = Issue.new(:author => user, :project => project)
|
||||
issue.safe_attributes = issue_attributes_from_keywords(issue)
|
||||
issue.safe_attributes = {'custom_field_values' => custom_field_values_from_keywords(issue)}
|
||||
issue.subject = cleaned_up_subject
|
||||
if issue.subject.blank?
|
||||
issue.subject = '(no subject)'
|
||||
end
|
||||
issue.description = cleaned_up_text_body
|
||||
|
||||
# add To and Cc as watchers before saving so the watchers can reply to Redmine
|
||||
add_watchers(issue)
|
||||
issue.save!
|
||||
add_attachments(issue)
|
||||
logger.info "MailHandler: issue ##{issue.id} created by #{user}" if logger && logger.info
|
||||
issue
|
||||
end
|
||||
|
||||
# Adds a note to an existing issue
|
||||
def receive_issue_reply(issue_id, from_journal=nil)
|
||||
issue = Issue.find_by_id(issue_id)
|
||||
return unless issue
|
||||
# check permission
|
||||
unless @@handler_options[:no_permission_check]
|
||||
unless user.allowed_to?(:add_issue_notes, issue.project) ||
|
||||
user.allowed_to?(:edit_issues, issue.project)
|
||||
raise UnauthorizedAction
|
||||
end
|
||||
end
|
||||
|
||||
# ignore CLI-supplied defaults for new issues
|
||||
@@handler_options[:issue].clear
|
||||
|
||||
journal = issue.init_journal(user)
|
||||
if from_journal && from_journal.private_notes?
|
||||
# If the received email was a reply to a private note, make the added note private
|
||||
issue.private_notes = true
|
||||
end
|
||||
issue.safe_attributes = issue_attributes_from_keywords(issue)
|
||||
issue.safe_attributes = {'custom_field_values' => custom_field_values_from_keywords(issue)}
|
||||
journal.notes = cleaned_up_text_body
|
||||
add_attachments(issue)
|
||||
issue.save!
|
||||
if logger && logger.info
|
||||
logger.info "MailHandler: issue ##{issue.id} updated by #{user}"
|
||||
end
|
||||
journal
|
||||
end
|
||||
|
||||
# Reply will be added to the issue
|
||||
def receive_journal_reply(journal_id)
|
||||
journal = Journal.find_by_id(journal_id)
|
||||
if journal && journal.journalized_type == 'Issue'
|
||||
receive_issue_reply(journal.journalized_id, journal)
|
||||
end
|
||||
end
|
||||
|
||||
# Receives a reply to a forum message
|
||||
def receive_message_reply(message_id)
|
||||
message = Message.find_by_id(message_id)
|
||||
if message
|
||||
message = message.root
|
||||
|
||||
unless @@handler_options[:no_permission_check]
|
||||
raise UnauthorizedAction unless user.allowed_to?(:add_messages, message.project)
|
||||
end
|
||||
|
||||
if !message.locked?
|
||||
reply = Message.new(:subject => cleaned_up_subject.gsub(%r{^.*msg\d+\]}, '').strip,
|
||||
:content => cleaned_up_text_body)
|
||||
reply.author = user
|
||||
reply.board = message.board
|
||||
message.children << reply
|
||||
add_attachments(reply)
|
||||
reply
|
||||
else
|
||||
if logger && logger.info
|
||||
logger.info "MailHandler: ignoring reply from [#{sender_email}] to a locked topic"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def add_attachments(obj)
|
||||
if email.attachments && email.attachments.any?
|
||||
email.attachments.each do |attachment|
|
||||
obj.attachments << Attachment.create(:container => obj,
|
||||
:file => attachment.decoded,
|
||||
:filename => attachment.filename,
|
||||
:author => user,
|
||||
:content_type => attachment.mime_type)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Adds To and Cc as watchers of the given object if the sender has the
|
||||
# appropriate permission
|
||||
def add_watchers(obj)
|
||||
if user.allowed_to?("add_#{obj.class.name.underscore}_watchers".to_sym, obj.project)
|
||||
addresses = [email.to, email.cc].flatten.compact.uniq.collect {|a| a.strip.downcase}
|
||||
unless addresses.empty?
|
||||
watchers = User.active.where('LOWER(mail) IN (?)', addresses).all
|
||||
watchers.each {|w| obj.add_watcher(w)}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def get_keyword(attr, options={})
|
||||
@keywords ||= {}
|
||||
if @keywords.has_key?(attr)
|
||||
@keywords[attr]
|
||||
else
|
||||
@keywords[attr] = begin
|
||||
if (options[:override] || @@handler_options[:allow_override].include?(attr.to_s)) &&
|
||||
(v = extract_keyword!(plain_text_body, attr, options[:format]))
|
||||
v
|
||||
elsif !@@handler_options[:issue][attr].blank?
|
||||
@@handler_options[:issue][attr]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Destructively extracts the value for +attr+ in +text+
|
||||
# Returns nil if no matching keyword found
|
||||
def extract_keyword!(text, attr, format=nil)
|
||||
keys = [attr.to_s.humanize]
|
||||
if attr.is_a?(Symbol)
|
||||
if user && user.language.present?
|
||||
keys << l("field_#{attr}", :default => '', :locale => user.language)
|
||||
end
|
||||
if Setting.default_language.present?
|
||||
keys << l("field_#{attr}", :default => '', :locale => Setting.default_language)
|
||||
end
|
||||
end
|
||||
keys.reject! {|k| k.blank?}
|
||||
keys.collect! {|k| Regexp.escape(k)}
|
||||
format ||= '.+'
|
||||
keyword = nil
|
||||
regexp = /^(#{keys.join('|')})[ \t]*:[ \t]*(#{format})\s*$/i
|
||||
if m = text.match(regexp)
|
||||
keyword = m[2].strip
|
||||
text.gsub!(regexp, '')
|
||||
end
|
||||
keyword
|
||||
end
|
||||
|
||||
def target_project
|
||||
# TODO: other ways to specify project:
|
||||
# * parse the email To field
|
||||
# * specific project (eg. Setting.mail_handler_target_project)
|
||||
target = Project.find_by_identifier(get_keyword(:project))
|
||||
raise MissingInformation.new('Unable to determine target project') if target.nil?
|
||||
target
|
||||
end
|
||||
|
||||
# Returns a Hash of issue attributes extracted from keywords in the email body
|
||||
def issue_attributes_from_keywords(issue)
|
||||
assigned_to = (k = get_keyword(:assigned_to, :override => true)) && find_assignee_from_keyword(k, issue)
|
||||
|
||||
attrs = {
|
||||
'tracker_id' => (k = get_keyword(:tracker)) && issue.project.trackers.named(k).first.try(:id),
|
||||
'status_id' => (k = get_keyword(:status)) && IssueStatus.named(k).first.try(:id),
|
||||
'priority_id' => (k = get_keyword(:priority)) && IssuePriority.named(k).first.try(:id),
|
||||
'category_id' => (k = get_keyword(:category)) && issue.project.issue_categories.named(k).first.try(:id),
|
||||
'assigned_to_id' => assigned_to.try(:id),
|
||||
'fixed_version_id' => (k = get_keyword(:fixed_version, :override => true)) &&
|
||||
issue.project.shared_versions.named(k).first.try(:id),
|
||||
'start_date' => get_keyword(:start_date, :override => true, :format => '\d{4}-\d{2}-\d{2}'),
|
||||
'due_date' => get_keyword(:due_date, :override => true, :format => '\d{4}-\d{2}-\d{2}'),
|
||||
'estimated_hours' => get_keyword(:estimated_hours, :override => true),
|
||||
'done_ratio' => get_keyword(:done_ratio, :override => true, :format => '(\d|10)?0')
|
||||
}.delete_if {|k, v| v.blank? }
|
||||
|
||||
if issue.new_record? && attrs['tracker_id'].nil?
|
||||
attrs['tracker_id'] = issue.project.trackers.first.try(:id)
|
||||
end
|
||||
|
||||
attrs
|
||||
end
|
||||
|
||||
# Returns a Hash of issue custom field values extracted from keywords in the email body
|
||||
def custom_field_values_from_keywords(customized)
|
||||
customized.custom_field_values.inject({}) do |h, v|
|
||||
if keyword = get_keyword(v.custom_field.name, :override => true)
|
||||
h[v.custom_field.id.to_s] = v.custom_field.value_from_keyword(keyword, customized)
|
||||
end
|
||||
h
|
||||
end
|
||||
end
|
||||
|
||||
# Returns the text/plain part of the email
|
||||
# If not found (eg. HTML-only email), returns the body with tags removed
|
||||
def plain_text_body
|
||||
return @plain_text_body unless @plain_text_body.nil?
|
||||
|
||||
part = email.text_part || email.html_part || email
|
||||
@plain_text_body = Redmine::CodesetUtil.to_utf8(part.body.decoded, part.charset)
|
||||
|
||||
# strip html tags and remove doctype directive
|
||||
@plain_text_body = strip_tags(@plain_text_body.strip)
|
||||
@plain_text_body.sub! %r{^<!DOCTYPE .*$}, ''
|
||||
@plain_text_body
|
||||
end
|
||||
|
||||
def cleaned_up_text_body
|
||||
cleanup_body(plain_text_body)
|
||||
end
|
||||
|
||||
def cleaned_up_subject
|
||||
subject = email.subject.to_s
|
||||
subject.strip[0,255]
|
||||
end
|
||||
|
||||
def self.full_sanitizer
|
||||
@full_sanitizer ||= HTML::FullSanitizer.new
|
||||
end
|
||||
|
||||
def self.assign_string_attribute_with_limit(object, attribute, value, limit=nil)
|
||||
limit ||= object.class.columns_hash[attribute.to_s].limit || 255
|
||||
value = value.to_s.slice(0, limit)
|
||||
object.send("#{attribute}=", value)
|
||||
end
|
||||
|
||||
# Returns a User from an email address and a full name
|
||||
def self.new_user_from_attributes(email_address, fullname=nil)
|
||||
user = User.new
|
||||
|
||||
# Truncating the email address would result in an invalid format
|
||||
user.mail = email_address
|
||||
assign_string_attribute_with_limit(user, 'login', email_address, User::LOGIN_LENGTH_LIMIT)
|
||||
|
||||
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, 'lastname', names.join(' '), 30)
|
||||
user.lastname = '-' if user.lastname.blank?
|
||||
|
||||
password_length = [Setting.password_min_length.to_i, 10].max
|
||||
user.password = Redmine::Utils.random_hex(password_length / 2 + 1)
|
||||
user.language = Setting.default_language
|
||||
user.mail_notification = 'only_my_events'
|
||||
|
||||
unless user.valid?
|
||||
user.login = "user#{Redmine::Utils.random_hex(6)}" unless user.errors[:login].blank?
|
||||
user.firstname = "-" unless user.errors[:firstname].blank?
|
||||
(puts user.errors[:lastname];user.lastname = "-") unless user.errors[:lastname].blank?
|
||||
end
|
||||
|
||||
user
|
||||
end
|
||||
|
||||
# Creates a User for the +email+ sender
|
||||
# Returns the user or nil if it could not be created
|
||||
def create_user_from_email
|
||||
from = email.header['from'].to_s
|
||||
addr, name = from, nil
|
||||
if m = from.match(/^"?(.+?)"?\s+<(.+@.+)>$/)
|
||||
addr, name = m[2], m[1]
|
||||
end
|
||||
if addr.present?
|
||||
user = self.class.new_user_from_attributes(addr, name)
|
||||
if @@handler_options[:no_notification]
|
||||
user.mail_notification = 'none'
|
||||
end
|
||||
if user.save
|
||||
user
|
||||
else
|
||||
logger.error "MailHandler: failed to create User: #{user.errors.full_messages}" if logger
|
||||
nil
|
||||
end
|
||||
else
|
||||
logger.error "MailHandler: failed to create User: no FROM address found" if logger
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
# Adds the newly created user to default group
|
||||
def add_user_to_group(default_group)
|
||||
if default_group.present?
|
||||
default_group.split(',').each do |group_name|
|
||||
if group = Group.named(group_name).first
|
||||
group.users << @user
|
||||
elsif logger
|
||||
logger.warn "MailHandler: could not add user to [#{group_name}], group not found"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Removes the email body of text after the truncation configurations.
|
||||
def cleanup_body(body)
|
||||
delimiters = Setting.mail_handler_body_delimiters.to_s.split(/[\r\n]+/).reject(&:blank?).map {|s| Regexp.escape(s)}
|
||||
unless delimiters.empty?
|
||||
regex = Regexp.new("^[> ]*(#{ delimiters.join('|') })\s*[\r\n].*", Regexp::MULTILINE)
|
||||
body = body.gsub(regex, '')
|
||||
end
|
||||
body.strip
|
||||
end
|
||||
|
||||
def find_assignee_from_keyword(keyword, issue)
|
||||
keyword = keyword.to_s.downcase
|
||||
assignable = issue.assignable_users
|
||||
assignee = nil
|
||||
assignee ||= assignable.detect {|a|
|
||||
a.mail.to_s.downcase == keyword ||
|
||||
a.login.to_s.downcase == keyword
|
||||
}
|
||||
if assignee.nil? && keyword.match(/ /)
|
||||
firstname, lastname = *(keyword.split) # "First Last Throwaway"
|
||||
assignee ||= assignable.detect {|a|
|
||||
a.is_a?(User) && a.firstname.to_s.downcase == firstname &&
|
||||
a.lastname.to_s.downcase == lastname
|
||||
}
|
||||
end
|
||||
if assignee.nil?
|
||||
assignee ||= assignable.detect {|a| a.name.downcase == keyword}
|
||||
end
|
||||
assignee
|
||||
end
|
||||
end
|
||||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
class MailHandler < ActionMailer::Base
|
||||
include ActionView::Helpers::SanitizeHelper
|
||||
include Redmine::I18n
|
||||
|
||||
class UnauthorizedAction < StandardError; end
|
||||
class MissingInformation < StandardError; end
|
||||
|
||||
attr_reader :email, :user
|
||||
|
||||
def self.receive(email, options={})
|
||||
@@handler_options = options.dup
|
||||
|
||||
@@handler_options[:issue] ||= {}
|
||||
|
||||
if @@handler_options[:allow_override].is_a?(String)
|
||||
@@handler_options[:allow_override] = @@handler_options[:allow_override].split(',').collect(&:strip)
|
||||
end
|
||||
@@handler_options[:allow_override] ||= []
|
||||
# Project needs to be overridable if not specified
|
||||
@@handler_options[:allow_override] << 'project' unless @@handler_options[:issue].has_key?(:project)
|
||||
# Status overridable by default
|
||||
@@handler_options[:allow_override] << 'status' unless @@handler_options[:issue].has_key?(:status)
|
||||
|
||||
@@handler_options[:no_account_notice] = (@@handler_options[:no_account_notice].to_s == '1')
|
||||
@@handler_options[:no_notification] = (@@handler_options[:no_notification].to_s == '1')
|
||||
@@handler_options[:no_permission_check] = (@@handler_options[:no_permission_check].to_s == '1')
|
||||
|
||||
email.force_encoding('ASCII-8BIT') if email.respond_to?(:force_encoding)
|
||||
super(email)
|
||||
end
|
||||
|
||||
def logger
|
||||
Rails.logger
|
||||
end
|
||||
|
||||
cattr_accessor :ignored_emails_headers
|
||||
@@ignored_emails_headers = {
|
||||
'X-Auto-Response-Suppress' => 'oof',
|
||||
'Auto-Submitted' => /^auto-/
|
||||
}
|
||||
|
||||
# Processes incoming emails
|
||||
# Returns the created object (eg. an issue, a message) or false
|
||||
def receive(email)
|
||||
@email = email
|
||||
sender_email = email.from.to_a.first.to_s.strip
|
||||
# Ignore emails received from the application emission address to avoid hell cycles
|
||||
if sender_email.downcase == Setting.mail_from.to_s.strip.downcase
|
||||
if logger && logger.info
|
||||
logger.info "MailHandler: ignoring email from Redmine emission address [#{sender_email}]"
|
||||
end
|
||||
return false
|
||||
end
|
||||
# Ignore auto generated emails
|
||||
self.class.ignored_emails_headers.each do |key, ignored_value|
|
||||
value = email.header[key]
|
||||
if value
|
||||
value = value.to_s.downcase
|
||||
if (ignored_value.is_a?(Regexp) && value.match(ignored_value)) || value == ignored_value
|
||||
if logger && logger.info
|
||||
logger.info "MailHandler: ignoring email with #{key}:#{value} header"
|
||||
end
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
@user = User.find_by_mail(sender_email) if sender_email.present?
|
||||
if @user && !@user.active?
|
||||
if logger && logger.info
|
||||
logger.info "MailHandler: ignoring email from non-active user [#{@user.login}]"
|
||||
end
|
||||
return false
|
||||
end
|
||||
if @user.nil?
|
||||
# Email was submitted by an unknown user
|
||||
case @@handler_options[:unknown_user]
|
||||
when 'accept'
|
||||
@user = User.anonymous
|
||||
when 'create'
|
||||
@user = create_user_from_email
|
||||
if @user
|
||||
if logger && logger.info
|
||||
logger.info "MailHandler: [#{@user.login}] account created"
|
||||
end
|
||||
add_user_to_group(@@handler_options[:default_group])
|
||||
unless @@handler_options[:no_account_notice]
|
||||
Mailer.run.account_information(@user, @user.password)
|
||||
end
|
||||
else
|
||||
if logger && logger.error
|
||||
logger.error "MailHandler: could not create account for [#{sender_email}]"
|
||||
end
|
||||
return false
|
||||
end
|
||||
else
|
||||
# Default behaviour, emails from unknown users are ignored
|
||||
if logger && logger.info
|
||||
logger.info "MailHandler: ignoring email from unknown user [#{sender_email}]"
|
||||
end
|
||||
return false
|
||||
end
|
||||
end
|
||||
User.current = @user
|
||||
dispatch
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
MESSAGE_ID_RE = %r{^<?redmine\.([a-z0-9_]+)\-(\d+)\.\d+@}
|
||||
ISSUE_REPLY_SUBJECT_RE = %r{\[[^\]]*#(\d+)\]}
|
||||
MESSAGE_REPLY_SUBJECT_RE = %r{\[[^\]]*msg(\d+)\]}
|
||||
|
||||
def dispatch
|
||||
headers = [email.in_reply_to, email.references].flatten.compact
|
||||
subject = email.subject.to_s
|
||||
if headers.detect {|h| h.to_s =~ MESSAGE_ID_RE}
|
||||
klass, object_id = $1, $2.to_i
|
||||
method_name = "receive_#{klass}_reply"
|
||||
if self.class.private_instance_methods.collect(&:to_s).include?(method_name)
|
||||
send method_name, object_id
|
||||
else
|
||||
# ignoring it
|
||||
end
|
||||
elsif m = subject.match(ISSUE_REPLY_SUBJECT_RE)
|
||||
receive_issue_reply(m[1].to_i)
|
||||
elsif m = subject.match(MESSAGE_REPLY_SUBJECT_RE)
|
||||
receive_message_reply(m[1].to_i)
|
||||
else
|
||||
dispatch_to_default
|
||||
end
|
||||
rescue ActiveRecord::RecordInvalid => e
|
||||
# TODO: send a email to the user
|
||||
logger.error e.message if logger
|
||||
false
|
||||
rescue MissingInformation => e
|
||||
logger.error "MailHandler: missing information from #{user}: #{e.message}" if logger
|
||||
false
|
||||
rescue UnauthorizedAction => e
|
||||
logger.error "MailHandler: unauthorized attempt from #{user}" if logger
|
||||
false
|
||||
end
|
||||
|
||||
def dispatch_to_default
|
||||
receive_issue
|
||||
end
|
||||
|
||||
# Creates a new issue
|
||||
def receive_issue
|
||||
project = target_project
|
||||
# check permission
|
||||
unless @@handler_options[:no_permission_check]
|
||||
raise UnauthorizedAction unless user.allowed_to?(:add_issues, project)
|
||||
end
|
||||
|
||||
issue = Issue.new(:author => user, :project => project)
|
||||
issue.safe_attributes = issue_attributes_from_keywords(issue)
|
||||
issue.safe_attributes = {'custom_field_values' => custom_field_values_from_keywords(issue)}
|
||||
issue.subject = cleaned_up_subject
|
||||
if issue.subject.blank?
|
||||
issue.subject = '(no subject)'
|
||||
end
|
||||
issue.description = cleaned_up_text_body
|
||||
|
||||
# add To and Cc as watchers before saving so the watchers can reply to Redmine
|
||||
add_watchers(issue)
|
||||
issue.save!
|
||||
add_attachments(issue)
|
||||
logger.info "MailHandler: issue ##{issue.id} created by #{user}" if logger && logger.info
|
||||
issue
|
||||
end
|
||||
|
||||
# Adds a note to an existing issue
|
||||
def receive_issue_reply(issue_id, from_journal=nil)
|
||||
issue = Issue.find_by_id(issue_id)
|
||||
return unless issue
|
||||
# check permission
|
||||
unless @@handler_options[:no_permission_check]
|
||||
unless user.allowed_to?(:add_issue_notes, issue.project) ||
|
||||
user.allowed_to?(:edit_issues, issue.project)
|
||||
raise UnauthorizedAction
|
||||
end
|
||||
end
|
||||
|
||||
# ignore CLI-supplied defaults for new issues
|
||||
@@handler_options[:issue].clear
|
||||
|
||||
journal = issue.init_journal(user)
|
||||
if from_journal && from_journal.private_notes?
|
||||
# If the received email was a reply to a private note, make the added note private
|
||||
issue.private_notes = true
|
||||
end
|
||||
issue.safe_attributes = issue_attributes_from_keywords(issue)
|
||||
issue.safe_attributes = {'custom_field_values' => custom_field_values_from_keywords(issue)}
|
||||
journal.notes = cleaned_up_text_body
|
||||
add_attachments(issue)
|
||||
issue.save!
|
||||
if logger && logger.info
|
||||
logger.info "MailHandler: issue ##{issue.id} updated by #{user}"
|
||||
end
|
||||
journal
|
||||
end
|
||||
|
||||
# Reply will be added to the issue
|
||||
def receive_journal_reply(journal_id)
|
||||
journal = Journal.find_by_id(journal_id)
|
||||
if journal && journal.journalized_type == 'Issue'
|
||||
receive_issue_reply(journal.journalized_id, journal)
|
||||
end
|
||||
end
|
||||
|
||||
# Receives a reply to a forum message
|
||||
def receive_message_reply(message_id)
|
||||
message = Message.find_by_id(message_id)
|
||||
if message
|
||||
message = message.root
|
||||
|
||||
unless @@handler_options[:no_permission_check]
|
||||
raise UnauthorizedAction unless user.allowed_to?(:add_messages, message.project)
|
||||
end
|
||||
|
||||
if !message.locked?
|
||||
reply = Message.new(:subject => cleaned_up_subject.gsub(%r{^.*msg\d+\]}, '').strip,
|
||||
:content => cleaned_up_text_body)
|
||||
reply.author = user
|
||||
reply.board = message.board
|
||||
message.children << reply
|
||||
add_attachments(reply)
|
||||
reply
|
||||
else
|
||||
if logger && logger.info
|
||||
logger.info "MailHandler: ignoring reply from [#{sender_email}] to a locked topic"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def add_attachments(obj)
|
||||
if email.attachments && email.attachments.any?
|
||||
email.attachments.each do |attachment|
|
||||
obj.attachments << Attachment.create(:container => obj,
|
||||
:file => attachment.decoded,
|
||||
:filename => attachment.filename,
|
||||
:author => user,
|
||||
:content_type => attachment.mime_type)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Adds To and Cc as watchers of the given object if the sender has the
|
||||
# appropriate permission
|
||||
def add_watchers(obj)
|
||||
if user.allowed_to?("add_#{obj.class.name.underscore}_watchers".to_sym, obj.project)
|
||||
addresses = [email.to, email.cc].flatten.compact.uniq.collect {|a| a.strip.downcase}
|
||||
unless addresses.empty?
|
||||
watchers = User.active.where('LOWER(mail) IN (?)', addresses).all
|
||||
watchers.each {|w| obj.add_watcher(w)}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def get_keyword(attr, options={})
|
||||
@keywords ||= {}
|
||||
if @keywords.has_key?(attr)
|
||||
@keywords[attr]
|
||||
else
|
||||
@keywords[attr] = begin
|
||||
if (options[:override] || @@handler_options[:allow_override].include?(attr.to_s)) &&
|
||||
(v = extract_keyword!(plain_text_body, attr, options[:format]))
|
||||
v
|
||||
elsif !@@handler_options[:issue][attr].blank?
|
||||
@@handler_options[:issue][attr]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Destructively extracts the value for +attr+ in +text+
|
||||
# Returns nil if no matching keyword found
|
||||
def extract_keyword!(text, attr, format=nil)
|
||||
keys = [attr.to_s.humanize]
|
||||
if attr.is_a?(Symbol)
|
||||
if user && user.language.present?
|
||||
keys << l("field_#{attr}", :default => '', :locale => user.language)
|
||||
end
|
||||
if Setting.default_language.present?
|
||||
keys << l("field_#{attr}", :default => '', :locale => Setting.default_language)
|
||||
end
|
||||
end
|
||||
keys.reject! {|k| k.blank?}
|
||||
keys.collect! {|k| Regexp.escape(k)}
|
||||
format ||= '.+'
|
||||
keyword = nil
|
||||
regexp = /^(#{keys.join('|')})[ \t]*:[ \t]*(#{format})\s*$/i
|
||||
if m = text.match(regexp)
|
||||
keyword = m[2].strip
|
||||
text.gsub!(regexp, '')
|
||||
end
|
||||
keyword
|
||||
end
|
||||
|
||||
def target_project
|
||||
# TODO: other ways to specify project:
|
||||
# * parse the email To field
|
||||
# * specific project (eg. Setting.mail_handler_target_project)
|
||||
target = Project.find_by_identifier(get_keyword(:project))
|
||||
raise MissingInformation.new('Unable to determine target project') if target.nil?
|
||||
target
|
||||
end
|
||||
|
||||
# Returns a Hash of issue attributes extracted from keywords in the email body
|
||||
def issue_attributes_from_keywords(issue)
|
||||
assigned_to = (k = get_keyword(:assigned_to, :override => true)) && find_assignee_from_keyword(k, issue)
|
||||
|
||||
attrs = {
|
||||
'tracker_id' => (k = get_keyword(:tracker)) && issue.project.trackers.named(k).first.try(:id),
|
||||
'status_id' => (k = get_keyword(:status)) && IssueStatus.named(k).first.try(:id),
|
||||
'priority_id' => (k = get_keyword(:priority)) && IssuePriority.named(k).first.try(:id),
|
||||
'category_id' => (k = get_keyword(:category)) && issue.project.issue_categories.named(k).first.try(:id),
|
||||
'assigned_to_id' => assigned_to.try(:id),
|
||||
'fixed_version_id' => (k = get_keyword(:fixed_version, :override => true)) &&
|
||||
issue.project.shared_versions.named(k).first.try(:id),
|
||||
'start_date' => get_keyword(:start_date, :override => true, :format => '\d{4}-\d{2}-\d{2}'),
|
||||
'due_date' => get_keyword(:due_date, :override => true, :format => '\d{4}-\d{2}-\d{2}'),
|
||||
'estimated_hours' => get_keyword(:estimated_hours, :override => true),
|
||||
'done_ratio' => get_keyword(:done_ratio, :override => true, :format => '(\d|10)?0')
|
||||
}.delete_if {|k, v| v.blank? }
|
||||
|
||||
if issue.new_record? && attrs['tracker_id'].nil?
|
||||
attrs['tracker_id'] = issue.project.trackers.first.try(:id)
|
||||
end
|
||||
|
||||
attrs
|
||||
end
|
||||
|
||||
# Returns a Hash of issue custom field values extracted from keywords in the email body
|
||||
def custom_field_values_from_keywords(customized)
|
||||
customized.custom_field_values.inject({}) do |h, v|
|
||||
if keyword = get_keyword(v.custom_field.name, :override => true)
|
||||
h[v.custom_field.id.to_s] = v.custom_field.value_from_keyword(keyword, customized)
|
||||
end
|
||||
h
|
||||
end
|
||||
end
|
||||
|
||||
# Returns the text/plain part of the email
|
||||
# If not found (eg. HTML-only email), returns the body with tags removed
|
||||
def plain_text_body
|
||||
return @plain_text_body unless @plain_text_body.nil?
|
||||
|
||||
part = email.text_part || email.html_part || email
|
||||
@plain_text_body = Redmine::CodesetUtil.to_utf8(part.body.decoded, part.charset)
|
||||
|
||||
# strip html tags and remove doctype directive
|
||||
@plain_text_body = strip_tags(@plain_text_body.strip)
|
||||
@plain_text_body.sub! %r{^<!DOCTYPE .*$}, ''
|
||||
@plain_text_body
|
||||
end
|
||||
|
||||
def cleaned_up_text_body
|
||||
cleanup_body(plain_text_body)
|
||||
end
|
||||
|
||||
def cleaned_up_subject
|
||||
subject = email.subject.to_s
|
||||
subject.strip[0,255]
|
||||
end
|
||||
|
||||
def self.full_sanitizer
|
||||
@full_sanitizer ||= HTML::FullSanitizer.new
|
||||
end
|
||||
|
||||
def self.assign_string_attribute_with_limit(object, attribute, value, limit=nil)
|
||||
limit ||= object.class.columns_hash[attribute.to_s].limit || 255
|
||||
value = value.to_s.slice(0, limit)
|
||||
object.send("#{attribute}=", value)
|
||||
end
|
||||
|
||||
# Returns a User from an email address and a full name
|
||||
def self.new_user_from_attributes(email_address, fullname=nil)
|
||||
user = User.new
|
||||
|
||||
# Truncating the email address would result in an invalid format
|
||||
user.mail = email_address
|
||||
assign_string_attribute_with_limit(user, 'login', email_address, User::LOGIN_LENGTH_LIMIT)
|
||||
|
||||
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, 'lastname', names.join(' '), 30)
|
||||
user.lastname = '-' if user.lastname.blank?
|
||||
|
||||
password_length = [Setting.password_min_length.to_i, 10].max
|
||||
user.password = Redmine::Utils.random_hex(password_length / 2 + 1)
|
||||
user.language = Setting.default_language
|
||||
user.mail_notification = 'only_my_events'
|
||||
|
||||
unless user.valid?
|
||||
user.login = "user#{Redmine::Utils.random_hex(6)}" unless user.errors[:login].blank?
|
||||
user.firstname = "-" unless user.errors[:firstname].blank?
|
||||
(puts user.errors[:lastname];user.lastname = "-") unless user.errors[:lastname].blank?
|
||||
end
|
||||
|
||||
user
|
||||
end
|
||||
|
||||
# Creates a User for the +email+ sender
|
||||
# Returns the user or nil if it could not be created
|
||||
def create_user_from_email
|
||||
from = email.header['from'].to_s
|
||||
addr, name = from, nil
|
||||
if m = from.match(/^"?(.+?)"?\s+<(.+@.+)>$/)
|
||||
addr, name = m[2], m[1]
|
||||
end
|
||||
if addr.present?
|
||||
user = self.class.new_user_from_attributes(addr, name)
|
||||
if @@handler_options[:no_notification]
|
||||
user.mail_notification = 'none'
|
||||
end
|
||||
if user.save
|
||||
user
|
||||
else
|
||||
logger.error "MailHandler: failed to create User: #{user.errors.full_messages}" if logger
|
||||
nil
|
||||
end
|
||||
else
|
||||
logger.error "MailHandler: failed to create User: no FROM address found" if logger
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
# Adds the newly created user to default group
|
||||
def add_user_to_group(default_group)
|
||||
if default_group.present?
|
||||
default_group.split(',').each do |group_name|
|
||||
if group = Group.named(group_name).first
|
||||
group.users << @user
|
||||
elsif logger
|
||||
logger.warn "MailHandler: could not add user to [#{group_name}], group not found"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Removes the email body of text after the truncation configurations.
|
||||
def cleanup_body(body)
|
||||
delimiters = Setting.mail_handler_body_delimiters.to_s.split(/[\r\n]+/).reject(&:blank?).map {|s| Regexp.escape(s)}
|
||||
unless delimiters.empty?
|
||||
regex = Regexp.new("^[> ]*(#{ delimiters.join('|') })\s*[\r\n].*", Regexp::MULTILINE)
|
||||
body = body.gsub(regex, '')
|
||||
end
|
||||
body.strip
|
||||
end
|
||||
|
||||
def find_assignee_from_keyword(keyword, issue)
|
||||
keyword = keyword.to_s.downcase
|
||||
assignable = issue.assignable_users
|
||||
assignee = nil
|
||||
assignee ||= assignable.detect {|a|
|
||||
a.mail.to_s.downcase == keyword ||
|
||||
a.login.to_s.downcase == keyword
|
||||
}
|
||||
if assignee.nil? && keyword.match(/ /)
|
||||
firstname, lastname = *(keyword.split) # "First Last Throwaway"
|
||||
assignee ||= assignable.detect {|a|
|
||||
a.is_a?(User) && a.firstname.to_s.downcase == firstname &&
|
||||
a.lastname.to_s.downcase == lastname
|
||||
}
|
||||
end
|
||||
if assignee.nil?
|
||||
assignee ||= assignable.detect {|a| a.name.downcase == keyword}
|
||||
end
|
||||
assignee
|
||||
end
|
||||
end
|
||||
|
|
1762
app/models/mailer.rb
1762
app/models/mailer.rb
File diff suppressed because it is too large
Load Diff
|
@ -1,181 +1,179 @@
|
|||
class Memo < ActiveRecord::Base
|
||||
include Redmine::SafeAttributes
|
||||
include UserScoreHelper
|
||||
include ApplicationHelper
|
||||
belongs_to :forum
|
||||
has_many_kindeditor_assets :assets, :dependent => :destroy
|
||||
belongs_to :author, :class_name => "User", :foreign_key => 'author_id'
|
||||
validates_presence_of :author_id, :forum_id, :subject,:content
|
||||
# 若是主题帖,则内容可以是空
|
||||
#validates :content, presence: true, if: Proc.new{|o| !o.parent_id.nil? }
|
||||
validates_length_of :subject, maximum: 50
|
||||
#validates_length_of :content, maximum: 3072
|
||||
validate :cannot_reply_to_locked_topic, :on => :create
|
||||
|
||||
acts_as_tree :counter_cache => :replies_count, :order => "#{Memo.table_name}.created_at ASC"
|
||||
acts_as_attachable
|
||||
has_many :user_score_details, :class_name => 'UserScoreDetails',:as => :score_changeable_obj
|
||||
has_many :praise_tread, as: :praise_tread_object, dependent: :destroy
|
||||
belongs_to :last_reply, :class_name => 'Memo', :foreign_key => 'last_reply_id'
|
||||
# acts_as_searchable :column => ['subject', 'content'],
|
||||
# #:include => { :forum => :p}
|
||||
# #:project_key => "#{Forum.table_name}.project_id"
|
||||
# :date_column => "#{table_name}.created_at"
|
||||
acts_as_event :title => Proc.new {|o| "#{o.forum.name}: #{o.subject}"},
|
||||
:datetime => :updated_at,
|
||||
# :datetime => :created_at,
|
||||
:description => :content,
|
||||
:author => :author,
|
||||
:type => Proc.new {|o| o.parent_id.nil? ? 'Memo' : 'Reply'},
|
||||
:url => Proc.new {|o| {:controller => 'memos', :action => 'show', :forum_id => o.forum_id}.merge(o.parent_id.nil? ? {:id => o.id} : {:id => o.parent_id, :r => o.id, :anchor => "reply-#{o.id}"})}
|
||||
acts_as_activity_provider :author_key => :author_id,
|
||||
:func => 'memos',
|
||||
:timestamp => 'created_at'
|
||||
# :find_options => {:type => 'memos'}
|
||||
# acts_as_watchable
|
||||
|
||||
safe_attributes "author_id",
|
||||
"subject",
|
||||
"content",
|
||||
"forum_id",
|
||||
"last_memo_id",
|
||||
"lock",
|
||||
"sticky",
|
||||
"parent_id",
|
||||
"replies_count"
|
||||
|
||||
after_create :add_author_as_watcher, :reset_counters!, :sendmail
|
||||
# after_update :update_memos_forum
|
||||
after_destroy :reset_counters!,:delete_kindeditor_assets#,:down_user_score -- 公共区发帖暂不计入得分
|
||||
# after_create :send_notification
|
||||
# after_save :plusParentAndForum
|
||||
# after_destroy :minusParentAndForum
|
||||
#before_save :be_user_score
|
||||
# scope :visible, lambda { |*args|
|
||||
# includes(:forum => ).where()
|
||||
# }
|
||||
|
||||
def sendmail
|
||||
thread1=Thread.new do
|
||||
Mailer.forum_message_added(self).deliver if Setting.notified_events.include?('forum_message_added')
|
||||
end
|
||||
end
|
||||
|
||||
def cannot_reply_to_locked_topic
|
||||
errors.add :base, l(:label_memo_locked) if root.locked? && self != root
|
||||
end
|
||||
|
||||
# def update_memos_forum
|
||||
# if forum_id_changed?
|
||||
# Message.update_all({:board_id => board_id}, ["id = ? OR parent_id = ?", root.id, root.id ])
|
||||
# Forum.reset_counters!(forum_id_was)
|
||||
# Forum.reset_counters!(forum_id)
|
||||
# end
|
||||
# end
|
||||
|
||||
def reset_counters!
|
||||
if parent && parent.id
|
||||
Memo.update_all({:last_reply_id => parent.children.maximum(:id)}, {:id => parent.id})
|
||||
parent.update_attribute(:updated_at, Time.now)
|
||||
end
|
||||
forum.reset_counters!
|
||||
end
|
||||
|
||||
def sticky?
|
||||
sticky == 1
|
||||
end
|
||||
|
||||
def replies
|
||||
Memo.where("parent_id = ?", id)
|
||||
end
|
||||
|
||||
def locked?
|
||||
self.lock
|
||||
end
|
||||
|
||||
def editable_by? user
|
||||
# user && user.logged? || (self.author == usr && usr.allowed_to?(:edit_own_messages, project))
|
||||
user.admin? || self.author == user
|
||||
end
|
||||
|
||||
def destroyable_by? user
|
||||
(user && self.author == user) || user.admin?
|
||||
#self.author == user || user.admin?
|
||||
end
|
||||
|
||||
def deleted_attach_able_by? user
|
||||
(user && user.logged? && (self.author == user) ) || user.admin?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def add_author_as_watcher
|
||||
Watcher.create(:watchable => self.root, :user => author)
|
||||
end
|
||||
|
||||
def send_notification
|
||||
if Setting.notified_events.include?('message_posted')
|
||||
Mailer.message_posted(self).deliver
|
||||
end
|
||||
end
|
||||
|
||||
def plusParentAndForum
|
||||
@forum = Forum.find(self.forum_id)
|
||||
@forum.memo_count = @forum.memo_count.to_int + 1
|
||||
@forum.last_memo_id = self.id
|
||||
if self.parent_id
|
||||
@parent_memo = Memo.find_by_id(self.parent_id)
|
||||
@parent_memo.last_reply_id = self
|
||||
@parent_memo.replies_count = @parent_memo.replies_count.to_int + 1
|
||||
@parent_memo.save
|
||||
else
|
||||
@forum.topic_count = @forum.topic_count.to_int + 1
|
||||
end
|
||||
@forum.save
|
||||
end
|
||||
|
||||
def minusParentAndForum
|
||||
@forum = Forum.find(self.forum_id)
|
||||
@forum.memo_count = @forum.memo_count.to_int - 1
|
||||
@forum.memo_count = 0 if @forum.memo_count.to_int < 0
|
||||
# @forum.last_memo_id = Memo.reorder('created_at ASC').find_all_by_forum_id(self.forum_id).last.id
|
||||
if self.parent_id
|
||||
@parent_memo = Memo.find_by_id(self.parent_id)
|
||||
# @parent_memo.last_reply_id = Memo.reorder('created_at ASC').find_all_by_parent_id(self.parent_id).last.id
|
||||
@parent_memo.replies_count = @parent_memo.replies_count.to_int - 1
|
||||
@parent_memo.replies_count = 0 if @parent_memo.replies_count.to_int < 0
|
||||
@parent_memo.save
|
||||
else
|
||||
@forum.topic_count = @forum.topic_count.to_int - 1
|
||||
@forum.topic_count = 0 if @forum.topic_count.to_int < 0
|
||||
end
|
||||
@forum.save
|
||||
end
|
||||
|
||||
#更新用户分数 -by zjc
|
||||
def be_user_score
|
||||
#新建memo且无parent的为发帖
|
||||
if self.parent_id.nil?
|
||||
UserScore.joint(:post_message, User.current,nil,self ,{ memo_id: self.id })
|
||||
update_memo_number(User.current,1)
|
||||
|
||||
#新建memo且有parent的为回帖
|
||||
elsif !self.parent_id.nil?
|
||||
UserScore.joint(:reply_posting, User.current,self.parent.author,self, { memo_id: self.id })
|
||||
update_replay_for_memo(User.current,1)
|
||||
end
|
||||
end
|
||||
|
||||
#被删除时更新用户分数
|
||||
def down_user_score
|
||||
update_memo_number(User.current,1)
|
||||
update_replay_for_memo(User.current,1)
|
||||
end
|
||||
|
||||
# Time 2015-03-26 15:20:24
|
||||
# Author lizanle
|
||||
# Description 从硬盘上删除资源
|
||||
def delete_kindeditor_assets
|
||||
delete_kindeditor_assets_from_disk self.id,1
|
||||
end
|
||||
end
|
||||
class Memo < ActiveRecord::Base
|
||||
include Redmine::SafeAttributes
|
||||
include UserScoreHelper
|
||||
include ApplicationHelper
|
||||
belongs_to :forum
|
||||
has_many_kindeditor_assets :assets, :dependent => :destroy
|
||||
belongs_to :author, :class_name => "User", :foreign_key => 'author_id'
|
||||
validates_presence_of :author_id, :forum_id, :subject,:content
|
||||
# 若是主题帖,则内容可以是空
|
||||
#validates :content, presence: true, if: Proc.new{|o| !o.parent_id.nil? }
|
||||
validates_length_of :subject, maximum: 50
|
||||
#validates_length_of :content, maximum: 3072
|
||||
validate :cannot_reply_to_locked_topic, :on => :create
|
||||
|
||||
acts_as_tree :counter_cache => :replies_count, :order => "#{Memo.table_name}.created_at ASC"
|
||||
acts_as_attachable
|
||||
has_many :user_score_details, :class_name => 'UserScoreDetails',:as => :score_changeable_obj
|
||||
has_many :praise_tread, as: :praise_tread_object, dependent: :destroy
|
||||
belongs_to :last_reply, :class_name => 'Memo', :foreign_key => 'last_reply_id'
|
||||
# acts_as_searchable :column => ['subject', 'content'],
|
||||
# #:include => { :forum => :p}
|
||||
# #:project_key => "#{Forum.table_name}.project_id"
|
||||
# :date_column => "#{table_name}.created_at"
|
||||
acts_as_event :title => Proc.new {|o| "#{o.forum.name}: #{o.subject}"},
|
||||
:datetime => :updated_at,
|
||||
# :datetime => :created_at,
|
||||
:description => :content,
|
||||
:author => :author,
|
||||
:type => Proc.new {|o| o.parent_id.nil? ? 'Memo' : 'Reply'},
|
||||
:url => Proc.new {|o| {:controller => 'memos', :action => 'show', :forum_id => o.forum_id}.merge(o.parent_id.nil? ? {:id => o.id} : {:id => o.parent_id, :r => o.id, :anchor => "reply-#{o.id}"})}
|
||||
acts_as_activity_provider :author_key => :author_id,
|
||||
:func => 'memos',
|
||||
:timestamp => 'created_at'
|
||||
# :find_options => {:type => 'memos'}
|
||||
# acts_as_watchable
|
||||
|
||||
safe_attributes "author_id",
|
||||
"subject",
|
||||
"content",
|
||||
"forum_id",
|
||||
"last_memo_id",
|
||||
"lock",
|
||||
"sticky",
|
||||
"parent_id",
|
||||
"replies_count"
|
||||
|
||||
after_create :add_author_as_watcher, :reset_counters!, :send_mail
|
||||
# after_update :update_memos_forum
|
||||
after_destroy :reset_counters!,:delete_kindeditor_assets#,:down_user_score -- 公共区发帖暂不计入得分
|
||||
# after_create :send_notification
|
||||
# after_save :plusParentAndForum
|
||||
# after_destroy :minusParentAndForum
|
||||
#before_save :be_user_score
|
||||
# scope :visible, lambda { |*args|
|
||||
# includes(:forum => ).where()
|
||||
# }
|
||||
|
||||
def send_mail
|
||||
Mailer.run.forum_message_added(self) if Setting.notified_events.include?('forum_message_added')
|
||||
end
|
||||
|
||||
def cannot_reply_to_locked_topic
|
||||
errors.add :base, l(:label_memo_locked) if root.locked? && self != root
|
||||
end
|
||||
|
||||
# def update_memos_forum
|
||||
# if forum_id_changed?
|
||||
# Message.update_all({:board_id => board_id}, ["id = ? OR parent_id = ?", root.id, root.id ])
|
||||
# Forum.reset_counters!(forum_id_was)
|
||||
# Forum.reset_counters!(forum_id)
|
||||
# end
|
||||
# end
|
||||
|
||||
def reset_counters!
|
||||
if parent && parent.id
|
||||
Memo.update_all({:last_reply_id => parent.children.maximum(:id)}, {:id => parent.id})
|
||||
parent.update_attribute(:updated_at, Time.now)
|
||||
end
|
||||
forum.reset_counters!
|
||||
end
|
||||
|
||||
def sticky?
|
||||
sticky == 1
|
||||
end
|
||||
|
||||
def replies
|
||||
Memo.where("parent_id = ?", id)
|
||||
end
|
||||
|
||||
def locked?
|
||||
self.lock
|
||||
end
|
||||
|
||||
def editable_by? user
|
||||
# user && user.logged? || (self.author == usr && usr.allowed_to?(:edit_own_messages, project))
|
||||
user.admin? || self.author == user
|
||||
end
|
||||
|
||||
def destroyable_by? user
|
||||
(user && self.author == user) || user.admin?
|
||||
#self.author == user || user.admin?
|
||||
end
|
||||
|
||||
def deleted_attach_able_by? user
|
||||
(user && user.logged? && (self.author == user) ) || user.admin?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def add_author_as_watcher
|
||||
Watcher.create(:watchable => self.root, :user => author)
|
||||
end
|
||||
|
||||
def send_notification
|
||||
if Setting.notified_events.include?('message_posted')
|
||||
Mailer.run.message_posted(self)
|
||||
end
|
||||
end
|
||||
|
||||
def plusParentAndForum
|
||||
@forum = Forum.find(self.forum_id)
|
||||
@forum.memo_count = @forum.memo_count.to_int + 1
|
||||
@forum.last_memo_id = self.id
|
||||
if self.parent_id
|
||||
@parent_memo = Memo.find_by_id(self.parent_id)
|
||||
@parent_memo.last_reply_id = self
|
||||
@parent_memo.replies_count = @parent_memo.replies_count.to_int + 1
|
||||
@parent_memo.save
|
||||
else
|
||||
@forum.topic_count = @forum.topic_count.to_int + 1
|
||||
end
|
||||
@forum.save
|
||||
end
|
||||
|
||||
def minusParentAndForum
|
||||
@forum = Forum.find(self.forum_id)
|
||||
@forum.memo_count = @forum.memo_count.to_int - 1
|
||||
@forum.memo_count = 0 if @forum.memo_count.to_int < 0
|
||||
# @forum.last_memo_id = Memo.reorder('created_at ASC').find_all_by_forum_id(self.forum_id).last.id
|
||||
if self.parent_id
|
||||
@parent_memo = Memo.find_by_id(self.parent_id)
|
||||
# @parent_memo.last_reply_id = Memo.reorder('created_at ASC').find_all_by_parent_id(self.parent_id).last.id
|
||||
@parent_memo.replies_count = @parent_memo.replies_count.to_int - 1
|
||||
@parent_memo.replies_count = 0 if @parent_memo.replies_count.to_int < 0
|
||||
@parent_memo.save
|
||||
else
|
||||
@forum.topic_count = @forum.topic_count.to_int - 1
|
||||
@forum.topic_count = 0 if @forum.topic_count.to_int < 0
|
||||
end
|
||||
@forum.save
|
||||
end
|
||||
|
||||
#更新用户分数 -by zjc
|
||||
def be_user_score
|
||||
#新建memo且无parent的为发帖
|
||||
if self.parent_id.nil?
|
||||
UserScore.joint(:post_message, User.current,nil,self ,{ memo_id: self.id })
|
||||
update_memo_number(User.current,1)
|
||||
|
||||
#新建memo且有parent的为回帖
|
||||
elsif !self.parent_id.nil?
|
||||
UserScore.joint(:reply_posting, User.current,self.parent.author,self, { memo_id: self.id })
|
||||
update_replay_for_memo(User.current,1)
|
||||
end
|
||||
end
|
||||
|
||||
#被删除时更新用户分数
|
||||
def down_user_score
|
||||
update_memo_number(User.current,1)
|
||||
update_replay_for_memo(User.current,1)
|
||||
end
|
||||
|
||||
# Time 2015-03-26 15:20:24
|
||||
# Author lizanle
|
||||
# Description 从硬盘上删除资源
|
||||
def delete_kindeditor_assets
|
||||
delete_kindeditor_assets_from_disk self.id,OwnerTypeHelper::MEMO
|
||||
end
|
||||
end
|
||||
|
|
|
@ -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
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
class Message < ActiveRecord::Base
|
||||
include Redmine::SafeAttributes
|
||||
include UserScoreHelper
|
||||
belongs_to :board
|
||||
belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
|
||||
has_many :praise_tread, as: :praise_tread_object, dependent: :destroy
|
||||
|
||||
acts_as_tree :counter_cache => :replies_count, :order => "#{Message.table_name}.created_on ASC"
|
||||
acts_as_attachable
|
||||
belongs_to :last_reply, :class_name => 'Message', :foreign_key => 'last_reply_id'
|
||||
|
||||
# added by fq
|
||||
has_many :acts, :class_name => 'Activity', :as => :act, :dependent => :destroy
|
||||
# 被ForgeActivity虚拟关联
|
||||
has_many :forge_acts, :class_name => 'ForgeActivity',:as =>:forge_act ,:dependent => :destroy
|
||||
# end
|
||||
|
||||
acts_as_searchable :columns => ['subject', 'content'],
|
||||
:include => {:board => :project},
|
||||
:project_key => "#{Board.table_name}.project_id",
|
||||
:date_column => "#{table_name}.created_on"
|
||||
acts_as_searchable :columns => ['subject', 'content'],
|
||||
:include => {:board => :course},
|
||||
:course_key => "#{Board.table_name}.course_id",
|
||||
:date_column => "#{table_name}.created_at"
|
||||
acts_as_event :title => Proc.new {|o| "#{o.board.name}: #{o.subject}"},
|
||||
:description => :content,
|
||||
:datetime => :updated_on,
|
||||
# :datetime => "#{Message.table_name}.created_on",
|
||||
:group => :parent,
|
||||
:type => Proc.new {|o| o.parent_id.nil? ? 'message' : 'reply'},
|
||||
:url => Proc.new {|o| {:controller => 'messages', :action => 'show', :board_id => o.board_id}.merge(o.parent_id.nil? ? {:id => o.id} :
|
||||
{:id => o.parent_id, :r => o.id, :anchor => "message-#{o.id}"})}
|
||||
|
||||
acts_as_activity_provider :find_options => {:include => [{:board => :project}, :author]},
|
||||
:author_key => :author_id
|
||||
acts_as_activity_provider :find_options => {:include => [{:board => :course}, :author]},
|
||||
:type => 'course_messages',
|
||||
:author_key => :author_id
|
||||
acts_as_watchable
|
||||
|
||||
validates_presence_of :board, :subject, :content
|
||||
validates_length_of :subject, :maximum => 255
|
||||
validate :cannot_reply_to_locked_topic, :on => :create
|
||||
|
||||
after_create :add_author_as_watcher, :reset_counters!
|
||||
after_update :update_messages_board
|
||||
after_destroy :reset_counters!,:down_user_score
|
||||
|
||||
# fq
|
||||
after_create :act_as_activity,:be_user_score,:act_as_forge_activity
|
||||
#before_save :be_user_score
|
||||
# end
|
||||
|
||||
scope :visible, lambda {|*args|
|
||||
includes(:board => :project).where(Project.allowed_to_condition(args.shift || User.current, :view_messages, *args))
|
||||
}
|
||||
|
||||
scope :course_visible, lambda {|*args|
|
||||
includes(:board => :course).where(Course.allowed_to_condition(args.shift || User.current, :view_course_messages, *args))
|
||||
}
|
||||
|
||||
|
||||
safe_attributes 'subject', 'content'
|
||||
safe_attributes 'board_id','locked', 'sticky',
|
||||
:if => lambda {|message, user|
|
||||
if message.project
|
||||
user.allowed_to?(:edit_messages, message.project)
|
||||
else
|
||||
user.allowed_to?(:edit_messages, message.course)
|
||||
end
|
||||
}
|
||||
|
||||
def visible?(user=User.current)
|
||||
if project
|
||||
!user.nil? && user.allowed_to?(:view_messages, project)
|
||||
elsif course
|
||||
!user.nil? && user.allowed_to?(:view_messages, course)
|
||||
end
|
||||
end
|
||||
|
||||
def cannot_reply_to_locked_topic
|
||||
# Can not reply to a locked topic
|
||||
errors.add :base, 'Topic is locked' if root.locked? && self != root
|
||||
end
|
||||
|
||||
def update_messages_board
|
||||
if board_id_changed?
|
||||
Message.update_all({:board_id => board_id}, ["id = ? OR parent_id = ?", root.id, root.id])
|
||||
Board.reset_counters!(board_id_was)
|
||||
Board.reset_counters!(board_id)
|
||||
end
|
||||
end
|
||||
|
||||
def reset_counters!
|
||||
if parent && parent.id
|
||||
Message.update_all({:last_reply_id => parent.children.maximum(:id)}, {:id => parent.id})
|
||||
end
|
||||
board.reset_counters!
|
||||
end
|
||||
|
||||
def sticky=(arg)
|
||||
write_attribute :sticky, (arg == true || arg.to_s == '1' ? 1 : 0)
|
||||
end
|
||||
|
||||
def sticky?
|
||||
sticky == 1
|
||||
end
|
||||
|
||||
def project
|
||||
board.project
|
||||
end
|
||||
|
||||
def course
|
||||
board.course
|
||||
end
|
||||
|
||||
def course_editable_by?(usr)
|
||||
usr && usr.logged? && (usr.allowed_to?(:edit_messages, course) || (self.author == usr && usr.allowed_to?(:edit_own_messages, course)))
|
||||
end
|
||||
|
||||
def course_destroyable_by?(usr)
|
||||
usr && usr.logged? && (usr.allowed_to?(:delete_messages, course) || (self.author == usr && usr.allowed_to?(:delete_own_messages, course)))
|
||||
end
|
||||
|
||||
def editable_by?(usr)
|
||||
usr && usr.logged? && (usr.allowed_to?(:edit_messages, project) || (self.author == usr && usr.allowed_to?(:edit_own_messages, project)))
|
||||
end
|
||||
|
||||
def destroyable_by?(usr)
|
||||
usr && usr.logged? && (usr.allowed_to?(:delete_messages, project) || (self.author == usr && usr.allowed_to?(:delete_own_messages, project)))
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def add_author_as_watcher
|
||||
Watcher.create(:watchable => self.root, :user => author)
|
||||
end
|
||||
|
||||
# fq
|
||||
def act_as_activity
|
||||
self.acts << Activity.new(:user_id => self.author_id)
|
||||
end
|
||||
# end
|
||||
|
||||
# Time 2015-02-27 14:32:25
|
||||
# Author lizanle
|
||||
# Description
|
||||
def act_as_forge_activity
|
||||
# 如果project为空,那么就是课程相关的消息
|
||||
if !self.board.project.nil?
|
||||
self.forge_acts << ForgeActivity.new(:user_id => self.author_id,
|
||||
:project_id => self.board.project.id)
|
||||
end
|
||||
end
|
||||
|
||||
#更新用户分数 -by zjc
|
||||
def be_user_score
|
||||
#新建message且无parent的为发帖
|
||||
|
||||
if self.parent_id.nil? && !self.board.project.nil?
|
||||
UserScore.joint(:post_message, self.author,nil,self, { message_id: self.id })
|
||||
update_memo_number(self.author,1)
|
||||
if self.board.project_id != -1
|
||||
update_memo_number(self.author,2,self.board.project)
|
||||
end
|
||||
#新建message且有parent的为回帖
|
||||
elsif !self.parent_id.nil? && !self.board.project.nil?
|
||||
UserScore.joint(:reply_posting, self.author,self.parent.author,self, { message_id: self.id })
|
||||
update_replay_for_memo(self.author,1)
|
||||
if self.board.project_id != -1
|
||||
update_replay_for_memo(self.author,2,self.board.project)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#减少用户分数
|
||||
def down_user_score
|
||||
if self.parent_id.nil? && !self.board.project.nil?
|
||||
UserScore.joint(:delete_message, self.author,nil,self, { message_id: self.id })
|
||||
update_memo_number(User.current,1)
|
||||
if self.board.project_id != -1
|
||||
update_memo_number(self.author,2,self.board.project)
|
||||
end
|
||||
elsif !self.parent_id.nil? && !self.board.project.nil?
|
||||
UserScore.joint(:reply_deleting, self.author,self.parent.author,self, { message_id: self.id })
|
||||
update_replay_for_memo(User.current,1)
|
||||
if self.board.project_id != -1
|
||||
update_replay_for_memo(self.author,2,self.board.project)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
class Message < ActiveRecord::Base
|
||||
include Redmine::SafeAttributes
|
||||
include UserScoreHelper
|
||||
include ApplicationHelper
|
||||
has_many_kindeditor_assets :assets, :dependent => :destroy
|
||||
belongs_to :board
|
||||
belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
|
||||
has_many :praise_tread, as: :praise_tread_object, dependent: :destroy
|
||||
|
||||
acts_as_tree :counter_cache => :replies_count, :order => "#{Message.table_name}.created_on ASC"
|
||||
acts_as_attachable
|
||||
belongs_to :last_reply, :class_name => 'Message', :foreign_key => 'last_reply_id'
|
||||
|
||||
# added by fq
|
||||
has_many :acts, :class_name => 'Activity', :as => :act, :dependent => :destroy
|
||||
# 被ForgeActivity虚拟关联
|
||||
has_many :forge_acts, :class_name => 'ForgeActivity',:as =>:forge_act ,:dependent => :destroy
|
||||
# end
|
||||
|
||||
acts_as_searchable :columns => ['subject', 'content'],
|
||||
:include => {:board => :project},
|
||||
:project_key => "#{Board.table_name}.project_id",
|
||||
:date_column => "#{table_name}.created_on"
|
||||
acts_as_searchable :columns => ['subject', 'content'],
|
||||
:include => {:board => :course},
|
||||
:course_key => "#{Board.table_name}.course_id",
|
||||
:date_column => "#{table_name}.created_at"
|
||||
acts_as_event :title => Proc.new {|o| "#{o.board.name}: #{o.subject}"},
|
||||
:description => :content,
|
||||
:datetime => :updated_on,
|
||||
# :datetime => "#{Message.table_name}.created_on",
|
||||
:group => :parent,
|
||||
:type => Proc.new {|o| o.parent_id.nil? ? 'message' : 'reply'},
|
||||
:url => Proc.new {|o| {:controller => 'messages', :action => 'show', :board_id => o.board_id}.merge(o.parent_id.nil? ? {:id => o.id} :
|
||||
{:id => o.parent_id, :r => o.id, :anchor => "message-#{o.id}"})}
|
||||
|
||||
acts_as_activity_provider :find_options => {:include => [{:board => :project}, :author]},
|
||||
:author_key => :author_id
|
||||
acts_as_activity_provider :find_options => {:include => [{:board => :course}, :author]},
|
||||
:type => 'course_messages',
|
||||
:author_key => :author_id
|
||||
acts_as_watchable
|
||||
|
||||
validates_presence_of :board, :subject, :content
|
||||
validates_length_of :subject, :maximum => 255
|
||||
validate :cannot_reply_to_locked_topic, :on => :create
|
||||
|
||||
after_create :add_author_as_watcher, :reset_counters!
|
||||
after_update :update_messages_board
|
||||
after_destroy :reset_counters!,:down_user_score,:delete_kindeditor_assets
|
||||
|
||||
after_create :act_as_activity,:be_user_score,:act_as_forge_activity, :send_mail
|
||||
#before_save :be_user_score
|
||||
|
||||
scope :visible, lambda {|*args|
|
||||
includes(:board => :project).where(Project.allowed_to_condition(args.shift || User.current, :view_messages, *args))
|
||||
}
|
||||
|
||||
scope :course_visible, lambda {|*args|
|
||||
includes(:board => :course).where(Course.allowed_to_condition(args.shift || User.current, :view_course_messages, *args))
|
||||
}
|
||||
|
||||
|
||||
safe_attributes 'subject', 'content'
|
||||
safe_attributes 'board_id','locked', 'sticky',
|
||||
:if => lambda {|message, user|
|
||||
if message.project
|
||||
user.allowed_to?(:edit_messages, message.project)
|
||||
else
|
||||
user.allowed_to?(:edit_messages, message.course)
|
||||
end
|
||||
}
|
||||
|
||||
def visible?(user=User.current)
|
||||
if project
|
||||
!user.nil? && user.allowed_to?(:view_messages, project)
|
||||
elsif course
|
||||
!user.nil? && user.allowed_to?(:view_messages, course)
|
||||
end
|
||||
end
|
||||
|
||||
def cannot_reply_to_locked_topic
|
||||
# Can not reply to a locked topic
|
||||
errors.add :base, 'Topic is locked' if root.locked? && self != root
|
||||
end
|
||||
|
||||
def update_messages_board
|
||||
if board_id_changed?
|
||||
Message.update_all({:board_id => board_id}, ["id = ? OR parent_id = ?", root.id, root.id])
|
||||
Board.reset_counters!(board_id_was)
|
||||
Board.reset_counters!(board_id)
|
||||
end
|
||||
end
|
||||
|
||||
def reset_counters!
|
||||
if parent && parent.id
|
||||
Message.update_all({:last_reply_id => parent.children.maximum(:id)}, {:id => parent.id})
|
||||
end
|
||||
board.reset_counters!
|
||||
end
|
||||
|
||||
def sticky=(arg)
|
||||
write_attribute :sticky, (arg == true || arg.to_s == '1' ? 1 : 0)
|
||||
end
|
||||
|
||||
def sticky?
|
||||
sticky == 1
|
||||
end
|
||||
|
||||
def project
|
||||
board.project
|
||||
end
|
||||
|
||||
def course
|
||||
board.course
|
||||
end
|
||||
|
||||
def course_editable_by?(usr)
|
||||
usr && usr.logged? && (usr.allowed_to?(:edit_messages, course) || (self.author == usr && usr.allowed_to?(:edit_own_messages, course)))
|
||||
end
|
||||
|
||||
def course_destroyable_by?(usr)
|
||||
usr && usr.logged? && (usr.allowed_to?(:delete_messages, course) || (self.author == usr && usr.allowed_to?(:delete_own_messages, course)))
|
||||
end
|
||||
|
||||
def editable_by?(usr)
|
||||
usr && usr.logged? && (usr.allowed_to?(:edit_messages, project) || (self.author == usr && usr.allowed_to?(:edit_own_messages, project)))
|
||||
end
|
||||
|
||||
def destroyable_by?(usr)
|
||||
usr && usr.logged? && (usr.allowed_to?(:delete_messages, project) || (self.author == usr && usr.allowed_to?(:delete_own_messages, project)))
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def add_author_as_watcher
|
||||
Watcher.create(:watchable => self.root, :user => author)
|
||||
end
|
||||
|
||||
# fq
|
||||
def act_as_activity
|
||||
self.acts << Activity.new(:user_id => self.author_id)
|
||||
end
|
||||
# end
|
||||
|
||||
# Time 2015-02-27 14:32:25
|
||||
# Author lizanle
|
||||
# Description
|
||||
def act_as_forge_activity
|
||||
# 如果project为空,那么就是课程相关的消息
|
||||
if !self.board.project.nil?
|
||||
self.forge_acts << ForgeActivity.new(:user_id => self.author_id,
|
||||
:project_id => self.board.project.id)
|
||||
end
|
||||
end
|
||||
|
||||
#更新用户分数 -by zjc
|
||||
def be_user_score
|
||||
#新建message且无parent的为发帖
|
||||
|
||||
if self.parent_id.nil? && !self.board.project.nil?
|
||||
UserScore.joint(:post_message, self.author,nil,self, { message_id: self.id })
|
||||
update_memo_number(self.author,1)
|
||||
if self.board.project_id != -1
|
||||
update_memo_number(self.author,2,self.board.project)
|
||||
end
|
||||
#新建message且有parent的为回帖
|
||||
elsif !self.parent_id.nil? && !self.board.project.nil?
|
||||
UserScore.joint(:reply_posting, self.author,self.parent.author,self, { message_id: self.id })
|
||||
update_replay_for_memo(self.author,1)
|
||||
if self.board.project_id != -1
|
||||
update_replay_for_memo(self.author,2,self.board.project)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#减少用户分数
|
||||
def down_user_score
|
||||
if self.parent_id.nil? && !self.board.project.nil?
|
||||
UserScore.joint(:delete_message, self.author,nil,self, { message_id: self.id })
|
||||
update_memo_number(User.current,1)
|
||||
if self.board.project_id != -1
|
||||
update_memo_number(self.author,2,self.board.project)
|
||||
end
|
||||
elsif !self.parent_id.nil? && !self.board.project.nil?
|
||||
UserScore.joint(:reply_deleting, self.author,self.parent.author,self, { message_id: self.id })
|
||||
update_replay_for_memo(User.current,1)
|
||||
if self.board.project_id != -1
|
||||
update_replay_for_memo(self.author,2,self.board.project)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def send_mail
|
||||
Mailer.run.message_posted(self) if Setting.notified_events.include?('message_posted')
|
||||
end
|
||||
|
||||
# Time 2015-03-31 09:15:06
|
||||
# Author lizanle
|
||||
# Description 删除对应消息的图片资源
|
||||
def delete_kindeditor_assets
|
||||
delete_kindeditor_assets_from_disk self.id,OwnerTypeHelper::MESSAGE
|
||||
end
|
||||
end
|
||||
|
|
|
@ -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
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
class News < ActiveRecord::Base
|
||||
include Redmine::SafeAttributes
|
||||
belongs_to :project
|
||||
#added by nwb
|
||||
belongs_to :course
|
||||
belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
|
||||
has_many :comments, :as => :commented, :dependent => :delete_all, :order => "created_on"
|
||||
# fq
|
||||
has_many :acts, :class_name => 'Activity', :as => :act, :dependent => :destroy
|
||||
# 被ForgeActivity虚拟关联
|
||||
has_many :forge_acts, :class_name => 'ForgeActivity',:as =>:forge_act ,:dependent => :destroy
|
||||
# end
|
||||
|
||||
validates_presence_of :title, :description
|
||||
validates_length_of :title, :maximum => 60
|
||||
validates_length_of :summary, :maximum => 255
|
||||
validates_length_of :description, :maximum => 10000
|
||||
|
||||
acts_as_attachable :delete_permission => :manage_news
|
||||
acts_as_searchable :columns => ['title', 'summary', "#{table_name}.description"], :include => :project
|
||||
acts_as_event :url => Proc.new {|o| {:controller => 'news', :action => 'show', :id => o.id}}
|
||||
acts_as_activity_provider :find_options => {:include => [:project, :author]},
|
||||
:author_key => :author_id
|
||||
#added by nwb
|
||||
#课程新闻独立于项目
|
||||
acts_as_activity_provider :type => 'course_news',
|
||||
:find_options => {:include => [:course, :author]},
|
||||
:author_key => :author_id
|
||||
acts_as_watchable
|
||||
|
||||
after_create :add_author_as_watcher
|
||||
# fq
|
||||
after_create :act_as_activity,:act_as_forge_activity
|
||||
# end
|
||||
|
||||
scope :visible, lambda {|*args|
|
||||
includes(:project).where(Project.allowed_to_condition(args.shift || User.current, :view_news, *args))
|
||||
}
|
||||
|
||||
scope :course_visible, lambda {|*args|
|
||||
includes(:course).where(Course.allowed_to_condition(args.shift || User.current, :view_course_news, *args))
|
||||
}
|
||||
safe_attributes 'title', 'summary', 'description'
|
||||
|
||||
def visible?(user=User.current)
|
||||
!user.nil? && user.allowed_to?(:view_news, project)
|
||||
end
|
||||
|
||||
# Returns true if the news can be commented by user
|
||||
def commentable?(user=User.current)
|
||||
user.allowed_to?(:comment_news, project)
|
||||
end
|
||||
|
||||
def recipients
|
||||
project.users.select {|user| user.notify_about?(self)}.map(&:mail)
|
||||
end
|
||||
|
||||
# returns latest news for projects visible by user
|
||||
def self.latest(user = User.current, count = 5)
|
||||
visible(user).includes([:author, :project]).order("#{News.table_name}.created_on DESC").limit(count).all
|
||||
end
|
||||
|
||||
# 新闻的短描述信息
|
||||
def short_description(length = 255)
|
||||
description.gsub(/<\/?.*?>/,"").html_safe if description
|
||||
#description.gsub(/^(.{#{length}}[^\n\r]*).*$/m, '\1...').strip if description
|
||||
#description
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def add_author_as_watcher
|
||||
Watcher.create(:watchable => self, :user => author)
|
||||
end
|
||||
## fq
|
||||
def act_as_activity
|
||||
self.acts << Activity.new(:user_id => self.author_id)
|
||||
end
|
||||
|
||||
# Time 2015-02-27 15:48:17
|
||||
# Author lizanle
|
||||
# Description 公用表中也要记录
|
||||
def act_as_forge_activity
|
||||
# 如果是project为空,那么是课程相关的,不需要保存
|
||||
if !self.project.nil?
|
||||
self.forge_acts << ForgeActivity.new(:user_id => self.author_id,
|
||||
:project_id => self.project.id)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
class News < ActiveRecord::Base
|
||||
include Redmine::SafeAttributes
|
||||
belongs_to :project
|
||||
include ApplicationHelper
|
||||
has_many_kindeditor_assets :assets, :dependent => :destroy
|
||||
#added by nwb
|
||||
belongs_to :course
|
||||
belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
|
||||
has_many :comments, :as => :commented, :dependent => :delete_all, :order => "created_on"
|
||||
# fq
|
||||
has_many :acts, :class_name => 'Activity', :as => :act, :dependent => :destroy
|
||||
# 被ForgeActivity虚拟关联
|
||||
has_many :forge_acts, :class_name => 'ForgeActivity',:as =>:forge_act ,:dependent => :destroy
|
||||
# end
|
||||
|
||||
validates_presence_of :title, :description
|
||||
validates_length_of :title, :maximum => 60
|
||||
validates_length_of :summary, :maximum => 255
|
||||
validates_length_of :description, :maximum => 10000
|
||||
|
||||
acts_as_attachable :delete_permission => :manage_news
|
||||
acts_as_searchable :columns => ['title', 'summary', "#{table_name}.description"], :include => :project
|
||||
acts_as_event :url => Proc.new {|o| {:controller => 'news', :action => 'show', :id => o.id}}
|
||||
acts_as_activity_provider :find_options => {:include => [:project, :author]},
|
||||
:author_key => :author_id
|
||||
#added by nwb
|
||||
#课程新闻独立于项目
|
||||
acts_as_activity_provider :type => 'course_news',
|
||||
:find_options => {:include => [:course, :author]},
|
||||
:author_key => :author_id
|
||||
acts_as_watchable
|
||||
|
||||
after_create :act_as_activity,:act_as_forge_activity,:add_author_as_watcher, :send_mail
|
||||
|
||||
after_destroy :delete_kindeditor_assets
|
||||
|
||||
scope :visible, lambda {|*args|
|
||||
includes(:project).where(Project.allowed_to_condition(args.shift || User.current, :view_news, *args))
|
||||
}
|
||||
|
||||
scope :course_visible, lambda {|*args|
|
||||
includes(:course).where(Course.allowed_to_condition(args.shift || User.current, :view_course_news, *args))
|
||||
}
|
||||
safe_attributes 'title', 'summary', 'description'
|
||||
|
||||
def visible?(user=User.current)
|
||||
!user.nil? && user.allowed_to?(:view_news, project)
|
||||
end
|
||||
|
||||
# Returns true if the news can be commented by user
|
||||
def commentable?(user=User.current)
|
||||
user.allowed_to?(:comment_news, project)
|
||||
end
|
||||
|
||||
def recipients
|
||||
project.users.select {|user| user.notify_about?(self)}.map(&:mail)
|
||||
end
|
||||
|
||||
# returns latest news for projects visible by user
|
||||
def self.latest(user = User.current, count = 5)
|
||||
visible(user).includes([:author, :project]).order("#{News.table_name}.created_on DESC").limit(count).all
|
||||
end
|
||||
|
||||
# 新闻的短描述信息
|
||||
def short_description(length = 255)
|
||||
description.gsub(/<\/?.*?>/,"").html_safe if description
|
||||
#description.gsub(/^(.{#{length}}[^\n\r]*).*$/m, '\1...').strip if description
|
||||
#description
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def add_author_as_watcher
|
||||
Watcher.create(:watchable => self, :user => author)
|
||||
end
|
||||
## fq
|
||||
def act_as_activity
|
||||
self.acts << Activity.new(:user_id => self.author_id)
|
||||
end
|
||||
|
||||
# Time 2015-02-27 15:48:17
|
||||
# Author lizanle
|
||||
# Description 公用表中也要记录
|
||||
def act_as_forge_activity
|
||||
# 如果是project为空,那么是课程相关的,不需要保存
|
||||
if !self.project.nil?
|
||||
self.forge_acts << ForgeActivity.new(:user_id => self.author_id,
|
||||
:project_id => self.project.id)
|
||||
end
|
||||
end
|
||||
|
||||
# Time 2015-03-31 13:50:54
|
||||
# Author lizanle
|
||||
# Description 删除news后删除对应的资源
|
||||
def delete_kindeditor_assets
|
||||
delete_kindeditor_assets_from_disk self.id,OwnerTypeHelper::NEWS
|
||||
end
|
||||
|
||||
def send_mail
|
||||
Mailer.run.news_added(self) if Setting.notified_events.include?('news_added')
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -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
|
||||
# attr_accessible :title, :body
|
||||
include Redmine::SafeAttributes
|
||||
belongs_to :open_source_project, :class_name => "OpenSourceProject", :foreign_key => 'osp_id'
|
||||
belongs_to :author, :class_name => "User", :foreign_key => 'author_id'
|
||||
|
||||
has_many :tags, :through => :project_tags, :class_name => 'Tag'
|
||||
has_many :project_tags, :class_name => 'ProjectTags'
|
||||
|
||||
has_many :relation_topics, :class_name => 'RelativeMemoToOpenSourceProject'
|
||||
|
||||
has_many :no_uses, :as => :no_use, :dependent => :delete_all
|
||||
|
||||
has_many :bugs_to_osp, :class_name => 'BugToOsp', :foreign_key => 'relative_memo_id', :dependent => :destroy
|
||||
|
||||
|
||||
acts_as_taggable
|
||||
|
||||
validates_presence_of :subject
|
||||
#validates :content, presence: true
|
||||
# validates_length_of :subject, maximum: 50
|
||||
#validates_length_of :content, maximum: 3072
|
||||
validate :cannot_reply_to_locked_topic, :on => :create
|
||||
validates_uniqueness_of :osp_id, :scope => [:subject, :content]
|
||||
|
||||
acts_as_tree :counter_cache => :replies_count, :order => "#{RelativeMemo.table_name}.created_at ASC"
|
||||
acts_as_attachable
|
||||
belongs_to :last_reply, :class_name => 'RelativeMemo', :foreign_key => 'last_reply_id'
|
||||
# acts_as_searchable :column => ['subject', 'content'],
|
||||
# #:include => { :forum => :p}
|
||||
# #:project_key => "#{Forum.table_name}.project_id"
|
||||
# :date_column => "#{table_name}.created_at"
|
||||
|
||||
# acts_as_event :title => Proc.new {|o| "#{o.forum.name}: #{o.subject}"},
|
||||
# :datetime => :updated_at,
|
||||
# # :datetime => :created_at,
|
||||
# :description => :content,
|
||||
# :author => :author,
|
||||
# :type => Proc.new {|o| o.parent_id.nil? ? 'Memo' : 'Reply'},
|
||||
# :url => Proc.new {|o| {:controller => 'memos', :action => 'show', :forum_id => o.forum_id}.merge(o.parent_id.nil? ? {:id => o.id} : {:id => o.parent_id, :r => o.id, :anchor => "reply-#{o.id}"})}
|
||||
# acts_as_activity_provider :author_key => :author_id,
|
||||
# :func => 'memos',
|
||||
# :timestamp => 'created_at'
|
||||
|
||||
# :find_options => {:type => 'memos'}
|
||||
# acts_as_watchable
|
||||
|
||||
safe_attributes "author_id",
|
||||
"subject",
|
||||
"content",
|
||||
"osp_id",
|
||||
"last_memo_id",
|
||||
"lock",
|
||||
"sticky",
|
||||
"parent_id",
|
||||
"replies_count",
|
||||
"is_quote"
|
||||
|
||||
after_create :add_author_as_watcher, :reset_counters!
|
||||
# after_update :update_memos_forum
|
||||
after_destroy :reset_counters!
|
||||
# after_create :send_notification
|
||||
# after_save :plusParentAndForum
|
||||
# after_destroy :minusParentAndForum
|
||||
|
||||
# scope :visible, lambda { |*args|
|
||||
# includes(:forum => ).where()
|
||||
# }
|
||||
|
||||
def cannot_reply_to_locked_topic
|
||||
errors.add :base, l(:label_memo_locked) if root.locked? && self != root
|
||||
end
|
||||
|
||||
def short_content(length = 25)
|
||||
str = "^(.{,#{length}})[^\n\r]*.*$"
|
||||
content.gsub(Regexp.new(str), '\1...').strip if content
|
||||
end
|
||||
|
||||
# def update_memos_forum
|
||||
# if forum_id_changed?
|
||||
# Message.update_all({:board_id => board_id}, ["id = ? OR parent_id = ?", root.id, root.id ])
|
||||
# Forum.reset_counters!(forum_id_was)
|
||||
# Forum.reset_counters!(forum_id)
|
||||
# end
|
||||
# end
|
||||
|
||||
|
||||
scope :no_use_for, lambda { |user_id|
|
||||
{ :include => :no_uses,
|
||||
:conditions => ["#{NoUse.table_name}.user_id = ?", user_id] }
|
||||
}
|
||||
|
||||
# 获取帖子的回复
|
||||
def replies
|
||||
memos = RelativeMemo.where("parent_id = ?", id)
|
||||
end
|
||||
|
||||
def no_use_for?(user)
|
||||
self.no_uses.each do |no_use|
|
||||
if no_use.user_id == user.id
|
||||
return true
|
||||
end
|
||||
end
|
||||
false
|
||||
end
|
||||
|
||||
def set_no_use(user, flag=true)
|
||||
flag ? set_filter(user) : remove_filter(user)
|
||||
end
|
||||
|
||||
def set_filter(user)
|
||||
self.no_uses << NoUse.new(:user => user)
|
||||
end
|
||||
|
||||
def remove_filter(user)
|
||||
return nil unless user && user.is_a?(User)
|
||||
NoUse.delete_all "no_use_type = '#{self.class}' AND no_use_id = #{self.id} AND user_id = #{user.id}"
|
||||
end
|
||||
|
||||
def reset_counters!
|
||||
if parent && parent.id
|
||||
RelativeMemo.update_all({:last_reply_id => parent.children.maximum(:id)}, {:id => parent.id})
|
||||
parent.update_attribute(:updated_at, Time.now)
|
||||
end
|
||||
# forum.reset_counters!
|
||||
end
|
||||
|
||||
def sticky?
|
||||
sticky == 1
|
||||
end
|
||||
|
||||
def replies
|
||||
RelativeMemo.where("parent_id = ?", id)
|
||||
end
|
||||
|
||||
def locked?
|
||||
self.lock
|
||||
end
|
||||
|
||||
def editable_by? user
|
||||
# user && user.logged? || (self.author == usr && usr.allowed_to?(:edit_own_messages, project))
|
||||
user.admin?
|
||||
end
|
||||
|
||||
# def destroyable_by? user
|
||||
# (user && user.logged? && (Forum.find(self.forum_id).creator_id == user.id) ) || user.admin?
|
||||
# #self.author == user || user.admin?
|
||||
# end
|
||||
|
||||
def deleted_attach_able_by? user
|
||||
(user && user.logged? && (self.author == user) ) || user.admin?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def add_author_as_watcher
|
||||
Watcher.create(:watchable => self.root, :user => author)
|
||||
end
|
||||
|
||||
def send_notification
|
||||
if Setting.notified_events.include?('message_posted')
|
||||
Mailer.message_posted(self).deliver
|
||||
end
|
||||
end
|
||||
|
||||
# def plusParentAndForum
|
||||
# @forum = Forum.find(self.forum_id)
|
||||
# @forum.memo_count = @forum.memo_count.to_int + 1
|
||||
# @forum.last_memo_id = self.id
|
||||
# if self.parent_id
|
||||
# @parent_memo = Memo.find_by_id(self.parent_id)
|
||||
# @parent_memo.last_reply_id = self
|
||||
# @parent_memo.replies_count = @parent_memo.replies_count.to_int + 1
|
||||
# @parent_memo.save
|
||||
# else
|
||||
# @forum.topic_count = @forum.topic_count.to_int + 1
|
||||
# end
|
||||
# @forum.save
|
||||
# end
|
||||
|
||||
# def minusParentAndForum
|
||||
# @forum = Forum.find(self.forum_id)
|
||||
# @forum.memo_count = @forum.memo_count.to_int - 1
|
||||
# @forum.memo_count = 0 if @forum.memo_count.to_int < 0
|
||||
# # @forum.last_memo_id = Memo.reorder('created_at ASC').find_all_by_forum_id(self.forum_id).last.id
|
||||
# if self.parent_id
|
||||
# @parent_memo = Memo.find_by_id(self.parent_id)
|
||||
# # @parent_memo.last_reply_id = Memo.reorder('created_at ASC').find_all_by_parent_id(self.parent_id).last.id
|
||||
# @parent_memo.replies_count = @parent_memo.replies_count.to_int - 1
|
||||
# @parent_memo.replies_count = 0 if @parent_memo.replies_count.to_int < 0
|
||||
# @parent_memo.save
|
||||
# else
|
||||
# @forum.topic_count = @forum.topic_count.to_int - 1
|
||||
# @forum.topic_count = 0 if @forum.topic_count.to_int < 0
|
||||
# end
|
||||
# @forum.save
|
||||
# end
|
||||
end
|
||||
|
||||
class RelativeMemo < ActiveRecord::Base
|
||||
# attr_accessible :title, :body
|
||||
include Redmine::SafeAttributes
|
||||
belongs_to :open_source_project, :class_name => "OpenSourceProject", :foreign_key => 'osp_id'
|
||||
belongs_to :author, :class_name => "User", :foreign_key => 'author_id'
|
||||
|
||||
has_many :tags, :through => :project_tags, :class_name => 'Tag'
|
||||
has_many :project_tags, :class_name => 'ProjectTags'
|
||||
|
||||
has_many :relation_topics, :class_name => 'RelativeMemoToOpenSourceProject'
|
||||
|
||||
has_many :no_uses, :as => :no_use, :dependent => :delete_all
|
||||
|
||||
has_many :bugs_to_osp, :class_name => 'BugToOsp', :foreign_key => 'relative_memo_id', :dependent => :destroy
|
||||
|
||||
|
||||
acts_as_taggable
|
||||
|
||||
validates_presence_of :subject
|
||||
#validates :content, presence: true
|
||||
# validates_length_of :subject, maximum: 50
|
||||
#validates_length_of :content, maximum: 3072
|
||||
validate :cannot_reply_to_locked_topic, :on => :create
|
||||
validates_uniqueness_of :osp_id, :scope => [:subject, :content]
|
||||
|
||||
acts_as_tree :counter_cache => :replies_count, :order => "#{RelativeMemo.table_name}.created_at ASC"
|
||||
acts_as_attachable
|
||||
belongs_to :last_reply, :class_name => 'RelativeMemo', :foreign_key => 'last_reply_id'
|
||||
# acts_as_searchable :column => ['subject', 'content'],
|
||||
# #:include => { :forum => :p}
|
||||
# #:project_key => "#{Forum.table_name}.project_id"
|
||||
# :date_column => "#{table_name}.created_at"
|
||||
|
||||
# acts_as_event :title => Proc.new {|o| "#{o.forum.name}: #{o.subject}"},
|
||||
# :datetime => :updated_at,
|
||||
# # :datetime => :created_at,
|
||||
# :description => :content,
|
||||
# :author => :author,
|
||||
# :type => Proc.new {|o| o.parent_id.nil? ? 'Memo' : 'Reply'},
|
||||
# :url => Proc.new {|o| {:controller => 'memos', :action => 'show', :forum_id => o.forum_id}.merge(o.parent_id.nil? ? {:id => o.id} : {:id => o.parent_id, :r => o.id, :anchor => "reply-#{o.id}"})}
|
||||
# acts_as_activity_provider :author_key => :author_id,
|
||||
# :func => 'memos',
|
||||
# :timestamp => 'created_at'
|
||||
|
||||
# :find_options => {:type => 'memos'}
|
||||
# acts_as_watchable
|
||||
|
||||
safe_attributes "author_id",
|
||||
"subject",
|
||||
"content",
|
||||
"osp_id",
|
||||
"last_memo_id",
|
||||
"lock",
|
||||
"sticky",
|
||||
"parent_id",
|
||||
"replies_count",
|
||||
"is_quote"
|
||||
|
||||
after_create :add_author_as_watcher, :reset_counters!
|
||||
# after_update :update_memos_forum
|
||||
after_destroy :reset_counters!
|
||||
# after_create :send_notification
|
||||
# after_save :plusParentAndForum
|
||||
# after_destroy :minusParentAndForum
|
||||
|
||||
# scope :visible, lambda { |*args|
|
||||
# includes(:forum => ).where()
|
||||
# }
|
||||
|
||||
def cannot_reply_to_locked_topic
|
||||
errors.add :base, l(:label_memo_locked) if root.locked? && self != root
|
||||
end
|
||||
|
||||
def short_content(length = 25)
|
||||
str = "^(.{,#{length}})[^\n\r]*.*$"
|
||||
content.gsub(Regexp.new(str), '\1...').strip if content
|
||||
end
|
||||
|
||||
# def update_memos_forum
|
||||
# if forum_id_changed?
|
||||
# Message.update_all({:board_id => board_id}, ["id = ? OR parent_id = ?", root.id, root.id ])
|
||||
# Forum.reset_counters!(forum_id_was)
|
||||
# Forum.reset_counters!(forum_id)
|
||||
# end
|
||||
# end
|
||||
|
||||
|
||||
scope :no_use_for, lambda { |user_id|
|
||||
{ :include => :no_uses,
|
||||
:conditions => ["#{NoUse.table_name}.user_id = ?", user_id] }
|
||||
}
|
||||
|
||||
# 获取帖子的回复
|
||||
def replies
|
||||
memos = RelativeMemo.where("parent_id = ?", id)
|
||||
end
|
||||
|
||||
def no_use_for?(user)
|
||||
self.no_uses.each do |no_use|
|
||||
if no_use.user_id == user.id
|
||||
return true
|
||||
end
|
||||
end
|
||||
false
|
||||
end
|
||||
|
||||
def set_no_use(user, flag=true)
|
||||
flag ? set_filter(user) : remove_filter(user)
|
||||
end
|
||||
|
||||
def set_filter(user)
|
||||
self.no_uses << NoUse.new(:user => user)
|
||||
end
|
||||
|
||||
def remove_filter(user)
|
||||
return nil unless user && user.is_a?(User)
|
||||
NoUse.delete_all "no_use_type = '#{self.class}' AND no_use_id = #{self.id} AND user_id = #{user.id}"
|
||||
end
|
||||
|
||||
def reset_counters!
|
||||
if parent && parent.id
|
||||
RelativeMemo.update_all({:last_reply_id => parent.children.maximum(:id)}, {:id => parent.id})
|
||||
parent.update_attribute(:updated_at, Time.now)
|
||||
end
|
||||
# forum.reset_counters!
|
||||
end
|
||||
|
||||
def sticky?
|
||||
sticky == 1
|
||||
end
|
||||
|
||||
def replies
|
||||
RelativeMemo.where("parent_id = ?", id)
|
||||
end
|
||||
|
||||
def locked?
|
||||
self.lock
|
||||
end
|
||||
|
||||
def editable_by? user
|
||||
# user && user.logged? || (self.author == usr && usr.allowed_to?(:edit_own_messages, project))
|
||||
user.admin?
|
||||
end
|
||||
|
||||
# def destroyable_by? user
|
||||
# (user && user.logged? && (Forum.find(self.forum_id).creator_id == user.id) ) || user.admin?
|
||||
# #self.author == user || user.admin?
|
||||
# end
|
||||
|
||||
def deleted_attach_able_by? user
|
||||
(user && user.logged? && (self.author == user) ) || user.admin?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def add_author_as_watcher
|
||||
Watcher.create(:watchable => self.root, :user => author)
|
||||
end
|
||||
|
||||
def send_notification
|
||||
if Setting.notified_events.include?('message_posted')
|
||||
Mailer.run.message_posted(self)
|
||||
end
|
||||
end
|
||||
|
||||
# def plusParentAndForum
|
||||
# @forum = Forum.find(self.forum_id)
|
||||
# @forum.memo_count = @forum.memo_count.to_int + 1
|
||||
# @forum.last_memo_id = self.id
|
||||
# if self.parent_id
|
||||
# @parent_memo = Memo.find_by_id(self.parent_id)
|
||||
# @parent_memo.last_reply_id = self
|
||||
# @parent_memo.replies_count = @parent_memo.replies_count.to_int + 1
|
||||
# @parent_memo.save
|
||||
# else
|
||||
# @forum.topic_count = @forum.topic_count.to_int + 1
|
||||
# end
|
||||
# @forum.save
|
||||
# end
|
||||
|
||||
# def minusParentAndForum
|
||||
# @forum = Forum.find(self.forum_id)
|
||||
# @forum.memo_count = @forum.memo_count.to_int - 1
|
||||
# @forum.memo_count = 0 if @forum.memo_count.to_int < 0
|
||||
# # @forum.last_memo_id = Memo.reorder('created_at ASC').find_all_by_forum_id(self.forum_id).last.id
|
||||
# if self.parent_id
|
||||
# @parent_memo = Memo.find_by_id(self.parent_id)
|
||||
# # @parent_memo.last_reply_id = Memo.reorder('created_at ASC').find_all_by_parent_id(self.parent_id).last.id
|
||||
# @parent_memo.replies_count = @parent_memo.replies_count.to_int - 1
|
||||
# @parent_memo.replies_count = 0 if @parent_memo.replies_count.to_int < 0
|
||||
# @parent_memo.save
|
||||
# else
|
||||
# @forum.topic_count = @forum.topic_count.to_int - 1
|
||||
# @forum.topic_count = 0 if @forum.topic_count.to_int < 0
|
||||
# end
|
||||
# @forum.save
|
||||
# end
|
||||
end
|
||||
|
||||
|
|
2059
app/models/user.rb
2059
app/models/user.rb
File diff suppressed because it is too large
Load Diff
|
@ -1,34 +1,28 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
class WikiContentObserver < ActiveRecord::Observer
|
||||
def after_create(wiki_content)
|
||||
##by senluo
|
||||
thread7=Thread.new do
|
||||
Mailer.wiki_content_added(wiki_content).deliver if Setting.notified_events.include?('wiki_content_added')
|
||||
end
|
||||
end
|
||||
|
||||
def after_update(wiki_content)
|
||||
if wiki_content.text_changed?
|
||||
##by senluo
|
||||
thread8=Thread.new do
|
||||
Mailer.wiki_content_updated(wiki_content).deliver if Setting.notified_events.include?('wiki_content_updated')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
class WikiContentObserver < ActiveRecord::Observer
|
||||
def after_create(wiki_content)
|
||||
Mailer.run.wiki_content_added(wiki_content) if Setting.notified_events.include?('wiki_content_added')
|
||||
end
|
||||
|
||||
def after_update(wiki_content)
|
||||
if wiki_content.text_changed?
|
||||
Mailer.run.wiki_content_updated(wiki_content) if Setting.notified_events.include?('wiki_content_updated')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -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.endup_time = params[:endup_time]
|
||||
@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
|
||||
|
||||
@issue_custom_fields = IssueCustomField.sorted.all
|
||||
|
|
|
@ -20,7 +20,7 @@ class HomeworkService
|
|||
many_times = course.homeworks.index(@bid) + 1
|
||||
name = @bid.name
|
||||
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
|
||||
#if is_course_teacher(User.current, course) && @bid.open_anonymous_evaluation == 1 && @bid.homeworks.count >= 2
|
||||
state = @bid.comment_status
|
||||
|
@ -282,7 +282,7 @@ class HomeworkService
|
|||
many_times = course.homeworks.index(@bid) + 1
|
||||
name = @bid.name
|
||||
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
|
||||
#if is_course_teacher(User.current, course) && @bid.open_anonymous_evaluation == 1 && @bid.homeworks.count >= 2
|
||||
state = @bid.comment_status
|
||||
|
|
|
@ -95,9 +95,7 @@ class UsersService
|
|||
# create a new token for password recovery
|
||||
token = Token.new(:user => user, :action => "recovery")
|
||||
if token.save
|
||||
Thread.new do
|
||||
Mailer.lost_password(token).deliver
|
||||
end
|
||||
Mailer.run.lost_password(token)
|
||||
return l(:notice_account_lost_email_sent,:locale => user.language)
|
||||
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}%>
|
||||
(<span id="jours_count" class="c_red f_12"><%= @jours_count %></span>)
|
||||
</li>
|
||||
<li>
|
||||
<%#= link_to "作品打包下载", zipdown_assort_path(obj_class: @bid.class, obj_id: @bid), class: "tb_all" unless @bid.homeworks.empty? %>
|
||||
<li><%= link_to "作品打包下载", zipdown_assort_path(obj_class: @bid.class, obj_id: @bid, format: :json),
|
||||
remote: true, class: "tb_all" unless @bid.homeworks.empty? %>
|
||||
</li>
|
||||
</ul>
|
||||
<% else %>
|
||||
|
|
|
@ -1,47 +1,53 @@
|
|||
<%= stylesheet_link_tag 'jquery/jquery-ui-1.9.2', :media => 'all' %>
|
||||
<%= error_messages_for 'bid' %>
|
||||
<%= hidden_field_tag 'course_id', @course.id %>
|
||||
<div class="project_r_h">
|
||||
<h2 class="project_h2"><%= l(:label_course_homework_new)%></h2>
|
||||
</div>
|
||||
<div class="hwork_new">
|
||||
<ul>
|
||||
<li class="ml45">
|
||||
<label><span class="c_red">*</span> <%= l(:field_name)%> :</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%>" >
|
||||
<p id="bid_name_span" class="c_red" style="padding-left: 55px;"></p>
|
||||
</li>
|
||||
<li class="ml45">
|
||||
<label class="fl" > <%= l(:field_quote)%> :</label>
|
||||
<textarea name="bid[description]" placeholder="最多3000个汉字(或6000个英文字符)" class="hwork_text fl"><%= bid.description%></textarea>
|
||||
</li>
|
||||
<div class="cl"></div>
|
||||
<li class="ml21">
|
||||
<label><span class="c_red">*</span> <%= l(:label_limit_time)%> :</label>
|
||||
<input type="text" name="bid[deadline]" id="bid_deadline" class="hwork_input02" onchange="regexDeadLine();" readonly="readonly" value="<%= bid.deadline%>" >
|
||||
<%= calendar_for('bid_deadline')%>
|
||||
</li>
|
||||
<li class=" mb5 ml30">
|
||||
<label ><%= l(:label_open_anonymous_evaluation)%> :</label>
|
||||
<input type="checkbox" name="bid[open_anonymous_evaluation]" id="bid_open_anonymous_evaluation" <%= bid.open_anonymous_evaluation == 1 ? 'checked' : ''%> >
|
||||
<div class="cl"></div>
|
||||
</li>
|
||||
<li class="ml9" id="bid_evaluation_num_li" style="display: <%= bid.open_anonymous_evaluation == 1 ? 'block' : 'none'%>;">
|
||||
<label><span class="c_red">*</span> <%= l(:field_evaluation_num)%> :</label>
|
||||
<input type="text" name="bid[evaluation_num]" id="bid_evaluation_num" class="hwork_input02" onkeyup="regex_evaluation_num();" value="<%= bid.evaluation_num%>">
|
||||
<span><%= l(:label_evaluation_description)%></span>
|
||||
<p id="bid_evaluation_num_span" class="c_red" style="padding-left: 90px;"></p>
|
||||
</li>
|
||||
<li class="ml45">
|
||||
<label class="fl"> <%= l(:label_attachment_plural) %> :</label>
|
||||
<%= render :partial => 'attachments/new_form', :locals => {:container => bid} %>
|
||||
<div class="cl"></div>
|
||||
</li>
|
||||
<li class=" ml90" >
|
||||
<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>
|
||||
<%= stylesheet_link_tag 'jquery/jquery-ui-1.9.2', :media => 'all' %>
|
||||
<%= error_messages_for 'bid' %>
|
||||
<%= hidden_field_tag 'course_id', @course.id %>
|
||||
<div class="project_r_h">
|
||||
<h2 class="project_h2"><%= l(:label_course_homework_new)%></h2>
|
||||
</div>
|
||||
<div class="hwork_new">
|
||||
<ul>
|
||||
<li class="ml45">
|
||||
<label><span class="c_red">*</span> <%= l(:field_name)%> :</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%>" >
|
||||
<p id="bid_name_span" class="c_red" style="padding-left: 55px;"></p>
|
||||
</li>
|
||||
<li class="ml45">
|
||||
<label class="fl" > <%= l(:field_quote)%> :</label>
|
||||
<!--<textarea name="bid[description]" placeholder="最多3000个汉字(或6000个英文字符)" class="hwork_text fl"></textarea>-->
|
||||
<% if edit_mode %>
|
||||
<%= f.kindeditor :description,:width=>'91%',:editor_id => 'bid_description_editor',:owner_id => bid.id,:owner_type =>OwnerTypeHelper::BID %>
|
||||
<% else %>
|
||||
<%= hidden_field_tag :asset_id,params[:asset_id],:required => false,:style => 'display:none' %>
|
||||
<%= f.kindeditor :description,:width=>'91%',:editor_id => 'bid_description_editor' %>
|
||||
<% end %>
|
||||
</li>
|
||||
<div class="cl"></div>
|
||||
<li class="ml21">
|
||||
<label><span class="c_red">*</span> <%= l(:label_limit_time)%> :</label>
|
||||
<input type="text" name="bid[deadline]" id="bid_deadline" class="hwork_input02" onchange="regexDeadLine();" readonly="readonly" value="<%= bid.deadline%>" >
|
||||
<%= calendar_for('bid_deadline')%>
|
||||
</li>
|
||||
<li class=" mb5 ml30">
|
||||
<label ><%= l(:label_open_anonymous_evaluation)%> :</label>
|
||||
<input type="checkbox" name="bid[open_anonymous_evaluation]" id="bid_open_anonymous_evaluation" <%= bid.open_anonymous_evaluation == 1 ? 'checked' : ''%> >
|
||||
<div class="cl"></div>
|
||||
</li>
|
||||
<li class="ml9" id="bid_evaluation_num_li" style="display: <%= bid.open_anonymous_evaluation == 1 ? 'block' : 'none'%>;">
|
||||
<label><span class="c_red">*</span> <%= l(:field_evaluation_num)%> :</label>
|
||||
<input type="text" name="bid[evaluation_num]" id="bid_evaluation_num" class="hwork_input02" onkeyup="regex_evaluation_num();" value="<%= bid.evaluation_num%>">
|
||||
<span><%= l(:label_evaluation_description)%></span>
|
||||
<p id="bid_evaluation_num_span" class="c_red" style="padding-left: 90px;"></p>
|
||||
</li>
|
||||
<li class="ml45">
|
||||
<label class="fl"> <%= l(:label_attachment_plural) %> :</label>
|
||||
<%= render :partial => 'attachments/new_form', :locals => {:container => bid} %>
|
||||
<div class="cl"></div>
|
||||
</li>
|
||||
<li class=" ml90" >
|
||||
<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| %>
|
||||
<%= 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 %>
|
|
@ -1,5 +1,6 @@
|
|||
<% if @project %>
|
||||
<%= render :partial => 'project_show', locals: {project: @project} %>
|
||||
<% elsif @course %>
|
||||
<%= render :partial => 'course_show', locals: {course: @course} %>
|
||||
<% end %>
|
||||
|
||||
<% if @project %>
|
||||
<%= render :partial => 'project_show', locals: {project: @project} %>
|
||||
<% elsif @course %>
|
||||
<%= render :partial => 'course_show', locals: {course: @course} %>
|
||||
<% end %>
|
||||
|
|
|
@ -1,28 +1,29 @@
|
|||
|
||||
<div class="msg_box" id='leave-message'>
|
||||
<%# reply_allow = JournalsForMessage.create_by_user? User.current %>
|
||||
<h4><%= l(:label_leave_message) %></h4>
|
||||
|
||||
<% if !User.current.logged?%>
|
||||
<div style="font-size: 14px;margin:20px;">
|
||||
<%= l(:label_user_login_tips) %>
|
||||
<%= link_to l(:label_user_login_new), signin_path %>
|
||||
<hr/>
|
||||
</div>
|
||||
<% else %>
|
||||
<%= form_for('new_form', :method => :post,
|
||||
:url => {:controller => 'words', :action => 'leave_course_message'}) do |f|%>
|
||||
<%= f.text_area 'course_message',:id => "leave_meassge",:style => "resize: none;",
|
||||
:placeholder => "#{l(:label_welcome_my_respond)}",:maxlength => 250%>
|
||||
<a href="#" class="grey_btn fr ml10">取 消</a>
|
||||
<a href="#" onclick='$("#leave_meassge").parent().submit();' class="blue_btn fr"> <%= l(:button_leave_meassge)%></a>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div id="history">
|
||||
<%= render :partial => 'history',:locals => { :contest => @contest, :journals => @jour, :state => false} %>
|
||||
</div>
|
||||
<ul class="wlist">
|
||||
<%= pagination_links_full @obj_pages, @obj_count, :per_page_links => false, :remote => false, :flag => true%>
|
||||
<%= javascript_include_tag "/assets/kindeditor/kindeditor" %>
|
||||
<div class="msg_box" id='leave-message'>
|
||||
<%# reply_allow = JournalsForMessage.create_by_user? User.current %>
|
||||
<h4><%= l(:label_leave_message) %></h4>
|
||||
|
||||
<% if !User.current.logged?%>
|
||||
<div style="font-size: 14px;margin:20px;">
|
||||
<%= l(:label_user_login_tips) %>
|
||||
<%= link_to l(:label_user_login_new), signin_path %>
|
||||
<hr/>
|
||||
</div>
|
||||
<% else %>
|
||||
<%= form_for('new_form', :method => :post,
|
||||
:url => {:controller => 'words', :action => 'leave_course_message'},:html => {:id=>'leave_message_form'}) do |f|%>
|
||||
<%= hidden_field_tag :asset_id,params[:asset_id],:required => false,:style => 'display:none' %>
|
||||
<%= f.kindeditor 'course_message',:editor_id => 'leave_message_editor',:input_html=>{:id => "leave_meassge",:style => "resize: none;",
|
||||
:placeholder => "#{l(:label_welcome_my_respond)}",:maxlength => 250}%>
|
||||
<a href="#" class="grey_btn fr ml10">取 消</a>
|
||||
<a href="#" onclick='leave_message_editor.sync();$("#leave_message_form").submit();' class="blue_btn fr"> <%= l(:button_leave_meassge)%></a>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div id="history">
|
||||
<%= render :partial => 'history',:locals => { :contest => @contest, :journals => @jour, :state => false} %>
|
||||
</div>
|
||||
<ul class="wlist">
|
||||
<%= pagination_links_full @obj_pages, @obj_count, :per_page_links => false, :remote => false, :flag => true%>
|
||||
</ul>
|
|
@ -32,7 +32,7 @@
|
|||
</script>
|
||||
<div id="bid_description_<%= bid.id%>" class="news_description mt5">
|
||||
<div id="bid_description_<%= bid.id%>_content">
|
||||
<%= textilizable bid, :description %>
|
||||
<%= textAreailizable bid, :description %>
|
||||
</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;">
|
||||
|
|
|
@ -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">
|
||||
<h2 class="project_h2"><%= l(:permission_new_course)%></h2>
|
||||
</div>
|
||||
|
@ -24,7 +37,8 @@
|
|||
<div class="cl"></div>
|
||||
<li class="ml45 mb10">
|
||||
<label><span class="c_red">*</span> <%= l(:label_new_course_password)%> :</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>
|
||||
<span class=" ml80 c_orange">学生或其他成员申请加入课程时候需要使用该口令,该口令可以由老师在课堂上公布。</span>
|
||||
</li>
|
||||
|
@ -35,7 +49,7 @@
|
|||
</li>
|
||||
<li class=" mb5 ml80">
|
||||
<label >公开 :</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>
|
||||
<div class="cl"></div>
|
||||
</li>
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
<%= 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" } %>
|
||||
<%= javascript_include_tag "/assets/kindeditor/kindeditor" %>
|
||||
<%= 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 %>
|
|
@ -12,12 +12,13 @@
|
|||
<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})", @canShowRealName,:class => 'problem_name c_orange fl') if @canShowRealName && e.respond_to?(:event_author) %>
|
||||
<span class="fl"> </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 />
|
||||
<p class="mt5 break_word"><%= e.event_description %>
|
||||
<br />
|
||||
<%= l :label_activity_time %> : <%= format_activity_day(day) %><%= format_time(e.event_datetime, false) %>
|
||||
<%= l :label_activity_time %> : <%= format_activity_day(day) %> <%= format_time(e.event_datetime, false) %>
|
||||
</p>
|
||||
</div>
|
||||
<div class="cl"></div>
|
||||
|
@ -25,7 +26,7 @@
|
|||
<% end%>
|
||||
<% end%>
|
||||
<% end%>
|
||||
|
||||
<% if @obj_pages.next_page.nil? %>
|
||||
<div class="problem_main">
|
||||
<a class="problem_pic fl">
|
||||
<%= image_tag(url_to_avatar(@user), :width => "42", :height => "42") %>
|
||||
|
@ -43,7 +44,7 @@
|
|||
</div>
|
||||
<div class="cl"></div>
|
||||
</div><!--课程动态 end-->
|
||||
|
||||
<% end%>
|
||||
<ul class="wlist">
|
||||
<%= pagination_links_full @obj_pages, @obj_count, :per_page_links => false, :remote => false, :flag => true%>
|
||||
</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) %>
|
||||
</td>
|
||||
<td style=" margin-right: 1" width="10%">
|
||||
<%= link_to '查看文章',{:controller => 'discuss_demos',:action => 'show',:id=>e.id} %>
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<%= 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="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>
|
||||
|
|
|
@ -15,7 +15,8 @@
|
|||
</div>
|
||||
<div class="cl"></div>
|
||||
<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="">
|
||||
<%= 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 class="cl"></div>
|
||||
</div><!---re_con_box end-->
|
||||
<% else %>
|
||||
<div class="re_con_box"><span class='fr mr10 pr_join_span '><%= file.filename %>是私有资源</span></div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
<ul class="wlist">
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
|
||||
<div class="re_con_top">
|
||||
<p class="f_l c_blue f_b f_14">共有 <%= all_attachments.count%> 个资源</p>
|
||||
<p class="f_r" style="color: #808080">
|
||||
<% if order == "asc" %>
|
||||
按 <%= 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"} %> /
|
||||
<%= 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"} %> /
|
||||
<%= 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"} %> 排序
|
||||
<% else %>
|
||||
按 <%= 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"} %> /
|
||||
<%= 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"} %> /
|
||||
<%= 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"} %> 排序
|
||||
<% 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) %> | 下载<%= file.downloads %> | 引用<%= 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>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% if @curse_attachments != nil %>
|
||||
<% @curse_attachments.each do |file| %>
|
||||
<% if @obj_attachments != nil %>
|
||||
<% @obj_attachments.each do |file| %>
|
||||
<%if file.is_public == 0 && !User.current.member_of?(@project)%>
|
||||
<%next%>
|
||||
<%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();">引 用</a><a href="javascript:void(0)" class="blue_btn grey_btn fl c_white" onclick="closeModal();">取 消</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 @obj_flag == '3'%>
|
||||
|
||||
$('#tags_show_issue').html('<%= escape_javascript(render :partial => 'tags/tag_name',
|
||||
<% if @addTag%>
|
||||
<% if @obj_flag == '3'%>
|
||||
$('#tags_show_issue').html('<%= escape_javascript(render :partial => 'tags/tag_name',
|
||||
:locals => {:obj => @obj,:non_list_all => false,:object_flag => @obj_flag}) %>');
|
||||
//$('#put-tag-form-issue').hide();
|
||||
$('#name-issue').val("");
|
||||
<% elsif @obj_flag == '6'%>
|
||||
$("#tags_show-<%=@obj.class%>-<%=@obj.id%>").empty();
|
||||
$("#tags_show-<%=@obj.class%>-<%=@obj.id%>").html('<%= escape_javascript(render :partial => 'tags/tag_name',
|
||||
//$('#put-tag-form-issue').hide();
|
||||
$('#name-issue').val("");
|
||||
<% elsif @obj_flag == '6'%>
|
||||
$("#tags_show-<%=@obj.class%>-<%=@obj.id%>").empty();
|
||||
$("#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}) %>');
|
||||
$("#put-tag-form- <%=@obj.class%>- <%=@obj.id%>").hide();
|
||||
$("#put-tag-form-<%=@obj.class%>-<%=@obj.id%> #name").val("");
|
||||
$("#put-tag-form- <%=@obj.class%>- <%=@obj.id%>").hide();
|
||||
$("#put-tag-form-<%=@obj.class%>-<%=@obj.id%> #name").val("");
|
||||
<% else %>
|
||||
$('#tags_show').html('<%= escape_javascript(render :partial => 'tags/tag_name',
|
||||
:locals => {:obj => @obj,:non_list_all => false,:object_flag => @obj_flag}) %>');
|
||||
$('#tags_show').html('<%=render_attachments_tag_save(@project, nil)%>');
|
||||
$('#put-tag-form #name').val("");
|
||||
//$('#put-tag-form').hide();
|
||||
<% end %>
|
||||
<% else %>
|
||||
|
||||
$('#tags_show').html('<%= escape_javascript(render :partial => 'tags/tag_name',
|
||||
:locals => {:obj => @obj,:non_list_all => false,:object_flag => @obj_flag}) %>');
|
||||
$('#tags_show').html('<%=render_attachments_tag_save(@project, nil)%>');
|
||||
$('#put-tag-form #name').val("");
|
||||
//$('#put-tag-form').hide();
|
||||
<% end %>
|
||||
<%else%>
|
||||
$("#attachments_fields").children().remove();
|
||||
$("#upload_file_count").text("未上传文件");
|
||||
$('#upload_file_div').slideToggle('slow');
|
||||
<%if @project%>
|
||||
$("#all_browse_div").html('<%= j(render partial: "show_all_attachment")%>');
|
||||
<%elsif @course%>
|
||||
$("#all_browse_div").html('<%= j(render partial: "course_show_all_attachment")%>');
|
||||
closeModal();
|
||||
$("#resource_list").html('<%= j(render partial: "course_file" ,locals: {course: @course}) %>');
|
||||
<%end%>
|
||||
<% if @project%>
|
||||
closeModal();
|
||||
$("#resource_list").html('<%= j(render partial: "project_file_new" ,locals: {project: @project}) %>');
|
||||
<%elsif @course%>
|
||||
closeModal();
|
||||
$("#resource_list").html('<%= j(render partial: "course_file" ,locals: {course: @course}) %>');
|
||||
<% end %>
|
||||
<% end %>
|
||||
$(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%>
|
||||
<li class="pic_head" style="line-height: 1.2;">
|
||||
<% if is_student_batch_homework %>
|
||||
<!-- 学生匿评 不现实姓名、头像,以及相关的连接 -->
|
||||
<a><%= image_tag(url_to_avatar("匿名"), :width => "40", :height => "40")%></a>
|
||||
<a>匿名</a>
|
||||
<% else %>
|
||||
<%= link_to image_tag(url_to_avatar(homework.user), :width => "40", :height => "40"), user_path(homework.user) %>
|
||||
<span>
|
||||
<% 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 %>
|
||||
<%= link_to user_name, user_path(homework.user), :title => user_name %>
|
||||
</span>
|
||||
<% end %>
|
||||
</li>
|
||||
<li class="wname">
|
||||
<% if homework.name == nil || homework.name == "" %>
|
||||
<% homework_filename = homework.user.name + "提交的作业" %>
|
||||
<% else %>
|
||||
<% homework_filename = homework.name %>
|
||||
<% 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%>
|
||||
<span class="c_grey ">
|
||||
提交时间:
|
||||
<%= format_time homework.created_at%>
|
||||
</span>
|
||||
</li>
|
||||
<li class="wdown">
|
||||
<%#= link_to "(#{homework.attachments.count.to_s}个附件)", "javascript:"%>
|
||||
</li>
|
||||
<li class="wscore">
|
||||
<% unless is_student_batch_homework %>
|
||||
<%= l(:label_teacher_score)%>:
|
||||
<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)%>
|
||||
</span>
|
||||
|
||||
<% end %>
|
||||
</li>
|
||||
<li class="wscore">
|
||||
<%= is_student_batch_homework ? l(:label_my_score) : l(:label_student_score)%>:
|
||||
<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))%>
|
||||
</span>
|
||||
</li>
|
||||
<% if is_teacher %>
|
||||
<!-- 是老师,所有列表正常显示 -->
|
||||
<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 %>
|
||||
<% 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"> 迟交!</span>
|
||||
<% end %>
|
||||
</li>
|
||||
<% else %>
|
||||
<!-- 是学生 -->
|
||||
<% if is_my_homework %>
|
||||
<!-- 我的作品,在未开启匿评和未使用匿评,显示为编辑和删除 -->
|
||||
<% if bid.comment_status == 0 || bid.open_anonymous_evaluation == 0 %>
|
||||
<li class="wmine">
|
||||
<%= link_to l(:button_edit), edit_homework_attach_path(homework) %>
|
||||
<% if homework.user == User.current || User.current.admin? %>
|
||||
<!-- 作业创建者显示删除作业 -->
|
||||
<%= link_to(l(:label_bid_respond_delete), homework,
|
||||
method: :delete, :confirm => l(:text_are_you_sure), :remote => true ) %>
|
||||
<% else %>
|
||||
<!-- 作业参与者显示退出作业 -->
|
||||
<%= 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) %>
|
||||
<% end %>
|
||||
</li>
|
||||
<% else %>
|
||||
<li class="wmine" title="只有开启匿评之前才能修改和删除作业哦!">
|
||||
<a style="color:#8e8e8e;"><%= l(:button_edit) %></a>
|
||||
<% if homework.user == User.current || User.current.admin? %>
|
||||
<!-- 作业创建者显示删除作业 -->
|
||||
<a style="color:#8e8e8e;">
|
||||
<%=l(:label_bid_respond_delete)%>
|
||||
</a>
|
||||
<% else %>
|
||||
<!-- 作业参与者显示退出作业 -->
|
||||
<a style="color:#8e8e8e;">
|
||||
<%=l(:label_logout) %>
|
||||
</a>
|
||||
<% end %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% elsif is_student_batch_homework%>
|
||||
<!-- 学生匿评列表 -->
|
||||
<% if bid.comment_status == 1 %>
|
||||
<!-- 处于开启匿评阶段,可以正常评分 -->
|
||||
<li class="wping">
|
||||
<%= 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") %>
|
||||
<span class="c_red"> 迟交!</span>
|
||||
<% end %>
|
||||
</li>
|
||||
<% elsif bid.comment_status == 2%>
|
||||
<!-- 处于匿评已关闭阶段,不容许评分 -->
|
||||
<li class="wping" title="关闭匿评后不可继续评分">
|
||||
<a style="background:#8e8e8e;">
|
||||
<%= l(:label_anonymous_comments) %>
|
||||
</a>
|
||||
<% 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"> 迟交!</span>
|
||||
<% end %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<!-- 学生众评列表,显示为点赞 -->
|
||||
<li class="wzan" id="homeworl_praise_li_<%= homework.id%>">
|
||||
<%= render :partial => "homework_attach/homework_praise", locals: {:homework => homework} %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% bid = homework.bid%>
|
||||
<li class="pic_head" style="line-height: 1.2;">
|
||||
<% if is_student_batch_homework %>
|
||||
<!-- 学生匿评 不现实姓名、头像,以及相关的连接 -->
|
||||
<a><%= image_tag(url_to_avatar("匿名"), :width => "40", :height => "40")%></a>
|
||||
<a>匿名</a>
|
||||
<% else %>
|
||||
<%= link_to image_tag(url_to_avatar(homework.user), :width => "40", :height => "40"), user_path(homework.user) %>
|
||||
<span>
|
||||
<% 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 %>
|
||||
<%= link_to user_name, user_path(homework.user), :title => user_name %>
|
||||
</span>
|
||||
<% end %>
|
||||
</li>
|
||||
<li class="wname">
|
||||
<% if homework.name == nil || homework.name == "" %>
|
||||
<% homework_filename = homework.user.name + "提交的作业" %>
|
||||
<% else %>
|
||||
<% homework_filename = homework.name %>
|
||||
<% 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%>
|
||||
<span class="c_grey ">
|
||||
提交时间:
|
||||
<%= format_time homework.created_at%>
|
||||
</span>
|
||||
</li>
|
||||
<li class="wdown">
|
||||
<%= link_to "(#{homework.attachments.count.to_s}个附件)", zipdown_download_user_homework_path(:homework => homework)%>
|
||||
</li>
|
||||
<li class="wscore">
|
||||
<% unless is_student_batch_homework %>
|
||||
<%= l(:label_teacher_score)%>:
|
||||
<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)%>
|
||||
</span>
|
||||
|
||||
<% end %>
|
||||
</li>
|
||||
<li class="wscore">
|
||||
<%= is_student_batch_homework ? l(:label_my_score) : l(:label_student_score)%>:
|
||||
<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))%>
|
||||
</span>
|
||||
</li>
|
||||
<% if is_teacher %>
|
||||
<!-- 是老师,所有列表正常显示 -->
|
||||
<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 %>
|
||||
<% 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"> 迟交!</span>
|
||||
<% end %>
|
||||
</li>
|
||||
<% else %>
|
||||
<!-- 是学生 -->
|
||||
<% if is_my_homework %>
|
||||
<!-- 我的作品,在未开启匿评和未使用匿评,显示为编辑和删除 -->
|
||||
<% if bid.comment_status == 0 || bid.open_anonymous_evaluation == 0 %>
|
||||
<li class="wmine">
|
||||
<%= link_to l(:button_edit), edit_homework_attach_path(homework) %>
|
||||
<% if homework.user == User.current || User.current.admin? %>
|
||||
<!-- 作业创建者显示删除作业 -->
|
||||
<%= link_to(l(:label_bid_respond_delete), homework,
|
||||
method: :delete, :confirm => l(:text_are_you_sure), :remote => true ) %>
|
||||
<% else %>
|
||||
<!-- 作业参与者显示退出作业 -->
|
||||
<%= 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) %>
|
||||
<% end %>
|
||||
</li>
|
||||
<% else %>
|
||||
<li class="wmine" title="只有开启匿评之前才能修改和删除作业哦!">
|
||||
<a style="color:#8e8e8e;"><%= l(:button_edit) %></a>
|
||||
<% if homework.user == User.current || User.current.admin? %>
|
||||
<!-- 作业创建者显示删除作业 -->
|
||||
<a style="color:#8e8e8e;">
|
||||
<%=l(:label_bid_respond_delete)%>
|
||||
</a>
|
||||
<% else %>
|
||||
<!-- 作业参与者显示退出作业 -->
|
||||
<a style="color:#8e8e8e;">
|
||||
<%=l(:label_logout) %>
|
||||
</a>
|
||||
<% end %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% elsif is_student_batch_homework%>
|
||||
<!-- 学生匿评列表 -->
|
||||
<% if bid.comment_status == 1 %>
|
||||
<!-- 处于开启匿评阶段,可以正常评分 -->
|
||||
<li class="wping">
|
||||
<%= 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") %>
|
||||
<span class="c_red"> 迟交!</span>
|
||||
<% end %>
|
||||
</li>
|
||||
<% elsif bid.comment_status == 2%>
|
||||
<!-- 处于匿评已关闭阶段,不容许评分 -->
|
||||
<li class="wping" title="关闭匿评后不可继续评分">
|
||||
<a style="background:#8e8e8e;">
|
||||
<%= l(:label_anonymous_comments) %>
|
||||
</a>
|
||||
<% 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"> 迟交!</span>
|
||||
<% end %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<!-- 学生众评列表,显示为点赞 -->
|
||||
<li class="wzan" id="homeworl_praise_li_<%= homework.id%>">
|
||||
<%= render :partial => "homework_attach/homework_praise", locals: {:homework => homework} %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% end %>
|
|
@ -6,6 +6,7 @@
|
|||
per_page: number of items to fetch per page
|
||||
remote: data-remote
|
||||
-%>
|
||||
|
||||
<%= link_to_unless current_page.first?, l('views.pagination.first').html_safe, url, :remote => remote %>
|
||||
<li>
|
||||
<%= 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
|
||||
remote: data-remote
|
||||
-%>
|
||||
<span class="spacer">
|
||||
<%= raw(t 'views.pagination.truncate') %>
|
||||
</span>
|
||||
<li>
|
||||
<%= link_to raw(t 'views.pagination.truncate'),:class=>'c_blue' %>
|
||||
</li>
|
|
@ -6,6 +6,6 @@
|
|||
per_page: number of items to fetch per page
|
||||
remote: data-remote
|
||||
-%>
|
||||
|
||||
<%= link_to_unless current_page.last?, t('views.pagination.next').html_safe, url, :rel => 'next', :remote => remote %>
|
||||
|
||||
<li>
|
||||
<%= 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
|
||||
<%= link_to_unless page.current?, page, url, {:remote => remote, :rel => page.next? ? 'next' : page.prev? ? 'prev' : nil}
|
||||
-%>
|
||||
|
||||
<%= 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} %>
|
||||
|
||||
<li class='<%= page.current? ? "wlist_select" : "" %>'>
|
||||
<%= 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.render do -%>
|
||||
<div id="paginator" class="pagination">
|
||||
<%= first_page_tag unless current_page.first? %>
|
||||
<ul id="paginator" class="wlist">
|
||||
<%#= first_page_tag unless current_page.first? %>
|
||||
<%= prev_page_tag unless current_page.first? %>
|
||||
<% each_page do |page| -%>
|
||||
<% if page.left_outer? || page.right_outer? || page.inside_window? -%>
|
||||
|
@ -18,6 +18,6 @@
|
|||
<% end -%>
|
||||
<% end -%>
|
||||
<%= next_page_tag unless current_page.last? %>
|
||||
<%= last_page_tag unless current_page.last? %>
|
||||
</div>
|
||||
<!--<%#= last_page_tag unless current_page.last? %>-->
|
||||
</ul>
|
||||
<% end -%>
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
per_page: number of items to fetch per page
|
||||
remote: data-remote
|
||||
-%>
|
||||
|
||||
<%= link_to_unless current_page.first?, t('views.pagination.previous').html_safe, url, :rel => 'prev', :remote => remote %>
|
||||
<li >
|
||||
<%= 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 %>
|
||||
<% teacher_num = teacherCount(@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)) %>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
@ -47,7 +48,7 @@
|
|||
</div>
|
||||
<div class="search fl">
|
||||
<%= 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" >
|
||||
<%= l(:label_search)%>
|
||||
</a>
|
||||
|
@ -94,7 +95,7 @@
|
|||
<span>| </span>
|
||||
<%= l(:label_account_identity_student)%>(<%= course_student_link student_num %>)
|
||||
<span>| </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><!--课程信息 end-->
|
||||
<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 %>
|
||||
</div>
|
||||
<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 class="subNav">
|
||||
<%= link_to l(:label_course_board), course_boards_path(@course), :class => "f14 c_blue02" %>
|
||||
|
|
|
@ -1,373 +1,373 @@
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="content">
|
||||
<h4 class="wmail_h4" style="color:#474646; font-size:14px; margin-bottom:5px;" >
|
||||
<%= @subject %>
|
||||
</h4>
|
||||
<% if @attachments.first || @course_news.first || @bids.first ||
|
||||
@homeworks.first || @course_journal_messages.first|| @course_messages.first %>
|
||||
<div class="wmail_main" style="padding:20px 10px 0px;">
|
||||
<h2 class="wmail_h2" style="color:#15bccf; "><%= l(:label_course_overview)%></h2>
|
||||
<% 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;">
|
||||
|
||||
<h4 class="wmail_h4" style="color:#474646; font-size:14px; margin-bottom:5px;" >
|
||||
<%= l(:label_course_news) %>
|
||||
<span class="wmail_num" style="color:#fe3f0c; margin-left:5px; font-weight:normal;">(<%= @course_news.count %>)</span>
|
||||
</h4>
|
||||
|
||||
<% @course_news.each do |course_new|%>
|
||||
<li style="clear: both; list-style: none;">
|
||||
<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>
|
||||
|
||||
<%= link_to truncate(course_new.course.name,length: 30,omission: '...'), course_url(course_new.course, :token => @token.value),
|
||||
:class=> "wmail_column",
|
||||
: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>
|
||||
|
||||
<%= 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;"%>
|
||||
<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),
|
||||
:class => 'wmail_info',
|
||||
: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>
|
||||
</li>
|
||||
<% end %>
|
||||
|
||||
<div class="cl"></div>
|
||||
</ul><!--课程动态 end-->
|
||||
<% end %>
|
||||
<% 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;">
|
||||
|
||||
<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?%>
|
||||
<% @bids.each do |bid| %>
|
||||
<li style="clear: both; list-style: none;">
|
||||
<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>
|
||||
|
||||
<%= link_to truncate(bid.courses.first.name,length: 30,omission: '...'), course_url(bid.courses.first, :token => @token.value),
|
||||
:class=> "wmail_column",
|
||||
: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>
|
||||
|
||||
<%= 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;"%>
|
||||
<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),
|
||||
:class => 'wmail_info',
|
||||
: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>
|
||||
</li>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% unless @homeworks.first.nil? %>
|
||||
<% @homeworks.each do |homework| %>
|
||||
<li style="clear: both; list-style: none;">
|
||||
<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>
|
||||
|
||||
<%= link_to truncate(homework.bid.courses.first.name,length: 30,omission: '...'), course_url(homework.bid.courses.first, :token => @token.value),
|
||||
:class=> "wmail_column",
|
||||
: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>
|
||||
|
||||
<%= 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;"%>
|
||||
<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),
|
||||
:class => 'wmail_info',
|
||||
: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>
|
||||
</li>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<div class="cl"></div>
|
||||
</ul><!--作业动态 end-->
|
||||
<% end %>
|
||||
|
||||
<% 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;">
|
||||
|
||||
<h4 class="wmail_h4" style="color:#474646; font-size:14px; margin-bottom:5px;" >
|
||||
<%= l(:view_course_journals_for_messages) %>
|
||||
<span class="wmail_num" style="color:#fe3f0c; margin-left:5px; font-weight:normal;">(<%= @course_journal_messages.count %>)</span>
|
||||
</h4>
|
||||
|
||||
<% @course_journal_messages.each do |course_journal_message|%>
|
||||
<li style="clear: both; list-style: none;">
|
||||
<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>
|
||||
|
||||
<%= link_to truncate(course_journal_message.course.name,length: 30,omission: '...'), course_url(course_journal_message.course, :token => @token.value),
|
||||
:class=> "wmail_column",
|
||||
: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>
|
||||
|
||||
<%= 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;"%>
|
||||
<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),
|
||||
:class => 'wmail_info',
|
||||
: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>
|
||||
</li>
|
||||
<% end %>
|
||||
|
||||
<div class="cl"></div>
|
||||
</ul><!--课程留言 end-->
|
||||
<% end %>
|
||||
|
||||
<% 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;">
|
||||
|
||||
<h4 class="wmail_h4" style="color:#474646; font-size:14px; margin-bottom:5px;" >
|
||||
<%= l(:view_borad_course) %>
|
||||
<span class="wmail_num" style="color:#fe3f0c; margin-left:5px; font-weight:normal;">(<%= @course_journal_messages.count %>)</span>
|
||||
</h4>
|
||||
|
||||
<% @course_messages.each do |course_message|%>
|
||||
<li style="clear: both; list-style: none;">
|
||||
<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>
|
||||
|
||||
<%= link_to truncate(course_message.course.name,length: 30,omission: '...'), course_url(course_message.course.id, :token => @token.value),
|
||||
:class=> "wmail_column",
|
||||
: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>
|
||||
|
||||
<%= 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;"%>
|
||||
<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),
|
||||
:class => 'wmail_info',
|
||||
: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>
|
||||
</li>
|
||||
<% end %>
|
||||
|
||||
<div class="cl"></div>
|
||||
</ul><!--课程讨论 end-->
|
||||
<% end %>
|
||||
|
||||
<% 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;">
|
||||
<h4 class="wmail_h4" style="color:#474646; font-size:14px; margin-bottom:5px;" >
|
||||
<%= l(:label_course_attendingcontestwork_download) %>
|
||||
<span class="wmail_num" style="color:#fe3f0c; margin-left:5px; font-weight:normal;">(<%= @attachments.count %>)</span>
|
||||
</h4>
|
||||
|
||||
<% @attachments.each do |attachment|%>
|
||||
<li style="clear: both; list-style: none;">
|
||||
<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>
|
||||
|
||||
<%= link_to truncate(attachment.course.name,length: 30,omission: '...'), course_url(attachment.course, :token => @token.value),
|
||||
:class=> "wmail_column",
|
||||
: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>
|
||||
|
||||
<%= 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;"%>
|
||||
<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),
|
||||
:class => 'wmail_info',
|
||||
: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>
|
||||
</li>
|
||||
<% end %>
|
||||
<div class="cl"></div>
|
||||
</ul><!--课件下载 end-->
|
||||
<% end %>
|
||||
</div><!--课程动态 end-->
|
||||
<% end %>
|
||||
<% if @issues.first || @project_messages.first %>
|
||||
<div class="wmail_main" style="padding:20px 10px 0px;">
|
||||
<h2 class="wmail_h2" style="color:#15bccf; "><%= l(:label_project_overview_new)%></h2>
|
||||
<% 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;">
|
||||
<h4 class="wmail_h4" style="color:#474646; font-size:14px; margin-bottom:5px;" >
|
||||
<%= l(:label_issue_tracking) %>
|
||||
<span class="wmail_num" style="color:#fe3f0c; margin-left:5px; font-weight:normal;">(<%= @issues.count %>)</span>
|
||||
</h4>
|
||||
|
||||
<% @issues.each do |issue|%>
|
||||
<li style="clear: both; list-style: none;">
|
||||
<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>
|
||||
|
||||
<%= link_to truncate(issue.project.name,length: 30,omission: '...'), project_url(issue.project, :token => @token.value),
|
||||
:class=> "wmail_column",
|
||||
: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>
|
||||
|
||||
<%= 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;"%>
|
||||
<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),
|
||||
:class => 'wmail_info',
|
||||
: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>
|
||||
</li>
|
||||
<% end %>
|
||||
|
||||
<div class="cl"></div>
|
||||
</ul><!--问题跟踪 end-->
|
||||
<% end %>
|
||||
|
||||
<% 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;">
|
||||
<h4 class="wmail_h4" style="color:#474646; font-size:14px; margin-bottom:5px;" >
|
||||
<%= l(:project_moule_boards_show) %>
|
||||
<span class="wmail_num" style="color:#fe3f0c; margin-left:5px; font-weight:normal;">(<%= @project_messages.count %>)</span>
|
||||
</h4>
|
||||
|
||||
<% @project_messages.each do |project_message|%>
|
||||
<li style="clear: both; list-style: none;">
|
||||
<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>
|
||||
|
||||
<%= link_to truncate(project_message.project.name,length: 30,omission: '...'), project_url(project_message.project, :token => @token.value),
|
||||
:class=> "wmail_column",
|
||||
: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>
|
||||
|
||||
<%= 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;"%>
|
||||
<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),
|
||||
:class => 'wmail_info',
|
||||
: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>
|
||||
</li>
|
||||
<% end %>
|
||||
|
||||
<div class="cl"></div>
|
||||
</ul><!--项目论坛 end-->
|
||||
<% end %>
|
||||
|
||||
|
||||
|
||||
</div><!--项目动态 end-->
|
||||
<% end %>
|
||||
<% unless @user_journal_messages.first.nil? %>
|
||||
<div class="wmail_main" style="padding:20px 10px 0px;">
|
||||
<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;">
|
||||
<h4 class="wmail_h4" style="color:#474646; font-size:14px; margin-bottom:5px;" >
|
||||
<%= l(:label_user_message) %>
|
||||
<span class="wmail_num" style="color:#fe3f0c; margin-left:5px; font-weight:normal;">(<%= @user_journal_messages.count %>)</span>
|
||||
</h4>
|
||||
|
||||
<% @user_journal_messages.each do |user_journal_message|%>
|
||||
<li style="clear: both; list-style: none;">
|
||||
<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),
|
||||
:class => "wmail_name",
|
||||
: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>
|
||||
|
||||
<%= link_to truncate(user_journal_message.notes,length: 30,omission: '...'),feedback_url(@user,:token => @token.value),
|
||||
:class => 'wmail_info',
|
||||
: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>
|
||||
|
||||
<% end %>
|
||||
|
||||
<div class="cl"></div>
|
||||
</ul><!--课程动态 end-->
|
||||
|
||||
</div><!--个人动态 end-->
|
||||
<% end %>
|
||||
<% if @forums.first || @memos.first %>
|
||||
<div class="wmail_main" style="padding:20px 10px 0px;">
|
||||
<h2 class="wmail_h2" style="color:#15bccf; "><%= l(:lable_bar_active) %></h2>
|
||||
<% 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;">
|
||||
<h4 class="wmail_h4" style="color:#474646; font-size:14px; margin-bottom:5px;" >
|
||||
<%= l(:label_user_forum) %>
|
||||
<span class="wmail_num" style="color:#fe3f0c; margin-left:5px; font-weight:normal;">(<%= @forums.count %>)</span>
|
||||
</h4>
|
||||
|
||||
<% @forums.each do |forum|%>
|
||||
<li style="clear: both; list-style: none;">
|
||||
<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),
|
||||
:class => "wmail_name",
|
||||
: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>
|
||||
|
||||
<%= link_to truncate(forum.name,length: 30,omission: '...'),forum_url(forum,:token => @token.value),
|
||||
:class => 'wmail_info',
|
||||
: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>
|
||||
|
||||
<% end %>
|
||||
|
||||
<div class="cl"></div>
|
||||
</ul><!-- 新建贴吧 end-->
|
||||
<% end %>
|
||||
<% 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;">
|
||||
<h4 class="wmail_h4" style="color:#474646; font-size:14px; margin-bottom:5px;" >
|
||||
<%= l(:label_user_message_forum) %>
|
||||
<span class="wmail_num" style="color:#fe3f0c; margin-left:5px; font-weight:normal;">(<%= @memos.count %>)</span>
|
||||
</h4>
|
||||
|
||||
<% @memos.each do |memo|%>
|
||||
<li style="clear: both; list-style: none;">
|
||||
<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),
|
||||
:class => "wmail_name",
|
||||
: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>
|
||||
|
||||
<%= link_to truncate(memo.subject,length: 30,omission: '...'),forum_memo_url(memo.forum, (memo.parent_id.nil? ? memo : memo.parent_id)),
|
||||
:class => 'wmail_info',
|
||||
: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>
|
||||
|
||||
<% end %>
|
||||
|
||||
<div class="cl"></div>
|
||||
</ul><!-- 新建贴吧 end-->
|
||||
<% end %>
|
||||
</div><!--贴吧动态 end-->
|
||||
<% end %>
|
||||
<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;" %>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="content">
|
||||
<h4 class="wmail_h4" style="color:#474646; font-size:14px; margin-bottom:5px;" >
|
||||
<%= @subject %>
|
||||
</h4>
|
||||
<% if @attachments.first || @course_news.first || @bids.first ||
|
||||
@homeworks.first || @course_journal_messages.first|| @course_messages.first %>
|
||||
<div class="wmail_main" style="padding:20px 10px 0px;">
|
||||
<h2 class="wmail_h2" style="color:#15bccf; "><%= l(:label_course_overview)%></h2>
|
||||
<% 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;">
|
||||
|
||||
<h4 class="wmail_h4" style="color:#474646; font-size:14px; margin-bottom:5px;" >
|
||||
<%= l(:label_course_news) %>
|
||||
<span class="wmail_num" style="color:#fe3f0c; margin-left:5px; font-weight:normal;">(<%= @course_news.count %>)</span>
|
||||
</h4>
|
||||
|
||||
<% @course_news.each do |course_new|%>
|
||||
<li style="clear: both; list-style: none;">
|
||||
<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>
|
||||
|
||||
<%= link_to truncate(course_new.course.name,length: 30,omission: '...'), course_url(course_new.course, :token => @token.value),
|
||||
:class=> "wmail_column",
|
||||
: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>
|
||||
|
||||
<%= 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;"%>
|
||||
<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),
|
||||
:class => 'wmail_info',
|
||||
: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>
|
||||
</li>
|
||||
<% end %>
|
||||
|
||||
<div class="cl"></div>
|
||||
</ul><!--课程动态 end-->
|
||||
<% end %>
|
||||
<% 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;">
|
||||
|
||||
<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?%>
|
||||
<% @bids.each do |bid| %>
|
||||
<li style="clear: both; list-style: none;">
|
||||
<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>
|
||||
|
||||
<%= link_to truncate(bid.courses.first.name,length: 30,omission: '...'), course_url(bid.courses.first, :token => @token.value),
|
||||
:class=> "wmail_column",
|
||||
: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>
|
||||
|
||||
<%= 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;"%>
|
||||
<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),
|
||||
:class => 'wmail_info',
|
||||
: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>
|
||||
</li>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% unless @homeworks.first.nil? %>
|
||||
<% @homeworks.each do |homework| %>
|
||||
<li style="clear: both; list-style: none;">
|
||||
<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>
|
||||
|
||||
<%= link_to truncate(homework.bid.courses.first.name,length: 30,omission: '...'), course_url(homework.bid.courses.first, :token => @token.value),
|
||||
:class=> "wmail_column",
|
||||
: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>
|
||||
|
||||
<%= 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;"%>
|
||||
<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),
|
||||
:class => 'wmail_info',
|
||||
: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_at) %></span>
|
||||
</li>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<div class="cl"></div>
|
||||
</ul><!--作业动态 end-->
|
||||
<% end %>
|
||||
|
||||
<% 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;">
|
||||
|
||||
<h4 class="wmail_h4" style="color:#474646; font-size:14px; margin-bottom:5px;" >
|
||||
<%= l(:view_course_journals_for_messages) %>
|
||||
<span class="wmail_num" style="color:#fe3f0c; margin-left:5px; font-weight:normal;">(<%= @course_journal_messages.count %>)</span>
|
||||
</h4>
|
||||
|
||||
<% @course_journal_messages.each do |course_journal_message|%>
|
||||
<li style="clear: both; list-style: none;">
|
||||
<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>
|
||||
|
||||
<%= link_to truncate(course_journal_message.course.name,length: 30,omission: '...'), course_url(course_journal_message.course, :token => @token.value),
|
||||
:class=> "wmail_column",
|
||||
: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>
|
||||
|
||||
<%= 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;"%>
|
||||
<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),
|
||||
:class => 'wmail_info',
|
||||
: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>
|
||||
</li>
|
||||
<% end %>
|
||||
|
||||
<div class="cl"></div>
|
||||
</ul><!--课程留言 end-->
|
||||
<% end %>
|
||||
|
||||
<% 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;">
|
||||
|
||||
<h4 class="wmail_h4" style="color:#474646; font-size:14px; margin-bottom:5px;" >
|
||||
<%= l(:view_borad_course) %>
|
||||
<span class="wmail_num" style="color:#fe3f0c; margin-left:5px; font-weight:normal;">(<%= @course_journal_messages.count %>)</span>
|
||||
</h4>
|
||||
|
||||
<% @course_messages.each do |course_message|%>
|
||||
<li style="clear: both; list-style: none;">
|
||||
<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>
|
||||
|
||||
<%= link_to truncate(course_message.course.name,length: 30,omission: '...'), course_url(course_message.course.id, :token => @token.value),
|
||||
:class=> "wmail_column",
|
||||
: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>
|
||||
|
||||
<%= 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;"%>
|
||||
<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),
|
||||
:class => 'wmail_info',
|
||||
: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>
|
||||
</li>
|
||||
<% end %>
|
||||
|
||||
<div class="cl"></div>
|
||||
</ul><!--课程讨论 end-->
|
||||
<% end %>
|
||||
|
||||
<% 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;">
|
||||
<h4 class="wmail_h4" style="color:#474646; font-size:14px; margin-bottom:5px;" >
|
||||
<%= l(:label_course_attendingcontestwork_download) %>
|
||||
<span class="wmail_num" style="color:#fe3f0c; margin-left:5px; font-weight:normal;">(<%= @attachments.count %>)</span>
|
||||
</h4>
|
||||
|
||||
<% @attachments.each do |attachment|%>
|
||||
<li style="clear: both; list-style: none;">
|
||||
<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>
|
||||
|
||||
<%= link_to truncate(attachment.course.name,length: 30,omission: '...'), course_url(attachment.course, :token => @token.value),
|
||||
:class=> "wmail_column",
|
||||
: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>
|
||||
|
||||
<%= 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;"%>
|
||||
<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),
|
||||
:class => 'wmail_info',
|
||||
: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>
|
||||
</li>
|
||||
<% end %>
|
||||
<div class="cl"></div>
|
||||
</ul><!--课件下载 end-->
|
||||
<% end %>
|
||||
</div><!--课程动态 end-->
|
||||
<% end %>
|
||||
<% if @issues.first || @project_messages.first %>
|
||||
<div class="wmail_main" style="padding:20px 10px 0px;">
|
||||
<h2 class="wmail_h2" style="color:#15bccf; "><%= l(:label_project_overview_new)%></h2>
|
||||
<% 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;">
|
||||
<h4 class="wmail_h4" style="color:#474646; font-size:14px; margin-bottom:5px;" >
|
||||
<%= l(:label_issue_tracking) %>
|
||||
<span class="wmail_num" style="color:#fe3f0c; margin-left:5px; font-weight:normal;">(<%= @issues.count %>)</span>
|
||||
</h4>
|
||||
|
||||
<% @issues.each do |issue|%>
|
||||
<li style="clear: both; list-style: none;">
|
||||
<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>
|
||||
|
||||
<%= link_to truncate(issue.project.name,length: 30,omission: '...'), project_url(issue.project, :token => @token.value),
|
||||
:class=> "wmail_column",
|
||||
: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>
|
||||
|
||||
<%= 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;"%>
|
||||
<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),
|
||||
:class => 'wmail_info',
|
||||
: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>
|
||||
</li>
|
||||
<% end %>
|
||||
|
||||
<div class="cl"></div>
|
||||
</ul><!--问题跟踪 end-->
|
||||
<% end %>
|
||||
|
||||
<% 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;">
|
||||
<h4 class="wmail_h4" style="color:#474646; font-size:14px; margin-bottom:5px;" >
|
||||
<%= l(:project_moule_boards_show) %>
|
||||
<span class="wmail_num" style="color:#fe3f0c; margin-left:5px; font-weight:normal;">(<%= @project_messages.count %>)</span>
|
||||
</h4>
|
||||
|
||||
<% @project_messages.each do |project_message|%>
|
||||
<li style="clear: both; list-style: none;">
|
||||
<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>
|
||||
|
||||
<%= link_to truncate(project_message.project.name,length: 30,omission: '...'), project_url(project_message.project, :token => @token.value),
|
||||
:class=> "wmail_column",
|
||||
: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>
|
||||
|
||||
<%= 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;"%>
|
||||
<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),
|
||||
:class => 'wmail_info',
|
||||
: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>
|
||||
</li>
|
||||
<% end %>
|
||||
|
||||
<div class="cl"></div>
|
||||
</ul><!--项目论坛 end-->
|
||||
<% end %>
|
||||
|
||||
|
||||
|
||||
</div><!--项目动态 end-->
|
||||
<% end %>
|
||||
<% unless @user_journal_messages.first.nil? %>
|
||||
<div class="wmail_main" style="padding:20px 10px 0px;">
|
||||
<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;">
|
||||
<h4 class="wmail_h4" style="color:#474646; font-size:14px; margin-bottom:5px;" >
|
||||
<%= l(:label_user_message) %>
|
||||
<span class="wmail_num" style="color:#fe3f0c; margin-left:5px; font-weight:normal;">(<%= @user_journal_messages.count %>)</span>
|
||||
</h4>
|
||||
|
||||
<% @user_journal_messages.each do |user_journal_message|%>
|
||||
<li style="clear: both; list-style: none;">
|
||||
<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),
|
||||
:class => "wmail_name",
|
||||
: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>
|
||||
|
||||
<%= link_to truncate(user_journal_message.notes,length: 30,omission: '...'),feedback_url(@user,:token => @token.value),
|
||||
:class => 'wmail_info',
|
||||
: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>
|
||||
|
||||
<% end %>
|
||||
|
||||
<div class="cl"></div>
|
||||
</ul><!--课程动态 end-->
|
||||
|
||||
</div><!--个人动态 end-->
|
||||
<% end %>
|
||||
<% if @forums.first || @memos.first %>
|
||||
<div class="wmail_main" style="padding:20px 10px 0px;">
|
||||
<h2 class="wmail_h2" style="color:#15bccf; "><%= l(:lable_bar_active) %></h2>
|
||||
<% 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;">
|
||||
<h4 class="wmail_h4" style="color:#474646; font-size:14px; margin-bottom:5px;" >
|
||||
<%= l(:label_user_forum) %>
|
||||
<span class="wmail_num" style="color:#fe3f0c; margin-left:5px; font-weight:normal;">(<%= @forums.count %>)</span>
|
||||
</h4>
|
||||
|
||||
<% @forums.each do |forum|%>
|
||||
<li style="clear: both; list-style: none;">
|
||||
<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),
|
||||
:class => "wmail_name",
|
||||
: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>
|
||||
|
||||
<%= link_to truncate(forum.name,length: 30,omission: '...'),forum_url(forum,:token => @token.value),
|
||||
:class => 'wmail_info',
|
||||
: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>
|
||||
|
||||
<% end %>
|
||||
|
||||
<div class="cl"></div>
|
||||
</ul><!-- 新建贴吧 end-->
|
||||
<% end %>
|
||||
<% 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;">
|
||||
<h4 class="wmail_h4" style="color:#474646; font-size:14px; margin-bottom:5px;" >
|
||||
<%= l(:label_user_message_forum) %>
|
||||
<span class="wmail_num" style="color:#fe3f0c; margin-left:5px; font-weight:normal;">(<%= @memos.count %>)</span>
|
||||
</h4>
|
||||
|
||||
<% @memos.each do |memo|%>
|
||||
<li style="clear: both; list-style: none;">
|
||||
<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),
|
||||
:class => "wmail_name",
|
||||
: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>
|
||||
|
||||
<%= link_to truncate(memo.subject,length: 30,omission: '...'),forum_memo_url(memo.forum, (memo.parent_id.nil? ? memo : memo.parent_id)),
|
||||
:class => 'wmail_info',
|
||||
: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>
|
||||
|
||||
<% end %>
|
||||
|
||||
<div class="cl"></div>
|
||||
</ul><!-- 新建贴吧 end-->
|
||||
<% end %>
|
||||
</div><!--贴吧动态 end-->
|
||||
<% end %>
|
||||
<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;" %>
|
||||
</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">
|
||||
<h2 class="project_h2"><%= l(:label_board) %></h2>
|
||||
</div>
|
||||
|
@ -24,7 +55,7 @@
|
|||
:class => 'talk_edit fr'
|
||||
) if @message.course_destroyable_by?(User.current) %>
|
||||
<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>
|
||||
<!-- <a href="#" class=" link_file ml60">附件:爱覅俄方if.zip(27.5kB)</a>-->
|
||||
<div class="cl"></div>
|
||||
|
@ -52,7 +83,7 @@
|
|||
<%= link_to_user_header message.author,false,:class => 'c_blue fb fl mb10 ' %>
|
||||
<span class="c_grey fr"><%= format_time(message.created_on) %></span>
|
||||
<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 %>
|
||||
</div>
|
||||
<div class="ping_disfoot">
|
||||
|
@ -87,7 +118,7 @@
|
|||
<div id="reply" style="display:none;">
|
||||
<%= 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} %>
|
||||
<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 %>
|
||||
<div id="preview" class="wiki"></div>
|
||||
</div>
|
||||
|
@ -97,32 +128,3 @@
|
|||
</ul>
|
||||
<% 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' %>
|
||||
<% replying ||= false %>
|
||||
<% 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>
|
||||
<label class="fl" ><span class="c_red">*</span> <%= l(:field_description) %> :</label>
|
||||
<%= 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>
|
||||
<p id="message_content_span" class="ml55"></p>
|
||||
</li>
|
||||
|
|
|
@ -1,12 +1,21 @@
|
|||
<%= javascript_include_tag "/assets/kindeditor/kindeditor" %>
|
||||
<li class="ml45">
|
||||
<label><span class="c_red">*</span> <%= l(:field_title) %> :</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 %>">
|
||||
<p id="title_notice_span" class="ml55"></p>
|
||||
</li>
|
||||
<li class="ml45">
|
||||
<label class="fl" ><span class="c_red">*</span> <%= l(:field_description) %> :</label>
|
||||
<textarea id="news_description" name="news[description]" placeholder="最多3000个汉字(或6000个英文字符)" class="hwork_text fl" onkeyup="regexDescription();" maxlength="6000"><%= is_new ? '' : @news.description %></textarea>
|
||||
<p id="description_notice_span" class="ml55"></p>
|
||||
<% if is_new %>
|
||||
<%= hidden_field_tag :asset_id,params[:asset_id],:required => false,:style => 'display:none' %>
|
||||
<label class="fl" ><span class="c_red">*</span> <%= l(:field_description) %> :</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> <%= l(:field_description) %> :</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>
|
||||
<div class="cl"></div>
|
||||
<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_cancel), course_news_index_path(@course), :onclick => '$("#add-news").hide()', :class => 'blue_btn grey_btn fl c_white' %>
|
||||
<% 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' %>
|
||||
<% end %>
|
||||
<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) %>
|
||||
<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>
|
||||
<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>
|
||||
<div class="cl"></div>
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
|
||||
function submitNews()
|
||||
{
|
||||
news_description_editor.sync();
|
||||
if(regexTitle() && regexDescription())
|
||||
{
|
||||
$("#news-form").submit();
|
||||
|
@ -51,6 +52,7 @@
|
|||
}
|
||||
function submitComment()
|
||||
{
|
||||
comment_editor.sync();
|
||||
$("#add_comment_form").submit();
|
||||
}
|
||||
function clearMessage()
|
||||
|
@ -58,7 +60,7 @@
|
|||
$("#comment_comments").val("");
|
||||
}
|
||||
</script>
|
||||
|
||||
<%= javascript_include_tag "/assets/kindeditor/kindeditor" %>
|
||||
<div class="project_r_h">
|
||||
<h2 class="project_h2"><%= l(:label_course_news) %></h2>
|
||||
</div>
|
||||
|
@ -84,7 +86,7 @@
|
|||
: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) %>
|
||||
<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 %>
|
||||
<!--<a href="#" class=" link_file">附件:爱覅俄方if.zip(27.5kB)</a> -->
|
||||
</div>
|
||||
|
@ -95,8 +97,9 @@
|
|||
<div class="msg_box">
|
||||
<h4><%= l(:label_comment_add) %></h4>
|
||||
<%= form_tag({:controller => 'comments', :action => 'create', :id => @news}, :id => "add_comment_form") do %>
|
||||
<div class="box">
|
||||
<%= text_area 'comment', 'comments', :placeholder=>"最多250个字"%>
|
||||
<div class="box" >
|
||||
<%= 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>
|
||||
<p>
|
||||
<a href="#" class="grey_btn fr ml10" onclick="clearMessage();"><%= l(:label_cancel_with_space) %></a>
|
||||
|
@ -106,6 +109,7 @@
|
|||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% comments = @comments.reverse %>
|
||||
<% comments.each do |comment| %>
|
||||
<% next if comment.new_record? %>
|
||||
|
@ -115,7 +119,7 @@
|
|||
<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>
|
||||
<div class="cl"></div>
|
||||
<p><%= textilizable(comment.comments) %></p>
|
||||
<p><%= textAreailizable(comment.comments) %></p>
|
||||
</div>
|
||||
<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) %>
|
||||
|
|
|
@ -130,4 +130,4 @@
|
|||
<% 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 'rails/all'
|
||||
require 'sprockets/railtie'
|
||||
|
||||
if defined?(Bundler)
|
||||
# If you precompile assets before deploying to production, use this line
|
||||
Bundler.require(*Rails.groups(:assets => %w(development test)))
|
||||
# If you want your assets lazily compiled in production, use this line
|
||||
# Bundler.require(:default, :assets, Rails.env)
|
||||
end
|
||||
|
||||
module RedmineApp
|
||||
class Application < Rails::Application
|
||||
# Settings in config/environments/* take precedence over those specified here.
|
||||
# Application configuration should go into files in config/initializers
|
||||
# -- all .rb files in that directory are automatically loaded.
|
||||
|
||||
#verifier if email is real
|
||||
|
||||
|
||||
config.generators do |g|
|
||||
g.test_framework :rspec,
|
||||
fixtures: true,
|
||||
view_specs: false,
|
||||
helper_specs: false,
|
||||
routing_specs: false,
|
||||
controller_specs: true,
|
||||
request_specs: false
|
||||
g.fixture_replacement :factory_girl, dir: "spec/factories"
|
||||
end
|
||||
# Custom directories with classes and modules you want to be autoloadable.
|
||||
config.autoload_paths += %W(#{config.root}/lib)
|
||||
|
||||
# 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.
|
||||
# config.plugins = [ :exception_notification, :ssl_requirement, :all ]
|
||||
|
||||
# Activate observers that should always be running.
|
||||
config.active_record.observers = :journals_for_message_observer, :message_observer, :issue_observer, :journal_observer, :news_observer,
|
||||
:document_observer, :wiki_content_observer, :comment_observer, :forum_observer, :memo_observer
|
||||
|
||||
config.active_record.store_full_sti_class = true
|
||||
config.active_record.default_timezone = :local
|
||||
|
||||
# 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.
|
||||
# config.time_zone = 'Central Time (US & Canada)'
|
||||
|
||||
# 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.default_locale = :de
|
||||
|
||||
# Configure the default encoding used in templates for Ruby 1.9.
|
||||
config.encoding = "utf-8"
|
||||
|
||||
# Configure sensitive parameters which will be filtered from the log file.
|
||||
config.filter_parameters += [:password]
|
||||
|
||||
# Enable the asset pipeline
|
||||
config.assets.enabled = false
|
||||
|
||||
# Version of your assets, change this if you want to expire all your assets
|
||||
config.assets.version = '1.0'
|
||||
|
||||
config.action_mailer.perform_deliveries = false
|
||||
|
||||
# Do not include all helpers
|
||||
config.action_controller.include_all_helpers = false
|
||||
|
||||
config.session_store :cookie_store, :key => '_redmine_session'
|
||||
|
||||
if File.exists?(File.join(File.dirname(__FILE__), 'additional_environment.rb'))
|
||||
instance_eval File.read(File.join(File.dirname(__FILE__), 'additional_environment.rb'))
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
require File.expand_path('../boot', __FILE__)
|
||||
|
||||
require 'rails/all'
|
||||
require 'sprockets/railtie'
|
||||
|
||||
if defined?(Bundler)
|
||||
# If you precompile assets before deploying to production, use this line
|
||||
Bundler.require(*Rails.groups(:assets => %w(development test)))
|
||||
# If you want your assets lazily compiled in production, use this line
|
||||
# Bundler.require(:default, :assets, Rails.env)
|
||||
end
|
||||
|
||||
module RedmineApp
|
||||
class Application < Rails::Application
|
||||
# Settings in config/environments/* take precedence over those specified here.
|
||||
# Application configuration should go into files in config/initializers
|
||||
# -- all .rb files in that directory are automatically loaded.
|
||||
|
||||
#verifier if email is real
|
||||
|
||||
|
||||
config.generators do |g|
|
||||
g.test_framework :rspec,
|
||||
fixtures: true,
|
||||
view_specs: false,
|
||||
helper_specs: false,
|
||||
routing_specs: false,
|
||||
controller_specs: true,
|
||||
request_specs: false
|
||||
g.fixture_replacement :factory_girl, dir: "spec/factories"
|
||||
end
|
||||
# Custom directories with classes and modules you want to be autoloadable.
|
||||
config.autoload_paths += %W(#{config.root}/lib)
|
||||
|
||||
# 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.
|
||||
# config.plugins = [ :exception_notification, :ssl_requirement, :all ]
|
||||
|
||||
# Activate observers that should always be running.
|
||||
config.active_record.observers = :journals_for_message_observer, :issue_observer, :journal_observer, :wiki_content_observer
|
||||
|
||||
config.active_record.store_full_sti_class = true
|
||||
config.active_record.default_timezone = :local
|
||||
|
||||
# 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.
|
||||
# config.time_zone = 'Central Time (US & Canada)'
|
||||
|
||||
# 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.default_locale = :de
|
||||
|
||||
# Configure the default encoding used in templates for Ruby 1.9.
|
||||
config.encoding = "utf-8"
|
||||
|
||||
# Configure sensitive parameters which will be filtered from the log file.
|
||||
config.filter_parameters += [:password]
|
||||
|
||||
# Enable the asset pipeline
|
||||
config.assets.enabled = false
|
||||
|
||||
# Version of your assets, change this if you want to expire all your assets
|
||||
config.assets.version = '1.0'
|
||||
|
||||
config.action_mailer.perform_deliveries = false
|
||||
|
||||
# Do not include all helpers
|
||||
config.action_controller.include_all_helpers = false
|
||||
|
||||
config.session_store :cookie_store, :key => '_redmine_session'
|
||||
|
||||
if File.exists?(File.join(File.dirname(__FILE__), 'additional_environment.rb'))
|
||||
instance_eval File.read(File.join(File.dirname(__FILE__), 'additional_environment.rb'))
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,212 +1,209 @@
|
|||
# = Redmine configuration file
|
||||
#
|
||||
# Each environment has it's own configuration options. If you are only
|
||||
# running in production, only the production block needs to be configured.
|
||||
# Environment specific configuration options override the default ones.
|
||||
#
|
||||
# Note that this file needs to be a valid YAML file.
|
||||
# DO NOT USE TABS! Use 2 spaces instead of tabs for identation.
|
||||
#
|
||||
# == Outgoing email settings (email_delivery setting)
|
||||
#
|
||||
# === Common configurations
|
||||
#
|
||||
# ==== Sendmail command
|
||||
#
|
||||
# production:
|
||||
# email_delivery:
|
||||
# delivery_method: :sendmail
|
||||
#
|
||||
# ==== Simple SMTP server at localhost
|
||||
#
|
||||
# production:
|
||||
# email_delivery:
|
||||
# delivery_method: :smtp
|
||||
# smtp_settings:
|
||||
# address: smtp.163.com
|
||||
# port: 25
|
||||
#
|
||||
# ==== SMTP server at example.com using LOGIN authentication and checking HELO for foo.com
|
||||
#
|
||||
# production:
|
||||
# email_delivery:
|
||||
# delivery_method: :smtp
|
||||
# smtp_settings:
|
||||
# address: smtp.gmail.com
|
||||
# port: 587
|
||||
# authentication: :login
|
||||
# domain: 'foo.com'
|
||||
# user_name: senluowanxiangt@gmail.com
|
||||
# password: 1913TXBja
|
||||
#
|
||||
# ==== SMTP server at example.com using PLAIN authentication
|
||||
#
|
||||
# production:
|
||||
# email_delivery:
|
||||
# delivery_method: :smtp
|
||||
# smtp_settings:
|
||||
# address: smtp.gmail.com
|
||||
# port: 587
|
||||
# authentication: :plain
|
||||
# domain: 'example.com'
|
||||
# user_name: senluowanxiangt@gmail.com
|
||||
# password: 1913TXBja
|
||||
#
|
||||
# ==== SMTP server at using TLS (GMail)
|
||||
#
|
||||
# This might require some additional configuration. See the guides at:
|
||||
# http://www.redmine.org/projects/redmine/wiki/EmailConfiguration
|
||||
#
|
||||
# production:
|
||||
# email_delivery:
|
||||
# delivery_method: :smtp
|
||||
# smtp_settings:
|
||||
# enable_starttls_auto: true
|
||||
# address: smtp.gmail.com
|
||||
# port: 587
|
||||
# domain: "smtp.gmail.com" # 'your.domain.com' for GoogleApps
|
||||
# authentication: :plain
|
||||
# user_name: senluowanxiangt@gmail.com
|
||||
# password: 1913TXBja
|
||||
#
|
||||
#
|
||||
# === More configuration options
|
||||
#
|
||||
# See the "Configuration options" at the following website for a list of the
|
||||
# full options allowed:
|
||||
#
|
||||
# http://wiki.rubyonrails.org/rails/pages/HowToSendEmailsWithActionMailer
|
||||
|
||||
|
||||
# default configuration options for all environments
|
||||
default:
|
||||
# Outgoing emails configuration (see examples above)
|
||||
email_delivery:
|
||||
delivery_method: :smtp
|
||||
smtp_settings:
|
||||
|
||||
|
||||
|
||||
address: smtp.126.com
|
||||
port: 25
|
||||
domain: smtp.126.com
|
||||
authentication: :plain
|
||||
user_name: "alanlong9278@126.com"
|
||||
password: 'alanlong8788786'
|
||||
|
||||
# Absolute path to the directory where attachments are stored.
|
||||
# The default is the 'files' directory in your Redmine instance.
|
||||
# Your Redmine instance needs to have write permission on this
|
||||
# directory.
|
||||
# Examples:
|
||||
# attachments_storage_path: /var/redmine/files
|
||||
# attachments_storage_path: D:/redmine/files
|
||||
attachments_storage_path:
|
||||
|
||||
# Configuration of the autologin cookie.
|
||||
# autologin_cookie_name: the name of the cookie (default: autologin)
|
||||
# autologin_cookie_path: the cookie path (default: /)
|
||||
# autologin_cookie_secure: true sets the cookie secure flag (default: false)
|
||||
autologin_cookie_name:
|
||||
autologin_cookie_path:
|
||||
autologin_cookie_secure:
|
||||
|
||||
# Configuration of SCM executable command.
|
||||
#
|
||||
# Absolute path (e.g. /usr/local/bin/hg) or command name (e.g. hg.exe, bzr.exe)
|
||||
# On Windows + CRuby, *.cmd, *.bat (e.g. hg.cmd, bzr.bat) does not work.
|
||||
#
|
||||
# On Windows + JRuby 1.6.2, path which contains spaces 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.
|
||||
# For example, "C:\TortoiseHg\hg.exe".
|
||||
#
|
||||
# Examples:
|
||||
# scm_subversion_command: svn # (default: svn)
|
||||
# scm_mercurial_command: C:\Program Files\TortoiseHg\hg.exe # (default: hg)
|
||||
# scm_git_command: /usr/local/bin/git # (default: git)
|
||||
# scm_cvs_command: cvs # (default: cvs)
|
||||
# scm_bazaar_command: bzr.exe # (default: bzr)
|
||||
# scm_darcs_command: darcs-1.0.9-i386-linux # (default: darcs)
|
||||
#
|
||||
scm_subversion_command:
|
||||
scm_mercurial_command:
|
||||
scm_git_command:
|
||||
scm_cvs_command:
|
||||
scm_bazaar_command:
|
||||
scm_darcs_command:
|
||||
|
||||
# Absolute path to the SCM commands errors (stderr) log file.
|
||||
# The default is to log in the 'log' directory of your Redmine instance.
|
||||
# Example:
|
||||
# scm_stderr_log_file: /var/log/redmine_scm_stderr.log
|
||||
scm_stderr_log_file:
|
||||
|
||||
# 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.
|
||||
# WARNING: losing/changing this key will make encrypted data unreadable.
|
||||
#
|
||||
# If you want to encrypt existing passwords in your database:
|
||||
# * set the cipher key here in your configuration file
|
||||
# * encrypt data using 'rake db:encrypt RAILS_ENV=production'
|
||||
#
|
||||
# If you have encrypted data and want to change this key, you have to:
|
||||
# * decrypt data using 'rake db:decrypt RAILS_ENV=production' first
|
||||
# * change the cipher key here in your configuration file
|
||||
# * encrypt data using 'rake db:encrypt RAILS_ENV=production'
|
||||
database_cipher_key:
|
||||
|
||||
# Set this to false to disable plugins' assets mirroring on startup.
|
||||
# You can use `rake redmine:plugins:assets` to manually mirror assets
|
||||
# to public/plugin_assets when you install/upgrade a Redmine plugin.
|
||||
#
|
||||
#mirror_plugins_assets_on_startup: false
|
||||
|
||||
# Your secret key for verifying cookie session data integrity. If you
|
||||
# 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
|
||||
# you'll be exposed to dictionary attacks.
|
||||
#
|
||||
# If you have a load-balancing Redmine cluster, you have to use the
|
||||
# same secret token on each machine.
|
||||
#secret_token: 'change it to a long random string'
|
||||
|
||||
# Absolute path (e.g. /usr/bin/convert, c:/im/convert.exe) to
|
||||
# the ImageMagick's `convert` binary. Used to generate attachment thumbnails.
|
||||
imagemagick_convert_command: '/home/pdl/redmine-2.3.2-0/common/bin/convert'
|
||||
|
||||
# Configuration of RMagcik font.
|
||||
#
|
||||
# Redmine uses RMagcik in order to export gantt png.
|
||||
# You don't need this setting if you don't install RMagcik.
|
||||
#
|
||||
# In CJK (Chinese, Japanese and Korean),
|
||||
# in order to show CJK characters correctly,
|
||||
# you need to set this configuration.
|
||||
#
|
||||
# Because there is no standard font across platforms in CJK,
|
||||
# you need to set a font installed in your server.
|
||||
#
|
||||
# This setting is not necessary in non CJK.
|
||||
#
|
||||
# Examples for Japanese:
|
||||
# Windows:
|
||||
# rmagick_font_path: C:\windows\fonts\msgothic.ttc
|
||||
# Linux:
|
||||
# rmagick_font_path: /usr/share/fonts/ipa-mincho/ipam.ttf
|
||||
#
|
||||
rmagick_font_path:
|
||||
|
||||
# Maximum number of simultaneous AJAX uploads
|
||||
#max_concurrent_ajax_uploads: 2
|
||||
#pic_types: "bmp,jpeg,jpg,png,gif"
|
||||
|
||||
# specific configuration options for production environment
|
||||
# that overrides the default ones
|
||||
production:
|
||||
# CJK support
|
||||
rmagick_font_path: /usr/share/fonts/ipa-mincho/ipam.ttf
|
||||
|
||||
# specific configuration options for development environment
|
||||
# that overrides the default ones
|
||||
development:
|
||||
# = Redmine configuration file
|
||||
#
|
||||
# Each environment has it's own configuration options. If you are only
|
||||
# running in production, only the production block needs to be configured.
|
||||
# Environment specific configuration options override the default ones.
|
||||
#
|
||||
# Note that this file needs to be a valid YAML file.
|
||||
# DO NOT USE TABS! Use 2 spaces instead of tabs for identation.
|
||||
#
|
||||
# == Outgoing email settings (email_delivery setting)
|
||||
#
|
||||
# === Common configurations
|
||||
#
|
||||
# ==== Sendmail command
|
||||
#
|
||||
# production:
|
||||
# email_delivery:
|
||||
# delivery_method: :sendmail
|
||||
#
|
||||
# ==== Simple SMTP server at localhost
|
||||
#
|
||||
# production:
|
||||
# email_delivery:
|
||||
# delivery_method: :smtp
|
||||
# smtp_settings:
|
||||
# address: smtp.163.com
|
||||
# port: 25
|
||||
#
|
||||
# ==== SMTP server at example.com using LOGIN authentication and checking HELO for foo.com
|
||||
#
|
||||
# production:
|
||||
# email_delivery:
|
||||
# delivery_method: :smtp
|
||||
# smtp_settings:
|
||||
# address: smtp.gmail.com
|
||||
# port: 587
|
||||
# authentication: :login
|
||||
# domain: 'foo.com'
|
||||
# user_name: senluowanxiangt@gmail.com
|
||||
# password: 1913TXBja
|
||||
#
|
||||
# ==== SMTP server at example.com using PLAIN authentication
|
||||
#
|
||||
# production:
|
||||
# email_delivery:
|
||||
# delivery_method: :smtp
|
||||
# smtp_settings:
|
||||
# address: smtp.gmail.com
|
||||
# port: 587
|
||||
# authentication: :plain
|
||||
# domain: 'example.com'
|
||||
# user_name: senluowanxiangt@gmail.com
|
||||
# password: 1913TXBja
|
||||
#
|
||||
# ==== SMTP server at using TLS (GMail)
|
||||
#
|
||||
# This might require some additional configuration. See the guides at:
|
||||
# http://www.redmine.org/projects/redmine/wiki/EmailConfiguration
|
||||
#
|
||||
# production:
|
||||
# email_delivery:
|
||||
# delivery_method: :smtp
|
||||
# smtp_settings:
|
||||
# enable_starttls_auto: true
|
||||
# address: smtp.gmail.com
|
||||
# port: 587
|
||||
# domain: "smtp.gmail.com" # 'your.domain.com' for GoogleApps
|
||||
# authentication: :plain
|
||||
# user_name: senluowanxiangt@gmail.com
|
||||
# password: 1913TXBja
|
||||
#
|
||||
#
|
||||
# === More configuration options
|
||||
#
|
||||
# See the "Configuration options" at the following website for a list of the
|
||||
# full options allowed:
|
||||
#
|
||||
# http://wiki.rubyonrails.org/rails/pages/HowToSendEmailsWithActionMailer
|
||||
|
||||
|
||||
# default configuration options for all environments
|
||||
default:
|
||||
# Outgoing emails configuration (see examples above)
|
||||
email_delivery:
|
||||
delivery_method: :smtp
|
||||
smtp_settings:
|
||||
address: smtp.126.com
|
||||
port: 25
|
||||
domain: smtp.126.com
|
||||
authentication: :plain
|
||||
user_name: "alanlong9278@126.com"
|
||||
password: 'alanlong8788786'
|
||||
|
||||
# Absolute path to the directory where attachments are stored.
|
||||
# The default is the 'files' directory in your Redmine instance.
|
||||
# Your Redmine instance needs to have write permission on this
|
||||
# directory.
|
||||
# Examples:
|
||||
# attachments_storage_path: /var/redmine/files
|
||||
# attachments_storage_path: D:/redmine/files
|
||||
attachments_storage_path:
|
||||
|
||||
# Configuration of the autologin cookie.
|
||||
# autologin_cookie_name: the name of the cookie (default: autologin)
|
||||
# autologin_cookie_path: the cookie path (default: /)
|
||||
# autologin_cookie_secure: true sets the cookie secure flag (default: false)
|
||||
autologin_cookie_name:
|
||||
autologin_cookie_path:
|
||||
autologin_cookie_secure:
|
||||
|
||||
# Configuration of SCM executable command.
|
||||
#
|
||||
# Absolute path (e.g. /usr/local/bin/hg) or command name (e.g. hg.exe, bzr.exe)
|
||||
# On Windows + CRuby, *.cmd, *.bat (e.g. hg.cmd, bzr.bat) does not work.
|
||||
#
|
||||
# On Windows + JRuby 1.6.2, path which contains spaces 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.
|
||||
# For example, "C:\TortoiseHg\hg.exe".
|
||||
#
|
||||
# Examples:
|
||||
# scm_subversion_command: svn # (default: svn)
|
||||
# scm_mercurial_command: C:\Program Files\TortoiseHg\hg.exe # (default: hg)
|
||||
# scm_git_command: /usr/local/bin/git # (default: git)
|
||||
# scm_cvs_command: cvs # (default: cvs)
|
||||
# scm_bazaar_command: bzr.exe # (default: bzr)
|
||||
# scm_darcs_command: darcs-1.0.9-i386-linux # (default: darcs)
|
||||
#
|
||||
scm_subversion_command:
|
||||
scm_mercurial_command:
|
||||
scm_git_command:
|
||||
scm_cvs_command:
|
||||
scm_bazaar_command:
|
||||
scm_darcs_command:
|
||||
|
||||
# Absolute path to the SCM commands errors (stderr) log file.
|
||||
# The default is to log in the 'log' directory of your Redmine instance.
|
||||
# Example:
|
||||
# scm_stderr_log_file: /var/log/redmine_scm_stderr.log
|
||||
scm_stderr_log_file:
|
||||
|
||||
# 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.
|
||||
# WARNING: losing/changing this key will make encrypted data unreadable.
|
||||
#
|
||||
# If you want to encrypt existing passwords in your database:
|
||||
# * set the cipher key here in your configuration file
|
||||
# * encrypt data using 'rake db:encrypt RAILS_ENV=production'
|
||||
#
|
||||
# If you have encrypted data and want to change this key, you have to:
|
||||
# * decrypt data using 'rake db:decrypt RAILS_ENV=production' first
|
||||
# * change the cipher key here in your configuration file
|
||||
# * encrypt data using 'rake db:encrypt RAILS_ENV=production'
|
||||
database_cipher_key:
|
||||
|
||||
# Set this to false to disable plugins' assets mirroring on startup.
|
||||
# You can use `rake redmine:plugins:assets` to manually mirror assets
|
||||
# to public/plugin_assets when you install/upgrade a Redmine plugin.
|
||||
#
|
||||
#mirror_plugins_assets_on_startup: false
|
||||
|
||||
# Your secret key for verifying cookie session data integrity. If you
|
||||
# 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
|
||||
# you'll be exposed to dictionary attacks.
|
||||
#
|
||||
# If you have a load-balancing Redmine cluster, you have to use the
|
||||
# same secret token on each machine.
|
||||
#secret_token: 'change it to a long random string'
|
||||
|
||||
# Absolute path (e.g. /usr/bin/convert, c:/im/convert.exe) to
|
||||
# the ImageMagick's `convert` binary. Used to generate attachment thumbnails.
|
||||
imagemagick_convert_command: '/home/pdl/redmine-2.3.2-0/common/bin/convert'
|
||||
|
||||
# Configuration of RMagcik font.
|
||||
#
|
||||
# Redmine uses RMagcik in order to export gantt png.
|
||||
# You don't need this setting if you don't install RMagcik.
|
||||
#
|
||||
# In CJK (Chinese, Japanese and Korean),
|
||||
# in order to show CJK characters correctly,
|
||||
# you need to set this configuration.
|
||||
#
|
||||
# Because there is no standard font across platforms in CJK,
|
||||
# you need to set a font installed in your server.
|
||||
#
|
||||
# This setting is not necessary in non CJK.
|
||||
#
|
||||
# Examples for Japanese:
|
||||
# Windows:
|
||||
# rmagick_font_path: C:\windows\fonts\msgothic.ttc
|
||||
# Linux:
|
||||
# rmagick_font_path: /usr/share/fonts/ipa-mincho/ipam.ttf
|
||||
#
|
||||
rmagick_font_path:
|
||||
|
||||
# Maximum number of simultaneous AJAX uploads
|
||||
#max_concurrent_ajax_uploads: 2
|
||||
#pic_types: "bmp,jpeg,jpg,png,gif"
|
||||
|
||||
# specific configuration options for production environment
|
||||
# that overrides the default ones
|
||||
production:
|
||||
# CJK support
|
||||
rmagick_font_path: /usr/share/fonts/ipa-mincho/ipam.ttf
|
||||
|
||||
# specific configuration options for development environment
|
||||
# that overrides the default ones
|
||||
development:
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
I18n.default_locale = 'en'
|
||||
I18n.backend = Redmine::I18n::Backend.new
|
||||
|
||||
require 'redmine'
|
||||
|
||||
# Load the secret token from the Redmine configuration file
|
||||
secret = Redmine::Configuration['secret_token']
|
||||
if secret.present?
|
||||
RedmineApp::Application.config.secret_token = secret
|
||||
end
|
||||
|
||||
Redmine::Plugin.load
|
||||
unless Redmine::Configuration['mirror_plugins_assets_on_startup'] == false
|
||||
Redmine::Plugin.mirror_assets
|
||||
end
|
||||
I18n.default_locale = 'en'
|
||||
I18n.backend = Redmine::I18n::Backend.new
|
||||
|
||||
require 'redmine'
|
||||
require 'trustie'
|
||||
|
||||
# Load the secret token from the Redmine configuration file
|
||||
secret = Redmine::Configuration['secret_token']
|
||||
if secret.present?
|
||||
RedmineApp::Application.config.secret_token = secret
|
||||
end
|
||||
|
||||
Redmine::Plugin.load
|
||||
unless Redmine::Configuration['mirror_plugins_assets_on_startup'] == false
|
||||
Redmine::Plugin.mirror_assets
|
||||
end
|
||||
|
|
|
@ -1,27 +1,15 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
require 'rubygems'
|
||||
require 'rufus-scheduler'
|
||||
|
||||
#users = User.where("mail_notification = 'week' or mail_notification = 'day'")
|
||||
|
||||
scheduler = Rufus::Scheduler.new
|
||||
scheduler.cron('0 0 * * 1') do
|
||||
users = User.where("mail_notification = 'week'")
|
||||
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, 7).deliver
|
||||
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
|
||||
|
||||
#coding=utf-8
|
||||
|
||||
|
||||
## 移入crontab
|
||||
|
||||
# scheduler = Rufus::Scheduler.new
|
||||
#
|
||||
# #每天18:00发送当天的邮件汇总
|
||||
# scheduler.cron('0 18 * * *') do
|
||||
# users = User.where(mail_notification: 'day')
|
||||
# users.each do |user|
|
||||
# mailer = Mailer.send_for_user_activities(user, Date.today, 1)
|
||||
# mailer.deliver if mailer
|
||||
# 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 #作业和留言 模块
|
||||
|
||||
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
|
||||
# 项目、课程、用户公用
|
||||
|
|
|
@ -187,7 +187,8 @@ zh:
|
|||
|
||||
|
||||
text_are_you_sure: 您确定要删除吗? #js 提示
|
||||
|
||||
text_are_you_sure_out: 你确定要退出该课程吗?
|
||||
text_are_you_sure_out_group: 你确定要退出该分班吗?
|
||||
|
||||
|
||||
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_sponsor: Department of Computer Science and Technology, NUDT
|
||||
label_co_organizer_NUDT: College of Computer, NUDT
|
||||
|
|
|
@ -6,10 +6,13 @@ en:
|
|||
#
|
||||
# 课程公共标签
|
||||
#
|
||||
label_course_join_student: 加入课程
|
||||
label_course_new: 新建课程
|
||||
|
||||
label_homework: 课程作业
|
||||
label_course_join_student: Join a course
|
||||
label_course_exit_student: Exit a course
|
||||
label_course_new: New course
|
||||
label_course_name: Course name
|
||||
|
||||
|
||||
label_homework: Task
|
||||
label_course_news: 课程通知
|
||||
label_main_teacher: 主讲教师
|
||||
label_course_term: 开课学期
|
||||
|
|
|
@ -13,6 +13,7 @@ zh:
|
|||
label_course_join_student: 加入课程
|
||||
label_course_exit_student: 退出课程
|
||||
label_course_new: 新建课程
|
||||
label_course_name: 课程名称
|
||||
|
||||
label_homework: 课程作业
|
||||
label_course_news: 课程通知
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue