mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
Merge branch 'issue718_workflow_suggest_users' into 'master'
Issue718 workflow suggest users See merge request Chill-Projet/chill-bundles!499
This commit is contained in:
commit
88b4159ced
@ -95,6 +95,16 @@ class AccompanyingCourseDocumentWorkflowHandler implements EntityWorkflowHandler
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getSuggestedUsers(EntityWorkflow $entityWorkflow): array
|
||||
{
|
||||
$suggestedUsers = $entityWorkflow->getUsersInvolved();
|
||||
|
||||
$referrer = $this->getRelatedEntity($entityWorkflow)->getCourse()->getUser();
|
||||
$suggestedUsers[spl_object_hash($referrer)] = $referrer;
|
||||
|
||||
return $suggestedUsers;
|
||||
}
|
||||
|
||||
public function getTemplate(EntityWorkflow $entityWorkflow, array $options = []): string
|
||||
{
|
||||
return '@ChillDocStore/AccompanyingCourseDocument/_workflow.html.twig';
|
||||
|
@ -30,6 +30,7 @@ use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||
use Symfony\Component\Workflow\Registry;
|
||||
use Symfony\Component\Workflow\TransitionBlocker;
|
||||
@ -48,11 +49,13 @@ class WorkflowController extends AbstractController
|
||||
|
||||
private Registry $registry;
|
||||
|
||||
private Security $security;
|
||||
|
||||
private TranslatorInterface $translator;
|
||||
|
||||
private ValidatorInterface $validator;
|
||||
|
||||
public function __construct(EntityWorkflowManager $entityWorkflowManager, EntityWorkflowRepository $entityWorkflowRepository, ValidatorInterface $validator, PaginatorFactory $paginatorFactory, Registry $registry, EntityManagerInterface $entityManager, TranslatorInterface $translator)
|
||||
public function __construct(EntityWorkflowManager $entityWorkflowManager, EntityWorkflowRepository $entityWorkflowRepository, ValidatorInterface $validator, PaginatorFactory $paginatorFactory, Registry $registry, EntityManagerInterface $entityManager, TranslatorInterface $translator, Security $security)
|
||||
{
|
||||
$this->entityWorkflowManager = $entityWorkflowManager;
|
||||
$this->entityWorkflowRepository = $entityWorkflowRepository;
|
||||
@ -61,6 +64,7 @@ class WorkflowController extends AbstractController
|
||||
$this->registry = $registry;
|
||||
$this->entityManager = $entityManager;
|
||||
$this->translator = $translator;
|
||||
$this->security = $security;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -291,10 +295,18 @@ class WorkflowController extends AbstractController
|
||||
|
||||
if (count($workflow->getEnabledTransitions($entityWorkflow)) > 0) {
|
||||
// possible transition
|
||||
|
||||
$usersInvolved = $entityWorkflow->getUsersInvolved();
|
||||
$currentUserFound = array_search($this->security->getUser(), $usersInvolved, true);
|
||||
|
||||
if (false !== $currentUserFound) {
|
||||
unset($usersInvolved[$currentUserFound]);
|
||||
}
|
||||
|
||||
$transitionForm = $this->createForm(
|
||||
WorkflowStepType::class,
|
||||
$entityWorkflow->getCurrentStep(),
|
||||
['transition' => true, 'entity_workflow' => $entityWorkflow]
|
||||
['transition' => true, 'entity_workflow' => $entityWorkflow, 'suggested_users' => $usersInvolved]
|
||||
);
|
||||
|
||||
$transitionForm->handleRequest($request);
|
||||
|
@ -348,6 +348,23 @@ class EntityWorkflow implements TrackCreationInterface, TrackUpdateInterface
|
||||
return $this->transitionningStep;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return User[]
|
||||
*/
|
||||
public function getUsersInvolved(): array
|
||||
{
|
||||
$usersInvolved = [];
|
||||
$usersInvolved[spl_object_hash($this->getCreatedBy())] = $this->getCreatedBy();
|
||||
|
||||
foreach ($this->steps as $step) {
|
||||
foreach ($step->getDestUser() as $u) {
|
||||
$usersInvolved[spl_object_hash($u)] = $u;
|
||||
}
|
||||
}
|
||||
|
||||
return $usersInvolved;
|
||||
}
|
||||
|
||||
public function getWorkflowName(): string
|
||||
{
|
||||
return $this->workflowName;
|
||||
|
@ -19,6 +19,7 @@ use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\Form\FormView;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
||||
use Symfony\Component\Serializer\SerializerInterface;
|
||||
|
||||
/**
|
||||
@ -28,12 +29,15 @@ class PickUserDynamicType extends AbstractType
|
||||
{
|
||||
private DenormalizerInterface $denormalizer;
|
||||
|
||||
private NormalizerInterface $normalizer;
|
||||
|
||||
private SerializerInterface $serializer;
|
||||
|
||||
public function __construct(DenormalizerInterface $denormalizer, SerializerInterface $serializer)
|
||||
public function __construct(DenormalizerInterface $denormalizer, SerializerInterface $serializer, NormalizerInterface $normalizer)
|
||||
{
|
||||
$this->denormalizer = $denormalizer;
|
||||
$this->serializer = $serializer;
|
||||
$this->normalizer = $normalizer;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
@ -46,6 +50,11 @@ class PickUserDynamicType extends AbstractType
|
||||
$view->vars['multiple'] = $options['multiple'];
|
||||
$view->vars['types'] = ['user'];
|
||||
$view->vars['uniqid'] = uniqid('pick_user_dyn');
|
||||
$view->vars['suggested'] = [];
|
||||
|
||||
foreach ($options['suggested'] as $user) {
|
||||
$view->vars['suggested'][] = $this->normalizer->normalize($user, 'json', ['groups' => 'read']);
|
||||
}
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
@ -53,7 +62,8 @@ class PickUserDynamicType extends AbstractType
|
||||
$resolver
|
||||
->setDefault('multiple', false)
|
||||
->setAllowedTypes('multiple', ['bool'])
|
||||
->setDefault('compound', false);
|
||||
->setDefault('compound', false)
|
||||
->setDefault('suggested', []);
|
||||
}
|
||||
|
||||
public function getBlockPrefix()
|
||||
|
@ -154,6 +154,7 @@ class WorkflowStepType extends AbstractType
|
||||
'label' => 'workflow.dest for next steps',
|
||||
'multiple' => true,
|
||||
'mapped' => false,
|
||||
'suggested' => $options['suggested_users'],
|
||||
])
|
||||
->add('future_dest_emails', ChillCollectionType::class, [
|
||||
'label' => 'workflow.dest by email',
|
||||
@ -200,6 +201,7 @@ class WorkflowStepType extends AbstractType
|
||||
->setAllowedTypes('transition', 'bool')
|
||||
->setRequired('entity_workflow')
|
||||
->setAllowedTypes('entity_workflow', EntityWorkflow::class)
|
||||
->setDefault('suggested_users', [])
|
||||
->setDefault('constraints', [
|
||||
new Callback(
|
||||
function ($step, ExecutionContextInterface $context, $payload) {
|
||||
|
@ -23,7 +23,7 @@ function loadDynamicPicker(element) {
|
||||
(input.value === '[]' || input.value === '') ?
|
||||
null : [ JSON.parse(input.value) ]
|
||||
)
|
||||
;
|
||||
suggested = JSON.parse(el.dataset.suggested)
|
||||
|
||||
if (!isMultiple) {
|
||||
if (input.value === '[]'){
|
||||
@ -37,6 +37,7 @@ function loadDynamicPicker(element) {
|
||||
':types="types" ' +
|
||||
':picked="picked" ' +
|
||||
':uniqid="uniqid" ' +
|
||||
':suggested="notPickedSuggested" ' +
|
||||
'@addNewEntity="addNewEntity" ' +
|
||||
'@removeEntity="removeEntity"></pick-entity>',
|
||||
components: {
|
||||
@ -48,16 +49,31 @@ function loadDynamicPicker(element) {
|
||||
types: JSON.parse(el.dataset.types),
|
||||
picked: picked === null ? [] : picked,
|
||||
uniqid: el.dataset.uniqid,
|
||||
suggested: suggested
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
notPickedSuggested() {
|
||||
if (this.multiple) {
|
||||
const pickedIds = new Set();
|
||||
for (const p of this.picked) {
|
||||
pickedIds.add(`${p.type}${p.id}`);
|
||||
}
|
||||
return this.suggested.filter(e => !pickedIds.has(`${e.type}${e.id}`))
|
||||
}
|
||||
|
||||
return this.suggested.filter(e => e.type !== this.picked.type && e.id !== e.picked.id);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
addNewEntity(entity) {
|
||||
addNewEntity({entity}) {
|
||||
if (this.multiple) {
|
||||
if (!this.picked.some(el => {
|
||||
return el.type === entity.type && el.id === entity.id;
|
||||
})) {
|
||||
this.picked.push(entity);
|
||||
input.value = JSON.stringify(this.picked);
|
||||
console.log(entity)
|
||||
}
|
||||
} else {
|
||||
if (!this.picked.some(el => {
|
||||
@ -69,7 +85,10 @@ function loadDynamicPicker(element) {
|
||||
}
|
||||
}
|
||||
},
|
||||
removeEntity(entity) {
|
||||
removeEntity({entity}) {
|
||||
if (-1 === this.suggested.findIndex(e => e.type === entity.type && e.id === entity.id)) {
|
||||
this.suggested.push(entity);
|
||||
}
|
||||
this.picked = this.picked.filter(e => !(e.type === entity.type && e.id === entity.id));
|
||||
input.value = JSON.stringify(this.picked);
|
||||
},
|
||||
|
@ -17,6 +17,9 @@
|
||||
</add-persons>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="list-suggest add-items inline">
|
||||
<li v-for="s in suggested" :key="s.id" @click="addNewSuggested(s)"><span>{{ s.text }}</span></li>
|
||||
</ul>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@ -49,6 +52,10 @@ export default {
|
||||
// display picked entities.
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
suggested: {
|
||||
type: Array,
|
||||
default: []
|
||||
}
|
||||
},
|
||||
emits: ['addNewEntity', 'removeEntity'],
|
||||
@ -96,9 +103,12 @@ export default {
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
addNewSuggested(entity) {
|
||||
this.$emit('addNewEntity', {entity: entity});
|
||||
},
|
||||
addNewEntity({ selected, modal }) {
|
||||
selected.forEach((item) => {
|
||||
this.$emit('addNewEntity', item.result);
|
||||
this.$emit('addNewEntity', { entity: item.result});
|
||||
}, this
|
||||
);
|
||||
this.$refs.addPersons.resetSearch(); // to cast child method
|
||||
@ -108,7 +118,7 @@ export default {
|
||||
if (!this.$props.removableIfSet) {
|
||||
return;
|
||||
}
|
||||
this.$emit('removeEntity', entity);
|
||||
this.$emit('removeEntity',{ entity: entity });
|
||||
}
|
||||
},
|
||||
}
|
||||
|
@ -249,7 +249,11 @@
|
||||
|
||||
{% block pick_entity_dynamic_widget %}
|
||||
<input type="hidden" {{ block('widget_attributes') }} {% if value is not empty %}value="{{ value|escape('html_attr') }}" {% endif %} data-input-uniqid="{{ form.vars['uniqid'] }}"/>
|
||||
<div data-module="pick-dynamic" data-types="{{ form.vars['types']|json_encode }}" data-multiple="{{ form.vars['multiple'] }}" data-uniqid="{{ form.vars['uniqid'] }}"></div>
|
||||
<div data-module="pick-dynamic"
|
||||
data-types="{{ form.vars['types']|json_encode }}"
|
||||
data-multiple="{{ form.vars['multiple'] }}"
|
||||
data-uniqid="{{ form.vars['uniqid'] }}"
|
||||
data-suggested="{{ form.vars['suggested']|json_encode|escape('html_attr') }}"></div>
|
||||
{% endblock %}
|
||||
|
||||
{% block pick_postal_code_widget %}
|
||||
|
@ -36,6 +36,11 @@ interface EntityWorkflowHandlerInterface
|
||||
*/
|
||||
public function getRoleShow(EntityWorkflow $entityWorkflow): ?string;
|
||||
|
||||
/**
|
||||
* @return User[]
|
||||
*/
|
||||
public function getSuggestedUsers(EntityWorkflow $entityWorkflow): array;
|
||||
|
||||
public function getTemplate(EntityWorkflow $entityWorkflow, array $options = []): string;
|
||||
|
||||
public function getTemplateData(EntityWorkflow $entityWorkflow, array $options = []): array;
|
||||
|
@ -18,21 +18,25 @@ use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\Form\FormView;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
||||
use Symfony\Component\Serializer\SerializerInterface;
|
||||
|
||||
/**
|
||||
* Pick user dymically, using vuejs module "AddPerson".
|
||||
* m* Pick user dymically, using vuejs module "AddPerson".
|
||||
*/
|
||||
class PickPersonDynamicType extends AbstractType
|
||||
{
|
||||
private DenormalizerInterface $denormalizer;
|
||||
|
||||
private DenormalizerInterface $normalizer;
|
||||
|
||||
private SerializerInterface $serializer;
|
||||
|
||||
public function __construct(DenormalizerInterface $denormalizer, SerializerInterface $serializer)
|
||||
public function __construct(DenormalizerInterface $denormalizer, SerializerInterface $serializer, NormalizerInterface $normalizer)
|
||||
{
|
||||
$this->denormalizer = $denormalizer;
|
||||
$this->serializer = $serializer;
|
||||
$this->normalizer = $normalizer;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
@ -45,6 +49,11 @@ class PickPersonDynamicType extends AbstractType
|
||||
$view->vars['multiple'] = $options['multiple'];
|
||||
$view->vars['types'] = ['person'];
|
||||
$view->vars['uniqid'] = uniqid('pick_user_dyn');
|
||||
$view->vars['suggested'] = [];
|
||||
|
||||
foreach ($options['suggested'] as $person) {
|
||||
$view->vars['suggested'][] = $this->normalizer->normalize($person, 'json', ['groups' => 'read']);
|
||||
}
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
@ -52,7 +61,8 @@ class PickPersonDynamicType extends AbstractType
|
||||
$resolver
|
||||
->setDefault('multiple', false)
|
||||
->setAllowedTypes('multiple', ['bool'])
|
||||
->setDefault('compound', false);
|
||||
->setDefault('compound', false)
|
||||
->setDefault('suggested', []);
|
||||
}
|
||||
|
||||
public function getBlockPrefix()
|
||||
|
@ -97,6 +97,21 @@ class AccompanyingPeriodWorkEvaluationDocumentWorkflowHandler implements EntityW
|
||||
return AccompanyingPeriodWorkEvaluationDocumentVoter::SEE;
|
||||
}
|
||||
|
||||
public function getSuggestedUsers(EntityWorkflow $entityWorkflow): array
|
||||
{
|
||||
$suggestedUsers = $entityWorkflow->getUsersInvolved();
|
||||
|
||||
$referrer = $this->getRelatedEntity($entityWorkflow)
|
||||
->getAccompanyingPeriodWorkEvaluation()
|
||||
->getAccompanyingPeriodWork()
|
||||
->getAccompanyingPeriod()
|
||||
->getUser();
|
||||
|
||||
$suggestedUsers[spl_object_hash($referrer)] = $referrer;
|
||||
|
||||
return $suggestedUsers;
|
||||
}
|
||||
|
||||
public function getTemplate(EntityWorkflow $entityWorkflow, array $options = []): string
|
||||
{
|
||||
return '@ChillPerson/Workflow/_evaluation_document.html.twig';
|
||||
|
@ -87,6 +87,20 @@ class AccompanyingPeriodWorkEvaluationWorkflowHandler implements EntityWorkflowH
|
||||
return AccompanyingPeriodWorkEvaluationVoter::SEE;
|
||||
}
|
||||
|
||||
public function getSuggestedUsers(EntityWorkflow $entityWorkflow): array
|
||||
{
|
||||
$suggestedUsers = $entityWorkflow->getUsersInvolved();
|
||||
|
||||
$referrer = $this->getRelatedEntity($entityWorkflow)
|
||||
->getAccompanyingPeriodWork()
|
||||
->getAccompanyingPeriod()
|
||||
->getUser();
|
||||
|
||||
$suggestedUsers[spl_object_hash($referrer)] = $referrer;
|
||||
|
||||
return $suggestedUsers;
|
||||
}
|
||||
|
||||
public function getTemplate(EntityWorkflow $entityWorkflow, array $options = []): string
|
||||
{
|
||||
return '@ChillPerson/Workflow/_evaluation.html.twig';
|
||||
|
@ -94,6 +94,19 @@ class AccompanyingPeriodWorkWorkflowHandler implements EntityWorkflowHandlerInte
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getSuggestedUsers(EntityWorkflow $entityWorkflow): array
|
||||
{
|
||||
$suggestedUsers = $entityWorkflow->getUsersInvolved();
|
||||
|
||||
$referrer = $this->getRelatedEntity($entityWorkflow)
|
||||
->getAccompanyingPeriod()
|
||||
->getUser();
|
||||
|
||||
$suggestedUsers[spl_object_hash($referrer)] = $referrer;
|
||||
|
||||
return $suggestedUsers;
|
||||
}
|
||||
|
||||
public function getTemplate(EntityWorkflow $entityWorkflow, array $options = []): string
|
||||
{
|
||||
return '@ChillPerson/Workflow/_accompanying_period_work.html.twig';
|
||||
|
@ -18,6 +18,7 @@ use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\Form\FormView;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
||||
use Symfony\Component\Serializer\SerializerInterface;
|
||||
|
||||
/**
|
||||
@ -27,12 +28,15 @@ class PickThirdpartyDynamicType extends AbstractType
|
||||
{
|
||||
private DenormalizerInterface $denormalizer;
|
||||
|
||||
private NormalizerInterface $normalizer;
|
||||
|
||||
private SerializerInterface $serializer;
|
||||
|
||||
public function __construct(DenormalizerInterface $denormalizer, SerializerInterface $serializer)
|
||||
public function __construct(DenormalizerInterface $denormalizer, SerializerInterface $serializer, NormalizerInterface $normalizer)
|
||||
{
|
||||
$this->denormalizer = $denormalizer;
|
||||
$this->serializer = $serializer;
|
||||
$this->normalizer = $normalizer;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
@ -45,6 +49,11 @@ class PickThirdpartyDynamicType extends AbstractType
|
||||
$view->vars['multiple'] = $options['multiple'];
|
||||
$view->vars['types'] = ['thirdparty'];
|
||||
$view->vars['uniqid'] = uniqid('pick_user_dyn');
|
||||
$view->vars['suggested'] = [];
|
||||
|
||||
foreach ($options['suggested'] as $tp) {
|
||||
$view->vars['suggested'][] = $this->normalizer->normalize($tp, 'json', ['groups' => 'read']);
|
||||
}
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
@ -52,7 +61,8 @@ class PickThirdpartyDynamicType extends AbstractType
|
||||
$resolver
|
||||
->setDefault('multiple', false)
|
||||
->setAllowedTypes('multiple', ['bool'])
|
||||
->setDefault('compound', false);
|
||||
->setDefault('compound', false)
|
||||
->setDefault('suggested', []);
|
||||
}
|
||||
|
||||
public function getBlockPrefix()
|
||||
|
Loading…
x
Reference in New Issue
Block a user