Create a Copy button widget for Requested Item in Service Portal

TEdwards
Kilo Sage

Hello all,

We have a requirement to create a copy button for requests/requested items in the Service Portal to be used to copy closed requests so the user does not have to enter the same information into a new request. I have been researching what others have done, and have found:

1.It is suggested that there is already one OOB, however I do not find one in my personal dev instance when following the directions in How to make Copy button form expose on service portal?.

2. I have also found  Button to copy and insert a new ticket into table, but it is specific to incidents and I am not sure how to adapt it to requests, which have variables that can vary widely.

3. I also took at look at the UI action on Requests in the platform, which I thought might serve as a template for creating a widget, but I am not sure if it would work:

var helper = new GlideappScriptHelper();
var request = helper.copyRequest(current);
gs.addInfoMessage(gs.getMessage('Request copied successfully'));
action.openGlideRecord(request);

 

Has anyone done this before, or can someone assist with how I might do this? Is it possible to adapt 2. or 3. above to my purpose or can someone point me in the right direction for finding the OOB copy button from 1. above?

Any help will be appreciated. Thanks!

1 ACCEPTED SOLUTION

Chris Sanford
Giga Guru

Ok so yeah its like this widget to resubmit request on the ticket page, script include to build the URL, variable set called 'copy_variables_from_uri_ritm_id' with client script to parse the URL

Widget HTML:

<div ng-if="::c.data.show_button" class="panel panel-default b wrapper-md" ng-class="{'wrapper-md': options.native_mobile != 'true', 'wrapper-sm': options.native_mobile == 'true'}">
  <button name="resubmit" ng-disabled="c.resubmitting" ng-click="c.redirectToResubmit()" class="btn btn-primary btn-block ng-binding ng-scope">
    Resubmit Request
  </button>
</div>

Widget Client script:

function() {
  var c = this;
	c.resubmitting = false;
	c.redirectToResubmit = function() {
		c.resubmitting = true;
		c.server.get({
			resubmitting: true
		}).then(function(r) {
			top.window.location = r.data.resubmit_url;
		});
	}
}

Widget Server script:

(function() {
	var tableName = $sp.getParameter('table');
	var recordId = $sp.getParameter('sys_id');
	if(tableName && recordId) {
		var recordGr = new GlideRecord(tableName);
		recordGr.get(recordId);
		if(!input) {
			data.show_button = new CatalogVariableURLBuilder().hasVariableSet(recordGr, 'copy_variables_from_uri_ritm_id');
		}
	}
	if(input && input.resubmitting) {
		data.resubmit_url = new CatalogVariableURLBuilder().getResubmitURL('sc_cat_item', recordGr);
	}
})();

CatalogVariableURLBuilder script include:

var CatalogVariableURLBuilder = Class.create();
CatalogVariableURLBuilder.prototype = {
    initialize: function() {},

    getJsonFromGr: function(ritmGr) {
        var variablesObj = ritmGr.variables.getElements(false);
        var outputObj = {};
        for (var i = 0; i < variablesObj.length; ++i) {
            var variable = variablesObj[i];
            var question = variable.getQuestion();
            if (question.getValue() && question.getName()) {
                outputObj[question.getName()] = question.getValue();
            }
        }
		return JSON.stringify(outputObj);
    },
	
	hasVariableSet: function(ritmGr, variableSetName) {
		if(ritmGr.getTableName() != 'sc_req_item' || !ritmGr.getValue('cat_item')) {
			return false;
		}
		var ioSetItem = new GlideRecord('io_set_item');
		ioSetItem.addQuery('sc_cat_item', ritmGr.getValue('cat_item'));
		ioSetItem.addQuery('variable_set.internal_name', variableSetName);
		ioSetItem.query();
		return ioSetItem.hasNext();
	},
	
	getResubmitURL: function(catItemPageId, ritmGr) {
		var catItemSysId = ritmGr.cat_item.toString();
		return "?id=" + catItemPageId + "&sys_id=" + catItemSysId + "&sysparm_copy_from_ritm_id=" + ritmGr.getUniqueValue();
	},

    type: 'CatalogVariableURLBuilder'
};

Variable set:

find_real_file.png

Onload client script (in this variable set)

function onLoad() {
	
	var prop, propVal;
	//get parameter from URL
	var ritmId = getParameterValue('sysparm_copy_from_ritm_id');
	console.debug('sysparm_variables URI parameter value: ' + ritmId);
	if (!ritmId) {
		//If parameter is empty, stop here.
		console.debug('aborting due to a missing sysparm_copy_from_ritm_id URI parameter');
		return;
	}
	var getVariableJson = new GlideAjax('CopyVariablesAjax');
	getVariableJson.addParam('sysparm_name', 'getVariableJson');
	getVariableJson.addParam('sysparm_copy_from_ritm_id', ritmId);
	getVariableJson.getXMLAnswer(populateForm);
	
	function populateForm(variableJsonStr) {
		console.debug('sysparm_copy_from_ritm_id variables JSON object: ' + variableJsonStr);
		var variableJson = JSON.parse(variableJsonStr);
		for(var formVariable in variableJson) {
			if(g_form.hasField(formVariable)) {
				g_form.setValue(formVariable, variableJson[formVariable]);
			}
		}
	}
}

function getParameterValue(name) {
	name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
	var regexS = "[\\?&]" + name + "=([^&#]*)";
	var regex = new RegExp(regexS);
	//Check if portal (gel=undefined) or classic UI, and get the HREF data appropriately in either case.
	var hrefPath = (typeof gel == 'undefined') ? this.location.href : top.location.href;
	var results = regex.exec(hrefPath);
	
	console.debug('HREF: ' + hrefPath);
	
	if (results == null) {
		return "";
	} else {
		return unescape(results[1]);
	}
}

CopyVariablesAjax script include client callable:

var CopyVariablesAjax = Class.create();
CopyVariablesAjax.prototype = Object.extendsObject(AbstractAjaxProcessor, {
	
	getVariableJson: function() {
		var ritmId = this.getParameter('sysparm_copy_from_ritm_id');
		var ritm = new GlideRecord('sc_req_item');
		if(!ritm.get(ritmId)) {
			return "{}";
		}
		return new CatalogVariableURLBuilder().getJsonFromGr(ritm);
	},

    type: 'CopyVariablesAjax'
});

Ok now you just need to, add the variable set to any catalog item that you want this functionality to work in, and also you should add the widget to the ticket page where the button needs to be.

View solution in original post

10 REPLIES 10

ziarahman
Tera Contributor

Hi chris,

 

I used all steps you mentioned there, everything is working except I have some multi row variable set which is not getting copied. 

 

Is there any way to accomodate multi-row variable too?