/*
* Project Name : Visual Python
* Description : GUI-based Python code generator
* File Name : File.js
* Author : Black Logic
* Note : Apps > File
* License : GNU GPLv3 with Visual Python special exception
* Date : 2021. 11. 18
* Change Date :
*/
//============================================================================
// [CLASS] File
//============================================================================
define([
__VP_TEXT_LOADER__('vp_base/html/m_apps/file.html'), // INTEGRATION: unified version of text loader
__VP_CSS_LOADER__('vp_base/css/m_apps/file'), // INTEGRATION: unified version of css loader
'vp_base/js/com/com_String',
'vp_base/js/com/com_util',
'vp_base/js/com/com_Const',
'vp_base/js/com/component/PopupComponent',
'vp_base/js/com/com_generatorV2',
'vp_base/data/m_library/pandasLibrary',
'vp_base/js/com/component/FileNavigation',
'vp_base/js/com/component/SuggestInput'
], function(fileHtml, fileCss, com_String, com_util, com_Const, PopupComponent
, pdGen, pandasLibrary, FileNavigation, SuggestInput) {
/**
* File
*/
class File extends PopupComponent {
_init() {
super._init();
/** Write codes executed before rendering */
this.config.dataview = false;
this.config.sizeLevel = 2;
this.config.checkModules = ['pd'];
this.fileExtensions = {
'csv': ['csv', 'tsv', 'txt'],
'excel': ['xlsx', 'xls'],
'json': ['json'],
'pickle': [],
'sas': [], // xport or sas7bdat
'spss': [],
'parquet': ['parquet']
}
this.package = {
input: [
{ name: 'vp_fileioType' },
{ name: 'vp_pageDom'}
]
}
// INTEGRATED: integrate data source from raw.github
// if (vpConfig.extensionType === 'notebook') {
// this.dataPath = window.location.origin + com_Const.DATA_PATH + "sample_csv/";
// } else if (vpConfig.extensionType === 'colab' || vpConfig.extensionType === 'lab') {
// // this.dataPath = com_Const.DATA_PATH + "sample_csv/";
// this.dataPath = 'https://raw.githubusercontent.com/visualpython/visualpython/main/data/sample_csv/';
// }
if (vpConfig.extensionType === 'lite') {
this.dataPath = '/drive/data/';
} else {
this.dataPath = 'https://raw.githubusercontent.com/visualpython/visualpython/main/visualpython/data/sample_csv/';
}
this.state = {
fileType: 'csv',
fileExtension: ['csv'],
selectedFile: '',
selectedPath: '',
vp_fileioType: 'Read',
vp_pageDom: '',
userOption: '',
...this.state
}
this.fileResultState = {
pathInputId : this.wrapSelector('#vp_fileRead #i0'),
fileInputId : this.wrapSelector('#vp_fileRead #fileName')
};
this.fileState = {
'Read': {
fileTypeId: {
'csv': 'pd_readCsv',
'excel': 'pd_readExcel',
'json': 'pd_readJson',
'pickle': 'pd_readPickle',
'sas': 'pd_readSas',
'spss': 'pd_readSpss',
'parquet':'pd_readParquet'
},
selectedType: 'csv',
package: null,
fileResultState: {
pathInputId : this.wrapSelector('#vp_fileRead #i0'),
fileInputId : this.wrapSelector('#vp_fileRead #fileName')
}
},
'Write': {
fileTypeId: {
'csv': 'pd_toCsv',
'excel': 'pd_toExcel',
'json': 'pd_toJson',
'pickle': 'pd_toPickle',
'parquet':'pd_toParquet'
},
selectedType: 'csv',
package: null,
fileResultState: {
pathInputId : this.wrapSelector('#vp_fileWrite #i1'),
fileInputId : this.wrapSelector('#vp_fileWrite #fileName')
}
},
// 'Sample': {
// library: 'pandas',
// code: "${vp_sampleReturn} = pd.read_csv('" + this.dataPath + "${vp_sampleFile}'${v})",
// input: [
// {
// name:'vp_sampleFile',
// label: 'Sample Data',
// component: 'option_select',
// options: [
// 'iris.csv', 'titanic.csv', 'fish.csv', 'campusRecruitment.csv',
// 'houseData_500.csv', 'economic_index.csv', 'tips.csv'
// ],
// options_label: [
// 'iris', 'titanic', 'fish', 'campusRecruitment',
// 'houseData_500', 'economic index', 'tips'
// ]
// }
// ],
// output: [
// {
// name:'vp_sampleReturn',
// type:'var',
// label:'Allocate to',
// required: true
// }
// ]
// }
"Sample": {
"library": "pandas",
"code": "${vp_sampleReturn} = pd.read_csv('" + this.dataPath + "${vp_sampleFile}')",
"options": [
{
"name": "vp_sampleFile",
"label": "Sample Data",
"required": true,
"component": [
"option_select"
],
"options": [
"iris.csv",
"titanic.csv",
"fish.csv",
"campusRecruitment.csv",
"houseData_500.csv",
"economic_index.csv",
"tips.csv"
],
"options_label": [
"iris",
"titanic",
"fish",
"campusRecruitment",
"houseData_500",
"economic index",
"tips"
]
},
{
"name": "vp_sampleReturn",
"label": "Allocate to",
"component": [
"data_select"
],
"output": true,
"required": true,
"value": 'vp_df'
}
]
}
}
}
_unbindEvent() {
super._unbindEvent();
$(document).off('change', this.wrapSelector('#fileReadAs'));
}
_bindEvent() {
super._bindEvent();
/** Implement binding events */
var that = this;
$(this.wrapSelector('#vp_fileioType')).on('change', function() {
var pageType = $(this).val();
that.state['vp_fileioType'] = pageType;
$(that.wrapSelector('.vp-fileio-box')).hide();
$(that.wrapSelector('#vp_file' + pageType)).show();
if (pageType === 'Read' && that.fileState[pageType].selectedType === 'spss') {
// show install button
that.showInstallButton();
// show install note below File type selection
$(`
|
|
`).insertAfter($(that.wrapSelector('#fileType')).closest('tr'));
} else {
that.hideInstallButton();
$(that.wrapSelector('.vp-spss-note')).remove();
}
//set fileExtensions
that.fileResultState = {
...that.fileState[pageType].fileResultState
};
});
// fileReadAs change Event, Use PyArrow
$(document).on('change', this.wrapSelector('#fileReadAs'), function() {
let isChecked = $(this).prop('checked');
var fileioType = that.state.vp_fileioType;
var prefix = '#vp_file' + fileioType + ' ';
var selectedType = that.fileState[fileioType]['selectedType'];
var fileioTypePrefix = fileioType.toLowerCase();
if(fileioTypePrefix == 'write'){
fileioTypePrefix = "to";
}
let fileId = that.fileState[fileioType].fileTypeId[selectedType];
if (isChecked) { // pyArrow
fileId = "pa_" + fileioTypePrefix + selectedType[0].toUpperCase() + selectedType.slice(1);
// that.fileState[fileioType].fileTypeId[that.state.fileExtension] = "pa_" + fileioTypePrefix + selectedFileFormat[0].toUpperCase() + selectedFileFormat.slice(1);
$(that.wrapSelector(prefix + '#vp_optionBox')).closest('.vp-accordian-container').hide();
} else { // pandas
// that.fileState[fileioType].fileTypeId[that.state.fileExtension] = "pd_" + fileioTypePrefix + selectedFileFormat[0].toUpperCase() + selectedFileFormat.slice(1);
if (that.state.fileType != 'parquet'){ // parquet has no options area
$(that.wrapSelector(prefix + '#vp_optionBox')).closest('.vp-accordian-container').show();
}
}
let pdLib = pandasLibrary.PANDAS_FUNCTION;
let thisPkg = JSON.parse(JSON.stringify(pdLib[fileId]));
that.fileState[fileioType].package = thisPkg;
});
}
_bindEventByType(pageType) {
var that = this;
var prefix = '#vp_file' + pageType + ' ';
var fileioTypePrefix = pageType.toLowerCase();
if(fileioTypePrefix == 'write'){
fileioTypePrefix = "to";
}
// select file type
$(this.wrapSelector(prefix + '#fileType')).change(function() {
var fileType = $(this).val();
that.fileState[pageType].selectedType = fileType;
// reload
that.renderPage(pageType);
that._bindEventByType(pageType);
});
// open file navigation
$(this.wrapSelector(prefix + '#vp_openFileNavigationBtn')).click(function() {
let type = 'save';
if (pageType == 'Read') {
type = 'open';
}
let extensionList = [];
if (that.state.fileExtension && that.state.fileExtension.length > 0) {
extensionList = that.state.fileExtension;
}
let fileNavi = new FileNavigation({
type: type,
extensions: extensionList,
finish: function(filesPath, status, error) {
let {file, path} = filesPath[0];
that.state.selectedFile = file;
that.state.selectedPath = path;
// set text
$(that.fileResultState.fileInputId).val(file);
$(that.fileResultState.pathInputId).val(path);
}
});
fileNavi.open();
});
}
saveState() {
var pageType = $(this.wrapSelector('#vp_fileioType')).val();
// save input state
$(this.wrapSelector('#vp_file' + pageType + ' input')).each(function () {
this.defaultValue = this.value;
});
// save checkbox state
$(this.wrapSelector('#vp_file' + pageType + ' input[type="checkbox"]')).each(function () {
if (this.checked) {
this.setAttribute("checked", true);
} else {
this.removeAttribute("checked");
}
});
// save select state
$(this.wrapSelector('#vp_file' + pageType + ' select > option')).each(function () {
if (this.selected) {
this.setAttribute("selected", true);
} else {
this.removeAttribute("selected");
}
});
var pageDom = $(this.wrapSelector('#vp_file' + pageType)).html();
this.state['vp_pageDom'] = pageDom;
}
loadStateAfterRender() {
var pageType = this.state['vp_fileioType'];
var pageDom = this.state['vp_pageDom'];
// load pageDom
$(this.wrapSelector('#vp_file' + pageType)).html(pageDom);
// set page type
$(this.wrapSelector('#vp_fileioType')).val(pageType);
// show loaded page
$(this.wrapSelector('.vp-fileio-box')).hide();
$(this.wrapSelector('#vp_file' + pageType)).show();
//set fileResultState
this.fileResultState = {
...this.fileState[pageType].fileResultState
};
// bind event by page type
this._bindEventByType(pageType);
}
templateForBody() {
/** Implement generating template */
let page = $(fileHtml);
// Removed dataselector for Allocation input
// let allocateSelector = new DataSelector({
// pageThis: this, id: 'vp_sampleReturn', placeholder: 'Variable name', value: 'vp_df'
// });
// $(page).find('#vp_sampleReturn').replaceWith(allocateSelector.toTagString());
return page;
}
renderPage(pageType) {
var that = this;
var prefix = '#vp_file' + pageType + ' ';
// clear
$(this.wrapSelector(prefix + '#vp_inputOutputBox table tbody')).html('');
$(this.wrapSelector(prefix + '#vp_optionBox table tbody')).html('');
var fileTypeObj = this.fileState[pageType]['fileTypeId'];
var selectedType = this.fileState[pageType]['selectedType'];
let fileId = fileTypeObj[selectedType];
let pdLib = pandasLibrary.PANDAS_FUNCTION;
let thisPkg = JSON.parse(JSON.stringify(pdLib[fileId]));
this.fileState[pageType].package = thisPkg;
this.state.fileExtension = that.fileExtensions[selectedType];
this.fileResultState = {
...this.fileState[pageType].fileResultState
};
if (selectedType == 'pickle' || selectedType == 'parquet') {
// hide additional option box
$(this.wrapSelector(prefix + '#vp_optionBox')).closest('.vp-accordian-container').hide();
} else {
$(this.wrapSelector(prefix + '#vp_optionBox')).closest('.vp-accordian-container').show();
}
if (pageType == 'Write') {
if (selectedType == 'json') {
this.fileResultState.pathInputId = this.wrapSelector(prefix + '#path_or_buf');
}
if (selectedType == 'pickle' || selectedType == 'parquet') {
this.fileResultState.pathInputId = this.wrapSelector(prefix + '#path');
}
}
// render interface
// pdGen.vp_showInterfaceOnPage(this.wrapSelector('#vp_file' + pageType), thisPkg);
// pdGen.vp_showInterfaceOnPage(this.wrapSelector('#vp_file' + pageType), thisPkg);
pdGen.vp_showInterfaceOnPage(this, thisPkg, this.state, parent=('#vp_file' + pageType));
// pyarrow can r/w parquet, csv and only read json.
if ((pageType == 'Read' && selectedType == 'json') || selectedType == 'parquet'|| selectedType == 'csv') {
// add checkbox 'Use PyArrow', next to File Type
$(this.wrapSelector(prefix + '#vp_inputOutputBox table tbody')).prepend(
$('').append($(` | `))
.append($(' | '))
);
} else {
$(this.wrapSelector(prefix + '#vp_inputOutputBox table tbody')).prepend(
$('
').append($(` | `))
.append($(' | '))
);
}
// prepend file type selector
var fileTypeList = Object.keys(fileTypeObj);
fileTypeList.forEach(type => {
$(this.wrapSelector(prefix + '#fileType')).append(
$(``)
);
});
// prepend user option
let hasAllocateTo = $(this.wrapSelector(prefix + '#o0')).length > 0;
if (hasAllocateTo) {
$(this.wrapSelector(prefix + '#o0')).closest('tr').after(
$('
').append($(` | `))
.append($(' | '))
)
} else {
$(this.wrapSelector(prefix + '#vp_inputOutputBox table tbody')).append(
$('
').append($(` | `))
.append($(' | '))
)
}
$(this.wrapSelector(prefix + '#fileType')).val(selectedType);
// add file navigation button
if (pageType == 'Write') {
if (selectedType == 'json') {
$(prefix + '#path_or_buf').parent().html(
com_util.formatString(''
, 'vp-file-browser-button')
);
} else if (selectedType == 'pickle' || selectedType == 'parquet') {
$(prefix + '#path').parent().html(
com_util.formatString(''
, 'vp-file-browser-button')
);
} else {
$(this.fileState[pageType]['fileResultState']['pathInputId']).parent().html(
com_util.formatString(''
, 'i1'
, 'vp-file-browser-button')
);
}
} else {
$(this.fileState[pageType]['fileResultState']['pathInputId']).parent().html(
com_util.formatString(''
, 'i0'
, 'vp-file-browser-button')
);
}
if (pageType === 'Read' && selectedType === 'spss') {
// show install button
this.showInstallButton();
// show install note below File type selection
$(`
|
|
`).insertAfter($(this.wrapSelector('#fileType')).closest('tr'));
} else {
this.hideInstallButton();
}
// encoding suggest input
$(this.wrapSelector('#encoding')).replaceWith(function() {
// encoding list : utf8 cp949 ascii
var encodingList = ['utf8', 'cp949', 'ascii'];
var suggestInput = new SuggestInput();
suggestInput.setComponentID('encoding');
suggestInput.addClass('vp-input vp-state');
suggestInput.setSuggestList(function() { return encodingList; });
suggestInput.setPlaceholder('encoding option');
return suggestInput.toTagString();
});
// separator suggest input
$(this.wrapSelector('#sep')).replaceWith(function() {
// separator list :
var sepList = [',', '|', '\\t', '\\n', ':', ';', '-', '_', '&', '/', '\\'];
var suggestInput = new SuggestInput();
suggestInput.setComponentID('sep');
suggestInput.addClass('vp-input vp-state');
suggestInput.setSuggestList(function() { return sepList; });
suggestInput.setPlaceholder('Input separator');
return suggestInput.toTagString();
});
}
render() {
super.render();
this.renderPage('Read');
this.renderPage('Write');
// initialize fileResultState
this.fileResultState = {
...this.fileState['Read'].fileResultState
};
if (this.state.vp_pageDom && this.state.vp_pageDom != '') {
this.loadStateAfterRender();
}
this._bindEventByType('Read');
this._bindEventByType('Write');
}
generateInstallCode() {
return [ '!pip install pyreadstat' ];
}
generateCode() {
var pageType = $(this.wrapSelector('#vp_fileioType')).val();
var sbCode = new com_String;
this.saveState();
var prefix = '#vp_file' + pageType + ' ';
var userOption = new com_String();
var userOptValue = $(this.wrapSelector(prefix + '#userOption')).val();
if (userOptValue != '') {
userOption.appendFormat(', {0}', userOptValue);
}
if (pageType == 'Sample') {
// sample csv code
// var result = pdGen.vp_codeGenerator(this.uuid + ' #vp_fileSample', { ...this.fileState[pageType] }, userOption.toString());
var result = pdGen.vp_codeGenerator(this, { ...this.fileState[pageType] }, this.state, userOption.toString(), parent='#vp_fileSample');
sbCode.append(result);
} else if (pageType == 'Read') {
var thisPkg = JSON.parse(JSON.stringify(this.fileState[pageType].package));
thisPkg.options.push({
name: 'fileType',
type: 'var'
});
// var result = pdGen.vp_codeGenerator(this.uuid + ' #vp_fileRead', thisPkg, userOption.toString());
var result = pdGen.vp_codeGenerator(this, thisPkg, this.state, userOption.toString(), parent='#vp_fileRead');
sbCode.append(result);
} else if (pageType == 'Write') {
var thisPkg = JSON.parse(JSON.stringify(this.fileState[pageType].package));
thisPkg.options.push({
name: 'fileType',
type: 'var'
});
// var result = pdGen.vp_codeGenerator(this.uuid + ' #vp_fileWrite', thisPkg, userOption.toString());
var result = pdGen.vp_codeGenerator(this, thisPkg, this.state, userOption.toString(), parent='#vp_fileWrite');
sbCode.append(result);
}
return sbCode.toString();
}
}
return File;
});