Merge branch 'szzh' into guange_dev

Conflicts:
	Gemfile
	config/application.rb
memcached_alan
sw 10 years ago
commit de192761b8

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

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

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

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

@ -145,10 +145,14 @@ class FilesController < ApplicationController
ids += version.id.to_s
end
end
resultSet = Attachment.where("((attachments.container_type = 'Project' And attachments.container_id = '#{project.id}') OR (container_type = 'Version' AND container_id IN (#{ids}))) AND filename LIKE :like ", like: "%#{keywords}%").
reorder(sort)
#resultSet = Attachment.find_by_sql("SELECT `attachments`.* FROM `attachments` LEFT OUTER JOIN `homework_attaches` ON `attachments`.container_type = 'HomeworkAttach' AND `attachments`.container_id = `homework_attaches`.id LEFT OUTER JOIN `homework_for_courses` ON `homework_attaches`.bid_id = `homework_for_courses`.bid_id LEFT OUTER JOIN `homework_for_courses` AS H_C ON `attachments`.container_type = 'Bid' AND `attachments`.container_id = H_C.bid_id WHERE (`homework_for_courses`.course_id = 117 OR H_C.course_id = 117 OR (`attachments`.container_type = 'Course' AND `attachments`.container_id = 117)) AND `attachments`.filename LIKE '%#{keywords}%'").reorder("created_on DESC")
end
if ids.blank?
resultSet = Attachment.where("attachments.container_type = 'Project' And attachments.container_id = '#{project.id}' AND filename LIKE :like ", like: "%#{keywords}%").
reorder(sort)
else
resultSet = Attachment.where("((attachments.container_type = 'Project' And attachments.container_id = '#{project.id}') OR (container_type = 'Version' AND container_id IN (#{ids}))) AND filename LIKE :like ", like: "%#{keywords}%").
reorder(sort)
end
end
def find_public_attache keywords,sort = ""
# StoresController#search 将每条文件都查出来,再次进行判断过滤。---> resultSet.to_a.map

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

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

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

@ -27,15 +27,7 @@ class ProjectsController < ApplicationController
menu_item :feedback, :only => :feedback
menu_item :share, :only => :share
before_filter :find_project, :except => [ :index, :search,:list, :new, :create, :copy, :statistics, :new_join,
:course, :enterprise_course, :course_enterprise,:view_homework_attaches]
before_filter :authorize, :only => [:show, :settings, :edit, :sort_project_members, :update, :modules, :close,
:reopen,:view_homework_attaches,:course]
before_filter :find_project, :except => [ :index, :search,:list, :new, :create, :copy, :statistics, :new_join, :course, :enterprise_course, :course_enterprise,:view_homework_attaches,:join_project]
# before_filter :authorize, :except => [:new_join, :new_homework, :homework, :statistics, :search, :watcherlist, :index, :list, :new, :create, :copy, :archive, :unarchive, :destroy, :member, :focus, :file,
# :statistics, :feedback, :course, :enterprise_course, :course_enterprise, :project_respond, :share,
# :show_projects_score, :issue_score_index, :news_score_index, :file_score_index, :code_submit_score_index, :projects_topic_score_index]
#此条勿删 课程相关权限 ,:new_homework,:homework,:feedback,,:member
before_filter :authorize, :only => [:show, :settings, :edit, :sort_project_members, :update, :modules, :close, :reopen,:view_homework_attaches,:course]
before_filter :authorize_global, :only => [:new, :create,:view_homework_attaches]
before_filter :require_admin, :only => [ :copy, :archive, :unarchive, :destroy, :calendar]
@ -181,6 +173,7 @@ class ProjectsController < ApplicationController
@project.safe_attributes = params[:project]
@project.organization_id = params[:organization_id]
@project.user_id = User.current.id
@project.project_new_type = 1
if validate_parent_id && @project.save
@project.set_allowed_parent!(params[:project]['parent_id']) if params[:project].has_key?('parent_id')
# Add current user as a project member if he is not admin
@ -331,6 +324,28 @@ class ProjectsController < ApplicationController
@member ||= @project.members.new
@trackers = Tracker.sorted.all
@wiki ||= @project.wiki
@select_tab = params[:tab]
# 处理从新建版本库返回来的错误信息
if !params[:repository_error_message].to_s.blank?
html = ""
errors = params[:repository_error_message].flatten
errors.each do |error|
# 版本库路径为空的错误信息不予提示
if(error!=l(:label_repository_path_not_null))
html << error << ";"
end
end
if params[:repository] == "pswd_is_null"
html << l(:label_password_not_null)
end
flash[:error] = html if !html.to_s.blank?
end
scm = params[:repository_scm] || (Redmine::Scm::Base.all & Setting.enabled_scm).first
@repository = Repository.factory(scm)
@repository.is_default = @project.repository.nil?
@repository.project = @project
end
def send_mail_to_member
@ -379,7 +394,7 @@ class ProjectsController < ApplicationController
# include CoursesHelper
def member
## 有角色参数的才是课程,没有的就是项目
@render_file = 'member_list'
@render_file = 'project_member_list'
# 判断是否课程
if @project.project_type == Project::ProjectType_course
@teachers= searchTeacherAndAssistant(@project)
@ -455,22 +470,10 @@ class ProjectsController < ApplicationController
def update
@project.safe_attributes = params[:project]
@project.organization_id = params[:organization_id]
#@project.dts_test = params[:project][:dts_test]
params[:project][:is_public] ? @project.is_public = 1 : @project.is_public = 0
params[:project][:hidden_repo] ? @project.hidden_repo = 1 : @project.hidden_repo = 0
if validate_parent_id && @project.save
@course = Course.find_by_extra(@project.identifier)
unless @course.nil?
@course.password = params[:project][:course][:password]
# added by bai
@course.term = params[:term]
@course.time = params[:time]
@course.setup_time = params[:setup_time]
@course.endup_time = params[:endup_time]
@course.class_period = params[:class_period]
# end
@course.save
end
@project.set_allowed_parent!(params[:project]['parent_id']) if params[:project].has_key?('parent_id')
if params[:project][:is_public] == '0'
project_status = ProjectStatus.find_by_project_id(@project.id)
project_status.destroy if project_status
@ -618,6 +621,17 @@ class ProjectsController < ApplicationController
end
end
#朋友圈、科研组、开发组之间的切换
def change_project_type
@project.project_new_type = params[:project_type]
if @project.save
message = @project.project_new_type
else
message = "0"
end
render :json => message
end
private
def memberAccess

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

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

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

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

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

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

@ -691,9 +691,11 @@ module CoursesHelper
#end
#poll_count
#Poll.where(polls_group_id: @course_ids, polls_type: Course, polls_status: 2||3).where("published_at>?",date_from).each do |poll|
# activities[poll.polls_group_id]+=1
#end
# 动态目前只统计发布的问卷,关闭的问卷不在动态内显示
# Poll.where(polls_group_id: @course_ids, polls_type: Course, polls_status: 2||3).where("published_at>?",date_from).each do |poll|
Poll.where(polls_group_id: @course_ids, polls_type: Course, polls_status: 2||3).where("published_at>?",date_from).each do |poll|
activities[poll.polls_group_id]+=1
end
#end

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

File diff suppressed because it is too large Load Diff

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

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

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

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

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

File diff suppressed because it is too large Load Diff

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

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

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

@ -0,0 +1,67 @@
<span id="attachments_fields" xmlns="http://www.w3.org/1999/html">
<% if defined?(container) && container && container.saved_attachments %>
<% if isReply %>
<% container.saved_attachments.each_with_index do |attachment, i| %>
<span id="attachments_p<%= i %>" class="sub_btn">
<%= text_field_tag("attachments[p#{i}][filename]", attachment.filename, :class => 'filename readonly', :readonly=>'readonly')%>
<%= text_field_tag("attachments[p#{i}][description]", attachment.description, :maxlength => 255, :placeholder => l(:label_optional_description), :class => 'description', :style=>"display: inline-block;") +
link_to('&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 %>
<% images = attachments.select(&:thumbnailable?) %>
<% if images.any? %>
<div class="thumbnails">
<div class="pro_pic mb10" width="100" height="73">
<% images.each do |attachment| %>
<div><%= thumbnail_tag(attachment) %></div>
<% end %>

@ -0,0 +1,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 "><%= thumbnail_issue_tag(attachment) %></div>
<% end %>
<% end %>
<% end %>
</div>
</div>

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

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

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

@ -0,0 +1,28 @@
<% selected_tab = params[:tab] ? params[:tab].to_s : tabs.first[:name] %>
<div class="hwork_new">
<div class="hwork_tb_">
<ul>
<% tabs.each do |tab| -%>
<li><%= link_to l(tab[:label]), { :tab => tab[:name] },
:id => "tab-#{tab[:name]}",
:class => (tab[:name] != selected_tab ? 'hwork_normaltab' : 'hwork_hovertab'),
:onclick => "showTab('#{tab[:name]}'); this.blur(); return false;" %></li>
<% end -%>
</ul>
<!-- <div class="tabs-buttons" style="display:none;">
<button class="tab-left" onclick="moveTabLeft(this);"></button>
<button class="tab-right" onclick="moveTabRight(this);"></button>
</div> -->
</div>
</div>
<script>
$(document).ready(displayTabsButtons);
$(window).resize(displayTabsButtons);
</script>
<% tabs.each do |tab| -%>
<%= content_tag('div', render(:partial => tab[:partial], :locals => {:tab => tab} ),
:id => "tab-content-#{tab[:name]}",
:style => (tab[:name] != selected_tab ? 'display:none' : nil),
:class => 'hwork_normaltab') %>
<% end -%>

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

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

@ -27,15 +27,15 @@
/***弹框***/
#popbox_tscore{width:480px;position:absolute;z-index:100;left:50%;top:50%;margin:-215px 0 0 -300px; background:#fff; -moz-border-radius:5px; -webkit-border-radius:5px; border-radius:5px; box-shadow:0px 0px 8px #194a81; overflow:auto;}
.alert .close02{width:26px;height:26px;overflow:hidden;position:absolute;top:-10px;right:-490px;background:url(images/close.png) no-repeat;cursor:pointer;}
.tscore_con h2{ display:block; background:#eaeaea; font-size:14px; color:#343333; height:31px; width: auto; margin-top:25px; padding-left:20px; padding-top:5px;}
/*#popbox_tscore{width:480px;position:absolute;z-index:100;left:50%;top:50%;margin:-215px 0 0 -300px; background:#fff; -moz-border-radius:5px; -webkit-border-radius:5px; border-radius:5px; box-shadow:0px 0px 8px #194a81; overflow:auto;}*/
/*.alert .close02{width:26px;height:26px;overflow:hidden;position:absolute;top:-10px;right:-490px;background:url(images/close.png) no-repeat;cursor:pointer;}*/
.tscore_con h2{ display:block; background:#eaeaea; font-size:14px; color:#343333; height:31px; width: auto; text-align: center; padding-top:5px;}
.tscore_box{ width:350px; margin:15px auto;}
.tscore_box li{ height:25px;}
</style>
<div class="tscore_con">
<div class="tscore_con" id="user_score">
<h2><%= @member_score.user.name %> 历次作业积分</h2>
<ul class="tscore_box">
<li ><span class="c_blue02 w280">作业名称</span><span class="c_blue02 w70">得分</span></li>

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

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

@ -1,3 +1,13 @@
//$('#ajax-modal').html('<%#= escape_javascript(render :partial => 'courses/show_member_score', :locals => {:member => @member_score}) %>');
//showModal('ajax-modal', '400px');
//$('#ajax-modal').addClass('new-watcher');
$('#ajax-modal').html('<%= escape_javascript(render :partial => 'courses/show_member_score', :locals => {:member => @member_score}) %>');
showModal('ajax-modal', '400px');
$('#ajax-modal').addClass('new-watcher');
//$('#ajax-modal').css('height','569px');
$('#ajax-modal').siblings().remove();
$('#ajax-modal').before("<span style='float: right;cursor:pointer;padding-left: 513px;'>" +
"<a href='javascript:void(0)' onclick='hidden_homework_score_form();'><img src='/images/bid/close.png' width='26px' height='26px' /></a></span>");
//$('#ajax-modal').parent().removeClass();
$('#ajax-modal').parent().css("top","30%").css("left","40%").css("position","fixed");
$('#ajax-modal').parent().addClass("new-watcher");

@ -45,8 +45,8 @@
</div>
<div class="cl"></div>
<div class="tag_h">
<%= render :partial => 'tags/tag_new', :locals => {:obj => file, :object_flag => "10"} %>
<%= render :partial => 'tags/tag_add', :locals => {:obj => file, :object_flag => "10"} %>
<%= render :partial => 'tags/tag_new', :locals => {:obj => file, :object_flag => "6"} %>
<%= render :partial => 'tags/tag_add', :locals => {:obj => file, :object_flag => "6"} %>
</div>
<div class="cl"></div>
</div><!---re_con_box end-->

@ -1,8 +1,3 @@
<div class="project_r_h">
<h2 class="project_h2"><%= l(:lable_file_sharingarea) %></h2>
</div>
<!--<%#= stylesheet_link_tag 'resource', :media => 'all' %> -->
<script>
function show_upload()
@ -11,7 +6,7 @@
showModal('ajax-modal', '513px');
$('#ajax-modal').siblings().remove();
$('#ajax-modal').before("<span style='float: right;cursor:pointer;padding-left: 513px;'><a href='javascript:void(0)' onclick='closeModal()'><img src='/images/bid/close.png' width='26px' height='26px' /></a></span>")
$('#ajax-modal').parent().css("top","").css("left","");
$('#ajax-modal').parent().css("top","40%").css("left","30%");
$('#ajax-modal').parent().addClass("popbox_polls");
}
@ -46,7 +41,7 @@
<div class="re_top">
<%= form_tag( search_project_project_files_path(@project), method: 'get',:class => "re_search f_l",:remote=>true) do %>
<%= text_field_tag 'name', params[:name], name: "name", :class => 're_schbox',:style=>"padding: 0px"%>
<%= submit_tag "内搜索", :class => "re_schbtn b_lblue",:name => "incourse",:id => "incourse", :onmouseover => "presscss('incourse')",:onmouseout =>"buttoncss()" %>
<%= submit_tag "内搜索", :class => "re_schbtn b_lblue",:name => "incourse",:id => "incourse", :onmouseover => "presscss('incourse')",:onmouseout =>"buttoncss()" %>
<%= submit_tag "全站搜索", :class => "re_schbtn b_lblue",:name => "insite",:id => "insite",:onmouseover => "presscss('insite')",:onmouseout =>"buttoncss()" %>
<% end %>
<% manage_allowed = User.current.allowed_to?(:manage_files, @project) %>

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

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

@ -7,5 +7,5 @@
showModal('ajax-modal', '513px');
$('#ajax-modal').siblings().remove();
$('#ajax-modal').before("<span style='float: right;cursor:pointer;padding-left: 513px;'><a href='javascript:void(0)' onclick='closeModal()'><img src='/images/bid/close.png' width='26px' height='26px' /></a></span>");
$('#ajax-modal').parent().css("top","").css("left","");
$('#ajax-modal').parent().css("top","30%").css("left","35%");
$('#ajax-modal').parent().addClass("popbox_polls");

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

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

@ -1,18 +1,10 @@
<div class="contextual">
<!--added by huang-->
<% if (@issue.author == User.current) || (User.current.admin?) %>
<!--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? %>
<!--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) %>
<%= 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) %>
<% 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 %>
<%= 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 %>
<%= 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>
<%= 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? %>
<% end %>

@ -1,119 +1,168 @@
<%= labelled_fields_for :issue, @issue do |f| %>
<fieldset class="collapsible collapsed" style="padding-left: 50px;">
<legend onclick="toggleFieldset(this);" style="font-size:12px;"><strong><%= l(:label_change_properties) %></strong></legend>
<div class="splitcontent" style="display: block;">
<div class="splitcontentleft">
<% if @issue.safe_attribute?('status_id') && @allowed_statuses.present? %>
<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>
<% else %>
<p><label><%= l(:field_status) %></label> <%= h(@issue.status.name) %></p>
<% end %>
<% if @issue.safe_attribute? 'priority_id' %>
<p><%= f.select :priority_id, (@priorities.collect {|p| [p.name, p.id]}), {:required => true}, :disabled => !@issue.leaf? %></p>
<% end %>
<% if @issue.safe_attribute? 'assigned_to_id' %>
<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>
<% end %>
<% if @issue.safe_attribute?('fixed_version_id') && @issue.assignable_versions.any? %>
<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') %>
<%= link_to(image_tag('add.png', :style => 'vertical-align: middle;'),
new_project_version_path(@issue.project),
:remote => true,
:method => 'get',
:title => l(:label_version_new),
:tabindex => 200) if User.current.allowed_to?(:manage_versions, @issue.project) %>
</p>
<% end %>
</div>
<div class="splitcontentright">
<% if @issue.safe_attribute? 'start_date' %>
<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>
<% end %>
<% if @issue.safe_attribute? 'due_date' %>
<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>
<% end %>
<% if @issue.safe_attribute? 'estimated_hours' %>
<p><%= f.text_field :estimated_hours, :size => 3, :disabled => !@issue.leaf?, :required => @issue.required_attribute?('estimated_hours') %> <%= l(:field_hours) %></p>
<% end %>
<script type="text/javascript">
// window.onload=function(){
// var img=$("#issue_due_date").next("img");
// img.attr("onclick","SetMinValue();");
// }
function TimeClose(dateText, inst) {
if(inst.id=="issue_start_date"){
time=dateText;
}
}
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?('done_ratio') && @issue.leaf? && Issue.use_field_for_done_ratio? %>
<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>
<% end %>
</div>
</div>
</fieldset>
<% if @issue.safe_attribute? 'custom_field_values' %>
<%= render :partial => 'issues/form_custom_fields' %>
<% end %>
<div class="newpro_box">
<fieldset class="collapsible">
<legend onclick="toggleFieldset(this);"><strong><%= l(:label_change_properties) %></strong></legend>
<ul class="fl">
<li>
<label class="label"><span class="c_red f12">*</span><%= l(:field_status) %></label>
<% if @issue.safe_attribute?('status_id') && @allowed_statuses.present? %>
<%= f.select :status_id,
(@allowed_statuses.collect { |p| [p.name, p.id] }),
{:no_label => true},
# ajax 刷新
#:onchange => "updateIssueFrom('#{escape_javascript project_issue_form_path(@project, :id => @issue, :format => 'js')}')",
:class => "w150" %>
<% else %>
<%= h(@issue.status.name) %>
<% end %>
</li>
<div class="cl"></div>
<li>
<label class="label"><span class="c_red f12">*</span><%= l(:field_priority) %></label>
<% if @issue.safe_attribute? 'priority_id' %>
<%= f.select :priority_id,
(@priorities.collect { |p| [p.name, p.id] }),
{:required => true, :no_label => true}, :disabled => !@issue.leaf?,
:class => "w150" %>
<% end %>
</li>
<div class="cl"></div>
<li>
<li>
<label class="label"><%= l(:field_assigned_to) %></label>
<% if @issue.safe_attribute? 'assigned_to_id' %>
<%= f.select :assigned_to_id, principals_options_for_select(@issue.assignable_users, @issue.assigned_to),
{:required => @issue.required_attribute?('assigned_to_id'), :no_label => true},
:class => "w150" %>
<% end %>
</li>
<div class="cl"></div>
<li>
<% if @issue.safe_attribute?('fixed_version_id') && @issue.assignable_versions.any? %>
<label class="label"><%= l(:field_fixed_version) %></label>
<%= 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},
:class => "w150" %>
<%#= link_to(image_tag('add.png', :style => 'vertical-align: middle;'),
new_project_version_path(@issue.project),
:remote => true,
:method => 'get',
:title => l(:label_version_new),
:tabindex => 200) if User.current.allowed_to?(:manage_versions, @issue.project) %>
<%= link_to "", new_project_version_path(@issue.project), :class => "pic_add mt5 ml5 " %>
<!--<a href="javascript:viod(0)" class="pic_add mt5 ml5"></a>-->
<% end %>
</li>
<div class="cl"></div>
</ul>
<ul class="fl ml90">
<li>
<label class="label02"><%= l(:field_start_date) %></label>
<% if @issue.safe_attribute? 'start_date' %>
<%= f.text_field :start_date,
:size => 22,
:disabled => !@issue.leaf?,
:no_label => true,
:required => @issue.required_attribute?('start_date') %>
<%= calendar_for('issue_start_date', 'start_date') if @issue.leaf? %>
<% end %>
</li>
<div class="cl"></div>
<li>
<label class="label02"><%= l(:field_due_date) %></label>
<% if @issue.safe_attribute? 'due_date' %>
<%= f.text_field :due_date, :size => 22,
:disabled => !@issue.leaf?,
:no_label => true,
:required => @issue.required_attribute?('due_date') %>
<%= calendar_for('issue_due_date', 'start_date') if @issue.leaf? %>
<% end %>
</li>
<div class="cl"></div>
<li>
<label class="label02"><%= l(:field_estimated_hours) %></label>
<% if @issue.safe_attribute? 'estimated_hours' %>
<%= f.text_field :estimated_hours, :size => 22,
:disabled => !@issue.leaf?,
:no_label => true,
:required => @issue.required_attribute?('estimated_hours') %>
<span class="mt3 ml5"><%= l(:field_hours) %></span>
<% end %>
</li>
<div class="cl"></div>
<li><label class="label02">&nbsp;% 完成&nbsp;&nbsp;:&nbsp;</label>
<% if @issue.safe_attribute?('done_ratio') && @issue.leaf? && Issue.use_field_for_done_ratio? %>
<%= f.select :done_ratio, ((0..10).to_a.collect { |r| ["#{r*10} %", r*10] }),
{:required => @issue.required_attribute?('done_ratio'), :no_label => true},
:onchange => "PrecentChange(this.value)",
:class => "w150" %>
<% end %>
</li>
<div class="cl"></div>
</ul>
</fieldset>
</div><!--newpro_box end-->
<script type="text/javascript">
// window.onload=function(){
// var img=$("#issue_due_date").next("img");
// img.attr("onclick","SetMinValue();");
// }
function TimeClose(dateText, inst) {
if (inst.id == "issue_start_date") {
time = dateText;
}
}
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 %>

@ -1,51 +1,41 @@
<%= labelled_form_for @issue, :html => {:id => 'issue-form', :multipart => true} do |f| %>
<%= error_messages_for 'issue', 'time_entry' %>
<%= render :partial => 'conflict' if @conflict %>
<div class="box">
<!--编辑的整个属性-->
<% if @edit_allowed || !@allowed_statuses.empty? %>
<fieldset class="tabular"><legend><%= l(:label_change_properties) %></legend>
<div id="all_attributes">
<%= render :partial => 'form', :locals => {:f => f} %>
<div id="all_attributes" style="display:none;">
<%= render :partial => 'form', :locals => {:f => f} %>
<!--<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>
<% end %><!--end-->
<div class="ping_C mb10"></div>
<!--<fieldset><legend><%#= l(:field_notes) %></legend>-->
<!--回复框-->
<% if @journals.present? %>
<div id="history">
<%= render :partial => 'history', :locals => {:issue => @issue, :journals => @journals} %>
</div>
</fieldset>
<% end %>
<fieldset><legend><%= l(:field_notes) %></legend>
<%= f.text_area :notes, :cols => 60, :rows => 10, :class => 'wiki-edit', :no_label => true %>
<%= wikitoolbar_for 'issue_notes' %>
<% 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 %>
<%= call_hook(:view_issues_edit_notes_bottom, { :issue => @issue, :notes => @notes, :form => f }) %>
<fieldset><legend>回复</legend>
<%= f.text_area :notes, :style => "width:99%;", :rows => "5", :no_label => true %>
</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>
<p><%= render :partial => 'attachments/form', :locals => {:container => @issue} %></p>
</fieldset>
<%= call_hook(:view_issues_edit_notes_bottom, {:issue => @issue, :notes => @notes, :form => f}) %>
<!--</fieldset>-->
<div class="box tabular" >
<p id="watchers_form">
<label style="font-size: 15px;"><%= l(:label_issue_watchers) %></label>
<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>
<!--<fieldset><legend><%#= l(:label_attachment_plural) %></legend>-->
<!--<p style="padding-top: 5px;"><%#= render :partial => 'attachments/new_form', :locals => {:container => @issue} %>
<!--</fieldset>-->
<div class="cl"></div>
<%= f.hidden_field :lock_version %>
<%= hidden_field_tag 'last_journal_id', params[:last_journal_id] || @issue.last_journal_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' %>
<%= hidden_field_tag 'reference_user_id', params[:reference_user_id] %>
<% end %>
<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| %>
<%= 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' %>
<p style="float:right; margin-right:1em;">
<%= 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>
</p>
<% end %>
<% end %>
</li>
<div class="cl"></div>
<% if @issue.safe_attribute? 'project_id' %>
<p><%= 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')}')" %></p>
<% end %>
<li>
<% if @issue.safe_attribute? 'description' %>
<label class="label">&nbsp;描述&nbsp;&nbsp;:&nbsp;</label>
<%= 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' %>
<p><%= f.select :tracker_id, @issue.project.trackers.collect {|t| [t.name, t.id]}, {:required => true},
:onchange => "updateIssueFrom('#{escape_javascript project_issue_form_path(@project, :id => @issue, :format => 'js')}')" %></p>
<% end %>
<% if @issue.safe_attribute? 'subject' %>
<p><%= f.text_field :subject, :size => 80, :maxlength => 255, :required => true, :style => "font-size:small" %></p>
<!--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 %>
<% end %>
<% if @issue.safe_attribute? 'description' %>
<p>
<%= f.label_for_field :description, :required => @issue.required_attribute?('description') %>
<%= 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,
:cols => 60,
:rows => (@issue.description.blank? ? 10 : [[10, @issue.description.length / 50].max, 100].min),
:accesskey => accesskey(:edit),
:class => 'wiki-edit',
:style => "font-size:small;width:520px;",
:no_label => true %>
<% end %>
</p>
<%= wikitoolbar_for 'issue_description' %>
<% end %>
<div id="attributes" class="attributes">
<%= render :partial => 'issues/attributes' %>
</div>
<%= call_hook(:view_issues_form_details_bottom, { :issue => @issue, :form => f }) %>
<% end %>
<%= wikitoolbar_for 'issue_description' %>
<% end %>
</li>
<div class="cl"></div>
</ul>
</div>
<li>
<% if @copy_from && @copy_from.attachments.any? %>
<p>
<!-- 去除附件复制功能 -->
<!-- <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 %>
</li>
<div class="cl"></div>
<li>
<br>
<label class="label"><%= l(:label_attachment_plural) %></label>
<%= render :partial => 'attachments/form', :locals => {:container => @issue} %>
</li>
<div class="cl"></div>
<div id="attributes">
<%= render :partial => 'issues/attributes' %>
</div>
<div class="cl"></div>
<!--<div class="newpro_box02 ">-->
<!--<label class="label"> <%#= l(:label_issue_watchers) %></label>-->
<!--<input id="" name="" size="22" class="fl mb10 h26" type="text" placeholder="搜索添加跟踪者">-->
<!--<span class="search_for_watchers">-->
<%#= link_to "",
# {:controller => 'watchers', :action => 'new', :project_id => @issue.project},
# :remote => true,
# :method => 'get',
:class => "pic_sch mt5 ml5" %>
<!--</span>-->
<%#= 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') -%>
<% for journal in journals %>
<% journals.reverse.each do |journal| %>
<!-- modified by bai -->
<div id="change-<%= journal.id %>" class="<%= journal.css_classes %>" style=" word-wrap: break-word; word-break: break-all">
<!-- end -->
<table width="660px" border="0" align="center">
<tr>
<td colspan="2" valign="top" width="50" ><%= image_tag(url_to_avatar(journal.user), :class => "avatar") %></td>
<td>
<table width="580px" border="0">
<tr>
<!-- add by huang -->
<td colspan="1" valign="top"> <%= authoring journal.created_on, journal.user, :label => :label_updated_time_by %> <div id="note-<%= journal.indice %>"></div></td>
<td><%= render_links(issue, journal, :reply_links => reply_links) unless journal.notes.blank? %></td>
<!--end-->
</tr>
<tr>
<td colspan="2" width="580px" >
<p class="font_description">
<% if journal.details.any? %>
<span class="details"> <% details_to_strings(journal.details).each do |string| %>
<%= string %>
<% end %> </span>
<% end %>
<%= render_notes(issue, journal, :reply_links => reply_links) unless journal.notes.blank? %>
</p></td>
</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 class="ping_C mb10">
<div class="ping_dispic"><a href="#" target="_blank"><%= image_tag(url_to_avatar(journal.user), :class => "ping_dispic",:width => 46,:height => 46) %></a></div>
<div class="ping_discon">
<div class="ping_distop">
<a href="#" target="_blank" class="c_blue fb fl mb10 "><%= journal.user %></a><span class="c_grey fr"><%= format_time journal.created_on %></span>
<div class="cl"></div>
<p>
<% if journal.details.any? %>
<% details_to_strings(journal.details).each do |string| %>
<p><%= string %></p>
<% end %>
<% end %>
</p>
</div>
<!--编辑、引用、回复按钮-->
<div class="ping_disfoot"><%= render_links_easy(issue, journal, :reply_links => reply_links) unless journal.notes.blank? %></div>
<!--回复内容、引用内容-->
<p><%= render_notes_issue(issue, journal, :reply_links => reply_links) unless journal.notes.blank? %></p>
<div class="cl"></div>
</div>
<div class="cl"></div>
</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 %>
<% 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">
<ul>
<% issue_list(issues) do |issue, level| -%>
<% issue_list(issues) do |issue, level| -%>
<% if @query.grouped? && (group = @query.group_by_column.value(issue)) != previous_group %>
<% reset_cycle %>
<% previous_group = group %>
<% end %>
<div style="">
<li id="issue-<%= issue.id %>" class="hascontextmenu-1 <%= issue.css_classes %> <%= level > 0 ? "idnt idnt-#{level}" : nil %>">
<% column_content = ( query.inline_columns.map {|column| "#{column_content_new(column, issue)}"}) %>
<% if issue.tracker_id == 1 %>
<%= image_tag("/images/task.png", :class => "img-tag-issues") %>
<% end %>
<% if issue.tracker_id == 2 %>
<%= image_tag("/images/feature.png", :class => "img-tag-issues") %>
<% end %>
<% if issue.tracker_id == 3 %>
<%= image_tag("/images/support.png", :class => "img-tag-issues") %>
<% end %>
<% if issue.tracker_id == 4 %>
<%= image_tag("/images/issues.png", :class => "img-tag-issues") %>
<% end %>
<!-- CONTENT LIST -->
<div class="problem_main">
<% column_content = ( query.inline_columns.map {|column| "#{column_content_new(column, issue)}"}) %>
<% unless issue.author.nil? || issue.author.name == "Anonymous" %>
<span class="issues_icon fl"></span>
<div class="problem_txt fl">
<%= link_to issue.author.name, user_path(issue.author), :class => "problem_name c_orange fl" %>
<span class="fl"><%= l(:label_post_on_issue) %>(<%= "#{raw column_content[2]}" %>)</span>
<div class="problem_tit_div fl">
<%=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" %>
</div>
<div class="cl"></div>
<p>
<% unless issue.assigned_to_id.nil? %>
<%= 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">
<% unless issue.author.nil? || issue.author.name == "Anonymous" %>
<ul class="list-group-item-meta" style="word-break: break-all;word-wrap: break-word;width: 100%;">
<!-- 在这里添加赞和踩-->
<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 class="cl"></div>
<% end %>
<div class="cl"></div>
</div>
<% end -%>
</ul>
</div>
<% end -%>
<ul class="wlist">
<%= pagination_links_full issue_pages, issue_count, :per_page_links => false, :remote => false, :flag => true %>
</ul>

@ -1,18 +1,70 @@
<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){
}
});
}
</script>
<div class="project_r_h">
<h2 class="project_h2"><%= l(:label_issue_tracking) %></h2>
</div>
<div class="problem_top">
<% unless @project.enabled_modules.where("name = 'issue_tracking'").empty? %>
<span>
<% if User.current.member_of?(@project) %>
<%= link_to l(:label_issue_new), {:controller => 'issues', :action => 'new', :copy_from => nil}, :param => :project_id, :caption => :label_issue_new,
:html => {:accesskey => Redmine::AccessKeys.key_for(:new_issue)}, :class => 'icon icon-add' %>
<% end %>
<%= link_to l(:label_query), '#', :class => 'icon icon-help',
:onclick => '$("#custom_query").slideToggle(400); ' if true || User.current.logged? %>
</span>
<%= form_tag({:controller => 'issues', :action => 'index', :project_id => @project}, :method => :get,:id=>"issue_query_form", :class => 'query_form') do %>
<%= hidden_field_tag 'set_filter', '1' %>
<div class="problem_search" >
<input class="problem_search_input fl" id="v_subject" type="text" name="v[subject]" value="">
<a href="javascript:void(0)" class="problem_search_btn fl" onclick="remote_function();" >搜索</a>
</div><!--problem_search end-->
<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 %>
<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 class="contextual">
<% if !@query.new_record? && @query.editable_by?(User.current) %>
@ -23,51 +75,6 @@
<% html_title(@query.new_record? ? l(:label_issue_plural) : @query.name) %>
<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>
<%= error_messages_for 'query' %>
@ -78,12 +85,14 @@
<%= l(:label_no_data) %>
</p>
<% else %>
<%= render :partial => 'issues/list', :locals => {:issues => @issues, :query => @query} %>
<div class="pagination">
<ul><%= pagination_links_full @issue_pages, @issue_count %></ul>
<div id="issue_list">
<%= render :partial => 'issues/list', :locals => {:issues => @issues, :query => @query,:issue_pages=>@issue_pages,:issue_count=>@issue_count} %>
</div>
<% end %>
<div style="float: right; padding-top: 30px">
<div style="float: left; padding-top: 30px">
<% other_formats_links do |f| %>
<%= 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;" %>
@ -91,7 +100,6 @@
<% end %>
</div>
<div id="csv-export-options" style="display:none;">
<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 %>
@ -115,11 +123,8 @@
</p>
<% end %>
</div>
<% end %>
<%= call_hook(:view_issues_index_bottom, {:issues => @issues, :project => @project, :query => @query}) %>
<% content_for :sidebar do %>
<%= render :partial => 'issues/sidebar' %>
<% 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>
</div>
<%= call_hook(:view_issues_new_top, {:issue => @issue}) %>
<%= labelled_form_for @issue, :url => project_issues_path(@project),
:html => {:id => 'issue-form', :multipart => true} do |f| %>
<%= error_messages_for 'issue' %>
<%= hidden_field_tag 'copy_from', params[:copy_from] if params[:copy_from] %>
<div class="box tabular">
<div id="all_attributes">
<%= render :partial => 'issues/form', :locals => {:f => f} %>
:html => {:id => 'issue-form', :multipart => true} do |f| %>
<%= error_messages_for 'issue' %>
<%= hidden_field_tag 'copy_from', params[:copy_from] if params[:copy_from] %>
<div>
<%= render :partial => 'issues/form', :locals => {:f => f} %>
</div>
<% if @copy_from && @copy_from.attachments.any? %>
<p>
<!-- 去除附件复制功能 -->
<!-- <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)%>
<!--<%= javascript_tag "$('#issue_subject').focus();" %>-->
<a href="#" class="blue_btn fl ml80" onclick="$('#issue-form').submit();">
<%= l(:button_create) %>
</a>
<%= preview_link preview_new_issue_path(:project_id => @project), 'issue-form','preview',{:class => "ButtonColor m3p10"}%>
<%= javascript_tag "$('#issue_subject').focus();" %>
<%#= preview_link preview_new_issue_path(:project_id => @project), 'issue-form', 'preview', {:class => "blue_btn fl ml10"} %>
<% end %>
<div id="preview" class="wiki"></div>

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

@ -1,5 +1,5 @@
$('#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) %>
$('#log_time').show();
<% else %>

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

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

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

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

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

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

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

@ -114,6 +114,9 @@ $(function(){
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();
}
@ -166,8 +169,8 @@ function cookieget(n)
<div class="custom_service">
<% get_memo %>
<%= 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 :content,:id => 'hidden', :required => true , :value => l(:label_feedback_value) %>
<%= f.hidden_field :subject,: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" %>
<a href="javascript:void(0);" class="opnionButton" style=" color:#fff;" id="" onclick="f_submit();"><%= l(:label_submit)%></a>
<% end %>

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

@ -13,8 +13,8 @@
<div class="custom_service">
<% get_memo %>
<%= 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 :content, :required => true , :value => l(:label_feedback_value) %>
<%= f.hidden_field :subject,: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();">
<%= l(:label_submit)%>
</a>

@ -10,230 +10,239 @@
<meta name="keywords" content="issue,bug,tracker" />
<%= csrf_meta_tag %>
<%= favicon %>
<%= stylesheet_link_tag 'jquery/jquery-ui-1.9.2', 'application', 'nyan', :media => 'all' %>
<%= stylesheet_link_tag 'rtl', :media => 'all' if l(:direction) == 'rtl' %>
<%= javascript_heads %>
<%= heads_for_theme %>
<%= hubspot_head %>
<%= stylesheet_link_tag 'public', 'pleft', 'project','jquery/jquery-ui-1.9.2' %>
<%= javascript_include_tag 'project', 'header','select_list_move' %>
<%= call_hook :view_layouts_base_html_head %>
<!-- page specific tags -->
<%= yield :header_tags -%>
<!--项目的三种类型-->
<script type="text/javascript">
function click_ok(url)
{
$('#light').css('display','none');
$('#fade').css('display','none');
//ajax处理请求
var project_type;
if($("#development_group").attr("checked") == "checked"){
project_type = 1;
}
else if($("#research_group").attr("checked") == "checked"){
project_type = 2;
}
else if($("#friend_organization").attr("checked") == "checked"){
project_type = 3;
}
$.get(
url,
{ project_type: project_type},
function (data) {
if(data == 1)
{
$("#setting_project_type").replaceWith("<%= escape_javascript(project_type_link(l(:label_development_team), 1))%>");
$("#project_memu_list").html('<%= escape_javascript(render(:partial => 'layouts/base_development_group')) %>');
$("#close_light").attr("onClick","close_window('development_group');");
}
else if(data == 2)
{
$("#setting_project_type").replaceWith("<%= escape_javascript(project_type_link(l(:label_research_group), 2))%>");
$("#project_memu_list").html('<%= escape_javascript(render(:partial => 'layouts/base_research_team')) %>');
$("#close_light").attr("onClick","close_window('research_group');");
}
else if(data == 3)
{
$("#setting_project_type").replaceWith("<%= escape_javascript(project_type_link(l(:label_friend_organization), 3))%>");
$("#project_memu_list").html('<%= escape_javascript(render(:partial => 'layouts/base_friend_group')) %>');
$("#close_light").attr("onClick","close_window('friend_organization');");
}
else
{
alert("服务器异常,请与管理员联系");
}
}
);
}
</script>
</head>
<!--add by huang-->
<body class="<%= h body_css_classes %>">
<div id="wrapper">
<div id="wrapper2">
<div id="wrapper3">
<%= render :partial => 'layouts/base_header'%>
<div id="main">
<div class="top-content">
<table>
<tr>
<td class="info_font" style="width: 240px;" rowspan="2"><a href="http://<%= Setting.host_name%>" style="color: #15bccf;"> <%= l(:label_projects_community)%> </a></td>
<td style="width: 430px; color: #15bccf"><strong><%= l(:label_user_location) %> : </strong></td>
<td rowspan="2" width="250px">
<div class="top-content-search">
<script type="text/javascript">
function regexName()
{
var name = $.trim($("#name").val());
if(name.length == 0)
{
$("#project_name_span").text("<%= l(:label_search_conditions_not_null) %>");
$("#project_name_span").css('color','#ff0000');
$("#project_name_span").focus();
return false;
}
else
{
$("#project_name_span").text("");
return true;
}
}
// 项目描述超过展开
$(function(){
$(".subNav").click(function(){
$(this).toggleClass("currentDd").siblings(".subNav").removeClass("currentDd")
$(this).toggleClass("currentDt").siblings(".subNav").removeClass("currentDt")
// 修改数字控制速度, slideUp(500)控制卷起速度
$(this).next(".navContent").slideToggle(500).siblings(".navContent").slideUp(500);
})
})
<body>
<div id="Container">
<%= render :partial => 'layouts/new_header'%>
<div class="cl"></div>
<!--TopBar begin-->
<div id="TopBar">
<div class="topbar_info02 fl">
<h2>
<a href="http://<%= Setting.host_name %>" target="_blank" class="c_blue">
<%= l(:label_projects_community) %>
</a>
</h2>
<p class="hidden">
<%= l(:label_user_location) %> :
<%= link_to l(:field_homepage), home_path %>
>
<a href="http://<%= Setting.host_name %>">
<%=l(:label_project_hosting_platform) %>
</a>
>
<%= link_to @project.name, nil %>
</p>
</div>
<div class="search fl">
function show_more_msg()
{$("#course_description").toggleClass("course_description_none");}
</script>
<%= form_tag(projects_search_path, :method => :get, :id => "project_search_form") do %>
<%= text_field_tag 'name', params[:name], :size => 20, :onkeyup => "regexName();", :style => "float:left" %>
<%= hidden_field_tag 'project_type', params[:project_type] %>
<%#= submit_tag l(:label_search), :class => "enterprise", :name => nil %>
<a href="#" onclick="submitSerch();" class="ButtonColor m3p10" style="float:left;padding-top: 3px; margin: 0px;padding-bottom:0px;" > <%= l(:label_search)%> </a>
<br />
<span id="project_name_span" style="float: left"></span>
<% end %>
</div></td>
</tr>
<tr>
<td>
<p class="top-content-list">
<%= link_to l(:label_home),home_path %> >
<%= link_to @project, project_path(@project) %>
</p></td>
</tr>
</table>
</div>
<!-- 左边侧栏内容 -->
<div id="sidebar">
<div class="project_left">
<div class="project_info">
<div class="pr_info_logo fl mr10 mb5">
<%= image_tag(url_to_avatar(@project), :style => 'width:61px; height:61px;') %>
</div>
<div class="pr_info_id fl mb5">
<%= l(:label_project_id)%><%= @project.id %>
</div>
<!--关注、申请加入/退出项目-->
<div id="join_exit_project_div">
<%= render 'layouts/join_exit_project' %>
</div>
<!-- 项目得分 -->
<div class="cl"></div>
<div class="pr_info_name f1">
<%= link_to @project.name, project_path(@project), :style => "color:#3E4040"%>
<% if !@project.is_public? %>
<span class="img_private"><%= l(:label_private)%></span>
<% end %>
</div>
<div class="cl"></div>
<div class="pr_info_score">
<% if @project.project_type == 0 %>
<%= l(:label_project_score)%> :
<%= link_to(format("%.2f" ,project_scores(@project) ).to_i, {:controller => 'projects',
:action => 'show_projects_score',
:remote => true,
:id => @project.id },
:style => "color: #EC6300;") %>
<% end %>
</div>
<div class="pr_info_foot">
<%= l(:label_member) %><span class="info_foot_num" >
<%= link_to "#{@project.members.count}", project_member_path(@project), :style => "color:#3CA5C6;font-weight:bold" %></span>
<span>| </span>
<%= l(:label_user_watcher) %><span class="info_foot_num">
<%= link_to "#{@project.watcher_users.count}", {:controller=>"projects", :action=>"watcherlist", :id => @project.id}, :style => "color:#3CA5C6;font-weight:bold" %></span>
<span>| </span>
<%= l(:project_module_attachments) %><span class="info_foot_num" >
<%= form_tag(projects_search_path, :method => :get, :id => "project_search_form", :class => "search_form") do %>
<%= text_field_tag 'name', params[:name], :placeholder => "项目名称", :class => "search_text fl", :onkeyup => "regexName('#{l(:label_search_conditions_not_null)}');" %>
<a href="#" onclick="submitSerch('<%= l(:label_search_conditions_not_null) %>');" class="search_btn fl f14 c_white" >
<%= l(:label_search)%>
</a>
<div class="cl"></div>
<span id="project_name_span" class="fl"></span>
<% end %>
</div>
</div><!--TopBar end-->
<div id="content">
<div id="LSide" class="fl">
<div class="project_info">
<div class="pr_info_logo fl mr10 mb5">
<%= image_tag(url_to_avatar(@project), :width => "60", :height => "60") %>
</div>
<div class="pr_info_id fl mb5 f14">
<%= l(:label_project_id)%><%= @project.id %>
</div>
<!--关注、申请加入/退出项目-->
<div id="join_exit_project_div">
<% text = @project.project_new_type == 1 ? l(:label_development_team) : (@project.project_new_type == 2 ? l(:label_research_group) : l(:label_friend_organization))%>
<% typeclass = @project.project_new_type == 1 ? "pr_kafa" : (@project.project_new_type == 2 ? "pr_keyan" : "pr_friend")%>
<%= render 'layouts/join_exit_project',{:text => text, :typeclass => typeclass} %>
</div>
<!-- 项目得分 -->
<div class="cl"></div>
<div>
<a class="pr_info_name fl c_dark fb break_word" href="javascript:void(0)" target="_blank" >
<%= l(:label_project_name) %><%= @project.name %>
<% if @project.is_public? %>
<span class="img_private"><%= l(:label_public)%></span>
<% else %>
<span class="img_private"><%= l(:label_private)%></span>
<% end %></a>
</div>
<div class="cl"></div>
<div>
<% if @project.project_type == 0 %>
<span class="fb f14 "><%= l(:label_project_score)%> :</span>
<%= link_to(format("%.2f" ,project_scores(@project) ).to_i, {:controller => 'projects',
:action => 'show_projects_score',
:remote => true,
:id => @project.id
}, :class => "c_orange f14" ) %>
<% end %>
</div>
<!--参数-->
<div class="pr_info_foot">
<%= l(:label_member) %><%= link_to "#{@project.members.count}", project_member_path(@project), :class => 'info_foot_num c_blue' %>
<span>|&nbsp;</span>
<%= l(:label_user_watcher) %><%= link_to "#{@project.watcher_users.count}", {:controller=>"projects", :action=>"watcherlist", :id => @project.id}, :class => 'info_foot_num c_blue' %>
<span>|&nbsp;</span>
<%= l(:project_module_attachments) %>
<% attaments_num = @project.attachments.count+Attachment.where(["`container_type` = 'Version' and `container_id` in (?)",@project.versions.map{ |v| v.id}]).all.count %>
<%= link_to "#{attaments_num}", project_files_path(@project), :style => "color:#3CA5C6;font-weight:bold" %></span>
</div>
<div class="cl"></div>
</div><!--项目信息 end-->
<%= link_to "#{attaments_num}", project_files_path(@project), :class => 'info_foot_num c_blue' %></span>
</div>
<div class="cl"></div>
</div><!--参数 end-->
<!--邀请加入-->
<div class="subNavBox">
<% if User.current.member_of?(@project) %>
<div class="subNav currentDd currentDt subNav_jiantou" id="expand_tools_expand_invit" onclick="expand_tools_expand('invit');"><%= l(:label_invite)%></div>
<ul class="navContent " style="display:block">
<li><%= link_to l(:label_invite_new_user), :controller=>"projects", :action=>"invite_members_by_mail", :id => @project %></li>
<% if User.current.allowed_to?(:manage_members, @project) %>
<li><%= link_to l(:label_invite_trustie_user), :controller=>"projects", :action=>"invite_members", :id => @project %></li>
<% end %>
</ul>
<% end %><!--end-->
<!--menu 左侧工具栏 -->
<!--project_new_type: 1为开发组2为科研组3为朋友圈子-->
<div id="project_memu_list">
<% if @project.project_new_type == 1 || @project.project_new_type.nil? %>
<%= render :partial => 'layouts/base_development_group', :locals => {:project => @project}%>
<% elsif @project.project_new_type == 2 %>
<%= render :partial => 'layouts/base_research_team', :locals => {:project => @project}%>
<% else %>
<%= render :partial => 'layouts/base_friend_group', :locals => {:project => @project}%>
<% end %>
</div>
<!-- end -->
</div><!--项目侧导航 end-->
<div class="cl"></div>
<div class="subNavBox">
<% if User.current.member_of?(@project) %>
<div class="subNav currentDd currentDt subNav_jiantou"><%= l(:label_invite)%></div>
<ul class="navContent " style="display:block; padding-left: 0px; margin-top:0px;">
<li><%= link_to l(:label_invite_new_user), :controller=>"projects", :action=>"invite_members_by_mail", :id => @project %></li>
<li><%= link_to l(:label_invite_trustie_user), :controller=>"projects", :action=>"invite_members", :id => @project %></li>
</ul>
<% end %>
<div class="subNav">
<%= link_to l(:label_activity), {:controller => 'projects', :action => 'show', :id => @project.id}, :style => "color:#3CA5C6" %>
<% unless ForgeActivity.where("project_id = ?", @project.id).count == 0 %>
<span class="subnav_num">(<%= ForgeActivity.where("project_id = ?", @project.id).count %>)</span>
<% end %>
</div>
<% unless @project.enabled_modules.where("name = 'issue_tracking'").empty? %>
<div class="subNav">
<%= link_to l(:label_issue_tracking), project_issues_path(@project), :style => "color:#3CA5C6" %>
<% unless @project.issues.count == 0 %>
<span class="subnav_num">(<%= @project.issues.count %>)</span><span>
<% end %>
<% if User.current.member_of?(@project) %>
<%= link_to "+"+l(:label_release_issue), new_project_issue_path(@project) , :style => "font-size:12px !important;color:#fff; padding:1px 3px 3px 3px;height:16px;margin-top:4px;background:#28be6c;float:right;line-height:20px;" %></span>
<% end %>
</div>
<% end %>
<% unless @project.enabled_modules.where("name = 'boards'").empty? %>
<div class="subNav">
<%= link_to l(:project_module_boards), project_boards_path(@project), :style => "color:#3CA5C6" %>
<% unless @project.boards.first.topics.count == 0 %>
<span class="subnav_num">(<%= @project.boards.first.topics.count %>)</span>
<% end %>
<% if User.current.member_of?(@project) %>
<%= link_to "+"+l(:project_module_boards_post), project_boards_path(@project, :flag => true), :layout => 'base_projects',:style => "font-size:12px !important;color:#fff; padding:0px 3px 3px 3px;height:16px;margin-top:5px;background:#28be6c;float:right;line-height:20px;" %>
<% end %>
</div>
<% end%>
<% unless @project.enabled_modules.where("name = 'files'").empty? %>
<div class="subNav">
<%= link_to l(:project_module_files), project_files_path(@project), :style => "color:#3CA5C6" %>
<% unless attaments_num == 0 %>
<span class="subnav_num">(<%= attaments_num %>)</span>
<% end %>
<% if User.current.member_of?(@project) %>
<%= link_to "+"+l(:label_upload_files), project_files_path(@project,:flag => true),:style => "font-size:12px !important;color:#fff; padding:1px 3px 3px 3px;height:16px;margin-top:4px;background:#28be6c;float:right;line-height:20px;" %>
<% 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}, :style => "color:#3CA5C6" %>
<span class="subnav_num">(<%= @project.repositories.count %>)</span>
<%# if User.current.member_of?(@project) %>
<%#= link_to "+"+l(:project_module_create_repository), new_project_repository_path(@project),:style => "font-size:12px;color:#fff; padding:1px 3px 3px 3px;height:18px;margin-top:3px;background:#28be6c;float:right;line-height:20px;" %>
<%# end %>
</div>
<% end %>
<!-- 项目描述 -->
<div class="project_intro">
<div id="course_description" class="course_description">
<h4 ><%= l(:label_project_overview)%></h4>
<div id="course_description_content" class="break_word">
<%= textilizable(@project.description) if @project.description && !@project.description.blank? %>
</div>
</div>
<div class="lg-foot" id="lg-foot" onclick="show_more_msg();">
<label id="expend_more_information" value="show_more"><%= l(:label_expend_information)%></label>
<span class="g-arr-down">
<img id="arrow" src="/images/jiantou.jpg" width="12" height="6" />
</span>
</div>
</div><!--项目简介 end-->
<div class="subNav subNav_jiantou"><%= l(:label_project_more) %></div>
<ul class="navContent" style="padding-left: 0px">
<%= render 'projects/tools_expand' %>
</ul>
</div><!--项目侧导航 end-->
<div class="cl"></div>
<!-- 项目描述 -->
<div class="project_intro">
<div id="course_description" class="course_description">
<h4 ><%= l(:label_project_overview) %></h4><%= @project.description %>
</div>
<div class="lg-foot" onclick="show_more_msg();"><%= l(:label_expend_information) %><span class="g-arr-down"><img src="/images/jiantou.jpg" width="12" height="6" /></span></div>
</div>
<!-- tag模块 -->
<div class="project_Label">
<h4 class="project_h4"><%= l(:label_tag)%>:</h4>
<div class="tag_h" >
<div class="user_tags">
<div id="tags">
<%= render :partial => 'tags/project_tag', :locals => {:obj => @project,:object_flag => "2"}%>
</div>
</div>
</div>
<div class="cl"></div>
</div><!--项目标签 end-->
</div>
</div>
<div id="content">
<!-- tag模块 -->
<div class="project_Label">
<h4 class="mb5"><%= l(:label_tag)%>:</h4>
<div class="tag_h">
<div id="tags">
<%= render :partial => 'tags/project_tag', :locals => {:obj => @project,:object_flag => "2"}%>
</div>
</div>
<div class="cl"></div>
</div><!--项目标签 end-->
</div>
</div>
<%= render_flash_messages %>
<%= yield %>
<%= call_hook :view_layouts_base_content %>
<div style="clear:both;"></div>
</div>
<%= render :partial => 'layouts/base_footer'%>
</div>
<div id="RSide" class="fl">
<%= render_flash_messages %>
<%= yield %>
<%= call_hook :view_layouts_base_content %>
<div style="clear:both;"></div>
</div>
<div style="clear:both;"></div>
<div class="cl"></div>
<%= render :partial => 'layouts/new_footer'%>
<div class="cl"></div>
</div><!--Container end-->
<div id="light" class="white_content02">
<!-- 这里写需弹出框的HTML代码 -->
<% text = @project.project_new_type == 1 ? "development_group" : (@project.project_new_type == 2 ? "research_group" : "friend_organization")%>
<div ><a href="javascript:void(0)" onClick="close_window('<%= text%>');" class="box_close" id="close_light"></a></div>
<div class=" mt10">
<h3 class="mb10 c_blue">请选择项目类型:</h3>
<ul class="mb10" id="project_type">
<li><input type="radio" name="project_type" <%= @project.project_new_type == 1 ? 'checked' : ''%> id="development_group"/><label >&nbsp;&nbsp;开发模式</label></li>
<li><input type="radio" name="project_type" <%= @project.project_new_type == 2 ? 'checked' : ''%> id="research_group"/><label >&nbsp;&nbsp;研讨模式</label></li>
<li><input type="radio" name="project_type" <%= @project.project_new_type == 3 ? 'checked' : ''%> id="friend_organization"/><label >&nbsp;&nbsp;圈子模式</label></li>
</ul>
<a href="javascript:void(0)" class="orange_btn" onclick="click_ok('<%= change_project_type_project_path @project%>');" >确定</a>
<div id="ajax-indicator" style="display:none;">
<span><%= l(:label_loading) %></span>
</div>
<div id="ajax-modal" style="display:none;"></div>
</div>
</div>
<%= call_hook :view_layouts_base_body_bottom %>
</div>
</div>
</div>
<div id="fade" class="black_overlay">123</div>
<%= render :partial => 'layouts/new_feedback' %>
<div id="ajax-indicator" style="display:none;">
<span><%= l(:label_loading) %></span>
</div>
<div id="ajax-modal" style="display:none;"></div>
<%= call_hook :view_layouts_base_body_bottom %>
</body>
</html>

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

@ -2,7 +2,7 @@
<% if @flag == "true"%>
$('#principals_for_new_member').html('<%= escape_javascript(render_project_members(@project)) %>');
<% else%>
$('#principals_for_new_member').html('<%= escape_javascript(render_principals_for_new_members(@project)) %>');
$('#principals_for_new_member').html('<%= escape_javascript(render_project_members(@project)) %>');
<% end%>
<% elsif @course%>
var checked = $("#principals input:checked").size();

@ -1,27 +1,17 @@
<%if @project%>
$('#tab-content-members').html('<%= escape_javascript(render :partial => 'projects/settings/members') %>');
<%if !@applied_members%>
<% if @members.present? && @members.all? {|m| m.valid? } %>
<% @members.each do |member| %>
$("#member-<%= member.id %>").effect("highlight");
<% end %>
<% else %>
<% if @members %>
<% errors = @members.collect {|m| m.errors.full_messages}.flatten.uniq.join(', ')%>
alert('<%= raw(escape_javascript(l(:notice_failed_to_save_members, :errors => errors || ''))) %>');
<% else%>
// alert('');
<% end%>
<% end %>
<% end %>
<%elsif @course%>
<% if @create_member_error_messages%>
alert("<%= @create_member_error_messages%>");
<% else%>
$('#course_members_setting').html('<%= escape_javascript(render :partial => 'courses/course_members') %>');
alert("添加成功");
<% end%>
<%end%>
hideOnLoad();
<%if @project%>
<% if @project_error_message%>
alert("<%= @project_error_message%>");
<% else%>
$('#pro_st_tbc_03').html('<%= escape_javascript(render :partial => 'projects/settings/new_members') %>');
hideOnLoad();
alert("<%= @succes_message%>");
<% end%>
<%elsif @course%>
<% if @create_member_error_messages%>
alert("<%= @create_member_error_messages%>");
<% else%>
$('#course_members_setting').html('<%= escape_javascript(render :partial => 'courses/course_members') %>');
alert("添加成功");
<% end%>
hideOnLoad();
<%end%>

@ -1,6 +1,7 @@
<%if @project%>
$('#tab-content-members').html('<%= escape_javascript(render :partial => 'projects/settings/members') %>');
<%elsif @course%>
$('#course_members_setting').html('<%= escape_javascript(render :partial => 'courses/course_members') %>');
<%end%>
hideOnLoad();
<%if @project%>
$('#pro_st_tbc_03').html('<%= escape_javascript(render :partial => 'projects/settings/new_members') %>');
// $('#tab-content-members').html('<%#= escape_javascript(render :partial => 'projects/settings/members') %>');
<%elsif @course%>
$('#course_members_setting').html('<%= escape_javascript(render :partial => 'courses/course_members') %>');
<%end%>
hideOnLoad();

@ -1,9 +1,8 @@
<%if @project%>
$('#tab-content-members').html('<%= escape_javascript(render :partial => 'projects/settings/members') %>');
$("#member-<%= @member.id %>").effect("highlight");
<%elsif @course%>
$('#course_members_setting').html('<%= escape_javascript(render :partial => 'courses/course_members') %>');
<%end%>
hideOnLoad();
<%if @project%>
$('#pro_st_tbc_03').html('<%= escape_javascript(render :partial => 'projects/settings/new_members') %>');
<%elsif @course%>
$('#course_members_setting').html('<%= escape_javascript(render :partial => 'courses/course_members') %>');
<%end%>
hideOnLoad();

@ -0,0 +1,43 @@
<%= error_messages_for 'message' %>
<% replying ||= false %>
<% extra_option = replying ? { readonly: true} : { maxlength: 200 } %>
<li>
<label><span class="c_red">*</span>&nbsp;<%= l(:field_subject) %>&nbsp;&nbsp;</label>
<% if replying %>
<%= f.text_field :subject, { size: 60, id: "message_subject",:class=>"talk_input w585" }.merge(extra_option) %>
<% else %>
<%= f.text_field :subject, { size: 60, id: "message_subject", onkeyup: "regexSubject();",:class=>"talk_input w585" }.merge(extra_option) %>
<% end %>
<p id="subject_span" class="ml55"></p>
</li>
<li class="ml60 mb5">
<% unless replying %>
<% if @message.safe_attribute? 'sticky' %>
<%= f.check_box :sticky %>
<%= label_tag 'message_sticky', l(:label_board_sticky) %>
<% end %>
<% if @message.safe_attribute? 'locked' %>
<%= f.check_box :locked %>
<%= label_tag 'message_locked', l(:label_board_locked) %>
<% end %>
<% end %>
<div class="cl"></div>
</li>
<li>
<div id="message_quote" class="wiki" style="width: 100%;word-break: break-all;word-wrap: break-word;"></div>
<label class="fl ml3" >&nbsp;<%= l(:field_description) %>&nbsp;&nbsp;</label>
<%= text_area :quote,:quote,:style => 'display:none' %>
<%= f.text_area :content, :class => 'talk_text fl', :id => 'message_content', :onkeyup => "regexContent();", :maxlength => 5000,:placeholder => "最多3000个汉字(或6000个英文字符)" %>
<div class="cl"></div>
<p id="message_content_span" class="ml55"></p>
</li>
<div class="cl"></div>
<li>
<label class="fl">&nbsp;&nbsp;<%= l(:label_attachment_plural) %>&nbsp;&nbsp;</label>
<div class="fl ml3">
<%= render :partial => 'attachments/form_project', :locals => {:container => @message,:isReply => @isReply} %>
</div>
</li>
<li >
<div class="cl"></div>
</li>

@ -1,209 +1,115 @@
<style type="text/css">
.lz {
position: relative;
min-height: 200px;
margin: 10px 2px;
border-radius: 5px;
box-shadow: 1px 1px 6px #97EBF4;
}
.lz-left {
float: left;
margin: 2%;
padding: 0;
}
.memo-section {
width: auto;
margin-left: 15%;
padding-top: 1%;
border-left: 2px dotted #EEE;/*#8BE9F3;*/
}
.memo-title {
margin: 1em 0;
padding-left: 1%;
padding-bottom: 1%;
font-weight: bold;
border-bottom: 1px dashed rgb(204, 204, 204);
}
.memo-content {
width: 82%;
padding: 1%;
margin: 1%;
margin-bottom: 40px;
background-color: #F6F6F6;
white-space: normal;
word-break: break-all;
word-wrap: break-word;
/*word-wrap: break-word;*/
}
.memo-timestamp {
position: absolute;
bottom: 0px;
/*right: 0;*/
left: 0;
margin: 20px;
}
.replies {
float: right;
/*max-width: 90%;*/
}
.reply-box {
float: right;
width: 640px;
padding: 3%;
/*border: 2px solid #C6F3F9;*/
border-top: 2px double #C6F3F9;
/*border-radius: 10px;*/
}
</style>
<div class="lz">
<div class="project_r_h">
<h2 class="project_h2"> <%= l(:label_board_plural) %></h2>
</div>
<!-- 在这里添加赞和踩-->
<span id="praise_tread" style="float: right">
<%= render :partial => "/praise_tread/praise_tread",:locals => {:obj => @topic,:show_flag => true,:user_id =>User.current.id,:horizontal => true}%>
</span>
<div class="contextual">
<%= watcher_link(@topic, User.current) %>
<%= link_to(
l(:button_quote),
{:action => 'quote', :id => @topic},
:remote => true,
:method => 'get',
:class => 'icon icon-comment',
:remote => true) if !@topic.locked? && authorize_for('messages', 'reply') %>
<%= link_to(
l(:button_edit),
{:action => 'edit', :id => @topic},
:class => 'icon icon-edit'
) if @message.editable_by?(User.current) %>
<%= link_to(
l(:button_delete),
{:action => 'destroy', :id => @topic},
:method => :post,
:data => {:confirm => l(:text_are_you_sure)},
:class => 'icon icon-del'
) if @message.destroyable_by?(User.current) %>
</div>
<div class="lz-left">
<div class="">
<%= link_to image_tag(url_to_avatar(@topic.author), :class => "avatar"), user_path(@topic.author) %>
</div>
<p class="">
<%= link_to @topic.author, user_path(@topic.author) %>
</p>
<div class="project_r_h">
<h2 class="project_h2"><%= h @board.name %></h2>
</div>
<div class="problem_main">
<div class="ping_dispic">
<%=link_to image_tag(url_to_avatar(@topic.author), :width => "46", :height => "46"), user_path(@topic.author) %>
</div>
<div class="memo-section" style="width: 100%;word-break: break-all;word-wrap: break-word;">
<div class="memo-title <%= @topic.sticky? ? 'sticky' : '' %> <%= @topic.locked? ? 'locked' : '' %>" style="width: 53%;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;">
<% if @project %>
<%= label_tag l(:field_subject) %>:
<%= link_to @topic.subject, project_boards_path(@topic.project),title: @topic.subject.to_s %>
<% elsif @course %>
<%= label_tag l(:field_subject) %>:
<%= link_to @topic.subject, course_boards_path(@topic.course),title: @topic.subject.to_s %>
<% end %>
</div>
<div class="memo-content">
<%= textilizable(@topic, :content) %>
<%= link_to_attachments @topic, :author => false %>
</div>
<div class="memo-timestamp">
<div style="float: left">
<%= authoring @topic.created_on, @topic.author %>
</div>
<div style="float: right">
<% if User.current.logged? %>
<%= toggle_link l(:button_reply), "reply", :focus => 'message_content' %>
<% else %>
<%= link_to l(:button_reply), signin_path %>
<% end %>
</div>
</div>
<div class="talk_txt fl">
<p class="problem_tit fl fb" style="word-break:break-all;" >
<%= @topic.subject %></p>
<br/>
<p>由<%= link_to_user_header @topic.author,false,:class=> 'problem_name c_orange' %> 添加于<%= format_time(@topic.created_on) %></p>
</div>
<br />
</div>
<!-- <a class="talk_edit fr">删除</a><a class="talk_edit fr">编辑</a><a class="talk_edit fr">置顶</a> -->
<%#= watcher_link(@topic, User.current) %>
<%= link_to(
l(:button_edit),
{:action => 'edit', :id => @topic},
:class => 'talk_edit fr'
) if @message.editable_by?(User.current) %>
<%= link_to(
l(:button_delete),
{:action => 'destroy', :id => @topic},
:method => :post,
:data => {:confirm => l(:text_are_you_sure)},
:class => 'talk_edit fr'
) if @message.destroyable_by?(User.current) %>
<div class="cl"></div>
<div class="talk_info mb10" style="word-break:break-all;"><%= textilizable(@topic, :content) %></div>
<div class="talk_info mb10"><%= link_to_attachment_project @topic, :author => false %></div>
<!-- <a href="#" class=" link_file ml60">附件爱覅俄方if.zip(27.5kB)</a>-->
<div class="cl"></div>
<% if User.current.logged? %>
<%= toggle_link l(:button_reply), "reply", :focus => 'message_content',:class => 'talk_edit fr' %>
<% else %>
<%= link_to l(:button_reply), signin_path,:class => 'talk_edit fr' %>
<% end %>
<%= link_to(
l(:button_quote),
{:action => 'quote', :id => @topic},
:remote => true,
:method => 'get',
:class => 'talk_edit fr',
:remote => true) if !@topic.locked? && authorize_for('messages', 'reply') %>
<div class="cl"></div>
</div><!--讨论主类容 end-->
<% unless @replies.empty? %>
<br />
<br />
<br />
<br />
<h3 class="comments"><%= l(:label_reply_plural) %> (<%= @reply_count %>)</h3>
<% reply_count = 0 %>
<% @replies.each do |message| %>
<div class="message reply" id="<%= "message-#{message.id}" %>">
<table class="borad-text-list">
<tr>
<td rowspan="3" valign="top" width="60px">
<%= link_to image_tag(url_to_avatar(message.author), :class => "avatar"), user_path(message.author) %>
</td>
<td>
<div class="contextual-borad">
<%= link_to(
"引用",
{:action => 'quote', :id => message},
:remote => true,
:method => 'get',
:title => l(:button_quote)) if !@topic.locked? && authorize_for('messages', 'reply') %>
<%= link_to(
#image_tag('edit.png'),
"编辑",
{:action => 'edit', :id => message},
:title => l(:button_edit)
) if message.editable_by?(User.current) %>
<%= link_to(
#image_tag('delete.png'),
"删除",
{:action => 'destroy', :id => message},
:method => :post,
:data => {:confirm => l(:text_are_you_sure)},
:title => l(:button_delete)
) if message.destroyable_by?(User.current) %>
</div>
</td>
</tr>
<tr>
<td class="comments">
<div class="wiki" style="width: 100%;word-break: break-all;word-wrap: break-word;">
<%= textAreailizable message,:content,:attachments => message.attachments %>
</div>
<%= link_to_attachments message, :author => false %>
</td>
</tr>
<tr>
<td class="font_lighter" style="float: left">
<%= authoring message.created_on, message.author %>
</td>
</tr>
</table>
</div>
<div class="ping_C mb10" id="<%= "message-#{message.id}" %>">
<div class="ping_dispic"><%= link_to image_tag(url_to_avatar(message.author), :width => '46',:height => '46'), user_path(message.author) %></div>
<div class="ping_discon">
<div class="ping_distop upload_img break_word">
<%= link_to_user_header message.author,false,:class => 'c_blue fb fl mb10 ' %>
<span class="c_grey fr"><%= format_time(message.created_on) %></span>
<div class="cl"></div>
<p class="break_word"><%= textAreailizable message,:content,:attachments => message.attachments %></p>
<%= link_to_attachments_course message, :author => false %>
</div>
<div class="ping_disfoot">
<%= link_to(
l(:button_quote),
{:action => 'quote', :id => message},
:remote => true,
:method => 'get',
:title => l(:button_quote)) if !@topic.locked? && authorize_for('messages', 'reply') %>
<%= link_to(
#image_tag('edit.png'),
l(:button_edit),
{:action => 'edit', :id => message},
:title => l(:button_edit)
) if message.course_editable_by?(User.current) %>
<%= link_to(
#image_tag('delete.png'),
l(:button_delete),
{:action => 'destroy', :id => message},
:method => :post,
:data => {:confirm => l(:text_are_you_sure)},
:title => l(:button_delete)
) if message.course_destroyable_by?(User.current) %>
</div>
<div class="cl"></div>
</div>
<div class="cl"></div>
</div><!---留言内容-->
<% end %>
<div class="pagination">
<%= pagination_links_full @reply_pages, @reply_count, :per_page_links => false %>
</div>
<% end %>
<% if !@topic.locked? && authorize_for('messages', 'reply') %>
<div id="reply" style="display:none;">
<%= form_for @reply, :as => :reply, :url => {:action => 'reply', :id => @topic}, :html => {:multipart => true, :id => 'message-form'} do |f| %>
<%= render :partial => 'form', :locals => {:f => f, :replying => true} %>
<input type="button" class="enterprise" value="<%=l(:button_submit) %>" onclick="submit_message_replay();" >
<%= form_for @reply, :as => :reply, :url => {:action => 'reply', :id => @topic}, :html => {:multipart => true, :id => 'message_form'} do |f| %>
<p class="talk_top"><%= l(:label_message_reply) %></p>
<%= render :partial => 'form_project', :locals => {:f => f, :replying => true} %>
<a href="#" onclick="submit_message_replay();"class="blue_btn fl c_white ml5" style="margin-left: 50px;"><%= l(:button_submit)%></a>
<% end %>
<div id="preview" class="wiki"></div>
</div>
<% end %>
<ul class="wlist">
<%= pagination_links_full @reply_pages, @reply_count, :per_page_links => false, :remote => false, :flag => true%>
</ul>
<% html_title @topic.subject %>
<script type="text/javascript">
var flag = false;
jQuery(document).ready(function($) {
transpotUrl('#content');
});
// var flag = false;
// jQuery(document).ready(function($) {
// transpotUrl('#content');
// });
function submit_message_replay()
{
if(flag)
{
$("#message-form").submit();
$("#message_form").submit();
}
}
function regexContent()

@ -3,22 +3,22 @@
</div>
<% if @message.project %>
<%= board_breadcrumb(@message) %>
<h3><%= avatar(@topic.author, :size => "24") %><span style = "width:100%;word-break:break-all;word-wrap: break-word;"><%=h @topic.subject %></span></h3>
<%= form_for @message, {
:as => :message,
:url => {:action => 'edit'},
:html => {:multipart => true,
:id => 'message-form',
:method => :post}
<%#= board_breadcrumb(@message) %>
<!--<h3><%#= avatar(@topic.author, :size => "24") %><span style = "width:100%;word-break:break-all;word-wrap: break-word;"><%#=h @topic.subject %></span></h3>-->
<div class="talk_new ml15">
<ul>
<%= form_for @message, { :as => :message,
:url => {:action => 'edit'},
:html => {:multipart => true,
:id => 'message-form',
:method => :post}
} do |f| %>
<%= render :partial => 'form',
<%= render :partial => 'form_project',
:locals => {:f => f, :replying => !@message.parent.nil?} %>
<a href="javascript:void(0)" onclick="$('#message-form').submit();" class="ButtonColor m3p10">
<%= l(:button_save) %>
</a>
<%= link_to l(:button_cancel), board_message_url(@message.board, @message.root, :r => (@message.parent_id && @message.id)), :class => "ButtonColor m3p10" %>
<a href="#" onclick="submitProjectsBoard();"class="blue_btn fl c_white"><%= l(:button_submit)%></a>
<%= link_to l(:button_cancel), board_message_url(@message.board, @message.root, :r => (@message.parent_id && @message.id)), :class => "blue_btn grey_btn fl c_white" %>
</ul>
</div>
<% end %>
<% elsif @message.course %>
<%#= course_board_breadcrumb(@message) %>

@ -13,6 +13,4 @@
<div id="preview" class="wiki"></div>
<% elsif @course %>
<%= render :partial => 'course_new' %>
<% end %>
<% end %>

@ -0,0 +1,27 @@
<li class="ml45">
<label><span class="c_red">*</span>&nbsp;<%= l(:field_title) %>&nbsp;&nbsp;</label>
<input type="text" name="news[title]" class="hwork_input" id="news_title" size="60" onkeyup="regexTitle();" maxlength="60" placeholder="60个字符以内" value="<%= is_new ? '' : @news.title %>">
<p id="title_notice_span" class="ml55"></p>
</li>
<li class="ml45">
<label class="fl" ><span class="c_red">*</span>&nbsp;<%= l(:field_description) %>&nbsp;&nbsp;</label>
<textarea id="news_description" name="news[description]" placeholder="最多3000个汉字(或6000个英文字符)" class="hwork_text fl" onkeyup="regexDescription();" maxlength="6000"><%= is_new ? '' : @news.description %></textarea>
<p id="description_notice_span" class="ml55"></p>
</li>
<div class="cl"></div>
<li class="ml45">
<label class="fl">&nbsp;&nbsp;<%= l(:label_attachment_plural) %>&nbsp;&nbsp;</label>
<%= render :partial => 'attachments/new_form', :locals => {:container => @news} %>
<div class="cl"></div>
</li>
<li class=" ml90" >
<% if is_new %>
<%= link_to l(:button_create), "#", :onclick => 'submitNews();', :onmouseover => 'submitFocus(this);', :class => 'blue_btn fl c_white' %>
<%= link_to l(:button_cancel), project_news_index_path(@project), :onclick => '$("#add-news").hide()', :class => 'blue_btn grey_btn fl c_white' %>
<% else %>
<%= link_to l(:button_save), "#", :onclick => 'submitNews();',:onmouseover => 'this.focus()',:class => 'blue_btn fl c_white' %>
<%= link_to l(:button_cancel), "#", :onclick => '$("#edit-news").hide(); return false;',:class => 'blue_btn grey_btn fl c_white' %>
<% end %>
<div class="cl"></div>
</li>
<!-- <#%= wikitoolbar_for 'news_description'%>-->

@ -1,95 +1,21 @@
<div class="project_r_h">
<h2 class="project_h2"><%= l(:label_news) %></h2>
</div>
<script type="text/javascript">
function regexTitle()
{
var name = $("#news_title").val();
if(name.length ==0)
{
$("#title_notice_span").text("<%= l(:label_title_blank)%>");
$("#title_notice_span").css('color','#ff0000');
$("#title_notice_span").focus();
return false;
}
else if(name.length <= 60)
{
$("#title_notice_span").text("<%= l(:label_field_correct)%>");
$("#title_notice_span").css('color','#008000');
return true;
}
else
{
$("#title_notice_span").text("<%= l(:label_title_long)%>");
$("#title_notice_span").css('color','#ff0000');
$("#title_notice_span").focus();
return false;
}
}
function regexDescription()
{
var name = $("#news_description").val();
if(name.length ==0)
{
$("#description_notice_span").text("<%= l(:label_descripition_blank)%>");
$("#description_notice_span").css('color','#ff0000');
$("#description_notice_span").focus();
return false;
}
else
{
$("#description_notice_span").text("<%= l(:label_field_correct)%>");
$("#description_notice_span").css('color','#008000');
return true;
}
}
function submitNews()
{
if(regexTitle() && regexDescription())
{
$("#news-form").submit();
}
}
function submitFocus(obj)
{
$(obj).focus();
}
</script>
<%
if @project.project_type == Project::ProjectType_course
btn_tips = l(:label_news_notice)
label_tips = l(:label_course_news)
else
btn_tips = l(:label_news_new)
label_tips = l(:label_news)
end
btn_tips = l(:label_news_new)
label_tips = l(:label_news)
%>
<% if @project.enabled_modules.where("name = 'news'").count > 0 && User.current.member_of?(@project) %>
<%= link_to(btn_tips,
new_project_news_path(@project),
:class => 'icon icon-add',
:onclick => 'showAndScrollTo("add-news", "news_title"); return false;') %>
<% end %>
<% if @project && User.current.allowed_to?(:manage_news, @project) %>
<div id="add-news" class="add_frame" style="display:none;">
<%= labelled_form_for @news, :url => project_news_index_path(@project),
:html => {:id => 'news-form', :multipart => true} do |f| %>
<%= render :partial => 'news/form', :locals => {:f => f} %>
<%#= submit_tag l(:button_create), :class => 'whiteButton m3p10 h30', :name => nil %><!-- button-submit -->
<%= link_to l(:button_create), "#", :onclick => 'submitNews();',:onmouseover => 'submitFocus(this);', :class => 'ButtonColor m3p10' %>
<div class="project_r_h">
<h2 class="project_h2"><%= label_tips %></h2>
</div>
<div class="talk_top">
<p class="fl"><%= l(:label_total_news) %><span><%= @news_count %></span><%= l(:label_project_new_list) %></p>
<% if @project && User.current.allowed_to?(:manage_news, @project) %>
<%= link_to(btn_tips, new_project_news_path(@project),
:class => 'problem_new_btn fl c_dorange') %>
<div class="cl"></div>
<%#= preview_link preview_news_path(:project_id => @project), 'news-form', target='preview', {:class => 'whiteButton m3p10'} %>
<% end %>
<div class="cl"></div>
</div>
<%= link_to l(:button_cancel), "#", :onclick => '$("#add-news").hide()', :class => 'ButtonColor m3p10' %>
<% end if @project %>
<div id="preview" class="wiki"></div>
</div>
<% end %>
<div>
<% if @newss.empty? %>
<p class="nodata">
@ -97,58 +23,26 @@
</p>
<% else %>
<% @newss.each do |news| %>
<div class="problem_main">
<%= link_to image_tag(url_to_avatar(news.author),:width => 42,:height => 42), user_path(news.author), :class => "problem_pic fl" %>
<div class="problem_txt fl mt5">
<%= link_to_user_header(news.author,false,{:class=> 'problem_name c_orange fl'}) if news.respond_to?(:author) %>
<span class="fl"> <%= l(:label_add_news) %></span><%= link_to h(news.title), news_path(news),:class => 'problem_tit fl fb c_dblue' %><br />
<div class="cl mb5"></div>
<p id="news_description_<%= news.id %>" class="mt5 break_word"><%= news.description %><br /> </p>
<div class="news_foot" style="display: none;" onclick="news_show_more_des(<%= news.id %>);" id="news_foot_<%= news.id %>"><%= l(:label_expend_information) %> <span class="g-arr-down"><img src="/images/jiantou.jpg" width="12" height="6" /></span></div>
<span class="f1"><%= l(:label_create_time) %> <%= format_time(news.created_on) %></span>
</div>
<div class="cl"></div>
</div><!--problem_main end-->
<table class="content-text-list">
<tr>
<td colspan="2" valign="top" width="50">
<%= link_to image_tag(url_to_avatar(news.author), :class => "avatar"), user_path(news.author) %>
</td>
<td>
<table width="580px" border="0">
<% if @project.project_type == 1 %>
<tr>
<td colspan="2" valign="top">
<strong><%= link_to_user(news.author) if news.respond_to?(:author) %></strong>
<span style="margin-left: 4px;" class="font_lighter"><%= l(:label_project_notice) %></span>
<span><%= link_to h(news.title), news_path(news) %></span>
<span style="float: right"><%= delete_link news_path(news) if User.current.allowed_to?(:manage_news, @project) %> </span>
</td>
</tr>
<% else %>
<tr>
<td colspan="2" valign="top">
<strong><%= link_to_user(news.author) if news.respond_to?(:author) %></strong>
<span style="margin-left: 4px;" class="font_lighter"><%= l(:label_project_newshare) %></span>
<span> <%= link_to h(news.title), news_path(news) %></span>
<span style="float: right" class='delete_icon'>
<%= delete_link news_path(news) if User.current.allowed_to?(:manage_news, @project) %>
</span>
</td>
</tr>
<% end %>
<tr>
<td colspan="2" width="580px">
<span class="font_description"><%= textilizable(news, :description) %></span></td>
</tr>
<tr>
<td align="left"><span class="font_lighter"> <%= l :label_update_time %>
&nbsp;<%= format_time(news.created_on) %></span></td>
<td width="350" align="right" class="a"><%= link_to l(:label_project_newother), news_path(news) if news.comments_count >0 %><%= "(#{l(:label_x_comments, :count => news.comments_count)})" if news.comments_count >= 0 %></td>
</tr>
</table>
</td>
</tr>
</table>
<% end %>
<% end %>
</div>
<!--end-->
<div style="padding-right: 10px">
<div class="pagination">
<ul>
<%= pagination_links_full @news_pages %>
</ul>
</div>
<ul class="wlist">
<%= pagination_links_full @news_pages, @news_count, :per_page_links => false, :remote => false, :flag => true%>
</ul>
<% other_formats_links do |f| %>
<%= f.link_to 'Atom', :url => {:project_id => @project, :key => User.current.rss_key} %>
@ -160,7 +54,6 @@
<% end %>
<% html_title(l(:label_news_plural)) -%>
</div>
<script type='text/javascript'>
$(document).ready(function ($) {

@ -27,6 +27,11 @@
}
}
function submitComment()
{
$("#add_comment_form").submit();
}
function regexDescription()
{
var name = $("#news_description").val();
@ -54,104 +59,71 @@
}
</script>
<div class="contextual">
<%= watcher_link(@news, User.current) %>
<%= link_to(l(:button_edit),
edit_news_path(@news),
:class => 'icon icon-edit',
:accesskey => accesskey(:edit),
:onclick => '$("#edit-news").show(); return false;') if User.current.allowed_to?(:manage_news, @project) %>
<%= delete_link news_path(@news) if User.current.allowed_to?(:manage_news, @project) %>
</div>
<h3><strong><%=h @news.title %></strong></h3>
<% if authorize_for('news', 'edit') %>
<div id="edit-news" style="display:none;">
<%= labelled_form_for :news, @news, :url => news_path(@news),
:html => { :id => 'news-form', :multipart => true, :method => :put } do |f| %>
<%= render :partial => 'form', :locals => { :f => f } %>
<%#= submit_tag l(:button_save) %>
<%= link_to l(:button_save), "#", :onclick => 'submitNews();',:onmouseover => 'this.focus()',:class => 'ButtonColor m3p10' %>
<%#= preview_link preview_news_path(:project_id => @project, :id => @news), 'news-form',target='preview',{:class => 'whiteButton m3p10'} %>
<%= link_to l(:button_cancel), "#", :onclick => '$("#edit-news").hide(); return false;',:class => 'ButtonColor m3p10'%>
<%= render :partial => 'project_form', :locals => { :f => f, :is_new => false } %>
<% end %>
<div id="preview" class="wiki"></div>
</div>
<% end %>
<div id="comments" style="margin-bottom:16px;">
<div style="margin:15px">
<span class="font_description">
<%= textilizable(@news, :description) %>
</span>
<br/>
<%= link_to_attachments @news %>
<br/>
<!--add comment-->
<% if @news.commentable? %>
<p>
<div class="problem_main">
<%= link_to image_tag(url_to_avatar(@news.author),:width => 42,:height => 42), user_path(@news.author), :class => "problem_pic fl" %>
<div class="problem_txt fl mt5">
<h4 class="r_txt_tit mb5"> <%=h @news.title %></h4>
<%#= watcher_link(@news, User.current) %>
<%= link_to(l(:button_edit),
edit_news_path(@news),
:class => 'talk_edit fr',
:accesskey => accesskey(:edit),
:onclick => '$("#edit-news").show(); return false;') if User.current.allowed_to?(:manage_news, @project) %>
<%= delete_link news_path(@news),:class => 'talk_edit fr' if User.current.allowed_to?(:manage_news, @project) %>
<div class="cl"></div>
<div class="mb5" style="word-break:break-all;"><%= textAreailizable(@news, :description) %><br /> <%= l(:label_create_time) %> <%= format_time(@news.created_on) %></div>
<%= link_to_attachments_course @news %>
<!--<a href="#" class=" link_file">附件爱覅俄方if.zip(27.5kB)</a> -->
</div>
<div class="cl"></div>
</div>
<!--add comment-->
<% if @news.commentable? %>
<div class="msg_box">
<%= toggle_link l(:label_comment_add), "add_comment_form", :focus => "comment_comments" %>
</p>
<%= form_tag({:controller => 'comments', :action => 'create', :id => @news}, :id => "add_comment_form", :style => "display:none;") do %>
<%= form_tag({:controller => 'comments', :action => 'create', :id => @news}, :id => "add_comment_form") do %>
<div class="box">
<%= text_area 'comment', 'comments', :cols => 80, :rows => 15, :class => 'wiki-edit' %>
<%= wikitoolbar_for 'comment_comments' %>
<%= text_area 'comment', 'comments', :rows => 5, :style => "width:98%" %>
</div>
<p>
<%= submit_tag l(:button_add) %>
</p>
<a onclick="submitComment();" class="blue_btn fr" href="javascript:void(0)" ><%= l(:label_comment_add) %></a>
<% end %>
<% end %>
<% html_title @news.title -%>
<% content_for :header_tags do %>
<%= stylesheet_link_tag 'scm' %>
<% end %>
<!--dispaly comments-->
<div class="line_heng"></div>
</div>
<h3 class="comments"><%= l(:label_comment_plural) %></h3>
<% comments = @comments.reverse %>
<% comments.each do |comment| %>
</div>
<% comments = @comments.reverse %>
<% comments.each do |comment| %>
<% next if comment.new_record? %>
<table width="660px" border="0" align="center">
<tr>
<td colspan="2" valign="top" width="50" >
<%= image_tag(url_to_avatar(comment.author), :class => "avatar")%>
</td>
<td>
<table width="580px" border="0">
<tr>
<td colspan="2" valign="top">
<strong><%= link_to_user(comment.author) if comment.respond_to?(:author) %> </strong>
<span class="font_lighter"><%= l(:label_project_newadd) %></span>
<%= l(:label_comment_plural) %>
</td>
</tr>
<tr>
<td colspan="2" width="580px" >
<span class="font_description">
<%= textilizable(comment.comments) %>
</span>
</td>
</tr>
<tr>
<td align="left">
<span class="font_lighter"> <%= format_time(comment.created_on) %></span>
</td>
<td width="200" align="right" class="a">
<%= link_to_if_authorized image_tag('delete.png'), {:controller => 'comments', :action => 'destroy', :id => @news, :comment_id => comment},
:data => {:confirm => l(:text_are_you_sure)},
:method => :delete,
:title => l(:button_delete) %>
</td>
</tr>
</table></td>
</tr>
</table>
<div class="ping_C mb10">
<div class="ping_dispic"><%= link_to image_tag(url_to_avatar(comment.author),:width => 42,:height => 42), user_path(comment.author), :class => "ping_dispic" %></div>
<div class="ping_discon">
<div class="ping_distop">
<%= link_to_user_header(comment.author,false,:class => 'c_blue fb fl mb10 ') if comment.respond_to?(:author) %><span class="c_grey fr"><%= format_time(comment.created_on) %></span>
<div class="cl"></div>
<p><%= textAreailizable(comment.comments) %></p>
</div>
<div class="ping_disfoot"><%= link_to_if_authorized image_tag('delete.png'), {:controller => 'comments', :action => 'destroy', :id => @news, :comment_id => comment},
:data => {:confirm => l(:text_are_you_sure)},
:method => :delete,
:title => l(:button_delete) %>
</div>
</div>
<div class="cl"></div>
</div>
<% end if @comments.any? %>
</div>
<% content_for :header_tags do %>
<%= stylesheet_link_tag 'scm' %>
<% end %>
<% html_title @news.title -%>

@ -4,12 +4,22 @@
label_tips = l(:label_course_news)
%>
<% if @project %>
<%= labelled_form_for @news, :url => project_news_index_path(@project),
:html => {:id => 'news-form', :multipart => true} do |f| %>
<%= render :partial => 'news/form', :locals => {:f => f} %>
<%= submit_tag l(:button_create), :class => "whiteButton m3p10 h30" %>
<%#= preview_link preview_news_path(:project_id => @project), 'news-form', target='preview', {:class => 'whiteButton m3p10'} %>
<% end %>
<div class="project_r_h">
<h2 class="project_h2"><%= l(:label_news) %></h2>
</div>
<div class="hwork_new">
<%= error_messages_for @news %>
<p class="talk_top pl15" >
<%= l(:label_news_new)%>
</p>
<ul>
<%= labelled_form_for @news, :url => project_news_index_path(@project),
:html => {:id => 'news-form', :multipart => true} do |f| %>
<%= render :partial => 'news/project_form', :locals => {:f => f, :is_new => true} %>
<% end if @project %>
</ul>
<div id="preview" class="wiki"></div>
</div>
<% elsif @course %>
<div class="project_r_h">
<h2 class="project_h2"><%= label_tips %></h2>

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

Loading…
Cancel
Save