Merge branch 'develop' into features/inventory-item-card-edit

This commit is contained in:
Oleksii Kriuchykhin 2023-11-16 11:12:50 +01:00
commit cc8b993430
101 changed files with 1351 additions and 1378 deletions

View file

@ -731,6 +731,7 @@ DEPENDENCIES
fastimage
figaro
graphviz
grover
httparty (~> 0.21.0)
i18n-js (~> 3.6)
image_processing

View file

@ -37,6 +37,7 @@
// Add and show modal
$(experimentWrapper).append($.parseHTML(result.html));
$(newMyModuleModal).modal('show');
window.initDateTimePickerComponent(`#date-time-picker-my-module`);
$(newMyModuleModal).find("input[type='text']").focus();
// Remove modal when it gets closed

View file

@ -141,43 +141,32 @@ var ExperimnetTable = {
let dateText = $(element).closest('.date-text');
let clearDate = $(element).closest('.datetime-container').find('.clear-date');
$(element).on('dp.change', function() {
$.ajax({
url: dueDateContainer.data('update-url'),
type: 'PATCH',
dataType: 'json',
data: { my_module: { due_date: $(element).val() } },
success: function(result) {
dueDateContainer.find('#dueDateLabelContainer').html(result.table_due_date_label.html);
dateText.data('due-status', result.table_due_date_label.due_status);
$(`#calendarDueDateContainer${row.id}`).parent().on('dp:ready', () => {
$(element).data('dateTimePicker').onChange = () => {
$.ajax({
url: dueDateContainer.data('update-url'),
type: 'PATCH',
dataType: 'json',
data: { my_module: { due_date: $(element).val() } },
success: function(result) {
dueDateContainer.find('#dueDateLabelContainer').html(result.table_due_date_label.html);
dateText.data('due-status', result.table_due_date_label.due_status);
if ($(result.table_due_date_label.html).data('due-date')) {
clearDate.addClass('open');
if ($(result.table_due_date_label.html).data('due-date')) {
clearDate.removeClass('tw-hidden');
} else {
clearDate.addClass('tw-hidden');
}
}
}
});
}
clearDate.on('click', () => {
$(element).data('dateTimePicker').clearDate();
});
});
$(element).on('dp.hide', function() {
dateText.attr('data-original-title', dateText.data('due-status'));
clearDate.removeClass('open');
});
$(element).on('dp.show', function() {
var datePicker = $('.bootstrap-datetimepicker-widget.dropdown-menu')[0];
// show full datepicker menu for due date
if (datePicker.getBoundingClientRect().bottom > window.innerHeight) {
datePicker.scrollIntoView(false);
} else if (datePicker.getBoundingClientRect().top < 0) {
datePicker.scrollIntoView();
}
dateText.attr('data-original-title', '').tooltip('hide');
if (dueDateContainer.find('.due-date-label').data('due-date')) {
clearDate.addClass('open');
}
});
window.initDateTimePickerComponent(`#calendarDueDateContainer${row.id}`);
});
},
initMyModuleActions: function() {
@ -505,9 +494,9 @@ var ExperimnetTable = {
}
},
selectDate: function($field) {
var datePicker = $field.data('DateTimePicker');
if (datePicker && datePicker.date()) {
return datePicker.date()._d.toUTCString();
var datePicker = $field.data('dateTimePicker');
if (datePicker && datePicker.date) {
return datePicker.date.toString();
}
return null;
},
@ -748,9 +737,7 @@ ExperimnetTable.filters.push({
},
active: (value) => { return value; },
clearFilter: ($container) => {
if ($('.due-date-filter .from-date', $container).data('DateTimePicker')) {
$('.due-date-filter .from-date', $container).data('DateTimePicker').clear();
}
$('.due-date-filter .from-date', $container).data('dateTimePicker')?.clearDate();
}
});
@ -763,9 +750,7 @@ ExperimnetTable.filters.push({
},
active: (value) => { return value; },
clearFilter: ($container) => {
if ($('.due-date-filter .to-date', $container).data('DateTimePicker')) {
$('.due-date-filter .to-date', $container).data('DateTimePicker').clear();
}
$('.due-date-filter .to-date', $container).data('dateTimePicker')?.clearDate();
}
});
@ -778,9 +763,7 @@ ExperimnetTable.filters.push({
},
active: (value) => { return value; },
clearFilter: ($container) => {
if ($('.archived-on-filter .from-date', $container).data('DateTimePicker')) {
$('.archived-on-filter .from-date', $container).data('DateTimePicker').clear();
}
$('.archived-on-filter .from-date', $container).data('dateTimePicker')?.clearDate();
}
});
@ -793,9 +776,7 @@ ExperimnetTable.filters.push({
},
active: (value) => { return value; },
clearFilter: ($container) => {
if ($('.archived-on-filter .to-date', $container).data('DateTimePicker')) {
$('.archived-on-filter .to-date', $container).data('DateTimePicker').clear();
}
$('.archived-on-filter .to-date', $container).data('dateTimePicker')?.clearDate();
}
});

View file

@ -26,13 +26,13 @@ var globalActivities = (function() {
};
function GlobalActivitiesFiltersGetDates() {
var fromDate = $('#calendar-from-date').data('DateTimePicker').date();
var toDate = $('#calendar-to-date').data('DateTimePicker').date();
var fromDate = $('#calendar-from-date').data('dateTimePicker').$refs.vueDateTime.datetime;
var toDate = $('#calendar-to-date').data('dateTimePicker').$refs.vueDateTime.datetime;
if (fromDate) {
fromDate = fromDate._d.date_to_string();
fromDate = fromDate.date_to_string();
}
if (toDate) {
toDate = toDate._d.date_to_string();
toDate = toDate.date_to_string();
}
return { from: fromDate, to: toDate };
}
@ -108,8 +108,8 @@ var globalActivities = (function() {
$('.date-selector .date.clear').click(() => {
updateRunning = true;
$('#calendar-from-date').data('DateTimePicker').clear();
$('#calendar-to-date').data('DateTimePicker').clear();
$('#calendar-from-date').data('dateTimePicker').clearDate();
$('#calendar-to-date').data('dateTimePicker').clearDate();
$('.ga-side .date-selector.filter-block')[0].dataset.periodSelect = '';
resetHotButtonsBackgroundColor();
updateRunning = false;
@ -205,8 +205,8 @@ var globalActivities = (function() {
var selectorsCount = $(projectFilter).length === 1 ? clearSelectors.length - 1 : 1;
updateRunning = true;
$('#calendar-from-date').data('DateTimePicker').clear();
$('#calendar-to-date').data('DateTimePicker').clear();
$('#calendar-from-date').data('dateTimePicker').clearDate();
$('#calendar-to-date').data('dateTimePicker').clearDate();
$('.ga-side .date-selector.filter-block')[0].dataset.periodSelect = '';
@ -331,27 +331,18 @@ var globalActivities = (function() {
});
});
$('#calendar-to-date').on('dp.change', function(e) {
var dateContainer = $('.ga-side .date-selector.filter-block');
if (!updateRunning) {
$('#calendar-from-date').data('DateTimePicker').minDate(e.date);
dateContainer[0].dataset.periodSelect = $('#calendar-to-date').val() + ' - ' + $('#calendar-from-date').val();
GlobalActivitiesUpdateTopPaneTags();
reloadActivities();
toggleClearButtons();
resetHotButtonsBackgroundColor();
}
});
$('#calendar-from-date').on('dp.change', function(e) {
var dateContainer = $('.ga-side .date-selector.filter-block');
if (!updateRunning) {
$('#calendar-to-date').data('DateTimePicker').maxDate(e.date);
dateContainer[0].dataset.periodSelect = $('#calendar-to-date').val() + ' - ' + $('#calendar-from-date').val();
GlobalActivitiesUpdateTopPaneTags();
reloadActivities();
toggleClearButtons();
resetHotButtonsBackgroundColor();
$('.datetime-picker-container').on('dp:ready', function() {
$(this).find('.calendar-input').data('dateTimePicker').onChange = () => {
let dateContainer = $('.ga-side .date-selector.filter-block');
if (!updateRunning) {
let toDate = $('#calendar-to-date').data('dateTimePicker').$refs.vueDateTime.datetime;
let fromDate = $('#calendar-from-date').data('dateTimePicker').$refs.vueDateTime.datetime;
dateContainer[0].dataset.periodSelect = (toDate ? toDate?.date_to_string() : '') + ' - ' + (fromDate ? fromDate.date_to_string() : '');
GlobalActivitiesUpdateTopPaneTags();
reloadActivities();
toggleClearButtons();
resetHotButtonsBackgroundColor();
}
}
});
@ -362,8 +353,8 @@ var globalActivities = (function() {
$('.date-selector .hot-button').click(function() {
var selectPeriod = this.dataset.period;
var dateContainer = $('.ga-side .date-selector.filter-block');
var fromDate = $('#calendar-from-date').data('DateTimePicker');
var toDate = $('#calendar-to-date').data('DateTimePicker');
var fromDate = $('#calendar-from-date').data('dateTimePicker');
var toDate = $('#calendar-to-date').data('dateTimePicker');
var today = new Date();
var yesterday = new Date(new Date().setDate(today.getDate() - 1));
var weekDay = today.getDay();
@ -375,26 +366,24 @@ var globalActivities = (function() {
var lastMonthEnd = new Date(new Date().setDate(firstDay.getDate() - 1));
var lastMonthStart = new Date(lastMonthEnd.getFullYear(), lastMonthEnd.getMonth(), 1);
updateRunning = true;
fromDate.minDate(new Date(1900, 1, 1));
toDate.maxDate(new Date(3000, 1, 1));
if (selectPeriod === 'today') {
fromDate.date(today);
toDate.date(today);
fromDate.$refs.vueDateTime.datetime = today;
toDate.$refs.vueDateTime.datetime = today;
} else if (selectPeriod === 'yesterday') {
fromDate.date(yesterday);
toDate.date(yesterday);
fromDate.$refs.vueDateTime.datetime = yesterday;
toDate.$refs.vueDateTime.datetime = yesterday;
} else if (selectPeriod === 'this_week') {
fromDate.date(today);
toDate.date(monday);
fromDate.$refs.vueDateTime.datetime = today;
toDate.$refs.vueDateTime.datetime = monday;
} else if (selectPeriod === 'last_week') {
fromDate.date(lastWeekEnd);
toDate.date(lastWeekStart);
fromDate.$refs.vueDateTime.datetime = lastWeekEnd;
toDate.$refs.vueDateTime.datetime = lastWeekStart;
} else if (selectPeriod === 'this_month') {
fromDate.date(today);
toDate.date(firstDay);
fromDate.$refs.vueDateTime.datetime = today;
toDate.$refs.vueDateTime.datetime = firstDay;
} else if (selectPeriod === 'last_month') {
fromDate.date(lastMonthEnd);
toDate.date(lastMonthStart);
fromDate.$refs.vueDateTime.datetime = lastMonthEnd;
toDate.$refs.vueDateTime.datetime = lastMonthStart;
}
updateRunning = false;
dateContainer[0].dataset.periodSelect = this.innerHTML;

View file

@ -56,9 +56,12 @@
// Bind ajax for editing due dates
function initStartDatePicker() {
$('#calendarStartDate').on('dp.change', function() {
updateStartDate();
$('.datetime-picker-container#start-date').on('dp:ready', () => {
$('#calendarStartDate').data('dateTimePicker').onChange = () => {
updateStartDate();
};
});
window.initDateTimePickerComponent('#calendarStartDateContainer');
}
function updateDueDate() {
@ -82,9 +85,12 @@
// Bind ajax for editing due dates
function initDueDatePicker() {
$('#calendarDueDate').on('dp.change', function() {
updateDueDate();
$('.datetime-picker-container#due-date').on('dp:ready', () => {
$('#calendarDueDate').data('dateTimePicker').onChange = () => {
updateDueDate();
};
});
window.initDateTimePickerComponent('#calendarDueDateContainer');
}
function initTagsSelector() {

View file

@ -763,6 +763,8 @@ function bindEditDueDateAjax() {
editDueDateModalBody.html(data.html);
editDueDateModalTitle.text(data.title);
window.initDateTimePickerComponent('#date-time-picker');
// Add listener to form inside modal
editDueDateModalBody.find("form")
.on("ajax:success", function(ev2, data2, status2) {

View file

@ -13,7 +13,6 @@
var ProjectsIndex = (function() {
var projectsWrapper = '#projectsWrapper';
var toolbarWrapper = '#toolbarWrapper';
var cardsWrapper = '#cardsWrapper';
var editProjectModal = '#edit-modal';
var moveToModal = '#move-to-modal';
@ -448,22 +447,13 @@ var ProjectsIndex = (function() {
data: { ...requestParams, ...{ page: 1 } },
success: function(data) {
$(projectsWrapper).find('.projects-title').html(data.title_html);
$(toolbarWrapper).html(data.toolbar_html);
initProjectsViewModeSwitch();
initCardData(viewContainer, data);
selectedProjects.length = 0;
selectedProjectFolders.length = 0;
updateProjectsToolbar();
initProjectsFilters();
initSorting();
// set current sort item
if (projectsCurrentSort) {
$('#sortMenuDropdown a').removeClass('selected');
$(`#sortMenuDropdown a[data-sort="${projectsCurrentSort}"]`).addClass('selected');
}
if (data.filtered) {
$(projectsWrapper).find('.project-list-end-placeholder').remove();
@ -546,11 +536,9 @@ var ProjectsIndex = (function() {
}
function selectDate($field) {
var datePicker = $field.data('DateTimePicker');
if (datePicker && datePicker.date()) {
return datePicker.date()._d.toUTCString();
} else if ($field.val()) {
return moment($field.val(), $field.data('dateFormat'))._d.toUTCString();
let datePicker = $field.data('dateTimePicker');
if (datePicker && datePicker.date) {
return datePicker.date.toString();
}
return null;
}
@ -576,32 +564,6 @@ var ProjectsIndex = (function() {
projectsViewSearch = $textFilter.val();
}
function saveCurrentFilters() {
getFilterValues();
currentFilters = {
createdOnFromFilter: $createdOnFromFilter.val(),
createdOnToFilter: $createdOnToFilter.val(),
membersFilter: membersFilter,
lookInsideFolders: lookInsideFolders,
archivedOnFromFilter: $archivedOnFromFilter.val(),
archivedOnToFilter: $archivedOnToFilter.val(),
projectsViewSearch: projectsViewSearch
};
}
function loadCurrentFilters() {
if (!currentFilters) return;
$createdOnFromFilter.val(currentFilters.createdOnFromFilter);
$createdOnToFilter.val(currentFilters.createdOnToFilter);
$foldersCB.attr('checked', !!currentFilters.lookInsideFolders);
dropdownSelector.setData($('.members-filter'), currentFilters.membersFilter);
$archivedOnFromFilter.val(currentFilters.archivedOnFromFilter);
$archivedOnToFilter.val(currentFilters.archivedOnToFilter);
$textFilter.val(currentFilters.projectsViewSearch);
}
function filtersEnabled() {
getFilterValues();
@ -640,7 +602,6 @@ var ProjectsIndex = (function() {
});
$filterDropdown.on('filter:apply', function() {
saveCurrentFilters();
appliedFiltersMark();
loadCardsView();
});
@ -650,12 +611,11 @@ var ProjectsIndex = (function() {
currentFilters = null;
dropdownSelector.clearData($membersFilter);
$createdOnFromFilter.val('');
$createdOnToFilter.val('');
$createdOnFromFilter.val('');
$createdOnToFilter.val('');
$archivedOnFromFilter.val('');
$archivedOnToFilter.val('');
$createdOnFromFilter.data('dateTimePicker').clearDate();
$createdOnToFilter.data('dateTimePicker').clearDate();
$archivedOnFromFilter.data('dateTimePicker').clearDate();
$archivedOnToFilter.data('dateTimePicker').clearDate();
$foldersCB.prop('checked', false);
$textFilter.val('');
});
@ -668,7 +628,6 @@ var ProjectsIndex = (function() {
$('#folderSearchInfo').hide();
});
loadCurrentFilters();
appliedFiltersMark();
}
@ -710,10 +669,12 @@ var ProjectsIndex = (function() {
initArchiveRestoreToolbarButtons();
initEditButton();
initMoveButton();
initProjectsViewModeSwitch();
initSelectAllCheckbox();
initArchiveRestoreButton();
loadCardsView();
initProjectsViewModeSwitch();
initProjectsFilters();
initSorting();
AsyncDropdown.init($(projectsWrapper));
$(projectsWrapper).on('click', '.folder-card-selector', function() {

View file

@ -132,9 +132,9 @@
}
function selectDate($field) {
var datePicker = $field.data('DateTimePicker');
if (datePicker && datePicker.date()) {
return datePicker.date()._d.toUTCString();
let datePicker = $field.data('dateTimePicker');
if (datePicker && datePicker.date) {
return datePicker.date.toString();
}
return null;
}
@ -186,12 +186,12 @@
// Clear filters
$filterDropdown.on('filter:clear', function() {
$(this).find('input').val('');
if ($startedOnFromFilter.data('DateTimePicker')) $startedOnFromFilter.data('DateTimePicker').clear();
if ($startedOnToFilter.data('DateTimePicker')) $startedOnToFilter.data('DateTimePicker').clear();
if ($modifiedOnFromFilter.data('DateTimePicker')) $modifiedOnFromFilter.data('DateTimePicker').clear();
if ($modifiedOnToFilter.data('DateTimePicker')) $modifiedOnToFilter.data('DateTimePicker').clear();
if ($archivedOnFromFilter.data('DateTimePicker')) $archivedOnFromFilter.data('DateTimePicker').clear();
if ($archivedOnToFilter.data('DateTimePicker')) $archivedOnToFilter.data('DateTimePicker').clear();
$startedOnFromFilter.data('dateTimePicker').clearDate();
$startedOnToFilter.data('dateTimePicker').clearDate();
$modifiedOnFromFilter.data('dateTimePicker').clearDate();
$modifiedOnToFilter.data('dateTimePicker').clearDate();
$archivedOnFromFilter.data('dateTimePicker').clearDate();
$archivedOnToFilter.data('dateTimePicker').clearDate();
});
}

View file

@ -47,9 +47,9 @@ var ProtocolsIndex = (function() {
}
function selectDate($field) {
var datePicker = $field.data('DateTimePicker');
if (datePicker && datePicker.date()) {
return datePicker.date()._d.toUTCString();
var datePicker = $field.data('dateTimePicker');
if (datePicker && datePicker.date) {
return datePicker.date.toString();
}
return null;
}
@ -129,12 +129,12 @@ var ProtocolsIndex = (function() {
dropdownSelector.clearData($accessByFilter);
$(this).find('input').val('');
if ($publishedOnFromFilter.data('DateTimePicker')) $publishedOnFromFilter.data('DateTimePicker').clear();
if ($publishedOnToFilter.data('DateTimePicker')) $publishedOnToFilter.data('DateTimePicker').clear();
if ($modifiedOnFromFilter.data('DateTimePicker')) $modifiedOnFromFilter.data('DateTimePicker').clear();
if ($modifiedOnToFilter.data('DateTimePicker')) $modifiedOnToFilter.data('DateTimePicker').clear();
if ($archivedOnFromFilter.data('DateTimePicker')) $archivedOnFromFilter.data('DateTimePicker').clear();
if ($archivedOnToFilter.data('DateTimePicker')) $archivedOnToFilter.data('DateTimePicker').clear();
$publishedOnFromFilter.data('dateTimePicker')?.clearDate();
$publishedOnToFilter.data('dateTimePicker')?.clearDate();
$modifiedOnFromFilter.data('dateTimePicker')?.clearDate();
$modifiedOnToFilter.data('dateTimePicker')?.clearDate();
$archivedOnFromFilter.data('dateTimePicker')?.clearDate();
$archivedOnToFilter.data('dateTimePicker')?.clearDate();
$hasDraft.prop('checked', false);
$textFilter.val('');
});

View file

@ -105,6 +105,7 @@
}],
fnInitComplete: function(e) {
initActionToolbar();
window.actionToolbarComponent.setReloadCallback(() =>
initRepositoriesDataTable('#repositoriesList', archived));
window.actionToolbarComponent.setBottomOffset(68);

View file

@ -2,316 +2,90 @@
/* 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 (date instanceof Date) && !isNaN(date.getTime());
}
function addLeadingZero(value) {
return ('0' + value).slice(-2);
}
function setDateTimePickerOpeningDirection(event) {
const element = $(event.target);
const dateTimePickerWidget = $('.bootstrap-datetimepicker-widget');
const windowHeight = element.closest('table').offset().top;
const inputTop = element.offset().top;
const pickerHeight = $('.bootstrap-datetimepicker-widget').outerHeight();
if (inputTop - windowHeight > pickerHeight) {
dateTimePickerWidget.addClass('top')
.removeClass('bottom')
.css({
top: 'auto',
bottom: '36px',
});
} else {
dateTimePickerWidget.addClass('bottom')
.removeClass('top')
.css({
top: '36px',
bottom: 'auto',
});
}
}
function recalcTimestamp(date, timeStr) {
if (!isValidTimeStr(timeStr)) {
date.setHours(0);
date.setMinutes(0);
return date;
}
date.setHours(timeStr.split(':')[0]);
date.setMinutes(timeStr.split(':')[1]);
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($container) {
let formId = $container.data('form-id');
let columnId = $container.data('column-id');
let dateStr = $container.find('input.date-part').data('selected-date');
let timeStr = $container.find('input.time-part').val();
let columnType = $container.data('type');
let date = new Date(dateStr);
let value = '';
let hiddenField;
if (isValidDate(date) && isValidTimeStr(timeStr)) {
value = stringDateTimeFormat(recalcTimestamp(date, timeStr), 'full');
}
hiddenField = `
<input class="repository-cell-value"
type="hidden"
form="${formId}"
name="repository_cells[${columnId}]"
value="${value}"
data-type="${columnType}"/>`;
$container.find('input.repository-cell-value').remove();
$container.prepend(hiddenField);
}
function insertRangeHiddenField($container) {
let formId = $container.data('form-id');
let columnId = $container.data('column-id');
let columnType = $container.data('type');
let $startContainer = $container.find('.start-time');
let $endContainer = $container.find('.end-time');
let startDate = new Date($startContainer.find('input.date-part').data('selected-date'));
let startTimeStr = $startContainer.find('input.time-part').val();
let endDate = new Date($endContainer.find('input.date-part').data('selected-date'));
let endTimeStr = $endContainer.find('input.time-part').val();
let hiddenField;
let value = '';
if (isValidDate(startDate)
&& isValidTimeStr(startTimeStr)
&& isValidDate(endDate)
&& isValidTimeStr(endTimeStr)) {
let start = stringDateTimeFormat(recalcTimestamp(startDate, startTimeStr), 'full');
let end = stringDateTimeFormat(recalcTimestamp(endDate, endTimeStr), 'full');
value = JSON.stringify({ start_time: start, end_time: end });
}
hiddenField = `
<input class="repository-cell-value"
type="hidden"
form="${formId}"
name="repository_cells[${columnId}]"
value='${value}'
data-type="${columnType}"/>`;
$container.find('input.repository-cell-value').remove();
$container.prepend(hiddenField);
}
function initChangeEvents($cell) {
$cell.find('input.time-part').on('change', function() {
let $input = $(this);
let $container = $input.closest('.datetime-container');
if ($container.hasClass('range-type')) {
insertRangeHiddenField($container);
} else {
insertHiddenField($container);
}
});
$cell.find('input.date-part').on('dp.change', function(e) {
let $input = $(this);
let date = e.date._d;
let $container = $input.closest('.datetime-container');
if (date !== undefined) {
$input.data('selected-date', stringDateTimeFormat(date, 'dateonly'));
} else {
$input.data('selected-date', '');
}
if ($container.hasClass('range-type')) {
insertRangeHiddenField($container);
} else {
insertHiddenField($container);
}
});
}
function dateInputField(value, dateDataValue) {
return `
<div class="sci-input-container date-container right-icon">
<input class="calendar-input date-part sci-input-field"
type="datetime"
placeholder="${formatJS}"
data-datetime-part="date"
data-selected-date="${dateDataValue}"
value='${value}'/>
<i class="sn-icon sn-icon-calendar"></i>
</div>
`;
}
function timeInputField(value) {
return `
<div class="sci-input-container time-container right-icon">
<input class="time-part sci-input-field"
type="text"
data-mask-type="time"
value='${value}'
placeholder="HH:mm"/>
<i class="sn-icon sn-icon-created"></i>
</div>
`;
}
function getDateOrDefault($span, mode) {
let dateStr = $span.data('date');
let date;
if (mode === 'timeonly') {
// Set default date if no data in span
date = new Date(dateStr);
if (isValidDate(date)) {
dateStr = stringDateTimeFormat(new Date(date), 'dateonly');
} else {
dateStr = stringDateTimeFormat(new Date(), 'dateonly');
}
}
return dateStr;
}
function getTimeOrDefault($span, mode) {
let timeStr = $span.data('time');
if ((mode === 'dateonly') && (!isValidTimeStr(timeStr))) {
timeStr = '00:00';
}
return timeStr;
}
function initCurrentTimeSelector($cell) {
$cell.find('.time-container .fa-clock').click(function() {
var inputField = $(this).prev();
var d = new Date();
var h = addLeadingZero(d.getHours());
var m = addLeadingZero(d.getMinutes());
inputField.val(h + ':' + m).change();
});
function placeholder(mode) {
if (mode === 'date') return formatJS;
if (mode === 'time') return 'HH:mm';
return `${formatJS} HH:mm`;
}
function initDateTimeEditMode(formId, columnId, $cell, mode, columnType) {
let $span = $cell.find('span').first();
let date = $span.data('date');
let dateDataValue = getDateOrDefault($span, mode);
let time = getTimeOrDefault($span, mode);
let datetime = $span.data('datetime');
let inputFields = `
<div class="form-group datetime-container ${mode}"
data-form-id="${formId}"
data-column-id="${columnId}"
const $span = $cell.find('span').first();
const dateTime = $span.data('datetime') || '';
const inputFields = `
<div class="datetime-container">
<div id="datetimePickerContainer${formId}${columnId}"
class="date-container ${mode} vue-date-time-picker-filter min-w-[160px]">
<input ref="input"
data-type="${columnType}"
data-current-datetime="${datetime}">
${dateInputField(date, dateDataValue)}
${timeInputField(time)}
</div>
`;
data-simple-format="true"
form="${formId}"
name="repository_cells[${columnId}]"
class="datetime" type="hidden"
data-default="${dateTime}"
v-model="date"
id="datetimePicker${formId}${columnId}" />
<date-time-picker class="w-full" @cleared="clearDate"
:teleport="false"
:clearable="true"
ref="vueDateTime" @change="updateDate" mode="${mode}"
placeholder="${placeholder(mode)}"></date-time-picker>
</div>
</div>
`;
$cell.html(inputFields);
initCurrentTimeSelector($cell);
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 })
.on('dp.show', (e) => {
setDateTimePickerOpeningDirection(e);
});
initChangeEvents($cell);
window.initDateTimePickerComponent(`#datetimePickerContainer${formId}${columnId}`);
}
function initDateTimeRangeEditMode(formId, columnId, $cell, mode, columnType) {
let $startSpan = $cell.find('span').first();
let startDate = $startSpan.data('date');
let startTime = getTimeOrDefault($startSpan, mode);
let startDatetime = getDateOrDefault($startSpan, mode);
let startDateDataValue = getDateOrDefault($startSpan, mode);
let $endSpan = $cell.find('span').last();
let endDate = $endSpan.data('date');
let endTime = getTimeOrDefault($endSpan, mode);
let endDatetime = getDateOrDefault($endSpan, mode);
let endDateDataValue = getDateOrDefault($endSpan, mode);
const $startSpan = $cell.find('span').first();
const startDateTime = $startSpan.data('datetime') || '';
const $endSpan = $cell.find('span').last();
const endDateTime = $endSpan.data('datetime') || '';
let inputFields = `
<div class="form-group datetime-container range-type ${mode}"
data-form-id="${formId}"
data-column-id="${columnId}"
data-type="${columnType}"
>
<div class="start-time ${mode}"
data-current-datetime="${startDatetime}">
${dateInputField(startDate, startDatetime)}
${timeInputField(startTime)}
</div>
<div class="separator"></div>
<div class="end-time ${mode}"
data-current-datetime="${endDatetime}">
${dateInputField(endDate, endDatetime)}
${timeInputField(endTime)}
</div>
</div>
`;
const inputFields = `
<div class="datetime-container range-type ${mode}">
<input type="hidden" form="${formId}" class="column-range" name="repository_cells[${columnId}]"
value='${JSON.stringify({ start_time: startDateTime, end_time: endDateTime })}'>
<div id="datetimeStartPickerComtainer${formId}${columnId}"
class="date-container ${mode} vue-date-time-picker-filter min-w-[160px]">
<input ref="input"
data-type="${columnType}"
data-simple-format="true"
form="${formId}"
class="datetime start" type="hidden"
data-default="${startDateTime}"
v-model="date"
id="datetimeStartPicker${formId}${columnId}" />
<date-time-picker class="w-full" @cleared="clearDate"
:teleport="false"
:clearable="true"
ref="vueDateTime" @change="updateDate"
mode="${mode}" placeholder="${placeholder(mode)}"></date-time-picker>
</div>
<div class="separator"></div>
<div id="datetimeEndPickerComtainer${formId}${columnId}"
class="date-container ${mode} vue-date-time-picker-filter min-w-[160px]">
<input ref="input"
data-type="${columnType}"
data-simple-format="true"
form="${formId}"
class="datetime end" type="hidden"
data-default="${endDateTime}"
v-model="date"
id="datetimeEndPicker${formId}${columnId}" />
<date-time-picker class="w-full" @cleared="clearDate"
:teleport="false"
:clearable="true"
ref="vueDateTime" @change="updateDate" mode="${mode}"
placeholder="${placeholder(mode)}"></date-time-picker>
</div>
</div>`;
$cell.html(inputFields);
initCurrentTimeSelector($cell);
Inputmask('datetime', {
inputFormat: 'HH:MM',
placeholder: 'HH:mm',
clearIncomplete: true,
showMaskOnHover: true,
hourFormat: 24
}).mask($cell.find('input[data-mask-type="time"]'));
let $cal1 = $cell.find('.calendar-input').first().datetimepicker({ ignoreReadonly: true, locale: 'en', format: formatJS });
let $cal2 = $cell.find('.calendar-input').last().datetimepicker({ ignoreReadonly: true, locale: 'en', format: formatJS });
$cal1.on('dp.change', function(e) {
$cal2.data('DateTimePicker').minDate(e.date);
}).on('dp.show', (e) => {
setDateTimePickerOpeningDirection(e);
});
$cal2.on('dp.change', function(e) {
$cal1.data('DateTimePicker').maxDate(e.date);
}).on('dp.show', (e) => {
setDateTimePickerOpeningDirection(e);
});
initChangeEvents($cell);
window.initDateTimePickerComponent(`#datetimeStartPickerComtainer${formId}${columnId}`);
window.initDateTimePickerComponent(`#datetimeEndPickerComtainer${formId}${columnId}`);
}
return {

View file

@ -75,37 +75,37 @@ $.fn.dataTable.render.editRepositoryStatusValue = function(formId, columnId, cel
$.fn.dataTable.render.editRepositoryDateTimeValue = function(formId, columnId, cell) {
let $cell = $(cell.node());
DateTimeHelper.initDateTimeEditMode(formId, columnId, $cell, '', 'RepositoryDateTimeValue');
DateTimeHelper.initDateTimeEditMode(formId, columnId, $cell, 'datetime', 'RepositoryDateTimeValue');
};
$.fn.dataTable.render.editRepositoryDateValue = function(formId, columnId, cell) {
let $cell = $(cell.node());
DateTimeHelper.initDateTimeEditMode(formId, columnId, $cell, 'dateonly', 'RepositoryDateValue');
DateTimeHelper.initDateTimeEditMode(formId, columnId, $cell, 'date', 'RepositoryDateValue');
};
$.fn.dataTable.render.editRepositoryTimeValue = function(formId, columnId, cell) {
let $cell = $(cell.node());
DateTimeHelper.initDateTimeEditMode(formId, columnId, $cell, 'timeonly', 'RepositoryTimeValue');
DateTimeHelper.initDateTimeEditMode(formId, columnId, $cell, 'time', 'RepositoryTimeValue');
};
$.fn.dataTable.render.editRepositoryDateTimeRangeValue = function(formId, columnId, cell) {
let $cell = $(cell.node());
DateTimeHelper.initDateTimeRangeEditMode(formId, columnId, $cell, '', 'RepositoryDateTimeRangeValue');
DateTimeHelper.initDateTimeRangeEditMode(formId, columnId, $cell, 'datetime', 'RepositoryDateTimeRangeValue');
};
$.fn.dataTable.render.editRepositoryDateRangeValue = function(formId, columnId, cell) {
let $cell = $(cell.node());
DateTimeHelper.initDateTimeRangeEditMode(formId, columnId, $cell, 'dateonly', 'RepositoryDateRangeValue');
DateTimeHelper.initDateTimeRangeEditMode(formId, columnId, $cell, 'date', 'RepositoryDateRangeValue');
};
$.fn.dataTable.render.editRepositoryTimeRangeValue = function(formId, columnId, cell) {
let $cell = $(cell.node());
DateTimeHelper.initDateTimeRangeEditMode(formId, columnId, $cell, 'timeonly', 'RepositoryTimeRangeValue');
DateTimeHelper.initDateTimeRangeEditMode(formId, columnId, $cell, 'time', 'RepositoryTimeRangeValue');
};
$.fn.dataTable.render.editRepositoryChecklistValue = function(formId, columnId, cell) {

View file

@ -78,27 +78,27 @@ $.fn.dataTable.render.newRepositoryNumberValue = function(formId, columnId, $cel
};
$.fn.dataTable.render.newRepositoryDateTimeValue = function(formId, columnId, $cell) {
DateTimeHelper.initDateTimeEditMode(formId, columnId, $cell, '', 'RepositoryDateTimeValue');
DateTimeHelper.initDateTimeEditMode(formId, columnId, $cell, 'datetime', 'RepositoryDateTimeValue');
};
$.fn.dataTable.render.newRepositoryTimeValue = function(formId, columnId, $cell) {
DateTimeHelper.initDateTimeEditMode(formId, columnId, $cell, 'timeonly', 'RepositoryTimeValue');
DateTimeHelper.initDateTimeEditMode(formId, columnId, $cell, 'time', 'RepositoryTimeValue');
};
$.fn.dataTable.render.newRepositoryDateValue = function(formId, columnId, $cell) {
DateTimeHelper.initDateTimeEditMode(formId, columnId, $cell, 'dateonly', 'RepositoryDateValue');
DateTimeHelper.initDateTimeEditMode(formId, columnId, $cell, 'date', 'RepositoryDateValue');
};
$.fn.dataTable.render.newRepositoryDateTimeRangeValue = function(formId, columnId, $cell) {
DateTimeHelper.initDateTimeRangeEditMode(formId, columnId, $cell, '', 'RepositoryDateTimeRangeValue');
DateTimeHelper.initDateTimeRangeEditMode(formId, columnId, $cell, 'datetime', 'RepositoryDateTimeRangeValue');
};
$.fn.dataTable.render.newRepositoryDateRangeValue = function(formId, columnId, $cell) {
DateTimeHelper.initDateTimeRangeEditMode(formId, columnId, $cell, 'dateonly', 'RepositoryDateRangeValue');
DateTimeHelper.initDateTimeRangeEditMode(formId, columnId, $cell, 'date', 'RepositoryDateRangeValue');
};
$.fn.dataTable.render.newRepositoryTimeRangeValue = function(formId, columnId, $cell) {
DateTimeHelper.initDateTimeRangeEditMode(formId, columnId, $cell, 'timeonly', 'RepositoryTimeRangeValue');
DateTimeHelper.initDateTimeRangeEditMode(formId, columnId, $cell, 'time', 'RepositoryTimeRangeValue');
};
$.fn.dataTable.render.newRepositoryStockValue = function() {

View file

@ -791,6 +791,7 @@ var RepositoryDatatable = (function(global) {
fnInitComplete: function() {
window.initActionToolbar();
window.actionToolbarComponent.setBottomOffset(68);
initHeaderTooltip();
disableCheckboxToggleOnCheckboxPreview();

View file

@ -76,18 +76,7 @@ $.fn.dataTable.render.RepositoryNumberValueValidator = function($input) {
};
$.fn.dataTable.render.RepositoryDateTimeValueValidator = function($input) {
let $container = $input.parents('.datetime-container');
let $date = $container.find('input.date-part');
let $time = $container.find('input.time-part');
if (($date.val() === '') === ($time.val() === '')) {
return true;
}
$container.find('.date-container')
.addClass('error')
.attr('data-error-text', I18n.t('repositories.table.date_time.errors.set_all_or_none'));
$container.find('.time-container').addClass('error');
return false;
return true;
};
$.fn.dataTable.render.RepositoryDateValueValidator = function() {
@ -99,11 +88,10 @@ $.fn.dataTable.render.RepositoryTimeValueValidator = function() {
};
$.fn.dataTable.render.RepositoryDateTimeRangeValueValidator = function($input) {
let $container = $input.parents('.datetime-container');
let $dateS = $container.find('.start-time input.date-part');
let $timeS = $container.find('.start-time input.time-part');
let $dateE = $container.find('.end-time input.date-part');
let $timeE = $container.find('.end-time input.time-part');
const $container = $input.parents('.datetime-container');
const $dateS = $container.find('.datetime.start');
const $dateE = $container.find('.datetime.end');
const $submitField = $container.find('.column-range');
let isValid = true;
let errorMessage;
let startTime;
@ -111,14 +99,12 @@ $.fn.dataTable.render.RepositoryDateTimeRangeValueValidator = function($input) {
let a = [];
if ($input.val()) {
startTime = new Date(JSON.parse($input.val()).start_time);
endTime = new Date(JSON.parse($input.val()).end_time);
startTime = new Date($dateS.val());
endTime = new Date($dateE.val());
}
a.push($dateS.val() === '');
a.push($timeS.val() === '');
a.push($dateE.val() === '');
a.push($timeE.val() === '');
if (a.filter((v, i, arr) => arr.indexOf(v) === i).length > 1) {
isValid = false;
@ -129,26 +115,35 @@ $.fn.dataTable.render.RepositoryDateTimeRangeValueValidator = function($input) {
}
if (isValid) {
const oldValue = $submitField.val();
let newValue;
if ($dateS.val() && $dateE.val()) {
newValue = JSON.stringify({ start_time: $dateS.val(), end_time: $dateE.val() });
}
if (oldValue !== newValue) {
$submitField.val(newValue);
}
return true;
}
$container.find('.date-container').addClass('error');
$container.find('.time-container').addClass('error');
$container.find('.date-container').first().attr('data-error-text', errorMessage);
return false;
};
$.fn.dataTable.render.RepositoryDateRangeValueValidator = function($input) {
let $container = $input.parents('.datetime-container');
let $dateS = $container.find('.start-time input.date-part');
let $dateE = $container.find('.end-time input.date-part');
const $container = $input.parents('.datetime-container');
const $dateS = $container.find('.datetime.start');
const $dateE = $container.find('.datetime.end');
const $submitField = $container.find('.column-range');
let isValid = true;
let errorMessage;
let endTime;
let startTime;
let endTime;
if ($input.val()) {
startTime = new Date(JSON.parse($input.val()).start_time);
endTime = new Date(JSON.parse($input.val()).end_time);
startTime = new Date($dateS.val());
endTime = new Date($dateE.val());
}
if (($dateS.val() === '') !== ($dateE.val() === '')) {
@ -160,6 +155,14 @@ $.fn.dataTable.render.RepositoryDateRangeValueValidator = function($input) {
}
if (isValid) {
const oldValue = $submitField.val();
let newValue;
if ($dateS.val() && $dateE.val()) {
newValue = JSON.stringify({ start_time: $dateS.val(), end_time: $dateE.val() });
}
if (oldValue !== newValue) {
$submitField.val(newValue);
}
return true;
}
@ -169,24 +172,40 @@ $.fn.dataTable.render.RepositoryDateRangeValueValidator = function($input) {
};
$.fn.dataTable.render.RepositoryTimeRangeValueValidator = function($input) {
let $container = $input.parents('.datetime-container');
let $timeS = $container.find('.start-time input.time-part');
let $timeE = $container.find('.end-time input.time-part');
const $container = $input.parents('.datetime-container');
const $dateS = $container.find('.datetime.start');
const $dateE = $container.find('.datetime.end');
const $submitField = $container.find('.column-range');
let isValid = true;
let errorMessage;
let startTime;
let endTime;
if (($timeS.val() === '') !== ($timeE.val() === '')) {
if ($input.val()) {
startTime = new Date($dateS.val());
endTime = new Date($dateE.val());
}
if (($dateS.val() === '') !== ($dateE.val() === '')) {
isValid = false;
errorMessage = I18n.t('repositories.table.date_time.errors.set_all_or_none');
} else if ($timeS.val() > $timeE.val()) {
} else if (endTime < startTime) {
isValid = false;
errorMessage = I18n.t('repositories.table.date_time.errors.not_valid_range');
}
if (isValid) {
const oldValue = $submitField.val();
let newValue;
if ($dateS.val() && $dateE.val()) {
newValue = JSON.stringify({ start_time: $dateS.val(), end_time: $dateE.val() });
}
if (oldValue !== newValue) {
$submitField.val(newValue);
}
return true;
}
$container.find('.time-container').addClass('error');
$container.find('.time-container').first().attr('data-error-text', errorMessage);
$container.find('.date-container').addClass('error');
$container.find('.date-container').first().attr('data-error-text', errorMessage);
return false;
};

View file

@ -54,6 +54,11 @@
$(document).on('mousedown', '[data-toggle="clear-date-time-picker"]', function() {
let dt = $(`#${$(this).data('target')}`);
if (dt.data('dateTimePicker')) {
dt.data('dateTimePicker').clearDate();
return;
}
if (!dt.data('DateTimePicker')) dt.datetimepicker({ useCurrent: false });
dt.data('DateTimePicker').clear();
dt.val('');

View file

@ -131,6 +131,14 @@ var filterDropdown = (function() {
});
}
function initDateTimePickerComponent() {
const dateTimePickers = document.querySelectorAll('.vue-date-time-picker-filter');
dateTimePickers.forEach((dateTimePicker) => {
$((`#${dateTimePicker.id}`)).removeClass('vue-date-time-picker-filter');
window.initDateTimePickerComponent(`#${dateTimePicker.id}`);
});
}
return {
init: function(filtersEnabledFunction) {
$filterContainer = $('.filter-container');
@ -138,6 +146,7 @@ var filterDropdown = (function() {
preventDropdownClose();
initApplyButton();
initCloseButton();
initDateTimePickerComponent();
initSearchField(filtersEnabledFunction);
this.toggleFilterMark($filterContainer, filtersEnabled)
return $filterContainer;

View file

@ -467,21 +467,17 @@
.clear-date {
cursor: pointer;
left: calc(100% - 16px);
position: absolute;
margin-left: auto;
opacity: 0;
text-align: center;
top: 0;
visibility: hidden;
width: 16px;
width: 24px;
}
&.open {
visibility: visible;
}
&:hover .clear-date {
opacity: 1;
}
.date-text {
display: block;
position: relative;
.alert-yellow {
color: $brand-warning;
margin-left: 4px;
@ -497,7 +493,7 @@
left: 0;
position: absolute;
top: 0;
width: calc(100% - 16px);
width: calc(100% - 24px);
.calendar-due-date {
opacity: 0;

View file

@ -248,6 +248,10 @@
top: 0;
width: 100%;
.dp__input_wrap {
opacity: 0;
}
#calendarDueDate {
opacity: 0;
}

View file

@ -1,4 +1,13 @@
.sci--layout-navigation-navigator {
.handle-mr {
display: block !important;
height: 100%;
opacity: 0;
right: -2px;
top: 0;
}
.menu-item:not(.active):hover {
background-color: var(--sn-super-light-grey);

View file

@ -494,7 +494,7 @@
}
.repository-edit-overlay--pagination {
bottom: 0;
bottom: .5rem;
height: 5em;
line-height: 5em;
padding: .5em;

View file

@ -349,7 +349,28 @@
}
.date-container {
width: 160px;
&.datetime {
width: 240px;
}
&.time {
width: 120px;
}
&.date {
width: 200px;
}
&.error {
&::after {
color: $brand-danger;
content: attr(data-error-text);
font-size: 12px;
margin-top: -4px;
position: absolute;
top: 100%;
}
}
}
.time-container {

View file

@ -1,5 +1,202 @@
// scss-lint:disable SelectorDepth NestingDepth
.dp--menu-wrapper {
font-weight: normal;
.dp__menu,
&.dp__menu {
border: 0;
box-shadow: 0px 4px 16px rgba(35, 31, 32, 0.15)
}
.dp__action_buttons {
flex: 1;
gap: .5rem;
}
.dp__active_date {
background-color: var(--sn-science-blue);
}
.dp__calendar_header_separator {
display: none;
}
.dp__month_year_wrap {
font-weight: bold;
}
.dp__month_year_row {
margin-bottom: .5rem;
}
.dp__menu_inner {
margin: 0 1rem;
padding: 1rem 0;
}
.dp__time_picker_overlay_container {
padding-bottom: .5rem;
}
.dp__button_bottom {
background-color: var(--sn-white);
margin-bottom: .5rem;
}
.dp--tp-wrap {
border-top: 1px solid var(--sn-light-grey);
padding: .5rem 1rem;
.dp__time_display {
margin: .5rem 0;
}
.dp__button_bottom {
margin-bottom: 0;
}
}
.dp__action_cancel {
color: var(--sn-blue);
}
.dp__action_button {
margin-inline-start: 0;
white-space: nowrap;
}
.dp__inner_nav {
border-radius: .25rem;
}
.dp__tp_inline_btn_bar {
height: 2px;
}
.dp__calendar_item {
display: flex;
justify-content: center;
}
.dp__btn:hover {
.dp__tp_inline_btn_bar {
background-color: var(--sn-science-blue);
}
}
.dp__overlay_container {
padding-bottom: .5rem;
}
.dp--arrow-btn-nav {
display: flex;
height: 40px;
padding: 0;
width: 40px;
.dp__inner_nav {
height: 40px;
padding: 0;
width: 40px;
}
}
}
.dp__input_wrap {
.dp__input_icon {
height: 1.5rem;
left: .5rem;
}
.dp__input {
height: 2.25rem;
line-height: unset;
}
}
.dp__main.only-time {
.dp--tp-wrap {
border-top: none;
}
.dp__overlay_container {
padding-bottom: 0;
}
}
.dp__theme_light {
--dp-background-color: var(--sn-white);
--dp-text-color: var(--sn-black);
--dp-hover-color: var(--sn-super-light-grey);
--dp-hover-text-color: #212121;
--dp-hover-icon-color: #959595;
--dp-primary-color: var(--sn-blue);
--dp-primary-disabled-color: var(--sn-super-light-blue);
--dp-primary-text-color: var(--sn-white);
--dp-secondary-color: var(--sn-grey);
--dp-border-color: var(--sn-light-grey);
--dp-menu-border-color: var(--sn-light-grey);
--dp-border-color-hover: var(--sn-light-grey);
--dp-disabled-color: var(--sn-super-light-grey);
--dp-scroll-bar-background: var(--sn-white);
--dp-scroll-bar-color: var(--sn-grey);
--dp-success-color: var(--sn-blue);
--dp-success-color-disabled: var(--sn-super-light-blue);
--dp-icon-color: var(--sn-black);
--dp-danger-color: var(--sn-delete-red);
--dp-marker-color: var(--sn-delete-red-disabled);
--dp-tooltip-color: var(--sn-super-light-grey);
--dp-disabled-color-text: var(--sn-grey);
--dp-highlight-color: var(--sn-super-light-grey);
--dp-range-between-dates-background-color: var(--dp-hover-color, var(--sn-super-light-grey));
--dp-range-between-dates-text-color: var(--dp-hover-text-color, var(--sn-black));
--dp-range-between-border-color: var(--dp-hover-color, var(--sn-super-light-grey));
}
:root {
/*General*/
--dp-font-family: inherit; /*Font family*/
--dp-border-radius: .25rem; /*Configurable border-radius*/
--dp-cell-border-radius: .25rem; /*Specific border radius for the calendar cell*/
--dp-common-transition: all 0.1s ease-in; /*Generic transition applied on buttons and calendar cells*/
/*Sizing*/
--dp-button-height: 2.5rem; /*Size for buttons in overlays*/
--dp-month-year-row-height: 2.5rem; /*Height of the month-year select row*/
--dp-month-year-row-button-size: 2.5rem; /*Specific height for the next/previous buttons*/
--dp-button-icon-height: 1.5rem; /*Icon sizing in buttons*/
--dp-cell-size: 1.875rem; /*Width and height of calendar cell*/
--dp-cell-padding: 0rem; /*Padding in the cell*/
--dp-common-padding: 1rem; /*Common padding used*/
--dp-input-padding: .3em 2rem .3rem 1rem; /*Padding in the input*/
--dp-menu-min-width: 276px; /*Adjust the min width of the menu*/
--dp-action-row-padding: 0 1rem 1rem; /*Adjust padding for the action row*/
--dp-action-buttons-padding: 0 .625rem; /*Adjust padding for the action buttons in action row*/
--dp-action-button-height: 1.875rem; /*Adjust height for the action buttons in action row*/
--dp-row-margin: 2px 0; /*Adjust the spacing between rows in the calendar*/
--dp-calendar-header-cell-padding: .5rem; /*Adjust padding in calendar header cells*/
--dp-two-calendars-spacing: .75rem; /*Space between multiple calendars*/
--dp-overlay-col-padding: .25rem; /*Padding in the overlay column*/
--dp-time-inc-dec-button-size: 1.5rem; /*Sizing for arrow buttons in the time picker*/
--dp-menu-padding: 1rem; /*Menu padding*/
--dp-input-icon-padding: 2rem; /*Padding on the left side of the input if icon is present*/
/*Font sizes*/
--dp-font-size: .875rem; /*Default font-size*/
--dp-preview-font-size: .75rem; /*Font size of the date preview in the action row*/
--dp-time-font-size: 1.875rem; /*Font size in the time picker*/
/*Transitions*/
--dp-animation-duration: 0.1s; /*Transition duration*/
--dp-menu-appear-transition-timing: cubic-bezier(.4, 0, 1, 1); /*Timing on menu appear animation*/
--dp-transition-timing: ease-out; /*Timing on slide animations*/
}
// Legacy
.bootstrap-datetimepicker-widget {
.glyphicon-calendar {
margin: 0;

View file

@ -79,11 +79,6 @@
}
}
.datetime-picker-container {
display: inline-block;
width: 46%;
}
.connect-line {
display: inline-block;
margin: 0 11px;

View file

@ -475,11 +475,11 @@ class MyModulesController < ApplicationController
if permitted_params[:started_on].present?
permitted_params[:started_on] =
Time.zone.strptime(permitted_params[:started_on], I18n.backend.date_format.dup.gsub(/%-/, '%') + ' %H:%M')
Time.zone.strptime(permitted_params[:started_on], '%Y/%m/%d %H:%M')
end
if permitted_params[:due_date].present?
permitted_params[:due_date] =
Time.zone.strptime(permitted_params[:due_date], I18n.backend.date_format.dup.gsub(/%-/, '%') + ' %H:%M')
Time.zone.strptime(permitted_params[:due_date], '%Y/%m/%d %H:%M')
end
permitted_params

View file

@ -69,7 +69,6 @@ class ProjectsController < ApplicationController
projects_cards_url: projects_cards_url,
title_html: title_html,
next_page: cards.next_page,
toolbar_html: render_to_string(partial: 'projects/index/toolbar'),
cards_html: render_to_string(
partial: 'projects/index/team_projects',
locals: { cards: cards, view_mode: params[:view_mode] }

View file

@ -94,10 +94,28 @@ module SciFormHelper
js_format
end
def datetime_picker_format_date_only_vue
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')
js_format
end
# Returns date and time format string for Bootstrap DateTimePicker
def datetime_picker_format_full
js_format = datetime_picker_format_date_only
js_format << ' HH:mm'
js_format
end
def datetime_picker_format_full_vue
js_format = datetime_picker_format_date_only_vue
js_format << ' HH:mm'
js_format
end
end

View file

@ -10,6 +10,8 @@ require('jquery-ui/ui/effects/effect-slide');
require('hammerjs');
import 'bootstrap';
require('bootstrap-select/js/bootstrap-select');
import '@vuepic/vue-datepicker/dist/main.css';
import 'vue3-draggable-resizable/dist/Vue3DraggableResizable.css'
window.bwipjs = require('bwip-js');
window.Decimal = require('decimal.js');

View file

@ -1 +1 @@
@import "bootstrap-select/sass/bootstrap-select"
@import "bootstrap-select/sass/bootstrap-select";

View file

@ -1,20 +1,18 @@
/* global notTurbolinksPreview */
import TurbolinksAdapter from 'vue-turbolinks';
import Vue from 'vue/dist/vue.esm';
import { createApp } from 'vue/dist/vue.esm-bundler.js';
import ActionToolbar from '../../vue/components/action_toolbar.vue';
Vue.use(TurbolinksAdapter);
Vue.prototype.i18n = window.I18n;
import { mountWithTurbolinks } from './helpers/turbolinks.js';
window.initActionToolbar = () => {
if (window.actionToolbarComponent) return;
if (notTurbolinksPreview()) {
new Vue({
el: '#actionToolbar',
components: {
ActionToolbar
}
const app = createApp({});
app.component('ActionToolbar', ActionToolbar);
app.config.globalProperties.i18n = window.I18n;
mountWithTurbolinks(app, '#actionToolbar', () => {
window.actionToolbarComponent = null
});
}
}

View file

@ -1,22 +1,14 @@
import TurbolinksAdapter from 'vue-turbolinks';
import Vue from 'vue/dist/vue.esm';
import AssignItemsToTaskModalContainer from '../../vue/assign_items_to_tasks_modal/container.vue';
import PerfectScrollbar from 'vue2-perfect-scrollbar';
import 'vue2-perfect-scrollbar/dist/vue2-perfect-scrollbar.css';
Vue.use(TurbolinksAdapter);
Vue.use(PerfectScrollbar);
Vue.prototype.i18n = window.I18n;
import PerfectScrollbar from 'vue3-perfect-scrollbar';
import { createApp } from 'vue/dist/vue.esm-bundler.js';
import 'vue3-perfect-scrollbar/dist/vue3-perfect-scrollbar.css';
import AssignItemsToTaskModalContainer from '../../vue/assign_items_to_tasks_modal/container.vue';
import { mountWithTurbolinks } from './helpers/turbolinks.js';
function initAssignItemsToTaskModalComponent() {
const container = $('.assign-items-to-task-modal-container');
if (container.length) {
window.AssignItemsToTaskModalComponentContainer = new Vue({
el: '.assign-items-to-task-modal-container',
name: 'AssignItemsToTaskModalComponent',
components: {
'assign-items-to-task-modal-container': AssignItemsToTaskModalContainer
},
const app = createApp({
data() {
return {
visibility: false,
@ -39,6 +31,10 @@ function initAssignItemsToTaskModalComponent() {
}
}
});
app.component('AssignItemsToTaskModalContainer', AssignItemsToTaskModalContainer);
app.use(PerfectScrollbar);
app.config.globalProperties.i18n = window.I18n;
window.AssignItemsToTaskModalComponentContainer = mountWithTurbolinks(app, '.assign-items-to-task-modal-container');
}
}

View file

@ -1,34 +0,0 @@
// Use this to register outside-click directive on a Vue component
// eslint-disable-next-line max-len
// eg v-click-outside="{handler: 'handlerToTrigger', exclude: [refs to ignore on click (eg 'searchInput', 'searchInputBtn')]}"
// eslint-enable-next-line max-len
export default {
bind(el, binding, vnode) {
el._vueClickOutside_ = (e) => {
let clickedOnExcludedEl = false;
const { exclude } = binding.value;
exclude.forEach(refName => {
if (!clickedOnExcludedEl) {
const excludedEl = vnode.context.$refs[refName];
if (!excludedEl) return;
clickedOnExcludedEl = (excludedEl._isVue ? excludedEl.$el : excludedEl).contains(e.target);
}
});
if (!el.contains(e.target) && !clickedOnExcludedEl) {
const { handler } = binding.value;
vnode.context[handler]();
}
};
document.addEventListener('click', el._vueClickOutside_);
document.addEventListener('touchstart', el._vueClickOutside_);
},
unbind(el) {
document.removeEventListener('click', el._vueClickOutside_);
document.removeEventListener('touchstart', el._vueClickOutside_);
el._vueClickOutside_ = null;
}
};

View file

@ -1,21 +1,15 @@
/* global notTurbolinksPreview */
import TurbolinksAdapter from 'vue-turbolinks';
import Vue from 'vue/dist/vue.esm';
import { createApp } from 'vue/dist/vue.esm-bundler.js';
import ExportStockConsumptionModal from '../../vue/repository_row/export_stock_consumption_modal.vue';
Vue.use(TurbolinksAdapter);
Vue.prototype.i18n = window.I18n;
import { mountWithTurbolinks } from './helpers/turbolinks.js';
window.initExportStockConsumptionModal = () => {
if (window.exportStockConsumptionModalComponent) return;
if (notTurbolinksPreview()) {
new Vue({
el: '#exportStockConsumtionModal',
components: {
ExportStockConsumptionModal,
},
});
const app = createApp({});
app.component('ExportStockConsumptionModal', ExportStockConsumptionModal);
app.config.globalProperties.i18n = window.I18n;
mountWithTurbolinks(app, '#exportStockConsumtionModal');
}
};

View file

@ -0,0 +1,15 @@
function mountWithTurbolinks(app, target, callback = null) {
const originalHtml = document.querySelector(target).innerHTML;
document.addEventListener('turbolinks:before-cache', () => {
app.unmount();
if (document.querySelector(target)) {
document.querySelector(target).innerHTML = originalHtml;
}
if (callback) callback();
}, { once: true });
return app.mount(target);
}
export { mountWithTurbolinks };

View file

@ -1,17 +1,9 @@
import TurbolinksAdapter from 'vue-turbolinks';
import Vue from 'vue/dist/vue.esm';
import { createApp } from 'vue/dist/vue.esm-bundler.js';
import LabelTemplateContainer from '../../vue/label_template/container.vue';
Vue.use(TurbolinksAdapter);
Vue.prototype.i18n = window.I18n;
import { mountWithTurbolinks } from './helpers/turbolinks.js';
window.initLabelTemplateComponent = () => {
new Vue({
el: '#labelTemplateContainer',
components: {
'label-template-container': LabelTemplateContainer
},
const app = createApp({
data() {
return {
labelTemplateUrl: $('#labelTemplateContainer').data('label-template-url'),
@ -21,6 +13,9 @@ window.initLabelTemplateComponent = () => {
};
}
});
app.component('LabelTemplateContainer', LabelTemplateContainer);
app.config.globalProperties.i18n = window.I18n;
mountWithTurbolinks(app, '#labelTemplateContainer');
};
initLabelTemplateComponent();

View file

@ -0,0 +1,79 @@
import { createApp } from 'vue/dist/vue.esm-bundler.js';
import DateTimePicker from '../../../vue/shared/date_time_picker.vue';
import { mountWithTurbolinks } from '../helpers/turbolinks.js';
/*
<div id="date-time-picker" class="vue-date-time-picker">
<input ref="input" type="hidden" v-model="date" id="legacy-id" data-default="" />
<date-time-picker ref="vueDateTime" @change="updateDate" :mode="date"></date-time-picker>
</div>
*/
window.initDateTimePickerComponent = (id) => {
const app = createApp({
data() {
return {
date: null,
onChange: null
};
},
mounted() {
if (this.$refs.input.dataset.default) {
const defaultDate = new Date(this.$refs.input.dataset.default.replace(/([^!\s])-/g, '$1/')); // Safari fix
this.date = this.formatDate(defaultDate);
this.$refs.vueDateTime.manualUpdate = true;
this.$refs.vueDateTime.datetime = defaultDate;
} else if (this.date) {
this.$refs.vueDateTime.manualUpdate = true;
this.$refs.vueDateTime.datetime = new Date(this.date);
}
$(this.$refs.input).data('dateTimePicker', this);
$(this.$el.parentElement).parent().trigger('dp:ready');
},
methods: {
formatDate(date) {
if (this.$refs.input.dataset.simpleFormat) {
const y = date.getFullYear();
const m = date.getMonth() + 1;
const d = date.getDate();
const hours = date.getHours();
const mins = date.getMinutes();
return `${y}/${m}/${d} ${hours}:${mins}`;
}
return date.toISOString();
},
updateDate(date) {
this.date = this.formatDate(date);
this.$nextTick(() => {
if (this.onChange) this.onChange(date);
});
},
setDate(date) {
this.date = this.formatDate(date);
this.$refs.vueDateTime.manualUpdate = true;
this.$refs.vueDateTime.datetime = date;
this.$nextTick(() => {
if (this.onChange) this.onChange(date);
});
},
clearDate() {
this.date = null;
this.$refs.vueDateTime.datetime = null;
this.$nextTick(() => {
if (this.onChange) this.onChange(null);
});
}
}
});
app.component('DateTimePicker', DateTimePicker);
app.config.globalProperties.i18n = window.I18n;
mountWithTurbolinks(app, id);
};
document.addEventListener('turbolinks:load', () => {
const dateTimePickers = document.querySelectorAll('.vue-date-time-picker');
dateTimePickers.forEach((dateTimePicker) => {
window.initDateTimePickerComponent(`#${dateTimePicker.id}`);
});
})

View file

@ -1,17 +1,13 @@
import TurbolinksAdapter from 'vue-turbolinks';
import Vue from 'vue/dist/vue.esm';
import PerfectScrollbar from 'vue3-perfect-scrollbar';
import { createApp } from 'vue/dist/vue.esm-bundler.js';
import 'vue3-perfect-scrollbar/dist/vue3-perfect-scrollbar.css';
import Breadcrumbs from '../../../vue/navigation/breadcrumbs/breadcrumbs.vue';
import PerfectScrollbar from 'vue2-perfect-scrollbar';
import 'vue2-perfect-scrollbar/dist/vue2-perfect-scrollbar.css';
import { mountWithTurbolinks } from '../helpers/turbolinks.js';
Vue.use(TurbolinksAdapter);
Vue.use(PerfectScrollbar);
Vue.prototype.i18n = window.I18n;
window.breadcrumbsComponent = new Vue({
el: '#breadcrumbs',
name: 'BreadcrumbsContainer',
components: {
breadcrumbs: Breadcrumbs
}
});
const app = createApp({});
app.component('Breadcrumbs', Breadcrumbs);
app.use(PerfectScrollbar);
app.config.globalProperties.i18n = window.I18n;
window.breadcrumbsComponent = mountWithTurbolinks(app, '#breadcrumbs');

View file

@ -1,19 +1,10 @@
import Vue from 'vue/dist/vue.esm';
import PerfectScrollbar from 'vue3-perfect-scrollbar';
import { createApp } from 'vue/dist/vue.esm-bundler.js';
import 'vue3-perfect-scrollbar/dist/vue3-perfect-scrollbar.css';
import NavigatorContainer from '../../../vue/navigation/navigator.vue';
import PerfectScrollbar from 'vue2-perfect-scrollbar';
import 'vue2-perfect-scrollbar/dist/vue2-perfect-scrollbar.css';
Vue.use(PerfectScrollbar);
Vue.prototype.i18n = window.I18n;
function addNavigationNavigatorContainer() {
let navigator = new Vue({
el: '#sciNavigationNavigatorContainer',
components: {
'navigator-container': NavigatorContainer
},
const app = createApp({
data() {
return {
reloadCurrentLevel: false,
@ -53,8 +44,10 @@ function addNavigationNavigatorContainer() {
}
}
});
window.navigatorContainer = navigator
app.component('NavigatorContainer', NavigatorContainer);
app.use(PerfectScrollbar);
app.config.globalProperties.i18n = window.I18n;
window.navigatorContainer = app.mount('#sciNavigationNavigatorContainer');
}
if (document.readyState !== 'loading') {

View file

@ -1,21 +1,14 @@
import Vue from 'vue/dist/vue.esm';
import PerfectScrollbar from 'vue3-perfect-scrollbar';
import { createApp } from 'vue/dist/vue.esm-bundler.js';
import 'vue3-perfect-scrollbar/dist/vue3-perfect-scrollbar.css';
import TopMenuContainer from '../../../vue/navigation/top_menu.vue';
import PerfectScrollbar from 'vue2-perfect-scrollbar';
import 'vue2-perfect-scrollbar/dist/vue2-perfect-scrollbar.css';
import outsideClick from '../directives/outside_click';
Vue.use(PerfectScrollbar);
Vue.directive('click-outside', outsideClick);
Vue.prototype.i18n = window.I18n;
function addNavigationTopMenuContainer() {
new Vue({
el: '#sciNavigationTopMenuContainer',
components: {
'top-menu-container': TopMenuContainer
}
});
const app = createApp({});
app.component('TopMenuContainer', TopMenuContainer);
app.use(PerfectScrollbar);
app.config.globalProperties.i18n = window.I18n;
app.mount('#sciNavigationTopMenuContainer');
}
if (document.readyState !== 'loading') {

View file

@ -1,11 +1,8 @@
import TurbolinksAdapter from 'vue-turbolinks';
import Vue from 'vue/dist/vue.esm';
import { createApp } from 'vue/dist/vue.esm-bundler.js';
import OpenVectorEditor from '../../vue/ove/OpenVectorEditor.vue';
import { mountWithTurbolinks } from './helpers/turbolinks.js';
Vue.use(TurbolinksAdapter);
Vue.prototype.i18n = window.I18n;
new Vue({
el: '#open-vector-editor',
components: { OpenVectorEditor }
});
const app = createApp({});
app.component('OpenVectorEditor', OpenVectorEditor);
app.config.globalProperties.i18n = window.I18n;
mountWithTurbolinks(app, '#open-vector-editor');

View file

@ -1,21 +1,25 @@
/* global HelperModule */
import TurbolinksAdapter from 'vue-turbolinks';
import Vue from 'vue/dist/vue.esm';
import PerfectScrollbar from 'vue3-perfect-scrollbar';
import { createApp } from 'vue/dist/vue.esm-bundler.js';
import ProtocolContainer from '../../vue/protocol/container.vue';
import PerfectScrollbar from 'vue2-perfect-scrollbar';
import outsideClick from './directives/outside_click';
Vue.use(PerfectScrollbar);
Vue.use(TurbolinksAdapter);
Vue.directive('click-outside', outsideClick);
Vue.prototype.i18n = window.I18n;
Vue.prototype.inlineEditing = window.inlineEditing;
Vue.prototype.ActiveStoragePreviews = window.ActiveStoragePreviews;
import { mountWithTurbolinks } from './helpers/turbolinks.js';
window.initProtocolComponent = () => {
Vue.prototype.dateFormat = $('#protocolContainer').data('date-format');
const app = createApp({
data() {
return {
protocolUrl: $('#protocolContainer').data('protocol-url'),
};
},
});
app.component('ProtocolContainer', ProtocolContainer);
app.use(PerfectScrollbar);
app.config.globalProperties.i18n = window.I18n;
app.config.globalProperties.inlineEditing = window.inlineEditing;
app.config.globalProperties.ActiveStoragePreviews = window.ActiveStoragePreviews;
app.config.globalProperties.dateFormat = $('#protocolContainer').data('date-format');
mountWithTurbolinks(app, '#protocolContainer');
$('.protocols-show').on('click', '#protocol-versions-modal .delete-draft', (e) => {
const url = e.currentTarget.dataset.url;
@ -28,18 +32,6 @@ window.initProtocolComponent = () => {
$('#deleteDraftModal form').on('ajax:error', function(_ev, data) {
HelperModule.flashAlertMsg(data.responseJSON.message, 'danger');
});
new Vue({
el: '#protocolContainer',
components: {
'protocol-container': ProtocolContainer
},
data() {
return {
protocolUrl: $('#protocolContainer').data('protocol-url')
};
}
});
};
initProtocolComponent();

View file

@ -1,18 +1,12 @@
import TurbolinksAdapter from 'vue-turbolinks';
import Vue from 'vue/dist/vue.esm';
import { createApp } from 'vue/dist/vue.esm-bundler.js';
import ProtocolFileImportModal from '../../vue/protocol_import/file_import_modal.vue';
Vue.use(TurbolinksAdapter);
Vue.prototype.i18n = window.I18n;
import { mountWithTurbolinks } from './helpers/turbolinks.js';
window.initProtocolFileImportModalComponent = () => {
new Vue({
el: '#protocolFileImportModal',
components: {
'protocol-file-import-modal': ProtocolFileImportModal
}
});
const app = createApp({});
app.component('ProtocolFileImportModal', ProtocolFileImportModal);
app.config.globalProperties.i18n = window.I18n;
mountWithTurbolinks(app, '#protocolFileImportModal');
};
initProtocolFileImportModalComponent();

View file

@ -1,11 +1,8 @@
/* global I18n */
import TurbolinksAdapter from 'vue-turbolinks';
import Vue from 'vue/dist/vue.esm';
import { createApp } from 'vue/dist/vue.esm-bundler.js';
import FilterContainer from '../../vue/repository_filter/container.vue';
Vue.use(TurbolinksAdapter);
Vue.prototype.i18n = window.I18n;
import { mountWithTurbolinks } from './helpers/turbolinks.js';
const DEFAULT_FILTERS = [
{
@ -62,7 +59,6 @@ const DEFAULT_FILTERS = [
window.repositoryFilterObject = null;
window.initRepositoryFilter = () => {
Vue.prototype.dateFormat = $('#filterContainer').data('date-format')
const defaultColumns = [
{ id: 'assigned', name: I18n.t('repositories.table.assigned_tasks'), data_type: 'RepositoryMyModuleValue' },
{ id: 'row_id', name: I18n.t('repositories.table.id'), data_type: 'RepositoryTextValue' },
@ -73,8 +69,7 @@ window.initRepositoryFilter = () => {
{ id: 'archived_on', name: I18n.t('repositories.table.archived_on'), data_type: 'RepositoryDateTimeValue' }
];
const defFilters = JSON.parse(JSON.stringify(DEFAULT_FILTERS));
const repositoryFilterContainer = new Vue({
el: '#filterContainer',
const app = createApp({
data: () => ({
filters: [],
defaultFilters: DEFAULT_FILTERS,
@ -86,10 +81,19 @@ window.initRepositoryFilter = () => {
}),
created() {
this.dataTableElement = $($('#filterContainer').data('datatable-id'));
},
components: {
'filter-container': FilterContainer
$.get($('#filterContainer').data('my-modules-url'), (data) => {
this.my_modules = data.data;
});
$.get($('#filterContainer').data('columns-url'), (data) => {
const combinedColumns = data.response.concat(defaultColumns);
this.columns = combinedColumns.sort((a, b) => a.name > b.name ? 1 : -1);
});
$.get($('#filterContainer').data('saved-filters-url'), (data) => {
this.savedFilters = data.data;
});
},
computed: {
filtersJSON() {
@ -144,19 +148,10 @@ window.initRepositoryFilter = () => {
}
}
});
$.get($('#filterContainer').data('my-modules-url'), (data) => {
repositoryFilterContainer.my_modules = data.data;
});
$.get($('#filterContainer').data('columns-url'), (data) => {
const combinedColumns = data.response.concat(defaultColumns);
repositoryFilterContainer.columns = combinedColumns.sort((a, b) => a.name > b.name ? 1 : -1);
});
$.get($('#filterContainer').data('saved-filters-url'), (data) => {
repositoryFilterContainer.savedFilters = data.data;
});
app.component('FilterContainer', FilterContainer);
app.config.globalProperties.i18n = window.I18n;
app.config.globalProperties.dateFormat = $('#filterContainer').data('date-format');
window.repositoryFilterObject = mountWithTurbolinks(app, '#filterContainer');
$('#filterContainer').on('click', (e) => {
$('#filterContainer .dropdown-selector-container').removeClass('open')
@ -166,6 +161,4 @@ window.initRepositoryFilter = () => {
$('#filtersDropdownButton').on('show.bs.dropdown', () => {
$('#filtersColumnsDropdown, #savedFiltersContainer').removeClass('open');
});
window.repositoryFilterObject = repositoryFilterContainer;
};

View file

@ -1,11 +1,13 @@
/* global notTurbolinksPreview */
import { createApp } from 'vue/dist/vue.esm-bundler.js';
import TurbolinksAdapter from 'vue-turbolinks';
import Vue from 'vue/dist/vue.esm';
import 'vue2-perfect-scrollbar/dist/vue2-perfect-scrollbar.css';
import PerfectScrollbar from 'vue2-perfect-scrollbar';
import RepositoryItemSidebar from '../../vue/repository_item_sidebar/RepositoryItemSidebar.vue';
import outsideClick from './directives/outside_click';
import { mountWithTurbolinks } from './helpers/turbolinks.js';
Vue.use(TurbolinksAdapter);
Vue.directive('click-outside', outsideClick);
@ -13,12 +15,10 @@ Vue.use(PerfectScrollbar);
Vue.prototype.i18n = window.I18n;
function initRepositoryItemSidebar() {
new Vue({
el: '#repositoryItemSidebar',
components: {
RepositoryItemSidebar
}
});
const app = createApp({});
app.component('RepositoryItemSidebar', RepositoryItemSidebar);
app.config.globalProperties.i18n = window.I18n;
mountWithTurbolinks(app, '#repositoryItemSidebar');
}
initRepositoryItemSidebar();

View file

@ -1,19 +1,11 @@
import TurbolinksAdapter from 'vue-turbolinks';
import Vue from 'vue/dist/vue.esm';
import { createApp } from 'vue/dist/vue.esm-bundler.js';
import PrintModalContainer from '../../vue/repository_print_modal/container.vue';
Vue.use(TurbolinksAdapter);
Vue.prototype.i18n = window.I18n;
import { mountWithTurbolinks } from './helpers/turbolinks.js';
function initPrintModalComponent() {
const container = $('.print-label-modal-container');
if (container.length) {
window.PrintModalComponent = new Vue({
el: '.print-label-modal-container',
name: 'PrintModalComponent',
components: {
'print-modal-container': PrintModalContainer
},
const app = createApp({
data() {
return {
showModal: false,
@ -36,6 +28,9 @@ function initPrintModalComponent() {
}
}
});
app.component('PrintModalContainer', PrintModalContainer);
app.config.globalProperties.i18n = window.I18n;
mountWithTurbolinks(app, '.print-label-modal-container');
}
}

View file

@ -1,16 +1,13 @@
import TurbolinksAdapter from 'vue-turbolinks';
import Vue from 'vue/dist/vue.esm';
import { createApp } from 'vue/dist/vue.esm-bundler.js';
import RepositorySearchContainer from '../../vue/repository_search/container.vue';
import { mountWithTurbolinks } from './helpers/turbolinks.js';
Vue.use(TurbolinksAdapter);
Vue.prototype.i18n = window.I18n;
window.initRepositorySearch = () => {
window.RepositorySearchComponent = new Vue({
el: '#inventorySearchComponent',
name: 'RepositorySearchComponent',
components: {
'repository_search_container': RepositorySearchContainer
}
});
const app = createApp({});
app.component('RepositorySearchContainer', RepositorySearchContainer);
app.config.globalProperties.i18n = window.I18n;
mountWithTurbolinks(app, '#inventorySearchComponent');
}

View file

@ -1,19 +1,11 @@
import TurbolinksAdapter from 'vue-turbolinks';
import Vue from 'vue/dist/vue.esm';
import PerfectScrollbar from 'vue3-perfect-scrollbar';
import { createApp } from 'vue/dist/vue.esm-bundler.js';
import Results from '../../vue/results/results.vue';
import PerfectScrollbar from 'vue2-perfect-scrollbar';
import outsideClick from './directives/outside_click';
import { mountWithTurbolinks } from './helpers/turbolinks.js';
Vue.use(PerfectScrollbar);
Vue.use(TurbolinksAdapter);
Vue.directive('click-outside', outsideClick);
Vue.prototype.i18n = window.I18n;
Vue.prototype.ActiveStoragePreviews = window.ActiveStoragePreviews;
new Vue({
el: '#results',
components: {
Results
}
});
const app = createApp({});
app.component('Results', Results);
app.use(PerfectScrollbar);
app.config.globalProperties.i18n = window.I18n;
app.config.globalProperties.ActiveStoragePreviews = window.ActiveStoragePreviews;
mountWithTurbolinks(app, '#results');

View file

@ -1,20 +1,14 @@
import Vue from 'vue/dist/vue.esm';
import PerfectScrollbar from 'vue3-perfect-scrollbar';
import { createApp } from 'vue/dist/vue.esm-bundler.js';
import 'vue3-perfect-scrollbar/dist/vue3-perfect-scrollbar.css';
import ShareLinkContainer from '../../vue/shareable_links/container.vue';
import PerfectScrollbar from 'vue2-perfect-scrollbar';
import 'vue2-perfect-scrollbar/dist/vue2-perfect-scrollbar.css';
Vue.use(PerfectScrollbar);
Vue.prototype.i18n = window.I18n;
function initShareTaskContainer() {
new Vue({
el: '.share-task-container',
components: {
'share-task-container': ShareLinkContainer
}
});
const app = createApp({});
app.component('ShareLinkContainer', ShareLinkContainer);
app.use(PerfectScrollbar);
app.config.globalProperties.i18n = window.I18n;
app.mount('.share-task-container');
}
initShareTaskContainer();

View file

@ -184,7 +184,7 @@ export default {
this.$emit("close");
});
},
beforeDestroy() {
beforeUnmount() {
delete window.AssignItemsToTaskModalComponent;
},
computed: {

View file

@ -111,7 +111,7 @@
this.$nextTick(this.setWidth);
window.addEventListener('scroll', this.setLeftOffset);
},
beforeDestroy() {
beforeUnmount() {
delete window.actionToolbarComponent;
window.removeEventListener('scroll', this.setLeftOffset);
},

View file

@ -14,7 +14,7 @@ export default {
mounted() {
this.observeChanges();
},
beforeDestroy() {
beforeUnmount() {
if (this.observer) {
this.observer.disconnect();
}

View file

@ -35,7 +35,7 @@ export default {
this.handleTinyMCEOpened(e.detail.target);
});
},
beforeDestroy() {
beforeUnmount() {
if (this.resizeObserver) {
this.resizeObserver.disconnect();
}

View file

@ -38,7 +38,7 @@
</template>
<script>
import { PerfectScrollbar } from 'vue2-perfect-scrollbar';
import { PerfectScrollbar } from 'vue3-perfect-scrollbar';
export default {
name: "BreadcrumbsDropdown",

View file

@ -1,17 +1,18 @@
<template>
<vue-resizable
<Vue3DraggableResizable
:initW="getNavigatorWidth()"
ref="vueResizable"
:max-width="400"
:min-width="208"
width="auto"
height="100%"
class="!h-full"
:active="['r']"
@resize:start="onResizeStart"
@resize:move="onResizeMove"
@resize:end="onResizeEnd"
:minW="208"
:disabledH="true"
:handles="['mr']"
:resizable="true"
:draggable="false"
class="max-w-[400px] !h-full"
@resize-start="onResizeStart"
@resizing="onResizeMove"
@resize-end="onResizeEnd"
>
<div class="ml-4 h-full border rounded relative bg-sn-white flex flex-col right-0 absolute navigator-container">
<div class="ml-4 h-full w-full border rounded bg-sn-white flex flex-col right-0 absolute navigator-container">
<div class="px-3 py-2.5 flex items-center relative leading-4">
<i class="sn-icon sn-icon-navigator"></i>
<div class="font-bold text-base pl-3">
@ -31,20 +32,20 @@
:archived="archived" />
</perfect-scrollbar>
</div>
</vue-resizable>
</Vue3DraggableResizable>
</template>
<script>
import NavigatorItem from './navigator_item.vue'
import VueResizable from 'vue-resizable'
import axios from '../../packs/custom_axios.js';
import Vue3DraggableResizable from 'vue3-draggable-resizable'
export default {
name : 'NavigatorContainer',
components: {
NavigatorItem,
VueResizable
Vue3DraggableResizable
},
data() {
return {
@ -54,7 +55,7 @@ export default {
navigatorYScroll: 0,
navigatorXScroll: 0,
currentItemId: null,
archived: null
archived: null,
}
},
props: {
@ -128,10 +129,11 @@ export default {
},
getNavigatorWidth() {
const computedStyle = getComputedStyle(document.documentElement);
return computedStyle.getPropertyValue('--navigator-navigation-width').trim();
return parseInt(computedStyle.getPropertyValue('--navigator-navigation-width').trim());
},
onResizeMove(event) {
document.documentElement.style.setProperty('--navigator-navigation-width', event.width + 'px');
if (event.w > 400) event.w = 400;
document.documentElement.style.setProperty('--navigator-navigation-width', event.w + 'px');
},
onResizeStart() {
document.body.style.cursor = 'url(/images/icon_small/Resize.svg) 0 0, auto';
@ -139,10 +141,11 @@ export default {
$('.sci--layout').addClass('!transition-none');
},
onResizeEnd(event) {
if (event.w > 400) event.w = 400;
document.body.style.cursor = 'default';
$('.sci--layout-navigation-navigator').removeClass('!transition-none');
$('.sci--layout').removeClass('!transition-none');
this.changeNavigatorState(event.width)
this.changeNavigatorState(event.w)
},
async changeNavigatorState(newWidth) {
try {

View file

@ -107,7 +107,7 @@
// Track name update in user profile settings
$(document).on('inlineEditing::updated', '.inline-editing-container[data-field-to-update="full_name"]', this.fetchData);
},
beforeDestroy: function(){
beforeUnmount: function(){
clearTimeout(this.unseenNotificationsTimeout);
},
computed: {

View file

@ -286,7 +286,7 @@
})
});
},
beforeDestroy() {
beforeUnmount() {
if (!this.inRepository) {
window.removeEventListener('scroll', this.initStackableHeaders, false);
}

View file

@ -429,6 +429,9 @@
},
updateElement(element, skipRequest=false, callback) {
let index = this.elements.findIndex((e) => e.id === element.id);
if (!this.elements[index]) return;
this.elements[index].isNew = false;
if (skipRequest) {

View file

@ -88,8 +88,6 @@
$.get(`/jobs/${this.jobId}/status`, (data) => {
let status = data.status;
console.log(data)
switch (status) {
case 'pending':
break;

View file

@ -9,11 +9,11 @@
@dropdown:changed="updateOperator" />
</div>
<div class="filter-datepicker-input">
<DateTimePicker @change="updateDate" :selectorId="`DatePicker${filter.id}`" :onlyDate="true" :defaultValue="date || fallbackDate()" />
<DateTimePicker @change="updateDate" :selectorId="`DatePicker${filter.id}`" :mode="'date'" :defaultValue="date || fallbackDate()" />
</div>
<span class="between-delimiter"></span>
<div class="filter-datepicker-to-input">
<DateTimePicker @change="updateDateTo" :selectorId="`DatePickerTo${filter.id}`" :onlyDate="true" :defaultValue="dateTo || fallbackDate(7 * 24 * 60 * 60)" />
<DateTimePicker @change="updateDateTo" :selectorId="`DatePickerTo${filter.id}`" :mode="'date'" :defaultValue="dateTo || fallbackDate(7 * 24 * 60 * 60)" />
</div>
</div>
</template>
@ -22,7 +22,7 @@
import FilterMixin from '../mixins/filter.js'
import RangeDateTimeFilterMixin from '../mixins/filters/range_date_time_filter.js'
import DropdownSelector from '../../shared/dropdown_selector.vue'
import DateTimePicker from '../../shared/date_picker.vue'
import DateTimePicker from '../../shared/date_time_picker.vue'
export default {
name: 'RepositoryDateRangeValue',

View file

@ -11,7 +11,7 @@
<template v-if="!isPreset">
<div class="datetime-filter-attributes">
<div class="filter-datepicker-input">
<DateTimePicker @change="updateDate" :selectorId="`DatePicker${filter.id}`" :defaultValue="null" />
<DateTimePicker @change="updateDate" :selectorId="`DatePicker${filter.id}`" :defaultValue="date" />
</div>
<div class="between-delimiter vertical" v-if="operator == 'between'"></div>
<div class="filter-datepicker-to-input">

View file

@ -10,11 +10,11 @@
</div>
<template v-if="!isPreset">
<div class="filter-datepicker-input">
<DateTimePicker @change="updateDate" :selectorId="`DatePicker${filter.id}`" :onlyDate="true" :defaultValue="date || fallbackDate()" />
<DateTimePicker @change="updateDate" :selectorId="`DatePicker${filter.id}`" :mode="'date'" :defaultValue="date || fallbackDate()" />
</div>
<span class="between-delimiter" v-if="operator == 'between'"></span>
<div class="filter-datepicker-to-input" v-if="operator == 'between'">
<DateTimePicker @change="updateDateTo" :selectorId="`DatePickerTo${filter.id}`" :onlyDate="true" :defaultValue="dateTo || fallbackDate(7 * 24 * 60 * 60)" />
<DateTimePicker @change="updateDateTo" :selectorId="`DatePickerTo${filter.id}`" :mode="'date'" :defaultValue="dateTo || fallbackDate(7 * 24 * 60 * 60)" />
</div>
</template>
</div>
@ -24,7 +24,7 @@
import FilterMixin from '../mixins/filter.js'
import DateTimeFilterMixin from '../mixins/filters/date_time_filter.js'
import DropdownSelector from '../../shared/dropdown_selector.vue'
import DateTimePicker from '../../shared/date_picker.vue'
import DateTimePicker from '../../shared/date_time_picker.vue'
export default {
name: 'RepositoryDateValue',

View file

@ -9,11 +9,11 @@
@dropdown:changed="updateOperator" />
</div>
<div class="filter-datepicker-input">
<DateTimePicker @change="updateDate" :selectorId="`TimePicker${filter.id}`" :timeOnly="true" :defaultValue="date || fallbackDate()" />
<DateTimePicker @change="updateDate" :selectorId="`TimePicker${filter.id}`" :mode="'time'" :defaultValue="date || fallbackDate()" />
</div>
<span class="between-delimiter"></span>
<div class="filter-datepicker-to-input">
<DateTimePicker @change="updateDateTo" :selectorId="`TimePickerTo${filter.id}`" :timeOnly="true" :defaultValue="dateTo || fallbackDate(7 * 24 * 60 * 60)" />
<DateTimePicker @change="updateDateTo" :selectorId="`TimePickerTo${filter.id}`" :mode="'time'" :defaultValue="dateTo || fallbackDate(7 * 24 * 60 * 60)" />
</div>
</div>
</template>

View file

@ -10,11 +10,11 @@
</div>
<template v-if="!isPreset">
<div class="filter-datepicker-input">
<DateTimePicker @change="updateDate" :selectorId="`TimePicker${filter.id}`" :timeOnly="true" :defaultValue="date || fallbackDate()" />
<DateTimePicker @change="updateDate" :selectorId="`TimePicker${filter.id}`" :mode="'time'" :defaultValue="date || fallbackDate()" />
</div>
<span class="between-delimiter" v-if="operator == 'between'"></span>
<div class="filter-datepicker-to-input" v-if="operator == 'between'">
<DateTimePicker @change="updateDateTo" :selectorId="`TimePickerTo${filter.id}`" :timeOnly="true" :defaultValue="dateTo || fallbackDate(7 * 24 * 60 * 60)" />
<DateTimePicker @change="updateDateTo" :selectorId="`TimePickerTo${filter.id}`" :mode="'time'" :defaultValue="dateTo || fallbackDate(7 * 24 * 60 * 60)" />
</div>
</template>
</div>

View file

@ -263,7 +263,7 @@ export default {
document.addEventListener('mousedown', this.handleOutsideClick);
this.inRepository = $('.assign-items-to-task-modal-container').length > 0;
},
beforeDestroy() {
beforeUnmount() {
delete window.repositoryItemSidebarComponent;
document.removeEventListener('mousedown', this.handleOutsideClick);
},

View file

@ -1,6 +1,6 @@
<template>
<div ref="modal"
class="modal fade"
class="modal fade"
id="exportStockConsumptionModal"
tabindex="-1"
role="dialog"
@ -22,7 +22,7 @@
<button type='button' class='btn btn-secondary' data-dismiss='modal' id='close-modal-export-stock-consumption'>
{{ i18n.t('general.cancel') }}
</button>
<button class="btn btn-success" id="export-stock-consumption" @click="exportConsumption">
{{ i18n.t('zip_export.consumption_generate') }}
</button>
@ -47,7 +47,7 @@
created() {
window.exportStockConsumptionModalComponent = this;
},
beforeDestroy() {
beforeUnmount() {
delete window.exportStockConsumptionModalComponent;
},
methods: {

View file

@ -1,7 +1,7 @@
<template>
<div
class="flex items-center mr-3 flex-nowrap relative"
v-click-outside="{handler: 'closeSearchInputs', exclude: ['searchInput', 'searchInputBtn', 'barcodeSearchInput', 'barcodeSearchInputBtn']}"
<div
class="flex items-center mr-3 flex-nowrap relative"
v-click-outside="closeSearchInputs"
>
<button :class="{hidden: searchOpened}" ref='searchInputBtn' class="btn btn-light btn-black icon-btn" :title="i18n.t('repositories.show.search_button_tooltip')" @click="openSearch">
<i class="sn-icon sn-icon-search"></i>
@ -35,7 +35,8 @@
</template>
<script>
import outsideClick from '../../packs/vue/directives/outside_click';
import { vOnClickOutside } from '@vueuse/components'
export default {
name: 'RepositorySearchContainer',
directives: {
@ -49,6 +50,9 @@ export default {
value: ''
}
},
directives: {
'click-outside': vOnClickOutside
},
watch: {
barcodeValue() {
this.updateRepositoySearch();

View file

@ -83,7 +83,7 @@
this.loadResults();
this.initStackableHeaders();
},
beforeDestroy() {
beforeUnmount() {
window.removeEventListener('scroll', this.loadResults, false);
window.removeEventListener('scroll', this.initStackableHeaders, false);
},

View file

@ -38,26 +38,27 @@
:chosenClass="'checklist-item-chosen'"
:forceFallback="true"
:handle="'.element-grip'"
item-key="id"
:disabled="editingItem || checklistItems.length < 2 || !element.attributes.orderable.urls.reorder_url"
@start="startReorder"
@end="endReorder"
>
<ChecklistItem
v-for="checklistItem in orderedChecklistItems"
:key="checklistItem.id"
:checklistItem="checklistItem"
:locked="locked"
:reordering="reordering"
:reorderChecklistItemUrl="element.attributes.orderable.urls.reorder_url"
:inRepository="inRepository"
:draggable="checklistItems.length > 1"
@editStart="editingItem = true"
@editEnd="editingItem = false"
@update="saveItem"
@toggle="saveItemChecked"
@removeItem="removeItem"
@component:delete="removeItem"
/>
<template #item="{element}">
<ChecklistItem
:checklistItem="element"
:locked="locked"
:reordering="reordering"
:reorderChecklistItemUrl="this.element.attributes.orderable.urls.reorder_url"
:inRepository="inRepository"
:draggable="checklistItems.length > 1"
@editStart="editingItem = true"
@editEnd="editingItem = false"
@update="saveItem"
@toggle="saveItemChecked"
@removeItem="removeItem"
@component:delete="removeItem"
/>
</template>
</Draggable>
<div v-if="element.attributes.orderable.urls.create_item_url && !addingNewItem"
class="flex items-center gap-1 text-sn-blue cursor-pointer mb-2 mt-1 "

View file

@ -1,8 +1,8 @@
<template>
<div class="content__checklist-item">
<div class="checklist-item-header flex rounded pl-10 ml-[-2.325rem] items-center relative w-full group/checklist-item-header" :class="{ 'locked': locked || editingText, 'editing-name': editingText }">
<div class="content__checklist-item pl-10 ml-[-2.325rem]">
<div class="checklist-item-header flex rounded items-center relative w-full group/checklist-item-header" :class="{ 'locked': locked || editingText, 'editing-name': editingText }">
<div v-if="reorderChecklistItemUrl"
class="absolute h-6 cursor-grab justify-center left-0 top-0.5 px-2 tw-hidden text-sn-grey element-grip step-element-grip--draggable"
class="absolute h-6 cursor-grab justify-center left-[-2.325rem] top-0.5 px-2 tw-hidden text-sn-grey element-grip step-element-grip--draggable"
:class="{ 'group-hover/checklist-item-header:flex': (!locked && !editingText && draggable) }"
>
<i class="sn-icon sn-icon-drag"></i>

View file

@ -129,7 +129,7 @@
created() {
window.addEventListener('beforeunload', this.showSaveWarning);
},
beforeDestroy() {
beforeUnmount() {
window.removeEventListener('beforeunload', this.showSaveWarning);
},
updated() {

View file

@ -1,60 +0,0 @@
<template>
<div v-if="!standAlone" class="datepicker sci-input-container right-icon">
<input
@change="update"
type="datetime"
class="form-control calendar-input sci-input-field"
:id="this.selectorId"
:placeholder="placeholder || 'dd/mm/yyyy'"
/>
<i class="sn-icon sn-icon-calendar"></i>
</div>
<div :class="className" v-else>
<input
@input="update"
type="datetime"
class='inline-block m-0 p-0 w-full border-none shadow-none outline-none'
:id="this.selectorId"
:placeholder="placeholder || 'dd/mm/yyyy'"
:disabled="disabled"
/>
</div>
</template>
<script>
import '../../../../vendor/assets/javascripts/bootstrap-datetimepicker';
export default {
name: 'DatePicker',
props: {
placeholder: { type: String },
selectorId: { type: String, required: true },
useCurrent: { type: Boolean, default: true },
defaultValue: { type: Date, default: null },
standAlone: { type: Boolean, default: false, required: false },
className: { type: String, default: '' },
disabled: { type: Boolean, default: false }
},
mounted() {
$("#" + this.selectorId).datetimepicker(
{
useCurrent: this.useCurrent,
ignoreReadonly: this.ignoreReadOnly,
locale: this.i18n.locale,
format: $('body').data('datetime-picker-format'),
date: this.defaultValue
}
);
$("#" + this.selectorId).on('dp.change', (e) => this.update(e.date))
if (this.isValidDate(this.defaultValue)) this.update(moment(this.defaultValue));
},
methods: {
update(value) {
this.$emit('change', (value?._isAMomentObject) ? value.toDate() : '');
},
isValidDate(date) {
return (date instanceof Date) && !isNaN(date.getTime());
},
}
}
</script>

View file

@ -1,36 +1,60 @@
<template>
<div class="date-time-picker" :class="{ 'grow': !standAlone, 'flex': standAlone}">
<DatePicker v-if="!timeOnly"
@change="updateDate"
:placeholder="placeholder"
:selectorId="`${this.selectorId}_Date`"
:defaultValue="defaultValue"
:standAlone="standAlone"
:className="dateClassName"
:disabled="disabled"
/>
<TimePicker v-if="!dateOnly"
@change="updateTime"
:placeholder="placeholder"
:selectorId="`${this.selectorId}_Time`"
:defaultValue="getTime(defaultValue)"
:standAlone="standAlone"
:className="timeClassName"
:disabled="disabled"
/>
<div class="date-time-picker grow">
<VueDatePicker
:class="{
'only-time': mode == 'time',
}"
v-model="compDatetime"
:teleport="teleport"
:text-input="true"
:no-today="true"
:clearable="clearable"
:format="format"
:month-change-on-scroll="false"
:six-weeks="true"
:auto-apply="true"
:partial-flow="true"
:markers="markers"
:enable-time-picker="mode == 'datetime'"
:time-picker="mode == 'time'"
:placeholder="placeholder" >
<template #arrow-right>
<img class="slot-icon" src="/images/calendar/navigate_next.svg"/>
</template>
<template #arrow-left>
<img class="slot-icon" src="/images/calendar/navigate_before.svg"/>
</template>
<template v-if="mode == 'time'" #input-icon>
<img class="input-slot-image" src="/images/calendar/clock.svg"/>
</template>
<template v-else #input-icon>
<img class="input-slot-image" src="/images/calendar/calendar.svg"/>
</template>
<template #clock-icon>
<img class="slot-icon" src="/images/calendar/clock.svg"/>
</template>
<template #calendar-icon>
<img class="slot-icon" src="/images/calendar/calendar.svg"/>
</template>
<template #arrow-up>
<img class="slot-icon" src="/images/calendar/up.svg"/>
</template>
<template #arrow-down>
<img class="slot-icon" src="/images/calendar/down.svg"/>
</template>
</VueDatePicker>
</div>
</template>
<script>
import TimePicker from './time_picker.vue'
import DatePicker from './date_picker.vue'
import VueDatePicker from '@vuepic/vue-datepicker';
export default {
name: 'DateTimePicker',
props: {
dateOnly: { type: Boolean, default: false },
timeOnly: { type: Boolean, default: false },
selectorId: { type: String, required: true },
mode: { type: String, default: 'datetime' },
clearable: { type: Boolean, default: false },
teleport: { type: Boolean, default: true },
defaultValue: { type: Date, required: false },
placeholder: { type: String },
standAlone: { type: Boolean, default: false, required: false },
@ -40,53 +64,105 @@
},
data() {
return {
date: '',
time: '',
datetime: ''
manualUpdate: false,
datetime: this.defaultValue,
time: null,
markers: [
{
date: new Date(),
type: 'dot',
color: '#3B99FD',
},
]
}
},
created() {
if (this.defaultValue) {
this.time = {
hours: this.defaultValue.getHours(),
minutes:this.defaultValue.getMinutes(),
}
}
},
components: {
TimePicker,
DatePicker
VueDatePicker
},
methods: {
updateDate(value) {
this.date = value;
this.updateDateTime();
},
getTime(dateTime) {
if(!this.isValidDate(dateTime)) return
return `${dateTime.getHours().toString().padStart(2, '0')}:${dateTime.getMinutes().toString().padStart(2, '0')}`
},
updateTime(value) {
this.time = value;
this.updateDateTime();
},
updateDateTime() {
this.recalcTimestamp();
this.$emit('change', this.datetime);
},
isValidTime() {
return /^([0-9]|0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]$/.test(this.time);
},
isValidDate(date) {
return (date instanceof Date) && !isNaN(date.getTime());
},
recalcTimestamp() {
let date = this.timeOnly ? new Date() : this.date;
if (this.isValidDate(date) && (this.dateOnly || this.isValidTime())) {
if (this.dateOnly) {
date.setHours(0);
date.setMinutes(0);
} else {
date.setHours(this.time.split(':')[0]);
date.setMinutes(this.time.split(':')[1]);
}
this.datetime = date
} else {
this.datetime = null;
watch: {
defaultValue: function () {
this.datetime = this.defaultValue;
this.time = {
hours: this.defaultValue ? this.defaultValue.getHours() : 0,
minutes: this.defaultValue ? this.defaultValue.getMinutes() : 0
}
},
datetime: function () {
if (this.mode == 'time') {
this.time = {
hours: this.datetime ? this.datetime.getHours() : 0,
minutes: this.datetime ? this.datetime.getMinutes() : 0
}
return
}
if (this.manualUpdate) {
this.manualUpdate = false;
return;
}
if ( this.datetime == null) {
this.$emit('cleared');
}
if (this.defaultValue != this.datetime) {
this.$emit('change', this.datetime);
}
},
time: function () {
if (this.manualUpdate) {
this.manualUpdate = false;
return;
}
if (this.mode != 'time') return;
let newDate;
if (this.time) {
newDate = new Date();
newDate.setHours(this.time.hours);
newDate.setMinutes(this.time.minutes);
} else {
newDate = null;
this.$emit('cleared');
}
if (this.defaultValue != newDate) {
this.$emit('change', newDate);
}
}
},
computed: {
compDatetime: {
get () {
if (this.mode == 'time') {
return this.time
} else {
return this.datetime
}
},
set (val) {
if (this.mode == 'time') {
this.time = val
} else {
this.datetime = val
}
}
},
format() {
if (this.mode == 'time') return 'HH:mm'
if (this.mode == 'date') return document.body.dataset.datetimePickerFormatVue
return `${document.body.dataset.datetimePickerFormatVue} HH:mm`
}
}
}

View file

@ -53,9 +53,9 @@
methods: {
updateFilter(params) {
if (params.value !== '' && params.value !== undefined && params.value !== null) {
this.$set(this.filterValues, params.key, params.value);
this.filterValues[params.key] = params.value;
} else {
this.$delete(this.filterValues, params.key);
delete this.filterValues[params.key];
}
},
applyFilters() {

View file

@ -15,7 +15,7 @@
'!mb-0': !openUp,
}"
v-if="showMenu"
v-click-outside="{handler: 'closeMenu', exclude: ['openBtn', 'flyout']}">
v-click-outside="closeMenu">
<span v-for="(item, i) in listItems" :key="i" class="contents">
<div v-if="item.dividerBefore" class="border-0 border-t border-solid border-sn-light-grey"></div>
<a :href="item.url" v-if="!item.submenu"
@ -64,6 +64,7 @@
<script>
import isInViewPort from './isInViewPort.js';
import { vOnClickOutside } from '@vueuse/components'
export default {
name: 'DropdownMenu',
@ -81,6 +82,9 @@ export default {
openUp: false
}
},
directives: {
'click-outside': vOnClickOutside
},
watch: {
showMenu() {
if (this.showMenu) {

View file

@ -15,18 +15,21 @@
:dragClass="'step-checklist-item-drag'"
:chosenClass="'step-checklist-item-chosen'"
:handle="'.step-element-grip'"
item-key="id"
>
<div v-for="(item, index) in reorderedItems" :key="item.id" class="step-element-header flex items-center">
<div class="step-element-grip step-element-grip--draggable">
<i class="sn-icon sn-icon-drag"></i>
<template #item="{element, index}">
<div class="step-element-header flex items-center">
<div class="step-element-grip step-element-grip--draggable">
<i class="sn-icon sn-icon-drag"></i>
</div>
<div class="step-element-name text-center">
<strong v-if="includeNumbers" class="step-element-number">{{ index + 1 }}</strong>
<i v-if="element.attributes.icon" class="fas" :class="element.attributes.icon"></i>
<span :title="nameWithFallbacks(element)" v-if="nameWithFallbacks(element)">{{ nameWithFallbacks(element) }}</span>
<span :title="element.attributes.placeholder" v-else class="step-element-name-placeholder">{{ element.attributes.placeholder }}</span>
</div>
</div>
<div class="step-element-name text-center">
<strong v-if="includeNumbers" class="step-element-number">{{ index + 1 }}</strong>
<i v-if="item.attributes.icon" class="fas" :class="item.attributes.icon"></i>
<span :title="nameWithFallbacks(item)" v-if="nameWithFallbacks(item)">{{ nameWithFallbacks(item) }}</span>
<span :title="item.attributes.placeholder" v-else class="step-element-name-placeholder">{{ item.attributes.placeholder }}</span>
</div>
</div>
</template>
</Draggable>
</div>
</div>

View file

@ -1,16 +1,5 @@
<template>
<div @click="toggle"
ref="container"
v-click-outside="{ handler: 'close', exclude: ['optionsContainer'] }"
class="sn-select"
:class="{
'sn-select--open': isOpen,
'sn-select--blank': !valueLabel,
'disabled cursor-default': disabled,
'cursor-pointer': !withEditCursor,
'sci-cursor-edit hover:border-sn-sleepy-grey': !disabled && !isOpen && withEditCursor,
[className]: true
}">
<div v-click-outside="close" @click="toggle" ref="container" class="sn-select" :class="{ 'sn-select--open': isOpen, 'sn-select--blank': !valueLabel, 'disabled': disabled }">
<slot>
<button ref="focusElement" class="sn-select__value">
<span>{{ valueLabel || (placeholder || i18n.t('general.select')) }}</span>
@ -60,8 +49,7 @@
</div>
</template>
<script>
import PerfectScrollbar from 'vue2-perfect-scrollbar';
import outsideClick from '../../packs/vue/directives/outside_click';
import { vOnClickOutside } from '@vueuse/components'
export default {
name: 'Select',
@ -78,7 +66,7 @@
disabled: { type: Boolean, default: false }
},
directives: {
'click-outside': outsideClick
'click-outside': vOnClickOutside
},
data() {
return {
@ -98,7 +86,7 @@
mounted() {
document.addEventListener('scroll', this.updateOptionPosition);
},
beforeDestroy() {
beforeUnmount() {
document.removeEventListener('scroll', this.updateOptionPosition);
},
methods: {

View file

@ -1,69 +0,0 @@
<template>
<div v-if="!standAlone" class="sci-input-container time-container right-icon">
<input class="time-part sci-input-field"
@input="update"
:id="this.selectorId"
type="text"
data-mask-type="time"
v-model="value"
placeholder="HH:mm"/>
<i class="sn-icon sn-icon-created"></i>
</div>
<span v-else :class="className">
<input class="time-part sci-input-field w-full inline-block m-0 p-0 border-none shadow-none outline-none"
@input="update"
:id="this.selectorId"
type="text"
data-mask-type="time"
:disabled="disabled"
v-model="value"
placeholder="HH:mm"
/>
</span>
</template>
<script>
export default {
name: 'TimePicker',
props: {
selectorId: { type: String, required: true },
defaultValue: { type: String, required: false },
standAlone: { type: Boolean, default: true, required: false },
className: { type: String, default: '', required: false },
disabled: { type: Boolean, default: false }
},
data() {
return {
value: ''
}
},
mounted() {
Inputmask('datetime', {
inputFormat: 'HH:MM',
placeholder: 'HH:mm',
clearIncomplete: true,
showMaskOnHover: true,
hourFormat: 24
}).mask($('#' + this.selectorId));
$('#' + this.selectorId).next().click(() => {
var inputField = $('#' + this.selectorId);
var d = new Date();
var h = ('0' + d.getHours()).slice(-2);
var m = ('0' + d.getMinutes()).slice(-2);
var value= h + ':' + m
inputField.val(value);
this.value = value;
this.update();
});
this.value = this.defaultValue;
this.update();
},
methods: {
update() {
this.$emit('change', this.value);
}
}
}
</script>

View file

@ -3,28 +3,18 @@
<div id="dueDateContainer" class="datetime-container"
data-update-url="<%= my_module_path(my_module, user, format: :json) %>">
<span class="date-text" data-editable="<%= due_date_editable %>"
<span class="date-text relative flex items-center" data-editable="<%= due_date_editable %>"
data-toggle="tooltip" data-placement="top" title="<%= due_status %>" data-due-status="<%= due_status %>">
<span id="dueDateLabelContainer" class="view-block" >
<%= render partial: "experiments/table_due_date_label" ,
locals: { my_module: my_module, user: user } %>
</span>
<% if due_date_editable %>
<div class="datetime-picker-container" id="due-date">
<input id="calendarDueDate<%= my_module.id %>"
type="datetime"
data-toggle='date-time-picker'
class="form-control calendar-input calendar-due-date "
readonly
placeholder="<%= t('my_modules.details.no_due_date_placeholder') %>"
data-date-format="<%= datetime_picker_format_full %>"
data-date-locale="<%= I18n.locale %>"
data-date-use-current="false"
data-date-orientation="left"
data-positioning-vertical="bottom"
value="<%= my_module.due_date ? l(my_module.due_date, format: :full) : '' %>"/>
<div class="datetime-picker-container vue-date-time-picker h-full" id="calendarDueDateContainer<%= my_module.id %>">
<input ref="input" type="hidden" data-simple-format="true" v-model="date" id="calendarDueDate<%= my_module.id %>" data-default="<%= my_module.due_date %>" />
<date-time-picker class="opacity-0" ref="vueDateTime" @change="updateDate" mode="datetime" placeholder="<%= t('my_modules.details.no_due_date_placeholder') %>"></date-time-picker>
</div>
<div class="sn-icon sn-icon-close clear-date"
<div class="sn-icon sn-icon-close clear-date <%= 'tw-hidden' if !my_module.due_date %>"
data-toggle='clear-date-time-picker'
data-target='calendarDueDate<%= my_module.id %>'>
</div>

View file

@ -1,14 +1,12 @@
<div class="datetime-picker-container"
id="<%= id %>"
data-id="<%= id %>"
data-use-current="<%= use_current %>"
data-datetime-picker-format="<%= datetime_picker_format_date_only %>">
<% if label %>
<label class="control-label required" for="calendar-<%= id %>"><%= label %></label>
<% end %>
<span class="sn-icon sn-icon-calendar"></span>
<input type="datetime" class="form-control calendar-input" name="calendar[<%= id %>]" id="calendar-<%= id %>" readonly="" data-ts="" placeholder="<%= placeholder %>" value="<%= defined?(setDate) ? setDate : '' %>"/>
<%= javascript_include_tag 'global_activities/date_picker' %>
<div class="datetime-picker-container">
<div id="date-time-picker-<%= id %>" class="vue-date-time-picker w-full">
<% selected_date = '' %>
<% selected_date = setDate if defined?(setDate) %>
<% selected_date = use_current %>
<% if label %>
<label class="sci-label" for="calendar-<%= id %>"><%= label %></label>
<% end %>
<input ref="input" type="hidden" class="calendar-input" id="calendar-<%= id %>" v-model="date" name="calendar[<%= id %>]" data-default="<%= defined?(setDate) ? setDate : '' %>" />
<date-time-picker class="w-full" @cleared="clearDate" ref="vueDateTime" placeholder="<%= placeholder %>" @change="updateDate" mode="date"></date-time-picker>
</div>
</div>

View file

@ -4,11 +4,6 @@
<%= content_for :sidebar do %>
<%= render partial: "/shared/sidebar/templates_sidebar", locals: {active: :label} %>
<% end %>
<% content_for :head do %>
<meta name="turbolinks-cache-control" content="no-cache">
<% end %>
<%= stylesheet_link_tag 'datatables' %>

View file

@ -24,6 +24,7 @@
<%= javascript_include_tag 'application' %>
<%= javascript_include_tag 'session_end' %>
<%= javascript_include_tag 'sidebar_toggle' %>
<%= stylesheet_link_tag 'application_pack', media: 'all' %>
<%= stylesheet_link_tag 'application', media: 'all' %>
@ -55,6 +56,8 @@
<%= stylesheet_link_tag 'tui_image_editor_styles' %>
<%= javascript_include_tag 'vue_navigation_navigator' %>
<%= javascript_include_tag 'vue_navigation_top_menu' %>
<%= javascript_include_tag 'vue_legacy_datetime_picker' %>
<style> :root { --navigator-navigation-width: <%= session[:navigator_width] || Constants::DEFAULT_NAV_WIDTH %>px; } </style>
</head>
<body
@ -69,6 +72,7 @@
data-atwho-rep-items-url="<%= atwho_rep_items_team_path(current_team) %>"
data-atwho-menu-items="<%= atwho_menu_items_team_path(current_team) %>"
data-datetime-picker-format="<%= datetime_picker_format_date_only %>"
data-datetime-picker-format-vue="<%= datetime_picker_format_date_only_vue %>"
<% end %>
>

View file

@ -1,7 +1,9 @@
<%= form_with model: @my_module, url: my_module_path(@my_module, format: :json), data: { remote: :true }, builder: SciFormHelper::SciFormBuilder do |f| %>
<%= f.datetime_picker :due_date,
value: @my_module.due_date,
label: t('my_modules.due_date.label'),
clear: true,
time: true %>
<label class="sci-label">
<%= t('my_modules.due_date.label') %>
</label>
<div id="date-time-picker" class="vue-date-time-picker">
<input ref="input" type="hidden" v-model="date" data-simple-format="true" name="my_module[due_date]" data-default="<%= l(@my_module.due_date, format: :full) if @my_module.due_date %>" />
<date-time-picker class="w-64" @cleared="clearDate" ref="vueDateTime" @change="updateDate" mode="datetime"></date-time-picker>
</div>
<% end %>

View file

@ -6,19 +6,12 @@
</span>
<% if due_date_editable %>
<div class="datetime-picker-container" id="due-date">
<span class="sn-icon sn-icon-calendar"></span>
<input id="calendarDueDate"
type="datetime"
data-toggle='date-time-picker'
class="form-control calendar-input"
readonly
placeholder="<%= t('my_modules.details.no_due_date_placeholder') %>"
data-date-format="<%= datetime_picker_format_full %>"
data-date-locale="<%= I18n.locale %>"
data-date-use-current="false"
data-date-orientation="left"
value="<%= my_module.due_date ? l(my_module.due_date, format: :full) : '' %>"/>
<div id="calendarDueDateContainer">
<input type="hidden" ref="input" v-model="date" data-simple-format="true" id="calendarDueDate" data-default="<%= l(my_module.due_date, format: :full) if my_module.due_date %>
" />
<date-time-picker class="w-full" ref="vueDateTime" :teleport="false" @change="updateDate" mode="datetime" :placeholder="'<%= t('my_modules.details.no_due_date_placeholder') %>'"></date-time-picker>
</div>
<span class="sn-icon sn-icon-close clear-date" data-toggle='clear-date-time-picker' data-target='calendarDueDate'></span>
</div>
<span class="sn-icon sn-icon-close clear-date" data-toggle='clear-date-time-picker' data-target='calendarDueDate'></span>
<% end %>
</span>

View file

@ -6,18 +6,11 @@
</span>
<% if start_date_editable %>
<div class="datetime-picker-container" id="start-date">
<span class="sn-icon sn-icon-calendar"></span>
<input id="calendarStartDate"
type="datetime"
data-toggle='date-time-picker'
class="form-control calendar-input"
readonly
placeholder="<%= t('my_modules.details.no_start_date_placeholder') %>"
data-date-format="<%= datetime_picker_format_full %>"
data-date-locale="<%= I18n.locale %>"
data-date-use-current="false"
value="<%= my_module.started_on ? l(my_module.started_on, format: :full) : '' %>"/>
<div id="calendarStartDateContainer">
<input type="hidden" ref="input" v-model="date" data-simple-format="true" id="calendarStartDate" data-default="<%= l(my_module.started_on, format: :full) if my_module.started_on %>" />
<date-time-picker class="w-full" ref="vueDateTime" :teleport="false" @change="updateDate" mode="datetime" :placeholder="'<%= t('my_modules.details.no_start_date_placeholder') %>'"></date-time-picker>
</div>
<span class="sn-icon sn-icon-close clear-date" data-toggle='clear-date-time-picker' data-target='calendarStartDate'></span>
</div>
<span class="sn-icon sn-icon-close clear-date" data-toggle='clear-date-time-picker' data-target='calendarStartDate'></span>
<% end %>
</span>

View file

@ -11,8 +11,8 @@
<%= f.hidden_field :view_mode, value: view_mode%>
<div class="row">
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
<label class="sci-label"><%= t('experiments.canvas.new_my_module_modal.name') %></label>
<div class="sci-input-container form-group">
<label><%= t('experiments.canvas.new_my_module_modal.name') %></label>
<%= text_field_tag 'my_module[name]', '', placeholder: t('experiments.canvas.new_my_module_modal.name_placeholder'), class: "sci-input-field" %>
</div>
</div>
@ -20,21 +20,12 @@
<div class="row">
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
<div class="form-group">
<div class="sci-input-container right-icon my-module-due-date-container">
<label for="my_module_due_date"><%= t('experiments.canvas.new_my_module_modal.due_date') %></label>
<i class="sn-icon sn-icon-calendar"></i>
<input id="my_module_due_date"
type="datetime"
name="my_module[due_date]"
data-toggle='date-time-picker'
class="sci-input-field calendar-input"
readonly
placeholder="<%= t('experiments.canvas.new_my_module_modal.due_date_placeholder') %>"
data-date-format="<%= datetime_picker_format_full %>"
data-date-locale="<%= I18n.locale %>"
data-date-use-current="false"
data-date-orientation="left"
value=""/>
<div class="my-module-due-date-container">
<label class="sci-label" for="my_module_due_date"><%= t('experiments.canvas.new_my_module_modal.due_date') %></label>
<div id="date-time-picker-my-module" class="vue-date-time-picker w-full">
<input ref="input" type="hidden" data-simple-format="true" class="calendar-input" id="date-time-picker-input" v-model="date" name="my_module[due_date]" />
<date-time-picker class="w-full" @cleared="clearDate" ref="vueDateTime" placeholder="<%= t('experiments.canvas.new_my_module_modal.due_date_placeholder') %>" @change="updateDate" mode="datetime"></date-time-picker>
</div>
</div>
</div>
</div>
@ -44,7 +35,7 @@
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
<%= f.hidden_field :tag_ids%>
<div class="form-group">
<label><%= t('experiments.canvas.new_my_module_modal.assigned_tags_label') %></label>
<label class="sci-label"><%= t('experiments.canvas.new_my_module_modal.assigned_tags_label') %></label>
<%= select_tag 'module-tags-selector', options_for_select([]),
data: {
'tags-create-url': project_create_tag_path(project_id: @experiment.project_id),
@ -58,7 +49,7 @@
<% if can_designate_users_to_new_task?(@experiment) %>
<div class="row">
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
<label><%= t('experiments.canvas.new_my_module_modal.assigned_users') %></label>
<label class="sci-label"><%= t('experiments.canvas.new_my_module_modal.assigned_users') %></label>
<%= select_tag 'my_module[user_ids]',
options_for_select(users.map{ |user|
[

View file

@ -20,5 +20,6 @@
</h1>
</div>
<div id="toolbarWrapper" class="toolbar-row" data-width-breakpoint="750">
<%= render partial: 'projects/index/toolbar' %>
</div>
</div>

View file

@ -1,7 +1,3 @@
<% content_for :head do %>
<meta name="turbolinks-cache-control" content="no-cache">
<% end %>
<% provide(:head_title, t("protocols.index.head_title")) %>
<% if current_team %>
@ -35,7 +31,7 @@
<% end %>
<div id="protocolFileImportModal">
<protocol-file-import-modal
<protocol-file-import-modal
import-url="<%= import_docx_protocols_path %>"
protocol-template-table-url="<%= protocols_path %>"
/>

View file

@ -1,7 +1,3 @@
<% content_for :head do %>
<meta name="turbolinks-cache-control" content="no-cache">
<% end %>
<%= stylesheet_link_tag 'datatables' %>
<% if params[:preview_report_id] %>

View file

@ -1,7 +1,3 @@
<% content_for :head do %>
<meta name="turbolinks-cache-control" content="no-cache">
<% end %>
<% provide(:head_title, t("libraries.show.head_title", library: @repository.name)) %>
<%= stylesheet_link_tag 'datatables' %>
<% provide(:container_class, "no-second-nav-container") %>

View file

@ -2,35 +2,18 @@
<div class="created-on-label">
<label class="sci-label"><%= label %></label>
</div>
<div class="flex items-center gap-5">
<div class="flex items-center gap-4">
<div class="datetime-picker-container flex">
<span class="sn-icon sn-icon-calendar"></span>
<input type="datetime"
id="<%= "#{container_class}_from" %>"
data-linked-max="#<%= "#{container_class}_to" %>"
data-toggle='date-time-picker'
class="form-control calendar-input from-date"
readonly
placeholder="<%= t('filters_modal.from_placeholder') %>"
data-date-format="<%= datetime_picker_format_full %>"
data-date-locale="<%= I18n.locale %>"
data-date-use-current="false"
value=""/>
<div id="<%= "#{container_class}_from_container" %>" class="vue-date-time-picker-filter grow">
<input ref="input" class="from-date" type="hidden" v-model="date" id="<%= "#{container_class}_from" %>" />
<date-time-picker class="w-full" @cleared="clearDate" ref="vueDateTime" @change="updateDate" mode="datetime" placeholder="<%= t('filters_modal.from_placeholder') %>"></date-time-picker>
</div>
</div>
<div class="datetime-picker-container flex">
<span class="sn-icon sn-icon-calendar"></span>
<input type="datetime"
data-toggle='date-time-picker'
id="<%= "#{container_class}_to" %>"
data-linked-min="#<%= "#{container_class}_from" %>"
class="form-control calendar-input to-date"
readonly
placeholder="<%= t('filters_modal.to_placeholder') %>"
data-date-format="<%= datetime_picker_format_full %>"
data-date-locale="<%= I18n.locale %>"
data-date-use-current="false"
data-date-orientation="left"
value=""/>
<div id="<%= "#{container_class}_to_container" %>" class="vue-date-time-picker-filter grow">
<input ref="input" class="to-date" type="hidden" v-model="date" id="<%= "#{container_class}_to" %>" />
<date-time-picker class="w-full" @cleared="clearDate" ref="vueDateTime" @change="updateDate" mode="datetime" placeholder="<%= t('filters_modal.to_placeholder') %>"></date-time-picker>
</div>
</div>
</div>
</div>

View file

@ -1,6 +1,3 @@
<% content_for :head do %>
<meta name="turbolinks-cache-control" content="no-cache">
<% end %>
<% provide(:head_title, t("users.settings.teams.head_title")) %>
<% provide(:container_class, "no-second-nav-container") %>

View file

@ -1,7 +1,3 @@
<% content_for :head do %>
<meta name="turbolinks-cache-control" content="no-cache">
<% end %>
<% provide(:head_title, t("users.settings.teams.head_title")) %>
<% provide(:container_class, "no-second-nav-container") %>

View file

@ -44,7 +44,8 @@ const entryList = {
vue_navigation_breadcrumbs: './app/javascript/packs/vue/navigation/breadcrumbs.js',
vue_protocol_file_import_modal: './app/javascript/packs/vue/protocol_file_import_modal.js',
vue_components_export_stock_consumption_modal: './app/javascript/packs/vue/export_stock_consumption_modal.js',
vue_components_manage_stock_value_modal: './app/javascript/packs/vue/manage_stock_value_modal.js'
vue_components_manage_stock_value_modal: './app/javascript/packs/vue/manage_stock_value_modal.js',
vue_legacy_datetime_picker: './app/javascript/packs/vue/legacy/datetime_picker.js',
}
// Engine pack loading based on https://github.com/rails/webpacker/issues/348#issuecomment-635480949

View file

@ -31,9 +31,13 @@
"@fortawesome/fontawesome-free": "^5.2.0",
"@joeattardi/emoji-button": "^4.6.2",
"@teselagen/ove": "^0.3.23",
"@vue/compiler-sfc": "^3.3.4",
"@vuepic/vue-datepicker": "^7.2.0",
"@vueuse/components": "^10.5.0",
"@vueuse/core": "^10.5.0",
"ajv": "6.12.6",
"autoprefixer": "10.4.14",
"axios": "^1.4.0",
"axios": "^1.6.0",
"babel-loader": "^8.2.5",
"babel-plugin-macros": "^3.1.0",
"bootstrap": "^3.4.1",
@ -78,14 +82,11 @@
"tui-color-picker": "^2.2.0",
"tui-image-editor": "github:scinote-eln/tui.image-editor#3_15_2_updated",
"twemoji": "^12.1.4",
"vue": "^2.6.11",
"vue-loader": "^15.9.1",
"vue-resizable": "2.1.3",
"vue-template-compiler": "^2.6.12",
"vue-turbolinks": "^2.2.1",
"vue2-perfect-scrollbar": "^1.5.56",
"vue2-scrollspy": "^2.3.1",
"vuedraggable": "^2.24.3",
"vue": "^3.3.4",
"vue-loader": "^16.0.0",
"vue3-draggable-resizable": "^1.6.5",
"vue3-perfect-scrollbar": "^1.6.1",
"vuedraggable": "^4.1.0",
"webpack": "^5.64.4",
"webpack-cli": "^4.10.0",
"webpack-manifest-plugin": "^1.3.2",

View file

@ -0,0 +1,9 @@
<svg width="16" height="18" viewBox="0 0 16 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M4 11C4.26 11 4.49 10.9 4.69 10.7C4.89 10.5 5 10.26 5 9.98C5 9.72 4.9 9.49 4.69 9.29C4.49 9.09 4.25 8.99 4 8.99C3.75 8.99 3.51 9.09 3.31 9.29C3.11 9.49 3 9.72 3 9.98C3 10.26 3.1 10.5 3.31 10.7C3.51 10.9 3.74 11 4 11Z" fill="#1D2939"/>
<path d="M4 15C4.26 15 4.49 14.9 4.69 14.7C4.89 14.5 5 14.26 5 13.98C5 13.72 4.9 13.49 4.69 13.29C4.49 13.09 4.25 12.99 4 12.99C3.75 12.99 3.51 13.09 3.31 13.29C3.11 13.49 3 13.72 3 13.98C3 14.26 3.1 14.5 3.31 14.7C3.51 14.9 3.74 15 4 15Z" fill="#1D2939"/>
<path d="M12 11C12.26 11 12.49 10.9 12.69 10.7C12.89 10.5 13 10.26 13 9.98C13 9.72 12.9 9.49 12.69 9.29C12.49 9.09 12.25 8.99 12 8.99C11.75 8.99 11.51 9.09 11.31 9.29C11.11 9.49 11 9.72 11 9.98C11 10.26 11.1 10.5 11.31 10.7C11.51 10.9 11.74 11 12 11Z" fill="#1D2939"/>
<path d="M12 15C12.26 15 12.49 14.9 12.69 14.7C12.89 14.5 13 14.26 13 13.98C13 13.72 12.9 13.49 12.69 13.29C12.49 13.09 12.25 12.99 12 12.99C11.75 12.99 11.51 13.09 11.31 13.29C11.11 13.49 11 13.72 11 13.98C11 14.26 11.1 14.5 11.31 14.7C11.51 14.9 11.74 15 12 15Z" fill="#1D2939"/>
<path d="M8.02 11C8.28 11 8.51 10.9 8.71 10.7C8.91 10.5 9.02 10.26 9.02 9.98C9.02 9.72 8.92 9.49 8.71 9.29C8.51 9.09 8.27 8.99 8.02 8.99C7.77 8.99 7.53 9.09 7.33 9.29C7.13 9.49 7.02 9.72 7.02 9.98C7.02 10.26 7.12 10.5 7.33 10.7C7.53 10.9 7.76 11 8.02 11Z" fill="#1D2939"/>
<path d="M8.02 15C8.28 15 8.51 14.9 8.71 14.7C8.91 14.5 9.02 14.26 9.02 13.98C9.02 13.72 8.92 13.49 8.71 13.29C8.51 13.09 8.27 12.99 8.02 12.99C7.77 12.99 7.53 13.09 7.33 13.29C7.13 13.49 7.02 13.72 7.02 13.98C7.02 14.26 7.12 14.5 7.33 14.7C7.53 14.9 7.76 15 8.02 15Z" fill="#1D2939"/>
<path d="M14 2H12V0H11V2H5V0H4V2H2C0.9 2 0 2.9 0 4V16C0 17.1 0.9 18 2 18H14C15.1 18 16 17.1 16 16V4C16 2.9 15.1 2 14 2ZM15 16C15 16.55 14.55 17 14 17H2C1.45 17 1 16.55 1 16V7H15V16ZM1 6V4C1 3.45 1.45 3 2 3H14C14.55 3 15 3.45 15 4V6H1Z" fill="#1D2939"/>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View file

@ -0,0 +1,3 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12.1256 13.35L12.8256 12.65L8.97559 8.8V4H7.97559V9.2L12.1256 13.35ZM9 18C7.75 18 6.57933 17.7627 5.488 17.288C4.396 16.8127 3.446 16.1707 2.638 15.362C1.82933 14.554 1.18733 13.604 0.712 12.512C0.237333 11.4207 0 10.25 0 9C0 7.75 0.237333 6.579 0.712 5.487C1.18733 4.39567 1.82933 3.44567 2.638 2.637C3.446 1.829 4.396 1.18733 5.488 0.712C6.57933 0.237333 7.75 0 9 0C10.25 0 11.421 0.237333 12.513 0.712C13.6043 1.18733 14.5543 1.829 15.363 2.637C16.171 3.44567 16.8127 4.39567 17.288 5.487C17.7627 6.579 18 7.75 18 9C18 10.25 17.7627 11.4207 17.288 12.512C16.8127 13.604 16.171 14.554 15.363 15.362C14.5543 16.1707 13.6043 16.8127 12.513 17.288C11.421 17.7627 10.25 18 9 18ZM9 17C11.2167 17 13.1043 16.221 14.663 14.663C16.221 13.1043 17 11.2167 17 9C17 6.78333 16.221 4.89567 14.663 3.337C13.1043 1.779 11.2167 1 9 1C6.78333 1 4.896 1.779 3.338 3.337C1.77933 4.89567 1 6.78333 1 9C1 11.2167 1.77933 13.1043 3.338 14.663C4.896 16.221 6.78333 17 9 17Z" fill="#1D2939"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -0,0 +1,5 @@
<svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="down">
<path id="down_2" d="M7.02502 9.69999L7.72502 8.99999L12.685 13.96L17.635 8.99999L18.335 9.69999L12.685 15.36L7.02502 9.69999Z" fill="#1D2939"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 267 B

View file

@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M13.3 16.6L8 11.3L13.3 6L14 6.7L9.4 11.3L14 15.9L13.3 16.6Z" fill="#1D2939"/>
</svg>

After

Width:  |  Height:  |  Size: 190 B

View file

@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.7 16.6L9 15.9L13.6 11.3L9 6.7L9.7 6L15 11.3L9.7 16.6Z" fill="#1D2939"/>
</svg>

After

Width:  |  Height:  |  Size: 187 B

View file

@ -0,0 +1,3 @@
<svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M18.335 14.135L17.635 14.835L12.675 9.87498L7.72502 14.835L7.02502 14.135L12.675 8.47498L18.335 14.135Z" fill="#1D2939"/>
</svg>

After

Width:  |  Height:  |  Size: 234 B

Some files were not shown because too many files have changed in this diff Show more