configure display of customer, project and activity in dropdown lists (#3151)
This commit is contained in:
@@ -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([
|
||||
|
||||
@@ -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'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
55
src/Form/Type/ActivityTypePatternType.php
Normal file
55
src/Form/Type/ActivityTypePatternType.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?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 Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
/**
|
||||
* Select the pattern that will be used when rendering an activity select.
|
||||
*/
|
||||
class ActivityTypePatternType extends AbstractType
|
||||
{
|
||||
private $translator;
|
||||
|
||||
public function __construct(TranslatorInterface $translator)
|
||||
{
|
||||
$this->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;
|
||||
}
|
||||
}
|
||||
@@ -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',
|
||||
|
||||
65
src/Form/Type/CustomerTypePatternType.php
Normal file
65
src/Form/Type/CustomerTypePatternType.php
Normal file
@@ -0,0 +1,65 @@
|
||||
<?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 Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
/**
|
||||
* Select the pattern that will be used when rendering a custom select.
|
||||
*/
|
||||
class CustomerTypePatternType extends AbstractType
|
||||
{
|
||||
private $translator;
|
||||
|
||||
public function __construct(TranslatorInterface $translator)
|
||||
{
|
||||
$this->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;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
},
|
||||
|
||||
61
src/Form/Type/ProjectTypePatternType.php
Normal file
61
src/Form/Type/ProjectTypePatternType.php
Normal file
@@ -0,0 +1,61 @@
|
||||
<?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 Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
/**
|
||||
* Select the pattern that will be used when rendering a project select.
|
||||
*/
|
||||
class ProjectTypePatternType extends AbstractType
|
||||
{
|
||||
private $translator;
|
||||
|
||||
public function __construct(TranslatorInterface $translator)
|
||||
{
|
||||
$this->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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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')],
|
||||
|
||||
@@ -116,6 +116,10 @@
|
||||
<source>modal.dirty</source>
|
||||
<target>Das Formular wurde geändert. Bitte klicken Sie „Speichern“, um die Änderungen zu sichern oder „Schließen“, um abzubrechen.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sdfgsdfgsdfg" resname="label.choice_pattern">
|
||||
<source>Display of entries in selection lists</source>
|
||||
<target>Darstellung der Einträge in Auswahllisten</target>
|
||||
</trans-unit>
|
||||
<!--
|
||||
Login / Security
|
||||
-->
|
||||
|
||||
@@ -116,6 +116,10 @@
|
||||
<source>modal.dirty</source>
|
||||
<target>The form has changed. Please click "Save" to save the changes or "Close" to cancel.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sdfgsdfgsdfg" resname="label.choice_pattern">
|
||||
<source>Display of entries in selection lists</source>
|
||||
<target>Display of entries in selection lists</target>
|
||||
</trans-unit>
|
||||
<!--
|
||||
Login / Security
|
||||
-->
|
||||
|
||||
Reference in New Issue
Block a user