mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-09-06 05:04:35 +08:00
Edit and new renderers for DateTime columns
This commit is contained in:
parent
7c71159303
commit
2a63854123
10 changed files with 265 additions and 15 deletions
|
@ -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 = `
|
||||||
|
<input type="hidden"
|
||||||
|
form="${formId}"
|
||||||
|
name="repository_cells[${columnId}]"
|
||||||
|
value="${value}" />`;
|
||||||
|
|
||||||
|
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 `
|
||||||
|
<input class="form-control editing calendar-input"
|
||||||
|
type="datetime"
|
||||||
|
data-form-id="${formId}"
|
||||||
|
data-column-id="${columnId}"
|
||||||
|
value='${value}'/>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function timeInputField(formId, columnId, value) {
|
||||||
|
return `
|
||||||
|
<input class="form-control editing"
|
||||||
|
type="text"
|
||||||
|
data-mask-type="time"
|
||||||
|
data-form-id="${formId}"
|
||||||
|
data-column-id="${columnId}"
|
||||||
|
value='${value}'
|
||||||
|
placeholder="HH:mm"/>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function initDateEditMode(formId, columnId, $cell, date, datetime) {
|
||||||
|
let inputFields = `
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="cell-timestamp-container" data-current-date="${datetime}" data-datetime-type="date"></div>
|
||||||
|
${dateInputField(formId, columnId, date)}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
$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 = `
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="cell-timestamp-container" data-current-date="${datetime}" data-datetime-type="time"></div>
|
||||||
|
${timeInputField(formId, columnId, time)}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
$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 = `
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="cell-timestamp-container" data-current-date="${datetime}" data-datetime-type="datetime"></div>
|
||||||
|
${dateInputField(formId, columnId, date)}
|
||||||
|
${timeInputField(formId, columnId, time)}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
$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,
|
||||||
|
};
|
||||||
|
}());
|
|
@ -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) {
|
$.fn.dataTable.render.editRowName = function(formId, cell) {
|
||||||
let $cell = $(cell.node());
|
let $cell = $(cell.node());
|
||||||
|
@ -89,15 +89,31 @@ $.fn.dataTable.render.editRepositoryStatusValue = function(formId, columnId, cel
|
||||||
};
|
};
|
||||||
|
|
||||||
$.fn.dataTable.render.editRepositoryDateTimeValue = function(formId, columnId, cell) {
|
$.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) {
|
$.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) {
|
$.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) {
|
$.fn.dataTable.render.editRepositoryDateTimeRangeValue = function(formId, columnId, cell) {
|
||||||
|
|
|
@ -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) {
|
$.fn.dataTable.render.newRowName = function(formId, $cell) {
|
||||||
$cell.html(`
|
$cell.html(`
|
||||||
|
@ -85,3 +85,19 @@ $.fn.dataTable.render.newRepositoryNumberValue = function(formId, columnId, $cel
|
||||||
|
|
||||||
SmartAnnotation.init($cell.find('input'));
|
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 '';
|
||||||
|
};
|
||||||
|
|
|
@ -55,7 +55,7 @@ $.fn.dataTable.render.defaultRepositoryDateValue = function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
$.fn.dataTable.render.RepositoryDateValue = function(data) {
|
$.fn.dataTable.render.RepositoryDateValue = function(data) {
|
||||||
return data.value;
|
return `<span data-datetime="${data.value.datetime}" data-date="${data.value.formatted}">${data.value.formatted}</span>`;
|
||||||
};
|
};
|
||||||
|
|
||||||
$.fn.dataTable.render.defaultRepositoryDateTimeValue = function() {
|
$.fn.dataTable.render.defaultRepositoryDateTimeValue = function() {
|
||||||
|
@ -63,7 +63,9 @@ $.fn.dataTable.render.defaultRepositoryDateTimeValue = function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
$.fn.dataTable.render.RepositoryDateTimeValue = function(data) {
|
$.fn.dataTable.render.RepositoryDateTimeValue = function(data) {
|
||||||
return data.value;
|
return `<span data-time="${data.value.time_formatted}"
|
||||||
|
data-datetime="${data.value.datetime}"
|
||||||
|
data-date="${data.value.date_formatted}">${data.value.formatted}</span>`;
|
||||||
};
|
};
|
||||||
|
|
||||||
$.fn.dataTable.render.defaultRepositoryTimeValue = function() {
|
$.fn.dataTable.render.defaultRepositoryTimeValue = function() {
|
||||||
|
@ -71,7 +73,8 @@ $.fn.dataTable.render.defaultRepositoryTimeValue = function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
$.fn.dataTable.render.RepositoryTimeValue = function(data) {
|
$.fn.dataTable.render.RepositoryTimeValue = function(data) {
|
||||||
return data.value;
|
return `<span data-time="${data.value.formatted}"
|
||||||
|
data-datetime="${data.value.datetime}">${data.value.formatted}</span>`;
|
||||||
};
|
};
|
||||||
|
|
||||||
$.fn.dataTable.render.defaultRepositoryTimeRangeValue = function() {
|
$.fn.dataTable.render.defaultRepositoryTimeRangeValue = function() {
|
||||||
|
@ -79,7 +82,7 @@ $.fn.dataTable.render.defaultRepositoryTimeRangeValue = function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
$.fn.dataTable.render.RepositoryTimeRangeValue = function(data) {
|
$.fn.dataTable.render.RepositoryTimeRangeValue = function(data) {
|
||||||
return data.value;
|
return `<span data-datetime="${data.value.datetime}">${data.value.formatted}</span>`;
|
||||||
};
|
};
|
||||||
|
|
||||||
$.fn.dataTable.render.defaultRepositoryDateTimeRangeValue = function() {
|
$.fn.dataTable.render.defaultRepositoryDateTimeRangeValue = function() {
|
||||||
|
|
|
@ -37,3 +37,7 @@ $.fn.dataTable.render.RepositoryChecklistValueValidator = function() {
|
||||||
$.fn.dataTable.render.RepositoryNumberValueValidator = function() {
|
$.fn.dataTable.render.RepositoryNumberValueValidator = function() {
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$.fn.dataTable.render.RepositoryDateTimeValueValidator = function() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ class RepositoryCell < ApplicationRecord
|
||||||
belongs_to :repository_date_value,
|
belongs_to :repository_date_value,
|
||||||
(lambda do
|
(lambda do
|
||||||
includes(:repository_cell)
|
includes(:repository_cell)
|
||||||
.where(repository_cells: { value_type: 'RepositoryDateValue' })
|
.where(repository_cells: { value_type: 'RepositoryDateTimeValueBase' })
|
||||||
end),
|
end),
|
||||||
optional: true, foreign_key: :value_id, inverse_of: :repository_cell
|
optional: true, foreign_key: :value_id, inverse_of: :repository_cell
|
||||||
belongs_to :repository_list_value,
|
belongs_to :repository_list_value,
|
||||||
|
@ -56,14 +56,14 @@ class RepositoryCell < ApplicationRecord
|
||||||
belongs_to :repository_date_time_value,
|
belongs_to :repository_date_time_value,
|
||||||
(lambda do
|
(lambda do
|
||||||
includes(:repository_cell)
|
includes(:repository_cell)
|
||||||
.where(repository_cells: { value_type: 'RepositoryDateTimeValue' })
|
.where(repository_cells: { value_type: 'RepositoryDateTimeValueBase' })
|
||||||
end),
|
end),
|
||||||
optional: true, foreign_key: :value_id, inverse_of: :repository_cell
|
optional: true, foreign_key: :value_id, inverse_of: :repository_cell
|
||||||
|
|
||||||
belongs_to :repository_time_value,
|
belongs_to :repository_time_value,
|
||||||
(lambda do
|
(lambda do
|
||||||
includes(:repository_cell)
|
includes(:repository_cell)
|
||||||
.where(repository_cells: { value_type: 'RepositoryTimeValue' })
|
.where(repository_cells: { value_type: 'RepositoryDateTimeValueBase' })
|
||||||
end),
|
end),
|
||||||
optional: true, foreign_key: :value_id, inverse_of: :repository_cell
|
optional: true, foreign_key: :value_id, inverse_of: :repository_cell
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,12 @@
|
||||||
module RepositoryDatatable
|
module RepositoryDatatable
|
||||||
class RepositoryDateTimeValueSerializer < RepositoryBaseValueSerializer
|
class RepositoryDateTimeValueSerializer < RepositoryBaseValueSerializer
|
||||||
def value
|
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
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,7 +3,10 @@
|
||||||
module RepositoryDatatable
|
module RepositoryDatatable
|
||||||
class RepositoryDateValueSerializer < RepositoryBaseValueSerializer
|
class RepositoryDateValueSerializer < RepositoryBaseValueSerializer
|
||||||
def value
|
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
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,7 +3,10 @@
|
||||||
module RepositoryDatatable
|
module RepositoryDatatable
|
||||||
class RepositoryTimeValueSerializer < RepositoryBaseValueSerializer
|
class RepositoryTimeValueSerializer < RepositoryBaseValueSerializer
|
||||||
def value
|
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
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -170,3 +170,17 @@
|
||||||
<%= javascript_include_tag "repositories/show" %>
|
<%= javascript_include_tag "repositories/show" %>
|
||||||
<%= javascript_include_tag "repositories/index" %>
|
<%= javascript_include_tag "repositories/index" %>
|
||||||
<%= javascript_pack_tag 'custom/inputmask' %>
|
<%= javascript_pack_tag 'custom/inputmask' %>
|
||||||
|
|
||||||
|
<script type="text/javascript" charset="utf-8">
|
||||||
|
<%
|
||||||
|
js_format = I18n.backend.date_format.dup
|
||||||
|
js_format.gsub!(/%-d/, 'D')
|
||||||
|
js_format.gsub!(/%d/, 'DD')
|
||||||
|
js_format.gsub!(/%-m/, 'M')
|
||||||
|
js_format.gsub!(/%m/, 'MM')
|
||||||
|
js_format.gsub!(/%b/, 'MMM')
|
||||||
|
js_format.gsub!(/%B/, 'MMMM')
|
||||||
|
js_format.gsub!('%Y', 'YYYY')
|
||||||
|
%>
|
||||||
|
const formatJS = "<%= js_format %>"
|
||||||
|
</script>
|
||||||
|
|
Loading…
Add table
Reference in a new issue