Search code examples
google-apps-scriptmodal-dialog

How to process string returned by modal dialog into an object


I need to process JSON files that are over 50,000 characters long. To do this, I want to use a modal dialog text area.

I have a dialog with two text areas. The first is for the original json file to be pasted into, and the second is where the processed file is to be outputted.

This all works in a testing mode where I pass a string to be processed with

function processText (input){
  let processedText = input.toUpperCase(); 
  //Browser.msgBox(processedText)
  return processedText; 
}

and I add ddddd in the first text area of the modal and click the process button in the modal I get DDDDD outputted to the second text area

but if I use my proper processText(input) below to process my JSON, I cannot get the passed value of the first text area to be an object so I can process it with processText(input)

How do I process the value of the first text area that is returned to processText(input) to be an object so I can process it

A Google sheet with everything in it https://docs.google.com/spreadsheets/d/1VwMhr_imlmGrjcybVdfuJP7KFWBmgjWcIhL0n5bYLxY/edit?usp=sharing

Thanks

my gs file is

function showInputDialog() {
  var html = HtmlService.createTemplateFromFile('inputDialog').evaluate()
      .setTitle('Enter Long String')
      .setHeight(800)
      .setWidth(900);
  SpreadsheetApp.getUi().showModalDialog(html, 'Input');
}

function processText(input) {
  Browser.msgBox(typeof input)
  let inputJSON = JSON.parse(input);
  Browser.msgBox(typeof inputJSON)
  
   //Filter
  let processedText = inputJSON.filter(item => item.id && item.label && item.options)
                  .map(({ id, label, options }) => 
                         isEmptyObject(options) === false ? ({ id, label, options}):({ id, label}));

 processedText.forEach(i => Object.values(i.options ?? {}).forEach(i => delete i.count));                    

 Browser.msgBox(processedText)
 
 return JSON.stringify(processedText);
}

my HTML file is

<button id="copyTOP" style="margin-bottom: 25px;" onclick="copy()">Copy Redurced sumApp JSON</button><input style="width:31%;height:30px;" type="button" value="Close" onClick="google.script.host.close();" />
<!DOCTYPE html>
<html>
  <head>
    <base target="_top" />
        <link
            rel="stylesheet"
            //href="https://ssl.gstatic.com/docs/script/css/add-ons1.css"
      href="https://res.cloudinary.com/greater-then-the-sum/raw/upload/v1699896536/add-ons1a_ruvbar.css"
        />
        <style>
            .container {
                margin: 5px 5px 5px 5px;
            }
        </style>
  </head>
  <body>
    <H4>Raw sumApp JSON Input</H4>
    <textarea id="copyOrig" class="form-control"></textarea>
    <br>
    <H4>Output</H4>
    <textarea id="copyReduced" class="form-control"></textarea>
    <br><br><br>
    <button id="propersize" onclick="processAndDisplay()">Process</button>

  </body>
</html>
<br>
<br>
<button id="copyBottom" style="margin-bottom: 25px;" onclick="copy()">Copy Reduced sumApp JSON</button><input style="width:31%;height:30px;" type="button" value="Close" onClick="google.script.host.close();" />

<script>
  function processAndDisplay() {
    var inputText = document.getElementById('copyOrig').value;
    google.script.run.withSuccessHandler(successHandler).processText(JSON.stringify(inputText)); 
  }

  function successHandler(processedText) {
    document.getElementById('copyReduced').value = processedText; 
  } 
</script>


<script type="text/javascript">
 function copy() {
  let textarea = document.getElementById("copyReduced");
  textarea.select();
  document.execCommand("copy");
 }

 function copyBOTTOM() {
  let textarea = document.getElementById("copyNEW");
  textarea.select();
  document.execCommand("copy");
 } 
 </script>

JSON file

[
    {
    "id": "c3c6f410f58e5836431b473ebcf134756232d04f2bf35edff8",
    "component": "checkbox",
    "customFields": [

    ],
    "index": 0,
    "label": "Sector2",
    "options": {
      "62f92fab79ac81d933765bd0bbc4a1f5ea26cb3a088bcb4e6e": {
        "index": 0,
        "value": "Bob",
        "label": "Bob",
        "count": 1
      },
      "2fe91aa3567c0d04c521dcd2fc7e40d7622bb8c3f594d503da": {
        "index": 1,
        "value": "Student",
        "label": "Student",
        "count": 1
      },
      "c59ea1159f33b91a7f6edc6925be5e373fc543e4": {
        "index": 2,
        "value": "BBB",
        "label": "BBB",
        "count": 1
      },
      "c59ea1159f33b91a7f6edc6925be5e373fc54AAA": {
        "index": 3,
        "value": "Orange Duck",
        "label": "Orange Duck",
        "count": 1
      }
    },
    "required": false,
    "validation": "/.*/",
    "imported": false
  },
  {
    "id": "f794c6a52e793ee6f5c42cd5df6b4435236e3495e951709485",
    "component": "textInput",
    "customFields": [

    ],
    "index": 1,
    "label": "Brown Cow",
    "options": {
    },
    "required": false,
    "validation": "/.*/",
    "imported": false
  },
  {
    "id": "f794c6a52e793ee6f5c42cd5df6b4435236e3495e95170ZZZ",
    "component": "textInput",
    "customFields": [

    ],
    "index": 1,
    "label": "Red Fish",
    "options": {
    },
    "required": false,
    "validation": "/.*/",
    "imported": false
  }
 ];

Solution

  • I will take a guess based on doubleunarys comment that you processed the json you posted, and this is causing the issue.

    So, if this is true, use your raw JSON

    As I was able to get this working using a validated JSON by replacing your processText function with

    function processText(input) {
      try {
        let inputObj = JSON.parse(input);
    
        let processedText = inputObj.filter(item => item.id && item.label && item.options)
          .map(({ id, label, options }) => {
            if (!isEmptyObject(options)) {
              return { id, label, options };
            } else {
              return { id, label };
            }
          });
    
        processedText.forEach(item => {
          if (item.options) {
            Object.values(item.options).forEach(option => delete option.count);
          }
        });
    
        // Convert each object in processedText to a JSON string
        let processedStrings = processedText.map(obj => JSON.stringify(obj,null,2));
    
        return processedStrings;
      } catch (error) {
        console.error('Error processing input:', error);
        throw new Error('Error processing input: ' + error.message);
      }
    }
    

    and in your HTML replace

    document.getElementById('copyReduced').value = "processedText;

    with

    document.getElementById('copyReduced').value = "["+processedText+"]";