question_answer availability

john_duchock
Kilo Guru

We recently went live with Service Portal for one of our customers and they noticed that when creating an incident via a record producer, the "options" (variables) are only visible by the "opened by" user.  There is a need to allow Watch List users to see this information.

I have tried modifying the widget by updating the line that toggles the display by removing the "IF".  This allowed the "options" glyphicon to display, but no data was displayed below it:

<!-- <div ng-if="data.variables.length > 0" ng-init="c.variable_toggle = true"> -->
<div ng-init="c.variable_toggle = true">

So, i figured this must be an ACL restriction, however looking at the OOTB ACLs, there is only one ACL for the question_answer table and modifying (and even deleting) did not seem to allow the variables to display.  Even more perplexing is the fact that even ADMIN's cannot see the data...

See screenshots below.  Is this a further ACL problem i am facing or is the issue in the widget?

find_real_file.png

find_real_file.png

1 ACCEPTED SOLUTION

Sure, this is the OOTB Ticket Fields widget for Kingston:

 

HTML

<div ng-if="data.canRead" class="panel b">
  <div class="panel-heading bg-primary">
    <div ng-init="spSearch.targetRequests()">
      <sp-c-link target="form" table="data.table" id="data.sys_id"/>
    </div>
    <span ng-if="data.agent" >
      ${Agent working on this {{data.tableLabel}}}:
      <div>{{data.agent}}</div>
    </span>
    <span ng-if="!data.agent && data.agentPossible" >${Your request has been submitted}</span>
    <span ng-if="!data.agentPossible">${{{data.tableLabel}} record details}</span>
  </div>

  <div class="panel-body">
    <div ng-if="data.fields.length > 0">
      <div class="row">
        <div class="col-md-6 col-sm-12 col-xs-6 m-b break-word" ng-repeat="field in data.fields" 
             ng-if="field.value && (field.type != 'decimal' || field.type == 'decimal' && field.value != 0)" >
          <label class="m-n">{{field.label}}</label>
          <span ng-switch="field.type">
            <div ng-switch-when="glide_date_time" title="{{field.display_value}}">
              <sn-time-ago timestamp="::field.value" />
            </div>
            <div ng-switch-default >{{field.display_value}}</div>
          </span>
        </div>
      </div>
    </div>

    <div ng-if="data.variables.length > 0" ng-init="c.variable_toggle = true">
      <button class="h4 options-btn" ng-click="c.variable_toggle = !c.variable_toggle" aria-expanded="{{c.variable_toggle}}" aria-controls="variables-toggle">
        <span style="font-size: 12px;" class="glyphicon" ng-class="c.variable_toggle ? 'glyphicon-chevron-down' : 'glyphicon-chevron-up'"></span>
        ${Options}
      </button>
      
      <div ng-if="c.variable_toggle" id="variables-toggle" aria-hidden="{{!c.variable_toggle}}">
        <hr role="presentation">
        <div class="m-b break-word" ng-repeat="variable in data.variables | filter:{visible_summary:true}">
          <label class="m-n">{{variable.label}}</label>
          <div>{{variable.display_value}}</div>
        </div>
      </div>
    </div>
  </div>

  <div ng-if="data.agentPossible && !data.agent && options.pickup_msg" class="panel-footer">
    <div id="ticket_fields_footer" class="text-center text-muted" style="font-style: italic;" ng-bind-html="data.pickupMsg">
    </div>
  </div>

</div>

 

CSS

.options-btn {
    border:none;
    background-image:none;
    background-color:transparent;
    -webkit-box-shadow: none;
    -moz-box-shadow: none;
    box-shadow: none;
}

 

Client Script

function ($scope, spUtil) {
		
	spUtil.recordWatch($scope, $scope.data.table, "sys_id=" + $scope.data.sys_id); 
}

 

Server Script

(function(){
	data.pickupMsg = gs.getMessage(options.pickup_msg);
	var gr = $sp.getRecord();
	if (gr == null)
		return;
	
	data.canRead = gr.canRead();
	if (!data.canRead) 
		return;

	var agent = "";
	var a = $sp.getField(gr, 'assigned_to');
	if (a != null)
		agent = a.display_value;

	var fields = $sp.getFields(gr, 'number,state,priority,sys_created_on');
	if (gr.getValue("sys_mod_count") > 0)
		fields.push($sp.getField(gr, 'sys_updated_on'));

	if (gr.getValue('price') > 0)
		fields.push($sp.getField(gr, 'price'));
	
	if (gr.getValue('recurring_price') > 0) {
		var rp = $sp.getField(gr, 'recurring_price');
		if (gr.isValidField("recurring_price"))
			rp.display_value = rp.display_value + " " + gr.getDisplayValue("recurring_frequency");
		fields.push(rp);
	}
	if (gr.isValidField("quantity"))
		fields.push($sp.getField(gr, 'quantity'));

	data.tableLabel = gr.getLabel();
	data.fields = fields;
	data.variables = $sp.getVariablesArray();
	data.agent = agent;
	data.agentPossible = gr.isValidField("assigned_to");
	data.table = gr.getTableName();
	data.sys_id = gr.getUniqueValue();
})()

 

 


Please consider marking my reply as Helpful and/or Accept Solution, if applicable. Thanks!

View solution in original post

7 REPLIES 7

Allen Andreas
Administrator
Administrator

Hi,

Unfortunately, there is more to this story than you may know or perhaps are telling us...unless something is drastically different by my instance vs. yours...something isn't right here. In MY instance, which is Kingston Patch 7, admins and others can see the Options field, in fact I'm looking at one right now that I have no involvement in. It was more just a matter of what conditions you set for the widget as to what records would show, but if you had access, you can see the options tab and by that, I mean it's OOB. Since the widget has to be edited, I believe (not all do, but most), then I would suggest you reapply the OOB one there and check for results.

Furthermore, I'm talking about the ticket fields widget, specifically.

Please mark reply as Helpful/Correct, Thanks!


Please consider marking my reply as Helpful and/or Accept Solution, if applicable. Thanks!

i will check that as we are NOT using the OOTB instance.  We made a copy in order to extend the fields displayed in the summary section.  The goal here is to allow users on the Watch List to view these options...i had just noticed that me (as admin) could not (using our cloned widget).  

I will review / test the OOTB widget today !

Are you sure that your user is not the caller_id value of the incident you are looking at?  Try using three different people as caller_id, opened_by and created_by...

I took a look and when adding the OOTB widget to the page, i get the same effect:  only the caller_id user can see options (ver:  glide-london-06-27-2018__patch2-09-19-2018)

find_real_file.png

 

OOTB (London) code for the Ticket Fields widget:

HTML

<div ng-if="data.canRead" class="panel b">
  <div class="panel-heading bg-primary">
    <div ng-init="spSearch.targetRequests()">
      <sp-c-link target="form" table="data.table" id="data.sys_id"/>
    </div>
    <h2 class="sr-only">${Ticket details}</h2>
    <span ng-if="data.agent" >
      ${Agent working on this {{data.tableLabel}}}:
      <div>{{data.agent}}</div>
    </span>
    <span ng-if="!data.agent && data.agentPossible" >${Your request has been submitted}</span>
    <span ng-if="!data.agentPossible">${{{data.tableLabel}} record details}</span>
  </div>

  <div class="panel-body">
    <dl class="ticket-fields" ng-if="data.fields.length > 0">
        <dt class= "col-md-6 col-sm-12 col-xs-6 break-word" 
            ng-if="field.value && (field.type != 'decimal' || field.type == 'decimal' && field.value != 0)" 
            ng-repeat-start="field in data.fields">{{field.label}}</dt>
        <dd class= "col-md-6 col-sm-12 col-xs-6 break-word" 
            ng-repeat-end ng-switch="field.type" 
            ng-if="field.value && (field.type != 'decimal' || field.type == 'decimal' && field.value != 0)">
          <div ng-switch-when="glide_date_time" title="{{field.display_value}}">
            <sn-time-ago timestamp="::field.value" />
          </div>
          <div ng-switch-default >{{field.display_value}}</div>
        </dd>
    </dl>
    <div ng-if="data.variables.length > 0" ng-init="c.variable_toggle = true">
      <button class="h4 options-btn" ng-click="c.variable_toggle = !c.variable_toggle" aria-expanded="{{c.variable_toggle}}" aria-controls="variables-toggle">
        <span style="font-size: 12px;" class="glyphicon" ng-class="c.variable_toggle ? 'glyphicon-chevron-down' : 'glyphicon-chevron-up'"></span>
        ${Options}
      </button>
      
      <div ng-if="c.variable_toggle" id="variables-toggle" aria-hidden="{{!c.variable_toggle}}">
        <hr role="presentation">
        <div class="m-b break-word" ng-repeat="variable in data.variables | filter:{visible_summary:true}">
          <label class="m-n">{{variable.label}}</label>
          <div>{{variable.display_value}}</div>
        </div>
      </div>
    </div>
  </div>

  <div ng-if="data.agentPossible && !data.agent && options.pickup_msg" class="panel-footer">
    <div id="ticket_fields_footer" class="text-center text-muted" style="font-style: italic;" ng-bind-html="data.pickupMsg">
    </div>
  </div>

</div>

 

CSS

.options-btn {
    border:none;
    background-image:none;
    background-color:transparent;
    -webkit-box-shadow: none;
    -moz-box-shadow: none;
    box-shadow: none;
}

.ticket-fields {
  margin-left: -7px;
  margin-right: -8px;
  -webkit-margin-before: 0;
  -webkit-margin-after: 0;
  
  dt {
    //font-weight: normal;
    margin-bottom: 10px;
  }
  dd {
    margin-bottom: 10px;
  }
}

 

Server

(function(){
	data.pickupMsg = gs.getMessage(options.pickup_msg);
	var gr = $sp.getRecord();
	if (gr == null)
		return;
	
	data.canRead = gr.canRead();
	if (!data.canRead) 
		return;

	var agent = "";
	var a = $sp.getField(gr, 'assigned_to');
	if (a != null)
		agent = a.display_value;

	var fields = $sp.getFields(gr, 'number,state,priority,sys_created_on');
	if (gr.getValue("sys_mod_count") > 0)
		fields.push($sp.getField(gr, 'sys_updated_on'));

	if (gr.getValue('price') > 0)
		fields.push($sp.getField(gr, 'price'));
	
	if (gr.getValue('recurring_price') > 0) {
		var rp = $sp.getField(gr, 'recurring_price');
		if (gr.isValidField("recurring_price"))
			rp.display_value = rp.display_value + " " + gr.getDisplayValue("recurring_frequency");
		fields.push(rp);
	}
	if (gr.isValidField("quantity"))
		fields.push($sp.getField(gr, 'quantity'));

	data.tableLabel = gr.getLabel();
	data.fields = fields;
	data.variables = $sp.getVariablesArray();
	data.agent = agent;
	data.agentPossible = gr.isValidField("assigned_to");
	data.table = gr.getTableName();
	data.sys_id = gr.getUniqueValue();
})()

 

Client

function ($scope, spUtil) {
		
	spUtil.recordWatch($scope, $scope.data.table, "sys_id=" + $scope.data.sys_id); 
}

 

Schema

[{"name":"pickup_msg","section":"Presentation","label":"Pickup message","type":"string"}]

 

NOTE:  There are no Angular Providers nor Templates associated with this widget.

The long-and-short of it is:  I need anyone that can access the ticket via portal (watch list users, caller, opened by) to see the ticket AND the options (variables).  Currently, these users are able to see the ticket (updated "read" ACL on incident table to include watch list users), but not all users can see the options (variables)...only the caller_id user can see them.  The only ACL on question_answer is the one OOTB that has no defined roles.  I tried deleting the ACL (backed up in XML before doing so) and this had no effect...

It has to be something simple i am overlooking, but it sure feels like an ACL issue...

john_duchock
Kilo Guru

I don't have a customer running Kingston Patch 7...  would you be able to post the widget code here so i can do a diff on them?