diff --git a/.scrutinizer.yml b/.scrutinizer.yml index fa1c158d..2b3c7882 100644 --- a/.scrutinizer.yml +++ b/.scrutinizer.yml @@ -42,5 +42,5 @@ filter: build_failure_conditions: - '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)' \ No newline at end of file diff --git a/UPGRADING.md b/UPGRADING.md index cdd02669..ed902d09 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -26,13 +26,13 @@ Remember to execute the necessary timezone conversion script, if you haven't upd ### 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)** - 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. -- 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: 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 (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 ### 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 - `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) A bug fixing release. Remember to execute the necessary timezone conversion script, if you haven't updated to 0.8 before (see below)! diff --git a/config/packages/kimai.yaml b/config/packages/kimai.yaml index 26b1b1a1..74f039ef 100644 --- a/config/packages/kimai.yaml +++ b/config/packages/kimai.yaml @@ -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: # -------------------------------------------------------------------------------- - # Settings for the user management and login forms - user: - registration: true - password_reset: true + # You can disable the user management functions in the authentication screens (default: true). + #user: + # registration: false + # password_reset: false + # -------------------------------------------------------------------------------- + # -------------------------------------------------------------------------------- # All configs related to timesheet and record management @@ -13,9 +23,11 @@ kimai: # render timesheet descriptions with markdown markdown_content: false - # Whether we display start and end time columns (false) or durations only (true). - # Setting this to true will also change the "edit timesheet" forms, more infos available in the configurations docu. - duration_only: false + # The time-tracking mode that should be used (allowed values: default, duration_only) + # + # 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. # 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 allow_future_times: true + # -------------------------------------------------------------------------------- # Invoice management #invoice: @@ -60,6 +73,7 @@ kimai: # - 'var/invoices/' # - 'templates/invoice/renderer/' + # -------------------------------------------------------------------------------- # Default settings used to populate forms #defaults: diff --git a/src/Configuration/TimesheetConfiguration.php b/src/Configuration/TimesheetConfiguration.php index ec037fe9..62e004bb 100644 --- a/src/Configuration/TimesheetConfiguration.php +++ b/src/Configuration/TimesheetConfiguration.php @@ -11,6 +11,9 @@ namespace App\Configuration; class TimesheetConfiguration implements SystemBundleConfiguration { + public const MODE_DURATION_ONLY = 'duration_only'; + public const MODE_DEFAULT = 'default'; + use StringAccessibleConfigTrait; public function getPrefix(): string @@ -25,7 +28,7 @@ class TimesheetConfiguration implements SystemBundleConfiguration public function isDurationOnly(): bool { - return (bool) $this->find('duration_only'); + return $this->find('mode') === self::MODE_DURATION_ONLY; } public function isMarkdownEnabled(): bool diff --git a/src/Controller/AbstractController.php b/src/Controller/AbstractController.php index 51f53e6d..cafc98c4 100644 --- a/src/Controller/AbstractController.php +++ b/src/Controller/AbstractController.php @@ -9,13 +9,15 @@ namespace App\Controller; -use Symfony\Bundle\FrameworkBundle\Controller\Controller; +use Symfony\Bundle\FrameworkBundle\Controller\AbstractController as BaseAbstractController; use Symfony\Component\Translation\DataCollectorTranslator; +use Symfony\Contracts\Service\ServiceSubscriberInterface; +use Symfony\Contracts\Translation\TranslatorInterface; /** * The abstract base controller. */ -abstract class AbstractController extends Controller +abstract class AbstractController extends BaseAbstractController implements ServiceSubscriberInterface { public const FLASH_SUCCESS = 'success'; public const FLASH_WARNING = 'warning'; @@ -89,4 +91,11 @@ abstract class AbstractController extends Controller $this->addFlash($type, $message); } + + public static function getSubscribedServices() + { + return array_merge(parent::getSubscribedServices(), [ + 'translator' => TranslatorInterface::class + ]); + } } diff --git a/src/Controller/SystemConfigurationController.php b/src/Controller/SystemConfigurationController.php index ee80b88c..a10cea06 100644 --- a/src/Controller/SystemConfigurationController.php +++ b/src/Controller/SystemConfigurationController.php @@ -14,6 +14,7 @@ use App\Event\SystemConfigurationEvent; use App\Form\Model\Configuration; use App\Form\Model\SystemConfiguration as SystemConfigurationModel; use App\Form\SystemConfigurationForm; +use App\Form\Type\TimesheetModeType; use App\Repository\ConfigurationRepository; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Symfony\Component\EventDispatcher\EventDispatcherInterface; @@ -199,11 +200,11 @@ class SystemConfigurationController extends AbstractController ->setSection(SystemConfigurationModel::SECTION_TIMESHEET) ->setConfiguration([ (new Configuration()) - ->setName('timesheet.markdown_content') - ->setType(CheckboxType::class) + ->setName('timesheet.mode') + ->setType(TimesheetModeType::class) ->setTranslationDomain('system-configuration'), (new Configuration()) - ->setName('timesheet.duration_only') + ->setName('timesheet.markdown_content') ->setType(CheckboxType::class) ->setTranslationDomain('system-configuration'), (new Configuration()) diff --git a/src/Controller/TimesheetController.php b/src/Controller/TimesheetController.php index da276d79..20ff6151 100644 --- a/src/Controller/TimesheetController.php +++ b/src/Controller/TimesheetController.php @@ -69,7 +69,6 @@ class TimesheetController extends AbstractController 'showFilter' => $form->isSubmitted(), 'toolbarForm' => $form->createView(), 'showSummary' => $this->getUser()->getPreferenceValue('timesheet.daily_stats', false), - 'duration_only' => $this->configuration->isDurationOnly(), ]); } diff --git a/src/Controller/TimesheetTeamController.php b/src/Controller/TimesheetTeamController.php index c5ffed79..a141f8c1 100644 --- a/src/Controller/TimesheetTeamController.php +++ b/src/Controller/TimesheetTeamController.php @@ -65,7 +65,6 @@ class TimesheetTeamController extends AbstractController 'query' => $query, 'showFilter' => $form->isSubmitted(), 'toolbarForm' => $form->createView(), - 'duration_only' => $this->configuration->isDurationOnly(), ]); } diff --git a/src/DataFixtures/CustomerFixtures.php b/src/DataFixtures/CustomerFixtures.php index faa126cd..05c7297d 100644 --- a/src/DataFixtures/CustomerFixtures.php +++ b/src/DataFixtures/CustomerFixtures.php @@ -33,7 +33,7 @@ class CustomerFixtures extends Fixture public const MIN_BUDGET = 0; public const MAX_BUDGET = 100000; 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 MAX_PROJECTS_PER_CUSTOMER = 25; 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); for ($c = 1; $c <= $amountGlobalActivities; $c++) { - $visibleActivity = 0 != $a % 3; + $visibleActivity = 0 != $c % 4; $activity = $this->createActivity($faker, null, $visibleActivity); $manager->persist($activity); } diff --git a/src/DependencyInjection/AppExtension.php b/src/DependencyInjection/AppExtension.php index a072b94f..2dd35149 100644 --- a/src/DependencyInjection/AppExtension.php +++ b/src/DependencyInjection/AppExtension.php @@ -32,6 +32,14 @@ class AppExtension extends Extension $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% $container->setParameter('kimai.data_dir', $config['data_dir']); $container->setParameter('kimai.plugin_dir', $config['plugin_dir']); diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index f48cdc29..166d0fe5 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -75,6 +75,16 @@ class Configuration implements ConfigurationInterface ->children() ->booleanNode('duration_only') ->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() ->booleanNode('markdown_content') ->defaultValue(false) diff --git a/src/Form/Type/TimesheetModeType.php b/src/Form/Type/TimesheetModeType.php new file mode 100644 index 00000000..e254e6ce --- /dev/null +++ b/src/Form/Type/TimesheetModeType.php @@ -0,0 +1,43 @@ +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; + } +} diff --git a/src/Twig/AssetExtension.php b/src/Twig/AssetExtension.php index f0f28ad2..1b551677 100644 --- a/src/Twig/AssetExtension.php +++ b/src/Twig/AssetExtension.php @@ -17,7 +17,7 @@ class AssetExtension extends BaseAssetExtension * Overwritten to support subdirectories and subdomains at the same time. * * @param string $path - * @param null $packageName + * @param null|string $packageName * @return mixed|string */ public function getAssetUrl($path, $packageName = null) diff --git a/src/Twig/TimesheetConfigExtension.php b/src/Twig/TimesheetConfigExtension.php new file mode 100644 index 00000000..c7f88ec0 --- /dev/null +++ b/src/Twig/TimesheetConfigExtension.php @@ -0,0 +1,42 @@ +configuration = $configuration; + } + + /** + * @return TwigFunction[] + */ + public function getFunctions() + { + return [ + new TwigFunction('is_duration_only', [$this, 'isDurationOnly']), + ]; + } + + public function isDurationOnly(): bool + { + return $this->configuration->isDurationOnly(); + } +} diff --git a/templates/timesheet-team/index.html.twig b/templates/timesheet-team/index.html.twig index 14684767..246ca62b 100644 --- a/templates/timesheet-team/index.html.twig +++ b/templates/timesheet-team/index.html.twig @@ -17,6 +17,7 @@ {% if entries.count == 0 %} {{ widgets.callout('warning', 'error.no_entries_found') }} {% else %} + {% set duration_only = is_duration_only() %} {% set columns = {'date': ''} %} {% if not duration_only %} diff --git a/templates/timesheet/index.html.twig b/templates/timesheet/index.html.twig index 69c720e5..8907a908 100644 --- a/templates/timesheet/index.html.twig +++ b/templates/timesheet/index.html.twig @@ -17,6 +17,7 @@ {% if entries.count == 0 %} {{ widgets.callout('warning', 'error.no_entries_found') }} {% else %} + {% set duration_only = is_duration_only() %} {% set canSeeRate = is_granted('view_rate_own_timesheet') %} {% set columns = {'date': ''} %} diff --git a/tests/Configuration/SystemConfigurationTest.php b/tests/Configuration/SystemConfigurationTest.php index e500f7ef..35dd5bad 100644 --- a/tests/Configuration/SystemConfigurationTest.php +++ b/tests/Configuration/SystemConfigurationTest.php @@ -38,7 +38,7 @@ class SystemConfigurationTest extends TestCase 'rules' => [ 'allow_future_times' => false, ], - 'duration_only' => true, + 'mode' => 'duration_only', 'markdown_content' => false, 'active_entries' => [ '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.currency')->setValue('RUB'), (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.active_entries.hard_limit')->setValue('7'), (new Configuration())->setName('timesheet.active_entries.soft_limit')->setValue('3'), @@ -95,9 +95,9 @@ class SystemConfigurationTest extends TestCase public function testDefaultWithMixedConfigs() { $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')); } /** diff --git a/tests/Configuration/TimesheetConfigurationTest.php b/tests/Configuration/TimesheetConfigurationTest.php index 5612f611..3179fcbc 100644 --- a/tests/Configuration/TimesheetConfigurationTest.php +++ b/tests/Configuration/TimesheetConfigurationTest.php @@ -37,7 +37,7 @@ class TimesheetConfigurationTest extends TestCase 'rules' => [ 'allow_future_times' => false, ], - 'duration_only' => true, + 'mode' => 'duration_only', 'markdown_content' => false, 'active_entries' => [ 'hard_limit' => 99, @@ -50,7 +50,7 @@ class TimesheetConfigurationTest extends TestCase { return [ (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.active_entries.hard_limit')->setValue('7'), (new Configuration())->setName('timesheet.active_entries.soft_limit')->setValue('3'), @@ -86,7 +86,7 @@ class TimesheetConfigurationTest extends TestCase public function testDefaultWithMixedConfigs() { $sut = $this->getSut($this->getDefaultSettings(), [ - (new Configuration())->setName('timesheet.duration_only')->setValue(''), + (new Configuration())->setName('timesheet.mode')->setValue('sdf'), ]); $this->assertEquals(false, $sut->isDurationOnly()); } diff --git a/tests/Controller/SystemConfigurationControllerTest.php b/tests/Controller/SystemConfigurationControllerTest.php index e9ba9e25..79108723 100644 --- a/tests/Controller/SystemConfigurationControllerTest.php +++ b/tests/Controller/SystemConfigurationControllerTest.php @@ -61,7 +61,7 @@ class SystemConfigurationControllerTest extends ControllerBaseTest $configService = $client->getContainer()->get(SystemConfiguration::class); $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(3, $configService->find('timesheet.active_entries.hard_limit')); $this->assertEquals(1, $configService->find('timesheet.active_entries.soft_limit')); @@ -70,8 +70,8 @@ class SystemConfigurationControllerTest extends ControllerBaseTest $client->submit($form, [ 'system_configuration_form' => [ 'configuration' => [ + ['name' => 'timesheet.mode', 'value' => 'duration_only'], ['name' => 'timesheet.markdown_content', 'value' => 1], - ['name' => 'timesheet.duration_only', 'value' => 1], ['name' => 'timesheet.rules.allow_future_times', 'value' => false], ['name' => 'timesheet.active_entries.hard_limit', 'value' => 99], ['name' => 'timesheet.active_entries.soft_limit', 'value' => 77], @@ -86,7 +86,7 @@ class SystemConfigurationControllerTest extends ControllerBaseTest $configService = $client->getContainer()->get(SystemConfiguration::class); $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(99, $configService->find('timesheet.active_entries.hard_limit')); $this->assertEquals(77, $configService->find('timesheet.active_entries.soft_limit')); @@ -101,8 +101,8 @@ class SystemConfigurationControllerTest extends ControllerBaseTest [ 'system_configuration_form' => [ 'configuration' => [ + ['name' => 'timesheet.mode', 'value' => 'foo'], ['name' => 'timesheet.markdown_content', 'value' => 1], - ['name' => 'timesheet.duration_only', 'value' => 1], ['name' => 'timesheet.rules.allow_future_times', 'value' => 1], ['name' => 'timesheet.active_entries.hard_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_4_value', + '#system_configuration_form_configuration_0_value', // mode + '#system_configuration_form_configuration_3_value', // hard_limit + '#system_configuration_form_configuration_4_value', // soft_limit ], - false + true ); } diff --git a/tests/Twig/TimesheetConfigExtensionTest.php b/tests/Twig/TimesheetConfigExtensionTest.php new file mode 100644 index 00000000..158c5158 --- /dev/null +++ b/tests/Twig/TimesheetConfigExtensionTest.php @@ -0,0 +1,47 @@ +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()); + } +} diff --git a/tests/Validator/Constraints/TimesheetValidatorTest.php b/tests/Validator/Constraints/TimesheetValidatorTest.php index 8d498d0d..c51a6fff 100644 --- a/tests/Validator/Constraints/TimesheetValidatorTest.php +++ b/tests/Validator/Constraints/TimesheetValidatorTest.php @@ -36,7 +36,7 @@ class TimesheetValidatorTest extends ConstraintValidatorTestCase 'rules' => [ 'allow_future_times' => false, ], - 'duration_only' => false, + 'mode' => 'default', ]); return new TimesheetValidator($authMock, $config); diff --git a/translations/system-configuration.de.xliff b/translations/system-configuration.de.xliff index e8624e88..f841ab96 100644 --- a/translations/system-configuration.de.xliff +++ b/translations/system-configuration.de.xliff @@ -22,9 +22,17 @@ label.timesheet.markdown_content Erlaube Markdown in den Beschreibungen der erfassten Zeiten - - label.timesheet.duration_only - "Duration only" Modus - ersetzt das Enddatum durch ein Eingabefeld für Zeitdauer + + label.timesheet.mode + Zeiterfassungs Modus + + + label.timesheet.mode_default + Standard Modus: erfasst Start und Enddatum + + + label.timesheet.mode_duration_only + Dauer: ersetzt das Enddatum durch ein Eingabefeld für Dauer label.timesheet.rules.allow_future_times diff --git a/translations/system-configuration.en.xliff b/translations/system-configuration.en.xliff index 30d952a4..34be2643 100644 --- a/translations/system-configuration.en.xliff +++ b/translations/system-configuration.en.xliff @@ -22,9 +22,17 @@ label.timesheet.markdown_content Allow Markdown in the timesheet descriptions - - label.timesheet.duration_only - "Duration only" mode - replaces the endtime field with an input for duration + + label.timesheet.mode + Timetracking mode + + + label.timesheet.mode_default + Default: accept start and end date + + + label.timesheet.mode_duration_only + Duration only: replaces the end date field with an input for duration label.timesheet.rules.allow_future_times diff --git a/translations/system-configuration.hu.xliff b/translations/system-configuration.hu.xliff index 6ebbb94b..35d31657 100644 --- a/translations/system-configuration.hu.xliff +++ b/translations/system-configuration.hu.xliff @@ -22,8 +22,8 @@ label.timesheet.markdown_content Markdown használatának engedélyezése a rögzítések leírásában - - label.timesheet.duration_only + + label.timesheet.mode_duration_only "Csak időtartam" mód - a befejezés mezőt kicseréli időtartamra