Name

sn_uibtk_api.ClientScript

Description

No description available

Script

const ClientScript = Class.create();
ClientScript.prototype = Object.extendsObject(BuilderToolkitAPIBase, {
  TABLE: 'sys_ux_client_script',
  FIELDS: ['script_api_version', 'required_translations', 'type', 'script', 'target', 'macroponent', 'name', 'includes'],

  /**
   * @param fields {string[]}
   */
  initialize: function(fields) {
      BuilderToolkitAPIBase.prototype.initialize.call(this, this.TABLE, fields || this.FIELDS);
  },

  /**
   * @param record the Client Script record we are working on
   */
  getRequiredTranslations: function(record) {
      const matchingStr = record?.type === 'transform' ? "helpers\.translateSync" : "helpers\.translate";

      const translations = [];
      const regex = `${matchingStr}\\(\\s*(?:(?:\\"([^\\"\\n]+)\\")|(?:\\'([^\\'\\n]+)\\'))`;
      const matches = record.script.match(regex);
      if (matches) {
          matches.filter((match) => match && match.indexOf(matchingStr.replace('\\')) === -1)
              .forEach((match) => {
                  translations.push({
                      code: null,
                      message: match,
                      comment: null
                  });
              });
      }
      return translations;
  },

  /**
   * @param clientScripts {clientScript[]} array of client scripts to work on
   * @param macroponentSysId {string} sys_id of the macroponent these scripts are tied to
   */
  upsertAndDeleteRecords: function(clientScripts = [], macroponentSysId = null) {
      // If we have no macroponentSysId, we might accidentally delete client scripts so ABORT
      if (!macroponentSysId) {
          return;
      }
      const clientScriptSysIds = clientScripts.map((cs) => cs.sysId) ?? [];
      const results = [];
      const clientScriptGR = this.getRecordsByQuery(`sys_idIN${Object.keys(clientScriptSysIds)}^ORmacroponent=${macroponentSysId}`, '', true);
      // Make sure we actually found something, then work on those
      if (clientScriptGR) {
          while (clientScriptGR.next()) {
              // If we aren't in the object, we are deleted
              if (!clientScriptSysIds.includes(clientScriptGR.getUniqueValue())) {
                  clientScriptGR.deleteRecord();
              }
              // Else we need to check for an update and remove from our list of IDs so we know what to create
              else {
                  const currentIdArr = clientScriptSysIds.splice(clientScriptSysIds.indexOf(clientScriptGR.getUniqueValue()), 1);

                  const currentScript = clientScripts.filter(({
                      sysId
                  }) => sysId === currentIdArr[0])[0];
                  const currentFieldValues = clientScriptGR.getElements().reduce(this.getFieldValues.bind(this), {});

                  // Get our required translations from the script and set them before we compare to be safe
                  currentScript.requiredTranslations = this.getRequiredTranslations(currentScript);

                  // Let's compare our field values to make sure we don't update needlessly
                  // If we don't match values, update the record and return the result
                  for (const field in currentScript) {
                      if (clientScriptGR.isValidField(field) && currentFieldValues[field] !== currentScript[field]) {
                          const {
                              sysId,
                              ...fields
                          } = currentScript;
                          this.setFieldValues(clientScriptGR, fields);
                          results.push(clientScriptGR.update());
                          break;
                      }
                  }
              }
          }
      }

      // Now if we have any clientScriptIds left, we need to insert
      const remainingRecords = clientScriptSysIds.length > 0 ? clientScripts.filter(({
          sysId
      }) => clientScriptSysIds.includes(sysId)) : null;
      if (remainingRecords !== null) {
          remainingRecords.forEach(({
              sysId,
              ...fields
          }) => {
              results.push(this.createRecord({
                  sysId,
                  ...fields,
                  requiredTranslations: this.getRequiredTranslations(fields)
              }));
          });
      }
      return results;
  },

  /**
   * @param records {object[]} array of records with camelCased keys
   */
  updateRecords: function(records) {
      return records.length === 0 ? true : records.map(function(record) {
          return this.updateRecord(record);
      }.bind(this));
  },

  /**
   * @param fields {object} a object with keys in camel case and values
   */
  updateRecord: function({
      sysId,
      ...fields
  }) {
      let recordGR = this.getRecordById(sysId, true);
      if (!recordGR) {
          return this.createRecord({
              sysId,
              ...fields
          });
      } else if (recordGR && recordGR.canWrite() && recordGR.getValue('target') !== 'preset') {
          this.setFieldValues(recordGR, fields);
          return recordGR.update();
      }
      return {
          error: true,
          reason: !recordGR ? BuilderToolkitConstants.ERRORS.NO_RECORD_FOUND : BuilderToolkitConstants.ERRORS.WRITE_ACCESS_ERROR_MESSAGE
      };
  },

  type: 'ClientScript'
});

Sys ID

9e03c49a7403111003e47792fd0af75c

Offical Documentation

Official Docs: