Request a New Localized Content Item

In this example, we'll take a look at a standalone workflow that can be used to request the creation of a new translated content item. by "translated content item", we mean a new content item that has one or more translations in place upon completion. The completed work will then be approved by someone who reviews it and asserts that the content is ready to go live.

This workflow can be launched and will route a task to an editorial group (or a specific editorial user) . The editor will create the initial master content item in the default locale. This editor will fill in its properties and then submit it for translation.

The workflow then routes to a translators team for work on the translations. Once the document is translated, it is marked as approved.

This example demonstrates integrated email as well as the usage of Script Workflow Handlers to execute custom scripts. These scripts are used to create new content, attach it to your workflow, modify properties on those documents and add new translations.

In this case, we'll assume that the content item being created is of type my:article. The my:article content type has the following schema:

{
    "_qname": "my:article",
    "_type": "d:type",
    "type": "object",
    "properties":{
        "title": {
            "type": "string"
        },
        "body": {
            "type": "string"
        }
    }
}

Here is the workflow model:

{
    "id": "request_new_localized_content_item",
    "title": "Request a New Localized Content Item",
    "nodes": {
        "start": {
            "type": "start",
            "transitions": {
                "start": "edit"
            },
            "handlers": {
                "LEAVE": [{
                    "type": "script",
                    "config": {
                       "script": "var masterNode = branch.create({'title': 'Sample Title', '_type': 'my:article'}); workflowTask.addDocument(masterNode); masterNode.addTranslation('es');"
                    }
                }]
            }
        },
        "edit": {
            "type": "participant",
            "title": "Editor works on requested master content in default locale",
            "swimlane": "editors",
            "email": "pending_editors",
            "transitions": {
                "approve": "translate",
                "cancel": "cancel"
            }            
        },
        "translate": {
            "type": "participant",
            "title": "Translator works on localized content",
            "swimlane": "translators",
            "email": "pending_translators",
            "transitions": {
                "approve": "complete",
                "reject": "edit"
            }            
        },
        "complete": {
            "type": "passthru",
            "title": "Complete",
            "email": "complete",
            "transitions": {
                "next": "end"
            }
        },
        "cancel": {
            "type": "passthru",
            "title": "Cancel",
            "email": "cancel",
            "transitions": {
                "next": "end"
            },
            "handlers": {
                "ENTER": [{
                    "type": "script",
                    "config": {
                        "script": "for (var i = 0; i < documents.length; i++) { documents[i].del(); }"
                    }
                }]
            }            
        },
        "end": {
            "type": "end"
        }
    },
    "swimlanes": {
        "editors": {
            "principals": []
        },
        "translators": {
            "principals": []
        }
    },
    "emails": {
        "pending_editors": {
            "body": "A new task has arrived in your task inbox: <a href='{{workflowTask.url}}'>{{workflowTask.url}}</a>",
            "subject": "A request was received for new content"
        },
        "pending_translators": {
            "body": "A new task has arrived in your task inbox: <a href='{{workflowTask.url}}'>{{workflowTask.url}}</a>",
            "subject": "A request was received for content to be translated"
        },
        "complete": {
            "body": "The following documents were produced:<br/>{{#each workflowTask.documents}}<a href='{{workflowTask.url}}/documents/{{_doc}}>{{title}}</a>{{/each}}",
            "subject": "Your request for new content was completed"
        },
        "cancel": {
            "body": "The cancelled task can be viewed here: <a href='{{workflowTask.url}}'>{{workflowTask.url}}</a>",
            "subject": "Your request for new content was cancelled"
        }        
    }
}

How it works

  1. The workflow model begins in the start state
  2. This immediately then transitions to the edit state. When leaving the start state, a workflow script handler is triggered that runs a script. The script creates an empty document of type my:article and attaches that document to the workflow. It also adds a translation for this document in the Spanish locale (es).
  3. Upon arriving to the edit state, an email is sent to the members of the editors swimlane to let them know that something has arrived for them to work on.
  4. The edit state is of type participant and so it requires an editor to interact with it to continue. In this case, the editor receives the email and clicks the link, bringing them to a task screen where they can choose their next actions.
  5. On the edit task screen, the editor clicks on the document and fills in the properties. They click save. And then they click complete to signal that they've finished their work.
  6. The flow now transitions to the translate state.
  7. The translate state is of type participant and so it requires a translator to interact with it to continue. In this case, the translator receives an email and clicks the link, bringing them to a task screen where they can choose their next actions.
  8. On the translate task screen, the translator clicks on the document and localizes it into Spanish. They click save. And then they click complete to signal that they've finished their work.
  9. The flow now transitions to the complete state. This is a state of type passthru which means it's going to simply pass through to the next transition (which would transition to the end state).
  10. The workflow ends.

Alternatively, if the editor were to click cancel in step 5, the workflow routes to the cancel state where a script runs to delete the document that was automatically created in step 1. And, if the translator were to click reject in step 8, the flow routes back to the editor for adjustments (along with comment).

Notes

This workflow intentionally leaves both the editors and translators swimlanes empty. The user who launches this workflow will be prompted to provide one or more principals to occupy the swimlanes. The swimlanes could be occupied by a single user, multiple users, a group, many groups or any combination of the aforementioned.

In practice, you may want to pre-assign these swimlanes to one or more groups or users. Assignments consist of strings containing the domainId and principalId. They are specified like this domainId/principalId.

Anyone who is a member of the editors swimlane will have the option to work on the workflow when it is in the edit state.

If the editors swimlane has exactly 1 user, the user will be auto-assigned to edit. On the other hand, if the editors swimlane has multiple users or groups, the participant state identified by edit will not be auto-assigned. Instead, a member of the swimlane will need to first Claim the Task.

The same holds for the translators swimlane. Assignment can be to one or more users or groups.