Home Analyst Portal

Portal is now 8.9 but some customisations from custom.js work while others dont. any ideas?

Mina_SaidiMina_Saidi Customer IT Monkey ✭

Hi All, We have upgraded recently to the latest version of the portal and not all our customisations are loading.
Our custom.js file has a few customisations, some work and some don’t.
e.g. the ‘adding comment to private” doesn’t work but the custom work item menu badge works customization works. e.g our home page customizations load but gird picker filter doesn't. All were working before the upgrade and are working in our production environment which is on 8.4 version at the moment but are not working correctly in dev (8.9 version). Can we have a look at this? We need it to work, is this an issue with the latest version of the portal, may be some customisations are not compatible with the latest version of the portal? Kind Regards

Answers

  • Brian_WiestBrian_Wiest Customer Super IT Monkey ✭✭✭✭✭
    Do you have everything in one custom.js file, or each customization is in its own file with the custom.js just running the getscript functions? I am running v8.9 and all my customization are working. I have seen sometimes for two different customization option cause issues. So when troubleshooting after an upgrade I turn off all customization and enable one at a time. and sometimes just the affected one to see the behavior and if any error in dev tools.
  • Mina_SaidiMina_Saidi Customer IT Monkey ✭

    Hi Brian,

    We have each customization in its separate file with the custom.js just running the getscript functions.

    I haven't tried turning them off and re-enabling them. I will give it a shot. im not very good with the dev tools :(

    I will give it a shot.


    Thanks for your reply.

  • Jeff_LangJeff_Lang Customer Ninja IT Monkey ✭✭✭✭

    we've found quite a few customization's that use observers need to have the the observer.disconnect line moved to get those scripts working, the grid picker filter was one of those scripts. moving the observer.disconnect(); line up into the if statement right above it should fix this one, and it should also work on both the most recent and previous versions of the portal.

    eg change
    <code>			//We are done observing.<br>			observer.disconnect();<br>        }
    if (titleElement.length > 0) { //An element with class of page_title exists.<br> var gridElement = $('[data-role=grid]') // Get the grid object<br> if (gridElement.length > 0) {<br> fnAddCustomFilterInputBoxToPage();<br> }<br>
    to
            if (titleElement.length > 0) { //An element with class of page_title exists.<br>			var gridElement = $('[data-role=grid]') // Get the grid object<br>			if (gridElement.length > 0) {<br>				fnAddCustomFilterInputBoxToPage();<br>				//We are done observing.<br>				observer.disconnect();<br>			}<br>        }<br><br>
    it's probably best to check any that are not working and if they use observers do the same to them, that should get most of them fixed for you hopefully
  • Mina_SaidiMina_Saidi Customer IT Monkey ✭

    thanks Jeff.

    I have had a look at the code that we are using for the custo grid picker filter and it doesn't have the "oberser.disconnect"

    /*
     Customise Grid Control UI to Provide Better Feedback
     and
     Sort Grid Control Alphabetically.
    */

    $(document).ready(function() {
        if (document.URL.indexOf("ServiceCatalog/RequestOffering") === -1) { //Only worry about request offering forms
            return;
        }
       
        //Get all objects that hold our kendo grids.
        var divGridControls = $("div[data-control=checkboxGridByCriteriaOld");

        for (var i = 0; i < divGridControls.length; i++) {       
            //Re-get this element as an object.
            var thisKendoGrid = $(divGridControls[i]).getKendoGrid();
        
      var kendoGridIndex = i;
      thisKendoGrid.kendoGridIndex = kendoGridIndex;
      
      /*Track if Grid is configured for 'Multi-Select'*/
      var isMultiSelect = divGridControls[i].getAttribute("data-control-ismultiselect").toLowerCase().trim();
      if (isMultiSelect == "true") {
       thisKendoGrid.isMultiSelect = true;
      }
      else {
       thisKendoGrid.isMultiSelect = false;
      }
      
      /* Keep track of multiple Selected Items in a separate array
      This is required as 'thisEventKendoGrid.select()' only returns the last selected item, not all items
      Am unsure why this occurs */
      if (thisKendoGrid.isMultiSelect) {
       thisKendoGrid.selectedItems = new Array();
      }
      
      //Add Selection Summary Footer
      var selectSummary_html = "<span id='gridSelectSummary" + kendoGridIndex + "' class='gridSelectSummary'></span>";
      thisKendoGrid.wrapper.find(".k-pager-info").parent().before(selectSummary_html);
      //Pre-set label with 'Empty'
      var selectSummary = "<div class='gridSelectSummary-label'>Selection:</div><div class='gridSelectSummary-label'><i><font color=gray>Empty</font></i></div>"; 
      $("#gridSelectSummary" + kendoGridIndex).html(selectSummary);
      
      //Bind 'Change' event whenever a Grid item is selected.
      thisKendoGrid.bind("change", function (e){
       //Note to self. the dataBound fires after the rows are returned, and dataBinding fires before.
       var thisEventKendoGrid = e.sender;
       //console.log(e.sender);
         
       /*html layout*/
       var selectSummary = "<div class='gridSelectSummary-label'>Selection:</div>";      
       var entry_html_prefix = "<div class='gridSelectSummary-entity'>";
       var entry_html_suffix = "</div>";
       
       var selectedRow = thisEventKendoGrid.select();   
       var entry_name = thisEventKendoGrid.dataItem(selectedRow).DisplayName;
       
       // Update selectedItems Array with changes   
       var selectedItems_index = jQuery.inArray(entry_name, thisEventKendoGrid.selectedItems);   
       
       if (selectedItems_index == -1) {                
        //Empty the array if multiSelect is not enabled, as we are changing the selection.
        if (thisEventKendoGrid.isMultiSelect == false) {
         thisEventKendoGrid.selectedItems = [];
        }
        //Add new entry.
        thisEventKendoGrid.selectedItems.push(entry_name);
       }
       else {
        //Remove entry if re-clicked.
        thisEventKendoGrid.selectedItems.splice(selectedItems_index, 1);
       }   
       
       //Build selected Summary List (using selectedItems Array)
       if (thisEventKendoGrid.selectedItems.length == 0) {
        selectSummary = selectSummary + "<div class='gridSelectSummary-label'><i><font color=gray>Empty</font></i></div>"
       }
       else {
        if (thisEventKendoGrid.isMultiSelect) {
         for (var j = 0; j < thisEventKendoGrid.selectedItems.length; j++) {
          selectSummary = selectSummary + entry_html_prefix + " &nbsp;" + thisEventKendoGrid.selectedItems[j] + "&nbsp; " + entry_html_suffix;
         }
        }
        else {
         selectSummary = selectSummary + entry_html_prefix + " &nbsp;" + entry_name + "&nbsp; " + entry_html_suffix;
        }
       }
       
       /*Show selected Summary*/
       $("#gridSelectSummary" + thisEventKendoGrid.kendoGridIndex).html(selectSummary);
      });
      
      
            var firstColumnName = thisKendoGrid.columns[0].field;
            //var firstColumnTitle = thisKendoGrid.columns[0].title;
            var numberOfRows = thisKendoGrid.dataSource.data().length
            if (numberOfRows > 0)
            {
                //This grid control already has data.
                //Sort this grid, using the first column. This will sort only once, after initial page load, whether items exist in the grid or not.
                thisKendoGrid.dataSource.query({
                  sort: { field: firstColumnName, dir: "asc" },
                  page: 1,
                  pageSize: 8,
                });
            }
            else{
                //If this request offering grid uses a previous question filter, then the initial sort won't work. Set up a one-time sort event.
       thisKendoGrid.one("dataBound", function (e){
                    //Note to self. the dataBound fires after the rows are returned, and dataBinding fires before.
                    var thisEventKendoGrid = e.sender;
                    console.log(e.sender);
                   
                    var firstEventColumnName = thisEventKendoGrid.columns[0].field;
                    var firstEventColumnTitle = thisEventKendoGrid.columns[0].title;
                    //console.log("Databinding changed in event. Sorting by first column '" + firstEventColumnName + "', '" + firstEventColumnTitle + "'");
                    thisEventKendoGrid.dataSource.query({
                      sort: { field: firstEventColumnName, dir: "asc" },
                      page: 1,
                      pageSize: 8,
                    });
                });
            }
        }
    });


    Neither does the code we are using for comments added as private by Default. any other ideas?

    thank for your reply.


    :(



  • Mina_SaidiMina_Saidi Customer IT Monkey ✭

    Sorry that was the code for the grid picker improvement not the code for the gird picker.


    I found the observer.disconnect line and made the change. Cleared my cache, restarted cache builder but no luck. :(

    /* ----------------------------------------------- */
    /* -------------- Custom Grid Search ------------- */
    /* ----------------------------------------------- */

    $(document).ready(function () {
    if (session.user.Analyst == 1){
     var url = window.location.href;
     if(url.indexOf("/View/") == -1 && url.indexOf("/Page/") == -1 )
     {
      // Loosely verify we are on a page with workitems, not using hte GetProjection API call.
      return;
     }
     
     var mainPageNode = document.getElementById('main_wrapper');
     
     // create an observer instance
     var observer = new MutationObserver(function(mutations) {
      
      if ($("#customgridfilter").length > 0) { //It was already added once from somewhere. Fixes an IE multi-observer bug.
       observer.disconnect();
       return;
      }
      
      //The page changed. See if our title exists. If it does, then our gridview should also exist.
      var titleElement = $(".page_title"); //The title "usually" exists. But not on dashboard pages.
      var dashboardElement = $(".dashboard"); //The dashboard always exists for...pages with dashboards.
      //If this page has a gridview, then it also exists as soon as either the title or dashboard div does.
      
            if (titleElement.length > 0 || dashboardElement.length > 0) { //An element with class of page_title exists.
       var gridElement = $('.k-grid-header') // Get the grid object
       if (gridElement.length > 0) {
        fnAddCustomFilterInputBoxToPage();
               //We are done observing.
                                    observer.disconnect();
                        }
      
     });
     
     // configure the observer and start the instance.
     var observerConfig = { attributes: true, childList: true, subtree: true, characterData: true };
     observer.observe(mainPageNode, observerConfig);
     

     function fnAddCustomFilterInputBoxToPage() {
      
      var shouldPrependText = false;
      var isPromotedView = false; //controls filtering options.
      
      var resetViewButtonParentDiv = $(".btn-clear-grid-filters").first().parent();
      if (resetViewButtonParentDiv.length > 0) {
       //We shouldn't use this for a promoted view. Only OOB views.
       var url = window.location.href;
       if (url.indexOf("/c5161e06-2378-4b44-aa89-5600e2d3b9d8") == -1 &&
        url.indexOf("/9a06b0af-2910-4783-a857-ba9e0ccb711a") == -1 && url.indexOf("/cca5abda-6803-4833-accd-d59a43e2d2cf") == -1 &&
        url.indexOf("/f94d43eb-eb42-4957-8c48-95b9b903c631") == -1 && url.indexOf("/62f452d5-66b5-429b-b2b1-b32d5562092b") == -1
        )
       {
        //console.log("Custom Grid View filter - detected promoted view.");
        isPromotedView = true;
       }
      }
      else{
       //There was no button with this grid? Try a widget view then.
       resetViewButtonParentDiv = $("a:contains('Reset State')").first().parent().parent(); //Add another parent.
       shouldPrependText = true;
      }
      
      if (resetViewButtonParentDiv.length == 0) {
       console.log("Found a grid view, but not a reset button. Cannot show search filter in this scenario.");
       return;
      }
      
      var strHtmlToAdd = "<div class='customgridsearch' style='margin-left: 10px; margin-top: 10px; display:inline-block;'>" +
              "<div style='color:#000; font-family:'400 18px/22px',?'Segoe UI',?'Open Sans',?Helvetica,?sans-serif; display:inline-block; width: 400px;'>" +
               "<span>Filter Results:&nbsp;</span>" + "<input type='text' id='customgridfilter' placeholder='Type filter and press enter...' style='color: #000000; width: 200px;' />" +
              "</div>" +
             "</div>"
      
      console.log("Appending grid view filter");
      if (shouldPrependText) {
       $(resetViewButtonParentDiv).prepend(strHtmlToAdd);
      }
      else{
       $(resetViewButtonParentDiv).append(strHtmlToAdd);
      }
      

      $("#customgridfilter").on('keydown', function(e){
       if(e.which == 13) {
        //filter our resultset.
        var strFilterText = $("#customgridfilter").val().trim();
        if (strFilterText.length > 0) {
         fnApplyCustomFilterToGridDataSource(strFilterText, isPromotedView);
        }
       }
       else if (e.which == 27) {//escape
        $("#customgridfilter").val("");
        fnRemoveCustomFiltersOnGridResultSet();
       }
      });
     }
     
     
     function fnApplyCustomFilterToGridDataSource(strFilterValue, isPromotedView) {
      var gridElement = $('[data-role=grid]'); // Get the grid div element
      var kendoGridElement = gridElement.data('kendoGrid'); //...as a kendo widget
      var datasource = kendoGridElement.dataSource;

      var criteriaFilterObjects = []; //empty, for now...
      
      var firstColumn = ""

      for(var i = 0; i < kendoGridElement.columns.length; i++) {
      //for(var i = 0; i < kendoGridElement.columns.length-10; i++) {
       if (kendoGridElement.columns[i].field == "Icon" || kendoGridElement.columns[i].field == "NumericId" ||
         kendoGridElement.columns[i].field == "BaseId" || kendoGridElement.columns[i].field == "ParentWorkItemId")
        continue;
       if (firstColumn == "") {
        //Set the first real column, since we need any column to work with for our kendo datasource OR filter later.
        firstColumn = kendoGridElement.columns[i].field;
       }
       
       if (kendoGridElement.columns[i].DataType == "string" || kendoGridElement.columns[i].DataType == "anchor" ||
        (kendoGridElement.columns[i].DataType == undefined && kendoGridElement.columns[i].field.indexOf("Key") == -1)
          )
       { //when using a filter, the "contains" operator only works with strings, or else it throws a server 500 error.
        //an undefined datatype is a SQL table view from custom SQL source, It still chokes on integers. And we can't guess the type from the column from here?
        
        var newSingleFilterObject = { field: kendoGridElement.columns[i].field, operator: "contains", value: strFilterValue }
        criteriaFilterObjects.push(newSingleFilterObject); //add it to our criteriaFilterObjects
       }
      }

      //kendogridview datasources don't allow us to use an OR directly on them. So instead, do an AND, with a nested OR.
      //In the case, the first valid column is not null, AND any other column contains the filtered data.
      
      var masterFilter = { logic: "and",
              filters: [{
              logic:"or",
              filters: criteriaFilterObjects
             },
             { field : firstColumn, operator : "neq", value: ""} ] //isnotnull doesn't work with this kendo filter?
           }
      //nestedFilterWithOrColumns = criteriaFilterObjects[2];
      //Set our new filter.
      if (isPromotedView) {
       //In some promoted views, the kendo filter is broken. If column 6 has a null value, then the OR clause removes that entire result, even if another column matches :(.
       //This is bypassed by using client-side filtering.
       datasource.options.serverFiltering = false
       datasource.options.serverPaging = false
      }
      datasource.filter(masterFilter);
     }
     
     function fnRemoveCustomFiltersOnGridResultSet() {
      var gridElement = $('[data-role=grid]'); // Get the grid div element
      var kendoGridElement = gridElement.data('kendoGrid'); //...as a kendo widget
      var datasource = kendoGridElement.dataSource;
      datasource.filter([]);
     }
    }
    });
    /* ----------------------------------------------- */
    /* ------------ End Custom Grid Search ----------- */
    /* ----------------------------------------------- */


  • Mina_SaidiMina_Saidi Customer IT Monkey ✭

    below is the code we are using for action log set to private for default.


    notice anything that I should change in this?


    /* ----------------------------------------------- */
    /* --------- IR - Default tick private ----------- */
    /* ----------------------------------------------- */
    //Change Request Tasks
    app.custom.formTasks.add('Incident', null, function(formObj, viewModel){ 
        formObj.boundReady(function () {
      //set comments to private by default
      $("#actionLogisPrivate").trigger("click").closest("div");
      //resets comment to private after adding a comment
      pageForm.viewModel.AppliesToTroubleTicket.bind("change", function () {
       setTimeout(function () {
        $("#actionLogisPrivate").trigger("click").closest("div");
       },0);
      });
     });
    });
    /* ----------------------------------------------- */
    /* ------- END IR - Default tick private --------- */
    /* ----------------------------------------------- */

    /* ----------------------------------------------- */
    /* --------- PR - Default tick private ----------- */
    /* ----------------------------------------------- */
    //Change Request Tasks
    app.custom.formTasks.add('Problem', null, function(formObj, viewModel){ 
        formObj.boundReady(function () {
      //set comments to private by default
      $("#actionLogisPrivate").trigger("click").closest("div");
      //resets comment to private after adding a comment
      pageForm.viewModel.AppliesToTroubleTicket.bind("change", function () {
       setTimeout(function () {
        $("#actionLogisPrivate").trigger("click").closest("div");
       },0);
      });
     });
    });
    /* ----------------------------------------------- */
    /* ------- END PR - Default tick private --------- */
    /* ----------------------------------------------- */

    /* ----------------------------------------------- */
    /* --------- SR - Default tick private ----------- */
    /* ----------------------------------------------- */
    //Change Request Tasks
    app.custom.formTasks.add('ServiceRequest', null, function(formObj, viewModel){ 
        formObj.boundReady(function () {
      //set comments to private by default
      $("#actionLogisPrivate").trigger("click").closest("div");
      //resets comment to private after adding a comment
      pageForm.viewModel.AppliesToWorkItem.bind("change", function () {
       setTimeout(function () {
        $("#actionLogisPrivate").trigger("click").closest("div");
       },0);
      });
     });
    });
    /* ----------------------------------------------- */
    /* ------- END SR - Default tick private --------- */
    /* ----------------------------------------------- */

    /* ----------------------------------------------- */
    /* --------- CR - Default tick private ----------- */
    /* ----------------------------------------------- */
    //Change Request Tasks
    app.custom.formTasks.add('ChangeRequest', null, function(formObj, viewModel){ 
        formObj.boundReady(function () {
      //set comments to private by default
      $("#actionLogisPrivate").trigger("click").closest("div");
      //resets comment to private after adding a comment
      pageForm.viewModel.AppliesToWorkItem.bind("change", function () {
       setTimeout(function () {
        $("#actionLogisPrivate").trigger("click").closest("div");
       },0);
      });
     });
    });
    /* ----------------------------------------------- */
    /* ------- END CR - Default tick private --------- */
    /* ----------------------------------------------- */

  • Jeff_LangJeff_Lang Customer Ninja IT Monkey ✭✭✭✭
    looks like you removed a close brace '}' when you moved that disconnect line

  • Mina_SaidiMina_Saidi Customer IT Monkey ✭

    @jeff_lang

    Hi Jeff,

    I have tried this, does the below look alright? I'm really bad with coding.

    any ideas?

    if (titleElement.length > 0 || dashboardElement.length > 0) { //An element with class of page_title exists.
       var gridElement = $('.k-grid-header') // Get the grid object
       if (gridElement.length > 0) {
        fnAddCustomFilterInputBoxToPage();
              //We are done observing.
        observer.disconnect();
       }
            }

     }


  • Mina_SaidiMina_Saidi Customer IT Monkey ✭

    We are also using the colour coded gried view that goes red for high priority jobs. that seems to work for some reason. looking at the code I found the observer.disconnect line.

     if (titleElement.length > 0 || dashboardElement.length > 0) { //An element with class of page_title exists.
       var gridElement = $('.k-grid-header') // Get the grid object
       if (gridElement.length > 0) {
        fnAddColorCodedGridView();
       }
       
       //We are done observing.
                observer.disconnect();
            }
      
     });
     


    how ever it seems to work without me touching it. while the same layout in the grid view filter doesn't work.

  • Mark_GearyMark_Geary Customer IT Monkey ✭
    Hi We have had the same problem. I have got most of them working but i cant get the user search one to work.
  • Mina_SaidiMina_Saidi Customer IT Monkey ✭

    Hi, we got most of it working as well but not the grid view filter. no matter what I do it doesn't work.

    does anyone else have any ideas with this?

Sign In or Register to comment.