diff --git a/css/common/subsetEditor.css b/css/common/subsetEditor.css index 1a1450ba..663ea3f5 100644 --- a/css/common/subsetEditor.css +++ b/css/common/subsetEditor.css @@ -242,16 +242,11 @@ margin: auto; display: inherit; } -.vp-ds-select-add-btn { +.vp-ds-select-btn-box button { height: 24px; background: #FFFFFF; border: 0.25px solid #E4E4E4; -} -.vp-ds-select-del-btn { - height: 24px; - background: #FFFFFF; - border: 0.25px solid #E4E4E4; - margin-top: 5px; + grid-row-gap: 5px; } .vp-ds-btn-add-condition { width: 95px; diff --git a/src/api/functions/fileNaviCommand.py b/src/api/functions/fileNaviCommand.py index 52858a8d..97c1a466 100644 --- a/src/api/functions/fileNaviCommand.py +++ b/src/api/functions/fileNaviCommand.py @@ -3,6 +3,7 @@ """ import os as _vp_os +import stat as _vp_stat def _vp_get_userprofile_path(): """ @@ -64,9 +65,17 @@ def _vp_sizeof_fmt(num, suffix='B'): num /= 1024.0 return '%.1f%s%s' % (num, 'Yi', suffix) -def _vp_search_path(path): +def _vp_search_path(path, show_hidden=False): """ Search child folder and file list under the given path + path: str + path to search file/dir list + show_hidden: bool (optional; default: False) + set True for show hidden file/dir + returns: list + list with scanned file/dir list + 0 element with current and parent path information + 1~n elements with file/dir list under given path """ import datetime as _dt _current = _vp_os.path.abspath(path) @@ -76,20 +85,21 @@ def _vp_search_path(path): _info = [] _info.append({'current':_current,'parent':_parent}) for _entry in i: - _name = _entry.name - _path = _entry.path # 파일 경로 - _stat = _entry.stat() - _size = _vp_sizeof_fmt(_stat.st_size) # 파일 크기 - _a_time = _stat.st_atime # 최근 액세스 시간 - _a_dt = _dt.datetime.fromtimestamp(_a_time).strftime('%Y-%m-%d %H:%M') - _m_time = _stat.st_mtime # 최근 수정 시간 - _m_dt = _dt.datetime.fromtimestamp(_m_time).strftime('%Y-%m-%d %H:%M') - _e_type = 'other' - if _entry.is_file(): - _e_type = 'file' - elif _entry.is_dir(): - _e_type = 'dir' - _info.append({'name':_name, 'type':_e_type, 'path':_path, 'size':_size, 'atime':str(_a_dt), 'mtime':str(_m_dt)}) + if show_hidden or _vp_check_hidden(_entry.path) == False: + _name = _entry.name + _path = _entry.path # 파일 경로 + _stat = _entry.stat() + _size = _vp_sizeof_fmt(_stat.st_size) # 파일 크기 + _a_time = _stat.st_atime # 최근 액세스 시간 + _a_dt = _dt.datetime.fromtimestamp(_a_time).strftime('%Y-%m-%d %H:%M') + _m_time = _stat.st_mtime # 최근 수정 시간 + _m_dt = _dt.datetime.fromtimestamp(_m_time).strftime('%Y-%m-%d %H:%M') + _e_type = 'other' + if _entry.is_file(): + _e_type = 'file' + elif _entry.is_dir(): + _e_type = 'dir' + _info.append({'name':_name, 'type':_e_type, 'path':_path, 'size':_size, 'atime':str(_a_dt), 'mtime':str(_m_dt)}) return _info def _vp_get_image_by_path(path): @@ -104,10 +114,20 @@ def _vp_get_relative_path(start, path): """ Get relative path using start path and current path start: str - start path + start path+ path: str current path returns: str current relative path """ - return _vp_os.path.relpath(path, start) \ No newline at end of file + return _vp_os.path.relpath(path, start) + +def _vp_check_hidden(path): + """ + Check if it's hidden + path: str + file path + returns: bool + True for hidden file/dir, False for others + """ + return bool(_vp_os.stat(path).st_file_attributes & _vp_stat.FILE_ATTRIBUTE_HIDDEN) \ No newline at end of file diff --git a/src/common/vpBind.js b/src/common/vpBind.js index 46499646..f57cfb04 100644 --- a/src/common/vpBind.js +++ b/src/common/vpBind.js @@ -72,11 +72,11 @@ define([ this.codepreview = undefined; this.howList = [ - { label: 'Inner', value: 'inner' }, - { label: 'Outer', value: 'outer' }, - { label: 'Left', value: 'left' }, - { label: 'Right', value: 'right' }, - { label: 'Cross', value: 'cross' }, + { label: 'Inner', value: 'inner', desc: 'Inner join' }, + { label: 'Full outer', value: 'outer', desc: 'Full outer join' }, + { label: 'Left outer', value: 'left', desc: 'Left outer join' }, + { label: 'Right outer', value: 'right', desc: 'Right outer join' }, + { label: 'Cross', value: 'cross', desc: 'Cartesian product' }, ] } @@ -116,13 +116,16 @@ define([ $(this._wrapSelector('#vp_bdHow')).val(merge.how); this._loadSelectorInput(this._wrapSelector('#vp_bdOn'), merge.on); - if (on && on.length > 0) { + if (merge.on && merge.on.length > 0) { $(this._wrapSelector('#vp_bdLeftOnSelect')).attr('disabled', true); $(this._wrapSelector('#vp_bdRightOnSelect')).attr('disabled', true); + $(this._wrapSelector('#vp_bdLeftIndex')).attr('disabled', true); + $(this._wrapSelector('#vp_bdRightIndex')).attr('disabled', true); } this._loadSelectorInput(this._wrapSelector('#vp_bdLeftOn'), merge.left.on); this._loadSelectorInput(this._wrapSelector('#vp_bdRightOn'), merge.right.on); - if (merge.left.on.length > 0 || merge.right.on.length > 0) { + if (merge.left.on.length > 0 || merge.right.on.length > 0 + || merge.left.useIndex || merge.right.useIndex) { $(this._wrapSelector('#vp_bdOnSelect')).attr('disabled', true); } @@ -361,7 +364,7 @@ define([ page.appendFormatLine(''); page.appendLine(''); @@ -666,9 +669,13 @@ define([ if (colList && colList.length > 0) { $(that._wrapSelector('#vp_bdLeftOnSelect')).attr('disabled', true); $(that._wrapSelector('#vp_bdRightOnSelect')).attr('disabled', true); + $(that._wrapSelector('#vp_bdLeftIndex')).attr('disabled', true); + $(that._wrapSelector('#vp_bdRightIndex')).attr('disabled', true); } else { $(that._wrapSelector('#vp_bdLeftOnSelect')).attr('disabled', false); $(that._wrapSelector('#vp_bdRightOnSelect')).attr('disabled', false); + $(that._wrapSelector('#vp_bdLeftIndex')).attr('disabled', false); + $(that._wrapSelector('#vp_bdRightIndex')).attr('disabled', false); } }); @@ -927,7 +934,7 @@ define([ //================================================================ // On columns //================================================================ - code.appendFormat(', on=[{0}]', on.map(col => col.code)); + code.appendFormat(', on=[{0}]', merge.on.map(col => col.code)); } else { //==================================================================== // Left & Right On columns diff --git a/src/common/vpCommon.js b/src/common/vpCommon.js index 9bb9d060..61ae16ef 100644 --- a/src/common/vpCommon.js +++ b/src/common/vpCommon.js @@ -298,7 +298,6 @@ define([ iopub: { output: function(msg) { // msg.content.data['text/plain'] - console.log(msg); resolve(msg.content.data); } } diff --git a/src/common/vpGroupby.js b/src/common/vpGroupby.js index 8cab9a4d..d909e303 100644 --- a/src/common/vpGroupby.js +++ b/src/common/vpGroupby.js @@ -102,6 +102,7 @@ define([ ] this.methodList = [ + { label: 'None', value: '' }, { label: 'count', value: 'count' }, { label: 'first', value: 'first' }, { label: 'last', value: 'last' }, @@ -134,13 +135,14 @@ define([ _loadState(state) { var { variable, groupby, useGrouper, grouperNumber, grouperPeriod, - display, method, advanced, allocateTo, resetIndex, + display, method, advanced, allocateTo, toFrame, resetIndex, advPageDom, advColList, advNamingList } = state; $(this._wrapSelector('#vp_gbVariable')).val(variable); $(this._wrapSelector('#vp_gbBy')).val(groupby.map(col=>col.code).join(',')); $(this._wrapSelector('#vp_gbBy')).data('list', groupby); + $(this._wrapSelector('#vp_gbResetIndex')).val(resetIndex?'yes':'no'); if (useGrouper) { $(this._wrapSelector('#vp_gbByGrouper')).removeAttr('disabled'); $(this._wrapSelector('#vp_gbByGrouper')).prop('checked', useGrouper); @@ -157,7 +159,7 @@ define([ $(this._wrapSelector('#vp_gbAdvanced')).trigger('change'); } $(this._wrapSelector('#vp_gbAllocateTo')).val(allocateTo); - $(this._wrapSelector('#vp_gbResetIndex')).val(resetIndex?'yes':'no'); + $(this._wrapSelector('#vp_gbToFrame')).val(toFrame); $(this._wrapSelector('.vp-gb-adv-box')).html(advPageDom); @@ -358,6 +360,7 @@ define([ page.appendLine('
'); page.appendFormatLine('', 'vp_gbAllocateTo', 'wp80', 'Allocate to'); page.appendFormatLine('', 'vp_gbAllocateTo', 'New variable name'); + page.appendFormatLine('', 'vp_gbToFrame', 'To DataFrame'); page.appendLine('
'); page.appendLine(''); // end of df-box @@ -618,6 +621,7 @@ define([ $(document).off('change', this._wrapSelector('#vp_gbMethodSelect')); $(document).off('change', this._wrapSelector('#vp_gbAdvanced')); $(document).off('change', this._wrapSelector('#vp_gbAllocateTo')); + $(document).off('change', this._wrapSelector('#vp_gbToFrame')); $(document).off('change', this._wrapSelector('#vp_gbResetIndex')); $(document).off('click', this._wrapSelector('#vp_gbAdvAdd')); @@ -716,6 +720,12 @@ define([ $(document).on('change', this._wrapSelector('#vp_gbDisplay'), function(event) { var colList = event.dataList; that.state.display = colList; + + if (colList && colList.length == 1) { + $(that._wrapSelector('#vp_gbToFrame')).parent().show(); + } else { + $(that._wrapSelector('#vp_gbToFrame')).parent().hide(); + } }); // display select button event @@ -756,6 +766,11 @@ define([ $(document).on('change', this._wrapSelector('#vp_gbAllocateTo'), function() { that.state.allocateTo = $(this).val(); }); + + // to dataframe event + $(document).on('change', this._wrapSelector('#vp_gbToFrame'), function() { + that.state.toFrame = $(this).prop('checked') == true; + }); // reset index checkbox event $(document).on('change', this._wrapSelector('#vp_gbResetIndex'), function() { @@ -1009,9 +1024,13 @@ define([ var code = new sb.StringBuilder(); var { variable, groupby, useGrouper, grouperNumber, grouperPeriod, - display, method, advanced, allocateTo, resetIndex + display, method, advanced, allocateTo, toFrame, resetIndex } = this.state; + if (!variable || variable == '') { + return ''; + } + // mapping colList states groupby = groupby.map(col => col.code); display = display.map(col => col.code); @@ -1048,13 +1067,13 @@ define([ //==================================================================== var colStr = ''; if (display) { - if (display.length == 1) { - // for 1 column - colStr = '[' + display.join('') + ']'; - } else if (display.length > 1) { + if (toFrame || display.length > 1) { // over 2 columns colStr = '[[' + display.join(',') + ']]'; - } + } else if (display.length == 1) { + // for 1 column + colStr = '[' + display.join('') + ']'; + } } //==================================================================== @@ -1172,21 +1191,24 @@ define([ //================================================================ // Method code generation //================================================================ - methodStr.appendFormat('{0}()', method); + if (method != '') { + methodStr.appendFormat('{0}()', method); + } } - // when using as_index option with Grouper, use .reset_index() - if (useGrouper && resetIndex) { - methodStr.append('.reset_index()'); + if (method != '') { + // when using as_index option with Grouper, use .reset_index() + if (useGrouper && resetIndex) { + methodStr.append('.reset_index()'); + } + // display columns + code.appendFormat('{0}.{1}', colStr, methodStr.toString()); } - // display columns - code.appendFormat('{0}.{1}', colStr, methodStr.toString()); - + if (allocateTo && allocateTo != '') { code.appendLine(); code.append(allocateTo); } - return code.toString(); } diff --git a/src/common/vpSubsetEditor.js b/src/common/vpSubsetEditor.js index 498cfbe0..4d977c06 100644 --- a/src/common/vpSubsetEditor.js +++ b/src/common/vpSubsetEditor.js @@ -72,8 +72,10 @@ define([ const VP_DS_DRAGGABLE = 'vp-ds-draggable'; /** select btns */ + const VP_DS_SELECT_ADD_ALL_BTN = 'vp-ds-select-add-all-btn'; const VP_DS_SELECT_ADD_BTN = 'vp-ds-select-add-btn'; const VP_DS_SELECT_DEL_BTN = 'vp-ds-select-del-btn'; + const VP_DS_SELECT_DEL_ALL_BTN = 'vp-ds-select-del-all-btn'; /** slicing box */ const VP_DS_SLICING_BOX = 'vp-ds-slicing-box'; @@ -509,8 +511,12 @@ define([ tag.appendLine(''); // VP_DS_SELECT_LEFT // row select - buttons tag.appendFormatLine('
', VP_DS_SELECT_BTN_BOX); + tag.appendFormatLine('' + , VP_DS_SELECT_ADD_ALL_BTN, 'select-row', 'Add all items', ''); tag.appendFormatLine('', VP_DS_SELECT_ADD_BTN, 'select-row', ''); tag.appendFormatLine('', VP_DS_SELECT_DEL_BTN, 'select-row', ''); + tag.appendFormatLine('' + , VP_DS_SELECT_DEL_ALL_BTN, 'select-row', 'Remove all items', ''); tag.appendLine('
'); // VP_DS_SELECT_BTNS // row select - right tag.appendFormatLine('
', VP_DS_SELECT_RIGHT); @@ -612,8 +618,12 @@ define([ tag.appendLine('
'); // VP_DS_SELECT_LEFT // col select - buttons tag.appendFormatLine('
', VP_DS_SELECT_BTN_BOX); + tag.appendFormatLine('' + , VP_DS_SELECT_ADD_ALL_BTN, 'select-col', 'Add all items', ''); tag.appendFormatLine('', VP_DS_SELECT_ADD_BTN, 'select-col', ''); tag.appendFormatLine('', VP_DS_SELECT_DEL_BTN, 'select-col', ''); + tag.appendFormatLine('' + , VP_DS_SELECT_DEL_ALL_BTN, 'select-col', 'Remove all items', ''); tag.appendLine('
'); // VP_DS_SELECT_BTNS // col select - right tag.appendFormatLine('
', VP_DS_SELECT_RIGHT); @@ -1320,8 +1330,10 @@ define([ $(document).off('change', this.wrapSelector('.select-row .' + VP_DS_SELECT_SEARCH)); $(document).off('change', this.wrapSelector('.select-col .' + VP_DS_SELECT_SEARCH)); $(document).off('click', this.wrapSelector('.' + VP_DS_SELECT_ITEM)); + $(document).off('click', this.wrapSelector('.' + VP_DS_SELECT_ADD_ALL_BTN)); $(document).off('click', this.wrapSelector('.' + VP_DS_SELECT_ADD_BTN)); $(document).off('click', this.wrapSelector('.' + VP_DS_SELECT_DEL_BTN)); + $(document).off('click', this.wrapSelector('.' + VP_DS_SELECT_DEL_ALL_BTN)); $(document).off('click', this.wrapSelector('.vp-add-col')); $(document).off('click', this.wrapSelector('.vp-del-col')); $(document).off('change', this.wrapSelector('.vp-ds-slicing-box input[type="text"]')); @@ -1653,6 +1665,21 @@ define([ } }); + // item indexing - add all + $(document).on('click', this.wrapSelector('.' + VP_DS_SELECT_ADD_ALL_BTN), function(event) { + var itemType = $(this).hasClass('select-row')? 'row':'col'; + var selector = '.select-' + itemType; + + $(that.wrapSelector('.' + VP_DS_SELECT_BOX + '.left .' + VP_DS_SELECT_ITEM + selector)).appendTo( + $(that.wrapSelector(selector + ' .' + VP_DS_SELECT_BOX + '.right')) + ); + $(that.wrapSelector(selector + ' .' + VP_DS_SELECT_BOX + ' .' + VP_DS_SELECT_ITEM)).addClass('added'); + $(that.wrapSelector('.' + VP_DS_SELECT_ITEM + '.selected')).removeClass('selected'); + that.state[itemType + 'Pointer'] = { start: -1, end: -1 }; + + that.generateCode(); + }); + // item indexing - add $(document).on('click', this.wrapSelector('.' + VP_DS_SELECT_ADD_BTN), function(event) { var itemType = $(this).hasClass('select-row')? 'row':'col'; @@ -1691,6 +1718,28 @@ define([ that.generateCode(); }); + // item indexing - del all + $(document).on('click', this.wrapSelector('.' + VP_DS_SELECT_DEL_ALL_BTN), function(event) { + var itemType = $(this).hasClass('select-row')? 'row':'col'; + var selector = '.select-' + itemType; + + var targetBoxQuery = that.wrapSelector(selector + ' .' + VP_DS_SELECT_BOX + '.left'); + $(that.wrapSelector(selector + ' .' + VP_DS_SELECT_ITEM)).appendTo( + $(targetBoxQuery) + ); + // sort + $(targetBoxQuery + ' .' + VP_DS_SELECT_ITEM).sort(function(a, b) { + return ($(b).data('idx')) < ($(a).data('idx')) ? 1 : -1; + }).appendTo( + $(targetBoxQuery) + ); + $(that.wrapSelector(selector + ' .' + VP_DS_SELECT_ITEM)).removeClass('added'); + $(that.wrapSelector(selector + ' .' + VP_DS_SELECT_ITEM)).removeClass('selected'); + that.state[itemType + 'Pointer'] = { start: -1, end: -1 }; + + that.generateCode(); + }); + // row-column condition add $(document).on('click', this.wrapSelector('.vp-add-col'), function(event) { that.handleColumnAdd(); @@ -2122,7 +2171,7 @@ define([ var rowList = []; for (var i = 0; i < rowTags.length; i++) { var rowValue = $(rowTags[i]).data('code'); - if (rowValue) { + if (rowValue != undefined) { rowList.push(rowValue); } } diff --git a/src/markdown/markdown.js b/src/markdown/markdown.js index c23f6d48..e88b0cca 100644 --- a/src/markdown/markdown.js +++ b/src/markdown/markdown.js @@ -403,7 +403,7 @@ define([ MathJax.Hub.Queue(["Typeset", MathJax.Hub, that.wrapSelector(vpCommon.formatString("{0}{1}", vpConst.VP_ID_PREFIX, "markdownPreview"))]); - // 변환안 된 이미지 있으면 경로로 설정하기 FIXME: + // // 변환안 된 이미지 있으면 경로로 설정하기 FIXME: html = html.replaceAll('vpImportImage:', ''); textBlock.writeCode(html); @@ -431,7 +431,8 @@ define([ .then(data => { var imgResult = data["image/png"]; - textarea.value = vpCommon.formatString("{0}![{1}]({2}:{3}){4}", preText, file, vpConst.VP_MARKDOWN_TOOLBAR_IMAGE_INDICATOR, file, postText); + // textarea.value = vpCommon.formatString("{0}![{1}]({2}:{3}){4}", preText, file, vpConst.VP_MARKDOWN_TOOLBAR_IMAGE_INDICATOR, file, postText); + textarea.value = vpCommon.formatString("{0}![{1}]({2}){3}", preText, file, file, postText); // 파일 ATTACH ID 생성 var pathSplit = file.split('.').join('/').split('/');