From 07fb72b31d62005e8e4e7970cd6484667d9bc889 Mon Sep 17 00:00:00 2001
From: Sebastian Listl <s.listl@adito.de>
Date: Wed, 14 Oct 2020 14:32:26 +0200
Subject: [PATCH] #1065237 Send email with workflow link

---
 .../CreateActivity_workflowService/process.js |  5 +-
 .../process.js                                |  2 +-
 process/DocumentTemplate_lib/process.js       |  3 +-
 process/Employee_lib/process.js               |  4 +-
 process/SendEmail_workflowService/process.js  | 18 +++--
 .../serviceTaskParameterProcess.js            | 34 +++++++++-
 .../SetAttribute_workflowService/process.js   |  2 +-
 process/Workflow_lib/process.js               | 66 ++++++++++++++++---
 process/redirect_rest/process.js              |  2 +-
 9 files changed, 110 insertions(+), 26 deletions(-)

diff --git a/process/CreateActivity_workflowService/process.js b/process/CreateActivity_workflowService/process.js
index 99d7da17dd..339b653450 100644
--- a/process/CreateActivity_workflowService/process.js
+++ b/process/CreateActivity_workflowService/process.js
@@ -15,7 +15,4 @@ var activityData = {
 };
 
 var links = [[variables.targetContext, variables.targetId]];
-var activity = ActivityUtils.insertNewActivity(activityData, links);
-
-result.string(activity.activityId);
-
+var activity = ActivityUtils.insertNewActivity(activityData, links);
\ No newline at end of file
diff --git a/process/CreateSalesproject_workflowService/process.js b/process/CreateSalesproject_workflowService/process.js
index a1fb1558fc..03e704f2ea 100644
--- a/process/CreateSalesproject_workflowService/process.js
+++ b/process/CreateSalesproject_workflowService/process.js
@@ -34,4 +34,4 @@ var processVariables = {
         "targetId": id,
         "targetContext": "Salesproject"
 }
-workflow.setProcessInstanceVariables(vars.get("$local.uid"), processVariables)
+result.object(processVariables);
diff --git a/process/DocumentTemplate_lib/process.js b/process/DocumentTemplate_lib/process.js
index 9d6c7fd07c..68621c5eef 100644
--- a/process/DocumentTemplate_lib/process.js
+++ b/process/DocumentTemplate_lib/process.js
@@ -637,6 +637,7 @@ DocumentTemplate.prototype.getReplacementsByContactIds = function (pContactIds,
     var placeholders = this._getRequiredPlaceholders(["{@firstname@}", "{@lastname@}"], pAdditionalPlaceholders);
     var contactPlaceholders = [];
     var additionalPlaceholders = {};
+    var isUserRequired = false;
     placeholders.forEach(function (placeholder)
     {
         switch (placeholder.type)
@@ -673,7 +674,7 @@ DocumentTemplate.prototype.getReplacementsByContactIds = function (pContactIds,
             if (placeholder.type === Placeholder.types.FIXEDVALUE)
                 replacements[contactId][placeholderName] = placeholder.valueDefinition;
             else if (placeholder.type === Placeholder.types.CALLBACKFUNCTION)
-                replacements[contactId][placeholderName] = placeholder.valueDefinition(contactId);
+                replacements[contactId][placeholderName] = placeholder.valueDefinition.call(this, contactId);
         }
     }
     return replacements;
diff --git a/process/Employee_lib/process.js b/process/Employee_lib/process.js
index 2c7e08724a..34e15d5760 100644
--- a/process/Employee_lib/process.js
+++ b/process/Employee_lib/process.js
@@ -22,7 +22,9 @@ EmployeeUtils.getCurrentContactId = function ()
 {
     if (vars.getString("$sys.isclient") == "true" && vars.exists("$global.user.contactId"))
         return  vars.get("$global.user.contactId");
-
+    if (!vars.exists("$sys.user"))
+        return null;
+    
     var user = tools.getCurrentUser();
     return user ? user[tools.PARAMS][tools.CONTACTID] : null;
 }
diff --git a/process/SendEmail_workflowService/process.js b/process/SendEmail_workflowService/process.js
index b2d61012cd..6ccbfe3e76 100644
--- a/process/SendEmail_workflowService/process.js
+++ b/process/SendEmail_workflowService/process.js
@@ -1,22 +1,33 @@
+import("Util_lib");
 import("Communication_lib");
 import("system.tools");
 import("system.result");
 import("DocumentTemplate_lib");
 import("system.vars");
 import("Email_lib");
+import("Placeholder_lib");
+import("Workflow_lib");
 
+var processInstanceId = vars.get("$local.uid");
 var variables = JSON.parse(vars.get("$local.value"));
 var recipientContactId = variables.recipientContactId;
 var documentTemplateId = variables.documentTemplateId;
 var senderName = variables.senderName;
 var mailSubject = variables.mailSubject;
 
-var email = Email.fromTemplate(documentTemplateId, recipientContactId);
+var actionParams = Utils.clone(variables);
+actionParams.processInstanceId = processInstanceId;
+var linkPlaceholder = new Placeholder("workflowActionLink", Placeholder.types.CALLBACKFUNCTION, function ()
+{
+    return WorkflowLinkActions.getActionLink("https://localhost:8443", actionParams.linkActionType, actionParams.redirectLink, actionParams);
+});
+
+var email = Email.fromTemplate(documentTemplateId, recipientContactId, null, [linkPlaceholder]);
 email.subject = mailSubject;
 email.toRecipients = [CommUtil.getStandardMail(recipientContactId)];
 
 //if we use @@instanceId in the mail body to track the user interaction, we replace it here with the instance id
-email.body = email.body.replace("@@instanceId", vars.get("$local.uid"));    
+email.body = email.body.replace("@@instanceId", processInstanceId);    
 
 var sendResult;
 if(senderName)
@@ -29,5 +40,4 @@ if(senderName)
 else
 {
     sendResult = email.send();  
-}
-result.string(sendResult);
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/process/SendEmail_workflowService/serviceTaskParameterProcess.js b/process/SendEmail_workflowService/serviceTaskParameterProcess.js
index 8fdc7e978b..b581232fe5 100644
--- a/process/SendEmail_workflowService/serviceTaskParameterProcess.js
+++ b/process/SendEmail_workflowService/serviceTaskParameterProcess.js
@@ -1,3 +1,4 @@
+import("system.vars");
 import("system.result");
 import("Workflow_lib");
 import("KeywordRegistry_basic");
@@ -19,7 +20,34 @@ var contacts = newSelect(["CONTACTID", new ContactTitleRenderer(Contact.createWi
     .table()
     .map(function (item) {return {id : item[0], name : item[1]};});
 
-result.object([
+var workflowLinkActionTypes = [];
+for (let typeName in WorkflowLinkActions.types)
+{
+    let actionType = WorkflowLinkActions.types[typeName];
+    workflowLinkActionTypes.push({id: actionType(), name: actionType.title});
+}
+
+var parameters = [
     new WorkflowServiceTaskParameter("documentTemplateId", "Document template", WorkflowServiceTaskParameter.ENUM(), templates),
-    new WorkflowServiceTaskParameter("recipientContactId", "Recipient", WorkflowServiceTaskParameter.ENUM(), contacts)
-]);
\ No newline at end of file
+    new WorkflowServiceTaskParameter("recipientContactId", "Recipient", WorkflowServiceTaskParameter.ENUM(), contacts),
+    new WorkflowServiceTaskParameter("linkActionType", "Link action", WorkflowServiceTaskParameter.ENUM(), workflowLinkActionTypes, true)
+];
+
+var currentValues = JSON.parse(vars.get("$local.value"));
+if (currentValues.linkActionType && currentValues.linkActionType.value)
+{
+    parameters.push(new WorkflowServiceTaskParameter("redirectLink", "Link", WorkflowServiceTaskParameter.STRING()));
+    switch (currentValues.linkActionType.value)
+    {
+        case WorkflowLinkActions.types.RECEIVE_TASK():
+            parameters.push(new WorkflowServiceTaskParameter("receiveTask", "Receive Task Id", WorkflowServiceTaskParameter.STRING()));
+            break;
+        case WorkflowLinkActions.types.SIGNAL():
+            parameters.push(new WorkflowServiceTaskParameter("signal", "Signal", WorkflowServiceTaskParameter.STRING()));
+            break;
+        case WorkflowLinkActions.types.MESSAGE():
+            parameters.push(new WorkflowServiceTaskParameter("message", "Message", WorkflowServiceTaskParameter.STRING()));
+    }
+}
+
+result.object(parameters);
\ No newline at end of file
diff --git a/process/SetAttribute_workflowService/process.js b/process/SetAttribute_workflowService/process.js
index 5ae7685d47..c9f17d88c3 100644
--- a/process/SetAttribute_workflowService/process.js
+++ b/process/SetAttribute_workflowService/process.js
@@ -16,4 +16,4 @@ if (variables.attributeName)
 else
     attributeId = variables.attributeId;
 
-result.string(new AttributeRelationQuery(variables.targetId, attributeId, variables.targetContext).insertAttribute(variables.attributeValue));
\ No newline at end of file
+new AttributeRelationQuery(variables.targetId, attributeId, variables.targetContext).insertAttribute(variables.attributeValue);
\ No newline at end of file
diff --git a/process/Workflow_lib/process.js b/process/Workflow_lib/process.js
index 16770fca1a..a876cd9f85 100644
--- a/process/Workflow_lib/process.js
+++ b/process/Workflow_lib/process.js
@@ -1,3 +1,4 @@
+import("system.process");
 import("Util_lib");
 import("system.text");
 import("system.logging");
@@ -605,44 +606,89 @@ WorkflowModelerApiCall.prototype.importModel = function ()
 function WorkflowLinkActions () {}
 
 WorkflowLinkActions.types = {
-    RECEIVE_TASK: function () {return "receive";}
+    RECEIVE_TASK: function () {return "rec";},
+    SIGNAL: function () {return "sig";},
+    MESSAGE: function () {return "msg";}
 };
 
+WorkflowLinkActions.types.RECEIVE_TASK.title = "Receive Task";
 WorkflowLinkActions.types.RECEIVE_TASK.execute = function (pParameters)
 {
-    if (!pParameters.piId || !pParameters.recId)
+    if (!pParameters.processInstanceId)
         return;
     
-    workflow.triggerReceiveTask(pParameters.piId, pParameters.recId);
+    workflow.triggerReceiveTask(pParameters.processInstanceId, pParameters.receiveTask || null);
 }
 
+WorkflowLinkActions.types.SIGNAL.title = "Signal";
+WorkflowLinkActions.types.SIGNAL.execute = function (pParameters)
+{
+    if (!pParameters.processInstanceId)
+        return;
+    workflow.signalEventReceived(pParameters.signal);
+}
+
+WorkflowLinkActions.types.MESSAGE.title = "Message";
+WorkflowLinkActions.types.MESSAGE.execute = function (pParameters)
+{
+    if (!pParameters.processInstanceId || !pParameters.message)
+        return;
+}
 
 WorkflowLinkActions.encodeAction = function (pType, pLink, pParams)
 {
-    var actionObj = pParams || {};
-    actionObj.type = pType;
-    actionObj.link = pLink;
+    if (!pParams)
+        pParams = {};
+    //map params to have shorter keys, results in shorter url
+    var actionObj = {};
+    if (pParams.processInstanceId)
+        actionObj.pi = pParams.processInstanceId;
+    if (pParams.signal)
+        actionObj.sg = pParams.signal;
+    if (pParams.message)
+        actionObj.ms = pParams.message;
+    if (pParams.receiveTask)
+        actionObj.re = pParams.receiveTask;
+    actionObj.ty = pType;
+    actionObj.ln = pLink;
     
     var actionString = JSON.stringify(actionObj);
     return encodeURIComponent(util.encodeBase64String(actionString));
 }
 
+WorkflowLinkActions.getActionLink = function (pBaseUrl, pType, pLink, pParams)
+{
+    if (!pBaseUrl.endsWith("/"))
+        pBaseUrl += "/";
+    return pBaseUrl + "services/rest/redirect_rest?act=" + WorkflowLinkActions.encodeAction(pType, pLink, pParams);
+}
+
 WorkflowLinkActions.parseAction = function (pEncodedAction)
 {
     try 
     {   
-        var decodedAction = decodeURIComponent(util.decodeBase64String(pEncodedAction))
+        var decodedAction = decodeURIComponent(util.decodeBase64String(pEncodedAction));
         var parsedAction = JSON.parse(decodedAction);
     }
     catch (err)
     {
         parsedAction = {};
     }
+    //map the object so it has understandable keys when used
+    var actionParams = {};
+    if (parsedAction.pi)
+        actionParams.processInstanceId = parsedAction.pi;
+    if (parsedAction.sg)
+        actionParams.signal = parsedAction.sg;
+    if (parsedAction.ms)
+        actionParams.message = parsedAction.ms;
+    if (parsedAction.re)
+        actionParams.receiveTask = parsedAction.re;
     
     return {
-        type: parsedAction.type || null,
-        redirectLink: parsedAction.link || null,
-        params: parsedAction,
+        type: parsedAction.ty || null,
+        redirectLink: parsedAction.ln || null,
+        params: actionParams,
         run: function ()
         {
             for (let typeName in WorkflowLinkActions.types)
diff --git a/process/redirect_rest/process.js b/process/redirect_rest/process.js
index 8fe7bdeca5..fe542e6008 100644
--- a/process/redirect_rest/process.js
+++ b/process/redirect_rest/process.js
@@ -1,6 +1,6 @@
 import("Workflow_lib");
+import("Util_lib");
 import("system.util");
-import("system.logging");
 
 function restget (pRequest)
 {
-- 
GitLab