diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb
index d1357d43f..e60e37bce 100644
--- a/app/controllers/accounts_controller.rb
+++ b/app/controllers/accounts_controller.rb
@@ -160,7 +160,7 @@ class AccountsController < ApplicationController
# 发送验证码
# params[:login] 手机号或者邮箱号
- # params[:type]为事件通知类型 1:用户注册注册 2:忘记密码 3: 绑定手机 4: 绑定邮箱 # 如果有新的继续后面加
+ # params[:type]为事件通知类型 1:用户注册注册 2:忘记密码 3: 绑定手机 4: 绑定邮箱, 5: 验收手机号有效 # 如果有新的继续后面加
# 发送验证码:send_type 1:注册手机验证码 2:找回密码手机验证码 3:找回密码邮箱验证码 4:绑定手机 5:绑定邮箱
# 6:手机验证码登录 7:邮箱验证码登录 8:邮箱注册验证码 9: 验收手机号有效
def get_verification_code
@@ -200,7 +200,7 @@ class AccountsController < ApplicationController
session[:user_id] = nil
end
- # type 事件类型 1:用户注册 2:忘记密码 3: 绑定手机 4: 绑定邮箱 # 如果有新的继续后面加
+ # type 事件类型 1:用户注册 2:忘记密码 3: 绑定手机 4: 绑定邮箱, 5: 验证手机号是否有效 # 如果有新的继续后面加
# login_type 1:手机类型 2:邮箱类型
def verify_type login_type, type
case type
@@ -212,6 +212,8 @@ class AccountsController < ApplicationController
login_type == 1 ? 4 : tip_exception('请填写正确的手机号')
when 4
login_type == 1 ? tip_exception('请填写正确的邮箱') : 5
+ when 5
+ login_type == 1 ? 9 : tip_exception('请填写正确的手机号')
end
end
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index e825d53da..2e2c7ff56 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -64,10 +64,10 @@ class ApplicationController < ActionController::Base
# 发送及记录激活码
# 发送验证码:type 1:注册手机验证码 2:找回密码手机验证码 3:找回密码邮箱验证码 4:绑定手机 5:绑定邮箱
- # 6:手机验证码登录 7:邮箱验证码登录 8:邮箱注册验证码
+ # 6:手机验证码登录 7:邮箱验证码登录 8:邮箱注册验证码 9:验证手机号有效
def check_verification_code(code, send_type, value)
case send_type
- when 1, 2, 4
+ when 1, 2, 4, 9
# 手机类型的发送
sigle_para = {phone: value}
status = Educoder::Sms.send(mobile: value, code: code)
@@ -241,14 +241,18 @@ class ApplicationController < ActionController::Base
User.current = User.find 57703
end
- if params[:debug] == 'teacher' #todo 为了测试,记得讲debug删除
- User.current = User.find 81403
- elsif params[:debug] == 'student'
- User.current = User.find 8686
- elsif params[:debug] == 'admin'
- User.current = User.find 1
- end
+ # 测试版前端需求
+ logger.info("######domain: #{request.host}")
+ if request.host == "47.96.87.25"
+ if params[:debug] == 'teacher' #todo 为了测试,记得讲debug删除
+ User.current = User.find 81403
+ elsif params[:debug] == 'student'
+ User.current = User.find 8686
+ elsif params[:debug] == 'admin'
+ User.current = User.find 1
+ end
+ end
# User.current = User.find 81403
end
@@ -583,4 +587,8 @@ class ApplicationController < ActionController::Base
def render_parameter_missing
render json: { status: -1, message: '参数缺失' }
end
+
+ def set_export_cookies
+ cookies[:fileDownload] = true
+ end
end
diff --git a/app/controllers/courses_controller.rb b/app/controllers/courses_controller.rb
index 9ae909dbc..abc3e4856 100644
--- a/app/controllers/courses_controller.rb
+++ b/app/controllers/courses_controller.rb
@@ -1027,7 +1027,10 @@ class CoursesController < ApplicationController
tip_exception(403,"无权限操作")
elsif @all_members.size == 0
normal_status(-1,"课堂暂时没有学生")
+ elsif params[:export].present? && params[:export]
+ normal_status(0,"正在下载中")
else
+ set_export_cookies
member_to_xlsx(@course, @all_members, @c_homeworks, @c_exercises, @c_tasks)
filename_ = "#{current_user.real_name}_#{@course.name}_全部成绩_#{Time.now.strftime('%Y%m%d_%H%M%S')}"
render xlsx: "#{format_sheet_name filename_.strip}",template: "courses/export_member_scores_excel.xlsx.axlsx",
diff --git a/app/controllers/exercises_controller.rb b/app/controllers/exercises_controller.rb
index 7c8c07d01..6f121db5f 100644
--- a/app/controllers/exercises_controller.rb
+++ b/app/controllers/exercises_controller.rb
@@ -1256,9 +1256,12 @@ class ExercisesController < ApplicationController
normal_status(-1,"试卷未发布")
elsif (@exercise_users_size == 0) || ( @export_ex_users&.exercise_user_committed.size == 0)
normal_status(-1,"暂无用户提交")
+ elsif params[:export].present? && params[:export]
+ normal_status(0,"正在下载中")
else
respond_to do |format|
format.xlsx{
+ set_export_cookies
get_export_users(@exercise,@course,@export_ex_users)
exercise_export_name_ =
"#{current_user.real_name}_#{@course.name}_#{@exercise.exercise_name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}"
@@ -1281,7 +1284,12 @@ class ExercisesController < ApplicationController
@exercise_questions = @exercise.exercise_questions.includes(:exercise_choices).order("question_number ASC")
filename_ = "#{@exercise.user.real_name}_#{@course.name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}.pdf"
stylesheets = "#{Rails.root}/app/templates/exercise_export/exercise_export.css"
- render pdf: 'exercise_export/blank_exercise', filename: filename_, stylesheets: stylesheets
+ if params[:export].present? && params[:export]
+ normal_status(0,"正在下载中")
+ else
+ set_export_cookies
+ render pdf: 'exercise_export/blank_exercise', filename: filename_, stylesheets: stylesheets
+ end
end
#空白试卷预览页面,仅供测试使用,无其他任何用途
diff --git a/app/controllers/games_controller.rb b/app/controllers/games_controller.rb
index b2de6dcad..b3b062c1a 100644
--- a/app/controllers/games_controller.rb
+++ b/app/controllers/games_controller.rb
@@ -116,10 +116,11 @@ class GamesController < ApplicationController
@qrcode_str = Base64.encode64( qr.to_img.resize(400,400).to_s )
else
- @type = "image"
#conv = Iconv.new("GBK", "utf-8")
@game_challenge = @game.challenge
type = @game_challenge.show_type
+ @type = shixun_show_type type
+
workspace_path = @game.try(:picture_path)
@answer_path = "#{Rails.root}/#{workspace_path}/#{@game_challenge.expect_picture_path}"
@user_path = "#{Rails.root}/#{workspace_path}/#{@game_challenge.picture_path}"
diff --git a/app/controllers/graduation_tasks_controller.rb b/app/controllers/graduation_tasks_controller.rb
index aeb5c409d..0885eeae2 100644
--- a/app/controllers/graduation_tasks_controller.rb
+++ b/app/controllers/graduation_tasks_controller.rb
@@ -132,6 +132,8 @@ class GraduationTasksController < ApplicationController
tip_exception(403, "无权限操作")
elsif complete_works == 0
normal_status(-1,"暂无用户提交")
+ elsif params[:export].present? && params[:export]
+ normal_status(0,"正在下载中")
else
respond_to do |format|
format.xlsx{
@@ -148,12 +150,17 @@ class GraduationTasksController < ApplicationController
zip_works = @work_excel.where("work_status > 0")
status = checkfileSize(zip_works)
if status == 0
- respond_to do |format|
- format.zip{
- zipfile = zip_homework_common @task, zip_works
- file = decode64(zipfile[0][:base64file])
- send_file "#{OUTPUT_FOLDER}/#{file}", filename: filename_for_content_disposition(file), type: 'application/zip'
- }
+ if params[:export].present? && params[:export]
+ normal_status(0,"正在下载中")
+ else
+ respond_to do |format|
+ format.zip{
+ set_export_cookies
+ zipfile = zip_homework_common @task, zip_works
+ file = decode64(zipfile[0][:base64file])
+ send_file "#{OUTPUT_FOLDER}/#{file}", filename: filename_for_content_disposition(file), type: 'application/zip'
+ }
+ end
end
else
normal_status(status,status == -2 ? "500M" : "无附件可下载")
diff --git a/app/controllers/graduation_topics_controller.rb b/app/controllers/graduation_topics_controller.rb
index 96816c2a6..bd93401f3 100644
--- a/app/controllers/graduation_topics_controller.rb
+++ b/app/controllers/graduation_topics_controller.rb
@@ -271,7 +271,12 @@ class GraduationTopicsController < ApplicationController
students = course.students.joins(user: :user_extension).order("user_extensions.student_id")
graduation_topic_to_xlsx(students,course)
topic_export_name_ = "#{current_user.real_name}_#{course.name}_毕设选题_#{Time.now.strftime('%Y%m%d_%H%M%S')}"
- render xlsx: "#{topic_export_name_.strip}",template: "graduation_topics/export.xlsx.axlsx",locals: {table_columns:@topic_head_cells,topic_users:@topic_body_cells}
+ if params[:export].present? && params[:export]
+ normal_status(0,"正在下载中")
+ else
+ set_export_cookies
+ render xlsx: "#{topic_export_name_.strip}",template: "graduation_topics/export.xlsx.axlsx",locals: {table_columns:@topic_head_cells,topic_users:@topic_body_cells}
+ end
rescue Exception => e
uid_logger(e.message)
missing_template
diff --git a/app/controllers/homework_commons_controller.rb b/app/controllers/homework_commons_controller.rb
index 481253f5b..603a59920 100644
--- a/app/controllers/homework_commons_controller.rb
+++ b/app/controllers/homework_commons_controller.rb
@@ -207,9 +207,12 @@ class HomeworkCommonsController < ApplicationController
tip_exception(403, "无权限操作")
elsif @work_excel.blank? || @work_excel.size == 0
normal_status(-1,"暂无用户提交!")
+ elsif params[:export].present? && params[:export]
+ normal_status(0,"正在下载中")
else
respond_to do |format|
format.xlsx{
+ set_export_cookies
student_work_to_xlsx(@work_excel,@homework)
exercise_export_name = "#{current_user.real_name}_#{@course.name}_#{@homework.name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}"
render xlsx: "#{exercise_export_name.strip}",template: "homework_commons/works_list.xlsx.axlsx",locals:
@@ -229,12 +232,17 @@ class HomeworkCommonsController < ApplicationController
end
if status == 0
- respond_to do |format|
- format.zip{
- zipfile = zip_homework_common @homework, zip_works
- file = decode64(zipfile[0][:base64file])
- send_file "#{OUTPUT_FOLDER}/#{file}", filename: filename_for_content_disposition(file), type: 'application/zip'
- }
+ if params[:export].present? && params[:export]
+ normal_status(0,"正在下载中")
+ else
+ respond_to do |format|
+ format.zip{
+ set_export_cookies
+ zipfile = zip_homework_common @homework, zip_works
+ file = decode64(zipfile[0][:base64file])
+ send_file "#{OUTPUT_FOLDER}/#{file}", filename: filename_for_content_disposition(file), type: 'application/zip'
+ }
+ end
end
else
normal_status(status, status == -2 ? "500M" : "无附件可下载")
diff --git a/app/controllers/myshixuns_controller.rb b/app/controllers/myshixuns_controller.rb
index fa47fd7f6..1d6b15969 100644
--- a/app/controllers/myshixuns_controller.rb
+++ b/app/controllers/myshixuns_controller.rb
@@ -24,7 +24,7 @@ class MyshixunsController < ApplicationController
ActiveRecord::Base.transaction do
begin
@shixun = Shixun.select(:id, :identifier).find(@myshixun.shixun_id)
- @myshixun.destroy
+ @myshixun.destroy!
StudentWork.where(:myshixun_id => @myshixun.id).update_all(:myshixun_id => 0, :work_status => 0)
diff --git a/app/controllers/polls_controller.rb b/app/controllers/polls_controller.rb
index 87435f743..7d978d722 100644
--- a/app/controllers/polls_controller.rb
+++ b/app/controllers/polls_controller.rb
@@ -945,9 +945,12 @@ class PollsController < ApplicationController
tip_exception(403,"无权限操作")
elsif (@poll.polls_status == 1) || (@poll_export_questions.size == 0) || (@poll_commit_ids.size == 0)
normal_status(-1,"暂无用户提交")
+ elsif params[:export].present? && params[:export]
+ normal_status(0,"正在下载中")
else
respond_to do |format|
format.xlsx{
+ set_export_cookies
polls_export_name_ = "#{current_user.real_name}_#{@course.name}_#{@poll.polls_name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}"
polls_user_commit = poll_commit_result(@poll,@poll_export_questions,@poll_users,@poll_commit_ids)
render xlsx: "#{polls_export_name_.strip}",template: "polls/commit_result.xlsx.axlsx",locals: {polls_user_commit:polls_user_commit}
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index c9ed6c597..672477790 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -1,10 +1,2 @@
class ProjectsController < ApplicationController
- def search
- query_params = { keyword: params[:keyword], category: 'manage' }
- projects = Users::ProjectService.new(current_user, query_params).call
-
- params[:limit] = params[:per_page].to_i.zero? ? 20 : params[:per_page].to_i
- @count = projects.count
- @projects = paginate projects
- end
end
\ No newline at end of file
diff --git a/app/controllers/users/base_controller.rb b/app/controllers/users/base_controller.rb
index fd138a182..969aca320 100644
--- a/app/controllers/users/base_controller.rb
+++ b/app/controllers/users/base_controller.rb
@@ -43,7 +43,7 @@ class Users::BaseController < ApplicationController
page = page_value
per_page = per_page_value
- return Kaminari.paginate_array(objs).page(page).per(per_page) unless observed_logged_user? && opts[:special]
+ return Kaminari.paginate_array(objs).page(page).per(per_page) unless opts[:special] && observed_logged_user?
# note: 为实现第一页少一条记录,让前端放置新建入口
if page == 1
diff --git a/app/controllers/users/projects_controller.rb b/app/controllers/users/projects_controller.rb
index 863b99b37..07f4d5cac 100644
--- a/app/controllers/users/projects_controller.rb
+++ b/app/controllers/users/projects_controller.rb
@@ -1,4 +1,6 @@
class Users::ProjectsController < Users::BaseController
+ skip_before_action :check_observed_user_exists!, only: [:search]
+
def index
projects = Users::ProjectService.new(observed_user, query_params).call
@@ -6,6 +8,15 @@ class Users::ProjectsController < Users::BaseController
@projects = paginate(projects.includes(:project_score, owner: { user_extension: :school }), special: true)
end
+ def search
+ query_params = { keyword: params[:keyword], category: 'manage' }
+ projects = Users::ProjectService.new(current_user, query_params).call
+
+ params[:limit] = params[:per_page].to_i.zero? ? 20 : params[:per_page].to_i
+ @count = projects.count
+ @projects = paginate projects
+ end
+
private
def query_params
diff --git a/app/controllers/zips_controller.rb b/app/controllers/zips_controller.rb
index f4822b96b..3ed1eb8b3 100644
--- a/app/controllers/zips_controller.rb
+++ b/app/controllers/zips_controller.rb
@@ -8,7 +8,13 @@ class ZipsController < ApplicationController
def shixun_report
service = BatchExportShixunReportService.new(@homework, @all_student_works)
filename_ = filename_for_content_disposition(service.filename)
- send_file service.zip, filename: filename_, type: 'application/zip'
+ if params[:export].present? && params[:export]
+ normal_status(0,"正在下载中")
+ else
+ set_export_cookies
+ send_file service.zip, filename: filename_, type: 'application/zip'
+ end
+
rescue BatchExportShixunReportService::Error => ex
normal_status(-1, ex.message)
end
@@ -18,7 +24,12 @@ class ZipsController < ApplicationController
exercises = ExportExercisesService.new(@exercise,@ex_users,@request_url)
file_name_ = filename_for_content_disposition(exercises.filename)
- send_file exercises.ex_zip, filename: file_name_, type: 'application/zip'
+ if params[:export].present? && params[:export]
+ normal_status(0,"正在下载中")
+ else
+ set_export_cookies
+ send_file exercises.ex_zip, filename: file_name_, type: 'application/zip'
+ end
rescue Exception => e
normal_status(-1, e.message)
end
diff --git a/app/helpers/games_helper.rb b/app/helpers/games_helper.rb
index aff05904f..5a9871673 100644
--- a/app/helpers/games_helper.rb
+++ b/app/helpers/games_helper.rb
@@ -6,7 +6,7 @@ module GamesHelper
end
# 获取目录下所有文件,返回一个文件名的数组 type是查看文件的类型image表示图片
- # type [[1, "图片"], [2, "apk/exe"], [3, "txt"], [4, "html"]]
+ # type [[1, "图片"], [2, "apk/exe"], [3, "txt"], [4, "html"], [5, "mp3"], [6, "mp4"]]
def get_dir_filename(path, type, game_id)
answer_picture = []
return answer_picture unless File.directory?(path)
@@ -39,6 +39,12 @@ module GamesHelper
end
f.close
@type = 'txt'
+ elsif extension == 'mp3' && type == 5
+ answer_picture << file
+ @type = 'mp3'
+ elsif extension == 'mp4' && type == 6
+ answer_picture << file
+ @type = 'mp4'
end
end
@@ -51,4 +57,21 @@ module GamesHelper
"编译失败,请在测试结果中查看具体的错误信息" : test_set.try(:actual_output)
end
end
+
+ def shixun_show_type type
+ case type.to_i
+ when 1
+ "image"
+ when 2
+ "apk/exe"
+ when 3
+ "txt"
+ when 4
+ "html"
+ when 5
+ "mp3"
+ when 6
+ "mp4"
+ end
+ end
end
diff --git a/app/models/challenge.rb b/app/models/challenge.rb
index 0bea54eb4..8e4d2ae42 100644
--- a/app/models/challenge.rb
+++ b/app/models/challenge.rb
@@ -1,5 +1,6 @@
class Challenge < ApplicationRecord
# difficulty: 关卡难度: 1.简单 2.中等 3.困难
+ # show_type: 效果展示:-1.无效果 1.图片 2.apk/exe 3.txt 4.html 5.mp3 6.mp4
default_scope { order("challenges.position asc") }
belongs_to :shixun, :touch => true, counter_cache: true
diff --git a/app/services/private_messages/create_service.rb b/app/services/private_messages/create_service.rb
index 560f1a540..88f3a084f 100644
--- a/app/services/private_messages/create_service.rb
+++ b/app/services/private_messages/create_service.rb
@@ -3,7 +3,7 @@ class PrivateMessages::CreateService < ApplicationService
attr_reader :sender, :receiver, :params
- def initialize(sender, receiver, **params)
+ def initialize(sender, receiver, params)
@sender = sender
@receiver = receiver
@params = params
diff --git a/app/views/games/picture_display.json.jbuilder b/app/views/games/picture_display.json.jbuilder
index 541c478a9..b43efa57e 100644
--- a/app/views/games/picture_display.json.jbuilder
+++ b/app/views/games/picture_display.json.jbuilder
@@ -24,5 +24,30 @@ elsif @type == "txt"
json.contents @contents.html_safe
elsif @type =="qrcode"
json.qrcode_str @qrcode_str
+elsif @type == "mp3" || @type == "mp4"
+ if @type == "mp4"
+ json.orignal_file [{"file_url": "http://120.27.231.56:48080/attachments/download/378171/123.mp4"}]
+ json.user_file [{"file_url": "http://120.27.231.56:48080/attachments/download/378172/456.mp4"}]
+ json.answer_file [{"file_url": "http://120.27.231.56:48080/attachments/download/378173/789.mp4"}]
+ else
+ json.orignal_file [{"file_url": "http://120.27.231.56:48080/attachments/download/378174/58099.mp3"}]
+ json.user_file [{"file_url": "http://120.27.231.56:48080/attachments/download/378175/654058514.mp3"}]
+ json.answer_file [{"file_url": "http://120.27.231.56:48080/attachments/download/378175/654058514.mp3"}]
+ end
+ # json.orignal_file do
+ # json.array! @orignal_picture do |file|
+ # json.file_url attachment_show_users_path(:file_name => file, :path => @original_path)
+ # end
+ # end
+ # json.user_file do
+ # json.array! @user_picture do |file|
+ # json.file_url attachment_show_users_path(:file_name => file, :path => @user_path, :time => Time.now.to_i)
+ # end
+ # end
+ # json.answer_file do
+ # json.array! @answer_picture do |file|
+ # json.file_url attachment_show_users_path(:file_name => file, :path => @answer_path)
+ # end
+ # end
end
\ No newline at end of file
diff --git a/app/views/users/get_user_info.json.jbuilder b/app/views/users/get_user_info.json.jbuilder
index d12b950f9..fc2eca762 100644
--- a/app/views/users/get_user_info.json.jbuilder
+++ b/app/views/users/get_user_info.json.jbuilder
@@ -1,4 +1,5 @@
json.username @user.full_name
+json.real_name @user.real_name
json.login @user.login
json.user_id @user.id
json.image_url url_to_avatar(@user)
diff --git a/app/views/projects/search.json.jbuilder b/app/views/users/projects/search.json.jbuilder
similarity index 100%
rename from app/views/projects/search.json.jbuilder
rename to app/views/users/projects/search.json.jbuilder
diff --git a/config/routes.rb b/config/routes.rb
index 1ce0e9d4c..1a573a3c2 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -84,7 +84,7 @@ Rails.application.routes.draw do
get :system_update
resource :trial_apply, only: [:create]
- resources :projects, only: [] do
+ resources :projects, module: :users, only: [] do
get :search, on: :collection
end
diff --git a/public/compatibility.html b/public/compatibility.html
index f13c673f5..f28bad2c8 100644
--- a/public/compatibility.html
+++ b/public/compatibility.html
@@ -5,9 +5,9 @@
EduCoder
-
-
-
+
+
+
diff --git a/public/images/educoder/path.png b/public/images/educoder/path.png
new file mode 100644
index 000000000..d3d816012
Binary files /dev/null and b/public/images/educoder/path.png differ
diff --git a/public/javascripts/media/clappr-playback-rate-plugin.min.js b/public/javascripts/media/clappr-playback-rate-plugin.min.js
new file mode 100644
index 000000000..8bbcbfaca
--- /dev/null
+++ b/public/javascripts/media/clappr-playback-rate-plugin.min.js
@@ -0,0 +1 @@
+!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e(require("clappr")):"function"==typeof define&&define.amd?define("clappr-playback-rate-plugin",["clappr"],e):"object"==typeof exports?exports["clappr-playback-rate-plugin"]=e(require("clappr")):t["clappr-playback-rate-plugin"]=e(t.clappr)}("undefined"!=typeof self?self:this,function(t){return function(t){function e(n){if(a[n])return a[n].exports;var o=a[n]={i:n,l:!1,exports:{}};return t[n].call(o.exports,o,o.exports,e),o.l=!0,o.exports}var a={};return e.m=t,e.c=a,e.d=function(t,a,n){e.o(t,a)||Object.defineProperty(t,a,{configurable:!1,enumerable:!0,get:n})},e.n=function(t){var a=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(a,"a",a),a},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="",e(e.s=0)}([function(t,e,a){"use strict";function n(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function o(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!e||"object"!=typeof e&&"function"!=typeof e?t:e}function r(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}Object.defineProperty(e,"__esModule",{value:!0});var i=a(1),l=(a.n(i),a(2)),c=a.n(l),s=a(3),u=a.n(s),p=function(){function t(t,e){for(var a=0;a\n <%= title %>\n\n\n'},function(t,e,a){e=t.exports=a(4)(void 0),e.push([t.i,".media-control[data-media-control] .media-control-layer[data-controls] .playback_rate[data-playback-rate-select] {\n float: right;\n margin-top: 5px;\n position: relative; }\n .media-control[data-media-control] .media-control-layer[data-controls] .playback_rate[data-playback-rate-select] button.media-control-button.media-control-icon {\n font-family: Roboto,\"Open Sans\",Arial,sans-serif;\n -webkit-font-smoothing: antialiased;\n font-size: 12px;\n cursor: pointer;\n padding: 10px; }\n .media-control[data-media-control] .media-control-layer[data-controls] .playback_rate[data-playback-rate-select] button.media-control-button.media-control-icon:hover {\n color: #c9c9c9; }\n .media-control[data-media-control] .media-control-layer[data-controls] .playback_rate[data-playback-rate-select] button.media-control-button.media-control-icon.changing {\n -webkit-animation: pulse 0.5s infinite alternate; }\n .media-control[data-media-control] .media-control-layer[data-controls] .playback_rate[data-playback-rate-select] > ul {\n display: none;\n list-style-type: none;\n position: absolute;\n bottom: 25px;\n border: 1px solid black;\n border-radius: 4px;\n background-color: rgba(0, 0, 0, 0.7); }\n .media-control[data-media-control] .media-control-layer[data-controls] .playback_rate[data-playback-rate-select] li {\n position: relative;\n font-size: 12px; }\n .media-control[data-media-control] .media-control-layer[data-controls] .playback_rate[data-playback-rate-select] li[data-title] {\n padding: 5px; }\n .media-control[data-media-control] .media-control-layer[data-controls] .playback_rate[data-playback-rate-select] li a {\n color: #aaa;\n padding: 2px 10px 2px 15px;\n display: block;\n text-decoration: none; }\n .media-control[data-media-control] .media-control-layer[data-controls] .playback_rate[data-playback-rate-select] li a.active {\n background-color: black;\n font-weight: bold;\n color: #fff; }\n .media-control[data-media-control] .media-control-layer[data-controls] .playback_rate[data-playback-rate-select] li a.active:before {\n content: '\\2713';\n position: absolute;\n top: 2px;\n left: 4px; }\n .media-control[data-media-control] .media-control-layer[data-controls] .playback_rate[data-playback-rate-select] li a:hover {\n color: #fff;\n text-decoration: none; }\n\n@-webkit-keyframes pulse {\n 0% {\n color: #fff; }\n 50% {\n color: #ff0101; }\n 100% {\n color: #B80000; } }\n",""])},function(t,e){function a(t,e){var a=t[1]||"",o=t[3];if(!o)return a;if(e&&"function"==typeof btoa){var r=n(o);return[a].concat(o.sources.map(function(t){return"/*# sourceURL="+o.sourceRoot+t+" */"})).concat([r]).join("\n")}return[a].join("\n")}function n(t){return"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(t))))+" */"}t.exports=function(t){var e=[];return e.toString=function(){return this.map(function(e){var n=a(e,t);return e[2]?"@media "+e[2]+"{"+n+"}":n}).join("")},e.i=function(t,a){"string"==typeof t&&(t=[[null,t,""]]);for(var n={},o=0;o0&&e._renderPlugin()})})}},{key:"removeThumbnail",value:function(t){var e=this,n=t.constructor===Array?t:[t];return this._onThumbsLoaded.then(function(){var t=!0,o=!1;return n.forEach(function(n){var i=e._thumbs.some(function(t,o){return t.src===n&&(e._thumbs.splice(o,1),e._getOptions().backdropHeight&&(e._$backdropCarouselImgs[o].remove(),e._$backdropCarouselImgs.splice(o,1)),!0)});i?o=!0:t=!1}),o&&e._renderPlugin(),c.Promise.resolve(t)})}},{key:"_init",value:function(){this._thumbsLoaded&&(this._$backdropCarouselImgs=[],this._createElements(),this._loadBackdrop(),this._renderPlugin())}},{key:"_getOptions",value:function(){if(!("scrubThumbnails"in this.core.options))throw"'scrubThumbnails property missing from options object.";return this.core.options.scrubThumbnails}},{key:"_appendElToMediaControl",value:function(){this.core.mediaControl.$el.find(".media-control-background").first().after(this.el)}},{key:"_onMouseMove",value:function(t){this._calculateHoverPosition(t),this._show=!0,this._renderPlugin()}},{key:"_onMouseLeave",value:function(){this._show=!1,this._renderPlugin()}},{key:"_calculateHoverPosition",value:function(t){var e=t.pageX-this.core.mediaControl.$seekBarContainer.offset().left;this._hoverPosition=Math.min(1,Math.max(e/this.core.mediaControl.$seekBarContainer.width(),0))}},{key:"_buildThumbsFromOptions",value:function(){var t=this,e=this._getOptions().thumbs,n=e.map(function(e){return t._addThumbFromSrc(e)});return c.Promise.all(n)}},{key:"_addThumbFromSrc",value:function(t){var e=this;return new c.Promise(function(e,n){var o=new Image;o.onload=function(){e(o)},o.onerror=n,o.src=t.url}).then(function(n){var o=t.time,i=null;e._thumbs.some(function(t,e){return o0?e._thumbs[i-1]:null;u&&(u.duration=o-u.time);var s=r?r.time-t.time:null,a=n.width,c=n.height,l={imageW:a,imageH:c,x:t.x||0,y:t.y||0,w:t.w||a,h:t.h||c,url:t.url,time:o,duration:s,src:t};return e._thumbs.splice(i,0,l),l})}},{key:"_buildImg",value:function(t,e){var n=e/t.h,o=(0,a.$)(" ").addClass("thumbnail-img").attr("src",t.url),i=(0,a.$)("
").addClass("thumbnail-container");return i.css("width",t.w*n),i.css("height",e),o.css({height:t.imageH*n,left:-1*t.x*n,top:-1*t.y*n}),i.append(o),i}},{key:"_loadBackdrop",value:function(){if(this._getOptions().backdropHeight)for(var t=this._$carousel,e=0;e=0;n--){var o=e[n];if(o.time<=t)return n}return 0}},{key:"_renderPlugin",value:function(){this._thumbsLoaded&&(this._show&&this._thumbs.length>0?(this.$el.removeClass("hidden"),this._updateCarousel(),this._updateSpotlightThumb()):this.$el.addClass("hidden"))}},{key:"_createElements",value:function(){this.$el.html(this.template({backdropHeight:this._getOptions().backdropHeight,spotlightHeight:this._getOptions().spotlightHeight})),this.$el.append(a.Styler.getStyleFor(d["default"])),this._$spotlight=this.$el.find(".spotlight"),this._$backdrop=this.$el.find(".backdrop"),this._$carousel=this._$backdrop.find(".carousel"),this.$el.addClass("hidden"),this._appendElToMediaControl()}}]),e}(a.UICorePlugin);e["default"]=p,t.exports=e["default"]},function(t,e,n){(function(t,o){"use strict";function i(t,e){this._id=t,this._clearFn=e}var r=n(4).nextTick,u=Function.prototype.apply,s=Array.prototype.slice,a={},c=0;e.setTimeout=function(){return new i(u.call(setTimeout,window,arguments),clearTimeout)},e.setInterval=function(){return new i(u.call(setInterval,window,arguments),clearInterval)},e.clearTimeout=e.clearInterval=function(t){t.close()},i.prototype.unref=i.prototype.ref=function(){},i.prototype.close=function(){this._clearFn.call(window,this._id)},e.enroll=function(t,e){clearTimeout(t._idleTimeoutId),t._idleTimeout=e},e.unenroll=function(t){clearTimeout(t._idleTimeoutId),t._idleTimeout=-1},e._unrefActive=e.active=function(t){clearTimeout(t._idleTimeoutId);var e=t._idleTimeout;e>=0&&(t._idleTimeoutId=setTimeout(function(){t._onTimeout&&t._onTimeout()},e))},e.setImmediate="function"==typeof t?t:function(t){var n=c++,o=!(arguments.length<2)&&s.call(arguments,1);return a[n]=!0,r(function(){a[n]&&(o?t.apply(null,o):t.call(null),e.clearImmediate(n))}),n},e.clearImmediate="function"==typeof o?o:function(t){delete a[t]}}).call(e,n(1).setImmediate,n(1).clearImmediate)},function(t,e){"use strict";t.exports=function(){var t=[];return t.toString=function(){for(var t=[],e=0;e1)for(var n=1;n\r\n\r\n<% }; %>\r\n<% if (spotlightHeight) { %>\r\n
\r\n<% }; %>\r\n'},function(e,n){e.exports=t}])});
\ No newline at end of file
diff --git a/public/javascripts/media/clappr.min.js b/public/javascripts/media/clappr.min.js
new file mode 100644
index 000000000..450d57602
--- /dev/null
+++ b/public/javascripts/media/clappr.min.js
@@ -0,0 +1 @@
+!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.Clappr=e():t.Clappr=e()}(window,function(){return e={},f.m=d=[function(t,e,r){"use strict";e.__esModule=!0,e.default=function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}},function(t,e,r){"use strict";e.__esModule=!0;var i,n=r(39),a=(i=n)&&i.__esModule?i:{default:i};e.default=function(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!e||"object"!==(void 0===e?"undefined":(0,a.default)(e))&&"function"!=typeof e?t:e}},function(t,e,r){"use strict";e.__esModule=!0;var i=o(r(135)),n=o(r(77)),a=o(r(39));function o(t){return t&&t.__esModule?t:{default:t}}e.default=function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+(void 0===e?"undefined":(0,a.default)(e)));t.prototype=(0,n.default)(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(i.default?(0,i.default)(t,e):t.__proto__=e)}},function(t,e,r){"use strict";e.__esModule=!0;var i,n=r(76),a=(i=n)&&i.__esModule?i:{default:i};function o(t,e){for(var r=0;r")},M.garbage=function(t){this.options.recycleVideo&&"VIDEO"===t[0].tagName.toUpperCase()&&(t.children().remove(),D.push(t))},M);function M(){(0,s.default)(this,M)}x.options={recycleVideo:!1};var N=e.DoubleEventHandler=(F.prototype.handle=function(t,e,r){var i=!(2]*>/,Xe=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,Ye=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,Ze=/^(?:body|html)$/i,$e=/([A-Z])/g,_e=["val","css","html","text","data","width","height","offset"],bf=Se.createElement("table"),cf=Se.createElement("tr"),df={tr:Se.createElement("tbody"),tbody:bf,thead:bf,tfoot:bf,td:cf,th:cf,"*":Se.createElement("div")},ef=/complete|loaded|interactive/,ff=/^[\w-]*$/,hf=(gf={}).toString,jf={},mf=Se.createElement("div"),nf={tabindex:"tabIndex",readonly:"readOnly",for:"htmlFor",class:"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},of=Array.isArray||function(t){return t instanceof Array},jf.matches=function(t,e){if(!e||!t||1!==t.nodeType)return!1;var r=t.matches||t.webkitMatchesSelector||t.mozMatchesSelector||t.oMatchesSelector||t.matchesSelector;if(r)return r.call(t,e);var i,n=t.parentNode,a=!n;return a&&(n=mf).appendChild(t),i=~jf.qsa(n,e).indexOf(t),a&&mf.removeChild(t),i},kf=function(t){return t.replace(/-+(.)?/g,function(t,e){return e?e.toUpperCase():""})},lf=function(r){return Qe.call(r,function(t,e){return r.indexOf(t)==e})},jf.fragment=function(t,e,r){var i,n,a;return Xe.test(t)&&(i=Me(Se.createElement(RegExp.$1))),i||(t.replace&&(t=t.replace(Ye,"<$1>$2>")),e===Ke&&(e=We.test(t)&&RegExp.$1),e in df||(e="*"),(a=df[e]).innerHTML=""+t,i=Me.each(Re.call(a.childNodes),function(){a.removeChild(this)})),uf(r)&&(n=Me(i),Me.each(r,function(t,e){-1<_e.indexOf(t)?n[t](e):n.attr(t,e)})),i},jf.Z=function(t,e){return new Df(t,e)},jf.isZ=function(t){return t instanceof jf.Z},jf.init=function(t,e){var r;if(!t)return jf.Z();if("string"==typeof t)if("<"==(t=t.trim())[0]&&We.test(t))r=jf.fragment(t,RegExp.$1,e),t=null;else{if(e!==Ke)return Me(e).find(t);r=jf.qsa(Se,t)}else{if(qf(t))return Me(Se).ready(t);if(jf.isZ(t))return t;if(of(t))r=function(t){return Qe.call(t,function(t){return null!=t})}(t);else if(tf(t))r=[t],t=null;else if(We.test(t))r=jf.fragment(t.trim(),RegExp.$1,e),t=null;else{if(e!==Ke)return Me(e).find(t);r=jf.qsa(Se,t)}}return jf.Z(r,t)},(Me=function(t,e){return jf.init(t,e)}).extend=function(e){var r,t=Re.call(arguments,1);return"boolean"==typeof e&&(r=e,e=t.shift()),t.forEach(function(t){!function t(e,r,i){for(Le in r)i&&(uf(r[Le])||of(r[Le]))?(uf(r[Le])&&!uf(e[Le])&&(e[Le]={}),of(r[Le])&&!of(e[Le])&&(e[Le]=[]),t(e[Le],r[Le],i)):r[Le]!==Ke&&(e[Le]=r[Le])}(e,t,r)}),e},jf.qsa=function(t,e){var r,i="#"==e[0],n=!i&&"."==e[0],a=i||n?e.slice(1):e,o=ff.test(a);return t.getElementById&&o&&i?(r=t.getElementById(a))?[r]:[]:1!==t.nodeType&&9!==t.nodeType&&11!==t.nodeType?[]:Re.call(o&&!i&&t.getElementsByClassName?n?t.getElementsByClassName(a):t.getElementsByTagName(e):t.querySelectorAll(e))},Me.contains=Se.documentElement.contains?function(t,e){return t!==e&&t.contains(e)}:function(t,e){for(;e&&(e=e.parentNode);)if(e===t)return!0;return!1},Me.type=pf,Me.isFunction=qf,Me.isWindow=rf,Me.isArray=of,Me.isPlainObject=uf,Me.isEmptyObject=function(t){var e;for(e in t)return!1;return!0},Me.isNumeric=function(t){var e=Number(t),r=typeof t;return null!=t&&"boolean"!=r&&("string"!=r||t.length)&&!isNaN(e)&&isFinite(e)||!1},Me.inArray=function(t,e,r){return Oe.indexOf.call(e,t,r)},Me.camelCase=kf,Me.trim=function(t){return null==t?"":String.prototype.trim.call(t)},Me.uuid=0,Me.support={},Me.expr={},Me.noop=function(){},Me.map=function(t,e){var r,i,n,a=[];if(vf(t))for(i=0;i)<[^<]*)*<\/script>/gi,Ok=/^(?:text|application)\/javascript/i,Pk=/^(?:text|application)\/xml/i,Qk="application/json",Rk="text/html",Sk=/^\s*$/,Tk=Kk.createElement("a");function Vk(t,e,r,i){if(t.global)return function(t,e,r){var i=Ik.Event(e);return Ik(t).trigger(i,r),!i.isDefaultPrevented()}(e||Kk,r,i)}function Yk(t,e){var r=e.context;if(!1===e.beforeSend.call(r,t,e)||!1===Vk(e,r,"ajaxBeforeSend",[t,e]))return!1;Vk(e,r,"ajaxSend",[t,e])}function Zk(t,e,r,i){var n=r.context,a="success";r.success.call(n,t,a,e),i&&i.resolveWith(n,[t,a,e]),Vk(r,n,"ajaxSuccess",[e,r,t]),_k(a,e,r)}function $k(t,e,r,i,n){var a=i.context;i.error.call(a,r,e,t),n&&n.rejectWith(a,[r,e,t]),Vk(i,a,"ajaxError",[r,i,t||e]),_k(e,r,i)}function _k(t,e,r){var i=r.context;r.complete.call(i,e,t),Vk(r,i,"ajaxComplete",[e,r]),function(t){t.global&&!--Ik.active&&Vk(t,null,"ajaxStop")}(r)}function bl(){}function dl(t,e){return""==e?t:(t+"&"+e).replace(/[&?]{1,2}/,"?")}function fl(t,e,r,i){return Ik.isFunction(e)&&(i=r,r=e,e=void 0),Ik.isFunction(r)||(i=r,r=void 0),{url:t,data:e,success:r,dataType:i}}Tk.href=window.location.href,Ik.active=0,Ik.ajaxJSONP=function(r,i){if(!("type"in r))return Ik.ajax(r);function t(t){Ik(s).triggerHandler("error",t||"abort")}var n,a,e=r.jsonpCallback,o=(Ik.isFunction(e)?e():e)||"Zepto"+Jk++,s=Kk.createElement("script"),l=window[o],u={abort:t};return i&&i.promise(u),Ik(s).on("load error",function(t,e){clearTimeout(a),Ik(s).off().remove(),"error"!=t.type&&n?Zk(n[0],u,r,i):$k(null,e||"error",u,r,i),window[o]=l,n&&Ik.isFunction(l)&&l(n[0]),l=n=void 0}),!1===Yk(u,r)?t("abort"):(window[o]=function(){n=arguments},s.src=r.url.replace(/\?(.+)=\?/,"?$1="+o),Kk.head.appendChild(s),0").html(t.replace(Nk,"")).find(i):t),s&&s.apply(n,arguments)},Ik.ajax(o),this};var gl=encodeURIComponent;Ik.param=function(t,e){var r=[];return r.add=function(t,e){Ik.isFunction(e)&&(e=e()),null==e&&(e=""),this.push(gl(t)+"="+gl(e))},function r(i,t,n,a){var o,s=Ik.isArray(t),l=Ik.isPlainObject(t);Ik.each(t,function(t,e){o=Ik.type(e),a&&(t=n?a:a+"["+(l||"object"==o||"array"==o?t:"")+"]"),!a&&s?i.add(e.name,e.value):"array"==o||!n&&"object"==o?r(i,e,n,t):i.add(t,e)})}(r,t,e),r.join("&").replace(/%20/g,"+")}}(Je),(_m=Je).Callbacks=function(i){i=_m.extend({},i);var e,r,n,a,o,s,l=[],u=!i.once&&[],d=function(t){for(e=i.memory&&t,r=!0,s=a||0,a=0,o=l.length,n=!0;l&&s/,Sq="Zepto"+ +new Date,Lq.qsa=function(a,o){return Tq(o,function(t,r,i){try{var e;!t&&r?t="*":Rq.test(t)&&(e=Kq(a).addClass(Sq),t="."+Sq+" "+t);var n=Mq(a,t)}catch(t){throw console.error("error performing selector: %o",o),t}finally{e&&e.removeClass(Sq)}return r?Lq.uniq(Kq.map(n,function(t,e){return r.call(t,e,n,i)})):n})},Lq.matches=function(i,t){return Tq(t,function(t,e,r){return(!t||Nq(i,t))&&(!e||e.call(i,null,r)===i)})},He.exports=Je},function(t,e,r){"use strict";Object.defineProperty(e,"__esModule",{value:!0});function n(t){return null===t?"":(""+t).replace(o,function(t){return a[t]})}function i(a,t){var e,r=new RegExp([(l.escape||u).source,(l.interpolate||u).source,(l.evaluate||u).source].join("|")+"|$","g"),o=0,s="__p+='";a.replace(r,function(t,e,r,i,n){return s+=a.slice(o,n).replace(c,function(t){return"\\"+d[t]}),e&&(s+="'+\n((__t=("+e+"))==null?'':escapeExpr(__t))+\n'"),r&&(s+="'+\n((__t=("+r+"))==null?'':__t)+\n'"),i&&(s+="';\n"+i+"\n__p+='"),o=n+t.length,t}),s+="';\n",l.variable||(s="with(obj||{}){\n"+s+"}\n"),s="var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};\n"+s+"return __p;\n//# sourceURL=/microtemplates/source["+f+++"]";try{e=new Function(l.variable||"obj","escapeExpr",s)}catch(t){throw t.source=s,t}if(t)return e(t,n);function i(t){return e.call(this,t,n)}return i.source="function("+(l.variable||"obj")+"){\n"+s+"}",i}var l={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g},u=/(.)^/,d={"'":"'","\\":"\\","\r":"r","\n":"n","\t":"t","\u2028":"u2028","\u2029":"u2029"},c=/\\|'|\r|\n|\t|\u2028|\u2029/g,a={"&":"&","<":"<",">":">",'"':""","'":"'"},o=new RegExp("[&<>\"']","g"),f=0;i.settings=l,e.default=i,t.exports=e.default},function(t,e){t.exports=function(r){var o=[];return o.toString=function(){return this.map(function(t){var e=function(t,e){var r=t[1]||"",i=t[3];if(!i)return r;if(e&&"function"==typeof btoa){var n=function(t){return"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(t))))+" */"}(i),a=i.sources.map(function(t){return"/*# sourceURL="+i.sourceRoot+t+" */"});return[r].concat(a).concat([n]).join("\n")}return[r].join("\n")}(t,r);return t[2]?"@media "+t[2]+"{"+e+"}":e}).join("")},o.i=function(t,e){"string"==typeof t&&(t=[[null,t,""]]);for(var r={},i=0;i=e.length?{value:void 0,done:!0}:(t=i(e,r),this._i+=t.length,{value:t,done:!1})})},function(t,e){t.exports=!0},function(t,e,i){function n(){}var a=i(21),o=i(116),s=i(51),l=i(49)("IE_PROTO"),u="prototype",d=function(){var t,e=i(67)("iframe"),r=s.length;for(e.style.display="none",i(117).appendChild(e),e.src="javascript:",(t=e.contentWindow.document).open(),t.write("