From 89b9a5c09dbc269981b9ea5fc094d78cefd2d93a Mon Sep 17 00:00:00 2001
From: lizanle <491823689@qq.com>
Date: Sat, 15 Aug 2015 17:06:41 +0800
Subject: [PATCH 01/90] =?UTF-8?q?=E8=B5=84=E6=BA=90=E5=BA=93?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/controllers/users_controller.rb | 77 +++++++++++++++++-
app/helpers/application_helper.rb | 3 +-
app/helpers/users_helper.rb | 23 ++++++
app/models/user.rb | 9 ++-
app/views/layouts/base_users_new.html.erb | 12 +++
config/routes.rb | 7 ++
db/schema.rb | 10 +++
public/stylesheets/public.css | 65 ++++++++++++++++
public/stylesheets/public_new.css | 95 +++++++++++++++++++++++
9 files changed, 297 insertions(+), 4 deletions(-)
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 39a467d53..0b3302fae 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -46,7 +46,7 @@ class UsersController < ApplicationController
:user_homeworks, :destroy_membership, :user_activities, :user_projects, :user_newfeedback, :user_comments,
:watch_contests, :info, :watch_projects, :show_score, :topic_score_index, :project_score_index,
:activity_score_index, :influence_score_index, :score_index,:show_new_score, :topic_new_score_index, :project_new_score_index,
- :activity_new_score_index, :influence_new_score_index, :score_new_index,:user_projects_index,
+ :activity_new_score_index, :influence_new_score_index, :score_new_index,:user_projects_index,:user_resource,
:user_courses4show,:user_projects4show,:user_course_activities,:user_project_activities,:user_feedback4show,:user_visitorlist]
before_filter :auth_user_extension, only: :show
#before_filter :rest_user_score, only: :show
@@ -807,6 +807,27 @@ class UsersController < ApplicationController
end
end
+ # 上传用户资源
+ def user_resource_create
+ @user = User.find(params[:id])
+ #@user.save_attachments(params[:attachments],User.current)
+ # Container_type为Principal
+ Attachment.attach_filesex(@user, params[:attachments], params[:attachment_type])
+ @attachments = Attachment.where("author_id = #{params[:id]} and container_type in('Project','Principal','Course','Issue','Document','Message','News','StudentWorkScore','HomewCommon') ").order("created_on desc")
+ respond_to do |format|
+ format.js
+ end
+ end
+
+ # 删除用户资源
+ def user_resource_delete
+ Attachment.delete(params[:resource_id])
+ @attachments = Attachment.where("author_id = #{params[:id]} and container_type in('Project','Principal','Course','Issue','Document','Message','News','StudentWorkScore','HomewCommon') ").order("created_on desc")
+ respond_to do |format|
+ format.js
+ end
+ end
+
def destroy
@user.destroy
respond_to do |format|
@@ -1008,6 +1029,55 @@ class UsersController < ApplicationController
@user = User.find(params[:id])
end
+ # 资源库 分为全部 课程资源 项目资源 附件
+ def user_resource
+ #确定container_type
+ # @user = User.find(params[:id])
+ if(params[:type].nil? || params[:type] == "1") #全部
+ if User.current.id == params[:id]
+ @attachments = Attachment.where("author_id = #{params[:id]} and container_type in('Project','Principal','Course','Issue','Document','Message','News','StudentWorkScore','HomewCommon') ").order("created_on desc")
+ else
+ @attachments = Attachment.where("author_id = #{params[:id]} and is_public = 1 and container_type in('Project','Principal','Course','Issue','Document','Message','News','StudentWorkScore','HomewCommon') ").order("created_on desc")
+ end
+ elsif params[:type] == "2" #课程资源
+ if User.current.id == params[:id]
+ @attachments = Attachment.where("author_id = #{params[:id]} and container_type = 'Course'").order("created_on desc")
+ else
+ @attachments = Attachment.where("author_id = #{params[:id]} and is_public = 1 and container_type = 'Course' ").order("created_on desc")
+ end
+ elsif params[:type] == "3" #项目资源
+ if User.current.id == params[:id]
+ @attachments = Attachment.where("author_id = #{params[:id]} and container_type = 'Project'").order("created_on desc")
+ else
+ @attachments = Attachment.where("author_id = #{params[:id]} and is_public = 1 and container_type = 'Project' ").order("created_on desc")
+ end
+ elsif params[:type] == "4" #附件
+ if User.current.id == params[:id]
+ @attachments = Attachment.where("author_id = #{params[:id]} and container_type in('Project','Issue','Document','Message','News','StudentWorkScore','HomewCommon')").order("created_on desc")
+ else
+ @attachments = Attachment.where("author_id = #{params[:id]} and is_public = 1 and container_type in('Issue','Document','Message','News','StudentWorkScore','HomewCommon')").order("created_on desc")
+ end
+ end
+ @type = params[:type]
+ respond_to do |format|
+ format.js
+ format.html {render :layout => 'base_users_new'}
+ end
+ end
+
+ # 根据资源关键字进行搜索
+ def resource_search
+ search = params[:search].to_s.strip.downcase
+ if User.current.id == params[:id]
+ @attachments = Attachment.where("author_id = #{params[:id]} and container_type not in ('Version','PhoneAppVersion','StudentWork') and (filename like '%#{search}%') ").order("created_on desc")
+ else
+ @attachments = Attachment.where("author_id = #{params[:id]} and container_type not in ('Version','PhoneAppVersion','StudentWork') and is_public = 1 and (filename like '%#{search}%') ").order("created_on desc")
+ end
+ respond_to do |format|
+ format.js
+ end
+ end
+
private
def find_user
@@ -1021,7 +1091,7 @@ class UsersController < ApplicationController
render_404
end
- def setting_layout(default_base='base_users')
+ def setting_layout(default_base='base_users_new')
User.current.admin? ? default_base : default_base
end
@@ -1071,4 +1141,7 @@ class UsersController < ApplicationController
impl.save
end
end
+
+
+
end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 6ac3c234a..cdcb6fc4d 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -1852,7 +1852,8 @@ module ApplicationHelper
candown = true
elsif attachment.container.class.to_s=="StudentWork"
candown = true
-
+ elsif attachment.container.class.to_s == "User"
+ candown = (attachment.is_public == 1 || attachment.is_public == true || attachment.author_id == User.current.id)
elsif attachment.container_type == "Bid" && attachment.container && attachment.container.courses
course = attachment.container.courses.first
candown = User.current.member_of_course?(attachment.container.courses.first) || (course.is_public == 1 && attachment.is_public == 1)
diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb
index 49865d335..41458bc90 100644
--- a/app/helpers/users_helper.rb
+++ b/app/helpers/users_helper.rb
@@ -29,6 +29,29 @@ module UsersHelper
["#{l(:status_locked)} (#{user_count_by_status[3].to_i})", '3']], selected.to_s)
end
+ def get_resource_type type
+ case type
+ when 'Course'
+ '课程资源'
+ when 'Project'
+ '项目资源'
+ when 'Issue'
+ '缺陷附件'
+ when 'Message'
+ '讨论区附件'
+ when 'Document'
+ '文档附件'
+ when 'News'
+ '通知附件'
+ when 'HomewCommon'
+ '作业附件'
+ when 'StudentWorkScore'
+ '批改附件'
+ when 'Principal'
+ '用户资源'
+ end
+ end
+
def user_mail_notification_options(user)
user.valid_notification_options.collect {|o| [l(o.last), o.first]}
end
diff --git a/app/models/user.rb b/app/models/user.rb
index 1cd0675c8..4fae33185 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -150,7 +150,8 @@ class User < Principal
nil
}
-
+ acts_as_attachable :view_permission => :view_files,
+ :delete_permission => :manage_files
acts_as_customizable
############################added by william
acts_as_taggable
@@ -239,6 +240,12 @@ class User < Principal
self.user_extensions ||= UserExtensions.new
end
+ # User现在可以作为一个Container_type,而Attachment的Container方法会有一个Container.try(:project),
+ # 所以这里定义一个空方法,保证不报错
+ def project
+
+ end
+
def user_score_attr
self.user_score ||= UserScore.new
end
diff --git a/app/views/layouts/base_users_new.html.erb b/app/views/layouts/base_users_new.html.erb
index 09d437da4..f9f065e2a 100644
--- a/app/views/layouts/base_users_new.html.erb
+++ b/app/views/layouts/base_users_new.html.erb
@@ -146,6 +146,12 @@
(<%=@user.projects.count%>)
+
<%= link_to "留言",feedback_path(@user),:class => "f14 c_blue02"%>
diff --git a/config/routes.rb b/config/routes.rb
index cdcb1126c..79ee367bb 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -344,12 +344,18 @@ RedmineApp::Application.routes.draw do
match 'file_score_index', :to => 'projects#file_score_index', :via => [:get, :post]
match 'code_submit_score_index', :to => 'projects#code_submit_score_index', :via => [:get, :post]
match 'projects_topic_score_index', :to => 'projects#projects_topic_score_index', :via => [:get, :post]
+ get "user_resource"
+ post "resource_search"
+ post "user_resource_create"
+ post "user_resource_delete"
# end
end
end
match 'users/:id/user_newfeedback', :to => 'users#user_newfeedback', :via => :get, :as => "feedback"
match 'users/:id/user_projects', :to => 'users#user_projects', :via => :get
+
+
#end
match 'my/account', :via => [:get, :post]
match 'my/account/destroy', :to => 'my#destroy', :via => [:get, :post]
@@ -841,6 +847,7 @@ RedmineApp::Application.routes.draw do
match 'system_log/clear'
##ended by lizanle
+
resources :git_callback do
collection do
post 'post_update'
diff --git a/db/schema.rb b/db/schema.rb
index 30ca29d12..d9511818e 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -746,6 +746,16 @@ ActiveRecord::Schema.define(:version => 20150801034945) 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/public/stylesheets/public.css b/public/stylesheets/public.css
index 82b3f17aa..4cc859721 100644
--- a/public/stylesheets/public.css
+++ b/public/stylesheets/public.css
@@ -467,3 +467,68 @@ img,embed{max-width: 100%;}
/*.copyright{ width:390px; margin:0 auto;height:20px;line-height:20px;}*/
/*a.f_grey {color:#666666;}*/
/*a.f_grey:hover {color:#000000;}*/
+
+/*资源库*/
+.resources {width:730px; background-color:#ffffff; padding:10px;}
+.resourcesBanner {width:730px; height:40px; background-color:#eaeaea; margin-bottom:10px;}
+.bannerName {background:#64bdd9; color:#ffffff; height:40px; line-height:40px; width:90px; text-align:center; font-weight:normal; vertical-align:middle; font-size: 16px; float:left;}
+.resourcesSelect {width:40px; height:40px; float:right; position:relative;}
+.resourcesSelected {width:25px; height:20px;}
+.resourcesIcon {margin-top:15px; display:block; position:relative; background:url(../images/resource_icon_list.png) 0px 0px no-repeat; width:25px; height:20px;}
+.resourcesIcon:hover { background:url(../images/resource_icon_list.png) 0px -25px no-repeat;}
+.resourcesType {width:50px; background-color:#ffffff; float:left; list-style:none; position:absolute; border:1px solid #eaeaea; border-radius:5px; top:35px; padding:5px 10px; left:-30px; font-size:12px; color:#888888; display:none;}
+a.resourcesGrey {font-size:12px; color:#888888;}
+a.resourcesGrey:hover {font-size:12px; color:#15bccf;}
+.resourcesBanner ul li:hover ul.resourcesType {display:block;}
+ul li:hover ul {display:block;}
+.resourcesUploadBox {float:right; width:103px; height:34px; background-color:#64bdd9; line-height:34px; vertical-align:middle; text-align:center; margin-left:12px;}
+.uploadIcon {background:url(../images/resource_icon_list.png) -35px 10px no-repeat; float:left; display:block; width:30px; height:30px; margin-left:-3px;}
+a.uploadText {color:#ffffff; font-size:14px;}
+.resourcesSearchloadBox {border:1px solid #e6e6e6; width:225px; float:right; background-color:#ffffff;}
+.searchResource {border:none; outline:none; background-color:#ffffff; width:184px; height:32px; padding-left:10px; display:block; float:left;}
+.searchIcon{width:31px; height:32px; background-color:#ffffff; background:url(../images/resource_icon_list.png) -40px -15px no-repeat; display:block; float:left;}
+.resourcesSearchBanner {height:34px; margin-bottom:10px;}
+.resourcesListTab {width:730px; height:40px; background-color:#f6f6f6; border-bottom:1px solid #eaeaea; font-size:14px; color:#7a7a7a;}
+.resourcesListName {width:175px; height:40px; line-height:40px; text-align:center;}
+.resourcesListSize {width:110px; height:40px; line-height:40px; text-align:center;}
+.resourcesListType {width:150px; height:40px; line-height:40px; text-align:center;}
+.resourcesListUploader {width:130px; height:40px; line-height:40px; text-align:center;}
+.resourcesListTime {width:165px; height:40px; line-height:40px; text-align:center;}
+.resourcesList {width:730px; height:39px; background-color:#ffffff; border-bottom:1px dashed #eaeaea; color:#9a9a9a; font-size:12px;}
+a.resourcesBlack {font-size:12px; color:#4c4c4c;}
+a.resourcesBlack:hover {font-size:12px; color:#000000;}
+.dropdown-menu {
+ position: absolute;
+ top: 100%;
+ left: 0;
+ z-index: 1000;
+ display: none;
+ float: left;
+ min-width: 80px;
+ padding: 5px 0;
+ margin: 2px 0 0;
+ font-size: 12px;
+ text-align: left;
+ background-color: #fff;
+ -webkit-background-clip: padding-box;
+ background-clip: padding-box;
+ border: 1px solid #ccc;
+ border-radius: 4px;
+ -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
+ box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
+}
+.dropdown-menu > li > a {
+ display: block;
+ padding: 3px 20px;
+ clear: both;
+ font-weight: normal;
+ line-height: 1.5;
+ color:#616060;
+ white-space: nowrap;
+}
+.dropdown-menu > li > a:hover{
+ color: #ffffff;
+ text-decoration: none;
+ background-color: #64bdd9;
+ outline:none;
+}
diff --git a/public/stylesheets/public_new.css b/public/stylesheets/public_new.css
index 7389dff8a..684213f20 100644
--- a/public/stylesheets/public_new.css
+++ b/public/stylesheets/public_new.css
@@ -444,4 +444,99 @@ div.ke-statusbar{height:1px; border-top:none;}
/*.copyright{ width:390px; margin:0 auto;height:20px;line-height:20px;}*/
/*a.f_grey {color:#666666;}*/
/*a.f_grey:hover {color:#000000;}*/
+/*资源库*/
+.resources {width:730px; background-color:#ffffff; padding:10px;float: right}
+.resourcesBanner {width:730px; height:40px; background-color:#eaeaea; margin-bottom:10px;}
+.bannerName {background:#64bdd9; color:#ffffff; height:40px; line-height:40px; width:90px; text-align:center; font-weight:normal; vertical-align:middle; font-size: 16px; float:left;}
+.resourcesSelect {width:40px; height:40px; float:right; position:relative;}
+.resourcesSelected {width:25px; height:20px;}
+.resourcesIcon {margin-top:15px; display:block; position:relative; background:url(images/resource_icon_list.png) 0px 0px no-repeat; width:25px; height:20px;}
+.resourcesIcon:hover { background:url(images/resource_icon_list.png) 0px -25px no-repeat;}
+.resourcesType {width:50px; background-color:#ffffff; float:left; list-style:none; position:absolute; border:1px solid #eaeaea; border-radius:5px; top:35px; padding:5px 10px; left:-30px; font-size:12px; color:#888888; display:none;}
+a.resourcesGrey {font-size:12px; color:#888888;}
+a.resourcesGrey:hover {font-size:12px; color:#15bccf;}
+.resourcesBanner ul li:hover ul.resourcesType {display:block;}
+ul li:hover ul {display:block;}
+.resourcesUploadBox {float:right; width:103px; height:34px; background-color:#64bdd9; line-height:34px; vertical-align:middle; text-align:center; margin-left:12px;}
+.uploadIcon {background:url(images/resource_icon_list.png) -35px 10px no-repeat; float:left; display:block; width:30px; height:30px; margin-left:-3px;}
+a.uploadText {color:#ffffff; font-size:14px;}
+.resourcesSearchloadBox {border:1px solid #e6e6e6; width:225px; float:right; background-color:#ffffff;}
+.searchResource {border:none; outline:none; background-color:#ffffff; width:184px; height:32px; padding-left:10px; display:block; float:left;}
+.searchIcon{width:31px; height:32px; background-color:#ffffff; background:url(images/resource_icon_list.png) -40px -15px no-repeat; display:block; float:left;}
+.resourcesSearchBanner {height:34px; margin-bottom:10px;}
+.resourcesListTab {width:730px; height:40px; background-color:#f6f6f6; border-bottom:1px solid #eaeaea; font-size:14px; color:#7a7a7a;}
+.resourcesListName {width:175px; height:40px; line-height:40px; text-align:center;}
+.resourcesListSize {width:110px; height:40px; line-height:40px; text-align:center;}
+.resourcesListType {width:150px; height:40px; line-height:40px; text-align:center;}
+.resourcesListUploader {width:130px; height:40px; line-height:40px; text-align:center;}
+.resourcesListTime {width:165px; height:40px; line-height:40px; text-align:center;}
+.resourcesList {width:730px; height:39px; background-color:#ffffff; border-bottom:1px dashed #eaeaea; color:#9a9a9a; font-size:12px;}
+a.resourcesBlack {font-size:12px; color:#4c4c4c;white-space: nowrap;text-align: left}
+a.resourcesBlack:hover {font-size:12px; color:#000000;}
+.dropdown-menu {
+ position: absolute;
+ top: 100%;
+ left: 0;
+ z-index: 1000;
+ display: none;
+ float: left;
+ min-width: 80px;
+ padding: 5px 0;
+ margin: 2px 0 0;
+ font-size: 12px;
+ text-align: left;
+ background-color: #fff;
+ -webkit-background-clip: padding-box;
+ background-clip: padding-box;
+ border: 1px solid #ccc;
+ border-radius: 4px;
+ -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
+ box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
+}
+.dropdown-menu > li > a {
+ display: block;
+ padding: 3px 20px;
+ clear: both;
+ font-weight: normal;
+ line-height: 1.5;
+ color:#616060;
+ white-space: nowrap;
+}
+.dropdown-menu > li > a:hover{
+ color: #ffffff;
+ text-decoration: none;
+ background-color: #64bdd9;
+ outline:none;
+}
+
+/*上传资源弹窗*/
+.resourceUploadPopup {width:400px; height:auto; border:3px solid #15bccf; padding-left:16px; padding-bottom:16px; background-color:#ffffff; position:absolute; top:50%; left:50%; margin-left:-200px; z-index:1000;}
+.uploadDialogText {font-size:16px; color:#15bccf; line-height:16px; padding-top:20px; width:140px; display:inline-block;}
+.uploadBoxContainer {height:33px; line-height:33px; margin-top:10px; position:relative}
+.uploadBox {width:100px; height:33px; line-height:33px; text-align:center; vertical-align:middle; background-color:#64bdd9; border-radius:3px; float:left; margin-right:12px;}
+a.uploadIcon {background:url(images/resource_icon_list.png) 8px -60px no-repeat; width:100px; height:33px;}
+.chooseFile {color:#ffffff; display:block; margin-left:32px;}
+.uploadResourceIntr {width:250px; height:33px; float:left; line-height:33px; font-size:12px;}
+.uploadResourceName {width:250px; display:inline-block; line-height:15px; font-size:12px; color:#444444; margin-bottom:2px;}
+.uploadResourceIntr2 {width:250px; display:inline-block; line-height:15px; font-size:12px; color:#444444;}
+.uploadType {margin:10px 0; border:1px solid #e6e6e6; width:100px; height:30px; outline:none; font-size:12px; color:#888888;}
+.uploadKeyword {margin-bottom:10px; outline:none; border:1px solid #e6e6e6; height:30px; width:280px;}
+
+/*发送资源弹窗*/
+/*.resourceShareContainer {width:100%; height:100%; background:#666; filter:alpha(opacity=50); opacity:0.5; -moz-opacity:0.5; position:absolute; left:0; top:0; z-index:-999;}*/
+.resourceSharePopup {width:300px; height:auto; border:3px solid #15bccf; padding-left:16px; padding-bottom:16px; background-color:#ffffff; position:absolute; top:50%; left:50%; margin-left:-150px; z-index:1000;}
+.sendText {font-size:16px; color:#15bccf; line-height:16px; padding-top:20px; width:140px; display:inline-block;}
+.resourcePopupClose {width:20px; height:20px; display:inline-block; float:right;}
+.resourceClose {background:url(images/resource_icon_list.png) 0px -40px no-repeat; width:20px; height:20px; display:inline-block;}
+.resourcesSearchBox {border:1px solid #e6e6e6; width:225px; height:25px; background-color:#ffffff; margin-top:12px; margin-bottom:15px;}
+.searchResourcePopup {border:none; outline:none; background-color:#ffffff; width:184px; height:25px; padding-left:10px; display:inline-block; float:left;}
+.searchIconPopup{width:31px; height:25px; background-color:#ffffff; background:url(images/resource_icon_list.png) -40px -18px no-repeat; display:inline-block; float:left;}
+.courseSend {width:260px; height:15px; line-height:15px; margin-bottom:10px;}
+.courseSendCheckbox {padding:0px; margin:0px; width:12px; height:12px; margin-right:10px; display:inline-block; margin-top:2px;}
+.sendCourseName {font-size:12px; color:#5f6060;}
+.courseSendSubmit {width:50px; height:25px; line-height:25px; text-align:center; vertical-align:middle; background-color:#64bdd9; margin-right:25px; float:left;}
+.courseSendCancel {width:50px; height:25px; line-height:25px; text-align:center; vertical-align:middle; background-color:#c1c1c1; float:left}
+a.sendSourceText {font-size:14px; color:#ffffff;}
+input.sendSourceText {font-size:14px;color:#ffffff;background-color:#64bdd9;}
+
From 421f86cdafc167e97861abdec162d50ae50f1bf1 Mon Sep 17 00:00:00 2001
From: lizanle <491823689@qq.com>
Date: Sat, 15 Aug 2015 17:07:50 +0800
Subject: [PATCH 02/90] =?UTF-8?q?=E8=B5=84=E6=BA=90=E5=BA=93?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/views/users/_attachment_list.html.erb | 30 +
.../users/_resource_upload_popup.html.erb | 43 +
app/views/users/_resources_list.html.erb | 17 +
app/views/users/_upload_resource.html.erb | 53 +
app/views/users/resource_search.js.erb | 1 +
app/views/users/user_resource.html.erb | 177 ++
app/views/users/user_resource.js.erb | 1 +
app/views/users/user_resource_create.js.erb | 3 +
app/views/users/user_resource_delete.js.erb | 1 +
public/javascripts/bootstrap.js | 2363 +++++++++++++++++
public/javascripts/jquery-1.3.2.js | 19 +
public/javascripts/sidebar.js | 64 +
.../stylesheets/images/resourceSearch_03.png | Bin 0 -> 1405 bytes
.../stylesheets/images/resourceSelect_03.png | Bin 0 -> 1087 bytes
.../images/resourceSelected_03.png | Bin 0 -> 1057 bytes
.../stylesheets/images/resourceUplaod_03.png | Bin 0 -> 1056 bytes
.../stylesheets/images/resource_icon_list.png | Bin 0 -> 2476 bytes
17 files changed, 2772 insertions(+)
create mode 100644 app/views/users/_attachment_list.html.erb
create mode 100644 app/views/users/_resource_upload_popup.html.erb
create mode 100644 app/views/users/_resources_list.html.erb
create mode 100644 app/views/users/_upload_resource.html.erb
create mode 100644 app/views/users/resource_search.js.erb
create mode 100644 app/views/users/user_resource.html.erb
create mode 100644 app/views/users/user_resource.js.erb
create mode 100644 app/views/users/user_resource_create.js.erb
create mode 100644 app/views/users/user_resource_delete.js.erb
create mode 100644 public/javascripts/bootstrap.js
create mode 100644 public/javascripts/jquery-1.3.2.js
create mode 100644 public/javascripts/sidebar.js
create mode 100644 public/stylesheets/images/resourceSearch_03.png
create mode 100644 public/stylesheets/images/resourceSelect_03.png
create mode 100644 public/stylesheets/images/resourceSelected_03.png
create mode 100644 public/stylesheets/images/resourceUplaod_03.png
create mode 100644 public/stylesheets/images/resource_icon_list.png
diff --git a/app/views/users/_attachment_list.html.erb b/app/views/users/_attachment_list.html.erb
new file mode 100644
index 000000000..33e944498
--- /dev/null
+++ b/app/views/users/_attachment_list.html.erb
@@ -0,0 +1,30 @@
+
+
+
+
+ 选择文件
+<%= file_field_tag 'attachments[dummy][file]',
+ :id => '_file',
+ :class => ie8? ? '':'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'),
+ :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)
+ } %>
+
+
+
+
+
+
+<%#= number_to_human_size(Setting.attachment_max_size.to_i.kilobytes) %>
+
diff --git a/app/views/users/_resource_upload_popup.html.erb b/app/views/users/_resource_upload_popup.html.erb
new file mode 100644
index 000000000..27eebceec
--- /dev/null
+++ b/app/views/users/_resource_upload_popup.html.erb
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
diff --git a/app/views/users/_resources_list.html.erb b/app/views/users/_resources_list.html.erb
new file mode 100644
index 000000000..078ee2c94
--- /dev/null
+++ b/app/views/users/_resources_list.html.erb
@@ -0,0 +1,17 @@
+<% if attachments.nil? || attachments.empty? %>
+<% else %>
+ <% attachments.each do |attach| %>
+
+
+
+ <%= link_to truncate(attach.filename,:length=>18), download_named_attachment_path(attach.id, attach.filename),
+ :title => attach.filename+"\n"+attach.description.to_s,:class=>'resourcesBlack'%>
+
+ <%= number_to_human_size(attach.filesize) %>
+ <%= get_resource_type(attach.container_type)%>
+ <%=User.find(attach.author_id).realname %>
+ <%= format_date(attach.created_on) %>
+ <%= attach.id %>
+
+ <% end %>
+<% end %>
\ No newline at end of file
diff --git a/app/views/users/_upload_resource.html.erb b/app/views/users/_upload_resource.html.erb
new file mode 100644
index 000000000..50807b080
--- /dev/null
+++ b/app/views/users/_upload_resource.html.erb
@@ -0,0 +1,53 @@
+
\ No newline at end of file
diff --git a/app/views/users/resource_search.js.erb b/app/views/users/resource_search.js.erb
new file mode 100644
index 000000000..69fc3dd43
--- /dev/null
+++ b/app/views/users/resource_search.js.erb
@@ -0,0 +1 @@
+$("#resources_list").html('<%= escape_javascript( render :partial => 'resources_list' ,:locals=>{ :attachments => @attachments})%>');
\ No newline at end of file
diff --git a/app/views/users/user_resource.html.erb b/app/views/users/user_resource.html.erb
new file mode 100644
index 000000000..aff14c2a3
--- /dev/null
+++ b/app/views/users/user_resource.html.erb
@@ -0,0 +1,177 @@
+
+<%= javascript_include_tag 'bootstrap'%>
+<%= stylesheet_link_tag 'project' %>
+<%= stylesheet_link_tag 'leftside' %>
+<%= javascript_include_tag 'attachments'%>
+
+
+
+
+
资源
+
+
+
+
+
+ <%= link_to '全部' ,user_resource_user_path(:id=>@user.id,:type=>1),:remote=>true,:method => 'get',:class=>'resourcesGrey' %>
+
+
+
+ <%= link_to '课程资源' ,user_resource_user_path(:id=>@user.id,:type=>2),:remote=>true,:method => 'get',:class=>'resourcesGrey' %>
+
+
+
+ <%= link_to '项目资源' ,user_resource_user_path(:id=>@user.id,:type=>3),:remote=>true,:method => 'get',:class=>'resourcesGrey' %>
+
+
+
+ <%= link_to '附件' ,user_resource_user_path(:id=>@user.id,:type=>4),:remote=>true,:method => 'get',:class=>'resourcesGrey' %>
+
+
+
+
+
+
+
+
+ <%= form_tag( url_for(:controller => 'users',:action => 'resource_search',:id=>@user.id),
+ :remote=>true ,:method => 'post',:class=>'resourcesSearchloadBox',:id=>'resource_search_form') do %>
+
+ <%= submit_tag '',:class=>'searchIcon',:style=>'border-style:none' %>
+
+ <% end %>
+
+
+
+
+ 资源名称
+ 大小
+ 类别
+ 上传者
+ 上传时间
+
+
+
+
+
+ <%= render :partial => 'resources_list' ,:locals=>{ :attachments => @attachments} %>
+
+
+
+
+ <%= render :partial => 'upload_resource' ,:locals => {:user=>@user}%>
+
+
+
+
+
diff --git a/app/views/users/user_resource.js.erb b/app/views/users/user_resource.js.erb
new file mode 100644
index 000000000..69fc3dd43
--- /dev/null
+++ b/app/views/users/user_resource.js.erb
@@ -0,0 +1 @@
+$("#resources_list").html('<%= escape_javascript( render :partial => 'resources_list' ,:locals=>{ :attachments => @attachments})%>');
\ No newline at end of file
diff --git a/app/views/users/user_resource_create.js.erb b/app/views/users/user_resource_create.js.erb
new file mode 100644
index 000000000..7e7cd2919
--- /dev/null
+++ b/app/views/users/user_resource_create.js.erb
@@ -0,0 +1,3 @@
+
+closeModal();
+$("#resources_list").html('<%= escape_javascript( render :partial => 'resources_list' ,:locals=>{ :attachments => @attachments})%>');
diff --git a/app/views/users/user_resource_delete.js.erb b/app/views/users/user_resource_delete.js.erb
new file mode 100644
index 000000000..69fc3dd43
--- /dev/null
+++ b/app/views/users/user_resource_delete.js.erb
@@ -0,0 +1 @@
+$("#resources_list").html('<%= escape_javascript( render :partial => 'resources_list' ,:locals=>{ :attachments => @attachments})%>');
\ No newline at end of file
diff --git a/public/javascripts/bootstrap.js b/public/javascripts/bootstrap.js
new file mode 100644
index 000000000..5debfd7de
--- /dev/null
+++ b/public/javascripts/bootstrap.js
@@ -0,0 +1,2363 @@
+/*!
+ * Bootstrap v3.3.5 (http://getbootstrap.com)
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under the MIT license
+ */
+
+if (typeof jQuery === 'undefined') {
+ throw new Error('Bootstrap\'s JavaScript requires jQuery')
+}
+
++function ($) {
+ 'use strict';
+ var version = $.fn.jquery.split(' ')[0].split('.')
+ if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1)) {
+ throw new Error('Bootstrap\'s JavaScript requires jQuery version 1.9.1 or higher')
+ }
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: transition.js v3.3.5
+ * http://getbootstrap.com/javascript/#transitions
+ * ========================================================================
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
+ // ============================================================
+
+ function transitionEnd() {
+ var el = document.createElement('bootstrap')
+
+ var transEndEventNames = {
+ WebkitTransition : 'webkitTransitionEnd',
+ MozTransition : 'transitionend',
+ OTransition : 'oTransitionEnd otransitionend',
+ transition : 'transitionend'
+ }
+
+ for (var name in transEndEventNames) {
+ if (el.style[name] !== undefined) {
+ return { end: transEndEventNames[name] }
+ }
+ }
+
+ return false // explicit for ie8 ( ._.)
+ }
+
+ // http://blog.alexmaccaw.com/css-transitions
+ $.fn.emulateTransitionEnd = function (duration) {
+ var called = false
+ var $el = this
+ $(this).one('bsTransitionEnd', function () { called = true })
+ var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
+ setTimeout(callback, duration)
+ return this
+ }
+
+ $(function () {
+ $.support.transition = transitionEnd()
+
+ if (!$.support.transition) return
+
+ $.event.special.bsTransitionEnd = {
+ bindType: $.support.transition.end,
+ delegateType: $.support.transition.end,
+ handle: function (e) {
+ if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments)
+ }
+ }
+ })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: alert.js v3.3.5
+ * http://getbootstrap.com/javascript/#alerts
+ * ========================================================================
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // ALERT CLASS DEFINITION
+ // ======================
+
+ var dismiss = '[data-dismiss="alert"]'
+ var Alert = function (el) {
+ $(el).on('click', dismiss, this.close)
+ }
+
+ Alert.VERSION = '3.3.5'
+
+ Alert.TRANSITION_DURATION = 150
+
+ Alert.prototype.close = function (e) {
+ var $this = $(this)
+ var selector = $this.attr('data-target')
+
+ if (!selector) {
+ selector = $this.attr('href')
+ selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
+ }
+
+ var $parent = $(selector)
+
+ if (e) e.preventDefault()
+
+ if (!$parent.length) {
+ $parent = $this.closest('.alert')
+ }
+
+ $parent.trigger(e = $.Event('close.bs.alert'))
+
+ if (e.isDefaultPrevented()) return
+
+ $parent.removeClass('in')
+
+ function removeElement() {
+ // detach from parent, fire event then clean up data
+ $parent.detach().trigger('closed.bs.alert').remove()
+ }
+
+ $.support.transition && $parent.hasClass('fade') ?
+ $parent
+ .one('bsTransitionEnd', removeElement)
+ .emulateTransitionEnd(Alert.TRANSITION_DURATION) :
+ removeElement()
+ }
+
+
+ // ALERT PLUGIN DEFINITION
+ // =======================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.alert')
+
+ if (!data) $this.data('bs.alert', (data = new Alert(this)))
+ if (typeof option == 'string') data[option].call($this)
+ })
+ }
+
+ var old = $.fn.alert
+
+ $.fn.alert = Plugin
+ $.fn.alert.Constructor = Alert
+
+
+ // ALERT NO CONFLICT
+ // =================
+
+ $.fn.alert.noConflict = function () {
+ $.fn.alert = old
+ return this
+ }
+
+
+ // ALERT DATA-API
+ // ==============
+
+ $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: button.js v3.3.5
+ * http://getbootstrap.com/javascript/#buttons
+ * ========================================================================
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // BUTTON PUBLIC CLASS DEFINITION
+ // ==============================
+
+ var Button = function (element, options) {
+ this.$element = $(element)
+ this.options = $.extend({}, Button.DEFAULTS, options)
+ this.isLoading = false
+ }
+
+ Button.VERSION = '3.3.5'
+
+ Button.DEFAULTS = {
+ loadingText: 'loading...'
+ }
+
+ Button.prototype.setState = function (state) {
+ var d = 'disabled'
+ var $el = this.$element
+ var val = $el.is('input') ? 'val' : 'html'
+ var data = $el.data()
+
+ state += 'Text'
+
+ if (data.resetText == null) $el.data('resetText', $el[val]())
+
+ // push to event loop to allow forms to submit
+ setTimeout($.proxy(function () {
+ $el[val](data[state] == null ? this.options[state] : data[state])
+
+ if (state == 'loadingText') {
+ this.isLoading = true
+ $el.addClass(d).attr(d, d)
+ } else if (this.isLoading) {
+ this.isLoading = false
+ $el.removeClass(d).removeAttr(d)
+ }
+ }, this), 0)
+ }
+
+ Button.prototype.toggle = function () {
+ var changed = true
+ var $parent = this.$element.closest('[data-toggle="buttons"]')
+
+ if ($parent.length) {
+ var $input = this.$element.find('input')
+ if ($input.prop('type') == 'radio') {
+ if ($input.prop('checked')) changed = false
+ $parent.find('.active').removeClass('active')
+ this.$element.addClass('active')
+ } else if ($input.prop('type') == 'checkbox') {
+ if (($input.prop('checked')) !== this.$element.hasClass('active')) changed = false
+ this.$element.toggleClass('active')
+ }
+ $input.prop('checked', this.$element.hasClass('active'))
+ if (changed) $input.trigger('change')
+ } else {
+ this.$element.attr('aria-pressed', !this.$element.hasClass('active'))
+ this.$element.toggleClass('active')
+ }
+ }
+
+
+ // BUTTON PLUGIN DEFINITION
+ // ========================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.button')
+ var options = typeof option == 'object' && option
+
+ if (!data) $this.data('bs.button', (data = new Button(this, options)))
+
+ if (option == 'toggle') data.toggle()
+ else if (option) data.setState(option)
+ })
+ }
+
+ var old = $.fn.button
+
+ $.fn.button = Plugin
+ $.fn.button.Constructor = Button
+
+
+ // BUTTON NO CONFLICT
+ // ==================
+
+ $.fn.button.noConflict = function () {
+ $.fn.button = old
+ return this
+ }
+
+
+ // BUTTON DATA-API
+ // ===============
+
+ $(document)
+ .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) {
+ var $btn = $(e.target)
+ if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
+ Plugin.call($btn, 'toggle')
+ if (!($(e.target).is('input[type="radio"]') || $(e.target).is('input[type="checkbox"]'))) e.preventDefault()
+ })
+ .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) {
+ $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type))
+ })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: carousel.js v3.3.5
+ * http://getbootstrap.com/javascript/#carousel
+ * ========================================================================
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // CAROUSEL CLASS DEFINITION
+ // =========================
+
+ var Carousel = function (element, options) {
+ this.$element = $(element)
+ this.$indicators = this.$element.find('.carousel-indicators')
+ this.options = options
+ this.paused = null
+ this.sliding = null
+ this.interval = null
+ this.$active = null
+ this.$items = null
+
+ this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this))
+
+ this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element
+ .on('mouseenter.bs.carousel', $.proxy(this.pause, this))
+ .on('mouseleave.bs.carousel', $.proxy(this.cycle, this))
+ }
+
+ Carousel.VERSION = '3.3.5'
+
+ Carousel.TRANSITION_DURATION = 600
+
+ Carousel.DEFAULTS = {
+ interval: 5000,
+ pause: 'hover',
+ wrap: true,
+ keyboard: true
+ }
+
+ Carousel.prototype.keydown = function (e) {
+ if (/input|textarea/i.test(e.target.tagName)) return
+ switch (e.which) {
+ case 37: this.prev(); break
+ case 39: this.next(); break
+ default: return
+ }
+
+ e.preventDefault()
+ }
+
+ Carousel.prototype.cycle = function (e) {
+ e || (this.paused = false)
+
+ this.interval && clearInterval(this.interval)
+
+ this.options.interval
+ && !this.paused
+ && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))
+
+ return this
+ }
+
+ Carousel.prototype.getItemIndex = function (item) {
+ this.$items = item.parent().children('.item')
+ return this.$items.index(item || this.$active)
+ }
+
+ Carousel.prototype.getItemForDirection = function (direction, active) {
+ var activeIndex = this.getItemIndex(active)
+ var willWrap = (direction == 'prev' && activeIndex === 0)
+ || (direction == 'next' && activeIndex == (this.$items.length - 1))
+ if (willWrap && !this.options.wrap) return active
+ var delta = direction == 'prev' ? -1 : 1
+ var itemIndex = (activeIndex + delta) % this.$items.length
+ return this.$items.eq(itemIndex)
+ }
+
+ Carousel.prototype.to = function (pos) {
+ var that = this
+ var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active'))
+
+ if (pos > (this.$items.length - 1) || pos < 0) return
+
+ if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid"
+ if (activeIndex == pos) return this.pause().cycle()
+
+ return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos))
+ }
+
+ Carousel.prototype.pause = function (e) {
+ e || (this.paused = true)
+
+ if (this.$element.find('.next, .prev').length && $.support.transition) {
+ this.$element.trigger($.support.transition.end)
+ this.cycle(true)
+ }
+
+ this.interval = clearInterval(this.interval)
+
+ return this
+ }
+
+ Carousel.prototype.next = function () {
+ if (this.sliding) return
+ return this.slide('next')
+ }
+
+ Carousel.prototype.prev = function () {
+ if (this.sliding) return
+ return this.slide('prev')
+ }
+
+ Carousel.prototype.slide = function (type, next) {
+ var $active = this.$element.find('.item.active')
+ var $next = next || this.getItemForDirection(type, $active)
+ var isCycling = this.interval
+ var direction = type == 'next' ? 'left' : 'right'
+ var that = this
+
+ if ($next.hasClass('active')) return (this.sliding = false)
+
+ var relatedTarget = $next[0]
+ var slideEvent = $.Event('slide.bs.carousel', {
+ relatedTarget: relatedTarget,
+ direction: direction
+ })
+ this.$element.trigger(slideEvent)
+ if (slideEvent.isDefaultPrevented()) return
+
+ this.sliding = true
+
+ isCycling && this.pause()
+
+ if (this.$indicators.length) {
+ this.$indicators.find('.active').removeClass('active')
+ var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)])
+ $nextIndicator && $nextIndicator.addClass('active')
+ }
+
+ var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid"
+ if ($.support.transition && this.$element.hasClass('slide')) {
+ $next.addClass(type)
+ $next[0].offsetWidth // force reflow
+ $active.addClass(direction)
+ $next.addClass(direction)
+ $active
+ .one('bsTransitionEnd', function () {
+ $next.removeClass([type, direction].join(' ')).addClass('active')
+ $active.removeClass(['active', direction].join(' '))
+ that.sliding = false
+ setTimeout(function () {
+ that.$element.trigger(slidEvent)
+ }, 0)
+ })
+ .emulateTransitionEnd(Carousel.TRANSITION_DURATION)
+ } else {
+ $active.removeClass('active')
+ $next.addClass('active')
+ this.sliding = false
+ this.$element.trigger(slidEvent)
+ }
+
+ isCycling && this.cycle()
+
+ return this
+ }
+
+
+ // CAROUSEL PLUGIN DEFINITION
+ // ==========================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.carousel')
+ var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option)
+ var action = typeof option == 'string' ? option : options.slide
+
+ if (!data) $this.data('bs.carousel', (data = new Carousel(this, options)))
+ if (typeof option == 'number') data.to(option)
+ else if (action) data[action]()
+ else if (options.interval) data.pause().cycle()
+ })
+ }
+
+ var old = $.fn.carousel
+
+ $.fn.carousel = Plugin
+ $.fn.carousel.Constructor = Carousel
+
+
+ // CAROUSEL NO CONFLICT
+ // ====================
+
+ $.fn.carousel.noConflict = function () {
+ $.fn.carousel = old
+ return this
+ }
+
+
+ // CAROUSEL DATA-API
+ // =================
+
+ var clickHandler = function (e) {
+ var href
+ var $this = $(this)
+ var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7
+ if (!$target.hasClass('carousel')) return
+ var options = $.extend({}, $target.data(), $this.data())
+ var slideIndex = $this.attr('data-slide-to')
+ if (slideIndex) options.interval = false
+
+ Plugin.call($target, options)
+
+ if (slideIndex) {
+ $target.data('bs.carousel').to(slideIndex)
+ }
+
+ e.preventDefault()
+ }
+
+ $(document)
+ .on('click.bs.carousel.data-api', '[data-slide]', clickHandler)
+ .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler)
+
+ $(window).on('load', function () {
+ $('[data-ride="carousel"]').each(function () {
+ var $carousel = $(this)
+ Plugin.call($carousel, $carousel.data())
+ })
+ })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: collapse.js v3.3.5
+ * http://getbootstrap.com/javascript/#collapse
+ * ========================================================================
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // COLLAPSE PUBLIC CLASS DEFINITION
+ // ================================
+
+ var Collapse = function (element, options) {
+ this.$element = $(element)
+ this.options = $.extend({}, Collapse.DEFAULTS, options)
+ this.$trigger = $('[data-toggle="collapse"][href="#' + element.id + '"],' +
+ '[data-toggle="collapse"][data-target="#' + element.id + '"]')
+ this.transitioning = null
+
+ if (this.options.parent) {
+ this.$parent = this.getParent()
+ } else {
+ this.addAriaAndCollapsedClass(this.$element, this.$trigger)
+ }
+
+ if (this.options.toggle) this.toggle()
+ }
+
+ Collapse.VERSION = '3.3.5'
+
+ Collapse.TRANSITION_DURATION = 350
+
+ Collapse.DEFAULTS = {
+ toggle: true
+ }
+
+ Collapse.prototype.dimension = function () {
+ var hasWidth = this.$element.hasClass('width')
+ return hasWidth ? 'width' : 'height'
+ }
+
+ Collapse.prototype.show = function () {
+ if (this.transitioning || this.$element.hasClass('in')) return
+
+ var activesData
+ var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing')
+
+ if (actives && actives.length) {
+ activesData = actives.data('bs.collapse')
+ if (activesData && activesData.transitioning) return
+ }
+
+ var startEvent = $.Event('show.bs.collapse')
+ this.$element.trigger(startEvent)
+ if (startEvent.isDefaultPrevented()) return
+
+ if (actives && actives.length) {
+ Plugin.call(actives, 'hide')
+ activesData || actives.data('bs.collapse', null)
+ }
+
+ var dimension = this.dimension()
+
+ this.$element
+ .removeClass('collapse')
+ .addClass('collapsing')[dimension](0)
+ .attr('aria-expanded', true)
+
+ this.$trigger
+ .removeClass('collapsed')
+ .attr('aria-expanded', true)
+
+ this.transitioning = 1
+
+ var complete = function () {
+ this.$element
+ .removeClass('collapsing')
+ .addClass('collapse in')[dimension]('')
+ this.transitioning = 0
+ this.$element
+ .trigger('shown.bs.collapse')
+ }
+
+ if (!$.support.transition) return complete.call(this)
+
+ var scrollSize = $.camelCase(['scroll', dimension].join('-'))
+
+ this.$element
+ .one('bsTransitionEnd', $.proxy(complete, this))
+ .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize])
+ }
+
+ Collapse.prototype.hide = function () {
+ if (this.transitioning || !this.$element.hasClass('in')) return
+
+ var startEvent = $.Event('hide.bs.collapse')
+ this.$element.trigger(startEvent)
+ if (startEvent.isDefaultPrevented()) return
+
+ var dimension = this.dimension()
+
+ this.$element[dimension](this.$element[dimension]())[0].offsetHeight
+
+ this.$element
+ .addClass('collapsing')
+ .removeClass('collapse in')
+ .attr('aria-expanded', false)
+
+ this.$trigger
+ .addClass('collapsed')
+ .attr('aria-expanded', false)
+
+ this.transitioning = 1
+
+ var complete = function () {
+ this.transitioning = 0
+ this.$element
+ .removeClass('collapsing')
+ .addClass('collapse')
+ .trigger('hidden.bs.collapse')
+ }
+
+ if (!$.support.transition) return complete.call(this)
+
+ this.$element
+ [dimension](0)
+ .one('bsTransitionEnd', $.proxy(complete, this))
+ .emulateTransitionEnd(Collapse.TRANSITION_DURATION)
+ }
+
+ Collapse.prototype.toggle = function () {
+ this[this.$element.hasClass('in') ? 'hide' : 'show']()
+ }
+
+ Collapse.prototype.getParent = function () {
+ return $(this.options.parent)
+ .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]')
+ .each($.proxy(function (i, element) {
+ var $element = $(element)
+ this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element)
+ }, this))
+ .end()
+ }
+
+ Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) {
+ var isOpen = $element.hasClass('in')
+
+ $element.attr('aria-expanded', isOpen)
+ $trigger
+ .toggleClass('collapsed', !isOpen)
+ .attr('aria-expanded', isOpen)
+ }
+
+ function getTargetFromTrigger($trigger) {
+ var href
+ var target = $trigger.attr('data-target')
+ || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
+
+ return $(target)
+ }
+
+
+ // COLLAPSE PLUGIN DEFINITION
+ // ==========================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.collapse')
+ var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
+
+ if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false
+ if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ var old = $.fn.collapse
+
+ $.fn.collapse = Plugin
+ $.fn.collapse.Constructor = Collapse
+
+
+ // COLLAPSE NO CONFLICT
+ // ====================
+
+ $.fn.collapse.noConflict = function () {
+ $.fn.collapse = old
+ return this
+ }
+
+
+ // COLLAPSE DATA-API
+ // =================
+
+ $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
+ var $this = $(this)
+
+ if (!$this.attr('data-target')) e.preventDefault()
+
+ var $target = getTargetFromTrigger($this)
+ var data = $target.data('bs.collapse')
+ var option = data ? 'toggle' : $this.data()
+
+ Plugin.call($target, option)
+ })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: dropdown.js v3.3.5
+ * http://getbootstrap.com/javascript/#dropdowns
+ * ========================================================================
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // DROPDOWN CLASS DEFINITION
+ // =========================
+
+ var backdrop = '.dropdown-backdrop'
+ var toggle = '[data-toggle="dropdown"]'
+ var Dropdown = function (element) {
+ $(element).on('click.bs.dropdown', this.toggle)
+ }
+
+ Dropdown.VERSION = '3.3.5'
+
+ function getParent($this) {
+ var selector = $this.attr('data-target')
+
+ if (!selector) {
+ selector = $this.attr('href')
+ selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
+ }
+
+ var $parent = selector && $(selector)
+
+ return $parent && $parent.length ? $parent : $this.parent()
+ }
+
+ function clearMenus(e) {
+ if (e && e.which === 3) return
+ $(backdrop).remove()
+ $(toggle).each(function () {
+ var $this = $(this)
+ var $parent = getParent($this)
+ var relatedTarget = { relatedTarget: this }
+
+ if (!$parent.hasClass('open')) return
+
+ if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return
+
+ $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
+
+ if (e.isDefaultPrevented()) return
+
+ $this.attr('aria-expanded', 'false')
+ $parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)
+ })
+ }
+
+ Dropdown.prototype.toggle = function (e) {
+ var $this = $(this)
+
+ if ($this.is('.disabled, :disabled')) return
+
+ var $parent = getParent($this)
+ var isActive = $parent.hasClass('open')
+
+ clearMenus()
+
+ if (!isActive) {
+ if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
+ // if mobile we use a backdrop because click events don't delegate
+ $(document.createElement('div'))
+ .addClass('dropdown-backdrop')
+ .insertAfter($(this))
+ .on('click', clearMenus)
+ }
+
+ var relatedTarget = { relatedTarget: this }
+ $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
+
+ if (e.isDefaultPrevented()) return
+
+ $this
+ .trigger('focus')
+ .attr('aria-expanded', 'true')
+
+ $parent
+ .toggleClass('open')
+ .trigger('shown.bs.dropdown', relatedTarget)
+ }
+
+ return false
+ }
+
+ Dropdown.prototype.keydown = function (e) {
+ if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return
+
+ var $this = $(this)
+
+ e.preventDefault()
+ e.stopPropagation()
+
+ if ($this.is('.disabled, :disabled')) return
+
+ var $parent = getParent($this)
+ var isActive = $parent.hasClass('open')
+
+ if (!isActive && e.which != 27 || isActive && e.which == 27) {
+ if (e.which == 27) $parent.find(toggle).trigger('focus')
+ return $this.trigger('click')
+ }
+
+ var desc = ' li:not(.disabled):visible a'
+ var $items = $parent.find('.dropdown-menu' + desc)
+
+ if (!$items.length) return
+
+ var index = $items.index(e.target)
+
+ if (e.which == 38 && index > 0) index-- // up
+ if (e.which == 40 && index < $items.length - 1) index++ // down
+ if (!~index) index = 0
+
+ $items.eq(index).trigger('focus')
+ }
+
+
+ // DROPDOWN PLUGIN DEFINITION
+ // ==========================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.dropdown')
+
+ if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))
+ if (typeof option == 'string') data[option].call($this)
+ })
+ }
+
+ var old = $.fn.dropdown
+
+ $.fn.dropdown = Plugin
+ $.fn.dropdown.Constructor = Dropdown
+
+
+ // DROPDOWN NO CONFLICT
+ // ====================
+
+ $.fn.dropdown.noConflict = function () {
+ $.fn.dropdown = old
+ return this
+ }
+
+
+ // APPLY TO STANDARD DROPDOWN ELEMENTS
+ // ===================================
+
+ $(document)
+ .on('click.bs.dropdown.data-api', clearMenus)
+ .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
+ .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
+ .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown)
+ .on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown)
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: modal.js v3.3.5
+ * http://getbootstrap.com/javascript/#modals
+ * ========================================================================
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // MODAL CLASS DEFINITION
+ // ======================
+
+ var Modal = function (element, options) {
+ this.options = options
+ this.$body = $(document.body)
+ this.$element = $(element)
+ this.$dialog = this.$element.find('.modal-dialog')
+ this.$backdrop = null
+ this.isShown = null
+ this.originalBodyPad = null
+ this.scrollbarWidth = 0
+ this.ignoreBackdropClick = false
+
+ if (this.options.remote) {
+ this.$element
+ .find('.modal-content')
+ .load(this.options.remote, $.proxy(function () {
+ this.$element.trigger('loaded.bs.modal')
+ }, this))
+ }
+ }
+
+ Modal.VERSION = '3.3.5'
+
+ Modal.TRANSITION_DURATION = 300
+ Modal.BACKDROP_TRANSITION_DURATION = 150
+
+ Modal.DEFAULTS = {
+ backdrop: true,
+ keyboard: true,
+ show: true
+ }
+
+ Modal.prototype.toggle = function (_relatedTarget) {
+ return this.isShown ? this.hide() : this.show(_relatedTarget)
+ }
+
+ Modal.prototype.show = function (_relatedTarget) {
+ var that = this
+ var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
+
+ this.$element.trigger(e)
+
+ if (this.isShown || e.isDefaultPrevented()) return
+
+ this.isShown = true
+
+ this.checkScrollbar()
+ this.setScrollbar()
+ this.$body.addClass('modal-open')
+
+ this.escape()
+ this.resize()
+
+ this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
+
+ this.$dialog.on('mousedown.dismiss.bs.modal', function () {
+ that.$element.one('mouseup.dismiss.bs.modal', function (e) {
+ if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true
+ })
+ })
+
+ this.backdrop(function () {
+ var transition = $.support.transition && that.$element.hasClass('fade')
+
+ if (!that.$element.parent().length) {
+ that.$element.appendTo(that.$body) // don't move modals dom position
+ }
+
+ that.$element
+ .show()
+ .scrollTop(0)
+
+ that.adjustDialog()
+
+ if (transition) {
+ that.$element[0].offsetWidth // force reflow
+ }
+
+ that.$element.addClass('in')
+
+ that.enforceFocus()
+
+ var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
+
+ transition ?
+ that.$dialog // wait for modal to slide in
+ .one('bsTransitionEnd', function () {
+ that.$element.trigger('focus').trigger(e)
+ })
+ .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
+ that.$element.trigger('focus').trigger(e)
+ })
+ }
+
+ Modal.prototype.hide = function (e) {
+ if (e) e.preventDefault()
+
+ e = $.Event('hide.bs.modal')
+
+ this.$element.trigger(e)
+
+ if (!this.isShown || e.isDefaultPrevented()) return
+
+ this.isShown = false
+
+ this.escape()
+ this.resize()
+
+ $(document).off('focusin.bs.modal')
+
+ this.$element
+ .removeClass('in')
+ .off('click.dismiss.bs.modal')
+ .off('mouseup.dismiss.bs.modal')
+
+ this.$dialog.off('mousedown.dismiss.bs.modal')
+
+ $.support.transition && this.$element.hasClass('fade') ?
+ this.$element
+ .one('bsTransitionEnd', $.proxy(this.hideModal, this))
+ .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
+ this.hideModal()
+ }
+
+ Modal.prototype.enforceFocus = function () {
+ $(document)
+ .off('focusin.bs.modal') // guard against infinite focus loop
+ .on('focusin.bs.modal', $.proxy(function (e) {
+ if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {
+ this.$element.trigger('focus')
+ }
+ }, this))
+ }
+
+ Modal.prototype.escape = function () {
+ if (this.isShown && this.options.keyboard) {
+ this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) {
+ e.which == 27 && this.hide()
+ }, this))
+ } else if (!this.isShown) {
+ this.$element.off('keydown.dismiss.bs.modal')
+ }
+ }
+
+ Modal.prototype.resize = function () {
+ if (this.isShown) {
+ $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this))
+ } else {
+ $(window).off('resize.bs.modal')
+ }
+ }
+
+ Modal.prototype.hideModal = function () {
+ var that = this
+ this.$element.hide()
+ this.backdrop(function () {
+ that.$body.removeClass('modal-open')
+ that.resetAdjustments()
+ that.resetScrollbar()
+ that.$element.trigger('hidden.bs.modal')
+ })
+ }
+
+ Modal.prototype.removeBackdrop = function () {
+ this.$backdrop && this.$backdrop.remove()
+ this.$backdrop = null
+ }
+
+ Modal.prototype.backdrop = function (callback) {
+ var that = this
+ var animate = this.$element.hasClass('fade') ? 'fade' : ''
+
+ if (this.isShown && this.options.backdrop) {
+ var doAnimate = $.support.transition && animate
+
+ this.$backdrop = $(document.createElement('div'))
+ .addClass('modal-backdrop ' + animate)
+ .appendTo(this.$body)
+
+ this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) {
+ if (this.ignoreBackdropClick) {
+ this.ignoreBackdropClick = false
+ return
+ }
+ if (e.target !== e.currentTarget) return
+ this.options.backdrop == 'static'
+ ? this.$element[0].focus()
+ : this.hide()
+ }, this))
+
+ if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
+
+ this.$backdrop.addClass('in')
+
+ if (!callback) return
+
+ doAnimate ?
+ this.$backdrop
+ .one('bsTransitionEnd', callback)
+ .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
+ callback()
+
+ } else if (!this.isShown && this.$backdrop) {
+ this.$backdrop.removeClass('in')
+
+ var callbackRemove = function () {
+ that.removeBackdrop()
+ callback && callback()
+ }
+ $.support.transition && this.$element.hasClass('fade') ?
+ this.$backdrop
+ .one('bsTransitionEnd', callbackRemove)
+ .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
+ callbackRemove()
+
+ } else if (callback) {
+ callback()
+ }
+ }
+
+ // these following methods are used to handle overflowing modals
+
+ Modal.prototype.handleUpdate = function () {
+ this.adjustDialog()
+ }
+
+ Modal.prototype.adjustDialog = function () {
+ var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight
+
+ this.$element.css({
+ paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '',
+ paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : ''
+ })
+ }
+
+ Modal.prototype.resetAdjustments = function () {
+ this.$element.css({
+ paddingLeft: '',
+ paddingRight: ''
+ })
+ }
+
+ Modal.prototype.checkScrollbar = function () {
+ var fullWindowWidth = window.innerWidth
+ if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8
+ var documentElementRect = document.documentElement.getBoundingClientRect()
+ fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left)
+ }
+ this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth
+ this.scrollbarWidth = this.measureScrollbar()
+ }
+
+ Modal.prototype.setScrollbar = function () {
+ var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
+ this.originalBodyPad = document.body.style.paddingRight || ''
+ if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)
+ }
+
+ Modal.prototype.resetScrollbar = function () {
+ this.$body.css('padding-right', this.originalBodyPad)
+ }
+
+ Modal.prototype.measureScrollbar = function () { // thx walsh
+ var scrollDiv = document.createElement('div')
+ scrollDiv.className = 'modal-scrollbar-measure'
+ this.$body.append(scrollDiv)
+ var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
+ this.$body[0].removeChild(scrollDiv)
+ return scrollbarWidth
+ }
+
+
+ // MODAL PLUGIN DEFINITION
+ // =======================
+
+ function Plugin(option, _relatedTarget) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.modal')
+ var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
+
+ if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
+ if (typeof option == 'string') data[option](_relatedTarget)
+ else if (options.show) data.show(_relatedTarget)
+ })
+ }
+
+ var old = $.fn.modal
+
+ $.fn.modal = Plugin
+ $.fn.modal.Constructor = Modal
+
+
+ // MODAL NO CONFLICT
+ // =================
+
+ $.fn.modal.noConflict = function () {
+ $.fn.modal = old
+ return this
+ }
+
+
+ // MODAL DATA-API
+ // ==============
+
+ $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
+ var $this = $(this)
+ var href = $this.attr('href')
+ var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7
+ var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
+
+ if ($this.is('a')) e.preventDefault()
+
+ $target.one('show.bs.modal', function (showEvent) {
+ if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown
+ $target.one('hidden.bs.modal', function () {
+ $this.is(':visible') && $this.trigger('focus')
+ })
+ })
+ Plugin.call($target, option, this)
+ })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: tooltip.js v3.3.5
+ * http://getbootstrap.com/javascript/#tooltip
+ * Inspired by the original jQuery.tipsy by Jason Frame
+ * ========================================================================
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // TOOLTIP PUBLIC CLASS DEFINITION
+ // ===============================
+
+ var Tooltip = function (element, options) {
+ this.type = null
+ this.options = null
+ this.enabled = null
+ this.timeout = null
+ this.hoverState = null
+ this.$element = null
+ this.inState = null
+
+ this.init('tooltip', element, options)
+ }
+
+ Tooltip.VERSION = '3.3.5'
+
+ Tooltip.TRANSITION_DURATION = 150
+
+ Tooltip.DEFAULTS = {
+ animation: true,
+ placement: 'top',
+ selector: false,
+ template: '
',
+ trigger: 'hover focus',
+ title: '',
+ delay: 0,
+ html: false,
+ container: false,
+ viewport: {
+ selector: 'body',
+ padding: 0
+ }
+ }
+
+ Tooltip.prototype.init = function (type, element, options) {
+ this.enabled = true
+ this.type = type
+ this.$element = $(element)
+ this.options = this.getOptions(options)
+ this.$viewport = this.options.viewport && $($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport))
+ this.inState = { click: false, hover: false, focus: false }
+
+ if (this.$element[0] instanceof document.constructor && !this.options.selector) {
+ throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!')
+ }
+
+ var triggers = this.options.trigger.split(' ')
+
+ for (var i = triggers.length; i--;) {
+ var trigger = triggers[i]
+
+ if (trigger == 'click') {
+ this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
+ } else if (trigger != 'manual') {
+ var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin'
+ var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
+
+ this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
+ this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
+ }
+ }
+
+ this.options.selector ?
+ (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
+ this.fixTitle()
+ }
+
+ Tooltip.prototype.getDefaults = function () {
+ return Tooltip.DEFAULTS
+ }
+
+ Tooltip.prototype.getOptions = function (options) {
+ options = $.extend({}, this.getDefaults(), this.$element.data(), options)
+
+ if (options.delay && typeof options.delay == 'number') {
+ options.delay = {
+ show: options.delay,
+ hide: options.delay
+ }
+ }
+
+ return options
+ }
+
+ Tooltip.prototype.getDelegateOptions = function () {
+ var options = {}
+ var defaults = this.getDefaults()
+
+ this._options && $.each(this._options, function (key, value) {
+ if (defaults[key] != value) options[key] = value
+ })
+
+ return options
+ }
+
+ Tooltip.prototype.enter = function (obj) {
+ var self = obj instanceof this.constructor ?
+ obj : $(obj.currentTarget).data('bs.' + this.type)
+
+ if (!self) {
+ self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
+ $(obj.currentTarget).data('bs.' + this.type, self)
+ }
+
+ if (obj instanceof $.Event) {
+ self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true
+ }
+
+ if (self.tip().hasClass('in') || self.hoverState == 'in') {
+ self.hoverState = 'in'
+ return
+ }
+
+ clearTimeout(self.timeout)
+
+ self.hoverState = 'in'
+
+ if (!self.options.delay || !self.options.delay.show) return self.show()
+
+ self.timeout = setTimeout(function () {
+ if (self.hoverState == 'in') self.show()
+ }, self.options.delay.show)
+ }
+
+ Tooltip.prototype.isInStateTrue = function () {
+ for (var key in this.inState) {
+ if (this.inState[key]) return true
+ }
+
+ return false
+ }
+
+ Tooltip.prototype.leave = function (obj) {
+ var self = obj instanceof this.constructor ?
+ obj : $(obj.currentTarget).data('bs.' + this.type)
+
+ if (!self) {
+ self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
+ $(obj.currentTarget).data('bs.' + this.type, self)
+ }
+
+ if (obj instanceof $.Event) {
+ self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false
+ }
+
+ if (self.isInStateTrue()) return
+
+ clearTimeout(self.timeout)
+
+ self.hoverState = 'out'
+
+ if (!self.options.delay || !self.options.delay.hide) return self.hide()
+
+ self.timeout = setTimeout(function () {
+ if (self.hoverState == 'out') self.hide()
+ }, self.options.delay.hide)
+ }
+
+ Tooltip.prototype.show = function () {
+ var e = $.Event('show.bs.' + this.type)
+
+ if (this.hasContent() && this.enabled) {
+ this.$element.trigger(e)
+
+ var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
+ if (e.isDefaultPrevented() || !inDom) return
+ var that = this
+
+ var $tip = this.tip()
+
+ var tipId = this.getUID(this.type)
+
+ this.setContent()
+ $tip.attr('id', tipId)
+ this.$element.attr('aria-describedby', tipId)
+
+ if (this.options.animation) $tip.addClass('fade')
+
+ var placement = typeof this.options.placement == 'function' ?
+ this.options.placement.call(this, $tip[0], this.$element[0]) :
+ this.options.placement
+
+ var autoToken = /\s?auto?\s?/i
+ var autoPlace = autoToken.test(placement)
+ if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
+
+ $tip
+ .detach()
+ .css({ top: 0, left: 0, display: 'block' })
+ .addClass(placement)
+ .data('bs.' + this.type, this)
+
+ this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
+ this.$element.trigger('inserted.bs.' + this.type)
+
+ var pos = this.getPosition()
+ var actualWidth = $tip[0].offsetWidth
+ var actualHeight = $tip[0].offsetHeight
+
+ if (autoPlace) {
+ var orgPlacement = placement
+ var viewportDim = this.getPosition(this.$viewport)
+
+ placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top' :
+ placement == 'top' && pos.top - actualHeight < viewportDim.top ? 'bottom' :
+ placement == 'right' && pos.right + actualWidth > viewportDim.width ? 'left' :
+ placement == 'left' && pos.left - actualWidth < viewportDim.left ? 'right' :
+ placement
+
+ $tip
+ .removeClass(orgPlacement)
+ .addClass(placement)
+ }
+
+ var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
+
+ this.applyPlacement(calculatedOffset, placement)
+
+ var complete = function () {
+ var prevHoverState = that.hoverState
+ that.$element.trigger('shown.bs.' + that.type)
+ that.hoverState = null
+
+ if (prevHoverState == 'out') that.leave(that)
+ }
+
+ $.support.transition && this.$tip.hasClass('fade') ?
+ $tip
+ .one('bsTransitionEnd', complete)
+ .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
+ complete()
+ }
+ }
+
+ Tooltip.prototype.applyPlacement = function (offset, placement) {
+ var $tip = this.tip()
+ var width = $tip[0].offsetWidth
+ var height = $tip[0].offsetHeight
+
+ // manually read margins because getBoundingClientRect includes difference
+ var marginTop = parseInt($tip.css('margin-top'), 10)
+ var marginLeft = parseInt($tip.css('margin-left'), 10)
+
+ // we must check for NaN for ie 8/9
+ if (isNaN(marginTop)) marginTop = 0
+ if (isNaN(marginLeft)) marginLeft = 0
+
+ offset.top += marginTop
+ offset.left += marginLeft
+
+ // $.fn.offset doesn't round pixel values
+ // so we use setOffset directly with our own function B-0
+ $.offset.setOffset($tip[0], $.extend({
+ using: function (props) {
+ $tip.css({
+ top: Math.round(props.top),
+ left: Math.round(props.left)
+ })
+ }
+ }, offset), 0)
+
+ $tip.addClass('in')
+
+ // check to see if placing tip in new offset caused the tip to resize itself
+ var actualWidth = $tip[0].offsetWidth
+ var actualHeight = $tip[0].offsetHeight
+
+ if (placement == 'top' && actualHeight != height) {
+ offset.top = offset.top + height - actualHeight
+ }
+
+ var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
+
+ if (delta.left) offset.left += delta.left
+ else offset.top += delta.top
+
+ var isVertical = /top|bottom/.test(placement)
+ var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
+ var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'
+
+ $tip.offset(offset)
+ this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)
+ }
+
+ Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) {
+ this.arrow()
+ .css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')
+ .css(isVertical ? 'top' : 'left', '')
+ }
+
+ Tooltip.prototype.setContent = function () {
+ var $tip = this.tip()
+ var title = this.getTitle()
+
+ $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
+ $tip.removeClass('fade in top bottom left right')
+ }
+
+ Tooltip.prototype.hide = function (callback) {
+ var that = this
+ var $tip = $(this.$tip)
+ var e = $.Event('hide.bs.' + this.type)
+
+ function complete() {
+ if (that.hoverState != 'in') $tip.detach()
+ that.$element
+ .removeAttr('aria-describedby')
+ .trigger('hidden.bs.' + that.type)
+ callback && callback()
+ }
+
+ this.$element.trigger(e)
+
+ if (e.isDefaultPrevented()) return
+
+ $tip.removeClass('in')
+
+ $.support.transition && $tip.hasClass('fade') ?
+ $tip
+ .one('bsTransitionEnd', complete)
+ .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
+ complete()
+
+ this.hoverState = null
+
+ return this
+ }
+
+ Tooltip.prototype.fixTitle = function () {
+ var $e = this.$element
+ if ($e.attr('title') || typeof $e.attr('data-original-title') != 'string') {
+ $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
+ }
+ }
+
+ Tooltip.prototype.hasContent = function () {
+ return this.getTitle()
+ }
+
+ Tooltip.prototype.getPosition = function ($element) {
+ $element = $element || this.$element
+
+ var el = $element[0]
+ var isBody = el.tagName == 'BODY'
+
+ var elRect = el.getBoundingClientRect()
+ if (elRect.width == null) {
+ // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
+ elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })
+ }
+ var elOffset = isBody ? { top: 0, left: 0 } : $element.offset()
+ var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
+ var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null
+
+ return $.extend({}, elRect, scroll, outerDims, elOffset)
+ }
+
+ Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
+ return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } :
+ placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
+ placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
+ /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
+
+ }
+
+ Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
+ var delta = { top: 0, left: 0 }
+ if (!this.$viewport) return delta
+
+ var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
+ var viewportDimensions = this.getPosition(this.$viewport)
+
+ if (/right|left/.test(placement)) {
+ var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll
+ var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
+ if (topEdgeOffset < viewportDimensions.top) { // top overflow
+ delta.top = viewportDimensions.top - topEdgeOffset
+ } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
+ delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset
+ }
+ } else {
+ var leftEdgeOffset = pos.left - viewportPadding
+ var rightEdgeOffset = pos.left + viewportPadding + actualWidth
+ if (leftEdgeOffset < viewportDimensions.left) { // left overflow
+ delta.left = viewportDimensions.left - leftEdgeOffset
+ } else if (rightEdgeOffset > viewportDimensions.right) { // right overflow
+ delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
+ }
+ }
+
+ return delta
+ }
+
+ Tooltip.prototype.getTitle = function () {
+ var title
+ var $e = this.$element
+ var o = this.options
+
+ title = $e.attr('data-original-title')
+ || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
+
+ return title
+ }
+
+ Tooltip.prototype.getUID = function (prefix) {
+ do prefix += ~~(Math.random() * 1000000)
+ while (document.getElementById(prefix))
+ return prefix
+ }
+
+ Tooltip.prototype.tip = function () {
+ if (!this.$tip) {
+ this.$tip = $(this.options.template)
+ if (this.$tip.length != 1) {
+ throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!')
+ }
+ }
+ return this.$tip
+ }
+
+ Tooltip.prototype.arrow = function () {
+ return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
+ }
+
+ Tooltip.prototype.enable = function () {
+ this.enabled = true
+ }
+
+ Tooltip.prototype.disable = function () {
+ this.enabled = false
+ }
+
+ Tooltip.prototype.toggleEnabled = function () {
+ this.enabled = !this.enabled
+ }
+
+ Tooltip.prototype.toggle = function (e) {
+ var self = this
+ if (e) {
+ self = $(e.currentTarget).data('bs.' + this.type)
+ if (!self) {
+ self = new this.constructor(e.currentTarget, this.getDelegateOptions())
+ $(e.currentTarget).data('bs.' + this.type, self)
+ }
+ }
+
+ if (e) {
+ self.inState.click = !self.inState.click
+ if (self.isInStateTrue()) self.enter(self)
+ else self.leave(self)
+ } else {
+ self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
+ }
+ }
+
+ Tooltip.prototype.destroy = function () {
+ var that = this
+ clearTimeout(this.timeout)
+ this.hide(function () {
+ that.$element.off('.' + that.type).removeData('bs.' + that.type)
+ if (that.$tip) {
+ that.$tip.detach()
+ }
+ that.$tip = null
+ that.$arrow = null
+ that.$viewport = null
+ })
+ }
+
+
+ // TOOLTIP PLUGIN DEFINITION
+ // =========================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.tooltip')
+ var options = typeof option == 'object' && option
+
+ if (!data && /destroy|hide/.test(option)) return
+ if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ var old = $.fn.tooltip
+
+ $.fn.tooltip = Plugin
+ $.fn.tooltip.Constructor = Tooltip
+
+
+ // TOOLTIP NO CONFLICT
+ // ===================
+
+ $.fn.tooltip.noConflict = function () {
+ $.fn.tooltip = old
+ return this
+ }
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: popover.js v3.3.5
+ * http://getbootstrap.com/javascript/#popovers
+ * ========================================================================
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // POPOVER PUBLIC CLASS DEFINITION
+ // ===============================
+
+ var Popover = function (element, options) {
+ this.init('popover', element, options)
+ }
+
+ if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
+
+ Popover.VERSION = '3.3.5'
+
+ Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
+ placement: 'right',
+ trigger: 'click',
+ content: '',
+ template: '
'
+ })
+
+
+ // NOTE: POPOVER EXTENDS tooltip.js
+ // ================================
+
+ Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
+
+ Popover.prototype.constructor = Popover
+
+ Popover.prototype.getDefaults = function () {
+ return Popover.DEFAULTS
+ }
+
+ Popover.prototype.setContent = function () {
+ var $tip = this.tip()
+ var title = this.getTitle()
+ var content = this.getContent()
+
+ $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
+ $tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events
+ this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
+ ](content)
+
+ $tip.removeClass('fade top bottom left right in')
+
+ // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
+ // this manually by checking the contents.
+ if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
+ }
+
+ Popover.prototype.hasContent = function () {
+ return this.getTitle() || this.getContent()
+ }
+
+ Popover.prototype.getContent = function () {
+ var $e = this.$element
+ var o = this.options
+
+ return $e.attr('data-content')
+ || (typeof o.content == 'function' ?
+ o.content.call($e[0]) :
+ o.content)
+ }
+
+ Popover.prototype.arrow = function () {
+ return (this.$arrow = this.$arrow || this.tip().find('.arrow'))
+ }
+
+
+ // POPOVER PLUGIN DEFINITION
+ // =========================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.popover')
+ var options = typeof option == 'object' && option
+
+ if (!data && /destroy|hide/.test(option)) return
+ if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ var old = $.fn.popover
+
+ $.fn.popover = Plugin
+ $.fn.popover.Constructor = Popover
+
+
+ // POPOVER NO CONFLICT
+ // ===================
+
+ $.fn.popover.noConflict = function () {
+ $.fn.popover = old
+ return this
+ }
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: scrollspy.js v3.3.5
+ * http://getbootstrap.com/javascript/#scrollspy
+ * ========================================================================
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // SCROLLSPY CLASS DEFINITION
+ // ==========================
+
+ function ScrollSpy(element, options) {
+ this.$body = $(document.body)
+ this.$scrollElement = $(element).is(document.body) ? $(window) : $(element)
+ this.options = $.extend({}, ScrollSpy.DEFAULTS, options)
+ this.selector = (this.options.target || '') + ' .nav li > a'
+ this.offsets = []
+ this.targets = []
+ this.activeTarget = null
+ this.scrollHeight = 0
+
+ this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this))
+ this.refresh()
+ this.process()
+ }
+
+ ScrollSpy.VERSION = '3.3.5'
+
+ ScrollSpy.DEFAULTS = {
+ offset: 10
+ }
+
+ ScrollSpy.prototype.getScrollHeight = function () {
+ return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
+ }
+
+ ScrollSpy.prototype.refresh = function () {
+ var that = this
+ var offsetMethod = 'offset'
+ var offsetBase = 0
+
+ this.offsets = []
+ this.targets = []
+ this.scrollHeight = this.getScrollHeight()
+
+ if (!$.isWindow(this.$scrollElement[0])) {
+ offsetMethod = 'position'
+ offsetBase = this.$scrollElement.scrollTop()
+ }
+
+ this.$body
+ .find(this.selector)
+ .map(function () {
+ var $el = $(this)
+ var href = $el.data('target') || $el.attr('href')
+ var $href = /^#./.test(href) && $(href)
+
+ return ($href
+ && $href.length
+ && $href.is(':visible')
+ && [[$href[offsetMethod]().top + offsetBase, href]]) || null
+ })
+ .sort(function (a, b) { return a[0] - b[0] })
+ .each(function () {
+ that.offsets.push(this[0])
+ that.targets.push(this[1])
+ })
+ }
+
+ ScrollSpy.prototype.process = function () {
+ var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
+ var scrollHeight = this.getScrollHeight()
+ var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height()
+ var offsets = this.offsets
+ var targets = this.targets
+ var activeTarget = this.activeTarget
+ var i
+
+ if (this.scrollHeight != scrollHeight) {
+ this.refresh()
+ }
+
+ if (scrollTop >= maxScroll) {
+ return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
+ }
+
+ if (activeTarget && scrollTop < offsets[0]) {
+ this.activeTarget = null
+ return this.clear()
+ }
+
+ for (i = offsets.length; i--;) {
+ activeTarget != targets[i]
+ && scrollTop >= offsets[i]
+ && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1])
+ && this.activate(targets[i])
+ }
+ }
+
+ ScrollSpy.prototype.activate = function (target) {
+ this.activeTarget = target
+
+ this.clear()
+
+ var selector = this.selector +
+ '[data-target="' + target + '"],' +
+ this.selector + '[href="' + target + '"]'
+
+ var active = $(selector)
+ .parents('li')
+ .addClass('active')
+
+ if (active.parent('.dropdown-menu').length) {
+ active = active
+ .closest('li.dropdown')
+ .addClass('active')
+ }
+
+ active.trigger('activate.bs.scrollspy')
+ }
+
+ ScrollSpy.prototype.clear = function () {
+ $(this.selector)
+ .parentsUntil(this.options.target, '.active')
+ .removeClass('active')
+ }
+
+
+ // SCROLLSPY PLUGIN DEFINITION
+ // ===========================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.scrollspy')
+ var options = typeof option == 'object' && option
+
+ if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ var old = $.fn.scrollspy
+
+ $.fn.scrollspy = Plugin
+ $.fn.scrollspy.Constructor = ScrollSpy
+
+
+ // SCROLLSPY NO CONFLICT
+ // =====================
+
+ $.fn.scrollspy.noConflict = function () {
+ $.fn.scrollspy = old
+ return this
+ }
+
+
+ // SCROLLSPY DATA-API
+ // ==================
+
+ $(window).on('load.bs.scrollspy.data-api', function () {
+ $('[data-spy="scroll"]').each(function () {
+ var $spy = $(this)
+ Plugin.call($spy, $spy.data())
+ })
+ })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: tab.js v3.3.5
+ * http://getbootstrap.com/javascript/#tabs
+ * ========================================================================
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // TAB CLASS DEFINITION
+ // ====================
+
+ var Tab = function (element) {
+ // jscs:disable requireDollarBeforejQueryAssignment
+ this.element = $(element)
+ // jscs:enable requireDollarBeforejQueryAssignment
+ }
+
+ Tab.VERSION = '3.3.5'
+
+ Tab.TRANSITION_DURATION = 150
+
+ Tab.prototype.show = function () {
+ var $this = this.element
+ var $ul = $this.closest('ul:not(.dropdown-menu)')
+ var selector = $this.data('target')
+
+ if (!selector) {
+ selector = $this.attr('href')
+ selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
+ }
+
+ if ($this.parent('li').hasClass('active')) return
+
+ var $previous = $ul.find('.active:last a')
+ var hideEvent = $.Event('hide.bs.tab', {
+ relatedTarget: $this[0]
+ })
+ var showEvent = $.Event('show.bs.tab', {
+ relatedTarget: $previous[0]
+ })
+
+ $previous.trigger(hideEvent)
+ $this.trigger(showEvent)
+
+ if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return
+
+ var $target = $(selector)
+
+ this.activate($this.closest('li'), $ul)
+ this.activate($target, $target.parent(), function () {
+ $previous.trigger({
+ type: 'hidden.bs.tab',
+ relatedTarget: $this[0]
+ })
+ $this.trigger({
+ type: 'shown.bs.tab',
+ relatedTarget: $previous[0]
+ })
+ })
+ }
+
+ Tab.prototype.activate = function (element, container, callback) {
+ var $active = container.find('> .active')
+ var transition = callback
+ && $.support.transition
+ && ($active.length && $active.hasClass('fade') || !!container.find('> .fade').length)
+
+ function next() {
+ $active
+ .removeClass('active')
+ .find('> .dropdown-menu > .active')
+ .removeClass('active')
+ .end()
+ .find('[data-toggle="tab"]')
+ .attr('aria-expanded', false)
+
+ element
+ .addClass('active')
+ .find('[data-toggle="tab"]')
+ .attr('aria-expanded', true)
+
+ if (transition) {
+ element[0].offsetWidth // reflow for transition
+ element.addClass('in')
+ } else {
+ element.removeClass('fade')
+ }
+
+ if (element.parent('.dropdown-menu').length) {
+ element
+ .closest('li.dropdown')
+ .addClass('active')
+ .end()
+ .find('[data-toggle="tab"]')
+ .attr('aria-expanded', true)
+ }
+
+ callback && callback()
+ }
+
+ $active.length && transition ?
+ $active
+ .one('bsTransitionEnd', next)
+ .emulateTransitionEnd(Tab.TRANSITION_DURATION) :
+ next()
+
+ $active.removeClass('in')
+ }
+
+
+ // TAB PLUGIN DEFINITION
+ // =====================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.tab')
+
+ if (!data) $this.data('bs.tab', (data = new Tab(this)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ var old = $.fn.tab
+
+ $.fn.tab = Plugin
+ $.fn.tab.Constructor = Tab
+
+
+ // TAB NO CONFLICT
+ // ===============
+
+ $.fn.tab.noConflict = function () {
+ $.fn.tab = old
+ return this
+ }
+
+
+ // TAB DATA-API
+ // ============
+
+ var clickHandler = function (e) {
+ e.preventDefault()
+ Plugin.call($(this), 'show')
+ }
+
+ $(document)
+ .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler)
+ .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler)
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: affix.js v3.3.5
+ * http://getbootstrap.com/javascript/#affix
+ * ========================================================================
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // AFFIX CLASS DEFINITION
+ // ======================
+
+ var Affix = function (element, options) {
+ this.options = $.extend({}, Affix.DEFAULTS, options)
+
+ this.$target = $(this.options.target)
+ .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))
+ .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this))
+
+ this.$element = $(element)
+ this.affixed = null
+ this.unpin = null
+ this.pinnedOffset = null
+
+ this.checkPosition()
+ }
+
+ Affix.VERSION = '3.3.5'
+
+ Affix.RESET = 'affix affix-top affix-bottom'
+
+ Affix.DEFAULTS = {
+ offset: 0,
+ target: window
+ }
+
+ Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) {
+ var scrollTop = this.$target.scrollTop()
+ var position = this.$element.offset()
+ var targetHeight = this.$target.height()
+
+ if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false
+
+ if (this.affixed == 'bottom') {
+ if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom'
+ return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom'
+ }
+
+ var initializing = this.affixed == null
+ var colliderTop = initializing ? scrollTop : position.top
+ var colliderHeight = initializing ? targetHeight : height
+
+ if (offsetTop != null && scrollTop <= offsetTop) return 'top'
+ if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom'
+
+ return false
+ }
+
+ Affix.prototype.getPinnedOffset = function () {
+ if (this.pinnedOffset) return this.pinnedOffset
+ this.$element.removeClass(Affix.RESET).addClass('affix')
+ var scrollTop = this.$target.scrollTop()
+ var position = this.$element.offset()
+ return (this.pinnedOffset = position.top - scrollTop)
+ }
+
+ Affix.prototype.checkPositionWithEventLoop = function () {
+ setTimeout($.proxy(this.checkPosition, this), 1)
+ }
+
+ Affix.prototype.checkPosition = function () {
+ if (!this.$element.is(':visible')) return
+
+ var height = this.$element.height()
+ var offset = this.options.offset
+ var offsetTop = offset.top
+ var offsetBottom = offset.bottom
+ var scrollHeight = Math.max($(document).height(), $(document.body).height())
+
+ if (typeof offset != 'object') offsetBottom = offsetTop = offset
+ if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element)
+ if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element)
+
+ var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom)
+
+ if (this.affixed != affix) {
+ if (this.unpin != null) this.$element.css('top', '')
+
+ var affixType = 'affix' + (affix ? '-' + affix : '')
+ var e = $.Event(affixType + '.bs.affix')
+
+ this.$element.trigger(e)
+
+ if (e.isDefaultPrevented()) return
+
+ this.affixed = affix
+ this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null
+
+ this.$element
+ .removeClass(Affix.RESET)
+ .addClass(affixType)
+ .trigger(affixType.replace('affix', 'affixed') + '.bs.affix')
+ }
+
+ if (affix == 'bottom') {
+ this.$element.offset({
+ top: scrollHeight - height - offsetBottom
+ })
+ }
+ }
+
+
+ // AFFIX PLUGIN DEFINITION
+ // =======================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.affix')
+ var options = typeof option == 'object' && option
+
+ if (!data) $this.data('bs.affix', (data = new Affix(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ var old = $.fn.affix
+
+ $.fn.affix = Plugin
+ $.fn.affix.Constructor = Affix
+
+
+ // AFFIX NO CONFLICT
+ // =================
+
+ $.fn.affix.noConflict = function () {
+ $.fn.affix = old
+ return this
+ }
+
+
+ // AFFIX DATA-API
+ // ==============
+
+ $(window).on('load', function () {
+ $('[data-spy="affix"]').each(function () {
+ var $spy = $(this)
+ var data = $spy.data()
+
+ data.offset = data.offset || {}
+
+ if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom
+ if (data.offsetTop != null) data.offset.top = data.offsetTop
+
+ Plugin.call($spy, data)
+ })
+ })
+
+}(jQuery);
diff --git a/public/javascripts/jquery-1.3.2.js b/public/javascripts/jquery-1.3.2.js
new file mode 100644
index 000000000..b1ae21d8b
--- /dev/null
+++ b/public/javascripts/jquery-1.3.2.js
@@ -0,0 +1,19 @@
+/*
+ * jQuery JavaScript Library v1.3.2
+ * http://jquery.com/
+ *
+ * Copyright (c) 2009 John Resig
+ * Dual licensed under the MIT and GPL licenses.
+ * http://docs.jquery.com/License
+ *
+ * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009)
+ * Revision: 6246
+ */
+(function(){var l=this,g,y=l.jQuery,p=l.$,o=l.jQuery=l.$=function(E,F){return new o.fn.init(E,F)},D=/^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,f=/^.[^:#\[\.,]*$/;o.fn=o.prototype={init:function(E,H){E=E||document;if(E.nodeType){this[0]=E;this.length=1;this.context=E;return this}if(typeof E==="string"){var G=D.exec(E);if(G&&(G[1]||!H)){if(G[1]){E=o.clean([G[1]],H)}else{var I=document.getElementById(G[3]);if(I&&I.id!=G[3]){return o().find(E)}var F=o(I||[]);F.context=document;F.selector=E;return F}}else{return o(H).find(E)}}else{if(o.isFunction(E)){return o(document).ready(E)}}if(E.selector&&E.context){this.selector=E.selector;this.context=E.context}return this.setArray(o.isArray(E)?E:o.makeArray(E))},selector:"",jquery:"1.3.2",size:function(){return this.length},get:function(E){return E===g?Array.prototype.slice.call(this):this[E]},pushStack:function(F,H,E){var G=o(F);G.prevObject=this;G.context=this.context;if(H==="find"){G.selector=this.selector+(this.selector?" ":"")+E}else{if(H){G.selector=this.selector+"."+H+"("+E+")"}}return G},setArray:function(E){this.length=0;Array.prototype.push.apply(this,E);return this},each:function(F,E){return o.each(this,F,E)},index:function(E){return o.inArray(E&&E.jquery?E[0]:E,this)},attr:function(F,H,G){var E=F;if(typeof F==="string"){if(H===g){return this[0]&&o[G||"attr"](this[0],F)}else{E={};E[F]=H}}return this.each(function(I){for(F in E){o.attr(G?this.style:this,F,o.prop(this,E[F],G,I,F))}})},css:function(E,F){if((E=="width"||E=="height")&&parseFloat(F)<0){F=g}return this.attr(E,F,"curCSS")},text:function(F){if(typeof F!=="object"&&F!=null){return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(F))}var E="";o.each(F||this,function(){o.each(this.childNodes,function(){if(this.nodeType!=8){E+=this.nodeType!=1?this.nodeValue:o.fn.text([this])}})});return E},wrapAll:function(E){if(this[0]){var F=o(E,this[0].ownerDocument).clone();if(this[0].parentNode){F.insertBefore(this[0])}F.map(function(){var G=this;while(G.firstChild){G=G.firstChild}return G}).append(this)}return this},wrapInner:function(E){return this.each(function(){o(this).contents().wrapAll(E)})},wrap:function(E){return this.each(function(){o(this).wrapAll(E)})},append:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.appendChild(E)}})},prepend:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.insertBefore(E,this.firstChild)}})},before:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this)})},after:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this.nextSibling)})},end:function(){return this.prevObject||o([])},push:[].push,sort:[].sort,splice:[].splice,find:function(E){if(this.length===1){var F=this.pushStack([],"find",E);F.length=0;o.find(E,this[0],F);return F}else{return this.pushStack(o.unique(o.map(this,function(G){return o.find(E,G)})),"find",E)}},clone:function(G){var E=this.map(function(){if(!o.support.noCloneEvent&&!o.isXMLDoc(this)){var I=this.outerHTML;if(!I){var J=this.ownerDocument.createElement("div");J.appendChild(this.cloneNode(true));I=J.innerHTML}return o.clean([I.replace(/ jQuery\d+="(?:\d+|null)"/g,"").replace(/^\s*/,"")])[0]}else{return this.cloneNode(true)}});if(G===true){var H=this.find("*").andSelf(),F=0;E.find("*").andSelf().each(function(){if(this.nodeName!==H[F].nodeName){return}var I=o.data(H[F],"events");for(var K in I){for(var J in I[K]){o.event.add(this,K,I[K][J],I[K][J].data)}}F++})}return E},filter:function(E){return this.pushStack(o.isFunction(E)&&o.grep(this,function(G,F){return E.call(G,F)})||o.multiFilter(E,o.grep(this,function(F){return F.nodeType===1})),"filter",E)},closest:function(E){var G=o.expr.match.POS.test(E)?o(E):null,F=0;return this.map(function(){var H=this;while(H&&H.ownerDocument){if(G?G.index(H)>-1:o(H).is(E)){o.data(H,"closest",F);return H}H=H.parentNode;F++}})},not:function(E){if(typeof E==="string"){if(f.test(E)){return this.pushStack(o.multiFilter(E,this,true),"not",E)}else{E=o.multiFilter(E,this)}}var F=E.length&&E[E.length-1]!==g&&!E.nodeType;return this.filter(function(){return F?o.inArray(this,E)<0:this!=E})},add:function(E){return this.pushStack(o.unique(o.merge(this.get(),typeof E==="string"?o(E):o.makeArray(E))))},is:function(E){return !!E&&o.multiFilter(E,this).length>0},hasClass:function(E){return !!E&&this.is("."+E)},val:function(K){if(K===g){var E=this[0];if(E){if(o.nodeName(E,"option")){return(E.attributes.value||{}).specified?E.value:E.text}if(o.nodeName(E,"select")){var I=E.selectedIndex,L=[],M=E.options,H=E.type=="select-one";if(I<0){return null}for(var F=H?I:0,J=H?I+1:M.length;F
=0||o.inArray(this.name,K)>=0)}else{if(o.nodeName(this,"select")){var N=o.makeArray(K);o("option",this).each(function(){this.selected=(o.inArray(this.value,N)>=0||o.inArray(this.text,N)>=0)});if(!N.length){this.selectedIndex=-1}}else{this.value=K}}})},html:function(E){return E===g?(this[0]?this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g,""):null):this.empty().append(E)},replaceWith:function(E){return this.after(E).remove()},eq:function(E){return this.slice(E,+E+1)},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments),"slice",Array.prototype.slice.call(arguments).join(","))},map:function(E){return this.pushStack(o.map(this,function(G,F){return E.call(G,F,G)}))},andSelf:function(){return this.add(this.prevObject)},domManip:function(J,M,L){if(this[0]){var I=(this[0].ownerDocument||this[0]).createDocumentFragment(),F=o.clean(J,(this[0].ownerDocument||this[0]),I),H=I.firstChild;if(H){for(var G=0,E=this.length;G1||G>0?I.cloneNode(true):I)}}if(F){o.each(F,z)}}return this;function K(N,O){return M&&o.nodeName(N,"table")&&o.nodeName(O,"tr")?(N.getElementsByTagName("tbody")[0]||N.appendChild(N.ownerDocument.createElement("tbody"))):N}}};o.fn.init.prototype=o.fn;function z(E,F){if(F.src){o.ajax({url:F.src,async:false,dataType:"script"})}else{o.globalEval(F.text||F.textContent||F.innerHTML||"")}if(F.parentNode){F.parentNode.removeChild(F)}}function e(){return +new Date}o.extend=o.fn.extend=function(){var J=arguments[0]||{},H=1,I=arguments.length,E=false,G;if(typeof J==="boolean"){E=J;J=arguments[1]||{};H=2}if(typeof J!=="object"&&!o.isFunction(J)){J={}}if(I==H){J=this;--H}for(;H-1}},swap:function(H,G,I){var E={};for(var F in G){E[F]=H.style[F];H.style[F]=G[F]}I.call(H);for(var F in G){H.style[F]=E[F]}},css:function(H,F,J,E){if(F=="width"||F=="height"){var L,G={position:"absolute",visibility:"hidden",display:"block"},K=F=="width"?["Left","Right"]:["Top","Bottom"];function I(){L=F=="width"?H.offsetWidth:H.offsetHeight;if(E==="border"){return}o.each(K,function(){if(!E){L-=parseFloat(o.curCSS(H,"padding"+this,true))||0}if(E==="margin"){L+=parseFloat(o.curCSS(H,"margin"+this,true))||0}else{L-=parseFloat(o.curCSS(H,"border"+this+"Width",true))||0}})}if(H.offsetWidth!==0){I()}else{o.swap(H,G,I)}return Math.max(0,Math.round(L))}return o.curCSS(H,F,J)},curCSS:function(I,F,G){var L,E=I.style;if(F=="opacity"&&!o.support.opacity){L=o.attr(E,"opacity");return L==""?"1":L}if(F.match(/float/i)){F=w}if(!G&&E&&E[F]){L=E[F]}else{if(q.getComputedStyle){if(F.match(/float/i)){F="float"}F=F.replace(/([A-Z])/g,"-$1").toLowerCase();var M=q.getComputedStyle(I,null);if(M){L=M.getPropertyValue(F)}if(F=="opacity"&&L==""){L="1"}}else{if(I.currentStyle){var J=F.replace(/\-(\w)/g,function(N,O){return O.toUpperCase()});L=I.currentStyle[F]||I.currentStyle[J];if(!/^\d+(px)?$/i.test(L)&&/^\d/.test(L)){var H=E.left,K=I.runtimeStyle.left;I.runtimeStyle.left=I.currentStyle.left;E.left=L||0;L=E.pixelLeft+"px";E.left=H;I.runtimeStyle.left=K}}}}return L},clean:function(F,K,I){K=K||document;if(typeof K.createElement==="undefined"){K=K.ownerDocument||K[0]&&K[0].ownerDocument||document}if(!I&&F.length===1&&typeof F[0]==="string"){var H=/^<(\w+)\s*\/?>$/.exec(F[0]);if(H){return[K.createElement(H[1])]}}var G=[],E=[],L=K.createElement("div");o.each(F,function(P,S){if(typeof S==="number"){S+=""}if(!S){return}if(typeof S==="string"){S=S.replace(/(<(\w+)[^>]*?)\/>/g,function(U,V,T){return T.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?U:V+">"+T+">"});var O=S.replace(/^\s+/,"").substring(0,10).toLowerCase();var Q=!O.indexOf("",""]||!O.indexOf("",""]||O.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,""]||!O.indexOf(""," "]||(!O.indexOf(""," "]||!O.indexOf(""," "]||!o.support.htmlSerialize&&[1,"div","
"]||[0,"",""];L.innerHTML=Q[1]+S+Q[2];while(Q[0]--){L=L.lastChild}if(!o.support.tbody){var R=/"&&!R?L.childNodes:[];for(var M=N.length-1;M>=0;--M){if(o.nodeName(N[M],"tbody")&&!N[M].childNodes.length){N[M].parentNode.removeChild(N[M])}}}if(!o.support.leadingWhitespace&&/^\s/.test(S)){L.insertBefore(K.createTextNode(S.match(/^\s*/)[0]),L.firstChild)}S=o.makeArray(L.childNodes)}if(S.nodeType){G.push(S)}else{G=o.merge(G,S)}});if(I){for(var J=0;G[J];J++){if(o.nodeName(G[J],"script")&&(!G[J].type||G[J].type.toLowerCase()==="text/javascript")){E.push(G[J].parentNode?G[J].parentNode.removeChild(G[J]):G[J])}else{if(G[J].nodeType===1){G.splice.apply(G,[J+1,0].concat(o.makeArray(G[J].getElementsByTagName("script"))))}I.appendChild(G[J])}}return E}return G},attr:function(J,G,K){if(!J||J.nodeType==3||J.nodeType==8){return g}var H=!o.isXMLDoc(J),L=K!==g;G=H&&o.props[G]||G;if(J.tagName){var F=/href|src|style/.test(G);if(G=="selected"&&J.parentNode){J.parentNode.selectedIndex}if(G in J&&H&&!F){if(L){if(G=="type"&&o.nodeName(J,"input")&&J.parentNode){throw"type property can't be changed"}J[G]=K}if(o.nodeName(J,"form")&&J.getAttributeNode(G)){return J.getAttributeNode(G).nodeValue}if(G=="tabIndex"){var I=J.getAttributeNode("tabIndex");return I&&I.specified?I.value:J.nodeName.match(/(button|input|object|select|textarea)/i)?0:J.nodeName.match(/^(a|area)$/i)&&J.href?0:g}return J[G]}if(!o.support.style&&H&&G=="style"){return o.attr(J.style,"cssText",K)}if(L){J.setAttribute(G,""+K)}var E=!o.support.hrefNormalized&&H&&F?J.getAttribute(G,2):J.getAttribute(G);return E===null?g:E}if(!o.support.opacity&&G=="opacity"){if(L){J.zoom=1;J.filter=(J.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(K)+""=="NaN"?"":"alpha(opacity="+K*100+")")}return J.filter&&J.filter.indexOf("opacity=")>=0?(parseFloat(J.filter.match(/opacity=([^)]*)/)[1])/100)+"":""}G=G.replace(/-([a-z])/ig,function(M,N){return N.toUpperCase()});if(L){J[G]=K}return J[G]},trim:function(E){return(E||"").replace(/^\s+|\s+$/g,"")},makeArray:function(G){var E=[];if(G!=null){var F=G.length;if(F==null||typeof G==="string"||o.isFunction(G)||G.setInterval){E[0]=G}else{while(F){E[--F]=G[F]}}}return E},inArray:function(G,H){for(var E=0,F=H.length;E0?this.clone(true):this).get();o.fn[F].apply(o(L[K]),I);J=J.concat(I)}return this.pushStack(J,E,G)}});o.each({removeAttr:function(E){o.attr(this,E,"");if(this.nodeType==1){this.removeAttribute(E)}},addClass:function(E){o.className.add(this,E)},removeClass:function(E){o.className.remove(this,E)},toggleClass:function(F,E){if(typeof E!=="boolean"){E=!o.className.has(this,F)}o.className[E?"add":"remove"](this,F)},remove:function(E){if(!E||o.filter(E,[this]).length){o("*",this).add([this]).each(function(){o.event.remove(this);o.removeData(this)});if(this.parentNode){this.parentNode.removeChild(this)}}},empty:function(){o(this).children().remove();while(this.firstChild){this.removeChild(this.firstChild)}}},function(E,F){o.fn[E]=function(){return this.each(F,arguments)}});function j(E,F){return E[0]&&parseInt(o.curCSS(E[0],F,true),10)||0}var h="jQuery"+e(),v=0,A={};o.extend({cache:{},data:function(F,E,G){F=F==l?A:F;var H=F[h];if(!H){H=F[h]=++v}if(E&&!o.cache[H]){o.cache[H]={}}if(G!==g){o.cache[H][E]=G}return E?o.cache[H][E]:H},removeData:function(F,E){F=F==l?A:F;var H=F[h];if(E){if(o.cache[H]){delete o.cache[H][E];E="";for(E in o.cache[H]){break}if(!E){o.removeData(F)}}}else{try{delete F[h]}catch(G){if(F.removeAttribute){F.removeAttribute(h)}}delete o.cache[H]}},queue:function(F,E,H){if(F){E=(E||"fx")+"queue";var G=o.data(F,E);if(!G||o.isArray(H)){G=o.data(F,E,o.makeArray(H))}else{if(H){G.push(H)}}}return G},dequeue:function(H,G){var E=o.queue(H,G),F=E.shift();if(!G||G==="fx"){F=E[0]}if(F!==g){F.call(H)}}});o.fn.extend({data:function(E,G){var H=E.split(".");H[1]=H[1]?"."+H[1]:"";if(G===g){var F=this.triggerHandler("getData"+H[1]+"!",[H[0]]);if(F===g&&this.length){F=o.data(this[0],E)}return F===g&&H[1]?this.data(H[0]):F}else{return this.trigger("setData"+H[1]+"!",[H[0],G]).each(function(){o.data(this,E,G)})}},removeData:function(E){return this.each(function(){o.removeData(this,E)})},queue:function(E,F){if(typeof E!=="string"){F=E;E="fx"}if(F===g){return o.queue(this[0],E)}return this.each(function(){var G=o.queue(this,E,F);if(E=="fx"&&G.length==1){G[0].call(this)}})},dequeue:function(E){return this.each(function(){o.dequeue(this,E)})}});
+/*
+ * Sizzle CSS Selector Engine - v0.9.3
+ * Copyright 2009, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ * More information: http://sizzlejs.com/
+ */
+(function(){var R=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,L=0,H=Object.prototype.toString;var F=function(Y,U,ab,ac){ab=ab||[];U=U||document;if(U.nodeType!==1&&U.nodeType!==9){return[]}if(!Y||typeof Y!=="string"){return ab}var Z=[],W,af,ai,T,ad,V,X=true;R.lastIndex=0;while((W=R.exec(Y))!==null){Z.push(W[1]);if(W[2]){V=RegExp.rightContext;break}}if(Z.length>1&&M.exec(Y)){if(Z.length===2&&I.relative[Z[0]]){af=J(Z[0]+Z[1],U)}else{af=I.relative[Z[0]]?[U]:F(Z.shift(),U);while(Z.length){Y=Z.shift();if(I.relative[Y]){Y+=Z.shift()}af=J(Y,af)}}}else{var ae=ac?{expr:Z.pop(),set:E(ac)}:F.find(Z.pop(),Z.length===1&&U.parentNode?U.parentNode:U,Q(U));af=F.filter(ae.expr,ae.set);if(Z.length>0){ai=E(af)}else{X=false}while(Z.length){var ah=Z.pop(),ag=ah;if(!I.relative[ah]){ah=""}else{ag=Z.pop()}if(ag==null){ag=U}I.relative[ah](ai,ag,Q(U))}}if(!ai){ai=af}if(!ai){throw"Syntax error, unrecognized expression: "+(ah||Y)}if(H.call(ai)==="[object Array]"){if(!X){ab.push.apply(ab,ai)}else{if(U.nodeType===1){for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&(ai[aa]===true||ai[aa].nodeType===1&&K(U,ai[aa]))){ab.push(af[aa])}}}else{for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&ai[aa].nodeType===1){ab.push(af[aa])}}}}}else{E(ai,ab)}if(V){F(V,U,ab,ac);if(G){hasDuplicate=false;ab.sort(G);if(hasDuplicate){for(var aa=1;aa":function(Z,U,aa){var X=typeof U==="string";if(X&&!/\W/.test(U)){U=aa?U:U.toUpperCase();for(var V=0,T=Z.length;V=0)){if(!V){T.push(Y)}}else{if(V){U[X]=false}}}}return false},ID:function(T){return T[1].replace(/\\/g,"")},TAG:function(U,T){for(var V=0;T[V]===false;V++){}return T[V]&&Q(T[V])?U[1]:U[1].toUpperCase()},CHILD:function(T){if(T[1]=="nth"){var U=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(T[2]=="even"&&"2n"||T[2]=="odd"&&"2n+1"||!/\D/.test(T[2])&&"0n+"+T[2]||T[2]);T[2]=(U[1]+(U[2]||1))-0;T[3]=U[3]-0}T[0]=L++;return T},ATTR:function(X,U,V,T,Y,Z){var W=X[1].replace(/\\/g,"");if(!Z&&I.attrMap[W]){X[1]=I.attrMap[W]}if(X[2]==="~="){X[4]=" "+X[4]+" "}return X},PSEUDO:function(X,U,V,T,Y){if(X[1]==="not"){if(X[3].match(R).length>1||/^\w/.test(X[3])){X[3]=F(X[3],null,null,U)}else{var W=F.filter(X[3],U,V,true^Y);if(!V){T.push.apply(T,W)}return false}}else{if(I.match.POS.test(X[0])||I.match.CHILD.test(X[0])){return true}}return X},POS:function(T){T.unshift(true);return T}},filters:{enabled:function(T){return T.disabled===false&&T.type!=="hidden"},disabled:function(T){return T.disabled===true},checked:function(T){return T.checked===true},selected:function(T){T.parentNode.selectedIndex;return T.selected===true},parent:function(T){return !!T.firstChild},empty:function(T){return !T.firstChild},has:function(V,U,T){return !!F(T[3],V).length},header:function(T){return/h\d/i.test(T.nodeName)},text:function(T){return"text"===T.type},radio:function(T){return"radio"===T.type},checkbox:function(T){return"checkbox"===T.type},file:function(T){return"file"===T.type},password:function(T){return"password"===T.type},submit:function(T){return"submit"===T.type},image:function(T){return"image"===T.type},reset:function(T){return"reset"===T.type},button:function(T){return"button"===T.type||T.nodeName.toUpperCase()==="BUTTON"},input:function(T){return/input|select|textarea|button/i.test(T.nodeName)}},setFilters:{first:function(U,T){return T===0},last:function(V,U,T,W){return U===W.length-1},even:function(U,T){return T%2===0},odd:function(U,T){return T%2===1},lt:function(V,U,T){return UT[3]-0},nth:function(V,U,T){return T[3]-0==U},eq:function(V,U,T){return T[3]-0==U}},filter:{PSEUDO:function(Z,V,W,aa){var U=V[1],X=I.filters[U];if(X){return X(Z,W,V,aa)}else{if(U==="contains"){return(Z.textContent||Z.innerText||"").indexOf(V[3])>=0}else{if(U==="not"){var Y=V[3];for(var W=0,T=Y.length;W=0)}}},ID:function(U,T){return U.nodeType===1&&U.getAttribute("id")===T},TAG:function(U,T){return(T==="*"&&U.nodeType===1)||U.nodeName===T},CLASS:function(U,T){return(" "+(U.className||U.getAttribute("class"))+" ").indexOf(T)>-1},ATTR:function(Y,W){var V=W[1],T=I.attrHandle[V]?I.attrHandle[V](Y):Y[V]!=null?Y[V]:Y.getAttribute(V),Z=T+"",X=W[2],U=W[4];return T==null?X==="!=":X==="="?Z===U:X==="*="?Z.indexOf(U)>=0:X==="~="?(" "+Z+" ").indexOf(U)>=0:!U?Z&&T!==false:X==="!="?Z!=U:X==="^="?Z.indexOf(U)===0:X==="$="?Z.substr(Z.length-U.length)===U:X==="|="?Z===U||Z.substr(0,U.length+1)===U+"-":false},POS:function(X,U,V,Y){var T=U[2],W=I.setFilters[T];if(W){return W(X,V,U,Y)}}}};var M=I.match.POS;for(var O in I.match){I.match[O]=RegExp(I.match[O].source+/(?![^\[]*\])(?![^\(]*\))/.source)}var E=function(U,T){U=Array.prototype.slice.call(U);if(T){T.push.apply(T,U);return T}return U};try{Array.prototype.slice.call(document.documentElement.childNodes)}catch(N){E=function(X,W){var U=W||[];if(H.call(X)==="[object Array]"){Array.prototype.push.apply(U,X)}else{if(typeof X.length==="number"){for(var V=0,T=X.length;V ";var T=document.documentElement;T.insertBefore(U,T.firstChild);if(!!document.getElementById(V)){I.find.ID=function(X,Y,Z){if(typeof Y.getElementById!=="undefined"&&!Z){var W=Y.getElementById(X[1]);return W?W.id===X[1]||typeof W.getAttributeNode!=="undefined"&&W.getAttributeNode("id").nodeValue===X[1]?[W]:g:[]}};I.filter.ID=function(Y,W){var X=typeof Y.getAttributeNode!=="undefined"&&Y.getAttributeNode("id");return Y.nodeType===1&&X&&X.nodeValue===W}}T.removeChild(U)})();(function(){var T=document.createElement("div");T.appendChild(document.createComment(""));if(T.getElementsByTagName("*").length>0){I.find.TAG=function(U,Y){var X=Y.getElementsByTagName(U[1]);if(U[1]==="*"){var W=[];for(var V=0;X[V];V++){if(X[V].nodeType===1){W.push(X[V])}}X=W}return X}}T.innerHTML=" ";if(T.firstChild&&typeof T.firstChild.getAttribute!=="undefined"&&T.firstChild.getAttribute("href")!=="#"){I.attrHandle.href=function(U){return U.getAttribute("href",2)}}})();if(document.querySelectorAll){(function(){var T=F,U=document.createElement("div");U.innerHTML="
";if(U.querySelectorAll&&U.querySelectorAll(".TEST").length===0){return}F=function(Y,X,V,W){X=X||document;if(!W&&X.nodeType===9&&!Q(X)){try{return E(X.querySelectorAll(Y),V)}catch(Z){}}return T(Y,X,V,W)};F.find=T.find;F.filter=T.filter;F.selectors=T.selectors;F.matches=T.matches})()}if(document.getElementsByClassName&&document.documentElement.getElementsByClassName){(function(){var T=document.createElement("div");T.innerHTML="
";if(T.getElementsByClassName("e").length===0){return}T.lastChild.className="e";if(T.getElementsByClassName("e").length===1){return}I.order.splice(1,0,"CLASS");I.find.CLASS=function(U,V,W){if(typeof V.getElementsByClassName!=="undefined"&&!W){return V.getElementsByClassName(U[1])}}})()}function P(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W0){X=T;break}}}T=T[U]}ad[W]=X}}}var K=document.compareDocumentPosition?function(U,T){return U.compareDocumentPosition(T)&16}:function(U,T){return U!==T&&(U.contains?U.contains(T):true)};var Q=function(T){return T.nodeType===9&&T.documentElement.nodeName!=="HTML"||!!T.ownerDocument&&Q(T.ownerDocument)};var J=function(T,aa){var W=[],X="",Y,V=aa.nodeType?[aa]:aa;while((Y=I.match.PSEUDO.exec(T))){X+=Y[0];T=T.replace(I.match.PSEUDO,"")}T=I.relative[T]?T+"*":T;for(var Z=0,U=V.length;Z0||T.offsetHeight>0};F.selectors.filters.animated=function(T){return o.grep(o.timers,function(U){return T===U.elem}).length};o.multiFilter=function(V,T,U){if(U){V=":not("+V+")"}return F.matches(V,T)};o.dir=function(V,U){var T=[],W=V[U];while(W&&W!=document){if(W.nodeType==1){T.push(W)}W=W[U]}return T};o.nth=function(X,T,V,W){T=T||1;var U=0;for(;X;X=X[V]){if(X.nodeType==1&&++U==T){break}}return X};o.sibling=function(V,U){var T=[];for(;V;V=V.nextSibling){if(V.nodeType==1&&V!=U){T.push(V)}}return T};return;l.Sizzle=F})();o.event={add:function(I,F,H,K){if(I.nodeType==3||I.nodeType==8){return}if(I.setInterval&&I!=l){I=l}if(!H.guid){H.guid=this.guid++}if(K!==g){var G=H;H=this.proxy(G);H.data=K}var E=o.data(I,"events")||o.data(I,"events",{}),J=o.data(I,"handle")||o.data(I,"handle",function(){return typeof o!=="undefined"&&!o.event.triggered?o.event.handle.apply(arguments.callee.elem,arguments):g});J.elem=I;o.each(F.split(/\s+/),function(M,N){var O=N.split(".");N=O.shift();H.type=O.slice().sort().join(".");var L=E[N];if(o.event.specialAll[N]){o.event.specialAll[N].setup.call(I,K,O)}if(!L){L=E[N]={};if(!o.event.special[N]||o.event.special[N].setup.call(I,K,O)===false){if(I.addEventListener){I.addEventListener(N,J,false)}else{if(I.attachEvent){I.attachEvent("on"+N,J)}}}}L[H.guid]=H;o.event.global[N]=true});I=null},guid:1,global:{},remove:function(K,H,J){if(K.nodeType==3||K.nodeType==8){return}var G=o.data(K,"events"),F,E;if(G){if(H===g||(typeof H==="string"&&H.charAt(0)==".")){for(var I in G){this.remove(K,I+(H||""))}}else{if(H.type){J=H.handler;H=H.type}o.each(H.split(/\s+/),function(M,O){var Q=O.split(".");O=Q.shift();var N=RegExp("(^|\\.)"+Q.slice().sort().join(".*\\.")+"(\\.|$)");if(G[O]){if(J){delete G[O][J.guid]}else{for(var P in G[O]){if(N.test(G[O][P].type)){delete G[O][P]}}}if(o.event.specialAll[O]){o.event.specialAll[O].teardown.call(K,Q)}for(F in G[O]){break}if(!F){if(!o.event.special[O]||o.event.special[O].teardown.call(K,Q)===false){if(K.removeEventListener){K.removeEventListener(O,o.data(K,"handle"),false)}else{if(K.detachEvent){K.detachEvent("on"+O,o.data(K,"handle"))}}}F=null;delete G[O]}}})}for(F in G){break}if(!F){var L=o.data(K,"handle");if(L){L.elem=null}o.removeData(K,"events");o.removeData(K,"handle")}}},trigger:function(I,K,H,E){var G=I.type||I;if(!E){I=typeof I==="object"?I[h]?I:o.extend(o.Event(G),I):o.Event(G);if(G.indexOf("!")>=0){I.type=G=G.slice(0,-1);I.exclusive=true}if(!H){I.stopPropagation();if(this.global[G]){o.each(o.cache,function(){if(this.events&&this.events[G]){o.event.trigger(I,K,this.handle.elem)}})}}if(!H||H.nodeType==3||H.nodeType==8){return g}I.result=g;I.target=H;K=o.makeArray(K);K.unshift(I)}I.currentTarget=H;var J=o.data(H,"handle");if(J){J.apply(H,K)}if((!H[G]||(o.nodeName(H,"a")&&G=="click"))&&H["on"+G]&&H["on"+G].apply(H,K)===false){I.result=false}if(!E&&H[G]&&!I.isDefaultPrevented()&&!(o.nodeName(H,"a")&&G=="click")){this.triggered=true;try{H[G]()}catch(L){}}this.triggered=false;if(!I.isPropagationStopped()){var F=H.parentNode||H.ownerDocument;if(F){o.event.trigger(I,K,F,true)}}},handle:function(K){var J,E;K=arguments[0]=o.event.fix(K||l.event);K.currentTarget=this;var L=K.type.split(".");K.type=L.shift();J=!L.length&&!K.exclusive;var I=RegExp("(^|\\.)"+L.slice().sort().join(".*\\.")+"(\\.|$)");E=(o.data(this,"events")||{})[K.type];for(var G in E){var H=E[G];if(J||I.test(H.type)){K.handler=H;K.data=H.data;var F=H.apply(this,arguments);if(F!==g){K.result=F;if(F===false){K.preventDefault();K.stopPropagation()}}if(K.isImmediatePropagationStopped()){break}}}},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(H){if(H[h]){return H}var F=H;H=o.Event(F);for(var G=this.props.length,J;G;){J=this.props[--G];H[J]=F[J]}if(!H.target){H.target=H.srcElement||document}if(H.target.nodeType==3){H.target=H.target.parentNode}if(!H.relatedTarget&&H.fromElement){H.relatedTarget=H.fromElement==H.target?H.toElement:H.fromElement}if(H.pageX==null&&H.clientX!=null){var I=document.documentElement,E=document.body;H.pageX=H.clientX+(I&&I.scrollLeft||E&&E.scrollLeft||0)-(I.clientLeft||0);H.pageY=H.clientY+(I&&I.scrollTop||E&&E.scrollTop||0)-(I.clientTop||0)}if(!H.which&&((H.charCode||H.charCode===0)?H.charCode:H.keyCode)){H.which=H.charCode||H.keyCode}if(!H.metaKey&&H.ctrlKey){H.metaKey=H.ctrlKey}if(!H.which&&H.button){H.which=(H.button&1?1:(H.button&2?3:(H.button&4?2:0)))}return H},proxy:function(F,E){E=E||function(){return F.apply(this,arguments)};E.guid=F.guid=F.guid||E.guid||this.guid++;return E},special:{ready:{setup:B,teardown:function(){}}},specialAll:{live:{setup:function(E,F){o.event.add(this,F[0],c)},teardown:function(G){if(G.length){var E=0,F=RegExp("(^|\\.)"+G[0]+"(\\.|$)");o.each((o.data(this,"events").live||{}),function(){if(F.test(this.type)){E++}});if(E<1){o.event.remove(this,G[0],c)}}}}}};o.Event=function(E){if(!this.preventDefault){return new o.Event(E)}if(E&&E.type){this.originalEvent=E;this.type=E.type}else{this.type=E}this.timeStamp=e();this[h]=true};function k(){return false}function u(){return true}o.Event.prototype={preventDefault:function(){this.isDefaultPrevented=u;var E=this.originalEvent;if(!E){return}if(E.preventDefault){E.preventDefault()}E.returnValue=false},stopPropagation:function(){this.isPropagationStopped=u;var E=this.originalEvent;if(!E){return}if(E.stopPropagation){E.stopPropagation()}E.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=u;this.stopPropagation()},isDefaultPrevented:k,isPropagationStopped:k,isImmediatePropagationStopped:k};var a=function(F){var E=F.relatedTarget;while(E&&E!=this){try{E=E.parentNode}catch(G){E=this}}if(E!=this){F.type=F.data;o.event.handle.apply(this,arguments)}};o.each({mouseover:"mouseenter",mouseout:"mouseleave"},function(F,E){o.event.special[E]={setup:function(){o.event.add(this,F,a,E)},teardown:function(){o.event.remove(this,F,a)}}});o.fn.extend({bind:function(F,G,E){return F=="unload"?this.one(F,G,E):this.each(function(){o.event.add(this,F,E||G,E&&G)})},one:function(G,H,F){var E=o.event.proxy(F||H,function(I){o(this).unbind(I,E);return(F||H).apply(this,arguments)});return this.each(function(){o.event.add(this,G,E,F&&H)})},unbind:function(F,E){return this.each(function(){o.event.remove(this,F,E)})},trigger:function(E,F){return this.each(function(){o.event.trigger(E,F,this)})},triggerHandler:function(E,G){if(this[0]){var F=o.Event(E);F.preventDefault();F.stopPropagation();o.event.trigger(F,G,this[0]);return F.result}},toggle:function(G){var E=arguments,F=1;while(Fa text ';var H=K.getElementsByTagName("*"),E=K.getElementsByTagName("a")[0];if(!H||!H.length||!E){return}o.support={leadingWhitespace:K.firstChild.nodeType==3,tbody:!K.getElementsByTagName("tbody").length,objectAll:!!K.getElementsByTagName("object")[0].getElementsByTagName("*").length,htmlSerialize:!!K.getElementsByTagName("link").length,style:/red/.test(E.getAttribute("style")),hrefNormalized:E.getAttribute("href")==="/a",opacity:E.style.opacity==="0.5",cssFloat:!!E.style.cssFloat,scriptEval:false,noCloneEvent:true,boxModel:null};G.type="text/javascript";try{G.appendChild(document.createTextNode("window."+J+"=1;"))}catch(I){}F.insertBefore(G,F.firstChild);if(l[J]){o.support.scriptEval=true;delete l[J]}F.removeChild(G);if(K.attachEvent&&K.fireEvent){K.attachEvent("onclick",function(){o.support.noCloneEvent=false;K.detachEvent("onclick",arguments.callee)});K.cloneNode(true).fireEvent("onclick")}o(function(){var L=document.createElement("div");L.style.width=L.style.paddingLeft="1px";document.body.appendChild(L);o.boxModel=o.support.boxModel=L.offsetWidth===2;document.body.removeChild(L).style.display="none"})})();var w=o.support.cssFloat?"cssFloat":"styleFloat";o.props={"for":"htmlFor","class":"className","float":w,cssFloat:w,styleFloat:w,readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",tabindex:"tabIndex"};o.fn.extend({_load:o.fn.load,load:function(G,J,K){if(typeof G!=="string"){return this._load(G)}var I=G.indexOf(" ");if(I>=0){var E=G.slice(I,G.length);G=G.slice(0,I)}var H="GET";if(J){if(o.isFunction(J)){K=J;J=null}else{if(typeof J==="object"){J=o.param(J);H="POST"}}}var F=this;o.ajax({url:G,type:H,dataType:"html",data:J,complete:function(M,L){if(L=="success"||L=="notmodified"){F.html(E?o("
").append(M.responseText.replace(/
diff --git a/config/routes.rb b/config/routes.rb
index 43d27ce4f..c77a1e892 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -351,6 +351,7 @@ RedmineApp::Application.routes.draw do
get "search_user_course"
post "add_exist_file_to_course"
get 'resource_preview'
+ post 'rename_resource'
# end
end
end
From 27ff5471ec0aaeba36739572b4468766b4dbfc76 Mon Sep 17 00:00:00 2001
From: cxt
Date: Tue, 18 Aug 2015 14:40:12 +0800
Subject: [PATCH 20/90] =?UTF-8?q?=E8=B6=85=E7=BA=A7=E7=AE=A1=E7=90=86?=
=?UTF-8?q?=E5=91=98=E6=96=B0=E5=A2=9E=E5=8A=9F=E8=83=BD=E9=A1=B5=E9=9D=A2?=
=?UTF-8?q?=E7=9A=84=E5=88=86=E9=A1=B5=E3=80=81=E6=B7=BB=E5=8A=A0=E8=B6=85?=
=?UTF-8?q?=E9=93=BE=E6=8E=A5=EF=BC=8C=E6=B7=BB=E5=8A=A0=E6=9F=A5=E8=AF=A2?=
=?UTF-8?q?=E6=9D=A1=E4=BB=B6=E3=80=82?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/controllers/admin_controller.rb | 66 +++++++++++----------
app/views/admin/course_messages.html.erb | 9 ++-
app/views/admin/homework.html.erb | 8 ++-
app/views/admin/latest_login_users.html.erb | 25 +++++++-
app/views/admin/leave_messages.html.erb | 37 ++++++++----
app/views/admin/messages_list.html.erb | 14 ++---
app/views/admin/notices.html.erb | 8 ++-
app/views/admin/project_messages.html.erb | 10 +++-
db/schema.rb | 8 +--
9 files changed, 118 insertions(+), 67 deletions(-)
diff --git a/app/controllers/admin_controller.rb b/app/controllers/admin_controller.rb
index 25536615a..1624008f2 100644
--- a/app/controllers/admin_controller.rb
+++ b/app/controllers/admin_controller.rb
@@ -397,19 +397,10 @@ class AdminController < ApplicationController
#留言列表
def leave_messages
- @jour = JournalsForMessage.where("jour_type = 'Principal' or jour_type = 'Course'").reorder('created_on desc')
- case params[:format]
- when 'xml', 'json'
- @offset, @limit = api_offset_and_limit({:limit => 30})
- else
- @limit = 30#per_page_option
- end
-
- @jour_count = @jour.count
- @jour_pages = Paginator.new @jour_count, @limit, params['page']
- @offset ||= @jour_pages.offset
- @jour = @jour.limit(@limit).offset(@offset).all
-
+ @jour = JournalsForMessage.find_by_sql("SELECT * FROM journals_for_messages AS j1
+ WHERE j1.jour_type IN ('Course','Principal') AND (j1.m_parent_id IS NULL OR (j1.m_parent_id IN (SELECT id FROM journals_for_messages WHERE jour_type IN ('Course','Principal')))) order by created_on desc")
+ @jour = paginateHelper @jour,30
+ @page = (params['page'] || 1).to_i - 1
respond_to do |format|
format.html
end
@@ -418,21 +409,8 @@ class AdminController < ApplicationController
#帖子
def messages_list
@memo = Memo.reorder("created_at desc")
-
-=begin
- case params[:format]
- when 'xml', 'json'
- @offset, @limit = api_offset_and_limit({:limit => 30})
- else
- @limit = 30#per_page_option
- end
-
- @memo_count = @memo.count
- @memo_pages = Paginator.new @memo_count, @limit, params['page']
- @offset ||= @memo_pages.offset
- @memo = @memo.limit(@limit).offset(@offset).all
-=end
-
+ @memo = paginateHelper @memo,30
+ @page = (params['page'] || 1).to_i - 1
respond_to do |format|
format.html
end
@@ -440,29 +418,55 @@ class AdminController < ApplicationController
#课程讨论区的帖子
def course_messages
- #@boards=Board.where('course_id is NULL')
- #@course_ms = Message.reorder('created_on desc')
@course_ms=Message.joins("join boards on messages.board_id=boards.id where boards.course_id is not NULL").reorder('created_on desc')
+ @course_ms = paginateHelper @course_ms,30
+ @page = (params['page'] || 1).to_i - 1
+ respond_to do |format|
+ format.html
+ end
end
#项目讨论区的帖子
def project_messages
@project_ms=Message.joins("join boards on messages.board_id=boards.id where boards.project_id != -1").reorder('created_on desc')
+ @project_ms = paginateHelper @project_ms,30
+ @page = (params['page'] || 1).to_i - 1
+ respond_to do |format|
+ format.html
+ end
end
#通知
def notices
@news = News.where('course_id is not NULL').order('created_on desc')
+ @news = paginateHelper @news,30
+ @page = (params['page'] || 1).to_i - 1
+ respond_to do |format|
+ format.html
+ end
end
#最近登录用户列表
def latest_login_users
- @user = User.order('last_login_on desc')
+ scope = User.order('last_login_on desc')
+ scope = scope.where("last_login_on>= '#{params[:startdate]} 00:00:00'") if params[:startdate].present?
+ scope =scope.where("last_login_on <= '#{params[:enddate]} 23:59:59'") if params[:enddate].present?
+ @user = scope
+ @user = paginateHelper @user,30
+ @page = (params['page'] || 1).to_i - 1
+ respond_to do |format|
+ format.html
+ end
end
#作业
def homework
@homework = HomeworkCommon.order('end_time desc')
+ @homework = paginateHelper @homework,30
+ @page = (params['page'] || 1).to_i - 1
+ respond_to do |format|
+ format.html
+ end
end
end
diff --git a/app/views/admin/course_messages.html.erb b/app/views/admin/course_messages.html.erb
index 8564d13dc..3db0a3e11 100644
--- a/app/views/admin/course_messages.html.erb
+++ b/app/views/admin/course_messages.html.erb
@@ -29,7 +29,7 @@
- <% @count=0%>
+ <% @count=@page*30%>
<% for course in @course_ms -%>
<% @count=@count + 1 %>
@@ -51,10 +51,10 @@
<%= format_date(course.created_on) %>
- <%= course.subject %>
+ <%= link_to(course.subject, course_boards_path(Board.where('id=?',course.board_id).first.course_id)) %>
- <%=course.replies_count %>
+ <%= link_to(course.replies_count, course_boards_path(Board.where('id=?',course.board_id).first.course_id)) %>
@@ -62,5 +62,8 @@
+
<% html_title(l(:label_message_plural)) -%>
diff --git a/app/views/admin/homework.html.erb b/app/views/admin/homework.html.erb
index 360ca4e39..7260d68ff 100644
--- a/app/views/admin/homework.html.erb
+++ b/app/views/admin/homework.html.erb
@@ -27,7 +27,7 @@
- <%@count=0 %>
+ <%@count=@page*30 %>
<% for homework in @homework do %>
<% @count+=1 %>
@@ -48,7 +48,7 @@
<% end %>
- <%=StudentWork.where('homework_common_id=?',homework.id).count %>
+ <%=link_to(StudentWork.where('homework_common_id=?',homework.id).count, student_work_index_path(:homework => homework.id))%>
<%=format_date(homework.end_time) %>
@@ -59,4 +59,8 @@
+
+
<% html_title(l(:label_user_homework)) -%>
diff --git a/app/views/admin/latest_login_users.html.erb b/app/views/admin/latest_login_users.html.erb
index dc35daec8..838cc0dcb 100644
--- a/app/views/admin/latest_login_users.html.erb
+++ b/app/views/admin/latest_login_users.html.erb
@@ -1,7 +1,26 @@
+<%= stylesheet_link_tag 'jquery/jquery-ui-1.9.2', :media => 'all' %>
<%=l(:label_latest_login_user_list)%>
+<%= form_tag({}, :method => :get) do %>
+
+
+ <%= l(:label_filter_plural) %>
+
+ 开始日期:
+ <%= text_field_tag 'startdate', params[:startdate], :size => 15, :onchange =>"regexDeadLine();", :style=>"float:left"%>
+ <%= calendar_for('startdate')%>
+ 结束日期:
+ <%= text_field_tag 'enddate', params[:enddate], :size => 15, :onchange =>"regexDeadLine();", :style=>"float:left"%>
+ <%= calendar_for('enddate')%>
+ <%= submit_tag l(:button_apply), :class => "small", :name => nil %>
+ <%= link_to l(:button_clear), {:controller => 'admin', :action => 'latest_login_users'}, :class => 'icon icon-reload' %>
+
+<% end %>
+
+
+
+
+
<% html_title(l(:label_latest_login_user_list)) -%>
diff --git a/app/views/admin/leave_messages.html.erb b/app/views/admin/leave_messages.html.erb
index 975c60b15..360e9b864 100644
--- a/app/views/admin/leave_messages.html.erb
+++ b/app/views/admin/leave_messages.html.erb
@@ -31,7 +31,7 @@
- <% @count=0%>
+ <% @count = @page * 30 %>
<% for journal in @jour -%>
<% @count=@count + 1 %>
">
@@ -49,20 +49,39 @@
<%= journal.jour_id %>
-
- <%= link_to(journal.try(:user).try(:realname).truncate(6, omission: '...'), user_path(journal.user)) %>
+ <%= journal.try(:user)%><% else %><%=journal.try(:user).try(:realname) %><% end %>'>
+ <% if journal.try(:user).try(:realname) == ' '%>
+ <%= link_to(journal.try(:user), user_path(journal.user)) %>
+ <% else %>
+ <%= link_to(journal.try(:user).try(:realname), user_path(journal.user)) %>
+ <% end %>
<%= format_date(journal.created_on) %>
-
- <%= journal.notes.truncate(15, omission: '...') %>
+
+ <%case journal.jour_type %>
+ <% when 'Principal' %>
+ <%= link_to(journal.notes.html_safe, feedback_path(journal.jour_id)) %>
+ <% when 'Course' %>
+ <%= link_to(journal.notes.html_safe, course_feedback_path(journal.jour_id)) %>
+ <% end %>
<% if(journal.m_reply_count) %>
- <%=journal.m_reply_count%>
+ <%case journal.jour_type %>
+ <% when 'Principal' %>
+ <%= link_to(journal.m_reply_count, feedback_path(journal.jour_id)) %>
+ <% when 'Course' %>
+ <%= link_to(journal.m_reply_count, course_feedback_path(journal.jour_id)) %>
+ <% end %>
<% else %>
- <%=0 %>
+ <%case journal.jour_type %>
+ <% when 'Principal' %>
+ <%= link_to(0, feedback_path(journal.jour_id)) %>
+ <% when 'Course' %>
+ <%= link_to(0, course_feedback_path(journal.jour_id)) %>
+ <% end %>
<% end %>
@@ -71,9 +90,7 @@
<% html_title(l(:label_leave_message_list)) -%>
diff --git a/app/views/admin/messages_list.html.erb b/app/views/admin/messages_list.html.erb
index 77cdbbc69..e0c84279d 100644
--- a/app/views/admin/messages_list.html.erb
+++ b/app/views/admin/messages_list.html.erb
@@ -29,7 +29,7 @@
- <% @count=0%>
+ <% @count=@page * 30%>
<% for memo in @memo -%>
<% @count=@count + 1 %>
">
@@ -50,20 +50,18 @@
<%= format_date(memo.created_at) %>
- <%= memo.subject %>
+ <%= link_to(memo.subject, forum_memo_path(memo.forum, memo)) %>
- <%=memo.replies_count %>
+ <%= link_to(memo.replies_count, forum_memo_path(memo.forum, memo)) %>
<% end %>
-
+
<% html_title(l(:label_message_plural)) -%>
diff --git a/app/views/admin/notices.html.erb b/app/views/admin/notices.html.erb
index 56f212720..f03a7b97a 100644
--- a/app/views/admin/notices.html.erb
+++ b/app/views/admin/notices.html.erb
@@ -33,7 +33,7 @@
- <% @count=0%>
+ <% @count=@page * 30%>
<% for news in @news -%>
<% @count=@count + 1 %>
">
@@ -63,7 +63,7 @@
<%= link_to(news.title, news_path(news)) %>
- <%=news.comments_count %>
+ <%= link_to(news.comments_count, news_path(news)) %>
<% end %>
@@ -71,4 +71,8 @@
+
+
<% html_title(l(:label_notification_list)) -%>
diff --git a/app/views/admin/project_messages.html.erb b/app/views/admin/project_messages.html.erb
index af2978422..dc44a7cba 100644
--- a/app/views/admin/project_messages.html.erb
+++ b/app/views/admin/project_messages.html.erb
@@ -29,7 +29,7 @@
- <% @count=0%>
+ <% @count=@page * 30 %>
<% for project in @project_ms -%>
<% @count=@count + 1 %>
@@ -51,10 +51,10 @@
<%= format_date(project.created_on) %>
- <%= project.subject %>
+ <%= link_to(project.subject, project_boards_path(Board.where('id=?',project.board_id).first.project_id)) %>
- <%=project.replies_count %>
+ <%= link_to(project.replies_count, project_boards_path(Board.where('id=?',project.board_id).first.project_id)) %>
@@ -63,4 +63,8 @@
+
+
<% html_title(l(:label_message_plural)) -%>
diff --git a/db/schema.rb b/db/schema.rb
index 8d78a9ca0..841bcc7e9 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -474,13 +474,6 @@ ActiveRecord::Schema.define(:version => 20150815030833) do
add_index "delayed_jobs", ["priority", "run_at"], :name => "delayed_jobs_priority"
- create_table "discuss_demos", :force => true do |t|
- t.string "title"
- t.text "body"
- t.datetime "created_at", :null => false
- t.datetime "updated_at", :null => false
- end
-
create_table "documents", :force => true do |t|
t.integer "project_id", :default => 0, :null => false
t.integer "category_id", :default => 0, :null => false
@@ -893,6 +886,7 @@ ActiveRecord::Schema.define(:version => 20150815030833) do
t.datetime "created_on"
t.integer "comments_count", :default => 0, :null => false
t.integer "course_id"
+ t.datetime "updated_on"
end
add_index "news", ["author_id"], :name => "index_news_on_author_id"
From 3e4f726855de4448c0fa8e6d7f2a2984d81a785c Mon Sep 17 00:00:00 2001
From: ouyangxuhua
Date: Tue, 18 Aug 2015 14:43:15 +0800
Subject: [PATCH 21/90] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=95=99=E8=A8=80?=
=?UTF-8?q?=E3=80=81=E6=8C=87=E6=B4=BE=E7=BB=99=E6=88=91?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/controllers/users_controller.rb | 3 +++
app/views/users/user_messages.html.erb | 34 +++++++++++++++++++++++---
2 files changed, 34 insertions(+), 3 deletions(-)
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 770d7d049..dbcbdefa6 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -126,6 +126,9 @@ class UsersController < ApplicationController
when 'issue'
@user_forge_messages = ForgeMessage.where("forge_message_type =? and user_id =?", "Issue", @user).order("created_at desc")
@user_course_messages = nil
+ when 'journal'
+ @user_forge_messages = ForgeMessage.where("forge_message_type =? and user_id =?", "Journal", @user).order("created_at desc")
+ @user_course_messages = nil
end
respond_to do |format|
format.html{render :layout=>'base_users_new'}
diff --git a/app/views/users/user_messages.html.erb b/app/views/users/user_messages.html.erb
index 2e7b110bf..c23ad3716 100644
--- a/app/views/users/user_messages.html.erb
+++ b/app/views/users/user_messages.html.erb
@@ -14,6 +14,7 @@
<%= link_to "问卷调查",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user, :type => 'poll'} %>
<%= link_to "指派给我",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user, :type => 'issue'} %>
+ <%= link_to "问题更新",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user, :type => 'journal'} %>
@@ -76,9 +77,36 @@
<% unless @user_forge_messages.nil? %>
<% @user_forge_messages.each do |ufm| %>
- <% if ufm.forge_message_type == "Issue" %>
- 22222
- <% end %>
+ <% if ufm.forge_message_type == "Issue" %>
+
+ <% end %>
+ <% if ufm.forge_message_type == "Journal" %>
+
+ <% end %>
<% end %>
<% end %>
<% else %>
From 9c4e89177f68967aa0537dc390737c6ea6ad463a Mon Sep 17 00:00:00 2001
From: ouyangxuhua
Date: Tue, 18 Aug 2015 14:44:46 +0800
Subject: [PATCH 22/90] =?UTF-8?q?=E7=95=99=E8=A8=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/views/users/user_messages.html.erb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/views/users/user_messages.html.erb b/app/views/users/user_messages.html.erb
index c23ad3716..77b7d5898 100644
--- a/app/views/users/user_messages.html.erb
+++ b/app/views/users/user_messages.html.erb
@@ -14,7 +14,7 @@
<%= link_to "问卷调查",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user, :type => 'poll'} %>
<%= link_to "指派给我",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user, :type => 'issue'} %>
- <%= link_to "问题更新",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user, :type => 'journal'} %>
+ <%= link_to "我的留言",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user, :type => 'journal'} %>
From 7219586b1e1cfb34b258052f6ab7ecaf3bfda01e Mon Sep 17 00:00:00 2001
From: lizanle <491823689@qq.com>
Date: Tue, 18 Aug 2015 15:25:36 +0800
Subject: [PATCH 23/90] =?UTF-8?q?=E8=B5=84=E6=BA=90=E5=BA=93?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/controllers/users_controller.rb | 37 ++++++++++++++---
.../users/_resource_search_form.html.erb | 7 ++++
app/views/users/_resources_list.html.erb | 2 +-
app/views/users/rename_resource.js.erb | 1 +
app/views/users/resource_preview.js.erb | 2 +
app/views/users/user_resource.html.erb | 41 ++++++++++---------
app/views/users/user_resource.js.erb | 1 +
7 files changed, 65 insertions(+), 26 deletions(-)
create mode 100644 app/views/users/_resource_search_form.html.erb
create mode 100644 app/views/users/rename_resource.js.erb
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 0df07acff..6bbfbd12b 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -40,7 +40,8 @@ class UsersController < ApplicationController
:user_watchlist, :user_fanslist,:update, :user_courses, :user_homeworks, :watch_projects, :show_score, :topic_score_index, :project_score_index,
:activity_score_index, :influence_score_index, :score_index,:show_new_score, :topic_new_score_index, :project_new_score_index,
:activity_new_score_index, :influence_new_score_index, :score_new_index,:update_score,:user_activities,:user_projects_index,
- :user_courses4show,:user_projects4show,:user_course_activities,:user_project_activities,:user_feedback4show,:user_visitorlist]
+ :user_courses4show,:user_projects4show,:user_course_activities,:user_project_activities,:user_feedback4show,:user_visitorlist,
+ :user_resource,:user_resource_create,:user_resource_delete,:rename_resource,:search_user_course,:add_exist_file_to_course,:resource_preview,:resource_search]
#edit has been deleted by huang, 2013-9-23
before_filter :find_user, :only => [:user_fanslist, :user_watchlist, :show, :edit, :update, :destroy, :edit_membership, :user_courses,
:user_homeworks, :destroy_membership, :user_activities, :user_projects, :user_newfeedback, :user_comments,
@@ -1139,11 +1140,37 @@ class UsersController < ApplicationController
# 根据资源关键字进行搜索
def resource_search
search = params[:search].to_s.strip.downcase
- if User.current.id == params[:id]
- @attachments = Attachment.where("author_id = #{params[:id]} and container_type not in ('Version','PhoneAppVersion','StudentWork') and (filename like '%#{search}%') ").order("created_on desc")
- else
- @attachments = Attachment.where("author_id = #{params[:id]} and container_type not in ('Version','PhoneAppVersion','StudentWork') and is_public = 1 and (filename like '%#{search}%') ").order("created_on desc")
+ # if User.current.id == params[:id]
+ # @attachments = Attachment.where("author_id = #{params[:id]} and container_type not in ('Version','PhoneAppVersion','StudentWork') and (filename like '%#{search}%') ").order("created_on desc")
+ # else
+ # @attachments = Attachment.where("author_id = #{params[:id]} and container_type not in ('Version','PhoneAppVersion','StudentWork') and is_public = 1 and (filename like '%#{search}%') ").order("created_on desc")
+ # end
+ if(params[:type].nil? || params[:type] == "1") #全部
+ if User.current.id == params[:id]
+ @attachments = Attachment.where("author_id = #{params[:id]} and container_type in('Project','Principal','Course','Issue','Document','Message','News','StudentWorkScore','HomewCommon') and (filename like '%#{search}%') ").order("created_on desc")
+ else
+ @attachments = Attachment.where("author_id = #{params[:id]} and is_public = 1 and container_type in('Project','Principal','Course','Issue','Document','Message','News','StudentWorkScore','HomewCommon') and (filename like '%#{search}%') ").order("created_on desc")
+ end
+ elsif params[:type] == "2" #课程资源
+ if User.current.id == params[:id]
+ @attachments = Attachment.where("author_id = #{params[:id]} and container_type = 'Course' and (filename like '%#{search}%')").order("created_on desc")
+ else
+ @attachments = Attachment.where("author_id = #{params[:id]} and is_public = 1 and container_type = 'Course' and (filename like '%#{search}%') ").order("created_on desc")
+ end
+ elsif params[:type] == "3" #项目资源
+ if User.current.id == params[:id]
+ @attachments = Attachment.where("author_id = #{params[:id]} and container_type = 'Project' and (filename like '%#{search}%')").order("created_on desc")
+ else
+ @attachments = Attachment.where("author_id = #{params[:id]} and is_public = 1 and container_type = 'Project' and (filename like '%#{search}%') ").order("created_on desc")
+ end
+ elsif params[:type] == "4" #附件
+ if User.current.id == params[:id]
+ @attachments = Attachment.where("author_id = #{params[:id]} and container_type in('Project','Issue','Document','Message','News','StudentWorkScore','HomewCommon') and (filename like '%#{search}%')").order("created_on desc")
+ else
+ @attachments = Attachment.where("author_id = #{params[:id]} and is_public = 1 and container_type in('Issue','Document','Message','News','StudentWorkScore','HomewCommon') and (filename like '%#{search}%')").order("created_on desc")
+ end
end
+ @type = params[:type]
respond_to do |format|
format.js
end
diff --git a/app/views/users/_resource_search_form.html.erb b/app/views/users/_resource_search_form.html.erb
new file mode 100644
index 000000000..0c48514b3
--- /dev/null
+++ b/app/views/users/_resource_search_form.html.erb
@@ -0,0 +1,7 @@
+<%= form_tag( url_for(:controller => 'users',:action => 'resource_search',:id=>user.id),
+ :remote=>true ,:method => 'post',:class=>'resourcesSearchloadBox',:id=>'resource_search_form') do %>
+
+ <%= hidden_field_tag(:type,type) %>
+ <%= submit_tag '',:class=>'searchIcon',:style=>'border-style:none' %>
+
+<% end %>
\ No newline at end of file
diff --git a/app/views/users/_resources_list.html.erb b/app/views/users/_resources_list.html.erb
index 078ee2c94..6f9ba0fee 100644
--- a/app/views/users/_resources_list.html.erb
+++ b/app/views/users/_resources_list.html.erb
@@ -5,7 +5,7 @@
<%= link_to truncate(attach.filename,:length=>18), download_named_attachment_path(attach.id, attach.filename),
- :title => attach.filename+"\n"+attach.description.to_s,:class=>'resourcesBlack'%>
+ :title => attach.filename,:class=>'resourcesBlack'%>
<%= number_to_human_size(attach.filesize) %>
<%= get_resource_type(attach.container_type)%>
diff --git a/app/views/users/rename_resource.js.erb b/app/views/users/rename_resource.js.erb
new file mode 100644
index 000000000..5556fb313
--- /dev/null
+++ b/app/views/users/rename_resource.js.erb
@@ -0,0 +1 @@
+alert(1)
\ No newline at end of file
diff --git a/app/views/users/resource_preview.js.erb b/app/views/users/resource_preview.js.erb
index a38d46374..c3e1fb3ab 100644
--- a/app/views/users/resource_preview.js.erb
+++ b/app/views/users/resource_preview.js.erb
@@ -1,3 +1,5 @@
<% if @preview_able %>
top.location.href = '<%=download_named_attachment_path(@file.id, @file.filename, preview: true) %>'
+<% else %>
+window.alert('该资源不可预览')
<% end %>
\ No newline at end of file
diff --git a/app/views/users/user_resource.html.erb b/app/views/users/user_resource.html.erb
index d9b992129..1c54fc67e 100644
--- a/app/views/users/user_resource.html.erb
+++ b/app/views/users/user_resource.html.erb
@@ -71,13 +71,9 @@
-
- <%= form_tag( url_for(:controller => 'users',:action => 'resource_search',:id=>@user.id),
- :remote=>true ,:method => 'post',:class=>'resourcesSearchloadBox',:id=>'resource_search_form') do %>
-
- <%= submit_tag '',:class=>'searchIcon',:style=>'border-style:none' %>
-
- <% end %>
+
+ <%= render :partial => 'resource_search_form',:locals => {:user=>@user,:type=>@type} %>
+
@@ -168,7 +164,7 @@ $(".resourcesList").click(function(e) {
}
//将当前行改变为白色
line.children().css("background-color", 'white');
- //当前行恢复编辑状态
+ //当前行恢复编辑状态到链接状态
if(ele.nodeName != 'INPUT') {
restore();
}
@@ -210,6 +206,7 @@ $(".resourcesList").click(function(e) {
'"/>
'+
'<% end %>');
$("#res_name").focus();
+ document.getElementById('res_name').scrollIntoView()
}
String.prototype.trim = function() {
var str = this,
@@ -219,38 +216,42 @@ $(".resourcesList").click(function(e) {
while (ws.test(str.charAt(--i)));
return str.slice(0, i + 1);
}
+
+ //恢复编辑状态到链接状态
+ //如果当前是编辑状态,任何的不在输入框里的单击右键事件都需要将编辑状态变回链接状态
+ //如果是编辑状态,且做了修改,那么久要进行修改,并且将修改值经过处理替换到页面显示
function restore(){
+ //上一行不为空 且链接不为空
if( last_line != null && res_link != null && res_link != '') {
- name = $("#res_name").val().trim();
- if(name != res_name.trim()){
+ name = $("#res_name") ? $("#res_name").val().trim() : $("#res_name") ;
+ if( name && name != res_name.trim()){
if(confirm('确定修改为 '+name)){
- //$("#res_name_form").submit();
-// $.ajax({
-// type:'post',
-// url:'<%#=rename_resource_user_path(@user) %>',
-// data: $("#res_name_form").serialize()
-// });
$.post(
'<%=rename_resource_user_path(@user) %>',
$("#res_name_form").serialize(),
function (data){
- if(data =='sucess'){
+ if(data =='sucess'){//修改成功,那么将链接恢复,并且将链接的显示内容改变。链接可以不变
last_line.children().first().html(res_link);
last_line.children().first().children().attr('title',name);
- last_line.children().first().children().html(name);
+ last_line.children().first().children().html(name.length > 17? name.substring(0,17)+'...' : name);
}else{
last_line.children().first().html(res_link);
+ res_link = null; //如果修改失败,恢复之后将res_link置空
}
},
'text'
);
}else{
- //last_line.children().first().html(res_link);
+ last_line.children().first().html(res_link);
+ res_link = null; //如果没有做修改,恢复之后将res_link置空
}
}else {
last_line.children().first().html(res_link);
+ res_link = null;//如果没有做修改,恢复之后将res_link置空
}
+
+
}
}
@@ -261,7 +262,7 @@ $(".resourcesList").click(function(e) {
}
line.children().css("background-color", 'white');
id = line.children().last().html();
- if (confirm('确定要删除资源' + line.children().first().children().attr('title').trim() + '么')){
+ if (confirm('确定要删除资源"' + line.children().first().children().attr('title').trim() + '"么?')){
$.ajax({
type: 'post',
url: '<%= user_resource_delete_user_path(@user)%>' + '?resource_id=' + id
diff --git a/app/views/users/user_resource.js.erb b/app/views/users/user_resource.js.erb
index 69fc3dd43..d69a769af 100644
--- a/app/views/users/user_resource.js.erb
+++ b/app/views/users/user_resource.js.erb
@@ -1 +1,2 @@
+$("#search_div").html('<%= escape_javascript( render :partial => 'resource_search_form',:locals => {:user=>@user,:type=>@type} ) %>');
$("#resources_list").html('<%= escape_javascript( render :partial => 'resources_list' ,:locals=>{ :attachments => @attachments})%>');
\ No newline at end of file
From 6b5547462338521b53a9da9548a488b699e76de5 Mon Sep 17 00:00:00 2001
From: huang
Date: Tue, 18 Aug 2015 15:27:16 +0800
Subject: [PATCH 24/90] =?UTF-8?q?=E4=BD=9C=E5=93=81=E8=A2=AB=E8=AF=84?=
=?UTF-8?q?=E9=98=85=20=E4=BD=9C=E5=93=81=E8=A2=AB=E5=9B=9E=E5=A4=8D=20?=
=?UTF-8?q?=E6=B6=88=E6=81=AF=E9=80=9A=E7=9F=A5?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/controllers/users_controller.rb | 4 ++++
app/models/journals_for_message.rb | 13 ++++++++++++-
app/models/student_works_score.rb | 11 +++++++++++
app/views/users/user_messages.html.erb | 2 +-
4 files changed, 28 insertions(+), 2 deletions(-)
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 770d7d049..3e50f3131 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -97,6 +97,8 @@ class UsersController < ApplicationController
end
# 用户消息
+ # 说明: homework 发布作业;message:讨论区; news:新闻; poll:问卷;works_reviewers:作品评阅
+ # issue:问题;
def user_messages
unless User.current.logged?
render_403
@@ -123,6 +125,8 @@ class UsersController < ApplicationController
@user_forge_messages = ForgeMessage.where("forge_message_type =? and user_id =?", "News", @user).order("created_at desc")
when 'poll'
@user_course_messages = CourseMessage.where("course_message_type =? and user_id =?", "Poll", @user).order("created_at desc")
+ when 'works_reviewers'
+ @user_course_messages = CourseMessage.where("course_message_type =? and user_id =?", "StudentWorksScore", @user).order("created_at desc")
when 'issue'
@user_forge_messages = ForgeMessage.where("forge_message_type =? and user_id =?", "Issue", @user).order("created_at desc")
@user_course_messages = nil
diff --git a/app/models/journals_for_message.rb b/app/models/journals_for_message.rb
index bcae58174..da19ba1f2 100644
--- a/app/models/journals_for_message.rb
+++ b/app/models/journals_for_message.rb
@@ -58,9 +58,11 @@ class JournalsForMessage < ActiveRecord::Base
has_many :acts, :class_name => 'Activity', :as => :act, :dependent => :destroy
# 课程动态
has_many :course_acts, :class_name => 'CourseActivity',:as =>:course_act ,:dependent => :destroy
+ # 消息关联
+ has_many :course_messages, :class_name => 'CourseMessage',:as =>:course_message ,:dependent => :destroy
validates :notes, presence: true, if: :is_homework_jour?
- after_create :act_as_activity, :act_as_course_activity
+ after_create :act_as_activity, :act_as_course_activity, :act_as_course_message
after_create :reset_counters!
after_destroy :reset_counters!
after_save :be_user_score
@@ -186,4 +188,13 @@ class JournalsForMessage < ActiveRecord::Base
self.course_acts << CourseActivity.new(:user_id => self.user_id,:course_id => self.jour_id)
end
end
+
+ # 课程作品留言消息通知
+ def act_as_course_message
+ if self.jour_type == 'StudentWorksScore'
+ if self.user_id != self.jour.user_id
+ self.course_messages << CourseMessage.new(:user_id => self.jour.user_id,:course_id => self.jour.student_work.homework_common.course.id)
+ end
+ end
+ end
end
diff --git a/app/models/student_works_score.rb b/app/models/student_works_score.rb
index 8fa14f8de..639722389 100644
--- a/app/models/student_works_score.rb
+++ b/app/models/student_works_score.rb
@@ -5,6 +5,17 @@ class StudentWorksScore < ActiveRecord::Base
belongs_to :user
belongs_to :student_work
has_many :journals_for_messages, :as => :jour, :dependent => :destroy
+ has_many :course_messages, :class_name =>'CourseMessage', :as => :course_message, :dependent => :destroy
acts_as_attachable
+
+ after_create :act_as_course_message
+
+ # 评阅作品消息提示
+ def act_as_course_message
+ if self.student_work
+ receiver = self.student_work.user
+ self.course_messages << CourseMessage.new(:user_id => receiver.id, :course_id => self.student_work.homework_common.course.id, :viewed => false)
+ end
+ end
end
diff --git a/app/views/users/user_messages.html.erb b/app/views/users/user_messages.html.erb
index 2e7b110bf..93e0fe967 100644
--- a/app/views/users/user_messages.html.erb
+++ b/app/views/users/user_messages.html.erb
@@ -22,7 +22,7 @@
<% if @new_message_count >0 %>
<% unless @user_course_messages.nil? %>
- <% @user_course_messages.each do |ucm| %>
+ <% @user_course_messages.each do |ucm| %>
<% if ucm.course_message_type == "News" %>
<%= image_tag(url_to_avatar(ucm.course_message.author), :width => "30", :height => "30") %>
From 32aef6f2891fd0fd50edd29b2ea88dc6c941c402 Mon Sep 17 00:00:00 2001
From: lizanle <491823689@qq.com>
Date: Tue, 18 Aug 2015 15:36:15 +0800
Subject: [PATCH 25/90] =?UTF-8?q?=E8=B5=84=E6=BA=90=E5=BA=93?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/views/users/user_resource.html.erb | 7 -------
1 file changed, 7 deletions(-)
diff --git a/app/views/users/user_resource.html.erb b/app/views/users/user_resource.html.erb
index 1c54fc67e..98984b3f9 100644
--- a/app/views/users/user_resource.html.erb
+++ b/app/views/users/user_resource.html.erb
@@ -28,8 +28,6 @@
function closeModal()
{
- //hideModal($("#popbox_upload"));
- //$("#attachments_fields").html('');
$("#upload_box").css("display","none");
}
@@ -48,19 +46,15 @@
-
<%= link_to '全部' ,user_resource_user_path(:id=>@user.id,:type=>1),:remote=>true,:method => 'get',:class=>'resourcesGrey' %>
-
<%= link_to '课程资源' ,user_resource_user_path(:id=>@user.id,:type=>2),:remote=>true,:method => 'get',:class=>'resourcesGrey' %>
-
<%= link_to '项目资源' ,user_resource_user_path(:id=>@user.id,:type=>3),:remote=>true,:method => 'get',:class=>'resourcesGrey' %>
-
<%= link_to '附件' ,user_resource_user_path(:id=>@user.id,:type=>4),:remote=>true,:method => 'get',:class=>'resourcesGrey' %>
@@ -73,7 +67,6 @@
上传资源
<%= render :partial => 'resource_search_form',:locals => {:user=>@user,:type=>@type} %>
-
From 375c016783b00bbbae617181011af267593b797c Mon Sep 17 00:00:00 2001
From: lizanle <491823689@qq.com>
Date: Tue, 18 Aug 2015 15:42:36 +0800
Subject: [PATCH 26/90] =?UTF-8?q?=E8=B5=84=E6=BA=90=E5=BA=93?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/views/users/user_resource.html.erb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/views/users/user_resource.html.erb b/app/views/users/user_resource.html.erb
index 98984b3f9..f5a6c57f0 100644
--- a/app/views/users/user_resource.html.erb
+++ b/app/views/users/user_resource.html.erb
@@ -199,7 +199,7 @@ $(".resourcesList").click(function(e) {
'"/>
'+
'<% end %>');
$("#res_name").focus();
- document.getElementById('res_name').scrollIntoView()
+ $("html,body").animate({scrollTop:$("#res_name").offset().top},1000)
}
String.prototype.trim = function() {
var str = this,
From 5f2965540655e8f440f249ba1e6c1502531683d1 Mon Sep 17 00:00:00 2001
From: huang
Date: Tue, 18 Aug 2015 16:35:19 +0800
Subject: [PATCH 27/90] =?UTF-8?q?issue=E7=8A=B6=E6=80=81=E6=9B=B4=E6=96=B0?=
=?UTF-8?q?=E6=98=BE=E7=A4=BA?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/views/users/user_messages.html.erb | 125 +++++++++++++------------
1 file changed, 63 insertions(+), 62 deletions(-)
diff --git a/app/views/users/user_messages.html.erb b/app/views/users/user_messages.html.erb
index af2ebd902..03cdda8ad 100644
--- a/app/views/users/user_messages.html.erb
+++ b/app/views/users/user_messages.html.erb
@@ -14,69 +14,69 @@
<%= link_to "问卷调查",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user, :type => 'poll'} %>
<%= link_to "指派给我",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user, :type => 'issue'} %>
- <%= link_to "我的留言",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user, :type => 'journal'} %>
+ <%= link_to "我的留言",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user, :type => 'issue_update'} %>
- <% if @new_message_count >0 %>
- <% unless @user_course_messages.nil? %>
- <% @user_course_messages.each do |ucm| %>
- <% if ucm.course_message_type == "News" %>
-
- <%= image_tag(url_to_avatar(ucm.course_message.author), :width => "30", :height => "30") %>
- "><%= ucm.course_message.author %>
- ">发布通知
-
- <%= link_to "#{ucm.course_message.title}", {:controller => 'news', :action => 'show', :id => ucm.course_message.id },:class =>"#{ucm.viewed == 0 ? "newsBlack" : "newsGrey"}" %>
- <%= time_tag(ucm.course_message.created_on).html_safe %>
-
- <% end %>
- <% if ucm.course_message_type == "HomeworkCommon" %>
-
- <% end %>
- <% if ucm.course_message_type == "Poll" %>
-
- <% end %>
- <% if ucm.course_message_type == "Message" %>
-
- <%= image_tag(url_to_avatar(ucm.course_message.author), :width => "30", :height => "30") %>
- "><%= ucm.course_message.author %>
- <% if ucm.course_message.parent_id.nil? %>
- ">发布帖子
-
- <%=link_to ucm.course_message.subject, course_boards_path(ucm.course_message.course,:parent_id => ucm.course_message.parent_id ? ucm.course_message.parent_id : ucm.course_message.id, :topic_id => ucm.course_message.id),:class=>"#{ucm.viewed==0?"newsBlack":"newsGrey"}" %>
- <%= time_tag(ucm.course_message.created_on).html_safe %>
- <% else %>
- ">回复帖子
-
- <%=link_to ucm.course_message.subject, course_boards_path(ucm.course_message.course,:parent_id => ucm.course_message.parent_id ? ucm.course_message.parent_id : ucm.course_message.id, :topic_id => ucm.course_message.id),:class=>"#{ucm.viewed==0?"newsBlack":"newsGrey"}" %>
- <%= time_tag(ucm.course_message.created_on).html_safe %>
- <% end %>
-
+ <% if @new_message_count >0 %>
+ <% unless @user_course_messages.nil? %>
+ <% @user_course_messages.each do |ucm| %>
+ <% if ucm.course_message_type == "News" %>
+
+ <%= image_tag(url_to_avatar(ucm.course_message.author), :width => "30", :height => "30") %>
+ "><%= ucm.course_message.author %>
+ ">发布通知
+
+ <%= link_to "#{ucm.course_message.title}", {:controller => 'news', :action => 'show', :id => ucm.course_message.id },:class =>"#{ucm.viewed == 0 ? "newsBlack" : "newsGrey"}" %>
+ <%= time_tag(ucm.course_message.created_on).html_safe %>
+
+ <% end %>
+ <% if ucm.course_message_type == "HomeworkCommon" %>
+
+ <% end %>
+ <% if ucm.course_message_type == "Poll" %>
+
+ <% end %>
+ <% if ucm.course_message_type == "Message" %>
+
+ <%= image_tag(url_to_avatar(ucm.course_message.author), :width => "30", :height => "30") %>
+ "><%= ucm.course_message.author %>
+ <% if ucm.course_message.parent_id.nil? %>
+ ">发布帖子
+
+ <%=link_to ucm.course_message.subject, course_boards_path(ucm.course_message.course,:parent_id => ucm.course_message.parent_id ? ucm.course_message.parent_id : ucm.course_message.id, :topic_id => ucm.course_message.id),:class=>"#{ucm.viewed==0?"newsBlack":"newsGrey"}" %>
+ <%= time_tag(ucm.course_message.created_on).html_safe %>
+ <% else %>
+ ">回复帖子
+
+ <%=link_to ucm.course_message.subject, course_boards_path(ucm.course_message.course,:parent_id => ucm.course_message.parent_id ? ucm.course_message.parent_id : ucm.course_message.id, :topic_id => ucm.course_message.id),:class=>"#{ucm.viewed==0?"newsBlack":"newsGrey"}" %>
+ <%= time_tag(ucm.course_message.created_on).html_safe %>
+ <% end %>
+
+ <% end %>
+
+ <% end %>
<% end %>
-
- <% end %>
- <% end %>
-
- <% unless @user_forge_messages.nil? %>
- <% @user_forge_messages.each do |ufm| %>
+
+ <% unless @user_forge_messages.nil? %>
+ <% @user_forge_messages.each do |ufm| %>
<% if ufm.forge_message_type == "Issue" %>
@@ -100,18 +100,19 @@
"><%= ufm.forge_message.user %>
- ">发了留言给我
+ ">
+ <%= ufm.forge_message.notes.empty? ? "更新了问题状态" : "在问题中留言了" %>
- <%= link_to ("#{ufm.forge_message.notes}"), issue_path(:id => ufm.forge_message.journalized_id), :class => "#{ufm.viewed == 0 ? "newsBlack" : "newsGrey"}" %>
+ <%= link_to ("#{ufm.forge_message.notes.empty? ? ufm.forge_message.issue.subject : ufm.forge_message.notes }"), issue_path(:id => ufm.forge_message.journalized_id), :class => "#{ufm.viewed == 0 ? "newsBlack" : "newsGrey"}" %>
<%= time_tag(ufm.forge_message.created_on).html_safe %>
<% end %>
+ <% end %>
+ <% end %>
+ <% else %>
+
暂无消息!
<% end %>
- <% end %>
- <% else %>
-
暂无消息!
- <% end %>
From 90661066d36e8e81069c6d0bc242095a855f6e84 Mon Sep 17 00:00:00 2001
From: huang
Date: Tue, 18 Aug 2015 16:53:26 +0800
Subject: [PATCH 28/90] =?UTF-8?q?=E5=8C=BA=E5=88=86=E8=AF=BE=E7=A8=8B/?=
=?UTF-8?q?=E9=A1=B9=E7=9B=AE=E8=AE=A8=E8=AE=BA=E5=8C=BA=20=E8=AF=BE?=
=?UTF-8?q?=E7=A8=8B=E9=A1=B9=E7=9B=AE/=E6=96=B0=E9=97=BB=20=E7=9A=84?=
=?UTF-8?q?=E6=B6=88=E6=81=AF=E6=98=BE=E7=A4=BA=E6=96=B9=E5=BC=8F?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/controllers/users_controller.rb | 8 ++++++--
app/views/users/user_messages.html.erb | 11 ++++++++---
2 files changed, 14 insertions(+), 5 deletions(-)
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index d1073c8c3..00ce151cf 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -117,16 +117,20 @@ class UsersController < ApplicationController
when 'homework'
@user_course_messages = CourseMessage.where("course_message_type =? and user_id =?", "HomeworkCommon", @user).order("created_at desc")
@user_forge_messages = nil
- when 'message'
+ when 'course_message'
@user_course_messages = CourseMessage.where("course_message_type =? and user_id =?", "Message", @user).order("created_at desc")
+ when 'forge_message'
@user_forge_messages = ForgeMessage.where("forge_message_type =? and user_id =?", "Message", @user).order("created_at desc")
- when 'news'
+ when 'course_news'
@user_course_messages = CourseMessage.where("course_message_type =? and user_id =?", "News", @user).order("created_at desc")
+ when 'forge_news'
@user_forge_messages = ForgeMessage.where("forge_message_type =? and user_id =?", "News", @user).order("created_at desc")
when 'poll'
@user_course_messages = CourseMessage.where("course_message_type =? and user_id =?", "Poll", @user).order("created_at desc")
when 'works_reviewers'
@user_course_messages = CourseMessage.where("course_message_type =? and user_id =?", "StudentWorksScore", @user).order("created_at desc")
+ when 'works_reply'
+ @user_course_messages = CourseMessage.where("course_message_type =? and user_id =?", "JournalsForMessage", @user).order("created_at desc")
when 'issue'
@user_forge_messages = ForgeMessage.where("forge_message_type =? and user_id =?", "Issue", @user).order("created_at desc")
@user_course_messages = nil
diff --git a/app/views/users/user_messages.html.erb b/app/views/users/user_messages.html.erb
index 03cdda8ad..a4cc521ff 100644
--- a/app/views/users/user_messages.html.erb
+++ b/app/views/users/user_messages.html.erb
@@ -9,12 +9,17 @@
<%= link_to "全部",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user} %>
<%= link_to "作业消息",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user, :type => 'homework'} %>
- <%= link_to "讨论区",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user, :type => 'message'} %>
- <%= link_to "课程通知",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user, :type => 'news'} %>
+ <%= link_to "课程讨论区",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user, :type => 'course_message'} %>
+ <%= link_to "课程通知",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user, :type => 'course_news'} %>
<%= link_to "问卷调查",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user, :type => 'poll'} %>
+ <%= link_to "作品评阅",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user, :type => 'works_reviewers'} %>
+ <%= link_to "作品讨论",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user, :type => 'works_reply'} %>
+
<%= link_to "指派给我",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user, :type => 'issue'} %>
- <%= link_to "我的留言",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user, :type => 'issue_update'} %>
+ <%= link_to "问题更新",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user, :type => 'issue_update'} %>
+ <%= link_to "项目讨论区",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user, :type => 'forge_message'} %>
+ <%= link_to "项目新闻",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user, :type => 'forge_news'} %>
From ae6260571b4d4321cf68d433f8d0c793dd9d0c94 Mon Sep 17 00:00:00 2001
From: lizanle <491823689@qq.com>
Date: Tue, 18 Aug 2015 16:57:41 +0800
Subject: [PATCH 29/90] =?UTF-8?q?=E8=B5=84=E6=BA=90=E5=BA=93?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/controllers/users_controller.rb | 8 ++++----
app/views/users/user_resource.html.erb | 2 +-
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 6bbfbd12b..c3c5da9cf 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -1106,25 +1106,25 @@ class UsersController < ApplicationController
#确定container_type
# @user = User.find(params[:id])
if(params[:type].nil? || params[:type] == "1") #全部
- if User.current.id == params[:id]
+ if User.current.id.to_i == params[:id].to_i
@attachments = Attachment.where("author_id = #{params[:id]} and container_type in('Project','Principal','Course','Issue','Document','Message','News','StudentWorkScore','HomewCommon') ").order("created_on desc")
else
@attachments = Attachment.where("author_id = #{params[:id]} and is_public = 1 and container_type in('Project','Principal','Course','Issue','Document','Message','News','StudentWorkScore','HomewCommon') ").order("created_on desc")
end
elsif params[:type] == "2" #课程资源
- if User.current.id == params[:id]
+ if User.current.id.to_i == params[:id].to_i
@attachments = Attachment.where("author_id = #{params[:id]} and container_type = 'Course'").order("created_on desc")
else
@attachments = Attachment.where("author_id = #{params[:id]} and is_public = 1 and container_type = 'Course' ").order("created_on desc")
end
elsif params[:type] == "3" #项目资源
- if User.current.id == params[:id]
+ if User.current.id.to_i == params[:id].to_i
@attachments = Attachment.where("author_id = #{params[:id]} and container_type = 'Project'").order("created_on desc")
else
@attachments = Attachment.where("author_id = #{params[:id]} and is_public = 1 and container_type = 'Project' ").order("created_on desc")
end
elsif params[:type] == "4" #附件
- if User.current.id == params[:id]
+ if User.current.id.to_i == params[:id].to_i
@attachments = Attachment.where("author_id = #{params[:id]} and container_type in('Project','Issue','Document','Message','News','StudentWorkScore','HomewCommon')").order("created_on desc")
else
@attachments = Attachment.where("author_id = #{params[:id]} and is_public = 1 and container_type in('Issue','Document','Message','News','StudentWorkScore','HomewCommon')").order("created_on desc")
diff --git a/app/views/users/user_resource.html.erb b/app/views/users/user_resource.html.erb
index f5a6c57f0..09bee5ac6 100644
--- a/app/views/users/user_resource.html.erb
+++ b/app/views/users/user_resource.html.erb
@@ -199,7 +199,7 @@ $(".resourcesList").click(function(e) {
'"/> '+
'<% end %>');
$("#res_name").focus();
- $("html,body").animate({scrollTop:$("#res_name").offset().top},1000)
+ $("html,body").animate({scrollTop:$("#res_name").offset().top},1000)
}
String.prototype.trim = function() {
var str = this,
From 652f5fa6e130a1d316530557803a4716fb1a7672 Mon Sep 17 00:00:00 2001
From: cxt
Date: Tue, 18 Aug 2015 17:00:58 +0800
Subject: [PATCH 30/90] =?UTF-8?q?=E8=B6=85=E7=BA=A7=E7=AE=A1=E7=90=86?=
=?UTF-8?q?=E5=91=98=E7=9A=84=E7=95=99=E8=A8=80=E5=88=97=E8=A1=A8=E3=80=81?=
=?UTF-8?q?=E5=B8=96=E5=AD=90=E3=80=81=E6=9C=80=E8=BF=91=E7=99=BB=E5=BD=95?=
=?UTF-8?q?=E7=94=A8=E6=88=B7=E5=88=97=E8=A1=A8=E7=9A=84=E7=BC=BA=E9=99=B7?=
=?UTF-8?q?=E4=BF=AE=E5=A4=8D?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/views/admin/course_messages.html.erb | 4 ++--
app/views/admin/latest_login_users.html.erb | 6 +++---
app/views/admin/leave_messages.html.erb | 4 ++--
app/views/admin/messages_list.html.erb | 10 +++++++---
app/views/admin/project_messages.html.erb | 4 ++--
5 files changed, 16 insertions(+), 12 deletions(-)
diff --git a/app/views/admin/course_messages.html.erb b/app/views/admin/course_messages.html.erb
index 3db0a3e11..c9e69357f 100644
--- a/app/views/admin/course_messages.html.erb
+++ b/app/views/admin/course_messages.html.erb
@@ -11,8 +11,8 @@
序号
-
- 来源
+
+ 来源(课程ID)
作者
diff --git a/app/views/admin/latest_login_users.html.erb b/app/views/admin/latest_login_users.html.erb
index 838cc0dcb..89514726a 100644
--- a/app/views/admin/latest_login_users.html.erb
+++ b/app/views/admin/latest_login_users.html.erb
@@ -9,10 +9,10 @@
<%= l(:label_filter_plural) %>
开始日期:
- <%= text_field_tag 'startdate', params[:startdate], :size => 15, :onchange =>"regexDeadLine();", :style=>"float:left"%>
- <%= calendar_for('startdate')%>
+ <%= text_field_tag 'startdate', params[:startdate], :size => 15, :onchange=>"$('#ui-datepicker-div').hide()", :style=>"float:left"%>
+ <%= calendar_for('startdate')%>
结束日期:
- <%= text_field_tag 'enddate', params[:enddate], :size => 15, :onchange =>"regexDeadLine();", :style=>"float:left"%>
+ <%= text_field_tag 'enddate', params[:enddate], :size => 15, :onchange =>"$('#ui-datepicker-div').hide()", :style=>"float:left"%>
<%= calendar_for('enddate')%>
<%= submit_tag l(:button_apply), :class => "small", :name => nil %>
<%= link_to l(:button_clear), {:controller => 'admin', :action => 'latest_login_users'}, :class => 'icon icon-reload' %>
diff --git a/app/views/admin/leave_messages.html.erb b/app/views/admin/leave_messages.html.erb
index 360e9b864..dee8b7443 100644
--- a/app/views/admin/leave_messages.html.erb
+++ b/app/views/admin/leave_messages.html.erb
@@ -13,8 +13,8 @@
类型
-
- 来源
+
+ 来源(课程或用户ID)
留言人
diff --git a/app/views/admin/messages_list.html.erb b/app/views/admin/messages_list.html.erb
index e0c84279d..ca84baa24 100644
--- a/app/views/admin/messages_list.html.erb
+++ b/app/views/admin/messages_list.html.erb
@@ -11,8 +11,8 @@
序号
-
- 来源
+
+ 来源(贴吧ID)
作者
@@ -50,7 +50,11 @@
<%= format_date(memo.created_at) %>
- <%= link_to(memo.subject, forum_memo_path(memo.forum, memo)) %>
+ <% if memo.parent_id.nil? || memo.subject.starts_with?('RE:')%>
+ <%= link_to(memo.subject, forum_memo_path(memo.forum, memo)) %>
+ <% else %>
+ <%= link_to("RE:"+memo.subject, forum_memo_path(memo.forum, memo)) %>
+ <% end %>
<%= link_to(memo.replies_count, forum_memo_path(memo.forum, memo)) %>
diff --git a/app/views/admin/project_messages.html.erb b/app/views/admin/project_messages.html.erb
index dc44a7cba..a5639eba7 100644
--- a/app/views/admin/project_messages.html.erb
+++ b/app/views/admin/project_messages.html.erb
@@ -11,8 +11,8 @@
序号
-
- 来源
+
+ 来源(项目ID)
作者
From 43d57074e51277b505fc7d7f7ed781c2a81cb2a8 Mon Sep 17 00:00:00 2001
From: lizanle <491823689@qq.com>
Date: Tue, 18 Aug 2015 17:26:39 +0800
Subject: [PATCH 31/90] =?UTF-8?q?=E8=B5=84=E6=BA=90=E5=BA=93?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/controllers/users_controller.rb | 2 +-
app/views/users/user_resource.html.erb | 5 +++--
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index c3c5da9cf..2caae19e1 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -894,7 +894,7 @@ class UsersController < ApplicationController
# format.js
# end
if @flag
- render :text=>'sucess'
+ render :text=> download_named_attachment_path(@attachment.id, @attachment.filename)
else
render :text=>'fail'
end
diff --git a/app/views/users/user_resource.html.erb b/app/views/users/user_resource.html.erb
index 09bee5ac6..1cad8f2de 100644
--- a/app/views/users/user_resource.html.erb
+++ b/app/views/users/user_resource.html.erb
@@ -158,7 +158,7 @@ $(".resourcesList").click(function(e) {
//将当前行改变为白色
line.children().css("background-color", 'white');
//当前行恢复编辑状态到链接状态
- if(ele.nodeName != 'INPUT') {
+ if(ele && ele.nodeName != 'INPUT') {
restore();
}
line = null;
@@ -224,9 +224,10 @@ $(".resourcesList").click(function(e) {
'<%=rename_resource_user_path(@user) %>',
$("#res_name_form").serialize(),
function (data){
- if(data =='sucess'){//修改成功,那么将链接恢复,并且将链接的显示内容改变。链接可以不变
+ if(data != 'fail'){//修改成功,那么将链接恢复,并且将链接的显示内容改变。链接可以不变
last_line.children().first().html(res_link);
last_line.children().first().children().attr('title',name);
+ last_line.children().first().children().attr('href',data);
last_line.children().first().children().html(name.length > 17? name.substring(0,17)+'...' : name);
}else{
last_line.children().first().html(res_link);
From 3836cfb40ba4bcd3b07b3a8dfb7698f24dddb3d6 Mon Sep 17 00:00:00 2001
From: lizanle <491823689@qq.com>
Date: Tue, 18 Aug 2015 17:45:14 +0800
Subject: [PATCH 32/90] =?UTF-8?q?=E8=B5=84=E6=BA=90=E5=BA=93?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/views/users/_resource_search_form.html.erb | 2 +-
app/views/users/user_resource.html.erb | 5 ++++-
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/app/views/users/_resource_search_form.html.erb b/app/views/users/_resource_search_form.html.erb
index 0c48514b3..725167b65 100644
--- a/app/views/users/_resource_search_form.html.erb
+++ b/app/views/users/_resource_search_form.html.erb
@@ -1,6 +1,6 @@
<%= form_tag( url_for(:controller => 'users',:action => 'resource_search',:id=>user.id),
:remote=>true ,:method => 'post',:class=>'resourcesSearchloadBox',:id=>'resource_search_form') do %>
-
+
<%= hidden_field_tag(:type,type) %>
<%= submit_tag '',:class=>'searchIcon',:style=>'border-style:none' %>
diff --git a/app/views/users/user_resource.html.erb b/app/views/users/user_resource.html.erb
index 1cad8f2de..621b0c17d 100644
--- a/app/views/users/user_resource.html.erb
+++ b/app/views/users/user_resource.html.erb
@@ -216,7 +216,10 @@ $(".resourcesList").click(function(e) {
function restore(){
//上一行不为空 且链接不为空
if( last_line != null && res_link != null && res_link != '') {
- name = $("#res_name") ? $("#res_name").val().trim() : $("#res_name") ;
+ name = $("#res_name").lenght != 0 && $("#res_name").val() != undefined ? $("#res_name").val().trim() : undefined ;
+ if (name == undefined || name === 'undefined' ){ //只要res_name没有值,那么就不是编辑状态
+ return;
+ }
if( name && name != res_name.trim()){
if(confirm('确定修改为 '+name)){
From e7f818deb9e62b599ab126b781eedbeef148a4bb Mon Sep 17 00:00:00 2001
From: lizanle <491823689@qq.com>
Date: Wed, 19 Aug 2015 09:20:39 +0800
Subject: [PATCH 33/90] =?UTF-8?q?=E8=B5=84=E6=BA=90=E5=BA=93=E6=90=9C?=
=?UTF-8?q?=E7=B4=A2=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/controllers/users_controller.rb | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 2caae19e1..bc9394716 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -1146,25 +1146,25 @@ class UsersController < ApplicationController
# @attachments = Attachment.where("author_id = #{params[:id]} and container_type not in ('Version','PhoneAppVersion','StudentWork') and is_public = 1 and (filename like '%#{search}%') ").order("created_on desc")
# end
if(params[:type].nil? || params[:type] == "1") #全部
- if User.current.id == params[:id]
+ if User.current.id.to_i == params[:id].to_i
@attachments = Attachment.where("author_id = #{params[:id]} and container_type in('Project','Principal','Course','Issue','Document','Message','News','StudentWorkScore','HomewCommon') and (filename like '%#{search}%') ").order("created_on desc")
else
@attachments = Attachment.where("author_id = #{params[:id]} and is_public = 1 and container_type in('Project','Principal','Course','Issue','Document','Message','News','StudentWorkScore','HomewCommon') and (filename like '%#{search}%') ").order("created_on desc")
end
elsif params[:type] == "2" #课程资源
- if User.current.id == params[:id]
+ if User.current.id.to_i == params[:id].to_i
@attachments = Attachment.where("author_id = #{params[:id]} and container_type = 'Course' and (filename like '%#{search}%')").order("created_on desc")
else
@attachments = Attachment.where("author_id = #{params[:id]} and is_public = 1 and container_type = 'Course' and (filename like '%#{search}%') ").order("created_on desc")
end
elsif params[:type] == "3" #项目资源
- if User.current.id == params[:id]
+ if User.current.id.to_i == params[:id].to_i
@attachments = Attachment.where("author_id = #{params[:id]} and container_type = 'Project' and (filename like '%#{search}%')").order("created_on desc")
else
@attachments = Attachment.where("author_id = #{params[:id]} and is_public = 1 and container_type = 'Project' and (filename like '%#{search}%') ").order("created_on desc")
end
elsif params[:type] == "4" #附件
- if User.current.id == params[:id]
+ if User.current.id.to_i == params[:id].to_i
@attachments = Attachment.where("author_id = #{params[:id]} and container_type in('Project','Issue','Document','Message','News','StudentWorkScore','HomewCommon') and (filename like '%#{search}%')").order("created_on desc")
else
@attachments = Attachment.where("author_id = #{params[:id]} and is_public = 1 and container_type in('Issue','Document','Message','News','StudentWorkScore','HomewCommon') and (filename like '%#{search}%')").order("created_on desc")
From d657e9f3cc44e2964828eb6dd173eb9cd7c1bf38 Mon Sep 17 00:00:00 2001
From: huang
Date: Wed, 19 Aug 2015 11:06:39 +0800
Subject: [PATCH 34/90] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20=E5=85=AC=E5=85=B1?=
=?UTF-8?q?=E8=B4=B4=E5=90=A7=20=E6=B6=88=E6=81=AF=E9=80=9A=E7=9F=A5?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/controllers/users_controller.rb | 11 ++--
app/models/forum.rb | 1 +
app/models/forum_message.rb | 11 ++++
app/models/memo.rb | 30 ++++++++++-
app/models/user.rb | 4 +-
.../20150818091800_create_forum_messages.rb | 13 +++++
db/schema.rb | 50 ++++++++++++++++++-
spec/factories/forum_messages.rb | 10 ++++
spec/models/forum_message_spec.rb | 5 ++
9 files changed, 126 insertions(+), 9 deletions(-)
create mode 100644 app/models/forum_message.rb
create mode 100644 db/migrate/20150818091800_create_forum_messages.rb
create mode 100644 spec/factories/forum_messages.rb
create mode 100644 spec/models/forum_message_spec.rb
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 00ce151cf..d77ccb958 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -97,8 +97,8 @@ class UsersController < ApplicationController
end
# 用户消息
- # 说明: homework 发布作业;message:讨论区; news:新闻; poll:问卷;works_reviewers:作品评阅
- # issue:问题;
+ # 说明: homework 发布作业;message:讨论区; news:新闻; poll:问卷;works_reviewers:作品评阅;works_reply:作品回复
+ # issue:问题;journal:缺陷状态更新; forum:公共贴吧
def user_messages
unless User.current.logged?
render_403
@@ -114,6 +114,7 @@ class UsersController < ApplicationController
when nil
@user_course_messages = @user.course_messages.reverse
@user_forge_messages = @user.forge_messages.reverse
+ @user_forum_messages = @user.forum_messages.reverse
when 'homework'
@user_course_messages = CourseMessage.where("course_message_type =? and user_id =?", "HomeworkCommon", @user).order("created_at desc")
@user_forge_messages = nil
@@ -134,9 +135,11 @@ class UsersController < ApplicationController
when 'issue'
@user_forge_messages = ForgeMessage.where("forge_message_type =? and user_id =?", "Issue", @user).order("created_at desc")
@user_course_messages = nil
- when 'journal'
- @user_forge_messages = ForgeMessage.where("forge_message_type =? and user_id =?", "Journal", @user).order("created_at desc")
+ when 'journal' # 缺陷状态更新、留言
+ @user_forge_messages = ForgeMessage.where("forge_message_type =? and user_id =?", "Forum", @user).order("created_at desc")
@user_course_messages = nil
+ when 'forum'
+ @user_forum_messages = ForumMessage.where("memo_message_type =? and user_id =?", "Forum", @user).order("created_at desc")
end
respond_to do |format|
format.html{render :layout=>'base_users_new'}
diff --git a/app/models/forum.rb b/app/models/forum.rb
index 2af1abf9e..530639f81 100644
--- a/app/models/forum.rb
+++ b/app/models/forum.rb
@@ -39,6 +39,7 @@ class Forum < ActiveRecord::Base
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
diff --git a/app/models/forum_message.rb b/app/models/forum_message.rb
new file mode 100644
index 000000000..c7b07e164
--- /dev/null
+++ b/app/models/forum_message.rb
@@ -0,0 +1,11 @@
+class ForumMessage < ActiveRecord::Base
+ attr_accessible :forum_id, :memo_message_id, :memo_message_type, :user_id, :viewed
+
+ belongs_to :memo
+ belongs_to :user
+
+ validates :user_id,presence: true
+ validates :forum_id,presence: true
+ validates :memo_message_id,presence: true
+ validates :memo_message_type, presence: true
+end
diff --git a/app/models/memo.rb b/app/models/memo.rb
index e0abaa19f..e4dabf131 100644
--- a/app/models/memo.rb
+++ b/app/models/memo.rb
@@ -16,6 +16,8 @@ class Memo < ActiveRecord::Base
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
+ # 消息
+ has_many :forum_messages, dependent: :destroy
belongs_to :last_reply, :class_name => 'Memo', :foreign_key => 'last_reply_id'
# acts_as_searchable :column => ['subject', 'content'],
# #:include => { :forum => :p}
@@ -44,7 +46,7 @@ class Memo < ActiveRecord::Base
"parent_id",
"replies_count"
- after_create :add_author_as_watcher, :reset_counters!, :send_mail
+ after_create :add_author_as_watcher, :reset_counters!, :send_mail, :send_message
# after_update :update_memos_forum
after_destroy :reset_counters!,:delete_kindeditor_assets#,:down_user_score -- 公共区发帖暂不计入得分
# after_create :send_notification
@@ -59,6 +61,32 @@ class Memo < ActiveRecord::Base
Mailer.run.forum_message_added(self) if Setting.notified_events.include?('forum_message_added')
end
+ # 公共贴吧消息记录
+ # 原则:贴吧创始人;发帖人,wanglingchun(特殊用户)
+ def send_message
+ receivers = []
+ u = User.find(6)
+ receivers << u
+ # 主贴
+ if self.parent_id.nil?
+ if self.author_id != self.forum.creator_id # 发帖人不是吧主
+ receivers << self.forum.creator
+ end
+ else # 回帖
+ # 添加吧主
+ if self.author_id != self.forum.creator_id
+ receivers << self.forum.creator
+ end
+ # 添加发帖人
+ if self.author_id != self.parent.author_id
+ receivers << self.parent.author
+ end
+ end
+ receivers.each do |r|
+ self.forum_messages << ForumMessage.new(:user_id => r.id, :forum_id => self.forum_id, :memo_message_id => self.id, :memo_message_type => "Forum", :viewed => false)
+ end
+ end
+
def cannot_reply_to_locked_topic
errors.add :base, l(:label_memo_locked) if root.locked? && self != root
end
diff --git a/app/models/user.rb b/app/models/user.rb
index 9f88ff53a..82ecdbd47 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -127,10 +127,10 @@ class User < Principal
has_many :messages, :foreign_key => 'author_id'
has_one :user_score, :dependent => :destroy
has_many :documents # 项目中关联的文档再次与人关联
-# 关联虚拟表
+# 关联消息表
has_many :forge_messages
has_many :course_messages
-# end
+ has_many :forum_messages
# 虚拟转换
has_many :new_jours, :as => :jour, :class_name => 'JournalsForMessage', :conditions => "status=1"
diff --git a/db/migrate/20150818091800_create_forum_messages.rb b/db/migrate/20150818091800_create_forum_messages.rb
new file mode 100644
index 000000000..20ad1ca51
--- /dev/null
+++ b/db/migrate/20150818091800_create_forum_messages.rb
@@ -0,0 +1,13 @@
+class CreateForumMessages < ActiveRecord::Migration
+ def change
+ create_table :forum_messages do |t|
+ t.integer :user_id
+ t.integer :forum_id
+ t.integer :memo_message_id
+ t.string :memo_message_type
+ t.integer :viewed
+
+ t.timestamps
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index db9b9ff9b..5471381d7 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
#
# It's strongly recommended to check this file into your version control system.
-ActiveRecord::Schema.define(:version => 20150810064247) do
+ActiveRecord::Schema.define(:version => 20150818091800) do
create_table "activities", :force => true do |t|
t.integer "act_id", :null => false
@@ -325,6 +325,15 @@ ActiveRecord::Schema.define(:version => 20150810064247) do
t.datetime "updated_on", :null => false
end
+ create_table "course_activities", :force => true do |t|
+ t.integer "user_id"
+ t.integer "course_id"
+ t.integer "course_act_id"
+ t.string "course_act_type"
+ t.datetime "created_at", :null => false
+ t.datetime "updated_at", :null => false
+ end
+
create_table "course_attachments", :force => true do |t|
t.string "filename"
t.string "disk_filename"
@@ -357,6 +366,16 @@ ActiveRecord::Schema.define(:version => 20150810064247) do
t.datetime "updated_at", :null => false
end
+ create_table "course_messages", :force => true do |t|
+ t.integer "user_id"
+ t.integer "course_id"
+ t.integer "course_message_id"
+ t.string "course_message_type"
+ t.integer "viewed"
+ t.datetime "created_at", :null => false
+ t.datetime "updated_at", :null => false
+ end
+
create_table "course_statuses", :force => true do |t|
t.integer "changesets_count"
t.integer "watchers_count"
@@ -455,6 +474,13 @@ ActiveRecord::Schema.define(:version => 20150810064247) do
add_index "delayed_jobs", ["priority", "run_at"], :name => "delayed_jobs_priority"
+ create_table "discuss_demos", :force => true do |t|
+ t.string "title"
+ t.text "body"
+ t.datetime "created_at", :null => false
+ t.datetime "updated_at", :null => false
+ end
+
create_table "documents", :force => true do |t|
t.integer "project_id", :default => 0, :null => false
t.integer "category_id", :default => 0, :null => false
@@ -536,6 +562,26 @@ ActiveRecord::Schema.define(:version => 20150810064247) do
add_index "forge_activities", ["forge_act_id"], :name => "index_forge_activities_on_forge_act_id"
+ create_table "forge_messages", :force => true do |t|
+ t.integer "user_id"
+ t.integer "project_id"
+ t.integer "forge_message_id"
+ t.string "forge_message_type"
+ t.integer "viewed"
+ t.datetime "created_at", :null => false
+ t.datetime "updated_at", :null => false
+ end
+
+ create_table "forum_messages", :force => true do |t|
+ t.integer "user_id"
+ t.integer "forum_id"
+ t.integer "memo_message_id"
+ t.string "memo_message_type"
+ t.integer "viewed"
+ t.datetime "created_at", :null => false
+ t.datetime "updated_at", :null => false
+ end
+
create_table "forums", :force => true do |t|
t.string "name", :null => false
t.text "description"
@@ -857,7 +903,6 @@ ActiveRecord::Schema.define(:version => 20150810064247) do
t.datetime "created_on"
t.integer "comments_count", :default => 0, :null => false
t.integer "course_id"
- t.datetime "updated_on"
end
add_index "news", ["author_id"], :name => "index_news_on_author_id"
@@ -1461,6 +1506,7 @@ ActiveRecord::Schema.define(:version => 20150810064247) do
t.string "identity_url"
t.string "mail_notification", :default => "", :null => false
t.string "salt", :limit => 64
+ t.integer "gid"
end
add_index "users", ["auth_source_id"], :name => "index_users_on_auth_source_id"
diff --git a/spec/factories/forum_messages.rb b/spec/factories/forum_messages.rb
new file mode 100644
index 000000000..adb114d3c
--- /dev/null
+++ b/spec/factories/forum_messages.rb
@@ -0,0 +1,10 @@
+FactoryGirl.define do
+ factory :forum_message do
+ user_id 1
+forum_id 1
+memo_message_id 1
+memo_message_type "MyString"
+viewed 1
+ end
+
+end
diff --git a/spec/models/forum_message_spec.rb b/spec/models/forum_message_spec.rb
new file mode 100644
index 000000000..e0159c3ca
--- /dev/null
+++ b/spec/models/forum_message_spec.rb
@@ -0,0 +1,5 @@
+require 'rails_helper'
+
+RSpec.describe ForumMessage, :type => :model do
+ pending "add some examples to (or delete) #{__FILE__}"
+end
From ff3edf4d5e56e335e9cbaaeb0b536a42c3252545 Mon Sep 17 00:00:00 2001
From: ouyangxuhua
Date: Wed, 19 Aug 2015 11:12:47 +0800
Subject: [PATCH 35/90] =?UTF-8?q?=E6=B6=88=E6=81=AF=E6=98=BE=E7=A4=BA?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/views/users/user_messages.html.erb | 52 ++++++++++++++++++++++++++
public/stylesheets/public_new.css | 4 +-
2 files changed, 54 insertions(+), 2 deletions(-)
diff --git a/app/views/users/user_messages.html.erb b/app/views/users/user_messages.html.erb
index a4cc521ff..089dca32f 100644
--- a/app/views/users/user_messages.html.erb
+++ b/app/views/users/user_messages.html.erb
@@ -76,6 +76,26 @@
<% end %>
<% end %>
+ <% if ucm.course_message_type == "StudentWorksScore" %>
+
+ <% end %>
+ <% if ucm.course_message_type == "JournalsForMessage" %>
+
+ <% end %>
<% end %>
<% end %>
@@ -113,6 +133,38 @@
<%= time_tag(ufm.forge_message.created_on).html_safe %>
<% end %>
+ <% if ufm.forge_message_type == "Message" %>
+
+ <%= image_tag(url_to_avatar(ufm.forge_message.author), :width => "30", :height => "30") %>
+ "><%= ufm.forge_message.author %>
+ <% if ufm.forge_message.parent_id.nil? %>
+ ">发布帖子
+
+ <%=link_to ufm.forge_message.subject, project_boards_path(ufm.forge_message.project,:parent_id => ufm.forge_message.parent_id ? ufm.forge_message.parent_id : ufm.forge_message.id, :topic_id => ufm.forge_message.id),:class=>"#{ufm.viewed==0?"newsBlack":"newsGrey"}" %>
+ <%= time_tag(ufm.forge_message.created_on).html_safe %>
+ <% else %>
+ ">回复帖子
+
+ <%=link_to ufm.forge_message.subject, project_boards_path(ufm.forge_message.project,:parent_id => ufm.forge_message.parent_id ? ufm.forge_message.parent_id : ufm.forge_message.id, :topic_id => ufm.forge_message.id),:class=>"#{ufm.viewed==0?"newsBlack":"newsGrey"}" %>
+ <%= time_tag(ufm.forge_message.created_on).html_safe %>
+ <% end %>
+
+ <% end %>
+ <% if ufm.forge_message_type == "News" %>
+
+ <% end %>
<% end %>
<% end %>
<% else %>
diff --git a/public/stylesheets/public_new.css b/public/stylesheets/public_new.css
index fb7e6fbf4..6837a5466 100644
--- a/public/stylesheets/public_new.css
+++ b/public/stylesheets/public_new.css
@@ -589,7 +589,7 @@ a.homepageMenuText {color:#484848; font-size:16px; margin-left:20px;}
.homepageNewsPortrait {width:40px; display:block; margin-top:7px;}
.homepageNewsPublisher {width:80px; max-width:80px; margin-right:10px; font-size:12px; color:#15bccf; display:block; padding-left:5px; overflow:hidden; white-space: nowrap; text-overflow:ellipsis; }
.homepageNewsType {width:95px; font-size:12px; color:#888888; display:block;}
-.homepageNewsTypeNotRead {width:95px; font-size:12px; font-weight:bold; color:#4B4B4B; display:block;}
+.homepageNewsTypeNotRead {width:95px; font-size:13px; font-weight:bold; color:#4B4B4B; display:block;}
.homepageNewsContent {width:395px; max-width:395px; margin-right:10px; font-size:12px; color:#4b4b4b; display:block; overflow:hidden; white-space: nowrap; text-overflow:ellipsis; }
.homepageNewsTime {width:75px; font-size:12px; color:#888888; display:block; text-align:right;}
a.homepageWhite {color:#ffffff;}
@@ -598,7 +598,7 @@ a.newsGrey {color:#4b4b4b;}
a.newsGrey:hover {color:#000000;}
a.newsBlue {color:#15bccf;}
a.newsBlue:hover {color:#0781b4;}
-a.newsBlack {color:#4B4B4B; font-weight:bold;}
+a.newsBlack {color:#4B4B4B; font-weight:bold; font-size:13px;}
a.newsBlack:hover {color:#0781b4;}
a.resourcesGrey {font-size:12px; color:#888888;}
a.resourcesGrey:hover {font-size:12px; color:#15bccf;}
From 2d282f73cb51286716fbc3900e37a2763a8cf193 Mon Sep 17 00:00:00 2001
From: huang
Date: Wed, 19 Aug 2015 11:21:48 +0800
Subject: [PATCH 36/90] =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E8=AE=A8=E8=AE=BA?=
=?UTF-8?q?=E5=8C=BA?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/models/message.rb | 1 -
1 file changed, 1 deletion(-)
diff --git a/app/models/message.rb b/app/models/message.rb
index 4cc233eb5..37129885f 100644
--- a/app/models/message.rb
+++ b/app/models/message.rb
@@ -232,7 +232,6 @@ class Message < ActiveRecord::Base
self.project.members.each do |m|
if m.user_id == Message.find(self.parent_id).author_id && m.user_id != self.author_id # 只针对主贴回复,回复自己的帖子不发消息
self.forge_messages << ForgeMessage.new(:user_id => m.user_id, :project_id => self.board.project_id, :viewed => false)
- self.forge_messages << ForgeMessage.new(:user_id => m.user_id, :project_id => self.board.project_id, :viewed => false)
end
end
end
From 0ef7d5f0fa23ac6f4e099770c8197242a4fc2228 Mon Sep 17 00:00:00 2001
From: lizanle <491823689@qq.com>
Date: Wed, 19 Aug 2015 12:04:06 +0800
Subject: [PATCH 37/90] =?UTF-8?q?=E8=B5=84=E6=BA=90=E5=BA=93=E5=8F=AF?=
=?UTF-8?q?=E8=A7=81=E6=80=A7=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/controllers/users_controller.rb | 27 ++++++++++++++++++---------
1 file changed, 18 insertions(+), 9 deletions(-)
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index bc9394716..c523bbb3d 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -1,3 +1,4 @@
+#encoding: utf-8
# Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang
#
@@ -14,6 +15,7 @@
# 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 UsersController < ApplicationController
layout :setting_layout
@@ -1109,13 +1111,18 @@ class UsersController < ApplicationController
if User.current.id.to_i == params[:id].to_i
@attachments = Attachment.where("author_id = #{params[:id]} and container_type in('Project','Principal','Course','Issue','Document','Message','News','StudentWorkScore','HomewCommon') ").order("created_on desc")
else
- @attachments = Attachment.where("author_id = #{params[:id]} and is_public = 1 and container_type in('Project','Principal','Course','Issue','Document','Message','News','StudentWorkScore','HomewCommon') ").order("created_on desc")
+ user_course_ids = User.find(params[:id]).courses.visible.map { |c| c.id} #如果课程私有资源,那么要看这个资源的课程是不是在 这个user的所有我可见的课程中
+ @attachments = Attachment.where("(author_id = #{params[:id]} and is_public = 1 " +
+ "and container_type in('Project','Principal','Course','Issue','Document','Message','News','StudentWorkScore','HomewCommon')) " +
+ "or (container_type = 'Course' and is_public <> -1 and container_id in (#{user_course_ids.join(',')}))").order("created_on desc")
end
elsif params[:type] == "2" #课程资源
if User.current.id.to_i == params[:id].to_i
@attachments = Attachment.where("author_id = #{params[:id]} and container_type = 'Course'").order("created_on desc")
else
- @attachments = Attachment.where("author_id = #{params[:id]} and is_public = 1 and container_type = 'Course' ").order("created_on desc")
+ user_course_ids = User.find(params[:id]).courses.visible.map { |c| c.id} #如果课程私有资源,那么要看这个资源的课程是不是在 这个user的所有我可见的课程中
+ @attachments = Attachment.where("(author_id = #{params[:id]} and is_public = 1 and container_type = 'Course')"+
+ "or (container_type = 'Course' and is_public <> -1 and container_id in (#{user_course_ids.join(',')}))").order("created_on desc")
end
elsif params[:type] == "3" #项目资源
if User.current.id.to_i == params[:id].to_i
@@ -1140,22 +1147,24 @@ class UsersController < ApplicationController
# 根据资源关键字进行搜索
def resource_search
search = params[:search].to_s.strip.downcase
- # if User.current.id == params[:id]
- # @attachments = Attachment.where("author_id = #{params[:id]} and container_type not in ('Version','PhoneAppVersion','StudentWork') and (filename like '%#{search}%') ").order("created_on desc")
- # else
- # @attachments = Attachment.where("author_id = #{params[:id]} and container_type not in ('Version','PhoneAppVersion','StudentWork') and is_public = 1 and (filename like '%#{search}%') ").order("created_on desc")
- # end
if(params[:type].nil? || params[:type] == "1") #全部
if User.current.id.to_i == params[:id].to_i
@attachments = Attachment.where("author_id = #{params[:id]} and container_type in('Project','Principal','Course','Issue','Document','Message','News','StudentWorkScore','HomewCommon') and (filename like '%#{search}%') ").order("created_on desc")
else
- @attachments = Attachment.where("author_id = #{params[:id]} and is_public = 1 and container_type in('Project','Principal','Course','Issue','Document','Message','News','StudentWorkScore','HomewCommon') and (filename like '%#{search}%') ").order("created_on desc")
+ user_course_ids = User.find(params[:id]).courses.visible.map { |c| c.id} #如果课程私有资源,那么要看这个资源的课程是不是在 这个user的所有我可见的课程中
+ @attachments = Attachment.where("((author_id = #{params[:id]} and is_public = 1 and container_type in" +
+ " ('Project','Principal','Course','Issue','Document','Message','News','StudentWorkScore','HomewCommon'))"+
+ " or (container_type = 'Course' and is_public <> -1 and container_id in (#{user_course_ids.join(',')})) )" +
+ " and (filename like '%#{search}%') ").order("created_on desc")
end
elsif params[:type] == "2" #课程资源
if User.current.id.to_i == params[:id].to_i
@attachments = Attachment.where("author_id = #{params[:id]} and container_type = 'Course' and (filename like '%#{search}%')").order("created_on desc")
else
- @attachments = Attachment.where("author_id = #{params[:id]} and is_public = 1 and container_type = 'Course' and (filename like '%#{search}%') ").order("created_on desc")
+ user_course_ids = User.find(params[:id]).courses.visible.map { |c| c.id} #如果课程私有资源,那么要看这个资源的课程是不是在 这个user的所有我可见的课程中
+ @attachments = Attachment.where("((author_id = #{params[:id]} and is_public = 1 and container_type = 'Course') "+
+ "or (container_type = 'Course' and is_public <> -1 and container_id in (#{user_course_ids.join(',')})) )"+
+ " and (filename like '%#{search}%') ").order("created_on desc")
end
elsif params[:type] == "3" #项目资源
if User.current.id.to_i == params[:id].to_i
From 425e0dd89a953885f844e277730d4865ed633181 Mon Sep 17 00:00:00 2001
From: huang
Date: Wed, 19 Aug 2015 15:03:04 +0800
Subject: [PATCH 38/90] =?UTF-8?q?=E5=85=AC=E5=85=B1=E8=AE=A8=E8=AE=BA?=
=?UTF-8?q?=E5=8C=BA=E6=B6=88=E6=81=AF=E9=A1=B5=E9=9D=A2=E6=B7=BB=E5=8A=A0?=
=?UTF-8?q?=20=E9=83=A8=E5=88=86=E7=95=8C=E9=9D=A2=E4=BF=AE=E6=94=B9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/controllers/users_controller.rb | 17 ++++++++--
app/views/users/user_messages.html.erb | 44 +++++++++++++++++---------
2 files changed, 43 insertions(+), 18 deletions(-)
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index d77ccb958..bc3719685 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -115,31 +115,42 @@ class UsersController < ApplicationController
@user_course_messages = @user.course_messages.reverse
@user_forge_messages = @user.forge_messages.reverse
@user_forum_messages = @user.forum_messages.reverse
+ @user_course_messages_count = @user_course_messages.count
+ @user_forge_messages_count = @user_forum_messages.count
when 'homework'
@user_course_messages = CourseMessage.where("course_message_type =? and user_id =?", "HomeworkCommon", @user).order("created_at desc")
- @user_forge_messages = nil
+ @user_course_messages_count = @user_course_messages.count
when 'course_message'
@user_course_messages = CourseMessage.where("course_message_type =? and user_id =?", "Message", @user).order("created_at desc")
+ @user_course_messages_count = @user_course_messages.count
when 'forge_message'
@user_forge_messages = ForgeMessage.where("forge_message_type =? and user_id =?", "Message", @user).order("created_at desc")
when 'course_news'
@user_course_messages = CourseMessage.where("course_message_type =? and user_id =?", "News", @user).order("created_at desc")
+ @user_course_messages_count = @user_course_messages.count
when 'forge_news'
@user_forge_messages = ForgeMessage.where("forge_message_type =? and user_id =?", "News", @user).order("created_at desc")
when 'poll'
@user_course_messages = CourseMessage.where("course_message_type =? and user_id =?", "Poll", @user).order("created_at desc")
+ @user_course_messages_count = @user_course_messages.count
when 'works_reviewers'
@user_course_messages = CourseMessage.where("course_message_type =? and user_id =?", "StudentWorksScore", @user).order("created_at desc")
+ @user_course_messages_count = @user_course_messages.count
when 'works_reply'
@user_course_messages = CourseMessage.where("course_message_type =? and user_id =?", "JournalsForMessage", @user).order("created_at desc")
+ @user_course_messages_count = @user_course_messages.count
when 'issue'
@user_forge_messages = ForgeMessage.where("forge_message_type =? and user_id =?", "Issue", @user).order("created_at desc")
- @user_course_messages = nil
+ @user_forge_messages_count = @user_forge_messages.count
when 'journal' # 缺陷状态更新、留言
@user_forge_messages = ForgeMessage.where("forge_message_type =? and user_id =?", "Forum", @user).order("created_at desc")
- @user_course_messages = nil
+ @user_forge_messages_count = @user_forge_messages.count
when 'forum'
@user_forum_messages = ForumMessage.where("memo_message_type =? and user_id =?", "Forum", @user).order("created_at desc")
+ @user_forum_messages_count = @user_forum_messages.count
+ else
+ render_404
+ return
end
respond_to do |format|
format.html{render :layout=>'base_users_new'}
diff --git a/app/views/users/user_messages.html.erb b/app/views/users/user_messages.html.erb
index 089dca32f..233b5bcb2 100644
--- a/app/views/users/user_messages.html.erb
+++ b/app/views/users/user_messages.html.erb
@@ -7,19 +7,31 @@
<%= link_to "全部",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user} %>
-
- <%= link_to "作业消息",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user, :type => 'homework'} %>
- <%= link_to "课程讨论区",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user, :type => 'course_message'} %>
- <%= link_to "课程通知",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user, :type => 'course_news'} %>
-
- <%= link_to "问卷调查",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user, :type => 'poll'} %>
- <%= link_to "作品评阅",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user, :type => 'works_reviewers'} %>
- <%= link_to "作品讨论",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user, :type => 'works_reply'} %>
-
- <%= link_to "指派给我",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user, :type => 'issue'} %>
- <%= link_to "问题更新",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user, :type => 'issue_update'} %>
- <%= link_to "项目讨论区",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user, :type => 'forge_message'} %>
- <%= link_to "项目新闻",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user, :type => 'forge_news'} %>
+ <%# 课程相关消息 %>
+ <% unless @user_course_messages.nil? %>
+ <% unless @user_course_messages_count > 0 %>
+ <%= link_to "作业消息",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user, :type => 'homework'} %>
+ <% end %>
+ <%= link_to "课程讨论区",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user, :type => 'course_message'} %>
+ <%= link_to "发布了课程通知",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user, :type => 'course_news'} %>
+ <%= link_to "问卷调查",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user, :type => 'poll'} %>
+ <% unless @user_course_messages_count > 0 %>
+ <%= link_to "作品评阅",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user, :type => 'works_reviewers'} %>
+ <% end %>
+ <%= link_to "作品讨论",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user, :type => 'works_reply'} %>
+ <% end %>
+ <%# 项目相关消息 %>
+ <% unless @user_forge_messages.nil? %>
+ <%= link_to "指派给我",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user, :type => 'issue'} %>
+ <%= link_to "更新了问题",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user, :type => 'issue_update'} %>
+ <%= link_to "项目讨论区",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user, :type => 'forge_message'} %>
+ <%= link_to "发布了新闻",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user, :type => 'forge_news'} %>
+ <% end %>
+ <%# 公共贴吧 %>
+ <% unless @user_forum_messages.nil? %>
+ <%= link_to "发布了帖子",{:controller=> 'users', :action => 'user_messages', id: User.current.id, host: Setting.host_user, :type => 'forum'} %>
+ <% end %>
+ <%# 用户留言 %>
@@ -82,7 +94,7 @@
"><%= ucm.course_message.user %>
">作品评阅
- <%= link_to ucm.course_message.comment, nil,:class=>"#{ucm.viewed==0?"newsBlack":"newsGrey"}" %>
+ <%= link_to ucm.course_message.comment, student_work_path(ucm.course_message.id),:class=>"#{ucm.viewed==0?"newsBlack":"newsGrey"}" %> %>
<%= time_tag(ucm.course_message.created_at).html_safe %>
<% end %>
@@ -92,7 +104,7 @@
"><%= ucm.course_message.user %>
">作品讨论
- <%= link_to ucm.course_message.notes, nil,:class=>"#{ucm.viewed==0?"newsBlack":"newsGrey"}" %>
+ <%= link_to ucm.course_message.notes, student_work_path(ucm.course_message.id),:class=>"#{ucm.viewed==0?"newsBlack":"newsGrey"}" %>
<%= time_tag(ucm.course_message.created_on).html_safe %>
<% end %>
@@ -167,6 +179,8 @@
<% end %>
<% end %>
<% end %>
+ <% unless @user_forum_messages.nil? %>
+ <% end %>
<% else %>
暂无消息!
<% end %>
From 929da7512da5d1c17d8e913b7e7937424faabead Mon Sep 17 00:00:00 2001
From: lizanle <491823689@qq.com>
Date: Wed, 19 Aug 2015 17:13:57 +0800
Subject: [PATCH 39/90] =?UTF-8?q?=E8=B5=84=E6=BA=90=E5=BA=93=E6=9C=80?=
=?UTF-8?q?=E6=96=B0=E7=95=8C=E9=9D=A2=E4=BF=AE=E6=94=B9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/controllers/users_controller.rb | 33 ++++++++-
.../users/_resource_search_form.html.erb | 2 +-
.../users/_resource_share_popup.html.erb | 15 +++-
app/views/users/_resources_list.html.erb | 5 +-
app/views/users/user_resource.html.erb | 58 +++++++++-------
public/stylesheets/images/homepage_icon.png | Bin 0 -> 6829 bytes
public/stylesheets/images/nav_icon.png | Bin 0 -> 3204 bytes
public/stylesheets/public_new.css | 65 ++++++++++++++----
8 files changed, 133 insertions(+), 45 deletions(-)
create mode 100644 public/stylesheets/images/homepage_icon.png
create mode 100644 public/stylesheets/images/nav_icon.png
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index c523bbb3d..e4109e5bb 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -825,7 +825,38 @@ class UsersController < ApplicationController
# 删除用户资源
def user_resource_delete
Attachment.delete(params[:resource_id])
- @attachments = Attachment.where("author_id = #{params[:id]} and container_type in('Project','Principal','Course','Issue','Document','Message','News','StudentWorkScore','HomewCommon') ").order("created_on desc")
+ #@attachments = Attachment.where("author_id = #{params[:id]} and container_type in('Project','Principal','Course','Issue','Document','Message','News','StudentWorkScore','HomewCommon') ").order("created_on desc")
+ if(params[:type].nil? || params[:type] == "1") #全部
+ if User.current.id.to_i == params[:id].to_i
+ @attachments = Attachment.where("author_id = #{params[:id]} and container_type in('Project','Principal','Course','Issue','Document','Message','News','StudentWorkScore','HomewCommon') ").order("created_on desc")
+ else
+ user_course_ids = User.find(params[:id]).courses.visible.map { |c| c.id} #如果课程私有资源,那么要看这个资源的课程是不是在 这个user的所有我可见的课程中
+ @attachments = Attachment.where("(author_id = #{params[:id]} and is_public = 1 " +
+ "and container_type in('Project','Principal','Course','Issue','Document','Message','News','StudentWorkScore','HomewCommon')) " +
+ "or (container_type = 'Course' and is_public <> -1 and container_id in (#{user_course_ids.join(',')}))").order("created_on desc")
+ end
+ elsif params[:type] == "2" #课程资源
+ if User.current.id.to_i == params[:id].to_i
+ @attachments = Attachment.where("author_id = #{params[:id]} and container_type = 'Course'").order("created_on desc")
+ else
+ user_course_ids = User.find(params[:id]).courses.visible.map { |c| c.id} #如果课程私有资源,那么要看这个资源的课程是不是在 这个user的所有我可见的课程中
+ @attachments = Attachment.where("(author_id = #{params[:id]} and is_public = 1 and container_type = 'Course')"+
+ "or (container_type = 'Course' and is_public <> -1 and container_id in (#{user_course_ids.join(',')}))").order("created_on desc")
+ end
+ elsif params[:type] == "3" #项目资源
+ if User.current.id.to_i == params[:id].to_i
+ @attachments = Attachment.where("author_id = #{params[:id]} and container_type = 'Project'").order("created_on desc")
+ else
+ @attachments = Attachment.where("author_id = #{params[:id]} and is_public = 1 and container_type = 'Project' ").order("created_on desc")
+ end
+ elsif params[:type] == "4" #附件
+ if User.current.id.to_i == params[:id].to_i
+ @attachments = Attachment.where("author_id = #{params[:id]} and container_type in('Project','Issue','Document','Message','News','StudentWorkScore','HomewCommon')").order("created_on desc")
+ else
+ @attachments = Attachment.where("author_id = #{params[:id]} and is_public = 1 and container_type in('Issue','Document','Message','News','StudentWorkScore','HomewCommon')").order("created_on desc")
+ end
+ end
+ @type = params[:type]
respond_to do |format|
format.js
end
diff --git a/app/views/users/_resource_search_form.html.erb b/app/views/users/_resource_search_form.html.erb
index 725167b65..5f854cba0 100644
--- a/app/views/users/_resource_search_form.html.erb
+++ b/app/views/users/_resource_search_form.html.erb
@@ -2,6 +2,6 @@
:remote=>true ,:method => 'post',:class=>'resourcesSearchloadBox',:id=>'resource_search_form') do %>
<%= hidden_field_tag(:type,type) %>
- <%= submit_tag '',:class=>'searchIcon',:style=>'border-style:none' %>
+ <%= submit_tag '',:class=>'homepageSearchIcon',:onfocus=>'this.blur();',:style=>'border-style:none' %>
<% end %>
\ No newline at end of file
diff --git a/app/views/users/_resource_share_popup.html.erb b/app/views/users/_resource_share_popup.html.erb
index 01ac79075..cad94056c 100644
--- a/app/views/users/_resource_share_popup.html.erb
+++ b/app/views/users/_resource_share_popup.html.erb
@@ -1,8 +1,17 @@
-