Restrict the selection count in choice (checkbox list)

Nice Post from of my Buddy .. Karan Varma

K2Guys

Drag and Drop DataLabel control to view canvas and Change its name to dlbScript
Drag and Drop Choice control to view canvas
Restrict Choice Selection -1
Change the name of Choice list to “ChkListUsers”
Set property Display Type to Check Box List

Restrict Choice Selection -2

Add data source to Choice control and changes the properties as per your requirement.
For dlbScript control do the following changes in properties
1. Set Literal property Checked
2. Click on Oval to add Expression for dlbScript control

Restrict Choice Selection -3

3. Add the below jQuery code

Restrict Choice Selection -4.jpg

Add jQuery code between the Script tag.

 

$("[name='ChkListUsers']").change(function(){
if($(':checked').length == 1){
$("[name='ChkListUsers']").not(':checked').prop('disabled',true);
}
if($(':checked').length == 0){
$("[name='ChkListUsers']").not(':checked').prop('disabled',false);
}
});

4. Once done click on Ok and then on Finish button for view.

Result:

Restrict Choice Selection -5.jpg

  • On selecting User 3 Other Users selection will be disabled.
  • Once you Unselected user 3 all users will be again selectable.

View original post

Integrating K2 with Atlassain HipChat

Inspired from my Boss’s (Simon Allport)’s post Slack & K2 Integration I have tried integrating K2 with HipChat and have created a small sample POC for you to look at.

Just to introduce you HipChat, which is an Atlassian Product used for team messaging and Collaboration. For more information you can visit About HipChat.

And to explain about this Sample POC, I have created a sample LeaveApproval Process which will assign the approval task to some User and will send Task Notification in HipChat to that User.

To achieve this we need a HipChat account which we can create here SignUp.

Once the account has been created, login with those Credentials. After you login you need to click on Launch the web app button which would navigate to the page where you can create a room.

Create a room using the link (Create a room) and give it a name, here I have named it as Leave Approval Tasks, and I have added all the approvers (Use Invite Your team) who gets assigned with Leave Approval Requests. So whenever an approval task gets assigned to someone, K2 would send a Task Notification to this room. To make this happen we need create an integration to this room, to do this we need select the room on left panel and click on +Add integrations.

ProfilePage

Now Select your room in the dropdown above and give your integration a name in the textbox below (Here I named it as Leave Approval Task) and click Create Button

Integrations

Once you create an integration you will be redirected to a page as shown below where you would see a URL which you can use to Send Notifications to this particular room. Along with the Url you will see a authentication token which we need to use while sending notifications to this room.

Also at the bottom of the page you see a section Extend HipChat with your Commands, we would talk about this section later in this post as it would be a very useful feature that we can use.

ExtendHipChat.png

Now our HipChat room is ready to receive notifications. Please make a note of Authentication token and room id from the URL as we are going to use them in code.

Alternatively we can generate authentication token for sending notification using the token generation page as shown below. This generated token can be used in API code.

CreateToken

Let us create an assembly which sends notification to the room which we have created above, this assembly uses HipChat API. So we need to add a reference to it.

For Installing HipChat API run below command in Nuget Package Manager Console. As HipChat API is built on ServiceStack.text 4.0.56 version we need to add the reference of that specific version too, else the code doesn’t work. So execute below commands for adding their references

Install-Package Hipchat-CS
Install-Package ServiceStack.Text -Version 4.0.56

Now add a method as shown below which takes few parameters and creates an HTML Text to send as a notification.

using System;
using HipchatApiV2;
using HipchatApiV2.Enums;

namespace POC.HipChat
{
 public class SendMessage
 {
 public static string SendHipChatNotification(string UserName, string RequestID, string Originator, string SubmittedDate)
 {

//Room Id – You can get from the integration 
 int RoomID = 0123456;
 //Auth Token which you see while creating Integration
 string Auth_Token = "xx**xxc**xxnhfM***WWE0K***IjEsy***ve";
 string htmlMessage, returnMessage;
 
 //Form the HTML of Notification with param values
htmlMessage = "<table border='1' style='border-style: solid; border-width: thin; width: 50%; background-color: greenyellow'><tr><td style='width: 7%'>" +
"<img src='link' height='40px' width='50px' /></td>" +
"<td style='width: 90%'>" +
 "<span id='spnMessage' style='font-family: Calibri'>Hey " + UserName + "!! A Leave Approval Request With Request ID : <b>" +
 RequestID + "</b> has been Submitted by <b>" + Originator + "</b> on <b>" + SubmittedDate + "</b> and is pending for your Approval. Please Act upon!!</span>" +
 "</td></tr></table>";

try
 {
 var client = new HipchatClient(Auth_Token);
 client.SendNotification(RoomID, htmlMessage, RoomColors.Green, false, HipchatMessageFormat.Html);
 returnMessage = "Success";
 }
 catch (Exception ex)
 {
 returnMessage = "Failed " + ex.Message; 
 }
 return returnMessage;
 }
 }
}

 

**once the assembly POC.HipChat is built copy the assembly along with HipchatApiV2 & ServiceStack.Text assemblies to C:ProgramFiles/K2BlackPearl/Bin folder

 Now Create an Endpoint Assembly Service Instance as shown below. Here I have named it as POC.HipChat

AddServiceInstance.png

Once the service instance has been created, you should be able to see the DLL method as shown below.

ServiceInstance.png

Now create an SMO for the method using this service instance. Here I have named it as POC.HipChat.SMO

NewSMO

Now our SMO is ready to send Task Notifications to HipChat. Now it’s just calling this method when required to send task notification.

I have created a sample Leave Approval Process which assigns a task to user and sends the notification to room when it assigns the task, also a SmartForm to submit the Leave Request.

Workflow.png

Submit Form

SubmitForm.png

I have submitted few requests as you can see in process overview as below

WorkSpace.png

Now let’s see how K2 workflow have sent Leave Approval Task notifications to room with the details in the below screen shot.

Here you see the notifications in HipChat Web Browser

HipChatNotification.png

And here as we can see it in HipChat Mobile Notification

Screenshot_2017-04-08-22-58-50

This is how we can make use of HipChat to receive K2 Notifications.

Now we can extend this POC to send Task Notification along with actions Approve & Reject Links so that the user can perform the action directly from HipChat itself.

Also in HipChat we have a feature to Extend HipChat with our own Commands, which they call as slash ‘/’ Commands. These slash commands can be used to send requests and get a response back from any server.

Now using these /Commands we can create some custom commands to gettasklist, taskcount, or perform any operation based on our requirements, some thing like below

  • /TaskList                                             –             To Get all active Task List
  • /TaskList {UserName}                      –             To get the Task List of that particular user
  • /ActionTask {SN},{ActionName}    –             To Perform a task based on SN.

This is how we can make use of HipChat and its features to integrate with K2.

Workflow For loop V/s Destination Rule – Plan per Slot (No Destinations)

[Agenda: To check performance variation between Workflow For loop and Destination RulePlan per Slot (No Destinations) with dynamic slot count.]

Working Example: Let me explain through a scenario where we have list of items which we get from an Smart Object method. Now in workflow we need to loop through each item and perform some task.

Now we have 2 ways to achieve this in workflow.

  1. Using ForEach loop
  2. Using Destination Rule (Plan Per Slot (no Destinations))

Our motive here is to find out which one is faster in execution.

Let’s see the workflow below and go through the each activities.

WKF

010-oneIn this step, “Add to audit” is a SmartObject Event which will insert a record into SQL data base. Here I’m using it to record time stamps to SQL db.
In this particular activity I’m logging this text “For Loop Beginning – {Date Time Stamp}

009-two

In this step, Add For each Event, and click on the icon beside source text box and selected the Smart Object Method that will return us list of Items.

ForLoop

008-threeIn this step, log each item to database. You will need to get the value from Item References under Process/Activity Data tab in Context Browser. See below screen shot.

LogForItem

007-four

 

In this step, Log this text “For Loop End & Dynamic Start – {Date Time Stamp}

 

 006-fiveIn this step, Add an activity and select destination rule Plan per slot (no Destinations).

(***If you are unable to see this option then just click back button and check advanced option and click next)

Click next button, now you need to select second radio option which says “select a list field to determine how many slots should be created.”

Select the Smart Object method which gives you the list of items and finish.

Now you can access those items in Instance Data Field under tab Activity Destination Instance in Workflow Context Browser.

See below screens PlanPerSlotLogDynamicItem

005-six

 

In this step, log text “Dynamic End – {Date Time Stamp}

 

Now just deploy the workflow and start a process instance and check the data base results. 

Results

SQLResults

Results

Result: For loop took 5 seconds to log 10 items to data base whereas Destination Rule took just 1 second to log 10 items.

So conclusion here is Destination Rule method is much faster than for loop.

Achieving Nested for Loop using Unbound Rules

Let me explain you through a scenario where you have smart form with 2 List views Brands List & Products List and a button to save the data as shown below.

1 Form

 

Now there is requirement here that for each brand there should be at least one product available before you perform save. Now to achieve this validation requirement in general approach we do something like below

foreach brand in brandsList
{
  foreach product in productsList
  {
     //check if a product exists for that brand
      If (Found)
      {
          //exit loop and go to next brand
      }
      else
      {
         //Fire Validation and exit loop
      }
   }
}

Now to achieve the same thing in smart form rules is not possible directly as K2 does not allow you to add for loop with in for loop, but we have a workaround which is using unbound rules. Let’s see how we do it.

We will be requiring 2 hidden data labels hdnDLIsValid which contains default value as False and hdnDLBrandName and 2 unbound rules ValidateLists and LoopProductBrands

 Now add the rules in LoopProductBrands as shown below.

Loop Product Brands

 

Similarly add rules in ValidateLists as shown below

ValidateLists

 

ValidateLists acts as a parent for loop which loops through all brands list and LoopProductBrands acts as a child for loop which loops through all products.

For each Brand we are storing the brand name in hidden data label hdnDLBrandName and then we are calling loopProductBrands, in which we are comparing the value in hdnDLBrandName with the column value in second List which is Products List.

If the value matches then it will the set the value of hdnDLIsValid to True.

Once the products loop gets completed, it checks whether hdnDLIsValid is still false, if yes then it means we have not found a match, so validation is failed and we can show the validation message and stop rules execution further.

Else if hdnDLIsValid is true then we found a match for that brand, so we can reset the value of hdnDLIsValid to its default value and move on to the next brand.

Now in the save Button Click we just have to call the unbound Rule ValidateLists before the code for saving the data.

ButtonSave

 

Now when you execute it should show you messages as in below screen grabs

 

Here a product is missing for brand LG, so the validation message gets fired for that particular brand.

Error Message

 

Here the validation gets passed as all brands has at least one product

Success Message

Finally this is how we can make use of unbound rules to achieve some complex validations like this.

K2 Unbound Rules & Achieving Nested For loop using unbound rules in K2 Smart forms

K2 have introduced a concept called Unbound rules post 4.5 release.

Unbound rules are nothing but a set of rules which are not bound to any control or event. They can be used as a common method which can be called multiple times across different events instead writing them individually in each event.

Also, as you already know that Nested for each looping is not possible in K2 smart forms, we can achieve it using unbound rules.

To-day I would like to explain how we can create unbound rules and use them across multiple events and then I will show you how we can achieve Nested for each loop using them

Let me start with creating an unbound rule and use it across multiple events.

Scenario:

Let’s assume we have a smart form with some controls along with 3 buttons Previous, Save, Next and on each button click we need to validate the form.

For this requirement we will create an unbound rule we use it across all the 3 button clicks.

Let’s Begin

Create a View as shown below

1 View Layout

All the fields here are mandatory for each button click

Now navigate to Rules tab and click on Add Rule and provide a name to unbound rule as you like. Here in my Case it is ValidateView as shown highlighted below

2 Naming Unbound

Now Navigate to Conditions Tab below and select an advanced condition is true and click on Green link to add the Conditions

3 Select AdvCond

Now add the validation Conditions as shown below and click OK to create advanced Condition.

4 Set AdvConds

Now I would like to show a message when any of this validation fails.

So navigate to Actions tab below and select show a message and click configure link and set the details as shown below

5 Show ValidMessage

Added HTML formatting tags, just to make this Validation message pop – up look pretty J

6 Set ValidMessage

Now we need to stop the execution when this validation gets failed, so we need to add one more rule with name Stop rule execution which will be available in Actions tab. You just need to add this as shown below, there is nothing to configure in this rule.

7 Add StopRule

Now the unbound rule is ready and we can start using this anywhere we required.

So let’s start configuring Save Button rule, click Add rule and from Events tab select when a control on the view raises an event and then click select control and then select the button you wish to configure the rules for.

8 Adding SaveBtnRule

Now I will select save button and then move to Actions tab and select Execute another rule and now click the green Configure link and select the unbound rule that you have created above.

9 Button SaveRule

Now after this rule we can add our logic to save the data or anything we want to do, which is explained in below screen shot. The rules that are written under this will be executed only when the above rule which validateView is successful.

10 BtnSave Final

Now as we did for save button we have to configure for other 2 buttons and use the same unbound rules for validating the controls. Once you configure all the rules the designer should look like something like below

11 All Rules

Now Save this view and add this to a form (or you can run it directly too) and test it.

12 Validation Message Fired

When I click on Save button it throws me a validation message as mandatory fields are empty, the same message will be shown when u click on any button if the mandatory fields are empty.

Now let me put some data into fields and click on Save again and see the result in below screen shot.

13 Data Saved Message

As I have entered all mandatory data the save rule executes successfully and shows me a success message.

So this how we can make use of unbound rules as per our requirement and make our code much efficient.

Now achieving Nested For Loop see it here NestedForLoopUsingUnBoundRules

IPC Thread Pool Settings

Have you ever wondered why in IPC Events when you are triggering a child workflow it takes some time to initiate and also in case of Synchronous calls it takes time to receive the call back from child work flow?

The reason for this is, K2 have provided a small configuration setting (See Below) in K2Server.Setup File which will be available under path C:\Program Files (x86)\K2 blackpearl\Host Server\Bin

<IPCSettings ExpireOnDelete=”false” IPCThreadInterval=”60″ />

Default value is set as 60 sec, which means for every 60 sec the IPC thread will check for new IPC Calls and trigger them.

You can decrease this value to speed up the IPC calls. But K2 have suggested not to set the value below 5 seconds due to some performance issues.

ipcthreadinterval

 

There are few more settings that could be helpful for us to know. Please find below article which explains more useful settings.

https://help.k2.com/kb001446

(FileLoadException) File Load Exception While calling K2 Methods

While using a class library method which has references to K2 Assemblies we might see a FileLoadException while debugging in Visual Studio as shown in below Screen shot.

fileloadexception

Just use this attribute useLegacyV2RuntimeActivationPolicy=”true” in the app.config <startup> element of the calling application and then rebuild which should fix the issue.

Sample app.config below

<?xml version=”1.0″ encoding=”utf-8″ ?>

<configuration>

<startup useLegacyV2RuntimeActivationPolicy=”true”>

<supportedRuntime version=”v4.0″ sku=”.NETFramework,Version=v4.5.2″ />

</startup>

</configuration>