Skip to content

Commit b662c30

Browse files
committed
Add DateRangeInput with daterangepicker for Bootstrap
1 parent 5463c0c commit b662c30

File tree

8 files changed

+675
-0
lines changed

8 files changed

+675
-0
lines changed

css/bootstrap-daterangepicker.css

Lines changed: 410 additions & 0 deletions
Large diffs are not rendered by default.

js/bootstrap-daterangepicker.min.js

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

js/moment.min.js

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/WebApp/BootstrapTheme/BootstrapTheme.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ class BootstrapTheme extends \WebApp\DefaultTheme\DefaultTheme {
77

88
public const MULTISELECT = 'multiselect';
99
public const DATEPICKER = 'datepicker';
10+
public const DATERANGEPICKER = 'daterangepicker';
1011
public const FILEUPLOAD = 'fileupload';
1112
public const IMAGEUPLOAD = 'imageupload';
1213
public const MULTIIMAGEUPLOAD = 'multiimageupload';
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
<?php
2+
3+
namespace WebApp\BootstrapTheme;
4+
5+
use TgI18n\I18N;
6+
use TgUtils\Date;
7+
use TgUtils\DateRange;
8+
9+
class DateRangeInputRenderer extends \WebApp\DefaultTheme\InputRenderer {
10+
11+
public function __construct($theme, $component) {
12+
parent::__construct($theme, $component);
13+
$this->theme->addFeature(BootstrapTheme::DATERANGEPICKER);
14+
$this->addClass('webappdaterange');
15+
$this->component->setType('text');
16+
}
17+
18+
public function render() {
19+
$options = $this->createOptions();
20+
$this->setData('options', $options);
21+
$this->setRangeData();
22+
$rc = '<div class="input-group date">'.
23+
'<div class="input-group-prepend input-group-addon">'.
24+
'<span class="input-group-text"><i class="fas fa-calendar-alt"></i></span>'.
25+
'</div>'.
26+
$this->renderStartTag('input').
27+
'</div>';
28+
return $rc;
29+
}
30+
31+
protected function createOptions() {
32+
$rc = array(
33+
'showDropdowns' => $this->component->showDropdowns(),
34+
'alwaysShowCalendars' => $this->component->alwaysShowCalendars(),
35+
'locale' => $this->createLocale(),
36+
'startDate' => $this->renderStartDate(),
37+
'endDate' => $this->renderEndDate(),
38+
);
39+
//return str_replace(array('"$$', '$$"'), array('', ''), json_encode($rc));
40+
return json_encode($rc);
41+
}
42+
43+
protected function setRangeData() {
44+
$this->setData('rangedefs', json_encode(array(
45+
I18N::_('today') => '[moment(), moment()]',
46+
I18N::_('yesterday') => '[moment().subtract(1, \'days\'), moment().subtract(1, \'days\')]',
47+
I18N::_('last_7_days') => '[moment().subtract(6, \'days\'), moment()]',
48+
I18N::_('last_30_days') => '[moment().subtract(29, \'days\'), moment()]',
49+
I18N::_('this_month') => '[moment().startOf(\'month\'), moment().endOf(\'month\')]',
50+
I18N::_('last_month') => '[moment().subtract(1, \'month\').startOf(\'month\'), moment().subtract(1, \'month\').endOf(\'month\')]'
51+
)));
52+
}
53+
54+
protected function createLocale() {
55+
$rc = array(
56+
"format" => I18N::_('daterange_format'), //"MM/DD/YYYY",
57+
"separator" => ' - ',
58+
"applyLabel" => I18N::_("apply_label"),
59+
"cancelLabel" => I18N::_("cancel_label"),
60+
"fromLabel" => I18N::_("from_label"),
61+
"toLabel" => I18N::_("to_label"),
62+
"customRangeLabel" => I18N::_("custom_label"),
63+
"weekLabel" => "W",
64+
"daysOfWeek" => $this->createWeekdayNames(),
65+
"monthNames" => $this->createMonthNames(),
66+
"firstDay" => 1,
67+
);
68+
return $rc;
69+
}
70+
71+
protected function getPeriod() {
72+
if ($this->period == NULL) {
73+
$orig = $this->component->getRange();
74+
$this->period = new DateRange();
75+
$this->period->set($orig->getFrom(), $orig->getUntil());
76+
if ($orig->getFrom() == NULL) $this->period->setFrom(new Date(time(), WFW_TIMEZONE));
77+
if ($orig->getUntil() == NULL) $this->period->setUntil(new Date(time(), WFW_TIMEZONE));
78+
}
79+
return $this->period;
80+
}
81+
82+
protected function renderStartDate() {
83+
$period = $this->getPeriod();
84+
return $period->getFrom()->format(I18N::_('daterange_internal_format'), TRUE);
85+
}
86+
87+
protected function renderEndDate() {
88+
$period = $this->getPeriod();
89+
return $period->getUntil()->format(I18N::_('daterange_internal_format'), TRUE);
90+
}
91+
92+
protected function createWeekdayNames() {
93+
$rc = array();
94+
foreach (array("sun", "mon", "tue", "wed", "thu", "fri", "sat") AS $k) {
95+
$rc[] = I18N::_($k);
96+
}
97+
return $rc;
98+
}
99+
100+
protected function createMonthNames() {
101+
$rc = array();
102+
foreach (array("january", "february", "march", "april", "may", "june", "july", "august", "september", "october", "november", "december") AS $k) {
103+
$rc[] = I18N::_($k);
104+
}
105+
return $rc;
106+
}
107+
108+
}

src/WebApp/BootstrapTheme/DefaultLayout.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ protected function renderLinks() {
2626
if ($this->theme->hasFeature(BootstrapTheme::DATEPICKER)) {
2727
$rc .= '<link rel="stylesheet" href="'.Utils::getCssPath('bootstrap-datepicker.min.css', TRUE).'" type="text/css">';
2828
}
29+
if ($this->theme->hasFeature(BootstrapTheme::DATERANGEPICKER)) {
30+
$rc .= '<link rel="stylesheet" href="'.Utils::getCssPath('bootstrap-daterangepicker.css', TRUE).'" type="text/css">';
31+
}
2932
if ($this->theme->hasFeature(BootstrapTheme::MULTISELECT)) {
3033
$rc .= '<link rel="stylesheet" href="'.Utils::getCssPath('filter-multi-select.css', TRUE).'" type="text/css">';
3134
}
@@ -189,6 +192,11 @@ protected function renderJavascript() {
189192
'<script src="'.Utils::getJavascriptPath('bootstrap-datepicker-locales.min.js', TRUE).'"></script>'.
190193
'<script>jQuery(document).ready(function () { $(\'.datepicker\').datepicker({ format: \''.I18N::_('datepicker_format').'\'}) })</script>';
191194
}
195+
if ($this->theme->hasFeature(BootstrapTheme::DATERANGEPICKER)) {
196+
$rc .= '<script src="'.Utils::getJavascriptPath('moment.min.js', TRUE).'"></script>'.
197+
'<script src="'.Utils::getJavascriptPath('bootstrap-daterangepicker.min.js', TRUE).'"></script>'.
198+
'<script>jQuery(document).ready(function () { jQuery(\'.webappdaterange\').each(function(index) { var elem = jQuery(this); var options = elem.data(\'options\'); var rangedefs = elem.data(\'rangedefs\'); options.ranges = {}; jQuery.each(rangedefs, function(key,value) { options.ranges[key] = eval(value); }); elem.daterangepicker(options); }) });</script>';
199+
}
192200
if ($this->theme->hasFeature(BootstrapTheme::TABS)) {
193201
$rc .= '<script type="text/javascript">jQuery(document).on(\'click\', \'ul.nav-tabs a\', function(e) { e.preventDefault(); jQuery(this).tab(\'show\').parent().addClass(\'active\'); jQuery(this).parent().siblings().removeClass(\'active\');});</script>';
194202
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?php
2+
3+
namespace WebApp\Component;
4+
5+
use TgI18n\I18N;
6+
use TgUtils\Date;
7+
use TgUtils\DateRange;
8+
9+
class DateRangeInput extends Input {
10+
11+
protected $showDropdowns = TRUE;
12+
protected $alwaysShowCalendars = TRUE;
13+
14+
public function __construct($parent, $id, $value = null) {
15+
parent::__construct($parent, $id, 'text', NULL);
16+
$this->period = $value;
17+
}
18+
19+
public function showDropdowns($newValue = NULL) {
20+
if ($newValue == NULL) return $this->showDropdowns;
21+
else $this->showDropdowns = $newValue;
22+
return $this;
23+
}
24+
25+
public function alwaysShowCalendars($newValue = NULL) {
26+
if ($newValue == NULL) return $this->alwaysShowCalendars;
27+
else $this->alwaysShowCalendars = $newValue;
28+
return $this;
29+
}
30+
31+
public function setRange($value) {
32+
$this->period = $value;
33+
return $this;
34+
}
35+
36+
public function getRange() {
37+
if ($this->period == NULL) $this->period = new DateRange();
38+
return $this->period;
39+
}
40+
41+
public static function getGetValue($name, $timezoneId) {
42+
$request = \TgUtils\Request::getRequest();
43+
$range = $request->getGetParam($name);
44+
return self::fromString($range);
45+
}
46+
47+
public static function getPostValue($name, $timezoneId) {
48+
$request = \TgUtils\Request::getRequest();
49+
$range = $request->getPostParam($name);
50+
return self::fromString($range);
51+
}
52+
53+
public function fromString($range) {
54+
if ($range != NULL) {
55+
list($fromS, $untilS) = explode(' - ', $range, 2);
56+
$from = Date::createFromFormat(I18N::_('daterange_internal_format').' H:i:s', $fromS.' 00:00:00', $timezoneId);
57+
$until = Date::createFromFormat(I18N::_('daterange_internal_format').' H:i:s', $untilS.' 23:59:59', $timezoneId);
58+
59+
return new DateRange($from, $until);
60+
}
61+
return NULL;
62+
}
63+
64+
}
65+

src/i18n.php

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,14 @@
357357
'de' => 'Die Löschung war nicht erfolgreich. Bitte versuche es später noch einmal.',
358358
'en' => 'The item could not be deleted. Please retry later.',
359359
),
360+
'daterange_format' => array(
361+
'de' => 'DD.MM.YYYY',
362+
'en' => 'DD/MM/YYYY',
363+
),
364+
'daterange_internal_format' => array(
365+
'de' => 'd.m.Y',
366+
'en' => 'd/m/Y',
367+
),
360368
'datepicker_format' => array(
361369
'de' => 'dd.mm.yyyy',
362370
'en' => 'dd/mm/yyyy',
@@ -582,6 +590,66 @@
582590
'de' => 'Dezember',
583591
'en' => 'December',
584592
),
593+
'mon' => array(
594+
'de' => 'Mo',
595+
'en' => 'Mo',
596+
),
597+
'tue' => array(
598+
'de' => 'Di',
599+
'en' => 'Tu',
600+
),
601+
'wed' => array(
602+
'de' => 'Mi',
603+
'en' => 'We',
604+
),
605+
'thu' => array(
606+
'de' => 'Do',
607+
'en' => 'Th',
608+
),
609+
'fri' => array(
610+
'de' => 'Fr',
611+
'en' => 'Fr',
612+
),
613+
'sat' => array(
614+
'de' => 'Sa',
615+
'en' => 'Sa',
616+
),
617+
'sun' => array(
618+
'de' => 'So',
619+
'en' => 'Su',
620+
),
621+
'apply_label' => array(
622+
'de' => 'Anwenden',
623+
'en' => 'Apply',
624+
),
625+
'today' => array(
626+
'de' => 'Heute',
627+
'en' => 'Today',
628+
),
629+
'yesterday' => array(
630+
'de' => 'Gestern',
631+
'en' => 'Yesterday',
632+
),
633+
'last_7_days' => array(
634+
'de' => 'Letzte 7 Tage',
635+
'en' => 'Last 7 days',
636+
),
637+
'last_30_days' => array(
638+
'de' => 'Letzte 30 Tage',
639+
'en' => 'Last 30 days',
640+
),
641+
'this_month' => array(
642+
'de' => 'Dieser Monat',
643+
'en' => 'This month',
644+
),
645+
'last_month' => array(
646+
'de' => 'Letzter Monat',
647+
'en' => 'Last month',
648+
),
649+
'custom_label' => array(
650+
'de' => 'Benutzerdefiniert',
651+
'en' => 'Custom',
652+
),
585653
/* Copy these 4 lines
586654
'' => array(
587655
'de' => '',

0 commit comments

Comments
 (0)