Custom watchlist widget : how to add an email into the list

Igor Myagchev
Tera Contributor

We added to our portal the ability for end-users to update ticket watchlists by selecting users from the sn-record-picker field. This implementation was inspired by Watchlist Widget V2 article.

 

However users sometimes want to add group emails (e.g. distribution lists) or external addresses.

 

After a long research I didn't find any suitable solution in the Community, so here the implementation of my watchlist widget that perfectly meet the needs. Hope it might be helpful for your portal implementation.

IgorMyagchev_0-1721380043049.png

 

The key features:

 - you can add email address to the watchlist in a similar way as in the backend UI

 - your email input is validated

 - when you add an email of a registered user the widget adds a reference to the user record instead

 - you can't add the same address twice

 

Requires:

 - ListUtil script include - see Managing Glide Lists

 

HTML Template::

 

 

<div class="panel panel-primary" ng-if="data.canRead">
  <div class="panel-heading">
    <h4 class="panel-title pull-left" style="font-size: 14px;" 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'"/> ${Users watching this ticket}
    </h4>
    <div class="clearfix"/>
  </div>
  <div ng-if="c.variable_toggle" class="panel-body">
    <form>
      <div ng-if="c.variable_toggle" class="panel-subheading" align="center" style="font-size: 12px;">Add user(s) to the watch list to be notified when this ticket is updated or closed</div>
      <div class="text-center text-italic text-muted">
        <sn-record-picker field="watch_list" sn-disabled="!data.canWrite" table="'sys_user'" display-field="'name'" display-fields="'email'" search-fields="'name'" value-field="'sys_id'" default-query="'active=true^web_service_access_only=false^nameISNOTEMPTY^user_nameISNOTEMPTY^emailISNOTEMPTY'" page-size="10" multiple="true"/>
      </div>
      <div ng-if="c.variable_toggle" class="panel-subheading" align="center" style="font-size: 12px;">Add an email address to the watch list above</div>
      <div class="textbox_space">
        <input ng-disabled="!data.canWrite" ng-model="data.watch_list_email" id="watch_list_email" class="form-control" type="email" maxlength="150" placeholder="Enter an email address if you can't find a user in the field above"/>
      </div>
      <div style="margin-top:15px; float: right;">
        <button ng-if="data.canWrite" ng-click="c.update()" type="submit" class="btn btn-primary btn-sm">${Update}</button>
      </div>
    </form>
  </div>
</div>

 

 

 

Client Script:

 

 

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

	$scope.watch_list = {
		displayValue: c.data.displayValue,
		value: c.data.value,
		canRead: c.data.canRead,
		canWrite: c.data.canWrite,
		name: 'watch_list'
	};
	
	$scope.$on("field.change", function(evt, parms) {
		if (parms.field.name == 'watch_list') {
			c.data.watch_list = parms.newValue;
		}
	});

	c.update = function() {
		var email = document.getElementById("watch_list_email");
		email.addEventListener("input", function(event){
			if (email.validity.typeMismatch) {
				email.setCustomValidity("Please enter a valid email address");
			} else {
				email.setCustomValidity("");
			}
		});

		if (!email || email.validity.valid) {
			c.server.get({
				watch_list : $scope.watch_list.value,
				watch_list_email:  $scope.data.watch_list_email
			}).then(function (r) {
				$scope.watch_list = {
					displayValue: r.data.displayValue.replaceAll(',','####'),
					value: r.data.value,
					canRead: c.data.canRead,
					canWrite: c.data.canWrite,
					name: 'watch_list'
				};
			});
			$scope.data.watch_list_email = "";
		}
	}
}

 

 

 

Server Script:

 

 

(function() {
	var wUtil = new ListUtil(input.watch_list);
	var wEmail = input.watch_list_email;
	data.table = (input && input.table) || options.table || $sp.getParameter("table");
	data.sys_id = (input && input.sys_id) || options.sys_id || $sp.getParameter("sys_id");

	var grTask = new GlideRecord(data.table);
	if (grTask.get(data.sys_id)) {
		data.canRead = grTask.watch_list.canRead();
		data.canWrite = grTask.watch_list.canWrite();

		if (input) {
			if (data.canWrite) {
				//The user has write access, allow update of the list
				if (wEmail && wEmail !== "") {
					//Add the email to the watch list
					var grUser = new GlideRecord('sys_user');
					grUser.addQuery('email', wEmail);
					grUser.addActiveQuery();
					grUser.query();

					if (grUser.next()) {
						// It's a user
						if (!wUtil.isInList(grUser.getUniqueValue())) {
							wUtil.addToList(grUser.getUniqueValue());
						} else {
							gs.addInfoMessage("This user is already in the watch list.");
							return;
						}
					} else {
						//It's not an existing user, so just adding the email to the wathlist
						if (!wUtil.isInList(wEmail)) {
							wUtil.addToList(wEmail);
						} else {
							gs.addInfoMessage("This email is already in the watch list.");
							return;
						}
					}
				}

				grTask.setValue('watch_list', wUtil.getList());
				grTask.update();

				data.value = grTask.getValue('watch_list');
				data.displayValue = grTask.getDisplayValue('watch_list');

				gs.addInfoMessage('Thank you, the watch list was updated.');

			} else {
				//The user doesn't have write access, show error message
				gs.addErrorMessage("Sorry, you don't have permission to update the watch list.");
			}

		} else {
			//if user has read rights, display the watch list values
			if (data.canRead) {
				data.value = grTask.getValue('watch_list');
				data.displayValue = grTask.getDisplayValue('watch_list');
			}
		}
	}
})();

 

 

 

Enjoy it!

2 REPLIES 2

Mark Manders
Mega Patron

You should really reconsider this requirement. You will be opening up your instance to non-users or even groups. There is no control on where emails are being send. And being on the watchlist makes that you receive emails with links that don't work, making it a very bad user experience. 


Please mark any helpful or correct solutions as such. That helps others find their solutions.
Mark

Indeed in case of external email address users will be notified but won't be able to access the ticket in the portal. If this is an issue I would restrict the email input to the internal MX domain only.

		email.addEventListener("input", function(event){
			if (email.validity.typeMismatch) {
				email.setCustomValidity("Please enter a valid email address");
			} else {
				//validate email domain
				var domain = email.value.split('@')[1];
				var allowdedDomain = "your.email.domain";
				//if empty or external domain
				if (!domain || domain.toLowerCase() !== allowdedDomain) {
					email.setCustomValidity("The external domain " + domain + " is not allowed");
				} else {
					email.setCustomValidity("");
				}
			}
		});