prepare release 1.14 (#2495)
* removed un-maintained docker file * update all packages * fix deprecations * only show one line descriptions for customer, projects and activities * allow to show export column in timesheet listing
This commit is contained in:
@@ -15,7 +15,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
class NotFoundException extends NotFoundHttpException
|
||||
{
|
||||
public function __construct(string $message = 'Not found', \Exception $previous = null, int $code = 0, array $headers = [])
|
||||
public function __construct(string $message = 'Not found', \Exception $previous = null, int $code = 404, array $headers = [])
|
||||
{
|
||||
parent::__construct($message, $previous, $code, $headers);
|
||||
}
|
||||
|
||||
45
src/EventSubscriber/PagerfantaExceptionSubscriber.php
Normal file
45
src/EventSubscriber/PagerfantaExceptionSubscriber.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?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\EventSubscriber;
|
||||
|
||||
use Pagerfanta\Exception\NotValidMaxPerPageException;
|
||||
use Pagerfanta\Exception\OutOfRangeCurrentPageException;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
|
||||
/**
|
||||
* Catches Pagerfanta Exceptions and converts them to "normal" Http Exceptions with status code 404.
|
||||
* This was mainly done to convert the 500 to 404 HTTP response code.
|
||||
* This prevents also the need to register them in fos_rest.yaml for the API.
|
||||
*/
|
||||
final class PagerfantaExceptionSubscriber implements EventSubscriberInterface
|
||||
{
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
KernelEvents::EXCEPTION => ['onCoreException', 1]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ExceptionEvent $event
|
||||
*/
|
||||
public function onCoreException(ExceptionEvent $event)
|
||||
{
|
||||
$throwable = $event->getThrowable();
|
||||
|
||||
if ($throwable instanceof NotValidMaxPerPageException || $throwable instanceof OutOfRangeCurrentPageException) {
|
||||
$notFoundHttpException = new NotFoundHttpException($throwable->getMessage(), $throwable, $throwable->getCode());
|
||||
$event->setThrowable($notFoundHttpException);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,27 +28,25 @@ use Symfony\Component\Form\FormEvent;
|
||||
use Symfony\Component\Form\FormEvents;
|
||||
|
||||
/**
|
||||
* Defines the form used to manipulate Timesheet entries.
|
||||
* @internal
|
||||
* Helper functions to manage dependent customer-project-activity fields.
|
||||
*/
|
||||
trait FormTrait
|
||||
{
|
||||
protected function addCustomer(FormBuilderInterface $builder, ?Customer $customer = null)
|
||||
{
|
||||
$builder
|
||||
->add('customer', CustomerType::class, [
|
||||
'query_builder' => function (CustomerRepository $repo) use ($builder, $customer) {
|
||||
$query = new CustomerFormTypeQuery($customer);
|
||||
$query->setUser($builder->getOption('user'));
|
||||
$builder->add('customer', CustomerType::class, [
|
||||
'query_builder' => function (CustomerRepository $repo) use ($builder, $customer) {
|
||||
$query = new CustomerFormTypeQuery($customer);
|
||||
$query->setUser($builder->getOption('user'));
|
||||
|
||||
return $repo->getQueryBuilderForFormType($query);
|
||||
},
|
||||
'data' => $customer ? $customer : '',
|
||||
'required' => false,
|
||||
'placeholder' => '',
|
||||
'mapped' => false,
|
||||
'project_enabled' => true,
|
||||
]);
|
||||
return $repo->getQueryBuilderForFormType($query);
|
||||
},
|
||||
'data' => $customer ? $customer : '',
|
||||
'required' => false,
|
||||
'placeholder' => '',
|
||||
'mapped' => false,
|
||||
'project_enabled' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
protected function addProject(FormBuilderInterface $builder, bool $isNew, ?Project $project = null, ?Customer $customer = null)
|
||||
@@ -102,17 +100,15 @@ trait FormTrait
|
||||
|
||||
protected function addActivity(FormBuilderInterface $builder, ?Activity $activity = null, ?Project $project = null)
|
||||
{
|
||||
$builder
|
||||
->add('activity', ActivityType::class, [
|
||||
'placeholder' => '',
|
||||
'query_builder' => function (ActivityRepository $repo) use ($builder, $activity, $project) {
|
||||
$query = new ActivityFormTypeQuery($activity, $project);
|
||||
$query->setUser($builder->getOption('user'));
|
||||
$builder->add('activity', ActivityType::class, [
|
||||
'placeholder' => '',
|
||||
'query_builder' => function (ActivityRepository $repo) use ($builder, $activity, $project) {
|
||||
$query = new ActivityFormTypeQuery($activity, $project);
|
||||
$query->setUser($builder->getOption('user'));
|
||||
|
||||
return $repo->getQueryBuilderForFormType($query);
|
||||
},
|
||||
])
|
||||
;
|
||||
return $repo->getQueryBuilderForFormType($query);
|
||||
},
|
||||
]);
|
||||
|
||||
// replaces the activity select after submission, to make sure only activities for the selected project are displayed
|
||||
$builder->addEventListener(
|
||||
@@ -143,20 +139,23 @@ trait FormTrait
|
||||
{
|
||||
@trigger_error('FormTrait::addDescription() is deprecated and will be removed with 2.0, use DescriptionType instead', E_USER_DEPRECATED);
|
||||
|
||||
$builder
|
||||
->add('description', DescriptionType::class, [
|
||||
'required' => false,
|
||||
'attr' => [
|
||||
'autofocus' => 'autofocus'
|
||||
]
|
||||
]);
|
||||
$builder->add('description', DescriptionType::class, [
|
||||
'required' => false,
|
||||
'attr' => [
|
||||
'autofocus' => 'autofocus'
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since 1.14
|
||||
*/
|
||||
protected function addTags(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder
|
||||
->add('tags', TagsType::class, [
|
||||
'required' => false,
|
||||
]);
|
||||
@trigger_error('FormTrait::addTags() is deprecated and will be removed with 2.0, use TagsType instead', E_USER_DEPRECATED);
|
||||
|
||||
$builder->add('tags', TagsType::class, [
|
||||
'required' => false,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ use App\Form\Type\DurationType;
|
||||
use App\Form\Type\FixedRateType;
|
||||
use App\Form\Type\HourlyRateType;
|
||||
use App\Form\Type\MetaFieldsCollectionType;
|
||||
use App\Form\Type\TagsType;
|
||||
use App\Form\Type\UserType;
|
||||
use App\Form\Type\YesNoType;
|
||||
use App\Repository\CustomerRepository;
|
||||
@@ -121,8 +122,7 @@ class TimesheetEditForm extends AbstractType
|
||||
$descriptionOptions['attr'] = ['autofocus' => 'autofocus'];
|
||||
}
|
||||
$builder->add('description', DescriptionType::class, $descriptionOptions);
|
||||
|
||||
$this->addTags($builder);
|
||||
$builder->add('tags', TagsType::class, ['required' => false]);
|
||||
$this->addRates($builder, $currency, $options);
|
||||
$this->addUser($builder, $options);
|
||||
$builder->add('metaFields', MetaFieldsCollectionType::class);
|
||||
|
||||
@@ -69,6 +69,36 @@ final class MarkdownExtension implements RuntimeExtensionInterface
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the entities comment (customer, project, activity ...) into a one-liner.
|
||||
*
|
||||
* @param string|null $content
|
||||
* @param bool $fullLength
|
||||
* @return string
|
||||
*/
|
||||
public function commentOneLiner(?string $content, bool $fullLength = false): string
|
||||
{
|
||||
if (empty($content)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$addHellip = false;
|
||||
|
||||
if (!$fullLength && \strlen($content) > 52) {
|
||||
$content = trim(substr($content, 0, 50));
|
||||
$addHellip = true;
|
||||
}
|
||||
|
||||
$content = explode(PHP_EOL, $content);
|
||||
$result = $content[0];
|
||||
|
||||
if (\count($content) > 1 || $addHellip) {
|
||||
$result .= ' …';
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the timesheet description content into HTML.
|
||||
*
|
||||
|
||||
@@ -44,6 +44,7 @@ class RuntimeExtensions extends AbstractExtension
|
||||
new TwigFilter('md2html', [MarkdownExtension::class, 'markdownToHtml'], ['pre_escape' => 'html', 'is_safe' => ['html']]),
|
||||
new TwigFilter('desc2html', [MarkdownExtension::class, 'timesheetContent'], ['pre_escape' => 'html', 'is_safe' => ['html']]),
|
||||
new TwigFilter('comment2html', [MarkdownExtension::class, 'commentContent'], ['pre_escape' => 'html', 'is_safe' => ['html']]),
|
||||
new TwigFilter('comment1line', [MarkdownExtension::class, 'commentOneLiner'], ['pre_escape' => 'html', 'is_safe' => ['html']]),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user