diff --git a/src/Controller/SystemConfigurationController.php b/src/Controller/SystemConfigurationController.php
index af015f4a..f07a26fd 100644
--- a/src/Controller/SystemConfigurationController.php
+++ b/src/Controller/SystemConfigurationController.php
@@ -14,12 +14,15 @@ use App\Event\SystemConfigurationEvent;
use App\Form\Model\Configuration;
use App\Form\Model\SystemConfiguration as SystemConfigurationModel;
use App\Form\SystemConfigurationForm;
+use App\Form\Type\ActivityTypePatternType;
use App\Form\Type\ArrayToCommaStringType;
+use App\Form\Type\CustomerTypePatternType;
use App\Form\Type\DatePickerType;
use App\Form\Type\DateTimeTextType;
use App\Form\Type\DayTimeType;
use App\Form\Type\LanguageType;
use App\Form\Type\MinuteIncrementType;
+use App\Form\Type\ProjectTypePatternType;
use App\Form\Type\RoundingModeType;
use App\Form\Type\SkinType;
use App\Form\Type\TimezoneType;
@@ -496,6 +499,24 @@ final class SystemConfigurationController extends AbstractController
->setLabel('currency')
->setType(CurrencyType::class)
->setOptions(['help' => 'default_value_new']),
+ (new Configuration())
+ ->setName('customer.choice_pattern')
+ ->setLabel('choice_pattern')
+ ->setType(CustomerTypePatternType::class),
+ ]),
+ (new SystemConfigurationModel('project'))
+ ->setConfiguration([
+ (new Configuration())
+ ->setName('project.choice_pattern')
+ ->setLabel('choice_pattern')
+ ->setType(ProjectTypePatternType::class),
+ ]),
+ (new SystemConfigurationModel('activity'))
+ ->setConfiguration([
+ (new Configuration())
+ ->setName('activity.choice_pattern')
+ ->setLabel('choice_pattern')
+ ->setType(ActivityTypePatternType::class),
]),
(new SystemConfigurationModel('user'))
->setConfiguration([
diff --git a/src/EventSubscriber/Actions/ActivitiesSubscriber.php b/src/EventSubscriber/Actions/ActivitiesSubscriber.php
index 7a0f0236..ca0a29ae 100644
--- a/src/EventSubscriber/Actions/ActivitiesSubscriber.php
+++ b/src/EventSubscriber/Actions/ActivitiesSubscriber.php
@@ -34,6 +34,10 @@ class ActivitiesSubscriber extends AbstractActionsSubscriber
$event->addCreate($this->path('admin_activity_create'));
}
+ if ($this->isGranted('system_configuration')) {
+ $event->addAction('settings', ['url' => $this->path('system_configuration_section', ['section' => 'activity']), 'class' => 'modal-ajax-form']);
+ }
+
$event->addHelp($this->documentationLink('activity.html'));
}
}
diff --git a/src/EventSubscriber/Actions/CustomersSubscriber.php b/src/EventSubscriber/Actions/CustomersSubscriber.php
index 8c3dace9..dd0c2bc5 100644
--- a/src/EventSubscriber/Actions/CustomersSubscriber.php
+++ b/src/EventSubscriber/Actions/CustomersSubscriber.php
@@ -34,6 +34,10 @@ class CustomersSubscriber extends AbstractActionsSubscriber
$event->addCreate($this->path('admin_customer_create'));
}
+ if ($this->isGranted('system_configuration')) {
+ $event->addAction('settings', ['url' => $this->path('system_configuration_section', ['section' => 'customer']), 'class' => 'modal-ajax-form']);
+ }
+
$event->addHelp($this->documentationLink('customer.html'));
}
}
diff --git a/src/EventSubscriber/Actions/ProjectsSubscriber.php b/src/EventSubscriber/Actions/ProjectsSubscriber.php
index d756cdc7..208f6088 100644
--- a/src/EventSubscriber/Actions/ProjectsSubscriber.php
+++ b/src/EventSubscriber/Actions/ProjectsSubscriber.php
@@ -35,6 +35,10 @@ class ProjectsSubscriber extends AbstractActionsSubscriber
$event->addCreate($this->path('admin_project_create'));
}
+ if ($this->isGranted('system_configuration')) {
+ $event->addAction('settings', ['url' => $this->path('system_configuration_section', ['section' => 'project']), 'class' => 'modal-ajax-form']);
+ }
+
$event->addHelp($this->documentationLink('project.html'));
}
}
diff --git a/src/Form/Type/ActivityType.php b/src/Form/Type/ActivityType.php
index 2c041a6c..df4838a3 100644
--- a/src/Form/Type/ActivityType.php
+++ b/src/Form/Type/ActivityType.php
@@ -9,6 +9,7 @@
namespace App\Form\Type;
+use App\Configuration\SystemConfiguration;
use App\Entity\Activity;
use App\Repository\ActivityRepository;
use App\Repository\Query\ActivityFormTypeQuery;
@@ -22,6 +23,44 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
*/
class ActivityType extends AbstractType
{
+ public const PATTERN_NAME = '{name}';
+ public const PATTERN_COMMENT = '{comment}';
+ public const PATTERN_SPACER = '{spacer}';
+ public const SPACER = ' - ';
+
+ private $configuration;
+ private $pattern;
+
+ public function __construct(SystemConfiguration $configuration)
+ {
+ $this->configuration = $configuration;
+ }
+
+ public function getChoiceLabel(Activity $activity): string
+ {
+ if ($this->pattern === null) {
+ $this->pattern = $this->configuration->find('activity.choice_pattern');
+
+ if ($this->pattern === null || stripos($this->pattern, '{') === false || stripos($this->pattern, '}') === false) {
+ $this->pattern = self::PATTERN_NAME;
+ }
+ }
+
+ $name = $this->pattern;
+ $name = str_replace(self::PATTERN_NAME, $activity->getName(), $name);
+ $name = str_replace(self::PATTERN_COMMENT, $activity->getComment(), $name);
+ $name = str_replace(self::PATTERN_SPACER, self::SPACER, $name);
+
+ $name = ltrim($name, self::SPACER);
+ $name = rtrim($name, self::SPACER);
+
+ if ($name === '' || $name === self::SPACER) {
+ $name = $activity->getName();
+ }
+
+ return $name;
+ }
+
/**
* {@inheritdoc}
*/
@@ -35,32 +74,18 @@ class ActivityType extends AbstractType
}
/**
- * {@inheritdoc}
- */
- public function choiceLabel(Activity $activity)
- {
- return $activity->getName();
- }
-
- /**
- * @param Activity $choiceValue
+ * @param Activity $activity
* @param string $key
* @param mixed $value
* @return array
*/
- public function choiceAttr($choiceValue, $key, $value)
+ public function getChoiceAttributes(Activity $activity, $key, $value)
{
- $project = null;
-
- if (!($choiceValue instanceof Activity)) {
- return [];
+ if (null !== ($project = $activity->getProject())) {
+ return ['data-project' => $project->getId(), 'data-currency' => $project->getCustomer()->getCurrency()];
}
- if (null !== $choiceValue->getProject()) {
- $project = $choiceValue->getProject()->getId();
- }
-
- return ['data-project' => $project];
+ return [];
}
/**
@@ -76,9 +101,9 @@ class ActivityType extends AbstractType
],
'label' => 'label.activity',
'class' => Activity::class,
- 'choice_label' => [$this, 'choiceLabel'],
+ 'choice_label' => [$this, 'getChoiceLabel'],
+ 'choice_attr' => [$this, 'getChoiceAttributes'],
'group_by' => [$this, 'groupBy'],
- 'choice_attr' => [$this, 'choiceAttr'],
'query_builder_for_user' => true,
// @var Project|Project[]|int|int[]|null
'projects' => null,
diff --git a/src/Form/Type/ActivityTypePatternType.php b/src/Form/Type/ActivityTypePatternType.php
new file mode 100644
index 00000000..c5ad1fad
--- /dev/null
+++ b/src/Form/Type/ActivityTypePatternType.php
@@ -0,0 +1,55 @@
+translator = $translator;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function configureOptions(OptionsResolver $resolver)
+ {
+ $name = $this->translator->trans('label.name');
+ $comment = $this->translator->trans('label.description');
+ $spacer = ActivityType::SPACER;
+
+ $resolver->setDefaults([
+ 'label' => 'label.choice_pattern',
+ 'choices' => [
+ $name => ActivityType::PATTERN_NAME,
+ $comment => ActivityType::PATTERN_COMMENT,
+ $name . $spacer . $comment => ActivityType::PATTERN_NAME . ActivityType::PATTERN_SPACER . ActivityType::PATTERN_COMMENT,
+ ]
+ ]);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getParent()
+ {
+ return ChoiceType::class;
+ }
+}
diff --git a/src/Form/Type/CustomerType.php b/src/Form/Type/CustomerType.php
index 713687e9..cfeaa594 100644
--- a/src/Form/Type/CustomerType.php
+++ b/src/Form/Type/CustomerType.php
@@ -9,6 +9,7 @@
namespace App\Form\Type;
+use App\Configuration\SystemConfiguration;
use App\Entity\Customer;
use App\Repository\CustomerRepository;
use App\Repository\Query\CustomerFormTypeQuery;
@@ -23,6 +24,53 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
*/
class CustomerType extends AbstractType
{
+ public const PATTERN_NAME = '{name}';
+ public const PATTERN_NUMBER = '{number}';
+ public const PATTERN_COMPANY = '{company}';
+ public const PATTERN_COMMENT = '{comment}';
+ public const PATTERN_SPACER = '{spacer}';
+ public const SPACER = ' - ';
+
+ private $configuration;
+ private $pattern;
+
+ public function __construct(SystemConfiguration $configuration)
+ {
+ $this->configuration = $configuration;
+ }
+
+ public function getChoiceLabel(Customer $customer): string
+ {
+ if ($this->pattern === null) {
+ $this->pattern = $this->configuration->find('customer.choice_pattern');
+
+ if ($this->pattern === null || stripos($this->pattern, '{') === false || stripos($this->pattern, '}') === false) {
+ $this->pattern = self::PATTERN_NAME;
+ }
+ }
+
+ $name = $this->pattern;
+ $name = str_replace(self::PATTERN_NAME, $customer->getName(), $name);
+ $name = str_replace(self::PATTERN_COMMENT, $customer->getComment(), $name);
+ $name = str_replace(self::PATTERN_NUMBER, $customer->getNumber(), $name);
+ $name = str_replace(self::PATTERN_COMPANY, $customer->getCompany() ?? $customer->getName(), $name);
+ $name = str_replace(self::PATTERN_SPACER, self::SPACER, $name);
+
+ $name = ltrim($name, self::SPACER);
+ $name = rtrim($name, self::SPACER);
+
+ if ($name === '' || $name === self::SPACER) {
+ $name = $customer->getName();
+ }
+
+ return $name;
+ }
+
+ public function getChoiceAttributes(Customer $customer, $key, $value): array
+ {
+ return ['data-currency' => $customer->getCurrency()];
+ }
+
/**
* {@inheritdoc}
*/
@@ -36,7 +84,8 @@ class CustomerType extends AbstractType
],
'label' => 'label.customer',
'class' => Customer::class,
- 'choice_label' => 'name',
+ 'choice_label' => [$this, 'getChoiceLabel'],
+ 'choice_attr' => [$this, 'getChoiceAttributes'],
'query_builder_for_user' => true,
'project_enabled' => false,
'project_select' => 'project',
diff --git a/src/Form/Type/CustomerTypePatternType.php b/src/Form/Type/CustomerTypePatternType.php
new file mode 100644
index 00000000..7e1f3ad0
--- /dev/null
+++ b/src/Form/Type/CustomerTypePatternType.php
@@ -0,0 +1,65 @@
+translator = $translator;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function configureOptions(OptionsResolver $resolver)
+ {
+ $name = $this->translator->trans('label.name');
+ $company = $this->translator->trans('label.company');
+ $number = $this->translator->trans('label.number');
+ $comment = $this->translator->trans('label.description');
+ $spacer = CustomerType::SPACER;
+
+ $resolver->setDefaults([
+ 'label' => 'label.choice_pattern',
+ 'choices' => [
+ $name => CustomerType::PATTERN_NAME,
+ $company => CustomerType::PATTERN_COMPANY,
+ $number => CustomerType::PATTERN_NUMBER,
+ $comment => CustomerType::PATTERN_COMMENT,
+ $name . $spacer . $company => CustomerType::PATTERN_NAME . CustomerType::PATTERN_SPACER . CustomerType::PATTERN_COMPANY,
+ $name . $spacer . $number => CustomerType::PATTERN_NAME . CustomerType::PATTERN_SPACER . CustomerType::PATTERN_NUMBER,
+ $name . $spacer . $comment => CustomerType::PATTERN_NAME . CustomerType::PATTERN_SPACER . CustomerType::PATTERN_COMMENT,
+ $number . $spacer . $name => CustomerType::PATTERN_NUMBER . CustomerType::PATTERN_SPACER . CustomerType::PATTERN_NAME,
+ $number . $spacer . $company => CustomerType::PATTERN_NUMBER . CustomerType::PATTERN_SPACER . CustomerType::PATTERN_COMPANY,
+ $number . $spacer . $comment => CustomerType::PATTERN_NUMBER . CustomerType::PATTERN_SPACER . CustomerType::PATTERN_COMMENT,
+ $company . $spacer . $comment => CustomerType::PATTERN_COMPANY . CustomerType::PATTERN_SPACER . CustomerType::PATTERN_COMMENT,
+ ]
+ ]);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getParent()
+ {
+ return ChoiceType::class;
+ }
+}
diff --git a/src/Form/Type/ProjectType.php b/src/Form/Type/ProjectType.php
index a70f173d..ce600484 100644
--- a/src/Form/Type/ProjectType.php
+++ b/src/Form/Type/ProjectType.php
@@ -9,10 +9,12 @@
namespace App\Form\Type;
+use App\Configuration\SystemConfiguration;
use App\Entity\Project;
use App\Repository\ProjectRepository;
use App\Repository\Query\ActivityQuery;
use App\Repository\Query\ProjectFormTypeQuery;
+use App\Utils\LocaleSettings;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\Options;
@@ -23,25 +25,93 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
*/
class ProjectType extends AbstractType
{
+ public const PATTERN_NAME = '{name}';
+ public const PATTERN_COMMENT = '{comment}';
+ public const PATTERN_ORDERNUMBER = '{ordernumber}';
+ public const PATTERN_DATERANGE = '{daterange}';
+ public const PATTERN_START = '{start}';
+ public const PATTERN_END = '{end}';
+ public const PATTERN_SPACER = '{spacer}';
+ public const SPACER = ' - ';
+
+ private $configuration;
+ private $localeSettings;
+ private $dateFormat;
+ private $pattern;
+
+ public function __construct(SystemConfiguration $configuration, LocaleSettings $localeSettings)
+ {
+ $this->configuration = $configuration;
+ $this->localeSettings = $localeSettings;
+ }
+
+ public function getChoiceLabel(Project $project): string
+ {
+ if ($this->dateFormat === null) {
+ $this->dateFormat = $this->localeSettings->getDateFormat();
+ }
+
+ if ($this->pattern === null) {
+ $this->pattern = $this->configuration->find('project.choice_pattern');
+
+ if ($this->pattern === null || stripos($this->pattern, '{') === false || stripos($this->pattern, '}') === false) {
+ $this->pattern = self::PATTERN_NAME;
+ }
+ }
+
+ $dateRange = '';
+ if ($project->getStart() !== null) {
+ $dateRange = self::PATTERN_START;
+ }
+ if ($project->getEnd() !== null) {
+ if ($dateRange !== '') {
+ $dateRange .= '-';
+ }
+ $dateRange .= self::PATTERN_END;
+ }
+
+ $start = '';
+ if ($project->getStart() !== null) {
+ $start = $project->getStart()->format($this->dateFormat);
+ }
+
+ $end = '';
+ if ($project->getEnd() !== null) {
+ $end = $project->getEnd()->format($this->dateFormat);
+ }
+
+ $name = $this->pattern;
+ $name = str_replace(self::PATTERN_NAME, $project->getName(), $name);
+ $name = str_replace(self::PATTERN_COMMENT, $project->getComment(), $name);
+ $name = str_replace(self::PATTERN_ORDERNUMBER, $project->getOrderNumber(), $name);
+ $name = str_replace(self::PATTERN_DATERANGE, $dateRange, $name);
+ $name = str_replace(self::PATTERN_START, $start, $name);
+ $name = str_replace(self::PATTERN_END, $end, $name);
+ $name = str_replace(self::PATTERN_SPACER, self::SPACER, $name);
+
+ $name = ltrim($name, self::SPACER);
+ $name = rtrim($name, self::SPACER);
+
+ if ($name === '' || $name === self::SPACER) {
+ $name = $project->getName();
+ }
+
+ return $name;
+ }
+
/**
- * @param Project $choiceValue
+ * @param Project $project
* @param string $key
* @param mixed $value
* @return array
*/
- public function choiceAttr($choiceValue, $key, $value)
+ public function getChoiceAttributes(Project $project, $key, $value): array
{
- $customer = null;
-
- if (!($choiceValue instanceof Project)) {
- return [];
+ if (null !== ($customer = $project->getCustomer())) {
+ return ['data-customer' => $customer->getId(), 'data-currency' => $customer->getCurrency()];
}
- if (null !== $choiceValue->getCustomer()) {
- $customer = $choiceValue->getCustomer()->getId();
- }
-
- return ['data-customer' => $customer];
+ return [];
}
/**
@@ -57,8 +127,8 @@ class ProjectType extends AbstractType
],
'label' => 'label.project',
'class' => Project::class,
- 'choice_label' => 'name',
- 'choice_attr' => [$this, 'choiceAttr'],
+ 'choice_label' => [$this, 'getChoiceLabel'],
+ 'choice_attr' => [$this, 'getChoiceAttributes'],
'group_by' => function (Project $project, $key, $index) {
return $project->getCustomer()->getName();
},
diff --git a/src/Form/Type/ProjectTypePatternType.php b/src/Form/Type/ProjectTypePatternType.php
new file mode 100644
index 00000000..41cd1f90
--- /dev/null
+++ b/src/Form/Type/ProjectTypePatternType.php
@@ -0,0 +1,61 @@
+translator = $translator;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function configureOptions(OptionsResolver $resolver)
+ {
+ $name = $this->translator->trans('label.name');
+ $comment = $this->translator->trans('label.description');
+ $orderNumber = $this->translator->trans('label.orderNumber');
+ $projectStart = $this->translator->trans('label.project_start');
+ $projectEnd = $this->translator->trans('label.project_end');
+
+ $spacer = ProjectType::SPACER;
+
+ $resolver->setDefaults([
+ 'label' => 'label.choice_pattern',
+ 'choices' => [
+ $name => ProjectType::PATTERN_NAME,
+ $comment => ProjectType::PATTERN_COMMENT,
+ $name . $spacer . $orderNumber => ProjectType::PATTERN_NAME . ProjectType::PATTERN_SPACER . ProjectType::PATTERN_ORDERNUMBER,
+ $name . $spacer . $comment => ProjectType::PATTERN_NAME . ProjectType::PATTERN_SPACER . ProjectType::PATTERN_COMMENT,
+ $name . $spacer . $projectStart . '-' . $projectEnd => ProjectType::PATTERN_NAME . ProjectType::PATTERN_SPACER . ProjectType::PATTERN_DATERANGE,
+ ]
+ ]);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getParent()
+ {
+ return ChoiceType::class;
+ }
+}
diff --git a/src/Utils/LocaleSettings.php b/src/Utils/LocaleSettings.php
index c68b2c78..dca605da 100644
--- a/src/Utils/LocaleSettings.php
+++ b/src/Utils/LocaleSettings.php
@@ -18,13 +18,27 @@ use Symfony\Component\HttpFoundation\RequestStack;
*/
final class LocaleSettings extends LocaleFormats
{
+ private $requestStack;
+ private $locale;
+
public function __construct(RequestStack $requestStack, LanguageFormattings $formats)
{
- $locale = Constants::DEFAULT_LOCALE;
- // request is null in a console command
- if (null !== $requestStack->getMasterRequest()) {
- $locale = $requestStack->getMasterRequest()->getLocale();
+ parent::__construct($formats, Constants::DEFAULT_LOCALE);
+ $this->requestStack = $requestStack;
+ }
+
+ public function getLocale(): string
+ {
+ if ($this->locale === null) {
+ $locale = \Locale::getDefault();
+
+ // request is null in a console command
+ if (null !== $this->requestStack->getMasterRequest()) {
+ $locale = $this->requestStack->getMasterRequest()->getLocale();
+ }
+ $this->locale = $locale;
}
- parent::__construct($formats, $locale);
+
+ return $this->locale;
}
}
diff --git a/tests/Controller/ActivityControllerTest.php b/tests/Controller/ActivityControllerTest.php
index 2080324d..f7b218dc 100644
--- a/tests/Controller/ActivityControllerTest.php
+++ b/tests/Controller/ActivityControllerTest.php
@@ -41,6 +41,30 @@ class ActivityControllerTest extends ControllerBaseTest
$client = $this->getClientForAuthenticatedUser(User::ROLE_TEAMLEAD);
$this->assertAccessIsGranted($client, '/admin/activity/');
$this->assertHasDataTable($client);
+
+ $this->assertPageActions($client, [
+ 'search' => '#',
+ 'visibility' => '#',
+ 'download toolbar-action' => $this->createUrl('/admin/activity/export'),
+ 'create modal-ajax-form' => $this->createUrl('/admin/activity/create'),
+ 'help' => 'https://www.kimai.org/documentation/activity.html'
+ ]);
+ }
+
+ public function testIndexActionAsSuperAdmin()
+ {
+ $client = $this->getClientForAuthenticatedUser(User::ROLE_SUPER_ADMIN);
+ $this->assertAccessIsGranted($client, '/admin/activity/');
+ $this->assertHasDataTable($client);
+
+ $this->assertPageActions($client, [
+ 'search' => '#',
+ 'visibility' => '#',
+ 'download toolbar-action' => $this->createUrl('/admin/activity/export'),
+ 'create modal-ajax-form' => $this->createUrl('/admin/activity/create'),
+ 'settings modal-ajax-form' => $this->createUrl('/admin/system-config/edit/activity'),
+ 'help' => 'https://www.kimai.org/documentation/activity.html'
+ ]);
}
public function testIndexActionWithSearchTermQuery()
diff --git a/tests/Controller/CustomerControllerTest.php b/tests/Controller/CustomerControllerTest.php
index 2c6f41f2..60c06052 100644
--- a/tests/Controller/CustomerControllerTest.php
+++ b/tests/Controller/CustomerControllerTest.php
@@ -43,6 +43,29 @@ class CustomerControllerTest extends ControllerBaseTest
$client = $this->getClientForAuthenticatedUser(User::ROLE_TEAMLEAD);
$this->assertAccessIsGranted($client, '/admin/customer/');
$this->assertHasDataTable($client);
+
+ $this->assertPageActions($client, [
+ 'search' => '#',
+ 'visibility' => '#',
+ 'download toolbar-action' => $this->createUrl('/admin/customer/export'),
+ 'help' => 'https://www.kimai.org/documentation/customer.html'
+ ]);
+ }
+
+ public function testIndexActionAsSuperAdmin()
+ {
+ $client = $this->getClientForAuthenticatedUser(User::ROLE_SUPER_ADMIN);
+ $this->assertAccessIsGranted($client, '/admin/customer/');
+ $this->assertHasDataTable($client);
+
+ $this->assertPageActions($client, [
+ 'search' => '#',
+ 'visibility' => '#',
+ 'download toolbar-action' => $this->createUrl('/admin/customer/export'),
+ 'create modal-ajax-form' => $this->createUrl('/admin/customer/create'),
+ 'settings modal-ajax-form' => $this->createUrl('/admin/system-config/edit/customer'),
+ 'help' => 'https://www.kimai.org/documentation/customer.html'
+ ]);
}
public function testIndexActionWithSearchTermQuery()
@@ -61,6 +84,14 @@ class CustomerControllerTest extends ControllerBaseTest
$this->assertAccessIsGranted($client, '/admin/customer/');
+ $this->assertPageActions($client, [
+ 'search' => '#',
+ 'visibility' => '#',
+ 'download toolbar-action' => $this->createUrl('/admin/customer/export'),
+ 'create modal-ajax-form' => $this->createUrl('/admin/customer/create'),
+ 'help' => 'https://www.kimai.org/documentation/customer.html'
+ ]);
+
$form = $client->getCrawler()->filter('form.searchform')->form();
$client->submit($form, [
'searchTerm' => 'feature:timetracking foo',
diff --git a/tests/Controller/ProjectControllerTest.php b/tests/Controller/ProjectControllerTest.php
index ed4a52c4..73bb958c 100644
--- a/tests/Controller/ProjectControllerTest.php
+++ b/tests/Controller/ProjectControllerTest.php
@@ -49,6 +49,29 @@ class ProjectControllerTest extends ControllerBaseTest
$client = $this->getClientForAuthenticatedUser(User::ROLE_TEAMLEAD);
$this->assertAccessIsGranted($client, '/admin/project/');
$this->assertHasDataTable($client);
+
+ $this->assertPageActions($client, [
+ 'search' => '#',
+ 'visibility' => '#',
+ 'download toolbar-action' => $this->createUrl('/admin/project/export'),
+ 'help' => 'https://www.kimai.org/documentation/project.html'
+ ]);
+ }
+
+ public function testIndexActionAsSuperAdmin()
+ {
+ $client = $this->getClientForAuthenticatedUser(User::ROLE_SUPER_ADMIN);
+ $this->assertAccessIsGranted($client, '/admin/project/');
+ $this->assertHasDataTable($client);
+
+ $this->assertPageActions($client, [
+ 'search' => '#',
+ 'visibility' => '#',
+ 'download toolbar-action' => $this->createUrl('/admin/project/export'),
+ 'create modal-ajax-form' => $this->createUrl('/admin/project/create'),
+ 'settings modal-ajax-form' => $this->createUrl('/admin/system-config/edit/project'),
+ 'help' => 'https://www.kimai.org/documentation/project.html'
+ ]);
}
public function testIndexActionWithSearchTermQuery()
@@ -67,6 +90,14 @@ class ProjectControllerTest extends ControllerBaseTest
$this->assertAccessIsGranted($client, '/admin/project/');
+ $this->assertPageActions($client, [
+ 'search' => '#',
+ 'visibility' => '#',
+ 'download toolbar-action' => $this->createUrl('/admin/project/export'),
+ 'create modal-ajax-form' => $this->createUrl('/admin/project/create'),
+ 'help' => 'https://www.kimai.org/documentation/project.html'
+ ]);
+
$form = $client->getCrawler()->filter('form.searchform')->form();
$client->submit($form, [
'searchTerm' => 'feature:timetracking foo',
diff --git a/tests/Controller/SystemConfigurationControllerTest.php b/tests/Controller/SystemConfigurationControllerTest.php
index 1fec2b8b..7aeaac0a 100644
--- a/tests/Controller/SystemConfigurationControllerTest.php
+++ b/tests/Controller/SystemConfigurationControllerTest.php
@@ -76,6 +76,8 @@ class SystemConfigurationControllerTest extends ControllerBaseTest
['form[name=system_configuration_form_authentication]', $this->createUrl('/admin/system-config/update/authentication')],
['form[name=system_configuration_form_rounding]', $this->createUrl('/admin/system-config/update/rounding')],
['form[name=system_configuration_form_customer]', $this->createUrl('/admin/system-config/update/customer')],
+ ['form[name=system_configuration_form_project]', $this->createUrl('/admin/system-config/update/project')],
+ ['form[name=system_configuration_form_activity]', $this->createUrl('/admin/system-config/update/activity')],
['form[name=system_configuration_form_user]', $this->createUrl('/admin/system-config/update/user')],
['form[name=system_configuration_form_theme]', $this->createUrl('/admin/system-config/update/theme')],
['form[name=system_configuration_form_calendar]', $this->createUrl('/admin/system-config/update/calendar')],
diff --git a/translations/messages.de.xlf b/translations/messages.de.xlf
index fd7ac980..fd97008c 100644
--- a/translations/messages.de.xlf
+++ b/translations/messages.de.xlf
@@ -116,6 +116,10 @@
modal.dirty
Das Formular wurde geändert. Bitte klicken Sie „Speichern“, um die Änderungen zu sichern oder „Schließen“, um abzubrechen.
+
+ Display of entries in selection lists
+ Darstellung der Einträge in Auswahllisten
+
diff --git a/translations/messages.en.xlf b/translations/messages.en.xlf
index 3e6c9b12..e7d51cca 100644
--- a/translations/messages.en.xlf
+++ b/translations/messages.en.xlf
@@ -116,6 +116,10 @@
modal.dirty
The form has changed. Please click "Save" to save the changes or "Close" to cancel.
+
+ Display of entries in selection lists
+ Display of entries in selection lists
+