Remove date/time pickers

This commit is contained in:
Michael Weimann 2022-04-13 01:02:37 +02:00 committed by Igor Scheller
parent 4b77290134
commit c4b2fbda1a
14 changed files with 2048 additions and 2065 deletions

View File

@ -74,7 +74,7 @@ To view the output of `dump` call the following commands:
```bash ```bash
vendor/bin/var-dump-server vendor/bin/var-dump-server
# or for running in docker # or for running in docker
docker exec -it engelsystem_dev-es_php_fpm-1 vendor/bin/var-dump-server docker-compose exec es_php_fpm vendor/bin/var-dump-server
``` ```
For more information check out the Var Dump Server documentation: [Symfony VarDumper](https://symfony.com/components/VarDumper) For more information check out the Var Dump Server documentation: [Symfony VarDumper](https://symfony.com/components/VarDumper)

View File

@ -1,6 +1,7 @@
<?php <?php
use Engelsystem\Database\Db; use Engelsystem\Database\Db;
use Engelsystem\Helpers\Carbon;
use Engelsystem\Models\Room; use Engelsystem\Models\Room;
/** /**
@ -21,7 +22,7 @@ function admin_shifts()
$valid = true; $valid = true;
$request = request(); $request = request();
$session = session(); $session = session();
$start = parse_date('Y-m-d H:i', date('Y-m-d') . ' 00:00'); $start = Carbon::createTimestampFromDatetime(date('Y-m-d') . 'T00:00');
$end = $start; $end = $start;
$mode = 'single'; $mode = 'single';
$angelmode = 'manually'; $angelmode = 'manually';
@ -87,14 +88,14 @@ function admin_shifts()
error(__('Please select a location.')); error(__('Please select a location.'));
} }
if ($request->has('start') && $tmp = parse_date('Y-m-d H:i', $request->input('start'))) { if ($request->has('start') && $tmp = Carbon::createTimestampFromDatetime($request->input('start'))) {
$start = $tmp; $start = $tmp;
} else { } else {
$valid = false; $valid = false;
error(__('Please select a start time.')); error(__('Please select a start time.'));
} }
if ($request->has('end') && $tmp = parse_date('Y-m-d H:i', $request->input('end'))) { if ($request->has('end') && $tmp = Carbon::createTimestampFromDatetime($request->input('end'))) {
$end = $tmp; $end = $tmp;
} else { } else {
$valid = false; $valid = false;
@ -233,8 +234,8 @@ function admin_shifts()
}); });
// Alle Tage durchgehen // Alle Tage durchgehen
$end_day = parse_date('Y-m-d H:i', date('Y-m-d', $end) . ' 00:00'); $end_day = Carbon::createTimestampFromDatetime(date('Y-m-d', $end) . ' 00:00');
$day = parse_date('Y-m-d H:i', date('Y-m-d', $start) . ' 00:00'); $day = Carbon::createTimestampFromDatetime(date('Y-m-d', $start) . ' 00:00');
do { do {
// Alle Schichtwechselstunden durchgehen // Alle Schichtwechselstunden durchgehen
for($i = 0; $i < count($change_hours); $i++) { for($i = 0; $i < count($change_hours); $i++) {
@ -250,13 +251,13 @@ function admin_shifts()
break; break;
} }
$interval_start = parse_date('Y-m-d H:i', date('Y-m-d', $day) . ' ' . $start_hour); $interval_start = Carbon::createTimestampFromDatetime(date('Y-m-d', $day) . ' ' . $start_hour);
if (str_replace(':', '', $end_hour) < str_replace(':', '', $start_hour)) { if (str_replace(':', '', $end_hour) < str_replace(':', '', $start_hour)) {
// Endstunde kleiner Startstunde? Dann sind wir im nächsten Tag gelandet // Endstunde kleiner Startstunde? Dann sind wir im nächsten Tag gelandet
$interval_end = parse_date('Y-m-d H:i', date('Y-m-d', $day + 36 * 60 * 60) . ' ' . $end_hour); $interval_end = Carbon::createTimestampFromDatetime(date('Y-m-d', $day + 36 * 60 * 60) . ' ' . $end_hour);
} else { } else {
// Endstunde ist noch im selben Tag // Endstunde ist noch im selben Tag
$interval_end = parse_date('Y-m-d H:i', date('Y-m-d', $day) . ' ' . $end_hour); $interval_end = Carbon::createTimestampFromDatetime(date('Y-m-d', $day) . ' ' . $end_hour);
} }
// Liegt das Intervall vor dem Startzeitpunkt -> Überspringen // Liegt das Intervall vor dem Startzeitpunkt -> Überspringen
@ -290,13 +291,12 @@ function admin_shifts()
]; ];
} }
$day = parse_date('Y-m-d H:i', date('Y-m-d', $day + 36 * 60 * 60) . ' 00:00'); $day = Carbon::createTimestampFromDatetime(date('Y-m-d', $day + 36 * 60 * 60) . ' 00:00');
} while($day <= $end_day); } while($day <= $end_day);
usort($shifts, function ($a, $b) { usort($shifts, function ($a, $b) {
return $a['start'] < $b['start'] ? -1 : 1; return $a['start'] < $b['start'] ? -1 : 1;
}); });
} }
$shifts_table = []; $shifts_table = [];

View File

@ -1,4 +1,5 @@
<?php <?php
// Methods to build a html form. // Methods to build a html form.
use Carbon\Carbon; use Carbon\Carbon;
@ -68,9 +69,8 @@ function form_date($name, $label, $value, $start_date = '', $end_date = '')
$end_date = is_numeric($end_date) ? date('Y-m-d', $end_date) : ''; $end_date = is_numeric($end_date) ? date('Y-m-d', $end_date) : '';
return form_element($label, ' return form_element($label, '
<div class="input-group date" id="' . $dom_id . '" data-min-date="' . $start_date . '" data-max-date="' . $end_date . '" data-target-input="nearest"> <div class="input-group date" id="' . $dom_id . '">
<input type="date" placeholder="YYYY-MM-DD" name="' . $name . '" class="form-control" value="' . htmlspecialchars((string)$value) . '" autocomplete="off">' <input type="date" placeholder="YYYY-MM-DD" pattern="[0-9]{4}-[0-9]{2}-[0-9]{2}" min="' . $start_date . '" max="' . $end_date . '" name="' . $name . '" class="form-control" value="' . htmlspecialchars((string)$value) . '" autocomplete="off">
. '<span class="input-group-text">' . icon('grid-3x3-gap-fill') . '</span>
</div> </div>
', $dom_id); ', $dom_id);
} }
@ -92,10 +92,9 @@ function form_datetime(string $name, string $label, $value)
} }
return form_element($label, sprintf(' return form_element($label, sprintf('
<div class="input-group datetime" id="%s" data-target-input="nearest"> <div class="input-group datetime" id="%s">
<input type="datetime-local" placeholder="YYYY-MM-DD HH:MM" name="%s" <input type="datetime-local" pattern="[0-9]{4}-[0-9]{2}-[0-9]{2} ([01][0-9]|2[0-3]):[0-5][0-9]" placeholder="YYYY-MM-DD HH:MM" name="%s"
class="form-control" value="%s" autocomplete="off" data-target="#%s">' class="form-control" value="%s" autocomplete="off">
. '<span class="input-group-text">' . icon('grid-3x3-gap-fill') . '</span>
</div> </div>
', $dom_id, $name, htmlspecialchars($value ? $value->format('Y-m-d H:i') : ''), $dom_id), $dom_id); ', $dom_id, $name, htmlspecialchars($value ? $value->format('Y-m-d H:i') : ''), $dom_id), $dom_id);
} }
@ -286,7 +285,8 @@ function form_text($name, $label, $value, $disabled = false, $maxlength = null,
function form_text_placeholder($name, $placeholder, $value, $disabled = false) function form_text_placeholder($name, $placeholder, $value, $disabled = false)
{ {
$disabled = $disabled ? ' disabled="disabled"' : ''; $disabled = $disabled ? ' disabled="disabled"' : '';
return form_element('', return form_element(
'',
'<input class="form-control" id="form_' . $name . '" type="text" name="' . $name '<input class="form-control" id="form_' . $name . '" type="text" name="' . $name
. '" value="' . htmlspecialchars((string)$value) . '" placeholder="' . $placeholder . '" value="' . htmlspecialchars((string)$value) . '" placeholder="' . $placeholder
. '" ' . $disabled . '/>' . '" ' . $disabled . '/>'

View File

@ -1,6 +1,6 @@
<?php <?php
use Carbon\Carbon; use Engelsystem\Helpers\Carbon;
use Engelsystem\Http\Exceptions\HttpTemporaryRedirect; use Engelsystem\Http\Exceptions\HttpTemporaryRedirect;
use Engelsystem\Models\BaseModel; use Engelsystem\Models\BaseModel;
use Engelsystem\ValidationResult; use Engelsystem\ValidationResult;
@ -145,9 +145,14 @@ function check_request_date($name, $error_message = null, $null_allowed = false,
*/ */
function check_date($input, $error_message = null, $null_allowed = false, $time_allowed = false) function check_date($input, $error_message = null, $null_allowed = false, $time_allowed = false)
{ {
$trimmed_input = trim((string) $input);
try { try {
$format = $time_allowed ? 'Y-m-d H:i' : 'Y-m-d'; if ($time_allowed) {
$time = Carbon::createFromFormat($format, trim($input)); $time = Carbon::createFromDatetime($trimmed_input);
} else {
$time = Carbon::createFromFormat('Y-m-d', $trimmed_input);
}
} catch (InvalidArgumentException $e) { } catch (InvalidArgumentException $e) {
$time = null; $time = null;
} }

View File

@ -20,8 +20,7 @@
"moment": "^2.29.2", "moment": "^2.29.2",
"moment-timezone": "^0.5.31", "moment-timezone": "^0.5.31",
"select2": "^4.0.13", "select2": "^4.0.13",
"select2-bootstrap-5-theme": "^1.1.1", "select2-bootstrap-5-theme": "^1.1.1"
"tempusdominus-bootstrap-4": "^5.39.0"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.11.5", "@babel/core": "^7.11.5",

View File

@ -93,102 +93,6 @@ $(function () {
}); });
/*
* Add a datepicker to all date input fields.
*/
$(function () {
$([
{
'select': $('.input-group.date'),
'format': 'YYYY-MM-DD',
'extraFormats': []
},
{
'select': $('.input-group.datetime'),
'format': 'YYYY-MM-DD HH:mm',
'extraFormats': ['YYYY-MM-DDTHH:mm']
},
]).each(function (_, element) {
element.select.each(function () {
var elem = $(this);
var opts = {
minDate: '',
maxDate: '',
locale: $('html').attr('lang'),
format: element.format,
extraFormats: element.extraFormats,
widgetPositioning: {horizontal: 'auto', vertical: 'bottom'},
icons: {
time: 'bi bi-clock',
date: 'bi bi-calendar',
up: 'bi bi-arrow-up',
down: 'bi bi-arrow-down',
previous: 'bi bi-arrow-left',
next: 'bi bi-arrow-right'
}
};
$.extend(opts, elem.data());
if (opts.minDate.length === 0) {
delete opts.minDate;
}
if (opts.maxDate.length === 0) {
delete opts.maxDate;
}
elem.children('input').attr('type', 'text');
elem.datetimepicker(opts);
// close on click anywhere outside
$(document).on('click', () => {
elem.data('datetimepicker').hide()
})
elem.children().on('click', (ev) => {
ev.stopImmediatePropagation();
elem.data('datetimepicker').toggle();
});
});
});
});
/*
* Add a timepicker to all time input fields.
*/
$(function () {
$('.input-group.time').each(function () {
var elem = $(this);
var opts = {
locale: $('html').attr('lang'),
format: 'HH:mm',
widgetPositioning: {horizontal: 'auto', vertical: 'bottom'},
icons: {
up: 'bi bi-arrow-up',
down: 'bi bi-arrow-down'
}
};
$.extend(opts, elem.data());
elem.children('input').attr('type', 'text');
elem.children('input').on('click', function (ev) {
ev.stopImmediatePropagation();
if (typeof elem.data('datetimepicker') === 'undefined') {
elem.datetimepicker(opts);
elem.data('datetimepicker').show();
// close on click anywhere outside
$(document).on('click', () => {
elem.data('datetimepicker').hide()
})
} else {
elem.data('datetimepicker').toggle();
}
});
});
});
/* /*
* Button to set current time in time input fields. * Button to set current time in time input fields.
*/ */

View File

@ -4,7 +4,6 @@ require('jquery-ui');
window.bootstrap = require('bootstrap'); window.bootstrap = require('bootstrap');
window.moment = require('moment'); window.moment = require('moment');
require('moment/locale/de'); require('moment/locale/de');
require('tempusdominus-bootstrap-4/build/js/tempusdominus-bootstrap-4');
require('chart.js'); require('chart.js');
require('./forms'); require('./forms');
require('./sticky-headers'); require('./sticky-headers');

View File

@ -23,7 +23,6 @@ $theme-colors: map-merge($theme-colors, $custom-colors);
@import "~bootstrap/scss/bootstrap"; @import "~bootstrap/scss/bootstrap";
@import "~bootstrap-icons/font/bootstrap-icons"; @import "~bootstrap-icons/font/bootstrap-icons";
@import "~tempusdominus-bootstrap-4/build/css/tempusdominus-bootstrap-4";
@import "~select2/src/scss/core"; @import "~select2/src/scss/core";
@import "~select2-bootstrap-5-theme/src/include-all"; @import "~select2-bootstrap-5-theme/src/include-all";
@import "error"; @import "error";

View File

@ -263,20 +263,14 @@
<div class="row"> <div class="row">
<div class="col-md-3 col-lg-2"> <div class="col-md-3 col-lg-2">
<label class="form-label">Date</label> <label class="form-label">Date</label>
<div class="input-group date" data-target-input="nearest"> <div class="input-group date">
<input type="date" placeholder="YYYY-MM-DD" name="design-date" class="form-control" value="2021-09-15"> <input type="date" placeholder="YYYY-MM-DD" pattern="[0-9]{4}-[0-9]{2}-[0-9]{2}" name="design-date" class="form-control" value="2021-09-15">
<span class="input-group-text">
<span class="bi bi-grid-3x3-gap-fill"></span>
</span>
</div> </div>
</div> </div>
<div class="col-md-3 col-lg-2"> <div class="col-md-3 col-lg-2">
<label class="form-label">Datetime</label> <label class="form-label">Datetime</label>
<div class="input-group datetime" data-target-input="nearest"> <div class="input-group datetime">
<input type="datetime-local" placeholder="YYYY-MM-DD HH:MM" name="design-datetime" class="form-control" value="2021-09-15T13:37"> <input type="datetime-local" placeholder="YYYY-MM-DD HH:MM" pattern="[0-9]{4}-[0-9]{2}-[0-9]{2} ([01][0-9]|2[0-3]):[0-5][0-9]" name="design-datetime" class="form-control" value="2021-09-15T13:37">
<span class="input-group-text">
<span class="bi bi-grid-3x3-gap-fill"></span>
</span>
</div> </div>
</div> </div>
</div> </div>

View File

@ -7,7 +7,7 @@
<div class="col-12 col-xxl-5 row pe-xxl-0"> <div class="col-12 col-xxl-5 row pe-xxl-0">
<div class="col-6 pe-xxl-0">%start_select%</div> <div class="col-6 pe-xxl-0">%start_select%</div>
<div class="col-6"> <div class="col-6">
<div class="input-group time" data-target-input="nearest"> <div class="input-group time">
<input <input
type="time" class="form-control" id="start_time" name="start_time" size="5" type="time" class="form-control" id="start_time" name="start_time" size="5"
pattern="^\d{1,2}:\d{2}$" placeholder="HH:MM" maxlength="5" value="%start_time%" pattern="^\d{1,2}:\d{2}$" placeholder="HH:MM" maxlength="5" value="%start_time%"
@ -24,7 +24,7 @@
<div class="col-12 col-xxl-5 row px-xxl-0"> <div class="col-12 col-xxl-5 row px-xxl-0">
<div class="col-6 pe-xxl-0">%end_select%</div> <div class="col-6 pe-xxl-0">%end_select%</div>
<div class="col-6"> <div class="col-6">
<div class="input-group time" data-target-input="nearest"> <div class="input-group time">
<input <input
type="time" class="form-control" id="end_time" name="end_time" size="5" type="time" class="form-control" id="end_time" name="end_time" size="5"
pattern="^\d{1,2}:\d{2}$" placeholder="HH:MM" maxlength="5" value="%end_time%" pattern="^\d{1,2}:\d{2}$" placeholder="HH:MM" maxlength="5" value="%end_time%"

50
src/Helpers/Carbon.php Normal file
View File

@ -0,0 +1,50 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Helpers;
use Psr\SimpleCache\InvalidArgumentException;
class Carbon extends \Carbon\Carbon
{
public const DATETIME_LOCAL = '!Y-m-d\TH:i';
public const DATETIME_FALLBACK = '!Y-m-d H:i';
public const DATETIME_FORMATS = [
self::DATETIME_LOCAL,
self::DATETIME_FALLBACK,
];
/**
* Parses HTML datetime-local and ISO date/time strings.
*
* @param string $value
* @return \Carbon\Carbon|null Carbon if parseable, else null
* @see self::DATETIME_FORMATS
*/
public static function createFromDatetime(string $value): ?\Carbon\Carbon
{
foreach (self::DATETIME_FORMATS as $datetimeFormat) {
if (self::canBeCreatedFromFormat($value, $datetimeFormat)) {
return self::createFromFormat($datetimeFormat, $value);
}
}
return null;
}
/**
* Parses HTML datetime-local and ISO date/time strings.
*
* @param string $value
* @return int|null Timestamp if parseable, else null
* @see self::DATETIME_FORMATS
*/
public static function createTimestampFromDatetime(string $value): ?int
{
$carbon = self::createFromDateTime($value);
return $carbon === null ? null : $carbon->timestamp;
}
}

View File

@ -0,0 +1,68 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Test\Unit\Helpers;
use Engelsystem\Helpers\Carbon;
use PHPUnit\Framework\TestCase;
use Traversable;
class CarbonTest extends TestCase
{
public function validDates(): Traversable
{
$format = '!Y-m-d H:i';
yield '2022-04-16T10:44' => ['2022-04-16T10:44', Carbon::createFromFormat($format, '2022-04-16 10:44')];
yield '2022-04-16 10:44' => ['2022-04-16T10:44', Carbon::createFromFormat($format, '2022-04-16 10:44')];
yield '2020-12-24T13:37' => ['2020-12-24T13:37', Carbon::createFromFormat($format, '2020-12-24 13:37')];
yield '2020-12-24 13:37' => ['2020-12-24T13:37', Carbon::createFromFormat($format, '2020-12-24 13:37')];
}
public function invalidDates(): Traversable
{
yield '202-12-12 11:11' => ['202-12-12T11:11'];
yield '2022-23-24' => ['2022-23-24'];
yield '16.04.2022 11:24' => ['16.04.2022 11:24'];
}
/**
* @covers \Engelsystem\Helpers\Carbon::createFromDatetime
* @dataProvider validDates
*/
public function testCreateFromValidDatetime(string $value, Carbon $expected): void
{
$date = Carbon::createFromDatetime($value);
self::assertSame($expected->timestamp, $date->timestamp);
}
/**
* @covers \Engelsystem\Helpers\Carbon::createFromDatetime
* @dataProvider invalidDates
*/
public function testCreateFromInvalidDatetime(string $value): void
{
$date = Carbon::createFromDatetime($value);
self::assertNull($date);
}
/**
* @covers \Engelsystem\Helpers\Carbon::createTimestampFromDatetime
* @dataProvider validDates
*/
public function testCreateTimestampFromValidDatetime(string $value, Carbon $expected): void
{
$timestamp = Carbon::createTimestampFromDatetime($value);
self::assertSame($expected->timestamp, $timestamp);
}
/**
* @covers \Engelsystem\Helpers\Carbon::createTimestampFromDatetime
* @dataProvider invalidDates
*/
public function testCreateTimestampFromInvalidDatetime(string $value): void
{
$timestamp = Carbon::createTimestampFromDatetime($value);
self::assertNull($timestamp);
}
}

3821
yarn.lock

File diff suppressed because it is too large Load Diff