fix: dynamic admin group choices (#741)

This commit is contained in:
JacquesDurand 2024-10-01 09:13:51 +02:00 committed by Hugo Nicolas
parent eea58804cd
commit 9167e81da2
No known key found for this signature in database
GPG key ID: 09CB3D93EB8B0E61
6 changed files with 145 additions and 14 deletions

View file

@ -2,7 +2,7 @@ import { Controller} from '@hotwired/stimulus'
/* stimulusFetch: 'lazy' */
export default class extends Controller {
static targets = ['servicesEnabledField', 'parentField', 'idField']
static targets = ['servicesEnabledField', 'parentField', 'idField', 'ownerField']
connect() {
const parentFields = document.querySelectorAll('[data-label="Parent"]')
@ -16,6 +16,17 @@ export default class extends Controller {
}
parentFieldTargetConnected(element) {
// edit page
const parentGroupId = element.value
const servicesEnabledToggle = document.getElementById('Group_servicesEnabled')
this.checkGroupEditDisableServices(parentGroupId, servicesEnabledToggle)
element.addEventListener('change', () => {
const newParentGroupId = element.value
this.checkGroupEditDisableServices(newParentGroupId, servicesEnabledToggle)
})
// list page
const observer = new MutationObserver( ( ) => {
if (element.tomselect) {
observer.disconnect()
@ -65,6 +76,17 @@ export default class extends Controller {
})
}
ownerFieldTargetConnected() {
const initialUserId = this.ownerFieldTarget.value
const groupsField = document.getElementById('Product_groups')
this.replaceGroups(initialUserId, groupsField)
this.ownerFieldTarget.addEventListener('change', () => {
const userId = this.ownerFieldTarget.value
this.replaceGroups(userId, groupsField)
})
}
async checkDisabledServices(tr) {
const id = tr.getAttribute('data-id')
const url = `/api/groups/${id}`
@ -122,4 +144,98 @@ export default class extends Controller {
})
}
async replaceGroups(userId, groupsField) {
const url = `/api/groups?user=${userId}&services_enabled=true&admin=0`
const response = await fetch(url, {method: 'GET'})
if (!response.ok) {
return
}
const data = await response.json()
const groups = data['hydra:member']
const parentDiv = groupsField.parentElement
const smallElement = parentDiv.querySelector('small')
const saveContinue = document.getElementsByClassName('action-saveAndContinue')[0]
const saveReturn = document.getElementsByClassName('action-saveAndReturn')[0]
const saveAdd = document.getElementsByClassName('action-saveAndAddAnother')[0]
groupsField.tomselect.clear()
groupsField.tomselect.clearOptions()
if (groups.length === 0) {
groupsField.tomselect.disable()
groupsField.tomselect.lock()
// show helper
if (null !== smallElement) {
smallElement.style.visibility = 'visible'
}
if (undefined !== saveContinue) {
saveContinue.disabled = true
}
if (undefined !== saveAdd) {
saveAdd.disabled = true
}
saveReturn.disabled = true
} else {
groups.map(group => {
groupsField.tomselect.addOption(new Option(group.name, group.id))
})
groupsField.tomselect.enable()
groupsField.tomselect.unlock()
// remove helper
if (null !== smallElement) {
smallElement.style.visibility = 'hidden'
}
if (undefined !== saveContinue) {
saveContinue.disabled = false
}
if (undefined !== saveAdd) {
saveAdd.disabled = false
}
saveReturn.disabled = false
}
}
async checkGroupEditDisableServices(parentGroupId, servicesEnabledToggle) {
const url = `/api/groups/${parentGroupId}`
const response = await fetch(url, {method: 'GET'})
if (!response.ok) {
return
}
const parentGroup = await response.json()
let parentAll = parentGroup.parentsRecursively
parentAll.push(parentGroup['@id'])
const parentDiv = servicesEnabledToggle.parentElement.parentElement
const smallElement = parentDiv.querySelector('small')
let disabled = false
for (const parentUrl of parentAll) {
const parentResponse = await fetch(parentUrl, { method: 'GET' })
if (!response.ok) {
return
}
const parent = await parentResponse.json()
if (!parent.servicesEnabled) {
servicesEnabledToggle.checked = false
servicesEnabledToggle.disabled = true
if (null !== smallElement) {
smallElement.style.visibility = 'visible'
}
disabled = true
break
}
}
if (!disabled) {
servicesEnabledToggle.disabled = false
if (null !== smallElement) {
smallElement.style.visibility = 'hidden'
}
}
}
}

View file

@ -252,7 +252,12 @@ abstract class AbstractProductCrudController extends AbstractCrudController impl
$groupsField = AssociationField::new('groups')->onlyOnForms();
$groupsFieldList = CollectionField::new('groups')->hideOnForm();
$ownerField = AssociationField::new('owner');
$ownerField = AssociationField::new('owner')
->setFormTypeOption('attr', [
'data-controller' => 'admin-parentgroup',
'data-admin-parentgroup-target' => 'ownerField',
])
->addWebpackEncoreEntries('admin');
$categoryField = AssociationField::new('category')
->setQueryBuilder(function (QueryBuilder $queryBuilder) {
return $this->categoryRepository->addTypeFilter($queryBuilder, $this->getProductType());

View file

@ -303,7 +303,7 @@ final class GroupCrudController extends AbstractCrudController implements GroupA
}
}
}
array_splice($fields, 3, 0, [$servicesEnabledField]);
array_splice($fields, 4, 0, [$servicesEnabledField]);
}
return $fields;
@ -328,7 +328,7 @@ final class GroupCrudController extends AbstractCrudController implements GroupA
];
if ($this->configurationRepository->getInstanceConfigurationOrCreate()->getServicesEnabled()) {
array_splice($fields, 2, 0, [$servicesEnabledField]);
array_splice($fields, 3, 0, [$servicesEnabledField]);
}
return $fields;

View file

@ -78,6 +78,11 @@ final class ServiceCrudController extends AbstractProductCrudController
/** @var ChoiceField $statusField */
$statusField->setChoices(ProductStatus::cases());
$i18prefix = $this->getI18nPrefix(self::class);
/** @var AssociationField $groupsField */
$groupsField->setHelp($i18prefix.'.field.groups.help');
if ($pageName === Crud::PAGE_NEW) {
return [$nameField, $ownerField, $categoryField, $statusField, $groupsField, $descriptionField, $imageField, $durationField];
}
@ -85,7 +90,6 @@ final class ServiceCrudController extends AbstractProductCrudController
$product = $this->getContext()?->getEntity()?->getInstance();
$owner = $product?->getOwner();
if (null !== $owner && !$owner->getUserGroupsConfirmedWithServices()->isEmpty()) {
/** @var AssociationField $groupsField */
$groupsField->setQueryBuilder(function (QueryBuilder $queryBuilder) use ($owner) {
return $queryBuilder
->join('entity.userGroups', 'ug')
@ -98,9 +102,7 @@ final class ServiceCrudController extends AbstractProductCrudController
;
});
} else {
$i18prefix = $this->getI18nPrefix(self::class);
/** @var AssociationField $groupsField */
$groupsField->setHelp($i18prefix.'.field.groups.help')->setDisabled();
$groupsField->setDisabled();
}
return [$nameField, $ownerField, $categoryField, $statusField, $groupsField, $descriptionField, $imageField, $durationField];
@ -114,6 +116,7 @@ final class ServiceCrudController extends AbstractProductCrudController
$categoryField,
$statusField,
$visibilityField,
$groupsFieldList,
$nameField,
$descriptionField,
$durationField,

View file

@ -90,7 +90,7 @@ final class GroupRepository extends ServiceEntityRepository
/**
* @return Group[]
*/
public function getGroupsByEnabledServices(bool $servicesEnabled, ?User $user = null): array
public function getGroupsByEnabledServices(bool $servicesEnabled, ?User $user = null, bool $admin = true): array
{
$qb = $this->createQueryBuilder('g')
->andWhere('g.servicesEnabled = :servicesEnabled')
@ -100,10 +100,15 @@ final class GroupRepository extends ServiceEntityRepository
$qb
->leftJoin('g.userGroups', 'gu')
->andWhere('gu.user = :user')
->setParameter('user', $user);
if ($admin) {
$qb
->andWhere('gu.mainAdminAccount = :mainAdminAccount OR gu.membership = :membership')
->setParameter('user', $user)
->setParameter('mainAdminAccount', true)
->setParameter('membership', UserMembership::ADMIN);
->setParameter('membership', UserMembership::ADMIN)
;
}
}
/** @var Group[] */

View file

@ -26,7 +26,9 @@ class GroupsProvider implements ProviderInterface
if (isset($context['filters']['user'])) { // @phpstan-ignore-line
$user = $this->userRepository->find($context['filters']['user']);
return $this->groupRepository->getGroupsByEnabledServices($context['filters']['services_enabled'] === 'true', $user); // @phpstan-ignore-line
$admin = (bool) ($context['filters']['admin'] ?? true); // @phpstan-ignore-line
return $this->groupRepository->getGroupsByEnabledServices($context['filters']['services_enabled'] === 'true', $user, $admin); // @phpstan-ignore-line
}
return $this->groupRepository->getGroupsByEnabledServices($context['filters']['services_enabled'] === 'true'); // @phpstan-ignore-line