cancel
Showing results for 
Search instead for 
Did you mean: 

Show Array of data in Workflow

dranakan
Champ on-the-rise
Champ on-the-rise
Hello,

I want to add some data during a Workflow. I would to be able to show an array and the user can add values.
For example, during a step in a workflow a page will be displayed the array. The user can add val1, val2, val3, val4 and other lines…


Workflow X

| Data1 | Data2 |
———————
|  val1 | val2 |
|  val3 | val4 |
|  …  |  … |

[NEXT]

I think that I have to :

1. Add in a model the data . Data1 (type any) and Data2 (type any)
2. Create a form control (like in alfresco/site-webscripts/org/alfresco/components/form/controls)
3. Create the worfklow
4. In the share-config-custom.xml, add the step of the workflow (<config evaluator="task-type"…) and add a field with the template (<control template="…)

Has someone a sample ?

(Activiti, Alfreco 4.0b)

Fr forum : https://forums.alfresco.com/fr/viewtopic.php?f=11&t=5283#p24274

Thank you
8 REPLIES 8

albertocursack
Champ in-the-making
Champ in-the-making
Hello Dranakan,
I think this could help you a little with the data model of the workflow

http://code.google.com/p/alfresco-share-datatable-property-type/

Regards,
Alberto

dranakan
Champ on-the-rise
Champ on-the-rise
Hello Dranakan,
I think this could help you a little with the data model of the workflow

http://code.google.com/p/alfresco-share-datatable-property-type/

Regards,
Alberto

Thank you albertocursack, I will analyse this !

dranakan
Champ on-the-rise
Champ on-the-rise
The code of alfresco-share-datatable-property-type is working 🙂
However I get problem to use it in a workflow form. I had to make some change to run the js code.
The table is displayed on the page during the JS script (I have add some alert("…") instead of breakpoints…  but the table cleared after the JS script… So the table is not displayed during the workflow…

I have done some changes :
1. Put the window.onload at the end
2. Replace in the init the DTP.drawDatatable(YAHOO.lang.trim(this.jsonProp.value)); by DTP.drawDatatable(""); (for the moment I just want to show the table…)

The table is diplayed and cleared after the message "end init".

<#–
        Title  : Datatable property type for Alfresco Share
        Author : Matija Svoren, msvoren@gmail.com
        Version: 1.0
–>

<link rel="stylesheet" type="text/css" href="${url.context}/yui/datatable/assets/skins/sam/datatable.css" />
<script type="text/javascript" src="${url.context}/yui/datasource/datasource-min.js"></script>
<script type="text/javascript" src="http://yui.yahooapis.com/2.8.2r1/build/datatable/datatable-min.js"></script>
<style>
.delButton {
        font-size:14px; font-wight:strong; color:red;
        width: 16px;  height: 16px; cursor: pointer;
}
.addButton {
        font-size:14px; font-wight:strong; color:blue; padding: 7px;
        cursor: pointer;
}
</style>

<#if field.control.params.config?exists>configDef<#assign dtConfig = field.control.params.config><#else>configNonDef<#assign dtConfig = "false"></#if>
<#if field.control.params.debug?exists>debugDef <#assign debug = field.control.params.debug><#else>debugNonDef<#assign debug = "false">   </#if>

<#if field??>${fieldHtmlId}
        <label for="${fieldHtmlId}">${field.label?html}:<#if field.mandatory><span class="mandatory-indicator">${msg("form.required.fields.marker")}</span></#if></label>
        <textarea id="${fieldHtmlId}" name="${field.name}"  rows="5" cols="250"
                <#if field.control.params.styleClass?exists>class="${field.control.params.styleClass}"</#if>
                <#if debug == "false">style="visibility:hidden; height:0px;"<#else>type="text"</#if>
         >${field.value}
        </textarea>
        <div id="dtContainer">
                <div class="yui-skin-sam" id="dtp-dt"></div>
        </div>
</#if>


<script type="text/javascript">//<![CDATA[
DTP = {
        jsonProp : null,
        columnDefinitions : new Array(),
        readOnly : false,
        label : "Datatable property",

        init: function(fieldHtmlId, config, view, label){
                this.dtConfig = config;
                this.label = label;
                alert("init…");
                if ( view == "view") { this.readOnly = true; }
                this.jsonProp = YAHOO.util.Dom.get(fieldHtmlId);
                DTP.drawDatatable("");
                //DTP.drawDatatable(YAHOO.lang.trim(this.jsonProp.value));
                alert("end init");
        },
        test: function(valueStr){
                alert("test" +valueStr);
        },


        /*
                generates datatable using JSON string from text field
        */
        drawDatatable: function(jsonString){
                alert("drawDatatable");
                if (!jsonString || jsonString == "") jsonString = "{}";
                alert("d1");
                var jsonData = eval ("(" + jsonString + ")");
                alert("d2");
                DTP.getTableDefinition();
                alert("d3");
                /* datatable columns are retreived based on table definition */
                var getMyKeys = function() {
                        var columnsList = [];
                        for each(c in DTP.columnDefinitions) {
                                if (c.type == "date") columnsList.push({key : c.key, parser: "date"});
                                else  columnsList.push(c.key); } return columnsList;
                }

                var jsonSource = new YAHOO.util.DataSource(jsonData);
                jsonSource.responseType = YAHOO.util.DataSource.TYPE_JSARRAY;
                jsonSource.responseSchema = { fields: getMyKeys() };

                this.dtpDatatable = new YAHOO.widget.DataTable("dtp-dt", DTP.columnDefinitions, jsonSource);

                DTP.datatableEvents();
        },

        /*
                adds events to datatable, add row, remove row, highlight, open edit cell…
        */
        datatableEvents: function(){
                alert("datatableEvents");
                if (!DTP.readOnly) {
                        /* create "add" button */
                        //get last th cell, and attach 'add' event
                        var lastCellNo = DTP.dtpDatatable.getTheadEl().rows[0].cells.length-1;
                        this.newRowButton = DTP.dtpDatatable.getTheadEl().rows[0].cells[lastCellNo];
                        var addButton = document.createElement('span');
                        addButton.innerHTML  = '+';
                        addButton.title = 'Add new row';
                        addButton.className = "addButton";
                        YAHOO.util.Event.addListener(addButton,'click',function(e){
                                var rowData = { delete: "-" };
                                var record = YAHOO.widget.DataTable._cloneObject(rowData);
                                DTP.dtpDatatable.addRow(record);
                        });
                        this.newRowButton.appendChild(addButton);
                        /* add "-" to each delete column */
                        for each(e in YAHOO.util.Dom.getElementsByClassName('delButton', 'td')) e.innerHTML = "<div class='yui-dt-liner'>-</div>";
                }

                this.highlightEditableCell = function(oArgs) { var elCell = oArgs.target;
                        if(YAHOO.util.Dom.hasClass(elCell, "yui-dt-editable")) { this.highlightCell(elCell); }
                };

                DTP.dtpDatatable.subscribe("cellMouseoverEvent", this.highlightEditableCell);
                DTP.dtpDatatable.subscribe("cellMouseoutEvent", DTP.dtpDatatable.onEventUnhighlightCell);

                /* save, update json string after save event */
                DTP.dtpDatatable.subscribe("editorSaveEvent", function(oArgs) { DTP.dtToJson(); });

                /* delete row event, or, by default, open cell to edit */
                DTP.dtpDatatable.subscribe('cellClickEvent',function(oArgs) {
                        var target = oArgs.target;
                        var column = DTP.dtpDatatable.getColumn(target);
                        if (column.key == 'delete') DTP.handleConfirm(target);
                        else DTP.dtpDatatable.onEventShowCellEditor(oArgs);
                });

                /* if in read mode, popup datatable on click */
                if (DTP.readOnly) {
                        DTP.dtpDatatable.subscribe('cellClickEvent', function(){ DTP.popupDT(); } );
                        DTP.tooltip = new YAHOO.widget.Tooltip("dtp-tooltip", { context:"dtp-dt", text:"Click on datagrid to popup!" });
                }
        },

        /*
                confirm dialog when deleting row
        */
        handleConfirm: function(toDelete){
                alert("handleConfi");
                var handleYes = function(){
                        this.hide(); DTP.dtpDatatable.deleteRow(toDelete); DTP.dtToJson(); return true;
                };
                var handleNo = function(){
                        this.hide(); return false;
                };

                var confirmDialog = new YAHOO.widget.SimpleDialog('DTPconfirmDialog',{
                                width: '300px',
                                fixedcenter: true,
                                visible: false,
                                draggable: false,
                                close: true,
                                text: "Are you sure you want to delete this row?",
                                constraintoviewport: true,
                                buttons: [{text:'Yes',handler:handleYes, isDefault:true },{text:'No',handler:handleNo}]
                });

                confirmDialog.setHeader('Delete row');
                confirmDialog.render(document.body);
                confirmDialog.show();

        },

        /*
                brings datatable in popup dialog
        */
        popupDT: function(){
                alert("popup");
                var handleClose = function(){
                        YAHOO.util.Dom.get("dtContainer").appendChild(YAHOO.util.Dom.get("dtp-dt"));
                        DTP.dtpDatatable.subscribe('cellClickEvent', function(){ DTP.popupDT(); } );
                        this.hide();
                        return true;
                };

                var confirmDialog = new YAHOO.widget.SimpleDialog('dtDialog',{
                                fixedcenter: true,
                                visible: false,
                                draggable: true,
                                close: false,
                                constraintoviewport: true,
                                modal:true,
                                buttons: [{text:'Close',handler:handleClose, isDefault:true }]
                });

                DTP.dtpDatatable.unsubscribe('cellClickEvent');
                confirmDialog.setHeader(DTP.label);
                confirmDialog.setBody(YAHOO.util.Dom.get("dtp-dt"));
                confirmDialog.render(document.body);
                confirmDialog.show();

        },

        /*
                gets table definition from what was provided in XML configuration. Parses parameter string to get definition.
                Sets-up formattters and editors according to column definition.
        */
        getTableDefinition: function(){
                alert("getTableDefinition");
                var getFormatter = function(t){
                        switch(t){
                                case "currency" : return YAHOO.widget.DataTable.formatCurrency; break;
                                case "number"   : return YAHOO.widget.DataTable.formatNumber;   break;
                                case "date"     : return YAHOO.widget.DataTable.formatDate;     break;
                                default         : return YAHOO.widget.DataTable.formatText;     break;
                        }
                        return t;
                };

                var getEditor = function(t, options){
                        if (DTP.readOnly == true) return null;
                        switch(t){
                                case "currency" : return new YAHOO.widget.TextboxCellEditor();  break;
                                case "number"   : return new YAHOO.widget.TextboxCellEditor();  break;
                                case "date"     : return new YAHOO.widget.DateCellEditor();     break;
                                case "radio"    : return new YAHOO.widget.RadioCellEditor({radioOptions: options ,disableBtns : true}); break;
                                case "checkbox" : return new YAHOO.widget.CheckboxCellEditor({checkboxOptions: options}); break;
                                case "dropdown" : return new YAHOO.widget.DropdownCellEditor({multiple: false, dropdownOptions: options}); break;
                                default         : return new YAHOO.widget.TextboxCellEditor();  break;
                        }
                }

                DTP.dtConfig = DTPtrim(DTP.dtConfig, ["&quot;"]); /* handles quotes if there's any */

                definition = DTP.dtConfig.split(";")

                for (var e = 0; e < definition.length; e++)
                {
                        var columns = definition[e].split(",");
                        if (columns && columns.length == 3) definition[e] = [ DTPtrim(columns[0]), DTPtrim(columns[1]), DTPtrim(columns[2]), null ];
                        else if (columns && columns.length > 3){
                                var l = [];
                                for (i = 3; i < columns.length; i++) l.push(DTPtrim(columns[i], ["'", "[", "]"]));
                                definition[e] = [ DTPtrim(columns[0]), DTPtrim(columns[1]), DTPtrim(columns[2]), l ];
                        }
                        else { // alert("Wrong datatable definition!" + (columns[0] ? " (at column)" + columns[0] : "" ));
                        }
                }

                function DTPtrim(s, toRemove){ for each (t in toRemove) while (s.indexOf(t) != -1) { s = s.replace(t,""); } return YAHOO.lang.trim(s); }

                for each (c in definition)
                  if (c[0] && c[0] != "") this.columnDefinitions.push({
                        "key" : c[0], "label" : c[1], "type" : c[2], formatter: getFormatter(c[2]), sortable: true, resizable: true, editor: getEditor(c[2], c[3])
                  });

                if (!this.readOnly) this.columnDefinitions.push({key:"delete", label:" ", className:"delButton"});
        },

        /*
                Gets datatable values in object, then converts object to JSON string
        */
        dtToJson: function(){
                alert("dtToJson");
                var records = DTP.dtpDatatable.getRecordSet().getRecords();
                var str = new Array();
                for (var i=0; i < records.length; i++) {
                        var o = new Object();
                        var keys = DTP.dtpDatatable.getColumnSet().keys;
                        for (var j=0; j < keys.length; j++) o[keys[j].getKey()] = records[i].getData(keys[j].getKey());
                        str.push(o);
                }
                DTP.jsonProp.value = YAHOO.lang.JSON.stringify(str);
        }
};
window.onload = function(e) { DTP.init("${fieldHtmlId}", "${dtConfig?html}", "${form.mode}", "${field.label?html}"); }
//]]></script>


Share-config-custom.xml

<config evaluator="string-compare" condition="activiti$Simple">
      <forms>
         <form>
            <field-visibility>

               <show id="sgfwf:libelle4" />
               <show id="bpm:assignee" />
               <show id="packageItems" />
               <!–  <show id="bpm:sendEMailNotifications" /> –>
            </field-visibility>
            <appearance>
               <set id="" appearance="title" label-id="workflow.set.general" />
               <set id="info" appearance="" template="/org/alfresco/components/form/2-column-set.ftl" />
               <set id="assignee" appearance="title" label-id="workflow.set.assignee" />
               <set id="items" appearance="title" label-id="workflow.set.items" />
               <set id="other" appearance="title" template="/org/alfresco/components/form/table-5-column-set.ftl" label-id="workflow.set.other" />

               <field id="bpm:workflowDescription" label-id="workflow.field.message">
                  <control template="/org/alfresco/components/form/controls/textarea.ftl">
                     <control-param name="style">width: 25%</control-param>
                  </control>
               </field>
                <field id="sgfwf:libelle4">
                <control template="/org/alfresco/components/form/controls/datatable-property.ftl">
                        <control-param name="config">
                                                id, ID, number;
                                                name, Item, text;
                                                quantity, Quantity, number;
                                                price, Price, currency;
                                                paid, Was paid, radio, ["Yes", "No"];
                                                features, Features, checkbox, ["JPEG", "MPEG", "MOV"];
                                                color, Color, dropdown, ["Black", "White", "Blue"];
                                                date, Date, date;
                                </control-param>
                        <control-param name="debug">true</control-param>
                  </control>
               </field>
               …

What do I change to use it in my workflow form ?

Thank you

dranakan
Champ on-the-rise
Champ on-the-rise
The problem comes from the jsonProp which is null ..
Firebug
this.jsonProp is null
[Stopper sur une erreur] var YUIDom=YAHOO.util.Dom,YUIEvent=YAH…lass(a,b)}else{YUIDom.addClass(a,b)}};
alfresco-min.js (ligne 295)

JsonProp at this point is null… (fieldHtmlId is setted). (From the jsscript, in the init)


this.jsonProp = YAHOO.util.Dom.get(fieldHtmlId);

If I try to get from the document… it's also nulll
var tt = document.getElementById(fieldHtmlId);

The window.onload is used to call the code… why the YAHOO.util.Dom.get(fieldHtmlId) don't get the value ?

dranakan
Champ on-the-rise
Champ on-the-rise
Why YAHOO.util.Dom.get("${fieldHtmlId}") when the js code is call from a workflow form ?

<link rel="stylesheet" type="text/css" href="${url.context}/yui/datatable/assets/skins/sam/datatable.css" />
<script type="text/javascript" src="${url.context}/yui/datasource/datasource-min.js"></script>
<script type="text/javascript" src="http://yui.yahooapis.com/2.8.2r1/build/datatable/datatable-min.js"></script>
<#–script type="text/javascript" src="${url.context}/yui/datatable/datatable-min.js"></script–>

<style>
.delButton {
        font-size:14px; font-wight:strong; color:red;
        width: 16px;  height: 16px; cursor: pointer;
}
.addButton {
        font-size:14px; font-wight:strong; color:blue; padding: 7px;
        cursor: pointer;
}
</style>

<#if field.control.params.config?exists><#assign dtConfig = field.control.params.config><#else><#assign dtConfig = "false"></#if>
<#if field.control.params.debug?exists> <#assign debug = field.control.params.debug><#else>    <#assign debug = "false">   </#if>

<#if field??>
        <label for="${fieldHtmlId}">${field.label?html}:<#if field.mandatory><span class="mandatory-indicator">${msg("form.required.fields.marker")}</span></#if></label>
        <textarea id="${fieldHtmlId}" name="${field.name}"  rows="5" cols="250"
                <#if field.control.params.styleClass?exists>class="${field.control.params.styleClass}"</#if>
                <#if debug == "false">style="visibility:hidden; height:0px;"<#else>type="text"</#if>
         >${field.value}
        </textarea>
        <div id="dtContainer">
                <div class="yui-skin-sam" id="dtp-dt"></div>
        </div>
</#if>

<script type="text/javascript">//<![CDATA[
window.onload = alert("jsonProp hors method : "+YAHOO.util.Dom.get("${fieldHtmlId}"));
//]]></script>
Here the YAHOO.util.Dom.get("${fieldHtmlId}") return null… the ${fieldHtmlId} has a value

dranakan
Champ on-the-rise
Champ on-the-rise
All is good if the form is called during the workflow (<config evaluator="task-type")
I think there is a bug with the start of the workflow… the js is not working correctly : https://issues.alfresco.com/jira/browse/ALF-11899

albertocursack
Champ in-the-making
Champ in-the-making
Hi dranakan,
        Sorry I didn't see your response before, Glad to hear you  found useful the datatable, I've founded really useful too.
       I didn't know that the built-in evaluators string-compare and task-type could make the difference…
       I am also trying something similar like you, add a datatable to a workflow form…

        In my workflow model I have a taks that are assigned to a user. If the task implicates differents steps, the user could divide the work and assign it to others user. In order to manage this subtasks within a task, I though I could define a workflow with 0..n sub workflows. Another approach I though, it could be using the datatable as a subtask list and inviting the others users to the task, making let them know what to do with the help of the subtask datatable in the form (this mean having only one workflow)

For the first one, one example could be:  

                        Task Name: Make Proposal
                         Assigned to: Peter

                        Then Peter could divide this task in small task (new workflows), i.e.:
                          
                                Subtask Name: Build Procurement Plan
                                Assigned to: Kate
                                Due Date: 12/12
                                Status: closed

                                Subtask Name: Write proposal, attach procurement plan, budget and send it
                                Assigned to: Mark
                                Due Date: 13/12
                                Status: closed


Like I said, I was thinkig to simplify this approach by having the datatable in the workflow form, making the task for multiple users, inviting to the same workflow  others (multiple users assigned), and tell them what to do and due date through the datatable…

Which one you think it will fit better, or do you think there is a better approach to do this…

Thanks, Alberto

dranakan
Champ on-the-rise
Champ on-the-rise
Hi Albert,

Your users could perhaps be the best help to choose. You should do two POC and ask some users to try.
Don't forget thinking if you need to look at the history of the workflow(s)(which solution is the best to see what has been done).

Best regards.