Merge branch 'guange_dev' into memcached_alan
Conflicts: .gitignore Gemfile app/views/issues/index.html.erb app/views/layouts/_base_feedback.html.erb app/views/tags/_tag_name.html.erb config/environments/production.rb db/schema.rb Signed-off-by: alan <547533434@qq.com>
This commit is contained in:
commit
c80263a66e
|
@ -5,6 +5,7 @@
|
|||
*.swp
|
||||
/config/database.yml
|
||||
/config/configuration.yml
|
||||
/config/additional_environment.rb
|
||||
/files/*
|
||||
/log/*
|
||||
/public/tmp/*
|
||||
|
@ -26,3 +27,4 @@ vendor/cache
|
|||
/files
|
||||
/public/images/avatars
|
||||
/public/files
|
||||
/tags
|
||||
|
|
48
Gemfile
48
Gemfile
|
@ -6,6 +6,8 @@ unless RUBY_PLATFORM =~ /w32/
|
|||
gem 'iconv'
|
||||
end
|
||||
|
||||
gem "mysql2", "= 0.3.18"
|
||||
gem 'redis-rails'
|
||||
gem 'rubyzip'
|
||||
gem 'delayed_job_active_record'#, :group => :production
|
||||
gem 'daemons'
|
||||
|
@ -21,9 +23,6 @@ gem "builder", "3.0.0"
|
|||
gem 'acts-as-taggable-on', '2.4.1'
|
||||
gem 'spreadsheet'
|
||||
gem 'ruby-ole'
|
||||
#gem 'email_verifier', path: 'lib/email_verifier'
|
||||
gem 'rufus-scheduler'
|
||||
gem 'dalli'
|
||||
gem 'rails_kindeditor',path:'lib/rails_kindeditor'
|
||||
group :development do
|
||||
gem 'grape-swagger'
|
||||
|
@ -83,56 +82,13 @@ group :openid do
|
|||
gem "rack-openid"
|
||||
end
|
||||
|
||||
# Optional gem for exporting the gantt to a PNG file, not supported with jruby
|
||||
platforms :jruby do
|
||||
# jruby-openssl is bundled with JRuby 1.7.0
|
||||
gem "jruby-openssl" if Object.const_defined?(:JRUBY_VERSION) && JRUBY_VERSION < '1.7.0'
|
||||
gem "activerecord-jdbc-adapter", "1.2.5"
|
||||
end
|
||||
|
||||
# Include database gems for the adapters found in the database
|
||||
# configuration file
|
||||
require 'erb'
|
||||
require 'yaml'
|
||||
database_file = File.join(File.dirname(__FILE__), "config/database.yml")
|
||||
if File.exist?(database_file)
|
||||
database_config = YAML::load(ERB.new(IO.read(database_file)).result)
|
||||
adapters = database_config.values.map {|c| c['adapter']}.compact.uniq
|
||||
if adapters.any?
|
||||
adapters.each do |adapter|
|
||||
case adapter
|
||||
when 'mysql2'
|
||||
gem "mysql2", "= 0.3.18", :platforms => [:mri, :mingw]
|
||||
gem "activerecord-jdbcmysql-adapter", :platforms => :jruby
|
||||
when 'mysql'
|
||||
gem "mysql", "~> 2.8.1", :platforms => [:mri, :mingw]
|
||||
gem "activerecord-jdbcmysql-adapter", :platforms => :jruby
|
||||
when /postgresql/
|
||||
gem "pg", ">= 0.11.0", :platforms => [:mri, :mingw]
|
||||
gem "activerecord-jdbcpostgresql-adapter", :platforms => :jruby
|
||||
when /sqlite3/
|
||||
gem "sqlite3", :platforms => [:mri, :mingw]
|
||||
gem "activerecord-jdbcsqlite3-adapter", :platforms => :jruby
|
||||
when /sqlserver/
|
||||
gem "tiny_tds", "~> 0.5.1", :platforms => [:mri, :mingw]
|
||||
gem "activerecord-sqlserver-adapter", :platforms => [:mri, :mingw]
|
||||
else
|
||||
warn("Unknown database adapter `#{adapter}` found in config/database.yml, use Gemfile.local to load your own database gems")
|
||||
end
|
||||
end
|
||||
else
|
||||
warn("No adapter found in config/database.yml, please configure it first")
|
||||
end
|
||||
else
|
||||
warn("Please configure your config/database.yml first")
|
||||
end
|
||||
|
||||
local_gemfile = File.join(File.dirname(__FILE__), "Gemfile.local")
|
||||
if File.exists?(local_gemfile)
|
||||
puts "Loading Gemfile.local ..." if $DEBUG # `ruby -d` or `bundle -v`
|
||||
instance_eval File.read(local_gemfile)
|
||||
end
|
||||
|
||||
# Load plugins' Gemfiles
|
||||
Dir.glob File.expand_path("../plugins/*/Gemfile", __FILE__) do |file|
|
||||
puts "Loading #{file} ..." if $DEBUG # `ruby -d` or `bundle -v`
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -228,6 +228,18 @@ module Mobile
|
|||
present :status, 0
|
||||
end
|
||||
|
||||
desc '课程课件'
|
||||
params do
|
||||
requires :token, type: String
|
||||
requires :course_id,type: Integer,desc: '课程id'
|
||||
end
|
||||
get ":course_id/attachments" do
|
||||
cs = CoursesService.new
|
||||
count = cs.course_attachments params
|
||||
present :data, count, with: Mobile::Entities::Attachment
|
||||
present :status, 0
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -16,8 +16,11 @@ module Mobile
|
|||
end
|
||||
end
|
||||
end
|
||||
attachment_expose :id
|
||||
attachment_expose :filename
|
||||
attachment_expose :description
|
||||
attachment_expose :downloads
|
||||
attachment_expose :quotes
|
||||
end
|
||||
end
|
||||
end
|
|
@ -332,7 +332,7 @@ class AccountController < ApplicationController
|
|||
token = Token.create(:user => user, :action => 'autologin')
|
||||
cookie_options = {
|
||||
:value => token.value,
|
||||
:expires => 1.year.from_now,
|
||||
:expires => 7.days.from_now,
|
||||
:path => (Redmine::Configuration['autologin_cookie_path'] || '/'),
|
||||
:secure => (Redmine::Configuration['autologin_cookie_secure'] ? true : false),
|
||||
:httponly => true
|
||||
|
|
|
@ -894,7 +894,6 @@ class ApplicationController < ActionController::Base
|
|||
set_autologin_cookie(user)
|
||||
end
|
||||
call_hook(:controller_account_success_authentication_after, {:user => user })
|
||||
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -1,59 +1,59 @@
|
|||
class AppliedProjectController < ApplicationController
|
||||
|
||||
#申请加入项目
|
||||
def applied_join_project
|
||||
@user_id = params[:user_id]
|
||||
@project = Project.find_by_id(params[:project_id])
|
||||
if params[:project_join]
|
||||
if @project
|
||||
user = User.find @user_id
|
||||
if user.member_of?(@project)
|
||||
@status = 3
|
||||
else
|
||||
@applieds = AppliedProject.where("user_id = ? and project_id = ?", params[:user_id],params[:project_id])
|
||||
if @applieds.count == 0
|
||||
appliedproject = AppliedProject.create(:user_id => params[:user_id], :project_id => params[:project_id])
|
||||
Mailer.run.applied_project(appliedproject)
|
||||
@status = 2
|
||||
else
|
||||
@status = 1
|
||||
end
|
||||
end
|
||||
else
|
||||
@status = 0
|
||||
end
|
||||
respond_to do |format|
|
||||
format.js
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
@applieds = AppliedProject.where("user_id = ? and project_id = ?", params[:user_id],params[:project_id])
|
||||
if @applieds.count == 0
|
||||
appliedproject = AppliedProject.create(:user_id => params[:user_id], :project_id => params[:project_id])
|
||||
Mailer.run.applied_project(appliedproject)
|
||||
end
|
||||
|
||||
#redirect_to project_path(params[:project_id])
|
||||
#redirect_to_referer_or {render :text => ( 'applied success.'), :layout => true}
|
||||
respond_to do |format|
|
||||
format.html { redirect_to_referer_or {render :text => (watching ? 'Watcher added.' : 'Watcher removed.'), :layout => true}}
|
||||
format.js { render :partial => 'set_applied'}
|
||||
end
|
||||
end
|
||||
|
||||
#取消申请
|
||||
def unapplied_join_project
|
||||
@project = Project.find(params[:project_id])
|
||||
#@applied = AppliedProject.find(params[:id])
|
||||
#@applied.destroy
|
||||
|
||||
AppliedProject.deleteappiled(params[:user_id], params[:project_id])
|
||||
|
||||
respond_to do |format|
|
||||
format.html { redirect_to_referer_or {render :text => (watching ? 'Watcher added.' : 'Watcher removed.'), :layout => true}}
|
||||
format.js { render :partial => 'set_applied' }
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
class AppliedProjectController < ApplicationController
|
||||
|
||||
#申请加入项目
|
||||
def applied_join_project
|
||||
@user_id = params[:user_id]
|
||||
@project = Project.find_by_id(params[:project_id])
|
||||
if params[:project_join]
|
||||
if @project
|
||||
user = User.find @user_id
|
||||
if user.member_of?(@project)
|
||||
@status = 3
|
||||
else
|
||||
@applieds = AppliedProject.where("user_id = ? and project_id = ?", params[:user_id],params[:project_id])
|
||||
if @applieds.count == 0
|
||||
appliedproject = AppliedProject.create(:user_id => params[:user_id], :project_id => params[:project_id])
|
||||
Mailer.run.applied_project(appliedproject)
|
||||
@status = 2
|
||||
else
|
||||
@status = 1
|
||||
end
|
||||
end
|
||||
else
|
||||
@status = 0
|
||||
end
|
||||
respond_to do |format|
|
||||
format.js
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
@applieds = AppliedProject.where("user_id = ? and project_id = ?", params[:user_id],params[:project_id])
|
||||
if @applieds.count == 0
|
||||
appliedproject = AppliedProject.create(:user_id => params[:user_id], :project_id => params[:project_id])
|
||||
Mailer.run.applied_project(appliedproject)
|
||||
end
|
||||
|
||||
#redirect_to project_path(params[:project_id])
|
||||
#redirect_to_referer_or {render :text => ( 'applied success.'), :layout => true}
|
||||
respond_to do |format|
|
||||
format.html { redirect_to_referer_or {render :text => (watching ? 'Watcher added.' : 'Watcher removed.'), :layout => true}}
|
||||
format.js { render :partial => 'set_applied'}
|
||||
end
|
||||
end
|
||||
|
||||
#取消申请
|
||||
def unapplied_join_project
|
||||
@project = Project.find(params[:project_id])
|
||||
#@applied = AppliedProject.find(params[:id])
|
||||
#@applied.destroy
|
||||
|
||||
AppliedProject.deleteappiled(params[:user_id], params[:project_id])
|
||||
|
||||
respond_to do |format|
|
||||
format.html { redirect_to_referer_or {render :text => (watching ? 'Watcher added.' : 'Watcher removed.'), :layout => true}}
|
||||
format.js { render :partial => 'set_applied' }
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -506,7 +506,8 @@ class BidsController < ApplicationController
|
|||
end
|
||||
|
||||
@cur_page = params[:page] || 1
|
||||
@homework_list = paginateHelper all_homework_list,10
|
||||
# @homework_list = paginateHelper all_homework_list,10
|
||||
@homework_list = all_homework_list
|
||||
@jours_count = @bid.journals_for_messages.where('m_parent_id IS NULL').count
|
||||
if params[:student_id].present?
|
||||
@temp = []
|
||||
|
@ -792,7 +793,7 @@ class BidsController < ApplicationController
|
|||
@bid.is_evaluation = params[:bid][:is_evaluation]
|
||||
@bid.proportion = params[:bid][:proportion]
|
||||
@bid.evaluation_num = params[:bid][:evaluation_num]
|
||||
@bid.open_anonymous_evaluation = params[:bid][:open_anonymous_evaluation]
|
||||
params[:bid][:open_anonymous_evaluation] ? @bid.open_anonymous_evaluation = 1 : @bid.open_anonymous_evaluation = 0
|
||||
@bid.reward_type = 3
|
||||
# @bid.budget = params[:bid][:budget]
|
||||
@bid.deadline = params[:bid][:deadline]
|
||||
|
|
|
@ -42,12 +42,19 @@ class BoardsController < ApplicationController
|
|||
elsif @course
|
||||
if (User.current.admin? || @course.is_public == 1 || (@course.is_public == 0 && User.current.member_of_course?(@course)))
|
||||
@boards = @course.boards.includes(:last_message => :author).all
|
||||
@boards = [] << @boards[0] if @boards.any?
|
||||
if @boards.size == 1
|
||||
@board = @boards.first
|
||||
show and return
|
||||
if @course.boards.empty?
|
||||
@board = @course.boards.build
|
||||
@board.name = " #{l(:label_borad_course) }"
|
||||
@board.description = @course.name.to_s
|
||||
@board.project_id = -1
|
||||
if @board.save
|
||||
@boards = @course.boards.includes(:last_message => :author).all
|
||||
end
|
||||
end
|
||||
render :layout => 'base_courses'
|
||||
unless @course.boards.empty?
|
||||
@board = @course.boards.first
|
||||
end
|
||||
show and return
|
||||
else
|
||||
render_403
|
||||
end
|
||||
|
@ -65,7 +72,7 @@ class BoardsController < ApplicationController
|
|||
'replies' => "#{Message.table_name}.replies_count",
|
||||
'updated_on' => "COALESCE(last_replies_messages.created_on, #{Message.table_name}.created_on)"
|
||||
|
||||
@topic_count = @board.topics.count
|
||||
@topic_count = @board ? @board.topics.count : 0
|
||||
if @project
|
||||
@topic_pages = Paginator.new @topic_count, per_page_option, params['page']
|
||||
@topics = @board.topics.
|
||||
|
@ -77,14 +84,13 @@ class BoardsController < ApplicationController
|
|||
preload(:author, {:last_reply => :author}).
|
||||
all
|
||||
elsif @course
|
||||
board_topics = @board.topics.
|
||||
reorder("#{Message.table_name}.sticky DESC").
|
||||
board_topics = @board ? @board.topics.reorder("#{Message.table_name}.sticky DESC").
|
||||
includes(:last_reply).
|
||||
# limit(@topic_pages.per_page).
|
||||
# offset(@topic_pages.offset).
|
||||
order(sort_clause).
|
||||
preload(:author, {:last_reply => :author}).
|
||||
all
|
||||
all : []
|
||||
@topics = paginateHelper board_topics,10
|
||||
end
|
||||
|
||||
|
|
|
@ -191,8 +191,9 @@ class CoursesController < ApplicationController
|
|||
results = searchmember_by_name(student_homework_score(@group.id,0,0,"desc"), q)
|
||||
end
|
||||
@is_remote = true
|
||||
@result_count = results.count
|
||||
@results = paginateHelper results, 10
|
||||
#@result_count = results.count
|
||||
#@results = paginateHelper results, 10
|
||||
@results = results
|
||||
@search_name = q
|
||||
end
|
||||
|
||||
|
@ -315,13 +316,15 @@ class CoursesController < ApplicationController
|
|||
when '1'
|
||||
@subPage_title = l :label_teacher_list
|
||||
@all_members = searchTeacherAndAssistant(@course)
|
||||
@members = paginateHelper @all_members, 10
|
||||
#@members = paginateHelper @all_members, 10
|
||||
@members = @all_members
|
||||
when '2'
|
||||
@subPage_title = l :label_student_list
|
||||
page = params[:page].nil? ? 0 : (params['page'].to_i - 1)
|
||||
@all_members = student_homework_score(0,page, 10,"desc")
|
||||
# @all_members = @course.members
|
||||
@members = paginateHelper_for_members @all_members, 10
|
||||
# @members = paginateHelper_for_members @all_members, 10
|
||||
@members = @all_members
|
||||
end
|
||||
respond_to do |format|
|
||||
if params[:page]
|
||||
|
@ -705,7 +708,7 @@ class CoursesController < ApplicationController
|
|||
#"show_course_journals_for_messages" => true,
|
||||
"show_bids" => true,
|
||||
"show_homeworks" => true,
|
||||
#"show_polls" => true
|
||||
"show_polls" => true
|
||||
}
|
||||
@date_to ||= Date.today + 1
|
||||
@date_from = (@date_to - @days) > @course.created_at.to_date ? (@date_to - @days) : @course.created_at.to_date
|
||||
|
@ -877,7 +880,7 @@ class CoursesController < ApplicationController
|
|||
students_for_courses.course_id = #{@course.id} and members.user_id = students_for_courses.student_id AND
|
||||
members.user_id NOT IN (SELECT homework_attaches.user_id FROM homework_attaches WHERE homework_attaches.bid_id in (SELECT bid_id FROM homework_for_courses WHERE course_id = #{@course.id} )
|
||||
)
|
||||
GROUP BY members.user_id ORDER BY score #{score_sort_by} limit #{start_from}, #{nums}"
|
||||
GROUP BY members.user_id ORDER BY score #{score_sort_by} " #limit #{start_from}, #{nums}"
|
||||
|
||||
end
|
||||
else
|
||||
|
|
|
@ -145,10 +145,14 @@ class FilesController < ApplicationController
|
|||
ids += version.id.to_s
|
||||
end
|
||||
end
|
||||
resultSet = Attachment.where("((attachments.container_type = 'Project' And attachments.container_id = '#{project.id}') OR (container_type = 'Version' AND container_id IN (#{ids}))) AND filename LIKE :like ", like: "%#{keywords}%").
|
||||
reorder(sort)
|
||||
#resultSet = Attachment.find_by_sql("SELECT `attachments`.* FROM `attachments` LEFT OUTER JOIN `homework_attaches` ON `attachments`.container_type = 'HomeworkAttach' AND `attachments`.container_id = `homework_attaches`.id LEFT OUTER JOIN `homework_for_courses` ON `homework_attaches`.bid_id = `homework_for_courses`.bid_id LEFT OUTER JOIN `homework_for_courses` AS H_C ON `attachments`.container_type = 'Bid' AND `attachments`.container_id = H_C.bid_id WHERE (`homework_for_courses`.course_id = 117 OR H_C.course_id = 117 OR (`attachments`.container_type = 'Course' AND `attachments`.container_id = 117)) AND `attachments`.filename LIKE '%#{keywords}%'").reorder("created_on DESC")
|
||||
end
|
||||
if ids.blank?
|
||||
resultSet = Attachment.where("attachments.container_type = 'Project' And attachments.container_id = '#{project.id}' AND filename LIKE :like ", like: "%#{keywords}%").
|
||||
reorder(sort)
|
||||
else
|
||||
resultSet = Attachment.where("((attachments.container_type = 'Project' And attachments.container_id = '#{project.id}') OR (container_type = 'Version' AND container_id IN (#{ids}))) AND filename LIKE :like ", like: "%#{keywords}%").
|
||||
reorder(sort)
|
||||
end
|
||||
end
|
||||
|
||||
def find_public_attache keywords,sort = ""
|
||||
# StoresController#search 将每条文件都查出来,再次进行判断过滤。---> resultSet.to_a.map
|
||||
|
|
|
@ -59,7 +59,8 @@ class HomeworkAttachController < ApplicationController
|
|||
all_homework_list = search_homework_member(all_homework_list,@search_name.to_s.downcase) if @search_name
|
||||
@cur_page = params[:page] || 1
|
||||
@cur_type = 2
|
||||
@homework_list = paginateHelper all_homework_list,10
|
||||
# @homework_list = paginateHelper all_homework_list,10
|
||||
@homework_list = all_homework_list
|
||||
@direction = direction == 'asc'? 'desc' : 'asc'
|
||||
respond_to do |format|
|
||||
format.js
|
||||
|
@ -93,7 +94,8 @@ class HomeworkAttachController < ApplicationController
|
|||
all_homework_list = search_homework_member(all_homework_list,@search_name.to_s.downcase) if @search_name
|
||||
@cur_page = params[:page] || 1
|
||||
@cur_type = 3
|
||||
@homework_list = paginateHelper all_homework_list,10
|
||||
# @homework_list = paginateHelper all_homework_list,10
|
||||
@homework_list = all_homework_list
|
||||
@direction = direction == 'asc'? 'desc' : 'asc'
|
||||
respond_to do |format|
|
||||
format.js
|
||||
|
@ -110,7 +112,8 @@ class HomeworkAttachController < ApplicationController
|
|||
all_homework_list = get_student_batch_homework_list @bid,User.current
|
||||
@cur_page = params[:page] || 1
|
||||
@cur_type = 4
|
||||
@homework_list = paginateHelper all_homework_list,10
|
||||
# @homework_list = paginateHelper all_homework_list,10
|
||||
@homework_list = all_homework_list
|
||||
respond_to do |format|
|
||||
format.js
|
||||
end
|
||||
|
@ -134,7 +137,8 @@ class HomeworkAttachController < ApplicationController
|
|||
WHERE homework_attaches.bid_id = #{@bid.id} AND homework_users.user_id = #{User.current.id}")
|
||||
end
|
||||
@cur_page = params[:page] || 1
|
||||
@homework_list = paginateHelper all_homework_list,10
|
||||
# @homework_list = paginateHelper all_homework_list,10
|
||||
@homework_list = all_homework_list
|
||||
respond_to do |format|
|
||||
format.js
|
||||
end
|
||||
|
@ -440,14 +444,15 @@ class HomeworkAttachController < ApplicationController
|
|||
homework = @homework
|
||||
is_teacher = @is_teacher ? 1 : 0
|
||||
#保存评分@homework.rate(@m_score.to_i,User.current.id,:quality, (@is_teacher ? 1 : 0))
|
||||
if @m_score
|
||||
@is_comprehensive_evaluation = @is_teacher ? 1 : (@is_anonymous_comments ? 2 : 3) #判断当前评论是老师评论?匿评?留言
|
||||
if @m_score && (@is_teacher || @is_anonymous_comments)
|
||||
rate = @homework.rates(:quality).where(:rater_id => User.current.id, :is_teacher_score => is_teacher).first
|
||||
if rate
|
||||
rate.stars = @m_score
|
||||
rate.save!
|
||||
else
|
||||
@homework.rates(:quality).new(:stars => @m_score, :rater_id => User.current.id, :is_teacher_score => is_teacher).save!
|
||||
rate = @homework.rates(:quality).new(:stars => @m_score, :rater_id => User.current.id, :is_teacher_score => is_teacher)
|
||||
end
|
||||
rate.save!
|
||||
|
||||
if homework.is_teacher_score == 0
|
||||
if is_teacher == 1
|
||||
|
@ -465,12 +470,26 @@ class HomeworkAttachController < ApplicationController
|
|||
end
|
||||
end
|
||||
homework.save!
|
||||
end
|
||||
end
|
||||
|
||||
#保存评论
|
||||
@is_comprehensive_evaluation = @is_teacher ? 1 : (@is_anonymous_comments ? 2 : 3) #判断当前评论是老师评论?匿评?留言
|
||||
if params[:new_form] && params[:new_form][:user_message] && params[:new_form][:user_message] != "" #有没有留言
|
||||
@homework.addjours User.current.id, params[:new_form][:user_message],0,@is_comprehensive_evaluation
|
||||
if params[:new_form] && params[:new_form][:user_message] #有没有留言
|
||||
jour = @homework.journals_for_messages.where("is_comprehensive_evaluation = 1 and user_id = #{User.current.id}").order("created_on DESC").first
|
||||
if params[:new_form][:user_message] == ""
|
||||
if @is_teacher
|
||||
unless jour
|
||||
jour = @homework.addjours User.current.id, "",0,@is_comprehensive_evaluation
|
||||
end
|
||||
end
|
||||
else
|
||||
jour = @homework.addjours User.current.id, params[:new_form][:user_message],0,@is_comprehensive_evaluation
|
||||
end
|
||||
end
|
||||
|
||||
if jour
|
||||
jour.save_attachments(params[:attachments])
|
||||
render_attachment_warning_if_needed(jour)
|
||||
jour.save
|
||||
end
|
||||
|
||||
@teacher_stars = @stars_reates.where("is_teacher_score = 1") #老师评分列表
|
||||
|
@ -612,7 +631,8 @@ class HomeworkAttachController < ApplicationController
|
|||
ORDER BY #{order_by}) AS table1
|
||||
WHERE table1.t_score IS NULL OR table1.t_score = 0 ")
|
||||
@all_homework_list = search_homework_member(@all_homework_list,@search_name.to_s.downcase) if @search_name
|
||||
@homework_list = paginateHelper @all_homework_list,10
|
||||
# @homework_list = paginateHelper @all_homework_list,10
|
||||
@homework_list = @all_homework_list
|
||||
end
|
||||
|
||||
#获取指定作业的所有成员
|
||||
|
|
|
@ -95,6 +95,7 @@ class IssuesController < ApplicationController
|
|||
format.api {
|
||||
Issue.load_visible_relations(@issues) if include_in_api_response?('relations')
|
||||
}
|
||||
# format.json { render :json => @issues.map { |issue| issue.to_json}} #:json => @issues.map { |issue| issue.to_json}
|
||||
format.atom { render_feed(@issues, :title => "#{@project || Setting.app_title}: #{l(:label_issue_plural)}") }
|
||||
format.csv { send_data(query_to_csv(@issues, @query, params), :type => 'text/csv; header=present', :filename => 'issues.csv') }
|
||||
format.pdf { send_data(issues_to_pdf(@issues, @project, @query), :type => 'application/pdf', :filename => 'issues.pdf') }
|
||||
|
|
|
@ -60,8 +60,12 @@ class MembersController < ApplicationController
|
|||
user_ids.each do |user_id|
|
||||
AppliedProject.deleteappiled(user_id, @project.id)
|
||||
end
|
||||
@succes_message = "拒绝成功"
|
||||
end
|
||||
end
|
||||
respond_to do |format|
|
||||
format.js
|
||||
end
|
||||
else
|
||||
#modify by nwb
|
||||
#更改课程成员逻辑
|
||||
|
@ -117,9 +121,14 @@ class MembersController < ApplicationController
|
|||
format.html { redirect_to invite_members_project_url(@project) }
|
||||
end
|
||||
else
|
||||
unless members.present? && members.all? {|m| m.valid? }
|
||||
@project_error_message = members.empty? ? l(:label_user_role_null) :members.collect {|m| m.errors.full_messages}.flatten.uniq.join(', ')
|
||||
else
|
||||
@succes_message = "添加成功"
|
||||
end
|
||||
respond_to do |format|
|
||||
format.html { redirect_to_settings_in_projects }
|
||||
format.js { @members = members; @applied_members = applied_members; }
|
||||
format.js
|
||||
format.api {
|
||||
@member = members.first
|
||||
if @member.valid?
|
||||
|
@ -184,6 +193,8 @@ class MembersController < ApplicationController
|
|||
|
||||
end # end of params[:refusal_button]
|
||||
|
||||
|
||||
|
||||
end
|
||||
|
||||
def update
|
||||
|
|
|
@ -20,7 +20,7 @@ class MyController < ApplicationController
|
|||
# edit
|
||||
before_filter :auth_login1, :only => [:account]
|
||||
#
|
||||
before_filter :require_login
|
||||
before_filter :require_login, except: [:change_mail_notification]
|
||||
|
||||
helper :issues
|
||||
helper :users
|
||||
|
@ -75,6 +75,19 @@ class MyController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def change_mail_notification
|
||||
token = params[:token]
|
||||
user = try_to_autologin1
|
||||
if user
|
||||
user.mail_notification = params[:mail_notification]
|
||||
user.save
|
||||
flash[:notice] = l(:notice_mail_notification_updated)
|
||||
redirect_to my_account_url
|
||||
else
|
||||
redirect_to signin_url
|
||||
end
|
||||
end
|
||||
|
||||
# Edit user's account
|
||||
def account
|
||||
@user = User.current
|
||||
|
|
|
@ -152,6 +152,9 @@ class NewsController < ApplicationController
|
|||
end
|
||||
|
||||
def edit
|
||||
if @course
|
||||
render :layout => "base_courses"
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
|
|
|
@ -29,7 +29,7 @@ class PollController < ApplicationController
|
|||
end
|
||||
#已提交问卷的用户不能再访问该界面
|
||||
if has_commit_poll?(@poll.id,User.current.id) && (!User.current.admin?)
|
||||
render_403
|
||||
redirect_to poll_index_url(:polls_type => "Course", :polls_group_id => @course.id)
|
||||
else
|
||||
@can_edit_poll = (!has_commit_poll?(@poll.id,User.current.id)) || User.current.admin?
|
||||
@percent = get_percent(@poll,User.current)
|
||||
|
|
|
@ -27,15 +27,7 @@ class ProjectsController < ApplicationController
|
|||
menu_item :feedback, :only => :feedback
|
||||
menu_item :share, :only => :share
|
||||
|
||||
before_filter :find_project, :except => [ :index, :search,:list, :new, :create, :copy, :statistics, :new_join,
|
||||
:course, :enterprise_course, :course_enterprise,:view_homework_attaches]
|
||||
before_filter :authorize, :only => [:show, :settings, :edit, :sort_project_members, :update, :modules, :close,
|
||||
:reopen,:view_homework_attaches,:course]
|
||||
before_filter :find_project, :except => [ :index, :search,:list, :new, :create, :copy, :statistics, :new_join, :course, :enterprise_course, :course_enterprise,:view_homework_attaches,:join_project]
|
||||
# before_filter :authorize, :except => [:new_join, :new_homework, :homework, :statistics, :search, :watcherlist, :index, :list, :new, :create, :copy, :archive, :unarchive, :destroy, :member, :focus, :file,
|
||||
# :statistics, :feedback, :course, :enterprise_course, :course_enterprise, :project_respond, :share,
|
||||
# :show_projects_score, :issue_score_index, :news_score_index, :file_score_index, :code_submit_score_index, :projects_topic_score_index]
|
||||
#此条勿删 课程相关权限 ,:new_homework,:homework,:feedback,,:member
|
||||
before_filter :authorize, :only => [:show, :settings, :edit, :sort_project_members, :update, :modules, :close, :reopen,:view_homework_attaches,:course]
|
||||
before_filter :authorize_global, :only => [:new, :create,:view_homework_attaches]
|
||||
before_filter :require_admin, :only => [ :copy, :archive, :unarchive, :destroy, :calendar]
|
||||
|
@ -181,6 +173,7 @@ class ProjectsController < ApplicationController
|
|||
@project.safe_attributes = params[:project]
|
||||
@project.organization_id = params[:organization_id]
|
||||
@project.user_id = User.current.id
|
||||
@project.project_new_type = 1
|
||||
if validate_parent_id && @project.save
|
||||
@project.set_allowed_parent!(params[:project]['parent_id']) if params[:project].has_key?('parent_id')
|
||||
# Add current user as a project member if he is not admin
|
||||
|
@ -250,18 +243,14 @@ class ProjectsController < ApplicationController
|
|||
# Author lizanle
|
||||
# Description 项目动态展示方法,删除了不必要的代码
|
||||
def show
|
||||
|
||||
# 试图跳转到请求的按钮
|
||||
# params[:login]为邮箱邀请用户加入,主要功能:
|
||||
# 1、自动注册
|
||||
# 2、加入项目、创建角色
|
||||
# 3、用户得分
|
||||
if params[:login]
|
||||
login = params[:login]
|
||||
login = login.sub(/%40/,'@')
|
||||
mail = params[:login]
|
||||
password = params[:password]
|
||||
us = UsersService.new
|
||||
user = us.register_auto(login,mail, password)
|
||||
Member.create(:role_ids => [4], :user_id => user.id,:project_id => @project.id)
|
||||
UserGrade.create(:user_id => user.id, :project_id => @project.id)
|
||||
User.current = user unless User.current.nil?
|
||||
# 自动激活用户
|
||||
user.status = 1
|
||||
user.save
|
||||
end
|
||||
if params[:jump] && redirect_to_project_menu_item(@project, params[:jump])
|
||||
return
|
||||
|
@ -331,14 +320,46 @@ class ProjectsController < ApplicationController
|
|||
@member ||= @project.members.new
|
||||
@trackers = Tracker.sorted.all
|
||||
@wiki ||= @project.wiki
|
||||
@select_tab = params[:tab]
|
||||
|
||||
# 处理从新建版本库返回来的错误信息
|
||||
if !params[:repository_error_message].to_s.blank?
|
||||
html = ""
|
||||
errors = params[:repository_error_message].flatten
|
||||
errors.each do |error|
|
||||
# 版本库路径为空的错误信息不予提示
|
||||
if(error!=l(:label_repository_path_not_null))
|
||||
html << error << ";"
|
||||
end
|
||||
end
|
||||
if params[:repository] == "pswd_is_null"
|
||||
html << l(:label_password_not_null)
|
||||
end
|
||||
flash[:error] = html if !html.to_s.blank?
|
||||
end
|
||||
scm = params[:repository_scm] || (Redmine::Scm::Base.all & Setting.enabled_scm).first
|
||||
@repository = Repository.factory(scm)
|
||||
@repository.is_default = @project.repository.nil?
|
||||
@repository.project = @project
|
||||
|
||||
end
|
||||
|
||||
# 两种情况:1、系统外用户;2、系统内用户 (通过邮件判定)
|
||||
def send_mail_to_member
|
||||
if !params[:mail].blank? && User.find_by_mail(params[:mail].to_s).nil?
|
||||
email = params[:mail]
|
||||
Mailer.run.send_invite_in_project(email, @project, User.current)
|
||||
@is_zhuce =false
|
||||
flash[:notice] = l(:notice_email_sent, :value => email)
|
||||
elsif !User.find_by_mail(params[:mail].to_s).nil?
|
||||
user = User.find_by_mail(params[:mail].to_s)
|
||||
if !user.member_of?(@project)
|
||||
email = params[:mail]
|
||||
Mailer.run.request_member_to_project(email, @project, User.current)
|
||||
flash[:notice] = l(:notice_email_sent, :value => email)
|
||||
else
|
||||
flash[:error] = l(:label_member_of_project, :value => email)
|
||||
end
|
||||
else
|
||||
flash[:error] = l(:notice_registed_error, :value => email)
|
||||
@is_zhuce = true
|
||||
|
@ -347,6 +368,7 @@ class ProjectsController < ApplicationController
|
|||
format.html{redirect_to invite_members_by_mail_project_url(@project)}
|
||||
end
|
||||
end
|
||||
|
||||
#发送邮件邀请新用户
|
||||
def invite_members_by_mail
|
||||
if User.current.member_of?(@project) || User.current.admin?
|
||||
|
@ -379,7 +401,7 @@ class ProjectsController < ApplicationController
|
|||
# include CoursesHelper
|
||||
def member
|
||||
## 有角色参数的才是课程,没有的就是项目
|
||||
@render_file = 'member_list'
|
||||
@render_file = 'project_member_list'
|
||||
# 判断是否课程
|
||||
if @project.project_type == Project::ProjectType_course
|
||||
@teachers= searchTeacherAndAssistant(@project)
|
||||
|
@ -455,22 +477,10 @@ class ProjectsController < ApplicationController
|
|||
def update
|
||||
@project.safe_attributes = params[:project]
|
||||
@project.organization_id = params[:organization_id]
|
||||
#@project.dts_test = params[:project][:dts_test]
|
||||
params[:project][:is_public] ? @project.is_public = 1 : @project.is_public = 0
|
||||
params[:project][:hidden_repo] ? @project.hidden_repo = 1 : @project.hidden_repo = 0
|
||||
if validate_parent_id && @project.save
|
||||
@course = Course.find_by_extra(@project.identifier)
|
||||
unless @course.nil?
|
||||
@course.password = params[:project][:course][:password]
|
||||
# added by bai
|
||||
@course.term = params[:term]
|
||||
@course.time = params[:time]
|
||||
@course.setup_time = params[:setup_time]
|
||||
@course.endup_time = params[:endup_time]
|
||||
@course.class_period = params[:class_period]
|
||||
# end
|
||||
@course.save
|
||||
end
|
||||
@project.set_allowed_parent!(params[:project]['parent_id']) if params[:project].has_key?('parent_id')
|
||||
|
||||
if params[:project][:is_public] == '0'
|
||||
project_status = ProjectStatus.find_by_project_id(@project.id)
|
||||
project_status.destroy if project_status
|
||||
|
@ -618,6 +628,17 @@ class ProjectsController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
#朋友圈、科研组、开发组之间的切换
|
||||
def change_project_type
|
||||
@project.project_new_type = params[:project_type]
|
||||
if @project.save
|
||||
message = @project.project_new_type
|
||||
else
|
||||
message = "0"
|
||||
end
|
||||
render :json => message
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def memberAccess
|
||||
|
|
|
@ -25,6 +25,7 @@ class ChangesetNotFound < Exception; end
|
|||
class InvalidRevisionParam < Exception; end
|
||||
|
||||
class RepositoriesController < ApplicationController
|
||||
include ApplicationHelper
|
||||
menu_item :repository
|
||||
menu_item :settings, :only => [:new, :create, :edit, :update, :destroy, :committers]
|
||||
default_search_scope :changesets
|
||||
|
@ -122,7 +123,7 @@ update
|
|||
if request.post? && @repository.save
|
||||
redirect_to settings_project_url(@project, :tab => 'repositories')
|
||||
else
|
||||
render :action => 'new'
|
||||
redirect_to settings_project_url(@project, :tab => 'repositories')
|
||||
end
|
||||
else # 原逻辑
|
||||
##xianbo
|
||||
|
@ -167,11 +168,12 @@ update
|
|||
|
||||
@repository.update_attributes(:login => User.current.login.to_s)
|
||||
end
|
||||
redirect_to settings_project_url(@project, :tab => 'repositories')
|
||||
else if(@repository_tag)
|
||||
render :action => 'newrepo', :layout =>'base_projects'
|
||||
redirect_to settings_project_url(@project, :tab => 'repositories',:repository_error_message=>@repository.errors.full_messages)
|
||||
else if(@repository_tag.blank?)
|
||||
#render :action => 'newrepo', :layout =>'base_projects'
|
||||
redirect_to settings_project_url(@project, :tab => 'repositories',:repository => "pswd_is_null",:repository_error_message=>@repository.errors.full_messages)
|
||||
else
|
||||
render :action => 'new', :layout =>'base_projects'
|
||||
redirect_to settings_project_url(@project, :tab => 'repositories',:repository => @repository,:repository_error_message=>@repository.errors.full_messages)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -234,24 +236,10 @@ update
|
|||
end
|
||||
|
||||
def destroy
|
||||
@root_path=RepositoriesHelper::ROOT_PATH
|
||||
@repo_name=User.current.login.to_s+"_"+@repository.identifier.to_s
|
||||
@repository_name=User.current.login.to_s+"/"+@repository.identifier.to_s+".git"
|
||||
@middle=User.current.login.to_s+"_"+@repository.identifier.to_s+"-write:"
|
||||
@repository.destroy if request.delete?
|
||||
DestroyRepositoryTask.new.destroy(User.current.id, @repository.id)
|
||||
@repository.hidden = true
|
||||
@repository.save
|
||||
redirect_to settings_project_url(@project, :tab => 'repositories')
|
||||
if(@repository.type=="Repository::Git")
|
||||
logger.info "destory the repository value"+"root path"+@root_path+"repo_name"+@repo_name+
|
||||
"repository_name"+@repository_name+"user group"+@middle
|
||||
system "sed -i /"+@repo_name+"/{d} "+@root_path+"htdocs/user.passwd"
|
||||
system "sed -i /"+@middle+"/{d} "+@root_path+"htdocs/group.passwd"
|
||||
system "rm -r "+@root_path+"htdocs/"+@repository_name
|
||||
# if(@sed_user&&@sed_group&&@remove)
|
||||
# else
|
||||
# logger.info "An error occured when destory the repository"+"delete form passwd: \n"+
|
||||
# @sed_user+"delete from group"+@sed_group+"delete from file"+@remove
|
||||
# end
|
||||
end
|
||||
end
|
||||
|
||||
def show
|
||||
|
|
|
@ -57,5 +57,98 @@ class TestController < ApplicationController
|
|||
attach.filename
|
||||
end
|
||||
|
||||
def mailer()
|
||||
raise unless Rails.env.development?
|
||||
@user = User.find(params[:user_id])
|
||||
send_for_user_activities(@user, Time.now,1)
|
||||
render 'mailer/send_for_user_activities'
|
||||
end
|
||||
def send_for_user_activities(user, date_to, days)
|
||||
date_from = date_to - days.days
|
||||
|
||||
end
|
||||
subject = "[ #{user.show_name}#{l(:label_day_mail)}]"
|
||||
@subject = " #{user.show_name}#{l(:label_day_mail)}"
|
||||
|
||||
date_from = "#{date_from} 17:59:59"
|
||||
date_to = "#{date_to} 17:59:59"
|
||||
|
||||
# 生成token用于直接点击登录
|
||||
@user = user
|
||||
token = Token.new(:user =>user , :action => 'autologin')
|
||||
token.save
|
||||
@token = token
|
||||
|
||||
# 查询user参加的项目及课程
|
||||
projects = user.projects
|
||||
courses = user.courses
|
||||
project_ids = projects.map{|project| project.id}.join(",")
|
||||
course_ids = courses.map {|course| course.id}.join(",")
|
||||
|
||||
# 查询user的缺陷,包括发布的,跟踪的以及被指派的缺陷
|
||||
sql = "select DISTINCT i.* from issues i, watchers w
|
||||
where (i.assigned_to_id = #{user.id} or i.author_id = #{user.id}
|
||||
or (w.watchable_type = 'Issue' and w.watchable_id = i.id and w.user_id = #{user.id}))
|
||||
and (i.created_on between '#{date_from}' and '#{date_to}') order by i.created_on desc"
|
||||
@issues = Issue.find_by_sql(sql)
|
||||
|
||||
# @bids 查询课程作业,包括老师发布的作业,以及user提交作业
|
||||
# @attachments查询课程课件更新
|
||||
@attachments ||= []
|
||||
|
||||
@bids ||= [] # 老师发布的作业
|
||||
|
||||
unless courses.first.nil?
|
||||
count = courses.count
|
||||
count = count - 1
|
||||
for i in 0..count do
|
||||
bids = courses[i].homeworks.where("bids.created_on between '#{date_from}' and '#{date_to}'").order("bids.created_on desc")
|
||||
attachments = courses[i].attachments.where("attachments.created_on between '#{date_from}' and '#{date_to}'").order('attachments.created_on DESC')
|
||||
@bids += bids if bids.count > 0
|
||||
@attachments += attachments if attachments.count > 0
|
||||
end
|
||||
end
|
||||
# user 提交的作业
|
||||
@homeworks = HomeworkAttach.where("user_id=#{user.id} and (created_at between '#{date_from}' and '#{date_to}')").order("created_at desc")
|
||||
|
||||
# 查询user在课程。项目中发布的讨论帖子
|
||||
messages = Message.find_by_sql("select DISTINCT * from messages where author_id = #{user.id} and (created_on between '#{date_from}' and '#{date_to}') order by created_on desc")
|
||||
@course_messages ||= []
|
||||
@project_messages ||= []
|
||||
unless messages.first.nil?
|
||||
messages.each do |msg|
|
||||
if msg.project
|
||||
@project_messages << msg
|
||||
elsif msg.course
|
||||
@course_messages << msg
|
||||
end
|
||||
end
|
||||
end
|
||||
# 查询user在课程中发布的通知,项目中发的新闻
|
||||
@course_news = (course_ids && !course_ids.empty?) ? News.find_by_sql("select DISTINCT n.* from news n
|
||||
where n.course_id in (#{course_ids})
|
||||
and (created_on between '#{date_from}' and '#{date_to}') order by created_on desc") : []
|
||||
@project_news = (project_ids && !project_ids.empty?) ? News.find_by_sql("select DISTINCT n.* from news n where n.project_id in (#{project_ids})
|
||||
and (created_on between '#{date_from}' and '#{date_to}') order by created_on desc") : []
|
||||
|
||||
# 查询user在课程及个人中留言
|
||||
@course_journal_messages = JournalsForMessage.find_by_sql("select DISTINCT * from journals_for_messages where
|
||||
jour_type='Course' and user_id = #{user.id}
|
||||
and (created_on between '#{date_from}' and '#{date_to}') order by created_on desc")
|
||||
@user_journal_messages = user.journals_for_messages.where("m_parent_id IS NULL and (created_on between '#{date_from}' and '#{date_to}')").order('created_on DESC')
|
||||
|
||||
|
||||
# 查询user新建贴吧或发布帖子
|
||||
@forums = Forum.find_by_sql("select DISTINCT * from forums where creator_id = #{user.id} and (created_at between '#{date_from}' and '#{date_to}') order by created_at desc")
|
||||
@memos = Memo.find_by_sql("select DISTINCT m.* from memos m, forums f where (m.author_id = #{user.id} or (m.forum_id = f.id and f.creator_id = #{user.id}))
|
||||
and (m.created_at between '#{date_from}' and '#{date_to}') order by m.created_at desc")
|
||||
|
||||
|
||||
has_content = [@issues,@homeworks,@course_messages,@project_messages,@course_news,@project_news,
|
||||
@course_journal_messages,@user_journal_messages,@forums,@memos,@attachments,@bids].any? {|o|
|
||||
!o.empty?
|
||||
}
|
||||
#有内容才发,没有不发
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
|
|
@ -85,13 +85,14 @@ class VersionsController < ApplicationController
|
|||
end
|
||||
|
||||
def new
|
||||
@version = @project.versions.build
|
||||
@version.safe_attributes = params[:version]
|
||||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.js
|
||||
end
|
||||
# @version = @project.versions.build
|
||||
# @version.safe_attributes = params[:version]
|
||||
#
|
||||
# respond_to do |format|
|
||||
# format.html
|
||||
# format.js
|
||||
# end
|
||||
redirect_to settings_project_url(@project, :tab => 'versions')
|
||||
end
|
||||
|
||||
def create
|
||||
|
@ -116,7 +117,8 @@ class VersionsController < ApplicationController
|
|||
end
|
||||
else
|
||||
respond_to do |format|
|
||||
format.html { render :action => 'new' }
|
||||
format.html { flash[:error] = @version.errors.full_messages.flatten.to_s
|
||||
redirect_to settings_project_url(@project, :tab => 'versions') }
|
||||
format.js { render :action => 'new' }
|
||||
format.api { render_validation_errors(@version) }
|
||||
end
|
||||
|
@ -136,7 +138,7 @@ class VersionsController < ApplicationController
|
|||
respond_to do |format|
|
||||
format.html {
|
||||
flash[:notice] = l(:notice_successful_update)
|
||||
redirect_back_or_default settings_project_path(@project, :tab => 'versions')
|
||||
redirect_to settings_project_path(@project, :tab => 'versions')
|
||||
}
|
||||
format.api { render_api_ok }
|
||||
end
|
||||
|
|
|
@ -81,9 +81,10 @@ class WordsController < ApplicationController
|
|||
@journal_destroyed = JournalsForMessage.delete_message(params[:object_id])
|
||||
if @journal_destroyed.jour_type == "Bid"
|
||||
@bid = Bid.find(@journal_destroyed.jour_id)
|
||||
end
|
||||
if @bid
|
||||
@jours_count = @bid.journals_for_messages.where('m_parent_id IS NULL').count
|
||||
elsif @journal_destroyed.jour_type == "Course"
|
||||
@course = Course.find @journal_destroyed.jour_id
|
||||
@jours_count = @course.journals_for_messages.where('m_parent_id IS NULL').count
|
||||
end
|
||||
respond_to do |format|
|
||||
format.js
|
||||
|
|
|
@ -188,6 +188,7 @@ class ZipdownController < ApplicationController
|
|||
files_paths.each do |filename|
|
||||
rename_file = File.basename(filename)
|
||||
rename_file = filename_to_real( File.basename(filename)) if is_attachment
|
||||
|
||||
begin
|
||||
zipfile.add(rename_file, filename)
|
||||
rescue Exception => e
|
||||
|
@ -238,4 +239,4 @@ class ZipdownController < ApplicationController
|
|||
attach = Attachment.find_by_disk_filename(name)
|
||||
attach.filename
|
||||
end
|
||||
end
|
||||
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.run.register(token)
|
||||
#flash[:notice] = l(:notice_account_register_done)
|
||||
#render action: 'email_valid', locals: {:mail => user.mail}
|
||||
else
|
||||
yield if block_given?
|
||||
end
|
||||
user
|
||||
end
|
||||
|
||||
def automatically_register(user, &block)
|
||||
# Automatic activation
|
||||
user.activate
|
||||
user.last_login_on = Time.now
|
||||
if user.save
|
||||
UserStatus.create(:user_id => user.id, :changsets_count => 0, :watchers_count => 0)
|
||||
#self.logged_user = user
|
||||
#flash[:notice] = l(:notice_account_activated)
|
||||
#redirect_to my_account_url
|
||||
else
|
||||
yield if block_given?
|
||||
end
|
||||
user
|
||||
end
|
||||
|
||||
def administrator_manually__register(user, &block)
|
||||
if user.save
|
||||
UserStatus.create(:user_id => user.id ,:changsets_count => 0, :watchers_count => 0)
|
||||
# Sends an email to the administrators
|
||||
Mailer.run.account_activation_request(user)
|
||||
#account_pending
|
||||
else
|
||||
yield if block_given?
|
||||
end
|
||||
user
|
||||
end
|
||||
|
||||
end
|
||||
# encoding: utf-8
|
||||
#
|
||||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
module AccountHelper
|
||||
|
||||
def email_activation_register(user, &block)
|
||||
token = Token.new(:user => user, :action => "register")
|
||||
if user.save and token.save
|
||||
UserStatus.create(:user_id => user.id, :changsets_count => 0, :watchers_count => 0)
|
||||
Mailer.run.register(token)
|
||||
#flash[:notice] = l(:notice_account_register_done)
|
||||
#render action: 'email_valid', locals: {:mail => user.mail}
|
||||
else
|
||||
yield if block_given?
|
||||
end
|
||||
user
|
||||
end
|
||||
|
||||
def automatically_register(user, &block)
|
||||
# Automatic activation
|
||||
user.activate
|
||||
user.last_login_on = Time.now
|
||||
if user.save
|
||||
UserStatus.create(:user_id => user.id, :changsets_count => 0, :watchers_count => 0)
|
||||
#self.logged_user = user
|
||||
#flash[:notice] = l(:notice_account_activated)
|
||||
#redirect_to my_account_url
|
||||
else
|
||||
yield if block_given?
|
||||
end
|
||||
user
|
||||
end
|
||||
|
||||
def administrator_manually__register(user, &block)
|
||||
if user.save
|
||||
UserStatus.create(:user_id => user.id ,:changsets_count => 0, :watchers_count => 0)
|
||||
# Sends an email to the administrators
|
||||
Mailer.run.account_activation_request(user)
|
||||
#account_pending
|
||||
else
|
||||
yield if block_given?
|
||||
end
|
||||
user
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -1,45 +1,45 @@
|
|||
# encoding: utf-8
|
||||
#
|
||||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
module ActivitiesHelper
|
||||
def sort_activity_events(events)
|
||||
events_by_group = events.group_by(&:event_group)
|
||||
sorted_events = []
|
||||
events.sort {|x, y| y.event_datetime <=> x.event_datetime}.each do |event|
|
||||
if group_events = events_by_group.delete(event.event_group)
|
||||
group_events.sort {|x, y| y.event_datetime <=> x.event_datetime}.each_with_index do |e, i|
|
||||
sorted_events << [e, i > 0] unless e.event_description.nil?
|
||||
end
|
||||
end
|
||||
end
|
||||
sorted_events
|
||||
end
|
||||
def sort_activity_events_course(events)
|
||||
events_by_group = events.group_by(&:event_group)
|
||||
sorted_events = []
|
||||
events.sort {|x, y| y.event_datetime <=> x.event_datetime}.each do |event|
|
||||
if group_events = events_by_group.delete(event.event_group)
|
||||
group_events.sort {|x, y| y.event_datetime <=> x.event_datetime}.each_with_index do |e, i|
|
||||
sorted_events << e unless e.event_description.nil?
|
||||
end
|
||||
end
|
||||
end
|
||||
sorted_events
|
||||
end
|
||||
end
|
||||
# encoding: utf-8
|
||||
#
|
||||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
module ActivitiesHelper
|
||||
def sort_activity_events(events)
|
||||
events_by_group = events.group_by(&:event_group)
|
||||
sorted_events = []
|
||||
events.sort {|x, y| y.event_datetime <=> x.event_datetime}.each do |event|
|
||||
if group_events = events_by_group.delete(event.event_group)
|
||||
group_events.sort {|x, y| y.event_datetime <=> x.event_datetime}.each_with_index do |e, i|
|
||||
sorted_events << [e, i > 0] unless e.event_description.nil?
|
||||
end
|
||||
end
|
||||
end
|
||||
sorted_events
|
||||
end
|
||||
def sort_activity_events_course(events)
|
||||
events_by_group = events.group_by(&:event_group)
|
||||
sorted_events = []
|
||||
events.sort {|x, y| y.event_datetime <=> x.event_datetime}.each do |event|
|
||||
if group_events = events_by_group.delete(event.event_group)
|
||||
group_events.sort {|x, y| y.event_datetime <=> x.event_datetime}.each_with_index do |e, i|
|
||||
sorted_events << e unless e.event_description.nil?
|
||||
end
|
||||
end
|
||||
end
|
||||
sorted_events
|
||||
end
|
||||
end
|
||||
|
|
|
@ -81,7 +81,7 @@ module ApplicationHelper
|
|||
def authorize_for(controller, action)
|
||||
User.current.allowed_to?({:controller => controller, :action => action}, @project)
|
||||
end
|
||||
|
||||
|
||||
# add by nwb
|
||||
def authorize_for_course(controller, action)
|
||||
User.current.allowed_to?({:controller => controller, :action => action}, @course)
|
||||
|
@ -128,6 +128,24 @@ module ApplicationHelper
|
|||
end
|
||||
end
|
||||
|
||||
def link_to_isuue_user(user, options={})
|
||||
if user.is_a?(User)
|
||||
name = h(user.name(options[:format]))
|
||||
link_to name, {:controller=> 'users', :action => 'show', id: user.id, host: Setting.user_domain}, :class => "pro_info_p"
|
||||
else
|
||||
h(user.to_s)
|
||||
end
|
||||
end
|
||||
|
||||
def link_to_settings_user(user, options={})
|
||||
if user.is_a?(User)
|
||||
name = h(user.name(options[:format]))
|
||||
link_to name, {:controller=> 'users', :action => 'show', id: user.id, host: Setting.user_domain}, :class => "w90 c_orange fl"
|
||||
else
|
||||
h(user.to_s)
|
||||
end
|
||||
end
|
||||
|
||||
#重载上面方法,增加样式显示
|
||||
def link_to_user_header user,canShowRealName=false,options={}
|
||||
if user.is_a?(User)
|
||||
|
@ -170,6 +188,28 @@ module ApplicationHelper
|
|||
s
|
||||
end
|
||||
|
||||
def link_to_issue_version(issue, options={})
|
||||
title = nil
|
||||
subject = nil
|
||||
text = options[:tracker] == false ? "##{issue.id}" : "#{issue.tracker} ##{issue.id}"
|
||||
if options[:subject] == false
|
||||
title = truncate(issue.subject, :length => 60)
|
||||
else
|
||||
subject = issue.subject
|
||||
if options[:truncate]
|
||||
subject = truncate(subject, :length => 60)
|
||||
end
|
||||
end
|
||||
if issue.status_id == 5
|
||||
s = link_to text, issue_path(issue), :class => "text_line_s", :title => title
|
||||
else
|
||||
s = link_to text, issue_path(issue), :class => "c_blue", :title => title
|
||||
end
|
||||
s << h(": #{subject}") if subject
|
||||
s = h("#{issue.project} - ") + s if options[:project]
|
||||
s
|
||||
end
|
||||
|
||||
# Generates a link to an attachment.
|
||||
# Options:
|
||||
# * :text - Link text (default to attachment filename)
|
||||
|
@ -193,7 +233,7 @@ module ApplicationHelper
|
|||
route_method = options.delete(:download) ? :download_named_attachment_path : :named_attachment_path
|
||||
html_options = options.slice!(:only_path)
|
||||
url = send(route_method, attachment, attachment.filename, options)
|
||||
url << "?token=#{token}" unless token.nil?
|
||||
url << "?token=#{token}" unless token.nil?
|
||||
link_to text, url, html_options
|
||||
end
|
||||
|
||||
|
@ -218,18 +258,18 @@ module ApplicationHelper
|
|||
h(text),
|
||||
{:controller => 'repositories', :action => 'revision', :id => repository.project, :repository_id => repository.identifier_param, :rev => rev},
|
||||
:title => l(:label_revision_id, format_revision(revision))
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
# Generates a link to a message
|
||||
def link_to_message(message, options={}, html_options = nil)
|
||||
link_to(
|
||||
truncate(message.subject, :length => 60),
|
||||
board_message_path(message.board_id, message.parent_id || message.id, {
|
||||
:r => (message.parent_id && message.id),
|
||||
:anchor => (message.parent_id ? "message-#{message.id}" : nil)
|
||||
}.merge(options)),
|
||||
html_options
|
||||
truncate(message.subject, :length => 60),
|
||||
board_message_path(message.board_id, message.parent_id || message.id, {
|
||||
:r => (message.parent_id && message.id),
|
||||
:anchor => (message.parent_id ? "message-#{message.id}" : nil)
|
||||
}.merge(options)),
|
||||
html_options
|
||||
)
|
||||
end
|
||||
|
||||
|
@ -281,8 +321,23 @@ module ApplicationHelper
|
|||
|
||||
def thumbnail_tag(attachment)
|
||||
link_to image_tag(thumbnail_path(attachment)),
|
||||
named_attachment_path(attachment, attachment.filename),
|
||||
:title => attachment.filename
|
||||
named_attachment_path(attachment, attachment.filename),
|
||||
:title => attachment.filename
|
||||
end
|
||||
|
||||
def thumbnail_issue_tag(attachment)
|
||||
imagesize = attachment.thumbnail(:size => "200*200")
|
||||
imagepath = named_attachment_path(attachment, attachment.filename)
|
||||
if imagesize
|
||||
link_to image_tag(thumbnail_path(attachment), height: '73', width: '100', name: 'issue_attachment_picture'),
|
||||
imagepath,
|
||||
:title => attachment.filename
|
||||
|
||||
else
|
||||
link_to image_tag(imagepath , height: '73', width: '100', name: 'issue_attachment_picture'),
|
||||
imagepath,
|
||||
:title => attachment.filename
|
||||
end
|
||||
end
|
||||
|
||||
# 图片缩略图链接
|
||||
|
@ -310,9 +365,9 @@ module ApplicationHelper
|
|||
def image_to_function(name, function, html_options = {})
|
||||
html_options.symbolize_keys!
|
||||
tag(:input, html_options.merge({
|
||||
:type => "image", :src => image_path(name),
|
||||
:onclick => (html_options[:onclick] ? "#{html_options[:onclick]}; " : "") + "#{function};"
|
||||
}))
|
||||
:type => "image", :src => image_path(name),
|
||||
:onclick => (html_options[:onclick] ? "#{html_options[:onclick]}; " : "") + "#{function};"
|
||||
}))
|
||||
end
|
||||
|
||||
def format_activity_title(text)
|
||||
|
@ -330,9 +385,9 @@ module ApplicationHelper
|
|||
|
||||
def format_version_name(version)
|
||||
if version.project == @project
|
||||
h(version)
|
||||
h(truncate(version.name,:length=>20))
|
||||
else
|
||||
h("#{version.project} - #{version}")
|
||||
h("#{version.project} - #{truncate(version.name,:length=>20)}")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -346,7 +401,7 @@ module ApplicationHelper
|
|||
# The given collection may be a subset of the whole project tree
|
||||
# (eg. some intermediate nodes are private and can not be seen)
|
||||
#Modified by nie.
|
||||
def render_project_nested_lists(projects)
|
||||
def render_project_nested_lists(projects)
|
||||
s = ''
|
||||
if projects.any?
|
||||
ancestors = []
|
||||
|
@ -375,9 +430,9 @@ module ApplicationHelper
|
|||
|
||||
if project.try(:project_type) == Project::ProjectType_project
|
||||
unless User.current.member_of?(@project)
|
||||
s << "<span style = 'float: right;'>"
|
||||
s << watcher_link(@project, User.current)#, ['whiteButton'])
|
||||
s << "</span>"
|
||||
s << "<span style = 'float: right;'>"
|
||||
s << watcher_link(@project, User.current)#, ['whiteButton'])
|
||||
s << "</span>"
|
||||
end
|
||||
s << (render :partial => 'projects/project', :locals => {:project => project}).to_s
|
||||
else
|
||||
|
@ -390,7 +445,7 @@ module ApplicationHelper
|
|||
@project = original_project
|
||||
end
|
||||
s.html_safe
|
||||
end
|
||||
end
|
||||
|
||||
def render_course_nested_lists(courses)
|
||||
s = ''
|
||||
|
@ -425,7 +480,7 @@ module ApplicationHelper
|
|||
end
|
||||
|
||||
|
||||
#added by young
|
||||
#added by young
|
||||
def render_project_nested_lists_new(projects)
|
||||
s = ''
|
||||
if projects.any?
|
||||
|
@ -454,7 +509,7 @@ module ApplicationHelper
|
|||
end
|
||||
s.html_safe
|
||||
end
|
||||
#end
|
||||
#end
|
||||
def render_page_hierarchy(pages, node=nil, options={})
|
||||
content = ''
|
||||
if pages[node]
|
||||
|
@ -489,14 +544,22 @@ module ApplicationHelper
|
|||
end
|
||||
end
|
||||
|
||||
def render_project_settings_tabs(tabs)
|
||||
if tabs.any?
|
||||
render :partial => 'common/project_tab', :locals => {:tabs => tabs}
|
||||
else
|
||||
content_tag 'p', l(:label_no_data), :class => "nodata"
|
||||
end
|
||||
end
|
||||
|
||||
# Renders the project quick-jump box
|
||||
def render_project_jump_box
|
||||
return unless User.current.logged?
|
||||
projects = User.current.memberships.collect(&:project).compact.select(&:active?).uniq
|
||||
if projects.any?
|
||||
options =
|
||||
("<option value=''>#{ l(:label_jump_to_a_project) }</option>" +
|
||||
'<option value="" disabled="disabled">---</option>').html_safe
|
||||
("<option value=''>#{ l(:label_jump_to_a_project) }</option>" +
|
||||
'<option value="" disabled="disabled">---</option>').html_safe
|
||||
|
||||
options << project_tree_options_for_select(projects, :selected => @project) do |p|
|
||||
{ :value => project_path(:id => p, :jump => current_menu_item) }
|
||||
|
@ -547,6 +610,17 @@ module ApplicationHelper
|
|||
s.html_safe
|
||||
end
|
||||
|
||||
#缺陷追踪者列表复选框生成
|
||||
def issue_watcher_check_box_tags_ex name, principals
|
||||
s = ''
|
||||
principals.each do |principal|
|
||||
s << "<li>#{ check_box_tag name, principal.id, false, :id => nil } #{h link_to principal.userInfo, user_path( principal.id)}</li>\n"
|
||||
end
|
||||
s.html_safe
|
||||
end
|
||||
|
||||
|
||||
|
||||
#扩展的checkbox生成
|
||||
def principals_check_box_tags_ex(name, principals)
|
||||
s = ''
|
||||
|
@ -556,6 +630,15 @@ module ApplicationHelper
|
|||
s.html_safe
|
||||
end
|
||||
|
||||
# li标签checkbos扩展
|
||||
def principals_check_box_tags_li(name, principals)
|
||||
s = ''
|
||||
principals.each do |principal|
|
||||
s << "<li>#{ check_box_tag name, principal.id, false, :id => nil } #{h link_to principal.userInfo, user_path( principal.id) }</li>\n"
|
||||
end
|
||||
s.html_safe
|
||||
end
|
||||
|
||||
#扩展的checkbox生成
|
||||
def principals_radio_box_tags_ex(name, principals)
|
||||
s = ''
|
||||
|
@ -666,24 +749,24 @@ module ApplicationHelper
|
|||
link_to(image_tag('2uparrow.png', :alt => l(:label_sort_highest)),
|
||||
url.merge({"#{name}[move_to]" => 'highest'}),
|
||||
:method => method, :title => l(:label_sort_highest)) +
|
||||
link_to(image_tag('1uparrow.png', :alt => l(:label_sort_higher)),
|
||||
url.merge({"#{name}[move_to]" => 'higher'}),
|
||||
:method => method, :title => l(:label_sort_higher)) +
|
||||
link_to(image_tag('1downarrow.png', :alt => l(:label_sort_lower)),
|
||||
url.merge({"#{name}[move_to]" => 'lower'}),
|
||||
:method => method, :title => l(:label_sort_lower)) +
|
||||
link_to(image_tag('2downarrow.png', :alt => l(:label_sort_lowest)),
|
||||
url.merge({"#{name}[move_to]" => 'lowest'}),
|
||||
:method => method, :title => l(:label_sort_lowest))
|
||||
link_to(image_tag('1uparrow.png', :alt => l(:label_sort_higher)),
|
||||
url.merge({"#{name}[move_to]" => 'higher'}),
|
||||
:method => method, :title => l(:label_sort_higher)) +
|
||||
link_to(image_tag('1downarrow.png', :alt => l(:label_sort_lower)),
|
||||
url.merge({"#{name}[move_to]" => 'lower'}),
|
||||
:method => method, :title => l(:label_sort_lower)) +
|
||||
link_to(image_tag('2downarrow.png', :alt => l(:label_sort_lowest)),
|
||||
url.merge({"#{name}[move_to]" => 'lowest'}),
|
||||
:method => method, :title => l(:label_sort_lowest))
|
||||
end
|
||||
|
||||
def breadcrumb(*args)
|
||||
elements = args.flatten
|
||||
elements.any? ? content_tag('p', (args.join(" \xc2\xbb ") + " \xc2\xbb ").html_safe, :class => 'breadcrumb') : nil
|
||||
elements.any? ? content_tag('p', (args.join(" \xc2\xbb ") + " \xc2\xbb ").html_safe, :class => 'wiki_con_tit"') : nil
|
||||
end
|
||||
|
||||
def other_formats_links(&block)
|
||||
concat('<p class="other-formats">'.html_safe + l(:label_export_to))
|
||||
concat('<p class="other-formats fl">'.html_safe + l(:label_export_to))
|
||||
yield Redmine::Views::OtherFormatsBuilder.new(self)
|
||||
concat('</p>'.html_safe)
|
||||
end
|
||||
|
@ -758,15 +841,15 @@ module ApplicationHelper
|
|||
def textilizable(*args)
|
||||
options = args.last.is_a?(Hash) ? args.pop : {}
|
||||
case args.size
|
||||
when 1
|
||||
obj = options[:object]
|
||||
text = args.shift
|
||||
when 2
|
||||
obj = args.shift
|
||||
attr = args.shift
|
||||
text = obj.send(attr).to_s
|
||||
else
|
||||
raise ArgumentError, 'invalid arguments to textilizable'
|
||||
when 1
|
||||
obj = options[:object]
|
||||
text = args.shift
|
||||
when 2
|
||||
obj = args.shift
|
||||
attr = args.shift
|
||||
text = obj.send(attr).to_s
|
||||
else
|
||||
raise ArgumentError, 'invalid arguments to textilizable'
|
||||
end
|
||||
return '' if text.blank?
|
||||
project = options[:project] || @project || (obj && obj.respond_to?(:project) ? obj.project : nil)
|
||||
|
@ -922,18 +1005,18 @@ module ApplicationHelper
|
|||
# check if page exists
|
||||
wiki_page = link_project.wiki.find_page(page)
|
||||
url = if anchor.present? && wiki_page.present? && (obj.is_a?(WikiContent) || obj.is_a?(WikiContent::Version)) && obj.page == wiki_page
|
||||
"##{anchor}"
|
||||
else
|
||||
case options[:wiki_links]
|
||||
when :local; "#{page.present? ? Wiki.titleize(page) : ''}.html" + (anchor.present? ? "##{anchor}" : '')
|
||||
when :anchor; "##{page.present? ? Wiki.titleize(page) : title}" + (anchor.present? ? "_#{anchor}" : '') # used for single-file wiki export
|
||||
else
|
||||
wiki_page_id = page.present? ? Wiki.titleize(page) : nil
|
||||
parent = wiki_page.nil? && obj.is_a?(WikiContent) && obj.page && project == link_project ? obj.page.title : nil
|
||||
url_for(:only_path => only_path, :controller => 'wiki', :action => 'show', :project_id => link_project,
|
||||
:id => wiki_page_id, :version => nil, :anchor => anchor, :parent => parent)
|
||||
end
|
||||
end
|
||||
"##{anchor}"
|
||||
else
|
||||
case options[:wiki_links]
|
||||
when :local; "#{page.present? ? Wiki.titleize(page) : ''}.html" + (anchor.present? ? "##{anchor}" : '')
|
||||
when :anchor; "##{page.present? ? Wiki.titleize(page) : title}" + (anchor.present? ? "_#{anchor}" : '') # used for single-file wiki export
|
||||
else
|
||||
wiki_page_id = page.present? ? Wiki.titleize(page) : nil
|
||||
parent = wiki_page.nil? && obj.is_a?(WikiContent) && obj.page && project == link_project ? obj.page.title : nil
|
||||
url_for(:only_path => only_path, :controller => 'wiki', :action => 'show', :project_id => link_project,
|
||||
:id => wiki_page_id, :version => nil, :anchor => anchor, :parent => parent)
|
||||
end
|
||||
end
|
||||
link_to(title.present? ? title.html_safe : h(page), url, :class => ('wiki-page' + (wiki_page ? '' : ' new')))
|
||||
else
|
||||
# project or wiki doesn't exist
|
||||
|
@ -1008,110 +1091,110 @@ module ApplicationHelper
|
|||
# project.changesets.visible raises an SQL error because of a double join on repositories
|
||||
if repository && (changeset = Changeset.visible.find_by_repository_id_and_revision(repository.id, identifier))
|
||||
link = link_to(h("#{project_prefix}#{repo_prefix}r#{identifier}"), {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :repository_id => repository.identifier_param, :rev => changeset.revision},
|
||||
:class => 'changeset',
|
||||
:title => truncate_single_line(changeset.comments, :length => 100))
|
||||
:class => 'changeset',
|
||||
:title => truncate_single_line(changeset.comments, :length => 100))
|
||||
end
|
||||
end
|
||||
elsif sep == '#'
|
||||
oid = identifier.to_i
|
||||
case prefix
|
||||
when nil
|
||||
if oid.to_s == identifier && issue = Issue.visible.find_by_id(oid, :include => :status)
|
||||
anchor = comment_id ? "note-#{comment_id}" : nil
|
||||
link = link_to("##{oid}", {:only_path => only_path, :controller => 'issues', :action => 'show', :id => oid, :anchor => anchor},
|
||||
:class => issue.css_classes,
|
||||
:title => "#{truncate(issue.subject, :length => 100)} (#{issue.status.name})")
|
||||
end
|
||||
when 'document'
|
||||
if document = Document.visible.find_by_id(oid)
|
||||
link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document},
|
||||
:class => 'document'
|
||||
end
|
||||
when 'version'
|
||||
if version = Version.visible.find_by_id(oid)
|
||||
link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version},
|
||||
:class => 'version'
|
||||
end
|
||||
when 'message'
|
||||
if message = Message.visible.find_by_id(oid, :include => :parent)
|
||||
link = link_to_message(message, {:only_path => only_path}, :class => 'message')
|
||||
end
|
||||
when 'forum'
|
||||
if board = Board.visible.find_by_id(oid)
|
||||
link = link_to h(board.name), {:only_path => only_path, :controller => 'boards', :action => 'show', :id => board, :project_id => board.project},
|
||||
:class => 'board'
|
||||
end
|
||||
when 'news'
|
||||
if news = News.visible.find_by_id(oid)
|
||||
link = link_to h(news.title), {:only_path => only_path, :controller => 'news', :action => 'show', :id => news},
|
||||
:class => 'news'
|
||||
end
|
||||
when 'project'
|
||||
if p = Project.visible.find_by_id(oid)
|
||||
link = link_to_project(p, {:only_path => only_path}, :class => 'project')
|
||||
end
|
||||
when nil
|
||||
if oid.to_s == identifier && issue = Issue.visible.find_by_id(oid, :include => :status)
|
||||
anchor = comment_id ? "note-#{comment_id}" : nil
|
||||
link = link_to("##{oid}", {:only_path => only_path, :controller => 'issues', :action => 'show', :id => oid, :anchor => anchor},
|
||||
:class => issue.css_classes,
|
||||
:title => "#{truncate(issue.subject, :length => 100)} (#{issue.status.name})")
|
||||
end
|
||||
when 'document'
|
||||
if document = Document.visible.find_by_id(oid)
|
||||
link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document},
|
||||
:class => 'document'
|
||||
end
|
||||
when 'version'
|
||||
if version = Version.visible.find_by_id(oid)
|
||||
link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version},
|
||||
:class => 'version'
|
||||
end
|
||||
when 'message'
|
||||
if message = Message.visible.find_by_id(oid, :include => :parent)
|
||||
link = link_to_message(message, {:only_path => only_path}, :class => 'message')
|
||||
end
|
||||
when 'forum'
|
||||
if board = Board.visible.find_by_id(oid)
|
||||
link = link_to h(board.name), {:only_path => only_path, :controller => 'boards', :action => 'show', :id => board, :project_id => board.project},
|
||||
:class => 'board'
|
||||
end
|
||||
when 'news'
|
||||
if news = News.visible.find_by_id(oid)
|
||||
link = link_to h(news.title), {:only_path => only_path, :controller => 'news', :action => 'show', :id => news},
|
||||
:class => 'news'
|
||||
end
|
||||
when 'project'
|
||||
if p = Project.visible.find_by_id(oid)
|
||||
link = link_to_project(p, {:only_path => only_path}, :class => 'project')
|
||||
end
|
||||
end
|
||||
elsif sep == ':'
|
||||
# removes the double quotes if any
|
||||
name = identifier.gsub(%r{^"(.*)"$}, "\\1")
|
||||
case prefix
|
||||
when 'document'
|
||||
if project && document = project.documents.visible.find_by_title(name)
|
||||
link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document},
|
||||
:class => 'document'
|
||||
end
|
||||
when 'version'
|
||||
if project && version = project.versions.visible.find_by_name(name)
|
||||
link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version},
|
||||
:class => 'version'
|
||||
end
|
||||
when 'forum'
|
||||
if project && board = project.boards.visible.find_by_name(name)
|
||||
link = link_to h(board.name), {:only_path => only_path, :controller => 'boards', :action => 'show', :id => board, :project_id => board.project},
|
||||
:class => 'board'
|
||||
end
|
||||
when 'news'
|
||||
if project && news = project.news.visible.find_by_title(name)
|
||||
link = link_to h(news.title), {:only_path => only_path, :controller => 'news', :action => 'show', :id => news},
|
||||
:class => 'news'
|
||||
end
|
||||
when 'commit', 'source', 'export'
|
||||
if project
|
||||
repository = nil
|
||||
if name =~ %r{^(([a-z0-9\-_]+)\|)(.+)$}
|
||||
repo_prefix, repo_identifier, name = $1, $2, $3
|
||||
repository = project.repositories.detect {|repo| repo.identifier == repo_identifier}
|
||||
else
|
||||
repository = project.repository
|
||||
when 'document'
|
||||
if project && document = project.documents.visible.find_by_title(name)
|
||||
link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document},
|
||||
:class => 'document'
|
||||
end
|
||||
if prefix == 'commit'
|
||||
if repository && (changeset = Changeset.visible.where("repository_id = ? AND scmid LIKE ?", repository.id, "#{name}%").first)
|
||||
link = link_to h("#{project_prefix}#{repo_prefix}#{name}"), {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :repository_id => repository.identifier_param, :rev => changeset.identifier},
|
||||
:class => 'changeset',
|
||||
:title => truncate_single_line(changeset.comments, :length => 100)
|
||||
end
|
||||
else
|
||||
if repository && User.current.allowed_to?(:browse_repository, project)
|
||||
name =~ %r{^[/\\]*(.*?)(@([^/\\@]+?))?(#(L\d+))?$}
|
||||
path, rev, anchor = $1, $3, $5
|
||||
link = link_to h("#{project_prefix}#{prefix}:#{repo_prefix}#{name}"), {:controller => 'repositories', :action => (prefix == 'export' ? 'raw' : 'entry'), :id => project, :repository_id => repository.identifier_param,
|
||||
:path => to_path_param(path),
|
||||
:rev => rev,
|
||||
:anchor => anchor},
|
||||
:class => (prefix == 'export' ? 'source download' : 'source')
|
||||
end
|
||||
when 'version'
|
||||
if project && version = project.versions.visible.find_by_name(name)
|
||||
link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version},
|
||||
:class => 'version'
|
||||
end
|
||||
when 'forum'
|
||||
if project && board = project.boards.visible.find_by_name(name)
|
||||
link = link_to h(board.name), {:only_path => only_path, :controller => 'boards', :action => 'show', :id => board, :project_id => board.project},
|
||||
:class => 'board'
|
||||
end
|
||||
when 'news'
|
||||
if project && news = project.news.visible.find_by_title(name)
|
||||
link = link_to h(news.title), {:only_path => only_path, :controller => 'news', :action => 'show', :id => news},
|
||||
:class => 'news'
|
||||
end
|
||||
when 'commit', 'source', 'export'
|
||||
if project
|
||||
repository = nil
|
||||
if name =~ %r{^(([a-z0-9\-_]+)\|)(.+)$}
|
||||
repo_prefix, repo_identifier, name = $1, $2, $3
|
||||
repository = project.repositories.detect {|repo| repo.identifier == repo_identifier}
|
||||
else
|
||||
repository = project.repository
|
||||
end
|
||||
if prefix == 'commit'
|
||||
if repository && (changeset = Changeset.visible.where("repository_id = ? AND scmid LIKE ?", repository.id, "#{name}%").first)
|
||||
link = link_to h("#{project_prefix}#{repo_prefix}#{name}"), {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :repository_id => repository.identifier_param, :rev => changeset.identifier},
|
||||
:class => 'changeset',
|
||||
:title => truncate_single_line(changeset.comments, :length => 100)
|
||||
end
|
||||
else
|
||||
if repository && User.current.allowed_to?(:browse_repository, project)
|
||||
name =~ %r{^[/\\]*(.*?)(@([^/\\@]+?))?(#(L\d+))?$}
|
||||
path, rev, anchor = $1, $3, $5
|
||||
link = link_to h("#{project_prefix}#{prefix}:#{repo_prefix}#{name}"), {:controller => 'repositories', :action => (prefix == 'export' ? 'raw' : 'entry'), :id => project, :repository_id => repository.identifier_param,
|
||||
:path => to_path_param(path),
|
||||
:rev => rev,
|
||||
:anchor => anchor},
|
||||
:class => (prefix == 'export' ? 'source download' : 'source')
|
||||
end
|
||||
end
|
||||
repo_prefix = nil
|
||||
end
|
||||
when 'attachment'
|
||||
attachments = options[:attachments] || (obj && obj.respond_to?(:attachments) ? obj.attachments : nil)
|
||||
if attachments && attachment = Attachment.latest_attach(attachments, name)
|
||||
link = link_to_attachment(attachment, :only_path => only_path, :download => true, :class => 'attachment')
|
||||
end
|
||||
when 'project'
|
||||
if p = Project.visible.where("identifier = :s OR LOWER(name) = :s", :s => name.downcase).first
|
||||
link = link_to_project(p, {:only_path => only_path}, :class => 'project')
|
||||
end
|
||||
repo_prefix = nil
|
||||
end
|
||||
when 'attachment'
|
||||
attachments = options[:attachments] || (obj && obj.respond_to?(:attachments) ? obj.attachments : nil)
|
||||
if attachments && attachment = Attachment.latest_attach(attachments, name)
|
||||
link = link_to_attachment(attachment, :only_path => only_path, :download => true, :class => 'attachment')
|
||||
end
|
||||
when 'project'
|
||||
if p = Project.visible.where("identifier = :s OR LOWER(name) = :s", :s => name.downcase).first
|
||||
link = link_to_project(p, {:only_path => only_path}, :class => 'project')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1128,9 +1211,9 @@ module ApplicationHelper
|
|||
@current_section += 1
|
||||
if @current_section > 1
|
||||
content_tag('div',
|
||||
link_to(image_tag('edit.png'), options[:edit_section_links].merge(:section => @current_section)),
|
||||
:class => 'contextual',
|
||||
:title => l(:button_edit_section)) + heading.html_safe
|
||||
link_to(image_tag('edit.png'), options[:edit_section_links].merge(:section => @current_section)),
|
||||
:class => 'contextual',
|
||||
:title => l(:button_edit_section)) + heading.html_safe
|
||||
else
|
||||
heading
|
||||
end
|
||||
|
@ -1249,10 +1332,10 @@ module ApplicationHelper
|
|||
# Same as Rails' simple_format helper without using paragraphs
|
||||
def simple_format_without_paragraph(text)
|
||||
text.to_s.
|
||||
gsub(/\r\n?/, "\n"). # \r\n and \r -> \n
|
||||
gsub(/\n\n+/, "<br /><br />"). # 2+ newline -> 2 br
|
||||
gsub(/([^\n]\n)(?=[^\n])/, '\1<br />'). # 1 newline -> br
|
||||
html_safe
|
||||
gsub(/\r\n?/, "\n"). # \r\n and \r -> \n
|
||||
gsub(/\n\n+/, "<br /><br />"). # 2+ newline -> 2 br
|
||||
gsub(/([^\n]\n)(?=[^\n])/, '\1<br />'). # 1 newline -> br
|
||||
html_safe
|
||||
end
|
||||
|
||||
def wiki_simple_format_without_paragraph(text)
|
||||
|
@ -1267,7 +1350,7 @@ module ApplicationHelper
|
|||
end
|
||||
|
||||
def lang_options_for_select(blank=true)
|
||||
{ 'Chinese简体中文 '=> 'zh', :English => :en}
|
||||
{ 'Chinese简体中文 '=> 'zh', :English => :en}
|
||||
end
|
||||
|
||||
def label_tag_for(name, option_tags = nil, options = {})
|
||||
|
@ -1334,9 +1417,31 @@ module ApplicationHelper
|
|||
|
||||
def delete_link(url, options={})
|
||||
options = {
|
||||
:method => :delete,
|
||||
:data => {:confirm => l(:text_are_you_sure)},
|
||||
:class => 'icon icon-del'
|
||||
:method => :delete,
|
||||
:data => {:confirm => l(:text_are_you_sure)},
|
||||
:class => 'icon icon-del'
|
||||
}.merge(options)
|
||||
|
||||
link_to l(:button_delete), url, options
|
||||
end
|
||||
|
||||
def delete_link_version(url, options={})
|
||||
options = {
|
||||
:method => :delete,
|
||||
:data => {:confirm => l(:text_are_you_sure)},
|
||||
:class => 'c_purple'
|
||||
}.merge(options)
|
||||
|
||||
link_to l(:button_delete), url, options
|
||||
end
|
||||
|
||||
|
||||
|
||||
def delete_new_link(url, options={})
|
||||
options = {
|
||||
:method => :delete,
|
||||
:data => {:confirm => l(:text_are_you_sure)},
|
||||
:class => "c_purple"
|
||||
}.merge(options)
|
||||
|
||||
link_to l(:button_delete), url, options
|
||||
|
@ -1347,11 +1452,11 @@ module ApplicationHelper
|
|||
:href => "#",
|
||||
:onclick => %|submitPreview("#{escape_javascript url_for(url)}", "#{escape_javascript form}", "#{escape_javascript target}"); return false;|,
|
||||
:accesskey => accesskey(:preview)
|
||||
}.merge(options)
|
||||
}.merge(options)
|
||||
end
|
||||
|
||||
def link_to_function(name, function, html_options={})
|
||||
content_tag(:a, name, {:href => '#', :onclick => "#{function}; return false;"}.merge(html_options))
|
||||
content_tag(:a, name, {:href => '#', :onclick => "#{function}; return false;"}.merge(:class => " c_purple"))
|
||||
end
|
||||
|
||||
# Helper to render JSON in views
|
||||
|
@ -1373,9 +1478,8 @@ module ApplicationHelper
|
|||
end
|
||||
|
||||
def check_all_links(form_name)
|
||||
link_to_function(l(:button_check_all), "checkAll('#{form_name}', true)") +
|
||||
" | ".html_safe +
|
||||
link_to_function(l(:button_uncheck_all), "checkAll('#{form_name}', false)")
|
||||
link_to_function(l(:button_check_all), "checkAll('#{form_name}', true)") + " ".html_safe + " | "+ " ".html_safe +
|
||||
link_to_function(l(:button_uncheck_all), "checkAll('#{form_name}', false)")
|
||||
end
|
||||
|
||||
def progress_bar(pcts, options={})
|
||||
|
@ -1386,12 +1490,12 @@ module ApplicationHelper
|
|||
width = options[:width] || '100px;'
|
||||
legend = options[:legend] || ''
|
||||
content_tag('table',
|
||||
content_tag('tr',
|
||||
(pcts[0] > 0 ? content_tag('td', '', :style => "width: #{pcts[0]}%;", :class => 'closed') : ''.html_safe) +
|
||||
(pcts[1] > 0 ? content_tag('td', '', :style => "width: #{pcts[1]}%;", :class => 'done') : ''.html_safe) +
|
||||
(pcts[2] > 0 ? content_tag('td', '', :style => "width: #{pcts[2]}%;", :class => 'todo') : ''.html_safe)
|
||||
), :class => 'progress', :style => "width: #{width};").html_safe +
|
||||
content_tag('p', legend, :class => 'percent').html_safe
|
||||
content_tag('tr',
|
||||
(pcts[0] > 0 ? content_tag('td', '', :style => "width: #{pcts[0]}%;", :class => 'closed') : ''.html_safe) +
|
||||
(pcts[1] > 0 ? content_tag('td', '', :style => "width: #{pcts[1]}%;", :class => 'done') : ''.html_safe) +
|
||||
(pcts[2] > 0 ? content_tag('td', '', :style => "width: #{pcts[2]}%;", :class => 'todo') : ''.html_safe)
|
||||
), :class => 'progress', :style => "width: #{width};").html_safe +
|
||||
content_tag('p', legend, :class => 'percent').html_safe
|
||||
end
|
||||
|
||||
def checked_image(checked=true)
|
||||
|
@ -1404,7 +1508,7 @@ module ApplicationHelper
|
|||
unless @context_menu_included
|
||||
content_for :header_tags do
|
||||
javascript_include_tag('context_menu') +
|
||||
stylesheet_link_tag('context_menu')
|
||||
stylesheet_link_tag('context_menu')
|
||||
end
|
||||
if l(:direction) == 'rtl'
|
||||
content_for :header_tags do
|
||||
|
@ -1435,7 +1539,7 @@ module ApplicationHelper
|
|||
tags = javascript_tag(
|
||||
"var datepickerOptions={dateFormat: 'yy-mm-dd', firstDay: #{start_of_week}, " +
|
||||
"showOn: 'button', buttonImageOnly: true, buttonImage: '" +
|
||||
path_to_image('/images/calendar.png') +
|
||||
path_to_image('/images/public_icon.png') +
|
||||
"', showButtonPanel: true, showWeek: true, showOtherMonths: true, selectOtherMonths: true};")
|
||||
jquery_locale = l('jquery.locale', :default => current_language.to_s)
|
||||
unless jquery_locale == 'en'
|
||||
|
@ -1457,7 +1561,7 @@ module ApplicationHelper
|
|||
tags = javascript_tag(
|
||||
"var datepickerOptions={dateFormat: 'yy-mm-dd',minDate: new Date(), firstDay: #{start_of_week}, " +
|
||||
"showOn: 'button', buttonImageOnly: true, buttonImage: '" +
|
||||
path_to_image('/images/calendar.png') +
|
||||
path_to_image('/images/public_icon.png') +
|
||||
"', showButtonPanel: true, showWeek: true, showOtherMonths: true, selectOtherMonths: true, onClose: function(dateText, inst) {TimeClose(dateText,inst);}, beforeShow : function(input){TimeBeforeShow(input);} };")
|
||||
jquery_locale = l('jquery.locale', :default => current_language.to_s)
|
||||
unless jquery_locale == 'en'
|
||||
|
@ -1663,7 +1767,7 @@ module ApplicationHelper
|
|||
end
|
||||
s
|
||||
end
|
||||
|
||||
|
||||
def get_memo
|
||||
@new_memo = Memo.new
|
||||
#@new_memo.subject = "有什么想说的,尽管来咆哮吧~~"
|
||||
|
@ -1717,6 +1821,17 @@ module ApplicationHelper
|
|||
candown
|
||||
end
|
||||
|
||||
def project_type_link(text, value)
|
||||
if value == 1
|
||||
link_to "<span class='pr_kafa'></span>#{text}".html_safe,"javascript:void(0)" ,:onClick => "show_window();", :class => "pr_join_a",:id => "setting_project_type"
|
||||
elsif value == 2
|
||||
link_to "<span class='pr_keyan'></span>#{text}".html_safe,"javascript:void(0)" ,:onClick => "show_window();", :class => "pr_join_a",:id => "setting_project_type"
|
||||
else
|
||||
link_to "<span class='pr_friend'></span>#{text}".html_safe,"javascript:void(0)" ,:onClick => "show_window();", :class => "pr_join_a",:id => "setting_project_type"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def wiki_helper
|
||||
|
@ -1746,11 +1861,11 @@ module ApplicationHelper
|
|||
html << (content_tag "span", l(:label_no_current_watchers))
|
||||
end
|
||||
for user in User.watched_by(obj.id)
|
||||
html << (link_to image_tag(url_to_avatar(user), :class => "avatar"), user_path(user), :class => "avatar", :title => "#{user.name}")
|
||||
count = count + 1
|
||||
if count >= 12
|
||||
break
|
||||
end
|
||||
html << (link_to image_tag(url_to_avatar(user), :class => "avatar"), user_path(user), :class => "avatar", :title => "#{user.name}")
|
||||
count = count + 1
|
||||
if count >= 12
|
||||
break
|
||||
end
|
||||
end
|
||||
html.html_safe
|
||||
end
|
||||
|
@ -1776,13 +1891,13 @@ module ApplicationHelper
|
|||
html.html_safe
|
||||
end
|
||||
|
||||
def show_bid_fans_picture(obj)
|
||||
def show_bid_fans_picture(obj)
|
||||
html = ''
|
||||
if obj.watcher_users.count == 0
|
||||
html << (content_tag "span", l(:label_project_no_follow))
|
||||
else
|
||||
obj.watcher_users.take(12).each do |user|
|
||||
html << (link_to image_tag(url_to_avatar(user), :class => "avatar"), user_path(user), :class => "avatar", :title => user.name)
|
||||
html << (link_to image_tag(url_to_avatar(user), :class => "avatar"), user_path(user), :class => "avatar", :title => user.name)
|
||||
end
|
||||
end
|
||||
html.html_safe
|
||||
|
@ -1817,7 +1932,7 @@ module ApplicationHelper
|
|||
html.html_safe
|
||||
end
|
||||
|
||||
def show_contest_project(contest)
|
||||
def show_contest_project(contest)
|
||||
html = ''
|
||||
if contest.projects.where('is_public = 1').count == 0
|
||||
html << (content_tag "p", l(:label_no_bid_project), :class => "font_lighter")
|
||||
|
@ -1829,7 +1944,7 @@ module ApplicationHelper
|
|||
html.html_safe
|
||||
end
|
||||
|
||||
def show_contest_softapplication(contest)
|
||||
def show_contest_softapplication(contest)
|
||||
html = ''
|
||||
if contest.softapplications.where('is_public = 1').count == 0
|
||||
html << (content_tag "p", l(:label_no_contest_softapplication), :class => "font_lighter")
|
||||
|
@ -1841,17 +1956,17 @@ module ApplicationHelper
|
|||
html.html_safe
|
||||
end
|
||||
|
||||
def show_contest_fans_picture(obj)
|
||||
def show_contest_fans_picture(obj)
|
||||
html = ''
|
||||
if obj.watcher_users.count == 0
|
||||
html << (content_tag "span", l(:label_project_no_follow))
|
||||
else
|
||||
obj.watcher_users.take(12).each do |user|
|
||||
html << (link_to image_tag(url_to_avatar(user), :class => "avatar"), user_path(user), :class => "avatar", :title => user.name)
|
||||
html << (link_to image_tag(url_to_avatar(user), :class => "avatar"), user_path(user), :class => "avatar", :title => user.name)
|
||||
end
|
||||
end
|
||||
html.html_safe
|
||||
end
|
||||
end
|
||||
|
||||
#display fans picture
|
||||
def show_more_fans?(obj)
|
||||
|
@ -1868,13 +1983,13 @@ module ApplicationHelper
|
|||
html << (content_tag "span", l(:label_no_current_fans))
|
||||
else
|
||||
obj.watcher_users.take(12).each do |user|
|
||||
html << (link_to image_tag(url_to_avatar(user), :class => "avatar"), user_path(user), :class => "avatar", :title => user.name)
|
||||
html << (link_to image_tag(url_to_avatar(user), :class => "avatar"), user_path(user), :class => "avatar", :title => user.name)
|
||||
end
|
||||
end
|
||||
html.html_safe
|
||||
end
|
||||
|
||||
# added by bai
|
||||
# added by bai
|
||||
def show_more_participate?(obj)
|
||||
if obj.join_in_contests.count > 12
|
||||
return true
|
||||
|
@ -1883,18 +1998,18 @@ module ApplicationHelper
|
|||
end
|
||||
end
|
||||
|
||||
def show_participate_picture(obj)
|
||||
def show_participate_picture(obj)
|
||||
html = ''
|
||||
count = 0
|
||||
if obj.join_in_contests.count == 0
|
||||
html << (content_tag "span", l(:label_no_current_participate))
|
||||
end
|
||||
for temp in obj.join_in_contests
|
||||
html << (link_to image_tag(url_to_avatar(temp.user), :class => "avatar"), user_path(temp.user), :class => "avatar", :title => "#{temp.user.name}")
|
||||
count = count + 1
|
||||
if count >= 12
|
||||
break
|
||||
end
|
||||
html << (link_to image_tag(url_to_avatar(temp.user), :class => "avatar"), user_path(temp.user), :class => "avatar", :title => "#{temp.user.name}")
|
||||
count = count + 1
|
||||
if count >= 12
|
||||
break
|
||||
end
|
||||
end
|
||||
html.html_safe
|
||||
end
|
||||
|
@ -1903,14 +2018,14 @@ module ApplicationHelper
|
|||
|
||||
# add by huang
|
||||
def show_watcher_list(user)
|
||||
html = ''
|
||||
count = 0
|
||||
html = ''
|
||||
count = 0
|
||||
for user in User.watched_by(user.id)
|
||||
html << (link_to image_tag(url_to_avatar(user), :class => "avatar"), user_path(user), :class => "avatar", :title => "#{user.name}")
|
||||
count = count + 1
|
||||
if count >= 12
|
||||
break
|
||||
end
|
||||
html << (link_to image_tag(url_to_avatar(user), :class => "avatar"), user_path(user), :class => "avatar", :title => "#{user.name}")
|
||||
count = count + 1
|
||||
if count >= 12
|
||||
break
|
||||
end
|
||||
end
|
||||
html.html_safe
|
||||
end
|
||||
|
@ -1928,14 +2043,14 @@ module ApplicationHelper
|
|||
return true if bid.nil?
|
||||
|
||||
case bid.homework_type
|
||||
when Bid::HomeworkFile
|
||||
attaches = HomeworkAttach.where(bid_id: curb)
|
||||
attaches.map(&:user_id).include? cur
|
||||
when Bid::HomeworkProject
|
||||
attaches = BidingProject.where(user_id: User.current, bid_id: bid)
|
||||
attaches.count > 0 # > 0 则有提交记录
|
||||
else
|
||||
true
|
||||
when Bid::HomeworkFile
|
||||
attaches = HomeworkAttach.where(bid_id: curb)
|
||||
attaches.map(&:user_id).include? cur
|
||||
when Bid::HomeworkProject
|
||||
attaches = BidingProject.where(user_id: User.current, bid_id: bid)
|
||||
attaches.count > 0 # > 0 则有提交记录
|
||||
else
|
||||
true
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -1964,6 +2079,8 @@ module ApplicationHelper
|
|||
forum_link = link_to l(:label_forum_all), {:controller => "forums", :action => "index"}
|
||||
stores_link = link_to l(:label_stores_index), {:controller => 'stores', :action=> 'index'}
|
||||
school_all_school_link = link_to l(:label_school_all), {:controller => 'school', :action => 'index'}
|
||||
project_new_link = link_to l(:label_project_new), {:controller => 'projects', :action => 'new', :host => Setting.project_domain}
|
||||
# project_mine_link = link_to l(:label_my_project), {:controller => 'users', :action => 'user_projects', :host => Setting.project_domain}
|
||||
|
||||
#@nav_dispaly_project_label
|
||||
nav_list = Array.new
|
||||
|
@ -1976,6 +2093,8 @@ module ApplicationHelper
|
|||
nav_list.push(main_contest_link) if @nav_dispaly_main_contest_label && @show_contest == 1 && visiable
|
||||
|
||||
nav_list.push(courses_link) if @nav_dispaly_course_label && @show_course == 1 && visiable
|
||||
nav_list.push(project_new_link) if @nav_dispaly_project_label
|
||||
# nav_list.push(project_mine_link) if @nav_dispaly_main_project_label
|
||||
# nav_list.push(projects_link) if @nav_dispaly_project_label
|
||||
#nav_list.push(users_link) if @nav_dispaly_user_label
|
||||
# nav_list.push(contest_link) if @nav_dispaly_contest_label && @show_contest == 1
|
||||
|
@ -1995,12 +2114,12 @@ module ApplicationHelper
|
|||
end
|
||||
|
||||
# def hadcommittedforcontest(curu)
|
||||
# message = JournalsForMessage.find_by_sql("select * from journals_for_messages where jour_type = 'Softapplication' ")
|
||||
# message.each do |createmessage|
|
||||
# if createmessage.user_id == curu
|
||||
# return true
|
||||
# end
|
||||
# end
|
||||
# message = JournalsForMessage.find_by_sql("select * from journals_for_messages where jour_type = 'Softapplication' ")
|
||||
# message.each do |createmessage|
|
||||
# if createmessage.user_id == curu
|
||||
# return true
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
|
||||
def footer_logo(ul_class=nil, li_class=nil)
|
||||
|
@ -2020,16 +2139,16 @@ module ApplicationHelper
|
|||
|
||||
def sort_homework_path(bid, sort, direction)
|
||||
case self.action_name
|
||||
when 'show_courseEx'
|
||||
get_not_batch_homework_homework_attach_index_path(bid_id: bid.id, sort: sort, direction: 'asc')
|
||||
when 'get_not_batch_homework'
|
||||
get_not_batch_homework_homework_attach_index_path(bid_id: bid.id, sort: sort, direction: direction)
|
||||
when 'get_batch_homeworks'
|
||||
get_batch_homeworks_homework_attach_index_path(bid_id: bid.id, sort: sort, direction: direction)
|
||||
when 'get_homeworks'
|
||||
get_homeworks_homework_attach_index_path(bid_id: bid.id, sort: sort, direction: direction)
|
||||
else
|
||||
'#'
|
||||
when 'show_courseEx'
|
||||
get_not_batch_homework_homework_attach_index_path(bid_id: bid.id, sort: sort, direction: 'asc')
|
||||
when 'get_not_batch_homework'
|
||||
get_not_batch_homework_homework_attach_index_path(bid_id: bid.id, sort: sort, direction: direction)
|
||||
when 'get_batch_homeworks'
|
||||
get_batch_homeworks_homework_attach_index_path(bid_id: bid.id, sort: sort, direction: direction)
|
||||
when 'get_homeworks'
|
||||
get_homeworks_homework_attach_index_path(bid_id: bid.id, sort: sort, direction: direction)
|
||||
else
|
||||
'#'
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -35,6 +35,16 @@ module AttachmentsHelper
|
|||
end
|
||||
end
|
||||
|
||||
def link_to_attachment_project(container, options = {})
|
||||
options.assert_valid_keys(:author, :thumbnails)
|
||||
|
||||
if container.attachments.any?
|
||||
options = {:deletable => container.attachments_deletable?, :author => true}.merge(options)
|
||||
render :partial => 'attachments/project_file_links',
|
||||
:locals => {:attachments => container.attachments, :options => options, :thumbnails => (options[:thumbnails] && Setting.thumbnails_enabled?)}
|
||||
end
|
||||
end
|
||||
|
||||
def link_to_attachments_course(container, options = {})
|
||||
options.assert_valid_keys(:author, :thumbnails)
|
||||
|
||||
|
|
|
@ -691,9 +691,11 @@ module CoursesHelper
|
|||
#end
|
||||
|
||||
#poll_count
|
||||
#Poll.where(polls_group_id: @course_ids, polls_type: Course, polls_status: 2||3).where("published_at>?",date_from).each do |poll|
|
||||
# activities[poll.polls_group_id]+=1
|
||||
#end
|
||||
# 动态目前只统计发布的问卷,关闭的问卷不在动态内显示
|
||||
# Poll.where(polls_group_id: @course_ids, polls_type: Course, polls_status: 2||3).where("published_at>?",date_from).each do |poll|
|
||||
Poll.where(polls_group_id: @course_ids, polls_type: Course, polls_status: 2||3).where("published_at>?",date_from).each do |poll|
|
||||
activities[poll.polls_group_id]+=1
|
||||
end
|
||||
#end
|
||||
|
||||
|
||||
|
|
|
@ -1,150 +1,150 @@
|
|||
# encoding: utf-8
|
||||
module FilesHelper
|
||||
include AttachmentsHelper
|
||||
|
||||
def downloadAll containers
|
||||
paths = []
|
||||
files = []
|
||||
tmpfile = "tmp.zip"
|
||||
|
||||
containers.each do |container|
|
||||
next if container.attachments.empty?
|
||||
if container.is_a?(Version);end
|
||||
container.attachments.each do |attachment|
|
||||
paths << attachment.diskfile
|
||||
file = attachment.diskfile
|
||||
# logger.error "[FilesHelper] downloadAll: #{e}"
|
||||
begin
|
||||
File.new(file, "r")
|
||||
rescue Exception => e
|
||||
logger.error e
|
||||
next
|
||||
end
|
||||
files << file
|
||||
# zip.add(file.path.dup.sub(directory, ''), file.path)
|
||||
end
|
||||
end
|
||||
|
||||
zipfile_name = "archive.zip"
|
||||
if File.exists? File.open(zipfile_name, "w+")
|
||||
ff = File.open(zipfile_name, "w+")
|
||||
ff.close
|
||||
File.delete ff
|
||||
end
|
||||
Zip::ZipFile.open(zipfile_name, Zip::ZipFile::CREATE) do |zipfile|
|
||||
files.each do |filename|
|
||||
directory = File.dirname filename
|
||||
# Two arguments:
|
||||
# - The name of the file as it will appear in the archive
|
||||
# - The original file, including the path to find it
|
||||
dir = filename.sub(directory+"/", '')
|
||||
zipfile.add(dir, filename)
|
||||
|
||||
end
|
||||
end
|
||||
File.new(zipfile_name,'w+')
|
||||
end
|
||||
|
||||
#带勾选框的课程列表
|
||||
def courses_check_box_tags(name,courses,current_course,attachment)
|
||||
s = ''
|
||||
courses.each do |course|
|
||||
if !course_contains_attachment?(course,attachment) && is_course_teacher(User.current,course) && course_in_current_or_next_term(course)
|
||||
s << "<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 get_attachments_by_tag attachments,tag
|
||||
attachments.each do |attachment|
|
||||
attachment.tag_list.include?(tag)
|
||||
end
|
||||
end
|
||||
|
||||
def visable_attachemnts_insite attachments,obj
|
||||
result = []
|
||||
if obj.is_a?(Course)
|
||||
attachments.each do |attachment|
|
||||
if attachment.is_public? || (attachment.container_type == "Course" && attachment.container_id == obj.id && User.current.member_of_course?(Course.find(attachment.container_id)))|| attachment.author_id == User.current.id
|
||||
result << attachment
|
||||
end
|
||||
end
|
||||
else if obj.is_a?(Project)
|
||||
attachments.each do |attachment|
|
||||
if attachment.is_public? || (attachment.container_type == "Project" && attachment.container_id == obj.id && User.current.member_of_course?(Project.find(attachment.container_id)))|| attachment.author_id == User.current.id
|
||||
result << attachment
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
|
||||
|
||||
# encoding: utf-8
|
||||
module FilesHelper
|
||||
include AttachmentsHelper
|
||||
|
||||
def downloadAll containers
|
||||
paths = []
|
||||
files = []
|
||||
tmpfile = "tmp.zip"
|
||||
|
||||
containers.each do |container|
|
||||
next if container.attachments.empty?
|
||||
if container.is_a?(Version);end
|
||||
container.attachments.each do |attachment|
|
||||
paths << attachment.diskfile
|
||||
file = attachment.diskfile
|
||||
# logger.error "[FilesHelper] downloadAll: #{e}"
|
||||
begin
|
||||
File.new(file, "r")
|
||||
rescue Exception => e
|
||||
logger.error e
|
||||
next
|
||||
end
|
||||
files << file
|
||||
# zip.add(file.path.dup.sub(directory, ''), file.path)
|
||||
end
|
||||
end
|
||||
|
||||
zipfile_name = "archive.zip"
|
||||
if File.exists? File.open(zipfile_name, "w+")
|
||||
ff = File.open(zipfile_name, "w+")
|
||||
ff.close
|
||||
File.delete ff
|
||||
end
|
||||
Zip::ZipFile.open(zipfile_name, Zip::ZipFile::CREATE) do |zipfile|
|
||||
files.each do |filename|
|
||||
directory = File.dirname filename
|
||||
# Two arguments:
|
||||
# - The name of the file as it will appear in the archive
|
||||
# - The original file, including the path to find it
|
||||
dir = filename.sub(directory+"/", '')
|
||||
zipfile.add(dir, filename)
|
||||
|
||||
end
|
||||
end
|
||||
File.new(zipfile_name,'w+')
|
||||
end
|
||||
|
||||
#带勾选框的课程列表
|
||||
def courses_check_box_tags(name,courses,current_course,attachment)
|
||||
s = ''
|
||||
courses.each do |course|
|
||||
if !course_contains_attachment?(course,attachment) && is_course_teacher(User.current,course) && course_in_current_or_next_term(course)
|
||||
s << "<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><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 has_project? user,file
|
||||
result = false
|
||||
user.projects.each do |project|
|
||||
if !project_contains_attachment?(project,file) && User.current.allowed_to?(:manage_files, project)
|
||||
return true
|
||||
end
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
# 判断指定的资源时候符合类型
|
||||
def isTypeOk(attachment, type, contentType)
|
||||
result = false
|
||||
if type != 0
|
||||
if attachment.attachtype == type
|
||||
result = true
|
||||
end
|
||||
else
|
||||
result = true
|
||||
end
|
||||
if result
|
||||
if contentType != '0' && contentType != attachment.suffix_type
|
||||
result = false
|
||||
end
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
def visable_attachemnts attachments
|
||||
result = []
|
||||
attachments.each do |attachment|
|
||||
if attachment.is_public? ||
|
||||
(attachment.container_type == "Project" && User.current.member_of?(attachment.project)) ||
|
||||
(attachment.container_type == "Course" && User.current.member_of_course?(Course.find(attachment.container_id)))||
|
||||
attachment.author_id == User.current.id
|
||||
result << attachment
|
||||
end
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
def get_attachments_by_tag attachments,tag
|
||||
attachments.each do |attachment|
|
||||
attachment.tag_list.include?(tag)
|
||||
end
|
||||
end
|
||||
|
||||
def visable_attachemnts_insite attachments,obj
|
||||
result = []
|
||||
if obj.is_a?(Course)
|
||||
attachments.each do |attachment|
|
||||
if attachment.is_public? || (attachment.container_type == "Course" && attachment.container_id == obj.id && User.current.member_of_course?(Course.find(attachment.container_id)))|| attachment.author_id == User.current.id
|
||||
result << attachment
|
||||
end
|
||||
end
|
||||
else if obj.is_a?(Project)
|
||||
attachments.each do |attachment|
|
||||
if attachment.is_public? || (attachment.container_type == "Project" && attachment.container_id == obj.id && User.current.member_of_course?(Project.find(attachment.container_id)))|| attachment.author_id == User.current.id
|
||||
result << attachment
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
|
||||
|
||||
end
|
|
@ -61,12 +61,38 @@ module IssuesHelper
|
|||
#h("#{issue.tracker} ##{issue.id}")
|
||||
# h("#{issue.tracker} #{issue.source_from}")
|
||||
s = ''
|
||||
s << link_to(@issue.project.name, project_issues_path(@issue.project))
|
||||
s << " > #"
|
||||
s << @issue.project_index
|
||||
s << link_to(@issue.project.name, project_issues_path(@issue.project), :class => "pro_page_top")
|
||||
s << " > "
|
||||
s << link_to("#" + @issue.project_index, project_issues_path(@issue.project), :class => "pro_page_top")
|
||||
s.html_safe
|
||||
end
|
||||
|
||||
#获取跟踪类型
|
||||
#REDO:时间紧需要优化,两个方法可以综合成一个
|
||||
def get_issue_type(value)
|
||||
if value == "缺陷" || value == 1
|
||||
class_type = "red_btn_cir ml10"
|
||||
elsif value == "功能" || value == 2
|
||||
class_type = "blue_btn_cir ml10"
|
||||
elsif value == "支持" || value == 3
|
||||
class_type = "green_btn_cir ml10"
|
||||
else
|
||||
class_type = "orange_btn_cir ml10"
|
||||
end
|
||||
end
|
||||
|
||||
def get_issue_typevalue(value)
|
||||
if value == "缺陷" || value == 1
|
||||
assign = "缺陷"
|
||||
elsif value == "功能" || value == 2
|
||||
assign = "功能"
|
||||
elsif value == "支持" || value == 3
|
||||
assign = "支持"
|
||||
else
|
||||
assign = "任务"
|
||||
end
|
||||
end
|
||||
|
||||
def render_issue_subject_with_tree(issue)
|
||||
s = ''
|
||||
ancestors = issue.root? ? [] : issue.ancestors.visible.all
|
||||
|
@ -314,17 +340,18 @@ module IssuesHelper
|
|||
if detail.property == 'attachment' && !value.blank? && atta = Attachment.find_by_id(detail.prop_key)
|
||||
# Link to the attachment if it has not been removed
|
||||
if options[:token].nil?
|
||||
value = link_to_attachment(atta, :download => true, :only_path => options[:only_path])
|
||||
value = atta.filename
|
||||
else
|
||||
value = link_to_attachment(atta, :download => true, :only_path => options[:only_path], :token => options[:token])
|
||||
end
|
||||
if options[:only_path] != false && atta.is_text?
|
||||
value += link_to(
|
||||
image_tag('magnifier.png'),
|
||||
:controller => 'attachments', :action => 'show',
|
||||
:id => atta, :filename => atta.filename
|
||||
)
|
||||
value = atta.filename
|
||||
end
|
||||
# 放大镜搜索功能
|
||||
# if options[:only_path] != false && atta.is_text?
|
||||
# value += link_to(
|
||||
# image_tag('magnifier.png'),
|
||||
# :controller => 'attachments', :action => 'show',
|
||||
# :id => atta, :filename => atta.filename
|
||||
# )
|
||||
# end
|
||||
else
|
||||
value = content_tag("i", h(value)) if value
|
||||
end
|
||||
|
|
|
@ -46,6 +46,26 @@ module JournalsHelper
|
|||
content.html_safe
|
||||
end
|
||||
|
||||
def render_links_easy(issue, journal, options={})
|
||||
content = ''
|
||||
editable = User.current.logged? && (User.current.allowed_to?(:edit_issue_notes, issue.project) || (journal.user == User.current && User.current.allowed_to?(:edit_own_issue_notes, issue.project)))
|
||||
destroyable = User.current.logged? && ((journal.user == User.current) || (issue.author_id == User.current.id) || (User.current.admin == 1))
|
||||
links = []
|
||||
if !journal.notes.blank?
|
||||
links << link_to(l(:button_quote),
|
||||
{:controller => 'journals', :action => 'new', :id => issue.id, :journal_id => journal},
|
||||
:remote => true,
|
||||
:method => 'post',
|
||||
:title => l(:button_quote)) if options[:reply_links]
|
||||
if destroyable
|
||||
links << link_to(l(:button_delete), { :controller => 'journals', :action => 'destroy', :id => journal, :format => 'js' },
|
||||
:title => l(:button_delete))
|
||||
end
|
||||
end
|
||||
content << content_tag('div', links.join(' ').html_safe, :class => 'contextual') unless links.empty?
|
||||
content.html_safe
|
||||
end
|
||||
|
||||
def render_notes (issue, journal, options={})
|
||||
content = ''
|
||||
editable = User.current.logged? && (User.current.allowed_to?(:edit_issue_notes, issue.project) || (journal.user == User.current && User.current.allowed_to?(:edit_own_issue_notes, issue.project)))
|
||||
|
@ -73,6 +93,35 @@ module JournalsHelper
|
|||
content_tag('div', content.html_safe, :id => "journal-#{journal.id}-notes", :class => css_classes ,:style => "width:580px")
|
||||
end
|
||||
|
||||
# 缺陷回复内容、引用内容
|
||||
# Redo:后面需要统一扩展
|
||||
def render_notes_issue (issue, journal, options={})
|
||||
content = ''
|
||||
editable = User.current.logged? && (User.current.allowed_to?(:edit_issue_notes, issue.project) || (journal.user == User.current && User.current.allowed_to?(:edit_own_issue_notes, issue.project)))
|
||||
destroyable = User.current.logged? && ((journal.user == User.current) || (issue.author_id == User.current.id) || (User.current.admin == 1))
|
||||
links = []
|
||||
if !journal.notes.blank?
|
||||
links << link_to(l(:button_quote),
|
||||
{:controller => 'journals', :action => 'new', :id => issue.id, :journal_id => journal},
|
||||
:remote => true,
|
||||
:method => 'post',
|
||||
:title => l(:button_quote)) if options[:reply_links]
|
||||
links << link_to_in_place_notes_editor(l(:button_edit), "journal-#{journal.id}-notes",
|
||||
{ :controller => 'journals', :action => 'edit', :id => journal, :format => 'js' },
|
||||
:title => l(:button_edit)) if editable
|
||||
#Added by young
|
||||
if destroyable
|
||||
links << link_to(l(:button_delete), { :controller => 'journals', :action => 'destroy', :id => journal, :format => 'js' },
|
||||
:title => l(:button_delete))
|
||||
end
|
||||
end
|
||||
#content << content_tag('div', links.join(' ').html_safe, :class => 'contextual', :style => 'margin-top:-25px;') unless links.empty?
|
||||
content << textilizable(journal, :notes)
|
||||
css_classes = "wiki"
|
||||
css_classes << " editable" if editable
|
||||
content_tag('div', content.html_safe, :id => "journal-#{journal.id}-notes", :class => css_classes ,:style => "width:510px")
|
||||
end
|
||||
|
||||
def link_to_in_place_notes_editor(text, field_id, url, options={})
|
||||
onclick = "$.ajax({url: '#{url_for(url)}', type: 'get'}); return false;"
|
||||
link_to text, '#', options.merge(:onclick => onclick)
|
||||
|
|
|
@ -1,96 +1,110 @@
|
|||
# encoding: utf-8
|
||||
#
|
||||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
module MembersHelper
|
||||
def render_principals_for_new_members(project)
|
||||
scope = Principal.active.sorted.not_member_of(project).like(params[:q])
|
||||
principal_count = scope.count
|
||||
principal_pages = Redmine::Pagination::Paginator.new principal_count, 10, params['page'] #by young
|
||||
principals = scope.offset(principal_pages.offset).limit(principal_pages.per_page).all
|
||||
s = content_tag('div', principals_check_box_tags_ex('membership[user_ids][]', principals), :id => 'principals')
|
||||
links = pagination_links_full(principal_pages, principal_count, :per_page_links => false) {|text, parameters, options|
|
||||
link_to text, autocomplete_project_memberships_path(project, parameters.merge(:q => params[:q], :format => 'js')), :remote => true
|
||||
}
|
||||
s + content_tag('div', content_tag('ul', links), :class => 'pagination_new')
|
||||
end
|
||||
|
||||
#获取项目可邀请的成员列表
|
||||
def render_project_members project
|
||||
scope = Principal.active.sorted.not_member_of(project).like(params[:q])
|
||||
principals = paginateHelper scope,10
|
||||
s = content_tag('ul', project_member_check_box_tags_ex('membership[user_ids][]', principals), :class => 'mb5', :style => "margin-left: -40px;")
|
||||
links = pagination_links_full(@obj_pages, @obj_count, :per_page_links => false, :remote => false, :flag => true){|text, parameters, options|
|
||||
link_to text, autocomplete_project_memberships_path(project, parameters.merge(:q => params[:q],:flag => true, :format => 'js')), :remote => true
|
||||
}
|
||||
s + content_tag('ul', links,:class => 'wlist')
|
||||
end
|
||||
|
||||
# add by nwb
|
||||
# 课程可添加的成员列表
|
||||
def render_principals_for_new_course_members(course)
|
||||
if params[:q] && params[:q] != ""
|
||||
scope = Principal.active.sorted.not_member_of_course(course).like(params[:q])
|
||||
else
|
||||
scope = []
|
||||
end
|
||||
principals = paginateHelper scope,10
|
||||
s = content_tag('ul', project_member_check_box_tags_ex('membership[user_ids][]', principals), :class => 'mb5', :id => 'principals')
|
||||
|
||||
links = pagination_links_full(@obj_pages, @obj_count, :per_page_links => false, :remote => false, :flag => true) {|text, parameters, options|
|
||||
link_to text, autocomplete_course_memberships_path(course, parameters.merge(:q => params[:q], :format => 'js')), :remote => true
|
||||
}
|
||||
|
||||
s + content_tag('ul', links,:class => 'wlist',:id => "course_member_pagination_links")
|
||||
end
|
||||
|
||||
|
||||
# 当前申请加入的成员名单
|
||||
def render_principals_for_applied_members(project)
|
||||
scope = project.applied_projects.map(&:user)
|
||||
principal_count = scope.count
|
||||
principal_pages = Redmine::Pagination::Paginator.new principal_count, 10, params['page']
|
||||
offset ||= principal_pages.offset
|
||||
principals = scope[offset, 10]
|
||||
#principals = scope.offset(principal_pages.offset).limit(principal_pages.per_page).all
|
||||
#principals = ApplicationController.new.paginateHelper scope,10
|
||||
|
||||
s = content_tag('div', principals_check_box_tags_ex('membership[user_ids][]', principals), :id => 'principals')
|
||||
|
||||
links = pagination_links_full(principal_pages, principal_count, :per_page_links => false) {|text, parameters, options|
|
||||
link_to text, appliedproject_project_memberships_path(project, parameters.merge(:q => params[:q], :format => 'js')), :remote => true
|
||||
}
|
||||
|
||||
s + content_tag('div', content_tag('ul', links), :class => 'applied_new')
|
||||
end
|
||||
|
||||
private
|
||||
def paginateHelper obj, pre_size=20
|
||||
@obj_count = obj.count
|
||||
@obj_pages = Redmine::Pagination::Paginator.new @obj_count, pre_size, params['page']
|
||||
if obj.kind_of? ActiveRecord::Base or obj.kind_of? ActiveRecord::Relation
|
||||
obj.limit(@obj_pages.per_page).offset(@obj_pages.offset)
|
||||
elsif obj.kind_of? Array
|
||||
obj[@obj_pages.offset, @obj_pages.per_page]
|
||||
else
|
||||
logger.error "[ApplicationController] Error : application_controller#paginateHelper ===> unknow category: #{obj.class}"
|
||||
raise RuntimeError, 'unknow type, Please input you type into this helper.'
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
# encoding: utf-8
|
||||
#
|
||||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
module MembersHelper
|
||||
def render_principals_for_new_members(project)
|
||||
scope = Principal.active.sorted.not_member_of(project).like(params[:q])
|
||||
principal_count = scope.count
|
||||
principal_pages = Redmine::Pagination::Paginator.new principal_count, 10, params['page'] #by young
|
||||
principals = scope.offset(principal_pages.offset).limit(principal_pages.per_page).all
|
||||
s = content_tag('div', principals_check_box_tags_ex('membership[user_ids][]', principals), :id => 'principals')
|
||||
links = pagination_links_full(principal_pages, principal_count, :per_page_links => false) {|text, parameters, options|
|
||||
link_to text, autocomplete_project_memberships_path(project, parameters.merge(:q => params[:q], :format => 'js')), :remote => true
|
||||
}
|
||||
s + content_tag('div', content_tag('ul', links), :class => 'pagination_new')
|
||||
end
|
||||
|
||||
#获取项目可邀请的成员列表
|
||||
def render_project_members project
|
||||
if params[:q] && params[:q].lstrip.rstrip != ""
|
||||
scope = Principal.active.sorted.not_member_of(project).like(params[:q])
|
||||
else
|
||||
scope = []
|
||||
end
|
||||
principals = paginateHelper scope,10
|
||||
s = content_tag('ul', project_member_check_box_tags_ex('membership[user_ids][]', principals), :class => 'mb5')
|
||||
links = pagination_links_full(@obj_pages, @obj_count, :per_page_links => false, :remote => false, :flag => true){|text, parameters, options|
|
||||
link_to text, autocomplete_project_memberships_path(project, parameters.merge(:q => params[:q],:flag => true, :format => 'js')), :remote => true
|
||||
}
|
||||
s + content_tag('ul', links,:class => 'wlist', :id => "course_member_pagination_links" )
|
||||
end
|
||||
|
||||
# add by nwb
|
||||
# 课程可添加的成员列表
|
||||
def render_principals_for_new_course_members(course)
|
||||
if params[:q] && params[:q].lstrip.rstrip != ""
|
||||
scope = Principal.active.sorted.not_member_of_course(course).like(params[:q])
|
||||
else
|
||||
scope = []
|
||||
end
|
||||
principals = paginateHelper scope,10
|
||||
s = content_tag('ul', project_member_check_box_tags_ex('membership[user_ids][]', principals), :class => 'mb5', :id => 'principals')
|
||||
|
||||
links = pagination_links_full(@obj_pages, @obj_count, :per_page_links => false, :remote => false, :flag => true) {|text, parameters, options|
|
||||
link_to text, autocomplete_course_memberships_path(course, parameters.merge(:q => params[:q], :format => 'js')), :remote => true
|
||||
}
|
||||
|
||||
s + content_tag('ul', links,:class => 'wlist',:id => "course_member_pagination_links")
|
||||
end
|
||||
|
||||
# 新申请加入项目成员列表
|
||||
def render_principals_for_applied_members_new project
|
||||
scope = project.applied_projects.map(&:user)
|
||||
principals = paginateHelper scope,10
|
||||
s = content_tag('ul', principals_check_box_tags_li('membership[user_ids][]', principals), :class => 'mb5')
|
||||
links = pagination_links_full(@obj_pages, @obj_count, :per_page_links => false, :remote => false, :flag => true){|text, parameters, options|
|
||||
link_to text, appliedproject_project_memberships_path(project, parameters.merge(:q => params[:q],:flag => true, :format => 'js')), :remote => true
|
||||
}
|
||||
s + content_tag('ul', links,:class => 'wlist', :id => "course_member_pagination_links" )
|
||||
end
|
||||
|
||||
# 当前申请加入的成员名单
|
||||
def render_principals_for_applied_members(project)
|
||||
scope = project.applied_projects.map(&:user)
|
||||
principal_count = scope.count
|
||||
principal_pages = Redmine::Pagination::Paginator.new principal_count, 10, params['page']
|
||||
offset ||= principal_pages.offset
|
||||
principals = scope[offset, 10]
|
||||
#principals = scope.offset(principal_pages.offset).limit(principal_pages.per_page).all
|
||||
#principals = ApplicationController.new.paginateHelper scope,10
|
||||
|
||||
s = content_tag('div', principals_check_box_tags_ex('membership[user_ids][]', principals), :id => 'principals')
|
||||
|
||||
links = pagination_links_full(principal_pages, principal_count, :per_page_links => false) {|text, parameters, options|
|
||||
link_to text, appliedproject_project_memberships_path(project, parameters.merge(:q => params[:q], :format => 'js')), :remote => true
|
||||
}
|
||||
|
||||
s + content_tag('div', content_tag('ul', links), :class => 'applied_new')
|
||||
end
|
||||
|
||||
private
|
||||
def paginateHelper obj, pre_size=20
|
||||
@obj_count = obj.count
|
||||
@obj_pages = Redmine::Pagination::Paginator.new @obj_count, pre_size, params['page']
|
||||
if obj.kind_of? ActiveRecord::Base or obj.kind_of? ActiveRecord::Relation
|
||||
obj.limit(@obj_pages.per_page).offset(@obj_pages.offset)
|
||||
elsif obj.kind_of? Array
|
||||
obj[@obj_pages.offset, @obj_pages.per_page]
|
||||
else
|
||||
logger.error "[ApplicationController] Error : application_controller#paginateHelper ===> unknow category: #{obj.class}"
|
||||
raise RuntimeError, 'unknow type, Please input you type into this helper.'
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
module OwnerTypeHelper
|
||||
MEMO = 1
|
||||
FORUM = 2
|
||||
MESSAGE = 3
|
||||
NEWS = 4
|
||||
COMMENT = 5
|
||||
BID = 6
|
||||
JOURNALSFORMESSAGE = 7
|
||||
module OwnerTypeHelper
|
||||
MEMO = 1
|
||||
FORUM = 2
|
||||
MESSAGE = 3
|
||||
NEWS = 4
|
||||
COMMENT = 5
|
||||
BID = 6
|
||||
JOURNALSFORMESSAGE = 7
|
||||
end
|
|
@ -21,7 +21,12 @@ include AvatarHelper
|
|||
module ProjectsHelper
|
||||
def link_to_version(version, options = {})
|
||||
return '' unless version && version.is_a?(Version)
|
||||
link_to_if version.visible?, format_version_name(version), { :controller => 'versions', :action => 'show', :id => version }, options
|
||||
link_to_if version.visible?, format_version_name(version), { :controller => 'versions', :action => 'show', :id => version }, :class => "c_blue02"
|
||||
end
|
||||
|
||||
def link_to_version_show(version, options = {})
|
||||
return '' unless version && version.is_a?(Version)
|
||||
link_to_if version.visible?, format_version_name(version), { :controller => 'versions', :action => 'show', :id => version }, :class => " f16 fb c_dblue "
|
||||
end
|
||||
|
||||
def project_settings_tabs
|
||||
|
@ -29,7 +34,7 @@ module ProjectsHelper
|
|||
{:name => 'modules', :action => :select_project_modules, :partial => 'projects/settings/modules', :label => :label_module_plural},
|
||||
{:name => 'members', :action => :manage_members, :partial => 'projects/settings/members', :label => :label_member_plural},
|
||||
{:name => 'versions', :action => :manage_versions, :partial => 'projects/settings/versions', :label => :label_version_plural},
|
||||
{:name => 'categories', :action => :manage_categories, :partial => 'projects/settings/issue_categories', :label => :label_issue_category_plural},
|
||||
# {:name => 'categories', :action => :manage_categories, :partial => 'projects/settings/issue_categories', :label => :label_issue_category_plural},
|
||||
# {:name => 'wiki', :action => :manage_wiki, :partial => 'projects/settings/wiki', :label => :label_wiki},
|
||||
{:name => 'repositories', :action => :manage_repository, :partial => 'projects/settings/repositories', :label => :label_repository_plural},
|
||||
#{:name => 'boards', :action => :manage_boards, :partial => 'projects/settings/boards', :label => :label_board_plural},
|
||||
|
@ -386,4 +391,20 @@ module ProjectsHelper
|
|||
end
|
||||
type
|
||||
end
|
||||
|
||||
#显示项目配置菜单
|
||||
def show_project_memu user
|
||||
if user.allowed_to?(:edit_project, @project)
|
||||
result = "edit_project"
|
||||
elsif user.allowed_to?(:select_project_modules, @project)
|
||||
result = "select_project_modules"
|
||||
elsif user.allowed_to?(:manage_members, @project)
|
||||
result = "manage_members"
|
||||
elsif user.allowed_to?(:manage_versions, @project)
|
||||
result = "manage_versions"
|
||||
elsif user.allowed_to?(:manage_repository, @project)
|
||||
result = "manage_repository"
|
||||
end
|
||||
result
|
||||
end
|
||||
end
|
||||
|
|
|
@ -255,8 +255,19 @@ module QueriesHelper
|
|||
# Give it a name, required to be valid
|
||||
@query = IssueQuery.new(:name => "_")
|
||||
@query.project = @project
|
||||
params[:f] = %w(subject status_id priority_id author_id assigned_to_id) unless params[:status_id].nil?
|
||||
params[:op] = {'subject' => "~" ,
|
||||
'status_id' => ( params[:status_id] == '0' ? "!":"=" ),
|
||||
'priority_id' => ( params[:priority_id] == '0' ? "!":"=" ),
|
||||
'author_id' => ( params[:author_id] == '0' ? "!":"=" ),
|
||||
'assigned_to_id' => ( params[:assigned_to_id] == '0' ? "!":"=" )} unless params[:status_id].nil?
|
||||
params[:v] = {'subject' => [params[:subject]],
|
||||
'status_id' => [params[:status_id]],
|
||||
'priority_id' => [params[:priority_id]],
|
||||
'author_id' => [params[:author_id]],
|
||||
'assigned_to_id' => [params[:assigned_to_id]]} unless params[:status_id].nil?
|
||||
@query.build_from_params(params)
|
||||
session[:query] = {:project_id => @query.project_id, :filters => @query.filters, :group_by => @query.group_by, :column_names => @query.column_names}
|
||||
#session[:query] = {:project_id => @query.project_id, :filters => @query.filters, :group_by => @query.group_by, :column_names => @query.column_names}
|
||||
else
|
||||
# retrieve from session
|
||||
@query = IssueQuery.find_by_id(session[:query][:id]) if session[:query][:id]
|
||||
|
|
|
@ -18,7 +18,11 @@
|
|||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
module RepositoriesHelper
|
||||
ROOT_PATH="/home/pdl/redmine-2.3.2-0/apache2/"
|
||||
if Rails.env.development?
|
||||
ROOT_PATH="/tmp/" if Rails.env.development?
|
||||
else
|
||||
ROOT_PATH="/home/pdl/redmine-2.3.2-0/apache2/"
|
||||
end
|
||||
PROJECT_PATH_CUT = 40
|
||||
REPO_IP_ADDRESS = Setting.repository_domain
|
||||
|
||||
|
|
|
@ -42,7 +42,28 @@ module WatchersHelper
|
|||
:object_id => (objects.size == 1 ? objects.first.id : objects.map(&:id).sort)
|
||||
)
|
||||
method = watched ? 'delete' : 'post'
|
||||
|
||||
|
||||
link_to text, url, :remote => true, :method => method, :class => css
|
||||
end
|
||||
|
||||
def watcher_link_issue(objects, user, options=[])
|
||||
return '' unless user && user.logged?
|
||||
objects = Array.wrap(objects)
|
||||
|
||||
watched = objects.any? {|object| object.watched_by?(user)}
|
||||
@watch_flag = (objects.first.instance_of?(User) or objects.first.instance_of?(Project) or objects.first.instance_of?(Contest) or (objects.first.instance_of?(Bid)))
|
||||
css = @watch_flag ? ([watcher_css(objects), watched ? 'talk_edit ' : 'talk_edit '].join(' ') << options[0].to_s) :
|
||||
([watcher_css(objects), watched ? 'talk_edit fr ' : 'talk_edit fr '].join(' ') << options[0].to_s)
|
||||
|
||||
text = @watch_flag ?
|
||||
(watched ? l(:button_unfollow) : l(:button_follow)) : (watched ? l(:button_unwatch) : l(:button_watch))
|
||||
|
||||
url = watch_path(
|
||||
:object_type => objects.first.class.to_s.underscore,
|
||||
:object_id => (objects.size == 1 ? objects.first.id : objects.map(&:id).sort)
|
||||
)
|
||||
method = watched ? 'delete' : 'post'
|
||||
|
||||
link_to text, url, :remote => true, :method => method, :class => css
|
||||
end
|
||||
|
||||
|
@ -261,17 +282,36 @@ module WatchersHelper
|
|||
content.present? ? content_tag('ul', content, :class => 'watchers') : content
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# 缺陷跟踪者列表复选框生成
|
||||
def watchers_checkboxes(object, users, checked=nil)
|
||||
if users.nil?
|
||||
|
||||
else
|
||||
# tag = check_box_tag 'issue[watcher_user_ids][]', user.id, c, :id => nil
|
||||
# content_tag 'label', "#{tag} #{h(user)}".html_safe,
|
||||
# :id => "issue_watcher_user_ids_#{user.id}",
|
||||
# :class => "floating"
|
||||
users.map do |user|
|
||||
c = checked.nil? ? object.watched_by?(user) : checked
|
||||
tag = check_box_tag 'issue[watcher_user_ids][]', user.id, c, :id => nil
|
||||
content_tag 'label', "#{tag} #{h(user)}".html_safe,
|
||||
:id => "issue_watcher_user_ids_#{user.id}",
|
||||
:class => "floating"
|
||||
s = content_tag(:ul,
|
||||
content_tag(:li, "#{check_box_tag 'issue[watcher_user_ids][]', user.id, c, :id => nil } #{h link_to user.userInfo, user_path( user.id)}".html_safe,
|
||||
:id=>"issue_watcher_user_ids_#{user.id}",:style=>"float: left;width: 175px;margin: 0px 20px 10px 0px; overflow: hidden; line-height:1.6em;" ),
|
||||
:class => "mb10 ml80")
|
||||
end.join.html_safe
|
||||
|
||||
# scope = users.sort
|
||||
# watchers = paginateHelper scope,10
|
||||
# s = content_tag('ul', issue_watcher_check_box_tags_ex('issue[watcher_user_ids][]', watchers), :class => 'mb10 ml80')
|
||||
# links = pagination_links_full(@obj_pages, @obj_count, :per_page_links => false, :remote => false, :flag => true){|text, parameters, options|
|
||||
# link_to text, watchers_autocomplete_for_user_path(@users, parameters.merge(:q => params[:q],:format => 'js',:flag => 'ture')), :remote => true
|
||||
# }
|
||||
# s + content_tag('ul', links,:class => 'wlist', :style =>"float:left;margin-top:0px;")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -304,8 +344,8 @@ module WatchersHelper
|
|||
def exit_project_link(project)
|
||||
link_to(l(:label_exit_project),exit_cur_project_path(project.id),
|
||||
:remote => true, :confirm => l(:lable_sure_exit_project),
|
||||
:style => "color: #fff; display:block;font-size:12px; padding: 0px 5px; margin-right: 10px; height: 20px; line-height: 22px; background: none repeat scroll 0% 0% #64BDD9; TES;padding-top:1px;" )
|
||||
end
|
||||
:class => "pr_join_a_quit" )
|
||||
end
|
||||
|
||||
#项目关注、取消关注
|
||||
#REDO:项目样式确定后方法需要对CSS变量进行改进
|
||||
|
@ -321,7 +361,7 @@ module WatchersHelper
|
|||
:object_id => (objects.size == 1 ? objects.first.id : objects.map(&:id).sort))
|
||||
method = watched ? 'delete' : 'post'
|
||||
link_to text, url, :remote => true, :method => method,
|
||||
:class => "project_watch_new" ,:id=>id
|
||||
:class => "pr_join_a" ,:id=>id
|
||||
end
|
||||
|
||||
#申请加入项目
|
||||
|
@ -339,7 +379,21 @@ module WatchersHelper
|
|||
:user_id => user.id,
|
||||
:project_id => project.id)
|
||||
method = applied ? 'delete' : 'post'
|
||||
link_to text, url, :remote => true, :method => method , :class => "project_watch_new",:id => id
|
||||
link_to text, url, :remote => true, :method => method , :class => "pr_join_a",:id => id
|
||||
end
|
||||
|
||||
def paginateHelper obj, pre_size=20
|
||||
@obj_count = obj.count
|
||||
@obj_pages = Redmine::Pagination::Paginator.new @obj_count, pre_size, params['page']
|
||||
if obj.kind_of? ActiveRecord::Base or obj.kind_of? ActiveRecord::Relation
|
||||
obj.limit(@obj_pages.per_page).offset(@obj_pages.offset)
|
||||
elsif obj.kind_of? Array
|
||||
obj[@obj_pages.offset, @obj_pages.per_page]
|
||||
else
|
||||
logger.error "[ApplicationController] Error : application_controller#paginateHelper ===> unknow category: #{obj.class}"
|
||||
raise RuntimeError, 'unknow type, Please input you type into this helper.'
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
|
|
@ -1,95 +1,95 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
class Document < ActiveRecord::Base
|
||||
include Redmine::SafeAttributes
|
||||
belongs_to :project
|
||||
belongs_to :user
|
||||
belongs_to :category, :class_name => "DocumentCategory", :foreign_key => "category_id"
|
||||
include UserScoreHelper
|
||||
after_save :be_user_score # user_score
|
||||
after_destroy :down_user_score
|
||||
acts_as_attachable :delete_permission => :delete_documents
|
||||
after_create :send_mail
|
||||
# 被ForgeActivity虚拟关联
|
||||
has_many :forge_acts, :class_name => 'ForgeActivity',:as =>:forge_act ,:dependent => :destroy
|
||||
# end
|
||||
acts_as_searchable :columns => ['title', "#{table_name}.description"], :include => :project
|
||||
acts_as_event :title => Proc.new {|o| "#{l(:label_document)}: #{o.title}"},
|
||||
#:author => Proc.new {|o| o.attachments.reorder("#{Attachment.table_name}.created_on ASC").first.try(:author) },
|
||||
:author => Proc.new {|o| User.find(o.user_id)},
|
||||
:url => Proc.new {|o| {:controller => 'documents', :action => 'show', :id => o.id}}
|
||||
acts_as_activity_provider :find_options => {:include => :project},
|
||||
:is_public => 'documents.is_public'
|
||||
|
||||
validates_presence_of :project, :title, :category
|
||||
validates_length_of :title, :maximum => 60
|
||||
after_create :act_as_forge_activity
|
||||
scope :visible, lambda {|*args|
|
||||
includes(:project).where(Project.allowed_to_condition(args.shift || User.current, :view_documents, *args))
|
||||
}
|
||||
|
||||
safe_attributes 'category_id', 'title', 'description','is_public'
|
||||
|
||||
def visible?(user=User.current)
|
||||
!user.nil? && user.allowed_to?(:view_documents, project)
|
||||
end
|
||||
|
||||
def has_right?(project,user=User.current)
|
||||
user.admin? || user.member_of?(project) || self.is_public==1
|
||||
end
|
||||
|
||||
def initialize(attributes=nil, *args)
|
||||
super
|
||||
if new_record?
|
||||
self.category ||= DocumentCategory.default
|
||||
end
|
||||
end
|
||||
|
||||
def updated_on
|
||||
unless @updated_on
|
||||
a = attachments.last
|
||||
@updated_on = (a && a.created_on) || created_on
|
||||
end
|
||||
@updated_on
|
||||
end
|
||||
|
||||
# update user score
|
||||
def be_user_score
|
||||
UserScore.project(:push_document, self.user,self,{ document_id: self.id })
|
||||
update_document(self.user,1)
|
||||
update_document(self.user,2,self.project)
|
||||
end
|
||||
|
||||
def down_user_score
|
||||
update_document(self.user,1)
|
||||
update_document(self.user,2,self.project)
|
||||
end
|
||||
|
||||
# Time 2015-03-02 10:51:16
|
||||
# Author lizanle
|
||||
# Description 新创建的document要在公共表ForgeActivity中记录
|
||||
def act_as_forge_activity
|
||||
self.forge_acts << ForgeActivity.new(:user_id => self.user_id,
|
||||
:project_id => self.project_id)
|
||||
end
|
||||
|
||||
def send_mail
|
||||
Mailer.run.document_added(self) if Setting.notified_events.include?('document_added')
|
||||
end
|
||||
|
||||
end
|
||||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
class Document < ActiveRecord::Base
|
||||
include Redmine::SafeAttributes
|
||||
belongs_to :project
|
||||
belongs_to :user
|
||||
belongs_to :category, :class_name => "DocumentCategory", :foreign_key => "category_id"
|
||||
include UserScoreHelper
|
||||
after_save :be_user_score # user_score
|
||||
after_destroy :down_user_score
|
||||
acts_as_attachable :delete_permission => :delete_documents
|
||||
after_create :send_mail
|
||||
# 被ForgeActivity虚拟关联
|
||||
has_many :forge_acts, :class_name => 'ForgeActivity',:as =>:forge_act ,:dependent => :destroy
|
||||
# end
|
||||
acts_as_searchable :columns => ['title', "#{table_name}.description"], :include => :project
|
||||
acts_as_event :title => Proc.new {|o| "#{l(:label_document)}: #{o.title}"},
|
||||
#:author => Proc.new {|o| o.attachments.reorder("#{Attachment.table_name}.created_on ASC").first.try(:author) },
|
||||
:author => Proc.new {|o| User.find(o.user_id)},
|
||||
:url => Proc.new {|o| {:controller => 'documents', :action => 'show', :id => o.id}}
|
||||
acts_as_activity_provider :find_options => {:include => :project},
|
||||
:is_public => 'documents.is_public'
|
||||
|
||||
validates_presence_of :project, :title, :category
|
||||
validates_length_of :title, :maximum => 60
|
||||
after_create :act_as_forge_activity
|
||||
scope :visible, lambda {|*args|
|
||||
includes(:project).where(Project.allowed_to_condition(args.shift || User.current, :view_documents, *args))
|
||||
}
|
||||
|
||||
safe_attributes 'category_id', 'title', 'description','is_public'
|
||||
|
||||
def visible?(user=User.current)
|
||||
!user.nil? && user.allowed_to?(:view_documents, project)
|
||||
end
|
||||
|
||||
def has_right?(project,user=User.current)
|
||||
user.admin? || user.member_of?(project) || self.is_public==1
|
||||
end
|
||||
|
||||
def initialize(attributes=nil, *args)
|
||||
super
|
||||
if new_record?
|
||||
self.category ||= DocumentCategory.default
|
||||
end
|
||||
end
|
||||
|
||||
def updated_on
|
||||
unless @updated_on
|
||||
a = attachments.last
|
||||
@updated_on = (a && a.created_on) || created_on
|
||||
end
|
||||
@updated_on
|
||||
end
|
||||
|
||||
# update user score
|
||||
def be_user_score
|
||||
UserScore.project(:push_document, self.user,self,{ document_id: self.id })
|
||||
update_document(self.user,1)
|
||||
update_document(self.user,2,self.project)
|
||||
end
|
||||
|
||||
def down_user_score
|
||||
update_document(self.user,1)
|
||||
update_document(self.user,2,self.project)
|
||||
end
|
||||
|
||||
# Time 2015-03-02 10:51:16
|
||||
# Author lizanle
|
||||
# Description 新创建的document要在公共表ForgeActivity中记录
|
||||
def act_as_forge_activity
|
||||
self.forge_acts << ForgeActivity.new(:user_id => self.user_id,
|
||||
:project_id => self.project_id)
|
||||
end
|
||||
|
||||
def send_mail
|
||||
Mailer.run.document_added(self) if Setting.notified_events.include?('document_added')
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -1,58 +1,58 @@
|
|||
class Forum < ActiveRecord::Base
|
||||
include Redmine::SafeAttributes
|
||||
include ApplicationHelper
|
||||
has_many_kindeditor_assets :assets, :dependent => :destroy
|
||||
has_many :topics, :class_name => 'Memo', :conditions => "#{Memo.table_name}.parent_id IS NULL", :order => "#{Memo.table_name}.created_at DESC", :dependent => :destroy
|
||||
has_many :memos, :dependent => :destroy, conditions: "parent_id IS NULL"
|
||||
belongs_to :creator, :class_name => "User", :foreign_key => 'creator_id'
|
||||
safe_attributes 'name',
|
||||
'description',
|
||||
'topic_count',
|
||||
'memo_count',
|
||||
'last_memo_id',
|
||||
'creator_id',
|
||||
'sticky',
|
||||
'locked'
|
||||
validates_presence_of :name, :creator_id, :description
|
||||
validates_length_of :name, maximum: 50
|
||||
#validates_length_of :description, maximum: 255
|
||||
validates :name, :uniqueness => true
|
||||
after_destroy :delete_kindeditor_assets
|
||||
acts_as_taggable
|
||||
scope :by_join_date, order("created_at DESC")
|
||||
after_create :send_mail
|
||||
def reset_counters!
|
||||
self.class.reset_counters!(id)
|
||||
end
|
||||
|
||||
def editable_by? user
|
||||
# user && user.logged? || (self.author == usr && usr.allowed_to?(:edit_own_messages, project))
|
||||
self.creator == user || user.admin?
|
||||
end
|
||||
|
||||
def destroyable_by? user
|
||||
# user && user.logged? && Forum.find(self.forum_id).creator_id == user.id || user.admin?
|
||||
self.creator == user || user.admin?
|
||||
end
|
||||
|
||||
def send_mail
|
||||
logger.debug "send mail for forum add."
|
||||
Mailer.run.forum_add(self) if Setting.notified_events.include?('forum_add')
|
||||
end
|
||||
# Updates topic_count, memo_count and last_memo_id attributes for +board_id+
|
||||
def self.reset_counters!(forum_id)
|
||||
forum_id = forum_id.to_i
|
||||
update_all("topic_count = (SELECT COUNT(*) FROM #{Memo.table_name} WHERE forum_id=#{forum_id} AND parent_id IS NULL)," +
|
||||
" memo_count = (SELECT COUNT(*) FROM #{Memo.table_name} WHERE forum_id=#{forum_id} AND parent_id IS NOT NULL)," +
|
||||
" last_memo_id = (SELECT MAX(id) FROM #{Memo.table_name} WHERE forum_id=#{forum_id})",
|
||||
["id = ?", forum_id])
|
||||
end
|
||||
|
||||
# Time 2015-03-26 15:50:54
|
||||
# Author lizanle
|
||||
# Description 删除论坛后删除对应的资源
|
||||
def delete_kindeditor_assets
|
||||
delete_kindeditor_assets_from_disk self.id,OwnerTypeHelper::FORUM
|
||||
end
|
||||
|
||||
end
|
||||
class Forum < ActiveRecord::Base
|
||||
include Redmine::SafeAttributes
|
||||
include ApplicationHelper
|
||||
has_many_kindeditor_assets :assets, :dependent => :destroy
|
||||
has_many :topics, :class_name => 'Memo', :conditions => "#{Memo.table_name}.parent_id IS NULL", :order => "#{Memo.table_name}.created_at DESC", :dependent => :destroy
|
||||
has_many :memos, :dependent => :destroy, conditions: "parent_id IS NULL"
|
||||
belongs_to :creator, :class_name => "User", :foreign_key => 'creator_id'
|
||||
safe_attributes 'name',
|
||||
'description',
|
||||
'topic_count',
|
||||
'memo_count',
|
||||
'last_memo_id',
|
||||
'creator_id',
|
||||
'sticky',
|
||||
'locked'
|
||||
validates_presence_of :name, :creator_id, :description
|
||||
validates_length_of :name, maximum: 50
|
||||
#validates_length_of :description, maximum: 255
|
||||
validates :name, :uniqueness => true
|
||||
after_destroy :delete_kindeditor_assets
|
||||
acts_as_taggable
|
||||
scope :by_join_date, order("created_at DESC")
|
||||
after_create :send_mail
|
||||
def reset_counters!
|
||||
self.class.reset_counters!(id)
|
||||
end
|
||||
|
||||
def editable_by? user
|
||||
# user && user.logged? || (self.author == usr && usr.allowed_to?(:edit_own_messages, project))
|
||||
self.creator == user || user.admin?
|
||||
end
|
||||
|
||||
def destroyable_by? user
|
||||
# user && user.logged? && Forum.find(self.forum_id).creator_id == user.id || user.admin?
|
||||
self.creator == user || user.admin?
|
||||
end
|
||||
|
||||
def send_mail
|
||||
logger.debug "send mail for forum add."
|
||||
Mailer.run.forum_add(self) if Setting.notified_events.include?('forum_add')
|
||||
end
|
||||
# Updates topic_count, memo_count and last_memo_id attributes for +board_id+
|
||||
def self.reset_counters!(forum_id)
|
||||
forum_id = forum_id.to_i
|
||||
update_all("topic_count = (SELECT COUNT(*) FROM #{Memo.table_name} WHERE forum_id=#{forum_id} AND parent_id IS NULL)," +
|
||||
" memo_count = (SELECT COUNT(*) FROM #{Memo.table_name} WHERE forum_id=#{forum_id} AND parent_id IS NOT NULL)," +
|
||||
" last_memo_id = (SELECT MAX(id) FROM #{Memo.table_name} WHERE forum_id=#{forum_id})",
|
||||
["id = ?", forum_id])
|
||||
end
|
||||
|
||||
# Time 2015-03-26 15:50:54
|
||||
# Author lizanle
|
||||
# Description 删除论坛后删除对应的资源
|
||||
def delete_kindeditor_assets
|
||||
delete_kindeditor_assets_from_disk self.id,OwnerTypeHelper::FORUM
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
class IssueObserver < ActiveRecord::Observer
|
||||
|
||||
def after_create(issue)
|
||||
# 将跟踪者与本项目的其他成员都设为收件方,并去重,不在进行抄送,
|
||||
recipients = issue.recipients - issue.watcher_recipients + issue.watcher_recipients
|
||||
recipients.each do |rec|
|
||||
Mailer.run.issue_add(issue,rec) if Setting.notified_events.include?('issue_added')
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
class IssueObserver < ActiveRecord::Observer
|
||||
|
||||
def after_create(issue)
|
||||
# 将跟踪者与本项目的其他成员都设为收件方,并去重,不在进行抄送,
|
||||
recipients = issue.recipients - issue.watcher_recipients + issue.watcher_recipients
|
||||
recipients.each do |rec|
|
||||
Mailer.run.issue_add(issue,rec) if Setting.notified_events.include?('issue_added')
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -310,7 +310,7 @@ class IssueQuery < Query
|
|||
:order => options[:order],
|
||||
:limit => options[:limit],
|
||||
:offset => options[:offset]
|
||||
)
|
||||
).reverse
|
||||
rescue ::ActiveRecord::StatementInvalid => e
|
||||
raise StatementInvalid.new(e.message)
|
||||
end
|
||||
|
|
|
@ -1,34 +1,34 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
class JournalObserver < ActiveRecord::Observer
|
||||
def after_create(journal)
|
||||
if journal.notify? &&
|
||||
(Setting.notified_events.include?('issue_updated') ||
|
||||
(Setting.notified_events.include?('issue_note_added') && journal.notes.present?) ||
|
||||
(Setting.notified_events.include?('issue_status_updated') && journal.new_status.present?) ||
|
||||
(Setting.notified_events.include?('issue_priority_updated') && journal.new_value_for('priority_id').present?)
|
||||
)
|
||||
# 将跟踪者与本项目的其他成员都设为收件方,并去重,不在进行抄送,
|
||||
recipients = journal.recipients - journal.watcher_recipients + journal.watcher_recipients
|
||||
recipients.each do |rec|
|
||||
|
||||
Mailer.run.issue_edit(journal,rec)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
class JournalObserver < ActiveRecord::Observer
|
||||
def after_create(journal)
|
||||
if journal.notify? &&
|
||||
(Setting.notified_events.include?('issue_updated') ||
|
||||
(Setting.notified_events.include?('issue_note_added') && journal.notes.present?) ||
|
||||
(Setting.notified_events.include?('issue_status_updated') && journal.new_status.present?) ||
|
||||
(Setting.notified_events.include?('issue_priority_updated') && journal.new_value_for('priority_id').present?)
|
||||
)
|
||||
# 将跟踪者与本项目的其他成员都设为收件方,并去重,不在进行抄送,
|
||||
recipients = journal.recipients - journal.watcher_recipients + journal.watcher_recipients
|
||||
recipients.each do |rec|
|
||||
|
||||
Mailer.run.issue_edit(journal,rec)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,175 +1,179 @@
|
|||
# fq
|
||||
# 数据库字段中带有m前缀和is_readed是二次开发添加,之前的字段基本复用
|
||||
# 注意reply_id 是提到人的id,不是留言id, Base中叫做 at_user
|
||||
class JournalsForMessage < ActiveRecord::Base
|
||||
include Redmine::SafeAttributes
|
||||
include UserScoreHelper
|
||||
include ApplicationHelper
|
||||
has_many_kindeditor_assets :assets, :dependent => :destroy
|
||||
safe_attributes "jour_type", # 留言所属类型
|
||||
"jour_id", # 留言所属类型的id
|
||||
"notes", # 留言内容
|
||||
"reply_id", # 留言被回复留言者的用户id(用户a回复了用户b,这是b的id,用以查询谁给b留言了)
|
||||
"status", # 留言是否被查看(弃用)
|
||||
"user_id", # 留言者的id
|
||||
"m_parent_id", # 留言信息的父留言id
|
||||
"is_readed", # 留言是否已读
|
||||
"m_reply_count", # 留言的回复数量
|
||||
"m_reply_id" # 回复某留言的留言id(a留言回复了b留言,这是b留言的id)
|
||||
"is_comprehensive_evaluation" # 1 教师评论、2 匿评、3 留言
|
||||
acts_as_tree :foreign_key => 'm_parent_id', :counter_cache => :m_reply_count, :order => "#{JournalsForMessage.table_name}.created_on ASC"
|
||||
after_destroy :delete_kindeditor_assets
|
||||
belongs_to :project,
|
||||
:foreign_key => 'jour_id',
|
||||
:conditions => "#{self.table_name}.jour_type = 'Project' "
|
||||
belongs_to :course,
|
||||
:foreign_key => 'jour_id'
|
||||
|
||||
|
||||
belongs_to :jour, :polymorphic => true
|
||||
belongs_to :user
|
||||
belongs_to :homework_attach
|
||||
belongs_to :at_user, :class_name => "User", :foreign_key => 'reply_id'
|
||||
|
||||
acts_as_event :title => Proc.new {|o| "#{l(:label_my_message)}"},
|
||||
:datetime => Proc.new {|o| o.updated_on },
|
||||
:author => Proc.new {|o| o.user },
|
||||
:description => Proc.new{|o| o.notes },
|
||||
:type => Proc.new {|o| o.jour_type },
|
||||
:url => Proc.new {|o|
|
||||
if o.jour.kind_of? Project
|
||||
{:controller => 'projects', :action => 'feedback', :id => o.jour, :r => o.id, :anchor => "word_li_#{o.id}"}
|
||||
elsif o.jour.kind_of? Course
|
||||
{:controller => 'courses', :action => 'feedback', :id => o.jour, :r => o.id, :anchor => "word_li_#{o.id}"}
|
||||
end
|
||||
}
|
||||
acts_as_activity_provider :author_key => :user_id,
|
||||
:timestamp => "#{self.table_name}.updated_on",
|
||||
:find_options => {:include => :project }
|
||||
|
||||
acts_as_activity_provider :type => 'course_journals_for_messages',
|
||||
:author_key => :user_id,
|
||||
:permission => :view_course_journals_for_messages,
|
||||
:timestamp => "#{self.table_name}.updated_on",
|
||||
:find_options => {:include => :course }
|
||||
|
||||
|
||||
has_many :acts, :class_name => 'Activity', :as => :act, :dependent => :destroy
|
||||
|
||||
validates :notes, presence: true
|
||||
after_create :act_as_activity #huang
|
||||
after_create :reset_counters!
|
||||
after_destroy :reset_counters!
|
||||
after_save :be_user_score
|
||||
after_destroy :down_user_score
|
||||
|
||||
# default_scope { where('m_parent_id IS NULL') }
|
||||
|
||||
def self.create_by_user? user
|
||||
if user.anonymous?
|
||||
return false
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def self.remove_by_user? user
|
||||
if( self.user == user ||
|
||||
( self.jour.kind_of?(User) && self.jour== user )
|
||||
)
|
||||
true
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
def self.delete_message(message_id)
|
||||
self.find(message_id).destroy
|
||||
# self.destroy_all "id = #{message_id}"
|
||||
end
|
||||
|
||||
def reference_user
|
||||
User.find(reply_id)
|
||||
end
|
||||
|
||||
def delete_by_user?user
|
||||
# 用户可删除自己的留言
|
||||
if self.user.id == user.id || user.admin?
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
def self.reference_message(user_id)
|
||||
@user = User.find(user_id)
|
||||
message = JournalsForMessage.find_by_sql("select * from journals_for_messages where reply_id = #{@user.id}
|
||||
or (jour_type = 'Bid' and jour_id in (select id from bids where author_id = #{@user.id}))")
|
||||
message
|
||||
end
|
||||
|
||||
def act_as_activity
|
||||
if self.jour_type == 'Principal'
|
||||
unless self.user_id == self.jour.id && self.user_id != self.reply_id && self.reply_id != 0
|
||||
# self.acts << Activity.new(:user_id => self.user_id)
|
||||
self.acts << Activity.new(:user_id => self.jour_id)
|
||||
end
|
||||
elsif self.jour_type == 'Project'
|
||||
self.acts << Activity.new(:user_id => self.reply_id)
|
||||
elsif self.jour_type == 'Course'
|
||||
self.acts << Activity.new(:user_id => self.reply_id)
|
||||
else
|
||||
end
|
||||
end
|
||||
|
||||
def reset_counters!
|
||||
self.class.reset_counters!(self)
|
||||
end
|
||||
def self.reset_counters! journals_for_messages
|
||||
# jfm_id = journals_for_messages.id.to_i
|
||||
count = find_all_by_m_parent_id(journals_for_messages.m_parent_id).count #(SELECT COUNT(*) FROM #{JournalsForMessage.table_name} WHERE m_parent_id = #{jfm_id} )
|
||||
update_all("m_reply_count = #{count.to_i}", ["id = ?", journals_for_messages.m_parent_id])
|
||||
end
|
||||
|
||||
#如果是在项目中留言则返回该项目否则返回nil - zjc
|
||||
def project
|
||||
if self.jour_type == 'Project'
|
||||
Project.find(self.jour_id)
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
# 更新用户分数 -by zjc
|
||||
def be_user_score
|
||||
#新建了留言回复
|
||||
if self.reply_id != 0
|
||||
#协同得分加分
|
||||
UserScore.joint(:reply_message, self.user,User.find(self.reply_id),self, { journals_for_messages_id: self.id })
|
||||
update_replay_for_message(self.user,1)
|
||||
if self.jour_type == "Project"
|
||||
update_replay_for_message(self.user,2,self.jour)
|
||||
end
|
||||
end
|
||||
end
|
||||
# 更新用户分数 -by zjc
|
||||
def down_user_score
|
||||
#删除了留言回复
|
||||
if self.reply_id != 0
|
||||
#协同得分减分
|
||||
UserScore.joint(:reply_message_delete, self.user,User.find(self.reply_id), { journals_for_messages_id: self.id })
|
||||
update_replay_for_message(self.user,1)
|
||||
if self.jour_type == "Project"
|
||||
update_replay_for_message(self.user,2,self.jour)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Time 2015-04-01 14:15:06
|
||||
# Author lizanle
|
||||
# Description 删除对应课程留言的图片资源
|
||||
def delete_kindeditor_assets
|
||||
delete_kindeditor_assets_from_disk self.id,7
|
||||
end
|
||||
end
|
||||
# fq
|
||||
# 数据库字段中带有m前缀和is_readed是二次开发添加,之前的字段基本复用
|
||||
# 注意reply_id 是提到人的id,不是留言id, Base中叫做 at_user
|
||||
class JournalsForMessage < ActiveRecord::Base
|
||||
include Redmine::SafeAttributes
|
||||
include UserScoreHelper
|
||||
include ApplicationHelper
|
||||
has_many_kindeditor_assets :assets, :dependent => :destroy
|
||||
safe_attributes "jour_type", # 留言所属类型
|
||||
"jour_id", # 留言所属类型的id
|
||||
"notes", # 留言内容
|
||||
"reply_id", # 留言被回复留言者的用户id(用户a回复了用户b,这是b的id,用以查询谁给b留言了)
|
||||
"status", # 留言是否被查看(弃用)
|
||||
"user_id", # 留言者的id
|
||||
"m_parent_id", # 留言信息的父留言id
|
||||
"is_readed", # 留言是否已读
|
||||
"m_reply_count", # 留言的回复数量
|
||||
"m_reply_id" # 回复某留言的留言id(a留言回复了b留言,这是b留言的id)
|
||||
"is_comprehensive_evaluation" # 1 教师评论、2 匿评、3 留言
|
||||
acts_as_tree :foreign_key => 'm_parent_id', :counter_cache => :m_reply_count, :order => "#{JournalsForMessage.table_name}.created_on ASC"
|
||||
after_destroy :delete_kindeditor_assets
|
||||
belongs_to :project,
|
||||
:foreign_key => 'jour_id',
|
||||
:conditions => "#{self.table_name}.jour_type = 'Project' "
|
||||
belongs_to :course,
|
||||
:foreign_key => 'jour_id'
|
||||
|
||||
|
||||
belongs_to :jour, :polymorphic => true
|
||||
belongs_to :user
|
||||
belongs_to :homework_attach
|
||||
belongs_to :at_user, :class_name => "User", :foreign_key => 'reply_id'
|
||||
|
||||
acts_as_event :title => Proc.new {|o| "#{l(:label_my_message)}"},
|
||||
:datetime => Proc.new {|o| o.updated_on },
|
||||
:author => Proc.new {|o| o.user },
|
||||
:description => Proc.new{|o| o.notes },
|
||||
:type => Proc.new {|o| o.jour_type },
|
||||
:url => Proc.new {|o|
|
||||
if o.jour.kind_of? Project
|
||||
{:controller => 'projects', :action => 'feedback', :id => o.jour, :r => o.id, :anchor => "word_li_#{o.id}"}
|
||||
elsif o.jour.kind_of? Course
|
||||
{:controller => 'courses', :action => 'feedback', :id => o.jour, :r => o.id, :anchor => "word_li_#{o.id}"}
|
||||
end
|
||||
}
|
||||
acts_as_activity_provider :author_key => :user_id,
|
||||
:timestamp => "#{self.table_name}.updated_on",
|
||||
:find_options => {:include => :project }
|
||||
|
||||
acts_as_activity_provider :type => 'course_journals_for_messages',
|
||||
:author_key => :user_id,
|
||||
:permission => :view_course_journals_for_messages,
|
||||
:timestamp => "#{self.table_name}.updated_on",
|
||||
:find_options => {:include => :course }
|
||||
acts_as_attachable
|
||||
|
||||
has_many :acts, :class_name => 'Activity', :as => :act, :dependent => :destroy
|
||||
|
||||
validates :notes, presence: true, if: :is_homework_jour?
|
||||
after_create :act_as_activity #huang
|
||||
after_create :reset_counters!
|
||||
after_destroy :reset_counters!
|
||||
after_save :be_user_score
|
||||
after_destroy :down_user_score
|
||||
|
||||
# default_scope { where('m_parent_id IS NULL') }
|
||||
|
||||
def self.create_by_user? user
|
||||
if user.anonymous?
|
||||
return false
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def self.remove_by_user? user
|
||||
if( self.user == user ||
|
||||
( self.jour.kind_of?(User) && self.jour== user )
|
||||
)
|
||||
true
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
def self.delete_message(message_id)
|
||||
self.find(message_id).destroy
|
||||
# self.destroy_all "id = #{message_id}"
|
||||
end
|
||||
|
||||
def is_homework_jour?
|
||||
self.jour_type != "HomeworkAttach"
|
||||
end
|
||||
|
||||
def reference_user
|
||||
User.find(reply_id)
|
||||
end
|
||||
|
||||
def delete_by_user?user
|
||||
# 用户可删除自己的留言
|
||||
if self.user.id == user.id || user.admin?
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
def self.reference_message(user_id)
|
||||
@user = User.find(user_id)
|
||||
message = JournalsForMessage.find_by_sql("select * from journals_for_messages where reply_id = #{@user.id}
|
||||
or (jour_type = 'Bid' and jour_id in (select id from bids where author_id = #{@user.id}))")
|
||||
message
|
||||
end
|
||||
|
||||
def act_as_activity
|
||||
if self.jour_type == 'Principal'
|
||||
unless self.user_id == self.jour.id && self.user_id != self.reply_id && self.reply_id != 0
|
||||
# self.acts << Activity.new(:user_id => self.user_id)
|
||||
self.acts << Activity.new(:user_id => self.jour_id)
|
||||
end
|
||||
elsif self.jour_type == 'Project'
|
||||
self.acts << Activity.new(:user_id => self.reply_id)
|
||||
elsif self.jour_type == 'Course'
|
||||
self.acts << Activity.new(:user_id => self.reply_id)
|
||||
else
|
||||
end
|
||||
end
|
||||
|
||||
def reset_counters!
|
||||
self.class.reset_counters!(self)
|
||||
end
|
||||
def self.reset_counters! journals_for_messages
|
||||
# jfm_id = journals_for_messages.id.to_i
|
||||
count = find_all_by_m_parent_id(journals_for_messages.m_parent_id).count #(SELECT COUNT(*) FROM #{JournalsForMessage.table_name} WHERE m_parent_id = #{jfm_id} )
|
||||
update_all("m_reply_count = #{count.to_i}", ["id = ?", journals_for_messages.m_parent_id])
|
||||
end
|
||||
|
||||
#如果是在项目中留言则返回该项目否则返回nil - zjc
|
||||
def project
|
||||
if self.jour_type == 'Project'
|
||||
Project.find(self.jour_id)
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
# 更新用户分数 -by zjc
|
||||
def be_user_score
|
||||
#新建了留言回复
|
||||
if self.reply_id != 0
|
||||
#协同得分加分
|
||||
UserScore.joint(:reply_message, self.user,User.find(self.reply_id),self, { journals_for_messages_id: self.id })
|
||||
update_replay_for_message(self.user,1)
|
||||
if self.jour_type == "Project"
|
||||
update_replay_for_message(self.user,2,self.jour)
|
||||
end
|
||||
end
|
||||
end
|
||||
# 更新用户分数 -by zjc
|
||||
def down_user_score
|
||||
#删除了留言回复
|
||||
if self.reply_id != 0
|
||||
#协同得分减分
|
||||
UserScore.joint(:reply_message_delete, self.user,User.find(self.reply_id), { journals_for_messages_id: self.id })
|
||||
update_replay_for_message(self.user,1)
|
||||
if self.jour_type == "Project"
|
||||
update_replay_for_message(self.user,2,self.jour)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Time 2015-04-01 14:15:06
|
||||
# Author lizanle
|
||||
# Description 删除对应课程留言的图片资源
|
||||
def delete_kindeditor_assets
|
||||
delete_kindeditor_assets_from_disk self.id,7
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# Added by young
|
||||
class JournalsForMessageObserver < ActiveRecord::Observer
|
||||
def after_create(journals_for_message)
|
||||
Mailer.run.journals_for_message_add(User.current, journals_for_message)
|
||||
end
|
||||
end
|
||||
|
||||
# Added by young
|
||||
class JournalsForMessageObserver < ActiveRecord::Observer
|
||||
def after_create(journals_for_message)
|
||||
Mailer.run.journals_for_message_add(User.current, journals_for_message)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,490 +1,490 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
class MailHandler < ActionMailer::Base
|
||||
include ActionView::Helpers::SanitizeHelper
|
||||
include Redmine::I18n
|
||||
|
||||
class UnauthorizedAction < StandardError; end
|
||||
class MissingInformation < StandardError; end
|
||||
|
||||
attr_reader :email, :user
|
||||
|
||||
def self.receive(email, options={})
|
||||
@@handler_options = options.dup
|
||||
|
||||
@@handler_options[:issue] ||= {}
|
||||
|
||||
if @@handler_options[:allow_override].is_a?(String)
|
||||
@@handler_options[:allow_override] = @@handler_options[:allow_override].split(',').collect(&:strip)
|
||||
end
|
||||
@@handler_options[:allow_override] ||= []
|
||||
# Project needs to be overridable if not specified
|
||||
@@handler_options[:allow_override] << 'project' unless @@handler_options[:issue].has_key?(:project)
|
||||
# Status overridable by default
|
||||
@@handler_options[:allow_override] << 'status' unless @@handler_options[:issue].has_key?(:status)
|
||||
|
||||
@@handler_options[:no_account_notice] = (@@handler_options[:no_account_notice].to_s == '1')
|
||||
@@handler_options[:no_notification] = (@@handler_options[:no_notification].to_s == '1')
|
||||
@@handler_options[:no_permission_check] = (@@handler_options[:no_permission_check].to_s == '1')
|
||||
|
||||
email.force_encoding('ASCII-8BIT') if email.respond_to?(:force_encoding)
|
||||
super(email)
|
||||
end
|
||||
|
||||
def logger
|
||||
Rails.logger
|
||||
end
|
||||
|
||||
cattr_accessor :ignored_emails_headers
|
||||
@@ignored_emails_headers = {
|
||||
'X-Auto-Response-Suppress' => 'oof',
|
||||
'Auto-Submitted' => /^auto-/
|
||||
}
|
||||
|
||||
# Processes incoming emails
|
||||
# Returns the created object (eg. an issue, a message) or false
|
||||
def receive(email)
|
||||
@email = email
|
||||
sender_email = email.from.to_a.first.to_s.strip
|
||||
# Ignore emails received from the application emission address to avoid hell cycles
|
||||
if sender_email.downcase == Setting.mail_from.to_s.strip.downcase
|
||||
if logger && logger.info
|
||||
logger.info "MailHandler: ignoring email from Redmine emission address [#{sender_email}]"
|
||||
end
|
||||
return false
|
||||
end
|
||||
# Ignore auto generated emails
|
||||
self.class.ignored_emails_headers.each do |key, ignored_value|
|
||||
value = email.header[key]
|
||||
if value
|
||||
value = value.to_s.downcase
|
||||
if (ignored_value.is_a?(Regexp) && value.match(ignored_value)) || value == ignored_value
|
||||
if logger && logger.info
|
||||
logger.info "MailHandler: ignoring email with #{key}:#{value} header"
|
||||
end
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
@user = User.find_by_mail(sender_email) if sender_email.present?
|
||||
if @user && !@user.active?
|
||||
if logger && logger.info
|
||||
logger.info "MailHandler: ignoring email from non-active user [#{@user.login}]"
|
||||
end
|
||||
return false
|
||||
end
|
||||
if @user.nil?
|
||||
# Email was submitted by an unknown user
|
||||
case @@handler_options[:unknown_user]
|
||||
when 'accept'
|
||||
@user = User.anonymous
|
||||
when 'create'
|
||||
@user = create_user_from_email
|
||||
if @user
|
||||
if logger && logger.info
|
||||
logger.info "MailHandler: [#{@user.login}] account created"
|
||||
end
|
||||
add_user_to_group(@@handler_options[:default_group])
|
||||
unless @@handler_options[:no_account_notice]
|
||||
Mailer.run.account_information(@user, @user.password)
|
||||
end
|
||||
else
|
||||
if logger && logger.error
|
||||
logger.error "MailHandler: could not create account for [#{sender_email}]"
|
||||
end
|
||||
return false
|
||||
end
|
||||
else
|
||||
# Default behaviour, emails from unknown users are ignored
|
||||
if logger && logger.info
|
||||
logger.info "MailHandler: ignoring email from unknown user [#{sender_email}]"
|
||||
end
|
||||
return false
|
||||
end
|
||||
end
|
||||
User.current = @user
|
||||
dispatch
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
MESSAGE_ID_RE = %r{^<?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
|
||||
|
|
1839
app/models/mailer.rb
1839
app/models/mailer.rb
File diff suppressed because it is too large
Load Diff
|
@ -1,179 +1,179 @@
|
|||
class Memo < ActiveRecord::Base
|
||||
include Redmine::SafeAttributes
|
||||
include UserScoreHelper
|
||||
include ApplicationHelper
|
||||
belongs_to :forum
|
||||
has_many_kindeditor_assets :assets, :dependent => :destroy
|
||||
belongs_to :author, :class_name => "User", :foreign_key => 'author_id'
|
||||
validates_presence_of :author_id, :forum_id, :subject,:content
|
||||
# 若是主题帖,则内容可以是空
|
||||
#validates :content, presence: true, if: Proc.new{|o| !o.parent_id.nil? }
|
||||
validates_length_of :subject, maximum: 50
|
||||
#validates_length_of :content, maximum: 3072
|
||||
validate :cannot_reply_to_locked_topic, :on => :create
|
||||
|
||||
acts_as_tree :counter_cache => :replies_count, :order => "#{Memo.table_name}.created_at ASC"
|
||||
acts_as_attachable
|
||||
has_many :user_score_details, :class_name => 'UserScoreDetails',:as => :score_changeable_obj
|
||||
has_many :praise_tread, as: :praise_tread_object, dependent: :destroy
|
||||
belongs_to :last_reply, :class_name => 'Memo', :foreign_key => 'last_reply_id'
|
||||
# acts_as_searchable :column => ['subject', 'content'],
|
||||
# #:include => { :forum => :p}
|
||||
# #:project_key => "#{Forum.table_name}.project_id"
|
||||
# :date_column => "#{table_name}.created_at"
|
||||
acts_as_event :title => Proc.new {|o| "#{o.forum.name}: #{o.subject}"},
|
||||
:datetime => :updated_at,
|
||||
# :datetime => :created_at,
|
||||
:description => :content,
|
||||
:author => :author,
|
||||
:type => Proc.new {|o| o.parent_id.nil? ? 'Memo' : 'Reply'},
|
||||
:url => Proc.new {|o| {:controller => 'memos', :action => 'show', :forum_id => o.forum_id}.merge(o.parent_id.nil? ? {:id => o.id} : {:id => o.parent_id, :r => o.id, :anchor => "reply-#{o.id}"})}
|
||||
acts_as_activity_provider :author_key => :author_id,
|
||||
:func => 'memos',
|
||||
:timestamp => 'created_at'
|
||||
# :find_options => {:type => 'memos'}
|
||||
# acts_as_watchable
|
||||
|
||||
safe_attributes "author_id",
|
||||
"subject",
|
||||
"content",
|
||||
"forum_id",
|
||||
"last_memo_id",
|
||||
"lock",
|
||||
"sticky",
|
||||
"parent_id",
|
||||
"replies_count"
|
||||
|
||||
after_create :add_author_as_watcher, :reset_counters!, :send_mail
|
||||
# after_update :update_memos_forum
|
||||
after_destroy :reset_counters!,:delete_kindeditor_assets#,:down_user_score -- 公共区发帖暂不计入得分
|
||||
# after_create :send_notification
|
||||
# after_save :plusParentAndForum
|
||||
# after_destroy :minusParentAndForum
|
||||
#before_save :be_user_score
|
||||
# scope :visible, lambda { |*args|
|
||||
# includes(:forum => ).where()
|
||||
# }
|
||||
|
||||
def send_mail
|
||||
Mailer.run.forum_message_added(self) if Setting.notified_events.include?('forum_message_added')
|
||||
end
|
||||
|
||||
def cannot_reply_to_locked_topic
|
||||
errors.add :base, l(:label_memo_locked) if root.locked? && self != root
|
||||
end
|
||||
|
||||
# def update_memos_forum
|
||||
# if forum_id_changed?
|
||||
# Message.update_all({:board_id => board_id}, ["id = ? OR parent_id = ?", root.id, root.id ])
|
||||
# Forum.reset_counters!(forum_id_was)
|
||||
# Forum.reset_counters!(forum_id)
|
||||
# end
|
||||
# end
|
||||
|
||||
def reset_counters!
|
||||
if parent && parent.id
|
||||
Memo.update_all({:last_reply_id => parent.children.maximum(:id)}, {:id => parent.id})
|
||||
parent.update_attribute(:updated_at, Time.now)
|
||||
end
|
||||
forum.reset_counters!
|
||||
end
|
||||
|
||||
def sticky?
|
||||
sticky == 1
|
||||
end
|
||||
|
||||
def replies
|
||||
Memo.where("parent_id = ?", id)
|
||||
end
|
||||
|
||||
def locked?
|
||||
self.lock
|
||||
end
|
||||
|
||||
def editable_by? user
|
||||
# user && user.logged? || (self.author == usr && usr.allowed_to?(:edit_own_messages, project))
|
||||
user.admin? || self.author == user
|
||||
end
|
||||
|
||||
def destroyable_by? user
|
||||
(user && self.author == user) || user.admin?
|
||||
#self.author == user || user.admin?
|
||||
end
|
||||
|
||||
def deleted_attach_able_by? user
|
||||
(user && user.logged? && (self.author == user) ) || user.admin?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def add_author_as_watcher
|
||||
Watcher.create(:watchable => self.root, :user => author)
|
||||
end
|
||||
|
||||
def send_notification
|
||||
if Setting.notified_events.include?('message_posted')
|
||||
Mailer.run.message_posted(self)
|
||||
end
|
||||
end
|
||||
|
||||
def plusParentAndForum
|
||||
@forum = Forum.find(self.forum_id)
|
||||
@forum.memo_count = @forum.memo_count.to_int + 1
|
||||
@forum.last_memo_id = self.id
|
||||
if self.parent_id
|
||||
@parent_memo = Memo.find_by_id(self.parent_id)
|
||||
@parent_memo.last_reply_id = self
|
||||
@parent_memo.replies_count = @parent_memo.replies_count.to_int + 1
|
||||
@parent_memo.save
|
||||
else
|
||||
@forum.topic_count = @forum.topic_count.to_int + 1
|
||||
end
|
||||
@forum.save
|
||||
end
|
||||
|
||||
def minusParentAndForum
|
||||
@forum = Forum.find(self.forum_id)
|
||||
@forum.memo_count = @forum.memo_count.to_int - 1
|
||||
@forum.memo_count = 0 if @forum.memo_count.to_int < 0
|
||||
# @forum.last_memo_id = Memo.reorder('created_at ASC').find_all_by_forum_id(self.forum_id).last.id
|
||||
if self.parent_id
|
||||
@parent_memo = Memo.find_by_id(self.parent_id)
|
||||
# @parent_memo.last_reply_id = Memo.reorder('created_at ASC').find_all_by_parent_id(self.parent_id).last.id
|
||||
@parent_memo.replies_count = @parent_memo.replies_count.to_int - 1
|
||||
@parent_memo.replies_count = 0 if @parent_memo.replies_count.to_int < 0
|
||||
@parent_memo.save
|
||||
else
|
||||
@forum.topic_count = @forum.topic_count.to_int - 1
|
||||
@forum.topic_count = 0 if @forum.topic_count.to_int < 0
|
||||
end
|
||||
@forum.save
|
||||
end
|
||||
|
||||
#更新用户分数 -by zjc
|
||||
def be_user_score
|
||||
#新建memo且无parent的为发帖
|
||||
if self.parent_id.nil?
|
||||
UserScore.joint(:post_message, User.current,nil,self ,{ memo_id: self.id })
|
||||
update_memo_number(User.current,1)
|
||||
|
||||
#新建memo且有parent的为回帖
|
||||
elsif !self.parent_id.nil?
|
||||
UserScore.joint(:reply_posting, User.current,self.parent.author,self, { memo_id: self.id })
|
||||
update_replay_for_memo(User.current,1)
|
||||
end
|
||||
end
|
||||
|
||||
#被删除时更新用户分数
|
||||
def down_user_score
|
||||
update_memo_number(User.current,1)
|
||||
update_replay_for_memo(User.current,1)
|
||||
end
|
||||
|
||||
# Time 2015-03-26 15:20:24
|
||||
# Author lizanle
|
||||
# Description 从硬盘上删除资源
|
||||
def delete_kindeditor_assets
|
||||
delete_kindeditor_assets_from_disk self.id,OwnerTypeHelper::MEMO
|
||||
end
|
||||
end
|
||||
class Memo < ActiveRecord::Base
|
||||
include Redmine::SafeAttributes
|
||||
include UserScoreHelper
|
||||
include ApplicationHelper
|
||||
belongs_to :forum
|
||||
has_many_kindeditor_assets :assets, :dependent => :destroy
|
||||
belongs_to :author, :class_name => "User", :foreign_key => 'author_id'
|
||||
validates_presence_of :author_id, :forum_id, :subject,:content
|
||||
# 若是主题帖,则内容可以是空
|
||||
#validates :content, presence: true, if: Proc.new{|o| !o.parent_id.nil? }
|
||||
validates_length_of :subject, maximum: 50
|
||||
#validates_length_of :content, maximum: 3072
|
||||
validate :cannot_reply_to_locked_topic, :on => :create
|
||||
|
||||
acts_as_tree :counter_cache => :replies_count, :order => "#{Memo.table_name}.created_at ASC"
|
||||
acts_as_attachable
|
||||
has_many :user_score_details, :class_name => 'UserScoreDetails',:as => :score_changeable_obj
|
||||
has_many :praise_tread, as: :praise_tread_object, dependent: :destroy
|
||||
belongs_to :last_reply, :class_name => 'Memo', :foreign_key => 'last_reply_id'
|
||||
# acts_as_searchable :column => ['subject', 'content'],
|
||||
# #:include => { :forum => :p}
|
||||
# #:project_key => "#{Forum.table_name}.project_id"
|
||||
# :date_column => "#{table_name}.created_at"
|
||||
acts_as_event :title => Proc.new {|o| "#{o.forum.name}: #{o.subject}"},
|
||||
:datetime => :updated_at,
|
||||
# :datetime => :created_at,
|
||||
:description => :content,
|
||||
:author => :author,
|
||||
:type => Proc.new {|o| o.parent_id.nil? ? 'Memo' : 'Reply'},
|
||||
:url => Proc.new {|o| {:controller => 'memos', :action => 'show', :forum_id => o.forum_id}.merge(o.parent_id.nil? ? {:id => o.id} : {:id => o.parent_id, :r => o.id, :anchor => "reply-#{o.id}"})}
|
||||
acts_as_activity_provider :author_key => :author_id,
|
||||
:func => 'memos',
|
||||
:timestamp => 'created_at'
|
||||
# :find_options => {:type => 'memos'}
|
||||
# acts_as_watchable
|
||||
|
||||
safe_attributes "author_id",
|
||||
"subject",
|
||||
"content",
|
||||
"forum_id",
|
||||
"last_memo_id",
|
||||
"lock",
|
||||
"sticky",
|
||||
"parent_id",
|
||||
"replies_count"
|
||||
|
||||
after_create :add_author_as_watcher, :reset_counters!, :send_mail
|
||||
# after_update :update_memos_forum
|
||||
after_destroy :reset_counters!,:delete_kindeditor_assets#,:down_user_score -- 公共区发帖暂不计入得分
|
||||
# after_create :send_notification
|
||||
# after_save :plusParentAndForum
|
||||
# after_destroy :minusParentAndForum
|
||||
#before_save :be_user_score
|
||||
# scope :visible, lambda { |*args|
|
||||
# includes(:forum => ).where()
|
||||
# }
|
||||
|
||||
def send_mail
|
||||
Mailer.run.forum_message_added(self) if Setting.notified_events.include?('forum_message_added')
|
||||
end
|
||||
|
||||
def cannot_reply_to_locked_topic
|
||||
errors.add :base, l(:label_memo_locked) if root.locked? && self != root
|
||||
end
|
||||
|
||||
# def update_memos_forum
|
||||
# if forum_id_changed?
|
||||
# Message.update_all({:board_id => board_id}, ["id = ? OR parent_id = ?", root.id, root.id ])
|
||||
# Forum.reset_counters!(forum_id_was)
|
||||
# Forum.reset_counters!(forum_id)
|
||||
# end
|
||||
# end
|
||||
|
||||
def reset_counters!
|
||||
if parent && parent.id
|
||||
Memo.update_all({:last_reply_id => parent.children.maximum(:id)}, {:id => parent.id})
|
||||
parent.update_attribute(:updated_at, Time.now)
|
||||
end
|
||||
forum.reset_counters!
|
||||
end
|
||||
|
||||
def sticky?
|
||||
sticky == 1
|
||||
end
|
||||
|
||||
def replies
|
||||
Memo.where("parent_id = ?", id)
|
||||
end
|
||||
|
||||
def locked?
|
||||
self.lock
|
||||
end
|
||||
|
||||
def editable_by? user
|
||||
# user && user.logged? || (self.author == usr && usr.allowed_to?(:edit_own_messages, project))
|
||||
user.admin? || self.author == user
|
||||
end
|
||||
|
||||
def destroyable_by? user
|
||||
(user && self.author == user) || user.admin?
|
||||
#self.author == user || user.admin?
|
||||
end
|
||||
|
||||
def deleted_attach_able_by? user
|
||||
(user && user.logged? && (self.author == user) ) || user.admin?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def add_author_as_watcher
|
||||
Watcher.create(:watchable => self.root, :user => author)
|
||||
end
|
||||
|
||||
def send_notification
|
||||
if Setting.notified_events.include?('message_posted')
|
||||
Mailer.run.message_posted(self)
|
||||
end
|
||||
end
|
||||
|
||||
def plusParentAndForum
|
||||
@forum = Forum.find(self.forum_id)
|
||||
@forum.memo_count = @forum.memo_count.to_int + 1
|
||||
@forum.last_memo_id = self.id
|
||||
if self.parent_id
|
||||
@parent_memo = Memo.find_by_id(self.parent_id)
|
||||
@parent_memo.last_reply_id = self
|
||||
@parent_memo.replies_count = @parent_memo.replies_count.to_int + 1
|
||||
@parent_memo.save
|
||||
else
|
||||
@forum.topic_count = @forum.topic_count.to_int + 1
|
||||
end
|
||||
@forum.save
|
||||
end
|
||||
|
||||
def minusParentAndForum
|
||||
@forum = Forum.find(self.forum_id)
|
||||
@forum.memo_count = @forum.memo_count.to_int - 1
|
||||
@forum.memo_count = 0 if @forum.memo_count.to_int < 0
|
||||
# @forum.last_memo_id = Memo.reorder('created_at ASC').find_all_by_forum_id(self.forum_id).last.id
|
||||
if self.parent_id
|
||||
@parent_memo = Memo.find_by_id(self.parent_id)
|
||||
# @parent_memo.last_reply_id = Memo.reorder('created_at ASC').find_all_by_parent_id(self.parent_id).last.id
|
||||
@parent_memo.replies_count = @parent_memo.replies_count.to_int - 1
|
||||
@parent_memo.replies_count = 0 if @parent_memo.replies_count.to_int < 0
|
||||
@parent_memo.save
|
||||
else
|
||||
@forum.topic_count = @forum.topic_count.to_int - 1
|
||||
@forum.topic_count = 0 if @forum.topic_count.to_int < 0
|
||||
end
|
||||
@forum.save
|
||||
end
|
||||
|
||||
#更新用户分数 -by zjc
|
||||
def be_user_score
|
||||
#新建memo且无parent的为发帖
|
||||
if self.parent_id.nil?
|
||||
UserScore.joint(:post_message, User.current,nil,self ,{ memo_id: self.id })
|
||||
update_memo_number(User.current,1)
|
||||
|
||||
#新建memo且有parent的为回帖
|
||||
elsif !self.parent_id.nil?
|
||||
UserScore.joint(:reply_posting, User.current,self.parent.author,self, { memo_id: self.id })
|
||||
update_replay_for_memo(User.current,1)
|
||||
end
|
||||
end
|
||||
|
||||
#被删除时更新用户分数
|
||||
def down_user_score
|
||||
update_memo_number(User.current,1)
|
||||
update_replay_for_memo(User.current,1)
|
||||
end
|
||||
|
||||
# Time 2015-03-26 15:20:24
|
||||
# Author lizanle
|
||||
# Description 从硬盘上删除资源
|
||||
def delete_kindeditor_assets
|
||||
delete_kindeditor_assets_from_disk self.id,OwnerTypeHelper::MEMO
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,221 +1,221 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
class Message < ActiveRecord::Base
|
||||
include Redmine::SafeAttributes
|
||||
include UserScoreHelper
|
||||
include ApplicationHelper
|
||||
has_many_kindeditor_assets :assets, :dependent => :destroy
|
||||
belongs_to :board
|
||||
belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
|
||||
has_many :praise_tread, as: :praise_tread_object, dependent: :destroy
|
||||
|
||||
acts_as_tree :counter_cache => :replies_count, :order => "#{Message.table_name}.created_on ASC"
|
||||
acts_as_attachable
|
||||
belongs_to :last_reply, :class_name => 'Message', :foreign_key => 'last_reply_id'
|
||||
|
||||
# added by fq
|
||||
has_many :acts, :class_name => 'Activity', :as => :act, :dependent => :destroy
|
||||
# 被ForgeActivity虚拟关联
|
||||
has_many :forge_acts, :class_name => 'ForgeActivity',:as =>:forge_act ,:dependent => :destroy
|
||||
# end
|
||||
|
||||
acts_as_searchable :columns => ['subject', 'content'],
|
||||
:include => {:board => :project},
|
||||
:project_key => "#{Board.table_name}.project_id",
|
||||
:date_column => "#{table_name}.created_on"
|
||||
acts_as_searchable :columns => ['subject', 'content'],
|
||||
:include => {:board => :course},
|
||||
:course_key => "#{Board.table_name}.course_id",
|
||||
:date_column => "#{table_name}.created_at"
|
||||
acts_as_event :title => Proc.new {|o| "#{o.board.name}: #{o.subject}"},
|
||||
:description => :content,
|
||||
:datetime => :updated_on,
|
||||
# :datetime => "#{Message.table_name}.created_on",
|
||||
:group => :parent,
|
||||
:type => Proc.new {|o| o.parent_id.nil? ? 'message' : 'reply'},
|
||||
:url => Proc.new {|o| {:controller => 'messages', :action => 'show', :board_id => o.board_id}.merge(o.parent_id.nil? ? {:id => o.id} :
|
||||
{:id => o.parent_id, :r => o.id, :anchor => "message-#{o.id}"})}
|
||||
|
||||
acts_as_activity_provider :find_options => {:include => [{:board => :project}, :author]},
|
||||
:author_key => :author_id
|
||||
acts_as_activity_provider :find_options => {:include => [{:board => :course}, :author]},
|
||||
:type => 'course_messages',
|
||||
:author_key => :author_id
|
||||
acts_as_watchable
|
||||
|
||||
validates_presence_of :board, :subject, :content
|
||||
validates_length_of :subject, :maximum => 255
|
||||
validate :cannot_reply_to_locked_topic, :on => :create
|
||||
|
||||
after_create :add_author_as_watcher, :reset_counters!
|
||||
after_update :update_messages_board
|
||||
after_destroy :reset_counters!,:down_user_score,:delete_kindeditor_assets
|
||||
|
||||
after_create :act_as_activity,:be_user_score,:act_as_forge_activity, :send_mail
|
||||
#before_save :be_user_score
|
||||
|
||||
scope :visible, lambda {|*args|
|
||||
includes(:board => :project).where(Project.allowed_to_condition(args.shift || User.current, :view_messages, *args))
|
||||
}
|
||||
|
||||
scope :course_visible, lambda {|*args|
|
||||
includes(:board => :course).where(Course.allowed_to_condition(args.shift || User.current, :view_course_messages, *args))
|
||||
}
|
||||
|
||||
|
||||
safe_attributes 'subject', 'content'
|
||||
safe_attributes 'board_id','locked', 'sticky',
|
||||
:if => lambda {|message, user|
|
||||
if message.project
|
||||
user.allowed_to?(:edit_messages, message.project)
|
||||
else
|
||||
user.allowed_to?(:edit_messages, message.course)
|
||||
end
|
||||
}
|
||||
|
||||
def visible?(user=User.current)
|
||||
if project
|
||||
!user.nil? && user.allowed_to?(:view_messages, project)
|
||||
elsif course
|
||||
!user.nil? && user.allowed_to?(:view_messages, course)
|
||||
end
|
||||
end
|
||||
|
||||
def cannot_reply_to_locked_topic
|
||||
# Can not reply to a locked topic
|
||||
errors.add :base, 'Topic is locked' if root.locked? && self != root
|
||||
end
|
||||
|
||||
def update_messages_board
|
||||
if board_id_changed?
|
||||
Message.update_all({:board_id => board_id}, ["id = ? OR parent_id = ?", root.id, root.id])
|
||||
Board.reset_counters!(board_id_was)
|
||||
Board.reset_counters!(board_id)
|
||||
end
|
||||
end
|
||||
|
||||
def reset_counters!
|
||||
if parent && parent.id
|
||||
Message.update_all({:last_reply_id => parent.children.maximum(:id)}, {:id => parent.id})
|
||||
end
|
||||
board.reset_counters!
|
||||
end
|
||||
|
||||
def sticky=(arg)
|
||||
write_attribute :sticky, (arg == true || arg.to_s == '1' ? 1 : 0)
|
||||
end
|
||||
|
||||
def sticky?
|
||||
sticky == 1
|
||||
end
|
||||
|
||||
def project
|
||||
board.project
|
||||
end
|
||||
|
||||
def course
|
||||
board.course
|
||||
end
|
||||
|
||||
def course_editable_by?(usr)
|
||||
usr && usr.logged? && (usr.allowed_to?(:edit_messages, course) || (self.author == usr && usr.allowed_to?(:edit_own_messages, course)))
|
||||
end
|
||||
|
||||
def course_destroyable_by?(usr)
|
||||
usr && usr.logged? && (usr.allowed_to?(:delete_messages, course) || (self.author == usr && usr.allowed_to?(:delete_own_messages, course)))
|
||||
end
|
||||
|
||||
def editable_by?(usr)
|
||||
usr && usr.logged? && (usr.allowed_to?(:edit_messages, project) || (self.author == usr && usr.allowed_to?(:edit_own_messages, project)))
|
||||
end
|
||||
|
||||
def destroyable_by?(usr)
|
||||
usr && usr.logged? && (usr.allowed_to?(:delete_messages, project) || (self.author == usr && usr.allowed_to?(:delete_own_messages, project)))
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def add_author_as_watcher
|
||||
Watcher.create(:watchable => self.root, :user => author)
|
||||
end
|
||||
|
||||
# fq
|
||||
def act_as_activity
|
||||
self.acts << Activity.new(:user_id => self.author_id)
|
||||
end
|
||||
# end
|
||||
|
||||
# Time 2015-02-27 14:32:25
|
||||
# Author lizanle
|
||||
# Description
|
||||
def act_as_forge_activity
|
||||
# 如果project为空,那么就是课程相关的消息
|
||||
if !self.board.project.nil?
|
||||
self.forge_acts << ForgeActivity.new(:user_id => self.author_id,
|
||||
:project_id => self.board.project.id)
|
||||
end
|
||||
end
|
||||
|
||||
#更新用户分数 -by zjc
|
||||
def be_user_score
|
||||
#新建message且无parent的为发帖
|
||||
|
||||
if self.parent_id.nil? && !self.board.project.nil?
|
||||
UserScore.joint(:post_message, self.author,nil,self, { message_id: self.id })
|
||||
update_memo_number(self.author,1)
|
||||
if self.board.project_id != -1
|
||||
update_memo_number(self.author,2,self.board.project)
|
||||
end
|
||||
#新建message且有parent的为回帖
|
||||
elsif !self.parent_id.nil? && !self.board.project.nil?
|
||||
UserScore.joint(:reply_posting, self.author,self.parent.author,self, { message_id: self.id })
|
||||
update_replay_for_memo(self.author,1)
|
||||
if self.board.project_id != -1
|
||||
update_replay_for_memo(self.author,2,self.board.project)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#减少用户分数
|
||||
def down_user_score
|
||||
if self.parent_id.nil? && !self.board.project.nil?
|
||||
UserScore.joint(:delete_message, self.author,nil,self, { message_id: self.id })
|
||||
update_memo_number(User.current,1)
|
||||
if self.board.project_id != -1
|
||||
update_memo_number(self.author,2,self.board.project)
|
||||
end
|
||||
elsif !self.parent_id.nil? && !self.board.project.nil?
|
||||
UserScore.joint(:reply_deleting, self.author,self.parent.author,self, { message_id: self.id })
|
||||
update_replay_for_memo(User.current,1)
|
||||
if self.board.project_id != -1
|
||||
update_replay_for_memo(self.author,2,self.board.project)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def send_mail
|
||||
Mailer.run.message_posted(self) if Setting.notified_events.include?('message_posted')
|
||||
end
|
||||
|
||||
# Time 2015-03-31 09:15:06
|
||||
# Author lizanle
|
||||
# Description 删除对应消息的图片资源
|
||||
def delete_kindeditor_assets
|
||||
delete_kindeditor_assets_from_disk self.id,OwnerTypeHelper::MESSAGE
|
||||
end
|
||||
end
|
||||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
class Message < ActiveRecord::Base
|
||||
include Redmine::SafeAttributes
|
||||
include UserScoreHelper
|
||||
include ApplicationHelper
|
||||
has_many_kindeditor_assets :assets, :dependent => :destroy
|
||||
belongs_to :board
|
||||
belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
|
||||
has_many :praise_tread, as: :praise_tread_object, dependent: :destroy
|
||||
|
||||
acts_as_tree :counter_cache => :replies_count, :order => "#{Message.table_name}.created_on ASC"
|
||||
acts_as_attachable
|
||||
belongs_to :last_reply, :class_name => 'Message', :foreign_key => 'last_reply_id'
|
||||
|
||||
# added by fq
|
||||
has_many :acts, :class_name => 'Activity', :as => :act, :dependent => :destroy
|
||||
# 被ForgeActivity虚拟关联
|
||||
has_many :forge_acts, :class_name => 'ForgeActivity',:as =>:forge_act ,:dependent => :destroy
|
||||
# end
|
||||
|
||||
acts_as_searchable :columns => ['subject', 'content'],
|
||||
:include => {:board => :project},
|
||||
:project_key => "#{Board.table_name}.project_id",
|
||||
:date_column => "#{table_name}.created_on"
|
||||
acts_as_searchable :columns => ['subject', 'content'],
|
||||
:include => {:board => :course},
|
||||
:course_key => "#{Board.table_name}.course_id",
|
||||
:date_column => "#{table_name}.created_at"
|
||||
acts_as_event :title => Proc.new {|o| "#{o.board.name}: #{o.subject}"},
|
||||
:description => :content,
|
||||
:datetime => :updated_on,
|
||||
# :datetime => "#{Message.table_name}.created_on",
|
||||
:group => :parent,
|
||||
:type => Proc.new {|o| o.parent_id.nil? ? 'message' : 'reply'},
|
||||
:url => Proc.new {|o| {:controller => 'messages', :action => 'show', :board_id => o.board_id}.merge(o.parent_id.nil? ? {:id => o.id} :
|
||||
{:id => o.parent_id, :r => o.id, :anchor => "message-#{o.id}"})}
|
||||
|
||||
acts_as_activity_provider :find_options => {:include => [{:board => :project}, :author]},
|
||||
:author_key => :author_id
|
||||
acts_as_activity_provider :find_options => {:include => [{:board => :course}, :author]},
|
||||
:type => 'course_messages',
|
||||
:author_key => :author_id
|
||||
acts_as_watchable
|
||||
|
||||
validates_presence_of :board, :subject, :content
|
||||
validates_length_of :subject, :maximum => 255
|
||||
validate :cannot_reply_to_locked_topic, :on => :create
|
||||
|
||||
after_create :add_author_as_watcher, :reset_counters!
|
||||
after_update :update_messages_board
|
||||
after_destroy :reset_counters!,:down_user_score,:delete_kindeditor_assets
|
||||
|
||||
after_create :act_as_activity,:be_user_score,:act_as_forge_activity, :send_mail
|
||||
#before_save :be_user_score
|
||||
|
||||
scope :visible, lambda {|*args|
|
||||
includes(:board => :project).where(Project.allowed_to_condition(args.shift || User.current, :view_messages, *args))
|
||||
}
|
||||
|
||||
scope :course_visible, lambda {|*args|
|
||||
includes(:board => :course).where(Course.allowed_to_condition(args.shift || User.current, :view_course_messages, *args))
|
||||
}
|
||||
|
||||
|
||||
safe_attributes 'subject', 'content'
|
||||
safe_attributes 'board_id','locked', 'sticky',
|
||||
:if => lambda {|message, user|
|
||||
if message.project
|
||||
user.allowed_to?(:edit_messages, message.project)
|
||||
else
|
||||
user.allowed_to?(:edit_messages, message.course)
|
||||
end
|
||||
}
|
||||
|
||||
def visible?(user=User.current)
|
||||
if project
|
||||
!user.nil? && user.allowed_to?(:view_messages, project)
|
||||
elsif course
|
||||
!user.nil? && user.allowed_to?(:view_messages, course)
|
||||
end
|
||||
end
|
||||
|
||||
def cannot_reply_to_locked_topic
|
||||
# Can not reply to a locked topic
|
||||
errors.add :base, 'Topic is locked' if root.locked? && self != root
|
||||
end
|
||||
|
||||
def update_messages_board
|
||||
if board_id_changed?
|
||||
Message.update_all({:board_id => board_id}, ["id = ? OR parent_id = ?", root.id, root.id])
|
||||
Board.reset_counters!(board_id_was)
|
||||
Board.reset_counters!(board_id)
|
||||
end
|
||||
end
|
||||
|
||||
def reset_counters!
|
||||
if parent && parent.id
|
||||
Message.update_all({:last_reply_id => parent.children.maximum(:id)}, {:id => parent.id})
|
||||
end
|
||||
board.reset_counters!
|
||||
end
|
||||
|
||||
def sticky=(arg)
|
||||
write_attribute :sticky, (arg == true || arg.to_s == '1' ? 1 : 0)
|
||||
end
|
||||
|
||||
def sticky?
|
||||
sticky == 1
|
||||
end
|
||||
|
||||
def project
|
||||
board.project
|
||||
end
|
||||
|
||||
def course
|
||||
board.course
|
||||
end
|
||||
|
||||
def course_editable_by?(usr)
|
||||
usr && usr.logged? && (usr.allowed_to?(:edit_messages, course) || (self.author == usr && usr.allowed_to?(:edit_own_messages, course)))
|
||||
end
|
||||
|
||||
def course_destroyable_by?(usr)
|
||||
usr && usr.logged? && (usr.allowed_to?(:delete_messages, course) || (self.author == usr && usr.allowed_to?(:delete_own_messages, course)))
|
||||
end
|
||||
|
||||
def editable_by?(usr)
|
||||
usr && usr.logged? && (usr.allowed_to?(:edit_messages, project) || (self.author == usr && usr.allowed_to?(:edit_own_messages, project)))
|
||||
end
|
||||
|
||||
def destroyable_by?(usr)
|
||||
usr && usr.logged? && (usr.allowed_to?(:delete_messages, project) || (self.author == usr && usr.allowed_to?(:delete_own_messages, project)))
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def add_author_as_watcher
|
||||
Watcher.create(:watchable => self.root, :user => author)
|
||||
end
|
||||
|
||||
# fq
|
||||
def act_as_activity
|
||||
self.acts << Activity.new(:user_id => self.author_id)
|
||||
end
|
||||
# end
|
||||
|
||||
# Time 2015-02-27 14:32:25
|
||||
# Author lizanle
|
||||
# Description
|
||||
def act_as_forge_activity
|
||||
# 如果project为空,那么就是课程相关的消息
|
||||
if !self.board.project.nil?
|
||||
self.forge_acts << ForgeActivity.new(:user_id => self.author_id,
|
||||
:project_id => self.board.project.id)
|
||||
end
|
||||
end
|
||||
|
||||
#更新用户分数 -by zjc
|
||||
def be_user_score
|
||||
#新建message且无parent的为发帖
|
||||
|
||||
if self.parent_id.nil? && !self.board.project.nil?
|
||||
UserScore.joint(:post_message, self.author,nil,self, { message_id: self.id })
|
||||
update_memo_number(self.author,1)
|
||||
if self.board.project_id != -1
|
||||
update_memo_number(self.author,2,self.board.project)
|
||||
end
|
||||
#新建message且有parent的为回帖
|
||||
elsif !self.parent_id.nil? && !self.board.project.nil?
|
||||
UserScore.joint(:reply_posting, self.author,self.parent.author,self, { message_id: self.id })
|
||||
update_replay_for_memo(self.author,1)
|
||||
if self.board.project_id != -1
|
||||
update_replay_for_memo(self.author,2,self.board.project)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#减少用户分数
|
||||
def down_user_score
|
||||
if self.parent_id.nil? && !self.board.project.nil?
|
||||
UserScore.joint(:delete_message, self.author,nil,self, { message_id: self.id })
|
||||
update_memo_number(User.current,1)
|
||||
if self.board.project_id != -1
|
||||
update_memo_number(self.author,2,self.board.project)
|
||||
end
|
||||
elsif !self.parent_id.nil? && !self.board.project.nil?
|
||||
UserScore.joint(:reply_deleting, self.author,self.parent.author,self, { message_id: self.id })
|
||||
update_replay_for_memo(User.current,1)
|
||||
if self.board.project_id != -1
|
||||
update_replay_for_memo(self.author,2,self.board.project)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def send_mail
|
||||
Mailer.run.message_posted(self) if Setting.notified_events.include?('message_posted')
|
||||
end
|
||||
|
||||
# Time 2015-03-31 09:15:06
|
||||
# Author lizanle
|
||||
# Description 删除对应消息的图片资源
|
||||
def delete_kindeditor_assets
|
||||
delete_kindeditor_assets_from_disk self.id,OwnerTypeHelper::MESSAGE
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,120 +1,120 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
class News < ActiveRecord::Base
|
||||
include Redmine::SafeAttributes
|
||||
belongs_to :project
|
||||
include ApplicationHelper
|
||||
has_many_kindeditor_assets :assets, :dependent => :destroy
|
||||
#added by nwb
|
||||
belongs_to :course
|
||||
belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
|
||||
has_many :comments, :as => :commented, :dependent => :delete_all, :order => "created_on"
|
||||
# fq
|
||||
has_many :acts, :class_name => 'Activity', :as => :act, :dependent => :destroy
|
||||
# 被ForgeActivity虚拟关联
|
||||
has_many :forge_acts, :class_name => 'ForgeActivity',:as =>:forge_act ,:dependent => :destroy
|
||||
# end
|
||||
|
||||
validates_presence_of :title, :description
|
||||
validates_length_of :title, :maximum => 60
|
||||
validates_length_of :summary, :maximum => 255
|
||||
validates_length_of :description, :maximum => 10000
|
||||
|
||||
acts_as_attachable :delete_permission => :manage_news
|
||||
acts_as_searchable :columns => ['title', 'summary', "#{table_name}.description"], :include => :project
|
||||
acts_as_event :url => Proc.new {|o| {:controller => 'news', :action => 'show', :id => o.id}}
|
||||
acts_as_activity_provider :find_options => {:include => [:project, :author]},
|
||||
:author_key => :author_id
|
||||
#added by nwb
|
||||
#课程新闻独立于项目
|
||||
acts_as_activity_provider :type => 'course_news',
|
||||
:find_options => {:include => [:course, :author]},
|
||||
:author_key => :author_id
|
||||
acts_as_watchable
|
||||
|
||||
after_create :act_as_activity,:act_as_forge_activity,:add_author_as_watcher, :send_mail
|
||||
|
||||
after_destroy :delete_kindeditor_assets
|
||||
|
||||
scope :visible, lambda {|*args|
|
||||
includes(:project).where(Project.allowed_to_condition(args.shift || User.current, :view_news, *args))
|
||||
}
|
||||
|
||||
scope :course_visible, lambda {|*args|
|
||||
includes(:course).where(Course.allowed_to_condition(args.shift || User.current, :view_course_news, *args))
|
||||
}
|
||||
safe_attributes 'title', 'summary', 'description'
|
||||
|
||||
def visible?(user=User.current)
|
||||
!user.nil? && user.allowed_to?(:view_news, project)
|
||||
end
|
||||
|
||||
# Returns true if the news can be commented by user
|
||||
def commentable?(user=User.current)
|
||||
user.allowed_to?(:comment_news, project)
|
||||
end
|
||||
|
||||
def recipients
|
||||
project.users.select {|user| user.notify_about?(self)}.map(&:mail)
|
||||
end
|
||||
|
||||
# returns latest news for projects visible by user
|
||||
def self.latest(user = User.current, count = 5)
|
||||
visible(user).includes([:author, :project]).order("#{News.table_name}.created_on DESC").limit(count).all
|
||||
end
|
||||
|
||||
# 新闻的短描述信息
|
||||
def short_description(length = 255)
|
||||
description.gsub(/<\/?.*?>/,"").html_safe if description
|
||||
#description.gsub(/^(.{#{length}}[^\n\r]*).*$/m, '\1...').strip if description
|
||||
#description
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def add_author_as_watcher
|
||||
Watcher.create(:watchable => self, :user => author)
|
||||
end
|
||||
## fq
|
||||
def act_as_activity
|
||||
self.acts << Activity.new(:user_id => self.author_id)
|
||||
end
|
||||
|
||||
# Time 2015-02-27 15:48:17
|
||||
# Author lizanle
|
||||
# Description 公用表中也要记录
|
||||
def act_as_forge_activity
|
||||
# 如果是project为空,那么是课程相关的,不需要保存
|
||||
if !self.project.nil?
|
||||
self.forge_acts << ForgeActivity.new(:user_id => self.author_id,
|
||||
:project_id => self.project.id)
|
||||
end
|
||||
end
|
||||
|
||||
# Time 2015-03-31 13:50:54
|
||||
# Author lizanle
|
||||
# Description 删除news后删除对应的资源
|
||||
def delete_kindeditor_assets
|
||||
delete_kindeditor_assets_from_disk self.id,OwnerTypeHelper::NEWS
|
||||
end
|
||||
|
||||
def send_mail
|
||||
Mailer.run.news_added(self) if Setting.notified_events.include?('news_added')
|
||||
end
|
||||
|
||||
end
|
||||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
class News < ActiveRecord::Base
|
||||
include Redmine::SafeAttributes
|
||||
belongs_to :project
|
||||
include ApplicationHelper
|
||||
has_many_kindeditor_assets :assets, :dependent => :destroy
|
||||
#added by nwb
|
||||
belongs_to :course
|
||||
belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
|
||||
has_many :comments, :as => :commented, :dependent => :delete_all, :order => "created_on"
|
||||
# fq
|
||||
has_many :acts, :class_name => 'Activity', :as => :act, :dependent => :destroy
|
||||
# 被ForgeActivity虚拟关联
|
||||
has_many :forge_acts, :class_name => 'ForgeActivity',:as =>:forge_act ,:dependent => :destroy
|
||||
# end
|
||||
|
||||
validates_presence_of :title, :description
|
||||
validates_length_of :title, :maximum => 60
|
||||
validates_length_of :summary, :maximum => 255
|
||||
validates_length_of :description, :maximum => 10000
|
||||
|
||||
acts_as_attachable :delete_permission => :manage_news
|
||||
acts_as_searchable :columns => ['title', 'summary', "#{table_name}.description"], :include => :project
|
||||
acts_as_event :url => Proc.new {|o| {:controller => 'news', :action => 'show', :id => o.id}}
|
||||
acts_as_activity_provider :find_options => {:include => [:project, :author]},
|
||||
:author_key => :author_id
|
||||
#added by nwb
|
||||
#课程新闻独立于项目
|
||||
acts_as_activity_provider :type => 'course_news',
|
||||
:find_options => {:include => [:course, :author]},
|
||||
:author_key => :author_id
|
||||
acts_as_watchable
|
||||
|
||||
after_create :act_as_activity,:act_as_forge_activity,:add_author_as_watcher, :send_mail
|
||||
|
||||
after_destroy :delete_kindeditor_assets
|
||||
|
||||
scope :visible, lambda {|*args|
|
||||
includes(:project).where(Project.allowed_to_condition(args.shift || User.current, :view_news, *args))
|
||||
}
|
||||
|
||||
scope :course_visible, lambda {|*args|
|
||||
includes(:course).where(Course.allowed_to_condition(args.shift || User.current, :view_course_news, *args))
|
||||
}
|
||||
safe_attributes 'title', 'summary', 'description'
|
||||
|
||||
def visible?(user=User.current)
|
||||
!user.nil? && user.allowed_to?(:view_news, project)
|
||||
end
|
||||
|
||||
# Returns true if the news can be commented by user
|
||||
def commentable?(user=User.current)
|
||||
user.allowed_to?(:comment_news, project)
|
||||
end
|
||||
|
||||
def recipients
|
||||
project.users.select {|user| user.notify_about?(self)}.map(&:mail)
|
||||
end
|
||||
|
||||
# returns latest news for projects visible by user
|
||||
def self.latest(user = User.current, count = 5)
|
||||
visible(user).includes([:author, :project]).order("#{News.table_name}.created_on DESC").limit(count).all
|
||||
end
|
||||
|
||||
# 新闻的短描述信息
|
||||
def short_description(length = 255)
|
||||
description.gsub(/<\/?.*?>/,"").html_safe if description
|
||||
#description.gsub(/^(.{#{length}}[^\n\r]*).*$/m, '\1...').strip if description
|
||||
#description
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def add_author_as_watcher
|
||||
Watcher.create(:watchable => self, :user => author)
|
||||
end
|
||||
## fq
|
||||
def act_as_activity
|
||||
self.acts << Activity.new(:user_id => self.author_id)
|
||||
end
|
||||
|
||||
# Time 2015-02-27 15:48:17
|
||||
# Author lizanle
|
||||
# Description 公用表中也要记录
|
||||
def act_as_forge_activity
|
||||
# 如果是project为空,那么是课程相关的,不需要保存
|
||||
if !self.project.nil?
|
||||
self.forge_acts << ForgeActivity.new(:user_id => self.author_id,
|
||||
:project_id => self.project.id)
|
||||
end
|
||||
end
|
||||
|
||||
# Time 2015-03-31 13:50:54
|
||||
# Author lizanle
|
||||
# Description 删除news后删除对应的资源
|
||||
def delete_kindeditor_assets
|
||||
delete_kindeditor_assets_from_disk self.id,OwnerTypeHelper::NEWS
|
||||
end
|
||||
|
||||
def send_mail
|
||||
Mailer.run.news_added(self) if Setting.notified_events.include?('news_added')
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -7,22 +7,24 @@ class Poll < ActiveRecord::Base
|
|||
has_many :poll_users, :dependent => :destroy
|
||||
has_many :users, :through => :poll_users #该文件被哪些用户提交答案过
|
||||
# 添加课程的poll动态
|
||||
# has_many :acts, :class_name => 'Activity', :as => :act, :dependent => :destroy
|
||||
# after_create :act_as_activity
|
||||
has_many :acts, :class_name => 'Activity', :as => :act, :dependent => :destroy
|
||||
after_create :act_as_activity
|
||||
|
||||
# acts_as_event :title => Proc.new {|o| "#{l(:label_my_message)} ##{o.id}: #{o.name}" },
|
||||
# :description => :description,
|
||||
# :author => :author,
|
||||
# :url => Proc.new {|o| {:controller => 'poll', :action => 'show', :id => o.id}}
|
||||
acts_as_event :title => Proc.new {|o| "#{l(:label_course_poll)}: #{o.polls_name}" },
|
||||
:description => :polls_description,
|
||||
:datetime => :published_at,
|
||||
:author => :user,
|
||||
:url => Proc.new {|o| {:controller => 'poll', :action => 'show', :id => o.id}}
|
||||
|
||||
# acts_as_activity_provider :type => 'polls',
|
||||
# :permission => :view_course_polls,
|
||||
#:find_options => {:include => [:course, :author]},
|
||||
#:timestamp => "#{self.table_name}.published_at",
|
||||
# :author_key => :author_id
|
||||
acts_as_activity_provider :type => 'polls',
|
||||
#:permission => :view_course_polls,
|
||||
:find_options => {:select => "#{Poll.table_name}.*",
|
||||
:joins => "LEFT JOIN #{Course.table_name} ON ( #{Poll.table_name}.polls_type='Course' AND #{Poll.table_name}.polls_status= 2 AND #{Poll.table_name}.polls_group_id = #{Course.table_name}.id )"},
|
||||
:timestamp => "#{self.table_name}.published_at",
|
||||
:author_key => :user_id
|
||||
|
||||
# def act_as_activity
|
||||
# self.acts << Activity.new(:user_id => self.user_id)
|
||||
# end
|
||||
def act_as_activity
|
||||
self.acts << Activity.new(:user_id => self.user_id)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -19,6 +19,7 @@ class Principal < ActiveRecord::Base
|
|||
self.table_name = "#{table_name_prefix}users#{table_name_suffix}"
|
||||
|
||||
# Account statuses
|
||||
# 0 全部;1 活动的; 2 已注册; 3 锁定
|
||||
STATUS_ANONYMOUS = 0
|
||||
STATUS_ACTIVE = 1
|
||||
STATUS_REGISTERED = 2
|
||||
|
|
|
@ -51,7 +51,7 @@ class Project < ActiveRecord::Base
|
|||
has_many :issue_categories, :dependent => :delete_all, :order => "#{IssueCategory.table_name}.name"
|
||||
has_many :boards, :dependent => :destroy, :order => "position ASC"
|
||||
has_one :repository, :conditions => ["is_default = ?", true]
|
||||
has_many :repositories, :dependent => :destroy
|
||||
has_many :repositories, :dependent => :destroy, conditions: "hidden=false"
|
||||
has_many :changesets, :through => :repository
|
||||
#added by xianbo for delete biding_project
|
||||
has_many :biding_projects, :dependent => :destroy
|
||||
|
|
|
@ -1,199 +1,199 @@
|
|||
class RelativeMemo < ActiveRecord::Base
|
||||
# attr_accessible :title, :body
|
||||
include Redmine::SafeAttributes
|
||||
belongs_to :open_source_project, :class_name => "OpenSourceProject", :foreign_key => 'osp_id'
|
||||
belongs_to :author, :class_name => "User", :foreign_key => 'author_id'
|
||||
|
||||
has_many :tags, :through => :project_tags, :class_name => 'Tag'
|
||||
has_many :project_tags, :class_name => 'ProjectTags'
|
||||
|
||||
has_many :relation_topics, :class_name => 'RelativeMemoToOpenSourceProject'
|
||||
|
||||
has_many :no_uses, :as => :no_use, :dependent => :delete_all
|
||||
|
||||
has_many :bugs_to_osp, :class_name => 'BugToOsp', :foreign_key => 'relative_memo_id', :dependent => :destroy
|
||||
|
||||
|
||||
acts_as_taggable
|
||||
|
||||
validates_presence_of :subject
|
||||
#validates :content, presence: true
|
||||
# validates_length_of :subject, maximum: 50
|
||||
#validates_length_of :content, maximum: 3072
|
||||
validate :cannot_reply_to_locked_topic, :on => :create
|
||||
validates_uniqueness_of :osp_id, :scope => [:subject, :content]
|
||||
|
||||
acts_as_tree :counter_cache => :replies_count, :order => "#{RelativeMemo.table_name}.created_at ASC"
|
||||
acts_as_attachable
|
||||
belongs_to :last_reply, :class_name => 'RelativeMemo', :foreign_key => 'last_reply_id'
|
||||
# acts_as_searchable :column => ['subject', 'content'],
|
||||
# #:include => { :forum => :p}
|
||||
# #:project_key => "#{Forum.table_name}.project_id"
|
||||
# :date_column => "#{table_name}.created_at"
|
||||
|
||||
# acts_as_event :title => Proc.new {|o| "#{o.forum.name}: #{o.subject}"},
|
||||
# :datetime => :updated_at,
|
||||
# # :datetime => :created_at,
|
||||
# :description => :content,
|
||||
# :author => :author,
|
||||
# :type => Proc.new {|o| o.parent_id.nil? ? 'Memo' : 'Reply'},
|
||||
# :url => Proc.new {|o| {:controller => 'memos', :action => 'show', :forum_id => o.forum_id}.merge(o.parent_id.nil? ? {:id => o.id} : {:id => o.parent_id, :r => o.id, :anchor => "reply-#{o.id}"})}
|
||||
# acts_as_activity_provider :author_key => :author_id,
|
||||
# :func => 'memos',
|
||||
# :timestamp => 'created_at'
|
||||
|
||||
# :find_options => {:type => 'memos'}
|
||||
# acts_as_watchable
|
||||
|
||||
safe_attributes "author_id",
|
||||
"subject",
|
||||
"content",
|
||||
"osp_id",
|
||||
"last_memo_id",
|
||||
"lock",
|
||||
"sticky",
|
||||
"parent_id",
|
||||
"replies_count",
|
||||
"is_quote"
|
||||
|
||||
after_create :add_author_as_watcher, :reset_counters!
|
||||
# after_update :update_memos_forum
|
||||
after_destroy :reset_counters!
|
||||
# after_create :send_notification
|
||||
# after_save :plusParentAndForum
|
||||
# after_destroy :minusParentAndForum
|
||||
|
||||
# scope :visible, lambda { |*args|
|
||||
# includes(:forum => ).where()
|
||||
# }
|
||||
|
||||
def cannot_reply_to_locked_topic
|
||||
errors.add :base, l(:label_memo_locked) if root.locked? && self != root
|
||||
end
|
||||
|
||||
def short_content(length = 25)
|
||||
str = "^(.{,#{length}})[^\n\r]*.*$"
|
||||
content.gsub(Regexp.new(str), '\1...').strip if content
|
||||
end
|
||||
|
||||
# def update_memos_forum
|
||||
# if forum_id_changed?
|
||||
# Message.update_all({:board_id => board_id}, ["id = ? OR parent_id = ?", root.id, root.id ])
|
||||
# Forum.reset_counters!(forum_id_was)
|
||||
# Forum.reset_counters!(forum_id)
|
||||
# end
|
||||
# end
|
||||
|
||||
|
||||
scope :no_use_for, lambda { |user_id|
|
||||
{ :include => :no_uses,
|
||||
:conditions => ["#{NoUse.table_name}.user_id = ?", user_id] }
|
||||
}
|
||||
|
||||
# 获取帖子的回复
|
||||
def replies
|
||||
memos = RelativeMemo.where("parent_id = ?", id)
|
||||
end
|
||||
|
||||
def no_use_for?(user)
|
||||
self.no_uses.each do |no_use|
|
||||
if no_use.user_id == user.id
|
||||
return true
|
||||
end
|
||||
end
|
||||
false
|
||||
end
|
||||
|
||||
def set_no_use(user, flag=true)
|
||||
flag ? set_filter(user) : remove_filter(user)
|
||||
end
|
||||
|
||||
def set_filter(user)
|
||||
self.no_uses << NoUse.new(:user => user)
|
||||
end
|
||||
|
||||
def remove_filter(user)
|
||||
return nil unless user && user.is_a?(User)
|
||||
NoUse.delete_all "no_use_type = '#{self.class}' AND no_use_id = #{self.id} AND user_id = #{user.id}"
|
||||
end
|
||||
|
||||
def reset_counters!
|
||||
if parent && parent.id
|
||||
RelativeMemo.update_all({:last_reply_id => parent.children.maximum(:id)}, {:id => parent.id})
|
||||
parent.update_attribute(:updated_at, Time.now)
|
||||
end
|
||||
# forum.reset_counters!
|
||||
end
|
||||
|
||||
def sticky?
|
||||
sticky == 1
|
||||
end
|
||||
|
||||
def replies
|
||||
RelativeMemo.where("parent_id = ?", id)
|
||||
end
|
||||
|
||||
def locked?
|
||||
self.lock
|
||||
end
|
||||
|
||||
def editable_by? user
|
||||
# user && user.logged? || (self.author == usr && usr.allowed_to?(:edit_own_messages, project))
|
||||
user.admin?
|
||||
end
|
||||
|
||||
# def destroyable_by? user
|
||||
# (user && user.logged? && (Forum.find(self.forum_id).creator_id == user.id) ) || user.admin?
|
||||
# #self.author == user || user.admin?
|
||||
# end
|
||||
|
||||
def deleted_attach_able_by? user
|
||||
(user && user.logged? && (self.author == user) ) || user.admin?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def add_author_as_watcher
|
||||
Watcher.create(:watchable => self.root, :user => author)
|
||||
end
|
||||
|
||||
def send_notification
|
||||
if Setting.notified_events.include?('message_posted')
|
||||
Mailer.run.message_posted(self)
|
||||
end
|
||||
end
|
||||
|
||||
# def plusParentAndForum
|
||||
# @forum = Forum.find(self.forum_id)
|
||||
# @forum.memo_count = @forum.memo_count.to_int + 1
|
||||
# @forum.last_memo_id = self.id
|
||||
# if self.parent_id
|
||||
# @parent_memo = Memo.find_by_id(self.parent_id)
|
||||
# @parent_memo.last_reply_id = self
|
||||
# @parent_memo.replies_count = @parent_memo.replies_count.to_int + 1
|
||||
# @parent_memo.save
|
||||
# else
|
||||
# @forum.topic_count = @forum.topic_count.to_int + 1
|
||||
# end
|
||||
# @forum.save
|
||||
# end
|
||||
|
||||
# def minusParentAndForum
|
||||
# @forum = Forum.find(self.forum_id)
|
||||
# @forum.memo_count = @forum.memo_count.to_int - 1
|
||||
# @forum.memo_count = 0 if @forum.memo_count.to_int < 0
|
||||
# # @forum.last_memo_id = Memo.reorder('created_at ASC').find_all_by_forum_id(self.forum_id).last.id
|
||||
# if self.parent_id
|
||||
# @parent_memo = Memo.find_by_id(self.parent_id)
|
||||
# # @parent_memo.last_reply_id = Memo.reorder('created_at ASC').find_all_by_parent_id(self.parent_id).last.id
|
||||
# @parent_memo.replies_count = @parent_memo.replies_count.to_int - 1
|
||||
# @parent_memo.replies_count = 0 if @parent_memo.replies_count.to_int < 0
|
||||
# @parent_memo.save
|
||||
# else
|
||||
# @forum.topic_count = @forum.topic_count.to_int - 1
|
||||
# @forum.topic_count = 0 if @forum.topic_count.to_int < 0
|
||||
# end
|
||||
# @forum.save
|
||||
# end
|
||||
end
|
||||
|
||||
class RelativeMemo < ActiveRecord::Base
|
||||
# attr_accessible :title, :body
|
||||
include Redmine::SafeAttributes
|
||||
belongs_to :open_source_project, :class_name => "OpenSourceProject", :foreign_key => 'osp_id'
|
||||
belongs_to :author, :class_name => "User", :foreign_key => 'author_id'
|
||||
|
||||
has_many :tags, :through => :project_tags, :class_name => 'Tag'
|
||||
has_many :project_tags, :class_name => 'ProjectTags'
|
||||
|
||||
has_many :relation_topics, :class_name => 'RelativeMemoToOpenSourceProject'
|
||||
|
||||
has_many :no_uses, :as => :no_use, :dependent => :delete_all
|
||||
|
||||
has_many :bugs_to_osp, :class_name => 'BugToOsp', :foreign_key => 'relative_memo_id', :dependent => :destroy
|
||||
|
||||
|
||||
acts_as_taggable
|
||||
|
||||
validates_presence_of :subject
|
||||
#validates :content, presence: true
|
||||
# validates_length_of :subject, maximum: 50
|
||||
#validates_length_of :content, maximum: 3072
|
||||
validate :cannot_reply_to_locked_topic, :on => :create
|
||||
validates_uniqueness_of :osp_id, :scope => [:subject, :content]
|
||||
|
||||
acts_as_tree :counter_cache => :replies_count, :order => "#{RelativeMemo.table_name}.created_at ASC"
|
||||
acts_as_attachable
|
||||
belongs_to :last_reply, :class_name => 'RelativeMemo', :foreign_key => 'last_reply_id'
|
||||
# acts_as_searchable :column => ['subject', 'content'],
|
||||
# #:include => { :forum => :p}
|
||||
# #:project_key => "#{Forum.table_name}.project_id"
|
||||
# :date_column => "#{table_name}.created_at"
|
||||
|
||||
# acts_as_event :title => Proc.new {|o| "#{o.forum.name}: #{o.subject}"},
|
||||
# :datetime => :updated_at,
|
||||
# # :datetime => :created_at,
|
||||
# :description => :content,
|
||||
# :author => :author,
|
||||
# :type => Proc.new {|o| o.parent_id.nil? ? 'Memo' : 'Reply'},
|
||||
# :url => Proc.new {|o| {:controller => 'memos', :action => 'show', :forum_id => o.forum_id}.merge(o.parent_id.nil? ? {:id => o.id} : {:id => o.parent_id, :r => o.id, :anchor => "reply-#{o.id}"})}
|
||||
# acts_as_activity_provider :author_key => :author_id,
|
||||
# :func => 'memos',
|
||||
# :timestamp => 'created_at'
|
||||
|
||||
# :find_options => {:type => 'memos'}
|
||||
# acts_as_watchable
|
||||
|
||||
safe_attributes "author_id",
|
||||
"subject",
|
||||
"content",
|
||||
"osp_id",
|
||||
"last_memo_id",
|
||||
"lock",
|
||||
"sticky",
|
||||
"parent_id",
|
||||
"replies_count",
|
||||
"is_quote"
|
||||
|
||||
after_create :add_author_as_watcher, :reset_counters!
|
||||
# after_update :update_memos_forum
|
||||
after_destroy :reset_counters!
|
||||
# after_create :send_notification
|
||||
# after_save :plusParentAndForum
|
||||
# after_destroy :minusParentAndForum
|
||||
|
||||
# scope :visible, lambda { |*args|
|
||||
# includes(:forum => ).where()
|
||||
# }
|
||||
|
||||
def cannot_reply_to_locked_topic
|
||||
errors.add :base, l(:label_memo_locked) if root.locked? && self != root
|
||||
end
|
||||
|
||||
def short_content(length = 25)
|
||||
str = "^(.{,#{length}})[^\n\r]*.*$"
|
||||
content.gsub(Regexp.new(str), '\1...').strip if content
|
||||
end
|
||||
|
||||
# def update_memos_forum
|
||||
# if forum_id_changed?
|
||||
# Message.update_all({:board_id => board_id}, ["id = ? OR parent_id = ?", root.id, root.id ])
|
||||
# Forum.reset_counters!(forum_id_was)
|
||||
# Forum.reset_counters!(forum_id)
|
||||
# end
|
||||
# end
|
||||
|
||||
|
||||
scope :no_use_for, lambda { |user_id|
|
||||
{ :include => :no_uses,
|
||||
:conditions => ["#{NoUse.table_name}.user_id = ?", user_id] }
|
||||
}
|
||||
|
||||
# 获取帖子的回复
|
||||
def replies
|
||||
memos = RelativeMemo.where("parent_id = ?", id)
|
||||
end
|
||||
|
||||
def no_use_for?(user)
|
||||
self.no_uses.each do |no_use|
|
||||
if no_use.user_id == user.id
|
||||
return true
|
||||
end
|
||||
end
|
||||
false
|
||||
end
|
||||
|
||||
def set_no_use(user, flag=true)
|
||||
flag ? set_filter(user) : remove_filter(user)
|
||||
end
|
||||
|
||||
def set_filter(user)
|
||||
self.no_uses << NoUse.new(:user => user)
|
||||
end
|
||||
|
||||
def remove_filter(user)
|
||||
return nil unless user && user.is_a?(User)
|
||||
NoUse.delete_all "no_use_type = '#{self.class}' AND no_use_id = #{self.id} AND user_id = #{user.id}"
|
||||
end
|
||||
|
||||
def reset_counters!
|
||||
if parent && parent.id
|
||||
RelativeMemo.update_all({:last_reply_id => parent.children.maximum(:id)}, {:id => parent.id})
|
||||
parent.update_attribute(:updated_at, Time.now)
|
||||
end
|
||||
# forum.reset_counters!
|
||||
end
|
||||
|
||||
def sticky?
|
||||
sticky == 1
|
||||
end
|
||||
|
||||
def replies
|
||||
RelativeMemo.where("parent_id = ?", id)
|
||||
end
|
||||
|
||||
def locked?
|
||||
self.lock
|
||||
end
|
||||
|
||||
def editable_by? user
|
||||
# user && user.logged? || (self.author == usr && usr.allowed_to?(:edit_own_messages, project))
|
||||
user.admin?
|
||||
end
|
||||
|
||||
# def destroyable_by? user
|
||||
# (user && user.logged? && (Forum.find(self.forum_id).creator_id == user.id) ) || user.admin?
|
||||
# #self.author == user || user.admin?
|
||||
# end
|
||||
|
||||
def deleted_attach_able_by? user
|
||||
(user && user.logged? && (self.author == user) ) || user.admin?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def add_author_as_watcher
|
||||
Watcher.create(:watchable => self.root, :user => author)
|
||||
end
|
||||
|
||||
def send_notification
|
||||
if Setting.notified_events.include?('message_posted')
|
||||
Mailer.run.message_posted(self)
|
||||
end
|
||||
end
|
||||
|
||||
# def plusParentAndForum
|
||||
# @forum = Forum.find(self.forum_id)
|
||||
# @forum.memo_count = @forum.memo_count.to_int + 1
|
||||
# @forum.last_memo_id = self.id
|
||||
# if self.parent_id
|
||||
# @parent_memo = Memo.find_by_id(self.parent_id)
|
||||
# @parent_memo.last_reply_id = self
|
||||
# @parent_memo.replies_count = @parent_memo.replies_count.to_int + 1
|
||||
# @parent_memo.save
|
||||
# else
|
||||
# @forum.topic_count = @forum.topic_count.to_int + 1
|
||||
# end
|
||||
# @forum.save
|
||||
# end
|
||||
|
||||
# def minusParentAndForum
|
||||
# @forum = Forum.find(self.forum_id)
|
||||
# @forum.memo_count = @forum.memo_count.to_int - 1
|
||||
# @forum.memo_count = 0 if @forum.memo_count.to_int < 0
|
||||
# # @forum.last_memo_id = Memo.reorder('created_at ASC').find_all_by_forum_id(self.forum_id).last.id
|
||||
# if self.parent_id
|
||||
# @parent_memo = Memo.find_by_id(self.parent_id)
|
||||
# # @parent_memo.last_reply_id = Memo.reorder('created_at ASC').find_all_by_parent_id(self.parent_id).last.id
|
||||
# @parent_memo.replies_count = @parent_memo.replies_count.to_int - 1
|
||||
# @parent_memo.replies_count = 0 if @parent_memo.replies_count.to_int < 0
|
||||
# @parent_memo.save
|
||||
# else
|
||||
# @forum.topic_count = @forum.topic_count.to_int - 1
|
||||
# @forum.topic_count = 0 if @forum.topic_count.to_int < 0
|
||||
# end
|
||||
# @forum.save
|
||||
# end
|
||||
end
|
||||
|
||||
|
|
|
@ -27,6 +27,14 @@ class Token < ActiveRecord::Base
|
|||
self.value = Token.generate_token_value
|
||||
end
|
||||
|
||||
def self.get_token_from_user(user, action)
|
||||
token = Token.where(:action => action, :user_id => user).first
|
||||
unless token
|
||||
token = Token.create(user: user, action: action)
|
||||
end
|
||||
token
|
||||
end
|
||||
|
||||
# Return true if token has expired
|
||||
def expired?
|
||||
return Time.now > self.created_on + @@validity_time
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
class WikiContentObserver < ActiveRecord::Observer
|
||||
def after_create(wiki_content)
|
||||
Mailer.run.wiki_content_added(wiki_content) if Setting.notified_events.include?('wiki_content_added')
|
||||
end
|
||||
|
||||
def after_update(wiki_content)
|
||||
if wiki_content.text_changed?
|
||||
Mailer.run.wiki_content_updated(wiki_content) if Setting.notified_events.include?('wiki_content_updated')
|
||||
end
|
||||
end
|
||||
end
|
||||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
class WikiContentObserver < ActiveRecord::Observer
|
||||
def after_create(wiki_content)
|
||||
Mailer.run.wiki_content_added(wiki_content) if Setting.notified_events.include?('wiki_content_added')
|
||||
end
|
||||
|
||||
def after_update(wiki_content)
|
||||
if wiki_content.text_changed?
|
||||
Mailer.run.wiki_content_updated(wiki_content) if Setting.notified_events.include?('wiki_content_updated')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
class ZipPack < ActiveRecord::Base
|
||||
# attr_accessible :title, :body
|
||||
|
||||
def self.packed?(bid_id, user_id, digests)
|
||||
zip_pack = ZipPack.where(homework_id: bid_id, user_id: user_id).first
|
||||
return false unless zip_pack && zip_pack.digests == digests
|
||||
zip_pack
|
||||
end
|
||||
|
||||
def file_valid?
|
||||
return false unless File.exist?(self.file_path)
|
||||
Trustie::Utils.digest(self.file_path) == self.file_digest
|
||||
end
|
||||
|
||||
def digests
|
||||
self.file_digests.split(',').sort
|
||||
end
|
||||
end
|
||||
class ZipPack < ActiveRecord::Base
|
||||
# attr_accessible :title, :body
|
||||
|
||||
def self.packed?(bid_id, user_id, digests)
|
||||
zip_pack = ZipPack.where(homework_id: bid_id, user_id: user_id).first
|
||||
return false unless zip_pack && zip_pack.digests == digests
|
||||
zip_pack
|
||||
end
|
||||
|
||||
def file_valid?
|
||||
return false unless File.exist?(self.file_path)
|
||||
Trustie::Utils.digest(self.file_path) == self.file_digest
|
||||
end
|
||||
|
||||
def digests
|
||||
self.file_digests.split(',').sort
|
||||
end
|
||||
end
|
||||
|
|
|
@ -428,6 +428,17 @@ class CoursesService
|
|||
result
|
||||
end
|
||||
|
||||
# 课程课件
|
||||
def course_attachments params
|
||||
result = []
|
||||
@course = Course.find(params[:course_id])
|
||||
@attachments = @course.attachments.order("created_on desc")
|
||||
@attachments.each do |atta|
|
||||
result << {:filename => atta.filename,:description => atta.description,:downloads => atta.downloads,:quotes => atta.quotes.nil? ? 0 :atta.quotes }
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
private
|
||||
def show_homework_info course,bid,current_user,is_course_teacher
|
||||
author_real_name = bid.author.lastname + bid.author.firstname
|
||||
|
|
|
@ -44,12 +44,14 @@ class UsersService
|
|||
#location = get_user_location @user
|
||||
#{:id => @user.id, :img_url => img_url, :nickname => @user.login, :gender => gender, :work_unit => work_unit, :mail => @user.mail, :location => location, :brief_introduction => @user.user_extensions.brief_introduction}
|
||||
end
|
||||
|
||||
# 自动注册功能 FOR:邮件邀请
|
||||
def register_auto(login,mail,password)
|
||||
@user = User.new
|
||||
@user.admin = false
|
||||
@user.register
|
||||
@user.login = login
|
||||
@user.mail =mail
|
||||
@user.mail = mail
|
||||
password_confirmation = password
|
||||
should_confirmation_password = true
|
||||
if !password.blank? && !password_confirmation.blank? && should_confirmation_password
|
||||
|
@ -59,9 +61,7 @@ class UsersService
|
|||
else
|
||||
@user.password = ""
|
||||
end
|
||||
|
||||
@user = automatically_register(@user)
|
||||
|
||||
if @user.id != nil
|
||||
ue = @user.user_extensions ||= UserExtensions.new
|
||||
ue.user_id = @user.id
|
||||
|
@ -69,6 +69,7 @@ class UsersService
|
|||
end
|
||||
@user
|
||||
end
|
||||
|
||||
#显示用户
|
||||
#id用户id
|
||||
def show_user(params)
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
#coding=utf-8
|
||||
#
|
||||
|
||||
class DestroyRepositoryTask
|
||||
def destroy(user_id, rep_id)
|
||||
user = User.find(user_id)
|
||||
repository = Repository.find(rep_id)
|
||||
|
||||
Rails.logger.info "start delete repository #{user} #{repository}"
|
||||
@root_path=RepositoriesHelper::ROOT_PATH
|
||||
@repo_name=user.login.to_s+"_"+repository.identifier.to_s
|
||||
@repository_name=user.login.to_s+"/"+repository.identifier.to_s+".git"
|
||||
@middle=user.login.to_s+"_"+repository.identifier.to_s+"-write:"
|
||||
repository.destroy
|
||||
if(repository.type=="Repository::Git")
|
||||
Rails.logger.info "destory the repository value"+"root path"+@root_path+"repo_name"+@repo_name+
|
||||
"repository_name"+@repository_name+"user group"+@middle
|
||||
system "sed -i /"+@repo_name+"/{d} "+@root_path+"htdocs/user.passwd"
|
||||
system "sed -i /"+@middle+"/{d} "+@root_path+"htdocs/group.passwd"
|
||||
system "rm -r "+@root_path+"htdocs/"+@repository_name
|
||||
end
|
||||
end
|
||||
|
||||
handle_asynchronously :destroy,:queue => 'repository'
|
||||
end
|
|
@ -68,7 +68,7 @@
|
|||
<td align="left">
|
||||
<% if Setting.autologin? %>
|
||||
<label for="autologin">
|
||||
<%= check_box_tag 'autologin', 1, false, :tabindex => 4 %>
|
||||
<%= check_box_tag 'autologin', 1, true, :tabindex => 4 %>
|
||||
<%= l(:label_stay_logged_in) %>
|
||||
</label>
|
||||
<% end %>
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
<div class="fl">
|
||||
<span id="attachments_fields" xmlns="http://www.w3.org/1999/html">
|
||||
<% if defined?(container) && container && container.saved_attachments %>
|
||||
<% container.attachments.each_with_index do |attachment, i| %>
|
||||
<span id="attachments_p<%= i %>" class="attachment">
|
||||
<%= text_field_tag("attachments[p#{i}][filename]", attachment.filename, :class => 'filename readonly', :readonly=>'readonly')%>
|
||||
<%= text_field_tag("attachments[p#{i}][description]", attachment.description, :maxlength => 254, :placeholder => l(:label_optional_description), :class => 'description', :style=>"display: inline-block;") %>
|
||||
<span class="ispublic-label"><%= l(:field_is_public)%>:</span>
|
||||
<%= check_box_tag("attachments[p#{i}][is_public_checkbox]", attachment.is_public,attachment.is_public == 1 ? true : false,:class => 'is_public')%>
|
||||
<%= text_field_tag("attachments[p#{i}][filename]", attachment.filename, :class => 'filename readonly', :readonly => 'readonly') %>
|
||||
<%= text_field_tag("attachments[p#{i}][description]", attachment.description, :maxlength => 254, :placeholder => l(:label_optional_description), :class => 'description', :style => "display: inline-block;") %>
|
||||
<span class="ispublic-label"><%= l(:field_is_public) %>:</span>
|
||||
<%= check_box_tag("attachments[p#{i}][is_public_checkbox]", attachment.is_public, attachment.is_public == 1 ? true : false, :class => 'is_public') %>
|
||||
<%= if attachment.id.nil?
|
||||
#待补充代码
|
||||
else
|
||||
|
@ -17,48 +18,56 @@
|
|||
<%= hidden_field_tag "attachments[p#{i}][token]", "#{attachment.token}" %>
|
||||
</span>
|
||||
<% end %>
|
||||
<% container.saved_attachments.each_with_index do |attachment, i| %>
|
||||
<span id="attachments_p<%= i %>" class="attachment">
|
||||
<%= text_field_tag("attachments[p#{i}][filename]", attachment.filename, :class => 'filename readonly', :readonly => 'readonly') %>
|
||||
<%= text_field_tag("attachments[p#{i}][description]", attachment.description, :maxlength => 254, :placeholder => l(:label_optional_description), :class => 'description', :style => "display: inline-block;") %>
|
||||
<span class="ispublic-label"><%= l(:field_is_public) %>:</span>
|
||||
<%= check_box_tag("attachments[p#{i}][is_public_checkbox]", attachment.is_public, attachment.is_public == 1 ? true : false, :class => 'is_public') %>
|
||||
<%= if attachment.id.nil?
|
||||
#待补充代码
|
||||
else
|
||||
link_to(' '.html_safe, attachment_path(attachment, :attachment_id => "p#{i}", :format => 'js'), :method => 'delete', :remote => true, :class => 'remove-upload')
|
||||
end
|
||||
%>
|
||||
<%#= render :partial => 'tags/tag', :locals => {:obj => attachment, :object_flag => "6"} %>
|
||||
|
||||
<%= hidden_field_tag "attachments[p#{i}][token]", "#{attachment.token}" %>
|
||||
</span>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</span>
|
||||
<script type='text/javascript'>
|
||||
// function CompatibleSend()
|
||||
// {
|
||||
// var obj=document.getElementById("_file");
|
||||
// var file= $(obj).clone();
|
||||
// file.click();
|
||||
// }
|
||||
</script>
|
||||
<% project = project %>
|
||||
<span class="add_attachment" style="font-weight:normal;">
|
||||
<% project = project %>
|
||||
<span class="add_attachment" style="font-weight:normal;">
|
||||
<%#= button_tag "浏览", :type=>"button", :onclick=>"CompatibleSend();" %>
|
||||
<!--%= link_to image_tag(),"javascript:void(0)", :onclick => "_file.click()"%-->
|
||||
<%= button_tag l(:button_browse), :type=>"button", :onclick=>"_file.click()",:onmouseover => 'this.focus()', :style => ie8? ? 'display:none' : '' %>
|
||||
<%= button_tag "文件浏览", :type=>"button", :onclick=>"$('#_file').click();",:onmouseover => 'this.focus()',:class => 'sub_btn' %>
|
||||
<%= file_field_tag 'attachments[dummy][file]',
|
||||
:id => '_file',
|
||||
:class => 'file_selector',
|
||||
:multiple => true,
|
||||
:onchange => 'addInputFiles(this);',
|
||||
:style => ie8? ? '' : 'display:none',
|
||||
:data => {
|
||||
:max_file_size => Setting.attachment_max_size.to_i.kilobytes,
|
||||
:max_file_size_message => l(:error_attachment_too_big, :max_size => number_to_human_size(Setting.attachment_max_size.to_i.kilobytes)),
|
||||
:max_concurrent_uploads => Redmine::Configuration['max_concurrent_ajax_uploads'].to_i,
|
||||
:upload_path => uploads_path(:format => 'js',:project =>project),
|
||||
:description_placeholder => l(:label_optional_description),
|
||||
:field_is_public => l(:field_is_public),
|
||||
:are_you_sure => l(:text_are_you_sure),
|
||||
:file_count => l(:label_file_count),
|
||||
:delete_all_files => l(:text_are_you_sure_all)
|
||||
} %>
|
||||
:id => '_file',
|
||||
:class => 'file_selector',
|
||||
:multiple => true,
|
||||
:onchange => 'addInputFiles(this);',
|
||||
:style => ie8? ? '' : 'display:none',
|
||||
:data => {
|
||||
:max_file_size => Setting.attachment_max_size.to_i.kilobytes,
|
||||
:max_file_size_message => l(:error_attachment_too_big, :max_size => number_to_human_size(Setting.attachment_max_size.to_i.kilobytes)),
|
||||
:max_concurrent_uploads => Redmine::Configuration['max_concurrent_ajax_uploads'].to_i,
|
||||
:upload_path => uploads_path(:format => 'js', :project => project),
|
||||
:description_placeholder => l(:label_optional_description),
|
||||
:field_is_public => l(:field_is_public),
|
||||
:are_you_sure => l(:text_are_you_sure),
|
||||
:file_count => l(:label_file_count),
|
||||
:delete_all_files => l(:text_are_you_sure_all)
|
||||
} %>
|
||||
<span id="upload_file_count">
|
||||
<%= l(:label_no_file_uploaded)%>
|
||||
<%= l(:label_no_file_uploaded) %>
|
||||
</span>
|
||||
(<%= l(:label_max_size) %>:
|
||||
<%= number_to_human_size(Setting.attachment_max_size.to_i.kilobytes) %>)
|
||||
</span>
|
||||
|
||||
<% content_for :header_tags do %>
|
||||
<%= javascript_include_tag 'attachments' %>
|
||||
<% end %>
|
||||
|
||||
<% content_for :header_tags do %>
|
||||
<%= javascript_include_tag 'attachments' %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
<span id="attachments_fields" xmlns="http://www.w3.org/1999/html">
|
||||
<% if defined?(container) && container && container.saved_attachments %>
|
||||
<% if isReply %>
|
||||
<% container.saved_attachments.each_with_index do |attachment, i| %>
|
||||
<span id="attachments_p<%= i %>" class="sub_btn">
|
||||
<%= text_field_tag("attachments[p#{i}][filename]", attachment.filename, :class => 'filename readonly', :readonly=>'readonly')%>
|
||||
<%= text_field_tag("attachments[p#{i}][description]", attachment.description, :maxlength => 255, :placeholder => l(:label_optional_description), :class => 'description', :style=>"display: inline-block;") +
|
||||
link_to(' '.html_safe, attachment_path(attachment, :attachment_id => "p#{i}", :format => 'js'), :method => 'delete', :remote => true, :class => 'remove-upload') %>
|
||||
<%#= render :partial => 'tags/tag', :locals => {:obj => attachment, :object_flag => "6"} %>
|
||||
<span class="ispublic-label"><%= l(:field_is_public)%>:</span>
|
||||
<%= check_box_tag("attachments[p#{i}][is_public_checkbox]", attachment.is_public,attachment.is_public == 1 ? true : false, :class => 'is_public')%>
|
||||
<%= hidden_field_tag "attachments[p#{i}][token]", "#{attachment.token}" %>
|
||||
</span>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<% container.attachments.each_with_index do |attachment, i| %>
|
||||
<span id="attachments_p<%= i %>" class="attachment">
|
||||
<%= text_field_tag("attachments[p#{i}][filename]", attachment.filename, :class => 'filename readonly', :readonly=>'readonly')%>
|
||||
<%= text_field_tag("attachments[p#{i}][description]", attachment.description, :maxlength => 255, :placeholder => l(:label_optional_description), :class => 'description', :style=>"display: inline-block;") +
|
||||
link_to(' '.html_safe, attachment_path(attachment, :attachment_id => "p#{i}", :format => 'js'), :method => 'delete', :remote => true, :class => 'remove-upload') %>
|
||||
<%#= render :partial => 'tags/tag', :locals => {:obj => attachment, :object_flag => "6"} %>
|
||||
<span class="ispublic-label"><%= l(:field_is_public)%>:</span>
|
||||
<%= check_box_tag("attachments[p#{i}][is_public_checkbox]", attachment.is_public,attachment.is_public == 1 ? true : false, :class => 'is_public')%>
|
||||
<%= hidden_field_tag "attachments[p#{i}][token]", "#{attachment.token}" %>
|
||||
</span>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</span>
|
||||
<script type='text/javascript'>
|
||||
// function CompatibleSend()
|
||||
// {
|
||||
// var obj=document.getElementById("_file");
|
||||
// var file= $(obj).clone();
|
||||
// file.click();
|
||||
// }
|
||||
</script>
|
||||
<span class="add_attachment">
|
||||
<%#= button_tag "浏览", :type=>"button", :onclick=>"CompatibleSend();" %>
|
||||
<!--%= link_to image_tag(),"javascript:void(0)", :onclick => "_file.click()"%-->
|
||||
<%= button_tag "文件浏览", :type=>"button", :onclick=>"_file.click()", :class =>"sub_btn",:style => ie8? ? 'display:none' : '' %>
|
||||
<%= file_field_tag 'attachments[dummy][file]',
|
||||
:id => '_file',
|
||||
:class => 'file_selector',
|
||||
:multiple => true,
|
||||
:onchange => 'addInputFiles(this);',
|
||||
:style => 'display:none',
|
||||
:data => {
|
||||
:max_file_size => Setting.attachment_max_size.to_i.kilobytes,
|
||||
:max_file_size_message => l(:error_attachment_too_big, :max_size => number_to_human_size(Setting.attachment_max_size.to_i.kilobytes)),
|
||||
:max_concurrent_uploads => Redmine::Configuration['max_concurrent_ajax_uploads'].to_i,
|
||||
:upload_path => uploads_path(:format => 'js'),
|
||||
:description_placeholder => l(:label_optional_description),
|
||||
:field_is_public => l(:field_is_public),
|
||||
:are_you_sure => l(:text_are_you_sure),
|
||||
:file_count => l(:label_file_count),
|
||||
:delete_all_files => l(:text_are_you_sure_all)
|
||||
} %>
|
||||
<span id="upload_file_count" :class="c_grey"><%= l(:label_no_file_uploaded)%></span>
|
||||
(<%= l(:label_max_size) %>: <%= number_to_human_size(Setting.attachment_max_size.to_i.kilobytes) %>)
|
||||
</span>
|
||||
|
||||
<% content_for :header_tags do %>
|
||||
<%= javascript_include_tag 'attachments' %>
|
||||
<% end %>
|
||||
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
<div style="font-weight:normal;">
|
||||
<% for attachment in attachments %>
|
||||
<div title="<%= attachment.filename%>" id = "attachment_" style="max-width: 300px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;float: left;">
|
||||
<%= link_to_short_attachment attachment, :class => 'link_file', :download => true, :length => 100 -%>
|
||||
</div>
|
||||
<% if attachment.is_text? %>
|
||||
<div style="float: left;">
|
||||
<%= link_to image_tag('magnifier.png'),
|
||||
{:controller => 'attachments',
|
||||
:action => 'show',
|
||||
:id => attachment,
|
||||
:filename => attachment.filename},
|
||||
:target => "_blank"%>
|
||||
</div>
|
||||
<% end %>
|
||||
<br>
|
||||
<% end %>
|
||||
</div>
|
|
@ -60,7 +60,7 @@
|
|||
<% if defined?(thumbnails) && thumbnails %>
|
||||
<% images = attachments.select(&:thumbnailable?) %>
|
||||
<% if images.any? %>
|
||||
<div class="thumbnails">
|
||||
<div class="pro_pic mb10" width="100" height="73">
|
||||
<% images.each do |attachment| %>
|
||||
<div><%= thumbnail_tag(attachment) %></div>
|
||||
<% end %>
|
||||
|
|
|
@ -0,0 +1,133 @@
|
|||
<script type="text/javascript">
|
||||
document.addEventListener('DOMContentLoaded',function(){
|
||||
var img = document.getElementsByName('issue_attachment_picture');
|
||||
|
||||
|
||||
function getImgNaturalStyle(img, callback) {
|
||||
var nWidth, nHeight;
|
||||
if (typeof img.naturalWidth == "undefined"|| img.naturalWidth == 0) {
|
||||
var image = new Image();
|
||||
image.src = img.src;
|
||||
if (image.complete) {
|
||||
callback(image);
|
||||
} else {
|
||||
image.onload = function () {
|
||||
callback(image);
|
||||
image.onload = null;
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (img.complete) {
|
||||
nWidth = img.naturalWidth;
|
||||
nHeight = img.naturalHeight;
|
||||
} else {
|
||||
img.onload = function () {
|
||||
nWidth = img.naturalWidth;
|
||||
nHeight = img.naturalHeight;
|
||||
image.onload = null;
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
return [nWidth, nHeight];
|
||||
}
|
||||
|
||||
|
||||
function UpdateImageInformation(image) {
|
||||
return [image.width,image.height];
|
||||
}
|
||||
|
||||
|
||||
for(i=0;i<img.length;i++)
|
||||
{
|
||||
imgNatural = getImgNaturalStyle(img[i],UpdateImageInformation);
|
||||
var width = imgNatural[0];
|
||||
var height = imgNatural[1];
|
||||
if (width<100)
|
||||
{
|
||||
img[i].width = width;
|
||||
}
|
||||
if (height<73) {
|
||||
img[i].height = height;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<div class="attachments" style="font-weight:normal;">
|
||||
<% is_float ||= false %>
|
||||
<% for attachment in attachments %>
|
||||
<p style="width: 100%;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;">
|
||||
<%if is_float%>
|
||||
<div style="max-width:55%;white-space: nowrap; overflow: hidden; text-overflow: ellipsis;float: left;">
|
||||
<% end%>
|
||||
<span title="<%= attachment.filename %>" id = "attachment_">
|
||||
<% if options[:length] %>
|
||||
<%= link_to_short_attachment attachment, :class => ' link_file_board', :download => true,:length => options[:length] -%>
|
||||
<% else %>
|
||||
<%= link_to_short_attachment attachment, :class => ' link_file_board', :download => true -%>
|
||||
<% end %>
|
||||
</span>
|
||||
<%if is_float%>
|
||||
</div>
|
||||
<% end%>
|
||||
|
||||
<% if attachment.is_text? %>
|
||||
<%= link_to image_tag('magnifier.png'),
|
||||
:controller => 'attachments',
|
||||
:action => 'show',
|
||||
:id => attachment,
|
||||
:filename => attachment.filename%>
|
||||
<% end %>
|
||||
<span title="<%= attachment.description%>">
|
||||
<%= h(truncate(" - #{attachment.description}", length: options[:length] ? options[:length]:15, omission: '...')) unless attachment.description.blank? %>
|
||||
</span>
|
||||
<span class="size">(
|
||||
<%= number_to_human_size attachment.filesize %>)
|
||||
</span>
|
||||
<% if options[:deletable] %>
|
||||
<% if attachment.container_type == 'HomeworkAttach' %>
|
||||
<%= link_to image_tag('delete.png'), {:controller => 'attachments', :action => 'delete_homework', :id => attachment.id},
|
||||
:data => {:confirm => l(:text_are_you_sure)},
|
||||
:method => :delete,
|
||||
:class => 'delete delete-homework-icon',
|
||||
:remote => true,
|
||||
:title => l(:button_delete) %>
|
||||
<% else %>
|
||||
<%= link_to image_tag('delete.png'), attachment_path(attachment),
|
||||
:data => {:confirm => l(:text_are_you_sure)},
|
||||
:method => :delete,
|
||||
:class => 'delete',
|
||||
#:remote => true,
|
||||
#:id => "attachments_" + attachment.id.to_s,
|
||||
:title => l(:button_delete) %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% if options[:wrap] %>
|
||||
<br/>
|
||||
|
||||
<% end %>
|
||||
<% if options[:author] %>
|
||||
<span class="author" title="<%= attachment.author%>">
|
||||
<%= link_to h(truncate(attachment.author.name, length: 10, omission: '...')),user_path(attachment.author),:class => "c_orange" %>,
|
||||
<%= format_time(attachment.created_on) %>
|
||||
</span>
|
||||
<% end %>
|
||||
</p>
|
||||
<% end %>
|
||||
<div class="thumbnails">
|
||||
<% if defined?(thumbnails) && thumbnails %>
|
||||
<% images = attachments.select(&:thumbnailable?) %>
|
||||
<% if images.any? %>
|
||||
<% images.each do |attachment| %>
|
||||
<div class="pro_pic fl " width="100" height="73"><%= thumbnail_issue_tag(attachment) %></div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
|
@ -46,7 +46,7 @@
|
|||
<%= link_to l(:button_delete_file),{:controller => :avatar,:action => :delete_image,:remote=>true,:source_type=> source.class,:source_id=>source.id},:confirm => l(:text_are_you_sure), :method => :post, :class => "btn_addPic", :style => "text-decoration:none;" %>
|
||||
<a href="javascript:void(0);" class="btn_addPic" style="text-decoration:none;">
|
||||
<span><%= l(:button_upload_photo) %></span>
|
||||
</a>
|
||||
</a>
|
||||
<!-- :accept => 'image/png,image/gif,image/jpeg', -->
|
||||
<span class="add_avatar" style="margin-left: -55px;width: 70px">
|
||||
<%= file_field_tag 'avatar[image]',
|
||||
|
@ -68,6 +68,7 @@
|
|||
:source_id => source.id.to_s
|
||||
} %>
|
||||
</span>
|
||||
|
||||
</div>
|
||||
<% content_for :header_tags do %>
|
||||
<%= javascript_include_tag 'avatars' %>
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
<%= image_tag(url_to_avatar(source), id: "avatar_image", :width =>"60", :height =>"60",:alt=>"上传图片")%>
|
||||
</a>
|
||||
<%#= link_to l(:button_delete_file),{:controller => :avatar,:action => :delete_image,:remote=>true,:source_type=> source.class,:source_id=>source.id},:confirm => l(:text_are_you_sure), :method => :post, :class => "upbtn fl" %>
|
||||
<a href="javascript:void(0)" class="upbtn fl">上传图片</a>
|
||||
<a href="javascript:void(0)" class="upbtn fl"><%= l(:button_upload_photo) %></a>
|
||||
<%= file_field_tag 'avatar[image]',
|
||||
:id => nil,
|
||||
:class => 'upload_file ',
|
||||
:class => 'upload_file',
|
||||
:size => "1",
|
||||
:multiple => false,
|
||||
:onchange => 'addInputAvatar(this);',
|
||||
|
|
|
@ -66,10 +66,10 @@
|
|||
</p>
|
||||
<% end %>
|
||||
<div class="ni_btn">
|
||||
<a href="javascript:" class="tijiao" onclick="clickOK();" >
|
||||
<a href="javascript:" class="tijiao" onclick="clickOK();" style="margin-bottom: 20px;" >
|
||||
确 定
|
||||
</a>
|
||||
<a href="javascript:" class="tijiao" onclick="clickCanel();">
|
||||
<a href="javascript:" class="tijiao" onclick="clickCanel();" style="margin-bottom: 20px;">
|
||||
取 消
|
||||
</a>
|
||||
</div>
|
||||
|
|
|
@ -1,16 +1,5 @@
|
|||
<%= render_flash_messages %>
|
||||
<div id="put-bid-form" style="display: none">
|
||||
<%= form_for HomeworkAttach.new, :url => {:controller => 'bids', :action => 'add_homework'}, :update => "bidding_project_list", :complete => '$("#put-bid-form").hide();', :html => {:multipart => true, :id => 'add_homework_form'} do |f| %>
|
||||
<fieldset>
|
||||
<legend>
|
||||
<%= l(:label_attachment_plural) %>
|
||||
</legend>
|
||||
<p id="put-bid-form-partial">
|
||||
<%= render :partial => 'attachments/form' %>
|
||||
</p>
|
||||
</fieldset>
|
||||
<%= submit_tag l(:button_create), :onclick => "return true" %>
|
||||
<% end %>
|
||||
<script type="text/javascript">
|
||||
function j_submit () {
|
||||
alert('start');
|
||||
|
|
|
@ -57,7 +57,6 @@
|
|||
<div class="dis" id="tbc_01">
|
||||
<%= render :partial => 'homework_attach/homeworks_list',
|
||||
:locals => {:homeworks => @homework_list,
|
||||
:homework_count => @obj_count,
|
||||
:remote => false,
|
||||
:not_batch_homework => @not_batch_homework,:is_student_batch_homework => @is_student_batch_homework}%>
|
||||
</div>
|
||||
|
|
|
@ -1,53 +1,54 @@
|
|||
<%= stylesheet_link_tag 'jquery/jquery-ui-1.9.2', :media => 'all' %>
|
||||
<%= error_messages_for 'bid' %>
|
||||
<%= hidden_field_tag 'course_id', @course.id %>
|
||||
<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 mb10">
|
||||
<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="javascript:void(0)"><%= 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 mb10">
|
||||
<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 class="fl"><span class="c_red">*</span> <%= l(:label_limit_time)%> :</label>
|
||||
<input type="text" name="bid[deadline]" id="bid_deadline" class="hwork_input02 fl" onchange="regexDeadLine();" readonly="readonly" value="<%= bid.deadline%>" >
|
||||
<%= calendar_for('bid_deadline')%>
|
||||
<div class="cl"></div>
|
||||
</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="javascript:void(0)"><%= 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,6 +1,6 @@
|
|||
$('#ajax-modal').html('<%= escape_javascript(render :partial => 'alert_anonyoms', locals: { bid: @bid, totle_size:@totle_size, cur_size:@cur_size, percent:@percent}) %>');
|
||||
showModal('ajax-modal', '500px');
|
||||
$('#ajax-modal').css('height','180px');
|
||||
//$('#ajax-modal').css('height','180px');
|
||||
$('#ajax-modal').siblings().remove();
|
||||
$('#ajax-modal').before("<span style='float: right;cursor:pointer;'>" +
|
||||
"<a href='javascript:' onclick='clickCanel();'><img src='/images/bid/close.png' width='26px' height='26px' /></a></span>");
|
||||
|
|
|
@ -13,3 +13,18 @@
|
|||
</p>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="talk_txt fl">
|
||||
<%= link_to h(topic.subject), board_message_path(@board, topic), title:topic.subject.to_s, :class =>"problem_tit fl" %>
|
||||
<% if topic.sticky? %>
|
||||
<a href="javascript:void(0)" class="talk_up fr c_red"><%= l(:label_board_sticky)%></a>
|
||||
<% end %>
|
||||
<br/>
|
||||
<%= l(:label_post_by)%><%= link_to topic.author, user_path(topic.author), :class =>"problem_name" %>
|
||||
<%= l(:label_post_by_time)%><%= format_time topic.created_on %>
|
||||
</div>
|
||||
<span class="talk_btn fr"><%= link_to (l(:label_short_reply) + " "+topic.replies_count.to_s), board_message_path(@board, topic), :style =>"color:#fff;line-height: 18px;" %></span>
|
||||
<div class="cl"></div>
|
||||
</div><!--讨论主类容 end-->
|
|
@ -1,97 +1,60 @@
|
|||
<script type="text/javascript">
|
||||
function submitProjectBoard()
|
||||
{
|
||||
if(regexSubject()&®exContent())
|
||||
{
|
||||
$("#message-form").submit();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<div id="add-message" class="add_frame" style="display:<%= !@flag.nil?&&@flag=='true' ? '' : 'none' %>;">
|
||||
<% if User.current.logged? %>
|
||||
<div class="project_r_h">
|
||||
<h2 class="project_h2"><%= l(:project_module_boards_post) %></h2>
|
||||
</div>
|
||||
<%= form_for @message, :url => new_board_message_path(@board), :html => {:multipart => true, :id => 'message-form'} do |f| %>
|
||||
<%= render :partial => 'messages/form', :locals => {:f => f} %>
|
||||
<p>
|
||||
<a herf="#" onclick="submitProjectBoard();" class="ButtonColor m3p10"><%= l(:button_submit)%></a>
|
||||
<%= link_to l(:button_cancel), "#", :onclick => '$("#add-message").hide(); return false;', :class => 'ButtonColor m3p10' %>
|
||||
</p>
|
||||
<% end %>
|
||||
<div id="preview" class="wiki"></div>
|
||||
<% end %>
|
||||
<div class="project_r_h">
|
||||
<h2 class="project_h2">
|
||||
<% if User.current.language == "zh"%>
|
||||
<%= h @board.name %>
|
||||
<% else %>
|
||||
<%= l(:project_module_boards) %>
|
||||
<% end %>
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<!--display the board-->
|
||||
<% if !User.current.logged? %>
|
||||
<div style="font-size: 14px;margin:20px;">
|
||||
<% if @project.project_type == 1 %>
|
||||
<%= l(:label_user_login_course_board) %>
|
||||
<% else %>
|
||||
<%= l(:label_user_login_project_board) %>
|
||||
<% end %>
|
||||
<%= link_to l(:label_user_login_new), signin_path %>
|
||||
<hr/>
|
||||
<div class="c_grey f14">
|
||||
<%= l(:label_user_login_project_board) %>
|
||||
<%= link_to l(:label_user_login_new), signin_path, :class => "c_blue ml5" %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<!-- 内容显示部分 -->
|
||||
<div class="project_right">
|
||||
<div class="project_r_h">
|
||||
<h2 class="project_h2">
|
||||
<% if User.current.language == "zh"%>
|
||||
<%= h @board.name %>
|
||||
<% else %>
|
||||
<%= l(:project_module_boards) %>
|
||||
<% end %>
|
||||
</h2>
|
||||
</div>
|
||||
<div class="talk_top">
|
||||
<div class="fl"><span><%= l(:label_project_board_count , :count => @topic_count)%></span></div>
|
||||
<% if @project.enabled_modules.where("name = 'boards'").count > 0 && User.current.member_of?(@project) %>
|
||||
<div class="talk_top">
|
||||
<div class="fl"><span><%= l(:label_project_board_count , :count => @topic_count)%></span></div>
|
||||
<% if @project.enabled_modules.where("name = 'boards'").count > 0 && User.current.member_of?(@project) %>
|
||||
<span><%= link_to l(:project_module_boards_post), new_board_message_path(@board),
|
||||
:class => 'problem_new_btn fl',
|
||||
:onclick => 'showAndScrollTo("add-message", "message_subject"); return false;' if User.current.logged? %></span>
|
||||
<% end %>
|
||||
:class => 'problem_new_btn fl c_dorange',
|
||||
:onclick => 'showAndScrollTo("add-message", "message_subject"); return false;' if User.current.logged? %></span>
|
||||
<% end %>
|
||||
<div class="cl"></div>
|
||||
</div>
|
||||
<!-- 帖子内容显示 -->
|
||||
<% if @topics.any? %>
|
||||
<% @topics.each do |topic| %>
|
||||
<div class="problem_main">
|
||||
<a>
|
||||
<%= link_to image_tag(url_to_avatar(topic.author), :class => "problem_pic talk_pic fl"), user_path(topic.author) %>
|
||||
</a>
|
||||
<div class="talk_txt fl">
|
||||
<div>
|
||||
<span><%= link_to h(topic.subject), board_message_path(@board, topic), title:topic.subject.to_s, :class =>"problem_tit fl" %></span>
|
||||
<% if topic.sticky? %>
|
||||
<span class="talk_up" style="float:right;"><%= l(:label_board_sticky)%></span>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="problem_line">
|
||||
<span><%= l(:label_post_by)%><%= link_to topic.author, user_path(topic.author), :class =>"problem_name" %></span>
|
||||
<span><%= l(:label_post_by_time)%><%= format_time topic.created_on %></span>
|
||||
</div>
|
||||
</div>
|
||||
<span class="talk_btn fr"><%= link_to (l(:label_short_reply) + " "+topic.replies_count.to_s), board_message_path(@board, topic), :style =>"color:#fff;line-height: 18px;" %></span>
|
||||
<!-- 帖子内容显示 -->
|
||||
<% if @topics.any? %>
|
||||
<% @topics.each do |topic| %>
|
||||
<div class="problem_main">
|
||||
<%= link_to image_tag(url_to_avatar(topic.author), :width=>"32",:height=>"32"), user_path(topic.author),:class => 'problem_pic talk_pic fl' %>
|
||||
<div class="talk_txt fl">
|
||||
<%= link_to h(topic.subject), board_message_path(@board, topic), title:topic.subject.to_s, :class =>"problem_tit fl" %>
|
||||
<% if topic.sticky? %>
|
||||
<a href="javascript:void(0)" class="talk_up fr c_red"><%= l(:label_board_sticky)%></a>
|
||||
<% end %>
|
||||
<br/>
|
||||
<%= l(:label_post_by)%><%= link_to topic.author, user_path(topic.author), :class =>"problem_name" %>
|
||||
<%= l(:label_post_by_time)%><%= format_time topic.created_on %>
|
||||
</div>
|
||||
<%= link_to (l(:label_short_reply) + " "+topic.replies_count.to_s), board_message_path(@board, topic), :class => "talk_btn fr c_white" %>
|
||||
<div class="cl"></div>
|
||||
</div><!--讨论主类容 end-->
|
||||
<% end %>
|
||||
<ul class="wlist">
|
||||
<%= pagination_links_full @topic_pages, @topic_count, :per_page_links => false, :remote => false, :flag => true %>
|
||||
</ul>
|
||||
<% else %>
|
||||
<p class="nodata"><%= l(:label_no_data) %></p>
|
||||
<% end %>
|
||||
<!--讨论主类容 end-->
|
||||
<div class="cl"></div>
|
||||
</div>
|
||||
<ul class="wlist">
|
||||
<%= pagination_links_full @topic_pages, @topic_count, :per_page_links => false, :remote => false, :flag => true %>
|
||||
</ul>
|
||||
<!--讨论主类容 end-->
|
||||
|
||||
<% other_formats_links do |f| %>
|
||||
<%= f.link_to 'Atom', :url => {:key => User.current.rss_key} %>
|
||||
<% end %>
|
||||
<%# other_formats_links do |f| %>
|
||||
<%#= f.link_to 'Atom', :url => {:key => User.current.rss_key} %>
|
||||
<%# end %>
|
||||
|
||||
<% html_title @board.name %>
|
||||
|
||||
|
|
|
@ -1,6 +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 %>
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
<% selected_tab = params[:tab] ? params[:tab].to_s : tabs.first[:name] %>
|
||||
<div class="hwork_new">
|
||||
<div class="hwork_tb_">
|
||||
<ul>
|
||||
<% tabs.each do |tab| -%>
|
||||
<li><%= link_to l(tab[:label]), { :tab => tab[:name] },
|
||||
:id => "tab-#{tab[:name]}",
|
||||
:class => (tab[:name] != selected_tab ? 'hwork_normaltab' : 'hwork_hovertab'),
|
||||
:onclick => "showTab('#{tab[:name]}'); this.blur(); return false;" %></li>
|
||||
<% end -%>
|
||||
</ul>
|
||||
<!-- <div class="tabs-buttons" style="display:none;">
|
||||
<button class="tab-left" onclick="moveTabLeft(this);"></button>
|
||||
<button class="tab-right" onclick="moveTabRight(this);"></button>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(document).ready(displayTabsButtons);
|
||||
$(window).resize(displayTabsButtons);
|
||||
</script>
|
||||
|
||||
<% tabs.each do |tab| -%>
|
||||
<%= content_tag('div', render(:partial => tab[:partial], :locals => {:tab => tab} ),
|
||||
:id => "tab-content-#{tab[:name]}",
|
||||
:style => (tab[:name] != selected_tab ? 'display:none' : nil),
|
||||
:class => 'hwork_normaltab') %>
|
||||
<% end -%>
|
|
@ -67,7 +67,7 @@
|
|||
<%= f.text_field :deadline,
|
||||
:required => true,
|
||||
:size => 60,
|
||||
:style => "width:150px;",
|
||||
:style => "width:150px;float:left;",
|
||||
:readonly => true,
|
||||
:placeholder => "#{l(:label_deadline)}"
|
||||
%>
|
||||
|
|
|
@ -79,16 +79,6 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="add-info">
|
||||
<%= content_tag "span","#{l(:label_duration_time)}:", :class => "course-font"%>
|
||||
<%= get_course_term @course %>
|
||||
</div>
|
||||
|
||||
<div class="add-info" style="margin-left: 30px; margin-top: -20px">
|
||||
<%= content_tag "span", "#{l(:label_course_brief_introduction)}:", :class => "course-font" %>
|
||||
<%= content_tag "div", course.short_description, :class => "brief_introduction", :title => course.short_description %>
|
||||
</div>
|
||||
|
||||
<div class="tags">
|
||||
<div id="tags">
|
||||
<%= image_tag( "/images/sidebar/tags.png") %>
|
||||
|
|
|
@ -1,50 +1,50 @@
|
|||
|
||||
<div class="members_left">
|
||||
<ul style=" border-bottom:none;">
|
||||
<li>
|
||||
<span class="w150 f_b" >
|
||||
用户
|
||||
</span>
|
||||
<span class="w150 f_b">
|
||||
角色
|
||||
</span>
|
||||
<span></span>
|
||||
</li>
|
||||
|
||||
<div id="course_member_list">
|
||||
<%= render :partial => "courses/member" %>
|
||||
</div>
|
||||
</ul>
|
||||
</div><!-- 左边-->
|
||||
<div class="members_right">
|
||||
<p class="c_blue fb mt10 mb5">添加成员</p>
|
||||
<%= form_for(@member, {:as => :membership, :url => course_memberships_path(@course), :remote => true, :method => :post}) do |f| %>
|
||||
<div class="member_search">
|
||||
<input hidden="hidden" value="true" name="flag">
|
||||
<input id="principal_search" class="member_search_input fl" type="text" placeholder="请输入用户名称来搜索好友">
|
||||
<%= javascript_tag "observeSearchfield('principal_search', null, '#{ escape_javascript autocomplete_course_memberships_path(@course, :format => 'js',:flag => true) }')" %>
|
||||
<div class="cl"></div>
|
||||
|
||||
<div id="principals_for_new_member">
|
||||
<%= render_principals_for_new_course_members(@course) %>
|
||||
</div>
|
||||
<div class="cl"></div>
|
||||
|
||||
<ul class="rolebox mb10 mt10">
|
||||
<li class="fb">
|
||||
<%= l(:label_role_plural) %>:
|
||||
</li>
|
||||
<% @roles.each do |role| %>
|
||||
<li>
|
||||
<%= radio_button_tag 'membership[role_ids][]', role.id, role.name == "学生" || role.name == "Student" %>
|
||||
<label ><%= h role %></label>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
<div class="cl mb10"></div>
|
||||
<a href="javascript:void(0)" class="member_btn" onclick="$('#new_membership').submit();">
|
||||
新增成员
|
||||
</a>
|
||||
</div>
|
||||
<% end%>
|
||||
|
||||
<div class="members_left">
|
||||
<ul style=" border-bottom:none;">
|
||||
<li>
|
||||
<span class="w150 f_b" >
|
||||
用户
|
||||
</span>
|
||||
<span class="w150 f_b">
|
||||
角色
|
||||
</span>
|
||||
<span></span>
|
||||
</li>
|
||||
|
||||
<div id="course_member_list">
|
||||
<%= render :partial => "courses/member" %>
|
||||
</div>
|
||||
</ul>
|
||||
</div><!-- 左边-->
|
||||
<div class="members_right">
|
||||
<p class="c_blue fb mt10 mb5">添加成员</p>
|
||||
<%= form_for(@member, {:as => :membership, :url => course_memberships_path(@course), :remote => true, :method => :post}) do |f| %>
|
||||
<div class="member_search">
|
||||
<input hidden="hidden" value="true" name="flag">
|
||||
<input id="principal_search" class="member_search_input fl" type="text" placeholder="请输入用户名称来搜索好友">
|
||||
<%= javascript_tag "observeSearchfield('principal_search', null, '#{ escape_javascript autocomplete_course_memberships_path(@course, :format => 'js',:flag => true) }')" %>
|
||||
<div class="cl"></div>
|
||||
|
||||
<div id="principals_for_new_member">
|
||||
<%= render_principals_for_new_course_members(@course) %>
|
||||
</div>
|
||||
<div class="cl"></div>
|
||||
|
||||
<ul class="rolebox mb10 mt10">
|
||||
<li class="fb">
|
||||
<%= l(:label_role_plural) %>:
|
||||
</li>
|
||||
<% @roles.each do |role| %>
|
||||
<li>
|
||||
<%= radio_button_tag 'membership[role_ids][]', role.id, role.name == "学生" || role.name == "Student" %>
|
||||
<label ><%= h role %></label>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
<div class="cl mb10"></div>
|
||||
<a href="javascript:void(0)" class="member_btn" onclick="$('#new_membership').submit();">
|
||||
新增成员
|
||||
</a>
|
||||
</div>
|
||||
<% end%>
|
||||
</div><!-- 右边 end-->
|
|
@ -16,7 +16,7 @@
|
|||
<% end%>
|
||||
|
||||
<ul class="wlist">
|
||||
<%= pagination_links_full @obj_pages, @obj_count, :per_page_links => false, :remote => false, :flag => true%>
|
||||
<%#= pagination_links_full @obj_pages, @obj_count, :per_page_links => false, :remote => false, :flag => true%>
|
||||
</ul>
|
||||
<div class="cl"></div>
|
||||
</div>
|
||||
|
|
|
@ -1,31 +1,31 @@
|
|||
<%= 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',:height => '140px;',:editor_id => 'leave_message_editor',:input_html=>{:id => "leave_meassge",:style => "resize: none;",
|
||||
:placeholder => "#{l(:label_welcome_my_respond)}",:maxlength => 250}%>
|
||||
<a href="javascript:void(0)" class="grey_btn fr ml10 mt10">取 消</a>
|
||||
<a href="javascript:void(0)" onclick='leave_message_editor.sync();$("#leave_message_form").submit();' class="blue_btn fr mt10">
|
||||
<%= 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',:height => '140px;',:editor_id => 'leave_message_editor',:input_html=>{:id => "leave_meassge",:style => "resize: none;",
|
||||
:placeholder => "#{l(:label_welcome_my_respond)}",:maxlength => 250}%>
|
||||
<a href="javascript:void(0)" class="grey_btn fr ml10 mt10">取 消</a>
|
||||
<a href="javascript:void(0)" onclick='leave_message_editor.sync();$("#leave_message_form").submit();' class="blue_btn fr mt10">
|
||||
<%= 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>
|
|
@ -70,9 +70,9 @@
|
|||
<% end; reset_cycle %>
|
||||
</div>
|
||||
|
||||
<ul class="wlist">
|
||||
<%= pagination_links_full @obj_pages, @obj_count, :per_page_links => false, :remote => @is_remote, :flag => true%>
|
||||
</ul>
|
||||
<!--<ul class="wlist">
|
||||
<% #= pagination_links_full @obj_pages, @obj_count, :per_page_links => false, :remote => @is_remote, :flag => true%>
|
||||
</ul>-->
|
||||
<% else%>
|
||||
<p class="nodata">
|
||||
<%= l(:label_no_data) %>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<%= form_tag( searchmembers_course_path(@course), method: 'get',:class => "f_l",:remote=>true,:id => "search_student") do %>
|
||||
<%= text_field_tag 'name', params[:name], name: "name", :class => 'st_search_input', :placeholder => '输入学生姓名、学号进行搜索'%>
|
||||
<%= text_field_tag 'name', params[:name], name: "name", :class => 'st_search_input', :placeholder => '输入学生昵称、姓名、学号进行搜索'%>
|
||||
<% if @group %>
|
||||
<%= hidden_field "search_group_id", params[:search_group_id],:value => "#{@group.id}", name: 'search_group_id' %>
|
||||
<input type="hidden" name="ingroup">
|
||||
|
|
|
@ -27,15 +27,15 @@
|
|||
|
||||
|
||||
/***弹框***/
|
||||
#popbox_tscore{width:480px;position:absolute;z-index:100;left:50%;top:50%;margin:-215px 0 0 -300px; background:#fff; -moz-border-radius:5px; -webkit-border-radius:5px; border-radius:5px; box-shadow:0px 0px 8px #194a81; overflow:auto;}
|
||||
.alert .close02{width:26px;height:26px;overflow:hidden;position:absolute;top:-10px;right:-490px;background:url(images/close.png) no-repeat;cursor:pointer;}
|
||||
.tscore_con h2{ display:block; background:#eaeaea; font-size:14px; color:#343333; height:31px; width: auto; margin-top:25px; padding-left:20px; padding-top:5px;}
|
||||
/*#popbox_tscore{width:480px;position:absolute;z-index:100;left:50%;top:50%;margin:-215px 0 0 -300px; background:#fff; -moz-border-radius:5px; -webkit-border-radius:5px; border-radius:5px; box-shadow:0px 0px 8px #194a81; overflow:auto;}*/
|
||||
/*.alert .close02{width:26px;height:26px;overflow:hidden;position:absolute;top:-10px;right:-490px;background:url(images/close.png) no-repeat;cursor:pointer;}*/
|
||||
.tscore_con h2{ display:block; background:#eaeaea; font-size:14px; color:#343333; height:31px; width: auto; text-align: center; padding-top:5px;}
|
||||
.tscore_box{ width:350px; margin:15px auto;}
|
||||
.tscore_box li{ height:25px;}
|
||||
</style>
|
||||
|
||||
|
||||
<div class="tscore_con">
|
||||
<div class="tscore_con" id="user_score">
|
||||
<h2><%= @member_score.user.name %> 历次作业积分</h2>
|
||||
<ul class="tscore_box">
|
||||
<li ><span class="c_blue02 w280">作业名称</span><span class="c_blue02 w70">得分</span></li>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<%= javascript_include_tag "/assets/kindeditor/kindeditor" %>
|
||||
<%= labelled_form_for @homework, :html => { :multipart => true }, :url => {:controller => 'bids', :action => 'create_homework',:course_id => "#{params[:id] || params[:course_id]}"} do |f| %>
|
||||
<%= render :partial => 'bids/new_homework_form', :locals => { :bid => @homework,:bid_id => "new_bid",:f => f,:edit_mode => false } %>
|
||||
<%= javascript_include_tag "/assets/kindeditor/kindeditor" %>
|
||||
<%= labelled_form_for @homework, :html => { :multipart => true }, :url => {:controller => 'bids', :action => 'create_homework',:course_id => "#{params[:id] || params[:course_id]}"} do |f| %>
|
||||
<%= render :partial => 'bids/new_homework_form', :locals => { :bid => @homework,:bid_id => "new_bid",:f => f,:edit_mode => false } %>
|
||||
<% end %>
|
|
@ -1,92 +1,92 @@
|
|||
<div class="project_r_h">
|
||||
<h2 class="project_h2"><%= l(:label_course_modify_settings)%></h2>
|
||||
</div>
|
||||
<div class="hwork_new">
|
||||
<div id="tb_" class="hwork_tb_">
|
||||
<ul>
|
||||
<li id="tb_1" class="hwork_hovertab" onclick="course_setting(1);" >
|
||||
基本信息
|
||||
</li>
|
||||
<li id="tb_2" class="hwork_normaltab" onclick="course_setting(2);">
|
||||
成员
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="hwork_dis" id="tbc_01" style="padding-top: 10px;">
|
||||
<ul>
|
||||
<%= labelled_form_for @course do |f| %>
|
||||
<li class="ml45 mb10">
|
||||
<%= render :partial => "avatar/new_avatar_form", :locals => {source: @course} %>
|
||||
<div class="cl"></div>
|
||||
</li>
|
||||
<li class="ml45">
|
||||
<label><span class="c_red">*</span> <%= l(:label_tags_course_name)%> :</label>
|
||||
<input type="text" name="course[name]" id="course_name" class="courses_input" maxlength="100" onkeyup="regex_course_name();" value="<%= @course.name%>">
|
||||
<span class="c_red" id="course_name_notice" style="display: none;">课程名称不能为空</span>
|
||||
</li>
|
||||
<div class="cl"></div>
|
||||
<li class="ml45">
|
||||
<label><span class="c_red">*</span> <%= l(:label_class_period)%> :</label>
|
||||
<input type="text" name="class_period" id="class_period" class="hwork_input02" onkeyup="regex_course_class_period();" maxlength="6" value="<%= @course.class_period%>">
|
||||
<span class="c_red" id="course_class_period_notice" style="display: none;"></span>
|
||||
</li>
|
||||
<div class="cl"></div>
|
||||
<li class="ml45 mb10">
|
||||
<label><span class="c_red">*</span> <%= l(:label_course_term)%> :</label>
|
||||
<%= select_tag :time,options_for_select(course_time_option(@course.time),@course.time), {} %>
|
||||
<%= select_tag :term,options_for_select(course_term_option,@course.term || cur_course_term),{} %>
|
||||
</li>
|
||||
<div class="cl"></div>
|
||||
<li class="ml45 mb10">
|
||||
<label><span class="c_red">*</span> <%= l(:label_new_course_password)%> :</label>
|
||||
<input type="password" name="course[password]" id="course_course_password" class="hwork_input02" value="<%= @course.password%>" onkeyup="regex_course_password();">
|
||||
<a id="psw_btn" href="javascript:void(0)">显示明码</a>
|
||||
<span class="c_red" id="course_course_password_notice"></span>
|
||||
<div class="cl"></div>
|
||||
<span class=" ml80 c_orange">学生或其他成员申请加入课程时候需要使用该口令,该口令可以由老师在课堂上公布。</span>
|
||||
</li>
|
||||
<li class="ml45">
|
||||
<label class="fl" > <%= l(:label_new_course_description)%> :</label>
|
||||
<textarea name="course[description]" placeholder="最多3000个汉字(或6000个英文字符)" class="courses_text fl" maxlength="6000"><%= @course.description%></textarea>
|
||||
<div class="cl"></div>
|
||||
</li>
|
||||
<li class=" mb5 ml80">
|
||||
<label >公开 :</label>
|
||||
<input <%= @course.is_public == 1 ? 'checked' : ''%> id="course_is_public" name="course[is_public]" type="checkbox">
|
||||
<span class="c_grey">(打钩为公开,不打钩则不公开,若不公开,仅课程成员可见该课程。)</span>
|
||||
<div class="cl"></div>
|
||||
</li>
|
||||
<li class=" mb5 ml30">
|
||||
<label >学生列表公开 :</label>
|
||||
<input <%= @course.open_student == 1 ? 'checked' : ''%> id="course_open_student" name="course[open_student]" type="checkbox" style="margin-left: 1px;"/>
|
||||
<span class="c_grey">(打钩为"学生列表公开",不打钩为不公开,若不公开,则课程外部人员看不到学生列表)</span>
|
||||
<div class="cl"></div>
|
||||
</li>
|
||||
<li class=" ml90" >
|
||||
<a href="javascript:void(0)" class="blue_btn fl c_white" onclick="submit_edit_course(<%= @course.id%>);" >提交</a>
|
||||
<%= link_to l(:button_cancel), course_path(@course), :class => "blue_btn grey_btn fl c_white" %>
|
||||
<div class="cl"></div>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="hwork_undis" id="tbc_02">
|
||||
<div class="search_course fl">
|
||||
<%= form_tag({:controller => 'courses', :action => 'search_member'},:id => "course_member_search_form", :method => :get, :class => "search_form_course",:remote => true) do %>
|
||||
<!-- , :onkeyup => "regexQ('#{l(:label_search_conditions_not_null)}');" -->
|
||||
<%= text_field_tag 'name', params[:name], :placeholder => "昵称、学号、姓名搜索", :class => "search_text fl" %>
|
||||
<a href="javascript:void(0)" onclick="submitMemberSerch('<%= l(:label_search_conditions_not_null) %>');" class="search_btn fl f14 c_white ml10" >
|
||||
<%= l(:label_search)%>
|
||||
</a>
|
||||
<br />
|
||||
<span id="course_member_name_span" style="float: left"></span>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="cl"></div>
|
||||
<div id="course_members_setting">
|
||||
<%= render :partial => "course_members" %>
|
||||
</div>
|
||||
</div><!---成员结束-->
|
||||
</div><!--talknew end-->
|
||||
<div class="project_r_h">
|
||||
<h2 class="project_h2"><%= l(:label_course_modify_settings)%></h2>
|
||||
</div>
|
||||
<div class="hwork_new">
|
||||
<div id="tb_" class="hwork_tb_">
|
||||
<ul>
|
||||
<li id="tb_1" class="hwork_hovertab" onclick="course_setting(1);" >
|
||||
基本信息
|
||||
</li>
|
||||
<li id="tb_2" class="hwork_normaltab" onclick="course_setting(2);">
|
||||
成员
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="hwork_dis" id="tbc_01" style="padding-top: 10px;">
|
||||
<ul>
|
||||
<%= labelled_form_for @course do |f| %>
|
||||
<li class="ml45 mb10">
|
||||
<%= render :partial => "avatar/new_avatar_form", :locals => {source: @course} %>
|
||||
<div class="cl"></div>
|
||||
</li>
|
||||
<li class="ml45">
|
||||
<label><span class="c_red">*</span> <%= l(:label_tags_course_name)%> :</label>
|
||||
<input type="text" name="course[name]" id="course_name" class="courses_input" maxlength="100" onkeyup="regex_course_name();" value="<%= @course.name%>">
|
||||
<span class="c_red" id="course_name_notice" style="display: none;">课程名称不能为空</span>
|
||||
</li>
|
||||
<div class="cl"></div>
|
||||
<li class="ml45">
|
||||
<label><span class="c_red">*</span> <%= l(:label_class_period)%> :</label>
|
||||
<input type="text" name="class_period" id="class_period" class="hwork_input02" onkeyup="regex_course_class_period();" maxlength="6" value="<%= @course.class_period%>">
|
||||
<span class="c_red" id="course_class_period_notice" style="display: none;"></span>
|
||||
</li>
|
||||
<div class="cl"></div>
|
||||
<li class="ml45 mb10">
|
||||
<label><span class="c_red">*</span> <%= l(:label_course_term)%> :</label>
|
||||
<%= select_tag :time,options_for_select(course_time_option(@course.time),@course.time), {} %>
|
||||
<%= select_tag :term,options_for_select(course_term_option,@course.term || cur_course_term),{} %>
|
||||
</li>
|
||||
<div class="cl"></div>
|
||||
<li class="ml45 mb10">
|
||||
<label><span class="c_red">*</span> <%= l(:label_new_course_password)%> :</label>
|
||||
<input type="password" name="course[password]" id="course_course_password" class="hwork_input02" value="<%= @course.password%>" onkeyup="regex_course_password();">
|
||||
<a id="psw_btn" href="javascript:void(0)">显示明码</a>
|
||||
<span class="c_red" id="course_course_password_notice"></span>
|
||||
<div class="cl"></div>
|
||||
<span class=" ml80 c_orange">学生或其他成员申请加入课程时候需要使用该口令,该口令可以由老师在课堂上公布。</span>
|
||||
</li>
|
||||
<li class="ml45">
|
||||
<label class="fl" > <%= l(:label_new_course_description)%> :</label>
|
||||
<textarea name="course[description]" placeholder="最多3000个汉字(或6000个英文字符)" class="courses_text fl" maxlength="6000"><%= @course.description%></textarea>
|
||||
<div class="cl"></div>
|
||||
</li>
|
||||
<li class=" mb5 ml80">
|
||||
<label >公开 :</label>
|
||||
<input <%= @course.is_public == 1 ? 'checked' : ''%> id="course_is_public" name="course[is_public]" type="checkbox">
|
||||
<span class="c_grey">(打钩为公开,不打钩则不公开,若不公开,仅课程成员可见该课程。)</span>
|
||||
<div class="cl"></div>
|
||||
</li>
|
||||
<li class=" mb5 ml30">
|
||||
<label >学生列表公开 :</label>
|
||||
<input <%= @course.open_student == 1 ? 'checked' : ''%> id="course_open_student" name="course[open_student]" type="checkbox" style="margin-left: 1px;"/>
|
||||
<span class="c_grey">(打钩为"学生列表公开",不打钩为不公开,若不公开,则课程外部人员看不到学生列表)</span>
|
||||
<div class="cl"></div>
|
||||
</li>
|
||||
<li class=" ml90" >
|
||||
<a href="javascript:void(0)" class="blue_btn fl c_white" onclick="submit_edit_course(<%= @course.id%>);" >提交</a>
|
||||
<%= link_to l(:button_cancel), course_path(@course), :class => "blue_btn grey_btn fl c_white" %>
|
||||
<div class="cl"></div>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="hwork_undis" id="tbc_02">
|
||||
<div class="search_course fl">
|
||||
<%= form_tag(search_member_course_path,:id => "course_member_search_form", :method => :get, :class => "search_form_course",:remote => true) do %>
|
||||
<!-- , :onkeyup => "regexQ('#{l(:label_search_conditions_not_null)}');" -->
|
||||
<%= text_field_tag 'name', params[:name], :placeholder => "昵称、学号、姓名搜索", :class => "search_text fl" %>
|
||||
<a href="javascript:void(0)" onclick="submitMemberSerch('<%= l(:label_search_conditions_not_null) %>');" class="search_btn fl f14 c_white ml10" >
|
||||
<%= l(:label_search)%>
|
||||
</a>
|
||||
<br />
|
||||
<span id="course_member_name_span" style="float: left"></span>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div id="course_members_setting">
|
||||
<%= render :partial => "course_members" %>
|
||||
</div>
|
||||
</div><!---成员结束-->
|
||||
</div><!--talknew end-->
|
||||
<div class="cl"></div>
|
|
@ -1,3 +1,13 @@
|
|||
//$('#ajax-modal').html('<%#= escape_javascript(render :partial => 'courses/show_member_score', :locals => {:member => @member_score}) %>');
|
||||
//showModal('ajax-modal', '400px');
|
||||
//$('#ajax-modal').addClass('new-watcher');
|
||||
|
||||
$('#ajax-modal').html('<%= escape_javascript(render :partial => 'courses/show_member_score', :locals => {:member => @member_score}) %>');
|
||||
showModal('ajax-modal', '400px');
|
||||
$('#ajax-modal').addClass('new-watcher');
|
||||
//$('#ajax-modal').css('height','569px');
|
||||
$('#ajax-modal').siblings().remove();
|
||||
$('#ajax-modal').before("<span style='float: right;cursor:pointer;padding-left: 513px;'>" +
|
||||
"<a href='javascript:void(0)' onclick='hidden_homework_score_form();'><img src='/images/bid/close.png' width='26px' height='26px' /></a></span>");
|
||||
//$('#ajax-modal').parent().removeClass();
|
||||
$('#ajax-modal').parent().css("top","30%").css("left","40%").css("position","fixed");
|
||||
$('#ajax-modal').parent().addClass("new-watcher");
|
||||
|
|
|
@ -62,11 +62,11 @@
|
|||
<!--<a href="javascript:void(0)" class="re_fabu f_r b_lblue" onclick="show_upload();">上传资源</a>-->
|
||||
<p class="c_grey fr mt10 mr5">
|
||||
上传:
|
||||
<a href="javascript:void(0);" class=" c_dblue" onclick="show_upload(1);">课件</a> |
|
||||
<a href="javascript:void(0);" class=" c_dblue" onclick="show_upload(2);">软件</a> |
|
||||
<a href="javascript:void(0);" class=" c_dblue" onclick="show_upload(3);">媒体</a> |
|
||||
<a href="javascript:void(0);" class=" c_dblue" onclick="show_upload(4);">代码</a> |
|
||||
<a href="javascript:void(0);" class=" c_dblue" onclick="show_upload(5);">其他</a>
|
||||
<a href="javascript:void(0);" class=" c_dblue font_bold" onclick="show_upload(1);">课件</a> |
|
||||
<a href="javascript:void(0);" class=" c_dblue font_bold" onclick="show_upload(2);">软件</a> |
|
||||
<a href="javascript:void(0);" class=" c_dblue font_bold" onclick="show_upload(3);">媒体</a> |
|
||||
<a href="javascript:void(0);" class=" c_dblue font_bold" onclick="show_upload(4);">代码</a> |
|
||||
<a href="javascript:void(0);" class=" c_dblue font_bold" onclick="show_upload(5);">其他</a>
|
||||
</p>
|
||||
<% end %>
|
||||
</div><!---re_top end-->
|
||||
|
|
|
@ -45,8 +45,8 @@
|
|||
</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"} %>
|
||||
<%= render :partial => 'tags/tag_new', :locals => {:obj => file, :object_flag => "6"} %>
|
||||
<%= render :partial => 'tags/tag_add', :locals => {:obj => file, :object_flag => "6"} %>
|
||||
</div>
|
||||
<div class="cl"></div>
|
||||
</div><!---re_con_box end-->
|
||||
|
|
|
@ -1,8 +1,3 @@
|
|||
|
||||
<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()
|
||||
|
@ -10,8 +5,8 @@
|
|||
$('#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').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","40%").css("left","36%");
|
||||
$('#ajax-modal').parent().addClass("popbox_polls");
|
||||
}
|
||||
|
||||
|
@ -46,7 +41,7 @@
|
|||
<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 => "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) %>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<div id="popbox_upload" style="margin-top: -30px;margin-left: -20px;margin-right: -10px;">
|
||||
<div class="upload_con">
|
||||
<h2>将此课件引入我的资源库</h2>
|
||||
<h2>将此文件引入我的资源库</h2>
|
||||
<% if error == '403' %>
|
||||
<div class="upload_box">
|
||||
<div style="color: red;">您没有权限引用此资源</div>
|
||||
|
@ -13,13 +13,11 @@
|
|||
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')%>
|
||||
<%= content_tag('div', projects_check_box_tags('projects[project][]', User.current.projects,project,file), :id => 'projects', :class => "hidden")%>
|
||||
<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>
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<div id="resource_list">
|
||||
<% if @isproject %>
|
||||
<%= render :partial => 'project_file', locals: {project: @project} %>
|
||||
<%= render :partial => 'project_file_new', locals: {project: @project} %>
|
||||
<% else %>
|
||||
<%= render :partial => 'course_file', locals: {course: @course} %>
|
||||
<% end %>
|
||||
|
|
|
@ -7,5 +7,5 @@
|
|||
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().css("top","30%").css("left","35%");
|
||||
$('#ajax-modal').parent().addClass("popbox_polls");
|
|
@ -17,11 +17,12 @@
|
|||
<p style="color: #ff0000">
|
||||
(<%= l(:label_memos_max_length) %>)
|
||||
</p>
|
||||
<p>
|
||||
<p class="fl" style="margin-top: 5px;">
|
||||
<%= l(:label_attachment_plural) %>
|
||||
<br />
|
||||
<%= render :partial => 'attachments/form', :locals => {:container => @memo} %>
|
||||
</p>
|
||||
<div class="cl"></div>
|
||||
<%= f.submit :value => l(:label_memo_create) %>
|
||||
<%= link_to l(:button_cancel), "#", :onclick => '$("#add-memo").hide(); return false;' %>
|
||||
</div>
|
||||
|
|
|
@ -52,6 +52,16 @@
|
|||
:style => "resize: none;", :class => 'noline', :placeholder => l(:text_caracters_maximum,:count=>250),
|
||||
:maxlength => 250 %>
|
||||
<%= f.text_field :reference_user_id, :style=>"display:none"%>
|
||||
<div class="cl"></div>
|
||||
<% if @is_anonymous_comments || @is_teacher %>
|
||||
<strong style="float: left;">
|
||||
文件:
|
||||
</strong>
|
||||
<div id="homework_attach_jour_attachment">
|
||||
<%= render :partial => 'attachments/form' %>
|
||||
</div>
|
||||
<div class="cl"></div>
|
||||
<% end %>
|
||||
<div style="float:right">
|
||||
<a href="javascript:" class="ping_sub1" id="jours_submit" onclick="submit_jours(<%= @is_teacher%>);">
|
||||
<%= l(:label_confirmation) %>
|
||||
|
|
|
@ -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}个附件)", 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 || bid.comment_status == 2 %>
|
||||
<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 || bid.comment_status == 2 %>
|
||||
<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 %>
|
|
@ -9,7 +9,7 @@
|
|||
<span>
|
||||
<%= l(:label_homework_list)%>
|
||||
(<font color="#CC0000">
|
||||
<%= homework_count%>
|
||||
<%= homeworks.count%>
|
||||
</font>)
|
||||
<%
|
||||
url= get_batch_homeworks_homework_attach_index_path(:bid_id => @bid.id) if is_batch_homeworks
|
||||
|
@ -48,8 +48,8 @@
|
|||
</span>
|
||||
</li>
|
||||
<li class="c_red" style="margin:25px 0 0 20px;"> 您还没提交作品,请点击提交作品按钮:)</li>
|
||||
<li class="wping">
|
||||
<%= link_to "提交作品", new_exercise_book_path(@bid), :style => "width:80px; margin:20px 0 0 350px;" %>
|
||||
<li class="wping" style="float: right;">
|
||||
<%= link_to "提交作品", new_exercise_book_path(@bid), :style => "margin:20px 20px 0 0;width:80px;" %>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="cl"></div>
|
||||
|
@ -66,11 +66,11 @@
|
|||
<% else %>
|
||||
<% end %>
|
||||
<!-- 如果是我的作业或者匿评列表界面不现实分页控件 -->
|
||||
<% unless is_my_homework || is_student_batch_homework %>
|
||||
<ul class="wlist">
|
||||
<%= pagination_links_full @obj_pages, @obj_count, :per_page_links => false, :remote => remote, :flag => true%>
|
||||
</ul>
|
||||
<% end %>
|
||||
<%# unless is_my_homework || is_student_batch_homework %>
|
||||
<!--<ul class="wlist">-->
|
||||
<%#= pagination_links_full @obj_pages, @obj_count, :per_page_links => false, :remote => remote, :flag => true%>
|
||||
<!--</ul>-->
|
||||
<%# end %>
|
||||
|
||||
<% if is_teacher %>
|
||||
<span style="color: red;">
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<%= format_time(jour.created_on) %>
|
||||
</span>
|
||||
<div class="cl"></div>
|
||||
<p><%= textilizable jour.notes%></p>
|
||||
<%= textilizable jour.notes%>
|
||||
</div>
|
||||
<div class="ping_disfoot">
|
||||
<% ids = 'project_respond_form_'+ jour.id.to_s%>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<div class="ping_distop">
|
||||
<span>
|
||||
<% if show_name %>
|
||||
<%= link_to user, user_path(user),:style => " font-weight:bold; color:#15bccf; margin-right:5px; background:none;", :target => "_blank"%>
|
||||
<%= link_to user, user_path(user),:style => " font-weight:bold; color:#15bccf; margin-right:5px; background:none;max-width: 40px;overflow: hidden;", :target => "_blank", title: user%>
|
||||
<% else%>
|
||||
<span style=" font-weight:bold; color:#15bccf; margin-right:5px; background:none;">
|
||||
<%= l(:label_anonymous) %>
|
||||
|
@ -36,9 +36,17 @@
|
|||
<% end %>
|
||||
</span>
|
||||
<div class="cl"></div>
|
||||
<p><%= textilizable jour.nil? ? "" : jour.notes%></p>
|
||||
<% notes = textilizable(jour.nil? ? "" : jour.notes)%>
|
||||
<%= notes.empty? ? "<p></p>".html_safe : notes%>
|
||||
</div>
|
||||
<div class="cl"></div>
|
||||
<% unless jour.nil? %>
|
||||
<% unless jour.attachments.empty?%>
|
||||
<%= render :partial => 'attachments/homework_jour_link',
|
||||
:locals => {:attachments => jour.attachments} %>
|
||||
<% end %>
|
||||
<div class="cl"></div>
|
||||
|
||||
<% ids = 'project_respond_form_'+ jour.id.to_s%>
|
||||
<div class="ping_disfoot">
|
||||
<span>
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue