Merge remote-tracking branch 'origin/szzh' into szzh

Conflicts:
	public/assets/kindeditor/kindeditor.js
memcached_alan
lizanle 10 years ago
commit f7dd4924c1

1
.gitignore vendored

@ -5,6 +5,7 @@
*.swp *.swp
/config/database.yml /config/database.yml
/config/configuration.yml /config/configuration.yml
/config/additional_environment.rb
/files/* /files/*
/log/* /log/*
/public/tmp/* /public/tmp/*

@ -6,6 +6,7 @@ unless RUBY_PLATFORM =~ /w32/
gem 'iconv' gem 'iconv'
end end
gem 'redis-rails'
gem 'rubyzip' gem 'rubyzip'
gem 'delayed_job_active_record'#, :group => :production gem 'delayed_job_active_record'#, :group => :production
gem 'daemons' gem 'daemons'

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

@ -332,7 +332,7 @@ class AccountController < ApplicationController
token = Token.create(:user => user, :action => 'autologin') token = Token.create(:user => user, :action => 'autologin')
cookie_options = { cookie_options = {
:value => token.value, :value => token.value,
:expires => 1.year.from_now, :expires => 7.days.from_now,
:path => (Redmine::Configuration['autologin_cookie_path'] || '/'), :path => (Redmine::Configuration['autologin_cookie_path'] || '/'),
:secure => (Redmine::Configuration['autologin_cookie_secure'] ? true : false), :secure => (Redmine::Configuration['autologin_cookie_secure'] ? true : false),
:httponly => true :httponly => true

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

@ -793,7 +793,7 @@ class BidsController < ApplicationController
@bid.is_evaluation = params[:bid][:is_evaluation] @bid.is_evaluation = params[:bid][:is_evaluation]
@bid.proportion = params[:bid][:proportion] @bid.proportion = params[:bid][:proportion]
@bid.evaluation_num = params[:bid][:evaluation_num] @bid.evaluation_num = params[:bid][:evaluation_num]
@bid.open_anonymous_evaluation = params[:bid][:open_anonymous_evaluation] params[:bid][:open_anonymous_evaluation] ? @bid.open_anonymous_evaluation = 1 : @bid.open_anonymous_evaluation = 0
@bid.reward_type = 3 @bid.reward_type = 3
# @bid.budget = params[:bid][:budget] # @bid.budget = params[:bid][:budget]
@bid.deadline = params[:bid][:deadline] @bid.deadline = params[:bid][:deadline]

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

@ -708,7 +708,7 @@ class CoursesController < ApplicationController
#"show_course_journals_for_messages" => true, #"show_course_journals_for_messages" => true,
"show_bids" => true, "show_bids" => true,
"show_homeworks" => true, "show_homeworks" => true,
#"show_polls" => true "show_polls" => true
} }
@date_to ||= Date.today + 1 @date_to ||= Date.today + 1
@date_from = (@date_to - @days) > @course.created_at.to_date ? (@date_to - @days) : @course.created_at.to_date @date_from = (@date_to - @days) > @course.created_at.to_date ? (@date_to - @days) : @course.created_at.to_date

@ -145,10 +145,14 @@ class FilesController < ApplicationController
ids += version.id.to_s ids += version.id.to_s
end end
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}%"). if ids.blank?
reorder(sort) resultSet = Attachment.where("attachments.container_type = 'Project' And attachments.container_id = '#{project.id}' AND filename LIKE :like ", like: "%#{keywords}%").
#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") reorder(sort)
end else
resultSet = Attachment.where("((attachments.container_type = 'Project' And attachments.container_id = '#{project.id}') OR (container_type = 'Version' AND container_id IN (#{ids}))) AND filename LIKE :like ", like: "%#{keywords}%").
reorder(sort)
end
end
def find_public_attache keywords,sort = "" def find_public_attache keywords,sort = ""
# StoresController#search 将每条文件都查出来,再次进行判断过滤。---> resultSet.to_a.map # StoresController#search 将每条文件都查出来,再次进行判断过滤。---> resultSet.to_a.map

@ -95,6 +95,7 @@ class IssuesController < ApplicationController
format.api { format.api {
Issue.load_visible_relations(@issues) if include_in_api_response?('relations') Issue.load_visible_relations(@issues) if include_in_api_response?('relations')
} }
# format.json { render :json => @issues.map { |issue| issue.to_json}} #:json => @issues.map { |issue| issue.to_json}
format.atom { render_feed(@issues, :title => "#{@project || Setting.app_title}: #{l(:label_issue_plural)}") } format.atom { render_feed(@issues, :title => "#{@project || Setting.app_title}: #{l(:label_issue_plural)}") }
format.csv { send_data(query_to_csv(@issues, @query, params), :type => 'text/csv; header=present', :filename => 'issues.csv') } format.csv { send_data(query_to_csv(@issues, @query, params), :type => 'text/csv; header=present', :filename => 'issues.csv') }
format.pdf { send_data(issues_to_pdf(@issues, @project, @query), :type => 'application/pdf', :filename => 'issues.pdf') } format.pdf { send_data(issues_to_pdf(@issues, @project, @query), :type => 'application/pdf', :filename => 'issues.pdf') }

@ -60,8 +60,12 @@ class MembersController < ApplicationController
user_ids.each do |user_id| user_ids.each do |user_id|
AppliedProject.deleteappiled(user_id, @project.id) AppliedProject.deleteappiled(user_id, @project.id)
end end
@succes_message = "拒绝成功"
end end
end end
respond_to do |format|
format.js
end
else else
#modify by nwb #modify by nwb
#更改课程成员逻辑 #更改课程成员逻辑
@ -117,9 +121,14 @@ class MembersController < ApplicationController
format.html { redirect_to invite_members_project_url(@project) } format.html { redirect_to invite_members_project_url(@project) }
end end
else else
unless members.present? && members.all? {|m| m.valid? }
@project_error_message = members.empty? ? l(:label_user_role_null) :members.collect {|m| m.errors.full_messages}.flatten.uniq.join(', ')
else
@succes_message = "添加成功"
end
respond_to do |format| respond_to do |format|
format.html { redirect_to_settings_in_projects } format.html { redirect_to_settings_in_projects }
format.js { @members = members; @applied_members = applied_members; } format.js
format.api { format.api {
@member = members.first @member = members.first
if @member.valid? if @member.valid?
@ -184,6 +193,8 @@ class MembersController < ApplicationController
end # end of params[:refusal_button] end # end of params[:refusal_button]
end end
def update def update

@ -29,7 +29,7 @@ class PollController < ApplicationController
end end
#已提交问卷的用户不能再访问该界面 #已提交问卷的用户不能再访问该界面
if has_commit_poll?(@poll.id,User.current.id) && (!User.current.admin?) if has_commit_poll?(@poll.id,User.current.id) && (!User.current.admin?)
render_403 redirect_to poll_index_url(:polls_type => "Course", :polls_group_id => @course.id)
else else
@can_edit_poll = (!has_commit_poll?(@poll.id,User.current.id)) || User.current.admin? @can_edit_poll = (!has_commit_poll?(@poll.id,User.current.id)) || User.current.admin?
@percent = get_percent(@poll,User.current) @percent = get_percent(@poll,User.current)

@ -27,15 +27,7 @@ class ProjectsController < ApplicationController
menu_item :feedback, :only => :feedback menu_item :feedback, :only => :feedback
menu_item :share, :only => :share menu_item :share, :only => :share
before_filter :find_project, :except => [ :index, :search,:list, :new, :create, :copy, :statistics, :new_join,
:course, :enterprise_course, :course_enterprise,:view_homework_attaches]
before_filter :authorize, :only => [:show, :settings, :edit, :sort_project_members, :update, :modules, :close,
:reopen,:view_homework_attaches,:course]
before_filter :find_project, :except => [ :index, :search,:list, :new, :create, :copy, :statistics, :new_join, :course, :enterprise_course, :course_enterprise,:view_homework_attaches,:join_project] before_filter :find_project, :except => [ :index, :search,:list, :new, :create, :copy, :statistics, :new_join, :course, :enterprise_course, :course_enterprise,:view_homework_attaches,:join_project]
# before_filter :authorize, :except => [:new_join, :new_homework, :homework, :statistics, :search, :watcherlist, :index, :list, :new, :create, :copy, :archive, :unarchive, :destroy, :member, :focus, :file,
# :statistics, :feedback, :course, :enterprise_course, :course_enterprise, :project_respond, :share,
# :show_projects_score, :issue_score_index, :news_score_index, :file_score_index, :code_submit_score_index, :projects_topic_score_index]
#此条勿删 课程相关权限 ,:new_homework,:homework,:feedback,,:member
before_filter :authorize, :only => [:show, :settings, :edit, :sort_project_members, :update, :modules, :close, :reopen,:view_homework_attaches,:course] before_filter :authorize, :only => [:show, :settings, :edit, :sort_project_members, :update, :modules, :close, :reopen,:view_homework_attaches,:course]
before_filter :authorize_global, :only => [:new, :create,:view_homework_attaches] before_filter :authorize_global, :only => [:new, :create,:view_homework_attaches]
before_filter :require_admin, :only => [ :copy, :archive, :unarchive, :destroy, :calendar] before_filter :require_admin, :only => [ :copy, :archive, :unarchive, :destroy, :calendar]
@ -181,6 +173,7 @@ class ProjectsController < ApplicationController
@project.safe_attributes = params[:project] @project.safe_attributes = params[:project]
@project.organization_id = params[:organization_id] @project.organization_id = params[:organization_id]
@project.user_id = User.current.id @project.user_id = User.current.id
@project.project_new_type = 1
if validate_parent_id && @project.save if validate_parent_id && @project.save
@project.set_allowed_parent!(params[:project]['parent_id']) if params[:project].has_key?('parent_id') @project.set_allowed_parent!(params[:project]['parent_id']) if params[:project].has_key?('parent_id')
# Add current user as a project member if he is not admin # Add current user as a project member if he is not admin
@ -250,8 +243,10 @@ class ProjectsController < ApplicationController
# Author lizanle # Author lizanle
# Description 项目动态展示方法,删除了不必要的代码 # Description 项目动态展示方法,删除了不必要的代码
def show def show
# params[:login]为邮箱邀请用户加入,主要功能:
# 试图跳转到请求的按钮 # 1、自动注册
# 2、加入项目、创建角色
# 3、用户得分
if params[:login] if params[:login]
login = params[:login] login = params[:login]
login = login.sub(/%40/,'@') login = login.sub(/%40/,'@')
@ -259,6 +254,7 @@ class ProjectsController < ApplicationController
password = params[:password] password = params[:password]
us = UsersService.new us = UsersService.new
user = us.register_auto(login,mail, password) user = us.register_auto(login,mail, password)
Member.create(:role_ids => [4], :user_id => user.id,:project_id => @project.id) Member.create(:role_ids => [4], :user_id => user.id,:project_id => @project.id)
UserGrade.create(:user_id => user.id, :project_id => @project.id) UserGrade.create(:user_id => user.id, :project_id => @project.id)
User.current = user unless User.current.nil? User.current = user unless User.current.nil?
@ -331,6 +327,28 @@ class ProjectsController < ApplicationController
@member ||= @project.members.new @member ||= @project.members.new
@trackers = Tracker.sorted.all @trackers = Tracker.sorted.all
@wiki ||= @project.wiki @wiki ||= @project.wiki
@select_tab = params[:tab]
# 处理从新建版本库返回来的错误信息
if !params[:repository_error_message].to_s.blank?
html = ""
errors = params[:repository_error_message].flatten
errors.each do |error|
# 版本库路径为空的错误信息不予提示
if(error!=l(:label_repository_path_not_null))
html << error << ";"
end
end
if params[:repository] == "pswd_is_null"
html << l(:label_password_not_null)
end
flash[:error] = html if !html.to_s.blank?
end
scm = params[:repository_scm] || (Redmine::Scm::Base.all & Setting.enabled_scm).first
@repository = Repository.factory(scm)
@repository.is_default = @project.repository.nil?
@repository.project = @project
end end
def send_mail_to_member def send_mail_to_member
@ -379,7 +397,7 @@ class ProjectsController < ApplicationController
# include CoursesHelper # include CoursesHelper
def member def member
## 有角色参数的才是课程,没有的就是项目 ## 有角色参数的才是课程,没有的就是项目
@render_file = 'member_list' @render_file = 'project_member_list'
# 判断是否课程 # 判断是否课程
if @project.project_type == Project::ProjectType_course if @project.project_type == Project::ProjectType_course
@teachers= searchTeacherAndAssistant(@project) @teachers= searchTeacherAndAssistant(@project)
@ -455,22 +473,10 @@ class ProjectsController < ApplicationController
def update def update
@project.safe_attributes = params[:project] @project.safe_attributes = params[:project]
@project.organization_id = params[:organization_id] @project.organization_id = params[:organization_id]
#@project.dts_test = params[:project][:dts_test] params[:project][:is_public] ? @project.is_public = 1 : @project.is_public = 0
params[:project][:hidden_repo] ? @project.hidden_repo = 1 : @project.hidden_repo = 0
if validate_parent_id && @project.save if validate_parent_id && @project.save
@course = Course.find_by_extra(@project.identifier)
unless @course.nil?
@course.password = params[:project][:course][:password]
# added by bai
@course.term = params[:term]
@course.time = params[:time]
@course.setup_time = params[:setup_time]
@course.endup_time = params[:endup_time]
@course.class_period = params[:class_period]
# end
@course.save
end
@project.set_allowed_parent!(params[:project]['parent_id']) if params[:project].has_key?('parent_id') @project.set_allowed_parent!(params[:project]['parent_id']) if params[:project].has_key?('parent_id')
if params[:project][:is_public] == '0' if params[:project][:is_public] == '0'
project_status = ProjectStatus.find_by_project_id(@project.id) project_status = ProjectStatus.find_by_project_id(@project.id)
project_status.destroy if project_status project_status.destroy if project_status
@ -618,6 +624,17 @@ class ProjectsController < ApplicationController
end end
end end
#朋友圈、科研组、开发组之间的切换
def change_project_type
@project.project_new_type = params[:project_type]
if @project.save
message = @project.project_new_type
else
message = "0"
end
render :json => message
end
private private
def memberAccess def memberAccess

@ -25,6 +25,7 @@ class ChangesetNotFound < Exception; end
class InvalidRevisionParam < Exception; end class InvalidRevisionParam < Exception; end
class RepositoriesController < ApplicationController class RepositoriesController < ApplicationController
include ApplicationHelper
menu_item :repository menu_item :repository
menu_item :settings, :only => [:new, :create, :edit, :update, :destroy, :committers] menu_item :settings, :only => [:new, :create, :edit, :update, :destroy, :committers]
default_search_scope :changesets default_search_scope :changesets
@ -122,7 +123,7 @@ update
if request.post? && @repository.save if request.post? && @repository.save
redirect_to settings_project_url(@project, :tab => 'repositories') redirect_to settings_project_url(@project, :tab => 'repositories')
else else
render :action => 'new' redirect_to settings_project_url(@project, :tab => 'repositories')
end end
else # 原逻辑 else # 原逻辑
##xianbo ##xianbo
@ -167,11 +168,12 @@ update
@repository.update_attributes(:login => User.current.login.to_s) @repository.update_attributes(:login => User.current.login.to_s)
end end
redirect_to settings_project_url(@project, :tab => 'repositories') redirect_to settings_project_url(@project, :tab => 'repositories',:repository_error_message=>@repository.errors.full_messages)
else if(@repository_tag) else if(@repository_tag.blank?)
render :action => 'newrepo', :layout =>'base_projects' #render :action => 'newrepo', :layout =>'base_projects'
redirect_to settings_project_url(@project, :tab => 'repositories',:repository => "pswd_is_null",:repository_error_message=>@repository.errors.full_messages)
else else
render :action => 'new', :layout =>'base_projects' redirect_to settings_project_url(@project, :tab => 'repositories',:repository => @repository,:repository_error_message=>@repository.errors.full_messages)
end end
end end

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

@ -81,9 +81,10 @@ class WordsController < ApplicationController
@journal_destroyed = JournalsForMessage.delete_message(params[:object_id]) @journal_destroyed = JournalsForMessage.delete_message(params[:object_id])
if @journal_destroyed.jour_type == "Bid" if @journal_destroyed.jour_type == "Bid"
@bid = Bid.find(@journal_destroyed.jour_id) @bid = Bid.find(@journal_destroyed.jour_id)
end
if @bid
@jours_count = @bid.journals_for_messages.where('m_parent_id IS NULL').count @jours_count = @bid.journals_for_messages.where('m_parent_id IS NULL').count
elsif @journal_destroyed.jour_type == "Course"
@course = Course.find @journal_destroyed.jour_id
@jours_count = @course.journals_for_messages.where('m_parent_id IS NULL').count
end end
respond_to do |format| respond_to do |format|
format.js format.js

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

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

@ -81,7 +81,7 @@ module ApplicationHelper
def authorize_for(controller, action) def authorize_for(controller, action)
User.current.allowed_to?({:controller => controller, :action => action}, @project) User.current.allowed_to?({:controller => controller, :action => action}, @project)
end end
# add by nwb # add by nwb
def authorize_for_course(controller, action) def authorize_for_course(controller, action)
User.current.allowed_to?({:controller => controller, :action => action}, @course) User.current.allowed_to?({:controller => controller, :action => action}, @course)
@ -128,6 +128,24 @@ module ApplicationHelper
end end
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={} def link_to_user_header user,canShowRealName=false,options={}
if user.is_a?(User) if user.is_a?(User)
@ -170,6 +188,28 @@ module ApplicationHelper
s s
end 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. # Generates a link to an attachment.
# Options: # Options:
# * :text - Link text (default to attachment filename) # * :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 route_method = options.delete(:download) ? :download_named_attachment_path : :named_attachment_path
html_options = options.slice!(:only_path) html_options = options.slice!(:only_path)
url = send(route_method, attachment, attachment.filename, options) 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 link_to text, url, html_options
end end
@ -218,18 +258,18 @@ module ApplicationHelper
h(text), h(text),
{:controller => 'repositories', :action => 'revision', :id => repository.project, :repository_id => repository.identifier_param, :rev => rev}, {:controller => 'repositories', :action => 'revision', :id => repository.project, :repository_id => repository.identifier_param, :rev => rev},
:title => l(:label_revision_id, format_revision(revision)) :title => l(:label_revision_id, format_revision(revision))
) )
end end
# Generates a link to a message # Generates a link to a message
def link_to_message(message, options={}, html_options = nil) def link_to_message(message, options={}, html_options = nil)
link_to( link_to(
truncate(message.subject, :length => 60), truncate(message.subject, :length => 60),
board_message_path(message.board_id, message.parent_id || message.id, { board_message_path(message.board_id, message.parent_id || message.id, {
:r => (message.parent_id && message.id), :r => (message.parent_id && message.id),
:anchor => (message.parent_id ? "message-#{message.id}" : nil) :anchor => (message.parent_id ? "message-#{message.id}" : nil)
}.merge(options)), }.merge(options)),
html_options html_options
) )
end end
@ -281,8 +321,22 @@ module ApplicationHelper
def thumbnail_tag(attachment) def thumbnail_tag(attachment)
link_to image_tag(thumbnail_path(attachment)), link_to image_tag(thumbnail_path(attachment)),
named_attachment_path(attachment, attachment.filename), named_attachment_path(attachment, attachment.filename),
:title => attachment.filename :title => attachment.filename
end
def thumbnail_issue_tag(attachment)
imagesize = attachment.thumbnail(:size => "50*50")
imagepath = named_attachment_path(attachment, attachment.filename)
if imagesize
link_to image_tag(imagesize),
imagepath,
:title => attachment.filename
else
link_to image_tag(imagepath , height: '73', width: '100'),
imagepath,
:title => attachment.filename
end
end end
# 图片缩略图链接 # 图片缩略图链接
@ -310,9 +364,9 @@ module ApplicationHelper
def image_to_function(name, function, html_options = {}) def image_to_function(name, function, html_options = {})
html_options.symbolize_keys! html_options.symbolize_keys!
tag(:input, html_options.merge({ tag(:input, html_options.merge({
:type => "image", :src => image_path(name), :type => "image", :src => image_path(name),
:onclick => (html_options[:onclick] ? "#{html_options[:onclick]}; " : "") + "#{function};" :onclick => (html_options[:onclick] ? "#{html_options[:onclick]}; " : "") + "#{function};"
})) }))
end end
def format_activity_title(text) def format_activity_title(text)
@ -330,9 +384,9 @@ module ApplicationHelper
def format_version_name(version) def format_version_name(version)
if version.project == @project if version.project == @project
h(version) h(truncate(version.name,:length=>20))
else else
h("#{version.project} - #{version}") h("#{version.project} - #{truncate(version.name,:length=>20)}")
end end
end end
@ -346,7 +400,7 @@ module ApplicationHelper
# The given collection may be a subset of the whole project tree # The given collection may be a subset of the whole project tree
# (eg. some intermediate nodes are private and can not be seen) # (eg. some intermediate nodes are private and can not be seen)
#Modified by nie. #Modified by nie.
def render_project_nested_lists(projects) def render_project_nested_lists(projects)
s = '' s = ''
if projects.any? if projects.any?
ancestors = [] ancestors = []
@ -375,9 +429,9 @@ module ApplicationHelper
if project.try(:project_type) == Project::ProjectType_project if project.try(:project_type) == Project::ProjectType_project
unless User.current.member_of?(@project) unless User.current.member_of?(@project)
s << "<span style = 'float: right;'>" s << "<span style = 'float: right;'>"
s << watcher_link(@project, User.current)#, ['whiteButton']) s << watcher_link(@project, User.current)#, ['whiteButton'])
s << "</span>" s << "</span>"
end end
s << (render :partial => 'projects/project', :locals => {:project => project}).to_s s << (render :partial => 'projects/project', :locals => {:project => project}).to_s
else else
@ -390,7 +444,7 @@ module ApplicationHelper
@project = original_project @project = original_project
end end
s.html_safe s.html_safe
end end
def render_course_nested_lists(courses) def render_course_nested_lists(courses)
s = '' s = ''
@ -425,7 +479,7 @@ module ApplicationHelper
end end
#added by young #added by young
def render_project_nested_lists_new(projects) def render_project_nested_lists_new(projects)
s = '' s = ''
if projects.any? if projects.any?
@ -454,7 +508,7 @@ module ApplicationHelper
end end
s.html_safe s.html_safe
end end
#end #end
def render_page_hierarchy(pages, node=nil, options={}) def render_page_hierarchy(pages, node=nil, options={})
content = '' content = ''
if pages[node] if pages[node]
@ -489,14 +543,22 @@ module ApplicationHelper
end end
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 # Renders the project quick-jump box
def render_project_jump_box def render_project_jump_box
return unless User.current.logged? return unless User.current.logged?
projects = User.current.memberships.collect(&:project).compact.select(&:active?).uniq projects = User.current.memberships.collect(&:project).compact.select(&:active?).uniq
if projects.any? if projects.any?
options = options =
("<option value=''>#{ l(:label_jump_to_a_project) }</option>" + ("<option value=''>#{ l(:label_jump_to_a_project) }</option>" +
'<option value="" disabled="disabled">---</option>').html_safe '<option value="" disabled="disabled">---</option>').html_safe
options << project_tree_options_for_select(projects, :selected => @project) do |p| options << project_tree_options_for_select(projects, :selected => @project) do |p|
{ :value => project_path(:id => p, :jump => current_menu_item) } { :value => project_path(:id => p, :jump => current_menu_item) }
@ -547,6 +609,17 @@ module ApplicationHelper
s.html_safe s.html_safe
end 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生成 #扩展的checkbox生成
def principals_check_box_tags_ex(name, principals) def principals_check_box_tags_ex(name, principals)
s = '' s = ''
@ -556,6 +629,15 @@ module ApplicationHelper
s.html_safe s.html_safe
end 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生成 #扩展的checkbox生成
def principals_radio_box_tags_ex(name, principals) def principals_radio_box_tags_ex(name, principals)
s = '' s = ''
@ -666,24 +748,24 @@ module ApplicationHelper
link_to(image_tag('2uparrow.png', :alt => l(:label_sort_highest)), link_to(image_tag('2uparrow.png', :alt => l(:label_sort_highest)),
url.merge({"#{name}[move_to]" => 'highest'}), url.merge({"#{name}[move_to]" => 'highest'}),
:method => method, :title => l(:label_sort_highest)) + :method => method, :title => l(:label_sort_highest)) +
link_to(image_tag('1uparrow.png', :alt => l(:label_sort_higher)), link_to(image_tag('1uparrow.png', :alt => l(:label_sort_higher)),
url.merge({"#{name}[move_to]" => 'higher'}), url.merge({"#{name}[move_to]" => 'higher'}),
:method => method, :title => l(:label_sort_higher)) + :method => method, :title => l(:label_sort_higher)) +
link_to(image_tag('1downarrow.png', :alt => l(:label_sort_lower)), link_to(image_tag('1downarrow.png', :alt => l(:label_sort_lower)),
url.merge({"#{name}[move_to]" => 'lower'}), url.merge({"#{name}[move_to]" => 'lower'}),
:method => method, :title => l(:label_sort_lower)) + :method => method, :title => l(:label_sort_lower)) +
link_to(image_tag('2downarrow.png', :alt => l(:label_sort_lowest)), link_to(image_tag('2downarrow.png', :alt => l(:label_sort_lowest)),
url.merge({"#{name}[move_to]" => 'lowest'}), url.merge({"#{name}[move_to]" => 'lowest'}),
:method => method, :title => l(:label_sort_lowest)) :method => method, :title => l(:label_sort_lowest))
end end
def breadcrumb(*args) def breadcrumb(*args)
elements = args.flatten 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 end
def other_formats_links(&block) 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) yield Redmine::Views::OtherFormatsBuilder.new(self)
concat('</p>'.html_safe) concat('</p>'.html_safe)
end end
@ -758,15 +840,15 @@ module ApplicationHelper
def textilizable(*args) def textilizable(*args)
options = args.last.is_a?(Hash) ? args.pop : {} options = args.last.is_a?(Hash) ? args.pop : {}
case args.size case args.size
when 1 when 1
obj = options[:object] obj = options[:object]
text = args.shift text = args.shift
when 2 when 2
obj = args.shift obj = args.shift
attr = args.shift attr = args.shift
text = obj.send(attr).to_s text = obj.send(attr).to_s
else else
raise ArgumentError, 'invalid arguments to textilizable' raise ArgumentError, 'invalid arguments to textilizable'
end end
return '' if text.blank? return '' if text.blank?
project = options[:project] || @project || (obj && obj.respond_to?(:project) ? obj.project : nil) project = options[:project] || @project || (obj && obj.respond_to?(:project) ? obj.project : nil)
@ -922,18 +1004,18 @@ module ApplicationHelper
# check if page exists # check if page exists
wiki_page = link_project.wiki.find_page(page) 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 url = if anchor.present? && wiki_page.present? && (obj.is_a?(WikiContent) || obj.is_a?(WikiContent::Version)) && obj.page == wiki_page
"##{anchor}" "##{anchor}"
else else
case options[:wiki_links] case options[:wiki_links]
when :local; "#{page.present? ? Wiki.titleize(page) : ''}.html" + (anchor.present? ? "##{anchor}" : '') 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 when :anchor; "##{page.present? ? Wiki.titleize(page) : title}" + (anchor.present? ? "_#{anchor}" : '') # used for single-file wiki export
else else
wiki_page_id = page.present? ? Wiki.titleize(page) : nil 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 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, url_for(:only_path => only_path, :controller => 'wiki', :action => 'show', :project_id => link_project,
:id => wiki_page_id, :version => nil, :anchor => anchor, :parent => parent) :id => wiki_page_id, :version => nil, :anchor => anchor, :parent => parent)
end end
end end
link_to(title.present? ? title.html_safe : h(page), url, :class => ('wiki-page' + (wiki_page ? '' : ' new'))) link_to(title.present? ? title.html_safe : h(page), url, :class => ('wiki-page' + (wiki_page ? '' : ' new')))
else else
# project or wiki doesn't exist # project or wiki doesn't exist
@ -1008,110 +1090,110 @@ module ApplicationHelper
# project.changesets.visible raises an SQL error because of a double join on repositories # 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)) 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}, 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', :class => 'changeset',
:title => truncate_single_line(changeset.comments, :length => 100)) :title => truncate_single_line(changeset.comments, :length => 100))
end end
end end
elsif sep == '#' elsif sep == '#'
oid = identifier.to_i oid = identifier.to_i
case prefix case prefix
when nil when nil
if oid.to_s == identifier && issue = Issue.visible.find_by_id(oid, :include => :status) if oid.to_s == identifier && issue = Issue.visible.find_by_id(oid, :include => :status)
anchor = comment_id ? "note-#{comment_id}" : nil anchor = comment_id ? "note-#{comment_id}" : nil
link = link_to("##{oid}", {:only_path => only_path, :controller => 'issues', :action => 'show', :id => oid, :anchor => anchor}, link = link_to("##{oid}", {:only_path => only_path, :controller => 'issues', :action => 'show', :id => oid, :anchor => anchor},
:class => issue.css_classes, :class => issue.css_classes,
:title => "#{truncate(issue.subject, :length => 100)} (#{issue.status.name})") :title => "#{truncate(issue.subject, :length => 100)} (#{issue.status.name})")
end end
when 'document' when 'document'
if document = Document.visible.find_by_id(oid) if document = Document.visible.find_by_id(oid)
link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document}, link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document},
:class => 'document' :class => 'document'
end end
when 'version' when 'version'
if version = Version.visible.find_by_id(oid) if version = Version.visible.find_by_id(oid)
link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version}, link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version},
:class => 'version' :class => 'version'
end end
when 'message' when 'message'
if message = Message.visible.find_by_id(oid, :include => :parent) if message = Message.visible.find_by_id(oid, :include => :parent)
link = link_to_message(message, {:only_path => only_path}, :class => 'message') link = link_to_message(message, {:only_path => only_path}, :class => 'message')
end end
when 'forum' when 'forum'
if board = Board.visible.find_by_id(oid) 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}, link = link_to h(board.name), {:only_path => only_path, :controller => 'boards', :action => 'show', :id => board, :project_id => board.project},
:class => 'board' :class => 'board'
end end
when 'news' when 'news'
if news = News.visible.find_by_id(oid) if news = News.visible.find_by_id(oid)
link = link_to h(news.title), {:only_path => only_path, :controller => 'news', :action => 'show', :id => news}, link = link_to h(news.title), {:only_path => only_path, :controller => 'news', :action => 'show', :id => news},
:class => 'news' :class => 'news'
end end
when 'project' when 'project'
if p = Project.visible.find_by_id(oid) if p = Project.visible.find_by_id(oid)
link = link_to_project(p, {:only_path => only_path}, :class => 'project') link = link_to_project(p, {:only_path => only_path}, :class => 'project')
end end
end end
elsif sep == ':' elsif sep == ':'
# removes the double quotes if any # removes the double quotes if any
name = identifier.gsub(%r{^"(.*)"$}, "\\1") name = identifier.gsub(%r{^"(.*)"$}, "\\1")
case prefix case prefix
when 'document' when 'document'
if project && document = project.documents.visible.find_by_title(name) 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}, link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document},
:class => 'document' :class => 'document'
end end
when 'version' when 'version'
if project && version = project.versions.visible.find_by_name(name) 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}, link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version},
:class => 'version' :class => 'version'
end end
when 'forum' when 'forum'
if project && board = project.boards.visible.find_by_name(name) 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}, link = link_to h(board.name), {:only_path => only_path, :controller => 'boards', :action => 'show', :id => board, :project_id => board.project},
:class => 'board' :class => 'board'
end end
when 'news' when 'news'
if project && news = project.news.visible.find_by_title(name) 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}, link = link_to h(news.title), {:only_path => only_path, :controller => 'news', :action => 'show', :id => news},
:class => '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 end
if prefix == 'commit' when 'commit', 'source', 'export'
if repository && (changeset = Changeset.visible.where("repository_id = ? AND scmid LIKE ?", repository.id, "#{name}%").first) if project
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}, repository = nil
:class => 'changeset', if name =~ %r{^(([a-z0-9\-_]+)\|)(.+)$}
:title => truncate_single_line(changeset.comments, :length => 100) repo_prefix, repo_identifier, name = $1, $2, $3
repository = project.repositories.detect {|repo| repo.identifier == repo_identifier}
else
repository = project.repository
end end
else if prefix == 'commit'
if repository && User.current.allowed_to?(:browse_repository, project) if repository && (changeset = Changeset.visible.where("repository_id = ? AND scmid LIKE ?", repository.id, "#{name}%").first)
name =~ %r{^[/\\]*(.*?)(@([^/\\@]+?))?(#(L\d+))?$} 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},
path, rev, anchor = $1, $3, $5 :class => 'changeset',
link = link_to h("#{project_prefix}#{prefix}:#{repo_prefix}#{name}"), {:controller => 'repositories', :action => (prefix == 'export' ? 'raw' : 'entry'), :id => project, :repository_id => repository.identifier_param, :title => truncate_single_line(changeset.comments, :length => 100)
:path => to_path_param(path), end
:rev => rev, else
:anchor => anchor}, if repository && User.current.allowed_to?(:browse_repository, project)
:class => (prefix == 'export' ? 'source download' : 'source') 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 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
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 end
end end
@ -1128,9 +1210,9 @@ module ApplicationHelper
@current_section += 1 @current_section += 1
if @current_section > 1 if @current_section > 1
content_tag('div', content_tag('div',
link_to(image_tag('edit.png'), options[:edit_section_links].merge(:section => @current_section)), link_to(image_tag('edit.png'), options[:edit_section_links].merge(:section => @current_section)),
:class => 'contextual', :class => 'contextual',
:title => l(:button_edit_section)) + heading.html_safe :title => l(:button_edit_section)) + heading.html_safe
else else
heading heading
end end
@ -1249,10 +1331,10 @@ module ApplicationHelper
# Same as Rails' simple_format helper without using paragraphs # Same as Rails' simple_format helper without using paragraphs
def simple_format_without_paragraph(text) def simple_format_without_paragraph(text)
text.to_s. text.to_s.
gsub(/\r\n?/, "\n"). # \r\n and \r -> \n gsub(/\r\n?/, "\n"). # \r\n and \r -> \n
gsub(/\n\n+/, "<br /><br />"). # 2+ newline -> 2 br gsub(/\n\n+/, "<br /><br />"). # 2+ newline -> 2 br
gsub(/([^\n]\n)(?=[^\n])/, '\1<br />'). # 1 newline -> br gsub(/([^\n]\n)(?=[^\n])/, '\1<br />'). # 1 newline -> br
html_safe html_safe
end end
def wiki_simple_format_without_paragraph(text) def wiki_simple_format_without_paragraph(text)
@ -1267,7 +1349,7 @@ module ApplicationHelper
end end
def lang_options_for_select(blank=true) def lang_options_for_select(blank=true)
{ 'Chinese简体中文 '=> 'zh', :English => :en} { 'Chinese简体中文 '=> 'zh', :English => :en}
end end
def label_tag_for(name, option_tags = nil, options = {}) def label_tag_for(name, option_tags = nil, options = {})
@ -1334,9 +1416,31 @@ module ApplicationHelper
def delete_link(url, options={}) def delete_link(url, options={})
options = { options = {
:method => :delete, :method => :delete,
:data => {:confirm => l(:text_are_you_sure)}, :data => {:confirm => l(:text_are_you_sure)},
:class => 'icon icon-del' :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) }.merge(options)
link_to l(:button_delete), url, options link_to l(:button_delete), url, options
@ -1347,11 +1451,11 @@ module ApplicationHelper
:href => "#", :href => "#",
:onclick => %|submitPreview("#{escape_javascript url_for(url)}", "#{escape_javascript form}", "#{escape_javascript target}"); return false;|, :onclick => %|submitPreview("#{escape_javascript url_for(url)}", "#{escape_javascript form}", "#{escape_javascript target}"); return false;|,
:accesskey => accesskey(:preview) :accesskey => accesskey(:preview)
}.merge(options) }.merge(options)
end end
def link_to_function(name, function, html_options={}) 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 end
# Helper to render JSON in views # Helper to render JSON in views
@ -1373,9 +1477,8 @@ module ApplicationHelper
end end
def check_all_links(form_name) def check_all_links(form_name)
link_to_function(l(:button_check_all), "checkAll('#{form_name}', true)") + link_to_function(l(:button_check_all), "checkAll('#{form_name}', true)") + "&nbsp;&nbsp;".html_safe + " | "+ "&nbsp;&nbsp;".html_safe +
" | ".html_safe + link_to_function(l(:button_uncheck_all), "checkAll('#{form_name}', false)")
link_to_function(l(:button_uncheck_all), "checkAll('#{form_name}', false)")
end end
def progress_bar(pcts, options={}) def progress_bar(pcts, options={})
@ -1386,12 +1489,12 @@ module ApplicationHelper
width = options[:width] || '100px;' width = options[:width] || '100px;'
legend = options[:legend] || '' legend = options[:legend] || ''
content_tag('table', content_tag('table',
content_tag('tr', content_tag('tr',
(pcts[0] > 0 ? content_tag('td', '', :style => "width: #{pcts[0]}%;", :class => 'closed') : ''.html_safe) + (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[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) (pcts[2] > 0 ? content_tag('td', '', :style => "width: #{pcts[2]}%;", :class => 'todo') : ''.html_safe)
), :class => 'progress', :style => "width: #{width};").html_safe + ), :class => 'progress', :style => "width: #{width};").html_safe +
content_tag('p', legend, :class => 'percent').html_safe content_tag('p', legend, :class => 'percent').html_safe
end end
def checked_image(checked=true) def checked_image(checked=true)
@ -1404,7 +1507,7 @@ module ApplicationHelper
unless @context_menu_included unless @context_menu_included
content_for :header_tags do content_for :header_tags do
javascript_include_tag('context_menu') + javascript_include_tag('context_menu') +
stylesheet_link_tag('context_menu') stylesheet_link_tag('context_menu')
end end
if l(:direction) == 'rtl' if l(:direction) == 'rtl'
content_for :header_tags do content_for :header_tags do
@ -1435,7 +1538,7 @@ module ApplicationHelper
tags = javascript_tag( tags = javascript_tag(
"var datepickerOptions={dateFormat: 'yy-mm-dd', firstDay: #{start_of_week}, " + "var datepickerOptions={dateFormat: 'yy-mm-dd', firstDay: #{start_of_week}, " +
"showOn: 'button', buttonImageOnly: true, buttonImage: '" + "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};") "', showButtonPanel: true, showWeek: true, showOtherMonths: true, selectOtherMonths: true};")
jquery_locale = l('jquery.locale', :default => current_language.to_s) jquery_locale = l('jquery.locale', :default => current_language.to_s)
unless jquery_locale == 'en' unless jquery_locale == 'en'
@ -1457,7 +1560,7 @@ module ApplicationHelper
tags = javascript_tag( tags = javascript_tag(
"var datepickerOptions={dateFormat: 'yy-mm-dd',minDate: new Date(), firstDay: #{start_of_week}, " + "var datepickerOptions={dateFormat: 'yy-mm-dd',minDate: new Date(), firstDay: #{start_of_week}, " +
"showOn: 'button', buttonImageOnly: true, buttonImage: '" + "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);} };") "', 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) jquery_locale = l('jquery.locale', :default => current_language.to_s)
unless jquery_locale == 'en' unless jquery_locale == 'en'
@ -1663,7 +1766,7 @@ module ApplicationHelper
end end
s s
end end
def get_memo def get_memo
@new_memo = Memo.new @new_memo = Memo.new
#@new_memo.subject = "有什么想说的,尽管来咆哮吧~~" #@new_memo.subject = "有什么想说的,尽管来咆哮吧~~"
@ -1717,6 +1820,17 @@ module ApplicationHelper
candown candown
end 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 private
def wiki_helper def wiki_helper
@ -1746,11 +1860,11 @@ module ApplicationHelper
html << (content_tag "span", l(:label_no_current_watchers)) html << (content_tag "span", l(:label_no_current_watchers))
end end
for user in User.watched_by(obj.id) 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}") html << (link_to image_tag(url_to_avatar(user), :class => "avatar"), user_path(user), :class => "avatar", :title => "#{user.name}")
count = count + 1 count = count + 1
if count >= 12 if count >= 12
break break
end end
end end
html.html_safe html.html_safe
end end
@ -1776,13 +1890,13 @@ module ApplicationHelper
html.html_safe html.html_safe
end end
def show_bid_fans_picture(obj) def show_bid_fans_picture(obj)
html = '' html = ''
if obj.watcher_users.count == 0 if obj.watcher_users.count == 0
html << (content_tag "span", l(:label_project_no_follow)) html << (content_tag "span", l(:label_project_no_follow))
else else
obj.watcher_users.take(12).each do |user| 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
end end
html.html_safe html.html_safe
@ -1817,7 +1931,7 @@ module ApplicationHelper
html.html_safe html.html_safe
end end
def show_contest_project(contest) def show_contest_project(contest)
html = '' html = ''
if contest.projects.where('is_public = 1').count == 0 if contest.projects.where('is_public = 1').count == 0
html << (content_tag "p", l(:label_no_bid_project), :class => "font_lighter") html << (content_tag "p", l(:label_no_bid_project), :class => "font_lighter")
@ -1829,7 +1943,7 @@ module ApplicationHelper
html.html_safe html.html_safe
end end
def show_contest_softapplication(contest) def show_contest_softapplication(contest)
html = '' html = ''
if contest.softapplications.where('is_public = 1').count == 0 if contest.softapplications.where('is_public = 1').count == 0
html << (content_tag "p", l(:label_no_contest_softapplication), :class => "font_lighter") html << (content_tag "p", l(:label_no_contest_softapplication), :class => "font_lighter")
@ -1841,17 +1955,17 @@ module ApplicationHelper
html.html_safe html.html_safe
end end
def show_contest_fans_picture(obj) def show_contest_fans_picture(obj)
html = '' html = ''
if obj.watcher_users.count == 0 if obj.watcher_users.count == 0
html << (content_tag "span", l(:label_project_no_follow)) html << (content_tag "span", l(:label_project_no_follow))
else else
obj.watcher_users.take(12).each do |user| 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
end end
html.html_safe html.html_safe
end end
#display fans picture #display fans picture
def show_more_fans?(obj) def show_more_fans?(obj)
@ -1868,13 +1982,13 @@ module ApplicationHelper
html << (content_tag "span", l(:label_no_current_fans)) html << (content_tag "span", l(:label_no_current_fans))
else else
obj.watcher_users.take(12).each do |user| 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
end end
html.html_safe html.html_safe
end end
# added by bai # added by bai
def show_more_participate?(obj) def show_more_participate?(obj)
if obj.join_in_contests.count > 12 if obj.join_in_contests.count > 12
return true return true
@ -1883,18 +1997,18 @@ module ApplicationHelper
end end
end end
def show_participate_picture(obj) def show_participate_picture(obj)
html = '' html = ''
count = 0 count = 0
if obj.join_in_contests.count == 0 if obj.join_in_contests.count == 0
html << (content_tag "span", l(:label_no_current_participate)) html << (content_tag "span", l(:label_no_current_participate))
end end
for temp in obj.join_in_contests 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}") 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 count = count + 1
if count >= 12 if count >= 12
break break
end end
end end
html.html_safe html.html_safe
end end
@ -1903,14 +2017,14 @@ module ApplicationHelper
# add by huang # add by huang
def show_watcher_list(user) def show_watcher_list(user)
html = '' html = ''
count = 0 count = 0
for user in User.watched_by(user.id) 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}") html << (link_to image_tag(url_to_avatar(user), :class => "avatar"), user_path(user), :class => "avatar", :title => "#{user.name}")
count = count + 1 count = count + 1
if count >= 12 if count >= 12
break break
end end
end end
html.html_safe html.html_safe
end end
@ -1928,14 +2042,14 @@ module ApplicationHelper
return true if bid.nil? return true if bid.nil?
case bid.homework_type case bid.homework_type
when Bid::HomeworkFile when Bid::HomeworkFile
attaches = HomeworkAttach.where(bid_id: curb) attaches = HomeworkAttach.where(bid_id: curb)
attaches.map(&:user_id).include? cur attaches.map(&:user_id).include? cur
when Bid::HomeworkProject when Bid::HomeworkProject
attaches = BidingProject.where(user_id: User.current, bid_id: bid) attaches = BidingProject.where(user_id: User.current, bid_id: bid)
attaches.count > 0 # > 0 则有提交记录 attaches.count > 0 # > 0 则有提交记录
else else
true true
end end
end end
@ -1964,6 +2078,8 @@ module ApplicationHelper
forum_link = link_to l(:label_forum_all), {:controller => "forums", :action => "index"} forum_link = link_to l(:label_forum_all), {:controller => "forums", :action => "index"}
stores_link = link_to l(:label_stores_index), {:controller => 'stores', :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'} 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_dispaly_project_label
nav_list = Array.new nav_list = Array.new
@ -1976,6 +2092,8 @@ module ApplicationHelper
nav_list.push(main_contest_link) if @nav_dispaly_main_contest_label && @show_contest == 1 && visiable 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(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(projects_link) if @nav_dispaly_project_label
#nav_list.push(users_link) if @nav_dispaly_user_label #nav_list.push(users_link) if @nav_dispaly_user_label
# nav_list.push(contest_link) if @nav_dispaly_contest_label && @show_contest == 1 # nav_list.push(contest_link) if @nav_dispaly_contest_label && @show_contest == 1
@ -1995,12 +2113,12 @@ module ApplicationHelper
end end
# def hadcommittedforcontest(curu) # def hadcommittedforcontest(curu)
# message = JournalsForMessage.find_by_sql("select * from journals_for_messages where jour_type = 'Softapplication' ") # message = JournalsForMessage.find_by_sql("select * from journals_for_messages where jour_type = 'Softapplication' ")
# message.each do |createmessage| # message.each do |createmessage|
# if createmessage.user_id == curu # if createmessage.user_id == curu
# return true # return true
# end # end
# end # end
# end # end
def footer_logo(ul_class=nil, li_class=nil) def footer_logo(ul_class=nil, li_class=nil)
@ -2020,16 +2138,16 @@ module ApplicationHelper
def sort_homework_path(bid, sort, direction) def sort_homework_path(bid, sort, direction)
case self.action_name case self.action_name
when 'show_courseEx' when 'show_courseEx'
get_not_batch_homework_homework_attach_index_path(bid_id: bid.id, sort: sort, direction: 'asc') get_not_batch_homework_homework_attach_index_path(bid_id: bid.id, sort: sort, direction: 'asc')
when 'get_not_batch_homework' when 'get_not_batch_homework'
get_not_batch_homework_homework_attach_index_path(bid_id: bid.id, sort: sort, direction: direction) get_not_batch_homework_homework_attach_index_path(bid_id: bid.id, sort: sort, direction: direction)
when 'get_batch_homeworks' when 'get_batch_homeworks'
get_batch_homeworks_homework_attach_index_path(bid_id: bid.id, sort: sort, direction: direction) get_batch_homeworks_homework_attach_index_path(bid_id: bid.id, sort: sort, direction: direction)
when 'get_homeworks' when 'get_homeworks'
get_homeworks_homework_attach_index_path(bid_id: bid.id, sort: sort, direction: direction) get_homeworks_homework_attach_index_path(bid_id: bid.id, sort: sort, direction: direction)
else else
'#' '#'
end end
end end

@ -35,6 +35,16 @@ module AttachmentsHelper
end end
end end
def link_to_attachment_project(container, options = {})
options.assert_valid_keys(:author, :thumbnails)
if container.attachments.any?
options = {:deletable => container.attachments_deletable?, :author => true}.merge(options)
render :partial => 'attachments/project_file_links',
:locals => {:attachments => container.attachments, :options => options, :thumbnails => (options[:thumbnails] && Setting.thumbnails_enabled?)}
end
end
def link_to_attachments_course(container, options = {}) def link_to_attachments_course(container, options = {})
options.assert_valid_keys(:author, :thumbnails) options.assert_valid_keys(:author, :thumbnails)

@ -691,9 +691,11 @@ module CoursesHelper
#end #end
#poll_count #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 # Poll.where(polls_group_id: @course_ids, polls_type: Course, polls_status: 2||3).where("published_at>?",date_from).each do |poll|
#end 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 #end

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

@ -61,12 +61,38 @@ module IssuesHelper
#h("#{issue.tracker} ##{issue.id}") #h("#{issue.tracker} ##{issue.id}")
# h("#{issue.tracker} #{issue.source_from}") # h("#{issue.tracker} #{issue.source_from}")
s = '' s = ''
s << link_to(@issue.project.name, project_issues_path(@issue.project)) s << link_to(@issue.project.name, project_issues_path(@issue.project), :class => "pro_page_top")
s << " > #" s << " > "
s << @issue.project_index s << link_to("#" + @issue.project_index, project_issues_path(@issue.project), :class => "pro_page_top")
s.html_safe s.html_safe
end end
#获取跟踪类型
#REDO:时间紧需要优化,两个方法可以综合成一个
def get_issue_type(value)
if value == "缺陷" || value == 1
class_type = "red_btn_cir ml10"
elsif value == "功能" || value == 2
class_type = "blue_btn_cir ml10"
elsif value == "支持" || value == 3
class_type = "green_btn_cir ml10"
else
class_type = "orange_btn_cir ml10"
end
end
def get_issue_typevalue(value)
if value == "缺陷" || value == 1
assign = "缺陷"
elsif value == "功能" || value == 2
assign = "功能"
elsif value == "支持" || value == 3
assign = "支持"
else
assign = "任务"
end
end
def render_issue_subject_with_tree(issue) def render_issue_subject_with_tree(issue)
s = '' s = ''
ancestors = issue.root? ? [] : issue.ancestors.visible.all ancestors = issue.root? ? [] : issue.ancestors.visible.all
@ -314,17 +340,18 @@ module IssuesHelper
if detail.property == 'attachment' && !value.blank? && atta = Attachment.find_by_id(detail.prop_key) if detail.property == 'attachment' && !value.blank? && atta = Attachment.find_by_id(detail.prop_key)
# Link to the attachment if it has not been removed # Link to the attachment if it has not been removed
if options[:token].nil? if options[:token].nil?
value = link_to_attachment(atta, :download => true, :only_path => options[:only_path]) value = atta.filename
else else
value = link_to_attachment(atta, :download => true, :only_path => options[:only_path], :token => options[:token]) value = atta.filename
end
if options[:only_path] != false && atta.is_text?
value += link_to(
image_tag('magnifier.png'),
:controller => 'attachments', :action => 'show',
:id => atta, :filename => atta.filename
)
end end
# 放大镜搜索功能
# if options[:only_path] != false && atta.is_text?
# value += link_to(
# image_tag('magnifier.png'),
# :controller => 'attachments', :action => 'show',
# :id => atta, :filename => atta.filename
# )
# end
else else
value = content_tag("i", h(value)) if value value = content_tag("i", h(value)) if value
end end

@ -46,6 +46,26 @@ module JournalsHelper
content.html_safe content.html_safe
end end
def render_links_easy(issue, journal, options={})
content = ''
editable = User.current.logged? && (User.current.allowed_to?(:edit_issue_notes, issue.project) || (journal.user == User.current && User.current.allowed_to?(:edit_own_issue_notes, issue.project)))
destroyable = User.current.logged? && ((journal.user == User.current) || (issue.author_id == User.current.id) || (User.current.admin == 1))
links = []
if !journal.notes.blank?
links << link_to(l(:button_quote),
{:controller => 'journals', :action => 'new', :id => issue.id, :journal_id => journal},
:remote => true,
:method => 'post',
:title => l(:button_quote)) if options[:reply_links]
if destroyable
links << link_to(l(:button_delete), { :controller => 'journals', :action => 'destroy', :id => journal, :format => 'js' },
:title => l(:button_delete))
end
end
content << content_tag('div', links.join(' ').html_safe, :class => 'contextual') unless links.empty?
content.html_safe
end
def render_notes (issue, journal, options={}) def render_notes (issue, journal, options={})
content = '' content = ''
editable = User.current.logged? && (User.current.allowed_to?(:edit_issue_notes, issue.project) || (journal.user == User.current && User.current.allowed_to?(:edit_own_issue_notes, issue.project))) editable = User.current.logged? && (User.current.allowed_to?(:edit_issue_notes, issue.project) || (journal.user == User.current && User.current.allowed_to?(:edit_own_issue_notes, issue.project)))
@ -73,6 +93,35 @@ module JournalsHelper
content_tag('div', content.html_safe, :id => "journal-#{journal.id}-notes", :class => css_classes ,:style => "width:580px") content_tag('div', content.html_safe, :id => "journal-#{journal.id}-notes", :class => css_classes ,:style => "width:580px")
end end
# 缺陷回复内容、引用内容
# Redo:后面需要统一扩展
def render_notes_issue (issue, journal, options={})
content = ''
editable = User.current.logged? && (User.current.allowed_to?(:edit_issue_notes, issue.project) || (journal.user == User.current && User.current.allowed_to?(:edit_own_issue_notes, issue.project)))
destroyable = User.current.logged? && ((journal.user == User.current) || (issue.author_id == User.current.id) || (User.current.admin == 1))
links = []
if !journal.notes.blank?
links << link_to(l(:button_quote),
{:controller => 'journals', :action => 'new', :id => issue.id, :journal_id => journal},
:remote => true,
:method => 'post',
:title => l(:button_quote)) if options[:reply_links]
links << link_to_in_place_notes_editor(l(:button_edit), "journal-#{journal.id}-notes",
{ :controller => 'journals', :action => 'edit', :id => journal, :format => 'js' },
:title => l(:button_edit)) if editable
#Added by young
if destroyable
links << link_to(l(:button_delete), { :controller => 'journals', :action => 'destroy', :id => journal, :format => 'js' },
:title => l(:button_delete))
end
end
#content << content_tag('div', links.join(' ').html_safe, :class => 'contextual', :style => 'margin-top:-25px;') unless links.empty?
content << textilizable(journal, :notes)
css_classes = "wiki"
css_classes << " editable" if editable
content_tag('div', content.html_safe, :id => "journal-#{journal.id}-notes", :class => css_classes ,:style => "width:510px")
end
def link_to_in_place_notes_editor(text, field_id, url, options={}) def link_to_in_place_notes_editor(text, field_id, url, options={})
onclick = "$.ajax({url: '#{url_for(url)}', type: 'get'}); return false;" onclick = "$.ajax({url: '#{url_for(url)}', type: 'get'}); return false;"
link_to text, '#', options.merge(:onclick => onclick) link_to text, '#', options.merge(:onclick => onclick)

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

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

@ -21,7 +21,12 @@ include AvatarHelper
module ProjectsHelper module ProjectsHelper
def link_to_version(version, options = {}) def link_to_version(version, options = {})
return '' unless version && version.is_a?(Version) return '' unless version && version.is_a?(Version)
link_to_if version.visible?, format_version_name(version), { :controller => 'versions', :action => 'show', :id => version }, options link_to_if version.visible?, format_version_name(version), { :controller => 'versions', :action => 'show', :id => version }, :class => "c_blue02"
end
def link_to_version_show(version, options = {})
return '' unless version && version.is_a?(Version)
link_to_if version.visible?, format_version_name(version), { :controller => 'versions', :action => 'show', :id => version }, :class => " f16 fb c_dblue "
end end
def project_settings_tabs def project_settings_tabs
@ -29,7 +34,7 @@ module ProjectsHelper
{:name => 'modules', :action => :select_project_modules, :partial => 'projects/settings/modules', :label => :label_module_plural}, {:name => 'modules', :action => :select_project_modules, :partial => 'projects/settings/modules', :label => :label_module_plural},
{:name => 'members', :action => :manage_members, :partial => 'projects/settings/members', :label => :label_member_plural}, {:name => 'members', :action => :manage_members, :partial => 'projects/settings/members', :label => :label_member_plural},
{:name => 'versions', :action => :manage_versions, :partial => 'projects/settings/versions', :label => :label_version_plural}, {:name => 'versions', :action => :manage_versions, :partial => 'projects/settings/versions', :label => :label_version_plural},
{:name => 'categories', :action => :manage_categories, :partial => 'projects/settings/issue_categories', :label => :label_issue_category_plural}, # {:name => 'categories', :action => :manage_categories, :partial => 'projects/settings/issue_categories', :label => :label_issue_category_plural},
# {:name => 'wiki', :action => :manage_wiki, :partial => 'projects/settings/wiki', :label => :label_wiki}, # {:name => 'wiki', :action => :manage_wiki, :partial => 'projects/settings/wiki', :label => :label_wiki},
{:name => 'repositories', :action => :manage_repository, :partial => 'projects/settings/repositories', :label => :label_repository_plural}, {:name => 'repositories', :action => :manage_repository, :partial => 'projects/settings/repositories', :label => :label_repository_plural},
#{:name => 'boards', :action => :manage_boards, :partial => 'projects/settings/boards', :label => :label_board_plural}, #{:name => 'boards', :action => :manage_boards, :partial => 'projects/settings/boards', :label => :label_board_plural},
@ -386,4 +391,20 @@ module ProjectsHelper
end end
type type
end end
#显示项目配置菜单
def show_project_memu user
if user.allowed_to?(:edit_project, @project)
result = "edit_project"
elsif user.allowed_to?(:select_project_modules, @project)
result = "select_project_modules"
elsif user.allowed_to?(:manage_members, @project)
result = "manage_members"
elsif user.allowed_to?(:manage_versions, @project)
result = "manage_versions"
elsif user.allowed_to?(:manage_repository, @project)
result = "manage_repository"
end
result
end
end end

@ -255,8 +255,19 @@ module QueriesHelper
# Give it a name, required to be valid # Give it a name, required to be valid
@query = IssueQuery.new(:name => "_") @query = IssueQuery.new(:name => "_")
@query.project = @project @query.project = @project
params[:f] = %w(subject status_id priority_id author_id assigned_to_id) unless params[:status_id].nil?
params[:op] = {'subject' => "~" ,
'status_id' => ( params[:status_id] == '0' ? "!":"=" ),
'priority_id' => ( params[:priority_id] == '0' ? "!":"=" ),
'author_id' => ( params[:author_id] == '0' ? "!":"=" ),
'assigned_to_id' => ( params[:assigned_to_id] == '0' ? "!":"=" )} unless params[:status_id].nil?
params[:v] = {'subject' => [params[:subject]],
'status_id' => [params[:status_id]],
'priority_id' => [params[:priority_id]],
'author_id' => [params[:author_id]],
'assigned_to_id' => [params[:assigned_to_id]]} unless params[:status_id].nil?
@query.build_from_params(params) @query.build_from_params(params)
session[:query] = {:project_id => @query.project_id, :filters => @query.filters, :group_by => @query.group_by, :column_names => @query.column_names} #session[:query] = {:project_id => @query.project_id, :filters => @query.filters, :group_by => @query.group_by, :column_names => @query.column_names}
else else
# retrieve from session # retrieve from session
@query = IssueQuery.find_by_id(session[:query][:id]) if session[:query][:id] @query = IssueQuery.find_by_id(session[:query][:id]) if session[:query][:id]

@ -42,7 +42,28 @@ module WatchersHelper
:object_id => (objects.size == 1 ? objects.first.id : objects.map(&:id).sort) :object_id => (objects.size == 1 ? objects.first.id : objects.map(&:id).sort)
) )
method = watched ? 'delete' : 'post' method = watched ? 'delete' : 'post'
link_to text, url, :remote => true, :method => method, :class => css
end
def watcher_link_issue(objects, user, options=[])
return '' unless user && user.logged?
objects = Array.wrap(objects)
watched = objects.any? {|object| object.watched_by?(user)}
@watch_flag = (objects.first.instance_of?(User) or objects.first.instance_of?(Project) or objects.first.instance_of?(Contest) or (objects.first.instance_of?(Bid)))
css = @watch_flag ? ([watcher_css(objects), watched ? 'talk_edit ' : 'talk_edit '].join(' ') << options[0].to_s) :
([watcher_css(objects), watched ? 'talk_edit fr ' : 'talk_edit fr '].join(' ') << options[0].to_s)
text = @watch_flag ?
(watched ? l(:button_unfollow) : l(:button_follow)) : (watched ? l(:button_unwatch) : l(:button_watch))
url = watch_path(
:object_type => objects.first.class.to_s.underscore,
:object_id => (objects.size == 1 ? objects.first.id : objects.map(&:id).sort)
)
method = watched ? 'delete' : 'post'
link_to text, url, :remote => true, :method => method, :class => css link_to text, url, :remote => true, :method => method, :class => css
end end
@ -261,17 +282,36 @@ module WatchersHelper
content.present? ? content_tag('ul', content, :class => 'watchers') : content content.present? ? content_tag('ul', content, :class => 'watchers') : content
end end
# 缺陷跟踪者列表复选框生成
def watchers_checkboxes(object, users, checked=nil) def watchers_checkboxes(object, users, checked=nil)
if users.nil? if users.nil?
else else
# tag = check_box_tag 'issue[watcher_user_ids][]', user.id, c, :id => nil
# content_tag 'label', "#{tag} #{h(user)}".html_safe,
# :id => "issue_watcher_user_ids_#{user.id}",
# :class => "floating"
users.map do |user| users.map do |user|
c = checked.nil? ? object.watched_by?(user) : checked c = checked.nil? ? object.watched_by?(user) : checked
tag = check_box_tag 'issue[watcher_user_ids][]', user.id, c, :id => nil s = content_tag(:ul,
content_tag 'label', "#{tag} #{h(user)}".html_safe, content_tag(:li, "#{check_box_tag 'issue[watcher_user_ids][]', user.id, c, :id => nil } #{h link_to user.userInfo, user_path( user.id)}".html_safe,
:id => "issue_watcher_user_ids_#{user.id}", :id=>"issue_watcher_user_ids_#{user.id}",:style=>"float: left;width: 175px;margin: 0px 20px 10px 0px; overflow: hidden; line-height:1.6em;" ),
:class => "floating" :class => "mb10 ml80")
end.join.html_safe end.join.html_safe
# scope = users.sort
# watchers = paginateHelper scope,10
# s = content_tag('ul', issue_watcher_check_box_tags_ex('issue[watcher_user_ids][]', watchers), :class => 'mb10 ml80')
# links = pagination_links_full(@obj_pages, @obj_count, :per_page_links => false, :remote => false, :flag => true){|text, parameters, options|
# link_to text, watchers_autocomplete_for_user_path(@users, parameters.merge(:q => params[:q],:format => 'js',:flag => 'ture')), :remote => true
# }
# s + content_tag('ul', links,:class => 'wlist', :style =>"float:left;margin-top:0px;")
end end
end end
@ -304,8 +344,8 @@ module WatchersHelper
def exit_project_link(project) def exit_project_link(project)
link_to(l(:label_exit_project),exit_cur_project_path(project.id), link_to(l(:label_exit_project),exit_cur_project_path(project.id),
:remote => true, :confirm => l(:lable_sure_exit_project), :remote => true, :confirm => l(:lable_sure_exit_project),
:style => "color: #fff; display:block;font-size:12px; padding: 0px 5px; margin-right: 10px; height: 20px; line-height: 22px; background: none repeat scroll 0% 0% #64BDD9; TES;padding-top:1px;" ) :class => "pr_join_a_quit" )
end end
#项目关注、取消关注 #项目关注、取消关注
#REDO:项目样式确定后方法需要对CSS变量进行改进 #REDO:项目样式确定后方法需要对CSS变量进行改进
@ -321,7 +361,7 @@ module WatchersHelper
:object_id => (objects.size == 1 ? objects.first.id : objects.map(&:id).sort)) :object_id => (objects.size == 1 ? objects.first.id : objects.map(&:id).sort))
method = watched ? 'delete' : 'post' method = watched ? 'delete' : 'post'
link_to text, url, :remote => true, :method => method, link_to text, url, :remote => true, :method => method,
:class => "project_watch_new" ,:id=>id :class => "pr_join_a" ,:id=>id
end end
#申请加入项目 #申请加入项目
@ -339,7 +379,21 @@ module WatchersHelper
:user_id => user.id, :user_id => user.id,
:project_id => project.id) :project_id => project.id)
method = applied ? 'delete' : 'post' method = applied ? 'delete' : 'post'
link_to text, url, :remote => true, :method => method , :class => "project_watch_new",:id => id link_to text, url, :remote => true, :method => method , :class => "pr_join_a",:id => id
end
def paginateHelper obj, pre_size=20
@obj_count = obj.count
@obj_pages = Redmine::Pagination::Paginator.new @obj_count, pre_size, params['page']
if obj.kind_of? ActiveRecord::Base or obj.kind_of? ActiveRecord::Relation
obj.limit(@obj_pages.per_page).offset(@obj_pages.offset)
elsif obj.kind_of? Array
obj[@obj_pages.offset, @obj_pages.per_page]
else
logger.error "[ApplicationController] Error : application_controller#paginateHelper ===> unknow category: #{obj.class}"
raise RuntimeError, 'unknow type, Please input you type into this helper.'
end end
end
end end

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

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

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

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

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

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

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

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

File diff suppressed because it is too large Load Diff

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

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

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

@ -7,22 +7,24 @@ class Poll < ActiveRecord::Base
has_many :poll_users, :dependent => :destroy has_many :poll_users, :dependent => :destroy
has_many :users, :through => :poll_users #该文件被哪些用户提交答案过 has_many :users, :through => :poll_users #该文件被哪些用户提交答案过
# 添加课程的poll动态 # 添加课程的poll动态
# has_many :acts, :class_name => 'Activity', :as => :act, :dependent => :destroy has_many :acts, :class_name => 'Activity', :as => :act, :dependent => :destroy
# after_create :act_as_activity after_create :act_as_activity
# acts_as_event :title => Proc.new {|o| "#{l(:label_my_message)} ##{o.id}: #{o.name}" }, acts_as_event :title => Proc.new {|o| "#{l(:label_course_poll)}: #{o.polls_name}" },
# :description => :description, :description => :polls_description,
# :author => :author, :datetime => :published_at,
# :url => Proc.new {|o| {:controller => 'poll', :action => 'show', :id => o.id}} :author => :user,
:url => Proc.new {|o| {:controller => 'poll', :action => 'show', :id => o.id}}
# acts_as_activity_provider :type => 'polls', acts_as_activity_provider :type => 'polls',
# :permission => :view_course_polls, #:permission => :view_course_polls,
#:find_options => {:include => [:course, :author]}, :find_options => {:select => "#{Poll.table_name}.*",
#:timestamp => "#{self.table_name}.published_at", :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 )"},
# :author_key => :author_id :timestamp => "#{self.table_name}.published_at",
:author_key => :user_id
# def act_as_activity def act_as_activity
# self.acts << Activity.new(:user_id => self.user_id) self.acts << Activity.new(:user_id => self.user_id)
# end end
end end

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

File diff suppressed because it is too large Load Diff

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

@ -1,18 +1,18 @@
class ZipPack < ActiveRecord::Base class ZipPack < ActiveRecord::Base
# attr_accessible :title, :body # attr_accessible :title, :body
def self.packed?(bid_id, user_id, digests) def self.packed?(bid_id, user_id, digests)
zip_pack = ZipPack.where(homework_id: bid_id, user_id: user_id).first zip_pack = ZipPack.where(homework_id: bid_id, user_id: user_id).first
return false unless zip_pack && zip_pack.digests == digests return false unless zip_pack && zip_pack.digests == digests
zip_pack zip_pack
end end
def file_valid? def file_valid?
return false unless File.exist?(self.file_path) return false unless File.exist?(self.file_path)
Trustie::Utils.digest(self.file_path) == self.file_digest Trustie::Utils.digest(self.file_path) == self.file_digest
end end
def digests def digests
self.file_digests.split(',').sort self.file_digests.split(',').sort
end end
end end

@ -44,12 +44,14 @@ class UsersService
#location = get_user_location @user #location = get_user_location @user
#{:id => @user.id, :img_url => img_url, :nickname => @user.login, :gender => gender, :work_unit => work_unit, :mail => @user.mail, :location => location, :brief_introduction => @user.user_extensions.brief_introduction} #{:id => @user.id, :img_url => img_url, :nickname => @user.login, :gender => gender, :work_unit => work_unit, :mail => @user.mail, :location => location, :brief_introduction => @user.user_extensions.brief_introduction}
end end
# 自动注册功能 FOR邮件邀请
def register_auto(login,mail,password) def register_auto(login,mail,password)
@user = User.new @user = User.new
@user.admin = false @user.admin = false
@user.register @user.register
@user.login = login @user.login = login
@user.mail =mail @user.mail = mail
password_confirmation = password password_confirmation = password
should_confirmation_password = true should_confirmation_password = true
if !password.blank? && !password_confirmation.blank? && should_confirmation_password if !password.blank? && !password_confirmation.blank? && should_confirmation_password
@ -59,9 +61,7 @@ class UsersService
else else
@user.password = "" @user.password = ""
end end
@user = automatically_register(@user) @user = automatically_register(@user)
if @user.id != nil if @user.id != nil
ue = @user.user_extensions ||= UserExtensions.new ue = @user.user_extensions ||= UserExtensions.new
ue.user_id = @user.id ue.user_id = @user.id
@ -69,6 +69,7 @@ class UsersService
end end
@user @user
end end
#显示用户 #显示用户
#id用户id #id用户id
def show_user(params) def show_user(params)

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

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

@ -0,0 +1,67 @@
<span id="attachments_fields" xmlns="http://www.w3.org/1999/html">
<% if defined?(container) && container && container.saved_attachments %>
<% if isReply %>
<% container.saved_attachments.each_with_index do |attachment, i| %>
<span id="attachments_p<%= i %>" class="sub_btn">
<%= text_field_tag("attachments[p#{i}][filename]", attachment.filename, :class => 'filename readonly', :readonly=>'readonly')%>
<%= text_field_tag("attachments[p#{i}][description]", attachment.description, :maxlength => 255, :placeholder => l(:label_optional_description), :class => 'description', :style=>"display: inline-block;") +
link_to('&nbsp;'.html_safe, attachment_path(attachment, :attachment_id => "p#{i}", :format => 'js'), :method => 'delete', :remote => true, :class => 'remove-upload') %>
<%#= render :partial => 'tags/tag', :locals => {:obj => attachment, :object_flag => "6"} %>
<span class="ispublic-label"><%= l(:field_is_public)%>:</span>
<%= check_box_tag("attachments[p#{i}][is_public_checkbox]", attachment.is_public,attachment.is_public == 1 ? true : false, :class => 'is_public')%>
<%= hidden_field_tag "attachments[p#{i}][token]", "#{attachment.token}" %>
</span>
<% end %>
<% else %>
<% container.attachments.each_with_index do |attachment, i| %>
<span id="attachments_p<%= i %>" class="attachment">
<%= text_field_tag("attachments[p#{i}][filename]", attachment.filename, :class => 'filename readonly', :readonly=>'readonly')%>
<%= text_field_tag("attachments[p#{i}][description]", attachment.description, :maxlength => 255, :placeholder => l(:label_optional_description), :class => 'description', :style=>"display: inline-block;") +
link_to('&nbsp;'.html_safe, attachment_path(attachment, :attachment_id => "p#{i}", :format => 'js'), :method => 'delete', :remote => true, :class => 'remove-upload') %>
<%#= render :partial => 'tags/tag', :locals => {:obj => attachment, :object_flag => "6"} %>
<span class="ispublic-label"><%= l(:field_is_public)%>:</span>
<%= check_box_tag("attachments[p#{i}][is_public_checkbox]", attachment.is_public,attachment.is_public == 1 ? true : false, :class => 'is_public')%>
<%= hidden_field_tag "attachments[p#{i}][token]", "#{attachment.token}" %>
</span>
<% end %>
<% end %>
<% end %>
</span>
<script type='text/javascript'>
// function CompatibleSend()
// {
// var obj=document.getElementById("_file");
// var file= $(obj).clone();
// file.click();
// }
</script>
<span class="add_attachment">
<%#= button_tag "浏览", :type=>"button", :onclick=>"CompatibleSend();" %>
<!--%= link_to image_tag(),"javascript:void(0)", :onclick => "_file.click()"%-->
<%= button_tag "文件浏览", :type=>"button", :onclick=>"_file.click()", :class =>"sub_btn",:style => ie8? ? 'display:none' : '' %>
<%= file_field_tag 'attachments[dummy][file]',
:id => '_file',
:class => 'file_selector',
:multiple => true,
:onchange => 'addInputFiles(this);',
:style => 'display:none',
:data => {
:max_file_size => Setting.attachment_max_size.to_i.kilobytes,
:max_file_size_message => l(:error_attachment_too_big, :max_size => number_to_human_size(Setting.attachment_max_size.to_i.kilobytes)),
:max_concurrent_uploads => Redmine::Configuration['max_concurrent_ajax_uploads'].to_i,
:upload_path => uploads_path(:format => 'js'),
:description_placeholder => l(:label_optional_description),
:field_is_public => l(:field_is_public),
:are_you_sure => l(:text_are_you_sure),
:file_count => l(:label_file_count),
:delete_all_files => l(:text_are_you_sure_all)
} %>
<span id="upload_file_count" :class="c_grey"><%= l(:label_no_file_uploaded)%></span>
(<%= l(:label_max_size) %>: <%= number_to_human_size(Setting.attachment_max_size.to_i.kilobytes) %>)
</span>
<% content_for :header_tags do %>
<%= javascript_include_tag 'attachments' %>
<% end %>

@ -60,7 +60,7 @@
<% if defined?(thumbnails) && thumbnails %> <% if defined?(thumbnails) && thumbnails %>
<% images = attachments.select(&:thumbnailable?) %> <% images = attachments.select(&:thumbnailable?) %>
<% if images.any? %> <% if images.any? %>
<div class="thumbnails"> <div class="pro_pic mb10" width="100" height="73">
<% images.each do |attachment| %> <% images.each do |attachment| %>
<div><%= thumbnail_tag(attachment) %></div> <div><%= thumbnail_tag(attachment) %></div>
<% end %> <% end %>

@ -0,0 +1,72 @@
<div class="attachments" style="font-weight:normal;">
<% is_float ||= false %>
<% for attachment in attachments %>
<p style="width: 100%;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;">
<%if is_float%>
<div style="max-width:55%;white-space: nowrap; overflow: hidden; text-overflow: ellipsis;float: left;">
<% end%>
<span title="<%= attachment.filename %>" id = "attachment_">
<% if options[:length] %>
<%= link_to_short_attachment attachment, :class => ' link_file_board', :download => true,:length => options[:length] -%>
<% else %>
<%= link_to_short_attachment attachment, :class => ' link_file_board', :download => true -%>
<% end %>
</span>
<%if is_float%>
</div>
<% end%>
<% if attachment.is_text? %>
<%= link_to image_tag('magnifier.png'),
:controller => 'attachments',
:action => 'show',
:id => attachment,
:filename => attachment.filename%>
<% end %>
<span title="<%= attachment.description%>">
<%= h(truncate(" - #{attachment.description}", length: options[:length] ? options[:length]:15, omission: '...')) unless attachment.description.blank? %>
</span>
<span class="size">(
<%= number_to_human_size attachment.filesize %>)
</span>
<% if options[:deletable] %>
<% if attachment.container_type == 'HomeworkAttach' %>
<%= link_to image_tag('delete.png'), {:controller => 'attachments', :action => 'delete_homework', :id => attachment.id},
:data => {:confirm => l(:text_are_you_sure)},
:method => :delete,
:class => 'delete delete-homework-icon',
:remote => true,
:title => l(:button_delete) %>
<% else %>
<%= link_to image_tag('delete.png'), attachment_path(attachment),
:data => {:confirm => l(:text_are_you_sure)},
:method => :delete,
:class => 'delete',
#:remote => true,
#:id => "attachments_" + attachment.id.to_s,
:title => l(:button_delete) %>
<% end %>
<% end %>
<% if options[:wrap] %>
<br/>
&nbsp;
<% end %>
<% if options[:author] %>
<span class="author" title="<%= attachment.author%>">
<%= link_to h(truncate(attachment.author.name, length: 10, omission: '...')),user_path(attachment.author),:class => "c_orange" %>,
<%= format_time(attachment.created_on) %>
</span>
<% end %>
</p>
<% end %>
<div class="thumbnails">
<% if defined?(thumbnails) && thumbnails %>
<% images = attachments.select(&:thumbnailable?) %>
<% if images.any? %>
<% images.each do |attachment| %>
<div class="pro_pic fl " width="100" height="73"><%= thumbnail_issue_tag(attachment) %></div>
<% end %>
<% end %>
<% end %>
</div>
</div>

@ -47,7 +47,6 @@
<a href="javascript:void(0);" class="btn_addPic" style="text-decoration:none;"> <a href="javascript:void(0);" class="btn_addPic" style="text-decoration:none;">
<span><%= l(:button_upload_photo) %></span> <span><%= l(:button_upload_photo) %></span>
</a> </a>
<span class="c_orange ml25 f12">(个人头像建议90*90大小课程和项目logo建议60*60大小或者等比图像)</span>
<!-- :accept => 'image/png,image/gif,image/jpeg', --> <!-- :accept => 'image/png,image/gif,image/jpeg', -->
<span class="add_avatar" style="margin-left: -55px;width: 70px"> <span class="add_avatar" style="margin-left: -55px;width: 70px">
<%= file_field_tag 'avatar[image]', <%= file_field_tag 'avatar[image]',
@ -69,6 +68,7 @@
:source_id => source.id.to_s :source_id => source.id.to_s
} %> } %>
</span> </span>
</div> </div>
<% content_for :header_tags do %> <% content_for :header_tags do %>
<%= javascript_include_tag 'avatars' %> <%= javascript_include_tag 'avatars' %>

@ -3,10 +3,9 @@
</a> </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" %> <%#= 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"><%= l(:button_upload_photo) %></a> <a href="javascript:void(0)" class="upbtn fl"><%= l(:button_upload_photo) %></a>
<span class="c_orange ml25 mt43 f12 fl ">(个人头像建议90*90大小课程和项目logo建议60*60大小或者等比图像)</span>
<%= file_field_tag 'avatar[image]', <%= file_field_tag 'avatar[image]',
:id => nil, :id => nil,
:class => 'upload_file ', :class => 'upload_file',
:size => "1", :size => "1",
:multiple => false, :multiple => false,
:onchange => 'addInputAvatar(this);', :onchange => 'addInputAvatar(this);',

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

@ -13,3 +13,18 @@
</p> </p>
<% end %> <% end %>
</div> </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" %>
&nbsp;<%= 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,4 +1,4 @@
<script type="text/javascript"> <script type="text/javascript" xmlns="http://www.w3.org/1999/html">
function submitProjectBoard() function submitProjectBoard()
{ {
if(regexSubject()&&regexContent()) if(regexSubject()&&regexContent())
@ -7,91 +7,77 @@
} }
} }
</script> </script>
<div id="add-message" class="add_frame" style="display:<%= !@flag.nil?&&@flag=='true' ? '' : 'none' %>;"> <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 id="add-message" class="talk_new ml15" style="display:<%= !@flag.nil?&&@flag=='true' ? '' : 'none' %>;">
<% if User.current.logged? %> <% 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| %> <%= 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 class="talk_top"><%= l(:project_module_boards_post) %></p>
<%= render :partial => 'messages/form_project', :locals => {:f => f} %>
<p> <p>
<a herf="#" onclick="submitProjectBoard();" class="ButtonColor m3p10"><%= l(:button_submit)%></a> <a href="javascript:void(0)" onclick="submitProjectBoard();" class="blue_btn fl ml55" style="margin-left: 55px"><%= l(:button_submit)%></a>
<%= link_to l(:button_cancel), "#", :onclick => '$("#add-message").hide(); return false;', :class => 'ButtonColor m3p10' %> <%= link_to l(:button_cancel), "#", :onclick => '$("#add-message").hide(); return false;', :class => 'grey_btn ml10 fl' %>
</p> </p>
<% end %> <% end %>
<div id="preview" class="wiki"></div> <div id="preview" class="wiki"></div>
<br/><br/>
<% end %> <% end %>
</div> </div>
<!--display the board--> <!--display the board-->
<% if !User.current.logged? %> <% if !User.current.logged? %>
<div style="font-size: 14px;margin:20px;"> <div class="c_grey f14">
<% if @project.project_type == 1 %> <%= l(:label_user_login_project_board) %>
<%= l(:label_user_login_course_board) %> <%= link_to l(:label_user_login_new), signin_path, :class => "c_blue ml5" %>
<% else %>
<%= l(:label_user_login_project_board) %>
<% end %>
<%= link_to l(:label_user_login_new), signin_path %>
<hr/>
</div> </div>
<% end %> <% end %>
<!-- 内容显示部分 --> <!-- 内容显示部分 -->
<div class="project_right"> <div class="talk_top">
<div class="project_r_h"> <div class="fl"><span><%= l(:label_project_board_count , :count => @topic_count)%></span></div>
<h2 class="project_h2"> <% if @project.enabled_modules.where("name = 'boards'").count > 0 && User.current.member_of?(@project) %>
<% 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) %>
<span><%= link_to l(:project_module_boards_post), new_board_message_path(@board), <span><%= link_to l(:project_module_boards_post), new_board_message_path(@board),
:class => 'problem_new_btn fl', :class => 'problem_new_btn fl c_dorange',
:onclick => 'showAndScrollTo("add-message", "message_subject"); return false;' if User.current.logged? %></span> :onclick => 'showAndScrollTo("add-message", "message_subject"); return false;' if User.current.logged? %></span>
<% end %> <% end %>
<div class="cl"></div> <div class="cl"></div>
</div> </div>
<!-- 帖子内容显示 --> <!-- 帖子内容显示 -->
<% if @topics.any? %> <% if @topics.any? %>
<% @topics.each do |topic| %> <% @topics.each do |topic| %>
<div class="problem_main"> <div class="problem_main">
<a> <%= link_to image_tag(url_to_avatar(topic.author), :width=>"32",:height=>"32"), user_path(topic.author),:class => 'problem_pic talk_pic fl' %>
<%= link_to image_tag(url_to_avatar(topic.author), :class => "problem_pic talk_pic fl"), user_path(topic.author) %>
</a>
<div class="talk_txt fl"> <div class="talk_txt fl">
<div> <%= link_to h(topic.subject), board_message_path(@board, topic), title:topic.subject.to_s, :class =>"problem_tit fl" %>
<span><%= link_to h(topic.subject), board_message_path(@board, topic), title:topic.subject.to_s, :class =>"problem_tit fl" %></span>
<% if topic.sticky? %> <% if topic.sticky? %>
<span class="talk_up" style="float:right;"><%= l(:label_board_sticky)%></span> <a href="javascript:void(0)" class="talk_up fr c_red"><%= l(:label_board_sticky)%></a>
<% end %> <% end %>
</div> <br/>
<div class="problem_line"> <%= l(:label_post_by)%><%= link_to topic.author, user_path(topic.author), :class =>"problem_name" %>
<span><%= l(:label_post_by)%><%= link_to topic.author, user_path(topic.author), :class =>"problem_name" %></span> &nbsp;<%= l(:label_post_by_time)%><%= format_time topic.created_on %>
&nbsp;<span><%= l(:label_post_by_time)%><%= format_time topic.created_on %></span>
</div>
</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> <%= 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 class="cl"></div>
</div><!--讨论主类容 end--> </div><!--讨论主类容 end-->
<% end %> <% end %>
<ul class="wlist">
<%= pagination_links_full @topic_pages, @topic_count, :per_page_links => false, :remote => false, :flag => true %>
</ul>
<% else %> <% else %>
<p class="nodata"><%= l(:label_no_data) %></p> <p class="nodata"><%= l(:label_no_data) %></p>
<% end %> <% end %>
<!--讨论主类容 end--> <ul class="wlist">
<div class="cl"></div> <%= pagination_links_full @topic_pages, @topic_count, :per_page_links => false, :remote => false, :flag => true %>
</div> </ul>
<!--讨论主类容 end-->
<% other_formats_links do |f| %> <%# other_formats_links do |f| %>
<%= f.link_to 'Atom', :url => {:key => User.current.rss_key} %> <%#= f.link_to 'Atom', :url => {:key => User.current.rss_key} %>
<% end %> <%# end %>
<% html_title @board.name %> <% html_title @board.name %>

@ -1,6 +1,6 @@
<% if @project %> <% if @project %>
<%= render :partial => 'project_show', locals: {project: @project} %> <%= render :partial => 'project_show', locals: {project: @project} %>
<% elsif @course %> <% elsif @course %>
<%= render :partial => 'course_show', locals: {course: @course} %> <%= render :partial => 'course_show', locals: {course: @course} %>
<% end %> <% 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, <%= f.text_field :deadline,
:required => true, :required => true,
:size => 60, :size => 60,
:style => "width:150px;", :style => "width:150px;float:left;",
:readonly => true, :readonly => true,
:placeholder => "#{l(:label_deadline)}" :placeholder => "#{l(:label_deadline)}"
%> %>

@ -1,50 +1,50 @@
<div class="members_left"> <div class="members_left">
<ul style=" border-bottom:none;"> <ul style=" border-bottom:none;">
<li> <li>
<span class="w150 f_b" > <span class="w150 f_b" >
用户 用户
</span> </span>
<span class="w150 f_b"> <span class="w150 f_b">
角色 角色
</span> </span>
<span></span> <span></span>
</li> </li>
<div id="course_member_list"> <div id="course_member_list">
<%= render :partial => "courses/member" %> <%= render :partial => "courses/member" %>
</div> </div>
</ul> </ul>
</div><!-- 左边--> </div><!-- 左边-->
<div class="members_right"> <div class="members_right">
<p class="c_blue fb mt10 mb5">添加成员</p> <p class="c_blue fb mt10 mb5">添加成员</p>
<%= form_for(@member, {:as => :membership, :url => course_memberships_path(@course), :remote => true, :method => :post}) do |f| %> <%= form_for(@member, {:as => :membership, :url => course_memberships_path(@course), :remote => true, :method => :post}) do |f| %>
<div class="member_search"> <div class="member_search">
<input hidden="hidden" value="true" name="flag"> <input hidden="hidden" value="true" name="flag">
<input id="principal_search" class="member_search_input fl" type="text" placeholder="请输入用户名称来搜索好友"> <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) }')" %> <%= javascript_tag "observeSearchfield('principal_search', null, '#{ escape_javascript autocomplete_course_memberships_path(@course, :format => 'js',:flag => true) }')" %>
<div class="cl"></div> <div class="cl"></div>
<div id="principals_for_new_member"> <div id="principals_for_new_member">
<%= render_principals_for_new_course_members(@course) %> <%= render_principals_for_new_course_members(@course) %>
</div> </div>
<div class="cl"></div> <div class="cl"></div>
<ul class="rolebox mb10 mt10"> <ul class="rolebox mb10 mt10">
<li class="fb"> <li class="fb">
<%= l(:label_role_plural) %> <%= l(:label_role_plural) %>
</li> </li>
<% @roles.each do |role| %> <% @roles.each do |role| %>
<li> <li>
<%= radio_button_tag 'membership[role_ids][]', role.id, role.name == "学生" || role.name == "Student" %> <%= radio_button_tag 'membership[role_ids][]', role.id, role.name == "学生" || role.name == "Student" %>
<label ><%= h role %></label> <label ><%= h role %></label>
</li> </li>
<% end %> <% end %>
</ul> </ul>
<div class="cl mb10"></div> <div class="cl mb10"></div>
<a href="javascript:void(0)" class="member_btn" onclick="$('#new_membership').submit();"> <a href="javascript:void(0)" class="member_btn" onclick="$('#new_membership').submit();">
新增成员 新增成员
</a> </a>
</div> </div>
<% end%> <% end%>
</div><!-- 右边 end--> </div><!-- 右边 end-->

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

@ -1,5 +1,5 @@
<%= form_tag( searchmembers_course_path(@course), method: 'get',:class => "f_l",:remote=>true,:id => "search_student") do %> <%= 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 %> <% if @group %>
<%= hidden_field "search_group_id", params[:search_group_id],:value => "#{@group.id}", name: 'search_group_id' %> <%= hidden_field "search_group_id", params[:search_group_id],:value => "#{@group.id}", name: 'search_group_id' %>
<input type="hidden" name="ingroup"> <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;} /*#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;} /*.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;} .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{ width:350px; margin:15px auto;}
.tscore_box li{ height:25px;} .tscore_box li{ height:25px;}
</style> </style>
<div class="tscore_con"> <div class="tscore_con" id="user_score">
<h2><%= @member_score.user.name %> 历次作业积分</h2> <h2><%= @member_score.user.name %> 历次作业积分</h2>
<ul class="tscore_box"> <ul class="tscore_box">
<li ><span class="c_blue02 w280">作业名称</span><span class="c_blue02 w70">得分</span></li> <li ><span class="c_blue02 w280">作业名称</span><span class="c_blue02 w70">得分</span></li>

@ -1,4 +1,4 @@
<%= javascript_include_tag "/assets/kindeditor/kindeditor" %> <%= 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| %> <%= 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 } %> <%= render :partial => 'bids/new_homework_form', :locals => { :bid => @homework,:bid_id => "new_bid",:f => f,:edit_mode => false } %>
<% end %> <% end %>

@ -1,92 +1,92 @@
<div class="project_r_h"> <div class="project_r_h">
<h2 class="project_h2"><%= l(:label_course_modify_settings)%></h2> <h2 class="project_h2"><%= l(:label_course_modify_settings)%></h2>
</div> </div>
<div class="hwork_new"> <div class="hwork_new">
<div id="tb_" class="hwork_tb_"> <div id="tb_" class="hwork_tb_">
<ul> <ul>
<li id="tb_1" class="hwork_hovertab" onclick="course_setting(1);" > <li id="tb_1" class="hwork_hovertab" onclick="course_setting(1);" >
基本信息 基本信息
</li> </li>
<li id="tb_2" class="hwork_normaltab" onclick="course_setting(2);"> <li id="tb_2" class="hwork_normaltab" onclick="course_setting(2);">
成员 成员
</li> </li>
</ul> </ul>
</div> </div>
<div class="hwork_dis" id="tbc_01" style="padding-top: 10px;"> <div class="hwork_dis" id="tbc_01" style="padding-top: 10px;">
<ul> <ul>
<%= labelled_form_for @course do |f| %> <%= labelled_form_for @course do |f| %>
<li class="ml45 mb10"> <li class="ml45 mb10">
<%= render :partial => "avatar/new_avatar_form", :locals => {source: @course} %> <%= render :partial => "avatar/new_avatar_form", :locals => {source: @course} %>
<div class="cl"></div> <div class="cl"></div>
</li> </li>
<li class="ml45"> <li class="ml45">
<label><span class="c_red">*</span>&nbsp;<%= l(:label_tags_course_name)%>&nbsp;&nbsp;</label> <label><span class="c_red">*</span>&nbsp;<%= l(:label_tags_course_name)%>&nbsp;&nbsp;</label>
<input type="text" name="course[name]" id="course_name" class="courses_input" maxlength="100" onkeyup="regex_course_name();" value="<%= @course.name%>"> <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> <span class="c_red" id="course_name_notice" style="display: none;">课程名称不能为空</span>
</li> </li>
<div class="cl"></div> <div class="cl"></div>
<li class="ml45"> <li class="ml45">
<label><span class="c_red">*</span>&nbsp;<%= l(:label_class_period)%>&nbsp;&nbsp;</label> <label><span class="c_red">*</span>&nbsp;<%= l(:label_class_period)%>&nbsp;&nbsp;</label>
<input type="text" name="class_period" id="class_period" class="hwork_input02" onkeyup="regex_course_class_period();" maxlength="6" value="<%= @course.class_period%>"> <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> <span class="c_red" id="course_class_period_notice" style="display: none;"></span>
</li> </li>
<div class="cl"></div> <div class="cl"></div>
<li class="ml45 mb10"> <li class="ml45 mb10">
<label><span class="c_red">*</span>&nbsp;<%= l(:label_course_term)%>&nbsp;&nbsp;</label> <label><span class="c_red">*</span>&nbsp;<%= l(:label_course_term)%>&nbsp;&nbsp;</label>
<%= select_tag :time,options_for_select(course_time_option(@course.time),@course.time), {} %> <%= 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),{} %> <%= select_tag :term,options_for_select(course_term_option,@course.term || cur_course_term),{} %>
</li> </li>
<div class="cl"></div> <div class="cl"></div>
<li class="ml45 mb10"> <li class="ml45 mb10">
<label><span class="c_red">*</span>&nbsp;<%= l(:label_new_course_password)%>&nbsp;&nbsp;</label> <label><span class="c_red">*</span>&nbsp;<%= l(:label_new_course_password)%>&nbsp;&nbsp;</label>
<input type="password" name="course[password]" id="course_course_password" class="hwork_input02" value="<%= @course.password%>" onkeyup="regex_course_password();"> <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> <a id="psw_btn" href="javascript:void(0)">显示明码</a>
<span class="c_red" id="course_course_password_notice"></span> <span class="c_red" id="course_course_password_notice"></span>
<div class="cl"></div> <div class="cl"></div>
<span class=" ml80 c_orange">学生或其他成员申请加入课程时候需要使用该口令,该口令可以由老师在课堂上公布。</span> <span class=" ml80 c_orange">学生或其他成员申请加入课程时候需要使用该口令,该口令可以由老师在课堂上公布。</span>
</li> </li>
<li class="ml45"> <li class="ml45">
<label class="fl" >&nbsp;&nbsp;<%= l(:label_new_course_description)%>&nbsp;&nbsp;</label> <label class="fl" >&nbsp;&nbsp;<%= l(:label_new_course_description)%>&nbsp;&nbsp;</label>
<textarea name="course[description]" placeholder="最多3000个汉字(或6000个英文字符)" class="courses_text fl" maxlength="6000"><%= @course.description%></textarea> <textarea name="course[description]" placeholder="最多3000个汉字(或6000个英文字符)" class="courses_text fl" maxlength="6000"><%= @course.description%></textarea>
<div class="cl"></div> <div class="cl"></div>
</li> </li>
<li class=" mb5 ml80"> <li class=" mb5 ml80">
<label >公开&nbsp;&nbsp;</label> <label >公开&nbsp;&nbsp;</label>
<input <%= @course.is_public == 1 ? 'checked' : ''%> id="course_is_public" name="course[is_public]" type="checkbox"> <input <%= @course.is_public == 1 ? 'checked' : ''%> id="course_is_public" name="course[is_public]" type="checkbox">
<span class="c_grey">(打钩为公开,不打钩则不公开,若不公开,仅课程成员可见该课程。)</span> <span class="c_grey">(打钩为公开,不打钩则不公开,若不公开,仅课程成员可见该课程。)</span>
<div class="cl"></div> <div class="cl"></div>
</li> </li>
<li class=" mb5 ml30"> <li class=" mb5 ml30">
<label >学生列表公开&nbsp;&nbsp;</label> <label >学生列表公开&nbsp;&nbsp;</label>
<input <%= @course.open_student == 1 ? 'checked' : ''%> id="course_open_student" name="course[open_student]" type="checkbox" style="margin-left: 1px;"/> <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> <span class="c_grey">(打钩为"学生列表公开",不打钩为不公开,若不公开,则课程外部人员看不到学生列表)</span>
<div class="cl"></div> <div class="cl"></div>
</li> </li>
<li class=" ml90" > <li class=" ml90" >
<a href="javascript:void(0)" class="blue_btn fl c_white" onclick="submit_edit_course(<%= @course.id%>);" >提交</a> <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" %> <%= link_to l(:button_cancel), course_path(@course), :class => "blue_btn grey_btn fl c_white" %>
<div class="cl"></div> <div class="cl"></div>
</li> </li>
<% end %> <% end %>
</ul> </ul>
</div> </div>
<div class="hwork_undis" id="tbc_02"> <div class="hwork_undis" id="tbc_02">
<div class="search_course fl"> <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 %> <%= 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)}');" --> <!-- , :onkeyup => "regexQ('#{l(:label_search_conditions_not_null)}');" -->
<%= text_field_tag 'name', params[:name], :placeholder => "昵称、学号、姓名搜索", :class => "search_text fl" %> <%= 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" > <a href="javascript:void(0)" onclick="submitMemberSerch('<%= l(:label_search_conditions_not_null) %>');" class="search_btn fl f14 c_white ml10" >
<%= l(:label_search)%> <%= l(:label_search)%>
</a> </a>
<br /> <br />
<span id="course_member_name_span" style="float: left"></span> <span id="course_member_name_span" style="float: left"></span>
<% end %> <% end %>
</div> </div>
<div class="cl"></div>
<div id="course_members_setting"> <div id="course_members_setting">
<%= render :partial => "course_members" %> <%= render :partial => "course_members" %>
</div> </div>
</div><!---成员结束--> </div><!---成员结束-->
</div><!--talknew end--> </div><!--talknew end-->
<div class="cl"></div> <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}) %>'); $('#ajax-modal').html('<%= escape_javascript(render :partial => 'courses/show_member_score', :locals => {:member => @member_score}) %>');
showModal('ajax-modal', '400px'); 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");

@ -45,8 +45,8 @@
</div> </div>
<div class="cl"></div> <div class="cl"></div>
<div class="tag_h"> <div class="tag_h">
<%= render :partial => 'tags/tag_new', :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 => "10"} %> <%= render :partial => 'tags/tag_add', :locals => {:obj => file, :object_flag => "6"} %>
</div> </div>
<div class="cl"></div> <div class="cl"></div>
</div><!---re_con_box end--> </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' %> --> <!--<%#= stylesheet_link_tag 'resource', :media => 'all' %> -->
<script> <script>
function show_upload() function show_upload()
@ -11,7 +6,7 @@
showModal('ajax-modal', '513px'); showModal('ajax-modal', '513px');
$('#ajax-modal').siblings().remove(); $('#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').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","40%").css("left","30%");
$('#ajax-modal').parent().addClass("popbox_polls"); $('#ajax-modal').parent().addClass("popbox_polls");
} }
@ -46,7 +41,7 @@
<div class="re_top"> <div class="re_top">
<%= form_tag( search_project_project_files_path(@project), method: 'get',:class => "re_search f_l",:remote=>true) do %> <%= 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"%> <%= 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()" %> <%= submit_tag "全站搜索", :class => "re_schbtn b_lblue",:name => "insite",:id => "insite",:onmouseover => "presscss('insite')",:onmouseout =>"buttoncss()" %>
<% end %> <% end %>
<% manage_allowed = User.current.allowed_to?(:manage_files, @project) %> <% 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 id="popbox_upload" style="margin-top: -30px;margin-left: -20px;margin-right: -10px;">
<div class="upload_con"> <div class="upload_con">
<h2>将此件引入我的资源库</h2> <h2>将此文件件引入我的资源库</h2>
<% if error == '403' %> <% if error == '403' %>
<div class="upload_box"> <div class="upload_box">
<div style="color: red;">您没有权限引用此资源</div> <div style="color: red;">您没有权限引用此资源</div>
@ -13,13 +13,11 @@
remote: true, remote: true,
id: "relation_file_form" do %> id: "relation_file_form" do %>
<%= hidden_field_tag(:file_id, file.id) %> <%= 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();">引&nbsp;&nbsp;用</a><a href="javascript:void(0)" class="blue_btn grey_btn fl c_white" onclick="closeModal();">取&nbsp;&nbsp;消</a> <a id="submit_quote" href="javascript:void(0)" class="blue_btn fl c_white" onclick="submit_quote();">引&nbsp;&nbsp;用</a><a href="javascript:void(0)" class="blue_btn grey_btn fl c_white" onclick="closeModal();">取&nbsp;&nbsp;消</a>
<% end -%> <% end -%>
</div> </div>
<% end %> <% end %>
</div> </div>
</div> </div>

@ -1,6 +1,6 @@
<div id="resource_list"> <div id="resource_list">
<% if @isproject %> <% if @isproject %>
<%= render :partial => 'project_file', locals: {project: @project} %> <%= render :partial => 'project_file_new', locals: {project: @project} %>
<% else %> <% else %>
<%= render :partial => 'course_file', locals: {course: @course} %> <%= render :partial => 'course_file', locals: {course: @course} %>
<% end %> <% end %>

@ -7,5 +7,5 @@
showModal('ajax-modal', '513px'); showModal('ajax-modal', '513px');
$('#ajax-modal').siblings().remove(); $('#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').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"); $('#ajax-modal').parent().addClass("popbox_polls");

@ -17,11 +17,12 @@
<p style="color: #ff0000"> <p style="color: #ff0000">
(<%= l(:label_memos_max_length) %>) (<%= l(:label_memos_max_length) %>)
</p> </p>
<p> <p class="fl" style="margin-top: 5px;">
<%= l(:label_attachment_plural) %> <%= l(:label_attachment_plural) %>
<br /> <br />
<%= render :partial => 'attachments/form', :locals => {:container => @memo} %> <%= render :partial => 'attachments/form', :locals => {:container => @memo} %>
</p> </p>
<div class="cl"></div>
<%= f.submit :value => l(:label_memo_create) %> <%= f.submit :value => l(:label_memo_create) %>
<%= link_to l(:button_cancel), "#", :onclick => '$("#add-memo").hide(); return false;' %> <%= link_to l(:button_cancel), "#", :onclick => '$("#add-memo").hide(); return false;' %>
</div> </div>

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

@ -48,8 +48,8 @@
</span> </span>
</li> </li>
<li class="c_red" style="margin:25px 0 0 20px;"> 您还没提交作品,请点击提交作品按钮:)</li> <li class="c_red" style="margin:25px 0 0 20px;"> 您还没提交作品,请点击提交作品按钮:)</li>
<li class="wping"> <li class="wping" style="float: right;">
<%= link_to "提交作品", new_exercise_book_path(@bid), :style => "width:80px; margin:20px 0 0 350px;" %> <%= link_to "提交作品", new_exercise_book_path(@bid), :style => "margin:20px 20px 0 0;width:80px;" %>
</li> </li>
</ul> </ul>
<div class="cl"></div> <div class="cl"></div>

@ -1,18 +1,10 @@
<div class="contextual"> <!--added by huang-->
<!--added by huang--> <%#= watcher_link_issue(@issue, User.current) %>
<%#= link_to l(:button_copy), project_copy_issue_path(@project, @issue), :class => 'icon icon-copy' if User.current.allowed_to?(:add_issues, @project) %>
<% if (@issue.author == User.current) || (User.current.admin?) %> <%= link_to l(:button_delete), issue_path(@issue.id), :data => {:confirm => issues_destroy_confirmation_message(@issue)}, :method => :delete, :class => 'talk_edit fr' if User.current.allowed_to?(:delete_issues, @project) %>
<!--end-->
<%= link_to l(:button_update), edit_issue_path(@issue), :onclick => 'showAndScrollTo("update", "issue_notes"); return false;', :class => 'icon icon-edit', :accesskey => accesskey(:edit) if @issue.editable? %>
<% if (@issue.author == User.current) || (User.current.admin?) %>
<%= link_to l(:button_edit), edit_issue_path(@issue), :onclick => 'showAndScrollTo("all_attributes", "issue_notes"); return false;', :class => 'talk_edit fr', :accesskey => accesskey(:edit) if @issue.editable? %>
<% else %> <% else %>
<%= link_to l(:label_user_newfeedback), edit_issue_path(@issue), :onclick => 'showAndScrollTo("update", "issue_notes"); return false;', :class => 'talk_edit fr', :accesskey => accesskey(:edit) if @issue.editable? %>
<%= link_to l(:label_user_newfeedback), edit_issue_path(@issue), :onclick => 'showAndScrollTo("update", "issue_notes"); return false;', :class => 'icon icon-edit', :accesskey => accesskey(:edit) if @issue.editable? %> <% end %>
<% end %>
<%= watcher_link(@issue, User.current) %>
<%= link_to l(:button_copy), project_copy_issue_path(@project, @issue), :class => 'icon icon-copy' if User.current.allowed_to?(:add_issues, @project) %>
<%= link_to l(:button_delete), issue_path(@issue.id), :data => {:confirm => issues_destroy_confirmation_message(@issue)}, :method => :delete, :class => 'icon icon-del' if User.current.allowed_to?(:delete_issues, @project) %>
</div>

@ -1,119 +1,168 @@
<%= labelled_fields_for :issue, @issue do |f| %> <%= labelled_fields_for :issue, @issue do |f| %>
<div class="newpro_box">
<fieldset class="collapsible collapsed" style="padding-left: 50px;"> <fieldset class="collapsible">
<legend onclick="toggleFieldset(this);" style="font-size:12px;"><strong><%= l(:label_change_properties) %></strong></legend> <legend onclick="toggleFieldset(this);"><strong><%= l(:label_change_properties) %></strong></legend>
<div class="splitcontent" style="display: block;"> <ul class="fl">
<div class="splitcontentleft"> <li>
<% if @issue.safe_attribute?('status_id') && @allowed_statuses.present? %> <label class="label"><span class="c_red f12">*</span><%= l(:field_status) %></label>
<p><%= f.select :status_id, (@allowed_statuses.collect {|p| [p.name, p.id]}), {:required => true}, :onchange => "updateIssueFrom('#{escape_javascript project_issue_form_path(@project, :id => @issue, :format => 'js')}')" %></p> <% if @issue.safe_attribute?('status_id') && @allowed_statuses.present? %>
<%= f.select :status_id,
<% else %> (@allowed_statuses.collect { |p| [p.name, p.id] }),
<p><label><%= l(:field_status) %></label> <%= h(@issue.status.name) %></p> {:no_label => true},
<% end %> # ajax 刷新
#:onchange => "updateIssueFrom('#{escape_javascript project_issue_form_path(@project, :id => @issue, :format => 'js')}')",
<% if @issue.safe_attribute? 'priority_id' %> :class => "w150" %>
<p><%= f.select :priority_id, (@priorities.collect {|p| [p.name, p.id]}), {:required => true}, :disabled => !@issue.leaf? %></p> <% else %>
<% end %> <%= h(@issue.status.name) %>
<% end %>
<% if @issue.safe_attribute? 'assigned_to_id' %> </li>
<p><%= f.select :assigned_to_id, principals_options_for_select(@issue.assignable_users, @issue.assigned_to), :include_blank => true, :required => @issue.required_attribute?('assigned_to_id') %></p> <div class="cl"></div>
<% end %> <li>
<label class="label"><span class="c_red f12">*</span><%= l(:field_priority) %></label>
<% if @issue.safe_attribute? 'priority_id' %>
<% if @issue.safe_attribute?('fixed_version_id') && @issue.assignable_versions.any? %> <%= f.select :priority_id,
<p><%= f.select :fixed_version_id, version_options_for_select(@issue.assignable_versions, @issue.fixed_version), :include_blank => true, :required => @issue.required_attribute?('fixed_version_id') %> (@priorities.collect { |p| [p.name, p.id] }),
<%= link_to(image_tag('add.png', :style => 'vertical-align: middle;'), {:required => true, :no_label => true}, :disabled => !@issue.leaf?,
new_project_version_path(@issue.project), :class => "w150" %>
:remote => true, <% end %>
:method => 'get', </li>
:title => l(:label_version_new), <div class="cl"></div>
:tabindex => 200) if User.current.allowed_to?(:manage_versions, @issue.project) %> <li>
</p> <li>
<% end %> <label class="label"><%= l(:field_assigned_to) %></label>
</div> <% if @issue.safe_attribute? 'assigned_to_id' %>
<%= f.select :assigned_to_id, principals_options_for_select(@issue.assignable_users, @issue.assigned_to),
<div class="splitcontentright"> {:required => @issue.required_attribute?('assigned_to_id'), :no_label => true},
:class => "w150" %>
<% if @issue.safe_attribute? 'start_date' %> <% end %>
<p><%= f.text_field :start_date, :size => 10, :disabled => !@issue.leaf?, :required => @issue.required_attribute?('start_date') %><%= calendar_for('issue_start_date','start_date') if @issue.leaf? %></p> </li>
<% end %> <div class="cl"></div>
<li>
<% if @issue.safe_attribute? 'due_date' %> <% if @issue.safe_attribute?('fixed_version_id') && @issue.assignable_versions.any? %>
<p><%= f.text_field :due_date, :size => 10, :disabled => !@issue.leaf?, :required => @issue.required_attribute?('due_date') %><%= calendar_for('issue_due_date','start_date') if @issue.leaf? %></p> <label class="label"><%= l(:field_fixed_version) %></label>
<% end %> <%= f.select :fixed_version_id, version_options_for_select(@issue.assignable_versions, @issue.fixed_version),
{:include_blank => true, :required => @issue.required_attribute?('fixed_version_id'), :no_label => true},
<% if @issue.safe_attribute? 'estimated_hours' %> :class => "w150" %>
<p><%= f.text_field :estimated_hours, :size => 3, :disabled => !@issue.leaf?, :required => @issue.required_attribute?('estimated_hours') %> <%= l(:field_hours) %></p> <%#= link_to(image_tag('add.png', :style => 'vertical-align: middle;'),
<% end %> new_project_version_path(@issue.project),
<script type="text/javascript"> :remote => true,
// window.onload=function(){ :method => 'get',
// var img=$("#issue_due_date").next("img"); :title => l(:label_version_new),
// img.attr("onclick","SetMinValue();"); :tabindex => 200) if User.current.allowed_to?(:manage_versions, @issue.project) %>
// } <%= link_to "", new_project_version_path(@issue.project), :class => "pic_add mt5 ml5 " %>
function TimeClose(dateText, inst) { <!--<a href="javascript:viod(0)" class="pic_add mt5 ml5"></a>-->
if(inst.id=="issue_start_date"){ <% end %>
time=dateText; </li>
} <div class="cl"></div>
}
var time=new Date(); </ul>
function TimeBeforeShow(input){ <ul class="fl ml90">
if(input.id=="issue_due_date"){ <li>
//var minDate = $(input).datepicker('option', 'minDate'); <label class="label02"><%= l(:field_start_date) %></label>
var tempdata=$("#issue_start_date").attr("value"); <% if @issue.safe_attribute? 'start_date' %>
<%= f.text_field :start_date,
$(input).datepicker('option', 'minDate',new Date(tempdata.replace(/-/g, "/"))); :size => 22,
//$('.selector').datepicker('option', 'minDate', '12/25/2012'); :disabled => !@issue.leaf?,
} :no_label => true,
} :required => @issue.required_attribute?('start_date') %>
<%= calendar_for('issue_start_date', 'start_date') if @issue.leaf? %>
function SetMinValue(){ <% end %>
/// var tempdata=$("#issue_start_date").attr("value"); </li>
//$('.selector').datepicker('option', 'minDate', '12/25/2012'); <div class="cl"></div>
//alert(tempdata); <li>
//$("#issue_due_date").datepicker({ <label class="label02"><%= l(:field_due_date) %></label>
// minDate: new Date(2014,08,23) <% if @issue.safe_attribute? 'due_date' %>
//var datepickerOptions= <%= f.text_field :due_date, :size => 22,
//{dateFormat: 'yy-mm-dd',minDate: new Date(2014,08,23), showOn: 'button', buttonImageOnly: true, buttonImage: "path_to_image('/images/calendar.png')", showButtonPanel: true, showWeek: true, showOtherMonths: true, selectOtherMonths: true}; :disabled => !@issue.leaf?,
//alert( $('.issue_due_date').length); :no_label => true,
//$('.selector')[1].datepicker('option', 'minDate', new Date(2014, 0 - 8, 23)); :required => @issue.required_attribute?('due_date') %>
//$("#issue_due_date").datepicker(datepickerOptions); <%= calendar_for('issue_due_date', 'start_date') if @issue.leaf? %>
//$("##{issue_due_date}").datepicker(datepickerOptions); <% end %>
//$("#issue_due_date").datepicker( </li>
// {dateFormat: 'yy-mm-dd',minDate: new Date(2014,08,23), showOn: 'button', buttonImageOnly: true, buttonImage: "path_to_image('/images/calendar.png')", showButtonPanel: true, showWeek: true, showOtherMonths: true, selectOtherMonths: true} <div class="cl"></div>
//) <li>
//}); <label class="label02"><%= l(:field_estimated_hours) %></label>
} <% if @issue.safe_attribute? 'estimated_hours' %>
function PrecentChange(obj){ <%= f.text_field :estimated_hours, :size => 22,
var _v= obj; :disabled => !@issue.leaf?,
if(_v==100) :no_label => true,
{ :required => @issue.required_attribute?('estimated_hours') %>
//var select=$("select[id='issue_status_id']"); <span class="mt3 ml5"><%= l(:field_hours) %></span>
$("select[id='issue_status_id']").find("option[value='3']").attr("selected","selected"); <% end %>
} </li>
else if(_v==0) <div class="cl"></div>
{ <li><label class="label02">&nbsp;% 完成&nbsp;&nbsp;:&nbsp;</label>
//alert(1); <% if @issue.safe_attribute?('done_ratio') && @issue.leaf? && Issue.use_field_for_done_ratio? %>
$("select[id='issue_status_id']").find("option[value='1']").attr("selected","selected"); <%= f.select :done_ratio, ((0..10).to_a.collect { |r| ["#{r*10} %", r*10] }),
} {:required => @issue.required_attribute?('done_ratio'), :no_label => true},
else if(_v!=100&&_v!=0) :onchange => "PrecentChange(this.value)",
{ :class => "w150" %>
// alert(2); <% end %>
$("select[id='issue_status_id']").find("option[value='2']").attr("selected","selected"); </li>
} <div class="cl"></div>
} </ul>
</script> </fieldset>
<% if @issue.safe_attribute?('done_ratio') && @issue.leaf? && Issue.use_field_for_done_ratio? %> </div><!--newpro_box end-->
<p><%= f.select :done_ratio, ((0..10).to_a.collect {|r| ["#{r*10} %", r*10] }), {:required => @issue.required_attribute?('done_ratio')},
{:onchange => "PrecentChange(this.value)"} %></p> <script type="text/javascript">
<% end %> // window.onload=function(){
// var img=$("#issue_due_date").next("img");
</div> // img.attr("onclick","SetMinValue();");
</div> // }
</fieldset> function TimeClose(dateText, inst) {
if (inst.id == "issue_start_date") {
<% if @issue.safe_attribute? 'custom_field_values' %> time = dateText;
<%= render :partial => 'issues/form_custom_fields' %> }
<% end %> }
var time = new Date();
function TimeBeforeShow(input) {
if (input.id == "issue_due_date") {
//var minDate = $(input).datepicker('option', 'minDate');
var tempdata = $("#issue_start_date").attr("value");
$(input).datepicker('option', 'minDate', new Date(tempdata.replace(/-/g, "/")));
//$('.selector').datepicker('option', 'minDate', '12/25/2012');
}
}
function SetMinValue() {
/// var tempdata=$("#issue_start_date").attr("value");
//$('.selector').datepicker('option', 'minDate', '12/25/2012');
//alert(tempdata);
//$("#issue_due_date").datepicker({
// minDate: new Date(2014,08,23)
//var datepickerOptions=
//{dateFormat: 'yy-mm-dd',minDate: new Date(2014,08,23), showOn: 'button', buttonImageOnly: true, buttonImage: "path_to_image('/images/calendar.png')", showButtonPanel: true, showWeek: true, showOtherMonths: true, selectOtherMonths: true};
//alert( $('.issue_due_date').length);
//$('.selector')[1].datepicker('option', 'minDate', new Date(2014, 0 - 8, 23));
//$("#issue_due_date").datepicker(datepickerOptions);
//$("##{issue_due_date}").datepicker(datepickerOptions);
//$("#issue_due_date").datepicker(
// {dateFormat: 'yy-mm-dd',minDate: new Date(2014,08,23), showOn: 'button', buttonImageOnly: true, buttonImage: "path_to_image('/images/calendar.png')", showButtonPanel: true, showWeek: true, showOtherMonths: true, selectOtherMonths: true}
//)
//});
}
function PrecentChange(obj) {
var _v = obj;
if (_v == 100) {
//var select=$("select[id='issue_status_id']");
$("select[id='issue_status_id']").find("option[value='3']").attr("selected", "selected");
}
else if (_v == 0) {
//alert(1);
$("select[id='issue_status_id']").find("option[value='1']").attr("selected", "selected");
}
else if (_v != 100 && _v != 0) {
// alert(2);
$("select[id='issue_status_id']").find("option[value='2']").attr("selected", "selected");
}
}
</script>
<% if @issue.safe_attribute? 'custom_field_values' %>
<%= render :partial => 'issues/form_custom_fields' %>
<% end %>
<% end %> <% end %>

@ -1,51 +1,43 @@
<%= labelled_form_for @issue, :html => {:id => 'issue-form', :multipart => true} do |f| %> <%= labelled_form_for @issue, :html => {:id => 'issue-form', :multipart => true} do |f| %>
<%= error_messages_for 'issue', 'time_entry' %> <%= error_messages_for 'issue', 'time_entry' %>
<%= render :partial => 'conflict' if @conflict %> <%= render :partial => 'conflict' if @conflict %>
<div class="box"> <!--编辑的整个属性-->
<% if @edit_allowed || !@allowed_statuses.empty? %> <% if @edit_allowed || !@allowed_statuses.empty? %>
<fieldset class="tabular"><legend><%= l(:label_change_properties) %></legend> <div id="all_attributes" style="display:none;">
<div id="all_attributes"> <%= render :partial => 'form', :locals => {:f => f} %>
<%= render :partial => 'form', :locals => {:f => f} %> <div class="ping_C mb10"></div>
<!--<a remote="true" href="javascript:void(0)" class="blue_btn fl" style="margin-left: 80px;margin-bottom: 10px;margin-top: -10px;" onclick="$('#issue-form').submit();">-->
<!--<%#= l(:button_submit) %>-->
<!--</a>-->
</div> </div>
</fieldset>
<% end %>
<fieldset><legend><%= l(:field_notes) %></legend> <% end %><!--end-->
<%= f.text_area :notes, :cols => 60, :rows => 10, :class => 'wiki-edit', :no_label => true %>
<%= wikitoolbar_for 'issue_notes' %>
<% if @issue.safe_attribute? 'private_notes' %> <!--<fieldset><legend><%#= l(:field_notes) %></legend>-->
<label for="issue_private_notes"><%= f.check_box :private_notes, :no_label => true %> <%= l(:field_private_notes) %></label> <!--回复框-->
<% if @journals.present? %>
<div id="history">
<%= render :partial => 'history', :locals => {:issue => @issue, :journals => @journals} %>
</div>
<% end %> <% end %>
<fieldset><legend>回复</legend>
<%= call_hook(:view_issues_edit_notes_bottom, { :issue => @issue, :notes => @notes, :form => f }) %> <%= f.text_area :notes, :style => "width:99%;", :rows => "5", :no_label => true %>
</fieldset> </fieldset>
<!--<%# if @issue.safe_attribute? 'private_notes' %>-->
<!--<label for="issue_private_notes"><%#= f.check_box :private_notes, :no_label => true %> <%#= l(:field_private_notes) %></label>-->
<!--<%# end %>-->
<fieldset><legend><%= l(:label_attachment_plural) %></legend> <%= call_hook(:view_issues_edit_notes_bottom, {:issue => @issue, :notes => @notes, :form => f}) %>
<p><%= render :partial => 'attachments/form', :locals => {:container => @issue} %></p> <!--</fieldset>-->
</fieldset>
<div class="box tabular" > <!--<fieldset><legend><%#= l(:label_attachment_plural) %></legend>-->
<p id="watchers_form"> <!--<p style="padding-top: 5px;"><%#= render :partial => 'attachments/new_form', :locals => {:container => @issue} %>
<label style="font-size: 15px;"><%= l(:label_issue_watchers) %></label> <!--</fieldset>-->
<span id="watchers_inputs" style="font-size: 15px;">
<%= watchers_checkboxes(@issue, @available_watchers) %>
</span>
<span class="search_for_watchers" style="font-size: 15px;">
<%= link_to l(:label_search_for_watchers),
{:controller => 'watchers', :action => 'new', :project_id => @issue.project},
:remote => true,
:method => 'get' %>
</span>
</p>
</div>
</div>
<div class="cl"></div>
<%= f.hidden_field :lock_version %> <%= f.hidden_field :lock_version %>
<%= hidden_field_tag 'last_journal_id', params[:last_journal_id] || @issue.last_journal_id %> <%= hidden_field_tag 'last_journal_id', params[:last_journal_id] || @issue.last_journal_id %>
<%= hidden_field_tag 'reference_user_id', params[:reference_user_id]%> <%= hidden_field_tag 'reference_user_id', params[:reference_user_id] %>
<%= submit_tag l(:button_submit) %>
<%= preview_link preview_edit_issue_path(:project_id => @project, :id => @issue), 'issue-form' %>
<% end %> <% end %>
<div id="preview" class="wiki"></div> <div id="preview" class="wiki"></div>

@ -1,65 +1,116 @@
<script type="text/javascript">
window.onready = function()
{
$("#issue_project_id").css("width","100%");
$("#issue_project_id").css("overflow ","hidden");
//issue_project_id
}
</script>
<%= labelled_fields_for :issue, @issue do |f| %> <%= labelled_fields_for :issue, @issue do |f| %>
<%= call_hook(:view_issues_form_details_top, { :issue => @issue, :form => f }) %> <%= call_hook(:view_issues_form_details_top, {:issue => @issue, :form => f}) %>
<div class="newpro_box">
<ul>
<li>
<% if @issue.safe_attribute? 'tracker_id' %>
<label class="label"><span class="c_red f12">*</span>&nbsp;类型&nbsp;&nbsp;:&nbsp;</label>
<%= f.select :tracker_id,
@issue.project.trackers.collect { |t| [t.name, t.id] },
{:required => true, :no_label => true},
:onchange => "updateIssueFrom('#{escape_javascript project_issue_form_path(@project, :id => @issue, :format => 'js')}')",
:class => "w90"
%>
<% end %>
</li>
<li>
<% if @issue.safe_attribute? 'is_private' %>
<%= f.check_box :is_private, :no_label => true, :class => "ml30" %>
<label class="fl ml5 mt3" for="issue_is_private" id="issue_is_private_label"><%= l(:field_is_private) %></label>
<% end %>
</li>
<div class="cl"></div>
<!--<li>-->
<!--<%# if @issue.safe_attribute? 'project_id' %>-->
<%#= f.select :project_id, project_tree_options_for_select(@issue.allowed_target_projects, :selected => @issue.project), {:required => true},
:onchange => "updateIssueFrom('#{escape_javascript project_issue_form_path(@project, :id => @issue, :format => 'js')}')" %>
<!--<%# end %>-->
<!--</li>-->
<li>
<% if @issue.safe_attribute? 'subject' %>
<label class="label"><span class="c_red f12">*</span>&nbsp;主题&nbsp;&nbsp;:&nbsp;</label>
<%= f.text_field :subject,
:class => "w583",
:maxlength => 255,
:style => "font-size:small",
:no_label => true
%>
<!--Added by young-->
<%= javascript_tag do %>
observeAutocompleteField('issue_subject',
'<%= escape_javascript auto_complete_issues_path(:project_id => @project, :scope => (Setting.cross_project_issue_relations? ? 'all' : nil)) %>
',
{ select: function(event, ui) {
$('input#issue_subject').val(ui.item.value);
}
});
<% end %>
<% if @issue.safe_attribute? 'is_private' %> <% end %>
<p style="float:right; margin-right:1em;"> </li>
<%= f.check_box :is_private, :no_label => true %><label class="inline" for="issue_is_private" id="issue_is_private_label"><%= l(:field_is_private) %></label> <div class="cl"></div>
</p>
<% end %>
<% if @issue.safe_attribute? 'project_id' %> <li>
<p><%= f.select :project_id, project_tree_options_for_select(@issue.allowed_target_projects, :selected => @issue.project), {:required => true}, <% if @issue.safe_attribute? 'description' %>
:onchange => "updateIssueFrom('#{escape_javascript project_issue_form_path(@project, :id => @issue, :format => 'js')}')" %></p> <label class="label">&nbsp;描述&nbsp;&nbsp;:&nbsp;</label>
<% end %> <%= f.label_for_field :description, :required => @issue.required_attribute?('description'), :no_label => true, :class => "label" %>
<%= link_to_function image_tag('edit.png'), '$(this).hide(); $("#issue_description_and_toolbar").show()' unless @issue.new_record? %>
<%= content_tag 'span', :id => "issue_description_and_toolbar", :style => (@issue.new_record? ? nil : 'display:none') do %>
<%= f.text_area :description,
:rows => (@issue.description.blank? ? 10 : [[10, @issue.description.length / 50].max, 100].min),
:accesskey => accesskey(:edit),
:class => "w583",
:no_label => true %>
<% end %>
<% if @issue.safe_attribute? 'tracker_id' %> <%= wikitoolbar_for 'issue_description' %>
<p><%= f.select :tracker_id, @issue.project.trackers.collect {|t| [t.name, t.id]}, {:required => true}, <% end %>
:onchange => "updateIssueFrom('#{escape_javascript project_issue_form_path(@project, :id => @issue, :format => 'js')}')" %></p> </li>
<div class="cl"></div>
<% end %> </ul>
</div>
<li>
<% if @issue.safe_attribute? 'subject' %> <% if @copy_from && @copy_from.attachments.any? %>
<p><%= f.text_field :subject, :size => 80, :maxlength => 255, :required => true, :style => "font-size:small" %></p> <p>
<!--Added by young--> <!-- 去除附件复制功能 -->
<%= javascript_tag do %> <!-- <label for="copy_attachments"><#%= l(:label_copy_attachments) %></label>
observeAutocompleteField('issue_subject', '<%= escape_javascript auto_complete_issues_path(:project_id => @project,:scope => (Setting.cross_project_issue_relations? ? 'all' : nil)) %>', <#%= check_box_tag 'copy_attachments', '1', @copy_attachments %> -->
{ select: function(event, ui) { </p>
$('input#issue_subject').val(ui.item.value); <% end %>
} <% if @copy_from && !@copy_from.leaf? %>
}); <p>
<% end %> <label for="copy_subtasks"><%= l(:label_copy_subtasks) %></label>
<%= check_box_tag 'copy_subtasks', '1', @copy_subtasks %>
<% end %> </p>
<% end %>
<% if @issue.safe_attribute? 'description' %> </li>
<p> <div class="cl"></div>
<%= f.label_for_field :description, :required => @issue.required_attribute?('description') %> <li>
<%= link_to_function image_tag('edit.png'), '$(this).hide(); $("#issue_description_and_toolbar").show()' unless @issue.new_record? %> <br>
<%= content_tag 'span', :id => "issue_description_and_toolbar", :style => (@issue.new_record? ? nil : 'display:none') do %> <label class="label"><%= l(:label_attachment_plural) %></label>
<%= f.text_area :description, <%= render :partial => 'attachments/form', :locals => {:container => @issue} %>
:cols => 60, </li>
:rows => (@issue.description.blank? ? 10 : [[10, @issue.description.length / 50].max, 100].min), <div class="cl"></div>
:accesskey => accesskey(:edit), <div id="attributes">
:class => 'wiki-edit', <%= render :partial => 'issues/attributes' %>
:style => "font-size:small;width:520px;", </div>
:no_label => true %> <div class="cl"></div>
<% end %> <!--<div class="newpro_box02 ">-->
</p> <!--<label class="label"> <%#= l(:label_issue_watchers) %></label>-->
<%= wikitoolbar_for 'issue_description' %> <!--<input id="" name="" size="22" class="fl mb10 h26" type="text" placeholder="搜索添加跟踪者">-->
<% end %> <!--<span class="search_for_watchers">-->
<%#= link_to "",
<div id="attributes" class="attributes"> # {:controller => 'watchers', :action => 'new', :project_id => @issue.project},
<%= render :partial => 'issues/attributes' %> # :remote => true,
</div> # :method => 'get',
:class => "pic_sch mt5 ml5" %>
<%= call_hook(:view_issues_form_details_bottom, { :issue => @issue, :form => f }) %> <!--</span>-->
<% end %> <%#= javascript_tag "observeSearchfield('user_search', 'users_for_watcher', '#{ escape_javascript watchers_autocomplete_for_user_path(:user => @available_watchers, :format => 'js', :flag => 'ture') }')" %>
<!--<div class="cl"></div>-->
<!--<span id="watchers_inputs">-->
<!--<%#= watchers_checkboxes(@issue, @available_watchers) %>-->
<!--</span>-->
<!--<div class="cl"></div>-->
<!--</div>-->
<%= call_hook(:view_issues_form_details_bottom, {:issue => @issue, :form => f}) %>
<% end %>

@ -1,43 +1,33 @@
<% reply_links = authorize_for('issues', 'edit') -%> <% reply_links = authorize_for('issues', 'edit') -%>
<% for journal in journals %> <% journals.reverse.each do |journal| %>
<!-- modified by bai --> <!-- modified by bai -->
<div id="change-<%= journal.id %>" class="<%= journal.css_classes %>" style=" word-wrap: break-word; word-break: break-all"> <div id="change-<%= journal.id %>" class="<%= journal.css_classes %>" style=" word-wrap: break-word; word-break: break-all">
<!-- end --> <!-- end -->
<table width="660px" border="0" align="center"> <div class="ping_C mb10">
<tr> <div class="ping_dispic"><a href="#" target="_blank"><%= image_tag(url_to_avatar(journal.user), :class => "ping_dispic",:width => 46,:height => 46) %></a></div>
<td colspan="2" valign="top" width="50" ><%= image_tag(url_to_avatar(journal.user), :class => "avatar") %></td> <div class="ping_discon">
<td> <div class="ping_distop">
<table width="580px" border="0"> <a href="#" target="_blank" class="c_blue fb fl mb10 "><%= journal.user %></a><span class="c_grey fr"><%= format_time journal.created_on %></span>
<tr> <div class="cl"></div>
<!-- add by huang --> <p>
<td colspan="1" valign="top"> <%= authoring journal.created_on, journal.user, :label => :label_updated_time_by %> <div id="note-<%= journal.indice %>"></div></td> <% if journal.details.any? %>
<td><%= render_links(issue, journal, :reply_links => reply_links) unless journal.notes.blank? %></td> <% details_to_strings(journal.details).each do |string| %>
<!--end--> <p><%= string %></p>
</tr> <% end %>
<tr> <% end %>
<td colspan="2" width="580px" > </p>
<p class="font_description"> </div>
<% if journal.details.any? %> <!--编辑、引用、回复按钮-->
<span class="details"> <% details_to_strings(journal.details).each do |string| %> <div class="ping_disfoot"><%= render_links_easy(issue, journal, :reply_links => reply_links) unless journal.notes.blank? %></div>
<!--回复内容、引用内容-->
<%= string %> <p><%= render_notes_issue(issue, journal, :reply_links => reply_links) unless journal.notes.blank? %></p>
<% end %> </span> <div class="cl"></div>
<% end %> </div>
<%= render_notes(issue, journal, :reply_links => reply_links) unless journal.notes.blank? %> <div class="cl"></div>
</p></td> </div>
</tr>
<tr>
<td align="left"><span class="font_lighter"> <%= format_time journal.created_on %></span></td>
<td width="200" align="right" class="a"></td>
</tr>
</table></td>
</tr>
</table>
</div> </div>
<div class="line_under"></div>
<%= call_hook(:view_issues_history_journal_bottom, { :journal => journal }) %> <%= call_hook(:view_issues_history_journal_bottom, { :journal => journal }) %>
<% end %> <% end %>
<% heads_for_wiki_formatter if User.current.allowed_to?(:edit_issue_notes, issue.project) || User.current.allowed_to?(:edit_own_issue_notes, issue.project) %> <% heads_for_wiki_formatter if User.current.allowed_to?(:edit_issue_notes, issue.project) || User.current.allowed_to?(:edit_own_issue_notes, issue.project) %>

@ -1,69 +1,35 @@
<div class="autoscroll"> <% issue_list(issues) do |issue, level| -%>
<ul>
<% issue_list(issues) do |issue, level| -%>
<% if @query.grouped? && (group = @query.group_by_column.value(issue)) != previous_group %> <% if @query.grouped? && (group = @query.group_by_column.value(issue)) != previous_group %>
<% reset_cycle %> <% reset_cycle %>
<% previous_group = group %> <% previous_group = group %>
<% end %> <% end %>
<div style=""> <!-- CONTENT LIST -->
<li id="issue-<%= issue.id %>" class="hascontextmenu-1 <%= issue.css_classes %> <%= level > 0 ? "idnt idnt-#{level}" : nil %>"> <div class="problem_main">
<% column_content = ( query.inline_columns.map {|column| "#{column_content_new(column, issue)}"}) %> <% column_content = ( query.inline_columns.map {|column| "#{column_content_new(column, issue)}"}) %>
<% if issue.tracker_id == 1 %> <% unless issue.author.nil? || issue.author.name == "Anonymous" %>
<%= image_tag("/images/task.png", :class => "img-tag-issues") %> <span class="issues_icon fl"></span>
<% end %> <div class="problem_txt fl">
<% if issue.tracker_id == 2 %> <%= link_to issue.author.name, user_path(issue.author), :class => "problem_name c_orange fl" %>
<%= image_tag("/images/feature.png", :class => "img-tag-issues") %> <span class="fl"><%= l(:label_post_on_issue) %>(<%= "#{raw column_content[2]}" %>)</span>
<% end %> <div class="problem_tit_div fl">
<% if issue.tracker_id == 3 %> <%=link_to "#{column_content[4]}<span class = '#{get_issue_type(column_content[1])}'>#{get_issue_typevalue(column_content[1])}</span>".html_safe, issue_path(issue.id), :class => "problem_tit_a break_word" %>
<%= image_tag("/images/support.png", :class => "img-tag-issues") %> </div>
<% end %> <div class="cl"></div>
<% if issue.tracker_id == 4 %> <p>
<%= image_tag("/images/issues.png", :class => "img-tag-issues") %> <% unless issue.assigned_to_id.nil? %>
<% end %> <%= l(:field_assigned_to) %>
<%=link_to issue.assigned_to(@user), user_path(issue.assigned_to(@user)), :class => "problem_name c_orange f1" %>
<% end %>
<%= l(:label_updated_time_on, format_date(issue.updated_on)).html_safe %>
</p>
</div>
<%=link_to "<span class = 'pic_mes'>#{issue.journals.all.count}</span>".html_safe, issue_path(issue.id), :class => "pro_mes_w" %>
<ul class="issue_list"> <div class="cl"></div>
<% unless issue.author.nil? || issue.author.name == "Anonymous" %> <% end %>
<ul class="list-group-item-meta" style="word-break: break-all;word-wrap: break-word;width: 100%;"> <div class="cl"></div>
<!-- 在这里添加赞和踩-->
<span id="praise_tread" style="float: right">
<%= render :partial => "/praise_tread/praise_tread",:locals =>
{:obj => issue,:show_flag => true,:user_id =>User.current.id,:horizontal => false}%>
</span>
<span>
<%= link_to issue.author.name, user_path(issue.author), :class => "bid_user_u" %>
</span>
<%= l(:label_post_on)%>
<% a = [] %>
<% a << column_content[1] %>
<%# a << "##{column_content[0]}" << "(#{raw column_content[2]}):" << column_content[4] %>
<% a << "#{issue.source_from}" << "(#{raw column_content[2]}):" << column_content[4] %>
<%= link_to a.join(' '), issue_path(issue.id), :class => "issue-link" , :target =>"_blank"%>
<ul class="list-group-item-meta">
<div class="wiki" style="width: 100%;word-break: break-all;word-wrap: break-word;">
<%= textilizable issue, :description %>
</div>
</ul>
</ul>
<ul class="list-group-item-meta" style="margin-top: -15px;">
<% unless issue.assigned_to_id.nil? %>
<span>
<%= l(:field_assigned_to)%>&nbsp;
</span>
<%= raw column_content[5] %>&nbsp;
<% end %>
<%= l(:label_updated_time_on, format_date(issue.updated_on)).html_safe %>
<div class="find-comment-class">
<span>
<%= link_to l(:label_find_all_comments), issue_path(issue.id) if issue.journals.all.count!= 0 %>
</span>
<%= l(:label_comments_count, :count => issue.journals.all.count) %>
</div>
</ul>
<% end -%>
</ul>
</li>
</div> </div>
<% end -%> <% end -%>
</ul> <ul class="wlist">
</div> <%= pagination_links_full issue_pages, issue_count, :per_page_links => false, :remote => false, :flag => true %>
</ul>

@ -1,18 +1,77 @@
<script>
function remote_function() {
$.ajax({
url:'<%= project_issues_path(@project)%>',
data:{
subject:$("#v_subject").attr("value").replace(/(^\s*)|(\s*$)/g, ""),
status_id: $("#status_id").attr("value").replace(/(^\s*)|(\s*$)/g, ""),
assigned_to_id: $("#assigned_to_id option:selected").attr("value").replace(/(^\s*)|(\s*$)/g, ""),
priority_id: $("#priority_id option:selected").attr("value").replace(/(^\s*)|(\s*$)/g, ""),
author_id: $("#author_id option:selected").attr("value").replace(/(^\s*)|(\s*$)/g, "")
},
success: function(data){
},
error: function(data){
}
});
}
function EnterPress(e){
var e = e || window.event;
if(e.keyCode == 13){
remote_function();
}
}
</script>
<div class="project_r_h"> <div class="project_r_h">
<h2 class="project_h2"><%= l(:label_issue_tracking) %></h2> <h2 class="project_h2"><%= l(:label_issue_tracking) %></h2>
</div> </div>
<div class="problem_top"> <div class="problem_top">
<% unless @project.enabled_modules.where("name = 'issue_tracking'").empty? %> <% unless @project.enabled_modules.where("name = 'issue_tracking'").empty? %>
<span> <%#= form_tag({:controller => 'issues', :action => 'index', :project_id => @project}, :method => :get,:id=>"issue_query_form", :class => 'query_form') do %>
<% if User.current.member_of?(@project) %> <%= hidden_field_tag 'set_filter', '1' %>
<%= link_to l(:label_issue_new), {:controller => 'issues', :action => 'new', :copy_from => nil}, :param => :project_id, :caption => :label_issue_new, <div class="problem_search" >
:html => {:accesskey => Redmine::AccessKeys.key_for(:new_issue)}, :class => 'icon icon-add' %> <input class="problem_search_input fl" id="v_subject" type="text" name="v[subject]" value="" onkeypress="EnterPress(event)" onkeydown="EnterPress()">
<% end %> <a href="javascript:void(0)" class="problem_search_btn fl" onclick="remote_function();" >搜索</a>
<%= link_to l(:label_query), '#', :class => 'icon icon-help', </div><!--problem_search end-->
:onclick => '$("#custom_query").slideToggle(400); ' if true || User.current.logged? %>
</span> <div id="filter_form" class="fr" >
<%= select( :issue,:user_id, @project.members.order("lower(users.login)").map{|c| [c.name, c.user_id]}.unshift(["指派给",0]),
{ :include_blank => false,:selected=>0
},
{:onchange=>"remote_function();",:id=>"assigned_to_id",:name=>"v[assigned_to_id]",:class=>"w90"}
)
%>
<%= select( :issue,:prior, [["低",1],["正常",2],["高",3],["紧急",4],["立刻",5]].unshift(["优先级",0]),
{ :include_blank => false,:selected=>0
},
{:onchange=>"remote_function();",:id=>"priority_id",:name=>"v[priority_id]",:class=>"w90"}
)
%>
<%= select( :issue,:status, [["新增",1],["正在解决",2],["已解决",3],["反馈",4],["关闭",5],["拒绝",6]].unshift(["状态",0]),
{ :include_blank => false,:selected=>0
},
{:onchange=>"remote_function();",:id=>"status_id",:name=>"v[status_id]",:class=>"w90"}
)
%>
<%= select( :issue,:user_id, @project.members.order("lower(users.login)").map{|c| [c.name, c.user_id]}.unshift(["作者",0]),
{ :include_blank => false,:selected=>0
},
{:onchange=>"remote_function();",:id=>"author_id",:name=>"v[author_id]",:class=>"w90"}
)
%>
</div><!--filter_form end-->
<div class="cl"></div>
<%# end %>
<p class="problem_p fl" ><%= l(:label_issues_sum) %><a href="javascript:void(0)" class="c_red"><%= @project.issues.count %></a>
<%= l(:lable_issues_undo) %><a href="javascript:void(0)" class="c_red"><%= @project.issues.where('status_id in (1,2,4,6)').count %> </a>
</p>
<div class="cl"></div>
<% end %> <% end %>
<span class="problem_p fr"><%= l(:label_issues_sum) %><span><%= @project.issues.count %></span> <%= l(:lable_issues_undo) %><span><%= @project.issues.where('status_id in (1,2,4,6)').count %></span></span>
</div> </div>
<div class="contextual"> <div class="contextual">
<% if !@query.new_record? && @query.editable_by?(User.current) %> <% if !@query.new_record? && @query.editable_by?(User.current) %>
@ -23,51 +82,6 @@
<% html_title(@query.new_record? ? l(:label_issue_plural) : @query.name) %> <% html_title(@query.new_record? ? l(:label_issue_plural) : @query.name) %>
<div style="clear:right; "> <div style="clear:right; ">
<%= form_tag({:controller => 'issues', :action => 'index', :project_id => @project}, :method => :get, :id => 'query_form', :class => 'query_form') do %>
<%= hidden_field_tag 'set_filter', '1' %>
<div id="custom_query" class="custom_query" style="display: <%= !params[:utf8].blank? ? 'block' : 'none' %>;">
<span>---<%= l :label_query_new %>---</span>
<div id="query_form_content" class="hide-when-print">
<fieldset id="filters" class="collapsible <%= @query.new_record? ? "" : "collapsed" %>">
<legend onclick="toggleFieldset(this);">
<%= l(:label_issue_query_condition) %>
</legend>
<div style="<%= @query.new_record? ? "" : "display: none;" %>">
<%= render :partial => 'queries/filters', :locals => {:query => @query} %>
</div>
</fieldset>
<!--
<fieldset class="collapsible collapsed">
<legend onclick="toggleFieldset(this);">
<%= l(:label_options) %>
</legend>
<div style="display: none;">
<table>
<tr>
<td><%= l(:field_column_names) %></td>
<td><%= render_query_columns_selection(@query) %></td>
</tr>
<tr>
<td><label for='group_by'><%= l(:field_group_by) %></label></td>
<td><%= select_tag('group_by', options_for_select([[]] + @query.groupable_columns.collect { |c| [c.caption, c.name.to_s] }, @query.group_by)) %></td>
</tr>
<tr>
<td><%= l(:button_show) %></td>
<td><%= available_block_columns_tags(@query) %></td>
</tr>
</table>
</div>
</fieldset>
-->
<div class="buttons hide-when-print">
<%= link_to_function l(:label_issue_query), 'submit_query_form("query_form")', :class => 'icon icon-checked' %>
<%= link_to l(:label_issue_cancel_query), {:set_filter => 1, :project_id => @project}, :class => 'icon icon-reload' %>
</div>
</div>
</div>
<% end %>
</div> </div>
<%= error_messages_for 'query' %> <%= error_messages_for 'query' %>
@ -78,12 +92,14 @@
<%= l(:label_no_data) %> <%= l(:label_no_data) %>
</p> </p>
<% else %> <% else %>
<%= render :partial => 'issues/list', :locals => {:issues => @issues, :query => @query} %> <div id="issue_list">
<div class="pagination"> <%= render :partial => 'issues/list', :locals => {:issues => @issues, :query => @query,:issue_pages=>@issue_pages,:issue_count=>@issue_count} %>
<ul><%= pagination_links_full @issue_pages, @issue_count %></ul>
</div> </div>
<% end %> <% end %>
<div style="float: right; padding-top: 30px">
<div style="float: left; padding-top: 30px">
<% other_formats_links do |f| %> <% other_formats_links do |f| %>
<%= f.link_to 'Atom', :url => params.merge(:key => User.current.rss_key) %> <%= f.link_to 'Atom', :url => params.merge(:key => User.current.rss_key) %>
<%= f.link_to 'CSV', :url => params, :onclick => "showModal('csv-export-options', '330px'); return false;" %> <%= f.link_to 'CSV', :url => params, :onclick => "showModal('csv-export-options', '330px'); return false;" %>
@ -91,7 +107,6 @@
<% end %> <% end %>
</div> </div>
<div id="csv-export-options" style="display:none;"> <div id="csv-export-options" style="display:none;">
<h3 class="title"><%= l(:label_export_options, :export_format => 'CSV') %></h3> <h3 class="title"><%= l(:label_export_options, :export_format => 'CSV') %></h3>
<%= form_tag(params.merge({:format => 'csv', :page => nil}), :method => :get, :id => 'csv-export-form') do %> <%= form_tag(params.merge({:format => 'csv', :page => nil}), :method => :get, :id => 'csv-export-form') do %>
@ -115,11 +130,8 @@
</p> </p>
<% end %> <% end %>
</div> </div>
<% end %> <% end %>
<%= call_hook(:view_issues_index_bottom, {:issues => @issues, :project => @project, :query => @query}) %> <%= call_hook(:view_issues_index_bottom, {:issues => @issues, :project => @project, :query => @query}) %>
<% content_for :sidebar do %> <% content_for :sidebar do %>
<%= render :partial => 'issues/sidebar' %> <%= render :partial => 'issues/sidebar' %>
<% end %> <% end %>

@ -0,0 +1 @@
$("#issue_list").html("<%= escape_javascript(render :partial => 'issues/list',:locals => {:issues => @issues, :query => @query,:issue_pages=>@issue_pages,:issue_count=>@issue_count})%>");

@ -1,57 +1,20 @@
<div class="project_r_h"> <div class="project_r_h" xmlns="http://www.w3.org/1999/html">
<h2 class="project_h2"><%= l(:label_issue_new) %></h2> <h2 class="project_h2"><%= l(:label_issue_new) %></h2>
</div> </div>
<%= call_hook(:view_issues_new_top, {:issue => @issue}) %> <%= call_hook(:view_issues_new_top, {:issue => @issue}) %>
<%= labelled_form_for @issue, :url => project_issues_path(@project), <%= labelled_form_for @issue, :url => project_issues_path(@project),
:html => {:id => 'issue-form', :multipart => true} do |f| %> :html => {:id => 'issue-form', :multipart => true} do |f| %>
<%= error_messages_for 'issue' %> <%= error_messages_for 'issue' %>
<%= hidden_field_tag 'copy_from', params[:copy_from] if params[:copy_from] %> <%= hidden_field_tag 'copy_from', params[:copy_from] if params[:copy_from] %>
<div class="box tabular"> <div>
<div id="all_attributes"> <%= render :partial => 'issues/form', :locals => {:f => f} %>
<%= render :partial => 'issues/form', :locals => {:f => f} %>
</div> </div>
<!--<%= javascript_tag "$('#issue_subject').focus();" %>-->
<% if @copy_from && @copy_from.attachments.any? %> <a href="#" class="blue_btn fl ml80" onclick="$('#issue-form').submit();">
<p> <%= l(:button_create) %>
<!-- 去除附件复制功能 -->
<!-- <label for="copy_attachments"><#%= l(:label_copy_attachments) %></label>
<#%= check_box_tag 'copy_attachments', '1', @copy_attachments %> -->
</p>
<% end %>
<% if @copy_from && !@copy_from.leaf? %>
<p>
<label for="copy_subtasks"><%= l(:label_copy_subtasks) %></label>
<%= check_box_tag 'copy_subtasks', '1', @copy_subtasks %>
</p>
<% end %>
<p id="attachments_form"><label><%= l(:label_attachment_plural) %></label><%= render :partial => 'attachments/form', :locals => {:container => @issue} %></p>
<% if @issue.safe_attribute? 'watcher_user_ids' -%>
<p id="watchers_form">
<label>
<%= l(:label_issue_watchers) %>
</label>
<span id="watchers_inputs">
<%= watchers_checkboxes(@issue, @available_watchers) %>
</span>
<span class="search_for_watchers">
<%= link_to l(:label_search_for_watchers),
{:controller => 'watchers', :action => 'new', :project_id => @issue.project},
:remote => true,
:method => 'get' %>
</span>
</p>
<% end %>
</div>
<a href="#" class="ButtonColor m3p10" onclick="$('#issue-form').submit();">
<%= l(:button_create)%>
</a> </a>
<%= preview_link preview_new_issue_path(:project_id => @project), 'issue-form','preview',{:class => "ButtonColor m3p10"}%> <%#= preview_link preview_new_issue_path(:project_id => @project), 'issue-form', 'preview', {:class => "blue_btn fl ml10"} %>
<%= javascript_tag "$('#issue_subject').focus();" %>
<% end %> <% end %>
<div id="preview" class="wiki"></div> <div id="preview" class="wiki"></div>

@ -1,177 +1,156 @@
<div class="project_r_h"> <div class="project_r_h">
<h2 class="project_h2"><%= l(:label_issue_edit) %></h2> <h2 class="project_h2"><%= l(:label_issue_edit) %></h2>
</div> </div>
<%# html_title "#{@issue.tracker.name} ##{@issue.id}: #{@issue.subject}" %>
<% html_title "#{@issue.tracker.name} #{@issue.source_from}'#'#{@issue.project_index}: #{@issue.subject}" %> <% html_title "#{@issue.tracker.name} #{@issue.source_from}'#'#{@issue.project_index}: #{@issue.subject}" %>
<div class="pro_page_box">
<%= render :partial => 'action_menu' %> <div class="pro_page_top break_word">
<a href="javascript:void(0)"><%= @issue.project.name %></a> >
<h3> <a href="javascript:void(0)"><%= "#" + @issue.project_index %></a>
<%= issue_heading(@issue) %> </div>
</h3> <div class="problem_main">
<div class="ping_dispic">
<style type="text/css"></style> <%= link_to image_tag(url_to_avatar(@issue.author), :width => 46, :height => 46), user_path(@issue.author), :class => "ping_dispic" %>
<div class="<%= @issue.css_classes %> details">
<% if @prev_issue_id || @next_issue_id %>
<div class="next-prev-links contextual">
<%= link_to_if @prev_issue_id,
"\xc2\xab #{l(:label_previous)}",
(@prev_issue_id ? issue_path(Issue.find_by_id(@prev_issue_id)) : nil),
:title => "##{@prev_issue_id}" %> |
<% if @issue_position && @issue_count %>
<span class="position"><%= l(:label_item_position, :position => @issue_position, :count => @issue_count) %></span> |
<% end %>
<%= link_to_if @next_issue_id,
"#{l(:label_next)} \xc2\xbb",
(@next_issue_id ? issue_path(Issue.find_by_id(@next_issue_id)) : nil),
:title => "##{@next_issue_id}" %>
</div> </div>
<% end %> <div class="talk_txt fl">
<p class="pro_page_tit" style="word-break:break-all;">
<!-- <%#= avatar(@issue.author, :size => "50") %> --> <%= @issue.subject %>
<span class='<%= "#{get_issue_type(@issue.tracker_id)}" %>'><%= get_issue_typevalue(@issue.tracker_id) %></span>
<div class="subject" style="word-wrap: break-word;"> </p><br/>
<%= render_issue_subject_with_tree(@issue) %>
</div> <div class="cl"></div>
<p>由<a href="javascript:void(0)" class="problem_name"><%= @issue.author %></a>
<!-- 顶和踩 在这里添加 -->
<span id="praise_tread" style="float: right">
<%= render :partial => "/praise_tread/praise_tread",:locals => {:obj => @issue,:show_flag => true,:user_id =>User.current.id,:horizontal => false}%>
</span>
<p class="author">
<%= authoring @issue.created_on, @issue.author %>.
<% if @issue.created_on != @issue.updated_on %> <% if @issue.created_on != @issue.updated_on %>
<%= l(:label_updated_time, time_tag(@issue.updated_on)).html_safe %>. 更新于 <%= format_time(@issue.created_on).html_safe %>
<% end %> <% else %>
</p> 添加于 <%= format_time(@issue.updated_on).html_safe %>
<!-- added by william -for tag --> <% end %>
<div id="tags"> </div>
<%= render :partial => 'tags/tag', :locals => {:obj => @issue,:object_flag => "3" }%> <!--talk_txt end-->
</div> <a href="javascript:void(0)" class="talk_edit fr"<%= render :partial => 'action_menu' %></a>
<table class="attributes"> <div class="cl"></div>
<%= issue_fields_rows do |rows| <div class="talk_info mb10" style="word-break:break-all;">
rows.left l(:field_status), h(@issue.status.name), :class => 'status' <% if @issue.description? || @issue.attachments.any? -%>
rows.left l(:field_priority), h(@issue.priority.name), :class => 'priority' <% if @issue.description? %>
<%#= link_to l(:button_quote), quoted_issue_path(@issue.id), :remote => true, :method => 'post', :class => 'icon icon-comment' if authorize_for('issues', 'edit') %>
unless @issue.disabled_core_fields.include?('assigned_to_id') <%= textilizable @issue, :description, :attachments => @issue.attachments %>
#modified by nie <% end %>
#modified by huang </div>
rows.left l(:field_assigned_to), (image_tag url_to_avatar(@issue.assigned_to(@user)), :class => 'avatar').to_s.html_safe + (@issue.assigned_to ? link_to_user(@issue.assigned_to) : "-"), :class => 'assigned-to' <div class="pro_pic_box mb10">
end <a href="javascript:void(0)" class="link_img fl">
# end huang <!--显示附件、图片-->
unless @issue.disabled_core_fields.include?('category_id') <%= link_to_attachment_project @issue, :thumbnails => true %></a><br/>
rows.left l(:field_category), h(@issue.category ? @issue.category.name : "-"), :class => 'category' <% end -%>
end <%= call_hook(:view_issues_show_description_bottom, :issue => @issue) %>
unless @issue.disabled_core_fields.include?('fixed_version_id') </div><!--pro_pic_box end-->
rows.left l(:field_fixed_version), (@issue.fixed_version ? link_to_version(@issue.fixed_version) : "-"), :class => 'fixed-version' <div class="cl"></div>
end <!--属性-->
<div class="pro_info_box mb10">
unless @issue.disabled_core_fields.include?('start_date') <%= issue_fields_rows do |rows| %>
rows.right l(:field_start_date), format_date(@issue.start_date), :class => 'start-date' <ul class="fl">
end
unless @issue.disabled_core_fields.include?('due_date') <li><p class="label"><span class="c_red f12">*</span>&nbsp;状态&nbsp;&nbsp;:&nbsp;</p>
rows.right l(:field_due_date), format_date(@issue.due_date), :class => 'due-date'
end <p class="pro_info_p"><%= @issue.status.name %></p>
unless @issue.disabled_core_fields.include?('done_ratio') </li>
rows.right l(:field_done_ratio), progress_bar(@issue.done_ratio, :width => '80px', :legend => "#{@issue.done_ratio}%"), :class => 'progress' <div class="cl"></div>
end <li><p class="label"><span class="c_red f12">*</span>&nbsp;优先级&nbsp;&nbsp;:&nbsp;</p>
unless @issue.disabled_core_fields.include?('estimated_hours') <span class="pro_info_p"><%= @issue.priority.name %></span>
unless @issue.estimated_hours.nil? </li>
rows.right l(:field_estimated_hours), l_hours(@issue.estimated_hours), :class => 'estimated-hours' <div class="cl"></div>
end <% unless @issue.disabled_core_fields.include?('assigned_to_id') %>
end <li><p class="label">&nbsp;指派给&nbsp;&nbsp;:&nbsp;</p>
if User.current.allowed_to?(:view_time_entries, @project) <span class="pro_info_p"><%= @issue.assigned_to ? link_to_isuue_user(@issue.assigned_to) : "-" %></span>
rows.right l(:label_spent_time), (@issue.total_spent_hours > 0 ? link_to(l_hours(@issue.total_spent_hours), project_issue_time_entries_path(@project, @issue)) : "-"), :class => 'spent-time' </li>
end <% end %>
end %> <div class="cl"></div>
<%= render_custom_fields_rows(@issue) %> <% unless @issue.disabled_core_fields.include?('fixed_version_id') %>
<%= call_hook(:view_issues_show_details_bottom, :issue => @issue) %> <li><p class="label">&nbsp;目标版本&nbsp;&nbsp;:&nbsp;</p>
</table> <span class="pro_info_p"><%= (@issue.fixed_version ? link_to_version(@issue.fixed_version, :class => "pro_info_p") : "-") %></span>
</li>
<% if @issue.description? || @issue.attachments.any? -%> <% end %>
<hr /> <div class="cl"></div>
<% if @issue.description? %> </ul>
<div class="description"> <ul class="fl ml90">
<div class="contextual"> <% unless @issue.disabled_core_fields.include?('start_date') %>
<%= link_to l(:button_quote), quoted_issue_path(@issue.id), :remote => true, :method => 'post', :class => 'icon icon-comment' if authorize_for('issues', 'edit') %> <li><p class="label02">&nbsp;开始日期&nbsp;&nbsp;:&nbsp;</p>
</div>
<p class="pro_info_p"><%= format_date(@issue.start_date) %></p></li>
<p><strong><%=l(:field_description)%></strong></p> <% end %>
<div class="wiki"> <div class="cl"></div>
<%= textilizable @issue, :description, :attachments => @issue.attachments %> <% unless @issue.disabled_core_fields.include?('due_date') %>
</div> <li><p class="label02">&nbsp;计划完成日期&nbsp;&nbsp;:&nbsp;</p>
</div> <span class="pro_info_p"><%= format_date(@issue.due_date) %></span>
<% end %> </li>
<%= link_to_attachments @issue, :thumbnails => true %> <% end %>
<% end -%> <div class="cl"></div>
<% unless @issue.disabled_core_fields.include?('estimated_hours') %>
<%= call_hook(:view_issues_show_description_bottom, :issue => @issue) %>
<li><p class="label02">&nbsp;预期时间&nbsp;&nbsp;:&nbsp;</p>
<% if false # !@issue.leaf? || User.current.allowed_to?(:manage_subtasks, @project) %> <span class="pro_info_p"><%= l_hours(@issue.estimated_hours) %></span>
<hr /> </li>
<div id="issue_tree"> <% end %>
<div class="contextual"> <div class="cl"></div>
<%= link_to_new_subtask(@issue) if User.current.allowed_to?(:manage_subtasks, @project) %> <% unless @issue.disabled_core_fields.include?('done_ratio') %>
</div> <li><p class="label02">&nbsp;% 完成&nbsp;&nbsp;:&nbsp;</p>
<span class="pro_info_p"><%= @issue.done_ratio %>%</span>
<p><strong><%=l(:label_subtask_plural)%></strong></p> </li>
<%= render_descendants_tree(@issue) unless @issue.leaf? %> <% end %>
</div> <div class="cl"></div>
<% end %> </ul>
<% end %>
<% if @relations.present? || User.current.allowed_to?(:manage_issue_relations, @project) %> <%#= render_custom_fields_rows(@issue) %>
<hr /> <%#= call_hook(:view_issues_show_details_bottom, :issue => @issue) %>
<div id="relations"> </div>
<%= render :partial => 'relations' %> <!--pro_info_box 属性 end-->
</div> <div class="cl"></div>
<% end %> <%= link_to l(:button_quote), quoted_issue_path(@issue.id), :remote => true, :method => 'post', :class => 'talk_edit fr' if authorize_for('issues', 'edit') %></a>
<div class="cl"></div>
</div>
<!--problem_main end-->
<div style="clear: both;"></div>
<% if @issue.editable? %>
<div id="update">
<%= render :partial => 'edit' %>
</div>
<!--留言-->
<p style="padding-top: 5px"></p>
<a remote="true" href="javascript:void(0)" class="blue_btn fr mr80" onclick="$('#issue-form').submit();">
<%= l(:button_submit) %>
</a>
<% end %>
<%#= submit_tag l(:button_submit) %>
<%#= preview_link preview_edit_issue_path(:project_id => @project, :id => @issue), 'issue-form' ,'preview',{:class => "blue_btn fr mr10"}%>
</div> </div>
<% if @changesets.present? %> <% if @changesets.present? %>
<div id="issue-changesets"> <div id="issue-changesets">
<h3><%=l(:label_associated_revisions)%></h3> <h3><%= l(:label_associated_revisions) %></h3>
<%= render :partial => 'changesets', :locals => { :changesets => @changesets} %> <%= render :partial => 'changesets', :locals => {:changesets => @changesets} %>
</div> </div>
<% end %>
<% if @journals.present? %>
<div id="history">
<h3><%=l(:label_history)%></h3>
<%= render :partial => 'history', :locals => { :issue => @issue, :journals => @journals } %>
</div>
<% end %> <% end %>
<!--留言-- end>
<!--<div style="clear: both;"></div>-->
<!--<%#= render :partial => 'action_menu' %>-->
<div style="clear: both;"></div> <div class="cl"></div>
<%= render :partial => 'action_menu' %>
<div style="clear: both;"></div>
<% if @issue.editable? %>
<div id="update">
<h3><%= l(:button_update) %></h3>
<%= render :partial => 'edit' %>
</div>
<% end %>
<% other_formats_links do |f| %> <% other_formats_links do |f| %>
<%= f.link_to 'Atom', :url => {:key => User.current.rss_key} %> <%= f.link_to 'Atom', :url => {:key => User.current.rss_key} %>
<%= f.link_to 'PDF' %> <%= f.link_to 'PDF' %>
<% end %> <% end %>
<% content_for :sidebar do %> <% content_for :sidebar do %>
<%= render :partial => 'issues/sidebar' %> <%= render :partial => 'issues/sidebar' %>
<br>
<% if User.current.allowed_to?(:add_issue_watchers, @project) || <% if User.current.allowed_to?(:add_issue_watchers, @project) ||
(@issue.watchers.present? && User.current.allowed_to?(:view_issue_watchers, @project)) %> (@issue.watchers.present? && User.current.allowed_to?(:view_issue_watchers, @project)) %>
<div id="watchers"> <div id="watchers">
<%= render :partial => 'watchers/watchers', :locals => {:watched => @issue} %> <%= render :partial => 'watchers/watchers', :locals => {:watched => @issue} %>
</div> </div>
<% end %> <% end %>
<% end %> <% end %>
<% content_for :header_tags do %> <% content_for :header_tags do %>

@ -1,5 +1,5 @@
$('#all_attributes').html('<%= escape_javascript(render :partial => 'form') %>'); $('#all_attributes').html('<%= escape_javascript(render :partial => 'form') %>');
$(.splitcontent).style("display", "block") //$(.splitcontent).style("display", "block")
<% if User.current.allowed_to?(:log_time, @issue.project) %> <% if User.current.allowed_to?(:log_time, @issue.project) %>
$('#log_time').show(); $('#log_time').show();
<% else %> <% else %>

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

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

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

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

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

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

@ -0,0 +1,52 @@
<% attaments_num = @project.attachments.count+Attachment.where(["`container_type` = 'Version' and `container_id` in (?)",@project.versions.map{ |v| v.id}]).all.count %>
<div class="subNav">
<%= link_to l(:label_activity), {:controller => 'projects', :action => 'show', :id => @project.id}, :class => "f14 c_blue02" %>
<% unless ForgeActivity.where("project_id = ?", @project.id).count == 0 %>
<a class="subnav_num">(<%= ForgeActivity.where("project_id = ?", @project.id).count %>)</a>
<% end %>
</div>
<% unless @project.enabled_modules.where("name = 'issue_tracking'").empty? %>
<div class="subNav">
<%= link_to l(:label_issue_tracking), project_issues_path(@project), :class => "f14 c_blue02" %>
<% unless @project.issues.count == 0 %>
<a class="subnav_num">(<%= @project.issues.count %>)</a>
<% end %>
<% if User.current.member_of?(@project) %>
<%= link_to "+"+l(:label_release_issue), new_project_issue_path(@project) , :class => "subnav_green" %>
<% end %>
</div>
<% end %>
<% unless @project.enabled_modules.where("name = 'boards'").empty? %>
<div class="subNav">
<%= link_to l(:project_module_boards), project_boards_path(@project), :class => "f14 c_blue02" %>
<% unless @project.boards.first.topics.count == 0 %>
<a class="subnav_num">(<%= @project.boards.first.topics.count %>)</a>
<% end %>
<% if User.current.member_of?(@project) %>
<%= link_to "+"+l(:project_module_boards_post), project_boards_path(@project, :flag => true), :layout => 'base_projects', :class => "subnav_green ml105" %>
<% end %>
</div>
<% end%>
<% unless @project.enabled_modules.where("name = 'files'").empty? %>
<div class="subNav">
<%= link_to l(:project_module_files), project_files_path(@project), :class => "f14 c_blue02" %>
<% unless attaments_num == 0 %>
<a class="subnav_num">(<%= attaments_num %>)</a>
<% end %>
<% if User.current.member_of?(@project) %>
<%= link_to "+"+l(:label_upload_files), project_files_path(@project,:flag => true), :class => "subnav_green ml95" %>
<% end %>
</div>
<% end%>
<% unless @project.enabled_modules.where("name = 'repository'").empty? || @project.repositories.count == 0 %>
<div class="subNav">
<%= link_to l(:project_module_repository), {:controller => 'repositories', :action => 'show', :id => @project.id}, :class => "f14 c_blue02" %>
<a class="subnav_num">(<%= @project.repositories.count %>)</a>
</div>
<% end %><!--meny end -->
<!-- more -->
<div class="subNav subNav_jiantou" onclick="expand_tools_expand();" id="expand_tools_expand"><%= l(:label_project_more) %></div>
<ul class="navContent">
<%= render 'projects/tools_expand' %>
</ul>

@ -1,11 +1,4 @@
<style type="text/css"> <style type="text/css">
#scrollsidebar{ font-size:12px; font-family:"微软雅黑","宋体"; line-height:1.9; background:#F6F7F8; font-style:normal;}
#scrollsidebar div,html,img,ul,li,p,body,h1,h2,h3,h4,p,a,table,tr,td,fieldset,input,span,ol{ }
#scrollsidebar div,img,tr,td,table{ border:0;}
#scrollsidebar ol,ul,li{ list-style-type:none}
#scrollsidebar .cl{ clear:both; overflow:hidden; }
#scrollsidebar a{ text-decoration:none;}
html{ overflow-x:hidden;} html{ overflow-x:hidden;}
.scrollsidebar{ position:fixed;bottom:1px; right:1px; background:none; } .scrollsidebar{ position:fixed;bottom:1px; right:1px; background:none; }
.side_content{width:154px; height:auto; overflow:hidden; float:left; } .side_content{width:154px; height:auto; overflow:hidden; float:left; }
@ -36,28 +29,9 @@
.msgserver a {color:#15bccf; } .msgserver a {color:#15bccf; }
.msgserver a:hover { text-decoration:underline; } .msgserver a:hover { text-decoration:underline; }
</style> </style>
<script>
/* =================================================
//
// jQuery Fixed Plugins 1.3.1
// author :
// Url:
// Data : 2012-03-30
//
// ???? : float --> ????[left or right]
// minStatue --> ??С???????show_btn
// skin --> ???????
// durationTime --> ??????
//???? :
$("#scrollsidebar2").fix({
float : 'right', //default.left or right
minStatue : true, //default.false or true
skin : 'green', //default.gray or yellow ??blue ??green ??orange ??white
durationTime : 1000 //
});
//
// =================================================*/
<head>
<script>
(function($){ (function($){
$.fn.fix = function(options){ $.fn.fix = function(options){
var defaults = { var defaults = {
@ -114,6 +88,9 @@ $(function(){
function f_submit() function f_submit()
{ {
var subject = $("#memo_subject").val();
var content = $("#memo_content_1").val();
$("#memo_subject").val(subject+""+ content.substr(0,18));
$("#new_memo").submit(); $("#new_memo").submit();
} }
@ -149,15 +126,18 @@ function cookieget(n)
return false; return false;
} }
</script> </script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title><%= l(:label_feedback) %></title>
</head> </head>
<body style="height:auto" > <body>
<!-- ?ú?? ???? --> <script type="text/javascript">
$(function() {
$("#scrollsidebar").fix({
float : 'right', //default.left or right
minStatue : cookieget('minStatue'),
skin : 'green', //default.gray or blue
durationTime : 600
});
});
</script>
<div class="scrollsidebar" id="scrollsidebar" style="float: right"> <div class="scrollsidebar" id="scrollsidebar" style="float: right">
<div class="side_content"> <div class="side_content">
<div class="side_list"> <div class="side_list">
@ -166,8 +146,8 @@ function cookieget(n)
<div class="custom_service"> <div class="custom_service">
<% get_memo %> <% get_memo %>
<%= form_for(@new_memo, :url => create_feedback_forum_path(@public_forum)) do |f| %> <%= form_for(@new_memo, :url => create_feedback_forum_path(@public_forum)) do |f| %>
<%= f.text_area :subject, :class => "opnionText", :placeholder => l(:label_feedback_tips) %> <%= f.hidden_field :subject,:required => true , :value => l(:label_feedback_value) %>
<%= f.hidden_field :content,:id => 'hidden', :required => true , :value => l(:label_feedback_value) %> <%= f.text_area :content,:class => "opnionText",:id=>"memo_content_1" ,:placeholder => l(:label_feedback_tips) %>
<%#= f.submit :value => l(:label_memo_create), :class => "opnionButton", :id => "button1" %> <%#= f.submit :value => l(:label_memo_create), :class => "opnionButton", :id => "button1" %>
<a href="javascript:void(0);" class="opnionButton" style=" color:#fff;" id="" onclick="f_submit();"><%= l(:label_submit)%></a> <a href="javascript:void(0);" class="opnionButton" style=" color:#fff;" id="" onclick="f_submit();"><%= l(:label_submit)%></a>
<% end %> <% end %>
@ -181,17 +161,4 @@ function cookieget(n)
</div> </div>
<div class="show_btn"><span><%= l(:label_submit)%></span></div> <div class="show_btn"><span><%= l(:label_submit)%></span></div>
</div> </div>
<!-- ?ú?? ?á?? -->
<script type="text/javascript">
$(function() {
$("#scrollsidebar").fix({
float : 'right', //default.left or right
minStatue : cookieget('minStatue'),
skin : 'green', //default.gray or blue
durationTime : 600
});
});
</script>
</body> </body>
</html>

@ -0,0 +1,29 @@
<% attaments_num = @project.attachments.count+Attachment.where(["`container_type` = 'Version' and `container_id` in (?)",@project.versions.map{ |v| v.id}]).all.count %>
<div class="subNav">
<%= link_to l(:label_activity), {:controller => 'projects', :action => 'show', :id => @project.id}, :class => "f14 c_blue02" %>
<% unless ForgeActivity.where("project_id = ?", @project.id).count == 0 %>
<a class="subnav_num">(<%= ForgeActivity.where("project_id = ?", @project.id).count %>)</a>
<% end %>
</div>
<% unless @project.enabled_modules.where("name = 'boards'").empty? %>
<div class="subNav">
<%= link_to l(:project_module_boards), project_boards_path(@project), :class => "f14 c_blue02" %>
<% unless @project.boards.first.topics.count == 0 %>
<a class="subnav_num">(<%= @project.boards.first.topics.count %>)</a>
<% end %>
<% if User.current.member_of?(@project) %>
<%= link_to "+"+l(:project_module_boards_post), project_boards_path(@project, :flag => true), :layout => 'base_projects', :class => "subnav_green ml105" %>
<% end %>
</div>
<% end%>
<% unless @project.enabled_modules.where("name = 'files'").empty? %>
<div class="subNav">
<%= link_to l(:project_module_files), project_files_path(@project), :class => "f14 c_blue02" %>
<% unless attaments_num == 0 %>
<a class="subnav_num">(<%= attaments_num %>)</a>
<% end %>
<% if User.current.member_of?(@project) %>
<%= link_to "+"+l(:label_upload_files), project_files_path(@project,:flag => true), :class => "subnav_green ml95" %>
<% end %>
</div>
<% end %>

@ -0,0 +1,40 @@
<% attaments_num = @project.attachments.count+Attachment.where(["`container_type` = 'Version' and `container_id` in (?)",@project.versions.map{ |v| v.id}]).all.count %>
<div class="subNav">
<%= link_to l(:label_activity), {:controller => 'projects', :action => 'show', :id => @project.id}, :class => "f14 c_blue02" %>
<% unless ForgeActivity.where("project_id = ?", @project.id).count == 0 %>
<a class="subnav_num">(<%= ForgeActivity.where("project_id = ?", @project.id).count %>)</a>
<% end %>
</div>
<% unless @project.enabled_modules.where("name = 'issue_tracking'").empty? %>
<div class="subNav">
<%= link_to l(:label_issue_tracking), project_issues_path(@project), :class => "f14 c_blue02" %>
<% unless @project.issues.count == 0 %>
<a class="subnav_num">(<%= @project.issues.count %>)</a>
<% end %>
<% if User.current.member_of?(@project) %>
<%= link_to "+"+l(:label_release_issue), new_project_issue_path(@project) , :class => "subnav_green" %>
<% end %>
</div>
<% end %>
<% unless @project.enabled_modules.where("name = 'boards'").empty? %>
<div class="subNav">
<%= link_to l(:project_module_boards), project_boards_path(@project), :class => "f14 c_blue02" %>
<% unless @project.boards.first.topics.count == 0 %>
<a class="subnav_num">(<%= @project.boards.first.topics.count %>)</a>
<% end %>
<% if User.current.member_of?(@project) %>
<%= link_to "+"+l(:project_module_boards_post), project_boards_path(@project, :flag => true), :layout => 'base_projects', :class => "subnav_green ml105" %>
<% end %>
</div>
<% end%>
<% unless @project.enabled_modules.where("name = 'files'").empty? %>
<div class="subNav">
<%= link_to l(:project_module_files), project_files_path(@project), :class => "f14 c_blue02" %>
<% unless attaments_num == 0 %>
<a class="subnav_num">(<%= attaments_num %>)</a>
<% end %>
<% if User.current.member_of?(@project) %>
<%= link_to "+"+l(:label_upload_files), project_files_path(@project,:flag => true), :class => "subnav_green ml95" %>
<% end %>
</div>
<% end%>

@ -8,9 +8,8 @@
<%= join_in_project_link(@project, User.current) %> <%= join_in_project_link(@project, User.current) %>
<% end %> <% end %>
<!--退出项目--> <!--退出项目-->
<% if ((User.current.member_of? @project) && <% if User.current.admin? || User.current.allowed_to?({:controller => 'projects', :action => 'settings'}, @project) %>
User.current.login? && <%= link_to "<span class='pr_setting'></span>#{l(:button_configure)}".html_safe, settings_project_path(@project), :class => "pr_join_a" %>
Member.where(:user_id => User.current.id, :project_id=>@project.id).first.roles.first.to_s != "Manager") %> <%= link_to "<span class='#{typeclass}'></span>#{text}".html_safe,"javascript:void(0)" ,:onClick => "show_window();", :class => "pr_join_a",:id => "setting_project_type"%>
<%= exit_project_link(@project) %>
<% end %> <% end %>
</div> </div>

@ -13,8 +13,8 @@
<div class="custom_service"> <div class="custom_service">
<% get_memo %> <% get_memo %>
<%= form_for(@new_memo, :url => create_feedback_forum_path(@public_forum)) do |f| %> <%= form_for(@new_memo, :url => create_feedback_forum_path(@public_forum)) do |f| %>
<%= f.text_area :subject, :class => "opnionText", :placeholder => l(:label_feedback_tips) %> <%= f.hidden_field :subject,:required => true , :value => l(:label_feedback_value) %>
<%= f.hidden_field :content, :required => true , :value => l(:label_feedback_value) %> <%= f.text_area :content,:class => "opnionText" , :placeholder => l(:label_feedback_tips) %>
<a href="javascript:void(0);" class="opnionButton" style=" color:#fff;" id="" onclick="f_submit();"> <a href="javascript:void(0);" class="opnionButton" style=" color:#fff;" id="" onclick="f_submit();">
<%= l(:label_submit)%> <%= l(:label_submit)%>
</a> </a>

@ -18,8 +18,8 @@
<% if User.current.logged? -%> <% if User.current.logged? -%>
<li id="current_user_li"> <li id="current_user_li">
<%= link_to_user_header(User.current,false,:class =>'parent')%> <%= link_to "#{User.current.login}<span class='pic_triangle'></span>".html_safe, {:controller=> 'users', :action => 'show', id: User.current.id, host: Setting.user_domain}, :class => "uses_name"%>
<ul id="user_sub_menu"> <ul id="user_sub_menu" style="right: 0px;display: none;">
<% unless User.current.projects.empty? %> <% unless User.current.projects.empty? %>
<li id="my_projects_li"> <li id="my_projects_li">
<%= link_to l(:label_my_projects), {:controller => 'users', :action => 'user_projects', id: User.current.id, host: Setting.project_domain}, :class => "parent" %> <%= link_to l(:label_my_projects), {:controller => 'users', :action => 'user_projects', id: User.current.id, host: Setting.project_domain}, :class => "parent" %>

@ -132,12 +132,12 @@
</div> </div>
<div class="subNav"> <div class="subNav">
<%= link_to l(:label_course_board), course_boards_path(@course), :class => "f14 c_blue02" %> <%= link_to l(:label_course_board), course_boards_path(@course), :class => "f14 c_blue02" %>
<%= link_to "(#{@course.boards[0].topics.count})", course_boards_path(@course), :class => "subnav_num c_orange" %> <%= link_to "(#{@course.boards.first ? @course.boards.first.topics.count : 0})", course_boards_path(@course), :class => "subnav_num c_orange" %>
<%= link_to( "+#{l(:label_message_new)}", new_board_message_path(@course.boards[0]), :class => 'subnav_green ml95 c_white') if User.current.member_of_course?(@course) %> <%= link_to( "+#{l(:label_message_new)}", new_board_message_path(@course.boards.first), :class => 'subnav_green ml95 c_white') if User.current.member_of_course?(@course) && @course.boards.first %>
</div> </div>
<div class="subNav"> <div class="subNav">
<%= link_to l(:label_course_feedback), course_feedback_path(@course), :class => "f14 c_blue02" %> <%= link_to l(:label_course_feedback), course_feedback_path(@course), :class => "f14 c_blue02" %>
<%= link_to "(#{course_feedback_count})", course_feedback_path(@course), :class => "subnav_num c_orange" %> <%= link_to "(#{course_feedback_count})", course_feedback_path(@course), :class => "subnav_num c_orange", :id => "course_jour_count"%>
</div> </div>
<div class="subNav"> <div class="subNav">
<%= link_to l(:label_poll), poll_index_path(:polls_type => "Course", :polls_group_id => @course.id), :class => " f14 c_blue02"%> <%= link_to l(:label_poll), poll_index_path(:polls_type => "Course", :polls_group_id => @course.id), :class => " f14 c_blue02"%>

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

Loading…
Cancel
Save