GithubHelp home page GithubHelp logo

sonata-workflow's Introduction

Yokai Sonata Workflow

Tests Coverage Contributors

License Latest Stable Version Current Unstable Version Downloads Monthly Total Downloads

Introduction

This library add Symfony Workflow component integration within Sonata Admin.

Features

  • add a menu dropdown to your admin detail pages on which you have buttons to apply available transitions
  • ship a controller to apply transition
  • allow to hook into the apply transition process to show an intermediate page

Code

Installation

$ composer require yokai/sonata-workflow

Configuration

Let say that you have an entity named PullRequest that is under workflow and for which you have an admin.

# config/packages/workflow.yml
framework:
    workflows:
        pull_request:
            type: state_machine
            marking_store:
                type: state_machine
                property: status
            supports:
                - App\Entity\PullRequest
            places:
                - opened
                - pending_review
                - merged
                - closed
            initial_marking:
                - opened
            transitions:
                start_review:
                    from: opened
                    to:   pending_review
                merge:
                    from: pending_review
                    to:   merged
                close:
                    from: pending_review
                    to:   closed

One extension for everything

The extension is usable for many entities and with no configuration.

You only need to create a service for it, configure the controller that will handle the transition action and configure on which admin you want it available.

For instance :

# config/packages/sonata_admin.yml
services:
    admin.pull_request:
        class: App\Admin\PullRequestAdmin
        public: true
        arguments: [~, App\Entity\PullRequest, Yokai\SonataWorkflow\Controller\WorkflowController]
        tags:
            - { name: 'sonata.admin', manager_type: orm, label: PullRequest }
    admin.extension.workflow:
        class: Yokai\SonataWorkflow\Admin\Extension\WorkflowExtension
        public: true
        arguments:
            - '@workflow.registry'
    Yokai\SonataWorkflow\Controller\WorkflowController:
        autowire: true
        tags: ['controller.service_arguments']

sonata_admin:
    extensions:
        admin.extension.workflow:
            admins:
                - admin.pull_request

note: You may noticed that we also registered the controller Yokai\SonataWorkflow\Controller\WorkflowController as a service. It is important, because it needs the workflow registry service to work.

More specific extension per admin

But the extension accepts many options if you wish to customize the behavior.

For instance :

# config/packages/sonata_admin.yml
services:
    admin.pull_request:
        class: App\Admin\PullRequestAdmin
        public: true
        arguments: [~, App\Entity\PullRequest, 'Yokai\SonataWorkflow\Controller\WorkflowController']
        tags:
            - { name: 'sonata.admin', manager_type: orm, label: PullRequest }
    admin.extension.pull_request_workflow:
        class: Yokai\SonataWorkflow\Admin\Extension\WorkflowExtension
        public: true
        arguments:
            - '@workflow.registry'
            - render_actions: [show]
              workflow_name: pull_request
              no_transition_label: No transition for pull request
              no_transition_icon: fa fa-times
              dropdown_transitions_label: Pull request transitions
              dropdown_transitions_icon: fa fa-archive
              transitions_default_icon: fa fa-step-forward
              transitions_icons:
                  start_review: fa fa-search
                  merge: fa fa-check
                  close: fa fa-times
    Yokai\SonataWorkflow\Controller\WorkflowController:
        autowire: true
        tags: ['controller.service_arguments']

sonata_admin:
    extensions:
        admin.extension.pull_request_workflow:
            admins:
                - admin.pull_request

What are these options ?

  • render_actions : Admin action names on which the extension should render its menu (defaults to [show, edit])
  • workflow_name : The name of the Workflow to handle (defaults to null)
  • no_transition_display : Whether or not to display a button when no transition is enabled (defaults to false)
  • no_transition_label : The button label when no transition is enabled (defaults to workflow_transitions_empty)
  • no_transition_icon : The button icon when no transition is enabled (defaults to fa fa-code-fork)
  • dropdown_transitions_label : The dropdown button label when there is transitions enabled (defaults to workflow_transitions)
  • dropdown_transitions_icon : The dropdown button icon when there is transitions enabled (defaults to fa fa-code-fork)
  • transitions_default_icon : The default transition icon for all transition (defaults to null : no icon)
  • transitions_icons : A hash with transition name as key and icon as value (defaults to [])

Hook into the transition process

Let say that when you start a review for a pull request, as a user, you will be asked to enter which users are involved in the review.

To achieve this, you will be asked to fill a dedicated form.

You only need to create a custom controller for your entity admin :

# config/packages/sonata_admin.yml
services:
    admin.pull_request:
        class: App\Admin\PullRequestAdmin
        public: true
        arguments: [~, App\Entity\PullRequest, App\Admin\Controller\PullRequestController]
        tags:
            - { name: 'sonata.admin', manager_type: orm, label: PullRequest }
<?php
// src/Admin/Controller/PullRequestController.php

declare(strict_types=1);

namespace App\Admin\Controller;

use App\Entity\PullRequest;
use App\Form\PullRequest\StartReviewType;
use Sonata\AdminBundle\Controller\CRUDController;
use Symfony\Component\HttpFoundation\Response;
use Yokai\SonataWorkflow\Controller\WorkflowControllerTrait;

class PullRequestController extends CRUDController
{
    use WorkflowControllerTrait;

    protected function preApplyTransition(object $object, string $transition): ?Response
    {
        switch ($transition) {
            case 'start_review':
                return $this->startReview($object, $transition);
        }

        return null;
    }

    protected function startReview(PullRequest $object, string $transition): ?Response
    {
        $form = $this->createForm(
            StartReviewType::class,
            [],
            [
                'action' => $this->admin->generateObjectUrl(
                    'workflow_apply_transition',
                    $object,
                    ['transition' => $transition]
                ),
            ]
        );

        $form->handleRequest($this->getRequest());

        if (!$form->isSubmitted() || !$form->isValid()) {
            $formView = $form->createView();

            return $this->renderWithExtraParams('admin/pull-request/start-review.html.twig', [
                'action' => 'edit',
                'form' => $formView,
                'object' => $object,
                'objectId' => $this->admin->getNormalizedIdentifier($object),
            ], null);
        }

        $data = $form->getData();
        // do something with the submitted data before returning null to continue applying transition

        return null;
    }
}

MIT License

License can be found here.

Authors

The library was originally created by Yann Eugoné. See the list of contributors.


Thank's to Prestaconcept for supporting this library.

sonata-workflow's People

Contributors

kevinecotree avatar metabor avatar mpoiriert avatar phansys avatar yann-eugone avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

sonata-workflow's Issues

Transition item is translated with a "leading" underscore

Maybe a minor issue, but the getLabel method is missing the $type argument:

$menu->addChild(
    $admin->getLabelTranslatorStrategy()->getLabel($transition->getName(), 'workflow'),
    $options
);

Which leads to something like:

workflow:
    _accept: Accetta
    _reject: Rifiuta
    _submit: Invia
    _suspend: Sospendi

What about using "label" or "transition" as $type argument?

Transition item is not translated using the admin translation domain

Here: https://github.com/yokai-php/sonata-workflow/blob/master/src/Admin/Extension/WorkflowExtension.php#L181 you are using:

$menu->addChild(
    $admin->getLabelTranslatorStrategy()->getLabel($transition->getName(), 'workflow'),
    $options
);

Which is correct, because the extension should use the same label translation strategy of the admin. But translation domain should be the same of the admin, this could be easily fixed:

$menu->setExtra('translation_domain', $admin->getTranslationDomain());

Multiple workflow support

I have multiple workflows configured for some entities. Symfony 4 has support for it, this plugin does not, is that correct? I can not find a way to pass a specific workflow to this manager. Thanks in advance!

workflow.registry service is private in sf4

The "workflow.registry" service or alias has been removed or inlined when the container was compiled. You should either make it public, or stop using the container directly and use dependency injection instead.

Prevent some transition in the admin

I have some transition that are executed via a cron. User should not be able to apply those transition from the admin.

Is there a way to do that or I should create a complete other workflow to handle that ?

Symfony 6 support

- yokai/sonata-workflow dev-sonata-4.x-compatibility requires symfony/workflow ^4.4|^5.0 -> found symfony/workflow[v4.4.0, ..., v4.4.42, v5.0.0, ..., v5.4.9] but it conflicts with your root composer.json require (6.0.*).

Dropdown appears on "show" screen toolbar

Even if "show" screen is not configured, transition dropdown is there, just replace "edit" with "show" in the URL to see. Not sure if that a major bug, but "show" screens are usually do not offer to change entity, anyway a configuration option to disable this behavior would be nice to see. Thanks.

Workflow and inherited entities

Hello, I'm getting "An exception has been thrown during the rendering of a template ("unable to find the route admin.verification.workflow_apply_transition")." and I believe this is sonata-workflow's issue. Here's my setup:

I have an abstract entity:

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Table(name="verification")
 * @ORM\Entity
 * @ORM\InheritanceType("JOINED")
 * @ORM\DiscriminatorColumn(name="verification_type", type="string")
 * @ORM\DiscriminatorMap({"personal"="PersonalVerification", "address"="AddressVerification"})
 */
abstract class Verification
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=100, nullable=false, unique=true)
     */
    private $status;
}

and two inherited entities PersonalVerification and AddressVerification.

/**
 * @ORM\Table(name="verification_personal")
 * @ORM\Entity
 */
class PersonalVerification extends Verification
{
    // ...
}

/**
 * @ORM\Table(name="verification_address")
 * @ORM\Entity()
 */
class AddressVerification extends Verification
{
    // ...
}

My worflow.yaml looks like this:

framework:
    workflows:
        verification_state:
            type: 'state_machine'
            places:
                - unverified
                - verified
                - rejected
            initial_place: unverified
            marking_store:
                type: "single_state"
                arguments: ['status']
            supports:
                - App\Entity\Verification
            transitions:
                accept:
                    from: unverified
                    to: verified
                reject:
                    from: unverified
                    to: rejected

My sonata_admin.yaml looks like:

services:
    admin.verification:
        class: App\Admin\VerificationAdmin
        arguments: [~, App\Entity\Verification, Yokai\SonataWorkflow\Controller\WorkflowController]
        tags:
            - { name: sonata.admin, manager_type: orm, label: 'Verifications' }
        public: true
        calls:
            - [setSubclasses, [{'Personal': App\Entity\PersonalVerification, 'Address': App\Entity\AddressVerification}]]

    admin.extension.verification_state_workflow:
        class: Yokai\SonataWorkflow\Admin\Extension\WorkflowExtension
        public: true
        arguments:
            - "@workflow.registry"
            - workflow_name: verification_state

    Yokai\SonataWorkflow\Controller\WorkflowController:
        autowire: true
        tags: ['controller.service_arguments']

sonata_admin:
    extensions:
        admin.extension.verification_state_workflow:
            admins:
                - admin.verification

I tried to change workflow's "supports" section to:

            supports:
                - App\Entity\PersonalVerification
                - App\Entity\AddressVerification

It results to successful render of "edit" page but without "transition" dropdown (seems like due to an exception in WorkflowExtension::configureSideMenu() inside getWorkflow() call which is dropped silently). Anyway I think

            supports:
                - App\Entity\Verification

more correct in this case, because "status" is the state property of the base class.

Thank you.

Issue with template

I am configured all according to documentation but i got exception about template:

An exception has been thrown during the rendering of a template ("Place "" is not valid for workflow "order".").

How can i fix this issue?

Sonata-admin dev-master and S5 missing sonata.admin.pool

I'm using Symfony 5.2 and sonata-admin of the 4.x-dev branch (because 3.x requires symfony/console 4.x) and while using this bundle getting a strange error:

Unable to find the admin class related to the current controller (Yokai\SonataWorkflow\Controller\WorkflowController).

While digging into the issue I've found that there's actually another exception shadowed and probably wrongly rethrown in Sonata-admin's CRUD controller in configureAdmin() method:

...
        try {
            $this->admin = $this->get('sonata.admin.pool')->getAdminByAdminCode($adminCode);
        } catch (\InvalidArgumentException $e) {
dd($e);
            throw new \RuntimeException(sprintf(
                'Unable to find the admin class related to the current controller (%s).',
                static::class
            ));
        }
...

CRUDController.php on line 906:
Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException {#1066 ▼
  -id: "sonata.admin.pool"
  -sourceId: null
  -alternatives: []
  #message: "The "sonata.admin.pool" service or alias has been removed or inlined when the container was compiled. You should either make it public, or stop using the contai ▶"
  #code: 0
  #file: "/Users/up/work/project/vendor/symfony/dependency-injection/Container.php"
  #line: 266
  trace: {▶}
}

Seems that 'sonata.admin.pool' is not public service anymore but how that could be related to Sonata-Workflow bundle?
Can you help me with this?

Allow transitions without 'edit' role

I am working on a project where one of our partners needs to look at the Entities and confirm they are correct by forwarding them throught the workflow. I dont want to give them writing access as this would confuse them too much.

The EDIT role is statically programmed into the code. Is there any way of changing that and connecting it to the guard attributs as set in the workflow.yaml ?

Exception on "Add new" form

Hi,

I'm trying to use this extension in one of my projects and although it seems to mostly work, when I try to create a new entry from Sonata admin I get the following exception:

An exception has been thrown during the rendering of a template ("Parameter "id" for route "admin_translations_workflow_apply_transition" must match "[^/]++" ("" given) to generate a corresponding URL.").

The route is defined as:

  admin_translations_workflow_apply_transition   ANY        ANY      ANY          /Web/Tools/PressArticles/w3c/accounts/translation/{id}/workflow/transition/{transition}/apply  

I believe the error is due to the fact that the new entry doesn't have an id yet, thus preventing that route from being generated.

Is there something special to do to handle sonata creation forms?

Thanks.

workflow.registry not fetchable on sf4.3 with traits

This seems to be a resurface of #1 .
I'm running symfony 4.3, sonata-workflow 0.1.2 and latest sonata. Also, I updated my services.yaml to include the definition of the WorkflowController, double checked all dumped the config via debug:container.

I even went so far as to try and define a setter injection for my custom controller, however this seems to have had no effect. Sonata must be loading the admins and associated controllers by other means than DI.

Still, since I'm using a custom controller and your WorkflowTrait, I am at a loss, as to what i could do.

Any thoughts on this, or points I may be missing?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.