-
-
Notifications
You must be signed in to change notification settings - Fork 119
Expand file tree
/
Copy pathtagGenerator.js
More file actions
338 lines (294 loc) · 11.9 KB
/
Copy pathtagGenerator.js
File metadata and controls
338 lines (294 loc) · 11.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
define([
'require'
, 'jquery'
, 'nbextensions/visualpython/src/common/vpCommon'
, 'nbextensions/visualpython/src/common/constant'
, 'nbextensions/visualpython/src/common/StringBuilder'
, 'nbextensions/visualpython/src/common/vpFuncJS'
, 'nbextensions/visualpython/src/common/vpMakeDom'
, 'nbextensions/visualpython/src/pandas/common/pandasLibrary'
, 'nbextensions/visualpython/src/common/component/vpSuggestInputText'
], function(requirejs, $, vpCommon, vpConst, sb, vpFuncJS, vpMakeDom, libPandas, vpSuggestInputText) {
/**
* 코드 실행 후 결과값 보여주기 여부
*/
var _VP_SHOW_RESULT = true;
/**
* 변수 조회 시 제외해야할 변수명
*/
var _VP_NOT_USING_VAR = ['_html', '_nms', 'NamespaceMagics', '_Jupyter', 'In', 'Out', 'exit', 'quit', 'get_ipython'];
/**
* 변수 조회 시 제외해야할 변수 타입
*/
var _VP_NOT_USING_TYPE = ['module', 'function', 'builtin_function_or_method', 'instance', '_Feature', 'type', 'ufunc'];
var funcOptProp = {
stepCount : 1
, funcName : "tagGenerator"
, funcID : "MJ000" // TODO: ID 규칙 생성 필요
}
var vpFuncJS = new vpFuncJS.VpFuncJS(funcOptProp);
// make dom
var { renderInput
, renderSelectBox
, renderOption
, renderLabel } = vpMakeDom;
/**
* @class TagGenerator
* @constructor
* @param {Object} pageThis Page Object
* @param {Object} package Library package ex)pd001
*/
var TagGenerator = function(pageThis, package) {
this.pageThis = pageThis;
this.package = package;
// 기본 표시 div tag
this.ioDiv = '#vp_inputOutputBox table';
this.optionDiv = '#vp_optionBox table';
// Form Id
this.formId = 'vp_optionForm';
}
/**
* Manually set package
* @param {object} package
*/
TagGenerator.prototype.setPackage = function(package) {
this.package = package;
}
// TODO: 전체 태그 생성
/**
* Generate Label & Input tags
*/
TagGenerator.prototype.generateTags = function() {
var package = this.package;
var that = this.pageThis;
console.log(package);
if (package == undefined) {
return;
}
console.log('start generating tags');
var ioBox = $(that.wrapSelector(this.ioDiv));
var optBox = $(that.wrapSelector(this.optionDiv));
// generate tag for parameters options
package.parameters && package.parameters.forEach(opt => {
// create tag
var label = this.generateLabel(opt);
var input = this.generateTag(opt);
console.log(label);
console.log(input);
if (opt.required == true) {
// if required, add to inputOutputBox
ioBox.append(
$('<tr></tr>').append($('<td></td>').append(label))
.append($('<td></td>').append(input))
);
} else {
// else add to optionBox
optBox.append(
$('<tr></tr>').append($('<td></td>').append(label))
.append($('<td></td>').append(input))
);
}
});
// generate tag for returns option
package.returns && package.returns.forEach(opt => {
// create tag
var label = this.generateLabel(opt);
var input = this.generateTag(opt);
// add to inputOutputBox
ioBox.append(
$('<tr></tr>').append($('<td></td>').append(label))
.append($('<td></td>').append(input))
);
});
}
/**
* Create Label Tag
* @param {object} optObj
*/
TagGenerator.prototype.generateLabel = function(optObj) {
var textValue = optObj.label;
if (optObj.required == true) {
// FIXME: required option label format
// if required, highlight with * (default)
textValue = '* ' + textValue;
}
// make label tag
var label = vpMakeDom.renderLabel({
class: 'vp-label'
, for: optObj.name
, text: textValue
});
return label;
}
// TODO: 단순 태그 생성기
/**
* Create Input Tag
* @param {object} optObj
* @returns {HTMLElement} Tag Element
*/
TagGenerator.prototype.generateTag = function(optObj) {
var that = this;
// cases for components
switch (optObj.component) {
case 'option':
// make select tag
var select = vpMakeDom.renderSelectBox(
{
class: 'vp-select'
, id: optObj.name
}
);
// option tag for 'option' list
var option = ['', ...optObj.option];
var option_label = ['Default', ...optObj.option_label];
select = vpMakeDom.renderOption(select, {
class: 'vp-option'
}, option, option_label);
return select;
case 'option_bool':
// make select tag
var select = vpMakeDom.renderSelectBox(
{
class: 'vp-select vp-select-bool'
, id: optObj.name
}
);
// option tag for True/False & default
var option = ['', 'True', 'False'];
var option_label = ['Default', 'True', 'False'];
select = vpMakeDom.renderOption(select, {
class: 'vp-option'
}, option, option_label);
return select;
case 'input':
default:
// make select tag for 'type' list
var inputDiv = $('<div></div>');
var select = vpMakeDom.renderSelectBox(
{
class: 'vp-types'
, id: optObj.name + '_types'
}
);
var types = optObj.type.indexOf('code') < 0 ? [...optObj.type, 'code'] : [...optObj.type];
select = vpMakeDom.renderOption(select, {
class: 'vp-types-opt'
}, types);
// TODO: type별 이벤트로 input 태그 붙이기
select.change(function() {
// select type event
var selectedType = $(this).val();
$(that.pageThis.wrapSelector('#' + optObj.name)).remove();
inputDiv.append(that.generateInput(selectedType, optObj));
});
inputDiv.prepend(select);
inputDiv.append(this.generateInput(optObj.type[0], optObj));
return inputDiv;
}
}
TagGenerator.prototype.generateInput = function(inputType, optObj) {
switch (inputType) {
case 'var':
// create select tag with variable list
var selectVar = $(`<select id="${optObj.name}"></select>`);
this.generateVarSelectTag(selectVar, optObj.var_type);
return selectVar;
case 'str':
var inputStr = $(`<input type="text" class="vp-str" id="${optObj.name}" placeholder="input text"/>`);
return inputStr;
case 'num':
var inputNum = $(`<input type="number" class="vp-num" id="${optObj.name}" placeholder="input number"/>`);
return inputNum;
case 'code':
var inputCode = $(`<input type="text" class="vp-code" id="${optObj.name}" placeholder="input code"/>`);
return inputCode;
case 'format':
// TODO: support format string using regex
default:
var inputDefault = $(`<input type="text" class="vp-default" id="${optObj.name}"/>`);
return inputDefault;
}
}
// TODO: 변수 조회해서 Select 태그 생성
/**
* Search variables with corresponding data types and append to select tag
* @param {object} slctTag
* @param {Array<string>} types
* @param {string} defaultValue
*/
TagGenerator.prototype.generateVarSelectTag = function(slctTag, types, defaultValue = '') {
// Index related types
var INDEX_TYPES = ['RangeIndex', 'CategoricalIndex', 'MultiIndex', 'IntervalIndex', 'DatetimeIndex', 'TimedeltaIndex', 'PeriodIndex', 'Int64Index', 'UInt64Index', 'Float64Index'];
// GroupBy related types
var GROUPBY_TYPES = ['DataFrameGroupBy', 'SeriesGroupBy']
// include related types
if (types != undefined && types.indexOf('Index') >= 0) {
types = types.concat(INDEX_TYPES);
}
if (types != undefined && types.indexOf('GroupBy') >= 0) {
types = types.concat(GROUPBY_TYPES);
}
// search variable list
this.searchVarList(types, function (result) {
var jsonVars = result.replace(/'/gi, `"`);
var varList = JSON.parse(jsonVars);
// option 태그 구성 FIXME: vpMakeDom 사용
varList.forEach(listVar => {
if (types.includes(listVar.varType) && listVar.varName[0] !== '_') {
var option = document.createElement('option');
$(option).attr({
'value':listVar.varName,
'text':listVar.varName
});
// cell metadata test : defaultValue에 따라서 selected 적용
if (listVar.varName == defaultValue) {
$(option).prop('selected', true);
}
option.append(document.createTextNode(listVar.varName));
$(slctTag).append(option);
}
});
// val-multi 일 경우(select multiple) value list 등록
var classname = $(tag).attr('class');
if (classname == 'var-multi') {
$(slctTag).val(defaultValue);
}
});
}
/**
* Return variables with specific data types
* @param {Array<string>} types 조회할 변수들의 데이터유형 목록
* @param {function} callback 조회 후 실행할 callback. parameter로 result를 받는다
*/
TagGenerator.prototype.searchVarList = function(types, callback) {
// make command for searching variable list
var cmdSB = new sb.StringBuilder();
cmdSB.append(`print([{'varName': v, 'varType': type(eval(v)).__name__}`);
cmdSB.appendFormat(`for v in dir() if (v not in {0}) `, JSON.stringify(_VP_NOT_USING_VAR));
cmdSB.appendFormat(`& (type(eval(v)).__name__ not in {0}) `, JSON.stringify(_VP_NOT_USING_TYPE));
// if no data types passed, exclude it
if (types != undefined && types.length > 0) {
cmdSB.appendFormat(`& (type(eval(v)).__name__ in {0})`, JSON.stringify(types));
}
cmdSB.appendFormat(`])`);
// execute on kernel
vpFuncJS.kernelExecute(cmdSB.toString(), function(result) {
callback(result);
});
}
// TODO: code generator
TagGenerator.prototype.generateCode = function() {
// TODO: parameter로 key-value 형태의 오브젝트 받기 (cell metadata와 동일한 구조면 좋음)
// - prefix&postfix 도 받아서 최종 code로 변환해주면 좋음
// TODO: code -> {v} 변환할 때 경우의 수
// 1. paired: false
// - vCode += 'value, ' / key 생략
// 2. 이미 사용된 키 ex) {data}.to_csv({v})
// - resultCode.replaceAll('{data}', value); / vCode 생략
// 3. 기본
// - vCode += 'key=value, '
}
return {
TagGenerator: TagGenerator
}
});