Tick Conversation Widget Not Showing All Activity

stevejarman
Giga Guru

I'd like the Ticket Conversation widget to show ALL activity that's viewable on a ticket when looking at the Platform view/form. I'm finding though that the status changes, email updates, etc don't show up (i.e. the "automatically generated" stuff). I've noticed that these entries also have a different colour (light grey) in the Platform view, so there's some sort of flag or type on them that's different.

I've gone over the widget code but can't spot the problem. Does anyone know why these entries don't show and how to make them show?

PLATFORM:

1.png

SERVICE PORTAL - TICKET CONVERSATIONS:

2.png

11 REPLIES 11

Hi nadon,



At first glance it looks like the "How" to getting the entire activity in the Portal is to clone the widget and add that functionality.


I saw that an option of includeExtended can be set to a boolean value. By default it's set to false and there is no option set in the options schema. So to change that setting you would add an object with the a property of the corresponding name and value of true in the "Additional option json format" field in the widget Intance.


{


  " includeExtended": true;


}



However, all that did was add the ability to add work notes from the Portal side.



So cloning and scripting your own way of getting the additional desired information (possibly from the audit table) and adding it to the client side where it merges the activities would be the "How".


Thank you Chris ! I will give   a try.


stevejarman
Giga Guru

All good. I've commented out the $sp.getStream and I'm just constructing my own stream with the same structure, but using the sys_audit table instead. Seems to be working well but I just need to test with a few more tickets in case there's any weirdness.


Sounds good Steve



Would you be able to post your solution?



Thanks


Sure. It's not the cleanest solution in the world, but it does appear to work just fine.



You want to comment out this line in the server script:



data.stream = $sp.getStream(data.table, data.sys_id);



And replace it with this (or something like it):



// BEGIN REPLACEMENT FOR THE $sp.getStream STREAM USING sys_audit TABLE


data.stream = {};


data.stream.display_value = data.number;


data.stream.label = gr.getLabel();


data.stream.number = data.number;


data.stream.short_description = gr.getDisplayValue("short_description");


data.stream.sys_id = data.sys_id;


data.stream.table = data.table;


data.stream.user_full_name = gs.getUserDisplayName();


data.stream.user_login = gs.getUserName();


data.stream.user_sys_id = gs.getUserID();



data.stream.journal_fields = [];



// A COUPLE OF THINGS WE'LL NEED LATER FOR TESTING WORK_NOTE ACCESS


var hasItilRole = UserHasSpecificRole(gs.getUserName(), "ITIL");


var isInWorkNotesList = false;



if (gr.getValue("work_notes_list"))


      isInWorkNotesList = gr.getValue("work_notes_list").toString().indexOf(gs.getUserID()) == -1 ? false : true;



// ALL OF THE ACTIVITY TYPES THAT WE'D LIKE TO LOOK AT


data.stream.journal_fields.push( { can_read: true, can_write: true, color: "transparent", label: "Additional Comments", name: "comments" } );


data.stream.journal_fields.push( { can_read: true, can_write: true, color: "gold", label: "Work Notes", name: "work_notes" } );


data.stream.journal_fields.push( { can_read: true, can_write: true, color: "green", label: "State", name: "state" } );


data.stream.journal_fields.push( { can_read: true, can_write: true, color: "blue", label: "Priority", name: "priority" } );


data.stream.journal_fields.push( { can_read: true, can_write: true, color: "red", label: "Category", name: "category" } );


data.stream.journal_fields.push( { can_read: true, can_write: true, color: "red", label: "Subcategory", name: "subcategory" } );


data.stream.journal_fields.push( { can_read: true, can_write: true, color: "aqua", label: "Assigned To", name: "assigned_to" } );


data.stream.journal_fields.push( { can_read: true, can_write: true, color: "aqua", label: "Assignment Group", name: "assignment_group" } );


data.stream.journal_fields.push( { can_read: true, can_write: true, color: "pink", label: "Short Description", name: "short_description" } );



fieldTypes = []; // THIS JUST SAVES US TYPING THEM ALL OUT AGAIN BELOW



for (var i = 0; i < data.stream.journal_fields.length; i++)


{


      fieldTypes.push(data.stream.journal_fields[i].name);


}



// ALL OF THE ENTRIES WE WANT TO SEE


data.stream.entries = [];



var rs2 = new GlideRecord("sys_audit");


rs2.addQuery("documentkey", data.sys_id.toString());


rs2.addQuery("tablename", data.table.toString());


rs2.addQuery("fieldname", "IN", fieldTypes.join(","));


rs2.orderByDesc("sys_created_on");


rs2.query();



while (rs2.next())


{


      // TEST USER'S ABILITY TO SEE WORK_NOTES - IF THEY CAN'T, AND THIS IS A WORK_NOTE, SKIP IT!


      if (rs2.fieldname.getValue().toString() == "work_notes" && !hasItilRole && !isInWorkNotesList)


              continue;                    



      data.stream.entries.push( {


              element: rs2.fieldname.getValue(),


              field_label: rs2.fieldname.getDisplayValue(),


              initials: gs.getUserDisplayName().split(" ")[0].toString().substr(0, 1) +gs.getUserDisplayName().split(" ")[1].toString().substr(0, 1),


              login_name: GetUserNameByUserId(rs2.user.getDisplayValue()),


              name: GetUserNameByUserId(rs2.user.getDisplayValue()),


              sys_created_on: rs2.sys_created_on.getValue(),


              sys_created_on_adjusted: rs2.sys_created_on.getDisplayValue(),


              sys_id: rs2.sys_id.toString(),


              user_sys_id: GetSysIdByUserId(rs2.user.getDisplayValue()),


              value: (rs2.newvalue.toString().indexOf("[code]") != -1) ? rs2.newvalue.toString().replace("[code]", "").replace("[/code]", "") : htmlEscape(rs2.newvalue.toString())


      } );



      if (rs2.fieldname.toString() == "state")


              data.stream.entries[data.stream.entries.length - 1].value = "State changed from <b>" +GetChoiceLabelByValue(data.table.toString(), rs2.oldvalue.toString(), "state") +"</b> to <b>" +GetChoiceLabelByValue(data.table.toString(), rs2.newvalue.toString(), "state") +"</b>";



      if (rs2.fieldname.toString() == "priority")


              data.stream.entries[data.stream.entries.length - 1].value = "Priority changed from <b>" +GetChoiceLabelByValue(data.table.toString(), rs2.oldvalue.toString(), "priority") +"</b> to <b>" +GetChoiceLabelByValue(data.table.toString(), rs2.newvalue.toString(), "priority") +"</b>";



      if (rs2.fieldname.toString() == "category")


              data.stream.entries[data.stream.entries.length - 1].value = "Category changed from <b>" +GetChoiceLabelByValue(data.table.toString(), rs2.oldvalue.toString(), "category") +"</b> to <b>" +GetChoiceLabelByValue(data.table.toString(), rs2.newvalue.toString(), "category") +"</b>";


             


      if (rs2.fieldname.toString() == "subcategory")


              data.stream.entries[data.stream.entries.length - 1].value = "Subcategory changed from <b>" +GetChoiceLabelByValue(data.table.toString(), rs2.oldvalue.toString(), "subcategory") +"</b> to <b>" +GetChoiceLabelByValue(data.table.toString(), rs2.newvalue.toString(), "subcategory") +"</b>";


             


      if (rs2.fieldname.toString() == "assigned_to")


              data.stream.entries[data.stream.entries.length - 1].value = "Assigned To changed from <b>" +GetUserNameBySysId(rs2.oldvalue.toString()) +"</b> to <b>" +GetUserNameBySysId(rs2.newvalue.toString()) +"</b>";



      if (rs2.fieldname.toString() == "assignment_group")


              data.stream.entries[data.stream.entries.length - 1].value = "Assignment Group changed from <b>" +GetGroupNameBySysId(rs2.oldvalue.toString()) +"</b> to <b>" +GetGroupNameBySysId(rs2.newvalue.toString()) +"</b>";



      if (rs2.fieldname.toString() == "short_description")


              data.stream.entries[data.stream.entries.length - 1].value = "Short Description changed from <b>" +rs2.oldvalue.toString() +"</b> to <b>" +rs2.newvalue.toString() +"</b>";


}


// END REPLACEMENT FOR THE $sp.getStream STREAM USING sys_audit TABLE


I've also got a bunch of fairly ugly little functions that I'm using throughout this, mostly just to look up users, groups, etc. These could definitely be done cleaner, but I didn't spend a lot of time on them. You can just tack these on at the end somewhere:



// EXTRA FUNCTIONS NEEDED FOR REPLACEMENT CODE


function UserHasSpecificRole(_user, _role)


{


      // SERVER-SIDE ONLY GIVES US HASROLE() WHICH IS OVERRIDDEN BY ADMIN - CUSTOM VERSION WORKS FOR EVERYTHING


      var rs = new GlideRecord("sys_user_has_role");  


      rs.addQuery("user.user_name", _user);  


      rs.addQuery("role.name", _role);  


      rs.query();  


      return rs.hasNext();


}



function GetUserNameByUserId(_id)


{


      var rs = new GlideRecord("sys_user");


      rs.addQuery("user_name", _id);


      rs.query();




      if (rs.next())


              return rs.getDisplayValue();


      else


              return "ServiceNow"; // IF WE CAN'T FIND IT, IT'S MOST LIKELY A BUSINESS RULE OR OTHER INTERNAL PROCESS


}



function GetSysIdByUserId(_id)


{


      var rs = new GlideRecord("sys_user");


      rs.addQuery("user_name", _id);


      rs.query();




      if (rs.next())


              return rs.sys_id.toString();


      else


              return "";


}



function GetUserNameBySysId(_id)


{


      var rs = new GlideRecord("sys_user");


      rs.addQuery("sys_id", _id);


      rs.query();




      if (rs.next())


              return rs.name.getDisplayValue();


      else


              return "Unknown";


}



function GetGroupNameBySysId(_id)


{


      var rs = new GlideRecord("sys_user_group");


      rs.addQuery("sys_id", _id);


      rs.query();




      if (rs.next())


              return rs.name.getDisplayValue();


      else


              return "Unknown";


}



function GetChoiceLabelByValue(_table, _value, _element)


{


      var rs = new GlideRecord("sys_choice");


      rs.addQuery("name", _table);


      rs.addQuery("value", _value);


      rs.addQuery("element", _element);


      rs.query();




      if (rs.next())


              return rs.label.toString();


      else


      {


              // WE DIDN'T FIND IT, ASSUME IT'S UP ON THE TASK TABLE. MANUALLY CHECK ONCE FOR IT, UGLY BUT ALRIGHT


              var rs1 = new GlideRecord("sys_choice");


              rs1.addQuery("name", "task");


              rs1.addQuery("value", _value);


              rs1.addQuery("element", _element);


              rs1.query();




              if (rs1.next())


                      return rs1.label.toString();


              else


                      return "None";


      }      


}


// END EXTRA FUNCTIONS NEEDED FOR REPLACEMENT CODE