diff --git a/resources/assets/js/countdown.js b/resources/assets/js/countdown.js index 99f7166b..1b3c2a51 100644 --- a/resources/assets/js/countdown.js +++ b/resources/assets/js/countdown.js @@ -2,79 +2,79 @@ const lang = document.documentElement.getAttribute('lang'); const templateFuture = 'in %value %unit'; const templatePast = lang === 'en' - ? '%value %unit ago' - : 'vor %value %unit'; + ? '%value %unit ago' + : 'vor %value %unit'; const yearUnits = lang === 'en' - ? ['year', 'years'] - : ['Jahr', 'Jahren']; + ? ['year', 'years'] + : ['Jahr', 'Jahren']; const monthUnits = lang === 'en' - ? ['month', 'months'] - : ['Monat', 'Monaten']; + ? ['month', 'months'] + : ['Monat', 'Monaten']; const dayUnits = lang === 'en' - ? ['day', 'days'] - : ['Tag', 'Tagen']; + ? ['day', 'days'] + : ['Tag', 'Tagen']; const hourUnits = lang === 'en' - ? ['hour', 'hours'] - : ['Stunde', 'Stunden']; + ? ['hour', 'hours'] + : ['Stunde', 'Stunden']; const minuteUnits = lang === 'en' - ? ['minute', 'minutes'] - : ['Minute', 'Minuten']; + ? ['minute', 'minutes'] + : ['Minute', 'Minuten']; const secondUnits = lang === 'en' - ? ['second', 'seconds'] - : ['Sekunde', 'Sekunden']; + ? ['second', 'seconds'] + : ['Sekunde', 'Sekunden']; const nowString = lang === 'en' ? 'now' : 'jetzt'; const secondsHour = 60 * 60; const timeFrames = [ - [365 * 24 * 60 * 60, yearUnits], - [30 * 24 * 60 * 60, monthUnits], - [24 * 60 * 60, dayUnits], - [secondsHour, hourUnits], - [60, minuteUnits], - [1, secondUnits], + [365 * 24 * 60 * 60, yearUnits], + [30 * 24 * 60 * 60, monthUnits], + [24 * 60 * 60, dayUnits], + [secondsHour, hourUnits], + [60, minuteUnits], + [1, secondUnits], ]; function formatFromNow(timestamp) { - const now = Date.now() / 1000; - const diff = Math.abs(timestamp - now); - const ago = now > timestamp; + const now = Date.now() / 1000; + const diff = Math.abs(timestamp - now); + const ago = now > timestamp; - for (const [duration, [singular, plural]] of timeFrames) { - const value = diff < secondsHour - ? Math.floor(diff / duration) - : Math.round(diff / duration); + for (const [duration, [singular, plural]] of timeFrames) { + const value = diff < secondsHour + ? Math.floor(diff / duration) + : Math.round(diff / duration); - if (value) { - const template = ago ? templatePast : templateFuture; - const unit = value === 1 ? singular : plural; - return template - .replace('%value', value) - .replace('%unit', unit); - } + if (value) { + const template = ago ? templatePast : templateFuture; + const unit = value === 1 ? singular : plural; + return template + .replace('%value', value) + .replace('%unit', unit); } + } - return nowString; + return nowString; } /** * Initialises all countdown fields on the page. */ $(function () { - $.each($('[data-countdown-ts]'), function (i, e) { - const span = $(e); - const timestamp = span.data('countdown-ts'); - const text = span.html(); - span.html(text.replace('%c', formatFromNow(timestamp))); - setInterval(function () { - span.html(text.replace('%c', formatFromNow(timestamp))); - }, 1000); - }); + $.each($('[data-countdown-ts]'), function (i, e) { + const span = $(e); + const timestamp = span.data('countdown-ts'); + const text = span.html(); + span.html(text.replace('%c', formatFromNow(timestamp))); + setInterval(function () { + span.html(text.replace('%c', formatFromNow(timestamp))); + }, 1000); + }); }); diff --git a/resources/assets/js/date.js b/resources/assets/js/date.js index 6cdb8d52..1f094527 100644 --- a/resources/assets/js/date.js +++ b/resources/assets/js/date.js @@ -5,9 +5,9 @@ * @returns {string|undefined} Formatted time or undefined for non-Date */ export const formatTime = (date) => { - if (!date instanceof Date) return; + if (!date instanceof Date) return; - return String(date.getHours()).padStart(2, '0') + ':' + return String(date.getHours()).padStart(2, '0') + ':' + String(date.getMinutes()).padStart(2, '0'); } @@ -18,9 +18,9 @@ export const formatTime = (date) => { * @returns {string|undefined} Formatted date or undefined for non-Date */ export const formatDay = (date) => { - if (!date instanceof Date) return; + if (!date instanceof Date) return; - return String(date.getFullYear()) + '-' + return String(date.getFullYear()) + '-' + String(date.getMonth() + 1).padStart(2, '0') + '-' + String(date.getDate()).padStart(2, '0'); } diff --git a/resources/assets/js/forms.js b/resources/assets/js/forms.js index 25668f01..6002d132 100644 --- a/resources/assets/js/forms.js +++ b/resources/assets/js/forms.js @@ -8,9 +8,9 @@ import { formatDay, formatTime } from './date'; * @param {boolean} checked True if the checkboxes should be checked */ global.checkAll = (id, checked) => { - $('#' + id + ' input[type="checkbox"]').each(function () { - this.checked = checked; - }); + $('#' + id + ' input[type="checkbox"]').each(function () { + this.checked = checked; + }); }; /** @@ -20,9 +20,9 @@ global.checkAll = (id, checked) => { * @param {list} shiftsList A list of numbers */ global.checkOwnTypes = (id, shiftsList) => { - $('#' + id + ' input[type="checkbox"]').each(function () { - this.checked = $.inArray(parseInt(this.value), shiftsList) != -1; - }); + $('#' + id + ' input[type="checkbox"]').each(function () { + this.checked = $.inArray(parseInt(this.value), shiftsList) != -1; + }); }; /** @@ -36,63 +36,63 @@ global.checkOwnTypes = (id, shiftsList) => { * @param {Date} to */ global.setInput = (from, to) => { - const fromDay = $('#start_day'); - const fromTime = $('#start_time'); - const toDay = $('#end_day'); - const toTime = $('#end_time'); + const fromDay = $('#start_day'); + const fromTime = $('#start_time'); + const toDay = $('#end_day'); + const toTime = $('#end_time'); - if (!fromDay || !fromTime || !toDay || !toTime) { - console.warn('cannot set input date because of missing field'); - return; - } + if (!fromDay || !fromTime || !toDay || !toTime) { + console.warn('cannot set input date because of missing field'); + return; + } - fromDay.val(formatDay(from)).trigger('change'); - fromTime.val(formatTime(from)); + fromDay.val(formatDay(from)).trigger('change'); + fromTime.val(formatTime(from)); - toDay.val(formatDay(to)).trigger('change'); - toTime.val(formatTime(to)); + toDay.val(formatDay(to)).trigger('change'); + toTime.val(formatTime(to)); }; global.setDay = (days) => { - days = days || 0; + days = days || 0; - const from = new Date(); - from.setHours(0, 0, 0, 0); + const from = new Date(); + from.setHours(0, 0, 0, 0); - // add days, Date handles the overflow - from.setDate(from.getDate() + days); + // add days, Date handles the overflow + from.setDate(from.getDate() + days); - const to = new Date(from); - to.setHours(23, 59); + const to = new Date(from); + to.setHours(23, 59); - setInput(from, to); + setInput(from, to); }; global.setHours = (hours) => { - hours = hours || 1; + hours = hours || 1; - const from = new Date(); - const to = new Date(from); + const from = new Date(); + const to = new Date(from); - // convert hours to add to milliseconds (60 minutes * 60 seconds * 1000 for milliseconds) - const msToAdd = hours * 60 * 60 * 1000; - to.setTime(to.getTime() + msToAdd, 'h'); - if (to < from) { - setInput(to, from); - return; - } + // convert hours to add to milliseconds (60 minutes * 60 seconds * 1000 for milliseconds) + const msToAdd = hours * 60 * 60 * 1000; + to.setTime(to.getTime() + msToAdd, 'h'); + if (to < from) { + setInput(to, from); + return; + } - setInput(from, to); + setInput(from, to); }; $(function () { - /** + /** * Disable every submit button after clicking (to prevent double-clicking) */ - $('form').submit(function (ev) { - $('input[type="submit"]').prop('readonly', true).addClass('disabled'); - return true; - }); + $('form').submit(function (ev) { + $('input[type="submit"]').prop('readonly', true).addClass('disabled'); + return true; + }); }); @@ -100,44 +100,44 @@ $(function () { * Button to set current time in time input fields. */ $(function () { - $('.input-group.time').each(function () { - const elem = $(this); - elem.find('button').on('click', function () { - const now = new Date(); - const input = elem.children('input').first(); - input.val(formatTime(now)); - const daySelector = $('#' + input.attr('id').replace('time', 'day')); - const days = daySelector.children('option'); - const yyyyMMDD = formatDay(now); - days.each(function (i) { - if ($(days[i]).val() === yyyyMMDD) { - daySelector.val($(days[i]).val()); - return false; - } - }); - }); + $('.input-group.time').each(function () { + const elem = $(this); + elem.find('button').on('click', function () { + const now = new Date(); + const input = elem.children('input').first(); + input.val(formatTime(now)); + const daySelector = $('#' + input.attr('id').replace('time', 'day')); + const days = daySelector.children('option'); + const yyyyMMDD = formatDay(now); + days.each(function (i) { + if ($(days[i]).val() === yyyyMMDD) { + daySelector.val($(days[i]).val()); + return false; + } + }); }); + }); }); $(function () { - $('select').select2({ - theme: 'bootstrap-5', - }); + $('select').select2({ + theme: 'bootstrap-5', + }); }) /** * Show oauth buttons on welcome title click */ $(function () { - $('#welcome-title').on('click', function () { - $('.btn-group.btn-group .btn.d-none').removeClass('d-none'); - }); - $('#settings-title').on('click', function () { - $('.user-settings .nav-item').removeClass('d-none'); - }); - $('#oauth-settings-title').on('click', function () { - $('table tr.d-none').removeClass('d-none'); - }); + $('#welcome-title').on('click', function () { + $('.btn-group.btn-group .btn.d-none').removeClass('d-none'); + }); + $('#settings-title').on('click', function () { + $('.user-settings .nav-item').removeClass('d-none'); + }); + $('#oauth-settings-title').on('click', function () { + $('table tr.d-none').removeClass('d-none'); + }); }); /** @@ -146,24 +146,24 @@ $(function () { * Uses DOMContentLoaded to prevent flickering */ window.addEventListener('DOMContentLoaded', () => { - const filter = document.getElementById('collapseShiftsFilterSelect'); - if (!filter || localStorage.getItem('collapseShiftsFilterSelect') !== 'hidden') { - return; - } + const filter = document.getElementById('collapseShiftsFilterSelect'); + if (!filter || localStorage.getItem('collapseShiftsFilterSelect') !== 'hidden') { + return; + } - filter.classList.remove('show'); + filter.classList.remove('show'); }); $(() => { - if (typeof (localStorage) === 'undefined') { - return; - } + if (typeof (localStorage) === 'undefined') { + return; + } - const onChange = (e) => { - localStorage.setItem('collapseShiftsFilterSelect', e.type); - }; + const onChange = (e) => { + localStorage.setItem('collapseShiftsFilterSelect', e.type); + }; - $('#collapseShiftsFilterSelect') - .on('hidden.bs.collapse', onChange) - .on('shown.bs.collapse', onChange); + $('#collapseShiftsFilterSelect') + .on('hidden.bs.collapse', onChange) + .on('shown.bs.collapse', onChange); }); diff --git a/resources/assets/js/sticky-headers.js b/resources/assets/js/sticky-headers.js index e227d59d..b1279d9d 100644 --- a/resources/assets/js/sticky-headers.js +++ b/resources/assets/js/sticky-headers.js @@ -2,31 +2,31 @@ * Enables the fixed headers and time lane for the shift-calendar and datatables */ $(function () { - if ($('.shift-calendar').length) { - const timeLanes = $('.shift-calendar .time'); - const headers = $('.shift-calendar .header'); - const topReference = $('.container-fluid .row'); + if ($('.shift-calendar').length) { + const timeLanes = $('.shift-calendar .time'); + const headers = $('.shift-calendar .header'); + const topReference = $('.container-fluid .row'); + timeLanes.css({ + 'position': 'relative', + 'z-index': 999 + }); + headers.css({ + 'position': 'relative', + 'z-index': 900 + }); + $(window).scroll( + function () { + const top = headers.parent().offset().top; + const left = 15; timeLanes.css({ - 'position': 'relative', - 'z-index': 999 + 'left': Math.max(0, $(window).scrollLeft() - left) + 'px' }); headers.css({ - 'position': 'relative', - 'z-index': 900 - }); - $(window).scroll( - function () { - const top = headers.parent().offset().top; - const left = 15; - timeLanes.css({ - 'left': Math.max(0, $(window).scrollLeft() - left) + 'px' - }); - headers.css({ - 'top': Math.max(0, $(window).scrollTop() - top + 'top': Math.max(0, $(window).scrollTop() - top - 13 + topReference.offset().top) + 'px' - }); - }); - } + }); + }); + } }); diff --git a/resources/assets/js/vendor.js b/resources/assets/js/vendor.js index 9ea07a1b..5d89b71b 100644 --- a/resources/assets/js/vendor.js +++ b/resources/assets/js/vendor.js @@ -6,5 +6,5 @@ require('./sticky-headers'); require('./countdown'); $.ajaxSetup({ - headers: {'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')} + headers: {'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')} }); diff --git a/webpack.config.js b/webpack.config.js index c3d6f121..b407cfc6 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -28,7 +28,7 @@ const plugins = [ let themeFileNameRegex = /theme\d+/; if (process.env.THEMES) { - themeFileNameRegex = new RegExp(`theme(${process.env.THEMES.replace(/,/g, '|')})\\.`); + themeFileNameRegex = new RegExp(`theme(${process.env.THEMES.replace(/,/g, '|')})\\.`); } const themePath = path.resolve('resources/assets/themes');