From ec69cca42a6f5f97f0919f5fda703e25330697bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rajmund=20Hru=C5=A1ka?= <rajmund.hruska@cesnet.cz> Date: Tue, 16 May 2023 16:04:02 +0200 Subject: [PATCH] Feature: Replace eonasdan-bootstrap-datetimepicker with tempus dominus (Redmine issue: #7651) --- Gruntfile.js | 10 +- .../design_bs3/templates/_layout.html | 4 +- .../templates/_layout_events_search.html | 8 +- lib/hawat/static/css/hawat.css | 5 + lib/hawat/static/js/hawat-jquery.js | 197 ++++++++---------- package.json | 2 +- yarn.lock | 14 +- 7 files changed, 115 insertions(+), 125 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index a2c6cd72..ea13e74e 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -182,20 +182,20 @@ module.exports = function(grunt) { src: './*', dest: '<%= project_paths.web_static_dir %>vendor/bootstrap-select/js/' }, - // ----- eonasdan-bootstrap-datetimepicker + // ----- tempus-dominus { expand: true, flatten: true, - cwd: 'node_modules/eonasdan-bootstrap-datetimepicker/build/css/', + cwd: 'node_modules/@eonasdan/tempus-dominus/dist/css/', src: './*', - dest: '<%= project_paths.web_static_dir %>vendor/bootstrap-datetimepicker/css/' + dest: '<%= project_paths.web_static_dir %>vendor/@eonasdan/tempus-dominus/css/' }, { expand: true, flatten: true, - cwd: 'node_modules/eonasdan-bootstrap-datetimepicker/build/js/', + cwd: 'node_modules/@eonasdan/tempus-dominus/dist/js/', src: './*', - dest: '<%= project_paths.web_static_dir %>vendor/bootstrap-datetimepicker/js/' + dest: '<%= project_paths.web_static_dir %>vendor/@eonasdan/tempus-dominus/js/' }, // ----- Font-Awesome Free { diff --git a/lib/hawat/blueprints/design_bs3/templates/_layout.html b/lib/hawat/blueprints/design_bs3/templates/_layout.html index 48a42386..a49dd356 100644 --- a/lib/hawat/blueprints/design_bs3/templates/_layout.html +++ b/lib/hawat/blueprints/design_bs3/templates/_layout.html @@ -34,7 +34,7 @@ <link rel="stylesheet" href="{{ url_for('static', filename='vendor/bootstrap/css/bootstrap.min.css') }}"> <link rel="stylesheet" href="{{ url_for('static', filename='vendor/bootstrap/css/bootstrap-theme.min.css') }}"> <link rel="stylesheet" href="{{ url_for('static', filename='vendor/bootstrap-select/css/bootstrap-select.min.css') }}"> - <link rel="stylesheet" href="{{ url_for('static', filename='vendor/bootstrap-datetimepicker/css/bootstrap-datetimepicker.min.css') }}"> + <link rel="stylesheet" href="{{ url_for('static', filename='vendor/@eonasdan/tempus-dominus/css/tempus-dominus.min.css') }}"> <!-- NVD3 CSS --> <link rel="stylesheet" href="{{ url_for('static', filename='vendor/nvd3/css/nv.d3.min.css') }}"> @@ -283,7 +283,7 @@ <!-- Optional JavaScript ----------------------------------------------> <script src="{{ url_for('static', filename='vendor/bootstrap/js/bootstrap.min.js') }}"></script> <script src="{{ url_for('static', filename='vendor/bootstrap-select/js/bootstrap-select.min.js') }}"></script> - <script src="{{ url_for('static', filename='vendor/bootstrap-datetimepicker/js/bootstrap-datetimepicker.min.js') }}"></script> + <script src="{{ url_for('static', filename='vendor/@eonasdan/tempus-dominus/js/tempus-dominus.min.js') }}"></script> <script src="{{ url_for('static', filename='js/hawat-jquery.js') }}"></script> {%- endblock bodyjs %} diff --git a/lib/hawat/blueprints/design_bs3/templates/_layout_events_search.html b/lib/hawat/blueprints/design_bs3/templates/_layout_events_search.html index d608c525..80acffcf 100644 --- a/lib/hawat/blueprints/design_bs3/templates/_layout_events_search.html +++ b/lib/hawat/blueprints/design_bs3/templates/_layout_events_search.html @@ -86,7 +86,7 @@ <div class="form-group{{ frmctrlhdn }}" id="form-group-detecttime"> <div class="col-sm-6"> {%- call macros_form.render_form_label_help_html(g.search_form.dt_from) %}{%- endcall %} - <div id="datetimepicker-from-1" class="input-group date datetimepicker-ymdhms-from widget-datetimepicker"> + <div id="datetimepicker-from" class="input-group date"> {{ g.search_form.dt_from(class_='form-control', disabled=frmctrldsb) }} <span class="input-group-addon"> {{ get_icon('calendar') }} @@ -97,7 +97,7 @@ </div> <div class="col-sm-6"> {%- call macros_form.render_form_label_help_html(g.search_form.dt_to) %}{%- endcall %} - <div id="datetimepicker-to-1" class="input-group date datetimepicker-ymdhms-to widget-datetimepicker"> + <div id="datetimepicker-to" class="input-group date"> {{ g.search_form.dt_to(class_='form-control', disabled=frmctrldsb) }} <span class="input-group-addon"> {{ get_icon('calendar') }} @@ -116,7 +116,7 @@ {{ macros_form.render_help_idea_reference() }} {{ macros_form.render_help_datetime() }} {%- endcall %} - <div id="datetimepicker-from-2" class="input-group date datetimepicker-ymdhms-from widget-datetimepicker"> + <div id="datetimepicker-from-2" class="input-group date"> {{ g.search_form.st_from(class_='form-control', disabled=frmctrldsb) }} <span class="input-group-addon"> {{ get_icon('calendar') }} @@ -130,7 +130,7 @@ {{ macros_form.render_help_idea_reference() }} {{ macros_form.render_help_datetime() }} {%- endcall %} - <div id="datetimepicker-to-2" class="input-group date datetimepicker-ymdhms-to widget-datetimepicker"> + <div id="datetimepicker-to-2" class="input-group date"> {{ g.search_form.st_to(class_='form-control', disabled=frmctrldsb) }} <span class="input-group-addon"> {{ get_icon('calendar') }} diff --git a/lib/hawat/static/css/hawat.css b/lib/hawat/static/css/hawat.css index 0f025229..ab9a983c 100644 --- a/lib/hawat/static/css/hawat.css +++ b/lib/hawat/static/css/hawat.css @@ -184,6 +184,11 @@ body { overflow-x: auto; } +/* Change the default width of the datetime picker box. */ +.tempus-dominus-widget { + width: 25rem; +} + /******************************************************************************* Custom style for timeline dataset tables. diff --git a/lib/hawat/static/js/hawat-jquery.js b/lib/hawat/static/js/hawat-jquery.js index 0c6cbb9a..6806954b 100644 --- a/lib/hawat/static/js/hawat-jquery.js +++ b/lib/hawat/static/js/hawat-jquery.js @@ -6,113 +6,100 @@ $(function() { - // Initialize date and datetime picker components. - //$('.datepicker').datetimepicker({ - // //locale: 'en', - // format: 'YYYY-MM-DD' - //}); - //$('.datetimepicker').datetimepicker({ - // //locale: 'en', - // format: 'YYYY-MM-DD HH:mm:ss' - //}); - - // Initialize linked date and datetime picker components. - $('#datetimepicker-from').datetimepicker({ - locale: GLOBAL_LOCALE, - format: 'YYYY-MM-DD HH:mm:ss', - icons: { - time: "fas fa-fw fa-clock", - date: "fas fa-fw fa-calendar-alt", - up: "fas fa-fw fa-arrow-up", - down: "fas fa-fw fa-arrow-down" - } - }); - $('#datetimepicker-to').datetimepicker({ - useCurrent: false, //Important! See issue #1075 - locale: GLOBAL_LOCALE, - format: 'YYYY-MM-DD HH:mm:ss', - icons: { - time: "fas fa-fw fa-clock", - date: "fas fa-fw fa-calendar-alt", - up: "fas fa-fw fa-arrow-up", - down: "fas fa-fw fa-arrow-down" - } - }); - $("#datetimepicker-from").on("dp.change", function (e) { - $('#datetimepicker-to').data("DateTimePicker").minDate(e.date); - }); - $("#datetimepicker-to").on("dp.change", function (e) { - $('#datetimepicker-from').data("DateTimePicker").maxDate(e.date); - }); - - // Initialize linked date and datetime picker components. - $('.datetimepicker-ymdhms-from').datetimepicker({ - locale: GLOBAL_LOCALE, - format: 'YYYY-MM-DD HH:mm:ss', - icons: { - time: "fas fa-fw fa-clock", - date: "fas fa-fw fa-calendar-alt", - up: "fas fa-fw fa-arrow-up", - down: "fas fa-fw fa-arrow-down" - } - }); - $('.datetimepicker-ymdhms-to').datetimepicker({ - useCurrent: false, //Important! See issue #1075 - locale: GLOBAL_LOCALE, - format: 'YYYY-MM-DD HH:mm:ss', - icons: { - time: "fas fa-fw fa-clock", - date: "fas fa-fw fa-calendar-alt", - up: "fas fa-fw fa-arrow-up", - down: "fas fa-fw fa-arrow-down" + const createTempusDominusInstance = (elementId, options) => { + const element = document.getElementById(elementId); + return new tempusDominus.TempusDominus(element, options); + }; + const createCommonOptions = (_format, _useSeconds) => { + return { + localization: { + locale: GLOBAL_LOCALE, + format: _format, + startOfTheWeek: 1, + hourCycle: 'h23' + }, + display: { + icons: { + time: "fas fa-fw fa-clock", + date: "fas fa-fw fa-calendar-alt", + up: "fas fa-fw fa-arrow-up", + down: "fas fa-fw fa-arrow-down", + previous: 'fas fa-chevron-left', + next: 'fas fa-chevron-right' + }, + components: { + seconds: _useSeconds + } + } } - }); - $("#datetimepicker-from-1").on("dp.change", function (e) { - $('#datetimepicker-to-1').data("DateTimePicker").minDate(e.date); - }); - $("#datetimepicker-to-1").on("dp.change", function (e) { - $('#datetimepicker-from-1').data("DateTimePicker").maxDate(e.date); - }); - $("#datetimepicker-from-2").on("dp.change", function (e) { - $('#datetimepicker-to-2').data("DateTimePicker").minDate(e.date); - }); - $("#datetimepicker-to-2").on("dp.change", function (e) { - $('#datetimepicker-from-2').data("DateTimePicker").maxDate(e.date); - }); + }; - // Disable built-in JS form validation in case the form`s cancel button is clicked.` - $('input[type="submit"][value="Cancel"]').click(function(){ - $(this).parents('form:first').attr('novalidate', 'novalidate'); - }); - - // Initialize linked date and datetime picker components. - $('#datetimepicker-hm-from').datetimepicker({ - locale: GLOBAL_LOCALE, - format: 'YYYY-MM-DD HH:mm', - icons: { - time: "fas fa-fw fa-clock", - date: "fas fa-fw fa-calendar-alt", - up: "fas fa-fw fa-arrow-up", - down: "fas fa-fw fa-arrow-down" - } - }); - $('#datetimepicker-hm-to').datetimepicker({ - useCurrent: false, //Important! See issue #1075 - locale: GLOBAL_LOCALE, - format: 'YYYY-MM-DD HH:mm', - icons: { - time: "fas fa-fw fa-clock", - date: "fas fa-fw fa-calendar-alt", - up: "fas fa-fw fa-arrow-up", - down: "fas fa-fw fa-arrow-down" - } - }); - $("#datetimepicker-hm-from").on("dp.change", function (e) { - $('#datetimepicker-hm-to').data("DateTimePicker").minDate(e.date); - }); - $("#datetimepicker-hm-to").on("dp.change", function (e) { - $('#datetimepicker-hm-from').data("DateTimePicker").maxDate(e.date); - }); + // Initialize date and datetime picker components. + const commonOptionsSeconds = createCommonOptions('yyyy-MM-dd HH:mm:ss', true); + if (document.getElementById('datetimepicker-from') && document.getElementById('datetimepicker-to')) { + const linked_from_1 = createTempusDominusInstance('datetimepicker-from', commonOptionsSeconds); + const linked_to_1 = createTempusDominusInstance('datetimepicker-to', { + useCurrent: false, + ...commonOptionsSeconds + }); + document.getElementById('datetimepicker-from').addEventListener(tempusDominus.Namespace.events.change, (e) => { + linked_to_1.updateOptions({ + restrictions: { + minDate: e.detail.date, + }, + }); + }); + document.getElementById('datetimepicker-to').addEventListener(tempusDominus.Namespace.events.change, (e) => { + linked_from_1.updateOptions({ + restrictions: { + maxDate: e.detail.date, + }, + }); + }); + } + if (document.getElementById('datetimepicker-from-2') && document.getElementById('datetimepicker-to-2')) { + const linked_from_2 = createTempusDominusInstance('datetimepicker-from-2', commonOptionsSeconds); + const linked_to_2 = createTempusDominusInstance('datetimepicker-to-2', { + useCurrent: false, + ...commonOptionsSeconds + }); + document.getElementById('datetimepicker-from-2').addEventListener(tempusDominus.Namespace.events.change, (e) => { + linked_to_2.updateOptions({ + restrictions: { + minDate: e.detail.date, + }, + }); + }); + document.getElementById('datetimepicker-to-2').addEventListener(tempusDominus.Namespace.events.change, (e) => { + linked_from_2.updateOptions({ + restrictions: { + maxDate: e.detail.date, + }, + }); + }); + } + const commonOptions = createCommonOptions('yyyy-MM-dd HH:mm', false); + if (document.getElementById('datetimepicker-hm-from') && document.getElementById('datetimepicker-hm-to')) { + const linked_from = createTempusDominusInstance('datetimepicker-hm-from', commonOptions); + const linked_to = createTempusDominusInstance('datetimepicker-hm-to', { + useCurrent: false, + ...commonOptions + }); + document.getElementById('datetimepicker-hm-from').addEventListener(tempusDominus.Namespace.events.change, (e) => { + linked_to.updateOptions({ + restrictions: { + minDate: e.detail.date, + }, + }); + }); + document.getElementById('datetimepicker-hm-to').addEventListener(tempusDominus.Namespace.events.change, (e) => { + linked_from.updateOptions({ + restrictions: { + maxDate: e.detail.date, + }, + }); + }); + } // Initialize select pickers. //$('.selectpicker').selectpicker(); diff --git a/package.json b/package.json index a78cddc2..34db54e5 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "@fortawesome/fontawesome-free": "^6.4.0", "@popperjs/core": "^2.11.7", "bootstrap": "^3.4.0", - "bootstrap-datepicker": "^1.7.1", + "@eonasdan/tempus-dominus": "^6.7.7", "bootstrap-select": "^1.13.18", "bootswatch": "^5.2.3", "cldr-core": "^43.0.0", diff --git a/yarn.lock b/yarn.lock index 9463a32c..ff8a414c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,11 @@ # yarn lockfile v1 +"@eonasdan/tempus-dominus@^6.7.7": + version "6.7.7" + resolved "https://registry.yarnpkg.com/@eonasdan/tempus-dominus/-/tempus-dominus-6.7.7.tgz#488c04ef775feb2779cbcc95d7715a188b29de9c" + integrity sha512-Ij/s+96iy1vDW/iVxIJEgsj/ChIM6Qk7R504uB55yObCFkrXzlWGSgyNJO7RNWiYmzcNtg/IHyBy5ZcrWJ+nrg== + "@fortawesome/fontawesome-free@^6.4.0": version "6.4.0" resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-6.4.0.tgz#1ee0c174e472c84b23cb46c995154dc383e3b4fe" @@ -286,13 +291,6 @@ boom@2.x.x: dependencies: hoek "2.x.x" -bootstrap-datepicker@^1.7.1: - version "1.9.0" - resolved "https://registry.yarnpkg.com/bootstrap-datepicker/-/bootstrap-datepicker-1.9.0.tgz#e4bfce3fcce1967876b21dc6833ec5994aaed090" - integrity sha512-9rYYbaVOheGYxjOr/+bJCmRPihfy+LkLSg4fIFMT9Od8WwWB/MB50w0JO1eBgKUMbb7PFHQD5uAfI3ArAxZRXA== - dependencies: - jquery ">=1.7.1 <4.0.0" - bootstrap-select@^1.13.18: version "1.13.18" resolved "https://registry.yarnpkg.com/bootstrap-select/-/bootstrap-select-1.13.18.tgz#4557119d58dc1159189977161c803962220e4dda" @@ -1851,7 +1849,7 @@ isstream@0.1.x, isstream@~0.1.2: resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= -"jquery@>=1.7.1 <4.0.0", "jquery@^1.8.3 || ^2.0 || ^3.0": +"jquery@^1.8.3 || ^2.0 || ^3.0": version "3.4.1" resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.4.1.tgz#714f1f8d9dde4bdfa55764ba37ef214630d80ef2" integrity sha512-36+AdBzCL+y6qjw5Tx7HgzeGCzC81MDDgaUP8ld2zhx58HdqXGoBd+tHdrBMiyjGQs0Hxs/MLZTu/eHNJJuWPw== -- GitLab