UI Action to Simplify Comparing Versions of Form, List, and Related List Layouts
It's upgrade time, and I'm reviewing "skips" and loving it!
One of the things that me and my team find challenging is reviewing updates to forms and lists because when you do the side-by-side comparison, you're looking at the XML for the update. It's a lot of data that masks the information that I'm looking for.
I've created a UI action for the Upgrade details record that makes it easier to to the comparison. Instead of looking at the content above you get to see the layout elements side-by-side in a table. When the UI Action is in place, you'll get this when you run it on a Upgrade details record for a form layout, list layout, or related lists layout.
The UI Action
Create a UI Action with the following properties:
- Name: Show List and Layout Diffs Simplified
- Table: Upgrade Detaisl [sys_upgrade_history_log]
- Select these check boxes
- * Active
- Show insert
- Show update
- Form context menu
- Show insert
- Script:
UI Action Script
/*_________________________________________________________________
* Description: Creates an HTML table that shows the differences between what's on two layouts.
* Parameters: None
* Returns: Nothing
* Sets: Nothing
________________________________________________________________*/
function myCompare() {
if (typeof scriptName == "undefined") {
// we will add the scriptName to the function Name
scriptName = "";
}
var functionName = "Function: myCompare\n";
functionName = scriptName + functionName;
try {
// Put content here
// Create an object that will have some functions we need
var o = {};
o.getRelationship = function(rel) {
var id = rel.replace(/REL:/, "");
var gr = new GlideRecord("sys_relationship");
if (gr.get(id)) {
return gr.getValue("name");
} else {
return rel;
}
};
o.getRecXml = function(name, state, source) {
if (gs.nil(name) || gs.nil(state)) {
return null;
}
var gr = new GlideRecord("sys_update_version");
gr.addQuery("name", name);
gr.addQuery("state", state);
if (!gs.nil(source)) {
gr.addQuery("source", historyId);
}
gr.orderByDesc("sys_updated_on");
gr.query();
gr.next();
var xml = GlideappUpdateVersion.replacePayloadWithPreviewXML(gr);
return xml;
};
o.getObj = function(record) {
//gs.addInfoMessage(record.payload);
var recordObj = new XMLHelper(record.payload).toObject();
if (recordObj.hasOwnProperty("sys_ui_related_list_entry")) {
return this.getRelatedListObj(recordObj);
} else if (recordObj.hasOwnProperty("sys_ui_element")) {
return this.getFormObj(recordObj);
} else if (recordObj.hasOwnProperty("sys_ui_list_element")) {
return this.getListObj(recordObj);
} else {
this.showMessage(recordObj);
}
};
o.getListObj = function(recordObj) {
var entriesObj = {};
var entries = recordObj.sys_ui_list_element;
for (var i = 0; i < entries.length; i++) {
var entry = entries[i];
var position = entry.position;
var entryName = entry.element;
entriesObj[position] = entryName;
}
return entriesObj;
};
o.getFormObj = function(recordObj) {
var entriesObj = {};
var entries = recordObj.sys_ui_element;
for (var i = 0; i < entries.length; i++) {
var entry = entries[i];
var position = entry.position;
var entryName = entry.element;
entriesObj[position] = entryName;
}
return entriesObj;
};
o.getRelatedListObj = function(recordObj) {
var entriesObj = {};
var listEntries = recordObj.sys_ui_related_list_entry;
for (var i = 0; i < listEntries.length; i++) {
var entry = listEntries[i];
var position = entry.position;
var entryName = this.getRelationship(entry.related_list);
entriesObj[position] = entryName;
}
return entriesObj;
};
o.createRow = function(cObj, uObj, index) {
var rowTemplate = "<tbody><tr><td>{0}</td><td>{1}</td><td>{2}</td></tr></tbody>";
var params = [];
params.push(" " + index + " ");
var leftCell = (uObj.hasOwnProperty(index + "")) ? uObj[index + ""] : "----";
var rightCell = (cObj.hasOwnProperty(index + "")) ? cObj[index + ""] : "----";
params.push(" " + leftCell + " ");
params.push(" " + rightCell + " ");
var row = gs.getMessage(rowTemplate, params);
return row;
};
o.createTable = function(header, rows) {
var tableTemplate = "<table>{0}{1}</table>";
var params = [];
params.push(header);
params.push(rows);
var table = gs.getMessage(tableTemplate, params);
return table;
};
o.createHeader = function(cName, uName, index) {
var rowTemplate = "<thead><tr><th>{0}</th><th>{1}</th><th>{2}</th></tr></thead>";
var params = [];
params.push(" " + index + " ");
params.push(" " + uName + " ");
params.push(" " + cName + " ");
var row = gs.getMessage(rowTemplate, params);
return row;
};
o.messageTemplate = messageTemplate = "<pre>{0}</pre>";
o.showMessage = function(obj) {
var objString = JSON.stringify(obj, undefined, 2);
gs.addInfoMessage(gs.getMessage(this.messageTemplate, objString));
};
/*******************
// Here's where we do the work
*******************/
var upgradeId = current.getUniqueValue();
var hlSysId = upgradeId;
var gr = new GlideRecord("sys_upgrade_history_log");
gr.addQuery("sys_id", hlSysId);
gr.query();
if (!gr.next()) {
return;
}
var historyId = gr.getValue("upgrade_history");
var currentXml = o.getRecXml(gr.getValue("file_name"), "current");
var upgradeXMl = o.getRecXml(gr.getValue("file_name"), "history", historyId);
var currentObj = o.getObj(currentXml);
var upgradeObj = o.getObj(upgradeXMl);
var length = Object.keys(currentObj).length;
length = (length > Object.keys(upgradeObj).length) ? length : Object.keys(upgradeObj).length;
var cName = "Our Version";
var uName = "Upgrade Version";
var tHead = "";
tHead = o.createHeader(cName, uName, "position");
var tRows = "";
for (var i = 0; i < length; i++) {
tRows += (o.createRow(currentObj, upgradeObj, i));
}
var table = o.createTable(tHead, tRows);
var winContent = '<textarea>[code]{0}[/code]</textarea>';
gs.addInfoMessage(gs.getMessage(winContent, table));
gs.addInfoMessage(gs.getMessage(table));
} catch (e) {
// enter what you want to happen if there is an error here
var errorMessage = functionName + e;
gs.addInfoMessage(errorMessage);
gs.log(errorMessage);
}
}
myCompare();
action.setRedirectURL(current);
Output of the UI Action
When you click on the UI action, it uses gs.addInfoMessage() to display a table like the one shown earlier and a small containing the HTML for the table enclosed in the [code][/code] tags. This table can be added to a comment or worknote on a task.</p> <p><img src="https://community.servicenow.com/community/image/serverpage/image-id/148249iE2A32473C71E22D2/image-size/large?v=v2&px=999" alt="image"></p> <p>Let me know if you have any questions.</p> <p>Thanks,</p> <p>Cody</p>
https://www.servicenow.com/community/developer-articles/ui-action-to-simplify-comparing-versions-of-form-list-and/ta-p/2298109