controllers_generate.js

import Swal from 'sweetalert2';
import Generate from '../views/generate/generate.html?raw';
import '../views/generate/generate.css';
import getCsvLists from '../utils/getCsvPropsAndItems.js';

/**
 * @function utilGenerate
 * @description Annonymous function to controll and make the logic for the Generate view
 * @returns {HTMLElement} - HTML template of Generate view
 */
export default () => {
  const divWrapper = document.createElement('div');
  divWrapper.innerHTML = Generate;

  // logic of this view
  /**
  *
  * @type {Generator}
  */
  const generator = new Generator(divWrapper);
  generator.init();
  return divWrapper;
};

/**
 * Represents the logic of the genarate controller view
 * @class
 * @constructor
 * @param {HTMLElement} htmlContent - The HTML template of the generator view
 * @example
 * const generator = new Generator(htmlTemplate);
 */
function Generator(htmlContent) {
  /** @this Generator */

  /** @member {HTMLElement} */
  this.htmlContent = htmlContent;
  /** @member {HTMLElement} */
  this.btnConverter = htmlContent.querySelector('.generate__button');
  /** @member {HTMLElement} */
  this.outputOption = htmlContent.querySelector('.generate__options-input');
  /** @member {HTMLElement} */
  this.outputPlace = htmlContent.querySelector('.output');
  /** @member {Array<HTMLElement>} */
  [this.jsonTextArea, this.csvTextArea] = htmlContent.querySelectorAll('.generate__textarea');
}

Generator.prototype = /** @lends Generator.prototype */ {
  constructor: Generator,


  /**
   * Init the Generator and add some lsiteners
   * @return {void}
   */
  init(){
    /**
    * Event to generate the translation of the JSON file into CSV file
    * @event convertBtn-click
    */
    this.btnConverter.addEventListener('click', this.convertJsonToCsv.bind(this));
    /**
    * Event to copy the result of the csv file into the clipboard
    * @event resultArea-click
    */
    this.csvTextArea.addEventListener('click', this.copyIntoClipboard.bind(this));
  },


  /**
   * Convert the JSON text into an array of properties and items
   * @method
   * @fires convertBtn-click
   * @return {void}
   */
  convertJsonToCsv(){
    const jsonText = this.jsonTextArea.value;
    // convert string into Json
    try {
      const json = JSON.parse(jsonText);
      const jsonList = json.length ? json : [json];
      const [properties, items] = getCsvLists(jsonList);
      this.renderOutput(properties, items);
      this.outputOption.addEventListener('click', this.renderOutput.bind(this,properties, items));
    } catch(err) {
      Swal.fire({
        title: 'Error to convert',
        text: 'Verify your json text',
        confirmButtonText: 'Ok',
        icon: 'error',
        backdrop: true,
        width: '50%',
        padding: '1rem',
        position: 'center',
        allowOutsideClick: true,
        allowEscapeKey: true,
        confirmButtonAriaLabel: 'Confirmar'

      });
    }
  },


  /**
   * Render the information input in the arrays into a csv format, it coould be in a table way or  just the csv text format
   * @param {Array<String>} properties List of properties of the json file
   * @param {Array<String[]>} items  List of the values of each item according to the properties list
   * @returns {void}
   */
  renderOutput(properties, items){
    this.outputPlace.innerHTML = '';
    if(this.outputOption.checked) {
      const table = this.renderTable(properties, items);
      this.outputPlace.appendChild(table);
      return;
    }

    this.csvTextArea.textContent = properties.join(',') + '\r\n';
    this.csvTextArea.textContent += items.join('\r\n');
    this.outputPlace.appendChild(this.csvTextArea);
  },

  /**
  * Copy into the clipboard the csv text result
  *
  * @method
  * @fires resultArea-click
  * @return {void}
  */
  copyIntoClipboard(){
    const textToCopy = this.csvTextArea.textContent;
    if(!textToCopy) {
      Swal.fire({
        title: 'Nothing to copy',
        text: 'Verify your json text',
        icon: 'warning',
        timer: 2000,
        toast: true,
        position: 'top-right',

        showConfirmButton: false,

      });
      return;
    }
    navigator.clipboard.writeText(textToCopy)
      .then(() => {
        // librarie to say alerts or say errors
        Swal.fire({
          title: 'Your Csv text has been copied',
          icon: 'success',
          timer: 3000,
          toast: true,
          position: 'top-right',

          showConfirmButton: false,

        });
      })
      .catch((err) => console.log(err));
  },

  /**
   * Render the rows of the table of the csv information
   * @param {Array<String[]>} data The data of each row
   * @returns {String} Each row in a HTML div but all in one and single string
  */
  renderRows(data){
    const rows = [];
    for(let j = 0; j < data.length; j +=1){
      rows.push(`
        <div class="table__row">
          ${this.renderCells(data[j])}
        </div>
      `);
    }
    return rows.join('');
  },

  /**
   * Render the cells of the table of the csv information
   * @param {Array<String>} data The data of each cell
   * @returns {String} Each cell in a HTML div but all in one and single string
  */
  renderCells(data) {
    const cells = [];
    for(let i = 0; i < data.length; i+=1){
      cells.push(`
        <span class="table__cell">
          ${data[i]}
        </span>
      `);
    }
    return cells.join('');
  },

  /**
   * Render the table of the csv information
   * @param {Array<String>} headerData The array of teh properties
   * @param {Array<String[]>} contentData The array of array of the items
   * @returns {HTMLElement} The table representation of the csv data
  */
  renderTable(headerData, contentData){
    const table = document.createElement('div');
    table.classList.add('generator__table');
    table.innerHTML = `
      <div class="table__header">
        ${this.renderCells(headerData)}
      </div>

      <div class="table__content">
        ${this.renderRows(contentData)}
      </div>
    `;
    return table;
  }
};


// prubes


/*
  => level 1
 [
  {
    "id": 1,
    "name": "Leanne Graham",
    "username": "Bret",
    "email": "Sincere@april.biz"
  },
  {
    "id": 2,
    "name": "Ervin Howell",
    "username": "Antonette",
    "email": "Shanna@melissa.tv"
  }
]

   =>level2
[
  {
    "id": 1,
    "name": "Leanne Graham",
    "username": "Bret",
    "email": "Sincere@april.biz",
    "address": {
      "street": "Kulas Light",
      "suite": "Apt. 556",
      "city": "Gwenborough",
      "zipcode": "92998-3874",
      "geo": {
        "lat": "-37.3159",
        "lng": "81.1496"
      }
    }
  },
  {
    "id": 2,
    "name": "Ervin Howell",
    "username": "Antonette",
    "email": "Shanna@melissa.tv",
    "address": {
      "street": "Victor Plains",
      "suite": "Suite 879",
      "city": "Wisokyburgh",
      "zipcode": "90566-7771",
      "geo": {
        "lat": "-43.9509",
        "lng": "-34.4618"
      }
    }
  }
]

*/