SOW to CSM/FSM Workspace Migration

Author: Rohan Aditya

Date: 7th October 2025

Key points covered:

  • Conflict Calendar on Change
  • Risk Assessment on Change
  • Completed Risk Assessment on Change
  • Check Conflicts on Change
  • Create Request on Incident

Quick Navigation

Conflict Calendar on Change

  1. Open the Conflict Calendar UI Action, sys_id = a8b7eac20b1332005775aabcb4673ae2
  2. Check Workspace Form Button or Workspace Form Menu
  3. Check Format for Configurable Workspace
  4. Update the Workspace Client Script:
  5. 
            function onClick(g_form) {
        var sys_id = g_form.getUniqueValue();
        var url = top.location.href;
    
        var routeGr = new GlideAjax(‘KAPChangeUtils’);
        routeGr.addParam('sysparm_name','getBaseURL');
        routeGr.getXMLAnswer(function(response){
            var route = url.split(response);
            var newUrl = route[1] + '/sub/change-conflict-calendar/' + sys_id;
            open(newUrl, '_self');
        });
    }
    
          
  6. We need to create a new page and Script include for this
  7. Create a Script Include with the Configurations
  8. Name: KAPChangeUtils
    Application: Global
    Accessible from: All application scopes
    Client Callable: True
    Active: True
    Mobile Callable: False
    Sandbox enabled: False
    Script include:
    
            var KAPChangeUtils = Class.create();
            KAPChangeUtils.prototype = Object.extendsObject(AbstractAjaxProcessor, {
              getBaseURL: function(){
                return gs.getProperty('glide.servlet.uri').toString();
              },
              type: 'KAPChangeUtils'
            });
    
          
  9. We need to create a page with UI Builder

Creating a Page in UI Builder

  1. Open UI Builder and search for CSM/FSM Configurable Workspace
  2. Click on + icon beside Pages and Variants to create a page


  3. Select “Create a new page”


  4. then “Create from scratch instead”


  5. Name: “Change Conflict Calendar


  6. So that URL path will be “change-conflict-calendar” (make sure this should be the URL path, as we call this URL In Workspace Client Script)

  7. Under the Required parameter section, click on +Add and enter the name as “SysId”. Then, click Look good, provide the page name as Conflict Calendar, and click Continue.

  8. Select “Build responsive” to build a responsive conflict calendar page

  9. This creates a new page, and it will be visible under “Pages and Variants” of CSM/ FSM Experience

  10. Open page from the list of pages


  11. Click on “Settings” on top the page


  12. Open Under Actions, click on arrow beside "Open records" Select “variant record”.


  13. Clear the Macroponent configuration & Event mapping fields and Set "App configuration" set to your new workspace(In our case it is CSM/FSM Configurable Workspace App Config) and Save the record.

  14. Now open “Page definition”


  15. A UX Macroponent Definition record will open, displaying the fields: Layout Model, Composition, Data, Internal Event Mapping, Properties, Dispatched Events, and State

  16. Using SN Utils, open the OOB record 4b5a6af60b0d1110c85e8a8db777b270, titled “Change Conflict Calendar default”, which is used in the OOB SOW

  17. Copy the values from the fields (Layout Model, Composition, Data, Internal Event Mapping, Properties, Dispatched Events, and State) in the OOB record, paste them into your new UX Macroponent Definition record, and then save the record..

  18. Now we have Conflict Calendar form button in CSM/ FSM Configurable workspace. After clicking on Conflict Calendar we get,


Risk Assessment on Change

  1. Open the Risk Assessment UI Action, sys_id = 8d300156d7033200532c24837e6103e8
  2. Check Workspace Form Button or Workspace Form Menu
  3. Check Format for Configurable Workspace
  4. Update the Workspace Client Script:
  5. 
     function onClick(g_form) {
         invokeAssessment();
     }
    
     function invokeAssessment() {
         g_form.hideAllFieldMsgs();
         if (g_form.isUserModified()) {
             handleDirtyForm();
         } else {
             var changeRequestSysId = g_form.getUniqueValue();
             var tableName = g_form.getTableName();
             var ga = new GlideAjax("ChangeRiskAsmtAjax");
             ga.addParam("sysparm_name", "invokeAssessmentAjax");
             ga.addParam("sysparm_id", changeRequestSysId);
             ga.addParam("sysparm_class", tableName);
             ga.getXMLAnswer(function(answer) {
    
                 answer = JSON.parse(answer);
                 if (!answer.hasAsmt)
                     g_form.addInfoMessage(getMessage("There are no risk assessments defined for this Change Request"));
                 else {
                     if (answer.asmtComplete)
                         handleCompletedAsmt();
                     else {
                         var asmtInstanceSysId = answer.asmtInstanceSysId;
                         var changeRiskAsmtSysId = answer.changeRiskAsmtSysId;
                         var changeRequestSysId = answer.changeRequestSysId;
                         var riskAsmtName = answer.riskAsmtName;
                         handleAsmt(asmtInstanceSysId, changeRiskAsmtSysId, changeRequestSysId, riskAsmtName);
                     }
                 }
             });
         }
     }
    
     function handleDirtyForm() {
         var msg = getMessage("Do you want to save changes to " + g_form.getValue("number") + " before leaving this page?");
         g_modal.confirm(getMessage("Confirmation"), msg, function(confirmed) {
             if (confirmed) {
                 g_form.save();
             }
    
         });
     }
    
     function handleCompletedAsmt() {
    
         var msg = getMessage("You have already completed the risk assessment. Would you like to edit your existing risk assessment?");
         g_modal.confirm(getMessage("Confirmation"), msg, function(confirmed) {
             if (confirmed) {
                 var changeRequestSysId = g_form.getUniqueValue();
                 var tableName = g_form.getTableName();
                 var ga = new GlideAjax("ChangeRiskAsmtAjax");
                 ga.addParam("sysparm_name", "copyAssessmentAjax");
                 ga.addParam("sysparm_id", changeRequestSysId);
                 ga.addParam("sysparm_class", tableName);
                 ga.getXMLAnswer(function(answer) {
    
                     answer = JSON.parse(answer);
                     if (!answer || !answer.hasAsmt)
                         g_form.addInfoMessage(getMessage("There are no risk assessments defined for this Change Request"));
                     else {
                         var asmtInstanceSysId = answer.asmtInstanceSysId;
                         var changeRiskAsmtSysId = answer.changeRiskAsmtSysId;
                         var changeRequestSysId = answer.changeRequestSysId;
                         var riskAsmtName = answer.riskAsmtName;
                         handleAsmt(asmtInstanceSysId, changeRiskAsmtSysId, changeRequestSysId, riskAsmtName);
                     }
                 });
             }
         });
     }
    
     function handleAsmt(asmtInstanceSysId, changeRiskAsmtSysId, changeRequestSysId, riskAsmtName) {
    
         var asmtUiPage = "assessment_take2";
         var url = asmtUiPage + ".do";
         url += "?sysparm_assessable_sysid=" + asmtInstanceSysId;
         url += "&sysparm_assessable_type=" + changeRiskAsmtSysId;
         url += "&sysparm_hide_header=true";
         url += "&sysparm_hide_save=true";
         url += "&sysparm_hide_cancel=true";
         url += "&sysparm_hide_source_details=true";
         url += "&sysparm_stack=no";
         url += "&sysparm_return_url=" + getEncodedUrl(changeRequestSysId, asmtInstanceSysId);
         g_modal.showFrame({
             url: url,
             title: 'JT Risk Assessments',
             size: 'lg',
             height: 1000,
         });
    
     }
    
     function getEncodedUrl(changeRequestSysId, asmtInstanceSysId) {
         var closeUiPage = "change_risk_asmt_close_dialog";
         var url = "/" + closeUiPage + ".do";
         url += "?sysparm_stack=no";
         url += "&sysparm_id=" + changeRequestSysId;
         url += "&sysparm_asmtInstanceSysId=" + asmtInstanceSysId;
         return encodeURIComponent(url);
     }
              

Completed Risk Assessment on Change

  1. Open the Completed Risk Assessment UI Action, sys_id = 5406d544b7612300da26e4f6ee11a9c3
  2. Check Workspace Form Button or Workspace Form Menu
  3. Check Format for Configurable Workspace
  4. Update the Workspace Client Script:
  5. 
     function onClick(g_form) {
         viewCompleted();
     }
    
     function viewCompleted() {
         var changeRequestSysId = g_form.getUniqueValue();
         var tableName = g_form.getTableName();
         var ga = new GlideAjax("ChangeRiskAsmtAjax");
         ga.addParam("sysparm_name", "viewAssessmentAjax");
         ga.addParam("sysparm_id", changeRequestSysId);
         ga.addParam("sysparm_class", tableName);
         ga.getXMLAnswer(function(answer) {
             answer = JSON.parse(answer);
             if (!answer || !answer.asmtComplete) {
                 g_form.addInfoMessage(getMessage("There are no completed risk assessments for this Change Request"));
             } else {
                 var asmtInstanceSysId = answer.asmtInstanceSysId;
                 var changeRiskAsmtSysId = answer.changeRiskAsmtSysId;
                 var changeRequestSysId = answer.changeRequestSysId;
                 var riskAsmtName = answer.riskAsmtName;
                 _showCompletedAsmt(asmtInstanceSysId, changeRiskAsmtSysId, changeRequestSysId, riskAsmtName);
             }
         });
     }
    
     function _showCompletedAsmt(asmtInstanceSysId, changeRiskAsmtSysId, changeRequestSysId, riskAsmtName) {
         g_form.hideAllFieldMsgs();
         var asmtUiPage = "assessment_take2";
         var url = asmtUiPage + ".do";
         url += "?sysparm_assessable_sysid=" + asmtInstanceSysId;
         url += "&sysparm_assessable_type=" + changeRiskAsmtSysId;
         url += "&sysparm_reader_view=true";
         url += "&sysparm_hide_header=true";
         url += "&sysparm_hide_save=true";
         url += "&sysparm_hide_cancel=true";
         url += "&sysparm_hide_source_details=true";
         url += "&sysparm_stack=no";
    
         g_modal.showFrame({
             url: url,
             title: riskAsmtName,
             size: 'lg',
             height: 1000
         });
     }
              

Check Conflicts on Change

  1. Open the Check Conflicts UI Action, sys_id = d3668ab84a36232b00bbd765d0e94336
  2. Check Active checkbox if UI action is needed
  3. Check Workspace Form Button or Workspace Form Menu
  4. Check Format for Configurable Workspace
  5. Update the Workspace Client Script:
  6. 
     function onClick(g_form) {
         var fields = [];
         var missingLabels = [];
    
         if (g_form.hasField("start_date") && !g_form.getValue("start_date")) {
             fields.push("start_date");
             missingLabels.push(g_form.getLabelOf("start_date"));
         }
    
         if (g_form.hasField("end_date") && !g_form.getValue("end_date")) {
             fields.push("end_date");
             missingLabels.push(g_form.getLabelOf("end_date"));
         }
    
         if (g_form.hasField("cmdb_ci") && !g_form.getValue("cmdb_ci")) {
             fields.push("cmdb_ci");
             missingLabels.push(g_form.getLabelOf("cmdb_ci"));
         }
    
         if (missingLabels.length > 0) {
             var msg = (missingLabels.length > 1) ?
                 "To check conflicts, the following fields need values: " + missingLabels.join(", ") :
                 "To check conflicts, the following field needs a value: " + missingLabels[0];
             g_form.addErrorMessage(msg);
             fields.forEach(function(field) {
                 g_form.showFieldMsg(field, "Required for conflict check", "error", false);
             });
             return;
         }
         g_form.clearMessages();
         g_form.submit("check_conflicts");
     }
              

Create Request on Incident

  1. Open the Create Request UI Action, sys_id = b7980ba483b76e10ccf85d70deaad32e
  2. Instead of creating a UI Action we can go with Action Assignment.
  3. Open the above record using SN Utils, it is “Create request” Action Assignment.
  4. Insert and Stay on the record, empty the view field and check the “Enable for all Configurable Experiences” check box and Save the record.
  5. 
    function onClick(g_form) {
        var fields = [];
        var missingLabels = [];
    
        if (g_form.hasField("start_date") && !g_form.getValue("start_date")) {
            fields.push("start_date");
            missingLabels.push(g_form.getLabelOf("start_date"));
        }
    
        if (g_form.hasField("end_date") && !g_form.getValue("end_date")) {
            fields.push("end_date");
            missingLabels.push(g_form.getLabelOf("end_date"));
        }
    
        if (g_form.hasField("cmdb_ci") && !g_form.getValue("cmdb_ci")) {
            fields.push("cmdb_ci");
            missingLabels.push(g_form.getLabelOf("cmdb_ci"));
        }
    
        if (missingLabels.length > 0) {
            var msg = (missingLabels.length > 1) ?
                "To check conflicts, the following fields need values: " + missingLabels.join(", ") :
                "To check conflicts, the following field needs a value: " + missingLabels[0];
            g_form.addErrorMessage(msg);
            fields.forEach(function(field) {
                g_form.showFieldMsg(field, "Required for conflict check", "error", false);
            });
            return;
        }
        g_form.clearMessages();
        g_form.submit("check_conflicts");
    }