configs: overwrite via prepend, mode instead of duration_only (#715)
This commit is contained in:
@@ -42,5 +42,5 @@ filter:
|
|||||||
|
|
||||||
build_failure_conditions:
|
build_failure_conditions:
|
||||||
- 'project.metric("scrutinizer.quality", < 9.30)'
|
- 'project.metric("scrutinizer.quality", < 9.30)'
|
||||||
- 'project.metric("scrutinizer.test_coverage", < 0.73)'
|
- 'project.metric("scrutinizer.test_coverage", < 0.9)'
|
||||||
- 'project.metric_change("scrutinizer.test_coverage", < -0.01)'
|
- 'project.metric_change("scrutinizer.test_coverage", < -0.01)'
|
||||||
20
UPGRADING.md
20
UPGRADING.md
@@ -26,13 +26,13 @@ Remember to execute the necessary timezone conversion script, if you haven't upd
|
|||||||
|
|
||||||
### BC BREAKS
|
### BC BREAKS
|
||||||
|
|
||||||
This release contains some BC breaks, which were necessary before 1.0 will be released: "now or never" ;-) sorry for the troubles!
|
This release contains some BC breaks which were necessary before 1.0 will be released (_now or never_), to prevent those BC breaks after 1.0.
|
||||||
|
|
||||||
- **Kimai requires PHP 7.2 now => [PHP 7.1 expired 4 month ago](https://www.php.net/supported-versions.php)**
|
- **Kimai requires PHP 7.2 now => [PHP 7.1 expired 4 month ago](https://www.php.net/supported-versions.php)**
|
||||||
- The `.env` variable `DATABASE_PREFIX` was removed and the table prefix is now hardcoded to `kimai2_`. If you used another prefix,
|
- The `.env` variable `DATABASE_PREFIX` was removed and the table prefix is now hardcoded to `kimai2_`. If you used another prefix,
|
||||||
you have to rename your tables manually before starting the update process. You can delete the row `DATABASE_PREFIX` from your `.env` file.
|
you have to rename your tables manually before starting the update process. You can delete the row `DATABASE_PREFIX` from your `.env` file.
|
||||||
- API: Format for DateTime objects changed, now including timezone identifier (previously 2019-03-02 14:23 - now 2019-03-02T14:23:00+00:00), see [#718](https://github.com/kevinpapst/kimai2/pull/718)
|
- API: Format for DateTime objects changed, now including timezone identifier (previously `2019-03-02 14:23` - now `2019-03-02T14:23:00+00:00`), see [#718](https://github.com/kevinpapst/kimai2/pull/718)
|
||||||
- API: changed from snake_case to camelCase (hourlyRate vs hourly_rate / fixedRate vs fixed_rate / orderNumber vs order_number / i18n config)
|
- API: changed from snake_case to camelCase (affected fields: hourlyRate vs hourly_rate / fixedRate vs fixed_rate / orderNumber vs order_number / i18n config object)
|
||||||
- Plugin mechanism changed: existing Plugins have to be deleted or updated
|
- Plugin mechanism changed: existing Plugins have to be deleted or updated
|
||||||
|
|
||||||
### Apply necessary changes to your `local.yaml`:
|
### Apply necessary changes to your `local.yaml`:
|
||||||
@@ -42,6 +42,20 @@ New permissions are available:
|
|||||||
- `system_actions` - for the experimental feature to flush your cache from the about screen
|
- `system_actions` - for the experimental feature to flush your cache from the about screen
|
||||||
- `plugins` - for accessing the new plugins screen
|
- `plugins` - for accessing the new plugins screen
|
||||||
|
|
||||||
|
The setting `kimai.timesheet.mode` replaces the setting `kimai.timesheet.duration_only`. If you used the duration_only mode, you need to change your config:
|
||||||
|
```yaml
|
||||||
|
# Before
|
||||||
|
kimai:
|
||||||
|
timesheet:
|
||||||
|
duration_only: true
|
||||||
|
|
||||||
|
# After
|
||||||
|
kimai:
|
||||||
|
timesheet:
|
||||||
|
mode: duration_only
|
||||||
|
```
|
||||||
|
Or switch the mode directly in the new System configuration screen within Kimai.
|
||||||
|
|
||||||
## [0.8.1](https://github.com/kevinpapst/kimai2/releases/tag/0.8.1)
|
## [0.8.1](https://github.com/kevinpapst/kimai2/releases/tag/0.8.1)
|
||||||
|
|
||||||
A bug fixing release. Remember to execute the necessary timezone conversion script, if you haven't updated to 0.8 before (see below)!
|
A bug fixing release. Remember to execute the necessary timezone conversion script, if you haven't updated to 0.8 before (see below)!
|
||||||
|
|||||||
@@ -1,10 +1,20 @@
|
|||||||
|
# ---------------------------------------------------------------------------------------------
|
||||||
|
# DO NOT EDIT THIS FILE, INSTEAD CREATE THE FILE "local.yaml" AND ADD YOUR SETTINGS IN THERE.
|
||||||
|
# See https://www.kimai.org/documentation/configurations.html
|
||||||
|
#
|
||||||
|
# Be aware that this file is YAML format and the indentation is important.
|
||||||
|
# Each config level needs to be indented with 4 additional spaces.
|
||||||
|
#
|
||||||
|
# ---------------------------------------------------------------------------------------------
|
||||||
kimai:
|
kimai:
|
||||||
|
|
||||||
# --------------------------------------------------------------------------------
|
# --------------------------------------------------------------------------------
|
||||||
# Settings for the user management and login forms
|
# You can disable the user management functions in the authentication screens (default: true).
|
||||||
user:
|
#user:
|
||||||
registration: true
|
# registration: false
|
||||||
password_reset: true
|
# password_reset: false
|
||||||
|
# --------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------------------
|
# --------------------------------------------------------------------------------
|
||||||
# All configs related to timesheet and record management
|
# All configs related to timesheet and record management
|
||||||
@@ -13,9 +23,11 @@ kimai:
|
|||||||
# render timesheet descriptions with markdown
|
# render timesheet descriptions with markdown
|
||||||
markdown_content: false
|
markdown_content: false
|
||||||
|
|
||||||
# Whether we display start and end time columns (false) or durations only (true).
|
# The time-tracking mode that should be used (allowed values: default, duration_only)
|
||||||
# Setting this to true will also change the "edit timesheet" forms, more infos available in the configurations docu.
|
#
|
||||||
duration_only: false
|
# default: display start and end time columns in timesheet view and form
|
||||||
|
# duration_only: display start time and duration, https://www.kimai.org/documentation/timesheet.html#duration-only-mode
|
||||||
|
mode: default
|
||||||
|
|
||||||
# Rounding rules are used to round the begin & end dates and the duration for timesheet records.
|
# Rounding rules are used to round the begin & end dates and the duration for timesheet records.
|
||||||
# The "default" rule will round "begin" down and "end" up to the full minute, the "duration" will not be rounded.
|
# The "default" rule will round "begin" down and "end" up to the full minute, the "duration" will not be rounded.
|
||||||
@@ -52,6 +64,7 @@ kimai:
|
|||||||
# whether records in the future can be created
|
# whether records in the future can be created
|
||||||
allow_future_times: true
|
allow_future_times: true
|
||||||
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------------------
|
# --------------------------------------------------------------------------------
|
||||||
# Invoice management
|
# Invoice management
|
||||||
#invoice:
|
#invoice:
|
||||||
@@ -60,6 +73,7 @@ kimai:
|
|||||||
# - 'var/invoices/'
|
# - 'var/invoices/'
|
||||||
# - 'templates/invoice/renderer/'
|
# - 'templates/invoice/renderer/'
|
||||||
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------------------
|
# --------------------------------------------------------------------------------
|
||||||
# Default settings used to populate forms
|
# Default settings used to populate forms
|
||||||
#defaults:
|
#defaults:
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ namespace App\Configuration;
|
|||||||
|
|
||||||
class TimesheetConfiguration implements SystemBundleConfiguration
|
class TimesheetConfiguration implements SystemBundleConfiguration
|
||||||
{
|
{
|
||||||
|
public const MODE_DURATION_ONLY = 'duration_only';
|
||||||
|
public const MODE_DEFAULT = 'default';
|
||||||
|
|
||||||
use StringAccessibleConfigTrait;
|
use StringAccessibleConfigTrait;
|
||||||
|
|
||||||
public function getPrefix(): string
|
public function getPrefix(): string
|
||||||
@@ -25,7 +28,7 @@ class TimesheetConfiguration implements SystemBundleConfiguration
|
|||||||
|
|
||||||
public function isDurationOnly(): bool
|
public function isDurationOnly(): bool
|
||||||
{
|
{
|
||||||
return (bool) $this->find('duration_only');
|
return $this->find('mode') === self::MODE_DURATION_ONLY;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isMarkdownEnabled(): bool
|
public function isMarkdownEnabled(): bool
|
||||||
|
|||||||
@@ -9,13 +9,15 @@
|
|||||||
|
|
||||||
namespace App\Controller;
|
namespace App\Controller;
|
||||||
|
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController as BaseAbstractController;
|
||||||
use Symfony\Component\Translation\DataCollectorTranslator;
|
use Symfony\Component\Translation\DataCollectorTranslator;
|
||||||
|
use Symfony\Contracts\Service\ServiceSubscriberInterface;
|
||||||
|
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The abstract base controller.
|
* The abstract base controller.
|
||||||
*/
|
*/
|
||||||
abstract class AbstractController extends Controller
|
abstract class AbstractController extends BaseAbstractController implements ServiceSubscriberInterface
|
||||||
{
|
{
|
||||||
public const FLASH_SUCCESS = 'success';
|
public const FLASH_SUCCESS = 'success';
|
||||||
public const FLASH_WARNING = 'warning';
|
public const FLASH_WARNING = 'warning';
|
||||||
@@ -89,4 +91,11 @@ abstract class AbstractController extends Controller
|
|||||||
|
|
||||||
$this->addFlash($type, $message);
|
$this->addFlash($type, $message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function getSubscribedServices()
|
||||||
|
{
|
||||||
|
return array_merge(parent::getSubscribedServices(), [
|
||||||
|
'translator' => TranslatorInterface::class
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ use App\Event\SystemConfigurationEvent;
|
|||||||
use App\Form\Model\Configuration;
|
use App\Form\Model\Configuration;
|
||||||
use App\Form\Model\SystemConfiguration as SystemConfigurationModel;
|
use App\Form\Model\SystemConfiguration as SystemConfigurationModel;
|
||||||
use App\Form\SystemConfigurationForm;
|
use App\Form\SystemConfigurationForm;
|
||||||
|
use App\Form\Type\TimesheetModeType;
|
||||||
use App\Repository\ConfigurationRepository;
|
use App\Repository\ConfigurationRepository;
|
||||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
|
||||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||||
@@ -199,11 +200,11 @@ class SystemConfigurationController extends AbstractController
|
|||||||
->setSection(SystemConfigurationModel::SECTION_TIMESHEET)
|
->setSection(SystemConfigurationModel::SECTION_TIMESHEET)
|
||||||
->setConfiguration([
|
->setConfiguration([
|
||||||
(new Configuration())
|
(new Configuration())
|
||||||
->setName('timesheet.markdown_content')
|
->setName('timesheet.mode')
|
||||||
->setType(CheckboxType::class)
|
->setType(TimesheetModeType::class)
|
||||||
->setTranslationDomain('system-configuration'),
|
->setTranslationDomain('system-configuration'),
|
||||||
(new Configuration())
|
(new Configuration())
|
||||||
->setName('timesheet.duration_only')
|
->setName('timesheet.markdown_content')
|
||||||
->setType(CheckboxType::class)
|
->setType(CheckboxType::class)
|
||||||
->setTranslationDomain('system-configuration'),
|
->setTranslationDomain('system-configuration'),
|
||||||
(new Configuration())
|
(new Configuration())
|
||||||
|
|||||||
@@ -69,7 +69,6 @@ class TimesheetController extends AbstractController
|
|||||||
'showFilter' => $form->isSubmitted(),
|
'showFilter' => $form->isSubmitted(),
|
||||||
'toolbarForm' => $form->createView(),
|
'toolbarForm' => $form->createView(),
|
||||||
'showSummary' => $this->getUser()->getPreferenceValue('timesheet.daily_stats', false),
|
'showSummary' => $this->getUser()->getPreferenceValue('timesheet.daily_stats', false),
|
||||||
'duration_only' => $this->configuration->isDurationOnly(),
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -65,7 +65,6 @@ class TimesheetTeamController extends AbstractController
|
|||||||
'query' => $query,
|
'query' => $query,
|
||||||
'showFilter' => $form->isSubmitted(),
|
'showFilter' => $form->isSubmitted(),
|
||||||
'toolbarForm' => $form->createView(),
|
'toolbarForm' => $form->createView(),
|
||||||
'duration_only' => $this->configuration->isDurationOnly(),
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ class CustomerFixtures extends Fixture
|
|||||||
public const MIN_BUDGET = 0;
|
public const MIN_BUDGET = 0;
|
||||||
public const MAX_BUDGET = 100000;
|
public const MAX_BUDGET = 100000;
|
||||||
public const MIN_GLOBAL_ACTIVITIES = 5;
|
public const MIN_GLOBAL_ACTIVITIES = 5;
|
||||||
public const MAX_GLOBAL_ACTIVITIES = 50;
|
public const MAX_GLOBAL_ACTIVITIES = 30;
|
||||||
public const MIN_PROJECTS_PER_CUSTOMER = 2;
|
public const MIN_PROJECTS_PER_CUSTOMER = 2;
|
||||||
public const MAX_PROJECTS_PER_CUSTOMER = 25;
|
public const MAX_PROJECTS_PER_CUSTOMER = 25;
|
||||||
public const MIN_ACTIVITIES_PER_PROJECT = 0;
|
public const MIN_ACTIVITIES_PER_PROJECT = 0;
|
||||||
@@ -72,7 +72,7 @@ class CustomerFixtures extends Fixture
|
|||||||
|
|
||||||
$amountGlobalActivities = rand(self::MIN_GLOBAL_ACTIVITIES, self::MAX_GLOBAL_ACTIVITIES);
|
$amountGlobalActivities = rand(self::MIN_GLOBAL_ACTIVITIES, self::MAX_GLOBAL_ACTIVITIES);
|
||||||
for ($c = 1; $c <= $amountGlobalActivities; $c++) {
|
for ($c = 1; $c <= $amountGlobalActivities; $c++) {
|
||||||
$visibleActivity = 0 != $a % 3;
|
$visibleActivity = 0 != $c % 4;
|
||||||
$activity = $this->createActivity($faker, null, $visibleActivity);
|
$activity = $this->createActivity($faker, null, $visibleActivity);
|
||||||
$manager->persist($activity);
|
$manager->persist($activity);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,14 @@ class AppExtension extends Extension
|
|||||||
$config = [];
|
$config = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @deprecated since 0.9, duration_only will be removed with 1.0
|
||||||
|
if (isset($config['timesheet']['duration_only'])) {
|
||||||
|
trigger_error('Configuration "kimai.timesheet.duration_only" is deprecated, please remove it', E_USER_DEPRECATED);
|
||||||
|
if (true === $config['timesheet']['duration_only'] && 'duration_only' !== $config['timesheet']['mode']) {
|
||||||
|
trigger_error('Found ambiguous configuration. Please remove "kimai.timesheet.duration_only" and set "kimai.timesheet.mode" instead.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// safe alternatives to %kernel.project_dir%
|
// safe alternatives to %kernel.project_dir%
|
||||||
$container->setParameter('kimai.data_dir', $config['data_dir']);
|
$container->setParameter('kimai.data_dir', $config['data_dir']);
|
||||||
$container->setParameter('kimai.plugin_dir', $config['plugin_dir']);
|
$container->setParameter('kimai.plugin_dir', $config['plugin_dir']);
|
||||||
|
|||||||
@@ -75,6 +75,16 @@ class Configuration implements ConfigurationInterface
|
|||||||
->children()
|
->children()
|
||||||
->booleanNode('duration_only')
|
->booleanNode('duration_only')
|
||||||
->defaultValue(false)
|
->defaultValue(false)
|
||||||
|
->setDeprecated()
|
||||||
|
->end()
|
||||||
|
->scalarNode('mode')
|
||||||
|
->defaultValue('default')
|
||||||
|
->validate()
|
||||||
|
->ifTrue(function ($value) {
|
||||||
|
return !in_array($value, ['default', 'duration_only']);
|
||||||
|
})
|
||||||
|
->thenInvalid('Chosen timesheet mode is invalid, allowed values: default, duration_only')
|
||||||
|
->end()
|
||||||
->end()
|
->end()
|
||||||
->booleanNode('markdown_content')
|
->booleanNode('markdown_content')
|
||||||
->defaultValue(false)
|
->defaultValue(false)
|
||||||
|
|||||||
43
src/Form/Type/TimesheetModeType.php
Normal file
43
src/Form/Type/TimesheetModeType.php
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Kimai time-tracking app.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Form\Type;
|
||||||
|
|
||||||
|
use App\Configuration\TimesheetConfiguration;
|
||||||
|
use Symfony\Component\Form\AbstractType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||||
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom form field type to select the timesheet mode.
|
||||||
|
*/
|
||||||
|
class TimesheetModeType extends AbstractType
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function configureOptions(OptionsResolver $resolver)
|
||||||
|
{
|
||||||
|
$resolver->setDefaults([
|
||||||
|
'label' => 'label.timesheet.mode',
|
||||||
|
'choices' => [
|
||||||
|
'label.timesheet.mode_default' => TimesheetConfiguration::MODE_DEFAULT,
|
||||||
|
'label.timesheet.mode_duration_only' => TimesheetConfiguration::MODE_DURATION_ONLY,
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getParent()
|
||||||
|
{
|
||||||
|
return ChoiceType::class;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,7 +17,7 @@ class AssetExtension extends BaseAssetExtension
|
|||||||
* Overwritten to support subdirectories and subdomains at the same time.
|
* Overwritten to support subdirectories and subdomains at the same time.
|
||||||
*
|
*
|
||||||
* @param string $path
|
* @param string $path
|
||||||
* @param null $packageName
|
* @param null|string $packageName
|
||||||
* @return mixed|string
|
* @return mixed|string
|
||||||
*/
|
*/
|
||||||
public function getAssetUrl($path, $packageName = null)
|
public function getAssetUrl($path, $packageName = null)
|
||||||
|
|||||||
42
src/Twig/TimesheetConfigExtension.php
Normal file
42
src/Twig/TimesheetConfigExtension.php
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Kimai time-tracking app.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Twig;
|
||||||
|
|
||||||
|
use App\Configuration\TimesheetConfiguration;
|
||||||
|
use Twig\Extension\AbstractExtension;
|
||||||
|
use Twig\TwigFunction;
|
||||||
|
|
||||||
|
class TimesheetConfigExtension extends AbstractExtension
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var TimesheetConfiguration
|
||||||
|
*/
|
||||||
|
protected $configuration;
|
||||||
|
|
||||||
|
public function __construct(TimesheetConfiguration $configuration)
|
||||||
|
{
|
||||||
|
$this->configuration = $configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return TwigFunction[]
|
||||||
|
*/
|
||||||
|
public function getFunctions()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
new TwigFunction('is_duration_only', [$this, 'isDurationOnly']),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isDurationOnly(): bool
|
||||||
|
{
|
||||||
|
return $this->configuration->isDurationOnly();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
{% if entries.count == 0 %}
|
{% if entries.count == 0 %}
|
||||||
{{ widgets.callout('warning', 'error.no_entries_found') }}
|
{{ widgets.callout('warning', 'error.no_entries_found') }}
|
||||||
{% else %}
|
{% else %}
|
||||||
|
{% set duration_only = is_duration_only() %}
|
||||||
{% set columns = {'date': ''} %}
|
{% set columns = {'date': ''} %}
|
||||||
|
|
||||||
{% if not duration_only %}
|
{% if not duration_only %}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
{% if entries.count == 0 %}
|
{% if entries.count == 0 %}
|
||||||
{{ widgets.callout('warning', 'error.no_entries_found') }}
|
{{ widgets.callout('warning', 'error.no_entries_found') }}
|
||||||
{% else %}
|
{% else %}
|
||||||
|
{% set duration_only = is_duration_only() %}
|
||||||
{% set canSeeRate = is_granted('view_rate_own_timesheet') %}
|
{% set canSeeRate = is_granted('view_rate_own_timesheet') %}
|
||||||
{% set columns = {'date': ''} %}
|
{% set columns = {'date': ''} %}
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ class SystemConfigurationTest extends TestCase
|
|||||||
'rules' => [
|
'rules' => [
|
||||||
'allow_future_times' => false,
|
'allow_future_times' => false,
|
||||||
],
|
],
|
||||||
'duration_only' => true,
|
'mode' => 'duration_only',
|
||||||
'markdown_content' => false,
|
'markdown_content' => false,
|
||||||
'active_entries' => [
|
'active_entries' => [
|
||||||
'hard_limit' => 99,
|
'hard_limit' => 99,
|
||||||
@@ -61,7 +61,7 @@ class SystemConfigurationTest extends TestCase
|
|||||||
(new Configuration())->setName('defaults.customer.timezone')->setValue('Russia/Moscov'),
|
(new Configuration())->setName('defaults.customer.timezone')->setValue('Russia/Moscov'),
|
||||||
(new Configuration())->setName('defaults.customer.currency')->setValue('RUB'),
|
(new Configuration())->setName('defaults.customer.currency')->setValue('RUB'),
|
||||||
(new Configuration())->setName('timesheet.rules.allow_future_times')->setValue('1'),
|
(new Configuration())->setName('timesheet.rules.allow_future_times')->setValue('1'),
|
||||||
(new Configuration())->setName('timesheet.duration_only')->setValue('0'),
|
(new Configuration())->setName('timesheet.mode')->setValue('default'),
|
||||||
(new Configuration())->setName('timesheet.markdown_content')->setValue('1'),
|
(new Configuration())->setName('timesheet.markdown_content')->setValue('1'),
|
||||||
(new Configuration())->setName('timesheet.active_entries.hard_limit')->setValue('7'),
|
(new Configuration())->setName('timesheet.active_entries.hard_limit')->setValue('7'),
|
||||||
(new Configuration())->setName('timesheet.active_entries.soft_limit')->setValue('3'),
|
(new Configuration())->setName('timesheet.active_entries.soft_limit')->setValue('3'),
|
||||||
@@ -95,9 +95,9 @@ class SystemConfigurationTest extends TestCase
|
|||||||
public function testDefaultWithMixedConfigs()
|
public function testDefaultWithMixedConfigs()
|
||||||
{
|
{
|
||||||
$sut = $this->getSut($this->getDefaultSettings(), [
|
$sut = $this->getSut($this->getDefaultSettings(), [
|
||||||
(new Configuration())->setName('timesheet.duration_only')->setValue(''),
|
(new Configuration())->setName('timesheet.rules.allow_future_times')->setValue(''),
|
||||||
]);
|
]);
|
||||||
$this->assertEquals(false, $sut->find('timesheet.duration_only'));
|
$this->assertEquals(false, $sut->find('timesheet.rules.allow_future_times'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ class TimesheetConfigurationTest extends TestCase
|
|||||||
'rules' => [
|
'rules' => [
|
||||||
'allow_future_times' => false,
|
'allow_future_times' => false,
|
||||||
],
|
],
|
||||||
'duration_only' => true,
|
'mode' => 'duration_only',
|
||||||
'markdown_content' => false,
|
'markdown_content' => false,
|
||||||
'active_entries' => [
|
'active_entries' => [
|
||||||
'hard_limit' => 99,
|
'hard_limit' => 99,
|
||||||
@@ -50,7 +50,7 @@ class TimesheetConfigurationTest extends TestCase
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
(new Configuration())->setName('timesheet.rules.allow_future_times')->setValue('1'),
|
(new Configuration())->setName('timesheet.rules.allow_future_times')->setValue('1'),
|
||||||
(new Configuration())->setName('timesheet.duration_only')->setValue('0'),
|
(new Configuration())->setName('timesheet.mode')->setValue('default'),
|
||||||
(new Configuration())->setName('timesheet.markdown_content')->setValue('1'),
|
(new Configuration())->setName('timesheet.markdown_content')->setValue('1'),
|
||||||
(new Configuration())->setName('timesheet.active_entries.hard_limit')->setValue('7'),
|
(new Configuration())->setName('timesheet.active_entries.hard_limit')->setValue('7'),
|
||||||
(new Configuration())->setName('timesheet.active_entries.soft_limit')->setValue('3'),
|
(new Configuration())->setName('timesheet.active_entries.soft_limit')->setValue('3'),
|
||||||
@@ -86,7 +86,7 @@ class TimesheetConfigurationTest extends TestCase
|
|||||||
public function testDefaultWithMixedConfigs()
|
public function testDefaultWithMixedConfigs()
|
||||||
{
|
{
|
||||||
$sut = $this->getSut($this->getDefaultSettings(), [
|
$sut = $this->getSut($this->getDefaultSettings(), [
|
||||||
(new Configuration())->setName('timesheet.duration_only')->setValue(''),
|
(new Configuration())->setName('timesheet.mode')->setValue('sdf'),
|
||||||
]);
|
]);
|
||||||
$this->assertEquals(false, $sut->isDurationOnly());
|
$this->assertEquals(false, $sut->isDurationOnly());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ class SystemConfigurationControllerTest extends ControllerBaseTest
|
|||||||
|
|
||||||
$configService = $client->getContainer()->get(SystemConfiguration::class);
|
$configService = $client->getContainer()->get(SystemConfiguration::class);
|
||||||
$this->assertEquals(false, $configService->find('timesheet.markdown_content'));
|
$this->assertEquals(false, $configService->find('timesheet.markdown_content'));
|
||||||
$this->assertEquals(false, $configService->find('timesheet.duration_only'));
|
$this->assertEquals('default', $configService->find('timesheet.mode'));
|
||||||
$this->assertEquals(true, $configService->find('timesheet.rules.allow_future_times'));
|
$this->assertEquals(true, $configService->find('timesheet.rules.allow_future_times'));
|
||||||
$this->assertEquals(3, $configService->find('timesheet.active_entries.hard_limit'));
|
$this->assertEquals(3, $configService->find('timesheet.active_entries.hard_limit'));
|
||||||
$this->assertEquals(1, $configService->find('timesheet.active_entries.soft_limit'));
|
$this->assertEquals(1, $configService->find('timesheet.active_entries.soft_limit'));
|
||||||
@@ -70,8 +70,8 @@ class SystemConfigurationControllerTest extends ControllerBaseTest
|
|||||||
$client->submit($form, [
|
$client->submit($form, [
|
||||||
'system_configuration_form' => [
|
'system_configuration_form' => [
|
||||||
'configuration' => [
|
'configuration' => [
|
||||||
|
['name' => 'timesheet.mode', 'value' => 'duration_only'],
|
||||||
['name' => 'timesheet.markdown_content', 'value' => 1],
|
['name' => 'timesheet.markdown_content', 'value' => 1],
|
||||||
['name' => 'timesheet.duration_only', 'value' => 1],
|
|
||||||
['name' => 'timesheet.rules.allow_future_times', 'value' => false],
|
['name' => 'timesheet.rules.allow_future_times', 'value' => false],
|
||||||
['name' => 'timesheet.active_entries.hard_limit', 'value' => 99],
|
['name' => 'timesheet.active_entries.hard_limit', 'value' => 99],
|
||||||
['name' => 'timesheet.active_entries.soft_limit', 'value' => 77],
|
['name' => 'timesheet.active_entries.soft_limit', 'value' => 77],
|
||||||
@@ -86,7 +86,7 @@ class SystemConfigurationControllerTest extends ControllerBaseTest
|
|||||||
|
|
||||||
$configService = $client->getContainer()->get(SystemConfiguration::class);
|
$configService = $client->getContainer()->get(SystemConfiguration::class);
|
||||||
$this->assertEquals(true, $configService->find('timesheet.markdown_content'));
|
$this->assertEquals(true, $configService->find('timesheet.markdown_content'));
|
||||||
$this->assertEquals(true, $configService->find('timesheet.duration_only'));
|
$this->assertEquals('duration_only', $configService->find('timesheet.mode'));
|
||||||
$this->assertEquals(false, $configService->find('timesheet.rules.allow_future_times'));
|
$this->assertEquals(false, $configService->find('timesheet.rules.allow_future_times'));
|
||||||
$this->assertEquals(99, $configService->find('timesheet.active_entries.hard_limit'));
|
$this->assertEquals(99, $configService->find('timesheet.active_entries.hard_limit'));
|
||||||
$this->assertEquals(77, $configService->find('timesheet.active_entries.soft_limit'));
|
$this->assertEquals(77, $configService->find('timesheet.active_entries.soft_limit'));
|
||||||
@@ -101,8 +101,8 @@ class SystemConfigurationControllerTest extends ControllerBaseTest
|
|||||||
[
|
[
|
||||||
'system_configuration_form' => [
|
'system_configuration_form' => [
|
||||||
'configuration' => [
|
'configuration' => [
|
||||||
|
['name' => 'timesheet.mode', 'value' => 'foo'],
|
||||||
['name' => 'timesheet.markdown_content', 'value' => 1],
|
['name' => 'timesheet.markdown_content', 'value' => 1],
|
||||||
['name' => 'timesheet.duration_only', 'value' => 1],
|
|
||||||
['name' => 'timesheet.rules.allow_future_times', 'value' => 1],
|
['name' => 'timesheet.rules.allow_future_times', 'value' => 1],
|
||||||
['name' => 'timesheet.active_entries.hard_limit', 'value' => -1],
|
['name' => 'timesheet.active_entries.hard_limit', 'value' => -1],
|
||||||
['name' => 'timesheet.active_entries.soft_limit', 'value' => -1],
|
['name' => 'timesheet.active_entries.soft_limit', 'value' => -1],
|
||||||
@@ -110,10 +110,11 @@ class SystemConfigurationControllerTest extends ControllerBaseTest
|
|||||||
]
|
]
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'#system_configuration_form_configuration_3_value',
|
'#system_configuration_form_configuration_0_value', // mode
|
||||||
'#system_configuration_form_configuration_4_value',
|
'#system_configuration_form_configuration_3_value', // hard_limit
|
||||||
|
'#system_configuration_form_configuration_4_value', // soft_limit
|
||||||
],
|
],
|
||||||
false
|
true
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
47
tests/Twig/TimesheetConfigExtensionTest.php
Normal file
47
tests/Twig/TimesheetConfigExtensionTest.php
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Kimai time-tracking app.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Tests\Twig;
|
||||||
|
|
||||||
|
use App\Configuration\ConfigLoaderInterface;
|
||||||
|
use App\Configuration\TimesheetConfiguration;
|
||||||
|
use App\Twig\TimesheetConfigExtension;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \App\Twig\TimesheetConfigExtension
|
||||||
|
*/
|
||||||
|
class TimesheetConfigExtensionTest extends TestCase
|
||||||
|
{
|
||||||
|
public function testGetFunctions()
|
||||||
|
{
|
||||||
|
$loader = $this->getMockBuilder(ConfigLoaderInterface::class)->getMock();
|
||||||
|
$config = new TimesheetConfiguration($loader, ['mode' => 'duration_only']);
|
||||||
|
$sut = new TimesheetConfigExtension($config);
|
||||||
|
$filters = $sut->getFunctions();
|
||||||
|
$this->assertCount(1, $filters);
|
||||||
|
$this->assertEquals('is_duration_only', $filters[0]->getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIsDurationOnly()
|
||||||
|
{
|
||||||
|
$loader = $this->getMockBuilder(ConfigLoaderInterface::class)->getMock();
|
||||||
|
$config = new TimesheetConfiguration($loader, ['mode' => 'duration_only']);
|
||||||
|
$sut = new TimesheetConfigExtension($config);
|
||||||
|
$this->assertTrue($sut->isDurationOnly());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIsNotDurationOnly()
|
||||||
|
{
|
||||||
|
$loader = $this->getMockBuilder(ConfigLoaderInterface::class)->getMock();
|
||||||
|
$config = new TimesheetConfiguration($loader, ['mode' => 'default']);
|
||||||
|
$sut = new TimesheetConfigExtension($config);
|
||||||
|
$this->assertFalse($sut->isDurationOnly());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -36,7 +36,7 @@ class TimesheetValidatorTest extends ConstraintValidatorTestCase
|
|||||||
'rules' => [
|
'rules' => [
|
||||||
'allow_future_times' => false,
|
'allow_future_times' => false,
|
||||||
],
|
],
|
||||||
'duration_only' => false,
|
'mode' => 'default',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return new TimesheetValidator($authMock, $config);
|
return new TimesheetValidator($authMock, $config);
|
||||||
|
|||||||
@@ -22,9 +22,17 @@
|
|||||||
<source>label.timesheet.markdown_content</source>
|
<source>label.timesheet.markdown_content</source>
|
||||||
<target>Erlaube Markdown in den Beschreibungen der erfassten Zeiten</target>
|
<target>Erlaube Markdown in den Beschreibungen der erfassten Zeiten</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="label.timesheet.duration_only">
|
<trans-unit id="label.timesheet.mode">
|
||||||
<source>label.timesheet.duration_only</source>
|
<source>label.timesheet.mode</source>
|
||||||
<target>"Duration only" Modus - ersetzt das Enddatum durch ein Eingabefeld für Zeitdauer</target>
|
<target>Zeiterfassungs Modus</target>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="label.timesheet.mode_default">
|
||||||
|
<source>label.timesheet.mode_default</source>
|
||||||
|
<target>Standard Modus: erfasst Start und Enddatum</target>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="label.timesheet.mode_duration_only">
|
||||||
|
<source>label.timesheet.mode_duration_only</source>
|
||||||
|
<target>Dauer: ersetzt das Enddatum durch ein Eingabefeld für Dauer</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="label.timesheet.rules.allow_future_times">
|
<trans-unit id="label.timesheet.rules.allow_future_times">
|
||||||
<source>label.timesheet.rules.allow_future_times</source>
|
<source>label.timesheet.rules.allow_future_times</source>
|
||||||
|
|||||||
@@ -22,9 +22,17 @@
|
|||||||
<source>label.timesheet.markdown_content</source>
|
<source>label.timesheet.markdown_content</source>
|
||||||
<target>Allow Markdown in the timesheet descriptions</target>
|
<target>Allow Markdown in the timesheet descriptions</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="label.timesheet.duration_only">
|
<trans-unit id="label.timesheet.mode">
|
||||||
<source>label.timesheet.duration_only</source>
|
<source>label.timesheet.mode</source>
|
||||||
<target>"Duration only" mode - replaces the endtime field with an input for duration</target>
|
<target>Timetracking mode</target>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="label.timesheet.mode_default">
|
||||||
|
<source>label.timesheet.mode_default</source>
|
||||||
|
<target>Default: accept start and end date</target>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="label.timesheet.mode_duration_only">
|
||||||
|
<source>label.timesheet.mode_duration_only</source>
|
||||||
|
<target>Duration only: replaces the end date field with an input for duration</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="label.timesheet.rules.allow_future_times">
|
<trans-unit id="label.timesheet.rules.allow_future_times">
|
||||||
<source>label.timesheet.rules.allow_future_times</source>
|
<source>label.timesheet.rules.allow_future_times</source>
|
||||||
|
|||||||
@@ -22,8 +22,8 @@
|
|||||||
<source>label.timesheet.markdown_content</source>
|
<source>label.timesheet.markdown_content</source>
|
||||||
<target>Markdown használatának engedélyezése a rögzítések leírásában</target>
|
<target>Markdown használatának engedélyezése a rögzítések leírásában</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="label.timesheet.duration_only">
|
<trans-unit id="label.timesheet.mode_duration_only">
|
||||||
<source>label.timesheet.duration_only</source>
|
<source>label.timesheet.mode_duration_only</source>
|
||||||
<target>"Csak időtartam" mód - a befejezés mezőt kicseréli időtartamra</target>
|
<target>"Csak időtartam" mód - a befejezés mezőt kicseréli időtartamra</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="label.timesheet.rules.allow_future_times">
|
<trans-unit id="label.timesheet.rules.allow_future_times">
|
||||||
|
|||||||
Reference in New Issue
Block a user