improved duration and minute selector (#2264)

* do not close modal if form is dirty
* deprecated TimesheetConfiguration
* inject timezone in form types
* cleanup usage of UserDateTimeFactory
* allow to configure increment steps for minutes
* use 15 minutes step for datetimepicker in project edit form
* use rounding rules for increments in minute select for begin and end
* allow duration in multi user and admin timesheet forms
* make dropdown values configurable
This commit is contained in:
Kevin Papst
2021-01-17 14:04:13 +01:00
committed by GitHub
parent e2324b7d51
commit 8d72d114c7
95 changed files with 1381 additions and 510 deletions

View File

@@ -14,95 +14,79 @@ namespace App\Configuration;
*/
class CalendarConfiguration implements SystemBundleConfiguration
{
use StringAccessibleConfigTrait;
private $configuration;
public function __construct(SystemConfiguration $configuration)
{
$this->configuration = $configuration;
}
public function find(string $key)
{
if (strpos($key, $this->getPrefix() . '.') === false) {
$key = $this->getPrefix() . '.' . $key;
}
return $this->configuration->find($key);
}
public function getPrefix(): string
{
return 'calendar';
}
/**
* @return array
*/
public function getBusinessDays(): array
{
return (array) $this->find('businessHours.days');
return $this->configuration->getCalendarBusinessDays();
}
/**
* @return string
*/
public function getBusinessTimeBegin(): string
{
return (string) $this->find('businessHours.begin');
return $this->configuration->getCalendarBusinessTimeBegin();
}
/**
* @return string
*/
public function getBusinessTimeEnd(): string
{
return (string) $this->find('businessHours.end');
return $this->configuration->getCalendarBusinessTimeEnd();
}
/**
* @return string
*/
public function getTimeframeBegin(): string
{
return (string) $this->find('visibleHours.begin');
return $this->configuration->getCalendarTimeframeBegin();
}
/**
* @return string
*/
public function getTimeframeEnd(): string
{
return (string) $this->find('visibleHours.end');
return $this->configuration->getCalendarTimeframeEnd();
}
/**
* @return int
*/
public function getDayLimit(): int
{
return (int) $this->find('day_limit');
return $this->configuration->getCalendarDayLimit();
}
/**
* @return bool
*/
public function isShowWeekNumbers(): bool
{
return (bool) $this->find('week_numbers');
return $this->configuration->isCalendarShowWeekNumbers();
}
/**
* @return bool
*/
public function isShowWeekends(): bool
{
return (bool) $this->find('weekends');
return $this->configuration->isCalendarShowWeekends();
}
/**
* @return null|string
*/
public function getGoogleApiKey(): ?string
{
return $this->find('google.api_key');
return $this->configuration->getCalendarGoogleApiKey();
}
/**
* @return null|array
*/
public function getGoogleSources(): ?array
{
return $this->find('google.sources');
return $this->configuration->getCalendarGoogleSources();
}
public function getSlotDuration(): string
{
return (string) $this->find('slot_duration');
return $this->configuration->getCalendarSlotDuration();
}
}

View File

@@ -14,7 +14,21 @@ namespace App\Configuration;
*/
class FormConfiguration implements SystemBundleConfiguration
{
use StringAccessibleConfigTrait;
private $configuration;
public function __construct(SystemConfiguration $configuration)
{
$this->configuration = $configuration;
}
public function find(string $key)
{
if (strpos($key, $this->getPrefix() . '.') === false) {
$key = $this->getPrefix() . '.' . $key;
}
return $this->configuration->find($key);
}
public function getPrefix(): string
{
@@ -23,36 +37,36 @@ class FormConfiguration implements SystemBundleConfiguration
public function getCustomerDefaultTimezone(): ?string
{
return $this->find('customer.timezone');
return $this->configuration->getCustomerDefaultTimezone();
}
public function getCustomerDefaultCurrency(): string
{
return $this->find('customer.currency');
return $this->configuration->getCustomerDefaultCurrency();
}
public function getCustomerDefaultCountry(): string
{
return $this->find('customer.country');
return $this->configuration->getCustomerDefaultCountry();
}
public function getUserDefaultTimezone(): ?string
{
return $this->find('user.timezone');
return $this->configuration->getUserDefaultTimezone();
}
public function getUserDefaultTheme(): ?string
{
return $this->find('user.theme');
return $this->configuration->getUserDefaultTheme();
}
public function getUserDefaultLanguage(): string
{
return $this->find('user.language');
return $this->configuration->getUserDefaultLanguage();
}
public function getUserDefaultCurrency(): string
{
return $this->find('user.currency');
return $this->configuration->getUserDefaultCurrency();
}
}

View File

@@ -23,10 +23,7 @@ class SystemConfiguration implements SystemBundleConfiguration
return $repository->getConfiguration();
}
public function getTimesheetDefaultBeginTime(): string
{
return (string) $this->find('timesheet.default_begin');
}
// ========== Calendar configurations ==========
public function getCalendarBusinessDays(): array
{
@@ -83,6 +80,8 @@ class SystemConfiguration implements SystemBundleConfiguration
return (string) $this->find('calendar.slot_duration');
}
// ========== Customer configurations ==========
public function getCustomerDefaultTimezone(): ?string
{
return $this->find('defaults.customer.timezone');
@@ -98,6 +97,8 @@ class SystemConfiguration implements SystemBundleConfiguration
return $this->find('defaults.customer.country');
}
// ========== User configurations ==========
public function getUserDefaultTimezone(): ?string
{
return $this->find('defaults.user.timezone');
@@ -117,4 +118,114 @@ class SystemConfiguration implements SystemBundleConfiguration
{
return $this->find('defaults.user.currency');
}
// ========== Timesheet configurations ==========
public function getTimesheetDefaultBeginTime(): string
{
return (string) $this->find('timesheet.default_begin');
}
public function isTimesheetAllowFutureTimes(): bool
{
return (bool) $this->find('timesheet.rules.allow_future_times');
}
public function isTimesheetAllowOverlappingRecords(): bool
{
return (bool) $this->find('timesheet.rules.allow_overlapping_records');
}
public function getTimesheetTrackingMode(): string
{
return (string) $this->find('timesheet.mode');
}
public function isTimesheetMarkdownEnabled(): bool
{
return (bool) $this->find('timesheet.markdown_content');
}
public function getTimesheetActiveEntriesHardLimit(): int
{
return (int) $this->find('timesheet.active_entries.hard_limit');
}
public function getTimesheetActiveEntriesSoftLimit(): int
{
return (int) $this->find('timesheet.active_entries.soft_limit');
}
public function getTimesheetDefaultRoundingDays(): string
{
return (string) $this->find('timesheet.rounding.default.days');
}
public function getTimesheetDefaultRoundingMode(): string
{
return (string) $this->find('timesheet.rounding.default.mode');
}
public function getTimesheetDefaultRoundingBegin(): int
{
return (int) $this->find('timesheet.rounding.default.begin');
}
public function getTimesheetDefaultRoundingEnd(): int
{
return (int) $this->find('timesheet.rounding.default.end');
}
public function getTimesheetDefaultRoundingDuration(): int
{
return (int) $this->find('timesheet.rounding.default.duration');
}
public function getTimesheetLockdownPeriodStart(): string
{
return (string) $this->find('timesheet.rules.lockdown_period_start');
}
public function getTimesheetLockdownPeriodEnd(): string
{
return (string) $this->find('timesheet.rules.lockdown_period_end');
}
public function getTimesheetLockdownGracePeriod(): string
{
return (string) $this->find('timesheet.rules.lockdown_grace_period');
}
public function isTimesheetLockdownActive(): bool
{
return !empty($this->find('timesheet.rules.lockdown_period_start')) && !empty($this->find('timesheet.rules.lockdown_period_end'));
}
private function getIncrement(string $key, int $fallback, int $min = 1): ?int
{
$config = $this->find($key);
if ($config === null || trim($config) === '') {
return $fallback;
}
$config = (int) $config;
return $config < $min ? null : $config;
}
public function getTimesheetIncrementDuration(): ?int
{
return $this->getIncrement('timesheet.duration_increment', $this->getTimesheetDefaultRoundingDuration(), 1);
}
public function getTimesheetIncrementBegin(): ?int
{
return $this->getIncrement('timesheet.time_increment', $this->getTimesheetDefaultRoundingBegin(), 0);
}
public function getTimesheetIncrementEnd(): ?int
{
return $this->getIncrement('timesheet.time_increment', $this->getTimesheetDefaultRoundingEnd(), 0);
}
}

View File

@@ -10,11 +10,25 @@
namespace App\Configuration;
/**
* @internal will be deprecated soon, use SystemConfiguration instead
* @deprecated since 1.13, use SystemConfiguration instead
*/
class TimesheetConfiguration implements SystemBundleConfiguration
{
use StringAccessibleConfigTrait;
private $configuration;
public function __construct(SystemConfiguration $configuration)
{
$this->configuration = $configuration;
}
public function find(string $key)
{
if (strpos($key, $this->getPrefix() . '.') === false) {
$key = $this->getPrefix() . '.' . $key;
}
return $this->configuration->find($key);
}
public function getPrefix(): string
{
@@ -23,81 +37,81 @@ class TimesheetConfiguration implements SystemBundleConfiguration
public function isAllowFutureTimes(): bool
{
return (bool) $this->find('rules.allow_future_times');
return $this->configuration->isTimesheetAllowFutureTimes();
}
public function isAllowOverlappingRecords(): bool
{
return (bool) $this->find('rules.allow_overlapping_records');
return $this->configuration->isTimesheetAllowOverlappingRecords();
}
public function getTrackingMode(): string
{
return (string) $this->find('mode');
return $this->configuration->getTimesheetTrackingMode();
}
public function getDefaultBeginTime(): string
{
return (string) $this->find('default_begin');
return $this->configuration->getTimesheetDefaultBeginTime();
}
public function isMarkdownEnabled(): bool
{
return (bool) $this->find('markdown_content');
return $this->configuration->isTimesheetMarkdownEnabled();
}
public function getActiveEntriesHardLimit(): int
{
return (int) $this->find('active_entries.hard_limit');
return $this->configuration->getTimesheetActiveEntriesHardLimit();
}
public function getActiveEntriesSoftLimit(): int
{
return (int) $this->find('active_entries.soft_limit');
return $this->configuration->getTimesheetActiveEntriesSoftLimit();
}
public function getDefaultRoundingDays(): string
{
return (string) $this->find('rounding.default.days');
return $this->configuration->getTimesheetDefaultRoundingDays();
}
public function getDefaultRoundingMode(): string
{
return (string) $this->find('rounding.default.mode');
return $this->configuration->getTimesheetDefaultRoundingMode();
}
public function getDefaultRoundingBegin(): int
{
return (int) $this->find('rounding.default.begin');
return $this->configuration->getTimesheetDefaultRoundingBegin();
}
public function getDefaultRoundingEnd(): int
{
return (int) $this->find('rounding.default.end');
return $this->configuration->getTimesheetDefaultRoundingEnd();
}
public function getDefaultRoundingDuration(): int
{
return (int) $this->find('rounding.default.duration');
return $this->configuration->getTimesheetDefaultRoundingDuration();
}
public function getLockdownPeriodStart(): string
{
return (string) $this->find('rules.lockdown_period_start');
return $this->configuration->getTimesheetLockdownPeriodStart();
}
public function getLockdownPeriodEnd(): string
{
return (string) $this->find('rules.lockdown_period_end');
return $this->configuration->getTimesheetLockdownPeriodEnd();
}
public function getLockdownGracePeriod(): string
{
return (string) $this->find('rules.lockdown_grace_period');
return $this->configuration->getTimesheetLockdownGracePeriod();
}
public function isLockdownActive(): bool
{
return !empty($this->find('rules.lockdown_period_start')) && !empty($this->find('rules.lockdown_period_end'));
return $this->configuration->isTimesheetLockdownActive();
}
}