diff --git a/app/assets/javascripts/repositories/renderers/columns/date_time_helper.js b/app/assets/javascripts/repositories/renderers/columns/date_time_helper.js new file mode 100644 index 000000000..7d5742eb0 --- /dev/null +++ b/app/assets/javascripts/repositories/renderers/columns/date_time_helper.js @@ -0,0 +1,186 @@ +/* global Inputmask formatJS */ +/* eslint-disable no-unused-vars */ + +var DateTimeHelper = (function() { + + function isValidTimeStr(timeStr) { + return /^([0-9]|0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]$/.test(timeStr); + } + + function isValidDate(date) { + return (Object.prototype.toString.call(date) === '[object Date]') && !isNaN(date.getTime()); + } + + function addLeadingZero(value) { + return ('0' + value).slice(-2); + } + + function recalcTimestamp(date, timeStr) { + if (!isValidTimeStr(timeStr)) { + date.setHours(0); + date.setMinutes(0); + return date; + } + let hours = timeStr.split(':')[0]; + let mins = timeStr.split(':')[1]; + date.setHours(hours); + date.setMinutes(mins); + return date; + } + + function stringDateTimeFormat(date, format) { + let y = date.getFullYear(); + let m = addLeadingZero(date.getMonth() + 1); + let d = addLeadingZero(date.getDate()); + let hours = addLeadingZero(date.getHours()); + let mins = addLeadingZero(date.getMinutes()); + + if (format === 'dateonly') { + return `${y}/${m}/${d}`; + } + return `${y}/${m}/${d} ${hours}:${mins}`; + } + + function insertHiddenField($input, date, timeStr, format) { + let formId = $input.data('form-id'); + let columnId = $input.data('column-id'); + let hiddenFieldContainer = $input.parent().find('.cell-timestamp-container'); + let hasTime = isValidTimeStr(timeStr); + let hasDate = isValidDate(date); + let value; + let hiddenField; + + if (!hasDate) { // Date needs to be presence + value = ''; + } else if (format === 'time' && !hasTime) { // Delete time value + value = ''; + } else if (format === 'datetime' && !hasTime) { // Delete date time value + value = ''; + } else { + // create date time format + value = stringDateTimeFormat(recalcTimestamp(date, timeStr), 'full'); + } + + hiddenField = ` + `; + + hiddenFieldContainer.html(hiddenField); + } + + function initChangeEvents($cell) { + $cell.find('input[data-mask-type=time]').on('change', function() { + let timeStr = $(this).val(); + let $container = $(this).parent().find('.cell-timestamp-container'); + let dateStr = $container.data('current-date'); + let columnType = $container.data('datetime-type'); + if (columnType === 'time' && !isValidDate(dateStr)) { + // new time without value for date + dateStr = stringDateTimeFormat(new Date(), 'dateonly'); + } + + insertHiddenField($(this), new Date(dateStr), timeStr, columnType); + }); + + $cell.find('.calendar-input').on('dp.change', function(e) { + let date = e.date._d; + let timeStr = $(this).parent().find('input[data-mask-type=time]').val(); + let $container = $(this).parent().find('.cell-timestamp-container'); + + if (date !== undefined) { + $container.data('current-date', stringDateTimeFormat(date, 'dateonly')); + } else { + $container.data('current-date', ''); + } + insertHiddenField($(this), date, timeStr, $container.data('datetime-type')); + }); + } + + function dateInputField(formId, columnId, value) { + return ` + + `; + } + + function timeInputField(formId, columnId, value) { + return ` + + `; + } + + function initDateEditMode(formId, columnId, $cell, date, datetime) { + let inputFields = ` +
+
+ ${dateInputField(formId, columnId, date)} +
+ `; + + $cell.html(inputFields); + + $cell.find('.calendar-input').datetimepicker({ ignoreReadonly: true, locale: 'en', format: formatJS }); + initChangeEvents($cell); + } + + function initTimeEditMode(formId, columnId, $cell, time, datetime) { + let inputFields = ` +
+
+ ${timeInputField(formId, columnId, time)} +
+ `; + + $cell.html(inputFields); + + Inputmask('datetime', { + inputFormat: 'HH:MM', + placeholder: 'HH:mm', + clearIncomplete: true, + showMaskOnHover: true, + hourFormat: 24 + }).mask($cell.find('input[data-mask-type="time"]')); + + initChangeEvents($cell); + } + + function initDateTimeEditMode(formId, columnId, $cell, date, time, datetime) { + let inputFields = ` +
+
+ ${dateInputField(formId, columnId, date)} + ${timeInputField(formId, columnId, time)} +
+ `; + + $cell.html(inputFields); + + Inputmask('datetime', { + inputFormat: 'HH:MM', + placeholder: 'HH:mm', + clearIncomplete: true, + showMaskOnHover: true, + hourFormat: 24 + }).mask($cell.find('input[data-mask-type="time"]')); + + $cell.find('.calendar-input').datetimepicker({ ignoreReadonly: true, locale: 'en', format: formatJS }); + initChangeEvents($cell); + } + + return { + initDateEditMode: initDateEditMode, + initTimeEditMode: initTimeEditMode, + initDateTimeEditMode: initDateTimeEditMode, + }; +}()); diff --git a/app/assets/javascripts/repositories/renderers/edit_renderers.js b/app/assets/javascripts/repositories/renderers/edit_renderers.js index 88a69fbb3..cb939fd3c 100644 --- a/app/assets/javascripts/repositories/renderers/edit_renderers.js +++ b/app/assets/javascripts/repositories/renderers/edit_renderers.js @@ -1,4 +1,4 @@ -/* global ListColumnHelper ChecklistColumnHelper Status SmartAnnotation I18n GLOBAL_CONSTANTS */ +/* global ListColumnHelper ChecklistColumnHelper Status SmartAnnotation I18n GLOBAL_CONSTANTS DateTimeHelper*/ $.fn.dataTable.render.editRowName = function(formId, cell) { let $cell = $(cell.node()); @@ -89,15 +89,31 @@ $.fn.dataTable.render.editRepositoryStatusValue = function(formId, columnId, cel }; $.fn.dataTable.render.editRepositoryDateTimeValue = function(formId, columnId, cell) { - return ''; + let $cell = $(cell.node()); + let $span = $cell.find('span').first(); + let date = $span.data('date'); + let time = $span.data('time'); + let datetime = $span.data('datetime'); + + DateTimeHelper.initDateTimeEditMode(formId, columnId, $cell, date, time, datetime); }; $.fn.dataTable.render.editRepositoryDateValue = function(formId, columnId, cell) { - return ''; + let $cell = $(cell.node()); + let $span = $cell.find('span').first(); + let date = $span.data('date'); + let datetime = $span.data('datetime'); + + DateTimeHelper.initDateEditMode(formId, columnId, $cell, date, datetime); }; $.fn.dataTable.render.editRepositoryTimeValue = function(formId, columnId, cell) { - return ''; + let $cell = $(cell.node()); + let $span = $cell.find('span').first(); + let time = $span.data('time'); + let datetime = $span.data('datetime'); + + DateTimeHelper.initTimeEditMode(formId, columnId, $cell, time, datetime); }; $.fn.dataTable.render.editRepositoryDateTimeRangeValue = function(formId, columnId, cell) { diff --git a/app/assets/javascripts/repositories/renderers/new_renderers.js b/app/assets/javascripts/repositories/renderers/new_renderers.js index 9439b0aad..f707debd9 100644 --- a/app/assets/javascripts/repositories/renderers/new_renderers.js +++ b/app/assets/javascripts/repositories/renderers/new_renderers.js @@ -1,4 +1,4 @@ -/* global ListColumnHelper ChecklistColumnHelper Status SmartAnnotation I18n GLOBAL_CONSTANTS */ +/* global ListColumnHelper ChecklistColumnHelper Status SmartAnnotation I18n GLOBAL_CONSTANTS DateTimeHelper formatJS */ $.fn.dataTable.render.newRowName = function(formId, $cell) { $cell.html(` @@ -85,3 +85,19 @@ $.fn.dataTable.render.newRepositoryNumberValue = function(formId, columnId, $cel SmartAnnotation.init($cell.find('input')); }; + +$.fn.dataTable.render.newRepositoryDateTimeValue = function(formId, columnId, $cell) { + DateTimeHelper.initDateTimeEditMode(formId, columnId, $cell, '', '', ''); +}; + +$.fn.dataTable.render.newRepositoryTimeValue = function(formId, columnId, $cell) { + DateTimeHelper.initTimeEditMode(formId, columnId, $cell, '', ''); +}; + +$.fn.dataTable.render.newRepositoryDateValue = function(formId, columnId, $cell) { + DateTimeHelper.initDateEditMode(formId, columnId, $cell, '', ''); +}; + +$.fn.dataTable.render.newRepositoryCheckboxValue = function(formId, columnId) { + return ''; +}; diff --git a/app/assets/javascripts/repositories/renderers/view_renderers.js b/app/assets/javascripts/repositories/renderers/view_renderers.js index acb1bf6b6..62c1718da 100644 --- a/app/assets/javascripts/repositories/renderers/view_renderers.js +++ b/app/assets/javascripts/repositories/renderers/view_renderers.js @@ -55,7 +55,7 @@ $.fn.dataTable.render.defaultRepositoryDateValue = function() { }; $.fn.dataTable.render.RepositoryDateValue = function(data) { - return data.value; + return `${data.value.formatted}`; }; $.fn.dataTable.render.defaultRepositoryDateTimeValue = function() { @@ -63,7 +63,9 @@ $.fn.dataTable.render.defaultRepositoryDateTimeValue = function() { }; $.fn.dataTable.render.RepositoryDateTimeValue = function(data) { - return data.value; + return `${data.value.formatted}`; }; $.fn.dataTable.render.defaultRepositoryTimeValue = function() { @@ -71,7 +73,8 @@ $.fn.dataTable.render.defaultRepositoryTimeValue = function() { }; $.fn.dataTable.render.RepositoryTimeValue = function(data) { - return data.value; + return `${data.value.formatted}`; }; $.fn.dataTable.render.defaultRepositoryTimeRangeValue = function() { @@ -79,7 +82,7 @@ $.fn.dataTable.render.defaultRepositoryTimeRangeValue = function() { }; $.fn.dataTable.render.RepositoryTimeRangeValue = function(data) { - return data.value; + return `${data.value.formatted}`; }; $.fn.dataTable.render.defaultRepositoryDateTimeRangeValue = function() { diff --git a/app/assets/javascripts/repositories/validators/base_validator.js b/app/assets/javascripts/repositories/validators/base_validator.js index 26a0942a6..35f887a7f 100644 --- a/app/assets/javascripts/repositories/validators/base_validator.js +++ b/app/assets/javascripts/repositories/validators/base_validator.js @@ -37,3 +37,7 @@ $.fn.dataTable.render.RepositoryChecklistValueValidator = function() { $.fn.dataTable.render.RepositoryNumberValueValidator = function() { return true; }; + +$.fn.dataTable.render.RepositoryDateTimeValueValidator = function() { + return true; +} diff --git a/app/models/repository_cell.rb b/app/models/repository_cell.rb index 194acbc6a..88d391216 100644 --- a/app/models/repository_cell.rb +++ b/app/models/repository_cell.rb @@ -23,7 +23,7 @@ class RepositoryCell < ApplicationRecord belongs_to :repository_date_value, (lambda do includes(:repository_cell) - .where(repository_cells: { value_type: 'RepositoryDateValue' }) + .where(repository_cells: { value_type: 'RepositoryDateTimeValueBase' }) end), optional: true, foreign_key: :value_id, inverse_of: :repository_cell belongs_to :repository_list_value, @@ -56,14 +56,14 @@ class RepositoryCell < ApplicationRecord belongs_to :repository_date_time_value, (lambda do includes(:repository_cell) - .where(repository_cells: { value_type: 'RepositoryDateTimeValue' }) + .where(repository_cells: { value_type: 'RepositoryDateTimeValueBase' }) end), optional: true, foreign_key: :value_id, inverse_of: :repository_cell belongs_to :repository_time_value, (lambda do includes(:repository_cell) - .where(repository_cells: { value_type: 'RepositoryTimeValue' }) + .where(repository_cells: { value_type: 'RepositoryDateTimeValueBase' }) end), optional: true, foreign_key: :value_id, inverse_of: :repository_cell diff --git a/app/serializers/repository_datatable/repository_date_time_value_serializer.rb b/app/serializers/repository_datatable/repository_date_time_value_serializer.rb index a58f84cf3..73998746d 100644 --- a/app/serializers/repository_datatable/repository_date_time_value_serializer.rb +++ b/app/serializers/repository_datatable/repository_date_time_value_serializer.rb @@ -3,7 +3,12 @@ module RepositoryDatatable class RepositoryDateTimeValueSerializer < RepositoryBaseValueSerializer def value - I18n.l(object.data, format: :full_with_comma) + { + formatted: I18n.l(object.data, format: :full_with_comma), + date_formatted: I18n.l(object.data, format: :full_date), + time_formatted: I18n.l(object.data, format: :time), + datetime: object.data.strftime('%Y/%m/%d %H:%M') + } end end end diff --git a/app/serializers/repository_datatable/repository_date_value_serializer.rb b/app/serializers/repository_datatable/repository_date_value_serializer.rb index a70ca09ec..8ae7618bc 100644 --- a/app/serializers/repository_datatable/repository_date_value_serializer.rb +++ b/app/serializers/repository_datatable/repository_date_value_serializer.rb @@ -3,7 +3,10 @@ module RepositoryDatatable class RepositoryDateValueSerializer < RepositoryBaseValueSerializer def value - I18n.l(object.data, format: :full_date) + { + formatted: I18n.l(object.data, format: :full_date), + datetime: object.data.strftime('%Y/%m/%d %H:%M') + } end end end diff --git a/app/serializers/repository_datatable/repository_time_value_serializer.rb b/app/serializers/repository_datatable/repository_time_value_serializer.rb index 28edaf57e..ea059feec 100644 --- a/app/serializers/repository_datatable/repository_time_value_serializer.rb +++ b/app/serializers/repository_datatable/repository_time_value_serializer.rb @@ -3,7 +3,10 @@ module RepositoryDatatable class RepositoryTimeValueSerializer < RepositoryBaseValueSerializer def value - I18n.l(object.data, format: :time) + { + formatted: I18n.l(object.data, format: :time), + datetime: object.data.strftime('%Y/%m/%d %H:%M') + } end end end diff --git a/app/views/repositories/show.html.erb b/app/views/repositories/show.html.erb index 22ec7869d..4eccd8ebf 100644 --- a/app/views/repositories/show.html.erb +++ b/app/views/repositories/show.html.erb @@ -170,3 +170,17 @@ <%= javascript_include_tag "repositories/show" %> <%= javascript_include_tag "repositories/index" %> <%= javascript_pack_tag 'custom/inputmask' %> + +