The Magnolia Workflow module provides a standard four eye content approval workflow preconfigured on the Pages app. However it's possible for any content app to have a workflow attached to it. If the app is already existing then a decoration file can be deployed. For custom content apps it easiest to configure the workflow directly. 

Existing content app

With existing apps the best approach is to use a decoration file. Using a decoration file will allow for changing the configuration on a target app without having to manually configure nodes or override a YAML based definition. As an example we will look at how to add workflow to the Assets app. In order to add workflow to this app we simply need to override the action configuration for the activation actions. 

/my-module/decorations/dam-app/apps/assets.yaml
subApps:
  browser:
    actions:
      
      activate: # publish
        icon: icon-publish
        catalog: workflow # Calls workflow-activate command
        command: activate # from the workflow module.
        
        # Give the user the ability to schedule publication.
        class: info.magnolia.module.workflow.action.OpenPublicationDialogActionDefinition
        dialogName: workflow:publish
        formTypes: &types
          comment: 
            type: java.lang.String
          publicationDate: 
            type: java.util.Date
        
        # In order to publish the user needs write access to the workspace and
        # the node must be publishable.
        availability:
          writePermissionRequired: true
          rules:
            isPublishableRule:
              implementationClass: info.magnolia.ui.framework.availability.IsPublishableRule
      # end activate: #######################################################################

 
      activateRecursive: # publish recursive
        icon: icon-publish-incl-sub
        catalog: workflow # Calls workflow-activate command
        command: activate # from the workflow module.
        
        # Give the user the ability to schedule publication.
        class: info.magnolia.module.workflow.action.OpenPublicationDialogActionDefinition
        dialogName: workflow:publishRecursive
        formTypes: *types # Reference the types configuration from activate.
        
        asynchronous: true # Bulk activations will be done asynchronously as to not block the interface.
        notifyUser: false
        recursive: true
        
        # In order to publish the user needs write access to the workspace and
        # the node must be publishable and not deleted.
        availability: &writablePublishableNotDeleted
          writePermissionRequired: true
          rules:
            isPublishableRule:
              implementationClass: info.magnolia.ui.framework.availability.IsPublishableRule
            isNotDeletedRule:
              implementationClass: info.magnolia.ui.framework.availability.IsNotDeletedRule
      # end activateRecursive: ##############################################################
      

      deactivate: # unpublish
        icon: icon-unpublish
        catalog: workflow   # Calls workflow-deactivate command
        command: deactivate # from the workflow module.
		
        # Give the user the ability to schedule unpublication.
        class: info.magnolia.module.workflow.action.OpenPublicationDialogActionDefinition
        dialogName: workflow:unpublish
        formTypes: *types # Reference the types configuration from activate.
		
        # In order to unpublish the user needs write access to the workspace and
        # the node must be publishable and not deleted.
        availability: *writablePublishableNotDeleted
      # end deactivate: #####################################################################


      activateDeleted: # publish deletion
        icon: icon-publish
        catalog: workflow # Calls workflow-activate command
        command: activate # from the workflow module.

        # Give the user the ability to schedule publication.
        class: info.magnolia.module.workflow.action.OpenPublicationDialogActionDefinition
        dialogName: workflow:publishDeletion
        formTypes: &types
          comment:
            type: java.lang.String
          publicationDate:
            type: java.util.Date

        availability: 
          writePermissionRequired: true
          rules: 
            IsDeletedRule: 
              implementationClass: info.magnolia.ui.framework.availability.IsDeletedRule
      # end activateDeleted: #################################################################

Custom content app

With custom apps the best approach is to configure the actions and actionbar directly. Simply copy the actions from the above decoration file and paste them into the actions block of your browser subapp. Next place them appropriately in the actionbar configuration. Here is an example from the Assets app shown in yaml.

This example is not a complete definition. It's trying to show how the activation actions are placed in the actionbar. Some configuration has been removed to bring focus to activation.

/modules/dam-app/apps/assets/subApps/browser/actionbar
actionbar: 
  defaultAction: editAsset
  sections: 
    root: 
      availability: 
        nodes: false
        root: true
      groups: 
        addActions: 
        editActions:

    deletedAsset: 
      availability: 
        nodeTypes: 
          mgnl-contact: mgnl:asset
        rules: 
          IsDeletedRule: 
            implementationClass: info.magnolia.ui.framework.availability.IsDeletedRule
      groups: 
        addActions: 
        editActions:

        # Configure activation actions for deletedAsset section
        activationActions: 
          items: 
            - name: activateDeleted # publish deletion
            - name: deactivate # unpublish
        #########################################################

        importExportActions:
        deletedActions:

    deletedFolder: 
      availability: 
        nodeTypes: 
          mgnl-folder: mgnl:folder
        rules: 
          IsDeletedRule: 
            implementationClass: info.magnolia.ui.framework.availability.IsDeletedRule
      groups: 
        addActions:
        editActions:

        # Configure activation actions for deletedFolder section
        activationActions: 
          items: 
            - name: activateDeleted # publish deletion
            - name: deactivate  # unpublish
        #########################################################

        importExportActions:
        deletedActions:

    asset: 
      availability: 
        nodeTypes: 
          mgnl-contact: mgnl:asset
      groups: 
        addActions:
        editActions:
		
		# Configure activation actions for asset section
        activationActions: 
          items: 
            - name: activate # publish
            - name: deactivate # unpublish
            - name: selectCampaignAction
        #########################################################

        downloadActions:
        importExportActions:
        versionsActions:

    folder: 
      availability: 
        nodeTypes: 
          mgnl-folder: mgnl:folder
      groups: 
        addActions:
        editActions:

        # Configure activation actions for folder section
        activationActions: 
          items: 
            - name: activate # publish
            - name: activateRecursive # publish recursive
            - name: deactivate # unpublish
            - name: selectCampaignAction
        #########################################################

        importExportActions:

    multiple: 
      groups: 
        editActions:

        # Configure activation actions for multiple section
        activationActions: 
          items: 
            - name: activate # publish
            - name: deactivate # unpublish
        #########################################################

        importExportActions:

Configuration

The above examples are just one configuration option. Specifically an example for the Assets app that works very much like the Pages app. However, you might want to configure things slightly differently and for that we have different configuration options.

Commands

The workflow module provides two commands for publication (i.e. activate and deactivate). They are located in configuration here: /modules/workflow/commands/workflow. The activate and deactivate commands are actually command chains. It should be noted that each of these chains will call the versioning command before activating (or deactivating). Versioning may or not be needed. 

Scheduling

The option to schedule is supported by the underlying workflow. In the example above we looked at the scheduling option, which is exactly how the Pages app works OOTB. You can schedule activation for a later date but still execute the workflow process immediately. This is also true for deactivation.

The scheduling configuration is provided by the class OpenPublicationDialogActionDefinition and looks like this:

class: info.magnolia.module.workflow.action.OpenPublicationDialogActionDefinition
dialogName: workflow:publish
formTypes: &types
  comment: 
    type: java.lang.String
  publicationDate: 
    type: java.util.Date

It's possible to disable the scheduling option by using a different definition class. The class WorkflowPublicationActionDefinition does have a few configuration options to adjust the confirmation texts.

class: info.magnolia.module.workflow.action.WorkflowPublicationActionDefinition

Availability

The availability of the actions differs a bit depending on the action itself. All actions need write permission to the workspace as to be able to update the metadata of the published nodes. Also the node must be "publishable" or, in other words, have the proper mixin for publishing. In some cases the node must not be in a deleted state. You may need to add more rules based on your use case. 

#trackbackRdf ($trackbackUtils.getContentIdentifier($page) $page.title $trackbackUtils.getPingUrl($page))