In the employee center approval if approver clicks on approve it should pop up the comment box

vinayak_2023
Tera Contributor

In the approval page on employee center if approver click on approve it should pop up the comment box to provide the reason for approval.

I have tried cloning the widgets Todo approvals and Todo Approvals action and added the logic for approve and it is working on the record which are not in the To-do configuration for ex Enhancement, but it is not working for the records which are configured in the To-do configuration example Request and change request. Please help me to work on all the approval records.

4 REPLIES 4

Ankur Bawiskar
Tera Patron
Tera Patron

@vinayak_2023 

share the complete widget code here

💡 If my response helped, please mark it as correct and close the thread 🔒— this helps future readers find the solution faster! 🙏

Regards,
Ankur
Certified Technical Architect  ||  9x ServiceNow MVP  ||  ServiceNow Community Leader

Please find the script:

Server Script for the Widget Todos Approval 

(function() {
    var REQUESTED_STATE = "requested";

    if (options && options.sysId) {
        data.approvalId = options.sysId;
        getApprovalInfo(data.approvalId);
        options.useCommentBox = false;

        // Invoke the cloned widget instead of OOB
        data.approvalActionsWidget = $sp.getWidget("todo-approval-actions-change", options);
    }

    function getApprovalInfo(sysId) {
        var sysApprovalRecord = new GlideRecordSecure('sysapproval_approver');
        data.shortDescription = "";
        if (sysApprovalRecord.get(sysId)) {
            data.isPosted = false;
            if (sysApprovalRecord.state.toString() !== REQUESTED_STATE)
                data.isPosted = true;

            if (!gs.nil(sysApprovalRecord.sysapproval) && !gs.nil(sysApprovalRecord.sysapproval.short_description))
                data.shortDescription = sysApprovalRecord.sysapproval.short_description;
            else if (!gs.nil(sysApprovalRecord.document_id))
                data.shortDescription = !gs.nil(sysApprovalRecord.document_id.short_description) ?
                    (sysApprovalRecord.document_id.number + " - " + sysApprovalRecord.document_id.short_description) :
                    sysApprovalRecord.document_id.number;
            else
                data.shortDescription = !gs.nil(sysApprovalRecord.sysapproval) ? sysApprovalRecord.sysapproval.number : "";

            data.approvalText = gs.getMessage("Do you want to approve the following: {0}?", data.shortDescription);
        } else {
            gs.addErrorMessage(gs.getMessage("Unexpected action occurred"));
        }
        return sysApprovalRecord;
    }
})();
Server script for the widget Todos Approval Actions
(function() {
    data.CONST = {
        i18n: {
            PLACEHOLDER_MESSAGE: gs.getMessage("If you are rejecting the request, provide the reason here."),
            REJECT_MODAL_TITLE: gs.getMessage("Reject Request"),
            REJECT_MODAL_MESSAGE: gs.getMessage("Please provide a reason for rejecting the request"),
            REJECT_MODAL_CANCEL: gs.getMessage("Cancel"),
            REJECT_MODAL_SUBMIT: gs.getMessage("Reject Request"),
            REJECT_MODAL_NO_COMMENT_MESSAGE: gs.getMessage("Provide the reason you are rejecting the request in the comments field."),
            APPROVE_MODAL_TITLE: gs.getMessage("Approve Request"),
            APPROVE_MODAL_MESSAGE: gs.getMessage("Please provide a reason for approving the request (optional)"),
           // APPROVE_MODAL_CANCEL: gs.getMessage("Cancel"),
           // APPROVE_MODAL_SUBMIT: gs.getMessage("Approve Request"),
            REAUTH_FAILED_MESSAGE: gs.getMessage('An error occurred during authentication. Please contact your system administrator.')
        },
        ACTION: "updateApprovals",
        REJECT_STATE: "rejected",
        APPROVED_STATE: "approved",
        REQUESTED_STATE: "requested",
        APPROVAL_TABLE: "sysapproval_approver"
    };

    // Get sysId and other options
    data.sysId = input && input.sysId ? input.sysId : options.sysId;
    data.commentId = input && input.commentId ? input.commentId : options.commentId;
    data.commentTable = input && input.commentTable ? input.commentTable : options.commentTable;

    // Force modal behavior for both approve and reject
    data.useCommentBox = false;

    if (data.sysId) {
        var todoApprovalActionsUtil = new sn_ex_sp.TodoApprovalActionsUtil();
        var approvalGr = todoApprovalActionsUtil.getTargetRecord(data.sysId, data.CONST.APPROVAL_TABLE);

        if (!gs.nil(approvalGr)) {
            data.esignRequiredObj = todoApprovalActionsUtil.getEsignObj(approvalGr);
            data.isApprover = todoApprovalActionsUtil.isApprover(approvalGr);

            if (data.isApprover) {
                data.isPosted = false;
                var commentGr = null;

                if (data.commentId && data.commentTable) {
                    commentGr = todoApprovalActionsUtil.getTargetRecord(data.commentId, data.commentTable);
                    if (!gs.nil(commentGr)) {
                        data.requireRejectionComment = todoApprovalActionsUtil.checkRejectionCommentRequired(commentGr);
                    }
                }

                // Only update when client explicitly sends action after modal
                if (input && input.action === data.CONST.ACTION) {
                    input.request.requireRejectionComment = data.requireRejectionComment;
                    input.request.useCommentBox = data.useCommentBox;
                    input.request.comments = input.request.comments || '';

                    // Update approval and comment for both approve and reject
                    data.isPosted = todoApprovalActionsUtil.updateApprovalAndComment(approvalGr, commentGr, input.request);

                    if (data.isPosted && !gs.nil(commentGr)) {
                        setPostApprovalInfo(todoApprovalActionsUtil.getPostApprovalInfo(approvalGr, commentGr));
                    }
                } else if (data.commentId && data.commentTable) {
                    if (approvalGr.state.toString() !== data.CONST.REQUESTED_STATE) {
                        data.isPosted = true;
                        if (!gs.nil(commentGr)) {
                            setPostApprovalInfo(todoApprovalActionsUtil.getPostApprovalInfo(approvalGr, commentGr));
                        }
                    }
                }
            }
        }
    }

    function setPostApprovalInfo(postApprovalInfo) {
        data.caption = postApprovalInfo.caption;
        data.comment = postApprovalInfo.comment;
        data.timestamp = postApprovalInfo.timestamp;
    }
})();
Client controller :
function todosApprovalController($scope, spModal, spAuthModal, $http, spUtil, $log) {
    var c = this;

    $scope.onActionClick = function(state) {
        if (state === c.data.CONST.REJECT_STATE) {
            // Always show modal for reject
            spModal.open({
                title: c.data.CONST.i18n.REJECT_MODAL_TITLE,
                message: c.data.CONST.i18n.REJECT_MODAL_MESSAGE,
                input: true, // Adds text box
                buttons: [{
                        label: c.data.CONST.i18n.REJECT_MODAL_CANCEL,
                        cancel: true
                    },
                    {
                        label: c.data.CONST.i18n.REJECT_MODAL_SUBMIT,
                        primary: true
                    }
                ]
            }).then(function(comment) {
                if (!comment || comment.trim() === '') {
                    spUtil.addErrorMessage(c.data.CONST.i18n.REJECT_MODAL_NO_COMMENT_MESSAGE);
                    return;
                }
                if (c.data.esignRequiredObj.e_sign_required) {
                    openEsignatureModal(state, comment);
                } else {
                    sendUpdateRequest(state, c.data.CONST.ACTION, comment);
                }
            });
        } else if (state === c.data.CONST.APPROVED_STATE) {
    spModal.open({
        title: c.data.CONST.i18n.APPROVE_MODAL_TITLE,
        widget: 'custom-approval-modal',
        buttons: [
            { label: c.data.CONST.i18n.APPROVE_MODAL_CANCEL, cancel: true },
            { label: c.data.CONST.i18n.APPROVE_MODAL_SUBMIT, primary: true }
        ]
    }).then(function(comment) {
        c.data.action = c.data.CONST.ACTION; // Explicitly set action
        sendUpdateRequest(state, c.data.CONST.ACTION, comment || '');
    });
}
        return false;
    };

    function sendUpdateRequest(state, action, comment) {
        c.data.action = action;
        c.data.sysId = c.data.sysId;
        c.data.commentId = c.data.commentId;
        c.data.commentTable = c.data.commentTable;
        c.data.useCommentBox = false; // Force modal behavior
        c.data.request = {
            state: state,
            comments: comment
        };
        c.server.update();
    }

    function openEsignatureModal(state, comment) {
        var requestParams = {
            username: c.data.esignRequiredObj.username,
            userSysId: c.data.esignRequiredObj.userSysId
        };
        spAuthModal.prompt(requestParams, requestParams.username, requestParams.userSysId)
            .then(null, function() {
                alert(c.data.CONST.i18n.REAUTH_FAILED_MESSAGE);
            })
            .then(function() {
                $http.post('/api/sn_ex_sp/approvals/updateState', {
                    sysId: c.data.sysId,
                    commentId: c.data.commentId,
                    commentTable: c.data.commentTable,
                    useCommentBox: false,
                    state: state,
                    comments: comment
                }).then(function(response) {
                    if (response && response.data && response.data.result) {
                        c.getPostApprovalInfo(response.data.result);
                    }
                }, function(reason) {
                    spUtil.addErrorMessage(c.data.CONST.i18n.REAUTH_FAILED_MESSAGE);
                    $log.error(reason);
                });
            });

        c.getPostApprovalInfo = function(result) {
            c.data.isPosted = result.isPosted;
            c.data.caption = result.postApprovalInfo.caption;
            c.data.comment = result.postApprovalInfo.comment;
            c.data.timestamp = result.postApprovalInfo.timestamp;
        };
    }
}


@vinayak_2023 

can you share XMLs of both the customized widget here so that it can be checked in PDI

Regards,
Ankur
Certified Technical Architect  ||  9x ServiceNow MVP  ||  ServiceNow Community Leader

Please find the attachments