Update the form to allow sending a workflow to an external destinee

OP#734 Modification du formulaire pour permettre l'envoi d'un workflow

https://champs-libres.openproject.com/work_packages/734
This commit is contained in:
Julien Fastré 2024-10-03 17:29:27 +02:00
parent da6589ba87
commit 071c5e3c55
Signed by: julienfastre
GPG Key ID: BDE2190974723FCB
7 changed files with 100 additions and 1 deletions

View File

@ -462,6 +462,13 @@ class EntityWorkflow implements TrackCreationInterface, TrackUpdateInterface
}
}
foreach ($transitionContextDTO->futureDestineeThirdParties as $thirdParty) {
new EntityWorkflowSend($newStep, $thirdParty, $transitionAt->add(new \DateInterval('P30D')));
}
foreach ($transitionContextDTO->futureDestineeEmails as $email) {
new EntityWorkflowSend($newStep, $email, $transitionAt->add(new \DateInterval('P30D')));
}
// copy the freeze
if ($this->isFreeze()) {
$newStep->setFreezeAfter(true);

View File

@ -115,6 +115,7 @@ class EntityWorkflowStep
/**
* @var Collection<int, EntityWorkflowSend>
*/
#[ORM\OneToMany(mappedBy: 'entityWorkflowStep', targetEntity: EntityWorkflowSend::class, cascade: ['persist'], orphanRemoval: true)]
private Collection $sends;
public function __construct()

View File

@ -12,14 +12,17 @@ declare(strict_types=1);
namespace Chill\MainBundle\Form;
use Chill\MainBundle\Entity\Workflow\EntityWorkflow;
use Chill\MainBundle\Form\Type\ChillCollectionType;
use Chill\MainBundle\Form\Type\ChillTextareaType;
use Chill\MainBundle\Form\Type\PickUserDynamicType;
use Chill\MainBundle\Form\Type\PickUserGroupOrUserDynamicType;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Chill\MainBundle\Workflow\WorkflowTransitionContextDTO;
use Chill\PersonBundle\Form\Type\PickPersonDynamicType;
use Chill\ThirdPartyBundle\Form\Type\PickThirdpartyDynamicType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints\Callback;
@ -101,6 +104,7 @@ class WorkflowStepType extends AbstractType
$toFinal = true;
$isForward = 'neutral';
$isSignature = [];
$isSentExternal = false;
$metadata = $workflow->getMetadataStore()->getTransitionMetadata($transition);
@ -124,6 +128,8 @@ class WorkflowStepType extends AbstractType
if (\array_key_exists('isSignature', $meta)) {
$isSignature = $meta['isSignature'];
}
$isSentExternal = $isSentExternal ? true : $meta['isSentExternal'] ?? false;
}
return [
@ -131,6 +137,7 @@ class WorkflowStepType extends AbstractType
'data-to-final' => $toFinal ? '1' : '0',
'data-is-forward' => $isForward,
'data-is-signature' => json_encode($isSignature),
'data-is-sent-external' => $isSentExternal ? '1' : '0',
];
},
])
@ -166,6 +173,24 @@ class WorkflowStepType extends AbstractType
'suggested' => $options['suggested_users'],
'empty_data' => '[]',
'attr' => ['class' => 'future-cc-users'],
])
->add('futureDestineeEmails', ChillCollectionType::class, [
'entry_type' => EmailType::class,
'entry_options' => [
'empty_data' => '',
],
'allow_add' => true,
'allow_delete' => true,
'delete_empty' => static fn (?string $email) => '' === $email || null === $email,
'button_add_label' => 'workflow.transition_destinee_add_emails',
'button_remove_label' => 'workflow.transition_destinee_remove_emails',
'help' => 'workflow.transition_destinee_emails_help',
'label' => 'workflow.transition_destinee_emails_label',
])
->add('futureDestineeThirdParties', PickThirdpartyDynamicType::class, [
'label' => 'workflow.transition_destinee_third_party',
'help' => 'workflow.transition_destinee_third_party_help',
'multiple' => true,
]);
$builder

View File

@ -11,7 +11,8 @@ window.addEventListener('DOMContentLoaded', function() {
userChoice = document.querySelector('#workflow_step_isPersonOrUserSignature_1'),
signatureZone = document.querySelector('#signature-zone'),
transitionFilterContainer = document.querySelector('#transitionFilter'),
transitionsContainer = document.querySelector('#transitions')
transitionsContainer = document.querySelector('#transitions'),
sendExternalContainer = document.querySelector('#sendExternalContainer')
;
// ShowHide instance for future dest users
@ -24,6 +25,10 @@ window.addEventListener('DOMContentLoaded', function() {
for (let transition of froms) {
for (let input of transition.querySelectorAll('input')) {
if (input.checked) {
if ('1' === input.dataset.isSentExternal) {
return false;
}
const inputData = JSON.parse(input.getAttribute('data-is-signature'))
if (inputData.includes('person') || inputData.includes('user')) {
return false;
@ -40,6 +45,26 @@ window.addEventListener('DOMContentLoaded', function() {
}
});
// ShowHide instance for send external
new ShowHide({
debug: true,
load_event: null,
froms: [divTransitions],
container: [sendExternalContainer],
test: function(froms, event) {
for (let transition of froms) {
for (let input of transition.querySelectorAll('input')) {
if (input.checked) {
if ('1' === input.dataset.isSentExternal) {
return true;
}
}
}
}
return false;
}
})
// ShowHide signature zone
new ShowHide({
debug: false,

View File

@ -84,6 +84,13 @@
</div>
</div>
<div id="sendExternalContainer">
{{ form_row(transition_form.futureDestineeThirdParties) }}
{{ form_errors(transition_form.futureDestineeThirdParties) }}
{{ form_row(transition_form.futureDestineeEmails) }}
{{ form_errors(transition_form.futureDestineeEmails) }}
</div>
<p>{{ form_label(transition_form.comment) }}</p>
{{ form_widget(transition_form.comment) }}

View File

@ -15,6 +15,8 @@ use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Entity\UserGroup;
use Chill\MainBundle\Entity\Workflow\EntityWorkflow;
use Chill\PersonBundle\Entity\Person;
use Chill\ThirdPartyBundle\Entity\ThirdParty;
use Chill\ThirdPartyBundle\Validator\ThirdPartyHasEmail;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Workflow\Transition;
@ -54,6 +56,29 @@ class WorkflowTransitionContextDTO
*/
public ?User $futureUserSignature = null;
/**
* a list of future destinee third parties, when a workflow does send the document
* to a remote third party.
*
* @var array<ThirdParty>
*/
#[Assert\All(
new ThirdPartyHasEmail(),
)]
public array $futureDestineeThirdParties = [];
/**
* a list of future destinee emails, when a workflow does send the document to a remote
* email.
*
* @var array<string>
*/
#[Assert\All([
new Assert\NotBlank(),
new Assert\Email(),
])]
public array $futureDestineeEmails = [];
public ?Transition $transition = null;
public string $comment = '';

View File

@ -558,6 +558,15 @@ workflow:
Automated transition: Transition automatique
waiting_for_signature: En attente de signature
Permissions: Workflows (suivi de décision)
transition_destinee_third_party: Destinataire à partir des tiers externes
transition_destinee_third_party_help: Chaque destinataire recevra un lien sécurisé par courriel.
transition_destinee_emails_label: Envoi par courriel
transition_destinee_add_emails: Ajouter une adresse de courriel
transition_destinee_remove_emails: Supprimer
transition_destinee_emails_help: Le lien sécurisé sera envoyé à chaque adresse indiquée
signature_zone: