I want to customize widget "My Request" on Service Portal.

ayano
Giga Guru

 

This is the widget "My Request" on Service Portal.

I want to display group name that person who opened Incident belong to next to the name. (The place I want to display is red square below.)

If the person belong to multiple groups, I'd like to display all group names.

How should I make it?

find_real_file.png

1 ACCEPTED SOLUTION

So looking at the HTML that is rendered through the following after angularjs runs:

<small class="text-muted">
  <div ng-repeat="f in item.secondary_displays" class="secondary-display">
    <span >INC0010019</span>
  </div>
  <div ng-repeat="f in item.secondary_displays" class="secondary-display">
    <span >1 - High</span>
  </div>
  <div ng-repeat="f in item.secondary_displays" class="secondary-display">
    <span >Avano Ishida</span>
  </div>
  <div>
    <span>My Group Name</span>
  </div>
</small>

 

What you are wanting to do is get the last two divs to be side by side rather than one above the other. There are a few ways to deal with that but I will show you a CSS only one.

// Added this class to the small html element. "<small class="text-muted secondary-wrapper">"
.secondary-wrapper {
  // Use flexbox to order the elements to make it easiet to align the items
  display: flex;

  // Allows the elements to wrap to a new line
  flex-wrap: wrap;
  
  // Most elements should be max width so there is one on each line
  div {
    width: 100%;
  }

  // Second last and last element should share a line
  div:nth-last-child(2), div:last-child {
    width: unset;
  }
  
  // Add some distance between the second last and last element
  div:last-child {
    margin-left: 1em;
  }
}

 

The result looks like:

find_real_file.png

 

Note that this will always make the second last and last lines in the small element share a line.

View solution in original post

9 REPLIES 9

[Server script]

(function() {
    
    var alsoRequest = false;
    
    var localInput = input; //to safeguard pollution of 'input' via BR or other scripts
    
    data.filterMsg = gs.getMessage("Search open requests");
    
    if (localInput && localInput.view === 'open')
        data.filterMsg = gs.getMessage("Search open requests");
    else if (localInput && localInput.view === 'close')
        data.filterMsg = gs.getMessage("Search closed requests");

    function getField(gr, name) {
            var f = {};
            var id = gr.getUniqueValue();
            gr = new GlideRecord(gr.getRecordClassName());
            gr.get(id);
            f.display_value = gr.getDisplayValue(name);
            f.value = gr.getValue(name);
            var ge = gr.getElement(name);
          if (ge) {
                var ed = ge.getED();
                if (ed)
                    f.type = ed.getInternalType();
                f.label = ge.getLabel();
            }
            return f;
    }

    function getMyRequestSysIds() {
        var ids = {};
        var rq_filter = new GlideRecord('request_filter');
        rq_filter.addActiveQuery();
        if (rq_filter.isValidField('applies_to'))
            rq_filter.addQuery('applies_to', 1).addOrCondition('applies_to', 10);
        rq_filter.query();
        while(rq_filter.next()) {
            var tableName = rq_filter.table_name;
            if (rq_filter.isValidField('table'))
                tableName = rq_filter.table;
            var gr = new GlideRecord(tableName);
            gr.addQuery(rq_filter.filter);
            gr.query();
            if (tableName == 'sc_request')
                alsoRequest = true;
            while(gr.next()) {
                var portalSettings = {};
                portalSettings.page = rq_filter.portal_page.nil()? '' : rq_filter.portal_page.getDisplayValue() + '';
                portalSettings.primary_display = rq_filter.primary_display.nil()? '': rq_filter.primary_display + '';
                portalSettings.secondary_displays = rq_filter.secondary_display.nil()? '': rq_filter.secondary_display + '';
                ids[gr.sys_id + ''] = portalSettings;
            }
        }
        return ids;
    }
    
    function GetGroupsForUser(user) {
  var gr = new GlideRecord('sys_user_grmember');
  gr.addQuery('user', user);
  gr.query();

  var res = [];
  while (gr.next()) {
    res.push(gr.getDisplayValue('group'));
  }

  return res;
}

    // retrieve the request's
    var myRequestMap = getMyRequestSysIds();
    var taskIDs = Object.keys(myRequestMap);

    var gr = new GlideRecordSecure('task');
    if (localInput && localInput.view === 'open')
        gr.addActiveQuery();
    else if (localInput && localInput.view === 'close')
        gr.addQuery('active', 0);
    else
        gr.addActiveQuery();

    gr.orderByDesc('sys_updated_on');
    if (localInput && localInput.search_text) {
            var req = [];
            var task = new GlideRecordSecure('task');
            task.addQuery('123TEXTQUERY321', localInput.search_text);
            if (localInput && localInput.view === 'open')
                task.addQuery('active', 1);
            else if (localInput && localInput.view === 'close')
                task.addQuery('active', 0);
            else
                task.addQuery('active', 1);
            task.addQuery('sys_id', taskIDs);
            task.query();

            while(task.next())
                req.push(task.getUniqueValue());
        
            if (alsoRequest) {
                var ritmGR = new GlideRecord('sc_req_item');
                if (localInput && localInput.view === 'open')
                    ritmGR.addQuery('request.active', 1);
                else if (localInput && localInput.view === 'close')
                    ritmGR.addQuery('request.active', 0);
                else
                    ritmGR.addQuery('request.active', 1);
                ritmGR.addQuery('123TEXTQUERY321', localInput.search_text);
                ritmGR.addQuery('request.sys_id', taskIDs);
                ritmGR.query();
                while(ritmGR.next())
                    req.push(ritmGR.getValue('request'));
            }
            gr.addQuery('sys_id', req);
        }
        else
            gr.addQuery('sys_id', taskIDs);
    gr.query();

    data.request = {};

// Just before the record is pushed to the req_list
record.groups = GetGroupsForUser(gr.getValue('opened_by'));
    
    data.request.req_list = [];
    var recordIdx = 0;    
    var limit = options.items_per_page? options.items_per_page : 15;
    if (localInput && localInput.action == 'fetch_more')
        data.lastLimit = localInput.lastLimit + limit;
    else
        data.lastLimit = limit;

    data.hasMore = false;
    while (recordIdx != data.lastLimit && gr.next()) {
        var portalSettings = myRequestMap[gr.getUniqueValue()];
        if (typeof portalSettings == 'undefined')
            portalSettings = {};

        var record = {};
        record.sys_id = gr.getValue('sys_id');

        if (gr.getRecordClassName() == 'sc_request') {
                var ritm = new GlideRecord("sc_req_item");
                ritm.addQuery("request", gr.getUniqueValue());
                ritm.query();
                if (ritm.getRowCount() == 0)
                    continue;
                if (ritm.getRowCount() > 1)
                    record.display_field = gs.getMessage("{0} requested items", ritm.getRowCount());
                else {
                    ritm.next();
                    record.display_field = ritm.cat_item.getDisplayValue() || ritm.getDisplayValue("short_description");
                }
                record.url = { id: portalSettings.page? portalSettings.page: 'sc_request', table: 'sc_request', sys_id: record.sys_id};
        } else {
                record.display_field = portalSettings.primary_display ? getField(gr, portalSettings.primary_display).display_value : getField(gr, 'number').display_value;
                record.url = { id: portalSettings.page? portalSettings.page :'ticket', table: gr.getRecordClassName(), sys_id: record.sys_id};
        }
        if (portalSettings.secondary_displays) {
            record.secondary_displays = [];
            portalSettings.secondary_displays.split(",").forEach(function (sDisplay){
                record.secondary_displays.push(getField(gr, sDisplay));
            });
        }
        else
            record.secondary_displays = getField(gr, 'short_description');
        
        record.updated_on = gr.getValue('sys_updated_on');
        record.state = gr.getDisplayValue('state');
        if((recordIdx !== 0) && (data.lastLimit - limit === recordIdx))
            record.highlight = true;

        data.request.req_list.push(record);
        recordIdx++;
    }

    if (gr.next())
            data.hasMore = true;
})();

 

Is the place to add right?

The HTML is in the right place for my demo, but the following line should move.

// Just before the record is pushed to the req_list
record.groups = GetGroupsForUser(gr.getValue('opened_by'));

 

Place it new the end of the script just above the "data.request.req_list.push(record)":

if((recordIdx !== 0) && (data.lastLimit - limit === recordIdx))
  record.highlight = true;

// HERE!
// Just before the record is pushed to the req_list
record.groups = GetGroupsForUser(gr.getValue('opened_by'));
// END HERE

data.request.req_list.push(record);
recordIdx++;

Thank you so much!!

It worked!!

But it was displayed in box of blue, not in box of Red.

find_real_file.png

So looking at the HTML that is rendered through the following after angularjs runs:

<small class="text-muted">
  <div ng-repeat="f in item.secondary_displays" class="secondary-display">
    <span >INC0010019</span>
  </div>
  <div ng-repeat="f in item.secondary_displays" class="secondary-display">
    <span >1 - High</span>
  </div>
  <div ng-repeat="f in item.secondary_displays" class="secondary-display">
    <span >Avano Ishida</span>
  </div>
  <div>
    <span>My Group Name</span>
  </div>
</small>

 

What you are wanting to do is get the last two divs to be side by side rather than one above the other. There are a few ways to deal with that but I will show you a CSS only one.

// Added this class to the small html element. "<small class="text-muted secondary-wrapper">"
.secondary-wrapper {
  // Use flexbox to order the elements to make it easiet to align the items
  display: flex;

  // Allows the elements to wrap to a new line
  flex-wrap: wrap;
  
  // Most elements should be max width so there is one on each line
  div {
    width: 100%;
  }

  // Second last and last element should share a line
  div:nth-last-child(2), div:last-child {
    width: unset;
  }
  
  // Add some distance between the second last and last element
  div:last-child {
    margin-left: 1em;
  }
}

 

The result looks like:

find_real_file.png

 

Note that this will always make the second last and last lines in the small element share a line.