Update Conflict Change Script to only show on Normal and Standard changes

Susan Davidson
Giga Guru

I have a requirement that we show a conflict message only for normal, standard and urgent changes

I have updated the conflict properties and the onchange rule to reflect the new message.

 

The problem i am having is excluding emergency changes (which don't require this message to show)

 

I've tried adding if (startDateReadOnly && type != 'emergency" || endDateReadOnly && type !=emergency)  to the below code without any luck.


How could i prevent this from showing if the change type is emergency?

SusanDavidson_0-1689797478252.png

 

1 ACCEPTED SOLUTION

OK Along with above changes in client script , update following ChangeRequestConflictUtils :

 

function initializeConflictDetection() {

	var trackerId = $('tracker_id').value;
	if (trackerId !== "") {
		runBackgroundPoll(trackerId);
		showProgressButton(true);
	}

	// Ensure the warning message and check conflicts button are
	// correctly shown/hidden (Poll every 2 seconds in case User has
	// cleared one of the 3 mandatory conflict detection fields)
	setInterval(updateWarningBoxAndConflictButton, 2000);

	setTimeout(function() {
		if (!g_form.isNewRecord() && ($('tracker_id').value !== "")) {
			if (updateWarningBoxAndConflictButton()) {
				updateConflictStatus();
				refreshConflicts();
			}
		}
	}, 1000);

	$("conflict_action_run").observe("click", function(event) {
		event.stop();

		// If we have unfilled mandatory fields then do not progress
		if (!g_form.mandatoryCheck())
			return;
		
		if (g_form.getValue('type')== 'emergency') // to make sure conflict calculation not to run
			return;

		if (g_form.isNewRecord() || g_form.modified){
			// Add a hidden parameter to indicate that the run conflict detection should be run after the form has saved
			var afterSaveURL = new GlideURL();

			if (g_form.isNewRecord())
				afterSaveURL.setFromString(g_form.getTableName() + '.do?sys_id=' + g_form.getUniqueValue());
			else
				afterSaveURL.setFromCurrent();

			addHidden(g_form.getFormElement(), 'sysparm_goto_url', afterSaveURL.getURL().replace(g_form.getTableName() + '.do','change_conflict_ui.do'));
			g_form.save();
		} else
		runConflictDetection();
	});

	//Add event listener for list v2 changes for Affected CI's
	CustomEventManager.observe('partial.page.reload', function (elem, e) {
		if (e && e.listID === g_form.getTableName() + '.task_ci.task')
			$('affected_item_count').value = e.totalRows;
	});

	//Add event listener for list v3 changes for Affected CI's
	CustomEventManager.observe('g_list.api.refresh', function (e) {
		if (e && e.listId === g_form.getTableName() + '.task_ci.task')
			$('affected_item_count').value = GlideList.get(g_form.getTableName() + '.task_ci.task').getRowCount();
	});

	var runTrackerEl = $('run_tracker_ui');
	if (runTrackerEl && runTrackerEl.value == 'true')
		runConflictDetection();
}

function getSchedulingConflictMessage() {
	var startDateReadOnly = g_form.is ("", g_form.getControl("start_date"));
	var endDateReadOnly = g_form.isReadOnly("", g_form.getControl("end_date"));

	if (startDateReadOnly || endDateReadOnly)
		return new GwtMessage().getMessage("Scheduling conflict detected. Review the Conflicts form section.");
	return new GwtMessage().getMessage("The Planned Start or Planned End Data falls within a Scheduled Change Freeze. Use the <a href='javascript&colon;void(0);' onclick='openNextAvailableTime()'>Scheduling Assistant</a> to avoid conflicts. If the change MUST occur at this time then approval will be needed from Joey Sudomir (including for Standard Changes)");
}

function runConflictDetection() {
	var cancelButtonId = 'cancelButton';
	var backgroundlButtonId = 'runInBackgroundButton';

	var dd = new GlideModal("simple_progress_viewer", true, "40em", "10.5em");
	dd.setTitle(new GwtMessage().getMessage("Checking conflicts"));
	dd.setPreference('sysparm_progress_name', "Conflict Checker");
	dd.setPreference("sysparm_renderer_expanded_levels", "0");
	dd.setPreference("sysparm_renderer_hide_drill_down", true);

	if ($('tracker_id').value == "") {
		dd.setPreference("sysparm_ajax_processor", "ChangeConflictAJAXProcessor");
		dd.setPreference("sysparm_sysid", g_form.getUniqueValue());
	} else

	dd.setPreference('sysparm_renderer_execution_id', $('tracker_id').value + "");
	dd.setPreference("sysparm_button_close", new GwtMessage().getMessage("Close"));

	dd.on("executionComplete", function(trackerObj) {
		receiveMessage(trackerObj);

		if (trackerObj.state == 4){
			var progressContainer = $("simple_progress_viewer");
			if (progressContainer)
				progressContainer.down("#container").innerHTML = $("conflict_canceled_progress_status").innerHTML;
		}

		var closeBtn = $("sysparm_button_close");
		if (closeBtn) {
			closeBtn.onclick = function() {
				showProgressButton(false);
				dd.destroy();
			};
		}

		var cancelButton = $(cancelButtonId);
		if (cancelButton)
			cancelButton.hide();

		var backgroundButton = $(backgroundlButtonId);
			if (backgroundButton)
				backgroundButton.hide();
	});

	dd.on("beforeclose", function() {
		runBackgroundPoll($('tracker_id').value);
	});

	dd.on("renderStatus", function(trackerObj) {
		// Record the value of the tracker for future use
		$('tracker_id').value = trackerObj.sys_id;

		// Add the cancel button
		if (!dd.hasCancelButton){
			// Create a button that closes the dialog when it is clicked
			// (But continues to run conflict detection in the background)
			var button = new Element('button', {'id': cancelButtonId, 'class': 'btn btn-default', 'style': 'margin: 0px 4px 0px 4px;'});
			button.update(new GwtMessage().getMessage("Cancel"));
			button.observe("click", function(event) {
				var backgroundButton = $(backgroundlButtonId);
				if (backgroundButton)
					backgroundButton.disable();

				cancelConflictDetection($('tracker_id').value);
			});

			// Add the button to the dialog and make a note of the fact that you added it
			var buttonPanel = $('buttonsPanel');
			buttonPanel.appendChild(button);
			dd.hasCancelButton = true;
		}

		// Add the Run in background button
		if (!dd.hasRunInBackgroundButton){
			// Create a button that closes the dialog when it is clicked
			// (But continues to run conflict detection in the background)
			var button = new Element('button', {'id': backgroundlButtonId, 'class': 'btn btn-primary', 'style': 'margin: 0px 4px 0px 4px;'});
			button.update(new GwtMessage().getMessage("Run in Background"));
			button.observe("click", function(event) {
				var cancelButton = $(cancelButtonId);
				if (cancelButton)
					cancelButton.disable();

				runBackgroundPoll($('tracker_id').value);
				dd.destroy();
			});

			// Add the button to the dialog and make a note of the fact that you added it
			var buttonPanel = $('buttonsPanel');
			buttonPanel.appendChild(button);
			dd.hasRunInBackgroundButton = true;
		}
	});

	showProgressButton(true);
	dd.render();
}

function updateWarningBoxAndConflictButton() {
	// Get values of all fields to determine if conflict detection should be allowed or not
	var cmdbCi = g_form.getValue('cmdb_ci');
	var startDate = g_form.getValue('start_date');
	var endDate = g_form.getValue('end_date');
	var conflictMode = $('conflict_mode').value;
	var affectedItemCount = $('affected_item_count').value;

	// Get references to the two gui widgets you intend to enable/disable
	var warningBox = $('conflictDetectionStatus');
	var checkConflictsButton = $('conflict_action_run');

	// Case1: Basic Mode + Configuration Item + Planned Start Date + Planned End Date
	if (conflictMode == 'basic' && cmdbCi != '' && startDate != '' && endDate != '') {
		warningBox.hide();
		checkConflictsButton.enable();
		return true;
	}

	// Case2: Advanced Mode + Configuration Item + Planned Start Date + Planned End Date
	if (conflictMode == 'advanced' && cmdbCi != '' && startDate != '' && endDate != '') {
		warningBox.hide();
		checkConflictsButton.enable();
		return true;
	}

	// Case3: Advanced Mode + Affected Items + Planned Start Date + Planned End Date
	if (conflictMode == 'advanced' && parseInt(affectedItemCount) != 0 && startDate != '' && endDate != '') {
		warningBox.hide();
		checkConflictsButton.enable();
		return true;
	}

	// Default: Do not allow User to run conflict detection
	warningBox.show();
	checkConflictsButton.disable();
	return false;
}

function showProgressButton(boolValue) {
	if (boolValue) {
		$("conflict_run_state").value = "executing";
		$("conflict_action_run").innerHTML = new GwtMessage().getMessage("View Progress");
	} else {
		$("conflict_run_state").value = "ready";
		$("conflict_action_run").innerHTML = new GwtMessage().getMessage("Check Conflicts");
	}
}

function runBackgroundPoll(sysId) {
	if (sysId != "") {
		var ga = new GlideAjax('ChangeConflictAJAXProcessor');
		ga.addParam('sysparm_name', 'getTrackerRecord');
		ga.addParam('sysparm_tracker_id', sysId);
		ga.getXMLAnswer(function (answer){
			receiveMessage(answer.evalJSON());
		});
	}
}

function cancelConflictDetection(sysId) {
	if (sysId != "") {
		var ga = new GlideAjax('ChangeConflictAJAXProcessor');
		ga.addParam('sysparm_name', 'cancel');
		ga.addParam('sysparm_tracker_id', sysId);
		ga.getXML();
	}
}

function everyTenPercent(percent, handler) {
	this.data = this.data || [false, false, false, false, false, false, false, false, false, false, false];
	var slot = ((Math.round(percent / 10) * 10) / 10);
	if (this.data[slot])
		return;
	this.data[slot] = true;
	handler();
}

function refreshConflicts() {
	var conflictLists = GlideList2.getListsForTable("conflict");
	var impactedCIs = GlideList2.get(g_form.getTableName() + '.task_cmdb_ci_service.task');
	conflictLists.push(impactedCIs);
	for (var i = 0; i < conflictLists.length; ++i)
		if (conflictLists[i]) //Check that the list is valid before trying to refresh
			conflictLists[i].refresh();
}

function receiveMessage(tracker) {
	/**
	* 0 - Pending
	* 1 - Running
	* 2 - Successful
	* 3 - Failed
	* 4 - Cancelled
	*/
	if (tracker.state == 0 || tracker.state == 1) {
		everyTenPercent(tracker.percent_complete, refreshConflicts);
		$("conflict_status").update(new GwtMessage().getMessage("{0}% completed", tracker.percent_complete));
		setTimeout(function() {
			this.runBackgroundPoll($("tracker_id").value);
		}, 2000);
	} else {
		$("tracker_id").value = "";
		showProgressButton(false);

		switch (tracker.state - 0){
			case 2:
				refreshConflicts();
				updateConflictLastRun(tracker.timestamp);
				updateConflictStatus();
				$("conflict_status").update(new GwtMessage().getMessage("Completed"));
				break;
			case 3:
			case 4:
				deleteConflicts(tracker);
				break;
		}

		setTimeout(function() {
			$("conflict_status").update("");
		}, 5000);
	}
}

function deleteConflicts(trackerObj){
	if (trackerObj.state == 3)
		$("conflict_status").update(new GwtMessage().getMessage("Failed"));

	if (trackerObj.state == 4)
		$("conflict_status").update(new GwtMessage().getMessage("Canceled"));

	var ga = new GlideAjax('ChangeConflictAJAXProcessor');
	ga.addParam('sysparm_name', 'deleteConflicts');
	ga.addParam('sysparm_sys_id', g_form.getUniqueValue());
	ga.getXML(function(){
		refreshConflicts();
		updateConflictLastRun("");
		g_form.setValue('conflict_status', 'Not Run');
	});
}

function updateConflictLastRun(timestamp) {
	// update the field which gets displayed when time displayed in 'calendar' or 'both' modes
	var conflictLastRunCalendar = $('sys_readonly.' + g_form.getTableName() + '.conflict_last_run');
	if (conflictLastRunCalendar)
		conflictLastRunCalendar.setValue(timestamp);

	// update the field which gets displayed when time displayed in 'timeAgo' mode
	var conflictLastRunTimeAgo = $(g_form.getTableName() + '.conflict_last_run.timeago');
	if (conflictLastRunTimeAgo)
		conflictLastRunTimeAgo.update(new GwtMessage().getMessage("Just now"));
}

function updateConflictStatus() {
	var conflictLastRun = $('sys_readonly.' + g_form.getTableName() + '.conflict_last_run');
	var ga = new GlideAjax("ChangeConflictAJAXProcessor");
	ga.addParam('sysparm_name', 'getConflictData');
	ga.addParam('sysparm_change_id', g_form.getUniqueValue());
	ga.getXML(function(message) {
		var conflictInfo = message.responseXML.documentElement.getAttribute("answer").evalJSON();
		if (conflictInfo.conflictCount === 0) {
			if (conflictLastRun == '')
				g_form.setValue('conflict_status', 'Not Run');
			else {
				g_form.setValue('conflict_status', 'No Conflict');
				updateConflictLastRun(conflictInfo.timestamp);
			}
		} else {
			g_form.setValue('conflict_status', 'Conflict');
			updateConflictLastRun(conflictInfo.timestamp);
		}
	});
}

Changes present on line 30

If my answer has helped with your question, please mark my answer as accepted solution and give a thumb up.
Regards,Sushant Malsure

View solution in original post

7 REPLIES 7

Yay - that did it! And without needing the changes on the client script.


Thank you!

 

here try the updated client script:

function onChange(control, oldValue, newValue, isLoading, isTemplate) {
    

	function getSchedulingConflictMessage() {
        var startDateReadOnly = g_form.isReadOnly("", g_form.getControl("start_date"));
        var endDateReadOnly = g_form.isReadOnly("", g_form.getControl("end_date"));
        if (startDateReadOnly || endDateReadOnly)
            return new GwtMessage().getMessage("Scheduling conflict detected. Review the Conflicts form section.");
        return new GwtMessage().getMessage("<font color='red'><font size=6>The Planned Start or Planned End Data falls within a Scheduled Change Freeze. If the change MUST occur at this time then approval will be needed from Joey Sudomir (including for Standard Changes). Use the <a href='javascript&colon;void(0);' onclick='openNextAvailableTime()'>Scheduling Assistant</a> to avoid conflicts.</font>");
    }

    function showConflictNotification() {
		var showConflictMessage = g_scratchpad.show_conflict_message;

        if (showConflictMessage.property === "never") return false;
        if (showConflictMessage.property === "always") return true;

		var showNotification = showConflictMessage.preference;
        return showNotification;
    }

    //We don't want to render the warning and link to the conflict scheduler if we're in 'print' mode
    var gURL = new GlideURL();
    gURL.setFromCurrent();
    var isPrint = !!gURL.getParam("sysparm_media");

    if (!isPrint && newValue === "Conflict" && showConflictNotification() && g_form.getValue('type')!= 'emergency') {
        g_form.addInfoMessage(getSchedulingConflictMessage(), "conflict_warn_status");
        return;
    } else if (isLoading || newValue === '')
        return;

    // Remove the warning message as status is not Conflict.
    var chgGlideUI = GlideUI.get();
    var messageKey = "alert_" + getSchedulingConflictMessage();

    if (!chgGlideUI.messages[messageKey])
        return;

    delete chgGlideUI.messages[messageKey];

    var messageCount = Object.keys(chgGlideUI.messages).length;
    if (messageCount === 0)
        chgGlideUI.clearOutputMessages();
    else {
        var msgElement = $("conflict_warn_status");
        if (msgElement)
            msgElement.remove();
    }
}

I have updated on line 27

 

 

If my answer has helped with your question, please mark my answer as accepted solution and give a thumb up.
Regards,Sushant Malsure

Unfortunately then the message shows on any change that is not an emergency even when it doesn't fall into the freeze dates (so always shows on any change that's not an emergency)