Home Analyst Portal

Work items with ACTIVITIES or RELATED ITEMS should have a flag letting analyst know items are there.

Jason_MeyerJason_Meyer Customer Advanced IT Monkey ✭✭✭
Please add some kind of flag for analysts when a work item has ACTIVITIES associated with it.  In our environment 90% of requests do not have ACTIVITIES, so when analysts are assigned a ticket that does, they are not aware.   It could be as simple as adding a number behind the menu.     Like    ACTIVITIES (3)     for a request that has 3 activities.   Just something to help the analyst realize there is information there.

Comments

  • Justin_WorkmanJustin_Workman Cireson Support Super IT Monkey ✭✭✭✭✭
    @Jason_Meyer - This is a great idea!  I threw this bit of js together to accomplish this.  If you add this to you custom.js file in CiresonPortal/CustomSpace it should do the trick.  
    $(document).ready(function () {
    	var mainPageNode = document.getElementById('main_wrapper');
    	var observer = new MutationObserver(function(mutations) {
    		var activityTab = $("[data-cid='Activities']")
    		if (activityTab.length > 0 ) {
    			if (pageForm.viewModel.Activity.length > 0) {
    			setActivityText(activityTab[0]);
    			observer.disconnect();
    			return; 
    			}
    			else {
    				observer.disconnect;
    				return;
    			}
    		}
    	});
    
    
    	var observerConfig = { attributes: true, childList: true, subtree: true, characterData: true };
    	observer.observe(mainPageNode, observerConfig);
    	
    	function setActivityText(control) {
    		var newActivityText = control.text + " (" + pageForm.viewModel.Activity.length + ")";
    		control.text = newActivityText;
    	}
    });
    


  • Brian_WiestBrian_Wiest Customer Super IT Monkey ✭✭✭✭✭
    Very cool. I added to my farms.
    Just one question.
    Is it possible to have the count = to non completed activities? 
  • Jeff_LangJeff_Lang Customer Ninja IT Monkey ✭✭✭✭
    @Brian_Wiest

    To have it calculate the number of activities that are not yet completed and to display that, you could try something like
    $(document).ready(function () {<br>	var mainPageNode = document.getElementById('main_wrapper');<br>	var observer = new MutationObserver(function(mutations) {<br>		var activityTab = $("[data-cid='Activities']")<br>		if (activityTab.length > 0 ) {<br>			var activeActivityCount = 0;<br>			for (var i = 0; i < pageForm.viewModel.Activity.length; i++) {<br>				if (pageForm.viewModel.Activity[i].Status.Name != 'Completed') { <br>					activeActivityCount = activeActivityCount + 1;<br>				}<br>			}<br>			if (activeActivityCount  > 0) {<br>				setActivityText(activityTab[0], activeActivityCount );<br>				observer.disconnect();<br>				return; <br>			}<br>			else {<br>				observer.disconnect;<br>				return;<br>			}<br>		}<br>	});<br><br><br>	var observerConfig = { attributes: true, childList: true, subtree: true, characterData: true };<br>	observer.observe(mainPageNode, observerConfig);<br>	<br>	function setActivityText(control, count) {<br>		var newActivityText = control.text + " (" + count + ")";<br>		control.text = newActivityText;<br>	}<br>});<br><br>


  • Justin_WorkmanJustin_Workman Cireson Support Super IT Monkey ✭✭✭✭✭
    @Jeff_Lang - Very nice addition!  It works well!

  • Jeff_LangJeff_Lang Customer Ninja IT Monkey ✭✭✭✭
    @Brian_Wiest @Justin_Workman

    seems there is an issue with counting the activities, I was just doing something else with them and when you get activities inside PA's or SA's they are not counted at the base level, so they have to be added recursively

    eg if pageForm.viewModel.Activity[i] refers to a PA with 4 activities inside the PA, then those 4 activities do not count in the initial pageForm.viewModel.Activity.length

    to get around this you would also need to loop through pageForm.viewModel.Activity[i].Activity as well, and however many turtles deep it goes :)

  • Brian_WiestBrian_Wiest Customer Super IT Monkey ✭✭✭✭✭
    Wondering if the great scripts could extend this a little more or as separate script that does the same count for attachments on the Related Items tabs. This would allow analysts to directly see that there are attachments in the request. Thanks
  • Tom_HendricksTom_Hendricks Customer Super IT Monkey ✭✭✭✭✭
    I started working on a Related Items script that steals shamelessly from this one, but unfortunately needs to be a bit more complex.  Open to feedback on the approach, here.

    The idea is: Get the "RelatedItems" tab, attach an observer to the pane with the same ID (see where it is getting complicated, now?), watch for controls that will be bound and count the length of viewModel objects with the same name (data-control-bind attribute).

    Results are mixed.  Sometimes I get a total that is exactly less than one (adding all controls together... so it is not an issue of starting at zero), and sometimes I get nothing back when I should be seeing results.  I think my code, as it currently is, disconnects the observer before all the controls are bound.

    This is a hastily-made work in progress, but maybe it will spur better ideas (this runs inside an existing document.ready() function, so it is not shown here):

    var mainPageNode = document.getElementById('main_wrapper');
    var relObserver = new MutationObserver(function (mutations) {
        var itemsTab = $("[data-cid='RelatedItems']");
        if (itemsTab.length > 0) {
     
            var itemTabId = $(itemsTab).attr("href");
            var itemTabContainer = $(itemTabId);
     
     
            var items = 0;
            var controls = $(itemTabContainer).find('div[data-control-bind]');
            if ($(controls).length > 0) { 
                $(controls).each(function () {
                    var relName = $(this).attr("data-control-bind");
                    if (pageForm.viewModel[relName] && pageForm.viewModel[relName].length) {
                        var moreItems = pageForm.viewModel[relName].length;
                        items = items + moreItems;
                    }
                });
     
                //if (items > 0) {
                $(itemsTab).text($(itemsTab).text() + " (" + items + ")");
                //}
    
                relObserver.disconnect();
                return;
            }
        }
    });
     
    var relObserverConfig = { attributes: true, childList: true, subtree: true, characterData: false };
    relObserver.observe(mainPageNode, observerConfig);


  • Jeff_LangJeff_Lang Customer Ninja IT Monkey ✭✭✭✭
    here is one that loops through PA's and SA's to get all the activities it misses counting by just grabbing the first number, it also counts related item lists and adds to the related items tab.

    at the top are a few variables  to set which related items lists to add to the count, to add specific lists just change the false to a true for the variable, by default it if just counting file attachments, but it can also do related CI's, WorkItems, and Watchers

    $(document).ready(function () {<br><br>	// set which Related Items to count, all set to true will be added to the displayed count<br>	var countRelatedCIs = false;<br>	var countFileAttachments = true;<br>	var countWorkItems = false;<br>	var countWatchers = false;<br><br>	var mainPageNode = document.getElementById('main_wrapper');<br>	var observer = new MutationObserver(function(mutations) {<br>		var activityTab = $("[data-cid='Activities']")<br>		if (activityTab.length > 0 ) {<br>			var activeActivityCount = 0;<br>			activeActivityCount = countActivities(pageForm.viewModel.Activity, activeActivityCount);<br>			if (activeActivityCount  > 0) {<br>				setActivityText(activityTab[0], activeActivityCount );<br>				observer.disconnect();<br>			} else {<br>				observer.disconnect;<br>			}<br>		}<br><br>		var relatedTab = $("[data-cid='RelatedItems']");<br>		if (relatedTab.length > 0 ) {<br>			var relatedItemsCount = 0;<br>			if (countRelatedCIs) { relatedItemsCount = relatedItemsCount + pageForm.viewModel.RelatesToConfigItem.length; }<br>			if (countFileAttachments) { relatedItemsCount = relatedItemsCount + pageForm.viewModel.FileAttachment.length; }<br>			if (countWorkItems) { relatedItemsCount = relatedItemsCount + pageForm.viewModel.RelatesToWorkItem.length; }<br>			if (countWatchers) { relatedItemsCount = relatedItemsCount + pageForm.viewModel.WatchList.length; }<br>			if (relatedItemsCount > 0) {<br>				setActivityText(relatedTab[0], relatedItemsCount );<br>				observer.disconnect();<br>			} else {<br>				observer.disconnect;<br>			}<br>		}<br>	});<br><br>	var observerConfig = { attributes: true, childList: true, subtree: true, characterData: true };<br>	observer.observe(mainPageNode, observerConfig);<br>	<br>	function countActivities(pFvMA, currCount) {<br>		for (var i = 0; i < pFvMA.length; i++) {<br>			if (pFvMA[i].Status.Name != 'Completed') { <br>				currCount = currCount + 1;<br>			}<br>			if (typeof(pFvMA[i].Activity) != 'undefined') {<br>				if (pFvMA[i].Activity.length > 0) {<br>					currCount = countActivities(pFvMA[i].Activity, currCount);<br>				}<br>			}<br>		}<br>		return currCount;<br>	}<br><br>	function setActivityText(control, count) {<br>		var newActivityText = control.text + " (" + count + ")";<br>		control.text = newActivityText;<br>	}<br>});<br>
  • Tom_HendricksTom_Hendricks Customer Super IT Monkey ✭✭✭✭✭
    I like this.  Much better.  Since my tickets are laid out a bit differently, I have a switch statement at the top that configures the bools at the top based on the ticket class.  It's an easy add.

    Now if we can just capture related KB article count this simply...
  • Rob_SimonRob_Simon Customer Adept IT Monkey ✭✭
    This is great! Just installed the code and working perfectly.
  • Tom_HendricksTom_Hendricks Customer Super IT Monkey ✭✭✭✭✭
    I was showing this off in my test environment and someone asked why it doesn't update when items are added/removed. So now it does.  :)  It also grabs KB articles, now that I realized that it isn't in the viewModel if you don't have any related articles.

    I also changed this from using a mutationObserver to just using the app.custom.formTasks.  That hasn't been useful for many other custom functions lately, but in this case it is perfect!

    // Define the forms that you wish to add an item count to, and which items should be counted.
    var formItems = {
        "ChangeRequest": ["RelatesToConfigItem", "FileAttachment", "RelatesToWorkItem", "WatchList", "RelatedHTMLKB"],
        "ServiceRequest": ["RelatesToConfigItem", "FileAttachment", "RelatesToWorkItem", "WatchList", "RelatedHTMLKB"],
        "Incident": ["RelatesToConfigItem", "FileAttachment", "RelatesToWorkItem", "WatchList", "RelatedHTMLKB"],
        "Problem": ["RelatesToConfigItem", "FileAttachment", "RelatesToWorkItem", "WatchList", "RelatedHTMLKB"]
    };
     
    function setItemCount(updateActivities, itemList) {
        if (updateActivities) {
            var activityTab = $("[data-cid='Activities']")
            if (activityTab.length > 0) {
                var activeActivityCount = 0;
                activeActivityCount = countActivities(pageForm.viewModel.Activity, activeActivityCount);
                if (activeActivityCount > 0) {
                    setActivityText(activityTab[0], activeActivityCount);
                }
            }
        }
     
        // Update the related items tab, if present
        var relatedTab = $("[data-cid='RelatedItems']");
        if (relatedTab.length > 0) {
            var relatedItemsCount = 0;
            // Count the items for each item type passed in (edit formItems to modify which are counted)
            $.each(itemList, function (index, value) {
                if (pageForm.viewModel[value]) { relatedItemsCount += pageForm.viewModel[value].length; }
            });
            if (relatedItemsCount > 0) {
                setActivityText(relatedTab[0], relatedItemsCount);
            }
        }
     
        function countActivities(pFvMA, currCount) {
            for (var i = 0; i < pFvMA.length; i++) {
                if (pFvMA[i].Status.Name != 'Completed') {
                    currCount = currCount + 1;
                }
                if (typeof (pFvMA[i].Activity) != 'undefined') {
                    if (pFvMA[i].Activity.length > 0) {
                        currCount = countActivities(pFvMA[i].Activity, currCount);
                    }
                }
            }
            return currCount;
        }
     
        // Create or change the number on the tab 
        function setActivityText(control, count) {
            var tagText = " (" + count + ")";
            var countTag = $(control).children("span.itemCount");
            if (countTag.length > 0) {
                countTag.html(tagText);
            }
            else {
                var newActivityText = control.text + "<span class='itemCount'>" + tagText + "</span>";
                $(control).html(newActivityText);
            }
        }
    }
     
    // Add the boundReady and boundChange tasks to the app.custom.formTasks collection
    for (var key in formItems) {
        app.custom.formTasks.add(key, null, function (formObj, viewModel) {
            formObj.boundReady(function () {
                setItemCount(true, formItems[key]);
            });
            $.each(formItems[key], function (index2, value2) {
                formObj.boundChange(value2, function () {
                    setItemCount(false, formItems[key]);
                });
            });
        });
    }


  • Brian_WiestBrian_Wiest Customer Super IT Monkey ✭✭✭✭✭
    Minor update suggestion on how I implemted. 
    For the activity count updated 
    if (pFvMA[i].Status.Name != 'Completed') {
    to 
    if (pFvMA[i].Status.Name == 'Pending' || pFvMA[i].Status.Name == 'In Progress') {
    
    This now does a direct count so Skipped and On hold do not show up on the total. Guess anyone can update to how their specific environment whats to track. :smile:
  • Jason_MeyerJason_Meyer Customer Advanced IT Monkey ✭✭✭

    Thanks everyone.  Question asked on Friday, up and running in our test environment a few days later.

  • Justin_WorkmanJustin_Workman Cireson Support Super IT Monkey ✭✭✭✭✭
    @Jason_Meyer - Thanks for asking the question!  I think some cool stuff came out of this conversation!
  • Marek_LefekMarek_Lefek Customer Advanced IT Monkey ✭✭✭
    edited April 2018
    Great idea. Implemented. Is there an option to not count PA, SA, RB? or count only RA and MA.
    eg. now it counts PA that will be closed automaticly.
  • Tom_HendricksTom_Hendricks Customer Super IT Monkey ✭✭✭✭✭
    Inside of the countActivities function, you could add an additional check to the if statement that Brian Wiest modified, to check what kind of activity it is.  For example:

    if ((pFvMA[i].Status.Name == 'Pending' || pFvMA[i].Status.Name == 'In Progress') 
    && (['System.WorkItem.Activity.ParallelActivity','System.WorkItem.Activity.SequentialActivity','Microsoft.SystemCenter.Orchestrator.RunbookAutomationActivity','System.WorkItem.Activity.SMARunbookActivity'].indexOf(pFvMA[i].ClassName) == -1)) {

    The idea is that if the activity's class name is NOT in the array (its index would be -1 if not present), it will be counted.  You could reverse this to include the classes you DO want to count, and test if its index is >= 0.
  • Marek_LefekMarek_Lefek Customer Advanced IT Monkey ✭✭✭
    Thanks @Tom_Hendricks!
  • Michael_CostelloMichael_Costello Customer IT Monkey ✭
    We implemented Jeff's version of this back in February.  Thank you all for this.  Today I noticed that the Related Items count is not displaying in IE 11 for CRs or SRs, portal version 8.4.3.  It works in Chrome though.  I tried Tom's version and IE seemed to like that less, as activities stopped displaying the count also.  Is this happening for anyone else?
  • Tom_HendricksTom_Hendricks Customer Super IT Monkey ✭✭✭✭✭
    I am not able to reply with it right at this moment, but I believe we also saw a bug with my version in certain browsers, dealing with the for loop at the bottom of the script.  IIRC, it had to do with the "key" being the name of the form in some browsers but just an integer in others.  I switched this to a JQuery $(obj).each(function(){}) statement and put both key and index in the function, which then helped this to work properly.  I might be able to provide the actual code tomorrow.
  • Brian_WiestBrian_Wiest Customer Super IT Monkey ✭✭✭✭✭
    In my environment we are running IE11 on Win10 LTSB and Chrome.
    This add on is running without issue on both browsers, on v8.4.3 and v8.5.0. 
    Is it possible you have another customspace js that is impacting this one? Does the console report anything?
    Attached is my version I am running. 
    HTH
  • Michael_CostelloMichael_Costello Customer IT Monkey ✭
    Well gents, I must have miss typed something when I tried it yesterday. I got it working.  I stripped out everything from custom.js and put in Tom's version.  That worked.  Then I added one thing back at a time and tested everything in between and its still working.  Thanks for the input.
  • Silas_SulserSilas_Sulser Customer Advanced IT Monkey ✭✭✭
    This is a very nice feature!
    I've recognized that the activities are only being counted if your portal language is set to English.
    Somehow it does not work for German portal language?



    Does anybody know why?

    Thanks and best regards
  • Brian_WiestBrian_Wiest Customer Super IT Monkey ✭✭✭✭✭
    Try updating line 36
    if ((pFvMA[i].Status.Name == 'Pending' || pFvMA[i].Status.Name == 'In Progress')

    To the localized versions of Pending and In Progress. 
  • Roland_KindRoland_Kind Partner Advanced IT Monkey ✭✭✭

    Hi,

    just as an other approach (to be language independent) --> use Id (GUID) - the ID should be static for all languages

    e.g. inProgress GUID =11fc3cef-15e5-bca4-dee0-9c1155ec8d83

    if ((pFvMA[i].Status.Id == '50c667cf-84e5-97f8-f6f8-d8acd99f181c' || pFvMA[i].Status.Id == '11fc3cef-15e5-bca4-dee0-9c1155ec8d83')

    maybe this helps


  • Justin_WorkmanJustin_Workman Cireson Support Super IT Monkey ✭✭✭✭✭
    Good call @Roland_Kind!

  • Silas_SulserSilas_Sulser Customer Advanced IT Monkey ✭✭✭

    Hi,

    just as an other approach (to be language independent) --> use Id (GUID) - the ID should be static for all languages

    e.g. inProgress GUID =11fc3cef-15e5-bca4-dee0-9c1155ec8d83

    if ((pFvMA[i].Status.Id == '50c667cf-84e5-97f8-f6f8-d8acd99f181c' || pFvMA[i].Status.Id == '11fc3cef-15e5-bca4-dee0-9c1155ec8d83')

    maybe this helps


    This did the trick, many thanks! ;)
  • Marek_LefekMarek_Lefek Customer Advanced IT Monkey ✭✭✭
    edited October 2018
    HI, does anyones try to modify counter to display number of all dependent aactivities to get eg. ACTIVITIES (3/5) means that 3 of 5 activities are not completed? I'll appreciate help with code.
  • Brian_WiestBrian_Wiest Customer Super IT Monkey ✭✭✭✭✭
    It is available in the last post I did with the attachment.
  • Marek_LefekMarek_Lefek Customer Advanced IT Monkey ✭✭✭
    I try your code from May 11, but I'm not so good programmer to modify this code with success.
Sign In or Register to comment.