The CreatorCon Call for Content is officially open! Get started here.

Dynamic Assigned to Visual Task Boards

jwagner
Tera Contributor

ServiceNow Friends,

We have been able to create task boards on an individual basis. We'd like to have a visual task board exist in the application menu and display results dynamically based on "assigned to". We can create the board we need, but don't want to create individually for each user.

Thanks,

Jeremy

1 ACCEPTED SOLUTION

LaurentChicoine
Tera Guru

Hi Jeremy,



This is a nice idea.



Here is how to do it (I made it in Istanbul so not sure about the compatibility with older versions, differences should only be in the creation of the task board):



1. Create a processor that will create the board if the user does not already have a visual task board for his tasks or if the user already has a board then we will redirect him to that board. The board sys_id will be stored as a user preference of the user.



Name: VTBTasksAssignedToMe


Type: script


Path: vtb_tasks_assigned_to_me


Script:


(function process(g_request, g_response, g_processor) {



      var vtbId = gs.getPreference('vtb.assigned.to.me');


      var vtbGr = new GlideRecord('vtb_board');


     


      if(!vtbId || !vtbGr.get(vtbId)){


              vtbGr = new GlideRecord('vtb_board');


              vtbGr.initialize();


              vtbGr.name = gs.getMessage('Tasks assigned to me');


              vtbGr.owner = gs.getUserID();


              vtbGr.table = 'task';


              vtbGr.filter = 'assigned_toDYNAMIC90d1921e5f510100a9ad2572f2b477fe';


              vtbGr.field = '__KANBAN__';


              vtbGr.card_limit = 1000;


              vtbGr.stream_limit = 50;


              vtbGr.show_list_toggle = true;


              vtbGr.background_color = 'vtb-board-color-1';


              vtbId = vtbGr.insert();


             


              //If using field kanban which is the default lanes we must create these lanes


              if(vtbGr.field == '__KANBAN__'){


                      var lanes = [gs.getMessage('To Do'), gs.getMessage('Doing'), gs.getMessage('Done')];


                     


                      lanes.forEach(function(lane, index){


                              var laneGr = new GlideRecord('vtb_lane');


                              laneGr.initialize();


                              laneGr.board = vtbId;


                              laneGr.name = lane;


                              laneGr.order = index;


                              laneGr.insert();


                      });


                     


              }


             


              //Setting the user prefrence


              gs.getUser().setPreference('vtb.assigned.to.me', vtbId);


      }


     


      g_processor.redirect('$vtb.do?sysparm_board=' + vtbId);



})(g_request, g_response, g_processor);



You can customize the script to change the default values. The filter is an encoded query, you might want to modify it, let's say to add "^active=true".



If you have different needs for that type of Visual Task board generated from a menu you might want to make this processor more scalable by adding parameters. I made it quickly to show the functionality.



2. Create a module to make this processor run



Title: Visual Task Board - Assigned to me (you can give another title if you want)


Application Menu: Choose what you want


Link type: URL (from Arguments:)


Arguments: vtb_tasks_assigned_to_me.do


Roles: If you want to limit the use to a specific role (ex: itil)



3. Create ACL for that processor (Only if you chose to limit the use to the specific role)



Type: processor


Name: VTBTasksAssignedToMe


Requires role: Role(s) you selected for the module



I hope this helps you, don't hesitate if you have any question.


View solution in original post

16 REPLIES 16

Laurent,



The Choice List Specification was the issue! THANK YOU SO MUCH! This was a major roadblock to keep us from upgrading to Jakarta. The only way I know how to set this is from the Form Designer, is it available elsewhere? If I may ask: What led you to believe the Choice List Specification was the issue?   What an obscure problem.



Thanks for the offer on the cleanup script, however, it is not necessary once the Choice list is set the board manages it's own lanes correctly.


Yes it's avaialbe in the dictionary record (sys_dictionary), it can be accessed from the Dictionary module or from the Table module (sys_db_object) when you open the table all the fields are listed and these links points to the dictionary records.



What led me to the issue is the fact that string field are not accepted in VTB (when using it in the normal way, without gliderecord or the standard forms in the platform). You told me that you simply added choices so I suspected you did not modify the choice list specification and was able to reproduce, so I then tried by specifying the choice list specification and it worked as expected, and it makes sense. The developers of the VTB probably added conditions based on that choice list specification field (instead of looking if choices are available) and probably that there is a different check for the choices to retrieve the lanes (which is not based around the previous check for choice list specification).



Glad it helped you in your upgrade!


Laurent,



Thanks for walking us through your train of thought. The insight into the board not working with strings and the inner workings of the VTB were key pieces.



Thanks again!


This was just what I needed after stuggling with trying to use "is(dynamic) Me" filter.

My requirement was to get modules individualized for various task types: incident, change and problem, so I expanded on your code a bit. Basically I added to AVAILABLE TYPES and then did a glide record on sys_choices to get the State labels to generate the lanes.

Thanks for sharing!

 

(function process(g_request, g_response, g_processor) {

var AVAILABLE_TYPES = {
'tasks_assigned_to_me': {
'name': gs.getMessage('Tasks assigned to me'),
'table': 'task',
'preference_name': 'vtb.assigned.to.me',
'filter': 'assigned_toDYNAMIC90d1921e5f510100a9ad2572f2b477fe',
'field': '__KANBAN__'
},

'tasks_assigned_to_my_groups':{
'name': gs.getMessage('Tasks assigned to my groups'),
'table': 'task',
'preference_name': 'vtb.assigned.to.my.groups',
'filter': 'assignment_groupDYNAMICd6435e965f510100a9ad2572f2b47744',
'field': '__KANBAN__'
},

'tasks_assigned_to_my_groups_by_sla':{
'name': gs.getMessage('Tasks assigned to my groups by SLA'),
'table': 'task',
'preference_name': 'vtb.assigned.to.my.groups.by.sla',
'filter': 'assignment_groupDYNAMICd6435e965f510100a9ad2572f2b47744',
'field': 'u_custom_sla_field'
},

'incidents_assigned_to_me': {
'name': gs.getMessage('Incidents Assigned to Me'),
'table': 'incident',
'preference_name': 'vtb.incidents.assigned.to.me',
'filter': 'assigned_toDYNAMIC90d1921e5f510100a9ad2572f2b477fe',
'field': 'state'
},

'problems_assigned_to_me': {
'name': gs.getMessage('Problems Assigned to Me'),
'table': 'problem',
'preference_name': 'vtb.problems.assigned.to.me',
'filter': 'assigned_toDYNAMIC90d1921e5f510100a9ad2572f2b477fe',
'field': 'state'
},
'changes_assigned_to_me': {
'name': gs.getMessage('Changes Assigned to Me'),
'table': 'change_request',
'preference_name': 'vtb.changes.assigned.to.me',
'filter': 'assigned_toDYNAMIC90d1921e5f510100a9ad2572f2b477fe',
'field': 'state'
}
};

var type = g_request.getParameter('type');
if(typeof AVAILABLE_TYPES[type] == 'undefined'){
g_processor.writeOutput(gs.getMessage('Invalid type'));
return;
}
var vtbId = gs.getPreference(AVAILABLE_TYPES[type].preference_name);
var vtbGr = new GlideRecord('vtb_board');

if(!vtbId || !vtbGr.get(vtbId)){
vtbGr = new GlideRecord('vtb_board');
vtbGr.initialize();
vtbGr.name = AVAILABLE_TYPES[type].name;
vtbGr.owner = gs.getUserID();
vtbGr.table = AVAILABLE_TYPES[type].table;
vtbGr.filter = AVAILABLE_TYPES[type].filter;
vtbGr.field = AVAILABLE_TYPES[type].field;
vtbGr.card_limit = 1000;
vtbGr.stream_limit = 50;
vtbGr.show_list_toggle = true;
vtbGr.background_color = 'vtb-board-color-1';
vtbId = vtbGr.insert();


var lanes = [];

//If using field kanban which is the default lanes we must create these lanes
if(vtbGr.field == '__KANBAN__'){
lanes = [gs.getMessage('To Do'), gs.getMessage('Doing'), gs.getMessage('Done')];
}
else if(vtbGr.field == 'state'){
var states = new GlideRecord("sys_choice");
states.addQuery("table", vtbGr.table);
states.addQuery("element", vtbGr.field);
states.orderBy("value");
states.query();
while(states.next()){
lanes.push(states.label.toString());
}
}
lanes.forEach(function(lane, index){
var laneGr = new GlideRecord('vtb_lane');
laneGr.initialize();
laneGr.board = vtbId;
laneGr.name = lane;
laneGr.order = index;
laneGr.insert();
});

//Setting the user prefrence
gs.getUser().setPreference(AVAILABLE_TYPES[type].preference_name, vtbId);
}
g_processor.redirect('$vtb.do?sysparm_board=' + vtbId);
})(g_request, g_response, g_processor);

Ben Collyer
Giga Guru

Laurent Chicoine,



That is a nice piece of work.   I was trying to figure out how to easily move some static VTB between instances and enable them for some users.   This is 90% of my solution.   Thanks.