diff --git a/app/AdminModule/ConfigurationModule/Forms/GroupFormFactory.php b/app/AdminModule/ConfigurationModule/Forms/GroupFormFactory.php
index dc7f7681c..87bb5cda0 100644
--- a/app/AdminModule/ConfigurationModule/Forms/GroupFormFactory.php
+++ b/app/AdminModule/ConfigurationModule/Forms/GroupFormFactory.php
@@ -44,7 +44,7 @@ public function __construct(
public function create(): Form
{
$form = $this->baseFormFactory->create();
-
+
$renderer = $form->getRenderer();
assert($renderer instanceof Bs4FormRenderer);
$renderer->wrappers['control']['container'] = 'div class="col-7"';
@@ -60,8 +60,6 @@ public function create(): Form
$groupFillTerm->addRule(Form::FILLED, 'admin.configuration.group_fill_term_empty');
$form->addComponent($groupFillTerm, 'groupFillTerm');
-
-
$form->addSubmit('submit', 'admin.common.save');
$form->setDefaults([
diff --git a/app/AdminModule/GroupsModule/Components/GroupsGridControl.php b/app/AdminModule/GroupsModule/Components/GroupsGridControl.php
index 0ca28d3f3..e1f3dd58b 100644
--- a/app/AdminModule/GroupsModule/Components/GroupsGridControl.php
+++ b/app/AdminModule/GroupsModule/Components/GroupsGridControl.php
@@ -6,18 +6,15 @@
use App\Model\Group\Commands\RemoveGroup;
use App\Model\Group\Commands\SaveGroup;
-use App\Model\Group\Repositories\GroupRepository;
use App\Model\Group\Group;
+use App\Model\Group\Repositories\GroupRepository;
+use App\Model\User\Repositories\UserRepository;
use App\Services\CommandBus;
-use App\Services\ExcelExportService;
-use Exception;
use Nette\Application\AbortException;
use Nette\Application\UI\Control;
use Nette\Application\UI\Form;
use Nette\Forms\Container;
use Nette\Forms\Controls\TextInput;
-use Nette\Http\Session;
-use Nette\Http\SessionSection;
use Nette\Localization\Translator;
use stdClass;
use Ublaboo\DataGrid\DataGrid;
@@ -30,14 +27,11 @@
*/
class GroupsGridControl extends Control
{
- private SessionSection $sessionSection;
-
public function __construct(
private CommandBus $commandBus,
private Translator $translator,
private GroupRepository $groupRepository,
- private ExcelExportService $excelExportService,
- private Session $session,
+ private readonly UserRepository $userRepository,
) {
$this->sessionSection = $session->getSection('srs');
}
@@ -64,12 +58,31 @@ public function createComponentGroupsGrid(string $name): void
$grid->setDefaultSort(['name' => 'ASC']);
$grid->setPagination(false);
+ $grid->addColumnText('name', 'admin.groups.group.column.name');
+
+ $grid->addColumnText('group_status', 'admin.groups.group.column.group_status');
- $grid->addColumnText('name', 'admin.program.groups.column.name');
+ $grid->addColumnText('leader_id', 'admin.groups.group.column.leader_name')
+ ->setRenderer(function (Group $row) {
+ $user = $this->userRepository->findById($row->getLeaderId());
- $grid->addColumnText('leader_email', 'admin.program.groups.column.name');
- $grid->addColumnText('places', 'admin.program.groups.column.name');
- $grid->addColumnText('price', 'admin.program.groups.column.name');
+ return $user->getFirstName() . ' ' . $user->getLastName();
+ })
+/*
+ ->setRenderer(static fn (Group $row) => Html::el('span')
+ ->setText(
+ $user = $this->userRepository->findById((int) $id);
+ $this->userService->setApproved($user, (bool) $approved);
+ $row->getEmail();
+ )
+ )
+*/
+ ->setFilterText();
+
+ $grid->addColumnText('leader_email', 'admin.groups.group.column.leader_email');
+ $grid->addColumnText('places', 'admin.groups.group.column.places');
+
+ $grid->addColumnText('price', 'admin.groups.group.column.price');
$grid->addInlineAdd()->setPositionTop()->onControlAdd[] = function (Container $container): void {
$container->addText('name', '')
@@ -93,7 +106,7 @@ public function createComponentGroupsGrid(string $name): void
$grid->getInlineEdit()->onSetDefaults[] = function (Container $container, Group $item): void {
$nameText = $container['name'];
assert($nameText instanceof TextInput);
- $nameText->addRule(Form::IS_NOT_IN, 'admin.program.groups.column.name_exists', $this->groupRepository->findOthersNames($item->getId()));
+ $nameText->addRule(Form::IS_NOT_IN, 'admin.program.groups.column.name_exists', $this->groupRepository->findAll());
$container->setDefaults([
'name' => $item->getName(),
@@ -161,6 +174,4 @@ public function handleDelete(int $id): void
$p->flashMessage('admin.program.groups.message.delete_success', 'success');
$p->redirect('this');
}
-
-
}
diff --git a/app/AdminModule/GroupsModule/Components/StatusGridControl.php b/app/AdminModule/GroupsModule/Components/StatusGridControl.php
index 1e5bd3bc3..9b340fc90 100644
--- a/app/AdminModule/GroupsModule/Components/StatusGridControl.php
+++ b/app/AdminModule/GroupsModule/Components/StatusGridControl.php
@@ -5,11 +5,10 @@
namespace App\AdminModule\GroupsModule\Components;
use App\Model\Acl\Repositories\RoleRepository;
-use App\Model\Acl\Role;
-use App\Model\Group\Status;
use App\Model\Group\Commands\RemoveStatus;
use App\Model\Group\Commands\SaveStatus;
use App\Model\Group\Repositories\StatusRepository;
+use App\Model\Group\Status;
use App\Services\AclService;
use App\Services\CommandBus;
use Nette\Application\AbortException;
@@ -30,7 +29,7 @@
*/
class StatusGridControl extends Control
{
- public function __construct(private CommandBus $commandBus, private Translator $translator, private StatusRepository $statusRepository, private RoleRepository $roleRepository, private AclService $aclService)
+ public function __construct(private CommandBus $commandBus, private Translator $translator, private StatusRepository $statusRepository)
{
}
@@ -62,14 +61,12 @@ public function createComponentStatusGrid(string $name): void
$container->addText('name', '')
->addRule(Form::FILLED, 'admin.groups.status.column.name_empty')
->addRule(Form::IS_NOT_IN, 'admin.groups.status.column.name_exists', $this->statusRepository->findAllNames());
-
};
$grid->getInlineAdd()->onSubmit[] = [$this, 'add'];
$grid->addInlineEdit()->onControlAdd[] = static function (Container $container): void {
$container->addText('name', '')
->addRule(Form::FILLED, 'admin.groups.status.column.name_empty');
-
};
$grid->getInlineEdit()->onSetDefaults[] = function (Container $container, Status $item): void {
$nameText = $container['name'];
@@ -97,8 +94,7 @@ public function createComponentStatusGrid(string $name): void
*/
public function add(stdClass $values): void
{
- $status = new Status($values->name);
-
+ $status = new Status();
$this->commandBus->handle(new SaveStatus($status));
@@ -136,12 +132,8 @@ public function handleDelete(int $id): void
$p = $this->getPresenter();
- if ($status->getBlocks()->isEmpty()) {
- $this->commandBus->handle(new RemoveStatus($status));
- $p->flashMessage('admin.groups.status.message.delete_success', 'success');
- } else {
- $p->flashMessage('admin.groups.status.message.delete_failed', 'danger');
- }
+ $this->commandBus->handle(new RemoveStatus($status));
+ $p->flashMessage('admin.groups.status.message.delete_success', 'success');
$p->redirect('this');
}
diff --git a/app/AdminModule/GroupsModule/Presenters/GroupsPresenter.php b/app/AdminModule/GroupsModule/Presenters/GroupsPresenter.php
index d1e233206..cd72f22f1 100644
--- a/app/AdminModule/GroupsModule/Presenters/GroupsPresenter.php
+++ b/app/AdminModule/GroupsModule/Presenters/GroupsPresenter.php
@@ -4,8 +4,8 @@
namespace App\AdminModule\GroupsModule\Presenters;
-use App\AdminModule\GroupsModule\Components\IGroupsGridControlFactory;
use App\AdminModule\GroupsModule\Components\GroupsGridControl;
+use App\AdminModule\GroupsModule\Components\IGroupsGridControlFactory;
use App\Model\Acl\Permission;
use App\Model\Group\Repositories\GroupRepository;
use Nette\Application\AbortException;
@@ -22,7 +22,6 @@ class GroupsPresenter extends GroupsBasePresenter
#[Inject]
public IGroupsGridControlFactory $groupsGridControlFactory;
-
/** @throws AbortException */
public function startup(): void
{
diff --git a/app/AdminModule/Presenters/templates/Dashboard/default.latte b/app/AdminModule/Presenters/templates/Dashboard/default.latte
index 824a60db1..3dedffe49 100644
--- a/app/AdminModule/Presenters/templates/Dashboard/default.latte
+++ b/app/AdminModule/Presenters/templates/Dashboard/default.latte
@@ -206,6 +206,11 @@
{_admin.configuration.menu.skautis}
+
+
+ {if $guestRole}
+
+
+ {elseif $groupLeaderRole}
+
+
+
+ {_web.application_content.approved_registration, ['roles' => $dbUser->getRolesText()]}
+
+
+
+
+
+
+
+ Název skupiny: {$group->getName()}
+
+
+ Status: {$group->getGroupStatus()}
+
+
+ Max pocet mist: {$group->getPlaces()}
+
+
+ Kod: {$group->getCode()}
+
+
+ Pocet clenu: {$groupUsersCount}
+
+
+ Pocet volnych mist: {($group->getPlaces())-$groupUsersCount}
+
+
+
+
+
+
+
+ {control groupUsersGrid}
+
+
+ {elseif $groupMemberRole}
+
+
+
+ {_web.application_content.approved_registration, ['roles' => $dbUser->getRolesText()]}
+
+
+
+
+
+
+
+ Název skupiny: {$group->getName()}
+
+
+ Status: {$group->getGroupStatus()}
+
+
+ Vedoucí: {$groupLeaderName}
+
+
+ Email vedoucího: {$group->getLeaderEmail()}
+
+
+
+
+
+ {elseif $nonregisteredRole}
+ {if $noRegisterableRole}
+
+
+
+ {if $registrationStart && $registrationEnd}
+ {_web.application_content.no_registerable_role_start_end, ['start' => $registrationStart->format('j. n. Y H:i'), 'end' => $registrationEnd->format('j. n. Y H:i')]}
+ {elseif $registrationStart}
+ {_web.application_content.no_registerable_role_start, ['start' => $registrationStart->format('j. n. Y H:i')]}
+ {elseif $registrationEnd}
+ {_web.application_content.no_registerable_role_end, ['end' => $registrationEnd->format('j. n. Y H:i')]}
+ {else}
+ {_web.application_content.no_registerable_role}
+ {/if}
+
+
+
+ {else}
+
+
+
+ {control applicationGroupForm}
+
+
+
+ {/if}
+ {else}
+ {if $unapprovedRole}
+
+
+
+ {_web.application_content.unapproved_registration, ['roles' => $dbUser->getRolesText()]}
+
+
+
+ {else}
+
+
+
+ {_web.application_content.approved_registration, ['roles' => $dbUser->getRolesText()]}
+
+
+
+
+
+ {control applicationsGrid}
+
+
+ {/if}
+ {/if}
+
diff --git a/app/WebModule/Components/templates/application_group_content_scripts.latte b/app/WebModule/Components/templates/application_group_content_scripts.latte
new file mode 100644
index 000000000..db92a4b7d
--- /dev/null
+++ b/app/WebModule/Components/templates/application_group_content_scripts.latte
@@ -0,0 +1,46 @@
+
diff --git a/app/WebModule/Components/templates/groupUsers_grid.latte b/app/WebModule/Components/templates/groupUsers_grid.latte
new file mode 100644
index 000000000..44d7f0ef3
--- /dev/null
+++ b/app/WebModule/Components/templates/groupUsers_grid.latte
@@ -0,0 +1 @@
+{control groupUsersGrid}
diff --git a/app/WebModule/Forms/ApplicationGroupFormFactory.php b/app/WebModule/Forms/ApplicationGroupFormFactory.php
new file mode 100644
index 000000000..9024ab2b6
--- /dev/null
+++ b/app/WebModule/Forms/ApplicationGroupFormFactory.php
@@ -0,0 +1,674 @@
+user = $user;
+
+ $form = $this->baseFormFactory->create();
+
+ $inputSex = $form->addRadioList('sex', 'web.application_content.sex', Sex::getSexOptions());
+
+ $inputFirstName = $form->addText('firstName', 'web.application_content.firstname')
+ ->addRule(Form::FILLED, 'web.application_content.firstname_empty');
+
+ $inputLastName = $form->addText('lastName', 'web.application_content.lastname')
+ ->addRule(Form::FILLED, 'web.application_content.lastname_empty');
+
+ $inputNickName = $form->addText('nickName', 'web.application_content.nickname');
+
+ $inputBirthdateDate = new DateControl('web.application_content.birthdate');
+ $inputBirthdateDate->addRule(Form::FILLED, 'web.application_content.birthdate_empty');
+ $form->addComponent($inputBirthdateDate, 'birthdate');
+
+ if ($this->user->isMember()) {
+ $inputSex->setDisabled();
+ $inputFirstName->setDisabled();
+ $inputLastName->setDisabled();
+ $inputNickName->setDisabled();
+ $inputBirthdateDate->setDisabled();
+ }
+
+ $form->addText('email', 'web.application_content.email')
+ ->setDisabled();
+
+ $form->addText('phone', 'web.application_content.phone')
+ ->setDisabled();
+
+ $form->addText('street', 'web.application_content.street')
+ ->addRule(Form::FILLED, 'web.application_content.street_empty')
+ ->addRule(Form::PATTERN, 'web.application_content.street_format', '^(.*[^0-9]+) (([1-9][0-9]*)/)?([1-9][0-9]*[a-cA-C]?)$');
+
+ $form->addText('city', 'web.application_content.city')
+ ->addRule(Form::FILLED, 'web.application_content.city_empty');
+
+ $form->addText('postcode', 'web.application_content.postcode')
+ ->addRule(Form::FILLED, 'web.application_content.postcode_empty')
+ ->addRule(Form::PATTERN, 'web.application_content.postcode_format', '^\d{3} ?\d{2}$');
+
+ $form->addText('state', 'web.application_content.state')
+ ->addRule(Form::FILLED, 'web.application_content.state_empty');
+
+ $form->addSelect('roles', 'web.application_content.roles', [9 => 'Vedoucí skupiny', 10 => 'Člen skupiny'])
+ ->addCondition($form::EQUAL, 9)
+ ->toggle('group-name')
+ ->toggle('group-members-count')
+ ->elseCondition($form::EQUAL, 10)
+ ->toggle('group-code')
+
+ ->addRule(Form::FILLED, 'web.application_content.custom_input_empty');
+
+ $form->addText('groupName', 'groupName')
+ ->setOption('id', 'group-name')
+ ->addCondition(Form::FILLED);
+
+ $form->addText('groupMembersCount', 'groupMembersCount')
+ ->setOption('id', 'group-members-count')
+ ->addCondition(Form::FILLED);
+
+ $form->addText('groupCode', 'groupCode')
+ ->setOption('id', 'group-code')
+ ->addCondition(Form::FILLED);
+
+// $this->addRolesSelect($form);
+
+// $this->addSubeventsSelect($form);
+
+// $this->addCustomInputs($form);
+
+ $form->addCheckbox('agreement', $this->queryBus->handle(new SettingStringValueQuery(Settings::APPLICATION_AGREEMENT)))
+ ->addRule(Form::FILLED, 'web.application_content.agreement_empty');
+
+ $form->addSubmit('submit', 'web.application_content.register');
+
+ $form->setDefaults([
+ 'sex' => $this->user->getSex(),
+ 'firstName' => $this->user->getFirstName(),
+ 'lastName' => $this->user->getLastName(),
+ 'nickName' => $this->user->getNickName(),
+ 'birthdate' => $this->user->getBirthdate(),
+ 'email' => $this->user->getEmail(),
+ 'phone' => $this->user->getPhone(),
+ 'street' => $this->user->getStreet(),
+ 'city' => $this->user->getCity(),
+ 'postcode' => $this->user->getPostcode(),
+ 'state' => $this->user->getState(),
+ ]);
+
+ $form->onSuccess[] = [$this, 'processForm'];
+
+ return $form;
+ }
+
+ /**
+ * Zpracuje formulář.
+ *
+ * @throws Throwable
+ */
+ public function processForm(Form $form, stdClass $values): void
+ {
+ $this->em->wrapInTransaction(function () use ($values): void {
+ if (property_exists($values, 'sex')) {
+ $this->user->setSex($values->sex);
+ }
+
+ if (property_exists($values, 'firstName')) {
+ $this->user->setFirstName($values->firstName);
+ }
+
+ if (property_exists($values, 'lastName')) {
+ $this->user->setLastName($values->lastName);
+ }
+
+ if (property_exists($values, 'nickName')) {
+ $this->user->setNickName($values->nickName);
+ }
+
+ if (property_exists($values, 'birthdate')) {
+ $this->user->setBirthdate($values->birthdate);
+ }
+
+ $this->user->setStreet($values->street);
+ $this->user->setCity($values->city);
+ $this->user->setPostcode($values->postcode);
+ $this->user->setState($values->state);
+
+/*
+ // role
+ if (property_exists($values, 'roles')) {
+ $roles = $this->roleRepository->findRolesByIds($values->roles);
+ } else {
+ $roles = $this->roleRepository->findFilteredRoles(true, false, false);
+ }
+*/
+ //group akce
+ switch ($values->roles) {
+ //vedouci skupiny
+ case 9:
+ if (property_exists($values, 'groupName') && (property_exists($values, 'groupMembersCount'))) {
+ $group = new Group();
+
+ $group->setName($values->groupName);
+ $group->setLeaderId($this->user->getId());
+ $group->setLeaderEmail($this->user->getEmail());
+ $group->setPlaces($values->groupMembersCount);
+ $group->setGroupStatus('waiting_for_filling');
+
+ $this->groupRepository->save($group);
+
+ $groupGeneratedCode = $group->getId() . time();
+ $group->setCode($groupGeneratedCode);
+
+ $this->groupRepository->save($group);
+
+ $this->user->setGroupId($group->getId());
+
+ $userRole = $this->roleRepository->findById($values->roles);
+ $this->user->addRole($userRole);
+ }
+
+ break;
+
+ //clen skupiny
+ case 10:
+ if (property_exists($values, 'groupCode')) {
+ $group = $this->groupRepository->findByCode($values->groupCode);
+ if (! $group) {
+ throw new InvalidArgumentException('Invalid code.');
+ }
+
+ $this->user->setGroupId($group->getId());
+ $userRole = $this->roleRepository->findById($values->roles);
+ $this->user->addRole($userRole);
+ }
+
+ break;
+ }
+
+/*
+ // vlastni pole
+ foreach ($this->customInputRepository->findByRolesOrderedByPosition($roles) as $customInput) {
+ $customInputId = 'custom' . $customInput->getId();
+ $customInputValue = $this->user->getCustomInputValue($customInput);
+
+ if ($customInput instanceof CustomText) {
+ $customInputValue = $customInputValue ?: new CustomTextValue($customInput, $this->user);
+ assert($customInputValue instanceof CustomTextValue);
+ $customInputValue->setValue($values->$customInputId);
+ } elseif ($customInput instanceof CustomCheckbox) {
+ $customInputValue = $customInputValue ?: new CustomCheckboxValue($customInput, $this->user);
+ assert($customInputValue instanceof CustomCheckboxValue);
+ $customInputValue->setValue($values->$customInputId);
+ } elseif ($customInput instanceof CustomSelect) {
+ $customInputValue = $customInputValue ?: new CustomSelectValue($customInput, $this->user);
+ assert($customInputValue instanceof CustomSelectValue);
+ $customInputValue->setValue($values->$customInputId);
+ } elseif ($customInput instanceof CustomMultiSelect) {
+ $customInputValue = $customInputValue ?: new CustomMultiSelectValue($customInput, $this->user);
+ assert($customInputValue instanceof CustomMultiSelectValue);
+ $customInputValue->setValue($values->$customInputId);
+ } elseif ($customInput instanceof CustomFile) {
+ $customInputValue = $customInputValue ?: new CustomFileValue($customInput, $this->user);
+ assert($customInputValue instanceof CustomFileValue);
+ $file = $values->$customInputId;
+ assert($file instanceof FileUpload);
+ if ($file->getError() === UPLOAD_ERR_OK) {
+ $path = $this->filesService->save($file, CustomFile::PATH, true, $file->name);
+ $customInputValue->setValue($path);
+ }
+ } elseif ($customInput instanceof CustomDate) {
+ $customInputValue = $customInputValue ?: new CustomDateValue($customInput, $this->user);
+ assert($customInputValue instanceof CustomDateValue);
+ $customInputValue->setValue($values->$customInputId);
+ } elseif ($customInput instanceof CustomDateTime) {
+ $customInputValue = $customInputValue ?: new CustomDateTimeValue($customInput, $this->user);
+ assert($customInputValue instanceof CustomDateTimeValue);
+ $customInputValue->setValue($values->$customInputId);
+ }
+
+ $this->customInputValueRepository->save($customInputValue);
+ }
+*/
+ // podakce
+ $subevents = '';
+/*
+ $subevents = $this->subeventRepository->explicitSubeventsExists() && ! empty($values->subevents)
+ ? $this->subeventRepository->findSubeventsByIds($values->subevents)
+ : new ArrayCollection([$this->subeventRepository->findImplicit()]);
+*/
+ // aktualizace údajů ve skautIS, jen pokud nemá propojený účet
+ if (! $this->user->isMember()) {
+ try {
+ $this->skautIsService->updatePersonBasic(
+ $this->user->getSkautISPersonId(),
+ $this->user->getSex(),
+ $this->user->getBirthdate(),
+ $this->user->getFirstName(),
+ $this->user->getLastName(),
+ $this->user->getNickName(),
+ );
+
+ $this->skautIsService->updatePersonAddress(
+ $this->user->getSkautISPersonId(),
+ $this->user->getStreet(),
+ $this->user->getCity(),
+ $this->user->getPostcode(),
+ $this->user->getState(),
+ );
+ } catch (WsdlException $ex) {
+ Debugger::log($ex, ILogger::WARNING);
+ $this->onSkautIsError();
+ }
+ }
+
+ // vytvoreni prihlasky
+// $this->applicationGroupService->register($this->user, $roles, $this->user);
+// $this->applicationGroupService->register_group($this->user, $roles, $this->user, $group);
+ });
+ }
+
+ /**
+ * Přidá vlastní pole přihlášky.
+ */
+ private function addCustomInputs(Form $form): void
+ {
+ foreach ($this->customInputRepository->findAllOrderedByPosition() as $customInput) {
+ $customInputId = 'custom' . $customInput->getId();
+ $customInputName = $customInput->getName();
+
+ switch (true) {
+ case $customInput instanceof CustomText:
+ $custom = $form->addText($customInputId, $customInputName);
+ break;
+
+ case $customInput instanceof CustomCheckbox:
+ $custom = $form->addCheckbox($customInputId, $customInputName);
+ break;
+
+ case $customInput instanceof CustomSelect:
+ $custom = $form->addSelect($customInputId, $customInputName, $customInput->getSelectOptions());
+ break;
+
+ case $customInput instanceof CustomMultiSelect:
+ $custom = $form->addMultiSelect($customInputId, $customInputName, $customInput->getSelectOptions());
+ break;
+
+ case $customInput instanceof CustomFile:
+ $custom = $form->addUpload($customInputId, $customInputName);
+ $custom->setHtmlAttribute('data-show-preview', 'true');
+ break;
+
+ case $customInput instanceof CustomDate:
+ $custom = new DateControl($customInputName);
+ $form->addComponent($custom, $customInputId);
+ break;
+
+ case $customInput instanceof CustomDateTime:
+ $custom = new DateTimeControl($customInputName);
+ $form->addComponent($custom, $customInputId);
+ break;
+
+ default:
+ throw new InvalidArgumentException();
+ }
+
+ $custom->setOption('id', 'form-group-' . $customInputId);
+
+ if ($customInput->isMandatory()) {
+ $rolesSelect = $form['roles'];
+ assert($rolesSelect instanceof MultiSelectBox);
+ $custom->addConditionOn($rolesSelect, self::class . '::toggleCustomInputRequired', ['id' => $customInputId, 'roles' => Helpers::getIds($customInput->getRoles())])
+ ->addRule(Form::FILLED, 'web.application_content.custom_input_empty');
+ }
+ }
+ }
+
+ /**
+ * Přidá select pro výběr podakcí.
+ *
+ * @throws NonUniqueResultException
+ * @throws NoResultException
+ */
+ private function addSubeventsSelect(Form $form): void
+ {
+ if (! $this->subeventRepository->explicitSubeventsExists()) {
+ return;
+ }
+
+ $subeventsOptions = $this->subeventService->getSubeventsOptionsWithCapacity(true, true, false, false);
+
+ $subeventsSelect = $form->addMultiSelect('subevents', 'web.application_content.subevents')->setItems(
+ $subeventsOptions,
+ );
+ $subeventsSelect->setOption('id', 'form-group-subevents');
+
+ $rolesSelect = $form['roles'];
+ assert($rolesSelect instanceof MultiSelectBox);
+ $subeventsSelect->addConditionOn(
+ $rolesSelect,
+ self::class . '::toggleSubeventsRequired',
+ Helpers::getIds($this->roleRepository->findFilteredRoles(false, true, false)),
+ )->addRule(Form::FILLED, 'web.application_content.subevents_empty');
+
+ $subeventsSelect
+ ->setRequired(false)
+ ->addRule([$this, 'validateSubeventsCapacities'], 'web.application_content.subevents_capacity_occupied');
+
+ // generovani chybovych hlasek pro vsechny kombinace podakci
+ foreach ($this->subeventRepository->findFilteredSubevents(true, false, false, false) as $subevent) {
+ if (! $subevent->getIncompatibleSubevents()->isEmpty()) {
+ $subeventsSelect->addRule(
+ [$this, 'validateSubeventsIncompatible'],
+ $this->translator->translate(
+ 'web.application_content.incompatible_subevents_selected',
+ null,
+ ['subevent' => $subevent->getName(), 'incompatibleSubevents' => $subevent->getIncompatibleSubeventsText()],
+ ),
+ [$subevent],
+ );
+ }
+
+ if (! $subevent->getRequiredSubeventsTransitive()->isEmpty()) {
+ $subeventsSelect->addRule(
+ [$this, 'validateSubeventsRequired'],
+ $this->translator->translate(
+ 'web.application_content.required_subevents_not_selected',
+ null,
+ ['subevent' => $subevent->getName(), 'requiredSubevents' => $subevent->getRequiredSubeventsTransitiveText()],
+ ),
+ [$subevent],
+ );
+ }
+ }
+ }
+
+ /**
+ * Přidá select pro výběr rolí.
+ */
+ private function addRolesSelect(Form $form): void
+ {
+ $registerableOptions = $this->aclService->getRolesOptionsWithCapacity(true, false);
+
+ $rolesSelect = $form->addMultiSelect('roles', 'web.application_content.roles')->setItems(
+ $registerableOptions,
+ );
+
+ foreach ($this->customInputRepository->findAll() as $customInput) {
+ $customInputId = 'custom' . $customInput->getId();
+ $rolesSelect->addCondition(self::class . '::toggleCustomInputVisibility', Helpers::getIds($customInput->getRoles()))
+ ->toggle('form-group-' . $customInputId);
+ }
+
+ $rolesSelect->addRule(Form::FILLED, 'web.application_content.roles_empty')
+ ->addRule([$this, 'validateRolesCapacities'], 'web.application_content.roles_capacity_occupied')
+ ->addRule([$this, 'validateRolesRegisterable'], 'web.application_content.roles_not_registerable')
+ ->addRule([$this, 'validateRolesMinimumAge'], 'web.application_content.roles_require_minimum_age');
+
+ // generovani chybovych hlasek pro vsechny kombinace roli
+ foreach ($this->roleRepository->findFilteredRoles(true, false, true, $this->user) as $role) {
+ if (! $role->getIncompatibleRoles()->isEmpty()) {
+ $rolesSelect->addRule(
+ [$this, 'validateRolesIncompatible'],
+ $this->translator->translate(
+ 'web.application_content.incompatible_roles_selected',
+ null,
+ ['role' => $role->getName(), 'incompatibleRoles' => $role->getIncompatibleRolesText()],
+ ),
+ [$role],
+ );
+ }
+
+ if (! $role->getRequiredRolesTransitive()->isEmpty()) {
+ $rolesSelect->addRule(
+ [$this, 'validateRolesRequired'],
+ $this->translator->translate(
+ 'web.application_content.required_roles_not_selected',
+ null,
+ ['role' => $role->getName(), 'requiredRoles' => $role->getRequiredRolesTransitiveText()],
+ ),
+ [$role],
+ );
+ }
+ }
+
+ // pokud je na vyber jen jedna role, je oznacena
+ if (count($registerableOptions) === 1) {
+ $rolesSelect->setDisabled();
+ $rolesSelect->setDefaultValue(array_keys($registerableOptions));
+ }
+ }
+
+ /**
+ * Ověří kapacity podakcí.
+ */
+ public function validateSubeventsCapacities(MultiSelectBox $field): bool
+ {
+ $selectedSubevents = $this->subeventRepository->findSubeventsByIds($field->getVaLue());
+
+ return $this->validators->validateSubeventsCapacities($selectedSubevents, $this->user);
+ }
+
+ /**
+ * Ověří kapacity rolí.
+ */
+ public function validateRolesCapacities(MultiSelectBox $field): bool
+ {
+ $selectedRoles = $this->roleRepository->findRolesByIds($field->getValue());
+
+ return $this->validators->validateRolesCapacities($selectedRoles, $this->user);
+ }
+
+ /**
+ * Ověří kompatibilitu podakcí.
+ *
+ * @param Subevent[] $args
+ */
+ public function validateSubeventsIncompatible(MultiSelectBox $field, array $args): bool
+ {
+ $selectedSubevents = $this->subeventRepository->findSubeventsByIds($field->getValue());
+ $testSubevent = $args[0];
+
+ return $this->validators->validateSubeventsIncompatible($selectedSubevents, $testSubevent);
+ }
+
+ /**
+ * Ověří výběr požadovaných podakcí.
+ *
+ * @param Subevent[] $args
+ */
+ public function validateSubeventsRequired(MultiSelectBox $field, array $args): bool
+ {
+ $selectedSubevents = $this->subeventRepository->findSubeventsByIds($field->getValue());
+ $testSubevent = $args[0];
+
+ return $this->validators->validateSubeventsRequired($selectedSubevents, $testSubevent);
+ }
+
+ /**
+ * Ověří kompatibilitu rolí.
+ *
+ * @param Role[] $args
+ */
+ public function validateRolesIncompatible(MultiSelectBox $field, array $args): bool
+ {
+ $selectedRoles = $this->roleRepository->findRolesByIds($field->getValue());
+ $testRole = $args[0];
+
+ return $this->validators->validateRolesIncompatible($selectedRoles, $testRole);
+ }
+
+ /**
+ * Ověří výběr požadovaných rolí.
+ *
+ * @param Role[] $args
+ */
+ public function validateRolesRequired(MultiSelectBox $field, array $args): bool
+ {
+ $selectedRoles = $this->roleRepository->findRolesByIds($field->getValue());
+ $testRole = $args[0];
+
+ return $this->validators->validateRolesRequired($selectedRoles, $testRole);
+ }
+
+ /**
+ * Ověří registrovatelnost rolí.
+ */
+ public function validateRolesRegisterable(MultiSelectBox $field): bool
+ {
+ $selectedRoles = $this->roleRepository->findRolesByIds($field->getValue());
+
+ return $this->validators->validateRolesRegisterable($selectedRoles, $this->user);
+ }
+
+ /**
+ * Ověří požadovaný minimální věk.
+ *
+ * @throws SettingsItemNotFoundException
+ * @throws Throwable
+ */
+ public function validateRolesMinimumAge(MultiSelectBox $field): bool
+ {
+ $selectedRoles = $this->roleRepository->findRolesByIds($field->getValue());
+
+ return $this->validators->validateRolesMinimumAge($selectedRoles, $this->user);
+ }
+
+ /**
+ * Přepíná povinnost podakcí podle kombinace rolí.
+
+ * @param int[] $rolesWithSubevents
+ */
+ public static function toggleSubeventsRequired(MultiSelectBox $field, array $rolesWithSubevents): bool
+ {
+ foreach ($field->getValue() as $roleId) {
+ if (in_array($roleId, $rolesWithSubevents)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Přepíná povinnost vlastních polí podle kombinace rolí.
+ *
+ * @param array