Feat/disable services 662 (#669)

* disable button for services

* add button to disable services

---------

Co-authored-by: Sarahshr <sarah@les-tilleuls.coop>
This commit is contained in:
Sarahshr 2023-12-21 14:21:58 +01:00 committed by Slim
parent 45b25f42c9
commit a664e9a9bd
20 changed files with 266 additions and 157 deletions

View file

@ -4,6 +4,8 @@ App\Entity\Configuration:
features (extends configuration_template):
configuration:
services:
servicesEnabled: true
notificationsSender:
notificationsSenderEmail: info@example.com
notificationsSenderName: Contact

View file

@ -10,14 +10,19 @@ use App\Controller\RequestTrait;
use App\Dto\Product\Search;
use App\Entity\Product;
use App\Entity\User;
use App\Enum\Product\ProductType;
use App\Form\Type\Product\SearchFormType;
use App\Message\Query\Product\GetProductByIdQuery;
use App\MessageBus\QueryBus;
use App\Repository\ConfigurationRepository;
use App\Repository\ProductRepository;
use App\Search\Meilisearch;
use Knp\Component\Pager\PaginatorInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\GoneHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Messenger\Exception\HandlerFailedException;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Routing\Requirement\Requirement;
@ -42,6 +47,8 @@ final class ProductController extends AbstractController
private readonly QueryBus $queryBus,
private readonly PaginatorInterface $paginator,
private readonly Meilisearch $meilisearch,
private readonly ConfigurationRepository $configurationRepository,
private readonly ProductRepository $productRepository,
) {
}
@ -64,6 +71,7 @@ final class ProductController extends AbstractController
'objects_pagination' => $this->paginate($this->meilisearch->searchObjects($searchDto)),
'services_pagination' => $this->paginate($this->meilisearch->searchServices($searchDto)),
'search_form' => $searchForm,
'services_enabled' => $this->configurationRepository->getServicesParameter(),
]);
}
@ -79,6 +87,14 @@ final class ProductController extends AbstractController
)]
public function show(string $slug, string $id): Response
{
/** @var ?Product $product */
$product = $this->productRepository->find(['id' => $id]);
if ($product === null) {
throw new NotFoundHttpException();
}
if (($product->getType() === ProductType::SERVICE && $this->configurationRepository->getServicesParameter()) || $product->getType() === ProductType::OBJECT) {
try {
/** @var Product $product */
$product = $this->queryBus->query(new GetProductByIdQuery(Uuid::fromString($id)));
@ -87,5 +103,8 @@ final class ProductController extends AbstractController
}
return $this->render('pages/product/show.html.twig', compact('slug', 'id', 'product'));
} else {
throw new GoneHttpException();
}
}
}

View file

@ -10,6 +10,7 @@ use App\Dto\Product\Search;
use App\Entity\User;
use App\Message\Query\User\Account\GetUserQuery;
use App\MessageBus\QueryBus;
use App\Repository\ConfigurationRepository;
use App\Search\Meilisearch;
use Knp\Component\Pager\PaginatorInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
@ -33,6 +34,7 @@ final class ProfileAction extends AbstractController
private readonly QueryBus $queryBus,
private readonly PaginatorInterface $paginator,
private readonly Meilisearch $meilisearch,
private readonly ConfigurationRepository $configurationRepository,
) {
}
@ -59,6 +61,7 @@ final class ProfileAction extends AbstractController
'user' => $user,
'objects_pagination' => $this->paginate($this->meilisearch->searchObjects($searchDto)),
'services_pagination' => $this->paginate($this->meilisearch->searchServices($searchDto)),
'services_enabled' => $this->configurationRepository->getServicesParameter(),
]);
}
}

View file

@ -47,6 +47,8 @@ final class MyAccountAction extends AbstractController
$canCreateGroup = $configuration->isGroupsCreationForAll() || $user->isAdmin();
$contactEmail = $configuration->getContactEmail();
return $this->render('pages/account/index.html.twig', compact('userHasNewLoanMessage', 'userHasNewLendingMessage', 'canCreateGroup', 'contactEmail'));
$servicesConfig = $this->configurationRepository->getServicesParameter();
return $this->render('pages/account/index.html.twig', compact('userHasNewLoanMessage', 'userHasNewLendingMessage', 'canCreateGroup', 'contactEmail', 'servicesConfig'));
}
}

View file

@ -11,12 +11,14 @@ use App\Entity\Product;
use App\Entity\User;
use App\Form\Type\Product\ServiceFormType;
use App\MessageBus\QueryBus;
use App\Repository\ConfigurationRepository;
use App\Tests\Functional\Controller\Product\ServiceControllerTest;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\GoneHttpException;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Routing\Requirement\Requirement;
use Symfony\Component\Security\Http\Attribute\CurrentUser;
@ -37,6 +39,7 @@ final class ServiceController extends AbstractController
public function __construct(
private readonly QueryBus $queryBus,
private readonly ProductManager $productManager,
private readonly ConfigurationRepository $configurationRepository,
) {
}
@ -51,6 +54,7 @@ final class ServiceController extends AbstractController
], name: 'new')]
public function new(Request $request, #[CurrentUser] User $user): Response
{
if ($this->configurationRepository->getServicesParameter()) {
$product = $this->productManager->initService($user);
$form = $this->getForm($product, $request);
if ($form->isSubmitted() && $form->isValid()) {
@ -63,6 +67,9 @@ final class ServiceController extends AbstractController
}
return $this->render('pages/product/new_service.html.twig', compact('form'));
} else {
throw new GoneHttpException();
}
}
#[Route([
@ -74,6 +81,7 @@ final class ServiceController extends AbstractController
)]
public function edit(string $id, Request $request): Response
{
if ($this->configurationRepository->getServicesParameter()) {
$product = $this->getProductForEdit($id);
$form = $this->getForm($product, $request);
if ($form->isSubmitted() && $form->isValid()) {
@ -86,5 +94,8 @@ final class ServiceController extends AbstractController
}
return $this->render('pages/product/edit_service.html.twig', compact('form', 'product'));
} else {
throw new GoneHttpException();
}
}
}

View file

@ -15,12 +15,14 @@ use App\Message\Query\User\GetUserObjectsQuery;
use App\Message\Query\User\GetUserServicesQuery;
use App\MessageBus\QueryBus;
use App\Repository\CategoryRepository;
use App\Repository\ConfigurationRepository;
use Doctrine\ORM\Query;
use Knp\Component\Pager\Pagination\PaginationInterface;
use Knp\Component\Pager\PaginatorInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\GoneHttpException;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Attribute\CurrentUser;
use Symfony\Component\Security\Http\Attribute\IsGranted;
@ -40,6 +42,7 @@ final class UserProductsController extends AbstractController
private readonly QueryBus $queryBus,
private readonly PaginatorInterface $paginator,
public readonly CategoryRepository $categoryRepository,
private readonly ConfigurationRepository $configurationRepository,
) {
}
@ -89,6 +92,10 @@ final class UserProductsController extends AbstractController
$query = $this->queryBus->query(new GetUserServicesQuery($user->getId(), $category?->getId()));
$pagination = $this->paginate($query, $this->getPage($request));
if ($this->configurationRepository->getServicesParameter()) {
return $this->render('pages/account/product/list.html.twig', compact('pagination', 'form'));
} else {
throw new GoneHttpException('there is no services');
}
}
}

View file

@ -75,6 +75,24 @@ class Configuration
/** end of basic getters and setters ------------------------------------------------ */
/**
* @return bool[]
*/
public function getServices(): array
{
/** @var array<bool> $services */
$services = $this->configuration['services'] ?? [];
return $services;
}
public function getServicesEnabled(): bool
{
$services = $this->getServices();
return $services['servicesEnabled'];
}
/**
* @return array<string, string>
*/

View file

@ -25,10 +25,18 @@ final class ParametersFormType extends AbstractType
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('servicesEnabled', CheckboxType::class, [
'label' => 'parameter.services',
'label_attr' => [
'class' => 'checkbox-inline checkbox-switch',
],
])
->add('notificationsSenderEmail', EmailType::class, [
'label' => 'parameter.mail',
'label_attr' => ['class' => 'col-sm-2 col-form-label'],
])
->add('notificationsSenderName', TextType::class, [
'label' => 'parameter.name',
])

View file

@ -17,6 +17,10 @@ final class ParametersFormCommand extends AbstractFormCommand
final public const ONLY_ADMIN = 'only_admin';
final public const ALL = 'all';
// services section —————————————————————————————————————————————
#[Assert\Type('bool')]
public bool $servicesEnabled = true;
// notificationsSender section —————————————————————————————————————————————
#[Assert\Email()]
#[Assert\NotBlank()]
@ -55,6 +59,7 @@ final class ParametersFormCommand extends AbstractFormCommand
protected function getSections(): array
{
return [
'services',
'notificationsSender',
'contact',
'groups',
@ -71,6 +76,7 @@ final class ParametersFormCommand extends AbstractFormCommand
public function hydrate(Configuration $configuration): self
{
$instanceConfiguration = $configuration->getConfiguration();
// dd($instanceConfiguration);
foreach (array_keys(get_class_vars($this::class)) as $classVar) {
$this->{$classVar} = $instanceConfiguration[$this->getSection($classVar)][$classVar]; // @phpstan-ignore-line
}

View file

@ -58,4 +58,16 @@ final class ConfigurationRepository extends ServiceEntityRepository
return $cfg;
}
public function getServicesParameter(): bool
{
/** @var array{configuration: array{ services: array{ servicesEnabled: bool }}} $config */
$config = $this
->createQueryBuilder('c')
->select('c.configuration')
->setMaxResults(1)
->getQuery()->getOneOrNullResult();
return $config['configuration']['services']['servicesEnabled'];
}
}

View file

@ -14,6 +14,11 @@
{% block main %}
{{ form_start(form) }}
<div class="row mb-lg-5">
<h2 class="h3 fw-bold mt-3">{{ 'parameters.services.h2'|trans }}</h2>
<hr/>
{{ form_widget(form.servicesEnabled) }}
<h2 class="h3 fw-bold mt-3">{{ 'parameters.senders.h2'|trans }}</h2>
<hr/>

View file

@ -15,7 +15,7 @@
</div>
<p class="ms-3 mb-0 fs-6 fw-bolder">{{ name }}</p>
</div>
{% if isPlace %}
{% if isPlace and address is not null %}
<div class="row mt-3">
<div class="col">
<p class="fw-bold fs-6 mb-0">{{ 'templates.components.product.lender.address'|trans }}</p>

View file

@ -11,6 +11,7 @@
{{ 'product.list_type_objects'|trans }} ({{ objects_pagination.totalItemCount }})
</button>
</li>
{% if services_enabled %}
<li class="nav-item product-type w-50" role="presentation">
<button class="nav-link rounded-0 w-100 {% if index == 1 %}active{% endif %}"
id="pills-services-tab"
@ -21,6 +22,7 @@
({{ services_pagination.totalItemCount }})
</button>
</li>
{% endif %}
</ul>
</div>
</div>

View file

@ -15,7 +15,7 @@
pagination: objects_pagination,
} %}
</div>
{% if services_pagination is defined and services_pagination is not null %}
{% if services_pagination is defined and services_pagination is not null and services_enabled %}
<div class="tab-pane fade"
id="pills-services"
role="tabpanel"

View file

@ -53,6 +53,7 @@
},
{
section: 'Mes services',
disable: servicesConfig,
links: [
{
name: 'Voir mes services',
@ -133,6 +134,7 @@
} %}
<div class="row flex-wrap">
{% for my_account_link in my_account_links %}
{% if my_account_link.disable is not defined %}
<div class="col-12 col-md-4">
<nav class="myAccount d-flex flex-column mt-3 mt-md-5">
<div class="myAccount-header w-100 rounded-2">
@ -183,6 +185,7 @@
</div>
</nav>
</div>
{% endif %}
{% endfor %}
</div>
<div class="d-grid col-12 col-md-6 mx-auto mt-5">

View file

@ -4,8 +4,8 @@
<div class="px-3 px-lg-0">
{% include 'components/layout/_title_3.html.twig' with {name: 'product.list_name'|trans} %}
{% include 'components/product/_search.html.twig' with {form: search_form} %}
{% include 'components/product/_section.html.twig'with {objects_pagination, services_pagination} %}
{% include 'components/product/_tab_content.html.twig' with {objects_pagination, services_pagination} %}
{% include 'components/product/_section.html.twig'with {objects_pagination, services_pagination, services_enabled} %}
{% include 'components/product/_tab_content.html.twig' with {objects_pagination, services_pagination, services_enabled} %}
</div>
{% endblock %}

View file

@ -56,7 +56,7 @@
<span>{{ (i18n_prefix ~ '.no_result')|trans }}</span>
</div>
{% else %}
{% include 'components/product/_section.html.twig' %}
{% include 'components/product/_section.html.twig' with {services_enabled} %}
{% include 'components/product/_tab_content.html.twig' with {objects_pagination, services_pagination} %}
{% endif %}
</div>

View file

@ -34,7 +34,7 @@ final class ParametersControllerTest extends WebTestCase
$form = $crawler->selectButton('parameters_form_submit')->form();
self::assertSame(5, $crawler->filter('input:checked')->count());
self::assertSame(6, $crawler->filter('input:checked')->count());
/** @var FormField $notificationsSenderEmailField */
$notificationsSenderEmailField = $form->get('parameters_form[notificationsSenderEmail]');
@ -69,7 +69,7 @@ final class ParametersControllerTest extends WebTestCase
$crawler = $client->followRedirect();
self::assertResponseIsSuccessful();
self::assertSame(1, $crawler->filter('input:checked')->count());
self::assertSame(2, $crawler->filter('input:checked')->count());
$form = $crawler->selectButton('parameters_form_submit')->form();
/** @var FormField $groupsCreationModeField */

View file

@ -260,6 +260,11 @@
<target>Paramètres de l'instance</target>
</trans-unit>
<trans-unit id="e1qNBMp" resname="parameters.services.h2">
<source>parameters.services.h2</source>
<target>Services</target>
</trans-unit>
<trans-unit id="eNqNAUs" resname="parameters.senders.h2">
<source>parameters.senders.h2</source>
<target>Expéditeur·rice des notifications</target>

View file

@ -6,6 +6,12 @@
</header>
<body>
<!-- notification sender section -->
<trans-unit id="qlPbwB3" resname="parameter.services">
<source>parameter.services</source>
<target>Services activés</target>
</trans-unit>
<!-- notification sender section -->
<trans-unit id="qqTbwBV" resname="parameter.mail">
<source>parameter.mail</source>