diff --git a/app/assets/javascripts/admin.js b/app/assets/javascripts/admin.js index dde8bc823..0cab04359 100644 --- a/app/assets/javascripts/admin.js +++ b/app/assets/javascripts/admin.js @@ -9,6 +9,7 @@ //= require bootstrap-notify //= require jquery.cookie.min //= require select2 +//= require moment.min //= require jquery.cxselect //= require bootstrap-datepicker //= require bootstrap-datetimepicker diff --git a/app/assets/javascripts/admins/competition_settings/index.js b/app/assets/javascripts/admins/competition_settings/index.js index cd10aeb4f..fa533f1d3 100644 --- a/app/assets/javascripts/admins/competition_settings/index.js +++ b/app/assets/javascripts/admins/competition_settings/index.js @@ -9,9 +9,9 @@ $(document).on('turbolinks:load', function(){ }; var timeOptions = { - autoclose: true, + autoclose: 1, language: 'zh-CN', - format: 'yyyy-mm-dd hh:ii:ss', + format: 'yyyy-mm-dd hh:ii', minuteStep: 30 }; @@ -23,18 +23,17 @@ $(document).on('turbolinks:load', function(){ $(element).find('.end-date').datepicker('setStartDate', e.date); }); }; + $(".competition-start-end-date .start-date").datetimepicker(timeOptions); + + $(".competition-start-end-date .end-date").datetimepicker(timeOptions); + + $(".nav-setting-form .enroll_end_time").datetimepicker(timeOptions); - // var defineTimeRangeSelect = function (element) { - // var options = $.extend({inputs: $(element).find('.start-date, .end-date')}, timeOptions); - // $(element).datetimepicker(options); - // - // $(element).find('.start-date').datetimepicker().on('changeDate', function (e) { - // $(element).find('.end-date').datetimepicker('setStartDate', e.date); - // }); - // }; + $(".stage-update-form .section-start-time").datetimepicker(timeOptions); + $(".stage-update-form .section-end-time").datetimepicker(timeOptions); defineDateRangeSelect('.teaching-mode-date'); - defineDateRangeSelect('.competition-start-end-date'); + // defineTimeRangeSelect('.competition-start-end-date'); var $basicForm = $('form.basic-setting-form'); @@ -59,13 +58,13 @@ $(document).on('turbolinks:load', function(){ if ($("input[name='mode']:checked").val() == 2) { var $courseId = $("input[name='course_id'"); - if ($courseId.val() === undefined || $course_id.val().length === 0) { + if ($courseId.val() === undefined || $courseId.val().length === 0) { $courseId.addClass('danger text-danger'); valid = false; } else { $courseId.removeClass('danger text-danger'); } - } else if ($("input[name='mode']:checked").val() == 4) { + } else if ($("input[name='mode']:checked").val() == 3) { var $techStartTime = $("input[name='teach_start_time'"); var $techEndTime = $("input[name='teach_end_time'"); if ($techStartTime.val() === undefined || $techStartTime.val().length === 0) { @@ -81,6 +80,10 @@ $(document).on('turbolinks:load', function(){ } else { $techEndTime.removeClass('danger text-danger'); } + } else { + $("input[name='course_id'").removeClass('danger text-danger'); + $("input[name='teach_start_time'").removeClass('danger text-danger'); + $("input[name='teach_end_time'").removeClass('danger text-danger'); } if (!valid) return; @@ -104,97 +107,614 @@ $(document).on('turbolinks:load', function(){ } }); }); + + var selectOptions = { + theme: 'bootstrap4', + placeholder: '请输入要添加的单位名称', + multiple: true, + minimumInputLength: 1, + ajax: { + delay: 500, + url: '/api/schools/for_option.json', + dataType: 'json', + data: function(params){ + return { keyword: params.term }; + }, + processResults: function(data){ + return { results: data.schools } + } + }, + templateResult: function (item) { + if(!item.id || item.id === '') return item.text; + return item.name || item.text; + }, + templateSelection: function(item){ + return item.name || item.text; + } + }; + + $('.sponsor-select').select2(selectOptions); + $('.allow-school-select').select2(selectOptions); + + + // 排行榜 + //链接 + $(".nav-setting-form").on("click",".add_linkBtn",function () { + var length=$(".nav-setting-form").find(".linkFormItem").length + 1; + var html='
\n' + + '
\n' + + ' \n' + + '
\n' + + '
\n' + + '
\n' + + '
\n' + + '
\n' + + ' +\n' + + ' ×\n' + + '
'; + $(this).parents(".linkFormItem").after(html); + }); + + $(".nav-setting-form").on("click", ".del_linkBtn", function () { + $(this).parents(".linkFormItem").remove(); + }); + + //有关报名要求 + $(".addRequireBtn").on("click",function () { + var length=$("#requireForm").find(".requireForm_item").length + 1; + var html='
\n' + + '
  
\n' + + '
\n' + + ' \n' + + '
\n' + + ' ~\n' + + '
\n' + + ' \n' + + '
\n' + + ' \n' + + '
\n' + + ' \n' + + '
\n' + + '
\n' + + ' \n' + + '
\n' + + '
\n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + '
\n' + + '
'; + $("#requireForm").append(html); + }); + + $("#requireForm").on("click",".delRequrieBtn",function () { + $(this).parents(".requireForm_item").remove(); + }); + + $('.competition-staff-settings').on('click', '.mutiple-limited-radio', function(){ + var radio = $(this); + if (radio.is(':checked')) { + radio.parent().parent().siblings().find('.mutiple-limited-radio').attr('checked', false) + } else { + radio.parent().parent().siblings().find('.mutiple-limited-radio').attr('checked', true) + } + }); + + var $navForm = $('form.nav-setting-form'); + $navForm.on('click', ".submit-btn", function () { + $navForm.find('.submit-btn').attr('disabled', 'disabled'); + $navForm.find('.error').html(''); + var valid = $navForm.valid(); + + if (!valid) return; + $.ajax({ + method: 'POST', + dataType: 'json', + url: $navForm.attr('action'), + data: new FormData($navForm[0]), + processData: false, + contentType: false, + success: function (data) { + $.notify({message: '保存成功'}); + // window.location.reload(); + }, + error: function (res) { + var data = res.responseJSON; + $navForm.find('.error').html(data.message); + }, + complete: function () { + $navForm.find('.submit-btn').attr('disabled', false); + } + }); + }); + +// 排行榜设置 + //删除小阶段 + $("#large_panel").on("click",".small_panel_item_del",function () { + var list = $(this).parents(".small_panel"); + $(this).parents(".small_panel_item").remove(); + + for(var i=0;i < $(list).find(".subName").length;i++){ + console.log(i); + $(list).find(".subName").eq(i).html("第"+parseInt(i+1)+"阶段"); + } + }); + + // $('form.stage-update-form').validate({ + // errorElement: 'span', + // errorClass: 'danger text-danger', + // rules: { + // stage_name: "required", + // "stage[][start_time]": "required", + // "stage[][end_time]": "required", + // "stage[][mission_count]": { + // required: true, + // min: 1 + // }, + // "stage[][entry]": { + // required: true, + // min: 1 + // }, + // score_rate: { + // required: true, + // range: [0, 100] + // } + // }, + // messages: { + // "stage[][mission_count]": { + // min: ">=1" + // }, + // "stage[][entry]": { + // min: ">=1" + // }, + // } + // }); + + $('.competition-chart-setting').on('click', ".update-stage", function () { + var updateForm = $(this).parents("form"); + $(this).attr('disabled', 'disabled'); + updateForm.find('.error').html(''); + // var valid = updateForm.valid(); + var valid = true; + + var $stageName = updateForm.find('input[name="stage_name"]'); + if($stageName.val() === undefined || $stageName.val().length === 0){ + $stageName.addClass('danger text-danger'); + valid = false; + } else { + $stageName.removeClass('danger text-danger'); + } + + var $scoreRate = updateForm.find('input[name="score_rate"]'); + if($scoreRate.val() === undefined || $scoreRate.val().length === 0){ + $scoreRate.addClass('danger text-danger'); + valid = false; + } else if (parseInt($scoreRate.val()) > 100 || parseInt($scoreRate.val()) < 0) { + $scoreRate.addClass('danger text-danger'); + $scoreRate.after('0-100之间的数值'); + valid = false; + } else { + $scoreRate.removeClass('danger text-danger'); + $scoreRate.siblings().remove(); + } + + updateForm.find('input[name="stage[][start_time]"]').each(function(_, e){ + var $ele = $(e); + if($ele.val() === undefined || $ele.val().length === 0){ + $ele.addClass('danger text-danger'); + valid = false; + } else { + $ele.removeClass('danger text-danger'); + } + }); + + updateForm.find('input[name="stage[][end_time]"]').each(function(_, e){ + var $ele = $(e); + if($ele.val() === undefined || $ele.val().length === 0){ + $ele.addClass('danger text-danger'); + valid = false; + } else { + $ele.removeClass('danger text-danger'); + } + }); + + updateForm.find('input[name="stage[][mission_count]"]').each(function(i, e){ + var $ele = $(e); + var $entry = updateForm.find('input[name="stage[][entry]"]').eq(i); + if($ele.val() === undefined || $ele.val().length === 0){ + $ele.addClass('danger text-danger'); + valid = false; + } else if (parseInt($ele.val()) < 1) { + $ele.addClass('danger text-danger'); + $ele.after('大于等于1'); + valid = false; + } else if (parseInt($ele.val()) > parseInt($entry.val())) { + $ele.addClass('danger text-danger'); + $ele.after('不能大于总任务数'); + valid = false; + } else { + $ele.removeClass('danger text-danger'); + $ele.siblings().remove(); + } + }); + + updateForm.find('input[name="stage[][entry]"]').each(function(_, e){ + var $ele = $(e); + if($ele.val() === undefined || $ele.val().length === 0){ + $ele.addClass('danger text-danger'); + valid = false; + } else if (parseInt($ele.val()) < 1) { + $ele.addClass('danger text-danger'); + $ele.after('大于等于1'); + valid = false; + } else { + $ele.removeClass('danger text-danger'); + $ele.siblings().remove(); + } + }); + + updateForm.find('input[name="stage[][identifiers][]"]').each(function(_, e){ + var $ele = $(e); + if($ele.val() === undefined || $ele.val().length === 0){ + $ele.addClass('danger text-danger'); + valid = false; + } else { + $ele.removeClass('danger text-danger'); + } + }); + + if (!valid) return; + + updateForm.find('input[name="stage[][mission_count]"]').each(function(_, e){ + var $missionCount = $(e); + var $entryCount = $(e).parents("div.row").find('input[name="stage[][mission_count]"]'); + if(parseInt($missionCount.val()) > parseInt($entryCount.val()) ){ + $missionCount.addClass('danger text-danger'); + $missionCount.after('不能大于总任务数'); + valid = false; + } else { + $missionCount.removeClass('danger text-danger'); + $missionCount.siblings().remove(); + } + }); + + $.ajax({ + method: 'POST', + dataType: 'json', + url: updateForm.attr('action'), + data: new FormData(updateForm[0]), + processData: false, + contentType: false, + success: function (data) { + $.notify({message: '保存成功'}); + window.location.reload(); + }, + error: function (res) { + var data = res.responseJSON; + $navForm.find('.error').html(data.message); + }, + complete: function () { + $navForm.find('.submit-btn').attr('disabled', false); + } + }); + }); + + $(".competition-chart-stages").on("click", ".add-new-tab", function () { + if($(".new-stage-form").length > 0){ + alert("请先保存上一个tab"); + } else { + var count = parseInt($("#large_panel").find(".large_panel_part").length)+1; + var html = '
' + + '
\n' + + ' tab标题\n' + + '
\n' + + ' \n' + + '
\n' + + ' 总排行榜占比:\n' + + '
\n' + + ' \n' + + '
%\n' + + '
\n' + + ' 新增子阶段\n' + + '
\n' + + ' 删除\n' + + ' 保存\n' + + '
\n' + + '
\n' + + '
\n' + + ' 第1阶段\n' + + '
\n' + + '
\n' + + ' 有效时间:\n' + + '
\n' + + ' \n' + + '
\n' + + ' ~\n' + + '
\n' + + ' \n' + + '
\n' + + ' 任务完成要求:\n' + + '
\n' + + ' \n' + + '
\n' + + ' /\n' + + '
\n' + + ' \n' + + '
\n' + + ' (总任务)\n' + + ' 成绩来源:\n' + + '
\n' + + ' \n' + + '
\n' + + '
\n' + + '
\n' + + '
\n' + + ' 任务1\n' + + '
\n' + + ' \n' + + '
\n' + + '
\n' + + '
\n' + + ' 任务2\n' + + '
\n' + + ' \n' + + '
\n' + + '
\n' + + '
\n' + + ' 任务3\n' + + '
\n' + + ' \n' + + '
\n' + + '
\n' + + '
\n' + + '
\n' + + ' \n' + + ' 删除\n' + + ' \n' + + '
\n' + + '
'; + $("#large_panel").append(html); + + $(".stage-update-form .section-start-time").datetimepicker(timeOptions); + $(".stage-update-form .section-end-time").datetimepicker(timeOptions); + } + }); + + //新增子阶段 + $(".competition-chart-stages").on("click", ".add-task-sub", function () { + var index = $(this).parents(".large_panel_part").attr("attr_line"); + var count= 0; + + console.log("sdfsf"); + console.log($("#small_panel_"+index).find(".small_panel_item").length > 0); + + if($("#small_panel_"+index).find(".small_panel_item").length > 0){ + count = parseInt($("#small_panel_"+index).find(".small_panel_item").last().attr("count")) + 1; + + console.log($("#small_panel_"+index).find(".small_panel_item").last().attr("count")); + }else{ + count = 1; + } + + var showCount=parseInt($("#small_panel_"+index).find(".small_panel_item").length) + 1; + + + var html='
\n' + + ' 第'+showCount+'阶段\n' + + '
\n' + + '
\n' + + ' 有效时间:\n' + + '
\n' + + ' \n' + + '
\n' + + ' ~\n' + + '
\n' + + ' \n' + + '
\n' + + ' 任务完成要求:\n' + + '
\n' + + ' \n' + + '
\n' + + ' /\n' + + '
\n' + + ' \n' + + '
\n' + + ' (总任务)\n' + + ' 成绩来源:\n' + + '
\n' + + ' \n' + + '
\n' + + '
\n' + + '
\n'+ + '
\n' + + ' 任务1\n' + + '
\n' + + ' \n' + + '
\n' + + '
\n' + + '
\n' + + ' 任务2\n' + + '
\n' + + ' \n' + + '
\n' + + '
\n' + + '
\n' + + ' 任务3\n' + + '
\n' + + ' \n' + + '
\n' + + '
\n' + + '
\n' + + '
\n' + + ' \n' + + ' 删除\n' + + ' \n' + + '
'; + $("#small_panel_"+index).append(html); + + $(".stage-update-form .section-start-time").datetimepicker(timeOptions); + $(".stage-update-form .section-end-time").datetimepicker(timeOptions); + }); } }); +//添加主办方或者开放范围 +function addSponsor(item){ + var html=''; + $(item).parents(".sponsorPanel").append(html); +} +//删除 +function del_sponsor(item){ + $(item).parents(".sponsor_label").remove(); +} -$(function () { - //MD编辑 - $("#MD_typeFrom").on("click",".add_MD_type",function () { +// 小阶段修改总任务数 +function change_total(item) { + var count=parseInt($(item).val()); - var length=$(".MD_type").find(".add_MD_type").length + 1; - var html='
\n' + - '
\n' + - ' \n' + - '
\n' + - '
\n' + - '
\n' + - ' \n' + - ' \n' + - '
'; - $("#MD_typeFrom").append(html); - }) - $("#MD_typeFrom").on("click",".del_MD_type",function () { - $(this).parents(".MD_type").remove(); - }) - - - //链接 - $("#linkForm").on("click",".add_linkBtn",function () { - var length=$("#linkForm").find(".linkFormItem").length + 1; - var html='
\n' + - '
\n' + - ' \n' + - '
\n' + - '
\n' + - '
\n' + - '
\n' + - ' \n' + - ' \n' + - '
' - $("#linkForm").append(html) - }) - $("#linkForm").on("click",".del_linkBtn",function () { - $(this).parents(".lineFromItem").remove(); - }) - - //有关报名要求 - $("#addRequireBtn").on("click",function () { - var length=$("#requireForm").find(".requireForm_item").length + 1; - var html='
\n' + - '
  
\n' + - '
\n' + - ' \n' + - '
\n' + - ' ~\n' + - '
\n' + - ' \n' + - '
\n' + - ' \n' + - '
\n' + - ' \n' + - '
\n' + - '
\n' + - ' \n' + + + var index = $(item).parents(".small_panel_item").attr("attr_line"); + var indexLarge = $(item).parents(".large_panel_part").attr("attr_line"); + console.log(indexLarge); + console.log(index); + + var divCount=parseInt($("#task_Input_"+index).find(".task_Input_div").length); + + + var html = ""; + if(count > divCount){ + for(var i=0;i < count-divCount ;i++){ + html+='
任务'+(divCount+i+1)+'\n' + + '
\n' + + '\n' + + '
\n' + + '
'; + } + $("#task_Input_"+index).append(html); + }else{ + var delCount = divCount - count ; + console.log(divCount); + console.log(count); + var _max=parseInt($("#task_Input_"+index).find(".task_Input_div:last").index()); + + console.log(_max); + var _get= _max - delCount; + + console.log(_get); + if(count == 0){ + $("#task_Input_"+index).empty(); + }else{ + $("#task_Input_"+index).find(".task_Input_div:gt("+_get+")").remove(); + } + + } + +} + +//删除tab +function Del_tab(item) { + $(item).parents(".large_panel_part").remove(); +} +//新增tab +function addNewTab(competition_id) { + if($(".new-stage-form").length > 0){ + alert("请先保存上一个tab"); + } else { + var count = parseInt($("#large_panel").find(".large_panel_part").length)+1; + var html = '
' + + '
\n' + + ' tab标题\n' + + '
\n' + + ' \n' + '
\n' + - '
\n' + - ' \n' + - ' \n' + - ' \n' + - ' \n' + + ' 总排行榜占比:\n' + + '
\n' + + ' \n' + + '
%\n' + + '
\n' + + ' 新增子阶段\n' + '
\n' + - '
'; - $("#requireForm").append(html); - }) - - $("#requireForm").on("click",".delRequrieBtn",function () { - $(this).parents(".requireForm_item").remove(); - }) -}) \ No newline at end of file + ' 删除\n' + + ' 保存\n' + + '
\n' + + '
\n' + + '
\n' + + ' 第1阶段\n' + + '
\n' + + '
\n' + + ' 有效时间:\n' + + '
\n' + + ' \n' + + '
\n' + + ' ~\n' + + '
\n' + + ' \n' + + '
\n' + + ' 任务完成要求:\n' + + '
\n' + + ' \n' + + '
\n' + + ' /\n' + + '
\n' + + ' \n' + + '
\n' + + ' (总任务)\n' + + ' 成绩来源:\n' + + '
\n' + + ' \n' + + '
\n' + + '
\n' + + '
\n' + + '
\n' + + ' 任务1\n' + + '
\n' + + ' \n' + + '
\n' + + '
\n' + + '
\n' + + ' 任务2\n' + + '
\n' + + ' \n' + + '
\n' + + '
\n' + + '
\n' + + ' 任务3\n' + + '
\n' + + ' \n' + + '
\n' + + '
\n' + + '
\n' + + '
\n' + + ' \n' + + ' 删除\n' + + ' \n' + + '
\n' + + '
'; + $("#large_panel").append(html); + } +} \ No newline at end of file diff --git a/app/assets/javascripts/admins/enroll_lists/index.js b/app/assets/javascripts/admins/enroll_lists/index.js index f53b82f41..a35168d93 100644 --- a/app/assets/javascripts/admins/enroll_lists/index.js +++ b/app/assets/javascripts/admins/enroll_lists/index.js @@ -1,6 +1,6 @@ $(document).on('turbolinks:load', function() { if($('body.admins-enroll-lists-index-page').length > 0){ - let search_form = $(".search-form"); + var search_form = $(".search-form"); //导出 $(".competition-enroll-list-form").on("click","#enroll-lists-export",function () { window.location.href = "/admins/competitions/"+$(this).attr("data-competition-id")+"/enroll_lists/export.xlsx?" + search_form.serialize(); diff --git a/app/assets/javascripts/admins/laboratories/index.js b/app/assets/javascripts/admins/laboratories/index.js index abb7cb72d..689910446 100644 --- a/app/assets/javascripts/admins/laboratories/index.js +++ b/app/assets/javascripts/admins/laboratories/index.js @@ -135,7 +135,7 @@ $(document).on('turbolinks:load', function() { }, templateResult: function (item) { if(!item.id || item.id === '') return item.text; - return item.real_name; + return $("" + item.real_name + " " + item.school_name + ' ' + item.hidden_phone + ""); }, templateSelection: function(item){ if (item.id) { diff --git a/app/assets/javascripts/admins/shixuns/index.js b/app/assets/javascripts/admins/shixuns/index.js index 849e13b5b..f3e69579a 100644 --- a/app/assets/javascripts/admins/shixuns/index.js +++ b/app/assets/javascripts/admins/shixuns/index.js @@ -5,7 +5,7 @@ $(document).on('turbolinks:load', function() { allowClear: true }); - let search_form = $(".search-form"); + var search_form = $(".search-form"); //导出 $(".shixuns-list-form").on("click","#shixuns-export",function () { window.location.href = "/admins/shixuns.xls?" + search_form.serialize(); diff --git a/app/assets/javascripts/admins/users/index.js b/app/assets/javascripts/admins/users/index.js index c7b8e5e6a..8b2bb2f40 100644 --- a/app/assets/javascripts/admins/users/index.js +++ b/app/assets/javascripts/admins/users/index.js @@ -15,15 +15,19 @@ $(document).on('turbolinks:load', function(){ var $unlockAction = $lockAction.siblings('.unlock-action'); var userId = $lockAction.data('id'); - - $.ajax({ - url: '/admins/users/' + userId + '/lock', - method: 'POST', - dataType: 'json', - success: function() { - showSuccessNotify(); - $lockAction.hide(); - $unlockAction.show(); + customConfirm({ + content: '确认加锁吗?', + ok: function(){ + $.ajax({ + url: '/admins/users/' + userId + '/lock', + method: 'POST', + dataType: 'json', + success: function() { + showSuccessNotify(); + $lockAction.hide(); + $unlockAction.show(); + } + }); } }); }); @@ -34,17 +38,21 @@ $(document).on('turbolinks:load', function(){ var $lockAction = $unlockAction.siblings('.lock-action'); var userId = $unlockAction.data('id'); - - $.ajax({ - url: '/admins/users/' + userId + '/unlock', - method: 'POST', - dataType: 'json', - success: function() { - showSuccessNotify(); - $lockAction.show(); - $unlockAction.hide(); + customConfirm({ + content: '确认解锁吗?', + ok: function () { + $.ajax({ + url: '/admins/users/' + userId + '/unlock', + method: 'POST', + dataType: 'json', + success: function() { + showSuccessNotify(); + $lockAction.show(); + $unlockAction.hide(); + } + }); } - }); + }) }); // active user @@ -54,18 +62,22 @@ $(document).on('turbolinks:load', function(){ var $lockAction = $activeAction.siblings('.lock-action'); var userId = $activeAction.data('id'); - - $.ajax({ - url: '/admins/users/' + userId + '/unlock', - method: 'POST', - dataType: 'json', - success: function() { - showSuccessNotify(); - $activeAction.hide(); - $lockAction.show(); - $unlockAction.hide(); + customConfirm({ + content: '确认激活吗?', + ok: function () { + $.ajax({ + url: '/admins/users/' + userId + '/unlock', + method: 'POST', + dataType: 'json', + success: function() { + showSuccessNotify(); + $activeAction.hide(); + $lockAction.show(); + $unlockAction.hide(); + } + }); } - }); + }) }); // ***************** reward grade modal ***************** diff --git a/app/assets/javascripts/bootstrap-datetimepicker.js b/app/assets/javascripts/bootstrap-datetimepicker.js index 8838cbcd2..f66d69c13 100755 --- a/app/assets/javascripts/bootstrap-datetimepicker.js +++ b/app/assets/javascripts/bootstrap-datetimepicker.js @@ -1,2636 +1,1967 @@ -/*! version : 4.17.47 - ========================================================= - bootstrap-datetimejs - https://github.com/Eonasdan/bootstrap-datetimepicker - Copyright (c) 2015 Jonathan Peterson - ========================================================= - */ -/* - The MIT License (MIT) - - Copyright (c) 2015 Jonathan Peterson - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - */ -/*global define:false */ -/*global exports:false */ -/*global require:false */ -/*global jQuery:false */ -/*global moment:false */ -(function (factory) { - 'use strict'; - if (typeof define === 'function' && define.amd) { - // AMD is used - Register as an anonymous module. - define(['jquery', 'moment'], factory); - } else if (typeof exports === 'object') { - module.exports = factory(require('jquery'), require('moment')); - } else { - // Neither AMD nor CommonJS used. Use global variables. - if (typeof jQuery === 'undefined') { - throw 'bootstrap-datetimepicker requires jQuery to be loaded first'; +/* ========================================================= + * bootstrap-datetimepicker.js + * ========================================================= + * Copyright 2012 Stefan Petre + * + * Improvements by Andrew Rowls + * Improvements by Sébastien Malot + * Improvements by Yun Lai + * Improvements by Kenneth Henderick + * Improvements by CuGBabyBeaR + * Improvements by Christian Vaas + * + * Project URL : http://www.malot.fr/bootstrap-datetimepicker + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ========================================================= */ + +(function(factory){ + if (typeof define === 'function' && define.amd) + define(['jquery'], factory); + else if (typeof exports === 'object') + factory(require('jquery')); + else + factory(jQuery); + +}(function($, undefined){ + + // Add ECMA262-5 Array methods if not supported natively (IE8) + if (!('indexOf' in Array.prototype)) { + Array.prototype.indexOf = function (find, i) { + if (i === undefined) i = 0; + if (i < 0) i += this.length; + if (i < 0) i = 0; + for (var n = this.length; i < n; i++) { + if (i in this && this[i] === find) { + return i; } - if (typeof moment === 'undefined') { - throw 'bootstrap-datetimepicker requires Moment.js to be loaded first'; + } + return -1; + } + } + + // Add timezone abbreviation support for ie6+, Chrome, Firefox + function timeZoneAbbreviation() { + var abbreviation, date, formattedStr, i, len, matchedStrings, ref, str; + date = (new Date()).toString(); + formattedStr = ((ref = date.split('(')[1]) != null ? ref.slice(0, -1) : 0) || date.split(' '); + if (formattedStr instanceof Array) { + matchedStrings = []; + for (var i = 0, len = formattedStr.length; i < len; i++) { + str = formattedStr[i]; + if ((abbreviation = (ref = str.match(/\b[A-Z]+\b/)) !== null) ? ref[0] : 0) { + matchedStrings.push(abbreviation); } - factory(jQuery, moment); + } + formattedStr = matchedStrings.pop(); } -}(function ($, moment) { - 'use strict'; - if (!moment) { - throw new Error('bootstrap-datetimepicker requires Moment.js to be loaded first'); + return formattedStr; + } + + function UTCDate() { + return new Date(Date.UTC.apply(Date, arguments)); + } + + // Picker object + var Datetimepicker = function (element, options) { + var that = this; + + this.element = $(element); + + // add container for single page application + // when page switch the datetimepicker div will be removed also. + this.container = options.container || 'body'; + + this.language = options.language || this.element.data('date-language') || 'en'; + this.language = this.language in dates ? this.language : this.language.split('-')[0]; // fr-CA fallback to fr + this.language = this.language in dates ? this.language : 'en'; + this.isRTL = dates[this.language].rtl || false; + this.formatType = options.formatType || this.element.data('format-type') || 'standard'; + this.format = DPGlobal.parseFormat(options.format || this.element.data('date-format') || dates[this.language].format || DPGlobal.getDefaultFormat(this.formatType, 'input'), this.formatType); + this.isInline = false; + this.isVisible = false; + this.isInput = this.element.is('input'); + this.fontAwesome = options.fontAwesome || this.element.data('font-awesome') || false; + + this.bootcssVer = options.bootcssVer || (this.isInput ? (this.element.is('.form-control') ? 3 : 2) : ( this.bootcssVer = this.element.is('.input-group') ? 3 : 2 )); + + this.component = this.element.is('.date') ? ( this.bootcssVer === 3 ? this.element.find('.input-group-addon .glyphicon-th, .input-group-addon .glyphicon-time, .input-group-addon .glyphicon-remove, .input-group-addon .glyphicon-calendar, .input-group-addon .fa-calendar, .input-group-addon .fa-clock-o').parent() : this.element.find('.add-on .icon-th, .add-on .icon-time, .add-on .icon-calendar, .add-on .fa-calendar, .add-on .fa-clock-o').parent()) : false; + this.componentReset = this.element.is('.date') ? ( this.bootcssVer === 3 ? this.element.find('.input-group-addon .glyphicon-remove, .input-group-addon .fa-times').parent():this.element.find('.add-on .icon-remove, .add-on .fa-times').parent()) : false; + this.hasInput = this.component && this.element.find('input').length; + if (this.component && this.component.length === 0) { + this.component = false; } + this.linkField = options.linkField || this.element.data('link-field') || false; + this.linkFormat = DPGlobal.parseFormat(options.linkFormat || this.element.data('link-format') || DPGlobal.getDefaultFormat(this.formatType, 'link'), this.formatType); + this.minuteStep = options.minuteStep || this.element.data('minute-step') || 5; + this.pickerPosition = options.pickerPosition || this.element.data('picker-position') || 'bottom-right'; + this.showMeridian = options.showMeridian || this.element.data('show-meridian') || false; + this.initialDate = options.initialDate || new Date(); + this.zIndex = options.zIndex || this.element.data('z-index') || undefined; + this.title = typeof options.title === 'undefined' ? false : options.title; + this.timezone = options.timezone || timeZoneAbbreviation(); + + this.icons = { + leftArrow: this.fontAwesome ? 'fa-arrow-left' : (this.bootcssVer === 3 ? 'glyphicon-arrow-left' : 'icon-arrow-left'), + rightArrow: this.fontAwesome ? 'fa-arrow-right' : (this.bootcssVer === 3 ? 'glyphicon-arrow-right' : 'icon-arrow-right') + } + this.icontype = this.fontAwesome ? 'fa' : 'glyphicon'; - var dateTimePicker = function (element, options) { - var picker = {}, - date, - viewDate, - unset = true, - input, - component = false, - widget = false, - use24Hours, - minViewModeNumber = 0, - actualFormat, - parseFormats, - currentViewMode, - datePickerModes = [ - { - clsName: 'days', - navFnc: 'M', - navStep: 1 - }, - { - clsName: 'months', - navFnc: 'y', - navStep: 1 - }, - { - clsName: 'years', - navFnc: 'y', - navStep: 10 - }, - { - clsName: 'decades', - navFnc: 'y', - navStep: 100 - } - ], - viewModes = ['days', 'months', 'years', 'decades'], - verticalModes = ['top', 'bottom', 'auto'], - horizontalModes = ['left', 'right', 'auto'], - toolbarPlacements = ['default', 'top', 'bottom'], - keyMap = { - 'up': 38, - 38: 'up', - 'down': 40, - 40: 'down', - 'left': 37, - 37: 'left', - 'right': 39, - 39: 'right', - 'tab': 9, - 9: 'tab', - 'escape': 27, - 27: 'escape', - 'enter': 13, - 13: 'enter', - 'pageUp': 33, - 33: 'pageUp', - 'pageDown': 34, - 34: 'pageDown', - 'shift': 16, - 16: 'shift', - 'control': 17, - 17: 'control', - 'space': 32, - 32: 'space', - 't': 84, - 84: 't', - 'delete': 46, - 46: 'delete' - }, - keyState = {}, - - /******************************************************************************** - * - * Private functions - * - ********************************************************************************/ - - hasTimeZone = function () { - return moment.tz !== undefined && options.timeZone !== undefined && options.timeZone !== null && options.timeZone !== ''; - }, - - getMoment = function (d) { - var returnMoment; - - if (d === undefined || d === null) { - returnMoment = moment(); //TODO should this use format? and locale? - } else if (moment.isDate(d) || moment.isMoment(d)) { - // If the date that is passed in is already a Date() or moment() object, - // pass it directly to moment. - returnMoment = moment(d); - } else if (hasTimeZone()) { // There is a string to parse and a default time zone - // parse with the tz function which takes a default time zone if it is not in the format string - returnMoment = moment.tz(d, parseFormats, options.useStrict, options.timeZone); - } else { - returnMoment = moment(d, parseFormats, options.useStrict); - } - - if (hasTimeZone()) { - returnMoment.tz(options.timeZone); - } - - return returnMoment; - }, - - isEnabled = function (granularity) { - if (typeof granularity !== 'string' || granularity.length > 1) { - throw new TypeError('isEnabled expects a single character string parameter'); - } - switch (granularity) { - case 'y': - return actualFormat.indexOf('Y') !== -1; - case 'M': - return actualFormat.indexOf('M') !== -1; - case 'd': - return actualFormat.toLowerCase().indexOf('d') !== -1; - case 'h': - case 'H': - return actualFormat.toLowerCase().indexOf('h') !== -1; - case 'm': - return actualFormat.indexOf('m') !== -1; - case 's': - return actualFormat.indexOf('s') !== -1; - default: - return false; - } - }, - - hasTime = function () { - return (isEnabled('h') || isEnabled('m') || isEnabled('s')); - }, - - hasDate = function () { - return (isEnabled('y') || isEnabled('M') || isEnabled('d')); - }, - - getDatePickerTemplate = function () { - var headTemplate = $('') - .append($('') - .append($('').addClass('prev').attr('data-action', 'previous') - .append($('').addClass(options.icons.previous)) - ) - .append($('').addClass('picker-switch').attr('data-action', 'pickerSwitch').attr('colspan', (options.calendarWeeks ? '6' : '5'))) - .append($('').addClass('next').attr('data-action', 'next') - .append($('').addClass(options.icons.next)) - ) - ), - contTemplate = $('') - .append($('') - .append($('').attr('colspan', (options.calendarWeeks ? '8' : '7'))) - ); - - return [ - $('
').addClass('datepicker-days') - .append($('').addClass('table-condensed') - .append(headTemplate) - .append($('')) - ), - $('
').addClass('datepicker-months') - .append($('
').addClass('table-condensed') - .append(headTemplate.clone()) - .append(contTemplate.clone()) - ), - $('
').addClass('datepicker-years') - .append($('
').addClass('table-condensed') - .append(headTemplate.clone()) - .append(contTemplate.clone()) - ), - $('
').addClass('datepicker-decades') - .append($('
').addClass('table-condensed') - .append(headTemplate.clone()) - .append(contTemplate.clone()) - ) - ]; - }, - - getTimePickerMainTemplate = function () { - var topRow = $(''), - middleRow = $(''), - bottomRow = $(''); - - if (isEnabled('h')) { - topRow.append($('
') - .append($('').attr({ href: '#', tabindex: '-1', 'title': options.tooltips.incrementHour }).addClass('btn').attr('data-action', 'incrementHours').append($('').addClass(options.icons.up)))); - middleRow.append($('') - .append($('').addClass('timepicker-hour').attr({ 'data-time-component': 'hours', 'title': options.tooltips.pickHour }).attr('data-action', 'showHours'))); - bottomRow.append($('') - .append($('').attr({ href: '#', tabindex: '-1', 'title': options.tooltips.decrementHour }).addClass('btn').attr('data-action', 'decrementHours').append($('').addClass(options.icons.down)))); - } - if (isEnabled('m')) { - if (isEnabled('h')) { - topRow.append($('').addClass('separator')); - middleRow.append($('').addClass('separator').html(':')); - bottomRow.append($('').addClass('separator')); - } - topRow.append($('') - .append($('').attr({ href: '#', tabindex: '-1', 'title': options.tooltips.incrementMinute }).addClass('btn').attr('data-action', 'incrementMinutes') - .append($('').addClass(options.icons.up)))); - middleRow.append($('') - .append($('').addClass('timepicker-minute').attr({ 'data-time-component': 'minutes', 'title': options.tooltips.pickMinute }).attr('data-action', 'showMinutes'))); - bottomRow.append($('') - .append($('').attr({ href: '#', tabindex: '-1', 'title': options.tooltips.decrementMinute }).addClass('btn').attr('data-action', 'decrementMinutes') - .append($('').addClass(options.icons.down)))); - } - if (isEnabled('s')) { - if (isEnabled('m')) { - topRow.append($('').addClass('separator')); - middleRow.append($('').addClass('separator').html(':')); - bottomRow.append($('').addClass('separator')); - } - topRow.append($('') - .append($('').attr({ href: '#', tabindex: '-1', 'title': options.tooltips.incrementSecond }).addClass('btn').attr('data-action', 'incrementSeconds') - .append($('').addClass(options.icons.up)))); - middleRow.append($('') - .append($('').addClass('timepicker-second').attr({ 'data-time-component': 'seconds', 'title': options.tooltips.pickSecond }).attr('data-action', 'showSeconds'))); - bottomRow.append($('') - .append($('').attr({ href: '#', tabindex: '-1', 'title': options.tooltips.decrementSecond }).addClass('btn').attr('data-action', 'decrementSeconds') - .append($('').addClass(options.icons.down)))); - } - - if (!use24Hours) { - topRow.append($('').addClass('separator')); - middleRow.append($('') - .append($('').addClass('separator')); - } - - return $('
').addClass('timepicker-picker') - .append($('').addClass('table-condensed') - .append([topRow, middleRow, bottomRow])); - }, - - getTimePickerTemplate = function () { - var hoursView = $('
').addClass('timepicker-hours') - .append($('
').addClass('table-condensed')), - minutesView = $('
').addClass('timepicker-minutes') - .append($('
').addClass('table-condensed')), - secondsView = $('
').addClass('timepicker-seconds') - .append($('
').addClass('table-condensed')), - ret = [getTimePickerMainTemplate()]; - - if (isEnabled('h')) { - ret.push(hoursView); - } - if (isEnabled('m')) { - ret.push(minutesView); - } - if (isEnabled('s')) { - ret.push(secondsView); - } + this._attachEvents(); - return ret; - }, + this.clickedOutside = function (e) { + // Clicked outside the datetimepicker, hide it + if ($(e.target).closest('.datetimepicker').length === 0) { + that.hide(); + } + } - getToolbar = function () { - var row = []; - if (options.showTodayButton) { - row.push($(' + - + @@ -24,6 +25,7 @@ + @@ -33,14 +35,14 @@ <%= javascript_void_link('奖励', class: 'action reward-grade-action', data: { toggle: 'modal', target: '.admin-users-reward-grade-modal', id: user.id }) %> - <%= javascript_void_link '解锁', class: 'action unlock-action', data: { id: user.id, confirm: '确认解锁吗?' }, style: user.locked? ? '' : 'display: none;' %> + <%= javascript_void_link '解锁', class: 'action unlock-action', data: { id: user.id }, style: user.locked? ? '' : 'display: none;' %> <% if user.registered? %> - <%= javascript_void_link '激活', class: 'action active-action', data: { id: user.id, confirm: '确认激活吗?' } %> + <%= javascript_void_link '激活', class: 'action active-action', data: { id: user.id } %> <% end %> <% if user.id != current_user.id %> - <%= javascript_void_link '加锁', class: 'action lock-action', data: { id: user.id, confirm: '确认加锁吗?' }, style: user.locked? || user.registered? ? 'display: none;' : '' %> + <%= javascript_void_link '加锁', class: 'action lock-action', data: { id: user.id }, style: user.locked? || user.registered? ? 'display: none;' : '' %> <% end %> <%= delete_link '删除', admins_user_path(user, element: ".user-item-#{user.id}"), class: 'delete-user-action' %> diff --git a/app/views/competitions/competition_modules/show.json.jbuilder b/app/views/competitions/competition_modules/show.json.jbuilder index 69cdcc544..14c3c0f57 100644 --- a/app/views/competitions/competition_modules/show.json.jbuilder +++ b/app/views/competitions/competition_modules/show.json.jbuilder @@ -1,9 +1,11 @@ -json.extract! @module, :id, :name, :position, :url, :md_edit +json.extract! @module, :id, :name, :position, :url -md = @module.competition_module_md_content +md = @module.competition_module_md_contents.take if md.present? + json.md_id md.id json.md_name md.name json.md_content md.content + json.competition_stage_id md.competition_stage_id json.created_at md.created_at.strftime('%Y-%m-%d %H:%M:%S') json.attachments do json.array! md.attachments, partial: 'attachments/attachment_simple', as: :attachment diff --git a/app/views/competitions/competition_teams/index.json.jbuilder b/app/views/competitions/competition_teams/index.json.jbuilder index 70651b4ae..f1f01b76a 100644 --- a/app/views/competitions/competition_teams/index.json.jbuilder +++ b/app/views/competitions/competition_teams/index.json.jbuilder @@ -1,5 +1,7 @@ json.count @all_count +json.members_count @all_member_count json.personal @personal +json.competition_name @competition.name json.competition_teams do json.array! @all_teams&.each do |team| json.extract! team, :id, :name, :invite_code diff --git a/app/views/competitions/competitions/common_header.json.jbuilder b/app/views/competitions/competitions/common_header.json.jbuilder index 0ecf6cfd5..2a1e0a92d 100644 --- a/app/views/competitions/competitions/common_header.json.jbuilder +++ b/app/views/competitions/competitions/common_header.json.jbuilder @@ -21,6 +21,7 @@ json.stages if @competition.mode == 2 json.course_id @competition.competition_mode_setting&.course_id + json.invite_code @competition.competition_mode_setting&.course&.invite_code json.member_of_course @user.member_of_course?(@competition.competition_mode_setting&.course) end diff --git a/app/views/cooperative/users/index.json.jbuilder b/app/views/cooperative/users/index.json.jbuilder index 5591474a4..5b1860928 100644 --- a/app/views/cooperative/users/index.json.jbuilder +++ b/app/views/cooperative/users/index.json.jbuilder @@ -1,6 +1,6 @@ json.count @users.total_count json.users do json.array! @users.each do |user| - json.extract! user, :id, :login, :real_name, :identity, :school_name + json.extract! user, :id, :login, :real_name, :identity, :school_name, :hidden_phone end end \ No newline at end of file diff --git a/config/locales/forms/save_team_form.zh-CN.yml b/config/locales/forms/save_team_form.zh-CN.yml index 106527687..7fc146d36 100644 --- a/config/locales/forms/save_team_form.zh-CN.yml +++ b/config/locales/forms/save_team_form.zh-CN.yml @@ -12,14 +12,15 @@ competitions/save_team_form: attributes: creator: + enrolled: "您已经报名过该竞赛了" teacher_enroll_forbidden: "本竞赛的参赛者限定为:学生" member_enroll_forbidden: "本竞赛的参赛者限定为:教师" teacher_ids: enroll_forbidden: "本竞赛的参赛者限定为:学生" invalid_count: "教师数量应为%{minimum}~%{maximum}人" - enrolled: "教师 ${names} 已加入其它战队了" + enrolled: "教师 %{names} 已加入其它战队了" member_ids: enroll_forbidden: "本竞赛的参赛者限定为:教师" invalid_count: "队员数量应为%{minimum}~%{maximum}人" - enrolled: "队员 ${names} 已加入其它战队了" + enrolled: "队员 %{names} 已加入其它战队了" diff --git a/config/routes.rb b/config/routes.rb index 80e1298cc..43ec58fba 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -852,6 +852,7 @@ Rails.application.routes.draw do resource :home, only: [:show] resource :session, only: [:create] resource :register, only: [:create] + resource :verification_code, only: [:create] resource :code_session, only: [:create] resource :verify, only: [:create] resource :check_account, only: [:create] @@ -1025,6 +1026,7 @@ Rails.application.routes.draw do resources :competition_settings, only: [:index] do post :basic_setting, on: :collection + post :nav_setting, on: :collection end resources :enroll_lists, only: [:index] do @@ -1032,10 +1034,9 @@ Rails.application.routes.draw do end resources :competition_stages, only: [:create, :update, :destroy] do - collection do - post :create_stage_section - post :update_stage_section - delete :destroy_stage_section + member do + post :send_message + post :calculate_stage_score end end end diff --git a/db/migrate/20191023074837_migrate_competition_module_type.rb b/db/migrate/20191023074837_migrate_competition_module_type.rb index 009b65cc9..c98c5797d 100644 --- a/db/migrate/20191023074837_migrate_competition_module_type.rb +++ b/db/migrate/20191023074837_migrate_competition_module_type.rb @@ -16,7 +16,7 @@ class MigrateCompetitionModuleType < ActiveRecord::Migration[5.2] mod_type = "manual" when '排行榜' mod_type = "chart" - when '资料下载 ' + when '资料下载' mod_type = "resource" else mod_type = "md" diff --git a/db/migrate/20191023103633_add_column_to_stage_sections.rb b/db/migrate/20191023103633_add_column_to_stage_sections.rb deleted file mode 100644 index baa1754fa..000000000 --- a/db/migrate/20191023103633_add_column_to_stage_sections.rb +++ /dev/null @@ -1,10 +0,0 @@ -class AddColumnToStageSections < ActiveRecord::Migration[5.2] - def change - def change - add_column :competition_stage_sections, :mission_count, :integer, default: 0 - add_column :competition_stage_sections, :score_source, :integer, default: 0 - - add_column :competition_entries, :shixun_identifier, :string - end - end -end diff --git a/db/migrate/20191024055404_migrate_com_module_resource.rb b/db/migrate/20191024055404_migrate_com_module_resource.rb new file mode 100644 index 000000000..f8625b2bc --- /dev/null +++ b/db/migrate/20191024055404_migrate_com_module_resource.rb @@ -0,0 +1,26 @@ +class MigrateComModuleResource < ActiveRecord::Migration[5.2] + def change + Competition.all.each do |competition| + competition.competition_modules.each do |com_module| + mod_type = "" + case com_module.name.strip + when '首页' + mod_type = "home" + when '报名' + mod_type = "enroll" + when '通知公告' + mod_type = "inform" + when '参赛手册' + mod_type = "manual" + when '排行榜' + mod_type = "chart" + when '资料下载' + mod_type = "resource" + else + mod_type = "md" + end + com_module.update_attributes!(module_type: mod_type) + end + end + end +end diff --git a/db/migrate/20191024075134_migrate_competition_module_manual.rb b/db/migrate/20191024075134_migrate_competition_module_manual.rb new file mode 100644 index 000000000..3a2f16cff --- /dev/null +++ b/db/migrate/20191024075134_migrate_competition_module_manual.rb @@ -0,0 +1,5 @@ +class MigrateCompetitionModuleManual < ActiveRecord::Migration[5.2] + def change + CompetitionModule.where(module_type: "manual").update_all(module_type: "md") + end +end diff --git a/db/migrate/20191024083706_migrate_competition_module_content.rb b/db/migrate/20191024083706_migrate_competition_module_content.rb new file mode 100644 index 000000000..72d023a38 --- /dev/null +++ b/db/migrate/20191024083706_migrate_competition_module_content.rb @@ -0,0 +1,17 @@ +class MigrateCompetitionModuleContent < ActiveRecord::Migration[5.2] + def change + Competition.all.each do |competition| + competition.informs.each do |inform| + if inform.status == 1 + com_module = competition.competition_modules.find_by(module_type: "inform") + elsif inform.status == 2 + com_module = competition.competition_modules.find_by(name: "参赛手册") + end + if com_module + new_md = CompetitionModuleMdContent.create!(competition_module_id: com_module.id, content: inform.description, name: inform.name) + Attachment.where(container_id: inform.id, container_type: "Inform").update_all(container_id: new_md.id, container_type: "CompetitionModuleMdContent") + end + end + end + end +end diff --git a/db/migrate/20191024090740_migrate_competition_chart_rules.rb b/db/migrate/20191024090740_migrate_competition_chart_rules.rb new file mode 100644 index 000000000..ed1dd56e9 --- /dev/null +++ b/db/migrate/20191024090740_migrate_competition_chart_rules.rb @@ -0,0 +1,14 @@ +class MigrateCompetitionChartRules < ActiveRecord::Migration[5.2] + def change + add_column :competition_module_md_contents, :competition_stage_id, :integer, default: 0 + + ChartRule.all.each do |rule| + if rule.competition + com_module = rule.competition.competition_modules.find_by(module_type: "chart") + if com_module + CompetitionModuleMdContent.create!(content: rule.content, competition_module_id: com_module.id, competition_stage_id: rule.competition_stage_id ? rule.competition_stage_id : 0) + end + end + end + end +end diff --git a/db/migrate/20191024105504_create_competition_schools.rb b/db/migrate/20191024105504_create_competition_schools.rb new file mode 100644 index 000000000..27a425abc --- /dev/null +++ b/db/migrate/20191024105504_create_competition_schools.rb @@ -0,0 +1,11 @@ +class CreateCompetitionSchools < ActiveRecord::Migration[5.2] + def change + create_table :competition_schools do |t| + t.references :competition, index: true + t.references :school, index: true + t.string :source + + t.timestamps + end + end +end diff --git a/db/migrate/20191025012950_add_column_to_stage_sections.rb b/db/migrate/20191025012950_add_column_to_stage_sections.rb new file mode 100644 index 000000000..5eb96aea9 --- /dev/null +++ b/db/migrate/20191025012950_add_column_to_stage_sections.rb @@ -0,0 +1,8 @@ +class AddColumnToStageSections < ActiveRecord::Migration[5.2] + def change + add_column :competition_stage_sections, :mission_count, :integer, default: 0 + add_column :competition_stage_sections, :score_source, :integer, default: 0 + + add_column :competition_entries, :shixun_identifier, :string + end +end diff --git a/public/assets/.sprockets-manifest-4627fa5586ef7fed55ca286af7c028e9.json b/public/assets/.sprockets-manifest-4627fa5586ef7fed55ca286af7c028e9.json index 2404fbf37..4ff1f742a 100644 --- a/public/assets/.sprockets-manifest-4627fa5586ef7fed55ca286af7c028e9.json +++ b/public/assets/.sprockets-manifest-4627fa5586ef7fed55ca286af7c028e9.json @@ -1 +1 @@ -{"files":{"admin-cd9ca8bacc973ce2dbace30c97f6c40bc08e2c2ee44972f668e738e1902c0121.js":{"logical_path":"admin.js","mtime":"2019-09-11T16:20:07+08:00","size":4350881,"digest":"cd9ca8bacc973ce2dbace30c97f6c40bc08e2c2ee44972f668e738e1902c0121","integrity":"sha256-zZyousyXPOLbrOMMl/bEC8COLC7kSXL2aOc44ZAsASE="},"admin-a1b3356efe50ff4717cf22475639b5333c5354ba03fd107c9b7a8d4ae76f47aa.css":{"logical_path":"admin.css","mtime":"2019-09-11T16:20:07+08:00","size":773445,"digest":"a1b3356efe50ff4717cf22475639b5333c5354ba03fd107c9b7a8d4ae76f47aa","integrity":"sha256-obM1bv5Q/0cXzyJHVjm1MzxTVLoD/RB8m3qNSudvR6o="},"font-awesome/fontawesome-webfont-7bfcab6db99d5cfbf1705ca0536ddc78585432cc5fa41bbd7ad0f009033b2979.eot":{"logical_path":"font-awesome/fontawesome-webfont.eot","mtime":"2019-08-14T17:22:43+08:00","size":165742,"digest":"7bfcab6db99d5cfbf1705ca0536ddc78585432cc5fa41bbd7ad0f009033b2979","integrity":"sha256-e/yrbbmdXPvxcFygU23ceFhUMsxfpBu9etDwCQM7KXk="},"font-awesome/fontawesome-webfont-2adefcbc041e7d18fcf2d417879dc5a09997aa64d675b7a3c4b6ce33da13f3fe.woff2":{"logical_path":"font-awesome/fontawesome-webfont.woff2","mtime":"2019-08-14T17:22:43+08:00","size":77160,"digest":"2adefcbc041e7d18fcf2d417879dc5a09997aa64d675b7a3c4b6ce33da13f3fe","integrity":"sha256-Kt78vAQefRj88tQXh53FoJmXqmTWdbejxLbOM9oT8/4="},"font-awesome/fontawesome-webfont-ba0c59deb5450f5cb41b3f93609ee2d0d995415877ddfa223e8a8a7533474f07.woff":{"logical_path":"font-awesome/fontawesome-webfont.woff","mtime":"2019-08-14T17:22:43+08:00","size":98024,"digest":"ba0c59deb5450f5cb41b3f93609ee2d0d995415877ddfa223e8a8a7533474f07","integrity":"sha256-ugxZ3rVFD1y0Gz+TYJ7i0NmVQVh33foiPoqKdTNHTwc="},"font-awesome/fontawesome-webfont-aa58f33f239a0fb02f5c7a6c45c043d7a9ac9a093335806694ecd6d4edc0d6a8.ttf":{"logical_path":"font-awesome/fontawesome-webfont.ttf","mtime":"2019-08-14T17:22:43+08:00","size":165548,"digest":"aa58f33f239a0fb02f5c7a6c45c043d7a9ac9a093335806694ecd6d4edc0d6a8","integrity":"sha256-qljzPyOaD7AvXHpsRcBD16msmgkzNYBmlOzW1O3A1qg="},"font-awesome/fontawesome-webfont-ad6157926c1622ba4e1d03d478f1541368524bfc46f51e42fe0d945f7ef323e4.svg":{"logical_path":"font-awesome/fontawesome-webfont.svg","mtime":"2019-08-14T17:22:43+08:00","size":444379,"digest":"ad6157926c1622ba4e1d03d478f1541368524bfc46f51e42fe0d945f7ef323e4","integrity":"sha256-rWFXkmwWIrpOHQPUePFUE2hSS/xG9R5C/g2UX37zI+Q="},"college-18f5e8400331634e898a35acc2187815c096c25e0ab74aba341ae916166cd287.js":{"logical_path":"college.js","mtime":"2019-10-17T09:44:58+08:00","size":3352744,"digest":"18f5e8400331634e898a35acc2187815c096c25e0ab74aba341ae916166cd287","integrity":"sha256-GPXoQAMxY06JijWswhh4FcCWwl4Kt0q6NBrpFhZs0oc="},"college-944d4273f62c7538368b9017fdd3387b5e3bea31a87873770eb231324546d4d9.css":{"logical_path":"college.css","mtime":"2019-09-11T16:20:07+08:00","size":546841,"digest":"944d4273f62c7538368b9017fdd3387b5e3bea31a87873770eb231324546d4d9","integrity":"sha256-lE1Cc/YsdTg2i5AX/dM4e1476jGoeHN3DrIxMkVG1Nk="},"logo-7ff112568709bf97f9898fe87249b7a8f200ff1f48d537d85af87215f1870423.png":{"logical_path":"logo.png","mtime":"2019-09-03T08:55:53+08:00","size":2816,"digest":"7ff112568709bf97f9898fe87249b7a8f200ff1f48d537d85af87215f1870423","integrity":"sha256-f/ESVocJv5f5iY/ockm3qPIA/x9I1TfYWvhyFfGHBCM="},"application-9cfbc3d792599a1d0de5c7b84209e1c2b2e60336f0f01e19f0581663918708fb.js":{"logical_path":"application.js","mtime":"2019-10-17T09:44:58+08:00","size":600706,"digest":"9cfbc3d792599a1d0de5c7b84209e1c2b2e60336f0f01e19f0581663918708fb","integrity":"sha256-nPvD15JZmh0N5ce4QgnhwrLmAzbw8B4Z8FgWY5GHCPs="},"application-5eb87c6e13676d0183317debce17fade27e68c4acee28c419438da15d53c94f2.css":{"logical_path":"application.css","mtime":"2019-09-11T16:20:07+08:00","size":1844002,"digest":"5eb87c6e13676d0183317debce17fade27e68c4acee28c419438da15d53c94f2","integrity":"sha256-Xrh8bhNnbQGDMX3rzhf63ifmjErO4oxBlDjaFdU8lPI="},"admin-c9e5ebe6191548550e27514196ea125cfbb402820ec125a0c9acf99d2d378fe4.js":{"logical_path":"admin.js","mtime":"2019-09-21T15:28:08+08:00","size":4382031,"digest":"c9e5ebe6191548550e27514196ea125cfbb402820ec125a0c9acf99d2d378fe4","integrity":"sha256-yeXr5hkVSFUOJ1FBluoSXPu0AoIOwSWgyaz5nS03j+Q="},"admin-59c59f8cae8bef4a8359286c985458110c9d03ea121516595c988943f4717c38.css":{"logical_path":"admin.css","mtime":"2019-09-21T14:49:04+08:00","size":840093,"digest":"59c59f8cae8bef4a8359286c985458110c9d03ea121516595c988943f4717c38","integrity":"sha256-WcWfjK6L70qDWShsmFRYEQydA+oSFRZZXJiJQ/RxfDg="},"college-38f953d6ba5b85d3fab63cb3c2bbf0d057ccc6454d07cfaafac3b06da37b8437.css":{"logical_path":"college.css","mtime":"2019-09-16T13:56:09+08:00","size":579109,"digest":"38f953d6ba5b85d3fab63cb3c2bbf0d057ccc6454d07cfaafac3b06da37b8437","integrity":"sha256-OPlT1rpbhdP6tjyzwrvw0FfMxkVNB8+q+sOwbaN7hDc="},"application-646b1158a4e8c1f13e684d6fe9025abc75f8d3ba5256e440802c0398223374f3.css":{"logical_path":"application.css","mtime":"2019-09-21T14:49:04+08:00","size":1988767,"digest":"646b1158a4e8c1f13e684d6fe9025abc75f8d3ba5256e440802c0398223374f3","integrity":"sha256-ZGsRWKTowfE+aE1v6QJavHX407pSVuRAgCwDmCIzdPM="},"admin-a47e37c0ec7cf5f22380249776d1e82d65b6b6aa272ed7389185aa200fa40751.js":{"logical_path":"admin.js","mtime":"2019-09-25T15:33:05+08:00","size":4383107,"digest":"a47e37c0ec7cf5f22380249776d1e82d65b6b6aa272ed7389185aa200fa40751","integrity":"sha256-pH43wOx89fIjgCSXdtHoLWW2tqonLtc4kYWqIA+kB1E="},"admin-432c4eac09b036c57ff1e88d902b8aa7df81164e4b419bac557cf1366c1d3ad9.js":{"logical_path":"admin.js","mtime":"2019-09-25T15:35:20+08:00","size":4383103,"digest":"432c4eac09b036c57ff1e88d902b8aa7df81164e4b419bac557cf1366c1d3ad9","integrity":"sha256-QyxOrAmwNsV/8eiNkCuKp9+BFk5LQZusVXzxNmwdOtk="},"admin-978e5ce607f77c26814a174f480da79ac246c2201868ef84654aa03bb6727b5a.js":{"logical_path":"admin.js","mtime":"2019-09-30T14:43:41+08:00","size":4387200,"digest":"978e5ce607f77c26814a174f480da79ac246c2201868ef84654aa03bb6727b5a","integrity":"sha256-l45c5gf3fCaBShdPSA2nmsJGwiAYaO+EZUqgO7Zye1o="},"admin-896281f4731722b0c084dbb1af21d0f34a5bc142d58aff57b391864ab71ddca7.css":{"logical_path":"admin.css","mtime":"2019-09-30T14:43:41+08:00","size":842269,"digest":"896281f4731722b0c084dbb1af21d0f34a5bc142d58aff57b391864ab71ddca7","integrity":"sha256-iWKB9HMXIrDAhNuxryHQ80pbwULViv9Xs5GGSrcd3Kc="},"application-97f313e9bb7d25476649f7d7215959cf421480fd0a3785d1956953bf94a1e8bd.css":{"logical_path":"application.css","mtime":"2019-09-30T14:43:41+08:00","size":1993118,"digest":"97f313e9bb7d25476649f7d7215959cf421480fd0a3785d1956953bf94a1e8bd","integrity":"sha256-l/MT6bt9JUdmSffXIVlZz0IUgP0KN4XRlWlTv5Sh6L0="},"admin-2cdb23442fa735025385b88f2900df04fef38b61530041a6dbe375ef0f0ae888.js":{"logical_path":"admin.js","mtime":"2019-10-11T14:38:33+08:00","size":4394616,"digest":"2cdb23442fa735025385b88f2900df04fef38b61530041a6dbe375ef0f0ae888","integrity":"sha256-LNsjRC+nNQJThbiPKQDfBP7zi2FTAEGm2+N17w8K6Ig="},"admin-2c2854b9a02158ded5a809aaf7144a8630b10354ab4e56fecc4dffcc713796cc.css":{"logical_path":"admin.css","mtime":"2019-10-10T17:12:05+08:00","size":846514,"digest":"2c2854b9a02158ded5a809aaf7144a8630b10354ab4e56fecc4dffcc713796cc","integrity":"sha256-LChUuaAhWN7VqAmq9xRKhjCxA1SrTlb+zE3/zHE3lsw="},"application-50059ae929866043b47015128702fcfba53d32a2df148e64e1d961c10651c6af.css":{"logical_path":"application.css","mtime":"2019-10-10T17:12:05+08:00","size":2001607,"digest":"50059ae929866043b47015128702fcfba53d32a2df148e64e1d961c10651c6af","integrity":"sha256-UAWa6SmGYEO0cBUShwL8+6U9MqLfFI5k4dlhwQZRxq8="},"admin-992cde09b6d17f00a49576ae2d9f1ced127244ba401ef5b7d677cab9741688d2.js":{"logical_path":"admin.js","mtime":"2019-10-16T16:11:32+08:00","size":4394790,"digest":"992cde09b6d17f00a49576ae2d9f1ced127244ba401ef5b7d677cab9741688d2","integrity":"sha256-mSzeCbbRfwCklXauLZ8c7RJyRLpAHvW31nfKuXQWiNI="},"admin-84f2a7791e275d6f820514370b3f968176b994b9dd7b8c3ba8bf48336b03f257.css":{"logical_path":"admin.css","mtime":"2019-10-16T19:25:40+08:00","size":846676,"digest":"84f2a7791e275d6f820514370b3f968176b994b9dd7b8c3ba8bf48336b03f257","integrity":"sha256-hPKneR4nXW+CBRQ3Cz+WgXa5lLnde4w7qL9IM2sD8lc="},"application-ef6bab84852baaf69a91fe6af875b6e1b118c55b4c7d165665c488fac80c4997.css":{"logical_path":"application.css","mtime":"2019-10-16T19:25:40+08:00","size":2001931,"digest":"ef6bab84852baaf69a91fe6af875b6e1b118c55b4c7d165665c488fac80c4997","integrity":"sha256-72urhIUrqvaakf5q+HW24bEYxVtMfRZWZcSI+sgMSZc="},"admin-c99030d305662f740aa84b6c925a1adbbaadaa07fd74e2655e64d44b4b97fc4a.js":{"logical_path":"admin.js","mtime":"2019-10-17T09:44:58+08:00","size":4394897,"digest":"c99030d305662f740aa84b6c925a1adbbaadaa07fd74e2655e64d44b4b97fc4a","integrity":"sha256-yZAw0wVmL3QKqEtskloa27qtqgf9dOJlXmTUS0uX/Eo="},"admin-534bde871d67f4d6fc8da611917d78be4066fc7593ba53ee92aa17068a199d6d.css":{"logical_path":"admin.css","mtime":"2019-10-17T10:22:41+08:00","size":846699,"digest":"534bde871d67f4d6fc8da611917d78be4066fc7593ba53ee92aa17068a199d6d","integrity":"sha256-U0vehx1n9Nb8jaYRkX14vkBm/HWTulPukqoXBooZnW0="},"cooperative-04cd6a60d41220d38ee45ce40b1d004e1d0bcd87c132fb1a7bab6144c1deb8d7.js":{"logical_path":"cooperative.js","mtime":"2019-10-17T10:17:56+08:00","size":4330072,"digest":"04cd6a60d41220d38ee45ce40b1d004e1d0bcd87c132fb1a7bab6144c1deb8d7","integrity":"sha256-BM1qYNQSINOO5FzkCx0ATh0LzYfBMvsae6thRMHeuNc="},"cooperative-a345bbfd8e38b70c9285ecc1747012ffcde429187983e2aea5657abb56b9b4f3.css":{"logical_path":"cooperative.css","mtime":"2019-10-17T10:21:41+08:00","size":830628,"digest":"a345bbfd8e38b70c9285ecc1747012ffcde429187983e2aea5657abb56b9b4f3","integrity":"sha256-o0W7/Y44twyShezBdHAS/83kKRh5g+KupWV6u1a5tPM="},"application-0e417478d56f42467e857cd186b29cbbc0d6c7c6e85c8a6f42f39ac618943de8.css":{"logical_path":"application.css","mtime":"2019-09-03T08:55:53+08:00","size":442932,"digest":"0e417478d56f42467e857cd186b29cbbc0d6c7c6e85c8a6f42f39ac618943de8","integrity":"sha256-DkF0eNVvQkZ+hXzRhrKcu8DWx8boXIpvQvOaxhiUPeg="},"cooperative-149f47b8675d60a8014ccff50f00f932ff69e2be286ffb74343bc4a3effb135b.js":{"logical_path":"cooperative.js","mtime":"2019-10-17T14:03:03+08:00","size":4338033,"digest":"149f47b8675d60a8014ccff50f00f932ff69e2be286ffb74343bc4a3effb135b","integrity":"sha256-FJ9HuGddYKgBTM/1DwD5Mv9p4r4ob/t0NDvEo+/7E1s="},"cooperative-6273b766d6ef11dd56174d868bab55e7f17af17546c888d2ba0dd0a6bcda76c8.css":{"logical_path":"cooperative.css","mtime":"2019-10-17T11:13:07+08:00","size":832914,"digest":"6273b766d6ef11dd56174d868bab55e7f17af17546c888d2ba0dd0a6bcda76c8","integrity":"sha256-YnO3ZtbvEd1WF02Gi6tV5/F68XVGyIjSug3Qprzadsg="},"admin-82f66cc80b5649c6530a562567f28fe8d05f7bc3b8221e0695b2216255c52ba6.js":{"logical_path":"admin.js","mtime":"2019-10-21T13:51:43+08:00","size":4397012,"digest":"82f66cc80b5649c6530a562567f28fe8d05f7bc3b8221e0695b2216255c52ba6","integrity":"sha256-gvZsyAtWScZTClYlZ/KP6NBfe8O4Ih4GlbIhYlXFK6Y="},"admin-1b5728d94f6bccfbcef452a760d94c3b6f31966bc65d7f89be077fc2ea512bec.js":{"logical_path":"admin.js","mtime":"2019-10-21T16:41:06+08:00","size":4397437,"digest":"1b5728d94f6bccfbcef452a760d94c3b6f31966bc65d7f89be077fc2ea512bec","integrity":"sha256-G1co2U9rzPvO9FKnYNlMO28xlmvGXX+Jvgd/wupRK+w="},"admin-c8c127fefa5eca98bca19832c246619318164e8f242635c07033e2423cc18a6f.js":{"logical_path":"admin.js","mtime":"2019-10-22T09:53:29+08:00","size":4408150,"digest":"c8c127fefa5eca98bca19832c246619318164e8f242635c07033e2423cc18a6f","integrity":"sha256-yMEn/vpeypi8oZgywkZhkxgWTo8kJjXAcDPiQjzBim8="},"admin-60d200c1fcdf61a60537d29ccf4479c6b1e5e904208870a63b8ee677c96b347e.css":{"logical_path":"admin.css","mtime":"2019-10-22T09:43:20+08:00","size":851150,"digest":"60d200c1fcdf61a60537d29ccf4479c6b1e5e904208870a63b8ee677c96b347e","integrity":"sha256-YNIAwfzfYaYFN9Kcz0R5xrHl6QQgiHCmO47md8lrNH4="},"cooperative-9fb7ac4ad44081fafd5ad2a3a1bfb7f4329ac96f28bc6446d1ff52b1e2e71286.js":{"logical_path":"cooperative.js","mtime":"2019-10-22T09:55:26+08:00","size":4338142,"digest":"9fb7ac4ad44081fafd5ad2a3a1bfb7f4329ac96f28bc6446d1ff52b1e2e71286","integrity":"sha256-n7esStRAgfr9WtKjob+39DKayW8ovGRG0f9SseLnEoY="}},"assets":{"admin.js":"admin-c8c127fefa5eca98bca19832c246619318164e8f242635c07033e2423cc18a6f.js","admin.css":"admin-60d200c1fcdf61a60537d29ccf4479c6b1e5e904208870a63b8ee677c96b347e.css","font-awesome/fontawesome-webfont.eot":"font-awesome/fontawesome-webfont-7bfcab6db99d5cfbf1705ca0536ddc78585432cc5fa41bbd7ad0f009033b2979.eot","font-awesome/fontawesome-webfont.woff2":"font-awesome/fontawesome-webfont-2adefcbc041e7d18fcf2d417879dc5a09997aa64d675b7a3c4b6ce33da13f3fe.woff2","font-awesome/fontawesome-webfont.woff":"font-awesome/fontawesome-webfont-ba0c59deb5450f5cb41b3f93609ee2d0d995415877ddfa223e8a8a7533474f07.woff","font-awesome/fontawesome-webfont.ttf":"font-awesome/fontawesome-webfont-aa58f33f239a0fb02f5c7a6c45c043d7a9ac9a093335806694ecd6d4edc0d6a8.ttf","font-awesome/fontawesome-webfont.svg":"font-awesome/fontawesome-webfont-ad6157926c1622ba4e1d03d478f1541368524bfc46f51e42fe0d945f7ef323e4.svg","college.js":"college-18f5e8400331634e898a35acc2187815c096c25e0ab74aba341ae916166cd287.js","college.css":"college-38f953d6ba5b85d3fab63cb3c2bbf0d057ccc6454d07cfaafac3b06da37b8437.css","logo.png":"logo-7ff112568709bf97f9898fe87249b7a8f200ff1f48d537d85af87215f1870423.png","application.js":"application-9cfbc3d792599a1d0de5c7b84209e1c2b2e60336f0f01e19f0581663918708fb.js","application.css":"application-0e417478d56f42467e857cd186b29cbbc0d6c7c6e85c8a6f42f39ac618943de8.css","cooperative.js":"cooperative-9fb7ac4ad44081fafd5ad2a3a1bfb7f4329ac96f28bc6446d1ff52b1e2e71286.js","cooperative.css":"cooperative-6273b766d6ef11dd56174d868bab55e7f17af17546c888d2ba0dd0a6bcda76c8.css"}} \ No newline at end of file +{"files":{"admin-cd9ca8bacc973ce2dbace30c97f6c40bc08e2c2ee44972f668e738e1902c0121.js":{"logical_path":"admin.js","mtime":"2019-09-11T16:20:07+08:00","size":4350881,"digest":"cd9ca8bacc973ce2dbace30c97f6c40bc08e2c2ee44972f668e738e1902c0121","integrity":"sha256-zZyousyXPOLbrOMMl/bEC8COLC7kSXL2aOc44ZAsASE="},"admin-a1b3356efe50ff4717cf22475639b5333c5354ba03fd107c9b7a8d4ae76f47aa.css":{"logical_path":"admin.css","mtime":"2019-09-11T16:20:07+08:00","size":773445,"digest":"a1b3356efe50ff4717cf22475639b5333c5354ba03fd107c9b7a8d4ae76f47aa","integrity":"sha256-obM1bv5Q/0cXzyJHVjm1MzxTVLoD/RB8m3qNSudvR6o="},"font-awesome/fontawesome-webfont-7bfcab6db99d5cfbf1705ca0536ddc78585432cc5fa41bbd7ad0f009033b2979.eot":{"logical_path":"font-awesome/fontawesome-webfont.eot","mtime":"2019-08-22T14:54:27+08:00","size":165742,"digest":"7bfcab6db99d5cfbf1705ca0536ddc78585432cc5fa41bbd7ad0f009033b2979","integrity":"sha256-e/yrbbmdXPvxcFygU23ceFhUMsxfpBu9etDwCQM7KXk="},"font-awesome/fontawesome-webfont-2adefcbc041e7d18fcf2d417879dc5a09997aa64d675b7a3c4b6ce33da13f3fe.woff2":{"logical_path":"font-awesome/fontawesome-webfont.woff2","mtime":"2019-08-22T14:54:27+08:00","size":77160,"digest":"2adefcbc041e7d18fcf2d417879dc5a09997aa64d675b7a3c4b6ce33da13f3fe","integrity":"sha256-Kt78vAQefRj88tQXh53FoJmXqmTWdbejxLbOM9oT8/4="},"font-awesome/fontawesome-webfont-ba0c59deb5450f5cb41b3f93609ee2d0d995415877ddfa223e8a8a7533474f07.woff":{"logical_path":"font-awesome/fontawesome-webfont.woff","mtime":"2019-08-22T14:54:27+08:00","size":98024,"digest":"ba0c59deb5450f5cb41b3f93609ee2d0d995415877ddfa223e8a8a7533474f07","integrity":"sha256-ugxZ3rVFD1y0Gz+TYJ7i0NmVQVh33foiPoqKdTNHTwc="},"font-awesome/fontawesome-webfont-aa58f33f239a0fb02f5c7a6c45c043d7a9ac9a093335806694ecd6d4edc0d6a8.ttf":{"logical_path":"font-awesome/fontawesome-webfont.ttf","mtime":"2019-08-22T14:54:27+08:00","size":165548,"digest":"aa58f33f239a0fb02f5c7a6c45c043d7a9ac9a093335806694ecd6d4edc0d6a8","integrity":"sha256-qljzPyOaD7AvXHpsRcBD16msmgkzNYBmlOzW1O3A1qg="},"font-awesome/fontawesome-webfont-ad6157926c1622ba4e1d03d478f1541368524bfc46f51e42fe0d945f7ef323e4.svg":{"logical_path":"font-awesome/fontawesome-webfont.svg","mtime":"2019-08-22T14:54:27+08:00","size":444379,"digest":"ad6157926c1622ba4e1d03d478f1541368524bfc46f51e42fe0d945f7ef323e4","integrity":"sha256-rWFXkmwWIrpOHQPUePFUE2hSS/xG9R5C/g2UX37zI+Q="},"college-18f5e8400331634e898a35acc2187815c096c25e0ab74aba341ae916166cd287.js":{"logical_path":"college.js","mtime":"2019-10-25T14:55:33+08:00","size":3352744,"digest":"18f5e8400331634e898a35acc2187815c096c25e0ab74aba341ae916166cd287","integrity":"sha256-GPXoQAMxY06JijWswhh4FcCWwl4Kt0q6NBrpFhZs0oc="},"college-944d4273f62c7538368b9017fdd3387b5e3bea31a87873770eb231324546d4d9.css":{"logical_path":"college.css","mtime":"2019-09-11T16:20:07+08:00","size":546841,"digest":"944d4273f62c7538368b9017fdd3387b5e3bea31a87873770eb231324546d4d9","integrity":"sha256-lE1Cc/YsdTg2i5AX/dM4e1476jGoeHN3DrIxMkVG1Nk="},"logo-7ff112568709bf97f9898fe87249b7a8f200ff1f48d537d85af87215f1870423.png":{"logical_path":"logo.png","mtime":"2019-10-21T22:52:15+08:00","size":2816,"digest":"7ff112568709bf97f9898fe87249b7a8f200ff1f48d537d85af87215f1870423","integrity":"sha256-f/ESVocJv5f5iY/ockm3qPIA/x9I1TfYWvhyFfGHBCM="},"application-9cfbc3d792599a1d0de5c7b84209e1c2b2e60336f0f01e19f0581663918708fb.js":{"logical_path":"application.js","mtime":"2019-10-25T14:55:33+08:00","size":600706,"digest":"9cfbc3d792599a1d0de5c7b84209e1c2b2e60336f0f01e19f0581663918708fb","integrity":"sha256-nPvD15JZmh0N5ce4QgnhwrLmAzbw8B4Z8FgWY5GHCPs="},"application-5eb87c6e13676d0183317debce17fade27e68c4acee28c419438da15d53c94f2.css":{"logical_path":"application.css","mtime":"2019-09-11T16:20:07+08:00","size":1844002,"digest":"5eb87c6e13676d0183317debce17fade27e68c4acee28c419438da15d53c94f2","integrity":"sha256-Xrh8bhNnbQGDMX3rzhf63ifmjErO4oxBlDjaFdU8lPI="},"admin-c9e5ebe6191548550e27514196ea125cfbb402820ec125a0c9acf99d2d378fe4.js":{"logical_path":"admin.js","mtime":"2019-09-21T15:28:08+08:00","size":4382031,"digest":"c9e5ebe6191548550e27514196ea125cfbb402820ec125a0c9acf99d2d378fe4","integrity":"sha256-yeXr5hkVSFUOJ1FBluoSXPu0AoIOwSWgyaz5nS03j+Q="},"admin-59c59f8cae8bef4a8359286c985458110c9d03ea121516595c988943f4717c38.css":{"logical_path":"admin.css","mtime":"2019-09-21T14:49:04+08:00","size":840093,"digest":"59c59f8cae8bef4a8359286c985458110c9d03ea121516595c988943f4717c38","integrity":"sha256-WcWfjK6L70qDWShsmFRYEQydA+oSFRZZXJiJQ/RxfDg="},"college-38f953d6ba5b85d3fab63cb3c2bbf0d057ccc6454d07cfaafac3b06da37b8437.css":{"logical_path":"college.css","mtime":"2019-09-16T13:56:09+08:00","size":579109,"digest":"38f953d6ba5b85d3fab63cb3c2bbf0d057ccc6454d07cfaafac3b06da37b8437","integrity":"sha256-OPlT1rpbhdP6tjyzwrvw0FfMxkVNB8+q+sOwbaN7hDc="},"application-646b1158a4e8c1f13e684d6fe9025abc75f8d3ba5256e440802c0398223374f3.css":{"logical_path":"application.css","mtime":"2019-09-21T14:49:04+08:00","size":1988767,"digest":"646b1158a4e8c1f13e684d6fe9025abc75f8d3ba5256e440802c0398223374f3","integrity":"sha256-ZGsRWKTowfE+aE1v6QJavHX407pSVuRAgCwDmCIzdPM="},"admin-a47e37c0ec7cf5f22380249776d1e82d65b6b6aa272ed7389185aa200fa40751.js":{"logical_path":"admin.js","mtime":"2019-09-25T15:33:05+08:00","size":4383107,"digest":"a47e37c0ec7cf5f22380249776d1e82d65b6b6aa272ed7389185aa200fa40751","integrity":"sha256-pH43wOx89fIjgCSXdtHoLWW2tqonLtc4kYWqIA+kB1E="},"admin-432c4eac09b036c57ff1e88d902b8aa7df81164e4b419bac557cf1366c1d3ad9.js":{"logical_path":"admin.js","mtime":"2019-09-25T15:35:20+08:00","size":4383103,"digest":"432c4eac09b036c57ff1e88d902b8aa7df81164e4b419bac557cf1366c1d3ad9","integrity":"sha256-QyxOrAmwNsV/8eiNkCuKp9+BFk5LQZusVXzxNmwdOtk="},"admin-978e5ce607f77c26814a174f480da79ac246c2201868ef84654aa03bb6727b5a.js":{"logical_path":"admin.js","mtime":"2019-09-30T14:43:41+08:00","size":4387200,"digest":"978e5ce607f77c26814a174f480da79ac246c2201868ef84654aa03bb6727b5a","integrity":"sha256-l45c5gf3fCaBShdPSA2nmsJGwiAYaO+EZUqgO7Zye1o="},"admin-896281f4731722b0c084dbb1af21d0f34a5bc142d58aff57b391864ab71ddca7.css":{"logical_path":"admin.css","mtime":"2019-09-30T14:43:41+08:00","size":842269,"digest":"896281f4731722b0c084dbb1af21d0f34a5bc142d58aff57b391864ab71ddca7","integrity":"sha256-iWKB9HMXIrDAhNuxryHQ80pbwULViv9Xs5GGSrcd3Kc="},"application-97f313e9bb7d25476649f7d7215959cf421480fd0a3785d1956953bf94a1e8bd.css":{"logical_path":"application.css","mtime":"2019-09-30T14:43:41+08:00","size":1993118,"digest":"97f313e9bb7d25476649f7d7215959cf421480fd0a3785d1956953bf94a1e8bd","integrity":"sha256-l/MT6bt9JUdmSffXIVlZz0IUgP0KN4XRlWlTv5Sh6L0="},"admin-2cdb23442fa735025385b88f2900df04fef38b61530041a6dbe375ef0f0ae888.js":{"logical_path":"admin.js","mtime":"2019-10-11T14:38:33+08:00","size":4394616,"digest":"2cdb23442fa735025385b88f2900df04fef38b61530041a6dbe375ef0f0ae888","integrity":"sha256-LNsjRC+nNQJThbiPKQDfBP7zi2FTAEGm2+N17w8K6Ig="},"admin-2c2854b9a02158ded5a809aaf7144a8630b10354ab4e56fecc4dffcc713796cc.css":{"logical_path":"admin.css","mtime":"2019-10-10T17:12:05+08:00","size":846514,"digest":"2c2854b9a02158ded5a809aaf7144a8630b10354ab4e56fecc4dffcc713796cc","integrity":"sha256-LChUuaAhWN7VqAmq9xRKhjCxA1SrTlb+zE3/zHE3lsw="},"application-50059ae929866043b47015128702fcfba53d32a2df148e64e1d961c10651c6af.css":{"logical_path":"application.css","mtime":"2019-10-10T17:12:05+08:00","size":2001607,"digest":"50059ae929866043b47015128702fcfba53d32a2df148e64e1d961c10651c6af","integrity":"sha256-UAWa6SmGYEO0cBUShwL8+6U9MqLfFI5k4dlhwQZRxq8="},"admin-992cde09b6d17f00a49576ae2d9f1ced127244ba401ef5b7d677cab9741688d2.js":{"logical_path":"admin.js","mtime":"2019-10-16T16:11:32+08:00","size":4394790,"digest":"992cde09b6d17f00a49576ae2d9f1ced127244ba401ef5b7d677cab9741688d2","integrity":"sha256-mSzeCbbRfwCklXauLZ8c7RJyRLpAHvW31nfKuXQWiNI="},"admin-84f2a7791e275d6f820514370b3f968176b994b9dd7b8c3ba8bf48336b03f257.css":{"logical_path":"admin.css","mtime":"2019-10-16T19:25:40+08:00","size":846676,"digest":"84f2a7791e275d6f820514370b3f968176b994b9dd7b8c3ba8bf48336b03f257","integrity":"sha256-hPKneR4nXW+CBRQ3Cz+WgXa5lLnde4w7qL9IM2sD8lc="},"application-ef6bab84852baaf69a91fe6af875b6e1b118c55b4c7d165665c488fac80c4997.css":{"logical_path":"application.css","mtime":"2019-10-16T19:25:40+08:00","size":2001931,"digest":"ef6bab84852baaf69a91fe6af875b6e1b118c55b4c7d165665c488fac80c4997","integrity":"sha256-72urhIUrqvaakf5q+HW24bEYxVtMfRZWZcSI+sgMSZc="},"admin-c99030d305662f740aa84b6c925a1adbbaadaa07fd74e2655e64d44b4b97fc4a.js":{"logical_path":"admin.js","mtime":"2019-10-17T09:44:58+08:00","size":4394897,"digest":"c99030d305662f740aa84b6c925a1adbbaadaa07fd74e2655e64d44b4b97fc4a","integrity":"sha256-yZAw0wVmL3QKqEtskloa27qtqgf9dOJlXmTUS0uX/Eo="},"admin-534bde871d67f4d6fc8da611917d78be4066fc7593ba53ee92aa17068a199d6d.css":{"logical_path":"admin.css","mtime":"2019-10-17T10:22:41+08:00","size":846699,"digest":"534bde871d67f4d6fc8da611917d78be4066fc7593ba53ee92aa17068a199d6d","integrity":"sha256-U0vehx1n9Nb8jaYRkX14vkBm/HWTulPukqoXBooZnW0="},"cooperative-04cd6a60d41220d38ee45ce40b1d004e1d0bcd87c132fb1a7bab6144c1deb8d7.js":{"logical_path":"cooperative.js","mtime":"2019-10-17T10:17:56+08:00","size":4330072,"digest":"04cd6a60d41220d38ee45ce40b1d004e1d0bcd87c132fb1a7bab6144c1deb8d7","integrity":"sha256-BM1qYNQSINOO5FzkCx0ATh0LzYfBMvsae6thRMHeuNc="},"cooperative-a345bbfd8e38b70c9285ecc1747012ffcde429187983e2aea5657abb56b9b4f3.css":{"logical_path":"cooperative.css","mtime":"2019-10-17T10:21:41+08:00","size":830628,"digest":"a345bbfd8e38b70c9285ecc1747012ffcde429187983e2aea5657abb56b9b4f3","integrity":"sha256-o0W7/Y44twyShezBdHAS/83kKRh5g+KupWV6u1a5tPM="},"application-0e417478d56f42467e857cd186b29cbbc0d6c7c6e85c8a6f42f39ac618943de8.css":{"logical_path":"application.css","mtime":"2019-09-03T08:55:53+08:00","size":442932,"digest":"0e417478d56f42467e857cd186b29cbbc0d6c7c6e85c8a6f42f39ac618943de8","integrity":"sha256-DkF0eNVvQkZ+hXzRhrKcu8DWx8boXIpvQvOaxhiUPeg="},"cooperative-149f47b8675d60a8014ccff50f00f932ff69e2be286ffb74343bc4a3effb135b.js":{"logical_path":"cooperative.js","mtime":"2019-10-17T14:03:03+08:00","size":4338033,"digest":"149f47b8675d60a8014ccff50f00f932ff69e2be286ffb74343bc4a3effb135b","integrity":"sha256-FJ9HuGddYKgBTM/1DwD5Mv9p4r4ob/t0NDvEo+/7E1s="},"cooperative-6273b766d6ef11dd56174d868bab55e7f17af17546c888d2ba0dd0a6bcda76c8.css":{"logical_path":"cooperative.css","mtime":"2019-10-17T11:13:07+08:00","size":832914,"digest":"6273b766d6ef11dd56174d868bab55e7f17af17546c888d2ba0dd0a6bcda76c8","integrity":"sha256-YnO3ZtbvEd1WF02Gi6tV5/F68XVGyIjSug3Qprzadsg="},"admin-82f66cc80b5649c6530a562567f28fe8d05f7bc3b8221e0695b2216255c52ba6.js":{"logical_path":"admin.js","mtime":"2019-10-21T13:51:43+08:00","size":4397012,"digest":"82f66cc80b5649c6530a562567f28fe8d05f7bc3b8221e0695b2216255c52ba6","integrity":"sha256-gvZsyAtWScZTClYlZ/KP6NBfe8O4Ih4GlbIhYlXFK6Y="},"admin-1b5728d94f6bccfbcef452a760d94c3b6f31966bc65d7f89be077fc2ea512bec.js":{"logical_path":"admin.js","mtime":"2019-10-21T16:41:06+08:00","size":4397437,"digest":"1b5728d94f6bccfbcef452a760d94c3b6f31966bc65d7f89be077fc2ea512bec","integrity":"sha256-G1co2U9rzPvO9FKnYNlMO28xlmvGXX+Jvgd/wupRK+w="},"admin-c8c127fefa5eca98bca19832c246619318164e8f242635c07033e2423cc18a6f.js":{"logical_path":"admin.js","mtime":"2019-10-22T09:53:29+08:00","size":4408150,"digest":"c8c127fefa5eca98bca19832c246619318164e8f242635c07033e2423cc18a6f","integrity":"sha256-yMEn/vpeypi8oZgywkZhkxgWTo8kJjXAcDPiQjzBim8="},"admin-60d200c1fcdf61a60537d29ccf4479c6b1e5e904208870a63b8ee677c96b347e.css":{"logical_path":"admin.css","mtime":"2019-10-22T09:43:20+08:00","size":851150,"digest":"60d200c1fcdf61a60537d29ccf4479c6b1e5e904208870a63b8ee677c96b347e","integrity":"sha256-YNIAwfzfYaYFN9Kcz0R5xrHl6QQgiHCmO47md8lrNH4="},"cooperative-9fb7ac4ad44081fafd5ad2a3a1bfb7f4329ac96f28bc6446d1ff52b1e2e71286.js":{"logical_path":"cooperative.js","mtime":"2019-10-22T09:55:26+08:00","size":4338142,"digest":"9fb7ac4ad44081fafd5ad2a3a1bfb7f4329ac96f28bc6446d1ff52b1e2e71286","integrity":"sha256-n7esStRAgfr9WtKjob+39DKayW8ovGRG0f9SseLnEoY="},"admin-a11066081d60365ddf25d5867560d1ccdd3197dbe82a5b6e969cc940e3429ff1.js":{"logical_path":"admin.js","mtime":"2019-10-24T14:16:30+08:00","size":4524252,"digest":"a11066081d60365ddf25d5867560d1ccdd3197dbe82a5b6e969cc940e3429ff1","integrity":"sha256-oRBmCB1gNl3fJdWGdWDRzN0xl9voKltulpzJQONCn/E="},"admin-7ce3dd717f7d12fcbc64caf14200230a1e68db439be0ba1879077599ff2c32c6.css":{"logical_path":"admin.css","mtime":"2019-10-24T10:10:08+08:00","size":852772,"digest":"7ce3dd717f7d12fcbc64caf14200230a1e68db439be0ba1879077599ff2c32c6","integrity":"sha256-fOPdcX99Evy8ZMrxQgAjCh5o20Ob4LoYeQd1mf8sMsY="},"college-93904c65d52c125aec0a463b9fd98bedda0018b78707f806be22685cca5d3747.css":{"logical_path":"college.css","mtime":"2019-10-24T10:10:08+08:00","size":579546,"digest":"93904c65d52c125aec0a463b9fd98bedda0018b78707f806be22685cca5d3747","integrity":"sha256-k5BMZdUsElrsCkY7n9mL7doAGLeHB/gGviJoXMpdN0c="},"cooperative-84c79d26a36aff5b496551b6d21b1bfb726b1bbc4153435a366115e96c204e06.js":{"logical_path":"cooperative.js","mtime":"2019-10-24T14:17:15+08:00","size":4338225,"digest":"84c79d26a36aff5b496551b6d21b1bfb726b1bbc4153435a366115e96c204e06","integrity":"sha256-hMedJqNq/1tJZVG20hsb+3JrG7xBU0NaNmEV6WwgTgY="},"cooperative-10a9ee5177e196572573ccea460e133c748072e223fdb473d05ee72c991fbbe3.css":{"logical_path":"cooperative.css","mtime":"2019-10-24T10:10:08+08:00","size":833351,"digest":"10a9ee5177e196572573ccea460e133c748072e223fdb473d05ee72c991fbbe3","integrity":"sha256-EKnuUXfhllclc8zqRg4TPHSAcuIj/bRz0F7nLJkfu+M="},"admin-441d8f3722e5f73e5748aaeb6f517101474cb1eb48a99f119e561f08b9e9dc60.js":{"logical_path":"admin.js","mtime":"2019-10-24T16:08:56+08:00","size":4525031,"digest":"441d8f3722e5f73e5748aaeb6f517101474cb1eb48a99f119e561f08b9e9dc60","integrity":"sha256-RB2PNyLl9z5XSKrrb1FxAUdMsetIqZ8RnlYfCLnp3GA="},"admin-76c52986591f274f639ad48dfbb480a1aeeec7647b6fa28fa541e78a064b6316.css":{"logical_path":"admin.css","mtime":"2019-10-24T15:25:17+08:00","size":867945,"digest":"76c52986591f274f639ad48dfbb480a1aeeec7647b6fa28fa541e78a064b6316","integrity":"sha256-dsUphlkfJ09jmtSN+7SAoa7ux2R7b6KPpUHnigZLYxY="},"cooperative-6c4c663b6b5071535bab2b76cc5e05ab5682665857763a76bf4f01afef51be5a.js":{"logical_path":"cooperative.js","mtime":"2019-10-24T17:56:20+08:00","size":4339039,"digest":"6c4c663b6b5071535bab2b76cc5e05ab5682665857763a76bf4f01afef51be5a","integrity":"sha256-bExmO2tQcVNbqyt2zF4Fq1aCZlhXdjp2v08Br+9Rvlo="},"admin-c63acadd431434979db50540a0bf7e65c75e1de0d1b449919f2cce89a0548d43.js":{"logical_path":"admin.js","mtime":"2019-10-24T18:12:33+08:00","size":4533182,"digest":"c63acadd431434979db50540a0bf7e65c75e1de0d1b449919f2cce89a0548d43","integrity":"sha256-xjrK3UMUNJedtQVAoL9+ZcdeHeDRtEmRnyzOiaBUjUM="},"admin-bd832b9a35eb3743dde9218beab61f9bcde1508767ad68dbedb1c89a4bb65c3a.css":{"logical_path":"admin.css","mtime":"2019-10-24T17:56:20+08:00","size":861450,"digest":"bd832b9a35eb3743dde9218beab61f9bcde1508767ad68dbedb1c89a4bb65c3a","integrity":"sha256-vYMrmjXrN0Pd6SGL6rYfm83hUIdnrWjb7bHImku2XDo="},"college-fa202780f3e7f96cb9b5916c6f0d7dd9e03cb746864bbd2dd491ed001c30ad8f.css":{"logical_path":"college.css","mtime":"2019-10-24T17:56:20+08:00","size":571936,"digest":"fa202780f3e7f96cb9b5916c6f0d7dd9e03cb746864bbd2dd491ed001c30ad8f","integrity":"sha256-+iAngPPn+Wy5tZFsbw192eA8t0aGS70t1JHtABwwrY8="},"cooperative-4f233e8963b0bd80bc56b71c209d31464d314240ac8d686806baf99511c53ad0.css":{"logical_path":"cooperative.css","mtime":"2019-10-24T17:56:20+08:00","size":825741,"digest":"4f233e8963b0bd80bc56b71c209d31464d314240ac8d686806baf99511c53ad0","integrity":"sha256-TyM+iWOwvYC8VrccIJ0xRk0xQkCsjWhoBrr5lRHFOtA="},"application-8c9d6bb61c50908f584b3070c79aeb95f25c1166d39e07da5e95438b39ca0de9.css":{"logical_path":"application.css","mtime":"2019-10-21T22:52:15+08:00","size":436995,"digest":"8c9d6bb61c50908f584b3070c79aeb95f25c1166d39e07da5e95438b39ca0de9","integrity":"sha256-jJ1rthxQkI9YSzBwx5rrlfJcEWbTngfaXpVDiznKDek="},"admin-bf2bd889f02d15c4913aa260497d72afeb26d701aac49a4ef6a75619af030152.js":{"logical_path":"admin.js","mtime":"2019-10-25T10:12:17+08:00","size":4533673,"digest":"bf2bd889f02d15c4913aa260497d72afeb26d701aac49a4ef6a75619af030152","integrity":"sha256-vyvYifAtFcSROqJgSX1yr+sm1wGqxJpO9qdWGa8DAVI="},"admin-46e564d29ffae5c71ae9b5e36dc0bd5de57b10f396eb2005bfb9cf51e7744cdd.css":{"logical_path":"admin.css","mtime":"2019-10-25T10:12:17+08:00","size":870355,"digest":"46e564d29ffae5c71ae9b5e36dc0bd5de57b10f396eb2005bfb9cf51e7744cdd","integrity":"sha256-RuVk0p/65cca6bXjbcC9XeV7EPOW6yAFv7nPUed0TN0="},"college-2299e05f5e9b640e333ece624d4ab18a678fdabff0bc18b69a9c2e3de49cba8e.css":{"logical_path":"college.css","mtime":"2019-10-25T10:12:17+08:00","size":580077,"digest":"2299e05f5e9b640e333ece624d4ab18a678fdabff0bc18b69a9c2e3de49cba8e","integrity":"sha256-IpngX16bZA4zPs5iTUqximeP2r/wvBi2mpwuPeScuo4="},"cooperative-f1ac8f14ad6ade8d1f79ca49ea9c79be77d49aae9d2705ca672e78444481700d.js":{"logical_path":"cooperative.js","mtime":"2019-10-25T14:55:33+08:00","size":4409145,"digest":"f1ac8f14ad6ade8d1f79ca49ea9c79be77d49aae9d2705ca672e78444481700d","integrity":"sha256-8ayPFK1q3o0fecpJ6px5vnfUmq6dJwXKZy54RESBcA0="},"cooperative-8057adee2454dbc9d648305faf9ede9824f40d3bd0184e816e8035bb7f1e730b.css":{"logical_path":"cooperative.css","mtime":"2019-10-25T10:12:17+08:00","size":833882,"digest":"8057adee2454dbc9d648305faf9ede9824f40d3bd0184e816e8035bb7f1e730b","integrity":"sha256-gFet7iRU28nWSDBfr57emCT0DTvQGE6BboA1u38ecws="},"admin-6f9bb9720e7e5040ae559a8fae11553313f77552a76416b3a9fe77198471964d.js":{"logical_path":"admin.js","mtime":"2019-10-25T17:00:09+08:00","size":4554537,"digest":"6f9bb9720e7e5040ae559a8fae11553313f77552a76416b3a9fe77198471964d","integrity":"sha256-b5u5cg5+UECuVZqPrhFVMxP3dVKnZBazqf53GYRxlk0="},"admin-ab3e0f7240ae4df8d1585c8d5e99df41edd3305ecc2abadcf8820796e1d9fc65.css":{"logical_path":"admin.css","mtime":"2019-10-25T09:55:22+08:00","size":862288,"digest":"ab3e0f7240ae4df8d1585c8d5e99df41edd3305ecc2abadcf8820796e1d9fc65","integrity":"sha256-qz4PckCuTfjRWFyNXpnfQe3TMF7MKrrc+IIHluHZ/GU="},"college-2fdfc5431b46ad4a454a25386dbcbc390466886f76b85fdb7e3f75018196a870.css":{"logical_path":"college.css","mtime":"2019-10-25T09:55:22+08:00","size":572010,"digest":"2fdfc5431b46ad4a454a25386dbcbc390466886f76b85fdb7e3f75018196a870","integrity":"sha256-L9/FQxtGrUpFSiU4bby8OQRmiG92uF/bfj91AYGWqHA="},"cooperative-47d516a0904d0633e82c1de39a6ec4c9e6de0a37813843e01d4bacf97e8b2ebf.css":{"logical_path":"cooperative.css","mtime":"2019-10-25T09:55:22+08:00","size":825815,"digest":"47d516a0904d0633e82c1de39a6ec4c9e6de0a37813843e01d4bacf97e8b2ebf","integrity":"sha256-R9UWoJBNBjPoLB3jmm7EyebeCjeBOEPgHUus+X6LLr8="}},"assets":{"admin.js":"admin-6f9bb9720e7e5040ae559a8fae11553313f77552a76416b3a9fe77198471964d.js","admin.css":"admin-ab3e0f7240ae4df8d1585c8d5e99df41edd3305ecc2abadcf8820796e1d9fc65.css","font-awesome/fontawesome-webfont.eot":"font-awesome/fontawesome-webfont-7bfcab6db99d5cfbf1705ca0536ddc78585432cc5fa41bbd7ad0f009033b2979.eot","font-awesome/fontawesome-webfont.woff2":"font-awesome/fontawesome-webfont-2adefcbc041e7d18fcf2d417879dc5a09997aa64d675b7a3c4b6ce33da13f3fe.woff2","font-awesome/fontawesome-webfont.woff":"font-awesome/fontawesome-webfont-ba0c59deb5450f5cb41b3f93609ee2d0d995415877ddfa223e8a8a7533474f07.woff","font-awesome/fontawesome-webfont.ttf":"font-awesome/fontawesome-webfont-aa58f33f239a0fb02f5c7a6c45c043d7a9ac9a093335806694ecd6d4edc0d6a8.ttf","font-awesome/fontawesome-webfont.svg":"font-awesome/fontawesome-webfont-ad6157926c1622ba4e1d03d478f1541368524bfc46f51e42fe0d945f7ef323e4.svg","college.js":"college-18f5e8400331634e898a35acc2187815c096c25e0ab74aba341ae916166cd287.js","college.css":"college-2fdfc5431b46ad4a454a25386dbcbc390466886f76b85fdb7e3f75018196a870.css","logo.png":"logo-7ff112568709bf97f9898fe87249b7a8f200ff1f48d537d85af87215f1870423.png","application.js":"application-9cfbc3d792599a1d0de5c7b84209e1c2b2e60336f0f01e19f0581663918708fb.js","application.css":"application-8c9d6bb61c50908f584b3070c79aeb95f25c1166d39e07da5e95438b39ca0de9.css","cooperative.js":"cooperative-f1ac8f14ad6ade8d1f79ca49ea9c79be77d49aae9d2705ca672e78444481700d.js","cooperative.css":"cooperative-47d516a0904d0633e82c1de39a6ec4c9e6de0a37813843e01d4bacf97e8b2ebf.css"}} \ No newline at end of file diff --git a/public/assets/admin-60d200c1fcdf61a60537d29ccf4479c6b1e5e904208870a63b8ee677c96b347e.css b/public/assets/admin-46e564d29ffae5c71ae9b5e36dc0bd5de57b10f396eb2005bfb9cf51e7744cdd.css similarity index 97% rename from public/assets/admin-60d200c1fcdf61a60537d29ccf4479c6b1e5e904208870a63b8ee677c96b347e.css rename to public/assets/admin-46e564d29ffae5c71ae9b5e36dc0bd5de57b10f396eb2005bfb9cf51e7744cdd.css index edf0f7f74..566ecebd4 100644 --- a/public/assets/admin-60d200c1fcdf61a60537d29ccf4479c6b1e5e904208870a63b8ee677c96b347e.css +++ b/public/assets/admin-46e564d29ffae5c71ae9b5e36dc0bd5de57b10f396eb2005bfb9cf51e7744cdd.css @@ -19161,6 +19161,362 @@ body[class*=jconfirm-no-scroll-] { transform: scale(1); } +/*! + * Datetimepicker for Bootstrap + * + * Copyright 2012 Stefan Petre + * Improvements by Andrew Rowls + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + */ +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker { + padding: 4px; + margin-top: 1px; + border-radius: 4px; + direction: ltr; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker-inline { + width: 220px; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker.datetimepicker-rtl { + direction: rtl; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker.datetimepicker-rtl table tr td span { + float: right; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker-dropdown, .datetimepicker-dropdown-left { + top: 0; + left: 0; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +[class*=" datetimepicker-dropdown"]:before { + content: ''; + display: inline-block; + border-left: 7px solid transparent; + border-right: 7px solid transparent; + border-bottom: 7px solid #ccc; + border-bottom-color: rgba(0, 0, 0, 0.2); + position: absolute; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +[class*=" datetimepicker-dropdown"]:after { + content: ''; + display: inline-block; + border-left: 6px solid transparent; + border-right: 6px solid transparent; + border-bottom: 6px solid #fff; + position: absolute; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +[class*=" datetimepicker-dropdown-top"]:before { + content: ''; + display: inline-block; + border-left: 7px solid transparent; + border-right: 7px solid transparent; + border-top: 7px solid #ccc; + border-top-color: rgba(0, 0, 0, 0.2); + border-bottom: 0; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +[class*=" datetimepicker-dropdown-top"]:after { + content: ''; + display: inline-block; + border-left: 6px solid transparent; + border-right: 6px solid transparent; + border-top: 6px solid #fff; + border-bottom: 0; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker-dropdown-bottom-left:before { + top: -7px; + right: 6px; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker-dropdown-bottom-left:after { + top: -6px; + right: 7px; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker-dropdown-bottom-right:before { + top: -7px; + left: 6px; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker-dropdown-bottom-right:after { + top: -6px; + left: 7px; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker-dropdown-top-left:before { + bottom: -7px; + right: 6px; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker-dropdown-top-left:after { + bottom: -6px; + right: 7px; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker-dropdown-top-right:before { + bottom: -7px; + left: 6px; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker-dropdown-top-right:after { + bottom: -6px; + left: 7px; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker > div { + display: none; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker.minutes div.datetimepicker-minutes { + display: block; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker.hours div.datetimepicker-hours { + display: block; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker.days div.datetimepicker-days { + display: block; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker.months div.datetimepicker-months { + display: block; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker.years div.datetimepicker-years { + display: block; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker table { + margin: 0; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker td, .datetimepicker th { + text-align: center; + width: 20px; + height: 20px; + border-radius: 4px; + border: 0; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.table-striped .datetimepicker table tr td, .table-striped .datetimepicker table tr th { + background-color: transparent; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker table tr td.minute:hover { + background: #eee; + cursor: pointer; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker table tr td.hour:hover { + background: #eee; + cursor: pointer; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker table tr td.day:hover { + background: #eee; + cursor: pointer; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker table tr td.old, .datetimepicker table tr td.new { + color: #999; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker table tr td.disabled, .datetimepicker table tr td.disabled:hover { + background: 0; + color: #999; + cursor: default; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker table tr td.today, .datetimepicker table tr td.today:hover, .datetimepicker table tr td.today.disabled, .datetimepicker table tr td.today.disabled:hover { + background-color: #fde19a; + background-image: -webkit-gradient(linear, left top, left bottom, from(#fdd49a), to(#fdf59a)); + background-image: linear-gradient(to bottom, #fdd49a, #fdf59a); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fdd49a',endColorstr='#fdf59a',GradientType=0); + border-color: #fdf59a #fdf59a #fbed50; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker table tr td.today:hover, .datetimepicker table tr td.today:hover:hover, .datetimepicker table tr td.today.disabled:hover, .datetimepicker table tr td.today.disabled:hover:hover, .datetimepicker table tr td.today:active, .datetimepicker table tr td.today:hover:active, .datetimepicker table tr td.today.disabled:active, .datetimepicker table tr td.today.disabled:hover:active, .datetimepicker table tr td.today.active, .datetimepicker table tr td.today:hover.active, .datetimepicker table tr td.today.disabled.active, .datetimepicker table tr td.today.disabled:hover.active, .datetimepicker table tr td.today.disabled, .datetimepicker table tr td.today:hover.disabled, .datetimepicker table tr td.today.disabled.disabled, .datetimepicker table tr td.today.disabled:hover.disabled, .datetimepicker table tr td.today[disabled], .datetimepicker table tr td.today:hover[disabled], .datetimepicker table tr td.today.disabled[disabled], .datetimepicker table tr td.today.disabled:hover[disabled] { + background-color: #fdf59a; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker table tr td.today:active, .datetimepicker table tr td.today:hover:active, .datetimepicker table tr td.today.disabled:active, .datetimepicker table tr td.today.disabled:hover:active, .datetimepicker table tr td.today.active, .datetimepicker table tr td.today:hover.active, .datetimepicker table tr td.today.disabled.active, .datetimepicker table tr td.today.disabled:hover.active { + background-color: #fbf069; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker table tr td.active, .datetimepicker table tr td.active:hover, .datetimepicker table tr td.active.disabled, .datetimepicker table tr td.active.disabled:hover { + background-color: #006dcc; + background-image: -webkit-gradient(linear, left top, left bottom, from(#08c), to(#04c)); + background-image: linear-gradient(to bottom, #08c, #04c); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc',endColorstr='#0044cc',GradientType=0); + border-color: #04c #04c #002a80; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); + color: #fff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker table tr td.active:hover, .datetimepicker table tr td.active:hover:hover, .datetimepicker table tr td.active.disabled:hover, .datetimepicker table tr td.active.disabled:hover:hover, .datetimepicker table tr td.active:active, .datetimepicker table tr td.active:hover:active, .datetimepicker table tr td.active.disabled:active, .datetimepicker table tr td.active.disabled:hover:active, .datetimepicker table tr td.active.active, .datetimepicker table tr td.active:hover.active, .datetimepicker table tr td.active.disabled.active, .datetimepicker table tr td.active.disabled:hover.active, .datetimepicker table tr td.active.disabled, .datetimepicker table tr td.active:hover.disabled, .datetimepicker table tr td.active.disabled.disabled, .datetimepicker table tr td.active.disabled:hover.disabled, .datetimepicker table tr td.active[disabled], .datetimepicker table tr td.active:hover[disabled], .datetimepicker table tr td.active.disabled[disabled], .datetimepicker table tr td.active.disabled:hover[disabled] { + background-color: #04c; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker table tr td.active:active, .datetimepicker table tr td.active:hover:active, .datetimepicker table tr td.active.disabled:active, .datetimepicker table tr td.active.disabled:hover:active, .datetimepicker table tr td.active.active, .datetimepicker table tr td.active:hover.active, .datetimepicker table tr td.active.disabled.active, .datetimepicker table tr td.active.disabled:hover.active { + background-color: #039; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker table tr td span { + display: block; + width: 23%; + height: 54px; + line-height: 54px; + float: left; + margin: 1%; + cursor: pointer; + border-radius: 4px; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker .datetimepicker-hours span { + height: 26px; + line-height: 26px; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker .datetimepicker-hours table tr td span.hour_am, .datetimepicker .datetimepicker-hours table tr td span.hour_pm { + width: 14.6%; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker .datetimepicker-hours fieldset legend, .datetimepicker .datetimepicker-minutes fieldset legend { + margin-bottom: inherit; + line-height: 30px; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker .datetimepicker-minutes span { + height: 26px; + line-height: 26px; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker table tr td span:hover { + background: #eee; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker table tr td span.disabled, .datetimepicker table tr td span.disabled:hover { + background: 0; + color: #999; + cursor: default; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker table tr td span.active, .datetimepicker table tr td span.active:hover, .datetimepicker table tr td span.active.disabled, .datetimepicker table tr td span.active.disabled:hover { + background-color: #006dcc; + background-image: -webkit-gradient(linear, left top, left bottom, from(#08c), to(#04c)); + background-image: linear-gradient(to bottom, #08c, #04c); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc',endColorstr='#0044cc',GradientType=0); + border-color: #04c #04c #002a80; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); + color: #fff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker table tr td span.active:hover, .datetimepicker table tr td span.active:hover:hover, .datetimepicker table tr td span.active.disabled:hover, .datetimepicker table tr td span.active.disabled:hover:hover, .datetimepicker table tr td span.active:active, .datetimepicker table tr td span.active:hover:active, .datetimepicker table tr td span.active.disabled:active, .datetimepicker table tr td span.active.disabled:hover:active, .datetimepicker table tr td span.active.active, .datetimepicker table tr td span.active:hover.active, .datetimepicker table tr td span.active.disabled.active, .datetimepicker table tr td span.active.disabled:hover.active, .datetimepicker table tr td span.active.disabled, .datetimepicker table tr td span.active:hover.disabled, .datetimepicker table tr td span.active.disabled.disabled, .datetimepicker table tr td span.active.disabled:hover.disabled, .datetimepicker table tr td span.active[disabled], .datetimepicker table tr td span.active:hover[disabled], .datetimepicker table tr td span.active.disabled[disabled], .datetimepicker table tr td span.active.disabled:hover[disabled] { + background-color: #04c; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker table tr td span.active:active, .datetimepicker table tr td span.active:hover:active, .datetimepicker table tr td span.active.disabled:active, .datetimepicker table tr td span.active.disabled:hover:active, .datetimepicker table tr td span.active.active, .datetimepicker table tr td span.active:hover.active, .datetimepicker table tr td span.active.disabled.active, .datetimepicker table tr td span.active.disabled:hover.active { + background-color: #039; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker table tr td span.old { + color: #999; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker th.switch { + width: 145px; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker th span.glyphicon { + pointer-events: none; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker thead tr:first-child th, .datetimepicker tfoot th { + cursor: pointer; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.datetimepicker thead tr:first-child th:hover, .datetimepicker tfoot th:hover { + background: #eee; +} + +/* line 9, app/assets/stylesheets/bootstrap-datetimepicker.min.css */ +.input-append.date .add-on i, .input-prepend.date .add-on i, .input-group.date .input-group-addon span { + cursor: pointer; + width: 14px; + height: 14px; +} + /* BASICS */ /* line 3, vendor/assets/codemirror/lib/codemirror.css */ .CodeMirror { @@ -24775,93 +25131,145 @@ input.form-control { flex: 1; } +/* line 32, app/assets/stylesheets/common.scss */ +.fl { + float: left; +} + /* line 33, app/assets/stylesheets/common.scss */ +.no_padding { + padding: 0px !important; +} + +/* line 34, app/assets/stylesheets/common.scss */ .font-12 { font-size: 12px !important; } -/* line 34, app/assets/stylesheets/common.scss */ +/* line 35, app/assets/stylesheets/common.scss */ .font-14 { font-size: 14px !important; } -/* line 35, app/assets/stylesheets/common.scss */ +/* line 36, app/assets/stylesheets/common.scss */ .font-16 { font-size: 16px !important; } -/* line 36, app/assets/stylesheets/common.scss */ +/* line 37, app/assets/stylesheets/common.scss */ .font-18 { font-size: 18px !important; } -/* line 37, app/assets/stylesheets/common.scss */ +/* line 38, app/assets/stylesheets/common.scss */ +.font-20 { + font-size: 20px !important; +} + +/* line 39, app/assets/stylesheets/common.scss */ +.font-24 { + font-size: 24px !important; +} + +/* line 40, app/assets/stylesheets/common.scss */ .padding10-5 { padding: 10px 5px; } -/* line 38, app/assets/stylesheets/common.scss */ +/* line 41, app/assets/stylesheets/common.scss */ .width100 { width: 100%; } -/* line 39, app/assets/stylesheets/common.scss */ +/* line 42, app/assets/stylesheets/common.scss */ .mb10 { margin-bottom: 10px; } -/* line 40, app/assets/stylesheets/common.scss */ +/* line 43, app/assets/stylesheets/common.scss */ .mt10 { margin-top: 10px; } -/* line 41, app/assets/stylesheets/common.scss */ +/* line 44, app/assets/stylesheets/common.scss */ .mr10 { margin-right: 10px; } -/* line 42, app/assets/stylesheets/common.scss */ +/* line 45, app/assets/stylesheets/common.scss */ +.ml10 { + margin-left: 10px; +} + +/* line 45, app/assets/stylesheets/common.scss */ +.ml20 { + margin-left: 20px; +} + +/* line 46, app/assets/stylesheets/common.scss */ .textarea-width-100 { width: 100%; resize: none; border: 1px solid #ccc; } -/* line 43, app/assets/stylesheets/common.scss */ +/* line 47, app/assets/stylesheets/common.scss */ .padding10 { padding: 10px; } -/* line 44, app/assets/stylesheets/common.scss */ +/* line 48, app/assets/stylesheets/common.scss */ .padding5-10 { padding: 5px 10px; } -/* line 45, app/assets/stylesheets/common.scss */ +/* line 49, app/assets/stylesheets/common.scss */ .position-r { position: relative; } -/* line 46, app/assets/stylesheets/common.scss */ +/* line 50, app/assets/stylesheets/common.scss */ .color-grey-c { color: #ccc; } -/* line 47, app/assets/stylesheets/common.scss */ +/* line 51, app/assets/stylesheets/common.scss */ +.color-blue { + color: #4CACFF; +} + +/* line 52, app/assets/stylesheets/common.scss */ +.color-orange { + color: #ff6800; +} + +/* line 53, app/assets/stylesheets/common.scss */ .inline-block { display: inline-block; } -/* line 48, app/assets/stylesheets/common.scss */ +/* line 54, app/assets/stylesheets/common.scss */ .hide { display: none; } -/* line 49, app/assets/stylesheets/common.scss */ +/* line 55, app/assets/stylesheets/common.scss */ .show { display: block; } +/* line 57, app/assets/stylesheets/common.scss */ +.input_small { + -webkit-box-flex: 0 !important; + flex: 0 0 6% !important; +} + +/* line 58, app/assets/stylesheets/common.scss */ +.input_middle { + -webkit-box-flex: 0 !important; + flex: 0 0 13% !important; +} + /* line 2, app/assets/stylesheets/admins/auth_schools.scss */ .admins-auth-schools-index-page .list-item-title { padding-bottom: 5px; @@ -25171,6 +25579,108 @@ input.form-control { background: #fff; } +/* line 3, app/assets/stylesheets/admins/competition_settings.scss */ +.admins-competition-settings-index-page .competition-mode-container .row { + height: 35px; +} + +/* line 7, app/assets/stylesheets/admins/competition_settings.scss */ +.admins-competition-settings-index-page .competition-mode-container .des-row { + height: auto; +} + +/* line 11, app/assets/stylesheets/admins/competition_settings.scss */ +.admins-competition-settings-index-page .competition-mode-container .form-control { + font-size: 14px; +} + +/* line 22, app/assets/stylesheets/admins/competition_settings.scss */ +.admins-competition-settings-index-page .col-md-label { + -webkit-box-flex: 0; + flex: 0 0 10%; + max-width: 10%; + min-width: 30px; + padding-right: 15px; + padding-left: 15px; + position: relative; +} + +/* line 31, app/assets/stylesheets/admins/competition_settings.scss */ +.admins-competition-settings-index-page .col-md-label-s { + -webkit-box-flex: 0; + flex: 0 0 30px; + padding-right: 15px; + padding-left: 15px; + position: relative; +} + +/* line 38, app/assets/stylesheets/admins/competition_settings.scss */ +.admins-competition-settings-index-page .setBtn_s { + height: 35px; + line-height: 20px; +} + +/* line 43, app/assets/stylesheets/admins/competition_settings.scss */ +.admins-competition-settings-index-page .sponsor_label { + border: 1px solid #4CACFF; + border-radius: 5px; + background-color: rgba(76, 172, 255, 0.3); + color: #333; + padding: 0px 4px; + height: 30px; + line-height: 30px; + float: left; + margin: 4px 5px; +} + +/* line 54, app/assets/stylesheets/admins/competition_settings.scss */ +.admins-competition-settings-index-page .sponsor_label span { + display: block; + float: left; + height: 28px; + line-height: 28px; + margin-right: 5px; +} + +/* line 62, app/assets/stylesheets/admins/competition_settings.scss */ +.admins-competition-settings-index-page .sponsor_label a { + font-size: 18px; + float: left; + height: 28px; + line-height: 28px; +} + +/* line 70, app/assets/stylesheets/admins/competition_settings.scss */ +.admins-competition-settings-index-page .large_panel { + padding: 0px 15px; +} + +/* line 73, app/assets/stylesheets/admins/competition_settings.scss */ +.admins-competition-settings-index-page .large_panel .large_panel_part { + border-top: 1px solid #eaeaea; +} + +/* line 76, app/assets/stylesheets/admins/competition_settings.scss */ +.admins-competition-settings-index-page .large_panel .large_panel_part:first-child { + border: none; +} + +/* line 80, app/assets/stylesheets/admins/competition_settings.scss */ +.admins-competition-settings-index-page .large_panel .large_panel_part > .row, .admins-competition-settings-index-page .large_panel .small_panel > .row { + border-bottom: 1px solid #eaeaea; + padding: 20px 0px; +} + +/* line 84, app/assets/stylesheets/admins/competition_settings.scss */ +.admins-competition-settings-index-page .large_panel .small_panel { + margin-left: 20px; +} + +/* line 87, app/assets/stylesheets/admins/competition_settings.scss */ +.admins-competition-settings-index-page .large_panel .row:last-child { + border: none; +} + /* line 4, app/assets/stylesheets/admins/cooperatives.scss */ .admins-cooperatives-index-page .coo-img-card .coo-img-item > .drag { cursor: move; @@ -26059,7 +26569,7 @@ input.form-control { flex: 3; } -/* line 18, app/assets/stylesheets/admin.scss */ +/* line 19, app/assets/stylesheets/admin.scss */ body { width: 100vw; height: 100vh; @@ -26074,28 +26584,28 @@ body { overflow: hidden; } -/* line 32, app/assets/stylesheets/admin.scss */ +/* line 33, app/assets/stylesheets/admin.scss */ .simple_form .form-group .collection_radio_buttons { margin-bottom: 0px; } -/* line 36, app/assets/stylesheets/admin.scss */ +/* line 37, app/assets/stylesheets/admin.scss */ .simple_form .form-group .form-check-inline { height: calc(1.5em + 0.75rem + 2px); } -/* line 42, app/assets/stylesheets/admin.scss */ +/* line 43, app/assets/stylesheets/admin.scss */ input.form-control { font-size: 14px; } -/* line 46, app/assets/stylesheets/admin.scss */ +/* line 47, app/assets/stylesheets/admin.scss */ .btn-default { color: #666; background: #e1e1e1 !important; } -/* line 50, app/assets/stylesheets/admin.scss */ +/* line 51, app/assets/stylesheets/admin.scss */ .export-absolute { right: 20px; position: absolute; diff --git a/public/assets/admin-46e564d29ffae5c71ae9b5e36dc0bd5de57b10f396eb2005bfb9cf51e7744cdd.css.gz b/public/assets/admin-46e564d29ffae5c71ae9b5e36dc0bd5de57b10f396eb2005bfb9cf51e7744cdd.css.gz new file mode 100644 index 000000000..8ab007ad3 Binary files /dev/null and b/public/assets/admin-46e564d29ffae5c71ae9b5e36dc0bd5de57b10f396eb2005bfb9cf51e7744cdd.css.gz differ diff --git a/public/assets/admin-60d200c1fcdf61a60537d29ccf4479c6b1e5e904208870a63b8ee677c96b347e.css.gz b/public/assets/admin-60d200c1fcdf61a60537d29ccf4479c6b1e5e904208870a63b8ee677c96b347e.css.gz deleted file mode 100644 index 44bb80d0d..000000000 Binary files a/public/assets/admin-60d200c1fcdf61a60537d29ccf4479c6b1e5e904208870a63b8ee677c96b347e.css.gz and /dev/null differ diff --git a/public/assets/admin-6f9bb9720e7e5040ae559a8fae11553313f77552a76416b3a9fe77198471964d.js b/public/assets/admin-6f9bb9720e7e5040ae559a8fae11553313f77552a76416b3a9fe77198471964d.js new file mode 100644 index 000000000..eaae27434 --- /dev/null +++ b/public/assets/admin-6f9bb9720e7e5040ae559a8fae11553313f77552a76416b3a9fe77198471964d.js @@ -0,0 +1,139261 @@ +/* +Unobtrusive JavaScript +https://github.com/rails/rails/blob/master/actionview/app/assets/javascripts +Released under the MIT license + */ + + +(function() { + var context = this; + + (function() { + (function() { + this.Rails = { + linkClickSelector: 'a[data-confirm], a[data-method], a[data-remote]:not([disabled]), a[data-disable-with], a[data-disable]', + buttonClickSelector: { + selector: 'button[data-remote]:not([form]), button[data-confirm]:not([form])', + exclude: 'form button' + }, + inputChangeSelector: 'select[data-remote], input[data-remote], textarea[data-remote]', + formSubmitSelector: 'form', + formInputClickSelector: 'form input[type=submit], form input[type=image], form button[type=submit], form button:not([type]), input[type=submit][form], input[type=image][form], button[type=submit][form], button[form]:not([type])', + formDisableSelector: 'input[data-disable-with]:enabled, button[data-disable-with]:enabled, textarea[data-disable-with]:enabled, input[data-disable]:enabled, button[data-disable]:enabled, textarea[data-disable]:enabled', + formEnableSelector: 'input[data-disable-with]:disabled, button[data-disable-with]:disabled, textarea[data-disable-with]:disabled, input[data-disable]:disabled, button[data-disable]:disabled, textarea[data-disable]:disabled', + fileInputSelector: 'input[name][type=file]:not([disabled])', + linkDisableSelector: 'a[data-disable-with], a[data-disable]', + buttonDisableSelector: 'button[data-remote][data-disable-with], button[data-remote][data-disable]' + }; + + }).call(this); + }).call(context); + + var Rails = context.Rails; + + (function() { + (function() { + var cspNonce; + + cspNonce = Rails.cspNonce = function() { + var meta; + meta = document.querySelector('meta[name=csp-nonce]'); + return meta && meta.content; + }; + + }).call(this); + (function() { + var expando, m; + + m = Element.prototype.matches || Element.prototype.matchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.msMatchesSelector || Element.prototype.oMatchesSelector || Element.prototype.webkitMatchesSelector; + + Rails.matches = function(element, selector) { + if (selector.exclude != null) { + return m.call(element, selector.selector) && !m.call(element, selector.exclude); + } else { + return m.call(element, selector); + } + }; + + expando = '_ujsData'; + + Rails.getData = function(element, key) { + var ref; + return (ref = element[expando]) != null ? ref[key] : void 0; + }; + + Rails.setData = function(element, key, value) { + if (element[expando] == null) { + element[expando] = {}; + } + return element[expando][key] = value; + }; + + Rails.$ = function(selector) { + return Array.prototype.slice.call(document.querySelectorAll(selector)); + }; + + }).call(this); + (function() { + var $, csrfParam, csrfToken; + + $ = Rails.$; + + csrfToken = Rails.csrfToken = function() { + var meta; + meta = document.querySelector('meta[name=csrf-token]'); + return meta && meta.content; + }; + + csrfParam = Rails.csrfParam = function() { + var meta; + meta = document.querySelector('meta[name=csrf-param]'); + return meta && meta.content; + }; + + Rails.CSRFProtection = function(xhr) { + var token; + token = csrfToken(); + if (token != null) { + return xhr.setRequestHeader('X-CSRF-Token', token); + } + }; + + Rails.refreshCSRFTokens = function() { + var param, token; + token = csrfToken(); + param = csrfParam(); + if ((token != null) && (param != null)) { + return $('form input[name="' + param + '"]').forEach(function(input) { + return input.value = token; + }); + } + }; + + }).call(this); + (function() { + var CustomEvent, fire, matches, preventDefault; + + matches = Rails.matches; + + CustomEvent = window.CustomEvent; + + if (typeof CustomEvent !== 'function') { + CustomEvent = function(event, params) { + var evt; + evt = document.createEvent('CustomEvent'); + evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail); + return evt; + }; + CustomEvent.prototype = window.Event.prototype; + preventDefault = CustomEvent.prototype.preventDefault; + CustomEvent.prototype.preventDefault = function() { + var result; + result = preventDefault.call(this); + if (this.cancelable && !this.defaultPrevented) { + Object.defineProperty(this, 'defaultPrevented', { + get: function() { + return true; + } + }); + } + return result; + }; + } + + fire = Rails.fire = function(obj, name, data) { + var event; + event = new CustomEvent(name, { + bubbles: true, + cancelable: true, + detail: data + }); + obj.dispatchEvent(event); + return !event.defaultPrevented; + }; + + Rails.stopEverything = function(e) { + fire(e.target, 'ujs:everythingStopped'); + e.preventDefault(); + e.stopPropagation(); + return e.stopImmediatePropagation(); + }; + + Rails.delegate = function(element, selector, eventType, handler) { + return element.addEventListener(eventType, function(e) { + var target; + target = e.target; + while (!(!(target instanceof Element) || matches(target, selector))) { + target = target.parentNode; + } + if (target instanceof Element && handler.call(target, e) === false) { + e.preventDefault(); + return e.stopPropagation(); + } + }); + }; + + }).call(this); + (function() { + var AcceptHeaders, CSRFProtection, createXHR, cspNonce, fire, prepareOptions, processResponse; + + cspNonce = Rails.cspNonce, CSRFProtection = Rails.CSRFProtection, fire = Rails.fire; + + AcceptHeaders = { + '*': '*/*', + text: 'text/plain', + html: 'text/html', + xml: 'application/xml, text/xml', + json: 'application/json, text/javascript', + script: 'text/javascript, application/javascript, application/ecmascript, application/x-ecmascript' + }; + + Rails.ajax = function(options) { + var xhr; + options = prepareOptions(options); + xhr = createXHR(options, function() { + var ref, response; + response = processResponse((ref = xhr.response) != null ? ref : xhr.responseText, xhr.getResponseHeader('Content-Type')); + if (Math.floor(xhr.status / 100) === 2) { + if (typeof options.success === "function") { + options.success(response, xhr.statusText, xhr); + } + } else { + if (typeof options.error === "function") { + options.error(response, xhr.statusText, xhr); + } + } + return typeof options.complete === "function" ? options.complete(xhr, xhr.statusText) : void 0; + }); + if ((options.beforeSend != null) && !options.beforeSend(xhr, options)) { + return false; + } + if (xhr.readyState === XMLHttpRequest.OPENED) { + return xhr.send(options.data); + } + }; + + prepareOptions = function(options) { + options.url = options.url || location.href; + options.type = options.type.toUpperCase(); + if (options.type === 'GET' && options.data) { + if (options.url.indexOf('?') < 0) { + options.url += '?' + options.data; + } else { + options.url += '&' + options.data; + } + } + if (AcceptHeaders[options.dataType] == null) { + options.dataType = '*'; + } + options.accept = AcceptHeaders[options.dataType]; + if (options.dataType !== '*') { + options.accept += ', */*; q=0.01'; + } + return options; + }; + + createXHR = function(options, done) { + var xhr; + xhr = new XMLHttpRequest(); + xhr.open(options.type, options.url, true); + xhr.setRequestHeader('Accept', options.accept); + if (typeof options.data === 'string') { + xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'); + } + if (!options.crossDomain) { + xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); + } + CSRFProtection(xhr); + xhr.withCredentials = !!options.withCredentials; + xhr.onreadystatechange = function() { + if (xhr.readyState === XMLHttpRequest.DONE) { + return done(xhr); + } + }; + return xhr; + }; + + processResponse = function(response, type) { + var parser, script; + if (typeof response === 'string' && typeof type === 'string') { + if (type.match(/\bjson\b/)) { + try { + response = JSON.parse(response); + } catch (error) {} + } else if (type.match(/\b(?:java|ecma)script\b/)) { + script = document.createElement('script'); + script.setAttribute('nonce', cspNonce()); + script.text = response; + document.head.appendChild(script).parentNode.removeChild(script); + } else if (type.match(/\b(xml|html|svg)\b/)) { + parser = new DOMParser(); + type = type.replace(/;.+/, ''); + try { + response = parser.parseFromString(response, type); + } catch (error) {} + } + } + return response; + }; + + Rails.href = function(element) { + return element.href; + }; + + Rails.isCrossDomain = function(url) { + var e, originAnchor, urlAnchor; + originAnchor = document.createElement('a'); + originAnchor.href = location.href; + urlAnchor = document.createElement('a'); + try { + urlAnchor.href = url; + return !(((!urlAnchor.protocol || urlAnchor.protocol === ':') && !urlAnchor.host) || (originAnchor.protocol + '//' + originAnchor.host === urlAnchor.protocol + '//' + urlAnchor.host)); + } catch (error) { + e = error; + return true; + } + }; + + }).call(this); + (function() { + var matches, toArray; + + matches = Rails.matches; + + toArray = function(e) { + return Array.prototype.slice.call(e); + }; + + Rails.serializeElement = function(element, additionalParam) { + var inputs, params; + inputs = [element]; + if (matches(element, 'form')) { + inputs = toArray(element.elements); + } + params = []; + inputs.forEach(function(input) { + if (!input.name || input.disabled) { + return; + } + if (matches(input, 'select')) { + return toArray(input.options).forEach(function(option) { + if (option.selected) { + return params.push({ + name: input.name, + value: option.value + }); + } + }); + } else if (input.checked || ['radio', 'checkbox', 'submit'].indexOf(input.type) === -1) { + return params.push({ + name: input.name, + value: input.value + }); + } + }); + if (additionalParam) { + params.push(additionalParam); + } + return params.map(function(param) { + if (param.name != null) { + return (encodeURIComponent(param.name)) + "=" + (encodeURIComponent(param.value)); + } else { + return param; + } + }).join('&'); + }; + + Rails.formElements = function(form, selector) { + if (matches(form, 'form')) { + return toArray(form.elements).filter(function(el) { + return matches(el, selector); + }); + } else { + return toArray(form.querySelectorAll(selector)); + } + }; + + }).call(this); + (function() { + var allowAction, fire, stopEverything; + + fire = Rails.fire, stopEverything = Rails.stopEverything; + + Rails.handleConfirm = function(e) { + if (!allowAction(this)) { + return stopEverything(e); + } + }; + + allowAction = function(element) { + var answer, callback, message; + message = element.getAttribute('data-confirm'); + if (!message) { + return true; + } + answer = false; + if (fire(element, 'confirm')) { + try { + answer = confirm(message); + } catch (error) {} + callback = fire(element, 'confirm:complete', [answer]); + } + return answer && callback; + }; + + }).call(this); + (function() { + var disableFormElement, disableFormElements, disableLinkElement, enableFormElement, enableFormElements, enableLinkElement, formElements, getData, matches, setData, stopEverything; + + matches = Rails.matches, getData = Rails.getData, setData = Rails.setData, stopEverything = Rails.stopEverything, formElements = Rails.formElements; + + Rails.handleDisabledElement = function(e) { + var element; + element = this; + if (element.disabled) { + return stopEverything(e); + } + }; + + Rails.enableElement = function(e) { + var element; + element = e instanceof Event ? e.target : e; + if (matches(element, Rails.linkDisableSelector)) { + return enableLinkElement(element); + } else if (matches(element, Rails.buttonDisableSelector) || matches(element, Rails.formEnableSelector)) { + return enableFormElement(element); + } else if (matches(element, Rails.formSubmitSelector)) { + return enableFormElements(element); + } + }; + + Rails.disableElement = function(e) { + var element; + element = e instanceof Event ? e.target : e; + if (matches(element, Rails.linkDisableSelector)) { + return disableLinkElement(element); + } else if (matches(element, Rails.buttonDisableSelector) || matches(element, Rails.formDisableSelector)) { + return disableFormElement(element); + } else if (matches(element, Rails.formSubmitSelector)) { + return disableFormElements(element); + } + }; + + disableLinkElement = function(element) { + var replacement; + replacement = element.getAttribute('data-disable-with'); + if (replacement != null) { + setData(element, 'ujs:enable-with', element.innerHTML); + element.innerHTML = replacement; + } + element.addEventListener('click', stopEverything); + return setData(element, 'ujs:disabled', true); + }; + + enableLinkElement = function(element) { + var originalText; + originalText = getData(element, 'ujs:enable-with'); + if (originalText != null) { + element.innerHTML = originalText; + setData(element, 'ujs:enable-with', null); + } + element.removeEventListener('click', stopEverything); + return setData(element, 'ujs:disabled', null); + }; + + disableFormElements = function(form) { + return formElements(form, Rails.formDisableSelector).forEach(disableFormElement); + }; + + disableFormElement = function(element) { + var replacement; + replacement = element.getAttribute('data-disable-with'); + if (replacement != null) { + if (matches(element, 'button')) { + setData(element, 'ujs:enable-with', element.innerHTML); + element.innerHTML = replacement; + } else { + setData(element, 'ujs:enable-with', element.value); + element.value = replacement; + } + } + element.disabled = true; + return setData(element, 'ujs:disabled', true); + }; + + enableFormElements = function(form) { + return formElements(form, Rails.formEnableSelector).forEach(enableFormElement); + }; + + enableFormElement = function(element) { + var originalText; + originalText = getData(element, 'ujs:enable-with'); + if (originalText != null) { + if (matches(element, 'button')) { + element.innerHTML = originalText; + } else { + element.value = originalText; + } + setData(element, 'ujs:enable-with', null); + } + element.disabled = false; + return setData(element, 'ujs:disabled', null); + }; + + }).call(this); + (function() { + var stopEverything; + + stopEverything = Rails.stopEverything; + + Rails.handleMethod = function(e) { + var csrfParam, csrfToken, form, formContent, href, link, method; + link = this; + method = link.getAttribute('data-method'); + if (!method) { + return; + } + href = Rails.href(link); + csrfToken = Rails.csrfToken(); + csrfParam = Rails.csrfParam(); + form = document.createElement('form'); + formContent = ""; + if ((csrfParam != null) && (csrfToken != null) && !Rails.isCrossDomain(href)) { + formContent += ""; + } + formContent += ''; + form.method = 'post'; + form.action = href; + form.target = link.target; + form.innerHTML = formContent; + form.style.display = 'none'; + document.body.appendChild(form); + form.querySelector('[type="submit"]').click(); + return stopEverything(e); + }; + + }).call(this); + (function() { + var ajax, fire, getData, isCrossDomain, isRemote, matches, serializeElement, setData, stopEverything, + slice = [].slice; + + matches = Rails.matches, getData = Rails.getData, setData = Rails.setData, fire = Rails.fire, stopEverything = Rails.stopEverything, ajax = Rails.ajax, isCrossDomain = Rails.isCrossDomain, serializeElement = Rails.serializeElement; + + isRemote = function(element) { + var value; + value = element.getAttribute('data-remote'); + return (value != null) && value !== 'false'; + }; + + Rails.handleRemote = function(e) { + var button, data, dataType, element, method, url, withCredentials; + element = this; + if (!isRemote(element)) { + return true; + } + if (!fire(element, 'ajax:before')) { + fire(element, 'ajax:stopped'); + return false; + } + withCredentials = element.getAttribute('data-with-credentials'); + dataType = element.getAttribute('data-type') || 'script'; + if (matches(element, Rails.formSubmitSelector)) { + button = getData(element, 'ujs:submit-button'); + method = getData(element, 'ujs:submit-button-formmethod') || element.method; + url = getData(element, 'ujs:submit-button-formaction') || element.getAttribute('action') || location.href; + if (method.toUpperCase() === 'GET') { + url = url.replace(/\?.*$/, ''); + } + if (element.enctype === 'multipart/form-data') { + data = new FormData(element); + if (button != null) { + data.append(button.name, button.value); + } + } else { + data = serializeElement(element, button); + } + setData(element, 'ujs:submit-button', null); + setData(element, 'ujs:submit-button-formmethod', null); + setData(element, 'ujs:submit-button-formaction', null); + } else if (matches(element, Rails.buttonClickSelector) || matches(element, Rails.inputChangeSelector)) { + method = element.getAttribute('data-method'); + url = element.getAttribute('data-url'); + data = serializeElement(element, element.getAttribute('data-params')); + } else { + method = element.getAttribute('data-method'); + url = Rails.href(element); + data = element.getAttribute('data-params'); + } + ajax({ + type: method || 'GET', + url: url, + data: data, + dataType: dataType, + beforeSend: function(xhr, options) { + if (fire(element, 'ajax:beforeSend', [xhr, options])) { + return fire(element, 'ajax:send', [xhr]); + } else { + fire(element, 'ajax:stopped'); + return false; + } + }, + success: function() { + var args; + args = 1 <= arguments.length ? slice.call(arguments, 0) : []; + return fire(element, 'ajax:success', args); + }, + error: function() { + var args; + args = 1 <= arguments.length ? slice.call(arguments, 0) : []; + return fire(element, 'ajax:error', args); + }, + complete: function() { + var args; + args = 1 <= arguments.length ? slice.call(arguments, 0) : []; + return fire(element, 'ajax:complete', args); + }, + crossDomain: isCrossDomain(url), + withCredentials: (withCredentials != null) && withCredentials !== 'false' + }); + return stopEverything(e); + }; + + Rails.formSubmitButtonClick = function(e) { + var button, form; + button = this; + form = button.form; + if (!form) { + return; + } + if (button.name) { + setData(form, 'ujs:submit-button', { + name: button.name, + value: button.value + }); + } + setData(form, 'ujs:formnovalidate-button', button.formNoValidate); + setData(form, 'ujs:submit-button-formaction', button.getAttribute('formaction')); + return setData(form, 'ujs:submit-button-formmethod', button.getAttribute('formmethod')); + }; + + Rails.handleMetaClick = function(e) { + var data, link, metaClick, method; + link = this; + method = (link.getAttribute('data-method') || 'GET').toUpperCase(); + data = link.getAttribute('data-params'); + metaClick = e.metaKey || e.ctrlKey; + if (metaClick && method === 'GET' && !data) { + return e.stopImmediatePropagation(); + } + }; + + }).call(this); + (function() { + var $, CSRFProtection, delegate, disableElement, enableElement, fire, formSubmitButtonClick, getData, handleConfirm, handleDisabledElement, handleMetaClick, handleMethod, handleRemote, refreshCSRFTokens; + + fire = Rails.fire, delegate = Rails.delegate, getData = Rails.getData, $ = Rails.$, refreshCSRFTokens = Rails.refreshCSRFTokens, CSRFProtection = Rails.CSRFProtection, enableElement = Rails.enableElement, disableElement = Rails.disableElement, handleDisabledElement = Rails.handleDisabledElement, handleConfirm = Rails.handleConfirm, handleRemote = Rails.handleRemote, formSubmitButtonClick = Rails.formSubmitButtonClick, handleMetaClick = Rails.handleMetaClick, handleMethod = Rails.handleMethod; + + if ((typeof jQuery !== "undefined" && jQuery !== null) && (jQuery.ajax != null) && !jQuery.rails) { + jQuery.rails = Rails; + jQuery.ajaxPrefilter(function(options, originalOptions, xhr) { + if (!options.crossDomain) { + return CSRFProtection(xhr); + } + }); + } + + Rails.start = function() { + if (window._rails_loaded) { + throw new Error('rails-ujs has already been loaded!'); + } + window.addEventListener('pageshow', function() { + $(Rails.formEnableSelector).forEach(function(el) { + if (getData(el, 'ujs:disabled')) { + return enableElement(el); + } + }); + return $(Rails.linkDisableSelector).forEach(function(el) { + if (getData(el, 'ujs:disabled')) { + return enableElement(el); + } + }); + }); + delegate(document, Rails.linkDisableSelector, 'ajax:complete', enableElement); + delegate(document, Rails.linkDisableSelector, 'ajax:stopped', enableElement); + delegate(document, Rails.buttonDisableSelector, 'ajax:complete', enableElement); + delegate(document, Rails.buttonDisableSelector, 'ajax:stopped', enableElement); + delegate(document, Rails.linkClickSelector, 'click', handleDisabledElement); + delegate(document, Rails.linkClickSelector, 'click', handleConfirm); + delegate(document, Rails.linkClickSelector, 'click', handleMetaClick); + delegate(document, Rails.linkClickSelector, 'click', disableElement); + delegate(document, Rails.linkClickSelector, 'click', handleRemote); + delegate(document, Rails.linkClickSelector, 'click', handleMethod); + delegate(document, Rails.buttonClickSelector, 'click', handleDisabledElement); + delegate(document, Rails.buttonClickSelector, 'click', handleConfirm); + delegate(document, Rails.buttonClickSelector, 'click', disableElement); + delegate(document, Rails.buttonClickSelector, 'click', handleRemote); + delegate(document, Rails.inputChangeSelector, 'change', handleDisabledElement); + delegate(document, Rails.inputChangeSelector, 'change', handleConfirm); + delegate(document, Rails.inputChangeSelector, 'change', handleRemote); + delegate(document, Rails.formSubmitSelector, 'submit', handleDisabledElement); + delegate(document, Rails.formSubmitSelector, 'submit', handleConfirm); + delegate(document, Rails.formSubmitSelector, 'submit', handleRemote); + delegate(document, Rails.formSubmitSelector, 'submit', function(e) { + return setTimeout((function() { + return disableElement(e); + }), 13); + }); + delegate(document, Rails.formSubmitSelector, 'ajax:send', disableElement); + delegate(document, Rails.formSubmitSelector, 'ajax:complete', enableElement); + delegate(document, Rails.formInputClickSelector, 'click', handleDisabledElement); + delegate(document, Rails.formInputClickSelector, 'click', handleConfirm); + delegate(document, Rails.formInputClickSelector, 'click', formSubmitButtonClick); + document.addEventListener('DOMContentLoaded', refreshCSRFTokens); + return window._rails_loaded = true; + }; + + if (window.Rails === Rails && fire(document, 'rails:attachBindings')) { + Rails.start(); + } + + }).call(this); + }).call(this); + + if (typeof module === "object" && module.exports) { + module.exports = Rails; + } else if (typeof define === "function" && define.amd) { + define(Rails); + } +}).call(this); +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.ActiveStorage=e():t.ActiveStorage=e()}(this,function(){return function(t){function e(n){if(r[n])return r[n].exports;var i=r[n]={i:n,l:!1,exports:{}};return t[n].call(i.exports,i,i.exports,e),i.l=!0,i.exports}var r={};return e.m=t,e.c=r,e.d=function(t,r,n){e.o(t,r)||Object.defineProperty(t,r,{configurable:!1,enumerable:!0,get:n})},e.n=function(t){var r=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(r,"a",r),r},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="",e(e.s=2)}([function(t,e,r){"use strict";function n(t){var e=a(document.head,'meta[name="'+t+'"]');if(e)return e.getAttribute("content")}function i(t,e){return"string"==typeof t&&(e=t,t=document),o(t.querySelectorAll(e))}function a(t,e){return"string"==typeof t&&(e=t,t=document),t.querySelector(e)}function u(t,e){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},n=t.disabled,i=r.bubbles,a=r.cancelable,u=r.detail,o=document.createEvent("Event");o.initEvent(e,i||!0,a||!0),o.detail=u||{};try{t.disabled=!1,t.dispatchEvent(o)}finally{t.disabled=n}return o}function o(t){return Array.isArray(t)?t:Array.from?Array.from(t):[].slice.call(t)}e.d=n,e.c=i,e.b=a,e.a=u,e.e=o},function(t,e,r){"use strict";function n(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function i(t,e){if(t&&"function"==typeof t[e]){for(var r=arguments.length,n=Array(r>2?r-2:0),i=2;i1&&void 0!==arguments[1]?arguments[1]:{};return Object(a.a)(this.form,"direct-uploads:"+t,{detail:e})}}]),t}()},function(t,e,r){"use strict";function n(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}r.d(e,"a",function(){return o});var i=r(1),a=r(0),u=function(){function t(t,e){for(var r=0;r1&&void 0!==arguments[1]?arguments[1]:{};return e.file=this.file,e.id=this.directUpload.id,Object(a.a)(this.input,"direct-upload:"+t,{detail:e})}},{key:"dispatchError",value:function(t){this.dispatch("error",{error:t}).defaultPrevented||alert(t)}},{key:"directUploadWillCreateBlobWithXHR",value:function(t){this.dispatch("before-blob-request",{xhr:t})}},{key:"directUploadWillStoreFileWithXHR",value:function(t){var e=this;this.dispatch("before-storage-request",{xhr:t}),t.upload.addEventListener("progress",function(t){return e.uploadRequestDidProgress(t)})}},{key:"url",get:function(){return this.input.getAttribute("data-direct-upload-url")}}]),t}()},function(t,e,r){"use strict";function n(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}r.d(e,"a",function(){return s});var i=r(7),a=r.n(i),u=function(){function t(t,e){for(var r=0;r>>25)+n|0,a+=(r&n|~r&i)+e[1]-389564586|0,a=(a<<12|a>>>20)+r|0,i+=(a&r|~a&n)+e[2]+606105819|0,i=(i<<17|i>>>15)+a|0,n+=(i&a|~i&r)+e[3]-1044525330|0,n=(n<<22|n>>>10)+i|0,r+=(n&i|~n&a)+e[4]-176418897|0,r=(r<<7|r>>>25)+n|0,a+=(r&n|~r&i)+e[5]+1200080426|0,a=(a<<12|a>>>20)+r|0,i+=(a&r|~a&n)+e[6]-1473231341|0,i=(i<<17|i>>>15)+a|0,n+=(i&a|~i&r)+e[7]-45705983|0,n=(n<<22|n>>>10)+i|0,r+=(n&i|~n&a)+e[8]+1770035416|0,r=(r<<7|r>>>25)+n|0,a+=(r&n|~r&i)+e[9]-1958414417|0,a=(a<<12|a>>>20)+r|0,i+=(a&r|~a&n)+e[10]-42063|0,i=(i<<17|i>>>15)+a|0,n+=(i&a|~i&r)+e[11]-1990404162|0,n=(n<<22|n>>>10)+i|0,r+=(n&i|~n&a)+e[12]+1804603682|0,r=(r<<7|r>>>25)+n|0,a+=(r&n|~r&i)+e[13]-40341101|0,a=(a<<12|a>>>20)+r|0,i+=(a&r|~a&n)+e[14]-1502002290|0,i=(i<<17|i>>>15)+a|0,n+=(i&a|~i&r)+e[15]+1236535329|0,n=(n<<22|n>>>10)+i|0,r+=(n&a|i&~a)+e[1]-165796510|0,r=(r<<5|r>>>27)+n|0,a+=(r&i|n&~i)+e[6]-1069501632|0,a=(a<<9|a>>>23)+r|0,i+=(a&n|r&~n)+e[11]+643717713|0,i=(i<<14|i>>>18)+a|0,n+=(i&r|a&~r)+e[0]-373897302|0,n=(n<<20|n>>>12)+i|0,r+=(n&a|i&~a)+e[5]-701558691|0,r=(r<<5|r>>>27)+n|0,a+=(r&i|n&~i)+e[10]+38016083|0,a=(a<<9|a>>>23)+r|0,i+=(a&n|r&~n)+e[15]-660478335|0,i=(i<<14|i>>>18)+a|0,n+=(i&r|a&~r)+e[4]-405537848|0,n=(n<<20|n>>>12)+i|0,r+=(n&a|i&~a)+e[9]+568446438|0,r=(r<<5|r>>>27)+n|0,a+=(r&i|n&~i)+e[14]-1019803690|0,a=(a<<9|a>>>23)+r|0,i+=(a&n|r&~n)+e[3]-187363961|0,i=(i<<14|i>>>18)+a|0,n+=(i&r|a&~r)+e[8]+1163531501|0,n=(n<<20|n>>>12)+i|0,r+=(n&a|i&~a)+e[13]-1444681467|0,r=(r<<5|r>>>27)+n|0,a+=(r&i|n&~i)+e[2]-51403784|0,a=(a<<9|a>>>23)+r|0,i+=(a&n|r&~n)+e[7]+1735328473|0,i=(i<<14|i>>>18)+a|0,n+=(i&r|a&~r)+e[12]-1926607734|0,n=(n<<20|n>>>12)+i|0,r+=(n^i^a)+e[5]-378558|0,r=(r<<4|r>>>28)+n|0,a+=(r^n^i)+e[8]-2022574463|0,a=(a<<11|a>>>21)+r|0,i+=(a^r^n)+e[11]+1839030562|0,i=(i<<16|i>>>16)+a|0,n+=(i^a^r)+e[14]-35309556|0,n=(n<<23|n>>>9)+i|0,r+=(n^i^a)+e[1]-1530992060|0,r=(r<<4|r>>>28)+n|0,a+=(r^n^i)+e[4]+1272893353|0,a=(a<<11|a>>>21)+r|0,i+=(a^r^n)+e[7]-155497632|0,i=(i<<16|i>>>16)+a|0,n+=(i^a^r)+e[10]-1094730640|0,n=(n<<23|n>>>9)+i|0,r+=(n^i^a)+e[13]+681279174|0,r=(r<<4|r>>>28)+n|0,a+=(r^n^i)+e[0]-358537222|0,a=(a<<11|a>>>21)+r|0,i+=(a^r^n)+e[3]-722521979|0,i=(i<<16|i>>>16)+a|0,n+=(i^a^r)+e[6]+76029189|0,n=(n<<23|n>>>9)+i|0,r+=(n^i^a)+e[9]-640364487|0,r=(r<<4|r>>>28)+n|0,a+=(r^n^i)+e[12]-421815835|0,a=(a<<11|a>>>21)+r|0,i+=(a^r^n)+e[15]+530742520|0,i=(i<<16|i>>>16)+a|0,n+=(i^a^r)+e[2]-995338651|0,n=(n<<23|n>>>9)+i|0,r+=(i^(n|~a))+e[0]-198630844|0,r=(r<<6|r>>>26)+n|0,a+=(n^(r|~i))+e[7]+1126891415|0,a=(a<<10|a>>>22)+r|0,i+=(r^(a|~n))+e[14]-1416354905|0,i=(i<<15|i>>>17)+a|0,n+=(a^(i|~r))+e[5]-57434055|0,n=(n<<21|n>>>11)+i|0,r+=(i^(n|~a))+e[12]+1700485571|0,r=(r<<6|r>>>26)+n|0,a+=(n^(r|~i))+e[3]-1894986606|0,a=(a<<10|a>>>22)+r|0,i+=(r^(a|~n))+e[10]-1051523|0,i=(i<<15|i>>>17)+a|0,n+=(a^(i|~r))+e[1]-2054922799|0,n=(n<<21|n>>>11)+i|0,r+=(i^(n|~a))+e[8]+1873313359|0,r=(r<<6|r>>>26)+n|0,a+=(n^(r|~i))+e[15]-30611744|0,a=(a<<10|a>>>22)+r|0,i+=(r^(a|~n))+e[6]-1560198380|0,i=(i<<15|i>>>17)+a|0,n+=(a^(i|~r))+e[13]+1309151649|0,n=(n<<21|n>>>11)+i|0,r+=(i^(n|~a))+e[4]-145523070|0,r=(r<<6|r>>>26)+n|0,a+=(n^(r|~i))+e[11]-1120210379|0,a=(a<<10|a>>>22)+r|0,i+=(r^(a|~n))+e[2]+718787259|0,i=(i<<15|i>>>17)+a|0,n+=(a^(i|~r))+e[9]-343485551|0,n=(n<<21|n>>>11)+i|0,t[0]=r+t[0]|0,t[1]=n+t[1]|0,t[2]=i+t[2]|0,t[3]=a+t[3]|0}function r(t){var e,r=[];for(e=0;e<64;e+=4)r[e>>2]=t.charCodeAt(e)+(t.charCodeAt(e+1)<<8)+(t.charCodeAt(e+2)<<16)+(t.charCodeAt(e+3)<<24);return r}function n(t){var e,r=[];for(e=0;e<64;e+=4)r[e>>2]=t[e]+(t[e+1]<<8)+(t[e+2]<<16)+(t[e+3]<<24);return r}function i(t){var n,i,a,u,o,s,f=t.length,c=[1732584193,-271733879,-1732584194,271733878];for(n=64;n<=f;n+=64)e(c,r(t.substring(n-64,n)));for(t=t.substring(n-64),i=t.length,a=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],n=0;n>2]|=t.charCodeAt(n)<<(n%4<<3);if(a[n>>2]|=128<<(n%4<<3),n>55)for(e(c,a),n=0;n<16;n+=1)a[n]=0;return u=8*f,u=u.toString(16).match(/(.*?)(.{0,8})$/),o=parseInt(u[2],16),s=parseInt(u[1],16)||0,a[14]=o,a[15]=s,e(c,a),c}function a(t){var r,i,a,u,o,s,f=t.length,c=[1732584193,-271733879,-1732584194,271733878];for(r=64;r<=f;r+=64)e(c,n(t.subarray(r-64,r)));for(t=r-64>2]|=t[r]<<(r%4<<3);if(a[r>>2]|=128<<(r%4<<3),r>55)for(e(c,a),r=0;r<16;r+=1)a[r]=0;return u=8*f,u=u.toString(16).match(/(.*?)(.{0,8})$/),o=parseInt(u[2],16),s=parseInt(u[1],16)||0,a[14]=o,a[15]=s,e(c,a),c}function u(t){var e,r="";for(e=0;e<4;e+=1)r+=p[t>>8*e+4&15]+p[t>>8*e&15];return r}function o(t){var e;for(e=0;e>16)+(e>>16)+(r>>16)<<16|65535&r},"undefined"==typeof ArrayBuffer||ArrayBuffer.prototype.slice||function(){function e(t,e){return t=0|t||0,t<0?Math.max(t+e,0):Math.min(t,e)}ArrayBuffer.prototype.slice=function(r,n){var i,a,u,o,s=this.byteLength,f=e(r,s),c=s;return n!==t&&(c=e(n,s)),f>c?new ArrayBuffer(0):(i=c-f,a=new ArrayBuffer(i),u=new Uint8Array(a),o=new Uint8Array(this,f,i),u.set(o),a)}}(),d.prototype.append=function(t){return this.appendBinary(s(t)),this},d.prototype.appendBinary=function(t){this._buff+=t,this._length+=t.length;var n,i=this._buff.length;for(n=64;n<=i;n+=64)e(this._hash,r(this._buff.substring(n-64,n)));return this._buff=this._buff.substring(n-64),this},d.prototype.end=function(t){var e,r,n=this._buff,i=n.length,a=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];for(e=0;e>2]|=n.charCodeAt(e)<<(e%4<<3);return this._finish(a,i),r=o(this._hash),t&&(r=l(r)),this.reset(),r},d.prototype.reset=function(){return this._buff="",this._length=0,this._hash=[1732584193,-271733879,-1732584194,271733878],this},d.prototype.getState=function(){return{buff:this._buff,length:this._length,hash:this._hash}},d.prototype.setState=function(t){return this._buff=t.buff,this._length=t.length,this._hash=t.hash,this},d.prototype.destroy=function(){delete this._hash,delete this._buff,delete this._length},d.prototype._finish=function(t,r){var n,i,a,u=r;if(t[u>>2]|=128<<(u%4<<3),u>55)for(e(this._hash,t),u=0;u<16;u+=1)t[u]=0;n=8*this._length,n=n.toString(16).match(/(.*?)(.{0,8})$/),i=parseInt(n[2],16),a=parseInt(n[1],16)||0,t[14]=i,t[15]=a,e(this._hash,t)},d.hash=function(t,e){return d.hashBinary(s(t),e)},d.hashBinary=function(t,e){var r=i(t),n=o(r);return e?l(n):n},d.ArrayBuffer=function(){this.reset()},d.ArrayBuffer.prototype.append=function(t){var r,i=h(this._buff.buffer,t,!0),a=i.length;for(this._length+=t.byteLength,r=64;r<=a;r+=64)e(this._hash,n(i.subarray(r-64,r)));return this._buff=r-64>2]|=n[e]<<(e%4<<3);return this._finish(a,i),r=o(this._hash),t&&(r=l(r)),this.reset(),r},d.ArrayBuffer.prototype.reset=function(){return this._buff=new Uint8Array(0),this._length=0,this._hash=[1732584193,-271733879,-1732584194,271733878],this},d.ArrayBuffer.prototype.getState=function(){var t=d.prototype.getState.call(this);return t.buff=c(t.buff),t},d.ArrayBuffer.prototype.setState=function(t){return t.buff=f(t.buff,!0),d.prototype.setState.call(this,t)},d.ArrayBuffer.prototype.destroy=d.prototype.destroy,d.ArrayBuffer.prototype._finish=d.prototype._finish,d.ArrayBuffer.hash=function(t,e){var r=a(new Uint8Array(t)),n=o(r);return e?l(n):n},d})},function(t,e,r){"use strict";function n(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}r.d(e,"a",function(){return u});var i=r(0),a=function(){function t(t,e){for(var r=0;r=200&&this.status<300){var e=this.response,r=e.direct_upload;delete e.direct_upload,this.attributes=e,this.directUploadData=r,this.callback(null,this.toJSON())}else this.requestDidError(t)}},{key:"requestDidError",value:function(t){this.callback('Error creating Blob for "'+this.file.name+'". Status: '+this.status)}},{key:"toJSON",value:function(){var t={};for(var e in this.attributes)t[e]=this.attributes[e];return t}},{key:"status",get:function(){return this.xhr.status}},{key:"response",get:function(){var t=this.xhr,e=t.responseType,r=t.response;return"json"==e?r:JSON.parse(r)}}]),t}()},function(t,e,r){"use strict";function n(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}r.d(e,"a",function(){return a});var i=function(){function t(t,e){for(var r=0;r=200&&r<300?this.callback(null,n):this.requestDidError(t)}},{key:"requestDidError",value:function(t){this.callback('Error storing "'+this.file.name+'". Status: '+this.xhr.status)}}]),t}()}])}); +/* +Turbolinks 5.2.0 +Copyright © 2018 Basecamp, LLC + */ + +(function(){var t=this;(function(){(function(){this.Turbolinks={supported:function(){return null!=window.history.pushState&&null!=window.requestAnimationFrame&&null!=window.addEventListener}(),visit:function(t,r){return e.controller.visit(t,r)},clearCache:function(){return e.controller.clearCache()},setProgressBarDelay:function(t){return e.controller.setProgressBarDelay(t)}}}).call(this)}).call(t);var e=t.Turbolinks;(function(){(function(){var t,r,n,o=[].slice;e.copyObject=function(t){var e,r,n;r={};for(e in t)n=t[e],r[e]=n;return r},e.closest=function(e,r){return t.call(e,r)},t=function(){var t,e;return t=document.documentElement,null!=(e=t.closest)?e:function(t){var e;for(e=this;e;){if(e.nodeType===Node.ELEMENT_NODE&&r.call(e,t))return e;e=e.parentNode}}}(),e.defer=function(t){return setTimeout(t,1)},e.throttle=function(t){var e;return e=null,function(){var r;return r=1<=arguments.length?o.call(arguments,0):[],null!=e?e:e=requestAnimationFrame(function(n){return function(){return e=null,t.apply(n,r)}}(this))}},e.dispatch=function(t,e){var r,o,i,s,a,u;return a=null!=e?e:{},u=a.target,r=a.cancelable,o=a.data,i=document.createEvent("Events"),i.initEvent(t,!0,r===!0),i.data=null!=o?o:{},i.cancelable&&!n&&(s=i.preventDefault,i.preventDefault=function(){return this.defaultPrevented||Object.defineProperty(this,"defaultPrevented",{get:function(){return!0}}),s.call(this)}),(null!=u?u:document).dispatchEvent(i),i},n=function(){var t;return t=document.createEvent("Events"),t.initEvent("test",!0,!0),t.preventDefault(),t.defaultPrevented}(),e.match=function(t,e){return r.call(t,e)},r=function(){var t,e,r,n;return t=document.documentElement,null!=(e=null!=(r=null!=(n=t.matchesSelector)?n:t.webkitMatchesSelector)?r:t.msMatchesSelector)?e:t.mozMatchesSelector}(),e.uuid=function(){var t,e,r;for(r="",t=e=1;36>=e;t=++e)r+=9===t||14===t||19===t||24===t?"-":15===t?"4":20===t?(Math.floor(4*Math.random())+8).toString(16):Math.floor(15*Math.random()).toString(16);return r}}).call(this),function(){e.Location=function(){function t(t){var e,r;null==t&&(t=""),r=document.createElement("a"),r.href=t.toString(),this.absoluteURL=r.href,e=r.hash.length,2>e?this.requestURL=this.absoluteURL:(this.requestURL=this.absoluteURL.slice(0,-e),this.anchor=r.hash.slice(1))}var e,r,n,o;return t.wrap=function(t){return t instanceof this?t:new this(t)},t.prototype.getOrigin=function(){return this.absoluteURL.split("/",3).join("/")},t.prototype.getPath=function(){var t,e;return null!=(t=null!=(e=this.requestURL.match(/\/\/[^\/]*(\/[^?;]*)/))?e[1]:void 0)?t:"/"},t.prototype.getPathComponents=function(){return this.getPath().split("/").slice(1)},t.prototype.getLastPathComponent=function(){return this.getPathComponents().slice(-1)[0]},t.prototype.getExtension=function(){var t,e;return null!=(t=null!=(e=this.getLastPathComponent().match(/\.[^.]*$/))?e[0]:void 0)?t:""},t.prototype.isHTML=function(){return this.getExtension().match(/^(?:|\.(?:htm|html|xhtml))$/)},t.prototype.isPrefixedBy=function(t){var e;return e=r(t),this.isEqualTo(t)||o(this.absoluteURL,e)},t.prototype.isEqualTo=function(t){return this.absoluteURL===(null!=t?t.absoluteURL:void 0)},t.prototype.toCacheKey=function(){return this.requestURL},t.prototype.toJSON=function(){return this.absoluteURL},t.prototype.toString=function(){return this.absoluteURL},t.prototype.valueOf=function(){return this.absoluteURL},r=function(t){return e(t.getOrigin()+t.getPath())},e=function(t){return n(t,"/")?t:t+"/"},o=function(t,e){return t.slice(0,e.length)===e},n=function(t,e){return t.slice(-e.length)===e},t}()}.call(this),function(){var t=function(t,e){return function(){return t.apply(e,arguments)}};e.HttpRequest=function(){function r(r,n,o){this.delegate=r,this.requestCanceled=t(this.requestCanceled,this),this.requestTimedOut=t(this.requestTimedOut,this),this.requestFailed=t(this.requestFailed,this),this.requestLoaded=t(this.requestLoaded,this),this.requestProgressed=t(this.requestProgressed,this),this.url=e.Location.wrap(n).requestURL,this.referrer=e.Location.wrap(o).absoluteURL,this.createXHR()}return r.NETWORK_FAILURE=0,r.TIMEOUT_FAILURE=-1,r.timeout=60,r.prototype.send=function(){var t;return this.xhr&&!this.sent?(this.notifyApplicationBeforeRequestStart(),this.setProgress(0),this.xhr.send(),this.sent=!0,"function"==typeof(t=this.delegate).requestStarted?t.requestStarted():void 0):void 0},r.prototype.cancel=function(){return this.xhr&&this.sent?this.xhr.abort():void 0},r.prototype.requestProgressed=function(t){return t.lengthComputable?this.setProgress(t.loaded/t.total):void 0},r.prototype.requestLoaded=function(){return this.endRequest(function(t){return function(){var e;return 200<=(e=t.xhr.status)&&300>e?t.delegate.requestCompletedWithResponse(t.xhr.responseText,t.xhr.getResponseHeader("Turbolinks-Location")):(t.failed=!0,t.delegate.requestFailedWithStatusCode(t.xhr.status,t.xhr.responseText))}}(this))},r.prototype.requestFailed=function(){return this.endRequest(function(t){return function(){return t.failed=!0,t.delegate.requestFailedWithStatusCode(t.constructor.NETWORK_FAILURE)}}(this))},r.prototype.requestTimedOut=function(){return this.endRequest(function(t){return function(){return t.failed=!0,t.delegate.requestFailedWithStatusCode(t.constructor.TIMEOUT_FAILURE)}}(this))},r.prototype.requestCanceled=function(){return this.endRequest()},r.prototype.notifyApplicationBeforeRequestStart=function(){return e.dispatch("turbolinks:request-start",{data:{url:this.url,xhr:this.xhr}})},r.prototype.notifyApplicationAfterRequestEnd=function(){return e.dispatch("turbolinks:request-end",{data:{url:this.url,xhr:this.xhr}})},r.prototype.createXHR=function(){return this.xhr=new XMLHttpRequest,this.xhr.open("GET",this.url,!0),this.xhr.timeout=1e3*this.constructor.timeout,this.xhr.setRequestHeader("Accept","text/html, application/xhtml+xml"),this.xhr.setRequestHeader("Turbolinks-Referrer",this.referrer),this.xhr.onprogress=this.requestProgressed,this.xhr.onload=this.requestLoaded,this.xhr.onerror=this.requestFailed,this.xhr.ontimeout=this.requestTimedOut,this.xhr.onabort=this.requestCanceled},r.prototype.endRequest=function(t){return this.xhr?(this.notifyApplicationAfterRequestEnd(),null!=t&&t.call(this),this.destroy()):void 0},r.prototype.setProgress=function(t){var e;return this.progress=t,"function"==typeof(e=this.delegate).requestProgressed?e.requestProgressed(this.progress):void 0},r.prototype.destroy=function(){var t;return this.setProgress(1),"function"==typeof(t=this.delegate).requestFinished&&t.requestFinished(),this.delegate=null,this.xhr=null},r}()}.call(this),function(){var t=function(t,e){return function(){return t.apply(e,arguments)}};e.ProgressBar=function(){function e(){this.trickle=t(this.trickle,this),this.stylesheetElement=this.createStylesheetElement(),this.progressElement=this.createProgressElement()}var r;return r=300,e.defaultCSS=".turbolinks-progress-bar {\n position: fixed;\n display: block;\n top: 0;\n left: 0;\n height: 3px;\n background: #0076ff;\n z-index: 9999;\n transition: width "+r+"ms ease-out, opacity "+r/2+"ms "+r/2+"ms ease-in;\n transform: translate3d(0, 0, 0);\n}",e.prototype.show=function(){return this.visible?void 0:(this.visible=!0,this.installStylesheetElement(),this.installProgressElement(),this.startTrickling())},e.prototype.hide=function(){return this.visible&&!this.hiding?(this.hiding=!0,this.fadeProgressElement(function(t){return function(){return t.uninstallProgressElement(),t.stopTrickling(),t.visible=!1,t.hiding=!1}}(this))):void 0},e.prototype.setValue=function(t){return this.value=t,this.refresh()},e.prototype.installStylesheetElement=function(){return document.head.insertBefore(this.stylesheetElement,document.head.firstChild)},e.prototype.installProgressElement=function(){return this.progressElement.style.width=0,this.progressElement.style.opacity=1,document.documentElement.insertBefore(this.progressElement,document.body),this.refresh()},e.prototype.fadeProgressElement=function(t){return this.progressElement.style.opacity=0,setTimeout(t,1.5*r)},e.prototype.uninstallProgressElement=function(){return this.progressElement.parentNode?document.documentElement.removeChild(this.progressElement):void 0},e.prototype.startTrickling=function(){return null!=this.trickleInterval?this.trickleInterval:this.trickleInterval=setInterval(this.trickle,r)},e.prototype.stopTrickling=function(){return clearInterval(this.trickleInterval),this.trickleInterval=null},e.prototype.trickle=function(){return this.setValue(this.value+Math.random()/100)},e.prototype.refresh=function(){return requestAnimationFrame(function(t){return function(){return t.progressElement.style.width=10+90*t.value+"%"}}(this))},e.prototype.createStylesheetElement=function(){var t;return t=document.createElement("style"),t.type="text/css",t.textContent=this.constructor.defaultCSS,t},e.prototype.createProgressElement=function(){var t;return t=document.createElement("div"),t.className="turbolinks-progress-bar",t},e}()}.call(this),function(){var t=function(t,e){return function(){return t.apply(e,arguments)}};e.BrowserAdapter=function(){function r(r){this.controller=r,this.showProgressBar=t(this.showProgressBar,this),this.progressBar=new e.ProgressBar}var n,o,i;return i=e.HttpRequest,n=i.NETWORK_FAILURE,o=i.TIMEOUT_FAILURE,r.prototype.visitProposedToLocationWithAction=function(t,e){return this.controller.startVisitToLocationWithAction(t,e)},r.prototype.visitStarted=function(t){return t.issueRequest(),t.changeHistory(),t.loadCachedSnapshot()},r.prototype.visitRequestStarted=function(t){return this.progressBar.setValue(0),t.hasCachedSnapshot()||"restore"!==t.action?this.showProgressBarAfterDelay():this.showProgressBar()},r.prototype.visitRequestProgressed=function(t){return this.progressBar.setValue(t.progress)},r.prototype.visitRequestCompleted=function(t){return t.loadResponse()},r.prototype.visitRequestFailedWithStatusCode=function(t,e){switch(e){case n:case o:return this.reload();default:return t.loadResponse()}},r.prototype.visitRequestFinished=function(t){return this.hideProgressBar()},r.prototype.visitCompleted=function(t){return t.followRedirect()},r.prototype.pageInvalidated=function(){return this.reload()},r.prototype.showProgressBarAfterDelay=function(){return this.progressBarTimeout=setTimeout(this.showProgressBar,this.controller.progressBarDelay)},r.prototype.showProgressBar=function(){return this.progressBar.show()},r.prototype.hideProgressBar=function(){return this.progressBar.hide(),clearTimeout(this.progressBarTimeout)},r.prototype.reload=function(){return window.location.reload()},r}()}.call(this),function(){var t=function(t,e){return function(){return t.apply(e,arguments)}};e.History=function(){function r(e){this.delegate=e,this.onPageLoad=t(this.onPageLoad,this),this.onPopState=t(this.onPopState,this)}return r.prototype.start=function(){return this.started?void 0:(addEventListener("popstate",this.onPopState,!1),addEventListener("load",this.onPageLoad,!1),this.started=!0)},r.prototype.stop=function(){return this.started?(removeEventListener("popstate",this.onPopState,!1),removeEventListener("load",this.onPageLoad,!1),this.started=!1):void 0},r.prototype.push=function(t,r){return t=e.Location.wrap(t),this.update("push",t,r)},r.prototype.replace=function(t,r){return t=e.Location.wrap(t),this.update("replace",t,r)},r.prototype.onPopState=function(t){var r,n,o,i;return this.shouldHandlePopState()&&(i=null!=(n=t.state)?n.turbolinks:void 0)?(r=e.Location.wrap(window.location),o=i.restorationIdentifier,this.delegate.historyPoppedToLocationWithRestorationIdentifier(r,o)):void 0},r.prototype.onPageLoad=function(t){return e.defer(function(t){return function(){return t.pageLoaded=!0}}(this))},r.prototype.shouldHandlePopState=function(){return this.pageIsLoaded()},r.prototype.pageIsLoaded=function(){return this.pageLoaded||"complete"===document.readyState},r.prototype.update=function(t,e,r){var n;return n={turbolinks:{restorationIdentifier:r}},history[t+"State"](n,null,e)},r}()}.call(this),function(){e.HeadDetails=function(){function t(t){var e,r,n,s,a,u;for(this.elements={},n=0,a=t.length;a>n;n++)u=t[n],u.nodeType===Node.ELEMENT_NODE&&(s=u.outerHTML,r=null!=(e=this.elements)[s]?e[s]:e[s]={type:i(u),tracked:o(u),elements:[]},r.elements.push(u))}var e,r,n,o,i;return t.fromHeadElement=function(t){var e;return new this(null!=(e=null!=t?t.childNodes:void 0)?e:[])},t.prototype.hasElementWithKey=function(t){return t in this.elements},t.prototype.getTrackedElementSignature=function(){var t,e;return function(){var r,n;r=this.elements,n=[];for(t in r)e=r[t].tracked,e&&n.push(t);return n}.call(this).join("")},t.prototype.getScriptElementsNotInDetails=function(t){return this.getElementsMatchingTypeNotInDetails("script",t)},t.prototype.getStylesheetElementsNotInDetails=function(t){return this.getElementsMatchingTypeNotInDetails("stylesheet",t)},t.prototype.getElementsMatchingTypeNotInDetails=function(t,e){var r,n,o,i,s,a;o=this.elements,s=[];for(n in o)i=o[n],a=i.type,r=i.elements,a!==t||e.hasElementWithKey(n)||s.push(r[0]);return s},t.prototype.getProvisionalElements=function(){var t,e,r,n,o,i,s;r=[],n=this.elements;for(e in n)o=n[e],s=o.type,i=o.tracked,t=o.elements,null!=s||i?t.length>1&&r.push.apply(r,t.slice(1)):r.push.apply(r,t);return r},t.prototype.getMetaValue=function(t){var e;return null!=(e=this.findMetaElementByName(t))?e.getAttribute("content"):void 0},t.prototype.findMetaElementByName=function(t){var r,n,o,i;r=void 0,i=this.elements;for(o in i)n=i[o].elements,e(n[0],t)&&(r=n[0]);return r},i=function(t){return r(t)?"script":n(t)?"stylesheet":void 0},o=function(t){return"reload"===t.getAttribute("data-turbolinks-track")},r=function(t){var e;return e=t.tagName.toLowerCase(),"script"===e},n=function(t){var e;return e=t.tagName.toLowerCase(),"style"===e||"link"===e&&"stylesheet"===t.getAttribute("rel")},e=function(t,e){var r;return r=t.tagName.toLowerCase(),"meta"===r&&t.getAttribute("name")===e},t}()}.call(this),function(){e.Snapshot=function(){function t(t,e){this.headDetails=t,this.bodyElement=e}return t.wrap=function(t){return t instanceof this?t:"string"==typeof t?this.fromHTMLString(t):this.fromHTMLElement(t)},t.fromHTMLString=function(t){var e;return e=document.createElement("html"),e.innerHTML=t,this.fromHTMLElement(e)},t.fromHTMLElement=function(t){var r,n,o,i;return o=t.querySelector("head"),r=null!=(i=t.querySelector("body"))?i:document.createElement("body"),n=e.HeadDetails.fromHeadElement(o),new this(n,r)},t.prototype.clone=function(){return new this.constructor(this.headDetails,this.bodyElement.cloneNode(!0))},t.prototype.getRootLocation=function(){var t,r;return r=null!=(t=this.getSetting("root"))?t:"/",new e.Location(r)},t.prototype.getCacheControlValue=function(){return this.getSetting("cache-control")},t.prototype.getElementForAnchor=function(t){try{return this.bodyElement.querySelector("[id='"+t+"'], a[name='"+t+"']")}catch(e){}},t.prototype.getPermanentElements=function(){return this.bodyElement.querySelectorAll("[id][data-turbolinks-permanent]")},t.prototype.getPermanentElementById=function(t){return this.bodyElement.querySelector("#"+t+"[data-turbolinks-permanent]")},t.prototype.getPermanentElementsPresentInSnapshot=function(t){var e,r,n,o,i;for(o=this.getPermanentElements(),i=[],r=0,n=o.length;n>r;r++)e=o[r],t.getPermanentElementById(e.id)&&i.push(e);return i},t.prototype.findFirstAutofocusableElement=function(){return this.bodyElement.querySelector("[autofocus]")},t.prototype.hasAnchor=function(t){return null!=this.getElementForAnchor(t)},t.prototype.isPreviewable=function(){return"no-preview"!==this.getCacheControlValue()},t.prototype.isCacheable=function(){return"no-cache"!==this.getCacheControlValue()},t.prototype.isVisitable=function(){return"reload"!==this.getSetting("visit-control")},t.prototype.getSetting=function(t){return this.headDetails.getMetaValue("turbolinks-"+t)},t}()}.call(this),function(){var t=[].slice;e.Renderer=function(){function e(){}var r;return e.render=function(){var e,r,n,o;return n=arguments[0],r=arguments[1],e=3<=arguments.length?t.call(arguments,2):[],o=function(t,e,r){r.prototype=t.prototype;var n=new r,o=t.apply(n,e);return Object(o)===o?o:n}(this,e,function(){}),o.delegate=n,o.render(r),o},e.prototype.renderView=function(t){return this.delegate.viewWillRender(this.newBody),t(),this.delegate.viewRendered(this.newBody)},e.prototype.invalidateView=function(){return this.delegate.viewInvalidated()},e.prototype.createScriptElement=function(t){var e;return"false"===t.getAttribute("data-turbolinks-eval")?t:(e=document.createElement("script"),e.textContent=t.textContent,e.async=!1,r(e,t),e)},r=function(t,e){var r,n,o,i,s,a,u;for(i=e.attributes,a=[],r=0,n=i.length;n>r;r++)s=i[r],o=s.name,u=s.value,a.push(t.setAttribute(o,u));return a},e}()}.call(this),function(){var t,r,n=function(t,e){function r(){this.constructor=t}for(var n in e)o.call(e,n)&&(t[n]=e[n]);return r.prototype=e.prototype,t.prototype=new r,t.__super__=e.prototype,t},o={}.hasOwnProperty;e.SnapshotRenderer=function(e){function o(t,e,r){this.currentSnapshot=t,this.newSnapshot=e,this.isPreview=r,this.currentHeadDetails=this.currentSnapshot.headDetails,this.newHeadDetails=this.newSnapshot.headDetails,this.currentBody=this.currentSnapshot.bodyElement,this.newBody=this.newSnapshot.bodyElement}return n(o,e),o.prototype.render=function(t){return this.shouldRender()?(this.mergeHead(),this.renderView(function(e){return function(){return e.replaceBody(),e.isPreview||e.focusFirstAutofocusableElement(),t()}}(this))):this.invalidateView()},o.prototype.mergeHead=function(){return this.copyNewHeadStylesheetElements(),this.copyNewHeadScriptElements(),this.removeCurrentHeadProvisionalElements(),this.copyNewHeadProvisionalElements()},o.prototype.replaceBody=function(){var t;return t=this.relocateCurrentBodyPermanentElements(),this.activateNewBodyScriptElements(),this.assignNewBody(),this.replacePlaceholderElementsWithClonedPermanentElements(t)},o.prototype.shouldRender=function(){return this.newSnapshot.isVisitable()&&this.trackedElementsAreIdentical()},o.prototype.trackedElementsAreIdentical=function(){return this.currentHeadDetails.getTrackedElementSignature()===this.newHeadDetails.getTrackedElementSignature()},o.prototype.copyNewHeadStylesheetElements=function(){var t,e,r,n,o;for(n=this.getNewHeadStylesheetElements(),o=[],e=0,r=n.length;r>e;e++)t=n[e],o.push(document.head.appendChild(t));return o},o.prototype.copyNewHeadScriptElements=function(){var t,e,r,n,o;for(n=this.getNewHeadScriptElements(),o=[],e=0,r=n.length;r>e;e++)t=n[e],o.push(document.head.appendChild(this.createScriptElement(t)));return o},o.prototype.removeCurrentHeadProvisionalElements=function(){var t,e,r,n,o;for(n=this.getCurrentHeadProvisionalElements(),o=[],e=0,r=n.length;r>e;e++)t=n[e],o.push(document.head.removeChild(t));return o},o.prototype.copyNewHeadProvisionalElements=function(){var t,e,r,n,o;for(n=this.getNewHeadProvisionalElements(),o=[],e=0,r=n.length;r>e;e++)t=n[e],o.push(document.head.appendChild(t));return o},o.prototype.relocateCurrentBodyPermanentElements=function(){var e,n,o,i,s,a,u;for(a=this.getCurrentBodyPermanentElements(),u=[],e=0,n=a.length;n>e;e++)i=a[e],s=t(i),o=this.newSnapshot.getPermanentElementById(i.id),r(i,s.element),r(o,i),u.push(s);return u},o.prototype.replacePlaceholderElementsWithClonedPermanentElements=function(t){var e,n,o,i,s,a,u;for(u=[],o=0,i=t.length;i>o;o++)a=t[o],n=a.element,s=a.permanentElement,e=s.cloneNode(!0),u.push(r(n,e));return u},o.prototype.activateNewBodyScriptElements=function(){var t,e,n,o,i,s;for(i=this.getNewBodyScriptElements(),s=[],e=0,o=i.length;o>e;e++)n=i[e],t=this.createScriptElement(n),s.push(r(n,t));return s},o.prototype.assignNewBody=function(){return document.body=this.newBody},o.prototype.focusFirstAutofocusableElement=function(){var t;return null!=(t=this.newSnapshot.findFirstAutofocusableElement())?t.focus():void 0},o.prototype.getNewHeadStylesheetElements=function(){return this.newHeadDetails.getStylesheetElementsNotInDetails(this.currentHeadDetails)},o.prototype.getNewHeadScriptElements=function(){return this.newHeadDetails.getScriptElementsNotInDetails(this.currentHeadDetails)},o.prototype.getCurrentHeadProvisionalElements=function(){return this.currentHeadDetails.getProvisionalElements()},o.prototype.getNewHeadProvisionalElements=function(){return this.newHeadDetails.getProvisionalElements()},o.prototype.getCurrentBodyPermanentElements=function(){return this.currentSnapshot.getPermanentElementsPresentInSnapshot(this.newSnapshot)},o.prototype.getNewBodyScriptElements=function(){return this.newBody.querySelectorAll("script")},o}(e.Renderer),t=function(t){var e;return e=document.createElement("meta"),e.setAttribute("name","turbolinks-permanent-placeholder"),e.setAttribute("content",t.id),{element:e,permanentElement:t}},r=function(t,e){var r;return(r=t.parentNode)?r.replaceChild(e,t):void 0}}.call(this),function(){var t=function(t,e){function n(){this.constructor=t}for(var o in e)r.call(e,o)&&(t[o]=e[o]);return n.prototype=e.prototype,t.prototype=new n,t.__super__=e.prototype,t},r={}.hasOwnProperty;e.ErrorRenderer=function(e){function r(t){var e;e=document.createElement("html"),e.innerHTML=t,this.newHead=e.querySelector("head"),this.newBody=e.querySelector("body")}return t(r,e),r.prototype.render=function(t){return this.renderView(function(e){return function(){return e.replaceHeadAndBody(),e.activateBodyScriptElements(),t()}}(this))},r.prototype.replaceHeadAndBody=function(){var t,e;return e=document.head,t=document.body,e.parentNode.replaceChild(this.newHead,e),t.parentNode.replaceChild(this.newBody,t)},r.prototype.activateBodyScriptElements=function(){var t,e,r,n,o,i;for(n=this.getScriptElements(),i=[],e=0,r=n.length;r>e;e++)o=n[e],t=this.createScriptElement(o),i.push(o.parentNode.replaceChild(t,o));return i},r.prototype.getScriptElements=function(){return document.documentElement.querySelectorAll("script")},r}(e.Renderer)}.call(this),function(){e.View=function(){function t(t){this.delegate=t,this.htmlElement=document.documentElement}return t.prototype.getRootLocation=function(){return this.getSnapshot().getRootLocation()},t.prototype.getElementForAnchor=function(t){return this.getSnapshot().getElementForAnchor(t)},t.prototype.getSnapshot=function(){return e.Snapshot.fromHTMLElement(this.htmlElement)},t.prototype.render=function(t,e){var r,n,o;return o=t.snapshot,r=t.error,n=t.isPreview,this.markAsPreview(n),null!=o?this.renderSnapshot(o,n,e):this.renderError(r,e)},t.prototype.markAsPreview=function(t){return t?this.htmlElement.setAttribute("data-turbolinks-preview",""):this.htmlElement.removeAttribute("data-turbolinks-preview")},t.prototype.renderSnapshot=function(t,r,n){return e.SnapshotRenderer.render(this.delegate,n,this.getSnapshot(),e.Snapshot.wrap(t),r)},t.prototype.renderError=function(t,r){return e.ErrorRenderer.render(this.delegate,r,t)},t}()}.call(this),function(){var t=function(t,e){return function(){return t.apply(e,arguments)}};e.ScrollManager=function(){function r(r){this.delegate=r,this.onScroll=t(this.onScroll,this),this.onScroll=e.throttle(this.onScroll)}return r.prototype.start=function(){return this.started?void 0:(addEventListener("scroll",this.onScroll,!1),this.onScroll(),this.started=!0)},r.prototype.stop=function(){return this.started?(removeEventListener("scroll",this.onScroll,!1),this.started=!1):void 0},r.prototype.scrollToElement=function(t){return t.scrollIntoView()},r.prototype.scrollToPosition=function(t){var e,r;return e=t.x,r=t.y,window.scrollTo(e,r)},r.prototype.onScroll=function(t){return this.updatePosition({x:window.pageXOffset,y:window.pageYOffset})},r.prototype.updatePosition=function(t){var e;return this.position=t,null!=(e=this.delegate)?e.scrollPositionChanged(this.position):void 0},r}()}.call(this),function(){e.SnapshotCache=function(){function t(t){this.size=t,this.keys=[],this.snapshots={}}var r;return t.prototype.has=function(t){var e;return e=r(t),e in this.snapshots},t.prototype.get=function(t){var e;if(this.has(t))return e=this.read(t),this.touch(t),e},t.prototype.put=function(t,e){return this.write(t,e),this.touch(t),e},t.prototype.read=function(t){var e;return e=r(t),this.snapshots[e]},t.prototype.write=function(t,e){var n;return n=r(t),this.snapshots[n]=e},t.prototype.touch=function(t){var e,n;return n=r(t),e=this.keys.indexOf(n),e>-1&&this.keys.splice(e,1),this.keys.unshift(n),this.trim()},t.prototype.trim=function(){var t,e,r,n,o;for(n=this.keys.splice(this.size),o=[],t=0,r=n.length;r>t;t++)e=n[t],o.push(delete this.snapshots[e]);return o},r=function(t){return e.Location.wrap(t).toCacheKey()},t}()}.call(this),function(){var t=function(t,e){return function(){return t.apply(e,arguments)}};e.Visit=function(){function r(r,n,o){this.controller=r,this.action=o,this.performScroll=t(this.performScroll,this),this.identifier=e.uuid(),this.location=e.Location.wrap(n),this.adapter=this.controller.adapter,this.state="initialized",this.timingMetrics={}}var n;return r.prototype.start=function(){return"initialized"===this.state?(this.recordTimingMetric("visitStart"),this.state="started",this.adapter.visitStarted(this)):void 0},r.prototype.cancel=function(){var t;return"started"===this.state?(null!=(t=this.request)&&t.cancel(),this.cancelRender(),this.state="canceled"):void 0},r.prototype.complete=function(){var t;return"started"===this.state?(this.recordTimingMetric("visitEnd"),this.state="completed","function"==typeof(t=this.adapter).visitCompleted&&t.visitCompleted(this),this.controller.visitCompleted(this)):void 0},r.prototype.fail=function(){var t;return"started"===this.state?(this.state="failed","function"==typeof(t=this.adapter).visitFailed?t.visitFailed(this):void 0):void 0},r.prototype.changeHistory=function(){var t,e;return this.historyChanged?void 0:(t=this.location.isEqualTo(this.referrer)?"replace":this.action,e=n(t),this.controller[e](this.location,this.restorationIdentifier),this.historyChanged=!0)},r.prototype.issueRequest=function(){return this.shouldIssueRequest()&&null==this.request?(this.progress=0,this.request=new e.HttpRequest(this,this.location,this.referrer),this.request.send()):void 0},r.prototype.getCachedSnapshot=function(){var t;return!(t=this.controller.getCachedSnapshotForLocation(this.location))||null!=this.location.anchor&&!t.hasAnchor(this.location.anchor)||"restore"!==this.action&&!t.isPreviewable()?void 0:t},r.prototype.hasCachedSnapshot=function(){return null!=this.getCachedSnapshot()},r.prototype.loadCachedSnapshot=function(){var t,e;return(e=this.getCachedSnapshot())?(t=this.shouldIssueRequest(),this.render(function(){var r;return this.cacheSnapshot(),this.controller.render({snapshot:e,isPreview:t},this.performScroll),"function"==typeof(r=this.adapter).visitRendered&&r.visitRendered(this),t?void 0:this.complete()})):void 0},r.prototype.loadResponse=function(){return null!=this.response?this.render(function(){var t,e;return this.cacheSnapshot(),this.request.failed?(this.controller.render({error:this.response},this.performScroll),"function"==typeof(t=this.adapter).visitRendered&&t.visitRendered(this),this.fail()):(this.controller.render({snapshot:this.response},this.performScroll),"function"==typeof(e=this.adapter).visitRendered&&e.visitRendered(this),this.complete())}):void 0},r.prototype.followRedirect=function(){return this.redirectedToLocation&&!this.followedRedirect?(this.location=this.redirectedToLocation,this.controller.replaceHistoryWithLocationAndRestorationIdentifier(this.redirectedToLocation,this.restorationIdentifier),this.followedRedirect=!0):void 0},r.prototype.requestStarted=function(){var t;return this.recordTimingMetric("requestStart"),"function"==typeof(t=this.adapter).visitRequestStarted?t.visitRequestStarted(this):void 0},r.prototype.requestProgressed=function(t){var e;return this.progress=t,"function"==typeof(e=this.adapter).visitRequestProgressed?e.visitRequestProgressed(this):void 0},r.prototype.requestCompletedWithResponse=function(t,r){return this.response=t,null!=r&&(this.redirectedToLocation=e.Location.wrap(r)),this.adapter.visitRequestCompleted(this)},r.prototype.requestFailedWithStatusCode=function(t,e){return this.response=e,this.adapter.visitRequestFailedWithStatusCode(this,t)},r.prototype.requestFinished=function(){var t;return this.recordTimingMetric("requestEnd"),"function"==typeof(t=this.adapter).visitRequestFinished?t.visitRequestFinished(this):void 0},r.prototype.performScroll=function(){return this.scrolled?void 0:("restore"===this.action?this.scrollToRestoredPosition()||this.scrollToTop():this.scrollToAnchor()||this.scrollToTop(),this.scrolled=!0)},r.prototype.scrollToRestoredPosition=function(){var t,e;return t=null!=(e=this.restorationData)?e.scrollPosition:void 0,null!=t?(this.controller.scrollToPosition(t),!0):void 0},r.prototype.scrollToAnchor=function(){return null!=this.location.anchor?(this.controller.scrollToAnchor(this.location.anchor),!0):void 0},r.prototype.scrollToTop=function(){return this.controller.scrollToPosition({x:0,y:0})},r.prototype.recordTimingMetric=function(t){var e;return null!=(e=this.timingMetrics)[t]?e[t]:e[t]=(new Date).getTime()},r.prototype.getTimingMetrics=function(){return e.copyObject(this.timingMetrics)},n=function(t){switch(t){case"replace":return"replaceHistoryWithLocationAndRestorationIdentifier";case"advance":case"restore":return"pushHistoryWithLocationAndRestorationIdentifier"}},r.prototype.shouldIssueRequest=function(){return"restore"===this.action?!this.hasCachedSnapshot():!0},r.prototype.cacheSnapshot=function(){return this.snapshotCached?void 0:(this.controller.cacheSnapshot(),this.snapshotCached=!0)},r.prototype.render=function(t){return this.cancelRender(),this.frame=requestAnimationFrame(function(e){return function(){return e.frame=null,t.call(e)}}(this))},r.prototype.cancelRender=function(){return this.frame?cancelAnimationFrame(this.frame):void 0},r}()}.call(this),function(){var t=function(t,e){return function(){return t.apply(e,arguments)}};e.Controller=function(){function r(){this.clickBubbled=t(this.clickBubbled,this),this.clickCaptured=t(this.clickCaptured,this),this.pageLoaded=t(this.pageLoaded,this),this.history=new e.History(this),this.view=new e.View(this),this.scrollManager=new e.ScrollManager(this),this.restorationData={},this.clearCache(),this.setProgressBarDelay(500)}return r.prototype.start=function(){return e.supported&&!this.started?(addEventListener("click",this.clickCaptured,!0),addEventListener("DOMContentLoaded",this.pageLoaded,!1),this.scrollManager.start(),this.startHistory(),this.started=!0,this.enabled=!0):void 0},r.prototype.disable=function(){return this.enabled=!1},r.prototype.stop=function(){return this.started?(removeEventListener("click",this.clickCaptured,!0),removeEventListener("DOMContentLoaded",this.pageLoaded,!1),this.scrollManager.stop(),this.stopHistory(),this.started=!1):void 0},r.prototype.clearCache=function(){return this.cache=new e.SnapshotCache(10)},r.prototype.visit=function(t,r){var n,o;return null==r&&(r={}),t=e.Location.wrap(t),this.applicationAllowsVisitingLocation(t)?this.locationIsVisitable(t)?(n=null!=(o=r.action)?o:"advance",this.adapter.visitProposedToLocationWithAction(t,n)):window.location=t:void 0},r.prototype.startVisitToLocationWithAction=function(t,r,n){var o;return e.supported?(o=this.getRestorationDataForIdentifier(n),this.startVisit(t,r,{restorationData:o})):window.location=t},r.prototype.setProgressBarDelay=function(t){return this.progressBarDelay=t},r.prototype.startHistory=function(){return this.location=e.Location.wrap(window.location),this.restorationIdentifier=e.uuid(),this.history.start(),this.history.replace(this.location,this.restorationIdentifier)},r.prototype.stopHistory=function(){return this.history.stop()},r.prototype.pushHistoryWithLocationAndRestorationIdentifier=function(t,r){return this.restorationIdentifier=r,this.location=e.Location.wrap(t),this.history.push(this.location,this.restorationIdentifier)},r.prototype.replaceHistoryWithLocationAndRestorationIdentifier=function(t,r){return this.restorationIdentifier=r,this.location=e.Location.wrap(t),this.history.replace(this.location,this.restorationIdentifier)},r.prototype.historyPoppedToLocationWithRestorationIdentifier=function(t,r){var n;return this.restorationIdentifier=r,this.enabled?(n=this.getRestorationDataForIdentifier(this.restorationIdentifier),this.startVisit(t,"restore",{restorationIdentifier:this.restorationIdentifier,restorationData:n,historyChanged:!0}),this.location=e.Location.wrap(t)):this.adapter.pageInvalidated()},r.prototype.getCachedSnapshotForLocation=function(t){var e;return null!=(e=this.cache.get(t))?e.clone():void 0},r.prototype.shouldCacheSnapshot=function(){return this.view.getSnapshot().isCacheable(); +},r.prototype.cacheSnapshot=function(){var t,r;return this.shouldCacheSnapshot()?(this.notifyApplicationBeforeCachingSnapshot(),r=this.view.getSnapshot(),t=this.lastRenderedLocation,e.defer(function(e){return function(){return e.cache.put(t,r.clone())}}(this))):void 0},r.prototype.scrollToAnchor=function(t){var e;return(e=this.view.getElementForAnchor(t))?this.scrollToElement(e):this.scrollToPosition({x:0,y:0})},r.prototype.scrollToElement=function(t){return this.scrollManager.scrollToElement(t)},r.prototype.scrollToPosition=function(t){return this.scrollManager.scrollToPosition(t)},r.prototype.scrollPositionChanged=function(t){var e;return e=this.getCurrentRestorationData(),e.scrollPosition=t},r.prototype.render=function(t,e){return this.view.render(t,e)},r.prototype.viewInvalidated=function(){return this.adapter.pageInvalidated()},r.prototype.viewWillRender=function(t){return this.notifyApplicationBeforeRender(t)},r.prototype.viewRendered=function(){return this.lastRenderedLocation=this.currentVisit.location,this.notifyApplicationAfterRender()},r.prototype.pageLoaded=function(){return this.lastRenderedLocation=this.location,this.notifyApplicationAfterPageLoad()},r.prototype.clickCaptured=function(){return removeEventListener("click",this.clickBubbled,!1),addEventListener("click",this.clickBubbled,!1)},r.prototype.clickBubbled=function(t){var e,r,n;return this.enabled&&this.clickEventIsSignificant(t)&&(r=this.getVisitableLinkForNode(t.target))&&(n=this.getVisitableLocationForLink(r))&&this.applicationAllowsFollowingLinkToLocation(r,n)?(t.preventDefault(),e=this.getActionForLink(r),this.visit(n,{action:e})):void 0},r.prototype.applicationAllowsFollowingLinkToLocation=function(t,e){var r;return r=this.notifyApplicationAfterClickingLinkToLocation(t,e),!r.defaultPrevented},r.prototype.applicationAllowsVisitingLocation=function(t){var e;return e=this.notifyApplicationBeforeVisitingLocation(t),!e.defaultPrevented},r.prototype.notifyApplicationAfterClickingLinkToLocation=function(t,r){return e.dispatch("turbolinks:click",{target:t,data:{url:r.absoluteURL},cancelable:!0})},r.prototype.notifyApplicationBeforeVisitingLocation=function(t){return e.dispatch("turbolinks:before-visit",{data:{url:t.absoluteURL},cancelable:!0})},r.prototype.notifyApplicationAfterVisitingLocation=function(t){return e.dispatch("turbolinks:visit",{data:{url:t.absoluteURL}})},r.prototype.notifyApplicationBeforeCachingSnapshot=function(){return e.dispatch("turbolinks:before-cache")},r.prototype.notifyApplicationBeforeRender=function(t){return e.dispatch("turbolinks:before-render",{data:{newBody:t}})},r.prototype.notifyApplicationAfterRender=function(){return e.dispatch("turbolinks:render")},r.prototype.notifyApplicationAfterPageLoad=function(t){return null==t&&(t={}),e.dispatch("turbolinks:load",{data:{url:this.location.absoluteURL,timing:t}})},r.prototype.startVisit=function(t,e,r){var n;return null!=(n=this.currentVisit)&&n.cancel(),this.currentVisit=this.createVisit(t,e,r),this.currentVisit.start(),this.notifyApplicationAfterVisitingLocation(t)},r.prototype.createVisit=function(t,r,n){var o,i,s,a,u;return i=null!=n?n:{},a=i.restorationIdentifier,s=i.restorationData,o=i.historyChanged,u=new e.Visit(this,t,r),u.restorationIdentifier=null!=a?a:e.uuid(),u.restorationData=e.copyObject(s),u.historyChanged=o,u.referrer=this.location,u},r.prototype.visitCompleted=function(t){return this.notifyApplicationAfterPageLoad(t.getTimingMetrics())},r.prototype.clickEventIsSignificant=function(t){return!(t.defaultPrevented||t.target.isContentEditable||t.which>1||t.altKey||t.ctrlKey||t.metaKey||t.shiftKey)},r.prototype.getVisitableLinkForNode=function(t){return this.nodeIsVisitable(t)?e.closest(t,"a[href]:not([target]):not([download])"):void 0},r.prototype.getVisitableLocationForLink=function(t){var r;return r=new e.Location(t.getAttribute("href")),this.locationIsVisitable(r)?r:void 0},r.prototype.getActionForLink=function(t){var e;return null!=(e=t.getAttribute("data-turbolinks-action"))?e:"advance"},r.prototype.nodeIsVisitable=function(t){var r;return(r=e.closest(t,"[data-turbolinks]"))?"false"!==r.getAttribute("data-turbolinks"):!0},r.prototype.locationIsVisitable=function(t){return t.isPrefixedBy(this.view.getRootLocation())&&t.isHTML()},r.prototype.getCurrentRestorationData=function(){return this.getRestorationDataForIdentifier(this.restorationIdentifier)},r.prototype.getRestorationDataForIdentifier=function(t){var e;return null!=(e=this.restorationData)[t]?e[t]:e[t]={}},r}()}.call(this),function(){!function(){var t,e;if((t=e=document.currentScript)&&!e.hasAttribute("data-turbolinks-suppress-warning"))for(;t=t.parentNode;)if(t===document.body)return console.warn("You are loading Turbolinks from a
').append($('').attr({ 'data-action': 'today', 'title': options.tooltips.today }).append($('').addClass(options.icons.today)))); - } - if (!options.sideBySide && hasDate() && hasTime()) { - row.push($('').append($('').attr({ 'data-action': 'togglePicker', 'title': options.tooltips.selectTime }).append($('').addClass(options.icons.time)))); - } - if (options.showClear) { - row.push($('').append($('').attr({ 'data-action': 'clear', 'title': options.tooltips.clear }).append($('').addClass(options.icons.clear)))); - } - if (options.showClose) { - row.push($('').append($('').attr({ 'data-action': 'close', 'title': options.tooltips.close }).append($('').addClass(options.icons.close)))); - } - return $('').addClass('table-condensed').append($('').append($('').append(row))); - }, - - getTemplate = function () { - var template = $('
').addClass('bootstrap-datetimepicker-widget dropdown-menu'), - dateView = $('
').addClass('datepicker').append(getDatePickerTemplate()), - timeView = $('
').addClass('timepicker').append(getTimePickerTemplate()), - content = $('
    ').addClass('list-unstyled'), - toolbar = $('
  • ').addClass('picker-switch' + (options.collapse ? ' accordion-toggle' : '')).append(getToolbar()); - - if (options.inline) { - template.removeClass('dropdown-menu'); - } + this.formatViewType = 'datetime'; + if ('formatViewType' in options) { + this.formatViewType = options.formatViewType; + } else if ('formatViewType' in this.element.data()) { + this.formatViewType = this.element.data('formatViewType'); + } - if (use24Hours) { - template.addClass('usetwentyfour'); - } + this.minView = 0; + if ('minView' in options) { + this.minView = options.minView; + } else if ('minView' in this.element.data()) { + this.minView = this.element.data('min-view'); + } + this.minView = DPGlobal.convertViewMode(this.minView); - if (isEnabled('s') && !use24Hours) { - template.addClass('wider'); - } + this.maxView = DPGlobal.modes.length - 1; + if ('maxView' in options) { + this.maxView = options.maxView; + } else if ('maxView' in this.element.data()) { + this.maxView = this.element.data('max-view'); + } + this.maxView = DPGlobal.convertViewMode(this.maxView); - if (options.sideBySide && hasDate() && hasTime()) { - template.addClass('timepicker-sbs'); - if (options.toolbarPlacement === 'top') { - template.append(toolbar); - } - template.append( - $('
    ').addClass('row') - .append(dateView.addClass('col-md-6')) - .append(timeView.addClass('col-md-6')) - ); - if (options.toolbarPlacement === 'bottom') { - template.append(toolbar); - } - return template; - } + this.wheelViewModeNavigation = false; + if ('wheelViewModeNavigation' in options) { + this.wheelViewModeNavigation = options.wheelViewModeNavigation; + } else if ('wheelViewModeNavigation' in this.element.data()) { + this.wheelViewModeNavigation = this.element.data('view-mode-wheel-navigation'); + } - if (options.toolbarPlacement === 'top') { - content.append(toolbar); - } - if (hasDate()) { - content.append($('
  • ').addClass((options.collapse && hasTime() ? 'collapse in' : '')).append(dateView)); - } - if (options.toolbarPlacement === 'default') { - content.append(toolbar); - } - if (hasTime()) { - content.append($('
  • ').addClass((options.collapse && hasDate() ? 'collapse' : '')).append(timeView)); - } - if (options.toolbarPlacement === 'bottom') { - content.append(toolbar); - } - return template.append(content); - }, + this.wheelViewModeNavigationInverseDirection = false; - dataToOptions = function () { - var eData, - dataOptions = {}; + if ('wheelViewModeNavigationInverseDirection' in options) { + this.wheelViewModeNavigationInverseDirection = options.wheelViewModeNavigationInverseDirection; + } else if ('wheelViewModeNavigationInverseDirection' in this.element.data()) { + this.wheelViewModeNavigationInverseDirection = this.element.data('view-mode-wheel-navigation-inverse-dir'); + } - if (element.is('input') || options.inline) { - eData = element.data(); - } else { - eData = element.find('input').data(); - } + this.wheelViewModeNavigationDelay = 100; + if ('wheelViewModeNavigationDelay' in options) { + this.wheelViewModeNavigationDelay = options.wheelViewModeNavigationDelay; + } else if ('wheelViewModeNavigationDelay' in this.element.data()) { + this.wheelViewModeNavigationDelay = this.element.data('view-mode-wheel-navigation-delay'); + } - if (eData.dateOptions && eData.dateOptions instanceof Object) { - dataOptions = $.extend(true, dataOptions, eData.dateOptions); - } + this.startViewMode = 2; + if ('startView' in options) { + this.startViewMode = options.startView; + } else if ('startView' in this.element.data()) { + this.startViewMode = this.element.data('start-view'); + } + this.startViewMode = DPGlobal.convertViewMode(this.startViewMode); + this.viewMode = this.startViewMode; + + this.viewSelect = this.minView; + if ('viewSelect' in options) { + this.viewSelect = options.viewSelect; + } else if ('viewSelect' in this.element.data()) { + this.viewSelect = this.element.data('view-select'); + } + this.viewSelect = DPGlobal.convertViewMode(this.viewSelect); - $.each(options, function (key) { - var attributeName = 'date' + key.charAt(0).toUpperCase() + key.slice(1); - if (eData[attributeName] !== undefined) { - dataOptions[key] = eData[attributeName]; - } - }); - return dataOptions; - }, - - place = function () { - var position = (component || element).position(), - offset = (component || element).offset(), - vertical = options.widgetPositioning.vertical, - horizontal = options.widgetPositioning.horizontal, - parent; - - if (options.widgetParent) { - parent = options.widgetParent.append(widget); - } else if (element.is('input')) { - parent = element.after(widget).parent(); - } else if (options.inline) { - parent = element.append(widget); - return; - } else { - parent = element; - element.children().first().after(widget); - } + this.forceParse = true; + if ('forceParse' in options) { + this.forceParse = options.forceParse; + } else if ('dateForceParse' in this.element.data()) { + this.forceParse = this.element.data('date-force-parse'); + } + var template = this.bootcssVer === 3 ? DPGlobal.templateV3 : DPGlobal.template; + while (template.indexOf('{iconType}') !== -1) { + template = template.replace('{iconType}', this.icontype); + } + while (template.indexOf('{leftArrow}') !== -1) { + template = template.replace('{leftArrow}', this.icons.leftArrow); + } + while (template.indexOf('{rightArrow}') !== -1) { + template = template.replace('{rightArrow}', this.icons.rightArrow); + } + this.picker = $(template) + .appendTo(this.isInline ? this.element : this.container) // 'body') + .on({ + click: $.proxy(this.click, this), + mousedown: $.proxy(this.mousedown, this) + }); + + if (this.wheelViewModeNavigation) { + if ($.fn.mousewheel) { + this.picker.on({mousewheel: $.proxy(this.mousewheel, this)}); + } else { + console.log('Mouse Wheel event is not supported. Please include the jQuery Mouse Wheel plugin before enabling this option'); + } + } - // Top and bottom logic - if (vertical === 'auto') { - if (offset.top + widget.height() * 1.5 >= $(window).height() + $(window).scrollTop() && - widget.height() + element.outerHeight() < offset.top) { - vertical = 'top'; - } else { - vertical = 'bottom'; - } - } + if (this.isInline) { + this.picker.addClass('datetimepicker-inline'); + } else { + this.picker.addClass('datetimepicker-dropdown-' + this.pickerPosition + ' dropdown-menu'); + } + if (this.isRTL) { + this.picker.addClass('datetimepicker-rtl'); + var selector = this.bootcssVer === 3 ? '.prev span, .next span' : '.prev i, .next i'; + this.picker.find(selector).toggleClass(this.icons.leftArrow + ' ' + this.icons.rightArrow); + } - // Left and right logic - if (horizontal === 'auto') { - if (parent.width() < offset.left + widget.outerWidth() / 2 && - offset.left + widget.outerWidth() > $(window).width()) { - horizontal = 'right'; - } else { - horizontal = 'left'; - } - } + $(document).on('mousedown touchend', this.clickedOutside); - if (vertical === 'top') { - widget.addClass('top').removeClass('bottom'); - } else { - widget.addClass('bottom').removeClass('top'); - } + this.autoclose = false; + if ('autoclose' in options) { + this.autoclose = options.autoclose; + } else if ('dateAutoclose' in this.element.data()) { + this.autoclose = this.element.data('date-autoclose'); + } - if (horizontal === 'right') { - widget.addClass('pull-right'); - } else { - widget.removeClass('pull-right'); - } + this.keyboardNavigation = true; + if ('keyboardNavigation' in options) { + this.keyboardNavigation = options.keyboardNavigation; + } else if ('dateKeyboardNavigation' in this.element.data()) { + this.keyboardNavigation = this.element.data('date-keyboard-navigation'); + } - // find the first parent element that has a non-static css positioning - if (parent.css('position') === 'static') { - parent = parent.parents().filter(function () { - return $(this).css('position') !== 'static'; - }).first(); - } + this.todayBtn = (options.todayBtn || this.element.data('date-today-btn') || false); + this.clearBtn = (options.clearBtn || this.element.data('date-clear-btn') || false); + this.todayHighlight = (options.todayHighlight || this.element.data('date-today-highlight') || false); + + this.weekStart = 0; + if (typeof options.weekStart !== 'undefined') { + this.weekStart = options.weekStart; + } else if (typeof this.element.data('date-weekstart') !== 'undefined') { + this.weekStart = this.element.data('date-weekstart'); + } else if (typeof dates[this.language].weekStart !== 'undefined') { + this.weekStart = dates[this.language].weekStart; + } + this.weekStart = this.weekStart % 7; + this.weekEnd = ((this.weekStart + 6) % 7); + this.onRenderDay = function (date) { + var render = (options.onRenderDay || function () { return []; })(date); + if (typeof render === 'string') { + render = [render]; + } + var res = ['day']; + return res.concat((render ? render : [])); + }; + this.onRenderHour = function (date) { + var render = (options.onRenderHour || function () { return []; })(date); + var res = ['hour']; + if (typeof render === 'string') { + render = [render]; + } + return res.concat((render ? render : [])); + }; + this.onRenderMinute = function (date) { + var render = (options.onRenderMinute || function () { return []; })(date); + var res = ['minute']; + if (typeof render === 'string') { + render = [render]; + } + if (date < this.startDate || date > this.endDate) { + res.push('disabled'); + } else if (Math.floor(this.date.getUTCMinutes() / this.minuteStep) === Math.floor(date.getUTCMinutes() / this.minuteStep)) { + res.push('active'); + } + return res.concat((render ? render : [])); + }; + this.onRenderYear = function (date) { + var render = (options.onRenderYear || function () { return []; })(date); + var res = ['year']; + if (typeof render === 'string') { + render = [render]; + } + if (this.date.getUTCFullYear() === date.getUTCFullYear()) { + res.push('active'); + } + var currentYear = date.getUTCFullYear(); + var endYear = this.endDate.getUTCFullYear(); + if (date < this.startDate || currentYear > endYear) { + res.push('disabled'); + } + return res.concat((render ? render : [])); + } + this.onRenderMonth = function (date) { + var render = (options.onRenderMonth || function () { return []; })(date); + var res = ['month']; + if (typeof render === 'string') { + render = [render]; + } + return res.concat((render ? render : [])); + } + this.startDate = new Date(-8639968443048000); + this.endDate = new Date(8639968443048000); + this.datesDisabled = []; + this.daysOfWeekDisabled = []; + this.setStartDate(options.startDate || this.element.data('date-startdate')); + this.setEndDate(options.endDate || this.element.data('date-enddate')); + this.setDatesDisabled(options.datesDisabled || this.element.data('date-dates-disabled')); + this.setDaysOfWeekDisabled(options.daysOfWeekDisabled || this.element.data('date-days-of-week-disabled')); + this.setMinutesDisabled(options.minutesDisabled || this.element.data('date-minute-disabled')); + this.setHoursDisabled(options.hoursDisabled || this.element.data('date-hour-disabled')); + this.fillDow(); + this.fillMonths(); + this.update(); + this.showMode(); + + if (this.isInline) { + this.show(); + } + }; + + Datetimepicker.prototype = { + constructor: Datetimepicker, + + _events: [], + _attachEvents: function () { + this._detachEvents(); + if (this.isInput) { // single input + this._events = [ + [this.element, { + focus: $.proxy(this.show, this), + keyup: $.proxy(this.update, this), + keydown: $.proxy(this.keydown, this) + }] + ]; + } + else if (this.component && this.hasInput) { // component: input + button + this._events = [ + // For components that are not readonly, allow keyboard nav + [this.element.find('input'), { + focus: $.proxy(this.show, this), + keyup: $.proxy(this.update, this), + keydown: $.proxy(this.keydown, this) + }], + [this.component, { + click: $.proxy(this.show, this) + }] + ]; + if (this.componentReset) { + this._events.push([ + this.componentReset, + {click: $.proxy(this.reset, this)} + ]); + } + } + else if (this.element.is('div')) { // inline datetimepicker + this.isInline = true; + } + else { + this._events = [ + [this.element, { + click: $.proxy(this.show, this) + }] + ]; + } + for (var i = 0, el, ev; i < this._events.length; i++) { + el = this._events[i][0]; + ev = this._events[i][1]; + el.on(ev); + } + }, + + _detachEvents: function () { + for (var i = 0, el, ev; i < this._events.length; i++) { + el = this._events[i][0]; + ev = this._events[i][1]; + el.off(ev); + } + this._events = []; + }, + + show: function (e) { + this.picker.show(); + this.height = this.component ? this.component.outerHeight() : this.element.outerHeight(); + if (this.forceParse) { + this.update(); + } + this.place(); + $(window).on('resize', $.proxy(this.place, this)); + if (e) { + e.stopPropagation(); + e.preventDefault(); + } + this.isVisible = true; + this.element.trigger({ + type: 'show', + date: this.date + }); + }, + + hide: function () { + if (!this.isVisible) return; + if (this.isInline) return; + this.picker.hide(); + $(window).off('resize', this.place); + this.viewMode = this.startViewMode; + this.showMode(); + if (!this.isInput) { + $(document).off('mousedown', this.hide); + } + + if ( + this.forceParse && + ( + this.isInput && this.element.val() || + this.hasInput && this.element.find('input').val() + ) + ) + this.setValue(); + this.isVisible = false; + this.element.trigger({ + type: 'hide', + date: this.date + }); + }, + + remove: function () { + this._detachEvents(); + $(document).off('mousedown', this.clickedOutside); + this.picker.remove(); + delete this.picker; + delete this.element.data().datetimepicker; + }, + + getDate: function () { + var d = this.getUTCDate(); + if (d === null) { + return null; + } + return new Date(d.getTime() + (d.getTimezoneOffset() * 60000)); + }, + + getUTCDate: function () { + return this.date; + }, + + getInitialDate: function () { + return this.initialDate + }, + + setInitialDate: function (initialDate) { + this.initialDate = initialDate; + }, + + setDate: function (d) { + this.setUTCDate(new Date(d.getTime() - (d.getTimezoneOffset() * 60000))); + }, + + setUTCDate: function (d) { + if (d >= this.startDate && d <= this.endDate) { + this.date = d; + this.setValue(); + this.viewDate = this.date; + this.fill(); + } else { + this.element.trigger({ + type: 'outOfRange', + date: d, + startDate: this.startDate, + endDate: this.endDate + }); + } + }, + + setFormat: function (format) { + this.format = DPGlobal.parseFormat(format, this.formatType); + var element; + if (this.isInput) { + element = this.element; + } else if (this.component) { + element = this.element.find('input'); + } + if (element && element.val()) { + this.setValue(); + } + }, + + setValue: function () { + var formatted = this.getFormattedDate(); + if (!this.isInput) { + if (this.component) { + this.element.find('input').val(formatted); + } + this.element.data('date', formatted); + } else { + this.element.val(formatted); + } + if (this.linkField) { + $('#' + this.linkField).val(this.getFormattedDate(this.linkFormat)); + } + }, + + getFormattedDate: function (format) { + format = format || this.format; + return DPGlobal.formatDate(this.date, format, this.language, this.formatType, this.timezone); + }, + + setStartDate: function (startDate) { + this.startDate = startDate || this.startDate; + if (this.startDate.valueOf() !== 8639968443048000) { + this.startDate = DPGlobal.parseDate(this.startDate, this.format, this.language, this.formatType, this.timezone); + } + this.update(); + this.updateNavArrows(); + }, + + setEndDate: function (endDate) { + this.endDate = endDate || this.endDate; + if (this.endDate.valueOf() !== 8639968443048000) { + this.endDate = DPGlobal.parseDate(this.endDate, this.format, this.language, this.formatType, this.timezone); + } + this.update(); + this.updateNavArrows(); + }, + + setDatesDisabled: function (datesDisabled) { + this.datesDisabled = datesDisabled || []; + if (!$.isArray(this.datesDisabled)) { + this.datesDisabled = this.datesDisabled.split(/,\s*/); + } + var mThis = this; + this.datesDisabled = $.map(this.datesDisabled, function (d) { + return DPGlobal.parseDate(d, mThis.format, mThis.language, mThis.formatType, mThis.timezone).toDateString(); + }); + this.update(); + this.updateNavArrows(); + }, + + setTitle: function (selector, value) { + return this.picker.find(selector) + .find('th:eq(1)') + .text(this.title === false ? value : this.title); + }, + + setDaysOfWeekDisabled: function (daysOfWeekDisabled) { + this.daysOfWeekDisabled = daysOfWeekDisabled || []; + if (!$.isArray(this.daysOfWeekDisabled)) { + this.daysOfWeekDisabled = this.daysOfWeekDisabled.split(/,\s*/); + } + this.daysOfWeekDisabled = $.map(this.daysOfWeekDisabled, function (d) { + return parseInt(d, 10); + }); + this.update(); + this.updateNavArrows(); + }, + + setMinutesDisabled: function (minutesDisabled) { + this.minutesDisabled = minutesDisabled || []; + if (!$.isArray(this.minutesDisabled)) { + this.minutesDisabled = this.minutesDisabled.split(/,\s*/); + } + this.minutesDisabled = $.map(this.minutesDisabled, function (d) { + return parseInt(d, 10); + }); + this.update(); + this.updateNavArrows(); + }, + + setHoursDisabled: function (hoursDisabled) { + this.hoursDisabled = hoursDisabled || []; + if (!$.isArray(this.hoursDisabled)) { + this.hoursDisabled = this.hoursDisabled.split(/,\s*/); + } + this.hoursDisabled = $.map(this.hoursDisabled, function (d) { + return parseInt(d, 10); + }); + this.update(); + this.updateNavArrows(); + }, + + place: function () { + if (this.isInline) return; + + if (!this.zIndex) { + var index_highest = 0; + $('div').each(function () { + var index_current = parseInt($(this).css('zIndex'), 10); + if (index_current > index_highest) { + index_highest = index_current; + } + }); + this.zIndex = index_highest + 10; + } + + var offset, top, left, containerOffset; + if (this.container instanceof $) { + containerOffset = this.container.offset(); + } else { + containerOffset = $(this.container).offset(); + } + + if (this.component) { + offset = this.component.offset(); + left = offset.left; + if (this.pickerPosition === 'bottom-left' || this.pickerPosition === 'top-left') { + left += this.component.outerWidth() - this.picker.outerWidth(); + } + } else { + offset = this.element.offset(); + left = offset.left; + if (this.pickerPosition === 'bottom-left' || this.pickerPosition === 'top-left') { + left += this.element.outerWidth() - this.picker.outerWidth(); + } + } + + var bodyWidth = document.body.clientWidth || window.innerWidth; + if (left + 220 > bodyWidth) { + left = bodyWidth - 220; + } + + if (this.pickerPosition === 'top-left' || this.pickerPosition === 'top-right') { + top = offset.top - this.picker.outerHeight(); + } else { + top = offset.top + this.height; + } + + top = top - containerOffset.top; + left = left - containerOffset.left; + + this.picker.css({ + top: top, + left: left, + zIndex: this.zIndex + }); + }, + + hour_minute: "^([0-9]|0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]", + + update: function () { + var date, fromArgs = false; + if (arguments && arguments.length && (typeof arguments[0] === 'string' || arguments[0] instanceof Date)) { + date = arguments[0]; + fromArgs = true; + } else { + date = (this.isInput ? this.element.val() : this.element.find('input').val()) || this.element.data('date') || this.initialDate; + if (typeof date === 'string') { + date = date.replace(/^\s+|\s+$/g,''); + } + } - if (parent.length === 0) { - throw new Error('datetimepicker component should be placed within a non-static positioned container'); - } + if (!date) { + date = new Date(); + fromArgs = false; + } - widget.css({ - top: vertical === 'top' ? 'auto' : position.top + element.outerHeight(), - bottom: vertical === 'top' ? parent.outerHeight() - (parent === element ? 0 : position.top) : 'auto', - left: horizontal === 'left' ? (parent === element ? 0 : position.left) : 'auto', - right: horizontal === 'left' ? 'auto' : parent.outerWidth() - element.outerWidth() - (parent === element ? 0 : position.left) + if (typeof date === "string") { + if (new RegExp(this.hour_minute).test(date) || new RegExp(this.hour_minute + ":[0-5][0-9]").test(date)) { + date = this.getDate() + } + } + + this.date = DPGlobal.parseDate(date, this.format, this.language, this.formatType, this.timezone); + + if (fromArgs) this.setValue(); + + if (this.date < this.startDate) { + this.viewDate = new Date(this.startDate); + } else if (this.date > this.endDate) { + this.viewDate = new Date(this.endDate); + } else { + this.viewDate = new Date(this.date); + } + this.fill(); + }, + + fillDow: function () { + var dowCnt = this.weekStart, + html = '
'; + while (dowCnt < this.weekStart + 7) { + html += ''; + } + html += ''; + this.picker.find('.datetimepicker-days thead').append(html); + }, + + fillMonths: function () { + var html = ''; + var d = new Date(this.viewDate); + for (var i = 0; i < 12; i++) { + d.setUTCMonth(i); + var classes = this.onRenderMonth(d); + html += '' + dates[this.language].monthsShort[i] + ''; + } + this.picker.find('.datetimepicker-months td').html(html); + }, + + fill: function () { + if (!this.date || !this.viewDate) { + return; + } + var d = new Date(this.viewDate), + year = d.getUTCFullYear(), + month = d.getUTCMonth(), + dayMonth = d.getUTCDate(), + hours = d.getUTCHours(), + startYear = this.startDate.getUTCFullYear(), + startMonth = this.startDate.getUTCMonth(), + endYear = this.endDate.getUTCFullYear(), + endMonth = this.endDate.getUTCMonth() + 1, + currentDate = (new UTCDate(this.date.getUTCFullYear(), this.date.getUTCMonth(), this.date.getUTCDate())).valueOf(), + today = new Date(); + this.setTitle('.datetimepicker-days', dates[this.language].months[month] + ' ' + year) + if (this.formatViewType === 'time') { + var formatted = this.getFormattedDate(); + this.setTitle('.datetimepicker-hours', formatted); + this.setTitle('.datetimepicker-minutes', formatted); + } else { + this.setTitle('.datetimepicker-hours', dayMonth + ' ' + dates[this.language].months[month] + ' ' + year); + this.setTitle('.datetimepicker-minutes', dayMonth + ' ' + dates[this.language].months[month] + ' ' + year); + } + this.picker.find('tfoot th.today') + .text(dates[this.language].today || dates['en'].today) + .toggle(this.todayBtn !== false); + this.picker.find('tfoot th.clear') + .text(dates[this.language].clear || dates['en'].clear) + .toggle(this.clearBtn !== false); + this.updateNavArrows(); + this.fillMonths(); + var prevMonth = UTCDate(year, month - 1, 28, 0, 0, 0, 0), + day = DPGlobal.getDaysInMonth(prevMonth.getUTCFullYear(), prevMonth.getUTCMonth()); + prevMonth.setUTCDate(day); + prevMonth.setUTCDate(day - (prevMonth.getUTCDay() - this.weekStart + 7) % 7); + var nextMonth = new Date(prevMonth); + nextMonth.setUTCDate(nextMonth.getUTCDate() + 42); + nextMonth = nextMonth.valueOf(); + var html = []; + var classes; + while (prevMonth.valueOf() < nextMonth) { + if (prevMonth.getUTCDay() === this.weekStart) { + html.push(''); + } + classes = this.onRenderDay(prevMonth); + if (prevMonth.getUTCFullYear() < year || (prevMonth.getUTCFullYear() === year && prevMonth.getUTCMonth() < month)) { + classes.push('old'); + } else if (prevMonth.getUTCFullYear() > year || (prevMonth.getUTCFullYear() === year && prevMonth.getUTCMonth() > month)) { + classes.push('new'); + } + // Compare internal UTC date with local today, not UTC today + if (this.todayHighlight && + prevMonth.getUTCFullYear() === today.getFullYear() && + prevMonth.getUTCMonth() === today.getMonth() && + prevMonth.getUTCDate() === today.getDate()) { + classes.push('today'); + } + if (prevMonth.valueOf() === currentDate) { + classes.push('active'); + } + if ((prevMonth.valueOf() + 86400000) <= this.startDate || prevMonth.valueOf() > this.endDate || + $.inArray(prevMonth.getUTCDay(), this.daysOfWeekDisabled) !== -1 || + $.inArray(prevMonth.toDateString(), this.datesDisabled) !== -1) { + classes.push('disabled'); + } + html.push(''); + if (prevMonth.getUTCDay() === this.weekEnd) { + html.push(''); + } + prevMonth.setUTCDate(prevMonth.getUTCDate() + 1); + } + this.picker.find('.datetimepicker-days tbody').empty().append(html.join('')); + + html = []; + var txt = '', meridian = '', meridianOld = ''; + var hoursDisabled = this.hoursDisabled || []; + d = new Date(this.viewDate) + for (var i = 0; i < 24; i++) { + d.setUTCHours(i); + classes = this.onRenderHour(d); + if (hoursDisabled.indexOf(i) !== -1) { + classes.push('disabled'); + } + var actual = UTCDate(year, month, dayMonth, i); + // We want the previous hour for the startDate + if ((actual.valueOf() + 3600000) <= this.startDate || actual.valueOf() > this.endDate) { + classes.push('disabled'); + } else if (hours === i) { + classes.push('active'); + } + if (this.showMeridian && dates[this.language].meridiem.length === 2) { + meridian = (i < 12 ? dates[this.language].meridiem[0] : dates[this.language].meridiem[1]); + if (meridian !== meridianOld) { + if (meridianOld !== '') { + html.push(''); + } + html.push('
' + meridian.toUpperCase() + ''); + } + meridianOld = meridian; + txt = (i % 12 ? i % 12 : 12); + if (i < 12) { + classes.push('hour_am'); + } else { + classes.push('hour_pm'); + } + html.push('' + txt + ''); + if (i === 23) { + html.push('
'); + } + } else { + txt = i + ':00'; + html.push('' + txt + ''); + } + } + this.picker.find('.datetimepicker-hours td').html(html.join('')); + + html = []; + txt = ''; + meridian = ''; + meridianOld = ''; + var minutesDisabled = this.minutesDisabled || []; + d = new Date(this.viewDate); + for (var i = 0; i < 60; i += this.minuteStep) { + if (minutesDisabled.indexOf(i) !== -1) continue; + d.setUTCMinutes(i); + d.setUTCSeconds(0); + classes = this.onRenderMinute(d); + if (this.showMeridian && dates[this.language].meridiem.length === 2) { + meridian = (hours < 12 ? dates[this.language].meridiem[0] : dates[this.language].meridiem[1]); + if (meridian !== meridianOld) { + if (meridianOld !== '') { + html.push(''); + } + html.push('
' + meridian.toUpperCase() + ''); + } + meridianOld = meridian; + txt = (hours % 12 ? hours % 12 : 12); + html.push('' + txt + ':' + (i < 10 ? '0' + i : i) + ''); + if (i === 59) { + html.push('
'); + } + } else { + txt = i + ':00'; + html.push('' + hours + ':' + (i < 10 ? '0' + i : i) + ''); + } + } + this.picker.find('.datetimepicker-minutes td').html(html.join('')); + + var currentYear = this.date.getUTCFullYear(); + var months = this.setTitle('.datetimepicker-months', year) + .end() + .find('.month').removeClass('active'); + if (currentYear === year) { + // getUTCMonths() returns 0 based, and we need to select the next one + // To cater bootstrap 2 we don't need to select the next one + months.eq(this.date.getUTCMonth()).addClass('active'); + } + if (year < startYear || year > endYear) { + months.addClass('disabled'); + } + if (year === startYear) { + months.slice(0, startMonth).addClass('disabled'); + } + if (year === endYear) { + months.slice(endMonth).addClass('disabled'); + } + + html = ''; + year = parseInt(year / 10, 10) * 10; + var yearCont = this.setTitle('.datetimepicker-years', year + '-' + (year + 9)) + .end() + .find('td'); + year -= 1; + d = new Date(this.viewDate); + for (var i = -1; i < 11; i++) { + d.setUTCFullYear(year); + classes = this.onRenderYear(d); + if (i === -1 || i === 10) { + classes.push(old); + } + html += '' + year + ''; + year += 1; + } + yearCont.html(html); + this.place(); + }, + + updateNavArrows: function () { + var d = new Date(this.viewDate), + year = d.getUTCFullYear(), + month = d.getUTCMonth(), + day = d.getUTCDate(), + hour = d.getUTCHours(); + switch (this.viewMode) { + case 0: + if (year <= this.startDate.getUTCFullYear() + && month <= this.startDate.getUTCMonth() + && day <= this.startDate.getUTCDate() + && hour <= this.startDate.getUTCHours()) { + this.picker.find('.prev').css({visibility: 'hidden'}); + } else { + this.picker.find('.prev').css({visibility: 'visible'}); + } + if (year >= this.endDate.getUTCFullYear() + && month >= this.endDate.getUTCMonth() + && day >= this.endDate.getUTCDate() + && hour >= this.endDate.getUTCHours()) { + this.picker.find('.next').css({visibility: 'hidden'}); + } else { + this.picker.find('.next').css({visibility: 'visible'}); + } + break; + case 1: + if (year <= this.startDate.getUTCFullYear() + && month <= this.startDate.getUTCMonth() + && day <= this.startDate.getUTCDate()) { + this.picker.find('.prev').css({visibility: 'hidden'}); + } else { + this.picker.find('.prev').css({visibility: 'visible'}); + } + if (year >= this.endDate.getUTCFullYear() + && month >= this.endDate.getUTCMonth() + && day >= this.endDate.getUTCDate()) { + this.picker.find('.next').css({visibility: 'hidden'}); + } else { + this.picker.find('.next').css({visibility: 'visible'}); + } + break; + case 2: + if (year <= this.startDate.getUTCFullYear() + && month <= this.startDate.getUTCMonth()) { + this.picker.find('.prev').css({visibility: 'hidden'}); + } else { + this.picker.find('.prev').css({visibility: 'visible'}); + } + if (year >= this.endDate.getUTCFullYear() + && month >= this.endDate.getUTCMonth()) { + this.picker.find('.next').css({visibility: 'hidden'}); + } else { + this.picker.find('.next').css({visibility: 'visible'}); + } + break; + case 3: + case 4: + if (year <= this.startDate.getUTCFullYear()) { + this.picker.find('.prev').css({visibility: 'hidden'}); + } else { + this.picker.find('.prev').css({visibility: 'visible'}); + } + if (year >= this.endDate.getUTCFullYear()) { + this.picker.find('.next').css({visibility: 'hidden'}); + } else { + this.picker.find('.next').css({visibility: 'visible'}); + } + break; + } + }, + + mousewheel: function (e) { + + e.preventDefault(); + e.stopPropagation(); + + if (this.wheelPause) { + return; + } + + this.wheelPause = true; + + var originalEvent = e.originalEvent; + + var delta = originalEvent.wheelDelta; + + var mode = delta > 0 ? 1 : (delta === 0) ? 0 : -1; + + if (this.wheelViewModeNavigationInverseDirection) { + mode = -mode; + } + + this.showMode(mode); + + setTimeout($.proxy(function () { + + this.wheelPause = false + + }, this), this.wheelViewModeNavigationDelay); + + }, + + click: function (e) { + e.stopPropagation(); + e.preventDefault(); + var target = $(e.target).closest('span, td, th, legend'); + if (target.is('.' + this.icontype)) { + target = $(target).parent().closest('span, td, th, legend'); + } + if (target.length === 1) { + if (target.is('.disabled')) { + this.element.trigger({ + type: 'outOfRange', + date: this.viewDate, + startDate: this.startDate, + endDate: this.endDate + }); + return; + } + switch (target[0].nodeName.toLowerCase()) { + case 'th': + switch (target[0].className) { + case 'switch': + this.showMode(1); + break; + case 'prev': + case 'next': + var dir = DPGlobal.modes[this.viewMode].navStep * (target[0].className === 'prev' ? -1 : 1); + switch (this.viewMode) { + case 0: + this.viewDate = this.moveHour(this.viewDate, dir); + break; + case 1: + this.viewDate = this.moveDate(this.viewDate, dir); + break; + case 2: + this.viewDate = this.moveMonth(this.viewDate, dir); + break; + case 3: + case 4: + this.viewDate = this.moveYear(this.viewDate, dir); + break; + } + this.fill(); + this.element.trigger({ + type: target[0].className + ':' + this.convertViewModeText(this.viewMode), + date: this.viewDate, + startDate: this.startDate, + endDate: this.endDate }); - }, - - notifyEvent = function (e) { - if (e.type === 'dp.change' && ((e.date && e.date.isSame(e.oldDate)) || (!e.date && !e.oldDate))) { - return; - } - element.trigger(e); - }, - - viewUpdate = function (e) { - if (e === 'y') { - e = 'YYYY'; - } - notifyEvent({ - type: 'dp.update', - change: e, - viewDate: viewDate.clone() + break; + case 'clear': + this.reset(); + if (this.autoclose) { + this.hide(); + } + break; + case 'today': + var date = new Date(); + date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds(), 0); + + // Respect startDate and endDate. + if (date < this.startDate) date = this.startDate; + else if (date > this.endDate) date = this.endDate; + + this.viewMode = this.startViewMode; + this.showMode(0); + this._setDate(date); + this.fill(); + if (this.autoclose) { + this.hide(); + } + break; + } + break; + case 'span': + if (!target.is('.disabled')) { + var year = this.viewDate.getUTCFullYear(), + month = this.viewDate.getUTCMonth(), + day = this.viewDate.getUTCDate(), + hours = this.viewDate.getUTCHours(), + minutes = this.viewDate.getUTCMinutes(), + seconds = this.viewDate.getUTCSeconds(); + + if (target.is('.month')) { + this.viewDate.setUTCDate(1); + month = target.parent().find('span').index(target); + day = this.viewDate.getUTCDate(); + this.viewDate.setUTCMonth(month); + this.element.trigger({ + type: 'changeMonth', + date: this.viewDate }); - }, - - showMode = function (dir) { - if (!widget) { - return; - } - if (dir) { - currentViewMode = Math.max(minViewModeNumber, Math.min(3, currentViewMode + dir)); - } - widget.find('.datepicker > div').hide().filter('.datepicker-' + datePickerModes[currentViewMode].clsName).show(); - }, - - fillDow = function () { - var row = $(''), - currentDate = viewDate.clone().startOf('w').startOf('d'); - - if (options.calendarWeeks === true) { - row.append($(''); - if (options.calendarWeeks) { - row.append(''); - } - html.push(row); - } - clsNames = ['day']; - if (currentDate.isBefore(viewDate, 'M')) { - clsNames.push('old'); - } - if (currentDate.isAfter(viewDate, 'M')) { - clsNames.push('new'); - } - if (currentDate.isSame(date, 'd') && !unset) { - clsNames.push('active'); - } - if (!isValid(currentDate, 'd')) { - clsNames.push('disabled'); - } - if (currentDate.isSame(getMoment(), 'd')) { - clsNames.push('today'); - } - if (currentDate.day() === 0 || currentDate.day() === 6) { - clsNames.push('weekend'); - } - notifyEvent({ - type: 'dp.classify', - date: currentDate, - classNames: clsNames - }); - row.append(''); - currentDate.add(1, 'd'); - } - - daysView.find('tbody').empty().append(html); - - updateMonths(); - - updateYears(); - - updateDecades(); - }, - - fillHours = function () { - var table = widget.find('.timepicker-hours table'), - currentHour = viewDate.clone().startOf('d'), - html = [], - row = $(''); - - if (viewDate.hour() > 11 && !use24Hours) { - currentHour.hour(12); - } - while (currentHour.isSame(viewDate, 'd') && (use24Hours || (viewDate.hour() < 12 && currentHour.hour() < 12) || viewDate.hour() > 11)) { - if (currentHour.hour() % 4 === 0) { - row = $(''); - html.push(row); - } - row.append(''); - currentHour.add(1, 'h'); - } - table.empty().append(html); - }, - - fillMinutes = function () { - var table = widget.find('.timepicker-minutes table'), - currentMinute = viewDate.clone().startOf('h'), - html = [], - row = $(''), - step = options.stepping === 1 ? 5 : options.stepping; - - while (viewDate.isSame(currentMinute, 'h')) { - if (currentMinute.minute() % (step * 4) === 0) { - row = $(''); - html.push(row); - } - row.append(''); - currentMinute.add(step, 'm'); - } - table.empty().append(html); - }, - - fillSeconds = function () { - var table = widget.find('.timepicker-seconds table'), - currentSecond = viewDate.clone().startOf('m'), - html = [], - row = $(''); - - while (viewDate.isSame(currentSecond, 'm')) { - if (currentSecond.second() % 20 === 0) { - row = $(''); - html.push(row); - } - row.append(''); - currentSecond.add(5, 's'); - } - - table.empty().append(html); - }, - - fillTime = function () { - var toggle, newDate, timeComponents = widget.find('.timepicker span[data-time-component]'); - - if (!use24Hours) { - toggle = widget.find('.timepicker [data-action=togglePeriod]'); - newDate = date.clone().add((date.hours() >= 12) ? -12 : 12, 'h'); - - toggle.text(date.format('A')); - - if (isValid(newDate, 'h')) { - toggle.removeClass('disabled'); - } else { - toggle.addClass('disabled'); - } - } - timeComponents.filter('[data-time-component=hours]').text(date.format(use24Hours ? 'HH' : 'hh')); - timeComponents.filter('[data-time-component=minutes]').text(date.format('mm')); - timeComponents.filter('[data-time-component=seconds]').text(date.format('ss')); - - fillHours(); - fillMinutes(); - fillSeconds(); - }, - - update = function () { - if (!widget) { - return; - } - fillDate(); - fillTime(); - }, - - setValue = function (targetMoment) { - var oldDate = unset ? null : date; - - // case of calling setValue(null or false) - if (!targetMoment) { - unset = true; - input.val(''); - element.data('date', ''); - notifyEvent({ - type: 'dp.change', - date: false, - oldDate: oldDate - }); - update(); - return; - } - - targetMoment = targetMoment.clone().locale(options.locale); - - if (hasTimeZone()) { - targetMoment.tz(options.timeZone); - } - - if (options.stepping !== 1) { - targetMoment.minutes((Math.round(targetMoment.minutes() / options.stepping) * options.stepping)).seconds(0); - - while (options.minDate && targetMoment.isBefore(options.minDate)) { - targetMoment.add(options.stepping, 'minutes'); - } - } - - if (isValid(targetMoment)) { - date = targetMoment; - viewDate = date.clone(); - input.val(date.format(actualFormat)); - element.data('date', date.format(actualFormat)); - unset = false; - update(); - notifyEvent({ - type: 'dp.change', - date: date.clone(), - oldDate: oldDate - }); - } else { - if (!options.keepInvalid) { - input.val(unset ? '' : date.format(actualFormat)); - } else { - notifyEvent({ - type: 'dp.change', - date: targetMoment, - oldDate: oldDate - }); - } - notifyEvent({ - type: 'dp.error', - date: targetMoment, - oldDate: oldDate - }); - } - }, - - /** - * Hides the widget. Possibly will emit dp.hide - */ - hide = function () { - var transitioning = false; - if (!widget) { - return picker; - } - // Ignore event if in the middle of a picker transition - widget.find('.collapse').each(function () { - var collapseData = $(this).data('collapse'); - if (collapseData && collapseData.transitioning) { - transitioning = true; - return false; - } - return true; + if (this.viewSelect >= 4) { + this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0)); + } + } else if (target.is('.hour')) { + hours = parseInt(target.text(), 10) || 0; + if (target.hasClass('hour_am') || target.hasClass('hour_pm')) { + if (hours === 12 && target.hasClass('hour_am')) { + hours = 0; + } else if (hours !== 12 && target.hasClass('hour_pm')) { + hours += 12; + } + } + this.viewDate.setUTCHours(hours); + this.element.trigger({ + type: 'changeHour', + date: this.viewDate }); - if (transitioning) { - return picker; - } - if (component && component.hasClass('btn')) { - component.toggleClass('active'); - } - widget.hide(); - - $(window).off('resize', place); - widget.off('click', '[data-action]'); - widget.off('mousedown', false); - - widget.remove(); - widget = false; - - notifyEvent({ - type: 'dp.hide', - date: date.clone() + if (this.viewSelect >= 1) { + this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0)); + } + } else if (target.is('.minute')) { + minutes = parseInt(target.text().substr(target.text().indexOf(':') + 1), 10) || 0; + this.viewDate.setUTCMinutes(minutes); + this.element.trigger({ + type: 'changeMinute', + date: this.viewDate }); - - input.blur(); - - viewDate = date.clone(); - - return picker; - }, - - clear = function () { - setValue(null); - }, - - parseInputDate = function (inputDate) { - if (options.parseInputDate === undefined) { - if (!moment.isMoment(inputDate) || inputDate instanceof Date) { - inputDate = getMoment(inputDate); - } + if (this.viewSelect >= 0) { + this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0)); + } + } + if (this.viewMode !== 0) { + var oldViewMode = this.viewMode; + this.showMode(-1); + this.fill(); + if (oldViewMode === this.viewMode && this.autoclose) { + this.hide(); + } + } else { + this.fill(); + if (this.autoclose) { + this.hide(); + } + } + } + break; + case 'td': + if (target.is('.day') && !target.is('.disabled')) { + var day = parseInt(target.text(), 10) || 1; + var year = this.viewDate.getUTCFullYear(), + month = this.viewDate.getUTCMonth(), + hours = this.viewDate.getUTCHours(), + minutes = this.viewDate.getUTCMinutes(), + seconds = this.viewDate.getUTCSeconds(); + if (target.is('.old')) { + if (month === 0) { + month = 11; + year -= 1; } else { - inputDate = options.parseInputDate(inputDate); - } - //inputDate.locale(options.locale); - return inputDate; - }, - - /******************************************************************************** - * - * Widget UI interaction functions - * - ********************************************************************************/ - actions = { - next: function () { - var navFnc = datePickerModes[currentViewMode].navFnc; - viewDate.add(datePickerModes[currentViewMode].navStep, navFnc); - fillDate(); - viewUpdate(navFnc); - }, - - previous: function () { - var navFnc = datePickerModes[currentViewMode].navFnc; - viewDate.subtract(datePickerModes[currentViewMode].navStep, navFnc); - fillDate(); - viewUpdate(navFnc); - }, - - pickerSwitch: function () { - showMode(1); - }, - - selectMonth: function (e) { - var month = $(e.target).closest('tbody').find('span').index($(e.target)); - viewDate.month(month); - if (currentViewMode === minViewModeNumber) { - setValue(date.clone().year(viewDate.year()).month(viewDate.month())); - if (!options.inline) { - hide(); - } - } else { - showMode(-1); - fillDate(); - } - viewUpdate('M'); - }, - - selectYear: function (e) { - var year = parseInt($(e.target).text(), 10) || 0; - viewDate.year(year); - if (currentViewMode === minViewModeNumber) { - setValue(date.clone().year(viewDate.year())); - if (!options.inline) { - hide(); - } - } else { - showMode(-1); - fillDate(); - } - viewUpdate('YYYY'); - }, - - selectDecade: function (e) { - var year = parseInt($(e.target).data('selection'), 10) || 0; - viewDate.year(year); - if (currentViewMode === minViewModeNumber) { - setValue(date.clone().year(viewDate.year())); - if (!options.inline) { - hide(); - } - } else { - showMode(-1); - fillDate(); - } - viewUpdate('YYYY'); - }, - - selectDay: function (e) { - var day = viewDate.clone(); - if ($(e.target).is('.old')) { - day.subtract(1, 'M'); - } - if ($(e.target).is('.new')) { - day.add(1, 'M'); - } - setValue(day.date(parseInt($(e.target).text(), 10))); - if (!hasTime() && !options.keepOpen && !options.inline) { - hide(); - } - }, - - incrementHours: function () { - var newDate = date.clone().add(1, 'h'); - if (isValid(newDate, 'h')) { - setValue(newDate); - } - }, - - incrementMinutes: function () { - var newDate = date.clone().add(options.stepping, 'm'); - if (isValid(newDate, 'm')) { - setValue(newDate); - } - }, - - incrementSeconds: function () { - var newDate = date.clone().add(1, 's'); - if (isValid(newDate, 's')) { - setValue(newDate); - } - }, - - decrementHours: function () { - var newDate = date.clone().subtract(1, 'h'); - if (isValid(newDate, 'h')) { - setValue(newDate); - } - }, - - decrementMinutes: function () { - var newDate = date.clone().subtract(options.stepping, 'm'); - if (isValid(newDate, 'm')) { - setValue(newDate); - } - }, - - decrementSeconds: function () { - var newDate = date.clone().subtract(1, 's'); - if (isValid(newDate, 's')) { - setValue(newDate); - } - }, - - togglePeriod: function () { - setValue(date.clone().add((date.hours() >= 12) ? -12 : 12, 'h')); - }, - - togglePicker: function (e) { - var $this = $(e.target), - $parent = $this.closest('ul'), - expanded = $parent.find('.in'), - closed = $parent.find('.collapse:not(.in)'), - collapseData; - - if (expanded && expanded.length) { - collapseData = expanded.data('collapse'); - if (collapseData && collapseData.transitioning) { - return; - } - if (expanded.collapse) { // if collapse plugin is available through bootstrap.js then use it - expanded.collapse('hide'); - closed.collapse('show'); - } else { // otherwise just toggle in class on the two views - expanded.removeClass('in'); - closed.addClass('in'); - } - if ($this.is('span')) { - $this.toggleClass(options.icons.time + ' ' + options.icons.date); - } else { - $this.find('span').toggleClass(options.icons.time + ' ' + options.icons.date); - } - - // NOTE: uncomment if toggled state will be restored in show() - //if (component) { - // component.find('span').toggleClass(options.icons.time + ' ' + options.icons.date); - //} - } - }, - - showPicker: function () { - widget.find('.timepicker > div:not(.timepicker-picker)').hide(); - widget.find('.timepicker .timepicker-picker').show(); - }, - - showHours: function () { - widget.find('.timepicker .timepicker-picker').hide(); - widget.find('.timepicker .timepicker-hours').show(); - }, - - showMinutes: function () { - widget.find('.timepicker .timepicker-picker').hide(); - widget.find('.timepicker .timepicker-minutes').show(); - }, - - showSeconds: function () { - widget.find('.timepicker .timepicker-picker').hide(); - widget.find('.timepicker .timepicker-seconds').show(); - }, - - selectHour: function (e) { - var hour = parseInt($(e.target).text(), 10); - - if (!use24Hours) { - if (date.hours() >= 12) { - if (hour !== 12) { - hour += 12; - } - } else { - if (hour === 12) { - hour = 0; - } - } - } - setValue(date.clone().hours(hour)); - actions.showPicker.call(picker); - }, - - selectMinute: function (e) { - setValue(date.clone().minutes(parseInt($(e.target).text(), 10))); - actions.showPicker.call(picker); - }, - - selectSecond: function (e) { - setValue(date.clone().seconds(parseInt($(e.target).text(), 10))); - actions.showPicker.call(picker); - }, - - clear: clear, - - today: function () { - var todaysDate = getMoment(); - if (isValid(todaysDate, 'd')) { - setValue(todaysDate); - } - }, - - close: hide - }, - - doAction = function (e) { - if ($(e.currentTarget).is('.disabled')) { - return false; - } - actions[$(e.currentTarget).data('action')].apply(picker, arguments); - return false; - }, - - /** - * Shows the widget. Possibly will emit dp.show and dp.change - */ - show = function () { - var currentMoment, - useCurrentGranularity = { - 'year': function (m) { - return m.month(0).date(1).hours(0).seconds(0).minutes(0); - }, - 'month': function (m) { - return m.date(1).hours(0).seconds(0).minutes(0); - }, - 'day': function (m) { - return m.hours(0).seconds(0).minutes(0); - }, - 'hour': function (m) { - return m.seconds(0).minutes(0); - }, - 'minute': function (m) { - return m.seconds(0); - } - }; - - if (input.prop('disabled') || (!options.ignoreReadonly && input.prop('readonly')) || widget) { - return picker; - } - if (input.val() !== undefined && input.val().trim().length !== 0) { - setValue(parseInputDate(input.val().trim())); - } else if (unset && options.useCurrent && (options.inline || (input.is('input') && input.val().trim().length === 0))) { - currentMoment = getMoment(); - if (typeof options.useCurrent === 'string') { - currentMoment = useCurrentGranularity[options.useCurrent](currentMoment); - } - setValue(currentMoment); - } - widget = getTemplate(); - - fillDow(); - fillMonths(); - - widget.find('.timepicker-hours').hide(); - widget.find('.timepicker-minutes').hide(); - widget.find('.timepicker-seconds').hide(); - - update(); - showMode(); - - $(window).on('resize', place); - widget.on('click', '[data-action]', doAction); // this handles clicks on the widget - widget.on('mousedown', false); - - if (component && component.hasClass('btn')) { - component.toggleClass('active'); - } - place(); - widget.show(); - if (options.focusOnShow && !input.is(':focus')) { - input.focus(); - } - - notifyEvent({ - type: 'dp.show' - }); - return picker; - }, - - /** - * Shows or hides the widget - */ - toggle = function () { - return (widget ? hide() : show()); - }, - - keydown = function (e) { - var handler = null, - index, - index2, - pressedKeys = [], - pressedModifiers = {}, - currentKey = e.which, - keyBindKeys, - allModifiersPressed, - pressed = 'p'; - - keyState[currentKey] = pressed; - - for (index in keyState) { - if (keyState.hasOwnProperty(index) && keyState[index] === pressed) { - pressedKeys.push(index); - if (parseInt(index, 10) !== currentKey) { - pressedModifiers[index] = true; - } - } - } - - for (index in options.keyBinds) { - if (options.keyBinds.hasOwnProperty(index) && typeof (options.keyBinds[index]) === 'function') { - keyBindKeys = index.split(' '); - if (keyBindKeys.length === pressedKeys.length && keyMap[currentKey] === keyBindKeys[keyBindKeys.length - 1]) { - allModifiersPressed = true; - for (index2 = keyBindKeys.length - 2; index2 >= 0; index2--) { - if (!(keyMap[keyBindKeys[index2]] in pressedModifiers)) { - allModifiersPressed = false; - break; - } - } - if (allModifiersPressed) { - handler = options.keyBinds[index]; - break; - } - } - } - } - - if (handler) { - handler.call(picker, widget); - e.stopPropagation(); - e.preventDefault(); - } - }, - - keyup = function (e) { - keyState[e.which] = 'r'; - e.stopPropagation(); - e.preventDefault(); - }, - - change = function (e) { - var val = $(e.target).val().trim(), - parsedDate = val ? parseInputDate(val) : null; - setValue(parsedDate); - e.stopImmediatePropagation(); - return false; - }, - - attachDatePickerElementEvents = function () { - input.on({ - 'change': change, - 'blur': options.debug ? '' : hide, - 'keydown': keydown, - 'keyup': keyup, - 'focus': options.allowInputToggle ? show : '' - }); - - if (element.is('input')) { - input.on({ - 'focus': show - }); - } else if (component) { - component.on('click', toggle); - component.on('mousedown', false); + month -= 1; } - }, - - detachDatePickerElementEvents = function () { - input.off({ - 'change': change, - 'blur': blur, - 'keydown': keydown, - 'keyup': keyup, - 'focus': options.allowInputToggle ? hide : '' - }); - - if (element.is('input')) { - input.off({ - 'focus': show - }); - } else if (component) { - component.off('click', toggle); - component.off('mousedown', false); - } - }, - - indexGivenDates = function (givenDatesArray) { - // Store given enabledDates and disabledDates as keys. - // This way we can check their existence in O(1) time instead of looping through whole array. - // (for example: options.enabledDates['2014-02-27'] === true) - var givenDatesIndexed = {}; - $.each(givenDatesArray, function () { - var dDate = parseInputDate(this); - if (dDate.isValid()) { - givenDatesIndexed[dDate.format('YYYY-MM-DD')] = true; - } - }); - return (Object.keys(givenDatesIndexed).length) ? givenDatesIndexed : false; - }, - - indexGivenHours = function (givenHoursArray) { - // Store given enabledHours and disabledHours as keys. - // This way we can check their existence in O(1) time instead of looping through whole array. - // (for example: options.enabledHours['2014-02-27'] === true) - var givenHoursIndexed = {}; - $.each(givenHoursArray, function () { - givenHoursIndexed[this] = true; + } else if (target.is('.new')) { + if (month === 11) { + month = 0; + year += 1; + } else { + month += 1; + } + } + this.viewDate.setUTCFullYear(year); + this.viewDate.setUTCMonth(month, day); + this.element.trigger({ + type: 'changeDay', + date: this.viewDate + }); + if (this.viewSelect >= 2) { + this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0)); + } + } + var oldViewMode = this.viewMode; + this.showMode(-1); + this.fill(); + if (oldViewMode === this.viewMode && this.autoclose) { + this.hide(); + } + break; + } + } + }, + + _setDate: function (date, which) { + if (!which || which === 'date') + this.date = date; + if (!which || which === 'view') + this.viewDate = date; + this.fill(); + this.setValue(); + var element; + if (this.isInput) { + element = this.element; + } else if (this.component) { + element = this.element.find('input'); + } + if (element) { + element.change(); + } + this.element.trigger({ + type: 'changeDate', + date: this.getDate() + }); + if(date === null) + this.date = this.viewDate; + }, + + moveMinute: function (date, dir) { + if (!dir) return date; + var new_date = new Date(date.valueOf()); + //dir = dir > 0 ? 1 : -1; + new_date.setUTCMinutes(new_date.getUTCMinutes() + (dir * this.minuteStep)); + return new_date; + }, + + moveHour: function (date, dir) { + if (!dir) return date; + var new_date = new Date(date.valueOf()); + //dir = dir > 0 ? 1 : -1; + new_date.setUTCHours(new_date.getUTCHours() + dir); + return new_date; + }, + + moveDate: function (date, dir) { + if (!dir) return date; + var new_date = new Date(date.valueOf()); + //dir = dir > 0 ? 1 : -1; + new_date.setUTCDate(new_date.getUTCDate() + dir); + return new_date; + }, + + moveMonth: function (date, dir) { + if (!dir) return date; + var new_date = new Date(date.valueOf()), + day = new_date.getUTCDate(), + month = new_date.getUTCMonth(), + mag = Math.abs(dir), + new_month, test; + dir = dir > 0 ? 1 : -1; + if (mag === 1) { + test = dir === -1 + // If going back one month, make sure month is not current month + // (eg, Mar 31 -> Feb 31 === Feb 28, not Mar 02) + ? function () { + return new_date.getUTCMonth() === month; + } + // If going forward one month, make sure month is as expected + // (eg, Jan 31 -> Feb 31 === Feb 28, not Mar 02) + : function () { + return new_date.getUTCMonth() !== new_month; + }; + new_month = month + dir; + new_date.setUTCMonth(new_month); + // Dec -> Jan (12) or Jan -> Dec (-1) -- limit expected date to 0-11 + if (new_month < 0 || new_month > 11) + new_month = (new_month + 12) % 12; + } else { + // For magnitudes >1, move one month at a time... + for (var i = 0; i < mag; i++) + // ...which might decrease the day (eg, Jan 31 to Feb 28, etc)... + new_date = this.moveMonth(new_date, dir); + // ...then reset the day, keeping it in the new month + new_month = new_date.getUTCMonth(); + new_date.setUTCDate(day); + test = function () { + return new_month !== new_date.getUTCMonth(); + }; + } + // Common date-resetting loop -- if date is beyond end of month, make it + // end of month + while (test()) { + new_date.setUTCDate(--day); + new_date.setUTCMonth(new_month); + } + return new_date; + }, + + moveYear: function (date, dir) { + return this.moveMonth(date, dir * 12); + }, + + dateWithinRange: function (date) { + return date >= this.startDate && date <= this.endDate; + }, + + keydown: function (e) { + if (this.picker.is(':not(:visible)')) { + if (e.keyCode === 27) // allow escape to hide and re-show picker + this.show(); + return; + } + var dateChanged = false, + dir, newDate, newViewDate; + switch (e.keyCode) { + case 27: // escape + this.hide(); + e.preventDefault(); + break; + case 37: // left + case 39: // right + if (!this.keyboardNavigation) break; + dir = e.keyCode === 37 ? -1 : 1; + var viewMode = this.viewMode; + if (e.ctrlKey) { + viewMode += 2; + } else if (e.shiftKey) { + viewMode += 1; + } + if (viewMode === 4) { + newDate = this.moveYear(this.date, dir); + newViewDate = this.moveYear(this.viewDate, dir); + } else if (viewMode === 3) { + newDate = this.moveMonth(this.date, dir); + newViewDate = this.moveMonth(this.viewDate, dir); + } else if (viewMode === 2) { + newDate = this.moveDate(this.date, dir); + newViewDate = this.moveDate(this.viewDate, dir); + } else if (viewMode === 1) { + newDate = this.moveHour(this.date, dir); + newViewDate = this.moveHour(this.viewDate, dir); + } else if (viewMode === 0) { + newDate = this.moveMinute(this.date, dir); + newViewDate = this.moveMinute(this.viewDate, dir); + } + if (this.dateWithinRange(newDate)) { + this.date = newDate; + this.viewDate = newViewDate; + this.setValue(); + this.update(); + e.preventDefault(); + dateChanged = true; + } + break; + case 38: // up + case 40: // down + if (!this.keyboardNavigation) break; + dir = e.keyCode === 38 ? -1 : 1; + viewMode = this.viewMode; + if (e.ctrlKey) { + viewMode += 2; + } else if (e.shiftKey) { + viewMode += 1; + } + if (viewMode === 4) { + newDate = this.moveYear(this.date, dir); + newViewDate = this.moveYear(this.viewDate, dir); + } else if (viewMode === 3) { + newDate = this.moveMonth(this.date, dir); + newViewDate = this.moveMonth(this.viewDate, dir); + } else if (viewMode === 2) { + newDate = this.moveDate(this.date, dir * 7); + newViewDate = this.moveDate(this.viewDate, dir * 7); + } else if (viewMode === 1) { + if (this.showMeridian) { + newDate = this.moveHour(this.date, dir * 6); + newViewDate = this.moveHour(this.viewDate, dir * 6); + } else { + newDate = this.moveHour(this.date, dir * 4); + newViewDate = this.moveHour(this.viewDate, dir * 4); + } + } else if (viewMode === 0) { + newDate = this.moveMinute(this.date, dir * 4); + newViewDate = this.moveMinute(this.viewDate, dir * 4); + } + if (this.dateWithinRange(newDate)) { + this.date = newDate; + this.viewDate = newViewDate; + this.setValue(); + this.update(); + e.preventDefault(); + dateChanged = true; + } + break; + case 13: // enter + if (this.viewMode !== 0) { + var oldViewMode = this.viewMode; + this.showMode(-1); + this.fill(); + if (oldViewMode === this.viewMode && this.autoclose) { + this.hide(); + } + } else { + this.fill(); + if (this.autoclose) { + this.hide(); + } + } + e.preventDefault(); + break; + case 9: // tab + this.hide(); + break; + } + if (dateChanged) { + var element; + if (this.isInput) { + element = this.element; + } else if (this.component) { + element = this.element.find('input'); + } + if (element) { + element.change(); + } + this.element.trigger({ + type: 'changeDate', + date: this.getDate() + }); + } + }, + + showMode: function (dir) { + if (dir) { + var newViewMode = Math.max(0, Math.min(DPGlobal.modes.length - 1, this.viewMode + dir)); + if (newViewMode >= this.minView && newViewMode <= this.maxView) { + this.element.trigger({ + type: 'changeMode', + date: this.viewDate, + oldViewMode: this.viewMode, + newViewMode: newViewMode + }); + + this.viewMode = newViewMode; + } + } + /* + vitalets: fixing bug of very special conditions: + jquery 1.7.1 + webkit + show inline datetimepicker in bootstrap popover. + Method show() does not set display css correctly and datetimepicker is not shown. + Changed to .css('display', 'block') solve the problem. + See https://github.com/vitalets/x-editable/issues/37 + + In jquery 1.7.2+ everything works fine. + */ + //this.picker.find('>div').hide().filter('.datetimepicker-'+DPGlobal.modes[this.viewMode].clsName).show(); + this.picker.find('>div').hide().filter('.datetimepicker-' + DPGlobal.modes[this.viewMode].clsName).css('display', 'block'); + this.updateNavArrows(); + }, + + reset: function () { + this._setDate(null, 'date'); + }, + + convertViewModeText: function (viewMode) { + switch (viewMode) { + case 4: + return 'decade'; + case 3: + return 'year'; + case 2: + return 'month'; + case 1: + return 'day'; + case 0: + return 'hour'; + } + } + }; + + var old = $.fn.datetimepicker; + $.fn.datetimepicker = function (option) { + var args = Array.apply(null, arguments); + args.shift(); + var internal_return; + this.each(function () { + var $this = $(this), + data = $this.data('datetimepicker'), + options = typeof option === 'object' && option; + if (!data) { + $this.data('datetimepicker', (data = new Datetimepicker(this, $.extend({}, $.fn.datetimepicker.defaults, options)))); + } + if (typeof option === 'string' && typeof data[option] === 'function') { + internal_return = data[option].apply(data, args); + if (internal_return !== undefined) { + return false; + } + } + }); + if (internal_return !== undefined) + return internal_return; + else + return this; + }; + + $.fn.datetimepicker.defaults = { + }; + $.fn.datetimepicker.Constructor = Datetimepicker; + var dates = $.fn.datetimepicker.dates = { + en: { + days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'], + daysShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], + daysMin: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su'], + months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], + monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], + meridiem: ['am', 'pm'], + suffix: ['st', 'nd', 'rd', 'th'], + today: 'Today', + clear: 'Clear' + } + }; + + var DPGlobal = { + modes: [ + { + clsName: 'minutes', + navFnc: 'Hours', + navStep: 1 + }, + { + clsName: 'hours', + navFnc: 'Date', + navStep: 1 + }, + { + clsName: 'days', + navFnc: 'Month', + navStep: 1 + }, + { + clsName: 'months', + navFnc: 'FullYear', + navStep: 1 + }, + { + clsName: 'years', + navFnc: 'FullYear', + navStep: 10 + } + ], + isLeapYear: function (year) { + return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0)) + }, + getDaysInMonth: function (year, month) { + return [31, (DPGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month] + }, + getDefaultFormat: function (type, field) { + if (type === 'standard') { + if (field === 'input') + return 'yyyy-mm-dd hh:ii'; + else + return 'yyyy-mm-dd hh:ii:ss'; + } else if (type === 'php') { + if (field === 'input') + return 'Y-m-d H:i'; + else + return 'Y-m-d H:i:s'; + } else { + throw new Error('Invalid format type.'); + } + }, + validParts: function (type) { + if (type === 'standard') { + return /t|hh?|HH?|p|P|z|Z|ii?|ss?|dd?|DD?|mm?|MM?|yy(?:yy)?/g; + } else if (type === 'php') { + return /[dDjlNwzFmMnStyYaABgGhHis]/g; + } else { + throw new Error('Invalid format type.'); + } + }, + nonpunctuation: /[^ -\/:-@\[-`{-~\t\n\rTZ]+/g, + parseFormat: function (format, type) { + // IE treats \0 as a string end in inputs (truncating the value), + // so it's a bad format delimiter, anyway + var separators = format.replace(this.validParts(type), '\0').split('\0'), + parts = format.match(this.validParts(type)); + if (!separators || !separators.length || !parts || parts.length === 0) { + throw new Error('Invalid date format.'); + } + return {separators: separators, parts: parts}; + }, + parseDate: function (date, format, language, type, timezone) { + if (date instanceof Date) { + var dateUTC = new Date(date.valueOf() - date.getTimezoneOffset() * 60000); + dateUTC.setMilliseconds(0); + return dateUTC; + } + if (/^\d{4}\-\d{1,2}\-\d{1,2}$/.test(date)) { + format = this.parseFormat('yyyy-mm-dd', type); + } + if (/^\d{4}\-\d{1,2}\-\d{1,2}[T ]\d{1,2}\:\d{1,2}$/.test(date)) { + format = this.parseFormat('yyyy-mm-dd hh:ii', type); + } + if (/^\d{4}\-\d{1,2}\-\d{1,2}[T ]\d{1,2}\:\d{1,2}\:\d{1,2}[Z]{0,1}$/.test(date)) { + format = this.parseFormat('yyyy-mm-dd hh:ii:ss', type); + } + if (/^[-+]\d+[dmwy]([\s,]+[-+]\d+[dmwy])*$/.test(date)) { + var part_re = /([-+]\d+)([dmwy])/, + parts = date.match(/([-+]\d+)([dmwy])/g), + part, dir; + date = new Date(); + for (var i = 0; i < parts.length; i++) { + part = part_re.exec(parts[i]); + dir = parseInt(part[1]); + switch (part[2]) { + case 'd': + date.setUTCDate(date.getUTCDate() + dir); + break; + case 'm': + date = Datetimepicker.prototype.moveMonth.call(Datetimepicker.prototype, date, dir); + break; + case 'w': + date.setUTCDate(date.getUTCDate() + dir * 7); + break; + case 'y': + date = Datetimepicker.prototype.moveYear.call(Datetimepicker.prototype, date, dir); + break; + } + } + return UTCDate(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds(), 0); + } + var parts = date && date.toString().match(this.nonpunctuation) || [], + date = new Date(0, 0, 0, 0, 0, 0, 0), + parsed = {}, + setters_order = ['hh', 'h', 'ii', 'i', 'ss', 's', 'yyyy', 'yy', 'M', 'MM', 'm', 'mm', 'D', 'DD', 'd', 'dd', 'H', 'HH', 'p', 'P', 'z', 'Z'], + setters_map = { + hh: function (d, v) { + return d.setUTCHours(v); + }, + h: function (d, v) { + return d.setUTCHours(v); + }, + HH: function (d, v) { + return d.setUTCHours(v === 12 ? 0 : v); + }, + H: function (d, v) { + return d.setUTCHours(v === 12 ? 0 : v); + }, + ii: function (d, v) { + return d.setUTCMinutes(v); + }, + i: function (d, v) { + return d.setUTCMinutes(v); + }, + ss: function (d, v) { + return d.setUTCSeconds(v); + }, + s: function (d, v) { + return d.setUTCSeconds(v); + }, + yyyy: function (d, v) { + return d.setUTCFullYear(v); + }, + yy: function (d, v) { + return d.setUTCFullYear(2000 + v); + }, + m: function (d, v) { + v -= 1; + while (v < 0) v += 12; + v %= 12; + d.setUTCMonth(v); + while (d.getUTCMonth() !== v) + if (isNaN(d.getUTCMonth())) + return d; + else + d.setUTCDate(d.getUTCDate() - 1); + return d; + }, + d: function (d, v) { + return d.setUTCDate(v); + }, + p: function (d, v) { + return d.setUTCHours(v === 1 ? d.getUTCHours() + 12 : d.getUTCHours()); + }, + z: function () { + return timezone + } + }, + val, filtered, part; + setters_map['M'] = setters_map['MM'] = setters_map['mm'] = setters_map['m']; + setters_map['dd'] = setters_map['d']; + setters_map['P'] = setters_map['p']; + setters_map['Z'] = setters_map['z']; + date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds()); + if (parts.length === format.parts.length) { + for (var i = 0, cnt = format.parts.length; i < cnt; i++) { + val = parseInt(parts[i], 10); + part = format.parts[i]; + if (isNaN(val)) { + switch (part) { + case 'MM': + filtered = $(dates[language].months).filter(function () { + var m = this.slice(0, parts[i].length), + p = parts[i].slice(0, m.length); + return m === p; }); - return (Object.keys(givenHoursIndexed).length) ? givenHoursIndexed : false; - }, - - initFormatting = function () { - var format = options.format || 'L LT'; - - actualFormat = format.replace(/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g, function (formatInput) { - var newinput = date.localeData().longDateFormat(formatInput) || formatInput; - return newinput.replace(/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g, function (formatInput2) { //temp fix for #740 - return date.localeData().longDateFormat(formatInput2) || formatInput2; - }); + val = $.inArray(filtered[0], dates[language].months) + 1; + break; + case 'M': + filtered = $(dates[language].monthsShort).filter(function () { + var m = this.slice(0, parts[i].length), + p = parts[i].slice(0, m.length); + return m.toLowerCase() === p.toLowerCase(); }); - - - parseFormats = options.extraFormats ? options.extraFormats.slice() : []; - if (parseFormats.indexOf(format) < 0 && parseFormats.indexOf(actualFormat) < 0) { - parseFormats.push(actualFormat); - } - - use24Hours = (actualFormat.toLowerCase().indexOf('a') < 1 && actualFormat.replace(/\[.*?\]/g, '').indexOf('h') < 1); - - if (isEnabled('y')) { - minViewModeNumber = 2; - } - if (isEnabled('M')) { - minViewModeNumber = 1; - } - if (isEnabled('d')) { - minViewModeNumber = 0; - } - - currentViewMode = Math.max(minViewModeNumber, currentViewMode); - - if (!unset) { - setValue(date); - } - }; - - /******************************************************************************** - * - * Public API functions - * ===================== - * - * Important: Do not expose direct references to private objects or the options - * object to the outer world. Always return a clone when returning values or make - * a clone when setting a private variable. - * - ********************************************************************************/ - picker.destroy = function () { - ///Destroys the widget and removes all attached event listeners - hide(); - detachDatePickerElementEvents(); - element.removeData('DateTimePicker'); - element.removeData('date'); + val = $.inArray(filtered[0], dates[language].monthsShort) + 1; + break; + case 'p': + case 'P': + val = $.inArray(parts[i].toLowerCase(), dates[language].meridiem); + break; + case 'z': + case 'Z': + timezone; + break; + + } + } + parsed[part] = val; + } + for (var i = 0, s; i < setters_order.length; i++) { + s = setters_order[i]; + if (s in parsed && !isNaN(parsed[s])) + setters_map[s](date, parsed[s]) + } + } + return date; + }, + formatDate: function (date, format, language, type, timezone) { + if (date === null) { + return ''; + } + var val; + if (type === 'standard') { + val = { + t: date.getTime(), + // year + yy: date.getUTCFullYear().toString().substring(2), + yyyy: date.getUTCFullYear(), + // month + m: date.getUTCMonth() + 1, + M: dates[language].monthsShort[date.getUTCMonth()], + MM: dates[language].months[date.getUTCMonth()], + // day + d: date.getUTCDate(), + D: dates[language].daysShort[date.getUTCDay()], + DD: dates[language].days[date.getUTCDay()], + p: (dates[language].meridiem.length === 2 ? dates[language].meridiem[date.getUTCHours() < 12 ? 0 : 1] : ''), + // hour + h: date.getUTCHours(), + // minute + i: date.getUTCMinutes(), + // second + s: date.getUTCSeconds(), + // timezone + z: timezone }; - picker.toggle = toggle; - - picker.show = show; - - picker.hide = hide; - - picker.disable = function () { - ///Disables the input element, the component is attached to, by adding a disabled="true" attribute to it. - ///If the widget was visible before that call it is hidden. Possibly emits dp.hide - hide(); - if (component && component.hasClass('btn')) { - component.addClass('disabled'); - } - input.prop('disabled', true); - return picker; - }; - - picker.enable = function () { - ///Enables the input element, the component is attached to, by removing disabled attribute from it. - if (component && component.hasClass('btn')) { - component.removeClass('disabled'); - } - input.prop('disabled', false); - return picker; - }; - - picker.ignoreReadonly = function (ignoreReadonly) { - if (arguments.length === 0) { - return options.ignoreReadonly; - } - if (typeof ignoreReadonly !== 'boolean') { - throw new TypeError('ignoreReadonly () expects a boolean parameter'); - } - options.ignoreReadonly = ignoreReadonly; - return picker; - }; - - picker.options = function (newOptions) { - if (arguments.length === 0) { - return $.extend(true, {}, options); - } - - if (!(newOptions instanceof Object)) { - throw new TypeError('options() options parameter should be an object'); - } - $.extend(true, options, newOptions); - $.each(options, function (key, value) { - if (picker[key] !== undefined) { - picker[key](value); - } else { - throw new TypeError('option ' + key + ' is not recognized!'); - } - }); - return picker; - }; - - picker.date = function (newDate) { - /// - ///Returns the component's model current date, a moment object or null if not set. - ///date.clone() - /// - /// - ///Sets the components model current moment to it. Passing a null value unsets the components model current moment. Parsing of the newDate parameter is made using moment library with the options.format and options.useStrict components configuration. - ///Takes string, Date, moment, null parameter. - /// - if (arguments.length === 0) { - if (unset) { - return null; - } - return date.clone(); - } - - if (newDate !== null && typeof newDate !== 'string' && !moment.isMoment(newDate) && !(newDate instanceof Date)) { - throw new TypeError('date() parameter must be one of [null, string, moment or Date]'); - } - - setValue(newDate === null ? null : parseInputDate(newDate)); - return picker; - }; - - picker.format = function (newFormat) { - ///test su - ///info about para - ///returns foo - if (arguments.length === 0) { - return options.format; - } - - if ((typeof newFormat !== 'string') && ((typeof newFormat !== 'boolean') || (newFormat !== false))) { - throw new TypeError('format() expects a string or boolean:false parameter ' + newFormat); - } - - options.format = newFormat; - if (actualFormat) { - initFormatting(); // reinit formatting - } - return picker; - }; - - picker.timeZone = function (newZone) { - if (arguments.length === 0) { - return options.timeZone; - } - - if (typeof newZone !== 'string') { - throw new TypeError('newZone() expects a string parameter'); - } - - options.timeZone = newZone; - - return picker; - }; - - picker.dayViewHeaderFormat = function (newFormat) { - if (arguments.length === 0) { - return options.dayViewHeaderFormat; - } - - if (typeof newFormat !== 'string') { - throw new TypeError('dayViewHeaderFormat() expects a string parameter'); - } - - options.dayViewHeaderFormat = newFormat; - return picker; - }; - - picker.extraFormats = function (formats) { - if (arguments.length === 0) { - return options.extraFormats; - } - - if (formats !== false && !(formats instanceof Array)) { - throw new TypeError('extraFormats() expects an array or false parameter'); - } - - options.extraFormats = formats; - if (parseFormats) { - initFormatting(); // reinit formatting - } - return picker; - }; - - picker.disabledDates = function (dates) { - /// - ///Returns an array with the currently set disabled dates on the component. - ///options.disabledDates - /// - /// - ///Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of - ///options.enabledDates if such exist. - ///Takes an [ string or Date or moment ] of values and allows the user to select only from those days. - /// - if (arguments.length === 0) { - return (options.disabledDates ? $.extend({}, options.disabledDates) : options.disabledDates); - } - - if (!dates) { - options.disabledDates = false; - update(); - return picker; - } - if (!(dates instanceof Array)) { - throw new TypeError('disabledDates() expects an array parameter'); - } - options.disabledDates = indexGivenDates(dates); - options.enabledDates = false; - update(); - return picker; - }; - - picker.enabledDates = function (dates) { - /// - ///Returns an array with the currently set enabled dates on the component. - ///options.enabledDates - /// - /// - ///Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of options.disabledDates if such exist. - ///Takes an [ string or Date or moment ] of values and allows the user to select only from those days. - /// - if (arguments.length === 0) { - return (options.enabledDates ? $.extend({}, options.enabledDates) : options.enabledDates); - } - - if (!dates) { - options.enabledDates = false; - update(); - return picker; - } - if (!(dates instanceof Array)) { - throw new TypeError('enabledDates() expects an array parameter'); - } - options.enabledDates = indexGivenDates(dates); - options.disabledDates = false; - update(); - return picker; - }; - - picker.daysOfWeekDisabled = function (daysOfWeekDisabled) { - if (arguments.length === 0) { - return options.daysOfWeekDisabled.splice(0); - } - - if ((typeof daysOfWeekDisabled === 'boolean') && !daysOfWeekDisabled) { - options.daysOfWeekDisabled = false; - update(); - return picker; - } - - if (!(daysOfWeekDisabled instanceof Array)) { - throw new TypeError('daysOfWeekDisabled() expects an array parameter'); - } - options.daysOfWeekDisabled = daysOfWeekDisabled.reduce(function (previousValue, currentValue) { - currentValue = parseInt(currentValue, 10); - if (currentValue > 6 || currentValue < 0 || isNaN(currentValue)) { - return previousValue; - } - if (previousValue.indexOf(currentValue) === -1) { - previousValue.push(currentValue); - } - return previousValue; - }, []).sort(); - if (options.useCurrent && !options.keepInvalid) { - var tries = 0; - while (!isValid(date, 'd')) { - date.add(1, 'd'); - if (tries === 31) { - throw 'Tried 31 times to find a valid date'; - } - tries++; - } - setValue(date); - } - update(); - return picker; - }; - - picker.maxDate = function (maxDate) { - if (arguments.length === 0) { - return options.maxDate ? options.maxDate.clone() : options.maxDate; - } - - if ((typeof maxDate === 'boolean') && maxDate === false) { - options.maxDate = false; - update(); - return picker; - } - - if (typeof maxDate === 'string') { - if (maxDate === 'now' || maxDate === 'moment') { - maxDate = getMoment(); - } - } - - var parsedDate = parseInputDate(maxDate); - - if (!parsedDate.isValid()) { - throw new TypeError('maxDate() Could not parse date parameter: ' + maxDate); - } - if (options.minDate && parsedDate.isBefore(options.minDate)) { - throw new TypeError('maxDate() date parameter is before options.minDate: ' + parsedDate.format(actualFormat)); - } - options.maxDate = parsedDate; - if (options.useCurrent && !options.keepInvalid && date.isAfter(maxDate)) { - setValue(options.maxDate); - } - if (viewDate.isAfter(parsedDate)) { - viewDate = parsedDate.clone().subtract(options.stepping, 'm'); - } - update(); - return picker; - }; - - picker.minDate = function (minDate) { - if (arguments.length === 0) { - return options.minDate ? options.minDate.clone() : options.minDate; - } - - if ((typeof minDate === 'boolean') && minDate === false) { - options.minDate = false; - update(); - return picker; - } - - if (typeof minDate === 'string') { - if (minDate === 'now' || minDate === 'moment') { - minDate = getMoment(); - } - } - - var parsedDate = parseInputDate(minDate); - - if (!parsedDate.isValid()) { - throw new TypeError('minDate() Could not parse date parameter: ' + minDate); - } - if (options.maxDate && parsedDate.isAfter(options.maxDate)) { - throw new TypeError('minDate() date parameter is after options.maxDate: ' + parsedDate.format(actualFormat)); - } - options.minDate = parsedDate; - if (options.useCurrent && !options.keepInvalid && date.isBefore(minDate)) { - setValue(options.minDate); - } - if (viewDate.isBefore(parsedDate)) { - viewDate = parsedDate.clone().add(options.stepping, 'm'); - } - update(); - return picker; - }; - - picker.defaultDate = function (defaultDate) { - /// - ///Returns a moment with the options.defaultDate option configuration or false if not set - ///date.clone() - /// - /// - ///Will set the picker's inital date. If a boolean:false value is passed the options.defaultDate parameter is cleared. - ///Takes a string, Date, moment, boolean:false - /// - if (arguments.length === 0) { - return options.defaultDate ? options.defaultDate.clone() : options.defaultDate; - } - if (!defaultDate) { - options.defaultDate = false; - return picker; - } - - if (typeof defaultDate === 'string') { - if (defaultDate === 'now' || defaultDate === 'moment') { - defaultDate = getMoment(); - } else { - defaultDate = getMoment(defaultDate); - } - } - - var parsedDate = parseInputDate(defaultDate); - if (!parsedDate.isValid()) { - throw new TypeError('defaultDate() Could not parse date parameter: ' + defaultDate); - } - if (!isValid(parsedDate)) { - throw new TypeError('defaultDate() date passed is invalid according to component setup validations'); - } - - options.defaultDate = parsedDate; - - if ((options.defaultDate && options.inline) || input.val().trim() === '') { - setValue(options.defaultDate); - } - return picker; - }; - - picker.locale = function (locale) { - if (arguments.length === 0) { - return options.locale; - } - - if (!moment.localeData(locale)) { - throw new TypeError('locale() locale ' + locale + ' is not loaded from moment locales!'); - } - - options.locale = locale; - date.locale(options.locale); - viewDate.locale(options.locale); - - if (actualFormat) { - initFormatting(); // reinit formatting - } - if (widget) { - hide(); - show(); - } - return picker; - }; - - picker.stepping = function (stepping) { - if (arguments.length === 0) { - return options.stepping; - } - - stepping = parseInt(stepping, 10); - if (isNaN(stepping) || stepping < 1) { - stepping = 1; - } - options.stepping = stepping; - return picker; - }; - - picker.useCurrent = function (useCurrent) { - var useCurrentOptions = ['year', 'month', 'day', 'hour', 'minute']; - if (arguments.length === 0) { - return options.useCurrent; - } - - if ((typeof useCurrent !== 'boolean') && (typeof useCurrent !== 'string')) { - throw new TypeError('useCurrent() expects a boolean or string parameter'); - } - if (typeof useCurrent === 'string' && useCurrentOptions.indexOf(useCurrent.toLowerCase()) === -1) { - throw new TypeError('useCurrent() expects a string parameter of ' + useCurrentOptions.join(', ')); - } - options.useCurrent = useCurrent; - return picker; - }; - - picker.collapse = function (collapse) { - if (arguments.length === 0) { - return options.collapse; - } - - if (typeof collapse !== 'boolean') { - throw new TypeError('collapse() expects a boolean parameter'); - } - if (options.collapse === collapse) { - return picker; - } - options.collapse = collapse; - if (widget) { - hide(); - show(); - } - return picker; - }; - - picker.icons = function (icons) { - if (arguments.length === 0) { - return $.extend({}, options.icons); - } - - if (!(icons instanceof Object)) { - throw new TypeError('icons() expects parameter to be an Object'); - } - $.extend(options.icons, icons); - if (widget) { - hide(); - show(); - } - return picker; - }; - - picker.tooltips = function (tooltips) { - if (arguments.length === 0) { - return $.extend({}, options.tooltips); - } - - if (!(tooltips instanceof Object)) { - throw new TypeError('tooltips() expects parameter to be an Object'); - } - $.extend(options.tooltips, tooltips); - if (widget) { - hide(); - show(); - } - return picker; - }; - - picker.useStrict = function (useStrict) { - if (arguments.length === 0) { - return options.useStrict; - } - - if (typeof useStrict !== 'boolean') { - throw new TypeError('useStrict() expects a boolean parameter'); - } - options.useStrict = useStrict; - return picker; - }; - - picker.sideBySide = function (sideBySide) { - if (arguments.length === 0) { - return options.sideBySide; - } - - if (typeof sideBySide !== 'boolean') { - throw new TypeError('sideBySide() expects a boolean parameter'); - } - options.sideBySide = sideBySide; - if (widget) { - hide(); - show(); - } - return picker; - }; - - picker.viewMode = function (viewMode) { - if (arguments.length === 0) { - return options.viewMode; - } - - if (typeof viewMode !== 'string') { - throw new TypeError('viewMode() expects a string parameter'); - } - - if (viewModes.indexOf(viewMode) === -1) { - throw new TypeError('viewMode() parameter must be one of (' + viewModes.join(', ') + ') value'); - } - - options.viewMode = viewMode; - currentViewMode = Math.max(viewModes.indexOf(viewMode), minViewModeNumber); - - showMode(); - return picker; - }; - - picker.toolbarPlacement = function (toolbarPlacement) { - if (arguments.length === 0) { - return options.toolbarPlacement; - } - - if (typeof toolbarPlacement !== 'string') { - throw new TypeError('toolbarPlacement() expects a string parameter'); - } - if (toolbarPlacements.indexOf(toolbarPlacement) === -1) { - throw new TypeError('toolbarPlacement() parameter must be one of (' + toolbarPlacements.join(', ') + ') value'); - } - options.toolbarPlacement = toolbarPlacement; - - if (widget) { - hide(); - show(); - } - return picker; - }; - - picker.widgetPositioning = function (widgetPositioning) { - if (arguments.length === 0) { - return $.extend({}, options.widgetPositioning); - } - - if (({}).toString.call(widgetPositioning) !== '[object Object]') { - throw new TypeError('widgetPositioning() expects an object variable'); - } - if (widgetPositioning.horizontal) { - if (typeof widgetPositioning.horizontal !== 'string') { - throw new TypeError('widgetPositioning() horizontal variable must be a string'); - } - widgetPositioning.horizontal = widgetPositioning.horizontal.toLowerCase(); - if (horizontalModes.indexOf(widgetPositioning.horizontal) === -1) { - throw new TypeError('widgetPositioning() expects horizontal parameter to be one of (' + horizontalModes.join(', ') + ')'); - } - options.widgetPositioning.horizontal = widgetPositioning.horizontal; - } - if (widgetPositioning.vertical) { - if (typeof widgetPositioning.vertical !== 'string') { - throw new TypeError('widgetPositioning() vertical variable must be a string'); - } - widgetPositioning.vertical = widgetPositioning.vertical.toLowerCase(); - if (verticalModes.indexOf(widgetPositioning.vertical) === -1) { - throw new TypeError('widgetPositioning() expects vertical parameter to be one of (' + verticalModes.join(', ') + ')'); - } - options.widgetPositioning.vertical = widgetPositioning.vertical; - } - update(); - return picker; - }; - - picker.calendarWeeks = function (calendarWeeks) { - if (arguments.length === 0) { - return options.calendarWeeks; - } - - if (typeof calendarWeeks !== 'boolean') { - throw new TypeError('calendarWeeks() expects parameter to be a boolean value'); - } - - options.calendarWeeks = calendarWeeks; - update(); - return picker; - }; - - picker.showTodayButton = function (showTodayButton) { - if (arguments.length === 0) { - return options.showTodayButton; - } - - if (typeof showTodayButton !== 'boolean') { - throw new TypeError('showTodayButton() expects a boolean parameter'); - } - - options.showTodayButton = showTodayButton; - if (widget) { - hide(); - show(); - } - return picker; - }; - - picker.showClear = function (showClear) { - if (arguments.length === 0) { - return options.showClear; - } - - if (typeof showClear !== 'boolean') { - throw new TypeError('showClear() expects a boolean parameter'); - } - - options.showClear = showClear; - if (widget) { - hide(); - show(); - } - return picker; - }; - - picker.widgetParent = function (widgetParent) { - if (arguments.length === 0) { - return options.widgetParent; - } - - if (typeof widgetParent === 'string') { - widgetParent = $(widgetParent); - } - - if (widgetParent !== null && (typeof widgetParent !== 'string' && !(widgetParent instanceof $))) { - throw new TypeError('widgetParent() expects a string or a jQuery object parameter'); - } - - options.widgetParent = widgetParent; - if (widget) { - hide(); - show(); - } - return picker; - }; - - picker.keepOpen = function (keepOpen) { - if (arguments.length === 0) { - return options.keepOpen; - } - - if (typeof keepOpen !== 'boolean') { - throw new TypeError('keepOpen() expects a boolean parameter'); - } - - options.keepOpen = keepOpen; - return picker; - }; - - picker.focusOnShow = function (focusOnShow) { - if (arguments.length === 0) { - return options.focusOnShow; - } - - if (typeof focusOnShow !== 'boolean') { - throw new TypeError('focusOnShow() expects a boolean parameter'); - } - - options.focusOnShow = focusOnShow; - return picker; - }; - - picker.inline = function (inline) { - if (arguments.length === 0) { - return options.inline; - } - - if (typeof inline !== 'boolean') { - throw new TypeError('inline() expects a boolean parameter'); - } - - options.inline = inline; - return picker; - }; - - picker.clear = function () { - clear(); - return picker; - }; - - picker.keyBinds = function (keyBinds) { - if (arguments.length === 0) { - return options.keyBinds; - } - - options.keyBinds = keyBinds; - return picker; - }; - - picker.getMoment = function (d) { - return getMoment(d); - }; - - picker.debug = function (debug) { - if (typeof debug !== 'boolean') { - throw new TypeError('debug() expects a boolean parameter'); - } - - options.debug = debug; - return picker; - }; - - picker.allowInputToggle = function (allowInputToggle) { - if (arguments.length === 0) { - return options.allowInputToggle; - } - - if (typeof allowInputToggle !== 'boolean') { - throw new TypeError('allowInputToggle() expects a boolean parameter'); - } - - options.allowInputToggle = allowInputToggle; - return picker; - }; - - picker.showClose = function (showClose) { - if (arguments.length === 0) { - return options.showClose; - } - - if (typeof showClose !== 'boolean') { - throw new TypeError('showClose() expects a boolean parameter'); - } - - options.showClose = showClose; - return picker; - }; - - picker.keepInvalid = function (keepInvalid) { - if (arguments.length === 0) { - return options.keepInvalid; - } - - if (typeof keepInvalid !== 'boolean') { - throw new TypeError('keepInvalid() expects a boolean parameter'); - } - options.keepInvalid = keepInvalid; - return picker; - }; - - picker.datepickerInput = function (datepickerInput) { - if (arguments.length === 0) { - return options.datepickerInput; - } - - if (typeof datepickerInput !== 'string') { - throw new TypeError('datepickerInput() expects a string parameter'); - } - - options.datepickerInput = datepickerInput; - return picker; - }; - - picker.parseInputDate = function (parseInputDate) { - if (arguments.length === 0) { - return options.parseInputDate; - } - - if (typeof parseInputDate !== 'function') { - throw new TypeError('parseInputDate() sholud be as function'); - } - - options.parseInputDate = parseInputDate; - - return picker; - }; - - picker.disabledTimeIntervals = function (disabledTimeIntervals) { - /// - ///Returns an array with the currently set disabled dates on the component. - ///options.disabledTimeIntervals - /// - /// - ///Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of - ///options.enabledDates if such exist. - ///Takes an [ string or Date or moment ] of values and allows the user to select only from those days. - /// - if (arguments.length === 0) { - return (options.disabledTimeIntervals ? $.extend({}, options.disabledTimeIntervals) : options.disabledTimeIntervals); - } - - if (!disabledTimeIntervals) { - options.disabledTimeIntervals = false; - update(); - return picker; - } - if (!(disabledTimeIntervals instanceof Array)) { - throw new TypeError('disabledTimeIntervals() expects an array parameter'); - } - options.disabledTimeIntervals = disabledTimeIntervals; - update(); - return picker; - }; - - picker.disabledHours = function (hours) { - /// - ///Returns an array with the currently set disabled hours on the component. - ///options.disabledHours - /// - /// - ///Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of - ///options.enabledHours if such exist. - ///Takes an [ int ] of values and disallows the user to select only from those hours. - /// - if (arguments.length === 0) { - return (options.disabledHours ? $.extend({}, options.disabledHours) : options.disabledHours); - } - - if (!hours) { - options.disabledHours = false; - update(); - return picker; - } - if (!(hours instanceof Array)) { - throw new TypeError('disabledHours() expects an array parameter'); - } - options.disabledHours = indexGivenHours(hours); - options.enabledHours = false; - if (options.useCurrent && !options.keepInvalid) { - var tries = 0; - while (!isValid(date, 'h')) { - date.add(1, 'h'); - if (tries === 24) { - throw 'Tried 24 times to find a valid date'; - } - tries++; - } - setValue(date); - } - update(); - return picker; - }; - - picker.enabledHours = function (hours) { - /// - ///Returns an array with the currently set enabled hours on the component. - ///options.enabledHours - /// - /// - ///Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of options.disabledHours if such exist. - ///Takes an [ int ] of values and allows the user to select only from those hours. - /// - if (arguments.length === 0) { - return (options.enabledHours ? $.extend({}, options.enabledHours) : options.enabledHours); - } - - if (!hours) { - options.enabledHours = false; - update(); - return picker; - } - if (!(hours instanceof Array)) { - throw new TypeError('enabledHours() expects an array parameter'); - } - options.enabledHours = indexGivenHours(hours); - options.disabledHours = false; - if (options.useCurrent && !options.keepInvalid) { - var tries = 0; - while (!isValid(date, 'h')) { - date.add(1, 'h'); - if (tries === 24) { - throw 'Tried 24 times to find a valid date'; - } - tries++; - } - setValue(date); - } - update(); - return picker; - }; - /** - * Returns the component's model current viewDate, a moment object or null if not set. Passing a null value unsets the components model current moment. Parsing of the newDate parameter is made using moment library with the options.format and options.useStrict components configuration. - * @param {Takes string, viewDate, moment, null parameter.} newDate - * @returns {viewDate.clone()} - */ - picker.viewDate = function (newDate) { - if (arguments.length === 0) { - return viewDate.clone(); - } - - if (!newDate) { - viewDate = date.clone(); - return picker; - } - - if (typeof newDate !== 'string' && !moment.isMoment(newDate) && !(newDate instanceof Date)) { - throw new TypeError('viewDate() parameter must be one of [string, moment or Date]'); - } - - viewDate = parseInputDate(newDate); - viewUpdate(); - return picker; - }; - - // initializing element and component attributes - if (element.is('input')) { - input = element; - } else { - input = element.find(options.datepickerInput); - if (input.length === 0) { - input = element.find('input'); - } else if (!input.is('input')) { - throw new Error('CSS class "' + options.datepickerInput + '" cannot be applied to non input element'); - } - } - - if (element.hasClass('input-group')) { - // in case there is more then one 'input-group-addon' Issue #48 - if (element.find('.datepickerbutton').length === 0) { - component = element.find('.input-group-addon'); - } else { - component = element.find('.datepickerbutton'); - } - } - - if (!options.inline && !input.is('input')) { - throw new Error('Could not initialize DateTimePicker without an input element'); - } - - // Set defaults for date here now instead of in var declaration - date = getMoment(); - viewDate = date.clone(); - - $.extend(true, options, dataToOptions()); - - picker.options(options); - - initFormatting(); - - attachDatePickerElementEvents(); - - if (input.prop('disabled')) { - picker.disable(); + if (dates[language].meridiem.length === 2) { + val.H = (val.h % 12 === 0 ? 12 : val.h % 12); } - if (input.is('input') && input.val().trim().length !== 0) { - setValue(parseInputDate(input.val().trim())); + else { + val.H = val.h; } - else if (options.defaultDate && input.attr('placeholder') === undefined) { - setValue(options.defaultDate); - } - if (options.inline) { - show(); - } - return picker; - }; - - /******************************************************************************** - * - * jQuery plugin constructor and defaults object - * - ********************************************************************************/ - - /** - * See (http://jquery.com/). - * @name jQuery - * @class - * See the jQuery Library (http://jquery.com/) for full details. This just - * documents the function and classes that are added to jQuery by this plug-in. - */ - /** - * See (http://jquery.com/) - * @name fn - * @class - * See the jQuery Library (http://jquery.com/) for full details. This just - * documents the function and classes that are added to jQuery by this plug-in. - * @memberOf jQuery - */ - /** - * Show comments - * @class datetimepicker - * @memberOf jQuery.fn - */ - $.fn.datetimepicker = function (options) { - options = options || {}; - - var args = Array.prototype.slice.call(arguments, 1), - isInstance = true, - thisMethods = ['destroy', 'hide', 'show', 'toggle'], - returnValue; - - if (typeof options === 'object') { - return this.each(function () { - var $this = $(this), - _options; - if (!$this.data('DateTimePicker')) { - // create a private copy of the defaults object - _options = $.extend(true, {}, $.fn.datetimepicker.defaults, options); - $this.data('DateTimePicker', dateTimePicker($this, _options)); - } - }); - } else if (typeof options === 'string') { - this.each(function () { - var $this = $(this), - instance = $this.data('DateTimePicker'); - if (!instance) { - throw new Error('bootstrap-datetimepicker("' + options + '") method was called on an element that is not using DateTimePicker'); - } - - returnValue = instance[options].apply(instance, args); - isInstance = returnValue === instance; - }); - - if (isInstance || $.inArray(options, thisMethods) > -1) { - return this; - } - - return returnValue; + val.HH = (val.H < 10 ? '0' : '') + val.H; + val.P = val.p.toUpperCase(); + val.Z = val.z; + val.hh = (val.h < 10 ? '0' : '') + val.h; + val.ii = (val.i < 10 ? '0' : '') + val.i; + val.ss = (val.s < 10 ? '0' : '') + val.s; + val.dd = (val.d < 10 ? '0' : '') + val.d; + val.mm = (val.m < 10 ? '0' : '') + val.m; + } else if (type === 'php') { + // php format + val = { + // year + y: date.getUTCFullYear().toString().substring(2), + Y: date.getUTCFullYear(), + // month + F: dates[language].months[date.getUTCMonth()], + M: dates[language].monthsShort[date.getUTCMonth()], + n: date.getUTCMonth() + 1, + t: DPGlobal.getDaysInMonth(date.getUTCFullYear(), date.getUTCMonth()), + // day + j: date.getUTCDate(), + l: dates[language].days[date.getUTCDay()], + D: dates[language].daysShort[date.getUTCDay()], + w: date.getUTCDay(), // 0 -> 6 + N: (date.getUTCDay() === 0 ? 7 : date.getUTCDay()), // 1 -> 7 + S: (date.getUTCDate() % 10 <= dates[language].suffix.length ? dates[language].suffix[date.getUTCDate() % 10 - 1] : ''), + // hour + a: (dates[language].meridiem.length === 2 ? dates[language].meridiem[date.getUTCHours() < 12 ? 0 : 1] : ''), + g: (date.getUTCHours() % 12 === 0 ? 12 : date.getUTCHours() % 12), + G: date.getUTCHours(), + // minute + i: date.getUTCMinutes(), + // second + s: date.getUTCSeconds() + }; + val.m = (val.n < 10 ? '0' : '') + val.n; + val.d = (val.j < 10 ? '0' : '') + val.j; + val.A = val.a.toString().toUpperCase(); + val.h = (val.g < 10 ? '0' : '') + val.g; + val.H = (val.G < 10 ? '0' : '') + val.G; + val.i = (val.i < 10 ? '0' : '') + val.i; + val.s = (val.s < 10 ? '0' : '') + val.s; + } else { + throw new Error('Invalid format type.'); + } + var date = [], + seps = $.extend([], format.separators); + for (var i = 0, cnt = format.parts.length; i < cnt; i++) { + if (seps.length) { + date.push(seps.shift()); } + date.push(val[format.parts[i]]); + } + if (seps.length) { + date.push(seps.shift()); + } + return date.join(''); + }, + convertViewMode: function (viewMode) { + switch (viewMode) { + case 4: + case 'decade': + viewMode = 4; + break; + case 3: + case 'year': + viewMode = 3; + break; + case 2: + case 'month': + viewMode = 2; + break; + case 1: + case 'day': + viewMode = 1; + break; + case 0: + case 'hour': + viewMode = 0; + break; + } + + return viewMode; + }, + headTemplate: '' + + '' + + '' + + '' + + '' + + '' + + '', + headTemplateV3: '' + + '' + + '' + + '' + + '' + + '' + + '', + contTemplate: '', + footTemplate: '' + + '' + + '' + + '' + }; + DPGlobal.template = '
' + + '
' + + '
' + dates[this.language].daysMin[(dowCnt++) % 7] + '
' + prevMonth.getUTCDate() + '
').addClass('cw').text('#')); - } - - while (currentDate.isBefore(viewDate.clone().endOf('w'))) { - row.append($('').addClass('dow').text(currentDate.format('dd'))); - currentDate.add(1, 'd'); - } - widget.find('.datepicker-days thead').append(row); - }, - - isInDisabledDates = function (testDate) { - return options.disabledDates[testDate.format('YYYY-MM-DD')] === true; - }, - - isInEnabledDates = function (testDate) { - return options.enabledDates[testDate.format('YYYY-MM-DD')] === true; - }, - - isInDisabledHours = function (testDate) { - return options.disabledHours[testDate.format('H')] === true; - }, - - isInEnabledHours = function (testDate) { - return options.enabledHours[testDate.format('H')] === true; - }, - - isValid = function (targetMoment, granularity) { - if (!targetMoment.isValid()) { - return false; - } - if (options.disabledDates && granularity === 'd' && isInDisabledDates(targetMoment)) { - return false; - } - if (options.enabledDates && granularity === 'd' && !isInEnabledDates(targetMoment)) { - return false; - } - if (options.minDate && targetMoment.isBefore(options.minDate, granularity)) { - return false; - } - if (options.maxDate && targetMoment.isAfter(options.maxDate, granularity)) { - return false; - } - if (options.daysOfWeekDisabled && granularity === 'd' && options.daysOfWeekDisabled.indexOf(targetMoment.day()) !== -1) { - return false; - } - if (options.disabledHours && (granularity === 'h' || granularity === 'm' || granularity === 's') && isInDisabledHours(targetMoment)) { - return false; - } - if (options.enabledHours && (granularity === 'h' || granularity === 'm' || granularity === 's') && !isInEnabledHours(targetMoment)) { - return false; - } - if (options.disabledTimeIntervals && (granularity === 'h' || granularity === 'm' || granularity === 's')) { - var found = false; - $.each(options.disabledTimeIntervals, function () { - if (targetMoment.isBetween(this[0], this[1])) { - found = true; - return false; - } - }); - if (found) { - return false; - } - } - return true; - }, - - fillMonths = function () { - var spans = [], - monthsShort = viewDate.clone().startOf('y').startOf('d'); - while (monthsShort.isSame(viewDate, 'y')) { - spans.push($('').attr('data-action', 'selectMonth').addClass('month').text(monthsShort.format('MMM'))); - monthsShort.add(1, 'M'); - } - widget.find('.datepicker-months td').empty().append(spans); - }, - - updateMonths = function () { - var monthsView = widget.find('.datepicker-months'), - monthsViewHeader = monthsView.find('th'), - months = monthsView.find('tbody').find('span'); - - monthsViewHeader.eq(0).find('span').attr('title', options.tooltips.prevYear); - monthsViewHeader.eq(1).attr('title', options.tooltips.selectYear); - monthsViewHeader.eq(2).find('span').attr('title', options.tooltips.nextYear); - - monthsView.find('.disabled').removeClass('disabled'); - - if (!isValid(viewDate.clone().subtract(1, 'y'), 'y')) { - monthsViewHeader.eq(0).addClass('disabled'); - } - - monthsViewHeader.eq(1).text(viewDate.year()); - - if (!isValid(viewDate.clone().add(1, 'y'), 'y')) { - monthsViewHeader.eq(2).addClass('disabled'); - } - - months.removeClass('active'); - if (date.isSame(viewDate, 'y') && !unset) { - months.eq(date.month()).addClass('active'); - } - - months.each(function (index) { - if (!isValid(viewDate.clone().month(index), 'M')) { - $(this).addClass('disabled'); - } + if (this.viewSelect >= 3) { + this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0)); + } + } else if (target.is('.year')) { + this.viewDate.setUTCDate(1); + year = parseInt(target.text(), 10) || 0; + this.viewDate.setUTCFullYear(year); + this.element.trigger({ + type: 'changeYear', + date: this.viewDate }); - }, - - updateYears = function () { - var yearsView = widget.find('.datepicker-years'), - yearsViewHeader = yearsView.find('th'), - startYear = viewDate.clone().subtract(5, 'y'), - endYear = viewDate.clone().add(6, 'y'), - html = ''; - - yearsViewHeader.eq(0).find('span').attr('title', options.tooltips.prevDecade); - yearsViewHeader.eq(1).attr('title', options.tooltips.selectDecade); - yearsViewHeader.eq(2).find('span').attr('title', options.tooltips.nextDecade); - - yearsView.find('.disabled').removeClass('disabled'); - - if (options.minDate && options.minDate.isAfter(startYear, 'y')) { - yearsViewHeader.eq(0).addClass('disabled'); - } - - yearsViewHeader.eq(1).text(startYear.year() + '-' + endYear.year()); - - if (options.maxDate && options.maxDate.isBefore(endYear, 'y')) { - yearsViewHeader.eq(2).addClass('disabled'); - } - - while (!startYear.isAfter(endYear, 'y')) { - html += '' + startYear.year() + ''; - startYear.add(1, 'y'); - } - - yearsView.find('td').html(html); - }, - - updateDecades = function () { - var decadesView = widget.find('.datepicker-decades'), - decadesViewHeader = decadesView.find('th'), - startDecade = moment({ y: viewDate.year() - (viewDate.year() % 100) - 1 }), - endDecade = startDecade.clone().add(100, 'y'), - startedAt = startDecade.clone(), - minDateDecade = false, - maxDateDecade = false, - endDecadeYear, - html = ''; - - decadesViewHeader.eq(0).find('span').attr('title', options.tooltips.prevCentury); - decadesViewHeader.eq(2).find('span').attr('title', options.tooltips.nextCentury); - - decadesView.find('.disabled').removeClass('disabled'); - - if (startDecade.isSame(moment({ y: 1900 })) || (options.minDate && options.minDate.isAfter(startDecade, 'y'))) { - decadesViewHeader.eq(0).addClass('disabled'); - } - - decadesViewHeader.eq(1).text(startDecade.year() + '-' + endDecade.year()); - - if (startDecade.isSame(moment({ y: 2000 })) || (options.maxDate && options.maxDate.isBefore(endDecade, 'y'))) { - decadesViewHeader.eq(2).addClass('disabled'); - } - - while (!startDecade.isAfter(endDecade, 'y')) { - endDecadeYear = startDecade.year() + 12; - minDateDecade = options.minDate && options.minDate.isAfter(startDecade, 'y') && options.minDate.year() <= endDecadeYear; - maxDateDecade = options.maxDate && options.maxDate.isAfter(startDecade, 'y') && options.maxDate.year() <= endDecadeYear; - html += '' + (startDecade.year() + 1) + ' - ' + (startDecade.year() + 12) + ''; - startDecade.add(12, 'y'); - } - html += ''; //push the dangling block over, at least this way it's even - - decadesView.find('td').html(html); - decadesViewHeader.eq(1).text((startedAt.year() + 1) + '-' + (startDecade.year())); - }, - - fillDate = function () { - var daysView = widget.find('.datepicker-days'), - daysViewHeader = daysView.find('th'), - currentDate, - html = [], - row, - clsNames = [], - i; - - if (!hasDate()) { - return; - } - - daysViewHeader.eq(0).find('span').attr('title', options.tooltips.prevMonth); - daysViewHeader.eq(1).attr('title', options.tooltips.selectMonth); - daysViewHeader.eq(2).find('span').attr('title', options.tooltips.nextMonth); - - daysView.find('.disabled').removeClass('disabled'); - daysViewHeader.eq(1).text(viewDate.format(options.dayViewHeaderFormat)); - - if (!isValid(viewDate.clone().subtract(1, 'M'), 'M')) { - daysViewHeader.eq(0).addClass('disabled'); - } - if (!isValid(viewDate.clone().add(1, 'M'), 'M')) { - daysViewHeader.eq(2).addClass('disabled'); - } - - currentDate = viewDate.clone().startOf('M').startOf('w').startOf('d'); - - for (i = 0; i < 42; i++) { //always display 42 days (should show 6 weeks) - if (currentDate.weekday() === 0) { - row = $('
' + currentDate.week() + '' + currentDate.date() + '
' + currentHour.format(use24Hours ? 'HH' : 'hh') + '
' + currentMinute.format('mm') + '
' + currentSecond.format('ss') + '
' + + DPGlobal.headTemplate + + DPGlobal.contTemplate + + DPGlobal.footTemplate + + '
' + + '' + + '
' + + '' + + DPGlobal.headTemplate + + DPGlobal.contTemplate + + DPGlobal.footTemplate + + '
' + + '
' + + '
' + + '' + + DPGlobal.headTemplate + + '' + + DPGlobal.footTemplate + + '
' + + '
' + + '
' + + '' + + DPGlobal.headTemplate + + DPGlobal.contTemplate + + DPGlobal.footTemplate + + '
' + + '
' + + '
' + + '' + + DPGlobal.headTemplate + + DPGlobal.contTemplate + + DPGlobal.footTemplate + + '
' + + '
' + + ''; + DPGlobal.templateV3 = '
' + + '
' + + '' + + DPGlobal.headTemplateV3 + + DPGlobal.contTemplate + + DPGlobal.footTemplate + + '
' + + '
' + + '
' + + '' + + DPGlobal.headTemplateV3 + + DPGlobal.contTemplate + + DPGlobal.footTemplate + + '
' + + '
' + + '
' + + '' + + DPGlobal.headTemplateV3 + + '' + + DPGlobal.footTemplate + + '
' + + '
' + + '
' + + '' + + DPGlobal.headTemplateV3 + + DPGlobal.contTemplate + + DPGlobal.footTemplate + + '
' + + '
' + + '
' + + '' + + DPGlobal.headTemplateV3 + + DPGlobal.contTemplate + + DPGlobal.footTemplate + + '
' + + '
' + + '
'; + $.fn.datetimepicker.DPGlobal = DPGlobal; + + /* DATETIMEPICKER NO CONFLICT + * =================== */ + + $.fn.datetimepicker.noConflict = function () { + $.fn.datetimepicker = old; + return this; + }; + + /* DATETIMEPICKER DATA-API + * ================== */ + + $(document).on( + 'focus.datetimepicker.data-api click.datetimepicker.data-api', + '[data-provide="datetimepicker"]', + function (e) { + var $this = $(this); + if ($this.data('datetimepicker')) return; + e.preventDefault(); + // component click requires us to explicitly show it + $this.datetimepicker('show'); + } + ); + $(function () { + $('[data-provide="datetimepicker-inline"]').datetimepicker(); + }); - throw new TypeError('Invalid arguments for DateTimePicker: ' + options); - }; - - $.fn.datetimepicker.defaults = { - timeZone: '', - format: false, - dayViewHeaderFormat: 'MMMM YYYY', - extraFormats: false, - stepping: 1, - minDate: false, - maxDate: false, - useCurrent: true, - collapse: true, - locale: moment.locale(), - defaultDate: false, - disabledDates: false, - enabledDates: false, - icons: { - time: 'glyphicon glyphicon-time', - date: 'glyphicon glyphicon-calendar', - up: 'glyphicon glyphicon-chevron-up', - down: 'glyphicon glyphicon-chevron-down', - previous: 'glyphicon glyphicon-chevron-left', - next: 'glyphicon glyphicon-chevron-right', - today: 'glyphicon glyphicon-screenshot', - clear: 'glyphicon glyphicon-trash', - close: 'glyphicon glyphicon-remove' - }, - tooltips: { - today: 'Go to today', - clear: 'Clear selection', - close: 'Close the picker', - selectMonth: 'Select Month', - prevMonth: 'Previous Month', - nextMonth: 'Next Month', - selectYear: 'Select Year', - prevYear: 'Previous Year', - nextYear: 'Next Year', - selectDecade: 'Select Decade', - prevDecade: 'Previous Decade', - nextDecade: 'Next Decade', - prevCentury: 'Previous Century', - nextCentury: 'Next Century', - pickHour: 'Pick Hour', - incrementHour: 'Increment Hour', - decrementHour: 'Decrement Hour', - pickMinute: 'Pick Minute', - incrementMinute: 'Increment Minute', - decrementMinute: 'Decrement Minute', - pickSecond: 'Pick Second', - incrementSecond: 'Increment Second', - decrementSecond: 'Decrement Second', - togglePeriod: 'Toggle Period', - selectTime: 'Select Time' - }, - useStrict: false, - sideBySide: false, - daysOfWeekDisabled: false, - calendarWeeks: false, - viewMode: 'days', - toolbarPlacement: 'default', - showTodayButton: false, - showClear: false, - showClose: false, - widgetPositioning: { - horizontal: 'auto', - vertical: 'auto' - }, - widgetParent: null, - ignoreReadonly: false, - keepOpen: false, - focusOnShow: true, - inline: false, - keepInvalid: false, - datepickerInput: '.datepickerinput', - keyBinds: { - up: function (widget) { - if (!widget) { - return; - } - var d = this.date() || this.getMoment(); - if (widget.find('.datepicker').is(':visible')) { - this.date(d.clone().subtract(7, 'd')); - } else { - this.date(d.clone().add(this.stepping(), 'm')); - } - }, - down: function (widget) { - if (!widget) { - this.show(); - return; - } - var d = this.date() || this.getMoment(); - if (widget.find('.datepicker').is(':visible')) { - this.date(d.clone().add(7, 'd')); - } else { - this.date(d.clone().subtract(this.stepping(), 'm')); - } - }, - 'control up': function (widget) { - if (!widget) { - return; - } - var d = this.date() || this.getMoment(); - if (widget.find('.datepicker').is(':visible')) { - this.date(d.clone().subtract(1, 'y')); - } else { - this.date(d.clone().add(1, 'h')); - } - }, - 'control down': function (widget) { - if (!widget) { - return; - } - var d = this.date() || this.getMoment(); - if (widget.find('.datepicker').is(':visible')) { - this.date(d.clone().add(1, 'y')); - } else { - this.date(d.clone().subtract(1, 'h')); - } - }, - left: function (widget) { - if (!widget) { - return; - } - var d = this.date() || this.getMoment(); - if (widget.find('.datepicker').is(':visible')) { - this.date(d.clone().subtract(1, 'd')); - } - }, - right: function (widget) { - if (!widget) { - return; - } - var d = this.date() || this.getMoment(); - if (widget.find('.datepicker').is(':visible')) { - this.date(d.clone().add(1, 'd')); - } - }, - pageUp: function (widget) { - if (!widget) { - return; - } - var d = this.date() || this.getMoment(); - if (widget.find('.datepicker').is(':visible')) { - this.date(d.clone().subtract(1, 'M')); - } - }, - pageDown: function (widget) { - if (!widget) { - return; - } - var d = this.date() || this.getMoment(); - if (widget.find('.datepicker').is(':visible')) { - this.date(d.clone().add(1, 'M')); - } - }, - enter: function () { - this.hide(); - }, - escape: function () { - this.hide(); - }, - //tab: function (widget) { //this break the flow of the form. disabling for now - // var toggle = widget.find('.picker-switch a[data-action="togglePicker"]'); - // if(toggle.length > 0) toggle.click(); - //}, - 'control space': function (widget) { - if (!widget) { - return; - } - if (widget.find('.timepicker').is(':visible')) { - widget.find('.btn[data-action="togglePeriod"]').click(); - } - }, - t: function () { - this.date(this.getMoment()); - }, - 'delete': function () { - this.clear(); - } - }, - debug: false, - allowInputToggle: false, - disabledTimeIntervals: false, - disabledHours: false, - enabledHours: false, - viewDate: false - }; - - return $.fn.datetimepicker; })); diff --git a/app/assets/javascripts/cooperative.js b/app/assets/javascripts/cooperative.js index 77e0477eb..b5d45557a 100644 --- a/app/assets/javascripts/cooperative.js +++ b/app/assets/javascripts/cooperative.js @@ -11,6 +11,7 @@ //= require select2 //= require jquery.cxselect //= require bootstrap-datepicker +//= require bootstrap-datetimepicker //= require bootstrap.viewer //= require jquery.mloading //= require jquery-confirm.min diff --git a/app/assets/javascripts/cooperative/laboratory_users/index.js b/app/assets/javascripts/cooperative/laboratory_users/index.js index cd705d8d0..19385f003 100644 --- a/app/assets/javascripts/cooperative/laboratory_users/index.js +++ b/app/assets/javascripts/cooperative/laboratory_users/index.js @@ -27,7 +27,7 @@ $(document).on('turbolinks:load', function() { }, templateResult: function (item) { if(!item.id || item.id === '') return item.text; - return item.real_name + "--" + item.identity; + return $("" + item.real_name + " " + item.school_name + ' ' + item.hidden_phone + ""); }, templateSelection: function(item){ if (item.id) { diff --git a/app/assets/javascripts/i18n/bootstrap-datetimepicker.zh-CN.js b/app/assets/javascripts/i18n/bootstrap-datetimepicker.zh-CN.js new file mode 100755 index 000000000..418fb3071 --- /dev/null +++ b/app/assets/javascripts/i18n/bootstrap-datetimepicker.zh-CN.js @@ -0,0 +1,16 @@ +/** + * Simplified Chinese translation for bootstrap-datetimepicker + * Yuan Cheung + */ +;(function($){ + $.fn.datetimepicker.dates['zh-CN'] = { + days: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"], + daysShort: ["周日", "周一", "周二", "周三", "周四", "周五", "周六", "周日"], + daysMin: ["日", "一", "二", "三", "四", "五", "六", "日"], + months: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"], + monthsShort: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"], + today: "今天", + suffix: [], + meridiem: ["上午", "下午"] + }; +}(jQuery)); diff --git a/app/assets/javascripts/moment.min.js b/app/assets/javascripts/moment.min.js new file mode 100644 index 000000000..451e445c2 --- /dev/null +++ b/app/assets/javascripts/moment.min.js @@ -0,0 +1,7 @@ +//! moment.js +//! version : 2.10.6 +//! authors : Tim Wood, Iskren Chernev, Moment.js contributors +//! license : MIT +//! momentjs.com +!function(a,b){"object"==typeof exports&&"undefined"!=typeof module?module.exports=b():"function"==typeof define&&define.amd?define(b):a.moment=b()}(this,function(){"use strict";function a(){return Hc.apply(null,arguments)}function b(a){Hc=a}function c(a){return"[object Array]"===Object.prototype.toString.call(a)}function d(a){return a instanceof Date||"[object Date]"===Object.prototype.toString.call(a)}function e(a,b){var c,d=[];for(c=0;c0)for(c in Jc)d=Jc[c],e=b[d],"undefined"!=typeof e&&(a[d]=e);return a}function n(b){m(this,b),this._d=new Date(null!=b._d?b._d.getTime():NaN),Kc===!1&&(Kc=!0,a.updateOffset(this),Kc=!1)}function o(a){return a instanceof n||null!=a&&null!=a._isAMomentObject}function p(a){return 0>a?Math.ceil(a):Math.floor(a)}function q(a){var b=+a,c=0;return 0!==b&&isFinite(b)&&(c=p(b)),c}function r(a,b,c){var d,e=Math.min(a.length,b.length),f=Math.abs(a.length-b.length),g=0;for(d=0;e>d;d++)(c&&a[d]!==b[d]||!c&&q(a[d])!==q(b[d]))&&g++;return g+f}function s(){}function t(a){return a?a.toLowerCase().replace("_","-"):a}function u(a){for(var b,c,d,e,f=0;f0;){if(d=v(e.slice(0,b).join("-")))return d;if(c&&c.length>=b&&r(e,c,!0)>=b-1)break;b--}f++}return null}function v(a){var b=null;if(!Lc[a]&&"undefined"!=typeof module&&module&&module.exports)try{b=Ic._abbr,require("./locale/"+a),w(b)}catch(c){}return Lc[a]}function w(a,b){var c;return a&&(c="undefined"==typeof b?y(a):x(a,b),c&&(Ic=c)),Ic._abbr}function x(a,b){return null!==b?(b.abbr=a,Lc[a]=Lc[a]||new s,Lc[a].set(b),w(a),Lc[a]):(delete Lc[a],null)}function y(a){var b;if(a&&a._locale&&a._locale._abbr&&(a=a._locale._abbr),!a)return Ic;if(!c(a)){if(b=v(a))return b;a=[a]}return u(a)}function z(a,b){var c=a.toLowerCase();Mc[c]=Mc[c+"s"]=Mc[b]=a}function A(a){return"string"==typeof a?Mc[a]||Mc[a.toLowerCase()]:void 0}function B(a){var b,c,d={};for(c in a)f(a,c)&&(b=A(c),b&&(d[b]=a[c]));return d}function C(b,c){return function(d){return null!=d?(E(this,b,d),a.updateOffset(this,c),this):D(this,b)}}function D(a,b){return a._d["get"+(a._isUTC?"UTC":"")+b]()}function E(a,b,c){return a._d["set"+(a._isUTC?"UTC":"")+b](c)}function F(a,b){var c;if("object"==typeof a)for(c in a)this.set(c,a[c]);else if(a=A(a),"function"==typeof this[a])return this[a](b);return this}function G(a,b,c){var d=""+Math.abs(a),e=b-d.length,f=a>=0;return(f?c?"+":"":"-")+Math.pow(10,Math.max(0,e)).toString().substr(1)+d}function H(a,b,c,d){var e=d;"string"==typeof d&&(e=function(){return this[d]()}),a&&(Qc[a]=e),b&&(Qc[b[0]]=function(){return G(e.apply(this,arguments),b[1],b[2])}),c&&(Qc[c]=function(){return this.localeData().ordinal(e.apply(this,arguments),a)})}function I(a){return a.match(/\[[\s\S]/)?a.replace(/^\[|\]$/g,""):a.replace(/\\/g,"")}function J(a){var b,c,d=a.match(Nc);for(b=0,c=d.length;c>b;b++)Qc[d[b]]?d[b]=Qc[d[b]]:d[b]=I(d[b]);return function(e){var f="";for(b=0;c>b;b++)f+=d[b]instanceof Function?d[b].call(e,a):d[b];return f}}function K(a,b){return a.isValid()?(b=L(b,a.localeData()),Pc[b]=Pc[b]||J(b),Pc[b](a)):a.localeData().invalidDate()}function L(a,b){function c(a){return b.longDateFormat(a)||a}var d=5;for(Oc.lastIndex=0;d>=0&&Oc.test(a);)a=a.replace(Oc,c),Oc.lastIndex=0,d-=1;return a}function M(a){return"function"==typeof a&&"[object Function]"===Object.prototype.toString.call(a)}function N(a,b,c){dd[a]=M(b)?b:function(a){return a&&c?c:b}}function O(a,b){return f(dd,a)?dd[a](b._strict,b._locale):new RegExp(P(a))}function P(a){return a.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(a,b,c,d,e){return b||c||d||e}).replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function Q(a,b){var c,d=b;for("string"==typeof a&&(a=[a]),"number"==typeof b&&(d=function(a,c){c[b]=q(a)}),c=0;cd;d++){if(e=h([2e3,d]),c&&!this._longMonthsParse[d]&&(this._longMonthsParse[d]=new RegExp("^"+this.months(e,"").replace(".","")+"$","i"),this._shortMonthsParse[d]=new RegExp("^"+this.monthsShort(e,"").replace(".","")+"$","i")),c||this._monthsParse[d]||(f="^"+this.months(e,"")+"|^"+this.monthsShort(e,""),this._monthsParse[d]=new RegExp(f.replace(".",""),"i")),c&&"MMMM"===b&&this._longMonthsParse[d].test(a))return d;if(c&&"MMM"===b&&this._shortMonthsParse[d].test(a))return d;if(!c&&this._monthsParse[d].test(a))return d}}function X(a,b){var c;return"string"==typeof b&&(b=a.localeData().monthsParse(b),"number"!=typeof b)?a:(c=Math.min(a.date(),T(a.year(),b)),a._d["set"+(a._isUTC?"UTC":"")+"Month"](b,c),a)}function Y(b){return null!=b?(X(this,b),a.updateOffset(this,!0),this):D(this,"Month")}function Z(){return T(this.year(),this.month())}function $(a){var b,c=a._a;return c&&-2===j(a).overflow&&(b=c[gd]<0||c[gd]>11?gd:c[hd]<1||c[hd]>T(c[fd],c[gd])?hd:c[id]<0||c[id]>24||24===c[id]&&(0!==c[jd]||0!==c[kd]||0!==c[ld])?id:c[jd]<0||c[jd]>59?jd:c[kd]<0||c[kd]>59?kd:c[ld]<0||c[ld]>999?ld:-1,j(a)._overflowDayOfYear&&(fd>b||b>hd)&&(b=hd),j(a).overflow=b),a}function _(b){a.suppressDeprecationWarnings===!1&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+b)}function aa(a,b){var c=!0;return g(function(){return c&&(_(a+"\n"+(new Error).stack),c=!1),b.apply(this,arguments)},b)}function ba(a,b){od[a]||(_(b),od[a]=!0)}function ca(a){var b,c,d=a._i,e=pd.exec(d);if(e){for(j(a).iso=!0,b=0,c=qd.length;c>b;b++)if(qd[b][1].exec(d)){a._f=qd[b][0];break}for(b=0,c=rd.length;c>b;b++)if(rd[b][1].exec(d)){a._f+=(e[6]||" ")+rd[b][0];break}d.match(ad)&&(a._f+="Z"),va(a)}else a._isValid=!1}function da(b){var c=sd.exec(b._i);return null!==c?void(b._d=new Date(+c[1])):(ca(b),void(b._isValid===!1&&(delete b._isValid,a.createFromInputFallback(b))))}function ea(a,b,c,d,e,f,g){var h=new Date(a,b,c,d,e,f,g);return 1970>a&&h.setFullYear(a),h}function fa(a){var b=new Date(Date.UTC.apply(null,arguments));return 1970>a&&b.setUTCFullYear(a),b}function ga(a){return ha(a)?366:365}function ha(a){return a%4===0&&a%100!==0||a%400===0}function ia(){return ha(this.year())}function ja(a,b,c){var d,e=c-b,f=c-a.day();return f>e&&(f-=7),e-7>f&&(f+=7),d=Da(a).add(f,"d"),{week:Math.ceil(d.dayOfYear()/7),year:d.year()}}function ka(a){return ja(a,this._week.dow,this._week.doy).week}function la(){return this._week.dow}function ma(){return this._week.doy}function na(a){var b=this.localeData().week(this);return null==a?b:this.add(7*(a-b),"d")}function oa(a){var b=ja(this,1,4).week;return null==a?b:this.add(7*(a-b),"d")}function pa(a,b,c,d,e){var f,g=6+e-d,h=fa(a,0,1+g),i=h.getUTCDay();return e>i&&(i+=7),c=null!=c?1*c:e,f=1+g+7*(b-1)-i+c,{year:f>0?a:a-1,dayOfYear:f>0?f:ga(a-1)+f}}function qa(a){var b=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==a?b:this.add(a-b,"d")}function ra(a,b,c){return null!=a?a:null!=b?b:c}function sa(a){var b=new Date;return a._useUTC?[b.getUTCFullYear(),b.getUTCMonth(),b.getUTCDate()]:[b.getFullYear(),b.getMonth(),b.getDate()]}function ta(a){var b,c,d,e,f=[];if(!a._d){for(d=sa(a),a._w&&null==a._a[hd]&&null==a._a[gd]&&ua(a),a._dayOfYear&&(e=ra(a._a[fd],d[fd]),a._dayOfYear>ga(e)&&(j(a)._overflowDayOfYear=!0),c=fa(e,0,a._dayOfYear),a._a[gd]=c.getUTCMonth(),a._a[hd]=c.getUTCDate()),b=0;3>b&&null==a._a[b];++b)a._a[b]=f[b]=d[b];for(;7>b;b++)a._a[b]=f[b]=null==a._a[b]?2===b?1:0:a._a[b];24===a._a[id]&&0===a._a[jd]&&0===a._a[kd]&&0===a._a[ld]&&(a._nextDay=!0,a._a[id]=0),a._d=(a._useUTC?fa:ea).apply(null,f),null!=a._tzm&&a._d.setUTCMinutes(a._d.getUTCMinutes()-a._tzm),a._nextDay&&(a._a[id]=24)}}function ua(a){var b,c,d,e,f,g,h;b=a._w,null!=b.GG||null!=b.W||null!=b.E?(f=1,g=4,c=ra(b.GG,a._a[fd],ja(Da(),1,4).year),d=ra(b.W,1),e=ra(b.E,1)):(f=a._locale._week.dow,g=a._locale._week.doy,c=ra(b.gg,a._a[fd],ja(Da(),f,g).year),d=ra(b.w,1),null!=b.d?(e=b.d,f>e&&++d):e=null!=b.e?b.e+f:f),h=pa(c,d,e,g,f),a._a[fd]=h.year,a._dayOfYear=h.dayOfYear}function va(b){if(b._f===a.ISO_8601)return void ca(b);b._a=[],j(b).empty=!0;var c,d,e,f,g,h=""+b._i,i=h.length,k=0;for(e=L(b._f,b._locale).match(Nc)||[],c=0;c0&&j(b).unusedInput.push(g),h=h.slice(h.indexOf(d)+d.length),k+=d.length),Qc[f]?(d?j(b).empty=!1:j(b).unusedTokens.push(f),S(f,d,b)):b._strict&&!d&&j(b).unusedTokens.push(f);j(b).charsLeftOver=i-k,h.length>0&&j(b).unusedInput.push(h),j(b).bigHour===!0&&b._a[id]<=12&&b._a[id]>0&&(j(b).bigHour=void 0),b._a[id]=wa(b._locale,b._a[id],b._meridiem),ta(b),$(b)}function wa(a,b,c){var d;return null==c?b:null!=a.meridiemHour?a.meridiemHour(b,c):null!=a.isPM?(d=a.isPM(c),d&&12>b&&(b+=12),d||12!==b||(b=0),b):b}function xa(a){var b,c,d,e,f;if(0===a._f.length)return j(a).invalidFormat=!0,void(a._d=new Date(NaN));for(e=0;ef)&&(d=f,c=b));g(a,c||b)}function ya(a){if(!a._d){var b=B(a._i);a._a=[b.year,b.month,b.day||b.date,b.hour,b.minute,b.second,b.millisecond],ta(a)}}function za(a){var b=new n($(Aa(a)));return b._nextDay&&(b.add(1,"d"),b._nextDay=void 0),b}function Aa(a){var b=a._i,e=a._f;return a._locale=a._locale||y(a._l),null===b||void 0===e&&""===b?l({nullInput:!0}):("string"==typeof b&&(a._i=b=a._locale.preparse(b)),o(b)?new n($(b)):(c(e)?xa(a):e?va(a):d(b)?a._d=b:Ba(a),a))}function Ba(b){var f=b._i;void 0===f?b._d=new Date:d(f)?b._d=new Date(+f):"string"==typeof f?da(b):c(f)?(b._a=e(f.slice(0),function(a){return parseInt(a,10)}),ta(b)):"object"==typeof f?ya(b):"number"==typeof f?b._d=new Date(f):a.createFromInputFallback(b)}function Ca(a,b,c,d,e){var f={};return"boolean"==typeof c&&(d=c,c=void 0),f._isAMomentObject=!0,f._useUTC=f._isUTC=e,f._l=c,f._i=a,f._f=b,f._strict=d,za(f)}function Da(a,b,c,d){return Ca(a,b,c,d,!1)}function Ea(a,b){var d,e;if(1===b.length&&c(b[0])&&(b=b[0]),!b.length)return Da();for(d=b[0],e=1;ea&&(a=-a,c="-"),c+G(~~(a/60),2)+b+G(~~a%60,2)})}function Ka(a){var b=(a||"").match(ad)||[],c=b[b.length-1]||[],d=(c+"").match(xd)||["-",0,0],e=+(60*d[1])+q(d[2]);return"+"===d[0]?e:-e}function La(b,c){var e,f;return c._isUTC?(e=c.clone(),f=(o(b)||d(b)?+b:+Da(b))-+e,e._d.setTime(+e._d+f),a.updateOffset(e,!1),e):Da(b).local()}function Ma(a){return 15*-Math.round(a._d.getTimezoneOffset()/15)}function Na(b,c){var d,e=this._offset||0;return null!=b?("string"==typeof b&&(b=Ka(b)),Math.abs(b)<16&&(b=60*b),!this._isUTC&&c&&(d=Ma(this)),this._offset=b,this._isUTC=!0,null!=d&&this.add(d,"m"),e!==b&&(!c||this._changeInProgress?bb(this,Ya(b-e,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,a.updateOffset(this,!0),this._changeInProgress=null)),this):this._isUTC?e:Ma(this)}function Oa(a,b){return null!=a?("string"!=typeof a&&(a=-a),this.utcOffset(a,b),this):-this.utcOffset()}function Pa(a){return this.utcOffset(0,a)}function Qa(a){return this._isUTC&&(this.utcOffset(0,a),this._isUTC=!1,a&&this.subtract(Ma(this),"m")),this}function Ra(){return this._tzm?this.utcOffset(this._tzm):"string"==typeof this._i&&this.utcOffset(Ka(this._i)),this}function Sa(a){return a=a?Da(a).utcOffset():0,(this.utcOffset()-a)%60===0}function Ta(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()}function Ua(){if("undefined"!=typeof this._isDSTShifted)return this._isDSTShifted;var a={};if(m(a,this),a=Aa(a),a._a){var b=a._isUTC?h(a._a):Da(a._a);this._isDSTShifted=this.isValid()&&r(a._a,b.toArray())>0}else this._isDSTShifted=!1;return this._isDSTShifted}function Va(){return!this._isUTC}function Wa(){return this._isUTC}function Xa(){return this._isUTC&&0===this._offset}function Ya(a,b){var c,d,e,g=a,h=null;return Ia(a)?g={ms:a._milliseconds,d:a._days,M:a._months}:"number"==typeof a?(g={},b?g[b]=a:g.milliseconds=a):(h=yd.exec(a))?(c="-"===h[1]?-1:1,g={y:0,d:q(h[hd])*c,h:q(h[id])*c,m:q(h[jd])*c,s:q(h[kd])*c,ms:q(h[ld])*c}):(h=zd.exec(a))?(c="-"===h[1]?-1:1,g={y:Za(h[2],c),M:Za(h[3],c),d:Za(h[4],c),h:Za(h[5],c),m:Za(h[6],c),s:Za(h[7],c),w:Za(h[8],c)}):null==g?g={}:"object"==typeof g&&("from"in g||"to"in g)&&(e=_a(Da(g.from),Da(g.to)),g={},g.ms=e.milliseconds,g.M=e.months),d=new Ha(g),Ia(a)&&f(a,"_locale")&&(d._locale=a._locale),d}function Za(a,b){var c=a&&parseFloat(a.replace(",","."));return(isNaN(c)?0:c)*b}function $a(a,b){var c={milliseconds:0,months:0};return c.months=b.month()-a.month()+12*(b.year()-a.year()),a.clone().add(c.months,"M").isAfter(b)&&--c.months,c.milliseconds=+b-+a.clone().add(c.months,"M"),c}function _a(a,b){var c;return b=La(b,a),a.isBefore(b)?c=$a(a,b):(c=$a(b,a),c.milliseconds=-c.milliseconds,c.months=-c.months),c}function ab(a,b){return function(c,d){var e,f;return null===d||isNaN(+d)||(ba(b,"moment()."+b+"(period, number) is deprecated. Please use moment()."+b+"(number, period)."),f=c,c=d,d=f),c="string"==typeof c?+c:c,e=Ya(c,d),bb(this,e,a),this}}function bb(b,c,d,e){var f=c._milliseconds,g=c._days,h=c._months;e=null==e?!0:e,f&&b._d.setTime(+b._d+f*d),g&&E(b,"Date",D(b,"Date")+g*d),h&&X(b,D(b,"Month")+h*d),e&&a.updateOffset(b,g||h)}function cb(a,b){var c=a||Da(),d=La(c,this).startOf("day"),e=this.diff(d,"days",!0),f=-6>e?"sameElse":-1>e?"lastWeek":0>e?"lastDay":1>e?"sameDay":2>e?"nextDay":7>e?"nextWeek":"sameElse";return this.format(b&&b[f]||this.localeData().calendar(f,this,Da(c)))}function db(){return new n(this)}function eb(a,b){var c;return b=A("undefined"!=typeof b?b:"millisecond"),"millisecond"===b?(a=o(a)?a:Da(a),+this>+a):(c=o(a)?+a:+Da(a),c<+this.clone().startOf(b))}function fb(a,b){var c;return b=A("undefined"!=typeof b?b:"millisecond"),"millisecond"===b?(a=o(a)?a:Da(a),+a>+this):(c=o(a)?+a:+Da(a),+this.clone().endOf(b)b-f?(c=a.clone().add(e-1,"months"),d=(b-f)/(f-c)):(c=a.clone().add(e+1,"months"),d=(b-f)/(c-f)),-(e+d)}function kb(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")}function lb(){var a=this.clone().utc();return 0b;b++)if(this._weekdaysParse[b]||(c=Da([2e3,1]).day(b),d="^"+this.weekdays(c,"")+"|^"+this.weekdaysShort(c,"")+"|^"+this.weekdaysMin(c,""),this._weekdaysParse[b]=new RegExp(d.replace(".",""),"i")),this._weekdaysParse[b].test(a))return b}function Pb(a){var b=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=a?(a=Kb(a,this.localeData()),this.add(a-b,"d")):b}function Qb(a){var b=(this.day()+7-this.localeData()._week.dow)%7;return null==a?b:this.add(a-b,"d")}function Rb(a){return null==a?this.day()||7:this.day(this.day()%7?a:a-7)}function Sb(a,b){H(a,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),b)})}function Tb(a,b){return b._meridiemParse}function Ub(a){return"p"===(a+"").toLowerCase().charAt(0)}function Vb(a,b,c){return a>11?c?"pm":"PM":c?"am":"AM"}function Wb(a,b){b[ld]=q(1e3*("0."+a))}function Xb(){return this._isUTC?"UTC":""}function Yb(){return this._isUTC?"Coordinated Universal Time":""}function Zb(a){return Da(1e3*a)}function $b(){return Da.apply(null,arguments).parseZone()}function _b(a,b,c){var d=this._calendar[a];return"function"==typeof d?d.call(b,c):d}function ac(a){var b=this._longDateFormat[a],c=this._longDateFormat[a.toUpperCase()];return b||!c?b:(this._longDateFormat[a]=c.replace(/MMMM|MM|DD|dddd/g,function(a){return a.slice(1)}),this._longDateFormat[a])}function bc(){return this._invalidDate}function cc(a){return this._ordinal.replace("%d",a)}function dc(a){return a}function ec(a,b,c,d){var e=this._relativeTime[c];return"function"==typeof e?e(a,b,c,d):e.replace(/%d/i,a)}function fc(a,b){var c=this._relativeTime[a>0?"future":"past"];return"function"==typeof c?c(b):c.replace(/%s/i,b)}function gc(a){var b,c;for(c in a)b=a[c],"function"==typeof b?this[c]=b:this["_"+c]=b;this._ordinalParseLenient=new RegExp(this._ordinalParse.source+"|"+/\d{1,2}/.source)}function hc(a,b,c,d){var e=y(),f=h().set(d,b);return e[c](f,a)}function ic(a,b,c,d,e){if("number"==typeof a&&(b=a,a=void 0),a=a||"",null!=b)return hc(a,b,c,e);var f,g=[];for(f=0;d>f;f++)g[f]=hc(a,f,c,e);return g}function jc(a,b){return ic(a,b,"months",12,"month")}function kc(a,b){return ic(a,b,"monthsShort",12,"month")}function lc(a,b){return ic(a,b,"weekdays",7,"day")}function mc(a,b){return ic(a,b,"weekdaysShort",7,"day")}function nc(a,b){return ic(a,b,"weekdaysMin",7,"day")}function oc(){var a=this._data;return this._milliseconds=Wd(this._milliseconds),this._days=Wd(this._days),this._months=Wd(this._months),a.milliseconds=Wd(a.milliseconds),a.seconds=Wd(a.seconds),a.minutes=Wd(a.minutes),a.hours=Wd(a.hours),a.months=Wd(a.months),a.years=Wd(a.years),this}function pc(a,b,c,d){var e=Ya(b,c);return a._milliseconds+=d*e._milliseconds,a._days+=d*e._days,a._months+=d*e._months,a._bubble()}function qc(a,b){return pc(this,a,b,1)}function rc(a,b){return pc(this,a,b,-1)}function sc(a){return 0>a?Math.floor(a):Math.ceil(a)}function tc(){var a,b,c,d,e,f=this._milliseconds,g=this._days,h=this._months,i=this._data;return f>=0&&g>=0&&h>=0||0>=f&&0>=g&&0>=h||(f+=864e5*sc(vc(h)+g),g=0,h=0),i.milliseconds=f%1e3,a=p(f/1e3),i.seconds=a%60,b=p(a/60),i.minutes=b%60,c=p(b/60),i.hours=c%24,g+=p(c/24),e=p(uc(g)),h+=e,g-=sc(vc(e)),d=p(h/12),h%=12,i.days=g,i.months=h,i.years=d,this}function uc(a){return 4800*a/146097}function vc(a){return 146097*a/4800}function wc(a){var b,c,d=this._milliseconds;if(a=A(a),"month"===a||"year"===a)return b=this._days+d/864e5,c=this._months+uc(b),"month"===a?c:c/12;switch(b=this._days+Math.round(vc(this._months)),a){case"week":return b/7+d/6048e5;case"day":return b+d/864e5;case"hour":return 24*b+d/36e5;case"minute":return 1440*b+d/6e4;case"second":return 86400*b+d/1e3;case"millisecond":return Math.floor(864e5*b)+d;default:throw new Error("Unknown unit "+a)}}function xc(){return this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*q(this._months/12)}function yc(a){return function(){return this.as(a)}}function zc(a){return a=A(a),this[a+"s"]()}function Ac(a){return function(){return this._data[a]}}function Bc(){return p(this.days()/7)}function Cc(a,b,c,d,e){return e.relativeTime(b||1,!!c,a,d)}function Dc(a,b,c){var d=Ya(a).abs(),e=ke(d.as("s")),f=ke(d.as("m")),g=ke(d.as("h")),h=ke(d.as("d")),i=ke(d.as("M")),j=ke(d.as("y")),k=e0,k[4]=c,Cc.apply(null,k)}function Ec(a,b){return void 0===le[a]?!1:void 0===b?le[a]:(le[a]=b,!0)}function Fc(a){var b=this.localeData(),c=Dc(this,!a,b);return a&&(c=b.pastFuture(+this,c)),b.postformat(c)}function Gc(){var a,b,c,d=me(this._milliseconds)/1e3,e=me(this._days),f=me(this._months);a=p(d/60),b=p(a/60),d%=60,a%=60,c=p(f/12),f%=12;var g=c,h=f,i=e,j=b,k=a,l=d,m=this.asSeconds();return m?(0>m?"-":"")+"P"+(g?g+"Y":"")+(h?h+"M":"")+(i?i+"D":"")+(j||k||l?"T":"")+(j?j+"H":"")+(k?k+"M":"")+(l?l+"S":""):"P0D"}var Hc,Ic,Jc=a.momentProperties=[],Kc=!1,Lc={},Mc={},Nc=/(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Q|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,Oc=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,Pc={},Qc={},Rc=/\d/,Sc=/\d\d/,Tc=/\d{3}/,Uc=/\d{4}/,Vc=/[+-]?\d{6}/,Wc=/\d\d?/,Xc=/\d{1,3}/,Yc=/\d{1,4}/,Zc=/[+-]?\d{1,6}/,$c=/\d+/,_c=/[+-]?\d+/,ad=/Z|[+-]\d\d:?\d\d/gi,bd=/[+-]?\d+(\.\d{1,3})?/,cd=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,dd={},ed={},fd=0,gd=1,hd=2,id=3,jd=4,kd=5,ld=6;H("M",["MM",2],"Mo",function(){return this.month()+1}),H("MMM",0,0,function(a){return this.localeData().monthsShort(this,a)}),H("MMMM",0,0,function(a){return this.localeData().months(this,a)}),z("month","M"),N("M",Wc),N("MM",Wc,Sc),N("MMM",cd),N("MMMM",cd),Q(["M","MM"],function(a,b){b[gd]=q(a)-1}),Q(["MMM","MMMM"],function(a,b,c,d){var e=c._locale.monthsParse(a,d,c._strict);null!=e?b[gd]=e:j(c).invalidMonth=a});var md="January_February_March_April_May_June_July_August_September_October_November_December".split("_"),nd="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),od={};a.suppressDeprecationWarnings=!1;var pd=/^\s*(?:[+-]\d{6}|\d{4})-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,qd=[["YYYYYY-MM-DD",/[+-]\d{6}-\d{2}-\d{2}/],["YYYY-MM-DD",/\d{4}-\d{2}-\d{2}/],["GGGG-[W]WW-E",/\d{4}-W\d{2}-\d/],["GGGG-[W]WW",/\d{4}-W\d{2}/],["YYYY-DDD",/\d{4}-\d{3}/]],rd=[["HH:mm:ss.SSSS",/(T| )\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss",/(T| )\d\d:\d\d:\d\d/],["HH:mm",/(T| )\d\d:\d\d/],["HH",/(T| )\d\d/]],sd=/^\/?Date\((\-?\d+)/i;a.createFromInputFallback=aa("moment construction falls back to js Date. This is discouraged and will be removed in upcoming major release. Please refer to https://github.com/moment/moment/issues/1407 for more info.",function(a){a._d=new Date(a._i+(a._useUTC?" UTC":""))}),H(0,["YY",2],0,function(){return this.year()%100}),H(0,["YYYY",4],0,"year"),H(0,["YYYYY",5],0,"year"),H(0,["YYYYYY",6,!0],0,"year"),z("year","y"),N("Y",_c),N("YY",Wc,Sc),N("YYYY",Yc,Uc),N("YYYYY",Zc,Vc),N("YYYYYY",Zc,Vc),Q(["YYYYY","YYYYYY"],fd),Q("YYYY",function(b,c){c[fd]=2===b.length?a.parseTwoDigitYear(b):q(b)}),Q("YY",function(b,c){c[fd]=a.parseTwoDigitYear(b)}),a.parseTwoDigitYear=function(a){return q(a)+(q(a)>68?1900:2e3)};var td=C("FullYear",!1);H("w",["ww",2],"wo","week"),H("W",["WW",2],"Wo","isoWeek"),z("week","w"),z("isoWeek","W"),N("w",Wc),N("ww",Wc,Sc),N("W",Wc),N("WW",Wc,Sc),R(["w","ww","W","WW"],function(a,b,c,d){b[d.substr(0,1)]=q(a)});var ud={dow:0,doy:6};H("DDD",["DDDD",3],"DDDo","dayOfYear"),z("dayOfYear","DDD"),N("DDD",Xc),N("DDDD",Tc),Q(["DDD","DDDD"],function(a,b,c){c._dayOfYear=q(a)}),a.ISO_8601=function(){};var vd=aa("moment().min is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548",function(){var a=Da.apply(null,arguments);return this>a?this:a}),wd=aa("moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548",function(){var a=Da.apply(null,arguments);return a>this?this:a});Ja("Z",":"),Ja("ZZ",""),N("Z",ad),N("ZZ",ad),Q(["Z","ZZ"],function(a,b,c){c._useUTC=!0,c._tzm=Ka(a)});var xd=/([\+\-]|\d\d)/gi;a.updateOffset=function(){};var yd=/(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/,zd=/^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/;Ya.fn=Ha.prototype;var Ad=ab(1,"add"),Bd=ab(-1,"subtract");a.defaultFormat="YYYY-MM-DDTHH:mm:ssZ";var Cd=aa("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(a){return void 0===a?this.localeData():this.locale(a)});H(0,["gg",2],0,function(){return this.weekYear()%100}),H(0,["GG",2],0,function(){return this.isoWeekYear()%100}),Db("gggg","weekYear"),Db("ggggg","weekYear"),Db("GGGG","isoWeekYear"),Db("GGGGG","isoWeekYear"),z("weekYear","gg"),z("isoWeekYear","GG"),N("G",_c),N("g",_c),N("GG",Wc,Sc),N("gg",Wc,Sc),N("GGGG",Yc,Uc),N("gggg",Yc,Uc),N("GGGGG",Zc,Vc),N("ggggg",Zc,Vc),R(["gggg","ggggg","GGGG","GGGGG"],function(a,b,c,d){b[d.substr(0,2)]=q(a)}),R(["gg","GG"],function(b,c,d,e){c[e]=a.parseTwoDigitYear(b)}),H("Q",0,0,"quarter"),z("quarter","Q"),N("Q",Rc),Q("Q",function(a,b){b[gd]=3*(q(a)-1)}),H("D",["DD",2],"Do","date"),z("date","D"),N("D",Wc),N("DD",Wc,Sc),N("Do",function(a,b){return a?b._ordinalParse:b._ordinalParseLenient}),Q(["D","DD"],hd),Q("Do",function(a,b){b[hd]=q(a.match(Wc)[0],10)});var Dd=C("Date",!0);H("d",0,"do","day"),H("dd",0,0,function(a){return this.localeData().weekdaysMin(this,a)}),H("ddd",0,0,function(a){return this.localeData().weekdaysShort(this,a)}),H("dddd",0,0,function(a){return this.localeData().weekdays(this,a)}),H("e",0,0,"weekday"),H("E",0,0,"isoWeekday"),z("day","d"),z("weekday","e"),z("isoWeekday","E"),N("d",Wc),N("e",Wc),N("E",Wc),N("dd",cd),N("ddd",cd),N("dddd",cd),R(["dd","ddd","dddd"],function(a,b,c){var d=c._locale.weekdaysParse(a);null!=d?b.d=d:j(c).invalidWeekday=a}),R(["d","e","E"],function(a,b,c,d){b[d]=q(a)});var Ed="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),Fd="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),Gd="Su_Mo_Tu_We_Th_Fr_Sa".split("_");H("H",["HH",2],0,"hour"),H("h",["hh",2],0,function(){return this.hours()%12||12}),Sb("a",!0),Sb("A",!1),z("hour","h"),N("a",Tb),N("A",Tb),N("H",Wc),N("h",Wc),N("HH",Wc,Sc),N("hh",Wc,Sc),Q(["H","HH"],id),Q(["a","A"],function(a,b,c){c._isPm=c._locale.isPM(a),c._meridiem=a}),Q(["h","hh"],function(a,b,c){b[id]=q(a),j(c).bigHour=!0});var Hd=/[ap]\.?m?\.?/i,Id=C("Hours",!0);H("m",["mm",2],0,"minute"),z("minute","m"),N("m",Wc),N("mm",Wc,Sc),Q(["m","mm"],jd);var Jd=C("Minutes",!1);H("s",["ss",2],0,"second"),z("second","s"),N("s",Wc),N("ss",Wc,Sc),Q(["s","ss"],kd);var Kd=C("Seconds",!1);H("S",0,0,function(){return~~(this.millisecond()/100)}),H(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),H(0,["SSS",3],0,"millisecond"),H(0,["SSSS",4],0,function(){return 10*this.millisecond()}),H(0,["SSSSS",5],0,function(){return 100*this.millisecond()}),H(0,["SSSSSS",6],0,function(){return 1e3*this.millisecond()}),H(0,["SSSSSSS",7],0,function(){return 1e4*this.millisecond()}),H(0,["SSSSSSSS",8],0,function(){return 1e5*this.millisecond()}),H(0,["SSSSSSSSS",9],0,function(){return 1e6*this.millisecond()}),z("millisecond","ms"),N("S",Xc,Rc),N("SS",Xc,Sc),N("SSS",Xc,Tc);var Ld;for(Ld="SSSS";Ld.length<=9;Ld+="S")N(Ld,$c);for(Ld="S";Ld.length<=9;Ld+="S")Q(Ld,Wb);var Md=C("Milliseconds",!1);H("z",0,0,"zoneAbbr"),H("zz",0,0,"zoneName");var Nd=n.prototype;Nd.add=Ad,Nd.calendar=cb,Nd.clone=db,Nd.diff=ib,Nd.endOf=ub,Nd.format=mb,Nd.from=nb,Nd.fromNow=ob,Nd.to=pb,Nd.toNow=qb,Nd.get=F,Nd.invalidAt=Cb,Nd.isAfter=eb,Nd.isBefore=fb,Nd.isBetween=gb,Nd.isSame=hb,Nd.isValid=Ab,Nd.lang=Cd,Nd.locale=rb,Nd.localeData=sb,Nd.max=wd,Nd.min=vd,Nd.parsingFlags=Bb,Nd.set=F,Nd.startOf=tb,Nd.subtract=Bd,Nd.toArray=yb,Nd.toObject=zb,Nd.toDate=xb,Nd.toISOString=lb,Nd.toJSON=lb,Nd.toString=kb,Nd.unix=wb,Nd.valueOf=vb,Nd.year=td,Nd.isLeapYear=ia,Nd.weekYear=Fb,Nd.isoWeekYear=Gb,Nd.quarter=Nd.quarters=Jb,Nd.month=Y,Nd.daysInMonth=Z,Nd.week=Nd.weeks=na,Nd.isoWeek=Nd.isoWeeks=oa,Nd.weeksInYear=Ib,Nd.isoWeeksInYear=Hb,Nd.date=Dd,Nd.day=Nd.days=Pb,Nd.weekday=Qb,Nd.isoWeekday=Rb,Nd.dayOfYear=qa,Nd.hour=Nd.hours=Id,Nd.minute=Nd.minutes=Jd,Nd.second=Nd.seconds=Kd, + Nd.millisecond=Nd.milliseconds=Md,Nd.utcOffset=Na,Nd.utc=Pa,Nd.local=Qa,Nd.parseZone=Ra,Nd.hasAlignedHourOffset=Sa,Nd.isDST=Ta,Nd.isDSTShifted=Ua,Nd.isLocal=Va,Nd.isUtcOffset=Wa,Nd.isUtc=Xa,Nd.isUTC=Xa,Nd.zoneAbbr=Xb,Nd.zoneName=Yb,Nd.dates=aa("dates accessor is deprecated. Use date instead.",Dd),Nd.months=aa("months accessor is deprecated. Use month instead",Y),Nd.years=aa("years accessor is deprecated. Use year instead",td),Nd.zone=aa("moment().zone is deprecated, use moment().utcOffset instead. https://github.com/moment/moment/issues/1779",Oa);var Od=Nd,Pd={sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},Qd={LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},Rd="Invalid date",Sd="%d",Td=/\d{1,2}/,Ud={future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},Vd=s.prototype;Vd._calendar=Pd,Vd.calendar=_b,Vd._longDateFormat=Qd,Vd.longDateFormat=ac,Vd._invalidDate=Rd,Vd.invalidDate=bc,Vd._ordinal=Sd,Vd.ordinal=cc,Vd._ordinalParse=Td,Vd.preparse=dc,Vd.postformat=dc,Vd._relativeTime=Ud,Vd.relativeTime=ec,Vd.pastFuture=fc,Vd.set=gc,Vd.months=U,Vd._months=md,Vd.monthsShort=V,Vd._monthsShort=nd,Vd.monthsParse=W,Vd.week=ka,Vd._week=ud,Vd.firstDayOfYear=ma,Vd.firstDayOfWeek=la,Vd.weekdays=Lb,Vd._weekdays=Ed,Vd.weekdaysMin=Nb,Vd._weekdaysMin=Gd,Vd.weekdaysShort=Mb,Vd._weekdaysShort=Fd,Vd.weekdaysParse=Ob,Vd.isPM=Ub,Vd._meridiemParse=Hd,Vd.meridiem=Vb,w("en",{ordinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(a){var b=a%10,c=1===q(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c}}),a.lang=aa("moment.lang is deprecated. Use moment.locale instead.",w),a.langData=aa("moment.langData is deprecated. Use moment.localeData instead.",y);var Wd=Math.abs,Xd=yc("ms"),Yd=yc("s"),Zd=yc("m"),$d=yc("h"),_d=yc("d"),ae=yc("w"),be=yc("M"),ce=yc("y"),de=Ac("milliseconds"),ee=Ac("seconds"),fe=Ac("minutes"),ge=Ac("hours"),he=Ac("days"),ie=Ac("months"),je=Ac("years"),ke=Math.round,le={s:45,m:45,h:22,d:26,M:11},me=Math.abs,ne=Ha.prototype;ne.abs=oc,ne.add=qc,ne.subtract=rc,ne.as=wc,ne.asMilliseconds=Xd,ne.asSeconds=Yd,ne.asMinutes=Zd,ne.asHours=$d,ne.asDays=_d,ne.asWeeks=ae,ne.asMonths=be,ne.asYears=ce,ne.valueOf=xc,ne._bubble=tc,ne.get=zc,ne.milliseconds=de,ne.seconds=ee,ne.minutes=fe,ne.hours=ge,ne.days=he,ne.weeks=Bc,ne.months=ie,ne.years=je,ne.humanize=Fc,ne.toISOString=Gc,ne.toString=Gc,ne.toJSON=Gc,ne.locale=rb,ne.localeData=sb,ne.toIsoString=aa("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",Gc),ne.lang=Cd,H("X",0,0,"unix"),H("x",0,0,"valueOf"),N("x",_c),N("X",bd),Q("X",function(a,b,c){c._d=new Date(1e3*parseFloat(a,10))}),Q("x",function(a,b,c){c._d=new Date(q(a))}),a.version="2.10.6",b(Da),a.fn=Od,a.min=Fa,a.max=Ga,a.utc=h,a.unix=Zb,a.months=jc,a.isDate=d,a.locale=w,a.invalid=l,a.duration=Ya,a.isMoment=o,a.weekdays=lc,a.parseZone=$b,a.localeData=y,a.isDuration=Ia,a.monthsShort=kc,a.weekdaysMin=nc,a.defineLocale=x,a.weekdaysShort=mc,a.normalizeUnits=A,a.relativeTimeThreshold=Ec;var oe=a;return oe}); \ No newline at end of file diff --git a/app/assets/stylesheets/admin.scss b/app/assets/stylesheets/admin.scss index 67947ce2c..756a5e241 100644 --- a/app/assets/stylesheets/admin.scss +++ b/app/assets/stylesheets/admin.scss @@ -7,6 +7,7 @@ @import "bootstrap-datepicker.standalone"; @import "jquery.mloading"; @import "jquery-confirm.min"; +@import "bootstrap-datetimepicker.min"; @import "codemirror/lib/codemirror"; @import "editormd/css/editormd.min"; diff --git a/app/assets/stylesheets/admins/competition_settings.scss b/app/assets/stylesheets/admins/competition_settings.scss index ad1dd14b3..cef12cae3 100644 --- a/app/assets/stylesheets/admins/competition_settings.scss +++ b/app/assets/stylesheets/admins/competition_settings.scss @@ -37,6 +37,55 @@ } .setBtn_s{ height: 35px; - line-height: 5px; + line-height: 20px; + } + + .sponsor_label{ + border:1px solid #4CACFF; + border-radius: 5px; + background-color: rgba(76,172,255,0.3); + color: #333; + padding:0px 4px; + height: 30px; + line-height: 30px; + float: left; + margin: 4px 5px; + + span{ + display: block; + float: left; + height: 28px; + line-height: 28px; + margin-right: 5px; + } + + a{ + font-size: 18px; + float: left; + height: 28px; + line-height: 28px; + } + } + + .large_panel{ + padding:0px 15px; + + .large_panel_part{ + border-top: 1px solid #eaeaea; + } + .large_panel_part:first-child{ + border:none; + } + + .large_panel_part >.row ,.small_panel >.row{ + border-bottom: 1px solid #eaeaea; + padding:20px 0px; + } + .small_panel{ + margin-left: 20px; + } + .row:last-child{ + border:none; + } } } \ No newline at end of file diff --git a/app/assets/stylesheets/bootstrap-datetimepicker.min.css b/app/assets/stylesheets/bootstrap-datetimepicker.min.css new file mode 100755 index 000000000..78485fee7 --- /dev/null +++ b/app/assets/stylesheets/bootstrap-datetimepicker.min.css @@ -0,0 +1,9 @@ +/*! + * Datetimepicker for Bootstrap + * + * Copyright 2012 Stefan Petre + * Improvements by Andrew Rowls + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + */.datetimepicker{padding:4px;margin-top:1px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;direction:ltr}.datetimepicker-inline{width:220px}.datetimepicker.datetimepicker-rtl{direction:rtl}.datetimepicker.datetimepicker-rtl table tr td span{float:right}.datetimepicker-dropdown,.datetimepicker-dropdown-left{top:0;left:0}[class*=" datetimepicker-dropdown"]:before{content:'';display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-bottom-color:rgba(0,0,0,0.2);position:absolute}[class*=" datetimepicker-dropdown"]:after{content:'';display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #fff;position:absolute}[class*=" datetimepicker-dropdown-top"]:before{content:'';display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-top:7px solid #ccc;border-top-color:rgba(0,0,0,0.2);border-bottom:0}[class*=" datetimepicker-dropdown-top"]:after{content:'';display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-top:6px solid #fff;border-bottom:0}.datetimepicker-dropdown-bottom-left:before{top:-7px;right:6px}.datetimepicker-dropdown-bottom-left:after{top:-6px;right:7px}.datetimepicker-dropdown-bottom-right:before{top:-7px;left:6px}.datetimepicker-dropdown-bottom-right:after{top:-6px;left:7px}.datetimepicker-dropdown-top-left:before{bottom:-7px;right:6px}.datetimepicker-dropdown-top-left:after{bottom:-6px;right:7px}.datetimepicker-dropdown-top-right:before{bottom:-7px;left:6px}.datetimepicker-dropdown-top-right:after{bottom:-6px;left:7px}.datetimepicker>div{display:none}.datetimepicker.minutes div.datetimepicker-minutes{display:block}.datetimepicker.hours div.datetimepicker-hours{display:block}.datetimepicker.days div.datetimepicker-days{display:block}.datetimepicker.months div.datetimepicker-months{display:block}.datetimepicker.years div.datetimepicker-years{display:block}.datetimepicker table{margin:0}.datetimepicker td,.datetimepicker th{text-align:center;width:20px;height:20px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;border:0}.table-striped .datetimepicker table tr td,.table-striped .datetimepicker table tr th{background-color:transparent}.datetimepicker table tr td.minute:hover{background:#eee;cursor:pointer}.datetimepicker table tr td.hour:hover{background:#eee;cursor:pointer}.datetimepicker table tr td.day:hover{background:#eee;cursor:pointer}.datetimepicker table tr td.old,.datetimepicker table tr td.new{color:#999}.datetimepicker table tr td.disabled,.datetimepicker table tr td.disabled:hover{background:0;color:#999;cursor:default}.datetimepicker table tr td.today,.datetimepicker table tr td.today:hover,.datetimepicker table tr td.today.disabled,.datetimepicker table tr td.today.disabled:hover{background-color:#fde19a;background-image:-moz-linear-gradient(top,#fdd49a,#fdf59a);background-image:-ms-linear-gradient(top,#fdd49a,#fdf59a);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fdd49a),to(#fdf59a));background-image:-webkit-linear-gradient(top,#fdd49a,#fdf59a);background-image:-o-linear-gradient(top,#fdd49a,#fdf59a);background-image:linear-gradient(to bottom,#fdd49a,#fdf59a);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fdd49a',endColorstr='#fdf59a',GradientType=0);border-color:#fdf59a #fdf59a #fbed50;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.datetimepicker table tr td.today:hover,.datetimepicker table tr td.today:hover:hover,.datetimepicker table tr td.today.disabled:hover,.datetimepicker table tr td.today.disabled:hover:hover,.datetimepicker table tr td.today:active,.datetimepicker table tr td.today:hover:active,.datetimepicker table tr td.today.disabled:active,.datetimepicker table tr td.today.disabled:hover:active,.datetimepicker table tr td.today.active,.datetimepicker table tr td.today:hover.active,.datetimepicker table tr td.today.disabled.active,.datetimepicker table tr td.today.disabled:hover.active,.datetimepicker table tr td.today.disabled,.datetimepicker table tr td.today:hover.disabled,.datetimepicker table tr td.today.disabled.disabled,.datetimepicker table tr td.today.disabled:hover.disabled,.datetimepicker table tr td.today[disabled],.datetimepicker table tr td.today:hover[disabled],.datetimepicker table tr td.today.disabled[disabled],.datetimepicker table tr td.today.disabled:hover[disabled]{background-color:#fdf59a}.datetimepicker table tr td.today:active,.datetimepicker table tr td.today:hover:active,.datetimepicker table tr td.today.disabled:active,.datetimepicker table tr td.today.disabled:hover:active,.datetimepicker table tr td.today.active,.datetimepicker table tr td.today:hover.active,.datetimepicker table tr td.today.disabled.active,.datetimepicker table tr td.today.disabled:hover.active{background-color:#fbf069}.datetimepicker table tr td.active,.datetimepicker table tr td.active:hover,.datetimepicker table tr td.active.disabled,.datetimepicker table tr td.active.disabled:hover{background-color:#006dcc;background-image:-moz-linear-gradient(top,#08c,#04c);background-image:-ms-linear-gradient(top,#08c,#04c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));background-image:-webkit-linear-gradient(top,#08c,#04c);background-image:-o-linear-gradient(top,#08c,#04c);background-image:linear-gradient(to bottom,#08c,#04c);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc',endColorstr='#0044cc',GradientType=0);border-color:#04c #04c #002a80;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.datetimepicker table tr td.active:hover,.datetimepicker table tr td.active:hover:hover,.datetimepicker table tr td.active.disabled:hover,.datetimepicker table tr td.active.disabled:hover:hover,.datetimepicker table tr td.active:active,.datetimepicker table tr td.active:hover:active,.datetimepicker table tr td.active.disabled:active,.datetimepicker table tr td.active.disabled:hover:active,.datetimepicker table tr td.active.active,.datetimepicker table tr td.active:hover.active,.datetimepicker table tr td.active.disabled.active,.datetimepicker table tr td.active.disabled:hover.active,.datetimepicker table tr td.active.disabled,.datetimepicker table tr td.active:hover.disabled,.datetimepicker table tr td.active.disabled.disabled,.datetimepicker table tr td.active.disabled:hover.disabled,.datetimepicker table tr td.active[disabled],.datetimepicker table tr td.active:hover[disabled],.datetimepicker table tr td.active.disabled[disabled],.datetimepicker table tr td.active.disabled:hover[disabled]{background-color:#04c}.datetimepicker table tr td.active:active,.datetimepicker table tr td.active:hover:active,.datetimepicker table tr td.active.disabled:active,.datetimepicker table tr td.active.disabled:hover:active,.datetimepicker table tr td.active.active,.datetimepicker table tr td.active:hover.active,.datetimepicker table tr td.active.disabled.active,.datetimepicker table tr td.active.disabled:hover.active{background-color:#039}.datetimepicker table tr td span{display:block;width:23%;height:54px;line-height:54px;float:left;margin:1%;cursor:pointer;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.datetimepicker .datetimepicker-hours span{height:26px;line-height:26px}.datetimepicker .datetimepicker-hours table tr td span.hour_am,.datetimepicker .datetimepicker-hours table tr td span.hour_pm{width:14.6%}.datetimepicker .datetimepicker-hours fieldset legend,.datetimepicker .datetimepicker-minutes fieldset legend{margin-bottom:inherit;line-height:30px}.datetimepicker .datetimepicker-minutes span{height:26px;line-height:26px}.datetimepicker table tr td span:hover{background:#eee}.datetimepicker table tr td span.disabled,.datetimepicker table tr td span.disabled:hover{background:0;color:#999;cursor:default}.datetimepicker table tr td span.active,.datetimepicker table tr td span.active:hover,.datetimepicker table tr td span.active.disabled,.datetimepicker table tr td span.active.disabled:hover{background-color:#006dcc;background-image:-moz-linear-gradient(top,#08c,#04c);background-image:-ms-linear-gradient(top,#08c,#04c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));background-image:-webkit-linear-gradient(top,#08c,#04c);background-image:-o-linear-gradient(top,#08c,#04c);background-image:linear-gradient(to bottom,#08c,#04c);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc',endColorstr='#0044cc',GradientType=0);border-color:#04c #04c #002a80;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.datetimepicker table tr td span.active:hover,.datetimepicker table tr td span.active:hover:hover,.datetimepicker table tr td span.active.disabled:hover,.datetimepicker table tr td span.active.disabled:hover:hover,.datetimepicker table tr td span.active:active,.datetimepicker table tr td span.active:hover:active,.datetimepicker table tr td span.active.disabled:active,.datetimepicker table tr td span.active.disabled:hover:active,.datetimepicker table tr td span.active.active,.datetimepicker table tr td span.active:hover.active,.datetimepicker table tr td span.active.disabled.active,.datetimepicker table tr td span.active.disabled:hover.active,.datetimepicker table tr td span.active.disabled,.datetimepicker table tr td span.active:hover.disabled,.datetimepicker table tr td span.active.disabled.disabled,.datetimepicker table tr td span.active.disabled:hover.disabled,.datetimepicker table tr td span.active[disabled],.datetimepicker table tr td span.active:hover[disabled],.datetimepicker table tr td span.active.disabled[disabled],.datetimepicker table tr td span.active.disabled:hover[disabled]{background-color:#04c}.datetimepicker table tr td span.active:active,.datetimepicker table tr td span.active:hover:active,.datetimepicker table tr td span.active.disabled:active,.datetimepicker table tr td span.active.disabled:hover:active,.datetimepicker table tr td span.active.active,.datetimepicker table tr td span.active:hover.active,.datetimepicker table tr td span.active.disabled.active,.datetimepicker table tr td span.active.disabled:hover.active{background-color:#039}.datetimepicker table tr td span.old{color:#999}.datetimepicker th.switch{width:145px}.datetimepicker th span.glyphicon{pointer-events:none}.datetimepicker thead tr:first-child th,.datetimepicker tfoot th{cursor:pointer}.datetimepicker thead tr:first-child th:hover,.datetimepicker tfoot th:hover{background:#eee}.input-append.date .add-on i,.input-prepend.date .add-on i,.input-group.date .input-group-addon span{cursor:pointer;width:14px;height:14px} \ No newline at end of file diff --git a/app/assets/stylesheets/common.scss b/app/assets/stylesheets/common.scss index 9312a694f..19df03619 100644 --- a/app/assets/stylesheets/common.scss +++ b/app/assets/stylesheets/common.scss @@ -29,7 +29,8 @@ input.form-control { .flex-1 { flex: 1; } - +.fl{float: left} +.no_padding{padding: 0px!important;} .font-12 { font-size: 12px !important; } .font-14 { font-size: 14px !important; } .font-16 { font-size: 16px !important; } @@ -48,6 +49,10 @@ input.form-control { .position-r{position:relative;} .color-grey-c{color:#ccc} .color-blue{color:#4CACFF} +.color-orange{color: #ff6800} .inline-block{display:inline-block;} .hide{display: none;} .show{display: block;} + +.input_small{flex: 0 0 6%!important;} +.input_middle{flex:0 0 13%!important;} diff --git a/app/controllers/admins/competition_settings_controller.rb b/app/controllers/admins/competition_settings_controller.rb index 9fee83c3e..b2e1dba26 100644 --- a/app/controllers/admins/competition_settings_controller.rb +++ b/app/controllers/admins/competition_settings_controller.rb @@ -20,10 +20,14 @@ class Admins::CompetitionSettingsController < Admins::BaseController end def basic_form_params - params.permit(:identifier, :name, :sub_title, :start_time, :end_time, :mode, :identifier, :bonus, :awards_count, :description, :course_id, :teach_start_time, :teach_end_time) + params.permit(:identifier, :name, :sub_title, :start_time, :end_time, :mode, + :identifier, :bonus, :awards_count, :description, :course_id, :teach_start_time, + :teach_end_time, sponsor_schools: [], region_schools: []) end def nav_form_params - params.permit(:enroll_end_time, competition_staffs: %i[category minimum maximum mutiple_limited], nav_module: %i[module_type name hidden position url]) + params.permit(:enroll_end_time, + competition_staffs: %i[category minimum maximum mutiple_limited], + navbar: %i[module_type name hidden position url]) end end \ No newline at end of file diff --git a/app/controllers/admins/competition_stages_controller.rb b/app/controllers/admins/competition_stages_controller.rb index 537240bde..b02d5ae8c 100644 --- a/app/controllers/admins/competition_stages_controller.rb +++ b/app/controllers/admins/competition_stages_controller.rb @@ -1,76 +1,46 @@ class Admins::CompetitionStagesController < Admins::BaseController def create - if @competition.competition_stages.exists?(name: params[:stage_name]) - render_error "已存在同名的阶段" - else - @competition.competition_stages << CompetitionStage.new(name: params[:stage_name]) - render_ok - end + Admins::CompetitionStageCreateService.call(current_competition, update_form_params) + render_ok end def update - current_stage.update_attributes!(name: params[:stage_name], score_rate: params[:score_rate]) + Admins::CompetitionStageUpdateService.call(current_competition, update_form_params, current_stage) render_ok end def destroy current_stage.destroy! - render_ok end - def create_stage_section - ActiveRecord::Base.transaction do - new_section = CompetitionStageSection.create!(competition_id: current_stage.competition_id, competition_stage_id: current_stage.id, - start_time: params[:new_start_time], end_time: params[:new_end_time], - entry: params[:entry], mission_count: params[:mission_count], score_source: params[:score_source]) - unless params[:shixun_identifiers].blank? - params[:shixun_identifiers].each do |identifier| - new_section.competition_entries << CompetitionEntry.new(competition_stage_id: current_stage.id, shixun_identifier: identifier) - end - end - render_ok + def calculate_stage_score + if current_stage.max_end_time && current_stage.max_end_time < Time.now + + else + render_error("#{current_stage.name}还未结束") end end - def update_stage_section - ActiveRecord::Base.transaction do - section = current_stage.competition_stage_sections.find_by!(id: params[:section_id]) - if section.present? - section_entries = section.competition_entries - if !params[:shixun_identifiers] - section_entries.destroy_all - else - if params[:shixun_identifiers].length < section_entries.size - section_entries[params[:shixun_identifiers].length, section_entries.size - 1].each(&:destroy) - end - - params[:shixun_identifiers].each_with_index do |identifier, index| - entry = section_entries[index] - if entry.present? - entry.update_attributes!(shixun_identifier: identifier) - else - section.competition_entries << CompetitionEntry.new(competition_stage_id: current_stage.id, shixun_identifier: identifier) - end + def send_message + if current_stage.max_end_time && current_stage.max_end_time > Time.now + User.where(id: TeamMember.where(competition_team_id: current_competition.competition_teams.pluck(:id)).pluck(:user_id).uniq).each do |user| + name = current_competition.name + "#{current_competition.sub_title}(#{stage.name})" + begin + if user.phone.present? + Educoder::Sms.send(mobile: user.phone.to_s, code: '1', send_type:'competition_start', user_name:user.show_name, + name:name, result:section.start_time.strftime('%Y-%m-%d %H:%M:%S')) end + rescue => e + logger_error(e) + render_error("发送验证码出错") end - section.update_attributes!(start_time: params[:new_start_time], end_time: params[:new_end_time], - entry: params[:entry], mission_count: params[:mission_count], score_source: params[:score_source]) - render_ok end + else + render_error("#{current_stage.name}已结束") end end - def destroy_stage_section - section = current_stage.competition_stage_sections.find_by!(id: params[:section_id]) - section.destroy! - render_ok - end - - def calculate_stage_score - - end - private def current_competition @@ -78,6 +48,11 @@ class Admins::CompetitionStagesController < Admins::BaseController end def current_stage - @_current_stage ||= CompetitionStage.find_by!(competition_id: params[:competition_id], id: params[:stage_id]) + @_current_stage ||= CompetitionStage.find_by!(competition_id: params[:competition_id], id: params[:id]) end + + def update_form_params + params.permit(:stage_name, :score_rate, stage: [:start_time, :end_time, :mission_count, :entry, :score_source, identifiers: []]) + end + end \ No newline at end of file diff --git a/app/controllers/admins/competitions_controller.rb b/app/controllers/admins/competitions_controller.rb index 2e2dbd4e2..ee563be1f 100644 --- a/app/controllers/admins/competitions_controller.rb +++ b/app/controllers/admins/competitions_controller.rb @@ -1,11 +1,10 @@ class Admins::CompetitionsController < Admins::BaseController - include CustomSortable before_action :find_competition, except: [:index] def index - params[:sort_by] = params[:sort_by].presence || 'created_on' - params[:sort_direction] = params[:sort_direction].presence || 'desc' - @competitions = custom_sort Competition.all, params[:sort_by], params[:sort_direction] + # params[:sort_by] = params[:sort_by].presence || 'created_at' + # params[:sort_direction] = params[:sort_direction].presence || 'desc' + @competitions = Competition.all.order("created_at desc") @params_page = params[:page] || 1 @competitions = paginate @competitions ids = @competitions.map(&:id) diff --git a/app/controllers/admins/users_controller.rb b/app/controllers/admins/users_controller.rb index cdb64c71f..6aaec04e1 100644 --- a/app/controllers/admins/users_controller.rb +++ b/app/controllers/admins/users_controller.rb @@ -32,13 +32,13 @@ class Admins::UsersController < Admins::BaseController end def lock - User.find(params[:user_id]).lock! + User.find(params[:id]).lock! render_ok end def unlock - User.find(params[:user_id]).activate! + User.find(params[:id]).activate! render_ok end diff --git a/app/controllers/competitions/competition_teams_controller.rb b/app/controllers/competitions/competition_teams_controller.rb index db4608807..6d28d6a16 100644 --- a/app/controllers/competitions/competition_teams_controller.rb +++ b/app/controllers/competitions/competition_teams_controller.rb @@ -59,6 +59,7 @@ class Competitions::CompetitionTeamsController < Competitions::BaseController end def index + @competition = current_competition @personal = current_competition.personal? if admin_or_business? all_competition_teams @@ -115,11 +116,13 @@ class Competitions::CompetitionTeamsController < Competitions::BaseController keyword = params[:keyword].to_s.strip if keyword.present? - teams = teams.joins(users: { user_extension: :school }).where('schools.name LIKE ?', "%#{keyword}%") + teams = teams.joins(user: { user_extension: :school }) + .where('competition_teams.name LIKE :keyword OR schools.name LIKE :keyword', keyword: "%#{keyword}%") end @all_count = teams.count @all_teams = paginate(teams.includes(:user, users: { user_extension: :school })) + @all_member_count = teams.joins(:team_members).count end def user_competition_teams @@ -135,7 +138,7 @@ class Competitions::CompetitionTeamsController < Competitions::BaseController def tech_mode # render_not_found if current_competition.mode != 3 - @team = current_competition.competition_teams.find_by(id: params[:id]) + @team = current_competition.competition_teams.find_by!(id: params[:id]) end def get_valid_myshixun_count(ids) diff --git a/app/controllers/competitions/competitions_controller.rb b/app/controllers/competitions/competitions_controller.rb index 2cae06774..c3c5c8524 100644 --- a/app/controllers/competitions/competitions_controller.rb +++ b/app/controllers/competitions/competitions_controller.rb @@ -13,7 +13,7 @@ class Competitions::CompetitionsController < Competitions::BaseController competitions = case params[:category] when 'nearly_published' then competitions.where(status: false) - when 'progressing' then competitions.where('end_time > NOW()') + when 'progressing' then competitions.where('status = 1 and end_time > NOW()') when 'ended' then competitions.where('end_time < NOW()') else competitions end @@ -30,6 +30,8 @@ class Competitions::CompetitionsController < Competitions::BaseController def show @competition = current_competition + + current_competition.increment(:visits) end def update @@ -69,13 +71,16 @@ class Competitions::CompetitionsController < Competitions::BaseController end def update_md_content - tip_exception("标题和内容不能为空") if params[:name].blank? || params[:content].blank? + tip_exception("内容不能为空") if params[:content].blank? + tip_exception("缺少competition_module_id") if params[:competition_module_id].blank? ActiveRecord::Base.transaction do + com_module = current_competition.competition_modules.find_by!(id: params[:competition_module_id]) if params[:md_content_id] - md_content = CompetitionModuleMdContent.find_by!(id: params[:md_content_id]) + md_content = CompetitionModuleMdContent.find_by!(id: params[:md_content_id], competition_module_id: com_module.id) md_content.update_attributes!(name: params[:name], content: params[:content]) else - md_content = CompetitionModuleMdContent.create!(name: params[:name], content: params[:content]) + stage = current_competition.competition_stages.find_by(id: params[:stage_id]) if params[:stage_id] + md_content = CompetitionModuleMdContent.create!(name: params[:name], content: params[:content], competition_module_id: com_module.id, competition_stage_id: stage&.id.to_i) end Attachment.associate_container(params[:attachment_ids], md_content.id, md_content.class) if params[:attachment_ids] normal_status("更新成功") @@ -84,8 +89,8 @@ class Competitions::CompetitionsController < Competitions::BaseController def chart_rules @competition = current_competition - @stages = @competition.competition_stages - @rule_contents = @competition.chart_rules + com_module = @competition.competition_modules.find_by(module_type: "chart") + @rule_contents = com_module&.competition_module_md_contents end def update_chart_rules diff --git a/app/controllers/competitions/students_controller.rb b/app/controllers/competitions/students_controller.rb index 8fd235fd1..9d0b40754 100644 --- a/app/controllers/competitions/students_controller.rb +++ b/app/controllers/competitions/students_controller.rb @@ -7,6 +7,7 @@ class Competitions::StudentsController < Competitions::BaseController end students = User.joins(:user_extension).where(status: 1, user_extensions: { identity: 1 }) + students = students.where(user_extensions: { school_id: current_competition.region_schools.pluck(:school_id) }) if current_competition.region_schools.size > 0 students = students.where.not(id: params[:student_ids]) if params[:student_ids].present? students = students.where('LOWER(CONCAT(lastname, firstname, login, nickname)) LIKE ?', "%#{keyword}%") @students = students.includes(user_extension: :school).limit(20) diff --git a/app/controllers/competitions/teachers_controller.rb b/app/controllers/competitions/teachers_controller.rb index 76c7cfe6a..04ab1bdd0 100644 --- a/app/controllers/competitions/teachers_controller.rb +++ b/app/controllers/competitions/teachers_controller.rb @@ -7,6 +7,7 @@ class Competitions::TeachersController < Competitions::BaseController end teachers = User.joins(:user_extension).where(status: 1, user_extensions: { identity: 0 }) + teachers = teachers.where(user_extensions: { school_id: current_competition.region_schools.pluck(:school_id) }) if current_competition.region_schools.size > 0 teachers = teachers.where.not(id: params[:teacher_ids]) if params[:teacher_ids].present? teachers = teachers.where('LOWER(CONCAT(lastname, firstname, login, nickname)) LIKE ?', "%#{keyword}%") @teachers = teachers.includes(user_extension: :school).limit(10) diff --git a/app/controllers/cooperative/users_controller.rb b/app/controllers/cooperative/users_controller.rb index 8d6e5f52a..4c6539147 100644 --- a/app/controllers/cooperative/users_controller.rb +++ b/app/controllers/cooperative/users_controller.rb @@ -2,9 +2,14 @@ class Cooperative::UsersController < Cooperative::BaseController def index params[:sort_by] = params[:sort_by].presence || 'created_on' params[:sort_direction] = params[:sort_direction].presence || 'desc' - params[:school_id] = current_laboratory.school_id - users = Admins::UserQuery.call(params) + users = Admins::UserQuery.call(search_params) @users = paginate users.includes(user_extension: :school) end + + private + + def search_params + params.permit(:name, :sort_by, :sort_direction) + end end \ No newline at end of file diff --git a/app/controllers/polls_controller.rb b/app/controllers/polls_controller.rb index bbd2a06fa..2504b8eb8 100644 --- a/app/controllers/polls_controller.rb +++ b/app/controllers/polls_controller.rb @@ -1363,7 +1363,7 @@ class PollsController < ApplicationController poll_ques_titles = poll_questions.pluck(:question_title).map {|k| ActionController::Base.helpers.strip_tags(k) if k.present?} poll_un_anony = poll.un_anonymous if poll_un_anony #是否匿名,默认为false - user_info = %w(登陆名 真实姓名 邮箱 学号 学员单位) + user_info = %w(登陆名 真实姓名 分班 邮箱 学号 学员单位) else user_info = [] end @@ -1436,9 +1436,10 @@ class PollsController < ApplicationController if poll_un_anony user_login = u_user.login user_name = u_user.real_name.present? ? u_user.real_name : "--" + user_class = poll.course.user_group_name(u_user.id) user_student_id = u_user.student_id.present? ? u_user.student_id : "--" user_school_name = u_user.school_name.present? ? u_user.school_name : "--" - user_cell += [user_login,user_name, u_user.mail, user_student_id, user_school_name] + user_cell += [user_login,user_name, user_class, u_user.mail, user_student_id, user_school_name] end all_user_cell = user_cell + user_answer_array user_commit.push(all_user_cell) diff --git a/app/controllers/weapps/code_sessions_controller.rb b/app/controllers/weapps/code_sessions_controller.rb index c92c3cb70..887e97eed 100644 --- a/app/controllers/weapps/code_sessions_controller.rb +++ b/app/controllers/weapps/code_sessions_controller.rb @@ -25,6 +25,8 @@ class Weapps::CodeSessionsController < Weapps::BaseController end set_session_unionid(user_info['unionId']) + user_info['nickname'] = user_info['nickName'] + session[:wechat_user_extra] = user_info end set_session_openid(result['openid']) diff --git a/app/controllers/weapps/sessions_controller.rb b/app/controllers/weapps/sessions_controller.rb index 371a3f7d3..8c7c57a7f 100644 --- a/app/controllers/weapps/sessions_controller.rb +++ b/app/controllers/weapps/sessions_controller.rb @@ -16,7 +16,7 @@ class Weapps::SessionsController < Weapps::BaseController end # 绑定微信号 - OpenUsers::Wechat.create!(user: user, uid: session_unionid) if user.wechat_open_user.blank? + OpenUsers::Wechat.create!(user: user, uid: session_unionid, extra: session[:wechat_user_extra]) if user.wechat_open_user.blank? successful_authentication(user) end diff --git a/app/controllers/weapps/verification_codes_controller.rb b/app/controllers/weapps/verification_codes_controller.rb new file mode 100644 index 000000000..7590c49f7 --- /dev/null +++ b/app/controllers/weapps/verification_codes_controller.rb @@ -0,0 +1,51 @@ +class Weapps::VerificationCodesController < Weapps::BaseController + before_action :require_wechat_login! + + def create + params[:type] == 'register' ? check_can_register : check_can_reset_password + end + + private + + def check_can_register + login = params[:login].to_s.strip + if login =~ /^[a-zA-Z0-9]+([._\\]*[a-zA-Z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/ + user = User.find_by(mail: login) + return render_error('该邮箱已注册') if user.present? + elsif login =~ /^1\d{10}$/ + user = User.find_by(phone: params[:login]) + return render_error('该手机号已注册') if user.present? + else + return render_error('请输入正确的邮箱或手机号') + end + + code = %W(0 1 2 3 4 5 6 7 8 9) + verification_code = code.sample(6).join + send_type = login =~ /^1\d{10}$/ ? 1 : 8 + # 记录验证码 + check_verification_code(verification_code, send_type, login) + + render_ok + end + + def check_can_reset_password + login = params[:login].to_s.strip + if login =~ /^[a-zA-Z0-9]+([._\\]*[a-zA-Z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/ + user = User.find_by(mail: login) + return render_error('该邮箱尚未注册') if user.blank? + elsif login =~ /^1\d{10}$/ + user = User.find_by(phone: login) + return render_error('该手机号尚未注册') if user.blank? + else + return render_error('请输入正确的邮箱或手机号') + end + + code = %W(0 1 2 3 4 5 6 7 8 9) + verification_code = code.sample(6).join + send_type = login =~ /^1\d{10}$/ ? 2 : 3 + # 记录验证码 + check_verification_code(verification_code, send_type, login) + + render_ok + end +end \ No newline at end of file diff --git a/app/forms/competitions/save_team_form.rb b/app/forms/competitions/save_team_form.rb index dd2610083..6b418eec8 100644 --- a/app/forms/competitions/save_team_form.rb +++ b/app/forms/competitions/save_team_form.rb @@ -86,6 +86,7 @@ class Competitions::SaveTeamForm # 创建者是否能多次报名 def check_creator_multiple_enrollable + return unless team.new_record? # 编辑战队时不需要校验 return unless competition.enrolled?(creator) if (creator.is_teacher? && competition.teacher_multiple_limited?) || (!creator.is_teacher? && competition.member_multiple_limited?) diff --git a/app/helpers/competitions_helper.rb b/app/helpers/competitions_helper.rb index 9e3e7f62a..ebafe4e02 100644 --- a/app/helpers/competitions_helper.rb +++ b/app/helpers/competitions_helper.rb @@ -37,7 +37,7 @@ module CompetitionsHelper def chart_stages competition stages = [] - statistic_stages = competition.competition_stages.where("rate > 0") + statistic_stages = competition.competition_stages.where("score_rate > 0") if competition.end_time && competition.end_time < Time.now && statistic_stages.size > 1 stages << {id: nil, name: "总排行榜", rate: 1.0, start_time: competition.start_time, end_time: competition.end_time} end diff --git a/app/helpers/courses_helper.rb b/app/helpers/courses_helper.rb index 9afbdd3af..4de15b20f 100644 --- a/app/helpers/courses_helper.rb +++ b/app/helpers/courses_helper.rb @@ -244,11 +244,7 @@ module CoursesHelper course_group_ids = course.group_course_power(user_id) course_groups = if course_group_ids.present? - sql = %Q{ - SELECT * FROM course_groups WHERE id in(SELECT course_group_id FROM teacher_course_groups WHERE id - IN(#{course_group_ids.join(",")})) order by position ASC - } - CourseGroup.find_by_sql(sql) + course.course_groups.where(id: course_group_ids).includes(:course_members) else course.course_groups.includes(:course_members) end diff --git a/app/helpers/export_helper.rb b/app/helpers/export_helper.rb index 534a78dc1..1274e07c7 100644 --- a/app/helpers/export_helper.rb +++ b/app/helpers/export_helper.rb @@ -300,8 +300,7 @@ module ExportHelper export_ex_users.includes(user: :user_extension).each_with_index do |e_user,index| user_info = e_user.user - member = course.students.find_by_user_id(e_user.user_id) - user_course = member.try(:course_group_name) + user_course = course.user_group_name(e_user.user_id) user_obj_score = e_user.objective_score < 0.0 ? 0.0 : e_user.objective_score.round(1).to_s user_suj_score = e_user.subjective_score < 0.0 ? 0.0 : e_user.subjective_score.round(1).to_s user_score = e_user.score.present? ? e_user.score.round(1).to_s : 0.0 diff --git a/app/libs/util.rb b/app/libs/util.rb index 38b5c9af5..1db9460f0 100644 --- a/app/libs/util.rb +++ b/app/libs/util.rb @@ -60,7 +60,7 @@ module Util return if str.blank? case type - when :phone then "#{str[0..2]}***#{str[-3..-1]}" + when :phone then "#{str[0..2]}****#{str[-4..-1]}" when :email then "#{str[0]}***#{str[(str.rindex('@')-1)..-1]}" else "#{str[0..2]}***#{str[-3..-1]}" end diff --git a/app/models/competition.rb b/app/models/competition.rb index 39e4f4dfe..b5526f74c 100644 --- a/app/models/competition.rb +++ b/app/models/competition.rb @@ -22,6 +22,9 @@ class Competition < ApplicationRecord has_many :attachments, as: :container, dependent: :destroy has_many :competition_awards, dependent: :destroy + has_many :competition_schools, dependent: :destroy + has_many :sponsor_schools, -> { where(source: :sponsor) }, class_name: 'CompetitionSchool' # 主办方 + has_many :region_schools, -> { where(source: :region) }, class_name: 'CompetitionSchool' # 开放范围 after_create :create_competition_modules @@ -66,7 +69,7 @@ class Competition < ApplicationRecord # 是否为个人赛 def personal? - competition_staffs.maximum(:maximum) == 1 || max_num == 1 + competition_staffs.sum(:maximum).to_i == 1 || (competition_staffs.nil? && max_num == 1) end # 报名是否结束 @@ -79,6 +82,12 @@ class Competition < ApplicationRecord team_members.exists?(user_id: user.id) end + # 是否开放 + def open?(user) + user_school_id = user.user_extension&.school_id.to_i + region_schools.size == 0 || region_schools.exists?(school_id: user_school_id) + end + # 是否禁止教师报名 def teacher_enroll_forbidden? teacher_staff.blank? || teacher_staff.maximum.zero? diff --git a/app/models/competition_module.rb b/app/models/competition_module.rb index 76f7610d2..3b1bfddda 100644 --- a/app/models/competition_module.rb +++ b/app/models/competition_module.rb @@ -3,22 +3,16 @@ class CompetitionModule < ApplicationRecord belongs_to :competition - has_one :competition_module_md_content, dependent: :destroy + has_many :competition_module_md_contents, dependent: :destroy def module_url - case module_type - when "home" - "/competitions/#{competition.identifier}" - when "inform" - "/competitions/#{competition.identifier}/informs?status=1" - when "manual" - "/competitions/#{competition.identifier}/informs?status=2" - when "chart" - "/competitions/#{competition.identifier}/charts" - when "enroll" - "/competitions/#{competition.identifier}/competition_teams" - else - url || "/competitions/#{competition.identifier}/md_content?md_content_id=#{competition_module_md_content&.id}" - end + result_url = url.present? ? url : case module_type + when "chart" + "/competitions/#{competition.identifier}/charts.json" + when "enroll" + "/competitions/#{competition.identifier}/competition_teams.json" + else + "/competitions/#{competition.identifier}/competition_modules/#{id}.json" + end end end diff --git a/app/models/competition_module_md_content.rb b/app/models/competition_module_md_content.rb index 9dfcfca84..4a8dacf9e 100644 --- a/app/models/competition_module_md_content.rb +++ b/app/models/competition_module_md_content.rb @@ -3,6 +3,6 @@ class CompetitionModuleMdContent < ApplicationRecord has_many :attachments, as: :container, dependent: :destroy - validates :name, presence: true + # validates :name, presence: true validates :content, presence: true end \ No newline at end of file diff --git a/app/models/competition_school.rb b/app/models/competition_school.rb new file mode 100644 index 000000000..c1a5decbe --- /dev/null +++ b/app/models/competition_school.rb @@ -0,0 +1,5 @@ +class CompetitionSchool < ApplicationRecord + # source sponsor: 主办方, region:开放范围 + belongs_to :competition + belongs_to :school +end diff --git a/app/models/competition_stage.rb b/app/models/competition_stage.rb index dec777b39..ca15733d9 100644 --- a/app/models/competition_stage.rb +++ b/app/models/competition_stage.rb @@ -5,6 +5,7 @@ class CompetitionStage < ApplicationRecord has_many :competition_entries, dependent: :destroy has_many :competition_scores, dependent: :destroy + has_one :competition_module_md_content, dependent: :destroy has_one :chart_rule, dependent: :destroy def min_start_time diff --git a/app/models/competition_stage_section.rb b/app/models/competition_stage_section.rb index 027e7ec69..3c8794ad8 100644 --- a/app/models/competition_stage_section.rb +++ b/app/models/competition_stage_section.rb @@ -1,4 +1,5 @@ class CompetitionStageSection < ApplicationRecord + # score_source 0: 经验值, 1:预测准确率 belongs_to :competition belongs_to :competition_stage diff --git a/app/models/course.rb b/app/models/course.rb index 6dd361733..01eed30db 100644 --- a/app/models/course.rb +++ b/app/models/course.rb @@ -130,6 +130,10 @@ class Course < ApplicationRecord course_members.find_by(user_id: user_id, role: %i(STUDENT)) end + def user_group_name(user_id) + students.find_by(user_id: user_id)&.course_group_name + end + def teacher_group(user_id) data = diff --git a/app/models/user.rb b/app/models/user.rb index 55572288c..6b5fc62ee 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -666,6 +666,10 @@ class User < ApplicationRecord if password.present? && password.size < MIX_PASSWORD_LIMIT && !User.current.admin? raise("密码长度不能低于#{MIX_PASSWORD_LIMIT}位") end + + if password.present? && password.size > 16 + raise('密码长度不能超过16位') + end end end diff --git a/app/models/weapp_settings/advert.rb b/app/models/weapp_settings/advert.rb index 564e85565..993b1fd85 100644 --- a/app/models/weapp_settings/advert.rb +++ b/app/models/weapp_settings/advert.rb @@ -1,2 +1,3 @@ class WeappSettings::Advert < WeappSetting + default_scope { order(position: :asc) } end \ No newline at end of file diff --git a/app/services/admins/competition_basic_setting_service.rb b/app/services/admins/competition_basic_setting_service.rb index e5a7dd6be..fd1c1453a 100644 --- a/app/services/admins/competition_basic_setting_service.rb +++ b/app/services/admins/competition_basic_setting_service.rb @@ -20,8 +20,9 @@ class Admins::CompetitionBasicSettingService < ApplicationService competition.save! + # 竞赛模式相关设置 if competition.mode == 1 || competition.mode == 4 - competition.competition_mode_setting.destroy + competition.competition_mode_setting&.destroy else setting = competition.competition_mode_setting || CompetitionModeSetting.create!(competition_id: competition.id) if competition.mode == 2 @@ -33,6 +34,26 @@ class Admins::CompetitionBasicSettingService < ApplicationService setting.save! end + # 主办方设置 + params[:sponsor_schools] = Array.wrap(params[:sponsor_schools]).map(&:to_i) + new_sponsor_school_ids = competition.sponsor_schools.pluck(:school_id) + new_school_ids = params[:sponsor_schools] - new_sponsor_school_ids + delete_school_ids = new_sponsor_school_ids - params[:sponsor_schools] + new_school_ids.each do |school_id| + CompetitionSchool.create!(competition_id: competition.id, school_id: school_id, source: 'sponsor') + end + competition.sponsor_schools.where(school_id: delete_school_ids).destroy_all + + # 开放范围设置 + params[:region_schools] = Array.wrap(params[:region_schools]).map(&:to_i) + old_region_school_ids = competition.region_schools.pluck(:school_id) + new_region_school_ids = params[:region_schools] - old_region_school_ids + delete_region_school_ids = old_region_school_ids - params[:region_schools] + new_region_school_ids.each do |school_id| + CompetitionSchool.create!(competition_id: competition.id, school_id: school_id, source: 'region') + end + competition.region_schools.where(school_id: delete_region_school_ids).destroy_all unless delete_region_school_ids.length == 0 + competition end end diff --git a/app/services/admins/competition_nav_setting_service.rb b/app/services/admins/competition_nav_setting_service.rb index 13b58a799..4254dd060 100644 --- a/app/services/admins/competition_nav_setting_service.rb +++ b/app/services/admins/competition_nav_setting_service.rb @@ -13,16 +13,17 @@ class Admins::CompetitionNavSettingService < ApplicationService # hidden_module_type = competition.all_module_types - params[:module_type] # competition.competition_modules.where(module_type: hidden_module_type).update_all(hidden: 1) - params[:nav_module].each do |nav| + params[:navbar].each do |nav| module_type = nav["module_type"] if competition.all_module_types.include?(module_type) com_module = competition.competition_modules.find_by(module_type: module_type) else com_module = CompetitionModule.create!(competition_id: competition.id, module_type: 'md') end - com_module.update_attributes!(hidden: nav["hidden"] ? 0 : 1, position: nav["position"], name: nav["name"], url: nav["url"]) + com_module.update_attributes!(hidden: nav["hidden"] ? 0 : 1, position: nav["position"] ? nav["position"] : com_module.position, name: nav["name"], url: nav["url"]) end + competition.update_attributes!(enroll_end_time: params[:enroll_end_time]) if params[:competition_staffs].present? competition.competition_staffs.delete_all params[:competition_staffs].each_with_index do |staff_params, index| diff --git a/app/services/admins/competition_stage_create_service.rb b/app/services/admins/competition_stage_create_service.rb new file mode 100644 index 000000000..4389a727d --- /dev/null +++ b/app/services/admins/competition_stage_create_service.rb @@ -0,0 +1,27 @@ +class Admins::CompetitionStageCreateService < ApplicationService + attr_reader :competition, :params + + def initialize(competition, params) + @params = params + @competition = competition + end + + def call + ActiveRecord::Base.transaction do + stage = CompetitionStage.create!(competition_id: competition.id, name: params[:stage_name], score_rate: (params[:score_rate].to_i / 100).round(2)) + + params[:stage].each do |section| + stage_section = CompetitionStageSection.create!(competition_id: competition.id, competition_stage_id: stage.id, + start_time: section["start_time"], end_time: section["end_time"], + mission_count: section["mission_count"], entry: section["entry"], + score_source: section["score_source"]) + section["identifiers"].each do |identifier| + CompetitionEntry.create!(competition_stage_section_id: stage_section.id, competition_stage_id: stage.id, + shixun_identifier: identifier) + end + end + + stage + end + end +end \ No newline at end of file diff --git a/app/services/admins/competition_stage_update_service.rb b/app/services/admins/competition_stage_update_service.rb new file mode 100644 index 000000000..da7fb4c6d --- /dev/null +++ b/app/services/admins/competition_stage_update_service.rb @@ -0,0 +1,30 @@ +class Admins::CompetitionStageUpdateService < ApplicationService + attr_reader :competition, :params, :stage + + def initialize(competition, params, stage) + @params = params + @competition = competition + @stage = stage + end + + def call + ActiveRecord::Base.transaction do + stage.update_attributes!(name: params[:stage_name], score_rate: (params[:score_rate].to_i / 100.0).round(2)) + + stage.competition_stage_sections.destroy_all + + params[:stage].each do |section| + stage_section = CompetitionStageSection.create!(competition_id: competition.id, competition_stage_id: stage.id, + start_time: section["start_time"], end_time: section["end_time"], + mission_count: section["mission_count"], entry: section["entry"], + score_source: section["score_source"]) + section["identifiers"].each do |identifier| + CompetitionEntry.create!(competition_stage_section_id: stage_section.id, competition_stage_id: stage.id, + shixun_identifier: identifier) + end + end + + stage + end + end +end \ No newline at end of file diff --git a/app/services/admins/drag_weapp_advert_service.rb b/app/services/admins/drag_weapp_advert_service.rb index b041c9d18..8bfb7c317 100644 --- a/app/services/admins/drag_weapp_advert_service.rb +++ b/app/services/admins/drag_weapp_advert_service.rb @@ -9,22 +9,22 @@ class Admins::DragWeappAdvertService < ApplicationService def call return if move.position + 1 == after&.position # 未移动 - carousels = WeappSettings::Advert.all + adverts = WeappSettings::Advert.all ActiveRecord::Base.transaction do if after.blank? || move.id == after.id # 移动至末尾 - total = carousels.count + total = adverts.count - carousels.where('position > ?', move.position).update_all('position = position - 1') + adverts.where('position > ?', move.position).update_all('position = position - 1') move.update!(position: total) return end if move.position > after.position # 前移 - carousels.where('position >= ? AND position < ?', after.position, move.position).update_all('position = position + 1') + adverts.where('position >= ? AND position < ?', after.position, move.position).update_all('position = position + 1') move.update!(position: after.position) else # 后移 - carousels.where('position > ? AND position < ?', move.position, after.position).update_all('position = position - 1') + adverts.where('position > ? AND position < ?', move.position, after.position).update_all('position = position - 1') move.update!(position: after.position - 1) end end diff --git a/app/services/competitions/create_personal_team_service.rb b/app/services/competitions/create_personal_team_service.rb index 907c59dc0..998a13880 100644 --- a/app/services/competitions/create_personal_team_service.rb +++ b/app/services/competitions/create_personal_team_service.rb @@ -11,6 +11,8 @@ class Competitions::CreatePersonalTeamService < ApplicationService def call raise Error, '个人赛才能报名' unless competition.personal? + raise Error, '本竞赛只面向部分学校/单位开放,你暂时没有参赛资格' unless competition.open?(user) + is_teacher = user.is_teacher? raise Error, '本竞赛的参赛者限定为:学生' if is_teacher && competition.teacher_enroll_forbidden? raise Error, '本竞赛的参赛者限定为:教师' if !is_teacher && competition.member_enroll_forbidden? diff --git a/app/services/competitions/join_team_service.rb b/app/services/competitions/join_team_service.rb index df889abe2..f22382150 100644 --- a/app/services/competitions/join_team_service.rb +++ b/app/services/competitions/join_team_service.rb @@ -13,6 +13,8 @@ class Competitions::JoinTeamService < ApplicationService invite_code = params[:invite_code].to_s.strip raise Error, '战队邀请码不能为空' if invite_code.blank? + raise Error, '本竞赛只面向部分学校/单位开放,你暂时没有参赛资格' unless competition.open?(user) + is_teacher = user.is_teacher? raise Error, '本竞赛的参赛者限定为:学生' if is_teacher && competition.teacher_enroll_forbidden? raise Error, '本竞赛的参赛者限定为:教师' if !is_teacher && competition.member_enroll_forbidden? @@ -22,7 +24,7 @@ class Competitions::JoinTeamService < ApplicationService raise Error, '您已加入该战队' if team.team_members.exists?(user_id: user.id) enrolled = competition.team_members.exists?(user_id: user.id) - if enrolled && (is_teacher && competition.teacher_multiple_limited?) || (!is_teacher && competition.member_multiple_limited?) + if enrolled && ((is_teacher && competition.teacher_multiple_limited?) || (!is_teacher && competition.member_multiple_limited?)) raise Error, '您已加入其它战队' end @@ -30,6 +32,6 @@ class Competitions::JoinTeamService < ApplicationService raise Error, '该战队队员人数已满' if !is_teacher && team.members.count == competition.member_staff.maximum role = is_teacher ? 3 : 2 - team.team_members.create!(competition_id: competition.id, user_id: user, role: role, is_teacher: is_teacher) + team.team_members.create!(competition_id: competition.id, user_id: user.id, role: role, is_teacher: is_teacher) end end \ No newline at end of file diff --git a/app/views/admins/competition_settings/index.html.erb b/app/views/admins/competition_settings/index.html.erb index 7133b7254..392d539ab 100644 --- a/app/views/admins/competition_settings/index.html.erb +++ b/app/views/admins/competition_settings/index.html.erb @@ -35,8 +35,8 @@ 起止时间
- <%= text_field_tag :start_time, @competition.start_time&.strftime('%Y-%m-%d'), autocomplete: 'off', class: 'form-control start-date mx-0 mr-2', placeholder: '竞赛开始时间' %> - <%= text_field_tag :end_time, @competition.end_time&.strftime('%Y-%m-%d'), autocomplete: 'off', class: 'form-control end-date mx-0', placeholder: '竞赛截止时间' %> + <%= text_field_tag :start_time, @competition.start_time&.strftime('%Y-%m-%d %H:%M'), autocomplete: 'off', class: 'form-control start-date mx-0 mr-2', placeholder: '竞赛开始时间' %> + <%= text_field_tag :end_time, @competition.end_time&.strftime('%Y-%m-%d %H:%M'), autocomplete: 'off', class: 'form-control end-date mx-0', placeholder: '竞赛截止时间' %>
@@ -93,12 +93,23 @@ -
+
主办方
-
+
+ <% sponsor_data = @competition.sponsor_schools.map { |s| [s.school.name, s.school.id] } %> + <%= select_tag :sponsor_schools, options_for_select(sponsor_data, @competition.sponsor_schools.map(&:school_id)), class: 'form-control sponsor-select', multiple: true %> +
+
+
+
+ 开放范围 +
+
+ <% region_data = @competition.region_schools.map { |s| [s.school.name, s.school.id] } %> + <%= select_tag :region_schools, options_for_select(region_data, @competition.region_schools.map(&:school_id)), class: 'form-control allow-school-select', multiple: true %>
@@ -151,134 +162,335 @@ 导航设置
-
- <% @competition.competition_modules.each do |com_module| %> - <% case com_module.module_type %> + <%= form_tag(nav_setting_admins_competition_competition_settings_path(@competition), method: :post, class: 'nav-setting-form flex-1', remote: true) do %> +
+ <% @competition.competition_modules.each do |com_module| %> + <% case com_module.module_type %> <% when 'home' %> -
-
+
+
+
+ +
+
+ <%= text_field_tag('navbar[][name]', com_module.name, id: nil, class: 'form-control', placeholder: '首页') %> + +
+
+ <%= text_field_tag('navbar[][position]', com_module.position, id: nil, class: 'form-control', placeholder: '位置') %> +
+
+
+ <% when 'enroll' %> +
-
- <%= text_field_tag('navbar[][name]', com_module.name, id: nil, class: 'form-control', placeholder: '首页') %> +
+ + 报名
-
- <%= text_field_tag('navbar[][position]', com_module.position, id: nil, class: 'form-control', placeholder: '位置') %> +
+
+
  
+
+ 报名截止时间 +
+
+ <%= text_field_tag :enroll_end_time, @competition.enroll_end_time&.strftime('%Y-%m-%d %H:%M'), autocomplete: 'off', class: 'form-control enroll_end_time', placeholder: '报名截止时间' %> +
+
+
+
  
+
+ 报名要求 +
+
+ <%= javascript_void_link '+', class: 'btn btn-primary waves-effect waves-light btn-xs setBtn_s addRequireBtn' %>
-
- <% end %> - <% end %> -
-
- -
-
- 报名 -
-
-
-
  
-
- 报名截止时间 -
-
-
-
-
  
-
- 报名要求 -
-
- -
-
+
-
-
-
  
-
- -
- ~ -
- -
- -
- -
-
- -
-
- -
-
+ <% when 'inform', 'chart', 'resource' %> +
+
+ +
+
+ + + <%= com_module.name %> +
+
+ <%= text_field_tag('navbar[][position]', com_module.position, id: nil, class: 'form-control', placeholder: '位置') %> +
+ <% if com_module.module_type == "resource" %> +
+ <%= text_field_tag('navbar[][url]', com_module.url, id: nil, class: 'form-control', placeholder: '请输入资料下载地址') %> +
+ <%= javascript_void_link '+', class: 'mt-1 btn btn-primary waves-effect waves-light btn-xs setBtn_s add_linkBtn' %> + <% end %> +
+ <% else %> +
+
+ +
+
+ + <%= text_field_tag('navbar[][name]', com_module.name, id: nil, class: 'form-control', placeholder: '请输入模块名称') %> +
+
+ <%= text_field_tag('navbar[][position]', com_module.position, id: nil, class: 'form-control', placeholder: '位置') %> +
+
+ <%= text_field_tag('navbar[][url]', com_module.url, id: nil, class: 'form-control', placeholder: '请输入资料下载地址') %> +
+ <%= javascript_void_link '+', class: 'mt-1 btn btn-primary waves-effect waves-light btn-xs setBtn_s add_linkBtn' %> + <%= javascript_void_link '×', class: 'mt-1 btn btn-icon waves-effect btn-default waves-light setBtn_s ml10 del_linkBtn' %> +
+ <% end %> + <% end %> -
+ + + + + + + + + +
-
-
- -
-
排行榜
-
-
-
-
+
-
-
资料下载
-
-
- -
-
-
-
- +
<%= javascript_void_link '保存', class: 'btn btn-primary submit-btn' %>
-
获奖证书
+ <% end %> +
+
-
-
-
-
<%= javascript_void_link '保存', class: 'btn btn-primary submit-btn' %>
-
+<% if @competition.mode == 1 %> +
+
+ 排行榜设置 + + 新增tab + + 实训ID填写示例:实训地址为https://www.educoder.net/shixuns/u5plmgka/challenges,则填写“u5plmgka”
-
-
+
+
+ <% if @competition.competition_stages.count > 0 %> + <% @competition.competition_stages.includes(competition_stage_sections: :competition_entries).each_with_index do |stage, index| %> + <%= form_tag(admins_competition_competition_stage_path(competition_id: @competition.id, id: stage.id), method: :put, class: 'stage-update-form flex-1', remote: true) do %> +
+
+ tab标题 +
+ +
+ 总排行榜占比: +
+ +
% +
+ 新增子阶段 + <% if stage.max_end_time > Time.now %> + <%= agree_link '发送短信提醒', send_message_admins_competition_competition_stage_path(@competition, stage, element: ".send-message-#{stage.id}"), + class: 'btn btn-outline-primary ml20', 'data-confirm': '确认执行发送短信操作?' %> + <% end %> + <% if stage.max_end_time < Time.now %> + <%= agree_link '计算成绩', calculate_stage_score_admins_competition_competition_stage_path(@competition, stage, element: ".calculate-score-#{stage.id}"), + class: 'btn btn-outline-primary ml20', 'data-confirm': '确认执行计算成绩操作?' %> + <% end %> +
+ <%= delete_link '删除', admins_competition_competition_stage_path(competition_id: @competition.id, id: stage.id), class: 'btn btn-default delete-stage ml20' %> + 保存 +
+ +
+ <% stage.competition_stage_sections.each_with_index do |section, j| %> +
+ 第<%= j + 1 %>阶段 +
+
+ 有效时间: +
+ <%= text_field_tag 'stage[][start_time]', section.start_time&.strftime('%Y-%m-%d %H:%M'), autocomplete: 'off', class: 'section-start-time form-control', placeholder: '有效开始时间' %> +
+ ~ +
+ <%= text_field_tag 'stage[][end_time]', section.end_time&.strftime('%Y-%m-%d %H:%M'), autocomplete: 'off', class: 'section-end-time form-control', placeholder: '有效结束时间' %> +
+ 任务完成要求: +
+ +
+ / +
+ +
+ (总任务) + 成绩来源: +
+ +
+
+
+ <% section.competition_entries.each_with_index do |entry, z| %> +
+ 任务<%= z+1 %> +
+ +
+
+ <% end %> +
+
+ + 删除 + +
+ <% end %> +
+
+
+ <% end %> + <% end %> + <% else %> + <%= form_tag(admins_competition_competition_stages_path(competition_id: @competition.id), method: :post, class: 'stage-update-form new-stage-form flex-1', remote: true) do %> +
+
+ tab标题 +
+ +
+ 总排行榜占比: +
+ +
% + + 删除 + 保存 +
+
+
+ 第1阶段 +
+
+ 有效时间: +
+ <%= text_field_tag 'stage[][start_time]', '', autocomplete: 'off', class: 'section-start-time form-control', placeholder: '有效开始时间' %> +
+ ~ +
+ <%= text_field_tag 'stage[][end_time]', '', autocomplete: 'off', class: 'section-end-time form-control', placeholder: '有效结束时间' %> +
+ 任务完成要求: +
+ +
+ / +
+ +
+ (总任务) + 成绩来源: +
+ +
+
+
+
+ 任务1 +
+ +
+
+
+ 任务2 +
+ +
+
+
+ 任务3 +
+ +
+
+
+
+ + 删除 + +
+
+
+ <% end %> + <% end %> +
+
+
+
+<% end %> \ No newline at end of file diff --git a/app/views/admins/competition_stages/destroy.js.erb b/app/views/admins/competition_stages/destroy.js.erb new file mode 100644 index 000000000..cdc8c3f7d --- /dev/null +++ b/app/views/admins/competition_stages/destroy.js.erb @@ -0,0 +1 @@ +window.location.reload(); \ No newline at end of file diff --git a/app/views/admins/users/index.json.jbuilder b/app/views/admins/users/index.json.jbuilder index 5591474a4..5b1860928 100644 --- a/app/views/admins/users/index.json.jbuilder +++ b/app/views/admins/users/index.json.jbuilder @@ -1,6 +1,6 @@ json.count @users.total_count json.users do json.array! @users.each do |user| - json.extract! user, :id, :login, :real_name, :identity, :school_name + json.extract! user, :id, :login, :real_name, :identity, :school_name, :hidden_phone end end \ No newline at end of file diff --git a/app/views/admins/users/shared/_user_list.html.erb b/app/views/admins/users/shared/_user_list.html.erb index 36b5d0f6e..698579b6f 100644 --- a/app/views/admins/users/shared/_user_list.html.erb +++ b/app/views/admins/users/shared/_user_list.html.erb @@ -5,11 +5,12 @@
邮件地址 手机号码 单位角色 <%= sort_tag('创建于', name: 'created_on', path: admins_users_path) %> <%= sort_tag('最后登录', name: 'last_login_on', path: admins_users_path) %> <%= sort_tag('经验值', name: 'experience', path: admins_users_path) %> <%= sort_tag('金币', name: 'grade', path: admins_users_path) %>操作操作
<%= overflow_hidden_span display_text(user.mail), width: 150 %> <%= overflow_hidden_span display_text(user.phone), width: 100 %> <%= overflow_hidden_span display_text(user.school_name), width: 150 %><%= user.identity %> <%= display_text(user.created_on&.strftime('%Y-%m-%d %H:%M')) %> <%= display_text(user.last_login_on&.strftime('%Y-%m-%d %H:%M')) %> <%= user.experience.to_i %>