diff --git a/Gemfile b/Gemfile index b4aca7f58..3d4171794 100644 --- a/Gemfile +++ b/Gemfile @@ -41,7 +41,7 @@ gem 'rack-attack' # JS datetime library, requirement of datetime picker gem 'momentjs-rails', '~> 2.17.1' # JS datetime picker -gem 'bootstrap3-datetimepicker-rails', '~> 4.15.35' +gem 'bootstrap3-datetimepicker-rails', '~> 4.17' # Select elements for Bootstrap gem 'bootstrap-select-rails', '~> 1.12.4' gem 'uglifier', '>= 1.3.0' diff --git a/Gemfile.lock b/Gemfile.lock index e369124f7..ef655a677 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -156,7 +156,7 @@ GEM autoprefixer-rails (>= 5.2.1) sassc (>= 2.0.0) bootstrap-select-rails (1.12.4) - bootstrap3-datetimepicker-rails (4.15.35) + bootstrap3-datetimepicker-rails (4.17.47) momentjs-rails (>= 2.8.1) bootstrap_form (2.7.0) builder (3.2.3) @@ -606,7 +606,7 @@ DEPENDENCIES bootsnap bootstrap-sass (~> 3.4.1) bootstrap-select-rails (~> 1.12.4) - bootstrap3-datetimepicker-rails (~> 4.15.35) + bootstrap3-datetimepicker-rails (~> 4.17) bootstrap_form (~> 2.7.0) bullet byebug diff --git a/app/assets/javascripts/my_modules.js b/app/assets/javascripts/my_modules.js index b9ab0a806..2616c2480 100644 --- a/app/assets/javascripts/my_modules.js +++ b/app/assets/javascripts/my_modules.js @@ -1,28 +1,24 @@ /* global I18n dropdownSelector */ /* eslint-disable no-use-before-define */ +function updateDueDate() { + let updateUrl = $('.due-date-container').data('update-url'); + let val = $('#calendar-due-date').val(); + $.ajax({ + url: updateUrl, + type: 'PATCH', + dataType: 'json', + data: { my_module: { due_date: val } }, + success: function(result) { + $('#due-date-label-container').html(result.due_date_label); + } + }); +} + // Bind ajax for editing due dates function initDueDatePicker() { - function updateDueDate(val) { - var updateUrl = $('.due-date-container').data('update-url'); - $.ajax({ - url: updateUrl, - type: 'PATCH', - dataType: 'json', - data: { my_module: { due_date: val } }, - success: function(result) { - $('.due-date-container').html($(result.module_header_due_date_label)); - initDueDatePicker(); - } - }); - } - $('#calendar-due-date').on('dp.change', function() { - updateDueDate($('#calendar-due-date').val()); - }); - - $('.flex-block.date-block .clear-date').off('click').on('click', function() { - updateDueDate(null); + updateDueDate(); }); } @@ -194,7 +190,7 @@ function applyTaskCompletedCallBack() { button.find('.btn') .removeClass('btn-default').addClass('btn-primary'); } - $('.due-date-container').html(data.module_header_due_date_label); + $('.due-date-container').html(data.module_header_due_date); initDueDatePicker(); $('.task-state-label').html(data.module_state_label); button.find('button').replaceWith(data.new_btn); diff --git a/app/assets/javascripts/projects/canvas.js.erb b/app/assets/javascripts/projects/canvas.js.erb index 902d4b7a3..a9ed88fda 100644 --- a/app/assets/javascripts/projects/canvas.js.erb +++ b/app/assets/javascripts/projects/canvas.js.erb @@ -750,7 +750,7 @@ function bindEditDueDateAjax() { editDueDateModalBody.find("form") .on("ajax:success", function(ev2, data2, status2) { // Update module's due date - dueDateLink.html(data2.due_date_label); + dueDateLink.html(data2.card_due_date_label); // Update module's classes if needed moduleEl diff --git a/app/assets/javascripts/protocols/steps.js.erb b/app/assets/javascripts/protocols/steps.js.erb index 119f84164..13f92463b 100644 --- a/app/assets/javascripts/protocols/steps.js.erb +++ b/app/assets/javascripts/protocols/steps.js.erb @@ -41,7 +41,7 @@ task_button.attr('data-action', 'uncomplete-task'); task_button.find('.btn') .removeClass('btn-toggle').addClass('btn-default'); - $('.task-due-date').html(data.module_header_due_date_label); + $('.task-due-date').html(data.module_header_due_date); $('.task-state-label').html(data.module_state_label); task_button .find('button') diff --git a/app/assets/javascripts/sitewide/date_time_picker.js b/app/assets/javascripts/sitewide/date_time_picker.js new file mode 100644 index 000000000..ce64dddb3 --- /dev/null +++ b/app/assets/javascripts/sitewide/date_time_picker.js @@ -0,0 +1,24 @@ +(function() { + 'use strict'; + + $(document).on('click', '[data-toggle="date-time-picker"]', function(ev) { + ev.preventDefault(); + ev.stopPropagation(); + + let dt = $(this); + + if (dt.data('DateTimePicker')) { + dt.data('DateTimePicker').destroy(); + } + + dt.datetimepicker({ ignoreReadonly: true }); + dt.data('DateTimePicker').show(); + }); + + $(document).on('click', '[data-toggle="clear-date-time-picker"]', function() { + let dt = $(`#${$(this).data('target')}`); + if (!dt.data('DateTimePicker')) dt.datetimepicker({ useCurrent: false }); + dt.data('DateTimePicker').clear(); + dt.val(''); + }); +}()); diff --git a/app/assets/stylesheets/my_modules/protocols/index.scss b/app/assets/stylesheets/my_modules/protocols/index.scss index d5a76bf33..ad8fd4e25 100644 --- a/app/assets/stylesheets/my_modules/protocols/index.scss +++ b/app/assets/stylesheets/my_modules/protocols/index.scss @@ -63,15 +63,15 @@ padding: 0 3px; position: relative; - &.alert-green { + .alert-green { color: $brand-success; } - &.alert-yellow { + .alert-yellow { color: $brand-warning; } - &.alert-red { + .alert-red { color: $brand-danger; } diff --git a/app/controllers/my_modules_controller.rb b/app/controllers/my_modules_controller.rb index 9398f53b2..70adfbabe 100644 --- a/app/controllers/my_modules_controller.rb +++ b/app/controllers/my_modules_controller.rb @@ -145,10 +145,8 @@ class MyModulesController < ApplicationController def update update_params = my_module_params if update_params[:due_date].present? - update_params[:due_date] = Time.strptime( - update_params[:due_date].delete('-'), - I18n.backend.date_format.dup.delete('-') - ) + update_params[:due_date] = + Time.zone.strptime(update_params[:due_date], I18n.backend.date_format.dup.gsub(/%-/, '%') + ' %H:%M') end @my_module.assign_attributes(update_params) @my_module.last_modified_by = current_user @@ -211,15 +209,19 @@ class MyModulesController < ApplicationController render json: { status: :ok, due_date_label: render_to_string( - partial: "my_modules/due_date_label.html.erb", + partial: 'my_modules/due_date_label.html.erb', locals: { my_module: @my_module } ), - module_header_due_date_label: render_to_string( - partial: "my_modules/module_header_due_date_label.html.erb", + card_due_date_label: render_to_string( + partial: 'my_modules/card_due_date_label.html.erb', + locals: { my_module: @my_module } + ), + module_header_due_date: render_to_string( + partial: 'my_modules/module_header_due_date.html.erb', locals: { my_module: @my_module } ), description_label: render_to_string( - partial: "my_modules/description_label.html.erb", + partial: 'my_modules/description_label.html.erb', locals: { my_module: @my_module } ), alerts: alerts @@ -577,8 +579,8 @@ class MyModulesController < ApplicationController render json: { new_btn: render_to_string(partial: new_btn_partial), completed: completed, - module_header_due_date_label: render_to_string( - partial: 'my_modules/module_header_due_date_label.html.erb', + module_header_due_date: render_to_string( + partial: 'my_modules/module_header_due_date.html.erb', locals: { my_module: @my_module } ), module_state_label: render_to_string( @@ -605,8 +607,8 @@ class MyModulesController < ApplicationController format.json do render json: { task_button_title: t('my_modules.buttons.uncomplete'), - module_header_due_date_label: render_to_string( - partial: 'my_modules/module_header_due_date_label.html.erb', + module_header_due_date: render_to_string( + partial: 'my_modules/module_header_due_date.html.erb', locals: { my_module: @my_module } ), module_state_label: render_to_string( diff --git a/app/helpers/bootstrap_form_helper.rb b/app/helpers/bootstrap_form_helper.rb index c7479f58f..c09ed7ac3 100644 --- a/app/helpers/bootstrap_form_helper.rb +++ b/app/helpers/bootstrap_form_helper.rb @@ -22,9 +22,10 @@ module BootstrapFormHelper def datetime_picker(name, options = {}) id = "#{@object_name}_#{name.to_s}" input_name = "#{@object_name}[#{name.to_s}]" - timestamp = @object[name] ? "#{@object[name].to_i}000" : "" + date_format = I18n.backend.date_format.dup + value = options[:value] ? options[:value].strftime(date_format + ' %H:%M') : '' js_locale = I18n.locale.to_s - js_format = I18n.backend.date_format.dup + js_format = date_format js_format.gsub!(/%-d/, 'D') js_format.gsub!(/%d/, 'DD') js_format.gsub!(/%-m/, 'M') @@ -32,36 +33,27 @@ module BootstrapFormHelper js_format.gsub!(/%b/, 'MMM') js_format.gsub!(/%B/, 'MMMM') js_format.gsub!('%Y', 'YYYY') + js_format << ' HH:mm' if options[:time] == true - label = name.to_s.humanize - if options[:label] then - label = options[:label] + label = options[:label] || name.to_s.humanize + + style = options[:style] ? "style='#{options[:style]}'" : '' + + res = "