Commit f6efc63f authored by Andreas Fernandez's avatar Andreas Fernandez
Browse files

[!!!][TASK] Replace bootstrap-datetimepicker

This patch replaces the bootstrap-datetimepicker with flatpickr which
is pretty lightweight.

Since this datetimepicker also has some sanity validation on board, much
custom datetime parsing in FormEngine can and has been removed,
including magic date manipulation by using addition or subtraction.

The year format for momentjs has been changed from `YYYY` to `Y` as well
to support years < 1000.

Currently the datepicker is not able to select a date < 100.
By manual selection, the picker jumps back to 1999 and not to 99 as
expected.

Resolves: #91606
Releases: master
Change-Id: Id723c5200c797019f6de0ed5a4c15b2137a32995
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/64833


Tested-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
Tested-by: Andreas Fernandez's avatarAndreas Fernandez <a.fernandez@scripting-base.de>
Tested-by: default avatarTYPO3com <noreply@typo3.com>
Reviewed-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
Reviewed-by: Andreas Fernandez's avatarAndreas Fernandez <a.fernandez@scripting-base.de>
parent 6bc69695
...@@ -91,7 +91,6 @@ module.exports = function (grunt) { ...@@ -91,7 +91,6 @@ module.exports = function (grunt) {
includePaths: [ includePaths: [
'node_modules/bootstrap-sass/assets/stylesheets', 'node_modules/bootstrap-sass/assets/stylesheets',
'node_modules/font-awesome/scss', 'node_modules/font-awesome/scss',
'node_modules/eonasdan-bootstrap-datetimepicker/src/sass',
'node_modules/tagsort' 'node_modules/tagsort'
] ]
}, },
...@@ -514,12 +513,13 @@ module.exports = function (grunt) { ...@@ -514,12 +513,13 @@ module.exports = function (grunt) {
'moment-timezone.js': 'moment-timezone/builds/moment-timezone-with-data.min.js', 'moment-timezone.js': 'moment-timezone/builds/moment-timezone-with-data.min.js',
'cropper.min.js': 'cropperjs/dist/cropper.min.js', 'cropper.min.js': 'cropperjs/dist/cropper.min.js',
'imagesloaded.pkgd.min.js': 'imagesloaded/imagesloaded.pkgd.min.js', 'imagesloaded.pkgd.min.js': 'imagesloaded/imagesloaded.pkgd.min.js',
'bootstrap-datetimepicker.js': 'eonasdan-bootstrap-datetimepicker/build/js/bootstrap-datetimepicker.min.js',
'autosize.js': 'autosize/dist/autosize.min.js', 'autosize.js': 'autosize/dist/autosize.min.js',
/* disabled for removed sourcemap reference in file /* disabled for removed sourcemap reference in file
'taboverride.min.js': 'taboverride/build/output/taboverride.min.js', 'taboverride.min.js': 'taboverride/build/output/taboverride.min.js',
*/ */
'broadcastchannel-polyfill.js': 'broadcastchannel-polyfill/index.js', 'broadcastchannel-polyfill.js': 'broadcastchannel-polyfill/index.js',
'flatpickr/flatpickr.min.js': 'flatpickr/dist/flatpickr.min.js',
'flatpickr/locales.js': 'flatpickr/dist/l10n/index.js',
'jquery.minicolors.js': '../node_modules/@claviska/jquery-minicolors/jquery.minicolors.min.js', 'jquery.minicolors.js': '../node_modules/@claviska/jquery-minicolors/jquery.minicolors.min.js',
'../../Images/colorpicker/jquery.minicolors.png': '../node_modules/@claviska/jquery-minicolors/jquery.minicolors.png', '../../Images/colorpicker/jquery.minicolors.png': '../node_modules/@claviska/jquery-minicolors/jquery.minicolors.png',
/* disabled until autocomplete formatGroup is fixed to pass on the index too /* disabled until autocomplete formatGroup is fixed to pass on the index too
...@@ -565,6 +565,7 @@ module.exports = function (grunt) { ...@@ -565,6 +565,7 @@ module.exports = function (grunt) {
thirdparty: { thirdparty: {
files: { files: {
"<%= paths.core %>Public/JavaScript/Contrib/broadcastchannel-polyfill.js": ["<%= paths.core %>Public/JavaScript/Contrib/broadcastchannel-polyfill.js"], "<%= paths.core %>Public/JavaScript/Contrib/broadcastchannel-polyfill.js": ["<%= paths.core %>Public/JavaScript/Contrib/broadcastchannel-polyfill.js"],
"<%= paths.core %>Public/JavaScript/Contrib/flatpickr/locales.js": ["<%= paths.core %>Public/JavaScript/Contrib/flatpickr/locales.js"],
"<%= paths.core %>Public/JavaScript/Contrib/require.js": ["<%= paths.core %>Public/JavaScript/Contrib/require.js"], "<%= paths.core %>Public/JavaScript/Contrib/require.js": ["<%= paths.core %>Public/JavaScript/Contrib/require.js"],
"<%= paths.core %>Public/JavaScript/Contrib/nprogress.js": ["<%= paths.core %>Public/JavaScript/Contrib/nprogress.js"], "<%= paths.core %>Public/JavaScript/Contrib/nprogress.js": ["<%= paths.core %>Public/JavaScript/Contrib/nprogress.js"],
"<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/core.js": ["<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/core.js"], "<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/core.js": ["<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/core.js"],
...@@ -575,8 +576,7 @@ module.exports = function (grunt) { ...@@ -575,8 +576,7 @@ module.exports = function (grunt) {
"<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/resizable.js": ["<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/resizable.js"], "<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/resizable.js": ["<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/resizable.js"],
"<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/selectable.js": ["<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/selectable.js"], "<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/selectable.js": ["<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/selectable.js"],
"<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/widget.js": ["<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/widget.js"], "<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/widget.js": ["<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/widget.js"],
"<%= paths.install %>Public/JavaScript/chosen.jquery.min.js": ["<%= paths.node_modules %>chosen-js/chosen.jquery.js"], "<%= paths.install %>Public/JavaScript/chosen.jquery.min.js": ["<%= paths.node_modules %>chosen-js/chosen.jquery.js"]
"<%= paths.core %>Public/JavaScript/Contrib/bootstrap-datetimepicker.js": ["<%= paths.core %>Public/JavaScript/Contrib/bootstrap-datetimepicker.js"]
} }
}, },
t3editor: { t3editor: {
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
// Components // Components
// //
@import "component/colorpicker"; @import "component/colorpicker";
@import "component/datetimepicker";
@import "component/svgtree"; @import "component/svgtree";
@import "component/elementbrowser"; @import "component/elementbrowser";
@import "component/modal"; @import "component/modal";
...@@ -38,11 +39,6 @@ ...@@ -38,11 +39,6 @@
@import "module/viewpage"; @import "module/viewpage";
@import "module/workspaces"; @import "module/workspaces";
//
// Components from bootstrap plugins
//
@import "bootstrap-datetimepicker";
// //
// Include chosen CSS file // Include chosen CSS file
// //
......
//
// Flatpickr datetime picker
//
//
// Variables
//
$day-grid-size: 32px;
$padding-day: ($day-grid-size / 16);
$margin-day: 2px;
$row-days-width: ($day-grid-size * 7 + $margin-day * 14 + $padding-day * 2 + 2);
$picker-width: $row-days-width;
.flatpickr-calendar {
opacity: 0;
display: none;
text-align: center;
visibility: hidden;
padding: 0;
animation: none;
direction: ltr;
border: 1px solid $dropdown-border;
font-size: $bs-datetimepicker-timepicker-font-size;
line-height: 24px;
position: absolute;
width: $picker-width;
box-sizing: border-box;
touch-action: manipulation;
background: $dropdown-bg;
&:before {
border-width: 5px;
margin: 0 -5px;
}
&:after {
border-width: 4px;
margin: 0 -4px;
}
&:before,
&:after {
position: absolute;
display: block;
pointer-events: none;
border: 6px solid transparent;
content: '';
height: 0;
width: 0;
left: 22px;
}
&.open,
&.inline {
opacity: 1;
max-height: 640px;
visibility: visible;
}
&.open {
display: inline-block;
z-index: 100;
&.animate {
animation: fpFadeInDown 300ms cubic-bezier(0.23, 1, 0.32, 1);
}
}
&.inline {
display: block;
position: relative;
top: 2px;
}
&.static {
position: absolute;
top: calc(100% + 2px);
&.open {
z-index: 99;
display: block;
}
}
}
.flatpickr-calendar .hasWeeks .dayContainer,
.flatpickr-calendar .hasTime .dayContainer {
border-bottom: 0;
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
}
.flatpickr-calendar .hasWeeks .dayContainer {
border-left: 0;
}
.flatpickr-calendar.hasTime .flatpickr-time {
height: 40px;
border-top: 1px solid $dropdown-divider-bg;
}
.flatpickr-calendar.noCalendar.hasTime .flatpickr-time {
height: auto;
border-top: none;
}
.flatpickr-calendar.rightMost:before,
.flatpickr-calendar.rightMost:after {
left: auto;
right: 22px;
}
.flatpickr-calendar.arrowTop:before,
.flatpickr-calendar.arrowTop:after {
bottom: 100%;
}
.flatpickr-calendar.arrowTop:before {
border-bottom-color: $dropdown-bg;
}
.flatpickr-calendar.arrowTop:after {
border-bottom-color: $dropdown-bg;
}
.flatpickr-calendar.arrowBottom:before,
.flatpickr-calendar.arrowBottom:after {
top: 100%;
}
.flatpickr-calendar.arrowBottom:before {
border-top-color: $dropdown-bg;
}
.flatpickr-calendar.arrowBottom:after {
border-top-color: $dropdown-bg;
}
.flatpickr-wrapper {
position: relative;
display: inline-block;
}
.flatpickr-months {
display: flex;
}
.flatpickr-months .flatpickr-month {
background: transparent;
color: $dropdown-color;
fill: $dropdown-color;
height: 34px;
line-height: 1;
text-align: center;
position: relative;
user-select: none;
overflow: hidden;
flex: 1;
}
.flatpickr-months .flatpickr-prev-month,
.flatpickr-months .flatpickr-next-month {
text-decoration: none;
cursor: pointer;
position: absolute;
top: 0;
height: 34px;
padding: 10px;
z-index: 3;
color: $dropdown-color;
fill: $dropdown-color;
&.flatpickr-disabled {
display: none;
}
i {
position: relative;
}
}
.flatpickr-months .flatpickr-prev-month.flatpickr-prev-month,
.flatpickr-months .flatpickr-next-month.flatpickr-prev-month {
left: 0;
}
.flatpickr-months .flatpickr-prev-month.flatpickr-next-month,
.flatpickr-months .flatpickr-next-month.flatpickr-next-month {
right: 0;
}
.flatpickr-months .flatpickr-prev-month:hover,
.flatpickr-months .flatpickr-next-month:hover {
color: $dropdown-color;
}
.flatpickr-months .flatpickr-prev-month:hover svg,
.flatpickr-months .flatpickr-next-month:hover svg {
fill: $bs-datetimepicker-active-bg;
}
.flatpickr-months .flatpickr-prev-month svg,
.flatpickr-months .flatpickr-next-month svg {
width: 14px;
height: 14px;
}
.flatpickr-months .flatpickr-prev-month svg path,
.flatpickr-months .flatpickr-next-month svg path {
transition: fill 0.1s;
}
.numInputWrapper {
position: relative;
height: auto;
}
.numInputWrapper input,
.numInputWrapper span {
display: inline-block;
}
.numInputWrapper input {
width: 100%;
}
.numInputWrapper input::-ms-clear {
display: none;
}
.numInputWrapper input::-webkit-outer-spin-button,
.numInputWrapper input::-webkit-inner-spin-button {
margin: 0;
-webkit-appearance: none;
}
.numInputWrapper span {
position: absolute;
right: 0;
width: 12px;
padding: 0 4px 0 2px;
height: 50%;
line-height: 50%;
opacity: 0;
cursor: pointer;
box-sizing: border-box;
}
.numInputWrapper span:hover {
background: $bs-datetimepicker-btn-hover-bg;
}
.numInputWrapper span:active {
background: $bs-datetimepicker-btn-hover-bg;
}
.numInputWrapper span:after {
display: block;
content: "";
position: absolute;
}
.numInputWrapper span.arrowUp {
top: 0;
border-bottom: 0;
}
.numInputWrapper span.arrowUp:after,
.numInputWrapper span.arrowDown:after {
top: calc(50% - 2px);
}
.numInputWrapper span.arrowUp:after {
border-left: 4px solid transparent;
border-right: 4px solid transparent;
border-bottom: 4px solid rgba(57, 57, 57, 0.6);
}
.numInputWrapper span.arrowDown {
top: 50%;
}
.numInputWrapper span.arrowDown:after {
border-left: 4px solid transparent;
border-right: 4px solid transparent;
border-top: 4px solid rgba(57, 57, 57, 0.6);
}
.numInputWrapper span svg {
width: inherit;
height: auto;
}
.numInputWrapper span svg path {
fill: rgba(0, 0, 0, 0.5);
}
.numInputWrapper:hover {
background: rgba(0, 0, 0, 0.05);
}
.numInputWrapper:hover span {
opacity: 1;
}
.flatpickr-current-month {
font-weight: 300;
color: inherit;
position: absolute;
width: 75%;
left: 12.5%;
padding: 7.48px 0 0;
line-height: 1;
height: 34px;
display: inline-block;
text-align: center;
transform: translate3d(0, 0, 0);
}
.flatpickr-current-month span.cur-month {
font-family: inherit;
font-weight: 700;
color: inherit;
display: inline-block;
margin-left: 0.5ch;
padding: 0;
}
.flatpickr-current-month span.cur-month:hover {
background: rgba(0, 0, 0, 0.05);
}
.flatpickr-current-month .numInputWrapper {
width: 5rem;
display: inline-block;
span.arrowUp {
&:after {
border-bottom-color: $dropdown-color;
}
}
span.arrowDown {
&:after {
border-top-color: $dropdown-color;
}
}
}
.flatpickr-current-month input.cur-year {
background: transparent;
box-sizing: border-box;
color: $dropdown-color;
cursor: text;
margin: 0;
display: inline-block;
font-size: inherit;
font-family: inherit;
font-weight: 300;
line-height: inherit;
height: auto;
border: 0;
border-radius: 0;
vertical-align: initial;
appearance: textfield;
}
.flatpickr-current-month input.cur-year {
&[disabled],
&[disabled]:hover {
font-size: 100%;
color: rgba(0, 0, 0, 0.5);
background: transparent;
pointer-events: none;
}
}
.flatpickr-current-month .flatpickr-monthDropdown-months {
appearance: menulist;
background: transparent;
border: none;
border-radius: 0;
box-sizing: border-box;
color: $dropdown-color;
cursor: pointer;
font-size: inherit;
font-family: inherit;
font-weight: 300;
height: 100%;
line-height: inherit;
position: relative;
vertical-align: initial;
width: auto;
&:focus {
outline: none;
}
&:hover {
background: $bs-datetimepicker-btn-hover-bg;
}
.flatpickr-monthDropdown-month {
background-color: $dropdown-bg;
padding: 0;
}
}
.flatpickr-weekdays {
background: transparent;
text-align: center;
overflow: hidden;
width: 100%;
display: flex;
align-items: center;
height: 28px;
.flatpickr-weekdaycontainer {
display: flex;
flex: 1;
}
}
span.flatpickr-weekday {
cursor: default;
font-size: 90%;
background: transparent;
color: $dropdown-color;
line-height: 1;
margin: 0;
text-align: center;
display: block;
flex: 1;
font-weight: bolder;
}
.dayContainer,
.flatpickr-weeks {
padding: 1px 0 0;
}
.flatpickr-days {
position: relative;
overflow: hidden;
display: flex;
align-items: flex-start;
width: $row-days-width;
}
.dayContainer {
padding: 0;
text-align: left;
width: $row-days-width;
min-width: $row-days-width;
max-width: $row-days-width;
box-sizing: border-box;
display: flex;
flex-wrap: wrap;
justify-content: space-around;
transform: translate3d(0, 0, 0);
opacity: 1;
}
.dayContainer + .dayContainer {
box-shadow: -1px 0 0 #e6e6e6;
}
.flatpickr-day {
background: none;
border: 1px solid transparent;
border-radius: $border-radius-base;
box-sizing: border-box;
color: $dropdown-link-color;
cursor: pointer;
font-weight: 400;
width: calc(100% / 7);
flex-basis: calc(100% / 7);
max-width: $day-grid-size;
height: $day-grid-size;
line-height: $day-grid-size;
margin: 0 $margin-day;
display: inline-block;
position: relative;
justify-content: center;
text-align: center;
}
.flatpickr-day.inRange,
.flatpickr-day.prevMonthDay.inRange,
.flatpickr-day.nextMonthDay.inRange,
.flatpickr-day.today.inRange,
.flatpickr-day.prevMonthDay.today.inRange,
.flatpickr-day.nextMonthDay.today.inRange,
.flatpickr-day:hover,
.flatpickr-day.prevMonthDay:hover,
.flatpickr-day.nextMonthDay:hover,
.flatpickr-day:focus,
.flatpickr-day.prevMonthDay:focus,
.flatpickr-day.nextMonthDay:focus {
cursor: pointer;
background: $bs-datetimepicker-btn-hover-bg;
}
.flatpickr-day.today {
border-color: #959ea9;
}
.flatpickr-day.today:hover,
.flatpickr-day.today:focus {
background: $bs-datetimepicker-btn-hover-bg;
}
.flatpickr-day.selected,
.flatpickr-day.startRange,
.flatpickr-day.endRange,
.flatpickr-day.selected.inRange,