Bug 28376: Replace jQueryUI date/timepicker with Flatpickr
This patch is a proof of concept demonstrating how jQueryUI date & time pickers could be replaced using the Flatpickr library (https://flatpickr.js.org/). NEW: I've modified the default configuration of Flatpickr instances so that a "Clear date" link is automatically appended. This eliminates the need to add a button to the markup and event handling for each case. NEW: Date/time formatting should be corrected in this revised patch. The patch modifies three pages as test cases: - Circulation -> Renew (with SpecifyDueDates enabled), to demonstrate date and time selection. - NEW: You can also test the datepicker shown when you renew an on-hold item. This demonstrates a configuration which requires that the selection be after today. - Administration -> Patron categories -> New category, to demonstrate a calendar-only date picker enforcing a date after today. - NEW: Reports -> Patrons. The "Date of birth" fields are linked so that the second cannot be before the first. I've made some customizations to the default Flatpickr library's CSS and incorporated it into staff-global.scss, so you must rebuild the staff client SCSS (https://wiki.koha-community.org/wiki/Working_with_SCSS_in_the_OPAC_and_staff_client). Signed-off-by: David Nind <david@davidnind.com> Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io> Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
This commit is contained in:
parent
1393e48d8e
commit
f892ae8bf1
10 changed files with 1095 additions and 44 deletions
2
koha-tmpl/intranet-tmpl/lib/flatpickr/flatpickr.min.js
vendored
Normal file
2
koha-tmpl/intranet-tmpl/lib/flatpickr/flatpickr.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
960
koha-tmpl/intranet-tmpl/prog/css/src/_flatpickr.scss
Normal file
960
koha-tmpl/intranet-tmpl/prog/css/src/_flatpickr.scss
Normal file
|
@ -0,0 +1,960 @@
|
|||
@import "vars";
|
||||
|
||||
@-webkit-keyframes fpFadeInDown {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translate3d(0, -20px, 0);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@-moz-keyframes fpFadeInDown {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translate3d(0, -20px, 0);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@-ms-keyframes fpFadeInDown {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translate3d(0, -20px, 0);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@-o-keyframes fpFadeInDown {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translate3d(0, -20px, 0);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fpFadeInDown {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translate3d(0, -20px, 0);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
.flatpickr-calendar {
|
||||
animation: none;
|
||||
background: transparent;
|
||||
border-radius: 5px;
|
||||
border: 0;
|
||||
box-sizing: border-box;
|
||||
direction: ltr;
|
||||
display: none;
|
||||
font-size: 14px;
|
||||
line-height: 24px;
|
||||
opacity: 0;
|
||||
padding: 0;
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
touch-action: manipulation;
|
||||
visibility: hidden;
|
||||
width: $calendarWidth;
|
||||
|
||||
@if variable-exists( "noCalendarBorder" ) {
|
||||
box-shadow: 0 3px 13px rgba(black, 0.08);
|
||||
}
|
||||
|
||||
@else {
|
||||
|
||||
background: $calendarBackground;
|
||||
box-shadow: 1px 1px 3px 0 #666;
|
||||
}
|
||||
|
||||
&.open,
|
||||
&.inline {
|
||||
opacity: 1;
|
||||
max-height: 640px;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
&.open {
|
||||
display: inline-block;
|
||||
z-index: 99999;
|
||||
}
|
||||
|
||||
&.animate.open {
|
||||
animation: fpFadeInDown 300ms $bezier;
|
||||
}
|
||||
|
||||
&.inline {
|
||||
display: block;
|
||||
position: relative;
|
||||
top: 2px;
|
||||
}
|
||||
|
||||
&.static {
|
||||
position: absolute;
|
||||
top: calc(100% + 2px);
|
||||
|
||||
&.open {
|
||||
z-index: 999;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
&.multiMonth {
|
||||
.flatpickr-days .dayContainer:nth-child(n+1) {
|
||||
& .flatpickr-day.inRange:nth-child(7n+7) {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
.flatpickr-days .dayContainer:nth-child(n+2) {
|
||||
& .flatpickr-day.inRange:nth-child(7n+1) {
|
||||
box-shadow: -2px 0 0 #e6e6e6, 5px 0 0 #e6e6e6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.hasWeeks,
|
||||
.hasTime {
|
||||
.dayContainer {
|
||||
border-bottom: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@if variable-exists( "noCalendarBorder" ) {
|
||||
.hasWeeks .dayContainer {
|
||||
border-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&.hasTime {
|
||||
.flatpickr-time {
|
||||
height: $timeHeight;
|
||||
border-top: 1px solid $calendarBorderColor;
|
||||
}
|
||||
|
||||
@if variable-exists( "noCalendarBorder" ) {
|
||||
.flatpickr-innerContainer {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
.flatpickr-time {
|
||||
border: 1px solid $calendarBorderColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.noCalendar.hasTime {
|
||||
.flatpickr-time {
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
|
||||
&:before,
|
||||
&:after {
|
||||
position: absolute;
|
||||
display: block;
|
||||
pointer-events: none;
|
||||
border: solid transparent;
|
||||
content: '';
|
||||
height: 0;
|
||||
width: 0;
|
||||
left: 22px;
|
||||
}
|
||||
|
||||
&.rightMost,
|
||||
&.arrowRight {
|
||||
|
||||
&:before,
|
||||
&:after {
|
||||
left: auto;
|
||||
right: 22px;
|
||||
}
|
||||
}
|
||||
|
||||
&.arrowCenter {
|
||||
|
||||
&:before,
|
||||
&:after {
|
||||
left: 50%;
|
||||
right: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
&:before {
|
||||
border-width: 5px;
|
||||
margin: 0 -5px;
|
||||
}
|
||||
|
||||
&:after {
|
||||
border-width: 4px;
|
||||
margin: 0 -4px;
|
||||
}
|
||||
|
||||
&.arrowTop {
|
||||
|
||||
&:before,
|
||||
&:after {
|
||||
bottom: 100%;
|
||||
}
|
||||
|
||||
&:before {
|
||||
border-bottom-color: $calendarBorderColor;
|
||||
}
|
||||
|
||||
&:after {
|
||||
@if variable-exists( "noCalendarBorder" ) {
|
||||
border-bottom-color: $monthBackground;
|
||||
}
|
||||
|
||||
@else {
|
||||
border-bottom-color: $calendarBackground;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.arrowBottom {
|
||||
|
||||
&:before,
|
||||
&:after {
|
||||
top: 100%;
|
||||
}
|
||||
|
||||
&:before {
|
||||
border-top-color: $calendarBorderColor;
|
||||
}
|
||||
|
||||
&:after {
|
||||
@if variable-exists( "noCalendarBorder" ) {
|
||||
border-top-color: $monthBackground;
|
||||
}
|
||||
|
||||
@else {
|
||||
border-top-color: $calendarBackground;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.flatpickr-wrapper {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.flatpickr-months {
|
||||
display: flex;
|
||||
|
||||
.flatpickr-month {
|
||||
@if variable-exists( "noCalendarBorder" ) {
|
||||
border-radius: 5px 5px 0 0;
|
||||
}
|
||||
|
||||
background: $monthBackground;
|
||||
color: $monthForeground;
|
||||
fill: $monthForeground;
|
||||
height: $monthNavHeight;
|
||||
line-height: 1;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
user-select: none;
|
||||
overflow: hidden;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.flatpickr-prev-month,
|
||||
.flatpickr-next-month {
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
height: $monthNavHeight;
|
||||
padding: 10px;
|
||||
z-index: 3;
|
||||
color: $monthForeground;
|
||||
fill: $monthForeground;
|
||||
|
||||
&.flatpickr-disabled {
|
||||
display: none;
|
||||
}
|
||||
|
||||
i {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
&.flatpickr-prev-month {
|
||||
/*!
|
||||
/*rtl:begin:ignore*/
|
||||
/*
|
||||
*/
|
||||
left: 0;
|
||||
/*!
|
||||
/*rtl:end:ignore*/
|
||||
/*
|
||||
*/
|
||||
}
|
||||
|
||||
&.flatpickr-next-month {
|
||||
/*!
|
||||
/*rtl:begin:ignore*/
|
||||
/*
|
||||
*/
|
||||
right: 0;
|
||||
/*!
|
||||
/*rtl:end:ignore*/
|
||||
/*
|
||||
*/
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: $todayColor;
|
||||
|
||||
svg {
|
||||
@if variable-exists( "arrow_hover_color" ){
|
||||
fill: $arrow_hover_color;
|
||||
}
|
||||
|
||||
@else {
|
||||
|
||||
fill: $todayColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
svg {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
|
||||
path {
|
||||
transition: fill 0.1s;
|
||||
fill: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.numInputWrapper {
|
||||
position: relative;
|
||||
height: auto;
|
||||
|
||||
input,
|
||||
span {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
input {
|
||||
width: 100%;
|
||||
|
||||
&::-ms-clear {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&::-webkit-outer-spin-button,
|
||||
&::-webkit-inner-spin-button {
|
||||
margin: 0;
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
}
|
||||
|
||||
span {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
width: $timecontrols;
|
||||
padding: 0 4px 0 2px;
|
||||
height: 50%;
|
||||
line-height: 50%;
|
||||
opacity: 0;
|
||||
cursor: pointer;
|
||||
border: 1px solid rgba($dayForeground, 0.15);
|
||||
box-sizing: border-box;
|
||||
|
||||
&:hover {
|
||||
background: rgba($invertedBg, 0.1);
|
||||
}
|
||||
|
||||
&:active {
|
||||
background: rgba($invertedBg, 0.2);
|
||||
}
|
||||
|
||||
&:after {
|
||||
display: block;
|
||||
content: "";
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
&.arrowUp {
|
||||
top: 0;
|
||||
border-bottom: 0;
|
||||
|
||||
&:after {
|
||||
border-left: 4px solid transparent;
|
||||
border-right: 4px solid transparent;
|
||||
border-bottom: 4px solid rgba($dayForeground, 0.6);
|
||||
top: 26%;
|
||||
}
|
||||
}
|
||||
|
||||
&.arrowDown {
|
||||
top: 50%;
|
||||
|
||||
&:after {
|
||||
border-left: 4px solid transparent;
|
||||
border-right: 4px solid transparent;
|
||||
border-top: 4px solid rgba($dayForeground, 0.6);
|
||||
top: 40%;
|
||||
}
|
||||
}
|
||||
|
||||
svg {
|
||||
width: inherit;
|
||||
height: auto;
|
||||
|
||||
path {
|
||||
fill: rgba($monthForeground, 0.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: rgba($invertedBg, 0.05);
|
||||
|
||||
span {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.flatpickr-current-month {
|
||||
font-size: 135%;
|
||||
line-height: inherit;
|
||||
font-weight: 300;
|
||||
color: inherit;
|
||||
position: absolute;
|
||||
width: 75%;
|
||||
left: 12.5%;
|
||||
padding: 0.22 * $monthNavHeight 0 0 0;
|
||||
line-height: 1;
|
||||
height: $monthNavHeight;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
transform: translate3d(0px, 0px, 0px);
|
||||
|
||||
span.cur-month {
|
||||
font-family: inherit;
|
||||
font-weight: 700;
|
||||
color: inherit;
|
||||
display: inline-block;
|
||||
margin-left: 0.5ch;
|
||||
padding: 0;
|
||||
|
||||
&:hover {
|
||||
background: rgba($invertedBg, 0.05);
|
||||
}
|
||||
}
|
||||
|
||||
.numInputWrapper {
|
||||
width: 8ch;
|
||||
display: inline-block;
|
||||
|
||||
span.arrowUp:after {
|
||||
border-bottom-color: $monthForeground;
|
||||
}
|
||||
|
||||
span.arrowDown:after {
|
||||
border-top-color: $monthForeground;
|
||||
}
|
||||
}
|
||||
|
||||
input.cur-year {
|
||||
background: transparent;
|
||||
box-sizing: border-box;
|
||||
color: inherit;
|
||||
cursor: text;
|
||||
padding: 0 0 0 0.5ch;
|
||||
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;
|
||||
-webkit-appearance: textfield;
|
||||
-moz-appearance: textfield;
|
||||
appearance: textfield;
|
||||
|
||||
&:focus {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
&[disabled],
|
||||
&[disabled]:hover {
|
||||
font-size: 100%;
|
||||
color: rgba($monthForeground, 0.5);
|
||||
background: transparent;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
.flatpickr-monthDropdown-months {
|
||||
appearance: none;
|
||||
background-image: url('data:image/svg+xml;charset=utf8,%3csvg fill="%23000000" fill-opacity="0.54" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"%3e%3cpath d="M7 10l5 5 5-5z"/%3e%3cpath d="M0 0h24v24H0z" fill="none"/%3e%3c/svg%3e');
|
||||
background-position: 100% 50%;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 24px 24px;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
box-sizing: border-box;
|
||||
color: inherit;
|
||||
cursor: pointer;
|
||||
font-size: 90%;
|
||||
font-family: inherit;
|
||||
font-weight: 300;
|
||||
height: auto;
|
||||
line-height: 120%;
|
||||
margin: -1px 0 0 0;
|
||||
outline: none;
|
||||
padding: 4px 28px 4px 4px;
|
||||
position: relative;
|
||||
vertical-align: initial;
|
||||
width: auto;
|
||||
|
||||
&:focus,
|
||||
&:active {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.flatpickr-monthDropdown-month {
|
||||
background-color: $monthBackground;
|
||||
outline: none;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.flatpickr-weekdays {
|
||||
background: $weekdaysBackground;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: $weekdaysHeight;
|
||||
|
||||
.flatpickr-weekdaycontainer {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
span.flatpickr-weekday {
|
||||
cursor: default;
|
||||
font-size: 90%;
|
||||
background: $monthBackground;
|
||||
color: $weekdaysForeground;
|
||||
line-height: 1;
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
display: block;
|
||||
flex: 1;
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
.dayContainer,
|
||||
.flatpickr-weeks {
|
||||
padding: 1px 0 0 0;
|
||||
}
|
||||
|
||||
.flatpickr-days {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
width: $daysWidth;
|
||||
|
||||
&:focus {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
@if variable-exists( "noCalendarBorder" ) {
|
||||
border-left: 1px solid $calendarBorderColor;
|
||||
border-right: 1px solid $calendarBorderColor;
|
||||
}
|
||||
}
|
||||
|
||||
.dayContainer {
|
||||
padding: 0;
|
||||
outline: 0;
|
||||
text-align: left;
|
||||
width: $daysWidth;
|
||||
min-width: $daysWidth;
|
||||
max-width: $daysWidth;
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
-ms-flex-wrap: wrap;
|
||||
-ms-flex-pack: justify;
|
||||
justify-content: space-around;
|
||||
transform: translate3d(0px, 0px, 0px);
|
||||
opacity: 1;
|
||||
|
||||
&+.dayContainer {
|
||||
box-shadow: -1px 0 0 $calendarBorderColor;
|
||||
}
|
||||
}
|
||||
|
||||
.flatpickr-day {
|
||||
background: none;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 150px;
|
||||
box-sizing: border-box;
|
||||
color: $dayForeground;
|
||||
cursor: pointer;
|
||||
|
||||
font-weight: 400;
|
||||
width: 14.2857143%;
|
||||
flex-basis: 14.2857143%;
|
||||
max-width: $daySize;
|
||||
height: $daySize;
|
||||
line-height: $daySize;
|
||||
margin: 0;
|
||||
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
|
||||
&,
|
||||
&.prevMonthDay,
|
||||
&.nextMonthDay {
|
||||
|
||||
&.inRange,
|
||||
&.today.inRange,
|
||||
&:hover,
|
||||
&:focus {
|
||||
cursor: pointer;
|
||||
outline: 0;
|
||||
background: $dayHoverBackground;
|
||||
border-color: $dayHoverBackground;
|
||||
}
|
||||
}
|
||||
|
||||
&.today {
|
||||
border-color: $todayColor;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
border-color: $todayColor;
|
||||
background: $todayColor;
|
||||
|
||||
@if variable-exists( "today_fg_color" ){
|
||||
color: $today_fg_color;
|
||||
}
|
||||
|
||||
@else {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.selected,
|
||||
&.startRange,
|
||||
&.endRange {
|
||||
|
||||
&,
|
||||
&.inRange,
|
||||
&:focus,
|
||||
&:hover,
|
||||
&.prevMonthDay,
|
||||
&.nextMonthDay {
|
||||
background: $selectedDayBackground;
|
||||
box-shadow: none;
|
||||
|
||||
@if variable-exists( "selectedDayForeground" ){
|
||||
color: $selectedDayForeground;
|
||||
}
|
||||
|
||||
@else {
|
||||
color: white;
|
||||
}
|
||||
|
||||
border-color: $selectedDayBackground;
|
||||
}
|
||||
|
||||
&.startRange {
|
||||
border-radius: 50px 0 0 50px;
|
||||
}
|
||||
|
||||
&.endRange {
|
||||
border-radius: 0 50px 50px 0;
|
||||
}
|
||||
|
||||
&.startRange+.endRange:not(:nth-child(7n+1)) {
|
||||
box-shadow: -5 * $dayMargin 0 0 $selectedDayBackground;
|
||||
}
|
||||
|
||||
&.startRange.endRange {
|
||||
border-radius: 50px;
|
||||
}
|
||||
}
|
||||
|
||||
&.inRange {
|
||||
border-radius: 0;
|
||||
box-shadow: -2.5 * $dayMargin 0 0 $dayHoverBackground, 2.5 * $dayMargin 0 0 $dayHoverBackground;
|
||||
}
|
||||
|
||||
&.flatpickr-disabled,
|
||||
&.flatpickr-disabled:hover,
|
||||
&.prevMonthDay,
|
||||
&.nextMonthDay,
|
||||
&.notAllowed,
|
||||
&.notAllowed.prevMonthDay,
|
||||
&.notAllowed.nextMonthDay {
|
||||
color: rgba($dayForeground, 0.3);
|
||||
background: transparent;
|
||||
|
||||
@if variable-exists( "disabled_border_color" ){
|
||||
border-color: $disabled_border_color;
|
||||
}
|
||||
|
||||
@else {
|
||||
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
&.flatpickr-disabled,
|
||||
&.flatpickr-disabled:hover {
|
||||
cursor: not-allowed;
|
||||
color: rgba($dayForeground, 0.1);
|
||||
}
|
||||
|
||||
&.week.selected {
|
||||
border-radius: 0;
|
||||
box-shadow: -2.5 * $dayMargin 0 0 $selectedDayBackground, 2.5 * $dayMargin 0 0 $selectedDayBackground;
|
||||
}
|
||||
|
||||
&.hidden {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.rangeMode .flatpickr-day {
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
.flatpickr-weekwrapper {
|
||||
float: left;
|
||||
|
||||
.flatpickr-weeks {
|
||||
padding: 0 12px;
|
||||
|
||||
@if variable-exists( "noCalendarBorder" ) {
|
||||
border-left: 1px solid $calendarBorderColor;
|
||||
}
|
||||
|
||||
@else {
|
||||
box-shadow: 1px 0 0 $calendarBorderColor;
|
||||
}
|
||||
}
|
||||
|
||||
.flatpickr-weekday {
|
||||
float: none;
|
||||
width: 100%;
|
||||
line-height: $weekdaysHeight;
|
||||
}
|
||||
|
||||
span.flatpickr-day {
|
||||
|
||||
&,
|
||||
&:hover {
|
||||
display: block;
|
||||
width: 100%;
|
||||
max-width: none;
|
||||
color: rgba($dayForeground, 0.3);
|
||||
background: transparent;
|
||||
cursor: default;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.flatpickr-innerContainer {
|
||||
display: block;
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
|
||||
@if variable-exists( "noCalendarBorder" ) {
|
||||
background: $calendarBackground;
|
||||
border-bottom: 1px solid $calendarBorderColor;
|
||||
}
|
||||
}
|
||||
|
||||
.flatpickr-rContainer {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.flatpickr-time {
|
||||
text-align: center;
|
||||
outline: 0;
|
||||
display: block;
|
||||
height: 0;
|
||||
line-height: $timeHeight;
|
||||
max-height: $timeHeight;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
|
||||
@if variable-exists( "noCalendarBorder" ) {
|
||||
background: $calendarBackground;
|
||||
border-radius: 0 0 5px 5px;
|
||||
}
|
||||
|
||||
&:after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.numInputWrapper {
|
||||
flex: 1;
|
||||
width: 40%;
|
||||
height: $timeHeight;
|
||||
float: left;
|
||||
|
||||
span.arrowUp:after {
|
||||
border-bottom-color: $dayForeground;
|
||||
}
|
||||
|
||||
span.arrowDown:after {
|
||||
border-top-color: $dayForeground;
|
||||
}
|
||||
}
|
||||
|
||||
&.hasSeconds .numInputWrapper {
|
||||
width: 26%;
|
||||
}
|
||||
|
||||
&.time24hr .numInputWrapper {
|
||||
width: 49%;
|
||||
}
|
||||
|
||||
input {
|
||||
background: transparent;
|
||||
box-shadow: none;
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
text-align: center;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: inherit;
|
||||
line-height: inherit;
|
||||
color: $dayForeground;
|
||||
font-size: 14px;
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
-webkit-appearance: textfield;
|
||||
-moz-appearance: textfield;
|
||||
appearance: textfield;
|
||||
|
||||
&.flatpickr-hour {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
&.flatpickr-minute,
|
||||
&.flatpickr-second {
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: 0;
|
||||
border: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.flatpickr-time-separator,
|
||||
.flatpickr-am-pm {
|
||||
height: inherit;
|
||||
float: left;
|
||||
line-height: inherit;
|
||||
color: $dayForeground;
|
||||
font-weight: bold;
|
||||
width: 2%;
|
||||
user-select: none;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.flatpickr-am-pm {
|
||||
outline: 0;
|
||||
width: 18%;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
input,
|
||||
.flatpickr-am-pm {
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
background: lighten($dayHoverBackground, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.flatpickr-input {
|
||||
background-repeat: no-repeat;
|
||||
background-position: 3px;
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='#369' class='bi bi-calendar3'%3E%3Cg stroke-width='1.333'%3E%3Cpath d='M10.5 0h-9A1.5 1.5 0 0 0 0 1.5v9A1.5 1.5 0 0 0 1.5 12h9a1.5 1.5 0 0 0 1.5-1.5v-9A1.5 1.5 0 0 0 10.5 0zM.75 2.893c0-.355.336-.643.75-.643h9c.414 0 .75.288.75.643v7.714c0 .355-.336.643-.75.643h-9c-.414 0-.75-.288-.75-.643z'/%3E%3Cpath d='M4.875 5.25a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5zm2.25 0a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5zm2.25 0a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5zM2.625 7.5a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5zm2.25 0a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5zm2.25 0a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5zm2.25 0a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5zm-6.75 2.25a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5zm2.25 0a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5zm2.25 0a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5z'/%3E%3C/g%3E%3C/svg%3E");
|
||||
border-style: inset;
|
||||
border-width: 1px;
|
||||
padding: 3px 3px 3px 20px;
|
||||
|
||||
&:focus {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
&[readonly] {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.flatpickr-day {
|
||||
border-radius: 0;
|
||||
}
|
37
koha-tmpl/intranet-tmpl/prog/css/src/_vars.scss
Normal file
37
koha-tmpl/intranet-tmpl/prog/css/src/_vars.scss
Normal file
|
@ -0,0 +1,37 @@
|
|||
$bezier: cubic-bezier(0.23, 1, 0.32, 1);
|
||||
$slideTime: 400ms;
|
||||
|
||||
|
||||
$daySize: 39px;
|
||||
$padding: $daySize / 16;
|
||||
$dayMargin: 2px;
|
||||
$daysWidth: $daySize * 7 + $dayMargin * 14 + $padding * 2 + 2;
|
||||
$calendarWidth: $daysWidth;
|
||||
|
||||
$monthNavHeight: 34px !default;
|
||||
$weekdaysHeight: 28px !default;
|
||||
$timeHeight: 40px;
|
||||
|
||||
|
||||
|
||||
$calendarBackground: #ffffff !default;
|
||||
$calendarBorderColor: #e6e6e6 !default;
|
||||
|
||||
$monthForeground: rgba(black, 0.9) !default;
|
||||
$arrow_hover_color: #f64747 !default;
|
||||
|
||||
$monthBackground: transparent !default;
|
||||
|
||||
$weekdaysBackground: transparent !default;
|
||||
$weekdaysForeground: rgba(black, 0.54) !default;
|
||||
|
||||
$dayForeground: #000 !default;
|
||||
$dayHoverBackground: #e6e6e6 !default;
|
||||
|
||||
$todayColor: #538200 !default;
|
||||
$selectedDayBackground: #FFF4C6 !default;
|
||||
$selectedDayForeground: #000;
|
||||
|
||||
$invertedBg: invert($calendarBackground);
|
||||
|
||||
$timecontrols: 25px;
|
|
@ -1,5 +1,6 @@
|
|||
@import "mixins";
|
||||
@import "tables";
|
||||
@import "flatpickr";
|
||||
|
||||
::selection {
|
||||
background: #538200;
|
||||
|
@ -54,6 +55,11 @@ a {
|
|||
padding: 0;
|
||||
}
|
||||
|
||||
&.clear_date {
|
||||
color: #C33;
|
||||
font-size: 130%;
|
||||
}
|
||||
|
||||
&.close {
|
||||
&:hover {
|
||||
color: #538200;
|
||||
|
@ -1809,6 +1815,10 @@ i {
|
|||
&[type="submit"] {
|
||||
background: #FFF none;
|
||||
}
|
||||
|
||||
&.flatpickr-input {
|
||||
padding: 3px 3px 3px 20px;
|
||||
}
|
||||
}
|
||||
|
||||
li {
|
||||
|
@ -3761,10 +3771,6 @@ input.renew {
|
|||
padding: .5em;
|
||||
}
|
||||
|
||||
.dialog input#renewonholdduedate {
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.date-select {
|
||||
label {
|
||||
display: inline-block;
|
||||
|
|
|
@ -2,13 +2,50 @@
|
|||
[% USE Koha %]
|
||||
[% USE raw %]
|
||||
<!-- calendar.inc -->
|
||||
[% FILTER collapse %]
|
||||
<script>
|
||||
var debug = "[% debug | html %]";
|
||||
var dateformat_pref = "[% Koha.Preference('dateformat ') | html %]";
|
||||
var dateformat_string = [% IF ( dateformat == "us" ) %]"mm/dd/yy"[% ELSIF ( dateformat == "metric" ) %]"dd/mm/yy"[% ELSIF ( dateformat == "dmydot" ) %]"dd.mm.yy"[% ELSE %]"yy-mm-dd"[% END %];
|
||||
var flatpickr_dateformat_string = [% IF ( dateformat == "us" ) %]"m/d/Y"[% ELSIF ( dateformat == "metric" ) %]"d/m/Y"[% ELSIF ( dateformat == "dmydot" ) %]"d.m.Y"[% ELSE %]"Y-m-d"[% END %];
|
||||
var sentmsg = 0;
|
||||
var bidi = [% IF(bidi) %] true[% ELSE %] false[% END %];
|
||||
var calendarFirstDayOfWeek = '[% Koha.Preference('CalendarFirstDayOfWeek') | html %]';
|
||||
var flatpickr_timeformat_string = [% IF Koha.Preference('TimeFormat') == '12hr' %]"h:i K"[% ELSE %]"H:i"[% END %];
|
||||
var flatpickr_timeformat = [% IF Koha.Preference('TimeFormat') == '12hr' %]false[% ELSE %]true[% END %];
|
||||
</script>
|
||||
<!-- / calendar.inc -->
|
||||
[% Asset.js("js/calendar.js") | $raw %]
|
||||
[% Asset.js("lib/flatpickr/flatpickr.min.js") | $raw %]
|
||||
<script>
|
||||
flatpickr.l10ns.default.weekdays = flatpickr_weekdays;
|
||||
flatpickr.l10ns.default.months = flatpickr_months;
|
||||
flatpickr.setDefaults({
|
||||
allowInput: true,
|
||||
dateFormat: flatpickr_dateformat_string,
|
||||
nextArrow: '<i class="fa fa-fw fa-arrow-right"></i>',
|
||||
prevArrow: '<i class="fa fa-fw fa-arrow-left"></i>',
|
||||
time_24hr: flatpickr_timeformat,
|
||||
locale: {
|
||||
"firstDayOfWeek": calendarFirstDayOfWeek
|
||||
},
|
||||
onReady: function( selectedDates, dateStr, instance ){
|
||||
/* When flatpickr instance is created, automatically append a "clear date" link */
|
||||
$(instance.input)
|
||||
.after( $("<a/>")
|
||||
.attr("href","#")
|
||||
.addClass("clear_date")
|
||||
.on("click", function(){
|
||||
instance.clear();
|
||||
})
|
||||
.addClass("fa fa-fw fa-remove")
|
||||
.attr("aria-hidden", true)
|
||||
.attr("aria-label", _("Clear date") )
|
||||
);
|
||||
},
|
||||
onClose: function( selectedDates, dateText, instance) {
|
||||
validate_date( selectedDates, instance );
|
||||
},
|
||||
});
|
||||
</script>
|
||||
[% END %]
|
||||
|
|
|
@ -683,6 +683,7 @@
|
|||
[% MACRO jsinclude BLOCK %]
|
||||
[% Asset.js("js/admin-menu.js") | $raw %]
|
||||
[% Asset.js("js/messaging-preference-form.js") | $raw %]
|
||||
[% Asset.js("lib/flatpickr/flatpickr.min.js") | $raw %]
|
||||
[% INCLUDE 'calendar.inc' %]
|
||||
[% INCLUDE 'datatables.inc' %]
|
||||
[% INCLUDE 'columns_settings.inc' %]
|
||||
|
|
|
@ -147,7 +147,7 @@
|
|||
<input type="hidden" name="override_limit" value="1" />
|
||||
<input type="hidden" name="override_holds" value="1" />
|
||||
<div>
|
||||
<label for="renewonholdduedate">Renewal due date:</label> <input type="text" size="12" id="renewonholdduedate" name="renewonholdduedate" value="" />
|
||||
<label for="renewonholdduedate">Renewal due date:</label> <input type="text" size="20" id="renewonholdduedate" name="renewonholdduedate" value="" />
|
||||
</div>
|
||||
<button type="submit" class="approve"><i class="fa fa-check"></i> Override and renew</button>
|
||||
</form>
|
||||
|
@ -220,7 +220,6 @@
|
|||
<div class="date-select" id="renew_date_override_fields">
|
||||
<div><label for="hard_due_date" class="hint">Renewal due date [% INCLUDE 'date-format.inc' %]:</label></div>
|
||||
<input type="text" size="20" id="hard_due_date" name="hard_due_date" value="[% hard_due_date | $KohaDates with_hours => 1 %]" />
|
||||
<button type="button" class="action btn btn-default btn-xs" id="cleardate" name="cleardate">Clear</button>
|
||||
</div> <!-- /.date-select -->
|
||||
</div>
|
||||
</fieldset>
|
||||
|
@ -245,8 +244,6 @@
|
|||
|
||||
[% MACRO jsinclude BLOCK %]
|
||||
[% INCLUDE 'calendar.inc' %]
|
||||
[% Asset.js("lib/jquery/plugins/jquery-ui-timepicker-addon.min.js") | $raw %]
|
||||
[% INCLUDE 'timepicker.inc' %]
|
||||
[% IF error %]
|
||||
<script>
|
||||
$( document ).ready(function() {
|
||||
|
@ -256,34 +253,18 @@
|
|||
[% END %]
|
||||
<script>
|
||||
$( document ).ready(function() {
|
||||
$("#renewonholdduedate").datetimepicker({
|
||||
onClose: function(dateText, inst) {
|
||||
validate_date(dateText, inst);
|
||||
},
|
||||
minDate: 1, // require that renewal date is after today
|
||||
hour: 23,
|
||||
minute: 59
|
||||
}).on('change', function(e) {
|
||||
if ( ! is_valid_date( $(this).val() ) ) {$(this).val('');}
|
||||
var renewonholdduedate = $("#renewonholdduedate").flatpickr({
|
||||
enableTime: true,
|
||||
dateFormat: flatpickr_dateformat_string + " " + flatpickr_timeformat_string,
|
||||
minDate: new Date().fp_incr(1)
|
||||
});
|
||||
|
||||
[% IF Koha.Preference('SpecifyDueDate') %]
|
||||
$("#hard_due_date").datetimepicker({
|
||||
onClose: function(dateText, inst) {
|
||||
validate_date(dateText, inst);
|
||||
},
|
||||
hour: 23,
|
||||
minute: 59
|
||||
}).on("change", function(e, value) {
|
||||
if ( ! is_valid_date( $(this).val() ) ) {$(this).val("");}
|
||||
});
|
||||
$("#cleardate").on("click",function(e){
|
||||
e.preventDefault();
|
||||
this.form.hard_due_date.value = '';
|
||||
this.form.barcode.focus();
|
||||
var hard_due_date = $("#hard_due_date").flatpickr({
|
||||
enableTime: true,
|
||||
dateFormat: flatpickr_dateformat_string + " " + flatpickr_timeformat_string,
|
||||
});
|
||||
[% END %]
|
||||
|
||||
});
|
||||
</script>
|
||||
[% END %]
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
[% USE Branches %]
|
||||
[% USE Koha %]
|
||||
[% USE Asset %]
|
||||
[% SET footerjs = 1 %]
|
||||
[% INCLUDE 'doc-head-open.inc' %]
|
||||
<title>[% IF ( do_it ) %]Patrons statistics › Results[% ELSE %]Patrons statistics[% END %] › Reports › Koha</title>
|
||||
|
@ -176,13 +177,16 @@
|
|||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Date of birth</td>
|
||||
<td colspan="2"></td>
|
||||
<td><label for="from">From</label> <input type="text" size="10" id="from" name="Filter" class="datepickerfrom" />
|
||||
<label for="to">To</label> <input size="10" id="to" name="Filter" value="" type="text" class="datepickerto" />
|
||||
<td>Date of birth</td>
|
||||
<td colspan="2"></td>
|
||||
<td>
|
||||
<label for="from">From</label>
|
||||
<input type="text" size="10" id="from" name="Filter" class="" />
|
||||
<label for="to">To</label>
|
||||
<input size="10" id="to" name="Filter" value="" type="text" class="" />
|
||||
<span class="hint">[% INCLUDE 'date-format.inc' %]</span>
|
||||
</td>
|
||||
</tr>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Gender</td>
|
||||
<td><input type="radio" name="Line" value="sex" /></td>
|
||||
|
@ -326,6 +330,19 @@
|
|||
|
||||
[% MACRO jsinclude BLOCK %]
|
||||
[% INCLUDE 'calendar.inc' %]
|
||||
<script>
|
||||
var startPicker = $("#from").flatpickr({
|
||||
onClose: function( selectedDates, dateText, instance) {
|
||||
validate_date( selectedDates, instance );
|
||||
endPicker.set('minDate', selectedDates[0]);
|
||||
}
|
||||
});
|
||||
var endPicker = $("#to").flatpickr({
|
||||
onClose: function( selectedDates, dateText, instance) {
|
||||
validate_date( selectedDates, instance );
|
||||
},
|
||||
});
|
||||
</script>
|
||||
[% END %]
|
||||
|
||||
[% INCLUDE 'intranet-bottom.inc' %]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* global debug sentmsg __ dateformat_pref dateformat_string bidi calendarFirstDayOfWeek */
|
||||
/* exported DateTime_from_syspref */
|
||||
/* exported DateTime_from_syspref flatpickr_weekdays flatpickr_months */
|
||||
var MSG_PLEASE_ENTER_A_VALID_DATE = ( __("Please enter a valid date (should match %s).") );
|
||||
if (debug > 1) {
|
||||
alert("dateformat: " + dateformat_pref + "\ndebug is on (level " + debug + ")");
|
||||
|
@ -8,7 +8,6 @@ if (debug > 1) {
|
|||
function is_valid_date(date) {
|
||||
// An empty string is considered as a valid date for convenient reasons.
|
||||
if (date === '') return 1;
|
||||
|
||||
var dateformat = dateformat_string;
|
||||
if (dateformat == 'us') {
|
||||
if (date.search(/^\d{2}\/\d{2}\/\d{4}($|\s)/) == -1) return 0;
|
||||
|
@ -24,7 +23,7 @@ function is_valid_date(date) {
|
|||
dateformat = 'dd.mm.yy';
|
||||
}
|
||||
try {
|
||||
$.datepicker.parseDate(dateformat, date);
|
||||
flatpickr.parseDate(date, dateformat);
|
||||
} catch (e) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -49,7 +48,7 @@ function validate_date(dateText, inst) {
|
|||
if (!is_valid_date(dateText)) {
|
||||
var dateformat_str = get_dateformat_str( dateformat_pref );
|
||||
alert(MSG_PLEASE_ENTER_A_VALID_DATE.format(dateformat_str));
|
||||
$('#' + inst.id).val('');
|
||||
inst.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -162,6 +161,16 @@ jQuery.validator.addMethod("date_on_or_after",
|
|||
return to >= from;
|
||||
});
|
||||
|
||||
var flatpickr_weekdays = {
|
||||
shorthand: [ __("Sun"), __("Mon"), __("Tue"), __("Wed"), __("Thu"), __("Fri"), __("Sat")],
|
||||
longhand: [ __("Sunday"), __("Monday"), __("Tuesday"), __("Wednesday"), __("Thursday"), __("Friday"), __("Saturday") ]
|
||||
};
|
||||
|
||||
var flatpickr_months = {
|
||||
shorthand: [ __("Jan"), __("Feb"), __("Mar"), __("Apr"), __("May"), __("Jun"), __("Jul"), __("Aug"), __("Sep"), __("Oct"), __("Nov"), __("Dec")],
|
||||
longhand: [ __("January"), __("February"), __("March"), __("April"), __("May"), __("June"), __("July"), __("August"), __("September"), __("October"), __("November"), __("December")]
|
||||
};
|
||||
|
||||
$(document).ready(function () {
|
||||
|
||||
$.datepicker.setDefaults({
|
||||
|
|
|
@ -21,6 +21,7 @@ jQuery.validator.addMethod( "enrollment_period", function(){
|
|||
}, __("Please choose an enrollment period in months OR by date.")
|
||||
);
|
||||
|
||||
flatpickr.l10ns.default.firstDayOfWeek = calendarFirstDayOfWeek;
|
||||
|
||||
$(document).ready(function() {
|
||||
KohaTable("patron_categories", {
|
||||
|
@ -39,9 +40,9 @@ $(document).ready(function() {
|
|||
"exportColumns": [0,1,2,3,4,5,6,7,8,9,10,11,12],
|
||||
}, columns_settings);
|
||||
|
||||
$("#enrolmentperioddate").datepicker({
|
||||
minDate: 1
|
||||
}); // Require that "until date" be in the future
|
||||
$("#enrolmentperioddate").flatpickr({
|
||||
minDate: new Date().fp_incr(1)
|
||||
});
|
||||
|
||||
if ($("#branches option:selected").length < 1) {
|
||||
$("#branches option:first").attr("selected", "selected");
|
||||
|
|
Loading…
Reference in a new issue