Support multi-site approval based workflow on wagtail - content-management-system

Objective
We would like to setup multi-site wagtail with approval chain.
Develop -> QA -> Release -> Production
Description
A develop / content editor goes to the wagtail admin and creates the content. Once done, sends the request for approval to move to QA site.
QA moderator reviews the content on develop site. If approved, the content gets moved to QA site. The content carries over to next stage approval (release).
Same process ahead for next sites in approval chain.
Questions
Is it possible to setup a publish chain with approval policy in wagtail? I tried to research a bit but could only find "workflow" and "workflow tasks". Do I need to custom code a workflow task to be able to achieve this?

This should be possible but you will need to consider what you really want to do in regards to the 'move' step, do you want to actually move the Page instance to a new site in a new tree or copy the current (and its history) and move that copy Page OR make a copy to put in place of the Page that was moved.
Nonetheless, the documentation on how to add a new Task type is the best place to start, it walks you through custom Task types.
In the solution below however, I thought it would be simplest to create a new model that behaves exactly like GroupApprovalTask (the default task included, used for moderation) but add a field that links it to the Site model.
This way, in the admin UI the admin users can now create as many PublishSiteTask as you want, one for each Site (QA/Dev/Prod etc) and then each of those could be linked to different user groups. It is important to differentiate between the database model (a task type with some fields) and the instances (a task created in the UI) and the actual task instances that are created against each page revision (not page) as the workflow steps progress.
Code Example
models.py
from django.db import models, transaction
from wagtail.core.models import GroupApprovalTask, Page, Site
# ... other imports
class PublishSiteTask(GroupApprovalTask):
site = models.OneToOneField(Site, on_delete=models.CASCADE)
admin_form_fields = ['site'] + GroupApprovalTask.admin_form_fields
#transaction.atomic
def on_action(self, task_state, user, action_name, **kwargs):
"""Performs an action on a task state determined by the ``action_name`` string passed"""
if action_name == 'approve':
# get the page that this action is referring to via the task_state.page_revision
page = task_state.page_revision.as_page_object()
# find the new parent target at this task's site
# how this is done depends on the site/page structure
new_parent_target = self.site.root_page
# move the page to a new location
# note: this will actually move it from its current tree, you may want to make a copy first
page.move(new_parent_target)
# be sure to preserve any existing task behaviour
super().on_action(task_state, user, action_name, **kwargs)
Additional Links
Task class definition
GroupApprovalTask class definition
You may want to do some pre-work in the code to check that the page can actually move to the different Site, each Page has a method can_move_to that could help.
The move method referenced above is part of the Wagtail code but the full docs for that method can be found in the Treebeard API docs which Wagtail uses to manage the tree structure.

Related

Trying to delete all records in a list based on a where clause

All of my workflows for a site have the ability to log data in the Workflow History list on my site. This is controlled at run-time with a parameter in list based on the workflow Name. I would like to be able to run a workflow on this setup table that will delete all records in the History list. My understanding is I can do this via REST call in SharePoint Designer workflow.
I have attempted many times to configure the REST Post command in Designer and I am never able to get this to work. I've searched over and over for a solution and not able to find such a solution.
I first tried deleting all that had the Workflow Association ID equal to the Workflow Name, but could not get that to work. Then I thought I would try selection each value using REST and then deleting that value using REST by the ID I received from the GET.
This is my delete (POST).
[%Workflow Context:Current Site URL%]/_api/lists/GetByTitle('Workflow History')/GetItemObject('[%Variable: HistoryID%]')
I also tried the DeleteListItem
[%Workflow Context:Current Site URL%]/_api/lists/GetByTitle('Workflow History')/DeleteListItem('[%Variable: HistoryID%]')
I want the user to be able to run this on any workflow from the setupWorkflow list I have. The workflow should delete all history for the current workflow.
We can get the list items in Workflow History list base on the WorkflowInstance, in designer workflow, we can get the Instance ID from the Workflow Context.
/_api/web/lists/getbytitle('Workflow%20History')/items?$filter=WorkflowInstance eq 'b87b131e-ce22-43f5-85be-ec81d1045bc7'
Then delete list item using REST API below.
/_api/web/lists/getbytitle('Workflow%20History')/GetItemById(ID)
The following articles for your reference.
Using HTTP Call/ Rest API from SharePoint Designer workflow to create list
workflow to delete list item on subsite( Sharepoint designer call http web service )

Add new category and custom page into Site Administration menu

I'm trying to add a new feature into site administration menu of moodle as part of a project that I am working on. Right now our customer only needs to integrate OnePay gateway into moodle. But in the future, they may require integration of other payment gateways (like PayPal) as well. So I need to create a category just for website administrators to input different types of payment. A new category should be somewhere in the "Advanced Features" menu (something like in the following screenshots)
Where to add new category
Example for onepay integration
With "Settings" page is a page that site administrator to input all necessary payment information (including customer's card number, access code, etc.). Right now I'm testing with using two of my testing pages for domestic and international payments.
Here is my code in file /lang/en/admin.php:
$string['payment'] = 'Payment';
$string['onepay'] = 'OnePay';
$string['test_onepay_domestic'] = 'Test Domestic Payment using OnePay';
$string['test_onepay_international'] = 'Test International Payment using OnePay';
In admin_custom directory, I created a path like this /payment/onepay/test/ and add 2 my testing pages into it. In folder /payment/, I added a file named menu.php. Here is my code in it.
<?php
$ADMIN->add('advancedfeatures', new admin_category('payment', get_string('payment', 'admin')));
$ADMIN->add('payment', new admin_category('payment', get_string('onepay', 'admin')));
//$domestic = new admin_settingpage('onepay', new lang_string('test_onepay_domestic', 'admin'), new moodle_url("/admin_custom/payment/onepay/test/domestic/index.php"));
//$international = new admin_settingpage('onepay', new lang_string('test_onepay_international', 'admin'), new moodle_url("/admin_custom/payment/onepay/test/international/index.php"));
$domestic = new admin_externalpage('test_onepay_domestic', get_string('test_onepay_domestic'), "$CFG->wwwroot/admin_custom/payment/onepay/test/domestic/index.php");
$international = new admin_externalpage('test_onepay_international', get_string('test_onepay_international'), "$CFG->wwwroot/admin_custom/payment/onepay/test/international/index.php");
$ADMIN->add('onepay', $domestic);
$ADMIN->add('onepay', $international);
I have attempted to include file menu.php in both files
/admin/settings/top.php
/admin/settings/server.php
But none of these works. Can anyone please tell me what should I do to get this works? Thank you very much. I really appreciate that.
Moodle doesn't have any sort of plugin type called 'payment', so by creating a hierarchy starting '/payment', you're already at odds with the way that Moodle works (as shown by needing to edit core files in order to add language strings and menu items).
I would recommend that you start again by creating an admin tool or a local plugin. Both of these types can have their own language strings and can add entries to the site admin menu (have a look at the settings.php inside any of the standard admin tool plugins or, for local plugins, an additional option is to create a local_MYPLUGIN_extend_settings_navigation() function). If you want to support multiple payment options, then your plugin could define a new subplugin type for each of the payment options.

Can "Request Publication" request go to a group other than the admin group in AEM6.1?

When a user does not have rights to publish a page, he sees "Request publication" button in Touch UI editor mode. When he clicks on "Request Publication", the workflow "Request for activation" starts and go to the admin's inbox. I want the page to go to some other group for publishing. How can I achieve this?
As shown in the image above, you can change the user/group to be anyone/anything in your instance.
You just need to change properties of default "Request for Activation" workflow.
However, it is recommended to make a new workflow of your own so that upgrades and patches don't revert your changes.
On the /libs/cq/workflow/content/console.html page with all available workflows. You should find workflow that you are interested in.
In you case it is possibly http://localhost:4502/cf#/etc/workflow/models/request_for_activation.html
On this page you can workflow config which contains several steps. Open for editing Request for activation step, switch to tab Arguments and then you can change Name patterns field. It should be regex pattern e.g. .*approver.* for all groups which contains approver in name.
As a variant you can custom workflow or step. In this case you need to figure out by you self how to configure it but usually it is something similar.

Implement Inbox Functionality in custom cq component?

We want to develop a smooth-flowing workflow experience (but still use workflows). Currently, a user needs to use the sidekick to initiate the workflow, then to the inbox, which takes them back to the page to use the sidekick again. When they go to the inbox, they need to restrict to the model and path of the page. It would be nice for the user to only have to go to the content page and from there, launch the different workflow forms that need to happen, like a little "inbox" right on the page that is subject to the workflow.
I have written a custom component that can initiate the custom workflow. The custom component can also query the WorkFlowSession and obtain any active WorkItems for the current page that the component resides (using the WorkItemFilter interface). What I want to do is provide a link to the user to the next step in the workflow from the custom component, just like the inbox does.
Here is an example output from an WorkItem instance toString method:
21.05.2014 09:45:29.300 *ERROR* [0:0:0:0:0:0:0:1%0 [1400679929160] GET /content/test/mailing1.html HTTP/1.1] org.rand.whatcounts.EmailCampaignCoordinator Found workitem: -----------------------------
WorkItem Id: /etc/workflow/instances/2014-05-21/model_1400679794564399000/workItems/node4_etc_workflow_instances_2014-05-21_model_1400679794564399000
Workflow Id: /etc/workflow/instances/2014-05-21/model_1400679794564399000
Payload: /content/test/mailing1
Payload Type: JCR_PATH
key = historyEntryPath value = /etc/workflow/instances/2014-05-21/model_1400679794564399000/history/1400679924113
key = comment value =
My hope is that by using the workflow api items, I can create the link that the user could click on to proceed in the workflow (just like the inbox).
Thanks for listening!
Phillip
There are two ways to implement this
Java-Based Solution
I was able to figure out one way by looking at
http://localhost:4502/libs/cq/workflow/components/inbox/list/json.jsp
The important part of this jsp is that, given a workItem instance, you can get the path for your next step using the JcrPathBuilderManager:
pathBuilder.getPath(wi);
Using this, I was able to output a link to the next step in the workflow to the user (without having user go to their inbox).
Javascript/JSON Based Solution
I didn't go far with this solution (I didn't write any js) but this was my fall back position if I didn't find the java-solution listed above. Once could implement custom JS in CQ Component that would call the json feed for the user inbox, do some client side filtering (to restrict it to only items related to current page). The URL to the feed is
http://localhost:4502/libs/cq/workflow/content/inbox/list.json?start=0&limit=40
Thanks!

Is it possible to associate a node to a workflow in alfresco?

I have to achieve the following:
Once a calendar event is created, start a workflow in which the assigned users (submitted with the form) are added to the workflow.
What I'm thinking to do is:
1 - to store the properties required for workflow in an aspect attached to the calendar then,
2 - to start the workflow from an addAspect behaviour and (associate it with the calendar event)
3 - then in an association behaviour add person(s) to the workflow as they're associated with the workflow.
I'm thinking this requires me to associate calendar-event => workflow in a source => target relationship so that as people are added, they're subscribed to the same behaviour policies.
You can add any nodeRef in de bpm_package. OOTB it's for example not possible to start a workflow on a folder. So starting the workflow from a JavaScript action you can do anything, like execute it on a calendar item (which is a node).
Create a calendar item and you'll see that via the Repository browser under the site/calendar a new .ics file has been created which is your node.