From 0f5756cfb4fb0f7dfd4539ea12636763d52bde13 Mon Sep 17 00:00:00 2001
From: BlasenhauerJ
Date: Sat, 19 Nov 2022 16:37:34 +0100
Subject: [PATCH] enhance logs + prepare jinja variables
- add datepicker library
- disabled update live if to date chosen, and reverse
- add futur variables for home, menu
- change head path
---
.../css/air-datepicker/air-datepicker.css | 18 -
src/ui/static/css/datepicker-foundation.css | 275 ++
.../static/css/datepicker-foundation.min.css | 1 +
src/ui/static/css/datepicker.css | 318 +++
src/ui/static/css/datepicker.min.css | 1 +
.../js/air-datepicker/air-datepicker.d.ts | 146 -
.../js/air-datepicker/air-datepicker.js | 2350 -----------------
src/ui/static/js/air-datepicker/index.es.js | 2 -
.../static/js/air-datepicker/locale/ar.d.ts | 6 -
src/ui/static/js/air-datepicker/locale/ar.js | 19 -
.../static/js/air-datepicker/locale/cs.d.ts | 6 -
src/ui/static/js/air-datepicker/locale/cs.js | 19 -
.../static/js/air-datepicker/locale/da.d.ts | 6 -
src/ui/static/js/air-datepicker/locale/da.js | 19 -
.../static/js/air-datepicker/locale/de.d.ts | 6 -
src/ui/static/js/air-datepicker/locale/de.js | 19 -
.../static/js/air-datepicker/locale/en.d.ts | 6 -
src/ui/static/js/air-datepicker/locale/en.js | 19 -
.../static/js/air-datepicker/locale/es.d.ts | 6 -
src/ui/static/js/air-datepicker/locale/es.js | 19 -
.../static/js/air-datepicker/locale/fi.d.ts | 6 -
src/ui/static/js/air-datepicker/locale/fi.js | 19 -
.../static/js/air-datepicker/locale/fr.d.ts | 6 -
src/ui/static/js/air-datepicker/locale/fr.js | 19 -
.../static/js/air-datepicker/locale/hu.d.ts | 6 -
src/ui/static/js/air-datepicker/locale/hu.js | 19 -
.../static/js/air-datepicker/locale/it.d.ts | 6 -
src/ui/static/js/air-datepicker/locale/it.js | 19 -
.../static/js/air-datepicker/locale/ja.d.ts | 6 -
src/ui/static/js/air-datepicker/locale/ja.js | 19 -
.../static/js/air-datepicker/locale/ko.d.ts | 6 -
src/ui/static/js/air-datepicker/locale/ko.js | 19 -
.../static/js/air-datepicker/locale/nl.d.ts | 6 -
src/ui/static/js/air-datepicker/locale/nl.js | 19 -
.../static/js/air-datepicker/locale/pl.d.ts | 6 -
src/ui/static/js/air-datepicker/locale/pl.js | 19 -
.../js/air-datepicker/locale/pt-BR.d.ts | 6 -
.../static/js/air-datepicker/locale/pt-BR.js | 19 -
.../static/js/air-datepicker/locale/pt.d.ts | 6 -
src/ui/static/js/air-datepicker/locale/pt.js | 19 -
.../static/js/air-datepicker/locale/ro.d.ts | 6 -
src/ui/static/js/air-datepicker/locale/ro.js | 19 -
.../static/js/air-datepicker/locale/ru.d.ts | 6 -
src/ui/static/js/air-datepicker/locale/ru.js | 19 -
.../static/js/air-datepicker/locale/si.d.ts | 6 -
src/ui/static/js/air-datepicker/locale/si.js | 19 -
.../static/js/air-datepicker/locale/sk.d.ts | 6 -
src/ui/static/js/air-datepicker/locale/sk.js | 19 -
.../static/js/air-datepicker/locale/sv.d.ts | 6 -
src/ui/static/js/air-datepicker/locale/sv.js | 19 -
.../static/js/air-datepicker/locale/th.d.ts | 6 -
src/ui/static/js/air-datepicker/locale/th.js | 19 -
.../static/js/air-datepicker/locale/tr.d.ts | 6 -
src/ui/static/js/air-datepicker/locale/tr.js | 19 -
.../static/js/air-datepicker/locale/uk.d.ts | 6 -
src/ui/static/js/air-datepicker/locale/uk.js | 19 -
.../static/js/air-datepicker/locale/zh.d.ts | 6 -
src/ui/static/js/air-datepicker/locale/zh.js | 19 -
.../static/js/datepicker/DateRangePicker.js | 210 ++
src/ui/static/js/datepicker/Datepicker.js | 502 ++++
.../static/js/datepicker/datepicker-full.js | 5 +
.../js/datepicker/datepicker-full.min.js | 1 +
src/ui/static/js/datepicker/datepicker.min.js | 1 +
.../static/js/datepicker/events/functions.js | 48 +
.../datepicker/events/inputFieldListeners.js | 195 ++
.../js/datepicker/events/otherListeners.js | 20 +
.../js/datepicker/events/pickerListeners.js | 68 +
.../static/js/datepicker/i18n/base-locales.js | 13 +
.../js/datepicker/i18n/locales/ar-DZ.js | 19 +
.../js/datepicker/i18n/locales/ar-tn.js | 15 +
.../static/js/datepicker/i18n/locales/ar.js | 15 +
.../static/js/datepicker/i18n/locales/az.js | 14 +
.../static/js/datepicker/i18n/locales/bg.js | 14 +
.../static/js/datepicker/i18n/locales/bm.js | 18 +
.../static/js/datepicker/i18n/locales/bn.js | 19 +
.../static/js/datepicker/i18n/locales/br.js | 18 +
.../static/js/datepicker/i18n/locales/bs.js | 15 +
.../static/js/datepicker/i18n/locales/ca.js | 18 +
.../static/js/datepicker/i18n/locales/cs.js | 19 +
.../static/js/datepicker/i18n/locales/cy.js | 14 +
.../static/js/datepicker/i18n/locales/da.js | 19 +
.../static/js/datepicker/i18n/locales/de.js | 18 +
.../static/js/datepicker/i18n/locales/el.js | 16 +
.../js/datepicker/i18n/locales/en-AU.js | 18 +
.../js/datepicker/i18n/locales/en-CA.js | 18 +
.../js/datepicker/i18n/locales/en-GB.js | 18 +
.../js/datepicker/i18n/locales/en-IE.js | 17 +
.../js/datepicker/i18n/locales/en-NZ.js | 17 +
.../js/datepicker/i18n/locales/en-ZA.js | 17 +
.../static/js/datepicker/i18n/locales/eo.js | 17 +
.../static/js/datepicker/i18n/locales/es.js | 18 +
.../static/js/datepicker/i18n/locales/et.js | 18 +
.../static/js/datepicker/i18n/locales/eu.js | 18 +
.../static/js/datepicker/i18n/locales/fa.js | 17 +
.../static/js/datepicker/i18n/locales/fi.js | 17 +
.../static/js/datepicker/i18n/locales/fo.js | 15 +
.../js/datepicker/i18n/locales/fr-CH.js | 21 +
.../static/js/datepicker/i18n/locales/fr.js | 18 +
.../static/js/datepicker/i18n/locales/gl.js | 16 +
.../static/js/datepicker/i18n/locales/he.js | 15 +
.../static/js/datepicker/i18n/locales/hi.js | 18 +
.../static/js/datepicker/i18n/locales/hr.js | 13 +
.../static/js/datepicker/i18n/locales/hu.js | 18 +
.../static/js/datepicker/i18n/locales/hy.js | 18 +
.../static/js/datepicker/i18n/locales/id.js | 19 +
.../static/js/datepicker/i18n/locales/is.js | 14 +
.../js/datepicker/i18n/locales/it-CH.js | 20 +
.../static/js/datepicker/i18n/locales/it.js | 18 +
.../static/js/datepicker/i18n/locales/ja.js | 17 +
.../static/js/datepicker/i18n/locales/ka.js | 17 +
.../static/js/datepicker/i18n/locales/kk.js | 15 +
.../static/js/datepicker/i18n/locales/km.js | 15 +
.../static/js/datepicker/i18n/locales/ko.js | 18 +
.../static/js/datepicker/i18n/locales/lt.js | 19 +
.../static/js/datepicker/i18n/locales/lv.js | 18 +
.../static/js/datepicker/i18n/locales/me.js | 17 +
.../static/js/datepicker/i18n/locales/mk.js | 15 +
.../static/js/datepicker/i18n/locales/mn.js | 17 +
.../static/js/datepicker/i18n/locales/mr.js | 18 +
.../static/js/datepicker/i18n/locales/ms.js | 15 +
.../js/datepicker/i18n/locales/nl-BE.js | 18 +
.../static/js/datepicker/i18n/locales/nl.js | 18 +
.../static/js/datepicker/i18n/locales/no.js | 18 +
.../static/js/datepicker/i18n/locales/oc.js | 17 +
.../static/js/datepicker/i18n/locales/pl.js | 17 +
.../js/datepicker/i18n/locales/pt-BR.js | 17 +
.../static/js/datepicker/i18n/locales/pt.js | 18 +
.../static/js/datepicker/i18n/locales/ro.js | 17 +
.../static/js/datepicker/i18n/locales/ru.js | 18 +
.../static/js/datepicker/i18n/locales/si.js | 18 +
.../static/js/datepicker/i18n/locales/sk.js | 18 +
.../static/js/datepicker/i18n/locales/sl.js | 15 +
.../static/js/datepicker/i18n/locales/sq.js | 18 +
.../js/datepicker/i18n/locales/sr-latn.js | 16 +
.../static/js/datepicker/i18n/locales/sr.js | 16 +
.../static/js/datepicker/i18n/locales/sv.js | 17 +
.../static/js/datepicker/i18n/locales/sw.js | 15 +
.../static/js/datepicker/i18n/locales/ta.js | 18 +
.../static/js/datepicker/i18n/locales/tg.js | 19 +
.../static/js/datepicker/i18n/locales/th.js | 14 +
.../static/js/datepicker/i18n/locales/tk.js | 18 +
.../static/js/datepicker/i18n/locales/tr.js | 17 +
.../static/js/datepicker/i18n/locales/uk.js | 17 +
.../js/datepicker/i18n/locales/uz-cyrl.js | 18 +
.../js/datepicker/i18n/locales/uz-latn.js | 18 +
.../static/js/datepicker/i18n/locales/vi.js | 16 +
.../js/datepicker/i18n/locales/zh-CN.js | 19 +
.../js/datepicker/i18n/locales/zh-TW.js | 20 +
.../static/js/datepicker/lib/date-format.js | 185 ++
src/ui/static/js/datepicker/lib/date.js | 100 +
src/ui/static/js/datepicker/lib/dom.js | 63 +
src/ui/static/js/datepicker/lib/event.js | 71 +
src/ui/static/js/datepicker/lib/utils.js | 61 +
src/ui/static/js/datepicker/locales/ar-DZ.js | 19 +
src/ui/static/js/datepicker/locales/ar-tn.js | 15 +
src/ui/static/js/datepicker/locales/ar.js | 15 +
src/ui/static/js/datepicker/locales/az.js | 14 +
src/ui/static/js/datepicker/locales/bg.js | 14 +
src/ui/static/js/datepicker/locales/bm.js | 18 +
src/ui/static/js/datepicker/locales/bn.js | 19 +
src/ui/static/js/datepicker/locales/br.js | 18 +
src/ui/static/js/datepicker/locales/bs.js | 15 +
src/ui/static/js/datepicker/locales/ca.js | 18 +
src/ui/static/js/datepicker/locales/cs.js | 19 +
src/ui/static/js/datepicker/locales/cy.js | 14 +
src/ui/static/js/datepicker/locales/da.js | 19 +
src/ui/static/js/datepicker/locales/de.js | 18 +
src/ui/static/js/datepicker/locales/el.js | 16 +
src/ui/static/js/datepicker/locales/en-AU.js | 18 +
src/ui/static/js/datepicker/locales/en-CA.js | 18 +
src/ui/static/js/datepicker/locales/en-GB.js | 18 +
src/ui/static/js/datepicker/locales/en-IE.js | 17 +
src/ui/static/js/datepicker/locales/en-NZ.js | 17 +
src/ui/static/js/datepicker/locales/en-ZA.js | 17 +
src/ui/static/js/datepicker/locales/eo.js | 17 +
src/ui/static/js/datepicker/locales/es.js | 18 +
src/ui/static/js/datepicker/locales/et.js | 18 +
src/ui/static/js/datepicker/locales/eu.js | 18 +
src/ui/static/js/datepicker/locales/fa.js | 17 +
src/ui/static/js/datepicker/locales/fi.js | 17 +
src/ui/static/js/datepicker/locales/fo.js | 15 +
src/ui/static/js/datepicker/locales/fr-CH.js | 21 +
src/ui/static/js/datepicker/locales/fr.js | 18 +
src/ui/static/js/datepicker/locales/gl.js | 16 +
src/ui/static/js/datepicker/locales/he.js | 15 +
src/ui/static/js/datepicker/locales/hi.js | 18 +
src/ui/static/js/datepicker/locales/hr.js | 13 +
src/ui/static/js/datepicker/locales/hu.js | 18 +
src/ui/static/js/datepicker/locales/hy.js | 18 +
src/ui/static/js/datepicker/locales/id.js | 19 +
src/ui/static/js/datepicker/locales/is.js | 14 +
src/ui/static/js/datepicker/locales/it-CH.js | 20 +
src/ui/static/js/datepicker/locales/it.js | 18 +
src/ui/static/js/datepicker/locales/ja.js | 17 +
src/ui/static/js/datepicker/locales/ka.js | 17 +
src/ui/static/js/datepicker/locales/kk.js | 15 +
src/ui/static/js/datepicker/locales/km.js | 15 +
src/ui/static/js/datepicker/locales/ko.js | 18 +
src/ui/static/js/datepicker/locales/lt.js | 19 +
src/ui/static/js/datepicker/locales/lv.js | 18 +
src/ui/static/js/datepicker/locales/me.js | 17 +
src/ui/static/js/datepicker/locales/mk.js | 15 +
src/ui/static/js/datepicker/locales/mn.js | 17 +
src/ui/static/js/datepicker/locales/mr.js | 18 +
src/ui/static/js/datepicker/locales/ms.js | 15 +
src/ui/static/js/datepicker/locales/nl-BE.js | 18 +
src/ui/static/js/datepicker/locales/nl.js | 18 +
src/ui/static/js/datepicker/locales/no.js | 18 +
src/ui/static/js/datepicker/locales/oc.js | 17 +
src/ui/static/js/datepicker/locales/pl.js | 17 +
src/ui/static/js/datepicker/locales/pt-BR.js | 17 +
src/ui/static/js/datepicker/locales/pt.js | 18 +
src/ui/static/js/datepicker/locales/ro.js | 17 +
src/ui/static/js/datepicker/locales/ru.js | 18 +
src/ui/static/js/datepicker/locales/si.js | 18 +
src/ui/static/js/datepicker/locales/sk.js | 18 +
src/ui/static/js/datepicker/locales/sl.js | 15 +
src/ui/static/js/datepicker/locales/sq.js | 18 +
.../static/js/datepicker/locales/sr-latn.js | 16 +
src/ui/static/js/datepicker/locales/sr.js | 16 +
src/ui/static/js/datepicker/locales/sv.js | 17 +
src/ui/static/js/datepicker/locales/sw.js | 15 +
src/ui/static/js/datepicker/locales/ta.js | 18 +
src/ui/static/js/datepicker/locales/tg.js | 19 +
src/ui/static/js/datepicker/locales/th.js | 14 +
src/ui/static/js/datepicker/locales/tk.js | 18 +
src/ui/static/js/datepicker/locales/tr.js | 17 +
src/ui/static/js/datepicker/locales/uk.js | 17 +
.../static/js/datepicker/locales/uz-cyrl.js | 18 +
.../static/js/datepicker/locales/uz-latn.js | 18 +
src/ui/static/js/datepicker/locales/vi.js | 16 +
src/ui/static/js/datepicker/locales/zh-CN.js | 19 +
src/ui/static/js/datepicker/locales/zh-TW.js | 20 +
src/ui/static/js/datepicker/main.js | 4 +
.../js/datepicker/options/defaultOptions.js | 38 +
.../js/datepicker/options/processOptions.js | 288 ++
src/ui/static/js/datepicker/picker/Picker.js | 389 +++
.../picker/templates/calendarWeeksTemplate.js | 8 +
.../picker/templates/daysTemplate.js | 8 +
.../picker/templates/pickerTemplate.js | 23 +
.../js/datepicker/picker/views/DaysView.js | 238 ++
.../js/datepicker/picker/views/MonthsView.js | 210 ++
.../static/js/datepicker/picker/views/View.js | 55 +
.../js/datepicker/picker/views/YearsView.js | 176 ++
src/ui/static/js/logs.js | 48 +-
src/ui/templates/head.html | 8 +-
src/ui/templates/home.html | 14 +-
src/ui/templates/logs.html | 16 +-
src/ui/templates/menu.html | 14 +-
249 files changed, 6389 insertions(+), 3167 deletions(-)
delete mode 100644 src/ui/static/css/air-datepicker/air-datepicker.css
create mode 100644 src/ui/static/css/datepicker-foundation.css
create mode 100644 src/ui/static/css/datepicker-foundation.min.css
create mode 100644 src/ui/static/css/datepicker.css
create mode 100644 src/ui/static/css/datepicker.min.css
delete mode 100644 src/ui/static/js/air-datepicker/air-datepicker.d.ts
delete mode 100644 src/ui/static/js/air-datepicker/air-datepicker.js
delete mode 100644 src/ui/static/js/air-datepicker/index.es.js
delete mode 100644 src/ui/static/js/air-datepicker/locale/ar.d.ts
delete mode 100644 src/ui/static/js/air-datepicker/locale/ar.js
delete mode 100644 src/ui/static/js/air-datepicker/locale/cs.d.ts
delete mode 100644 src/ui/static/js/air-datepicker/locale/cs.js
delete mode 100644 src/ui/static/js/air-datepicker/locale/da.d.ts
delete mode 100644 src/ui/static/js/air-datepicker/locale/da.js
delete mode 100644 src/ui/static/js/air-datepicker/locale/de.d.ts
delete mode 100644 src/ui/static/js/air-datepicker/locale/de.js
delete mode 100644 src/ui/static/js/air-datepicker/locale/en.d.ts
delete mode 100644 src/ui/static/js/air-datepicker/locale/en.js
delete mode 100644 src/ui/static/js/air-datepicker/locale/es.d.ts
delete mode 100644 src/ui/static/js/air-datepicker/locale/es.js
delete mode 100644 src/ui/static/js/air-datepicker/locale/fi.d.ts
delete mode 100644 src/ui/static/js/air-datepicker/locale/fi.js
delete mode 100644 src/ui/static/js/air-datepicker/locale/fr.d.ts
delete mode 100644 src/ui/static/js/air-datepicker/locale/fr.js
delete mode 100644 src/ui/static/js/air-datepicker/locale/hu.d.ts
delete mode 100644 src/ui/static/js/air-datepicker/locale/hu.js
delete mode 100644 src/ui/static/js/air-datepicker/locale/it.d.ts
delete mode 100644 src/ui/static/js/air-datepicker/locale/it.js
delete mode 100644 src/ui/static/js/air-datepicker/locale/ja.d.ts
delete mode 100644 src/ui/static/js/air-datepicker/locale/ja.js
delete mode 100644 src/ui/static/js/air-datepicker/locale/ko.d.ts
delete mode 100644 src/ui/static/js/air-datepicker/locale/ko.js
delete mode 100644 src/ui/static/js/air-datepicker/locale/nl.d.ts
delete mode 100644 src/ui/static/js/air-datepicker/locale/nl.js
delete mode 100644 src/ui/static/js/air-datepicker/locale/pl.d.ts
delete mode 100644 src/ui/static/js/air-datepicker/locale/pl.js
delete mode 100644 src/ui/static/js/air-datepicker/locale/pt-BR.d.ts
delete mode 100644 src/ui/static/js/air-datepicker/locale/pt-BR.js
delete mode 100644 src/ui/static/js/air-datepicker/locale/pt.d.ts
delete mode 100644 src/ui/static/js/air-datepicker/locale/pt.js
delete mode 100644 src/ui/static/js/air-datepicker/locale/ro.d.ts
delete mode 100644 src/ui/static/js/air-datepicker/locale/ro.js
delete mode 100644 src/ui/static/js/air-datepicker/locale/ru.d.ts
delete mode 100644 src/ui/static/js/air-datepicker/locale/ru.js
delete mode 100644 src/ui/static/js/air-datepicker/locale/si.d.ts
delete mode 100644 src/ui/static/js/air-datepicker/locale/si.js
delete mode 100644 src/ui/static/js/air-datepicker/locale/sk.d.ts
delete mode 100644 src/ui/static/js/air-datepicker/locale/sk.js
delete mode 100644 src/ui/static/js/air-datepicker/locale/sv.d.ts
delete mode 100644 src/ui/static/js/air-datepicker/locale/sv.js
delete mode 100644 src/ui/static/js/air-datepicker/locale/th.d.ts
delete mode 100644 src/ui/static/js/air-datepicker/locale/th.js
delete mode 100644 src/ui/static/js/air-datepicker/locale/tr.d.ts
delete mode 100644 src/ui/static/js/air-datepicker/locale/tr.js
delete mode 100644 src/ui/static/js/air-datepicker/locale/uk.d.ts
delete mode 100644 src/ui/static/js/air-datepicker/locale/uk.js
delete mode 100644 src/ui/static/js/air-datepicker/locale/zh.d.ts
delete mode 100644 src/ui/static/js/air-datepicker/locale/zh.js
create mode 100644 src/ui/static/js/datepicker/DateRangePicker.js
create mode 100644 src/ui/static/js/datepicker/Datepicker.js
create mode 100644 src/ui/static/js/datepicker/datepicker-full.js
create mode 100644 src/ui/static/js/datepicker/datepicker-full.min.js
create mode 100644 src/ui/static/js/datepicker/datepicker.min.js
create mode 100644 src/ui/static/js/datepicker/events/functions.js
create mode 100644 src/ui/static/js/datepicker/events/inputFieldListeners.js
create mode 100644 src/ui/static/js/datepicker/events/otherListeners.js
create mode 100644 src/ui/static/js/datepicker/events/pickerListeners.js
create mode 100644 src/ui/static/js/datepicker/i18n/base-locales.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/ar-DZ.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/ar-tn.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/ar.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/az.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/bg.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/bm.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/bn.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/br.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/bs.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/ca.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/cs.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/cy.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/da.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/de.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/el.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/en-AU.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/en-CA.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/en-GB.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/en-IE.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/en-NZ.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/en-ZA.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/eo.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/es.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/et.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/eu.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/fa.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/fi.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/fo.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/fr-CH.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/fr.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/gl.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/he.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/hi.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/hr.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/hu.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/hy.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/id.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/is.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/it-CH.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/it.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/ja.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/ka.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/kk.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/km.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/ko.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/lt.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/lv.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/me.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/mk.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/mn.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/mr.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/ms.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/nl-BE.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/nl.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/no.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/oc.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/pl.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/pt-BR.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/pt.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/ro.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/ru.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/si.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/sk.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/sl.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/sq.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/sr-latn.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/sr.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/sv.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/sw.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/ta.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/tg.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/th.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/tk.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/tr.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/uk.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/uz-cyrl.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/uz-latn.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/vi.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/zh-CN.js
create mode 100644 src/ui/static/js/datepicker/i18n/locales/zh-TW.js
create mode 100644 src/ui/static/js/datepicker/lib/date-format.js
create mode 100644 src/ui/static/js/datepicker/lib/date.js
create mode 100644 src/ui/static/js/datepicker/lib/dom.js
create mode 100644 src/ui/static/js/datepicker/lib/event.js
create mode 100644 src/ui/static/js/datepicker/lib/utils.js
create mode 100644 src/ui/static/js/datepicker/locales/ar-DZ.js
create mode 100644 src/ui/static/js/datepicker/locales/ar-tn.js
create mode 100644 src/ui/static/js/datepicker/locales/ar.js
create mode 100644 src/ui/static/js/datepicker/locales/az.js
create mode 100644 src/ui/static/js/datepicker/locales/bg.js
create mode 100644 src/ui/static/js/datepicker/locales/bm.js
create mode 100644 src/ui/static/js/datepicker/locales/bn.js
create mode 100644 src/ui/static/js/datepicker/locales/br.js
create mode 100644 src/ui/static/js/datepicker/locales/bs.js
create mode 100644 src/ui/static/js/datepicker/locales/ca.js
create mode 100644 src/ui/static/js/datepicker/locales/cs.js
create mode 100644 src/ui/static/js/datepicker/locales/cy.js
create mode 100644 src/ui/static/js/datepicker/locales/da.js
create mode 100644 src/ui/static/js/datepicker/locales/de.js
create mode 100644 src/ui/static/js/datepicker/locales/el.js
create mode 100644 src/ui/static/js/datepicker/locales/en-AU.js
create mode 100644 src/ui/static/js/datepicker/locales/en-CA.js
create mode 100644 src/ui/static/js/datepicker/locales/en-GB.js
create mode 100644 src/ui/static/js/datepicker/locales/en-IE.js
create mode 100644 src/ui/static/js/datepicker/locales/en-NZ.js
create mode 100644 src/ui/static/js/datepicker/locales/en-ZA.js
create mode 100644 src/ui/static/js/datepicker/locales/eo.js
create mode 100644 src/ui/static/js/datepicker/locales/es.js
create mode 100644 src/ui/static/js/datepicker/locales/et.js
create mode 100644 src/ui/static/js/datepicker/locales/eu.js
create mode 100644 src/ui/static/js/datepicker/locales/fa.js
create mode 100644 src/ui/static/js/datepicker/locales/fi.js
create mode 100644 src/ui/static/js/datepicker/locales/fo.js
create mode 100644 src/ui/static/js/datepicker/locales/fr-CH.js
create mode 100644 src/ui/static/js/datepicker/locales/fr.js
create mode 100644 src/ui/static/js/datepicker/locales/gl.js
create mode 100644 src/ui/static/js/datepicker/locales/he.js
create mode 100644 src/ui/static/js/datepicker/locales/hi.js
create mode 100644 src/ui/static/js/datepicker/locales/hr.js
create mode 100644 src/ui/static/js/datepicker/locales/hu.js
create mode 100644 src/ui/static/js/datepicker/locales/hy.js
create mode 100644 src/ui/static/js/datepicker/locales/id.js
create mode 100644 src/ui/static/js/datepicker/locales/is.js
create mode 100644 src/ui/static/js/datepicker/locales/it-CH.js
create mode 100644 src/ui/static/js/datepicker/locales/it.js
create mode 100644 src/ui/static/js/datepicker/locales/ja.js
create mode 100644 src/ui/static/js/datepicker/locales/ka.js
create mode 100644 src/ui/static/js/datepicker/locales/kk.js
create mode 100644 src/ui/static/js/datepicker/locales/km.js
create mode 100644 src/ui/static/js/datepicker/locales/ko.js
create mode 100644 src/ui/static/js/datepicker/locales/lt.js
create mode 100644 src/ui/static/js/datepicker/locales/lv.js
create mode 100644 src/ui/static/js/datepicker/locales/me.js
create mode 100644 src/ui/static/js/datepicker/locales/mk.js
create mode 100644 src/ui/static/js/datepicker/locales/mn.js
create mode 100644 src/ui/static/js/datepicker/locales/mr.js
create mode 100644 src/ui/static/js/datepicker/locales/ms.js
create mode 100644 src/ui/static/js/datepicker/locales/nl-BE.js
create mode 100644 src/ui/static/js/datepicker/locales/nl.js
create mode 100644 src/ui/static/js/datepicker/locales/no.js
create mode 100644 src/ui/static/js/datepicker/locales/oc.js
create mode 100644 src/ui/static/js/datepicker/locales/pl.js
create mode 100644 src/ui/static/js/datepicker/locales/pt-BR.js
create mode 100644 src/ui/static/js/datepicker/locales/pt.js
create mode 100644 src/ui/static/js/datepicker/locales/ro.js
create mode 100644 src/ui/static/js/datepicker/locales/ru.js
create mode 100644 src/ui/static/js/datepicker/locales/si.js
create mode 100644 src/ui/static/js/datepicker/locales/sk.js
create mode 100644 src/ui/static/js/datepicker/locales/sl.js
create mode 100644 src/ui/static/js/datepicker/locales/sq.js
create mode 100644 src/ui/static/js/datepicker/locales/sr-latn.js
create mode 100644 src/ui/static/js/datepicker/locales/sr.js
create mode 100644 src/ui/static/js/datepicker/locales/sv.js
create mode 100644 src/ui/static/js/datepicker/locales/sw.js
create mode 100644 src/ui/static/js/datepicker/locales/ta.js
create mode 100644 src/ui/static/js/datepicker/locales/tg.js
create mode 100644 src/ui/static/js/datepicker/locales/th.js
create mode 100644 src/ui/static/js/datepicker/locales/tk.js
create mode 100644 src/ui/static/js/datepicker/locales/tr.js
create mode 100644 src/ui/static/js/datepicker/locales/uk.js
create mode 100644 src/ui/static/js/datepicker/locales/uz-cyrl.js
create mode 100644 src/ui/static/js/datepicker/locales/uz-latn.js
create mode 100644 src/ui/static/js/datepicker/locales/vi.js
create mode 100644 src/ui/static/js/datepicker/locales/zh-CN.js
create mode 100644 src/ui/static/js/datepicker/locales/zh-TW.js
create mode 100644 src/ui/static/js/datepicker/main.js
create mode 100644 src/ui/static/js/datepicker/options/defaultOptions.js
create mode 100644 src/ui/static/js/datepicker/options/processOptions.js
create mode 100644 src/ui/static/js/datepicker/picker/Picker.js
create mode 100644 src/ui/static/js/datepicker/picker/templates/calendarWeeksTemplate.js
create mode 100644 src/ui/static/js/datepicker/picker/templates/daysTemplate.js
create mode 100644 src/ui/static/js/datepicker/picker/templates/pickerTemplate.js
create mode 100644 src/ui/static/js/datepicker/picker/views/DaysView.js
create mode 100644 src/ui/static/js/datepicker/picker/views/MonthsView.js
create mode 100644 src/ui/static/js/datepicker/picker/views/View.js
create mode 100644 src/ui/static/js/datepicker/picker/views/YearsView.js
diff --git a/src/ui/static/css/air-datepicker/air-datepicker.css b/src/ui/static/css/air-datepicker/air-datepicker.css
deleted file mode 100644
index 6d6be2281..000000000
--- a/src/ui/static/css/air-datepicker/air-datepicker.css
+++ /dev/null
@@ -1,18 +0,0 @@
-.air-datepicker-cell.-day-.-other-month-,.air-datepicker-cell.-year-.-other-decade-{color:var(--adp-color-other-month)}.air-datepicker-cell.-day-.-other-month-:hover,.air-datepicker-cell.-year-.-other-decade-:hover{color:var(--adp-color-other-month-hover)}.-disabled-.-focus-.air-datepicker-cell.-day-.-other-month-,.-disabled-.-focus-.air-datepicker-cell.-year-.-other-decade-{color:var(--adp-color-other-month)}.-selected-.air-datepicker-cell.-day-.-other-month-,.-selected-.air-datepicker-cell.-year-.-other-decade-{color:#fff;background:var(--adp-background-color-selected-other-month)}.-selected-.-focus-.air-datepicker-cell.-day-.-other-month-,.-selected-.-focus-.air-datepicker-cell.-year-.-other-decade-{background:var(--adp-background-color-selected-other-month-focused)}.-in-range-.air-datepicker-cell.-day-.-other-month-,.-in-range-.air-datepicker-cell.-year-.-other-decade-{background-color:var(--adp-background-color-in-range);color:var(--adp-color)}.-in-range-.-focus-.air-datepicker-cell.-day-.-other-month-,.-in-range-.-focus-.air-datepicker-cell.-year-.-other-decade-{background-color:var(--adp-background-color-in-range-focused)}.air-datepicker-cell.-day-.-other-month-:empty,.air-datepicker-cell.-year-.-other-decade-:empty{background:none;border:none}.air-datepicker-cell{border-radius:var(--adp-cell-border-radius);box-sizing:border-box;cursor:pointer;display:flex;position:relative;align-items:center;justify-content:center;z-index:1}.air-datepicker-cell.-focus-{background:var(--adp-cell-background-color-hover)}.air-datepicker-cell.-current-{color:var(--adp-color-current-date)}.air-datepicker-cell.-current-.-focus-{color:var(--adp-color)}.air-datepicker-cell.-current-.-in-range-{color:var(--adp-color-current-date)}.air-datepicker-cell.-disabled-{cursor:default;color:var(--adp-color-disabled)}.air-datepicker-cell.-disabled-.-focus-{color:var(--adp-color-disabled)}.air-datepicker-cell.-disabled-.-in-range-{color:var(--adp-color-disabled-in-range)}.air-datepicker-cell.-disabled-.-current-.-focus-{color:var(--adp-color-disabled)}.air-datepicker-cell.-in-range-{background:var(--adp-cell-background-color-in-range);border-radius:0}.air-datepicker-cell.-in-range-:hover{background:var(--adp-cell-background-color-in-range-hover)}.air-datepicker-cell.-range-from-{border:1px solid var(--adp-cell-border-color-in-range);background-color:var(--adp-cell-background-color-in-range);border-radius:var(--adp-cell-border-radius) 0 0 var(--adp-cell-border-radius)}.air-datepicker-cell.-range-to-{border:1px solid var(--adp-cell-border-color-in-range);background-color:var(--adp-cell-background-color-in-range);border-radius:0 var(--adp-cell-border-radius) var(--adp-cell-border-radius) 0}.air-datepicker-cell.-range-to-.-range-from-{border-radius:var(--adp-cell-border-radius)}.air-datepicker-cell.-selected-{color:#fff;border:none;background:var(--adp-cell-background-color-selected)}.air-datepicker-cell.-selected-.-current-{color:#fff;background:var(--adp-cell-background-color-selected)}.air-datepicker-cell.-selected-.-focus-{background:var(--adp-cell-background-color-selected-hover)}
-
-.air-datepicker-body{transition:all var(--adp-transition-duration) var(--adp-transition-ease)}.air-datepicker-body.-hidden-{display:none}.air-datepicker-body--day-names{display:grid;grid-template-columns:repeat(7, var(--adp-day-cell-width));margin:8px 0 3px}.air-datepicker-body--day-name{color:var(--adp-day-name-color);display:flex;align-items:center;justify-content:center;flex:1;text-align:center;text-transform:uppercase;font-size:.8em}.air-datepicker-body--day-name.-clickable-{cursor:pointer}.air-datepicker-body--day-name.-clickable-:hover{color:var(--adp-day-name-color-hover)}.air-datepicker-body--cells{display:grid}.air-datepicker-body--cells.-days-{grid-template-columns:repeat(7, var(--adp-day-cell-width));grid-auto-rows:var(--adp-day-cell-height)}.air-datepicker-body--cells.-months-{grid-template-columns:repeat(3, 1fr);grid-auto-rows:var(--adp-month-cell-height)}.air-datepicker-body--cells.-years-{grid-template-columns:repeat(4, 1fr);grid-auto-rows:var(--adp-year-cell-height)}
-
-.air-datepicker-nav{display:flex;justify-content:space-between;border-bottom:1px solid var(--adp-border-color-inner);min-height:var(--adp-nav-height);padding:var(--adp-padding);box-sizing:content-box}.-only-timepicker- .air-datepicker-nav{display:none}.air-datepicker-nav--title,.air-datepicker-nav--action{display:flex;cursor:pointer;align-items:center;justify-content:center}.air-datepicker-nav--action{width:var(--adp-nav-action-size);border-radius:var(--adp-border-radius);-webkit-user-select:none;-moz-user-select:none;user-select:none}.air-datepicker-nav--action:hover{background:var(--adp-background-color-hover)}.air-datepicker-nav--action:active{background:var(--adp-background-color-active)}.air-datepicker-nav--action.-disabled-{visibility:hidden}.air-datepicker-nav--action svg{width:32px;height:32px}.air-datepicker-nav--action path{fill:none;stroke:var(--adp-nav-arrow-color);stroke-width:2px}.air-datepicker-nav--title{border-radius:var(--adp-border-radius);padding:0 8px}.air-datepicker-nav--title i{font-style:normal;color:var(--adp-nav-color-secondary);margin-left:.3em}.air-datepicker-nav--title:hover{background:var(--adp-background-color-hover)}.air-datepicker-nav--title:active{background:var(--adp-background-color-active)}.air-datepicker-nav--title.-disabled-{cursor:default;background:none}
-
-.air-datepicker-buttons{display:grid;grid-auto-columns:1fr;grid-auto-flow:column}.air-datepicker-button{display:inline-flex;color:var(--adp-btn-color);border-radius:var(--adp-btn-border-radius);cursor:pointer;height:var(--adp-btn-height);border:none;background:rgba(255,255,255,0)}.air-datepicker-button:hover{color:var(--adp-btn-color-hover);background:var(--adp-btn-background-color-hover)}.air-datepicker-button:focus{color:var(--adp-btn-color-hover);background:var(--adp-btn-background-color-hover);outline:none}.air-datepicker-button:active{background:var(--adp-btn-background-color-active)}.air-datepicker-button span{outline:none;display:flex;align-items:center;justify-content:center;width:100%;height:100%}
-
-.air-datepicker-time{display:grid;grid-template-columns:-webkit-max-content 1fr;grid-template-columns:max-content 1fr;grid-column-gap:12px;align-items:center;position:relative;padding:0 var(--adp-time-padding-inner)}.-only-timepicker- .air-datepicker-time{border-top:none}.air-datepicker-time--current{display:flex;align-items:center;flex:1;font-size:14px;text-align:center}.air-datepicker-time--current-colon{margin:0 2px 3px;line-height:1}.air-datepicker-time--current-hours,.air-datepicker-time--current-minutes{line-height:1;font-size:19px;font-family:"Century Gothic", CenturyGothic, AppleGothic, sans-serif;position:relative;z-index:1}.air-datepicker-time--current-hours:after,.air-datepicker-time--current-minutes:after{content:'';background:var(--adp-background-color-hover);border-radius:var(--adp-border-radius);position:absolute;left:-2px;top:-3px;right:-2px;bottom:-2px;z-index:-1;opacity:0}.air-datepicker-time--current-hours.-focus-:after,.air-datepicker-time--current-minutes.-focus-:after{opacity:1}.air-datepicker-time--current-ampm{text-transform:uppercase;align-self:flex-end;color:var(--adp-time-day-period-color);margin-left:6px;font-size:11px;margin-bottom:1px}.air-datepicker-time--row{display:flex;align-items:center;font-size:11px;height:17px;background:linear-gradient(to right, var(--adp-time-track-color), var(--adp-time-track-color)) left 50%/100% var(--adp-time-track-height) no-repeat}.air-datepicker-time--row:first-child{margin-bottom:4px}.air-datepicker-time--row input[type='range']{background:none;cursor:pointer;flex:1;height:100%;width:100%;padding:0;margin:0;-webkit-appearance:none}.air-datepicker-time--row input[type='range']::-webkit-slider-thumb{-webkit-appearance:none}.air-datepicker-time--row input[type='range']::-ms-tooltip{display:none}.air-datepicker-time--row input[type='range']:hover::-webkit-slider-thumb{border-color:var(--adp-time-track-color-hover)}.air-datepicker-time--row input[type='range']:hover::-moz-range-thumb{border-color:var(--adp-time-track-color-hover)}.air-datepicker-time--row input[type='range']:hover::-ms-thumb{border-color:var(--adp-time-track-color-hover)}.air-datepicker-time--row input[type='range']:focus{outline:none}.air-datepicker-time--row input[type='range']:focus::-webkit-slider-thumb{background:var(--adp-cell-background-color-selected);border-color:var(--adp-cell-background-color-selected)}.air-datepicker-time--row input[type='range']:focus::-moz-range-thumb{background:var(--adp-cell-background-color-selected);border-color:var(--adp-cell-background-color-selected)}.air-datepicker-time--row input[type='range']:focus::-ms-thumb{background:var(--adp-cell-background-color-selected);border-color:var(--adp-cell-background-color-selected)}.air-datepicker-time--row input[type='range']::-webkit-slider-thumb{box-sizing:border-box;height:12px;width:12px;border-radius:3px;border:1px solid var(--adp-time-track-color);background:#fff;cursor:pointer;-webkit-transition:background var(--adp-transition-duration);transition:background var(--adp-transition-duration)}.air-datepicker-time--row input[type='range']::-moz-range-thumb{box-sizing:border-box;height:12px;width:12px;border-radius:3px;border:1px solid var(--adp-time-track-color);background:#fff;cursor:pointer;-moz-transition:background var(--adp-transition-duration);transition:background var(--adp-transition-duration)}.air-datepicker-time--row input[type='range']::-ms-thumb{box-sizing:border-box;height:12px;width:12px;border-radius:3px;border:1px solid var(--adp-time-track-color);background:#fff;cursor:pointer;-ms-transition:background var(--adp-transition-duration);transition:background var(--adp-transition-duration)}.air-datepicker-time--row input[type='range']::-webkit-slider-thumb{margin-top:calc(var(--adp-time-thumb-size) / 2 * -1)}.air-datepicker-time--row input[type='range']::-webkit-slider-runnable-track{border:none;height:var(--adp-time-track-height);cursor:pointer;color:transparent;background:transparent}.air-datepicker-time--row input[type='range']::-moz-range-track{border:none;height:var(--adp-time-track-height);cursor:pointer;color:transparent;background:transparent}.air-datepicker-time--row input[type='range']::-ms-track{border:none;height:var(--adp-time-track-height);cursor:pointer;color:transparent;background:transparent}.air-datepicker-time--row input[type='range']::-ms-fill-lower{background:transparent}.air-datepicker-time--row input[type='range']::-ms-fill-upper{background:transparent}
-
-.air-datepicker{--adp-font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";--adp-font-size: 14px;--adp-width: 246px;--adp-z-index: 100;--adp-padding: 4px;--adp-grid-areas:
- 'nav'
- 'body'
- 'timepicker'
- 'buttons';--adp-transition-duration: .3s;--adp-transition-ease: ease-out;--adp-transition-offset: 8px;--adp-background-color: #fff;--adp-background-color-hover: #f0f0f0;--adp-background-color-active: #eaeaea;--adp-background-color-in-range: rgba(92, 196, 239, .1);--adp-background-color-in-range-focused: rgba(92, 196, 239, .2);--adp-background-color-selected-other-month-focused: #8ad5f4;--adp-background-color-selected-other-month: #a2ddf6;--adp-color: #4a4a4a;--adp-color-secondary: #9c9c9c;--adp-accent-color: #4eb5e6;--adp-color-current-date: var(--adp-accent-color);--adp-color-other-month: #dedede;--adp-color-disabled: #aeaeae;--adp-color-disabled-in-range: #939393;--adp-color-other-month-hover: #c5c5c5;--adp-border-color: #dbdbdb;--adp-border-color-inner: #efefef;--adp-border-radius: 4px;--adp-border-color-inline: #d7d7d7;--adp-nav-height: 32px;--adp-nav-arrow-color: var(--adp-color-secondary);--adp-nav-action-size: 32px;--adp-nav-color-secondary: var(--adp-color-secondary);--adp-day-name-color: #ff9a19;--adp-day-name-color-hover: #8ad5f4;--adp-day-cell-width: 1fr;--adp-day-cell-height: 32px;--adp-month-cell-height: 42px;--adp-year-cell-height: 56px;--adp-pointer-size: 10px;--adp-poiner-border-radius: 2px;--adp-pointer-offset: 14px;--adp-cell-border-radius: 4px;--adp-cell-background-color-hover: var(--adp-background-color-hover);--adp-cell-background-color-selected: #5cc4ef;--adp-cell-background-color-selected-hover: #45bced;--adp-cell-background-color-in-range: rgba(92, 196, 239, 0.1);--adp-cell-background-color-in-range-hover: rgba(92, 196, 239, 0.2);--adp-cell-border-color-in-range: var(--adp-cell-background-color-selected);--adp-btn-height: 32px;--adp-btn-color: var(--adp-accent-color);--adp-btn-color-hover: var(--adp-color);--adp-btn-border-radius: var(--adp-border-radius);--adp-btn-background-color-hover: var(--adp-background-color-hover);--adp-btn-background-color-active: var(--adp-background-color-active);--adp-time-track-height: 1px;--adp-time-track-color: #dedede;--adp-time-track-color-hover: #b1b1b1;--adp-time-thumb-size: 12px;--adp-time-padding-inner: 10px;--adp-time-day-period-color: var(--adp-color-secondary);--adp-mobile-font-size: 16px;--adp-mobile-nav-height: 40px;--adp-mobile-width: 320px;--adp-mobile-day-cell-height: 38px;--adp-mobile-month-cell-height: 48px;--adp-mobile-year-cell-height: 64px}.air-datepicker-overlay{--adp-overlay-background-color: rgba(0, 0, 0, .3);--adp-overlay-transition-duration: .3s;--adp-overlay-transition-ease: ease-out;--adp-overlay-z-index: 99}
-
-.air-datepicker{background:var(--adp-background-color);border:1px solid var(--adp-border-color);box-shadow:0 4px 12px rgba(0,0,0,0.15);border-radius:var(--adp-border-radius);box-sizing:content-box;display:grid;grid-template-columns:1fr;grid-template-rows:repeat(4, -webkit-max-content);grid-template-rows:repeat(4, max-content);grid-template-areas:var(--adp-grid-areas);font-family:var(--adp-font-family),sans-serif;font-size:var(--adp-font-size);color:var(--adp-color);width:var(--adp-width);position:absolute;transition:opacity var(--adp-transition-duration) var(--adp-transition-ease),transform var(--adp-transition-duration) var(--adp-transition-ease);z-index:var(--adp-z-index)}.air-datepicker:not(.-custom-position-){opacity:0}.air-datepicker.-from-top-{transform:translateY(calc(var(--adp-transition-offset) * -1))}.air-datepicker.-from-right-{transform:translateX(var(--adp-transition-offset))}.air-datepicker.-from-bottom-{transform:translateY(var(--adp-transition-offset))}.air-datepicker.-from-left-{transform:translateX(calc(var(--adp-transition-offset) * -1))}.air-datepicker.-active-:not(.-custom-position-){transform:translate(0, 0);opacity:1}.air-datepicker.-active-.-custom-position-{transition:none}.air-datepicker.-inline-{border-color:var(--adp-border-color-inline);box-shadow:none;position:static;left:auto;right:auto;opacity:1;transform:none}.air-datepicker.-inline- .air-datepicker--pointer{display:none}.air-datepicker.-is-mobile-{--adp-font-size: var(--adp-mobile-font-size);--adp-day-cell-height: var(--adp-mobile-day-cell-height);--adp-month-cell-height: var(--adp-mobile-month-cell-height);--adp-year-cell-height: var(--adp-mobile-year-cell-height);--adp-nav-height: var(--adp-mobile-nav-height);--adp-nav-action-size: var(--adp-mobile-nav-height);position:fixed;width:var(--adp-mobile-width);border:none}.air-datepicker.-is-mobile- *{-webkit-tap-highlight-color:transparent}.air-datepicker.-is-mobile- .air-datepicker--pointer{display:none}.air-datepicker.-is-mobile-:not(.-custom-position-){transform:translate(-50%, calc(-50% + var(--adp-transition-offset)))}.air-datepicker.-is-mobile-.-active-:not(.-custom-position-){transform:translate(-50%, -50%)}.air-datepicker.-custom-position-{transition:none}.air-datepicker-global-container{position:absolute;left:0;top:0}.air-datepicker--pointer{--pointer-half-size: calc(var(--adp-pointer-size) / 2);position:absolute;width:var(--adp-pointer-size);height:var(--adp-pointer-size);z-index:-1}.air-datepicker--pointer:after{content:'';position:absolute;background:#fff;border-top:1px solid var(--adp-border-color-inline);border-right:1px solid var(--adp-border-color-inline);border-top-right-radius:var(--adp-poiner-border-radius);width:var(--adp-pointer-size);height:var(--adp-pointer-size);box-sizing:border-box}.-top-left- .air-datepicker--pointer,.-top-center- .air-datepicker--pointer,.-top-right- .air-datepicker--pointer,[data-popper-placement^='top'] .air-datepicker--pointer{top:calc(100% - var(--pointer-half-size) + 1px)}.-top-left- .air-datepicker--pointer:after,.-top-center- .air-datepicker--pointer:after,.-top-right- .air-datepicker--pointer:after,[data-popper-placement^='top'] .air-datepicker--pointer:after{transform:rotate(135deg)}.-right-top- .air-datepicker--pointer,.-right-center- .air-datepicker--pointer,.-right-bottom- .air-datepicker--pointer,[data-popper-placement^='right'] .air-datepicker--pointer{right:calc(100% - var(--pointer-half-size) + 1px)}.-right-top- .air-datepicker--pointer:after,.-right-center- .air-datepicker--pointer:after,.-right-bottom- .air-datepicker--pointer:after,[data-popper-placement^='right'] .air-datepicker--pointer:after{transform:rotate(225deg)}.-bottom-left- .air-datepicker--pointer,.-bottom-center- .air-datepicker--pointer,.-bottom-right- .air-datepicker--pointer,[data-popper-placement^='bottom'] .air-datepicker--pointer{bottom:calc(100% - var(--pointer-half-size) + 1px)}.-bottom-left- .air-datepicker--pointer:after,.-bottom-center- .air-datepicker--pointer:after,.-bottom-right- .air-datepicker--pointer:after,[data-popper-placement^='bottom'] .air-datepicker--pointer:after{transform:rotate(315deg)}.-left-top- .air-datepicker--pointer,.-left-center- .air-datepicker--pointer,.-left-bottom- .air-datepicker--pointer,[data-popper-placement^='left'] .air-datepicker--pointer{left:calc(100% - var(--pointer-half-size) + 1px)}.-left-top- .air-datepicker--pointer:after,.-left-center- .air-datepicker--pointer:after,.-left-bottom- .air-datepicker--pointer:after,[data-popper-placement^='left'] .air-datepicker--pointer:after{transform:rotate(45deg)}.-top-left- .air-datepicker--pointer,.-bottom-left- .air-datepicker--pointer{left:var(--adp-pointer-offset)}.-top-right- .air-datepicker--pointer,.-bottom-right- .air-datepicker--pointer{right:var(--adp-pointer-offset)}.-top-center- .air-datepicker--pointer,.-bottom-center- .air-datepicker--pointer{left:calc(50% - var(--adp-pointer-size) / 2)}.-left-top- .air-datepicker--pointer,.-right-top- .air-datepicker--pointer{top:var(--adp-pointer-offset)}.-left-bottom- .air-datepicker--pointer,.-right-bottom- .air-datepicker--pointer{bottom:var(--adp-pointer-offset)}.-left-center- .air-datepicker--pointer,.-right-center- .air-datepicker--pointer{top:calc(50% - var(--adp-pointer-size) / 2)}.air-datepicker--navigation{grid-area:nav}.air-datepicker--content{box-sizing:content-box;padding:var(--adp-padding);grid-area:body}.-only-timepicker- .air-datepicker--content{display:none}.air-datepicker--time{grid-area:timepicker}.air-datepicker--buttons{grid-area:buttons}.air-datepicker--buttons,.air-datepicker--time{padding:var(--adp-padding);border-top:1px solid var(--adp-border-color-inner)}.air-datepicker-overlay{position:fixed;background:var(--adp-overlay-background-color);left:0;top:0;width:0;height:0;opacity:0;transition:opacity var(--adp-overlay-transition-duration) var(--adp-overlay-transition-ease),left 0s,height 0s,width 0s;transition-delay:0s,var(--adp-overlay-transition-duration),var(--adp-overlay-transition-duration),var(--adp-overlay-transition-duration);z-index:var(--adp-overlay-z-index)}.air-datepicker-overlay.-active-{opacity:1;width:100%;height:100%;transition:opacity var(--adp-overlay-transition-duration) var(--adp-overlay-transition-ease),height 0s,width 0s}
-
diff --git a/src/ui/static/css/datepicker-foundation.css b/src/ui/static/css/datepicker-foundation.css
new file mode 100644
index 000000000..eb16026cf
--- /dev/null
+++ b/src/ui/static/css/datepicker-foundation.css
@@ -0,0 +1,275 @@
+.datepicker {
+ display: none;
+}
+
+.datepicker.active {
+ display: block;
+}
+
+.datepicker-dropdown {
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: 10;
+ padding-top: 4px;
+}
+
+.datepicker-dropdown.datepicker-orient-top {
+ padding-top: 0;
+ padding-bottom: 4px;
+}
+
+.datepicker-picker {
+ display: inline-block;
+ border-radius: 0;
+ background-color: #fefefe;
+}
+
+.datepicker-dropdown .datepicker-picker {
+ box-shadow: 0 0 0 1px #cacaca;
+}
+
+.datepicker-picker span {
+ display: block;
+ flex: 1;
+ border: 0;
+ border-radius: 0;
+ cursor: default;
+ text-align: center;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+.datepicker-main {
+ padding: 2px;
+}
+
+.datepicker-footer {
+ box-shadow: inset 0 1px 1px rgba(10, 10, 10, 0.1);
+ background-color: #e6e6e6;
+}
+
+.datepicker-grid,
+.datepicker-view .days-of-week,
+.datepicker-view,
+.datepicker-controls {
+ display: flex;
+}
+
+.datepicker-grid {
+ flex-wrap: wrap;
+}
+
+.datepicker-view .days .datepicker-cell,
+.datepicker-view .dow {
+ flex-basis: 14.2857142857%;
+}
+
+.datepicker-view.datepicker-grid .datepicker-cell {
+ flex-basis: 25%;
+}
+
+.datepicker-cell,
+.datepicker-view .week {
+ height: 2.25rem;
+ line-height: 2.25rem;
+}
+
+.datepicker-title {
+ box-shadow: inset 0 -1px 1px rgba(10, 10, 10, 0.1);
+ background-color: #e6e6e6;
+ padding: 0.375rem 0.75rem;
+ text-align: center;
+ font-weight: bold;
+}
+
+.datepicker-header .datepicker-controls {
+ padding: 2px 2px 0;
+}
+
+.datepicker-controls .button {
+ margin: 0;
+ background-color: #fefefe;
+ color: #0a0a0a;
+}
+
+.datepicker-controls .button:hover,
+.datepicker-controls .button:focus {
+ background-color: #d8d8d8;
+}
+
+.datepicker-controls .button:hover[disabled],
+.datepicker-controls .button:focus[disabled] {
+ opacity: 0.25;
+ background-color: #fefefe;
+ color: #0a0a0a;
+}
+
+.datepicker-header .datepicker-controls .button {
+ border-color: transparent;
+ font-weight: bold;
+}
+
+.datepicker-footer .datepicker-controls .button {
+ margin: calc(0.375rem - 1px) 0.375rem;
+ border-radius: 0;
+ width: 100%;
+ font-size: 0.75rem;
+}
+
+.datepicker-controls .view-switch {
+ flex: auto;
+}
+
+.datepicker-controls .prev-btn,
+.datepicker-controls .next-btn {
+ padding-right: 0.375rem;
+ padding-left: 0.375rem;
+ width: 2.25rem;
+}
+
+.datepicker-controls .prev-btn.disabled,
+.datepicker-controls .next-btn.disabled {
+ visibility: hidden;
+}
+
+.datepicker-view .dow {
+ height: 1.5rem;
+ line-height: 1.5rem;
+ font-size: 0.875rem;
+ font-weight: bold;
+}
+
+.datepicker-view .week {
+ width: 2.25rem;
+ color: #8a8a8a;
+ font-size: 0.75rem;
+}
+
+@media (max-width: 22.5rem) {
+ .datepicker-view .week {
+ width: 1.96875rem;
+ }
+}
+
+.datepicker-grid {
+ width: 15.75rem;
+}
+
+@media (max-width: 22.5rem) {
+ .calendar-weeks + .days .datepicker-grid {
+ width: 13.78125rem;
+ }
+}
+
+.datepicker-cell:not(.disabled):hover {
+ background-color: #f8f8f8;
+ cursor: pointer;
+}
+
+.datepicker-cell.focused:not(.selected) {
+ background-color: #f1f1f1;
+}
+
+.datepicker-cell.selected,
+.datepicker-cell.selected:hover {
+ background-color: #1779ba;
+ color: #fefefe;
+ font-weight: semibold;
+}
+
+.datepicker-cell.disabled {
+ color: #e6e6e6;
+}
+
+.datepicker-cell.prev:not(.disabled),
+.datepicker-cell.next:not(.disabled) {
+ color: #cacaca;
+}
+
+.datepicker-cell.prev.selected,
+.datepicker-cell.next.selected {
+ color: #e5e5e5;
+}
+
+.datepicker-cell.highlighted:not(.selected):not(.range):not(.today) {
+ border-radius: 0;
+ background-color: #f7f7f7;
+}
+
+.datepicker-cell.highlighted:not(.selected):not(.range):not(.today):not(.disabled):hover {
+ background-color: #f1f1f1;
+}
+
+.datepicker-cell.highlighted:not(.selected):not(.range):not(.today).focused {
+ background-color: #f1f1f1;
+}
+
+.datepicker-cell.today:not(.selected) {
+ background-color: #d7ecfa;
+}
+
+.datepicker-cell.today:not(.selected):not(.disabled) {
+ color: #8a8a8a;
+}
+
+.datepicker-cell.today.focused:not(.selected) {
+ background-color: #cbe7f9;
+}
+
+.datepicker-cell.range-end:not(.selected),
+.datepicker-cell.range-start:not(.selected) {
+ background-color: #767676;
+ color: #fefefe;
+}
+
+.datepicker-cell.range-end.focused:not(.selected),
+.datepicker-cell.range-start.focused:not(.selected) {
+ background-color: #707070;
+}
+
+.datepicker-cell.range-start {
+ border-radius: 0 0 0 0;
+}
+
+.datepicker-cell.range-end {
+ border-radius: 0 0 0 0;
+}
+
+.datepicker-cell.range {
+ border-radius: 0;
+ background-color: #e6e6e6;
+}
+
+.datepicker-cell.range:not(.disabled):not(.focused):not(.today):hover {
+ background-color: #e0e0e0;
+}
+
+.datepicker-cell.range.disabled {
+ color: #cdcdcd;
+}
+
+.datepicker-cell.range.focused {
+ background-color: #d9d9d9;
+}
+
+.datepicker-cell.range.today {
+ background-color: #b3dbf6;
+}
+
+.datepicker-view.datepicker-grid .datepicker-cell {
+ height: 4.5rem;
+ line-height: 4.5rem;
+}
+
+.datepicker-input.in-edit {
+ border-color: #a4a4a4;
+}
+
+.datepicker-input.in-edit:focus,
+.datepicker-input.in-edit:active {
+ box-shadow: 0 0 0.25em 0.25em rgba(164, 164, 164, 0.2);
+}
\ No newline at end of file
diff --git a/src/ui/static/css/datepicker-foundation.min.css b/src/ui/static/css/datepicker-foundation.min.css
new file mode 100644
index 000000000..8465be876
--- /dev/null
+++ b/src/ui/static/css/datepicker-foundation.min.css
@@ -0,0 +1 @@
+.datepicker{display:none}.datepicker.active{display:block}.datepicker-dropdown{left:0;padding-top:4px;position:absolute;top:0;z-index:10}.datepicker-dropdown.datepicker-orient-top{padding-bottom:4px;padding-top:0}.datepicker-picker{background-color:#fefefe;border-radius:0;display:inline-block}.datepicker-dropdown .datepicker-picker{box-shadow:0 0 0 1px #cacaca}.datepicker-picker span{-webkit-touch-callout:none;border:0;border-radius:0;cursor:default;display:block;flex:1;text-align:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.datepicker-main{padding:2px}.datepicker-footer{background-color:#e6e6e6;box-shadow:inset 0 1px 1px hsla(0,0%,4%,.1)}.datepicker-controls,.datepicker-grid,.datepicker-view,.datepicker-view .days-of-week{display:flex}.datepicker-grid{flex-wrap:wrap}.datepicker-view .days .datepicker-cell,.datepicker-view .dow{flex-basis:14.2857142857%}.datepicker-view.datepicker-grid .datepicker-cell{flex-basis:25%}.datepicker-cell,.datepicker-view .week{height:2.25rem;line-height:2.25rem}.datepicker-title{background-color:#e6e6e6;box-shadow:inset 0 -1px 1px hsla(0,0%,4%,.1);font-weight:700;padding:.375rem .75rem;text-align:center}.datepicker-header .datepicker-controls{padding:2px 2px 0}.datepicker-controls .button{background-color:#fefefe;color:#0a0a0a;margin:0}.datepicker-controls .button:focus,.datepicker-controls .button:hover{background-color:#d8d8d8}.datepicker-controls .button:focus[disabled],.datepicker-controls .button:hover[disabled]{background-color:#fefefe;color:#0a0a0a;opacity:.25}.datepicker-header .datepicker-controls .button{border-color:transparent;font-weight:700}.datepicker-footer .datepicker-controls .button{border-radius:0;font-size:.75rem;margin:calc(.375rem - 1px) .375rem;width:100%}.datepicker-controls .view-switch{flex:auto}.datepicker-controls .next-btn,.datepicker-controls .prev-btn{padding-left:.375rem;padding-right:.375rem;width:2.25rem}.datepicker-controls .next-btn.disabled,.datepicker-controls .prev-btn.disabled{visibility:hidden}.datepicker-view .dow{font-size:.875rem;font-weight:700;height:1.5rem;line-height:1.5rem}.datepicker-view .week{color:#8a8a8a;font-size:.75rem;width:2.25rem}@media (max-width:22.5rem){.datepicker-view .week{width:1.96875rem}}.datepicker-grid{width:15.75rem}@media (max-width:22.5rem){.calendar-weeks+.days .datepicker-grid{width:13.78125rem}}.datepicker-cell:not(.disabled):hover{background-color:#f8f8f8;cursor:pointer}.datepicker-cell.focused:not(.selected){background-color:#f1f1f1}.datepicker-cell.selected,.datepicker-cell.selected:hover{background-color:#1779ba;color:#fefefe;font-weight:semibold}.datepicker-cell.disabled{color:#e6e6e6}.datepicker-cell.next:not(.disabled),.datepicker-cell.prev:not(.disabled){color:#cacaca}.datepicker-cell.next.selected,.datepicker-cell.prev.selected{color:#e5e5e5}.datepicker-cell.highlighted:not(.selected):not(.range):not(.today){background-color:#f7f7f7;border-radius:0}.datepicker-cell.highlighted:not(.selected):not(.range):not(.today).focused,.datepicker-cell.highlighted:not(.selected):not(.range):not(.today):not(.disabled):hover{background-color:#f1f1f1}.datepicker-cell.today:not(.selected){background-color:#d7ecfa}.datepicker-cell.today:not(.selected):not(.disabled){color:#8a8a8a}.datepicker-cell.today.focused:not(.selected){background-color:#cbe7f9}.datepicker-cell.range-end:not(.selected),.datepicker-cell.range-start:not(.selected){background-color:#767676;color:#fefefe}.datepicker-cell.range-end.focused:not(.selected),.datepicker-cell.range-start.focused:not(.selected){background-color:#707070}.datepicker-cell.range-end,.datepicker-cell.range-start{border-radius:0 0 0 0}.datepicker-cell.range{background-color:#e6e6e6;border-radius:0}.datepicker-cell.range:not(.disabled):not(.focused):not(.today):hover{background-color:#e0e0e0}.datepicker-cell.range.disabled{color:#cdcdcd}.datepicker-cell.range.focused{background-color:#d9d9d9}.datepicker-cell.range.today{background-color:#b3dbf6}.datepicker-view.datepicker-grid .datepicker-cell{height:4.5rem;line-height:4.5rem}.datepicker-input.in-edit{border-color:#a4a4a4}.datepicker-input.in-edit:active,.datepicker-input.in-edit:focus{box-shadow:0 0 .25em .25em hsla(0,0%,64%,.2)}
\ No newline at end of file
diff --git a/src/ui/static/css/datepicker.css b/src/ui/static/css/datepicker.css
new file mode 100644
index 000000000..e51ff9c14
--- /dev/null
+++ b/src/ui/static/css/datepicker.css
@@ -0,0 +1,318 @@
+.datepicker {
+ display: none;
+}
+
+.datepicker.active {
+ display: block;
+}
+
+.datepicker-dropdown {
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: 20;
+ padding-top: 4px;
+}
+
+.datepicker-dropdown.datepicker-orient-top {
+ padding-top: 0;
+ padding-bottom: 4px;
+}
+
+.datepicker-picker {
+ display: inline-block;
+ border-radius: 4px;
+ background-color: white;
+}
+
+.datepicker-dropdown .datepicker-picker {
+ box-shadow: 0 2px 3px rgba(10, 10, 10, 0.1), 0 0 0 1px rgba(10, 10, 10, 0.1);
+}
+
+.datepicker-picker span {
+ display: block;
+ flex: 1;
+ border: 0;
+ border-radius: 4px;
+ cursor: default;
+ text-align: center;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+.datepicker-main {
+ padding: 2px;
+}
+
+.datepicker-footer {
+ box-shadow: inset 0 1px 1px rgba(10, 10, 10, 0.1);
+ background-color: whitesmoke;
+}
+
+.datepicker-grid,
+.datepicker-view .days-of-week,
+.datepicker-view,
+.datepicker-controls {
+ display: flex;
+}
+
+.datepicker-grid {
+ flex-wrap: wrap;
+}
+
+.datepicker-view .days .datepicker-cell,
+.datepicker-view .dow {
+ flex-basis: 14.2857142857%;
+}
+
+.datepicker-view.datepicker-grid .datepicker-cell {
+ flex-basis: 25%;
+}
+
+.datepicker-cell,
+.datepicker-view .week {
+ height: 2.25rem;
+ line-height: 2.25rem;
+}
+
+.datepicker-title {
+ box-shadow: inset 0 -1px 1px rgba(10, 10, 10, 0.1);
+ background-color: whitesmoke;
+ padding: 0.375rem 0.75rem;
+ text-align: center;
+ font-weight: 700;
+}
+
+.datepicker-header .datepicker-controls {
+ padding: 2px 2px 0;
+}
+
+.datepicker-controls .button {
+ display: inline-flex;
+ position: relative;
+ align-items: center;
+ justify-content: center;
+ margin: 0;
+ border: 1px solid #dbdbdb;
+ border-radius: 4px;
+ box-shadow: none;
+ background-color: white;
+ cursor: pointer;
+ padding: calc(0.375em - 1px) 0.75em;
+ height: 2.25em;
+ vertical-align: top;
+ text-align: center;
+ line-height: 1.5;
+ white-space: nowrap;
+ color: #363636;
+ font-size: 1rem;
+}
+
+.datepicker-controls .button:focus,
+.datepicker-controls .button:active {
+ outline: none;
+}
+
+.datepicker-controls .button:hover {
+ border-color: #b5b5b5;
+ color: #363636;
+}
+
+.datepicker-controls .button:focus {
+ border-color: #3273dc;
+ color: #363636;
+}
+
+.datepicker-controls .button:focus:not(:active) {
+ box-shadow: 0 0 0 0.125em rgba(50, 115, 220, 0.25);
+}
+
+.datepicker-controls .button:active {
+ border-color: #4a4a4a;
+ color: #363636;
+}
+
+.datepicker-controls .button[disabled] {
+ cursor: not-allowed;
+}
+
+.datepicker-header .datepicker-controls .button {
+ border-color: transparent;
+ font-weight: bold;
+}
+
+.datepicker-header .datepicker-controls .button:hover {
+ background-color: #f9f9f9;
+}
+
+.datepicker-header .datepicker-controls .button:focus:not(:active) {
+ box-shadow: 0 0 0 0.125em rgba(255, 255, 255, 0.25);
+}
+
+.datepicker-header .datepicker-controls .button:active {
+ background-color: #f2f2f2;
+}
+
+.datepicker-header .datepicker-controls .button[disabled] {
+ box-shadow: none;
+}
+
+.datepicker-footer .datepicker-controls .button {
+ margin: calc(0.375rem - 1px) 0.375rem;
+ border-radius: 2px;
+ width: 100%;
+ font-size: 0.75rem;
+}
+
+.datepicker-controls .view-switch {
+ flex: auto;
+}
+
+.datepicker-controls .prev-btn,
+.datepicker-controls .next-btn {
+ padding-right: 0.375rem;
+ padding-left: 0.375rem;
+ width: 2.25rem;
+}
+
+.datepicker-controls .prev-btn.disabled,
+.datepicker-controls .next-btn.disabled {
+ visibility: hidden;
+}
+
+.datepicker-view .dow {
+ height: 1.5rem;
+ line-height: 1.5rem;
+ font-size: 0.875rem;
+ font-weight: 700;
+}
+
+.datepicker-view .week {
+ width: 2.25rem;
+ color: #b5b5b5;
+ font-size: 0.75rem;
+}
+
+@media (max-width: 22.5rem) {
+ .datepicker-view .week {
+ width: 1.96875rem;
+ }
+}
+
+.datepicker-grid {
+ width: 15.75rem;
+}
+
+@media (max-width: 22.5rem) {
+ .calendar-weeks + .days .datepicker-grid {
+ width: 13.78125rem;
+ }
+}
+
+.datepicker-cell:not(.disabled):hover {
+ background-color: #f9f9f9;
+ cursor: pointer;
+}
+
+.datepicker-cell.focused:not(.selected) {
+ background-color: #e8e8e8;
+}
+
+.datepicker-cell.selected,
+.datepicker-cell.selected:hover {
+ background-color: #3273dc;
+ color: #fff;
+ font-weight: 600;
+}
+
+.datepicker-cell.disabled {
+ color: #dbdbdb;
+}
+
+.datepicker-cell.prev:not(.disabled),
+.datepicker-cell.next:not(.disabled) {
+ color: #7a7a7a;
+}
+
+.datepicker-cell.prev.selected,
+.datepicker-cell.next.selected {
+ color: #e6e6e6;
+}
+
+.datepicker-cell.highlighted:not(.selected):not(.range):not(.today) {
+ border-radius: 0;
+ background-color: whitesmoke;
+}
+
+.datepicker-cell.highlighted:not(.selected):not(.range):not(.today):not(.disabled):hover {
+ background-color: #eeeeee;
+}
+
+.datepicker-cell.highlighted:not(.selected):not(.range):not(.today).focused {
+ background-color: #e8e8e8;
+}
+
+.datepicker-cell.today:not(.selected) {
+ background-color: #00d1b2;
+}
+
+.datepicker-cell.today:not(.selected):not(.disabled) {
+ color: #fff;
+}
+
+.datepicker-cell.today.focused:not(.selected) {
+ background-color: #00c4a7;
+}
+
+.datepicker-cell.range-end:not(.selected),
+.datepicker-cell.range-start:not(.selected) {
+ background-color: #b5b5b5;
+ color: #fff;
+}
+
+.datepicker-cell.range-end.focused:not(.selected),
+.datepicker-cell.range-start.focused:not(.selected) {
+ background-color: #afafaf;
+}
+
+.datepicker-cell.range-start {
+ border-radius: 4px 0 0 4px;
+}
+
+.datepicker-cell.range-end {
+ border-radius: 0 4px 4px 0;
+}
+
+.datepicker-cell.range {
+ border-radius: 0;
+ background-color: #dbdbdb;
+}
+
+.datepicker-cell.range:not(.disabled):not(.focused):not(.today):hover {
+ background-color: #d5d5d5;
+}
+
+.datepicker-cell.range.disabled {
+ color: #c2c2c2;
+}
+
+.datepicker-cell.range.focused {
+ background-color: #cfcfcf;
+}
+
+.datepicker-view.datepicker-grid .datepicker-cell {
+ height: 4.5rem;
+ line-height: 4.5rem;
+}
+
+.datepicker-input.in-edit {
+ border-color: #2366d1;
+}
+
+.datepicker-input.in-edit:focus,
+.datepicker-input.in-edit:active {
+ box-shadow: 0 0 0.25em 0.25em rgba(35, 102, 209, 0.2);
+}
\ No newline at end of file
diff --git a/src/ui/static/css/datepicker.min.css b/src/ui/static/css/datepicker.min.css
new file mode 100644
index 000000000..c2cfa6802
--- /dev/null
+++ b/src/ui/static/css/datepicker.min.css
@@ -0,0 +1 @@
+.datepicker{display:none}.datepicker.active{display:block}.datepicker-dropdown{left:0;padding-top:4px;position:absolute;top:0;z-index:20}.datepicker-dropdown.datepicker-orient-top{padding-bottom:4px;padding-top:0}.datepicker-picker{background-color:#fff;border-radius:4px;display:inline-block}.datepicker-dropdown .datepicker-picker{box-shadow:0 2px 3px hsla(0,0%,4%,.1),0 0 0 1px hsla(0,0%,4%,.1)}.datepicker-picker span{-webkit-touch-callout:none;border:0;border-radius:4px;cursor:default;display:block;flex:1;text-align:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.datepicker-main{padding:2px}.datepicker-footer{background-color:#f5f5f5;box-shadow:inset 0 1px 1px hsla(0,0%,4%,.1)}.datepicker-controls,.datepicker-grid,.datepicker-view,.datepicker-view .days-of-week{display:flex}.datepicker-grid{flex-wrap:wrap}.datepicker-view .days .datepicker-cell,.datepicker-view .dow{flex-basis:14.2857142857%}.datepicker-view.datepicker-grid .datepicker-cell{flex-basis:25%}.datepicker-cell,.datepicker-view .week{height:2.25rem;line-height:2.25rem}.datepicker-title{background-color:#f5f5f5;box-shadow:inset 0 -1px 1px hsla(0,0%,4%,.1);font-weight:700;padding:.375rem .75rem;text-align:center}.datepicker-header .datepicker-controls{padding:2px 2px 0}.datepicker-controls .button{align-items:center;background-color:#fff;border:1px solid #dbdbdb;border-radius:4px;box-shadow:none;color:#363636;cursor:pointer;display:inline-flex;font-size:1rem;height:2.25em;justify-content:center;line-height:1.5;margin:0;padding:calc(.375em - 1px) .75em;position:relative;text-align:center;vertical-align:top;white-space:nowrap}.datepicker-controls .button:active,.datepicker-controls .button:focus{outline:none}.datepicker-controls .button:hover{border-color:#b5b5b5;color:#363636}.datepicker-controls .button:focus{border-color:#3273dc;color:#363636}.datepicker-controls .button:focus:not(:active){box-shadow:0 0 0 .125em rgba(50,115,220,.25)}.datepicker-controls .button:active{border-color:#4a4a4a;color:#363636}.datepicker-controls .button[disabled]{cursor:not-allowed}.datepicker-header .datepicker-controls .button{border-color:transparent;font-weight:700}.datepicker-header .datepicker-controls .button:hover{background-color:#f9f9f9}.datepicker-header .datepicker-controls .button:focus:not(:active){box-shadow:0 0 0 .125em hsla(0,0%,100%,.25)}.datepicker-header .datepicker-controls .button:active{background-color:#f2f2f2}.datepicker-header .datepicker-controls .button[disabled]{box-shadow:none}.datepicker-footer .datepicker-controls .button{border-radius:2px;font-size:.75rem;margin:calc(.375rem - 1px) .375rem;width:100%}.datepicker-controls .view-switch{flex:auto}.datepicker-controls .next-btn,.datepicker-controls .prev-btn{padding-left:.375rem;padding-right:.375rem;width:2.25rem}.datepicker-controls .next-btn.disabled,.datepicker-controls .prev-btn.disabled{visibility:hidden}.datepicker-view .dow{font-size:.875rem;font-weight:700;height:1.5rem;line-height:1.5rem}.datepicker-view .week{color:#b5b5b5;font-size:.75rem;width:2.25rem}@media (max-width:22.5rem){.datepicker-view .week{width:1.96875rem}}.datepicker-grid{width:15.75rem}@media (max-width:22.5rem){.calendar-weeks+.days .datepicker-grid{width:13.78125rem}}.datepicker-cell:not(.disabled):hover{background-color:#f9f9f9;cursor:pointer}.datepicker-cell.focused:not(.selected){background-color:#e8e8e8}.datepicker-cell.selected,.datepicker-cell.selected:hover{background-color:#3273dc;color:#fff;font-weight:600}.datepicker-cell.disabled{color:#dbdbdb}.datepicker-cell.next:not(.disabled),.datepicker-cell.prev:not(.disabled){color:#7a7a7a}.datepicker-cell.next.selected,.datepicker-cell.prev.selected{color:#e6e6e6}.datepicker-cell.highlighted:not(.selected):not(.range):not(.today){background-color:#f5f5f5;border-radius:0}.datepicker-cell.highlighted:not(.selected):not(.range):not(.today):not(.disabled):hover{background-color:#eee}.datepicker-cell.highlighted:not(.selected):not(.range):not(.today).focused{background-color:#e8e8e8}.datepicker-cell.today:not(.selected){background-color:#00d1b2}.datepicker-cell.today:not(.selected):not(.disabled){color:#fff}.datepicker-cell.today.focused:not(.selected){background-color:#00c4a7}.datepicker-cell.range-end:not(.selected),.datepicker-cell.range-start:not(.selected){background-color:#b5b5b5;color:#fff}.datepicker-cell.range-end.focused:not(.selected),.datepicker-cell.range-start.focused:not(.selected){background-color:#afafaf}.datepicker-cell.range-start{border-radius:4px 0 0 4px}.datepicker-cell.range-end{border-radius:0 4px 4px 0}.datepicker-cell.range{background-color:#dbdbdb;border-radius:0}.datepicker-cell.range:not(.disabled):not(.focused):not(.today):hover{background-color:#d5d5d5}.datepicker-cell.range.disabled{color:#c2c2c2}.datepicker-cell.range.focused{background-color:#cfcfcf}.datepicker-view.datepicker-grid .datepicker-cell{height:4.5rem;line-height:4.5rem}.datepicker-input.in-edit{border-color:#2366d1}.datepicker-input.in-edit:active,.datepicker-input.in-edit:focus{box-shadow:0 0 .25em .25em rgba(35,102,209,.2)}
\ No newline at end of file
diff --git a/src/ui/static/js/air-datepicker/air-datepicker.d.ts b/src/ui/static/js/air-datepicker/air-datepicker.d.ts
deleted file mode 100644
index 0f4a9122a..000000000
--- a/src/ui/static/js/air-datepicker/air-datepicker.d.ts
+++ /dev/null
@@ -1,146 +0,0 @@
-declare type AirDatepickerSelector = string | HTMLElement;
-
-export declare type AirDatepickerLocale = {
- days: string[],
- daysShort: string[],
- daysMin: string[],
- months: string[],
- monthsShort: string[],
- today: string,
- clear: string,
- dateFormat: string,
- timeFormat: string,
- firstDay: 0 | 1 | 2 | 3 | 4 | 5 | 6,
-}
-
-export declare type AirDatepickerButton = {
- content: string | ((dp: AirDatepicker) => string),
- tagName?: keyof HTMLElementTagNameMap,
- className?: string,
- attrs?: Record,
- onClick?: (dp: AirDatepicker) => void
-}
-
-export declare type AirDatepickerButtonPresets = 'clear' | 'today';
-
-export declare type AirDatepickerPosition = 'left' | 'left top' | 'left bottom' | 'top' | 'top left' | 'top right' | 'right' | 'right top' | 'right bottom' | 'bottom' | 'bottom left' | 'bottom right';
-export declare type AirDatepickerViews = 'days' | 'months' | 'years';
-export declare type AirDatepickerViewsSingle = 'day' | 'month' | 'year';
-export declare type AirDatepickerDate = string | number | Date;
-export declare type AirDatepickerNavEntry = string | ((dp: AirDatepicker) => string);
-export declare type AirDatepickerDecade = [number, number];
-export declare type AirDatepickerPositionCallback = (
- {
- $datepicker,
- $target,
- $pointer,
- isViewChange,
- done
- }: {
- $datepicker: HTMLDivElement,
- $target: HTMLInputElement,
- $pointer: HTMLElement,
- isViewChange: boolean,
- done: () => void
- }) => void | (() => void)
-
-export declare type AirDatepickerOptions = {
- classes: string
- inline: boolean,
- locale: Partial,
- startDate: AirDatepickerDate,
- firstDay: number,
- isMobile: boolean,
- visible: boolean,
- weekends: [number, number],
- dateFormat: string | ((d: Date) => string),
- altField: AirDatepickerSelector,
- altFieldDateFormat: string,
- toggleSelected: boolean,
- keyboardNav: boolean,
- selectedDates: AirDatepickerDate[] | false,
- container: AirDatepickerSelector,
- position: AirDatepickerPosition | AirDatepickerPositionCallback,
- offset: number,
- view: AirDatepickerViews,
- minView: AirDatepickerViews,
- showOtherMonths: boolean,
- selectOtherMonths: boolean,
- moveToOtherMonthsOnSelect: boolean,
- showOtherYears: boolean,
- selectOtherYears: boolean,
- moveToOtherYearsOnSelect: boolean,
- minDate: AirDatepickerDate | false,
- maxDate: AirDatepickerDate | false,
- disableNavWhenOutOfRange: true,
- multipleDates: number | true | false,
- multipleDatesSeparator: string,
- range: boolean,
- dynamicRange: boolean,
- buttons: AirDatepickerButtonPresets | AirDatepickerButton | (AirDatepickerButtonPresets| AirDatepickerButton)[] | false,
- monthsField: keyof AirDatepickerLocale,
- showEvent: string,
- autoClose: boolean,
- prevHtml: string,
- nextHtml: string,
- navTitles: {
- days?: AirDatepickerNavEntry,
- months?: AirDatepickerNavEntry,
- years?: AirDatepickerNavEntry
- },
- timepicker: boolean,
- onlyTimepicker: boolean,
- dateTimeSeparator: string,
- timeFormat: string,
- minHours: number,
- maxHours: number,
- minMinutes: number,
- maxMinutes: number,
- hoursStep: number,
- minutesStep: number,
-
- onSelect: ({date, formattedDate, datepicker}: {date: Date | Date[], formattedDate: string | string[], datepicker: AirDatepicker}) => void,
- onChangeViewDate: ({month, year, decade}: {month: number, year: number, decade: AirDatepickerDecade}) => void,
- onChangeView: (view: AirDatepickerViews) => void,
- onRenderCell: (params: {date: Date, cellType: AirDatepickerViewsSingle, datepicker: AirDatepicker}) => ({
- disabled?: boolean,
- classes?: string,
- html?: string
- attrs?: Record
- } | void),
- onShow: (isAnimationComplete: boolean) => void,
- onHide: (isAnimationComplete: boolean) => void,
- onClickDayName: ({dayIndex, datepicker}: {dayIndex: number, datepicker: AirDatepicker}) => void
-}
-
-
-declare class AirDatepicker {
- constructor(el: string | E, opts? : Partial)
- static version: string
- show: () => void
- hide: () => void
- next: () => void
- prev: () => void
- selectDate: (date: AirDatepickerDate | AirDatepickerDate[], opts?: {updateTime?: boolean, silent?: boolean}) => void
- unselectDate: (date: AirDatepickerDate) => void
- clear: () => void
- formatDate: (date: AirDatepickerDate, format: string) => string
- destroy: () => void
- update: (newOpts: Partial) => void
- setCurrentView: (newView: AirDatepickerViews) => void
- setViewDate: (newViewDate: AirDatepickerDate) => void
- setFocusDate: (date: AirDatepickerDate | false, opts?: {viewDateTransition?: boolean}) => void
- up: (date?: AirDatepickerDate) => void
- down: (date?: AirDatepickerDate) => void
-
- $el: E
- $datepicker: HTMLDivElement
- viewDate: Date
- currentView: AirDatepickerViews
- selectedDates: Date[]
- focusDate: Date | false
- visible: boolean
-}
-
-
-export default AirDatepicker;
diff --git a/src/ui/static/js/air-datepicker/air-datepicker.js b/src/ui/static/js/air-datepicker/air-datepicker.js
deleted file mode 100644
index da4885f2d..000000000
--- a/src/ui/static/js/air-datepicker/air-datepicker.js
+++ /dev/null
@@ -1,2350 +0,0 @@
-const { default: AirDatepicker } = require("air-datepicker");
-
-!(function (e, t) {
- "object" == typeof exports && "object" == typeof module
- ? (module.exports = t())
- : "function" == typeof define && define.amd
- ? define([], t)
- : "object" == typeof exports
- ? (exports.AirDatepicker = t())
- : (e.AirDatepicker = t());
-})(this, function () {
- return (function () {
- "use strict";
- var e = {
- d: function (t, i) {
- for (var s in i)
- e.o(i, s) &&
- !e.o(t, s) &&
- Object.defineProperty(t, s, { enumerable: !0, get: i[s] });
- },
- o: function (e, t) {
- return Object.prototype.hasOwnProperty.call(e, t);
- },
- },
- t = {};
- e.d(t, {
- default: function () {
- return j;
- },
- });
- var i = {
- days: "days",
- months: "months",
- years: "years",
- day: "day",
- month: "month",
- year: "year",
- eventChangeViewDate: "changeViewDate",
- eventChangeCurrentView: "changeCurrentView",
- eventChangeFocusDate: "changeFocusDate",
- eventChangeSelectedDate: "changeSelectedDate",
- eventChangeTime: "changeTime",
- eventChangeLastSelectedDate: "changeLastSelectedDate",
- actionSelectDate: "selectDate",
- actionUnselectDate: "unselectDate",
- cssClassWeekend: "-weekend-",
- },
- s = {
- classes: "",
- inline: !1,
- locale: {
- days: [
- "Воскресенье",
- "Понедельник",
- "Вторник",
- "Среда",
- "Четверг",
- "Пятница",
- "Суббота",
- ],
- daysShort: ["Вос", "Пон", "Вто", "Сре", "Чет", "Пят", "Суб"],
- daysMin: ["Вс", "Пн", "Вт", "Ср", "Чт", "Пт", "Сб"],
- months: [
- "Январь",
- "Февраль",
- "Март",
- "Апрель",
- "Май",
- "Июнь",
- "Июль",
- "Август",
- "Сентябрь",
- "Октябрь",
- "Ноябрь",
- "Декабрь",
- ],
- monthsShort: [
- "Янв",
- "Фев",
- "Мар",
- "Апр",
- "Май",
- "Июн",
- "Июл",
- "Авг",
- "Сен",
- "Окт",
- "Ноя",
- "Дек",
- ],
- today: "Сегодня",
- clear: "Очистить",
- dateFormat: "dd.MM.yyyy",
- timeFormat: "HH:mm",
- firstDay: 1,
- },
- startDate: new Date(),
- firstDay: "",
- weekends: [6, 0],
- dateFormat: "",
- altField: "",
- altFieldDateFormat: "T",
- toggleSelected: !0,
- keyboardNav: !0,
- selectedDates: !1,
- container: "",
- isMobile: !1,
- visible: !1,
- position: "bottom left",
- offset: 12,
- view: i.days,
- minView: i.days,
- showOtherMonths: !0,
- selectOtherMonths: !0,
- moveToOtherMonthsOnSelect: !0,
- showOtherYears: !0,
- selectOtherYears: !0,
- moveToOtherYearsOnSelect: !0,
- minDate: "",
- maxDate: "",
- disableNavWhenOutOfRange: !0,
- multipleDates: !1,
- multipleDatesSeparator: ", ",
- range: !1,
- dynamicRange: !0,
- buttons: !1,
- monthsField: "monthsShort",
- showEvent: "focus",
- autoClose: !1,
- prevHtml: '',
- nextHtml: '',
- navTitles: {
- days: "MMMM, yyyy",
- months: "yyyy",
- years: "yyyy1 - yyyy2",
- },
- timepicker: !1,
- onlyTimepicker: !1,
- dateTimeSeparator: " ",
- timeFormat: "",
- minHours: 0,
- maxHours: 24,
- minMinutes: 0,
- maxMinutes: 59,
- hoursStep: 1,
- minutesStep: 1,
- onSelect: !1,
- onChangeViewDate: !1,
- onChangeView: !1,
- onRenderCell: !1,
- onShow: !1,
- onHide: !1,
- onClickDayName: !1,
- };
- function a(e) {
- let t =
- arguments.length > 1 && void 0 !== arguments[1]
- ? arguments[1]
- : document;
- return "string" == typeof e ? t.querySelector(e) : e;
- }
- function n() {
- let {
- tagName: e = "div",
- className: t = "",
- innerHtml: i = "",
- id: s = "",
- attrs: a = {},
- } = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {},
- n = document.createElement(e);
- return (
- t && n.classList.add(...t.split(" ")),
- s && (n.id = s),
- i && (n.innerHTML = i),
- a && r(n, a),
- n
- );
- }
- function r(e, t) {
- for (let [i, s] of Object.entries(t))
- void 0 !== s && e.setAttribute(i, s);
- return e;
- }
- function h(e) {
- return new Date(e.getFullYear(), e.getMonth() + 1, 0).getDate();
- }
- function o(e) {
- let t = e.getHours(),
- i = t % 12 == 0 ? 12 : t % 12;
- return {
- year: e.getFullYear(),
- month: e.getMonth(),
- fullMonth:
- e.getMonth() + 1 < 10 ? "0" + (e.getMonth() + 1) : e.getMonth() + 1,
- date: e.getDate(),
- fullDate: e.getDate() < 10 ? "0" + e.getDate() : e.getDate(),
- day: e.getDay(),
- hours: t,
- fullHours: l(t),
- hours12: i,
- fullHours12: l(i),
- minutes: e.getMinutes(),
- fullMinutes:
- e.getMinutes() < 10 ? "0" + e.getMinutes() : e.getMinutes(),
- };
- }
- function l(e) {
- return e < 10 ? "0" + e : e;
- }
- function d(e) {
- let t = 10 * Math.floor(e.getFullYear() / 10);
- return [t, t + 9];
- }
- function c() {
- let e = [];
- for (var t = arguments.length, i = new Array(t), s = 0; s < t; s++)
- i[s] = arguments[s];
- return (
- i.forEach((t) => {
- if ("object" == typeof t) for (let i in t) t[i] && e.push(i);
- else t && e.push(t);
- }),
- e.join(" ")
- );
- }
- function u(e, t) {
- let s =
- arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : i.days;
- if (!e || !t) return !1;
- let a = o(e),
- n = o(t),
- r = {
- [i.days]:
- a.date === n.date && a.month === n.month && a.year === n.year,
- [i.months]: a.month === n.month && a.year === n.year,
- [i.years]: a.year === n.year,
- };
- return r[s];
- }
- function p(e, t, i) {
- let s = g(e, !1).getTime(),
- a = g(t, !1).getTime();
- return i ? s >= a : s > a;
- }
- function m(e, t) {
- return !p(e, t, !0);
- }
- function g(e) {
- let t =
- !(arguments.length > 1 && void 0 !== arguments[1]) || arguments[1],
- i = new Date(e.getTime());
- return "boolean" != typeof t || t || D(i), i;
- }
- function D(e) {
- return e.setHours(0, 0, 0, 0), e;
- }
- function v(e, t, i) {
- e.length
- ? e.forEach((e) => {
- e.addEventListener(t, i);
- })
- : e.addEventListener(t, i);
- }
- function y(e, t) {
- return (
- !(!e || e === document || e instanceof DocumentFragment) &&
- (e.matches(t) ? e : y(e.parentNode, t))
- );
- }
- function f(e, t, i) {
- return e > i ? i : e < t ? t : e;
- }
- function w(e) {
- for (
- var t = arguments.length, i = new Array(t > 1 ? t - 1 : 0), s = 1;
- s < t;
- s++
- )
- i[s - 1] = arguments[s];
- return (
- i
- .filter((e) => e)
- .forEach((t) => {
- for (let [i, s] of Object.entries(t))
- if (void 0 !== s && "[object Object]" === s.toString()) {
- let t = void 0 !== e[i] ? e[i].toString() : void 0,
- a = s.toString(),
- n = Array.isArray(s) ? [] : {};
- (e[i] = e[i] ? (t !== a ? n : e[i]) : n), w(e[i], s);
- } else e[i] = s;
- }),
- e
- );
- }
- function b(e) {
- let t = e;
- return (
- e instanceof Date || (t = new Date(e)),
- isNaN(t.getTime()) &&
- (console.log(
- 'Unable to convert value "'.concat(e, '" to Date object')
- ),
- (t = !1)),
- t
- );
- }
- function k(e) {
- let t = "\\s|\\.|-|/|\\\\|,|\\$|\\!|\\?|:|;";
- return new RegExp("(^|>|" + t + ")(" + e + ")($|<|" + t + ")", "g");
- }
- function C(e, t, i) {
- return (
- t in e
- ? Object.defineProperty(e, t, {
- value: i,
- enumerable: !0,
- configurable: !0,
- writable: !0,
- })
- : (e[t] = i),
- e
- );
- }
- class _ {
- constructor() {
- let {
- type: e,
- date: t,
- dp: i,
- opts: s,
- body: a,
- } = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {};
- C(this, "focus", () => {
- this.$cell.classList.add("-focus-"), (this.focused = !0);
- }),
- C(this, "removeFocus", () => {
- this.$cell.classList.remove("-focus-"), (this.focused = !1);
- }),
- C(this, "select", () => {
- this.$cell.classList.add("-selected-"), (this.selected = !0);
- }),
- C(this, "removeSelect", () => {
- this.$cell.classList.remove(
- "-selected-",
- "-range-from-",
- "-range-to-"
- ),
- (this.selected = !1);
- }),
- C(this, "onChangeSelectedDate", () => {
- this.isDisabled ||
- (this._handleSelectedStatus(),
- this.opts.range && this._handleRangeStatus());
- }),
- C(this, "onChangeFocusDate", (e) => {
- if (!e) return void (this.focused && this.removeFocus());
- let t = u(e, this.date, this.type);
- t ? this.focus() : !t && this.focused && this.removeFocus(),
- this.opts.range && this._handleRangeStatus();
- }),
- C(
- this,
- "render",
- () => (
- (this.$cell.innerHTML = this._getHtml()),
- (this.$cell.adpCell = this),
- this.$cell
- )
- ),
- (this.type = e),
- (this.singleType = this.type.slice(0, -1)),
- (this.date = t),
- (this.dp = i),
- (this.opts = s),
- (this.body = a),
- (this.customData = !1),
- this.init();
- }
- init() {
- let { range: e, onRenderCell: t } = this.opts;
- t &&
- (this.customData = t({
- date: this.date,
- cellType: this.singleType,
- datepicker: this.dp,
- })),
- this._createElement(),
- this._bindDatepickerEvents(),
- this._handleInitialFocusStatus(),
- this.dp.hasSelectedDates &&
- (this._handleSelectedStatus(), e && this._handleRangeStatus());
- }
- _bindDatepickerEvents() {
- this.dp.on(i.eventChangeSelectedDate, this.onChangeSelectedDate),
- this.dp.on(i.eventChangeFocusDate, this.onChangeFocusDate);
- }
- unbindDatepickerEvents() {
- this.dp.off(i.eventChangeSelectedDate, this.onChangeSelectedDate),
- this.dp.off(i.eventChangeFocusDate, this.onChangeFocusDate);
- }
- _createElement() {
- var e;
- let { year: t, month: i, date: s } = o(this.date),
- a =
- (null === (e = this.customData) || void 0 === e
- ? void 0
- : e.attrs) || {};
- this.$cell = n({
- className: this._getClassName(),
- attrs: { "data-year": t, "data-month": i, "data-date": s, ...a },
- });
- }
- _getClassName() {
- var e, t;
- let s = new Date(),
- { selectOtherMonths: a, selectOtherYears: n } = this.opts,
- { minDate: r, maxDate: h } = this.dp,
- { day: l } = o(this.date),
- d = this._isOutOfMinMaxRange(),
- p =
- null === (e = this.customData) || void 0 === e
- ? void 0
- : e.disabled,
- m = c("air-datepicker-cell", "-".concat(this.singleType, "-"), {
- "-current-": u(s, this.date, this.type),
- "-min-date-": r && u(r, this.date, this.type),
- "-max-date-": h && u(h, this.date, this.type),
- }),
- g = "";
- switch (this.type) {
- case i.days:
- g = c({
- "-weekend-": this.dp.isWeekend(l),
- "-other-month-": this.isOtherMonth,
- "-disabled-": (this.isOtherMonth && !a) || d || p,
- });
- break;
- case i.months:
- g = c({ "-disabled-": d || p });
- break;
- case i.years:
- g = c({
- "-other-decade-": this.isOtherDecade,
- "-disabled-": d || (this.isOtherDecade && !n) || p,
- });
- }
- return c(
- m,
- g,
- null === (t = this.customData) || void 0 === t ? void 0 : t.classes
- );
- }
- _getHtml() {
- var e;
- let { year: t, month: s, date: a } = o(this.date),
- { showOtherMonths: n, showOtherYears: r } = this.opts;
- if (null !== (e = this.customData) && void 0 !== e && e.html)
- return this.customData.html;
- switch (this.type) {
- case i.days:
- return !n && this.isOtherMonth ? "" : a;
- case i.months:
- return this.dp.locale[this.opts.monthsField][s];
- case i.years:
- return !r && this.isOtherDecade ? "" : t;
- }
- }
- _isOutOfMinMaxRange() {
- let { minDate: e, maxDate: t } = this.dp,
- { type: s, date: a } = this,
- { month: n, year: r, date: h } = o(a),
- l = s === i.days,
- d = s === i.years,
- c = !!e && new Date(r, d ? e.getMonth() : n, l ? h : e.getDate()),
- u = !!t && new Date(r, d ? t.getMonth() : n, l ? h : t.getDate());
- return e && t ? m(c, e) || p(u, t) : e ? m(c, e) : t ? p(u, t) : void 0;
- }
- destroy() {
- this.unbindDatepickerEvents();
- }
- _handleRangeStatus() {
- let { rangeDateFrom: e, rangeDateTo: t } = this.dp,
- i = c({
- "-in-range-":
- e && t && ((s = this.date), (a = e), (n = t), p(s, a) && m(s, n)),
- "-range-from-": e && u(this.date, e, this.type),
- "-range-to-": t && u(this.date, t, this.type),
- });
- var s, a, n;
- this.$cell.classList.remove("-range-from-", "-range-to-", "-in-range-"),
- i && this.$cell.classList.add(...i.split(" "));
- }
- _handleSelectedStatus() {
- let e = this.dp._checkIfDateIsSelected(this.date, this.type);
- e ? this.select() : !e && this.selected && this.removeSelect();
- }
- _handleInitialFocusStatus() {
- u(this.dp.focusDate, this.date, this.type) && this.focus();
- }
- get isDisabled() {
- return this.$cell.matches(".-disabled-");
- }
- get isOtherMonth() {
- return this.dp.isOtherMonth(this.date);
- }
- get isOtherDecade() {
- return this.dp.isOtherDecade(this.date);
- }
- }
- function M(e, t, i) {
- return (
- t in e
- ? Object.defineProperty(e, t, {
- value: i,
- enumerable: !0,
- configurable: !0,
- writable: !0,
- })
- : (e[t] = i),
- e
- );
- }
- let $ = {
- [i.days]:
- '' +
- ''),
- [i.months]: ''
- ),
- [i.years]: ''
- ),
- };
- const S = ".air-datepicker-cell";
- class T {
- constructor(e) {
- let { dp: t, type: s, opts: a } = e;
- M(this, "handleClick", (e) => {
- let t = e.target.closest(S).adpCell;
- if (t.isDisabled) return;
- if (!this.dp.isMinViewReached) return void this.dp.down();
- let i = this.dp._checkIfDateIsSelected(t.date, t.type);
- i
- ? this.dp._handleAlreadySelectedDates(i, t.date)
- : this.dp.selectDate(t.date);
- }),
- M(this, "handleDayNameClick", (e) => {
- let t = e.target.getAttribute("data-day-index");
- this.opts.onClickDayName({
- dayIndex: Number(t),
- datepicker: this.dp,
- });
- }),
- M(this, "onChangeCurrentView", (e) => {
- e !== this.type ? this.hide() : (this.show(), this.render());
- }),
- M(this, "onMouseOverCell", (e) => {
- let t = y(e.target, S);
- this.dp.setFocusDate(!!t && t.adpCell.date);
- }),
- M(this, "onMouseOutCell", () => {
- this.dp.setFocusDate(!1);
- }),
- M(this, "onClickBody", (e) => {
- let { onClickDayName: t } = this.opts,
- i = e.target;
- i.closest(S) && this.handleClick(e),
- t &&
- i.closest(".air-datepicker-body--day-name") &&
- this.handleDayNameClick(e);
- }),
- M(this, "onMouseDown", (e) => {
- this.pressed = !0;
- let t = y(e.target, S),
- i = t && t.adpCell;
- u(i.date, this.dp.rangeDateFrom) && (this.rangeFromFocused = !0),
- u(i.date, this.dp.rangeDateTo) && (this.rangeToFocused = !0);
- }),
- M(this, "onMouseMove", (e) => {
- if (!this.pressed || !this.dp.isMinViewReached) return;
- e.preventDefault();
- let t = y(e.target, S),
- i = t && t.adpCell,
- { selectedDates: s, rangeDateTo: a, rangeDateFrom: n } = this.dp;
- if (!i || i.isDisabled) return;
- let { date: r } = i;
- if (2 === s.length) {
- if (this.rangeFromFocused && !p(r, a)) {
- let { hours: e, minutes: t } = o(n);
- r.setHours(e),
- r.setMinutes(t),
- (this.dp.rangeDateFrom = r),
- this.dp.replaceDate(n, r);
- }
- if (this.rangeToFocused && !m(r, n)) {
- let { hours: e, minutes: t } = o(a);
- r.setHours(e),
- r.setMinutes(t),
- (this.dp.rangeDateTo = r),
- this.dp.replaceDate(a, r);
- }
- }
- }),
- M(this, "onMouseUp", () => {
- (this.pressed = !1),
- (this.rangeFromFocused = !1),
- (this.rangeToFocused = !1);
- }),
- M(this, "onChangeViewDate", (e, t) => {
- if (!this.isVisible) return;
- let s = d(e),
- a = d(t);
- switch (this.dp.currentView) {
- case i.days:
- if (u(e, t, i.months)) return;
- break;
- case i.months:
- if (u(e, t, i.years)) return;
- break;
- case i.years:
- if (s[0] === a[0] && s[1] === a[1]) return;
- }
- this.render();
- }),
- M(this, "render", () => {
- this.destroyCells(),
- this._generateCells(),
- this.cells.forEach((e) => {
- this.$cells.appendChild(e.render());
- });
- }),
- (this.dp = t),
- (this.type = s),
- (this.opts = a),
- (this.cells = []),
- (this.$el = ""),
- (this.pressed = !1),
- (this.isVisible = !0),
- this.init();
- }
- init() {
- this._buildBaseHtml(),
- this.type === i.days && this.renderDayNames(),
- this.render(),
- this._bindEvents(),
- this._bindDatepickerEvents();
- }
- _bindEvents() {
- let { range: e, dynamicRange: t } = this.opts;
- v(this.$el, "mouseover", this.onMouseOverCell),
- v(this.$el, "mouseout", this.onMouseOutCell),
- v(this.$el, "click", this.onClickBody),
- e &&
- t &&
- (v(this.$el, "mousedown", this.onMouseDown),
- v(this.$el, "mousemove", this.onMouseMove),
- v(window.document, "mouseup", this.onMouseUp));
- }
- _bindDatepickerEvents() {
- this.dp.on(i.eventChangeViewDate, this.onChangeViewDate),
- this.dp.on(i.eventChangeCurrentView, this.onChangeCurrentView);
- }
- _buildBaseHtml() {
- (this.$el = n({
- className: "air-datepicker-body -".concat(this.type, "-"),
- innerHtml: $[this.type],
- })),
- (this.$names = a(".air-datepicker-body--day-names", this.$el)),
- (this.$cells = a(".air-datepicker-body--cells", this.$el));
- }
- _getDayNamesHtml() {
- let e =
- arguments.length > 0 && void 0 !== arguments[0]
- ? arguments[0]
- : this.dp.locale.firstDay,
- t = "",
- s = this.dp.isWeekend,
- { onClickDayName: a } = this.opts,
- n = e,
- r = 0;
- for (; r < 7; ) {
- let e = n % 7,
- h = c("air-datepicker-body--day-name", {
- [i.cssClassWeekend]: s(e),
- "-clickable-": !!a,
- }),
- o = this.dp.locale.daysMin[e];
- (t += '")
- .concat(o, "
")),
- r++,
- n++;
- }
- return t;
- }
- _getDaysCells() {
- let {
- viewDate: e,
- locale: { firstDay: t },
- } = this.dp,
- i = h(e),
- { year: s, month: a } = o(e),
- n = new Date(s, a, 1),
- r = new Date(s, a, i),
- l = n.getDay() - t,
- d = 6 - r.getDay() + t;
- (l = l < 0 ? l + 7 : l), (d = d > 6 ? d - 7 : d);
- let c = (function (e, t) {
- let { year: i, month: s, date: a } = o(e);
- return new Date(i, s, a - t);
- })(n, l),
- u = i + l + d,
- p = c.getDate(),
- { year: m, month: g } = o(c),
- D = 0;
- for (; D < u; ) {
- let e = new Date(m, g, p + D);
- this._generateCell(e), D++;
- }
- }
- _generateCell(e) {
- let { type: t, dp: i, opts: s } = this,
- a = new _({ type: t, dp: i, opts: s, date: e, body: this });
- return this.cells.push(a), a;
- }
- _generateDayCells() {
- this._getDaysCells();
- }
- _generateMonthCells() {
- let { year: e } = this.dp.parsedViewDate,
- t = 0;
- for (; t < 12; )
- this.cells.push(this._generateCell(new Date(e, t))), t++;
- }
- _generateYearCells() {
- let e = d(this.dp.viewDate),
- t = e[0] - 1,
- i = e[1] + 1,
- s = t;
- for (; s <= i; )
- this.cells.push(this._generateCell(new Date(s, 0))), s++;
- }
- renderDayNames() {
- this.$names.innerHTML = this._getDayNamesHtml();
- }
- _generateCells() {
- switch (this.type) {
- case i.days:
- this._generateDayCells();
- break;
- case i.months:
- this._generateMonthCells();
- break;
- case i.years:
- this._generateYearCells();
- }
- }
- show() {
- (this.isVisible = !0), this.$el.classList.remove("-hidden-");
- }
- hide() {
- (this.isVisible = !1), this.$el.classList.add("-hidden-");
- }
- destroyCells() {
- this.cells.forEach((e) => e.destroy()),
- (this.cells = []),
- (this.$cells.innerHTML = "");
- }
- destroy() {
- this.destroyCells(),
- this.dp.off(i.eventChangeViewDate, this.onChangeViewDate),
- this.dp.off(i.eventChangeCurrentView, this.onChangeCurrentView);
- }
- }
- function F(e, t, i) {
- return (
- t in e
- ? Object.defineProperty(e, t, {
- value: i,
- enumerable: !0,
- configurable: !0,
- writable: !0,
- })
- : (e[t] = i),
- e
- );
- }
- class V {
- constructor(e) {
- let { dp: t, opts: i } = e;
- F(this, "onClickNav", (e) => {
- let t = y(e.target, ".air-datepicker-nav--action");
- if (!t) return;
- let i = t.dataset.action;
- this.dp[i]();
- }),
- F(this, "onChangeViewDate", () => {
- this.render(), this._resetNavStatus(), this.handleNavStatus();
- }),
- F(this, "onChangeCurrentView", () => {
- this.render(), this._resetNavStatus(), this.handleNavStatus();
- }),
- F(this, "onClickNavTitle", () => {
- this.dp.isFinalView || this.dp.up();
- }),
- F(this, "update", () => {
- let { prevHtml: e, nextHtml: t } = this.opts;
- (this.$prev.innerHTML = e),
- (this.$next.innerHTML = t),
- this._resetNavStatus(),
- this.render(),
- this.handleNavStatus();
- }),
- F(this, "renderDelay", () => {
- setTimeout(this.render);
- }),
- F(this, "render", () => {
- (this.$title.innerHTML = this._getTitle()),
- (function (e, t) {
- for (let i in t)
- t[i] ? e.classList.add(i) : e.classList.remove(i);
- })(this.$title, { "-disabled-": this.dp.isFinalView });
- }),
- (this.dp = t),
- (this.opts = i),
- this.init();
- }
- init() {
- this._createElement(),
- this._buildBaseHtml(),
- this._defineDOM(),
- this.render(),
- this.handleNavStatus(),
- this._bindEvents(),
- this._bindDatepickerEvents();
- }
- _defineDOM() {
- (this.$title = a(".air-datepicker-nav--title", this.$el)),
- (this.$prev = a('[data-action="prev"]', this.$el)),
- (this.$next = a('[data-action="next"]', this.$el));
- }
- _bindEvents() {
- this.$el.addEventListener("click", this.onClickNav),
- this.$title.addEventListener("click", this.onClickNavTitle);
- }
- _bindDatepickerEvents() {
- this.dp.on(i.eventChangeViewDate, this.onChangeViewDate),
- this.dp.on(i.eventChangeCurrentView, this.onChangeCurrentView),
- this.isNavIsFunction &&
- (this.dp.on(i.eventChangeSelectedDate, this.renderDelay),
- this.dp.opts.timepicker &&
- this.dp.on(i.eventChangeTime, this.render));
- }
- destroy() {
- this.dp.off(i.eventChangeViewDate, this.onChangeViewDate),
- this.dp.off(i.eventChangeCurrentView, this.onChangeCurrentView),
- this.isNavIsFunction &&
- (this.dp.off(i.eventChangeSelectedDate, this.renderDelay),
- this.dp.opts.timepicker &&
- this.dp.off(i.eventChangeTime, this.render));
- }
- _createElement() {
- this.$el = n({ tagName: "nav", className: "air-datepicker-nav" });
- }
- _getTitle() {
- let { dp: e, opts: t } = this,
- i = t.navTitles[e.currentView];
- return "function" == typeof i ? i(e) : e.formatDate(e.viewDate, i);
- }
- handleNavStatus() {
- let { disableNavWhenOutOfRange: e } = this.opts,
- { minDate: t, maxDate: s } = this.dp;
- if ((!t && !s) || !e) return;
- let { year: a, month: n } = this.dp.parsedViewDate,
- r = !!t && o(t),
- h = !!s && o(s);
- switch (this.dp.currentView) {
- case i.days:
- t && r.month >= n && r.year >= a && this._disableNav("prev"),
- s && h.month <= n && h.year <= a && this._disableNav("next");
- break;
- case i.months:
- t && r.year >= a && this._disableNav("prev"),
- s && h.year <= a && this._disableNav("next");
- break;
- case i.years: {
- let e = d(this.dp.viewDate);
- t && r.year >= e[0] && this._disableNav("prev"),
- s && h.year <= e[1] && this._disableNav("next");
- break;
- }
- }
- }
- _disableNav(e) {
- a('[data-action="' + e + '"]', this.$el).classList.add("-disabled-");
- }
- _resetNavStatus() {
- !(function (e) {
- for (
- var t = arguments.length, i = new Array(t > 1 ? t - 1 : 0), s = 1;
- s < t;
- s++
- )
- i[s - 1] = arguments[s];
- e.length
- ? e.forEach((e) => {
- e.classList.remove(...i);
- })
- : e.classList.remove(...i);
- })(
- this.$el.querySelectorAll(".air-datepicker-nav--action"),
- "-disabled-"
- );
- }
- _buildBaseHtml() {
- let { prevHtml: e, nextHtml: t } = this.opts;
- this.$el.innerHTML =
- ''.concat(
- e,
- "
"
- ) +
- '' +
- ''.concat(
- t,
- "
"
- );
- }
- get isNavIsFunction() {
- let { navTitles: e } = this.opts;
- return Object.keys(e).find((t) => "function" == typeof e[t]);
- }
- }
- var x = {
- today: {
- content: (e) => e.locale.today,
- onClick: (e) => e.setViewDate(new Date()),
- },
- clear: { content: (e) => e.locale.clear, onClick: (e) => e.clear() },
- };
- class H {
- constructor(e) {
- let { dp: t, opts: i } = e;
- (this.dp = t), (this.opts = i), this.init();
- }
- init() {
- this.createElement(), this.render();
- }
- createElement() {
- this.$el = n({ className: "air-datepicker-buttons" });
- }
- destroy() {
- this.$el.parentNode.removeChild(this.$el);
- }
- clearHtml() {
- return (this.$el.innerHTML = ""), this;
- }
- generateButtons() {
- let { buttons: e } = this.opts;
- Array.isArray(e) || (e = [e]),
- e.forEach((e) => {
- let t = e;
- "string" == typeof e && x[e] && (t = x[e]);
- let i = this.createButton(t);
- t.onClick && this.attachEventToButton(i, t.onClick),
- this.$el.appendChild(i);
- });
- }
- attachEventToButton(e, t) {
- e.addEventListener("click", () => {
- t(this.dp);
- });
- }
- createButton(e) {
- let {
- content: t,
- className: i,
- tagName: s = "button",
- attrs: a = {},
- } = e,
- r = "function" == typeof t ? t(this.dp) : t;
- return n({
- tagName: s,
- innerHtml: "".concat(r, ""),
- className: c("air-datepicker-button", i),
- attrs: a,
- });
- }
- render() {
- this.generateButtons();
- }
- }
- function L(e, t, i) {
- return (
- t in e
- ? Object.defineProperty(e, t, {
- value: i,
- enumerable: !0,
- configurable: !0,
- writable: !0,
- })
- : (e[t] = i),
- e
- );
- }
- class O {
- constructor() {
- let { opts: e, dp: t } =
- arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {};
- L(this, "toggleTimepickerIsActive", (e) => {
- this.dp.timepickerIsActive = e;
- }),
- L(this, "onChangeSelectedDate", (e) => {
- let { date: t, updateTime: i = !1 } = e;
- t &&
- (this.setMinMaxTime(t),
- this.setCurrentTime(!!i && t),
- this.addTimeToDate(t));
- }),
- L(this, "onChangeLastSelectedDate", (e) => {
- e && (this.setTime(e), this.render());
- }),
- L(this, "onChangeInputRange", (e) => {
- let t = e.target;
- (this[t.getAttribute("name")] = t.value),
- this.updateText(),
- this.dp.trigger(i.eventChangeTime, {
- hours: this.hours,
- minutes: this.minutes,
- });
- }),
- L(this, "onMouseEnterLeave", (e) => {
- let t = e.target.getAttribute("name"),
- i = this.$minutesText;
- "hours" === t && (i = this.$hoursText),
- i.classList.toggle("-focus-");
- }),
- L(this, "onFocus", () => {
- this.toggleTimepickerIsActive(!0);
- }),
- L(this, "onBlur", () => {
- this.toggleTimepickerIsActive(!1);
- }),
- (this.opts = e),
- (this.dp = t);
- let { timeFormat: s } = this.dp.locale;
- s && (s.match(k("h")) || s.match(k("hh"))) && (this.ampm = !0),
- this.init();
- }
- init() {
- this.setTime(this.dp.lastSelectedDate || this.dp.viewDate),
- this.createElement(),
- this.buildHtml(),
- this.defineDOM(),
- this.render(),
- this.bindDatepickerEvents(),
- this.bindDOMEvents();
- }
- bindDatepickerEvents() {
- this.dp.on(i.eventChangeSelectedDate, this.onChangeSelectedDate),
- this.dp.on(
- i.eventChangeLastSelectedDate,
- this.onChangeLastSelectedDate
- );
- }
- bindDOMEvents() {
- let e = "input";
- navigator.userAgent.match(/trident/gi) && (e = "change"),
- v(this.$ranges, e, this.onChangeInputRange),
- v(this.$ranges, "mouseenter", this.onMouseEnterLeave),
- v(this.$ranges, "mouseleave", this.onMouseEnterLeave),
- v(this.$ranges, "focus", this.onFocus),
- v(this.$ranges, "mousedown", this.onFocus),
- v(this.$ranges, "blur", this.onBlur);
- }
- createElement() {
- this.$el = n({
- className: c("air-datepicker-time", { "-am-pm-": this.dp.ampm }),
- });
- }
- destroy() {
- this.dp.off(i.eventChangeSelectedDate, this.onChangeSelectedDate),
- this.dp.off(
- i.eventChangeLastSelectedDate,
- this.onChangeLastSelectedDate
- ),
- this.$el.parentNode.removeChild(this.$el);
- }
- buildHtml() {
- let {
- ampm: e,
- hours: t,
- displayHours: i,
- minutes: s,
- minHours: a,
- minMinutes: n,
- maxHours: r,
- maxMinutes: h,
- dayPeriod: o,
- opts: { hoursStep: d, minutesStep: c },
- } = this;
- this.$el.innerHTML =
- '' +
- ' '.concat(
- l(i),
- ""
- ) +
- ' :' +
- ' '.concat(
- l(s),
- ""
- ) +
- " ".concat(
- e
- ? "".concat(
- o,
- ""
- )
- : ""
- ) +
- '
";
- }
- defineDOM() {
- let e = (e) => a(e, this.$el);
- (this.$ranges = this.$el.querySelectorAll('[type="range"]')),
- (this.$hours = e('[name="hours"]')),
- (this.$minutes = e('[name="minutes"]')),
- (this.$hoursText = e(".air-datepicker-time--current-hours")),
- (this.$minutesText = e(".air-datepicker-time--current-minutes")),
- (this.$ampm = e(".air-datepicker-time--current-ampm"));
- }
- setTime(e) {
- this.setMinMaxTime(e), this.setCurrentTime(e);
- }
- addTimeToDate(e) {
- e && (e.setHours(this.hours), e.setMinutes(this.minutes));
- }
- setMinMaxTime(e) {
- if ((this.setMinMaxTimeFromOptions(), e)) {
- let { minDate: t, maxDate: i } = this.dp;
- t && u(e, t) && this.setMinTimeFromMinDate(t),
- i && u(e, i) && this.setMaxTimeFromMaxDate(i);
- }
- }
- setCurrentTime(e) {
- let { hours: t, minutes: i } = e ? o(e) : this;
- (this.hours = f(t, this.minHours, this.maxHours)),
- (this.minutes = f(i, this.minMinutes, this.maxMinutes));
- }
- setMinMaxTimeFromOptions() {
- let {
- minHours: e,
- minMinutes: t,
- maxHours: i,
- maxMinutes: s,
- } = this.opts;
- (this.minHours = f(e, 0, 23)),
- (this.minMinutes = f(t, 0, 59)),
- (this.maxHours = f(i, 0, 23)),
- (this.maxMinutes = f(s, 0, 59));
- }
- setMinTimeFromMinDate(e) {
- let { lastSelectedDate: t } = this.dp;
- (this.minHours = e.getHours()),
- t && t.getHours() > e.getHours()
- ? (this.minMinutes = this.opts.minMinutes)
- : (this.minMinutes = e.getMinutes());
- }
- setMaxTimeFromMaxDate(e) {
- let { lastSelectedDate: t } = this.dp;
- (this.maxHours = e.getHours()),
- t && t.getHours() < e.getHours()
- ? (this.maxMinutes = this.opts.maxMinutes)
- : (this.maxMinutes = e.getMinutes());
- }
- getDayPeriod(e, t) {
- let i = e,
- s = Number(e);
- e instanceof Date && ((i = o(e)), (s = Number(i.hours)));
- let a = "am";
- if (t || this.ampm) {
- switch (!0) {
- case 12 === s:
- case s > 11:
- a = "pm";
- }
- s = s % 12 == 0 ? 12 : s % 12;
- }
- return { hours: s, dayPeriod: a };
- }
- updateSliders() {
- (r(this.$hours, { min: this.minHours, max: this.maxHours }).value =
- this.hours),
- (r(this.$minutes, {
- min: this.minMinutes,
- max: this.maxMinutes,
- }).value = this.minutes);
- }
- updateText() {
- (this.$hoursText.innerHTML = l(this.displayHours)),
- (this.$minutesText.innerHTML = l(this.minutes)),
- this.ampm && (this.$ampm.innerHTML = this.dayPeriod);
- }
- set hours(e) {
- this._hours = e;
- let { hours: t, dayPeriod: i } = this.getDayPeriod(e);
- (this.displayHours = t), (this.dayPeriod = i);
- }
- get hours() {
- return this._hours;
- }
- render() {
- this.updateSliders(), this.updateText();
- }
- }
- function E(e, t, i) {
- return (
- t in e
- ? Object.defineProperty(e, t, {
- value: i,
- enumerable: !0,
- configurable: !0,
- writable: !0,
- })
- : (e[t] = i),
- e
- );
- }
- class A {
- constructor(e) {
- let { dp: t, opts: i } = e;
- E(this, "pressedKeys", new Set()),
- E(
- this,
- "hotKeys",
- new Map([
- [
- [
- ["Control", "ArrowRight"],
- ["Control", "ArrowUp"],
- ],
- (e) => e.month++,
- ],
- [
- [
- ["Control", "ArrowLeft"],
- ["Control", "ArrowDown"],
- ],
- (e) => e.month--,
- ],
- [
- [
- ["Shift", "ArrowRight"],
- ["Shift", "ArrowUp"],
- ],
- (e) => e.year++,
- ],
- [
- [
- ["Shift", "ArrowLeft"],
- ["Shift", "ArrowDown"],
- ],
- (e) => e.year--,
- ],
- [
- [
- ["Alt", "ArrowRight"],
- ["Alt", "ArrowUp"],
- ],
- (e) => (e.year += 10),
- ],
- [
- [
- ["Alt", "ArrowLeft"],
- ["Alt", "ArrowDown"],
- ],
- (e) => (e.year -= 10),
- ],
- [["Control", "Shift", "ArrowUp"], (e, t) => t.up()],
- ])
- ),
- E(this, "handleHotKey", (e) => {
- let t = this.hotKeys.get(e),
- i = o(this.getInitialFocusDate());
- t(i, this.dp);
- let { year: s, month: a, date: n } = i,
- r = h(new Date(s, a));
- r < n && (n = r);
- let l = this.dp.getClampedDate(new Date(s, a, n));
- this.dp.setFocusDate(l, { viewDateTransition: !0 });
- }),
- E(this, "isHotKeyPressed", () => {
- let e = !1,
- t = this.pressedKeys.size,
- i = (e) => this.pressedKeys.has(e);
- for (let [s] of this.hotKeys) {
- if (e) break;
- if (Array.isArray(s[0]))
- s.forEach((a) => {
- e || t !== a.length || (e = a.every(i) && s);
- });
- else {
- if (t !== s.length) continue;
- e = s.every(i) && s;
- }
- }
- return e;
- }),
- E(this, "isArrow", (e) => e >= 37 && e <= 40),
- E(this, "onKeyDown", (e) => {
- let { key: t, which: i } = e,
- {
- dp: s,
- dp: { focusDate: a },
- opts: n,
- } = this;
- this.registerKey(t);
- let r = this.isHotKeyPressed();
- if (r) return e.preventDefault(), void this.handleHotKey(r);
- if (this.isArrow(i))
- return e.preventDefault(), void this.focusNextCell(t);
- if ("Enter" === t) {
- if (s.currentView !== n.minView) return void s.down();
- if (a) {
- let e = s._checkIfDateIsSelected(a);
- return void (e
- ? s._handleAlreadySelectedDates(e, a)
- : s.selectDate(a));
- }
- }
- "Escape" === t && this.dp.hide();
- }),
- E(this, "onKeyUp", (e) => {
- this.removeKey(e.key);
- }),
- (this.dp = t),
- (this.opts = i),
- this.init();
- }
- init() {
- this.bindKeyboardEvents();
- }
- bindKeyboardEvents() {
- let { $el: e } = this.dp;
- e.addEventListener("keydown", this.onKeyDown),
- e.addEventListener("keyup", this.onKeyUp);
- }
- destroy() {
- let { $el: e } = this.dp;
- e.removeEventListener("keydown", this.onKeyDown),
- e.removeEventListener("keyup", this.onKeyUp),
- (this.hotKeys = null),
- (this.pressedKeys = null);
- }
- getInitialFocusDate() {
- let {
- focusDate: e,
- currentView: t,
- selectedDates: s,
- parsedViewDate: { year: a, month: n },
- } = this.dp,
- r = e || s[s.length - 1];
- if (!r)
- switch (t) {
- case i.days:
- r = new Date(a, n, new Date().getDate());
- break;
- case i.months:
- r = new Date(a, n, 1);
- break;
- case i.years:
- r = new Date(a, 0, 1);
- }
- return r;
- }
- focusNextCell(e) {
- let t = this.getInitialFocusDate(),
- { currentView: s } = this.dp,
- { days: a, months: n, years: r } = i,
- h = o(t),
- l = h.year,
- d = h.month,
- c = h.date;
- switch (e) {
- case "ArrowLeft":
- s === a && (c -= 1), s === n && (d -= 1), s === r && (l -= 1);
- break;
- case "ArrowUp":
- s === a && (c -= 7), s === n && (d -= 3), s === r && (l -= 4);
- break;
- case "ArrowRight":
- s === a && (c += 1), s === n && (d += 1), s === r && (l += 1);
- break;
- case "ArrowDown":
- s === a && (c += 7), s === n && (d += 3), s === r && (l += 4);
- }
- let u = this.dp.getClampedDate(new Date(l, d, c));
- this.dp.setFocusDate(u, { viewDateTransition: !0 });
- }
- registerKey(e) {
- this.pressedKeys.add(e);
- }
- removeKey(e) {
- this.pressedKeys.delete(e);
- }
- }
- let N = {
- on(e, t) {
- this.__events || (this.__events = {}),
- this.__events[e]
- ? this.__events[e].push(t)
- : (this.__events[e] = [t]);
- },
- off(e, t) {
- this.__events &&
- this.__events[e] &&
- (this.__events[e] = this.__events[e].filter((e) => e !== t));
- },
- removeAllEvents() {
- this.__events = {};
- },
- trigger(e) {
- for (
- var t = arguments.length, i = new Array(t > 1 ? t - 1 : 0), s = 1;
- s < t;
- s++
- )
- i[s - 1] = arguments[s];
- this.__events &&
- this.__events[e] &&
- this.__events[e].forEach((e) => {
- e(...i);
- });
- },
- };
- function I(e, t, i) {
- return (
- t in e
- ? Object.defineProperty(e, t, {
- value: i,
- enumerable: !0,
- configurable: !0,
- writable: !0,
- })
- : (e[t] = i),
- e
- );
- }
- let R = "",
- P = "",
- B = "",
- K = !1;
- class j {
- constructor(e, t) {
- var r = this;
- if (
- (I(this, "viewIndexes", [i.days, i.months, i.years]),
- I(this, "next", () => {
- let { year: e, month: t } = this.parsedViewDate;
- switch (this.currentView) {
- case i.days:
- this.setViewDate(new Date(e, t + 1, 1));
- break;
- case i.months:
- this.setViewDate(new Date(e + 1, t, 1));
- break;
- case i.years:
- this.setViewDate(new Date(e + 10, 0, 1));
- }
- }),
- I(this, "prev", () => {
- let { year: e, month: t } = this.parsedViewDate;
- switch (this.currentView) {
- case i.days:
- this.setViewDate(new Date(e, t - 1, 1));
- break;
- case i.months:
- this.setViewDate(new Date(e - 1, t, 1));
- break;
- case i.years:
- this.setViewDate(new Date(e - 10, 0, 1));
- }
- }),
- I(this, "_finishHide", () => {
- (this.hideAnimation = !1),
- this._destroyComponents(),
- this.$container.removeChild(this.$datepicker);
- }),
- I(this, "setPosition", function (e) {
- let t =
- arguments.length > 1 && void 0 !== arguments[1] && arguments[1];
- if ("function" == typeof (e = e || r.opts.position))
- return void (r.customHide = e({
- $datepicker: r.$datepicker,
- $target: r.$el,
- $pointer: r.$pointer,
- isViewChange: t,
- done: r._finishHide,
- }));
- let i,
- s,
- { isMobile: a } = r.opts,
- n = r.$el.getBoundingClientRect(),
- h = r.$el.getBoundingClientRect(),
- o = r.$datepicker.offsetParent,
- l = r.$el.offsetParent,
- d = r.$datepicker.getBoundingClientRect(),
- c = e.split(" "),
- u = window.scrollY,
- p = window.scrollX,
- m = r.opts.offset,
- g = c[0],
- D = c[1];
- if (a) r.$datepicker.style.cssText = "left: 50%; top: 50%";
- else {
- if (
- (o === l &&
- o !== document.body &&
- ((h = {
- top: r.$el.offsetTop,
- left: r.$el.offsetLeft,
- width: n.width,
- height: r.$el.offsetHeight,
- }),
- (u = 0),
- (p = 0)),
- o !== l && o !== document.body)
- ) {
- let e = o.getBoundingClientRect();
- (h = {
- top: n.top - e.top,
- left: n.left - e.left,
- width: n.width,
- height: n.height,
- }),
- (u = 0),
- (p = 0);
- }
- switch (g) {
- case "top":
- i = h.top - d.height - m;
- break;
- case "right":
- s = h.left + h.width + m;
- break;
- case "bottom":
- i = h.top + h.height + m;
- break;
- case "left":
- s = h.left - d.width - m;
- }
- switch (D) {
- case "top":
- i = h.top;
- break;
- case "right":
- s = h.left + h.width - d.width;
- break;
- case "bottom":
- i = h.top + h.height - d.height;
- break;
- case "left":
- s = h.left;
- break;
- case "center":
- /left|right/.test(g)
- ? (i = h.top + h.height / 2 - d.height / 2)
- : (s = h.left + h.width / 2 - d.width / 2);
- }
- r.$datepicker.style.cssText = "left: "
- .concat(s + p, "px; top: ")
- .concat(i + u, "px");
- }
- }),
- I(this, "_setInputValue", () => {
- let {
- opts: e,
- $altField: t,
- locale: { dateFormat: i },
- } = this,
- { altFieldDateFormat: s, altField: a } = e;
- a && t && (t.value = this._getInputValue(s)),
- (this.$el.value = this._getInputValue(i));
- }),
- I(this, "_getInputValue", (e) => {
- let { selectedDates: t, opts: i } = this,
- { multipleDates: s, multipleDatesSeparator: a } = i;
- if (!t.length) return "";
- let n = "function" == typeof e,
- r = n ? e(s ? t : t[0]) : t.map((t) => this.formatDate(t, e));
- return (r = n ? r : r.join(a)), r;
- }),
- I(this, "_checkIfDateIsSelected", function (e) {
- let t =
- arguments.length > 1 && void 0 !== arguments[1]
- ? arguments[1]
- : i.days,
- s = !1;
- return (
- r.selectedDates.some((i) => {
- let a = u(e, i, t);
- return (s = a && i), a;
- }),
- s
- );
- }),
- I(this, "_scheduleCallAfterTransition", (e) => {
- this._cancelScheduledCall(),
- e && e(!1),
- (this._onTransitionEnd = () => {
- e && e(!0);
- }),
- this.$datepicker.addEventListener(
- "transitionend",
- this._onTransitionEnd,
- { once: !0 }
- );
- }),
- I(this, "_cancelScheduledCall", () => {
- this.$datepicker.removeEventListener(
- "transitionend",
- this._onTransitionEnd
- );
- }),
- I(this, "setViewDate", (e) => {
- if (!((e = b(e)) instanceof Date)) return;
- if (u(e, this.viewDate)) return;
- let t = this.viewDate;
- this.viewDate = e;
- let { onChangeViewDate: s } = this.opts;
- if (s) {
- let { month: e, year: t } = this.parsedViewDate;
- s({ month: e, year: t, decade: this.curDecade });
- }
- this.trigger(i.eventChangeViewDate, e, t);
- }),
- I(this, "setFocusDate", function (e) {
- let t =
- arguments.length > 1 && void 0 !== arguments[1]
- ? arguments[1]
- : {};
- (!e || (e = b(e)) instanceof Date) &&
- ((r.focusDate = e),
- r.opts.range && e && r._handleRangeOnFocus(),
- r.trigger(i.eventChangeFocusDate, e, t));
- }),
- I(this, "setCurrentView", (e) => {
- if (this.viewIndexes.includes(e)) {
- if (
- ((this.currentView = e),
- this.elIsInput && this.visible && this.setPosition(void 0, !0),
- this.trigger(i.eventChangeCurrentView, e),
- !this.views[e])
- ) {
- let t = (this.views[e] = new T({
- dp: this,
- opts: this.opts,
- type: e,
- }));
- this.shouldUpdateDOM && this.$content.appendChild(t.$el);
- }
- this.opts.onChangeView && this.opts.onChangeView(e);
- }
- }),
- I(this, "_updateLastSelectedDate", (e) => {
- (this.lastSelectedDate = e),
- this.trigger(i.eventChangeLastSelectedDate, e);
- }),
- I(this, "destroy", () => {
- let { showEvent: e, isMobile: t } = this.opts,
- i = this.$datepicker.parentNode;
- i && i.removeChild(this.$datepicker),
- this.$el.removeEventListener(e, this._onFocus),
- this.$el.removeEventListener("blur", this._onBlur),
- window.removeEventListener("resize", this._onResize),
- t && this._removeMobileAttributes(),
- this.keyboardNav && this.keyboardNav.destroy(),
- (this.views = null),
- (this.nav = null),
- (this.$datepicker = null),
- (this.opts = null),
- (this.$customContainer = null),
- (this.viewDate = null),
- (this.focusDate = null),
- (this.selectedDates = null),
- (this.rangeDateFrom = null),
- (this.rangeDateTo = null);
- }),
- I(this, "update", (e) => {
- let t = w({}, this.opts);
- w(this.opts, e);
- let {
- timepicker: s,
- buttons: a,
- range: n,
- selectedDates: r,
- isMobile: h,
- } = this.opts,
- o = this.visible || this.treatAsInline;
- this._createMinMaxDates(),
- this._limitViewDateByMaxMinDates(),
- this._handleLocale(),
- !t.selectedDates && r && this.selectDate(r),
- e.view && this.setCurrentView(e.view),
- this._setInputValue(),
- t.range && !n
- ? ((this.rangeDateTo = !1), (this.rangeDateFrom = !1))
- : !t.range &&
- n &&
- this.selectedDates.length &&
- ((this.rangeDateFrom = this.selectedDates[0]),
- (this.rangeDateTo = this.selectedDates[1])),
- t.timepicker && !s
- ? (o && this.timepicker.destroy(),
- (this.timepicker = !1),
- this.$timepicker.parentNode.removeChild(this.$timepicker))
- : !t.timepicker && s && this._addTimepicker(),
- !t.buttons && a
- ? this._addButtons()
- : t.buttons && !a
- ? (this.buttons.destroy(),
- this.$buttons.parentNode.removeChild(this.$buttons))
- : o && t.buttons && a && this.buttons.clearHtml().render(),
- !t.isMobile && h
- ? (this.treatAsInline || B || this._createMobileOverlay(),
- this._addMobileAttributes(),
- this.visible && this._showMobileOverlay())
- : t.isMobile &&
- !h &&
- (this._removeMobileAttributes(),
- this.visible &&
- (B.classList.remove("-active-"),
- "function" != typeof this.opts.position &&
- this.setPosition())),
- o &&
- (this.nav.update(),
- this.views[this.currentView].render(),
- this.currentView === i.days &&
- this.views[this.currentView].renderDayNames());
- }),
- I(this, "isOtherMonth", (e) => {
- let { month: t } = o(e);
- return t !== this.parsedViewDate.month;
- }),
- I(this, "isOtherYear", (e) => {
- let { year: t } = o(e);
- return t !== this.parsedViewDate.year;
- }),
- I(this, "isOtherDecade", (e) => {
- let { year: t } = o(e),
- [i, s] = d(this.viewDate);
- return t < i || t > s;
- }),
- I(this, "_onChangeSelectedDate", (e) => {
- let { silent: t } = e;
- setTimeout(() => {
- this._setInputValue(),
- this.opts.onSelect && !t && this._triggerOnSelect();
- });
- }),
- I(this, "_onChangeFocusedDate", function (e) {
- let { viewDateTransition: t } =
- arguments.length > 1 && void 0 !== arguments[1]
- ? arguments[1]
- : {};
- if (!e) return;
- let i = !1;
- t &&
- (i = r.isOtherMonth(e) || r.isOtherYear(e) || r.isOtherDecade(e)),
- i && r.setViewDate(e);
- }),
- I(this, "_onChangeTime", (e) => {
- let { hours: t, minutes: i } = e,
- s = new Date(),
- {
- lastSelectedDate: a,
- opts: { onSelect: n },
- } = this,
- r = a;
- a || (r = s);
- let h = this.getCell(r, this.currentViewSingular),
- o = h && h.adpCell;
- (o && o.isDisabled) ||
- (r.setHours(t),
- r.setMinutes(i),
- a
- ? (this._setInputValue(), n && this._triggerOnSelect())
- : this.selectDate(r));
- }),
- I(this, "_onFocus", (e) => {
- this.visible || this.show();
- }),
- I(this, "_onBlur", (e) => {
- this.inFocus || !this.visible || this.opts.isMobile || this.hide();
- }),
- I(this, "_onMouseDown", (e) => {
- this.inFocus = !0;
- }),
- I(this, "_onMouseUp", (e) => {
- (this.inFocus = !1), this.$el.focus();
- }),
- I(this, "_onResize", () => {
- this.visible &&
- "function" != typeof this.opts.position &&
- this.setPosition();
- }),
- I(this, "_onClickOverlay", () => {
- this.visible && this.hide();
- }),
- I(this, "isWeekend", (e) => this.opts.weekends.includes(e)),
- I(this, "getClampedDate", (e) => {
- let { minDate: t, maxDate: i } = this,
- s = e;
- return i && p(e, i) ? (s = i) : t && m(e, t) && (s = t), s;
- }),
- (this.$el = a(e)),
- !this.$el)
- )
- return;
- (this.$datepicker = n({ className: "air-datepicker" })),
- (this.opts = w({}, s, t)),
- (this.$customContainer =
- !!this.opts.container && a(this.opts.container)),
- (this.$altField = a(this.opts.altField || !1)),
- R || (R = a("body"));
- let { view: h, startDate: l } = this.opts;
- l || (this.opts.startDate = new Date()),
- "INPUT" === this.$el.nodeName && (this.elIsInput = !0),
- (this.inited = !1),
- (this.visible = !1),
- (this.viewDate = b(this.opts.startDate)),
- (this.focusDate = !1),
- (this.initialReadonly = this.$el.getAttribute("readonly")),
- (this.customHide = !1),
- (this.currentView = h),
- (this.selectedDates = []),
- (this.views = {}),
- (this.keys = []),
- (this.rangeDateFrom = ""),
- (this.rangeDateTo = ""),
- (this.timepickerIsActive = !1),
- (this.treatAsInline = this.opts.inline || !this.elIsInput),
- this.init();
- }
- init() {
- let {
- opts: e,
- treatAsInline: t,
- opts: {
- inline: i,
- isMobile: s,
- selectedDates: a,
- keyboardNav: r,
- onlyTimepicker: h,
- },
- } = this;
- var o;
- K ||
- i ||
- !this.elIsInput ||
- ((K = !0),
- (P = n({ className: (o = j.defaultContainerId), id: o })),
- R.appendChild(P)),
- !s || B || t || this._createMobileOverlay(),
- this._handleLocale(),
- this._bindSubEvents(),
- this._createMinMaxDates(),
- this._limitViewDateByMaxMinDates(),
- this.elIsInput &&
- (i || this._bindEvents(),
- r && !h && (this.keyboardNav = new A({ dp: this, opts: e }))),
- a && this.selectDate(a, { silent: !0 }),
- this.opts.visible && !t && this.show(),
- s && !t && this.$el.setAttribute("readonly", !0),
- t && this._createComponents();
- }
- _createMobileOverlay() {
- (B = n({ className: "air-datepicker-overlay" })), P.appendChild(B);
- }
- _createComponents() {
- let {
- opts: e,
- treatAsInline: t,
- opts: {
- inline: i,
- buttons: s,
- timepicker: a,
- position: n,
- classes: r,
- onlyTimepicker: h,
- isMobile: o,
- },
- } = this;
- this._buildBaseHtml(),
- this.elIsInput && (i || this._setPositionClasses(n)),
- (!i && this.elIsInput) || this.$datepicker.classList.add("-inline-"),
- r && this.$datepicker.classList.add(...r.split(" ")),
- h && this.$datepicker.classList.add("-only-timepicker-"),
- o && !t && this._addMobileAttributes(),
- (this.views[this.currentView] = new T({
- dp: this,
- type: this.currentView,
- opts: e,
- })),
- (this.nav = new V({ dp: this, opts: e })),
- a && this._addTimepicker(),
- s && this._addButtons(),
- this.$content.appendChild(this.views[this.currentView].$el),
- this.$nav.appendChild(this.nav.$el);
- }
- _destroyComponents() {
- for (let e in this.views) this.views[e].destroy();
- (this.views = {}),
- this.nav.destroy(),
- this.timepicker && this.timepicker.destroy();
- }
- _addMobileAttributes() {
- B.addEventListener("click", this._onClickOverlay),
- this.$datepicker.classList.add("-is-mobile-"),
- this.$el.setAttribute("readonly", !0);
- }
- _removeMobileAttributes() {
- B.removeEventListener("click", this._onClickOverlay),
- this.$datepicker.classList.remove("-is-mobile-"),
- this.initialReadonly ||
- "" === this.initialReadonly ||
- this.$el.removeAttribute("readonly");
- }
- _createMinMaxDates() {
- let { minDate: e, maxDate: t } = this.opts;
- (this.minDate = !!e && b(e)), (this.maxDate = !!t && b(t));
- }
- _addTimepicker() {
- (this.$timepicker = n({ className: "air-datepicker--time" })),
- this.$datepicker.appendChild(this.$timepicker),
- (this.timepicker = new O({ dp: this, opts: this.opts })),
- this.$timepicker.appendChild(this.timepicker.$el);
- }
- _addButtons() {
- (this.$buttons = n({ className: "air-datepicker--buttons" })),
- this.$datepicker.appendChild(this.$buttons),
- (this.buttons = new H({ dp: this, opts: this.opts })),
- this.$buttons.appendChild(this.buttons.$el);
- }
- _bindSubEvents() {
- this.on(i.eventChangeSelectedDate, this._onChangeSelectedDate),
- this.on(i.eventChangeFocusDate, this._onChangeFocusedDate),
- this.on(i.eventChangeTime, this._onChangeTime);
- }
- _buildBaseHtml() {
- let { inline: e } = this.opts;
- var t, i;
- this.elIsInput
- ? e
- ? ((t = this.$datepicker),
- (i = this.$el).parentNode.insertBefore(t, i.nextSibling))
- : this.$container.appendChild(this.$datepicker)
- : this.$el.appendChild(this.$datepicker),
- (this.$datepicker.innerHTML =
- ''),
- (this.$content = a(".air-datepicker--content", this.$datepicker)),
- (this.$pointer = a(".air-datepicker--pointer", this.$datepicker)),
- (this.$nav = a(".air-datepicker--navigation", this.$datepicker));
- }
- _handleLocale() {
- let {
- locale: e,
- dateFormat: t,
- firstDay: i,
- timepicker: s,
- onlyTimepicker: a,
- timeFormat: n,
- dateTimeSeparator: r,
- } = this.opts;
- var h;
- (this.locale = ((h = e), JSON.parse(JSON.stringify(h)))),
- t && (this.locale.dateFormat = t),
- void 0 !== n && "" !== n && (this.locale.timeFormat = n);
- let { timeFormat: o } = this.locale;
- if (
- ("" !== i && (this.locale.firstDay = i), s && "function" != typeof t)
- ) {
- let e = o ? r : "";
- this.locale.dateFormat = [this.locale.dateFormat, o || ""].join(e);
- }
- a &&
- "function" != typeof t &&
- (this.locale.dateFormat = this.locale.timeFormat);
- }
- _setPositionClasses(e) {
- if ("function" == typeof e)
- return void this.$datepicker.classList.add("-custom-position-");
- let t = (e = e.split(" "))[0],
- i = e[1],
- s = "air-datepicker -"
- .concat(t, "-")
- .concat(i, "- -from-")
- .concat(t, "-");
- this.$datepicker.classList.add(...s.split(" "));
- }
- _bindEvents() {
- this.$el.addEventListener(this.opts.showEvent, this._onFocus),
- this.$el.addEventListener("blur", this._onBlur),
- this.$datepicker.addEventListener("mousedown", this._onMouseDown),
- this.$datepicker.addEventListener("mouseup", this._onMouseUp),
- window.addEventListener("resize", this._onResize);
- }
- _limitViewDateByMaxMinDates() {
- let { viewDate: e, minDate: t, maxDate: i } = this;
- i && p(e, i) && this.setViewDate(i),
- t && m(e, t) && this.setViewDate(t);
- }
- formatDate() {
- let e =
- arguments.length > 0 && void 0 !== arguments[0]
- ? arguments[0]
- : this.viewDate,
- t = arguments.length > 1 ? arguments[1] : void 0;
- if (((e = b(e)), !(e instanceof Date))) return;
- let i = t,
- s = this.locale,
- a = o(e),
- n = d(e),
- r = j.replacer,
- h = "am";
- this.opts.timepicker &&
- this.timepicker &&
- (h = this.timepicker.getDayPeriod(e).dayPeriod);
- let l = {
- T: e.getTime(),
- m: a.minutes,
- mm: a.fullMinutes,
- h: a.hours12,
- hh: a.fullHours12,
- H: a.hours,
- HH: a.fullHours,
- aa: h,
- AA: h.toUpperCase(),
- E: s.daysShort[a.day],
- EEEE: s.days[a.day],
- d: a.date,
- dd: a.fullDate,
- M: a.month + 1,
- MM: a.fullMonth,
- MMM: s.monthsShort[a.month],
- MMMM: s.months[a.month],
- yy: a.year.toString().slice(-2),
- yyyy: a.year,
- yyyy1: n[0],
- yyyy2: n[1],
- };
- for (let [e, t] of Object.entries(l)) i = r(i, k(e), t);
- return i;
- }
- down(e) {
- this._handleUpDownActions(e, "down");
- }
- up(e) {
- this._handleUpDownActions(e, "up");
- }
- selectDate(e) {
- let t,
- s =
- arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : {},
- { currentView: a, parsedViewDate: n, selectedDates: r } = this,
- { updateTime: h } = s,
- {
- moveToOtherMonthsOnSelect: o,
- moveToOtherYearsOnSelect: l,
- multipleDates: d,
- range: c,
- autoClose: u,
- } = this.opts,
- m = r.length;
- if (Array.isArray(e))
- return (
- e.forEach((e) => {
- this.selectDate(e, s);
- }),
- new Promise((e) => {
- setTimeout(e);
- })
- );
- if ((e = b(e)) instanceof Date) {
- if (
- (a === i.days &&
- e.getMonth() !== n.month &&
- o &&
- (t = new Date(e.getFullYear(), e.getMonth(), 1)),
- a === i.years &&
- e.getFullYear() !== n.year &&
- l &&
- (t = new Date(e.getFullYear(), 0, 1)),
- t && this.setViewDate(t),
- d && !c)
- ) {
- if (m === d) return;
- this._checkIfDateIsSelected(e) || r.push(e);
- } else if (c)
- switch (m) {
- case 1:
- r.push(e),
- this.rangeDateTo || (this.rangeDateTo = e),
- p(this.rangeDateFrom, this.rangeDateTo) &&
- ((this.rangeDateTo = this.rangeDateFrom),
- (this.rangeDateFrom = e)),
- (this.selectedDates = [this.rangeDateFrom, this.rangeDateTo]);
- break;
- case 2:
- (this.selectedDates = [e]),
- (this.rangeDateFrom = e),
- (this.rangeDateTo = "");
- break;
- default:
- (this.selectedDates = [e]), (this.rangeDateFrom = e);
- }
- else this.selectedDates = [e];
- return (
- this.trigger(i.eventChangeSelectedDate, {
- action: i.actionSelectDate,
- silent: null == s ? void 0 : s.silent,
- date: e,
- updateTime: h,
- }),
- this._updateLastSelectedDate(e),
- u &&
- !this.timepickerIsActive &&
- this.visible &&
- (d || c ? c && 1 === m && this.hide() : this.hide()),
- new Promise((e) => {
- setTimeout(e);
- })
- );
- }
- }
- unselectDate(e) {
- let t = this.selectedDates,
- s = this;
- if ((e = b(e)) instanceof Date)
- return t.some((a, n) => {
- if (u(a, e))
- return (
- t.splice(n, 1),
- s.selectedDates.length
- ? s._updateLastSelectedDate(
- s.selectedDates[s.selectedDates.length - 1]
- )
- : ((s.rangeDateFrom = ""),
- (s.rangeDateTo = ""),
- s._updateLastSelectedDate(!1)),
- this.trigger(i.eventChangeSelectedDate, {
- action: i.actionUnselectDate,
- date: e,
- }),
- !0
- );
- });
- }
- replaceDate(e, t) {
- let s = this.selectedDates.find((t) => u(t, e, this.currentView)),
- a = this.selectedDates.indexOf(s);
- a < 0 ||
- u(this.selectedDates[a], t, this.currentView) ||
- ((this.selectedDates[a] = t),
- this.trigger(i.eventChangeSelectedDate, {
- action: i.actionSelectDate,
- date: t,
- updateTime: !0,
- }),
- this._updateLastSelectedDate(t));
- }
- clear() {
- let e =
- arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {};
- return (
- (this.selectedDates = []),
- (this.rangeDateFrom = !1),
- (this.rangeDateTo = !1),
- this.trigger(i.eventChangeSelectedDate, {
- action: i.actionUnselectDate,
- silent: e.silent,
- }),
- new Promise((e) => {
- setTimeout(e);
- })
- );
- }
- show() {
- let { onShow: e, isMobile: t } = this.opts;
- this._cancelScheduledCall(),
- this.visible || this.hideAnimation || this._createComponents(),
- this.setPosition(this.opts.position),
- this.$datepicker.classList.add("-active-"),
- (this.visible = !0),
- e && this._scheduleCallAfterTransition(e),
- t && this._showMobileOverlay();
- }
- hide() {
- let { onHide: e, isMobile: t } = this.opts,
- i = this._hasTransition();
- (this.visible = !1),
- (this.hideAnimation = !0),
- this.$datepicker.classList.remove("-active-"),
- this.customHide && this.customHide(),
- this.elIsInput && this.$el.blur(),
- this._scheduleCallAfterTransition((t) => {
- !this.customHide && ((t && i) || (!t && !i)) && this._finishHide(),
- e && e(t);
- }),
- t && B.classList.remove("-active-");
- }
- _triggerOnSelect() {
- let e = [],
- t = [],
- {
- selectedDates: i,
- locale: s,
- opts: { onSelect: a, multipleDates: n, range: r },
- } = this,
- h = n || r,
- o = "function" == typeof s.dateFormat;
- i.length &&
- ((e = i.map(g)),
- (t = o
- ? n
- ? s.dateFormat(e)
- : e.map((e) => s.dateFormat(e))
- : e.map((e) => this.formatDate(e, s.dateFormat)))),
- a({
- date: h ? e : e[0],
- formattedDate: h ? t : t[0],
- datepicker: this,
- });
- }
- _handleAlreadySelectedDates(e, t) {
- let { range: i, toggleSelected: s } = this.opts;
- i
- ? s
- ? this.unselectDate(t)
- : 2 !== this.selectedDates.length && this.selectDate(t)
- : s && this.unselectDate(t),
- s || this._updateLastSelectedDate(e);
- }
- _handleUpDownActions(e, t) {
- if (!((e = b(e || this.focusDate || this.viewDate)) instanceof Date))
- return;
- let i = "up" === t ? this.viewIndex + 1 : this.viewIndex - 1;
- i > 2 && (i = 2),
- i < 0 && (i = 0),
- this.setViewDate(new Date(e.getFullYear(), e.getMonth(), 1)),
- this.setCurrentView(this.viewIndexes[i]);
- }
- _handleRangeOnFocus() {
- 1 === this.selectedDates.length &&
- (p(this.selectedDates[0], this.focusDate)
- ? ((this.rangeDateTo = this.selectedDates[0]),
- (this.rangeDateFrom = this.focusDate))
- : ((this.rangeDateTo = this.focusDate),
- (this.rangeDateFrom = this.selectedDates[0])));
- }
- getCell(e) {
- let t =
- arguments.length > 1 && void 0 !== arguments[1]
- ? arguments[1]
- : i.day;
- if (!((e = b(e)) instanceof Date)) return;
- let { year: s, month: a, date: n } = o(e),
- r = '[data-year="'.concat(s, '"]'),
- h = '[data-month="'.concat(a, '"]'),
- l = '[data-date="'.concat(n, '"]'),
- d = {
- [i.day]: "".concat(r).concat(h).concat(l),
- [i.month]: "".concat(r).concat(h),
- [i.year]: "".concat(r),
- };
- return this.views[this.currentView].$el.querySelector(d[t]);
- }
- _showMobileOverlay() {
- B.classList.add("-active-");
- }
- _hasTransition() {
- return (
- window
- .getComputedStyle(this.$datepicker)
- .getPropertyValue("transition-duration")
- .split(", ")
- .reduce((e, t) => parseFloat(t) + e, 0) > 0
- );
- }
- get shouldUpdateDOM() {
- return this.visible || this.treatAsInline;
- }
- get parsedViewDate() {
- return o(this.viewDate);
- }
- get currentViewSingular() {
- return this.currentView.slice(0, -1);
- }
- get curDecade() {
- return d(this.viewDate);
- }
- get viewIndex() {
- return this.viewIndexes.indexOf(this.currentView);
- }
- get isFinalView() {
- return this.currentView === i.years;
- }
- get hasSelectedDates() {
- return this.selectedDates.length > 0;
- }
- get isMinViewReached() {
- return (
- this.currentView === this.opts.minView || this.currentView === i.days
- );
- }
- get $container() {
- return this.$customContainer || P;
- }
- static replacer(e, t, i) {
- return e.replace(t, function (e, t, s, a) {
- return t + i + a;
- });
- }
- }
- var U;
- const datepicker = new AirDatepicker("input[fetchdatetimepicker]");
- return (
- I(j, "defaults", s),
- I(j, "version", "3.3.1"),
- I(j, "defaultContainerId", "air-datepicker-global-container"),
- (U = j.prototype),
- Object.assign(U, N),
- t.default
- );
- })();
-});
diff --git a/src/ui/static/js/air-datepicker/index.es.js b/src/ui/static/js/air-datepicker/index.es.js
deleted file mode 100644
index 4074f38eb..000000000
--- a/src/ui/static/js/air-datepicker/index.es.js
+++ /dev/null
@@ -1,2 +0,0 @@
-import AirDatepicker from "air-datepicker";
-export default AirDatepicker;
diff --git a/src/ui/static/js/air-datepicker/locale/ar.d.ts b/src/ui/static/js/air-datepicker/locale/ar.d.ts
deleted file mode 100644
index 5b79468ec..000000000
--- a/src/ui/static/js/air-datepicker/locale/ar.d.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-declare module 'air-datepicker/locale/ar' {
- import {AirDatepickerLocale} from 'air-datepicker';
- const ar: AirDatepickerLocale;
-
- export default ar;
-}
diff --git a/src/ui/static/js/air-datepicker/locale/ar.js b/src/ui/static/js/air-datepicker/locale/ar.js
deleted file mode 100644
index 828683a7b..000000000
--- a/src/ui/static/js/air-datepicker/locale/ar.js
+++ /dev/null
@@ -1,19 +0,0 @@
-"use strict";
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.default = void 0;
-var _default = {
- days: ['الأحد', 'الأثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعه', 'السبت'],
- daysShort: ['الأحد', 'الأثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعه', 'السبت'],
- daysMin: ['الأحد', 'الأثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعه', 'السبت'],
- months: ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'اكتوبر', 'نوفمبر', 'ديسمبر'],
- monthsShort: ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'اكتوبر', 'نوفمبر', 'ديسمبر'],
- today: 'اليوم',
- clear: 'حذف',
- dateFormat: 'dd/MM/yyyy',
- timeFormat: 'hh:mm aa',
- firstDay: 0
-};
-exports.default = _default;
\ No newline at end of file
diff --git a/src/ui/static/js/air-datepicker/locale/cs.d.ts b/src/ui/static/js/air-datepicker/locale/cs.d.ts
deleted file mode 100644
index 5e91529bb..000000000
--- a/src/ui/static/js/air-datepicker/locale/cs.d.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-declare module 'air-datepicker/locale/cs' {
- import {AirDatepickerLocale} from 'air-datepicker';
- const cs: AirDatepickerLocale;
-
- export default cs;
-}
diff --git a/src/ui/static/js/air-datepicker/locale/cs.js b/src/ui/static/js/air-datepicker/locale/cs.js
deleted file mode 100644
index 65062439c..000000000
--- a/src/ui/static/js/air-datepicker/locale/cs.js
+++ /dev/null
@@ -1,19 +0,0 @@
-"use strict";
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.default = void 0;
-var _default = {
- days: ['Neděle', 'Pondělí', 'Úterý', 'Středa', 'Čtvrtek', 'Pátek', 'Sobota'],
- daysShort: ['Ne', 'Po', 'Út', 'St', 'Čt', 'Pá', 'So'],
- daysMin: ['Ne', 'Po', 'Út', 'St', 'Čt', 'Pá', 'So'],
- months: ['Leden', 'Únor', 'Březen', 'Duben', 'Květen', 'Červen', 'Červenec', 'Srpen', 'Září', 'Říjen', 'Listopad', 'Prosinec'],
- monthsShort: ['Led', 'Úno', 'Bře', 'Dub', 'Kvě', 'Čvn', 'Čvc', 'Srp', 'Zář', 'Říj', 'Lis', 'Pro'],
- today: 'Dnes',
- clear: 'Vymazat',
- dateFormat: 'dd.MM.yyyy',
- timeFormat: 'HH:mm',
- firstDay: 1
-};
-exports.default = _default;
\ No newline at end of file
diff --git a/src/ui/static/js/air-datepicker/locale/da.d.ts b/src/ui/static/js/air-datepicker/locale/da.d.ts
deleted file mode 100644
index 173e75805..000000000
--- a/src/ui/static/js/air-datepicker/locale/da.d.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-declare module 'air-datepicker/locale/da' {
- import {AirDatepickerLocale} from 'air-datepicker';
- const da: AirDatepickerLocale;
-
- export default da;
-}
diff --git a/src/ui/static/js/air-datepicker/locale/da.js b/src/ui/static/js/air-datepicker/locale/da.js
deleted file mode 100644
index 7f527b4a2..000000000
--- a/src/ui/static/js/air-datepicker/locale/da.js
+++ /dev/null
@@ -1,19 +0,0 @@
-"use strict";
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.default = void 0;
-var _default = {
- days: ['Søndag', 'Mandag', 'Tirsdag', 'Onsdag', 'Torsdag', 'Fredag', 'Lørdag'],
- daysShort: ['Søn', 'Man', 'Tir', 'Ons', 'Tor', 'Fre', 'Lør'],
- daysMin: ['Sø', 'Ma', 'Ti', 'On', 'To', 'Fr', 'Lø'],
- months: ['Januar', 'Februar', 'Marts', 'April', 'Maj', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'December'],
- monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'Maj', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dec'],
- today: 'I dag',
- clear: 'Nulstil',
- dateFormat: 'dd/MM/yyyy',
- timeFormat: 'HH:mm',
- firstDay: 1
-};
-exports.default = _default;
\ No newline at end of file
diff --git a/src/ui/static/js/air-datepicker/locale/de.d.ts b/src/ui/static/js/air-datepicker/locale/de.d.ts
deleted file mode 100644
index ac35fc8ec..000000000
--- a/src/ui/static/js/air-datepicker/locale/de.d.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-declare module 'air-datepicker/locale/de' {
- import {AirDatepickerLocale} from 'air-datepicker';
- const de: AirDatepickerLocale;
-
- export default de;
-}
diff --git a/src/ui/static/js/air-datepicker/locale/de.js b/src/ui/static/js/air-datepicker/locale/de.js
deleted file mode 100644
index da9c582a1..000000000
--- a/src/ui/static/js/air-datepicker/locale/de.js
+++ /dev/null
@@ -1,19 +0,0 @@
-"use strict";
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.default = void 0;
-var _default = {
- days: ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'],
- daysShort: ['Son', 'Mon', 'Die', 'Mit', 'Don', 'Fre', 'Sam'],
- daysMin: ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'],
- months: ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'],
- monthsShort: ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],
- today: 'Heute',
- clear: 'Aufräumen',
- dateFormat: 'dd.MM.yyyy',
- timeFormat: 'HH:ii',
- firstDay: 1
-};
-exports.default = _default;
\ No newline at end of file
diff --git a/src/ui/static/js/air-datepicker/locale/en.d.ts b/src/ui/static/js/air-datepicker/locale/en.d.ts
deleted file mode 100644
index 060236fc8..000000000
--- a/src/ui/static/js/air-datepicker/locale/en.d.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-declare module 'air-datepicker/locale/en' {
- import {AirDatepickerLocale} from 'air-datepicker';
- const en: AirDatepickerLocale;
-
- export default en;
-}
diff --git a/src/ui/static/js/air-datepicker/locale/en.js b/src/ui/static/js/air-datepicker/locale/en.js
deleted file mode 100644
index 7788883c2..000000000
--- a/src/ui/static/js/air-datepicker/locale/en.js
+++ /dev/null
@@ -1,19 +0,0 @@
-"use strict";
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.default = void 0;
-var _default = {
- days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
- daysShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
- daysMin: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'],
- months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
- monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
- today: 'Today',
- clear: 'Clear',
- dateFormat: 'MM/dd/yyyy',
- timeFormat: 'hh:mm aa',
- firstDay: 0
-};
-exports.default = _default;
\ No newline at end of file
diff --git a/src/ui/static/js/air-datepicker/locale/es.d.ts b/src/ui/static/js/air-datepicker/locale/es.d.ts
deleted file mode 100644
index 2c7e2b041..000000000
--- a/src/ui/static/js/air-datepicker/locale/es.d.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-declare module 'air-datepicker/locale/es' {
- import {AirDatepickerLocale} from 'air-datepicker';
- const es: AirDatepickerLocale;
-
- export default es;
-}
diff --git a/src/ui/static/js/air-datepicker/locale/es.js b/src/ui/static/js/air-datepicker/locale/es.js
deleted file mode 100644
index a5a1886fe..000000000
--- a/src/ui/static/js/air-datepicker/locale/es.js
+++ /dev/null
@@ -1,19 +0,0 @@
-"use strict";
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.default = void 0;
-var _default = {
- days: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado'],
- daysShort: ['Dom', 'Lun', 'Mar', 'Mie', 'Jue', 'Vie', 'Sab'],
- daysMin: ['Do', 'Lu', 'Ma', 'Mi', 'Ju', 'Vi', 'Sa'],
- months: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'],
- monthsShort: ['Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun', 'Jul', 'Ago', 'Sep', 'Oct', 'Nov', 'Dic'],
- today: 'Hoy',
- clear: 'Limpiar',
- dateFormat: 'dd/MM/yyyy',
- timeFormat: 'hh:mm aa',
- firstDay: 1
-};
-exports.default = _default;
\ No newline at end of file
diff --git a/src/ui/static/js/air-datepicker/locale/fi.d.ts b/src/ui/static/js/air-datepicker/locale/fi.d.ts
deleted file mode 100644
index 6b8f7e5d0..000000000
--- a/src/ui/static/js/air-datepicker/locale/fi.d.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-declare module 'air-datepicker/locale/fi' {
- import {AirDatepickerLocale} from 'air-datepicker';
- const fi: AirDatepickerLocale;
-
- export default fi;
-}
diff --git a/src/ui/static/js/air-datepicker/locale/fi.js b/src/ui/static/js/air-datepicker/locale/fi.js
deleted file mode 100644
index c4b538b54..000000000
--- a/src/ui/static/js/air-datepicker/locale/fi.js
+++ /dev/null
@@ -1,19 +0,0 @@
-"use strict";
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.default = void 0;
-var _default = {
- days: ['Sunnuntai', 'Maanantai', 'Tiistai', 'Keskiviikko', 'Torstai', 'Perjantai', 'Lauantai'],
- daysShort: ['Su', 'Ma', 'Ti', 'Ke', 'To', 'Pe', 'La'],
- daysMin: ['Su', 'Ma', 'Ti', 'Ke', 'To', 'Pe', 'La'],
- months: ['Tammikuu', 'Helmikuu', 'Maaliskuu', 'Huhtikuu', 'Toukokuu', 'Kesäkuu', 'Heinäkuu', 'Elokuu', 'Syyskuu', 'Lokakuu', 'Marraskuu', 'Joulukuu'],
- monthsShort: ['Tammi', 'Helmi', 'Maalis', 'Huhti', 'Touko', 'Kesä', 'Heinä', 'Elo', 'Syys', 'Loka', 'Marras', 'Joulu'],
- today: 'Tänään',
- clear: 'Tyhjennä',
- dateFormat: 'dd.MM.yyyy',
- timeFormat: 'HH:mm',
- firstDay: 1
-};
-exports.default = _default;
\ No newline at end of file
diff --git a/src/ui/static/js/air-datepicker/locale/fr.d.ts b/src/ui/static/js/air-datepicker/locale/fr.d.ts
deleted file mode 100644
index 9cc25a55b..000000000
--- a/src/ui/static/js/air-datepicker/locale/fr.d.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-declare module 'air-datepicker/locale/fr' {
- import {AirDatepickerLocale} from 'air-datepicker';
- const fr: AirDatepickerLocale;
-
- export default fr;
-}
diff --git a/src/ui/static/js/air-datepicker/locale/fr.js b/src/ui/static/js/air-datepicker/locale/fr.js
deleted file mode 100644
index 11ab7fe31..000000000
--- a/src/ui/static/js/air-datepicker/locale/fr.js
+++ /dev/null
@@ -1,19 +0,0 @@
-"use strict";
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.default = void 0;
-var _default = {
- days: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi'],
- daysShort: ['Dim', 'Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam'],
- daysMin: ['Di', 'Lu', 'Ma', 'Me', 'Je', 'Ve', 'Sa'],
- months: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
- monthsShort: ['Jan', 'Fév', 'Mars', 'Avr', 'Mai', 'Juin', 'Juil', 'Août', 'Sep', 'Oct', 'Nov', 'Dec'],
- today: "Aujourd'hui",
- clear: 'Effacer',
- dateFormat: 'dd/MM/yyyy',
- timeFormat: 'HH:mm',
- firstDay: 1
-};
-exports.default = _default;
\ No newline at end of file
diff --git a/src/ui/static/js/air-datepicker/locale/hu.d.ts b/src/ui/static/js/air-datepicker/locale/hu.d.ts
deleted file mode 100644
index a6558b97a..000000000
--- a/src/ui/static/js/air-datepicker/locale/hu.d.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-declare module 'air-datepicker/locale/hu' {
- import {AirDatepickerLocale} from 'air-datepicker';
- const hu: AirDatepickerLocale;
-
- export default hu;
-}
diff --git a/src/ui/static/js/air-datepicker/locale/hu.js b/src/ui/static/js/air-datepicker/locale/hu.js
deleted file mode 100644
index 30c5d38ef..000000000
--- a/src/ui/static/js/air-datepicker/locale/hu.js
+++ /dev/null
@@ -1,19 +0,0 @@
-"use strict";
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.default = void 0;
-var _default = {
- days: ['Vasárnap', 'Hétfő', 'Kedd', 'Szerda', 'Csütörtök', 'Péntek', 'Szombat'],
- daysShort: ['Va', 'Hé', 'Ke', 'Sze', 'Cs', 'Pé', 'Szo'],
- daysMin: ['V', 'H', 'K', 'Sz', 'Cs', 'P', 'Sz'],
- months: ['Január', 'Február', 'Március', 'Április', 'Május', 'Június', 'Július', 'Augusztus', 'Szeptember', 'Október', 'November', 'December'],
- monthsShort: ['Jan', 'Feb', 'Már', 'Ápr', 'Máj', 'Jún', 'Júl', 'Aug', 'Szep', 'Okt', 'Nov', 'Dec'],
- today: 'Ma',
- clear: 'Törlés',
- dateFormat: 'yyyy-MM-dd',
- timeFormat: 'hh:mm aa',
- firstDay: 1
-};
-exports.default = _default;
\ No newline at end of file
diff --git a/src/ui/static/js/air-datepicker/locale/it.d.ts b/src/ui/static/js/air-datepicker/locale/it.d.ts
deleted file mode 100644
index ca8aecd37..000000000
--- a/src/ui/static/js/air-datepicker/locale/it.d.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-declare module 'air-datepicker/locale/it' {
- import {AirDatepickerLocale} from 'air-datepicker';
- const it: AirDatepickerLocale;
-
- export default it;
-}
diff --git a/src/ui/static/js/air-datepicker/locale/it.js b/src/ui/static/js/air-datepicker/locale/it.js
deleted file mode 100644
index 12b663d6d..000000000
--- a/src/ui/static/js/air-datepicker/locale/it.js
+++ /dev/null
@@ -1,19 +0,0 @@
-"use strict";
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.default = void 0;
-var _default = {
- days: ['Domenica', 'Lunedì', 'Martedì', 'Mercoledì', 'Giovedì', 'Venerdì', 'Sabato'],
- daysShort: ['Dom', 'Lun', 'Mar', 'Mer', 'Gio', 'Ven', 'Sab'],
- daysMin: ['Do', 'Lu', 'Ma', 'Me', 'Gi', 'Ve', 'Sa'],
- months: ['Gennaio', 'Febbraio', 'Marzo', 'Aprile', 'Maggio', 'Giugno', 'Luglio', 'Agosto', 'Settembre', 'Ottobre', 'Novembre', 'Dicembre'],
- monthsShort: ['Gen', 'Feb', 'Mar', 'Apr', 'Mag', 'Giu', 'Lug', 'Ago', 'Set', 'Ott', 'Nov', 'Dic'],
- today: 'Oggi',
- clear: 'Cancella',
- dateFormat: 'dd/MM/yyyy',
- timeFormat: 'HH:mm',
- firstDay: 1
-};
-exports.default = _default;
\ No newline at end of file
diff --git a/src/ui/static/js/air-datepicker/locale/ja.d.ts b/src/ui/static/js/air-datepicker/locale/ja.d.ts
deleted file mode 100644
index da763b250..000000000
--- a/src/ui/static/js/air-datepicker/locale/ja.d.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-declare module 'air-datepicker/locale/ja' {
- import {AirDatepickerLocale} from 'air-datepicker';
- const ja: AirDatepickerLocale;
-
- export default ja;
-}
diff --git a/src/ui/static/js/air-datepicker/locale/ja.js b/src/ui/static/js/air-datepicker/locale/ja.js
deleted file mode 100644
index 1228fc60a..000000000
--- a/src/ui/static/js/air-datepicker/locale/ja.js
+++ /dev/null
@@ -1,19 +0,0 @@
-"use strict";
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.default = void 0;
-var _default = {
- days: ['日曜日', '月曜日', '火曜日', '水曜日', '木曜日', '金曜日', '土曜日'],
- daysShort: ['日', '月', '火', '水', '木', '金', '土'],
- daysMin: ['日', '月', '火', '水', '木', '金', '土'],
- months: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
- monthsShort: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
- today: '今日',
- clear: 'クリア',
- dateFormat: 'yyyy/MM/dd',
- timeFormat: 'HH:mm',
- firstDay: 0
-};
-exports.default = _default;
\ No newline at end of file
diff --git a/src/ui/static/js/air-datepicker/locale/ko.d.ts b/src/ui/static/js/air-datepicker/locale/ko.d.ts
deleted file mode 100644
index db244b076..000000000
--- a/src/ui/static/js/air-datepicker/locale/ko.d.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-declare module 'air-datepicker/locale/ko' {
- import {AirDatepickerLocale} from 'air-datepicker';
- const ko: AirDatepickerLocale;
-
- export default ko;
-}
diff --git a/src/ui/static/js/air-datepicker/locale/ko.js b/src/ui/static/js/air-datepicker/locale/ko.js
deleted file mode 100644
index 092901d71..000000000
--- a/src/ui/static/js/air-datepicker/locale/ko.js
+++ /dev/null
@@ -1,19 +0,0 @@
-"use strict";
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.default = void 0;
-var _default = {
- days: ['일요일', '월요일', '화요일', '수요일', '목요일', '금요일', '토요일'],
- daysShort: ['일', '월', '화', '수', '목', '금', '토'],
- daysMin: ['일', '월', '화', '수', '목', '금', '토'],
- months: ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월'],
- monthsShort: ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월'],
- today: '오늘',
- clear: '초기화',
- dateFormat: 'MM/dd/yyyy',
- timeFormat: 'hh:mm aa',
- firstDay: 0
-};
-exports.default = _default;
\ No newline at end of file
diff --git a/src/ui/static/js/air-datepicker/locale/nl.d.ts b/src/ui/static/js/air-datepicker/locale/nl.d.ts
deleted file mode 100644
index ce294eec9..000000000
--- a/src/ui/static/js/air-datepicker/locale/nl.d.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-declare module 'air-datepicker/locale/nl' {
- import {AirDatepickerLocale} from 'air-datepicker';
- const nl: AirDatepickerLocale;
-
- export default nl;
-}
diff --git a/src/ui/static/js/air-datepicker/locale/nl.js b/src/ui/static/js/air-datepicker/locale/nl.js
deleted file mode 100644
index 3c03fd2f3..000000000
--- a/src/ui/static/js/air-datepicker/locale/nl.js
+++ /dev/null
@@ -1,19 +0,0 @@
-"use strict";
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.default = void 0;
-var _default = {
- days: ['zondag', 'maandag', 'dinsdag', 'woensdag', 'donderdag', 'vrijdag', 'zaterdag'],
- daysShort: ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'],
- daysMin: ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'],
- months: ['Januari', 'Februari', 'Maart', 'April', 'Mei', 'Juni', 'Juli', 'Augustus', 'September', 'Oktober', 'November', 'December'],
- monthsShort: ['Jan', 'Feb', 'Mrt', 'Apr', 'Mei', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dec'],
- today: 'Vandaag',
- clear: 'Legen',
- dateFormat: 'dd-MM-yyyy',
- timeFormat: 'HH:mm',
- firstDay: 0
-};
-exports.default = _default;
\ No newline at end of file
diff --git a/src/ui/static/js/air-datepicker/locale/pl.d.ts b/src/ui/static/js/air-datepicker/locale/pl.d.ts
deleted file mode 100644
index a053d09e6..000000000
--- a/src/ui/static/js/air-datepicker/locale/pl.d.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-declare module 'air-datepicker/locale/pl' {
- import {AirDatepickerLocale} from 'air-datepicker';
- const pl: AirDatepickerLocale;
-
- export default pl;
-}
diff --git a/src/ui/static/js/air-datepicker/locale/pl.js b/src/ui/static/js/air-datepicker/locale/pl.js
deleted file mode 100644
index 6bef2c36d..000000000
--- a/src/ui/static/js/air-datepicker/locale/pl.js
+++ /dev/null
@@ -1,19 +0,0 @@
-"use strict";
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.default = void 0;
-var _default = {
- days: ['Niedziela', 'Poniedziałek', 'Wtorek', 'Środa', 'Czwartek', 'Piątek', 'Sobota'],
- daysShort: ['Nie', 'Pon', 'Wto', 'Śro', 'Czw', 'Pią', 'Sob'],
- daysMin: ['Nd', 'Pn', 'Wt', 'Śr', 'Czw', 'Pt', 'So'],
- months: ['Styczeń', 'Luty', 'Marzec', 'Kwiecień', 'Maj', 'Czerwiec', 'Lipiec', 'Sierpień', 'Wrzesień', 'Październik', 'Listopad', 'Grudzień'],
- monthsShort: ['Sty', 'Lut', 'Mar', 'Kwi', 'Maj', 'Cze', 'Lip', 'Sie', 'Wrz', 'Paź', 'Lis', 'Gru'],
- today: 'Dzisiaj',
- clear: 'Wyczyść',
- dateFormat: 'yyyy-MM-dd',
- timeFormat: 'hh:mm:aa',
- firstDay: 1
-};
-exports.default = _default;
\ No newline at end of file
diff --git a/src/ui/static/js/air-datepicker/locale/pt-BR.d.ts b/src/ui/static/js/air-datepicker/locale/pt-BR.d.ts
deleted file mode 100644
index 6c1c6baf4..000000000
--- a/src/ui/static/js/air-datepicker/locale/pt-BR.d.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-declare module 'air-datepicker/locale/pt-BR' {
- import {AirDatepickerLocale} from 'air-datepicker';
- const pt-BR: AirDatepickerLocale;
-
- export default pt-BR;
-}
diff --git a/src/ui/static/js/air-datepicker/locale/pt-BR.js b/src/ui/static/js/air-datepicker/locale/pt-BR.js
deleted file mode 100644
index 455b3a5aa..000000000
--- a/src/ui/static/js/air-datepicker/locale/pt-BR.js
+++ /dev/null
@@ -1,19 +0,0 @@
-"use strict";
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.default = void 0;
-var _default = {
- days: ['Domingo', 'Segunda', 'Terça', 'Quarta', 'Quinta', 'Sexta', 'Sábado'],
- daysShort: ['Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sab'],
- daysMin: ['Do', 'Se', 'Te', 'Qu', 'Qu', 'Se', 'Sa'],
- months: ['Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'],
- monthsShort: ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez'],
- today: 'Hoje',
- clear: 'Limpar',
- dateFormat: 'dd/MM/yyyy',
- timeFormat: 'HH:mm',
- firstDay: 0
-};
-exports.default = _default;
\ No newline at end of file
diff --git a/src/ui/static/js/air-datepicker/locale/pt.d.ts b/src/ui/static/js/air-datepicker/locale/pt.d.ts
deleted file mode 100644
index 8881f43e7..000000000
--- a/src/ui/static/js/air-datepicker/locale/pt.d.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-declare module 'air-datepicker/locale/pt' {
- import {AirDatepickerLocale} from 'air-datepicker';
- const pt: AirDatepickerLocale;
-
- export default pt;
-}
diff --git a/src/ui/static/js/air-datepicker/locale/pt.js b/src/ui/static/js/air-datepicker/locale/pt.js
deleted file mode 100644
index ff2c0cda6..000000000
--- a/src/ui/static/js/air-datepicker/locale/pt.js
+++ /dev/null
@@ -1,19 +0,0 @@
-"use strict";
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.default = void 0;
-var _default = {
- days: ['Domingo', 'Segunda', 'Terça', 'Quarta', 'Quinta', 'Sexta', 'Sábado'],
- daysShort: ['Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sab'],
- daysMin: ['Do', 'Se', 'Te', 'Qa', 'Qi', 'Sx', 'Sa'],
- months: ['Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'],
- monthsShort: ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez'],
- today: 'Hoje',
- clear: 'Limpar',
- dateFormat: 'dd/MM/yyyy',
- timeFormat: 'HH:mm',
- firstDay: 1
-};
-exports.default = _default;
\ No newline at end of file
diff --git a/src/ui/static/js/air-datepicker/locale/ro.d.ts b/src/ui/static/js/air-datepicker/locale/ro.d.ts
deleted file mode 100644
index 7bfde1a1f..000000000
--- a/src/ui/static/js/air-datepicker/locale/ro.d.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-declare module 'air-datepicker/locale/ro' {
- import {AirDatepickerLocale} from 'air-datepicker';
- const ro: AirDatepickerLocale;
-
- export default ro;
-}
diff --git a/src/ui/static/js/air-datepicker/locale/ro.js b/src/ui/static/js/air-datepicker/locale/ro.js
deleted file mode 100644
index a65920d0d..000000000
--- a/src/ui/static/js/air-datepicker/locale/ro.js
+++ /dev/null
@@ -1,19 +0,0 @@
-"use strict";
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.default = void 0;
-var _default = {
- days: ['Duminică', 'Luni', 'Marţi', 'Miercuri', 'Joi', 'Vineri', 'Sâmbătă'],
- daysShort: ['Dum', 'Lun', 'Mar', 'Mie', 'Joi', 'Vin', 'Sâm'],
- daysMin: ['D', 'L', 'Ma', 'Mi', 'J', 'V', 'S'],
- months: ['Ianuarie', 'Februarie', 'Martie', 'Aprilie', 'Mai', 'Iunie', 'Iulie', 'August', 'Septembrie', 'Octombrie', 'Noiembrie', 'Decembrie'],
- monthsShort: ['Ian', 'Feb', 'Mar', 'Apr', 'Mai', 'Iun', 'Iul', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec'],
- today: 'Azi',
- clear: 'Şterge',
- dateFormat: 'dd.MM.yyyy',
- timeFormat: 'HH:mm',
- firstDay: 1
-};
-exports.default = _default;
\ No newline at end of file
diff --git a/src/ui/static/js/air-datepicker/locale/ru.d.ts b/src/ui/static/js/air-datepicker/locale/ru.d.ts
deleted file mode 100644
index 0d2e8fe5c..000000000
--- a/src/ui/static/js/air-datepicker/locale/ru.d.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-declare module 'air-datepicker/locale/ru' {
- import {AirDatepickerLocale} from 'air-datepicker';
- const ru: AirDatepickerLocale;
-
- export default ru;
-}
diff --git a/src/ui/static/js/air-datepicker/locale/ru.js b/src/ui/static/js/air-datepicker/locale/ru.js
deleted file mode 100644
index 8910ba5bf..000000000
--- a/src/ui/static/js/air-datepicker/locale/ru.js
+++ /dev/null
@@ -1,19 +0,0 @@
-"use strict";
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.default = void 0;
-var _default = {
- days: ['Воскресенье', 'Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота'],
- daysShort: ['Вос', 'Пон', 'Вто', 'Сре', 'Чет', 'Пят', 'Суб'],
- daysMin: ['Вс', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб'],
- months: ['Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'],
- monthsShort: ['Янв', 'Фев', 'Мар', 'Апр', 'Май', 'Июн', 'Июл', 'Авг', 'Сен', 'Окт', 'Ноя', 'Дек'],
- today: 'Сегодня',
- clear: 'Очистить',
- dateFormat: 'dd.MM.yyyy',
- timeFormat: 'HH:mm',
- firstDay: 1
-};
-exports.default = _default;
\ No newline at end of file
diff --git a/src/ui/static/js/air-datepicker/locale/si.d.ts b/src/ui/static/js/air-datepicker/locale/si.d.ts
deleted file mode 100644
index 59b6c2b1a..000000000
--- a/src/ui/static/js/air-datepicker/locale/si.d.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-declare module 'air-datepicker/locale/si' {
- import {AirDatepickerLocale} from 'air-datepicker';
- const si: AirDatepickerLocale;
-
- export default si;
-}
diff --git a/src/ui/static/js/air-datepicker/locale/si.js b/src/ui/static/js/air-datepicker/locale/si.js
deleted file mode 100644
index fa5878642..000000000
--- a/src/ui/static/js/air-datepicker/locale/si.js
+++ /dev/null
@@ -1,19 +0,0 @@
-"use strict";
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.default = void 0;
-var _default = {
- days: ['ඉරිදා', 'සදුදා', 'අඟහරැවදා', 'බදාදා', 'බ්රහස්පතින්', 'සිකුරාදා', 'සෙනසුරාදා'],
- daysShort: ['ඉරිදා', 'සදුදා', 'අඟහ', 'බදාදා', 'බ්රහස්', 'සිකුරා', 'සෙන'],
- daysMin: ['ඉරි', 'සදු', 'අඟ', 'බදා', 'බ්රහ', 'සිකු', 'සෙ'],
- months: ['ජනවාරි', 'පෙබරවාරි', 'මාර්තු', 'අප්රේල්', 'මැයි', 'ජූනි', 'ජූලි', 'අගෝස්තු', 'සැප්තැම්බර්', 'ඔක්තෝබර්', 'නොවැම්බර්', 'දෙසැම්බර්'],
- monthsShort: ['ජන', 'පෙබ', 'මාර්', 'අප්රේල්', 'මැයි', 'ජූනි', 'ජූලි', 'අගෝ', 'සැප්', 'ඔක්', 'නොවැ', 'දෙසැ'],
- today: 'අද',
- clear: 'යලි සකසන්න',
- dateFormat: 'yyyy-mm-dd',
- timeFormat: 'hh:ii aa',
- firstDay: 1
-};
-exports.default = _default;
\ No newline at end of file
diff --git a/src/ui/static/js/air-datepicker/locale/sk.d.ts b/src/ui/static/js/air-datepicker/locale/sk.d.ts
deleted file mode 100644
index e0f2d0a28..000000000
--- a/src/ui/static/js/air-datepicker/locale/sk.d.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-declare module 'air-datepicker/locale/sk' {
- import {AirDatepickerLocale} from 'air-datepicker';
- const sk: AirDatepickerLocale;
-
- export default sk;
-}
diff --git a/src/ui/static/js/air-datepicker/locale/sk.js b/src/ui/static/js/air-datepicker/locale/sk.js
deleted file mode 100644
index b3146e3d9..000000000
--- a/src/ui/static/js/air-datepicker/locale/sk.js
+++ /dev/null
@@ -1,19 +0,0 @@
-"use strict";
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.default = void 0;
-var _default = {
- days: ['Nedeľa', 'Pondelok', 'Utorok', 'Streda', 'Štvrtok', 'Piatok', 'Sobota'],
- daysShort: ['Ned', 'Pon', 'Uto', 'Str', 'Štv', 'Pia', 'Sob'],
- daysMin: ['Ne', 'Po', 'Ut', 'St', 'Št', 'Pi', 'So'],
- months: ['Január', 'Február', 'Marec', 'Apríl', 'Máj', 'Jún', 'Júl', 'August', 'September', 'Október', 'November', 'December'],
- monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'Máj', 'Jún', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dec'],
- today: 'Dnes',
- clear: 'Vymazať',
- dateFormat: 'dd.MM.yyyy',
- timeFormat: 'HH:mm',
- firstDay: 1
-};
-exports.default = _default;
\ No newline at end of file
diff --git a/src/ui/static/js/air-datepicker/locale/sv.d.ts b/src/ui/static/js/air-datepicker/locale/sv.d.ts
deleted file mode 100644
index c8f20bd1b..000000000
--- a/src/ui/static/js/air-datepicker/locale/sv.d.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-declare module 'air-datepicker/locale/sv' {
- import {AirDatepickerLocale} from 'air-datepicker';
- const sv: AirDatepickerLocale;
-
- export default sv;
-}
diff --git a/src/ui/static/js/air-datepicker/locale/sv.js b/src/ui/static/js/air-datepicker/locale/sv.js
deleted file mode 100644
index 5d775c3d8..000000000
--- a/src/ui/static/js/air-datepicker/locale/sv.js
+++ /dev/null
@@ -1,19 +0,0 @@
-"use strict";
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.default = void 0;
-var _default = {
- days: ['Söndag', 'Måndag', 'Tisdag', 'Onsdag', 'Torsdag', 'Fredag', 'Lördag'],
- daysShort: ['Sön', 'Mån', 'Tis', 'Ons', 'Tor', 'Fre', 'Lör'],
- daysMin: ['Sö', 'Må', 'Ti', 'On', 'To', 'Fr', 'Lö'],
- months: ['Januari', 'Februari', 'Mars', 'April', 'Maj', 'Juni', 'Juli', 'Augusti', 'September', 'Oktober', 'November', 'December'],
- monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'Maj', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dec'],
- today: 'I dag',
- clear: 'Nollställ',
- dateFormat: 'yyyy-MM-dd',
- timeFormat: 'HH:mm',
- firstDay: 1
-};
-exports.default = _default;
\ No newline at end of file
diff --git a/src/ui/static/js/air-datepicker/locale/th.d.ts b/src/ui/static/js/air-datepicker/locale/th.d.ts
deleted file mode 100644
index 79f604363..000000000
--- a/src/ui/static/js/air-datepicker/locale/th.d.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-declare module 'air-datepicker/locale/th' {
- import {AirDatepickerLocale} from 'air-datepicker';
- const th: AirDatepickerLocale;
-
- export default th;
-}
diff --git a/src/ui/static/js/air-datepicker/locale/th.js b/src/ui/static/js/air-datepicker/locale/th.js
deleted file mode 100644
index bf46ca49c..000000000
--- a/src/ui/static/js/air-datepicker/locale/th.js
+++ /dev/null
@@ -1,19 +0,0 @@
-"use strict";
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.default = void 0;
-var _default = {
- days: ['วันอาทิตย์', 'วันจันทร์', 'วันอังคาร', 'วันพุธ', 'วันพฤหัสบดี', 'วันศุกร์', 'วันเสาร์'],
- daysShort: ['อา.', 'จ.', 'อ.', 'พ.', 'พฤ.', 'ศ.', 'ส.'],
- daysMin: ['อา.', 'จ.', 'อ.', 'พ.', 'พฤ.', 'ศ.', 'ส.'],
- months: ['มกราคม', 'กุมภาพันธ์', 'มีนาคม', 'เมษายน', 'พฤษภาคม', 'มิถุนายน', 'กรกฎาคม', 'สิงหาคม', 'กันยายน', 'ตุลาคม', 'พฤศจิกายน', 'ธันวาคม'],
- monthsShort: ['ม.ค.', 'ก.พ.', 'มี.ค.', 'เม.ย.', 'พ.ค.', 'มิ.ย.', 'ก.ค.', 'ส.ค.', 'ก.ย.', 'ต.ค.', 'พ.ย.', 'ธ.ค.'],
- today: 'วันนี้',
- clear: 'ล้าง',
- dateFormat: 'dd/MM/yyyy',
- timeFormat: 'HH:mm',
- firstDay: 0
-};
-exports.default = _default;
\ No newline at end of file
diff --git a/src/ui/static/js/air-datepicker/locale/tr.d.ts b/src/ui/static/js/air-datepicker/locale/tr.d.ts
deleted file mode 100644
index d5b63430f..000000000
--- a/src/ui/static/js/air-datepicker/locale/tr.d.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-declare module 'air-datepicker/locale/tr' {
- import {AirDatepickerLocale} from 'air-datepicker';
- const tr: AirDatepickerLocale;
-
- export default tr;
-}
diff --git a/src/ui/static/js/air-datepicker/locale/tr.js b/src/ui/static/js/air-datepicker/locale/tr.js
deleted file mode 100644
index 94939b0ab..000000000
--- a/src/ui/static/js/air-datepicker/locale/tr.js
+++ /dev/null
@@ -1,19 +0,0 @@
-"use strict";
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.default = void 0;
-var _default = {
- days: ['Pazar', 'Pazartesi', 'Salı', 'Çarşamba', 'Perşembe', 'Cuma', 'Cumartesi'],
- daysShort: ['Pzr', 'Pts', 'Sl', 'Çar', 'Per', 'Cum', 'Cts'],
- daysMin: ['Pa', 'Pt', 'Sl', 'Ça', 'Pe', 'Cu', 'Ct'],
- months: ['Ocak', 'Şubat', 'Mart', 'Nisan', 'Mayıs', 'Haziran', 'Temmuz', 'Ağustos', 'Eylül', 'Ekim', 'Kasım', 'Aralık'],
- monthsShort: ['Oca', 'Şbt', 'Mrt', 'Nsn', 'Mys', 'Hzr', 'Tmz', 'Ağt', 'Eyl', 'Ekm', 'Ksm', 'Arl'],
- today: 'Bugün',
- clear: 'Temizle',
- dateFormat: 'dd.MM.yyyy',
- timeFormat: 'hh:mm aa',
- firstDay: 1
-};
-exports.default = _default;
\ No newline at end of file
diff --git a/src/ui/static/js/air-datepicker/locale/uk.d.ts b/src/ui/static/js/air-datepicker/locale/uk.d.ts
deleted file mode 100644
index e09b47450..000000000
--- a/src/ui/static/js/air-datepicker/locale/uk.d.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-declare module 'air-datepicker/locale/uk' {
- import {AirDatepickerLocale} from 'air-datepicker';
- const uk: AirDatepickerLocale;
-
- export default uk;
-}
diff --git a/src/ui/static/js/air-datepicker/locale/uk.js b/src/ui/static/js/air-datepicker/locale/uk.js
deleted file mode 100644
index f71db2b99..000000000
--- a/src/ui/static/js/air-datepicker/locale/uk.js
+++ /dev/null
@@ -1,19 +0,0 @@
-"use strict";
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.default = void 0;
-var _default = {
- days: ['Неділя', 'Понеділок', 'Вівторок', 'Середа', 'Четвер', 'П’ятниця', 'Субота'],
- daysShort: ['Нед', 'Пнд', 'Вів', 'Срд', 'Чтв', 'Птн', 'Сбт'],
- daysMin: ['Нд', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб'],
- months: ['Січень', 'Лютий', 'Березень', 'Квітень', 'Травень', 'Червень', 'Липень', 'Серпень', 'Вересень', 'Жовтень', 'Листопад', 'Грудень'],
- monthsShort: ['Січ', 'Лют', 'Бер', 'Кві', 'Тра', 'Чер', 'Лип', 'Сер', 'Вер', 'Жов', 'Лис', 'Гру'],
- today: 'Сьогодні',
- clear: 'Очистити',
- dateFormat: 'dd.MM.yyyy',
- timeFormat: 'HH:mm',
- firstDay: 1
-};
-exports.default = _default;
\ No newline at end of file
diff --git a/src/ui/static/js/air-datepicker/locale/zh.d.ts b/src/ui/static/js/air-datepicker/locale/zh.d.ts
deleted file mode 100644
index 5e6be4f98..000000000
--- a/src/ui/static/js/air-datepicker/locale/zh.d.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-declare module 'air-datepicker/locale/zh' {
- import {AirDatepickerLocale} from 'air-datepicker';
- const zh: AirDatepickerLocale;
-
- export default zh;
-}
diff --git a/src/ui/static/js/air-datepicker/locale/zh.js b/src/ui/static/js/air-datepicker/locale/zh.js
deleted file mode 100644
index 4a2b48ba4..000000000
--- a/src/ui/static/js/air-datepicker/locale/zh.js
+++ /dev/null
@@ -1,19 +0,0 @@
-"use strict";
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.default = void 0;
-var _default = {
- days: ['周日', '周一', '周二', '周三', '周四', '周五', '周六'],
- daysShort: ['日', '一', '二', '三', '四', '五', '六'],
- daysMin: ['日', '一', '二', '三', '四', '五', '六'],
- months: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
- monthsShort: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
- today: '今天',
- clear: '清除',
- dateFormat: 'yyyy-MM-dd',
- timeFormat: 'HH:mm',
- firstDay: 1
-};
-exports.default = _default;
\ No newline at end of file
diff --git a/src/ui/static/js/datepicker/DateRangePicker.js b/src/ui/static/js/datepicker/DateRangePicker.js
new file mode 100644
index 000000000..0f5fa702e
--- /dev/null
+++ b/src/ui/static/js/datepicker/DateRangePicker.js
@@ -0,0 +1,210 @@
+import {registerListeners, unregisterListeners} from './lib/event.js';
+import {formatDate} from './lib/date-format.js';
+import Datepicker from './Datepicker.js';
+
+// filter out the config options inapproprite to pass to Datepicker
+function filterOptions(options) {
+ const newOpts = Object.assign({}, options);
+
+ delete newOpts.inputs;
+ delete newOpts.allowOneSidedRange;
+ delete newOpts.maxNumberOfDates; // to ensure each datepicker handles a single date
+
+ return newOpts;
+}
+
+function setupDatepicker(rangepicker, changeDateListener, el, options) {
+ registerListeners(rangepicker, [
+ [el, 'changeDate', changeDateListener],
+ ]);
+ new Datepicker(el, options, rangepicker);
+}
+
+function onChangeDate(rangepicker, ev) {
+ // to prevent both datepickers trigger the other side's update each other
+ if (rangepicker._updating) {
+ return;
+ }
+ rangepicker._updating = true;
+
+ const target = ev.target;
+ if (target.datepicker === undefined) {
+ return;
+ }
+
+ const datepickers = rangepicker.datepickers;
+ const setDateOptions = {render: false};
+ const changedSide = rangepicker.inputs.indexOf(target);
+ const otherSide = changedSide === 0 ? 1 : 0;
+ const changedDate = datepickers[changedSide].dates[0];
+ const otherDate = datepickers[otherSide].dates[0];
+
+ if (changedDate !== undefined && otherDate !== undefined) {
+ // if the start of the range > the end, swap them
+ if (changedSide === 0 && changedDate > otherDate) {
+ datepickers[0].setDate(otherDate, setDateOptions);
+ datepickers[1].setDate(changedDate, setDateOptions);
+ } else if (changedSide === 1 && changedDate < otherDate) {
+ datepickers[0].setDate(changedDate, setDateOptions);
+ datepickers[1].setDate(otherDate, setDateOptions);
+ }
+ } else if (!rangepicker.allowOneSidedRange) {
+ // to prevent the range from becoming one-sided, copy changed side's
+ // selection (no matter if it's empty) to the other side
+ if (changedDate !== undefined || otherDate !== undefined) {
+ setDateOptions.clear = true;
+ datepickers[otherSide].setDate(datepickers[changedSide].dates, setDateOptions);
+ }
+ }
+ datepickers[0].picker.update().render();
+ datepickers[1].picker.update().render();
+ delete rangepicker._updating;
+}
+
+/**
+ * Class representing a date range picker
+ */
+export default class DateRangePicker {
+ /**
+ * Create a date range picker
+ * @param {Element} element - element to bind a date range picker
+ * @param {Object} [options] - config options
+ */
+ constructor(element, options = {}) {
+ const inputs = Array.isArray(options.inputs)
+ ? options.inputs
+ : Array.from(element.querySelectorAll('input'));
+ if (inputs.length < 2) {
+ return;
+ }
+
+ element.rangepicker = this;
+ this.element = element;
+ this.inputs = inputs.slice(0, 2);
+ this.allowOneSidedRange = !!options.allowOneSidedRange;
+
+ const changeDateListener = onChangeDate.bind(null, this);
+ const cleanOptions = filterOptions(options);
+ // in order for initial date setup to work right when pcicLvel > 0,
+ // let Datepicker constructor add the instance to the rangepicker
+ const datepickers = [];
+ Object.defineProperty(this, 'datepickers', {
+ get() {
+ return datepickers;
+ },
+ });
+ setupDatepicker(this, changeDateListener, this.inputs[0], cleanOptions);
+ setupDatepicker(this, changeDateListener, this.inputs[1], cleanOptions);
+ Object.freeze(datepickers);
+ // normalize the range if inital dates are given
+ if (datepickers[0].dates.length > 0) {
+ onChangeDate(this, {target: this.inputs[0]});
+ } else if (datepickers[1].dates.length > 0) {
+ onChangeDate(this, {target: this.inputs[1]});
+ }
+ }
+
+ /**
+ * @type {Array} - selected date of the linked date pickers
+ */
+ get dates() {
+ return this.datepickers.length === 2
+ ? [
+ this.datepickers[0].dates[0],
+ this.datepickers[1].dates[0],
+ ]
+ : undefined;
+ }
+
+ /**
+ * Set new values to the config options
+ * @param {Object} options - config options to update
+ */
+ setOptions(options) {
+ this.allowOneSidedRange = !!options.allowOneSidedRange;
+
+ const cleanOptions = filterOptions(options);
+ this.datepickers[0].setOptions(cleanOptions);
+ this.datepickers[1].setOptions(cleanOptions);
+ }
+
+ /**
+ * Destroy the DateRangePicker instance
+ * @return {DateRangePicker} - the instance destroyed
+ */
+ destroy() {
+ this.datepickers[0].destroy();
+ this.datepickers[1].destroy();
+ unregisterListeners(this);
+ delete this.element.rangepicker;
+ }
+
+ /**
+ * Get the start and end dates of the date range
+ *
+ * The method returns Date objects by default. If format string is passed,
+ * it returns date strings formatted in given format.
+ * The result array always contains 2 items (start date/end date) and
+ * undefined is used for unselected side. (e.g. If none is selected,
+ * the result will be [undefined, undefined]. If only the end date is set
+ * when allowOneSidedRange config option is true, [undefined, endDate] will
+ * be returned.)
+ *
+ * @param {String} [format] - Format string to stringify the dates
+ * @return {Array} - Start and end dates
+ */
+ getDates(format = undefined) {
+ const callback = format
+ ? date => formatDate(date, format, this.datepickers[0].config.locale)
+ : date => new Date(date);
+
+ return this.dates.map(date => date === undefined ? date : callback(date));
+ }
+
+ /**
+ * Set the start and end dates of the date range
+ *
+ * The method calls datepicker.setDate() internally using each of the
+ * arguments in start→end order.
+ *
+ * When a clear: true option object is passed instead of a date, the method
+ * clears the date.
+ *
+ * If an invalid date, the same date as the current one or an option object
+ * without clear: true is passed, the method considers that argument as an
+ * "ineffective" argument because calling datepicker.setDate() with those
+ * values makes no changes to the date selection.
+ *
+ * When the allowOneSidedRange config option is false, passing {clear: true}
+ * to clear the range works only when it is done to the last effective
+ * argument (in other words, passed to rangeEnd or to rangeStart along with
+ * ineffective rangeEnd). This is because when the date range is changed,
+ * it gets normalized based on the last change at the end of the changing
+ * process.
+ *
+ * @param {Date|Number|String|Object} rangeStart - Start date of the range
+ * or {clear: true} to clear the date
+ * @param {Date|Number|String|Object} rangeEnd - End date of the range
+ * or {clear: true} to clear the date
+ */
+ setDates(rangeStart, rangeEnd) {
+ const [datepicker0, datepicker1] = this.datepickers;
+ const origDates = this.dates;
+
+ // If range normalization runs on every change, we can't set a new range
+ // that starts after the end of the current range correctly because the
+ // normalization process swaps start↔︎end right after setting the new start
+ // date. To prevent this, the normalization process needs to run once after
+ // both of the new dates are set.
+ this._updating = true;
+ datepicker0.setDate(rangeStart);
+ datepicker1.setDate(rangeEnd);
+ delete this._updating;
+
+ if (datepicker1.dates[0] !== origDates[1]) {
+ onChangeDate(this, {target: this.inputs[1]});
+ } else if (datepicker0.dates[0] !== origDates[0]) {
+ onChangeDate(this, {target: this.inputs[0]});
+ }
+ }
+}
diff --git a/src/ui/static/js/datepicker/Datepicker.js b/src/ui/static/js/datepicker/Datepicker.js
new file mode 100644
index 000000000..babffc06b
--- /dev/null
+++ b/src/ui/static/js/datepicker/Datepicker.js
@@ -0,0 +1,502 @@
+import {lastItemOf, stringToArray, isInRange} from './lib/utils.js';
+import {today, regularizeDate} from './lib/date.js';
+import {parseDate, formatDate} from './lib/date-format.js';
+import {isActiveElement} from './lib/dom.js';
+import {registerListeners, unregisterListeners} from './lib/event.js';
+import {locales} from './i18n/base-locales.js';
+import defaultOptions from './options/defaultOptions.js';
+import processOptions from './options/processOptions.js';
+import Picker from './picker/Picker.js';
+import {triggerDatepickerEvent} from './events/functions.js';
+import {onKeydown, onFocus, onMousedown, onClickInput, onPaste} from './events/inputFieldListeners.js';
+import {onClickOutside} from './events/otherListeners.js';
+
+function stringifyDates(dates, config) {
+ return dates
+ .map(dt => formatDate(dt, config.format, config.locale))
+ .join(config.dateDelimiter);
+}
+
+// parse input dates and create an array of time values for selection
+// returns undefined if there are no valid dates in inputDates
+// when origDates (current selection) is passed, the function works to mix
+// the input dates into the current selection
+function processInputDates(datepicker, inputDates, clear = false) {
+ // const {config, dates: origDates, rangepicker} = datepicker;
+ const {config, dates: origDates, rangeSideIndex} = datepicker;
+ if (inputDates.length === 0) {
+ // empty input is considered valid unless origiDates is passed
+ return clear ? [] : undefined;
+ }
+
+ // const rangeEnd = rangepicker && datepicker === rangepicker.datepickers[1];
+ let newDates = inputDates.reduce((dates, dt) => {
+ let date = parseDate(dt, config.format, config.locale);
+ if (date === undefined) {
+ return dates;
+ }
+ // adjust to 1st of the month/Jan 1st of the year
+ // or to the last day of the monh/Dec 31st of the year if the datepicker
+ // is the range-end picker of a rangepicker
+ date = regularizeDate(date, config.pickLevel, rangeSideIndex);
+ if (
+ isInRange(date, config.minDate, config.maxDate)
+ && !dates.includes(date)
+ && !config.datesDisabled.includes(date)
+ && (config.pickLevel > 0 || !config.daysOfWeekDisabled.includes(new Date(date).getDay()))
+ ) {
+ dates.push(date);
+ }
+ return dates;
+ }, []);
+ if (newDates.length === 0) {
+ return;
+ }
+ if (config.multidate && !clear) {
+ // get the synmetric difference between origDates and newDates
+ newDates = newDates.reduce((dates, date) => {
+ if (!origDates.includes(date)) {
+ dates.push(date);
+ }
+ return dates;
+ }, origDates.filter(date => !newDates.includes(date)));
+ }
+ // do length check always because user can input multiple dates regardless of the mode
+ return config.maxNumberOfDates && newDates.length > config.maxNumberOfDates
+ ? newDates.slice(config.maxNumberOfDates * -1)
+ : newDates;
+}
+
+// refresh the UI elements
+// modes: 1: input only, 2, picker only, 3 both
+function refreshUI(datepicker, mode = 3, quickRender = true) {
+ const {config, picker, inputField} = datepicker;
+ if (mode & 2) {
+ const newView = picker.active ? config.pickLevel : config.startView;
+ picker.update().changeView(newView).render(quickRender);
+ }
+ if (mode & 1 && inputField) {
+ inputField.value = stringifyDates(datepicker.dates, config);
+ }
+}
+
+function setDate(datepicker, inputDates, options) {
+ let {clear, render, autohide, revert} = options;
+ if (render === undefined) {
+ render = true;
+ }
+ if (!render) {
+ autohide = false;
+ } else if (autohide === undefined) {
+ autohide = datepicker.config.autohide;
+ }
+
+ const newDates = processInputDates(datepicker, inputDates, clear);
+ if (!newDates && !revert) {
+ return;
+ }
+ if (newDates && newDates.toString() !== datepicker.dates.toString()) {
+ datepicker.dates = newDates;
+ refreshUI(datepicker, render ? 3 : 1);
+ triggerDatepickerEvent(datepicker, 'changeDate');
+ } else {
+ refreshUI(datepicker, 1);
+ }
+
+ if (autohide) {
+ datepicker.hide();
+ }
+}
+
+/**
+ * Class representing a date picker
+ */
+export default class Datepicker {
+ /**
+ * Create a date picker
+ * @param {Element} element - element to bind a date picker
+ * @param {Object} [options] - config options
+ * @param {DateRangePicker} [rangepicker] - DateRangePicker instance the
+ * date picker belongs to. Use this only when creating date picker as a part
+ * of date range picker
+ */
+ constructor(element, options = {}, rangepicker = undefined) {
+ element.datepicker = this;
+ this.element = element;
+
+ const config = this.config = Object.assign({
+ buttonClass: (options.buttonClass && String(options.buttonClass)) || 'button',
+ container: null,
+ defaultViewDate: today(),
+ maxDate: undefined,
+ minDate: undefined,
+ }, processOptions(defaultOptions, this));
+ // configure by type
+ const inline = this.inline = element.tagName !== 'INPUT';
+ let inputField;
+ if (inline) {
+ config.container = element;
+ } else {
+ if (options.container) {
+ // omit string type check because it doesn't guarantee to avoid errors
+ // (invalid selector string causes abend with sytax error)
+ config.container = options.container instanceof HTMLElement
+ ? options.container
+ : document.querySelector(options.container);
+ }
+ inputField = this.inputField = element;
+ inputField.classList.add('datepicker-input');
+ }
+ if (rangepicker) {
+ // check validiry
+ const index = rangepicker.inputs.indexOf(inputField);
+ const datepickers = rangepicker.datepickers;
+ if (index < 0 || index > 1 || !Array.isArray(datepickers)) {
+ throw Error('Invalid rangepicker object.');
+ }
+ // attach itaelf to the rangepicker here so that processInputDates() can
+ // determine if this is the range-end picker of the rangepicker while
+ // setting inital values when pickLevel > 0
+ datepickers[index] = this;
+ // add getter for rangepicker
+ Object.defineProperty(this, 'rangepicker', {
+ get() {
+ return rangepicker;
+ },
+ });
+ Object.defineProperty(this, 'rangeSideIndex', {
+ get() {
+ return index;
+ },
+ });
+ }
+
+ // set up config
+ this._options = options;
+ Object.assign(config, processOptions(options, this));
+
+ // set initial dates
+ let initialDates;
+ if (inline) {
+ initialDates = stringToArray(element.dataset.date, config.dateDelimiter);
+ delete element.dataset.date;
+ } else {
+ initialDates = stringToArray(inputField.value, config.dateDelimiter);
+ }
+ this.dates = [];
+ // process initial value
+ const inputDateValues = processInputDates(this, initialDates);
+ if (inputDateValues && inputDateValues.length > 0) {
+ this.dates = inputDateValues;
+ }
+ if (inputField) {
+ inputField.value = stringifyDates(this.dates, config);
+ }
+
+ const picker = this.picker = new Picker(this);
+
+ if (inline) {
+ this.show();
+ } else {
+ // set up event listeners in other modes
+ const onMousedownDocument = onClickOutside.bind(null, this);
+ const listeners = [
+ [inputField, 'keydown', onKeydown.bind(null, this)],
+ [inputField, 'focus', onFocus.bind(null, this)],
+ [inputField, 'mousedown', onMousedown.bind(null, this)],
+ [inputField, 'click', onClickInput.bind(null, this)],
+ [inputField, 'paste', onPaste.bind(null, this)],
+ [document, 'mousedown', onMousedownDocument],
+ [document, 'touchstart', onMousedownDocument],
+ [window, 'resize', picker.place.bind(picker)]
+ ];
+ registerListeners(this, listeners);
+ }
+ }
+
+ /**
+ * Format Date object or time value in given format and language
+ * @param {Date|Number} date - date or time value to format
+ * @param {String|Object} format - format string or object that contains
+ * toDisplay() custom formatter, whose signature is
+ * - args:
+ * - date: {Date} - Date instance of the date passed to the method
+ * - format: {Object} - the format object passed to the method
+ * - locale: {Object} - locale for the language specified by `lang`
+ * - return:
+ * {String} formatted date
+ * @param {String} [lang=en] - language code for the locale to use
+ * @return {String} formatted date
+ */
+ static formatDate(date, format, lang) {
+ return formatDate(date, format, lang && locales[lang] || locales.en);
+ }
+
+ /**
+ * Parse date string
+ * @param {String|Date|Number} dateStr - date string, Date object or time
+ * value to parse
+ * @param {String|Object} format - format string or object that contains
+ * toValue() custom parser, whose signature is
+ * - args:
+ * - dateStr: {String|Date|Number} - the dateStr passed to the method
+ * - format: {Object} - the format object passed to the method
+ * - locale: {Object} - locale for the language specified by `lang`
+ * - return:
+ * {Date|Number} parsed date or its time value
+ * @param {String} [lang=en] - language code for the locale to use
+ * @return {Number} time value of parsed date
+ */
+ static parseDate(dateStr, format, lang) {
+ return parseDate(dateStr, format, lang && locales[lang] || locales.en);
+ }
+
+ /**
+ * @type {Object} - Installed locales in `[languageCode]: localeObject` format
+ * en`:_English (US)_ is pre-installed.
+ */
+ static get locales() {
+ return locales;
+ }
+
+ /**
+ * @type {Boolean} - Whether the picker element is shown. `true` whne shown
+ */
+ get active() {
+ return !!(this.picker && this.picker.active);
+ }
+
+ /**
+ * @type {HTMLDivElement} - DOM object of picker element
+ */
+ get pickerElement() {
+ return this.picker ? this.picker.element : undefined;
+ }
+
+ /**
+ * Set new values to the config options
+ * @param {Object} options - config options to update
+ */
+ setOptions(options) {
+ const picker = this.picker;
+ const newOptions = processOptions(options, this);
+ Object.assign(this._options, options);
+ Object.assign(this.config, newOptions);
+ picker.setOptions(newOptions);
+
+ refreshUI(this, 3);
+ }
+
+ /**
+ * Show the picker element
+ */
+ show() {
+ if (this.inputField) {
+ if (this.inputField.disabled) {
+ return;
+ }
+ if (!isActiveElement(this.inputField) && !this.config.disableTouchKeyboard) {
+ this._showing = true;
+ this.inputField.focus();
+ delete this._showing;
+ }
+ }
+ this.picker.show();
+ }
+
+ /**
+ * Hide the picker element
+ * Not available on inline picker
+ */
+ hide() {
+ if (this.inline) {
+ return;
+ }
+ this.picker.hide();
+ this.picker.update().changeView(this.config.startView).render();
+ }
+
+ /**
+ * Destroy the Datepicker instance
+ * @return {Detepicker} - the instance destroyed
+ */
+ destroy() {
+ this.hide();
+ unregisterListeners(this);
+ this.picker.detach();
+ if (!this.inline) {
+ this.inputField.classList.remove('datepicker-input');
+ }
+ delete this.element.datepicker;
+ return this;
+ }
+
+ /**
+ * Get the selected date(s)
+ *
+ * The method returns a Date object of selected date by default, and returns
+ * an array of selected dates in multidate mode. If format string is passed,
+ * it returns date string(s) formatted in given format.
+ *
+ * @param {String} [format] - Format string to stringify the date(s)
+ * @return {Date|String|Date[]|String[]} - selected date(s), or if none is
+ * selected, empty array in multidate mode and untitled in sigledate mode
+ */
+ getDate(format = undefined) {
+ const callback = format
+ ? date => formatDate(date, format, this.config.locale)
+ : date => new Date(date);
+
+ if (this.config.multidate) {
+ return this.dates.map(callback);
+ }
+ if (this.dates.length > 0) {
+ return callback(this.dates[0]);
+ }
+ }
+
+ /**
+ * Set selected date(s)
+ *
+ * In multidate mode, you can pass multiple dates as a series of arguments
+ * or an array. (Since each date is parsed individually, the type of the
+ * dates doesn't have to be the same.)
+ * The given dates are used to toggle the select status of each date. The
+ * number of selected dates is kept from exceeding the length set to
+ * maxNumberOfDates.
+ *
+ * With clear: true option, the method can be used to clear the selection
+ * and to replace the selection instead of toggling in multidate mode.
+ * If the option is passed with no date arguments or an empty dates array,
+ * it works as "clear" (clear the selection then set nothing), and if the
+ * option is passed with new dates to select, it works as "replace" (clear
+ * the selection then set the given dates)
+ *
+ * When render: false option is used, the method omits re-rendering the
+ * picker element. In this case, you need to call refresh() method later in
+ * order for the picker element to reflect the changes. The input field is
+ * refreshed always regardless of this option.
+ *
+ * When invalid (unparsable, repeated, disabled or out-of-range) dates are
+ * passed, the method ignores them and applies only valid ones. In the case
+ * that all the given dates are invalid, which is distinguished from passing
+ * no dates, the method considers it as an error and leaves the selection
+ * untouched. (The input field also remains untouched unless revert: true
+ * option is used.)
+ *
+ * @param {...(Date|Number|String)|Array} [dates] - Date strings, Date
+ * objects, time values or mix of those for new selection
+ * @param {Object} [options] - function options
+ * - clear: {boolean} - Whether to clear the existing selection
+ * defualt: false
+ * - render: {boolean} - Whether to re-render the picker element
+ * default: true
+ * - autohide: {boolean} - Whether to hide the picker element after re-render
+ * Ignored when used with render: false
+ * default: config.autohide
+ * - revert: {boolean} - Whether to refresh the input field when all the
+ * passed dates are invalid
+ * default: false
+ */
+ setDate(...args) {
+ const dates = [...args];
+ const opts = {};
+ const lastArg = lastItemOf(args);
+ if (
+ typeof lastArg === 'object'
+ && !Array.isArray(lastArg)
+ && !(lastArg instanceof Date)
+ && lastArg
+ ) {
+ Object.assign(opts, dates.pop());
+ }
+
+ const inputDates = Array.isArray(dates[0]) ? dates[0] : dates;
+ setDate(this, inputDates, opts);
+ }
+
+ /**
+ * Update the selected date(s) with input field's value
+ * Not available on inline picker
+ *
+ * The input field will be refreshed with properly formatted date string.
+ *
+ * In the case that all the entered dates are invalid (unparsable, repeated,
+ * disabled or out-of-range), whixh is distinguished from empty input field,
+ * the method leaves the input field untouched as well as the selection by
+ * default. If revert: true option is used in this case, the input field is
+ * refreshed with the existing selection.
+ *
+ * @param {Object} [options] - function options
+ * - autohide: {boolean} - whether to hide the picker element after refresh
+ * default: false
+ * - revert: {boolean} - Whether to refresh the input field when all the
+ * passed dates are invalid
+ * default: false
+ */
+ update(options = undefined) {
+ if (this.inline) {
+ return;
+ }
+
+ const opts = Object.assign(options || {}, {clear: true, render: true});
+ const inputDates = stringToArray(this.inputField.value, this.config.dateDelimiter);
+ setDate(this, inputDates, opts);
+ }
+
+ /**
+ * Refresh the picker element and the associated input field
+ * @param {String} [target] - target item when refreshing one item only
+ * 'picker' or 'input'
+ * @param {Boolean} [forceRender] - whether to re-render the picker element
+ * regardless of its state instead of optimized refresh
+ */
+ refresh(target = undefined, forceRender = false) {
+ if (target && typeof target !== 'string') {
+ forceRender = target;
+ target = undefined;
+ }
+
+ let mode;
+ if (target === 'picker') {
+ mode = 2;
+ } else if (target === 'input') {
+ mode = 1;
+ } else {
+ mode = 3;
+ }
+ refreshUI(this, mode, !forceRender);
+ }
+
+ /**
+ * Enter edit mode
+ * Not available on inline picker or when the picker element is hidden
+ */
+ enterEditMode() {
+ if (this.inline || !this.picker.active || this.editMode) {
+ return;
+ }
+ this.editMode = true;
+ this.inputField.classList.add('in-edit');
+ }
+
+ /**
+ * Exit from edit mode
+ * Not available on inline picker
+ * @param {Object} [options] - function options
+ * - update: {boolean} - whether to call update() after exiting
+ * If false, input field is revert to the existing selection
+ * default: false
+ */
+ exitEditMode(options = undefined) {
+ if (this.inline || !this.editMode) {
+ return;
+ }
+ const opts = Object.assign({update: false}, options);
+ delete this.editMode;
+ this.inputField.classList.remove('in-edit');
+ if (opts.update) {
+ this.update(opts);
+ }
+ }
+}
diff --git a/src/ui/static/js/datepicker/datepicker-full.js b/src/ui/static/js/datepicker/datepicker-full.js
new file mode 100644
index 000000000..b054896ac
--- /dev/null
+++ b/src/ui/static/js/datepicker/datepicker-full.js
@@ -0,0 +1,5 @@
+import Datepicker from './Datepicker.js';
+import DateRangePicker from './DateRangePicker.js';
+
+window.Datepicker = Datepicker;
+window.DateRangePicker = DateRangePicker;
diff --git a/src/ui/static/js/datepicker/datepicker-full.min.js b/src/ui/static/js/datepicker/datepicker-full.min.js
new file mode 100644
index 000000000..dab79456b
--- /dev/null
+++ b/src/ui/static/js/datepicker/datepicker-full.min.js
@@ -0,0 +1 @@
+!function(){"use strict";function e(e,t){return Object.prototype.hasOwnProperty.call(e,t)}function t(e){return e[e.length-1]}function i(e,...t){return t.forEach((t=>{e.includes(t)||e.push(t)})),e}function s(e,t){return e?e.split(t):[]}function n(e,t,i){return(void 0===t||e>=t)&&(void 0===i||e<=i)}function a(e,t,i){return ei?i:e}function r(e,t,i={},s=0,n=""){n+=`<${Object.keys(i).reduce(((e,t)=>{let n=i[t];return"function"==typeof n&&(n=n(s)),`${e} ${t}="${n}"`}),e)}>${e}>`;const a=s+1;return a\s+/g,">").replace(/\s+,"<")}function o(e){return new Date(e).setHours(0,0,0,0)}function c(){return(new Date).setHours(0,0,0,0)}function l(...e){switch(e.length){case 0:return c();case 1:return o(e[0])}const t=new Date(0);return t.setFullYear(...e),t.setHours(0,0,0,0)}function h(e,t){const i=new Date(e);return i.setDate(i.getDate()+t)}function u(e,t){const i=new Date(e),s=i.getMonth()+t;let n=s%12;n<0&&(n+=12);const a=i.setMonth(s);return i.getMonth()!==n?i.setDate(0):a}function f(e,t){const i=new Date(e),s=i.getMonth(),n=i.setFullYear(i.getFullYear()+t);return 1===s&&2===i.getMonth()?i.setDate(0):n}function p(e,t){return(e-t+7)%7}function g(e,t,i=0){const s=new Date(e).getDay();return h(e,p(t,i)-p(s,i))}function m(e,t){const i=new Date(e).getFullYear();return Math.floor(i/t)*t}function w(e,t,i){if(1!==t&&2!==t)return e;const s=new Date(e);return 1===t?i?s.setMonth(s.getMonth()+1,0):s.setDate(1):i?s.setFullYear(s.getFullYear()+1,0,0):s.setMonth(0,1),s.setHours(0,0,0,0)}const D=/dd?|DD?|mm?|MM?|yy?(?:yy)?/,y=/[\s!-/:-@[-`{-~年月日]+/;let v={};const b={y:(e,t)=>new Date(e).setFullYear(parseInt(t,10)),m(e,t,i){const s=new Date(e);let n=parseInt(t,10)-1;if(isNaN(n)){if(!t)return NaN;const e=t.toLowerCase(),s=t=>t.toLowerCase().startsWith(e);if(n=i.monthsShort.findIndex(s),n<0&&(n=i.months.findIndex(s)),n<0)return NaN}return s.setMonth(n),s.getMonth()!==x(n)?s.setDate(0):s.getTime()},d:(e,t)=>new Date(e).setDate(parseInt(t,10))},k={d:e=>e.getDate(),dd:e=>M(e.getDate(),2),D:(e,t)=>t.daysShort[e.getDay()],DD:(e,t)=>t.days[e.getDay()],m:e=>e.getMonth()+1,mm:e=>M(e.getMonth()+1,2),M:(e,t)=>t.monthsShort[e.getMonth()],MM:(e,t)=>t.months[e.getMonth()],y:e=>e.getFullYear(),yy:e=>M(e.getFullYear(),2).slice(-2),yyyy:e=>M(e.getFullYear(),4)};function x(e){return e>-1?e%12:x(e+12)}function M(e,t){return e.toString().padStart(t,"0")}function S(e){if("string"!=typeof e)throw new Error("Invalid date format.");if(e in v)return v[e];const i=e.split(D),s=e.match(new RegExp(D,"g"));if(0===i.length||!s)throw new Error("Invalid date format.");const n=s.map((e=>k[e])),a=Object.keys(b).reduce(((e,t)=>(s.find((e=>"D"!==e[0]&&e[0].toLowerCase()===t))&&e.push(t),e)),[]);return v[e]={parser(e,t){const i=e.split(y).reduce(((e,t,i)=>{if(t.length>0&&s[i]){const n=s[i][0];"M"===n?e.m=t:"D"!==n&&(e[n]=t)}return e}),{});return a.reduce(((e,s)=>{const n=b[s](e,i[s],t);return isNaN(n)?e:n}),c())},formatter:(e,s)=>n.reduce(((t,n,a)=>t+`${i[a]}${n(e,s)}`),"")+t(i)}}function O(e,t,i){if(e instanceof Date||"number"==typeof e){const t=o(e);return isNaN(t)?void 0:t}if(e){if("today"===e)return c();if(t&&t.toValue){const s=t.toValue(e,t,i);return isNaN(s)?void 0:o(s)}return S(t).parser(e,i)}}function C(e,t,i){if(isNaN(e)||!e&&0!==e)return"";const s="number"==typeof e?new Date(e):e;return t.toDisplay?t.toDisplay(s,t,i):S(t).formatter(s,i)}const E=document.createRange();function F(e){return E.createContextualFragment(e)}function V(e){return e.parentElement||(e.parentNode instanceof ShadowRoot?e.parentNode.host:void 0)}function N(e){return e.getRootNode().activeElement===e}function L(e){"none"!==e.style.display&&(e.style.display&&(e.dataset.styleDisplay=e.style.display),e.style.display="none")}function B(e){"none"===e.style.display&&(e.dataset.styleDisplay?(e.style.display=e.dataset.styleDisplay,delete e.dataset.styleDisplay):e.style.display="")}function A(e){e.firstChild&&(e.removeChild(e.firstChild),A(e))}const Y=new WeakMap,{addEventListener:W,removeEventListener:H}=EventTarget.prototype;function j(e,t){let i=Y.get(e);i||(i=[],Y.set(e,i)),t.forEach((e=>{W.call(...e),i.push(e)}))}function T(e){let t=Y.get(e);t&&(t.forEach((e=>{H.call(...e)})),Y.delete(e))}if(!Event.prototype.composedPath){const e=(t,i=[])=>{let s;return i.push(t),t.parentNode?s=t.parentNode:t.host?s=t.host:t.defaultView&&(s=t.defaultView),s?e(s,i):i};Event.prototype.composedPath=function(){return e(this.target)}}function _(e,t,i){const[s,...n]=e;return t(s)?s:s!==i&&"HTML"!==s.tagName&&0!==n.length?_(n,t,i):void 0}function K(e,t){const i="function"==typeof t?t:e=>e instanceof Element&&e.matches(t);return _(e.composedPath(),i,e.currentTarget)}const $={en:{days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],today:"Today",clear:"Clear",titleFormat:"MM y"}},R={autohide:!1,beforeShowDay:null,beforeShowDecade:null,beforeShowMonth:null,beforeShowYear:null,calendarWeeks:!1,clearBtn:!1,dateDelimiter:",",datesDisabled:[],daysOfWeekDisabled:[],daysOfWeekHighlighted:[],defaultViewDate:void 0,disableTouchKeyboard:!1,format:"mm/dd/yyyy",language:"en",maxDate:null,maxNumberOfDates:1,maxView:3,minDate:null,nextArrow:"»",orientation:"auto",pickLevel:0,prevArrow:"«",showDaysOfWeek:!0,showOnClick:!0,showOnFocus:!0,startView:0,title:"",todayBtn:!1,todayBtnMode:0,todayHighlight:!1,updateOnBlur:!0,weekStart:0},{language:I,format:P,weekStart:q}=R;function J(e,t){return e.length<6&&t>=0&&t<7?i(e,t):e}function U(e){return(e+6)%7}function z(e,t,i,s){const n=O(e,t,i);return void 0!==n?n:s}function X(e,t,i=3){const s=parseInt(e,10);return s>=0&&s<=i?s:t}function G(t,s){const n=Object.assign({},t),a={},r=s.constructor.locales,d=s.rangeSideIndex;let{format:o,language:c,locale:h,maxDate:u,maxView:f,minDate:p,pickLevel:g,startView:m,weekStart:y}=s.config||{};if(n.language){let e;if(n.language!==c&&(r[n.language]?e=n.language:(e=n.language.split("-")[0],void 0===r[e]&&(e=!1))),delete n.language,e){c=a.language=e;const t=h||r[I];h=Object.assign({format:P,weekStart:q},r[I]),c!==I&&Object.assign(h,r[c]),a.locale=h,o===t.format&&(o=a.format=h.format),y===t.weekStart&&(y=a.weekStart=h.weekStart,a.weekEnd=U(h.weekStart))}}if(n.format){const e="function"==typeof n.format.toDisplay,t="function"==typeof n.format.toValue,i=D.test(n.format);(e&&t||i)&&(o=a.format=n.format),delete n.format}let v=g;void 0!==n.pickLevel&&(v=X(n.pickLevel,2),delete n.pickLevel),v!==g&&(v>g&&(void 0===n.minDate&&(n.minDate=p),void 0===n.maxDate&&(n.maxDate=u)),n.datesDisabled||(n.datesDisabled=[]),g=a.pickLevel=v);let b=p,k=u;if(void 0!==n.minDate){const e=l(0,0,1);b=null===n.minDate?e:z(n.minDate,o,h,b),b!==e&&(b=w(b,g,!1)),delete n.minDate}if(void 0!==n.maxDate&&(k=null===n.maxDate?void 0:z(n.maxDate,o,h,k),void 0!==k&&(k=w(k,g,!0)),delete n.maxDate),k{const s=O(t,o,h);return void 0!==s?i(e,w(s,g,d)):e}),[]),delete n.datesDisabled),void 0!==n.defaultViewDate){const e=O(n.defaultViewDate,o,h);void 0!==e&&(a.defaultViewDate=e),delete n.defaultViewDate}if(void 0!==n.weekStart){const e=Number(n.weekStart)%7;isNaN(e)||(y=a.weekStart=e,a.weekEnd=U(e)),delete n.weekStart}if(n.daysOfWeekDisabled&&(a.daysOfWeekDisabled=n.daysOfWeekDisabled.reduce(J,[]),delete n.daysOfWeekDisabled),n.daysOfWeekHighlighted&&(a.daysOfWeekHighlighted=n.daysOfWeekHighlighted.reduce(J,[]),delete n.daysOfWeekHighlighted),void 0!==n.maxNumberOfDates){const e=parseInt(n.maxNumberOfDates,10);e>=0&&(a.maxNumberOfDates=e,a.multidate=1!==e),delete n.maxNumberOfDates}n.dateDelimiter&&(a.dateDelimiter=String(n.dateDelimiter),delete n.dateDelimiter);let x=f;void 0!==n.maxView&&(x=X(n.maxView,f),delete n.maxView),x=g>x?g:x,x!==f&&(f=a.maxView=x);let M=m;if(void 0!==n.startView&&(M=X(n.startView,M),delete n.startView),Mf&&(M=f),M!==m&&(a.startView=M),n.prevArrow){const e=F(n.prevArrow);e.childNodes.length>0&&(a.prevArrow=e.childNodes),delete n.prevArrow}if(n.nextArrow){const e=F(n.nextArrow);e.childNodes.length>0&&(a.nextArrow=e.childNodes),delete n.nextArrow}if(void 0!==n.disableTouchKeyboard&&(a.disableTouchKeyboard="ontouchstart"in document&&!!n.disableTouchKeyboard,delete n.disableTouchKeyboard),n.orientation){const e=n.orientation.toLowerCase().split(/\s+/g);a.orientation={x:e.find((e=>"left"===e||"right"===e))||"auto",y:e.find((e=>"top"===e||"bottom"===e))||"auto"},delete n.orientation}if(void 0!==n.todayBtnMode){switch(n.todayBtnMode){case 0:case 1:a.todayBtnMode=n.todayBtnMode}delete n.todayBtnMode}return Object.keys(n).forEach((t=>{void 0!==n[t]&&e(R,t)&&(a[t]=n[t])})),a}const Q=d(''),Z=d(`\n
${r("span",7,{class:"dow"})}
\n
${r("span",42)}
\n
`),ee=d(`\n
\n
${r("span",6,{class:"week"})}
\n
`);class te{constructor(e,t){Object.assign(this,t,{picker:e,element:F('').firstChild,selected:[]}),this.init(this.picker.datepicker.config)}init(e){void 0!==e.pickLevel&&(this.isMinView=this.id===e.pickLevel),this.setOptions(e),this.updateFocus(),this.updateSelection()}performBeforeHook(e,t,s){let n=this.beforeShow(new Date(s));switch(typeof n){case"boolean":n={enabled:n};break;case"string":n={classes:n}}if(n){if(!1===n.enabled&&(e.classList.add("disabled"),i(this.disabled,t)),n.classes){const s=n.classes.split(/\s+/);e.classList.add(...s),s.includes("disabled")&&i(this.disabled,t)}n.content&&function(e,t){A(e),t instanceof DocumentFragment?e.appendChild(t):"string"==typeof t?e.appendChild(F(t)):"function"==typeof t.forEach&&t.forEach((t=>{e.appendChild(t)}))}(e,n.content)}}}class ie extends te{constructor(e){super(e,{id:0,name:"days",cellClass:"day"})}init(e,t=!0){if(t){const e=F(Z).firstChild;this.dow=e.firstChild,this.grid=e.lastChild,this.element.appendChild(e)}super.init(e)}setOptions(t){let i;if(e(t,"minDate")&&(this.minDate=t.minDate),e(t,"maxDate")&&(this.maxDate=t.maxDate),t.datesDisabled&&(this.datesDisabled=t.datesDisabled),t.daysOfWeekDisabled&&(this.daysOfWeekDisabled=t.daysOfWeekDisabled,i=!0),t.daysOfWeekHighlighted&&(this.daysOfWeekHighlighted=t.daysOfWeekHighlighted),void 0!==t.todayHighlight&&(this.todayHighlight=t.todayHighlight),void 0!==t.weekStart&&(this.weekStart=t.weekStart,this.weekEnd=t.weekEnd,i=!0),t.locale){const e=this.locale=t.locale;this.dayNames=e.daysMin,this.switchLabelFormat=e.titleFormat,i=!0}if(void 0!==t.beforeShowDay&&(this.beforeShow="function"==typeof t.beforeShowDay?t.beforeShowDay:void 0),void 0!==t.calendarWeeks)if(t.calendarWeeks&&!this.calendarWeeks){const e=F(ee).firstChild;this.calendarWeeks={element:e,dow:e.firstChild,weeks:e.lastChild},this.element.insertBefore(e,this.element.firstChild)}else this.calendarWeeks&&!t.calendarWeeks&&(this.element.removeChild(this.calendarWeeks.element),this.calendarWeeks=null);void 0!==t.showDaysOfWeek&&(t.showDaysOfWeek?(B(this.dow),this.calendarWeeks&&B(this.calendarWeeks.dow)):(L(this.dow),this.calendarWeeks&&L(this.calendarWeeks.dow))),i&&Array.from(this.dow.children).forEach(((e,t)=>{const i=(this.weekStart+t)%7;e.textContent=this.dayNames[i],e.className=this.daysOfWeekDisabled.includes(i)?"dow disabled":"dow"}))}updateFocus(){const e=new Date(this.picker.viewDate),t=e.getFullYear(),i=e.getMonth(),s=l(t,i,1),n=g(s,this.weekStart,this.weekStart);this.first=s,this.last=l(t,i+1,0),this.start=n,this.focused=this.picker.viewDate}updateSelection(){const{dates:e,rangepicker:t}=this.picker.datepicker;this.selected=e,t&&(this.range=t.dates)}render(){this.today=this.todayHighlight?c():void 0,this.disabled=[...this.datesDisabled];const e=C(this.focused,this.switchLabelFormat,this.locale);if(this.picker.setViewSwitchLabel(e),this.picker.setPrevBtnDisabled(this.first<=this.minDate),this.picker.setNextBtnDisabled(this.last>=this.maxDate),this.calendarWeeks){const e=g(this.first,1,1);Array.from(this.calendarWeeks.weeks.children).forEach(((t,i)=>{t.textContent=function(e){const t=g(e,4,1),i=g(new Date(t).setMonth(0,4),4,1);return Math.round((t-i)/6048e5)+1}(h(e,7*i))}))}Array.from(this.grid.children).forEach(((e,t)=>{const s=e.classList,n=h(this.start,t),a=new Date(n),r=a.getDay();if(e.className=`datepicker-cell ${this.cellClass}`,e.dataset.date=n,e.textContent=a.getDate(),nthis.last&&s.add("next"),this.today===n&&s.add("today"),(nthis.maxDate||this.disabled.includes(n))&&s.add("disabled"),this.daysOfWeekDisabled.includes(r)&&(s.add("disabled"),i(this.disabled,n)),this.daysOfWeekHighlighted.includes(r)&&s.add("highlighted"),this.range){const[e,t]=this.range;n>e&&n{e.classList.remove("range","range-start","range-end","selected","focused")})),Array.from(this.grid.children).forEach((i=>{const s=Number(i.dataset.date),n=i.classList;s>e&&s{e.classList.remove("focused")})),this.grid.children[e].classList.add("focused")}}function se(e,t){if(!e||!e[0]||!e[1])return;const[[i,s],[n,a]]=e;return i>t||ne})))),super.init(e)}setOptions(t){if(t.locale&&(this.monthNames=t.locale.monthsShort),e(t,"minDate"))if(void 0===t.minDate)this.minYear=this.minMonth=this.minDate=void 0;else{const e=new Date(t.minDate);this.minYear=e.getFullYear(),this.minMonth=e.getMonth(),this.minDate=e.setDate(1)}if(e(t,"maxDate"))if(void 0===t.maxDate)this.maxYear=this.maxMonth=this.maxDate=void 0;else{const e=new Date(t.maxDate);this.maxYear=e.getFullYear(),this.maxMonth=e.getMonth(),this.maxDate=l(this.maxYear,this.maxMonth+1,0)}this.isMinView?t.datesDisabled&&(this.datesDisabled=t.datesDisabled):this.datesDisabled=[],void 0!==t.beforeShowMonth&&(this.beforeShow="function"==typeof t.beforeShowMonth?t.beforeShowMonth:void 0)}updateFocus(){const e=new Date(this.picker.viewDate);this.year=e.getFullYear(),this.focused=e.getMonth()}updateSelection(){const{dates:e,rangepicker:t}=this.picker.datepicker;this.selected=e.reduce(((e,t)=>{const s=new Date(t),n=s.getFullYear(),a=s.getMonth();return void 0===e[n]?e[n]=[a]:i(e[n],a),e}),{}),t&&t.dates&&(this.range=t.dates.map((e=>{const t=new Date(e);return isNaN(t)?void 0:[t.getFullYear(),t.getMonth()]})))}render(){this.disabled=this.datesDisabled.reduce(((e,t)=>{const i=new Date(t);return this.year===i.getFullYear()&&e.push(i.getMonth()),e}),[]),this.picker.setViewSwitchLabel(this.year),this.picker.setPrevBtnDisabled(this.year<=this.minYear),this.picker.setNextBtnDisabled(this.year>=this.maxYear);const e=this.selected[this.year]||[],t=this.yearthis.maxYear,i=this.year===this.minYear,s=this.year===this.maxYear,n=se(this.range,this.year);Array.from(this.grid.children).forEach(((a,r)=>{const d=a.classList,o=l(this.year,r,1);if(a.className=`datepicker-cell ${this.cellClass}`,this.isMinView&&(a.dataset.date=o),a.textContent=this.monthNames[r],(t||i&&rthis.maxMonth||this.disabled.includes(r))&&d.add("disabled"),n){const[e,t]=n;r>e&&r{e.classList.remove("range","range-start","range-end","selected","focused")})),Array.from(this.grid.children).forEach(((s,n)=>{const a=s.classList;n>t&&n{e.classList.remove("focused")})),this.grid.children[this.focused].classList.add("focused")}}class ae extends te{constructor(e,t){super(e,t)}init(e,t=!0){var i;t&&(this.navStep=10*this.step,this.beforeShowOption=`beforeShow${i=this.cellClass,[...i].reduce(((e,t,i)=>e+(i?t:t.toUpperCase())),"")}`,this.grid=this.element,this.element.classList.add(this.name,"datepicker-grid"),this.grid.appendChild(F(r("span",12)))),super.init(e)}setOptions(t){if(e(t,"minDate")&&(void 0===t.minDate?this.minYear=this.minDate=void 0:(this.minYear=m(t.minDate,this.step),this.minDate=l(this.minYear,0,1))),e(t,"maxDate")&&(void 0===t.maxDate?this.maxYear=this.maxDate=void 0:(this.maxYear=m(t.maxDate,this.step),this.maxDate=l(this.maxYear,11,31))),this.isMinView?t.datesDisabled&&(this.datesDisabled=t.datesDisabled):this.datesDisabled=[],void 0!==t[this.beforeShowOption]){const e=t[this.beforeShowOption];this.beforeShow="function"==typeof e?e:void 0}}updateFocus(){const e=new Date(this.picker.viewDate),t=m(e,this.navStep),i=t+9*this.step;this.first=t,this.last=i,this.start=t-this.step,this.focused=m(e,this.step)}updateSelection(){const{dates:e,rangepicker:t}=this.picker.datepicker;this.selected=e.reduce(((e,t)=>i(e,m(t,this.step))),[]),t&&t.dates&&(this.range=t.dates.map((e=>{if(void 0!==e)return m(e,this.step)})))}render(){this.disabled=this.datesDisabled.map((e=>new Date(e).getFullYear())),this.picker.setViewSwitchLabel(`${this.first}-${this.last}`),this.picker.setPrevBtnDisabled(this.first<=this.minYear),this.picker.setNextBtnDisabled(this.last>=this.maxYear),Array.from(this.grid.children).forEach(((e,t)=>{const i=e.classList,s=this.start+t*this.step,n=l(s,0,1);if(e.className=`datepicker-cell ${this.cellClass}`,this.isMinView&&(e.dataset.date=n),e.textContent=e.dataset.year=s,0===t?i.add("prev"):11===t&&i.add("next"),(sthis.maxYear||this.disabled.includes(s))&&i.add("disabled"),this.range){const[e,t]=this.range;s>e&&s{e.classList.remove("range","range-start","range-end","selected","focused")})),Array.from(this.grid.children).forEach((i=>{const s=Number(i.textContent),n=i.classList;s>e&&s{e.classList.remove("focused")})),this.grid.children[e].classList.add("focused")}}function re(e,t){const i={date:e.getDate(),viewDate:new Date(e.picker.viewDate),viewId:e.picker.currentView.id,datepicker:e};e.element.dispatchEvent(new CustomEvent(t,{detail:i}))}function de(e,t){const{minDate:i,maxDate:s}=e.config,{currentView:n,viewDate:r}=e.picker;let d;switch(n.id){case 0:d=u(r,t);break;case 1:d=f(r,t);break;default:d=f(r,t*n.navStep)}d=a(d,i,s),e.picker.changeFocus(d).render()}function oe(e){const t=e.picker.currentView.id;t!==e.config.maxView&&e.picker.changeView(t+1).render()}function ce(e){e.config.updateOnBlur?e.update({revert:!0}):e.refresh("input"),e.hide()}function le(e,t){const i=e.picker,s=new Date(i.viewDate),n=i.currentView.id,a=1===n?u(s,t-s.getMonth()):f(s,t-s.getFullYear());i.changeFocus(a).changeView(n-1).render()}function he(e){const t=e.picker,i=c();if(1===e.config.todayBtnMode){if(e.config.autohide)return void e.setDate(i);e.setDate(i,{render:!1}),t.update()}t.viewDate!==i&&t.changeFocus(i),t.changeView(0).render()}function ue(e){e.setDate({clear:!0})}function fe(e){oe(e)}function pe(e){de(e,-1)}function ge(e){de(e,1)}function me(e,t){const i=K(t,".datepicker-cell");if(!i||i.classList.contains("disabled"))return;const{id:s,isMinView:n}=e.picker.currentView;n?e.setDate(Number(i.dataset.date)):le(e,Number(1===s?i.dataset.month:i.dataset.year))}function we(e){e.preventDefault()}const De=["left","top","right","bottom"].reduce(((e,t)=>(e[t]=`datepicker-orient-${t}`,e)),{}),ye=e=>e?`${e}px`:e;function ve(t,i){if(void 0!==i.title&&(i.title?(t.controls.title.textContent=i.title,B(t.controls.title)):(t.controls.title.textContent="",L(t.controls.title))),i.prevArrow){const e=t.controls.prevBtn;A(e),i.prevArrow.forEach((t=>{e.appendChild(t.cloneNode(!0))}))}if(i.nextArrow){const e=t.controls.nextBtn;A(e),i.nextArrow.forEach((t=>{e.appendChild(t.cloneNode(!0))}))}if(i.locale&&(t.controls.todayBtn.textContent=i.locale.today,t.controls.clearBtn.textContent=i.locale.clear),void 0!==i.todayBtn&&(i.todayBtn?B(t.controls.todayBtn):L(t.controls.todayBtn)),e(i,"minDate")||e(i,"maxDate")){const{minDate:e,maxDate:i}=t.datepicker.config;t.controls.todayBtn.disabled=!n(c(),e,i)}void 0!==i.clearBtn&&(i.clearBtn?B(t.controls.clearBtn):L(t.controls.clearBtn))}function be(e){const{dates:i,config:s}=e;return a(i.length>0?t(i):s.defaultViewDate,s.minDate,s.maxDate)}function ke(e,t){const i=new Date(e.viewDate),s=new Date(t),{id:n,year:a,first:r,last:d}=e.currentView,o=s.getFullYear();switch(e.viewDate=t,o!==i.getFullYear()&&re(e.datepicker,"changeYear"),s.getMonth()!==i.getMonth()&&re(e.datepicker,"changeMonth"),n){case 0:return td;case 1:return o!==a;default:return od}}function xe(e){return window.getComputedStyle(e).direction}function Me(e){const t=V(e);if(t!==document.body&&t)return"visible"!==window.getComputedStyle(t).overflow?t:Me(t)}class Se{constructor(e){const{config:t}=this.datepicker=e,i=Q.replace(/%buttonClass%/g,t.buttonClass),s=this.element=F(i).firstChild,[n,a,r]=s.firstChild.children,d=n.firstElementChild,[o,c,l]=n.lastElementChild.children,[h,u]=r.firstChild.children,f={title:d,prevBtn:o,viewSwitch:c,nextBtn:l,todayBtn:h,clearBtn:u};this.main=a,this.controls=f;const p=e.inline?"inline":"dropdown";s.classList.add(`datepicker-${p}`),ve(this,t),this.viewDate=be(e),j(e,[[s,"mousedown",we],[a,"click",me.bind(null,e)],[f.viewSwitch,"click",fe.bind(null,e)],[f.prevBtn,"click",pe.bind(null,e)],[f.nextBtn,"click",ge.bind(null,e)],[f.todayBtn,"click",he.bind(null,e)],[f.clearBtn,"click",ue.bind(null,e)]]),this.views=[new ie(this),new ne(this),new ae(this,{id:2,name:"years",cellClass:"year",step:1}),new ae(this,{id:3,name:"decades",cellClass:"decade",step:10})],this.currentView=this.views[t.startView],this.currentView.render(),this.main.appendChild(this.currentView.element),t.container?t.container.appendChild(this.element):e.inputField.after(this.element)}setOptions(e){ve(this,e),this.views.forEach((t=>{t.init(e,!1)})),this.currentView.render()}detach(){this.element.remove()}show(){if(this.active)return;const{datepicker:e,element:t}=this;if(e.inline)t.classList.add("active");else{const i=xe(e.inputField);i!==xe(V(t))?t.dir=i:t.dir&&t.removeAttribute("dir"),t.style.visiblity="hidden",t.classList.add("active"),this.place(),t.style.visiblity="",e.config.disableTouchKeyboard&&e.inputField.blur()}this.active=!0,re(e,"show")}hide(){this.active&&(this.datepicker.exitEditMode(),this.element.classList.remove("active"),this.active=!1,re(this.datepicker,"hide"))}place(){const{classList:e,offsetParent:t,style:i}=this.element,{config:s,inputField:n}=this.datepicker,{width:a,height:r}=this.element.getBoundingClientRect(),{left:d,top:o,right:c,bottom:l,width:h,height:u}=n.getBoundingClientRect();let{x:f,y:p}=s.orientation,g=d,m=o;if(t!==document.body&&t){const e=t.getBoundingClientRect();g-=e.left-t.scrollLeft,m-=e.top-t.scrollTop}else g+=window.scrollX,m+=window.scrollY;const w=Me(n);let D=0,y=0,{clientWidth:v,clientHeight:b}=document.documentElement;if(w){const e=w.getBoundingClientRect();e.top>0&&(y=e.top),e.left>0&&(D=e.left),e.rightv?(f="right",vy&&l+r>b?"top":"bottom"),"top"===p?m-=r:m+=u,e.remove(...Object.values(De)),e.add(De[f],De[p]),i.left=ye(g),i.top=ye(m)}setViewSwitchLabel(e){this.controls.viewSwitch.textContent=e}setPrevBtnDisabled(e){this.controls.prevBtn.disabled=e}setNextBtnDisabled(e){this.controls.nextBtn.disabled=e}changeView(e){const t=this.currentView,i=this.views[e];return i.id!==t.id&&(this.currentView=i,this._renderMethod="render",re(this.datepicker,"changeView"),this.main.replaceChild(i.element,t.element)),this}changeFocus(e){return this._renderMethod=ke(this,e)?"render":"refreshFocus",this.views.forEach((e=>{e.updateFocus()})),this}update(){const e=be(this.datepicker);return this._renderMethod=ke(this,e)?"render":"refresh",this.views.forEach((e=>{e.updateFocus(),e.updateSelection()})),this}render(e=!0){const t=e&&this._renderMethod||"render";delete this._renderMethod,this.currentView[t]()}}function Oe(e,t,i,s,a,r){if(n(e,a,r)){if(s(e)){return Oe(t(e,i),t,i,s,a,r)}return e}}function Ce(e,t,i,s){const n=e.picker,a=n.currentView,r=a.step||1;let d,o,c=n.viewDate;switch(a.id){case 0:c=s?h(c,7*i):t.ctrlKey||t.metaKey?f(c,i):h(c,i),d=h,o=e=>a.disabled.includes(e);break;case 1:c=u(c,s?4*i:i),d=u,o=e=>{const t=new Date(e),{year:i,disabled:s}=a;return t.getFullYear()===i&&s.includes(t.getMonth())};break;default:c=f(c,i*(s?4:1)*r),d=f,o=e=>a.disabled.includes(m(e,r))}c=Oe(c,d,i<0?-r:r,o,a.minDate,a.maxDate),void 0!==c&&n.changeFocus(c).render()}function Ee(e,t){const i=t.key;if("Tab"===i)return void ce(e);const s=e.picker,{id:n,isMinView:a}=s.currentView;if(s.active){if(e.editMode)return void("Enter"===i?e.exitEditMode({update:!0,autohide:e.config.autohide}):"Escape"===i&&s.hide());if("ArrowLeft"===i)if(t.ctrlKey||t.metaKey)de(e,-1);else{if(t.shiftKey)return void e.enterEditMode();Ce(e,t,-1,!1)}else if("ArrowRight"===i)if(t.ctrlKey||t.metaKey)de(e,1);else{if(t.shiftKey)return void e.enterEditMode();Ce(e,t,1,!1)}else if("ArrowUp"===i)if(t.ctrlKey||t.metaKey)oe(e);else{if(t.shiftKey)return void e.enterEditMode();Ce(e,t,-1,!0)}else if("ArrowDown"===i){if(t.shiftKey&&!t.ctrlKey&&!t.metaKey)return void e.enterEditMode();Ce(e,t,1,!0)}else{if("Enter"!==i)return void("Escape"===i?s.hide():"Backspace"!==i&&"Delete"!==i&&(1!==i.length||t.ctrlKey||t.metaKey)||e.enterEditMode());if(a)return void e.setDate(s.viewDate);s.changeView(n-1).render()}}else{if("ArrowDown"!==i)return void("Enter"===i?e.update():"Escape"===i&&s.show());s.show()}t.preventDefault()}function Fe(e){e.config.showOnFocus&&!e._showing&&e.show()}function Ve(e,t){const i=t.target;(e.picker.active||e.config.showOnClick)&&(i._active=N(i),i._clicking=setTimeout((()=>{delete i._active,delete i._clicking}),2e3))}function Ne(e,t){const i=t.target;i._clicking&&(clearTimeout(i._clicking),delete i._clicking,i._active&&e.enterEditMode(),delete i._active,e.config.showOnClick&&e.show())}function Le(e,t){t.clipboardData.types.includes("text/plain")&&e.enterEditMode()}function Be(e,t){const{element:i,picker:s}=e;if(!s.active&&!N(i))return;const n=s.element;K(t,(e=>e===i||e===n))||ce(e)}function Ae(e,t){return e.map((e=>C(e,t.format,t.locale))).join(t.dateDelimiter)}function Ye(e,t,i=!1){const{config:s,dates:a,rangeSideIndex:r}=e;if(0===t.length)return i?[]:void 0;let d=t.reduce(((e,t)=>{let i=O(t,s.format,s.locale);return void 0===i||(i=w(i,s.pickLevel,r),!n(i,s.minDate,s.maxDate)||e.includes(i)||s.datesDisabled.includes(i)||!(s.pickLevel>0)&&s.daysOfWeekDisabled.includes(new Date(i).getDay())||e.push(i)),e}),[]);return 0!==d.length?(s.multidate&&!i&&(d=d.reduce(((e,t)=>(a.includes(t)||e.push(t),e)),a.filter((e=>!d.includes(e))))),s.maxNumberOfDates&&d.length>s.maxNumberOfDates?d.slice(-1*s.maxNumberOfDates):d):void 0}function We(e,t=3,i=!0){const{config:s,picker:n,inputField:a}=e;if(2&t){const e=n.active?s.pickLevel:s.startView;n.update().changeView(e).render(i)}1&t&&a&&(a.value=Ae(e.dates,s))}function He(e,t,i){let{clear:s,render:n,autohide:a,revert:r}=i;void 0===n&&(n=!0),n?void 0===a&&(a=e.config.autohide):a=!1;const d=Ye(e,t,s);(d||r)&&(d&&d.toString()!==e.dates.toString()?(e.dates=d,We(e,n?3:1),re(e,"changeDate")):We(e,1),a&&e.hide())}class je{constructor(e,t={},i){e.datepicker=this,this.element=e;const n=this.config=Object.assign({buttonClass:t.buttonClass&&String(t.buttonClass)||"button",container:null,defaultViewDate:c(),maxDate:void 0,minDate:void 0},G(R,this)),a=this.inline="INPUT"!==e.tagName;let r,d;if(a?n.container=e:(t.container&&(n.container=t.container instanceof HTMLElement?t.container:document.querySelector(t.container)),r=this.inputField=e,r.classList.add("datepicker-input")),i){const e=i.inputs.indexOf(r),t=i.datepickers;if(e<0||e>1||!Array.isArray(t))throw Error("Invalid rangepicker object.");t[e]=this,Object.defineProperty(this,"rangepicker",{get:()=>i}),Object.defineProperty(this,"rangeSideIndex",{get:()=>e})}this._options=t,Object.assign(n,G(t,this)),a?(d=s(e.dataset.date,n.dateDelimiter),delete e.dataset.date):d=s(r.value,n.dateDelimiter),this.dates=[];const o=Ye(this,d);o&&o.length>0&&(this.dates=o),r&&(r.value=Ae(this.dates,n));const l=this.picker=new Se(this);if(a)this.show();else{const e=Be.bind(null,this);j(this,[[r,"keydown",Ee.bind(null,this)],[r,"focus",Fe.bind(null,this)],[r,"mousedown",Ve.bind(null,this)],[r,"click",Ne.bind(null,this)],[r,"paste",Le.bind(null,this)],[document,"mousedown",e],[document,"touchstart",e],[window,"resize",l.place.bind(l)]])}}static formatDate(e,t,i){return C(e,t,i&&$[i]||$.en)}static parseDate(e,t,i){return O(e,t,i&&$[i]||$.en)}static get locales(){return $}get active(){return!(!this.picker||!this.picker.active)}get pickerElement(){return this.picker?this.picker.element:void 0}setOptions(e){const t=this.picker,i=G(e,this);Object.assign(this._options,e),Object.assign(this.config,i),t.setOptions(i),We(this,3)}show(){if(this.inputField){if(this.inputField.disabled)return;N(this.inputField)||this.config.disableTouchKeyboard||(this._showing=!0,this.inputField.focus(),delete this._showing)}this.picker.show()}hide(){this.inline||(this.picker.hide(),this.picker.update().changeView(this.config.startView).render())}destroy(){return this.hide(),T(this),this.picker.detach(),this.inline||this.inputField.classList.remove("datepicker-input"),delete this.element.datepicker,this}getDate(e){const t=e?t=>C(t,e,this.config.locale):e=>new Date(e);return this.config.multidate?this.dates.map(t):this.dates.length>0?t(this.dates[0]):void 0}setDate(...e){const i=[...e],s={},n=t(e);"object"!=typeof n||Array.isArray(n)||n instanceof Date||!n||Object.assign(s,i.pop());He(this,Array.isArray(i[0])?i[0]:i,s)}update(e){if(this.inline)return;const t=Object.assign(e||{},{clear:!0,render:!0});He(this,s(this.inputField.value,this.config.dateDelimiter),t)}refresh(e,t=!1){let i;e&&"string"!=typeof e&&(t=e,e=void 0),i="picker"===e?2:"input"===e?1:3,We(this,i,!t)}enterEditMode(){this.inline||!this.picker.active||this.editMode||(this.editMode=!0,this.inputField.classList.add("in-edit"))}exitEditMode(e){if(this.inline||!this.editMode)return;const t=Object.assign({update:!1},e);delete this.editMode,this.inputField.classList.remove("in-edit"),t.update&&this.update(t)}}function Te(e){const t=Object.assign({},e);return delete t.inputs,delete t.allowOneSidedRange,delete t.maxNumberOfDates,t}function _e(e,t,i,s){j(e,[[i,"changeDate",t]]),new je(i,s,e)}function Ke(e,t){if(e._updating)return;e._updating=!0;const i=t.target;if(void 0===i.datepicker)return;const s=e.datepickers,n={render:!1},a=e.inputs.indexOf(i),r=0===a?1:0,d=s[a].dates[0],o=s[r].dates[0];void 0!==d&&void 0!==o?0===a&&d>o?(s[0].setDate(o,n),s[1].setDate(d,n)):1===a&&da}),_e(this,s,this.inputs[0],n),_e(this,s,this.inputs[1],n),Object.freeze(a),a[0].dates.length>0?Ke(this,{target:this.inputs[0]}):a[1].dates.length>0&&Ke(this,{target:this.inputs[1]})}get dates(){return 2===this.datepickers.length?[this.datepickers[0].dates[0],this.datepickers[1].dates[0]]:void 0}setOptions(e){this.allowOneSidedRange=!!e.allowOneSidedRange;const t=Te(e);this.datepickers[0].setOptions(t),this.datepickers[1].setOptions(t)}destroy(){this.datepickers[0].destroy(),this.datepickers[1].destroy(),T(this),delete this.element.rangepicker}getDates(e){const t=e?t=>C(t,e,this.datepickers[0].config.locale):e=>new Date(e);return this.dates.map((e=>void 0===e?e:t(e)))}setDates(e,t){const[i,s]=this.datepickers,n=this.dates;this._updating=!0,i.setDate(e),s.setDate(t),delete this._updating,s.dates[0]!==n[1]?Ke(this,{target:this.inputs[1]}):i.dates[0]!==n[0]&&Ke(this,{target:this.inputs[0]})}}}();
\ No newline at end of file
diff --git a/src/ui/static/js/datepicker/datepicker.min.js b/src/ui/static/js/datepicker/datepicker.min.js
new file mode 100644
index 000000000..7590ab30b
--- /dev/null
+++ b/src/ui/static/js/datepicker/datepicker.min.js
@@ -0,0 +1 @@
+var Datepicker=function(){"use strict";function e(e,t){return Object.prototype.hasOwnProperty.call(e,t)}function t(e){return e[e.length-1]}function i(e,...t){return t.forEach((t=>{e.includes(t)||e.push(t)})),e}function s(e,t){return e?e.split(t):[]}function n(e,t,i){return(void 0===t||e>=t)&&(void 0===i||e<=i)}function a(e,t,i){return ei?i:e}function r(e,t,i={},s=0,n=""){n+=`<${Object.keys(i).reduce(((e,t)=>{let n=i[t];return"function"==typeof n&&(n=n(s)),`${e} ${t}="${n}"`}),e)}>${e}>`;const a=s+1;return a\s+/g,">").replace(/\s+,"<")}function o(e){return new Date(e).setHours(0,0,0,0)}function c(){return(new Date).setHours(0,0,0,0)}function l(...e){switch(e.length){case 0:return c();case 1:return o(e[0])}const t=new Date(0);return t.setFullYear(...e),t.setHours(0,0,0,0)}function h(e,t){const i=new Date(e);return i.setDate(i.getDate()+t)}function u(e,t){const i=new Date(e),s=i.getMonth()+t;let n=s%12;n<0&&(n+=12);const a=i.setMonth(s);return i.getMonth()!==n?i.setDate(0):a}function f(e,t){const i=new Date(e),s=i.getMonth(),n=i.setFullYear(i.getFullYear()+t);return 1===s&&2===i.getMonth()?i.setDate(0):n}function p(e,t){return(e-t+7)%7}function g(e,t,i=0){const s=new Date(e).getDay();return h(e,p(t,i)-p(s,i))}function m(e,t){const i=new Date(e).getFullYear();return Math.floor(i/t)*t}function w(e,t,i){if(1!==t&&2!==t)return e;const s=new Date(e);return 1===t?i?s.setMonth(s.getMonth()+1,0):s.setDate(1):i?s.setFullYear(s.getFullYear()+1,0,0):s.setMonth(0,1),s.setHours(0,0,0,0)}const y=/dd?|DD?|mm?|MM?|yy?(?:yy)?/,D=/[\s!-/:-@[-`{-~年月日]+/;let v={};const b={y:(e,t)=>new Date(e).setFullYear(parseInt(t,10)),m(e,t,i){const s=new Date(e);let n=parseInt(t,10)-1;if(isNaN(n)){if(!t)return NaN;const e=t.toLowerCase(),s=t=>t.toLowerCase().startsWith(e);if(n=i.monthsShort.findIndex(s),n<0&&(n=i.months.findIndex(s)),n<0)return NaN}return s.setMonth(n),s.getMonth()!==x(n)?s.setDate(0):s.getTime()},d:(e,t)=>new Date(e).setDate(parseInt(t,10))},k={d:e=>e.getDate(),dd:e=>M(e.getDate(),2),D:(e,t)=>t.daysShort[e.getDay()],DD:(e,t)=>t.days[e.getDay()],m:e=>e.getMonth()+1,mm:e=>M(e.getMonth()+1,2),M:(e,t)=>t.monthsShort[e.getMonth()],MM:(e,t)=>t.months[e.getMonth()],y:e=>e.getFullYear(),yy:e=>M(e.getFullYear(),2).slice(-2),yyyy:e=>M(e.getFullYear(),4)};function x(e){return e>-1?e%12:x(e+12)}function M(e,t){return e.toString().padStart(t,"0")}function S(e){if("string"!=typeof e)throw new Error("Invalid date format.");if(e in v)return v[e];const i=e.split(y),s=e.match(new RegExp(y,"g"));if(0===i.length||!s)throw new Error("Invalid date format.");const n=s.map((e=>k[e])),a=Object.keys(b).reduce(((e,t)=>(s.find((e=>"D"!==e[0]&&e[0].toLowerCase()===t))&&e.push(t),e)),[]);return v[e]={parser(e,t){const i=e.split(D).reduce(((e,t,i)=>{if(t.length>0&&s[i]){const n=s[i][0];"M"===n?e.m=t:"D"!==n&&(e[n]=t)}return e}),{});return a.reduce(((e,s)=>{const n=b[s](e,i[s],t);return isNaN(n)?e:n}),c())},formatter:(e,s)=>n.reduce(((t,n,a)=>t+`${i[a]}${n(e,s)}`),"")+t(i)}}function C(e,t,i){if(e instanceof Date||"number"==typeof e){const t=o(e);return isNaN(t)?void 0:t}if(e){if("today"===e)return c();if(t&&t.toValue){const s=t.toValue(e,t,i);return isNaN(s)?void 0:o(s)}return S(t).parser(e,i)}}function O(e,t,i){if(isNaN(e)||!e&&0!==e)return"";const s="number"==typeof e?new Date(e):e;return t.toDisplay?t.toDisplay(s,t,i):S(t).formatter(s,i)}const E=document.createRange();function F(e){return E.createContextualFragment(e)}function V(e){return e.parentElement||(e.parentNode instanceof ShadowRoot?e.parentNode.host:void 0)}function N(e){return e.getRootNode().activeElement===e}function L(e){"none"!==e.style.display&&(e.style.display&&(e.dataset.styleDisplay=e.style.display),e.style.display="none")}function B(e){"none"===e.style.display&&(e.dataset.styleDisplay?(e.style.display=e.dataset.styleDisplay,delete e.dataset.styleDisplay):e.style.display="")}function Y(e){e.firstChild&&(e.removeChild(e.firstChild),Y(e))}const A=new WeakMap,{addEventListener:W,removeEventListener:H}=EventTarget.prototype;function T(e,t){let i=A.get(e);i||(i=[],A.set(e,i)),t.forEach((e=>{W.call(...e),i.push(e)}))}if(!Event.prototype.composedPath){const e=(t,i=[])=>{let s;return i.push(t),t.parentNode?s=t.parentNode:t.host?s=t.host:t.defaultView&&(s=t.defaultView),s?e(s,i):i};Event.prototype.composedPath=function(){return e(this.target)}}function K(e,t,i){const[s,...n]=e;return t(s)?s:s!==i&&"HTML"!==s.tagName&&0!==n.length?K(n,t,i):void 0}function j(e,t){const i="function"==typeof t?t:e=>e instanceof Element&&e.matches(t);return K(e.composedPath(),i,e.currentTarget)}const $={en:{days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],today:"Today",clear:"Clear",titleFormat:"MM y"}},_={autohide:!1,beforeShowDay:null,beforeShowDecade:null,beforeShowMonth:null,beforeShowYear:null,calendarWeeks:!1,clearBtn:!1,dateDelimiter:",",datesDisabled:[],daysOfWeekDisabled:[],daysOfWeekHighlighted:[],defaultViewDate:void 0,disableTouchKeyboard:!1,format:"mm/dd/yyyy",language:"en",maxDate:null,maxNumberOfDates:1,maxView:3,minDate:null,nextArrow:"»",orientation:"auto",pickLevel:0,prevArrow:"«",showDaysOfWeek:!0,showOnClick:!0,showOnFocus:!0,startView:0,title:"",todayBtn:!1,todayBtnMode:0,todayHighlight:!1,updateOnBlur:!0,weekStart:0},{language:I,format:P,weekStart:R}=_;function q(e,t){return e.length<6&&t>=0&&t<7?i(e,t):e}function J(e){return(e+6)%7}function U(e,t,i,s){const n=C(e,t,i);return void 0!==n?n:s}function z(e,t,i=3){const s=parseInt(e,10);return s>=0&&s<=i?s:t}function X(t,s){const n=Object.assign({},t),a={},r=s.constructor.locales,d=s.rangeSideIndex;let{format:o,language:c,locale:h,maxDate:u,maxView:f,minDate:p,pickLevel:g,startView:m,weekStart:D}=s.config||{};if(n.language){let e;if(n.language!==c&&(r[n.language]?e=n.language:(e=n.language.split("-")[0],void 0===r[e]&&(e=!1))),delete n.language,e){c=a.language=e;const t=h||r[I];h=Object.assign({format:P,weekStart:R},r[I]),c!==I&&Object.assign(h,r[c]),a.locale=h,o===t.format&&(o=a.format=h.format),D===t.weekStart&&(D=a.weekStart=h.weekStart,a.weekEnd=J(h.weekStart))}}if(n.format){const e="function"==typeof n.format.toDisplay,t="function"==typeof n.format.toValue,i=y.test(n.format);(e&&t||i)&&(o=a.format=n.format),delete n.format}let v=g;void 0!==n.pickLevel&&(v=z(n.pickLevel,2),delete n.pickLevel),v!==g&&(v>g&&(void 0===n.minDate&&(n.minDate=p),void 0===n.maxDate&&(n.maxDate=u)),n.datesDisabled||(n.datesDisabled=[]),g=a.pickLevel=v);let b=p,k=u;if(void 0!==n.minDate){const e=l(0,0,1);b=null===n.minDate?e:U(n.minDate,o,h,b),b!==e&&(b=w(b,g,!1)),delete n.minDate}if(void 0!==n.maxDate&&(k=null===n.maxDate?void 0:U(n.maxDate,o,h,k),void 0!==k&&(k=w(k,g,!0)),delete n.maxDate),k{const s=C(t,o,h);return void 0!==s?i(e,w(s,g,d)):e}),[]),delete n.datesDisabled),void 0!==n.defaultViewDate){const e=C(n.defaultViewDate,o,h);void 0!==e&&(a.defaultViewDate=e),delete n.defaultViewDate}if(void 0!==n.weekStart){const e=Number(n.weekStart)%7;isNaN(e)||(D=a.weekStart=e,a.weekEnd=J(e)),delete n.weekStart}if(n.daysOfWeekDisabled&&(a.daysOfWeekDisabled=n.daysOfWeekDisabled.reduce(q,[]),delete n.daysOfWeekDisabled),n.daysOfWeekHighlighted&&(a.daysOfWeekHighlighted=n.daysOfWeekHighlighted.reduce(q,[]),delete n.daysOfWeekHighlighted),void 0!==n.maxNumberOfDates){const e=parseInt(n.maxNumberOfDates,10);e>=0&&(a.maxNumberOfDates=e,a.multidate=1!==e),delete n.maxNumberOfDates}n.dateDelimiter&&(a.dateDelimiter=String(n.dateDelimiter),delete n.dateDelimiter);let x=f;void 0!==n.maxView&&(x=z(n.maxView,f),delete n.maxView),x=g>x?g:x,x!==f&&(f=a.maxView=x);let M=m;if(void 0!==n.startView&&(M=z(n.startView,M),delete n.startView),Mf&&(M=f),M!==m&&(a.startView=M),n.prevArrow){const e=F(n.prevArrow);e.childNodes.length>0&&(a.prevArrow=e.childNodes),delete n.prevArrow}if(n.nextArrow){const e=F(n.nextArrow);e.childNodes.length>0&&(a.nextArrow=e.childNodes),delete n.nextArrow}if(void 0!==n.disableTouchKeyboard&&(a.disableTouchKeyboard="ontouchstart"in document&&!!n.disableTouchKeyboard,delete n.disableTouchKeyboard),n.orientation){const e=n.orientation.toLowerCase().split(/\s+/g);a.orientation={x:e.find((e=>"left"===e||"right"===e))||"auto",y:e.find((e=>"top"===e||"bottom"===e))||"auto"},delete n.orientation}if(void 0!==n.todayBtnMode){switch(n.todayBtnMode){case 0:case 1:a.todayBtnMode=n.todayBtnMode}delete n.todayBtnMode}return Object.keys(n).forEach((t=>{void 0!==n[t]&&e(_,t)&&(a[t]=n[t])})),a}const G=d(''),Q=d(`\n
${r("span",7,{class:"dow"})}
\n
${r("span",42)}
\n
`),Z=d(`\n
\n
${r("span",6,{class:"week"})}
\n
`);class ee{constructor(e,t){Object.assign(this,t,{picker:e,element:F('').firstChild,selected:[]}),this.init(this.picker.datepicker.config)}init(e){void 0!==e.pickLevel&&(this.isMinView=this.id===e.pickLevel),this.setOptions(e),this.updateFocus(),this.updateSelection()}performBeforeHook(e,t,s){let n=this.beforeShow(new Date(s));switch(typeof n){case"boolean":n={enabled:n};break;case"string":n={classes:n}}if(n){if(!1===n.enabled&&(e.classList.add("disabled"),i(this.disabled,t)),n.classes){const s=n.classes.split(/\s+/);e.classList.add(...s),s.includes("disabled")&&i(this.disabled,t)}n.content&&function(e,t){Y(e),t instanceof DocumentFragment?e.appendChild(t):"string"==typeof t?e.appendChild(F(t)):"function"==typeof t.forEach&&t.forEach((t=>{e.appendChild(t)}))}(e,n.content)}}}class te extends ee{constructor(e){super(e,{id:0,name:"days",cellClass:"day"})}init(e,t=!0){if(t){const e=F(Q).firstChild;this.dow=e.firstChild,this.grid=e.lastChild,this.element.appendChild(e)}super.init(e)}setOptions(t){let i;if(e(t,"minDate")&&(this.minDate=t.minDate),e(t,"maxDate")&&(this.maxDate=t.maxDate),t.datesDisabled&&(this.datesDisabled=t.datesDisabled),t.daysOfWeekDisabled&&(this.daysOfWeekDisabled=t.daysOfWeekDisabled,i=!0),t.daysOfWeekHighlighted&&(this.daysOfWeekHighlighted=t.daysOfWeekHighlighted),void 0!==t.todayHighlight&&(this.todayHighlight=t.todayHighlight),void 0!==t.weekStart&&(this.weekStart=t.weekStart,this.weekEnd=t.weekEnd,i=!0),t.locale){const e=this.locale=t.locale;this.dayNames=e.daysMin,this.switchLabelFormat=e.titleFormat,i=!0}if(void 0!==t.beforeShowDay&&(this.beforeShow="function"==typeof t.beforeShowDay?t.beforeShowDay:void 0),void 0!==t.calendarWeeks)if(t.calendarWeeks&&!this.calendarWeeks){const e=F(Z).firstChild;this.calendarWeeks={element:e,dow:e.firstChild,weeks:e.lastChild},this.element.insertBefore(e,this.element.firstChild)}else this.calendarWeeks&&!t.calendarWeeks&&(this.element.removeChild(this.calendarWeeks.element),this.calendarWeeks=null);void 0!==t.showDaysOfWeek&&(t.showDaysOfWeek?(B(this.dow),this.calendarWeeks&&B(this.calendarWeeks.dow)):(L(this.dow),this.calendarWeeks&&L(this.calendarWeeks.dow))),i&&Array.from(this.dow.children).forEach(((e,t)=>{const i=(this.weekStart+t)%7;e.textContent=this.dayNames[i],e.className=this.daysOfWeekDisabled.includes(i)?"dow disabled":"dow"}))}updateFocus(){const e=new Date(this.picker.viewDate),t=e.getFullYear(),i=e.getMonth(),s=l(t,i,1),n=g(s,this.weekStart,this.weekStart);this.first=s,this.last=l(t,i+1,0),this.start=n,this.focused=this.picker.viewDate}updateSelection(){const{dates:e,rangepicker:t}=this.picker.datepicker;this.selected=e,t&&(this.range=t.dates)}render(){this.today=this.todayHighlight?c():void 0,this.disabled=[...this.datesDisabled];const e=O(this.focused,this.switchLabelFormat,this.locale);if(this.picker.setViewSwitchLabel(e),this.picker.setPrevBtnDisabled(this.first<=this.minDate),this.picker.setNextBtnDisabled(this.last>=this.maxDate),this.calendarWeeks){const e=g(this.first,1,1);Array.from(this.calendarWeeks.weeks.children).forEach(((t,i)=>{t.textContent=function(e){const t=g(e,4,1),i=g(new Date(t).setMonth(0,4),4,1);return Math.round((t-i)/6048e5)+1}(h(e,7*i))}))}Array.from(this.grid.children).forEach(((e,t)=>{const s=e.classList,n=h(this.start,t),a=new Date(n),r=a.getDay();if(e.className=`datepicker-cell ${this.cellClass}`,e.dataset.date=n,e.textContent=a.getDate(),nthis.last&&s.add("next"),this.today===n&&s.add("today"),(nthis.maxDate||this.disabled.includes(n))&&s.add("disabled"),this.daysOfWeekDisabled.includes(r)&&(s.add("disabled"),i(this.disabled,n)),this.daysOfWeekHighlighted.includes(r)&&s.add("highlighted"),this.range){const[e,t]=this.range;n>e&&n{e.classList.remove("range","range-start","range-end","selected","focused")})),Array.from(this.grid.children).forEach((i=>{const s=Number(i.dataset.date),n=i.classList;s>e&&s{e.classList.remove("focused")})),this.grid.children[e].classList.add("focused")}}function ie(e,t){if(!e||!e[0]||!e[1])return;const[[i,s],[n,a]]=e;return i>t||ne})))),super.init(e)}setOptions(t){if(t.locale&&(this.monthNames=t.locale.monthsShort),e(t,"minDate"))if(void 0===t.minDate)this.minYear=this.minMonth=this.minDate=void 0;else{const e=new Date(t.minDate);this.minYear=e.getFullYear(),this.minMonth=e.getMonth(),this.minDate=e.setDate(1)}if(e(t,"maxDate"))if(void 0===t.maxDate)this.maxYear=this.maxMonth=this.maxDate=void 0;else{const e=new Date(t.maxDate);this.maxYear=e.getFullYear(),this.maxMonth=e.getMonth(),this.maxDate=l(this.maxYear,this.maxMonth+1,0)}this.isMinView?t.datesDisabled&&(this.datesDisabled=t.datesDisabled):this.datesDisabled=[],void 0!==t.beforeShowMonth&&(this.beforeShow="function"==typeof t.beforeShowMonth?t.beforeShowMonth:void 0)}updateFocus(){const e=new Date(this.picker.viewDate);this.year=e.getFullYear(),this.focused=e.getMonth()}updateSelection(){const{dates:e,rangepicker:t}=this.picker.datepicker;this.selected=e.reduce(((e,t)=>{const s=new Date(t),n=s.getFullYear(),a=s.getMonth();return void 0===e[n]?e[n]=[a]:i(e[n],a),e}),{}),t&&t.dates&&(this.range=t.dates.map((e=>{const t=new Date(e);return isNaN(t)?void 0:[t.getFullYear(),t.getMonth()]})))}render(){this.disabled=this.datesDisabled.reduce(((e,t)=>{const i=new Date(t);return this.year===i.getFullYear()&&e.push(i.getMonth()),e}),[]),this.picker.setViewSwitchLabel(this.year),this.picker.setPrevBtnDisabled(this.year<=this.minYear),this.picker.setNextBtnDisabled(this.year>=this.maxYear);const e=this.selected[this.year]||[],t=this.yearthis.maxYear,i=this.year===this.minYear,s=this.year===this.maxYear,n=ie(this.range,this.year);Array.from(this.grid.children).forEach(((a,r)=>{const d=a.classList,o=l(this.year,r,1);if(a.className=`datepicker-cell ${this.cellClass}`,this.isMinView&&(a.dataset.date=o),a.textContent=this.monthNames[r],(t||i&&rthis.maxMonth||this.disabled.includes(r))&&d.add("disabled"),n){const[e,t]=n;r>e&&r{e.classList.remove("range","range-start","range-end","selected","focused")})),Array.from(this.grid.children).forEach(((s,n)=>{const a=s.classList;n>t&&n{e.classList.remove("focused")})),this.grid.children[this.focused].classList.add("focused")}}class ne extends ee{constructor(e,t){super(e,t)}init(e,t=!0){var i;t&&(this.navStep=10*this.step,this.beforeShowOption=`beforeShow${i=this.cellClass,[...i].reduce(((e,t,i)=>e+(i?t:t.toUpperCase())),"")}`,this.grid=this.element,this.element.classList.add(this.name,"datepicker-grid"),this.grid.appendChild(F(r("span",12)))),super.init(e)}setOptions(t){if(e(t,"minDate")&&(void 0===t.minDate?this.minYear=this.minDate=void 0:(this.minYear=m(t.minDate,this.step),this.minDate=l(this.minYear,0,1))),e(t,"maxDate")&&(void 0===t.maxDate?this.maxYear=this.maxDate=void 0:(this.maxYear=m(t.maxDate,this.step),this.maxDate=l(this.maxYear,11,31))),this.isMinView?t.datesDisabled&&(this.datesDisabled=t.datesDisabled):this.datesDisabled=[],void 0!==t[this.beforeShowOption]){const e=t[this.beforeShowOption];this.beforeShow="function"==typeof e?e:void 0}}updateFocus(){const e=new Date(this.picker.viewDate),t=m(e,this.navStep),i=t+9*this.step;this.first=t,this.last=i,this.start=t-this.step,this.focused=m(e,this.step)}updateSelection(){const{dates:e,rangepicker:t}=this.picker.datepicker;this.selected=e.reduce(((e,t)=>i(e,m(t,this.step))),[]),t&&t.dates&&(this.range=t.dates.map((e=>{if(void 0!==e)return m(e,this.step)})))}render(){this.disabled=this.datesDisabled.map((e=>new Date(e).getFullYear())),this.picker.setViewSwitchLabel(`${this.first}-${this.last}`),this.picker.setPrevBtnDisabled(this.first<=this.minYear),this.picker.setNextBtnDisabled(this.last>=this.maxYear),Array.from(this.grid.children).forEach(((e,t)=>{const i=e.classList,s=this.start+t*this.step,n=l(s,0,1);if(e.className=`datepicker-cell ${this.cellClass}`,this.isMinView&&(e.dataset.date=n),e.textContent=e.dataset.year=s,0===t?i.add("prev"):11===t&&i.add("next"),(sthis.maxYear||this.disabled.includes(s))&&i.add("disabled"),this.range){const[e,t]=this.range;s>e&&s{e.classList.remove("range","range-start","range-end","selected","focused")})),Array.from(this.grid.children).forEach((i=>{const s=Number(i.textContent),n=i.classList;s>e&&s{e.classList.remove("focused")})),this.grid.children[e].classList.add("focused")}}function ae(e,t){const i={date:e.getDate(),viewDate:new Date(e.picker.viewDate),viewId:e.picker.currentView.id,datepicker:e};e.element.dispatchEvent(new CustomEvent(t,{detail:i}))}function re(e,t){const{minDate:i,maxDate:s}=e.config,{currentView:n,viewDate:r}=e.picker;let d;switch(n.id){case 0:d=u(r,t);break;case 1:d=f(r,t);break;default:d=f(r,t*n.navStep)}d=a(d,i,s),e.picker.changeFocus(d).render()}function de(e){const t=e.picker.currentView.id;t!==e.config.maxView&&e.picker.changeView(t+1).render()}function oe(e){e.config.updateOnBlur?e.update({revert:!0}):e.refresh("input"),e.hide()}function ce(e,t){const i=e.picker,s=new Date(i.viewDate),n=i.currentView.id,a=1===n?u(s,t-s.getMonth()):f(s,t-s.getFullYear());i.changeFocus(a).changeView(n-1).render()}function le(e){const t=e.picker,i=c();if(1===e.config.todayBtnMode){if(e.config.autohide)return void e.setDate(i);e.setDate(i,{render:!1}),t.update()}t.viewDate!==i&&t.changeFocus(i),t.changeView(0).render()}function he(e){e.setDate({clear:!0})}function ue(e){de(e)}function fe(e){re(e,-1)}function pe(e){re(e,1)}function ge(e,t){const i=j(t,".datepicker-cell");if(!i||i.classList.contains("disabled"))return;const{id:s,isMinView:n}=e.picker.currentView;n?e.setDate(Number(i.dataset.date)):ce(e,Number(1===s?i.dataset.month:i.dataset.year))}function me(e){e.preventDefault()}const we=["left","top","right","bottom"].reduce(((e,t)=>(e[t]=`datepicker-orient-${t}`,e)),{}),ye=e=>e?`${e}px`:e;function De(t,i){if(void 0!==i.title&&(i.title?(t.controls.title.textContent=i.title,B(t.controls.title)):(t.controls.title.textContent="",L(t.controls.title))),i.prevArrow){const e=t.controls.prevBtn;Y(e),i.prevArrow.forEach((t=>{e.appendChild(t.cloneNode(!0))}))}if(i.nextArrow){const e=t.controls.nextBtn;Y(e),i.nextArrow.forEach((t=>{e.appendChild(t.cloneNode(!0))}))}if(i.locale&&(t.controls.todayBtn.textContent=i.locale.today,t.controls.clearBtn.textContent=i.locale.clear),void 0!==i.todayBtn&&(i.todayBtn?B(t.controls.todayBtn):L(t.controls.todayBtn)),e(i,"minDate")||e(i,"maxDate")){const{minDate:e,maxDate:i}=t.datepicker.config;t.controls.todayBtn.disabled=!n(c(),e,i)}void 0!==i.clearBtn&&(i.clearBtn?B(t.controls.clearBtn):L(t.controls.clearBtn))}function ve(e){const{dates:i,config:s}=e;return a(i.length>0?t(i):s.defaultViewDate,s.minDate,s.maxDate)}function be(e,t){const i=new Date(e.viewDate),s=new Date(t),{id:n,year:a,first:r,last:d}=e.currentView,o=s.getFullYear();switch(e.viewDate=t,o!==i.getFullYear()&&ae(e.datepicker,"changeYear"),s.getMonth()!==i.getMonth()&&ae(e.datepicker,"changeMonth"),n){case 0:return td;case 1:return o!==a;default:return od}}function ke(e){return window.getComputedStyle(e).direction}function xe(e){const t=V(e);if(t!==document.body&&t)return"visible"!==window.getComputedStyle(t).overflow?t:xe(t)}class Me{constructor(e){const{config:t}=this.datepicker=e,i=G.replace(/%buttonClass%/g,t.buttonClass),s=this.element=F(i).firstChild,[n,a,r]=s.firstChild.children,d=n.firstElementChild,[o,c,l]=n.lastElementChild.children,[h,u]=r.firstChild.children,f={title:d,prevBtn:o,viewSwitch:c,nextBtn:l,todayBtn:h,clearBtn:u};this.main=a,this.controls=f;const p=e.inline?"inline":"dropdown";s.classList.add(`datepicker-${p}`),De(this,t),this.viewDate=ve(e),T(e,[[s,"mousedown",me],[a,"click",ge.bind(null,e)],[f.viewSwitch,"click",ue.bind(null,e)],[f.prevBtn,"click",fe.bind(null,e)],[f.nextBtn,"click",pe.bind(null,e)],[f.todayBtn,"click",le.bind(null,e)],[f.clearBtn,"click",he.bind(null,e)]]),this.views=[new te(this),new se(this),new ne(this,{id:2,name:"years",cellClass:"year",step:1}),new ne(this,{id:3,name:"decades",cellClass:"decade",step:10})],this.currentView=this.views[t.startView],this.currentView.render(),this.main.appendChild(this.currentView.element),t.container?t.container.appendChild(this.element):e.inputField.after(this.element)}setOptions(e){De(this,e),this.views.forEach((t=>{t.init(e,!1)})),this.currentView.render()}detach(){this.element.remove()}show(){if(this.active)return;const{datepicker:e,element:t}=this;if(e.inline)t.classList.add("active");else{const i=ke(e.inputField);i!==ke(V(t))?t.dir=i:t.dir&&t.removeAttribute("dir"),t.style.visiblity="hidden",t.classList.add("active"),this.place(),t.style.visiblity="",e.config.disableTouchKeyboard&&e.inputField.blur()}this.active=!0,ae(e,"show")}hide(){this.active&&(this.datepicker.exitEditMode(),this.element.classList.remove("active"),this.active=!1,ae(this.datepicker,"hide"))}place(){const{classList:e,offsetParent:t,style:i}=this.element,{config:s,inputField:n}=this.datepicker,{width:a,height:r}=this.element.getBoundingClientRect(),{left:d,top:o,right:c,bottom:l,width:h,height:u}=n.getBoundingClientRect();let{x:f,y:p}=s.orientation,g=d,m=o;if(t!==document.body&&t){const e=t.getBoundingClientRect();g-=e.left-t.scrollLeft,m-=e.top-t.scrollTop}else g+=window.scrollX,m+=window.scrollY;const w=xe(n);let y=0,D=0,{clientWidth:v,clientHeight:b}=document.documentElement;if(w){const e=w.getBoundingClientRect();e.top>0&&(D=e.top),e.left>0&&(y=e.left),e.rightv?(f="right",vD&&l+r>b?"top":"bottom"),"top"===p?m-=r:m+=u,e.remove(...Object.values(we)),e.add(we[f],we[p]),i.left=ye(g),i.top=ye(m)}setViewSwitchLabel(e){this.controls.viewSwitch.textContent=e}setPrevBtnDisabled(e){this.controls.prevBtn.disabled=e}setNextBtnDisabled(e){this.controls.nextBtn.disabled=e}changeView(e){const t=this.currentView,i=this.views[e];return i.id!==t.id&&(this.currentView=i,this._renderMethod="render",ae(this.datepicker,"changeView"),this.main.replaceChild(i.element,t.element)),this}changeFocus(e){return this._renderMethod=be(this,e)?"render":"refreshFocus",this.views.forEach((e=>{e.updateFocus()})),this}update(){const e=ve(this.datepicker);return this._renderMethod=be(this,e)?"render":"refresh",this.views.forEach((e=>{e.updateFocus(),e.updateSelection()})),this}render(e=!0){const t=e&&this._renderMethod||"render";delete this._renderMethod,this.currentView[t]()}}function Se(e,t,i,s,a,r){if(n(e,a,r)){if(s(e)){return Se(t(e,i),t,i,s,a,r)}return e}}function Ce(e,t,i,s){const n=e.picker,a=n.currentView,r=a.step||1;let d,o,c=n.viewDate;switch(a.id){case 0:c=s?h(c,7*i):t.ctrlKey||t.metaKey?f(c,i):h(c,i),d=h,o=e=>a.disabled.includes(e);break;case 1:c=u(c,s?4*i:i),d=u,o=e=>{const t=new Date(e),{year:i,disabled:s}=a;return t.getFullYear()===i&&s.includes(t.getMonth())};break;default:c=f(c,i*(s?4:1)*r),d=f,o=e=>a.disabled.includes(m(e,r))}c=Se(c,d,i<0?-r:r,o,a.minDate,a.maxDate),void 0!==c&&n.changeFocus(c).render()}function Oe(e,t){const i=t.key;if("Tab"===i)return void oe(e);const s=e.picker,{id:n,isMinView:a}=s.currentView;if(s.active){if(e.editMode)return void("Enter"===i?e.exitEditMode({update:!0,autohide:e.config.autohide}):"Escape"===i&&s.hide());if("ArrowLeft"===i)if(t.ctrlKey||t.metaKey)re(e,-1);else{if(t.shiftKey)return void e.enterEditMode();Ce(e,t,-1,!1)}else if("ArrowRight"===i)if(t.ctrlKey||t.metaKey)re(e,1);else{if(t.shiftKey)return void e.enterEditMode();Ce(e,t,1,!1)}else if("ArrowUp"===i)if(t.ctrlKey||t.metaKey)de(e);else{if(t.shiftKey)return void e.enterEditMode();Ce(e,t,-1,!0)}else if("ArrowDown"===i){if(t.shiftKey&&!t.ctrlKey&&!t.metaKey)return void e.enterEditMode();Ce(e,t,1,!0)}else{if("Enter"!==i)return void("Escape"===i?s.hide():"Backspace"!==i&&"Delete"!==i&&(1!==i.length||t.ctrlKey||t.metaKey)||e.enterEditMode());if(a)return void e.setDate(s.viewDate);s.changeView(n-1).render()}}else{if("ArrowDown"!==i)return void("Enter"===i?e.update():"Escape"===i&&s.show());s.show()}t.preventDefault()}function Ee(e){e.config.showOnFocus&&!e._showing&&e.show()}function Fe(e,t){const i=t.target;(e.picker.active||e.config.showOnClick)&&(i._active=N(i),i._clicking=setTimeout((()=>{delete i._active,delete i._clicking}),2e3))}function Ve(e,t){const i=t.target;i._clicking&&(clearTimeout(i._clicking),delete i._clicking,i._active&&e.enterEditMode(),delete i._active,e.config.showOnClick&&e.show())}function Ne(e,t){t.clipboardData.types.includes("text/plain")&&e.enterEditMode()}function Le(e,t){const{element:i,picker:s}=e;if(!s.active&&!N(i))return;const n=s.element;j(t,(e=>e===i||e===n))||oe(e)}function Be(e,t){return e.map((e=>O(e,t.format,t.locale))).join(t.dateDelimiter)}function Ye(e,t,i=!1){const{config:s,dates:a,rangeSideIndex:r}=e;if(0===t.length)return i?[]:void 0;let d=t.reduce(((e,t)=>{let i=C(t,s.format,s.locale);return void 0===i||(i=w(i,s.pickLevel,r),!n(i,s.minDate,s.maxDate)||e.includes(i)||s.datesDisabled.includes(i)||!(s.pickLevel>0)&&s.daysOfWeekDisabled.includes(new Date(i).getDay())||e.push(i)),e}),[]);return 0!==d.length?(s.multidate&&!i&&(d=d.reduce(((e,t)=>(a.includes(t)||e.push(t),e)),a.filter((e=>!d.includes(e))))),s.maxNumberOfDates&&d.length>s.maxNumberOfDates?d.slice(-1*s.maxNumberOfDates):d):void 0}function Ae(e,t=3,i=!0){const{config:s,picker:n,inputField:a}=e;if(2&t){const e=n.active?s.pickLevel:s.startView;n.update().changeView(e).render(i)}1&t&&a&&(a.value=Be(e.dates,s))}function We(e,t,i){let{clear:s,render:n,autohide:a,revert:r}=i;void 0===n&&(n=!0),n?void 0===a&&(a=e.config.autohide):a=!1;const d=Ye(e,t,s);(d||r)&&(d&&d.toString()!==e.dates.toString()?(e.dates=d,Ae(e,n?3:1),ae(e,"changeDate")):Ae(e,1),a&&e.hide())}return class{constructor(e,t={},i){e.datepicker=this,this.element=e;const n=this.config=Object.assign({buttonClass:t.buttonClass&&String(t.buttonClass)||"button",container:null,defaultViewDate:c(),maxDate:void 0,minDate:void 0},X(_,this)),a=this.inline="INPUT"!==e.tagName;let r,d;if(a?n.container=e:(t.container&&(n.container=t.container instanceof HTMLElement?t.container:document.querySelector(t.container)),r=this.inputField=e,r.classList.add("datepicker-input")),i){const e=i.inputs.indexOf(r),t=i.datepickers;if(e<0||e>1||!Array.isArray(t))throw Error("Invalid rangepicker object.");t[e]=this,Object.defineProperty(this,"rangepicker",{get:()=>i}),Object.defineProperty(this,"rangeSideIndex",{get:()=>e})}this._options=t,Object.assign(n,X(t,this)),a?(d=s(e.dataset.date,n.dateDelimiter),delete e.dataset.date):d=s(r.value,n.dateDelimiter),this.dates=[];const o=Ye(this,d);o&&o.length>0&&(this.dates=o),r&&(r.value=Be(this.dates,n));const l=this.picker=new Me(this);if(a)this.show();else{const e=Le.bind(null,this);T(this,[[r,"keydown",Oe.bind(null,this)],[r,"focus",Ee.bind(null,this)],[r,"mousedown",Fe.bind(null,this)],[r,"click",Ve.bind(null,this)],[r,"paste",Ne.bind(null,this)],[document,"mousedown",e],[document,"touchstart",e],[window,"resize",l.place.bind(l)]])}}static formatDate(e,t,i){return O(e,t,i&&$[i]||$.en)}static parseDate(e,t,i){return C(e,t,i&&$[i]||$.en)}static get locales(){return $}get active(){return!(!this.picker||!this.picker.active)}get pickerElement(){return this.picker?this.picker.element:void 0}setOptions(e){const t=this.picker,i=X(e,this);Object.assign(this._options,e),Object.assign(this.config,i),t.setOptions(i),Ae(this,3)}show(){if(this.inputField){if(this.inputField.disabled)return;N(this.inputField)||this.config.disableTouchKeyboard||(this._showing=!0,this.inputField.focus(),delete this._showing)}this.picker.show()}hide(){this.inline||(this.picker.hide(),this.picker.update().changeView(this.config.startView).render())}destroy(){return this.hide(),function(e){let t=A.get(e);t&&(t.forEach((e=>{H.call(...e)})),A.delete(e))}(this),this.picker.detach(),this.inline||this.inputField.classList.remove("datepicker-input"),delete this.element.datepicker,this}getDate(e){const t=e?t=>O(t,e,this.config.locale):e=>new Date(e);return this.config.multidate?this.dates.map(t):this.dates.length>0?t(this.dates[0]):void 0}setDate(...e){const i=[...e],s={},n=t(e);"object"!=typeof n||Array.isArray(n)||n instanceof Date||!n||Object.assign(s,i.pop());We(this,Array.isArray(i[0])?i[0]:i,s)}update(e){if(this.inline)return;const t=Object.assign(e||{},{clear:!0,render:!0});We(this,s(this.inputField.value,this.config.dateDelimiter),t)}refresh(e,t=!1){let i;e&&"string"!=typeof e&&(t=e,e=void 0),i="picker"===e?2:"input"===e?1:3,Ae(this,i,!t)}enterEditMode(){this.inline||!this.picker.active||this.editMode||(this.editMode=!0,this.inputField.classList.add("in-edit"))}exitEditMode(e){if(this.inline||!this.editMode)return;const t=Object.assign({update:!1},e);delete this.editMode,this.inputField.classList.remove("in-edit"),t.update&&this.update(t)}}}();
\ No newline at end of file
diff --git a/src/ui/static/js/datepicker/events/functions.js b/src/ui/static/js/datepicker/events/functions.js
new file mode 100644
index 000000000..c0853017a
--- /dev/null
+++ b/src/ui/static/js/datepicker/events/functions.js
@@ -0,0 +1,48 @@
+import {limitToRange} from '../lib/utils.js';
+import {addMonths, addYears} from '../lib/date.js';
+
+export function triggerDatepickerEvent(datepicker, type) {
+ const detail = {
+ date: datepicker.getDate(),
+ viewDate: new Date(datepicker.picker.viewDate),
+ viewId: datepicker.picker.currentView.id,
+ datepicker,
+ };
+ datepicker.element.dispatchEvent(new CustomEvent(type, {detail}));
+}
+
+// direction: -1 (to previous), 1 (to next)
+export function goToPrevOrNext(datepicker, direction) {
+ const {minDate, maxDate} = datepicker.config;
+ const {currentView, viewDate} = datepicker.picker;
+ let newViewDate;
+ switch (currentView.id) {
+ case 0:
+ newViewDate = addMonths(viewDate, direction);
+ break;
+ case 1:
+ newViewDate = addYears(viewDate, direction);
+ break;
+ default:
+ newViewDate = addYears(viewDate, direction * currentView.navStep);
+ }
+ newViewDate = limitToRange(newViewDate, minDate, maxDate);
+ datepicker.picker.changeFocus(newViewDate).render();
+}
+
+export function switchView(datepicker) {
+ const viewId = datepicker.picker.currentView.id;
+ if (viewId === datepicker.config.maxView) {
+ return;
+ }
+ datepicker.picker.changeView(viewId + 1).render();
+}
+
+export function unfocus(datepicker) {
+ if (datepicker.config.updateOnBlur) {
+ datepicker.update({revert: true});
+ } else {
+ datepicker.refresh('input');
+ }
+ datepicker.hide();
+}
diff --git a/src/ui/static/js/datepicker/events/inputFieldListeners.js b/src/ui/static/js/datepicker/events/inputFieldListeners.js
new file mode 100644
index 000000000..acc9cc2a9
--- /dev/null
+++ b/src/ui/static/js/datepicker/events/inputFieldListeners.js
@@ -0,0 +1,195 @@
+import {isInRange} from '../lib/utils.js';
+import {isActiveElement} from '../lib/dom.js';
+import {addDays, addMonths, addYears, startOfYearPeriod} from '../lib/date.js';
+import {goToPrevOrNext, switchView, unfocus} from './functions.js';
+
+// Find the closest date that doesn't meet the condition for unavailable date
+// Returns undefined if no available date is found
+// addFn: function to calculate the next date
+// - args: time value, amount
+// increase: amount to pass to addFn
+// testFn: function to test the unavailablity of the date
+// - args: time value; retun: true if unavailable
+function findNextAvailableOne(date, addFn, increase, testFn, min, max) {
+ if (!isInRange(date, min, max)) {
+ return;
+ }
+ if (testFn(date)) {
+ const newDate = addFn(date, increase);
+ return findNextAvailableOne(newDate, addFn, increase, testFn, min, max);
+ }
+ return date;
+}
+
+// direction: -1 (left/up), 1 (right/down)
+// vertical: true for up/down, false for left/right
+function moveByArrowKey(datepicker, ev, direction, vertical) {
+ const picker = datepicker.picker;
+ const currentView = picker.currentView;
+ const step = currentView.step || 1;
+ let viewDate = picker.viewDate;
+ let addFn;
+ let testFn;
+ switch (currentView.id) {
+ case 0:
+ if (vertical) {
+ viewDate = addDays(viewDate, direction * 7);
+ } else if (ev.ctrlKey || ev.metaKey) {
+ viewDate = addYears(viewDate, direction);
+ } else {
+ viewDate = addDays(viewDate, direction);
+ }
+ addFn = addDays;
+ testFn = (date) => currentView.disabled.includes(date);
+ break;
+ case 1:
+ viewDate = addMonths(viewDate, vertical ? direction * 4 : direction);
+ addFn = addMonths;
+ testFn = (date) => {
+ const dt = new Date(date);
+ const {year, disabled} = currentView;
+ return dt.getFullYear() === year && disabled.includes(dt.getMonth());
+ };
+ break;
+ default:
+ viewDate = addYears(viewDate, direction * (vertical ? 4 : 1) * step);
+ addFn = addYears;
+ testFn = date => currentView.disabled.includes(startOfYearPeriod(date, step));
+ }
+ viewDate = findNextAvailableOne(
+ viewDate,
+ addFn,
+ direction < 0 ? -step : step,
+ testFn,
+ currentView.minDate,
+ currentView.maxDate
+ );
+ if (viewDate !== undefined) {
+ picker.changeFocus(viewDate).render();
+ }
+}
+
+export function onKeydown(datepicker, ev) {
+ const key = ev.key;
+ if (key === 'Tab') {
+ unfocus(datepicker);
+ return;
+ }
+
+ const picker = datepicker.picker;
+ const {id, isMinView} = picker.currentView;
+ if (!picker.active) {
+ if (key === 'ArrowDown') {
+ picker.show();
+ } else {
+ if (key === 'Enter') {
+ datepicker.update();
+ } else if (key === 'Escape') {
+ picker.show();
+ }
+ return;
+ }
+ } else if (datepicker.editMode) {
+ if (key === 'Enter') {
+ datepicker.exitEditMode({update: true, autohide: datepicker.config.autohide});
+ } else if (key === 'Escape') {
+ picker.hide();
+ }
+ return;
+ } else {
+ if (key === 'ArrowLeft') {
+ if (ev.ctrlKey || ev.metaKey) {
+ goToPrevOrNext(datepicker, -1);
+ } else if (ev.shiftKey) {
+ datepicker.enterEditMode();
+ return;
+ } else {
+ moveByArrowKey(datepicker, ev, -1, false);
+ }
+ } else if (key === 'ArrowRight') {
+ if (ev.ctrlKey || ev.metaKey) {
+ goToPrevOrNext(datepicker, 1);
+ } else if (ev.shiftKey) {
+ datepicker.enterEditMode();
+ return;
+ } else {
+ moveByArrowKey(datepicker, ev, 1, false);
+ }
+ } else if (key === 'ArrowUp') {
+ if (ev.ctrlKey || ev.metaKey) {
+ switchView(datepicker);
+ } else if (ev.shiftKey) {
+ datepicker.enterEditMode();
+ return;
+ } else {
+ moveByArrowKey(datepicker, ev, -1, true);
+ }
+ } else if (key === 'ArrowDown') {
+ if (ev.shiftKey && !ev.ctrlKey && !ev.metaKey) {
+ datepicker.enterEditMode();
+ return;
+ }
+ moveByArrowKey(datepicker, ev, 1, true);
+ } else if (key === 'Enter') {
+ if (isMinView) {
+ datepicker.setDate(picker.viewDate);
+ return;
+ }
+ picker.changeView(id - 1).render();
+ } else {
+ if (key === 'Escape') {
+ picker.hide();
+ } else if (
+ key === 'Backspace'
+ || key === 'Delete'
+ || (key.length === 1 && !ev.ctrlKey && !ev.metaKey)
+ ) {
+ datepicker.enterEditMode();
+ }
+ return;
+ }
+ }
+ ev.preventDefault();
+}
+
+export function onFocus(datepicker) {
+ if (datepicker.config.showOnFocus && !datepicker._showing) {
+ datepicker.show();
+ }
+}
+
+// for the prevention for entering edit mode while getting focus on click
+export function onMousedown(datepicker, ev) {
+ const el = ev.target;
+ if (datepicker.picker.active || datepicker.config.showOnClick) {
+ el._active = isActiveElement(el);
+ el._clicking = setTimeout(() => {
+ delete el._active;
+ delete el._clicking;
+ }, 2000);
+ }
+}
+
+export function onClickInput(datepicker, ev) {
+ const el = ev.target;
+ if (!el._clicking) {
+ return;
+ }
+ clearTimeout(el._clicking);
+ delete el._clicking;
+
+ if (el._active) {
+ datepicker.enterEditMode();
+ }
+ delete el._active;
+
+ if (datepicker.config.showOnClick) {
+ datepicker.show();
+ }
+}
+
+export function onPaste(datepicker, ev) {
+ if (ev.clipboardData.types.includes('text/plain')) {
+ datepicker.enterEditMode();
+ }
+}
diff --git a/src/ui/static/js/datepicker/events/otherListeners.js b/src/ui/static/js/datepicker/events/otherListeners.js
new file mode 100644
index 000000000..d25b5daa3
--- /dev/null
+++ b/src/ui/static/js/datepicker/events/otherListeners.js
@@ -0,0 +1,20 @@
+import {isActiveElement} from '../lib/dom.js';
+import {findElementInEventPath} from '../lib/event.js';
+import {unfocus} from './functions.js';
+
+// for the `document` to delegate the events from outside the picker/input field
+export function onClickOutside(datepicker, ev) {
+ const {element, picker} = datepicker;
+ // check both picker's and input's activeness to make updateOnBlur work in
+ // the cases where...
+ // - picker is hidden by ESC key press → input stays focused
+ // - input is unfocused by closing mobile keyboard → piker is kept shown
+ if (!picker.active && !isActiveElement(element)) {
+ return;
+ }
+ const pickerElem = picker.element;
+ if (findElementInEventPath(ev, el => el === element || el === pickerElem)) {
+ return;
+ }
+ unfocus(datepicker);
+}
diff --git a/src/ui/static/js/datepicker/events/pickerListeners.js b/src/ui/static/js/datepicker/events/pickerListeners.js
new file mode 100644
index 000000000..3deff58c1
--- /dev/null
+++ b/src/ui/static/js/datepicker/events/pickerListeners.js
@@ -0,0 +1,68 @@
+import {today, addMonths, addYears} from '../lib/date.js';
+import {findElementInEventPath} from '../lib/event.js';
+import {goToPrevOrNext, switchView} from './functions.js';
+
+function goToSelectedMonthOrYear(datepicker, selection) {
+ const picker = datepicker.picker;
+ const viewDate = new Date(picker.viewDate);
+ const viewId = picker.currentView.id;
+ const newDate = viewId === 1
+ ? addMonths(viewDate, selection - viewDate.getMonth())
+ : addYears(viewDate, selection - viewDate.getFullYear());
+
+ picker.changeFocus(newDate).changeView(viewId - 1).render();
+}
+
+export function onClickTodayBtn(datepicker) {
+ const picker = datepicker.picker;
+ const currentDate = today();
+ if (datepicker.config.todayBtnMode === 1) {
+ if (datepicker.config.autohide) {
+ datepicker.setDate(currentDate);
+ return;
+ }
+ datepicker.setDate(currentDate, {render: false});
+ picker.update();
+ }
+ if (picker.viewDate !== currentDate) {
+ picker.changeFocus(currentDate);
+ }
+ picker.changeView(0).render();
+}
+
+export function onClickClearBtn(datepicker) {
+ datepicker.setDate({clear: true});
+}
+
+export function onClickViewSwitch(datepicker) {
+ switchView(datepicker);
+}
+
+export function onClickPrevBtn(datepicker) {
+ goToPrevOrNext(datepicker, -1);
+}
+
+export function onClickNextBtn(datepicker) {
+ goToPrevOrNext(datepicker, 1);
+}
+
+// For the picker's main block to delegete the events from `datepicker-cell`s
+export function onClickView(datepicker, ev) {
+ const target = findElementInEventPath(ev, '.datepicker-cell');
+ if (!target || target.classList.contains('disabled')) {
+ return;
+ }
+
+ const {id, isMinView} = datepicker.picker.currentView;
+ if (isMinView) {
+ datepicker.setDate(Number(target.dataset.date));
+ } else if (id === 1) {
+ goToSelectedMonthOrYear(datepicker, Number(target.dataset.month));
+ } else {
+ goToSelectedMonthOrYear(datepicker, Number(target.dataset.year));
+ }
+}
+
+export function onMousedownPicker(ev) {
+ ev.preventDefault();
+}
diff --git a/src/ui/static/js/datepicker/i18n/base-locales.js b/src/ui/static/js/datepicker/i18n/base-locales.js
new file mode 100644
index 000000000..96bd963d7
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/base-locales.js
@@ -0,0 +1,13 @@
+// default locales
+export const locales = {
+ en: {
+ days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
+ daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
+ daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"],
+ months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
+ monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
+ today: "Today",
+ clear: "Clear",
+ titleFormat: "MM y"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/ar-DZ.js b/src/ui/static/js/datepicker/i18n/locales/ar-DZ.js
new file mode 100644
index 000000000..0a9269d91
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/ar-DZ.js
@@ -0,0 +1,19 @@
+/**
+ * Arabic-Algeria translation for bootstrap-datepicker
+ * Rabah Saadi
+ */
+export default {
+ 'ar-DZ': {
+ days: ["الأحد", "الاثنين", "الثلاثاء", "الأربعاء", "الخميس", "الجمعة", "السبت", "الأحد"],
+ daysShort: ["أحد", "اثنين", "ثلاثاء", "أربعاء", "خميس", "جمعة", "سبت", "أحد"],
+ daysMin: ["ح", "ن", "ث", "ع", "خ", "ج", "س", "ح"],
+ months: ["جانفي","فيفري","مارس","أفريل","ماي","جوان","جويليه","أوت","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],
+ monthsShort: ["جانفي","فيفري","مارس","أفريل","ماي","جوان","جويليه","أوت","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],
+ today: "هذا اليوم",
+ rtl: true,
+ monthsTitle: "أشهر",
+ clear: "إزالة",
+ format: "yyyy/mm/dd",
+ weekStart: 0
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/ar-tn.js b/src/ui/static/js/datepicker/i18n/locales/ar-tn.js
new file mode 100644
index 000000000..5a3b6af8e
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/ar-tn.js
@@ -0,0 +1,15 @@
+/**
+ * Arabic-Tunisia translation for bootstrap-datepicker
+ * Souhaieb Besbes
+ */
+export default {
+ 'ar-tn': {
+ days: ["الأحد", "الاثنين", "الثلاثاء", "الأربعاء", "الخميس", "الجمعة", "السبت", "الأحد"],
+ daysShort: ["أحد", "اثنين", "ثلاثاء", "أربعاء", "خميس", "جمعة", "سبت", "أحد"],
+ daysMin: ["ح", "ن", "ث", "ع", "خ", "ج", "س", "ح"],
+ months: ["جانفي","فيفري","مارس","أفريل","ماي","جوان","جويليه","أوت","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],
+ monthsShort: ["جانفي","فيفري","مارس","أفريل","ماي","جوان","جويليه","أوت","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],
+ today: "هذا اليوم",
+ rtl: true
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/ar.js b/src/ui/static/js/datepicker/i18n/locales/ar.js
new file mode 100644
index 000000000..3ee311fe2
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/ar.js
@@ -0,0 +1,15 @@
+/**
+ * Arabic translation for bootstrap-datepicker
+ * Mohammed Alshehri
+ */
+export default {
+ ar: {
+ days: ["الأحد", "الاثنين", "الثلاثاء", "الأربعاء", "الخميس", "الجمعة", "السبت", "الأحد"],
+ daysShort: ["أحد", "اثنين", "ثلاثاء", "أربعاء", "خميس", "جمعة", "سبت", "أحد"],
+ daysMin: ["ح", "ن", "ث", "ع", "خ", "ج", "س", "ح"],
+ months: ["يناير", "فبراير", "مارس", "أبريل", "مايو", "يونيو", "يوليو", "أغسطس", "سبتمبر", "أكتوبر", "نوفمبر", "ديسمبر"],
+ monthsShort: ["يناير", "فبراير", "مارس", "أبريل", "مايو", "يونيو", "يوليو", "أغسطس", "سبتمبر", "أكتوبر", "نوفمبر", "ديسمبر"],
+ today: "هذا اليوم",
+ rtl: true
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/az.js b/src/ui/static/js/datepicker/i18n/locales/az.js
new file mode 100644
index 000000000..52c38bb8d
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/az.js
@@ -0,0 +1,14 @@
+// Azerbaijani
+export default {
+ az: {
+ days: ["Bazar", "Bazar ertəsi", "Çərşənbə axşamı", "Çərşənbə", "Cümə axşamı", "Cümə", "Şənbə"],
+ daysShort: ["B.", "B.e", "Ç.a", "Ç.", "C.a", "C.", "Ş."],
+ daysMin: ["B.", "B.e", "Ç.a", "Ç.", "C.a", "C.", "Ş."],
+ months: ["Yanvar", "Fevral", "Mart", "Aprel", "May", "İyun", "İyul", "Avqust", "Sentyabr", "Oktyabr", "Noyabr", "Dekabr"],
+ monthsShort: ["Yan", "Fev", "Mar", "Apr", "May", "İyun", "İyul", "Avq", "Sen", "Okt", "Noy", "Dek"],
+ today: "Bu gün",
+ weekStart: 1,
+ clear: "Təmizlə",
+ monthsTitle: 'Aylar'
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/bg.js b/src/ui/static/js/datepicker/i18n/locales/bg.js
new file mode 100644
index 000000000..a667db287
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/bg.js
@@ -0,0 +1,14 @@
+/**
+ * Bulgarian translation for bootstrap-datepicker
+ * Apostol Apostolov
+ */
+export default {
+ bg: {
+ days: ["Неделя", "Понеделник", "Вторник", "Сряда", "Четвъртък", "Петък", "Събота"],
+ daysShort: ["Нед", "Пон", "Вто", "Сря", "Чет", "Пет", "Съб"],
+ daysMin: ["Н", "П", "В", "С", "Ч", "П", "С"],
+ months: ["Януари", "Февруари", "Март", "Април", "Май", "Юни", "Юли", "Август", "Септември", "Октомври", "Ноември", "Декември"],
+ monthsShort: ["Ян", "Фев", "Мар", "Апр", "Май", "Юни", "Юли", "Авг", "Сеп", "Окт", "Ное", "Дек"],
+ today: "днес"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/bm.js b/src/ui/static/js/datepicker/i18n/locales/bm.js
new file mode 100644
index 000000000..92bcdbbc5
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/bm.js
@@ -0,0 +1,18 @@
+/**
+ * Bamanankan (bm) translation for bootstrap-datepicker
+ * Fatou Fall
+ */
+export default {
+ bm: {
+ days: ["Kari","Ntɛnɛn","Tarata","Araba","Alamisa","Juma","Sibiri"],
+ daysShort: ["Kar","Ntɛ","Tar","Ara","Ala","Jum","Sib"],
+ daysMin: ["Ka","Nt","Ta","Ar","Al","Ju","Si"],
+ months: ["Zanwuyekalo","Fewuruyekalo","Marisikalo","Awirilikalo","Mɛkalo","Zuwɛnkalo","Zuluyekalo","Utikalo","Sɛtanburukalo","ɔkutɔburukalo","Nowanburukalo","Desanburukalo"],
+ monthsShort: ["Zan","Few","Mar","Awi","Mɛ","Zuw","Zul","Uti","Sɛt","ɔku","Now","Des"],
+ today: "Bi",
+ monthsTitle: "Kalo",
+ clear: "Ka jɔsi",
+ weekStart: 1,
+ format: "dd/mm/yyyy"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/bn.js b/src/ui/static/js/datepicker/i18n/locales/bn.js
new file mode 100644
index 000000000..94aca096d
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/bn.js
@@ -0,0 +1,19 @@
+/**
+ * Bengali (Bangla) translation for bootstrap-datepicker
+ * Karim Khan
+ * Orif N. Jr.
+ */
+export default {
+ bn: {
+ days: ["রবিবার","সোমবার","মঙ্গলবার","বুধবার","বৃহস্পতিবার","শুক্রবার","শনিবার"],
+ daysShort: ["রবিবার","সোমবার","মঙ্গলবার","বুধবার","বৃহস্পতিবার","শুক্রবার","শনিবার"],
+ daysMin: ["রবি","সোম","মঙ্গল","বুধ","বৃহস্পতি","শুক্র","শনি"],
+ months: ["জানুয়ারী","ফেব্রুয়ারি","মার্চ","এপ্রিল","মে","জুন","জুলাই","অগাস্ট","সেপ্টেম্বর","অক্টোবর","নভেম্বর","ডিসেম্বর"],
+ monthsShort: ["জানুয়ারী","ফেব্রুয়ারি","মার্চ","এপ্রিল","মে","জুন","জুলাই","অগাস্ট","সেপ্টেম্বর","অক্টোবর","নভেম্বর","ডিসেম্বর"],
+ today: "আজ",
+ monthsTitle: "মাস",
+ clear: "পরিষ্কার",
+ weekStart: 0,
+ format: "mm/dd/yyyy"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/br.js b/src/ui/static/js/datepicker/i18n/locales/br.js
new file mode 100644
index 000000000..39ca7a7ea
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/br.js
@@ -0,0 +1,18 @@
+/**
+ * Breton translation for bootstrap-datepicker
+ * Gwenn Meynier
+ */
+export default {
+ br: {
+ days: ["Sul", "Lun", "Meurzh", "Merc'her", "Yaou", "Gwener", "Sadorn"],
+ daysShort: ["Sul", "Lun", "Meu.", "Mer.", "Yao.", "Gwe.", "Sad."],
+ daysMin: ["Su", "L", "Meu", "Mer", "Y", "G", "Sa"],
+ months: ["Genver", "C'hwevrer", "Meurzh", "Ebrel", "Mae", "Mezheven", "Gouere", "Eost", "Gwengolo", "Here", "Du", "Kerzu"],
+ monthsShort: ["Genv.", "C'hw.", "Meur.", "Ebre.", "Mae", "Mezh.", "Goue.", "Eost", "Gwen.", "Here", "Du", "Kerz."],
+ today: "Hiziv",
+ monthsTitle: "Miz",
+ clear: "Dilemel",
+ weekStart: 1,
+ format: "dd/mm/yyyy"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/bs.js b/src/ui/static/js/datepicker/i18n/locales/bs.js
new file mode 100644
index 000000000..47b7fa49c
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/bs.js
@@ -0,0 +1,15 @@
+/**
+ * Bosnian translation for bootstrap-datepicker
+ */
+export default {
+ bs: {
+ days: ["Nedjelja","Ponedjeljak", "Utorak", "Srijeda", "Četvrtak", "Petak", "Subota"],
+ daysShort: ["Ned", "Pon", "Uto", "Sri", "Čet", "Pet", "Sub"],
+ daysMin: ["N", "Po", "U", "Sr", "Č", "Pe", "Su"],
+ months: ["Januar", "Februar", "Mart", "April", "Maj", "Juni", "Juli", "August", "Septembar", "Oktobar", "Novembar", "Decembar"],
+ monthsShort: ["Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec"],
+ today: "Danas",
+ weekStart: 1,
+ format: "dd.mm.yyyy"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/ca.js b/src/ui/static/js/datepicker/i18n/locales/ca.js
new file mode 100644
index 000000000..9260b6071
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/ca.js
@@ -0,0 +1,18 @@
+/**
+ * Catalan translation for bootstrap-datepicker
+ * J. Garcia
+ */
+export default {
+ ca: {
+ days: ["diumenge", "dilluns", "dimarts", "dimecres", "dijous", "divendres", "dissabte"],
+ daysShort: ["dg.", "dl.", "dt.", "dc.", "dj.", "dv.", "ds."],
+ daysMin: ["dg", "dl", "dt", "dc", "dj", "dv", "ds"],
+ months: ["gener", "febrer", "març", "abril", "maig", "juny", "juliol", "agost", "setembre", "octubre", "novembre", "desembre"],
+ monthsShort: ["gen.", "febr.", "març", "abr.", "maig", "juny", "jul.", "ag.", "set.", "oct.", "nov.", "des."],
+ today: "Avui",
+ monthsTitle: "Mesos",
+ clear: "Esborra",
+ weekStart: 1,
+ format: "dd/mm/yyyy"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/cs.js b/src/ui/static/js/datepicker/i18n/locales/cs.js
new file mode 100644
index 000000000..ac3e584af
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/cs.js
@@ -0,0 +1,19 @@
+/**
+ * Czech translation for bootstrap-datepicker
+ * Matěj Koubík
+ * Fixes by Michal Remiš
+ */
+export default {
+ cs: {
+ days: ["Neděle", "Pondělí", "Úterý", "Středa", "Čtvrtek", "Pátek", "Sobota"],
+ daysShort: ["Ned", "Pon", "Úte", "Stř", "Čtv", "Pát", "Sob"],
+ daysMin: ["Ne", "Po", "Út", "St", "Čt", "Pá", "So"],
+ months: ["Leden", "Únor", "Březen", "Duben", "Květen", "Červen", "Červenec", "Srpen", "Září", "Říjen", "Listopad", "Prosinec"],
+ monthsShort: ["Led", "Úno", "Bře", "Dub", "Kvě", "Čer", "Čnc", "Srp", "Zář", "Říj", "Lis", "Pro"],
+ today: "Dnes",
+ clear: "Vymazat",
+ monthsTitle: "Měsíc",
+ weekStart: 1,
+ format: "dd.mm.yyyy"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/cy.js b/src/ui/static/js/datepicker/i18n/locales/cy.js
new file mode 100644
index 000000000..0efd1a695
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/cy.js
@@ -0,0 +1,14 @@
+/**
+ * Welsh translation for bootstrap-datepicker
+ * S. Morris
+ */
+export default {
+ cy: {
+ days: ["Sul", "Llun", "Mawrth", "Mercher", "Iau", "Gwener", "Sadwrn"],
+ daysShort: ["Sul", "Llu", "Maw", "Mer", "Iau", "Gwe", "Sad"],
+ daysMin: ["Su", "Ll", "Ma", "Me", "Ia", "Gwe", "Sa"],
+ months: ["Ionawr", "Chewfror", "Mawrth", "Ebrill", "Mai", "Mehefin", "Gorfennaf", "Awst", "Medi", "Hydref", "Tachwedd", "Rhagfyr"],
+ monthsShort: ["Ion", "Chw", "Maw", "Ebr", "Mai", "Meh", "Gor", "Aws", "Med", "Hyd", "Tach", "Rha"],
+ today: "Heddiw"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/da.js b/src/ui/static/js/datepicker/i18n/locales/da.js
new file mode 100644
index 000000000..5bbdbec1e
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/da.js
@@ -0,0 +1,19 @@
+/**
+ * Danish translation for bootstrap-datepicker
+ * Christian Pedersen
+ * Ivan Mylyanyk
+ */
+export default {
+ da: {
+ days: ["Søndag", "Mandag", "Tirsdag", "Onsdag", "Torsdag", "Fredag", "Lørdag"],
+ daysShort: ["Søn", "Man", "Tir", "Ons", "Tor", "Fre", "Lør"],
+ daysMin: ["Sø", "Ma", "Ti", "On", "To", "Fr", "Lø"],
+ months: ["Januar", "Februar", "Marts", "April", "Maj", "Juni", "Juli", "August", "September", "Oktober", "November", "December"],
+ monthsShort: ["Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec"],
+ today: "I Dag",
+ weekStart: 1,
+ clear: "Nulstil",
+ format: "dd/mm/yyyy",
+ monthsTitle: "Måneder"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/de.js b/src/ui/static/js/datepicker/i18n/locales/de.js
new file mode 100644
index 000000000..bd0f5dd4a
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/de.js
@@ -0,0 +1,18 @@
+/**
+ * German translation for bootstrap-datepicker
+ * Sam Zurcher
+ */
+export default {
+ de: {
+ days: ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"],
+ daysShort: ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"],
+ daysMin: ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"],
+ months: ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"],
+ monthsShort: ["Jan", "Feb", "Mär", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"],
+ today: "Heute",
+ monthsTitle: "Monate",
+ clear: "Löschen",
+ weekStart: 1,
+ format: "dd.mm.yyyy"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/el.js b/src/ui/static/js/datepicker/i18n/locales/el.js
new file mode 100644
index 000000000..4a3f2df3b
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/el.js
@@ -0,0 +1,16 @@
+/**
+ * Greek translation for bootstrap-datepicker
+ */
+export default {
+ el: {
+ days: ["Κυριακή", "Δευτέρα", "Τρίτη", "Τετάρτη", "Πέμπτη", "Παρασκευή", "Σάββατο"],
+ daysShort: ["Κυρ", "Δευ", "Τρι", "Τετ", "Πεμ", "Παρ", "Σαβ"],
+ daysMin: ["Κυ", "Δε", "Τρ", "Τε", "Πε", "Πα", "Σα"],
+ months: ["Ιανουάριος", "Φεβρουάριος", "Μάρτιος", "Απρίλιος", "Μάιος", "Ιούνιος", "Ιούλιος", "Αύγουστος", "Σεπτέμβριος", "Οκτώβριος", "Νοέμβριος", "Δεκέμβριος"],
+ monthsShort: ["Ιαν", "Φεβ", "Μαρ", "Απρ", "Μάι", "Ιουν", "Ιουλ", "Αυγ", "Σεπ", "Οκτ", "Νοε", "Δεκ"],
+ today: "Σήμερα",
+ clear: "Καθαρισμός",
+ weekStart: 1,
+ format: "d/m/yyyy"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/en-AU.js b/src/ui/static/js/datepicker/i18n/locales/en-AU.js
new file mode 100644
index 000000000..cddae4086
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/en-AU.js
@@ -0,0 +1,18 @@
+/**
+ * Australian English translation for bootstrap-datepicker
+ * Steve Chapman
+ */
+export default {
+ 'en-AU': {
+ days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
+ daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
+ daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"],
+ months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
+ monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
+ today: "Today",
+ monthsTitle: "Months",
+ clear: "Clear",
+ weekStart: 1,
+ format: "d/mm/yyyy"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/en-CA.js b/src/ui/static/js/datepicker/i18n/locales/en-CA.js
new file mode 100644
index 000000000..aeef9b690
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/en-CA.js
@@ -0,0 +1,18 @@
+/**
+ * Canadian English translation for bootstrap-datepicker
+ * Mike Nacey
+ */
+export default {
+ 'en-CA': {
+ days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
+ daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
+ daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"],
+ months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
+ monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
+ today: "Today",
+ monthsTitle: "Months",
+ clear: "Clear",
+ weekStart: 0,
+ format: "yyyy-mm-dd"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/en-GB.js b/src/ui/static/js/datepicker/i18n/locales/en-GB.js
new file mode 100644
index 000000000..fa865ad71
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/en-GB.js
@@ -0,0 +1,18 @@
+/**
+ * British English translation for bootstrap-datepicker
+ * Xavier Dutreilh
+ */
+export default {
+ 'en-GB': {
+ days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
+ daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
+ daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"],
+ months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
+ monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
+ today: "Today",
+ monthsTitle: "Months",
+ clear: "Clear",
+ weekStart: 1,
+ format: "dd/mm/yyyy"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/en-IE.js b/src/ui/static/js/datepicker/i18n/locales/en-IE.js
new file mode 100644
index 000000000..c9988bd48
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/en-IE.js
@@ -0,0 +1,17 @@
+/**
+ * Irish English translation for bootstrap-datepicker
+ */
+export default {
+ 'en-IE': {
+ days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
+ daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
+ daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"],
+ months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
+ monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
+ today: "Today",
+ monthsTitle: "Months",
+ clear: "Clear",
+ weekStart: 1,
+ format: "dd/mm/yyyy"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/en-NZ.js b/src/ui/static/js/datepicker/i18n/locales/en-NZ.js
new file mode 100644
index 000000000..bad9a0766
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/en-NZ.js
@@ -0,0 +1,17 @@
+/**
+ * New Zealand English translation for bootstrap-datepicker
+ */
+export default {
+ 'en-NZ': {
+ days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
+ daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
+ daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"],
+ months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
+ monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
+ today: "Today",
+ monthsTitle: "Months",
+ clear: "Clear",
+ weekStart: 1,
+ format: "d/mm/yyyy"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/en-ZA.js b/src/ui/static/js/datepicker/i18n/locales/en-ZA.js
new file mode 100644
index 000000000..e44e4693d
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/en-ZA.js
@@ -0,0 +1,17 @@
+/**
+ * South African English translation for bootstrap-datepicker
+ */
+export default {
+ 'en-ZA': {
+ days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
+ daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
+ daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"],
+ months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
+ monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
+ today: "Today",
+ monthsTitle: "Months",
+ clear: "Clear",
+ weekStart: 1,
+ format: "yyyy/mm/d"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/eo.js b/src/ui/static/js/datepicker/i18n/locales/eo.js
new file mode 100644
index 000000000..a53430013
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/eo.js
@@ -0,0 +1,17 @@
+/**
+ * Esperanto translation for bootstrap-datepicker
+ * Emmanuel Debanne
+ */
+export default {
+ eo: {
+ days: ["dimanĉo", "lundo", "mardo", "merkredo", "ĵaŭdo", "vendredo", "sabato"],
+ daysShort: ["dim.", "lun.", "mar.", "mer.", "ĵaŭ.", "ven.", "sam."],
+ daysMin: ["d", "l", "ma", "me", "ĵ", "v", "s"],
+ months: ["januaro", "februaro", "marto", "aprilo", "majo", "junio", "julio", "aŭgusto", "septembro", "oktobro", "novembro", "decembro"],
+ monthsShort: ["jan.", "feb.", "mar.", "apr.", "majo", "jun.", "jul.", "aŭg.", "sep.", "okt.", "nov.", "dec."],
+ today: "Hodiaŭ",
+ clear: "Nuligi",
+ weekStart: 1,
+ format: "yyyy-mm-dd"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/es.js b/src/ui/static/js/datepicker/i18n/locales/es.js
new file mode 100644
index 000000000..201f52f65
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/es.js
@@ -0,0 +1,18 @@
+/**
+ * Spanish translation for bootstrap-datepicker
+ * Bruno Bonamin
+ */
+export default {
+ es: {
+ days: ["Domingo", "Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sábado"],
+ daysShort: ["Dom", "Lun", "Mar", "Mié", "Jue", "Vie", "Sáb"],
+ daysMin: ["Do", "Lu", "Ma", "Mi", "Ju", "Vi", "Sa"],
+ months: ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"],
+ monthsShort: ["Ene", "Feb", "Mar", "Abr", "May", "Jun", "Jul", "Ago", "Sep", "Oct", "Nov", "Dic"],
+ today: "Hoy",
+ monthsTitle: "Meses",
+ clear: "Borrar",
+ weekStart: 1,
+ format: "dd/mm/yyyy"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/et.js b/src/ui/static/js/datepicker/i18n/locales/et.js
new file mode 100644
index 000000000..183878b1c
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/et.js
@@ -0,0 +1,18 @@
+/**
+ * Estonian translation for bootstrap-datepicker
+ * Ando Roots
+ * Fixes by Illimar Tambek <
+ */
+export default {
+ et: {
+ days: ["Pühapäev", "Esmaspäev", "Teisipäev", "Kolmapäev", "Neljapäev", "Reede", "Laupäev"],
+ daysShort: ["Pühap", "Esmasp", "Teisip", "Kolmap", "Neljap", "Reede", "Laup"],
+ daysMin: ["P", "E", "T", "K", "N", "R", "L"],
+ months: ["Jaanuar", "Veebruar", "Märts", "Aprill", "Mai", "Juuni", "Juuli", "August", "September", "Oktoober", "November", "Detsember"],
+ monthsShort: ["Jaan", "Veebr", "Märts", "Apr", "Mai", "Juuni", "Juuli", "Aug", "Sept", "Okt", "Nov", "Dets"],
+ today: "Täna",
+ clear: "Tühjenda",
+ weekStart: 1,
+ format: "dd.mm.yyyy"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/eu.js b/src/ui/static/js/datepicker/i18n/locales/eu.js
new file mode 100644
index 000000000..1f3c2c30e
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/eu.js
@@ -0,0 +1,18 @@
+/**
+ * Basque translation for bootstrap-datepicker
+ * Arkaitz Etxeberria
+ */
+export default {
+ eu: {
+ days: ['Igandea', 'Astelehena', 'Asteartea', 'Asteazkena', 'Osteguna', 'Ostirala', 'Larunbata'],
+ daysShort: ['Ig', 'Al', 'Ar', 'Az', 'Og', 'Ol', 'Lr'],
+ daysMin: ['Ig', 'Al', 'Ar', 'Az', 'Og', 'Ol', 'Lr'],
+ months: ['Urtarrila', 'Otsaila', 'Martxoa', 'Apirila', 'Maiatza', 'Ekaina', 'Uztaila', 'Abuztua', 'Iraila', 'Urria', 'Azaroa', 'Abendua'],
+ monthsShort: ['Urt', 'Ots', 'Mar', 'Api', 'Mai', 'Eka', 'Uzt', 'Abu', 'Ira', 'Urr', 'Aza', 'Abe'],
+ today: "Gaur",
+ monthsTitle: "Hilabeteak",
+ clear: "Ezabatu",
+ weekStart: 1,
+ format: "yyyy/mm/dd"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/fa.js b/src/ui/static/js/datepicker/i18n/locales/fa.js
new file mode 100644
index 000000000..dece24ed0
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/fa.js
@@ -0,0 +1,17 @@
+/**
+ * Persian translation for bootstrap-datepicker
+ * Mostafa Rokooie
+ */
+export default {
+ fa: {
+ days: ["یکشنبه", "دوشنبه", "سهشنبه", "چهارشنبه", "پنجشنبه", "جمعه", "شنبه", "یکشنبه"],
+ daysShort: ["یک", "دو", "سه", "چهار", "پنج", "جمعه", "شنبه", "یک"],
+ daysMin: ["ی", "د", "س", "چ", "پ", "ج", "ش", "ی"],
+ months: ["ژانویه", "فوریه", "مارس", "آوریل", "مه", "ژوئن", "ژوئیه", "اوت", "سپتامبر", "اکتبر", "نوامبر", "دسامبر"],
+ monthsShort: ["ژان", "فور", "مار", "آور", "مه", "ژون", "ژوی", "اوت", "سپت", "اکت", "نوا", "دسا"],
+ today: "امروز",
+ clear: "پاک کن",
+ weekStart: 1,
+ format: "yyyy/mm/dd"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/fi.js b/src/ui/static/js/datepicker/i18n/locales/fi.js
new file mode 100644
index 000000000..d9fde77fb
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/fi.js
@@ -0,0 +1,17 @@
+/**
+ * Finnish translation for bootstrap-datepicker
+ * Jaakko Salonen
+ */
+export default {
+ fi: {
+ days: ["sunnuntai", "maanantai", "tiistai", "keskiviikko", "torstai", "perjantai", "lauantai"],
+ daysShort: ["sun", "maa", "tii", "kes", "tor", "per", "lau"],
+ daysMin: ["su", "ma", "ti", "ke", "to", "pe", "la"],
+ months: ["tammikuu", "helmikuu", "maaliskuu", "huhtikuu", "toukokuu", "kesäkuu", "heinäkuu", "elokuu", "syyskuu", "lokakuu", "marraskuu", "joulukuu"],
+ monthsShort: ["tammi", "helmi", "maalis", "huhti", "touko", "kesä", "heinä", "elo", "syys", "loka", "marras", "joulu"],
+ today: "tänään",
+ clear: "Tyhjennä",
+ weekStart: 1,
+ format: "d.m.yyyy"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/fo.js b/src/ui/static/js/datepicker/i18n/locales/fo.js
new file mode 100644
index 000000000..908ccfcc8
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/fo.js
@@ -0,0 +1,15 @@
+/**
+ * Faroese translation for bootstrap-datepicker
+ * Theodor Johannesen
+ */
+export default {
+ fo: {
+ days: ["Sunnudagur", "Mánadagur", "Týsdagur", "Mikudagur", "Hósdagur", "Fríggjadagur", "Leygardagur"],
+ daysShort: ["Sun", "Mán", "Týs", "Mik", "Hós", "Frí", "Ley"],
+ daysMin: ["Su", "Má", "Tý", "Mi", "Hó", "Fr", "Le"],
+ months: ["Januar", "Februar", "Marts", "Apríl", "Mei", "Juni", "Juli", "August", "Septembur", "Oktobur", "Novembur", "Desembur"],
+ monthsShort: ["Jan", "Feb", "Mar", "Apr", "Mei", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Des"],
+ today: "Í Dag",
+ clear: "Reinsa"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/fr-CH.js b/src/ui/static/js/datepicker/i18n/locales/fr-CH.js
new file mode 100644
index 000000000..6d90d69bd
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/fr-CH.js
@@ -0,0 +1,21 @@
+/**
+ * French (Switzerland) translation for bootstrap-datepicker
+ * Christoph Jossi
+ * Based on
+ * French translation for bootstrap-datepicker
+ * Nico Mollet
+ */
+export default {
+ 'fr-CH': {
+ days: ["Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi"],
+ daysShort: ["Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam"],
+ daysMin: ["D", "L", "Ma", "Me", "J", "V", "S"],
+ months: ["Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre"],
+ monthsShort: ["Jan", "Fév", "Mar", "Avr", "Mai", "Jui", "Jul", "Aou", "Sep", "Oct", "Nov", "Déc"],
+ today: "Aujourd'hui",
+ monthsTitle: "Mois",
+ clear: "Effacer",
+ weekStart: 1,
+ format: "dd.mm.yyyy"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/fr.js b/src/ui/static/js/datepicker/i18n/locales/fr.js
new file mode 100644
index 000000000..cac7cc355
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/fr.js
@@ -0,0 +1,18 @@
+/**
+ * French translation for bootstrap-datepicker
+ * Nico Mollet
+ */
+export default {
+ fr: {
+ days: ["dimanche", "lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi"],
+ daysShort: ["dim.", "lun.", "mar.", "mer.", "jeu.", "ven.", "sam."],
+ daysMin: ["d", "l", "ma", "me", "j", "v", "s"],
+ months: ["janvier", "février", "mars", "avril", "mai", "juin", "juillet", "août", "septembre", "octobre", "novembre", "décembre"],
+ monthsShort: ["janv.", "févr.", "mars", "avril", "mai", "juin", "juil.", "août", "sept.", "oct.", "nov.", "déc."],
+ today: "Aujourd'hui",
+ monthsTitle: "Mois",
+ clear: "Effacer",
+ weekStart: 1,
+ format: "dd/mm/yyyy"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/gl.js b/src/ui/static/js/datepicker/i18n/locales/gl.js
new file mode 100644
index 000000000..86581e78d
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/gl.js
@@ -0,0 +1,16 @@
+/**
+ * Galician translation
+ */
+export default {
+ gl: {
+ days: ["Domingo", "Luns", "Martes", "Mércores", "Xoves", "Venres", "Sábado"],
+ daysShort: ["Dom", "Lun", "Mar", "Mér", "Xov", "Ven", "Sáb"],
+ daysMin: ["Do", "Lu", "Ma", "Me", "Xo", "Ve", "Sa"],
+ months: ["Xaneiro", "Febreiro", "Marzo", "Abril", "Maio", "Xuño", "Xullo", "Agosto", "Setembro", "Outubro", "Novembro", "Decembro"],
+ monthsShort: ["Xan", "Feb", "Mar", "Abr", "Mai", "Xun", "Xul", "Ago", "Sep", "Out", "Nov", "Dec"],
+ today: "Hoxe",
+ clear: "Limpar",
+ weekStart: 1,
+ format: "dd/mm/yyyy"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/he.js b/src/ui/static/js/datepicker/i18n/locales/he.js
new file mode 100644
index 000000000..c7f1d62e6
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/he.js
@@ -0,0 +1,15 @@
+/**
+ * Hebrew translation for bootstrap-datepicker
+ * Sagie Maoz
+ */
+export default {
+ he: {
+ days: ["ראשון", "שני", "שלישי", "רביעי", "חמישי", "שישי", "שבת", "ראשון"],
+ daysShort: ["א", "ב", "ג", "ד", "ה", "ו", "ש", "א"],
+ daysMin: ["א", "ב", "ג", "ד", "ה", "ו", "ש", "א"],
+ months: ["ינואר", "פברואר", "מרץ", "אפריל", "מאי", "יוני", "יולי", "אוגוסט", "ספטמבר", "אוקטובר", "נובמבר", "דצמבר"],
+ monthsShort: ["ינו", "פבר", "מרץ", "אפר", "מאי", "יונ", "יול", "אוג", "ספט", "אוק", "נוב", "דצמ"],
+ today: "היום",
+ rtl: true
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/hi.js b/src/ui/static/js/datepicker/i18n/locales/hi.js
new file mode 100644
index 000000000..25d68cdab
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/hi.js
@@ -0,0 +1,18 @@
+/**
+ * Hindi translation for bootstrap-datepicker
+ * Visar Uruqi
+ */
+export default {
+ hi: {
+ days: ["रविवार", "सोमवार", "मंगलवार", "बुधवार", "गुरुवार", "शुक्रवार", "शनिवार"],
+ daysShort: ["सूर्य", "सोम", "मंगल", "बुध", "गुरु", "शुक्र", "शनि"],
+ daysMin: ["र", "सो", "मं", "बु", "गु", "शु", "श"],
+ months: ["जनवरी", "फ़रवरी", "मार्च", "अप्रैल", "मई", "जून", "जुलाई", "अगस्त", "सितम्बर", "अक्टूबर", "नवंबर", "दिसम्बर"],
+ monthsShort: ["जन", "फ़रवरी", "मार्च", "अप्रैल", "मई", "जून", "जुलाई", "अगस्त", "सितं", "अक्टूबर", "नवं", "दिसम्बर"],
+ today: "आज",
+ monthsTitle: "महीने",
+ clear: "साफ",
+ weekStart: 1,
+ format: "dd / mm / yyyy"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/hr.js b/src/ui/static/js/datepicker/i18n/locales/hr.js
new file mode 100644
index 000000000..0360859c2
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/hr.js
@@ -0,0 +1,13 @@
+/**
+ * Croatian localisation
+ */
+export default {
+ hr: {
+ days: ["Nedjelja", "Ponedjeljak", "Utorak", "Srijeda", "Četvrtak", "Petak", "Subota"],
+ daysShort: ["Ned", "Pon", "Uto", "Sri", "Čet", "Pet", "Sub"],
+ daysMin: ["Ne", "Po", "Ut", "Sr", "Če", "Pe", "Su"],
+ months: ["Siječanj", "Veljača", "Ožujak", "Travanj", "Svibanj", "Lipanj", "Srpanj", "Kolovoz", "Rujan", "Listopad", "Studeni", "Prosinac"],
+ monthsShort: ["Sij", "Velj", "Ožu", "Tra", "Svi", "Lip", "Srp", "Kol", "Ruj", "Lis", "Stu", "Pro"],
+ today: "Danas"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/hu.js b/src/ui/static/js/datepicker/i18n/locales/hu.js
new file mode 100644
index 000000000..f5342671b
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/hu.js
@@ -0,0 +1,18 @@
+/**
+ * Hungarian translation for bootstrap-datepicker
+ * Sotus László
+ */
+export default {
+ hu: {
+ days: ["vasárnap", "hétfő", "kedd", "szerda", "csütörtök", "péntek", "szombat"],
+ daysShort: ["vas", "hét", "ked", "sze", "csü", "pén", "szo"],
+ daysMin: ["V", "H", "K", "Sze", "Cs", "P", "Szo"],
+ months: ["január", "február", "március", "április", "május", "június", "július", "augusztus", "szeptember", "október", "november", "december"],
+ monthsShort: ["jan", "feb", "már", "ápr", "máj", "jún", "júl", "aug", "sze", "okt", "nov", "dec"],
+ today: "ma",
+ weekStart: 1,
+ clear: "töröl",
+ titleFormat: "y. MM",
+ format: "yyyy.mm.dd"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/hy.js b/src/ui/static/js/datepicker/i18n/locales/hy.js
new file mode 100644
index 000000000..599dc800e
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/hy.js
@@ -0,0 +1,18 @@
+/**
+ * Armenian translation for bootstrap-datepicker
+ * Hayk Chamyan
+ */
+export default {
+ hy: {
+ days: ["Կիրակի", "Երկուշաբթի", "Երեքշաբթի", "Չորեքշաբթի", "Հինգշաբթի", "Ուրբաթ", "Շաբաթ"],
+ daysShort: ["Կիր", "Երկ", "Երե", "Չոր", "Հին", "Ուրբ", "Շաբ"],
+ daysMin: ["Կի", "Եկ", "Եք", "Չո", "Հի", "Ու", "Շա"],
+ months: ["Հունվար", "Փետրվար", "Մարտ", "Ապրիլ", "Մայիս", "Հունիս", "Հուլիս", "Օգոստոս", "Սեպտեմբեր", "Հոկտեմբեր", "Նոյեմբեր", "Դեկտեմբեր"],
+ monthsShort: ["Հնվ", "Փետ", "Մար", "Ապր", "Մայ", "Հուն", "Հուլ", "Օգս", "Սեպ", "Հոկ", "Նոյ", "Դեկ"],
+ today: "Այսօր",
+ clear: "Ջնջել",
+ format: "dd.mm.yyyy",
+ weekStart: 1,
+ monthsTitle: 'Ամիսնէր'
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/id.js b/src/ui/static/js/datepicker/i18n/locales/id.js
new file mode 100644
index 000000000..4dc532baa
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/id.js
@@ -0,0 +1,19 @@
+/**
+ * Bahasa translation for bootstrap-datepicker
+ * Azwar Akbar
+ * Ardeman
+ */
+export default {
+ id: {
+ days: ["Minggu", "Senin", "Selasa", "Rabu", "Kamis", "Jumat", "Sabtu"],
+ daysShort: ["Min", "Sen", "Sel", "Rab", "Kam", "Jum", "Sab"],
+ daysMin: ["Mg", "Sn", "Sl", "Rb", "Km", "Jm", "Sb"],
+ months: ["Januari", "Februari", "Maret", "April", "Mei", "Juni", "Juli", "Agustus", "September", "Oktober", "November", "Desember"],
+ monthsShort: ["Jan", "Feb", "Mar", "Apr", "Mei", "Jun", "Jul", "Agt", "Sep", "Okt", "Nov", "Des"],
+ today: "Hari Ini",
+ monthsTitle: "Bulan",
+ clear: "Kosongkan",
+ weekStart: 0,
+ format: "dd-mm-yyyy"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/is.js b/src/ui/static/js/datepicker/i18n/locales/is.js
new file mode 100644
index 000000000..efbd2a6d9
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/is.js
@@ -0,0 +1,14 @@
+/**
+ * Icelandic translation for bootstrap-datepicker
+ * Hinrik Örn Sigurðsson
+ */
+export default {
+ is: {
+ days: ["Sunnudagur", "Mánudagur", "Þriðjudagur", "Miðvikudagur", "Fimmtudagur", "Föstudagur", "Laugardagur"],
+ daysShort: ["Sun", "Mán", "Þri", "Mið", "Fim", "Fös", "Lau"],
+ daysMin: ["Su", "Má", "Þr", "Mi", "Fi", "Fö", "La"],
+ months: ["Janúar", "Febrúar", "Mars", "Apríl", "Maí", "Júní", "Júlí", "Ágúst", "September", "Október", "Nóvember", "Desember"],
+ monthsShort: ["Jan", "Feb", "Mar", "Apr", "Maí", "Jún", "Júl", "Ágú", "Sep", "Okt", "Nóv", "Des"],
+ today: "Í Dag"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/it-CH.js b/src/ui/static/js/datepicker/i18n/locales/it-CH.js
new file mode 100644
index 000000000..21e355bb9
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/it-CH.js
@@ -0,0 +1,20 @@
+/**
+ * Italian (Switzerland) translation for bootstrap-datepicker
+ * Christoph Jossi
+ * Based on
+ * Italian translation for bootstrap-datepicker
+ * Enrico Rubboli
+ */
+export default {
+ 'it-CH': {
+ days: ["Domenica", "Lunedì", "Martedì", "Mercoledì", "Giovedì", "Venerdì", "Sabato"],
+ daysShort: ["Dom", "Lun", "Mar", "Mer", "Gio", "Ven", "Sab"],
+ daysMin: ["Do", "Lu", "Ma", "Me", "Gi", "Ve", "Sa"],
+ months: ["Gennaio", "Febbraio", "Marzo", "Aprile", "Maggio", "Giugno", "Luglio", "Agosto", "Settembre", "Ottobre", "Novembre", "Dicembre"],
+ monthsShort: ["Gen", "Feb", "Mar", "Apr", "Mag", "Giu", "Lug", "Ago", "Set", "Ott", "Nov", "Dic"],
+ today: "Oggi",
+ clear: "Cancella",
+ weekStart: 1,
+ format: "dd.mm.yyyy"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/it.js b/src/ui/static/js/datepicker/i18n/locales/it.js
new file mode 100644
index 000000000..169500447
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/it.js
@@ -0,0 +1,18 @@
+/**
+ * Italian translation for bootstrap-datepicker
+ * Enrico Rubboli
+ */
+export default {
+ it: {
+ days: ["Domenica", "Lunedì", "Martedì", "Mercoledì", "Giovedì", "Venerdì", "Sabato"],
+ daysShort: ["Dom", "Lun", "Mar", "Mer", "Gio", "Ven", "Sab"],
+ daysMin: ["Do", "Lu", "Ma", "Me", "Gi", "Ve", "Sa"],
+ months: ["Gennaio", "Febbraio", "Marzo", "Aprile", "Maggio", "Giugno", "Luglio", "Agosto", "Settembre", "Ottobre", "Novembre", "Dicembre"],
+ monthsShort: ["Gen", "Feb", "Mar", "Apr", "Mag", "Giu", "Lug", "Ago", "Set", "Ott", "Nov", "Dic"],
+ today: "Oggi",
+ monthsTitle: "Mesi",
+ clear: "Cancella",
+ weekStart: 1,
+ format: "dd/mm/yyyy"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/ja.js b/src/ui/static/js/datepicker/i18n/locales/ja.js
new file mode 100644
index 000000000..bdcb0dd99
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/ja.js
@@ -0,0 +1,17 @@
+/**
+ * Japanese translation for bootstrap-datepicker
+ * Norio Suzuki
+ */
+export default {
+ ja: {
+ days: ["日曜", "月曜", "火曜", "水曜", "木曜", "金曜", "土曜"],
+ daysShort: ["日", "月", "火", "水", "木", "金", "土"],
+ daysMin: ["日", "月", "火", "水", "木", "金", "土"],
+ months: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"],
+ monthsShort: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"],
+ today: "今日",
+ format: "yyyy/mm/dd",
+ titleFormat: "y年mm月",
+ clear: "クリア"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/ka.js b/src/ui/static/js/datepicker/i18n/locales/ka.js
new file mode 100644
index 000000000..b2a7c0ddf
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/ka.js
@@ -0,0 +1,17 @@
+/**
+ * Georgian translation for bootstrap-datepicker
+ * Levan Melikishvili
+ */
+export default {
+ ka: {
+ days: ["კვირა", "ორშაბათი", "სამშაბათი", "ოთხშაბათი", "ხუთშაბათი", "პარასკევი", "შაბათი"],
+ daysShort: ["კვი", "ორშ", "სამ", "ოთხ", "ხუთ", "პარ", "შაბ"],
+ daysMin: ["კვ", "ორ", "სა", "ოთ", "ხუ", "პა", "შა"],
+ months: ["იანვარი", "თებერვალი", "მარტი", "აპრილი", "მაისი", "ივნისი", "ივლისი", "აგვისტო", "სექტემბერი", "ოქტომბერი", "ნოემბერი", "დეკემბერი"],
+ monthsShort: ["იან", "თებ", "მარ", "აპრ", "მაი", "ივნ", "ივლ", "აგვ", "სექ", "ოქტ", "ნოე", "დეკ"],
+ today: "დღეს",
+ clear: "გასუფთავება",
+ weekStart: 1,
+ format: "dd.mm.yyyy"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/kk.js b/src/ui/static/js/datepicker/i18n/locales/kk.js
new file mode 100644
index 000000000..46ad589e8
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/kk.js
@@ -0,0 +1,15 @@
+/**
+ * Kazakh translation for bootstrap-datepicker
+ * Yerzhan Tolekov
+ */
+export default {
+ kk: {
+ days: ["Жексенбі", "Дүйсенбі", "Сейсенбі", "Сәрсенбі", "Бейсенбі", "Жұма", "Сенбі"],
+ daysShort: ["Жек", "Дүй", "Сей", "Сәр", "Бей", "Жұм", "Сен"],
+ daysMin: ["Жк", "Дс", "Сс", "Ср", "Бс", "Жм", "Сн"],
+ months: ["Қаңтар", "Ақпан", "Наурыз", "Сәуір", "Мамыр", "Маусым", "Шілде", "Тамыз", "Қыркүйек", "Қазан", "Қараша", "Желтоқсан"],
+ monthsShort: ["Қаң", "Ақп", "Нау", "Сәу", "Мам", "Мау", "Шіл", "Там", "Қыр", "Қаз", "Қар", "Жел"],
+ today: "Бүгін",
+ weekStart: 1
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/km.js b/src/ui/static/js/datepicker/i18n/locales/km.js
new file mode 100644
index 000000000..1688262e0
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/km.js
@@ -0,0 +1,15 @@
+/**
+ * Khmer translation for bootstrap-datepicker
+ * This is the Updated Version of: https: //github.com/uxsolutions/bootstrap-datepicker/blob/71308d42cce9524284c50c6fac50422d1790ac0f/js/locales/bootstrap-datepicker.kh.js
+ */
+export default {
+ km: {
+ days: ["អាទិត្យ", "ចន្ទ", "អង្គារ", "ពុធ", "ព្រហស្បតិ៍", "សុក្រ", "សៅរ៍"],
+ daysShort: ["អា.ទិ", "ចន្ទ", "អង្គារ", "ពុធ", "ព្រ.ហ", "សុក្រ", "សៅរ៍"],
+ daysMin: ["អា.ទិ", "ចន្ទ", "អង្គារ", "ពុធ", "ព្រ.ហ", "សុក្រ", "សៅរ៍"],
+ months: ["មករា", "កុម្ភះ", "មិនា", "មេសា", "ឧសភា", "មិថុនា", "កក្កដា", "សីហា", "កញ្ញា", "តុលា", "វិច្ឆិកា", "ធ្នូ"],
+ monthsShort: ["មករា", "កុម្ភះ", "មិនា", "មេសា", "ឧសភា", "មិថុនា", "កក្កដា", "សីហា", "កញ្ញា", "តុលា", "វិច្ឆិកា", "ធ្នូ"],
+ today: "ថ្ងៃនេះ",
+ clear: "សំអាត"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/ko.js b/src/ui/static/js/datepicker/i18n/locales/ko.js
new file mode 100644
index 000000000..d5eb49e8b
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/ko.js
@@ -0,0 +1,18 @@
+/**
+ * Korean translation for bootstrap-datepicker
+ * This is a port from https: //github.com/moment/moment/blob/develop/src/locale/ko.js
+ */
+export default {
+ ko: {
+ days: ["일요일", "월요일", "화요일", "수요일", "목요일", "금요일", "토요일"],
+ daysShort: ["일", "월", "화", "수", "목", "금", "토"],
+ daysMin: ["일", "월", "화", "수", "목", "금", "토"],
+ months: ["1월", "2월", "3월", "4월", "5월", "6월", "7월", "8월", "9월", "10월", "11월", "12월"],
+ monthsShort: ["1월", "2월", "3월", "4월", "5월", "6월", "7월", "8월", "9월", "10월", "11월", "12월"],
+ today: "오늘",
+ clear: "삭제",
+ format: "yyyy-mm-dd",
+ titleFormat: "y년mm월",
+ weekStart: 0
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/lt.js b/src/ui/static/js/datepicker/i18n/locales/lt.js
new file mode 100644
index 000000000..960ef9fff
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/lt.js
@@ -0,0 +1,19 @@
+/**
+ * Lithuanian translation for bootstrap-datepicker
+ * Šarūnas Gliebus
+ */
+
+export default {
+ lt: {
+ days: ["Sekmadienis", "Pirmadienis", "Antradienis", "Trečiadienis", "Ketvirtadienis", "Penktadienis", "Šeštadienis"],
+ daysShort: ["S", "Pr", "A", "T", "K", "Pn", "Š"],
+ daysMin: ["Sk", "Pr", "An", "Tr", "Ke", "Pn", "Št"],
+ months: ["Sausis", "Vasaris", "Kovas", "Balandis", "Gegužė", "Birželis", "Liepa", "Rugpjūtis", "Rugsėjis", "Spalis", "Lapkritis", "Gruodis"],
+ monthsShort: ["Sau", "Vas", "Kov", "Bal", "Geg", "Bir", "Lie", "Rugp", "Rugs", "Spa", "Lap", "Gru"],
+ today: "Šiandien",
+ monthsTitle: "Mėnesiai",
+ clear: "Išvalyti",
+ weekStart: 1,
+ format: "yyyy-mm-dd"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/lv.js b/src/ui/static/js/datepicker/i18n/locales/lv.js
new file mode 100644
index 000000000..68a4542f8
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/lv.js
@@ -0,0 +1,18 @@
+/**
+ * Latvian translation for bootstrap-datepicker
+ * Artis Avotins
+ */
+
+export default {
+ lv: {
+ days: ["Svētdiena", "Pirmdiena", "Otrdiena", "Trešdiena", "Ceturtdiena", "Piektdiena", "Sestdiena"],
+ daysShort: ["Sv", "P", "O", "T", "C", "Pk", "S"],
+ daysMin: ["Sv", "Pr", "Ot", "Tr", "Ce", "Pk", "Se"],
+ months: ["Janvāris", "Februāris", "Marts", "Aprīlis", "Maijs", "Jūnijs", "Jūlijs", "Augusts", "Septembris", "Oktobris", "Novembris", "Decembris"],
+ monthsShort: ["Jan", "Feb", "Mar", "Apr", "Mai", "Jūn", "Jūl", "Aug", "Sep", "Okt", "Nov", "Dec"],
+ monthsTitle: "Mēneši",
+ today: "Šodien",
+ clear: "Nodzēst",
+ weekStart: 1
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/me.js b/src/ui/static/js/datepicker/i18n/locales/me.js
new file mode 100644
index 000000000..7fa5cb376
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/me.js
@@ -0,0 +1,17 @@
+/**
+ * Montenegrin translation for bootstrap-datepicker
+ * Miodrag Nikač
+ */
+export default {
+ me: {
+ days: ["Nedjelja","Ponedjeljak", "Utorak", "Srijeda", "Četvrtak", "Petak", "Subota"],
+ daysShort: ["Ned", "Pon", "Uto", "Sri", "Čet", "Pet", "Sub"],
+ daysMin: ["Ne", "Po", "Ut", "Sr", "Če", "Pe", "Su"],
+ months: ["Januar", "Februar", "Mart", "April", "Maj", "Jun", "Jul", "Avgust", "Septembar", "Oktobar", "Novembar", "Decembar"],
+ monthsShort: ["Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Avg", "Sep", "Okt", "Nov", "Dec"],
+ today: "Danas",
+ weekStart: 1,
+ clear: "Izbriši",
+ format: "dd.mm.yyyy"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/mk.js b/src/ui/static/js/datepicker/i18n/locales/mk.js
new file mode 100644
index 000000000..7debd94fd
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/mk.js
@@ -0,0 +1,15 @@
+/**
+ * Macedonian translation for bootstrap-datepicker
+ * Marko Aleksic
+ */
+export default {
+ mk: {
+ days: ["Недела", "Понеделник", "Вторник", "Среда", "Четврток", "Петок", "Сабота"],
+ daysShort: ["Нед", "Пон", "Вто", "Сре", "Чет", "Пет", "Саб"],
+ daysMin: ["Не", "По", "Вт", "Ср", "Че", "Пе", "Са"],
+ months: ["Јануари", "Февруари", "Март", "Април", "Мај", "Јуни", "Јули", "Август", "Септември", "Октомври", "Ноември", "Декември"],
+ monthsShort: ["Јан", "Фев", "Мар", "Апр", "Мај", "Јун", "Јул", "Авг", "Сеп", "Окт", "Ное", "Дек"],
+ today: "Денес",
+ format: "dd.mm.yyyy"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/mn.js b/src/ui/static/js/datepicker/i18n/locales/mn.js
new file mode 100644
index 000000000..6bd14dbe7
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/mn.js
@@ -0,0 +1,17 @@
+/**
+ * Mongolian translation for bootstrap-datepicker
+ * Andrey Torsunov
+ */
+export default {
+ mn: {
+ days: ["Ням", "Даваа", "Мягмар", "Лхагва", "Пүрэв", "Баасан", "Бямба"],
+ daysShort: ["Ням", "Дав", "Мяг", "Лха", "Пүр", "Баа", "Бям"],
+ daysMin: ["Ня", "Да", "Мя", "Лх", "Пү", "Ба", "Бя"],
+ months: ["Хулгана", "Үхэр", "Бар", "Туулай", "Луу", "Могой", "Морь", "Хонь", "Бич", "Тахиа", "Нохой", "Гахай"],
+ monthsShort: ["Хул", "Үхэ", "Бар", "Туу", "Луу", "Мог", "Мор", "Хон", "Бич", "Тах", "Нох", "Гах"],
+ today: "Өнөөдөр",
+ clear: "Тодорхой",
+ format: "yyyy.mm.dd",
+ weekStart: 1
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/mr.js b/src/ui/static/js/datepicker/i18n/locales/mr.js
new file mode 100644
index 000000000..3f29a0266
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/mr.js
@@ -0,0 +1,18 @@
+/**
+ * Marathi translation for bootstrap-datepicker
+ * Sushant Pimple
+ */
+export default {
+ mr: {
+ days: ["रविवार", "सोमवार", "मंगळवार", "बुधवार", "गुरुवार", "शुक्रवार", "शनिवार"],
+ daysShort: ["रवि", "सोम", "मंगळ", "बुध", "गुरु", "शुक्र", "शनि"],
+ daysMin: ["र", "सो", "मं", "बु", "गु", "शु", "श"],
+ months: ["जानेवारी", "फेब्रुवारी", "मार्च", "एप्रिल", "मे", "जून", "जुलै", "ऑगस्ट", "सप्टेंबर", "ऑक्टोबर", "नोव्हेंबर", "डिसेंबर"],
+ monthsShort: ["जाने.", "फेब्रु.", "मार्च", "एप्रिल", "मे", "जून", "जुलै", "ऑगस्ट", "सप्टें.", "ऑक्टो.", "नोव्हें.", "डिसें."],
+ today: "आज",
+ monthsTitle: "महीने",
+ clear: "हटवा",
+ weekStart: 1,
+ format: "dd / mm / yyyy"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/ms.js b/src/ui/static/js/datepicker/i18n/locales/ms.js
new file mode 100644
index 000000000..66a947ffd
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/ms.js
@@ -0,0 +1,15 @@
+/**
+ * Malay translation for bootstrap-datepicker
+ * Ateman Faiz
+ */
+export default {
+ ms: {
+ days: ["Ahad", "Isnin", "Selasa", "Rabu", "Khamis", "Jumaat", "Sabtu"],
+ daysShort: ["Aha", "Isn", "Sel", "Rab", "Kha", "Jum", "Sab"],
+ daysMin: ["Ah", "Is", "Se", "Ra", "Kh", "Ju", "Sa"],
+ months: ["Januari", "Februari", "Mac", "April", "Mei", "Jun", "Julai", "Ogos", "September", "Oktober", "November", "Disember"],
+ monthsShort: ["Jan", "Feb", "Mar", "Apr", "Mei", "Jun", "Jul", "Ogo", "Sep", "Okt", "Nov", "Dis"],
+ today: "Hari Ini",
+ clear: "Bersihkan"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/nl-BE.js b/src/ui/static/js/datepicker/i18n/locales/nl-BE.js
new file mode 100644
index 000000000..b4a5c878b
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/nl-BE.js
@@ -0,0 +1,18 @@
+/**
+ * Belgium-Dutch translation for bootstrap-datepicker
+ * Julien Poulin
+ */
+export default {
+ 'nl-BE': {
+ days: ["zondag", "maandag", "dinsdag", "woensdag", "donderdag", "vrijdag", "zaterdag"],
+ daysShort: ["zo", "ma", "di", "wo", "do", "vr", "za"],
+ daysMin: ["zo", "ma", "di", "wo", "do", "vr", "za"],
+ months: ["januari", "februari", "maart", "april", "mei", "juni", "juli", "augustus", "september", "oktober", "november", "december"],
+ monthsShort: ["jan", "feb", "mrt", "apr", "mei", "jun", "jul", "aug", "sep", "okt", "nov", "dec"],
+ today: "Vandaag",
+ monthsTitle: "Maanden",
+ clear: "Leegmaken",
+ weekStart: 1,
+ format: "dd/mm/yyyy"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/nl.js b/src/ui/static/js/datepicker/i18n/locales/nl.js
new file mode 100644
index 000000000..365dc21b3
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/nl.js
@@ -0,0 +1,18 @@
+/**
+ * Dutch translation for bootstrap-datepicker
+ * Reinier Goltstein
+ */
+export default {
+ nl: {
+ days: ["zondag", "maandag", "dinsdag", "woensdag", "donderdag", "vrijdag", "zaterdag"],
+ daysShort: ["zo", "ma", "di", "wo", "do", "vr", "za"],
+ daysMin: ["zo", "ma", "di", "wo", "do", "vr", "za"],
+ months: ["januari", "februari", "maart", "april", "mei", "juni", "juli", "augustus", "september", "oktober", "november", "december"],
+ monthsShort: ["jan", "feb", "mrt", "apr", "mei", "jun", "jul", "aug", "sep", "okt", "nov", "dec"],
+ today: "Vandaag",
+ monthsTitle: "Maanden",
+ clear: "Wissen",
+ weekStart: 1,
+ format: "dd-mm-yyyy"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/no.js b/src/ui/static/js/datepicker/i18n/locales/no.js
new file mode 100644
index 000000000..aa54b82c4
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/no.js
@@ -0,0 +1,18 @@
+/**
+ * Norwegian translation for bootstrap-datepicker
+ * George Gooding
+ */
+export default {
+ no: {
+ days: ['søndag', 'mandag', 'tirsdag', 'onsdag', 'torsdag', 'fredag', 'lørdag'],
+ daysShort: ['søn', 'man', 'tir', 'ons', 'tor', 'fre', 'lør'],
+ daysMin: ['sø', 'ma', 'ti', 'on', 'to', 'fr', 'lø'],
+ months: ['januar', 'februar', 'mars', 'april', 'mai', 'juni', 'juli', 'august', 'september', 'oktober', 'november', 'desember'],
+ monthsShort: ['jan', 'feb', 'mar', 'apr', 'mai', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'des'],
+ today: 'i dag',
+ monthsTitle: 'Måneder',
+ clear: 'Nullstill',
+ weekStart: 1,
+ format: 'dd.mm.yyyy'
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/oc.js b/src/ui/static/js/datepicker/i18n/locales/oc.js
new file mode 100644
index 000000000..b04e9f00c
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/oc.js
@@ -0,0 +1,17 @@
+/**
+ * Occitan translation for bootstrap-datepicker
+ */
+export default {
+ oc: {
+ days: ["Dimenge", "Diluns", "Dimars", "Dimècres", "Dijòus", "Divendres", "Dissabte"],
+ daysShort: ["Dim", "Dil", "Dmr", "Dmc", "Dij", "Div", "Dis"],
+ daysMin: ["dg", "dl", "dr", "dc", "dj", "dv", "ds"],
+ months: ["Genièr", "Febrièr", "Març", "Abrial", "Mai", "Junh", "Julhet", "Agost", "Setembre", "Octobre", "Novembre", "Decembre"],
+ monthsShort: ["Gen", "Feb", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Oct", "Nov", "Dec"],
+ today: "Uèi",
+ monthsTitle: "Meses",
+ clear: "Escafar",
+ weekStart: 1,
+ format: "dd/mm/yyyy"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/pl.js b/src/ui/static/js/datepicker/i18n/locales/pl.js
new file mode 100644
index 000000000..62b8ede6c
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/pl.js
@@ -0,0 +1,17 @@
+/**
+ * Polish translation for bootstrap-datepicker
+ * Robert
+ */
+export default {
+ pl: {
+ days: ["Niedziela", "Poniedziałek", "Wtorek", "Środa", "Czwartek", "Piątek", "Sobota"],
+ daysShort: ["Niedz.", "Pon.", "Wt.", "Śr.", "Czw.", "Piąt.", "Sob."],
+ daysMin: ["Ndz.", "Pn.", "Wt.", "Śr.", "Czw.", "Pt.", "Sob."],
+ months: ["Styczeń", "Luty", "Marzec", "Kwiecień", "Maj", "Czerwiec", "Lipiec", "Sierpień", "Wrzesień", "Październik", "Listopad", "Grudzień"],
+ monthsShort: ["Sty.", "Lut.", "Mar.", "Kwi.", "Maj", "Cze.", "Lip.", "Sie.", "Wrz.", "Paź.", "Lis.", "Gru."],
+ today: "Dzisiaj",
+ weekStart: 1,
+ clear: "Wyczyść",
+ format: "dd.mm.yyyy"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/pt-BR.js b/src/ui/static/js/datepicker/i18n/locales/pt-BR.js
new file mode 100644
index 000000000..051c03119
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/pt-BR.js
@@ -0,0 +1,17 @@
+/**
+ * Brazilian translation for bootstrap-datepicker
+ * Cauan Cabral
+ */
+export default {
+ 'pt-BR': {
+ days: ["Domingo", "Segunda", "Terça", "Quarta", "Quinta", "Sexta", "Sábado"],
+ daysShort: ["Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb"],
+ daysMin: ["Do", "Se", "Te", "Qu", "Qu", "Se", "Sa"],
+ months: ["Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"],
+ monthsShort: ["Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"],
+ today: "Hoje",
+ monthsTitle: "Meses",
+ clear: "Limpar",
+ format: "dd/mm/yyyy"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/pt.js b/src/ui/static/js/datepicker/i18n/locales/pt.js
new file mode 100644
index 000000000..baaa6ea7c
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/pt.js
@@ -0,0 +1,18 @@
+/**
+ * Portuguese translation for bootstrap-datepicker
+ * Original code: Cauan Cabral
+ * Tiago Melo
+ */
+export default {
+ pt: {
+ days: ["Domingo", "Segunda", "Terça", "Quarta", "Quinta", "Sexta", "Sábado"],
+ daysShort: ["Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb"],
+ daysMin: ["Do", "Se", "Te", "Qu", "Qu", "Se", "Sa"],
+ months: ["Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"],
+ monthsShort: ["Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"],
+ today: "Hoje",
+ monthsTitle: "Meses",
+ clear: "Limpar",
+ format: "dd/mm/yyyy"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/ro.js b/src/ui/static/js/datepicker/i18n/locales/ro.js
new file mode 100644
index 000000000..1039334c8
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/ro.js
@@ -0,0 +1,17 @@
+/**
+ * Romanian translation for bootstrap-datepicker
+ * Cristian Vasile
+ */
+export default {
+ ro: {
+ days: ["Duminică", "Luni", "Marţi", "Miercuri", "Joi", "Vineri", "Sâmbătă"],
+ daysShort: ["Dum", "Lun", "Mar", "Mie", "Joi", "Vin", "Sâm"],
+ daysMin: ["Du", "Lu", "Ma", "Mi", "Jo", "Vi", "Sâ"],
+ months: ["Ianuarie", "Februarie", "Martie", "Aprilie", "Mai", "Iunie", "Iulie", "August", "Septembrie", "Octombrie", "Noiembrie", "Decembrie"],
+ monthsShort: ["Ian", "Feb", "Mar", "Apr", "Mai", "Iun", "Iul", "Aug", "Sep", "Oct", "Nov", "Dec"],
+ today: "Astăzi",
+ clear: "Șterge",
+ weekStart: 1,
+ format: "dd/mm/yyyy"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/ru.js b/src/ui/static/js/datepicker/i18n/locales/ru.js
new file mode 100644
index 000000000..b1e866ede
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/ru.js
@@ -0,0 +1,18 @@
+/**
+ * Russian translation for bootstrap-datepicker
+ * Victor Taranenko
+ */
+export default {
+ ru: {
+ days: ["Воскресенье", "Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Суббота"],
+ daysShort: ["Вск", "Пнд", "Втр", "Срд", "Чтв", "Птн", "Суб"],
+ daysMin: ["Вс", "Пн", "Вт", "Ср", "Чт", "Пт", "Сб"],
+ months: ["Январь", "Февраль", "Март", "Апрель", "Май", "Июнь", "Июль", "Август", "Сентябрь", "Октябрь", "Ноябрь", "Декабрь"],
+ monthsShort: ["Янв", "Фев", "Мар", "Апр", "Май", "Июн", "Июл", "Авг", "Сен", "Окт", "Ноя", "Дек"],
+ today: "Сегодня",
+ clear: "Очистить",
+ format: "dd.mm.yyyy",
+ weekStart: 1,
+ monthsTitle: 'Месяцы'
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/si.js b/src/ui/static/js/datepicker/i18n/locales/si.js
new file mode 100644
index 000000000..a09d0dfaa
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/si.js
@@ -0,0 +1,18 @@
+/**
+ * Sinhala translation for bootstrap-datepicker
+ * Chanaka Fernando
+ */
+export default {
+ si: {
+ days: ["ඉරිදා", "සඳුදා", "අඟහරුවාදා", "බදාදා", "බ්රහස්පතින්දා", "සිකුරාදා", "සෙනසුරාදා"],
+ daysShort: ["ඉරි", "සඳු", "අඟ", "බදා", "බ්රහ", "සිකු", "සෙන"],
+ daysMin: ["ඉ", "ස", "අ", "බ", "බ්ර", "සි", "සෙ"],
+ months: ["ජනවාරි", "පෙබරවාරි", "මාර්තු", "අප්රේල්", "මැයි", "ජුනි", "ජූලි", "අගෝස්තු", "සැප්තැම්බර්", "ඔක්තෝබර්", "නොවැම්බර්", "දෙසැම්බර්"],
+ monthsShort: ["ජන", "පෙබ", "මාර්", "අප්රේ", "මැයි", "ජුනි", "ජූලි", "අගෝ", "සැප්", "ඔක්", "නොවැ", "දෙසැ"],
+ today: "අද",
+ monthsTitle: "මාස",
+ clear: "මකන්න",
+ weekStart: 0,
+ format: "yyyy-mm-dd"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/sk.js b/src/ui/static/js/datepicker/i18n/locales/sk.js
new file mode 100644
index 000000000..9c4a70d4c
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/sk.js
@@ -0,0 +1,18 @@
+/**
+ * Slovak translation for bootstrap-datepicker
+ * Marek Lichtner
+ * Fixes by Michal Remiš
+ */
+export default {
+ sk: {
+ days: ["Nedeľa", "Pondelok", "Utorok", "Streda", "Štvrtok", "Piatok", "Sobota"],
+ daysShort: ["Ned", "Pon", "Uto", "Str", "Štv", "Pia", "Sob"],
+ daysMin: ["Ne", "Po", "Ut", "St", "Št", "Pia", "So"],
+ months: ["Január", "Február", "Marec", "Apríl", "Máj", "Jún", "Júl", "August", "September", "Október", "November", "December"],
+ monthsShort: ["Jan", "Feb", "Mar", "Apr", "Máj", "Jún", "Júl", "Aug", "Sep", "Okt", "Nov", "Dec"],
+ today: "Dnes",
+ clear: "Vymazať",
+ weekStart: 1,
+ format: "d.m.yyyy"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/sl.js b/src/ui/static/js/datepicker/i18n/locales/sl.js
new file mode 100644
index 000000000..87acf5a62
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/sl.js
@@ -0,0 +1,15 @@
+/**
+ * Slovene translation for bootstrap-datepicker
+ * Gregor Rudolf
+ */
+export default {
+ sl: {
+ days: ["Nedelja", "Ponedeljek", "Torek", "Sreda", "Četrtek", "Petek", "Sobota"],
+ daysShort: ["Ned", "Pon", "Tor", "Sre", "Čet", "Pet", "Sob"],
+ daysMin: ["Ne", "Po", "To", "Sr", "Če", "Pe", "So"],
+ months: ["Januar", "Februar", "Marec", "April", "Maj", "Junij", "Julij", "Avgust", "September", "Oktober", "November", "December"],
+ monthsShort: ["Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Avg", "Sep", "Okt", "Nov", "Dec"],
+ today: "Danes",
+ weekStart: 1
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/sq.js b/src/ui/static/js/datepicker/i18n/locales/sq.js
new file mode 100644
index 000000000..be94a7643
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/sq.js
@@ -0,0 +1,18 @@
+/**
+ * Albanian translation for bootstrap-datepicker
+ * Tomor Pupovci
+ */
+export default {
+ sq: {
+ days: ["E Diel", "E Hënë", "E Martē", "E Mërkurë", "E Enjte", "E Premte", "E Shtunë"],
+ daysShort: ["Die", "Hën", "Mar", "Mër", "Enj", "Pre", "Shtu"],
+ daysMin: ["Di", "Hë", "Ma", "Më", "En", "Pr", "Sht"],
+ months: ["Janar", "Shkurt", "Mars", "Prill", "Maj", "Qershor", "Korrik", "Gusht", "Shtator", "Tetor", "Nëntor", "Dhjetor"],
+ monthsShort: ["Jan", "Shk", "Mar", "Pri", "Maj", "Qer", "Korr", "Gu", "Sht", "Tet", "Nën", "Dhjet"],
+ monthsTitle: "Muaj",
+ today: "Sot",
+ weekStart: 1,
+ format: "dd/mm/yyyy",
+ clear: "Pastro"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/sr-latn.js b/src/ui/static/js/datepicker/i18n/locales/sr-latn.js
new file mode 100644
index 000000000..a84b45196
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/sr-latn.js
@@ -0,0 +1,16 @@
+/**
+ * Serbian latin translation for bootstrap-datepicker
+ * Bojan Milosavlević
+ */
+export default {
+ 'sr-latn': {
+ days: ["Nedelja","Ponedeljak", "Utorak", "Sreda", "Četvrtak", "Petak", "Subota"],
+ daysShort: ["Ned", "Pon", "Uto", "Sre", "Čet", "Pet", "Sub"],
+ daysMin: ["N", "Po", "U", "Sr", "Č", "Pe", "Su"],
+ months: ["Januar", "Februar", "Mart", "April", "Maj", "Jun", "Jul", "Avgust", "Septembar", "Oktobar", "Novembar", "Decembar"],
+ monthsShort: ["Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Avg", "Sep", "Okt", "Nov", "Dec"],
+ today: "Danas",
+ weekStart: 1,
+ format: "dd.mm.yyyy"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/sr.js b/src/ui/static/js/datepicker/i18n/locales/sr.js
new file mode 100644
index 000000000..2a2ae0a05
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/sr.js
@@ -0,0 +1,16 @@
+/**
+ * Serbian cyrillic translation for bootstrap-datepicker
+ * Bojan Milosavlević
+ */
+export default {
+ sr: {
+ days: ["Недеља","Понедељак", "Уторак", "Среда", "Четвртак", "Петак", "Субота"],
+ daysShort: ["Нед", "Пон", "Уто", "Сре", "Чет", "Пет", "Суб"],
+ daysMin: ["Н", "По", "У", "Ср", "Ч", "Пе", "Су"],
+ months: ["Јануар", "Фебруар", "Март", "Април", "Мај", "Јун", "Јул", "Август", "Септембар", "Октобар", "Новембар", "Децембар"],
+ monthsShort: ["Јан", "Феб", "Мар", "Апр", "Мај", "Јун", "Јул", "Авг", "Сеп", "Окт", "Нов", "Дец"],
+ today: "Данас",
+ weekStart: 1,
+ format: "dd.mm.yyyy"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/sv.js b/src/ui/static/js/datepicker/i18n/locales/sv.js
new file mode 100644
index 000000000..2323d4363
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/sv.js
@@ -0,0 +1,17 @@
+/**
+ * Swedish translation for bootstrap-datepicker
+ * Patrik Ragnarsson
+ */
+export default {
+ sv: {
+ days: ["söndag", "måndag", "tisdag", "onsdag", "torsdag", "fredag", "lördag"],
+ daysShort: ["sön", "mån", "tis", "ons", "tor", "fre", "lör"],
+ daysMin: ["sö", "må", "ti", "on", "to", "fr", "lö"],
+ months: ["januari", "februari", "mars", "april", "maj", "juni", "juli", "augusti", "september", "oktober", "november", "december"],
+ monthsShort: ["jan", "feb", "mar", "apr", "maj", "jun", "jul", "aug", "sep", "okt", "nov", "dec"],
+ today: "Idag",
+ format: "yyyy-mm-dd",
+ weekStart: 1,
+ clear: "Rensa"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/sw.js b/src/ui/static/js/datepicker/i18n/locales/sw.js
new file mode 100644
index 000000000..61ce0add2
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/sw.js
@@ -0,0 +1,15 @@
+/**
+ * Swahili translation for bootstrap-datepicker
+ * Edwin Mugendi
+ * Source: http: //scriptsource.org/cms/scripts/page.php?item_id=entry_detail&uid=xnfaqyzcku
+ */
+export default {
+ sw: {
+ days: ["Jumapili", "Jumatatu", "Jumanne", "Jumatano", "Alhamisi", "Ijumaa", "Jumamosi"],
+ daysShort: ["J2", "J3", "J4", "J5", "Alh", "Ij", "J1"],
+ daysMin: ["2", "3", "4", "5", "A", "I", "1"],
+ months: ["Januari", "Februari", "Machi", "Aprili", "Mei", "Juni", "Julai", "Agosti", "Septemba", "Oktoba", "Novemba", "Desemba"],
+ monthsShort: ["Jan", "Feb", "Mac", "Apr", "Mei", "Jun", "Jul", "Ago", "Sep", "Okt", "Nov", "Des"],
+ today: "Leo"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/ta.js b/src/ui/static/js/datepicker/i18n/locales/ta.js
new file mode 100644
index 000000000..3a7ed92b1
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/ta.js
@@ -0,0 +1,18 @@
+/**
+ * Tamil translation for bootstrap-datepicker
+ * Abubacker Siddik A
+ */
+export default {
+ ta: {
+ days: ["ஞாயிறு", "திங்கள்", "செவ்வாய்", "புதன்", "வியாழன்", "வெள்ளி", "சனி"],
+ daysShort: ["ஞாயி", "திங்", "செவ்", "புத", "வியா", "வெள்", "சனி"],
+ daysMin: ["ஞா", "தி", "செ", "பு", "வி", "வெ", "ச"],
+ months: ["ஜனவரி", "பிப்ரவரி", "மார்ச்", "ஏப்ரல்", "மே", "ஜூன்", "ஜூலை", "ஆகஸ்டு", "செப்டம்பர்", "அக்டோபர்", "நவம்பர்", "டிசம்பர்"],
+ monthsShort: ["ஜன", "பிப்", "மார்", "ஏப்", "மே", "ஜூன்", "ஜூலை", "ஆக", "செப்", "அக்", "நவ", "டிச"],
+ today: "இன்று",
+ monthsTitle: "மாதங்கள்",
+ clear: "நீக்கு",
+ weekStart: 1,
+ format: "dd/mm/yyyy"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/tg.js b/src/ui/static/js/datepicker/i18n/locales/tg.js
new file mode 100644
index 000000000..b389e6b3f
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/tg.js
@@ -0,0 +1,19 @@
+/**
+ * Tajik (cyrillic) translation for bootstrap-datepicker
+ * Bakhtiyor Bahritidinov
+ * Orif N. Jr.
+ */
+export default {
+ tg: {
+ days: ["Якшанбе", "Душанбе", "Сешанбе", "Чоршанбе", "Панҷшанбе", "Ҷумъа", "Шанбе"],
+ daysShort: ["Яшб", "Дшб", "Сшб", "Чшб", "Пшб", "Ҷум", "Шнб"],
+ daysMin: ["Яш", "Дш", "Сш", "Чш", "Пш", "Ҷм", "Шб"],
+ months: ["Январ", "Феврал", "Март", "Апрел", "Май", "Июн", "Июл", "Август", "Сентябр", "Октябр", "Ноябр", "Декабр"],
+ monthsShort: ["Янв", "Фев", "Мар", "Апр", "Май", "Июн", "Июл", "Авг", "Сен", "Окт", "Ноя", "Дек"],
+ today: "Имрӯз",
+ monthsTitle: "Моҳҳо",
+ clear: "Тоза намудан",
+ weekStart: 1,
+ format: "dd.mm.yyyy"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/th.js b/src/ui/static/js/datepicker/i18n/locales/th.js
new file mode 100644
index 000000000..cbfa391e7
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/th.js
@@ -0,0 +1,14 @@
+/**
+ * Thai translation for bootstrap-datepicker
+ * Suchau Jiraprapot
+ */
+export default {
+ th: {
+ days: ["อาทิตย์", "จันทร์", "อังคาร", "พุธ", "พฤหัส", "ศุกร์", "เสาร์", "อาทิตย์"],
+ daysShort: ["อา", "จ", "อ", "พ", "พฤ", "ศ", "ส", "อา"],
+ daysMin: ["อา", "จ", "อ", "พ", "พฤ", "ศ", "ส", "อา"],
+ months: ["มกราคม", "กุมภาพันธ์", "มีนาคม", "เมษายน", "พฤษภาคม", "มิถุนายน", "กรกฎาคม", "สิงหาคม", "กันยายน", "ตุลาคม", "พฤศจิกายน", "ธันวาคม"],
+ monthsShort: ["ม.ค.", "ก.พ.", "มี.ค.", "เม.ย.", "พ.ค.", "มิ.ย.", "ก.ค.", "ส.ค.", "ก.ย.", "ต.ค.", "พ.ย.", "ธ.ค."],
+ today: "วันนี้"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/tk.js b/src/ui/static/js/datepicker/i18n/locales/tk.js
new file mode 100644
index 000000000..0705b1ccd
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/tk.js
@@ -0,0 +1,18 @@
+/**
+ * Turkmen translation for bootstrap-datepicker
+ * N'Bayramberdiyev
+ */
+export default {
+ tk: {
+ days: ["Ýekşenbe", "Duşenbe", "Sişenbe", "Çarşenbe", "Penşenbe", "Anna", "Şenbe"],
+ daysShort: ["Ýek", "Duş", "Siş", "Çar", "Pen", "Ann", "Şen"],
+ daysMin: ["Ýe", "Du", "Si", "Ça", "Pe", "An", "Şe"],
+ months: ["Ýanwar", "Fewral", "Mart", "Aprel", "Maý", "Iýun", "Iýul", "Awgust", "Sentýabr", "Oktýabr", "Noýabr", "Dekabr"],
+ monthsShort: ["Ýan", "Few", "Mar", "Apr", "Maý", "Iýn", "Iýl", "Awg", "Sen", "Okt", "Noý", "Dek"],
+ today: "Bu gün",
+ monthsTitle: "Aýlar",
+ clear: "Aýyr",
+ weekStart: 1,
+ format: "dd.mm.yyyy"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/tr.js b/src/ui/static/js/datepicker/i18n/locales/tr.js
new file mode 100644
index 000000000..0f8390e10
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/tr.js
@@ -0,0 +1,17 @@
+/**
+ * Turkish translation for bootstrap-datepicker
+ * Serkan Algur
+ */
+export default {
+ tr: {
+ days: ["Pazar", "Pazartesi", "Salı", "Çarşamba", "Perşembe", "Cuma", "Cumartesi"],
+ daysShort: ["Pz", "Pzt", "Sal", "Çrş", "Prş", "Cu", "Cts"],
+ daysMin: ["Pz", "Pzt", "Sa", "Çr", "Pr", "Cu", "Ct"],
+ months: ["Ocak", "Şubat", "Mart", "Nisan", "Mayıs", "Haziran", "Temmuz", "Ağustos", "Eylül", "Ekim", "Kasım", "Aralık"],
+ monthsShort: ["Oca", "Şub", "Mar", "Nis", "May", "Haz", "Tem", "Ağu", "Eyl", "Eki", "Kas", "Ara"],
+ today: "Bugün",
+ clear: "Temizle",
+ weekStart: 1,
+ format: "dd.mm.yyyy"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/uk.js b/src/ui/static/js/datepicker/i18n/locales/uk.js
new file mode 100644
index 000000000..fe5ae79d1
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/uk.js
@@ -0,0 +1,17 @@
+/**
+ * Ukrainian translation for bootstrap-datepicker
+ * Igor Polynets
+ */
+export default {
+ uk: {
+ days: ["Неділя", "Понеділок", "Вівторок", "Середа", "Четвер", "П'ятниця", "Субота"],
+ daysShort: ["Нед", "Пнд", "Втр", "Срд", "Чтв", "Птн", "Суб"],
+ daysMin: ["Нд", "Пн", "Вт", "Ср", "Чт", "Пт", "Сб"],
+ months: ["Cічень", "Лютий", "Березень", "Квітень", "Травень", "Червень", "Липень", "Серпень", "Вересень", "Жовтень", "Листопад", "Грудень"],
+ monthsShort: ["Січ", "Лют", "Бер", "Кві", "Тра", "Чер", "Лип", "Сер", "Вер", "Жов", "Лис", "Гру"],
+ today: "Сьогодні",
+ clear: "Очистити",
+ format: "dd.mm.yyyy",
+ weekStart: 1
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/uz-cyrl.js b/src/ui/static/js/datepicker/i18n/locales/uz-cyrl.js
new file mode 100644
index 000000000..b5a7cac58
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/uz-cyrl.js
@@ -0,0 +1,18 @@
+/**
+ * Uzbek cyrillic translation for bootstrap-datepicker
+ * Kakhramonov Javlonbek
+ */
+export default {
+ 'uz-cyrl': {
+ days: ["Якшанба", "Душанба", "Сешанба", "Чоршанба", "Пайшанба", "Жума", "Шанба"],
+ daysShort: ["Якш", "Ду", "Се", "Чор", "Пай", "Жу", "Ша"],
+ daysMin: ["Як", "Ду", "Се", "Чо", "Па", "Жу", "Ша"],
+ months: ["Январь","Февраль","Март","Апрель","Май","Июнь","Июль","Август","Сентябрь","Октябрь","Ноябрь","Декабрь"],
+ monthsShort: ["Янв","Фев","Мар","Апр","Май","Июн","Июл","Авг","Сен","Окт","Ноя","Дек"],
+ today: "Бугун",
+ clear: "Ўчириш",
+ format: "dd.mm.yyyy",
+ weekStart: 1,
+ monthsTitle: 'Ойлар'
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/uz-latn.js b/src/ui/static/js/datepicker/i18n/locales/uz-latn.js
new file mode 100644
index 000000000..9b689dbe2
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/uz-latn.js
@@ -0,0 +1,18 @@
+/**
+ * Uzbek latin translation for bootstrap-datepicker
+ * Kakhramonov Javlonbek
+ */
+export default {
+ 'uz-latn': {
+ days: ["Yakshanba", "Dushanba", "Seshanba", "Chorshanba", "Payshanba", "Juma", "Shanba"],
+ daysShort: ["Yak", "Du", "Se", "Chor", "Pay", "Ju", "Sha"],
+ daysMin: ["Ya", "Du", "Se", "Cho", "Pa", "Ju", "Sha"],
+ months: ["Yanvar", "Fevral", "Mart", "Aprel", "May", "Iyun", "Iyul", "Avgust", "Sentabr", "Oktabr", "Noyabr", "Dekabr"],
+ monthsShort: ["Yan", "Fev", "Mar", "Apr", "May", "Iyn", "Iyl", "Avg", "Sen", "Okt", "Noy", "Dek"],
+ today: "Bugun",
+ clear: "O'chirish",
+ format: "dd.mm.yyyy",
+ weekStart: 1,
+ monthsTitle: 'Oylar'
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/vi.js b/src/ui/static/js/datepicker/i18n/locales/vi.js
new file mode 100644
index 000000000..ffb8da93d
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/vi.js
@@ -0,0 +1,16 @@
+/**
+ * Vietnamese translation for bootstrap-datepicker
+ * An Vo
+ */
+export default {
+ vi: {
+ days: ["Chủ nhật", "Thứ hai", "Thứ ba", "Thứ tư", "Thứ năm", "Thứ sáu", "Thứ bảy"],
+ daysShort: ["CN", "Thứ 2", "Thứ 3", "Thứ 4", "Thứ 5", "Thứ 6", "Thứ 7"],
+ daysMin: ["CN", "T2", "T3", "T4", "T5", "T6", "T7"],
+ months: ["Tháng 1", "Tháng 2", "Tháng 3", "Tháng 4", "Tháng 5", "Tháng 6", "Tháng 7", "Tháng 8", "Tháng 9", "Tháng 10", "Tháng 11", "Tháng 12"],
+ monthsShort: ["Th1", "Th2", "Th3", "Th4", "Th5", "Th6", "Th7", "Th8", "Th9", "Th10", "Th11", "Th12"],
+ today: "Hôm nay",
+ clear: "Xóa",
+ format: "dd/mm/yyyy"
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/zh-CN.js b/src/ui/static/js/datepicker/i18n/locales/zh-CN.js
new file mode 100644
index 000000000..4aadcd14b
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/zh-CN.js
@@ -0,0 +1,19 @@
+/**
+ * Simplified Chinese translation for bootstrap-datepicker
+ * Yuan Cheung
+ */
+export default {
+ 'zh-CN': {
+ days: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"],
+ daysShort: ["周日", "周一", "周二", "周三", "周四", "周五", "周六"],
+ daysMin: ["日", "一", "二", "三", "四", "五", "六"],
+ months: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
+ monthsShort: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"],
+ today: "今天",
+ monthsTitle: "选择月份",
+ clear: "清除",
+ format: "yyyy-mm-dd",
+ titleFormat: "y年mm月",
+ weekStart: 1
+ }
+};
diff --git a/src/ui/static/js/datepicker/i18n/locales/zh-TW.js b/src/ui/static/js/datepicker/i18n/locales/zh-TW.js
new file mode 100644
index 000000000..762334b16
--- /dev/null
+++ b/src/ui/static/js/datepicker/i18n/locales/zh-TW.js
@@ -0,0 +1,20 @@
+/**
+ * Traditional Chinese translation for bootstrap-datepicker
+ * Rung-Sheng Jang
+ * FrankWu Fix more appropriate use of Traditional Chinese habit
+ */
+export default {
+ 'zh-TW': {
+ days: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"],
+ daysShort: ["週日", "週一", "週二", "週三", "週四", "週五", "週六"],
+ daysMin: ["日", "一", "二", "三", "四", "五", "六"],
+ months: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
+ monthsShort: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"],
+ today: "今天",
+ monthsTitle: "月份",
+ format: "yyyy/mm/dd",
+ weekStart: 0,
+ titleFormat: "y年mm月",
+ clear: "清除"
+ }
+};
diff --git a/src/ui/static/js/datepicker/lib/date-format.js b/src/ui/static/js/datepicker/lib/date-format.js
new file mode 100644
index 000000000..09ef250be
--- /dev/null
+++ b/src/ui/static/js/datepicker/lib/date-format.js
@@ -0,0 +1,185 @@
+import {stripTime, today} from './date.js';
+import {lastItemOf} from './utils.js';
+
+// pattern for format parts
+export const reFormatTokens = /dd?|DD?|mm?|MM?|yy?(?:yy)?/;
+// pattern for non date parts
+export const reNonDateParts = /[\s!-/:-@[-`{-~年月日]+/;
+// cache for persed formats
+let knownFormats = {};
+// parse funtions for date parts
+const parseFns = {
+ y(date, year) {
+ return new Date(date).setFullYear(parseInt(year, 10));
+ },
+ m(date, month, locale) {
+ const newDate = new Date(date);
+ let monthIndex = parseInt(month, 10) - 1;
+
+ if (isNaN(monthIndex)) {
+ if (!month) {
+ return NaN;
+ }
+
+ const monthName = month.toLowerCase();
+ const compareNames = name => name.toLowerCase().startsWith(monthName);
+ // compare with both short and full names because some locales have periods
+ // in the short names (not equal to the first X letters of the full names)
+ monthIndex = locale.monthsShort.findIndex(compareNames);
+ if (monthIndex < 0) {
+ monthIndex = locale.months.findIndex(compareNames);
+ }
+ if (monthIndex < 0) {
+ return NaN;
+ }
+ }
+
+ newDate.setMonth(monthIndex);
+ return newDate.getMonth() !== normalizeMonth(monthIndex)
+ ? newDate.setDate(0)
+ : newDate.getTime();
+ },
+ d(date, day) {
+ return new Date(date).setDate(parseInt(day, 10));
+ },
+};
+// format functions for date parts
+const formatFns = {
+ d(date) {
+ return date.getDate();
+ },
+ dd(date) {
+ return padZero(date.getDate(), 2);
+ },
+ D(date, locale) {
+ return locale.daysShort[date.getDay()];
+ },
+ DD(date, locale) {
+ return locale.days[date.getDay()];
+ },
+ m(date) {
+ return date.getMonth() + 1;
+ },
+ mm(date) {
+ return padZero(date.getMonth() + 1, 2);
+ },
+ M(date, locale) {
+ return locale.monthsShort[date.getMonth()];
+ },
+ MM(date, locale) {
+ return locale.months[date.getMonth()];
+ },
+ y(date) {
+ return date.getFullYear();
+ },
+ yy(date) {
+ return padZero(date.getFullYear(), 2).slice(-2);
+ },
+ yyyy(date) {
+ return padZero(date.getFullYear(), 4);
+ },
+};
+
+// get month index in normal range (0 - 11) from any number
+function normalizeMonth(monthIndex) {
+ return monthIndex > -1 ? monthIndex % 12 : normalizeMonth(monthIndex + 12);
+}
+
+function padZero(num, length) {
+ return num.toString().padStart(length, '0');
+}
+
+function parseFormatString(format) {
+ if (typeof format !== 'string') {
+ throw new Error("Invalid date format.");
+ }
+ if (format in knownFormats) {
+ return knownFormats[format];
+ }
+
+ // sprit the format string into parts and seprators
+ const separators = format.split(reFormatTokens);
+ const parts = format.match(new RegExp(reFormatTokens, 'g'));
+ if (separators.length === 0 || !parts) {
+ throw new Error("Invalid date format.");
+ }
+
+ // collect format functions used in the format
+ const partFormatters = parts.map(token => formatFns[token]);
+
+ // collect parse function keys used in the format
+ // iterate over parseFns' keys in order to keep the order of the keys.
+ const partParserKeys = Object.keys(parseFns).reduce((keys, key) => {
+ const token = parts.find(part => part[0] !== 'D' && part[0].toLowerCase() === key);
+ if (token) {
+ keys.push(key);
+ }
+ return keys;
+ }, []);
+
+ return knownFormats[format] = {
+ parser(dateStr, locale) {
+ const dateParts = dateStr.split(reNonDateParts).reduce((dtParts, part, index) => {
+ if (part.length > 0 && parts[index]) {
+ const token = parts[index][0];
+ if (token === 'M') {
+ dtParts.m = part;
+ } else if (token !== 'D') {
+ dtParts[token] = part;
+ }
+ }
+ return dtParts;
+ }, {});
+
+ // iterate over partParserkeys so that the parsing is made in the oder
+ // of year, month and day to prevent the day parser from correcting last
+ // day of month wrongly
+ return partParserKeys.reduce((origDate, key) => {
+ const newDate = parseFns[key](origDate, dateParts[key], locale);
+ // ingnore the part failed to parse
+ return isNaN(newDate) ? origDate : newDate;
+ }, today());
+ },
+ formatter(date, locale) {
+ let dateStr = partFormatters.reduce((str, fn, index) => {
+ return str += `${separators[index]}${fn(date, locale)}`;
+ }, '');
+ // separators' length is always parts' length + 1,
+ return dateStr += lastItemOf(separators);
+ },
+ };
+}
+
+export function parseDate(dateStr, format, locale) {
+ if (dateStr instanceof Date || typeof dateStr === 'number') {
+ const date = stripTime(dateStr);
+ return isNaN(date) ? undefined : date;
+ }
+ if (!dateStr) {
+ return undefined;
+ }
+ if (dateStr === 'today') {
+ return today();
+ }
+
+ if (format && format.toValue) {
+ const date = format.toValue(dateStr, format, locale);
+ return isNaN(date) ? undefined : stripTime(date);
+ }
+
+ return parseFormatString(format).parser(dateStr, locale);
+}
+
+export function formatDate(date, format, locale) {
+ if (isNaN(date) || (!date && date !== 0)) {
+ return '';
+ }
+
+ const dateObj = typeof date === 'number' ? new Date(date) : date;
+
+ if (format.toDisplay) {
+ return format.toDisplay(dateObj, format, locale);
+ }
+
+ return parseFormatString(format).formatter(dateObj, locale);
+}
diff --git a/src/ui/static/js/datepicker/lib/date.js b/src/ui/static/js/datepicker/lib/date.js
new file mode 100644
index 000000000..4282901c2
--- /dev/null
+++ b/src/ui/static/js/datepicker/lib/date.js
@@ -0,0 +1,100 @@
+export function stripTime(timeValue) {
+ return new Date(timeValue).setHours(0, 0, 0, 0);
+}
+
+export function today() {
+ return new Date().setHours(0, 0, 0, 0);
+}
+
+// Get the time value of the start of given date or year, month and day
+export function dateValue(...args) {
+ switch (args.length) {
+ case 0:
+ return today();
+ case 1:
+ return stripTime(args[0]);
+ }
+
+ // use setFullYear() to keep 2-digit year from being mapped to 1900-1999
+ const newDate = new Date(0);
+ newDate.setFullYear(...args);
+ return newDate.setHours(0, 0, 0, 0);
+}
+
+export function addDays(date, amount) {
+ const newDate = new Date(date);
+ return newDate.setDate(newDate.getDate() + amount);
+}
+
+export function addWeeks(date, amount) {
+ return addDays(date, amount * 7);
+}
+
+export function addMonths(date, amount) {
+ // If the day of the date is not in the new month, the last day of the new
+ // month will be returned. e.g. Jan 31 + 1 month → Feb 28 (not Mar 03)
+ const newDate = new Date(date);
+ const monthsToSet = newDate.getMonth() + amount;
+ let expectedMonth = monthsToSet % 12;
+ if (expectedMonth < 0) {
+ expectedMonth += 12;
+ }
+
+ const time = newDate.setMonth(monthsToSet);
+ return newDate.getMonth() !== expectedMonth ? newDate.setDate(0) : time;
+}
+
+export function addYears(date, amount) {
+ // If the date is Feb 29 and the new year is not a leap year, Feb 28 of the
+ // new year will be returned.
+ const newDate = new Date(date);
+ const expectedMonth = newDate.getMonth();
+ const time = newDate.setFullYear(newDate.getFullYear() + amount);
+ return expectedMonth === 1 && newDate.getMonth() === 2 ? newDate.setDate(0) : time;
+}
+
+// Calculate the distance bettwen 2 days of the week
+function dayDiff(day, from) {
+ return (day - from + 7) % 7;
+}
+
+// Get the date of the specified day of the week of given base date
+export function dayOfTheWeekOf(baseDate, dayOfWeek, weekStart = 0) {
+ const baseDay = new Date(baseDate).getDay();
+ return addDays(baseDate, dayDiff(dayOfWeek, weekStart) - dayDiff(baseDay, weekStart));
+}
+
+// Get the ISO week of a date
+export function getWeek(date) {
+ // start of ISO week is Monday
+ const thuOfTheWeek = dayOfTheWeekOf(date, 4, 1);
+ // 1st week == the week where the 4th of January is in
+ const firstThu = dayOfTheWeekOf(new Date(thuOfTheWeek).setMonth(0, 4), 4, 1);
+ return Math.round((thuOfTheWeek - firstThu) / 604800000) + 1;
+}
+
+// Get the start year of the period of years that includes given date
+// years: length of the year period
+export function startOfYearPeriod(date, years) {
+ /* @see https://en.wikipedia.org/wiki/Year_zero#ISO_8601 */
+ const year = new Date(date).getFullYear();
+ return Math.floor(year / years) * years;
+}
+
+// Convert date to the first/last date of the month/year of the date
+export function regularizeDate(date, timeSpan, useLastDate) {
+ if (timeSpan !== 1 && timeSpan !== 2) {
+ return date;
+ }
+ const newDate = new Date(date);
+ if (timeSpan === 1) {
+ useLastDate
+ ? newDate.setMonth(newDate.getMonth() + 1, 0)
+ : newDate.setDate(1);
+ } else {
+ useLastDate
+ ? newDate.setFullYear(newDate.getFullYear() + 1, 0, 0)
+ : newDate.setMonth(0, 1);
+ }
+ return newDate.setHours(0, 0, 0, 0);
+}
diff --git a/src/ui/static/js/datepicker/lib/dom.js b/src/ui/static/js/datepicker/lib/dom.js
new file mode 100644
index 000000000..c32fe7515
--- /dev/null
+++ b/src/ui/static/js/datepicker/lib/dom.js
@@ -0,0 +1,63 @@
+const range = document.createRange();
+
+export function parseHTML(html) {
+ return range.createContextualFragment(html);
+}
+
+export function getParent(el) {
+ return el.parentElement
+ || (el.parentNode instanceof ShadowRoot ? el.parentNode.host : undefined);
+}
+
+export function isActiveElement(el) {
+ return el.getRootNode().activeElement === el;
+}
+
+// equivalent to jQuery's :visble
+export function isVisible(el) {
+ return !!(el.offsetWidth || el.offsetHeight || el.getClientRects().length);
+}
+
+export function hideElement(el) {
+ if (el.style.display === 'none') {
+ return;
+ }
+ // back up the existing display setting in data-style-display
+ if (el.style.display) {
+ el.dataset.styleDisplay = el.style.display;
+ }
+ el.style.display = 'none';
+}
+
+export function showElement(el) {
+ if (el.style.display !== 'none') {
+ return;
+ }
+ if (el.dataset.styleDisplay) {
+ // restore backed-up dispay property
+ el.style.display = el.dataset.styleDisplay;
+ delete el.dataset.styleDisplay;
+ } else {
+ el.style.display = '';
+ }
+}
+
+export function emptyChildNodes(el) {
+ if (el.firstChild) {
+ el.removeChild(el.firstChild);
+ emptyChildNodes(el);
+ }
+}
+
+export function replaceChildNodes(el, newChildNodes) {
+ emptyChildNodes(el);
+ if (newChildNodes instanceof DocumentFragment) {
+ el.appendChild(newChildNodes);
+ } else if (typeof newChildNodes === 'string') {
+ el.appendChild(parseHTML(newChildNodes));
+ } else if (typeof newChildNodes.forEach === 'function') {
+ newChildNodes.forEach((node) => {
+ el.appendChild(node);
+ });
+ }
+}
diff --git a/src/ui/static/js/datepicker/lib/event.js b/src/ui/static/js/datepicker/lib/event.js
new file mode 100644
index 000000000..e2922644a
--- /dev/null
+++ b/src/ui/static/js/datepicker/lib/event.js
@@ -0,0 +1,71 @@
+const listenerRegistry = new WeakMap();
+const {addEventListener, removeEventListener} = EventTarget.prototype;
+
+// Register event listeners to a key object
+// listeners: array of listener definitions;
+// - each definition must be a flat array of event target and the arguments
+// used to call addEventListener() on the target
+export function registerListeners(keyObj, listeners) {
+ let registered = listenerRegistry.get(keyObj);
+ if (!registered) {
+ registered = [];
+ listenerRegistry.set(keyObj, registered);
+ }
+ listeners.forEach((listener) => {
+ addEventListener.call(...listener);
+ registered.push(listener);
+ });
+}
+
+export function unregisterListeners(keyObj) {
+ let listeners = listenerRegistry.get(keyObj);
+ if (!listeners) {
+ return;
+ }
+ listeners.forEach((listener) => {
+ removeEventListener.call(...listener);
+ });
+ listenerRegistry.delete(keyObj);
+}
+
+// Event.composedPath() polyfill for Edge
+// based on https://gist.github.com/kleinfreund/e9787d73776c0e3750dcfcdc89f100ec
+if (!Event.prototype.composedPath) {
+ const getComposedPath = (node, path = []) => {
+ path.push(node);
+
+ let parent;
+ if (node.parentNode) {
+ parent = node.parentNode;
+ } else if (node.host) { // ShadowRoot
+ parent = node.host;
+ } else if (node.defaultView) { // Document
+ parent = node.defaultView;
+ }
+ return parent ? getComposedPath(parent, path) : path;
+ };
+
+ Event.prototype.composedPath = function () {
+ return getComposedPath(this.target);
+ };
+}
+
+function findFromPath(path, criteria, currentTarget) {
+ const [node, ...rest] = path;
+ if (criteria(node)) {
+ return node;
+ }
+ if (node === currentTarget || node.tagName === 'HTML' || rest.length === 0) {
+ // stop when reaching currentTarget or
+ return;
+ }
+ return findFromPath(rest, criteria, currentTarget);
+}
+
+// Search for the actual target of a delegated event
+export function findElementInEventPath(ev, selector) {
+ const criteria = typeof selector === 'function'
+ ? selector
+ : el => el instanceof Element && el.matches(selector);
+ return findFromPath(ev.composedPath(), criteria, ev.currentTarget);
+}
diff --git a/src/ui/static/js/datepicker/lib/utils.js b/src/ui/static/js/datepicker/lib/utils.js
new file mode 100644
index 000000000..5ad8a796c
--- /dev/null
+++ b/src/ui/static/js/datepicker/lib/utils.js
@@ -0,0 +1,61 @@
+export function hasProperty(obj, prop) {
+ return Object.prototype.hasOwnProperty.call(obj, prop);
+}
+
+export function lastItemOf(arr) {
+ return arr[arr.length - 1];
+}
+
+// push only the items not included in the array
+export function pushUnique(arr, ...items) {
+ items.forEach((item) => {
+ if (arr.includes(item)) {
+ return;
+ }
+ arr.push(item);
+ });
+ return arr;
+}
+
+export function stringToArray(str, separator) {
+ // convert empty string to an empty array
+ return str ? str.split(separator) : [];
+}
+
+export function isInRange(testVal, min, max) {
+ const minOK = min === undefined || testVal >= min;
+ const maxOK = max === undefined || testVal <= max;
+ return minOK && maxOK;
+}
+
+export function limitToRange(val, min, max) {
+ if (val < min) {
+ return min;
+ }
+ if (val > max) {
+ return max;
+ }
+ return val;
+}
+
+export function createTagRepeat(tagName, repeat, attributes = {}, index = 0, html = '') {
+ const openTagSrc = Object.keys(attributes).reduce((src, attr) => {
+ let val = attributes[attr];
+ if (typeof val === 'function') {
+ val = val(index);
+ }
+ return `${src} ${attr}="${val}"`;
+ }, tagName);
+ html += `<${openTagSrc}>${tagName}>`;
+
+ const next = index + 1;
+ return next < repeat
+ ? createTagRepeat(tagName, repeat, attributes, next, html)
+ : html;
+}
+
+// Remove the spacing surrounding tags for HTML parser not to create text nodes
+// before/after elements
+export function optimizeTemplateHTML(html) {
+ return html.replace(/>\s+/g, '>').replace(/\s+, '<');
+}
diff --git a/src/ui/static/js/datepicker/locales/ar-DZ.js b/src/ui/static/js/datepicker/locales/ar-DZ.js
new file mode 100644
index 000000000..dd7c8ddcb
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/ar-DZ.js
@@ -0,0 +1,19 @@
+/**
+ * Arabic-Algeria translation for bootstrap-datepicker
+ * Rabah Saadi
+ */
+(function () {
+ Datepicker.locales['ar-DZ'] = {
+ days: ["الأحد", "الاثنين", "الثلاثاء", "الأربعاء", "الخميس", "الجمعة", "السبت", "الأحد"],
+ daysShort: ["أحد", "اثنين", "ثلاثاء", "أربعاء", "خميس", "جمعة", "سبت", "أحد"],
+ daysMin: ["ح", "ن", "ث", "ع", "خ", "ج", "س", "ح"],
+ months: ["جانفي","فيفري","مارس","أفريل","ماي","جوان","جويليه","أوت","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],
+ monthsShort: ["جانفي","فيفري","مارس","أفريل","ماي","جوان","جويليه","أوت","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],
+ today: "هذا اليوم",
+ rtl: true,
+ monthsTitle: "أشهر",
+ clear: "إزالة",
+ format: "yyyy/mm/dd",
+ weekStart: 0
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/ar-tn.js b/src/ui/static/js/datepicker/locales/ar-tn.js
new file mode 100644
index 000000000..d94df17a9
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/ar-tn.js
@@ -0,0 +1,15 @@
+/**
+ * Arabic-Tunisia translation for bootstrap-datepicker
+ * Souhaieb Besbes
+ */
+(function () {
+ Datepicker.locales['ar-tn'] = {
+ days: ["الأحد", "الاثنين", "الثلاثاء", "الأربعاء", "الخميس", "الجمعة", "السبت", "الأحد"],
+ daysShort: ["أحد", "اثنين", "ثلاثاء", "أربعاء", "خميس", "جمعة", "سبت", "أحد"],
+ daysMin: ["ح", "ن", "ث", "ع", "خ", "ج", "س", "ح"],
+ months: ["جانفي","فيفري","مارس","أفريل","ماي","جوان","جويليه","أوت","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],
+ monthsShort: ["جانفي","فيفري","مارس","أفريل","ماي","جوان","جويليه","أوت","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],
+ today: "هذا اليوم",
+ rtl: true
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/ar.js b/src/ui/static/js/datepicker/locales/ar.js
new file mode 100644
index 000000000..608fe0d3e
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/ar.js
@@ -0,0 +1,15 @@
+/**
+ * Arabic translation for bootstrap-datepicker
+ * Mohammed Alshehri
+ */
+(function () {
+ Datepicker.locales.ar = {
+ days: ["الأحد", "الاثنين", "الثلاثاء", "الأربعاء", "الخميس", "الجمعة", "السبت", "الأحد"],
+ daysShort: ["أحد", "اثنين", "ثلاثاء", "أربعاء", "خميس", "جمعة", "سبت", "أحد"],
+ daysMin: ["ح", "ن", "ث", "ع", "خ", "ج", "س", "ح"],
+ months: ["يناير", "فبراير", "مارس", "أبريل", "مايو", "يونيو", "يوليو", "أغسطس", "سبتمبر", "أكتوبر", "نوفمبر", "ديسمبر"],
+ monthsShort: ["يناير", "فبراير", "مارس", "أبريل", "مايو", "يونيو", "يوليو", "أغسطس", "سبتمبر", "أكتوبر", "نوفمبر", "ديسمبر"],
+ today: "هذا اليوم",
+ rtl: true
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/az.js b/src/ui/static/js/datepicker/locales/az.js
new file mode 100644
index 000000000..ae3d4def8
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/az.js
@@ -0,0 +1,14 @@
+// Azerbaijani
+(function () {
+ Datepicker.locales.az = {
+ days: ["Bazar", "Bazar ertəsi", "Çərşənbə axşamı", "Çərşənbə", "Cümə axşamı", "Cümə", "Şənbə"],
+ daysShort: ["B.", "B.e", "Ç.a", "Ç.", "C.a", "C.", "Ş."],
+ daysMin: ["B.", "B.e", "Ç.a", "Ç.", "C.a", "C.", "Ş."],
+ months: ["Yanvar", "Fevral", "Mart", "Aprel", "May", "İyun", "İyul", "Avqust", "Sentyabr", "Oktyabr", "Noyabr", "Dekabr"],
+ monthsShort: ["Yan", "Fev", "Mar", "Apr", "May", "İyun", "İyul", "Avq", "Sen", "Okt", "Noy", "Dek"],
+ today: "Bu gün",
+ weekStart: 1,
+ clear: "Təmizlə",
+ monthsTitle: 'Aylar'
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/bg.js b/src/ui/static/js/datepicker/locales/bg.js
new file mode 100644
index 000000000..81d649efd
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/bg.js
@@ -0,0 +1,14 @@
+/**
+ * Bulgarian translation for bootstrap-datepicker
+ * Apostol Apostolov
+ */
+(function () {
+ Datepicker.locales.bg = {
+ days: ["Неделя", "Понеделник", "Вторник", "Сряда", "Четвъртък", "Петък", "Събота"],
+ daysShort: ["Нед", "Пон", "Вто", "Сря", "Чет", "Пет", "Съб"],
+ daysMin: ["Н", "П", "В", "С", "Ч", "П", "С"],
+ months: ["Януари", "Февруари", "Март", "Април", "Май", "Юни", "Юли", "Август", "Септември", "Октомври", "Ноември", "Декември"],
+ monthsShort: ["Ян", "Фев", "Мар", "Апр", "Май", "Юни", "Юли", "Авг", "Сеп", "Окт", "Ное", "Дек"],
+ today: "днес"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/bm.js b/src/ui/static/js/datepicker/locales/bm.js
new file mode 100644
index 000000000..57550b8fb
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/bm.js
@@ -0,0 +1,18 @@
+/**
+ * Bamanankan (bm) translation for bootstrap-datepicker
+ * Fatou Fall
+ */
+(function () {
+ Datepicker.locales.bm = {
+ days: ["Kari","Ntɛnɛn","Tarata","Araba","Alamisa","Juma","Sibiri"],
+ daysShort: ["Kar","Ntɛ","Tar","Ara","Ala","Jum","Sib"],
+ daysMin: ["Ka","Nt","Ta","Ar","Al","Ju","Si"],
+ months: ["Zanwuyekalo","Fewuruyekalo","Marisikalo","Awirilikalo","Mɛkalo","Zuwɛnkalo","Zuluyekalo","Utikalo","Sɛtanburukalo","ɔkutɔburukalo","Nowanburukalo","Desanburukalo"],
+ monthsShort: ["Zan","Few","Mar","Awi","Mɛ","Zuw","Zul","Uti","Sɛt","ɔku","Now","Des"],
+ today: "Bi",
+ monthsTitle: "Kalo",
+ clear: "Ka jɔsi",
+ weekStart: 1,
+ format: "dd/mm/yyyy"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/bn.js b/src/ui/static/js/datepicker/locales/bn.js
new file mode 100644
index 000000000..6143362af
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/bn.js
@@ -0,0 +1,19 @@
+/**
+ * Bengali (Bangla) translation for bootstrap-datepicker
+ * Karim Khan
+ * Orif N. Jr.
+ */
+(function () {
+ Datepicker.locales.bn = {
+ days: ["রবিবার","সোমবার","মঙ্গলবার","বুধবার","বৃহস্পতিবার","শুক্রবার","শনিবার"],
+ daysShort: ["রবিবার","সোমবার","মঙ্গলবার","বুধবার","বৃহস্পতিবার","শুক্রবার","শনিবার"],
+ daysMin: ["রবি","সোম","মঙ্গল","বুধ","বৃহস্পতি","শুক্র","শনি"],
+ months: ["জানুয়ারী","ফেব্রুয়ারি","মার্চ","এপ্রিল","মে","জুন","জুলাই","অগাস্ট","সেপ্টেম্বর","অক্টোবর","নভেম্বর","ডিসেম্বর"],
+ monthsShort: ["জানুয়ারী","ফেব্রুয়ারি","মার্চ","এপ্রিল","মে","জুন","জুলাই","অগাস্ট","সেপ্টেম্বর","অক্টোবর","নভেম্বর","ডিসেম্বর"],
+ today: "আজ",
+ monthsTitle: "মাস",
+ clear: "পরিষ্কার",
+ weekStart: 0,
+ format: "mm/dd/yyyy"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/br.js b/src/ui/static/js/datepicker/locales/br.js
new file mode 100644
index 000000000..f6419a589
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/br.js
@@ -0,0 +1,18 @@
+/**
+ * Breton translation for bootstrap-datepicker
+ * Gwenn Meynier
+ */
+(function () {
+ Datepicker.locales.br = {
+ days: ["Sul", "Lun", "Meurzh", "Merc'her", "Yaou", "Gwener", "Sadorn"],
+ daysShort: ["Sul", "Lun", "Meu.", "Mer.", "Yao.", "Gwe.", "Sad."],
+ daysMin: ["Su", "L", "Meu", "Mer", "Y", "G", "Sa"],
+ months: ["Genver", "C'hwevrer", "Meurzh", "Ebrel", "Mae", "Mezheven", "Gouere", "Eost", "Gwengolo", "Here", "Du", "Kerzu"],
+ monthsShort: ["Genv.", "C'hw.", "Meur.", "Ebre.", "Mae", "Mezh.", "Goue.", "Eost", "Gwen.", "Here", "Du", "Kerz."],
+ today: "Hiziv",
+ monthsTitle: "Miz",
+ clear: "Dilemel",
+ weekStart: 1,
+ format: "dd/mm/yyyy"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/bs.js b/src/ui/static/js/datepicker/locales/bs.js
new file mode 100644
index 000000000..306f163d3
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/bs.js
@@ -0,0 +1,15 @@
+/**
+ * Bosnian translation for bootstrap-datepicker
+ */
+(function () {
+ Datepicker.locales.bs = {
+ days: ["Nedjelja","Ponedjeljak", "Utorak", "Srijeda", "Četvrtak", "Petak", "Subota"],
+ daysShort: ["Ned", "Pon", "Uto", "Sri", "Čet", "Pet", "Sub"],
+ daysMin: ["N", "Po", "U", "Sr", "Č", "Pe", "Su"],
+ months: ["Januar", "Februar", "Mart", "April", "Maj", "Juni", "Juli", "August", "Septembar", "Oktobar", "Novembar", "Decembar"],
+ monthsShort: ["Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec"],
+ today: "Danas",
+ weekStart: 1,
+ format: "dd.mm.yyyy"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/ca.js b/src/ui/static/js/datepicker/locales/ca.js
new file mode 100644
index 000000000..20c30beac
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/ca.js
@@ -0,0 +1,18 @@
+/**
+ * Catalan translation for bootstrap-datepicker
+ * J. Garcia
+ */
+(function () {
+ Datepicker.locales.ca = {
+ days: ["diumenge", "dilluns", "dimarts", "dimecres", "dijous", "divendres", "dissabte"],
+ daysShort: ["dg.", "dl.", "dt.", "dc.", "dj.", "dv.", "ds."],
+ daysMin: ["dg", "dl", "dt", "dc", "dj", "dv", "ds"],
+ months: ["gener", "febrer", "març", "abril", "maig", "juny", "juliol", "agost", "setembre", "octubre", "novembre", "desembre"],
+ monthsShort: ["gen.", "febr.", "març", "abr.", "maig", "juny", "jul.", "ag.", "set.", "oct.", "nov.", "des."],
+ today: "Avui",
+ monthsTitle: "Mesos",
+ clear: "Esborra",
+ weekStart: 1,
+ format: "dd/mm/yyyy"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/cs.js b/src/ui/static/js/datepicker/locales/cs.js
new file mode 100644
index 000000000..7531dda83
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/cs.js
@@ -0,0 +1,19 @@
+/**
+ * Czech translation for bootstrap-datepicker
+ * Matěj Koubík
+ * Fixes by Michal Remiš
+ */
+(function () {
+ Datepicker.locales.cs = {
+ days: ["Neděle", "Pondělí", "Úterý", "Středa", "Čtvrtek", "Pátek", "Sobota"],
+ daysShort: ["Ned", "Pon", "Úte", "Stř", "Čtv", "Pát", "Sob"],
+ daysMin: ["Ne", "Po", "Út", "St", "Čt", "Pá", "So"],
+ months: ["Leden", "Únor", "Březen", "Duben", "Květen", "Červen", "Červenec", "Srpen", "Září", "Říjen", "Listopad", "Prosinec"],
+ monthsShort: ["Led", "Úno", "Bře", "Dub", "Kvě", "Čer", "Čnc", "Srp", "Zář", "Říj", "Lis", "Pro"],
+ today: "Dnes",
+ clear: "Vymazat",
+ monthsTitle: "Měsíc",
+ weekStart: 1,
+ format: "dd.mm.yyyy"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/cy.js b/src/ui/static/js/datepicker/locales/cy.js
new file mode 100644
index 000000000..7c609992f
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/cy.js
@@ -0,0 +1,14 @@
+/**
+ * Welsh translation for bootstrap-datepicker
+ * S. Morris
+ */
+(function () {
+ Datepicker.locales.cy = {
+ days: ["Sul", "Llun", "Mawrth", "Mercher", "Iau", "Gwener", "Sadwrn"],
+ daysShort: ["Sul", "Llu", "Maw", "Mer", "Iau", "Gwe", "Sad"],
+ daysMin: ["Su", "Ll", "Ma", "Me", "Ia", "Gwe", "Sa"],
+ months: ["Ionawr", "Chewfror", "Mawrth", "Ebrill", "Mai", "Mehefin", "Gorfennaf", "Awst", "Medi", "Hydref", "Tachwedd", "Rhagfyr"],
+ monthsShort: ["Ion", "Chw", "Maw", "Ebr", "Mai", "Meh", "Gor", "Aws", "Med", "Hyd", "Tach", "Rha"],
+ today: "Heddiw"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/da.js b/src/ui/static/js/datepicker/locales/da.js
new file mode 100644
index 000000000..fb7a18961
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/da.js
@@ -0,0 +1,19 @@
+/**
+ * Danish translation for bootstrap-datepicker
+ * Christian Pedersen
+ * Ivan Mylyanyk
+ */
+(function () {
+ Datepicker.locales.da = {
+ days: ["Søndag", "Mandag", "Tirsdag", "Onsdag", "Torsdag", "Fredag", "Lørdag"],
+ daysShort: ["Søn", "Man", "Tir", "Ons", "Tor", "Fre", "Lør"],
+ daysMin: ["Sø", "Ma", "Ti", "On", "To", "Fr", "Lø"],
+ months: ["Januar", "Februar", "Marts", "April", "Maj", "Juni", "Juli", "August", "September", "Oktober", "November", "December"],
+ monthsShort: ["Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec"],
+ today: "I Dag",
+ weekStart: 1,
+ clear: "Nulstil",
+ format: "dd/mm/yyyy",
+ monthsTitle: "Måneder"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/de.js b/src/ui/static/js/datepicker/locales/de.js
new file mode 100644
index 000000000..60c87be51
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/de.js
@@ -0,0 +1,18 @@
+/**
+ * German translation for bootstrap-datepicker
+ * Sam Zurcher
+ */
+(function () {
+ Datepicker.locales.de = {
+ days: ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"],
+ daysShort: ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"],
+ daysMin: ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"],
+ months: ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"],
+ monthsShort: ["Jan", "Feb", "Mär", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"],
+ today: "Heute",
+ monthsTitle: "Monate",
+ clear: "Löschen",
+ weekStart: 1,
+ format: "dd.mm.yyyy"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/el.js b/src/ui/static/js/datepicker/locales/el.js
new file mode 100644
index 000000000..a65a21dc6
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/el.js
@@ -0,0 +1,16 @@
+/**
+ * Greek translation for bootstrap-datepicker
+ */
+(function () {
+ Datepicker.locales.el = {
+ days: ["Κυριακή", "Δευτέρα", "Τρίτη", "Τετάρτη", "Πέμπτη", "Παρασκευή", "Σάββατο"],
+ daysShort: ["Κυρ", "Δευ", "Τρι", "Τετ", "Πεμ", "Παρ", "Σαβ"],
+ daysMin: ["Κυ", "Δε", "Τρ", "Τε", "Πε", "Πα", "Σα"],
+ months: ["Ιανουάριος", "Φεβρουάριος", "Μάρτιος", "Απρίλιος", "Μάιος", "Ιούνιος", "Ιούλιος", "Αύγουστος", "Σεπτέμβριος", "Οκτώβριος", "Νοέμβριος", "Δεκέμβριος"],
+ monthsShort: ["Ιαν", "Φεβ", "Μαρ", "Απρ", "Μάι", "Ιουν", "Ιουλ", "Αυγ", "Σεπ", "Οκτ", "Νοε", "Δεκ"],
+ today: "Σήμερα",
+ clear: "Καθαρισμός",
+ weekStart: 1,
+ format: "d/m/yyyy"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/en-AU.js b/src/ui/static/js/datepicker/locales/en-AU.js
new file mode 100644
index 000000000..6d8455619
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/en-AU.js
@@ -0,0 +1,18 @@
+/**
+ * Australian English translation for bootstrap-datepicker
+ * Steve Chapman
+ */
+(function () {
+ Datepicker.locales['en-AU'] = {
+ days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
+ daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
+ daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"],
+ months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
+ monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
+ today: "Today",
+ monthsTitle: "Months",
+ clear: "Clear",
+ weekStart: 1,
+ format: "d/mm/yyyy"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/en-CA.js b/src/ui/static/js/datepicker/locales/en-CA.js
new file mode 100644
index 000000000..3a35c32d2
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/en-CA.js
@@ -0,0 +1,18 @@
+/**
+ * Canadian English translation for bootstrap-datepicker
+ * Mike Nacey
+ */
+(function () {
+ Datepicker.locales['en-CA'] = {
+ days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
+ daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
+ daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"],
+ months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
+ monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
+ today: "Today",
+ monthsTitle: "Months",
+ clear: "Clear",
+ weekStart: 0,
+ format: "yyyy-mm-dd"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/en-GB.js b/src/ui/static/js/datepicker/locales/en-GB.js
new file mode 100644
index 000000000..da848f97f
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/en-GB.js
@@ -0,0 +1,18 @@
+/**
+ * British English translation for bootstrap-datepicker
+ * Xavier Dutreilh
+ */
+(function () {
+ Datepicker.locales['en-GB'] = {
+ days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
+ daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
+ daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"],
+ months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
+ monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
+ today: "Today",
+ monthsTitle: "Months",
+ clear: "Clear",
+ weekStart: 1,
+ format: "dd/mm/yyyy"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/en-IE.js b/src/ui/static/js/datepicker/locales/en-IE.js
new file mode 100644
index 000000000..1a41302cf
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/en-IE.js
@@ -0,0 +1,17 @@
+/**
+ * Irish English translation for bootstrap-datepicker
+ */
+(function () {
+ Datepicker.locales['en-IE'] = {
+ days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
+ daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
+ daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"],
+ months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
+ monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
+ today: "Today",
+ monthsTitle: "Months",
+ clear: "Clear",
+ weekStart: 1,
+ format: "dd/mm/yyyy"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/en-NZ.js b/src/ui/static/js/datepicker/locales/en-NZ.js
new file mode 100644
index 000000000..dd34ac41d
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/en-NZ.js
@@ -0,0 +1,17 @@
+/**
+ * New Zealand English translation for bootstrap-datepicker
+ */
+(function () {
+ Datepicker.locales['en-NZ'] = {
+ days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
+ daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
+ daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"],
+ months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
+ monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
+ today: "Today",
+ monthsTitle: "Months",
+ clear: "Clear",
+ weekStart: 1,
+ format: "d/mm/yyyy"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/en-ZA.js b/src/ui/static/js/datepicker/locales/en-ZA.js
new file mode 100644
index 000000000..6455097d1
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/en-ZA.js
@@ -0,0 +1,17 @@
+/**
+ * South African English translation for bootstrap-datepicker
+ */
+(function () {
+ Datepicker.locales['en-ZA'] = {
+ days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
+ daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
+ daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"],
+ months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
+ monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
+ today: "Today",
+ monthsTitle: "Months",
+ clear: "Clear",
+ weekStart: 1,
+ format: "yyyy/mm/d"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/eo.js b/src/ui/static/js/datepicker/locales/eo.js
new file mode 100644
index 000000000..f68306559
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/eo.js
@@ -0,0 +1,17 @@
+/**
+ * Esperanto translation for bootstrap-datepicker
+ * Emmanuel Debanne
+ */
+(function () {
+ Datepicker.locales.eo = {
+ days: ["dimanĉo", "lundo", "mardo", "merkredo", "ĵaŭdo", "vendredo", "sabato"],
+ daysShort: ["dim.", "lun.", "mar.", "mer.", "ĵaŭ.", "ven.", "sam."],
+ daysMin: ["d", "l", "ma", "me", "ĵ", "v", "s"],
+ months: ["januaro", "februaro", "marto", "aprilo", "majo", "junio", "julio", "aŭgusto", "septembro", "oktobro", "novembro", "decembro"],
+ monthsShort: ["jan.", "feb.", "mar.", "apr.", "majo", "jun.", "jul.", "aŭg.", "sep.", "okt.", "nov.", "dec."],
+ today: "Hodiaŭ",
+ clear: "Nuligi",
+ weekStart: 1,
+ format: "yyyy-mm-dd"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/es.js b/src/ui/static/js/datepicker/locales/es.js
new file mode 100644
index 000000000..d2be3f872
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/es.js
@@ -0,0 +1,18 @@
+/**
+ * Spanish translation for bootstrap-datepicker
+ * Bruno Bonamin
+ */
+(function () {
+ Datepicker.locales.es = {
+ days: ["Domingo", "Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sábado"],
+ daysShort: ["Dom", "Lun", "Mar", "Mié", "Jue", "Vie", "Sáb"],
+ daysMin: ["Do", "Lu", "Ma", "Mi", "Ju", "Vi", "Sa"],
+ months: ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"],
+ monthsShort: ["Ene", "Feb", "Mar", "Abr", "May", "Jun", "Jul", "Ago", "Sep", "Oct", "Nov", "Dic"],
+ today: "Hoy",
+ monthsTitle: "Meses",
+ clear: "Borrar",
+ weekStart: 1,
+ format: "dd/mm/yyyy"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/et.js b/src/ui/static/js/datepicker/locales/et.js
new file mode 100644
index 000000000..35a71def0
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/et.js
@@ -0,0 +1,18 @@
+/**
+ * Estonian translation for bootstrap-datepicker
+ * Ando Roots
+ * Fixes by Illimar Tambek <
+ */
+(function () {
+ Datepicker.locales.et = {
+ days: ["Pühapäev", "Esmaspäev", "Teisipäev", "Kolmapäev", "Neljapäev", "Reede", "Laupäev"],
+ daysShort: ["Pühap", "Esmasp", "Teisip", "Kolmap", "Neljap", "Reede", "Laup"],
+ daysMin: ["P", "E", "T", "K", "N", "R", "L"],
+ months: ["Jaanuar", "Veebruar", "Märts", "Aprill", "Mai", "Juuni", "Juuli", "August", "September", "Oktoober", "November", "Detsember"],
+ monthsShort: ["Jaan", "Veebr", "Märts", "Apr", "Mai", "Juuni", "Juuli", "Aug", "Sept", "Okt", "Nov", "Dets"],
+ today: "Täna",
+ clear: "Tühjenda",
+ weekStart: 1,
+ format: "dd.mm.yyyy"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/eu.js b/src/ui/static/js/datepicker/locales/eu.js
new file mode 100644
index 000000000..fd664f209
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/eu.js
@@ -0,0 +1,18 @@
+/**
+ * Basque translation for bootstrap-datepicker
+ * Arkaitz Etxeberria
+ */
+(function () {
+ Datepicker.locales.eu = {
+ days: ['Igandea', 'Astelehena', 'Asteartea', 'Asteazkena', 'Osteguna', 'Ostirala', 'Larunbata'],
+ daysShort: ['Ig', 'Al', 'Ar', 'Az', 'Og', 'Ol', 'Lr'],
+ daysMin: ['Ig', 'Al', 'Ar', 'Az', 'Og', 'Ol', 'Lr'],
+ months: ['Urtarrila', 'Otsaila', 'Martxoa', 'Apirila', 'Maiatza', 'Ekaina', 'Uztaila', 'Abuztua', 'Iraila', 'Urria', 'Azaroa', 'Abendua'],
+ monthsShort: ['Urt', 'Ots', 'Mar', 'Api', 'Mai', 'Eka', 'Uzt', 'Abu', 'Ira', 'Urr', 'Aza', 'Abe'],
+ today: "Gaur",
+ monthsTitle: "Hilabeteak",
+ clear: "Ezabatu",
+ weekStart: 1,
+ format: "yyyy/mm/dd"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/fa.js b/src/ui/static/js/datepicker/locales/fa.js
new file mode 100644
index 000000000..3e1e43e83
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/fa.js
@@ -0,0 +1,17 @@
+/**
+ * Persian translation for bootstrap-datepicker
+ * Mostafa Rokooie
+ */
+(function () {
+ Datepicker.locales.fa = {
+ days: ["یکشنبه", "دوشنبه", "سهشنبه", "چهارشنبه", "پنجشنبه", "جمعه", "شنبه", "یکشنبه"],
+ daysShort: ["یک", "دو", "سه", "چهار", "پنج", "جمعه", "شنبه", "یک"],
+ daysMin: ["ی", "د", "س", "چ", "پ", "ج", "ش", "ی"],
+ months: ["ژانویه", "فوریه", "مارس", "آوریل", "مه", "ژوئن", "ژوئیه", "اوت", "سپتامبر", "اکتبر", "نوامبر", "دسامبر"],
+ monthsShort: ["ژان", "فور", "مار", "آور", "مه", "ژون", "ژوی", "اوت", "سپت", "اکت", "نوا", "دسا"],
+ today: "امروز",
+ clear: "پاک کن",
+ weekStart: 1,
+ format: "yyyy/mm/dd"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/fi.js b/src/ui/static/js/datepicker/locales/fi.js
new file mode 100644
index 000000000..bfd8cd052
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/fi.js
@@ -0,0 +1,17 @@
+/**
+ * Finnish translation for bootstrap-datepicker
+ * Jaakko Salonen
+ */
+(function () {
+ Datepicker.locales.fi = {
+ days: ["sunnuntai", "maanantai", "tiistai", "keskiviikko", "torstai", "perjantai", "lauantai"],
+ daysShort: ["sun", "maa", "tii", "kes", "tor", "per", "lau"],
+ daysMin: ["su", "ma", "ti", "ke", "to", "pe", "la"],
+ months: ["tammikuu", "helmikuu", "maaliskuu", "huhtikuu", "toukokuu", "kesäkuu", "heinäkuu", "elokuu", "syyskuu", "lokakuu", "marraskuu", "joulukuu"],
+ monthsShort: ["tammi", "helmi", "maalis", "huhti", "touko", "kesä", "heinä", "elo", "syys", "loka", "marras", "joulu"],
+ today: "tänään",
+ clear: "Tyhjennä",
+ weekStart: 1,
+ format: "d.m.yyyy"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/fo.js b/src/ui/static/js/datepicker/locales/fo.js
new file mode 100644
index 000000000..18d19491b
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/fo.js
@@ -0,0 +1,15 @@
+/**
+ * Faroese translation for bootstrap-datepicker
+ * Theodor Johannesen
+ */
+(function () {
+ Datepicker.locales.fo = {
+ days: ["Sunnudagur", "Mánadagur", "Týsdagur", "Mikudagur", "Hósdagur", "Fríggjadagur", "Leygardagur"],
+ daysShort: ["Sun", "Mán", "Týs", "Mik", "Hós", "Frí", "Ley"],
+ daysMin: ["Su", "Má", "Tý", "Mi", "Hó", "Fr", "Le"],
+ months: ["Januar", "Februar", "Marts", "Apríl", "Mei", "Juni", "Juli", "August", "Septembur", "Oktobur", "Novembur", "Desembur"],
+ monthsShort: ["Jan", "Feb", "Mar", "Apr", "Mei", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Des"],
+ today: "Í Dag",
+ clear: "Reinsa"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/fr-CH.js b/src/ui/static/js/datepicker/locales/fr-CH.js
new file mode 100644
index 000000000..278a638b6
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/fr-CH.js
@@ -0,0 +1,21 @@
+/**
+ * French (Switzerland) translation for bootstrap-datepicker
+ * Christoph Jossi
+ * Based on
+ * French translation for bootstrap-datepicker
+ * Nico Mollet
+ */
+(function () {
+ Datepicker.locales['fr-CH'] = {
+ days: ["Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi"],
+ daysShort: ["Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam"],
+ daysMin: ["D", "L", "Ma", "Me", "J", "V", "S"],
+ months: ["Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre"],
+ monthsShort: ["Jan", "Fév", "Mar", "Avr", "Mai", "Jui", "Jul", "Aou", "Sep", "Oct", "Nov", "Déc"],
+ today: "Aujourd'hui",
+ monthsTitle: "Mois",
+ clear: "Effacer",
+ weekStart: 1,
+ format: "dd.mm.yyyy"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/fr.js b/src/ui/static/js/datepicker/locales/fr.js
new file mode 100644
index 000000000..86323f884
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/fr.js
@@ -0,0 +1,18 @@
+/**
+ * French translation for bootstrap-datepicker
+ * Nico Mollet
+ */
+(function () {
+ Datepicker.locales.fr = {
+ days: ["dimanche", "lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi"],
+ daysShort: ["dim.", "lun.", "mar.", "mer.", "jeu.", "ven.", "sam."],
+ daysMin: ["d", "l", "ma", "me", "j", "v", "s"],
+ months: ["janvier", "février", "mars", "avril", "mai", "juin", "juillet", "août", "septembre", "octobre", "novembre", "décembre"],
+ monthsShort: ["janv.", "févr.", "mars", "avril", "mai", "juin", "juil.", "août", "sept.", "oct.", "nov.", "déc."],
+ today: "Aujourd'hui",
+ monthsTitle: "Mois",
+ clear: "Effacer",
+ weekStart: 1,
+ format: "dd/mm/yyyy"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/gl.js b/src/ui/static/js/datepicker/locales/gl.js
new file mode 100644
index 000000000..1b52b5a4a
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/gl.js
@@ -0,0 +1,16 @@
+/**
+ * Galician translation
+ */
+(function () {
+ Datepicker.locales.gl = {
+ days: ["Domingo", "Luns", "Martes", "Mércores", "Xoves", "Venres", "Sábado"],
+ daysShort: ["Dom", "Lun", "Mar", "Mér", "Xov", "Ven", "Sáb"],
+ daysMin: ["Do", "Lu", "Ma", "Me", "Xo", "Ve", "Sa"],
+ months: ["Xaneiro", "Febreiro", "Marzo", "Abril", "Maio", "Xuño", "Xullo", "Agosto", "Setembro", "Outubro", "Novembro", "Decembro"],
+ monthsShort: ["Xan", "Feb", "Mar", "Abr", "Mai", "Xun", "Xul", "Ago", "Sep", "Out", "Nov", "Dec"],
+ today: "Hoxe",
+ clear: "Limpar",
+ weekStart: 1,
+ format: "dd/mm/yyyy"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/he.js b/src/ui/static/js/datepicker/locales/he.js
new file mode 100644
index 000000000..4c1138f7a
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/he.js
@@ -0,0 +1,15 @@
+/**
+ * Hebrew translation for bootstrap-datepicker
+ * Sagie Maoz
+ */
+(function () {
+ Datepicker.locales.he = {
+ days: ["ראשון", "שני", "שלישי", "רביעי", "חמישי", "שישי", "שבת", "ראשון"],
+ daysShort: ["א", "ב", "ג", "ד", "ה", "ו", "ש", "א"],
+ daysMin: ["א", "ב", "ג", "ד", "ה", "ו", "ש", "א"],
+ months: ["ינואר", "פברואר", "מרץ", "אפריל", "מאי", "יוני", "יולי", "אוגוסט", "ספטמבר", "אוקטובר", "נובמבר", "דצמבר"],
+ monthsShort: ["ינו", "פבר", "מרץ", "אפר", "מאי", "יונ", "יול", "אוג", "ספט", "אוק", "נוב", "דצמ"],
+ today: "היום",
+ rtl: true
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/hi.js b/src/ui/static/js/datepicker/locales/hi.js
new file mode 100644
index 000000000..48e41cc35
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/hi.js
@@ -0,0 +1,18 @@
+/**
+ * Hindi translation for bootstrap-datepicker
+ * Visar Uruqi
+ */
+(function () {
+ Datepicker.locales.hi = {
+ days: ["रविवार", "सोमवार", "मंगलवार", "बुधवार", "गुरुवार", "शुक्रवार", "शनिवार"],
+ daysShort: ["सूर्य", "सोम", "मंगल", "बुध", "गुरु", "शुक्र", "शनि"],
+ daysMin: ["र", "सो", "मं", "बु", "गु", "शु", "श"],
+ months: ["जनवरी", "फ़रवरी", "मार्च", "अप्रैल", "मई", "जून", "जुलाई", "अगस्त", "सितम्बर", "अक्टूबर", "नवंबर", "दिसम्बर"],
+ monthsShort: ["जन", "फ़रवरी", "मार्च", "अप्रैल", "मई", "जून", "जुलाई", "अगस्त", "सितं", "अक्टूबर", "नवं", "दिसम्बर"],
+ today: "आज",
+ monthsTitle: "महीने",
+ clear: "साफ",
+ weekStart: 1,
+ format: "dd / mm / yyyy"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/hr.js b/src/ui/static/js/datepicker/locales/hr.js
new file mode 100644
index 000000000..18544a0e2
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/hr.js
@@ -0,0 +1,13 @@
+/**
+ * Croatian localisation
+ */
+(function () {
+ Datepicker.locales.hr = {
+ days: ["Nedjelja", "Ponedjeljak", "Utorak", "Srijeda", "Četvrtak", "Petak", "Subota"],
+ daysShort: ["Ned", "Pon", "Uto", "Sri", "Čet", "Pet", "Sub"],
+ daysMin: ["Ne", "Po", "Ut", "Sr", "Če", "Pe", "Su"],
+ months: ["Siječanj", "Veljača", "Ožujak", "Travanj", "Svibanj", "Lipanj", "Srpanj", "Kolovoz", "Rujan", "Listopad", "Studeni", "Prosinac"],
+ monthsShort: ["Sij", "Velj", "Ožu", "Tra", "Svi", "Lip", "Srp", "Kol", "Ruj", "Lis", "Stu", "Pro"],
+ today: "Danas"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/hu.js b/src/ui/static/js/datepicker/locales/hu.js
new file mode 100644
index 000000000..5eaffa61d
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/hu.js
@@ -0,0 +1,18 @@
+/**
+ * Hungarian translation for bootstrap-datepicker
+ * Sotus László
+ */
+(function () {
+ Datepicker.locales.hu = {
+ days: ["vasárnap", "hétfő", "kedd", "szerda", "csütörtök", "péntek", "szombat"],
+ daysShort: ["vas", "hét", "ked", "sze", "csü", "pén", "szo"],
+ daysMin: ["V", "H", "K", "Sze", "Cs", "P", "Szo"],
+ months: ["január", "február", "március", "április", "május", "június", "július", "augusztus", "szeptember", "október", "november", "december"],
+ monthsShort: ["jan", "feb", "már", "ápr", "máj", "jún", "júl", "aug", "sze", "okt", "nov", "dec"],
+ today: "ma",
+ weekStart: 1,
+ clear: "töröl",
+ titleFormat: "y. MM",
+ format: "yyyy.mm.dd"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/hy.js b/src/ui/static/js/datepicker/locales/hy.js
new file mode 100644
index 000000000..dd662d0df
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/hy.js
@@ -0,0 +1,18 @@
+/**
+ * Armenian translation for bootstrap-datepicker
+ * Hayk Chamyan
+ */
+(function () {
+ Datepicker.locales.hy = {
+ days: ["Կիրակի", "Երկուշաբթի", "Երեքշաբթի", "Չորեքշաբթի", "Հինգշաբթի", "Ուրբաթ", "Շաբաթ"],
+ daysShort: ["Կիր", "Երկ", "Երե", "Չոր", "Հին", "Ուրբ", "Շաբ"],
+ daysMin: ["Կի", "Եկ", "Եք", "Չո", "Հի", "Ու", "Շա"],
+ months: ["Հունվար", "Փետրվար", "Մարտ", "Ապրիլ", "Մայիս", "Հունիս", "Հուլիս", "Օգոստոս", "Սեպտեմբեր", "Հոկտեմբեր", "Նոյեմբեր", "Դեկտեմբեր"],
+ monthsShort: ["Հնվ", "Փետ", "Մար", "Ապր", "Մայ", "Հուն", "Հուլ", "Օգս", "Սեպ", "Հոկ", "Նոյ", "Դեկ"],
+ today: "Այսօր",
+ clear: "Ջնջել",
+ format: "dd.mm.yyyy",
+ weekStart: 1,
+ monthsTitle: 'Ամիսնէր'
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/id.js b/src/ui/static/js/datepicker/locales/id.js
new file mode 100644
index 000000000..0f0c2b9fa
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/id.js
@@ -0,0 +1,19 @@
+/**
+ * Bahasa translation for bootstrap-datepicker
+ * Azwar Akbar
+ * Ardeman
+ */
+(function () {
+ Datepicker.locales.id = {
+ days: ["Minggu", "Senin", "Selasa", "Rabu", "Kamis", "Jumat", "Sabtu"],
+ daysShort: ["Min", "Sen", "Sel", "Rab", "Kam", "Jum", "Sab"],
+ daysMin: ["Mg", "Sn", "Sl", "Rb", "Km", "Jm", "Sb"],
+ months: ["Januari", "Februari", "Maret", "April", "Mei", "Juni", "Juli", "Agustus", "September", "Oktober", "November", "Desember"],
+ monthsShort: ["Jan", "Feb", "Mar", "Apr", "Mei", "Jun", "Jul", "Agt", "Sep", "Okt", "Nov", "Des"],
+ today: "Hari Ini",
+ monthsTitle: "Bulan",
+ clear: "Kosongkan",
+ weekStart: 0,
+ format: "dd-mm-yyyy"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/is.js b/src/ui/static/js/datepicker/locales/is.js
new file mode 100644
index 000000000..18f818dc4
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/is.js
@@ -0,0 +1,14 @@
+/**
+ * Icelandic translation for bootstrap-datepicker
+ * Hinrik Örn Sigurðsson
+ */
+(function () {
+ Datepicker.locales.is = {
+ days: ["Sunnudagur", "Mánudagur", "Þriðjudagur", "Miðvikudagur", "Fimmtudagur", "Föstudagur", "Laugardagur"],
+ daysShort: ["Sun", "Mán", "Þri", "Mið", "Fim", "Fös", "Lau"],
+ daysMin: ["Su", "Má", "Þr", "Mi", "Fi", "Fö", "La"],
+ months: ["Janúar", "Febrúar", "Mars", "Apríl", "Maí", "Júní", "Júlí", "Ágúst", "September", "Október", "Nóvember", "Desember"],
+ monthsShort: ["Jan", "Feb", "Mar", "Apr", "Maí", "Jún", "Júl", "Ágú", "Sep", "Okt", "Nóv", "Des"],
+ today: "Í Dag"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/it-CH.js b/src/ui/static/js/datepicker/locales/it-CH.js
new file mode 100644
index 000000000..b1081cd4a
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/it-CH.js
@@ -0,0 +1,20 @@
+/**
+ * Italian (Switzerland) translation for bootstrap-datepicker
+ * Christoph Jossi
+ * Based on
+ * Italian translation for bootstrap-datepicker
+ * Enrico Rubboli
+ */
+(function () {
+ Datepicker.locales['it-CH'] = {
+ days: ["Domenica", "Lunedì", "Martedì", "Mercoledì", "Giovedì", "Venerdì", "Sabato"],
+ daysShort: ["Dom", "Lun", "Mar", "Mer", "Gio", "Ven", "Sab"],
+ daysMin: ["Do", "Lu", "Ma", "Me", "Gi", "Ve", "Sa"],
+ months: ["Gennaio", "Febbraio", "Marzo", "Aprile", "Maggio", "Giugno", "Luglio", "Agosto", "Settembre", "Ottobre", "Novembre", "Dicembre"],
+ monthsShort: ["Gen", "Feb", "Mar", "Apr", "Mag", "Giu", "Lug", "Ago", "Set", "Ott", "Nov", "Dic"],
+ today: "Oggi",
+ clear: "Cancella",
+ weekStart: 1,
+ format: "dd.mm.yyyy"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/it.js b/src/ui/static/js/datepicker/locales/it.js
new file mode 100644
index 000000000..70d98ab70
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/it.js
@@ -0,0 +1,18 @@
+/**
+ * Italian translation for bootstrap-datepicker
+ * Enrico Rubboli
+ */
+(function () {
+ Datepicker.locales.it = {
+ days: ["Domenica", "Lunedì", "Martedì", "Mercoledì", "Giovedì", "Venerdì", "Sabato"],
+ daysShort: ["Dom", "Lun", "Mar", "Mer", "Gio", "Ven", "Sab"],
+ daysMin: ["Do", "Lu", "Ma", "Me", "Gi", "Ve", "Sa"],
+ months: ["Gennaio", "Febbraio", "Marzo", "Aprile", "Maggio", "Giugno", "Luglio", "Agosto", "Settembre", "Ottobre", "Novembre", "Dicembre"],
+ monthsShort: ["Gen", "Feb", "Mar", "Apr", "Mag", "Giu", "Lug", "Ago", "Set", "Ott", "Nov", "Dic"],
+ today: "Oggi",
+ monthsTitle: "Mesi",
+ clear: "Cancella",
+ weekStart: 1,
+ format: "dd/mm/yyyy"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/ja.js b/src/ui/static/js/datepicker/locales/ja.js
new file mode 100644
index 000000000..f1c1b3030
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/ja.js
@@ -0,0 +1,17 @@
+/**
+ * Japanese translation for bootstrap-datepicker
+ * Norio Suzuki
+ */
+(function () {
+ Datepicker.locales.ja = {
+ days: ["日曜", "月曜", "火曜", "水曜", "木曜", "金曜", "土曜"],
+ daysShort: ["日", "月", "火", "水", "木", "金", "土"],
+ daysMin: ["日", "月", "火", "水", "木", "金", "土"],
+ months: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"],
+ monthsShort: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"],
+ today: "今日",
+ format: "yyyy/mm/dd",
+ titleFormat: "y年mm月",
+ clear: "クリア"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/ka.js b/src/ui/static/js/datepicker/locales/ka.js
new file mode 100644
index 000000000..b0cd474a4
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/ka.js
@@ -0,0 +1,17 @@
+/**
+ * Georgian translation for bootstrap-datepicker
+ * Levan Melikishvili
+ */
+(function () {
+ Datepicker.locales.ka = {
+ days: ["კვირა", "ორშაბათი", "სამშაბათი", "ოთხშაბათი", "ხუთშაბათი", "პარასკევი", "შაბათი"],
+ daysShort: ["კვი", "ორშ", "სამ", "ოთხ", "ხუთ", "პარ", "შაბ"],
+ daysMin: ["კვ", "ორ", "სა", "ოთ", "ხუ", "პა", "შა"],
+ months: ["იანვარი", "თებერვალი", "მარტი", "აპრილი", "მაისი", "ივნისი", "ივლისი", "აგვისტო", "სექტემბერი", "ოქტომბერი", "ნოემბერი", "დეკემბერი"],
+ monthsShort: ["იან", "თებ", "მარ", "აპრ", "მაი", "ივნ", "ივლ", "აგვ", "სექ", "ოქტ", "ნოე", "დეკ"],
+ today: "დღეს",
+ clear: "გასუფთავება",
+ weekStart: 1,
+ format: "dd.mm.yyyy"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/kk.js b/src/ui/static/js/datepicker/locales/kk.js
new file mode 100644
index 000000000..9b85f8cf9
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/kk.js
@@ -0,0 +1,15 @@
+/**
+ * Kazakh translation for bootstrap-datepicker
+ * Yerzhan Tolekov
+ */
+(function () {
+ Datepicker.locales.kk = {
+ days: ["Жексенбі", "Дүйсенбі", "Сейсенбі", "Сәрсенбі", "Бейсенбі", "Жұма", "Сенбі"],
+ daysShort: ["Жек", "Дүй", "Сей", "Сәр", "Бей", "Жұм", "Сен"],
+ daysMin: ["Жк", "Дс", "Сс", "Ср", "Бс", "Жм", "Сн"],
+ months: ["Қаңтар", "Ақпан", "Наурыз", "Сәуір", "Мамыр", "Маусым", "Шілде", "Тамыз", "Қыркүйек", "Қазан", "Қараша", "Желтоқсан"],
+ monthsShort: ["Қаң", "Ақп", "Нау", "Сәу", "Мам", "Мау", "Шіл", "Там", "Қыр", "Қаз", "Қар", "Жел"],
+ today: "Бүгін",
+ weekStart: 1
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/km.js b/src/ui/static/js/datepicker/locales/km.js
new file mode 100644
index 000000000..71e294cd3
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/km.js
@@ -0,0 +1,15 @@
+/**
+ * Khmer translation for bootstrap-datepicker
+ * This is the Updated Version of: https: //github.com/uxsolutions/bootstrap-datepicker/blob/71308d42cce9524284c50c6fac50422d1790ac0f/js/locales/bootstrap-datepicker.kh.js
+ */
+(function () {
+ Datepicker.locales.km = {
+ days: ["អាទិត្យ", "ចន្ទ", "អង្គារ", "ពុធ", "ព្រហស្បតិ៍", "សុក្រ", "សៅរ៍"],
+ daysShort: ["អា.ទិ", "ចន្ទ", "អង្គារ", "ពុធ", "ព្រ.ហ", "សុក្រ", "សៅរ៍"],
+ daysMin: ["អា.ទិ", "ចន្ទ", "អង្គារ", "ពុធ", "ព្រ.ហ", "សុក្រ", "សៅរ៍"],
+ months: ["មករា", "កុម្ភះ", "មិនា", "មេសា", "ឧសភា", "មិថុនា", "កក្កដា", "សីហា", "កញ្ញា", "តុលា", "វិច្ឆិកា", "ធ្នូ"],
+ monthsShort: ["មករា", "កុម្ភះ", "មិនា", "មេសា", "ឧសភា", "មិថុនា", "កក្កដា", "សីហា", "កញ្ញា", "តុលា", "វិច្ឆិកា", "ធ្នូ"],
+ today: "ថ្ងៃនេះ",
+ clear: "សំអាត"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/ko.js b/src/ui/static/js/datepicker/locales/ko.js
new file mode 100644
index 000000000..3be9400b9
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/ko.js
@@ -0,0 +1,18 @@
+/**
+ * Korean translation for bootstrap-datepicker
+ * This is a port from https: //github.com/moment/moment/blob/develop/src/locale/ko.js
+ */
+(function () {
+ Datepicker.locales.ko = {
+ days: ["일요일", "월요일", "화요일", "수요일", "목요일", "금요일", "토요일"],
+ daysShort: ["일", "월", "화", "수", "목", "금", "토"],
+ daysMin: ["일", "월", "화", "수", "목", "금", "토"],
+ months: ["1월", "2월", "3월", "4월", "5월", "6월", "7월", "8월", "9월", "10월", "11월", "12월"],
+ monthsShort: ["1월", "2월", "3월", "4월", "5월", "6월", "7월", "8월", "9월", "10월", "11월", "12월"],
+ today: "오늘",
+ clear: "삭제",
+ format: "yyyy-mm-dd",
+ titleFormat: "y년mm월",
+ weekStart: 0
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/lt.js b/src/ui/static/js/datepicker/locales/lt.js
new file mode 100644
index 000000000..894e8cbc5
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/lt.js
@@ -0,0 +1,19 @@
+/**
+ * Lithuanian translation for bootstrap-datepicker
+ * Šarūnas Gliebus
+ */
+
+(function () {
+ Datepicker.locales.lt = {
+ days: ["Sekmadienis", "Pirmadienis", "Antradienis", "Trečiadienis", "Ketvirtadienis", "Penktadienis", "Šeštadienis"],
+ daysShort: ["S", "Pr", "A", "T", "K", "Pn", "Š"],
+ daysMin: ["Sk", "Pr", "An", "Tr", "Ke", "Pn", "Št"],
+ months: ["Sausis", "Vasaris", "Kovas", "Balandis", "Gegužė", "Birželis", "Liepa", "Rugpjūtis", "Rugsėjis", "Spalis", "Lapkritis", "Gruodis"],
+ monthsShort: ["Sau", "Vas", "Kov", "Bal", "Geg", "Bir", "Lie", "Rugp", "Rugs", "Spa", "Lap", "Gru"],
+ today: "Šiandien",
+ monthsTitle: "Mėnesiai",
+ clear: "Išvalyti",
+ weekStart: 1,
+ format: "yyyy-mm-dd"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/lv.js b/src/ui/static/js/datepicker/locales/lv.js
new file mode 100644
index 000000000..109014b9a
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/lv.js
@@ -0,0 +1,18 @@
+/**
+ * Latvian translation for bootstrap-datepicker
+ * Artis Avotins
+ */
+
+(function () {
+ Datepicker.locales.lv = {
+ days: ["Svētdiena", "Pirmdiena", "Otrdiena", "Trešdiena", "Ceturtdiena", "Piektdiena", "Sestdiena"],
+ daysShort: ["Sv", "P", "O", "T", "C", "Pk", "S"],
+ daysMin: ["Sv", "Pr", "Ot", "Tr", "Ce", "Pk", "Se"],
+ months: ["Janvāris", "Februāris", "Marts", "Aprīlis", "Maijs", "Jūnijs", "Jūlijs", "Augusts", "Septembris", "Oktobris", "Novembris", "Decembris"],
+ monthsShort: ["Jan", "Feb", "Mar", "Apr", "Mai", "Jūn", "Jūl", "Aug", "Sep", "Okt", "Nov", "Dec"],
+ monthsTitle: "Mēneši",
+ today: "Šodien",
+ clear: "Nodzēst",
+ weekStart: 1
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/me.js b/src/ui/static/js/datepicker/locales/me.js
new file mode 100644
index 000000000..6ecc09729
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/me.js
@@ -0,0 +1,17 @@
+/**
+ * Montenegrin translation for bootstrap-datepicker
+ * Miodrag Nikač
+ */
+(function () {
+ Datepicker.locales.me = {
+ days: ["Nedjelja","Ponedjeljak", "Utorak", "Srijeda", "Četvrtak", "Petak", "Subota"],
+ daysShort: ["Ned", "Pon", "Uto", "Sri", "Čet", "Pet", "Sub"],
+ daysMin: ["Ne", "Po", "Ut", "Sr", "Če", "Pe", "Su"],
+ months: ["Januar", "Februar", "Mart", "April", "Maj", "Jun", "Jul", "Avgust", "Septembar", "Oktobar", "Novembar", "Decembar"],
+ monthsShort: ["Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Avg", "Sep", "Okt", "Nov", "Dec"],
+ today: "Danas",
+ weekStart: 1,
+ clear: "Izbriši",
+ format: "dd.mm.yyyy"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/mk.js b/src/ui/static/js/datepicker/locales/mk.js
new file mode 100644
index 000000000..df87e2d18
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/mk.js
@@ -0,0 +1,15 @@
+/**
+ * Macedonian translation for bootstrap-datepicker
+ * Marko Aleksic
+ */
+(function () {
+ Datepicker.locales.mk = {
+ days: ["Недела", "Понеделник", "Вторник", "Среда", "Четврток", "Петок", "Сабота"],
+ daysShort: ["Нед", "Пон", "Вто", "Сре", "Чет", "Пет", "Саб"],
+ daysMin: ["Не", "По", "Вт", "Ср", "Че", "Пе", "Са"],
+ months: ["Јануари", "Февруари", "Март", "Април", "Мај", "Јуни", "Јули", "Август", "Септември", "Октомври", "Ноември", "Декември"],
+ monthsShort: ["Јан", "Фев", "Мар", "Апр", "Мај", "Јун", "Јул", "Авг", "Сеп", "Окт", "Ное", "Дек"],
+ today: "Денес",
+ format: "dd.mm.yyyy"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/mn.js b/src/ui/static/js/datepicker/locales/mn.js
new file mode 100644
index 000000000..c080280be
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/mn.js
@@ -0,0 +1,17 @@
+/**
+ * Mongolian translation for bootstrap-datepicker
+ * Andrey Torsunov
+ */
+(function () {
+ Datepicker.locales.mn = {
+ days: ["Ням", "Даваа", "Мягмар", "Лхагва", "Пүрэв", "Баасан", "Бямба"],
+ daysShort: ["Ням", "Дав", "Мяг", "Лха", "Пүр", "Баа", "Бям"],
+ daysMin: ["Ня", "Да", "Мя", "Лх", "Пү", "Ба", "Бя"],
+ months: ["Хулгана", "Үхэр", "Бар", "Туулай", "Луу", "Могой", "Морь", "Хонь", "Бич", "Тахиа", "Нохой", "Гахай"],
+ monthsShort: ["Хул", "Үхэ", "Бар", "Туу", "Луу", "Мог", "Мор", "Хон", "Бич", "Тах", "Нох", "Гах"],
+ today: "Өнөөдөр",
+ clear: "Тодорхой",
+ format: "yyyy.mm.dd",
+ weekStart: 1
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/mr.js b/src/ui/static/js/datepicker/locales/mr.js
new file mode 100644
index 000000000..67289df2a
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/mr.js
@@ -0,0 +1,18 @@
+/**
+ * Marathi translation for bootstrap-datepicker
+ * Sushant Pimple
+ */
+(function () {
+ Datepicker.locales.mr = {
+ days: ["रविवार", "सोमवार", "मंगळवार", "बुधवार", "गुरुवार", "शुक्रवार", "शनिवार"],
+ daysShort: ["रवि", "सोम", "मंगळ", "बुध", "गुरु", "शुक्र", "शनि"],
+ daysMin: ["र", "सो", "मं", "बु", "गु", "शु", "श"],
+ months: ["जानेवारी", "फेब्रुवारी", "मार्च", "एप्रिल", "मे", "जून", "जुलै", "ऑगस्ट", "सप्टेंबर", "ऑक्टोबर", "नोव्हेंबर", "डिसेंबर"],
+ monthsShort: ["जाने.", "फेब्रु.", "मार्च", "एप्रिल", "मे", "जून", "जुलै", "ऑगस्ट", "सप्टें.", "ऑक्टो.", "नोव्हें.", "डिसें."],
+ today: "आज",
+ monthsTitle: "महीने",
+ clear: "हटवा",
+ weekStart: 1,
+ format: "dd / mm / yyyy"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/ms.js b/src/ui/static/js/datepicker/locales/ms.js
new file mode 100644
index 000000000..20283bd4d
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/ms.js
@@ -0,0 +1,15 @@
+/**
+ * Malay translation for bootstrap-datepicker
+ * Ateman Faiz
+ */
+(function () {
+ Datepicker.locales.ms = {
+ days: ["Ahad", "Isnin", "Selasa", "Rabu", "Khamis", "Jumaat", "Sabtu"],
+ daysShort: ["Aha", "Isn", "Sel", "Rab", "Kha", "Jum", "Sab"],
+ daysMin: ["Ah", "Is", "Se", "Ra", "Kh", "Ju", "Sa"],
+ months: ["Januari", "Februari", "Mac", "April", "Mei", "Jun", "Julai", "Ogos", "September", "Oktober", "November", "Disember"],
+ monthsShort: ["Jan", "Feb", "Mar", "Apr", "Mei", "Jun", "Jul", "Ogo", "Sep", "Okt", "Nov", "Dis"],
+ today: "Hari Ini",
+ clear: "Bersihkan"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/nl-BE.js b/src/ui/static/js/datepicker/locales/nl-BE.js
new file mode 100644
index 000000000..6cf3d5654
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/nl-BE.js
@@ -0,0 +1,18 @@
+/**
+ * Belgium-Dutch translation for bootstrap-datepicker
+ * Julien Poulin
+ */
+(function () {
+ Datepicker.locales['nl-BE'] = {
+ days: ["zondag", "maandag", "dinsdag", "woensdag", "donderdag", "vrijdag", "zaterdag"],
+ daysShort: ["zo", "ma", "di", "wo", "do", "vr", "za"],
+ daysMin: ["zo", "ma", "di", "wo", "do", "vr", "za"],
+ months: ["januari", "februari", "maart", "april", "mei", "juni", "juli", "augustus", "september", "oktober", "november", "december"],
+ monthsShort: ["jan", "feb", "mrt", "apr", "mei", "jun", "jul", "aug", "sep", "okt", "nov", "dec"],
+ today: "Vandaag",
+ monthsTitle: "Maanden",
+ clear: "Leegmaken",
+ weekStart: 1,
+ format: "dd/mm/yyyy"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/nl.js b/src/ui/static/js/datepicker/locales/nl.js
new file mode 100644
index 000000000..1bc12ea12
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/nl.js
@@ -0,0 +1,18 @@
+/**
+ * Dutch translation for bootstrap-datepicker
+ * Reinier Goltstein
+ */
+(function () {
+ Datepicker.locales.nl = {
+ days: ["zondag", "maandag", "dinsdag", "woensdag", "donderdag", "vrijdag", "zaterdag"],
+ daysShort: ["zo", "ma", "di", "wo", "do", "vr", "za"],
+ daysMin: ["zo", "ma", "di", "wo", "do", "vr", "za"],
+ months: ["januari", "februari", "maart", "april", "mei", "juni", "juli", "augustus", "september", "oktober", "november", "december"],
+ monthsShort: ["jan", "feb", "mrt", "apr", "mei", "jun", "jul", "aug", "sep", "okt", "nov", "dec"],
+ today: "Vandaag",
+ monthsTitle: "Maanden",
+ clear: "Wissen",
+ weekStart: 1,
+ format: "dd-mm-yyyy"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/no.js b/src/ui/static/js/datepicker/locales/no.js
new file mode 100644
index 000000000..d9c55fe4b
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/no.js
@@ -0,0 +1,18 @@
+/**
+ * Norwegian translation for bootstrap-datepicker
+ * George Gooding
+ */
+(function () {
+ Datepicker.locales.no = {
+ days: ['søndag', 'mandag', 'tirsdag', 'onsdag', 'torsdag', 'fredag', 'lørdag'],
+ daysShort: ['søn', 'man', 'tir', 'ons', 'tor', 'fre', 'lør'],
+ daysMin: ['sø', 'ma', 'ti', 'on', 'to', 'fr', 'lø'],
+ months: ['januar', 'februar', 'mars', 'april', 'mai', 'juni', 'juli', 'august', 'september', 'oktober', 'november', 'desember'],
+ monthsShort: ['jan', 'feb', 'mar', 'apr', 'mai', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'des'],
+ today: 'i dag',
+ monthsTitle: 'Måneder',
+ clear: 'Nullstill',
+ weekStart: 1,
+ format: 'dd.mm.yyyy'
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/oc.js b/src/ui/static/js/datepicker/locales/oc.js
new file mode 100644
index 000000000..c1d600743
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/oc.js
@@ -0,0 +1,17 @@
+/**
+ * Occitan translation for bootstrap-datepicker
+ */
+(function () {
+ Datepicker.locales.oc = {
+ days: ["Dimenge", "Diluns", "Dimars", "Dimècres", "Dijòus", "Divendres", "Dissabte"],
+ daysShort: ["Dim", "Dil", "Dmr", "Dmc", "Dij", "Div", "Dis"],
+ daysMin: ["dg", "dl", "dr", "dc", "dj", "dv", "ds"],
+ months: ["Genièr", "Febrièr", "Març", "Abrial", "Mai", "Junh", "Julhet", "Agost", "Setembre", "Octobre", "Novembre", "Decembre"],
+ monthsShort: ["Gen", "Feb", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Oct", "Nov", "Dec"],
+ today: "Uèi",
+ monthsTitle: "Meses",
+ clear: "Escafar",
+ weekStart: 1,
+ format: "dd/mm/yyyy"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/pl.js b/src/ui/static/js/datepicker/locales/pl.js
new file mode 100644
index 000000000..55444afd7
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/pl.js
@@ -0,0 +1,17 @@
+/**
+ * Polish translation for bootstrap-datepicker
+ * Robert
+ */
+(function () {
+ Datepicker.locales.pl = {
+ days: ["Niedziela", "Poniedziałek", "Wtorek", "Środa", "Czwartek", "Piątek", "Sobota"],
+ daysShort: ["Niedz.", "Pon.", "Wt.", "Śr.", "Czw.", "Piąt.", "Sob."],
+ daysMin: ["Ndz.", "Pn.", "Wt.", "Śr.", "Czw.", "Pt.", "Sob."],
+ months: ["Styczeń", "Luty", "Marzec", "Kwiecień", "Maj", "Czerwiec", "Lipiec", "Sierpień", "Wrzesień", "Październik", "Listopad", "Grudzień"],
+ monthsShort: ["Sty.", "Lut.", "Mar.", "Kwi.", "Maj", "Cze.", "Lip.", "Sie.", "Wrz.", "Paź.", "Lis.", "Gru."],
+ today: "Dzisiaj",
+ weekStart: 1,
+ clear: "Wyczyść",
+ format: "dd.mm.yyyy"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/pt-BR.js b/src/ui/static/js/datepicker/locales/pt-BR.js
new file mode 100644
index 000000000..fb855c904
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/pt-BR.js
@@ -0,0 +1,17 @@
+/**
+ * Brazilian translation for bootstrap-datepicker
+ * Cauan Cabral
+ */
+(function () {
+ Datepicker.locales['pt-BR'] = {
+ days: ["Domingo", "Segunda", "Terça", "Quarta", "Quinta", "Sexta", "Sábado"],
+ daysShort: ["Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb"],
+ daysMin: ["Do", "Se", "Te", "Qu", "Qu", "Se", "Sa"],
+ months: ["Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"],
+ monthsShort: ["Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"],
+ today: "Hoje",
+ monthsTitle: "Meses",
+ clear: "Limpar",
+ format: "dd/mm/yyyy"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/pt.js b/src/ui/static/js/datepicker/locales/pt.js
new file mode 100644
index 000000000..f25cf9b48
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/pt.js
@@ -0,0 +1,18 @@
+/**
+ * Portuguese translation for bootstrap-datepicker
+ * Original code: Cauan Cabral
+ * Tiago Melo
+ */
+(function () {
+ Datepicker.locales.pt = {
+ days: ["Domingo", "Segunda", "Terça", "Quarta", "Quinta", "Sexta", "Sábado"],
+ daysShort: ["Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb"],
+ daysMin: ["Do", "Se", "Te", "Qu", "Qu", "Se", "Sa"],
+ months: ["Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"],
+ monthsShort: ["Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"],
+ today: "Hoje",
+ monthsTitle: "Meses",
+ clear: "Limpar",
+ format: "dd/mm/yyyy"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/ro.js b/src/ui/static/js/datepicker/locales/ro.js
new file mode 100644
index 000000000..0b98838e8
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/ro.js
@@ -0,0 +1,17 @@
+/**
+ * Romanian translation for bootstrap-datepicker
+ * Cristian Vasile
+ */
+(function () {
+ Datepicker.locales.ro = {
+ days: ["Duminică", "Luni", "Marţi", "Miercuri", "Joi", "Vineri", "Sâmbătă"],
+ daysShort: ["Dum", "Lun", "Mar", "Mie", "Joi", "Vin", "Sâm"],
+ daysMin: ["Du", "Lu", "Ma", "Mi", "Jo", "Vi", "Sâ"],
+ months: ["Ianuarie", "Februarie", "Martie", "Aprilie", "Mai", "Iunie", "Iulie", "August", "Septembrie", "Octombrie", "Noiembrie", "Decembrie"],
+ monthsShort: ["Ian", "Feb", "Mar", "Apr", "Mai", "Iun", "Iul", "Aug", "Sep", "Oct", "Nov", "Dec"],
+ today: "Astăzi",
+ clear: "Șterge",
+ weekStart: 1,
+ format: "dd/mm/yyyy"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/ru.js b/src/ui/static/js/datepicker/locales/ru.js
new file mode 100644
index 000000000..f85cc51ea
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/ru.js
@@ -0,0 +1,18 @@
+/**
+ * Russian translation for bootstrap-datepicker
+ * Victor Taranenko
+ */
+(function () {
+ Datepicker.locales.ru = {
+ days: ["Воскресенье", "Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Суббота"],
+ daysShort: ["Вск", "Пнд", "Втр", "Срд", "Чтв", "Птн", "Суб"],
+ daysMin: ["Вс", "Пн", "Вт", "Ср", "Чт", "Пт", "Сб"],
+ months: ["Январь", "Февраль", "Март", "Апрель", "Май", "Июнь", "Июль", "Август", "Сентябрь", "Октябрь", "Ноябрь", "Декабрь"],
+ monthsShort: ["Янв", "Фев", "Мар", "Апр", "Май", "Июн", "Июл", "Авг", "Сен", "Окт", "Ноя", "Дек"],
+ today: "Сегодня",
+ clear: "Очистить",
+ format: "dd.mm.yyyy",
+ weekStart: 1,
+ monthsTitle: 'Месяцы'
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/si.js b/src/ui/static/js/datepicker/locales/si.js
new file mode 100644
index 000000000..04bf43f0c
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/si.js
@@ -0,0 +1,18 @@
+/**
+ * Sinhala translation for bootstrap-datepicker
+ * Chanaka Fernando
+ */
+(function () {
+ Datepicker.locales.si = {
+ days: ["ඉරිදා", "සඳුදා", "අඟහරුවාදා", "බදාදා", "බ්රහස්පතින්දා", "සිකුරාදා", "සෙනසුරාදා"],
+ daysShort: ["ඉරි", "සඳු", "අඟ", "බදා", "බ්රහ", "සිකු", "සෙන"],
+ daysMin: ["ඉ", "ස", "අ", "බ", "බ්ර", "සි", "සෙ"],
+ months: ["ජනවාරි", "පෙබරවාරි", "මාර්තු", "අප්රේල්", "මැයි", "ජුනි", "ජූලි", "අගෝස්තු", "සැප්තැම්බර්", "ඔක්තෝබර්", "නොවැම්බර්", "දෙසැම්බර්"],
+ monthsShort: ["ජන", "පෙබ", "මාර්", "අප්රේ", "මැයි", "ජුනි", "ජූලි", "අගෝ", "සැප්", "ඔක්", "නොවැ", "දෙසැ"],
+ today: "අද",
+ monthsTitle: "මාස",
+ clear: "මකන්න",
+ weekStart: 0,
+ format: "yyyy-mm-dd"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/sk.js b/src/ui/static/js/datepicker/locales/sk.js
new file mode 100644
index 000000000..0f813abf3
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/sk.js
@@ -0,0 +1,18 @@
+/**
+ * Slovak translation for bootstrap-datepicker
+ * Marek Lichtner
+ * Fixes by Michal Remiš
+ */
+(function () {
+ Datepicker.locales.sk = {
+ days: ["Nedeľa", "Pondelok", "Utorok", "Streda", "Štvrtok", "Piatok", "Sobota"],
+ daysShort: ["Ned", "Pon", "Uto", "Str", "Štv", "Pia", "Sob"],
+ daysMin: ["Ne", "Po", "Ut", "St", "Št", "Pia", "So"],
+ months: ["Január", "Február", "Marec", "Apríl", "Máj", "Jún", "Júl", "August", "September", "Október", "November", "December"],
+ monthsShort: ["Jan", "Feb", "Mar", "Apr", "Máj", "Jún", "Júl", "Aug", "Sep", "Okt", "Nov", "Dec"],
+ today: "Dnes",
+ clear: "Vymazať",
+ weekStart: 1,
+ format: "d.m.yyyy"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/sl.js b/src/ui/static/js/datepicker/locales/sl.js
new file mode 100644
index 000000000..6fae7fd23
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/sl.js
@@ -0,0 +1,15 @@
+/**
+ * Slovene translation for bootstrap-datepicker
+ * Gregor Rudolf
+ */
+(function () {
+ Datepicker.locales.sl = {
+ days: ["Nedelja", "Ponedeljek", "Torek", "Sreda", "Četrtek", "Petek", "Sobota"],
+ daysShort: ["Ned", "Pon", "Tor", "Sre", "Čet", "Pet", "Sob"],
+ daysMin: ["Ne", "Po", "To", "Sr", "Če", "Pe", "So"],
+ months: ["Januar", "Februar", "Marec", "April", "Maj", "Junij", "Julij", "Avgust", "September", "Oktober", "November", "December"],
+ monthsShort: ["Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Avg", "Sep", "Okt", "Nov", "Dec"],
+ today: "Danes",
+ weekStart: 1
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/sq.js b/src/ui/static/js/datepicker/locales/sq.js
new file mode 100644
index 000000000..32b2f1d6b
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/sq.js
@@ -0,0 +1,18 @@
+/**
+ * Albanian translation for bootstrap-datepicker
+ * Tomor Pupovci
+ */
+(function () {
+ Datepicker.locales.sq = {
+ days: ["E Diel", "E Hënë", "E Martē", "E Mërkurë", "E Enjte", "E Premte", "E Shtunë"],
+ daysShort: ["Die", "Hën", "Mar", "Mër", "Enj", "Pre", "Shtu"],
+ daysMin: ["Di", "Hë", "Ma", "Më", "En", "Pr", "Sht"],
+ months: ["Janar", "Shkurt", "Mars", "Prill", "Maj", "Qershor", "Korrik", "Gusht", "Shtator", "Tetor", "Nëntor", "Dhjetor"],
+ monthsShort: ["Jan", "Shk", "Mar", "Pri", "Maj", "Qer", "Korr", "Gu", "Sht", "Tet", "Nën", "Dhjet"],
+ monthsTitle: "Muaj",
+ today: "Sot",
+ weekStart: 1,
+ format: "dd/mm/yyyy",
+ clear: "Pastro"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/sr-latn.js b/src/ui/static/js/datepicker/locales/sr-latn.js
new file mode 100644
index 000000000..65281d434
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/sr-latn.js
@@ -0,0 +1,16 @@
+/**
+ * Serbian latin translation for bootstrap-datepicker
+ * Bojan Milosavlević
+ */
+(function () {
+ Datepicker.locales['sr-latn'] = {
+ days: ["Nedelja","Ponedeljak", "Utorak", "Sreda", "Četvrtak", "Petak", "Subota"],
+ daysShort: ["Ned", "Pon", "Uto", "Sre", "Čet", "Pet", "Sub"],
+ daysMin: ["N", "Po", "U", "Sr", "Č", "Pe", "Su"],
+ months: ["Januar", "Februar", "Mart", "April", "Maj", "Jun", "Jul", "Avgust", "Septembar", "Oktobar", "Novembar", "Decembar"],
+ monthsShort: ["Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Avg", "Sep", "Okt", "Nov", "Dec"],
+ today: "Danas",
+ weekStart: 1,
+ format: "dd.mm.yyyy"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/sr.js b/src/ui/static/js/datepicker/locales/sr.js
new file mode 100644
index 000000000..275edd7d4
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/sr.js
@@ -0,0 +1,16 @@
+/**
+ * Serbian cyrillic translation for bootstrap-datepicker
+ * Bojan Milosavlević
+ */
+(function () {
+ Datepicker.locales.sr = {
+ days: ["Недеља","Понедељак", "Уторак", "Среда", "Четвртак", "Петак", "Субота"],
+ daysShort: ["Нед", "Пон", "Уто", "Сре", "Чет", "Пет", "Суб"],
+ daysMin: ["Н", "По", "У", "Ср", "Ч", "Пе", "Су"],
+ months: ["Јануар", "Фебруар", "Март", "Април", "Мај", "Јун", "Јул", "Август", "Септембар", "Октобар", "Новембар", "Децембар"],
+ monthsShort: ["Јан", "Феб", "Мар", "Апр", "Мај", "Јун", "Јул", "Авг", "Сеп", "Окт", "Нов", "Дец"],
+ today: "Данас",
+ weekStart: 1,
+ format: "dd.mm.yyyy"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/sv.js b/src/ui/static/js/datepicker/locales/sv.js
new file mode 100644
index 000000000..955ff67d0
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/sv.js
@@ -0,0 +1,17 @@
+/**
+ * Swedish translation for bootstrap-datepicker
+ * Patrik Ragnarsson
+ */
+(function () {
+ Datepicker.locales.sv = {
+ days: ["söndag", "måndag", "tisdag", "onsdag", "torsdag", "fredag", "lördag"],
+ daysShort: ["sön", "mån", "tis", "ons", "tor", "fre", "lör"],
+ daysMin: ["sö", "må", "ti", "on", "to", "fr", "lö"],
+ months: ["januari", "februari", "mars", "april", "maj", "juni", "juli", "augusti", "september", "oktober", "november", "december"],
+ monthsShort: ["jan", "feb", "mar", "apr", "maj", "jun", "jul", "aug", "sep", "okt", "nov", "dec"],
+ today: "Idag",
+ format: "yyyy-mm-dd",
+ weekStart: 1,
+ clear: "Rensa"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/sw.js b/src/ui/static/js/datepicker/locales/sw.js
new file mode 100644
index 000000000..e67b01f76
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/sw.js
@@ -0,0 +1,15 @@
+/**
+ * Swahili translation for bootstrap-datepicker
+ * Edwin Mugendi
+ * Source: http: //scriptsource.org/cms/scripts/page.php?item_id=entry_detail&uid=xnfaqyzcku
+ */
+(function () {
+ Datepicker.locales.sw = {
+ days: ["Jumapili", "Jumatatu", "Jumanne", "Jumatano", "Alhamisi", "Ijumaa", "Jumamosi"],
+ daysShort: ["J2", "J3", "J4", "J5", "Alh", "Ij", "J1"],
+ daysMin: ["2", "3", "4", "5", "A", "I", "1"],
+ months: ["Januari", "Februari", "Machi", "Aprili", "Mei", "Juni", "Julai", "Agosti", "Septemba", "Oktoba", "Novemba", "Desemba"],
+ monthsShort: ["Jan", "Feb", "Mac", "Apr", "Mei", "Jun", "Jul", "Ago", "Sep", "Okt", "Nov", "Des"],
+ today: "Leo"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/ta.js b/src/ui/static/js/datepicker/locales/ta.js
new file mode 100644
index 000000000..ff3389286
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/ta.js
@@ -0,0 +1,18 @@
+/**
+ * Tamil translation for bootstrap-datepicker
+ * Abubacker Siddik A
+ */
+(function () {
+ Datepicker.locales.ta = {
+ days: ["ஞாயிறு", "திங்கள்", "செவ்வாய்", "புதன்", "வியாழன்", "வெள்ளி", "சனி"],
+ daysShort: ["ஞாயி", "திங்", "செவ்", "புத", "வியா", "வெள்", "சனி"],
+ daysMin: ["ஞா", "தி", "செ", "பு", "வி", "வெ", "ச"],
+ months: ["ஜனவரி", "பிப்ரவரி", "மார்ச்", "ஏப்ரல்", "மே", "ஜூன்", "ஜூலை", "ஆகஸ்டு", "செப்டம்பர்", "அக்டோபர்", "நவம்பர்", "டிசம்பர்"],
+ monthsShort: ["ஜன", "பிப்", "மார்", "ஏப்", "மே", "ஜூன்", "ஜூலை", "ஆக", "செப்", "அக்", "நவ", "டிச"],
+ today: "இன்று",
+ monthsTitle: "மாதங்கள்",
+ clear: "நீக்கு",
+ weekStart: 1,
+ format: "dd/mm/yyyy"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/tg.js b/src/ui/static/js/datepicker/locales/tg.js
new file mode 100644
index 000000000..497c83717
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/tg.js
@@ -0,0 +1,19 @@
+/**
+ * Tajik (cyrillic) translation for bootstrap-datepicker
+ * Bakhtiyor Bahritidinov
+ * Orif N. Jr.
+ */
+(function () {
+ Datepicker.locales.tg = {
+ days: ["Якшанбе", "Душанбе", "Сешанбе", "Чоршанбе", "Панҷшанбе", "Ҷумъа", "Шанбе"],
+ daysShort: ["Яшб", "Дшб", "Сшб", "Чшб", "Пшб", "Ҷум", "Шнб"],
+ daysMin: ["Яш", "Дш", "Сш", "Чш", "Пш", "Ҷм", "Шб"],
+ months: ["Январ", "Феврал", "Март", "Апрел", "Май", "Июн", "Июл", "Август", "Сентябр", "Октябр", "Ноябр", "Декабр"],
+ monthsShort: ["Янв", "Фев", "Мар", "Апр", "Май", "Июн", "Июл", "Авг", "Сен", "Окт", "Ноя", "Дек"],
+ today: "Имрӯз",
+ monthsTitle: "Моҳҳо",
+ clear: "Тоза намудан",
+ weekStart: 1,
+ format: "dd.mm.yyyy"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/th.js b/src/ui/static/js/datepicker/locales/th.js
new file mode 100644
index 000000000..bdeb7904e
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/th.js
@@ -0,0 +1,14 @@
+/**
+ * Thai translation for bootstrap-datepicker
+ * Suchau Jiraprapot
+ */
+(function () {
+ Datepicker.locales.th = {
+ days: ["อาทิตย์", "จันทร์", "อังคาร", "พุธ", "พฤหัส", "ศุกร์", "เสาร์", "อาทิตย์"],
+ daysShort: ["อา", "จ", "อ", "พ", "พฤ", "ศ", "ส", "อา"],
+ daysMin: ["อา", "จ", "อ", "พ", "พฤ", "ศ", "ส", "อา"],
+ months: ["มกราคม", "กุมภาพันธ์", "มีนาคม", "เมษายน", "พฤษภาคม", "มิถุนายน", "กรกฎาคม", "สิงหาคม", "กันยายน", "ตุลาคม", "พฤศจิกายน", "ธันวาคม"],
+ monthsShort: ["ม.ค.", "ก.พ.", "มี.ค.", "เม.ย.", "พ.ค.", "มิ.ย.", "ก.ค.", "ส.ค.", "ก.ย.", "ต.ค.", "พ.ย.", "ธ.ค."],
+ today: "วันนี้"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/tk.js b/src/ui/static/js/datepicker/locales/tk.js
new file mode 100644
index 000000000..4c8affd4a
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/tk.js
@@ -0,0 +1,18 @@
+/**
+ * Turkmen translation for bootstrap-datepicker
+ * N'Bayramberdiyev
+ */
+(function () {
+ Datepicker.locales.tk = {
+ days: ["Ýekşenbe", "Duşenbe", "Sişenbe", "Çarşenbe", "Penşenbe", "Anna", "Şenbe"],
+ daysShort: ["Ýek", "Duş", "Siş", "Çar", "Pen", "Ann", "Şen"],
+ daysMin: ["Ýe", "Du", "Si", "Ça", "Pe", "An", "Şe"],
+ months: ["Ýanwar", "Fewral", "Mart", "Aprel", "Maý", "Iýun", "Iýul", "Awgust", "Sentýabr", "Oktýabr", "Noýabr", "Dekabr"],
+ monthsShort: ["Ýan", "Few", "Mar", "Apr", "Maý", "Iýn", "Iýl", "Awg", "Sen", "Okt", "Noý", "Dek"],
+ today: "Bu gün",
+ monthsTitle: "Aýlar",
+ clear: "Aýyr",
+ weekStart: 1,
+ format: "dd.mm.yyyy"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/tr.js b/src/ui/static/js/datepicker/locales/tr.js
new file mode 100644
index 000000000..5a97ed774
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/tr.js
@@ -0,0 +1,17 @@
+/**
+ * Turkish translation for bootstrap-datepicker
+ * Serkan Algur
+ */
+(function () {
+ Datepicker.locales.tr = {
+ days: ["Pazar", "Pazartesi", "Salı", "Çarşamba", "Perşembe", "Cuma", "Cumartesi"],
+ daysShort: ["Pz", "Pzt", "Sal", "Çrş", "Prş", "Cu", "Cts"],
+ daysMin: ["Pz", "Pzt", "Sa", "Çr", "Pr", "Cu", "Ct"],
+ months: ["Ocak", "Şubat", "Mart", "Nisan", "Mayıs", "Haziran", "Temmuz", "Ağustos", "Eylül", "Ekim", "Kasım", "Aralık"],
+ monthsShort: ["Oca", "Şub", "Mar", "Nis", "May", "Haz", "Tem", "Ağu", "Eyl", "Eki", "Kas", "Ara"],
+ today: "Bugün",
+ clear: "Temizle",
+ weekStart: 1,
+ format: "dd.mm.yyyy"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/uk.js b/src/ui/static/js/datepicker/locales/uk.js
new file mode 100644
index 000000000..382103527
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/uk.js
@@ -0,0 +1,17 @@
+/**
+ * Ukrainian translation for bootstrap-datepicker
+ * Igor Polynets
+ */
+(function () {
+ Datepicker.locales.uk = {
+ days: ["Неділя", "Понеділок", "Вівторок", "Середа", "Четвер", "П'ятниця", "Субота"],
+ daysShort: ["Нед", "Пнд", "Втр", "Срд", "Чтв", "Птн", "Суб"],
+ daysMin: ["Нд", "Пн", "Вт", "Ср", "Чт", "Пт", "Сб"],
+ months: ["Cічень", "Лютий", "Березень", "Квітень", "Травень", "Червень", "Липень", "Серпень", "Вересень", "Жовтень", "Листопад", "Грудень"],
+ monthsShort: ["Січ", "Лют", "Бер", "Кві", "Тра", "Чер", "Лип", "Сер", "Вер", "Жов", "Лис", "Гру"],
+ today: "Сьогодні",
+ clear: "Очистити",
+ format: "dd.mm.yyyy",
+ weekStart: 1
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/uz-cyrl.js b/src/ui/static/js/datepicker/locales/uz-cyrl.js
new file mode 100644
index 000000000..3dd8dde79
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/uz-cyrl.js
@@ -0,0 +1,18 @@
+/**
+ * Uzbek cyrillic translation for bootstrap-datepicker
+ * Kakhramonov Javlonbek
+ */
+(function () {
+ Datepicker.locales['uz-cyrl'] = {
+ days: ["Якшанба", "Душанба", "Сешанба", "Чоршанба", "Пайшанба", "Жума", "Шанба"],
+ daysShort: ["Якш", "Ду", "Се", "Чор", "Пай", "Жу", "Ша"],
+ daysMin: ["Як", "Ду", "Се", "Чо", "Па", "Жу", "Ша"],
+ months: ["Январь","Февраль","Март","Апрель","Май","Июнь","Июль","Август","Сентябрь","Октябрь","Ноябрь","Декабрь"],
+ monthsShort: ["Янв","Фев","Мар","Апр","Май","Июн","Июл","Авг","Сен","Окт","Ноя","Дек"],
+ today: "Бугун",
+ clear: "Ўчириш",
+ format: "dd.mm.yyyy",
+ weekStart: 1,
+ monthsTitle: 'Ойлар'
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/uz-latn.js b/src/ui/static/js/datepicker/locales/uz-latn.js
new file mode 100644
index 000000000..8f18dac68
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/uz-latn.js
@@ -0,0 +1,18 @@
+/**
+ * Uzbek latin translation for bootstrap-datepicker
+ * Kakhramonov Javlonbek
+ */
+(function () {
+ Datepicker.locales['uz-latn'] = {
+ days: ["Yakshanba", "Dushanba", "Seshanba", "Chorshanba", "Payshanba", "Juma", "Shanba"],
+ daysShort: ["Yak", "Du", "Se", "Chor", "Pay", "Ju", "Sha"],
+ daysMin: ["Ya", "Du", "Se", "Cho", "Pa", "Ju", "Sha"],
+ months: ["Yanvar", "Fevral", "Mart", "Aprel", "May", "Iyun", "Iyul", "Avgust", "Sentabr", "Oktabr", "Noyabr", "Dekabr"],
+ monthsShort: ["Yan", "Fev", "Mar", "Apr", "May", "Iyn", "Iyl", "Avg", "Sen", "Okt", "Noy", "Dek"],
+ today: "Bugun",
+ clear: "O'chirish",
+ format: "dd.mm.yyyy",
+ weekStart: 1,
+ monthsTitle: 'Oylar'
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/vi.js b/src/ui/static/js/datepicker/locales/vi.js
new file mode 100644
index 000000000..90b5cb8a6
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/vi.js
@@ -0,0 +1,16 @@
+/**
+ * Vietnamese translation for bootstrap-datepicker
+ * An Vo
+ */
+(function () {
+ Datepicker.locales.vi = {
+ days: ["Chủ nhật", "Thứ hai", "Thứ ba", "Thứ tư", "Thứ năm", "Thứ sáu", "Thứ bảy"],
+ daysShort: ["CN", "Thứ 2", "Thứ 3", "Thứ 4", "Thứ 5", "Thứ 6", "Thứ 7"],
+ daysMin: ["CN", "T2", "T3", "T4", "T5", "T6", "T7"],
+ months: ["Tháng 1", "Tháng 2", "Tháng 3", "Tháng 4", "Tháng 5", "Tháng 6", "Tháng 7", "Tháng 8", "Tháng 9", "Tháng 10", "Tháng 11", "Tháng 12"],
+ monthsShort: ["Th1", "Th2", "Th3", "Th4", "Th5", "Th6", "Th7", "Th8", "Th9", "Th10", "Th11", "Th12"],
+ today: "Hôm nay",
+ clear: "Xóa",
+ format: "dd/mm/yyyy"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/zh-CN.js b/src/ui/static/js/datepicker/locales/zh-CN.js
new file mode 100644
index 000000000..adec7d20c
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/zh-CN.js
@@ -0,0 +1,19 @@
+/**
+ * Simplified Chinese translation for bootstrap-datepicker
+ * Yuan Cheung
+ */
+(function () {
+ Datepicker.locales['zh-CN'] = {
+ days: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"],
+ daysShort: ["周日", "周一", "周二", "周三", "周四", "周五", "周六"],
+ daysMin: ["日", "一", "二", "三", "四", "五", "六"],
+ months: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
+ monthsShort: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"],
+ today: "今天",
+ monthsTitle: "选择月份",
+ clear: "清除",
+ format: "yyyy-mm-dd",
+ titleFormat: "y年mm月",
+ weekStart: 1
+ };
+}());
diff --git a/src/ui/static/js/datepicker/locales/zh-TW.js b/src/ui/static/js/datepicker/locales/zh-TW.js
new file mode 100644
index 000000000..379f7d89e
--- /dev/null
+++ b/src/ui/static/js/datepicker/locales/zh-TW.js
@@ -0,0 +1,20 @@
+/**
+ * Traditional Chinese translation for bootstrap-datepicker
+ * Rung-Sheng Jang
+ * FrankWu Fix more appropriate use of Traditional Chinese habit
+ */
+(function () {
+ Datepicker.locales['zh-TW'] = {
+ days: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"],
+ daysShort: ["週日", "週一", "週二", "週三", "週四", "週五", "週六"],
+ daysMin: ["日", "一", "二", "三", "四", "五", "六"],
+ months: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
+ monthsShort: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"],
+ today: "今天",
+ monthsTitle: "月份",
+ format: "yyyy/mm/dd",
+ weekStart: 0,
+ titleFormat: "y年mm月",
+ clear: "清除"
+ };
+}());
diff --git a/src/ui/static/js/datepicker/main.js b/src/ui/static/js/datepicker/main.js
new file mode 100644
index 000000000..7b589db91
--- /dev/null
+++ b/src/ui/static/js/datepicker/main.js
@@ -0,0 +1,4 @@
+import Datepicker from './Datepicker.js';
+import DateRangePicker from './DateRangePicker.js';
+
+export {Datepicker, DateRangePicker};
diff --git a/src/ui/static/js/datepicker/options/defaultOptions.js b/src/ui/static/js/datepicker/options/defaultOptions.js
new file mode 100644
index 000000000..d037ede4b
--- /dev/null
+++ b/src/ui/static/js/datepicker/options/defaultOptions.js
@@ -0,0 +1,38 @@
+// config options updatable by setOptions() and their default values
+const defaultOptions = {
+ autohide: false,
+ beforeShowDay: null,
+ beforeShowDecade: null,
+ beforeShowMonth: null,
+ beforeShowYear: null,
+ calendarWeeks: false,
+ clearBtn: false,
+ dateDelimiter: ',',
+ datesDisabled: [],
+ daysOfWeekDisabled: [],
+ daysOfWeekHighlighted: [],
+ defaultViewDate: undefined, // placeholder, defaults to today() by the program
+ disableTouchKeyboard: false,
+ format: 'mm/dd/yyyy',
+ language: 'en',
+ maxDate: null,
+ maxNumberOfDates: 1,
+ maxView: 3,
+ minDate: null,
+ nextArrow: '»',
+ orientation: 'auto',
+ pickLevel: 0,
+ prevArrow: '«',
+ showDaysOfWeek: true,
+ showOnClick: true,
+ showOnFocus: true,
+ startView: 0,
+ title: '',
+ todayBtn: false,
+ todayBtnMode: 0,
+ todayHighlight: false,
+ updateOnBlur: true,
+ weekStart: 0,
+};
+
+export default defaultOptions;
diff --git a/src/ui/static/js/datepicker/options/processOptions.js b/src/ui/static/js/datepicker/options/processOptions.js
new file mode 100644
index 000000000..007b83676
--- /dev/null
+++ b/src/ui/static/js/datepicker/options/processOptions.js
@@ -0,0 +1,288 @@
+import {hasProperty, pushUnique} from '../lib/utils.js';
+import {dateValue, regularizeDate} from '../lib/date.js';
+import {reFormatTokens, parseDate} from '../lib/date-format.js';
+import {parseHTML} from '../lib/dom.js';
+import defaultOptions from './defaultOptions.js';
+
+const {
+ language: defaultLang,
+ format: defaultFormat,
+ weekStart: defaultWeekStart,
+} = defaultOptions;
+
+// Reducer function to filter out invalid day-of-week from the input
+function sanitizeDOW(dow, day) {
+ return dow.length < 6 && day >= 0 && day < 7
+ ? pushUnique(dow, day)
+ : dow;
+}
+
+function calcEndOfWeek(startOfWeek) {
+ return (startOfWeek + 6) % 7;
+}
+
+// validate input date. if invalid, fallback to the original value
+function validateDate(value, format, locale, origValue) {
+ const date = parseDate(value, format, locale);
+ return date !== undefined ? date : origValue;
+}
+
+// Validate viewId. if invalid, fallback to the original value
+function validateViewId(value, origValue, max = 3) {
+ const viewId = parseInt(value, 10);
+ return viewId >= 0 && viewId <= max ? viewId : origValue;
+}
+
+// Create Datepicker configuration to set
+export default function processOptions(options, datepicker) {
+ const inOpts = Object.assign({}, options);
+ const config = {};
+ const locales = datepicker.constructor.locales;
+ const rangeSideIndex = datepicker.rangeSideIndex;
+ let {
+ format,
+ language,
+ locale,
+ maxDate,
+ maxView,
+ minDate,
+ pickLevel,
+ startView,
+ weekStart,
+ } = datepicker.config || {};
+
+ if (inOpts.language) {
+ let lang;
+ if (inOpts.language !== language) {
+ if (locales[inOpts.language]) {
+ lang = inOpts.language;
+ } else {
+ // Check if langauge + region tag can fallback to the one without
+ // region (e.g. fr-CA → fr)
+ lang = inOpts.language.split('-')[0];
+ if (locales[lang] === undefined) {
+ lang = false;
+ }
+ }
+ }
+ delete inOpts.language;
+ if (lang) {
+ language = config.language = lang;
+
+ // update locale as well when updating language
+ const origLocale = locale || locales[defaultLang];
+ // use default language's properties for the fallback
+ locale = Object.assign({
+ format: defaultFormat,
+ weekStart: defaultWeekStart
+ }, locales[defaultLang]);
+ if (language !== defaultLang) {
+ Object.assign(locale, locales[language]);
+ }
+ config.locale = locale;
+ // if format and/or weekStart are the same as old locale's defaults,
+ // update them to new locale's defaults
+ if (format === origLocale.format) {
+ format = config.format = locale.format;
+ }
+ if (weekStart === origLocale.weekStart) {
+ weekStart = config.weekStart = locale.weekStart;
+ config.weekEnd = calcEndOfWeek(locale.weekStart);
+ }
+ }
+ }
+
+ if (inOpts.format) {
+ const hasToDisplay = typeof inOpts.format.toDisplay === 'function';
+ const hasToValue = typeof inOpts.format.toValue === 'function';
+ const validFormatString = reFormatTokens.test(inOpts.format);
+ if ((hasToDisplay && hasToValue) || validFormatString) {
+ format = config.format = inOpts.format;
+ }
+ delete inOpts.format;
+ }
+
+ //*** pick level ***//
+ let newPickLevel = pickLevel;
+ if (inOpts.pickLevel !== undefined) {
+ newPickLevel = validateViewId(inOpts.pickLevel, 2);
+ delete inOpts.pickLevel;
+ }
+ if (newPickLevel !== pickLevel) {
+ if (newPickLevel > pickLevel) {
+ // complement current minDate/madDate so that the existing range will be
+ // expanded to fit the new level later
+ if (inOpts.minDate === undefined) {
+ inOpts.minDate = minDate;
+ }
+ if (inOpts.maxDate === undefined) {
+ inOpts.maxDate = maxDate;
+ }
+ }
+ // complement datesDisabled so that it will be reset later
+ if (!inOpts.datesDisabled) {
+ inOpts.datesDisabled = [];
+ }
+ pickLevel = config.pickLevel = newPickLevel;
+ }
+
+ //*** dates ***//
+ // while min and maxDate for "no limit" in the options are better to be null
+ // (especially when updating), the ones in the config have to be undefined
+ // because null is treated as 0 (= unix epoch) when comparing with time value
+ let minDt = minDate;
+ let maxDt = maxDate;
+ if (inOpts.minDate !== undefined) {
+ const defaultMinDt = dateValue(0, 0, 1);
+ minDt = inOpts.minDate === null
+ ? defaultMinDt // set 0000-01-01 to prevent negative values for year
+ : validateDate(inOpts.minDate, format, locale, minDt);
+ if (minDt !== defaultMinDt) {
+ minDt = regularizeDate(minDt, pickLevel, false);
+ }
+ delete inOpts.minDate;
+ }
+ if (inOpts.maxDate !== undefined) {
+ maxDt = inOpts.maxDate === null
+ ? undefined
+ : validateDate(inOpts.maxDate, format, locale, maxDt);
+ if (maxDt !== undefined) {
+ maxDt = regularizeDate(maxDt, pickLevel, true);
+ }
+ delete inOpts.maxDate;
+ }
+ if (maxDt < minDt) {
+ minDate = config.minDate = maxDt;
+ maxDate = config.maxDate = minDt;
+ } else {
+ if (minDate !== minDt) {
+ minDate = config.minDate = minDt;
+ }
+ if (maxDate !== maxDt) {
+ maxDate = config.maxDate = maxDt;
+ }
+ }
+
+ if (inOpts.datesDisabled) {
+ config.datesDisabled = inOpts.datesDisabled.reduce((dates, dt) => {
+ const date = parseDate(dt, format, locale);
+ return date !== undefined
+ ? pushUnique(dates, regularizeDate(date, pickLevel, rangeSideIndex))
+ : dates;
+ }, []);
+ delete inOpts.datesDisabled;
+ }
+ if (inOpts.defaultViewDate !== undefined) {
+ const viewDate = parseDate(inOpts.defaultViewDate, format, locale);
+ if (viewDate !== undefined) {
+ config.defaultViewDate = viewDate;
+ }
+ delete inOpts.defaultViewDate;
+ }
+
+ //*** days of week ***//
+ if (inOpts.weekStart !== undefined) {
+ const wkStart = Number(inOpts.weekStart) % 7;
+ if (!isNaN(wkStart)) {
+ weekStart = config.weekStart = wkStart;
+ config.weekEnd = calcEndOfWeek(wkStart);
+ }
+ delete inOpts.weekStart;
+ }
+ if (inOpts.daysOfWeekDisabled) {
+ config.daysOfWeekDisabled = inOpts.daysOfWeekDisabled.reduce(sanitizeDOW, []);
+ delete inOpts.daysOfWeekDisabled;
+ }
+ if (inOpts.daysOfWeekHighlighted) {
+ config.daysOfWeekHighlighted = inOpts.daysOfWeekHighlighted.reduce(sanitizeDOW, []);
+ delete inOpts.daysOfWeekHighlighted;
+ }
+
+ //*** multi date ***//
+ if (inOpts.maxNumberOfDates !== undefined) {
+ const maxNumberOfDates = parseInt(inOpts.maxNumberOfDates, 10);
+ if (maxNumberOfDates >= 0) {
+ config.maxNumberOfDates = maxNumberOfDates;
+ config.multidate = maxNumberOfDates !== 1;
+ }
+ delete inOpts.maxNumberOfDates;
+ }
+ if (inOpts.dateDelimiter) {
+ config.dateDelimiter = String(inOpts.dateDelimiter);
+ delete inOpts.dateDelimiter;
+ }
+
+ //*** view ***//
+ let newMaxView = maxView;
+ if (inOpts.maxView !== undefined) {
+ newMaxView = validateViewId(inOpts.maxView, maxView);
+ delete inOpts.maxView;
+ }
+ // ensure max view >= pick level
+ newMaxView = pickLevel > newMaxView ? pickLevel : newMaxView;
+ if (newMaxView !== maxView) {
+ maxView = config.maxView = newMaxView;
+ }
+
+ let newStartView = startView;
+ if (inOpts.startView !== undefined) {
+ newStartView = validateViewId(inOpts.startView, newStartView);
+ delete inOpts.startView;
+ }
+ // ensure pick level <= start view <= max view
+ if (newStartView < pickLevel) {
+ newStartView = pickLevel;
+ } else if (newStartView > maxView) {
+ newStartView = maxView;
+ }
+ if (newStartView !== startView) {
+ config.startView = newStartView;
+ }
+
+ //*** template ***//
+ if (inOpts.prevArrow) {
+ const prevArrow = parseHTML(inOpts.prevArrow);
+ if (prevArrow.childNodes.length > 0) {
+ config.prevArrow = prevArrow.childNodes;
+ }
+ delete inOpts.prevArrow;
+ }
+ if (inOpts.nextArrow) {
+ const nextArrow = parseHTML(inOpts.nextArrow);
+ if (nextArrow.childNodes.length > 0) {
+ config.nextArrow = nextArrow.childNodes;
+ }
+ delete inOpts.nextArrow;
+ }
+
+ //*** misc ***//
+ if (inOpts.disableTouchKeyboard !== undefined) {
+ config.disableTouchKeyboard = 'ontouchstart' in document && !!inOpts.disableTouchKeyboard;
+ delete inOpts.disableTouchKeyboard;
+ }
+ if (inOpts.orientation) {
+ const orientation = inOpts.orientation.toLowerCase().split(/\s+/g);
+ config.orientation = {
+ x: orientation.find(x => (x === 'left' || x === 'right')) || 'auto',
+ y: orientation.find(y => (y === 'top' || y === 'bottom')) || 'auto',
+ };
+ delete inOpts.orientation;
+ }
+ if (inOpts.todayBtnMode !== undefined) {
+ switch(inOpts.todayBtnMode) {
+ case 0:
+ case 1:
+ config.todayBtnMode = inOpts.todayBtnMode;
+ }
+ delete inOpts.todayBtnMode;
+ }
+
+ //*** copy the rest ***//
+ Object.keys(inOpts).forEach((key) => {
+ if (inOpts[key] !== undefined && hasProperty(defaultOptions, key)) {
+ config[key] = inOpts[key];
+ }
+ });
+
+ return config;
+}
diff --git a/src/ui/static/js/datepicker/picker/Picker.js b/src/ui/static/js/datepicker/picker/Picker.js
new file mode 100644
index 000000000..cbcfaaf71
--- /dev/null
+++ b/src/ui/static/js/datepicker/picker/Picker.js
@@ -0,0 +1,389 @@
+import {hasProperty, lastItemOf, isInRange, limitToRange} from '../lib/utils.js';
+import {today} from '../lib/date.js';
+import {parseHTML, getParent, showElement, hideElement, emptyChildNodes} from '../lib/dom.js';
+import {registerListeners} from '../lib/event.js';
+import pickerTemplate from './templates/pickerTemplate.js';
+import DaysView from './views/DaysView.js';
+import MonthsView from './views/MonthsView.js';
+import YearsView from './views/YearsView.js';
+import {triggerDatepickerEvent} from '../events/functions.js';
+import {
+ onClickTodayBtn,
+ onClickClearBtn,
+ onClickViewSwitch,
+ onClickPrevBtn,
+ onClickNextBtn,
+ onClickView,
+ onMousedownPicker,
+} from '../events/pickerListeners.js';
+
+const orientClasses = ['left', 'top', 'right', 'bottom'].reduce((obj, key) => {
+ obj[key] = `datepicker-orient-${key}`;
+ return obj;
+}, {});
+const toPx = num => num ? `${num}px` : num;
+
+function processPickerOptions(picker, options) {
+ if (options.title !== undefined) {
+ if (options.title) {
+ picker.controls.title.textContent = options.title;
+ showElement(picker.controls.title);
+ } else {
+ picker.controls.title.textContent = '';
+ hideElement(picker.controls.title);
+ }
+ }
+ if (options.prevArrow) {
+ const prevBtn = picker.controls.prevBtn;
+ emptyChildNodes(prevBtn);
+ options.prevArrow.forEach((node) => {
+ prevBtn.appendChild(node.cloneNode(true));
+ });
+ }
+ if (options.nextArrow) {
+ const nextBtn = picker.controls.nextBtn;
+ emptyChildNodes(nextBtn);
+ options.nextArrow.forEach((node) => {
+ nextBtn.appendChild(node.cloneNode(true));
+ });
+ }
+ if (options.locale) {
+ picker.controls.todayBtn.textContent = options.locale.today;
+ picker.controls.clearBtn.textContent = options.locale.clear;
+ }
+ if (options.todayBtn !== undefined) {
+ if (options.todayBtn) {
+ showElement(picker.controls.todayBtn);
+ } else {
+ hideElement(picker.controls.todayBtn);
+ }
+ }
+ if (hasProperty(options, 'minDate') || hasProperty(options, 'maxDate')) {
+ const {minDate, maxDate} = picker.datepicker.config;
+ picker.controls.todayBtn.disabled = !isInRange(today(), minDate, maxDate);
+ }
+ if (options.clearBtn !== undefined) {
+ if (options.clearBtn) {
+ showElement(picker.controls.clearBtn);
+ } else {
+ hideElement(picker.controls.clearBtn);
+ }
+ }
+}
+
+// Compute view date to reset, which will be...
+// - the last item of the selected dates or defaultViewDate if no selection
+// - limitted to minDate or maxDate if it exceeds the range
+function computeResetViewDate(datepicker) {
+ const {dates, config} = datepicker;
+ const viewDate = dates.length > 0 ? lastItemOf(dates) : config.defaultViewDate;
+ return limitToRange(viewDate, config.minDate, config.maxDate);
+}
+
+// Change current view's view date
+function setViewDate(picker, newDate) {
+ const oldViewDate = new Date(picker.viewDate);
+ const newViewDate = new Date(newDate);
+ const {id, year, first, last} = picker.currentView;
+ const viewYear = newViewDate.getFullYear();
+
+ picker.viewDate = newDate;
+ if (viewYear !== oldViewDate.getFullYear()) {
+ triggerDatepickerEvent(picker.datepicker, 'changeYear');
+ }
+ if (newViewDate.getMonth() !== oldViewDate.getMonth()) {
+ triggerDatepickerEvent(picker.datepicker, 'changeMonth');
+ }
+
+ // return whether the new date is in different period on time from the one
+ // displayed in the current view
+ // when true, the view needs to be re-rendered on the next UI refresh.
+ switch (id) {
+ case 0:
+ return newDate < first || newDate > last;
+ case 1:
+ return viewYear !== year;
+ default:
+ return viewYear < first || viewYear > last;
+ }
+}
+
+function getTextDirection(el) {
+ return window.getComputedStyle(el).direction;
+}
+
+// find the closet scrollable ancestor elemnt under the body
+function findScrollParents(el) {
+ const parent = getParent(el);
+ if (parent === document.body || !parent) {
+ return;
+ }
+
+ // checking overflow only is enough because computed overflow cannot be
+ // visible or a combination of visible and other when either axis is set
+ // to other than visible.
+ // (Setting one axis to other than 'visible' while the other is 'visible'
+ // results in the other axis turning to 'auto')
+ return window.getComputedStyle(parent).overflow !== 'visible'
+ ? parent
+ : findScrollParents(parent);
+}
+
+// Class representing the picker UI
+export default class Picker {
+ constructor(datepicker) {
+ const {config} = this.datepicker = datepicker;
+
+ const template = pickerTemplate.replace(/%buttonClass%/g, config.buttonClass);
+ const element = this.element = parseHTML(template).firstChild;
+ const [header, main, footer] = element.firstChild.children;
+ const title = header.firstElementChild;
+ const [prevBtn, viewSwitch, nextBtn] = header.lastElementChild.children;
+ const [todayBtn, clearBtn] = footer.firstChild.children;
+ const controls = {
+ title,
+ prevBtn,
+ viewSwitch,
+ nextBtn,
+ todayBtn,
+ clearBtn,
+ };
+ this.main = main;
+ this.controls = controls;
+
+ const elementClass = datepicker.inline ? 'inline' : 'dropdown';
+ element.classList.add(`datepicker-${elementClass}`);
+
+ processPickerOptions(this, config);
+ this.viewDate = computeResetViewDate(datepicker);
+
+ // set up event listeners
+ registerListeners(datepicker, [
+ [element, 'mousedown', onMousedownPicker],
+ [main, 'click', onClickView.bind(null, datepicker)],
+ [controls.viewSwitch, 'click', onClickViewSwitch.bind(null, datepicker)],
+ [controls.prevBtn, 'click', onClickPrevBtn.bind(null, datepicker)],
+ [controls.nextBtn, 'click', onClickNextBtn.bind(null, datepicker)],
+ [controls.todayBtn, 'click', onClickTodayBtn.bind(null, datepicker)],
+ [controls.clearBtn, 'click', onClickClearBtn.bind(null, datepicker)],
+ ]);
+
+ // set up views
+ this.views = [
+ new DaysView(this),
+ new MonthsView(this),
+ new YearsView(this, {id: 2, name: 'years', cellClass: 'year', step: 1}),
+ new YearsView(this, {id: 3, name: 'decades', cellClass: 'decade', step: 10}),
+ ];
+ this.currentView = this.views[config.startView];
+
+ this.currentView.render();
+ this.main.appendChild(this.currentView.element);
+ if (config.container) {
+ config.container.appendChild(this.element);
+ } else {
+ datepicker.inputField.after(this.element);
+ }
+ }
+
+ setOptions(options) {
+ processPickerOptions(this, options);
+ this.views.forEach((view) => {
+ view.init(options, false);
+ });
+ this.currentView.render();
+ }
+
+ detach() {
+ this.element.remove();
+ }
+
+ show() {
+ if (this.active) {
+ return;
+ }
+
+ const {datepicker, element} = this;
+ if (datepicker.inline) {
+ element.classList.add('active');
+ } else {
+ // ensure picker's direction matches input's
+ const inputDirection = getTextDirection(datepicker.inputField);
+ if (inputDirection !== getTextDirection(getParent(element))) {
+ element.dir = inputDirection;
+ } else if (element.dir) {
+ element.removeAttribute('dir');
+ }
+
+ element.style.visiblity = 'hidden';
+ element.classList.add('active');
+ this.place();
+ element.style.visiblity = '';
+
+ if (datepicker.config.disableTouchKeyboard) {
+ datepicker.inputField.blur();
+ }
+ }
+ this.active = true;
+ triggerDatepickerEvent(datepicker, 'show');
+ }
+
+ hide() {
+ if (!this.active) {
+ return;
+ }
+ this.datepicker.exitEditMode();
+ this.element.classList.remove('active');
+ this.active = false;
+ triggerDatepickerEvent(this.datepicker, 'hide');
+ }
+
+ place() {
+ const {classList, offsetParent, style} = this.element;
+ const {config, inputField} = this.datepicker;
+ const {
+ width: calendarWidth,
+ height: calendarHeight,
+ } = this.element.getBoundingClientRect();
+ const {
+ left: inputLeft,
+ top: inputTop,
+ right: inputRight,
+ bottom: inputBottom,
+ width: inputWidth,
+ height: inputHeight
+ } = inputField.getBoundingClientRect();
+ let {x: orientX, y: orientY} = config.orientation;
+ let left = inputLeft;
+ let top = inputTop;
+
+ // caliculate offsetLeft/Top of inputField
+ if (offsetParent === document.body || !offsetParent) {
+ left += window.scrollX;
+ top += window.scrollY;
+ } else {
+ const offsetParentRect = offsetParent.getBoundingClientRect();
+ left -= offsetParentRect.left - offsetParent.scrollLeft;
+ top -= offsetParentRect.top - offsetParent.scrollTop;
+ }
+
+ // caliculate the boundaries of the visible area that contains inputField
+ const scrollParent = findScrollParents(inputField);
+ let scrollAreaLeft = 0;
+ let scrollAreaTop = 0;
+ let {
+ clientWidth: scrollAreaRight,
+ clientHeight: scrollAreaBottom,
+ } = document.documentElement;
+
+ if (scrollParent) {
+ const scrollParentRect = scrollParent.getBoundingClientRect();
+ if (scrollParentRect.top > 0) {
+ scrollAreaTop = scrollParentRect.top;
+ }
+ if (scrollParentRect.left > 0) {
+ scrollAreaLeft = scrollParentRect.left;
+ }
+ if (scrollParentRect.right < scrollAreaRight) {
+ scrollAreaRight = scrollParentRect.right;
+ }
+ if (scrollParentRect.bottom < scrollAreaBottom) {
+ scrollAreaBottom = scrollParentRect.bottom;
+ }
+ }
+
+ // determine the horizontal orientation and left position
+ let adjustment = 0;
+ if (orientX === 'auto') {
+ if (inputLeft < scrollAreaLeft) {
+ orientX = 'left';
+ adjustment = scrollAreaLeft - inputLeft;
+ } else if (inputLeft + calendarWidth > scrollAreaRight) {
+ orientX = 'right';
+ if (scrollAreaRight < inputRight) {
+ adjustment = scrollAreaRight - inputRight;
+ }
+ } else if (getTextDirection(inputField) === 'rtl') {
+ orientX = inputRight - calendarWidth < scrollAreaLeft ? 'left' : 'right';
+ } else {
+ orientX = 'left';
+ }
+ }
+ if (orientX === 'right') {
+ left += inputWidth - calendarWidth;
+ }
+ left += adjustment;
+
+ // determine the vertical orientation and top position
+ if (orientY === 'auto') {
+ if (inputTop - calendarHeight > scrollAreaTop) {
+ orientY = inputBottom + calendarHeight > scrollAreaBottom ? 'top' : 'bottom';
+ } else {
+ orientY = 'bottom';
+ }
+ }
+ if (orientY === 'top') {
+ top -= calendarHeight;
+ } else {
+ top += inputHeight;
+ }
+
+ classList.remove(...Object.values(orientClasses));
+ classList.add(orientClasses[orientX], orientClasses[orientY]);
+
+ style.left = toPx(left);
+ style.top = toPx(top);
+ }
+
+ setViewSwitchLabel(labelText) {
+ this.controls.viewSwitch.textContent = labelText;
+ }
+
+ setPrevBtnDisabled(disabled) {
+ this.controls.prevBtn.disabled = disabled;
+ }
+
+ setNextBtnDisabled(disabled) {
+ this.controls.nextBtn.disabled = disabled;
+ }
+
+ changeView(viewId) {
+ const oldView = this.currentView;
+ const newView = this.views[viewId];
+ if (newView.id !== oldView.id) {
+ this.currentView = newView;
+ this._renderMethod = 'render';
+ triggerDatepickerEvent(this.datepicker, 'changeView');
+ this.main.replaceChild(newView.element, oldView.element);
+ }
+ return this;
+ }
+
+ // Change the focused date (view date)
+ changeFocus(newViewDate) {
+ this._renderMethod = setViewDate(this, newViewDate) ? 'render' : 'refreshFocus';
+ this.views.forEach((view) => {
+ view.updateFocus();
+ });
+ return this;
+ }
+
+ // Apply the change of the selected dates
+ update() {
+ const newViewDate = computeResetViewDate(this.datepicker);
+ this._renderMethod = setViewDate(this, newViewDate) ? 'render' : 'refresh';
+ this.views.forEach((view) => {
+ view.updateFocus();
+ view.updateSelection();
+ });
+ return this;
+ }
+
+ // Refresh the picker UI
+ render(quickRender = true) {
+ const renderMethod = (quickRender && this._renderMethod) || 'render';
+ delete this._renderMethod;
+
+ this.currentView[renderMethod]();
+ }
+}
diff --git a/src/ui/static/js/datepicker/picker/templates/calendarWeeksTemplate.js b/src/ui/static/js/datepicker/picker/templates/calendarWeeksTemplate.js
new file mode 100644
index 000000000..ca70ae727
--- /dev/null
+++ b/src/ui/static/js/datepicker/picker/templates/calendarWeeksTemplate.js
@@ -0,0 +1,8 @@
+import {createTagRepeat, optimizeTemplateHTML} from '../../lib/utils.js';
+
+const calendarWeeksTemplate = optimizeTemplateHTML(`
+
+
${createTagRepeat('span', 6, {class: 'week'})}
+
`);
+
+export default calendarWeeksTemplate;
diff --git a/src/ui/static/js/datepicker/picker/templates/daysTemplate.js b/src/ui/static/js/datepicker/picker/templates/daysTemplate.js
new file mode 100644
index 000000000..c51c6d46d
--- /dev/null
+++ b/src/ui/static/js/datepicker/picker/templates/daysTemplate.js
@@ -0,0 +1,8 @@
+import {createTagRepeat, optimizeTemplateHTML} from '../../lib/utils.js';
+
+const daysTemplate = optimizeTemplateHTML(`
+
${createTagRepeat('span', 7, {class: 'dow'})}
+
${createTagRepeat('span', 42)}
+
`);
+
+export default daysTemplate;
diff --git a/src/ui/static/js/datepicker/picker/templates/pickerTemplate.js b/src/ui/static/js/datepicker/picker/templates/pickerTemplate.js
new file mode 100644
index 000000000..b389a4eb0
--- /dev/null
+++ b/src/ui/static/js/datepicker/picker/templates/pickerTemplate.js
@@ -0,0 +1,23 @@
+import {optimizeTemplateHTML} from '../../lib/utils.js';
+
+const pickerTemplate = optimizeTemplateHTML(``);
+
+export default pickerTemplate;
diff --git a/src/ui/static/js/datepicker/picker/views/DaysView.js b/src/ui/static/js/datepicker/picker/views/DaysView.js
new file mode 100644
index 000000000..de3c33617
--- /dev/null
+++ b/src/ui/static/js/datepicker/picker/views/DaysView.js
@@ -0,0 +1,238 @@
+import {hasProperty, pushUnique} from '../../lib/utils.js';
+import {today, dateValue, addDays, addWeeks, dayOfTheWeekOf, getWeek} from '../../lib/date.js';
+import {formatDate} from '../../lib/date-format.js';
+import {parseHTML, showElement, hideElement} from '../../lib/dom.js';
+import daysTemplate from '../templates/daysTemplate.js';
+import calendarWeeksTemplate from '../templates/calendarWeeksTemplate.js';
+import View from './View.js';
+
+export default class DaysView extends View {
+ constructor(picker) {
+ super(picker, {
+ id: 0,
+ name: 'days',
+ cellClass: 'day',
+ });
+ }
+
+ init(options, onConstruction = true) {
+ if (onConstruction) {
+ const inner = parseHTML(daysTemplate).firstChild;
+ this.dow = inner.firstChild;
+ this.grid = inner.lastChild;
+ this.element.appendChild(inner);
+ }
+ super.init(options);
+ }
+
+ setOptions(options) {
+ let updateDOW;
+
+ if (hasProperty(options, 'minDate')) {
+ this.minDate = options.minDate;
+ }
+ if (hasProperty(options, 'maxDate')) {
+ this.maxDate = options.maxDate;
+ }
+ if (options.datesDisabled) {
+ this.datesDisabled = options.datesDisabled;
+ }
+ if (options.daysOfWeekDisabled) {
+ this.daysOfWeekDisabled = options.daysOfWeekDisabled;
+ updateDOW = true;
+ }
+ if (options.daysOfWeekHighlighted) {
+ this.daysOfWeekHighlighted = options.daysOfWeekHighlighted;
+ }
+ if (options.todayHighlight !== undefined) {
+ this.todayHighlight = options.todayHighlight;
+ }
+ if (options.weekStart !== undefined) {
+ this.weekStart = options.weekStart;
+ this.weekEnd = options.weekEnd;
+ updateDOW = true;
+ }
+ if (options.locale) {
+ const locale = this.locale = options.locale;
+ this.dayNames = locale.daysMin;
+ this.switchLabelFormat = locale.titleFormat;
+ updateDOW = true;
+ }
+ if (options.beforeShowDay !== undefined) {
+ this.beforeShow = typeof options.beforeShowDay === 'function'
+ ? options.beforeShowDay
+ : undefined;
+ }
+
+ if (options.calendarWeeks !== undefined) {
+ if (options.calendarWeeks && !this.calendarWeeks) {
+ const weeksElem = parseHTML(calendarWeeksTemplate).firstChild;
+ this.calendarWeeks = {
+ element: weeksElem,
+ dow: weeksElem.firstChild,
+ weeks: weeksElem.lastChild,
+ };
+ this.element.insertBefore(weeksElem, this.element.firstChild);
+ } else if (this.calendarWeeks && !options.calendarWeeks) {
+ this.element.removeChild(this.calendarWeeks.element);
+ this.calendarWeeks = null;
+ }
+ }
+ if (options.showDaysOfWeek !== undefined) {
+ if (options.showDaysOfWeek) {
+ showElement(this.dow);
+ if (this.calendarWeeks) {
+ showElement(this.calendarWeeks.dow);
+ }
+ } else {
+ hideElement(this.dow);
+ if (this.calendarWeeks) {
+ hideElement(this.calendarWeeks.dow);
+ }
+ }
+ }
+
+ // update days-of-week when locale, daysOfweekDisabled or weekStart is changed
+ if (updateDOW) {
+ Array.from(this.dow.children).forEach((el, index) => {
+ const dow = (this.weekStart + index) % 7;
+ el.textContent = this.dayNames[dow];
+ el.className = this.daysOfWeekDisabled.includes(dow) ? 'dow disabled' : 'dow';
+ });
+ }
+ }
+
+ // Apply update on the focused date to view's settings
+ updateFocus() {
+ const viewDate = new Date(this.picker.viewDate);
+ const viewYear = viewDate.getFullYear();
+ const viewMonth = viewDate.getMonth();
+ const firstOfMonth = dateValue(viewYear, viewMonth, 1);
+ const start = dayOfTheWeekOf(firstOfMonth, this.weekStart, this.weekStart);
+
+ this.first = firstOfMonth;
+ this.last = dateValue(viewYear, viewMonth + 1, 0);
+ this.start = start;
+ this.focused = this.picker.viewDate;
+ }
+
+ // Apply update on the selected dates to view's settings
+ updateSelection() {
+ const {dates, rangepicker} = this.picker.datepicker;
+ this.selected = dates;
+ if (rangepicker) {
+ this.range = rangepicker.dates;
+ }
+ }
+
+ // Update the entire view UI
+ render() {
+ // update today marker on ever render
+ this.today = this.todayHighlight ? today() : undefined;
+ // refresh disabled dates on every render in order to clear the ones added
+ // by beforeShow hook at previous render
+ this.disabled = [...this.datesDisabled];
+
+ const switchLabel = formatDate(this.focused, this.switchLabelFormat, this.locale);
+ this.picker.setViewSwitchLabel(switchLabel);
+ this.picker.setPrevBtnDisabled(this.first <= this.minDate);
+ this.picker.setNextBtnDisabled(this.last >= this.maxDate);
+
+ if (this.calendarWeeks) {
+ // start of the UTC week (Monday) of the 1st of the month
+ const startOfWeek = dayOfTheWeekOf(this.first, 1, 1);
+ Array.from(this.calendarWeeks.weeks.children).forEach((el, index) => {
+ el.textContent = getWeek(addWeeks(startOfWeek, index));
+ });
+ }
+ Array.from(this.grid.children).forEach((el, index) => {
+ const classList = el.classList;
+ const current = addDays(this.start, index);
+ const date = new Date(current);
+ const day = date.getDay();
+
+ el.className = `datepicker-cell ${this.cellClass}`;
+ el.dataset.date = current;
+ el.textContent = date.getDate();
+
+ if (current < this.first) {
+ classList.add('prev');
+ } else if (current > this.last) {
+ classList.add('next');
+ }
+ if (this.today === current) {
+ classList.add('today');
+ }
+ if (current < this.minDate || current > this.maxDate || this.disabled.includes(current)) {
+ classList.add('disabled');
+ }
+ if (this.daysOfWeekDisabled.includes(day)) {
+ classList.add('disabled');
+ pushUnique(this.disabled, current);
+ }
+ if (this.daysOfWeekHighlighted.includes(day)) {
+ classList.add('highlighted');
+ }
+ if (this.range) {
+ const [rangeStart, rangeEnd] = this.range;
+ if (current > rangeStart && current < rangeEnd) {
+ classList.add('range');
+ }
+ if (current === rangeStart) {
+ classList.add('range-start');
+ }
+ if (current === rangeEnd) {
+ classList.add('range-end');
+ }
+ }
+ if (this.selected.includes(current)) {
+ classList.add('selected');
+ }
+ if (current === this.focused) {
+ classList.add('focused');
+ }
+
+ if (this.beforeShow) {
+ this.performBeforeHook(el, current, current);
+ }
+ });
+ }
+
+ // Update the view UI by applying the changes of selected and focused items
+ refresh() {
+ const [rangeStart, rangeEnd] = this.range || [];
+ this.grid
+ .querySelectorAll('.range, .range-start, .range-end, .selected, .focused')
+ .forEach((el) => {
+ el.classList.remove('range', 'range-start', 'range-end', 'selected', 'focused');
+ });
+ Array.from(this.grid.children).forEach((el) => {
+ const current = Number(el.dataset.date);
+ const classList = el.classList;
+ if (current > rangeStart && current < rangeEnd) {
+ classList.add('range');
+ }
+ if (current === rangeStart) {
+ classList.add('range-start');
+ }
+ if (current === rangeEnd) {
+ classList.add('range-end');
+ }
+ if (this.selected.includes(current)) {
+ classList.add('selected');
+ }
+ if (current === this.focused) {
+ classList.add('focused');
+ }
+ });
+ }
+
+ // Update the view UI by applying the change of focused item
+ refreshFocus() {
+ const index = Math.round((this.focused - this.start) / 86400000);
+ this.grid.querySelectorAll('.focused').forEach((el) => {
+ el.classList.remove('focused');
+ });
+ this.grid.children[index].classList.add('focused');
+ }
+}
diff --git a/src/ui/static/js/datepicker/picker/views/MonthsView.js b/src/ui/static/js/datepicker/picker/views/MonthsView.js
new file mode 100644
index 000000000..af4f6432c
--- /dev/null
+++ b/src/ui/static/js/datepicker/picker/views/MonthsView.js
@@ -0,0 +1,210 @@
+import {hasProperty, pushUnique, createTagRepeat} from '../../lib/utils.js';
+import {dateValue} from '../../lib/date.js';
+import {parseHTML} from '../../lib/dom.js';
+import View from './View.js';
+
+function computeMonthRange(range, thisYear) {
+ if (!range || !range[0] || !range[1]) {
+ return;
+ }
+
+ const [[startY, startM], [endY, endM]] = range;
+ if (startY > thisYear || endY < thisYear) {
+ return;
+ }
+ return [
+ startY === thisYear ? startM : -1,
+ endY === thisYear ? endM : 12,
+ ];
+}
+
+export default class MonthsView extends View {
+ constructor(picker) {
+ super(picker, {
+ id: 1,
+ name: 'months',
+ cellClass: 'month',
+ });
+ }
+
+ init(options, onConstruction = true) {
+ if (onConstruction) {
+ this.grid = this.element;
+ this.element.classList.add('months', 'datepicker-grid');
+ this.grid.appendChild(parseHTML(createTagRepeat('span', 12, {'data-month': ix => ix})));
+ }
+ super.init(options);
+ }
+
+ setOptions(options) {
+ if (options.locale) {
+ this.monthNames = options.locale.monthsShort;
+ }
+ if (hasProperty(options, 'minDate')) {
+ if (options.minDate === undefined) {
+ this.minYear = this.minMonth = this.minDate = undefined;
+ } else {
+ const minDateObj = new Date(options.minDate);
+ this.minYear = minDateObj.getFullYear();
+ this.minMonth = minDateObj.getMonth();
+ this.minDate = minDateObj.setDate(1);
+ }
+ }
+ if (hasProperty(options, 'maxDate')) {
+ if (options.maxDate === undefined) {
+ this.maxYear = this.maxMonth = this.maxDate = undefined;
+ } else {
+ const maxDateObj = new Date(options.maxDate);
+ this.maxYear = maxDateObj.getFullYear();
+ this.maxMonth = maxDateObj.getMonth();
+ this.maxDate = dateValue(this.maxYear, this.maxMonth + 1, 0);
+ }
+ }
+ if (this.isMinView) {
+ if (options.datesDisabled) {
+ this.datesDisabled = options.datesDisabled;
+ }
+ } else {
+ this.datesDisabled = [];
+ }
+ if (options.beforeShowMonth !== undefined) {
+ this.beforeShow = typeof options.beforeShowMonth === 'function'
+ ? options.beforeShowMonth
+ : undefined;
+ }
+ }
+
+ // Update view's settings to reflect the viewDate set on the picker
+ updateFocus() {
+ const viewDate = new Date(this.picker.viewDate);
+ this.year = viewDate.getFullYear();
+ this.focused = viewDate.getMonth();
+ }
+
+ // Update view's settings to reflect the selected dates
+ updateSelection() {
+ const {dates, rangepicker} = this.picker.datepicker;
+ this.selected = dates.reduce((selected, timeValue) => {
+ const date = new Date(timeValue);
+ const year = date.getFullYear();
+ const month = date.getMonth();
+ if (selected[year] === undefined) {
+ selected[year] = [month];
+ } else {
+ pushUnique(selected[year], month);
+ }
+ return selected;
+ }, {});
+ if (rangepicker && rangepicker.dates) {
+ this.range = rangepicker.dates.map(timeValue => {
+ const date = new Date(timeValue);
+ return isNaN(date) ? undefined : [date.getFullYear(), date.getMonth()];
+ });
+ }
+ }
+
+ // Update the entire view UI
+ render() {
+ // refresh disabled months on every render in order to clear the ones added
+ // by beforeShow hook at previous render
+ // this.disabled = [...this.datesDisabled];
+ this.disabled = this.datesDisabled.reduce((arr, disabled) => {
+ const dt = new Date(disabled);
+ if (this.year === dt.getFullYear()) {
+ arr.push(dt.getMonth());
+ }
+ return arr;
+ }, []);
+
+ this.picker.setViewSwitchLabel(this.year);
+ this.picker.setPrevBtnDisabled(this.year <= this.minYear);
+ this.picker.setNextBtnDisabled(this.year >= this.maxYear);
+
+ const selected = this.selected[this.year] || [];
+ const yrOutOfRange = this.year < this.minYear || this.year > this.maxYear;
+ const isMinYear = this.year === this.minYear;
+ const isMaxYear = this.year === this.maxYear;
+ const range = computeMonthRange(this.range, this.year);
+
+ Array.from(this.grid.children).forEach((el, index) => {
+ const classList = el.classList;
+ const date = dateValue(this.year, index, 1);
+
+ el.className = `datepicker-cell ${this.cellClass}`;
+ if (this.isMinView) {
+ el.dataset.date = date;
+ }
+ // reset text on every render to clear the custom content set
+ // by beforeShow hook at previous render
+ el.textContent = this.monthNames[index];
+
+ if (
+ yrOutOfRange
+ || isMinYear && index < this.minMonth
+ || isMaxYear && index > this.maxMonth
+ || this.disabled.includes(index)
+ ) {
+ classList.add('disabled');
+ }
+ if (range) {
+ const [rangeStart, rangeEnd] = range;
+ if (index > rangeStart && index < rangeEnd) {
+ classList.add('range');
+ }
+ if (index === rangeStart) {
+ classList.add('range-start');
+ }
+ if (index === rangeEnd) {
+ classList.add('range-end');
+ }
+ }
+ if (selected.includes(index)) {
+ classList.add('selected');
+ }
+ if (index === this.focused) {
+ classList.add('focused');
+ }
+
+ if (this.beforeShow) {
+ this.performBeforeHook(el, index, date);
+ }
+ });
+ }
+
+ // Update the view UI by applying the changes of selected and focused items
+ refresh() {
+ const selected = this.selected[this.year] || [];
+ const [rangeStart, rangeEnd] = computeMonthRange(this.range, this.year) || [];
+ this.grid
+ .querySelectorAll('.range, .range-start, .range-end, .selected, .focused')
+ .forEach((el) => {
+ el.classList.remove('range', 'range-start', 'range-end', 'selected', 'focused');
+ });
+ Array.from(this.grid.children).forEach((el, index) => {
+ const classList = el.classList;
+ if (index > rangeStart && index < rangeEnd) {
+ classList.add('range');
+ }
+ if (index === rangeStart) {
+ classList.add('range-start');
+ }
+ if (index === rangeEnd) {
+ classList.add('range-end');
+ }
+ if (selected.includes(index)) {
+ classList.add('selected');
+ }
+ if (index === this.focused) {
+ classList.add('focused');
+ }
+ });
+ }
+
+ // Update the view UI by applying the change of focused item
+ refreshFocus() {
+ this.grid.querySelectorAll('.focused').forEach((el) => {
+ el.classList.remove('focused');
+ });
+ this.grid.children[this.focused].classList.add('focused');
+ }
+}
\ No newline at end of file
diff --git a/src/ui/static/js/datepicker/picker/views/View.js b/src/ui/static/js/datepicker/picker/views/View.js
new file mode 100644
index 000000000..fe9123136
--- /dev/null
+++ b/src/ui/static/js/datepicker/picker/views/View.js
@@ -0,0 +1,55 @@
+import {pushUnique} from '../../lib/utils.js';
+import {parseHTML, replaceChildNodes} from '../../lib/dom.js';
+
+// Base class of the view classes
+export default class View {
+ constructor(picker, config) {
+ Object.assign(this, config, {
+ picker,
+ element: parseHTML(``).firstChild,
+ selected: [],
+ });
+ this.init(this.picker.datepicker.config);
+ }
+
+ init(options) {
+ if (options.pickLevel !== undefined) {
+ this.isMinView = this.id === options.pickLevel;
+ }
+ this.setOptions(options);
+ this.updateFocus();
+ this.updateSelection();
+ }
+
+ // Execute beforeShow() callback and apply the result to the element
+ // args:
+ // - current - current value on the iteration on view rendering
+ // - timeValue - time value of the date to pass to beforeShow()
+ performBeforeHook(el, current, timeValue) {
+ let result = this.beforeShow(new Date(timeValue));
+ switch (typeof result) {
+ case 'boolean':
+ result = {enabled: result};
+ break;
+ case 'string':
+ result = {classes: result};
+ }
+
+ if (result) {
+ if (result.enabled === false) {
+ el.classList.add('disabled');
+ pushUnique(this.disabled, current);
+ }
+ if (result.classes) {
+ const extraClasses = result.classes.split(/\s+/);
+ el.classList.add(...extraClasses);
+ if (extraClasses.includes('disabled')) {
+ pushUnique(this.disabled, current);
+ }
+ }
+ if (result.content) {
+ replaceChildNodes(el, result.content);
+ }
+ }
+ }
+}
diff --git a/src/ui/static/js/datepicker/picker/views/YearsView.js b/src/ui/static/js/datepicker/picker/views/YearsView.js
new file mode 100644
index 000000000..5faed1f91
--- /dev/null
+++ b/src/ui/static/js/datepicker/picker/views/YearsView.js
@@ -0,0 +1,176 @@
+import {hasProperty, pushUnique, createTagRepeat} from '../../lib/utils.js';
+import {dateValue, startOfYearPeriod} from '../../lib/date.js';
+import {parseHTML} from '../../lib/dom.js';
+import View from './View.js';
+
+function toTitleCase(word) {
+ return [...word].reduce((str, ch, ix) => str += ix ? ch : ch.toUpperCase(), '');
+}
+
+// Class representing the years and decades view elements
+export default class YearsView extends View {
+ constructor(picker, config) {
+ super(picker, config);
+ }
+
+ init(options, onConstruction = true) {
+ if (onConstruction) {
+ this.navStep = this.step * 10;
+ this.beforeShowOption = `beforeShow${toTitleCase(this.cellClass)}`;
+ this.grid = this.element;
+ this.element.classList.add(this.name, 'datepicker-grid');
+ this.grid.appendChild(parseHTML(createTagRepeat('span', 12)));
+ }
+ super.init(options);
+ }
+
+ setOptions(options) {
+ if (hasProperty(options, 'minDate')) {
+ if (options.minDate === undefined) {
+ this.minYear = this.minDate = undefined;
+ } else {
+ this.minYear = startOfYearPeriod(options.minDate, this.step);
+ this.minDate = dateValue(this.minYear, 0, 1);
+ }
+ }
+ if (hasProperty(options, 'maxDate')) {
+ if (options.maxDate === undefined) {
+ this.maxYear = this.maxDate = undefined;
+ } else {
+ this.maxYear = startOfYearPeriod(options.maxDate, this.step);
+ this.maxDate = dateValue(this.maxYear, 11, 31);
+ }
+ }
+ if (this.isMinView) {
+ if (options.datesDisabled) {
+ this.datesDisabled = options.datesDisabled;
+ }
+ } else {
+ this.datesDisabled = [];
+ }
+ if (options[this.beforeShowOption] !== undefined) {
+ const beforeShow = options[this.beforeShowOption];
+ this.beforeShow = typeof beforeShow === 'function' ? beforeShow : undefined;
+ }
+ }
+
+ // Update view's settings to reflect the viewDate set on the picker
+ updateFocus() {
+ const viewDate = new Date(this.picker.viewDate);
+ const first = startOfYearPeriod(viewDate, this.navStep);
+ const last = first + 9 * this.step;
+
+ this.first = first;
+ this.last = last;
+ this.start = first - this.step;
+ this.focused = startOfYearPeriod(viewDate, this.step);
+ }
+
+ // Update view's settings to reflect the selected dates
+ updateSelection() {
+ const {dates, rangepicker} = this.picker.datepicker;
+ this.selected = dates.reduce((years, timeValue) => {
+ return pushUnique(years, startOfYearPeriod(timeValue, this.step));
+ }, []);
+ if (rangepicker && rangepicker.dates) {
+ this.range = rangepicker.dates.map(timeValue => {
+ if (timeValue !== undefined) {
+ return startOfYearPeriod(timeValue, this.step);
+ }
+ });
+ }
+ }
+
+ // Update the entire view UI
+ render() {
+ // refresh disabled years on every render in order to clear the ones added
+ // by beforeShow hook at previous render
+ // this.disabled = [...this.datesDisabled];
+ this.disabled = this.datesDisabled.map(disabled => new Date(disabled).getFullYear());
+
+ this.picker.setViewSwitchLabel(`${this.first}-${this.last}`);
+ this.picker.setPrevBtnDisabled(this.first <= this.minYear);
+ this.picker.setNextBtnDisabled(this.last >= this.maxYear);
+
+ Array.from(this.grid.children).forEach((el, index) => {
+ const classList = el.classList;
+ const current = this.start + (index * this.step);
+ const date = dateValue(current, 0, 1);
+
+ el.className = `datepicker-cell ${this.cellClass}`;
+ if (this.isMinView) {
+ el.dataset.date = date;
+ }
+ el.textContent = el.dataset.year = current;
+
+ if (index === 0) {
+ classList.add('prev');
+ } else if (index === 11) {
+ classList.add('next');
+ }
+ if (current < this.minYear || current > this.maxYear || this.disabled.includes(current)) {
+ classList.add('disabled');
+ }
+ if (this.range) {
+ const [rangeStart, rangeEnd] = this.range;
+ if (current > rangeStart && current < rangeEnd) {
+ classList.add('range');
+ }
+ if (current === rangeStart) {
+ classList.add('range-start');
+ }
+ if (current === rangeEnd) {
+ classList.add('range-end');
+ }
+ }
+ if (this.selected.includes(current)) {
+ classList.add('selected');
+ }
+ if (current === this.focused) {
+ classList.add('focused');
+ }
+
+ if (this.beforeShow) {
+ this.performBeforeHook(el, current, date);
+ }
+ });
+ }
+
+ // Update the view UI by applying the changes of selected and focused items
+ refresh() {
+ const [rangeStart, rangeEnd] = this.range || [];
+ this.grid
+ .querySelectorAll('.range, .range-start, .range-end, .selected, .focused')
+ .forEach((el) => {
+ el.classList.remove('range', 'range-start', 'range-end', 'selected', 'focused');
+ });
+ Array.from(this.grid.children).forEach((el) => {
+ const current = Number(el.textContent);
+ const classList = el.classList;
+ if (current > rangeStart && current < rangeEnd) {
+ classList.add('range');
+ }
+ if (current === rangeStart) {
+ classList.add('range-start');
+ }
+ if (current === rangeEnd) {
+ classList.add('range-end');
+ }
+ if (this.selected.includes(current)) {
+ classList.add('selected');
+ }
+ if (current === this.focused) {
+ classList.add('focused');
+ }
+ });
+ }
+
+ // Update the view UI by applying the change of focused item
+ refreshFocus() {
+ const index = Math.round((this.focused - this.start) / this.step);
+ this.grid.querySelectorAll('.focused').forEach((el) => {
+ el.classList.remove('focused');
+ });
+ this.grid.children[index].classList.add('focused');
+ }
+}
diff --git a/src/ui/static/js/logs.js b/src/ui/static/js/logs.js
index 712c4e485..b401b09e6 100644
--- a/src/ui/static/js/logs.js
+++ b/src/ui/static/js/logs.js
@@ -1,5 +1,5 @@
import { Checkbox } from "./utils.js";
-//import AirDatepicker from "./air-datepicker/index.js";
+import Datepicker from "./datepicker/datepicker.js";
class LogsDropdown {
constructor(prefix = "logs") {
@@ -186,17 +186,45 @@ class FetchLogs {
return isSettings ? this.getLogsFromToDate() : "";
}
});
+ //disabled/enabled filed logic
+ this.toDateInp.addEventListener("input", (e) => {
+ this.toDateInp.value
+ ? this.updateDelayInp.setAttribute("disabled", "")
+ : this.updateDelayInp.removeAttribute("disabled");
+ this.toDateInp.value
+ ? this.liveUpdateInp.setAttribute("disabled", "")
+ : this.liveUpdateInp.removeAttribute("disabled");
+ });
+
+ this.updateDelayInp.addEventListener("input", (e) => {
+ this.updateDelayInp.value
+ ? this.toDateInp.setAttribute("disabled", "")
+ : this.toDateInp.removeAttribute("disabled");
+ });
+
+ this.liveUpdateInp.addEventListener("input", (e) => {
+ this.liveUpdateInp.checked
+ ? this.toDateInp.setAttribute("disabled", "")
+ : this.toDateInp.removeAttribute("disabled");
+ });
}
getSettings() {
//get settings
+ //check valid instance name
this.instanceName = this.instance.textContent;
if (!this.instanceName || this.instanceName.trim() === "none") return false;
- this.fromDate = this.fromDateInp.valueAsNumber
- ? this.fromDateInp.valueAsNumber
+ //if a date value exist, check if is a timestamp
+ if (this.fromDateInp.value && isNaN(Date.parse(this.fromDateInp.value)))
+ return false;
+ if (this.toDateInp.value && isNaN(Date.parse(this.toDateInp.value)))
+ return false;
+ //check valid date
+ this.fromDate = Date.parse(this.fromDateInp.value)
+ ? Date.parse(this.fromDateInp.value)
: Date.now() - 86400000;
- this.toDate = this.toDateInp.valueAsNumber
- ? this.toDateInp.valueAsNumber
+ this.toDate = Date.parse(this.toDateInp.value)
+ ? Date.parse(this.toDateInp.value)
: false;
this.updateDelay =
this.updateDelayInp.value * 1000 ? this.updateDelayInp.value : 2000;
@@ -372,7 +400,17 @@ class FilterLogs {
}
}
+class LogsDate {
+ constructor(el, options = {}) {
+ this.datepicker = new Datepicker(el, options);
+ this.init();
+ this.container = document.querySelector("[logs-settings]");
+ }
+}
+
const setCheckbox = new Checkbox("[logs-settings]");
const dropdown = new LogsDropdown();
const setLogs = new FetchLogs();
const setFilter = new FilterLogs();
+const fromDatepicker = new LogsDate(document.querySelector("input#from-date"));
+const toDatepicker = new LogsDate(document.querySelector("input#to-date"));
diff --git a/src/ui/templates/head.html b/src/ui/templates/head.html
index 66bc10a9c..d6cf815f1 100644
--- a/src/ui/templates/head.html
+++ b/src/ui/templates/head.html
@@ -45,7 +45,13 @@
{% elif current_endpoint == "cache" %}
{% elif current_endpoint == "logs" %}
-
+
+
+
{% endif %}
diff --git a/src/ui/templates/home.html b/src/ui/templates/home.html
index 6399ab542..a0f030b58 100644
--- a/src/ui/templates/home.html
+++ b/src/ui/templates/home.html
@@ -66,7 +66,7 @@
{{ instances_number }}
1 / {{ instances_number }}{{instance_health_count}} / {{ instances_number }}
is working
@@ -104,10 +104,18 @@
{{ services_number }}
- last created is
service-1{{services_ui_count}}
+ ui,
+ {{services_scheduler_count}}
+ scheduler,
+ {{services_autoconf_count}}
+ autoconf
diff --git a/src/ui/templates/logs.html b/src/ui/templates/logs.html
index f83e44480..7109446fb 100644
--- a/src/ui/templates/logs.html
+++ b/src/ui/templates/logs.html
@@ -71,11 +71,11 @@ url_for(request.endpoint)[1:].split("/")[-1].strip().replace('_', '-') %}
From date
@@ -91,11 +91,11 @@ url_for(request.endpoint)[1:].split("/")[-1].strip().replace('_', '-') %}
To date
@@ -144,14 +144,14 @@ url_for(request.endpoint)[1:].split("/")[-1].strip().replace('_', '-') %}
type="number"
id="update-delay"
name="update-delay"
- class="col-span-12 sm:col-span-6 lg:col-span-4 3xl:col-span-3 dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 disabled:opacity-75 focus:valid:border-green-500 focus:invalid:border-red-500 outline-none focus:border-primary text-sm leading-5.6 ease block w-full appearance-none rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-3 py-1 font-normal text-gray-700 transition-all placeholder:text-gray-500"
+ class="disabled:bg-gray-400 dark:disabled:bg-gray-800 dark:disabled:border-gray-800 dark:disabled:text-gray-300 disabled:text-gray-700 col-span-12 sm:col-span-6 lg:col-span-4 3xl:col-span-3 dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 disabled:opacity-75 focus:valid:border-green-500 focus:invalid:border-red-500 outline-none focus:border-primary text-sm leading-5.6 ease block w-full appearance-none rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-3 py-1 font-normal text-gray-700 transition-all placeholder:text-gray-500"
placeholder="2"
pattern="(.*?)"
required
/>
-
+