Name

sn_flow_diagram.FlowDiagramActionApi

Description

No description available

Script

var FlowDiagramActionApi = Class.create();
FlowDiagramActionApi.prototype = {
  initialize: function() {},

  type: "FlowDiagramActionApi",
};

var recordCache = {};
var ENABLE_CACHE = true;
var ATTRIBUTES = [
  "sys_id",
  "name",
  "order",
  "type",
  "description",
  "category.name",
  "sys_scope",
  "sys_name",
  "system_level",
  "script",
  "menu_option",
  "visibility_condition",
  "shape_template",
  "allow_delete",
  "x",
  "y",
  "port_offset_x",
  "port_offset_y",
  "active",
  "spot",
  "from_max_links",
  "to_max_links",
  "direction",
  "shape_port",
  "node_type",
];

FlowDiagramActionApi.setCachedRecord = function(table, sysId, gr) {
  if (table && !recordCache[table]) {
      recordCache[table] = {};
  }
  if (table && sysId && !recordCache[table][sysId]) {
      recordCache[table][sysId] = {};
  }
  if (table && sysId && gr) {
      recordCache[table][sysId] = gr;
  }
};

FlowDiagramActionApi.getCachedRecord = function(table, sysId) {
  if (ENABLE_CACHE && recordCache && recordCache[table] && recordCache[table][sysId]) {
      return recordCache[table][sysId];
  }
  return;
};

FlowDiagramActionApi.getDbTable = function(table) {
  var dGr = new GlideRecord(table);
  return dGr;
};

FlowDiagramActionApi.setValueIfExists = function(gr, component, fieldName, setDisplayAndReference) {
  if (gr && gr[fieldName]) {
      if (setDisplayAndReference) {
          component[fieldName + "Id"] = gr.getValue(fieldName);
          component[fieldName] = gr.getDisplayValue(fieldName);
      } else {
          component[fieldName] = gr.getValue(fieldName);
      }
  }
};

FlowDiagramActionApi.componentToPojo = function(gr, nodeTypeSysId) {
  var component = {};

  FlowDiagramActionApi.setValueIfExists(gr, component, "category", true);
  FlowDiagramActionApi.setValueIfExists(gr, component, "subcategory", true);

  if (gr && gr.isValidRecord && typeof gr.isValidRecord === "function") {
      component.is_valid_record = gr.isValidRecord();
  }
  if (nodeTypeSysId) {
      component.node_type = nodeTypeSysId;
  }

  for (var i in ATTRIBUTES) {
      FlowDiagramActionApi.setValueIfExists(gr, component, ATTRIBUTES[i]);
  }

  component.getValue = function(key) {
      return component[key];
  };
  component.getDisplayValue = function(key) {
      return component[key];
  };

  component.isValidRecord = function() {
      return component.is_valid_record || false;
  };

  return component;
};

FlowDiagramActionApi.getActionNodeType = function() {
  return FlowDiagramActionApi.getActionNodeTypeBySysId(FlowDiagramConstants.SYS_IDS.FLOW_ACTION_NODE_TYPE);
};

FlowDiagramActionApi.getActionNodeTypeBySysId = function(sysId) {
  var table = FlowDiagramConstants.TABLE_NAMES.DIAGRAM_BUILDER.NODE_TYPE;
  var actionNodeType = FlowDiagramActionApi.getCachedRecord(table, sysId);
  if (!actionNodeType) {
      var dGr = FlowDiagramActionApi.getDbTable(table);
      dGr.get(sysId);
      actionNodeType = FlowDiagramActionApi.componentToPojo(dGr);
      FlowDiagramActionApi.setCachedRecord(table, sysId, actionNodeType);
  }
  return actionNodeType;
};

FlowDiagramActionApi.getDiagramActionBySysIds = function(sysIds) {
  var table = FlowDiagramConstants.TABLE_NAMES.DIAGRAM_BUILDER.DIAGRAM_ACTION;
  var diagramActions = FlowDiagramActionApi.getCachedRecord(table, sysIds);
  if (!diagramActions) {
      var dGr = FlowDiagramActionApi.getDbTable(table);
      dGr.addQuery("sys_id", "IN", sysIds);
      dGr.query();
      diagramActions = [];
      while (dGr.next()) {
          diagramActions.push(FlowDiagramActionApi.componentToPojo(dGr));
      }
      FlowDiagramActionApi.setCachedRecord(table, sysIds, diagramActions);
  }
  return diagramActions;
};

FlowDiagramActionApi.getContextMenusGlideRecord = function(nodeTypeSysId) {
  var table = FlowDiagramConstants.TABLE_NAMES.DIAGRAM_BUILDER.CONTEXT_MENU_OPTION_M2M;
  var contextRecord = FlowDiagramActionApi.getCachedRecord(table, nodeTypeSysId);
  // No need to look up context menu if it's a blank node
  if (!contextRecord && nodeTypeSysId !== FlowDiagramConstants.SYS_IDS.FLOW_END_NODE_TYPE) {
      var dGr = FlowDiagramActionApi.getDbTable(table);
      dGr.addQuery("active", "true");
      dGr.addQuery("node_type", nodeTypeSysId);
      dGr.orderBy("order");
      dGr.query();
      contextRecord = [];
      while (dGr.next()) {
          contextRecord.push(FlowDiagramActionApi.componentToPojo(dGr));
      }
      FlowDiagramActionApi.setCachedRecord(table, nodeTypeSysId, contextRecord);
  }
  // Can be empty
  return contextRecord;
};

FlowDiagramActionApi.getUIActionsGlideRecord = function(menuOptionId) {
  var table = FlowDiagramConstants.TABLE_NAMES.DIAGRAM_BUILDER.CONTEXT_MENU_OPTION;
  var uiActions = FlowDiagramActionApi.getCachedRecord(table, menuOptionId);
  if (!uiActions) {
      var dGr = FlowDiagramActionApi.getDbTable(table);
      dGr.get(menuOptionId);
      uiActions = FlowDiagramActionApi.componentToPojo(dGr);
      FlowDiagramActionApi.setCachedRecord(table, menuOptionId, uiActions);
  }
  return uiActions;
};

FlowDiagramActionApi.getConnectorsGlideRecord = function(nodeTypeSysId) {
  var table = FlowDiagramConstants.TABLE_NAMES.DIAGRAM_BUILDER.NODE_CONNECTOR;
  var grConnectors = FlowDiagramActionApi.getCachedRecord(table, nodeTypeSysId);
  if (!grConnectors) {
      var dGr = FlowDiagramActionApi.getDbTable(table);
      dGr.addQuery("active", "true");
      dGr.addQuery("node_type", nodeTypeSysId);
      dGr.query();
      grConnectors = [];
      while (dGr.next()) {
          grConnectors.push(FlowDiagramActionApi.componentToPojo(dGr));
      }
      FlowDiagramActionApi.setCachedRecord(table, nodeTypeSysId, grConnectors);
  }
  return grConnectors;
};

FlowDiagramActionApi.getConnectorPortGlideRecord = function(sysId) {
  var table = FlowDiagramConstants.TABLE_NAMES.DIAGRAM_BUILDER.NODE_CONNECTOR_PORT;
  var grConnectorPort = FlowDiagramActionApi.getCachedRecord(table, sysId);
  if (!grConnectorPort) {
      var dGr = FlowDiagramActionApi.getDbTable(table);
      dGr.get(sysId);
      grConnectorPort = FlowDiagramActionApi.componentToPojo(dGr);
      FlowDiagramActionApi.setCachedRecord(table, sysId, grConnectorPort);
  }
  return grConnectorPort;
};

FlowDiagramActionApi.getSpotGlideRecord = function(sysId) {
  var table = FlowDiagramConstants.TABLE_NAMES.DIAGRAM_BUILDER.SPOT;
  var grSpot = FlowDiagramActionApi.getCachedRecord(table, sysId);
  if (!grSpot) {
      var dGr = FlowDiagramActionApi.getDbTable(table);
      dGr.get(sysId);
      grSpot = FlowDiagramActionApi.componentToPojo(dGr);
      FlowDiagramActionApi.setCachedRecord(table, sysId, grSpot);
  }
  return grSpot;
};

FlowDiagramActionApi.getNodeTypeHandlerGlideRecord = function(actionNodeTypeSysId) {
  var table = FlowDiagramConstants.TABLE_NAMES.DIAGRAM_BUILDER.NODE_TYPE_HANDLER;
  var grNodeTypeHandler = FlowDiagramActionApi.getCachedRecord(table, actionNodeTypeSysId);
  if (!grNodeTypeHandler) {
      var dGr = FlowDiagramActionApi.getDbTable(table);
      dGr.addQuery("active", "true");
      dGr.addQuery("node_type", actionNodeTypeSysId);
      dGr.query();
      grNodeTypeHandler = [];
      while (dGr.next()) {
          grNodeTypeHandler.push(FlowDiagramActionApi.componentToPojo(dGr));
      }
      FlowDiagramActionApi.setCachedRecord(table, actionNodeTypeSysId, grNodeTypeHandler);
  }
  return grNodeTypeHandler;
};

FlowDiagramActionApi.getFlowlogicIcon = function(flowlogicType) {
  if (!FlowDiagramConstants.FLOW_LOGIC_TYPES[flowlogicType])
      return FlowDiagramConstants.IMAGES_PATH.DIAGRAM_LOGIC.DEFAULT_ICON;

  return FlowDiagramConstants.IMAGES_PATH.DIAGRAM_LOGIC + flowlogicType.toLowerCase() + ".svg";
};

FlowDiagramActionApi.stringToBool = function(str) {
  return ["1", "true", "yes"].indexOf(str) !== -1;
};

/**
* Build a map of sys_id -> subset of GlideRecord (GR) attributes
*
* This function prevents incorrect mapping of GR values resulting
* from trying to store a GlideRecord tuple from a result set
* while it is being iterated over
*
* @param {*} tableName
* @param {*} arrayOfIds
* @returns
*/
FlowDiagramActionApi.componentMapFromGlideRecordQuery = function(tableName, arrayOfIds) {
  var gr = FlowDiagramActionApi.getDbTable(tableName);
  gr.addQuery("sys_id", "IN", arrayOfIds.join(","));
  gr.query();
  var componentMap = {};
  while (gr.next()) componentMap[gr.getUniqueValue()] = FlowDiagramActionApi.componentToPojo(gr);

  return componentMap;
};

FlowDiagramActionApi.getContextMenuOptionDisplayName = function(optionName) {
  var optionNameLowerCase = optionName.toLowerCase();
  if (FlowDiagramConstants.CONTEXT_MENU_OPTIONS[optionNameLowerCase]) {
      return FlowDiagramConstants.CONTEXT_MENU_OPTIONS[optionNameLowerCase];
  }
  return optionName;
};

FlowDiagramActionApi.getContextMenuOptions = function(actionNodeTypeSysId) {
  var menuOptions = [];
  var actionContextMenuOptions = FlowDiagramActionApi.getContextMenusGlideRecord(actionNodeTypeSysId);
  for (var i in actionContextMenuOptions) {
      var uiActionMenuRecord = FlowDiagramActionApi.getUIActionsGlideRecord(actionContextMenuOptions[i].menu_option);
      var optionName = uiActionMenuRecord.name;
      menuOptions.push({
          sysId: uiActionMenuRecord.sys_id,
          name: optionName,
          script: uiActionMenuRecord.script,
          showOption: uiActionMenuRecord.visibility_condition,
          displayName: FlowDiagramActionApi.getContextMenuOptionDisplayName(optionName),
          icon: FlowDiagramActionApi.getIconUrl(optionName)
      });
  }
  return menuOptions;
};

FlowDiagramActionApi.getIconUrl = function(name) {
  var url = "";
  switch (name) {
      case "View":
          url = FlowDiagramConstants.IMAGES_PATH.CONTEXT_MENU_VIEW;
          break;
      case "Delete":
          url = FlowDiagramConstants.IMAGES_PATH.CONTEXT_MENU_DELETE;
          break;
      case "Open in Subflow Designer":
      case "Open in Action Designer":
          url = FlowDiagramConstants.IMAGES_PATH.CONTEXT_MENU_OPEN;
          break;
      case "Duplicate":
          url = FlowDiagramConstants.IMAGES_PATH.CONTEXT_MENU_DUPLICATE;
          break;
  }
  return url;
};

FlowDiagramActionApi.getNodeTypeHandlers = function(actionNodeTypeSysId) {
  var nodeTypeHandlers = FlowDiagramActionApi.getNodeTypeHandlerGlideRecord(actionNodeTypeSysId);
  var handlers = [];
  for (var i in nodeTypeHandlers) {
      var nodeHandler = {
          script: nodeTypeHandlers[i].getValue("script"),
          type: nodeTypeHandler[i].getValue("type"),
      };
      handlers.push(nodeHandler);
  }
  return handlers;
};

FlowDiagramActionApi.getConnectorPortSpot = function(spotId) {
  var spot = FlowDiagramActionApi.getSpotGlideRecord(spotId);
  return {
      sysId: spot.getValue("sys_id"),
      x: spot.getValue("x") || "0",
      y: spot.getValue("y") || "0",
  };
};

FlowDiagramActionApi.getShapeConnectorPort = function(shapePort) {
  var actionConnectorPort = FlowDiagramActionApi.getConnectorPortGlideRecord(shapePort);
  return {
      shapeTemplate: actionConnectorPort.getValue("shape_template"),
      active: FlowDiagramActionApi.stringToBool(actionConnectorPort.getValue("active")),
      offsetX: actionConnectorPort.getValue("port_offset_x"),
      offsetY: actionConnectorPort.getValue("port_offset_y"),
      spot: FlowDiagramActionApi.getConnectorPortSpot(actionConnectorPort.getValue("spot")),
  };
};

FlowDiagramActionApi.getShapeConnectors = function(actionNodeTypeSysId) {
  var connectors = [];
  var actionConnectors = FlowDiagramActionApi.getConnectorsGlideRecord(actionNodeTypeSysId);
  for (var i in actionConnectors) {
      var actionConnector = actionConnectors[i];
      var connector = {
          active: FlowDiagramActionApi.stringToBool(actionConnector.getValue("active")),
          name: actionConnector.getValue("sys_name"),
          direction: actionConnector.getValue("direction"),
          order: actionConnector.getValue("order"),
          sysId: actionConnector.getValue("sys_id"),
          fromMaxLinks: actionConnector.getValue("from_max_links"),
          toMaxLinks: actionConnector.getValue("to_max_links"),
      };

      connector.connectorPort = FlowDiagramActionApi.getShapeConnectorPort(actionConnector.shape_port.toString());
      connectors.push(connector);
  }

  return connectors;
};

FlowDiagramActionApi.buildNodeType = function(actionNodeType) {
  return {
      active: "1",
      description: actionNodeType.getValue("description"),
      shapeTemplate: actionNodeType.getValue("shape_template"),
      nodeType: actionNodeType.getValue("sys_name"),
      sysId: actionNodeType.getValue("sys_id"),
      allowDelete: FlowDiagramActionApi.stringToBool(actionNodeType.getValue("allow_delete")),
      menuOptions: FlowDiagramActionApi.getContextMenuOptions(actionNodeType.getValue("sys_id")),
      nodeTypeHandlers: FlowDiagramActionApi.getNodeTypeHandlers(actionNodeType.getValue("sys_id")),
  };
};

FlowDiagramActionApi.createGhostAction = function(actionNodeType, id) {
  return {
      name: FlowDiagramConstants.NODE_NAMES.GHOST_ACTION,
      key: sn_flow.FlowDesigner.getGeneratedGuid(),
      sysId: id,
      description: "",
      icon: FlowDiagramConstants.IMAGES_PATH.GHOST_ICON,
      category: "Default",
      categoryId: "Default",
      subCategory: "Default",
      order: 100,
      nodeType: FlowDiagramActionApi.buildNodeType(actionNodeType),
      attributes: [],
      connectors: FlowDiagramActionApi.getShapeConnectors(actionNodeType.sys_id),
      actionDependencies: "[]",
      additionalProperties: {
          allowChildren: false,
          iconBackground: FlowDiagramConstants.NODE_ICON_BACKGROUND_COLORS.GHOST,
      },
  };
};

FlowDiagramActionApi.buildProperties = function(componentPojoOrGr, actionNodeType, typeOfGlideRecord, instanceType) {
  var category,
      categoryId,
      subCategory = "Default",
      order = 100,
      allowChildren = false,
      icon = "",
      iconBackground = "";

  if (typeOfGlideRecord === FlowDiagramConstants.ACTION_MAP_ID_TYPE.ACTION_TYPE) {
      var scopeGr = FlowDiagramActionApi.getDbTable(FlowDiagramConstants.TABLE_NAMES.SCOPE);
      scopeGr.get(componentPojoOrGr.sys_scope);
      category = scopeGr.getValue("name");
      categoryId = scopeGr.getValue("sys_id");
      subCategory = componentPojoOrGr.category ? componentPojoOrGr.category.name : ""; // Flowlogics don't have categories, not sure what to sub here

      if (instanceType === FlowDiagramConstants.INSTANCE_TYPES.FLOW_LOGIC_INSTANCE_TYPE) {
          allowChildren = true;
          icon = FlowDiagramActionApi.getFlowlogicIcon(componentPojoOrGr.getValue("type"));
      } else if (instanceType === FlowDiagramConstants.INSTANCE_TYPES.SUBFLOW_INSTANCE_TYPE) {
          icon = "/images/icon-subflow.svg";
      } else {
          // Check if the action type is ServiceNow Core - if so, leave it alone to use default SNOW logo
          if (!componentPojoOrGr.system_level)
              icon = category === "Global" ? "/images/icon-global-scope.svg" : scopeGr.getDisplayValue("logo");
      }

  } else if (typeOfGlideRecord === FlowDiagramConstants.ACTION_MAP_ID_TYPE.DIAGRAM_ACTION_TYPE) {
      category = componentPojoOrGr.getDisplayValue("category");
      categoryId = componentPojoOrGr.getValue("categoryId");
      subCategory = componentPojoOrGr.getDisplayValue("subcategory");
      order = componentPojoOrGr.getValue("order");

      if (actionNodeType.node_type === FlowDiagramConstants.NODE_TYPES.SUBFLOW_INS_OUTS) {
          icon = '/images/subflow_inputs_outputs.svg';
      }
  }

  iconBackground = icon && "#E4E6E7";

  var returnedNode = {
      name: componentPojoOrGr.getValue("name"),
      key: sn_flow.FlowDesigner.getGeneratedGuid(),
      sysId: componentPojoOrGr.getValue("sys_id"), // Originally used with diagram action ID, but we repurposed with action type ID
      description: componentPojoOrGr.getValue("description"),
      icon: icon,
      category: category,
      categoryId: categoryId,
      subCategory: subCategory,
      order: order,
      nodeType: FlowDiagramActionApi.buildNodeType(actionNodeType),
      attributes: [],
      connectors: FlowDiagramActionApi.getShapeConnectors(actionNodeType.sys_id),
      actionDependencies: "[]",
      additionalProperties: {
          allowChildren: allowChildren,
          iconBackground: iconBackground,
      },
  };

  return returnedNode;
};

FlowDiagramActionApi.mapFlowlogicNodeType = function(type) {
  switch (type) {
      case FlowDiagramConstants.FLOW_LOGIC_TYPES.IF:
      case FlowDiagramConstants.FLOW_LOGIC_TYPES.ELSEIF:
          return FlowDiagramConstants.SYS_IDS.FLOW_LOGIC_CONDITIONAL_NODE_TYPE;
      case FlowDiagramConstants.FLOW_LOGIC_TYPES.FOREACH:
          return FlowDiagramConstants.SYS_IDS.FLOW_LOGIC_LOOP_TYPE;
      case FlowDiagramConstants.FLOW_LOGIC_TYPES.DOUNTIL:
          return FlowDiagramConstants.SYS_IDS.FLOW_LOGIC_DO_LOOP_TYPE;
      case FlowDiagramConstants.FLOW_LOGIC_TYPES.PARALLELBLOCK:
          return FlowDiagramConstants.SYS_IDS.FLOW_LOGIC_PARALLEL_BLOCK;
      case FlowDiagramConstants.FLOW_LOGIC_TYPES.DECISIONBLOCK:
          return FlowDiagramConstants.SYS_IDS.FLOW_LOGIC_DECISION_BLOCK;
      case FlowDiagramConstants.FLOW_LOGIC_TYPES.PARALLEL:
      case FlowDiagramConstants.FLOW_LOGIC_TYPES.DECISION:
          return FlowDiagramConstants.SYS_IDS.FLOW_LOGIC_ONE_TO_MANY;
      case FlowDiagramConstants.FLOW_LOGIC_TYPES.RUNDYNAMICFLOW:
      case FlowDiagramConstants.FLOW_LOGIC_TYPES.ELSE:
      case FlowDiagramConstants.FLOW_LOGIC_TYPES.TIMER:
      case FlowDiagramConstants.FLOW_LOGIC_TYPES.RUNWORKFLOW:
          return FlowDiagramConstants.SYS_IDS.FLOW_LOGIC_ONE_TO_ONE;
      default:
          return FlowDiagramConstants.SYS_IDS.FLOW_ACTION_NODE_TYPE;
  }
};

FlowDiagramActionApi.createActionActionProperties = function(actionIdMap, actionNodeType, actionProperties, errors) {
  var actionTypeDefinitionMap = FlowDiagramActionApi.componentMapFromGlideRecordQuery(
      FlowDiagramConstants.TABLE_NAMES.ACTIONS.ACTION_TYPE_DEFINITION,
      actionIdMap[FlowDiagramConstants.ID_INPUTS.ACTION_TYPE_IDS]
  );

  for (var i = 0; i < actionIdMap[FlowDiagramConstants.ID_INPUTS.ACTION_TYPE_IDS].length; i++) {
      var actionTypeId = actionIdMap[FlowDiagramConstants.ID_INPUTS.ACTION_TYPE_IDS][i];
      // Since the key is based on type (definition) instead of instance, we can ignore duplicate types
      if (actionProperties[actionTypeId]) continue;

      var actionType = actionTypeDefinitionMap[actionTypeId];
      if (actionType)
          actionProperties.push(
              FlowDiagramActionApi.buildProperties(
                  actionType,
                  actionNodeType,
                  FlowDiagramConstants.ACTION_MAP_ID_TYPE.ACTION_TYPE
              )
          );
      else {
          actionProperties.push(FlowDiagramActionApi.createGhostAction(actionNodeType, actionTypeId));
          errors.push("Invalid action type ID: " + actionTypeId);
      }
  }
};

FlowDiagramActionApi.createSubflowActionProperties = function(actionIdMap, actionNodeType, actionProperties, errors) {
  var subflowDefinitionMap = FlowDiagramActionApi.componentMapFromGlideRecordQuery(
      FlowDiagramConstants.TABLE_NAMES.FLOW.BASE,
      actionIdMap[FlowDiagramConstants.ID_INPUTS.SUBFLOW_TYPE_IDS]
  );

  for (var i = 0; i < actionIdMap[FlowDiagramConstants.ID_INPUTS.SUBFLOW_TYPE_IDS].length; i++) {
      var subflowId = actionIdMap[FlowDiagramConstants.ID_INPUTS.SUBFLOW_TYPE_IDS][i];

      var subflow = subflowDefinitionMap[subflowId];
      if (subflow) {
          // Build this subflow's prop map
          actionProperties.push(
              FlowDiagramActionApi.buildProperties(
                  subflow,
                  actionNodeType,
                  FlowDiagramConstants.ACTION_MAP_ID_TYPE.ACTION_TYPE,
                  FlowDiagramConstants.INSTANCE_TYPES.SUBFLOW_INSTANCE_TYPE
              )
          );
      } else errors.push("Invalid subflow ID: " + subflowId);
  }
};

FlowDiagramActionApi.createFlowLogicActionProperties = function(actionIdMap, actionProperties, errors) {
  var flowLogicDefinitionMap = FlowDiagramActionApi.componentMapFromGlideRecordQuery(
      FlowDiagramConstants.TABLE_NAMES.FLOWLOGICS.FLOW_LOGIC_DEFINITION,
      actionIdMap[FlowDiagramConstants.ID_INPUTS.FLOWLOGIC_TYPE_IDS]
  );
  for (var i = 0; i < actionIdMap[FlowDiagramConstants.ID_INPUTS.FLOWLOGIC_TYPE_IDS].length; i++) {
      var flowlogicTypeId = actionIdMap[FlowDiagramConstants.ID_INPUTS.FLOWLOGIC_TYPE_IDS][i];

      // Since the key is based on type (definition) instead of instance, we can ignore duplicate types
      if (actionProperties[flowlogicTypeId]) continue;

      var flowlogicType = flowLogicDefinitionMap[flowlogicTypeId];
      if (flowlogicType) {
          var flowlogicTypeField = flowlogicType.getValue("type");

          // different flow logics have different node types, e.g ifs have 2 connector ports, foreach has looping connectors, etc
          var mappedFlowlogicNodeTypeSysId = FlowDiagramActionApi.mapFlowlogicNodeType(flowlogicTypeField);

          // This says "getActionNodeTypeBySysId" but both action and flowlogic node types are off the same table, sn_diagram_builder_node_type
          var flowlogicNodeType = FlowDiagramActionApi.getActionNodeTypeBySysId(mappedFlowlogicNodeTypeSysId);
          actionProperties.push(
              FlowDiagramActionApi.buildProperties(
                  flowlogicType,
                  flowlogicNodeType,
                  FlowDiagramConstants.ACTION_MAP_ID_TYPE.ACTION_TYPE,
                  FlowDiagramConstants.INSTANCE_TYPES.FLOW_LOGIC_INSTANCE_TYPE
              )
          );
      } else errors.push("Invalid flowlogic type ID: " + flowlogicTypeId);
  }
};

FlowDiagramActionApi.createDiagramActionActionProperties = function(actionIdMap, actionProperties, errors) {
  var diagramActionIds = actionIdMap[FlowDiagramConstants.ID_INPUTS.DIAGRAM_ACTION_TYPE_IDS];

  var diagramActions = FlowDiagramActionApi.getDiagramActionBySysIds(diagramActionIds.join(","));

  for (var i in diagramActions) {
      var diagramAction = diagramActions[i];
      var diagramActionId = diagramAction.getValue("sys_id");

      if (actionProperties[diagramActionId]) continue;

      var diagramActionNodeType = FlowDiagramActionApi.getActionNodeTypeBySysId(diagramAction.getValue("node_type"));
      if (diagramActionNodeType.isValidRecord())
          actionProperties.push(
              FlowDiagramActionApi.buildProperties(
                  diagramAction,
                  diagramActionNodeType,
                  FlowDiagramConstants.ACTION_MAP_ID_TYPE.DIAGRAM_ACTION_TYPE
              )
          );
      else errors.push("Invalid diagramActionId: " + diagramActionId);
  }
};

FlowDiagramActionApi.getActionProperties = function(actionIdMap, errors) {
  if (typeof actionIdMap === "string") actionIdMap = JSON.parse(actionIdMap);

  var actionProperties = [];

  // Refactor: is now object (previously was gliderecord)
  var actionNodeType = FlowDiagramActionApi.getActionNodeType();

  // Flow Actions
  if (actionIdMap.hasOwnProperty(FlowDiagramConstants.ID_INPUTS.ACTION_TYPE_IDS))
      FlowDiagramActionApi.createActionActionProperties(actionIdMap, actionNodeType, actionProperties, errors);

  // Subflows
  if (actionIdMap.hasOwnProperty(FlowDiagramConstants.ID_INPUTS.SUBFLOW_TYPE_IDS))
      FlowDiagramActionApi.createSubflowActionProperties(actionIdMap, actionNodeType, actionProperties, errors);

  // Flow Logics
  if (actionIdMap.hasOwnProperty(FlowDiagramConstants.ID_INPUTS.FLOWLOGIC_TYPE_IDS))
      FlowDiagramActionApi.createFlowLogicActionProperties(actionIdMap, actionProperties, errors);

  // Diagram Actions
  if (actionIdMap.hasOwnProperty(FlowDiagramConstants.ID_INPUTS.DIAGRAM_ACTION_TYPE_IDS))
      FlowDiagramActionApi.createDiagramActionActionProperties(actionIdMap, actionProperties, errors);

  return actionProperties;
};

FlowDiagramActionApi.getActionPropertyMap = function(actionIdMap, errors) {
  return FlowDiagramActionApi.getActionProperties(actionIdMap, errors);
};

Sys ID

03eca9f777013010b2b4ddd9cf5a99c6

Offical Documentation

Official Docs: