diff --git a/Gemfile b/Gemfile
index 9642e320c..68656957f 100644
--- a/Gemfile
+++ b/Gemfile
@@ -6,6 +6,10 @@ unless RUBY_PLATFORM =~ /w32/
gem 'iconv'
end
+source 'http://rubygems.oneapm.com' do
+ gem 'oneapm_rpm'
+end
+
gem "mysql2", "= 0.3.18"
gem 'redis-rails'
gem 'rubyzip'
diff --git a/app/api/mobile/apis/comments.rb b/app/api/mobile/apis/comments.rb
index edc7bcf54..544ebf0ce 100644
--- a/app/api/mobile/apis/comments.rb
+++ b/app/api/mobile/apis/comments.rb
@@ -99,6 +99,19 @@ module Mobile
present :status, 0
end
+ desc '留言详情'
+ params do
+ requires :token, type: String
+ requires :comment_parent_id,type:Integer,desc:'留言id'
+ optional :course_id,type:Integer,desc:'课程id'
+ end
+ get ':comment_parent_id/comment_details' do
+ cs = CommentService.new
+ jour = cs.comment_detail params,current_user
+ present :data, jour, with: Mobile::Entities::Jours
+ present :status, 0
+ end
+
end
end
end
diff --git a/app/api/mobile/apis/users.rb b/app/api/mobile/apis/users.rb
index 675ad33c5..583a130d1 100644
--- a/app/api/mobile/apis/users.rb
+++ b/app/api/mobile/apis/users.rb
@@ -98,6 +98,7 @@ module Mobile
params do
requires :token, type: String
requires :user_id, type: Integer,desc: '被留言的用户id'
+ requires :page,type:Integer,desc:'请求数据的页码'
end
get ':user_id/messages' do
us = UsersService.new
@@ -106,19 +107,46 @@ module Mobile
present :status,0
end
- desc "给用户留言或回复用户留言"
+ desc "回复用户留言"
params do
requires :token, type: String
requires :user_id, type: Integer,desc: '被留言的用户id'
requires :content,type:String,desc:'留言内容'
- optional :refer_user_id,type:Integer,desc:'被回复的用户id'
+ requires :ref_user_id,type:Integer,desc:'被回复的用户id'
+ requires :parent_id,type:Integer,desc:'留言父id'
+ requires :ref_message_id,type:Integer,desc:'引用消息id'
+ optional :type,type:Integer,desc:'回复类型'
+ optional :course_id,type:Integer,desc:'课程id'
end
- post ':user_id/leave_message' do
+ post ':user_id/reply_message' do
us = UsersService.new
- jours = us.leave_messages params,current_user
+ jours = us.reply_user_messages params,current_user
present :status,0
end
+ desc "给用户留言"
+ params do
+ requires :token, type: String
+ requires :user_id, type: Integer,desc:'被留言的用户id'
+ requires :content, type: String,desc:'留言内容'
+ end
+ post ':user_id/leave_message' do
+ us = UsersService.new
+ us.leave_message params,current_user
+ present :data,0
+ end
+
+ desc "与我相关"
+ params do
+ requires :token, type: String
+ requires :page,type:Integer,desc:'页码'
+ end
+ get ':user_id/all_my_dynamic' do
+ us = UsersService.new
+ my_jours = us.reply_my_messages params,current_user
+ present :data,my_jours,with:Mobile::Entities::Jours
+ present :status,0
+ end
end
end
end
diff --git a/app/api/mobile/entities/jours.rb b/app/api/mobile/entities/jours.rb
index 10fd0f893..97eabd21f 100644
--- a/app/api/mobile/entities/jours.rb
+++ b/app/api/mobile/entities/jours.rb
@@ -14,6 +14,11 @@ module Mobile
else
f.send(field)
end
+ else
+ case f
+ when :course_name
+ f[:jour_type] == "Course" ? f.course.name : ""
+ end
end
end
end
@@ -27,6 +32,11 @@ module Mobile
jours_expose :notes
jours_expose :m_reply_id
jours_expose :m_parent_id
+ expose :course,using:Mobile::Entities::Course do |f,opt|
+ if f.is_a?(::JournalsForMessage) && f[:jour_type] == "Course"
+ f.course
+ end
+ end
expose :reply_user,using: Mobile::Entities::User do |f, opt|
f.at_user
end
diff --git a/app/controllers/account_controller.rb b/app/controllers/account_controller.rb
index 7976e1aa4..dc1cceb87 100644
--- a/app/controllers/account_controller.rb
+++ b/app/controllers/account_controller.rb
@@ -336,6 +336,7 @@ class AccountController < ApplicationController
:expires => 1.month.from_now,
:path => (Redmine::Configuration['autologin_cookie_path'] || '/'),
:secure => (Redmine::Configuration['autologin_cookie_secure'] ? true : false),
+ :domain => Redmine::Configuration['cookie_domain'],
:httponly => true
}
cookies[autologin_cookie_name] = cookie_options
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 0dc86fb01..88cd51d67 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -199,7 +199,7 @@ class ApplicationController < ActionController::Base
# Logs out current user
def logout_user
if User.current.logged?
- cookies.delete(autologin_cookie_name)
+ cookies.delete(autologin_cookie_name, domain: :all)
# Token.delete_all(["user_id = ? AND action = ?", User.current.id, 'autologin'])
self.logged_user = nil
end
diff --git a/app/controllers/avatar_controller.rb b/app/controllers/avatar_controller.rb
index ef7cdf2f7..a7c0e7b95 100644
--- a/app/controllers/avatar_controller.rb
+++ b/app/controllers/avatar_controller.rb
@@ -1,9 +1,9 @@
class AvatarController < ApplicationController
-
-
+
+ include ActionView::Helpers::NumberHelper
#before_filter :set_cache_buster
include AvatarHelper
-
+
def upload
# Make sure that API users get used to set this content type
# as it won't trigger Rails' automatic parsing of the request body for parameters
@@ -24,48 +24,58 @@ class AvatarController < ApplicationController
else
@image_file=params[:filename]
end
+ @temp_file = StringIO.new(@temp_file)
end
end
end
if @temp_file && (@temp_file.size > 0)
- diskfile=disk_filename(@source_type,@source_id)
- @urlfile='/' << File.join("images","avatars",avatar_directory(@source_type),avatar_filename(@source_id,@image_file))
+ if @temp_file.size > Setting.upload_avatar_max_size.to_i
+ @status = 1
+ @msg = l(:error_upload_avatar_to_large, :max_size => number_to_human_size(Setting.upload_avatar_max_size.to_i))
+ elsif Trustie::Utils::Image.new(@temp_file).image?
+ diskfile=disk_filename(@source_type,@source_id)
+ @urlfile='/' << File.join("images","avatars",avatar_directory(@source_type),avatar_filename(@source_id,@image_file))
- # 用户头像上传时进行特别处理
- if @source_type == 'User'
+ # 用户头像上传时进行特别处理
+ if @source_type == 'User'
diskfile += "temp"
@urlfile += "temp"
- end
+ end
- logger.info("Saving avatar '#{diskfile}' (#{@temp_file.size} bytes)")
- path = File.dirname(diskfile)
- unless File.directory?(path)
- FileUtils.mkdir_p(path)
- end
- md5 = Digest::MD5.new
- File.open(diskfile, "wb") do |f|
- if @temp_file.respond_to?(:read)
- buffer = ""
- while (buffer = @temp_file.read(8192))
- f.write(buffer)
- md5.update(buffer)
+ logger.info("Saving avatar '#{diskfile}' (#{@temp_file.size} bytes)")
+ path = File.dirname(diskfile)
+ unless File.directory?(path)
+ FileUtils.mkdir_p(path)
+ end
+ md5 = Digest::MD5.new
+ File.open(diskfile, "wb") do |f|
+ if @temp_file.respond_to?(:read)
+ @temp_file.rewind
+ buffer = ""
+ while (buffer = @temp_file.read(8192))
+ f.write(buffer)
+ md5.update(buffer)
+ end
+ else
+ f.write(@temp_file)
+ md5.update(@temp_file)
end
- else
- f.write(@temp_file)
- md5.update(@temp_file)
end
+
+ Trustie::Utils::Image.new(diskfile,true).compress(300)
+ @status = 0
+ @msg = ''
+ else
+ @status = 2
+ @msg = l(:not_valid_image_file)
end
-# self.digest = md5.hexdigest
end
@temp_file = nil
- image = Trustie::Utils::Image.new(diskfile,true)
- image.compress(300)
-
respond_to do |format|
format.json{
- render :inline => "#{@urlfile.to_s}?#{Time.now.to_i}",:content_type => 'text/html'
+ render :inline => {status: @status, message:@msg, url:"#{@urlfile.to_s}?#{Time.now.to_i}"}.to_json,:content_type => 'text/html'
return
}
format.js
diff --git a/app/controllers/bids_controller.rb b/app/controllers/bids_controller.rb
index c98df27d3..35236414f 100644
--- a/app/controllers/bids_controller.rb
+++ b/app/controllers/bids_controller.rb
@@ -675,11 +675,12 @@ class BidsController < ApplicationController
#删除作业
#by xianbo
def homework_destroy
- @bid_to_destroy = Bid.find params[:course_id]
+ @bid_to_destroy = Bid.find params[:id]
+ course_url = course_homework_path(@bid_to_destroy.courses.first)
(render_403; return false) unless User.current.admin?||User.current.id==@bid_to_destroy.author_id
@bid_to_destroy.destroy
respond_to do |format|
- format.html { redirect_to :back }
+ format.html { redirect_to course_url }
format.js
#format.api { render_api_ok }
end
diff --git a/app/controllers/files_controller.rb b/app/controllers/files_controller.rb
index aa2c9574b..0003f7586 100644
--- a/app/controllers/files_controller.rb
+++ b/app/controllers/files_controller.rb
@@ -67,9 +67,7 @@ class FilesController < ApplicationController
end
sort = "#{@sort} #{@order}"
end
-
# show_attachments [@course]
-
begin
q = "%#{params[:name].strip}%"
#(redirect_to stores_url, :notice => l(:label_sumbit_empty);return) if params[:name].blank?
@@ -108,14 +106,18 @@ class FilesController < ApplicationController
end
sort = "#{@sort} #{@order}"
end
-
begin
q = "%#{params[:name].strip}%"
#(redirect_to stores_url, :notice => l(:label_sumbit_empty);return) if params[:name].blank?
if params[:insite]
- @result = find_public_attache q,sort
- @result = visable_attachemnts_insite @result,@project
- @searched_attach = paginateHelper @result,10
+ if q == "%%"
+ @result = []
+ @searched_attach = paginateHelper @result,10
+ else
+ @result = find_public_attache q,sort
+ @result = visable_attachemnts_insite @result,@project
+ @searched_attach = paginateHelper @result,10
+ end
else
@result = find_project_attache q,@project,sort
@result = visable_attachemnts @result
diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb
index 8acca7f81..539d84e65 100644
--- a/app/controllers/issues_controller.rb
+++ b/app/controllers/issues_controller.rb
@@ -126,11 +126,11 @@ class IssuesController < ApplicationController
@edit_allowed = User.current.allowed_to?(:edit_issues, @project)
@priorities = IssuePriority.active
@time_entry = TimeEntry.new(:issue => @issue, :project => @issue.project)
-
+
@project_base_tag = (params[:project_id] || @issue.project) ? 'base_projects':'base'#by young
@available_watchers = (@issue.project.users.sort + @issue.watcher_users).uniq
-
- respond_to do |format|
+
+ respond_to do |format|``
format.html {
retrieve_previous_and_next_issue_ids
render :template => 'issues/show', :layout => @project_base_tag#by young
@@ -169,7 +169,7 @@ class IssuesController < ApplicationController
attrs = {:tracker_id => @issue.tracker, :parent_issue_id => @issue.parent_issue_id}.reject {|k,v| v.nil?}
redirect_to new_project_issue_url(@issue.project, :issue => attrs)
else
- redirect_to issue_url(@issue)
+ redirect_to issue_url(@issue.id)
end
}
format.api { render :action => 'show', :status => :created, :location => issue_url(@issue) }
@@ -239,7 +239,8 @@ class IssuesController < ApplicationController
flash[:notice] = l(:notice_successful_update) unless @issue.current_journal.new_record?
respond_to do |format|
- format.html { redirect_back_or_default issue_path(@issue) }
+
+ format.html { redirect_to issue_url(@issue.id) }
format.api { render_api_ok }
end
else
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index c79d0862f..b9e46daee 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -247,9 +247,9 @@ class ProjectsController < ApplicationController
# 1、自动注册
# 2、加入项目、创建角色
# 3、用户得分
- if params[:email]
- user = User.find_by_mail(params[:email].to_s)
- Member.create(:role_ids => [4], :user_id => user.id,:project_id => @project.id)
+ if params[:mail]
+ Member.create(:role_ids => [4], :user_id => params[:user],:project_id => params[:id])
+ UserGrade.create(:user_id =>params[:user], :project_id => params[:id])
end
if params[:jump] && redirect_to_project_menu_item(@project, params[:jump])
return
@@ -348,7 +348,7 @@ class ProjectsController < ApplicationController
if !params[:mail].blank? && User.find_by_mail(params[:mail].to_s).nil?
email = params[:mail]
Mailer.run.send_invite_in_project(email, @project, User.current)
- @is_zhuce =false
+ @is_zhuce = false
flash[:notice] = l(:notice_email_sent, :value => email)
elsif !User.find_by_mail(params[:mail].to_s).nil?
user = User.find_by_mail(params[:mail].to_s)
diff --git a/app/controllers/zipdown_controller.rb b/app/controllers/zipdown_controller.rb
index 06d69f72e..d9b900833 100644
--- a/app/controllers/zipdown_controller.rb
+++ b/app/controllers/zipdown_controller.rb
@@ -9,10 +9,14 @@ class ZipdownController < ApplicationController
#统一下载功能
def download
- begin
- send_file "#{OUTPUT_FOLDER}/#{params[:file]}", :filename => params[:filename], :type => detect_content_type(params[:file])
- rescue => e
- render file: 'public/no_file_found.html'
+ if User.current.logged?
+ begin
+ send_file "#{OUTPUT_FOLDER}/#{params[:file]}", :filename => params[:filename], :type => detect_content_type(params[:file])
+ rescue => e
+ render file: 'public/no_file_found.html'
+ end
+ else
+ render_403
end
end
diff --git a/app/helpers/account_helper.rb b/app/helpers/account_helper.rb
index 7ad6fe65b..827557a40 100644
--- a/app/helpers/account_helper.rb
+++ b/app/helpers/account_helper.rb
@@ -47,6 +47,18 @@ module AccountHelper
user
end
+ # 自动创建一个新用户,但是初始状态是锁定的
+ def automatically_register_lock(user, &block)
+ user.lock
+ user.last_login_on = Time.now
+ if user.save
+ UserStatus.create(:user_id => user.id, :changsets_count => 0, :watchers_count => 0)
+ 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)
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 0836bf307..a07ff320d 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -622,8 +622,8 @@ module ApplicationHelper
# 公开项目资源可以引用,admin和管理员和资源上传者拥有设置公开私有权限
def authority_pubilic_for_files(project, file)
@result = false
- if (is_project_manager?(User.current.id, @project.id) || file.author_id == User.current.id || User.current.admin) &&
- project_contains_attachment?(project,file) && file.container_id == project.id && file.container_type == "Project"
+ if (is_project_manager?(User.current.id, @project.id) && User.current.allowed_to?(:manage_files, project)) || file.author_id == User.current.id || User.current.admin &&
+ project_contains_attachment?(project,file) && file.container_id == project.id && file.container_type == "Project"
@result = true
end
return @result
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index 508e58ba3..12925b0b1 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -65,6 +65,16 @@ module ProjectsHelper
content_tag('div', content, :class => "tabs")
end
+ # 判断我的项目中是否有重名项目
+ def judge_same_projectname(user, project_name)
+ result = false
+ my_projects = user.projects
+ my_projects.each do |mp|
+ result = true if mp.name == project_name
+ end
+ return result
+ end
+
# Added by young
def course_settings_tabs
tabs = [{:name => 'info', :action => :edit_project, :partial => 'projects/edit', :label => :label_information_plural, :course=>'1'},
diff --git a/app/helpers/queries_helper.rb b/app/helpers/queries_helper.rb
index d9d910a66..43d01a5dd 100644
--- a/app/helpers/queries_helper.rb
+++ b/app/helpers/queries_helper.rb
@@ -255,7 +255,7 @@ 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[:f] = %w(subject status_id priority_id author_id assigned_to_id created_on) unless params[:status_id].nil?
params[:op] = {'subject' => "~" ,
'status_id' => ( params[:status_id] == '0' ? "!":"=" ),
'priority_id' => ( params[:priority_id] == '0' ? "!":"=" ),
@@ -266,6 +266,22 @@ module QueriesHelper
'priority_id' => [params[:priority_id]],
'author_id' => [params[:author_id]],
'assigned_to_id' => [params[:assigned_to_id]]} unless params[:status_id].nil?
+ if(params[:status_id] != nil)
+ if( params[:issue_create_date_start]!=nil && params[:issue_create_date_start]!='' &&
+ params[:issue_create_date_end]!=nil && params[:issue_create_date_end]!='' )
+ params[:op][:created_on]='><'
+ params[:v][:created_on]=[params[:issue_create_date_start],params[:issue_create_date_end]]
+ elsif(params[:issue_create_date_start]!=nil && params[:issue_create_date_start]!='')
+ params[:op][:created_on]='>='
+ params[:v][:created_on]=[params[:issue_create_date_start]]
+ elsif(params[:issue_create_date_end]!=nil && params[:issue_create_date_end]!='')
+ params[:op][:created_on]='<='
+ params[:v][:created_on]=[params[:issue_create_date_end]]
+ else
+ params[:op][:created_on]='!'
+ params[:v][:created_on]=''
+ end
+ end
@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}
# else
diff --git a/app/models/mailer.rb b/app/models/mailer.rb
index 7756b7e27..2c3a94874 100644
--- a/app/models/mailer.rb
+++ b/app/models/mailer.rb
@@ -58,14 +58,10 @@ class Mailer < ActionMailer::Base
us = UsersService.new
# 自动激活用户
user = us.register_auto(login, @email, @password)
-
- Member.create(:role_ids => [4], :user_id => user.id,:project_id => project.id)
- UserGrade.create(:user_id => user.id, :project_id => project.id)
User.current = user unless User.current.nil?
@user = user
@token = Token.get_token_from_user(user, 'autologin')
- @project_url = url_for(:controller => 'projects', :action => 'show', :id => project.id,:user => user, :token => @token.value
- )
+ @project_url = url_for(:controller => 'projects', :action => 'show', :id => project.id, :user => user.id, :mail => true, :token => @token.value)
mail :to => email, :subject => @subject
end
@@ -77,7 +73,7 @@ class Mailer < ActionMailer::Base
@project_name = "#{project.name}"
@user = user
@token = Token.get_token_from_user(user, 'autologin')
- @project_url = url_for(:controller => 'projects', :action => 'show', :id => project.id, :email => email, :token => @token.value)
+ @project_url = url_for(:controller => 'projects', :action => 'show', :id => project.id, :user => user.id, :mail => true, :token => @token.value)
mail :to => email, :subject => @subject
end
diff --git a/app/models/project.rb b/app/models/project.rb
index f257058ea..47878dbec 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -114,7 +114,7 @@ class Project < ActiveRecord::Base
validates_presence_of :name, :identifier
validates_uniqueness_of :identifier
- validates_uniqueness_of :name
+ # validates_uniqueness_of :name
validates_associated :wiki#, :repository
# validates_length_of :description, :maximum => 255
validates_length_of :name, :maximum => 255
diff --git a/app/services/comment_service.rb b/app/services/comment_service.rb
index f75e14b85..a742d0eee 100644
--- a/app/services/comment_service.rb
+++ b/app/services/comment_service.rb
@@ -101,4 +101,17 @@ class CommentService
@jours
end
+ def comment_detail params,current_user
+ if !params[:course_id].nil? && params[:course_id] != 0
+ course = Course.find(params[:course_id])
+ jour = course.journals_for_messages.where("id = ? ",params[:comment_parent_id])
+ jour
+ else
+ jour1 = JournalsForMessage.where("id = ? ",params[:comment_parent_id])
+ jour1
+ end
+ end
+
+
+
end
\ No newline at end of file
diff --git a/app/services/courses_service.rb b/app/services/courses_service.rb
index 26d8df16f..49170bf30 100644
--- a/app/services/courses_service.rb
+++ b/app/services/courses_service.rb
@@ -364,19 +364,20 @@ class CoursesService
latest_course_dynamics = []
latest_news = course.news.order("created_on desc").first
unless latest_news.nil?
- latest_course_dynamics << {:type => 1,:time => latest_news.created_on,:message => l(:label_recently_updated_notification,:locale => get_user_language(current_user))}
+ latest_course_dynamics << {:type => 1,:time => latest_news.created_on,
+ :message =>latest_news.author.realname<< l(:label_recently_updated_notification,:locale => get_user_language(current_user))<<":"<< latest_news.title }
end
latest_message = course.journals_for_messages.order("created_on desc").first
unless latest_message.nil?
- latest_course_dynamics << {:type => 2,:time => latest_message.created_on,:message => l(:label_recently_updated_message,:locale => get_user_language(current_user))}
+ latest_course_dynamics << {:type => 2,:time => latest_message.created_on,:message =>latest_message.user.realname << l(:label_recently_updated_message,:locale => get_user_language(current_user))<<":"<
diff --git a/app/views/courses/_course.html.erb b/app/views/courses/_course.html.erb
index 222d90458..420a22f8a 100644
--- a/app/views/courses/_course.html.erb
+++ b/app/views/courses/_course.html.erb
@@ -39,8 +39,8 @@
<%= content_tag "span", "#{l(:label_course_brief_introduction)}:", :class => "course-font" %> - <%= content_tag "div", course.short_description, :class => "brief_introduction", :title => course.short_description %>
+ <%= content_tag "div", course.short_description, :class => "brief_introduction",:style=>'float:left;', :title => course.short_description %> diff --git a/app/views/courses/homework.html.erb b/app/views/courses/homework.html.erb index f7cf2a360..7b74351cd 100644 --- a/app/views/courses/homework.html.erb +++ b/app/views/courses/homework.html.erb @@ -21,6 +21,9 @@<%= l(:lebel_homework_commit)%> ( <%= link_to bid.homeworks.count, course_for_bid_path(bid.id), :class => 'c_red'%> )
<% if @is_teacher%> <%= bid_anonymous_comment(bid)%> + <% if bid.homeworks.empty? %> + <%= link_to(l(:button_delete),bids_homework_path(:id => bid.id), :method => :delete, :confirm => l(:label_delete_confirm), :class => "fr mr10 work_edit") %> + <% end %> <%= link_to(l(:button_edit),edit_bid_path(:course_id =>@course.id, :bid_id => bid.id), :class => "fr mr10 work_edit") %> <% elsif @is_student%> <%= student_anonymous_comment bid %> @@ -59,4 +62,4 @@共有 <%= all_attachments.count%> 个资源
@@ -22,13 +22,13 @@ <% if User.current.logged? %> <% if (manage_allowed || file.author_id == User.current.id) && project_contains_attachment?(project,file) %> <%= link_to(l(:label_slected_to_other_project),quote_resource_show_project_project_file_path(project,file),:class => "f_l re_select",:remote => true) if has_project?(User.current,file) %> - <% else %> - <%= link_to(l(:label_slected_to_project),quote_resource_show_project_project_file_path(project,file),:class => "f_l re_select",:remote => true) if has_project?(User.current,file) %> - <% end %> - <% if authority_pubilic_for_files(project, file) %> + <% if authority_pubilic_for_files(project, file) && delete_allowed %> <%= link_to (file.is_public? ? "公开":"私有"), update_file_dense_attachments_path(:attachmentid=>file.id,:newtype=>(file.is_public? ? 0:1)),:remote=>true,:class=>"f_l re_open",:method => :post %> + <% end %> + <% else %> + <%= link_to(l(:label_slected_to_project),quote_resource_show_project_project_file_path(project,file),:class => "f_l re_select",:remote => true) if has_project?(User.current,file) %> <% end %> <% end %>
<%= l(:label_user_location) %> : - <%= link_to l(:field_homepage), home_path %> - > - - <%=l(:label_project_hosting_platform) %> - - > - <%= link_to @project.name, project_path(@project.id) %> + <%= link_to l(:field_homepage), home_path %> > <%=l(:label_project_hosting_platform) %> ><%= link_to @project.name, project_path(@project.id) %>
+
<%= textAreailizable act,:notes %>
+
<%= textilizable act,:notes %>
<%= l :label_activity_time %> :<%= format_activity_day(act.created_on) %> <%= format_time(act.created_on, false) %>
<%= setting_text_field :activity_days_default, :size => 6 %> <%= l(:label_day_plural) %>
<%= setting_text_field :host_name, :size => 60 %> +
<%= setting_text_field :host_course, :size => 60 %> +
<%= setting_text_field :host_contest, :size => 60 %> +
<%= setting_text_field :host_user, :size => 60 %> +
<%= setting_text_field :host_repository, :size => 60 %> + <%= l(:label_example) %>: <%= @guessed_host_and_path %>
<%= setting_select :protocol, [['HTTP', 'http'], ['HTTPS', 'https']] %>
diff --git a/app/views/users/user_homeworks.html.erb b/app/views/users/user_homeworks.html.erb index 06c67320a..74560909d 100644 --- a/app/views/users/user_homeworks.html.erb +++ b/app/views/users/user_homeworks.html.erb @@ -1,4 +1,4 @@ - +u <% if @user.user_extensions.identity == 0 %> <%= render :partial => 'my_create_homework' %> diff --git a/config/configuration.yml b/config/configuration.yml index 87a54a976..45e307157 100644 --- a/config/configuration.yml +++ b/config/configuration.yml @@ -90,6 +90,7 @@ default: user_name: "huang.jingquan@163.com" password: 'xinhu1ji2qu366' + cookie_domain: ".trustie.net" # Absolute path to the directory where attachments are stored. # The default is the 'files' directory in your Redmine instance. # Your Redmine instance needs to have write permission on this diff --git a/config/locales/commons/en.yml b/config/locales/commons/en.yml index 5eb92f07e..c0e29b797 100644 --- a/config/locales/commons/en.yml +++ b/config/locales/commons/en.yml @@ -113,6 +113,7 @@ en: one: "1 error prohibited this %{model} from being saved" other: "%{count} errors prohibited this %{model} from being saved" messages: + record_invalid: "validate error: %{errors}" inclusion: "is not included in the list" exclusion: "is reserved" invalid: "is invalid" @@ -428,4 +429,4 @@ en: previous: "« Previous" next: "Next »" truncate: "..." - \ No newline at end of file + diff --git a/config/locales/commons/zh.yml b/config/locales/commons/zh.yml index 231c5280a..a023bc8cb 100644 --- a/config/locales/commons/zh.yml +++ b/config/locales/commons/zh.yml @@ -121,6 +121,7 @@ zh: one: "由于发生了一个错误 %{model} 无法保存" other: "%{count} 个错误使得 %{model} 无法保存" messages: + record_invalid: "校验失败: %{errors}" inclusion: "不包含于列表中" exclusion: "是保留关键字" invalid: "是无效的" @@ -352,7 +353,7 @@ zh: # label_feedback: 意见反馈 label_feedback_tips: "欢迎反馈网站问题,课程中遇到的问题请反馈给相关老师!" - label_technical_support: "技术支持:" + label_technical_support: "QQ 在线支持:" label_feedback_success: "您的意见已经反馈到公共贴吧的新手讨论吧,我们会第一时间解决您的问题,谢谢支持!" label_feedback_value: "该帖来自用户反馈:)" @@ -435,4 +436,4 @@ zh: last: "末页 »" previous: "« 上一页" next: "下一页 »" - truncate: "..." \ No newline at end of file + truncate: "..." diff --git a/config/locales/en.yml b/config/locales/en.yml index 8989ae36a..8419ae188 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -183,6 +183,10 @@ en: setting_bcc_recipients: Blind carbon copy recipients (bcc) setting_plain_text_mail: Plain text mail (no HTML) setting_host_name: Host name and path + setting_host_course: Host course and path + setting_host_contest: Host contest and path + setting_host_user: Host user and path + setting_host_repository: Host repository and path setting_text_formatting: Text formatting setting_wiki_compression: Wiki history compression setting_feeds_limit: Maximum number of items in Atom feeds @@ -755,6 +759,7 @@ en: button_create_and_continue: Create and continue button_test: Test button_edit: Edit + button_delete: Delete button_edit_associated_wikipage: "Edit associated Wiki page: %{page_title}" button_add: Add button_change: Change @@ -1521,4 +1526,5 @@ en: label_commit_failed: commit failed #api end error_upload_avatar_to_large: "too big (%{max_size})" + not_valid_image_file: not a valid image file diff --git a/config/locales/zh.yml b/config/locales/zh.yml index 5c1014c7a..73a97c035 100644 --- a/config/locales/zh.yml +++ b/config/locales/zh.yml @@ -190,6 +190,10 @@ zh: setting_bcc_recipients: 使用密件抄送 (bcc) setting_plain_text_mail: 纯文本(无HTML) setting_host_name: 主机名称 + setting_host_course: 课程域名 + setting_host_contest: 竞赛域名 + setting_host_user: 用户域名 + setting_host_repository: 仓库域名 setting_text_formatting: 文本格式 setting_wiki_compression: 压缩Wiki历史文档 setting_feeds_limit: RSS Feed内容条数限制 @@ -845,6 +849,7 @@ zh: button_create_and_continue: 创建并继续 button_test: 测试 button_edit: 编辑 + button_delete: 删除 button_edit_associated_wikipage: "编辑相关wiki页面: %{page_title}" button_add: 新增 button_change: 修改 @@ -1985,3 +1990,4 @@ zh: label_code: 代码 error_upload_avatar_to_large: "超过大小限制 (%{max_size})" + not_valid_image_file: 不是有效的图片文件 diff --git a/config/oneapm.yml b/config/oneapm.yml new file mode 100644 index 000000000..e5b2e7bed --- /dev/null +++ b/config/oneapm.yml @@ -0,0 +1,135 @@ +# +# OneApm RubyAgent Configuration +# + +# Here are the settings that are common to all environments +common: &default_settings + # ============================== LICENSE KEY =============================== + + # + # Get your license key from oneapm.com + # + license_key: 'BAQMBw8FUwR2542UFFpDXFgVVk66e2dZWB4EBlQHSf846wgBGwICFQoD0498BAEfBgNIAlQ=' + + # Agent Enabled (Ruby/Rails Only) + # Valid values are true, false and auto. + # + # agent_enabled: auto + + # This app_name will be the application name in oneapm.com in your account. + # + # Caution: If you change this name, a new application will appear in the OneApm + # user interface with the new name, and data will stop reporting to the + # app with the old name. + # + app_name: trusite + + # When "true", the agent collects performance data about your + # application and reports this data to the OneApm service at + # oneapm.com. This global switch is normally overridden for each + # environment below. (formerly called 'enabled') + monitor_mode: true + + # Specify its log level here. + log_level: info + + # log_file_path: 'log' + # log_file_name: 'oneapm_agent.log' + + # The oneapm agent communicates with the service via https by default. + # ssl: true + + # ======================== Browser Monitoring ============================= + browser_monitoring: + # By default the agent automatically injects the monitoring JavaScript + # into web pages. Set this attribute to false to turn off this behavior. + auto_instrument: true + + # Proxy settings for connecting to the OneApm server. + # + # proxy_host: hostname + # proxy_port: 8080 + # proxy_user: + # proxy_pass: + + # Tells transaction tracer and error collector (when enabled) + # whether or not to capture HTTP params. When true, frameworks can + # exclude HTTP parameters from being captured. + # Rails: the RoR filter_parameter_logging excludes parameters + capture_params: false + + # Transaction tracer captures deep information about slow + # transactions and sends this to the OneApm service once a + # minute. Included in the transaction is the exact call sequence of + # the transactions including any SQL statements issued. + transaction_tracer: + + # Transaction tracer is enabled by default. + enabled: true + + # Threshold in seconds for when to collect a transaction + # trace. When the response time of a controller action exceeds + # this threshold, a transaction trace will be recorded and sent to + # OneApm. Valid values are any float value, or (default) "apdex_f", + # which will use the threshold for an dissatisfying Apdex + # controller action - four times the Apdex T value. + transaction_threshold: apdex_f + + # When transaction tracer is on, SQL statements can optionally be + # recorded. The recorder has three modes, "off" which sends no + # SQL, "raw" which sends the SQL statement in its original form, + # and "obfuscated", which strips out numeric and string literals. + record_sql: obfuscated + + # Threshold in seconds for when to collect stack trace for a SQL + # call. In other words, when SQL statements exceed this threshold, + # then capture and send to OneApm the current stack trace. This is + # helpful for pinpointing where long SQL calls originate from. + stack_trace_threshold: 0.500 + + # Determines whether the agent will capture query plans for slow + # SQL queries. Only supported in mysql and postgres. Should be + # set to false when using other adapters. + # explain_enabled: true + + # Threshold for query execution time below which query plans will + # not be captured. Relevant only when `explain_enabled` is true. + # explain_threshold: 0.5 + + # Error collector captures information about uncaught exceptions and + # sends them to OneApm for viewing + error_collector: + + # Error collector is enabled by default. + enabled: true + + # Ignore the following errors, add your own. + ignore_errors: "ActionController::RoutingError,Sinatra::NotFound" + +# ===================== Application Environments ======================== +# Environment-specific settings are in this section. +# For Rails applications, RAILS_ENV is used to determine the environment. + +# NOTE if your application has other named environments, you should +# provide oneapm configuration settings for these environments here. + +development: + <<: *default_settings + # Turn on communication to OneApm service in development mode + monitor_mode: true + app_name: My Application (Development) + +test: + <<: *default_settings + monitor_mode: false + +# Turn on the agent in production for 24x7 monitoring. +production: + <<: *default_settings + monitor_mode: true + +# Staging environment which behaves identically to production. +staging: + <<: *default_settings + monitor_mode: true + app_name: My Application (Staging) diff --git a/config/routes.rb b/config/routes.rb index 411386afc..9a8e71156 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -251,7 +251,7 @@ RedmineApp::Application.routes.draw do post 'boards/:board_id/topics/:id/edit', :to => 'messages#edit' post 'boards/:board_id/topics/:id/destroy', :to => 'messages#destroy' # boards end - post 'bids/homework_destroy', :to => 'bids#homework_destroy' + delete 'bids/homework', :to => 'bids#homework_destroy' # Misc issue routes. TODO: move into resources match '/issues/auto_complete', :to => 'auto_completes#issues', :via => :get, :as => 'auto_complete_issues' diff --git a/db/schema.rb b/db/schema.rb index e3828b0be..83599c087 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -659,6 +659,16 @@ ActiveRecord::Schema.define(:version => 20150514133640) do add_index "journal_details", ["journal_id"], :name => "journal_details_journal_id" + create_table "journal_details_copy", :force => true do |t| + t.integer "journal_id", :default => 0, :null => false + t.string "property", :limit => 30, :default => "", :null => false + t.string "prop_key", :limit => 30, :default => "", :null => false + t.text "old_value" + t.text "value" + end + + add_index "journal_details_copy", ["journal_id"], :name => "journal_details_journal_id" + create_table "journal_replies", :id => false, :force => true do |t| t.integer "journal_id" t.integer "user_id" diff --git a/lib/rails_kindeditor/lib/rails_kindeditor/helper.rb b/lib/rails_kindeditor/lib/rails_kindeditor/helper.rb index c3252ed1c..1f4c867ba 100644 --- a/lib/rails_kindeditor/lib/rails_kindeditor/helper.rb +++ b/lib/rails_kindeditor/lib/rails_kindeditor/helper.rb @@ -4,6 +4,7 @@ module RailsKindeditor def kindeditor_tag(name, content = nil, options = {}) id = sanitize_to_id(name) input_html = { :id => id }.merge(options.delete(:input_html) || {}) + input_html = input_html.merge(style: 'display:none') output = ActiveSupport::SafeBuffer.new output << text_area_tag(name, content, input_html) output << javascript_tag(js_replace(id, options.merge(window_onload: 'true'))) @@ -12,6 +13,7 @@ module RailsKindeditor def kindeditor(name, method, options = {}) # TODO: Refactory options: 1. kindeditor_option 2. html_option input_html = (options.delete(:input_html) || {}).stringify_keys + input_html = input_html.merge(style: 'display:none') output_buffer = ActiveSupport::SafeBuffer.new output_buffer << build_text_area_tag(name, method, self, options, input_html) output_buffer << javascript_tag(js_replace(input_html['id'],options.merge(window_onload: 'true'))) diff --git a/lib/trustie/utils/image.rb b/lib/trustie/utils/image.rb index 9178b291a..7e23e7b66 100644 --- a/lib/trustie/utils/image.rb +++ b/lib/trustie/utils/image.rb @@ -3,11 +3,36 @@ module Trustie module Utils class Image - def initialize(file, bak) + def initialize(file, bak=false) @file = file @bak = bak end + def bitmap?(data) + data[0,2]==77.chr + 66.chr + end + + def gif?(data) + data[0,4]==71.chr + 73.chr + 70.chr + 56.chr + end + + def jpeg?(data) + data[0,3]== 0xff.chr + 0xd8.chr + 0xff.chr + end + def png?(data) + data[0,2]==0x89.chr + 80.chr + end + + def image? + data = '' + if @file.respond_to?(:read) + data = @file.read(9) + @file.rewind + end + return false if data.size < 9 + bitmap?(data) || gif?(data) || jpeg?(data) || png?(data) + end + def compress(size=300) backup if @bak begin diff --git a/public/javascripts/course.js b/public/javascripts/course.js index 227048ef6..972ee858f 100644 --- a/public/javascripts/course.js +++ b/public/javascripts/course.js @@ -1,182 +1,158 @@ //配置课程信息 -function course_setting(id) -{ +function course_setting(id) { //alert(id); - $('#tb_'+id).removeClass().addClass("hwork_hovertab"); - $('#tbc_0'+id).removeClass().addClass("dis"); - $('#tb_'+(3-id)).removeClass().addClass("hwork_normaltab"); - $('#tbc_0'+(3-id)).removeClass().addClass("undis"); + $('#tb_' + id).removeClass().addClass("hwork_hovertab"); + $('#tbc_0' + id).removeClass().addClass("dis"); + $('#tb_' + (3 - id)).removeClass().addClass("hwork_normaltab"); + $('#tbc_0' + (3 - id)).removeClass().addClass("undis"); } -$(function(){ - $("img").removeAttr("align"); +$(function() { + $("img").removeAttr("align"); }); /////////////////////////////////////////////////////////////// //添加分班 -function add_group(url,course_id) { - var group_name = $('#group_name').val(); - $.get( - url, - { valid: "name", - value: group_name, - course_id: course_id }, - function (data) { - if (data.valid) { - $("#add_group_name").submit(); - } - else - { - alert(data.message); +function add_group(url, course_id) { + var group_name = $('#group_name').val(); + $.get( + url, { + valid: "name", + value: group_name, + course_id: course_id + }, + function(data) { + if (data.valid) { + $("#add_group_name").submit(); + } else { + alert(data.message); + } } - } - ); -} -//修改分班:修改分班时得考虑什么都不改但是点击确定的情况 -function edit_group(id,url,course_id,group_id) -{ - var group_name = $('#'+id).val(); + ); + } + //修改分班:修改分班时得考虑什么都不改但是点击确定的情况 + +function edit_group(id, url, course_id, group_id) { + var group_name = $('#' + id).val(); $.get( - url, - { + url, { valid: "name", value: group_name, course_id: course_id, group_id: group_id }, - function (data) { + function(data) { if (data.valid) { - $("#update_group_"+group_id).submit(); - } - else - { + $("#update_group_" + group_id).submit(); + } else { alert(data.message); } } ); } -function hidden_homework_score_form() -{ - hideModal($("#user_score")); -} -/////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////新建课程相关 -//验证课程名称 -function regex_course_name() -{ - var name = $.trim($("#course_name").val()); - if(name.length == 0) - { - $("#course_name_notice").show(); - return false; - } - else - { - $("#course_name_notice").hide(); - return true; - } -} -//验证课程学时 -function regex_course_class_period() -{ - var class_period = $.trim($("#class_period").val()); - var regex = /^\d*$/; - if(class_period.length == 0) - { - $("#course_class_period_notice").html("学时总数不能为空"); - $("#course_class_period_notice").show(); - return false; +function hidden_homework_score_form() { + hideModal($("#user_score")); } - else if (regex.test(class_period)) { - if(parseInt(class_period) > 0) - { - $("#course_class_period_notice").html(""); - $("#course_class_period_notice").hide(); + /////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////新建课程相关 + //验证课程名称 + +function regex_course_name() { + var name = $.trim($("#course_name").val()); + if (name.length == 0) { + $("#course_name_notice").show(); + return false; + } else { + $("#course_name_notice").hide(); return true; } - else - { - $("#course_class_period_notice").html("学时总数必须大于0"); + } + //验证课程学时 + +function regex_course_class_period() { + var class_period = $.trim($("#class_period").val()); + var regex = /^\d*$/; + if (class_period.length == 0) { + $("#course_class_period_notice").html("学时总数不能为空"); + $("#course_class_period_notice").show(); + return false; + } else if (regex.test(class_period)) { + if (parseInt(class_period) > 0) { + $("#course_class_period_notice").html(""); + $("#course_class_period_notice").hide(); + return true; + } else { + $("#course_class_period_notice").html("学时总数必须大于0"); + $("#course_class_period_notice").show(); + return false; + } + } else { + $("#course_class_period_notice").html("学时总数必须为数字"); $("#course_class_period_notice").show(); return false; } } - else - { - $("#course_class_period_notice").html("学时总数必须为数字"); - $("#course_class_period_notice").show(); - return false; - } -} -//验证密码 -function regex_course_password() -{ - var class_period = $.trim($("#course_course_password").val()); - var regex = /^\w+$/; - if(class_period.length == 0) - { - $("#course_course_password_notice").html("课程密码不能为空"); - $("#course_course_password_notice").show(); - return false; - } - else if (regex.test(class_period)) { - $("#course_course_password_notice").html(""); - $("#course_course_password_notice").hide(); - return true; - } - else - { - $("#course_course_password_notice").html("课程密码有非法字符"); - $("#course_course_password_notice").show(); - return false; + //验证密码 + +function regex_course_password() { + var class_period = $.trim($("#course_course_password").val()); + var regex = /^\w+$/; + if (class_period.length == 0) { + $("#course_course_password_notice").html("课程密码不能为空"); + $("#course_course_password_notice").show(); + return false; + } else if (regex.test(class_period)) { + $("#course_course_password_notice").html(""); + $("#course_course_password_notice").hide(); + return true; + } else { + $("#course_course_password_notice").html("课程密码有非法字符"); + $("#course_course_password_notice").show(); + return false; + } } -} -//提交新建课程 -function submit_new_course() -{ - if(regex_course_name()&®ex_course_class_period()&®ex_course_password()) - { + //提交新建课程 + +function submit_new_course() { + if (regex_course_name() && regex_course_class_period() && regex_course_password()) { $("#new_course").submit(); } } -function submit_edit_course(id) -{ - if(regex_course_name()&®ex_course_class_period()&®ex_course_password()) - { - $("#edit_course_"+id).submit(); +function submit_edit_course(id) { + if (regex_course_name() && regex_course_class_period() && regex_course_password()) { + $("#edit_course_" + id).submit(); } } /////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////课程讨论区 function regexSubject(id) { - var subjectid = "#message_subject" + id ; + var subjectid = "#message_subject" + id; var content = $.trim($(subjectid).val()); var message = "#subject_span" + id; if (content.length == 0) { $(message).text("主题不能为空"); $(message).css('color', '#ff0000'); - return false; - } - else { + return false; + } else { $(message).text("填写正确"); $(message).css('color', '#008000'); return true; } return false; } + function regexContent(id) { var contentid = "#message_content" + id; - var message = "#message_content_span"+ id; + var message = "#message_content_span" + id; var content = $.trim($(contentid).val()); if (content.length == 0) { $(message).text("描述不能为空"); $(message).css('color', '#ff0000'); - return false; - } - else { + return false; + } else { $(message).text("填写正确"); $(message).css('color', '#008000'); return true; @@ -195,297 +171,242 @@ function submitProjectsBoard(id) { /////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////// 课程通知 -function regexTitle() -{ +function regexTitle() { var name = $("#news_title").val(); - if(name.length ==0) - { + if (name.length == 0) { $("#title_notice_span").text("标题不能为空"); - $("#title_notice_span").css('color','#ff0000'); + $("#title_notice_span").css('color', '#ff0000'); $("#news_title").focus(); return false; - } - else if(name.length <= 60) - { + } else if (name.length <= 60) { $("#title_notice_span").text("填写正确"); - $("#title_notice_span").css('color','#008000'); + $("#title_notice_span").css('color', '#008000'); return true; - } - else - { + } else { $("#title_notice_span").text("标题超过60个字符"); - $("#title_notice_span").css('color','#ff0000'); + $("#title_notice_span").css('color', '#ff0000'); $("#news_title").focus(); return false; } } -function regexDescription() -{ +function regexDescription() { var name = news_description_editor.html(); - if(name.length ==0) - { + if (name.length == 0) { $("#description_notice_span").text("描述不能为空"); - $("#description_notice_span").css('color','#ff0000'); + $("#description_notice_span").css('color', '#ff0000'); $("#description_notice_span").focus(); return false; - } - else if(name.length >=6000){ + } else if (name.length >= 6000) { $("#description_notice_span").text("描述最多3000个汉字(或6000个英文字符)"); - $("#description_notice_span").css('color','#ff0000'); + $("#description_notice_span").css('color', '#ff0000'); $("#description_notice_span").focus(); return false; - } - else - { + } else { $("#description_notice_span").text("填写正确"); - $("#description_notice_span").css('color','#008000'); + $("#description_notice_span").css('color', '#008000'); return true; } } -function submitNews() -{ - if(regexTitle() && regexDescription()) - { +function submitNews() { + if (regexTitle() && regexDescription()) { news_description_editor.sync(); $("#news-form").submit(); } } -function submitFocus(obj) -{ +function submitFocus(obj) { $(obj).focus(); } -function submitComment() -{ +function submitComment() { comment_editor.sync(); $("#add_comment_form").submit(); } /////////////////////////////////////////////////课程讨论区 -function course_board_submit_message_replay() -{ - if(MessageReplayVevify()) - { - message_content_editor.sync();//提交内容之前要sync,不然服务器端取不到值 +function course_board_submit_message_replay() { + if (MessageReplayVevify()) { + message_content_editor.sync(); //提交内容之前要sync,不然服务器端取不到值 $("#message_form").submit(); } } -function course_board_canel_message_replay() -{ +function course_board_canel_message_replay() { $("#reply").hide(200); $("#message_quote").html(""); } function MessageReplayVevify() { - var content = message_content_editor.html();//$.trim($("#message_content").val()); - if (content.length == 0) { - $("#message_content_span").text("回复不能为空"); - $("#message_content_span").css('color', '#ff0000'); - return false; - } - else { - $("#message_content_span").text("填写正确"); - $("#message_content_span").css('color', '#008000'); - return true; + var content = message_content_editor.html(); //$.trim($("#message_content").val()); + if (content.length == 0) { + $("#message_content_span").text("回复不能为空"); + $("#message_content_span").css('color', '#ff0000'); + return false; + } else { + $("#message_content_span").text("填写正确"); + $("#message_content_span").css('color', '#008000'); + return true; + } } -} -////////////////////////////////////////////////// + ////////////////////////////////////////////////// /////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////// //验证搜索时输入名字 -function regexName(content) -{ - var name = $.trim($("#name").val()); - if(name.length == 0) - { - $("#project_name_span").text(content); - $("#project_name_span").css('color','#ff0000'); - $("#project_name_span").focus(); - return false; +function regexName(content) { + var name = $.trim($("#name").val()); + if (name.length == 0) { + $("#project_name_span").text(content); + $("#project_name_span").css('color', '#ff0000'); + $("#project_name_span").focus(); + return false; + } else { + $("#project_name_span").text(""); + return true; + } } - else - { - $("#project_name_span").text(""); - return true; + //提交搜索 + +function submitSerch(content) { + if (regexName(content)) { + $("#course_search_form").submit(); } } -//提交搜索 -function submitSerch(content) -{ - if(regexName(content)){$("#course_search_form").submit();} -} //验证搜索时输入名字 -function regexQ(content) -{ - var name = $.trim($("#q").val()); - if(name.length == 0) - { - $("#course_member_name_span").text(content); - $("#course_member_name_span").css('color','#ff0000'); - $("#course_member_name_span").focus(); - return false; - } - else - { - $("#course_member_name_span").text(""); - return true; +function regexQ(content) { + var name = $.trim($("#q").val()); + if (name.length == 0) { + $("#course_member_name_span").text(content); + $("#course_member_name_span").css('color', '#ff0000'); + $("#course_member_name_span").focus(); + return false; + } else { + $("#course_member_name_span").text(""); + return true; + } } -} -//提交课程成员搜索 -function submitMemberSerch(content) -{ + //提交课程成员搜索 + +function submitMemberSerch(content) { //if(regexQ(content)){$("#course_member_search_form").submit();} $("#course_member_search_form").submit(); } //课程描述显示更多信息 -function show_more_msg() -{ - $("#course_description").toggleClass("course_description_none"); -} -//作业描述显示更多信息 -function news_show_more_des(id) -{ - $('#news_description_' + id).toggleClass("news_description_none"); +function show_more_msg() { + $("#course_description").toggleClass("course_description_none"); + } + //作业描述显示更多信息 + +function news_show_more_des(id) { + $('#news_description_' + id).toggleClass("news_description_none"); } -function bid_show_more_des(id) -{ + +function bid_show_more_des(id) { $("#bid_description_" + id).toggleClass("news_description_none"); } //课程作业结束时间倒计时 -function show_bid_dead_line(year,month,day,divname) -{ - var now = new Date(); - var endDate = new Date(year, month-1, day); - var leftTime=endDate.getTime()-now.getTime(); - var leftsecond = parseInt(leftTime/1000); - var day1=Math.floor(leftsecond/(60*60*24)); - var hour=Math.floor((leftsecond-day1*24*60*60)/3600); - var minute=Math.floor((leftsecond-day1*24*60*60-hour*3600)/60); - var second=Math.floor(leftsecond-day1*24*60*60-hour*3600-minute*60); - $("#"+divname).html("" - + "作品提交还剩:
"); -} -//验证新建作业的名字 -function regex_bid_name() -{ +function show_bid_dead_line(year, month, day, divname) { + var now = new Date(); + var endDate = new Date(year, month - 1, day); + var leftTime = endDate.getTime() - now.getTime(); + var leftsecond = parseInt(leftTime / 1000); + var day1 = Math.floor(leftsecond / (60 * 60 * 24)); + var hour = Math.floor((leftsecond - day1 * 24 * 60 * 60) / 3600); + var minute = Math.floor((leftsecond - day1 * 24 * 60 * 60 - hour * 3600) / 60); + var second = Math.floor(leftsecond - day1 * 24 * 60 * 60 - hour * 3600 - minute * 60); + $("#" + divname).html("" + "作品提交还剩:
"); + } + //验证新建作业的名字 + +function regex_bid_name() { var name = $.trim($("#bid_name").val()); - if(name=="") - { + if (name == "") { $("#bid_name_span").text("名称不能为空"); return false; - } - else - { + } else { $("#bid_name_span").text(""); return true; } } //验证匿评数量 -function regex_evaluation_num() -{ +function regex_evaluation_num() { var evaluation_num = $.trim($("#bid_evaluation_num").val()); var regex = /^\d+$/; - if($("#bid_open_anonymous_evaluation").attr("checked") == "checked") - { - if(evaluation_num=="") - { + if ($("#bid_open_anonymous_evaluation").attr("checked") == "checked") { + if (evaluation_num == "") { $("#bid_evaluation_num_span").text("匿评分配数量不能为空"); return false; - } - else if(regex.test(evaluation_num)) - { - if(evaluation_num > 0) - { + } else if (regex.test(evaluation_num)) { + if (evaluation_num > 0) { $("#bid_evaluation_num_span").text(""); return true; - } - else - { + } else { $("#bid_evaluation_num_span").text("匿评分配数量必须为大于0"); return false; } - } - else - { + } else { $("#bid_evaluation_num_span").text("匿评分配数量只能为数字"); return false; } - } - else - { + } else { return true; } } //点击是否开启匿评单选框效果 -$(function(){ - $("#bid_open_anonymous_evaluation").click(function(){ - if($("#bid_open_anonymous_evaluation").attr("checked") == "checked") - { +$(function() { + $("#bid_open_anonymous_evaluation").click(function() { + if ($("#bid_open_anonymous_evaluation").attr("checked") == "checked") { $("#bid_evaluation_num_li").slideDown(); - } - else - { + } else { $("#bid_evaluation_num_li").slideUp(); } }); }); //老师提交新建作业 -function submit_new_bid(id) -{ - if(regex_bid_name()&®ex_evaluation_num()) - { +function submit_new_bid(id) { + if (regex_bid_name() && regex_evaluation_num()) { bid_description_editor.sync(); - $("#"+id).submit(); + $("#" + id).submit(); } } -function show_window (id1,id2,top,left) { - $('#'+ id1).css('top',top); - $('#'+ id1).css('left',left); - $('#'+ id1).css('display','block'); - $('#' + id2).css('display','block'); +function show_window(id1, id2, top, left) { + $('#' + id1).css('top', top); + $('#' + id1).css('left', left); + $('#' + id1).css('display', 'block'); + $('#' + id2).css('display', 'block'); } -function close_window(id1,id2){ - $('#' + id1).css('display','none'); - $('#' + id2).css('display','none'); +function close_window(id1, id2) { + $('#' + id1).css('display', 'none'); + $('#' + id2).css('display', 'none'); } //隐藏提示狂 -function hidden_atert_form(cur_page,cur_type) -{ +function hidden_atert_form(cur_page, cur_type) { hideModal($("#popbox")); } //当课程描述长度小于112px时,不显示更多按钮 -$(function(){ - if($("#course_description_content").height()>112) - { +$(function() { + if ($("#course_description_content").height() > 112) { $("#lg-foot").show(); } }); //将右侧的最小高度设置成左侧高度,美化界面 // firefox pre标签换行 -$(document).ready(function () { - $("#RSide").css("min-height",$("#LSide").height()-30); +$(document).ready(function() { + $("#RSide").css("min-height", $("#LSide").height() - 30); var userAgent = navigator.userAgent.toLowerCase(); var browser = { version: (userAgent.match(/.+(?:rv|it|ra|ie)[/: ]([d.]+)/) || [])[1], @@ -494,50 +415,55 @@ $(document).ready(function () { msie: /msie/.test(userAgent) && !/opera/.test(userAgent), mozilla: /mozilla/.test(userAgent) && !/(compatible|webkit)/.test(userAgent) }; - if (browser.mozilla || browser.opera){ + if (browser.mozilla || browser.opera) { $("pre").addClass("break_word_firefox"); - } - else{ + } else { $("pre").addClass("break_word"); } }); // 日历选择日期后关闭 -function regexDeadLine() -{ +function regexDeadLine() { ('#ui-datepicker-div').hide; } //新建、修改课程明码显示 -$(function(){ +$(function() { $("#psw_btn").click(function() { - alert("密码: "+$("#course_course_password").val()); + alert("密码: " + $("#course_course_password").val()); }); }); //课程通知更多按钮显示 -$(function(){ - $('.news_description').each(function () { - if($(this).height() >= 38) - { - $('#news_foot_'+$(this).attr('id').replace('news_description_','')).css("display","block"); - } +$(function() { + $('.news_description').each(function() { + if ($(this).height() >= 38) { + $('#news_foot_' + $(this).attr('id').replace('news_description_', '')).css("display", "block"); + } + }); + + $(".news_description img").one('load', function() { + var node = $(this).parents('.news_description'); + if (node && node.height() >= 38) { + $('#news_foot_' + node.attr('id').replace('news_description_', '')).css("display", "block"); + } + }).each(function() { + if (this.complete) { + $(this).load(); } - ) + }); }); //查找TAG资源 -function search_tag_attachment(url,tag_name,q,course_id,sort) -{ +function search_tag_attachment(url, tag_name, q, course_id, sort) { //alert("111"); $.get( - url, - { + url, { tag_name: tag_name, q: q, - course_id:course_id + course_id: course_id }, - function (data) { + function(data) { } ); @@ -546,27 +472,22 @@ function search_tag_attachment(url,tag_name,q,course_id,sort) // 课程讨论区 function showhelpAndScrollToMessage(id, id1, count) { $('#' + id).toggle(); - if(cookieget("repositories_visiable") == "true") - { - cookiesave("repositories_visiable", false,'','',''); - } - else - { - cookiesave("repositories_visiable", true,'','',''); + if (cookieget("repositories_visiable") == "true") { + cookiesave("repositories_visiable", false, '', '', ''); + } else { + cookiesave("repositories_visiable", true, '', '', ''); } var information = $(id1); var val = information.attr("value"); - if(val=="show_help") - { - $(id1).text("收起回复(" + count + ")" ); + if (val == "show_help") { + $(id1).text("收起回复(" + count + ")"); information.attr("value", "hide_help"); - } - else - { + } else { $(id1).text("展开回复(" + count + ")"); information.attr("value", "show_help"); } } + function show_more_reply(contentid, id2, id3) { $(contentid).toggleClass("course_description_none"); var information = $(id2); @@ -576,10 +497,9 @@ function show_more_reply(contentid, id2, id3) { $(id2).text("[收起]"); information.attr("value", "hide_more"); arrow.attr("src", "/images/jiantouup.jpg") - } - else { + } else { $(id2).text("[展开]"); information.attr("value", "show_more"); arrow.attr("src", "/images/jiantou.jpg") } -} \ No newline at end of file +} diff --git a/public/javascripts/jq-upload/upload.js b/public/javascripts/jq-upload/upload.js index 985450648..71dbefc32 100644 --- a/public/javascripts/jq-upload/upload.js +++ b/public/javascripts/jq-upload/upload.js @@ -44,9 +44,18 @@ $(function() { }, done: function(e, data) { var imgSpan = jQuery('#avatar_image'); - imgSpan.attr({ - "src": data.result.text ? data.result.text() : data.result - }); + var result = data.result.text ? data.result.text() : data.result; + if(result){ + var o = JSON.parse(result); + if(o.status == 0){ + imgSpan.attr({ + "src": o.url + }); + } else { + alert(o.message); + } + } + } }); }); diff --git a/public/javascripts/project.js b/public/javascripts/project.js index 481755410..947520b28 100644 --- a/public/javascripts/project.js +++ b/public/javascripts/project.js @@ -219,6 +219,7 @@ function regexTitle() { } function regexDescription() { + project_news_description_editor.sync(); var name = $("#news_description").val(); if (name.length == 0) { $("#description_notice_span").text("描述不能为空"); @@ -426,10 +427,41 @@ $(function(){ cookiesave(personalized_expand_key,JSON.stringify(personalized_map)); target.toggle(timeout); } - $("*[nhtype='toggle4cookie']").click(function(){ + $("*[nhtype='toggle4cookie']").live('click',function(){ personalized_click($(this),500); }); personalized_init(); }); -//cookie记忆html区块 显示/隐藏 的代码 end \ No newline at end of file +//cookie记忆html区块 显示/隐藏 的代码 end + +// 新建项目的时候判断是否与我已有的项目重复 +function judgeprojectname(){ + $('#new_project').validate({ + errorPlacement: function(error, element){ + alert('error') + }, + success: function(label){ + alert('ok') + }, + onkeyup: false, + rules : { + name:{required : true, + remote : { + url : 'projects/judge_same_projectname', + type:'get', + dataType:'text', + data:{ + name : function(){ return $.trim( $("#name").val() ); } + }, + dataFilter:function( data ){ + if( data=='true')return false; else return true; + } + } + } + }, + messages : { + name:{required : "请填写项目名称!",remote:'您已新建过同名项目,请修改项目名称!'} + } + }); +} diff --git a/public/stylesheets/application.css b/public/stylesheets/application.css index 85ef3240a..5c586b757 100644 --- a/public/stylesheets/application.css +++ b/public/stylesheets/application.css @@ -2794,3 +2794,4 @@ div.repos_explain{ padding-bottom: 20px; } .upload_img img{max-width: 100%;} +#activity .upload_img img{width: 580px;} diff --git a/public/stylesheets/project.css b/public/stylesheets/project.css index d6bef6524..5a6d98fbe 100644 --- a/public/stylesheets/project.css +++ b/public/stylesheets/project.css @@ -330,6 +330,7 @@ a:hover.st_add{ color:#ff8e15;} .hwork_new{ color:#4c4c4c;} .c_red{ color:#F00;} .hwork_input{ border:1px solid #64bdd9; height:22px; width:555px; background:#fff; margin-bottom:10px; padding:5px;} +.hwork_input_news{ border:1px solid #64bdd9; height:22px; width:594px; background:#fff; margin-bottom:10px; padding:5px;} .hwork_input02{ border:1px solid #64bdd9; height:15px; width:120px; background:#fff; margin-bottom:10px; padding:5px;} .hwork_text{ border:1px solid #64bdd9; height:100px;width:555px; background:#fff; margin-left:5px; padding:5px; margin-bottom:10px;} .hwork_new ul li{ } diff --git a/public/stylesheets/public.css b/public/stylesheets/public.css index 586704d16..c8d18609f 100644 --- a/public/stylesheets/public.css +++ b/public/stylesheets/public.css @@ -93,6 +93,7 @@ h4{ font-size:14px; color:#3b3b3b;} .w520{ width:520px;} .w543{ width:543px;} .w557{ width:557px;} +.w576{ width:576px;} .w583{ width:583px;} .w350{ width:350px;} .w610{ width:610px;} @@ -286,7 +287,8 @@ html{ overflow-x:hidden;} .close_btn span { display:none;} .side_center .custom_service p { text-align:center; padding:6px 0; margin:0; vertical-align:middle;} .msgserver { margin-top:5px;} -.msgserver a { background:url(../images/sidebar_bg.png) no-repeat -119px -112px; padding-left:22px; height:21px; display:block; } +/*.msgserver a { background:url(../images/sidebar_bg.png) no-repeat -119px -112px; padding-left:22px; height:21px; display:block; }*/ +.msgserver a { padding-left:4px; height:21px; display:block; } .opnionText{box-shadow:none; width:122px; height:180px; border-color: #DFDFDF; background:#fff; color:#999; padding:3px; font-size:12px;overflow:auto; background-attachment:fixed;border-style:solid;} a.opnionButton{ display:block; background:#15bccf; width:130px; height:23px; margin-top:5px; text-align:center; padding-top:3px;} a:hover.opnionButton{background: #0fa9bb; } diff --git a/spec/factories/attachments.rb b/spec/factories/attachments.rb new file mode 100644 index 000000000..da8e787ed --- /dev/null +++ b/spec/factories/attachments.rb @@ -0,0 +1,10 @@ +#coding=utf-8 +# +FactoryGirl.define do + factory :attachment do + filename "11.gif" + filesize 296833 + digest "8a74e086d7716f89bc4fbac0606589c7" + disk_directory "2015/05" + end +end diff --git a/spec/factories/homeworks.rb b/spec/factories/homeworks.rb new file mode 100644 index 000000000..208255a8d --- /dev/null +++ b/spec/factories/homeworks.rb @@ -0,0 +1,17 @@ +#coding=utf-8 +# +#:author_id, :budget, :deadline, :name, :description, :homework_type, :password + +FactoryGirl.define do + factory :homework, class: Bid do + name "test homework" + budget 0 + deadline {(Time.now+1.days).strftime('%Y-%m-%d')} + description "description" + homework_type 3 + reward_type 3 + end + + factory :homework_attach, class: HomeworkAttach do + end +end diff --git a/spec/factories/users.rb b/spec/factories/users.rb index 2c695b920..4595aacc5 100644 --- a/spec/factories/users.rb +++ b/spec/factories/users.rb @@ -6,4 +6,12 @@ FactoryGirl.define do password "foobar111" password_confirmation "foobar111" end + + factory :student, class: User do + login "student" + mail "student@example.com" + password "foobar111" + password_confirmation "foobar111" + end + end diff --git a/spec/models/forum_observer_spec.rb b/spec/models/forum_observer_spec.rb deleted file mode 100644 index 76d68fafa..000000000 --- a/spec/models/forum_observer_spec.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'spec_helper' - -describe ForumObserver do - pending "add some examples to (or delete) #{__FILE__}" -end diff --git a/spec/models/memo_observer_spec.rb b/spec/models/memo_observer_spec.rb deleted file mode 100644 index 82603ba7a..000000000 --- a/spec/models/memo_observer_spec.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'spec_helper' - -describe MemoObserver do - pending "add some examples to (or delete) #{__FILE__}" -end diff --git a/spec/requests/avatar_request_spec.rb b/spec/requests/avatar_request_spec.rb new file mode 100644 index 000000000..da80e38bf --- /dev/null +++ b/spec/requests/avatar_request_spec.rb @@ -0,0 +1,15 @@ +require 'rails_helper' + +RSpec.describe "avatar request", type: :request do + describe "上传头像" do + let(:user){FactoryGirl.create(:user)} + + it "参数正确,可以成功上传头像" do + data = File.open("#{Rails.root}/spec/fixtures/test.jpg").read + binding.pry + post upload_avatar_path(source_type: 'User', source_id: user.id, filename: 'test.jpg') + expect(response).to have_http_status(:success) + expect(response.body).to include(/\/images\/avatars\/User\//) + end + end +end diff --git a/spec/requests/course_request_spec.rb b/spec/requests/course_request_spec.rb index d58df398e..feca37259 100644 --- a/spec/requests/course_request_spec.rb +++ b/spec/requests/course_request_spec.rb @@ -35,13 +35,53 @@ RSpec.describe "课程", :type => :request do context "修改课程图片" do include Rack::Test::Methods let(:avatar) {Rack::Test::UploadedFile.new("#{Rails.root}/spec/fixtures/test.jpg",'image/jpg')} + context "正常图片上传成功" do subject(:resp) {post upload_avatar_path(source_type: 'Course', source_id: course.id, format: :json),"avatar"=>{image: avatar}} it{ expect(subject).to be_ok } it{ expect(subject.body).not_to be_empty } + it "状态要为0" do + o = ActiveSupport::JSON.decode(subject.body) + expect(o["status"]).to eq(0) + end + it "要回传图片地址" do + o = ActiveSupport::JSON.decode(subject.body) + expect(o["url"]).not_to be_empty + end + end + + context "不是图片,上传失败" do + let(:invalid_avatar) {Rack::Test::UploadedFile.new("#{Rails.root}/spec/fixtures/hah.txt",'text/plain')} + before do + resp = post upload_avatar_path(source_type: 'Course', source_id: course.id, format: :json),"avatar"=>{image: invalid_avatar} + @o = ActiveSupport::JSON.decode(resp.body) + end + it "状态不为0" do + expect(@o["status"]).not_to eq(0) + end + it "要回传错误信息" do + expect(@o["message"]).to be_include("图片") + end + end + + context "文件过大,上传失败" do + before do + big_file = Rack::Test::UploadedFile.new("#{Rails.root}/spec/fixtures/test.jpg",'image/jpg') + allow(ActionDispatch::Http::UploadedFile).to receive(:new).and_return(double('BigFile',size: 10*1024*1024, original_filename: 'rais.jpg', tempfile: nil)) + # trace = TracePoint.new(:call) do |tp| + # p [tp.lineno, tp.defined_class, tp.method_id, tp.event] if tp.method_id == :post + # end + resp = post upload_avatar_path(source_type: 'Course', source_id: course.id, format: :json),'avatar[image]'=> big_file + @o = ActiveSupport::JSON.decode(resp.body) + end + it "状态不为0" do + expect(@o["status"]).not_to eq(0) + end + it "要回传错误信息" do + expect(@o["message"]).to be_include("大") + end end - it "不是图片,上传失败" end end diff --git a/spec/requests/homework_request_spec.rb b/spec/requests/homework_request_spec.rb new file mode 100644 index 000000000..05733a56d --- /dev/null +++ b/spec/requests/homework_request_spec.rb @@ -0,0 +1,52 @@ +require 'rails_helper' +require 'shared_account_spec' + +RSpec.describe "homework", type: :request do + include_context "create user" + let(:course) {FactoryGirl.create(:course, teacher: current_user)} + let(:homework){FactoryGirl.attributes_for(:homework)} + + before { + shared_register + } + describe "创建作业" do + before do + post calls_create_homework_path(course_id: course.id), { + bid: homework + } + @homework = assigns(:bid) + end + it "参数正确,可以成功创建作业" do + expect(response).to redirect_to(course_homework_url(course.id)) + end + it {expect(course.homeworks).to_not be_empty} + it {expect(@homework.acts).to_not be_empty} + it {expect(@homework.watchers).to_not be_empty} + it {expect(@homework.attachments).to_not be_empty} + end + + describe "删除作业" do + before do + shared_login + post calls_create_homework_path(course_id: course.id), { + bid: homework + } + @homework = assigns(:bid) + delete bids_homework_path(id: @homework.id) + end + it{expect(response).to redirect_to(course_homework_path(course.id))} + it "homework_for_courses应删除" do + expect(course.homeworks).to be_empty + end + it "相关活动也删除" do + expect(@homework.acts).to be_empty + end + it "watches 删除" do + expect(@homework.watchers).to be_empty + end + it "附件 删除" do + expect(@homework.attachments).to be_empty + end + end + +end diff --git a/spec/requests/zipdown_request_spec.rb b/spec/requests/zipdown_request_spec.rb index eb179f104..72831d26f 100644 --- a/spec/requests/zipdown_request_spec.rb +++ b/spec/requests/zipdown_request_spec.rb @@ -1,6 +1,40 @@ require 'rails_helper' +require 'shared_account_spec' +# "attachments"=>{"1"=>{"filename"=>"11.gif", "description"=>"", "is_public_checkbox"=>"1", "token"=>"33731.8a74e086d7716f89bc4fbac0606589c7"}} RSpec.describe "作业打包下载", :type => :request do + let(:student){FactoryGirl.create(:student)} describe "单独下载某学生作业" do + include_context "create user" + before { + FactoryGirl.create(:user) + shared_login + @homework = FactoryGirl.create(:homework, author_id: current_user.id) + + @attch = HomeworkAttach.new + @attch.bid_id = @homework.id + @attch.user_id = student.id + @attachment = Attachment.new(:file => File.open(File.join(Rails.root, "spec/fixtures/test.jpg"))) + @attachment.author = User.current + @attachment.container_type = 'HomeworkAttach' + @attachment.container_id = @attch.id + @attachment.filename = "test.jpg" + @attachment.save + params = {"1"=>{"filename" => "test.jpg", "description" =>"", + "is_public_checkbox"=>"1", + "token" => "#{@attachment.id}.#{@attachment.digest}" } + } + @attch.save_attachments(params) + @attch.name = "test.jpg" + @attch.save! + } + it "正常下载" do + uu = current_user + allow(uu).to receive(:admin?).and_return(true) + allow(User).to receive(:current).and_return(uu) + get zipdown_download_user_homework_path, {homework:@attch.id} + expect(response).to have_http_status(:success) + expect(response.content_type).to eq(Mime::Type.new("applcation/zip",:zip)) + end end end