Maik Skoddow
Tera Patron
Tera Patron
find_real_file.png
Part 1Part 2Part 3Part 4
Part5

 

Force commenting on rejecting of an approval

In my article Improving the Approval Experience, Part 2 I have introduced the custom variants of the "Approve" and "Reject" buttons, and now I want to demonstrate how the "Reject" buttons can be extended by a feature that forces the approver to enter a comment in a popup dialog:

 

find_real_file.png

 

Why do we need this?

OOTB you cannot reject an approval request without providing a reason. But the user experience is bad since the check for a missing comment is done server-side after submitting the form. The better approach would be to trigger a client-side check and open a respective popup dialog for entering a comment.

 

UI Page "approval_reject_confirm"

There are different approaches for building popup dialogs. One of them loads a prepared UI Page which acts as container for the form. Therefore, we have e to create a respective UI Page at first.

Go to System UI > UI Pages and create a new record with the following properties

 

FieldValue
Nameapproval_reject_confirm
HTML
<?xml version="1.0" encoding="utf-8" ?>
<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
  <g:dialog_notes_ok_cancel
    dialog_id="approval_reject_confirm"
    textarea_id="reject_reason_text"
    textarea_label="${gs.getMessage('Reason')}"
    textarea_label_title="${gs.getMessage('A reason is required to reject this approval')}"
    textarea_name="reject_reason_text"
    textarea_onkeyup="enableButton()"
    textarea_onchange="enableButton()"
    textarea_style="height:auto; width: 100%; resize: vertical;"
    textarea_title="${gs.getMessage('Enter the reason here')}"
    ok=""
    ok_action="callSubmitReject"
    ok_id="reject_confirm_ok_btn"
    ok_title="${gs.getMessage('Reject approval')}"
    ok_type="button"
    ok_style_class="btn btn-primary disabled"
    cancel_title="${gs.getMessage('Close the dialog')}"
  />
</j:jelly>
Client script
function callSubmitReject() {
  var textArea = $("reject_reason_text");
  
  if (textArea) {
    submitReject(textArea.value.trim());
  }
}

(function() {
  $("reject_reason_text").focus();
})();

 

UI Action "Reject"

If already done, we can take the copied version of the OOTB UI Action "Reject" which was built in the article Improving the Approval Experience, Part 2. If not you can decide to extend the OOTB UI Action or create a new custom version (in that case don't forget to deactivate the OOTB variant!)

Go to System UI > UI Actions and modify the existing UI Action or create a new one with the following properties:

 

FieldValue
Action namereject
Show update(checked)
Client(checked)
Form button(checked)
Form StyleDestructive
OnclickloadConfirmDialog();
Conditioncurrent.state == 'requested' && (new ApprovalDelegationUtil().isMyApproval(current))
Script
var rejectConfirmDialog;

function loadConfirmDialog() {
  var strComments = (g_form.getValue("comments") || '').trim();
  
  //in case no comment have been entered a popup will be opened to force entering of a reject reason
  if (strComments.length == 0) {
    var dialogClass = window.GlideModal ? GlideModal : GlideDialogWindow;

    rejectConfirmDialog = new dialogClass("approval_reject_confirm", false, 648, 250);

    rejectConfirmDialog.setTitle(new GwtMessage().getMessage("Reject")); 
    rejectConfirmDialog.render();
  }
  else {
    gsftSubmit(null, g_form.getFormElement(), "reject");
  }
}

function submitReject(comments) {
  g_form.setValue("comments", comments); 
  rejectConfirmDialog.destroy();
  gsftSubmit(null, g_form.getFormElement(), "reject");
}

if (typeof window == 'undefined') {
  rejectApproval();
}

//server side code of that UI Action
function rejectApproval() {
  var comments = false;

  //check whether user has entered a reject reason
  if (current.comments.getJournalEntry(1) != undefined) {
    var lastComment = current.comments.getJournalEntry(1);
    var index       = (current.comments.getJournalEntry(1) + '').indexOf(gs.getUserDisplayName());

    if (index > -1 && index <= 22) {
      comments = true;
    }
  }

  if(!JSUtil.nil(current.comments) || comments) {
    current.state = 'rejected';
    
    current.update();
    new ApprovalUserFeedback().rejected(current);
    action.setRedirectURL(current);
  }
  else {
    gs.addErrorMessage(gs.getMessage("Comments are required when rejecting an approval"));
    current.setAbortAction(true);
  }
}

 

Feel free to customize the code according to your needs. And please let me know in the comments if you have any suggestions for improvement.

Comments
Somujit1
Tera Contributor

Hi @Maik Skoddow

 

Is there a way to achieve the same when performing the rejection (using the List Choice and List Context Menu Reject UI Action)?

 

I tried with creating the UI Page as shared by you and updating the two OOTB the UI Actions as attached. But it doesn't seem to work.  Can you please help me on the same, if it is possible.

Thanks in advance.UI Action.JPGUI_Action_Script.JPG

AlainT1
Tera Guru

What a great series!  Thank you @Maik Skoddow 

Version history
Last update:
‎08-28-2021 10:22 PM
Updated by: