const exportToCsv = (data, csvFileName) => {
        const link = document.createElement("a");

        if (undefined !== link.download) { // downloads supported?
            const csvRows = [],
                // get the key names for the CSV header (column names)
                headers = Object.keys(data[0]),

                escCsvValue = value => "string" === typeof value && (-1 !== value.indexOf('"') || -1 !== value.indexOf(",")) // escape values that contain quotes or commas
                                            ? '"' + value.replace(/"/g, '""') + '"' // Dobule quotes are double escaped
                                            : value,

                convertCharset = s => "string" === typeof s
                                            ? s.replace(/[—–]/g, "-") // convert long dash/tiret to the unicode
                                                .replace(/[“”„‟«»]/, '"') // quotes
                                                .replaceAll("’", "'") // apostrophes
                                                .replaceAll("×", "x") // ×
                                                .replaceAll("(", "(") // TODO: make it smarter, put into array. And there are a lot more characters that really worth to convert instead of this Chinese bracket.
                                                .replaceAll(")", ")")
                                            : s;

            // add the column names as header
            csvRows.push(headers.map(escCsvValue).join(","));
            // convert each JSON object into CSV row
            data.forEach(item => csvRows.push(headers.map(header => escCsvValue(convertCharset(item[header]))).join(",")));

            link.setAttribute("href", URL.createObjectURL(new Blob([csvRows.join("\n")], { type: "text/csv;charset=utf-8;" }))); // utf-8
            link.setAttribute("download", csvFileName);
            link.style.visibility = "hidden";

            document.body.appendChild(link);
            link.click(); // simulate native click
            document.body.removeChild(link);
        }
    };