Blog

Watchlist Widget

Add a watchlist widget to your Ticket form in Service Portal.  Allow self service users to add email addresses to the watchlist.

This just allows watchlist users to get emails on the ticket.  To allow watchlist users view the ticket in the Service Portal, you'll have to adjust your ACLs and SP configuration.

NOTE: This was updated on 10/27/2020 for the Paris release

Email Format Check

Auto Complete

Confirmation Message

Widget V1

This one doesn’t allow the user to view users in the system

Name: Ticket Watchlist User No View
ID: ticket_watchlist_user_no_view

HTML

<div class="panel panel-primary">
  <div class="panel-heading">
    <h4 class="panel-title"><fa ng-if="::options.glyph.length" name="" class="m-r-sm" />Add to Watchlist</h4>
  </div>
  <div class="panel-body">
    <form ng-submit="server.update()">
      ${Enter an email address to follow}
      <div class="textbox_space">
        <input ng-model="data.watch_list" id="watch_list" class="form-control" type="email" maxlength="50" />
      </div>
      <div style="margin-top:15px; float: right;">
        <button type="submit" class="btn btn-primary post-btn ng-scope">Add</button>
      </div>
      <div style="margin-right:250px;" ng-if="data.response" class="alert alert-success">{{::data.response}}</div>
    </form>
  </div>
</div>

CSS

.textbox_space {
margin-top: 10px;
margin-bottom: 10px;
}

Client Script

api.controller=function() {
  /* widget controller */
  var c = this;
};


Server Script

(function() {
	data.submitMsg = gs.getMessage("Add");
	if (input) {
		data.sys_id = (input && input.sys_id) || options.sys_id || $sp.getParameter("sys_id");
		data.table = (input && input.table) || options.table || $sp.getParameter("table");

		data.watch_list = "";
		var grTask = new GlideRecord(data.table);
		grTask.query("sys_id", data.sys_id);
		grTask.query();
		//console.log('grTask Query: ' + grTask.getEncodedQuery() + ' = ' + grTask.getRowCount());
		if (grTask.next()) {
			var wList = grTask.watch_list;
			var wEmail = input.watch_list;
			var grUser = new GlideRecord('sys_user');
			grUser.addQuery('email', wEmail);
			grUser.query();
			if (grUser.next()) {
				// It's a user
				if(wList != "") {
					wList = (wList + "," + grUser.sys_id);
				} else {
					wList = grUser.sys_id;
				}
			} else {
				//It's not a user either...so just add the address to the list...except instance email address
				wList = (wList + "," + wEmail);
			}
			grTask.setValue("watch_list",wList);
			data.response = 'Thank you, email was added.';
			grTask.update();
		}
	}
})();

Widget V2

This is a different version allows a user to view users and select them. You might not want to use this version due to security reasons, but some companies only have employees use the service portal. You may need to adjust acls for viewing users

Name: Ticket Watchlist View Users
ID: ticket_watchlist_view_users

HTML

<div class="panel panel-primary" ng-if="data.canRead">
  <div class="panel-heading">
    <h4 class="panel-title pull-left">
      ${Watch list}
    </h4>
    <div class="clearfix"></div>
  </div>
  <div class="panel-body">
    <form ng-submit="save()">
      <div class="text-center text-italic text-muted">
        <div>
          <sn-record-picker field="watch_list" sn-disabled="!data.canWrite" table="'sys_user'" display-field="'email'" display-fields="'name'" search-fields="'email'" value-field="'sys_id'" default-query="'active=true^web_service_access_only=false^user_nameISNOTEMPTY^emailISNOTEMPTY'" page-size="10" multiple="true"></sn-record-picker>   </div>
        <div style="margin-top:15px; float: right;">
          <button type="submit" class="btn btn-primary post-btn ng-scope">Save</button>
        </div>
      </div>
    </form>
  </div>
</div>

CSS

Client Script

api.controller=function($scope, spUtil, $http) {
	var c = this;

	$scope.watch_list = {
		displayValue: c.data.displayValue,
		value: c.data.value,
		name: 'watch_list'
	};
	$scope.save = function(){
		c.data.watchList = $scope.watch_list.value;
		c.server.update().then(function() {

			spUtil.recordWatch($scope, c.data.table, "sys_id=" + c.data.sys_id, function(name, data) {
				if(name.name == 'record.updated' && data.operation == 'update'){
					$scope.watch_list.value = data.record.watch_list.value;
					$scope.watch_list.displayValue = data.record.watch_list.display_value;
					$scope.$apply();
				}
			});
		});
	};
	$scope.$on("field.change", function(evt, parms) {
		if (parms.field.name == 'watch_list') {}

	});
};  


Server Script

(function() {
	var gr;
	if(input){
		gr = new GlideRecord(input.table);
		if(gr.get(input.sys_id)){
			if(gr.watch_list.canWrite()){
				gr.watch_list = input.watchList;
				gr.update();
				gs.addInfoMessage('Updated');
			}
			else{
				gs.addErrorMessage("Update failed, you don't have the required access");
			}
		}
	}
	else{
		var sys_id = (input && input.sys_id) || options.sys_id || $sp.getParameter("sys_id");
		var table = (input && input.table) || options.table || $sp.getParameter("table");
		gr = new GlideRecord(table);
		if(gr.get(sys_id)){
			data.table = table;
			data.sys_id = sys_id;
			data.canRead = gr.watch_list.canRead();
			data.canWrite = gr.watch_list.canWrite();
			if(data.canRead){
				var dV = gr.getDisplayValue('watch_list');
				var sV = gr.getValue('watch_list');
				//data.displayValue = dV == '' ? [] : dV;
				//data.value = sV == null ? [] : sV;
				data.displayValue = dV;
				data.value = sV;
			}
		}
	}
})();

Fields: Bootstrap color, Glyph