import 'babel-polyfill';
import * as XLSX from 'xlsx';
import parser from 'xml2json-light';
import _ from 'lodash';
import Utility from './utility';
/**
* 차트 데이터 직접입력 이외의 방식을 모두 담당하는 클래스
* @alias Input
*/
export default class Input {
/**
* @description spreadsheet 로 부터 데이터를 가져옴
* <p>static 함수
* @param { object } option spreadsheet 로 부터 데이터를 가져올 때 적용시킬 옵션
* @memberof Input
* @instance
*/
static async getDataFromSpreadSheet(option) {
const defaultOption = {
sheet: 1,
datasetDirection: 'horizontal',
datasets: [],
};
option = { ...defaultOption, ...option };
option.sheet -= 1;
if (option.file === undefined) {
Utility.error('No filename in spreadsheet');
return;
}
// eslint-disable-next-line consistent-return
return new Promise(((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.responseType = 'arraybuffer';
xhr.onload = () => {
if (xhr.status >= 200 && xhr.status < 300) {
const arraybuffer = xhr.response;
const preData = new Uint8Array(arraybuffer);
const arr = [];
for (let i = 0; i !== preData.length; ++i) { arr[i] = String.fromCharCode(preData[i]); }
const bstr = arr.join(''); // bstr [의미불명확]
const workbook = XLSX.read(bstr, {
type: 'binary',
});
const sheetName = workbook.SheetNames[option.sheet];
const workSheet = workbook.Sheets[sheetName];
const data = XLSX.utils.sheet_to_json(workSheet, {
raw: true,
});
const chartData = {
labels: [],
datasets: [],
};
const firstLineData = Object.keys(data[0]);
const datasetsIndex = [];
if (option.datasetDirection === 'vertical') {
for (let i = 1; i < firstLineData.length; i++) {
const isIncludeExclude = _.some(option.excludeLabel, (el) => {
if (_.includes(firstLineData[i], el)) {
return el;
}
return null;
});
if (!isIncludeExclude) {
chartData.labels.push(firstLineData[i]);
}
}
if (option.datasets.length === 0) {
for (let i = 0; i < data.length; i++) {
datasetsIndex.push(i);
}
} else {
for (let i = 0; i < data.length; i++) {
const datasetLabel = data[i][firstLineData[0]];
if (option.datasets.indexOf(datasetLabel) !== -1) { datasetsIndex.push(i); }
}
}
// make each datasets
for (let i = 0; i < datasetsIndex.length; i++) {
const dataset = {
label: data[datasetsIndex[i]][firstLineData[0]],
};
dataset.data = [];
for (let j = 1; j < firstLineData.length; j++) {
const isIncludeExclude = _.some(option.excludeLabel, (el) => {
if (_.includes(firstLineData[j], el)) {
return el;
}
return null;
});
if (!isIncludeExclude) {
dataset.data.push(data[datasetsIndex[i]][firstLineData[j]]);
}
}
chartData.datasets.push(dataset);
}
} else {
const labelKey = firstLineData[0];
for (let i = 0; i < data.length; i++) {
const isIncludeExclude = _.some(option.excludeLabel, (el) => {
if (_.includes(data[i][labelKey], el)) {
return el;
}
return null;
});
if (!isIncludeExclude) {
chartData.labels.push(data[i][labelKey]);
}
}
if (option.datasets.length === 0) {
for (let i = 1; i < firstLineData.length; i++) {
datasetsIndex.push(i);
}
} else {
for (let i = 0; i < option.datasets.length; i++) {
const datasetLabel = option.datasets[i];
const arrayIndex = firstLineData.indexOf(datasetLabel);
if (arrayIndex !== -1) { datasetsIndex.push(arrayIndex); }
}
}
// make each datasets
for (let i = 0; i < datasetsIndex.length; i++) {
const dataset = {
label: firstLineData[datasetsIndex[i]],
};
dataset.data = [];
for (let j = 0; j < data.length; j++) {
const isIncludeExclude = _.some(option.excludeLabel, (el) => {
if (_.includes(data[j][dataset.label], el)) {
return el;
}
return null;
});
if (!isIncludeExclude) {
dataset.data.push(data[j][dataset.label]);
}
}
chartData.datasets.push(dataset);
}
}
resolve(chartData);
}
};
xhr.onerror = () => {
reject(new Error(xhr.statusText));
};
xhr.open('GET', option.file, true);
xhr.send();
}));
}
/**
* @description API 로 부터 데이터를 가져옴
* <p>static 함수
* @param { string } url API URL
* @param { object } params API Parameters
* @instance
* @memberof Input
*/
static async getDataFromAPI(url, params) {
if (url === undefined) {
Utility.error('API Url is not defined');
return;
}
let finalUrl = url;
if (params !== undefined && Object.keys(params).length !== 0) {
finalUrl += '?';
Object.keys(params).forEach((key) => {
finalUrl += `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`;
});
}
// eslint-disable-next-line consistent-return
return new Promise(((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.onload = () => {
if (xhr.status >= 200 && xhr.status < 300) {
let object;
if (xhr.response[0] === '<') {
object = parser.xml2json(xhr.response);
} else {
object = JSON.parse(xhr.response);
}
resolve(object);
} else {
reject(new Error(xhr.statusText));
}
};
xhr.onerror = () => {
reject(new Error(xhr.statusText));
};
xhr.open('GET', finalUrl);
xhr.send();
}));
}
}