Release 2.11 (#4580)

This commit is contained in:
Kevin Papst
2024-02-02 13:52:24 +01:00
committed by GitHub
parent a9a32c83ac
commit 49e69d1ae3
55 changed files with 347 additions and 264 deletions

View File

@@ -64,7 +64,7 @@ final class TranslationCommand extends Command
$bases = [
'core' => $this->projectDirectory . '/translations/*.xlf',
//'plugins' => $this->projectDirectory . Kernel::PLUGIN_DIRECTORY . '/*/Resources/translations/*.xlf',
'plugins' => $this->projectDirectory . Kernel::PLUGIN_DIRECTORY . '/*/Resources/translations/*.xlf',
'theme' => $this->projectDirectory . '/vendor/kevinpapst/tabler-bundle/translations/*.xlf',
];

View File

@@ -17,11 +17,11 @@ class Constants
/**
* The current release version
*/
public const VERSION = '2.10.0';
public const VERSION = '2.11.0';
/**
* The current release: major * 10000 + minor * 100 + patch
*/
public const VERSION_ID = 21000;
public const VERSION_ID = 21100;
/**
* The software name
*/

View File

@@ -26,6 +26,7 @@ use App\Repository\TimesheetRepository;
use App\Repository\UserRepository;
use App\Timesheet\TimesheetStatisticService;
use App\User\UserService;
use App\Utils\PageSetup;
use Doctrine\Common\Collections\ArrayCollection;
use Endroid\QrCode\Builder\Builder;
use Endroid\QrCode\Encoding\Encoding;
@@ -54,6 +55,17 @@ final class ProfileController extends AbstractController
return $this->redirectToRoute('user_profile', ['username' => $this->getUser()->getUserIdentifier()]);
}
private function getPageSetup(User $profile, string $view): PageSetup
{
$page = new PageSetup('users');
$page->setHelp('users.html');
$page->setActionName('user');
$page->setActionView($view);
$page->setActionPayload(['user' => $profile]);
return $page;
}
#[Route(path: '/{username}', name: 'user_profile', methods: ['GET'])]
#[IsGranted('view', 'profile')]
public function indexAction(User $profile, TimesheetRepository $repository, TimesheetStatisticService $statisticService): Response
@@ -74,6 +86,7 @@ final class ProfileController extends AbstractController
$viewVars = [
'tab' => 'charts',
'page_setup' => $this->getPageSetup($profile, 'charts'),
'user' => $profile,
'stats' => $userStats,
'workingSince' => $workStartingDay,
@@ -105,6 +118,7 @@ final class ProfileController extends AbstractController
return $this->render('user/profile.html.twig', [
'tab' => 'edit',
'page_setup' => $this->getPageSetup($profile, 'edit'),
'user' => $profile,
'form' => $form->createView(),
]);
@@ -128,6 +142,7 @@ final class ProfileController extends AbstractController
return $this->render('user/form.html.twig', [
'tab' => 'password',
'page_setup' => $this->getPageSetup($profile, 'password'),
'user' => $profile,
'form' => $form->createView(),
]);
@@ -151,6 +166,7 @@ final class ProfileController extends AbstractController
return $this->render('user/api-token.html.twig', [
'tab' => 'api-token',
'page_setup' => $this->getPageSetup($profile, 'api-token'),
'user' => $profile,
'form' => $form->createView(),
]);
@@ -182,6 +198,7 @@ final class ProfileController extends AbstractController
return $this->render('user/form.html.twig', [
'tab' => 'roles',
'page_setup' => $this->getPageSetup($profile, 'roles'),
'user' => $profile,
'form' => $form->createView(),
]);
@@ -208,6 +225,7 @@ final class ProfileController extends AbstractController
return $this->render('user/contract.html.twig', [
'tab' => 'contract',
'page_setup' => $this->getPageSetup($profile, 'contract'),
'user' => $profile,
'form' => $form->createView(),
]);
@@ -243,6 +261,7 @@ final class ProfileController extends AbstractController
return $this->render('user/form.html.twig', [
'tab' => 'teams',
'page_setup' => $this->getPageSetup($profile, 'teams'),
'user' => $profile,
'form' => $form->createView(),
]);
@@ -294,6 +313,7 @@ final class ProfileController extends AbstractController
return $this->render('user/preferences.html.twig', [
'tab' => 'settings',
'page_setup' => $this->getPageSetup($profile, 'settings'),
'user' => $profile,
'form' => $form->createView(),
'sections' => $sections
@@ -422,6 +442,7 @@ final class ProfileController extends AbstractController
return $this->render('user/2fa.html.twig', [
'tab' => '2fa',
'page_setup' => $this->getPageSetup($profile, '2fa'),
'user' => $profile,
'form' => $form->createView(),
'deactivate' => $this->getTwoFactorDeactivationForm($profile)->createView(),

View File

@@ -54,7 +54,7 @@ class Activity implements EntityWithMetaFields, EntityWithBudget
*/
#[ORM\Column(name: 'name', type: 'string', length: 150, nullable: false)]
#[Assert\NotBlank]
#[Assert\Length(min: 3, max: 150)]
#[Assert\Length(min: 2, max: 150)]
#[Serializer\Expose]
#[Serializer\Groups(['Default'])]
#[Exporter\Expose(label: 'name')]

View File

@@ -41,7 +41,7 @@ class Customer implements EntityWithMetaFields, EntityWithBudget
private ?int $id = null;
#[ORM\Column(name: 'name', type: 'string', length: 150, nullable: false)]
#[Assert\NotBlank]
#[Assert\Length(min: 3, max: 150)]
#[Assert\Length(min: 2, max: 150)]
#[Serializer\Expose]
#[Serializer\Groups(['Default'])]
#[Exporter\Expose(label: 'name')]

View File

@@ -59,7 +59,7 @@ class Project implements EntityWithMetaFields, EntityWithBudget
*/
#[ORM\Column(name: 'name', type: 'string', length: 150, nullable: false)]
#[Assert\NotNull]
#[Assert\Length(min: 3, max: 150)]
#[Assert\Length(min: 2, max: 150)]
#[Serializer\Expose]
#[Serializer\Groups(['Default'])]
#[Exporter\Expose(label: 'name')]

View File

@@ -19,10 +19,6 @@ use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
/**
* When visiting the homepage, this listener redirects the user to the most
* appropriate localized version according to the browser settings.
*
* See http://symfony.com/doc/current/components/http_kernel/introduction.html#the-kernel-request-event
*
* @author Oleg Voronkovich <oleg-voronkovich@yandex.ru>
*/
final class RedirectToLocaleSubscriber implements EventSubscriberInterface
{
@@ -41,7 +37,7 @@ final class RedirectToLocaleSubscriber implements EventSubscriberInterface
{
$request = $event->getRequest();
// Ignore sub-requests and all URLs but the homepage
// only trigger on the homepage
if ('/' !== $request->getPathInfo()) {
return;
}
@@ -53,7 +49,7 @@ final class RedirectToLocaleSubscriber implements EventSubscriberInterface
return;
}
$allLanguages = $this->localeService->getAllLocales();
$allLanguages = $this->localeService->getTranslatedLocales();
// Add the default locale at the first position of the array, because getPreferredLanguage()
// returns the first element when no appropriate language is found

View File

@@ -16,10 +16,17 @@ use Symfony\Component\Form\Exception\TransformationFailedException;
final class TagArrayToStringTransformer implements DataTransformerInterface
{
private bool $create = true;
public function __construct(private TagRepository $tagRepository)
{
}
public function setCreate(bool $create): void
{
$this->create = $create;
}
/**
* Transforms an array of tags to a string.
*
@@ -55,15 +62,17 @@ final class TagArrayToStringTransformer implements DataTransformerInterface
// get the current tags and find the new ones that should be created
$tags = $this->tagRepository->findBy(['name' => $names]);
// works, because of the implicit case: (string) $tag
$newNames = array_diff($names, $tags);
if ($this->create) {
// works, because of the implicit case: (string) $tag
$newNames = array_diff($names, $tags);
foreach ($newNames as $name) {
$tag = new Tag();
$tag->setName(mb_substr($name, 0, 100));
$tags[] = $tag;
foreach ($newNames as $name) {
$tag = new Tag();
$tag->setName(mb_substr($name, 0, 100));
$tags[] = $tag;
// new tags persist automatically thanks to the cascade={"persist"}
// new tags persist automatically thanks to the cascade={"persist"}
}
}
return $tags;

View File

@@ -36,7 +36,7 @@ final class SearchTermType extends AbstractType
'placeholder' => 'search',
],
'constraints' => [
new Length(['min' => 3])
new Length(['min' => 2])
],
]);
}

View File

@@ -30,9 +30,12 @@ final class TagsInputType extends AbstractType
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->addModelTransformer(new CollectionToArrayTransformer(), true)
->addModelTransformer($this->transformer, true);
if ($options['allow_create'] === false) {
$this->transformer->setCreate(false);
}
$builder->addModelTransformer(new CollectionToArrayTransformer(), true);
$builder->addModelTransformer($this->transformer, true);
}
public function configureOptions(OptionsResolver $resolver): void

View File

@@ -16,11 +16,11 @@ use Twig\Extension\RuntimeExtensionInterface;
final class EncoreExtension implements RuntimeExtensionInterface, ServiceSubscriberInterface
{
private string $publicDir;
public function __construct(private ContainerInterface $container, string $projectDirectory)
public function __construct(
private readonly ContainerInterface $container,
private readonly string $projectDirectory
)
{
$this->publicDir = $projectDirectory . '/public';
}
public static function getSubscribedServices(): array
@@ -38,7 +38,7 @@ final class EncoreExtension implements RuntimeExtensionInterface, ServiceSubscri
$source = '';
foreach ($files as $file) {
$source .= file_get_contents($this->publicDir . '/' . $file);
$source .= file_get_contents($this->projectDirectory . '/public/' . $file);
}
$lookup->reset();