Hi,
We would like to add workflow/wizard functionality into our existing SmartGWT based application. I have searched forum and found those threads requesting workflow examples, but not a single line of working example code:
So, I would like to share what I have learned so far.
I have created a simple flow starting with fetching process state data from client-only DataSource.
Next node is a script task which logs data.
Then, there is a user task which displays a form in the window and allows user to enter data.
Modified data is processed by a gateway, which compares to specified criteria.
Then it goes to error flow and back to user form or, if data matches criteria (field1='value1')), to node saving data and finishing process.
Here is index.html js example code:
	
and MainEntryPoint.java gwt example code:
	Data file for client-only ds test.data.xml:
	I have been working with SmartClient 12.1d dated 2019.12.01.
Comments welcome.
MichalG
					We would like to add workflow/wizard functionality into our existing SmartGWT based application. I have searched forum and found those threads requesting workflow examples, but not a single line of working example code:
- https://forums.smartclient.com/forum...amples-missing
- https://forums.smartclient.com/forum...rkflow-example
- https://forums.smartclient.com/forum...-by-sponsoring
- https://forums.smartclient.com/forum...orkflow-widget
- https://forums.smartclient.com/forum...rkflow-example
- https://forums.smartclient.com/forum...rkflow-feature
- https://forums.smartclient.com/forum...bpm-or-similar
So, I would like to share what I have learned so far.
I have created a simple flow starting with fetching process state data from client-only DataSource.
Next node is a script task which logs data.
Then, there is a user task which displays a form in the window and allows user to enter data.
Modified data is processed by a gateway, which compares to specified criteria.
Then it goes to error flow and back to user form or, if data matches criteria (field1='value1')), to node saving data and finishing process.
Here is index.html js example code:
Code:
	
	<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="content-type" content="text/html; charset=UTF-8">
        <title>Client</title>
    </head>
    <body>
        <script type="text/javascript">
            var isomorphicDir = "isomorphic/";
        </script>
        <script src="isomorphic/system/modules-debug/ISC_Core.js">          </script>
        <script src="isomorphic/system/modules-debug/ISC_Foundation.js">    </script>
        <script src="isomorphic/system/modules-debug/ISC_Containers.js">    </script>
        <script src="isomorphic/system/modules-debug/ISC_Grids.js">         </script>
        <script src="isomorphic/system/modules-debug/ISC_Forms.js">         </script>
        <script src="isomorphic/system/modules-debug/ISC_RichTextEditor.js"></script>
        <script src="isomorphic/system/modules-debug/ISC_Calendar.js">      </script>
        <script src="isomorphic/system/modules-debug/ISC_DataBinding.js">   </script>
        <script src="isomorphic/system/modules-debug/ISC_Workflow.js">      </script>
        <script src="isomorphic/skins/Graphite/load_skin.js"></script>
        <script type="text/javascript">
var ds = isc.DataSource.create({
    ID: "Test",
    dataURL: "test.data.xml",
    dataFormat: "xml",
    dataProtocol: "postXML",
    fields: [
        {name: "id", type: "text", primaryKey: true},
        {name: "field1", type: "text"},
        {name: "field2", type: "text"},
    ],
    clientOnly: true
});
var process = isc.Process.create({
    //state: {field1: "valueA", field2: "valueB"},
    elements : [
        isc.ServiceTask.create({
            ID: "data",
            dataSource: ds,
            outputFieldList: ["id", "field1", "field2"],
            operationType: "fetch",
            criteria: {field1: "valueA"},
            nextElement: "script"
        }),
        isc.ScriptTask.create({
            ID: "script",
            inputFieldList: ["id", "field1", "field2"],
            execute: function(input, inputRecord) {
                isc.logEcho(inputRecord, "ScriptTask");
            },
            nextElement: "form"
        }),
        isc.UserTask.create({
            ID: "form",
            inputFieldList: ["id", "field1", "field2"],
            outputFieldList: ["id", "field1", "field2"],
            targetView: isc.Window.create({
                ID: "wnd",
                width: 300,
                height: 120,
                items: [isc.DynamicForm.create({
                    ID: "df",
                    fields:[
                        {name:"id", type:"text", hidden: true},
                        {name:"field1", type:"text"},
                        {name:"field2", type:"text"},
                        {title:"Submit", type:"submit"}
                    ],
                })]
            }),
            targetForm: "df",
            nextElement: "gate"
        }),
//      isc.XORGateway.create({ ID: "gate", inputFieldList: "field1", criteria: advancedCriteria, failureElement: "errorFlow", nextElement: "goodFlow" }),
        isc.DecisionGateway.create({
            ID: "gate",
            inputFieldList: ["id", "field1","field2"],
            criteriaMap: {goodFlow: {field1: "value1"}, errorFlow: {field1: "value2"}},
            defaultElement: "errorFlow"
        }),
        isc.ScriptTask.create({
            ID:"goodFlow",
            inputFieldList: ["id", "field1", "field2"],
            execute: function(input, inputRecord) {
                isc.warn("goodFlow - save");
                isc.Window.getById("wnd").hide();
            },
            nextElement: "save"
        }),
        isc.ServiceTask.create({
            ID: "save",
            inputFieldList: ["id", "field1", "field2"],
            dataSource: ds,
            operationType: "update",
        }),
        isc.ScriptTask.create({
            ID:"errorFlow",
            inputFieldList: ["id", "field1", "field2"],
            execute: function(input, inputRecord) {
                isc.warn("errorFlow - try again");
            },
            nextElement: "script"
        })
    ]
});
process.start();
        </script>
    </body>
</html>
and MainEntryPoint.java gwt example code:
Code:
	
	package pl.com.tech4.client;
import com.google.gwt.core.client.EntryPoint;
import com.smartgwt.client.data.Criteria;
import com.smartgwt.client.data.DataSource;
import com.smartgwt.client.data.Record;
import com.smartgwt.client.data.fields.DataSourceTextField;
import com.smartgwt.client.types.DSDataFormat;
import com.smartgwt.client.types.DSOperationType;
import com.smartgwt.client.types.DSProtocol;
import com.smartgwt.client.util.SC;
import com.smartgwt.client.util.workflow.DecisionGateway;
import com.smartgwt.client.util.workflow.ProcessElement;
import com.smartgwt.client.util.workflow.ScriptTask;
import com.smartgwt.client.util.workflow.ServiceTask;
import com.smartgwt.client.util.workflow.UserTask;
import com.smartgwt.client.util.workflow.XORGateway;
import com.smartgwt.client.widgets.Window;
import com.smartgwt.client.widgets.form.DynamicForm;
import com.smartgwt.client.widgets.form.fields.SubmitItem;
import com.smartgwt.client.widgets.form.fields.TextItem;
import java.util.HashMap;
public class MainEntryPoint implements EntryPoint {
    @Override
    public void onModuleLoad() {
        layout();
    }
    private void layout() {
        DataSource ds = new DataSource();
        ds.setID("Test");
        ds.setDataURL("test.data.xml");
        ds.setDataFormat(DSDataFormat.XML);
        ds.setDataProtocol(DSProtocol.POSTXML);
        DataSourceTextField id = new DataSourceTextField("id");
        id.setPrimaryKey(true);
        DataSourceTextField field1 = new DataSourceTextField("field1");
        DataSourceTextField field2 = new DataSourceTextField("field2");
        ds.setFields(id, field1, field2);
        ds.setClientOnly(true);
        com.smartgwt.client.util.workflow.Process process = new com.smartgwt.client.util.workflow.Process() {
            @Override
            public void finished(Record state) {
                SC.logWarn("Process finished.");
            }
        };
        process.setID("process");
        ServiceTask dataTask = new ServiceTask();
        dataTask.setID("data");
        dataTask.setDataSource(ds);
        dataTask.setOutputFieldList("id", "field1", "field2");
        dataTask.setOperationType(DSOperationType.FETCH);
        dataTask.setCriteria(new Criteria("field1", "valueA"));
        dataTask.setNextElement("script");
        ScriptTask scriptTask = new ScriptTask() {
            @Override
            public Object execute(Object input, Record inputRecord) {
                SC.logEcho(inputRecord.getJsObj(),"scriptTask");
                return input;
            }
        };
        scriptTask.setID("script");
        scriptTask.setNextElement("form");
        scriptTask.setInputFieldList("id", "field1", "field2");
        UserTask formTask = new UserTask();
        formTask.setID("form");
        formTask.setNextElement("gate");
        formTask.setInputFieldList("id", "field1", "field2");
        formTask.setOutputFieldList("id", "field1", "field2");
        final Window wnd = new Window();
        wnd.setWidth(300);
        wnd.setHeight(120);
        DynamicForm df = new DynamicForm();
        df.setID("df");
        TextItem idItem = new TextItem("id");
        idItem.setHidden(true);
        TextItem field1Item = new TextItem("field1");
        TextItem field2Item = new TextItem("field2");
        SubmitItem submit = new SubmitItem("submit");
        df.setFields(idItem, field1Item, field2Item, submit);
        wnd.addItem(df);
        formTask.setTargetView(wnd);
        formTask.setTargetForm(df);
//        XORGateway gateway = new XORGateway();
//        gateway.setCriteria(criteria);
//        gateway.setNextElement("goodFlow");
//        gateway.setFailureElement("errorFlow");
        DecisionGateway gateway = new DecisionGateway();
        gateway.setID("gate");
        HashMap criteriaMap = new HashMap();
        criteriaMap.put("goodFlow", new Criteria("field1", "value1"));
        criteriaMap.put("errorFlow", new Criteria("field1", "value2"));
        gateway.setCriteriaMap(criteriaMap);
        gateway.setDefaultElement("errorFlow");
        ScriptTask goodFlowTask = new ScriptTask() {
            @Override
            public Object execute(Object input, Record inputRecord) {
                SC.warn("goodFlow - save");
                wnd.hide();
                return input;
            }
        };
        goodFlowTask.setID("goodFlow");
        goodFlowTask.setInputFieldList("id", "field1", "field2");
        goodFlowTask.setNextElement("save");
        ServiceTask saveTask = new ServiceTask();
        saveTask.setID("save");
        saveTask.setDataSource(ds);
        saveTask.setInputFieldList("id", "field1", "field2");
        saveTask.setOperationType(DSOperationType.UPDATE);
        ScriptTask errorFlowTask = new ScriptTask() {
            @Override
            public Object execute(Object input, Record inputRecord) {
                SC.warn("errorFlow - try again");
                return input;
            }
        };
        errorFlowTask.setID("errorFlow");
        errorFlowTask.setInputFieldList("id", "field1", "field2");
        errorFlowTask.setNextElement("script");
        ProcessElement[] elements = new ProcessElement[7];
        elements[0] = dataTask;
        elements[1] = scriptTask;
        elements[2] = formTask;
        elements[3] = gateway;
        elements[4] = goodFlowTask;
        elements[5] = saveTask;
        elements[6] = errorFlowTask;
//        process.setElements(elements);//does not work
        process.getOrCreateJsObj();
        process.setAttribute("elements", elements, true);
        //Record state = new Record();
        //state.setAttribute("field1Item", "value2");
        //process.setState(state);
        process.start();
    }
}
Code:
	
	<response>
    <startRow>0</startRow>
    <endRow>1</endRow>
    <totalRows>2</totalRows>
    <data>
        <Test>
            <id>1</id>
            <field1>valueA</field1>
            <field2>valueB</field2>
        </Test>
        <Test>
            <id>2</id>
            <field1>valueC</field1>
            <field2>valueD</field2>
        </Test>
    </data>
    <status>STATUS_SUCCESS</status>
</response>
Comments welcome.
MichalG

Comment