- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
03-04-2021 02:36 AM
Hi -
I'm adding a new required field "Incident Commander" to the "Promote Major Incident" ui page (mim_workbench_promote).
I've got the reference field added and working fine in the html, saving the page results in the data being saved just fine, etc.
The one bug I'm having is that the required star isn't visible until after I add DATA into the reference field. (Edit: And if I blank that data, the star goes away!)
Can anyone see what I'm missing?
Note: in both the html and the script, I'm only including portions relevant to the Incident Commander field.
Thanks in advance!
HTML:
<div class="form-group" id="incident-commander-wrapper">
<label class="col-sm-2 control-label" for="mim-promote-incident-commander">
<span mandatory="true" class="required-marker label_description" />
Incident Commander
</label>
<div class="col-sm-12 col-md-6 form-field input_controls">
<div class="is-required">
<g:ui_reference required="required" name="mim-promote-incident-commander" id="mim-promote-incident-commander" table="sys_user" query="roles=itil^ORuser_name=tbd" value="$[assignedUser.sys_id]" displayValue="$[assignedUser.name]" onchange="promoteModal.incidentCommanderOnChange();"/>
</div>
</div>
</div>
Catalog Client Script:
(function(global) {
var incidentCommanderModified = false;
var incidentCommander = $("mim-promote-incident-commander");
var incidentCommanderWrapper = $('incident-commander-wrapper');
var promoteBtn = $('mim-promote-button');
incidentCommanderOnChange();
itaocOnChange();
function _debounce(func, wait, immediate) {
var timeout;
return function() {
var context = this,
args = arguments;
var later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
}
function incidentCommanderOnChange() {
if (incidentCommanderModified == false) {
incidentCommanderModified = true;
}
if (incidentCommanderModified == true) {
if (!incidentCommander.value.trim()) {
incidentCommanderWrapper.removeClassName('is-filled');
} else {
incidentCommanderWrapper.addClassName('is-filled');
}
}
if (_checkCurrentlyRequiredFields()) {
promoteBtn.removeClassName('disabled');
promoteBtn.writeAttribute('aria-disabled', false);
} else {
promoteBtn.addClassName('disabled');
promoteBtn.writeAttribute('aria-disabled', true);
}
}
function _checkCurrentlyRequiredFields() {
if ( /*workNotesModified==true &&*/ businessImpactModified == true && incidentCommanderModified == true && itaocModified == true) {
return true;
} else {
return false;
}
}
function _promoteRestCall(record) {
var dfd = $j.Deferred();
var api = '/api/sn_major_inc_mgmt/mim/actions/' + window.NOW.MAJOR_INCIDENT_WORKBENCH.sys_id;
var data = {
action: 'PROMOTE',
record: record
};
$j.ajax({
type: 'POST',
url: api,
data: JSON.stringify(data),
success: function(data) {
dfd.resolve(data);
},
error: function() {
dfd.reject();
},
contentType: "application/json",
dataType: 'json'
});
return dfd.promise();
}
function promote() {
getMessage("Promoted to a major incident", function(msg) {
var updateWorkNotes = msg + "\n" + workNotes.value.trim();
if (!promoteBtn.hasClassName('disabled')) {
if (window.NOW.MAJOR_INCIDENT_WORKBENCH) {
var record = {};
record.work_notes = updateWorkNotes;
record.business_impact = businessImpact.value;
record.u_incident_commander = incidentCommander.value;
record.u_itaoc = itaoc.value;
_promoteRestCall(record).then(function() {
dialog.setPreference('reload', true);
close();
});
} else {
//When UI Page is rendered from Form UI Action
g_form.getControl('work_notes').value = updateWorkNotes;
g_form.setValue('business_impact', businessImpact.value);
g_form.setValue('u_incident_commander', incidentCommander.value);
g_form.setValue('u_itaoc', itaoc.value);
GlideModal.prototype.get('sn_major_inc_mgmt_mim_workbench_promote').destroy();
gsftSubmit(null, g_form.getFormElement(), 'sysverb_mim_accept');
}
}
});
}
function close() {
dialog.destroy();
}
global.promoteModal = {
promote: promote,
close: close,
//workNotesOnChange: _debounce(workNotesOnChange, 200), // Only execute when left idle for 200 ms
businessImpactOnChange: _debounce(businessImpactOnChange, 200), // Only execute when left idle for 200 ms
incidentCommanderOnChange: _debounce(incidentCommanderOnChange, 200), // Only execute when left idle for 200 ms
itaocOnChange: _debounce(itaocOnChange, 200) // Only execute when left idle for 200 ms
};
})(window);
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
03-05-2021 09:04 AM
That helps - I see more of what's going on now. You can just change your div class like this.
<div class="form-group is-required" id="incident-commander-wrapper">
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
03-04-2021 02:46 PM
Hi Rita,
Please post the entire Client script. I am unable to reproduce this (adding only Incident Commander) in my PDI with the lines you've included, and there are lines and blocks here that were already in the out of the box version unchanged, so this has been difficult to follow. I can tell you that only by adding the HTML, and the below lines to the Client script, the "Incident Commander" field (by label) appears mandatory, though as I am unable to populate it without some pertinent code, I can't confirm if it appears not mandatory when populated and enables the Promote button. I also added the if (_checkCurrentlyRequiredFields()) { block to the workNotesOnChange function so that the Promote button wouldn't become enabled after only the mandatory Work notes are populated.
var incidentCommanderModified = false;
var incidentCommander = $("mim-promote-incident-commander");
var incidentCommanderWrapper = $('incident-commander-wrapper');
...
//I added this section modeled after the existing currentWorkNotes, hoping to trigger
//incidentCommanderOnChange(), but I didn't dig up an example of a UI Page with a reference field, so I guessed wrong
//plus, I can't populate this field with anything other than typing gibberish into it
//since the reference search icon doesn't work, or any other normal reference field functions
var currentIncidentCommander = dialog.getPreference('ASSIGNED_TO');//trying to use this in place of your custom field
if(currentIncidentCommander) {
incidentCommander.value = currentIncidentCommander;
incidentCommanderOnChange();
}
...
function incidentCommanderOnChange() {
if (incidentCommanderModified == false) {
incidentCommanderModified = true;
}
if (incidentCommanderModified == true) {
if (!incidentCommander.value.trim()) {
incidentCommanderWrapper.removeClassName('is-filled');
} else {
incidentCommanderWrapper.addClassName('is-filled');
}
}
if (_checkCurrentlyRequiredFields()) {
promoteBtn.removeClassName('disabled');
promoteBtn.writeAttribute('aria-disabled', false);
} else {
promoteBtn.addClassName('disabled');
promoteBtn.writeAttribute('aria-disabled', true);
}
}
function _checkCurrentlyRequiredFields() {
if ( workNotesModified==true && /*businessImpactModified == true &&*/ incidentCommanderModified == true /*&& itaocModified == true*/) {
return true;
} else {
return false;
}
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
03-04-2021 08:22 PM
The UI Page mim_workbench_promote is created as part of the Major Incident Management plugin, as is the business_impact field.
The FULL html is:
<?xml version="1.0" encoding="utf-8" ?>
<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
<!-- To use <g:ui_reference/> in this UI page, below are the required JS.-->
<g:requires name="scripts/functions.js" includes="true" />
<g:requires name="scripts/functions_reference.js" includes="true" />
<g:requires name="scripts/utils.js" includes="true" />
<g:requires name="scripts/accessibility_tabindex.js" includes="true" />
<g:requires name="scripts/slushbucket.js" includes="true" />
<g:requires name="scripts/ac.js" includes="true" />
<g:requires name="scripts/ac_derived_field_support.js" includes="true" />
<g:requires name="scripts/popups.js" includes="true" />
<g:requires name="scripts/classes/AutoComplete.js" includes="true" />
<g:requires name="scripts/classes/SlushBucket.js" includes="true" />
<g:requires name="scripts/classes/ajax/AJAXCompleter.js" includes="true" />
<g:requires name="scripts/classes/ajax/AJAXReferenceControls.js" includes="true" />
<g:requires name="scripts/classes/ajax/AJAXOtherCompleter.js" includes="true" />
<g:requires name="scripts/classes/ajax/AJAXReferenceCompleter.js" includes="true" />
<g:requires name="scripts/classes/ajax/AJAXReferenceCompleterMulti.js" includes="true" />
<g:requires name="scripts/classes/ajax/AJAXTableCompleter.js" includes="true" />
<g:requires name="scripts/classes/ajax/AJAXEmailClientCompleter.js" includes="true" />
<j2:set var="jvar_theme" value="$[gs.getProperty('glide.css.theme.ui16')]"/>
<g2:requires name="styles/css_includes_doctype.css" includes="true" params="c=$[gs.getCssCacheVersionString()]$[jvar_theme]" />
<!-- end required JS-->
<style>
.form-horizontal {
margin-top: 5px;
margin-bottom: 20px;
}
.promote-modal-textarea {
resize: vertical;
min-height: 120px
}
#dialog_buttons .btn{
margin-left: 10px;
padding-left: 15px;
padding-right: 15px;
}
#work-notes-wrapper .required-marker {
display: inline-block;
}
#business-impact-wrapper .required-marker {
display: inline-block;
}
</style>
<g:evaluate var="jvar_itaocQuery" jelly='true'>
//var util = new UserGroupUtils(); //this doesn't work for some reason. calling query here explicitly
//var itaocQuery = util.getGroupUsers('IT_AOC');
var users = {};
var gr_itaoc = new GlideRecord('sys_user_grmember');
gr_itaoc.addQuery('group.name', 'IT_AOC');
gr_itaoc.query();
while (gr_itaoc.next()) {
users[gr_itaoc.user.toString()] = true;
}
var ids = [];
for (var id in users){
ids.push(id);
}
itaocQuery = 'sys_idIN' + ids.toString();
itaocQuery;
</g:evaluate>
<!--g:evaluate var="jvar_incident_id" jelly = "true">//g_form not working
var assignedUser;
var incident_id = g_form.getUniqueValue()l
incident_id;
//var inc = new GlideRecord("incident");
//inc.addQuery("sys_id", incident_id);
//inc.query();
//if (inc.next()){
// assignedUser = new GlideRecord("sys_user");
// assignedUser.addQuery("sys_id", inc.u_itaoc);
// assignedUser.query();
// assignedUser.next();
//}
//assignedUser;
</g:evaluate-->
<g:ui_form id="workbench_promote_fields">
<div class="form-horizontal">
<div class="form-group" id="work-notes-wrapper">
<label class="col-sm-2 control-label" for="mim-promote-work-notes">
<!--span mandatory="true" class="required-marker label_description"></span-->
${gs.getMessage('Work notes')}
</label>
<div class="col-sm-10">
<!--textarea required="true" class="form-control promote-modal-textarea" id="mim-promote-work-notes" type="text" oninput="promoteModal.workNotesOnChange()" onchange="promoteModal.workNotesOnChange()"></textarea-->
<textarea class="form-control promote-modal-textarea" id="mim-promote-work-notes" type="text"></textarea>
</div>
</div>
<div class="form-group" id="business-impact-wrapper">
<label class="col-sm-2 control-label" for="mim-promote-business-impact">
<span mandatory="true" class="required-marker label_description"></span>
${gs.getMessage('Business Impact')}
</label>
<div class="col-sm-10">
<textarea required="true" class="form-control promote-modal-textarea" name="mim-promote-business-impact" id="mim-promote-business-impact" oninput="promoteModal.businessImpactOnChange()" onchange="promoteModal.businessImpactOnChange()"></textarea>
</div>
</div>
<div class="form-group" id="incident-commander-wrapper">
<!--span mandatory="true" class="required-marker label_description"><span class="sr-only">${gs.getMessage('required')}</span></span-->
<label class="col-sm-2 control-label" for="mim-promote-incident-commander">
<span mandatory="true" class="required-marker label_description" />
Incident Commander
</label>
<div class="col-sm-12 col-md-6 form-field input_controls">
<div class="is-required">
<g:ui_reference required="required" name="mim-promote-incident-commander" id="mim-promote-incident-commander" table="sys_user" query="roles=itil^ORuser_name=tbd" value="$[assignedUser.sys_id]" displayValue="$[assignedUser.name]" onchange="promoteModal.incidentCommanderOnChange();"/>
</div>
</div>
</div>
<div class="form-group" id="itaoc-wrapper">
<!--label class="col-sm-2 control-label">
<span mandatory="true" class="required-marker label_description"><span class="sr-only">${gs.getMessage('required')}</span></span> ITAOC
</label-->
<label class="col-sm-2 control-label" for="mim-promote-itaoc">
<span mandatory="true" class="required-marker label_description" />
<span class="label-text" label="ITAOC">ITAOC</span>
</label>
<div class="col-sm-12 col-md-6 form-field input_controls">
<g:ui_reference name="mim-promote-itaoc" id="mim-promote-itaoc" table="sys_user" query="${itaocQuery}" value="$[assignedUser.sys_id]" displayValue="$[assignedUser.name]" onchange="promoteModal.itaocOnChange();"/>
</div>
</div>
</div>
<div id="dialog_buttons" class="clearfix pull-right">
<button type="button" class="btn btn-default" onclick="promoteModal.close()" title="${gs.getMessage('Close the dialog')}">${gs.getMessage('Cancel')}</button>
<button type="button" class="btn btn-primary disabled" aria-disabled="true" id="mim-promote-button" title="${gs.getMessage('Promote to Major Incident')}" onclick="promoteModal.promote()">${gs.getMessage('Promote')}</button>
</div>
</g:ui_form>
</j:jelly>
And the FULL client script is:
(function(global) {
var workNotesModified = false;
var businessImpactModified = false;
var incidentCommanderModified = false;
var itaocModified = false;
var workNotes = $("mim-promote-work-notes");
var businessImpact = $("mim-promote-business-impact");
var incidentCommander = $("mim-promote-incident-commander");
var itaoc = $("mim-promote-itaoc");
var itaocWrapper = $('itaoc-wrapper');
var incidentCommanderWrapper = $('incident-commander-wrapper');
var businessImpactWrapper = $('business-impact-wrapper');
var workNotesWrapper = $('work-notes-wrapper');
var promoteBtn = $('mim-promote-button');
workNotes.focus();
var dialog = GlideModal.prototype.get("sn_major_inc_mgmt_mim_workbench_promote");
var currentWorkNotes = dialog.getPreference('WORK_NOTES');
if (currentWorkNotes) {
workNotes.value = currentWorkNotes;
workNotesOnChange();
}
var currentBusinessImpact = dialog.getPreference('BUSINESS_IMPACT');
if (currentBusinessImpact) {
businessImpact.value = currentBusinessImpact;
businessImpactOnChange();
}
incidentCommanderOnChange();
itaocOnChange();
function _debounce(func, wait, immediate) {
var timeout;
return function() {
var context = this,
args = arguments;
var later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
}
/*function workNotesOnChange() {//not currently used, as this isn't required
if (workNotesModified==false){
workNotesModified=true;
}
if (_checkCurrentlyRequiredFields()){
if (!workNotes.value.trim()) {
workNotesWrapper.removeClassName('is-filled');
promoteBtn.addClassName('disabled');
promoteBtn.writeAttribute('aria-disabled', true);
} else {
workNotesWrapper.addClassName('is-filled');
promoteBtn.removeClassName('disabled');
promoteBtn.writeAttribute('aria-disabled', false);
}
}
}*/
function businessImpactOnChange() {
if (businessImpactModified == false) {
businessImpactModified = true;
}
if (businessImpactModified == true) {
if (!businessImpact.value.trim()) {
businessImpactWrapper.removeClassName('is-filled');
} else {
businessImpactWrapper.addClassName('is-filled');
}
}
if (_checkCurrentlyRequiredFields()) {
promoteBtn.removeClassName('disabled');
promoteBtn.writeAttribute('aria-disabled', false);
} else {
promoteBtn.addClassName('disabled');
promoteBtn.writeAttribute('aria-disabled', true);
}
}
function incidentCommanderOnChange() {
if (incidentCommanderModified == false) {
incidentCommanderModified = true;
}
if (incidentCommanderModified == true) {
if (!incidentCommander.value.trim()) {
incidentCommanderWrapper.removeClassName('is-filled');
} else {
incidentCommanderWrapper.addClassName('is-filled');
}
}
if (_checkCurrentlyRequiredFields()) {
promoteBtn.removeClassName('disabled');
promoteBtn.writeAttribute('aria-disabled', false);
} else {
promoteBtn.addClassName('disabled');
promoteBtn.writeAttribute('aria-disabled', true);
}
}
function itaocOnChange() {
if (itaocModified == false) {
itaocModified = true;
}
if (itaocModified == true) {
if (!itaoc.value.trim()) {
itaocWrapper.removeClassName('is-filled');
} else {
itaocWrapper.addClassName('is-filled');
}
}
if (_checkCurrentlyRequiredFields()) {
promoteBtn.removeClassName('disabled');
promoteBtn.writeAttribute('aria-disabled', false);
} else {
promoteBtn.addClassName('disabled');
promoteBtn.writeAttribute('aria-disabled', true);
}
}
function _checkCurrentlyRequiredFields() {
if ( /*workNotesModified==true &&*/ businessImpactModified == true && incidentCommanderModified == true && itaocModified == true) {
return true;
} else {
return false;
}
}
function _promoteRestCall(record) {
var dfd = $j.Deferred();
var api = '/api/sn_major_inc_mgmt/mim/actions/' + window.NOW.MAJOR_INCIDENT_WORKBENCH.sys_id;
var data = {
action: 'PROMOTE',
record: record
};
$j.ajax({
type: 'POST',
url: api,
data: JSON.stringify(data),
success: function(data) {
dfd.resolve(data);
},
error: function() {
dfd.reject();
},
contentType: "application/json",
dataType: 'json'
});
return dfd.promise();
}
function promote() {
getMessage("Promoted to a major incident", function(msg) {
var updateWorkNotes = msg + "\n" + workNotes.value.trim();
if (!promoteBtn.hasClassName('disabled')) {
if (window.NOW.MAJOR_INCIDENT_WORKBENCH) {
var record = {};
record.work_notes = updateWorkNotes;
record.business_impact = businessImpact.value;
record.u_incident_commander = incidentCommander.value;
record.u_itaoc = itaoc.value;
_promoteRestCall(record).then(function() {
dialog.setPreference('reload', true);
close();
});
} else {
//When UI Page is rendered from Form UI Action
g_form.getControl('work_notes').value = updateWorkNotes;
g_form.setValue('business_impact', businessImpact.value);
g_form.setValue('u_incident_commander', incidentCommander.value);
g_form.setValue('u_itaoc', itaoc.value);
GlideModal.prototype.get('sn_major_inc_mgmt_mim_workbench_promote').destroy();
gsftSubmit(null, g_form.getFormElement(), 'sysverb_mim_accept');
}
}
});
}
function close() {
dialog.destroy();
}
global.promoteModal = {
promote: promote,
close: close,
//workNotesOnChange: _debounce(workNotesOnChange, 200), // Only execute when left idle for 200 ms
businessImpactOnChange: _debounce(businessImpactOnChange, 200), // Only execute when left idle for 200 ms
incidentCommanderOnChange: _debounce(incidentCommanderOnChange, 200), // Only execute when left idle for 200 ms
itaocOnChange: _debounce(itaocOnChange, 200) // Only execute when left idle for 200 ms
};
})(window);
I have not modified the UI Action "Promote to Major Incident", so I don't believe the
var currentIncidentCommander = dialog.getPreference('ASSIGNED_TO');//trying to use this in place of your custom field
that you added would actually pull any info, although I did play with it for a bit. Like you, I couldn't get it to work with a reference field.
Thanks so much for looking at this!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
03-05-2021 09:04 AM
That helps - I see more of what's going on now. You can just change your div class like this.
<div class="form-group is-required" id="incident-commander-wrapper">
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
03-05-2021 02:16 PM
That did it! Thank you so much!