diff --git a/src/Bundle/ChillActivityBundle/Entity/ActivityType.php b/src/Bundle/ChillActivityBundle/Entity/ActivityType.php index 94f732a89..bdf75ed05 100644 --- a/src/Bundle/ChillActivityBundle/Entity/ActivityType.php +++ b/src/Bundle/ChillActivityBundle/Entity/ActivityType.php @@ -271,7 +271,7 @@ class ActivityType public function checkSocialActionsVisibility(ExecutionContextInterface $context, $payload) { if ($this->socialIssuesVisible !== $this->socialActionsVisible) { - if (!($this->socialIssuesVisible === 2 && $this->socialActionsVisible === 1)) { + if (!(2 === $this->socialIssuesVisible && 1 === $this->socialActionsVisible)) { $context ->buildViolation('The socialActionsVisible value is not compatible with the socialIssuesVisible value') ->atPath('socialActionsVisible') diff --git a/src/Bundle/ChillMainBundle/Entity/Workflow/EntityWorkflow.php b/src/Bundle/ChillMainBundle/Entity/Workflow/EntityWorkflow.php index c7a322338..a132706d7 100644 --- a/src/Bundle/ChillMainBundle/Entity/Workflow/EntityWorkflow.php +++ b/src/Bundle/ChillMainBundle/Entity/Workflow/EntityWorkflow.php @@ -174,6 +174,20 @@ class EntityWorkflow implements TrackCreationInterface, TrackUpdateInterface return null; } + public function getCurrentStepChained(): ?EntityWorkflowStep + { + $steps = $this->getStepsChained(); + $currentStep = $this->getCurrentStep(); + + foreach ($steps as $step) { + if ($step === $currentStep) { + return $step; + } + } + + return null; + } + public function getCurrentStepCreatedAt(): ?DateTimeInterface { if (null !== $previous = $this->getPreviousStepIfAny()) { diff --git a/src/Bundle/ChillMainBundle/Form/WorkflowStepType.php b/src/Bundle/ChillMainBundle/Form/WorkflowStepType.php index 18ac10c47..eaca35812 100644 --- a/src/Bundle/ChillMainBundle/Form/WorkflowStepType.php +++ b/src/Bundle/ChillMainBundle/Form/WorkflowStepType.php @@ -48,6 +48,8 @@ class WorkflowStepType extends AbstractType $entityWorkflow = $options['entity_workflow']; $handler = $this->entityWorkflowManager->getHandler($entityWorkflow); $workflow = $this->registry->get($entityWorkflow, $entityWorkflow->getWorkflowName()); + $place = $workflow->getMarking($entityWorkflow); + $placeMetadata = $workflow->getMetadataStore()->getPlaceMetadata(array_keys($place->getPlaces())[0]); if (true === $options['transition']) { if (null === $options['entity_workflow']) { @@ -68,40 +70,77 @@ class WorkflowStepType extends AbstractType $transitions ); + if (array_key_exists('validationFilterInputLabels', $placeMetadata)) { + $inputLabels = $placeMetadata['validationFilterInputLabels']; + + $builder->add('transitionFilter', ChoiceType::class, [ + 'multiple' => false, + 'label' => 'workflow.My decision', + 'choices' => [ + 'forward' => 'forward', + 'backward' => 'backward', + 'neutral' => 'neutral', + ], + 'choice_label' => function (string $key) use ($inputLabels) { + return $this->translatableStringHelper->localize($inputLabels[$key]); + }, + 'choice_attr' => static function (string $key) { + return [ + $key => $key, + ]; + }, + 'mapped' => false, + 'expanded' => true, + 'data' => 'forward', + ]); + } + $builder ->add('transition', ChoiceType::class, [ - 'label' => 'workflow.Transition to apply', + 'label' => 'workflow.Next step', 'mapped' => false, 'multiple' => false, 'expanded' => true, 'choices' => $choices, 'choice_label' => function (Transition $transition) use ($workflow) { - $meta = $workflow->getMetadataStore()->getTransitionMetadata($transition); + $meta = $workflow->getMetadataStore()->getTransitionMetadata($transition); - if (array_key_exists('label', $meta)) { - return $this->translatableStringHelper->localize($meta['label']); - } + if (array_key_exists('label', $meta)) { + return $this->translatableStringHelper->localize($meta['label']); + } - return $transition->getName(); - }, + return $transition->getName(); + }, 'choice_attr' => static function (Transition $transition) use ($workflow) { - $toFinal = true; + $toFinal = true; + $isForward = 'neutral'; - foreach ($transition->getTos() as $to) { - $meta = $workflow->getMetadataStore()->getPlaceMetadata($to); + $metadata = $workflow->getMetadataStore()->getTransitionMetadata($transition); - if ( + if (array_key_exists('isForward', $metadata)) { + if ($metadata['isForward']) { + $isForward = 'forward'; + } else { + $isForward = 'backward'; + } + } + + foreach ($transition->getTos() as $to) { + $meta = $workflow->getMetadataStore()->getPlaceMetadata($to); + + if ( !array_key_exists('isFinal', $meta) || false === $meta['isFinal'] ) { - $toFinal = false; - } + $toFinal = false; } + } - return [ - 'data-is-transition' => 'data-is-transition', - 'data-to-final' => $toFinal ? '1' : '0', - ]; - }, + return [ + 'data-is-transition' => 'data-is-transition', + 'data-to-final' => $toFinal ? '1' : '0', + 'data-is-forward' => $isForward, + ]; + }, ]) ->add('future_dest_users', PickUserDynamicType::class, [ 'label' => 'workflow.dest for next steps', diff --git a/src/Bundle/ChillMainBundle/Resources/public/lib/show_hide/show_hide.js b/src/Bundle/ChillMainBundle/Resources/public/lib/show_hide/show_hide.js index f2bcc9b45..25307a120 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/lib/show_hide/show_hide.js +++ b/src/Bundle/ChillMainBundle/Resources/public/lib/show_hide/show_hide.js @@ -1,19 +1,19 @@ /** * Create a control to show or hide values - * + * * Possible options are: - * + * * - froms: an Element, an Array of Element, or a NodeList. A * listener will be attached to **all** input of those elements * and will trigger the check on changes - * - test: a function which will test the element and will return true + * - test: a function which will test the element and will return true * if the content must be shown, false if it must be hidden. - * The function will receive the `froms` as first argument, and the + * The function will receive the `froms` as first argument, and the * event as second argument. - * - container: an Element, an Array of Element, or a Node List. The + * - container: an Element, an Array of Element, or a Node List. The * child nodes will be hidden / shown inside this container * - event_name: the name of the event to listen to. `'change'` by default. - * + * * @param object options */ var ShowHide = function(options) { @@ -26,8 +26,10 @@ var ShowHide = function(options) { container_content = [], debug = 'debug' in options ? options.debug : false, load_event = 'load_event' in options ? options.load_event : 'load', - id = 'uid' in options ? options.id : Math.random(); - + id = 'uid' in options ? options.id : Math.random(), + toggle_callback = 'toggle_callback' in options ? options.toggle_callback : null + ; + var bootstrap = function(event) { if (debug) { console.log('debug is activated on this show-hide', this); @@ -39,15 +41,14 @@ var ShowHide = function(options) { contents.push(el); } container_content.push(contents); - // console.log('container content', container_content); } // attach the listener on each input for (let f of froms.values()) { - let - inputs = f.querySelectorAll('input'), + let + inputs = f.querySelectorAll('input'), selects = f.querySelectorAll('select'); - + for (let input of inputs.values()) { if (debug) { console.log('attaching event to input', input); @@ -67,10 +68,10 @@ var ShowHide = function(options) { } // first launch of the show/hide - onChange(event); + onChange(event); }; - + var onChange = function (event) { var result = test(froms, event), me; @@ -89,45 +90,53 @@ var ShowHide = function(options) { } else { throw "the result of test is not a boolean"; } - + }; - + var forceHide = function() { if (debug) { console.log('force hide'); } - for (let contents of container_content.values()) { - for (let el of contents.values()) { - el.remove(); + if (toggle_callback !== null) { + toggle_callback(container, 'hide'); + } else { + for (let contents of container_content.values()) { + for (let el of contents.values()) { + el.remove(); + } } } is_shown = false; }; - + var forceShow = function() { if (debug) { console.log('show'); } - for (let i of container_content.keys()) { - var contents = container_content[i]; - for (let el of contents.values()) { - container[i].appendChild(el); + if (toggle_callback !== null) { + toggle_callback(container, 'show'); + } else { + for (let i of container_content.keys()) { + var contents = container_content[i]; + for (let el of contents.values()) { + container[i].appendChild(el); + } } } is_shown = true; }; - + var forceCompute = function(event) { onChange(event); }; - - + + if (load_event !== null) { window.addEventListener('load', bootstrap); } else { bootstrap(null); } - + return { forceHide: forceHide, forceShow: forceShow, diff --git a/src/Bundle/ChillMainBundle/Resources/public/page/workflow-show/index.js b/src/Bundle/ChillMainBundle/Resources/public/page/workflow-show/index.js index 2e2d4e89c..f589ee7d5 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/page/workflow-show/index.js +++ b/src/Bundle/ChillMainBundle/Resources/public/page/workflow-show/index.js @@ -2,29 +2,74 @@ import {ShowHide} from 'ChillMainAssets/lib/show_hide/show_hide.js'; window.addEventListener('DOMContentLoaded', function() { let - finalizeAfterContainer = document.querySelector('#finalizeAfter'), + divTransitions = document.querySelector('#transitions'), futureDestUsersContainer = document.querySelector('#futureDestUsers') ; - if (null === finalizeAfterContainer) { - return; - } - - new ShowHide({ - load_event: null, - froms: [finalizeAfterContainer], - container: [futureDestUsersContainer], - test: function(containers, arg2, arg3) { - for (let container of containers) { - for (let input of container.querySelectorAll('input')) { - if (!input.checked) { - return true; - } else { - return false; + if (null !== divTransitions) { + new ShowHide({ + load_event: null, + froms: [divTransitions], + container: [futureDestUsersContainer], + test: function(divs, arg2, arg3) { + for (let div of divs) { + for (let input of div.querySelectorAll('input')) { + if (input.checked) { + if (input.dataset.toFinal === "1") { + return false; + } else { + return true; + } + } } } - } - }, - }) + return true; + }, + }); + } + + let + transitionFilterContainer = document.querySelector('#transitionFilter'), + transitions = document.querySelector('#transitions') + ; + + if (null !== transitionFilterContainer) { + transitions.querySelectorAll('.form-check').forEach(function(row) { + + const isForward = row.querySelector('input').dataset.isForward; + console.log(row); + console.log(isForward); + + new ShowHide({ + load_event: null, + froms: [transitionFilterContainer], + container: row, + test: function (containers) { + for (let container of containers) { + for (let input of container.querySelectorAll('input')) { + if (input.checked) { + return isForward === input.value; + } + } + } + }, + toggle_callback: function (c, dir) { + for (let div of c) { + let input = div.querySelector('input'); + if ('hide' === dir) { + input.checked = false; + input.disabled = true; + } else { + input.disabled = false; + } + } + }, + }); + }); + } + + + + }); diff --git a/src/Bundle/ChillMainBundle/Resources/views/Workflow/_decision.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Workflow/_decision.html.twig index 4b14b39bc..e557d9e89 100644 --- a/src/Bundle/ChillMainBundle/Resources/views/Workflow/_decision.html.twig +++ b/src/Bundle/ChillMainBundle/Resources/views/Workflow/_decision.html.twig @@ -3,7 +3,60 @@ {% if transition_form is not null %} {{ form_start(transition_form) }} - {{ form_row(transition_form.transition) }} + {% set step = entity_workflow.currentStepChained %} + {% set labels = workflow_metadata(entity_workflow, 'label', step.currentStep) %} + {% set label = labels is null ? step.currentStep : labels|localize_translatable_string %} + +
+ {{ step.previous.comment|chill_markdown_to_html }} ++
{{ 'workflow.Users allowed to apply transition'|trans }} :
+